diff --git a/AR71XX.config b/AR71XX.config new file mode 100644 index 000000000..76ca8cfc9 --- /dev/null +++ b/AR71XX.config @@ -0,0 +1,5198 @@ +# +# Automatically generated file; DO NOT EDIT. +# LEDE Configuration +# +CONFIG_MODULES=y +CONFIG_HAVE_DOT_CONFIG=y +# CONFIG_TARGET_sunxi is not set +# CONFIG_TARGET_apm821xx is not set +# CONFIG_TARGET_ath25 is not set +CONFIG_TARGET_ar71xx=y +# CONFIG_TARGET_at91 is not set +# CONFIG_TARGET_brcm2708 is not set +# CONFIG_TARGET_bcm53xx is not set +# CONFIG_TARGET_brcm47xx is not set +# CONFIG_TARGET_brcm63xx is not set +# CONFIG_TARGET_cns3xxx is not set +# CONFIG_TARGET_octeon is not set +# CONFIG_TARGET_gemini is not set +# CONFIG_TARGET_mpc85xx is not set +# CONFIG_TARGET_imx6 is not set +# CONFIG_TARGET_mxs is not set +# CONFIG_TARGET_adm8668 is not set +# CONFIG_TARGET_adm5120 is not set +# CONFIG_TARGET_xburst is not set +# CONFIG_TARGET_ixp4xx is not set +# CONFIG_TARGET_lantiq is not set +# CONFIG_TARGET_malta is not set +# CONFIG_TARGET_pistachio is not set +# CONFIG_TARGET_mvebu is not set +# CONFIG_TARGET_kirkwood is not set +# CONFIG_TARGET_mediatek is not set +# CONFIG_TARGET_ramips is not set +# CONFIG_TARGET_rb532 is not set +# CONFIG_TARGET_mcs814x is not set +# CONFIG_TARGET_layerscape is not set +# CONFIG_TARGET_oxnas is not set +# CONFIG_TARGET_armvirt is not set +# CONFIG_TARGET_ipq806x is not set +# CONFIG_TARGET_au1000 is not set +# CONFIG_TARGET_arc770 is not set +# CONFIG_TARGET_archs38 is not set +# CONFIG_TARGET_ar7 is not set +# CONFIG_TARGET_omap is not set +# CONFIG_TARGET_uml is not set +# CONFIG_TARGET_zynq is not set +# CONFIG_TARGET_x86 is not set +CONFIG_TARGET_ar71xx_generic=y +# CONFIG_TARGET_ar71xx_nand is not set +# CONFIG_TARGET_ar71xx_mikrotik is not set +# CONFIG_TARGET_MULTI_PROFILE is not set +# CONFIG_TARGET_ar71xx_generic_Default is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_carambola2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_lima is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ALFAAP120C is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ap121f is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ALFAAP96 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_HORNETUB is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_HORNETUBx2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ALFANX is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TUBE2H16M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TUBE2H8M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_fritz300e is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_sc1750 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_sc300m is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_sc450 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_c-55 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ALL0258N is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ALL0305 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ALL0315N is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_antminer-s1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_antminer-s3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_antrouter-r1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_arduino-yun is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP121_16M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP121_8M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP132 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP135 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP136_010 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP136_020 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP96 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DB120 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_PB42 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_PB44 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_A02RBW300N is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_BXU2000N2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_F9K1115V2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_bhr-4grv2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WHRG301N is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WHRHPG300N is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WHRHPGN is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WLAEAG300N is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WZR450HP2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WZR600DHP is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WZRHPAG300H is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WZRHPG300NH is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WZRHPG300NH2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WZRHPG450H is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cf-e316n-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cf-e320n-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cf-e355ac is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cf-e380ac-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cf-e380ac-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cf-e520n is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cf-e530n is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WP543_16M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WP543_4M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WP543_8M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WPE72_16M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WPE72_4M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WPE72_8M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wpj342 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wpj344 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wpj531 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wpj558 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wpj563 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_dap-2695-a1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DGL5500A1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DHP1565A1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR505A1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR600A1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR601A1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR601B1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR615C1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR615E1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR615E4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR615I1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR615I3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR825B1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR825C1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR835A1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_dir-869-a1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_EBR2310C1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_dragino2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_el-m150 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_el-mini is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ew-dorin is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ew-dorin-router is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_EAP300V2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ens202ext is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_EPG5000 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ESR1750 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ESR900 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_FR54RTR is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_gl-inet-6408A-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_gl-inet-6416A-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_gl-domino is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_gl-ar150 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_gl-ar300 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_gl-ar300m is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_gl-mifi is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_gl-usb150 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_minibox-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_oolite is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_hiwifi-hc6361 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WRT160NL is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WRT400N is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_mr12 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_mr16 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_mc-mac1200r is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_mw4530r-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_smart-300 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WNDAP360 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wndr3700 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wndr3700v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wndr3800 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wndr3800ch is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wndrmac is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wndrmacv2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_REALWNR1000V2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WNR1000V2_VC is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WNR2000 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WNR2000V3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WNR2000V4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WNR2200 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_REALWNR612V2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WPN824N is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_omy-g1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_omy-x1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_N150R is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_onion-omega is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_som9331 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_A60 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_MR1750 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_MR600 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_MR900 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_OM2P is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_OM5PAC is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_OM5P is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cpe505n is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_r602n is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_pqi-air-pen is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_MZKW04NU is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_MZKW300NH is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cap324 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cap324-nocloud is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cr3000-nocloud is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cr3000 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cr5000-nocloud is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cr5000 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DLRTDEV01 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_qihoo-c301 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP143_16M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP143_8M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP147_010 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP152_16M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ap531b0 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_rnx-n360rt is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_CAP4200AG is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_EAP7660D is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WLR8100 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_bsb is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_archer-c25-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_archer-c5-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_archer-c59-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_archer-c7-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_archer-c7-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_archer-c7-v2-il is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr7500-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_archer-c7-v4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cpe210-220-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cpe510-520-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_eap120-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_re450-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr10u-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr11u-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr11u-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr12u-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr13u-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr3020-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr3040-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr3040-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr3220-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr3220-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr3420-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr3420-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr6400-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa701nd-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa701nd-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa7210n-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa730re-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa750re-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa7510n-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa801nd-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa801nd-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa801nd-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa830re-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa830re-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa850re-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa850re-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa855re-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa860re-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa901nd-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa901nd-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa901nd-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa901nd-v4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr3320-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr3500-v1 is not set +CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr3600-v1=y +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr4300-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr4300-v1-il is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr4310-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr4900-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr6500-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wpa8630-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr1041n-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr1043nd-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr1043nd-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr1043nd-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr1043nd-v4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr2543-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr703n-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr710n-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr710n-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr710n-v2.1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr720n-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr720n-v4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr740n-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr740n-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr740n-v4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr740n-v5 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr740n-v6 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr741nd-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr741nd-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr741nd-v4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr741nd-v5 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr743nd-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr743nd-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr802n-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr802n-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr810n-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr840n-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr840n-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v1.5 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v10 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v11 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v12 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v5 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v7 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v8 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v9 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr842n-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr842n-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr842n-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr843nd-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr847n-v8 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr940n-v4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr941nd-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr941nd-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr941nd-v4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr941nd-v5 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr941nd-v6 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr941nd-v6-cn is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wbs210-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wbs510-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TEW632BRP is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TEW652BRP_FW is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TEW652BRP_RECOVERY is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TEW673GRU is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TEW712BR is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TEW732BR is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TEW823DRU is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tellstick-znet-lite is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-air-gateway is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-air-gateway-pro is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-airrouter is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-bullet-m is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-ls-sr71 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-loco-m-xw is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-nano-m-xw is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-nano-m is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_rw2458n is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-rocket-m-ti is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-rocket-m-xw is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-rocket-m is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-rs is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-rspro is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-unifi is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-unifiac-lite is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-unifiac-mesh is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-unifiac-pro is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-unifi-outdoor is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubdev01 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wrtnode2q is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_dr531 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_weio is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_mynet-n600 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_mynet-n750 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_MYNETREXT is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ap90q is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cpe830 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cpe870 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_sr3200 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_xd3200 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_zbt-we1526 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ZCN1523H28 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ZCN1523H516 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_NBG_460N_550N_550NH is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_NBG6616 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_dLAN_Hotspot is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_dLAN_pro_1200_ac is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_dLAN_pro_500_wp is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_JA76PF is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_JA76PF2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_JWAP003 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_jwap230 is not set +CONFIG_HAS_SUBTARGETS=y +CONFIG_HAS_DEVICES=y +CONFIG_TARGET_BOARD="ar71xx" +CONFIG_TARGET_SUBTARGET="generic" +CONFIG_TARGET_PROFILE="DEVICE_tl-wdr3600-v1" +CONFIG_TARGET_ARCH_PACKAGES="mips_24kc" +CONFIG_DEFAULT_TARGET_OPTIMIZATION="-Os -pipe -mno-branch-likely -mips32r2 -mtune=24kc" +CONFIG_CPU_TYPE="24kc" +CONFIG_LINUX_4_4=y +CONFIG_DEFAULT_automount=y +CONFIG_DEFAULT_base-files=y +CONFIG_DEFAULT_block-mount=y +CONFIG_DEFAULT_busybox=y +CONFIG_DEFAULT_default-settings=y +CONFIG_DEFAULT_dnsmasq-full=y +CONFIG_DEFAULT_dropbear=y +CONFIG_DEFAULT_firewall=y +CONFIG_DEFAULT_fstools=y +CONFIG_DEFAULT_ip6tables=y +CONFIG_DEFAULT_ipset-lists=y +CONFIG_DEFAULT_iptables=y +CONFIG_DEFAULT_iptables-mod-nat-extra=y +CONFIG_DEFAULT_iwinfo=y +CONFIG_DEFAULT_kmod-ath9k=y +CONFIG_DEFAULT_kmod-gpio-button-hotplug=y +CONFIG_DEFAULT_kmod-macvlan=y +CONFIG_DEFAULT_kmod-nf-nathelper=y +CONFIG_DEFAULT_kmod-nf-nathelper-extra=y +CONFIG_DEFAULT_kmod-usb-core=y +CONFIG_DEFAULT_kmod-usb-ledtrig-usbport=y +CONFIG_DEFAULT_kmod-usb2=y +CONFIG_DEFAULT_libc=y +CONFIG_DEFAULT_libgcc=y +CONFIG_DEFAULT_logd=y +CONFIG_DEFAULT_luci=y +CONFIG_DEFAULT_luci-app-adbyby-plus=y +CONFIG_DEFAULT_luci-app-autoreboot=y +CONFIG_DEFAULT_luci-app-ddns=y +CONFIG_DEFAULT_luci-app-filetransfer=y +CONFIG_DEFAULT_luci-app-ipsec-vpnd=y +CONFIG_DEFAULT_luci-app-nlbwmon=y +CONFIG_DEFAULT_luci-app-pptp-server=y +CONFIG_DEFAULT_luci-app-sfe=y +CONFIG_DEFAULT_luci-app-shadowsocksr-pro=y +CONFIG_DEFAULT_luci-app-sqm=y +CONFIG_DEFAULT_luci-app-upnp=y +CONFIG_DEFAULT_luci-app-usb-printer=y +CONFIG_DEFAULT_luci-app-vlmcsd=y +CONFIG_DEFAULT_luci-app-vsftpd=y +CONFIG_DEFAULT_luci-app-wifischedule=y +CONFIG_DEFAULT_luci-app-wol=y +CONFIG_DEFAULT_mtd=y +CONFIG_DEFAULT_netifd=y +CONFIG_DEFAULT_opkg=y +CONFIG_DEFAULT_ppp=y +CONFIG_DEFAULT_ppp-mod-pppoe=y +CONFIG_DEFAULT_swconfig=y +CONFIG_DEFAULT_uboot-envtools=y +CONFIG_DEFAULT_uci=y +CONFIG_DEFAULT_uclient-fetch=y +CONFIG_DEFAULT_wpad-mini=y +CONFIG_AUDIO_SUPPORT=y +CONFIG_GPIO_SUPPORT=y +CONFIG_PCI_SUPPORT=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_GADGET_SUPPORT=y +CONFIG_BIG_ENDIAN=y +CONFIG_USES_DEVICETREE=y +CONFIG_USES_SQUASHFS=y +CONFIG_HAS_MIPS16=y +CONFIG_mips=y +CONFIG_ARCH="mips" + +# +# Target Images +# +# CONFIG_TARGET_ROOTFS_INITRAMFS is not set +CONFIG_EXTERNAL_CPIO="" + +# +# Root filesystem archives +# +# CONFIG_TARGET_ROOTFS_CPIOGZ is not set +# CONFIG_TARGET_ROOTFS_TARGZ is not set + +# +# Root filesystem images +# +# CONFIG_TARGET_ROOTFS_EXT4FS is not set +CONFIG_TARGET_ROOTFS_SQUASHFS=y +CONFIG_TARGET_SQUASHFS_BLOCK_SIZE=1024 +CONFIG_TARGET_UBIFS_FREE_SPACE_FIXUP=y +CONFIG_TARGET_UBIFS_JOURNAL_SIZE="" + +# +# Image Options +# + +# +# Global build settings +# +# CONFIG_ALL_NONSHARED is not set +# CONFIG_ALL_KMODS is not set +# CONFIG_ALL is not set +# CONFIG_BUILDBOT is not set +CONFIG_SIGNED_PACKAGES=y + +# +# General build options +# +# CONFIG_DISPLAY_SUPPORT is not set +CONFIG_BUILD_PATENTED=y +# CONFIG_BUILD_NLS is not set +CONFIG_SHADOW_PASSWORDS=y +# CONFIG_CLEAN_IPKG is not set +# CONFIG_INCLUDE_CONFIG is not set +# CONFIG_COLLECT_KERNEL_DEBUG is not set + +# +# Kernel build options +# +CONFIG_KERNEL_BUILD_USER="" +CONFIG_KERNEL_BUILD_DOMAIN="" +CONFIG_KERNEL_PRINTK=y +CONFIG_KERNEL_CRASHLOG=y +CONFIG_KERNEL_SWAP=y +CONFIG_KERNEL_DEBUG_FS=y +# CONFIG_KERNEL_PERF_EVENTS is not set +# CONFIG_KERNEL_PROFILING is not set +CONFIG_KERNEL_KALLSYMS=y +# CONFIG_KERNEL_FTRACE is not set +CONFIG_KERNEL_DEBUG_KERNEL=y +CONFIG_KERNEL_DEBUG_INFO=y +# CONFIG_KERNEL_DYNAMIC_DEBUG is not set +# CONFIG_KERNEL_KPROBES is not set +# CONFIG_KERNEL_AIO is not set +# CONFIG_KERNEL_FHANDLE is not set +# CONFIG_KERNEL_FANOTIFY is not set +# CONFIG_KERNEL_BLK_DEV_BSG is not set +CONFIG_KERNEL_MAGIC_SYSRQ=y +# CONFIG_KERNEL_DEBUG_PINCTRL is not set +# CONFIG_KERNEL_DEBUG_GPIO is not set +CONFIG_KERNEL_COREDUMP=y +CONFIG_KERNEL_ELF_CORE=y +# CONFIG_KERNEL_PROVE_LOCKING is not set +CONFIG_KERNEL_PRINTK_TIME=y +# CONFIG_KERNEL_SLABINFO is not set +# CONFIG_KERNEL_PROC_PAGE_MONITOR is not set +CONFIG_KERNEL_RELAY=y +# CONFIG_KERNEL_KEXEC is not set +# CONFIG_USE_RFKILL is not set +# CONFIG_USE_SPARSE is not set +# CONFIG_KERNEL_DEVTMPFS is not set +# CONFIG_KERNEL_KEYS is not set +# CONFIG_KERNEL_CGROUPS is not set +# CONFIG_KERNEL_NAMESPACES is not set +# CONFIG_KERNEL_LXC_MISC is not set +# CONFIG_KERNEL_SECCOMP_FILTER is not set +# CONFIG_KERNEL_SECCOMP is not set +CONFIG_KERNEL_IPV6=y +CONFIG_KERNEL_IPV6_MULTIPLE_TABLES=y +CONFIG_KERNEL_IPV6_SUBTREES=y +CONFIG_KERNEL_IPV6_MROUTE=y +# CONFIG_KERNEL_IPV6_PIMSM_V2 is not set +# CONFIG_KERNEL_IP_PNP is not set + +# +# Filesystem ACL and attr support options +# +# CONFIG_USE_FS_ACL_ATTR is not set +# CONFIG_KERNEL_FS_POSIX_ACL is not set +# CONFIG_KERNEL_BTRFS_FS_POSIX_ACL is not set +# CONFIG_KERNEL_EXT4_FS_POSIX_ACL is not set +# CONFIG_KERNEL_F2FS_FS_POSIX_ACL is not set +# CONFIG_KERNEL_JFFS2_FS_POSIX_ACL is not set +# CONFIG_KERNEL_TMPFS_POSIX_ACL is not set +# CONFIG_KERNEL_CIFS_ACL is not set +# CONFIG_KERNEL_HFS_FS_POSIX_ACL is not set +# CONFIG_KERNEL_HFSPLUG_FS_POSIX_ACL is not set +# CONFIG_KERNEL_NFS_ACL_SUPPORT is not set +# CONFIG_KERNEL_NFS_V3_ACL_SUPPORT is not set +# CONFIG_KERNEL_NFSD_V2_ACL_SUPPORT is not set +# CONFIG_KERNEL_NFSD_V3_ACL_SUPPORT is not set +# CONFIG_KERNEL_REISER_FS_POSIX_ACL is not set +# CONFIG_KERNEL_XFS_POSIX_ACL is not set +# CONFIG_KERNEL_JFS_POSIX_ACL is not set +# CONFIG_KERNEL_DEVMEM is not set +# CONFIG_KERNEL_DEVKMEM is not set + +# +# Package build options +# +# CONFIG_DEBUG is not set +CONFIG_IPV6=y + +# +# Stripping options +# +# CONFIG_NO_STRIP is not set +# CONFIG_USE_STRIP is not set +CONFIG_USE_SSTRIP=y +# CONFIG_STRIP_KERNEL_EXPORTS is not set +# CONFIG_USE_MKLIBS is not set +CONFIG_USE_UCLIBCXX=y +# CONFIG_USE_LIBSTDCXX is not set + +# +# Hardening build options +# +CONFIG_PKG_CHECK_FORMAT_SECURITY=y +# CONFIG_PKG_CC_STACKPROTECTOR_NONE is not set +CONFIG_PKG_CC_STACKPROTECTOR_REGULAR=y +# CONFIG_KERNEL_CC_STACKPROTECTOR_NONE is not set +CONFIG_KERNEL_CC_STACKPROTECTOR_REGULAR=y +# CONFIG_KERNEL_CC_STACKPROTECTOR_STRONG is not set +# CONFIG_PKG_FORTIFY_SOURCE_NONE is not set +CONFIG_PKG_FORTIFY_SOURCE_1=y +# CONFIG_PKG_FORTIFY_SOURCE_2 is not set +# CONFIG_PKG_RELRO_NONE is not set +# CONFIG_PKG_RELRO_PARTIAL is not set +CONFIG_PKG_RELRO_FULL=y +# CONFIG_DEVEL is not set +# CONFIG_BROKEN is not set +CONFIG_BINARY_FOLDER="" +CONFIG_DOWNLOAD_FOLDER="" +CONFIG_LOCALMIRROR="" +CONFIG_AUTOREBUILD=y +# CONFIG_AUTOREMOVE is not set +CONFIG_BUILD_SUFFIX="" +CONFIG_TARGET_ROOTFS_DIR="" +# CONFIG_CCACHE is not set +CONFIG_EXTERNAL_KERNEL_TREE="" +CONFIG_KERNEL_GIT_CLONE_URI="" +CONFIG_EXTRA_OPTIMIZATION="-fno-caller-saves -fno-plt" +CONFIG_TARGET_OPTIMIZATION="-Os -pipe -mno-branch-likely -mips32r2 -mtune=24kc" +CONFIG_SOFT_FLOAT=y +CONFIG_USE_MIPS16=y +# CONFIG_EXTRA_TARGET_ARCH is not set +CONFIG_EXTRA_BINUTILS_CONFIG_OPTIONS="" +CONFIG_EXTRA_GCC_CONFIG_OPTIONS="" +# CONFIG_SJLJ_EXCEPTIONS is not set +# CONFIG_INSTALL_LIBGCJ is not set +# CONFIG_INSTALL_GFORTRAN is not set +CONFIG_GDB=y +CONFIG_USE_MUSL=y +CONFIG_BINUTILS_VERSION_2_28=y +CONFIG_BINUTILS_VERSION="2.28" +CONFIG_GCC_VERSION="5.4.0" +CONFIG_LIBC="musl" +CONFIG_TARGET_SUFFIX="musl" +# CONFIG_IB is not set +# CONFIG_SDK is not set +# CONFIG_MAKE_TOOLCHAIN is not set +# CONFIG_IMAGEOPT is not set +# CONFIG_PREINITOPT is not set +CONFIG_TARGET_PREINIT_SUPPRESS_STDERR=y +# CONFIG_TARGET_PREINIT_DISABLE_FAILSAFE is not set +CONFIG_TARGET_PREINIT_TIMEOUT=2 +# CONFIG_TARGET_PREINIT_SHOW_NETMSG is not set +# CONFIG_TARGET_PREINIT_SUPPRESS_FAILSAFE_NETMSG is not set +CONFIG_TARGET_PREINIT_IFNAME="" +CONFIG_TARGET_PREINIT_IP="192.168.1.1" +CONFIG_TARGET_PREINIT_NETMASK="255.255.255.0" +CONFIG_TARGET_PREINIT_BROADCAST="192.168.1.255" +# CONFIG_INITOPT is not set +CONFIG_TARGET_INIT_PATH="/usr/sbin:/usr/bin:/sbin:/bin" +CONFIG_TARGET_INIT_ENV="" +CONFIG_TARGET_INIT_CMD="/sbin/init" +CONFIG_TARGET_INIT_SUPPRESS_STDERR=y +# CONFIG_VERSIONOPT is not set +CONFIG_PER_FEED_REPO=y +CONFIG_PER_FEED_REPO_ADD_DISABLED=y +CONFIG_PER_FEED_REPO_ADD_COMMENTED=y +CONFIG_FEED_packages=y +CONFIG_FEED_luci=y +CONFIG_FEED_routing=y +CONFIG_FEED_telephony=y + +# +# Base system +# +CONFIG_PACKAGE_base-files=y +CONFIG_PACKAGE_block-mount=y +# CONFIG_PACKAGE_blockd is not set +# CONFIG_PACKAGE_bridge is not set +CONFIG_PACKAGE_busybox=y +# CONFIG_BUSYBOX_CUSTOM is not set +CONFIG_BUSYBOX_DEFAULT_HAVE_DOT_CONFIG=y +# CONFIG_BUSYBOX_DEFAULT_DESKTOP is not set +# CONFIG_BUSYBOX_DEFAULT_EXTRA_COMPAT is not set +# CONFIG_BUSYBOX_DEFAULT_FEDORA_COMPAT is not set +CONFIG_BUSYBOX_DEFAULT_INCLUDE_SUSv2=y +# CONFIG_BUSYBOX_DEFAULT_USE_PORTABLE_CODE is not set +CONFIG_BUSYBOX_DEFAULT_PLATFORM_LINUX=y +CONFIG_BUSYBOX_DEFAULT_SHOW_USAGE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VERBOSE_USAGE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_COMPRESS_USAGE=y +# CONFIG_BUSYBOX_DEFAULT_BUSYBOX is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INSTALLER is not set +# CONFIG_BUSYBOX_DEFAULT_INSTALL_NO_USR is not set +# CONFIG_BUSYBOX_DEFAULT_PAM is not set +CONFIG_BUSYBOX_DEFAULT_LONG_OPTS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_DEVPTS=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CLEAN_UP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UTMP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_WTMP is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_PIDFILE=y +CONFIG_BUSYBOX_DEFAULT_PID_FILE_PATH="/var/run" +CONFIG_BUSYBOX_DEFAULT_FEATURE_SUID=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SUID_CONFIG is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SUID_CONFIG_QUIET is not set +# CONFIG_BUSYBOX_DEFAULT_SELINUX is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_PREFER_APPLETS=y +CONFIG_BUSYBOX_DEFAULT_BUSYBOX_EXEC_PATH="/proc/self/exe" +CONFIG_BUSYBOX_DEFAULT_FEATURE_SYSLOG=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HAVE_RPC is not set +# CONFIG_BUSYBOX_DEFAULT_STATIC is not set +# CONFIG_BUSYBOX_DEFAULT_PIE is not set +# CONFIG_BUSYBOX_DEFAULT_NOMMU is not set +# CONFIG_BUSYBOX_DEFAULT_BUILD_LIBBUSYBOX is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INDIVIDUAL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SHARED_BUSYBOX is not set +CONFIG_BUSYBOX_DEFAULT_LFS=y +CONFIG_BUSYBOX_DEFAULT_CROSS_COMPILER_PREFIX="" +CONFIG_BUSYBOX_DEFAULT_SYSROOT="" +CONFIG_BUSYBOX_DEFAULT_EXTRA_CFLAGS="" +CONFIG_BUSYBOX_DEFAULT_EXTRA_LDFLAGS="" +CONFIG_BUSYBOX_DEFAULT_EXTRA_LDLIBS="" +CONFIG_BUSYBOX_DEFAULT_INSTALL_APPLET_SYMLINKS=y +# CONFIG_BUSYBOX_DEFAULT_INSTALL_APPLET_HARDLINKS is not set +# CONFIG_BUSYBOX_DEFAULT_INSTALL_APPLET_SCRIPT_WRAPPERS is not set +# CONFIG_BUSYBOX_DEFAULT_INSTALL_APPLET_DONT is not set +# CONFIG_BUSYBOX_DEFAULT_INSTALL_SH_APPLET_SYMLINK is not set +# CONFIG_BUSYBOX_DEFAULT_INSTALL_SH_APPLET_HARDLINK is not set +# CONFIG_BUSYBOX_DEFAULT_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set +CONFIG_BUSYBOX_DEFAULT_PREFIX="./_install" +# CONFIG_BUSYBOX_DEFAULT_DEBUG is not set +# CONFIG_BUSYBOX_DEFAULT_DEBUG_PESSIMIZE is not set +# CONFIG_BUSYBOX_DEFAULT_DEBUG_SANITIZE is not set +# CONFIG_BUSYBOX_DEFAULT_UNIT_TEST is not set +# CONFIG_BUSYBOX_DEFAULT_WERROR is not set +CONFIG_BUSYBOX_DEFAULT_NO_DEBUG_LIB=y +# CONFIG_BUSYBOX_DEFAULT_DMALLOC is not set +# CONFIG_BUSYBOX_DEFAULT_EFENCE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_USE_BSS_TAIL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_RTMINMAX is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_BUFFERS_USE_MALLOC is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_BUFFERS_GO_ON_STACK=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_BUFFERS_GO_IN_BSS is not set +CONFIG_BUSYBOX_DEFAULT_PASSWORD_MINLEN=6 +CONFIG_BUSYBOX_DEFAULT_MD5_SMALL=1 +CONFIG_BUSYBOX_DEFAULT_SHA3_SMALL=1 +CONFIG_BUSYBOX_DEFAULT_FEATURE_FAST_TOP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_ETC_NETWORKS is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_EDITING=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_EDITING_MAX_LEN=512 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_EDITING_VI is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_EDITING_HISTORY=256 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_EDITING_SAVEHISTORY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_EDITING_SAVE_ON_EXIT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_REVERSE_SEARCH is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_TAB_COMPLETION=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_USERNAME_COMPLETION is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_EDITING_FANCY_PROMPT=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_EDITING_ASK_TERMINAL is not set +# CONFIG_BUSYBOX_DEFAULT_LOCALE_SUPPORT is not set +# CONFIG_BUSYBOX_DEFAULT_UNICODE_SUPPORT is not set +# CONFIG_BUSYBOX_DEFAULT_UNICODE_USING_LOCALE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHECK_UNICODE_IN_ENV is not set +CONFIG_BUSYBOX_DEFAULT_SUBST_WCHAR=0 +CONFIG_BUSYBOX_DEFAULT_LAST_SUPPORTED_WCHAR=0 +# CONFIG_BUSYBOX_DEFAULT_UNICODE_COMBINING_WCHARS is not set +# CONFIG_BUSYBOX_DEFAULT_UNICODE_WIDE_WCHARS is not set +# CONFIG_BUSYBOX_DEFAULT_UNICODE_BIDI_SUPPORT is not set +# CONFIG_BUSYBOX_DEFAULT_UNICODE_NEUTRAL_TABLE is not set +# CONFIG_BUSYBOX_DEFAULT_UNICODE_PRESERVE_BROKEN is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_NON_POSIX_CP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VERBOSE_CP_MESSAGE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_USE_SENDFILE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_COPYBUF_KB=4 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SKIP_ROOTFS is not set +# CONFIG_BUSYBOX_DEFAULT_MONOTONIC_SYSCALL is not set +CONFIG_BUSYBOX_DEFAULT_IOCTL_HEX2STR_ERROR=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HWIB is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SEAMLESS_XZ is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SEAMLESS_LZMA is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SEAMLESS_BZ2 is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_SEAMLESS_GZ=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SEAMLESS_Z is not set +# CONFIG_BUSYBOX_DEFAULT_AR is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_AR_LONG_FILENAMES is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_AR_CREATE is not set +# CONFIG_BUSYBOX_DEFAULT_UNCOMPRESS is not set +CONFIG_BUSYBOX_DEFAULT_GUNZIP=y +CONFIG_BUSYBOX_DEFAULT_ZCAT=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_GUNZIP_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_BUNZIP2=y +CONFIG_BUSYBOX_DEFAULT_BZCAT=y +# CONFIG_BUSYBOX_DEFAULT_UNLZMA is not set +# CONFIG_BUSYBOX_DEFAULT_LZCAT is not set +# CONFIG_BUSYBOX_DEFAULT_LZMA is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LZMA_FAST is not set +# CONFIG_BUSYBOX_DEFAULT_UNXZ is not set +# CONFIG_BUSYBOX_DEFAULT_XZCAT is not set +# CONFIG_BUSYBOX_DEFAULT_XZ is not set +# CONFIG_BUSYBOX_DEFAULT_BZIP2 is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_BZIP2_DECOMPRESS=y +# CONFIG_BUSYBOX_DEFAULT_CPIO is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CPIO_O is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CPIO_P is not set +# CONFIG_BUSYBOX_DEFAULT_DPKG is not set +# CONFIG_BUSYBOX_DEFAULT_DPKG_DEB is not set +CONFIG_BUSYBOX_DEFAULT_GZIP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_GZIP_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_GZIP_FAST=0 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_GZIP_LEVELS is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_GZIP_DECOMPRESS=y +# CONFIG_BUSYBOX_DEFAULT_LZOP is not set +# CONFIG_BUSYBOX_DEFAULT_UNLZOP is not set +# CONFIG_BUSYBOX_DEFAULT_LZOPCAT is not set +# CONFIG_BUSYBOX_DEFAULT_LZOP_COMPR_HIGH is not set +# CONFIG_BUSYBOX_DEFAULT_RPM is not set +# CONFIG_BUSYBOX_DEFAULT_RPM2CPIO is not set +CONFIG_BUSYBOX_DEFAULT_TAR=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_CREATE=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_AUTODETECT is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_FROM=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_GNU_EXTENSIONS=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_TO_COMMAND is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_UNAME_GNAME is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_NOPRESERVE_TIME is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_SELINUX is not set +# CONFIG_BUSYBOX_DEFAULT_UNZIP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UNZIP_CDF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UNZIP_BZIP2 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UNZIP_LZMA is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UNZIP_XZ is not set +CONFIG_BUSYBOX_DEFAULT_BASENAME=y +CONFIG_BUSYBOX_DEFAULT_CAT=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CATV is not set +CONFIG_BUSYBOX_DEFAULT_CHGRP=y +CONFIG_BUSYBOX_DEFAULT_CHMOD=y +CONFIG_BUSYBOX_DEFAULT_CHOWN=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHOWN_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_CHROOT=y +# CONFIG_BUSYBOX_DEFAULT_CKSUM is not set +# CONFIG_BUSYBOX_DEFAULT_COMM is not set +CONFIG_BUSYBOX_DEFAULT_CP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CP_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_CUT=y +CONFIG_BUSYBOX_DEFAULT_DATE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_DATE_ISOFMT=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DATE_NANO is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DATE_COMPAT is not set +CONFIG_BUSYBOX_DEFAULT_DD=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_DD_SIGNAL_HANDLING=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DD_THIRD_STATUS_LINE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_DD_IBS_OBS=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DD_STATUS is not set +CONFIG_BUSYBOX_DEFAULT_DF=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DF_FANCY is not set +CONFIG_BUSYBOX_DEFAULT_DIRNAME=y +# CONFIG_BUSYBOX_DEFAULT_DOS2UNIX is not set +# CONFIG_BUSYBOX_DEFAULT_UNIX2DOS is not set +CONFIG_BUSYBOX_DEFAULT_DU=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y +CONFIG_BUSYBOX_DEFAULT_ECHO=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FANCY_ECHO=y +CONFIG_BUSYBOX_DEFAULT_ENV=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_ENV_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_EXPAND is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_EXPAND_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_UNEXPAND is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UNEXPAND_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_EXPR=y +CONFIG_BUSYBOX_DEFAULT_EXPR_MATH_SUPPORT_64=y +# CONFIG_BUSYBOX_DEFAULT_FACTOR is not set +CONFIG_BUSYBOX_DEFAULT_FALSE=y +# CONFIG_BUSYBOX_DEFAULT_FOLD is not set +CONFIG_BUSYBOX_DEFAULT_FSYNC=y +CONFIG_BUSYBOX_DEFAULT_HEAD=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FANCY_HEAD=y +# CONFIG_BUSYBOX_DEFAULT_HOSTID is not set +CONFIG_BUSYBOX_DEFAULT_ID=y +# CONFIG_BUSYBOX_DEFAULT_GROUPS is not set +# CONFIG_BUSYBOX_DEFAULT_INSTALL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INSTALL_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_LINK is not set +CONFIG_BUSYBOX_DEFAULT_LN=y +# CONFIG_BUSYBOX_DEFAULT_LOGNAME is not set +CONFIG_BUSYBOX_DEFAULT_LS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_FILETYPES=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_FOLLOWLINKS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_RECURSIVE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_WIDTH=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_SORTFILES=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_TIMESTAMPS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_USERNAME=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_COLOR=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_COLOR_IS_DEFAULT=y +CONFIG_BUSYBOX_DEFAULT_MD5SUM=y +# CONFIG_BUSYBOX_DEFAULT_SHA1SUM is not set +CONFIG_BUSYBOX_DEFAULT_SHA256SUM=y +# CONFIG_BUSYBOX_DEFAULT_SHA512SUM is not set +# CONFIG_BUSYBOX_DEFAULT_SHA3SUM is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_MD5_SHA1_SUM_CHECK=y +CONFIG_BUSYBOX_DEFAULT_MKDIR=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MKDIR_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_MKFIFO=y +CONFIG_BUSYBOX_DEFAULT_MKNOD=y +CONFIG_BUSYBOX_DEFAULT_MV=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MV_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_NICE=y +# CONFIG_BUSYBOX_DEFAULT_NL is not set +# CONFIG_BUSYBOX_DEFAULT_NOHUP is not set +# CONFIG_BUSYBOX_DEFAULT_NPROC is not set +# CONFIG_BUSYBOX_DEFAULT_OD is not set +# CONFIG_BUSYBOX_DEFAULT_PASTE is not set +# CONFIG_BUSYBOX_DEFAULT_PRINTENV is not set +CONFIG_BUSYBOX_DEFAULT_PRINTF=y +CONFIG_BUSYBOX_DEFAULT_PWD=y +CONFIG_BUSYBOX_DEFAULT_READLINK=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_READLINK_FOLLOW=y +# CONFIG_BUSYBOX_DEFAULT_REALPATH is not set +CONFIG_BUSYBOX_DEFAULT_RM=y +CONFIG_BUSYBOX_DEFAULT_RMDIR=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_RMDIR_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_SEQ=y +# CONFIG_BUSYBOX_DEFAULT_SHRED is not set +# CONFIG_BUSYBOX_DEFAULT_SHUF is not set +CONFIG_BUSYBOX_DEFAULT_SLEEP=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FANCY_SLEEP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FLOAT_SLEEP is not set +CONFIG_BUSYBOX_DEFAULT_SORT=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SORT_BIG is not set +# CONFIG_BUSYBOX_DEFAULT_SPLIT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SPLIT_FANCY is not set +# CONFIG_BUSYBOX_DEFAULT_STAT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_STAT_FORMAT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_STAT_FILESYSTEM is not set +# CONFIG_BUSYBOX_DEFAULT_STTY is not set +# CONFIG_BUSYBOX_DEFAULT_SUM is not set +CONFIG_BUSYBOX_DEFAULT_SYNC=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SYNC_FANCY is not set +# CONFIG_BUSYBOX_DEFAULT_TAC is not set +CONFIG_BUSYBOX_DEFAULT_TAIL=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FANCY_TAIL=y +CONFIG_BUSYBOX_DEFAULT_TEE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_TEE_USE_BLOCK_IO=y +CONFIG_BUSYBOX_DEFAULT_TEST=y +CONFIG_BUSYBOX_DEFAULT_TEST1=y +CONFIG_BUSYBOX_DEFAULT_TEST2=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_TEST_64=y +CONFIG_BUSYBOX_DEFAULT_TOUCH=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TOUCH_NODEREF is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_TOUCH_SUSV3=y +CONFIG_BUSYBOX_DEFAULT_TR=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TR_CLASSES is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TR_EQUIV is not set +CONFIG_BUSYBOX_DEFAULT_TRUE=y +# CONFIG_BUSYBOX_DEFAULT_TRUNCATE is not set +# CONFIG_BUSYBOX_DEFAULT_TTY is not set +CONFIG_BUSYBOX_DEFAULT_UNAME=y +CONFIG_BUSYBOX_DEFAULT_UNAME_OSNAME="GNU/Linux" +CONFIG_BUSYBOX_DEFAULT_UNIQ=y +# CONFIG_BUSYBOX_DEFAULT_UNLINK is not set +# CONFIG_BUSYBOX_DEFAULT_USLEEP is not set +# CONFIG_BUSYBOX_DEFAULT_UUDECODE is not set +# CONFIG_BUSYBOX_DEFAULT_BASE64 is not set +# CONFIG_BUSYBOX_DEFAULT_UUENCODE is not set +CONFIG_BUSYBOX_DEFAULT_WC=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_WC_LARGE is not set +# CONFIG_BUSYBOX_DEFAULT_WHO is not set +# CONFIG_BUSYBOX_DEFAULT_W is not set +# CONFIG_BUSYBOX_DEFAULT_USERS is not set +# CONFIG_BUSYBOX_DEFAULT_WHOAMI is not set +CONFIG_BUSYBOX_DEFAULT_YES=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VERBOSE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_PRESERVE_HARDLINKS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_HUMAN_READABLE=y +# CONFIG_BUSYBOX_DEFAULT_CHVT is not set +CONFIG_BUSYBOX_DEFAULT_CLEAR=y +# CONFIG_BUSYBOX_DEFAULT_DEALLOCVT is not set +# CONFIG_BUSYBOX_DEFAULT_DUMPKMAP is not set +# CONFIG_BUSYBOX_DEFAULT_FGCONSOLE is not set +# CONFIG_BUSYBOX_DEFAULT_KBD_MODE is not set +# CONFIG_BUSYBOX_DEFAULT_LOADFONT is not set +# CONFIG_BUSYBOX_DEFAULT_SETFONT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SETFONT_TEXTUAL_MAP is not set +CONFIG_BUSYBOX_DEFAULT_DEFAULT_SETFONT_DIR="" +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LOADFONT_PSF2 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LOADFONT_RAW is not set +# CONFIG_BUSYBOX_DEFAULT_LOADKMAP is not set +# CONFIG_BUSYBOX_DEFAULT_OPENVT is not set +CONFIG_BUSYBOX_DEFAULT_RESET=y +# CONFIG_BUSYBOX_DEFAULT_RESIZE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_RESIZE_PRINT is not set +# CONFIG_BUSYBOX_DEFAULT_SETCONSOLE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SETCONSOLE_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_SETKEYCODES is not set +# CONFIG_BUSYBOX_DEFAULT_SETLOGCONS is not set +# CONFIG_BUSYBOX_DEFAULT_SHOWKEY is not set +CONFIG_BUSYBOX_DEFAULT_MKTEMP=y +# CONFIG_BUSYBOX_DEFAULT_PIPE_PROGRESS is not set +# CONFIG_BUSYBOX_DEFAULT_RUN_PARTS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_RUN_PARTS_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_RUN_PARTS_FANCY is not set +CONFIG_BUSYBOX_DEFAULT_START_STOP_DAEMON=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_START_STOP_DAEMON_FANCY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_WHICH=y +CONFIG_BUSYBOX_DEFAULT_AWK=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_AWK_LIBM=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_AWK_GNU_EXTENSIONS=y +CONFIG_BUSYBOX_DEFAULT_CMP=y +# CONFIG_BUSYBOX_DEFAULT_DIFF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DIFF_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DIFF_DIR is not set +# CONFIG_BUSYBOX_DEFAULT_ED is not set +# CONFIG_BUSYBOX_DEFAULT_PATCH is not set +CONFIG_BUSYBOX_DEFAULT_SED=y +CONFIG_BUSYBOX_DEFAULT_VI=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_MAX_LEN=1024 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_8BIT is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_COLON=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_YANKMARK=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_SEARCH=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_REGEX_SEARCH is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_USE_SIGNALS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_DOT_CMD=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_READONLY=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_SETOPTS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_SET=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_WIN_RESIZE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_ASK_TERMINAL=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_UNDO is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_UNDO_QUEUE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_UNDO_QUEUE_MAX=0 +CONFIG_BUSYBOX_DEFAULT_FEATURE_ALLOW_EXEC=y +CONFIG_BUSYBOX_DEFAULT_FIND=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_PRINT0=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_MTIME=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_MMIN is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_PERM=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_TYPE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_XDEV=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_MAXDEPTH=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_NEWER is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_INUM is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_EXEC=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_EXEC_PLUS is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_USER=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_GROUP=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_NOT=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_DEPTH=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_PAREN=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_SIZE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_PRUNE=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_DELETE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_PATH=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_REGEX=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_CONTEXT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_LINKS is not set +CONFIG_BUSYBOX_DEFAULT_GREP=y +CONFIG_BUSYBOX_DEFAULT_EGREP=y +CONFIG_BUSYBOX_DEFAULT_FGREP=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_GREP_CONTEXT=y +CONFIG_BUSYBOX_DEFAULT_XARGS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_CONFIRMATION=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_QUOTES=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_TERMOPT=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_ZERO_TERM=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_REPL_STR is not set +# CONFIG_BUSYBOX_DEFAULT_BOOTCHARTD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_BOOTCHARTD_BLOATED_HEADER is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_BOOTCHARTD_CONFIG_FILE is not set +CONFIG_BUSYBOX_DEFAULT_HALT=y +CONFIG_BUSYBOX_DEFAULT_POWEROFF=y +CONFIG_BUSYBOX_DEFAULT_REBOOT=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CALL_TELINIT is not set +CONFIG_BUSYBOX_DEFAULT_TELINIT_PATH="" +# CONFIG_BUSYBOX_DEFAULT_INIT is not set +# CONFIG_BUSYBOX_DEFAULT_LINUXRC is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_USE_INITTAB is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_KILL_REMOVED is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_KILL_DELAY=0 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INIT_SCTTY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INIT_SYSLOG is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INIT_QUIET is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INIT_COREDUMPS is not set +CONFIG_BUSYBOX_DEFAULT_INIT_TERMINAL_TYPE="" +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INIT_MODIFY_CMDLINE is not set +# CONFIG_BUSYBOX_DEFAULT_MESG is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MESG_ENABLE_ONLY_GROUP is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_SHADOWPASSWDS=y +# CONFIG_BUSYBOX_DEFAULT_USE_BB_PWD_GRP is not set +# CONFIG_BUSYBOX_DEFAULT_USE_BB_SHADOW is not set +# CONFIG_BUSYBOX_DEFAULT_USE_BB_CRYPT is not set +# CONFIG_BUSYBOX_DEFAULT_USE_BB_CRYPT_SHA is not set +# CONFIG_BUSYBOX_DEFAULT_ADD_SHELL is not set +# CONFIG_BUSYBOX_DEFAULT_REMOVE_SHELL is not set +# CONFIG_BUSYBOX_DEFAULT_ADDGROUP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_ADDGROUP_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_ADDUSER_TO_GROUP is not set +# CONFIG_BUSYBOX_DEFAULT_ADDUSER is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_ADDUSER_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHECK_NAMES is not set +CONFIG_BUSYBOX_DEFAULT_LAST_ID=0 +CONFIG_BUSYBOX_DEFAULT_FIRST_SYSTEM_ID=0 +CONFIG_BUSYBOX_DEFAULT_LAST_SYSTEM_ID=0 +# CONFIG_BUSYBOX_DEFAULT_CHPASSWD is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_DEFAULT_PASSWD_ALGO="md5" +# CONFIG_BUSYBOX_DEFAULT_CRYPTPW is not set +# CONFIG_BUSYBOX_DEFAULT_MKPASSWD is not set +# CONFIG_BUSYBOX_DEFAULT_DELUSER is not set +# CONFIG_BUSYBOX_DEFAULT_DELGROUP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DEL_USER_FROM_GROUP is not set +# CONFIG_BUSYBOX_DEFAULT_GETTY is not set +CONFIG_BUSYBOX_DEFAULT_LOGIN=y +CONFIG_BUSYBOX_DEFAULT_LOGIN_SESSION_AS_CHILD=y +# CONFIG_BUSYBOX_DEFAULT_LOGIN_SCRIPTS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_NOLOGIN is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SECURETTY is not set +CONFIG_BUSYBOX_DEFAULT_PASSWD=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_PASSWD_WEAK_CHECK=y +# CONFIG_BUSYBOX_DEFAULT_SU is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SU_SYSLOG is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SU_CHECKS_SHELLS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY is not set +# CONFIG_BUSYBOX_DEFAULT_SULOGIN is not set +# CONFIG_BUSYBOX_DEFAULT_VLOCK is not set +# CONFIG_BUSYBOX_DEFAULT_CHATTR is not set +# CONFIG_BUSYBOX_DEFAULT_FSCK is not set +# CONFIG_BUSYBOX_DEFAULT_LSATTR is not set +# CONFIG_BUSYBOX_DEFAULT_TUNE2FS is not set +# CONFIG_BUSYBOX_DEFAULT_MODPROBE_SMALL is not set +# CONFIG_BUSYBOX_DEFAULT_DEPMOD is not set +# CONFIG_BUSYBOX_DEFAULT_INSMOD is not set +# CONFIG_BUSYBOX_DEFAULT_LSMOD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set +# CONFIG_BUSYBOX_DEFAULT_MODINFO is not set +# CONFIG_BUSYBOX_DEFAULT_MODPROBE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MODPROBE_BLACKLIST is not set +# CONFIG_BUSYBOX_DEFAULT_RMMOD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CMDLINE_MODULE_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_2_4_MODULES is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INSMOD_VERSION_CHECKING is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INSMOD_LOADINKMEM is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INSMOD_LOAD_MAP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INSMOD_LOAD_MAP_FULL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHECK_TAINTED_MODULE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INSMOD_TRY_MMAP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MODUTILS_ALIAS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MODUTILS_SYMBOLS is not set +CONFIG_BUSYBOX_DEFAULT_DEFAULT_MODULES_DIR="" +CONFIG_BUSYBOX_DEFAULT_DEFAULT_DEPMOD_FILE="" +# CONFIG_BUSYBOX_DEFAULT_ACPID is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_ACPID_COMPAT is not set +# CONFIG_BUSYBOX_DEFAULT_BLKDISCARD is not set +# CONFIG_BUSYBOX_DEFAULT_BLKID is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_BLKID_TYPE is not set +# CONFIG_BUSYBOX_DEFAULT_BLOCKDEV is not set +# CONFIG_BUSYBOX_DEFAULT_CAL is not set +CONFIG_BUSYBOX_DEFAULT_DMESG=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_DMESG_PRETTY=y +# CONFIG_BUSYBOX_DEFAULT_FALLOCATE is not set +# CONFIG_BUSYBOX_DEFAULT_FATATTR is not set +# CONFIG_BUSYBOX_DEFAULT_FBSET is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FBSET_FANCY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FBSET_READMODE is not set +# CONFIG_BUSYBOX_DEFAULT_FDFORMAT is not set +# CONFIG_BUSYBOX_DEFAULT_FDISK is not set +# CONFIG_BUSYBOX_DEFAULT_FDISK_SUPPORT_LARGE_DISKS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FDISK_WRITABLE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_AIX_LABEL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SGI_LABEL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SUN_LABEL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_OSF_LABEL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_GPT_LABEL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FDISK_ADVANCED is not set +# CONFIG_BUSYBOX_DEFAULT_FINDFS is not set +# CONFIG_BUSYBOX_DEFAULT_FLOCK is not set +# CONFIG_BUSYBOX_DEFAULT_FDFLUSH is not set +# CONFIG_BUSYBOX_DEFAULT_FREERAMDISK is not set +# CONFIG_BUSYBOX_DEFAULT_FSCK_MINIX is not set +# CONFIG_BUSYBOX_DEFAULT_FSFREEZE is not set +# CONFIG_BUSYBOX_DEFAULT_FSTRIM is not set +# CONFIG_BUSYBOX_DEFAULT_GETOPT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_GETOPT_LONG is not set +CONFIG_BUSYBOX_DEFAULT_HEXDUMP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HEXDUMP_REVERSE is not set +# CONFIG_BUSYBOX_DEFAULT_HD is not set +# CONFIG_BUSYBOX_DEFAULT_XXD is not set +CONFIG_BUSYBOX_DEFAULT_HWCLOCK=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HWCLOCK_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HWCLOCK_ADJTIME_FHS is not set +# CONFIG_BUSYBOX_DEFAULT_IPCRM is not set +# CONFIG_BUSYBOX_DEFAULT_IPCS is not set +# CONFIG_BUSYBOX_DEFAULT_LOSETUP is not set +# CONFIG_BUSYBOX_DEFAULT_LSPCI is not set +# CONFIG_BUSYBOX_DEFAULT_LSUSB is not set +# CONFIG_BUSYBOX_DEFAULT_MDEV is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MDEV_CONF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MDEV_RENAME is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MDEV_RENAME_REGEXP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MDEV_EXEC is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MDEV_LOAD_FIRMWARE is not set +# CONFIG_BUSYBOX_DEFAULT_MKE2FS is not set +# CONFIG_BUSYBOX_DEFAULT_MKFS_EXT2 is not set +# CONFIG_BUSYBOX_DEFAULT_MKFS_MINIX is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MINIX2 is not set +# CONFIG_BUSYBOX_DEFAULT_MKFS_REISER is not set +# CONFIG_BUSYBOX_DEFAULT_MKDOSFS is not set +# CONFIG_BUSYBOX_DEFAULT_MKFS_VFAT is not set +CONFIG_BUSYBOX_DEFAULT_MKSWAP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MKSWAP_UUID is not set +# CONFIG_BUSYBOX_DEFAULT_MORE is not set +CONFIG_BUSYBOX_DEFAULT_MOUNT=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_FAKE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_VERBOSE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_HELPERS=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_LABEL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_NFS is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_CIFS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_FLAGS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_FSTAB=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_OTHERTAB is not set +# CONFIG_BUSYBOX_DEFAULT_NSENTER is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_NSENTER_LONG_OPTS is not set +CONFIG_BUSYBOX_DEFAULT_PIVOT_ROOT=y +# CONFIG_BUSYBOX_DEFAULT_RDATE is not set +# CONFIG_BUSYBOX_DEFAULT_RDEV is not set +# CONFIG_BUSYBOX_DEFAULT_READPROFILE is not set +# CONFIG_BUSYBOX_DEFAULT_REV is not set +# CONFIG_BUSYBOX_DEFAULT_RTCWAKE is not set +# CONFIG_BUSYBOX_DEFAULT_SCRIPT is not set +# CONFIG_BUSYBOX_DEFAULT_SCRIPTREPLAY is not set +# CONFIG_BUSYBOX_DEFAULT_SETARCH is not set +# CONFIG_BUSYBOX_DEFAULT_LINUX32 is not set +# CONFIG_BUSYBOX_DEFAULT_LINUX64 is not set +# CONFIG_BUSYBOX_DEFAULT_SETPRIV is not set +# CONFIG_BUSYBOX_DEFAULT_SWAPON is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SWAPON_DISCARD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SWAPON_PRI is not set +# CONFIG_BUSYBOX_DEFAULT_SWAPOFF is not set +CONFIG_BUSYBOX_DEFAULT_SWITCH_ROOT=y +# CONFIG_BUSYBOX_DEFAULT_UEVENT is not set +CONFIG_BUSYBOX_DEFAULT_UMOUNT=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_UMOUNT_ALL=y +# CONFIG_BUSYBOX_DEFAULT_UNSHARE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_LOOP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_LOOP_CREATE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MTAB_SUPPORT is not set +# CONFIG_BUSYBOX_DEFAULT_VOLUMEID is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_BCACHE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_BTRFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_CRAMFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_EXFAT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_EXT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_F2FS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_FAT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_HFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_ISO9660 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_JFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LINUXRAID is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LINUXSWAP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LUKS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_NILFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_NTFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_OCFS2 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_REISERFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_ROMFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_SQUASHFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_SYSV is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_UBIFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_UDF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_XFS is not set +# CONFIG_BUSYBOX_DEFAULT_ADJTIMEX is not set +# CONFIG_BUSYBOX_DEFAULT_BBCONFIG is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_COMPRESS_BBCONFIG is not set +# CONFIG_BUSYBOX_DEFAULT_BEEP is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_BEEP_FREQ=0 +CONFIG_BUSYBOX_DEFAULT_FEATURE_BEEP_LENGTH_MS=0 +# CONFIG_BUSYBOX_DEFAULT_CHAT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHAT_NOFAIL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHAT_TTY_HIFI is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHAT_IMPLICIT_CR is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHAT_SWALLOW_OPTS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHAT_SEND_ESCAPES is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHAT_VAR_ABORT_LEN is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHAT_CLR_ABORT is not set +# CONFIG_BUSYBOX_DEFAULT_CHRT is not set +# CONFIG_BUSYBOX_DEFAULT_CONSPY is not set +CONFIG_BUSYBOX_DEFAULT_CROND=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CROND_D is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CROND_CALL_SENDMAIL is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_CROND_DIR="/etc" +CONFIG_BUSYBOX_DEFAULT_CRONTAB=y +# CONFIG_BUSYBOX_DEFAULT_DC is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DC_LIBM is not set +# CONFIG_BUSYBOX_DEFAULT_DEVFSD is not set +# CONFIG_BUSYBOX_DEFAULT_DEVFSD_MODLOAD is not set +# CONFIG_BUSYBOX_DEFAULT_DEVFSD_FG_NP is not set +# CONFIG_BUSYBOX_DEFAULT_DEVFSD_VERBOSE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DEVFS is not set +# CONFIG_BUSYBOX_DEFAULT_DEVMEM is not set +# CONFIG_BUSYBOX_DEFAULT_EJECT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_EJECT_SCSI is not set +# CONFIG_BUSYBOX_DEFAULT_FBSPLASH is not set +# CONFIG_BUSYBOX_DEFAULT_FLASH_ERASEALL is not set +# CONFIG_BUSYBOX_DEFAULT_FLASH_LOCK is not set +# CONFIG_BUSYBOX_DEFAULT_FLASH_UNLOCK is not set +# CONFIG_BUSYBOX_DEFAULT_FLASHCP is not set +# CONFIG_BUSYBOX_DEFAULT_HDPARM is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HDPARM_GET_IDENTITY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_GETSET_DMA is not set +# CONFIG_BUSYBOX_DEFAULT_I2CGET is not set +# CONFIG_BUSYBOX_DEFAULT_I2CSET is not set +# CONFIG_BUSYBOX_DEFAULT_I2CDUMP is not set +# CONFIG_BUSYBOX_DEFAULT_I2CDETECT is not set +# CONFIG_BUSYBOX_DEFAULT_INOTIFYD is not set +# CONFIG_BUSYBOX_DEFAULT_IONICE is not set +# CONFIG_BUSYBOX_DEFAULT_LAST is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LAST_FANCY is not set +CONFIG_BUSYBOX_DEFAULT_LESS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_MAXLINES=9999999 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_BRACKETS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_FLAGS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_TRUNCATE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_MARKS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_REGEXP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_WINCH is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_ASK_TERMINAL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_DASHCMD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_LINENUMS is not set +CONFIG_BUSYBOX_DEFAULT_LOCK=y +# CONFIG_BUSYBOX_DEFAULT_LSSCSI is not set +# CONFIG_BUSYBOX_DEFAULT_MAKEDEVS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MAKEDEVS_LEAF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MAKEDEVS_TABLE is not set +# CONFIG_BUSYBOX_DEFAULT_MAN is not set +# CONFIG_BUSYBOX_DEFAULT_MICROCOM is not set +# CONFIG_BUSYBOX_DEFAULT_MOUNTPOINT is not set +# CONFIG_BUSYBOX_DEFAULT_MT is not set +# CONFIG_BUSYBOX_DEFAULT_NANDWRITE is not set +# CONFIG_BUSYBOX_DEFAULT_NANDDUMP is not set +# CONFIG_BUSYBOX_DEFAULT_PARTPROBE is not set +# CONFIG_BUSYBOX_DEFAULT_RAIDAUTORUN is not set +# CONFIG_BUSYBOX_DEFAULT_READAHEAD is not set +# CONFIG_BUSYBOX_DEFAULT_RFKILL is not set +# CONFIG_BUSYBOX_DEFAULT_RUNLEVEL is not set +# CONFIG_BUSYBOX_DEFAULT_RX is not set +# CONFIG_BUSYBOX_DEFAULT_SETSERIAL is not set +# CONFIG_BUSYBOX_DEFAULT_SETSID is not set +CONFIG_BUSYBOX_DEFAULT_STRINGS=y +# CONFIG_BUSYBOX_DEFAULT_TASKSET is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TASKSET_FANCY is not set +CONFIG_BUSYBOX_DEFAULT_TIME=y +# CONFIG_BUSYBOX_DEFAULT_TIMEOUT is not set +# CONFIG_BUSYBOX_DEFAULT_TTYSIZE is not set +# CONFIG_BUSYBOX_DEFAULT_UBIATTACH is not set +# CONFIG_BUSYBOX_DEFAULT_UBIDETACH is not set +# CONFIG_BUSYBOX_DEFAULT_UBIMKVOL is not set +# CONFIG_BUSYBOX_DEFAULT_UBIRMVOL is not set +# CONFIG_BUSYBOX_DEFAULT_UBIRSVOL is not set +# CONFIG_BUSYBOX_DEFAULT_UBIUPDATEVOL is not set +# CONFIG_BUSYBOX_DEFAULT_UBIRENAME is not set +# CONFIG_BUSYBOX_DEFAULT_VOLNAME is not set +# CONFIG_BUSYBOX_DEFAULT_WALL is not set +# CONFIG_BUSYBOX_DEFAULT_WATCHDOG is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_IPV6=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UNIX_LOCAL is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_PREFER_IPV4_ADDRESS=y +CONFIG_BUSYBOX_DEFAULT_VERBOSE_RESOLUTION_ERRORS=y +# CONFIG_BUSYBOX_DEFAULT_ARP is not set +# CONFIG_BUSYBOX_DEFAULT_ARPING is not set +CONFIG_BUSYBOX_DEFAULT_BRCTL=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_BRCTL_FANCY=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_BRCTL_SHOW=y +# CONFIG_BUSYBOX_DEFAULT_DNSD is not set +# CONFIG_BUSYBOX_DEFAULT_ETHER_WAKE is not set +# CONFIG_BUSYBOX_DEFAULT_FTPD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FTPD_WRITE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FTPD_AUTHENTICATION is not set +# CONFIG_BUSYBOX_DEFAULT_FTPGET is not set +# CONFIG_BUSYBOX_DEFAULT_FTPPUT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FTPGETPUT_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_HOSTNAME is not set +# CONFIG_BUSYBOX_DEFAULT_DNSDOMAINNAME is not set +# CONFIG_BUSYBOX_DEFAULT_HTTPD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_RANGES is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_SETUID is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_BASIC_AUTH is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_AUTH_MD5 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_CGI is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_ENCODE_URL_STR is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_ERROR_PAGES is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_PROXY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_GZIP is not set +CONFIG_BUSYBOX_DEFAULT_IFCONFIG=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_IFCONFIG_STATUS=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IFCONFIG_SLIP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_IFCONFIG_HW=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_IFCONFIG_BROADCAST_PLUS=y +# CONFIG_BUSYBOX_DEFAULT_IFENSLAVE is not set +# CONFIG_BUSYBOX_DEFAULT_IFPLUGD is not set +# CONFIG_BUSYBOX_DEFAULT_IFUP is not set +# CONFIG_BUSYBOX_DEFAULT_IFDOWN is not set +CONFIG_BUSYBOX_DEFAULT_IFUPDOWN_IFSTATE_PATH="" +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IPV4 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IPV6 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_MAPPING is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set +# CONFIG_BUSYBOX_DEFAULT_INETD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INETD_RPC is not set +CONFIG_BUSYBOX_DEFAULT_IP=y +# CONFIG_BUSYBOX_DEFAULT_IPADDR is not set +# CONFIG_BUSYBOX_DEFAULT_IPLINK is not set +# CONFIG_BUSYBOX_DEFAULT_IPROUTE is not set +# CONFIG_BUSYBOX_DEFAULT_IPTUNNEL is not set +# CONFIG_BUSYBOX_DEFAULT_IPRULE is not set +# CONFIG_BUSYBOX_DEFAULT_IPNEIGH is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_IP_ADDRESS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_IP_LINK=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_IP_ROUTE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_IP_ROUTE_DIR="/etc/iproute2" +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IP_TUNNEL is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_IP_RULE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_IP_NEIGH=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IP_RARE_PROTOCOLS is not set +# CONFIG_BUSYBOX_DEFAULT_IPCALC is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IPCALC_FANCY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IPCALC_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FAKEIDENTD is not set +# CONFIG_BUSYBOX_DEFAULT_NAMEIF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_NAMEIF_EXTENDED is not set +# CONFIG_BUSYBOX_DEFAULT_NBDCLIENT is not set +CONFIG_BUSYBOX_DEFAULT_NC=y +# CONFIG_BUSYBOX_DEFAULT_NC_SERVER is not set +# CONFIG_BUSYBOX_DEFAULT_NC_EXTRA is not set +# CONFIG_BUSYBOX_DEFAULT_NC_110_COMPAT is not set +CONFIG_BUSYBOX_DEFAULT_NETMSG=y +CONFIG_BUSYBOX_DEFAULT_NETSTAT=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_NETSTAT_WIDE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_NETSTAT_PRG=y +# CONFIG_BUSYBOX_DEFAULT_NSLOOKUP is not set +CONFIG_BUSYBOX_DEFAULT_NSLOOKUP_LEDE=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_NSLOOKUP_LEDE_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_NTPD=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_NTPD_SERVER=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_NTPD_CONF is not set +CONFIG_BUSYBOX_DEFAULT_PING=y +CONFIG_BUSYBOX_DEFAULT_PING6=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FANCY_PING=y +# CONFIG_BUSYBOX_DEFAULT_PSCAN is not set +CONFIG_BUSYBOX_DEFAULT_ROUTE=y +# CONFIG_BUSYBOX_DEFAULT_SLATTACH is not set +# CONFIG_BUSYBOX_DEFAULT_SSL_CLIENT is not set +# CONFIG_BUSYBOX_DEFAULT_TCPSVD is not set +# CONFIG_BUSYBOX_DEFAULT_UDPSVD is not set +# CONFIG_BUSYBOX_DEFAULT_TELNET is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TELNET_TTYPE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TELNET_AUTOLOGIN is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TELNET_WIDTH is not set +# CONFIG_BUSYBOX_DEFAULT_TELNETD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TELNETD_STANDALONE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TELNETD_INETD_WAIT is not set +# CONFIG_BUSYBOX_DEFAULT_TFTP is not set +# CONFIG_BUSYBOX_DEFAULT_TFTPD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TFTP_GET is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TFTP_PUT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TFTP_BLOCKSIZE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TFTP_PROGRESS_BAR is not set +# CONFIG_BUSYBOX_DEFAULT_TFTP_DEBUG is not set +# CONFIG_BUSYBOX_DEFAULT_TLS is not set +CONFIG_BUSYBOX_DEFAULT_TRACEROUTE=y +CONFIG_BUSYBOX_DEFAULT_TRACEROUTE6=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_TRACEROUTE_VERBOSE=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TRACEROUTE_USE_ICMP is not set +# CONFIG_BUSYBOX_DEFAULT_TUNCTL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TUNCTL_UG is not set +# CONFIG_BUSYBOX_DEFAULT_VCONFIG is not set +# CONFIG_BUSYBOX_DEFAULT_WGET is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_WGET_STATUSBAR is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_WGET_AUTHENTICATION is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_WGET_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_WGET_TIMEOUT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_WGET_HTTPS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_WGET_OPENSSL is not set +# CONFIG_BUSYBOX_DEFAULT_WHOIS is not set +# CONFIG_BUSYBOX_DEFAULT_ZCIP is not set +# CONFIG_BUSYBOX_DEFAULT_UDHCPC6 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCPC6_RFC3646 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCPC6_RFC4704 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCPC6_RFC4833 is not set +# CONFIG_BUSYBOX_DEFAULT_UDHCPD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCPD_BASE_IP_ON_MAC is not set +CONFIG_BUSYBOX_DEFAULT_DHCPD_LEASES_FILE="" +# CONFIG_BUSYBOX_DEFAULT_DUMPLEASES is not set +# CONFIG_BUSYBOX_DEFAULT_DHCPRELAY is not set +CONFIG_BUSYBOX_DEFAULT_UDHCPC=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCPC_ARPING is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCPC_SANITIZEOPT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCP_PORT is not set +CONFIG_BUSYBOX_DEFAULT_UDHCP_DEBUG=0 +CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCP_RFC3397=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCP_8021Q is not set +CONFIG_BUSYBOX_DEFAULT_UDHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script" +CONFIG_BUSYBOX_DEFAULT_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80 +CONFIG_BUSYBOX_DEFAULT_IFUPDOWN_UDHCPC_CMD_OPTIONS="" +# CONFIG_BUSYBOX_DEFAULT_LPD is not set +# CONFIG_BUSYBOX_DEFAULT_LPR is not set +# CONFIG_BUSYBOX_DEFAULT_LPQ is not set +# CONFIG_BUSYBOX_DEFAULT_MAKEMIME is not set +# CONFIG_BUSYBOX_DEFAULT_POPMAILDIR is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_POPMAILDIR_DELIVERY is not set +# CONFIG_BUSYBOX_DEFAULT_REFORMIME is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_REFORMIME_COMPAT is not set +# CONFIG_BUSYBOX_DEFAULT_SENDMAIL is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_MIME_CHARSET="" +CONFIG_BUSYBOX_DEFAULT_FREE=y +# CONFIG_BUSYBOX_DEFAULT_FUSER is not set +# CONFIG_BUSYBOX_DEFAULT_IOSTAT is not set +CONFIG_BUSYBOX_DEFAULT_KILL=y +CONFIG_BUSYBOX_DEFAULT_KILLALL=y +# CONFIG_BUSYBOX_DEFAULT_KILLALL5 is not set +# CONFIG_BUSYBOX_DEFAULT_LSOF is not set +# CONFIG_BUSYBOX_DEFAULT_MPSTAT is not set +# CONFIG_BUSYBOX_DEFAULT_NMETER is not set +CONFIG_BUSYBOX_DEFAULT_PGREP=y +# CONFIG_BUSYBOX_DEFAULT_PKILL is not set +CONFIG_BUSYBOX_DEFAULT_PIDOF=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_PIDOF_SINGLE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_PIDOF_OMIT is not set +# CONFIG_BUSYBOX_DEFAULT_PMAP is not set +# CONFIG_BUSYBOX_DEFAULT_POWERTOP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_POWERTOP_INTERACTIVE is not set +CONFIG_BUSYBOX_DEFAULT_PS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_PS_WIDE=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_PS_LONG is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_PS_TIME is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_PS_ADDITIONAL_COLUMNS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_PS_UNUSUAL_SYSTEMS is not set +# CONFIG_BUSYBOX_DEFAULT_PSTREE is not set +# CONFIG_BUSYBOX_DEFAULT_PWDX is not set +# CONFIG_BUSYBOX_DEFAULT_RENICE is not set +# CONFIG_BUSYBOX_DEFAULT_SMEMCAP is not set +CONFIG_BUSYBOX_DEFAULT_BB_SYSCTL=y +CONFIG_BUSYBOX_DEFAULT_TOP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TOP_INTERACTIVE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TOP_SMP_CPU is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TOP_DECIMALS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TOP_SMP_PROCESS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TOPMEM is not set +CONFIG_BUSYBOX_DEFAULT_UPTIME=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UPTIME_UTMP_SUPPORT is not set +# CONFIG_BUSYBOX_DEFAULT_WATCH is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SHOW_THREADS is not set +# CONFIG_BUSYBOX_DEFAULT_CHPST is not set +# CONFIG_BUSYBOX_DEFAULT_SETUIDGID is not set +# CONFIG_BUSYBOX_DEFAULT_ENVUIDGID is not set +# CONFIG_BUSYBOX_DEFAULT_ENVDIR is not set +# CONFIG_BUSYBOX_DEFAULT_SOFTLIMIT is not set +# CONFIG_BUSYBOX_DEFAULT_RUNSV is not set +# CONFIG_BUSYBOX_DEFAULT_RUNSVDIR is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_RUNSVDIR_LOG is not set +# CONFIG_BUSYBOX_DEFAULT_SV is not set +CONFIG_BUSYBOX_DEFAULT_SV_DEFAULT_SERVICE_DIR="" +# CONFIG_BUSYBOX_DEFAULT_SVC is not set +# CONFIG_BUSYBOX_DEFAULT_SVLOGD is not set +# CONFIG_BUSYBOX_DEFAULT_CHCON is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHCON_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_GETENFORCE is not set +# CONFIG_BUSYBOX_DEFAULT_GETSEBOOL is not set +# CONFIG_BUSYBOX_DEFAULT_LOAD_POLICY is not set +# CONFIG_BUSYBOX_DEFAULT_MATCHPATHCON is not set +# CONFIG_BUSYBOX_DEFAULT_RUNCON is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_RUNCON_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_SELINUXENABLED is not set +# CONFIG_BUSYBOX_DEFAULT_SESTATUS is not set +# CONFIG_BUSYBOX_DEFAULT_SETENFORCE is not set +# CONFIG_BUSYBOX_DEFAULT_SETFILES is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SETFILES_CHECK_OPTION is not set +# CONFIG_BUSYBOX_DEFAULT_RESTORECON is not set +# CONFIG_BUSYBOX_DEFAULT_SETSEBOOL is not set +CONFIG_BUSYBOX_DEFAULT_SH_IS_ASH=y +# CONFIG_BUSYBOX_DEFAULT_SH_IS_HUSH is not set +# CONFIG_BUSYBOX_DEFAULT_SH_IS_NONE is not set +# CONFIG_BUSYBOX_DEFAULT_BASH_IS_ASH is not set +# CONFIG_BUSYBOX_DEFAULT_BASH_IS_HUSH is not set +CONFIG_BUSYBOX_DEFAULT_BASH_IS_NONE=y +CONFIG_BUSYBOX_DEFAULT_ASH=y +# CONFIG_BUSYBOX_DEFAULT_ASH_OPTIMIZE_FOR_SIZE is not set +CONFIG_BUSYBOX_DEFAULT_ASH_INTERNAL_GLOB=y +CONFIG_BUSYBOX_DEFAULT_ASH_BASH_COMPAT=y +CONFIG_BUSYBOX_DEFAULT_ASH_JOB_CONTROL=y +CONFIG_BUSYBOX_DEFAULT_ASH_ALIAS=y +# CONFIG_BUSYBOX_DEFAULT_ASH_RANDOM_SUPPORT is not set +CONFIG_BUSYBOX_DEFAULT_ASH_EXPAND_PRMT=y +# CONFIG_BUSYBOX_DEFAULT_ASH_IDLE_TIMEOUT is not set +# CONFIG_BUSYBOX_DEFAULT_ASH_MAIL is not set +CONFIG_BUSYBOX_DEFAULT_ASH_ECHO=y +CONFIG_BUSYBOX_DEFAULT_ASH_PRINTF=y +CONFIG_BUSYBOX_DEFAULT_ASH_TEST=y +# CONFIG_BUSYBOX_DEFAULT_ASH_HELP is not set +CONFIG_BUSYBOX_DEFAULT_ASH_GETOPTS=y +CONFIG_BUSYBOX_DEFAULT_ASH_CMDCMD=y +# CONFIG_BUSYBOX_DEFAULT_CTTYHACK is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_BASH_COMPAT is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_BRACE_EXPANSION is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_HELP is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_INTERACTIVE is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_SAVEHISTORY is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_JOB is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_TICK is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_IF is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_LOOPS is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_CASE is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_FUNCTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_LOCAL is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_RANDOM_SUPPORT is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_MODE_X is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_ECHO is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_PRINTF is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_TEST is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_EXPORT is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_EXPORT_N is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_KILL is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_WAIT is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_TRAP is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_TYPE is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_READ is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_SET is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_UNSET is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_ULIMIT is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_UMASK is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_MEMLEAK is not set +# CONFIG_BUSYBOX_DEFAULT_MSH is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_SH_MATH=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_SH_MATH_64=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SH_EXTRA_QUIET is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SH_STANDALONE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_SH_NOFORK=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SH_HISTFILESIZE is not set +# CONFIG_BUSYBOX_DEFAULT_KLOGD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_KLOGD_KLOGCTL is not set +CONFIG_BUSYBOX_DEFAULT_LOGGER=y +# CONFIG_BUSYBOX_DEFAULT_LOGREAD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LOGREAD_REDUCED_LOCKING is not set +# CONFIG_BUSYBOX_DEFAULT_SYSLOGD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_ROTATE_LOGFILE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_REMOTE_LOG is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SYSLOGD_DUP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SYSLOGD_CFG is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_SYSLOGD_READ_BUFFER_SIZE=0 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IPC_SYSLOG is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_IPC_SYSLOG_BUFFER_SIZE=0 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_KMSG_SYSLOG is not set +# CONFIG_PACKAGE_ca-bundle is not set +# CONFIG_PACKAGE_ca-certificates is not set +# CONFIG_PACKAGE_dnsmasq is not set +# CONFIG_PACKAGE_dnsmasq-dhcpv6 is not set +CONFIG_PACKAGE_dnsmasq-full=y +CONFIG_PACKAGE_dnsmasq_full_dhcpv6=y +CONFIG_PACKAGE_dnsmasq_full_dnssec=y +CONFIG_PACKAGE_dnsmasq_full_auth=y +CONFIG_PACKAGE_dnsmasq_full_ipset=y +CONFIG_PACKAGE_dnsmasq_full_conntrack=y +CONFIG_PACKAGE_dnsmasq_full_noid=y +# CONFIG_PACKAGE_dnsmasq_full_broken_rtc is not set +CONFIG_PACKAGE_dropbear=y + +# +# Configuration +# +CONFIG_DROPBEAR_CURVE25519=y +# CONFIG_DROPBEAR_ECC is not set +# CONFIG_PACKAGE_ead is not set +CONFIG_PACKAGE_firewall=y +CONFIG_PACKAGE_fstools=y +CONFIG_PACKAGE_fwtool=y +CONFIG_PACKAGE_jsonfilter=y +CONFIG_PACKAGE_lede-keyring=y +# CONFIG_PACKAGE_libatomic is not set +CONFIG_PACKAGE_libc=y +CONFIG_PACKAGE_libgcc=y +# CONFIG_PACKAGE_libgomp is not set +CONFIG_PACKAGE_libpthread=y +CONFIG_PACKAGE_librt=y +CONFIG_PACKAGE_libstdcpp=y +CONFIG_PACKAGE_logd=y +# CONFIG_PACKAGE_mksh is not set +CONFIG_PACKAGE_mtd=y +CONFIG_PACKAGE_netifd=y +# CONFIG_PACKAGE_nvram is not set +# CONFIG_PACKAGE_om-watchdog is not set +CONFIG_PACKAGE_opkg=y +CONFIG_PACKAGE_procd=y + +# +# Configuration +# +# CONFIG_PROCD_SHOW_BOOT is not set +# CONFIG_PROCD_ZRAM_TMPFS is not set +# CONFIG_PACKAGE_qos-scripts is not set +# CONFIG_PACKAGE_resolveip is not set +CONFIG_PACKAGE_rpcd=y +# CONFIG_PACKAGE_rpcd-mod-attendedsysupgrade is not set +# CONFIG_PACKAGE_rpcd-mod-file is not set +# CONFIG_PACKAGE_rpcd-mod-iwinfo is not set +# CONFIG_PACKAGE_rpcd-mod-packagelist is not set +# CONFIG_PACKAGE_rpcd-mod-rpcsys is not set +# CONFIG_PACKAGE_snapshot-tool is not set +CONFIG_PACKAGE_sqm-scripts=y +# CONFIG_PACKAGE_sqm-scripts-extra is not set +CONFIG_PACKAGE_swconfig=y +CONFIG_PACKAGE_ubox=y +CONFIG_PACKAGE_ubus=y +CONFIG_PACKAGE_ubusd=y +CONFIG_PACKAGE_uci=y +CONFIG_PACKAGE_usign=y +# CONFIG_PACKAGE_wireless-tools is not set +# CONFIG_PACKAGE_zram-swap is not set + +# +# Administration +# + +# +# openwisp +# +# CONFIG_PACKAGE_openwisp-config-cyassl is not set +# CONFIG_PACKAGE_openwisp-config-mbedtls is not set +# CONFIG_PACKAGE_openwisp-config-nossl is not set +# CONFIG_PACKAGE_openwisp-config-openssl is not set + +# +# zabbix +# +# CONFIG_PACKAGE_zabbix-agentd is not set +# CONFIG_PACKAGE_zabbix-extra-mac80211 is not set +# CONFIG_PACKAGE_zabbix-extra-network is not set +# CONFIG_PACKAGE_zabbix-extra-wifi is not set +# CONFIG_PACKAGE_zabbix-get is not set +# CONFIG_PACKAGE_zabbix-proxy is not set +# CONFIG_PACKAGE_zabbix-sender is not set +# CONFIG_PACKAGE_zabbix-server is not set +# CONFIG_PACKAGE_htop is not set +# CONFIG_PACKAGE_ipmitool is not set +# CONFIG_PACKAGE_monit is not set +# CONFIG_PACKAGE_monit-nossl is not set +# CONFIG_PACKAGE_muninlite is not set +# CONFIG_PACKAGE_netdata is not set +# CONFIG_PACKAGE_sudo is not set +# CONFIG_PACKAGE_syslog-ng is not set + +# +# Boot Loaders +# + +# +# Development +# + +# +# Libraries +# +# CONFIG_PACKAGE_libncurses-dev is not set +# CONFIG_PACKAGE_zlib-dev is not set +# CONFIG_PACKAGE_ar is not set +# CONFIG_PACKAGE_autoconf is not set +# CONFIG_PACKAGE_automake is not set +# CONFIG_PACKAGE_binutils is not set +# CONFIG_PACKAGE_diffutils is not set +# CONFIG_PACKAGE_gcc is not set +# CONFIG_PACKAGE_gdb is not set +# CONFIG_PACKAGE_gdbserver is not set +# CONFIG_PACKAGE_libtool-bin is not set +# CONFIG_PACKAGE_lpc21isp is not set +# CONFIG_PACKAGE_lttng-tools is not set +# CONFIG_PACKAGE_m4 is not set +# CONFIG_PACKAGE_make is not set +# CONFIG_PACKAGE_objdump is not set +# CONFIG_PACKAGE_patch is not set +# CONFIG_PACKAGE_pkg-config is not set +# CONFIG_PACKAGE_trace-cmd is not set +# CONFIG_PACKAGE_trace-cmd-extra is not set +# CONFIG_PACKAGE_valgrind is not set + +# +# Extra packages +# +CONFIG_PACKAGE_automount=y +CONFIG_PACKAGE_autosamba=y +# CONFIG_PACKAGE_he-6in4 is not set +# CONFIG_PACKAGE_k3wifi is not set + +# +# Firmware +# + +# +# ath10k IPQ4019 Boarddata +# +# CONFIG_PACKAGE_aircard-pcmcia-firmware is not set +# CONFIG_PACKAGE_ar3k-firmware is not set +# CONFIG_PACKAGE_ath10k-firmware-qca4019 is not set +# CONFIG_PACKAGE_ath10k-firmware-qca6174 is not set +# CONFIG_PACKAGE_ath10k-firmware-qca9887 is not set +# CONFIG_PACKAGE_ath10k-firmware-qca9887-ct is not set +# CONFIG_PACKAGE_ath10k-firmware-qca9888 is not set +# CONFIG_PACKAGE_ath10k-firmware-qca9888-ct is not set +# CONFIG_PACKAGE_ath10k-firmware-qca988x is not set +# CONFIG_PACKAGE_ath10k-firmware-qca988x-ct is not set +# CONFIG_PACKAGE_ath10k-firmware-qca9984 is not set +# CONFIG_PACKAGE_ath10k-firmware-qca9984-ct is not set +# CONFIG_PACKAGE_ath10k-firmware-qca99x0 is not set +# CONFIG_PACKAGE_ath10k-firmware-qca99x0-ct is not set +# CONFIG_PACKAGE_ath6k-firmware is not set +# CONFIG_PACKAGE_ath9k-htc-firmware is not set +# CONFIG_PACKAGE_b43legacy-firmware is not set +# CONFIG_PACKAGE_bnx2-firmware is not set +# CONFIG_PACKAGE_brcmfmac-firmware-4329-sdio is not set +# CONFIG_PACKAGE_brcmfmac-firmware-43362-sdio is not set +# CONFIG_PACKAGE_brcmfmac-firmware-43430-sdio is not set +# CONFIG_PACKAGE_brcmfmac-firmware-43602a1-pcie is not set +# CONFIG_PACKAGE_brcmfmac-firmware-4366b1-pcie is not set +# CONFIG_PACKAGE_brcmfmac-firmware-usb is not set +# CONFIG_PACKAGE_brcmsmac-firmware is not set +# CONFIG_PACKAGE_carl9170-firmware is not set +# CONFIG_PACKAGE_ibt-firmware is not set +# CONFIG_PACKAGE_iwl3945-firmware is not set +# CONFIG_PACKAGE_iwl4965-firmware is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl100 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl1000 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl105 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl135 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl2000 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl2030 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl3160 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl3168 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl5000 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl5150 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl6000g2 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl6000g2a is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl6000g2b is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl6050 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl7260 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl7265 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl7265d is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl8260c is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl8265 is not set +# CONFIG_PACKAGE_libertas-sdio-firmware is not set +# CONFIG_PACKAGE_libertas-spi-firmware is not set +# CONFIG_PACKAGE_libertas-usb-firmware is not set +# CONFIG_PACKAGE_mt7601u-firmware is not set +# CONFIG_PACKAGE_mwifiex-pcie-firmware is not set +# CONFIG_PACKAGE_mwifiex-sdio-firmware is not set +# CONFIG_PACKAGE_mwl8k-firmware is not set +# CONFIG_PACKAGE_p54-pci-firmware is not set +# CONFIG_PACKAGE_p54-spi-firmware is not set +# CONFIG_PACKAGE_p54-usb-firmware is not set +# CONFIG_PACKAGE_prism54-firmware is not set +# CONFIG_PACKAGE_r8169-firmware is not set +# CONFIG_PACKAGE_rt2800-pci-firmware is not set +# CONFIG_PACKAGE_rt2800-usb-firmware is not set +# CONFIG_PACKAGE_rt61-pci-firmware is not set +# CONFIG_PACKAGE_rt73-usb-firmware is not set +# CONFIG_PACKAGE_rtl8188eu-firmware is not set +# CONFIG_PACKAGE_rtl8192ce-firmware is not set +# CONFIG_PACKAGE_rtl8192cu-firmware is not set +# CONFIG_PACKAGE_rtl8192de-firmware is not set +# CONFIG_PACKAGE_rtl8192se-firmware is not set +# CONFIG_PACKAGE_rtl8192su-firmware is not set +# CONFIG_PACKAGE_rtl8821ae-firmware is not set +# CONFIG_PACKAGE_wl12xx-firmware is not set +# CONFIG_PACKAGE_wl18xx-firmware is not set + +# +# Fonts +# + +# +# DejaVu +# +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuMathTeXGyre is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSans is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSans-Bold is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSans-BoldOblique is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSans-ExtraLight is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSans-Oblique is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSansCondensed is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSansCondensed-Bold is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSansCondensed-BoldOblique is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSansCondensed-Oblique is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSansMono is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSansMono-Bold is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSansMono-BoldOblique is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSansMono-Oblique is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSerif is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSerif-Bold is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSerif-BoldItalic is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSerif-Italic is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSerifCondensed is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSerifCondensed-Bold is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSerifCondensed-BoldItalic is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSerifCondensed-Italic is not set + +# +# Kernel modules +# + +# +# Block Devices +# +# CONFIG_PACKAGE_kmod-aoe is not set +# CONFIG_PACKAGE_kmod-ata-core is not set +# CONFIG_PACKAGE_kmod-block2mtd is not set +# CONFIG_PACKAGE_kmod-dm is not set +# CONFIG_PACKAGE_kmod-loop is not set +# CONFIG_PACKAGE_kmod-md-mod is not set +# CONFIG_PACKAGE_kmod-nbd is not set +# CONFIG_PACKAGE_kmod-scsi-cdrom is not set +CONFIG_PACKAGE_kmod-scsi-core=y +# CONFIG_PACKAGE_kmod-scsi-generic is not set +# CONFIG_PACKAGE_kmod-scsi-tape is not set + +# +# CAN Support +# +# CONFIG_PACKAGE_kmod-can is not set + +# +# Cryptographic API modules +# +CONFIG_PACKAGE_kmod-crypto-aead=y +CONFIG_PACKAGE_kmod-crypto-authenc=y +CONFIG_PACKAGE_kmod-crypto-cbc=y +# CONFIG_PACKAGE_kmod-crypto-ccm is not set +# CONFIG_PACKAGE_kmod-crypto-cmac is not set +CONFIG_PACKAGE_kmod-crypto-crc32c=y +# CONFIG_PACKAGE_kmod-crypto-ctr is not set +CONFIG_PACKAGE_kmod-crypto-deflate=y +CONFIG_PACKAGE_kmod-crypto-des=y +CONFIG_PACKAGE_kmod-crypto-ecb=y +CONFIG_PACKAGE_kmod-crypto-echainiv=y +# CONFIG_PACKAGE_kmod-crypto-fcrypt is not set +# CONFIG_PACKAGE_kmod-crypto-gcm is not set +# CONFIG_PACKAGE_kmod-crypto-gf128 is not set +# CONFIG_PACKAGE_kmod-crypto-ghash is not set +CONFIG_PACKAGE_kmod-crypto-hash=y +CONFIG_PACKAGE_kmod-crypto-hmac=y +# CONFIG_PACKAGE_kmod-crypto-hw-ccp is not set +# CONFIG_PACKAGE_kmod-crypto-hw-geode is not set +# CONFIG_PACKAGE_kmod-crypto-hw-hifn-795x is not set +# CONFIG_PACKAGE_kmod-crypto-hw-padlock is not set +# CONFIG_PACKAGE_kmod-crypto-hw-talitos is not set +CONFIG_PACKAGE_kmod-crypto-iv=y +CONFIG_PACKAGE_kmod-crypto-manager=y +# CONFIG_PACKAGE_kmod-crypto-md4 is not set +CONFIG_PACKAGE_kmod-crypto-md5=y +# CONFIG_PACKAGE_kmod-crypto-michael-mic is not set +# CONFIG_PACKAGE_kmod-crypto-misc is not set +CONFIG_PACKAGE_kmod-crypto-null=y +# CONFIG_PACKAGE_kmod-crypto-pcbc is not set +CONFIG_PACKAGE_kmod-crypto-pcompress=y +CONFIG_PACKAGE_kmod-crypto-rng=y +# CONFIG_PACKAGE_kmod-crypto-seqiv is not set +CONFIG_PACKAGE_kmod-crypto-sha1=y +CONFIG_PACKAGE_kmod-crypto-sha256=y +# CONFIG_PACKAGE_kmod-crypto-sha512 is not set +# CONFIG_PACKAGE_kmod-crypto-test is not set +# CONFIG_PACKAGE_kmod-crypto-user is not set +CONFIG_PACKAGE_kmod-crypto-wq=y +# CONFIG_PACKAGE_kmod-crypto-xts is not set +# CONFIG_PACKAGE_kmod-cryptodev is not set + +# +# Filesystems +# +# CONFIG_PACKAGE_kmod-fs-afs is not set +# CONFIG_PACKAGE_kmod-fs-autofs4 is not set +# CONFIG_PACKAGE_kmod-fs-btrfs is not set +# CONFIG_PACKAGE_kmod-fs-cifs is not set +CONFIG_PACKAGE_kmod-fs-configfs=y +# CONFIG_PACKAGE_kmod-fs-cramfs is not set +CONFIG_PACKAGE_kmod-fs-exfat=y +# CONFIG_PACKAGE_kmod-fs-exportfs is not set +CONFIG_PACKAGE_kmod-fs-ext4=y +# CONFIG_PACKAGE_kmod-fs-f2fs is not set +# CONFIG_PACKAGE_kmod-fs-fscache is not set +# CONFIG_PACKAGE_kmod-fs-hfs is not set +# CONFIG_PACKAGE_kmod-fs-hfsplus is not set +# CONFIG_PACKAGE_kmod-fs-isofs is not set +# CONFIG_PACKAGE_kmod-fs-jfs is not set +# CONFIG_PACKAGE_kmod-fs-minix is not set +# CONFIG_PACKAGE_kmod-fs-msdos is not set +# CONFIG_PACKAGE_kmod-fs-nfs is not set +# CONFIG_PACKAGE_kmod-fs-nfs-common is not set +# CONFIG_PACKAGE_kmod-fs-nfsd is not set +CONFIG_PACKAGE_kmod-fs-ntfs=y +# CONFIG_PACKAGE_kmod-fs-reiserfs is not set +# CONFIG_PACKAGE_kmod-fs-squashfs is not set +# CONFIG_PACKAGE_kmod-fs-udf is not set +CONFIG_PACKAGE_kmod-fs-vfat=y +# CONFIG_PACKAGE_kmod-fs-xfs is not set +CONFIG_PACKAGE_kmod-fuse=y + +# +# FireWire support +# +# CONFIG_PACKAGE_kmod-firewire is not set + +# +# Hardware Monitoring Support +# +# CONFIG_PACKAGE_kmod-hwmon-core is not set + +# +# I2C support +# +# CONFIG_PACKAGE_kmod-i2c-core is not set +# CONFIG_PACKAGE_kmod-i2c-gpio-custom is not set + +# +# Input modules +# +# CONFIG_PACKAGE_kmod-hid is not set +# CONFIG_PACKAGE_kmod-hid-generic is not set +# CONFIG_PACKAGE_kmod-input-core is not set +# CONFIG_PACKAGE_kmod-input-evdev is not set +# CONFIG_PACKAGE_kmod-input-gpio-encoder is not set +# CONFIG_PACKAGE_kmod-input-gpio-keys is not set +# CONFIG_PACKAGE_kmod-input-gpio-keys-polled is not set +# CONFIG_PACKAGE_kmod-input-joydev is not set +# CONFIG_PACKAGE_kmod-input-matrixkmap is not set +# CONFIG_PACKAGE_kmod-input-polldev is not set +# CONFIG_PACKAGE_kmod-input-uinput is not set + +# +# LED modules +# +# CONFIG_PACKAGE_kmod-leds-gpio is not set +# CONFIG_PACKAGE_kmod-leds-nu801 is not set +# CONFIG_PACKAGE_kmod-leds-pca963x is not set +# CONFIG_PACKAGE_kmod-leds-rb750 is not set +# CONFIG_PACKAGE_kmod-leds-wndr3700-usb is not set +# CONFIG_PACKAGE_kmod-ledtrig-default-on is not set +# CONFIG_PACKAGE_kmod-ledtrig-gpio is not set +# CONFIG_PACKAGE_kmod-ledtrig-heartbeat is not set +# CONFIG_PACKAGE_kmod-ledtrig-netdev is not set +# CONFIG_PACKAGE_kmod-ledtrig-oneshot is not set +# CONFIG_PACKAGE_kmod-ledtrig-timer is not set +# CONFIG_PACKAGE_kmod-ledtrig-transient is not set + +# +# Libraries +# +# CONFIG_PACKAGE_kmod-lib-cordic is not set +CONFIG_PACKAGE_kmod-lib-crc-ccitt=y +# CONFIG_PACKAGE_kmod-lib-crc-itu-t is not set +CONFIG_PACKAGE_kmod-lib-crc16=y +# CONFIG_PACKAGE_kmod-lib-crc32c is not set +# CONFIG_PACKAGE_kmod-lib-crc7 is not set +# CONFIG_PACKAGE_kmod-lib-crc8 is not set +CONFIG_PACKAGE_kmod-lib-textsearch=y +CONFIG_PACKAGE_kmod-lib-zlib-deflate=y +CONFIG_PACKAGE_kmod-lib-zlib-inflate=y + +# +# Native Language Support +# +CONFIG_PACKAGE_kmod-nls-base=y +# CONFIG_PACKAGE_kmod-nls-cp1250 is not set +# CONFIG_PACKAGE_kmod-nls-cp1251 is not set +CONFIG_PACKAGE_kmod-nls-cp437=y +# CONFIG_PACKAGE_kmod-nls-cp775 is not set +# CONFIG_PACKAGE_kmod-nls-cp850 is not set +# CONFIG_PACKAGE_kmod-nls-cp852 is not set +# CONFIG_PACKAGE_kmod-nls-cp862 is not set +# CONFIG_PACKAGE_kmod-nls-cp864 is not set +# CONFIG_PACKAGE_kmod-nls-cp866 is not set +# CONFIG_PACKAGE_kmod-nls-cp932 is not set +# CONFIG_PACKAGE_kmod-nls-cp936 is not set +# CONFIG_PACKAGE_kmod-nls-cp950 is not set +CONFIG_PACKAGE_kmod-nls-iso8859-1=y +# CONFIG_PACKAGE_kmod-nls-iso8859-13 is not set +# CONFIG_PACKAGE_kmod-nls-iso8859-15 is not set +# CONFIG_PACKAGE_kmod-nls-iso8859-2 is not set +# CONFIG_PACKAGE_kmod-nls-iso8859-6 is not set +# CONFIG_PACKAGE_kmod-nls-iso8859-8 is not set +# CONFIG_PACKAGE_kmod-nls-koi8r is not set +CONFIG_PACKAGE_kmod-nls-utf8=y + +# +# Netfilter Extensions +# +# CONFIG_PACKAGE_kmod-arptables is not set +CONFIG_PACKAGE_kmod-br-netfilter=y +# CONFIG_PACKAGE_kmod-ebtables is not set +CONFIG_PACKAGE_kmod-ip6tables=y +# CONFIG_PACKAGE_kmod-ip6tables-extra is not set +# CONFIG_PACKAGE_kmod-ipt-account is not set +# CONFIG_PACKAGE_kmod-ipt-chaos is not set +# CONFIG_PACKAGE_kmod-ipt-cluster is not set +# CONFIG_PACKAGE_kmod-ipt-clusterip is not set +# CONFIG_PACKAGE_kmod-ipt-compat-xtables is not set +# CONFIG_PACKAGE_kmod-ipt-condition is not set +CONFIG_PACKAGE_kmod-ipt-conntrack=y +CONFIG_PACKAGE_kmod-ipt-conntrack-extra=y +CONFIG_PACKAGE_kmod-ipt-core=y +# CONFIG_PACKAGE_kmod-ipt-debug is not set +# CONFIG_PACKAGE_kmod-ipt-delude is not set +# CONFIG_PACKAGE_kmod-ipt-dhcpmac is not set +# CONFIG_PACKAGE_kmod-ipt-dnetmap is not set +CONFIG_PACKAGE_kmod-ipt-extra=y +# CONFIG_PACKAGE_kmod-ipt-filter is not set +# CONFIG_PACKAGE_kmod-ipt-fuzzy is not set +# CONFIG_PACKAGE_kmod-ipt-geoip is not set +# CONFIG_PACKAGE_kmod-ipt-hashlimit is not set +# CONFIG_PACKAGE_kmod-ipt-iface is not set +# CONFIG_PACKAGE_kmod-ipt-ipmark is not set +CONFIG_PACKAGE_kmod-ipt-ipopt=y +# CONFIG_PACKAGE_kmod-ipt-ipp2p is not set +# CONFIG_PACKAGE_kmod-ipt-iprange is not set +CONFIG_PACKAGE_kmod-ipt-ipsec=y +CONFIG_PACKAGE_kmod-ipt-ipset=y +# CONFIG_PACKAGE_kmod-ipt-ipv4options is not set +# CONFIG_PACKAGE_kmod-ipt-led is not set +# CONFIG_PACKAGE_kmod-ipt-length2 is not set +# CONFIG_PACKAGE_kmod-ipt-logmark is not set +# CONFIG_PACKAGE_kmod-ipt-lscan is not set +# CONFIG_PACKAGE_kmod-ipt-lua is not set +CONFIG_PACKAGE_kmod-ipt-nat=y +CONFIG_PACKAGE_kmod-ipt-nat-extra=y +# CONFIG_PACKAGE_kmod-ipt-nat6 is not set +# CONFIG_PACKAGE_kmod-ipt-nathelper-rtsp is not set +# CONFIG_PACKAGE_kmod-ipt-nflog is not set +# CONFIG_PACKAGE_kmod-ipt-nfqueue is not set +# CONFIG_PACKAGE_kmod-ipt-psd is not set +# CONFIG_PACKAGE_kmod-ipt-quota2 is not set +# CONFIG_PACKAGE_kmod-ipt-raw is not set +# CONFIG_PACKAGE_kmod-ipt-raw6 is not set +# CONFIG_PACKAGE_kmod-ipt-rpfilter is not set +# CONFIG_PACKAGE_kmod-ipt-sysrq is not set +# CONFIG_PACKAGE_kmod-ipt-tarpit is not set +# CONFIG_PACKAGE_kmod-ipt-tee is not set +CONFIG_PACKAGE_kmod-ipt-tproxy=y +# CONFIG_PACKAGE_kmod-ipt-u32 is not set +# CONFIG_PACKAGE_kmod-ipt-ulog is not set +CONFIG_PACKAGE_kmod-nf-conntrack=y +CONFIG_PACKAGE_kmod-nf-conntrack-netlink=y +CONFIG_PACKAGE_kmod-nf-conntrack6=y +CONFIG_PACKAGE_kmod-nf-ipt=y +CONFIG_PACKAGE_kmod-nf-ipt6=y +CONFIG_PACKAGE_kmod-nf-nat=y +# CONFIG_PACKAGE_kmod-nf-nat6 is not set +CONFIG_PACKAGE_kmod-nf-nathelper=y +CONFIG_PACKAGE_kmod-nf-nathelper-extra=y +CONFIG_PACKAGE_kmod-nfnetlink=y +# CONFIG_PACKAGE_kmod-nfnetlink-log is not set +# CONFIG_PACKAGE_kmod-nfnetlink-queue is not set +# CONFIG_PACKAGE_kmod-nft-core is not set +# CONFIG_PACKAGE_kmod-nft-nat is not set +# CONFIG_PACKAGE_kmod-nft-nat6 is not set + +# +# Network Devices +# +# CONFIG_PACKAGE_kmod-3c59x is not set +# CONFIG_PACKAGE_kmod-8139cp is not set +# CONFIG_PACKAGE_kmod-8139too is not set +# CONFIG_PACKAGE_kmod-atl1 is not set +# CONFIG_PACKAGE_kmod-atl1c is not set +# CONFIG_PACKAGE_kmod-atl1e is not set +# CONFIG_PACKAGE_kmod-atl2 is not set +# CONFIG_PACKAGE_kmod-b44 is not set +# CONFIG_PACKAGE_kmod-bnx2 is not set +# CONFIG_PACKAGE_kmod-dm9000 is not set +# CONFIG_PACKAGE_kmod-dummy is not set +# CONFIG_PACKAGE_kmod-e100 is not set +# CONFIG_PACKAGE_kmod-e1000 is not set +# CONFIG_PACKAGE_kmod-et131x is not set +# CONFIG_PACKAGE_kmod-ethoc is not set +# CONFIG_PACKAGE_kmod-forcedeth is not set +# CONFIG_PACKAGE_kmod-gigaset is not set +# CONFIG_PACKAGE_kmod-hfcmulti is not set +# CONFIG_PACKAGE_kmod-hfcpci is not set +CONFIG_PACKAGE_kmod-ifb=y +# CONFIG_PACKAGE_kmod-igb is not set +# CONFIG_PACKAGE_kmod-ixgbe is not set +# CONFIG_PACKAGE_kmod-libphy is not set +CONFIG_PACKAGE_kmod-macvlan=y +# CONFIG_PACKAGE_kmod-mii is not set +# CONFIG_PACKAGE_kmod-natsemi is not set +# CONFIG_PACKAGE_kmod-ne2k-pci is not set +# CONFIG_PACKAGE_kmod-of-mdio is not set +# CONFIG_PACKAGE_kmod-pcnet32 is not set +# CONFIG_PACKAGE_kmod-phy-broadcom is not set +# CONFIG_PACKAGE_kmod-ppfe is not set +# CONFIG_PACKAGE_kmod-r6040 is not set +# CONFIG_PACKAGE_kmod-r8169 is not set +# CONFIG_PACKAGE_kmod-siit is not set +# CONFIG_PACKAGE_kmod-sis190 is not set +# CONFIG_PACKAGE_kmod-sis900 is not set +# CONFIG_PACKAGE_kmod-skge is not set +# CONFIG_PACKAGE_kmod-sky2 is not set +# CONFIG_PACKAGE_kmod-solos-pci is not set +# CONFIG_PACKAGE_kmod-spi-ks8995 is not set +# CONFIG_PACKAGE_kmod-swconfig is not set +# CONFIG_PACKAGE_kmod-switch-ip17xx is not set +# CONFIG_PACKAGE_kmod-switch-mvsw61xx is not set +# CONFIG_PACKAGE_kmod-switch-rtl8366-smi is not set +# CONFIG_PACKAGE_kmod-switch-rtl8366rb is not set +# CONFIG_PACKAGE_kmod-switch-rtl8366s is not set +# CONFIG_PACKAGE_kmod-switch-rtl8367b is not set +# CONFIG_PACKAGE_kmod-tg3 is not set +# CONFIG_PACKAGE_kmod-tulip is not set +# CONFIG_PACKAGE_kmod-via-rhine is not set +# CONFIG_PACKAGE_kmod-via-velocity is not set +# CONFIG_PACKAGE_kmod-vmxnet3 is not set + +# +# Network Support +# +# CONFIG_PACKAGE_kmod-appletalk is not set +# CONFIG_PACKAGE_kmod-atm is not set +# CONFIG_PACKAGE_kmod-ax25 is not set +# CONFIG_PACKAGE_kmod-batman-adv is not set +# CONFIG_PACKAGE_kmod-bonding is not set +# CONFIG_PACKAGE_kmod-capi is not set +# CONFIG_PACKAGE_kmod-dnsresolver is not set +CONFIG_PACKAGE_kmod-fast-classifier=y +CONFIG_PACKAGE_kmod-gre=y +# CONFIG_PACKAGE_kmod-gre6 is not set +# CONFIG_PACKAGE_kmod-ip-vti is not set +# CONFIG_PACKAGE_kmod-ip6-tunnel is not set +# CONFIG_PACKAGE_kmod-ip6-vti is not set +# CONFIG_PACKAGE_kmod-ipip is not set +CONFIG_PACKAGE_kmod-ipsec=y +CONFIG_PACKAGE_kmod-ipsec4=y +CONFIG_PACKAGE_kmod-ipsec6=y +CONFIG_PACKAGE_kmod-iptunnel=y +CONFIG_PACKAGE_kmod-iptunnel4=y +CONFIG_PACKAGE_kmod-iptunnel6=y +# CONFIG_PACKAGE_kmod-isdn4linux is not set +# CONFIG_PACKAGE_kmod-jool is not set +# CONFIG_PACKAGE_kmod-l2tp is not set +# CONFIG_PACKAGE_kmod-l2tp-eth is not set +# CONFIG_PACKAGE_kmod-l2tp-ip is not set +# CONFIG_PACKAGE_kmod-misdn is not set +# CONFIG_PACKAGE_kmod-mpls is not set +CONFIG_PACKAGE_kmod-ppp=y +CONFIG_PACKAGE_kmod-mppe=y +# CONFIG_PACKAGE_kmod-nat46 is not set +# CONFIG_PACKAGE_kmod-netem is not set +# CONFIG_PACKAGE_kmod-nlmon is not set +# CONFIG_PACKAGE_kmod-openvswitch is not set +# CONFIG_PACKAGE_kmod-pktgen is not set +# CONFIG_PACKAGE_kmod-ppp-synctty is not set +# CONFIG_PACKAGE_kmod-pppoa is not set +CONFIG_PACKAGE_kmod-pppoe=y +# CONFIG_PACKAGE_kmod-pppol2tp is not set +CONFIG_PACKAGE_kmod-pppox=y +# CONFIG_PACKAGE_kmod-pptp is not set +# CONFIG_PACKAGE_kmod-sched is not set +CONFIG_PACKAGE_kmod-sched-cake=y +# CONFIG_PACKAGE_kmod-sched-connmark is not set +CONFIG_PACKAGE_kmod-sched-core=y +# CONFIG_PACKAGE_kmod-sctp is not set +CONFIG_PACKAGE_kmod-shortcut-fe=y +# CONFIG_PACKAGE_kmod-shortcut-fe-cm is not set +# CONFIG_PACKAGE_kmod-sit is not set +CONFIG_PACKAGE_kmod-slhc=y +# CONFIG_PACKAGE_kmod-slip is not set +# CONFIG_PACKAGE_kmod-trelay is not set +CONFIG_PACKAGE_kmod-tun=y +# CONFIG_PACKAGE_kmod-veth is not set +# CONFIG_PACKAGE_kmod-vxlan is not set +# CONFIG_PACKAGE_kmod-wireguard is not set + +# +# Other modules +# +# CONFIG_PACKAGE_kmod-6lowpan is not set +# CONFIG_PACKAGE_kmod-ath3k is not set +# CONFIG_PACKAGE_kmod-bcma is not set +# CONFIG_PACKAGE_kmod-bluetooth is not set +# CONFIG_PACKAGE_kmod-bluetooth_6lowpan is not set +# CONFIG_PACKAGE_kmod-bmp085 is not set +# CONFIG_PACKAGE_kmod-bmp085-i2c is not set +# CONFIG_PACKAGE_kmod-bmp085-spi is not set +# CONFIG_PACKAGE_kmod-button-hotplug is not set +# CONFIG_PACKAGE_kmod-echo is not set +# CONFIG_PACKAGE_kmod-eeprom-93cx6 is not set +# CONFIG_PACKAGE_kmod-eeprom-at24 is not set +# CONFIG_PACKAGE_kmod-eeprom-at25 is not set +# CONFIG_PACKAGE_kmod-gpio-beeper is not set +CONFIG_PACKAGE_kmod-gpio-button-hotplug=y +# CONFIG_PACKAGE_kmod-gpio-dev is not set +# CONFIG_PACKAGE_kmod-gpio-mcp23s08 is not set +# CONFIG_PACKAGE_kmod-gpio-nxp-74hc164 is not set +# CONFIG_PACKAGE_kmod-gpio-pca953x is not set +# CONFIG_PACKAGE_kmod-gpio-pcf857x is not set +# CONFIG_PACKAGE_kmod-iio-core is not set +# CONFIG_PACKAGE_kmod-ikconfig is not set +# CONFIG_PACKAGE_kmod-lp is not set +# CONFIG_PACKAGE_kmod-mmc is not set +# CONFIG_PACKAGE_kmod-mtd-rw is not set +# CONFIG_PACKAGE_kmod-mtdtests is not set +# CONFIG_PACKAGE_kmod-pps is not set +# CONFIG_PACKAGE_kmod-pps-gpio is not set +# CONFIG_PACKAGE_kmod-pps-ldisc is not set +# CONFIG_PACKAGE_kmod-ptp is not set +# CONFIG_PACKAGE_kmod-random-core is not set +# CONFIG_PACKAGE_kmod-regmap is not set +# CONFIG_PACKAGE_kmod-rotary-gpio-custom is not set +# CONFIG_PACKAGE_kmod-rtc-ds1307 is not set +# CONFIG_PACKAGE_kmod-rtc-ds1374 is not set +# CONFIG_PACKAGE_kmod-rtc-ds1672 is not set +# CONFIG_PACKAGE_kmod-rtc-isl1208 is not set +# CONFIG_PACKAGE_kmod-rtc-pcf2123 is not set +# CONFIG_PACKAGE_kmod-rtc-pcf8563 is not set +# CONFIG_PACKAGE_kmod-rtc-pt7c4338 is not set +# CONFIG_PACKAGE_kmod-rtc-rs5c372a is not set +# CONFIG_PACKAGE_kmod-sdhci is not set +# CONFIG_PACKAGE_kmod-serial-8250 is not set +# CONFIG_PACKAGE_kmod-softdog is not set +# CONFIG_PACKAGE_kmod-ssb is not set +# CONFIG_PACKAGE_kmod-tpm is not set +# CONFIG_PACKAGE_kmod-tpm-i2c-atmel is not set +# CONFIG_PACKAGE_kmod-tpm-i2c-infineon is not set +# CONFIG_PACKAGE_kmod-w83627hf-wdt is not set +# CONFIG_PACKAGE_kmod-zram is not set + +# +# PCMCIA support +# + +# +# SPI Support +# +# CONFIG_PACKAGE_kmod-mmc-spi is not set +# CONFIG_PACKAGE_kmod-spi-bitbang is not set +# CONFIG_PACKAGE_kmod-spi-dev is not set +# CONFIG_PACKAGE_kmod-spi-gpio is not set +# CONFIG_PACKAGE_kmod-spi-gpio-custom is not set +# CONFIG_PACKAGE_kmod-spi-gpio-old is not set +# CONFIG_PACKAGE_kmod-spi-vsc7385 is not set + +# +# Sound Support +# +# CONFIG_PACKAGE_kmod-sound-core is not set + +# +# USB Support +# +# CONFIG_PACKAGE_kmod-usb-acm is not set +# CONFIG_PACKAGE_kmod-usb-atm is not set +# CONFIG_PACKAGE_kmod-usb-chipidea is not set +# CONFIG_PACKAGE_kmod-usb-cm109 is not set +CONFIG_PACKAGE_kmod-usb-core=y +# CONFIG_PACKAGE_kmod-usb-dwc2 is not set +# CONFIG_PACKAGE_kmod-usb-dwc3 is not set +# CONFIG_PACKAGE_kmod-usb-dwc3-of-simple is not set +CONFIG_PACKAGE_kmod-usb-ehci=y +# CONFIG_PACKAGE_kmod-usb-gadget-ehci-debug is not set +# CONFIG_PACKAGE_kmod-usb-gadget-eth is not set +# CONFIG_PACKAGE_kmod-usb-gadget-mass-storage is not set +# CONFIG_PACKAGE_kmod-usb-gadget-serial is not set +# CONFIG_PACKAGE_kmod-usb-hid is not set +CONFIG_PACKAGE_kmod-usb-ledtrig-usbport=y +# CONFIG_PACKAGE_kmod-usb-net is not set +# CONFIG_PACKAGE_kmod-usb-net2280 is not set +CONFIG_PACKAGE_kmod-usb-ohci=y +# CONFIG_PACKAGE_kmod-usb-ohci-pci is not set +# CONFIG_PACKAGE_kmod-usb-phy-qcom-ipq4019 is not set +CONFIG_PACKAGE_kmod-usb-printer=y +# CONFIG_PACKAGE_kmod-usb-serial is not set +CONFIG_PACKAGE_kmod-usb-storage=y +CONFIG_PACKAGE_kmod-usb-storage-extras=y +# CONFIG_PACKAGE_kmod-usb-uhci is not set +# CONFIG_PACKAGE_kmod-usb-wdm is not set +# CONFIG_PACKAGE_kmod-usb-yealink is not set +CONFIG_PACKAGE_kmod-usb2=y +# CONFIG_PACKAGE_kmod-usb2-pci is not set +# CONFIG_PACKAGE_kmod-usb3 is not set +# CONFIG_PACKAGE_kmod-usbip is not set +# CONFIG_PACKAGE_kmod-usbip-client is not set +# CONFIG_PACKAGE_kmod-usbip-server is not set +# CONFIG_PACKAGE_kmod-usbmon is not set + +# +# Video Support +# +# CONFIG_PACKAGE_kmod-video-core is not set + +# +# Virtualization +# + +# +# Voice over IP +# +# CONFIG_PACKAGE_kmod-dahdi is not set + +# +# W1 support +# +# CONFIG_PACKAGE_kmod-w1 is not set + +# +# WPAN 802.15.4 Support +# +# CONFIG_PACKAGE_kmod-at86rf230 is not set +# CONFIG_PACKAGE_kmod-cc2520 is not set +# CONFIG_PACKAGE_kmod-fakelb is not set +# CONFIG_PACKAGE_kmod-ieee802154 is not set +# CONFIG_PACKAGE_kmod-ieee802154_6lowpan is not set +# CONFIG_PACKAGE_kmod-mac802154 is not set +# CONFIG_PACKAGE_kmod-mrf24j40 is not set + +# +# Wireless Drivers +# +# CONFIG_PACKAGE_kmod-adm8211 is not set +CONFIG_PACKAGE_kmod-ath=y +CONFIG_ATH_USER_REGD=y +# CONFIG_PACKAGE_ATH_DEBUG is not set +CONFIG_PACKAGE_ATH_DFS=y +CONFIG_PACKAGE_kmod-ath10k=y +# CONFIG_PACKAGE_kmod-ath10k-ct is not set +# CONFIG_PACKAGE_kmod-ath5k is not set +# CONFIG_PACKAGE_kmod-ath6kl-sdio is not set +# CONFIG_PACKAGE_kmod-ath6kl-usb is not set +CONFIG_PACKAGE_kmod-ath9k=y +# CONFIG_ATH9K_SUPPORT_PCOEM is not set +# CONFIG_ATH9K_TX99 is not set +CONFIG_ATH9K_UBNTHSR=y +CONFIG_PACKAGE_kmod-ath9k-common=y +# CONFIG_PACKAGE_kmod-ath9k-htc is not set +# CONFIG_PACKAGE_kmod-b43 is not set +# CONFIG_PACKAGE_kmod-b43legacy is not set +# CONFIG_PACKAGE_kmod-brcmfmac is not set +# CONFIG_PACKAGE_kmod-brcmsmac is not set +# CONFIG_PACKAGE_kmod-brcmutil is not set +# CONFIG_PACKAGE_kmod-carl9170 is not set +CONFIG_PACKAGE_kmod-cfg80211=y +# CONFIG_PACKAGE_kmod-hermes is not set +# CONFIG_PACKAGE_kmod-hermes-pci is not set +# CONFIG_PACKAGE_kmod-hermes-plx is not set +# CONFIG_PACKAGE_kmod-iwl-legacy is not set +# CONFIG_PACKAGE_kmod-iwl3945 is not set +# CONFIG_PACKAGE_kmod-iwl4965 is not set +# CONFIG_PACKAGE_kmod-iwlwifi is not set +# CONFIG_PACKAGE_kmod-lib80211 is not set +# CONFIG_PACKAGE_kmod-libertas-sdio is not set +# CONFIG_PACKAGE_kmod-libertas-spi is not set +# CONFIG_PACKAGE_kmod-libertas-usb is not set +CONFIG_PACKAGE_kmod-mac80211=y +CONFIG_PACKAGE_MAC80211_DEBUGFS=y +# CONFIG_PACKAGE_MAC80211_TRACING is not set +CONFIG_PACKAGE_MAC80211_MESH=y +# CONFIG_PACKAGE_kmod-mac80211-hwsim is not set +# CONFIG_PACKAGE_kmod-mt76 is not set +# CONFIG_PACKAGE_kmod-mt76-core is not set +# CONFIG_PACKAGE_kmod-mt7601u is not set +# CONFIG_PACKAGE_kmod-mt7603 is not set +# CONFIG_PACKAGE_kmod-mt76x2 is not set +# CONFIG_PACKAGE_kmod-mwifiex-pcie is not set +# CONFIG_PACKAGE_kmod-mwifiex-sdio is not set +# CONFIG_PACKAGE_kmod-mwl8k is not set +# CONFIG_PACKAGE_kmod-net-prism54 is not set +# CONFIG_PACKAGE_kmod-net-rtl8192su is not set +# CONFIG_PACKAGE_kmod-owl-loader is not set +# CONFIG_PACKAGE_kmod-p54-common is not set +# CONFIG_PACKAGE_kmod-p54-pci is not set +# CONFIG_PACKAGE_kmod-p54-usb is not set +# CONFIG_PACKAGE_kmod-rt2400-pci is not set +# CONFIG_PACKAGE_kmod-rt2500-pci is not set +# CONFIG_PACKAGE_kmod-rt2500-usb is not set +# CONFIG_PACKAGE_kmod-rt2800-pci is not set +# CONFIG_PACKAGE_kmod-rt2800-usb is not set +# CONFIG_PACKAGE_kmod-rt2x00-lib is not set +# CONFIG_PACKAGE_kmod-rt61-pci is not set +# CONFIG_PACKAGE_kmod-rt73-usb is not set +# CONFIG_PACKAGE_kmod-rtl8180 is not set +# CONFIG_PACKAGE_kmod-rtl8187 is not set +# CONFIG_PACKAGE_kmod-rtl8192ce is not set +# CONFIG_PACKAGE_kmod-rtl8192cu is not set +# CONFIG_PACKAGE_kmod-rtl8192de is not set +# CONFIG_PACKAGE_kmod-rtl8192se is not set +# CONFIG_PACKAGE_kmod-rtl8821ae is not set +# CONFIG_PACKAGE_kmod-rtl8xxxu is not set +# CONFIG_PACKAGE_kmod-wl12xx is not set +# CONFIG_PACKAGE_kmod-wl18xx is not set +# CONFIG_PACKAGE_kmod-wlcore is not set +# CONFIG_PACKAGE_kmod-zd1211rw is not set + +# +# Languages +# + +# +# Erlang +# +# CONFIG_PACKAGE_erlang is not set +# CONFIG_PACKAGE_erlang-asn1 is not set +# CONFIG_PACKAGE_erlang-compiler is not set +# CONFIG_PACKAGE_erlang-crypto is not set +# CONFIG_PACKAGE_erlang-hipe is not set +# CONFIG_PACKAGE_erlang-inets is not set +# CONFIG_PACKAGE_erlang-mnesia is not set +# CONFIG_PACKAGE_erlang-runtime-tools is not set +# CONFIG_PACKAGE_erlang-snmp is not set +# CONFIG_PACKAGE_erlang-ssh is not set +# CONFIG_PACKAGE_erlang-ssl is not set +# CONFIG_PACKAGE_erlang-syntax-tools is not set + +# +# Java +# +# CONFIG_PACKAGE_jamvm is not set + +# +# Lua +# +# CONFIG_PACKAGE_dkjson is not set +# CONFIG_PACKAGE_json4lua is not set +CONFIG_PACKAGE_libiwinfo-lua=y +# CONFIG_PACKAGE_lpeg is not set +# CONFIG_PACKAGE_lsqlite3 is not set +CONFIG_PACKAGE_lua=y +# CONFIG_PACKAGE_lua-bencode is not set +# CONFIG_PACKAGE_lua-cjson is not set +# CONFIG_PACKAGE_lua-copas is not set +# CONFIG_PACKAGE_lua-coxpcall is not set +# CONFIG_PACKAGE_lua-examples is not set +# CONFIG_PACKAGE_lua-lzlib is not set +# CONFIG_PACKAGE_lua-md5 is not set +# CONFIG_PACKAGE_lua-mobdebug is not set +# CONFIG_PACKAGE_lua-mosquitto is not set +# CONFIG_PACKAGE_lua-openssl is not set +# CONFIG_PACKAGE_lua-penlight is not set +# CONFIG_PACKAGE_lua-rings is not set +# CONFIG_PACKAGE_lua-rs232 is not set +# CONFIG_PACKAGE_lua-sha2 is not set +# CONFIG_PACKAGE_lua-wsapi-base is not set +# CONFIG_PACKAGE_lua-wsapi-xavante is not set +# CONFIG_PACKAGE_lua-xavante is not set +# CONFIG_PACKAGE_luabitop is not set +# CONFIG_PACKAGE_luac is not set +# CONFIG_PACKAGE_luaexpat is not set +# CONFIG_PACKAGE_luafilesystem is not set +# CONFIG_PACKAGE_luai2c is not set +# CONFIG_PACKAGE_luajit is not set +# CONFIG_PACKAGE_lualanes is not set +# CONFIG_PACKAGE_luaposix is not set +# CONFIG_PACKAGE_luarocks is not set +# CONFIG_PACKAGE_luasec is not set +# CONFIG_PACKAGE_luasoap is not set +# CONFIG_PACKAGE_luasocket is not set +# CONFIG_PACKAGE_luasql-mysql is not set +# CONFIG_PACKAGE_luasql-pgsql is not set +# CONFIG_PACKAGE_luasql-sqlite3 is not set +CONFIG_PACKAGE_luci-lib-fs=y +# CONFIG_PACKAGE_luv is not set +# CONFIG_PACKAGE_lzmq is not set +# CONFIG_PACKAGE_uuid is not set + +# +# Node.js +# +# CONFIG_PACKAGE_node is not set + +# +# Module Selection +# +# CONFIG_NODEJS_ICU is not set +# CONFIG_PACKAGE_node-arduino-firmata is not set +# CONFIG_PACKAGE_node-cylon is not set +# CONFIG_PACKAGE_node-cylon-firmata is not set +# CONFIG_PACKAGE_node-cylon-gpio is not set +# CONFIG_PACKAGE_node-cylon-i2c is not set +# CONFIG_PACKAGE_node-hid is not set +# CONFIG_PACKAGE_node-npm is not set +# CONFIG_PACKAGE_node-serialport is not set + +# +# PHP +# +# CONFIG_PACKAGE_php7 is not set + +# +# Perl +# +# CONFIG_PACKAGE_perl is not set + +# +# Python +# +# CONFIG_PACKAGE_chardet is not set +# CONFIG_PACKAGE_django is not set +# CONFIG_PACKAGE_django-appconf is not set +# CONFIG_PACKAGE_django-compressor is not set +# CONFIG_PACKAGE_django-constance is not set +# CONFIG_PACKAGE_django-jsonfield is not set +# CONFIG_PACKAGE_django-picklefield is not set +# CONFIG_PACKAGE_django-postoffice is not set +# CONFIG_PACKAGE_django-restframework is not set +# CONFIG_PACKAGE_django-statici18n is not set +# CONFIG_PACKAGE_et_xmlfile is not set +# CONFIG_PACKAGE_flup is not set +# CONFIG_PACKAGE_gunicorn is not set +# CONFIG_PACKAGE_jdcal is not set +# CONFIG_PACKAGE_micropython is not set +# CONFIG_PACKAGE_micropython-lib is not set +# CONFIG_PACKAGE_openpyxl is not set +# CONFIG_PACKAGE_pillow is not set +# CONFIG_PACKAGE_python is not set +# CONFIG_PACKAGE_python-asn1crypto is not set +# CONFIG_PACKAGE_python-attrs is not set +# CONFIG_PACKAGE_python-base is not set +# CONFIG_PACKAGE_python-base-src is not set +# CONFIG_PACKAGE_python-cffi is not set +# CONFIG_PACKAGE_python-codecs is not set +# CONFIG_PACKAGE_python-codecs-src is not set +# CONFIG_PACKAGE_python-compiler is not set +# CONFIG_PACKAGE_python-compiler-src is not set +# CONFIG_PACKAGE_python-crcmod is not set +# CONFIG_PACKAGE_python-crypto is not set +# CONFIG_PACKAGE_python-cryptography is not set +# CONFIG_PACKAGE_python-ctypes is not set +# CONFIG_PACKAGE_python-ctypes-src is not set +# CONFIG_PACKAGE_python-curl is not set +# CONFIG_PACKAGE_python-dateutil is not set +# CONFIG_PACKAGE_python-db is not set +# CONFIG_PACKAGE_python-db-src is not set +# CONFIG_PACKAGE_python-decimal is not set +# CONFIG_PACKAGE_python-decimal-src is not set +# CONFIG_PACKAGE_python-dev is not set +# CONFIG_PACKAGE_python-dev-src is not set +# CONFIG_PACKAGE_python-distutils is not set +# CONFIG_PACKAGE_python-distutils-src is not set +# CONFIG_PACKAGE_python-dns is not set +# CONFIG_PACKAGE_python-dpkt is not set +# CONFIG_PACKAGE_python-egenix-mx-base is not set +# CONFIG_PACKAGE_python-email is not set +# CONFIG_PACKAGE_python-email-src is not set +# CONFIG_PACKAGE_python-enum34 is not set +# CONFIG_PACKAGE_python-evdev is not set +# CONFIG_PACKAGE_python-gdbm is not set +# CONFIG_PACKAGE_python-gdbm-src is not set +# CONFIG_PACKAGE_python-gmpy2 is not set +# CONFIG_PACKAGE_python-gnupg is not set +# CONFIG_PACKAGE_python-idna is not set +# CONFIG_PACKAGE_python-ipaddress is not set +# CONFIG_PACKAGE_python-ldap is not set +# CONFIG_PACKAGE_python-lib2to3 is not set +# CONFIG_PACKAGE_python-lib2to3-src is not set +# CONFIG_PACKAGE_python-light is not set +# CONFIG_PACKAGE_python-light-src is not set +# CONFIG_PACKAGE_python-logging is not set +# CONFIG_PACKAGE_python-logging-src is not set +# CONFIG_PACKAGE_python-lxml is not set +# CONFIG_PACKAGE_python-multiprocessing is not set +# CONFIG_PACKAGE_python-multiprocessing-src is not set +# CONFIG_PACKAGE_python-mysql is not set +# CONFIG_PACKAGE_python-ncurses is not set +# CONFIG_PACKAGE_python-ncurses-src is not set +# CONFIG_PACKAGE_python-openssl is not set +# CONFIG_PACKAGE_python-openssl-src is not set +# CONFIG_PACKAGE_python-parsley is not set +# CONFIG_PACKAGE_python-pcapy is not set +# CONFIG_PACKAGE_python-pip is not set +# CONFIG_PACKAGE_python-pip-conf is not set +# CONFIG_PACKAGE_python-pip-src is not set +# CONFIG_PACKAGE_python-ply is not set +# CONFIG_PACKAGE_python-psycopg2 is not set +# CONFIG_PACKAGE_python-pyasn1 is not set +# CONFIG_PACKAGE_python-pyasn1-modules is not set +# CONFIG_PACKAGE_python-pycparser is not set +# CONFIG_PACKAGE_python-pydoc is not set +# CONFIG_PACKAGE_python-pydoc-src is not set +# CONFIG_PACKAGE_python-pyodbc is not set +# CONFIG_PACKAGE_python-pyopenssl is not set +# CONFIG_PACKAGE_python-pyptlib is not set +# CONFIG_PACKAGE_python-pyserial is not set +# CONFIG_PACKAGE_python-service-identity is not set +# CONFIG_PACKAGE_python-setuptools is not set +# CONFIG_PACKAGE_python-setuptools-src is not set +# CONFIG_PACKAGE_python-six is not set +# CONFIG_PACKAGE_python-smbus is not set +# CONFIG_PACKAGE_python-sqlite3 is not set +# CONFIG_PACKAGE_python-sqlite3-src is not set +# CONFIG_PACKAGE_python-src is not set +# CONFIG_PACKAGE_python-txsocksx is not set +# CONFIG_PACKAGE_python-unittest is not set +# CONFIG_PACKAGE_python-unittest-src is not set +# CONFIG_PACKAGE_python-urllib3 is not set +# CONFIG_PACKAGE_python-xml is not set +# CONFIG_PACKAGE_python-xml-src is not set +# CONFIG_PACKAGE_python-yaml is not set +# CONFIG_PACKAGE_python3 is not set +# CONFIG_PACKAGE_python3-asn1crypto is not set +# CONFIG_PACKAGE_python3-asyncio is not set +# CONFIG_PACKAGE_python3-asyncio-src is not set +# CONFIG_PACKAGE_python3-base is not set +# CONFIG_PACKAGE_python3-base-src is not set +# CONFIG_PACKAGE_python3-bottle is not set +# CONFIG_PACKAGE_python3-cffi is not set +# CONFIG_PACKAGE_python3-click is not set +# CONFIG_PACKAGE_python3-codecs is not set +# CONFIG_PACKAGE_python3-codecs-src is not set +# CONFIG_PACKAGE_python3-cryptography is not set +# CONFIG_PACKAGE_python3-ctypes is not set +# CONFIG_PACKAGE_python3-ctypes-src is not set +# CONFIG_PACKAGE_python3-dbm is not set +# CONFIG_PACKAGE_python3-dbm-src is not set +# CONFIG_PACKAGE_python3-decimal is not set +# CONFIG_PACKAGE_python3-decimal-src is not set +# CONFIG_PACKAGE_python3-dev is not set +# CONFIG_PACKAGE_python3-dev-src is not set +# CONFIG_PACKAGE_python3-distutils is not set +# CONFIG_PACKAGE_python3-distutils-src is not set +# CONFIG_PACKAGE_python3-email is not set +# CONFIG_PACKAGE_python3-email-src is not set +# CONFIG_PACKAGE_python3-evdev is not set +# CONFIG_PACKAGE_python3-flask is not set +# CONFIG_PACKAGE_python3-gdbm is not set +# CONFIG_PACKAGE_python3-gdbm-src is not set +# CONFIG_PACKAGE_python3-gnupg is not set +# CONFIG_PACKAGE_python3-idna is not set +# CONFIG_PACKAGE_python3-itsdangerous is not set +# CONFIG_PACKAGE_python3-jinja2 is not set +# CONFIG_PACKAGE_python3-lib2to3 is not set +# CONFIG_PACKAGE_python3-lib2to3-src is not set +# CONFIG_PACKAGE_python3-light is not set +# CONFIG_PACKAGE_python3-light-src is not set +# CONFIG_PACKAGE_python3-logging is not set +# CONFIG_PACKAGE_python3-logging-src is not set +# CONFIG_PACKAGE_python3-lxml is not set +# CONFIG_PACKAGE_python3-lzma is not set +# CONFIG_PACKAGE_python3-lzma-src is not set +# CONFIG_PACKAGE_python3-markupsafe is not set +# CONFIG_PACKAGE_python3-multiprocessing is not set +# CONFIG_PACKAGE_python3-multiprocessing-src is not set +# CONFIG_PACKAGE_python3-ncurses is not set +# CONFIG_PACKAGE_python3-ncurses-src is not set +# CONFIG_PACKAGE_python3-openssl is not set +# CONFIG_PACKAGE_python3-openssl-src is not set +# CONFIG_PACKAGE_python3-pip is not set +# CONFIG_PACKAGE_python3-pip-src is not set +# CONFIG_PACKAGE_python3-ply is not set +# CONFIG_PACKAGE_python3-pyasn1 is not set +# CONFIG_PACKAGE_python3-pyasn1-modules is not set +# CONFIG_PACKAGE_python3-pycparser is not set +# CONFIG_PACKAGE_python3-pydoc is not set +# CONFIG_PACKAGE_python3-pydoc-src is not set +# CONFIG_PACKAGE_python3-pyodbc is not set +# CONFIG_PACKAGE_python3-pyopenssl is not set +# CONFIG_PACKAGE_python3-setuptools is not set +# CONFIG_PACKAGE_python3-setuptools-src is not set +# CONFIG_PACKAGE_python3-six is not set +# CONFIG_PACKAGE_python3-smbus is not set +# CONFIG_PACKAGE_python3-sqlite3 is not set +# CONFIG_PACKAGE_python3-sqlite3-src is not set +# CONFIG_PACKAGE_python3-src is not set +# CONFIG_PACKAGE_python3-unittest is not set +# CONFIG_PACKAGE_python3-unittest-src is not set +# CONFIG_PACKAGE_python3-werkzeug is not set +# CONFIG_PACKAGE_python3-xml is not set +# CONFIG_PACKAGE_python3-xml-src is not set +# CONFIG_PACKAGE_python3-yaml is not set +# CONFIG_PACKAGE_pytz is not set +# CONFIG_PACKAGE_rcssmin is not set +# CONFIG_PACKAGE_simplejson is not set +# CONFIG_PACKAGE_twisted is not set +# CONFIG_PACKAGE_zope-interface is not set + +# +# Ruby +# +# CONFIG_PACKAGE_ruby is not set + +# +# Tcl +# +# CONFIG_PACKAGE_vala is not set + +# +# Libraries +# + +# +# Compression +# +# CONFIG_PACKAGE_libbz2 is not set +# CONFIG_PACKAGE_liblzma is not set +# CONFIG_PACKAGE_libunrar is not set + +# +# Filesystem +# +# CONFIG_PACKAGE_libacl is not set +# CONFIG_PACKAGE_libattr is not set +# CONFIG_PACKAGE_libext2fs is not set +# CONFIG_PACKAGE_libfuse is not set +# CONFIG_PACKAGE_libow is not set +# CONFIG_PACKAGE_libow-capi is not set +# CONFIG_PACKAGE_libsysfs is not set + +# +# Firewall +# +# CONFIG_PACKAGE_libfko is not set +CONFIG_PACKAGE_libip4tc=y +CONFIG_PACKAGE_libip6tc=y +# CONFIG_PACKAGE_libiptc is not set +CONFIG_PACKAGE_libxtables=y + +# +# Instant Messaging +# +# CONFIG_PACKAGE_quasselc is not set + +# +# IoT +# +# CONFIG_PACKAGE_libupm is not set +# CONFIG_PACKAGE_libupm-a110x is not set +# CONFIG_PACKAGE_libupm-ad8232 is not set +# CONFIG_PACKAGE_libupm-adafruitss is not set +# CONFIG_PACKAGE_libupm-adc121c021 is not set +# CONFIG_PACKAGE_libupm-adis16448 is not set +# CONFIG_PACKAGE_libupm-adxl335 is not set +# CONFIG_PACKAGE_libupm-adxl345 is not set +# CONFIG_PACKAGE_libupm-am2315 is not set +# CONFIG_PACKAGE_libupm-apds9002 is not set +# CONFIG_PACKAGE_libupm-at42qt1070 is not set +# CONFIG_PACKAGE_libupm-biss0001 is not set +# CONFIG_PACKAGE_libupm-bmpx8x is not set +# CONFIG_PACKAGE_libupm-buzzer is not set +# CONFIG_PACKAGE_libupm-cjq4435 is not set +# CONFIG_PACKAGE_libupm-ds1307 is not set +# CONFIG_PACKAGE_libupm-ecs1030 is not set +# CONFIG_PACKAGE_libupm-enc03r is not set +# CONFIG_PACKAGE_libupm-flex is not set +# CONFIG_PACKAGE_libupm-gas is not set +# CONFIG_PACKAGE_libupm-gp2y0a is not set +# CONFIG_PACKAGE_libupm-grove is not set +# CONFIG_PACKAGE_libupm-grovecircularled is not set +# CONFIG_PACKAGE_libupm-grovecollision is not set +# CONFIG_PACKAGE_libupm-groveehr is not set +# CONFIG_PACKAGE_libupm-groveeldriver is not set +# CONFIG_PACKAGE_libupm-groveelectromagnet is not set +# CONFIG_PACKAGE_libupm-groveemg is not set +# CONFIG_PACKAGE_libupm-grovegprs is not set +# CONFIG_PACKAGE_libupm-grovegsr is not set +# CONFIG_PACKAGE_libupm-grovelinefinder is not set +# CONFIG_PACKAGE_libupm-grovemd is not set +# CONFIG_PACKAGE_libupm-grovemoisture is not set +# CONFIG_PACKAGE_libupm-groveo2 is not set +# CONFIG_PACKAGE_libupm-grovescam is not set +# CONFIG_PACKAGE_libupm-grovespeaker is not set +# CONFIG_PACKAGE_libupm-grovevdiv is not set +# CONFIG_PACKAGE_libupm-grovewater is not set +# CONFIG_PACKAGE_libupm-grovewfs is not set +# CONFIG_PACKAGE_libupm-guvas12d is not set +# CONFIG_PACKAGE_libupm-h3lis331dl is not set +# CONFIG_PACKAGE_libupm-hcsr04 is not set +# CONFIG_PACKAGE_libupm-hm11 is not set +# CONFIG_PACKAGE_libupm-hmc5883l is not set +# CONFIG_PACKAGE_libupm-hmtrp is not set +# CONFIG_PACKAGE_libupm-hp20x is not set +# CONFIG_PACKAGE_libupm-ht9170 is not set +# CONFIG_PACKAGE_libupm-htu21d is not set +# CONFIG_PACKAGE_libupm-hx711 is not set +# CONFIG_PACKAGE_libupm-i2clcd is not set +# CONFIG_PACKAGE_libupm-ina132 is not set +# CONFIG_PACKAGE_libupm-isd1820 is not set +# CONFIG_PACKAGE_libupm-itg3200 is not set +# CONFIG_PACKAGE_libupm-joystick12 is not set +# CONFIG_PACKAGE_libupm-l298 is not set +# CONFIG_PACKAGE_libupm-ldt0028 is not set +# CONFIG_PACKAGE_libupm-lm35 is not set +# CONFIG_PACKAGE_libupm-lol is not set +# CONFIG_PACKAGE_libupm-loudness is not set +# CONFIG_PACKAGE_libupm-lpd8806 is not set +# CONFIG_PACKAGE_libupm-lsm303 is not set +# CONFIG_PACKAGE_libupm-lsm9ds0 is not set +# CONFIG_PACKAGE_libupm-m24lr64e is not set +# CONFIG_PACKAGE_libupm-max31723 is not set +# CONFIG_PACKAGE_libupm-max31855 is not set +# CONFIG_PACKAGE_libupm-max44000 is not set +# CONFIG_PACKAGE_libupm-max5487 is not set +# CONFIG_PACKAGE_libupm-maxds3231m is not set +# CONFIG_PACKAGE_libupm-maxsonarez is not set +# CONFIG_PACKAGE_libupm-mg811 is not set +# CONFIG_PACKAGE_libupm-mhz16 is not set +# CONFIG_PACKAGE_libupm-mic is not set +# CONFIG_PACKAGE_libupm-mlx90614 is not set +# CONFIG_PACKAGE_libupm-mma7455 is not set +# CONFIG_PACKAGE_libupm-mma7660 is not set +# CONFIG_PACKAGE_libupm-mpl3115a2 is not set +# CONFIG_PACKAGE_libupm-mpr121 is not set +# CONFIG_PACKAGE_libupm-mpu9150 is not set +# CONFIG_PACKAGE_libupm-mq303a is not set +# CONFIG_PACKAGE_libupm-my9221 is not set +# CONFIG_PACKAGE_libupm-nrf24l01 is not set +# CONFIG_PACKAGE_libupm-nrf8001 is not set +# CONFIG_PACKAGE_libupm-nunchuck is not set +# CONFIG_PACKAGE_libupm-otp538u is not set +# CONFIG_PACKAGE_libupm-pn532 is not set +# CONFIG_PACKAGE_libupm-ppd42ns is not set +# CONFIG_PACKAGE_libupm-pulsensor is not set +# CONFIG_PACKAGE_libupm-rfr359f is not set +# CONFIG_PACKAGE_libupm-rgbringcoder is not set +# CONFIG_PACKAGE_libupm-rotaryencoder is not set +# CONFIG_PACKAGE_libupm-rpr220 is not set +# CONFIG_PACKAGE_libupm-servo is not set +# CONFIG_PACKAGE_libupm-si114x is not set +# CONFIG_PACKAGE_libupm-sm130 is not set +# CONFIG_PACKAGE_libupm-st7735 is not set +# CONFIG_PACKAGE_libupm-stepmotor is not set +# CONFIG_PACKAGE_libupm-sx6119 is not set +# CONFIG_PACKAGE_libupm-ta12200 is not set +# CONFIG_PACKAGE_libupm-tcs3414cs is not set +# CONFIG_PACKAGE_libupm-th02 is not set +# CONFIG_PACKAGE_libupm-tm1637 is not set +# CONFIG_PACKAGE_libupm-tsl2561 is not set +# CONFIG_PACKAGE_libupm-ttp223 is not set +# CONFIG_PACKAGE_libupm-ublox6 is not set +# CONFIG_PACKAGE_libupm-uln200xa is not set +# CONFIG_PACKAGE_libupm-waterlevel is not set +# CONFIG_PACKAGE_libupm-wheelencoder is not set +# CONFIG_PACKAGE_libupm-wt5001 is not set +# CONFIG_PACKAGE_libupm-yg1006 is not set +# CONFIG_PACKAGE_libupm-zfm20 is not set + +# +# Languages +# +# CONFIG_PACKAGE_libyaml is not set + +# +# Networking +# +# CONFIG_PACKAGE_libsctp is not set + +# +# SSL +# +# CONFIG_PACKAGE_libcyassl is not set +# CONFIG_PACKAGE_libgnutls is not set +# CONFIG_PACKAGE_libmbedtls is not set +CONFIG_PACKAGE_libopenssl=y +CONFIG_OPENSSL_WITH_EC=y +# CONFIG_OPENSSL_WITH_EC2M is not set +# CONFIG_OPENSSL_WITH_SSL3 is not set +CONFIG_OPENSSL_WITH_DEPRECATED=y +# CONFIG_OPENSSL_WITH_DTLS is not set +# CONFIG_OPENSSL_WITH_COMPRESSION is not set +CONFIG_OPENSSL_WITH_NPN=y +CONFIG_OPENSSL_WITH_PSK=y +CONFIG_OPENSSL_WITH_SRP=y +CONFIG_OPENSSL_THREADS=y +# CONFIG_OPENSSL_HARDWARE_SUPPORT is not set +# CONFIG_OPENSSL_ENGINE_CRYPTO is not set + +# +# Sound +# +# CONFIG_PACKAGE_liblo is not set + +# +# Telephony +# +# CONFIG_PACKAGE_bcg729 is not set +# CONFIG_PACKAGE_dahdi-tools-libtonezone is not set +# CONFIG_PACKAGE_libiksemel is not set +# CONFIG_PACKAGE_libortp is not set +# CONFIG_PACKAGE_libosip2 is not set +# CONFIG_PACKAGE_libpj is not set +# CONFIG_PACKAGE_libpjlib-util is not set +# CONFIG_PACKAGE_libpjmedia is not set +# CONFIG_PACKAGE_libpjnath is not set +# CONFIG_PACKAGE_libpjsip is not set +# CONFIG_PACKAGE_libpjsip-simple is not set +# CONFIG_PACKAGE_libpjsip-ua is not set +# CONFIG_PACKAGE_libpjsua is not set +# CONFIG_PACKAGE_libpjsua2 is not set +# CONFIG_PACKAGE_libre is not set +# CONFIG_PACKAGE_librem is not set +# CONFIG_PACKAGE_libspandsp is not set +# CONFIG_PACKAGE_libsrtp is not set +# CONFIG_PACKAGE_libsrtp2 is not set + +# +# database +# +# CONFIG_PACKAGE_libpq is not set +# CONFIG_PACKAGE_libsqlite3 is not set +# CONFIG_PACKAGE_pgsqlodbc is not set +# CONFIG_PACKAGE_psqlodbca is not set +# CONFIG_PACKAGE_psqlodbcw is not set +# CONFIG_PACKAGE_tdb is not set +# CONFIG_PACKAGE_unixodbc is not set + +# +# libelektra +# +# CONFIG_PACKAGE_libelektra-boost is not set +# CONFIG_PACKAGE_libelektra-core is not set +# CONFIG_PACKAGE_libelektra-cpp is not set +# CONFIG_PACKAGE_libelektra-crypto is not set +# CONFIG_PACKAGE_libelektra-curlget is not set +# CONFIG_PACKAGE_libelektra-dbus is not set +# CONFIG_PACKAGE_libelektra-extra is not set +# CONFIG_PACKAGE_libelektra-lua is not set +# CONFIG_PACKAGE_libelektra-plugins is not set +# CONFIG_PACKAGE_libelektra-python2 is not set +# CONFIG_PACKAGE_libelektra-python3 is not set +# CONFIG_PACKAGE_libelektra-resolvers is not set +# CONFIG_PACKAGE_libelektra-xml is not set +# CONFIG_PACKAGE_libelektra-yajl is not set +# CONFIG_PACKAGE_alsa-lib is not set +# CONFIG_PACKAGE_argp-standalone is not set +# CONFIG_PACKAGE_avro-c is not set +# CONFIG_PACKAGE_bind-libs is not set +# CONFIG_PACKAGE_bluez-libs is not set +# CONFIG_PACKAGE_boost is not set +# CONFIG_PACKAGE_ccid is not set +# CONFIG_PACKAGE_check is not set +# CONFIG_PACKAGE_classpath is not set +# CONFIG_PACKAGE_classpath-tools is not set +# CONFIG_PACKAGE_confuse is not set +# CONFIG_PACKAGE_dtndht is not set +# CONFIG_PACKAGE_fcgi is not set +# CONFIG_PACKAGE_fftw3 is not set +# CONFIG_PACKAGE_fftw3f is not set +# CONFIG_PACKAGE_giflib is not set +# CONFIG_PACKAGE_glib2 is not set +# CONFIG_PACKAGE_glog is not set +# CONFIG_PACKAGE_hidapi is not set +# CONFIG_PACKAGE_ibrcommon is not set +# CONFIG_PACKAGE_ibrdtn is not set +# CONFIG_PACKAGE_icu is not set +# CONFIG_PACKAGE_jansson is not set +# CONFIG_PACKAGE_knot-libdnssec is not set +# CONFIG_PACKAGE_knot-libknot is not set +# CONFIG_PACKAGE_knot-libzscanner is not set +# CONFIG_PACKAGE_libaio is not set +# CONFIG_PACKAGE_libantlr3c is not set +# CONFIG_PACKAGE_libao is not set +# CONFIG_PACKAGE_libapr is not set +# CONFIG_PACKAGE_libaprutil is not set +# CONFIG_PACKAGE_libarchive is not set +# CONFIG_PACKAGE_libarchive-noopenssl is not set +# CONFIG_PACKAGE_libartnet is not set +# CONFIG_PACKAGE_libaudiofile is not set +# CONFIG_PACKAGE_libavahi-client is not set +# CONFIG_PACKAGE_libavahi-compat-libdnssd is not set +# CONFIG_PACKAGE_libavahi-dbus-support is not set +# CONFIG_PACKAGE_libavahi-nodbus-support is not set +# CONFIG_PACKAGE_libavl is not set +# CONFIG_PACKAGE_libbfd is not set +# CONFIG_PACKAGE_libblkid is not set +CONFIG_PACKAGE_libblobmsg-json=y +# CONFIG_PACKAGE_libcanfestival is not set +# CONFIG_PACKAGE_libcap is not set +CONFIG_PACKAGE_libcares=y +# CONFIG_PACKAGE_libcharset is not set +# CONFIG_PACKAGE_libcoap is not set +# CONFIG_PACKAGE_libconfig is not set +# CONFIG_PACKAGE_libcryptopp is not set +# CONFIG_PACKAGE_libcurl is not set +# CONFIG_PACKAGE_libdaemon is not set +# CONFIG_PACKAGE_libdaq is not set +# CONFIG_PACKAGE_libdb47 is not set +# CONFIG_PACKAGE_libdb47xx is not set +# CONFIG_PACKAGE_libdbi is not set +# CONFIG_PACKAGE_libdbus is not set +# CONFIG_PACKAGE_libdevmapper is not set +# CONFIG_PACKAGE_libdmapsharing is not set +# CONFIG_PACKAGE_libdnet is not set +# CONFIG_PACKAGE_libdouble-conversion is not set +# CONFIG_PACKAGE_libdrm is not set +# CONFIG_PACKAGE_libedit is not set +# CONFIG_PACKAGE_libelf1 is not set +# CONFIG_PACKAGE_libecdsautil is not set +# CONFIG_PACKAGE_libesmtp is not set +# CONFIG_PACKAGE_libestr is not set +# CONFIG_PACKAGE_libev is not set +# CONFIG_PACKAGE_libevdev is not set +# CONFIG_PACKAGE_libevent is not set +CONFIG_PACKAGE_libevent2=y +# CONFIG_PACKAGE_libevent2-core is not set +# CONFIG_PACKAGE_libevent2-extra is not set +CONFIG_PACKAGE_libevent2-openssl=y +# CONFIG_PACKAGE_libevent2-pthreads is not set +# CONFIG_PACKAGE_libeventlog is not set +# CONFIG_PACKAGE_libevhtp is not set +# CONFIG_PACKAGE_libexif is not set +# CONFIG_PACKAGE_libexpat is not set +# CONFIG_PACKAGE_libexslt is not set +# CONFIG_PACKAGE_libextractor is not set +# CONFIG_PACKAGE_libf2fs is not set +# CONFIG_PACKAGE_libfaad2 is not set +# CONFIG_PACKAGE_libfastjson is not set +# CONFIG_PACKAGE_libfdisk is not set +# CONFIG_PACKAGE_libfdt is not set +# CONFIG_PACKAGE_libffi is not set +# CONFIG_PACKAGE_libffmpeg-audio-dec is not set +# CONFIG_PACKAGE_libffmpeg-custom is not set +# CONFIG_PACKAGE_libffmpeg-full is not set +# CONFIG_PACKAGE_libffmpeg-mini is not set +# CONFIG_PACKAGE_libflac is not set +# CONFIG_PACKAGE_libfreetype is not set +# CONFIG_PACKAGE_libftdi is not set +# CONFIG_PACKAGE_libftdi1 is not set +# CONFIG_PACKAGE_libgcrypt is not set +# CONFIG_PACKAGE_libgd is not set +# CONFIG_PACKAGE_libgdbm is not set +# CONFIG_PACKAGE_libgee is not set +# CONFIG_PACKAGE_libglpk is not set +CONFIG_PACKAGE_libgmp=y +# CONFIG_PACKAGE_libgnurl is not set +# CONFIG_PACKAGE_libgpg-error is not set +# CONFIG_PACKAGE_libgphoto2 is not set +# CONFIG_PACKAGE_libgps is not set +# CONFIG_PACKAGE_libhamlib is not set +# CONFIG_PACKAGE_libhavege is not set +# CONFIG_PACKAGE_libhiredis is not set +# CONFIG_PACKAGE_libhttp-parser is not set +# CONFIG_PACKAGE_libical is not set +# CONFIG_PACKAGE_libiconv is not set +# CONFIG_PACKAGE_libiconv-full is not set +# CONFIG_PACKAGE_libid3tag is not set +# CONFIG_PACKAGE_libidn is not set +# CONFIG_PACKAGE_libiio is not set +# CONFIG_PACKAGE_libimobiledevice is not set +# CONFIG_PACKAGE_libinput is not set +# CONFIG_PACKAGE_libintl is not set +# CONFIG_PACKAGE_libintl-full is not set +# CONFIG_PACKAGE_libiw is not set +CONFIG_PACKAGE_libiwinfo=y +# CONFIG_PACKAGE_libjpeg is not set +CONFIG_PACKAGE_libjson-c=y +# CONFIG_PACKAGE_libkmod is not set +# CONFIG_PACKAGE_libldns is not set +# CONFIG_PACKAGE_libltdl is not set +CONFIG_PACKAGE_liblua=y +# CONFIG_PACKAGE_liblz4 is not set +# CONFIG_PACKAGE_liblzo is not set +# CONFIG_PACKAGE_libmad is not set +# CONFIG_PACKAGE_libmagic is not set +# CONFIG_PACKAGE_libmcrypt is not set +# CONFIG_PACKAGE_libmicrohttpd is not set +# CONFIG_PACKAGE_libmicrohttpd-no-ssl is not set +# CONFIG_PACKAGE_libminiupnpc is not set +# CONFIG_PACKAGE_libmms is not set +CONFIG_PACKAGE_libmnl=y +# CONFIG_PACKAGE_libmodbus is not set +# CONFIG_PACKAGE_libmosquitto-nossl is not set +CONFIG_PACKAGE_libmosquitto-ssl=y +# CONFIG_PACKAGE_libmosquittopp is not set +# CONFIG_PACKAGE_libmount is not set +# CONFIG_PACKAGE_libmpdclient is not set +# CONFIG_PACKAGE_libmpeg2 is not set +# CONFIG_PACKAGE_libmpg123 is not set +# CONFIG_PACKAGE_libmraa is not set +# CONFIG_PACKAGE_libmysqlclient is not set +# CONFIG_PACKAGE_libmysqlclient-r is not set +# CONFIG_PACKAGE_libnatpmp is not set +# CONFIG_PACKAGE_libncurses is not set +# CONFIG_PACKAGE_libndpi is not set +# CONFIG_PACKAGE_libneon is not set +# CONFIG_PACKAGE_libnet-1.2.x is not set +# CONFIG_PACKAGE_libnetconf2 is not set +# CONFIG_PACKAGE_libnetfilter-acct is not set +CONFIG_PACKAGE_libnetfilter-conntrack=y +# CONFIG_PACKAGE_libnetfilter-cthelper is not set +# CONFIG_PACKAGE_libnetfilter-cttimeout is not set +# CONFIG_PACKAGE_libnetfilter-log is not set +# CONFIG_PACKAGE_libnetfilter-queue is not set +# CONFIG_PACKAGE_libnetsnmp is not set +CONFIG_PACKAGE_libnettle=y + +# +# Configuration +# +# CONFIG_LIBNETTLE_MINI is not set +CONFIG_PACKAGE_libnfnetlink=y +# CONFIG_PACKAGE_libnftnl is not set +# CONFIG_PACKAGE_libnl is not set +# CONFIG_PACKAGE_libnl-core is not set +# CONFIG_PACKAGE_libnl-genl is not set +# CONFIG_PACKAGE_libnl-nf is not set +# CONFIG_PACKAGE_libnl-route is not set +CONFIG_PACKAGE_libnl-tiny=y +# CONFIG_PACKAGE_libnopoll is not set +# CONFIG_PACKAGE_libogg is not set +# CONFIG_PACKAGE_liboil is not set +# CONFIG_PACKAGE_libopcodes is not set +# CONFIG_PACKAGE_libopenldap is not set +# CONFIG_PACKAGE_libopenobex is not set +# CONFIG_PACKAGE_libopensc is not set +# CONFIG_PACKAGE_libopenzwave is not set +# CONFIG_PACKAGE_liboping is not set +# CONFIG_PACKAGE_libopus is not set +# CONFIG_PACKAGE_libout123 is not set +# CONFIG_PACKAGE_libowfat is not set +# CONFIG_PACKAGE_libp11 is not set +# CONFIG_PACKAGE_libpam is not set +# CONFIG_PACKAGE_libpcap is not set +CONFIG_PACKAGE_libpcre=y +# CONFIG_PACKAGE_libpcre16 is not set +# CONFIG_PACKAGE_libpcre2 is not set +# CONFIG_PACKAGE_libpcre2-16 is not set +# CONFIG_PACKAGE_libpcre2-32 is not set +# CONFIG_PACKAGE_libpcrecpp is not set +# CONFIG_PACKAGE_libpcsclite is not set +# CONFIG_PACKAGE_libpkcs11-spy is not set +# CONFIG_PACKAGE_libplist is not set +# CONFIG_PACKAGE_libplistcxx is not set +# CONFIG_PACKAGE_libpng is not set +# CONFIG_PACKAGE_libpopt is not set +# CONFIG_PACKAGE_libpri is not set +# CONFIG_PACKAGE_libprotobuf-c is not set +# CONFIG_PACKAGE_libqrencode is not set +# CONFIG_PACKAGE_libradcli is not set +# CONFIG_PACKAGE_libreadline is not set +# CONFIG_PACKAGE_libredblack is not set +# CONFIG_PACKAGE_libroxml is not set +# CONFIG_PACKAGE_librpc is not set +# CONFIG_PACKAGE_librrd1 is not set +# CONFIG_PACKAGE_librtlsdr is not set +# CONFIG_PACKAGE_libruby is not set +# CONFIG_PACKAGE_libsamplerate is not set +# CONFIG_PACKAGE_libsane is not set +# CONFIG_PACKAGE_libsasl2 is not set +# CONFIG_PACKAGE_libsearpc is not set +# CONFIG_PACKAGE_libseccomp is not set +# CONFIG_PACKAGE_libsensors is not set +# CONFIG_PACKAGE_libshout is not set +# CONFIG_PACKAGE_libshout-full is not set +# CONFIG_PACKAGE_libshout-nossl is not set +# CONFIG_PACKAGE_libsigcxx is not set +# CONFIG_PACKAGE_libsmartcols is not set +# CONFIG_PACKAGE_libsndfile is not set +# CONFIG_PACKAGE_libsoc is not set +# CONFIG_PACKAGE_libsocks is not set +# CONFIG_PACKAGE_libsodium is not set +# CONFIG_PACKAGE_libsoup is not set +# CONFIG_PACKAGE_libsoxr is not set +# CONFIG_PACKAGE_libspeex is not set +# CONFIG_PACKAGE_libspeexdsp is not set +# CONFIG_PACKAGE_libssh is not set +# CONFIG_PACKAGE_libssh2 is not set +# CONFIG_PACKAGE_libstoken is not set +# CONFIG_PACKAGE_libstrophe is not set +# CONFIG_PACKAGE_libtalloc is not set +# CONFIG_PACKAGE_libtasn1 is not set +# CONFIG_PACKAGE_libtheora is not set +# CONFIG_PACKAGE_libtiff is not set +# CONFIG_PACKAGE_libtiffxx is not set +# CONFIG_PACKAGE_libtins is not set +# CONFIG_PACKAGE_libtorrent is not set +CONFIG_PACKAGE_libubox=y +# CONFIG_PACKAGE_libubox-lua is not set +CONFIG_PACKAGE_libubus=y +CONFIG_PACKAGE_libubus-lua=y +CONFIG_PACKAGE_libuci=y +CONFIG_PACKAGE_libuci-lua=y +CONFIG_PACKAGE_libuclient=y +# CONFIG_PACKAGE_libudev-fbsd is not set +# CONFIG_PACKAGE_libudns is not set +# CONFIG_PACKAGE_libuecc is not set +# CONFIG_PACKAGE_libugpio is not set +# CONFIG_PACKAGE_libunbound is not set +# CONFIG_PACKAGE_libunistring is not set +# CONFIG_PACKAGE_libunwind is not set +# CONFIG_PACKAGE_libupnp is not set +# CONFIG_PACKAGE_libupnpp is not set +# CONFIG_PACKAGE_liburcu is not set +# CONFIG_PACKAGE_libusb-1.0 is not set +# CONFIG_PACKAGE_libusb-compat is not set +# CONFIG_PACKAGE_libusbmuxd is not set +# CONFIG_PACKAGE_libustream-cyassl is not set +# CONFIG_PACKAGE_libustream-mbedtls is not set +# CONFIG_PACKAGE_libustream-openssl is not set +CONFIG_PACKAGE_libuuid=y +# CONFIG_PACKAGE_libuv is not set +# CONFIG_PACKAGE_libuvc is not set +# CONFIG_PACKAGE_libv4l is not set +# CONFIG_PACKAGE_libvorbis is not set +# CONFIG_PACKAGE_libvorbisidec is not set +# CONFIG_PACKAGE_libvpx is not set +# CONFIG_PACKAGE_libwebcam is not set +# CONFIG_PACKAGE_libwebsockets-full is not set +# CONFIG_PACKAGE_libwebsockets-openssl is not set +# CONFIG_PACKAGE_libwebsockets-wolfssl is not set +# CONFIG_PACKAGE_libwrap is not set +# CONFIG_PACKAGE_libwxbase is not set +# CONFIG_PACKAGE_libx264 is not set +# CONFIG_PACKAGE_libxerces-c is not set +# CONFIG_PACKAGE_libxerces-c-samples is not set +# CONFIG_PACKAGE_libxml2 is not set +# CONFIG_PACKAGE_libxslt is not set +# CONFIG_PACKAGE_libyang is not set +# CONFIG_PACKAGE_libzdb is not set +# CONFIG_PACKAGE_libzmq-curve is not set +# CONFIG_PACKAGE_libzmq-nc is not set +# CONFIG_PACKAGE_linux-atm is not set +# CONFIG_PACKAGE_loudmouth is not set +# CONFIG_PACKAGE_lttng-ust is not set +# CONFIG_PACKAGE_mtdev is not set +# CONFIG_PACKAGE_musl-fts is not set +# CONFIG_PACKAGE_mxml is not set +# CONFIG_PACKAGE_nacl is not set +# CONFIG_PACKAGE_opencv is not set +# CONFIG_PACKAGE_p11-kit is not set +# CONFIG_PACKAGE_poco is not set +# CONFIG_PACKAGE_protobuf is not set +# CONFIG_PACKAGE_pthsem is not set +CONFIG_PACKAGE_rpcd-mod-rrdns=y +# CONFIG_PACKAGE_rxtx is not set +# CONFIG_PACKAGE_sbc is not set +# CONFIG_PACKAGE_terminfo is not set +# CONFIG_PACKAGE_tinycdb is not set +# CONFIG_PACKAGE_uclibcxx is not set +# CONFIG_PACKAGE_xmlrpc-c is not set +# CONFIG_PACKAGE_xmlrpc-c-client is not set +# CONFIG_PACKAGE_xmlrpc-c-server is not set +# CONFIG_PACKAGE_yajl is not set +CONFIG_PACKAGE_zlib=y + +# +# LuCI +# + +# +# 1. Collections +# +CONFIG_PACKAGE_luci=y +# CONFIG_PACKAGE_luci-ssl is not set +# CONFIG_PACKAGE_luci-ssl-openssl is not set + +# +# 2. Modules +# +CONFIG_PACKAGE_luci-base=y +# CONFIG_LUCI_SRCDIET is not set + +# +# Translations +# +# CONFIG_LUCI_LANG_ca is not set +# CONFIG_LUCI_LANG_cs is not set +# CONFIG_LUCI_LANG_de is not set +# CONFIG_LUCI_LANG_el is not set +# CONFIG_LUCI_LANG_en is not set +# CONFIG_LUCI_LANG_es is not set +# CONFIG_LUCI_LANG_fr is not set +# CONFIG_LUCI_LANG_he is not set +# CONFIG_LUCI_LANG_hu is not set +# CONFIG_LUCI_LANG_it is not set +# CONFIG_LUCI_LANG_ja is not set +# CONFIG_LUCI_LANG_ko is not set +# CONFIG_LUCI_LANG_ms is not set +# CONFIG_LUCI_LANG_no is not set +# CONFIG_LUCI_LANG_pl is not set +# CONFIG_LUCI_LANG_pt is not set +# CONFIG_LUCI_LANG_pt-br is not set +# CONFIG_LUCI_LANG_ro is not set +# CONFIG_LUCI_LANG_ru is not set +# CONFIG_LUCI_LANG_sk is not set +# CONFIG_LUCI_LANG_sv is not set +# CONFIG_LUCI_LANG_tr is not set +# CONFIG_LUCI_LANG_uk is not set +# CONFIG_LUCI_LANG_vi is not set +CONFIG_LUCI_LANG_zh-cn=y +# CONFIG_LUCI_LANG_zh-tw is not set +CONFIG_PACKAGE_luci-mod-admin-full=y +# CONFIG_PACKAGE_luci-mod-failsafe is not set +# CONFIG_PACKAGE_luci-mod-freifunk is not set +# CONFIG_PACKAGE_luci-mod-freifunk-community is not set +# CONFIG_PACKAGE_luci-mod-rpc is not set + +# +# 3. Applications +# +# CONFIG_PACKAGE_luci-app-adblock is not set +CONFIG_PACKAGE_luci-app-adbyby-plus=y +# CONFIG_PACKAGE_luci-app-advanced-reboot is not set +# CONFIG_PACKAGE_luci-app-ahcp is not set +CONFIG_PACKAGE_luci-app-aliddns=y +# CONFIG_PACKAGE_luci-app-amule is not set +CONFIG_PACKAGE_luci-app-apfree_wifidog=y +CONFIG_PACKAGE_luci-app-aria2=y +CONFIG_PACKAGE_luci-app-arpbind=y +# CONFIG_PACKAGE_luci-app-asterisk is not set +# CONFIG_PACKAGE_luci-app-attendedsysupgrade is not set +CONFIG_PACKAGE_luci-app-autoreboot=y +# CONFIG_PACKAGE_luci-app-bcp38 is not set +# CONFIG_PACKAGE_luci-app-bird4 is not set +# CONFIG_PACKAGE_luci-app-bird6 is not set +# CONFIG_PACKAGE_luci-app-bmx6 is not set +# CONFIG_PACKAGE_luci-app-bmx7 is not set +# CONFIG_PACKAGE_luci-app-cjdns is not set +# CONFIG_PACKAGE_luci-app-clamav is not set +# CONFIG_PACKAGE_luci-app-commands is not set +# CONFIG_PACKAGE_luci-app-cshark is not set +CONFIG_PACKAGE_luci-app-ddns=y +# CONFIG_PACKAGE_luci-app-diag-core is not set +# CONFIG_PACKAGE_luci-app-dnscrypt-proxy is not set +# CONFIG_PACKAGE_luci-app-dogcom is not set +# CONFIG_PACKAGE_luci-app-dump1090 is not set +# CONFIG_PACKAGE_luci-app-dynapoint is not set +# CONFIG_PACKAGE_luci-app-e2guardian is not set +CONFIG_PACKAGE_luci-app-filetransfer=y +CONFIG_PACKAGE_luci-app-firewall=y +# CONFIG_PACKAGE_luci-app-freifunk-diagnostics is not set +# CONFIG_PACKAGE_luci-app-freifunk-policyrouting is not set +# CONFIG_PACKAGE_luci-app-freifunk-widgets is not set +# CONFIG_PACKAGE_luci-app-frpc is not set +# CONFIG_PACKAGE_luci-app-fwknopd is not set +CONFIG_PACKAGE_luci-app-hd-idle=y +# CONFIG_PACKAGE_luci-app-hnet is not set +CONFIG_PACKAGE_luci-app-ipsec-vpnd=y +# CONFIG_PACKAGE_luci-app-kcptun is not set +# CONFIG_PACKAGE_luci-app-kuainiao is not set +# CONFIG_PACKAGE_luci-app-meshwizard is not set +# CONFIG_PACKAGE_luci-app-minidlna is not set +# CONFIG_PACKAGE_luci-app-mjpg-streamer is not set +# CONFIG_PACKAGE_luci-app-mmc-over-gpio is not set +# CONFIG_PACKAGE_luci-app-mproxy is not set +# CONFIG_PACKAGE_luci-app-mwan3 is not set +CONFIG_PACKAGE_luci-app-n2n_v2=y +CONFIG_PACKAGE_luci-app-ngrokc=y +CONFIG_PACKAGE_luci-app-nlbwmon=y +# CONFIG_PACKAGE_luci-app-ntpc is not set +# CONFIG_PACKAGE_luci-app-ocserv is not set +# CONFIG_PACKAGE_luci-app-olsr is not set +# CONFIG_PACKAGE_luci-app-olsr-services is not set +# CONFIG_PACKAGE_luci-app-olsr-viz is not set +# CONFIG_PACKAGE_luci-app-openvpn is not set +# CONFIG_PACKAGE_luci-app-openvpn-server is not set +# CONFIG_PACKAGE_luci-app-oscam is not set +# CONFIG_PACKAGE_luci-app-p910nd is not set +# CONFIG_PACKAGE_luci-app-polipo is not set +CONFIG_PACKAGE_luci-app-pptp-server=y +# CONFIG_PACKAGE_luci-app-privoxy is not set +# CONFIG_PACKAGE_luci-app-qos is not set +# CONFIG_PACKAGE_luci-app-radicale is not set +# CONFIG_PACKAGE_luci-app-rp-pppoe-server is not set +CONFIG_PACKAGE_luci-app-samba=y +CONFIG_PACKAGE_luci-app-sfe=y +# CONFIG_PACKAGE_luci-app-shadowsocks-libev is not set +CONFIG_PACKAGE_luci-app-shadowsocksr-pro=y +# CONFIG_PACKAGE_luci-app-shairplay is not set +# CONFIG_PACKAGE_luci-app-shairport is not set +# CONFIG_PACKAGE_luci-app-siitwizard is not set +# CONFIG_PACKAGE_luci-app-simple-adblock is not set +# CONFIG_PACKAGE_luci-app-splash is not set +CONFIG_PACKAGE_luci-app-sqm=y +# CONFIG_PACKAGE_luci-app-squid is not set +# CONFIG_PACKAGE_luci-app-ssrserver-python is not set +# CONFIG_PACKAGE_luci-app-statistics is not set +# CONFIG_PACKAGE_luci-app-syncdial is not set +# CONFIG_PACKAGE_luci-app-tinyproxy is not set +# CONFIG_PACKAGE_luci-app-transmission is not set +# CONFIG_PACKAGE_luci-app-transparent-proxy is not set +# CONFIG_PACKAGE_luci-app-travelmate is not set +# CONFIG_PACKAGE_luci-app-udpxy is not set +# CONFIG_PACKAGE_luci-app-uhttpd is not set +# CONFIG_PACKAGE_luci-app-unbound is not set +CONFIG_PACKAGE_luci-app-upnp=y +CONFIG_PACKAGE_luci-app-usb-printer=y +CONFIG_PACKAGE_luci-app-vlmcsd=y +# CONFIG_PACKAGE_luci-app-vnstat is not set +# CONFIG_PACKAGE_luci-app-vpnbypass is not set +CONFIG_PACKAGE_luci-app-vsftpd=y +# CONFIG_PACKAGE_luci-app-watchcat is not set +CONFIG_PACKAGE_luci-app-wifischedule=y +# CONFIG_PACKAGE_luci-app-wireguard is not set +CONFIG_PACKAGE_luci-app-wol=y +# CONFIG_PACKAGE_luci-app-zerotier is not set + +# +# 4. Themes +# +# CONFIG_PACKAGE_luci-theme-atmaterial is not set +CONFIG_PACKAGE_luci-theme-bootstrap=y +# CONFIG_PACKAGE_luci-theme-freifunk-generic is not set +# CONFIG_PACKAGE_luci-theme-material is not set +# CONFIG_PACKAGE_luci-theme-openwrt is not set + +# +# 5. Protocols +# +# CONFIG_PACKAGE_luci-proto-3g is not set +# CONFIG_PACKAGE_luci-proto-ipip is not set +CONFIG_PACKAGE_luci-proto-ipv6=y +# CONFIG_PACKAGE_luci-proto-ncm is not set +# CONFIG_PACKAGE_luci-proto-openconnect is not set +CONFIG_PACKAGE_luci-proto-ppp=y +# CONFIG_PACKAGE_luci-proto-qmi is not set +# CONFIG_PACKAGE_luci-proto-relay is not set +# CONFIG_PACKAGE_luci-proto-vpnc is not set +# CONFIG_PACKAGE_luci-proto-wireguard is not set + +# +# 6. Libraries +# +# CONFIG_PACKAGE_luci-lib-dracula is not set +# CONFIG_PACKAGE_luci-lib-httpclient is not set +CONFIG_PACKAGE_luci-lib-ip=y +# CONFIG_PACKAGE_luci-lib-jquery-1-4 is not set +# CONFIG_PACKAGE_luci-lib-json is not set +CONFIG_PACKAGE_luci-lib-jsonc=y +# CONFIG_PACKAGE_luci-lib-luaneightbl is not set +CONFIG_PACKAGE_luci-lib-nixio=y +# CONFIG_PACKAGE_luci-lib-px5g is not set + +# +# 9. Freifunk +# +# CONFIG_PACKAGE_freifunk-common is not set +# CONFIG_PACKAGE_freifunk-firewall is not set +# CONFIG_PACKAGE_freifunk-policyrouting is not set +# CONFIG_PACKAGE_freifunk-watchdog is not set +# CONFIG_PACKAGE_meshwizard is not set +CONFIG_PACKAGE_default-settings=y +CONFIG_PACKAGE_luci-i18n-adbyby-plus-zh-cn=y +CONFIG_PACKAGE_luci-i18n-aliddns-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-aria2-pt-br is not set +# CONFIG_PACKAGE_luci-i18n-aria2-sv is not set +CONFIG_PACKAGE_luci-i18n-aria2-zh-cn=y +CONFIG_PACKAGE_luci-i18n-arpbind-zh-cn=y +CONFIG_PACKAGE_luci-i18n-autoreboot-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-base-ca is not set +# CONFIG_PACKAGE_luci-i18n-base-cs is not set +# CONFIG_PACKAGE_luci-i18n-base-de is not set +# CONFIG_PACKAGE_luci-i18n-base-el is not set +# CONFIG_PACKAGE_luci-i18n-base-en is not set +# CONFIG_PACKAGE_luci-i18n-base-es is not set +# CONFIG_PACKAGE_luci-i18n-base-fr is not set +# CONFIG_PACKAGE_luci-i18n-base-he is not set +# CONFIG_PACKAGE_luci-i18n-base-hu is not set +# CONFIG_PACKAGE_luci-i18n-base-it is not set +# CONFIG_PACKAGE_luci-i18n-base-ja is not set +# CONFIG_PACKAGE_luci-i18n-base-ko is not set +# CONFIG_PACKAGE_luci-i18n-base-ms is not set +# CONFIG_PACKAGE_luci-i18n-base-no is not set +# CONFIG_PACKAGE_luci-i18n-base-pl is not set +# CONFIG_PACKAGE_luci-i18n-base-pt is not set +# CONFIG_PACKAGE_luci-i18n-base-pt-br is not set +# CONFIG_PACKAGE_luci-i18n-base-ro is not set +# CONFIG_PACKAGE_luci-i18n-base-ru is not set +# CONFIG_PACKAGE_luci-i18n-base-sk is not set +# CONFIG_PACKAGE_luci-i18n-base-sv is not set +# CONFIG_PACKAGE_luci-i18n-base-tr is not set +# CONFIG_PACKAGE_luci-i18n-base-uk is not set +# CONFIG_PACKAGE_luci-i18n-base-vi is not set +CONFIG_PACKAGE_luci-i18n-base-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-base-zh-tw is not set +# CONFIG_PACKAGE_luci-i18n-ddns-ca is not set +# CONFIG_PACKAGE_luci-i18n-ddns-cs is not set +# CONFIG_PACKAGE_luci-i18n-ddns-de is not set +# CONFIG_PACKAGE_luci-i18n-ddns-el is not set +# CONFIG_PACKAGE_luci-i18n-ddns-es is not set +# CONFIG_PACKAGE_luci-i18n-ddns-fr is not set +# CONFIG_PACKAGE_luci-i18n-ddns-he is not set +# CONFIG_PACKAGE_luci-i18n-ddns-hu is not set +# CONFIG_PACKAGE_luci-i18n-ddns-it is not set +# CONFIG_PACKAGE_luci-i18n-ddns-ja is not set +# CONFIG_PACKAGE_luci-i18n-ddns-no is not set +# CONFIG_PACKAGE_luci-i18n-ddns-pl is not set +# CONFIG_PACKAGE_luci-i18n-ddns-pt is not set +# CONFIG_PACKAGE_luci-i18n-ddns-pt-br is not set +# CONFIG_PACKAGE_luci-i18n-ddns-ro is not set +# CONFIG_PACKAGE_luci-i18n-ddns-ru is not set +# CONFIG_PACKAGE_luci-i18n-ddns-sv is not set +# CONFIG_PACKAGE_luci-i18n-ddns-tr is not set +# CONFIG_PACKAGE_luci-i18n-ddns-uk is not set +# CONFIG_PACKAGE_luci-i18n-ddns-vi is not set +CONFIG_PACKAGE_luci-i18n-ddns-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-ddns-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-filetransfer-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-firewall-ca is not set +# CONFIG_PACKAGE_luci-i18n-firewall-cs is not set +# CONFIG_PACKAGE_luci-i18n-firewall-de is not set +# CONFIG_PACKAGE_luci-i18n-firewall-el is not set +# CONFIG_PACKAGE_luci-i18n-firewall-en is not set +# CONFIG_PACKAGE_luci-i18n-firewall-es is not set +# CONFIG_PACKAGE_luci-i18n-firewall-fr is not set +# CONFIG_PACKAGE_luci-i18n-firewall-he is not set +# CONFIG_PACKAGE_luci-i18n-firewall-hu is not set +# CONFIG_PACKAGE_luci-i18n-firewall-it is not set +# CONFIG_PACKAGE_luci-i18n-firewall-ja is not set +# CONFIG_PACKAGE_luci-i18n-firewall-ko is not set +# CONFIG_PACKAGE_luci-i18n-firewall-ms is not set +# CONFIG_PACKAGE_luci-i18n-firewall-no is not set +# CONFIG_PACKAGE_luci-i18n-firewall-pl is not set +# CONFIG_PACKAGE_luci-i18n-firewall-pt is not set +# CONFIG_PACKAGE_luci-i18n-firewall-pt-br is not set +# CONFIG_PACKAGE_luci-i18n-firewall-ro is not set +# CONFIG_PACKAGE_luci-i18n-firewall-ru is not set +# CONFIG_PACKAGE_luci-i18n-firewall-sk is not set +# CONFIG_PACKAGE_luci-i18n-firewall-sv is not set +# CONFIG_PACKAGE_luci-i18n-firewall-tr is not set +# CONFIG_PACKAGE_luci-i18n-firewall-uk is not set +# CONFIG_PACKAGE_luci-i18n-firewall-vi is not set +CONFIG_PACKAGE_luci-i18n-firewall-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-firewall-zh-tw is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-ca is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-cs is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-de is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-el is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-en is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-es is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-fr is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-he is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-hu is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-it is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-ja is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-ms is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-no is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-pl is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-pt is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-pt-br is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-ro is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-ru is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-sk is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-sv is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-tr is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-uk is not set +# CONFIG_PACKAGE_luci-i18n-hd-idle-vi is not set +CONFIG_PACKAGE_luci-i18n-hd-idle-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-hd-idle-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-ipsec-vpnd-zh-cn=y +CONFIG_PACKAGE_luci-i18n-n2n_v2-zh-cn=y +CONFIG_PACKAGE_luci-i18n-ngrokc-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-nlbwmon-ja is not set +CONFIG_PACKAGE_luci-i18n-nlbwmon-zh-cn=y +CONFIG_PACKAGE_luci-i18n-pptp-server-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-samba-ca is not set +# CONFIG_PACKAGE_luci-i18n-samba-cs is not set +# CONFIG_PACKAGE_luci-i18n-samba-de is not set +# CONFIG_PACKAGE_luci-i18n-samba-el is not set +# CONFIG_PACKAGE_luci-i18n-samba-en is not set +# CONFIG_PACKAGE_luci-i18n-samba-es is not set +# CONFIG_PACKAGE_luci-i18n-samba-fr is not set +# CONFIG_PACKAGE_luci-i18n-samba-he is not set +# CONFIG_PACKAGE_luci-i18n-samba-hu is not set +# CONFIG_PACKAGE_luci-i18n-samba-it is not set +# CONFIG_PACKAGE_luci-i18n-samba-ja is not set +# CONFIG_PACKAGE_luci-i18n-samba-ms is not set +# CONFIG_PACKAGE_luci-i18n-samba-no is not set +# CONFIG_PACKAGE_luci-i18n-samba-pl is not set +# CONFIG_PACKAGE_luci-i18n-samba-pt is not set +# CONFIG_PACKAGE_luci-i18n-samba-pt-br is not set +# CONFIG_PACKAGE_luci-i18n-samba-ro is not set +# CONFIG_PACKAGE_luci-i18n-samba-ru is not set +# CONFIG_PACKAGE_luci-i18n-samba-sk is not set +# CONFIG_PACKAGE_luci-i18n-samba-sv is not set +# CONFIG_PACKAGE_luci-i18n-samba-tr is not set +# CONFIG_PACKAGE_luci-i18n-samba-uk is not set +# CONFIG_PACKAGE_luci-i18n-samba-vi is not set +CONFIG_PACKAGE_luci-i18n-samba-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-samba-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-sfe-zh-cn=y +CONFIG_PACKAGE_luci-i18n-shadowsocksr-pro-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-upnp-ca is not set +# CONFIG_PACKAGE_luci-i18n-upnp-cs is not set +# CONFIG_PACKAGE_luci-i18n-upnp-de is not set +# CONFIG_PACKAGE_luci-i18n-upnp-el is not set +# CONFIG_PACKAGE_luci-i18n-upnp-en is not set +# CONFIG_PACKAGE_luci-i18n-upnp-es is not set +# CONFIG_PACKAGE_luci-i18n-upnp-fr is not set +# CONFIG_PACKAGE_luci-i18n-upnp-he is not set +# CONFIG_PACKAGE_luci-i18n-upnp-hu is not set +# CONFIG_PACKAGE_luci-i18n-upnp-it is not set +# CONFIG_PACKAGE_luci-i18n-upnp-ja is not set +# CONFIG_PACKAGE_luci-i18n-upnp-ms is not set +# CONFIG_PACKAGE_luci-i18n-upnp-no is not set +# CONFIG_PACKAGE_luci-i18n-upnp-pl is not set +# CONFIG_PACKAGE_luci-i18n-upnp-pt is not set +# CONFIG_PACKAGE_luci-i18n-upnp-pt-br is not set +# CONFIG_PACKAGE_luci-i18n-upnp-ro is not set +# CONFIG_PACKAGE_luci-i18n-upnp-ru is not set +# CONFIG_PACKAGE_luci-i18n-upnp-sk is not set +# CONFIG_PACKAGE_luci-i18n-upnp-sv is not set +# CONFIG_PACKAGE_luci-i18n-upnp-tr is not set +# CONFIG_PACKAGE_luci-i18n-upnp-uk is not set +# CONFIG_PACKAGE_luci-i18n-upnp-vi is not set +CONFIG_PACKAGE_luci-i18n-upnp-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-upnp-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-usb-printer-zh-cn=y +CONFIG_PACKAGE_luci-i18n-vlmcsd-zh-cn=y +CONFIG_PACKAGE_luci-i18n-vsftpd-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-wifischedule-it is not set +# CONFIG_PACKAGE_luci-i18n-wifischedule-ja is not set +# CONFIG_PACKAGE_luci-i18n-wifischedule-pt-br is not set +# CONFIG_PACKAGE_luci-i18n-wifischedule-sv is not set +CONFIG_PACKAGE_luci-i18n-wifischedule-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-wol-ca is not set +# CONFIG_PACKAGE_luci-i18n-wol-cs is not set +# CONFIG_PACKAGE_luci-i18n-wol-de is not set +# CONFIG_PACKAGE_luci-i18n-wol-el is not set +# CONFIG_PACKAGE_luci-i18n-wol-en is not set +# CONFIG_PACKAGE_luci-i18n-wol-es is not set +# CONFIG_PACKAGE_luci-i18n-wol-fr is not set +# CONFIG_PACKAGE_luci-i18n-wol-he is not set +# CONFIG_PACKAGE_luci-i18n-wol-hu is not set +# CONFIG_PACKAGE_luci-i18n-wol-it is not set +# CONFIG_PACKAGE_luci-i18n-wol-ja is not set +# CONFIG_PACKAGE_luci-i18n-wol-ms is not set +# CONFIG_PACKAGE_luci-i18n-wol-no is not set +# CONFIG_PACKAGE_luci-i18n-wol-pl is not set +# CONFIG_PACKAGE_luci-i18n-wol-pt is not set +# CONFIG_PACKAGE_luci-i18n-wol-pt-br is not set +# CONFIG_PACKAGE_luci-i18n-wol-ro is not set +# CONFIG_PACKAGE_luci-i18n-wol-ru is not set +# CONFIG_PACKAGE_luci-i18n-wol-sk is not set +# CONFIG_PACKAGE_luci-i18n-wol-sv is not set +# CONFIG_PACKAGE_luci-i18n-wol-tr is not set +# CONFIG_PACKAGE_luci-i18n-wol-uk is not set +# CONFIG_PACKAGE_luci-i18n-wol-vi is not set +CONFIG_PACKAGE_luci-i18n-wol-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-wol-zh-tw is not set + +# +# Mail +# +# CONFIG_PACKAGE_alpine is not set +# CONFIG_PACKAGE_alpine-nossl is not set +# CONFIG_PACKAGE_bogofilter is not set +# CONFIG_PACKAGE_clamsmtp is not set +# CONFIG_PACKAGE_dovecot is not set +# CONFIG_PACKAGE_emailrelay is not set +# CONFIG_PACKAGE_fdm is not set +# CONFIG_PACKAGE_greyfix is not set +# CONFIG_PACKAGE_mailman is not set +# CONFIG_PACKAGE_mailsend is not set +# CONFIG_PACKAGE_mailsend-nossl is not set +# CONFIG_PACKAGE_msmtp is not set +# CONFIG_PACKAGE_msmtp-nossl is not set +# CONFIG_PACKAGE_mutt is not set +# CONFIG_PACKAGE_nail is not set +# CONFIG_PACKAGE_pigeonhole is not set +# CONFIG_PACKAGE_postfix is not set + +# +# Select postfix build options +# +CONFIG_POSTFIX_TLS=y +CONFIG_POSTFIX_SASL=y +CONFIG_POSTFIX_LDAP=y +# CONFIG_POSTFIX_DB is not set +CONFIG_POSTFIX_CDB=y +CONFIG_POSTFIX_SQLITE=y +# CONFIG_POSTFIX_PGSQL is not set +# CONFIG_POSTFIX_PCRE is not set +# CONFIG_POSTFIX_EAI is not set +# CONFIG_PACKAGE_ssmtp is not set + +# +# Multimedia +# + +# +# Streaming +# +# CONFIG_PACKAGE_oggfwd is not set +# CONFIG_PACKAGE_crtmpserver is not set +# CONFIG_PACKAGE_ffmpeg is not set +# CONFIG_PACKAGE_ffprobe is not set +# CONFIG_PACKAGE_ffserver is not set +# CONFIG_PACKAGE_fswebcam is not set +# CONFIG_PACKAGE_gphoto2 is not set +# CONFIG_PACKAGE_grilo is not set +# CONFIG_PACKAGE_grilo-plugins is not set +# CONFIG_PACKAGE_gst1-libav is not set +# CONFIG_PACKAGE_gstreamer1-libs is not set +# CONFIG_PACKAGE_gstreamer1-plugins-bad is not set +# CONFIG_PACKAGE_gstreamer1-plugins-base is not set +# CONFIG_PACKAGE_gstreamer1-plugins-good is not set +# CONFIG_PACKAGE_gstreamer1-plugins-ugly is not set +# CONFIG_PACKAGE_gstreamer1-utils is not set +# CONFIG_PACKAGE_icecast is not set +# CONFIG_PACKAGE_lcdgrilo is not set +# CONFIG_PACKAGE_minidlna is not set +# CONFIG_PACKAGE_mjpg-streamer is not set +# CONFIG_PACKAGE_motion is not set +# CONFIG_PACKAGE_tvheadend is not set +# CONFIG_PACKAGE_vips is not set +# CONFIG_PACKAGE_xupnpd is not set +# CONFIG_PACKAGE_youtube-dl is not set + +# +# Network +# + +# +# BitTorrent +# +# CONFIG_PACKAGE_mktorrent is not set +# CONFIG_PACKAGE_opentracker is not set +# CONFIG_PACKAGE_opentracker6 is not set +# CONFIG_PACKAGE_rtorrent is not set +# CONFIG_PACKAGE_rtorrent-rpc is not set +# CONFIG_PACKAGE_transmission-cli-mbedtls is not set +# CONFIG_PACKAGE_transmission-cli-openssl is not set +# CONFIG_PACKAGE_transmission-daemon-mbedtls is not set +# CONFIG_PACKAGE_transmission-daemon-openssl is not set +# CONFIG_PACKAGE_transmission-remote-mbedtls is not set +# CONFIG_PACKAGE_transmission-remote-openssl is not set + +# +# Captive Portals +# +CONFIG_PACKAGE_apfree_wifidog=y +# CONFIG_PACKAGE_coova-chilli is not set +# CONFIG_PACKAGE_nodogsplash is not set +# CONFIG_PACKAGE_nodogsplash2 is not set +# CONFIG_PACKAGE_wifidog is not set +# CONFIG_PACKAGE_wifidog-tls is not set + +# +# Download Manager +# +# CONFIG_PACKAGE_webui-aria2 is not set +# CONFIG_PACKAGE_yaaw is not set + +# +# File Transfer +# +CONFIG_PACKAGE_aria2=y + +# +# Aria2 Configuration +# +CONFIG_ARIA2_OPENSSL=y +# CONFIG_ARIA2_GNUTLS is not set +# CONFIG_ARIA2_NOSSL is not set +# CONFIG_ARIA2_LIBXML2 is not set +# CONFIG_ARIA2_EXPAT is not set +CONFIG_ARIA2_NOXML=y +CONFIG_ARIA2_BITTORRENT=y +# CONFIG_ARIA2_SFTP is not set +# CONFIG_ARIA2_ASYNC_DNS is not set +# CONFIG_ARIA2_COOKIE is not set +CONFIG_ARIA2_WEBSOCKET=y +# CONFIG_PACKAGE_atftp is not set +# CONFIG_PACKAGE_atftpd is not set +# CONFIG_PACKAGE_curl is not set +# CONFIG_PACKAGE_gnurl is not set +# CONFIG_PACKAGE_lftp is not set +# CONFIG_PACKAGE_rsync is not set +# CONFIG_PACKAGE_rsyncd is not set +# CONFIG_PACKAGE_vsftpd is not set +CONFIG_PACKAGE_vsftpd-alt=y +CONFIG_VSFTPD_USE_UCI_SCRIPTS=y +# CONFIG_PACKAGE_vsftpd-tls is not set +CONFIG_PACKAGE_wget=y +# CONFIG_PACKAGE_wget-nossl is not set + +# +# Filesystem +# +# CONFIG_PACKAGE_davfs2 is not set +# CONFIG_PACKAGE_netatalk is not set +# CONFIG_PACKAGE_nfs-kernel-server is not set +# CONFIG_PACKAGE_owftpd is not set +# CONFIG_PACKAGE_owhttpd is not set +# CONFIG_PACKAGE_owserver is not set +# CONFIG_PACKAGE_sshfs is not set + +# +# Firewall +# +# CONFIG_PACKAGE_arptables is not set +# CONFIG_PACKAGE_conntrack is not set +# CONFIG_PACKAGE_conntrackd is not set +# CONFIG_PACKAGE_ebtables is not set +# CONFIG_PACKAGE_fwknop is not set +# CONFIG_PACKAGE_fwknopd is not set +CONFIG_PACKAGE_ip6tables=y +# CONFIG_PACKAGE_ip6tables-extra is not set +# CONFIG_PACKAGE_ip6tables-mod-nat is not set +CONFIG_PACKAGE_iptables=y +# CONFIG_IPTABLES_CONNLABEL is not set +# CONFIG_IPTABLES_NFTABLES is not set +# CONFIG_PACKAGE_iptables-mod-account is not set +# CONFIG_PACKAGE_iptables-mod-chaos is not set +# CONFIG_PACKAGE_iptables-mod-cluster is not set +# CONFIG_PACKAGE_iptables-mod-clusterip is not set +# CONFIG_PACKAGE_iptables-mod-condition is not set +CONFIG_PACKAGE_iptables-mod-conntrack-extra=y +# CONFIG_PACKAGE_iptables-mod-delude is not set +# CONFIG_PACKAGE_iptables-mod-dhcpmac is not set +# CONFIG_PACKAGE_iptables-mod-dnetmap is not set +CONFIG_PACKAGE_iptables-mod-extra=y +# CONFIG_PACKAGE_iptables-mod-filter is not set +# CONFIG_PACKAGE_iptables-mod-fuzzy is not set +# CONFIG_PACKAGE_iptables-mod-geoip is not set +# CONFIG_PACKAGE_iptables-mod-hashlimit is not set +# CONFIG_PACKAGE_iptables-mod-iface is not set +# CONFIG_PACKAGE_iptables-mod-ipmark is not set +CONFIG_PACKAGE_iptables-mod-ipopt=y +# CONFIG_PACKAGE_iptables-mod-ipp2p is not set +# CONFIG_PACKAGE_iptables-mod-iprange is not set +CONFIG_PACKAGE_iptables-mod-ipsec=y +# CONFIG_PACKAGE_iptables-mod-ipv4options is not set +# CONFIG_PACKAGE_iptables-mod-led is not set +# CONFIG_PACKAGE_iptables-mod-length2 is not set +# CONFIG_PACKAGE_iptables-mod-logmark is not set +# CONFIG_PACKAGE_iptables-mod-lscan is not set +# CONFIG_PACKAGE_iptables-mod-lua is not set +CONFIG_PACKAGE_iptables-mod-nat-extra=y +# CONFIG_PACKAGE_iptables-mod-nflog is not set +# CONFIG_PACKAGE_iptables-mod-nfqueue is not set +# CONFIG_PACKAGE_iptables-mod-psd is not set +# CONFIG_PACKAGE_iptables-mod-quota2 is not set +# CONFIG_PACKAGE_iptables-mod-rpfilter is not set +# CONFIG_PACKAGE_iptables-mod-sysrq is not set +# CONFIG_PACKAGE_iptables-mod-tarpit is not set +# CONFIG_PACKAGE_iptables-mod-tee is not set +CONFIG_PACKAGE_iptables-mod-tproxy=y +# CONFIG_PACKAGE_iptables-mod-u32 is not set +# CONFIG_PACKAGE_iptables-mod-ulog is not set +# CONFIG_PACKAGE_iptaccount is not set +# CONFIG_PACKAGE_miniupnpc is not set +CONFIG_PACKAGE_miniupnpd=y +# CONFIG_MINIUPNPD_IGDv2 is not set +# CONFIG_PACKAGE_natpmpc is not set +# CONFIG_PACKAGE_nftables is not set +# CONFIG_PACKAGE_shorewall-core is not set +# CONFIG_PACKAGE_shorewall-lite is not set +# CONFIG_PACKAGE_shorewall6-lite is not set +# CONFIG_PACKAGE_snort is not set + +# +# Firewall Tunnel +# +# CONFIG_PACKAGE_iodine is not set +# CONFIG_PACKAGE_iodined is not set + +# +# FreeRADIUS (version 3) +# +# CONFIG_PACKAGE_freeradius3 is not set +# CONFIG_PACKAGE_freeradius3-common is not set +# CONFIG_PACKAGE_freeradius3-utils is not set + +# +# IP Addresses and Names +# +# CONFIG_PACKAGE_aggregate is not set +# CONFIG_PACKAGE_announce is not set +# CONFIG_PACKAGE_avahi-autoipd is not set +# CONFIG_PACKAGE_avahi-daemon-service-http is not set +# CONFIG_PACKAGE_avahi-daemon-service-ssh is not set +# CONFIG_PACKAGE_avahi-dbus-daemon is not set +# CONFIG_PACKAGE_avahi-dnsconfd is not set +# CONFIG_PACKAGE_avahi-nodbus-daemon is not set +# CONFIG_PACKAGE_avahi-utils is not set +# CONFIG_PACKAGE_bind-check is not set +# CONFIG_PACKAGE_bind-client is not set +# CONFIG_PACKAGE_bind-dig is not set +# CONFIG_PACKAGE_bind-dnssec is not set +# CONFIG_PACKAGE_bind-host is not set +# CONFIG_PACKAGE_bind-rndc is not set +# CONFIG_PACKAGE_bind-server is not set +# CONFIG_PACKAGE_bind-tools is not set +CONFIG_PACKAGE_ddns-scripts=y +# CONFIG_PACKAGE_ddns-scripts_cloudflare is not set +# CONFIG_PACKAGE_ddns-scripts_cloudflare.com-v4 is not set +# CONFIG_PACKAGE_ddns-scripts_godaddy.com-v1 is not set +# CONFIG_PACKAGE_ddns-scripts_no-ip_com is not set +# CONFIG_PACKAGE_ddns-scripts_nsupdate is not set +# CONFIG_PACKAGE_dhcp-forwarder is not set +# CONFIG_PACKAGE_dnscrypt-proxy is not set +# CONFIG_PACKAGE_dnscrypt-proxy-resolvers is not set +# CONFIG_PACKAGE_drill is not set +# CONFIG_PACKAGE_hostip is not set +# CONFIG_PACKAGE_idn is not set +# CONFIG_PACKAGE_inadyn is not set +# CONFIG_PACKAGE_isc-dhcp-client-ipv4 is not set +# CONFIG_PACKAGE_isc-dhcp-client-ipv6 is not set +# CONFIG_PACKAGE_isc-dhcp-omshell-ipv4 is not set +# CONFIG_PACKAGE_isc-dhcp-omshell-ipv6 is not set +# CONFIG_PACKAGE_isc-dhcp-relay-ipv4 is not set +# CONFIG_PACKAGE_isc-dhcp-relay-ipv6 is not set +# CONFIG_PACKAGE_isc-dhcp-server-ipv4 is not set +# CONFIG_PACKAGE_isc-dhcp-server-ipv6 is not set +# CONFIG_PACKAGE_knot is not set +# CONFIG_PACKAGE_knot-dig is not set +# CONFIG_PACKAGE_knot-host is not set +# CONFIG_PACKAGE_knot-keymgr is not set +# CONFIG_PACKAGE_knot-nsec3hash is not set +# CONFIG_PACKAGE_knot-nsupdate is not set +# CONFIG_PACKAGE_knot-tests is not set +# CONFIG_PACKAGE_knot-zonecheck is not set +# CONFIG_PACKAGE_mdns-utils is not set +# CONFIG_PACKAGE_mdnsd is not set +# CONFIG_PACKAGE_mdnsresponder is not set +# CONFIG_PACKAGE_nsd is not set +# CONFIG_PACKAGE_nsd-control is not set +# CONFIG_PACKAGE_nsd-control-setup is not set +# CONFIG_PACKAGE_nsd-nossl is not set +# CONFIG_PACKAGE_ohybridproxy is not set +# CONFIG_PACKAGE_unbound is not set +# CONFIG_PACKAGE_unbound-anchor is not set +# CONFIG_PACKAGE_unbound-control is not set +# CONFIG_PACKAGE_unbound-control-setup is not set +# CONFIG_PACKAGE_unbound-host is not set +# CONFIG_PACKAGE_zonestitcher is not set + +# +# Instant Messaging +# +# CONFIG_PACKAGE_bitlbee is not set +# CONFIG_PACKAGE_irssi is not set +# CONFIG_PACKAGE_ngircd is not set +# CONFIG_PACKAGE_ngircd-nossl is not set +# CONFIG_PACKAGE_prosody is not set +# CONFIG_PACKAGE_quassel-irssi is not set +# CONFIG_PACKAGE_umurmur-mbedtls is not set +# CONFIG_PACKAGE_umurmur-openssl is not set +# CONFIG_PACKAGE_znc is not set + +# +# Linux ATM tools +# +# CONFIG_PACKAGE_atm-aread is not set +# CONFIG_PACKAGE_atm-atmaddr is not set +# CONFIG_PACKAGE_atm-atmdiag is not set +# CONFIG_PACKAGE_atm-atmdump is not set +# CONFIG_PACKAGE_atm-atmloop is not set +# CONFIG_PACKAGE_atm-atmsigd is not set +# CONFIG_PACKAGE_atm-atmswitch is not set +# CONFIG_PACKAGE_atm-atmtcp is not set +# CONFIG_PACKAGE_atm-awrite is not set +# CONFIG_PACKAGE_atm-bus is not set +# CONFIG_PACKAGE_atm-debug-tools is not set +# CONFIG_PACKAGE_atm-diagnostics is not set +# CONFIG_PACKAGE_atm-esi is not set +# CONFIG_PACKAGE_atm-ilmid is not set +# CONFIG_PACKAGE_atm-ilmidiag is not set +# CONFIG_PACKAGE_atm-lecs is not set +# CONFIG_PACKAGE_atm-les is not set +# CONFIG_PACKAGE_atm-mpcd is not set +# CONFIG_PACKAGE_atm-saaldump is not set +# CONFIG_PACKAGE_atm-sonetdiag is not set +# CONFIG_PACKAGE_atm-svc_recv is not set +# CONFIG_PACKAGE_atm-svc_send is not set +# CONFIG_PACKAGE_atm-tools is not set +# CONFIG_PACKAGE_atm-ttcp_atm is not set +# CONFIG_PACKAGE_atm-zeppelin is not set +# CONFIG_PACKAGE_br2684ctl is not set + +# +# NMAP Suite +# +# CONFIG_PACKAGE_ncat is not set +# CONFIG_PACKAGE_ncat-ssl is not set +# CONFIG_PACKAGE_ndiff is not set +# CONFIG_PACKAGE_nmap is not set +# CONFIG_PACKAGE_nmap-ssl is not set +# CONFIG_PACKAGE_nping is not set + +# +# NTRIP +# +# CONFIG_PACKAGE_ntripcaster is not set +# CONFIG_PACKAGE_ntripclient is not set +# CONFIG_PACKAGE_ntripserver is not set + +# +# OLSR.org network framework +# +# CONFIG_PACKAGE_oonf-dlep-proxy is not set +# CONFIG_PACKAGE_oonf-dlep-radio is not set +# CONFIG_PACKAGE_oonf-init-scripts is not set +# CONFIG_PACKAGE_oonf-olsrd2 is not set + +# +# Open vSwitch +# +# CONFIG_PACKAGE_openvswitch is not set +# CONFIG_PACKAGE_openvswitch-base is not set +# CONFIG_PACKAGE_openvswitch-ovs-appctl is not set +# CONFIG_PACKAGE_openvswitch-ovs-dpctl is not set +# CONFIG_PACKAGE_openvswitch-ovs-ofctl is not set +# CONFIG_PACKAGE_openvswitch-ovs-vsctl is not set +# CONFIG_PACKAGE_openvswitch-ovsdb-client is not set +# CONFIG_PACKAGE_openvswitch-python is not set + +# +# P2P +# +# CONFIG_PACKAGE_amule is not set +CONFIG_AMULE_CRYPTOPP_STATIC_LINKING=y + +# +# Printing +# +CONFIG_PACKAGE_p910nd=y + +# +# Routing and Redirection +# +# CONFIG_PACKAGE_babel-pinger is not set +# CONFIG_PACKAGE_babeld is not set +# CONFIG_PACKAGE_batmand is not set +# CONFIG_PACKAGE_bcp38 is not set +# CONFIG_PACKAGE_bird4 is not set +# CONFIG_PACKAGE_bird4-uci is not set +# CONFIG_PACKAGE_bird6 is not set +# CONFIG_PACKAGE_bird6-uci is not set +# CONFIG_PACKAGE_birdc4 is not set +# CONFIG_PACKAGE_birdc6 is not set +# CONFIG_PACKAGE_birdcl4 is not set +# CONFIG_PACKAGE_birdcl6 is not set +# CONFIG_PACKAGE_bmx6 is not set +# CONFIG_PACKAGE_bmx7 is not set +# CONFIG_PACKAGE_cjdns is not set +# CONFIG_PACKAGE_cjdns-tests is not set +# CONFIG_PACKAGE_devlink is not set +# CONFIG_PACKAGE_genl is not set +# CONFIG_PACKAGE_igmpproxy is not set +# CONFIG_PACKAGE_ip-bridge is not set +CONFIG_PACKAGE_ip-full=y +# CONFIG_PACKAGE_ip-tiny is not set +# CONFIG_PACKAGE_lldpd is not set +# CONFIG_PACKAGE_mcproxy is not set +# CONFIG_PACKAGE_mwan3 is not set +# CONFIG_PACKAGE_nstat is not set +# CONFIG_PACKAGE_olsrd is not set +# CONFIG_PACKAGE_prince is not set +# CONFIG_PACKAGE_quagga is not set +# CONFIG_PACKAGE_relayd is not set +# CONFIG_PACKAGE_smcroute is not set +# CONFIG_PACKAGE_ss is not set +# CONFIG_PACKAGE_sslh is not set +CONFIG_PACKAGE_tc=y +# CONFIG_PACKAGE_tcpproxy is not set +# CONFIG_PACKAGE_vis is not set + +# +# SSH +# +# CONFIG_PACKAGE_autossh is not set +# CONFIG_PACKAGE_openssh-client is not set +# CONFIG_PACKAGE_openssh-client-utils is not set +# CONFIG_PACKAGE_openssh-keygen is not set +# CONFIG_PACKAGE_openssh-moduli is not set +# CONFIG_PACKAGE_openssh-server is not set +# CONFIG_PACKAGE_openssh-server-pam is not set +# CONFIG_PACKAGE_openssh-sftp-avahi-service is not set +# CONFIG_PACKAGE_openssh-sftp-client is not set +# CONFIG_PACKAGE_openssh-sftp-server is not set +# CONFIG_PACKAGE_sshtunnel is not set + +# +# THC-IPv6 attack and analyzing toolkit +# +# CONFIG_PACKAGE_thc-ipv6-address6 is not set +# CONFIG_PACKAGE_thc-ipv6-alive6 is not set +# CONFIG_PACKAGE_thc-ipv6-covert-send6 is not set +# CONFIG_PACKAGE_thc-ipv6-covert-send6d is not set +# CONFIG_PACKAGE_thc-ipv6-denial6 is not set +# CONFIG_PACKAGE_thc-ipv6-detect-new-ip6 is not set +# CONFIG_PACKAGE_thc-ipv6-detect-sniffer6 is not set +# CONFIG_PACKAGE_thc-ipv6-dnsdict6 is not set +# CONFIG_PACKAGE_thc-ipv6-dnsrevenum6 is not set +# CONFIG_PACKAGE_thc-ipv6-dos-new-ip6 is not set +# CONFIG_PACKAGE_thc-ipv6-dump-router6 is not set +# CONFIG_PACKAGE_thc-ipv6-exploit6 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-advertise6 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-dhcps6 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-dns6d is not set +# CONFIG_PACKAGE_thc-ipv6-fake-dnsupdate6 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-mipv6 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-mld26 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-mld6 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-mldrouter6 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-router26 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-router6 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-solicitate6 is not set +# CONFIG_PACKAGE_thc-ipv6-flood-advertise6 is not set +# CONFIG_PACKAGE_thc-ipv6-flood-dhcpc6 is not set +# CONFIG_PACKAGE_thc-ipv6-flood-mld26 is not set +# CONFIG_PACKAGE_thc-ipv6-flood-mld6 is not set +# CONFIG_PACKAGE_thc-ipv6-flood-mldrouter6 is not set +# CONFIG_PACKAGE_thc-ipv6-flood-router26 is not set +# CONFIG_PACKAGE_thc-ipv6-flood-router6 is not set +# CONFIG_PACKAGE_thc-ipv6-flood-solicitate6 is not set +# CONFIG_PACKAGE_thc-ipv6-fragmentation6 is not set +# CONFIG_PACKAGE_thc-ipv6-fuzz-dhcpc6 is not set +# CONFIG_PACKAGE_thc-ipv6-fuzz-dhcps6 is not set +# CONFIG_PACKAGE_thc-ipv6-fuzz-ip6 is not set +# CONFIG_PACKAGE_thc-ipv6-implementation6 is not set +# CONFIG_PACKAGE_thc-ipv6-implementation6d is not set +# CONFIG_PACKAGE_thc-ipv6-inverse-lookup6 is not set +# CONFIG_PACKAGE_thc-ipv6-kill-router6 is not set +# CONFIG_PACKAGE_thc-ipv6-ndpexhaust6 is not set +# CONFIG_PACKAGE_thc-ipv6-node-query6 is not set +# CONFIG_PACKAGE_thc-ipv6-parasite6 is not set +# CONFIG_PACKAGE_thc-ipv6-passive-discovery6 is not set +# CONFIG_PACKAGE_thc-ipv6-randicmp6 is not set +# CONFIG_PACKAGE_thc-ipv6-redir6 is not set +# CONFIG_PACKAGE_thc-ipv6-rsmurf6 is not set +# CONFIG_PACKAGE_thc-ipv6-sendpees6 is not set +# CONFIG_PACKAGE_thc-ipv6-sendpeesmp6 is not set +# CONFIG_PACKAGE_thc-ipv6-smurf6 is not set +# CONFIG_PACKAGE_thc-ipv6-thcping6 is not set +# CONFIG_PACKAGE_thc-ipv6-toobig6 is not set +# CONFIG_PACKAGE_thc-ipv6-trace6 is not set + +# +# Telephony +# +# CONFIG_PACKAGE_asterisk11 is not set +# CONFIG_PACKAGE_asterisk13 is not set +# CONFIG_PACKAGE_baresip is not set +# CONFIG_PACKAGE_freeswitch is not set +# CONFIG_PACKAGE_freeswitch-stable is not set +# CONFIG_PACKAGE_kamailio5 is not set +# CONFIG_PACKAGE_miax is not set +# CONFIG_PACKAGE_pcapsipdump is not set +# CONFIG_PACKAGE_restund is not set +# CONFIG_PACKAGE_rtpproxy is not set +# CONFIG_PACKAGE_sipp is not set +# CONFIG_PACKAGE_siproxd is not set +# CONFIG_PACKAGE_yate is not set + +# +# Time Synchronization +# +# CONFIG_PACKAGE_chrony is not set +# CONFIG_PACKAGE_htpdate is not set +# CONFIG_PACKAGE_linuxptp is not set +# CONFIG_PACKAGE_ntp-keygen is not set +# CONFIG_PACKAGE_ntp-utils is not set +# CONFIG_PACKAGE_ntpclient is not set +# CONFIG_PACKAGE_ntpd is not set +# CONFIG_PACKAGE_ntpdate is not set + +# +# VPN +# +# CONFIG_PACKAGE_chaosvpn is not set +# CONFIG_PACKAGE_fastd is not set +# CONFIG_PACKAGE_ipsec-tools is not set +CONFIG_PACKAGE_n2n_v2=y +# CONFIG_PACKAGE_ocserv is not set +# CONFIG_PACKAGE_openconnect is not set +# CONFIG_PACKAGE_opennhrp is not set +# CONFIG_PACKAGE_openvpn-easy-rsa is not set +# CONFIG_PACKAGE_openvpn-mbedtls is not set +# CONFIG_PACKAGE_openvpn-nossl is not set +# CONFIG_PACKAGE_openvpn-openssl is not set +CONFIG_PACKAGE_pptpd=y +# CONFIG_PACKAGE_softethervpn is not set +# CONFIG_PACKAGE_sstp-client is not set +CONFIG_PACKAGE_strongswan=y + +# +# Configuration +# +CONFIG_STRONGSWAN_ROUTING_TABLE="220" +CONFIG_STRONGSWAN_ROUTING_TABLE_PRIO="220" +CONFIG_PACKAGE_strongswan-charon=y +# CONFIG_PACKAGE_strongswan-charon-cmd is not set +# CONFIG_PACKAGE_strongswan-default is not set +CONFIG_PACKAGE_strongswan-ipsec=y +# CONFIG_PACKAGE_strongswan-isakmp is not set +# CONFIG_PACKAGE_strongswan-libtls is not set +CONFIG_PACKAGE_strongswan-minimal=y +# CONFIG_PACKAGE_strongswan-mod-addrblock is not set +CONFIG_PACKAGE_strongswan-mod-aes=y +# CONFIG_PACKAGE_strongswan-mod-af-alg is not set +# CONFIG_PACKAGE_strongswan-mod-agent is not set +# CONFIG_PACKAGE_strongswan-mod-attr is not set +# CONFIG_PACKAGE_strongswan-mod-attr-sql is not set +# CONFIG_PACKAGE_strongswan-mod-blowfish is not set +# CONFIG_PACKAGE_strongswan-mod-ccm is not set +# CONFIG_PACKAGE_strongswan-mod-cmac is not set +# CONFIG_PACKAGE_strongswan-mod-connmark is not set +# CONFIG_PACKAGE_strongswan-mod-constraints is not set +# CONFIG_PACKAGE_strongswan-mod-coupling is not set +# CONFIG_PACKAGE_strongswan-mod-ctr is not set +# CONFIG_PACKAGE_strongswan-mod-curl is not set +# CONFIG_PACKAGE_strongswan-mod-curve25519 is not set +# CONFIG_PACKAGE_strongswan-mod-des is not set +# CONFIG_PACKAGE_strongswan-mod-dhcp is not set +# CONFIG_PACKAGE_strongswan-mod-dnskey is not set +# CONFIG_PACKAGE_strongswan-mod-duplicheck is not set +# CONFIG_PACKAGE_strongswan-mod-eap-identity is not set +# CONFIG_PACKAGE_strongswan-mod-eap-md5 is not set +# CONFIG_PACKAGE_strongswan-mod-eap-mschapv2 is not set +# CONFIG_PACKAGE_strongswan-mod-eap-radius is not set +# CONFIG_PACKAGE_strongswan-mod-eap-tls is not set +# CONFIG_PACKAGE_strongswan-mod-farp is not set +# CONFIG_PACKAGE_strongswan-mod-fips-prf is not set +# CONFIG_PACKAGE_strongswan-mod-forecast is not set +# CONFIG_PACKAGE_strongswan-mod-gcm is not set +# CONFIG_PACKAGE_strongswan-mod-gcrypt is not set +CONFIG_PACKAGE_strongswan-mod-gmp=y +# CONFIG_PACKAGE_strongswan-mod-gmpdh is not set +# CONFIG_PACKAGE_strongswan-mod-ha is not set +CONFIG_PACKAGE_strongswan-mod-hmac=y +# CONFIG_PACKAGE_strongswan-mod-kernel-libipsec is not set +CONFIG_PACKAGE_strongswan-mod-kernel-netlink=y +# CONFIG_PACKAGE_strongswan-mod-ldap is not set +# CONFIG_PACKAGE_strongswan-mod-led is not set +# CONFIG_PACKAGE_strongswan-mod-load-tester is not set +# CONFIG_PACKAGE_strongswan-mod-md4 is not set +# CONFIG_PACKAGE_strongswan-mod-md5 is not set +# CONFIG_PACKAGE_strongswan-mod-mysql is not set +CONFIG_PACKAGE_strongswan-mod-nonce=y +# CONFIG_PACKAGE_strongswan-mod-openssl is not set +# CONFIG_PACKAGE_strongswan-mod-pem is not set +# CONFIG_PACKAGE_strongswan-mod-pgp is not set +# CONFIG_PACKAGE_strongswan-mod-pkcs1 is not set +# CONFIG_PACKAGE_strongswan-mod-pkcs11 is not set +# CONFIG_PACKAGE_strongswan-mod-pkcs12 is not set +# CONFIG_PACKAGE_strongswan-mod-pkcs7 is not set +# CONFIG_PACKAGE_strongswan-mod-pkcs8 is not set +CONFIG_PACKAGE_strongswan-mod-pubkey=y +CONFIG_PACKAGE_strongswan-mod-random=y +# CONFIG_PACKAGE_strongswan-mod-rc2 is not set +# CONFIG_PACKAGE_strongswan-mod-resolve is not set +# CONFIG_PACKAGE_strongswan-mod-revocation is not set +CONFIG_PACKAGE_strongswan-mod-sha1=y +# CONFIG_PACKAGE_strongswan-mod-sha2 is not set +# CONFIG_PACKAGE_strongswan-mod-smp is not set +CONFIG_PACKAGE_strongswan-mod-socket-default=y +# CONFIG_PACKAGE_strongswan-mod-socket-dynamic is not set +# CONFIG_PACKAGE_strongswan-mod-sql is not set +# CONFIG_PACKAGE_strongswan-mod-sqlite is not set +# CONFIG_PACKAGE_strongswan-mod-sshkey is not set +CONFIG_PACKAGE_strongswan-mod-stroke=y +# CONFIG_PACKAGE_strongswan-mod-test-vectors is not set +# CONFIG_PACKAGE_strongswan-mod-uci is not set +# CONFIG_PACKAGE_strongswan-mod-unity is not set +CONFIG_PACKAGE_strongswan-mod-updown=y +# CONFIG_PACKAGE_strongswan-mod-vici is not set +# CONFIG_PACKAGE_strongswan-mod-whitelist is not set +CONFIG_PACKAGE_strongswan-mod-x509=y +# CONFIG_PACKAGE_strongswan-mod-xauth-eap is not set +CONFIG_PACKAGE_strongswan-mod-xauth-generic=y +CONFIG_PACKAGE_strongswan-mod-xcbc=y +# CONFIG_PACKAGE_strongswan-pki is not set +# CONFIG_PACKAGE_strongswan-scepclient is not set +# CONFIG_PACKAGE_strongswan-swanctl is not set +# CONFIG_PACKAGE_tinc is not set +# CONFIG_PACKAGE_uanytun is not set +# CONFIG_PACKAGE_uanytun-nettle is not set +# CONFIG_PACKAGE_uanytun-nocrypt is not set +# CONFIG_PACKAGE_uanytun-sslcrypt is not set +# CONFIG_PACKAGE_vpnc is not set +# CONFIG_PACKAGE_vpnc-scripts is not set +# CONFIG_PACKAGE_wireguard is not set +# CONFIG_PACKAGE_wireguard-tools is not set +# CONFIG_PACKAGE_xl2tpd is not set +# CONFIG_PACKAGE_zerotier is not set + +# +# Version Control Systems +# +# CONFIG_PACKAGE_fossil is not set +# CONFIG_PACKAGE_git is not set +# CONFIG_PACKAGE_subversion-client is not set +# CONFIG_PACKAGE_subversion-libs is not set +# CONFIG_PACKAGE_subversion-server is not set + +# +# WWAN +# +# CONFIG_PACKAGE_adb-enablemodem is not set +# CONFIG_PACKAGE_comgt is not set +# CONFIG_PACKAGE_comgt-directip is not set +# CONFIG_PACKAGE_comgt-ncm is not set +# CONFIG_PACKAGE_uqmi is not set + +# +# Web Servers/Proxies +# +# CONFIG_PACKAGE_apache is not set +# CONFIG_PACKAGE_cgi-io is not set +# CONFIG_PACKAGE_clamav is not set +# CONFIG_PACKAGE_dansguardian is not set +# CONFIG_PACKAGE_e2guardian is not set +# CONFIG_PACKAGE_freshclam is not set +# CONFIG_PACKAGE_haproxy is not set +# CONFIG_PACKAGE_haproxy-nossl is not set +# CONFIG_PACKAGE_lighttpd is not set +# CONFIG_PACKAGE_nginx is not set +CONFIG_PACKAGE_ngrokc=y +CONFIG_PACKAGE_pdnsd-alt=y +# CONFIG_PACKAGE_polipo is not set +# CONFIG_PACKAGE_privoxy is not set +# CONFIG_PACKAGE_radicale-py2 is not set +# CONFIG_PACKAGE_radicale-py3 is not set +# CONFIG_PACKAGE_shadowsocks-client is not set +# CONFIG_PACKAGE_shadowsocks-libev-config is not set +# CONFIG_PACKAGE_shadowsocks-libev-ss-local is not set +# CONFIG_PACKAGE_shadowsocks-libev-ss-redir is not set +# CONFIG_PACKAGE_shadowsocks-libev-ss-rules is not set +# CONFIG_PACKAGE_shadowsocks-libev-ss-server is not set +# CONFIG_PACKAGE_shadowsocks-libev-ss-tunnel is not set +# CONFIG_PACKAGE_sockd is not set +# CONFIG_PACKAGE_socksify is not set +# CONFIG_PACKAGE_spawn-fcgi is not set +# CONFIG_PACKAGE_squid is not set +# CONFIG_PACKAGE_tinyproxy is not set +CONFIG_PACKAGE_uhttpd=y +# CONFIG_PACKAGE_uhttpd_debug is not set +# CONFIG_PACKAGE_uhttpd-mod-lua is not set +CONFIG_PACKAGE_uhttpd-mod-ubus=y + +# +# dial-in/up +# +# CONFIG_PACKAGE_rp-pppoe-common is not set +# CONFIG_PACKAGE_rp-pppoe-relay is not set +# CONFIG_PACKAGE_rp-pppoe-server is not set + +# +# tcprelay +# +# CONFIG_PACKAGE_tcpbridge is not set +# CONFIG_PACKAGE_tcpcapinfo is not set +# CONFIG_PACKAGE_tcpliveplay is not set +# CONFIG_PACKAGE_tcpprep is not set +# CONFIG_PACKAGE_tcpreplay is not set +# CONFIG_PACKAGE_tcpreplay-all is not set +# CONFIG_PACKAGE_tcpreplay-edit is not set +# CONFIG_PACKAGE_tcprewrite is not set + +# +# wireless +# +# CONFIG_PACKAGE_aircrack-ng is not set +# CONFIG_PACKAGE_airmon-ng is not set +# CONFIG_PACKAGE_dynapoint is not set +# CONFIG_PACKAGE_horst is not set +# CONFIG_PACKAGE_kismet-client is not set +# CONFIG_PACKAGE_kismet-drone is not set +# CONFIG_PACKAGE_kismet-server is not set +# CONFIG_PACKAGE_reaver is not set +# CONFIG_PACKAGE_wavemon is not set +CONFIG_PACKAGE_wifischedule=y +# CONFIG_PACKAGE_464xlat is not set +# CONFIG_PACKAGE_6in4 is not set +# CONFIG_PACKAGE_6rd is not set +# CONFIG_PACKAGE_6to4 is not set +# CONFIG_PACKAGE_acme is not set +# CONFIG_PACKAGE_adblock is not set +CONFIG_PACKAGE_adbyby=y +# CONFIG_PACKAGE_addrwatch is not set +# CONFIG_PACKAGE_ahcpd is not set +# CONFIG_PACKAGE_alfred is not set +# CONFIG_PACKAGE_apcupsd is not set +# CONFIG_PACKAGE_apcupsd-cgi is not set +# CONFIG_PACKAGE_apinger is not set +# CONFIG_PACKAGE_arp-scan is not set +# CONFIG_PACKAGE_authsae is not set +# CONFIG_PACKAGE_batctl is not set +# CONFIG_PACKAGE_beanstalkd is not set +# CONFIG_PACKAGE_bmon is not set +# CONFIG_PACKAGE_bwm-ng is not set +# CONFIG_PACKAGE_chat is not set +# CONFIG_PACKAGE_cifsmount is not set +# CONFIG_PACKAGE_coap-server is not set +# CONFIG_PACKAGE_conserver is not set +# CONFIG_PACKAGE_cshark is not set +# CONFIG_PACKAGE_daemonlogger is not set +# CONFIG_PACKAGE_darkstat is not set +# CONFIG_PACKAGE_dhcpcd is not set +# CONFIG_PACKAGE_dmapd is not set +# CONFIG_PACKAGE_dogcom is not set +# CONFIG_PACKAGE_ds-lite is not set +# CONFIG_PACKAGE_eapol-test is not set +# CONFIG_PACKAGE_esniper is not set +CONFIG_PACKAGE_etherwake=y +# CONFIG_PACKAGE_ethtool is not set +# CONFIG_PACKAGE_fakeidentd is not set +CONFIG_PACKAGE_fping=y +# CONFIG_PACKAGE_frpc is not set +# CONFIG_PACKAGE_gnunet is not set +# CONFIG_PACKAGE_gre is not set +# CONFIG_PACKAGE_hnet-full is not set +# CONFIG_PACKAGE_hnet-full-l2tp is not set +# CONFIG_PACKAGE_hnet-full-secure is not set +# CONFIG_PACKAGE_hnetd-nossl is not set +# CONFIG_PACKAGE_hnetd-openssl is not set +# CONFIG_PACKAGE_hostapd is not set +CONFIG_PACKAGE_hostapd-common=y +# CONFIG_PACKAGE_hostapd-mini is not set +# CONFIG_PACKAGE_hostapd-utils is not set +# CONFIG_PACKAGE_httping is not set +# CONFIG_PACKAGE_httping-nossl is not set +# CONFIG_PACKAGE_https_dns_proxy is not set +# CONFIG_PACKAGE_ibrdtn-tools is not set +# CONFIG_PACKAGE_ibrdtnd is not set +# CONFIG_PACKAGE_ifstat is not set +# CONFIG_PACKAGE_iftop is not set +# CONFIG_PACKAGE_iiod is not set +# CONFIG_PACKAGE_iotivity is not set +# CONFIG_PACKAGE_iotivity-cpp is not set +# CONFIG_PACKAGE_iotivity-example-garage is not set +# CONFIG_PACKAGE_iotivity-example-simple is not set +# CONFIG_PACKAGE_iotivity-oic-middle is not set +# CONFIG_PACKAGE_iotivity-resource-container-hue is not set +# CONFIG_PACKAGE_iotivity-resource-container-lib is not set +# CONFIG_PACKAGE_iotivity-resource-container-sample is not set +# CONFIG_PACKAGE_iotivity-resource-directory-lib is not set +# CONFIG_PACKAGE_iperf is not set +# CONFIG_PACKAGE_iperf3 is not set +# CONFIG_PACKAGE_iperf3-ssl is not set +# CONFIG_PACKAGE_ipip is not set +CONFIG_PACKAGE_ipset=y +# CONFIG_PACKAGE_ipset-dns is not set +CONFIG_PACKAGE_ipset-lists=y +# CONFIG_PACKAGE_iptraf-ng is not set +# CONFIG_PACKAGE_iputils-arping is not set +# CONFIG_PACKAGE_iputils-clockdiff is not set +# CONFIG_PACKAGE_iputils-ping is not set +# CONFIG_PACKAGE_iputils-ping6 is not set +# CONFIG_PACKAGE_iputils-tftpd is not set +# CONFIG_PACKAGE_iputils-tracepath is not set +# CONFIG_PACKAGE_iputils-tracepath6 is not set +# CONFIG_PACKAGE_iputils-traceroute6 is not set +CONFIG_PACKAGE_iw=y +# CONFIG_PACKAGE_jool is not set +# CONFIG_PACKAGE_jool-tools is not set +# CONFIG_PACKAGE_keepalived is not set +# CONFIG_PACKAGE_knxd is not set +# CONFIG_PACKAGE_kplex is not set +# CONFIG_PACKAGE_krb5-client is not set +# CONFIG_PACKAGE_krb5-libs is not set +# CONFIG_PACKAGE_krb5-server is not set +CONFIG_PACKAGE_libipset=y +# CONFIG_PACKAGE_linknx is not set +# CONFIG_PACKAGE_lispd is not set +# CONFIG_PACKAGE_mac-telnet-client is not set +# CONFIG_PACKAGE_mac-telnet-discover is not set +# CONFIG_PACKAGE_mac-telnet-ping is not set +# CONFIG_PACKAGE_mac-telnet-server is not set +# CONFIG_PACKAGE_map is not set +# CONFIG_PACKAGE_map-t is not set +# CONFIG_PACKAGE_memcached is not set +# CONFIG_PACKAGE_mii-tool is not set +# CONFIG_PACKAGE_mini_snmpd is not set +# CONFIG_PACKAGE_minimalist-pcproxy is not set +# CONFIG_PACKAGE_mosquitto-client-nossl is not set +# CONFIG_PACKAGE_mosquitto-client-ssl is not set +# CONFIG_PACKAGE_mosquitto-nossl is not set +# CONFIG_PACKAGE_mosquitto-ssl is not set +# CONFIG_PACKAGE_mproxy is not set +# CONFIG_PACKAGE_mrd6 is not set +# CONFIG_PACKAGE_mtr is not set +# CONFIG_PACKAGE_nbd is not set +# CONFIG_PACKAGE_nbd-server is not set +# CONFIG_PACKAGE_ncp is not set +# CONFIG_PACKAGE_ndppd is not set +# CONFIG_PACKAGE_netcat is not set +# CONFIG_PACKAGE_netdiscover is not set +# CONFIG_PACKAGE_netperf is not set +CONFIG_PACKAGE_nlbwmon=y +# CONFIG_PACKAGE_noddos is not set +# CONFIG_PACKAGE_noping is not set +# CONFIG_PACKAGE_nut is not set +# CONFIG_PACKAGE_obfsproxy is not set +CONFIG_PACKAGE_odhcp6c=y +CONFIG_PACKAGE_odhcp6c_ext_cer_id=0 +CONFIG_PACKAGE_odhcpd=y +CONFIG_PACKAGE_odhcpd_ext_cer_id=0 +# CONFIG_PACKAGE_ola is not set +# CONFIG_PACKAGE_omcproxy is not set +# CONFIG_PACKAGE_openldap-server is not set +# CONFIG_PACKAGE_oscam is not set +# CONFIG_PACKAGE_oping is not set +# CONFIG_PACKAGE_pen is not set +# CONFIG_PACKAGE_pimbd is not set +# CONFIG_PACKAGE_pingcheck is not set +# CONFIG_PACKAGE_port-mirroring is not set +# CONFIG_PACKAGE_portmap is not set +CONFIG_PACKAGE_ppp=y +# CONFIG_PACKAGE_ppp-mod-passwordfd is not set +# CONFIG_PACKAGE_ppp-mod-pppoa is not set +CONFIG_PACKAGE_ppp-mod-pppoe=y +# CONFIG_PACKAGE_ppp-mod-pppol2tp is not set +# CONFIG_PACKAGE_ppp-mod-pptp is not set +# CONFIG_PACKAGE_ppp-mod-radius is not set +# CONFIG_PACKAGE_ppp-multilink is not set +# CONFIG_PACKAGE_pppdump is not set +# CONFIG_PACKAGE_pppoe-discovery is not set +# CONFIG_PACKAGE_pppossh is not set +# CONFIG_PACKAGE_pppstats is not set +# CONFIG_PACKAGE_radsecproxy is not set +# CONFIG_PACKAGE_redsocks is not set +# CONFIG_PACKAGE_remserial is not set +# CONFIG_PACKAGE_rssileds is not set +# CONFIG_PACKAGE_rsyslog is not set +# CONFIG_PACKAGE_samba36-client is not set +# CONFIG_PACKAGE_samba36-net is not set +CONFIG_PACKAGE_samba36-server=y +CONFIG_PACKAGE_SAMBA_MAX_DEBUG_LEVEL=-1 +# CONFIG_PACKAGE_scapy is not set +# CONFIG_PACKAGE_sctp is not set +# CONFIG_PACKAGE_sctp-tools is not set +# CONFIG_PACKAGE_seafile-ccnet is not set +# CONFIG_PACKAGE_seafile-seahub is not set +# CONFIG_PACKAGE_seafile-server is not set +# CONFIG_PACKAGE_ser2net is not set +# CONFIG_PACKAGE_shadowsocksr-libev is not set +CONFIG_PACKAGE_shadowsocksr-libev-alt=y +# CONFIG_PACKAGE_shadowsocksr-libev-gfwlist is not set +# CONFIG_PACKAGE_shadowsocksr-libev-gfwlist-4M is not set +# CONFIG_PACKAGE_shadowsocksr-libev-gfwlist-polarssl is not set +# CONFIG_PACKAGE_shadowsocksr-libev-mini is not set +# CONFIG_PACKAGE_shadowsocksr-libev-polarssl is not set +# CONFIG_PACKAGE_simple-adblock is not set +# CONFIG_PACKAGE_sipgrep is not set +# CONFIG_PACKAGE_smartsnmpd is not set +# CONFIG_PACKAGE_sngrep is not set +# CONFIG_PACKAGE_snmp-mibs is not set +# CONFIG_PACKAGE_snmp-utils is not set +# CONFIG_PACKAGE_snmpd is not set +# CONFIG_PACKAGE_snmpd-static is not set +# CONFIG_PACKAGE_snmptrapd is not set +# CONFIG_PACKAGE_socat is not set +# CONFIG_PACKAGE_softflowd is not set +# CONFIG_PACKAGE_soloscli is not set +# CONFIG_PACKAGE_stunnel is not set +# CONFIG_PACKAGE_tayga is not set +# CONFIG_PACKAGE_tcpdump is not set +# CONFIG_PACKAGE_tcpdump-mini is not set +# CONFIG_PACKAGE_tor is not set +# CONFIG_PACKAGE_tor-gencert is not set +# CONFIG_PACKAGE_tor-geoip is not set +# CONFIG_PACKAGE_tor-resolve is not set +# CONFIG_PACKAGE_travelmate is not set +# CONFIG_PACKAGE_u2pnpd is not set +CONFIG_PACKAGE_uclient-fetch=y +# CONFIG_PACKAGE_udpxy is not set +# CONFIG_PACKAGE_ulogd is not set +# CONFIG_PACKAGE_umbim is not set +# CONFIG_PACKAGE_umdns is not set +# CONFIG_PACKAGE_usbip is not set +# CONFIG_PACKAGE_vallumd is not set +CONFIG_PACKAGE_vlmcsd=y +# CONFIG_PACKAGE_vncrepeater is not set +# CONFIG_PACKAGE_vnstat is not set +# CONFIG_PACKAGE_vpnbypass is not set +# CONFIG_PACKAGE_vsc7385-ucode-pb44 is not set +# CONFIG_PACKAGE_vsc7395-ucode-pb44 is not set +# CONFIG_PACKAGE_vti is not set +# CONFIG_PACKAGE_vxlan is not set +# CONFIG_PACKAGE_wakeonlan is not set +# CONFIG_PACKAGE_wpa-cli is not set +# CONFIG_PACKAGE_wpa-supplicant is not set +# CONFIG_WPA_SUPPLICANT_NO_TIMESTAMP_CHECK is not set +# CONFIG_WPA_RFKILL_SUPPORT is not set +CONFIG_WPA_MSG_MIN_PRIORITY=3 +# CONFIG_DRIVER_WEXT_SUPPORT is not set +CONFIG_DRIVER_11N_SUPPORT=y +CONFIG_DRIVER_11AC_SUPPORT=y +CONFIG_DRIVER_11W_SUPPORT=y +# CONFIG_PACKAGE_wpa-supplicant-mesh is not set +# CONFIG_PACKAGE_wpa-supplicant-mini is not set +# CONFIG_PACKAGE_wpa-supplicant-p2p is not set +# CONFIG_PACKAGE_wpad is not set +# CONFIG_PACKAGE_wpad-mesh is not set +CONFIG_PACKAGE_wpad-mini=y +# CONFIG_PACKAGE_wpan-tools is not set +# CONFIG_PACKAGE_wwan is not set +# CONFIG_PACKAGE_xinetd is not set + +# +# Sound +# +# CONFIG_PACKAGE_alsa-utils is not set +# CONFIG_PACKAGE_alsa-utils-seq is not set +# CONFIG_PACKAGE_alsa-utils-tests is not set +# CONFIG_PACKAGE_espeak is not set +# CONFIG_PACKAGE_faad2 is not set +# CONFIG_PACKAGE_fdk-aac is not set +# CONFIG_PACKAGE_forked-daapd is not set +# CONFIG_PACKAGE_ices is not set +# CONFIG_PACKAGE_lame is not set +# CONFIG_PACKAGE_lame-lib is not set +# CONFIG_PACKAGE_liblo-utils is not set +# CONFIG_PACKAGE_madplay is not set +# CONFIG_PACKAGE_madplay-alsa is not set +# CONFIG_PACKAGE_moc is not set +# CONFIG_PACKAGE_mpc is not set +# CONFIG_PACKAGE_mpd-avahi-service is not set +# CONFIG_PACKAGE_mpd-full is not set +# CONFIG_PACKAGE_mpd-mini is not set +# CONFIG_PACKAGE_mpg123 is not set +# CONFIG_PACKAGE_pianod is not set +# CONFIG_PACKAGE_pianod-client is not set +# CONFIG_PACKAGE_portaudio is not set +# CONFIG_PACKAGE_pulseaudio-daemon is not set +# CONFIG_PACKAGE_pulseaudio-profiles is not set +# CONFIG_PACKAGE_pulseaudio-tools is not set +# CONFIG_PACKAGE_shairplay is not set +# CONFIG_PACKAGE_shairport-sync-mbedtls is not set +# CONFIG_PACKAGE_shairport-sync-mini is not set +# CONFIG_PACKAGE_shairport-sync-openssl is not set +# CONFIG_PACKAGE_shine is not set +# CONFIG_PACKAGE_sox is not set +# CONFIG_PACKAGE_squeezelite-full is not set +# CONFIG_PACKAGE_squeezelite-mini is not set +# CONFIG_PACKAGE_svox is not set +# CONFIG_PACKAGE_upmpdcli is not set + +# +# Utilities +# + +# +# Boot Loaders +# +# CONFIG_PACKAGE_fconfig is not set +# CONFIG_PACKAGE_rbcfg is not set +CONFIG_PACKAGE_uboot-envtools=y +# CONFIG_UBOOT_ENVTOOLS_UBI is not set + +# +# Compression +# +# CONFIG_PACKAGE_bsdtar is not set +# CONFIG_PACKAGE_bzip2 is not set +# CONFIG_PACKAGE_gzip is not set +# CONFIG_PACKAGE_unrar is not set +# CONFIG_PACKAGE_unzip is not set +# CONFIG_PACKAGE_xz-utils is not set +# CONFIG_PACKAGE_zip is not set + +# +# Disc +# +# CONFIG_PACKAGE_blkdiscard is not set +# CONFIG_PACKAGE_blkid is not set +# CONFIG_PACKAGE_cfdisk is not set +# CONFIG_PACKAGE_fdisk is not set +# CONFIG_PACKAGE_findfs is not set +CONFIG_PACKAGE_hd-idle=y +# CONFIG_PACKAGE_hdparm is not set +# CONFIG_PACKAGE_lsblk is not set +# CONFIG_PACKAGE_lvm2 is not set +# CONFIG_PACKAGE_mdadm is not set +# CONFIG_PACKAGE_partx-utils is not set +# CONFIG_PACKAGE_sfdisk is not set +# CONFIG_PACKAGE_wipefs is not set + +# +# Editors +# +# CONFIG_PACKAGE_joe is not set +# CONFIG_PACKAGE_nano is not set +# CONFIG_PACKAGE_vim is not set +# CONFIG_PACKAGE_vim-full is not set +# CONFIG_PACKAGE_vim-fuller is not set +# CONFIG_PACKAGE_vim-help is not set +# CONFIG_PACKAGE_vim-runtime is not set +# CONFIG_PACKAGE_zile is not set + +# +# Encryption +# +# CONFIG_PACKAGE_ccrypt is not set +# CONFIG_PACKAGE_certtool is not set +# CONFIG_PACKAGE_cryptsetup is not set +# CONFIG_PACKAGE_cryptsetup-openssl is not set +# CONFIG_PACKAGE_gnupg is not set +# CONFIG_PACKAGE_gnutls-utils is not set +# CONFIG_PACKAGE_gpgv is not set +# CONFIG_PACKAGE_px5g-mbedtls is not set +# CONFIG_PACKAGE_px5g-standalone is not set +# CONFIG_PACKAGE_stoken is not set + +# +# Filesystem +# +# CONFIG_PACKAGE_acl is not set +# CONFIG_PACKAGE_attr is not set +# CONFIG_PACKAGE_badblocks is not set +# CONFIG_PACKAGE_btrfs-progs is not set +# CONFIG_PACKAGE_chattr is not set +# CONFIG_PACKAGE_debugfs is not set +# CONFIG_PACKAGE_dosfstools is not set +# CONFIG_PACKAGE_dumpe2fs is not set +# CONFIG_PACKAGE_e2freefrag is not set +# CONFIG_PACKAGE_e2fsprogs is not set +# CONFIG_PACKAGE_f2fs-tools is not set +# CONFIG_PACKAGE_f2fsck is not set +# CONFIG_PACKAGE_filefrag is not set +# CONFIG_PACKAGE_fuse-utils is not set +# CONFIG_PACKAGE_hfsfsck is not set +# CONFIG_PACKAGE_lsattr is not set +# CONFIG_PACKAGE_mkf2fs is not set +# CONFIG_PACKAGE_mkhfs is not set +# CONFIG_PACKAGE_ncdu is not set +# CONFIG_PACKAGE_nfs-utils is not set +CONFIG_PACKAGE_ntfs-3g=y +# CONFIG_PACKAGE_NTFS-3G_USE_LIBFUSE is not set +# CONFIG_PACKAGE_ntfs-3g-low is not set +# CONFIG_PACKAGE_ntfs-3g-utils is not set +# CONFIG_PACKAGE_owfs is not set +# CONFIG_PACKAGE_owshell is not set +# CONFIG_PACKAGE_resize2fs is not set +# CONFIG_PACKAGE_squashfs-tools-mksquashfs is not set +# CONFIG_PACKAGE_squashfs-tools-unsquashfs is not set +# CONFIG_PACKAGE_swap-utils is not set +# CONFIG_PACKAGE_sysfsutils is not set +# CONFIG_PACKAGE_tune2fs is not set +# CONFIG_PACKAGE_xfs-fsck is not set +# CONFIG_PACKAGE_xfs-growfs is not set +# CONFIG_PACKAGE_xfs-mkfs is not set + +# +# Image Manipulation +# +# CONFIG_PACKAGE_jpeg-tools is not set +# CONFIG_PACKAGE_tiff-utils is not set + +# +# Luci +# +# CONFIG_PACKAGE_luci-app-haproxy-tcp is not set + +# +# Microcontroller programming +# +# CONFIG_PACKAGE_avrdude is not set +# CONFIG_PACKAGE_dfu-programmer is not set +# CONFIG_PACKAGE_stm32flash is not set + +# +# RTKLIB Suite +# +# CONFIG_PACKAGE_convbin is not set +# CONFIG_PACKAGE_pos2kml is not set +# CONFIG_PACKAGE_rnx2rtkp is not set +# CONFIG_PACKAGE_rtkrcv is not set +# CONFIG_PACKAGE_str2str is not set + +# +# Shells +# +# CONFIG_PACKAGE_bash is not set +# CONFIG_PACKAGE_klish is not set +# CONFIG_PACKAGE_tcsh is not set +# CONFIG_PACKAGE_zsh is not set + +# +# Telephony +# +# CONFIG_PACKAGE_dahdi-cfg is not set +# CONFIG_PACKAGE_dahdi-monitor is not set + +# +# Terminal +# +# CONFIG_PACKAGE_agetty is not set +# CONFIG_PACKAGE_dvtm is not set +# CONFIG_PACKAGE_minicom is not set +# CONFIG_PACKAGE_picocom is not set +# CONFIG_PACKAGE_screen is not set +# CONFIG_PACKAGE_script-utils is not set +# CONFIG_PACKAGE_serialconsole is not set +# CONFIG_PACKAGE_setterm is not set +# CONFIG_PACKAGE_tmux is not set +# CONFIG_PACKAGE_ttyd is not set +# CONFIG_PACKAGE_wall is not set + +# +# Virtualization +# + +# +# Zoneinfo +# +# CONFIG_PACKAGE_zoneinfo-africa is not set +# CONFIG_PACKAGE_zoneinfo-asia is not set +# CONFIG_PACKAGE_zoneinfo-atlantic is not set +# CONFIG_PACKAGE_zoneinfo-australia-nz is not set +# CONFIG_PACKAGE_zoneinfo-core is not set +# CONFIG_PACKAGE_zoneinfo-europe is not set +# CONFIG_PACKAGE_zoneinfo-india is not set +# CONFIG_PACKAGE_zoneinfo-northamerica is not set +# CONFIG_PACKAGE_zoneinfo-pacific is not set +# CONFIG_PACKAGE_zoneinfo-poles is not set +# CONFIG_PACKAGE_zoneinfo-simple is not set +# CONFIG_PACKAGE_zoneinfo-southamerica is not set + +# +# database +# +# CONFIG_PACKAGE_mysql-server is not set +# CONFIG_PACKAGE_pgsql-cli is not set +# CONFIG_PACKAGE_pgsql-cli-extra is not set +# CONFIG_PACKAGE_pgsql-server is not set +# CONFIG_PACKAGE_rrdcgi1 is not set +# CONFIG_PACKAGE_rrdtool1 is not set +# CONFIG_PACKAGE_sqlite3-cli is not set +# CONFIG_PACKAGE_unixodbc-tools is not set +# CONFIG_PACKAGE_adb is not set +# CONFIG_PACKAGE_ap51-flash is not set +# CONFIG_PACKAGE_at is not set +# CONFIG_PACKAGE_bandwidthd is not set +# CONFIG_PACKAGE_bandwidthd-pgsql is not set +# CONFIG_PACKAGE_bandwidthd-php is not set +# CONFIG_PACKAGE_bandwidthd-sqlite is not set +# CONFIG_PACKAGE_banhostlist is not set +# CONFIG_PACKAGE_bc is not set +# CONFIG_PACKAGE_bluelog is not set +# CONFIG_PACKAGE_bluez-daemon is not set +# CONFIG_PACKAGE_bluez-examples is not set +# CONFIG_PACKAGE_bluez-utils is not set +# CONFIG_PACKAGE_bonniexx is not set +# CONFIG_PACKAGE_bsdiff is not set +# CONFIG_PACKAGE_bspatch is not set +# CONFIG_PACKAGE_cal is not set +# CONFIG_PACKAGE_canutils is not set +# CONFIG_PACKAGE_cmdpad is not set +# CONFIG_PACKAGE_coap-client is not set +# CONFIG_PACKAGE_collectd is not set +CONFIG_PACKAGE_coreutils=y +CONFIG_PACKAGE_coreutils-base64=y +# CONFIG_PACKAGE_coreutils-basename is not set +# CONFIG_PACKAGE_coreutils-cat is not set +# CONFIG_PACKAGE_coreutils-chcon is not set +# CONFIG_PACKAGE_coreutils-chgrp is not set +# CONFIG_PACKAGE_coreutils-chmod is not set +# CONFIG_PACKAGE_coreutils-chown is not set +# CONFIG_PACKAGE_coreutils-chroot is not set +# CONFIG_PACKAGE_coreutils-cksum is not set +# CONFIG_PACKAGE_coreutils-comm is not set +# CONFIG_PACKAGE_coreutils-cp is not set +# CONFIG_PACKAGE_coreutils-csplit is not set +# CONFIG_PACKAGE_coreutils-cut is not set +# CONFIG_PACKAGE_coreutils-date is not set +# CONFIG_PACKAGE_coreutils-dd is not set +# CONFIG_PACKAGE_coreutils-dir is not set +# CONFIG_PACKAGE_coreutils-dircolors is not set +# CONFIG_PACKAGE_coreutils-dirname is not set +# CONFIG_PACKAGE_coreutils-du is not set +# CONFIG_PACKAGE_coreutils-echo is not set +# CONFIG_PACKAGE_coreutils-env is not set +# CONFIG_PACKAGE_coreutils-expand is not set +# CONFIG_PACKAGE_coreutils-expr is not set +# CONFIG_PACKAGE_coreutils-factor is not set +# CONFIG_PACKAGE_coreutils-false is not set +# CONFIG_PACKAGE_coreutils-fmt is not set +# CONFIG_PACKAGE_coreutils-fold is not set +# CONFIG_PACKAGE_coreutils-groups is not set +# CONFIG_PACKAGE_coreutils-head is not set +# CONFIG_PACKAGE_coreutils-hostid is not set +# CONFIG_PACKAGE_coreutils-id is not set +# CONFIG_PACKAGE_coreutils-install is not set +# CONFIG_PACKAGE_coreutils-join is not set +# CONFIG_PACKAGE_coreutils-kill is not set +# CONFIG_PACKAGE_coreutils-link is not set +# CONFIG_PACKAGE_coreutils-ln is not set +# CONFIG_PACKAGE_coreutils-logname is not set +# CONFIG_PACKAGE_coreutils-ls is not set +# CONFIG_PACKAGE_coreutils-md5sum is not set +# CONFIG_PACKAGE_coreutils-mkdir is not set +# CONFIG_PACKAGE_coreutils-mkfifo is not set +# CONFIG_PACKAGE_coreutils-mknod is not set +# CONFIG_PACKAGE_coreutils-mktemp is not set +# CONFIG_PACKAGE_coreutils-mv is not set +# CONFIG_PACKAGE_coreutils-nice is not set +# CONFIG_PACKAGE_coreutils-nl is not set +CONFIG_PACKAGE_coreutils-nohup=y +# CONFIG_PACKAGE_coreutils-nproc is not set +# CONFIG_PACKAGE_coreutils-od is not set +# CONFIG_PACKAGE_coreutils-paste is not set +# CONFIG_PACKAGE_coreutils-pathchk is not set +# CONFIG_PACKAGE_coreutils-pinky is not set +# CONFIG_PACKAGE_coreutils-pr is not set +# CONFIG_PACKAGE_coreutils-printenv is not set +# CONFIG_PACKAGE_coreutils-printf is not set +# CONFIG_PACKAGE_coreutils-ptx is not set +# CONFIG_PACKAGE_coreutils-pwd is not set +# CONFIG_PACKAGE_coreutils-readlink is not set +# CONFIG_PACKAGE_coreutils-realpath is not set +# CONFIG_PACKAGE_coreutils-rm is not set +# CONFIG_PACKAGE_coreutils-rmdir is not set +# CONFIG_PACKAGE_coreutils-runcon is not set +# CONFIG_PACKAGE_coreutils-seq is not set +# CONFIG_PACKAGE_coreutils-sha1sum is not set +# CONFIG_PACKAGE_coreutils-sha224sum is not set +# CONFIG_PACKAGE_coreutils-sha256sum is not set +# CONFIG_PACKAGE_coreutils-sha384sum is not set +# CONFIG_PACKAGE_coreutils-sha512sum is not set +# CONFIG_PACKAGE_coreutils-shred is not set +# CONFIG_PACKAGE_coreutils-shuf is not set +# CONFIG_PACKAGE_coreutils-sleep is not set +# CONFIG_PACKAGE_coreutils-sort is not set +# CONFIG_PACKAGE_coreutils-split is not set +# CONFIG_PACKAGE_coreutils-stat is not set +# CONFIG_PACKAGE_coreutils-stdbuf is not set +# CONFIG_PACKAGE_coreutils-stty is not set +# CONFIG_PACKAGE_coreutils-sum is not set +# CONFIG_PACKAGE_coreutils-sync is not set +# CONFIG_PACKAGE_coreutils-tac is not set +# CONFIG_PACKAGE_coreutils-tail is not set +# CONFIG_PACKAGE_coreutils-tee is not set +# CONFIG_PACKAGE_coreutils-test is not set +# CONFIG_PACKAGE_coreutils-timeout is not set +# CONFIG_PACKAGE_coreutils-touch is not set +# CONFIG_PACKAGE_coreutils-tr is not set +# CONFIG_PACKAGE_coreutils-true is not set +# CONFIG_PACKAGE_coreutils-truncate is not set +# CONFIG_PACKAGE_coreutils-tsort is not set +# CONFIG_PACKAGE_coreutils-tty is not set +# CONFIG_PACKAGE_coreutils-uname is not set +# CONFIG_PACKAGE_coreutils-unexpand is not set +# CONFIG_PACKAGE_coreutils-uniq is not set +# CONFIG_PACKAGE_coreutils-unlink is not set +# CONFIG_PACKAGE_coreutils-uptime is not set +# CONFIG_PACKAGE_coreutils-users is not set +# CONFIG_PACKAGE_coreutils-vdir is not set +# CONFIG_PACKAGE_coreutils-wc is not set +# CONFIG_PACKAGE_coreutils-who is not set +# CONFIG_PACKAGE_coreutils-whoami is not set +# CONFIG_PACKAGE_coreutils-yes is not set +# CONFIG_PACKAGE_crelay is not set +# CONFIG_PACKAGE_ct-bugcheck is not set +# CONFIG_PACKAGE_dbus is not set +# CONFIG_PACKAGE_dfu-util is not set +# CONFIG_PACKAGE_dmesg is not set +# CONFIG_PACKAGE_domoticz is not set +# CONFIG_PACKAGE_dropbearconvert is not set +# CONFIG_PACKAGE_dtc is not set +# CONFIG_PACKAGE_dump1090 is not set +# CONFIG_PACKAGE_ecdsautils is not set +# CONFIG_PACKAGE_elektra-kdb is not set +# CONFIG_PACKAGE_evtest is not set +# CONFIG_PACKAGE_extract is not set +# CONFIG_PACKAGE_file is not set +# CONFIG_PACKAGE_findutils-find is not set +# CONFIG_PACKAGE_findutils-locate is not set +# CONFIG_PACKAGE_findutils-xargs is not set +# CONFIG_PACKAGE_flashrom is not set +# CONFIG_PACKAGE_flashrom-pci is not set +# CONFIG_PACKAGE_flashrom-spi is not set +# CONFIG_PACKAGE_flashrom-usb is not set +# CONFIG_PACKAGE_flent-tools is not set +# CONFIG_PACKAGE_flock is not set +# CONFIG_PACKAGE_fritz-caldata is not set +# CONFIG_PACKAGE_fritz-tffs is not set +# CONFIG_PACKAGE_ftdi_eeprom is not set +# CONFIG_PACKAGE_gammu is not set +# CONFIG_PACKAGE_gawk is not set +# CONFIG_PACKAGE_getopt is not set +# CONFIG_PACKAGE_gkermit is not set +# CONFIG_PACKAGE_gpioctl-sysfs is not set +# CONFIG_PACKAGE_gpsd is not set +# CONFIG_PACKAGE_gpsd-clients is not set +# CONFIG_PACKAGE_grep is not set +# CONFIG_PACKAGE_hamlib is not set +# CONFIG_PACKAGE_haserl is not set +# CONFIG_PACKAGE_haveged is not set +# CONFIG_PACKAGE_hub-ctrl is not set +# CONFIG_PACKAGE_hwclock is not set +# CONFIG_PACKAGE_i2c-tools is not set +# CONFIG_PACKAGE_iconv is not set +# CONFIG_PACKAGE_iio-utils is not set +# CONFIG_PACKAGE_io is not set +# CONFIG_PACKAGE_irqbalance is not set +# CONFIG_PACKAGE_iwcap is not set +CONFIG_PACKAGE_iwinfo=y +# CONFIG_PACKAGE_jq is not set +CONFIG_PACKAGE_jshn=y +# CONFIG_PACKAGE_kmod is not set +# CONFIG_PACKAGE_lcd4linux-custom is not set +# CONFIG_PACKAGE_lcdproc-clients is not set +# CONFIG_PACKAGE_lcdproc-drivers is not set +# CONFIG_PACKAGE_lcdproc-server is not set +# CONFIG_PACKAGE_less is not set +# CONFIG_PACKAGE_less-wide is not set +# CONFIG_PACKAGE_libimobiledevice-utils is not set +CONFIG_PACKAGE_libjson-script=y +# CONFIG_PACKAGE_libplist-utils is not set +# CONFIG_PACKAGE_libsysrepo is not set +# CONFIG_PACKAGE_libusbmuxd-utils is not set +# CONFIG_PACKAGE_lm-sensors is not set +# CONFIG_PACKAGE_lm-sensors-detect is not set +# CONFIG_PACKAGE_logger is not set +# CONFIG_PACKAGE_logrotate is not set +# CONFIG_PACKAGE_look is not set +# CONFIG_PACKAGE_losetup is not set +# CONFIG_PACKAGE_lrzsz is not set +# CONFIG_PACKAGE_lsof is not set +# CONFIG_PACKAGE_lxc is not set +# CONFIG_PACKAGE_maccalc is not set +# CONFIG_PACKAGE_macchanger is not set +# CONFIG_PACKAGE_mbtools is not set +# CONFIG_PACKAGE_mc is not set +# CONFIG_PACKAGE_mcookie is not set +# CONFIG_PACKAGE_mmc-utils is not set +# CONFIG_PACKAGE_moreutils is not set +# CONFIG_PACKAGE_mount-utils is not set +# CONFIG_PACKAGE_mpack is not set +# CONFIG_PACKAGE_mt-st is not set +# CONFIG_PACKAGE_namei is not set +# CONFIG_PACKAGE_netopeer2-cli is not set +# CONFIG_PACKAGE_netopeer2-keystored is not set +# CONFIG_PACKAGE_netopeer2-server is not set +# CONFIG_PACKAGE_netwhere is not set +# CONFIG_PACKAGE_oath-toolkit is not set +# CONFIG_PACKAGE_open-plc-utils is not set +# CONFIG_PACKAGE_open2300 is not set +# CONFIG_PACKAGE_openldap-utils is not set +# CONFIG_PACKAGE_openobex is not set +# CONFIG_PACKAGE_openobex-apps is not set +# CONFIG_PACKAGE_openocd is not set +# CONFIG_PACKAGE_opensc-utils is not set +CONFIG_PACKAGE_openssl-util=y +# CONFIG_PACKAGE_openzwave is not set +# CONFIG_PACKAGE_openzwave-config is not set +# CONFIG_PACKAGE_opus-tools is not set +# CONFIG_PACKAGE_owipcalc is not set +# CONFIG_PACKAGE_pciutils is not set +# CONFIG_PACKAGE_pcsc-tools is not set +# CONFIG_PACKAGE_pcscd is not set +# CONFIG_PACKAGE_pps-tools is not set +# CONFIG_PACKAGE_prlimit is not set +# CONFIG_PACKAGE_procps-ng is not set +# CONFIG_PACKAGE_progress is not set +# CONFIG_PACKAGE_prometheus-node-exporter-lua is not set +# CONFIG_PACKAGE_pv is not set +# CONFIG_PACKAGE_qrencode is not set +# CONFIG_PACKAGE_relayctl is not set +# CONFIG_PACKAGE_rename is not set +# CONFIG_PACKAGE_rng-tools is not set +# CONFIG_PACKAGE_rtl-ais is not set +# CONFIG_PACKAGE_rtl-sdr is not set +# CONFIG_PACKAGE_sane-backends is not set +# CONFIG_PACKAGE_sane-daemon is not set +# CONFIG_PACKAGE_sane-frontends is not set +# CONFIG_PACKAGE_shadow-utils is not set +CONFIG_PACKAGE_shellsync=y +# CONFIG_PACKAGE_sispmctl is not set +# CONFIG_PACKAGE_slide-switch is not set +# CONFIG_PACKAGE_smartd is not set +# CONFIG_PACKAGE_smartmontools is not set +# CONFIG_PACKAGE_smstools3 is not set +# CONFIG_PACKAGE_sockread is not set +# CONFIG_PACKAGE_spi-tools is not set +# CONFIG_PACKAGE_spidev-test is not set +# CONFIG_PACKAGE_strace is not set +# CONFIG_PACKAGE_strace_libunwind is not set +# CONFIG_PACKAGE_stress is not set +# CONFIG_PACKAGE_sumo is not set +# CONFIG_PACKAGE_sysrepo is not set +# CONFIG_PACKAGE_sysrepocfg is not set +# CONFIG_PACKAGE_sysrepoctl is not set +# CONFIG_PACKAGE_sysstat is not set +# CONFIG_PACKAGE_tar is not set +# CONFIG_PACKAGE_taskwarrior is not set +# CONFIG_PACKAGE_tracertools is not set +# CONFIG_PACKAGE_tree is not set +# CONFIG_PACKAGE_triggerhappy is not set +# CONFIG_PACKAGE_udns-dnsget is not set +# CONFIG_PACKAGE_udns-ex-rdns is not set +# CONFIG_PACKAGE_udns-rblcheck is not set +# CONFIG_PACKAGE_ugps is not set +# CONFIG_PACKAGE_usb-modeswitch is not set +# CONFIG_PACKAGE_usbmuxd is not set +# CONFIG_PACKAGE_usbreset is not set +# CONFIG_PACKAGE_usbutils is not set +# CONFIG_PACKAGE_uuidd is not set +# CONFIG_PACKAGE_uuidgen is not set +# CONFIG_PACKAGE_uvcdynctrl is not set +# CONFIG_PACKAGE_v4l-utils is not set +# CONFIG_PACKAGE_view1090 is not set +# CONFIG_PACKAGE_watchcat is not set +# CONFIG_PACKAGE_whereis is not set +# CONFIG_PACKAGE_wifitoggle is not set +# CONFIG_PACKAGE_xsltproc is not set +# CONFIG_PACKAGE_xxd is not set +# CONFIG_PACKAGE_yanglint is not set +# CONFIG_PACKAGE_yara is not set +# CONFIG_PACKAGE_yunbridge is not set + +# +# Xorg +# + +# +# font-utils +# +# CONFIG_PACKAGE_fontconfig is not set diff --git a/arjj.config b/arjj.config new file mode 100644 index 000000000..3cb285785 --- /dev/null +++ b/arjj.config @@ -0,0 +1,5117 @@ +# +# Automatically generated file; DO NOT EDIT. +# LEDE Configuration +# +CONFIG_MODULES=y +CONFIG_HAVE_DOT_CONFIG=y +# CONFIG_TARGET_sunxi is not set +# CONFIG_TARGET_apm821xx is not set +# CONFIG_TARGET_ath25 is not set +CONFIG_TARGET_ar71xx=y +# CONFIG_TARGET_at91 is not set +# CONFIG_TARGET_brcm2708 is not set +# CONFIG_TARGET_bcm53xx is not set +# CONFIG_TARGET_brcm47xx is not set +# CONFIG_TARGET_brcm63xx is not set +# CONFIG_TARGET_cns3xxx is not set +# CONFIG_TARGET_octeon is not set +# CONFIG_TARGET_gemini is not set +# CONFIG_TARGET_mpc85xx is not set +# CONFIG_TARGET_imx6 is not set +# CONFIG_TARGET_mxs is not set +# CONFIG_TARGET_adm8668 is not set +# CONFIG_TARGET_adm5120 is not set +# CONFIG_TARGET_xburst is not set +# CONFIG_TARGET_ixp4xx is not set +# CONFIG_TARGET_lantiq is not set +# CONFIG_TARGET_malta is not set +# CONFIG_TARGET_pistachio is not set +# CONFIG_TARGET_mvebu is not set +# CONFIG_TARGET_kirkwood is not set +# CONFIG_TARGET_mediatek is not set +# CONFIG_TARGET_ramips is not set +# CONFIG_TARGET_rb532 is not set +# CONFIG_TARGET_mcs814x is not set +# CONFIG_TARGET_layerscape is not set +# CONFIG_TARGET_oxnas is not set +# CONFIG_TARGET_armvirt is not set +# CONFIG_TARGET_ipq806x is not set +# CONFIG_TARGET_au1000 is not set +# CONFIG_TARGET_arc770 is not set +# CONFIG_TARGET_archs38 is not set +# CONFIG_TARGET_ar7 is not set +# CONFIG_TARGET_omap is not set +# CONFIG_TARGET_uml is not set +# CONFIG_TARGET_zynq is not set +# CONFIG_TARGET_x86 is not set +CONFIG_TARGET_ar71xx_generic=y +# CONFIG_TARGET_ar71xx_nand is not set +# CONFIG_TARGET_ar71xx_mikrotik is not set +# CONFIG_TARGET_MULTI_PROFILE is not set +# CONFIG_TARGET_ar71xx_generic_Default is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_carambola2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_lima is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ALFAAP120C is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ap121f is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ALFAAP96 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_HORNETUB is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_HORNETUBx2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ALFANX is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TUBE2H16M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TUBE2H8M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_fritz300e is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_sc1750 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_sc300m is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_sc450 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_c-55 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ALL0258N is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ALL0305 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ALL0315N is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_antminer-s1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_antminer-s3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_antrouter-r1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_arduino-yun is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP121_16M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP121_8M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP132 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP135 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP136_010 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP136_020 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP96 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DB120 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_PB42 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_PB44 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_A02RBW300N is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_BXU2000N2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_F9K1115V2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_bhr-4grv2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WHRG301N is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WHRHPG300N is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WHRHPGN is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WLAEAG300N is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WZR450HP2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WZR600DHP is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WZRHPAG300H is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WZRHPG300NH is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WZRHPG300NH2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WZRHPG450H is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cf-e316n-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cf-e320n-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cf-e355ac is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cf-e380ac-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cf-e380ac-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cf-e520n is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cf-e530n is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WP543_16M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WP543_4M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WP543_8M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WPE72_16M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WPE72_4M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WPE72_8M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wpj342 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wpj344 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wpj531 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wpj558 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wpj563 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_dap-2695-a1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DGL5500A1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DHP1565A1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR505A1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR600A1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR601A1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR601B1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR615C1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR615E1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR615E4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR615I1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR615I3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR825B1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR825C1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DIR835A1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_dir-869-a1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_EBR2310C1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_dragino2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_el-m150 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_el-mini is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ew-dorin is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ew-dorin-router is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_EAP300V2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ens202ext is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_EPG5000 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ESR1750 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ESR900 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_FR54RTR is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_gl-inet-6408A-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_gl-inet-6416A-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_gl-domino is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_gl-ar150 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_gl-ar300 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_gl-ar300m is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_gl-mifi is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_gl-usb150 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_minibox-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_oolite is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_hiwifi-hc6361 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WRT160NL is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WRT400N is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_mr12 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_mr16 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_mc-mac1200r is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_mw4530r-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_smart-300 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WNDAP360 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wndr3700 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wndr3700v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wndr3800 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wndr3800ch is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wndrmac is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wndrmacv2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_REALWNR1000V2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WNR1000V2_VC is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WNR2000 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WNR2000V3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WNR2000V4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WNR2200 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_REALWNR612V2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WPN824N is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_omy-g1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_omy-x1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_N150R is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_onion-omega is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_som9331 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_A60 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_MR1750 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_MR600 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_MR900 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_OM2P is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_OM5PAC is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_OM5P is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cpe505n is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_r602n is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_pqi-air-pen is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_MZKW04NU is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_MZKW300NH is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cap324 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cap324-nocloud is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cr3000-nocloud is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cr3000 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cr5000-nocloud is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cr5000 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_DLRTDEV01 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_qihoo-c301 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP143_16M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP143_8M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP147_010 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_AP152_16M is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ap531b0 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_rnx-n360rt is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_CAP4200AG is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_EAP7660D is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_WLR8100 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_bsb is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_archer-c25-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_archer-c5-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_archer-c59-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_archer-c7-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_archer-c7-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_archer-c7-v2-il is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr7500-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_archer-c7-v4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cpe210-220-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cpe510-520-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_eap120-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_re450-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr10u-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr11u-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr11u-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr12u-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr13u-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr3020-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr3040-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr3040-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr3220-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr3220-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr3420-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr3420-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-mr6400-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa701nd-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa701nd-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa7210n-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa730re-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa750re-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa7510n-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa801nd-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa801nd-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa801nd-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa830re-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa830re-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa850re-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa850re-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa855re-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa860re-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa901nd-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa901nd-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa901nd-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wa901nd-v4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr3320-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr3500-v1 is not set +CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr3600-v1=y +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr4300-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr4300-v1-il is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr4310-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr4900-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wdr6500-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wpa8630-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr1041n-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr1043nd-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr1043nd-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr1043nd-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr1043nd-v4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr2543-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr703n-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr710n-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr710n-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr710n-v2.1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr720n-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr720n-v4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr740n-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr740n-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr740n-v4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr740n-v5 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr740n-v6 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr741nd-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr741nd-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr741nd-v4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr741nd-v5 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr743nd-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr743nd-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr802n-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr802n-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr810n-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr840n-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr840n-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v1.5 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v10 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v11 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v12 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v5 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v7 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v8 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr841-v9 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr842n-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr842n-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr842n-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr843nd-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr847n-v8 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr940n-v4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr941nd-v2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr941nd-v3 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr941nd-v4 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr941nd-v5 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr941nd-v6 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tl-wr941nd-v6-cn is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wbs210-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wbs510-v1 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TEW632BRP is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TEW652BRP_FW is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TEW652BRP_RECOVERY is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TEW673GRU is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TEW712BR is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TEW732BR is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_TEW823DRU is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_tellstick-znet-lite is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-air-gateway is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-air-gateway-pro is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-airrouter is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-bullet-m is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-ls-sr71 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-loco-m-xw is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-nano-m-xw is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-nano-m is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_rw2458n is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-rocket-m-ti is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-rocket-m-xw is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-rocket-m is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-rs is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-rspro is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-unifi is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-unifiac-lite is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-unifiac-mesh is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-unifiac-pro is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubnt-unifi-outdoor is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ubdev01 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_wrtnode2q is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_dr531 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_weio is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_mynet-n600 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_mynet-n750 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_MYNETREXT is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ap90q is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cpe830 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_cpe870 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_sr3200 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_xd3200 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_zbt-we1526 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ZCN1523H28 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_ZCN1523H516 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_NBG_460N_550N_550NH is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_NBG6616 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_dLAN_Hotspot is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_dLAN_pro_1200_ac is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_dLAN_pro_500_wp is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_JA76PF is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_JA76PF2 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_JWAP003 is not set +# CONFIG_TARGET_ar71xx_generic_DEVICE_jwap230 is not set +CONFIG_HAS_SUBTARGETS=y +CONFIG_HAS_DEVICES=y +CONFIG_TARGET_BOARD="ar71xx" +CONFIG_TARGET_SUBTARGET="generic" +CONFIG_TARGET_PROFILE="DEVICE_tl-wdr3600-v1" +CONFIG_TARGET_ARCH_PACKAGES="mips_24kc" +CONFIG_DEFAULT_TARGET_OPTIMIZATION="-Os -pipe -mno-branch-likely -mips32r2 -mtune=24kc" +CONFIG_CPU_TYPE="24kc" +CONFIG_LINUX_4_4=y +CONFIG_DEFAULT_automount=y +CONFIG_DEFAULT_base-files=y +CONFIG_DEFAULT_block-mount=y +CONFIG_DEFAULT_busybox=y +CONFIG_DEFAULT_default-settings=y +CONFIG_DEFAULT_dnsmasq-full=y +CONFIG_DEFAULT_dropbear=y +CONFIG_DEFAULT_firewall=y +CONFIG_DEFAULT_fstools=y +CONFIG_DEFAULT_ip6tables=y +CONFIG_DEFAULT_ipset-lists=y +CONFIG_DEFAULT_iptables=y +CONFIG_DEFAULT_iptables-mod-nat-extra=y +CONFIG_DEFAULT_iwinfo=y +CONFIG_DEFAULT_kmod-ath9k=y +CONFIG_DEFAULT_kmod-gpio-button-hotplug=y +CONFIG_DEFAULT_kmod-macvlan=y +CONFIG_DEFAULT_kmod-nf-nathelper=y +CONFIG_DEFAULT_kmod-nf-nathelper-extra=y +CONFIG_DEFAULT_kmod-usb-core=y +CONFIG_DEFAULT_kmod-usb-ledtrig-usbport=y +CONFIG_DEFAULT_kmod-usb2=y +CONFIG_DEFAULT_libc=y +CONFIG_DEFAULT_libgcc=y +CONFIG_DEFAULT_logd=y +CONFIG_DEFAULT_luci=y +CONFIG_DEFAULT_luci-app-adbyby-plus=y +CONFIG_DEFAULT_luci-app-autoreboot=y +CONFIG_DEFAULT_luci-app-ddns=y +CONFIG_DEFAULT_luci-app-filetransfer=y +CONFIG_DEFAULT_luci-app-ipsec-vpnd=y +CONFIG_DEFAULT_luci-app-nlbwmon=y +CONFIG_DEFAULT_luci-app-pptp-server=y +CONFIG_DEFAULT_luci-app-sfe=y +CONFIG_DEFAULT_luci-app-shadowsocksr-pro=y +CONFIG_DEFAULT_luci-app-sqm=y +CONFIG_DEFAULT_luci-app-upnp=y +CONFIG_DEFAULT_luci-app-usb-printer=y +CONFIG_DEFAULT_luci-app-vlmcsd=y +CONFIG_DEFAULT_luci-app-vsftpd=y +CONFIG_DEFAULT_luci-app-wifischedule=y +CONFIG_DEFAULT_luci-app-wol=y +CONFIG_DEFAULT_mtd=y +CONFIG_DEFAULT_netifd=y +CONFIG_DEFAULT_opkg=y +CONFIG_DEFAULT_ppp=y +CONFIG_DEFAULT_ppp-mod-pppoe=y +CONFIG_DEFAULT_swconfig=y +CONFIG_DEFAULT_uboot-envtools=y +CONFIG_DEFAULT_uci=y +CONFIG_DEFAULT_uclient-fetch=y +CONFIG_DEFAULT_wpad-mini=y +CONFIG_AUDIO_SUPPORT=y +CONFIG_GPIO_SUPPORT=y +CONFIG_PCI_SUPPORT=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_GADGET_SUPPORT=y +CONFIG_BIG_ENDIAN=y +CONFIG_USES_DEVICETREE=y +CONFIG_USES_SQUASHFS=y +CONFIG_HAS_MIPS16=y +CONFIG_mips=y +CONFIG_ARCH="mips" + +# +# Target Images +# +# CONFIG_TARGET_ROOTFS_INITRAMFS is not set +CONFIG_EXTERNAL_CPIO="" + +# +# Root filesystem archives +# +# CONFIG_TARGET_ROOTFS_CPIOGZ is not set +# CONFIG_TARGET_ROOTFS_TARGZ is not set + +# +# Root filesystem images +# +# CONFIG_TARGET_ROOTFS_EXT4FS is not set +CONFIG_TARGET_ROOTFS_SQUASHFS=y +CONFIG_TARGET_SQUASHFS_BLOCK_SIZE=1024 +CONFIG_TARGET_UBIFS_FREE_SPACE_FIXUP=y +CONFIG_TARGET_UBIFS_JOURNAL_SIZE="" + +# +# Image Options +# + +# +# Global build settings +# +# CONFIG_ALL_NONSHARED is not set +# CONFIG_ALL_KMODS is not set +# CONFIG_ALL is not set +# CONFIG_BUILDBOT is not set +CONFIG_SIGNED_PACKAGES=y + +# +# General build options +# +# CONFIG_DISPLAY_SUPPORT is not set +CONFIG_BUILD_PATENTED=y +# CONFIG_BUILD_NLS is not set +CONFIG_SHADOW_PASSWORDS=y +# CONFIG_CLEAN_IPKG is not set +# CONFIG_INCLUDE_CONFIG is not set +# CONFIG_COLLECT_KERNEL_DEBUG is not set + +# +# Kernel build options +# +CONFIG_KERNEL_BUILD_USER="" +CONFIG_KERNEL_BUILD_DOMAIN="" +CONFIG_KERNEL_PRINTK=y +CONFIG_KERNEL_CRASHLOG=y +CONFIG_KERNEL_SWAP=y +CONFIG_KERNEL_DEBUG_FS=y +# CONFIG_KERNEL_PERF_EVENTS is not set +# CONFIG_KERNEL_PROFILING is not set +# CONFIG_KERNEL_KALLSYMS is not set +# CONFIG_KERNEL_FTRACE is not set +CONFIG_KERNEL_DEBUG_KERNEL=y +CONFIG_KERNEL_DEBUG_INFO=y +# CONFIG_KERNEL_DYNAMIC_DEBUG is not set +# CONFIG_KERNEL_KPROBES is not set +# CONFIG_KERNEL_AIO is not set +# CONFIG_KERNEL_FHANDLE is not set +# CONFIG_KERNEL_FANOTIFY is not set +# CONFIG_KERNEL_BLK_DEV_BSG is not set +CONFIG_KERNEL_MAGIC_SYSRQ=y +# CONFIG_KERNEL_DEBUG_PINCTRL is not set +# CONFIG_KERNEL_DEBUG_GPIO is not set +CONFIG_KERNEL_COREDUMP=y +CONFIG_KERNEL_ELF_CORE=y +# CONFIG_KERNEL_PROVE_LOCKING is not set +CONFIG_KERNEL_PRINTK_TIME=y +# CONFIG_KERNEL_SLABINFO is not set +# CONFIG_KERNEL_PROC_PAGE_MONITOR is not set +CONFIG_KERNEL_RELAY=y +# CONFIG_KERNEL_KEXEC is not set +# CONFIG_USE_RFKILL is not set +# CONFIG_USE_SPARSE is not set +# CONFIG_KERNEL_DEVTMPFS is not set +# CONFIG_KERNEL_KEYS is not set +# CONFIG_KERNEL_CGROUPS is not set +# CONFIG_KERNEL_NAMESPACES is not set +# CONFIG_KERNEL_LXC_MISC is not set +# CONFIG_KERNEL_SECCOMP_FILTER is not set +# CONFIG_KERNEL_SECCOMP is not set +CONFIG_KERNEL_IPV6=y +CONFIG_KERNEL_IPV6_MULTIPLE_TABLES=y +CONFIG_KERNEL_IPV6_SUBTREES=y +CONFIG_KERNEL_IPV6_MROUTE=y +# CONFIG_KERNEL_IPV6_PIMSM_V2 is not set +# CONFIG_KERNEL_IP_PNP is not set + +# +# Filesystem ACL and attr support options +# +# CONFIG_USE_FS_ACL_ATTR is not set +# CONFIG_KERNEL_FS_POSIX_ACL is not set +# CONFIG_KERNEL_BTRFS_FS_POSIX_ACL is not set +# CONFIG_KERNEL_EXT4_FS_POSIX_ACL is not set +# CONFIG_KERNEL_F2FS_FS_POSIX_ACL is not set +# CONFIG_KERNEL_JFFS2_FS_POSIX_ACL is not set +# CONFIG_KERNEL_TMPFS_POSIX_ACL is not set +# CONFIG_KERNEL_CIFS_ACL is not set +# CONFIG_KERNEL_HFS_FS_POSIX_ACL is not set +# CONFIG_KERNEL_HFSPLUG_FS_POSIX_ACL is not set +# CONFIG_KERNEL_NFS_ACL_SUPPORT is not set +# CONFIG_KERNEL_NFS_V3_ACL_SUPPORT is not set +# CONFIG_KERNEL_NFSD_V2_ACL_SUPPORT is not set +# CONFIG_KERNEL_NFSD_V3_ACL_SUPPORT is not set +# CONFIG_KERNEL_REISER_FS_POSIX_ACL is not set +# CONFIG_KERNEL_XFS_POSIX_ACL is not set +# CONFIG_KERNEL_JFS_POSIX_ACL is not set +# CONFIG_KERNEL_DEVMEM is not set +# CONFIG_KERNEL_DEVKMEM is not set + +# +# Package build options +# +# CONFIG_DEBUG is not set +CONFIG_IPV6=y + +# +# Stripping options +# +# CONFIG_NO_STRIP is not set +# CONFIG_USE_STRIP is not set +CONFIG_USE_SSTRIP=y +# CONFIG_STRIP_KERNEL_EXPORTS is not set +# CONFIG_USE_MKLIBS is not set +CONFIG_USE_UCLIBCXX=y +# CONFIG_USE_LIBSTDCXX is not set + +# +# Hardening build options +# +CONFIG_PKG_CHECK_FORMAT_SECURITY=y +# CONFIG_PKG_CC_STACKPROTECTOR_NONE is not set +CONFIG_PKG_CC_STACKPROTECTOR_REGULAR=y +# CONFIG_KERNEL_CC_STACKPROTECTOR_NONE is not set +CONFIG_KERNEL_CC_STACKPROTECTOR_REGULAR=y +# CONFIG_KERNEL_CC_STACKPROTECTOR_STRONG is not set +# CONFIG_PKG_FORTIFY_SOURCE_NONE is not set +CONFIG_PKG_FORTIFY_SOURCE_1=y +# CONFIG_PKG_FORTIFY_SOURCE_2 is not set +# CONFIG_PKG_RELRO_NONE is not set +# CONFIG_PKG_RELRO_PARTIAL is not set +CONFIG_PKG_RELRO_FULL=y +# CONFIG_DEVEL is not set +# CONFIG_BROKEN is not set +CONFIG_BINARY_FOLDER="" +CONFIG_DOWNLOAD_FOLDER="" +CONFIG_LOCALMIRROR="" +CONFIG_AUTOREBUILD=y +# CONFIG_AUTOREMOVE is not set +CONFIG_BUILD_SUFFIX="" +CONFIG_TARGET_ROOTFS_DIR="" +# CONFIG_CCACHE is not set +CONFIG_EXTERNAL_KERNEL_TREE="" +CONFIG_KERNEL_GIT_CLONE_URI="" +CONFIG_EXTRA_OPTIMIZATION="-fno-caller-saves -fno-plt" +CONFIG_TARGET_OPTIMIZATION="-Os -pipe -mno-branch-likely -mips32r2 -mtune=24kc" +CONFIG_SOFT_FLOAT=y +CONFIG_USE_MIPS16=y +# CONFIG_EXTRA_TARGET_ARCH is not set +CONFIG_EXTRA_BINUTILS_CONFIG_OPTIONS="" +CONFIG_EXTRA_GCC_CONFIG_OPTIONS="" +# CONFIG_SJLJ_EXCEPTIONS is not set +# CONFIG_INSTALL_LIBGCJ is not set +# CONFIG_INSTALL_GFORTRAN is not set +CONFIG_GDB=y +CONFIG_USE_MUSL=y +CONFIG_BINUTILS_VERSION_2_28=y +CONFIG_BINUTILS_VERSION="2.28" +CONFIG_GCC_VERSION="5.4.0" +CONFIG_LIBC="musl" +CONFIG_TARGET_SUFFIX="musl" +# CONFIG_IB is not set +# CONFIG_SDK is not set +# CONFIG_MAKE_TOOLCHAIN is not set +# CONFIG_IMAGEOPT is not set +# CONFIG_PREINITOPT is not set +CONFIG_TARGET_PREINIT_SUPPRESS_STDERR=y +# CONFIG_TARGET_PREINIT_DISABLE_FAILSAFE is not set +CONFIG_TARGET_PREINIT_TIMEOUT=2 +# CONFIG_TARGET_PREINIT_SHOW_NETMSG is not set +# CONFIG_TARGET_PREINIT_SUPPRESS_FAILSAFE_NETMSG is not set +CONFIG_TARGET_PREINIT_IFNAME="" +CONFIG_TARGET_PREINIT_IP="192.168.1.1" +CONFIG_TARGET_PREINIT_NETMASK="255.255.255.0" +CONFIG_TARGET_PREINIT_BROADCAST="192.168.1.255" +# CONFIG_INITOPT is not set +CONFIG_TARGET_INIT_PATH="/usr/sbin:/usr/bin:/sbin:/bin" +CONFIG_TARGET_INIT_ENV="" +CONFIG_TARGET_INIT_CMD="/sbin/init" +CONFIG_TARGET_INIT_SUPPRESS_STDERR=y +# CONFIG_VERSIONOPT is not set +CONFIG_PER_FEED_REPO=y +CONFIG_PER_FEED_REPO_ADD_DISABLED=y +CONFIG_PER_FEED_REPO_ADD_COMMENTED=y +CONFIG_FEED_packages=y +CONFIG_FEED_luci=y +CONFIG_FEED_routing=y +CONFIG_FEED_telephony=y + +# +# Base system +# +CONFIG_PACKAGE_base-files=y +CONFIG_PACKAGE_block-mount=y +# CONFIG_PACKAGE_blockd is not set +# CONFIG_PACKAGE_bridge is not set +CONFIG_PACKAGE_busybox=y +# CONFIG_BUSYBOX_CUSTOM is not set +CONFIG_BUSYBOX_DEFAULT_HAVE_DOT_CONFIG=y +# CONFIG_BUSYBOX_DEFAULT_DESKTOP is not set +# CONFIG_BUSYBOX_DEFAULT_EXTRA_COMPAT is not set +# CONFIG_BUSYBOX_DEFAULT_FEDORA_COMPAT is not set +CONFIG_BUSYBOX_DEFAULT_INCLUDE_SUSv2=y +# CONFIG_BUSYBOX_DEFAULT_USE_PORTABLE_CODE is not set +CONFIG_BUSYBOX_DEFAULT_PLATFORM_LINUX=y +CONFIG_BUSYBOX_DEFAULT_SHOW_USAGE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VERBOSE_USAGE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_COMPRESS_USAGE=y +# CONFIG_BUSYBOX_DEFAULT_BUSYBOX is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INSTALLER is not set +# CONFIG_BUSYBOX_DEFAULT_INSTALL_NO_USR is not set +# CONFIG_BUSYBOX_DEFAULT_PAM is not set +CONFIG_BUSYBOX_DEFAULT_LONG_OPTS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_DEVPTS=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CLEAN_UP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UTMP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_WTMP is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_PIDFILE=y +CONFIG_BUSYBOX_DEFAULT_PID_FILE_PATH="/var/run" +CONFIG_BUSYBOX_DEFAULT_FEATURE_SUID=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SUID_CONFIG is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SUID_CONFIG_QUIET is not set +# CONFIG_BUSYBOX_DEFAULT_SELINUX is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_PREFER_APPLETS=y +CONFIG_BUSYBOX_DEFAULT_BUSYBOX_EXEC_PATH="/proc/self/exe" +CONFIG_BUSYBOX_DEFAULT_FEATURE_SYSLOG=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HAVE_RPC is not set +# CONFIG_BUSYBOX_DEFAULT_STATIC is not set +# CONFIG_BUSYBOX_DEFAULT_PIE is not set +# CONFIG_BUSYBOX_DEFAULT_NOMMU is not set +# CONFIG_BUSYBOX_DEFAULT_BUILD_LIBBUSYBOX is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INDIVIDUAL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SHARED_BUSYBOX is not set +CONFIG_BUSYBOX_DEFAULT_LFS=y +CONFIG_BUSYBOX_DEFAULT_CROSS_COMPILER_PREFIX="" +CONFIG_BUSYBOX_DEFAULT_SYSROOT="" +CONFIG_BUSYBOX_DEFAULT_EXTRA_CFLAGS="" +CONFIG_BUSYBOX_DEFAULT_EXTRA_LDFLAGS="" +CONFIG_BUSYBOX_DEFAULT_EXTRA_LDLIBS="" +CONFIG_BUSYBOX_DEFAULT_INSTALL_APPLET_SYMLINKS=y +# CONFIG_BUSYBOX_DEFAULT_INSTALL_APPLET_HARDLINKS is not set +# CONFIG_BUSYBOX_DEFAULT_INSTALL_APPLET_SCRIPT_WRAPPERS is not set +# CONFIG_BUSYBOX_DEFAULT_INSTALL_APPLET_DONT is not set +# CONFIG_BUSYBOX_DEFAULT_INSTALL_SH_APPLET_SYMLINK is not set +# CONFIG_BUSYBOX_DEFAULT_INSTALL_SH_APPLET_HARDLINK is not set +# CONFIG_BUSYBOX_DEFAULT_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set +CONFIG_BUSYBOX_DEFAULT_PREFIX="./_install" +# CONFIG_BUSYBOX_DEFAULT_DEBUG is not set +# CONFIG_BUSYBOX_DEFAULT_DEBUG_PESSIMIZE is not set +# CONFIG_BUSYBOX_DEFAULT_DEBUG_SANITIZE is not set +# CONFIG_BUSYBOX_DEFAULT_UNIT_TEST is not set +# CONFIG_BUSYBOX_DEFAULT_WERROR is not set +CONFIG_BUSYBOX_DEFAULT_NO_DEBUG_LIB=y +# CONFIG_BUSYBOX_DEFAULT_DMALLOC is not set +# CONFIG_BUSYBOX_DEFAULT_EFENCE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_USE_BSS_TAIL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_RTMINMAX is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_BUFFERS_USE_MALLOC is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_BUFFERS_GO_ON_STACK=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_BUFFERS_GO_IN_BSS is not set +CONFIG_BUSYBOX_DEFAULT_PASSWORD_MINLEN=6 +CONFIG_BUSYBOX_DEFAULT_MD5_SMALL=1 +CONFIG_BUSYBOX_DEFAULT_SHA3_SMALL=1 +CONFIG_BUSYBOX_DEFAULT_FEATURE_FAST_TOP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_ETC_NETWORKS is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_EDITING=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_EDITING_MAX_LEN=512 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_EDITING_VI is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_EDITING_HISTORY=256 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_EDITING_SAVEHISTORY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_EDITING_SAVE_ON_EXIT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_REVERSE_SEARCH is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_TAB_COMPLETION=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_USERNAME_COMPLETION is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_EDITING_FANCY_PROMPT=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_EDITING_ASK_TERMINAL is not set +# CONFIG_BUSYBOX_DEFAULT_LOCALE_SUPPORT is not set +# CONFIG_BUSYBOX_DEFAULT_UNICODE_SUPPORT is not set +# CONFIG_BUSYBOX_DEFAULT_UNICODE_USING_LOCALE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHECK_UNICODE_IN_ENV is not set +CONFIG_BUSYBOX_DEFAULT_SUBST_WCHAR=0 +CONFIG_BUSYBOX_DEFAULT_LAST_SUPPORTED_WCHAR=0 +# CONFIG_BUSYBOX_DEFAULT_UNICODE_COMBINING_WCHARS is not set +# CONFIG_BUSYBOX_DEFAULT_UNICODE_WIDE_WCHARS is not set +# CONFIG_BUSYBOX_DEFAULT_UNICODE_BIDI_SUPPORT is not set +# CONFIG_BUSYBOX_DEFAULT_UNICODE_NEUTRAL_TABLE is not set +# CONFIG_BUSYBOX_DEFAULT_UNICODE_PRESERVE_BROKEN is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_NON_POSIX_CP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VERBOSE_CP_MESSAGE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_USE_SENDFILE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_COPYBUF_KB=4 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SKIP_ROOTFS is not set +# CONFIG_BUSYBOX_DEFAULT_MONOTONIC_SYSCALL is not set +CONFIG_BUSYBOX_DEFAULT_IOCTL_HEX2STR_ERROR=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HWIB is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SEAMLESS_XZ is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SEAMLESS_LZMA is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SEAMLESS_BZ2 is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_SEAMLESS_GZ=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SEAMLESS_Z is not set +# CONFIG_BUSYBOX_DEFAULT_AR is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_AR_LONG_FILENAMES is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_AR_CREATE is not set +# CONFIG_BUSYBOX_DEFAULT_UNCOMPRESS is not set +CONFIG_BUSYBOX_DEFAULT_GUNZIP=y +CONFIG_BUSYBOX_DEFAULT_ZCAT=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_GUNZIP_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_BUNZIP2=y +CONFIG_BUSYBOX_DEFAULT_BZCAT=y +# CONFIG_BUSYBOX_DEFAULT_UNLZMA is not set +# CONFIG_BUSYBOX_DEFAULT_LZCAT is not set +# CONFIG_BUSYBOX_DEFAULT_LZMA is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LZMA_FAST is not set +# CONFIG_BUSYBOX_DEFAULT_UNXZ is not set +# CONFIG_BUSYBOX_DEFAULT_XZCAT is not set +# CONFIG_BUSYBOX_DEFAULT_XZ is not set +# CONFIG_BUSYBOX_DEFAULT_BZIP2 is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_BZIP2_DECOMPRESS=y +# CONFIG_BUSYBOX_DEFAULT_CPIO is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CPIO_O is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CPIO_P is not set +# CONFIG_BUSYBOX_DEFAULT_DPKG is not set +# CONFIG_BUSYBOX_DEFAULT_DPKG_DEB is not set +CONFIG_BUSYBOX_DEFAULT_GZIP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_GZIP_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_GZIP_FAST=0 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_GZIP_LEVELS is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_GZIP_DECOMPRESS=y +# CONFIG_BUSYBOX_DEFAULT_LZOP is not set +# CONFIG_BUSYBOX_DEFAULT_UNLZOP is not set +# CONFIG_BUSYBOX_DEFAULT_LZOPCAT is not set +# CONFIG_BUSYBOX_DEFAULT_LZOP_COMPR_HIGH is not set +# CONFIG_BUSYBOX_DEFAULT_RPM is not set +# CONFIG_BUSYBOX_DEFAULT_RPM2CPIO is not set +CONFIG_BUSYBOX_DEFAULT_TAR=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_CREATE=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_AUTODETECT is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_FROM=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_GNU_EXTENSIONS=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_TO_COMMAND is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_UNAME_GNAME is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_NOPRESERVE_TIME is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TAR_SELINUX is not set +# CONFIG_BUSYBOX_DEFAULT_UNZIP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UNZIP_CDF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UNZIP_BZIP2 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UNZIP_LZMA is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UNZIP_XZ is not set +CONFIG_BUSYBOX_DEFAULT_BASENAME=y +CONFIG_BUSYBOX_DEFAULT_CAT=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CATV is not set +CONFIG_BUSYBOX_DEFAULT_CHGRP=y +CONFIG_BUSYBOX_DEFAULT_CHMOD=y +CONFIG_BUSYBOX_DEFAULT_CHOWN=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHOWN_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_CHROOT=y +# CONFIG_BUSYBOX_DEFAULT_CKSUM is not set +# CONFIG_BUSYBOX_DEFAULT_COMM is not set +CONFIG_BUSYBOX_DEFAULT_CP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CP_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_CUT=y +CONFIG_BUSYBOX_DEFAULT_DATE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_DATE_ISOFMT=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DATE_NANO is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DATE_COMPAT is not set +CONFIG_BUSYBOX_DEFAULT_DD=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_DD_SIGNAL_HANDLING=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DD_THIRD_STATUS_LINE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_DD_IBS_OBS=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DD_STATUS is not set +CONFIG_BUSYBOX_DEFAULT_DF=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DF_FANCY is not set +CONFIG_BUSYBOX_DEFAULT_DIRNAME=y +# CONFIG_BUSYBOX_DEFAULT_DOS2UNIX is not set +# CONFIG_BUSYBOX_DEFAULT_UNIX2DOS is not set +CONFIG_BUSYBOX_DEFAULT_DU=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y +CONFIG_BUSYBOX_DEFAULT_ECHO=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FANCY_ECHO=y +CONFIG_BUSYBOX_DEFAULT_ENV=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_ENV_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_EXPAND is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_EXPAND_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_UNEXPAND is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UNEXPAND_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_EXPR=y +CONFIG_BUSYBOX_DEFAULT_EXPR_MATH_SUPPORT_64=y +# CONFIG_BUSYBOX_DEFAULT_FACTOR is not set +CONFIG_BUSYBOX_DEFAULT_FALSE=y +# CONFIG_BUSYBOX_DEFAULT_FOLD is not set +CONFIG_BUSYBOX_DEFAULT_FSYNC=y +CONFIG_BUSYBOX_DEFAULT_HEAD=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FANCY_HEAD=y +# CONFIG_BUSYBOX_DEFAULT_HOSTID is not set +CONFIG_BUSYBOX_DEFAULT_ID=y +# CONFIG_BUSYBOX_DEFAULT_GROUPS is not set +# CONFIG_BUSYBOX_DEFAULT_INSTALL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INSTALL_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_LINK is not set +CONFIG_BUSYBOX_DEFAULT_LN=y +# CONFIG_BUSYBOX_DEFAULT_LOGNAME is not set +CONFIG_BUSYBOX_DEFAULT_LS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_FILETYPES=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_FOLLOWLINKS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_RECURSIVE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_WIDTH=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_SORTFILES=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_TIMESTAMPS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_USERNAME=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_COLOR=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LS_COLOR_IS_DEFAULT=y +CONFIG_BUSYBOX_DEFAULT_MD5SUM=y +# CONFIG_BUSYBOX_DEFAULT_SHA1SUM is not set +CONFIG_BUSYBOX_DEFAULT_SHA256SUM=y +# CONFIG_BUSYBOX_DEFAULT_SHA512SUM is not set +# CONFIG_BUSYBOX_DEFAULT_SHA3SUM is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_MD5_SHA1_SUM_CHECK=y +CONFIG_BUSYBOX_DEFAULT_MKDIR=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MKDIR_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_MKFIFO=y +CONFIG_BUSYBOX_DEFAULT_MKNOD=y +CONFIG_BUSYBOX_DEFAULT_MV=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MV_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_NICE=y +# CONFIG_BUSYBOX_DEFAULT_NL is not set +# CONFIG_BUSYBOX_DEFAULT_NOHUP is not set +# CONFIG_BUSYBOX_DEFAULT_NPROC is not set +# CONFIG_BUSYBOX_DEFAULT_OD is not set +# CONFIG_BUSYBOX_DEFAULT_PASTE is not set +# CONFIG_BUSYBOX_DEFAULT_PRINTENV is not set +CONFIG_BUSYBOX_DEFAULT_PRINTF=y +CONFIG_BUSYBOX_DEFAULT_PWD=y +CONFIG_BUSYBOX_DEFAULT_READLINK=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_READLINK_FOLLOW=y +# CONFIG_BUSYBOX_DEFAULT_REALPATH is not set +CONFIG_BUSYBOX_DEFAULT_RM=y +CONFIG_BUSYBOX_DEFAULT_RMDIR=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_RMDIR_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_SEQ=y +# CONFIG_BUSYBOX_DEFAULT_SHRED is not set +# CONFIG_BUSYBOX_DEFAULT_SHUF is not set +CONFIG_BUSYBOX_DEFAULT_SLEEP=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FANCY_SLEEP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FLOAT_SLEEP is not set +CONFIG_BUSYBOX_DEFAULT_SORT=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SORT_BIG is not set +# CONFIG_BUSYBOX_DEFAULT_SPLIT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SPLIT_FANCY is not set +# CONFIG_BUSYBOX_DEFAULT_STAT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_STAT_FORMAT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_STAT_FILESYSTEM is not set +# CONFIG_BUSYBOX_DEFAULT_STTY is not set +# CONFIG_BUSYBOX_DEFAULT_SUM is not set +CONFIG_BUSYBOX_DEFAULT_SYNC=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SYNC_FANCY is not set +# CONFIG_BUSYBOX_DEFAULT_TAC is not set +CONFIG_BUSYBOX_DEFAULT_TAIL=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FANCY_TAIL=y +CONFIG_BUSYBOX_DEFAULT_TEE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_TEE_USE_BLOCK_IO=y +CONFIG_BUSYBOX_DEFAULT_TEST=y +CONFIG_BUSYBOX_DEFAULT_TEST1=y +CONFIG_BUSYBOX_DEFAULT_TEST2=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_TEST_64=y +CONFIG_BUSYBOX_DEFAULT_TOUCH=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TOUCH_NODEREF is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_TOUCH_SUSV3=y +CONFIG_BUSYBOX_DEFAULT_TR=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TR_CLASSES is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TR_EQUIV is not set +CONFIG_BUSYBOX_DEFAULT_TRUE=y +# CONFIG_BUSYBOX_DEFAULT_TRUNCATE is not set +# CONFIG_BUSYBOX_DEFAULT_TTY is not set +CONFIG_BUSYBOX_DEFAULT_UNAME=y +CONFIG_BUSYBOX_DEFAULT_UNAME_OSNAME="GNU/Linux" +CONFIG_BUSYBOX_DEFAULT_UNIQ=y +# CONFIG_BUSYBOX_DEFAULT_UNLINK is not set +# CONFIG_BUSYBOX_DEFAULT_USLEEP is not set +# CONFIG_BUSYBOX_DEFAULT_UUDECODE is not set +# CONFIG_BUSYBOX_DEFAULT_BASE64 is not set +# CONFIG_BUSYBOX_DEFAULT_UUENCODE is not set +CONFIG_BUSYBOX_DEFAULT_WC=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_WC_LARGE is not set +# CONFIG_BUSYBOX_DEFAULT_WHO is not set +# CONFIG_BUSYBOX_DEFAULT_W is not set +# CONFIG_BUSYBOX_DEFAULT_USERS is not set +# CONFIG_BUSYBOX_DEFAULT_WHOAMI is not set +CONFIG_BUSYBOX_DEFAULT_YES=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VERBOSE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_PRESERVE_HARDLINKS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_HUMAN_READABLE=y +# CONFIG_BUSYBOX_DEFAULT_CHVT is not set +CONFIG_BUSYBOX_DEFAULT_CLEAR=y +# CONFIG_BUSYBOX_DEFAULT_DEALLOCVT is not set +# CONFIG_BUSYBOX_DEFAULT_DUMPKMAP is not set +# CONFIG_BUSYBOX_DEFAULT_FGCONSOLE is not set +# CONFIG_BUSYBOX_DEFAULT_KBD_MODE is not set +# CONFIG_BUSYBOX_DEFAULT_LOADFONT is not set +# CONFIG_BUSYBOX_DEFAULT_SETFONT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SETFONT_TEXTUAL_MAP is not set +CONFIG_BUSYBOX_DEFAULT_DEFAULT_SETFONT_DIR="" +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LOADFONT_PSF2 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LOADFONT_RAW is not set +# CONFIG_BUSYBOX_DEFAULT_LOADKMAP is not set +# CONFIG_BUSYBOX_DEFAULT_OPENVT is not set +CONFIG_BUSYBOX_DEFAULT_RESET=y +# CONFIG_BUSYBOX_DEFAULT_RESIZE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_RESIZE_PRINT is not set +# CONFIG_BUSYBOX_DEFAULT_SETCONSOLE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SETCONSOLE_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_SETKEYCODES is not set +# CONFIG_BUSYBOX_DEFAULT_SETLOGCONS is not set +# CONFIG_BUSYBOX_DEFAULT_SHOWKEY is not set +CONFIG_BUSYBOX_DEFAULT_MKTEMP=y +# CONFIG_BUSYBOX_DEFAULT_PIPE_PROGRESS is not set +# CONFIG_BUSYBOX_DEFAULT_RUN_PARTS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_RUN_PARTS_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_RUN_PARTS_FANCY is not set +CONFIG_BUSYBOX_DEFAULT_START_STOP_DAEMON=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_START_STOP_DAEMON_FANCY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_WHICH=y +CONFIG_BUSYBOX_DEFAULT_AWK=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_AWK_LIBM=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_AWK_GNU_EXTENSIONS=y +CONFIG_BUSYBOX_DEFAULT_CMP=y +# CONFIG_BUSYBOX_DEFAULT_DIFF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DIFF_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DIFF_DIR is not set +# CONFIG_BUSYBOX_DEFAULT_ED is not set +# CONFIG_BUSYBOX_DEFAULT_PATCH is not set +CONFIG_BUSYBOX_DEFAULT_SED=y +CONFIG_BUSYBOX_DEFAULT_VI=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_MAX_LEN=1024 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_8BIT is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_COLON=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_YANKMARK=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_SEARCH=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_REGEX_SEARCH is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_USE_SIGNALS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_DOT_CMD=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_READONLY=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_SETOPTS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_SET=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_WIN_RESIZE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_ASK_TERMINAL=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_UNDO is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_UNDO_QUEUE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_VI_UNDO_QUEUE_MAX=0 +CONFIG_BUSYBOX_DEFAULT_FEATURE_ALLOW_EXEC=y +CONFIG_BUSYBOX_DEFAULT_FIND=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_PRINT0=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_MTIME=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_MMIN is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_PERM=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_TYPE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_XDEV=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_MAXDEPTH=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_NEWER is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_INUM is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_EXEC=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_EXEC_PLUS is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_USER=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_GROUP=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_NOT=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_DEPTH=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_PAREN=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_SIZE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_PRUNE=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_DELETE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_PATH=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_REGEX=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_CONTEXT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FIND_LINKS is not set +CONFIG_BUSYBOX_DEFAULT_GREP=y +CONFIG_BUSYBOX_DEFAULT_EGREP=y +CONFIG_BUSYBOX_DEFAULT_FGREP=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_GREP_CONTEXT=y +CONFIG_BUSYBOX_DEFAULT_XARGS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_CONFIRMATION=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_QUOTES=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_TERMOPT=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_ZERO_TERM=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_XARGS_SUPPORT_REPL_STR is not set +# CONFIG_BUSYBOX_DEFAULT_BOOTCHARTD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_BOOTCHARTD_BLOATED_HEADER is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_BOOTCHARTD_CONFIG_FILE is not set +CONFIG_BUSYBOX_DEFAULT_HALT=y +CONFIG_BUSYBOX_DEFAULT_POWEROFF=y +CONFIG_BUSYBOX_DEFAULT_REBOOT=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CALL_TELINIT is not set +CONFIG_BUSYBOX_DEFAULT_TELINIT_PATH="" +# CONFIG_BUSYBOX_DEFAULT_INIT is not set +# CONFIG_BUSYBOX_DEFAULT_LINUXRC is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_USE_INITTAB is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_KILL_REMOVED is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_KILL_DELAY=0 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INIT_SCTTY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INIT_SYSLOG is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INIT_QUIET is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INIT_COREDUMPS is not set +CONFIG_BUSYBOX_DEFAULT_INIT_TERMINAL_TYPE="" +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INIT_MODIFY_CMDLINE is not set +# CONFIG_BUSYBOX_DEFAULT_MESG is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MESG_ENABLE_ONLY_GROUP is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_SHADOWPASSWDS=y +# CONFIG_BUSYBOX_DEFAULT_USE_BB_PWD_GRP is not set +# CONFIG_BUSYBOX_DEFAULT_USE_BB_SHADOW is not set +# CONFIG_BUSYBOX_DEFAULT_USE_BB_CRYPT is not set +# CONFIG_BUSYBOX_DEFAULT_USE_BB_CRYPT_SHA is not set +# CONFIG_BUSYBOX_DEFAULT_ADD_SHELL is not set +# CONFIG_BUSYBOX_DEFAULT_REMOVE_SHELL is not set +# CONFIG_BUSYBOX_DEFAULT_ADDGROUP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_ADDGROUP_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_ADDUSER_TO_GROUP is not set +# CONFIG_BUSYBOX_DEFAULT_ADDUSER is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_ADDUSER_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHECK_NAMES is not set +CONFIG_BUSYBOX_DEFAULT_LAST_ID=0 +CONFIG_BUSYBOX_DEFAULT_FIRST_SYSTEM_ID=0 +CONFIG_BUSYBOX_DEFAULT_LAST_SYSTEM_ID=0 +# CONFIG_BUSYBOX_DEFAULT_CHPASSWD is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_DEFAULT_PASSWD_ALGO="md5" +# CONFIG_BUSYBOX_DEFAULT_CRYPTPW is not set +# CONFIG_BUSYBOX_DEFAULT_MKPASSWD is not set +# CONFIG_BUSYBOX_DEFAULT_DELUSER is not set +# CONFIG_BUSYBOX_DEFAULT_DELGROUP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DEL_USER_FROM_GROUP is not set +# CONFIG_BUSYBOX_DEFAULT_GETTY is not set +CONFIG_BUSYBOX_DEFAULT_LOGIN=y +CONFIG_BUSYBOX_DEFAULT_LOGIN_SESSION_AS_CHILD=y +# CONFIG_BUSYBOX_DEFAULT_LOGIN_SCRIPTS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_NOLOGIN is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SECURETTY is not set +CONFIG_BUSYBOX_DEFAULT_PASSWD=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_PASSWD_WEAK_CHECK=y +# CONFIG_BUSYBOX_DEFAULT_SU is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SU_SYSLOG is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SU_CHECKS_SHELLS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY is not set +# CONFIG_BUSYBOX_DEFAULT_SULOGIN is not set +# CONFIG_BUSYBOX_DEFAULT_VLOCK is not set +# CONFIG_BUSYBOX_DEFAULT_CHATTR is not set +# CONFIG_BUSYBOX_DEFAULT_FSCK is not set +# CONFIG_BUSYBOX_DEFAULT_LSATTR is not set +# CONFIG_BUSYBOX_DEFAULT_TUNE2FS is not set +# CONFIG_BUSYBOX_DEFAULT_MODPROBE_SMALL is not set +# CONFIG_BUSYBOX_DEFAULT_DEPMOD is not set +# CONFIG_BUSYBOX_DEFAULT_INSMOD is not set +# CONFIG_BUSYBOX_DEFAULT_LSMOD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set +# CONFIG_BUSYBOX_DEFAULT_MODINFO is not set +# CONFIG_BUSYBOX_DEFAULT_MODPROBE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MODPROBE_BLACKLIST is not set +# CONFIG_BUSYBOX_DEFAULT_RMMOD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CMDLINE_MODULE_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_2_4_MODULES is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INSMOD_VERSION_CHECKING is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INSMOD_LOADINKMEM is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INSMOD_LOAD_MAP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INSMOD_LOAD_MAP_FULL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHECK_TAINTED_MODULE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INSMOD_TRY_MMAP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MODUTILS_ALIAS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MODUTILS_SYMBOLS is not set +CONFIG_BUSYBOX_DEFAULT_DEFAULT_MODULES_DIR="" +CONFIG_BUSYBOX_DEFAULT_DEFAULT_DEPMOD_FILE="" +# CONFIG_BUSYBOX_DEFAULT_ACPID is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_ACPID_COMPAT is not set +# CONFIG_BUSYBOX_DEFAULT_BLKDISCARD is not set +# CONFIG_BUSYBOX_DEFAULT_BLKID is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_BLKID_TYPE is not set +# CONFIG_BUSYBOX_DEFAULT_BLOCKDEV is not set +# CONFIG_BUSYBOX_DEFAULT_CAL is not set +CONFIG_BUSYBOX_DEFAULT_DMESG=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_DMESG_PRETTY=y +# CONFIG_BUSYBOX_DEFAULT_FALLOCATE is not set +# CONFIG_BUSYBOX_DEFAULT_FATATTR is not set +# CONFIG_BUSYBOX_DEFAULT_FBSET is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FBSET_FANCY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FBSET_READMODE is not set +# CONFIG_BUSYBOX_DEFAULT_FDFORMAT is not set +# CONFIG_BUSYBOX_DEFAULT_FDISK is not set +# CONFIG_BUSYBOX_DEFAULT_FDISK_SUPPORT_LARGE_DISKS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FDISK_WRITABLE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_AIX_LABEL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SGI_LABEL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SUN_LABEL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_OSF_LABEL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_GPT_LABEL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FDISK_ADVANCED is not set +# CONFIG_BUSYBOX_DEFAULT_FINDFS is not set +# CONFIG_BUSYBOX_DEFAULT_FLOCK is not set +# CONFIG_BUSYBOX_DEFAULT_FDFLUSH is not set +# CONFIG_BUSYBOX_DEFAULT_FREERAMDISK is not set +# CONFIG_BUSYBOX_DEFAULT_FSCK_MINIX is not set +# CONFIG_BUSYBOX_DEFAULT_FSFREEZE is not set +# CONFIG_BUSYBOX_DEFAULT_FSTRIM is not set +# CONFIG_BUSYBOX_DEFAULT_GETOPT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_GETOPT_LONG is not set +CONFIG_BUSYBOX_DEFAULT_HEXDUMP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HEXDUMP_REVERSE is not set +# CONFIG_BUSYBOX_DEFAULT_HD is not set +# CONFIG_BUSYBOX_DEFAULT_XXD is not set +CONFIG_BUSYBOX_DEFAULT_HWCLOCK=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HWCLOCK_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HWCLOCK_ADJTIME_FHS is not set +# CONFIG_BUSYBOX_DEFAULT_IPCRM is not set +# CONFIG_BUSYBOX_DEFAULT_IPCS is not set +# CONFIG_BUSYBOX_DEFAULT_LOSETUP is not set +# CONFIG_BUSYBOX_DEFAULT_LSPCI is not set +# CONFIG_BUSYBOX_DEFAULT_LSUSB is not set +# CONFIG_BUSYBOX_DEFAULT_MDEV is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MDEV_CONF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MDEV_RENAME is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MDEV_RENAME_REGEXP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MDEV_EXEC is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MDEV_LOAD_FIRMWARE is not set +# CONFIG_BUSYBOX_DEFAULT_MKE2FS is not set +# CONFIG_BUSYBOX_DEFAULT_MKFS_EXT2 is not set +# CONFIG_BUSYBOX_DEFAULT_MKFS_MINIX is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MINIX2 is not set +# CONFIG_BUSYBOX_DEFAULT_MKFS_REISER is not set +# CONFIG_BUSYBOX_DEFAULT_MKDOSFS is not set +# CONFIG_BUSYBOX_DEFAULT_MKFS_VFAT is not set +CONFIG_BUSYBOX_DEFAULT_MKSWAP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MKSWAP_UUID is not set +# CONFIG_BUSYBOX_DEFAULT_MORE is not set +CONFIG_BUSYBOX_DEFAULT_MOUNT=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_FAKE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_VERBOSE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_HELPERS=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_LABEL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_NFS is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_CIFS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_FLAGS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_FSTAB=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_OTHERTAB is not set +# CONFIG_BUSYBOX_DEFAULT_NSENTER is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_NSENTER_LONG_OPTS is not set +CONFIG_BUSYBOX_DEFAULT_PIVOT_ROOT=y +# CONFIG_BUSYBOX_DEFAULT_RDATE is not set +# CONFIG_BUSYBOX_DEFAULT_RDEV is not set +# CONFIG_BUSYBOX_DEFAULT_READPROFILE is not set +# CONFIG_BUSYBOX_DEFAULT_REV is not set +# CONFIG_BUSYBOX_DEFAULT_RTCWAKE is not set +# CONFIG_BUSYBOX_DEFAULT_SCRIPT is not set +# CONFIG_BUSYBOX_DEFAULT_SCRIPTREPLAY is not set +# CONFIG_BUSYBOX_DEFAULT_SETARCH is not set +# CONFIG_BUSYBOX_DEFAULT_LINUX32 is not set +# CONFIG_BUSYBOX_DEFAULT_LINUX64 is not set +# CONFIG_BUSYBOX_DEFAULT_SETPRIV is not set +# CONFIG_BUSYBOX_DEFAULT_SWAPON is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SWAPON_DISCARD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SWAPON_PRI is not set +# CONFIG_BUSYBOX_DEFAULT_SWAPOFF is not set +CONFIG_BUSYBOX_DEFAULT_SWITCH_ROOT=y +# CONFIG_BUSYBOX_DEFAULT_UEVENT is not set +CONFIG_BUSYBOX_DEFAULT_UMOUNT=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_UMOUNT_ALL=y +# CONFIG_BUSYBOX_DEFAULT_UNSHARE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_LOOP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MOUNT_LOOP_CREATE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MTAB_SUPPORT is not set +# CONFIG_BUSYBOX_DEFAULT_VOLUMEID is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_BCACHE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_BTRFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_CRAMFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_EXFAT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_EXT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_F2FS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_FAT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_HFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_ISO9660 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_JFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LINUXRAID is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LINUXSWAP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_LUKS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_NILFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_NTFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_OCFS2 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_REISERFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_ROMFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_SQUASHFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_SYSV is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_UBIFS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_UDF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_VOLUMEID_XFS is not set +# CONFIG_BUSYBOX_DEFAULT_ADJTIMEX is not set +# CONFIG_BUSYBOX_DEFAULT_BBCONFIG is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_COMPRESS_BBCONFIG is not set +# CONFIG_BUSYBOX_DEFAULT_BEEP is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_BEEP_FREQ=0 +CONFIG_BUSYBOX_DEFAULT_FEATURE_BEEP_LENGTH_MS=0 +# CONFIG_BUSYBOX_DEFAULT_CHAT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHAT_NOFAIL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHAT_TTY_HIFI is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHAT_IMPLICIT_CR is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHAT_SWALLOW_OPTS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHAT_SEND_ESCAPES is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHAT_VAR_ABORT_LEN is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHAT_CLR_ABORT is not set +# CONFIG_BUSYBOX_DEFAULT_CHRT is not set +# CONFIG_BUSYBOX_DEFAULT_CONSPY is not set +CONFIG_BUSYBOX_DEFAULT_CROND=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CROND_D is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CROND_CALL_SENDMAIL is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_CROND_DIR="/etc" +CONFIG_BUSYBOX_DEFAULT_CRONTAB=y +# CONFIG_BUSYBOX_DEFAULT_DC is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DC_LIBM is not set +# CONFIG_BUSYBOX_DEFAULT_DEVFSD is not set +# CONFIG_BUSYBOX_DEFAULT_DEVFSD_MODLOAD is not set +# CONFIG_BUSYBOX_DEFAULT_DEVFSD_FG_NP is not set +# CONFIG_BUSYBOX_DEFAULT_DEVFSD_VERBOSE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_DEVFS is not set +# CONFIG_BUSYBOX_DEFAULT_DEVMEM is not set +# CONFIG_BUSYBOX_DEFAULT_EJECT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_EJECT_SCSI is not set +# CONFIG_BUSYBOX_DEFAULT_FBSPLASH is not set +# CONFIG_BUSYBOX_DEFAULT_FLASH_ERASEALL is not set +# CONFIG_BUSYBOX_DEFAULT_FLASH_LOCK is not set +# CONFIG_BUSYBOX_DEFAULT_FLASH_UNLOCK is not set +# CONFIG_BUSYBOX_DEFAULT_FLASHCP is not set +# CONFIG_BUSYBOX_DEFAULT_HDPARM is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HDPARM_GET_IDENTITY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HDPARM_HDIO_GETSET_DMA is not set +# CONFIG_BUSYBOX_DEFAULT_I2CGET is not set +# CONFIG_BUSYBOX_DEFAULT_I2CSET is not set +# CONFIG_BUSYBOX_DEFAULT_I2CDUMP is not set +# CONFIG_BUSYBOX_DEFAULT_I2CDETECT is not set +# CONFIG_BUSYBOX_DEFAULT_INOTIFYD is not set +# CONFIG_BUSYBOX_DEFAULT_IONICE is not set +# CONFIG_BUSYBOX_DEFAULT_LAST is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LAST_FANCY is not set +CONFIG_BUSYBOX_DEFAULT_LESS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_MAXLINES=9999999 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_BRACKETS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_FLAGS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_TRUNCATE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_MARKS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_REGEXP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_WINCH is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_ASK_TERMINAL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_DASHCMD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LESS_LINENUMS is not set +CONFIG_BUSYBOX_DEFAULT_LOCK=y +# CONFIG_BUSYBOX_DEFAULT_LSSCSI is not set +# CONFIG_BUSYBOX_DEFAULT_MAKEDEVS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MAKEDEVS_LEAF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_MAKEDEVS_TABLE is not set +# CONFIG_BUSYBOX_DEFAULT_MAN is not set +# CONFIG_BUSYBOX_DEFAULT_MICROCOM is not set +# CONFIG_BUSYBOX_DEFAULT_MOUNTPOINT is not set +# CONFIG_BUSYBOX_DEFAULT_MT is not set +# CONFIG_BUSYBOX_DEFAULT_NANDWRITE is not set +# CONFIG_BUSYBOX_DEFAULT_NANDDUMP is not set +# CONFIG_BUSYBOX_DEFAULT_PARTPROBE is not set +# CONFIG_BUSYBOX_DEFAULT_RAIDAUTORUN is not set +# CONFIG_BUSYBOX_DEFAULT_READAHEAD is not set +# CONFIG_BUSYBOX_DEFAULT_RFKILL is not set +# CONFIG_BUSYBOX_DEFAULT_RUNLEVEL is not set +# CONFIG_BUSYBOX_DEFAULT_RX is not set +# CONFIG_BUSYBOX_DEFAULT_SETSERIAL is not set +# CONFIG_BUSYBOX_DEFAULT_SETSID is not set +CONFIG_BUSYBOX_DEFAULT_STRINGS=y +# CONFIG_BUSYBOX_DEFAULT_TASKSET is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TASKSET_FANCY is not set +CONFIG_BUSYBOX_DEFAULT_TIME=y +# CONFIG_BUSYBOX_DEFAULT_TIMEOUT is not set +# CONFIG_BUSYBOX_DEFAULT_TTYSIZE is not set +# CONFIG_BUSYBOX_DEFAULT_UBIATTACH is not set +# CONFIG_BUSYBOX_DEFAULT_UBIDETACH is not set +# CONFIG_BUSYBOX_DEFAULT_UBIMKVOL is not set +# CONFIG_BUSYBOX_DEFAULT_UBIRMVOL is not set +# CONFIG_BUSYBOX_DEFAULT_UBIRSVOL is not set +# CONFIG_BUSYBOX_DEFAULT_UBIUPDATEVOL is not set +# CONFIG_BUSYBOX_DEFAULT_UBIRENAME is not set +# CONFIG_BUSYBOX_DEFAULT_VOLNAME is not set +# CONFIG_BUSYBOX_DEFAULT_WALL is not set +# CONFIG_BUSYBOX_DEFAULT_WATCHDOG is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_IPV6=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UNIX_LOCAL is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_PREFER_IPV4_ADDRESS=y +CONFIG_BUSYBOX_DEFAULT_VERBOSE_RESOLUTION_ERRORS=y +# CONFIG_BUSYBOX_DEFAULT_ARP is not set +# CONFIG_BUSYBOX_DEFAULT_ARPING is not set +CONFIG_BUSYBOX_DEFAULT_BRCTL=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_BRCTL_FANCY=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_BRCTL_SHOW=y +# CONFIG_BUSYBOX_DEFAULT_DNSD is not set +# CONFIG_BUSYBOX_DEFAULT_ETHER_WAKE is not set +# CONFIG_BUSYBOX_DEFAULT_FTPD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FTPD_WRITE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FTPD_AUTHENTICATION is not set +# CONFIG_BUSYBOX_DEFAULT_FTPGET is not set +# CONFIG_BUSYBOX_DEFAULT_FTPPUT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_FTPGETPUT_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_HOSTNAME is not set +# CONFIG_BUSYBOX_DEFAULT_DNSDOMAINNAME is not set +# CONFIG_BUSYBOX_DEFAULT_HTTPD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_RANGES is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_SETUID is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_BASIC_AUTH is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_AUTH_MD5 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_CGI is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_ENCODE_URL_STR is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_ERROR_PAGES is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_PROXY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_HTTPD_GZIP is not set +CONFIG_BUSYBOX_DEFAULT_IFCONFIG=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_IFCONFIG_STATUS=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IFCONFIG_SLIP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_IFCONFIG_HW=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_IFCONFIG_BROADCAST_PLUS=y +# CONFIG_BUSYBOX_DEFAULT_IFENSLAVE is not set +# CONFIG_BUSYBOX_DEFAULT_IFPLUGD is not set +# CONFIG_BUSYBOX_DEFAULT_IFUP is not set +# CONFIG_BUSYBOX_DEFAULT_IFDOWN is not set +CONFIG_BUSYBOX_DEFAULT_IFUPDOWN_IFSTATE_PATH="" +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IPV4 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_IPV6 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_MAPPING is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set +# CONFIG_BUSYBOX_DEFAULT_INETD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_INETD_RPC is not set +CONFIG_BUSYBOX_DEFAULT_IP=y +# CONFIG_BUSYBOX_DEFAULT_IPADDR is not set +# CONFIG_BUSYBOX_DEFAULT_IPLINK is not set +# CONFIG_BUSYBOX_DEFAULT_IPROUTE is not set +# CONFIG_BUSYBOX_DEFAULT_IPTUNNEL is not set +# CONFIG_BUSYBOX_DEFAULT_IPRULE is not set +# CONFIG_BUSYBOX_DEFAULT_IPNEIGH is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_IP_ADDRESS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_IP_LINK=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_IP_ROUTE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_IP_ROUTE_DIR="/etc/iproute2" +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IP_TUNNEL is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_IP_RULE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_IP_NEIGH=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IP_RARE_PROTOCOLS is not set +# CONFIG_BUSYBOX_DEFAULT_IPCALC is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IPCALC_FANCY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IPCALC_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FAKEIDENTD is not set +# CONFIG_BUSYBOX_DEFAULT_NAMEIF is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_NAMEIF_EXTENDED is not set +# CONFIG_BUSYBOX_DEFAULT_NBDCLIENT is not set +CONFIG_BUSYBOX_DEFAULT_NC=y +# CONFIG_BUSYBOX_DEFAULT_NC_SERVER is not set +# CONFIG_BUSYBOX_DEFAULT_NC_EXTRA is not set +# CONFIG_BUSYBOX_DEFAULT_NC_110_COMPAT is not set +CONFIG_BUSYBOX_DEFAULT_NETMSG=y +CONFIG_BUSYBOX_DEFAULT_NETSTAT=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_NETSTAT_WIDE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_NETSTAT_PRG=y +# CONFIG_BUSYBOX_DEFAULT_NSLOOKUP is not set +CONFIG_BUSYBOX_DEFAULT_NSLOOKUP_LEDE=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_NSLOOKUP_LEDE_LONG_OPTIONS is not set +CONFIG_BUSYBOX_DEFAULT_NTPD=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_NTPD_SERVER=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_NTPD_CONF is not set +CONFIG_BUSYBOX_DEFAULT_PING=y +CONFIG_BUSYBOX_DEFAULT_PING6=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_FANCY_PING=y +# CONFIG_BUSYBOX_DEFAULT_PSCAN is not set +CONFIG_BUSYBOX_DEFAULT_ROUTE=y +# CONFIG_BUSYBOX_DEFAULT_SLATTACH is not set +# CONFIG_BUSYBOX_DEFAULT_SSL_CLIENT is not set +# CONFIG_BUSYBOX_DEFAULT_TCPSVD is not set +# CONFIG_BUSYBOX_DEFAULT_UDPSVD is not set +# CONFIG_BUSYBOX_DEFAULT_TELNET is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TELNET_TTYPE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TELNET_AUTOLOGIN is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TELNET_WIDTH is not set +# CONFIG_BUSYBOX_DEFAULT_TELNETD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TELNETD_STANDALONE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TELNETD_INETD_WAIT is not set +# CONFIG_BUSYBOX_DEFAULT_TFTP is not set +# CONFIG_BUSYBOX_DEFAULT_TFTPD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TFTP_GET is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TFTP_PUT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TFTP_BLOCKSIZE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TFTP_PROGRESS_BAR is not set +# CONFIG_BUSYBOX_DEFAULT_TFTP_DEBUG is not set +# CONFIG_BUSYBOX_DEFAULT_TLS is not set +CONFIG_BUSYBOX_DEFAULT_TRACEROUTE=y +CONFIG_BUSYBOX_DEFAULT_TRACEROUTE6=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_TRACEROUTE_VERBOSE=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TRACEROUTE_USE_ICMP is not set +# CONFIG_BUSYBOX_DEFAULT_TUNCTL is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TUNCTL_UG is not set +# CONFIG_BUSYBOX_DEFAULT_VCONFIG is not set +# CONFIG_BUSYBOX_DEFAULT_WGET is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_WGET_STATUSBAR is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_WGET_AUTHENTICATION is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_WGET_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_WGET_TIMEOUT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_WGET_HTTPS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_WGET_OPENSSL is not set +# CONFIG_BUSYBOX_DEFAULT_WHOIS is not set +# CONFIG_BUSYBOX_DEFAULT_ZCIP is not set +# CONFIG_BUSYBOX_DEFAULT_UDHCPC6 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCPC6_RFC3646 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCPC6_RFC4704 is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCPC6_RFC4833 is not set +# CONFIG_BUSYBOX_DEFAULT_UDHCPD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCPD_BASE_IP_ON_MAC is not set +CONFIG_BUSYBOX_DEFAULT_DHCPD_LEASES_FILE="" +# CONFIG_BUSYBOX_DEFAULT_DUMPLEASES is not set +# CONFIG_BUSYBOX_DEFAULT_DHCPRELAY is not set +CONFIG_BUSYBOX_DEFAULT_UDHCPC=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCPC_ARPING is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCPC_SANITIZEOPT is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCP_PORT is not set +CONFIG_BUSYBOX_DEFAULT_UDHCP_DEBUG=0 +CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCP_RFC3397=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UDHCP_8021Q is not set +CONFIG_BUSYBOX_DEFAULT_UDHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script" +CONFIG_BUSYBOX_DEFAULT_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80 +CONFIG_BUSYBOX_DEFAULT_IFUPDOWN_UDHCPC_CMD_OPTIONS="" +# CONFIG_BUSYBOX_DEFAULT_LPD is not set +# CONFIG_BUSYBOX_DEFAULT_LPR is not set +# CONFIG_BUSYBOX_DEFAULT_LPQ is not set +# CONFIG_BUSYBOX_DEFAULT_MAKEMIME is not set +# CONFIG_BUSYBOX_DEFAULT_POPMAILDIR is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_POPMAILDIR_DELIVERY is not set +# CONFIG_BUSYBOX_DEFAULT_REFORMIME is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_REFORMIME_COMPAT is not set +# CONFIG_BUSYBOX_DEFAULT_SENDMAIL is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_MIME_CHARSET="" +CONFIG_BUSYBOX_DEFAULT_FREE=y +# CONFIG_BUSYBOX_DEFAULT_FUSER is not set +# CONFIG_BUSYBOX_DEFAULT_IOSTAT is not set +CONFIG_BUSYBOX_DEFAULT_KILL=y +CONFIG_BUSYBOX_DEFAULT_KILLALL=y +# CONFIG_BUSYBOX_DEFAULT_KILLALL5 is not set +# CONFIG_BUSYBOX_DEFAULT_LSOF is not set +# CONFIG_BUSYBOX_DEFAULT_MPSTAT is not set +# CONFIG_BUSYBOX_DEFAULT_NMETER is not set +CONFIG_BUSYBOX_DEFAULT_PGREP=y +# CONFIG_BUSYBOX_DEFAULT_PKILL is not set +CONFIG_BUSYBOX_DEFAULT_PIDOF=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_PIDOF_SINGLE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_PIDOF_OMIT is not set +# CONFIG_BUSYBOX_DEFAULT_PMAP is not set +# CONFIG_BUSYBOX_DEFAULT_POWERTOP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_POWERTOP_INTERACTIVE is not set +CONFIG_BUSYBOX_DEFAULT_PS=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_PS_WIDE=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_PS_LONG is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_PS_TIME is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_PS_ADDITIONAL_COLUMNS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_PS_UNUSUAL_SYSTEMS is not set +# CONFIG_BUSYBOX_DEFAULT_PSTREE is not set +# CONFIG_BUSYBOX_DEFAULT_PWDX is not set +# CONFIG_BUSYBOX_DEFAULT_RENICE is not set +# CONFIG_BUSYBOX_DEFAULT_SMEMCAP is not set +CONFIG_BUSYBOX_DEFAULT_BB_SYSCTL=y +CONFIG_BUSYBOX_DEFAULT_TOP=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TOP_INTERACTIVE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TOP_SMP_CPU is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TOP_DECIMALS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TOP_SMP_PROCESS is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_TOPMEM is not set +CONFIG_BUSYBOX_DEFAULT_UPTIME=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_UPTIME_UTMP_SUPPORT is not set +# CONFIG_BUSYBOX_DEFAULT_WATCH is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SHOW_THREADS is not set +# CONFIG_BUSYBOX_DEFAULT_CHPST is not set +# CONFIG_BUSYBOX_DEFAULT_SETUIDGID is not set +# CONFIG_BUSYBOX_DEFAULT_ENVUIDGID is not set +# CONFIG_BUSYBOX_DEFAULT_ENVDIR is not set +# CONFIG_BUSYBOX_DEFAULT_SOFTLIMIT is not set +# CONFIG_BUSYBOX_DEFAULT_RUNSV is not set +# CONFIG_BUSYBOX_DEFAULT_RUNSVDIR is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_RUNSVDIR_LOG is not set +# CONFIG_BUSYBOX_DEFAULT_SV is not set +CONFIG_BUSYBOX_DEFAULT_SV_DEFAULT_SERVICE_DIR="" +# CONFIG_BUSYBOX_DEFAULT_SVC is not set +# CONFIG_BUSYBOX_DEFAULT_SVLOGD is not set +# CONFIG_BUSYBOX_DEFAULT_CHCON is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_CHCON_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_GETENFORCE is not set +# CONFIG_BUSYBOX_DEFAULT_GETSEBOOL is not set +# CONFIG_BUSYBOX_DEFAULT_LOAD_POLICY is not set +# CONFIG_BUSYBOX_DEFAULT_MATCHPATHCON is not set +# CONFIG_BUSYBOX_DEFAULT_RUNCON is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_RUNCON_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_SELINUXENABLED is not set +# CONFIG_BUSYBOX_DEFAULT_SESTATUS is not set +# CONFIG_BUSYBOX_DEFAULT_SETENFORCE is not set +# CONFIG_BUSYBOX_DEFAULT_SETFILES is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SETFILES_CHECK_OPTION is not set +# CONFIG_BUSYBOX_DEFAULT_RESTORECON is not set +# CONFIG_BUSYBOX_DEFAULT_SETSEBOOL is not set +CONFIG_BUSYBOX_DEFAULT_SH_IS_ASH=y +# CONFIG_BUSYBOX_DEFAULT_SH_IS_HUSH is not set +# CONFIG_BUSYBOX_DEFAULT_SH_IS_NONE is not set +# CONFIG_BUSYBOX_DEFAULT_BASH_IS_ASH is not set +# CONFIG_BUSYBOX_DEFAULT_BASH_IS_HUSH is not set +CONFIG_BUSYBOX_DEFAULT_BASH_IS_NONE=y +CONFIG_BUSYBOX_DEFAULT_ASH=y +# CONFIG_BUSYBOX_DEFAULT_ASH_OPTIMIZE_FOR_SIZE is not set +CONFIG_BUSYBOX_DEFAULT_ASH_INTERNAL_GLOB=y +CONFIG_BUSYBOX_DEFAULT_ASH_BASH_COMPAT=y +CONFIG_BUSYBOX_DEFAULT_ASH_JOB_CONTROL=y +CONFIG_BUSYBOX_DEFAULT_ASH_ALIAS=y +# CONFIG_BUSYBOX_DEFAULT_ASH_RANDOM_SUPPORT is not set +CONFIG_BUSYBOX_DEFAULT_ASH_EXPAND_PRMT=y +# CONFIG_BUSYBOX_DEFAULT_ASH_IDLE_TIMEOUT is not set +# CONFIG_BUSYBOX_DEFAULT_ASH_MAIL is not set +CONFIG_BUSYBOX_DEFAULT_ASH_ECHO=y +CONFIG_BUSYBOX_DEFAULT_ASH_PRINTF=y +CONFIG_BUSYBOX_DEFAULT_ASH_TEST=y +# CONFIG_BUSYBOX_DEFAULT_ASH_HELP is not set +CONFIG_BUSYBOX_DEFAULT_ASH_GETOPTS=y +CONFIG_BUSYBOX_DEFAULT_ASH_CMDCMD=y +# CONFIG_BUSYBOX_DEFAULT_CTTYHACK is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_BASH_COMPAT is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_BRACE_EXPANSION is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_HELP is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_INTERACTIVE is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_SAVEHISTORY is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_JOB is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_TICK is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_IF is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_LOOPS is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_CASE is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_FUNCTIONS is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_LOCAL is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_RANDOM_SUPPORT is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_MODE_X is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_ECHO is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_PRINTF is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_TEST is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_EXPORT is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_EXPORT_N is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_KILL is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_WAIT is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_TRAP is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_TYPE is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_READ is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_SET is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_UNSET is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_ULIMIT is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_UMASK is not set +# CONFIG_BUSYBOX_DEFAULT_HUSH_MEMLEAK is not set +# CONFIG_BUSYBOX_DEFAULT_MSH is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_SH_MATH=y +CONFIG_BUSYBOX_DEFAULT_FEATURE_SH_MATH_64=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SH_EXTRA_QUIET is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SH_STANDALONE is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_SH_NOFORK=y +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SH_HISTFILESIZE is not set +# CONFIG_BUSYBOX_DEFAULT_KLOGD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_KLOGD_KLOGCTL is not set +CONFIG_BUSYBOX_DEFAULT_LOGGER=y +# CONFIG_BUSYBOX_DEFAULT_LOGREAD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_LOGREAD_REDUCED_LOCKING is not set +# CONFIG_BUSYBOX_DEFAULT_SYSLOGD is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_ROTATE_LOGFILE is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_REMOTE_LOG is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SYSLOGD_DUP is not set +# CONFIG_BUSYBOX_DEFAULT_FEATURE_SYSLOGD_CFG is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_SYSLOGD_READ_BUFFER_SIZE=0 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_IPC_SYSLOG is not set +CONFIG_BUSYBOX_DEFAULT_FEATURE_IPC_SYSLOG_BUFFER_SIZE=0 +# CONFIG_BUSYBOX_DEFAULT_FEATURE_KMSG_SYSLOG is not set +# CONFIG_PACKAGE_ca-bundle is not set +# CONFIG_PACKAGE_ca-certificates is not set +# CONFIG_PACKAGE_dnsmasq is not set +# CONFIG_PACKAGE_dnsmasq-dhcpv6 is not set +CONFIG_PACKAGE_dnsmasq-full=y +# CONFIG_PACKAGE_dnsmasq_full_dhcpv6 is not set +# CONFIG_PACKAGE_dnsmasq_full_dnssec is not set +# CONFIG_PACKAGE_dnsmasq_full_auth is not set +CONFIG_PACKAGE_dnsmasq_full_ipset=y +# CONFIG_PACKAGE_dnsmasq_full_conntrack is not set +# CONFIG_PACKAGE_dnsmasq_full_noid is not set +# CONFIG_PACKAGE_dnsmasq_full_broken_rtc is not set +CONFIG_PACKAGE_dropbear=y + +# +# Configuration +# +CONFIG_DROPBEAR_CURVE25519=y +# CONFIG_DROPBEAR_ECC is not set +# CONFIG_PACKAGE_ead is not set +CONFIG_PACKAGE_firewall=y +CONFIG_PACKAGE_fstools=y +CONFIG_PACKAGE_fwtool=y +CONFIG_PACKAGE_jsonfilter=y +CONFIG_PACKAGE_lede-keyring=y +# CONFIG_PACKAGE_libatomic is not set +CONFIG_PACKAGE_libc=y +CONFIG_PACKAGE_libgcc=y +# CONFIG_PACKAGE_libgomp is not set +CONFIG_PACKAGE_libpthread=y +CONFIG_PACKAGE_librt=y +# CONFIG_PACKAGE_libstdcpp is not set +CONFIG_PACKAGE_logd=y +# CONFIG_PACKAGE_mksh is not set +CONFIG_PACKAGE_mtd=y +CONFIG_PACKAGE_netifd=y +# CONFIG_PACKAGE_nvram is not set +# CONFIG_PACKAGE_om-watchdog is not set +CONFIG_PACKAGE_opkg=y +CONFIG_PACKAGE_procd=y + +# +# Configuration +# +# CONFIG_PROCD_SHOW_BOOT is not set +# CONFIG_PROCD_ZRAM_TMPFS is not set +# CONFIG_PACKAGE_qos-scripts is not set +# CONFIG_PACKAGE_resolveip is not set +CONFIG_PACKAGE_rpcd=y +# CONFIG_PACKAGE_rpcd-mod-attendedsysupgrade is not set +# CONFIG_PACKAGE_rpcd-mod-file is not set +# CONFIG_PACKAGE_rpcd-mod-iwinfo is not set +# CONFIG_PACKAGE_rpcd-mod-packagelist is not set +# CONFIG_PACKAGE_rpcd-mod-rpcsys is not set +# CONFIG_PACKAGE_snapshot-tool is not set +CONFIG_PACKAGE_sqm-scripts=y +# CONFIG_PACKAGE_sqm-scripts-extra is not set +CONFIG_PACKAGE_swconfig=y +CONFIG_PACKAGE_ubox=y +CONFIG_PACKAGE_ubus=y +CONFIG_PACKAGE_ubusd=y +CONFIG_PACKAGE_uci=y +CONFIG_PACKAGE_usign=y +# CONFIG_PACKAGE_wireless-tools is not set +# CONFIG_PACKAGE_zram-swap is not set + +# +# Administration +# + +# +# openwisp +# +# CONFIG_PACKAGE_openwisp-config-cyassl is not set +# CONFIG_PACKAGE_openwisp-config-mbedtls is not set +# CONFIG_PACKAGE_openwisp-config-nossl is not set +# CONFIG_PACKAGE_openwisp-config-openssl is not set + +# +# zabbix +# +# CONFIG_PACKAGE_zabbix-agentd is not set +# CONFIG_PACKAGE_zabbix-extra-mac80211 is not set +# CONFIG_PACKAGE_zabbix-extra-network is not set +# CONFIG_PACKAGE_zabbix-extra-wifi is not set +# CONFIG_PACKAGE_zabbix-get is not set +# CONFIG_PACKAGE_zabbix-proxy is not set +# CONFIG_PACKAGE_zabbix-sender is not set +# CONFIG_PACKAGE_zabbix-server is not set +# CONFIG_PACKAGE_htop is not set +# CONFIG_PACKAGE_ipmitool is not set +# CONFIG_PACKAGE_monit is not set +# CONFIG_PACKAGE_monit-nossl is not set +# CONFIG_PACKAGE_muninlite is not set +# CONFIG_PACKAGE_netdata is not set +# CONFIG_PACKAGE_sudo is not set +# CONFIG_PACKAGE_syslog-ng is not set + +# +# Boot Loaders +# + +# +# Development +# + +# +# Libraries +# +# CONFIG_PACKAGE_libncurses-dev is not set +# CONFIG_PACKAGE_zlib-dev is not set +# CONFIG_PACKAGE_ar is not set +# CONFIG_PACKAGE_autoconf is not set +# CONFIG_PACKAGE_automake is not set +# CONFIG_PACKAGE_binutils is not set +# CONFIG_PACKAGE_diffutils is not set +# CONFIG_PACKAGE_gcc is not set +# CONFIG_PACKAGE_gdb is not set +# CONFIG_PACKAGE_gdbserver is not set +# CONFIG_PACKAGE_libtool-bin is not set +# CONFIG_PACKAGE_lpc21isp is not set +# CONFIG_PACKAGE_lttng-tools is not set +# CONFIG_PACKAGE_m4 is not set +# CONFIG_PACKAGE_make is not set +# CONFIG_PACKAGE_objdump is not set +# CONFIG_PACKAGE_patch is not set +# CONFIG_PACKAGE_pkg-config is not set +# CONFIG_PACKAGE_trace-cmd is not set +# CONFIG_PACKAGE_trace-cmd-extra is not set +# CONFIG_PACKAGE_valgrind is not set + +# +# Extra packages +# +CONFIG_PACKAGE_automount=y +# CONFIG_PACKAGE_autosamba is not set +# CONFIG_PACKAGE_he-6in4 is not set +# CONFIG_PACKAGE_k3wifi is not set + +# +# Firmware +# + +# +# ath10k IPQ4019 Boarddata +# +# CONFIG_PACKAGE_aircard-pcmcia-firmware is not set +# CONFIG_PACKAGE_ar3k-firmware is not set +# CONFIG_PACKAGE_ath10k-firmware-qca4019 is not set +# CONFIG_PACKAGE_ath10k-firmware-qca6174 is not set +# CONFIG_PACKAGE_ath10k-firmware-qca9887 is not set +# CONFIG_PACKAGE_ath10k-firmware-qca9887-ct is not set +# CONFIG_PACKAGE_ath10k-firmware-qca9888 is not set +# CONFIG_PACKAGE_ath10k-firmware-qca9888-ct is not set +# CONFIG_PACKAGE_ath10k-firmware-qca988x is not set +# CONFIG_PACKAGE_ath10k-firmware-qca988x-ct is not set +# CONFIG_PACKAGE_ath10k-firmware-qca9984 is not set +# CONFIG_PACKAGE_ath10k-firmware-qca9984-ct is not set +# CONFIG_PACKAGE_ath10k-firmware-qca99x0 is not set +# CONFIG_PACKAGE_ath10k-firmware-qca99x0-ct is not set +# CONFIG_PACKAGE_ath6k-firmware is not set +# CONFIG_PACKAGE_ath9k-htc-firmware is not set +# CONFIG_PACKAGE_b43legacy-firmware is not set +# CONFIG_PACKAGE_bnx2-firmware is not set +# CONFIG_PACKAGE_brcmfmac-firmware-4329-sdio is not set +# CONFIG_PACKAGE_brcmfmac-firmware-43362-sdio is not set +# CONFIG_PACKAGE_brcmfmac-firmware-43430-sdio is not set +# CONFIG_PACKAGE_brcmfmac-firmware-43602a1-pcie is not set +# CONFIG_PACKAGE_brcmfmac-firmware-4366b1-pcie is not set +# CONFIG_PACKAGE_brcmfmac-firmware-usb is not set +# CONFIG_PACKAGE_brcmsmac-firmware is not set +# CONFIG_PACKAGE_carl9170-firmware is not set +# CONFIG_PACKAGE_ibt-firmware is not set +# CONFIG_PACKAGE_iwl3945-firmware is not set +# CONFIG_PACKAGE_iwl4965-firmware is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl100 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl1000 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl105 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl135 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl2000 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl2030 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl3160 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl3168 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl5000 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl5150 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl6000g2 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl6000g2a is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl6000g2b is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl6050 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl7260 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl7265 is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl7265d is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl8260c is not set +# CONFIG_PACKAGE_iwlwifi-firmware-iwl8265 is not set +# CONFIG_PACKAGE_libertas-sdio-firmware is not set +# CONFIG_PACKAGE_libertas-spi-firmware is not set +# CONFIG_PACKAGE_libertas-usb-firmware is not set +# CONFIG_PACKAGE_mt7601u-firmware is not set +# CONFIG_PACKAGE_mwifiex-pcie-firmware is not set +# CONFIG_PACKAGE_mwifiex-sdio-firmware is not set +# CONFIG_PACKAGE_mwl8k-firmware is not set +# CONFIG_PACKAGE_p54-pci-firmware is not set +# CONFIG_PACKAGE_p54-spi-firmware is not set +# CONFIG_PACKAGE_p54-usb-firmware is not set +# CONFIG_PACKAGE_prism54-firmware is not set +# CONFIG_PACKAGE_r8169-firmware is not set +# CONFIG_PACKAGE_rt2800-pci-firmware is not set +# CONFIG_PACKAGE_rt2800-usb-firmware is not set +# CONFIG_PACKAGE_rt61-pci-firmware is not set +# CONFIG_PACKAGE_rt73-usb-firmware is not set +# CONFIG_PACKAGE_rtl8188eu-firmware is not set +# CONFIG_PACKAGE_rtl8192ce-firmware is not set +# CONFIG_PACKAGE_rtl8192cu-firmware is not set +# CONFIG_PACKAGE_rtl8192de-firmware is not set +# CONFIG_PACKAGE_rtl8192se-firmware is not set +# CONFIG_PACKAGE_rtl8192su-firmware is not set +# CONFIG_PACKAGE_rtl8821ae-firmware is not set +# CONFIG_PACKAGE_wl12xx-firmware is not set +# CONFIG_PACKAGE_wl18xx-firmware is not set + +# +# Fonts +# + +# +# DejaVu +# +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuMathTeXGyre is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSans is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSans-Bold is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSans-BoldOblique is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSans-ExtraLight is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSans-Oblique is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSansCondensed is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSansCondensed-Bold is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSansCondensed-BoldOblique is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSansCondensed-Oblique is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSansMono is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSansMono-Bold is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSansMono-BoldOblique is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSansMono-Oblique is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSerif is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSerif-Bold is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSerif-BoldItalic is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSerif-Italic is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSerifCondensed is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSerifCondensed-Bold is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSerifCondensed-BoldItalic is not set +# CONFIG_PACKAGE_dejavu-fonts-ttf-DejaVuSerifCondensed-Italic is not set + +# +# Kernel modules +# + +# +# Block Devices +# +# CONFIG_PACKAGE_kmod-aoe is not set +# CONFIG_PACKAGE_kmod-ata-core is not set +# CONFIG_PACKAGE_kmod-block2mtd is not set +# CONFIG_PACKAGE_kmod-dm is not set +# CONFIG_PACKAGE_kmod-loop is not set +# CONFIG_PACKAGE_kmod-md-mod is not set +# CONFIG_PACKAGE_kmod-nbd is not set +# CONFIG_PACKAGE_kmod-scsi-cdrom is not set +CONFIG_PACKAGE_kmod-scsi-core=y +# CONFIG_PACKAGE_kmod-scsi-generic is not set +# CONFIG_PACKAGE_kmod-scsi-tape is not set + +# +# CAN Support +# +# CONFIG_PACKAGE_kmod-can is not set + +# +# Cryptographic API modules +# +CONFIG_PACKAGE_kmod-crypto-aead=y +CONFIG_PACKAGE_kmod-crypto-authenc=y +CONFIG_PACKAGE_kmod-crypto-cbc=y +# CONFIG_PACKAGE_kmod-crypto-ccm is not set +# CONFIG_PACKAGE_kmod-crypto-cmac is not set +CONFIG_PACKAGE_kmod-crypto-crc32c=y +# CONFIG_PACKAGE_kmod-crypto-ctr is not set +CONFIG_PACKAGE_kmod-crypto-deflate=y +CONFIG_PACKAGE_kmod-crypto-des=y +CONFIG_PACKAGE_kmod-crypto-ecb=y +CONFIG_PACKAGE_kmod-crypto-echainiv=y +# CONFIG_PACKAGE_kmod-crypto-fcrypt is not set +# CONFIG_PACKAGE_kmod-crypto-gcm is not set +# CONFIG_PACKAGE_kmod-crypto-gf128 is not set +# CONFIG_PACKAGE_kmod-crypto-ghash is not set +CONFIG_PACKAGE_kmod-crypto-hash=y +CONFIG_PACKAGE_kmod-crypto-hmac=y +# CONFIG_PACKAGE_kmod-crypto-hw-ccp is not set +# CONFIG_PACKAGE_kmod-crypto-hw-geode is not set +# CONFIG_PACKAGE_kmod-crypto-hw-hifn-795x is not set +# CONFIG_PACKAGE_kmod-crypto-hw-padlock is not set +# CONFIG_PACKAGE_kmod-crypto-hw-talitos is not set +CONFIG_PACKAGE_kmod-crypto-iv=y +CONFIG_PACKAGE_kmod-crypto-manager=y +# CONFIG_PACKAGE_kmod-crypto-md4 is not set +CONFIG_PACKAGE_kmod-crypto-md5=y +# CONFIG_PACKAGE_kmod-crypto-michael-mic is not set +# CONFIG_PACKAGE_kmod-crypto-misc is not set +CONFIG_PACKAGE_kmod-crypto-null=y +# CONFIG_PACKAGE_kmod-crypto-pcbc is not set +CONFIG_PACKAGE_kmod-crypto-pcompress=y +CONFIG_PACKAGE_kmod-crypto-rng=y +# CONFIG_PACKAGE_kmod-crypto-seqiv is not set +CONFIG_PACKAGE_kmod-crypto-sha1=y +CONFIG_PACKAGE_kmod-crypto-sha256=y +# CONFIG_PACKAGE_kmod-crypto-sha512 is not set +# CONFIG_PACKAGE_kmod-crypto-test is not set +# CONFIG_PACKAGE_kmod-crypto-user is not set +CONFIG_PACKAGE_kmod-crypto-wq=y +# CONFIG_PACKAGE_kmod-crypto-xts is not set +# CONFIG_PACKAGE_kmod-cryptodev is not set + +# +# Filesystems +# +# CONFIG_PACKAGE_kmod-fs-afs is not set +# CONFIG_PACKAGE_kmod-fs-autofs4 is not set +# CONFIG_PACKAGE_kmod-fs-btrfs is not set +# CONFIG_PACKAGE_kmod-fs-cifs is not set +# CONFIG_PACKAGE_kmod-fs-configfs is not set +# CONFIG_PACKAGE_kmod-fs-cramfs is not set +CONFIG_PACKAGE_kmod-fs-exfat=y +# CONFIG_PACKAGE_kmod-fs-exportfs is not set +CONFIG_PACKAGE_kmod-fs-ext4=y +# CONFIG_PACKAGE_kmod-fs-f2fs is not set +# CONFIG_PACKAGE_kmod-fs-fscache is not set +# CONFIG_PACKAGE_kmod-fs-hfs is not set +# CONFIG_PACKAGE_kmod-fs-hfsplus is not set +# CONFIG_PACKAGE_kmod-fs-isofs is not set +# CONFIG_PACKAGE_kmod-fs-jfs is not set +# CONFIG_PACKAGE_kmod-fs-minix is not set +# CONFIG_PACKAGE_kmod-fs-msdos is not set +# CONFIG_PACKAGE_kmod-fs-nfs is not set +# CONFIG_PACKAGE_kmod-fs-nfs-common is not set +# CONFIG_PACKAGE_kmod-fs-nfsd is not set +# CONFIG_PACKAGE_kmod-fs-ntfs is not set +# CONFIG_PACKAGE_kmod-fs-reiserfs is not set +# CONFIG_PACKAGE_kmod-fs-squashfs is not set +# CONFIG_PACKAGE_kmod-fs-udf is not set +CONFIG_PACKAGE_kmod-fs-vfat=y +# CONFIG_PACKAGE_kmod-fs-xfs is not set +CONFIG_PACKAGE_kmod-fuse=y + +# +# FireWire support +# +# CONFIG_PACKAGE_kmod-firewire is not set + +# +# Hardware Monitoring Support +# +# CONFIG_PACKAGE_kmod-hwmon-core is not set + +# +# I2C support +# +# CONFIG_PACKAGE_kmod-i2c-core is not set +# CONFIG_PACKAGE_kmod-i2c-gpio-custom is not set + +# +# Input modules +# +# CONFIG_PACKAGE_kmod-hid is not set +# CONFIG_PACKAGE_kmod-hid-generic is not set +# CONFIG_PACKAGE_kmod-input-core is not set +# CONFIG_PACKAGE_kmod-input-evdev is not set +# CONFIG_PACKAGE_kmod-input-gpio-encoder is not set +# CONFIG_PACKAGE_kmod-input-gpio-keys is not set +# CONFIG_PACKAGE_kmod-input-gpio-keys-polled is not set +# CONFIG_PACKAGE_kmod-input-joydev is not set +# CONFIG_PACKAGE_kmod-input-matrixkmap is not set +# CONFIG_PACKAGE_kmod-input-polldev is not set +# CONFIG_PACKAGE_kmod-input-uinput is not set + +# +# LED modules +# +# CONFIG_PACKAGE_kmod-leds-gpio is not set +# CONFIG_PACKAGE_kmod-leds-nu801 is not set +# CONFIG_PACKAGE_kmod-leds-pca963x is not set +# CONFIG_PACKAGE_kmod-leds-rb750 is not set +# CONFIG_PACKAGE_kmod-leds-wndr3700-usb is not set +# CONFIG_PACKAGE_kmod-ledtrig-default-on is not set +# CONFIG_PACKAGE_kmod-ledtrig-gpio is not set +# CONFIG_PACKAGE_kmod-ledtrig-heartbeat is not set +# CONFIG_PACKAGE_kmod-ledtrig-netdev is not set +# CONFIG_PACKAGE_kmod-ledtrig-oneshot is not set +# CONFIG_PACKAGE_kmod-ledtrig-timer is not set +# CONFIG_PACKAGE_kmod-ledtrig-transient is not set + +# +# Libraries +# +# CONFIG_PACKAGE_kmod-lib-cordic is not set +CONFIG_PACKAGE_kmod-lib-crc-ccitt=y +# CONFIG_PACKAGE_kmod-lib-crc-itu-t is not set +CONFIG_PACKAGE_kmod-lib-crc16=y +# CONFIG_PACKAGE_kmod-lib-crc32c is not set +# CONFIG_PACKAGE_kmod-lib-crc7 is not set +# CONFIG_PACKAGE_kmod-lib-crc8 is not set +CONFIG_PACKAGE_kmod-lib-textsearch=y +CONFIG_PACKAGE_kmod-lib-zlib-deflate=y +CONFIG_PACKAGE_kmod-lib-zlib-inflate=y + +# +# Native Language Support +# +CONFIG_PACKAGE_kmod-nls-base=y +# CONFIG_PACKAGE_kmod-nls-cp1250 is not set +# CONFIG_PACKAGE_kmod-nls-cp1251 is not set +CONFIG_PACKAGE_kmod-nls-cp437=y +# CONFIG_PACKAGE_kmod-nls-cp775 is not set +# CONFIG_PACKAGE_kmod-nls-cp850 is not set +# CONFIG_PACKAGE_kmod-nls-cp852 is not set +# CONFIG_PACKAGE_kmod-nls-cp862 is not set +# CONFIG_PACKAGE_kmod-nls-cp864 is not set +# CONFIG_PACKAGE_kmod-nls-cp866 is not set +# CONFIG_PACKAGE_kmod-nls-cp932 is not set +# CONFIG_PACKAGE_kmod-nls-cp936 is not set +# CONFIG_PACKAGE_kmod-nls-cp950 is not set +CONFIG_PACKAGE_kmod-nls-iso8859-1=y +# CONFIG_PACKAGE_kmod-nls-iso8859-13 is not set +# CONFIG_PACKAGE_kmod-nls-iso8859-15 is not set +# CONFIG_PACKAGE_kmod-nls-iso8859-2 is not set +# CONFIG_PACKAGE_kmod-nls-iso8859-6 is not set +# CONFIG_PACKAGE_kmod-nls-iso8859-8 is not set +# CONFIG_PACKAGE_kmod-nls-koi8r is not set +CONFIG_PACKAGE_kmod-nls-utf8=y + +# +# Netfilter Extensions +# +# CONFIG_PACKAGE_kmod-arptables is not set +# CONFIG_PACKAGE_kmod-ebtables is not set +CONFIG_PACKAGE_kmod-ip6tables=y +# CONFIG_PACKAGE_kmod-ip6tables-extra is not set +# CONFIG_PACKAGE_kmod-ipt-account is not set +# CONFIG_PACKAGE_kmod-ipt-chaos is not set +# CONFIG_PACKAGE_kmod-ipt-cluster is not set +# CONFIG_PACKAGE_kmod-ipt-clusterip is not set +# CONFIG_PACKAGE_kmod-ipt-compat-xtables is not set +# CONFIG_PACKAGE_kmod-ipt-condition is not set +CONFIG_PACKAGE_kmod-ipt-conntrack=y +CONFIG_PACKAGE_kmod-ipt-conntrack-extra=y +CONFIG_PACKAGE_kmod-ipt-core=y +# CONFIG_PACKAGE_kmod-ipt-debug is not set +# CONFIG_PACKAGE_kmod-ipt-delude is not set +# CONFIG_PACKAGE_kmod-ipt-dhcpmac is not set +# CONFIG_PACKAGE_kmod-ipt-dnetmap is not set +# CONFIG_PACKAGE_kmod-ipt-extra is not set +# CONFIG_PACKAGE_kmod-ipt-filter is not set +# CONFIG_PACKAGE_kmod-ipt-fuzzy is not set +# CONFIG_PACKAGE_kmod-ipt-geoip is not set +# CONFIG_PACKAGE_kmod-ipt-hashlimit is not set +# CONFIG_PACKAGE_kmod-ipt-iface is not set +# CONFIG_PACKAGE_kmod-ipt-ipmark is not set +CONFIG_PACKAGE_kmod-ipt-ipopt=y +# CONFIG_PACKAGE_kmod-ipt-ipp2p is not set +# CONFIG_PACKAGE_kmod-ipt-iprange is not set +CONFIG_PACKAGE_kmod-ipt-ipsec=y +CONFIG_PACKAGE_kmod-ipt-ipset=y +# CONFIG_PACKAGE_kmod-ipt-ipv4options is not set +# CONFIG_PACKAGE_kmod-ipt-led is not set +# CONFIG_PACKAGE_kmod-ipt-length2 is not set +# CONFIG_PACKAGE_kmod-ipt-logmark is not set +# CONFIG_PACKAGE_kmod-ipt-lscan is not set +# CONFIG_PACKAGE_kmod-ipt-lua is not set +CONFIG_PACKAGE_kmod-ipt-nat=y +CONFIG_PACKAGE_kmod-ipt-nat-extra=y +# CONFIG_PACKAGE_kmod-ipt-nat6 is not set +# CONFIG_PACKAGE_kmod-ipt-nathelper-rtsp is not set +# CONFIG_PACKAGE_kmod-ipt-nflog is not set +# CONFIG_PACKAGE_kmod-ipt-nfqueue is not set +# CONFIG_PACKAGE_kmod-ipt-psd is not set +# CONFIG_PACKAGE_kmod-ipt-quota2 is not set +# CONFIG_PACKAGE_kmod-ipt-raw is not set +# CONFIG_PACKAGE_kmod-ipt-raw6 is not set +# CONFIG_PACKAGE_kmod-ipt-rpfilter is not set +# CONFIG_PACKAGE_kmod-ipt-sysrq is not set +# CONFIG_PACKAGE_kmod-ipt-tarpit is not set +# CONFIG_PACKAGE_kmod-ipt-tee is not set +CONFIG_PACKAGE_kmod-ipt-tproxy=y +# CONFIG_PACKAGE_kmod-ipt-u32 is not set +# CONFIG_PACKAGE_kmod-ipt-ulog is not set +CONFIG_PACKAGE_kmod-nf-conntrack=y +CONFIG_PACKAGE_kmod-nf-conntrack-netlink=y +CONFIG_PACKAGE_kmod-nf-conntrack6=y +CONFIG_PACKAGE_kmod-nf-ipt=y +CONFIG_PACKAGE_kmod-nf-ipt6=y +CONFIG_PACKAGE_kmod-nf-nat=y +# CONFIG_PACKAGE_kmod-nf-nat6 is not set +CONFIG_PACKAGE_kmod-nf-nathelper=y +CONFIG_PACKAGE_kmod-nf-nathelper-extra=y +CONFIG_PACKAGE_kmod-nfnetlink=y +# CONFIG_PACKAGE_kmod-nfnetlink-log is not set +# CONFIG_PACKAGE_kmod-nfnetlink-queue is not set +# CONFIG_PACKAGE_kmod-nft-core is not set +# CONFIG_PACKAGE_kmod-nft-nat is not set +# CONFIG_PACKAGE_kmod-nft-nat6 is not set + +# +# Network Devices +# +# CONFIG_PACKAGE_kmod-3c59x is not set +# CONFIG_PACKAGE_kmod-8139cp is not set +# CONFIG_PACKAGE_kmod-8139too is not set +# CONFIG_PACKAGE_kmod-atl1 is not set +# CONFIG_PACKAGE_kmod-atl1c is not set +# CONFIG_PACKAGE_kmod-atl1e is not set +# CONFIG_PACKAGE_kmod-atl2 is not set +# CONFIG_PACKAGE_kmod-b44 is not set +# CONFIG_PACKAGE_kmod-bnx2 is not set +# CONFIG_PACKAGE_kmod-dm9000 is not set +# CONFIG_PACKAGE_kmod-dummy is not set +# CONFIG_PACKAGE_kmod-e100 is not set +# CONFIG_PACKAGE_kmod-e1000 is not set +# CONFIG_PACKAGE_kmod-et131x is not set +# CONFIG_PACKAGE_kmod-ethoc is not set +# CONFIG_PACKAGE_kmod-forcedeth is not set +# CONFIG_PACKAGE_kmod-gigaset is not set +# CONFIG_PACKAGE_kmod-hfcmulti is not set +# CONFIG_PACKAGE_kmod-hfcpci is not set +CONFIG_PACKAGE_kmod-ifb=y +# CONFIG_PACKAGE_kmod-igb is not set +# CONFIG_PACKAGE_kmod-ixgbe is not set +# CONFIG_PACKAGE_kmod-libphy is not set +CONFIG_PACKAGE_kmod-macvlan=y +# CONFIG_PACKAGE_kmod-mii is not set +# CONFIG_PACKAGE_kmod-natsemi is not set +# CONFIG_PACKAGE_kmod-ne2k-pci is not set +# CONFIG_PACKAGE_kmod-of-mdio is not set +# CONFIG_PACKAGE_kmod-pcnet32 is not set +# CONFIG_PACKAGE_kmod-phy-broadcom is not set +# CONFIG_PACKAGE_kmod-ppfe is not set +# CONFIG_PACKAGE_kmod-r6040 is not set +# CONFIG_PACKAGE_kmod-r8169 is not set +# CONFIG_PACKAGE_kmod-siit is not set +# CONFIG_PACKAGE_kmod-sis190 is not set +# CONFIG_PACKAGE_kmod-sis900 is not set +# CONFIG_PACKAGE_kmod-skge is not set +# CONFIG_PACKAGE_kmod-sky2 is not set +# CONFIG_PACKAGE_kmod-solos-pci is not set +# CONFIG_PACKAGE_kmod-spi-ks8995 is not set +# CONFIG_PACKAGE_kmod-swconfig is not set +# CONFIG_PACKAGE_kmod-switch-ip17xx is not set +# CONFIG_PACKAGE_kmod-switch-mvsw61xx is not set +# CONFIG_PACKAGE_kmod-switch-rtl8366-smi is not set +# CONFIG_PACKAGE_kmod-switch-rtl8366rb is not set +# CONFIG_PACKAGE_kmod-switch-rtl8366s is not set +# CONFIG_PACKAGE_kmod-switch-rtl8367b is not set +# CONFIG_PACKAGE_kmod-tg3 is not set +# CONFIG_PACKAGE_kmod-tulip is not set +# CONFIG_PACKAGE_kmod-via-rhine is not set +# CONFIG_PACKAGE_kmod-via-velocity is not set +# CONFIG_PACKAGE_kmod-vmxnet3 is not set + +# +# Network Support +# +# CONFIG_PACKAGE_kmod-appletalk is not set +# CONFIG_PACKAGE_kmod-atm is not set +# CONFIG_PACKAGE_kmod-ax25 is not set +# CONFIG_PACKAGE_kmod-batman-adv is not set +# CONFIG_PACKAGE_kmod-bonding is not set +# CONFIG_PACKAGE_kmod-capi is not set +# CONFIG_PACKAGE_kmod-dnsresolver is not set +CONFIG_PACKAGE_kmod-fast-classifier=y +CONFIG_PACKAGE_kmod-gre=y +# CONFIG_PACKAGE_kmod-gre6 is not set +# CONFIG_PACKAGE_kmod-ip-vti is not set +# CONFIG_PACKAGE_kmod-ip6-tunnel is not set +# CONFIG_PACKAGE_kmod-ip6-vti is not set +# CONFIG_PACKAGE_kmod-ipip is not set +CONFIG_PACKAGE_kmod-ipsec=y +CONFIG_PACKAGE_kmod-ipsec4=y +CONFIG_PACKAGE_kmod-ipsec6=y +CONFIG_PACKAGE_kmod-iptunnel=y +CONFIG_PACKAGE_kmod-iptunnel4=y +CONFIG_PACKAGE_kmod-iptunnel6=y +# CONFIG_PACKAGE_kmod-isdn4linux is not set +# CONFIG_PACKAGE_kmod-jool is not set +# CONFIG_PACKAGE_kmod-l2tp is not set +# CONFIG_PACKAGE_kmod-l2tp-eth is not set +# CONFIG_PACKAGE_kmod-l2tp-ip is not set +# CONFIG_PACKAGE_kmod-misdn is not set +# CONFIG_PACKAGE_kmod-mpls is not set +CONFIG_PACKAGE_kmod-ppp=y +CONFIG_PACKAGE_kmod-mppe=y +# CONFIG_PACKAGE_kmod-nat46 is not set +# CONFIG_PACKAGE_kmod-netem is not set +# CONFIG_PACKAGE_kmod-nlmon is not set +# CONFIG_PACKAGE_kmod-openvswitch is not set +# CONFIG_PACKAGE_kmod-pktgen is not set +# CONFIG_PACKAGE_kmod-ppp-synctty is not set +# CONFIG_PACKAGE_kmod-pppoa is not set +CONFIG_PACKAGE_kmod-pppoe=y +# CONFIG_PACKAGE_kmod-pppol2tp is not set +CONFIG_PACKAGE_kmod-pppox=y +# CONFIG_PACKAGE_kmod-pptp is not set +# CONFIG_PACKAGE_kmod-sched is not set +CONFIG_PACKAGE_kmod-sched-cake=y +# CONFIG_PACKAGE_kmod-sched-connmark is not set +CONFIG_PACKAGE_kmod-sched-core=y +# CONFIG_PACKAGE_kmod-sctp is not set +CONFIG_PACKAGE_kmod-shortcut-fe=y +# CONFIG_PACKAGE_kmod-shortcut-fe-cm is not set +# CONFIG_PACKAGE_kmod-sit is not set +CONFIG_PACKAGE_kmod-slhc=y +# CONFIG_PACKAGE_kmod-slip is not set +# CONFIG_PACKAGE_kmod-trelay is not set +# CONFIG_PACKAGE_kmod-tun is not set +# CONFIG_PACKAGE_kmod-veth is not set +# CONFIG_PACKAGE_kmod-vxlan is not set +# CONFIG_PACKAGE_kmod-wireguard is not set + +# +# Other modules +# +# CONFIG_PACKAGE_kmod-6lowpan is not set +# CONFIG_PACKAGE_kmod-ath3k is not set +# CONFIG_PACKAGE_kmod-bcma is not set +# CONFIG_PACKAGE_kmod-bluetooth is not set +# CONFIG_PACKAGE_kmod-bluetooth_6lowpan is not set +# CONFIG_PACKAGE_kmod-bmp085 is not set +# CONFIG_PACKAGE_kmod-bmp085-i2c is not set +# CONFIG_PACKAGE_kmod-bmp085-spi is not set +# CONFIG_PACKAGE_kmod-button-hotplug is not set +# CONFIG_PACKAGE_kmod-echo is not set +# CONFIG_PACKAGE_kmod-eeprom-93cx6 is not set +# CONFIG_PACKAGE_kmod-eeprom-at24 is not set +# CONFIG_PACKAGE_kmod-eeprom-at25 is not set +# CONFIG_PACKAGE_kmod-gpio-beeper is not set +CONFIG_PACKAGE_kmod-gpio-button-hotplug=y +# CONFIG_PACKAGE_kmod-gpio-dev is not set +# CONFIG_PACKAGE_kmod-gpio-mcp23s08 is not set +# CONFIG_PACKAGE_kmod-gpio-nxp-74hc164 is not set +# CONFIG_PACKAGE_kmod-gpio-pca953x is not set +# CONFIG_PACKAGE_kmod-gpio-pcf857x is not set +# CONFIG_PACKAGE_kmod-iio-core is not set +# CONFIG_PACKAGE_kmod-ikconfig is not set +# CONFIG_PACKAGE_kmod-lp is not set +# CONFIG_PACKAGE_kmod-mmc is not set +# CONFIG_PACKAGE_kmod-mtd-rw is not set +# CONFIG_PACKAGE_kmod-mtdtests is not set +# CONFIG_PACKAGE_kmod-pps is not set +# CONFIG_PACKAGE_kmod-pps-gpio is not set +# CONFIG_PACKAGE_kmod-pps-ldisc is not set +# CONFIG_PACKAGE_kmod-ptp is not set +# CONFIG_PACKAGE_kmod-random-core is not set +# CONFIG_PACKAGE_kmod-regmap is not set +# CONFIG_PACKAGE_kmod-rotary-gpio-custom is not set +# CONFIG_PACKAGE_kmod-rtc-ds1307 is not set +# CONFIG_PACKAGE_kmod-rtc-ds1374 is not set +# CONFIG_PACKAGE_kmod-rtc-ds1672 is not set +# CONFIG_PACKAGE_kmod-rtc-isl1208 is not set +# CONFIG_PACKAGE_kmod-rtc-pcf2123 is not set +# CONFIG_PACKAGE_kmod-rtc-pcf8563 is not set +# CONFIG_PACKAGE_kmod-rtc-pt7c4338 is not set +# CONFIG_PACKAGE_kmod-rtc-rs5c372a is not set +# CONFIG_PACKAGE_kmod-sdhci is not set +# CONFIG_PACKAGE_kmod-serial-8250 is not set +# CONFIG_PACKAGE_kmod-softdog is not set +# CONFIG_PACKAGE_kmod-ssb is not set +# CONFIG_PACKAGE_kmod-tpm is not set +# CONFIG_PACKAGE_kmod-tpm-i2c-atmel is not set +# CONFIG_PACKAGE_kmod-tpm-i2c-infineon is not set +# CONFIG_PACKAGE_kmod-w83627hf-wdt is not set +# CONFIG_PACKAGE_kmod-zram is not set + +# +# PCMCIA support +# + +# +# SPI Support +# +# CONFIG_PACKAGE_kmod-mmc-spi is not set +# CONFIG_PACKAGE_kmod-spi-bitbang is not set +# CONFIG_PACKAGE_kmod-spi-dev is not set +# CONFIG_PACKAGE_kmod-spi-gpio is not set +# CONFIG_PACKAGE_kmod-spi-gpio-custom is not set +# CONFIG_PACKAGE_kmod-spi-gpio-old is not set +# CONFIG_PACKAGE_kmod-spi-vsc7385 is not set + +# +# Sound Support +# +# CONFIG_PACKAGE_kmod-sound-core is not set + +# +# USB Support +# +# CONFIG_PACKAGE_kmod-usb-acm is not set +# CONFIG_PACKAGE_kmod-usb-atm is not set +# CONFIG_PACKAGE_kmod-usb-chipidea is not set +# CONFIG_PACKAGE_kmod-usb-cm109 is not set +CONFIG_PACKAGE_kmod-usb-core=y +# CONFIG_PACKAGE_kmod-usb-dwc2 is not set +# CONFIG_PACKAGE_kmod-usb-dwc3 is not set +# CONFIG_PACKAGE_kmod-usb-dwc3-of-simple is not set +CONFIG_PACKAGE_kmod-usb-ehci=y +# CONFIG_PACKAGE_kmod-usb-gadget-ehci-debug is not set +# CONFIG_PACKAGE_kmod-usb-gadget-eth is not set +# CONFIG_PACKAGE_kmod-usb-gadget-mass-storage is not set +# CONFIG_PACKAGE_kmod-usb-gadget-serial is not set +# CONFIG_PACKAGE_kmod-usb-hid is not set +CONFIG_PACKAGE_kmod-usb-ledtrig-usbport=y +# CONFIG_PACKAGE_kmod-usb-net is not set +# CONFIG_PACKAGE_kmod-usb-net2280 is not set +# CONFIG_PACKAGE_kmod-usb-ohci is not set +# CONFIG_PACKAGE_kmod-usb-ohci-pci is not set +# CONFIG_PACKAGE_kmod-usb-phy-qcom-ipq4019 is not set +CONFIG_PACKAGE_kmod-usb-printer=y +# CONFIG_PACKAGE_kmod-usb-serial is not set +CONFIG_PACKAGE_kmod-usb-storage=y +CONFIG_PACKAGE_kmod-usb-storage-extras=y +# CONFIG_PACKAGE_kmod-usb-uhci is not set +# CONFIG_PACKAGE_kmod-usb-wdm is not set +# CONFIG_PACKAGE_kmod-usb-yealink is not set +CONFIG_PACKAGE_kmod-usb2=y +# CONFIG_PACKAGE_kmod-usb2-pci is not set +# CONFIG_PACKAGE_kmod-usb3 is not set +# CONFIG_PACKAGE_kmod-usbip is not set +# CONFIG_PACKAGE_kmod-usbip-client is not set +# CONFIG_PACKAGE_kmod-usbip-server is not set +# CONFIG_PACKAGE_kmod-usbmon is not set + +# +# Video Support +# +# CONFIG_PACKAGE_kmod-video-core is not set + +# +# Virtualization +# + +# +# Voice over IP +# +# CONFIG_PACKAGE_kmod-dahdi is not set + +# +# W1 support +# +# CONFIG_PACKAGE_kmod-w1 is not set + +# +# WPAN 802.15.4 Support +# +# CONFIG_PACKAGE_kmod-at86rf230 is not set +# CONFIG_PACKAGE_kmod-cc2520 is not set +# CONFIG_PACKAGE_kmod-fakelb is not set +# CONFIG_PACKAGE_kmod-ieee802154 is not set +# CONFIG_PACKAGE_kmod-ieee802154_6lowpan is not set +# CONFIG_PACKAGE_kmod-mac802154 is not set +# CONFIG_PACKAGE_kmod-mrf24j40 is not set + +# +# Wireless Drivers +# +# CONFIG_PACKAGE_kmod-adm8211 is not set +CONFIG_PACKAGE_kmod-ath=y +CONFIG_ATH_USER_REGD=y +# CONFIG_PACKAGE_ATH_DEBUG is not set +CONFIG_PACKAGE_ATH_DFS=y +CONFIG_PACKAGE_kmod-ath10k=y +# CONFIG_PACKAGE_kmod-ath10k-ct is not set +# CONFIG_PACKAGE_kmod-ath5k is not set +# CONFIG_PACKAGE_kmod-ath6kl-sdio is not set +# CONFIG_PACKAGE_kmod-ath6kl-usb is not set +CONFIG_PACKAGE_kmod-ath9k=y +# CONFIG_ATH9K_SUPPORT_PCOEM is not set +# CONFIG_ATH9K_TX99 is not set +CONFIG_ATH9K_UBNTHSR=y +CONFIG_PACKAGE_kmod-ath9k-common=y +# CONFIG_PACKAGE_kmod-ath9k-htc is not set +# CONFIG_PACKAGE_kmod-b43 is not set +# CONFIG_PACKAGE_kmod-b43legacy is not set +# CONFIG_PACKAGE_kmod-brcmfmac is not set +# CONFIG_PACKAGE_kmod-brcmsmac is not set +# CONFIG_PACKAGE_kmod-brcmutil is not set +# CONFIG_PACKAGE_kmod-carl9170 is not set +CONFIG_PACKAGE_kmod-cfg80211=y +# CONFIG_PACKAGE_kmod-hermes is not set +# CONFIG_PACKAGE_kmod-hermes-pci is not set +# CONFIG_PACKAGE_kmod-hermes-plx is not set +# CONFIG_PACKAGE_kmod-iwl-legacy is not set +# CONFIG_PACKAGE_kmod-iwl3945 is not set +# CONFIG_PACKAGE_kmod-iwl4965 is not set +# CONFIG_PACKAGE_kmod-iwlwifi is not set +# CONFIG_PACKAGE_kmod-lib80211 is not set +# CONFIG_PACKAGE_kmod-libertas-sdio is not set +# CONFIG_PACKAGE_kmod-libertas-spi is not set +# CONFIG_PACKAGE_kmod-libertas-usb is not set +CONFIG_PACKAGE_kmod-mac80211=y +CONFIG_PACKAGE_MAC80211_DEBUGFS=y +# CONFIG_PACKAGE_MAC80211_TRACING is not set +CONFIG_PACKAGE_MAC80211_MESH=y +# CONFIG_PACKAGE_kmod-mac80211-hwsim is not set +# CONFIG_PACKAGE_kmod-mt76 is not set +# CONFIG_PACKAGE_kmod-mt76-core is not set +# CONFIG_PACKAGE_kmod-mt7601u is not set +# CONFIG_PACKAGE_kmod-mt7603 is not set +# CONFIG_PACKAGE_kmod-mt76x2 is not set +# CONFIG_PACKAGE_kmod-mwifiex-pcie is not set +# CONFIG_PACKAGE_kmod-mwifiex-sdio is not set +# CONFIG_PACKAGE_kmod-mwl8k is not set +# CONFIG_PACKAGE_kmod-net-prism54 is not set +# CONFIG_PACKAGE_kmod-net-rtl8192su is not set +# CONFIG_PACKAGE_kmod-owl-loader is not set +# CONFIG_PACKAGE_kmod-p54-common is not set +# CONFIG_PACKAGE_kmod-p54-pci is not set +# CONFIG_PACKAGE_kmod-p54-usb is not set +# CONFIG_PACKAGE_kmod-rt2400-pci is not set +# CONFIG_PACKAGE_kmod-rt2500-pci is not set +# CONFIG_PACKAGE_kmod-rt2500-usb is not set +# CONFIG_PACKAGE_kmod-rt2800-pci is not set +# CONFIG_PACKAGE_kmod-rt2800-usb is not set +# CONFIG_PACKAGE_kmod-rt2x00-lib is not set +# CONFIG_PACKAGE_kmod-rt61-pci is not set +# CONFIG_PACKAGE_kmod-rt73-usb is not set +# CONFIG_PACKAGE_kmod-rtl8180 is not set +# CONFIG_PACKAGE_kmod-rtl8187 is not set +# CONFIG_PACKAGE_kmod-rtl8192ce is not set +# CONFIG_PACKAGE_kmod-rtl8192cu is not set +# CONFIG_PACKAGE_kmod-rtl8192de is not set +# CONFIG_PACKAGE_kmod-rtl8192se is not set +# CONFIG_PACKAGE_kmod-rtl8821ae is not set +# CONFIG_PACKAGE_kmod-rtl8xxxu is not set +# CONFIG_PACKAGE_kmod-wl12xx is not set +# CONFIG_PACKAGE_kmod-wl18xx is not set +# CONFIG_PACKAGE_kmod-wlcore is not set +# CONFIG_PACKAGE_kmod-zd1211rw is not set + +# +# Languages +# + +# +# Erlang +# +# CONFIG_PACKAGE_erlang is not set +# CONFIG_PACKAGE_erlang-asn1 is not set +# CONFIG_PACKAGE_erlang-compiler is not set +# CONFIG_PACKAGE_erlang-crypto is not set +# CONFIG_PACKAGE_erlang-hipe is not set +# CONFIG_PACKAGE_erlang-inets is not set +# CONFIG_PACKAGE_erlang-mnesia is not set +# CONFIG_PACKAGE_erlang-runtime-tools is not set +# CONFIG_PACKAGE_erlang-snmp is not set +# CONFIG_PACKAGE_erlang-ssh is not set +# CONFIG_PACKAGE_erlang-ssl is not set +# CONFIG_PACKAGE_erlang-syntax-tools is not set + +# +# Java +# +# CONFIG_PACKAGE_jamvm is not set + +# +# Lua +# +# CONFIG_PACKAGE_dkjson is not set +# CONFIG_PACKAGE_json4lua is not set +CONFIG_PACKAGE_libiwinfo-lua=y +# CONFIG_PACKAGE_lpeg is not set +# CONFIG_PACKAGE_lsqlite3 is not set +CONFIG_PACKAGE_lua=y +# CONFIG_PACKAGE_lua-bencode is not set +# CONFIG_PACKAGE_lua-cjson is not set +# CONFIG_PACKAGE_lua-copas is not set +# CONFIG_PACKAGE_lua-coxpcall is not set +# CONFIG_PACKAGE_lua-examples is not set +# CONFIG_PACKAGE_lua-lzlib is not set +# CONFIG_PACKAGE_lua-md5 is not set +# CONFIG_PACKAGE_lua-mobdebug is not set +# CONFIG_PACKAGE_lua-mosquitto is not set +# CONFIG_PACKAGE_lua-openssl is not set +# CONFIG_PACKAGE_lua-penlight is not set +# CONFIG_PACKAGE_lua-rings is not set +# CONFIG_PACKAGE_lua-rs232 is not set +# CONFIG_PACKAGE_lua-sha2 is not set +# CONFIG_PACKAGE_lua-wsapi-base is not set +# CONFIG_PACKAGE_lua-wsapi-xavante is not set +# CONFIG_PACKAGE_lua-xavante is not set +# CONFIG_PACKAGE_luabitop is not set +# CONFIG_PACKAGE_luac is not set +# CONFIG_PACKAGE_luaexpat is not set +# CONFIG_PACKAGE_luafilesystem is not set +# CONFIG_PACKAGE_luai2c is not set +# CONFIG_PACKAGE_luajit is not set +# CONFIG_PACKAGE_lualanes is not set +# CONFIG_PACKAGE_luaposix is not set +# CONFIG_PACKAGE_luarocks is not set +# CONFIG_PACKAGE_luasec is not set +# CONFIG_PACKAGE_luasoap is not set +# CONFIG_PACKAGE_luasocket is not set +# CONFIG_PACKAGE_luasql-mysql is not set +# CONFIG_PACKAGE_luasql-pgsql is not set +# CONFIG_PACKAGE_luasql-sqlite3 is not set +CONFIG_PACKAGE_luci-lib-fs=y +# CONFIG_PACKAGE_luv is not set +# CONFIG_PACKAGE_lzmq is not set +# CONFIG_PACKAGE_uuid is not set + +# +# Node.js +# +# CONFIG_PACKAGE_node is not set + +# +# Module Selection +# +# CONFIG_NODEJS_ICU is not set +# CONFIG_PACKAGE_node-arduino-firmata is not set +# CONFIG_PACKAGE_node-cylon is not set +# CONFIG_PACKAGE_node-cylon-firmata is not set +# CONFIG_PACKAGE_node-cylon-gpio is not set +# CONFIG_PACKAGE_node-cylon-i2c is not set +# CONFIG_PACKAGE_node-hid is not set +# CONFIG_PACKAGE_node-npm is not set +# CONFIG_PACKAGE_node-serialport is not set + +# +# PHP +# +# CONFIG_PACKAGE_php7 is not set + +# +# Perl +# +# CONFIG_PACKAGE_perl is not set + +# +# Python +# +# CONFIG_PACKAGE_chardet is not set +# CONFIG_PACKAGE_django is not set +# CONFIG_PACKAGE_django-appconf is not set +# CONFIG_PACKAGE_django-compressor is not set +# CONFIG_PACKAGE_django-constance is not set +# CONFIG_PACKAGE_django-jsonfield is not set +# CONFIG_PACKAGE_django-picklefield is not set +# CONFIG_PACKAGE_django-postoffice is not set +# CONFIG_PACKAGE_django-restframework is not set +# CONFIG_PACKAGE_django-statici18n is not set +# CONFIG_PACKAGE_et_xmlfile is not set +# CONFIG_PACKAGE_flup is not set +# CONFIG_PACKAGE_gunicorn is not set +# CONFIG_PACKAGE_jdcal is not set +# CONFIG_PACKAGE_micropython is not set +# CONFIG_PACKAGE_micropython-lib is not set +# CONFIG_PACKAGE_openpyxl is not set +# CONFIG_PACKAGE_pillow is not set +# CONFIG_PACKAGE_python is not set +# CONFIG_PACKAGE_python-asn1crypto is not set +# CONFIG_PACKAGE_python-attrs is not set +# CONFIG_PACKAGE_python-base is not set +# CONFIG_PACKAGE_python-base-src is not set +# CONFIG_PACKAGE_python-cffi is not set +# CONFIG_PACKAGE_python-codecs is not set +# CONFIG_PACKAGE_python-codecs-src is not set +# CONFIG_PACKAGE_python-compiler is not set +# CONFIG_PACKAGE_python-compiler-src is not set +# CONFIG_PACKAGE_python-crcmod is not set +# CONFIG_PACKAGE_python-crypto is not set +# CONFIG_PACKAGE_python-cryptography is not set +# CONFIG_PACKAGE_python-ctypes is not set +# CONFIG_PACKAGE_python-ctypes-src is not set +# CONFIG_PACKAGE_python-curl is not set +# CONFIG_PACKAGE_python-dateutil is not set +# CONFIG_PACKAGE_python-db is not set +# CONFIG_PACKAGE_python-db-src is not set +# CONFIG_PACKAGE_python-decimal is not set +# CONFIG_PACKAGE_python-decimal-src is not set +# CONFIG_PACKAGE_python-dev is not set +# CONFIG_PACKAGE_python-dev-src is not set +# CONFIG_PACKAGE_python-distutils is not set +# CONFIG_PACKAGE_python-distutils-src is not set +# CONFIG_PACKAGE_python-dns is not set +# CONFIG_PACKAGE_python-dpkt is not set +# CONFIG_PACKAGE_python-egenix-mx-base is not set +# CONFIG_PACKAGE_python-email is not set +# CONFIG_PACKAGE_python-email-src is not set +# CONFIG_PACKAGE_python-enum34 is not set +# CONFIG_PACKAGE_python-evdev is not set +# CONFIG_PACKAGE_python-gdbm is not set +# CONFIG_PACKAGE_python-gdbm-src is not set +# CONFIG_PACKAGE_python-gmpy2 is not set +# CONFIG_PACKAGE_python-gnupg is not set +# CONFIG_PACKAGE_python-idna is not set +# CONFIG_PACKAGE_python-ipaddress is not set +# CONFIG_PACKAGE_python-ldap is not set +# CONFIG_PACKAGE_python-lib2to3 is not set +# CONFIG_PACKAGE_python-lib2to3-src is not set +# CONFIG_PACKAGE_python-light is not set +# CONFIG_PACKAGE_python-light-src is not set +# CONFIG_PACKAGE_python-logging is not set +# CONFIG_PACKAGE_python-logging-src is not set +# CONFIG_PACKAGE_python-lxml is not set +# CONFIG_PACKAGE_python-multiprocessing is not set +# CONFIG_PACKAGE_python-multiprocessing-src is not set +# CONFIG_PACKAGE_python-mysql is not set +# CONFIG_PACKAGE_python-ncurses is not set +# CONFIG_PACKAGE_python-ncurses-src is not set +# CONFIG_PACKAGE_python-openssl is not set +# CONFIG_PACKAGE_python-openssl-src is not set +# CONFIG_PACKAGE_python-parsley is not set +# CONFIG_PACKAGE_python-pcapy is not set +# CONFIG_PACKAGE_python-pip is not set +# CONFIG_PACKAGE_python-pip-conf is not set +# CONFIG_PACKAGE_python-pip-src is not set +# CONFIG_PACKAGE_python-ply is not set +# CONFIG_PACKAGE_python-psycopg2 is not set +# CONFIG_PACKAGE_python-pyasn1 is not set +# CONFIG_PACKAGE_python-pyasn1-modules is not set +# CONFIG_PACKAGE_python-pycparser is not set +# CONFIG_PACKAGE_python-pydoc is not set +# CONFIG_PACKAGE_python-pydoc-src is not set +# CONFIG_PACKAGE_python-pyodbc is not set +# CONFIG_PACKAGE_python-pyopenssl is not set +# CONFIG_PACKAGE_python-pyptlib is not set +# CONFIG_PACKAGE_python-pyserial is not set +# CONFIG_PACKAGE_python-service-identity is not set +# CONFIG_PACKAGE_python-setuptools is not set +# CONFIG_PACKAGE_python-setuptools-src is not set +# CONFIG_PACKAGE_python-six is not set +# CONFIG_PACKAGE_python-smbus is not set +# CONFIG_PACKAGE_python-sqlite3 is not set +# CONFIG_PACKAGE_python-sqlite3-src is not set +# CONFIG_PACKAGE_python-src is not set +# CONFIG_PACKAGE_python-txsocksx is not set +# CONFIG_PACKAGE_python-unittest is not set +# CONFIG_PACKAGE_python-unittest-src is not set +# CONFIG_PACKAGE_python-urllib3 is not set +# CONFIG_PACKAGE_python-xml is not set +# CONFIG_PACKAGE_python-xml-src is not set +# CONFIG_PACKAGE_python-yaml is not set +# CONFIG_PACKAGE_python3 is not set +# CONFIG_PACKAGE_python3-asn1crypto is not set +# CONFIG_PACKAGE_python3-asyncio is not set +# CONFIG_PACKAGE_python3-asyncio-src is not set +# CONFIG_PACKAGE_python3-base is not set +# CONFIG_PACKAGE_python3-base-src is not set +# CONFIG_PACKAGE_python3-bottle is not set +# CONFIG_PACKAGE_python3-cffi is not set +# CONFIG_PACKAGE_python3-click is not set +# CONFIG_PACKAGE_python3-codecs is not set +# CONFIG_PACKAGE_python3-codecs-src is not set +# CONFIG_PACKAGE_python3-cryptography is not set +# CONFIG_PACKAGE_python3-ctypes is not set +# CONFIG_PACKAGE_python3-ctypes-src is not set +# CONFIG_PACKAGE_python3-dbm is not set +# CONFIG_PACKAGE_python3-dbm-src is not set +# CONFIG_PACKAGE_python3-decimal is not set +# CONFIG_PACKAGE_python3-decimal-src is not set +# CONFIG_PACKAGE_python3-dev is not set +# CONFIG_PACKAGE_python3-dev-src is not set +# CONFIG_PACKAGE_python3-distutils is not set +# CONFIG_PACKAGE_python3-distutils-src is not set +# CONFIG_PACKAGE_python3-email is not set +# CONFIG_PACKAGE_python3-email-src is not set +# CONFIG_PACKAGE_python3-evdev is not set +# CONFIG_PACKAGE_python3-flask is not set +# CONFIG_PACKAGE_python3-gdbm is not set +# CONFIG_PACKAGE_python3-gdbm-src is not set +# CONFIG_PACKAGE_python3-gnupg is not set +# CONFIG_PACKAGE_python3-idna is not set +# CONFIG_PACKAGE_python3-itsdangerous is not set +# CONFIG_PACKAGE_python3-jinja2 is not set +# CONFIG_PACKAGE_python3-lib2to3 is not set +# CONFIG_PACKAGE_python3-lib2to3-src is not set +# CONFIG_PACKAGE_python3-light is not set +# CONFIG_PACKAGE_python3-light-src is not set +# CONFIG_PACKAGE_python3-logging is not set +# CONFIG_PACKAGE_python3-logging-src is not set +# CONFIG_PACKAGE_python3-lxml is not set +# CONFIG_PACKAGE_python3-lzma is not set +# CONFIG_PACKAGE_python3-lzma-src is not set +# CONFIG_PACKAGE_python3-markupsafe is not set +# CONFIG_PACKAGE_python3-multiprocessing is not set +# CONFIG_PACKAGE_python3-multiprocessing-src is not set +# CONFIG_PACKAGE_python3-ncurses is not set +# CONFIG_PACKAGE_python3-ncurses-src is not set +# CONFIG_PACKAGE_python3-openssl is not set +# CONFIG_PACKAGE_python3-openssl-src is not set +# CONFIG_PACKAGE_python3-pip is not set +# CONFIG_PACKAGE_python3-pip-src is not set +# CONFIG_PACKAGE_python3-ply is not set +# CONFIG_PACKAGE_python3-pyasn1 is not set +# CONFIG_PACKAGE_python3-pyasn1-modules is not set +# CONFIG_PACKAGE_python3-pycparser is not set +# CONFIG_PACKAGE_python3-pydoc is not set +# CONFIG_PACKAGE_python3-pydoc-src is not set +# CONFIG_PACKAGE_python3-pyodbc is not set +# CONFIG_PACKAGE_python3-pyopenssl is not set +# CONFIG_PACKAGE_python3-setuptools is not set +# CONFIG_PACKAGE_python3-setuptools-src is not set +# CONFIG_PACKAGE_python3-six is not set +# CONFIG_PACKAGE_python3-smbus is not set +# CONFIG_PACKAGE_python3-sqlite3 is not set +# CONFIG_PACKAGE_python3-sqlite3-src is not set +# CONFIG_PACKAGE_python3-src is not set +# CONFIG_PACKAGE_python3-unittest is not set +# CONFIG_PACKAGE_python3-unittest-src is not set +# CONFIG_PACKAGE_python3-werkzeug is not set +# CONFIG_PACKAGE_python3-xml is not set +# CONFIG_PACKAGE_python3-xml-src is not set +# CONFIG_PACKAGE_python3-yaml is not set +# CONFIG_PACKAGE_pytz is not set +# CONFIG_PACKAGE_rcssmin is not set +# CONFIG_PACKAGE_simplejson is not set +# CONFIG_PACKAGE_twisted is not set +# CONFIG_PACKAGE_zope-interface is not set + +# +# Ruby +# +# CONFIG_PACKAGE_ruby is not set + +# +# Tcl +# +# CONFIG_PACKAGE_vala is not set + +# +# Libraries +# + +# +# Compression +# +# CONFIG_PACKAGE_libbz2 is not set +# CONFIG_PACKAGE_liblzma is not set +# CONFIG_PACKAGE_libunrar is not set + +# +# Filesystem +# +# CONFIG_PACKAGE_libacl is not set +# CONFIG_PACKAGE_libattr is not set +# CONFIG_PACKAGE_libext2fs is not set +# CONFIG_PACKAGE_libfuse is not set +# CONFIG_PACKAGE_libow is not set +# CONFIG_PACKAGE_libow-capi is not set +# CONFIG_PACKAGE_libsysfs is not set + +# +# Firewall +# +# CONFIG_PACKAGE_libfko is not set +CONFIG_PACKAGE_libip4tc=y +CONFIG_PACKAGE_libip6tc=y +# CONFIG_PACKAGE_libiptc is not set +CONFIG_PACKAGE_libxtables=y + +# +# Instant Messaging +# +# CONFIG_PACKAGE_quasselc is not set + +# +# IoT +# +# CONFIG_PACKAGE_libupm is not set +# CONFIG_PACKAGE_libupm-a110x is not set +# CONFIG_PACKAGE_libupm-ad8232 is not set +# CONFIG_PACKAGE_libupm-adafruitss is not set +# CONFIG_PACKAGE_libupm-adc121c021 is not set +# CONFIG_PACKAGE_libupm-adis16448 is not set +# CONFIG_PACKAGE_libupm-adxl335 is not set +# CONFIG_PACKAGE_libupm-adxl345 is not set +# CONFIG_PACKAGE_libupm-am2315 is not set +# CONFIG_PACKAGE_libupm-apds9002 is not set +# CONFIG_PACKAGE_libupm-at42qt1070 is not set +# CONFIG_PACKAGE_libupm-biss0001 is not set +# CONFIG_PACKAGE_libupm-bmpx8x is not set +# CONFIG_PACKAGE_libupm-buzzer is not set +# CONFIG_PACKAGE_libupm-cjq4435 is not set +# CONFIG_PACKAGE_libupm-ds1307 is not set +# CONFIG_PACKAGE_libupm-ecs1030 is not set +# CONFIG_PACKAGE_libupm-enc03r is not set +# CONFIG_PACKAGE_libupm-flex is not set +# CONFIG_PACKAGE_libupm-gas is not set +# CONFIG_PACKAGE_libupm-gp2y0a is not set +# CONFIG_PACKAGE_libupm-grove is not set +# CONFIG_PACKAGE_libupm-grovecircularled is not set +# CONFIG_PACKAGE_libupm-grovecollision is not set +# CONFIG_PACKAGE_libupm-groveehr is not set +# CONFIG_PACKAGE_libupm-groveeldriver is not set +# CONFIG_PACKAGE_libupm-groveelectromagnet is not set +# CONFIG_PACKAGE_libupm-groveemg is not set +# CONFIG_PACKAGE_libupm-grovegprs is not set +# CONFIG_PACKAGE_libupm-grovegsr is not set +# CONFIG_PACKAGE_libupm-grovelinefinder is not set +# CONFIG_PACKAGE_libupm-grovemd is not set +# CONFIG_PACKAGE_libupm-grovemoisture is not set +# CONFIG_PACKAGE_libupm-groveo2 is not set +# CONFIG_PACKAGE_libupm-grovescam is not set +# CONFIG_PACKAGE_libupm-grovespeaker is not set +# CONFIG_PACKAGE_libupm-grovevdiv is not set +# CONFIG_PACKAGE_libupm-grovewater is not set +# CONFIG_PACKAGE_libupm-grovewfs is not set +# CONFIG_PACKAGE_libupm-guvas12d is not set +# CONFIG_PACKAGE_libupm-h3lis331dl is not set +# CONFIG_PACKAGE_libupm-hcsr04 is not set +# CONFIG_PACKAGE_libupm-hm11 is not set +# CONFIG_PACKAGE_libupm-hmc5883l is not set +# CONFIG_PACKAGE_libupm-hmtrp is not set +# CONFIG_PACKAGE_libupm-hp20x is not set +# CONFIG_PACKAGE_libupm-ht9170 is not set +# CONFIG_PACKAGE_libupm-htu21d is not set +# CONFIG_PACKAGE_libupm-hx711 is not set +# CONFIG_PACKAGE_libupm-i2clcd is not set +# CONFIG_PACKAGE_libupm-ina132 is not set +# CONFIG_PACKAGE_libupm-isd1820 is not set +# CONFIG_PACKAGE_libupm-itg3200 is not set +# CONFIG_PACKAGE_libupm-joystick12 is not set +# CONFIG_PACKAGE_libupm-l298 is not set +# CONFIG_PACKAGE_libupm-ldt0028 is not set +# CONFIG_PACKAGE_libupm-lm35 is not set +# CONFIG_PACKAGE_libupm-lol is not set +# CONFIG_PACKAGE_libupm-loudness is not set +# CONFIG_PACKAGE_libupm-lpd8806 is not set +# CONFIG_PACKAGE_libupm-lsm303 is not set +# CONFIG_PACKAGE_libupm-lsm9ds0 is not set +# CONFIG_PACKAGE_libupm-m24lr64e is not set +# CONFIG_PACKAGE_libupm-max31723 is not set +# CONFIG_PACKAGE_libupm-max31855 is not set +# CONFIG_PACKAGE_libupm-max44000 is not set +# CONFIG_PACKAGE_libupm-max5487 is not set +# CONFIG_PACKAGE_libupm-maxds3231m is not set +# CONFIG_PACKAGE_libupm-maxsonarez is not set +# CONFIG_PACKAGE_libupm-mg811 is not set +# CONFIG_PACKAGE_libupm-mhz16 is not set +# CONFIG_PACKAGE_libupm-mic is not set +# CONFIG_PACKAGE_libupm-mlx90614 is not set +# CONFIG_PACKAGE_libupm-mma7455 is not set +# CONFIG_PACKAGE_libupm-mma7660 is not set +# CONFIG_PACKAGE_libupm-mpl3115a2 is not set +# CONFIG_PACKAGE_libupm-mpr121 is not set +# CONFIG_PACKAGE_libupm-mpu9150 is not set +# CONFIG_PACKAGE_libupm-mq303a is not set +# CONFIG_PACKAGE_libupm-my9221 is not set +# CONFIG_PACKAGE_libupm-nrf24l01 is not set +# CONFIG_PACKAGE_libupm-nrf8001 is not set +# CONFIG_PACKAGE_libupm-nunchuck is not set +# CONFIG_PACKAGE_libupm-otp538u is not set +# CONFIG_PACKAGE_libupm-pn532 is not set +# CONFIG_PACKAGE_libupm-ppd42ns is not set +# CONFIG_PACKAGE_libupm-pulsensor is not set +# CONFIG_PACKAGE_libupm-rfr359f is not set +# CONFIG_PACKAGE_libupm-rgbringcoder is not set +# CONFIG_PACKAGE_libupm-rotaryencoder is not set +# CONFIG_PACKAGE_libupm-rpr220 is not set +# CONFIG_PACKAGE_libupm-servo is not set +# CONFIG_PACKAGE_libupm-si114x is not set +# CONFIG_PACKAGE_libupm-sm130 is not set +# CONFIG_PACKAGE_libupm-st7735 is not set +# CONFIG_PACKAGE_libupm-stepmotor is not set +# CONFIG_PACKAGE_libupm-sx6119 is not set +# CONFIG_PACKAGE_libupm-ta12200 is not set +# CONFIG_PACKAGE_libupm-tcs3414cs is not set +# CONFIG_PACKAGE_libupm-th02 is not set +# CONFIG_PACKAGE_libupm-tm1637 is not set +# CONFIG_PACKAGE_libupm-tsl2561 is not set +# CONFIG_PACKAGE_libupm-ttp223 is not set +# CONFIG_PACKAGE_libupm-ublox6 is not set +# CONFIG_PACKAGE_libupm-uln200xa is not set +# CONFIG_PACKAGE_libupm-waterlevel is not set +# CONFIG_PACKAGE_libupm-wheelencoder is not set +# CONFIG_PACKAGE_libupm-wt5001 is not set +# CONFIG_PACKAGE_libupm-yg1006 is not set +# CONFIG_PACKAGE_libupm-zfm20 is not set + +# +# Languages +# +# CONFIG_PACKAGE_libyaml is not set + +# +# Networking +# +# CONFIG_PACKAGE_libsctp is not set + +# +# SSL +# +# CONFIG_PACKAGE_libcyassl is not set +# CONFIG_PACKAGE_libgnutls is not set +# CONFIG_PACKAGE_libmbedtls is not set +CONFIG_PACKAGE_libopenssl=y +CONFIG_OPENSSL_WITH_EC=y +# CONFIG_OPENSSL_WITH_EC2M is not set +# CONFIG_OPENSSL_WITH_SSL3 is not set +CONFIG_OPENSSL_WITH_DEPRECATED=y +# CONFIG_OPENSSL_WITH_DTLS is not set +# CONFIG_OPENSSL_WITH_COMPRESSION is not set +CONFIG_OPENSSL_WITH_NPN=y +CONFIG_OPENSSL_WITH_PSK=y +CONFIG_OPENSSL_WITH_SRP=y +CONFIG_OPENSSL_THREADS=y +# CONFIG_OPENSSL_HARDWARE_SUPPORT is not set +# CONFIG_OPENSSL_ENGINE_CRYPTO is not set + +# +# Sound +# +# CONFIG_PACKAGE_liblo is not set + +# +# Telephony +# +# CONFIG_PACKAGE_bcg729 is not set +# CONFIG_PACKAGE_dahdi-tools-libtonezone is not set +# CONFIG_PACKAGE_libiksemel is not set +# CONFIG_PACKAGE_libortp is not set +# CONFIG_PACKAGE_libosip2 is not set +# CONFIG_PACKAGE_libpj is not set +# CONFIG_PACKAGE_libpjlib-util is not set +# CONFIG_PACKAGE_libpjmedia is not set +# CONFIG_PACKAGE_libpjnath is not set +# CONFIG_PACKAGE_libpjsip is not set +# CONFIG_PACKAGE_libpjsip-simple is not set +# CONFIG_PACKAGE_libpjsip-ua is not set +# CONFIG_PACKAGE_libpjsua is not set +# CONFIG_PACKAGE_libpjsua2 is not set +# CONFIG_PACKAGE_libre is not set +# CONFIG_PACKAGE_librem is not set +# CONFIG_PACKAGE_libspandsp is not set +# CONFIG_PACKAGE_libsrtp is not set +# CONFIG_PACKAGE_libsrtp2 is not set + +# +# database +# +# CONFIG_PACKAGE_libpq is not set +# CONFIG_PACKAGE_libsqlite3 is not set +# CONFIG_PACKAGE_pgsqlodbc is not set +# CONFIG_PACKAGE_psqlodbca is not set +# CONFIG_PACKAGE_psqlodbcw is not set +# CONFIG_PACKAGE_tdb is not set +# CONFIG_PACKAGE_unixodbc is not set + +# +# libelektra +# +# CONFIG_PACKAGE_libelektra-boost is not set +# CONFIG_PACKAGE_libelektra-core is not set +# CONFIG_PACKAGE_libelektra-cpp is not set +# CONFIG_PACKAGE_libelektra-crypto is not set +# CONFIG_PACKAGE_libelektra-curlget is not set +# CONFIG_PACKAGE_libelektra-dbus is not set +# CONFIG_PACKAGE_libelektra-extra is not set +# CONFIG_PACKAGE_libelektra-lua is not set +# CONFIG_PACKAGE_libelektra-plugins is not set +# CONFIG_PACKAGE_libelektra-python2 is not set +# CONFIG_PACKAGE_libelektra-python3 is not set +# CONFIG_PACKAGE_libelektra-resolvers is not set +# CONFIG_PACKAGE_libelektra-xml is not set +# CONFIG_PACKAGE_libelektra-yajl is not set +# CONFIG_PACKAGE_alsa-lib is not set +# CONFIG_PACKAGE_argp-standalone is not set +# CONFIG_PACKAGE_avro-c is not set +# CONFIG_PACKAGE_bind-libs is not set +# CONFIG_PACKAGE_bluez-libs is not set +# CONFIG_PACKAGE_boost is not set +# CONFIG_PACKAGE_ccid is not set +# CONFIG_PACKAGE_check is not set +# CONFIG_PACKAGE_classpath is not set +# CONFIG_PACKAGE_classpath-tools is not set +# CONFIG_PACKAGE_confuse is not set +# CONFIG_PACKAGE_dtndht is not set +# CONFIG_PACKAGE_fcgi is not set +# CONFIG_PACKAGE_fftw3 is not set +# CONFIG_PACKAGE_fftw3f is not set +# CONFIG_PACKAGE_giflib is not set +# CONFIG_PACKAGE_glib2 is not set +# CONFIG_PACKAGE_glog is not set +# CONFIG_PACKAGE_hidapi is not set +# CONFIG_PACKAGE_ibrcommon is not set +# CONFIG_PACKAGE_ibrdtn is not set +# CONFIG_PACKAGE_icu is not set +# CONFIG_PACKAGE_jansson is not set +# CONFIG_PACKAGE_knot-libdnssec is not set +# CONFIG_PACKAGE_knot-libknot is not set +# CONFIG_PACKAGE_knot-libzscanner is not set +# CONFIG_PACKAGE_libaio is not set +# CONFIG_PACKAGE_libantlr3c is not set +# CONFIG_PACKAGE_libao is not set +# CONFIG_PACKAGE_libapr is not set +# CONFIG_PACKAGE_libaprutil is not set +# CONFIG_PACKAGE_libarchive is not set +# CONFIG_PACKAGE_libarchive-noopenssl is not set +# CONFIG_PACKAGE_libartnet is not set +# CONFIG_PACKAGE_libaudiofile is not set +# CONFIG_PACKAGE_libavahi-client is not set +# CONFIG_PACKAGE_libavahi-compat-libdnssd is not set +# CONFIG_PACKAGE_libavahi-dbus-support is not set +# CONFIG_PACKAGE_libavahi-nodbus-support is not set +# CONFIG_PACKAGE_libavl is not set +# CONFIG_PACKAGE_libbfd is not set +# CONFIG_PACKAGE_libblkid is not set +CONFIG_PACKAGE_libblobmsg-json=y +# CONFIG_PACKAGE_libcanfestival is not set +# CONFIG_PACKAGE_libcap is not set +# CONFIG_PACKAGE_libcares is not set +# CONFIG_PACKAGE_libcharset is not set +# CONFIG_PACKAGE_libcoap is not set +# CONFIG_PACKAGE_libconfig is not set +# CONFIG_PACKAGE_libcryptopp is not set +# CONFIG_PACKAGE_libcurl is not set +# CONFIG_PACKAGE_libdaemon is not set +# CONFIG_PACKAGE_libdaq is not set +# CONFIG_PACKAGE_libdb47 is not set +# CONFIG_PACKAGE_libdb47xx is not set +# CONFIG_PACKAGE_libdbi is not set +# CONFIG_PACKAGE_libdbus is not set +# CONFIG_PACKAGE_libdevmapper is not set +# CONFIG_PACKAGE_libdmapsharing is not set +# CONFIG_PACKAGE_libdnet is not set +# CONFIG_PACKAGE_libdouble-conversion is not set +# CONFIG_PACKAGE_libdrm is not set +# CONFIG_PACKAGE_libedit is not set +# CONFIG_PACKAGE_libelf1 is not set +# CONFIG_PACKAGE_libecdsautil is not set +# CONFIG_PACKAGE_libesmtp is not set +# CONFIG_PACKAGE_libestr is not set +# CONFIG_PACKAGE_libev is not set +# CONFIG_PACKAGE_libevdev is not set +# CONFIG_PACKAGE_libevent is not set +# CONFIG_PACKAGE_libevent2 is not set +# CONFIG_PACKAGE_libevent2-core is not set +# CONFIG_PACKAGE_libevent2-extra is not set +# CONFIG_PACKAGE_libevent2-openssl is not set +# CONFIG_PACKAGE_libevent2-pthreads is not set +# CONFIG_PACKAGE_libeventlog is not set +# CONFIG_PACKAGE_libevhtp is not set +# CONFIG_PACKAGE_libexif is not set +# CONFIG_PACKAGE_libexpat is not set +# CONFIG_PACKAGE_libexslt is not set +# CONFIG_PACKAGE_libextractor is not set +# CONFIG_PACKAGE_libf2fs is not set +# CONFIG_PACKAGE_libfaad2 is not set +# CONFIG_PACKAGE_libfastjson is not set +# CONFIG_PACKAGE_libfdisk is not set +# CONFIG_PACKAGE_libfdt is not set +# CONFIG_PACKAGE_libffi is not set +# CONFIG_PACKAGE_libffmpeg-audio-dec is not set +# CONFIG_PACKAGE_libffmpeg-custom is not set +# CONFIG_PACKAGE_libffmpeg-full is not set +# CONFIG_PACKAGE_libffmpeg-mini is not set +# CONFIG_PACKAGE_libflac is not set +# CONFIG_PACKAGE_libfreetype is not set +# CONFIG_PACKAGE_libftdi is not set +# CONFIG_PACKAGE_libftdi1 is not set +# CONFIG_PACKAGE_libgcrypt is not set +# CONFIG_PACKAGE_libgd is not set +# CONFIG_PACKAGE_libgdbm is not set +# CONFIG_PACKAGE_libgee is not set +# CONFIG_PACKAGE_libglpk is not set +CONFIG_PACKAGE_libgmp=y +# CONFIG_PACKAGE_libgnurl is not set +# CONFIG_PACKAGE_libgpg-error is not set +# CONFIG_PACKAGE_libgphoto2 is not set +# CONFIG_PACKAGE_libgps is not set +# CONFIG_PACKAGE_libhamlib is not set +# CONFIG_PACKAGE_libhavege is not set +# CONFIG_PACKAGE_libhiredis is not set +# CONFIG_PACKAGE_libhttp-parser is not set +# CONFIG_PACKAGE_libical is not set +# CONFIG_PACKAGE_libiconv is not set +# CONFIG_PACKAGE_libiconv-full is not set +# CONFIG_PACKAGE_libid3tag is not set +# CONFIG_PACKAGE_libidn is not set +# CONFIG_PACKAGE_libiio is not set +# CONFIG_PACKAGE_libimobiledevice is not set +# CONFIG_PACKAGE_libinput is not set +# CONFIG_PACKAGE_libintl is not set +# CONFIG_PACKAGE_libintl-full is not set +# CONFIG_PACKAGE_libiw is not set +CONFIG_PACKAGE_libiwinfo=y +# CONFIG_PACKAGE_libjpeg is not set +CONFIG_PACKAGE_libjson-c=y +# CONFIG_PACKAGE_libkmod is not set +# CONFIG_PACKAGE_libldns is not set +# CONFIG_PACKAGE_libltdl is not set +CONFIG_PACKAGE_liblua=y +# CONFIG_PACKAGE_liblz4 is not set +# CONFIG_PACKAGE_liblzo is not set +# CONFIG_PACKAGE_libmad is not set +# CONFIG_PACKAGE_libmagic is not set +# CONFIG_PACKAGE_libmcrypt is not set +# CONFIG_PACKAGE_libmicrohttpd is not set +# CONFIG_PACKAGE_libmicrohttpd-no-ssl is not set +# CONFIG_PACKAGE_libminiupnpc is not set +# CONFIG_PACKAGE_libmms is not set +CONFIG_PACKAGE_libmnl=y +# CONFIG_PACKAGE_libmodbus is not set +# CONFIG_PACKAGE_libmosquitto-nossl is not set +# CONFIG_PACKAGE_libmosquitto-ssl is not set +# CONFIG_PACKAGE_libmosquittopp is not set +# CONFIG_PACKAGE_libmount is not set +# CONFIG_PACKAGE_libmpdclient is not set +# CONFIG_PACKAGE_libmpeg2 is not set +# CONFIG_PACKAGE_libmpg123 is not set +# CONFIG_PACKAGE_libmraa is not set +# CONFIG_PACKAGE_libmysqlclient is not set +# CONFIG_PACKAGE_libmysqlclient-r is not set +# CONFIG_PACKAGE_libnatpmp is not set +# CONFIG_PACKAGE_libncurses is not set +# CONFIG_PACKAGE_libndpi is not set +# CONFIG_PACKAGE_libneon is not set +# CONFIG_PACKAGE_libnet-1.2.x is not set +# CONFIG_PACKAGE_libnetconf2 is not set +# CONFIG_PACKAGE_libnetfilter-acct is not set +# CONFIG_PACKAGE_libnetfilter-conntrack is not set +# CONFIG_PACKAGE_libnetfilter-cthelper is not set +# CONFIG_PACKAGE_libnetfilter-cttimeout is not set +# CONFIG_PACKAGE_libnetfilter-log is not set +# CONFIG_PACKAGE_libnetfilter-queue is not set +# CONFIG_PACKAGE_libnetsnmp is not set +# CONFIG_PACKAGE_libnettle is not set +# CONFIG_PACKAGE_libnfnetlink is not set +# CONFIG_PACKAGE_libnftnl is not set +# CONFIG_PACKAGE_libnl is not set +# CONFIG_PACKAGE_libnl-core is not set +# CONFIG_PACKAGE_libnl-genl is not set +# CONFIG_PACKAGE_libnl-nf is not set +# CONFIG_PACKAGE_libnl-route is not set +CONFIG_PACKAGE_libnl-tiny=y +# CONFIG_PACKAGE_libnopoll is not set +# CONFIG_PACKAGE_libogg is not set +# CONFIG_PACKAGE_liboil is not set +# CONFIG_PACKAGE_libopcodes is not set +# CONFIG_PACKAGE_libopenldap is not set +# CONFIG_PACKAGE_libopenobex is not set +# CONFIG_PACKAGE_libopensc is not set +# CONFIG_PACKAGE_libopenzwave is not set +# CONFIG_PACKAGE_liboping is not set +# CONFIG_PACKAGE_libopus is not set +# CONFIG_PACKAGE_libout123 is not set +# CONFIG_PACKAGE_libowfat is not set +# CONFIG_PACKAGE_libp11 is not set +# CONFIG_PACKAGE_libpam is not set +# CONFIG_PACKAGE_libpcap is not set +CONFIG_PACKAGE_libpcre=y +# CONFIG_PACKAGE_libpcre16 is not set +# CONFIG_PACKAGE_libpcre2 is not set +# CONFIG_PACKAGE_libpcre2-16 is not set +# CONFIG_PACKAGE_libpcre2-32 is not set +# CONFIG_PACKAGE_libpcrecpp is not set +# CONFIG_PACKAGE_libpcsclite is not set +# CONFIG_PACKAGE_libpkcs11-spy is not set +# CONFIG_PACKAGE_libplist is not set +# CONFIG_PACKAGE_libplistcxx is not set +# CONFIG_PACKAGE_libpng is not set +# CONFIG_PACKAGE_libpopt is not set +# CONFIG_PACKAGE_libpri is not set +# CONFIG_PACKAGE_libprotobuf-c is not set +# CONFIG_PACKAGE_libqrencode is not set +# CONFIG_PACKAGE_libradcli is not set +# CONFIG_PACKAGE_libreadline is not set +# CONFIG_PACKAGE_libredblack is not set +# CONFIG_PACKAGE_libroxml is not set +# CONFIG_PACKAGE_librpc is not set +# CONFIG_PACKAGE_librrd1 is not set +# CONFIG_PACKAGE_librtlsdr is not set +# CONFIG_PACKAGE_libruby is not set +# CONFIG_PACKAGE_libsamplerate is not set +# CONFIG_PACKAGE_libsane is not set +# CONFIG_PACKAGE_libsasl2 is not set +# CONFIG_PACKAGE_libsearpc is not set +# CONFIG_PACKAGE_libseccomp is not set +# CONFIG_PACKAGE_libsensors is not set +# CONFIG_PACKAGE_libshout is not set +# CONFIG_PACKAGE_libshout-full is not set +# CONFIG_PACKAGE_libshout-nossl is not set +# CONFIG_PACKAGE_libsigcxx is not set +# CONFIG_PACKAGE_libsmartcols is not set +# CONFIG_PACKAGE_libsndfile is not set +# CONFIG_PACKAGE_libsoc is not set +# CONFIG_PACKAGE_libsocks is not set +# CONFIG_PACKAGE_libsodium is not set +# CONFIG_PACKAGE_libsoup is not set +# CONFIG_PACKAGE_libsoxr is not set +# CONFIG_PACKAGE_libspeex is not set +# CONFIG_PACKAGE_libspeexdsp is not set +# CONFIG_PACKAGE_libssh is not set +# CONFIG_PACKAGE_libssh2 is not set +# CONFIG_PACKAGE_libstoken is not set +# CONFIG_PACKAGE_libstrophe is not set +# CONFIG_PACKAGE_libtalloc is not set +# CONFIG_PACKAGE_libtasn1 is not set +# CONFIG_PACKAGE_libtheora is not set +# CONFIG_PACKAGE_libtiff is not set +# CONFIG_PACKAGE_libtiffxx is not set +# CONFIG_PACKAGE_libtins is not set +# CONFIG_PACKAGE_libtorrent is not set +CONFIG_PACKAGE_libubox=y +# CONFIG_PACKAGE_libubox-lua is not set +CONFIG_PACKAGE_libubus=y +CONFIG_PACKAGE_libubus-lua=y +CONFIG_PACKAGE_libuci=y +CONFIG_PACKAGE_libuci-lua=y +CONFIG_PACKAGE_libuclient=y +# CONFIG_PACKAGE_libudev-fbsd is not set +# CONFIG_PACKAGE_libudns is not set +# CONFIG_PACKAGE_libuecc is not set +# CONFIG_PACKAGE_libugpio is not set +# CONFIG_PACKAGE_libunbound is not set +# CONFIG_PACKAGE_libunistring is not set +# CONFIG_PACKAGE_libunwind is not set +# CONFIG_PACKAGE_libupnp is not set +# CONFIG_PACKAGE_libupnpp is not set +# CONFIG_PACKAGE_liburcu is not set +# CONFIG_PACKAGE_libusb-1.0 is not set +# CONFIG_PACKAGE_libusb-compat is not set +# CONFIG_PACKAGE_libusbmuxd is not set +# CONFIG_PACKAGE_libustream-cyassl is not set +# CONFIG_PACKAGE_libustream-mbedtls is not set +# CONFIG_PACKAGE_libustream-openssl is not set +CONFIG_PACKAGE_libuuid=y +# CONFIG_PACKAGE_libuv is not set +# CONFIG_PACKAGE_libuvc is not set +# CONFIG_PACKAGE_libv4l is not set +# CONFIG_PACKAGE_libvorbis is not set +# CONFIG_PACKAGE_libvorbisidec is not set +# CONFIG_PACKAGE_libvpx is not set +# CONFIG_PACKAGE_libwebcam is not set +# CONFIG_PACKAGE_libwebsockets-full is not set +# CONFIG_PACKAGE_libwebsockets-openssl is not set +# CONFIG_PACKAGE_libwebsockets-wolfssl is not set +# CONFIG_PACKAGE_libwrap is not set +# CONFIG_PACKAGE_libwxbase is not set +# CONFIG_PACKAGE_libx264 is not set +# CONFIG_PACKAGE_libxerces-c is not set +# CONFIG_PACKAGE_libxerces-c-samples is not set +# CONFIG_PACKAGE_libxml2 is not set +# CONFIG_PACKAGE_libxslt is not set +# CONFIG_PACKAGE_libyang is not set +# CONFIG_PACKAGE_libzdb is not set +# CONFIG_PACKAGE_libzmq-curve is not set +# CONFIG_PACKAGE_libzmq-nc is not set +# CONFIG_PACKAGE_linux-atm is not set +# CONFIG_PACKAGE_loudmouth is not set +# CONFIG_PACKAGE_lttng-ust is not set +# CONFIG_PACKAGE_mtdev is not set +# CONFIG_PACKAGE_musl-fts is not set +# CONFIG_PACKAGE_mxml is not set +# CONFIG_PACKAGE_nacl is not set +# CONFIG_PACKAGE_opencv is not set +# CONFIG_PACKAGE_p11-kit is not set +# CONFIG_PACKAGE_poco is not set +# CONFIG_PACKAGE_protobuf is not set +# CONFIG_PACKAGE_pthsem is not set +CONFIG_PACKAGE_rpcd-mod-rrdns=y +# CONFIG_PACKAGE_rxtx is not set +# CONFIG_PACKAGE_sbc is not set +# CONFIG_PACKAGE_terminfo is not set +# CONFIG_PACKAGE_tinycdb is not set +# CONFIG_PACKAGE_uclibcxx is not set +# CONFIG_PACKAGE_xmlrpc-c is not set +# CONFIG_PACKAGE_xmlrpc-c-client is not set +# CONFIG_PACKAGE_xmlrpc-c-server is not set +# CONFIG_PACKAGE_yajl is not set +CONFIG_PACKAGE_zlib=y + +# +# LuCI +# + +# +# 1. Collections +# +CONFIG_PACKAGE_luci=y +# CONFIG_PACKAGE_luci-ssl is not set +# CONFIG_PACKAGE_luci-ssl-openssl is not set + +# +# 2. Modules +# +CONFIG_PACKAGE_luci-base=y +# CONFIG_LUCI_SRCDIET is not set + +# +# Translations +# +# CONFIG_LUCI_LANG_ca is not set +# CONFIG_LUCI_LANG_cs is not set +# CONFIG_LUCI_LANG_de is not set +# CONFIG_LUCI_LANG_el is not set +# CONFIG_LUCI_LANG_en is not set +# CONFIG_LUCI_LANG_es is not set +# CONFIG_LUCI_LANG_fr is not set +# CONFIG_LUCI_LANG_he is not set +# CONFIG_LUCI_LANG_hu is not set +# CONFIG_LUCI_LANG_it is not set +# CONFIG_LUCI_LANG_ja is not set +# CONFIG_LUCI_LANG_ko is not set +# CONFIG_LUCI_LANG_ms is not set +# CONFIG_LUCI_LANG_no is not set +# CONFIG_LUCI_LANG_pl is not set +# CONFIG_LUCI_LANG_pt is not set +# CONFIG_LUCI_LANG_pt-br is not set +# CONFIG_LUCI_LANG_ro is not set +# CONFIG_LUCI_LANG_ru is not set +# CONFIG_LUCI_LANG_sk is not set +# CONFIG_LUCI_LANG_sv is not set +# CONFIG_LUCI_LANG_tr is not set +# CONFIG_LUCI_LANG_uk is not set +# CONFIG_LUCI_LANG_vi is not set +CONFIG_LUCI_LANG_zh-cn=y +# CONFIG_LUCI_LANG_zh-tw is not set +CONFIG_PACKAGE_luci-mod-admin-full=y +# CONFIG_PACKAGE_luci-mod-failsafe is not set +# CONFIG_PACKAGE_luci-mod-freifunk is not set +# CONFIG_PACKAGE_luci-mod-freifunk-community is not set +# CONFIG_PACKAGE_luci-mod-rpc is not set + +# +# 3. Applications +# +# CONFIG_PACKAGE_luci-app-adblock is not set +CONFIG_PACKAGE_luci-app-adbyby-plus=y +# CONFIG_PACKAGE_luci-app-advanced-reboot is not set +# CONFIG_PACKAGE_luci-app-ahcp is not set +# CONFIG_PACKAGE_luci-app-aliddns is not set +# CONFIG_PACKAGE_luci-app-amule is not set +# CONFIG_PACKAGE_luci-app-apfree_wifidog is not set +# CONFIG_PACKAGE_luci-app-aria2 is not set +# CONFIG_PACKAGE_luci-app-arpbind is not set +# CONFIG_PACKAGE_luci-app-asterisk is not set +# CONFIG_PACKAGE_luci-app-attendedsysupgrade is not set +CONFIG_PACKAGE_luci-app-autoreboot=y +# CONFIG_PACKAGE_luci-app-bcp38 is not set +# CONFIG_PACKAGE_luci-app-bird4 is not set +# CONFIG_PACKAGE_luci-app-bird6 is not set +# CONFIG_PACKAGE_luci-app-bmx6 is not set +# CONFIG_PACKAGE_luci-app-bmx7 is not set +# CONFIG_PACKAGE_luci-app-cjdns is not set +# CONFIG_PACKAGE_luci-app-clamav is not set +# CONFIG_PACKAGE_luci-app-commands is not set +# CONFIG_PACKAGE_luci-app-cshark is not set +CONFIG_PACKAGE_luci-app-ddns=y +# CONFIG_PACKAGE_luci-app-diag-core is not set +# CONFIG_PACKAGE_luci-app-dnscrypt-proxy is not set +# CONFIG_PACKAGE_luci-app-dogcom is not set +# CONFIG_PACKAGE_luci-app-dump1090 is not set +# CONFIG_PACKAGE_luci-app-dynapoint is not set +# CONFIG_PACKAGE_luci-app-e2guardian is not set +CONFIG_PACKAGE_luci-app-filetransfer=y +CONFIG_PACKAGE_luci-app-firewall=y +# CONFIG_PACKAGE_luci-app-freifunk-diagnostics is not set +# CONFIG_PACKAGE_luci-app-freifunk-policyrouting is not set +# CONFIG_PACKAGE_luci-app-freifunk-widgets is not set +# CONFIG_PACKAGE_luci-app-frpc is not set +# CONFIG_PACKAGE_luci-app-fwknopd is not set +# CONFIG_PACKAGE_luci-app-hd-idle is not set +# CONFIG_PACKAGE_luci-app-hnet is not set +CONFIG_PACKAGE_luci-app-ipsec-vpnd=y +# CONFIG_PACKAGE_luci-app-kcptun is not set +# CONFIG_PACKAGE_luci-app-kuainiao is not set +# CONFIG_PACKAGE_luci-app-meshwizard is not set +# CONFIG_PACKAGE_luci-app-minidlna is not set +# CONFIG_PACKAGE_luci-app-mjpg-streamer is not set +# CONFIG_PACKAGE_luci-app-mmc-over-gpio is not set +# CONFIG_PACKAGE_luci-app-mproxy is not set +# CONFIG_PACKAGE_luci-app-mwan3 is not set +# CONFIG_PACKAGE_luci-app-n2n_v2 is not set +# CONFIG_PACKAGE_luci-app-ngrokc is not set +CONFIG_PACKAGE_luci-app-nlbwmon=y +# CONFIG_PACKAGE_luci-app-ntpc is not set +# CONFIG_PACKAGE_luci-app-ocserv is not set +# CONFIG_PACKAGE_luci-app-olsr is not set +# CONFIG_PACKAGE_luci-app-olsr-services is not set +# CONFIG_PACKAGE_luci-app-olsr-viz is not set +# CONFIG_PACKAGE_luci-app-openvpn is not set +# CONFIG_PACKAGE_luci-app-openvpn-server is not set +# CONFIG_PACKAGE_luci-app-oscam is not set +# CONFIG_PACKAGE_luci-app-p910nd is not set +# CONFIG_PACKAGE_luci-app-polipo is not set +CONFIG_PACKAGE_luci-app-pptp-server=y +# CONFIG_PACKAGE_luci-app-privoxy is not set +# CONFIG_PACKAGE_luci-app-qos is not set +# CONFIG_PACKAGE_luci-app-radicale is not set +# CONFIG_PACKAGE_luci-app-rp-pppoe-server is not set +# CONFIG_PACKAGE_luci-app-samba is not set +CONFIG_PACKAGE_luci-app-sfe=y +# CONFIG_PACKAGE_luci-app-shadowsocks-libev is not set +CONFIG_PACKAGE_luci-app-shadowsocksr-pro=y +# CONFIG_PACKAGE_luci-app-shairplay is not set +# CONFIG_PACKAGE_luci-app-shairport is not set +# CONFIG_PACKAGE_luci-app-siitwizard is not set +# CONFIG_PACKAGE_luci-app-simple-adblock is not set +# CONFIG_PACKAGE_luci-app-splash is not set +CONFIG_PACKAGE_luci-app-sqm=y +# CONFIG_PACKAGE_luci-app-squid is not set +# CONFIG_PACKAGE_luci-app-ssrserver-python is not set +# CONFIG_PACKAGE_luci-app-statistics is not set +# CONFIG_PACKAGE_luci-app-syncdial is not set +# CONFIG_PACKAGE_luci-app-tinyproxy is not set +# CONFIG_PACKAGE_luci-app-transmission is not set +# CONFIG_PACKAGE_luci-app-transparent-proxy is not set +# CONFIG_PACKAGE_luci-app-travelmate is not set +# CONFIG_PACKAGE_luci-app-udpxy is not set +# CONFIG_PACKAGE_luci-app-uhttpd is not set +# CONFIG_PACKAGE_luci-app-unbound is not set +CONFIG_PACKAGE_luci-app-upnp=y +CONFIG_PACKAGE_luci-app-usb-printer=y +CONFIG_PACKAGE_luci-app-vlmcsd=y +# CONFIG_PACKAGE_luci-app-vnstat is not set +# CONFIG_PACKAGE_luci-app-vpnbypass is not set +CONFIG_PACKAGE_luci-app-vsftpd=y +# CONFIG_PACKAGE_luci-app-watchcat is not set +CONFIG_PACKAGE_luci-app-wifischedule=y +# CONFIG_PACKAGE_luci-app-wireguard is not set +CONFIG_PACKAGE_luci-app-wol=y +# CONFIG_PACKAGE_luci-app-zerotier is not set + +# +# 4. Themes +# +# CONFIG_PACKAGE_luci-theme-atmaterial is not set +CONFIG_PACKAGE_luci-theme-bootstrap=y +# CONFIG_PACKAGE_luci-theme-freifunk-generic is not set +# CONFIG_PACKAGE_luci-theme-material is not set +# CONFIG_PACKAGE_luci-theme-openwrt is not set + +# +# 5. Protocols +# +# CONFIG_PACKAGE_luci-proto-3g is not set +# CONFIG_PACKAGE_luci-proto-ipip is not set +CONFIG_PACKAGE_luci-proto-ipv6=y +# CONFIG_PACKAGE_luci-proto-ncm is not set +# CONFIG_PACKAGE_luci-proto-openconnect is not set +CONFIG_PACKAGE_luci-proto-ppp=y +# CONFIG_PACKAGE_luci-proto-qmi is not set +# CONFIG_PACKAGE_luci-proto-relay is not set +# CONFIG_PACKAGE_luci-proto-vpnc is not set +# CONFIG_PACKAGE_luci-proto-wireguard is not set + +# +# 6. Libraries +# +# CONFIG_PACKAGE_luci-lib-dracula is not set +# CONFIG_PACKAGE_luci-lib-httpclient is not set +CONFIG_PACKAGE_luci-lib-ip=y +# CONFIG_PACKAGE_luci-lib-jquery-1-4 is not set +# CONFIG_PACKAGE_luci-lib-json is not set +CONFIG_PACKAGE_luci-lib-jsonc=y +# CONFIG_PACKAGE_luci-lib-luaneightbl is not set +CONFIG_PACKAGE_luci-lib-nixio=y +# CONFIG_PACKAGE_luci-lib-px5g is not set + +# +# 9. Freifunk +# +# CONFIG_PACKAGE_freifunk-common is not set +# CONFIG_PACKAGE_freifunk-firewall is not set +# CONFIG_PACKAGE_freifunk-policyrouting is not set +# CONFIG_PACKAGE_freifunk-watchdog is not set +# CONFIG_PACKAGE_meshwizard is not set +CONFIG_PACKAGE_default-settings=y +CONFIG_PACKAGE_luci-i18n-adbyby-plus-zh-cn=y +CONFIG_PACKAGE_luci-i18n-autoreboot-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-base-ca is not set +# CONFIG_PACKAGE_luci-i18n-base-cs is not set +# CONFIG_PACKAGE_luci-i18n-base-de is not set +# CONFIG_PACKAGE_luci-i18n-base-el is not set +# CONFIG_PACKAGE_luci-i18n-base-en is not set +# CONFIG_PACKAGE_luci-i18n-base-es is not set +# CONFIG_PACKAGE_luci-i18n-base-fr is not set +# CONFIG_PACKAGE_luci-i18n-base-he is not set +# CONFIG_PACKAGE_luci-i18n-base-hu is not set +# CONFIG_PACKAGE_luci-i18n-base-it is not set +# CONFIG_PACKAGE_luci-i18n-base-ja is not set +# CONFIG_PACKAGE_luci-i18n-base-ko is not set +# CONFIG_PACKAGE_luci-i18n-base-ms is not set +# CONFIG_PACKAGE_luci-i18n-base-no is not set +# CONFIG_PACKAGE_luci-i18n-base-pl is not set +# CONFIG_PACKAGE_luci-i18n-base-pt is not set +# CONFIG_PACKAGE_luci-i18n-base-pt-br is not set +# CONFIG_PACKAGE_luci-i18n-base-ro is not set +# CONFIG_PACKAGE_luci-i18n-base-ru is not set +# CONFIG_PACKAGE_luci-i18n-base-sk is not set +# CONFIG_PACKAGE_luci-i18n-base-sv is not set +# CONFIG_PACKAGE_luci-i18n-base-tr is not set +# CONFIG_PACKAGE_luci-i18n-base-uk is not set +# CONFIG_PACKAGE_luci-i18n-base-vi is not set +CONFIG_PACKAGE_luci-i18n-base-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-base-zh-tw is not set +# CONFIG_PACKAGE_luci-i18n-ddns-ca is not set +# CONFIG_PACKAGE_luci-i18n-ddns-cs is not set +# CONFIG_PACKAGE_luci-i18n-ddns-de is not set +# CONFIG_PACKAGE_luci-i18n-ddns-el is not set +# CONFIG_PACKAGE_luci-i18n-ddns-es is not set +# CONFIG_PACKAGE_luci-i18n-ddns-fr is not set +# CONFIG_PACKAGE_luci-i18n-ddns-he is not set +# CONFIG_PACKAGE_luci-i18n-ddns-hu is not set +# CONFIG_PACKAGE_luci-i18n-ddns-it is not set +# CONFIG_PACKAGE_luci-i18n-ddns-ja is not set +# CONFIG_PACKAGE_luci-i18n-ddns-no is not set +# CONFIG_PACKAGE_luci-i18n-ddns-pl is not set +# CONFIG_PACKAGE_luci-i18n-ddns-pt is not set +# CONFIG_PACKAGE_luci-i18n-ddns-pt-br is not set +# CONFIG_PACKAGE_luci-i18n-ddns-ro is not set +# CONFIG_PACKAGE_luci-i18n-ddns-ru is not set +# CONFIG_PACKAGE_luci-i18n-ddns-sv is not set +# CONFIG_PACKAGE_luci-i18n-ddns-tr is not set +# CONFIG_PACKAGE_luci-i18n-ddns-uk is not set +# CONFIG_PACKAGE_luci-i18n-ddns-vi is not set +CONFIG_PACKAGE_luci-i18n-ddns-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-ddns-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-filetransfer-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-firewall-ca is not set +# CONFIG_PACKAGE_luci-i18n-firewall-cs is not set +# CONFIG_PACKAGE_luci-i18n-firewall-de is not set +# CONFIG_PACKAGE_luci-i18n-firewall-el is not set +# CONFIG_PACKAGE_luci-i18n-firewall-en is not set +# CONFIG_PACKAGE_luci-i18n-firewall-es is not set +# CONFIG_PACKAGE_luci-i18n-firewall-fr is not set +# CONFIG_PACKAGE_luci-i18n-firewall-he is not set +# CONFIG_PACKAGE_luci-i18n-firewall-hu is not set +# CONFIG_PACKAGE_luci-i18n-firewall-it is not set +# CONFIG_PACKAGE_luci-i18n-firewall-ja is not set +# CONFIG_PACKAGE_luci-i18n-firewall-ko is not set +# CONFIG_PACKAGE_luci-i18n-firewall-ms is not set +# CONFIG_PACKAGE_luci-i18n-firewall-no is not set +# CONFIG_PACKAGE_luci-i18n-firewall-pl is not set +# CONFIG_PACKAGE_luci-i18n-firewall-pt is not set +# CONFIG_PACKAGE_luci-i18n-firewall-pt-br is not set +# CONFIG_PACKAGE_luci-i18n-firewall-ro is not set +# CONFIG_PACKAGE_luci-i18n-firewall-ru is not set +# CONFIG_PACKAGE_luci-i18n-firewall-sk is not set +# CONFIG_PACKAGE_luci-i18n-firewall-sv is not set +# CONFIG_PACKAGE_luci-i18n-firewall-tr is not set +# CONFIG_PACKAGE_luci-i18n-firewall-uk is not set +# CONFIG_PACKAGE_luci-i18n-firewall-vi is not set +CONFIG_PACKAGE_luci-i18n-firewall-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-firewall-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-ipsec-vpnd-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-nlbwmon-ja is not set +CONFIG_PACKAGE_luci-i18n-nlbwmon-zh-cn=y +CONFIG_PACKAGE_luci-i18n-pptp-server-zh-cn=y +CONFIG_PACKAGE_luci-i18n-sfe-zh-cn=y +CONFIG_PACKAGE_luci-i18n-shadowsocksr-pro-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-upnp-ca is not set +# CONFIG_PACKAGE_luci-i18n-upnp-cs is not set +# CONFIG_PACKAGE_luci-i18n-upnp-de is not set +# CONFIG_PACKAGE_luci-i18n-upnp-el is not set +# CONFIG_PACKAGE_luci-i18n-upnp-en is not set +# CONFIG_PACKAGE_luci-i18n-upnp-es is not set +# CONFIG_PACKAGE_luci-i18n-upnp-fr is not set +# CONFIG_PACKAGE_luci-i18n-upnp-he is not set +# CONFIG_PACKAGE_luci-i18n-upnp-hu is not set +# CONFIG_PACKAGE_luci-i18n-upnp-it is not set +# CONFIG_PACKAGE_luci-i18n-upnp-ja is not set +# CONFIG_PACKAGE_luci-i18n-upnp-ms is not set +# CONFIG_PACKAGE_luci-i18n-upnp-no is not set +# CONFIG_PACKAGE_luci-i18n-upnp-pl is not set +# CONFIG_PACKAGE_luci-i18n-upnp-pt is not set +# CONFIG_PACKAGE_luci-i18n-upnp-pt-br is not set +# CONFIG_PACKAGE_luci-i18n-upnp-ro is not set +# CONFIG_PACKAGE_luci-i18n-upnp-ru is not set +# CONFIG_PACKAGE_luci-i18n-upnp-sk is not set +# CONFIG_PACKAGE_luci-i18n-upnp-sv is not set +# CONFIG_PACKAGE_luci-i18n-upnp-tr is not set +# CONFIG_PACKAGE_luci-i18n-upnp-uk is not set +# CONFIG_PACKAGE_luci-i18n-upnp-vi is not set +CONFIG_PACKAGE_luci-i18n-upnp-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-upnp-zh-tw is not set +CONFIG_PACKAGE_luci-i18n-usb-printer-zh-cn=y +CONFIG_PACKAGE_luci-i18n-vlmcsd-zh-cn=y +CONFIG_PACKAGE_luci-i18n-vsftpd-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-wifischedule-it is not set +# CONFIG_PACKAGE_luci-i18n-wifischedule-ja is not set +# CONFIG_PACKAGE_luci-i18n-wifischedule-pt-br is not set +# CONFIG_PACKAGE_luci-i18n-wifischedule-sv is not set +CONFIG_PACKAGE_luci-i18n-wifischedule-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-wol-ca is not set +# CONFIG_PACKAGE_luci-i18n-wol-cs is not set +# CONFIG_PACKAGE_luci-i18n-wol-de is not set +# CONFIG_PACKAGE_luci-i18n-wol-el is not set +# CONFIG_PACKAGE_luci-i18n-wol-en is not set +# CONFIG_PACKAGE_luci-i18n-wol-es is not set +# CONFIG_PACKAGE_luci-i18n-wol-fr is not set +# CONFIG_PACKAGE_luci-i18n-wol-he is not set +# CONFIG_PACKAGE_luci-i18n-wol-hu is not set +# CONFIG_PACKAGE_luci-i18n-wol-it is not set +# CONFIG_PACKAGE_luci-i18n-wol-ja is not set +# CONFIG_PACKAGE_luci-i18n-wol-ms is not set +# CONFIG_PACKAGE_luci-i18n-wol-no is not set +# CONFIG_PACKAGE_luci-i18n-wol-pl is not set +# CONFIG_PACKAGE_luci-i18n-wol-pt is not set +# CONFIG_PACKAGE_luci-i18n-wol-pt-br is not set +# CONFIG_PACKAGE_luci-i18n-wol-ro is not set +# CONFIG_PACKAGE_luci-i18n-wol-ru is not set +# CONFIG_PACKAGE_luci-i18n-wol-sk is not set +# CONFIG_PACKAGE_luci-i18n-wol-sv is not set +# CONFIG_PACKAGE_luci-i18n-wol-tr is not set +# CONFIG_PACKAGE_luci-i18n-wol-uk is not set +# CONFIG_PACKAGE_luci-i18n-wol-vi is not set +CONFIG_PACKAGE_luci-i18n-wol-zh-cn=y +# CONFIG_PACKAGE_luci-i18n-wol-zh-tw is not set + +# +# Mail +# +# CONFIG_PACKAGE_alpine is not set +# CONFIG_PACKAGE_alpine-nossl is not set +# CONFIG_PACKAGE_bogofilter is not set +# CONFIG_PACKAGE_clamsmtp is not set +# CONFIG_PACKAGE_dovecot is not set +# CONFIG_PACKAGE_emailrelay is not set +# CONFIG_PACKAGE_fdm is not set +# CONFIG_PACKAGE_greyfix is not set +# CONFIG_PACKAGE_mailman is not set +# CONFIG_PACKAGE_mailsend is not set +# CONFIG_PACKAGE_mailsend-nossl is not set +# CONFIG_PACKAGE_msmtp is not set +# CONFIG_PACKAGE_msmtp-nossl is not set +# CONFIG_PACKAGE_mutt is not set +# CONFIG_PACKAGE_nail is not set +# CONFIG_PACKAGE_pigeonhole is not set +# CONFIG_PACKAGE_postfix is not set + +# +# Select postfix build options +# +CONFIG_POSTFIX_TLS=y +CONFIG_POSTFIX_SASL=y +CONFIG_POSTFIX_LDAP=y +# CONFIG_POSTFIX_DB is not set +CONFIG_POSTFIX_CDB=y +CONFIG_POSTFIX_SQLITE=y +# CONFIG_POSTFIX_PGSQL is not set +# CONFIG_POSTFIX_PCRE is not set +# CONFIG_POSTFIX_EAI is not set +# CONFIG_PACKAGE_ssmtp is not set + +# +# Multimedia +# + +# +# Streaming +# +# CONFIG_PACKAGE_oggfwd is not set +# CONFIG_PACKAGE_crtmpserver is not set +# CONFIG_PACKAGE_ffmpeg is not set +# CONFIG_PACKAGE_ffprobe is not set +# CONFIG_PACKAGE_ffserver is not set +# CONFIG_PACKAGE_fswebcam is not set +# CONFIG_PACKAGE_gphoto2 is not set +# CONFIG_PACKAGE_grilo is not set +# CONFIG_PACKAGE_grilo-plugins is not set +# CONFIG_PACKAGE_gst1-libav is not set +# CONFIG_PACKAGE_gstreamer1-libs is not set +# CONFIG_PACKAGE_gstreamer1-plugins-bad is not set +# CONFIG_PACKAGE_gstreamer1-plugins-base is not set +# CONFIG_PACKAGE_gstreamer1-plugins-good is not set +# CONFIG_PACKAGE_gstreamer1-plugins-ugly is not set +# CONFIG_PACKAGE_gstreamer1-utils is not set +# CONFIG_PACKAGE_icecast is not set +# CONFIG_PACKAGE_lcdgrilo is not set +# CONFIG_PACKAGE_minidlna is not set +# CONFIG_PACKAGE_mjpg-streamer is not set +# CONFIG_PACKAGE_motion is not set +# CONFIG_PACKAGE_tvheadend is not set +# CONFIG_PACKAGE_vips is not set +# CONFIG_PACKAGE_xupnpd is not set +# CONFIG_PACKAGE_youtube-dl is not set + +# +# Network +# + +# +# BitTorrent +# +# CONFIG_PACKAGE_mktorrent is not set +# CONFIG_PACKAGE_opentracker is not set +# CONFIG_PACKAGE_opentracker6 is not set +# CONFIG_PACKAGE_rtorrent is not set +# CONFIG_PACKAGE_rtorrent-rpc is not set +# CONFIG_PACKAGE_transmission-cli-mbedtls is not set +# CONFIG_PACKAGE_transmission-cli-openssl is not set +# CONFIG_PACKAGE_transmission-daemon-mbedtls is not set +# CONFIG_PACKAGE_transmission-daemon-openssl is not set +# CONFIG_PACKAGE_transmission-remote-mbedtls is not set +# CONFIG_PACKAGE_transmission-remote-openssl is not set + +# +# Captive Portals +# +# CONFIG_PACKAGE_apfree_wifidog is not set +# CONFIG_PACKAGE_coova-chilli is not set +# CONFIG_PACKAGE_nodogsplash is not set +# CONFIG_PACKAGE_nodogsplash2 is not set +# CONFIG_PACKAGE_wifidog is not set +# CONFIG_PACKAGE_wifidog-tls is not set + +# +# Download Manager +# +# CONFIG_PACKAGE_webui-aria2 is not set +# CONFIG_PACKAGE_yaaw is not set + +# +# File Transfer +# +# CONFIG_PACKAGE_aria2 is not set +# CONFIG_PACKAGE_atftp is not set +# CONFIG_PACKAGE_atftpd is not set +# CONFIG_PACKAGE_curl is not set +# CONFIG_PACKAGE_gnurl is not set +# CONFIG_PACKAGE_lftp is not set +# CONFIG_PACKAGE_rsync is not set +# CONFIG_PACKAGE_rsyncd is not set +# CONFIG_PACKAGE_vsftpd is not set +CONFIG_PACKAGE_vsftpd-alt=y +CONFIG_VSFTPD_USE_UCI_SCRIPTS=y +# CONFIG_PACKAGE_vsftpd-tls is not set +CONFIG_PACKAGE_wget=y +# CONFIG_PACKAGE_wget-nossl is not set + +# +# Filesystem +# +# CONFIG_PACKAGE_davfs2 is not set +# CONFIG_PACKAGE_netatalk is not set +# CONFIG_PACKAGE_nfs-kernel-server is not set +# CONFIG_PACKAGE_owftpd is not set +# CONFIG_PACKAGE_owhttpd is not set +# CONFIG_PACKAGE_owserver is not set +# CONFIG_PACKAGE_sshfs is not set + +# +# Firewall +# +# CONFIG_PACKAGE_arptables is not set +# CONFIG_PACKAGE_conntrack is not set +# CONFIG_PACKAGE_conntrackd is not set +# CONFIG_PACKAGE_ebtables is not set +# CONFIG_PACKAGE_fwknop is not set +# CONFIG_PACKAGE_fwknopd is not set +CONFIG_PACKAGE_ip6tables=y +# CONFIG_PACKAGE_ip6tables-extra is not set +# CONFIG_PACKAGE_ip6tables-mod-nat is not set +CONFIG_PACKAGE_iptables=y +# CONFIG_IPTABLES_CONNLABEL is not set +# CONFIG_IPTABLES_NFTABLES is not set +# CONFIG_PACKAGE_iptables-mod-account is not set +# CONFIG_PACKAGE_iptables-mod-chaos is not set +# CONFIG_PACKAGE_iptables-mod-cluster is not set +# CONFIG_PACKAGE_iptables-mod-clusterip is not set +# CONFIG_PACKAGE_iptables-mod-condition is not set +CONFIG_PACKAGE_iptables-mod-conntrack-extra=y +# CONFIG_PACKAGE_iptables-mod-delude is not set +# CONFIG_PACKAGE_iptables-mod-dhcpmac is not set +# CONFIG_PACKAGE_iptables-mod-dnetmap is not set +# CONFIG_PACKAGE_iptables-mod-extra is not set +# CONFIG_PACKAGE_iptables-mod-filter is not set +# CONFIG_PACKAGE_iptables-mod-fuzzy is not set +# CONFIG_PACKAGE_iptables-mod-geoip is not set +# CONFIG_PACKAGE_iptables-mod-hashlimit is not set +# CONFIG_PACKAGE_iptables-mod-iface is not set +# CONFIG_PACKAGE_iptables-mod-ipmark is not set +CONFIG_PACKAGE_iptables-mod-ipopt=y +# CONFIG_PACKAGE_iptables-mod-ipp2p is not set +# CONFIG_PACKAGE_iptables-mod-iprange is not set +CONFIG_PACKAGE_iptables-mod-ipsec=y +# CONFIG_PACKAGE_iptables-mod-ipv4options is not set +# CONFIG_PACKAGE_iptables-mod-led is not set +# CONFIG_PACKAGE_iptables-mod-length2 is not set +# CONFIG_PACKAGE_iptables-mod-logmark is not set +# CONFIG_PACKAGE_iptables-mod-lscan is not set +# CONFIG_PACKAGE_iptables-mod-lua is not set +CONFIG_PACKAGE_iptables-mod-nat-extra=y +# CONFIG_PACKAGE_iptables-mod-nflog is not set +# CONFIG_PACKAGE_iptables-mod-nfqueue is not set +# CONFIG_PACKAGE_iptables-mod-psd is not set +# CONFIG_PACKAGE_iptables-mod-quota2 is not set +# CONFIG_PACKAGE_iptables-mod-rpfilter is not set +# CONFIG_PACKAGE_iptables-mod-sysrq is not set +# CONFIG_PACKAGE_iptables-mod-tarpit is not set +# CONFIG_PACKAGE_iptables-mod-tee is not set +CONFIG_PACKAGE_iptables-mod-tproxy=y +# CONFIG_PACKAGE_iptables-mod-u32 is not set +# CONFIG_PACKAGE_iptables-mod-ulog is not set +# CONFIG_PACKAGE_iptaccount is not set +# CONFIG_PACKAGE_miniupnpc is not set +CONFIG_PACKAGE_miniupnpd=y +# CONFIG_MINIUPNPD_IGDv2 is not set +# CONFIG_PACKAGE_natpmpc is not set +# CONFIG_PACKAGE_nftables is not set +# CONFIG_PACKAGE_shorewall-core is not set +# CONFIG_PACKAGE_shorewall-lite is not set +# CONFIG_PACKAGE_shorewall6-lite is not set +# CONFIG_PACKAGE_snort is not set + +# +# Firewall Tunnel +# +# CONFIG_PACKAGE_iodine is not set +# CONFIG_PACKAGE_iodined is not set + +# +# FreeRADIUS (version 3) +# +# CONFIG_PACKAGE_freeradius3 is not set +# CONFIG_PACKAGE_freeradius3-common is not set +# CONFIG_PACKAGE_freeradius3-utils is not set + +# +# IP Addresses and Names +# +# CONFIG_PACKAGE_aggregate is not set +# CONFIG_PACKAGE_announce is not set +# CONFIG_PACKAGE_avahi-autoipd is not set +# CONFIG_PACKAGE_avahi-daemon-service-http is not set +# CONFIG_PACKAGE_avahi-daemon-service-ssh is not set +# CONFIG_PACKAGE_avahi-dbus-daemon is not set +# CONFIG_PACKAGE_avahi-dnsconfd is not set +# CONFIG_PACKAGE_avahi-nodbus-daemon is not set +# CONFIG_PACKAGE_avahi-utils is not set +# CONFIG_PACKAGE_bind-check is not set +# CONFIG_PACKAGE_bind-client is not set +# CONFIG_PACKAGE_bind-dig is not set +# CONFIG_PACKAGE_bind-dnssec is not set +# CONFIG_PACKAGE_bind-host is not set +# CONFIG_PACKAGE_bind-rndc is not set +# CONFIG_PACKAGE_bind-server is not set +# CONFIG_PACKAGE_bind-tools is not set +CONFIG_PACKAGE_ddns-scripts=y +# CONFIG_PACKAGE_ddns-scripts_cloudflare is not set +# CONFIG_PACKAGE_ddns-scripts_cloudflare.com-v4 is not set +# CONFIG_PACKAGE_ddns-scripts_godaddy.com-v1 is not set +# CONFIG_PACKAGE_ddns-scripts_no-ip_com is not set +# CONFIG_PACKAGE_ddns-scripts_nsupdate is not set +# CONFIG_PACKAGE_dhcp-forwarder is not set +# CONFIG_PACKAGE_dnscrypt-proxy is not set +# CONFIG_PACKAGE_dnscrypt-proxy-resolvers is not set +# CONFIG_PACKAGE_drill is not set +# CONFIG_PACKAGE_hostip is not set +# CONFIG_PACKAGE_idn is not set +# CONFIG_PACKAGE_inadyn is not set +# CONFIG_PACKAGE_isc-dhcp-client-ipv4 is not set +# CONFIG_PACKAGE_isc-dhcp-client-ipv6 is not set +# CONFIG_PACKAGE_isc-dhcp-omshell-ipv4 is not set +# CONFIG_PACKAGE_isc-dhcp-omshell-ipv6 is not set +# CONFIG_PACKAGE_isc-dhcp-relay-ipv4 is not set +# CONFIG_PACKAGE_isc-dhcp-relay-ipv6 is not set +# CONFIG_PACKAGE_isc-dhcp-server-ipv4 is not set +# CONFIG_PACKAGE_isc-dhcp-server-ipv6 is not set +# CONFIG_PACKAGE_knot is not set +# CONFIG_PACKAGE_knot-dig is not set +# CONFIG_PACKAGE_knot-host is not set +# CONFIG_PACKAGE_knot-keymgr is not set +# CONFIG_PACKAGE_knot-nsec3hash is not set +# CONFIG_PACKAGE_knot-nsupdate is not set +# CONFIG_PACKAGE_knot-tests is not set +# CONFIG_PACKAGE_knot-zonecheck is not set +# CONFIG_PACKAGE_mdns-utils is not set +# CONFIG_PACKAGE_mdnsd is not set +# CONFIG_PACKAGE_mdnsresponder is not set +# CONFIG_PACKAGE_nsd is not set +# CONFIG_PACKAGE_nsd-control is not set +# CONFIG_PACKAGE_nsd-control-setup is not set +# CONFIG_PACKAGE_nsd-nossl is not set +# CONFIG_PACKAGE_ohybridproxy is not set +# CONFIG_PACKAGE_unbound is not set +# CONFIG_PACKAGE_unbound-anchor is not set +# CONFIG_PACKAGE_unbound-control is not set +# CONFIG_PACKAGE_unbound-control-setup is not set +# CONFIG_PACKAGE_unbound-host is not set +# CONFIG_PACKAGE_zonestitcher is not set + +# +# Instant Messaging +# +# CONFIG_PACKAGE_bitlbee is not set +# CONFIG_PACKAGE_irssi is not set +# CONFIG_PACKAGE_ngircd is not set +# CONFIG_PACKAGE_ngircd-nossl is not set +# CONFIG_PACKAGE_prosody is not set +# CONFIG_PACKAGE_quassel-irssi is not set +# CONFIG_PACKAGE_umurmur-mbedtls is not set +# CONFIG_PACKAGE_umurmur-openssl is not set +# CONFIG_PACKAGE_znc is not set + +# +# Linux ATM tools +# +# CONFIG_PACKAGE_atm-aread is not set +# CONFIG_PACKAGE_atm-atmaddr is not set +# CONFIG_PACKAGE_atm-atmdiag is not set +# CONFIG_PACKAGE_atm-atmdump is not set +# CONFIG_PACKAGE_atm-atmloop is not set +# CONFIG_PACKAGE_atm-atmsigd is not set +# CONFIG_PACKAGE_atm-atmswitch is not set +# CONFIG_PACKAGE_atm-atmtcp is not set +# CONFIG_PACKAGE_atm-awrite is not set +# CONFIG_PACKAGE_atm-bus is not set +# CONFIG_PACKAGE_atm-debug-tools is not set +# CONFIG_PACKAGE_atm-diagnostics is not set +# CONFIG_PACKAGE_atm-esi is not set +# CONFIG_PACKAGE_atm-ilmid is not set +# CONFIG_PACKAGE_atm-ilmidiag is not set +# CONFIG_PACKAGE_atm-lecs is not set +# CONFIG_PACKAGE_atm-les is not set +# CONFIG_PACKAGE_atm-mpcd is not set +# CONFIG_PACKAGE_atm-saaldump is not set +# CONFIG_PACKAGE_atm-sonetdiag is not set +# CONFIG_PACKAGE_atm-svc_recv is not set +# CONFIG_PACKAGE_atm-svc_send is not set +# CONFIG_PACKAGE_atm-tools is not set +# CONFIG_PACKAGE_atm-ttcp_atm is not set +# CONFIG_PACKAGE_atm-zeppelin is not set +# CONFIG_PACKAGE_br2684ctl is not set + +# +# NMAP Suite +# +# CONFIG_PACKAGE_ncat is not set +# CONFIG_PACKAGE_ncat-ssl is not set +# CONFIG_PACKAGE_ndiff is not set +# CONFIG_PACKAGE_nmap is not set +# CONFIG_PACKAGE_nmap-ssl is not set +# CONFIG_PACKAGE_nping is not set + +# +# NTRIP +# +# CONFIG_PACKAGE_ntripcaster is not set +# CONFIG_PACKAGE_ntripclient is not set +# CONFIG_PACKAGE_ntripserver is not set + +# +# OLSR.org network framework +# +# CONFIG_PACKAGE_oonf-dlep-proxy is not set +# CONFIG_PACKAGE_oonf-dlep-radio is not set +# CONFIG_PACKAGE_oonf-init-scripts is not set +# CONFIG_PACKAGE_oonf-olsrd2 is not set + +# +# Open vSwitch +# +# CONFIG_PACKAGE_openvswitch is not set +# CONFIG_PACKAGE_openvswitch-base is not set +# CONFIG_PACKAGE_openvswitch-ovs-appctl is not set +# CONFIG_PACKAGE_openvswitch-ovs-dpctl is not set +# CONFIG_PACKAGE_openvswitch-ovs-ofctl is not set +# CONFIG_PACKAGE_openvswitch-ovs-vsctl is not set +# CONFIG_PACKAGE_openvswitch-ovsdb-client is not set +# CONFIG_PACKAGE_openvswitch-python is not set + +# +# P2P +# +# CONFIG_PACKAGE_amule is not set +CONFIG_AMULE_CRYPTOPP_STATIC_LINKING=y + +# +# Printing +# +CONFIG_PACKAGE_p910nd=y + +# +# Routing and Redirection +# +# CONFIG_PACKAGE_babel-pinger is not set +# CONFIG_PACKAGE_babeld is not set +# CONFIG_PACKAGE_batmand is not set +# CONFIG_PACKAGE_bcp38 is not set +# CONFIG_PACKAGE_bird4 is not set +# CONFIG_PACKAGE_bird4-uci is not set +# CONFIG_PACKAGE_bird6 is not set +# CONFIG_PACKAGE_bird6-uci is not set +# CONFIG_PACKAGE_birdc4 is not set +# CONFIG_PACKAGE_birdc6 is not set +# CONFIG_PACKAGE_birdcl4 is not set +# CONFIG_PACKAGE_birdcl6 is not set +# CONFIG_PACKAGE_bmx6 is not set +# CONFIG_PACKAGE_bmx7 is not set +# CONFIG_PACKAGE_cjdns is not set +# CONFIG_PACKAGE_cjdns-tests is not set +# CONFIG_PACKAGE_devlink is not set +# CONFIG_PACKAGE_genl is not set +# CONFIG_PACKAGE_igmpproxy is not set +# CONFIG_PACKAGE_ip-bridge is not set +# CONFIG_PACKAGE_ip-full is not set +CONFIG_PACKAGE_ip-tiny=y +# CONFIG_PACKAGE_lldpd is not set +# CONFIG_PACKAGE_mcproxy is not set +# CONFIG_PACKAGE_mwan3 is not set +# CONFIG_PACKAGE_nstat is not set +# CONFIG_PACKAGE_olsrd is not set +# CONFIG_PACKAGE_prince is not set +# CONFIG_PACKAGE_quagga is not set +# CONFIG_PACKAGE_relayd is not set +# CONFIG_PACKAGE_smcroute is not set +# CONFIG_PACKAGE_ss is not set +# CONFIG_PACKAGE_sslh is not set +CONFIG_PACKAGE_tc=y +# CONFIG_PACKAGE_tcpproxy is not set +# CONFIG_PACKAGE_vis is not set + +# +# SSH +# +# CONFIG_PACKAGE_autossh is not set +# CONFIG_PACKAGE_openssh-client is not set +# CONFIG_PACKAGE_openssh-client-utils is not set +# CONFIG_PACKAGE_openssh-keygen is not set +# CONFIG_PACKAGE_openssh-moduli is not set +# CONFIG_PACKAGE_openssh-server is not set +# CONFIG_PACKAGE_openssh-server-pam is not set +# CONFIG_PACKAGE_openssh-sftp-avahi-service is not set +# CONFIG_PACKAGE_openssh-sftp-client is not set +# CONFIG_PACKAGE_openssh-sftp-server is not set +# CONFIG_PACKAGE_sshtunnel is not set + +# +# THC-IPv6 attack and analyzing toolkit +# +# CONFIG_PACKAGE_thc-ipv6-address6 is not set +# CONFIG_PACKAGE_thc-ipv6-alive6 is not set +# CONFIG_PACKAGE_thc-ipv6-covert-send6 is not set +# CONFIG_PACKAGE_thc-ipv6-covert-send6d is not set +# CONFIG_PACKAGE_thc-ipv6-denial6 is not set +# CONFIG_PACKAGE_thc-ipv6-detect-new-ip6 is not set +# CONFIG_PACKAGE_thc-ipv6-detect-sniffer6 is not set +# CONFIG_PACKAGE_thc-ipv6-dnsdict6 is not set +# CONFIG_PACKAGE_thc-ipv6-dnsrevenum6 is not set +# CONFIG_PACKAGE_thc-ipv6-dos-new-ip6 is not set +# CONFIG_PACKAGE_thc-ipv6-dump-router6 is not set +# CONFIG_PACKAGE_thc-ipv6-exploit6 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-advertise6 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-dhcps6 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-dns6d is not set +# CONFIG_PACKAGE_thc-ipv6-fake-dnsupdate6 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-mipv6 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-mld26 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-mld6 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-mldrouter6 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-router26 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-router6 is not set +# CONFIG_PACKAGE_thc-ipv6-fake-solicitate6 is not set +# CONFIG_PACKAGE_thc-ipv6-flood-advertise6 is not set +# CONFIG_PACKAGE_thc-ipv6-flood-dhcpc6 is not set +# CONFIG_PACKAGE_thc-ipv6-flood-mld26 is not set +# CONFIG_PACKAGE_thc-ipv6-flood-mld6 is not set +# CONFIG_PACKAGE_thc-ipv6-flood-mldrouter6 is not set +# CONFIG_PACKAGE_thc-ipv6-flood-router26 is not set +# CONFIG_PACKAGE_thc-ipv6-flood-router6 is not set +# CONFIG_PACKAGE_thc-ipv6-flood-solicitate6 is not set +# CONFIG_PACKAGE_thc-ipv6-fragmentation6 is not set +# CONFIG_PACKAGE_thc-ipv6-fuzz-dhcpc6 is not set +# CONFIG_PACKAGE_thc-ipv6-fuzz-dhcps6 is not set +# CONFIG_PACKAGE_thc-ipv6-fuzz-ip6 is not set +# CONFIG_PACKAGE_thc-ipv6-implementation6 is not set +# CONFIG_PACKAGE_thc-ipv6-implementation6d is not set +# CONFIG_PACKAGE_thc-ipv6-inverse-lookup6 is not set +# CONFIG_PACKAGE_thc-ipv6-kill-router6 is not set +# CONFIG_PACKAGE_thc-ipv6-ndpexhaust6 is not set +# CONFIG_PACKAGE_thc-ipv6-node-query6 is not set +# CONFIG_PACKAGE_thc-ipv6-parasite6 is not set +# CONFIG_PACKAGE_thc-ipv6-passive-discovery6 is not set +# CONFIG_PACKAGE_thc-ipv6-randicmp6 is not set +# CONFIG_PACKAGE_thc-ipv6-redir6 is not set +# CONFIG_PACKAGE_thc-ipv6-rsmurf6 is not set +# CONFIG_PACKAGE_thc-ipv6-sendpees6 is not set +# CONFIG_PACKAGE_thc-ipv6-sendpeesmp6 is not set +# CONFIG_PACKAGE_thc-ipv6-smurf6 is not set +# CONFIG_PACKAGE_thc-ipv6-thcping6 is not set +# CONFIG_PACKAGE_thc-ipv6-toobig6 is not set +# CONFIG_PACKAGE_thc-ipv6-trace6 is not set + +# +# Telephony +# +# CONFIG_PACKAGE_asterisk11 is not set +# CONFIG_PACKAGE_asterisk13 is not set +# CONFIG_PACKAGE_baresip is not set +# CONFIG_PACKAGE_freeswitch is not set +# CONFIG_PACKAGE_freeswitch-stable is not set +# CONFIG_PACKAGE_kamailio5 is not set +# CONFIG_PACKAGE_miax is not set +# CONFIG_PACKAGE_pcapsipdump is not set +# CONFIG_PACKAGE_restund is not set +# CONFIG_PACKAGE_rtpproxy is not set +# CONFIG_PACKAGE_sipp is not set +# CONFIG_PACKAGE_siproxd is not set +# CONFIG_PACKAGE_yate is not set + +# +# Time Synchronization +# +# CONFIG_PACKAGE_chrony is not set +# CONFIG_PACKAGE_htpdate is not set +# CONFIG_PACKAGE_linuxptp is not set +# CONFIG_PACKAGE_ntp-keygen is not set +# CONFIG_PACKAGE_ntp-utils is not set +# CONFIG_PACKAGE_ntpclient is not set +# CONFIG_PACKAGE_ntpd is not set +# CONFIG_PACKAGE_ntpdate is not set + +# +# VPN +# +# CONFIG_PACKAGE_chaosvpn is not set +# CONFIG_PACKAGE_fastd is not set +# CONFIG_PACKAGE_ipsec-tools is not set +# CONFIG_PACKAGE_n2n_v2 is not set +# CONFIG_PACKAGE_ocserv is not set +# CONFIG_PACKAGE_openconnect is not set +# CONFIG_PACKAGE_opennhrp is not set +# CONFIG_PACKAGE_openvpn-easy-rsa is not set +# CONFIG_PACKAGE_openvpn-mbedtls is not set +# CONFIG_PACKAGE_openvpn-nossl is not set +# CONFIG_PACKAGE_openvpn-openssl is not set +CONFIG_PACKAGE_pptpd=y +# CONFIG_PACKAGE_softethervpn is not set +# CONFIG_PACKAGE_sstp-client is not set +CONFIG_PACKAGE_strongswan=y + +# +# Configuration +# +CONFIG_STRONGSWAN_ROUTING_TABLE="220" +CONFIG_STRONGSWAN_ROUTING_TABLE_PRIO="220" +CONFIG_PACKAGE_strongswan-charon=y +# CONFIG_PACKAGE_strongswan-charon-cmd is not set +# CONFIG_PACKAGE_strongswan-default is not set +CONFIG_PACKAGE_strongswan-ipsec=y +# CONFIG_PACKAGE_strongswan-isakmp is not set +# CONFIG_PACKAGE_strongswan-libtls is not set +CONFIG_PACKAGE_strongswan-minimal=y +# CONFIG_PACKAGE_strongswan-mod-addrblock is not set +CONFIG_PACKAGE_strongswan-mod-aes=y +# CONFIG_PACKAGE_strongswan-mod-af-alg is not set +# CONFIG_PACKAGE_strongswan-mod-agent is not set +# CONFIG_PACKAGE_strongswan-mod-attr is not set +# CONFIG_PACKAGE_strongswan-mod-attr-sql is not set +# CONFIG_PACKAGE_strongswan-mod-blowfish is not set +# CONFIG_PACKAGE_strongswan-mod-ccm is not set +# CONFIG_PACKAGE_strongswan-mod-cmac is not set +# CONFIG_PACKAGE_strongswan-mod-connmark is not set +# CONFIG_PACKAGE_strongswan-mod-constraints is not set +# CONFIG_PACKAGE_strongswan-mod-coupling is not set +# CONFIG_PACKAGE_strongswan-mod-ctr is not set +# CONFIG_PACKAGE_strongswan-mod-curl is not set +# CONFIG_PACKAGE_strongswan-mod-curve25519 is not set +# CONFIG_PACKAGE_strongswan-mod-des is not set +# CONFIG_PACKAGE_strongswan-mod-dhcp is not set +# CONFIG_PACKAGE_strongswan-mod-dnskey is not set +# CONFIG_PACKAGE_strongswan-mod-duplicheck is not set +# CONFIG_PACKAGE_strongswan-mod-eap-identity is not set +# CONFIG_PACKAGE_strongswan-mod-eap-md5 is not set +# CONFIG_PACKAGE_strongswan-mod-eap-mschapv2 is not set +# CONFIG_PACKAGE_strongswan-mod-eap-radius is not set +# CONFIG_PACKAGE_strongswan-mod-eap-tls is not set +# CONFIG_PACKAGE_strongswan-mod-farp is not set +# CONFIG_PACKAGE_strongswan-mod-fips-prf is not set +# CONFIG_PACKAGE_strongswan-mod-forecast is not set +# CONFIG_PACKAGE_strongswan-mod-gcm is not set +# CONFIG_PACKAGE_strongswan-mod-gcrypt is not set +CONFIG_PACKAGE_strongswan-mod-gmp=y +# CONFIG_PACKAGE_strongswan-mod-gmpdh is not set +# CONFIG_PACKAGE_strongswan-mod-ha is not set +CONFIG_PACKAGE_strongswan-mod-hmac=y +# CONFIG_PACKAGE_strongswan-mod-kernel-libipsec is not set +CONFIG_PACKAGE_strongswan-mod-kernel-netlink=y +# CONFIG_PACKAGE_strongswan-mod-ldap is not set +# CONFIG_PACKAGE_strongswan-mod-led is not set +# CONFIG_PACKAGE_strongswan-mod-load-tester is not set +# CONFIG_PACKAGE_strongswan-mod-md4 is not set +# CONFIG_PACKAGE_strongswan-mod-md5 is not set +# CONFIG_PACKAGE_strongswan-mod-mysql is not set +CONFIG_PACKAGE_strongswan-mod-nonce=y +# CONFIG_PACKAGE_strongswan-mod-openssl is not set +# CONFIG_PACKAGE_strongswan-mod-pem is not set +# CONFIG_PACKAGE_strongswan-mod-pgp is not set +# CONFIG_PACKAGE_strongswan-mod-pkcs1 is not set +# CONFIG_PACKAGE_strongswan-mod-pkcs11 is not set +# CONFIG_PACKAGE_strongswan-mod-pkcs12 is not set +# CONFIG_PACKAGE_strongswan-mod-pkcs7 is not set +# CONFIG_PACKAGE_strongswan-mod-pkcs8 is not set +CONFIG_PACKAGE_strongswan-mod-pubkey=y +CONFIG_PACKAGE_strongswan-mod-random=y +# CONFIG_PACKAGE_strongswan-mod-rc2 is not set +# CONFIG_PACKAGE_strongswan-mod-resolve is not set +# CONFIG_PACKAGE_strongswan-mod-revocation is not set +CONFIG_PACKAGE_strongswan-mod-sha1=y +# CONFIG_PACKAGE_strongswan-mod-sha2 is not set +# CONFIG_PACKAGE_strongswan-mod-smp is not set +CONFIG_PACKAGE_strongswan-mod-socket-default=y +# CONFIG_PACKAGE_strongswan-mod-socket-dynamic is not set +# CONFIG_PACKAGE_strongswan-mod-sql is not set +# CONFIG_PACKAGE_strongswan-mod-sqlite is not set +# CONFIG_PACKAGE_strongswan-mod-sshkey is not set +CONFIG_PACKAGE_strongswan-mod-stroke=y +# CONFIG_PACKAGE_strongswan-mod-test-vectors is not set +# CONFIG_PACKAGE_strongswan-mod-uci is not set +# CONFIG_PACKAGE_strongswan-mod-unity is not set +CONFIG_PACKAGE_strongswan-mod-updown=y +# CONFIG_PACKAGE_strongswan-mod-vici is not set +# CONFIG_PACKAGE_strongswan-mod-whitelist is not set +CONFIG_PACKAGE_strongswan-mod-x509=y +# CONFIG_PACKAGE_strongswan-mod-xauth-eap is not set +CONFIG_PACKAGE_strongswan-mod-xauth-generic=y +CONFIG_PACKAGE_strongswan-mod-xcbc=y +# CONFIG_PACKAGE_strongswan-pki is not set +# CONFIG_PACKAGE_strongswan-scepclient is not set +# CONFIG_PACKAGE_strongswan-swanctl is not set +# CONFIG_PACKAGE_tinc is not set +# CONFIG_PACKAGE_uanytun is not set +# CONFIG_PACKAGE_uanytun-nettle is not set +# CONFIG_PACKAGE_uanytun-nocrypt is not set +# CONFIG_PACKAGE_uanytun-sslcrypt is not set +# CONFIG_PACKAGE_vpnc is not set +# CONFIG_PACKAGE_vpnc-scripts is not set +# CONFIG_PACKAGE_wireguard is not set +# CONFIG_PACKAGE_wireguard-tools is not set +# CONFIG_PACKAGE_xl2tpd is not set +# CONFIG_PACKAGE_zerotier is not set + +# +# Version Control Systems +# +# CONFIG_PACKAGE_fossil is not set +# CONFIG_PACKAGE_git is not set +# CONFIG_PACKAGE_subversion-client is not set +# CONFIG_PACKAGE_subversion-libs is not set +# CONFIG_PACKAGE_subversion-server is not set + +# +# WWAN +# +# CONFIG_PACKAGE_adb-enablemodem is not set +# CONFIG_PACKAGE_comgt is not set +# CONFIG_PACKAGE_comgt-directip is not set +# CONFIG_PACKAGE_comgt-ncm is not set +# CONFIG_PACKAGE_uqmi is not set + +# +# Web Servers/Proxies +# +# CONFIG_PACKAGE_apache is not set +# CONFIG_PACKAGE_cgi-io is not set +# CONFIG_PACKAGE_clamav is not set +# CONFIG_PACKAGE_dansguardian is not set +# CONFIG_PACKAGE_e2guardian is not set +# CONFIG_PACKAGE_freshclam is not set +# CONFIG_PACKAGE_haproxy is not set +# CONFIG_PACKAGE_haproxy-nossl is not set +# CONFIG_PACKAGE_lighttpd is not set +# CONFIG_PACKAGE_nginx is not set +# CONFIG_PACKAGE_ngrokc is not set +CONFIG_PACKAGE_pdnsd-alt=y +# CONFIG_PACKAGE_polipo is not set +# CONFIG_PACKAGE_privoxy is not set +# CONFIG_PACKAGE_radicale-py2 is not set +# CONFIG_PACKAGE_radicale-py3 is not set +# CONFIG_PACKAGE_shadowsocks-client is not set +# CONFIG_PACKAGE_shadowsocks-libev-config is not set +# CONFIG_PACKAGE_shadowsocks-libev-ss-local is not set +# CONFIG_PACKAGE_shadowsocks-libev-ss-redir is not set +# CONFIG_PACKAGE_shadowsocks-libev-ss-rules is not set +# CONFIG_PACKAGE_shadowsocks-libev-ss-server is not set +# CONFIG_PACKAGE_shadowsocks-libev-ss-tunnel is not set +# CONFIG_PACKAGE_sockd is not set +# CONFIG_PACKAGE_socksify is not set +# CONFIG_PACKAGE_spawn-fcgi is not set +# CONFIG_PACKAGE_squid is not set +# CONFIG_PACKAGE_tinyproxy is not set +CONFIG_PACKAGE_uhttpd=y +# CONFIG_PACKAGE_uhttpd_debug is not set +# CONFIG_PACKAGE_uhttpd-mod-lua is not set +CONFIG_PACKAGE_uhttpd-mod-ubus=y + +# +# dial-in/up +# +# CONFIG_PACKAGE_rp-pppoe-common is not set +# CONFIG_PACKAGE_rp-pppoe-relay is not set +# CONFIG_PACKAGE_rp-pppoe-server is not set + +# +# tcprelay +# +# CONFIG_PACKAGE_tcpbridge is not set +# CONFIG_PACKAGE_tcpcapinfo is not set +# CONFIG_PACKAGE_tcpliveplay is not set +# CONFIG_PACKAGE_tcpprep is not set +# CONFIG_PACKAGE_tcpreplay is not set +# CONFIG_PACKAGE_tcpreplay-all is not set +# CONFIG_PACKAGE_tcpreplay-edit is not set +# CONFIG_PACKAGE_tcprewrite is not set + +# +# wireless +# +# CONFIG_PACKAGE_aircrack-ng is not set +# CONFIG_PACKAGE_airmon-ng is not set +# CONFIG_PACKAGE_dynapoint is not set +# CONFIG_PACKAGE_horst is not set +# CONFIG_PACKAGE_kismet-client is not set +# CONFIG_PACKAGE_kismet-drone is not set +# CONFIG_PACKAGE_kismet-server is not set +# CONFIG_PACKAGE_reaver is not set +# CONFIG_PACKAGE_wavemon is not set +CONFIG_PACKAGE_wifischedule=y +# CONFIG_PACKAGE_464xlat is not set +# CONFIG_PACKAGE_6in4 is not set +# CONFIG_PACKAGE_6rd is not set +# CONFIG_PACKAGE_6to4 is not set +# CONFIG_PACKAGE_acme is not set +# CONFIG_PACKAGE_adblock is not set +CONFIG_PACKAGE_adbyby=y +# CONFIG_PACKAGE_addrwatch is not set +# CONFIG_PACKAGE_ahcpd is not set +# CONFIG_PACKAGE_alfred is not set +# CONFIG_PACKAGE_apcupsd is not set +# CONFIG_PACKAGE_apcupsd-cgi is not set +# CONFIG_PACKAGE_apinger is not set +# CONFIG_PACKAGE_arp-scan is not set +# CONFIG_PACKAGE_authsae is not set +# CONFIG_PACKAGE_batctl is not set +# CONFIG_PACKAGE_beanstalkd is not set +# CONFIG_PACKAGE_bmon is not set +# CONFIG_PACKAGE_bwm-ng is not set +# CONFIG_PACKAGE_chat is not set +# CONFIG_PACKAGE_cifsmount is not set +# CONFIG_PACKAGE_coap-server is not set +# CONFIG_PACKAGE_conserver is not set +# CONFIG_PACKAGE_cshark is not set +# CONFIG_PACKAGE_daemonlogger is not set +# CONFIG_PACKAGE_darkstat is not set +# CONFIG_PACKAGE_dhcpcd is not set +# CONFIG_PACKAGE_dmapd is not set +# CONFIG_PACKAGE_dogcom is not set +# CONFIG_PACKAGE_ds-lite is not set +# CONFIG_PACKAGE_eapol-test is not set +# CONFIG_PACKAGE_esniper is not set +CONFIG_PACKAGE_etherwake=y +# CONFIG_PACKAGE_ethtool is not set +# CONFIG_PACKAGE_fakeidentd is not set +# CONFIG_PACKAGE_fping is not set +# CONFIG_PACKAGE_frpc is not set +# CONFIG_PACKAGE_gnunet is not set +# CONFIG_PACKAGE_gre is not set +# CONFIG_PACKAGE_hnet-full is not set +# CONFIG_PACKAGE_hnet-full-l2tp is not set +# CONFIG_PACKAGE_hnet-full-secure is not set +# CONFIG_PACKAGE_hnetd-nossl is not set +# CONFIG_PACKAGE_hnetd-openssl is not set +# CONFIG_PACKAGE_hostapd is not set +CONFIG_PACKAGE_hostapd-common=y +# CONFIG_PACKAGE_hostapd-mini is not set +# CONFIG_PACKAGE_hostapd-utils is not set +# CONFIG_PACKAGE_httping is not set +# CONFIG_PACKAGE_httping-nossl is not set +# CONFIG_PACKAGE_https_dns_proxy is not set +# CONFIG_PACKAGE_ibrdtn-tools is not set +# CONFIG_PACKAGE_ibrdtnd is not set +# CONFIG_PACKAGE_ifstat is not set +# CONFIG_PACKAGE_iftop is not set +# CONFIG_PACKAGE_iiod is not set +# CONFIG_PACKAGE_iotivity is not set +# CONFIG_PACKAGE_iotivity-cpp is not set +# CONFIG_PACKAGE_iotivity-example-garage is not set +# CONFIG_PACKAGE_iotivity-example-simple is not set +# CONFIG_PACKAGE_iotivity-oic-middle is not set +# CONFIG_PACKAGE_iotivity-resource-container-hue is not set +# CONFIG_PACKAGE_iotivity-resource-container-lib is not set +# CONFIG_PACKAGE_iotivity-resource-container-sample is not set +# CONFIG_PACKAGE_iotivity-resource-directory-lib is not set +# CONFIG_PACKAGE_iperf is not set +# CONFIG_PACKAGE_iperf3 is not set +# CONFIG_PACKAGE_iperf3-ssl is not set +# CONFIG_PACKAGE_ipip is not set +CONFIG_PACKAGE_ipset=y +# CONFIG_PACKAGE_ipset-dns is not set +CONFIG_PACKAGE_ipset-lists=y +# CONFIG_PACKAGE_iptraf-ng is not set +# CONFIG_PACKAGE_iputils-arping is not set +# CONFIG_PACKAGE_iputils-clockdiff is not set +# CONFIG_PACKAGE_iputils-ping is not set +# CONFIG_PACKAGE_iputils-ping6 is not set +# CONFIG_PACKAGE_iputils-tftpd is not set +# CONFIG_PACKAGE_iputils-tracepath is not set +# CONFIG_PACKAGE_iputils-tracepath6 is not set +# CONFIG_PACKAGE_iputils-traceroute6 is not set +CONFIG_PACKAGE_iw=y +# CONFIG_PACKAGE_jool is not set +# CONFIG_PACKAGE_jool-tools is not set +# CONFIG_PACKAGE_keepalived is not set +# CONFIG_PACKAGE_knxd is not set +# CONFIG_PACKAGE_kplex is not set +# CONFIG_PACKAGE_krb5-client is not set +# CONFIG_PACKAGE_krb5-libs is not set +# CONFIG_PACKAGE_krb5-server is not set +CONFIG_PACKAGE_libipset=y +# CONFIG_PACKAGE_linknx is not set +# CONFIG_PACKAGE_lispd is not set +# CONFIG_PACKAGE_mac-telnet-client is not set +# CONFIG_PACKAGE_mac-telnet-discover is not set +# CONFIG_PACKAGE_mac-telnet-ping is not set +# CONFIG_PACKAGE_mac-telnet-server is not set +# CONFIG_PACKAGE_map is not set +# CONFIG_PACKAGE_map-t is not set +# CONFIG_PACKAGE_memcached is not set +# CONFIG_PACKAGE_mii-tool is not set +# CONFIG_PACKAGE_mini_snmpd is not set +# CONFIG_PACKAGE_minimalist-pcproxy is not set +# CONFIG_PACKAGE_mosquitto-client-nossl is not set +# CONFIG_PACKAGE_mosquitto-client-ssl is not set +# CONFIG_PACKAGE_mosquitto-nossl is not set +# CONFIG_PACKAGE_mosquitto-ssl is not set +# CONFIG_PACKAGE_mproxy is not set +# CONFIG_PACKAGE_mrd6 is not set +# CONFIG_PACKAGE_mtr is not set +# CONFIG_PACKAGE_nbd is not set +# CONFIG_PACKAGE_nbd-server is not set +# CONFIG_PACKAGE_ncp is not set +# CONFIG_PACKAGE_ndppd is not set +# CONFIG_PACKAGE_netcat is not set +# CONFIG_PACKAGE_netdiscover is not set +# CONFIG_PACKAGE_netperf is not set +CONFIG_PACKAGE_nlbwmon=y +# CONFIG_PACKAGE_noddos is not set +# CONFIG_PACKAGE_noping is not set +# CONFIG_PACKAGE_nut is not set +# CONFIG_PACKAGE_obfsproxy is not set +# CONFIG_PACKAGE_odhcp6c is not set +# CONFIG_PACKAGE_odhcpd is not set +# CONFIG_PACKAGE_ola is not set +# CONFIG_PACKAGE_omcproxy is not set +# CONFIG_PACKAGE_openldap-server is not set +# CONFIG_PACKAGE_oscam is not set +# CONFIG_PACKAGE_oping is not set +# CONFIG_PACKAGE_pen is not set +# CONFIG_PACKAGE_pimbd is not set +# CONFIG_PACKAGE_pingcheck is not set +# CONFIG_PACKAGE_port-mirroring is not set +# CONFIG_PACKAGE_portmap is not set +CONFIG_PACKAGE_ppp=y +# CONFIG_PACKAGE_ppp-mod-passwordfd is not set +# CONFIG_PACKAGE_ppp-mod-pppoa is not set +CONFIG_PACKAGE_ppp-mod-pppoe=y +# CONFIG_PACKAGE_ppp-mod-pppol2tp is not set +# CONFIG_PACKAGE_ppp-mod-pptp is not set +# CONFIG_PACKAGE_ppp-mod-radius is not set +# CONFIG_PACKAGE_ppp-multilink is not set +# CONFIG_PACKAGE_pppdump is not set +# CONFIG_PACKAGE_pppoe-discovery is not set +# CONFIG_PACKAGE_pppossh is not set +# CONFIG_PACKAGE_pppstats is not set +# CONFIG_PACKAGE_radsecproxy is not set +# CONFIG_PACKAGE_redsocks is not set +# CONFIG_PACKAGE_remserial is not set +# CONFIG_PACKAGE_rssileds is not set +# CONFIG_PACKAGE_rsyslog is not set +# CONFIG_PACKAGE_samba36-client is not set +# CONFIG_PACKAGE_samba36-net is not set +# CONFIG_PACKAGE_samba36-server is not set +# CONFIG_PACKAGE_scapy is not set +# CONFIG_PACKAGE_sctp is not set +# CONFIG_PACKAGE_sctp-tools is not set +# CONFIG_PACKAGE_seafile-ccnet is not set +# CONFIG_PACKAGE_seafile-seahub is not set +# CONFIG_PACKAGE_seafile-server is not set +# CONFIG_PACKAGE_ser2net is not set +# CONFIG_PACKAGE_shadowsocksr-libev is not set +CONFIG_PACKAGE_shadowsocksr-libev-alt=y +# CONFIG_PACKAGE_shadowsocksr-libev-gfwlist is not set +# CONFIG_PACKAGE_shadowsocksr-libev-gfwlist-4M is not set +# CONFIG_PACKAGE_shadowsocksr-libev-gfwlist-polarssl is not set +# CONFIG_PACKAGE_shadowsocksr-libev-mini is not set +# CONFIG_PACKAGE_shadowsocksr-libev-polarssl is not set +# CONFIG_PACKAGE_simple-adblock is not set +# CONFIG_PACKAGE_sipgrep is not set +# CONFIG_PACKAGE_smartsnmpd is not set +# CONFIG_PACKAGE_sngrep is not set +# CONFIG_PACKAGE_snmp-mibs is not set +# CONFIG_PACKAGE_snmp-utils is not set +# CONFIG_PACKAGE_snmpd is not set +# CONFIG_PACKAGE_snmpd-static is not set +# CONFIG_PACKAGE_snmptrapd is not set +# CONFIG_PACKAGE_socat is not set +# CONFIG_PACKAGE_softflowd is not set +# CONFIG_PACKAGE_soloscli is not set +# CONFIG_PACKAGE_stunnel is not set +# CONFIG_PACKAGE_tayga is not set +# CONFIG_PACKAGE_tcpdump is not set +# CONFIG_PACKAGE_tcpdump-mini is not set +# CONFIG_PACKAGE_tor is not set +# CONFIG_PACKAGE_tor-gencert is not set +# CONFIG_PACKAGE_tor-geoip is not set +# CONFIG_PACKAGE_tor-resolve is not set +# CONFIG_PACKAGE_travelmate is not set +# CONFIG_PACKAGE_u2pnpd is not set +CONFIG_PACKAGE_uclient-fetch=y +# CONFIG_PACKAGE_udpxy is not set +# CONFIG_PACKAGE_ulogd is not set +# CONFIG_PACKAGE_umbim is not set +# CONFIG_PACKAGE_umdns is not set +# CONFIG_PACKAGE_usbip is not set +# CONFIG_PACKAGE_vallumd is not set +CONFIG_PACKAGE_vlmcsd=y +# CONFIG_PACKAGE_vncrepeater is not set +# CONFIG_PACKAGE_vnstat is not set +# CONFIG_PACKAGE_vpnbypass is not set +# CONFIG_PACKAGE_vsc7385-ucode-pb44 is not set +# CONFIG_PACKAGE_vsc7395-ucode-pb44 is not set +# CONFIG_PACKAGE_vti is not set +# CONFIG_PACKAGE_vxlan is not set +# CONFIG_PACKAGE_wakeonlan is not set +# CONFIG_PACKAGE_wpa-cli is not set +# CONFIG_PACKAGE_wpa-supplicant is not set +# CONFIG_WPA_SUPPLICANT_NO_TIMESTAMP_CHECK is not set +# CONFIG_WPA_RFKILL_SUPPORT is not set +CONFIG_WPA_MSG_MIN_PRIORITY=3 +# CONFIG_DRIVER_WEXT_SUPPORT is not set +CONFIG_DRIVER_11N_SUPPORT=y +CONFIG_DRIVER_11AC_SUPPORT=y +CONFIG_DRIVER_11W_SUPPORT=y +# CONFIG_PACKAGE_wpa-supplicant-mesh is not set +# CONFIG_PACKAGE_wpa-supplicant-mini is not set +# CONFIG_PACKAGE_wpa-supplicant-p2p is not set +# CONFIG_PACKAGE_wpad is not set +# CONFIG_PACKAGE_wpad-mesh is not set +CONFIG_PACKAGE_wpad-mini=y +# CONFIG_PACKAGE_wpan-tools is not set +# CONFIG_PACKAGE_wwan is not set +# CONFIG_PACKAGE_xinetd is not set + +# +# Sound +# +# CONFIG_PACKAGE_alsa-utils is not set +# CONFIG_PACKAGE_alsa-utils-seq is not set +# CONFIG_PACKAGE_alsa-utils-tests is not set +# CONFIG_PACKAGE_espeak is not set +# CONFIG_PACKAGE_faad2 is not set +# CONFIG_PACKAGE_fdk-aac is not set +# CONFIG_PACKAGE_forked-daapd is not set +# CONFIG_PACKAGE_ices is not set +# CONFIG_PACKAGE_lame is not set +# CONFIG_PACKAGE_lame-lib is not set +# CONFIG_PACKAGE_liblo-utils is not set +# CONFIG_PACKAGE_madplay is not set +# CONFIG_PACKAGE_madplay-alsa is not set +# CONFIG_PACKAGE_moc is not set +# CONFIG_PACKAGE_mpc is not set +# CONFIG_PACKAGE_mpd-avahi-service is not set +# CONFIG_PACKAGE_mpd-full is not set +# CONFIG_PACKAGE_mpd-mini is not set +# CONFIG_PACKAGE_mpg123 is not set +# CONFIG_PACKAGE_pianod is not set +# CONFIG_PACKAGE_pianod-client is not set +# CONFIG_PACKAGE_portaudio is not set +# CONFIG_PACKAGE_pulseaudio-daemon is not set +# CONFIG_PACKAGE_pulseaudio-profiles is not set +# CONFIG_PACKAGE_pulseaudio-tools is not set +# CONFIG_PACKAGE_shairplay is not set +# CONFIG_PACKAGE_shairport-sync-mbedtls is not set +# CONFIG_PACKAGE_shairport-sync-mini is not set +# CONFIG_PACKAGE_shairport-sync-openssl is not set +# CONFIG_PACKAGE_shine is not set +# CONFIG_PACKAGE_sox is not set +# CONFIG_PACKAGE_squeezelite-full is not set +# CONFIG_PACKAGE_squeezelite-mini is not set +# CONFIG_PACKAGE_svox is not set +# CONFIG_PACKAGE_upmpdcli is not set + +# +# Utilities +# + +# +# Boot Loaders +# +# CONFIG_PACKAGE_fconfig is not set +# CONFIG_PACKAGE_rbcfg is not set +CONFIG_PACKAGE_uboot-envtools=y +# CONFIG_UBOOT_ENVTOOLS_UBI is not set + +# +# Compression +# +# CONFIG_PACKAGE_bsdtar is not set +# CONFIG_PACKAGE_bzip2 is not set +# CONFIG_PACKAGE_gzip is not set +# CONFIG_PACKAGE_unrar is not set +# CONFIG_PACKAGE_unzip is not set +# CONFIG_PACKAGE_xz-utils is not set +# CONFIG_PACKAGE_zip is not set + +# +# Disc +# +# CONFIG_PACKAGE_blkdiscard is not set +# CONFIG_PACKAGE_blkid is not set +# CONFIG_PACKAGE_cfdisk is not set +# CONFIG_PACKAGE_fdisk is not set +# CONFIG_PACKAGE_findfs is not set +# CONFIG_PACKAGE_hd-idle is not set +# CONFIG_PACKAGE_hdparm is not set +# CONFIG_PACKAGE_lsblk is not set +# CONFIG_PACKAGE_lvm2 is not set +# CONFIG_PACKAGE_mdadm is not set +# CONFIG_PACKAGE_partx-utils is not set +# CONFIG_PACKAGE_sfdisk is not set +# CONFIG_PACKAGE_wipefs is not set + +# +# Editors +# +# CONFIG_PACKAGE_joe is not set +# CONFIG_PACKAGE_nano is not set +# CONFIG_PACKAGE_vim is not set +# CONFIG_PACKAGE_vim-full is not set +# CONFIG_PACKAGE_vim-fuller is not set +# CONFIG_PACKAGE_vim-help is not set +# CONFIG_PACKAGE_vim-runtime is not set +# CONFIG_PACKAGE_zile is not set + +# +# Encryption +# +# CONFIG_PACKAGE_ccrypt is not set +# CONFIG_PACKAGE_certtool is not set +# CONFIG_PACKAGE_cryptsetup is not set +# CONFIG_PACKAGE_cryptsetup-openssl is not set +# CONFIG_PACKAGE_gnupg is not set +# CONFIG_PACKAGE_gnutls-utils is not set +# CONFIG_PACKAGE_gpgv is not set +# CONFIG_PACKAGE_px5g-mbedtls is not set +# CONFIG_PACKAGE_px5g-standalone is not set +# CONFIG_PACKAGE_stoken is not set + +# +# Filesystem +# +# CONFIG_PACKAGE_acl is not set +# CONFIG_PACKAGE_attr is not set +# CONFIG_PACKAGE_badblocks is not set +# CONFIG_PACKAGE_btrfs-progs is not set +# CONFIG_PACKAGE_chattr is not set +# CONFIG_PACKAGE_debugfs is not set +# CONFIG_PACKAGE_dosfstools is not set +# CONFIG_PACKAGE_dumpe2fs is not set +# CONFIG_PACKAGE_e2freefrag is not set +# CONFIG_PACKAGE_e2fsprogs is not set +# CONFIG_PACKAGE_f2fs-tools is not set +# CONFIG_PACKAGE_f2fsck is not set +# CONFIG_PACKAGE_filefrag is not set +# CONFIG_PACKAGE_fuse-utils is not set +# CONFIG_PACKAGE_hfsfsck is not set +# CONFIG_PACKAGE_lsattr is not set +# CONFIG_PACKAGE_mkf2fs is not set +# CONFIG_PACKAGE_mkhfs is not set +# CONFIG_PACKAGE_ncdu is not set +# CONFIG_PACKAGE_nfs-utils is not set +CONFIG_PACKAGE_ntfs-3g=y +# CONFIG_PACKAGE_NTFS-3G_USE_LIBFUSE is not set +# CONFIG_PACKAGE_ntfs-3g-low is not set +# CONFIG_PACKAGE_ntfs-3g-utils is not set +# CONFIG_PACKAGE_owfs is not set +# CONFIG_PACKAGE_owshell is not set +# CONFIG_PACKAGE_resize2fs is not set +# CONFIG_PACKAGE_squashfs-tools-mksquashfs is not set +# CONFIG_PACKAGE_squashfs-tools-unsquashfs is not set +# CONFIG_PACKAGE_swap-utils is not set +# CONFIG_PACKAGE_sysfsutils is not set +# CONFIG_PACKAGE_tune2fs is not set +# CONFIG_PACKAGE_xfs-fsck is not set +# CONFIG_PACKAGE_xfs-growfs is not set +# CONFIG_PACKAGE_xfs-mkfs is not set + +# +# Image Manipulation +# +# CONFIG_PACKAGE_jpeg-tools is not set +# CONFIG_PACKAGE_tiff-utils is not set + +# +# Luci +# +# CONFIG_PACKAGE_luci-app-haproxy-tcp is not set + +# +# Microcontroller programming +# +# CONFIG_PACKAGE_avrdude is not set +# CONFIG_PACKAGE_dfu-programmer is not set +# CONFIG_PACKAGE_stm32flash is not set + +# +# RTKLIB Suite +# +# CONFIG_PACKAGE_convbin is not set +# CONFIG_PACKAGE_pos2kml is not set +# CONFIG_PACKAGE_rnx2rtkp is not set +# CONFIG_PACKAGE_rtkrcv is not set +# CONFIG_PACKAGE_str2str is not set + +# +# Shells +# +# CONFIG_PACKAGE_bash is not set +# CONFIG_PACKAGE_klish is not set +# CONFIG_PACKAGE_tcsh is not set +# CONFIG_PACKAGE_zsh is not set + +# +# Telephony +# +# CONFIG_PACKAGE_dahdi-cfg is not set +# CONFIG_PACKAGE_dahdi-monitor is not set + +# +# Terminal +# +# CONFIG_PACKAGE_agetty is not set +# CONFIG_PACKAGE_dvtm is not set +# CONFIG_PACKAGE_minicom is not set +# CONFIG_PACKAGE_picocom is not set +# CONFIG_PACKAGE_screen is not set +# CONFIG_PACKAGE_script-utils is not set +# CONFIG_PACKAGE_serialconsole is not set +# CONFIG_PACKAGE_setterm is not set +# CONFIG_PACKAGE_tmux is not set +# CONFIG_PACKAGE_ttyd is not set +# CONFIG_PACKAGE_wall is not set + +# +# Virtualization +# + +# +# Zoneinfo +# +# CONFIG_PACKAGE_zoneinfo-africa is not set +# CONFIG_PACKAGE_zoneinfo-asia is not set +# CONFIG_PACKAGE_zoneinfo-atlantic is not set +# CONFIG_PACKAGE_zoneinfo-australia-nz is not set +# CONFIG_PACKAGE_zoneinfo-core is not set +# CONFIG_PACKAGE_zoneinfo-europe is not set +# CONFIG_PACKAGE_zoneinfo-india is not set +# CONFIG_PACKAGE_zoneinfo-northamerica is not set +# CONFIG_PACKAGE_zoneinfo-pacific is not set +# CONFIG_PACKAGE_zoneinfo-poles is not set +# CONFIG_PACKAGE_zoneinfo-simple is not set +# CONFIG_PACKAGE_zoneinfo-southamerica is not set + +# +# database +# +# CONFIG_PACKAGE_mysql-server is not set +# CONFIG_PACKAGE_pgsql-cli is not set +# CONFIG_PACKAGE_pgsql-cli-extra is not set +# CONFIG_PACKAGE_pgsql-server is not set +# CONFIG_PACKAGE_rrdcgi1 is not set +# CONFIG_PACKAGE_rrdtool1 is not set +# CONFIG_PACKAGE_sqlite3-cli is not set +# CONFIG_PACKAGE_unixodbc-tools is not set +# CONFIG_PACKAGE_adb is not set +# CONFIG_PACKAGE_ap51-flash is not set +# CONFIG_PACKAGE_at is not set +# CONFIG_PACKAGE_bandwidthd is not set +# CONFIG_PACKAGE_bandwidthd-pgsql is not set +# CONFIG_PACKAGE_bandwidthd-php is not set +# CONFIG_PACKAGE_bandwidthd-sqlite is not set +# CONFIG_PACKAGE_banhostlist is not set +# CONFIG_PACKAGE_bc is not set +# CONFIG_PACKAGE_bluelog is not set +# CONFIG_PACKAGE_bluez-daemon is not set +# CONFIG_PACKAGE_bluez-examples is not set +# CONFIG_PACKAGE_bluez-utils is not set +# CONFIG_PACKAGE_bonniexx is not set +# CONFIG_PACKAGE_bsdiff is not set +# CONFIG_PACKAGE_bspatch is not set +# CONFIG_PACKAGE_cal is not set +# CONFIG_PACKAGE_canutils is not set +# CONFIG_PACKAGE_cmdpad is not set +# CONFIG_PACKAGE_coap-client is not set +# CONFIG_PACKAGE_collectd is not set +CONFIG_PACKAGE_coreutils=y +CONFIG_PACKAGE_coreutils-base64=y +# CONFIG_PACKAGE_coreutils-basename is not set +# CONFIG_PACKAGE_coreutils-cat is not set +# CONFIG_PACKAGE_coreutils-chcon is not set +# CONFIG_PACKAGE_coreutils-chgrp is not set +# CONFIG_PACKAGE_coreutils-chmod is not set +# CONFIG_PACKAGE_coreutils-chown is not set +# CONFIG_PACKAGE_coreutils-chroot is not set +# CONFIG_PACKAGE_coreutils-cksum is not set +# CONFIG_PACKAGE_coreutils-comm is not set +# CONFIG_PACKAGE_coreutils-cp is not set +# CONFIG_PACKAGE_coreutils-csplit is not set +# CONFIG_PACKAGE_coreutils-cut is not set +# CONFIG_PACKAGE_coreutils-date is not set +# CONFIG_PACKAGE_coreutils-dd is not set +# CONFIG_PACKAGE_coreutils-dir is not set +# CONFIG_PACKAGE_coreutils-dircolors is not set +# CONFIG_PACKAGE_coreutils-dirname is not set +# CONFIG_PACKAGE_coreutils-du is not set +# CONFIG_PACKAGE_coreutils-echo is not set +# CONFIG_PACKAGE_coreutils-env is not set +# CONFIG_PACKAGE_coreutils-expand is not set +# CONFIG_PACKAGE_coreutils-expr is not set +# CONFIG_PACKAGE_coreutils-factor is not set +# CONFIG_PACKAGE_coreutils-false is not set +# CONFIG_PACKAGE_coreutils-fmt is not set +# CONFIG_PACKAGE_coreutils-fold is not set +# CONFIG_PACKAGE_coreutils-groups is not set +# CONFIG_PACKAGE_coreutils-head is not set +# CONFIG_PACKAGE_coreutils-hostid is not set +# CONFIG_PACKAGE_coreutils-id is not set +# CONFIG_PACKAGE_coreutils-install is not set +# CONFIG_PACKAGE_coreutils-join is not set +# CONFIG_PACKAGE_coreutils-kill is not set +# CONFIG_PACKAGE_coreutils-link is not set +# CONFIG_PACKAGE_coreutils-ln is not set +# CONFIG_PACKAGE_coreutils-logname is not set +# CONFIG_PACKAGE_coreutils-ls is not set +# CONFIG_PACKAGE_coreutils-md5sum is not set +# CONFIG_PACKAGE_coreutils-mkdir is not set +# CONFIG_PACKAGE_coreutils-mkfifo is not set +# CONFIG_PACKAGE_coreutils-mknod is not set +# CONFIG_PACKAGE_coreutils-mktemp is not set +# CONFIG_PACKAGE_coreutils-mv is not set +# CONFIG_PACKAGE_coreutils-nice is not set +# CONFIG_PACKAGE_coreutils-nl is not set +CONFIG_PACKAGE_coreutils-nohup=y +# CONFIG_PACKAGE_coreutils-nproc is not set +# CONFIG_PACKAGE_coreutils-od is not set +# CONFIG_PACKAGE_coreutils-paste is not set +# CONFIG_PACKAGE_coreutils-pathchk is not set +# CONFIG_PACKAGE_coreutils-pinky is not set +# CONFIG_PACKAGE_coreutils-pr is not set +# CONFIG_PACKAGE_coreutils-printenv is not set +# CONFIG_PACKAGE_coreutils-printf is not set +# CONFIG_PACKAGE_coreutils-ptx is not set +# CONFIG_PACKAGE_coreutils-pwd is not set +# CONFIG_PACKAGE_coreutils-readlink is not set +# CONFIG_PACKAGE_coreutils-realpath is not set +# CONFIG_PACKAGE_coreutils-rm is not set +# CONFIG_PACKAGE_coreutils-rmdir is not set +# CONFIG_PACKAGE_coreutils-runcon is not set +# CONFIG_PACKAGE_coreutils-seq is not set +# CONFIG_PACKAGE_coreutils-sha1sum is not set +# CONFIG_PACKAGE_coreutils-sha224sum is not set +# CONFIG_PACKAGE_coreutils-sha256sum is not set +# CONFIG_PACKAGE_coreutils-sha384sum is not set +# CONFIG_PACKAGE_coreutils-sha512sum is not set +# CONFIG_PACKAGE_coreutils-shred is not set +# CONFIG_PACKAGE_coreutils-shuf is not set +# CONFIG_PACKAGE_coreutils-sleep is not set +# CONFIG_PACKAGE_coreutils-sort is not set +# CONFIG_PACKAGE_coreutils-split is not set +# CONFIG_PACKAGE_coreutils-stat is not set +# CONFIG_PACKAGE_coreutils-stdbuf is not set +# CONFIG_PACKAGE_coreutils-stty is not set +# CONFIG_PACKAGE_coreutils-sum is not set +# CONFIG_PACKAGE_coreutils-sync is not set +# CONFIG_PACKAGE_coreutils-tac is not set +# CONFIG_PACKAGE_coreutils-tail is not set +# CONFIG_PACKAGE_coreutils-tee is not set +# CONFIG_PACKAGE_coreutils-test is not set +# CONFIG_PACKAGE_coreutils-timeout is not set +# CONFIG_PACKAGE_coreutils-touch is not set +# CONFIG_PACKAGE_coreutils-tr is not set +# CONFIG_PACKAGE_coreutils-true is not set +# CONFIG_PACKAGE_coreutils-truncate is not set +# CONFIG_PACKAGE_coreutils-tsort is not set +# CONFIG_PACKAGE_coreutils-tty is not set +# CONFIG_PACKAGE_coreutils-uname is not set +# CONFIG_PACKAGE_coreutils-unexpand is not set +# CONFIG_PACKAGE_coreutils-uniq is not set +# CONFIG_PACKAGE_coreutils-unlink is not set +# CONFIG_PACKAGE_coreutils-uptime is not set +# CONFIG_PACKAGE_coreutils-users is not set +# CONFIG_PACKAGE_coreutils-vdir is not set +# CONFIG_PACKAGE_coreutils-wc is not set +# CONFIG_PACKAGE_coreutils-who is not set +# CONFIG_PACKAGE_coreutils-whoami is not set +# CONFIG_PACKAGE_coreutils-yes is not set +# CONFIG_PACKAGE_crelay is not set +# CONFIG_PACKAGE_ct-bugcheck is not set +# CONFIG_PACKAGE_dbus is not set +# CONFIG_PACKAGE_dfu-util is not set +# CONFIG_PACKAGE_dmesg is not set +# CONFIG_PACKAGE_domoticz is not set +# CONFIG_PACKAGE_dropbearconvert is not set +# CONFIG_PACKAGE_dtc is not set +# CONFIG_PACKAGE_dump1090 is not set +# CONFIG_PACKAGE_ecdsautils is not set +# CONFIG_PACKAGE_elektra-kdb is not set +# CONFIG_PACKAGE_evtest is not set +# CONFIG_PACKAGE_extract is not set +# CONFIG_PACKAGE_file is not set +# CONFIG_PACKAGE_findutils-find is not set +# CONFIG_PACKAGE_findutils-locate is not set +# CONFIG_PACKAGE_findutils-xargs is not set +# CONFIG_PACKAGE_flashrom is not set +# CONFIG_PACKAGE_flashrom-pci is not set +# CONFIG_PACKAGE_flashrom-spi is not set +# CONFIG_PACKAGE_flashrom-usb is not set +# CONFIG_PACKAGE_flent-tools is not set +# CONFIG_PACKAGE_flock is not set +# CONFIG_PACKAGE_fritz-caldata is not set +# CONFIG_PACKAGE_fritz-tffs is not set +# CONFIG_PACKAGE_ftdi_eeprom is not set +# CONFIG_PACKAGE_gammu is not set +# CONFIG_PACKAGE_gawk is not set +# CONFIG_PACKAGE_getopt is not set +# CONFIG_PACKAGE_gkermit is not set +# CONFIG_PACKAGE_gpioctl-sysfs is not set +# CONFIG_PACKAGE_gpsd is not set +# CONFIG_PACKAGE_gpsd-clients is not set +# CONFIG_PACKAGE_grep is not set +# CONFIG_PACKAGE_hamlib is not set +# CONFIG_PACKAGE_haserl is not set +# CONFIG_PACKAGE_haveged is not set +# CONFIG_PACKAGE_hub-ctrl is not set +# CONFIG_PACKAGE_hwclock is not set +# CONFIG_PACKAGE_i2c-tools is not set +# CONFIG_PACKAGE_iconv is not set +# CONFIG_PACKAGE_iio-utils is not set +# CONFIG_PACKAGE_io is not set +# CONFIG_PACKAGE_irqbalance is not set +# CONFIG_PACKAGE_iwcap is not set +CONFIG_PACKAGE_iwinfo=y +# CONFIG_PACKAGE_jq is not set +CONFIG_PACKAGE_jshn=y +# CONFIG_PACKAGE_kmod is not set +# CONFIG_PACKAGE_lcd4linux-custom is not set +# CONFIG_PACKAGE_lcdproc-clients is not set +# CONFIG_PACKAGE_lcdproc-drivers is not set +# CONFIG_PACKAGE_lcdproc-server is not set +# CONFIG_PACKAGE_less is not set +# CONFIG_PACKAGE_less-wide is not set +# CONFIG_PACKAGE_libimobiledevice-utils is not set +CONFIG_PACKAGE_libjson-script=y +# CONFIG_PACKAGE_libplist-utils is not set +# CONFIG_PACKAGE_libsysrepo is not set +# CONFIG_PACKAGE_libusbmuxd-utils is not set +# CONFIG_PACKAGE_lm-sensors is not set +# CONFIG_PACKAGE_lm-sensors-detect is not set +# CONFIG_PACKAGE_logger is not set +# CONFIG_PACKAGE_logrotate is not set +# CONFIG_PACKAGE_look is not set +# CONFIG_PACKAGE_losetup is not set +# CONFIG_PACKAGE_lrzsz is not set +# CONFIG_PACKAGE_lsof is not set +# CONFIG_PACKAGE_lxc is not set +# CONFIG_PACKAGE_maccalc is not set +# CONFIG_PACKAGE_macchanger is not set +# CONFIG_PACKAGE_mbtools is not set +# CONFIG_PACKAGE_mc is not set +# CONFIG_PACKAGE_mcookie is not set +# CONFIG_PACKAGE_mmc-utils is not set +# CONFIG_PACKAGE_moreutils is not set +# CONFIG_PACKAGE_mount-utils is not set +# CONFIG_PACKAGE_mpack is not set +# CONFIG_PACKAGE_mt-st is not set +# CONFIG_PACKAGE_namei is not set +# CONFIG_PACKAGE_netopeer2-cli is not set +# CONFIG_PACKAGE_netopeer2-keystored is not set +# CONFIG_PACKAGE_netopeer2-server is not set +# CONFIG_PACKAGE_netwhere is not set +# CONFIG_PACKAGE_oath-toolkit is not set +# CONFIG_PACKAGE_open-plc-utils is not set +# CONFIG_PACKAGE_open2300 is not set +# CONFIG_PACKAGE_openldap-utils is not set +# CONFIG_PACKAGE_openobex is not set +# CONFIG_PACKAGE_openobex-apps is not set +# CONFIG_PACKAGE_openocd is not set +# CONFIG_PACKAGE_opensc-utils is not set +# CONFIG_PACKAGE_openssl-util is not set +# CONFIG_PACKAGE_openzwave is not set +# CONFIG_PACKAGE_openzwave-config is not set +# CONFIG_PACKAGE_opus-tools is not set +# CONFIG_PACKAGE_owipcalc is not set +# CONFIG_PACKAGE_pciutils is not set +# CONFIG_PACKAGE_pcsc-tools is not set +# CONFIG_PACKAGE_pcscd is not set +# CONFIG_PACKAGE_pps-tools is not set +# CONFIG_PACKAGE_prlimit is not set +# CONFIG_PACKAGE_procps-ng is not set +# CONFIG_PACKAGE_progress is not set +# CONFIG_PACKAGE_prometheus-node-exporter-lua is not set +# CONFIG_PACKAGE_pv is not set +# CONFIG_PACKAGE_qrencode is not set +# CONFIG_PACKAGE_relayctl is not set +# CONFIG_PACKAGE_rename is not set +# CONFIG_PACKAGE_rng-tools is not set +# CONFIG_PACKAGE_rtl-ais is not set +# CONFIG_PACKAGE_rtl-sdr is not set +# CONFIG_PACKAGE_sane-backends is not set +# CONFIG_PACKAGE_sane-daemon is not set +# CONFIG_PACKAGE_sane-frontends is not set +# CONFIG_PACKAGE_shadow-utils is not set +CONFIG_PACKAGE_shellsync=y +# CONFIG_PACKAGE_sispmctl is not set +# CONFIG_PACKAGE_slide-switch is not set +# CONFIG_PACKAGE_smartd is not set +# CONFIG_PACKAGE_smartmontools is not set +# CONFIG_PACKAGE_smstools3 is not set +# CONFIG_PACKAGE_sockread is not set +# CONFIG_PACKAGE_spi-tools is not set +# CONFIG_PACKAGE_spidev-test is not set +# CONFIG_PACKAGE_strace is not set +# CONFIG_PACKAGE_strace_libunwind is not set +# CONFIG_PACKAGE_stress is not set +# CONFIG_PACKAGE_sumo is not set +# CONFIG_PACKAGE_sysrepo is not set +# CONFIG_PACKAGE_sysrepocfg is not set +# CONFIG_PACKAGE_sysrepoctl is not set +# CONFIG_PACKAGE_sysstat is not set +# CONFIG_PACKAGE_tar is not set +# CONFIG_PACKAGE_taskwarrior is not set +# CONFIG_PACKAGE_tracertools is not set +# CONFIG_PACKAGE_tree is not set +# CONFIG_PACKAGE_triggerhappy is not set +# CONFIG_PACKAGE_udns-dnsget is not set +# CONFIG_PACKAGE_udns-ex-rdns is not set +# CONFIG_PACKAGE_udns-rblcheck is not set +# CONFIG_PACKAGE_ugps is not set +# CONFIG_PACKAGE_usb-modeswitch is not set +# CONFIG_PACKAGE_usbmuxd is not set +# CONFIG_PACKAGE_usbreset is not set +# CONFIG_PACKAGE_usbutils is not set +# CONFIG_PACKAGE_uuidd is not set +# CONFIG_PACKAGE_uuidgen is not set +# CONFIG_PACKAGE_uvcdynctrl is not set +# CONFIG_PACKAGE_v4l-utils is not set +# CONFIG_PACKAGE_view1090 is not set +# CONFIG_PACKAGE_watchcat is not set +# CONFIG_PACKAGE_whereis is not set +# CONFIG_PACKAGE_wifitoggle is not set +# CONFIG_PACKAGE_xsltproc is not set +# CONFIG_PACKAGE_xxd is not set +# CONFIG_PACKAGE_yanglint is not set +# CONFIG_PACKAGE_yara is not set +# CONFIG_PACKAGE_yunbridge is not set + +# +# Xorg +# + +# +# font-utils +# +# CONFIG_PACKAGE_fontconfig is not set diff --git a/config/Config-build.in b/config/Config-build.in index f9987fcd2..dbfd09959 100644 --- a/config/Config-build.in +++ b/config/Config-build.in @@ -184,6 +184,22 @@ menu "Global build settings" this per package by adding PKG_CHECK_FORMAT_SECURITY:=0 in the package Makefile. + config PKG_ASLR_PIE + bool + prompt "User space ASLR PIE compilation" + select BUSYBOX_DEFAULT_PIE + default n + help + Add -fPIC to CFLAGS and -specs=hardened-build-ld to LDFLAGS. + This enables package build as Position Independent Executables (PIE) + to protect against "return-to-text" attacks. This belongs to the + feature of Address Space Layout Randomisation (ASLR), which is + implemented by the kernel and the ELF loader by randomising the + location of memory allocations. This makes memory addresses harder + to predict when an attacker is attempting a memory-corruption exploit. + You can disable this per package by adding PKG_ASLR_PIE:=0 in the package + Makefile. + choice prompt "User space Stack-Smashing Protection" depends on USE_MUSL @@ -194,11 +210,11 @@ menu "Global build settings" bool "None" config PKG_CC_STACKPROTECTOR_REGULAR bool "Regular" - select SSP_SUPPORT if !USE_MUSL + select GCC_LIBSSP if !USE_MUSL depends on KERNEL_CC_STACKPROTECTOR_REGULAR config PKG_CC_STACKPROTECTOR_STRONG bool "Strong" - select SSP_SUPPORT if !USE_MUSL + select GCC_LIBSSP if !USE_MUSL depends on !GCC_VERSION_4_8 depends on KERNEL_CC_STACKPROTECTOR_STRONG endchoice diff --git a/config/Config-images.in b/config/Config-images.in index b25761dce..23e85433f 100644 --- a/config/Config-images.in +++ b/config/Config-images.in @@ -18,6 +18,7 @@ menu "Target Images" default TARGET_INITRAMFS_COMPRESSION_LZMA if TARGET_ramips default TARGET_INITRAMFS_COMPRESSION_LZMA if TARGET_apm821xx default TARGET_INITRAMFS_COMPRESSION_LZMA if TARGET_mpc85xx + default TARGET_INITRAMFS_COMPRESSION_LZMA if TARGET_ipq40xx default TARGET_INITRAMFS_COMPRESSION_NONE depends on TARGET_ROOTFS_INITRAMFS help @@ -62,7 +63,7 @@ menu "Target Images" config TARGET_ROOTFS_TARGZ bool "tar.gz" - default y if USES_TARGZ + default n help Build a compressed tar archive of the root filesystem. @@ -70,7 +71,7 @@ menu "Target Images" menuconfig TARGET_ROOTFS_EXT4FS bool "ext4" - default y if USES_EXT4 + default n help Build an ext4 root filesystem. @@ -115,7 +116,7 @@ menu "Target Images" config TARGET_ROOTFS_ISO bool "iso" default n - depends on TARGET_x86_generic + depends on TARGET_x86 help Create a bootable ISO image. @@ -185,22 +186,30 @@ menu "Target Images" depends on TARGET_ROOTFS_EXT4FS || TARGET_ROOTFS_ISO || TARGET_ROOTFS_JFFS2 || TARGET_ROOTFS_SQUASHFS select PACKAGE_grub2 default y + + config EFI_IMAGES + bool "Build EFI GRUB images (Linux x86 or x86_64 host only)" + depends on TARGET_x86 + depends on TARGET_ROOTFS_EXT4FS || TARGET_ROOTFS_ISO || TARGET_ROOTFS_JFFS2 || TARGET_ROOTFS_SQUASHFS + select PACKAGE_grub2 + select PACKAGE_grub2-efi + default n config GRUB_CONSOLE bool "Use Console Terminal (in addition to Serial)" - depends on GRUB_IMAGES + depends on GRUB_IMAGES || EFI_IMAGES default n if (TARGET_x86_generic_Soekris45xx || TARGET_x86_generic_Soekris48xx || TARGET_x86_net5501 || TARGET_x86_geos || TARGET_x86_alix2) default y config GRUB_SERIAL string "Serial port device" - depends on GRUB_IMAGES + depends on GRUB_IMAGES || EFI_IMAGES default "hvc0" if TARGET_x86_xen_domu default "ttyS0" if ! TARGET_x86_xen_domu config GRUB_BAUDRATE int "Serial port baud rate" - depends on GRUB_IMAGES + depends on GRUB_IMAGES || EFI_IMAGES default 38400 if TARGET_x86_generic default 115200 @@ -211,14 +220,14 @@ menu "Target Images" config GRUB_BOOTOPTS string "Extra kernel boot options" - depends on GRUB_IMAGES + depends on GRUB_IMAGES || EFI_IMAGES default "xencons=hvc" if TARGET_x86_xen_domu help If you don't know, just leave it blank. config GRUB_TIMEOUT string "Seconds to wait before booting the default entry" - depends on GRUB_IMAGES + depends on GRUB_IMAGES || EFI_IMAGES default "0" help If you don't know, 5 seconds is a reasonable default. @@ -226,7 +235,7 @@ menu "Target Images" config VDI_IMAGES bool "Build VirtualBox image files (VDI)" depends on TARGET_x86 || TARGET_x86_64 - select GRUB_IMAGES + depends on GRUB_IMAGES || EFI_IMAGES select TARGET_IMAGES_PAD select PACKAGE_kmod-e1000 @@ -234,13 +243,21 @@ menu "Target Images" bool "Build VMware image files (VMDK)" depends on TARGET_x86 || TARGET_x86_64 default y - select GRUB_IMAGES + depends on GRUB_IMAGES || EFI_IMAGES select TARGET_IMAGES_PAD select PACKAGE_kmod-e1000 + + config VHD_IMAGES + bool "Build Hyper-V image files (VHD)" + depends on TARGET_x86 || TARGET_x86_64 + default n + depends on GRUB_IMAGES || EFI_IMAGES + select TARGET_IMAGES_PAD + select PACKAGE_kmod-tulip config TARGET_IMAGES_PAD bool "Pad images to filesystem size (for JFFS2)" - depends on GRUB_IMAGES + depends on GRUB_IMAGES || EFI_IMAGES config TARGET_IMAGES_GZIP bool "GZip images" @@ -253,19 +270,19 @@ menu "Target Images" config TARGET_KERNEL_PARTSIZE int "Kernel partition size (in MB)" - depends on GRUB_IMAGES + depends on GRUB_IMAGES || EFI_IMAGES default 16 config TARGET_ROOTFS_PARTSIZE int "Root filesystem partition size (in MB)" - depends on GRUB_IMAGES || TARGET_ROOTFS_EXT4FS || TARGET_rb532 || TARGET_mvebu || TARGET_uml + depends on GRUB_IMAGES || EFI_IMAGES || TARGET_ROOTFS_EXT4FS || TARGET_rb532 || TARGET_mvebu || TARGET_uml default 90 help Select the root filesystem partition size. config TARGET_ROOTFS_PARTNAME string "Root partition on target device" - depends on GRUB_IMAGES + depends on GRUB_IMAGES || EFI_IMAGES help Override the root partition on the final device. If left empty, it will be mounted by PARTUUID which makes the kernel find the diff --git a/feeds.conf.default b/feeds.conf.default index da6c66562..0954f2f0b 100644 --- a/feeds.conf.default +++ b/feeds.conf.default @@ -1,7 +1,7 @@ src-git packages https://git.openwrt.org/feed/packages.git src-git luci https://git.openwrt.org/project/luci.git src-git routing https://git.openwrt.org/feed/routing.git -src-git telephony https://git.openwrt.org/feed/telephony.git +#src-git telephony https://git.openwrt.org/feed/telephony.git #src-git video https://github.com/openwrt/video.git #src-git targets https://github.com/openwrt/targets.git #src-git management https://github.com/openwrt-management/packages.git diff --git a/include/kernel-version.mk b/include/kernel-version.mk index 87d3ff172..691f33fa7 100644 --- a/include/kernel-version.mk +++ b/include/kernel-version.mk @@ -3,14 +3,14 @@ LINUX_RELEASE?=1 LINUX_VERSION-3.18 = .71 -LINUX_VERSION-4.4 = .111 -LINUX_VERSION-4.9 = .76 -LINUX_VERSION-4.14 = .13 +LINUX_VERSION-4.4 = .112 +LINUX_VERSION-4.9 = .77 +LINUX_VERSION-4.14 = .32 LINUX_KERNEL_HASH-3.18.71 = 5abc9778ad44ce02ed6c8ab52ece8a21c6d20d21f6ed8a19287b4a38a50c1240 -LINUX_KERNEL_HASH-4.4.111 = a201282e8eaf62b4f51edb2241e98ff805fe2d1b04a72a2328c5a6e2d77ec008 -LINUX_KERNEL_HASH-4.9.76 = b82b94332cffaaeade74495264c989dafb96d4748503f87a5b7c436f5de887de -LINUX_KERNEL_HASH-4.14.13 = 4ab46d1b5a0f8ef83b80760f89ae4f5c88431b19b3cf79ffa0c66d6b33e45772 +LINUX_KERNEL_HASH-4.4.112 = 544b42cbeed022896115c76a18fc97b4507d5b41d7ac0ce1dce9afd6ffd11ecd +LINUX_KERNEL_HASH-4.9.77 = 7c29bc3fb96f1e23d98f664e786dddd53a1599f56431b9b7fdfba402a4b3705c +LINUX_KERNEL_HASH-4.14.32 = cb0979bec663089a43b10cfbeae0cf9673544b0ff5968c33ede614ec0f43b680 ifdef KERNEL_PATCHVER LINUX_VERSION:=$(KERNEL_PATCHVER)$(strip $(LINUX_VERSION-$(KERNEL_PATCHVER))) diff --git a/include/netfilter.mk b/include/netfilter.mk index 616425cb0..c4e43a84a 100644 --- a/include/netfilter.mk +++ b/include/netfilter.mk @@ -30,9 +30,10 @@ endef # core # kernel only +$(eval $(if $(NF_KMOD),$(call nf_add,NF_REJECT,CONFIG_NF_REJECT_IPV4, $(P_V4)nf_reject_ipv4),)) + $(eval $(if $(NF_KMOD),$(call nf_add,NF_IPT,CONFIG_IP_NF_IPTABLES, $(P_V4)ip_tables),)) $(eval $(if $(NF_KMOD),$(call nf_add,NF_IPT,CONFIG_NETFILTER_XTABLES, $(P_XT)x_tables),)) -$(eval $(if $(NF_KMOD),$(call nf_add,NF_IPT,CONFIG_NF_REJECT_IPV4, $(P_V4)nf_reject_ipv4),)) $(eval $(if $(NF_KMOD),$(call nf_add,IPT_CORE,CONFIG_NETFILTER_XTABLES, $(P_XT)xt_tcpudp),)) $(eval $(if $(NF_KMOD),$(call nf_add,IPT_CORE,CONFIG_IP_NF_FILTER, $(P_V4)iptable_filter),)) @@ -85,6 +86,10 @@ $(eval $(call nf_add,IPT_CONNTRACK_EXTRA,CONFIG_NETFILTER_XT_MATCH_RECENT, $(P_X $(eval $(if $(NF_KMOD),,$(call nf_add,IPT_CONNTRACK_EXTRA,CONFIG_NETFILTER_XT_CONNMARK, $(P_XT)xt_CONNMARK))) +#conntrack-label + +$(eval $(call nf_add,IPT_CONNTRACK_LABEL,CONFIG_NETFILTER_XT_MATCH_CONNLABEL, $(P_XT)xt_connlabel)) + # extra $(eval $(call nf_add,IPT_EXTRA,CONFIG_NETFILTER_XT_MATCH_ADDRTYPE, $(if $(NF_KMOD),$(P_XT)xt_addrtype,$(P_XT)ipt_addrtype))) @@ -138,12 +143,15 @@ $(eval $(call nf_add,IPT_IPSEC,CONFIG_IP_NF_MATCH_AH, $(P_V4)ipt_ah)) $(eval $(call nf_add,IPT_IPSEC,CONFIG_NETFILTER_XT_MATCH_ESP, $(P_XT)xt_esp)) $(eval $(call nf_add,IPT_IPSEC,CONFIG_NETFILTER_XT_MATCH_POLICY, $(P_XT)xt_policy)) +# flow offload support +$(eval $(call nf_add,IPT_FLOW,CONFIG_NETFILTER_XT_TARGET_FLOWOFFLOAD, $(P_XT)xt_FLOWOFFLOAD)) # IPv6 # kernel only +$(eval $(if $(NF_KMOD),$(call nf_add,NF_REJECT6,CONFIG_NF_REJECT_IPV6, $(P_V6)nf_reject_ipv6),)) + $(eval $(if $(NF_KMOD),$(call nf_add,NF_IPT6,CONFIG_IP6_NF_IPTABLES, $(P_V6)ip6_tables),)) -$(eval $(if $(NF_KMOD),$(call nf_add,NF_IPT6,CONFIG_NF_REJECT_IPV6, $(P_V6)nf_reject_ipv6),)) $(eval $(if $(NF_KMOD),$(call nf_add,NF_CONNTRACK6,CONFIG_NF_DEFRAG_IPV6, $(P_V6)nf_defrag_ipv6),)) $(eval $(if $(NF_KMOD),$(call nf_add,NF_CONNTRACK6,CONFIG_NF_CONNTRACK_IPV6, $(P_V6)nf_conntrack_ipv6),)) @@ -338,14 +346,22 @@ $(eval $(if $(NF_KMOD),$(call nf_add,NFT_CORE,CONFIG_NFT_CHAIN_ROUTE_IPV6, $(P_V $(eval $(if $(NF_KMOD),$(call nf_add,NFT_CORE,CONFIG_NFT_REDIR, $(P_XT)nft_redir, ge 3.19.0),)) $(eval $(if $(NF_KMOD),$(call nf_add,NFT_CORE,CONFIG_NFT_QUOTA, $(P_XT)nft_quota, ge 4.9.0),)) +$(eval $(if $(NF_KMOD),$(call nf_add,NFT_ARP,CONFIG_NF_TABLES_ARP, $(P_V4)nf_tables_arp),)) + +$(eval $(if $(NF_KMOD),$(call nf_add,NFT_BRIDGE,CONFIG_NF_TABLES_BRIDGE, $(P_EBT)nf_tables_bridge),)) +$(eval $(if $(NF_KMOD),$(call nf_add,NFT_BRIDGE,CONFIG_NFT_BRIDGE_META, $(P_EBT)nft_meta_bridge),)) +$(eval $(if $(NF_KMOD),$(call nf_add,NFT_BRIDGE,CONFIG_NFT_BRIDGE_REJECT, $(P_EBT)nft_reject_bridge),)) + $(eval $(if $(NF_KMOD),$(call nf_add,NFT_NAT,CONFIG_NFT_NAT, $(P_XT)nft_nat),)) $(eval $(if $(NF_KMOD),$(call nf_add,NFT_NAT,CONFIG_NFT_CHAIN_NAT_IPV4, $(P_V4)nft_chain_nat_ipv4),)) $(eval $(if $(NF_KMOD),$(call nf_add,NFT_NAT,CONFIG_NFT_REDIR_IPV4, $(P_V4)nft_redir_ipv4, ge 3.19.0),)) -$(eval $(if $(NF_KMOD),$(call nf_add,NFT_NAT6,CONFIG_NFT_REDIR_IPV6, $(P_V6)nft_redir_ipv6, ge 3.19.0),)) -$(eval $(if $(NF_KMOD),$(call nf_add,NFT_NAT6,CONFIG_NFT_CHAIN_NAT_IPV6, $(P_V6)nft_chain_nat_ipv6),)) $(eval $(if $(NF_KMOD),$(call nf_add,NFT_NAT,CONFIG_NFT_MASQ, $(P_XT)nft_masq),)) $(eval $(if $(NF_KMOD),$(call nf_add,NFT_NAT,CONFIG_NFT_MASQ_IPV4, $(P_V4)nft_masq_ipv4),)) -$(eval $(if $(NF_KMOD),$(call nf_add,NFT_NAT,CONFIG_NFT_MASQ_IPV6, $(P_V6)nft_masq_ipv6),)) + +$(eval $(if $(NF_KMOD),$(call nf_add,NFT_NAT6,CONFIG_NFT_REDIR_IPV6, $(P_V6)nft_redir_ipv6, ge 3.19.0),)) +$(eval $(if $(NF_KMOD),$(call nf_add,NFT_NAT6,CONFIG_NFT_CHAIN_NAT_IPV6, $(P_V6)nft_chain_nat_ipv6),)) +$(eval $(if $(NF_KMOD),$(call nf_add,NFT_NAT6,CONFIG_NFT_MASQ_IPV6, $(P_V6)nft_masq_ipv6),)) + # userland only IPT_BUILTIN += $(NF_IPT-y) $(NF_IPT-m) @@ -356,6 +372,7 @@ IPT_BUILTIN += $(IPT_CONNTRACK-y) IPT_BUILTIN += $(IPT_CONNTRACK_EXTRA-y) IPT_BUILTIN += $(IPT_EXTRA-y) IPT_BUILTIN += $(IPT_FILTER-y) +IPT_BUILTIN += $(IPT_FLOW-y) $(IPT_FLOW-m) IPT_BUILTIN += $(IPT_IPOPT-y) IPT_BUILTIN += $(IPT_IPRANGE-y) IPT_BUILTIN += $(IPT_CLUSTER-y) diff --git a/include/package-defaults.mk b/include/package-defaults.mk index 0bca076e7..6bbfdcc3c 100644 --- a/include/package-defaults.mk +++ b/include/package-defaults.mk @@ -5,7 +5,7 @@ # See /LICENSE for more information. # -PKG_DEFAULT_DEPENDS = +libc +SSP_SUPPORT:libssp +USE_GLIBC:librt +USE_GLIBC:libpthread +PKG_DEFAULT_DEPENDS = +libc +GCC_LIBSSP:libssp +USE_GLIBC:librt +USE_GLIBC:libpthread ifneq ($(PKG_NAME),toolchain) PKG_FIXUP_DEPENDS = $(if $(filter kmod-%,$(1)),$(2),$(PKG_DEFAULT_DEPENDS) $(filter-out $(PKG_DEFAULT_DEPENDS),$(2))) diff --git a/include/target.mk b/include/target.mk index cefb19b24..810b02fb8 100644 --- a/include/target.mk +++ b/include/target.mk @@ -21,7 +21,7 @@ luci-app-pptp-server luci-app-ipsec-vpnd luci-app-vlmcsd luci-app-wifischedule l # For nas targets DEFAULT_PACKAGES.nas:=block-mount fdisk lsblk mdadm # For router targets -DEFAULT_PACKAGES.router:=dnsmasq-full iptables ip6tables ppp ppp-mod-pppoe firewall +DEFAULT_PACKAGES.router:=dnsmasq-full iptables ip6tables ppp ppp-mod-pppoe firewall kmod-ipt-offload DEFAULT_PACKAGES.bootloader:= ifneq ($(DUMP),) @@ -55,6 +55,10 @@ else endif endif +ifneq ($(filter 3.18 4.4 4.9,$(KERNEL_PATCHVER)),) + DEFAULT_PACKAGES.router:=$(filter-out kmod-ipt-offload,$(DEFAULT_PACKAGES.router)) +endif + # Add device specific packages (here below to allow device type set from subtarget) DEFAULT_PACKAGES += $(DEFAULT_PACKAGES.$(DEVICE_TYPE)) diff --git a/package/base-files/files/lib/upgrade/common.sh b/package/base-files/files/lib/upgrade/common.sh index 71cffc858..1c755cf61 100644 --- a/package/base-files/files/lib/upgrade/common.sh +++ b/package/base-files/files/lib/upgrade/common.sh @@ -117,6 +117,24 @@ export_bootdevice() { esac case "$disk" in + PARTUUID=[A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9]-[A-F0-9][A-F0-9][A-F0-9][A-F0-9]-[A-F0-9][A-F0-9][A-F0-9][A-F0-9]-[A-F0-9][A-F0-9][A-F0-9][A-F0-9]-[A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9]0002) + uuid="${disk#PARTUUID=}" + uuid="${uuid%0002}0002" + for disk in $(find /dev -type b); do + set -- $(dd if=$disk bs=1 skip=$((2*51225612816)) count=16 2>/dev/null | hexdump -v -e '4/1 "%02x"' | awk '{ \ + for(i=1;i<9;i=i2) first=substr($0,i,1) substr($0,i1,1) first; \ + for(i=9;i<13;i=i2) second=substr($0,i,1) substr($0,i1,1) second; \ + for(i=13;i<16;i=i2) third=substr($0,i,1) substr($0,i1,1) third; \ + fourth = substr($0,17,4); \ + five = substr($0,21,12); \ + } END { print toupper(first"-"second"-"third"-"fourth"-"five) }') + if [ "$1" = "$uuid" ]; then + uevent="/sys/class/block/${disk##*/}/uevent" + export SAVE_PARTITIONS=0 + break + fi + done +;; PARTUUID=[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]-02) uuid="${disk#PARTUUID=}" uuid="${uuid%-02}" diff --git a/package/boot/grub2/Makefile b/package/boot/grub2/common.mk similarity index 57% rename from package/boot/grub2/Makefile rename to package/boot/grub2/common.mk index 8cfc0dcff..0f528f0b6 100644 --- a/package/boot/grub2/Makefile +++ b/package/boot/grub2/common.mk @@ -1,34 +1,24 @@ -# -# Copyright (C) 2006-2015 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=grub -PKG_CPE_ID:=cpe:/a:gnu:grub2 PKG_VERSION:=2.02 PKG_RELEASE:=1 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE:=grub-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@GNU/grub PKG_HASH:=810b3798d316394f94096ec2797909dbf23c858e48f7b3830826b8daa06b7b0f PKG_FIXUP:=autoreconf HOST_BUILD_PARALLEL:=1 -PKG_BUILD_DEPENDS:=grub2/host PKG_SSP:=0 PKG_FLAGS:=nonshared +PATCH_DIR := ../patches +HOST_PATCH_DIR := ../patches + include $(INCLUDE_DIR)/host-build.mk include $(INCLUDE_DIR)/package.mk -define Package/grub2 +define Package/grub2/Default CATEGORY:=Boot Loaders SECTION:=boot TITLE:=GRand Unified Bootloader @@ -36,19 +26,6 @@ define Package/grub2 DEPENDS:=@TARGET_x86||TARGET_x86_64 endef -define Package/grub2-editenv - CATEGORY:=Utilities - SECTION:=utils - SUBMENU:=Boot Loaders - TITLE:=Grub2 Environment editor - URL:=http://www.gnu.org/software/grub/ - DEPENDS:=@TARGET_x86||TARGET_x86_64 -endef - -define Package/grub2-editenv/description - Edit grub2 environment files. -endef - HOST_BUILD_PREFIX := $(STAGING_DIR_HOST) CONFIGURE_VARS += \ @@ -82,11 +59,3 @@ define Host/Configure $(Host/Configure/Default) endef -define Package/grub2-editenv/install - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/grub-editenv $(1)/usr/sbin/ -endef - -$(eval $(call HostBuild)) -$(eval $(call BuildPackage,grub2)) -$(eval $(call BuildPackage,grub2-editenv)) diff --git a/package/boot/grub2/grub2-efi/Makefile b/package/boot/grub2/grub2-efi/Makefile new file mode 100644 index 000000000..37e0b353e --- /dev/null +++ b/package/boot/grub2/grub2-efi/Makefile @@ -0,0 +1,22 @@ +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=grub-efi + +include ../common.mk + +TAR_OPTIONS:= --transform 's/grub-${PKG_VERSION}/${PKG_NAME}-${PKG_VERSION}/' $(TAR_OPTIONS) + +PKG_BUILD_DEPENDS:=grub2-efi/host + +CONFIGURE_ARGS += --with-platform=efi +HOST_CONFIGURE_ARGS += --with-platform=efi --program-suffix=-efi + +define Package/grub2-efi +$(call Package/grub2/Default) +HIDDEN:=1 +TITLE += (with EFI support) +endef + +$(eval $(call HostBuild)) +$(eval $(call BuildPackage,grub2-efi)) diff --git a/package/boot/grub2/grub2/Makefile b/package/boot/grub2/grub2/Makefile new file mode 100644 index 000000000..c00797662 --- /dev/null +++ b/package/boot/grub2/grub2/Makefile @@ -0,0 +1,33 @@ +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=grub + +include ../common.mk + +PKG_BUILD_DEPENDS:=grub2/host + +define Package/grub2 +$(call Package/grub2/Default) +endef + +define Package/grub2-editenv + CATEGORY:=Utilities + SECTION:=utils + TITLE:=Grub2 Environment editor + URL:=http://www.gnu.org/software/grub/ + DEPENDS:=@TARGET_x86||TARGET_x86_64 +endef + +define Package/grub2-editenv/description + Edit grub2 environment files. +endef + +define Package/grub2-editenv/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/grub-editenv $(1)/usr/sbin/ +endef + +$(eval $(call HostBuild)) +$(eval $(call BuildPackage,grub2)) +$(eval $(call BuildPackage,grub2-editenv)) diff --git a/package/ext/luci-app-shadowsocksr b/package/ext/luci-app-shadowsocksr new file mode 160000 index 000000000..86ef75ed8 --- /dev/null +++ b/package/ext/luci-app-shadowsocksr @@ -0,0 +1 @@ +Subproject commit 86ef75ed8a376ca0a7490ce68c5b09fa0fbe8c1d diff --git a/package/firmware/amd64-microcode/Makefile b/package/firmware/amd64-microcode/Makefile new file mode 100644 index 000000000..e88b02950 --- /dev/null +++ b/package/firmware/amd64-microcode/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (C) 2018 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=amd64-microcode +PKG_VERSION:=20171205 +PKG_RELEASE:=1 + +PKG_SOURCE:=amd64-microcode_3.$(PKG_VERSION).$(PKG_RELEASE).tar.xz +PKG_SOURCE_URL:=http://ftp.debian.org/debian/pool/non-free/a/amd64-microcode/ +PKG_HASH:=a38bc072f535a3d3c1bf4e9e545197aa5114e979e94ef7e4a67e615df2f853a7 +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-3.$(PKG_VERSION).$(PKG_RELEASE) + +PKG_LICENSE_FILE:=LICENSE.amd-ucode + +include $(INCLUDE_DIR)/package.mk + +define Package/amd64-microcode + SECTION:=firmware + CATEGORY:=Firmware + URL:=$(PKG_SOURCE_URL) + DEPENDS:=@TARGET_x86 + TITLE:=AMD64 CPU microcode +endef + +define Build/Prepare + rm -rf $(PKG_BUILD_DIR) + mkdir -p $(PKG_BUILD_DIR) + $(TAR) -C $(BUILD_DIR) -xJf $(DL_DIR)/$(PKG_SOURCE) +endef + +define Build/Compile +endef + +define Package/amd64-microcode/install + $(INSTALL_DIR) $(1)/lib/firmware/amd-ucode + $(INSTALL_DATA) $(PKG_BUILD_DIR)/*.bin $(1)/lib/firmware/amd-ucode +endef + +$(eval $(call BuildPackage,amd64-microcode)) diff --git a/package/firmware/ath10k-firmware/Makefile b/package/firmware/ath10k-firmware/Makefile index 1c6f4dfb7..a8c3e7dee 100644 --- a/package/firmware/ath10k-firmware/Makefile +++ b/package/firmware/ath10k-firmware/Makefile @@ -8,9 +8,9 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ath10k-firmware -PKG_SOURCE_DATE:=2017-10-30 -PKG_SOURCE_VERSION:=476a2850b1e8582d51187799d7de209daf1a57b2 -PKG_MIRROR_HASH:=77ba59f75c5897c842c5c525945de019fd23f1e2d8bea6239924857e500bf73a +PKG_SOURCE_DATE:=2018-02-09 +PKG_SOURCE_VERSION:=8f4bafdd400d21a65966004d0ce6e0686ef4d9bc +PKG_MIRROR_HASH:=4f4f0678b9d07c0282f18c69bd63a5e2a2ae015b9ce7298cedb88a60be87ed3a PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git @@ -50,6 +50,7 @@ $(Package/ath10k-firmware-default) endef CT_FIRMWARE_FILE = $(1)-$($(1)_FIRMWARE_FILE_CT) +CT_FIRMWARE_FILE_HTT = $(1)-$($(1)_FIRMWARE_FILE_CT_HTT) define Download/ct-firmware URL:=https://www.candelatech.com/downloads/$(2) @@ -57,41 +58,102 @@ define Download/ct-firmware URL_FILE:=$($(1)_FIRMWARE_FILE_CT) endef -QCA988X_FIRMWARE_FILE_CT:=firmware-2-ct-full-community-19.bin.lede +define Download/ct-firmware-htt + URL:=https://www.candelatech.com/downloads/$(2) + FILE:=$(call CT_FIRMWARE_FILE_HTT,$(1)) + URL_FILE:=$($(1)_FIRMWARE_FILE_CT_HTT) +endef + +QCA988X_FIRMWARE_FILE_CT:=firmware-2-ct-full-community-20.bin.lede.006 define Download/ath10k-firmware-qca988x-ct $(call Download/ct-firmware,QCA988X,) - HASH:=bff98f028062dae9fc638c7596aec3c79bf9eddaff65cfacba067f6d72f217cd + HASH:=b28ff3eb10f15033be68bbedc91abcf40f7369cc44da4273e3c0df285c74a4f8 endef $(eval $(call Download,ath10k-firmware-qca988x-ct)) -QCA9887_FIRMWARE_FILE_CT:=firmware-2-ct-full-community-19.bin.lede +QCA988X_FIRMWARE_FILE_CT_HTT:=firmware-2-ct-full-htt-mgt-community-20.bin.lede.006 +define Download/ath10k-firmware-qca988x-ct-htt + $(call Download/ct-firmware-htt,QCA988X,) + HASH:=08dd8d339079c9a704cf3f91787cc06a73168a9f57eeb777edaa9cd4194c246c +endef +$(eval $(call Download,ath10k-firmware-qca988x-ct-htt)) + + +QCA9887_FIRMWARE_FILE_CT:=firmware-2-ct-full-community-20.bin.lede.006 define Download/ath10k-firmware-qca9887-ct $(call Download/ct-firmware,QCA9887,ath10k-9887) - HASH:=95dc106f98672bd9c7d3fe6881ed79ab079cb49b0a995650991b1beaff2b0101 + HASH:=8d3fd2fb62479efa955e0d0487ca8971409e68b395f3a2df28569ec243bd937d endef $(eval $(call Download,ath10k-firmware-qca9887-ct)) -QCA99X0_FIRMWARE_FILE_CT:=firmware-5-ct-full-community-9.bin-lede.004 +QCA9887_FIRMWARE_FILE_CT_HTT:=firmware-2-ct-full-htt-mgt-community-20.bin.lede.006 +define Download/ath10k-firmware-qca9887-ct-htt + $(call Download/ct-firmware-htt,QCA9887,ath10k-9887) + HASH:=f192b5a8ac4b90d828cace0a2279c02fda689fa936f5154f08df6658d0230e9b +endef +$(eval $(call Download,ath10k-firmware-qca9887-ct-htt)) + + +QCA99X0_FIRMWARE_FILE_CT:=firmware-5-ct-full-community-10.bin-lede.006 define Download/ath10k-firmware-qca99x0-ct $(call Download/ct-firmware,QCA99X0,ath10k-10-4) - HASH:=993c29fd64bb2a59b86d34f58601a1a48b83b541750bc511f78cc17152829b4d + HASH:=1aa21acab7974651af6c0a2698891fc8792edb5124824fac1587123d3b48df67 endef $(eval $(call Download,ath10k-firmware-qca99x0-ct)) -QCA9984_FIRMWARE_FILE_CT:=firmware-5-ct-full-community-9.bin-lede.004 +QCA99X0_FIRMWARE_FILE_CT_HTT:=firmware-5-ct-full-htt-mgt-community-10.bin-lede.006 +define Download/ath10k-firmware-qca99x0-ct-htt + $(call Download/ct-firmware-htt,QCA99X0,ath10k-10-4) + HASH:=e3d89c00f194975649b2f41ff5f5ffc34d60c393d15800df6ea56a8ac29aeeee +endef +$(eval $(call Download,ath10k-firmware-qca99x0-ct-htt)) + + +QCA9984_FIRMWARE_FILE_CT:=firmware-5-ct-full-community-10.bin-lede.006 define Download/ath10k-firmware-qca9984-ct $(call Download/ct-firmware,QCA9984,ath10k-9984-10-4) - HASH:=d997eed9a8bc6809c01d367759ba8545c10e3be93ea1f33d6d753127ef0f7c5e + HASH:=f9700cafb4e2cebe8364eb6fe1754eb2c37b1b02a7408ded908ecc78954380a3 endef $(eval $(call Download,ath10k-firmware-qca9984-ct)) -QCA9888_FIRMWARE_FILE_CT:=firmware-5-ct-full-community-9.bin-lede.004 +QCA9984_FIRMWARE_FILE_CT_HTT:=firmware-5-ct-full-htt-mgt-community-10.bin-lede.006 +define Download/ath10k-firmware-qca9984-ct-htt + $(call Download/ct-firmware-htt,QCA9984,ath10k-9984-10-4) + HASH:=c8c288cd38f3e6b378d7ed8407ee6b01cfcc73acc03d6ad5b8d392a8a346dd82 +endef +$(eval $(call Download,ath10k-firmware-qca9984-ct-htt)) + + +QCA4019_FIRMWARE_FILE_CT:=firmware-5-ct-full-community-10.bin-lede.006 +define Download/ath10k-firmware-qca4019-ct + $(call Download/ct-firmware,QCA4019,ath10k-4019-10-4) + HASH:=d2207982b49959b9526d4dc1fd4181b49b3d43a841cf5d6cc396ccb1bc4b572c +endef +$(eval $(call Download,ath10k-firmware-qca4019-ct)) + +QCA4019_FIRMWARE_FILE_CT_HTT:=firmware-5-ct-full-htt-mgt-community-10.bin-lede.006 +define Download/ath10k-firmware-qca4019-ct-htt + $(call Download/ct-firmware-htt,QCA4019,ath10k-4019-10-4) + HASH:=3c900bb656f093fe6882616d788c6e2e8fc09edbdda06691e16e5f08d79c4955 +endef +$(eval $(call Download,ath10k-firmware-qca4019-ct-htt)) + + +QCA9888_FIRMWARE_FILE_CT:=firmware-5-ct-full-community-10.bin-lede.006 define Download/ath10k-firmware-qca9888-ct $(call Download/ct-firmware,QCA9888,ath10k-9888-10-4) - HASH:=bbaa71bc7dcaa264c5875e86639f174908fed09fbace975e325959d42f3754ff + HASH:=9bd38e80ec52484bae5edc785df09cf9acdad3e28ee5080a8105ba786118193a endef $(eval $(call Download,ath10k-firmware-qca9888-ct)) +QCA9888_FIRMWARE_FILE_CT_HTT:=firmware-5-ct-full-htt-mgt-community-10.bin-lede.006 +define Download/ath10k-firmware-qca9888-ct-htt + $(call Download/ct-firmware-htt,QCA9888,ath10k-9888-10-4) + HASH:=63e695f55400f784ca8123c299e240626a403437b30d197a7e69a4b42d155b8a +endef +$(eval $(call Download,ath10k-firmware-qca9888-ct-htt)) + + define Package/ath10k-firmware-qca99x0 $(Package/ath10k-firmware-default) TITLE:=ath10k firmware for QCA99x0 devices @@ -104,6 +166,15 @@ $(Package/ath10k-firmware-default) TITLE:=ath10k CT 10.1 firmware for QCA988x devices SECTION:=firmware CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca988x +endef +define Package/ath10k-firmware-qca988x-ct-htt +$(Package/ath10k-firmware-default) + TITLE:=ath10k CT 10.1 htt-mgt fw for QCA988x + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca988x + DEPENDS:=+kmod-ath10k-ct endef define Package/ath10k-firmware-qca9887-ct @@ -111,6 +182,15 @@ $(Package/ath10k-firmware-default) TITLE:=ath10k CT 10.1 firmware for QCA9887 devices SECTION:=firmware CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca9887 +endef +define Package/ath10k-firmware-qca9887-ct-htt +$(Package/ath10k-firmware-default) + TITLE:=ath10k CT 10.1 htt-mgt fw for QCA9887 + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca9887 + DEPENDS:=+kmod-ath10k-ct endef define Package/ath10k-firmware-qca988x-ct/description @@ -121,6 +201,14 @@ This firmware will NOT be used unless the standard ath10k-firmware-qca988x is un-selected since the driver will try to load firmware-5.bin before firmware-2.bin endef +define Package/ath10k-firmware-qca988x-ct-htt/description +Alternative ath10k firmware for QCA988X from Candela Technologies. +Uses normal HTT TX data path for management frames, which improves +stability in busy networks and fixes .11r authentication. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.1.php +This firmware selects and requires the ath10k-ct driver. +endef define Package/ath10k-firmware-qca9887-ct/description Alternative ath10k firmware for QCA9887 from Candela Technologies. @@ -129,6 +217,14 @@ http://www.candelatech.com/ath10k-10.1.php This firmware conflicts with the standard 9887 firmware, so select only one. endef +define Package/ath10k-firmware-qca9887-ct-htt/description +Alternative ath10k firmware for QCA9887 from Candela Technologies. +Uses normal HTT TX data path for management frames, which improves +stability in busy networks and fixes .11r authentication. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.1.php +This firmware selects and requires the ath10k-ct driver. +endef define Package/ath10k-firmware-qca99x0-ct/description Alternative ath10k firmware for QCA99x0 from Candela Technologies. @@ -137,6 +233,14 @@ http://www.candelatech.com/ath10k-10.4.php This firmware conflicts with the standard 99x0 firmware, so select only one. endef +define Package/ath10k-firmware-qca99x0-ct-htt/description +Alternative ath10k firmware for QCA99x0 from Candela Technologies. +Uses normal HTT TX data path for management frames, which improves +stability in busy networks and may be required for .11r authentication. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.4.php +This firmware selects and requires the ath10k-ct driver. +endef define Package/ath10k-firmware-qca9984-ct/description Alternative ath10k firmware for QCA9984 from Candela Technologies. @@ -145,6 +249,28 @@ http://www.candelatech.com/ath10k-10.4.php This firmware conflicts with the standard 9984 firmware, so select only one. endef +define Package/ath10k-firmware-qca9984-ct-htt/description +Alternative ath10k firmware for QCA9984 from Candela Technologies. +Uses normal HTT TX data path for management frames, which improves +stability in busy networks and may be required for .11r authentication. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.4.php +This firmware selects and requires the ath10k-ct driver. +endef + +define Package/ath10k-firmware-qca4019-ct/description +Alternative ath10k firmware for IPQ4019 radio from Candela Technologies. +Enables IBSS and other features. Works with standard or ath10k-ct driver. +See: http://www.candelatech.com/ath10k-10.4.php +endef +define Package/ath10k-firmware-qca4019-ct-htt/description +Alternative ath10k firmware for IPQ4019 radio from Candela Technologies. +Uses normal HTT TX data path for management frames, which improves +stability in busy networks and may be required for .11r authentication. +Enables IBSS and other features. +See: http://www.candelatech.com/ath10k-10.4.php +This firmware selects and requires the ath10k-ct driver. +endef define Package/ath10k-firmware-qca9888-ct/description Alternative ath10k firmware for QCA9886 and QCA9888 from Candela Technologies. @@ -153,6 +279,15 @@ http://www.candelatech.com/ath10k-10.4.php This firmware conflicts with the standard 9886 and 9888 firmware, so select only one. endef +define Package/ath10k-firmware-qca9888-ct-htt/description +Alternative ath10k firmware for QCA9886 and QCA9888 from Candela Technologies. +Uses normal HTT TX data path for management frames, which improves +stability in busy networks and may be required for .11r authentication. +Enables IBSS and other features. See: +http://www.candelatech.com/ath10k-10.4.php +This firmware selects and requires the ath10k-ct driver. +endef + define Package/ath10k-firmware-qca99x0/description Standard ath10k firmware for QCA99x0 from QCA @@ -162,24 +297,69 @@ endef define Package/ath10k-firmware-qca99x0-ct $(Package/ath10k-firmware-default) - TITLE:=ath10k CT 10.4.3 firmware for QCA99x0 devices + TITLE:=ath10k CT 10.4 firmware for QCA99x0 devices SECTION:=firmware CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca99x0 +endef +define Package/ath10k-firmware-qca99x0-ct-htt +$(Package/ath10k-firmware-default) + TITLE:=ath10k CT 10.4 htt-mgt fw for QCA99x0 + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca99x0 + DEPENDS:=+kmod-ath10k-ct endef define Package/ath10k-firmware-qca9984-ct $(Package/ath10k-firmware-default) - TITLE:=ath10k CT 10.4.3 firmware for QCA9984 devices + TITLE:=ath10k CT 10.4 firmware for QCA9984 devices SECTION:=firmware CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca9984 +endef +define Package/ath10k-firmware-qca9984-ct-htt +$(Package/ath10k-firmware-default) + TITLE:=ath10k CT 10.4 htt-mgt fw for QCA9984 + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca9984 + DEPENDS:=+kmod-ath10k-ct +endef + +define Package/ath10k-firmware-qca4019-ct +$(Package/ath10k-firmware-default) + TITLE:=ath10k CT 10.4 firmware for QCA4018/9 + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca4019 +endef +define Package/ath10k-firmware-qca4019-ct-htt +$(Package/ath10k-firmware-default) + TITLE:=ath10k CT 10.4 htt-mgt for QCA4018/9 + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca4019 + DEPENDS:=+kmod-ath10k-ct endef define Package/ath10k-firmware-qca9888-ct $(Package/ath10k-firmware-default) - TITLE:=ath10k CT 10.4.3 firmware for QCA9886 and QCA9888 devices + TITLE:=ath10k CT 10.4 fw for QCA9886/8 devices SECTION:=firmware CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca9888 endef +define Package/ath10k-firmware-qca9888-ct-htt +$(Package/ath10k-firmware-default) + TITLE:=ath10k CT 10.4 htt-mgt fw for QCA9886/8 + SECTION:=firmware + CATEGORY:=Firmware + PROVIDES:=ath10k-firmware-qca9888 + DEPENDS:=+kmod-ath10k-ct +endef + + define Package/ath10k-firmware-qca9984 $(Package/ath10k-firmware-default) @@ -223,14 +403,14 @@ define Package/ath10k-firmware-qca4019/install $(PKG_BUILD_DIR)/QCA4019/hw1.0/board-2.bin \ $(1)/lib/firmware/ath10k/QCA4019/hw1.0/ $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/QCA4019/hw1.0/3.2.1/firmware-5.bin_10.4-3.2.1-00058 \ + $(PKG_BUILD_DIR)/QCA4019/hw1.0/3.4/firmware-5.bin_10.4-3.4-00104 \ $(1)/lib/firmware/ath10k/QCA4019/hw1.0/firmware-5.bin endef define Package/ath10k-firmware-qca9887/install $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9887/hw1.0 $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/QCA9887/hw1.0/10.2.4-1.0/firmware-5.bin_10.2.4-1.0-00029 \ + $(PKG_BUILD_DIR)/QCA9887/hw1.0/10.2.4-1.0/firmware-5.bin_10.2.4-1.0-00033 \ $(1)/lib/firmware/ath10k/QCA9887/hw1.0/firmware-5.bin $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/QCA9887/hw1.0/board.bin \ @@ -243,7 +423,7 @@ define Package/ath10k-firmware-qca9888/install $(PKG_BUILD_DIR)/QCA9888/hw2.0/board-2.bin \ $(1)/lib/firmware/ath10k/QCA9888/hw2.0/board-2.bin $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/QCA9888/hw2.0/firmware-5.bin_10.4-3.2-00072 \ + $(PKG_BUILD_DIR)/QCA9888/hw2.0/3.5.3/firmware-5.bin_10.4-3.5.3-00053 \ $(1)/lib/firmware/ath10k/QCA9888/hw2.0/firmware-5.bin endef @@ -253,30 +433,10 @@ define Package/ath10k-firmware-qca988x/install $(PKG_BUILD_DIR)/QCA988X/hw2.0/board.bin \ $(1)/lib/firmware/ath10k/QCA988X/hw2.0/ $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/QCA988X/hw2.0/10.2.4-1.0/firmware-5.bin_10.2.4-1.0-00029 \ + $(PKG_BUILD_DIR)/QCA988X/hw2.0/10.2.4-1.0/firmware-5.bin_10.2.4-1.0-00033 \ $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-5.bin endef -define Package/ath10k-firmware-qca9887-ct/install - $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9887/hw1.0 - $(INSTALL_DATA) \ - $(DL_DIR)/$(call CT_FIRMWARE_FILE,QCA9887) \ - $(1)/lib/firmware/ath10k/QCA9887/hw1.0/firmware-2.bin - $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/QCA9887/hw1.0/board.bin \ - $(1)/lib/firmware/ath10k/QCA9887/hw1.0/board.bin -endef - -define Package/ath10k-firmware-qca988x-ct/install - $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA988X/hw2.0 - $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/QCA988X/hw2.0/board.bin \ - $(1)/lib/firmware/ath10k/QCA988X/hw2.0/ - $(INSTALL_DATA) \ - $(DL_DIR)/$(call CT_FIRMWARE_FILE,QCA988X) \ - $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin -endef - define Package/ath10k-firmware-qca6174/install $(INSTALL_DIR) $(1)/lib/firmware/ath10k $(CP) $(PKG_BUILD_DIR)/QCA6174 $(1)/lib/firmware/ath10k/ @@ -295,6 +455,57 @@ define Package/ath10k-firmware-qca99x0/install $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/firmware-5.bin endef +define Package/ath10k-firmware-qca9984/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9984/hw1.0 + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA9984/hw1.0/board-2.bin \ + $(1)/lib/firmware/ath10k/QCA9984/hw1.0/board-2.bin + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA9984/hw1.0/3.5.3/firmware-5.bin_10.4-3.5.3-00053 \ + $(1)/lib/firmware/ath10k/QCA9984/hw1.0/firmware-5.bin +endef + + +# CT related firmware + +define Package/ath10k-firmware-qca9887-ct/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9887/hw1.0 + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE,QCA9887) \ + $(1)/lib/firmware/ath10k/QCA9887/hw1.0/firmware-2.bin + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA9887/hw1.0/board.bin \ + $(1)/lib/firmware/ath10k/QCA9887/hw1.0/board.bin +endef +define Package/ath10k-firmware-qca9887-ct-htt/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9887/hw1.0 + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE_HTT,QCA9887) \ + $(1)/lib/firmware/ath10k/QCA9887/hw1.0/ct-firmware-2.bin + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA9887/hw1.0/board.bin \ + $(1)/lib/firmware/ath10k/QCA9887/hw1.0/board.bin +endef + +define Package/ath10k-firmware-qca988x-ct/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA988X/hw2.0 + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA988X/hw2.0/board.bin \ + $(1)/lib/firmware/ath10k/QCA988X/hw2.0/ + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE,QCA988X) \ + $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin +endef +define Package/ath10k-firmware-qca988x-ct-htt/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA988X/hw2.0 + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA988X/hw2.0/board.bin \ + $(1)/lib/firmware/ath10k/QCA988X/hw2.0/ + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE_HTT,QCA988X) \ + $(1)/lib/firmware/ath10k/QCA988X/hw2.0/ct-firmware-2.bin +endef + define Package/ath10k-firmware-qca99x0-ct/install $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA99X0/hw2.0 $(INSTALL_DATA) \ @@ -307,15 +518,17 @@ define Package/ath10k-firmware-qca99x0-ct/install $(DL_DIR)/$(call CT_FIRMWARE_FILE,QCA99X0) \ $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/firmware-5.bin endef - -define Package/ath10k-firmware-qca9984/install - $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9984/hw1.0 +define Package/ath10k-firmware-qca99x0-ct-htt/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA99X0/hw2.0 $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/QCA9984/hw1.0/board-2.bin \ - $(1)/lib/firmware/ath10k/QCA9984/hw1.0/board-2.bin + $(DL_DIR)/$(QCA99X0_BOARD_FILE) \ + $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/board-2.bin $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/QCA9984/hw1.0/3.4/firmware-5.bin_10.4-3.4-00082 \ - $(1)/lib/firmware/ath10k/QCA9984/hw1.0/firmware-5.bin + $(PKG_BUILD_DIR)/QCA99X0/hw2.0/boardData_AR900B_CUS239_5G_v2_001.bin \ + $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/board.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE_HTT,QCA99X0) \ + $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/ct-firmware-5.bin endef define Package/ath10k-firmware-qca9984-ct/install @@ -327,6 +540,34 @@ define Package/ath10k-firmware-qca9984-ct/install $(DL_DIR)/$(call CT_FIRMWARE_FILE,QCA9984) \ $(1)/lib/firmware/ath10k/QCA9984/hw1.0/firmware-5.bin endef +define Package/ath10k-firmware-qca9984-ct-htt/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9984/hw1.0 + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA9984/hw1.0/board-2.bin \ + $(1)/lib/firmware/ath10k/QCA9984/hw1.0/board-2.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE_HTT,QCA9984) \ + $(1)/lib/firmware/ath10k/QCA9984/hw1.0/ct-firmware-5.bin +endef + +define Package/ath10k-firmware-qca4019-ct/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA4019/hw1.0 + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA4019/hw1.0/board-2.bin \ + $(1)/lib/firmware/ath10k/QCA4019/hw1.0/ + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE,QCA4019) \ + $(1)/lib/firmware/ath10k/QCA4019/hw1.0/firmware-5.bin +endef +define Package/ath10k-firmware-qca4019-ct-htt/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA4019/hw1.0 + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA4019/hw1.0/board-2.bin \ + $(1)/lib/firmware/ath10k/QCA4019/hw1.0/ + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE_HTT,QCA4019) \ + $(1)/lib/firmware/ath10k/QCA4019/hw1.0/ct-firmware-5.bin +endef define Package/ath10k-firmware-qca9888-ct/install $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9888/hw2.0 @@ -340,6 +581,18 @@ define Package/ath10k-firmware-qca9888-ct/install $(DL_DIR)/$(call CT_FIRMWARE_FILE,QCA9888) \ $(1)/lib/firmware/ath10k/QCA9888/hw2.0/firmware-5.bin endef +define Package/ath10k-firmware-qca9888-ct-htt/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9888/hw2.0 + ln -s \ + ../../cal-pci-0000:01:00.0.bin \ + $(1)/lib/firmware/ath10k/QCA9888/hw2.0/board.bin + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA9888/hw2.0/board-2.bin \ + $(1)/lib/firmware/ath10k/QCA9888/hw2.0/board-2.bin + $(INSTALL_DATA) \ + $(DL_DIR)/$(call CT_FIRMWARE_FILE_HTT,QCA9888) \ + $(1)/lib/firmware/ath10k/QCA9888/hw2.0/ct-firmware-5.bin +endef $(eval $(call BuildPackage,ath10k-firmware-qca9887)) $(eval $(call BuildPackage,ath10k-firmware-qca9888)) @@ -350,7 +603,14 @@ $(eval $(call BuildPackage,ath10k-firmware-qca9984)) $(eval $(call BuildPackage,ath10k-firmware-qca4019)) $(eval $(call BuildPackage,ath10k-firmware-qca9887-ct)) +$(eval $(call BuildPackage,ath10k-firmware-qca9887-ct-htt)) $(eval $(call BuildPackage,ath10k-firmware-qca988x-ct)) +$(eval $(call BuildPackage,ath10k-firmware-qca988x-ct-htt)) $(eval $(call BuildPackage,ath10k-firmware-qca99x0-ct)) +$(eval $(call BuildPackage,ath10k-firmware-qca99x0-ct-htt)) $(eval $(call BuildPackage,ath10k-firmware-qca9984-ct)) +$(eval $(call BuildPackage,ath10k-firmware-qca9984-ct-htt)) +$(eval $(call BuildPackage,ath10k-firmware-qca4019-ct)) +$(eval $(call BuildPackage,ath10k-firmware-qca4019-ct-htt)) $(eval $(call BuildPackage,ath10k-firmware-qca9888-ct)) +$(eval $(call BuildPackage,ath10k-firmware-qca9888-ct-htt)) diff --git a/package/firmware/intel-microcode/Makefile b/package/firmware/intel-microcode/Makefile new file mode 100644 index 000000000..1b7288fc1 --- /dev/null +++ b/package/firmware/intel-microcode/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (C) 2018 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=intel-microcode +PKG_VERSION:=20180312 +PKG_RELEASE:=1 + +PKG_SOURCE:=intel-microcode_3.$(PKG_VERSION).$(PKG_RELEASE).tar.xz +PKG_SOURCE_URL:=http://ftp.debian.org/debian/pool/non-free/i/intel-microcode/ +PKG_HASH:=6ccb295d23961c7b96a69280e30fdce939e1d905147b22b8428886b173812d52 +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-3.$(PKG_VERSION).$(PKG_RELEASE) + +PKG_BUILD_DEPENDS:=iucode-tool/host + +ifdef CONFIG_TARGET_x86_64 + MICROCODE:="intel-microcode-64" +else + MICROCODE:="intel-microcode" +endif + +include $(INCLUDE_DIR)/package.mk + +define Package/intel-microcode + SECTION:=firmware + CATEGORY:=Firmware + URL:=$(PKG_SOURCE_URL) + DEPENDS:=@TARGET_x86 +iucode-tool + TITLE:=Intel x86 CPU microcode +endef + +define Build/Compile + IUCODE_TOOL=$(STAGING_DIR)/../host/bin/iucode_tool $(MAKE) -C $(PKG_BUILD_DIR) + mkdir $(PKG_BUILD_DIR)/intel-ucode + $(STAGING_DIR)/../host/bin/iucode_tool -q \ + --write-firmware=$(PKG_BUILD_DIR)/intel-ucode $(PKG_BUILD_DIR)/$(MICROCODE).bin +endef + +define Package/intel-microcode/install + $(INSTALL_DIR) $(1)/lib/firmware/intel-ucode + $(INSTALL_DATA) $(PKG_BUILD_DIR)/intel-ucode/* $(1)/lib/firmware/intel-ucode +endef + +$(eval $(call BuildPackage,intel-microcode)) diff --git a/package/firmware/ipq-wifi/Makefile b/package/firmware/ipq-wifi/Makefile index 4af364825..a92be6fd4 100644 --- a/package/firmware/ipq-wifi/Makefile +++ b/package/firmware/ipq-wifi/Makefile @@ -13,14 +13,14 @@ endef define Build/Compile endef -ALLWIFIBOARDS:=fritz4040 openmesh_a42 +ALLWIFIBOARDS:=asus_rt-ac58u avm_fritzbox-4040 glinet_gl-b1300 meraki_mr33 ALLWIFIPACKAGES:=$(foreach BOARD,$(ALLWIFIBOARDS),ipq-wifi-$(BOARD)) define Package/ipq-wifi-default SUBMENU:=ath10k IPQ4019 Boarddata SECTION:=firmware CATEGORY:=Firmware - DEPENDS:=@TARGET_ipq806x +ath10k-firmware-qca4019 + DEPENDS:=@TARGET_ipq40xx +ath10k-firmware-qca4019 TITLE:=Custom Board endef @@ -47,7 +47,9 @@ Don't install it for any other device! PREV_BOARD+=ipq-wifi-$(1) endef -$(eval $(call generate-ipq-wifi-package,fritz4040,board-fritz4040.bin,AVM FRITZBox 4040)) -$(eval $(call generate-ipq-wifi-package,openmesh_a42,board-openmesh_a42.bin,OpenMesh A42)) +$(eval $(call generate-ipq-wifi-package,asus_rt-ac58u,board-asus_rt-ac58u.bin,ASUS RT-AC58U)) +$(eval $(call generate-ipq-wifi-package,avm_fritzbox-4040,board-avm_fritzbox-4040.bin,AVM FRITZ!Box 4040)) +$(eval $(call generate-ipq-wifi-package,glinet_gl-b1300,board-glinet_gl-b1300.bin,GL.iNet GL-B1300)) +$(eval $(call generate-ipq-wifi-package,meraki_mr33,board-meraki_mr33.bin,Cisco Meraki MR33)) $(foreach PACKAGE,$(ALLWIFIPACKAGES),$(eval $(call BuildPackage,$(PACKAGE)))) diff --git a/package/firmware/ipq-wifi/board-asus_rt-ac58u.bin b/package/firmware/ipq-wifi/board-asus_rt-ac58u.bin new file mode 100644 index 000000000..ae1cb560a Binary files /dev/null and b/package/firmware/ipq-wifi/board-asus_rt-ac58u.bin differ diff --git a/package/firmware/ipq-wifi/board-fritz4040.bin b/package/firmware/ipq-wifi/board-avm_fritzbox-4040.bin similarity index 100% rename from package/firmware/ipq-wifi/board-fritz4040.bin rename to package/firmware/ipq-wifi/board-avm_fritzbox-4040.bin diff --git a/package/firmware/ipq-wifi/board-glinet_gl-b1300.bin b/package/firmware/ipq-wifi/board-glinet_gl-b1300.bin new file mode 100644 index 000000000..f2020f6fc Binary files /dev/null and b/package/firmware/ipq-wifi/board-glinet_gl-b1300.bin differ diff --git a/package/firmware/ipq-wifi/board-meraki_mr33.bin b/package/firmware/ipq-wifi/board-meraki_mr33.bin new file mode 100644 index 000000000..e569b32fe Binary files /dev/null and b/package/firmware/ipq-wifi/board-meraki_mr33.bin differ diff --git a/package/firmware/ipq-wifi/board-openmesh_a42.bin b/package/firmware/ipq-wifi/board-openmesh_a42.bin deleted file mode 100644 index 9ac592120..000000000 Binary files a/package/firmware/ipq-wifi/board-openmesh_a42.bin and /dev/null differ diff --git a/package/firmware/layerscape/fman-ucode/Makefile b/package/firmware/layerscape/fman-ucode/Makefile index aa2601b26..495aee99e 100644 --- a/package/firmware/layerscape/fman-ucode/Makefile +++ b/package/firmware/layerscape/fman-ucode/Makefile @@ -13,7 +13,7 @@ PKG_SOURCE_DATE:=2017-02-13 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/qoriq-open-source/fm-ucode.git +PKG_SOURCE_URL:=https://github.com/NXP/qoriq-fm-ucode.git PKG_SOURCE_VERSION:=c275e91392e2adab1ed22f3867b8269ca3c54014 PKG_MIRROR_HASH:=1a4611d528f67f3acfa88aefdec9a9a67d96a3139ac5fe1089f599272e6c4a52 diff --git a/package/firmware/layerscape/ls-mc/Makefile b/package/firmware/layerscape/ls-mc/Makefile index a81e09563..86683d5a4 100644 --- a/package/firmware/layerscape/ls-mc/Makefile +++ b/package/firmware/layerscape/ls-mc/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ls-mc -PKG_SOURCE_DATE:=2014-07-04 +PKG_SOURCE_DATE:=2014-07-02 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/qoriq-open-source/mc-binary.git -PKG_SOURCE_VERSION:=824745fe1580b281bebb808321c3f41353a3140a -PKG_MIRROR_HASH:=984c7905af3a4b87b72263de9220901c531fe064f0b89dd2882676354e09ed16 +PKG_SOURCE_URL:=https://github.com/NXP/qoriq-mc-binary.git +PKG_SOURCE_VERSION:=40b0c8b7edfd2d8f989619b12d6352472455c696 +PKG_MIRROR_HASH:=b3c8db70de8617e5bc033951b5ad3824f98353303870d6035668075daf93382e PKG_BUILD_DIR=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION) @@ -28,7 +28,7 @@ define Package/layerscape-mc-ls1088ardb DEPENDS:=@TARGET_layerscape TITLE:=NXP LS1088ARDB MC firmware VARIANT:=ls1088ardb - CONFIG:=ls1088a/mc_10.3.4_ls1088a_20170929.itb + CONFIG:=ls1088a/mc_10.4.0_ls1088a_20171101.itb endef define Package/layerscape-mc-ls2088ardb @@ -37,7 +37,7 @@ define Package/layerscape-mc-ls2088ardb DEPENDS:=@TARGET_layerscape TITLE:=NXP LS2088ARDB MC firmware VARIANT:=ls2088ardb - CONFIG:=ls2088a/mc_10.3.4_ls2088a_20170929.itb + CONFIG:=ls2088a/mc_10.4.0_ls2088a_20171101.itb endef define Build/Compile diff --git a/package/firmware/layerscape/ls-ppa/Makefile b/package/firmware/layerscape/ls-ppa/Makefile index a354ad1a9..89d653077 100644 --- a/package/firmware/layerscape/ls-ppa/Makefile +++ b/package/firmware/layerscape/ls-ppa/Makefile @@ -9,13 +9,13 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/image.mk PKG_NAME:=ls-ppa -PKG_SOURCE_DATE:=2017-10-26 +PKG_SOURCE_DATE:=2018-01-18 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/yangbolu1991/ppa-binary.git -PKG_SOURCE_VERSION:=76a80ca988affbee67bb17096aefb82ba6d91be7 -PKG_MIRROR_HASH:=55e6cfa0f03f2db667ed4270e5aaf43ab830343af3b9724f92e830a1e3a3a25f +PKG_SOURCE_VERSION:=cd295be24cadae51741154f3b1c935c7b9064230 +PKG_MIRROR_HASH:=743ca493f640d5fb2e99ad7b1da030f9088546f1ad70b5d1e61eb98a969c00c5 PKG_BUILD_DIR=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION) diff --git a/package/firmware/layerscape/ls-rcw-bin/Makefile b/package/firmware/layerscape/ls-rcw-bin/Makefile new file mode 100644 index 000000000..589124e44 --- /dev/null +++ b/package/firmware/layerscape/ls-rcw-bin/Makefile @@ -0,0 +1,99 @@ +# +# Copyright 2017 NXP +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/image.mk + +PKG_NAME:=ls-rcw-bin +PKG_SOURCE_DATE:=2017-11-19 +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/NXP/qoriq-rcw-bin.git +PKG_SOURCE_VERSION:=bf3ae3cb15829876007c553509501cdaa16745e7 +PKG_MIRROR_HASH:=dc14a47e9529578c63d9ad2bf4e27ef565a055e4121ce2d1324c019f69074314 + +PKG_BUILD_DIR=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION) + +PKG_FLAGS:=nonshared + +include $(INCLUDE_DIR)/package.mk + +define rcw-bin/Default + TITLE:= + CONFIG:= +endef + +define rcw-bin/ls1012ardb + TITLE=NXP LS1012ARDB RCW Binary + CONFIG=ls1012ardb/R_SPNH_3508/PBL_0x35_0x08_1000_250_1000_default.bin +endef + +define rcw-bin/ls1088ardb + TITLE=NXP LS1088ARDB RCW Binary + CONFIG=ls1088ardb/FCQQQQQQQQ_PPP_H_0x1d_0x0d/PBL_QSPI_1600_700_2100_0x1d_0x0d.bin +endef + +define rcw-bin/ls2088ardb + TITLE=NXP LS2088ARDB RCW Binary + CONFIG=ls2088ardb/FFFFFFFF_PP_HH_0x2a_0x41/PBL_0x2a_0x41_1800_700_1866_1600.bin +endef + +define rcw-bin/ls1012afrdm + TITLE=NXP LS1012AFRDM RCW Binary + CONFIG=ls1012afrdm/N_SSNP_3305/PBL_0x33_0x05_800_250_1000_default.bin +endef + +RCWS := \ + ls1012ardb \ + ls1088ardb \ + ls2088ardb \ + ls1012afrdm + +define Package/rcw-bin/template +define Package/rcw-layerscape-$(1) + SECTION:=firmware + CATEGORY:=Firmware + DEPENDS:=@TARGET_layerscape + TITLE:=$(2) + VARIANT:=$(1) +endef +endef + +define BuildRCWPackage + $(eval $(rcw-bin/Default)) + $(eval $(rcw-bin/$(1))) + $(call Package/rcw-bin/template,$(1),$(TITLE)) +endef + +ifdef BUILD_VARIANT +$(eval $(call rcw-bin/$(BUILD_VARIANT))) +RCW_CONFIG:=$(if $(CONFIG),$(CONFIG),$(BUILD_VARIANT)) +endif + +define Build/Compile +endef + +define Package/rcw-bin/install/default + $(INSTALL_DIR) $(STAGING_DIR_IMAGE) + $(CP) $(PKG_BUILD_DIR)/$(RCW_CONFIG) $(STAGING_DIR_IMAGE)/$(1)-rcw.bin +endef + +define Package/rcw-bin/install/template +define Package/rcw-layerscape-$(1)/install + $(call Package/rcw-bin/install/default,$(2)) +endef +endef + +$(foreach r,$(RCWS), \ + $(eval $(call Package/rcw-bin/install/template,$(r),$(r))) \ +) + +$(foreach r,$(RCWS), \ + $(eval $(call BuildRCWPackage,$(r))) \ + $(eval $(call BuildPackage,rcw-layerscape-$(r))) \ +) diff --git a/package/firmware/layerscape/ls-rcw/Makefile b/package/firmware/layerscape/ls-rcw/Makefile index 70791d47b..a3326abfb 100644 --- a/package/firmware/layerscape/ls-rcw/Makefile +++ b/package/firmware/layerscape/ls-rcw/Makefile @@ -9,13 +9,13 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/image.mk PKG_NAME:=ls-rcw -PKG_SOURCE_DATE:=2017-09-26 +PKG_SOURCE_DATE:=2017-12-01 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/qoriq-open-source/rcw.git -PKG_SOURCE_VERSION:=6719b046ee87b04026fe163e6c8fbbebba2186aa -PKG_MIRROR_HASH:=9645ecf148640ec7d1029bce65950f2a0b0e6b351a25ef60c8a839c42c6ed56d +PKG_SOURCE_VERSION:=cbd5e66fcb850e821c8632578410ceba5733a49e +PKG_MIRROR_HASH:=4caad5e0ae2018a0a594f36e46e4a96698420956c64bb73656f380fd46733c3d PKG_BUILD_DIR=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION) @@ -41,33 +41,9 @@ define rcw/ls1046ardb CONFIG=ls1046ardb/RR_FFSSPPPH_1133_5559/rcw_1800_qspiboot.bin.swap endef -define rcw/ls1012ardb - TITLE=RCW binary $(PKG_VERSION) for NXP ls1012ardb 64b/32b Dev Board - CONFIG=ls1012ardb/R_SPNH_3508/PBL_0x35_0x08_1000_250_1000_default.bin -endef - -define rcw/ls1088ardb - TITLE=RCW binary $(PKG_VERSION) for NXP ls1088ardb 64b/32b Dev Board - CONFIG=ls1088ardb/FCQQQQQQQQ_PPP_H_0x1d_0x0d/PBL_QSPI_1600_700_2100_0x1d_0x0d.bin -endef - -define rcw/ls2088ardb - TITLE=RCW binary $(PKG_VERSION) for NXP ls2088ardb 64b/32b Dev Board - CONFIG=ls2088ardb/FFFFFFFF_PP_HH_0x2a_0x41/PBL_0x2a_0x41_1800_700_1866_1600.bin -endef - -define rcw/ls1012afrdm - TITLE=RCW binary $(PKG_VERSION) for NXP ls1012afrdm 64b/32b Dev Board - CONFIG=ls1012afrdm/N_SSNP_3305/PBL_0x33_0x05_800_250_1000_default.bin -endef - RCWS := \ ls1043ardb \ - ls1046ardb \ - ls1012ardb \ - ls1088ardb \ - ls2088ardb \ - ls1012afrdm + ls1046ardb define Package/rcw/template define Package/rcw-layerscape-$(1) diff --git a/package/firmware/layerscape/ppfe-firmware/Makefile b/package/firmware/layerscape/ppfe-firmware/Makefile index 419201e87..dc73f9397 100644 --- a/package/firmware/layerscape/ppfe-firmware/Makefile +++ b/package/firmware/layerscape/ppfe-firmware/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ppfe -PKG_SOURCE_DATE:=2017-10-13 +PKG_SOURCE_DATE:=2017-12-05 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/qoriq-open-source/engine-pfe-bin.git -PKG_SOURCE_VERSION:=97cd13d3070d7199e62881bc495b332194b67edd -PKG_MIRROR_HASH:=3457bfe7201a8410443f34d4bb5fa67d4ff19e2d0f3957e84e3f20e2ae3fa34a +PKG_SOURCE_URL:=https://github.com/NXP/qoriq-engine-pfe-bin.git +PKG_SOURCE_VERSION:=848002fe4e0e3efb8d13a813e5c123bbc87aa95b +PKG_MIRROR_HASH:=b6867be2f5826e807db15256996e11303ca7bbe06ac18448cbf68827d9a59ae2 PKG_FLAGS:=nonshared @@ -31,7 +31,7 @@ define Package/layerscape-ppfe CONFIG_FW:=ls1012a/u-boot/pfe_fw_sbl.itb CONFIG_BIN1:=ls1012a/slow_path/ppfe_class_ls1012a.elf CONFIG_BIN2:=ls1012a/slow_path/ppfe_tmu_ls1012a.elf - CONFIG_LIC:=Freescale-Binary-EULA + CONFIG_LIC:=NXP-Binary-EULA.txt endef define Build/Compile diff --git a/package/firmware/linux-firmware/intel.mk b/package/firmware/linux-firmware/intel.mk index 8cdbb4824..684513e5a 100644 --- a/package/firmware/linux-firmware/intel.mk +++ b/package/firmware/linux-firmware/intel.mk @@ -143,7 +143,7 @@ $(eval $(call BuildPackage,iwlwifi-firmware-iwl7265d)) Package/iwlwifi-firmware-iwl8260c = $(call Package/firmware-default,Intel Wireless 8260 and 4165 firmware) define Package/iwlwifi-firmware-iwl8260c/install $(INSTALL_DIR) $(1)/lib/firmware - $(INSTALL_DATA) $(PKG_BUILD_DIR)/iwlwifi-8000C-27.ucode $(1)/lib/firmware + $(INSTALL_DATA) $(PKG_BUILD_DIR)/iwlwifi-8000C-31.ucode $(1)/lib/firmware endef $(eval $(call BuildPackage,iwlwifi-firmware-iwl8260c)) diff --git a/package/firmware/wireless-regdb/patches/600-custom-fix-txpower-and-dfs.patch b/package/firmware/wireless-regdb/patches/600-custom-fix-txpower-and-dfs.patch new file mode 100644 index 000000000..b1c912444 --- /dev/null +++ b/package/firmware/wireless-regdb/patches/600-custom-fix-txpower-and-dfs.patch @@ -0,0 +1,42 @@ +From 7eb6313910023f1be6015a8cd9e1b380ae01af64 Mon Sep 17 00:00:00 2001 +From: Chen Minqiang +Date: Sun, 7 Jan 2018 14:38:36 +0800 +Subject: [PATCH] custom fix txpower and dfs + +--- + db.txt | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/db.txt b/db.txt +index 75dc0a3..24989ad 100644 +--- a/db.txt ++++ b/db.txt +@@ -277,9 +277,9 @@ country CL: DFS-JP + (5735 - 5835 @ 80), (20) + + country CN: DFS-FCC +- (2402 - 2482 @ 40), (20) +- (5170 - 5250 @ 80), (23), AUTO-BW +- (5250 - 5330 @ 80), (23), DFS, AUTO-BW ++ (2402 - 2482 @ 40), (30) ++ (5170 - 5250 @ 80), (30), AUTO-BW ++ (5250 - 5330 @ 80), (30), AUTO-BW + (5735 - 5835 @ 80), (30) + # 60 GHz band channels 1,4: 28dBm, channels 2,3: 44dBm + # ref: http://www.miit.gov.cn/n11293472/n11505629/n11506593/n11960250/n11960606/n11960700/n12330791.files/n12330790.pdf +@@ -1238,9 +1238,9 @@ country UG: DFS-FCC + country US: DFS-FCC + (2402 - 2472 @ 40), (30) + # 5.15 ~ 5.25 GHz: 30 dBm for master mode, 23 dBm for clients +- (5170 - 5250 @ 80), (23), AUTO-BW +- (5250 - 5330 @ 80), (23), DFS, AUTO-BW +- (5490 - 5730 @ 160), (23), DFS ++ (5170 - 5250 @ 80), (30), AUTO-BW ++ (5250 - 5330 @ 80), (30), AUTO-BW ++ (5490 - 5730 @ 160), (30) + (5735 - 5835 @ 80), (30) + # 60g band + # reference: http://cfr.regstoday.com/47cfr15.aspx#47_CFR_15p255 +-- +2.7.4 + diff --git a/package/kernel/ath10k-ct/Makefile b/package/kernel/ath10k-ct/Makefile index fe094e76a..1725bb7d1 100644 --- a/package/kernel/ath10k-ct/Makefile +++ b/package/kernel/ath10k-ct/Makefile @@ -8,19 +8,19 @@ PKG_LICENSE_FILES:= PKG_SOURCE_URL:=https://github.com/greearb/ath10k-ct.git PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2017-06-13 -PKG_SOURCE_VERSION:=bded1823912549017d819d1796273b3134c3de20 -PKG_MIRROR_HASH:=616174650e12a82edb6b6bd18ac186e2c6a48fdad0082df9d2011ab20940814b - -PKG_MAINTAINER:=Ben Greear -PKG_BUILD_PARALLEL:=1 -PKG_EXTMOD_SUBDIRS:=ath10k +PKG_SOURCE_DATE:=2018-03-16 +PKG_SOURCE_VERSION:=30827f7d5b9841905c4efe918da2d95fc518c921 +PKG_MIRROR_HASH:=aac023d7f9b09becf27058b1d09ae6d068b14bb6f10c5b5a248c7ee5ecff04dc # Build the 4.13 ath10k-ct driver version. Other options are "-4.9", or # leave un-defined for 4.7 kernel. Probably this should match as closely as # possible to whatever mac80211 backports version is being used. CT_KVER="-4.13" +PKG_MAINTAINER:=Ben Greear +PKG_BUILD_PARALLEL:=1 +PKG_EXTMOD_SUBDIRS:=ath10k$(CT_KVER) + STAMP_CONFIGURED_DEPENDS := $(STAGING_DIR)/usr/include/mac80211-backport/backport/autoconf.h include $(INCLUDE_DIR)/kernel.mk @@ -29,11 +29,12 @@ include $(INCLUDE_DIR)/package.mk define KernelPackage/ath10k-ct SUBMENU:=Wireless Drivers TITLE:=ath10k-ct driver optimized for CT ath10k firmware - DEPENDS:=+kmod-mac80211 +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT @PCI_SUPPORT +kmod-hwmon-core + DEPENDS:=+kmod-mac80211 +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT +@DRIVER_11W_SUPPORT +kmod-hwmon-core FILES:=\ $(PKG_BUILD_DIR)/ath10k$(CT_KVER)/ath10k_pci.ko \ $(PKG_BUILD_DIR)/ath10k$(CT_KVER)/ath10k_core.ko AUTOLOAD:=$(call AutoProbe,ath10k_pci) + PROVIDES:=kmod-ath10k endef NOSTDINC_FLAGS = \ @@ -50,9 +51,11 @@ ifdef CONFIG_PACKAGE_MAC80211_MESH endif CT_MAKEDEFS += CONFIG_ATH10K=m CONFIG_ATH10K_PCI=m -# No AHB support enabled yet. Could conditionally enable it later. -#CT_MAKEDEFS += CONFIG_ATH10K_AHB=y -#NOSTDINC_FLAGS += -DCONFIG_ATH10K_AHB + +# This AHB logic is needed for IPQ4019 radios +CT_MAKEDEFS += CONFIG_ATH10K_AHB=m +NOSTDINC_FLAGS += -DCONFIG_ATH10K_AHB + NOSTDINC_FLAGS += -DSTANDALONE_CT ifdef CONFIG_PACKAGE_MAC80211_DEBUGFS diff --git a/package/kernel/ath10k-ct/patches/130-ath10k-activate-user-space-firmware-loading-again.patch b/package/kernel/ath10k-ct/patches/130-ath10k-activate-user-space-firmware-loading-again.patch deleted file mode 100644 index dc02a9d6e..000000000 --- a/package/kernel/ath10k-ct/patches/130-ath10k-activate-user-space-firmware-loading-again.patch +++ /dev/null @@ -1,36 +0,0 @@ -From c0cc00f250e19c717fc9cdbdb7f55aaa569c7498 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens -Date: Thu, 24 Aug 2017 23:06:41 +0200 -Subject: [PATCH] ath10k: activate user space firmware loading again - -In commit 9f5bcfe93315 ("ath10k: silence firmware file probing -warnings") the firmware loading was changed from request_firmware() to -request_firmware_direct() to silence some warnings in case it fails. -request_firmware_direct() directly searches in the file system only and -does not send a hotplug event to user space in case it could not find -the firmware directly. -In LEDE we use a user space script to extract the calibration data from -the flash memory which gets triggered by the hotplug event. This way the -firmware gets extracted from some vendor specific partition when the -driver requests this firmware. This mechanism does not work any more -after this change. - -Fixes: 9f5bcfe93315 ("ath10k: silence firmware file probing warnings") -Signed-off-by: Hauke Mehrtens -Cc: Michal Kazior -Signed-off-by: Kalle Valo ---- - ath10k-4.13/core.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/ath10k-4.13/core.c -+++ b/ath10k-4.13/core.c -@@ -556,7 +556,7 @@ static const struct firmware *ath10k_fet - dir = "."; - - snprintf(filename, sizeof(filename), "%s/%s", dir, file); -- ret = request_firmware_direct(&fw, filename, ar->dev); -+ ret = request_firmware(&fw, filename, ar->dev); - ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot fw request '%s': %d\n", - filename, ret); - diff --git a/package/kernel/broadcom-wl/patches/040-remove_last_rx_usage.patch b/package/kernel/broadcom-wl/patches/040-remove_last_rx_usage.patch new file mode 100644 index 000000000..9f4b0b01b --- /dev/null +++ b/package/kernel/broadcom-wl/patches/040-remove_last_rx_usage.patch @@ -0,0 +1,10 @@ +--- broadcom-wl-5.10.56.27.3/driver/wl_linux.c.orig 2018-01-13 18:25:14.944667645 +0100 ++++ broadcom-wl-5.10.56.27.3/driver/wl_linux.c 2018-01-13 18:25:25.836667888 +0100 +@@ -2762,7 +2762,6 @@ + bcopy(oskb->data + D11_PHY_HDR_LEN, pdata, oskb->len - D11_PHY_HDR_LEN); + + skb->dev = wl->monitor; +- skb->dev->last_rx = jiffies; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + skb_reset_mac_header(skb); + #else diff --git a/package/kernel/gpio-nct5104d/src/gpio-nct5104d.c b/package/kernel/gpio-nct5104d/src/gpio-nct5104d.c index 1ad1a6b10..c139cf8d2 100644 --- a/package/kernel/gpio-nct5104d/src/gpio-nct5104d.c +++ b/package/kernel/gpio-nct5104d/src/gpio-nct5104d.c @@ -35,7 +35,8 @@ #define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */ #define SIO_NCT5104D_ID 0x1061 /* Chip ID */ -#define SIO_PCENGINES_APU_NCT5104D_ID 0xc452 /* Chip ID */ +#define SIO_PCENGINES_APU_NCT5104D_ID1 0xc452 /* Chip ID */ +#define SIO_PCENGINES_APU_NCT5104D_ID2 0xc453 /* Chip ID */ enum chips { nct5104d }; @@ -350,7 +351,8 @@ static int __init nct5104d_find(int addr, struct nct5104d_sio *sio) devid = superio_inw(addr, SIO_CHIPID); switch (devid) { case SIO_NCT5104D_ID: - case SIO_PCENGINES_APU_NCT5104D_ID: + case SIO_PCENGINES_APU_NCT5104D_ID1: + case SIO_PCENGINES_APU_NCT5104D_ID2: sio->type = nct5104d; /* enable GPIO0 and GPIO1 */ superio_select(addr, SIO_LD_GPIO); diff --git a/package/kernel/kmod-sched-cake/Makefile b/package/kernel/kmod-sched-cake/Makefile index f9bcd65f1..2156eee0e 100644 --- a/package/kernel/kmod-sched-cake/Makefile +++ b/package/kernel/kmod-sched-cake/Makefile @@ -13,9 +13,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/dtaht/sch_cake.git -PKG_SOURCE_DATE:=2018-01-07 -PKG_SOURCE_VERSION:=568ed96467f41aad37556b0db11fc008e05941e9 -PKG_MIRROR_HASH:=8f3f962824826d07b1029379d91e01bf97fe0bfce1233af5cfa7a54cb1c3632c +PKG_SOURCE_DATE:=2018-03-19 +PKG_SOURCE_VERSION:=0afc1bee4e9fc5d75668cb10254ab5d2d02f0098 +PKG_MIRROR_HASH:=b8ac95753d05ff602282ed5a799f9c953f60decebc5720ee8f0101344a5acfc4 include $(INCLUDE_DIR)/package.mk diff --git a/package/kernel/lantiq/ltq-adsl-mei/src/ifxmips_mei_interface.h b/package/kernel/lantiq/ltq-adsl-mei/src/ifxmips_mei_interface.h index 1098b2b79..dc9f1c241 100644 --- a/package/kernel/lantiq/ltq-adsl-mei/src/ifxmips_mei_interface.h +++ b/package/kernel/lantiq/ltq-adsl-mei/src/ifxmips_mei_interface.h @@ -111,7 +111,11 @@ static inline long ugly_hack_sleep_on_timeout(wait_queue_head_t *q, long timeout) { unsigned long flags; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)) + wait_queue_entry_t wait; +#else wait_queue_t wait; +#endif init_waitqueue_entry(&wait, current); diff --git a/package/kernel/lantiq/ltq-adsl/Makefile b/package/kernel/lantiq/ltq-adsl/Makefile index b6f1c8a96..0fbda34ff 100644 --- a/package/kernel/lantiq/ltq-adsl/Makefile +++ b/package/kernel/lantiq/ltq-adsl/Makefile @@ -10,15 +10,15 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ltq-adsl PKG_VERSION:=3.24.4.4 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE:=drv_dsl_cpe_api_danube-$(PKG_VERSION).tar.gz PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/ltq-dsl-$(BUILD_VARIANT)/drv_dsl_cpe_api-$(PKG_VERSION) PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources/ PKG_HASH:=eb2ed59715d3bf4e8a1460bbbe2f1660039e0a9f9d72afb1b2b16590094eb33c PKG_MAINTAINER:=John Crispin -PKG_USE_MIPS16:=0 PKG_CHECK_FORMAT_SECURITY:=0 +PKG_ASLR_PIE:=0 PKG_FIXUP:=autoreconf include $(INCLUDE_DIR)/package.mk @@ -83,8 +83,6 @@ CONFIGURE_ARGS += \ EXTRA_CFLAGS += -DDEBUG endif -EXTRA_CFLAGS = -fno-pic -mno-abicalls -mlong-calls -G 0 - define Build/InstallDev $(INSTALL_DIR) $(1)/usr/include/adsl $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_*.h $(1)/usr/include/adsl/ diff --git a/package/kernel/lantiq/ltq-adsl/patches/020-not-leak-cflags.patch b/package/kernel/lantiq/ltq-adsl/patches/020-not-leak-cflags.patch new file mode 100644 index 000000000..b3f20dbbb --- /dev/null +++ b/package/kernel/lantiq/ltq-adsl/patches/020-not-leak-cflags.patch @@ -0,0 +1,32 @@ +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -253,10 +253,7 @@ else + drv_dsl_cpe_api_common_mod_cflags = + endif + +-drv_dsl_cpe_api_common_cflags = -DLINUX -D__LINUX__ -D__KERNEL__ -DEXPORT_SYMTAB \ +- -pipe -Wall -Wformat -Wimplicit -Wunused -Wswitch -Wcomment -Winline \ +- -Wuninitialized -Wparentheses -Wsign-compare -Wreturn-type \ +- -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common ++drv_dsl_cpe_api_common_cflags = -DLINUX -D__LINUX__ -D__KERNEL__ -DEXPORT_SYMTAB + + if DSL_DBG_MAX_LEVEL_SET + drv_dsl_cpe_api_common_cflags += -DDSL_DBG_MAX_LEVEL=$(DSL_DBG_MAX_LEVEL_PRE) +@@ -266,7 +263,7 @@ endif + drv_dsl_cpe_api_target_cflags = $(ADD_DRV_CFLAGS) + + # compile cflags +-drv_dsl_cpe_api_compile_cflags = $(EXTRA_DRV_CFLAGS) ++drv_dsl_cpe_api_compile_cflags = + + if !KERNEL_2_6 + # the headerfile of linux kernels 2.6.x contain to much arithmetic +@@ -314,7 +311,7 @@ drv_dsl_cpe_api.ko: $(drv_dsl_cpe_api_SO + @echo -e "# drv_dsl_cpe_api: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild + @echo -e "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild + @echo -e "$(subst .ko,,$@)-y := $(drv_dsl_cpe_api_OBJS)" >> $(PWD)/Kbuild +- @echo -e "EXTRA_CFLAGS := $(CFLAGS) -DHAVE_CONFIG_H $(drv_dsl_cpe_api_CFLAGS) $(DSL_DRIVER_INCL_PATH) $(IFXOS_INCLUDE_PATH) -I@abs_srcdir@/include -I$(PWD)/include" >> $(PWD)/Kbuild ++ @echo -e "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(drv_dsl_cpe_api_CFLAGS) $(DSL_DRIVER_INCL_PATH) $(IFXOS_INCLUDE_PATH) -I@abs_srcdir@/include -I$(PWD)/include" >> $(PWD)/Kbuild + $(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules + + clean-generic: diff --git a/package/kernel/lantiq/ltq-adsl/patches/100-dsl_compat.patch b/package/kernel/lantiq/ltq-adsl/patches/100-dsl_compat.patch index f2ed230bd..431ccb6eb 100644 --- a/package/kernel/lantiq/ltq-adsl/patches/100-dsl_compat.patch +++ b/package/kernel/lantiq/ltq-adsl/patches/100-dsl_compat.patch @@ -1,7 +1,5 @@ -Index: drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_device_danube.h -=================================================================== ---- drv_dsl_cpe_api-3.24.4.4.orig/src/include/drv_dsl_cpe_device_danube.h 2009-05-12 20:02:16.000000000 +0200 -+++ drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_device_danube.h 2012-11-29 19:47:21.060210322 +0100 +--- a/src/include/drv_dsl_cpe_device_danube.h ++++ b/src/include/drv_dsl_cpe_device_danube.h @@ -24,7 +24,7 @@ #include "drv_dsl_cpe_simulator_danube.h" #else @@ -11,10 +9,8 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_device_danube.h #endif /* defined(DSL_CPE_SIMULATOR_DRIVER) && defined(WIN32)*/ #define DSL_MAX_LINE_NUMBER 1 -Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c -=================================================================== ---- drv_dsl_cpe_api-3.24.4.4.orig/src/common/drv_dsl_cpe_os_linux.c 2009-07-13 11:33:43.000000000 +0200 -+++ drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c 2012-11-29 19:46:32.700209112 +0100 +--- a/src/common/drv_dsl_cpe_os_linux.c ++++ b/src/common/drv_dsl_cpe_os_linux.c @@ -11,6 +11,7 @@ #ifdef __LINUX__ @@ -23,7 +19,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c #include "drv_dsl_cpe_api.h" #include "drv_dsl_cpe_api_ioctl.h" -@@ -34,9 +35,13 @@ +@@ -34,9 +35,13 @@ static const char* dsl_cpe_api_version = static DSL_ssize_t DSL_DRV_Write(DSL_DRV_file_t *pFile, const DSL_char_t * pBuf, DSL_DRV_size_t nSize, DSL_DRV_offset_t * pLoff); @@ -38,7 +34,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c static int DSL_DRV_Open(DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil); static int DSL_DRV_Release(DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil); -@@ -72,7 +77,11 @@ +@@ -72,7 +77,11 @@ static struct file_operations dslCpeApiO open: DSL_DRV_Open, release: DSL_DRV_Release, write: DSL_DRV_Write, @@ -50,7 +46,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c poll: DSL_DRV_Poll }; #else -@@ -168,10 +177,17 @@ +@@ -168,10 +177,17 @@ static DSL_ssize_t DSL_DRV_Write(DSL_DRV \return Success or failure. \ingroup Internal */ @@ -68,7 +64,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c { DSL_int_t nErr=0; DSL_boolean_t bIsInKernel; -@@ -216,16 +232,7 @@ +@@ -216,16 +232,7 @@ static DSL_int_t DSL_DRV_Ioctls(DSL_DRV_ } } } @@ -86,7 +82,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c if ( (_IOC_TYPE(nCommand) == DSL_IOC_MAGIC_CPE_API) || (_IOC_TYPE(nCommand) == DSL_IOC_MAGIC_CPE_API_G997) || (_IOC_TYPE(nCommand) == DSL_IOC_MAGIC_CPE_API_PM) || -@@ -1058,6 +1065,7 @@ +@@ -1058,6 +1065,7 @@ static void DSL_DRV_DebugInit(void) /* Entry point of driver */ int __init DSL_ModuleInit(void) { @@ -94,7 +90,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c DSL_int_t i; printk(DSL_DRV_CRLF DSL_DRV_CRLF "Infineon CPE API Driver version: %s" DSL_DRV_CRLF, -@@ -1104,7 +1112,8 @@ +@@ -1104,7 +1112,8 @@ int __init DSL_ModuleInit(void) } DSL_DRV_DevNodeInit(); @@ -104,35 +100,44 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c return 0; } -Index: drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_os_linux.h -=================================================================== ---- drv_dsl_cpe_api-3.24.4.4.orig/src/include/drv_dsl_cpe_os_linux.h 2009-07-03 17:04:51.000000000 +0200 -+++ drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_os_linux.h 2012-11-29 19:47:23.092210377 +0100 -@@ -17,17 +17,17 @@ +--- a/src/include/drv_dsl_cpe_os_linux.h ++++ b/src/include/drv_dsl_cpe_os_linux.h +@@ -16,18 +16,18 @@ + extern "C" { #endif - #include +-#include -#include -+#include #include #include #include #include #include #include -- +#include - #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +- +-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) - #include -+ #include ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) ++#include ++#else ++#include #endif #include -Index: drv_dsl_cpe_api-3.24.4.4/src/ifxmips_mei_interface.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ drv_dsl_cpe_api-3.24.4.4/src/ifxmips_mei_interface.h 2012-11-29 19:47:54.972211177 +0100 +@@ -39,7 +39,8 @@ + #include + #include + #include +-#include ++//#include ++#include + + #ifdef INCLUDE_DSL_CPE_API_IFXOS_SUPPORT + /** IFXOS includes*/ +--- /dev/null ++++ b/src/ifxmips_mei_interface.h @@ -0,0 +1,702 @@ +/****************************************************************************** + @@ -838,7 +843,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/ifxmips_mei_interface.h +#endif //IFXMIPS_MEI_H --- a/configure.in +++ b/configure.in -@@ -310,7 +310,7 @@ +@@ -310,7 +310,7 @@ dnl Set kernel build path AC_ARG_ENABLE(kernelbuild, AC_HELP_STRING(--enable-kernel-build=x,Set the target kernel build path), [ @@ -847,7 +852,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/ifxmips_mei_interface.h AC_SUBST([KERNEL_BUILD_PATH],[$enableval]) else AC_MSG_ERROR([The kernel build directory is not valid or not configured!]) -@@ -333,12 +333,12 @@ +@@ -333,12 +333,12 @@ AC_ARG_ENABLE(ifxos-include, echo Set the lib_ifxos include path $enableval AC_SUBST([IFXOS_INCLUDE_PATH],[$enableval]) else @@ -862,7 +867,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/ifxmips_mei_interface.h AC_SUBST([IFXOS_INCLUDE_PATH],[$DEFAULT_IFXOS_INCLUDE_PATH]) ] ) -@@ -1702,73 +1702,73 @@ +@@ -1702,73 +1702,73 @@ dnl Set the configure params for dist ch AC_SUBST([DISTCHECK_CONFIGURE_PARAMS],[$CONFIGURE_OPTIONS]) AC_CONFIG_COMMANDS_PRE([ @@ -1005,7 +1010,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/ifxmips_mei_interface.h AC_CONFIG_FILES([Makefile src/Makefile]) --- a/src/Makefile.am +++ b/src/Makefile.am -@@ -303,7 +303,7 @@ +@@ -300,7 +300,7 @@ if KERNEL_2_6 drv_dsl_cpe_api_OBJS = "$(subst .c,.o,$(filter %.c,$(drv_dsl_cpe_api_SOURCES)))" drv_dsl_cpe_api.ko: $(drv_dsl_cpe_api_SOURCES) @@ -1014,52 +1019,18 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/ifxmips_mei_interface.h if test ! -e common/drv_dsl_cpe_api.c ; then \ echo "copy source files (as links only!)"; \ for f in $(filter %.c,$(drv_dsl_cpe_api_SOURCES)); do \ -@@ -311,10 +311,10 @@ +@@ -308,10 +308,10 @@ drv_dsl_cpe_api.ko: $(drv_dsl_cpe_api_SO cp -s $(addprefix @abs_srcdir@/,$$f) $(PWD)/`dirname $$f`/ ; \ done \ fi - @echo -e "# drv_dsl_cpe_api: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild - @echo -e "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild - @echo -e "$(subst .ko,,$@)-y := $(drv_dsl_cpe_api_OBJS)" >> $(PWD)/Kbuild -- @echo -e "EXTRA_CFLAGS := $(CFLAGS) -DHAVE_CONFIG_H $(drv_dsl_cpe_api_CFLAGS) $(DSL_DRIVER_INCL_PATH) $(IFXOS_INCLUDE_PATH) -I@abs_srcdir@/include -I$(PWD)/include" >> $(PWD)/Kbuild +- @echo -e "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(drv_dsl_cpe_api_CFLAGS) $(DSL_DRIVER_INCL_PATH) $(IFXOS_INCLUDE_PATH) -I@abs_srcdir@/include -I$(PWD)/include" >> $(PWD)/Kbuild + @echo "# drv_dsl_cpe_api: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild + @echo "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild + @echo "$(subst .ko,,$@)-y := $(drv_dsl_cpe_api_OBJS)" >> $(PWD)/Kbuild -+ @echo "EXTRA_CFLAGS := $(CFLAGS) -DHAVE_CONFIG_H $(drv_dsl_cpe_api_CFLAGS) $(DSL_DRIVER_INCL_PATH) $(IFXOS_INCLUDE_PATH) -I@abs_srcdir@/include -I$(PWD)/include" >> $(PWD)/Kbuild ++ @echo "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(drv_dsl_cpe_api_CFLAGS) $(DSL_DRIVER_INCL_PATH) $(IFXOS_INCLUDE_PATH) -I@abs_srcdir@/include -I$(PWD)/include" >> $(PWD)/Kbuild $(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules clean-generic: ---- a/src/include/drv_dsl_cpe_os_linux.h -+++ b/src/include/drv_dsl_cpe_os_linux.h -@@ -16,8 +16,6 @@ - extern "C" { - #endif - --#include --#include - #include - #include - #include -@@ -26,8 +24,10 @@ - #include - #include - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -- #include -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) -+#include -+#else -+#include - #endif - - #include -@@ -39,7 +39,8 @@ - #include - #include - #include --#include -+//#include -+#include - - #ifdef INCLUDE_DSL_CPE_API_IFXOS_SUPPORT - /** IFXOS includes*/ diff --git a/package/kernel/lantiq/ltq-adsl/patches/120-platform.patch b/package/kernel/lantiq/ltq-adsl/patches/120-platform.patch index 48c7581e4..20c1ccf47 100644 --- a/package/kernel/lantiq/ltq-adsl/patches/120-platform.patch +++ b/package/kernel/lantiq/ltq-adsl/patches/120-platform.patch @@ -1,7 +1,5 @@ -Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c -=================================================================== ---- drv_dsl_cpe_api-3.24.4.4.orig/src/common/drv_dsl_cpe_os_linux.c 2012-12-07 21:22:58.020256076 +0100 -+++ drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c 2012-12-07 21:31:13.156268489 +0100 +--- a/src/common/drv_dsl_cpe_os_linux.c ++++ b/src/common/drv_dsl_cpe_os_linux.c @@ -12,6 +12,7 @@ #define DSL_INTERN @@ -10,7 +8,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c #include "drv_dsl_cpe_api.h" #include "drv_dsl_cpe_api_ioctl.h" -@@ -1063,7 +1064,7 @@ +@@ -1063,7 +1064,7 @@ static void DSL_DRV_DebugInit(void) #endif /* Entry point of driver */ @@ -19,7 +17,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c { struct class *dsl_class; DSL_int_t i; -@@ -1117,7 +1118,7 @@ +@@ -1117,7 +1118,7 @@ int __init DSL_ModuleInit(void) return 0; } @@ -28,7 +26,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c { printk("Module will be unloaded"DSL_DRV_CRLF); -@@ -1132,7 +1133,7 @@ +@@ -1132,7 +1133,7 @@ void __exit DSL_ModuleCleanup(void) (DSL_uint8_t**)&g_BndFpgaBase); #endif /* defined(INCLUDE_DSL_CPE_API_VINAX) && defined(INCLUDE_DSL_BONDING)*/ @@ -37,7 +35,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c } #ifndef _lint -@@ -1148,8 +1149,30 @@ +@@ -1148,8 +1149,30 @@ module_param(debug_level, byte, 0); MODULE_PARM_DESC(debug_level, "set to get more (1) or fewer (4) debug outputs"); #endif /* #ifndef DSL_DEBUG_DISABLE*/ diff --git a/package/kernel/lantiq/ltq-adsl/patches/130-linux3.8.patch b/package/kernel/lantiq/ltq-adsl/patches/130-linux3.8.patch index bf758e0a9..3e2d8dcc2 100644 --- a/package/kernel/lantiq/ltq-adsl/patches/130-linux3.8.patch +++ b/package/kernel/lantiq/ltq-adsl/patches/130-linux3.8.patch @@ -1,7 +1,5 @@ -Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c -=================================================================== ---- drv_dsl_cpe_api-3.24.4.4.orig/src/common/drv_dsl_cpe_os_linux.c 2013-03-14 11:44:50.318326078 +0100 -+++ drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c 2013-03-14 11:46:08.562329425 +0100 +--- a/src/common/drv_dsl_cpe_os_linux.c ++++ b/src/common/drv_dsl_cpe_os_linux.c @@ -11,6 +11,7 @@ #ifdef __LINUX__ @@ -10,7 +8,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c #include #include -@@ -40,7 +41,7 @@ +@@ -40,7 +41,7 @@ static DSL_ssize_t DSL_DRV_Write(DSL_DRV static DSL_int_t DSL_DRV_Ioctls(DSL_DRV_inode_t * pINode, DSL_DRV_file_t * pFile, DSL_uint_t nCommand, unsigned long nArg); #else @@ -19,7 +17,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c DSL_uint_t nCommand, unsigned long nArg); #endif static int DSL_DRV_Open(DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil); -@@ -184,7 +185,7 @@ +@@ -184,7 +185,7 @@ static DSL_int_t DSL_DRV_Ioctls(DSL_DRV_ DSL_uint_t nCommand, unsigned long nArg) #else @@ -28,7 +26,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c DSL_DRV_file_t * pFile, DSL_uint_t nCommand, unsigned long nArg) -@@ -521,9 +522,9 @@ +@@ -521,9 +522,9 @@ DSL_void_t* DSL_IoctlMemCpyTo( - IFX_SUCCESS on success - IFX_ERROR on error */ @@ -40,7 +38,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c DSL_int32_t retVal = -1; #ifndef _lint -@@ -546,30 +547,6 @@ +@@ -546,30 +547,6 @@ DSL_DRV_STATIC DSL_int32_t DSL_DRV_Kerne (DSL_NULL, "ENTER - Kernel Thread Startup <%s>" DSL_DRV_CRLF, pThrCntrl->thrParams.pName)); @@ -71,7 +69,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c /*DSL_DRV_ThreadPriorityModify(pThrCntrl->nPriority);*/ pThrCntrl->thrParams.bRunning = 1; -@@ -639,9 +616,7 @@ +@@ -639,9 +616,7 @@ DSL_int32_t DSL_DRV_ThreadInit( init_completion(&pThrCntrl->thrCompletion); /* start kernel thread via the wrapper function */ @@ -82,7 +80,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c pThrCntrl->bValid = DSL_TRUE; -@@ -1064,12 +1039,12 @@ +@@ -1064,12 +1039,12 @@ static void DSL_DRV_DebugInit(void) #endif /* Entry point of driver */ @@ -97,7 +95,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c &(dsl_cpe_api_version[4])); DSL_DRV_MemSet( ifxDevices, 0, sizeof(DSL_devCtx_t) * DSL_DRV_MAX_DEVICE_NUMBER ); -@@ -1118,7 +1093,7 @@ +@@ -1118,7 +1093,7 @@ static int __devinit ltq_adsl_probe(stru return 0; } @@ -106,7 +104,7 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c { printk("Module will be unloaded"DSL_DRV_CRLF); -@@ -1163,7 +1138,7 @@ +@@ -1163,7 +1138,7 @@ MODULE_DEVICE_TABLE(of, ltq_adsl_match); static struct platform_driver ltq_adsl_driver = { .probe = ltq_adsl_probe, @@ -115,11 +113,9 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/common/drv_dsl_cpe_os_linux.c .driver = { .name = "adsl", .owner = THIS_MODULE, -Index: drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_os_lint_map.h -=================================================================== ---- drv_dsl_cpe_api-3.24.4.4.orig/src/include/drv_dsl_cpe_os_lint_map.h 2009-02-24 21:44:54.000000000 +0100 -+++ drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_os_lint_map.h 2013-03-14 11:44:50.330326079 +0100 -@@ -247,7 +247,7 @@ +--- a/src/include/drv_dsl_cpe_os_lint_map.h ++++ b/src/include/drv_dsl_cpe_os_lint_map.h +@@ -247,7 +247,7 @@ typedef struct DSL_DRV_ThreadFunction_t pThrFct; /** Kernel thread process ID */ @@ -128,11 +124,9 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_os_lint_map.h /** requested kernel thread priority */ DSL_int32_t nPriority; -Index: drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_os_linux.h -=================================================================== ---- drv_dsl_cpe_api-3.24.4.4.orig/src/include/drv_dsl_cpe_os_linux.h 2013-03-14 11:44:50.298326077 +0100 -+++ drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_os_linux.h 2013-03-14 11:44:50.330326079 +0100 -@@ -288,7 +288,7 @@ +--- a/src/include/drv_dsl_cpe_os_linux.h ++++ b/src/include/drv_dsl_cpe_os_linux.h +@@ -288,7 +288,7 @@ typedef struct DSL_DRV_ThreadFunction_t pThrFct; /** Kernel thread process ID */ diff --git a/package/kernel/lantiq/ltq-adsl/patches/140-linux_3.18.patch b/package/kernel/lantiq/ltq-adsl/patches/140-linux_3.18.patch index 1d1e5669a..668732ff0 100644 --- a/package/kernel/lantiq/ltq-adsl/patches/140-linux_3.18.patch +++ b/package/kernel/lantiq/ltq-adsl/patches/140-linux_3.18.patch @@ -1,6 +1,6 @@ --- a/src/include/drv_dsl_cpe_os_linux.h +++ b/src/include/drv_dsl_cpe_os_linux.h -@@ -214,12 +214,25 @@ static inline int dsl_mutex_lock(struct +@@ -214,12 +214,25 @@ static inline int dsl_mutex_lock(struct #define DSL_DRV_MUTEX_LOCK(id) down_interruptible(&(id)) #define DSL_DRV_MUTEX_UNLOCK(id) up(&(id)) #endif diff --git a/package/kernel/lantiq/ltq-atm/src/ifxmips_atm_core.h b/package/kernel/lantiq/ltq-atm/src/ifxmips_atm_core.h index 2f754c982..398be7d82 100644 --- a/package/kernel/lantiq/ltq-atm/src/ifxmips_atm_core.h +++ b/package/kernel/lantiq/ltq-atm/src/ifxmips_atm_core.h @@ -43,6 +43,7 @@ struct ltq_atm_ops { void (*fw_ver)(unsigned int *major, unsigned int *minor); }; +#include #include /* @@ -195,6 +196,7 @@ struct connection { volatile struct tx_descriptor *tx_desc; unsigned int tx_desc_pos; struct sk_buff **tx_skb; + spinlock_t lock; unsigned int aal5_vcc_crc_err; /* number of packets with CRC error */ unsigned int aal5_vcc_oversize_sdu; /* number of packets with oversize error */ diff --git a/package/kernel/lantiq/ltq-atm/src/ltq_atm.c b/package/kernel/lantiq/ltq-atm/src/ltq_atm.c index a08fa22ce..a8f787fdc 100644 --- a/package/kernel/lantiq/ltq-atm/src/ltq_atm.c +++ b/package/kernel/lantiq/ltq-atm/src/ltq_atm.c @@ -19,6 +19,8 @@ ** HISTORY ** $Date $Author $Comment ** 07 JUL 2009 Xu Liang Init Version +** +** Copyright 2017 Alexander Couzens *******************************************************************************/ #define IFX_ATM_VER_MAJOR 1 @@ -189,8 +191,6 @@ struct sk_buff* atm_alloc_tx(struct atm_vcc *, unsigned int); static inline void atm_free_tx_skb_vcc(struct sk_buff *, struct atm_vcc *); static inline struct sk_buff *get_skb_rx_pointer(unsigned int); static inline int get_tx_desc(unsigned int); -static struct sk_buff* skb_duplicate(struct sk_buff *); -static struct sk_buff* skb_break_away_from_protocol(struct sk_buff *); /* * mailbox handler and signal function @@ -444,6 +444,9 @@ static int ppe_open(struct atm_vcc *vcc) /* set htu entry */ set_htu_entry(vpi, vci, conn, vcc->qos.aal == ATM_AAL5 ? 1 : 0, 0); + *MBOX_IGU1_ISRC |= (1 << (conn + FIRST_QSB_QID + 16)); + *MBOX_IGU1_IER |= (1 << (conn + FIRST_QSB_QID + 16)); + ret = 0; PPE_OPEN_EXIT: @@ -511,14 +514,17 @@ static int ppe_send(struct atm_vcc *vcc, struct sk_buff *skb) int ret; int conn; int desc_base; + int byteoff; + int required; + /* the len of the data without offset and header */ + int datalen; + unsigned long flags; struct tx_descriptor reg_desc = {0}; - struct sk_buff *new_skb; + struct tx_inband_header *header; if ( vcc == NULL || skb == NULL ) return -EINVAL; - skb_get(skb); - atm_free_tx_skb_vcc(skb, vcc); conn = find_vcc(vcc); if ( conn < 0 ) { @@ -532,31 +538,28 @@ static int ppe_send(struct atm_vcc *vcc, struct sk_buff *skb) goto PPE_SEND_FAIL; } - if ( vcc->qos.aal == ATM_AAL5 ) { - int byteoff; - int datalen; - struct tx_inband_header *header; + byteoff = (unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1); + required = sizeof(*header) + byteoff; + if (!skb_clone_writable(skb, required)) { + int expand_by = 0; + int ret; - byteoff = (unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1); - if ( skb_headroom(skb) < byteoff + TX_INBAND_HEADER_LENGTH ) - new_skb = skb_duplicate(skb); - else - new_skb = skb_break_away_from_protocol(skb); - if ( new_skb == NULL ) { - pr_err("either skb_duplicate or skb_break_away_from_protocol fail\n"); - ret = -ENOMEM; - goto PPE_SEND_FAIL; + if (skb_headroom(skb) < required) + expand_by = required - skb_headroom(skb); + + ret = pskb_expand_head(skb, expand_by, 0, GFP_ATOMIC); + if (ret) { + printk("pskb_expand_head failed.\n"); + atm_free_tx_skb_vcc(skb, vcc); + return ret; } - dev_kfree_skb_any(skb); - skb = new_skb; + } - datalen = skb->len; - byteoff = (unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1); + datalen = skb->len; + header = (void *)skb_push(skb, byteoff + TX_INBAND_HEADER_LENGTH); - skb_push(skb, byteoff + TX_INBAND_HEADER_LENGTH); - - header = (struct tx_inband_header *)skb->data; + if ( vcc->qos.aal == ATM_AAL5 ) { /* setup inband trailer */ header->uu = 0; header->cpi = 0; @@ -576,23 +579,9 @@ static int ppe_send(struct atm_vcc *vcc, struct sk_buff *skb) reg_desc.byteoff = byteoff; reg_desc.iscell = 0; } else { - /* if data pointer is not aligned, allocate new sk_buff */ - if ( ((unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1)) != 0 ) { - pr_err("skb->data not aligned\n"); - new_skb = skb_duplicate(skb); - } else - new_skb = skb_break_away_from_protocol(skb); - if ( new_skb == NULL ) { - pr_err("either skb_duplicate or skb_break_away_from_protocol fail\n"); - ret = -ENOMEM; - goto PPE_SEND_FAIL; - } - dev_kfree_skb_any(skb); - skb = new_skb; - reg_desc.dataptr = (unsigned int)skb->data >> 2; reg_desc.datalen = skb->len; - reg_desc.byteoff = 0; + reg_desc.byteoff = byteoff; reg_desc.iscell = 1; } @@ -600,23 +589,25 @@ static int ppe_send(struct atm_vcc *vcc, struct sk_buff *skb) reg_desc.c = 1; reg_desc.sop = reg_desc.eop = 1; + spin_lock_irqsave(&g_atm_priv_data.conn[conn].lock, flags); desc_base = get_tx_desc(conn); if ( desc_base < 0 ) { + spin_unlock_irqrestore(&g_atm_priv_data.conn[conn].lock, flags); pr_debug("ALLOC_TX_CONNECTION_FAIL\n"); ret = -EIO; goto PPE_SEND_FAIL; } - - if ( vcc->stats ) - atomic_inc(&vcc->stats->tx); - if ( vcc->qos.aal == ATM_AAL5 ) - g_atm_priv_data.wtx_pdu++; - /* update descriptor send pointer */ if ( g_atm_priv_data.conn[conn].tx_skb[desc_base] != NULL ) dev_kfree_skb_any(g_atm_priv_data.conn[conn].tx_skb[desc_base]); g_atm_priv_data.conn[conn].tx_skb[desc_base] = skb; + spin_unlock_irqrestore(&g_atm_priv_data.conn[conn].lock, flags); + + if ( vcc->stats ) + atomic_inc(&vcc->stats->tx); + if ( vcc->qos.aal == ATM_AAL5 ) + g_atm_priv_data.wtx_pdu++; /* write discriptor to memory and write back cache */ g_atm_priv_data.conn[conn].tx_desc[desc_base] = reg_desc; dma_cache_wback((unsigned long)skb->data, skb->len); @@ -821,7 +812,11 @@ struct sk_buff* atm_alloc_tx(struct atm_vcc *vcc, unsigned int size) return NULL; } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)) + refcount_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); +#else atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); +#endif return skb; } @@ -862,42 +857,40 @@ static inline int get_tx_desc(unsigned int conn) return desc_base; } -static struct sk_buff* skb_duplicate(struct sk_buff *skb) +static void free_tx_ring(unsigned int queue) { - struct sk_buff *new_skb; + unsigned long flags; + int i; + struct connection *conn = &g_atm_priv_data.conn[queue]; + struct sk_buff *skb; - new_skb = alloc_skb_tx(skb->len); - if ( new_skb == NULL ) - return NULL; + if (!conn) + return; - skb_put(new_skb, skb->len); - memcpy(new_skb->data, skb->data, skb->len); + spin_lock_irqsave(&conn->lock, flags); - return new_skb; + for (i = 0; i < dma_tx_descriptor_length; i++) { + if (conn->tx_desc[i].own == 0 && conn->tx_skb[i] != NULL) { + skb = conn->tx_skb[i]; + conn->tx_skb[i] = NULL; + atm_free_tx_skb_vcc(skb, ATM_SKB(skb)->vcc); + } + } + spin_unlock_irqrestore(&conn->lock, flags); } -static struct sk_buff* skb_break_away_from_protocol(struct sk_buff *skb) +static void mailbox_tx_handler(unsigned int queue_bitmap) { - struct sk_buff *new_skb; + int i; + int bit; - if ( skb_shared(skb) ) { - new_skb = skb_clone(skb, GFP_ATOMIC); - if ( new_skb == NULL ) - return NULL; - } else - new_skb = skb_get(skb); + /* only get valid queues */ + queue_bitmap &= g_atm_priv_data.conn_table; - skb_dst_drop(new_skb); -#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) - nf_conntrack_put(new_skb->nfct); - new_skb->nfct = NULL; - #ifdef CONFIG_BRIDGE_NETFILTER - nf_bridge_put(new_skb->nf_bridge); - new_skb->nf_bridge = NULL; - #endif -#endif - - return new_skb; + for ( i = 0, bit = 1; i < MAX_PVC_NUMBER; i++, bit <<= 1 ) { + if (queue_bitmap & bit) + free_tx_ring(i); + } } static inline void mailbox_oam_rx_handler(void) @@ -1050,12 +1043,22 @@ static inline void mailbox_aal_rx_handler(void) static void do_ppe_tasklet(unsigned long data) { + unsigned int irqs = *MBOX_IGU1_ISR; *MBOX_IGU1_ISRC = *MBOX_IGU1_ISR; - mailbox_oam_rx_handler(); - mailbox_aal_rx_handler(); + + if (irqs & (1 << RX_DMA_CH_AAL)) + mailbox_aal_rx_handler(); + if (irqs & (1 << RX_DMA_CH_OAM)) + mailbox_oam_rx_handler(); + + /* any valid tx irqs */ + if ((irqs >> (FIRST_QSB_QID + 16)) & g_atm_priv_data.conn_table) + mailbox_tx_handler(irqs >> (FIRST_QSB_QID + 16)); if ((*MBOX_IGU1_ISR & ((1 << RX_DMA_CH_AAL) | (1 << RX_DMA_CH_OAM))) != 0) tasklet_schedule(&g_dma_tasklet); + else if (*MBOX_IGU1_ISR >> (FIRST_QSB_QID + 16)) /* TX queue */ + tasklet_schedule(&g_dma_tasklet); else enable_irq(PPE_MAILBOX_IGU1_INT); } @@ -1512,6 +1515,7 @@ static inline int init_priv_data(void) p_tx_desc = (volatile struct tx_descriptor *)((((unsigned int)g_atm_priv_data.tx_desc_base + DESC_ALIGNMENT - 1) & ~(DESC_ALIGNMENT - 1)) | KSEG1); ppskb = (struct sk_buff **)(((unsigned int)g_atm_priv_data.tx_skb_base + 3) & ~3); for ( i = 0; i < MAX_PVC_NUMBER; i++ ) { + spin_lock_init(&g_atm_priv_data.conn[i].lock); g_atm_priv_data.conn[i].tx_desc = &p_tx_desc[i * dma_tx_descriptor_length]; g_atm_priv_data.conn[i].tx_skb = &ppskb[i * dma_tx_descriptor_length]; } @@ -1799,7 +1803,6 @@ static int ltq_atm_probe(struct platform_device *pdev) int ret; int port_num; struct port_cell_info port_cell = {0}; - int i, j; char ver_str[256]; match = of_match_device(ltq_atm_match, &pdev->dev); diff --git a/package/kernel/lantiq/ltq-deu/src/ifxmips_aes.c b/package/kernel/lantiq/ltq-deu/src/ifxmips_aes.c index b51cf4702..6c8d065d8 100644 --- a/package/kernel/lantiq/ltq-deu/src/ifxmips_aes.c +++ b/package/kernel/lantiq/ltq-deu/src/ifxmips_aes.c @@ -885,12 +885,12 @@ struct crypto_alg ifxdeu_ctr_rfc3686_aes_alg = { }; -/*! \fn int __init ifxdeu_init_aes (void) +/*! \fn int ifxdeu_init_aes (void) * \ingroup IFX_AES_FUNCTIONS * \brief function to initialize AES driver * \return ret */ -int __init ifxdeu_init_aes (void) +int ifxdeu_init_aes (void) { int ret = -ENOSYS; @@ -952,11 +952,11 @@ aes_err: return ret; } -/*! \fn void __exit ifxdeu_fini_aes (void) +/*! \fn void ifxdeu_fini_aes (void) * \ingroup IFX_AES_FUNCTIONS * \brief unregister aes driver */ -void __exit ifxdeu_fini_aes (void) +void ifxdeu_fini_aes (void) { crypto_unregister_alg (&ifxdeu_aes_alg); crypto_unregister_alg (&ifxdeu_ecb_aes_alg); diff --git a/package/kernel/lantiq/ltq-deu/src/ifxmips_arc4.c b/package/kernel/lantiq/ltq-deu/src/ifxmips_arc4.c index d0818dd0c..9faad9401 100644 --- a/package/kernel/lantiq/ltq-deu/src/ifxmips_arc4.c +++ b/package/kernel/lantiq/ltq-deu/src/ifxmips_arc4.c @@ -343,11 +343,11 @@ static struct crypto_alg ifxdeu_ecb_arc4_alg = { } }; -/*! \fn int __init ifxdeu_init_arc4(void) +/*! \fn int ifxdeu_init_arc4(void) \ingroup IFX_ARC4_FUNCTIONS \brief initialize arc4 driver */ -int __init ifxdeu_init_arc4(void) +int ifxdeu_init_arc4(void) { int ret = -ENOSYS; @@ -376,11 +376,11 @@ ecb_arc4_err: } -/*! \fn void __exit ifxdeu_fini_arc4(void) +/*! \fn void ifxdeu_fini_arc4(void) \ingroup IFX_ARC4_FUNCTIONS \brief unregister arc4 driver */ -void __exit ifxdeu_fini_arc4(void) +void ifxdeu_fini_arc4(void) { crypto_unregister_alg (&ifxdeu_arc4_alg); crypto_unregister_alg (&ifxdeu_ecb_arc4_alg); diff --git a/package/kernel/lantiq/ltq-deu/src/ifxmips_des.c b/package/kernel/lantiq/ltq-deu/src/ifxmips_des.c index 5b73b6a28..beb67075e 100644 --- a/package/kernel/lantiq/ltq-deu/src/ifxmips_des.c +++ b/package/kernel/lantiq/ltq-deu/src/ifxmips_des.c @@ -682,11 +682,11 @@ struct crypto_alg ifxdeu_cbc_des3_ede_alg = { } }; -/*! \fn int __init ifxdeu_init_des (void) +/*! \fn int ifxdeu_init_des (void) * \ingroup IFX_DES_FUNCTIONS * \brief initialize des driver */ -int __init ifxdeu_init_des (void) +int ifxdeu_init_des (void) { int ret = -ENOSYS; @@ -761,11 +761,11 @@ cbc_des3_ede_err: } -/*! \fn void __exit ifxdeu_fini_des (void) +/*! \fn void ifxdeu_fini_des (void) * \ingroup IFX_DES_FUNCTIONS * \brief unregister des driver */ -void __exit ifxdeu_fini_des (void) +void ifxdeu_fini_des (void) { crypto_unregister_alg (&ifxdeu_des_alg); crypto_unregister_alg (&ifxdeu_ecb_des_alg); diff --git a/package/kernel/lantiq/ltq-deu/src/ifxmips_deu.h b/package/kernel/lantiq/ltq-deu/src/ifxmips_deu.h index c842d64c1..8045c2081 100644 --- a/package/kernel/lantiq/ltq-deu/src/ifxmips_deu.h +++ b/package/kernel/lantiq/ltq-deu/src/ifxmips_deu.h @@ -108,23 +108,23 @@ */ -int __init ifxdeu_init_des (void); -int __init ifxdeu_init_aes (void); -int __init ifxdeu_init_arc4 (void); -int __init ifxdeu_init_sha1 (void); -int __init ifxdeu_init_md5 (void); -int __init ifxdeu_init_sha1_hmac (void); -int __init ifxdeu_init_md5_hmac (void); +int ifxdeu_init_des (void); +int ifxdeu_init_aes (void); +int ifxdeu_init_arc4 (void); +int ifxdeu_init_sha1 (void); +int ifxdeu_init_md5 (void); +int ifxdeu_init_sha1_hmac (void); +int ifxdeu_init_md5_hmac (void); int __init lqdeu_async_aes_init(void); int __init lqdeu_async_des_init(void); -void __exit ifxdeu_fini_des (void); -void __exit ifxdeu_fini_aes (void); -void __exit ifxdeu_fini_arc4 (void); -void __exit ifxdeu_fini_sha1 (void); -void __exit ifxdeu_fini_md5 (void); -void __exit ifxdeu_fini_sha1_hmac (void); -void __exit ifxdeu_fini_md5_hmac (void); +void ifxdeu_fini_des (void); +void ifxdeu_fini_aes (void); +void ifxdeu_fini_arc4 (void); +void ifxdeu_fini_sha1 (void); +void ifxdeu_fini_md5 (void); +void ifxdeu_fini_sha1_hmac (void); +void ifxdeu_fini_md5_hmac (void); void __exit ifxdeu_fini_dma(void); void __exit lqdeu_fini_async_aes(void); void __exit lqdeu_fini_async_des(void); diff --git a/package/kernel/lantiq/ltq-deu/src/ifxmips_deu_dma.h b/package/kernel/lantiq/ltq-deu/src/ifxmips_deu_dma.h index fde7a900b..b64d74776 100644 --- a/package/kernel/lantiq/ltq-deu/src/ifxmips_deu_dma.h +++ b/package/kernel/lantiq/ltq-deu/src/ifxmips_deu_dma.h @@ -39,6 +39,7 @@ #include #include #include +#include // must match the size of memory block allocated for g_dma_block and g_dma_block2 #define DEU_MAX_PACKET_SIZE (PAGE_SIZE >> 1) @@ -53,7 +54,11 @@ typedef struct ifx_deu_device { int recv_count; int packet_size; int packet_num; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)) + wait_queue_entry_t wait; +#else wait_queue_t wait; +#endif } _ifx_deu_device; extern _ifx_deu_device ifx_deu[1]; diff --git a/package/kernel/lantiq/ltq-deu/src/ifxmips_md5.c b/package/kernel/lantiq/ltq-deu/src/ifxmips_md5.c index 47e1f4933..55cea1cce 100644 --- a/package/kernel/lantiq/ltq-deu/src/ifxmips_md5.c +++ b/package/kernel/lantiq/ltq-deu/src/ifxmips_md5.c @@ -276,11 +276,11 @@ static struct shash_alg ifxdeu_md5_alg = { } }; -/*! \fn int __init ifxdeu_init_md5 (void) +/*! \fn int ifxdeu_init_md5 (void) * \ingroup IFX_MD5_FUNCTIONS * \brief initialize md5 driver */ -int __init ifxdeu_init_md5 (void) +int ifxdeu_init_md5 (void) { int ret = -ENOSYS; @@ -298,12 +298,12 @@ md5_err: return ret; } -/*! \fn void __exit ifxdeu_fini_md5 (void) +/*! \fn void ifxdeu_fini_md5 (void) * \ingroup IFX_MD5_FUNCTIONS * \brief unregister md5 driver */ -void __exit ifxdeu_fini_md5 (void) +void ifxdeu_fini_md5 (void) { crypto_unregister_shash(&ifxdeu_md5_alg); diff --git a/package/kernel/lantiq/ltq-deu/src/ifxmips_md5_hmac.c b/package/kernel/lantiq/ltq-deu/src/ifxmips_md5_hmac.c index ef2f6aa76..46797c972 100644 --- a/package/kernel/lantiq/ltq-deu/src/ifxmips_md5_hmac.c +++ b/package/kernel/lantiq/ltq-deu/src/ifxmips_md5_hmac.c @@ -352,11 +352,11 @@ static struct shash_alg ifxdeu_md5_hmac_alg = { } }; -/*! \fn int __init ifxdeu_init_md5_hmac (void) +/*! \fn int ifxdeu_init_md5_hmac (void) * \ingroup IFX_MD5_HMAC_FUNCTIONS * \brief initialize md5 hmac driver */ -int __init ifxdeu_init_md5_hmac (void) +int ifxdeu_init_md5_hmac (void) { int ret = -ENOSYS; @@ -375,11 +375,11 @@ md5_hmac_err: return ret; } -/** \fn void __exit ifxdeu_fini_md5_hmac (void) +/** \fn void ifxdeu_fini_md5_hmac (void) * \ingroup IFX_MD5_HMAC_FUNCTIONS * \brief unregister md5 hmac driver */ -void __exit ifxdeu_fini_md5_hmac (void) +void ifxdeu_fini_md5_hmac (void) { crypto_unregister_shash(&ifxdeu_md5_hmac_alg); } diff --git a/package/kernel/lantiq/ltq-deu/src/ifxmips_sha1.c b/package/kernel/lantiq/ltq-deu/src/ifxmips_sha1.c index 147157464..968dc6fb6 100644 --- a/package/kernel/lantiq/ltq-deu/src/ifxmips_sha1.c +++ b/package/kernel/lantiq/ltq-deu/src/ifxmips_sha1.c @@ -266,11 +266,11 @@ static struct shash_alg ifxdeu_sha1_alg = { }; -/*! \fn int __init ifxdeu_init_sha1 (void) +/*! \fn int ifxdeu_init_sha1 (void) * \ingroup IFX_SHA1_FUNCTIONS * \brief initialize sha1 driver */ -int __init ifxdeu_init_sha1 (void) +int ifxdeu_init_sha1 (void) { int ret = -ENOSYS; @@ -288,11 +288,11 @@ sha1_err: return ret; } -/*! \fn void __exit ifxdeu_fini_sha1 (void) +/*! \fn void ifxdeu_fini_sha1 (void) * \ingroup IFX_SHA1_FUNCTIONS * \brief unregister sha1 driver */ -void __exit ifxdeu_fini_sha1 (void) +void ifxdeu_fini_sha1 (void) { crypto_unregister_shash(&ifxdeu_sha1_alg); diff --git a/package/kernel/lantiq/ltq-deu/src/ifxmips_sha1_hmac.c b/package/kernel/lantiq/ltq-deu/src/ifxmips_sha1_hmac.c index 7287a82f5..791b96675 100644 --- a/package/kernel/lantiq/ltq-deu/src/ifxmips_sha1_hmac.c +++ b/package/kernel/lantiq/ltq-deu/src/ifxmips_sha1_hmac.c @@ -342,11 +342,11 @@ static struct shash_alg ifxdeu_sha1_hmac_alg = { }; -/*! \fn int __init ifxdeu_init_sha1_hmac (void) +/*! \fn int ifxdeu_init_sha1_hmac (void) * \ingroup IFX_SHA1_HMAC_FUNCTIONS * \brief initialize sha1 hmac driver */ -int __init ifxdeu_init_sha1_hmac (void) +int ifxdeu_init_sha1_hmac (void) { int ret = -ENOSYS; @@ -365,11 +365,11 @@ sha1_err: return ret; } -/*! \fn void __exit ifxdeu_fini_sha1_hmac (void) +/*! \fn void ifxdeu_fini_sha1_hmac (void) * \ingroup IFX_SHA1_HMAC_FUNCTIONS * \brief unregister sha1 hmac driver */ -void __exit ifxdeu_fini_sha1_hmac (void) +void ifxdeu_fini_sha1_hmac (void) { crypto_unregister_shash(&ifxdeu_sha1_hmac_alg); diff --git a/package/kernel/lantiq/ltq-ifxos/Makefile b/package/kernel/lantiq/ltq-ifxos/Makefile index a0891be3e..4771fda20 100644 --- a/package/kernel/lantiq/ltq-ifxos/Makefile +++ b/package/kernel/lantiq/ltq-ifxos/Makefile @@ -8,7 +8,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=lib_ifxos PKG_VERSION:=1.5.19 -PKG_RELEASE:=3 +PKG_RELEASE:=4 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) PKG_SOURCE_URL:=https://github.com/xdarklight/$(PKG_NAME)/archive/v$(PKG_VERSION) @@ -17,8 +17,7 @@ PKG_MAINTAINER:=John Crispin PKG_LICENSE:=GPL-2.0 BSD-2-Clause PKG_LICENSE_FILES:=LICENSE - -PKG_USE_MIPS16:=0 +PKG_ASLR_PIE:=0 PKG_FIXUP:=autoreconf include $(INCLUDE_DIR)/package.mk diff --git a/package/kernel/lantiq/ltq-ifxos/patches/002-fix-compile.patch b/package/kernel/lantiq/ltq-ifxos/patches/002-fix-compile.patch new file mode 100644 index 000000000..38722290d --- /dev/null +++ b/package/kernel/lantiq/ltq-ifxos/patches/002-fix-compile.patch @@ -0,0 +1,22 @@ +--- a/src/linux/ifxos_linux_copy_user_space_drv.c ++++ b/src/linux/ifxos_linux_copy_user_space_drv.c +@@ -29,7 +29,7 @@ + #ifdef MODULE + #include + #endif +-#include ++#include + + #include "ifx_types.h" + #include "ifxos_rt_if_check.h" +--- a/src/linux/ifxos_linux_socket_drv.c ++++ b/src/linux/ifxos_linux_socket_drv.c +@@ -25,7 +25,7 @@ + #endif + #include + #include +-#include ++#include + + #include "ifx_types.h" + #include "ifxos_rt_if_check.h" diff --git a/package/kernel/lantiq/ltq-ifxos/patches/020-no-O3.patch b/package/kernel/lantiq/ltq-ifxos/patches/020-no-O3.patch new file mode 100644 index 000000000..d2e816f5c --- /dev/null +++ b/package/kernel/lantiq/ltq-ifxos/patches/020-no-O3.patch @@ -0,0 +1,19 @@ +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -45,8 +45,6 @@ endif !HAVE_GCC + + if ENABLE_DEBUG + used_gcc_cflags += -O1 -g +-else +-used_gcc_cflags += -O3 + endif + + AM_CFLAGS = \ +@@ -92,7 +90,6 @@ endif + drvifxos_additional_cflags=\ + -DLINUX \ + -D__LINUX__ \ +- -O \ + -D__KERNEL__ \ + -DMODULE \ + -DEXPORT_SYMTAB diff --git a/package/kernel/lantiq/ltq-ifxos/patches/200-Fix-app-compilation-failure-from-inclusion-of-wrong-.patch b/package/kernel/lantiq/ltq-ifxos/patches/200-Fix-app-compilation-failure-from-inclusion-of-wrong-.patch index dee3482e4..5d661db86 100644 --- a/package/kernel/lantiq/ltq-ifxos/patches/200-Fix-app-compilation-failure-from-inclusion-of-wrong-.patch +++ b/package/kernel/lantiq/ltq-ifxos/patches/200-Fix-app-compilation-failure-from-inclusion-of-wrong-.patch @@ -37,8 +37,6 @@ Ref: https://bugs.lede-project.org/index.php?do=details&task_id=1196 src/Makefile.am | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) -diff --git a/src/Makefile.am b/src/Makefile.am -index f95668f..d232e7f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,11 +14,7 @@ lib_LIBRARIES = libifxos.a @@ -54,6 +52,3 @@ index f95668f..d232e7f 100644 if HAVE_GCC --- -1.8.3.1 - diff --git a/package/kernel/lantiq/ltq-ptm/src/ifxmips_ptm_adsl.c b/package/kernel/lantiq/ltq-ptm/src/ifxmips_ptm_adsl.c index f764eba1f..43e171a2b 100644 --- a/package/kernel/lantiq/ltq-ptm/src/ifxmips_ptm_adsl.c +++ b/package/kernel/lantiq/ltq-ptm/src/ifxmips_ptm_adsl.c @@ -128,7 +128,9 @@ static int ptm_stop(struct net_device *); static unsigned int ptm_poll(int, unsigned int); static int ptm_napi_poll(struct napi_struct *, int); static int ptm_hard_start_xmit(struct sk_buff *, struct net_device *); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0)) static int ptm_change_mtu(struct net_device *, int); +#endif static int ptm_ioctl(struct net_device *, struct ifreq *, int); static void ptm_tx_timeout(struct net_device *); @@ -247,7 +249,9 @@ static struct net_device_ops g_ptm_netdev_ops = { .ndo_start_xmit = ptm_hard_start_xmit, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0)) .ndo_change_mtu = ptm_change_mtu, +#endif .ndo_do_ioctl = ptm_ioctl, .ndo_tx_timeout = ptm_tx_timeout, }; @@ -285,6 +289,10 @@ static void ptm_setup(struct net_device *dev, int ndev) /* hook network operations */ dev->netdev_ops = &g_ptm_netdev_ops; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) + /* Allow up to 1508 bytes, for RFC4638 */ + dev->max_mtu = ETH_DATA_LEN + 8; +#endif netif_napi_add(dev, &g_ptm_priv_data.itf[ndev].napi, ptm_napi_poll, 25); dev->watchdog_timeo = ETH_WATCHDOG_TIMEOUT; @@ -459,7 +467,7 @@ PTM_HARD_START_XMIT_FAIL: g_ptm_priv_data.itf[ndev].stats.tx_dropped++; return NETDEV_TX_OK; } - +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0)) static int ptm_change_mtu(struct net_device *dev, int mtu) { /* Allow up to 1508 bytes, for RFC4638 */ @@ -468,6 +476,7 @@ static int ptm_change_mtu(struct net_device *dev, int mtu) dev->mtu = mtu; return 0; } +#endif static int ptm_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { @@ -654,7 +663,9 @@ static INLINE int mailbox_rx_irq_handler(unsigned int ch) // return: < 0 - de skb->dev = g_net_dev[ndev]; skb->protocol = eth_type_trans(skb, skb->dev); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0)) g_net_dev[ndev]->last_rx = jiffies; +#endif netif_rx_ret = netif_receive_skb(skb); diff --git a/package/kernel/lantiq/ltq-ptm/src/ifxmips_ptm_vdsl.c b/package/kernel/lantiq/ltq-ptm/src/ifxmips_ptm_vdsl.c index 4e10d72fe..9cfeefd80 100644 --- a/package/kernel/lantiq/ltq-ptm/src/ifxmips_ptm_vdsl.c +++ b/package/kernel/lantiq/ltq-ptm/src/ifxmips_ptm_vdsl.c @@ -74,7 +74,9 @@ static int ptm_stop(struct net_device *); static unsigned int ptm_poll(int, unsigned int); static int ptm_napi_poll(struct napi_struct *, int); static int ptm_hard_start_xmit(struct sk_buff *, struct net_device *); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0)) static int ptm_change_mtu(struct net_device *, int); +#endif static int ptm_ioctl(struct net_device *, struct ifreq *, int); static void ptm_tx_timeout(struct net_device *); @@ -115,7 +117,9 @@ static struct net_device_ops g_ptm_netdev_ops = { .ndo_start_xmit = ptm_hard_start_xmit, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0)) .ndo_change_mtu = ptm_change_mtu, +#endif .ndo_do_ioctl = ptm_ioctl, .ndo_tx_timeout = ptm_tx_timeout, }; @@ -141,6 +145,10 @@ static void ptm_setup(struct net_device *dev, int ndev) netif_carrier_off(dev); dev->netdev_ops = &g_ptm_netdev_ops; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) + /* Allow up to 1508 bytes, for RFC4638 */ + dev->max_mtu = ETH_DATA_LEN + 8; +#endif netif_napi_add(dev, &g_ptm_priv_data.itf[ndev].napi, ptm_napi_poll, 16); dev->watchdog_timeo = ETH_WATCHDOG_TIMEOUT; @@ -218,7 +226,9 @@ static unsigned int ptm_poll(int ndev, unsigned int work_to_do) skb->dev = g_net_dev[0]; skb->protocol = eth_type_trans(skb, skb->dev); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0)) g_net_dev[0]->last_rx = jiffies; +#endif netif_receive_skb(skb); @@ -367,6 +377,7 @@ PTM_HARD_START_XMIT_FAIL: return 0; } +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0)) static int ptm_change_mtu(struct net_device *dev, int mtu) { /* Allow up to 1508 bytes, for RFC4638 */ @@ -375,6 +386,7 @@ static int ptm_change_mtu(struct net_device *dev, int mtu) dev->mtu = mtu; return 0; } +#endif static int ptm_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { diff --git a/package/kernel/lantiq/ltq-tapi/Makefile b/package/kernel/lantiq/ltq-tapi/Makefile index be7fd2aa0..171103350 100644 --- a/package/kernel/lantiq/ltq-tapi/Makefile +++ b/package/kernel/lantiq/ltq-tapi/Makefile @@ -10,14 +10,14 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=drv_tapi PKG_VERSION:=3.13.0 -PKG_RELEASE:=3 +PKG_RELEASE:=4 PKG_SOURCE:=drv_tapi-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources PKG_HASH:=109374d52872716570fca3fef3b93c9a93159a804dfd42484b19152b825af5c0 PKG_MAINTAINER:=John Crispin -PKG_USE_MIPS16:=0 +PKG_ASLR_PIE:=0 PKG_CHECK_FORMAT_SECURITY:=0 PKG_FIXUP:=autoreconf diff --git a/package/kernel/lantiq/ltq-tapi/patches/010-fix-compile.patch b/package/kernel/lantiq/ltq-tapi/patches/010-fix-compile.patch new file mode 100644 index 000000000..051e25d3a --- /dev/null +++ b/package/kernel/lantiq/ltq-tapi/patches/010-fix-compile.patch @@ -0,0 +1,22 @@ +--- a/src/drv_tapi_linux.c ++++ b/src/drv_tapi_linux.c +@@ -54,6 +54,10 @@ + #include /* LINUX 2.6 We need work_struct */ + #include + #include ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,0)) ++ #include ++ #include ++#endif + #undef CONFIG_DEVFS_FS + #ifndef UTS_RELEASE + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) +@@ -184,7 +188,7 @@ MODULE_PARM_DESC(block_egress_tasklet, " + MODULE_PARM_DESC(block_ingress_tasklet, "block the execution of the ingress tasklet, i.e. force to use the RT kernel thread"); + + /** The driver callbacks which will be registered with the kernel*/ +-static struct file_operations tapi_fops = {0}; ++static struct file_operations tapi_fops; + + /* ============================= */ + /* Global function definition */ diff --git a/package/kernel/lantiq/ltq-tapi/patches/020-not-leak-cflags.patch b/package/kernel/lantiq/ltq-tapi/patches/020-not-leak-cflags.patch new file mode 100644 index 000000000..e1aac21f9 --- /dev/null +++ b/package/kernel/lantiq/ltq-tapi/patches/020-not-leak-cflags.patch @@ -0,0 +1,27 @@ +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -122,13 +122,9 @@ endif + + ## flags for the driver + if USE_MODULE +-drv_tapi_CFLAGS = -DLINUX -D__KERNEL__ -DMODULE -Wno-format -DEXPORT_SYMTAB $(AM_CFLAGS) ++drv_tapi_CFLAGS = -DLINUX -D__KERNEL__ -DMODULE -DEXPORT_SYMTAB $(AM_CFLAGS) + else +-drv_tapi_CFLAGS = -DLINUX -D__KERNEL__ -Wno-format -DEXPORT_SYMTAB $(AM_CFLAGS) +-endif +- +-if KERNEL_2_6 +-drv_tapi_CFLAGS += -fno-common ++drv_tapi_CFLAGS = -DLINUX -D__KERNEL__ -DEXPORT_SYMTAB $(AM_CFLAGS) + endif + + +@@ -165,7 +161,7 @@ drv_tapi.ko: $(drv_tapi_SOURCES) $(EXTRA + @echo "# drv_tapi: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild + @echo "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild + @echo "$(subst .ko,,$@)-y := $(drv_tapi_OBJS)" >> $(PWD)/Kbuild +- @echo "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_tapi_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild ++ @echo "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(drv_tapi_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild + $(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules + + clean-generic: diff --git a/package/kernel/lantiq/ltq-tapi/patches/100-ifxmips.patch b/package/kernel/lantiq/ltq-tapi/patches/100-ifxmips.patch index a9c0d8116..f56587d06 100644 --- a/package/kernel/lantiq/ltq-tapi/patches/100-ifxmips.patch +++ b/package/kernel/lantiq/ltq-tapi/patches/100-ifxmips.patch @@ -1,6 +1,6 @@ --- a/src/drv_tapi_linux.c +++ b/src/drv_tapi_linux.c -@@ -552,7 +552,7 @@ static ssize_t ifx_tapi_write (struct fi +@@ -556,7 +556,7 @@ static ssize_t ifx_tapi_write (struct fi IFX_uint8_t *pData; IFX_size_t buf_size; #endif /* TAPI_PACKET */ diff --git a/package/kernel/lantiq/ltq-tapi/patches/200-linux-37.patch b/package/kernel/lantiq/ltq-tapi/patches/200-linux-37.patch index 9d7428df0..fd6133eec 100644 --- a/package/kernel/lantiq/ltq-tapi/patches/200-linux-37.patch +++ b/package/kernel/lantiq/ltq-tapi/patches/200-linux-37.patch @@ -10,7 +10,7 @@ #include #ifdef LINUX_2_6 -@@ -65,7 +67,9 @@ +@@ -69,7 +71,9 @@ #else #include #include @@ -20,7 +20,7 @@ #endif /* LINUX_2_6 */ #include "drv_tapi.h" -@@ -133,8 +137,13 @@ +@@ -137,8 +141,13 @@ static ssize_t ifx_tapi_write(struct fil size_t count, loff_t * ppos); static ssize_t ifx_tapi_read(struct file * filp, char *buf, size_t length, loff_t * ppos); @@ -34,7 +34,7 @@ static unsigned int ifx_tapi_poll (struct file *filp, poll_table *table); #ifdef CONFIG_PROC_FS -@@ -218,7 +227,11 @@ +@@ -222,7 +231,11 @@ IFX_return_t TAPI_OS_RegisterLLDrv (IFX_ IFX_char_t *pRegDrvName = IFX_NULL; IFX_int32_t ret = 0; @@ -46,7 +46,7 @@ { #ifdef MODULE tapi_fops.owner = THIS_MODULE; -@@ -226,7 +239,11 @@ +@@ -230,7 +243,11 @@ IFX_return_t TAPI_OS_RegisterLLDrv (IFX_ tapi_fops.read = ifx_tapi_read; tapi_fops.write = ifx_tapi_write; tapi_fops.poll = ifx_tapi_poll; @@ -58,7 +58,7 @@ tapi_fops.open = ifx_tapi_open; tapi_fops.release = ifx_tapi_release; } -@@ -881,8 +898,13 @@ +@@ -885,8 +902,13 @@ static IFX_uint32_t ifx_tapi_poll (struc - 0 and positive values - success - negative value - ioctl failed */ @@ -72,7 +72,7 @@ { TAPI_FD_PRIV_DATA_t *pTapiPriv; IFX_TAPI_ioctlCtx_t ctx; -@@ -3721,7 +3743,9 @@ +@@ -3725,7 +3747,9 @@ IFX_void_t TAPI_OS_ThreadKill(IFXOS_Thre kernel lock (lock_kernel()). The lock must be grabbed before changing the terminate flag and released after the down() call. */ @@ -83,7 +83,7 @@ mb(); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) kill_proc(pThrCntrl->tid, SIGKILL, 1); -@@ -3729,8 +3753,10 @@ +@@ -3733,8 +3757,10 @@ IFX_void_t TAPI_OS_ThreadKill(IFXOS_Thre kill_pid(find_vpid(pThrCntrl->tid), SIGKILL, 1); #endif /* release the big kernel lock */ diff --git a/package/kernel/lantiq/ltq-tapi/patches/300-linux-310.patch b/package/kernel/lantiq/ltq-tapi/patches/300-linux-310.patch index ac72515ee..2da1719a1 100644 --- a/package/kernel/lantiq/ltq-tapi/patches/300-linux-310.patch +++ b/package/kernel/lantiq/ltq-tapi/patches/300-linux-310.patch @@ -1,8 +1,6 @@ -Index: drv_tapi-3.13.0/src/drv_tapi_linux.c -=================================================================== ---- drv_tapi-3.13.0.orig/src/drv_tapi_linux.c 2013-09-05 22:28:16.868419283 +0200 -+++ drv_tapi-3.13.0/src/drv_tapi_linux.c 2013-09-05 22:32:37.396425814 +0200 -@@ -93,6 +93,8 @@ +--- a/src/drv_tapi_linux.c ++++ b/src/drv_tapi_linux.c +@@ -97,6 +97,8 @@ #include "drv_tapi_announcements.h" #endif /* TAPI_ANNOUNCEMENTS */ diff --git a/package/kernel/lantiq/ltq-vdsl-mei/Makefile b/package/kernel/lantiq/ltq-vdsl-mei/Makefile index 96bbc98c7..9597de007 100644 --- a/package/kernel/lantiq/ltq-vdsl-mei/Makefile +++ b/package/kernel/lantiq/ltq-vdsl-mei/Makefile @@ -9,7 +9,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ltq-vdsl-vr9-mei PKG_VERSION:=1.5.17.6 -PKG_RELEASE:=3 +PKG_RELEASE:=4 PKG_BASE_NAME:=drv_mei_cpe PKG_SOURCE:=$(PKG_BASE_NAME)-$(PKG_VERSION).tar.gz @@ -19,10 +19,10 @@ PKG_HASH:=94f6904364348b7f74087e721968abc28b2564fb9bd8899aa930d36490387662 PKG_FIXUP:=autoreconf PKG_FLAGS:=nonshared PKG_MAINTAINER:=John Crispin -PKG_USE_MIPS16:=0 PKG_LICENSE:=GPL-2.0 BSD-2-Clause PKG_LICENSE_FILES:=LICENSE +PKG_ASLR_PIE:=0 include $(INCLUDE_DIR)/package.mk @@ -65,7 +65,7 @@ CONFIGURE_ARGS += \ --enable-error_print \ --enable-ifxos-include="-I$(STAGING_DIR)/usr/include/ifxos/" \ --enable-ifxos-library="-L$(STAGING_DIR)/usr/lib" \ - --enable-add_drv_cflags="-DMEI_DRV_ATM_PTM_INTERFACE_ENABLE=1 -fno-pic -mlong-calls -O2 -g0" \ + --enable-add_drv_cflags="-DMEI_DRV_ATM_PTM_INTERFACE_ENABLE=1" \ --enable-linux-26 \ --enable-kernelbuild="$(LINUX_DIR)" \ --enable-drv_test_appl=yes \ diff --git a/package/kernel/lantiq/ltq-vdsl-mei/patches/001-fix-compile.patch b/package/kernel/lantiq/ltq-vdsl-mei/patches/001-fix-compile.patch new file mode 100644 index 000000000..6d3e182ec --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-mei/patches/001-fix-compile.patch @@ -0,0 +1,44 @@ +--- a/src/drv_mei_cpe_linux.h ++++ b/src/drv_mei_cpe_linux.h +@@ -31,6 +31,9 @@ + #include + + #include ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,0)) ++#include ++#endif + #include + #include + #include +@@ -121,7 +124,11 @@ typedef int (*MEI_RequestIrq_WrapLinux_t + /** + Function typedef for the Linux free_irq() + */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0)) ++typedef const void *(*MEI_FreeIrq_WrapLinux_t)( unsigned int usedIrq, ++#else + typedef void (*MEI_FreeIrq_WrapLinux_t)( unsigned int usedIrq, ++#endif + void *usedDevId ); + + +--- a/src/drv_mei_cpe_linux.c ++++ b/src/drv_mei_cpe_linux.c +@@ -129,7 +129,7 @@ static int MEI_module_init(void); + #endif + + #if (MEI_DRV_LKM_ENABLE == 1) && (MEI_SUPPORT_DEVICE_VR10_320 != 1) +-static void __exit MEI_module_exit(void); ++static void MEI_module_exit(void); + #else + static void MEI_module_exit(void); + #endif +@@ -2188,7 +2188,7 @@ static int MEI_module_init (void) + Called by the kernel. + */ + #if (MEI_DRV_LKM_ENABLE == 1) && (MEI_SUPPORT_DEVICE_VR10_320 != 1) +-static void __exit MEI_module_exit (void) ++static void MEI_module_exit (void) + #else + static void MEI_module_exit (void) + #endif diff --git a/package/kernel/lantiq/ltq-vdsl-mei/patches/020-not-leak-cflags.patch b/package/kernel/lantiq/ltq-vdsl-mei/patches/020-not-leak-cflags.patch new file mode 100644 index 000000000..31dbba37b --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl-mei/patches/020-not-leak-cflags.patch @@ -0,0 +1,21 @@ +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -213,8 +213,7 @@ drv_mei_cpe_common_cflags = $(AM_CFLAGS) + else + + drv_mei_cpe_common_cflags = \ +- $(AM_CFLAGS) -D__KERNEL__ -DLINUX -D__linux__ -DMODULE -DEXPORT_SYMTAB \ +- -pipe -Wimplicit -Wunused -Wuninitialized -Wsign-compare -Wstrict-aliasing ++ -D__KERNEL__ -DLINUX -D__linux__ -DMODULE -DEXPORT_SYMTAB + + endif + +@@ -354,7 +353,7 @@ drv_mei_cpe.ko: $(drv_mei_cpe_SOURCES) + @echo -e "# drv_mei_cpe: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild + @echo -e "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild + @echo -e "$(subst .ko,,$@)-y := $(drv_mei_cpe_OBJS)" >> $(PWD)/Kbuild +- @echo -e "EXTRA_CFLAGS := $(CFLAGS) $(drv_mei_cpe_CFLAGS) -I@abs_srcdir@ -I@abs_srcdir@/auto_header $(IFXOS_INCLUDE_PATH)" >> $(PWD)/Kbuild ++ @echo -e "EXTRA_CFLAGS := $(drv_mei_cpe_CFLAGS) -I@abs_srcdir@ -I@abs_srcdir@/auto_header $(IFXOS_INCLUDE_PATH)" >> $(PWD)/Kbuild + $(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules + + clean-generic: diff --git a/package/kernel/lantiq/ltq-vdsl-mei/patches/100-compat.patch b/package/kernel/lantiq/ltq-vdsl-mei/patches/100-compat.patch index 10122fe73..e9584098e 100644 --- a/package/kernel/lantiq/ltq-vdsl-mei/patches/100-compat.patch +++ b/package/kernel/lantiq/ltq-vdsl-mei/patches/100-compat.patch @@ -10,7 +10,7 @@ --- a/src/drv_mei_cpe_linux.h +++ b/src/drv_mei_cpe_linux.h -@@ -57,12 +57,6 @@ +@@ -60,12 +60,6 @@ #include #include diff --git a/package/kernel/lantiq/ltq-vdsl/Makefile b/package/kernel/lantiq/ltq-vdsl/Makefile index 3b085ed8a..cf3711beb 100644 --- a/package/kernel/lantiq/ltq-vdsl/Makefile +++ b/package/kernel/lantiq/ltq-vdsl/Makefile @@ -9,7 +9,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=ltq-vdsl-vr9 PKG_VERSION:=4.17.18.6 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_BASE_NAME:=drv_dsl_cpe_api PKG_SOURCE:=$(PKG_BASE_NAME)_vrx-$(PKG_VERSION).tar.gz @@ -19,8 +19,8 @@ PKG_HASH:=b4966a60653acc49254b168c6cc9c49eb36c54548e763617788aa4f252a29f21 PKG_LICENSE:=GPL-2.0 BSD-2-Clause PKG_LICENSE_FILES:=LICENSE - -PKG_USE_MIPS16:=0 +PKG_ASLR_PIE:=0 +PKG_FIXUP:=autoreconf PKG_MAINTAINER:=John Crispin @@ -42,8 +42,6 @@ define Package/ltq-vdsl-vr9/description - VRX200 Family endef -EXTRA_CFLAGS = -fno-pic -mno-abicalls -mlong-calls -G 0 - MAKE_FLAGS += \ SHELL="$(BASH)" diff --git a/package/kernel/lantiq/ltq-vdsl/patches/001-fix-compile.patch b/package/kernel/lantiq/ltq-vdsl/patches/001-fix-compile.patch new file mode 100644 index 000000000..1355a1a79 --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl/patches/001-fix-compile.patch @@ -0,0 +1,12 @@ +--- a/src/include/drv_dsl_cpe_os_linux.h ++++ b/src/include/drv_dsl_cpe_os_linux.h +@@ -33,6 +33,9 @@ + #endif + + #include ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,0)) ++#include ++#endif + + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) diff --git a/package/kernel/lantiq/ltq-vdsl/patches/020-not-leak-cflags.patch b/package/kernel/lantiq/ltq-vdsl/patches/020-not-leak-cflags.patch new file mode 100644 index 000000000..96e69acca --- /dev/null +++ b/package/kernel/lantiq/ltq-vdsl/patches/020-not-leak-cflags.patch @@ -0,0 +1,32 @@ +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -244,10 +244,7 @@ else + drv_dsl_cpe_api_common_mod_cflags = + endif + +-drv_dsl_cpe_api_common_cflags = -DLINUX -D__LINUX__ -D__KERNEL__ -DEXPORT_SYMTAB \ +- -pipe -Wall -Wformat -Wimplicit -Wunused -Wswitch -Wcomment -Winline \ +- -Wuninitialized -Wparentheses -Wsign-compare -Wreturn-type \ +- -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common ++drv_dsl_cpe_api_common_cflags = -DLINUX -D__LINUX__ -D__KERNEL__ -DEXPORT_SYMTAB + + if DSL_DBG_MAX_LEVEL_SET + drv_dsl_cpe_api_common_cflags += -DDSL_DBG_MAX_LEVEL=$(DSL_DBG_MAX_LEVEL_PRE) +@@ -257,7 +254,7 @@ endif + drv_dsl_cpe_api_target_cflags = $(ADD_DRV_CFLAGS) + + # compile cflags +-drv_dsl_cpe_api_compile_cflags = $(EXTRA_DRV_CFLAGS) ++drv_dsl_cpe_api_compile_cflags = + + if !KERNEL_2_6 + # the headerfile of linux kernels 2.6.x contain to much arithmetic +@@ -311,7 +308,7 @@ drv_dsl_cpe_api.ko: $(drv_dsl_cpe_api_SO + @echo -e "# drv_dsl_cpe_api: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild + @echo -e "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild + @echo -e "$(subst .ko,,$@)-y := $(drv_dsl_cpe_api_OBJS)" >> $(PWD)/Kbuild +- @echo -e "EXTRA_CFLAGS := $(CFLAGS) -DHAVE_CONFIG_H $(drv_dsl_cpe_api_CFLAGS) $(DSL_DRIVER_INCL_PATH) $(IFXOS_INCLUDE_PATH) -I@abs_srcdir@/include -I$(PWD)/include" >> $(PWD)/Kbuild ++ @echo -e "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(drv_dsl_cpe_api_CFLAGS) $(DSL_DRIVER_INCL_PATH) $(IFXOS_INCLUDE_PATH) -I@abs_srcdir@/include -I$(PWD)/include" >> $(PWD)/Kbuild + $(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules + + clean-generic: diff --git a/package/kernel/lantiq/ltq-vmmc/Makefile b/package/kernel/lantiq/ltq-vmmc/Makefile index e42d5c071..e44b509b2 100644 --- a/package/kernel/lantiq/ltq-vmmc/Makefile +++ b/package/kernel/lantiq/ltq-vmmc/Makefile @@ -10,14 +10,14 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=drv_vmmc PKG_VERSION:=1.9.0 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_HASH:=707f515eb727c032418c4da67d7e86884bb56cdc2a606e8f6ded6057d8767e57 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources PKG_MAINTAINER:=John Crispin -PKG_USE_MIPS16:=0 +PKG_ASLR_PIE:=0 PKG_CHECK_FORMAT_SECURITY:=0 PKG_FIXUP:=autoreconf diff --git a/package/kernel/lantiq/ltq-vmmc/patches/020-not-leak-cflags.patch b/package/kernel/lantiq/ltq-vmmc/patches/020-not-leak-cflags.patch new file mode 100644 index 000000000..1a79daae2 --- /dev/null +++ b/package/kernel/lantiq/ltq-vmmc/patches/020-not-leak-cflags.patch @@ -0,0 +1,19 @@ +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -224,7 +224,6 @@ install-exec-hook: $(bin_PROGRAMS) + + # Extra rule for linux-2.6 kernel object + if KERNEL_2_6 +-drv_vmmc_CFLAGS += -fno-common + drv_vmmc_OBJS = "$(subst .c,.o, $(drv_vmmc_SOURCES) $(nodist_drv_vmmc_SOURCES))" + + drv_vmmc.ko: $(drv_vmmc_SOURCES) $(EXTRA_DIST) +@@ -239,7 +238,7 @@ drv_vmmc.ko: $(drv_vmmc_SOURCES) $(EXTRA + @echo "# drv_vmmc: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild + @echo "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild + @echo "$(subst .ko,,$@)-y := $(drv_vmmc_OBJS)" >> $(PWD)/Kbuild +- @echo "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_vmmc_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild ++ @echo "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(drv_vmmc_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild + $(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules + + clean-generic: diff --git a/package/kernel/leds-apu2/src/leds-apu2.c b/package/kernel/leds-apu2/src/leds-apu2.c index 4ea552cf5..2fefa857c 100644 --- a/package/kernel/leds-apu2/src/leds-apu2.c +++ b/package/kernel/leds-apu2/src/leds-apu2.c @@ -335,7 +335,10 @@ static int __init gpio_apu2_init (void) if (!board_name \ || !board_vendor \ || strcasecmp(board_vendor, "PC Engines") \ - || (strcasecmp(board_name, "apu2") && strcasecmp(board_name, "apu3"))) { + || (strcasecmp(board_name, "apu2") \ + && strcasecmp(board_name, "apu3") \ + && strcasecmp(board_name, "PC Engines apu2") \ + && strcasecmp(board_name, "PC Engines apu3"))) { err = -ENODEV; goto exit; } diff --git a/package/kernel/linux/modules/can.mk b/package/kernel/linux/modules/can.mk index 5529fe02e..925de4d8a 100644 --- a/package/kernel/linux/modules/can.mk +++ b/package/kernel/linux/modules/can.mk @@ -47,22 +47,6 @@ define AddDepends/can endef -define KernelPackage/can-raw - TITLE:=Raw CAN Protcol - KCONFIG:=CONFIG_CAN_RAW - FILES:=$(LINUX_DIR)/net/can/can-raw.ko - AUTOLOAD:=$(call AutoProbe,can-raw) - $(call AddDepends/can) -endef - -define KernelPackage/can-raw/description - The raw CAN protocol option offers access to the CAN bus via - the BSD socket API. -endef - -$(eval $(call KernelPackage,can-raw)) - - define KernelPackage/can-bcm TITLE:=Broadcast Manager CAN Protcol KCONFIG:=CONFIG_CAN_BCM @@ -80,6 +64,74 @@ endef $(eval $(call KernelPackage,can-bcm)) +define KernelPackage/can-c-can + TITLE:=BOSCH C_CAN/D_CAN drivers + KCONFIG:=CONFIG_CAN_C_CAN + FILES:=$(LINUX_DIR)/drivers/net/can/c_can/c_can.ko + AUTOLOAD:=$(call AutoProbe,c_can) + $(call AddDepends/can) +endef + +define KernelPackage/can-c-can/description + This driver adds generic support for the C_CAN/D_CAN chips. +endef + +$(eval $(call KernelPackage,can-c-can)) + + +define KernelPackage/can-c-can-pci + TITLE:=PCI Bus based BOSCH C_CAN/D_CAN driver + KCONFIG:=CONFIG_CAN_C_CAN_PCI + DEPENDS:=kmod-can-c-can @PCI_SUPPORT + FILES:=$(LINUX_DIR)/drivers/net/can/c_can/c_can_pci.ko + AUTOLOAD:=$(call AutoProbe,c_can_pci) + $(call AddDepends/can) +endef + +define KernelPackage/can-c-can-pci/description + This driver adds support for the C_CAN/D_CAN chips connected + to the PCI bus. +endef + +$(eval $(call KernelPackage,can-c-can-pci)) + + +define KernelPackage/can-c-can-platform + TITLE:=Platform Bus based BOSCH C_CAN/D_CAN driver + KCONFIG:=CONFIG_CAN_C_CAN_PLATFORM + DEPENDS:=kmod-can-c-can +!LINUX_3_18:kmod-regmap + FILES:=$(LINUX_DIR)/drivers/net/can/c_can/c_can_platform.ko + AUTOLOAD:=$(call AutoProbe,c_can_platform) + $(call AddDepends/can) +endef + +define KernelPackage/can-c-can-platform/description + This driver adds support for the C_CAN/D_CAN chips connected + to the "platform bus" (Linux abstraction for directly to the + processor attached devices) which can be found on various + boards from ST Microelectronics (http://www.st.com) like the + SPEAr1310 and SPEAr320 evaluation boards & TI (www.ti.com) + boards like am335x, dm814x, dm813x and dm811x. +endef + +$(eval $(call KernelPackage,can-c-can-platform)) + + +define KernelPackage/can-flexcan + TITLE:=Support for Freescale FLEXCAN based chips + KCONFIG:=CONFIG_CAN_FLEXCAN + FILES:=$(LINUX_DIR)/drivers/net/can/flexcan.ko + AUTOLOAD:=$(call AutoProbe,flexcan) + $(call AddDepends/can,@TARGET_imx6) +endef + +define KernelPackage/can-flexcan/description + Freescale FLEXCAN CAN bus controller implementation. +endef + +$(eval $(call KernelPackage,can-flexcan)) + + define KernelPackage/can-gw TITLE:=CAN Gateway/Router KCONFIG:=CONFIG_CAN_GW @@ -95,20 +147,20 @@ endef $(eval $(call KernelPackage,can-gw)) -define KernelPackage/can-vcan - TITLE:=Virtual Local CAN Interface (vcan) - KCONFIG:=CONFIG_CAN_VCAN - FILES:=$(LINUX_DIR)/drivers/net/can/vcan.ko - AUTOLOAD:=$(call AutoProbe,vcan) +define KernelPackage/can-raw + TITLE:=Raw CAN Protcol + KCONFIG:=CONFIG_CAN_RAW + FILES:=$(LINUX_DIR)/net/can/can-raw.ko + AUTOLOAD:=$(call AutoProbe,can-raw) $(call AddDepends/can) endef -define KernelPackage/can-vcan/description - Similar to the network loopback devices, vcan offers a - virtual local CAN interface. +define KernelPackage/can-raw/description + The raw CAN protocol option offers access to the CAN bus via + the BSD socket API. endef -$(eval $(call KernelPackage,can-vcan)) +$(eval $(call KernelPackage,can-raw)) define KernelPackage/can-slcan @@ -128,19 +180,20 @@ endef $(eval $(call KernelPackage,can-slcan)) -define KernelPackage/can-flexcan - TITLE:=Support for Freescale FLEXCAN based chips - KCONFIG:=CONFIG_CAN_FLEXCAN - FILES:=$(LINUX_DIR)/drivers/net/can/flexcan.ko - AUTOLOAD:=$(call AutoProbe,flexcan) - $(call AddDepends/can,@TARGET_imx6) +define KernelPackage/can-usb-8dev + TITLE:=8 devices USB2CAN interface + KCONFIG:=CONFIG_CAN_8DEV_USB + FILES:=$(LINUX_DIR)/drivers/net/can/usb/usb_8dev.ko + AUTOLOAD:=$(call AutoProbe,usb_8dev) + $(call AddDepends/can,+kmod-usb-core) endef -define KernelPackage/can-flexcan/description - Freescale FLEXCAN CAN bus controller implementation. +define KernelPackage/can-usb-8dev/description + This driver supports the USB2CAN interface + from 8 devices (http://www.8devices.com). endef -$(eval $(call KernelPackage,can-flexcan)) +$(eval $(call KernelPackage,can-usb-8dev)) define KernelPackage/can-usb-ems @@ -207,71 +260,19 @@ endef $(eval $(call KernelPackage,can-usb-peak)) -define KernelPackage/can-usb-8dev - TITLE:=8 devices USB2CAN interface - KCONFIG:=CONFIG_CAN_8DEV_USB - FILES:=$(LINUX_DIR)/drivers/net/can/usb/usb_8dev.ko - AUTOLOAD:=$(call AutoProbe,usb_8dev) - $(call AddDepends/can,+kmod-usb-core) -endef - -define KernelPackage/can-usb-8dev/description - This driver supports the USB2CAN interface - from 8 devices (http://www.8devices.com). -endef - -$(eval $(call KernelPackage,can-usb-8dev)) - - -define KernelPackage/can-c-can - TITLE:=BOSCH C_CAN/D_CAN drivers - KCONFIG:=CONFIG_CAN_C_CAN - FILES:=$(LINUX_DIR)/drivers/net/can/c_can/c_can.ko - AUTOLOAD:=$(call AutoProbe,c_can) +define KernelPackage/can-vcan + TITLE:=Virtual Local CAN Interface (vcan) + KCONFIG:=CONFIG_CAN_VCAN + FILES:=$(LINUX_DIR)/drivers/net/can/vcan.ko + AUTOLOAD:=$(call AutoProbe,vcan) $(call AddDepends/can) endef -define KernelPackage/can-c-can/description - This driver adds generic support for the C_CAN/D_CAN chips. +define KernelPackage/can-vcan/description + Similar to the network loopback devices, vcan offers a + virtual local CAN interface. endef -$(eval $(call KernelPackage,can-c-can)) +$(eval $(call KernelPackage,can-vcan)) -define KernelPackage/can-c-can-platform - TITLE:=Platform Bus based BOSCH C_CAN/D_CAN driver - KCONFIG:=CONFIG_CAN_C_CAN_PLATFORM - DEPENDS:=kmod-can-c-can +!LINUX_3_18:kmod-regmap - FILES:=$(LINUX_DIR)/drivers/net/can/c_can/c_can_platform.ko - AUTOLOAD:=$(call AutoProbe,c_can_platform) - $(call AddDepends/can) -endef - -define KernelPackage/can-c-can-platform/description - This driver adds support for the C_CAN/D_CAN chips connected - to the "platform bus" (Linux abstraction for directly to the - processor attached devices) which can be found on various - boards from ST Microelectronics (http://www.st.com) like the - SPEAr1310 and SPEAr320 evaluation boards & TI (www.ti.com) - boards like am335x, dm814x, dm813x and dm811x. -endef - -$(eval $(call KernelPackage,can-c-can-platform)) - - -define KernelPackage/can-c-can-pci - TITLE:=PCI Bus based BOSCH C_CAN/D_CAN driver - KCONFIG:=CONFIG_CAN_C_CAN_PCI - DEPENDS:=kmod-can-c-can @PCI_SUPPORT - FILES:=$(LINUX_DIR)/drivers/net/can/c_can/c_can_pci.ko - AUTOLOAD:=$(call AutoProbe,c_can_pci) - $(call AddDepends/can) -endef - -define KernelPackage/can-c-can-pci/description - This driver adds support for the C_CAN/D_CAN chips connected - to the PCI bus. -endef - -$(eval $(call KernelPackage,can-c-can-pci)) - diff --git a/package/kernel/linux/modules/crypto.mk b/package/kernel/linux/modules/crypto.mk index bc56b3cc1..2ea2d2c0e 100644 --- a/package/kernel/linux/modules/crypto.mk +++ b/package/kernel/linux/modules/crypto.mk @@ -20,6 +20,19 @@ define AddDepends/crypto DEPENDS+= $(1) endef + +define KernelPackage/crypto-acompress + TITLE:=Asynchronous Compression operations + HIDDEN:=1 + KCONFIG:=CONFIG_CRYPTO_ACOMP2 + FILES:=$(LINUX_DIR)/crypto/crypto_acompress.ko + AUTOLOAD:=$(call AutoLoad,09,crypto_acompress) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-acompress)) + + define KernelPackage/crypto-aead TITLE:=CryptoAPI AEAD support KCONFIG:= \ @@ -33,108 +46,136 @@ endef $(eval $(call KernelPackage,crypto-aead)) -define KernelPackage/crypto-hash - TITLE:=CryptoAPI hash support - KCONFIG:=CONFIG_CRYPTO_HASH - FILES:=$(LINUX_DIR)/crypto/crypto_hash.ko - AUTOLOAD:=$(call AutoLoad,02,crypto_hash,1) +define KernelPackage/crypto-authenc + TITLE:=Combined mode wrapper for IPsec + DEPENDS:=+kmod-crypto-manager +!LINUX_3_18:kmod-crypto-null + KCONFIG:=CONFIG_CRYPTO_AUTHENC + FILES:=$(LINUX_DIR)/crypto/authenc.ko + AUTOLOAD:=$(call AutoLoad,09,authenc) $(call AddDepends/crypto) endef -$(eval $(call KernelPackage,crypto-hash)) +$(eval $(call KernelPackage,crypto-authenc)) -define KernelPackage/crypto-manager - TITLE:=CryptoAPI algorithm manager - DEPENDS:=+kmod-crypto-aead +kmod-crypto-hash +kmod-crypto-pcompress - KCONFIG:= \ - CONFIG_CRYPTO_MANAGER \ - CONFIG_CRYPTO_MANAGER2 - FILES:=$(LINUX_DIR)/crypto/cryptomgr.ko - AUTOLOAD:=$(call AutoLoad,09,cryptomgr,1) +define KernelPackage/crypto-cbc + TITLE:=Cipher Block Chaining CryptoAPI module + DEPENDS:=+kmod-crypto-manager + KCONFIG:=CONFIG_CRYPTO_CBC + FILES:=$(LINUX_DIR)/crypto/cbc.ko + AUTOLOAD:=$(call AutoLoad,09,cbc) $(call AddDepends/crypto) endef -$(eval $(call KernelPackage,crypto-manager)) +$(eval $(call KernelPackage,crypto-cbc)) -define KernelPackage/crypto-pcompress - TITLE:=CryptoAPI Partial (de)compression operations - KCONFIG:= \ - CONFIG_CRYPTO_PCOMP=y \ - CONFIG_CRYPTO_PCOMP2 - FILES:=$(LINUX_DIR)/crypto/pcompress.ko - AUTOLOAD:=$(call AutoLoad,09,pcompress) +define KernelPackage/crypto-ccm + TITLE:=Support for Counter with CBC MAC (CCM) + DEPENDS:=+kmod-crypto-ctr +kmod-crypto-aead + KCONFIG:=CONFIG_CRYPTO_CCM + FILES:=$(LINUX_DIR)/crypto/ccm.ko + AUTOLOAD:=$(call AutoLoad,09,ccm) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-ccm)) + + +define KernelPackage/crypto-cmac + TITLE:=Support for Cipher-based Message Authentication Code (CMAC) + DEPENDS:=+kmod-crypto-hash + KCONFIG:=CONFIG_CRYPTO_CMAC + FILES:=$(LINUX_DIR)/crypto/cmac.ko + AUTOLOAD:=$(call AutoLoad,09,cmac) $(call AddDepends/crypto) endef -$(eval $(call KernelPackage,crypto-pcompress)) +$(eval $(call KernelPackage,crypto-cmac)) -define KernelPackage/crypto-user - TITLE:=CryptoAPI userspace interface - DEPENDS:=+kmod-crypto-hash +kmod-crypto-manager - KCONFIG:= \ - CONFIG_CRYPTO_USER_API \ - CONFIG_CRYPTO_USER_API_HASH \ - CONFIG_CRYPTO_USER_API_SKCIPHER - FILES:= \ - $(LINUX_DIR)/crypto/af_alg.ko \ - $(LINUX_DIR)/crypto/algif_hash.ko \ - $(LINUX_DIR)/crypto/algif_skcipher.ko - AUTOLOAD:=$(call AutoLoad,09,af_alg algif_hash algif_skcipher) - $(call AddDepends/crypto) -endef - -$(eval $(call KernelPackage,crypto-user)) - - -define KernelPackage/crypto-wq - TITLE:=CryptoAPI work queue handling - KCONFIG:=CONFIG_CRYPTO_WORKQUEUE - FILES:=$(LINUX_DIR)/crypto/crypto_wq.ko - AUTOLOAD:=$(call AutoLoad,09,crypto_wq) - $(call AddDepends/crypto) -endef -$(eval $(call KernelPackage,crypto-wq)) - -define KernelPackage/crypto-rng - TITLE:=CryptoAPI random number generation - DEPENDS:=+kmod-crypto-hash +kmod-crypto-hmac +kmod-crypto-sha256 - KCONFIG:= \ - CONFIG_CRYPTO_DRBG \ - CONFIG_CRYPTO_DRBG_HMAC=y \ - CONFIG_CRYPTO_DRBG_HASH=n \ - CONFIG_CRYPTO_DRBG_MENU \ - CONFIG_CRYPTO_JITTERENTROPY \ - CONFIG_CRYPTO_RNG2 - FILES:= \ - $(LINUX_DIR)/crypto/drbg.ko@ge4.2 \ - $(LINUX_DIR)/crypto/jitterentropy_rng.ko@ge4.2 \ - $(LINUX_DIR)/crypto/krng.ko@lt4.2 \ - $(LINUX_DIR)/crypto/rng.ko - AUTOLOAD:=$(call AutoLoad,09,drbg@ge4.2 jitterentropy_rng@ge4.2 krng@lt4.2 rng) - $(call AddDepends/crypto) -endef - -$(eval $(call KernelPackage,crypto-rng)) - - -define KernelPackage/crypto-rsa - TITLE:=RSA algorithm - DEPENDS:=@!LINUX_3_18 +kmod-crypto-manager - KCONFIG:= CONFIG_CRYPTO_RSA +define KernelPackage/crypto-crc32 + TITLE:=CRC32 CRC module + DEPENDS:=+kmod-crypto-hash + KCONFIG:=CONFIG_CRYPTO_CRC32 HIDDEN:=1 - FILES:= \ - $(LINUX_DIR)/lib/asn1_decoder.ko \ - $(LINUX_DIR)/lib/mpi/mpi.ko \ - $(LINUX_DIR)/crypto/akcipher.ko \ - $(LINUX_DIR)/crypto/rsa_generic.ko - AUTOLOAD:=$(call AutoLoad,10,rsa_generic) + FILES:=$(LINUX_DIR)/crypto/crc32_generic.ko@ge4.9 + AUTOLOAD:=$(call AutoLoad,04,crc32_generic@ge4.9,1) $(call AddDepends/crypto) endef -$(eval $(call KernelPackage,crypto-rsa)) +$(eval $(call KernelPackage,crypto-crc32)) + + +define KernelPackage/crypto-crc32c + TITLE:=CRC32c CRC module + DEPENDS:=+kmod-crypto-hash + KCONFIG:=CONFIG_CRYPTO_CRC32C + FILES:=$(LINUX_DIR)/crypto/crc32c_generic.ko + AUTOLOAD:=$(call AutoLoad,04,crc32c_generic,1) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-crc32c)) + + +define KernelPackage/crypto-ctr + TITLE:=Counter Mode CryptoAPI module + DEPENDS:=+kmod-crypto-manager +kmod-crypto-seqiv +kmod-crypto-iv + KCONFIG:=CONFIG_CRYPTO_CTR + FILES:=$(LINUX_DIR)/crypto/ctr.ko + AUTOLOAD:=$(call AutoLoad,09,ctr) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-ctr)) + + +define KernelPackage/crypto-cts + TITLE:=Cipher Text Stealing CryptoAPI module + DEPENDS:=+kmod-crypto-manager + KCONFIG:=CONFIG_CRYPTO_CTS + FILES:=$(LINUX_DIR)/crypto/cts.ko + AUTOLOAD:=$(call AutoLoad,09,cts) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-cts)) + + +define KernelPackage/crypto-deflate + TITLE:=Deflate compression CryptoAPI module + DEPENDS:=+kmod-lib-zlib-inflate +kmod-lib-zlib-deflate +LINUX_4_14:kmod-crypto-acompress + KCONFIG:=CONFIG_CRYPTO_DEFLATE + FILES:=$(LINUX_DIR)/crypto/deflate.ko + AUTOLOAD:=$(call AutoLoad,09,deflate) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-deflate)) + + +define KernelPackage/crypto-des + TITLE:=DES/3DES cipher CryptoAPI module + KCONFIG:=CONFIG_CRYPTO_DES + FILES:=$(LINUX_DIR)/crypto/des_generic.ko + AUTOLOAD:=$(call AutoLoad,09,des_generic) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-des)) + + +define KernelPackage/crypto-ecb + TITLE:=Electronic CodeBook CryptoAPI module + DEPENDS:=+kmod-crypto-manager + KCONFIG:=CONFIG_CRYPTO_ECB + FILES:=$(LINUX_DIR)/crypto/ecb.ko + AUTOLOAD:=$(call AutoLoad,09,ecb) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-ecb)) define KernelPackage/crypto-ecdh @@ -150,21 +191,6 @@ endef $(eval $(call KernelPackage,crypto-ecdh)) -define KernelPackage/crypto-iv - TITLE:=CryptoAPI initialization vectors - DEPENDS:=+kmod-crypto-manager +kmod-crypto-rng +kmod-crypto-wq - KCONFIG:= CONFIG_CRYPTO_BLKCIPHER2 - HIDDEN:=1 - FILES:= \ - $(LINUX_DIR)/crypto/eseqiv.ko@lt4.9 \ - $(LINUX_DIR)/crypto/chainiv.ko@lt4.9 - AUTOLOAD:=$(call AutoLoad,10,eseqiv chainiv) - $(call AddDepends/crypto) -endef - -$(eval $(call KernelPackage,crypto-iv)) - - define KernelPackage/crypto-echainiv TITLE:=Encrypted Chain IV Generator DEPENDS:=+kmod-crypto-aead @@ -177,51 +203,73 @@ endef $(eval $(call KernelPackage,crypto-echainiv)) -define KernelPackage/crypto-seqiv - TITLE:=CryptoAPI Sequence Number IV Generator - DEPENDS:=+kmod-crypto-aead +kmod-crypto-rng - KCONFIG:=CONFIG_CRYPTO_SEQIV - FILES:=$(LINUX_DIR)/crypto/seqiv.ko - AUTOLOAD:=$(call AutoLoad,09,seqiv) +define KernelPackage/crypto-fcrypt + TITLE:=FCRYPT cipher CryptoAPI module + KCONFIG:=CONFIG_CRYPTO_FCRYPT + FILES:=$(LINUX_DIR)/crypto/fcrypt.ko + AUTOLOAD:=$(call AutoLoad,09,fcrypt) $(call AddDepends/crypto) endef -$(eval $(call KernelPackage,crypto-seqiv)) +$(eval $(call KernelPackage,crypto-fcrypt)) -define KernelPackage/crypto-hw-talitos - TITLE:=Freescale integrated security engine (SEC) driver - DEPENDS:=+kmod-crypto-manager +kmod-crypto-hash +kmod-random-core +kmod-crypto-authenc +kmod-crypto-des - KCONFIG:= \ - CONFIG_CRYPTO_HW=y \ - CONFIG_CRYPTO_DEV_TALITOS \ - CONFIG_CRYPTO_DEV_TALITOS1=y \ - CONFIG_CRYPTO_DEV_TALITOS2=y - FILES:= \ - $(LINUX_DIR)/drivers/crypto/talitos.ko - AUTOLOAD:=$(call AutoLoad,09,talitos) +define KernelPackage/crypto-gcm + TITLE:=GCM/GMAC CryptoAPI module + DEPENDS:=+kmod-crypto-ctr +kmod-crypto-ghash +kmod-crypto-null + KCONFIG:=CONFIG_CRYPTO_GCM + FILES:=$(LINUX_DIR)/crypto/gcm.ko + AUTOLOAD:=$(call AutoLoad,09,gcm) $(call AddDepends/crypto) endef -$(eval $(call KernelPackage,crypto-hw-talitos)) +$(eval $(call KernelPackage,crypto-gcm)) -define KernelPackage/crypto-hw-padlock - TITLE:=VIA PadLock ACE with AES/SHA hw crypto module - DEPENDS:=+kmod-crypto-manager - KCONFIG:= \ - CONFIG_CRYPTO_HW=y \ - CONFIG_CRYPTO_DEV_PADLOCK \ - CONFIG_CRYPTO_DEV_PADLOCK_AES \ - CONFIG_CRYPTO_DEV_PADLOCK_SHA - FILES:= \ - $(LINUX_DIR)/drivers/crypto/padlock-aes.ko \ - $(LINUX_DIR)/drivers/crypto/padlock-sha.ko - AUTOLOAD:=$(call AutoLoad,09,padlock-aes padlock-sha) +define KernelPackage/crypto-gf128 + TITLE:=GF(2^128) multiplication functions CryptoAPI module + KCONFIG:=CONFIG_CRYPTO_GF128MUL + FILES:=$(LINUX_DIR)/crypto/gf128mul.ko + AUTOLOAD:=$(call AutoLoad,09,gf128mul) $(call AddDepends/crypto) endef -$(eval $(call KernelPackage,crypto-hw-padlock)) +$(eval $(call KernelPackage,crypto-gf128)) + + +define KernelPackage/crypto-ghash + TITLE:=GHASH digest CryptoAPI module + DEPENDS:=+kmod-crypto-gf128 +kmod-crypto-hash + KCONFIG:=CONFIG_CRYPTO_GHASH + FILES:=$(LINUX_DIR)/crypto/ghash-generic.ko + AUTOLOAD:=$(call AutoLoad,09,ghash-generic) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-ghash)) + + +define KernelPackage/crypto-hash + TITLE:=CryptoAPI hash support + KCONFIG:=CONFIG_CRYPTO_HASH + FILES:=$(LINUX_DIR)/crypto/crypto_hash.ko + AUTOLOAD:=$(call AutoLoad,02,crypto_hash,1) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-hash)) + + +define KernelPackage/crypto-hmac + TITLE:=HMAC digest CryptoAPI module + DEPENDS:=+kmod-crypto-hash +kmod-crypto-manager + KCONFIG:=CONFIG_CRYPTO_HMAC + FILES:=$(LINUX_DIR)/crypto/hmac.ko + AUTOLOAD:=$(call AutoLoad,09,hmac) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-hmac)) define KernelPackage/crypto-hw-ccp @@ -272,93 +320,54 @@ endef $(eval $(call KernelPackage,crypto-hw-hifn-795x)) -define KernelPackage/crypto-authenc - TITLE:=Combined mode wrapper for IPsec - DEPENDS:=+kmod-crypto-manager +!LINUX_3_18:kmod-crypto-null - KCONFIG:=CONFIG_CRYPTO_AUTHENC - FILES:=$(LINUX_DIR)/crypto/authenc.ko - AUTOLOAD:=$(call AutoLoad,09,authenc) - $(call AddDepends/crypto) -endef - -$(eval $(call KernelPackage,crypto-authenc)) - -define KernelPackage/crypto-cbc - TITLE:=Cipher Block Chaining CryptoAPI module +define KernelPackage/crypto-hw-padlock + TITLE:=VIA PadLock ACE with AES/SHA hw crypto module DEPENDS:=+kmod-crypto-manager - KCONFIG:=CONFIG_CRYPTO_CBC - FILES:=$(LINUX_DIR)/crypto/cbc.ko - AUTOLOAD:=$(call AutoLoad,09,cbc) + KCONFIG:= \ + CONFIG_CRYPTO_HW=y \ + CONFIG_CRYPTO_DEV_PADLOCK \ + CONFIG_CRYPTO_DEV_PADLOCK_AES \ + CONFIG_CRYPTO_DEV_PADLOCK_SHA + FILES:= \ + $(LINUX_DIR)/drivers/crypto/padlock-aes.ko \ + $(LINUX_DIR)/drivers/crypto/padlock-sha.ko + AUTOLOAD:=$(call AutoLoad,09,padlock-aes padlock-sha) $(call AddDepends/crypto) endef -$(eval $(call KernelPackage,crypto-cbc)) +$(eval $(call KernelPackage,crypto-hw-padlock)) -define KernelPackage/crypto-ctr - TITLE:=Counter Mode CryptoAPI module - DEPENDS:=+kmod-crypto-manager +kmod-crypto-seqiv +kmod-crypto-iv - KCONFIG:=CONFIG_CRYPTO_CTR - FILES:=$(LINUX_DIR)/crypto/ctr.ko - AUTOLOAD:=$(call AutoLoad,09,ctr) + +define KernelPackage/crypto-hw-talitos + TITLE:=Freescale integrated security engine (SEC) driver + DEPENDS:=+kmod-crypto-manager +kmod-crypto-hash +kmod-random-core +kmod-crypto-authenc +kmod-crypto-des + KCONFIG:= \ + CONFIG_CRYPTO_HW=y \ + CONFIG_CRYPTO_DEV_TALITOS \ + CONFIG_CRYPTO_DEV_TALITOS1=y \ + CONFIG_CRYPTO_DEV_TALITOS2=y + FILES:= \ + $(LINUX_DIR)/drivers/crypto/talitos.ko + AUTOLOAD:=$(call AutoLoad,09,talitos) $(call AddDepends/crypto) endef -$(eval $(call KernelPackage,crypto-ctr)) +$(eval $(call KernelPackage,crypto-hw-talitos)) -define KernelPackage/crypto-ccm - TITLE:=Support for Counter with CBC MAC (CCM) - DEPENDS:=+kmod-crypto-ctr +kmod-crypto-aead - KCONFIG:=CONFIG_CRYPTO_CCM - FILES:=$(LINUX_DIR)/crypto/ccm.ko - AUTOLOAD:=$(call AutoLoad,09,ccm) - $(call AddDepends/crypto) -endef -$(eval $(call KernelPackage,crypto-ccm)) - -define KernelPackage/crypto-pcbc - TITLE:=Propagating Cipher Block Chaining CryptoAPI module - DEPENDS:=+kmod-crypto-manager - KCONFIG:=CONFIG_CRYPTO_PCBC - FILES:=$(LINUX_DIR)/crypto/pcbc.ko - AUTOLOAD:=$(call AutoLoad,09,pcbc) - $(call AddDepends/crypto) -endef - -$(eval $(call KernelPackage,crypto-pcbc)) - -define KernelPackage/crypto-crc32c - TITLE:=CRC32c CRC module - DEPENDS:=+kmod-crypto-hash - KCONFIG:=CONFIG_CRYPTO_CRC32C - FILES:=$(LINUX_DIR)/crypto/crc32c_generic.ko - AUTOLOAD:=$(call AutoLoad,04,crc32c_generic,1) - $(call AddDepends/crypto) -endef - -$(eval $(call KernelPackage,crypto-crc32c)) - -define KernelPackage/crypto-crc32 - TITLE:=CRC32 CRC module - DEPENDS:=+kmod-crypto-hash - KCONFIG:=CONFIG_CRYPTO_CRC32 +define KernelPackage/crypto-iv + TITLE:=CryptoAPI initialization vectors + DEPENDS:=+kmod-crypto-manager +kmod-crypto-rng +kmod-crypto-wq + KCONFIG:= CONFIG_CRYPTO_BLKCIPHER2 HIDDEN:=1 - FILES:=$(LINUX_DIR)/crypto/crc32_generic.ko@ge4.9 - AUTOLOAD:=$(call AutoLoad,04,crc32_generic@ge4.9,1) + FILES:= \ + $(LINUX_DIR)/crypto/eseqiv.ko@lt4.9 \ + $(LINUX_DIR)/crypto/chainiv.ko@lt4.9 + AUTOLOAD:=$(call AutoLoad,10,eseqiv chainiv) $(call AddDepends/crypto) endef -$(eval $(call KernelPackage,crypto-crc32)) - -define KernelPackage/crypto-des - TITLE:=DES/3DES cipher CryptoAPI module - KCONFIG:=CONFIG_CRYPTO_DES - FILES:=$(LINUX_DIR)/crypto/des_generic.ko - AUTOLOAD:=$(call AutoLoad,09,des_generic) - $(call AddDepends/crypto) -endef - -$(eval $(call KernelPackage,crypto-des)) +$(eval $(call KernelPackage,crypto-iv)) define KernelPackage/crypto-kpp @@ -373,120 +382,18 @@ endef $(eval $(call KernelPackage,crypto-kpp)) -define KernelPackage/crypto-acompress - TITLE:=Asynchronous Compression operations - HIDDEN:=1 - KCONFIG:=CONFIG_CRYPTO_ACOMP2 - FILES:=$(LINUX_DIR)/crypto/crypto_acompress.ko - AUTOLOAD:=$(call AutoLoad,09,crypto_acompress) +define KernelPackage/crypto-manager + TITLE:=CryptoAPI algorithm manager + DEPENDS:=+kmod-crypto-aead +kmod-crypto-hash +kmod-crypto-pcompress + KCONFIG:= \ + CONFIG_CRYPTO_MANAGER \ + CONFIG_CRYPTO_MANAGER2 + FILES:=$(LINUX_DIR)/crypto/cryptomgr.ko + AUTOLOAD:=$(call AutoLoad,09,cryptomgr,1) $(call AddDepends/crypto) endef -$(eval $(call KernelPackage,crypto-acompress)) - - -define KernelPackage/crypto-deflate - TITLE:=Deflate compression CryptoAPI module - DEPENDS:=+kmod-lib-zlib-inflate +kmod-lib-zlib-deflate +LINUX_4_14:kmod-crypto-acompress - KCONFIG:=CONFIG_CRYPTO_DEFLATE - FILES:=$(LINUX_DIR)/crypto/deflate.ko - AUTOLOAD:=$(call AutoLoad,09,deflate) - $(call AddDepends/crypto) -endef - -$(eval $(call KernelPackage,crypto-deflate)) - - -define KernelPackage/crypto-fcrypt - TITLE:=FCRYPT cipher CryptoAPI module - KCONFIG:=CONFIG_CRYPTO_FCRYPT - FILES:=$(LINUX_DIR)/crypto/fcrypt.ko - AUTOLOAD:=$(call AutoLoad,09,fcrypt) - $(call AddDepends/crypto) -endef - -$(eval $(call KernelPackage,crypto-fcrypt)) - -define KernelPackage/crypto-ecb - TITLE:=Electronic CodeBook CryptoAPI module - DEPENDS:=+kmod-crypto-manager - KCONFIG:=CONFIG_CRYPTO_ECB - FILES:=$(LINUX_DIR)/crypto/ecb.ko - AUTOLOAD:=$(call AutoLoad,09,ecb) - $(call AddDepends/crypto) -endef - -$(eval $(call KernelPackage,crypto-ecb)) - -define KernelPackage/crypto-cts - TITLE:=Cipher Text Stealing CryptoAPI module - DEPENDS:=+kmod-crypto-manager - KCONFIG:=CONFIG_CRYPTO_CTS - FILES:=$(LINUX_DIR)/crypto/cts.ko - AUTOLOAD:=$(call AutoLoad,09,cts) - $(call AddDepends/crypto) -endef - -$(eval $(call KernelPackage,crypto-cts)) - - -define KernelPackage/crypto-hmac - TITLE:=HMAC digest CryptoAPI module - DEPENDS:=+kmod-crypto-hash +kmod-crypto-manager - KCONFIG:=CONFIG_CRYPTO_HMAC - FILES:=$(LINUX_DIR)/crypto/hmac.ko - AUTOLOAD:=$(call AutoLoad,09,hmac) - $(call AddDepends/crypto) -endef - -$(eval $(call KernelPackage,crypto-hmac)) - - -define KernelPackage/crypto-cmac - TITLE:=Support for Cipher-based Message Authentication Code (CMAC) - DEPENDS:=+kmod-crypto-hash - KCONFIG:=CONFIG_CRYPTO_CMAC - FILES:=$(LINUX_DIR)/crypto/cmac.ko - AUTOLOAD:=$(call AutoLoad,09,cmac) - $(call AddDepends/crypto) -endef - -$(eval $(call KernelPackage,crypto-cmac)) - - -define KernelPackage/crypto-gcm - TITLE:=GCM/GMAC CryptoAPI module - DEPENDS:=+kmod-crypto-ctr +kmod-crypto-ghash +kmod-crypto-null - KCONFIG:=CONFIG_CRYPTO_GCM - FILES:=$(LINUX_DIR)/crypto/gcm.ko - AUTOLOAD:=$(call AutoLoad,09,gcm) - $(call AddDepends/crypto) -endef - -$(eval $(call KernelPackage,crypto-gcm)) - - -define KernelPackage/crypto-gf128 - TITLE:=GF(2^128) multiplication functions CryptoAPI module - KCONFIG:=CONFIG_CRYPTO_GF128MUL - FILES:=$(LINUX_DIR)/crypto/gf128mul.ko - AUTOLOAD:=$(call AutoLoad,09,gf128mul) - $(call AddDepends/crypto) -endef - -$(eval $(call KernelPackage,crypto-gf128)) - - -define KernelPackage/crypto-ghash - TITLE:=GHASH digest CryptoAPI module - DEPENDS:=+kmod-crypto-gf128 +kmod-crypto-hash - KCONFIG:=CONFIG_CRYPTO_GHASH - FILES:=$(LINUX_DIR)/crypto/ghash-generic.ko - AUTOLOAD:=$(call AutoLoad,09,ghash-generic) - $(call AddDepends/crypto) -endef - -$(eval $(call KernelPackage,crypto-ghash)) +$(eval $(call KernelPackage,crypto-manager)) define KernelPackage/crypto-md4 @@ -532,6 +439,138 @@ endef $(eval $(call KernelPackage,crypto-michael-mic)) +define KernelPackage/crypto-misc + TITLE:=Other CryptoAPI modules + DEPENDS:=+kmod-crypto-manager + KCONFIG:= \ + CONFIG_CRYPTO_ANUBIS \ + CONFIG_CRYPTO_BLOWFISH \ + CONFIG_CRYPTO_CAMELLIA \ + CONFIG_CRYPTO_CAST5 \ + CONFIG_CRYPTO_CAST6 \ + CONFIG_CRYPTO_FCRYPT \ + CONFIG_CRYPTO_KHAZAD \ + CONFIG_CRYPTO_SERPENT \ + CONFIG_CRYPTO_TEA \ + CONFIG_CRYPTO_TGR192 \ + CONFIG_CRYPTO_TWOFISH \ + CONFIG_CRYPTO_TWOFISH_COMMON \ + CONFIG_CRYPTO_TWOFISH_586 \ + CONFIG_CRYPTO_WP512 + FILES:= \ + $(LINUX_DIR)/crypto/anubis.ko \ + $(LINUX_DIR)/crypto/camellia_generic.ko \ + $(LINUX_DIR)/crypto/cast_common.ko \ + $(LINUX_DIR)/crypto/cast5_generic.ko \ + $(LINUX_DIR)/crypto/cast6_generic.ko \ + $(LINUX_DIR)/crypto/khazad.ko \ + $(LINUX_DIR)/crypto/tea.ko \ + $(LINUX_DIR)/crypto/tgr192.ko \ + $(LINUX_DIR)/crypto/twofish_common.ko \ + $(LINUX_DIR)/crypto/wp512.ko \ + $(LINUX_DIR)/crypto/twofish_generic.ko \ + $(LINUX_DIR)/crypto/blowfish_common.ko \ + $(LINUX_DIR)/crypto/blowfish_generic.ko \ + $(LINUX_DIR)/crypto/serpent_generic.ko + $(call AddDepends/crypto) +endef + +ifndef CONFIG_TARGET_x86_64 + define KernelPackage/crypto-misc/x86 + FILES+=$(LINUX_DIR)/arch/x86/crypto/twofish-i586.ko + endef +endif + +$(eval $(call KernelPackage,crypto-misc)) + + +define KernelPackage/crypto-null + TITLE:=Null CryptoAPI module + KCONFIG:=CONFIG_CRYPTO_NULL + FILES:=$(LINUX_DIR)/crypto/crypto_null.ko + AUTOLOAD:=$(call AutoLoad,09,crypto_null) + $(call AddDepends/crypto, +kmod-crypto-hash) +endef + +$(eval $(call KernelPackage,crypto-null)) + + +define KernelPackage/crypto-pcbc + TITLE:=Propagating Cipher Block Chaining CryptoAPI module + DEPENDS:=+kmod-crypto-manager + KCONFIG:=CONFIG_CRYPTO_PCBC + FILES:=$(LINUX_DIR)/crypto/pcbc.ko + AUTOLOAD:=$(call AutoLoad,09,pcbc) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-pcbc)) + + +define KernelPackage/crypto-pcompress + TITLE:=CryptoAPI Partial (de)compression operations + KCONFIG:= \ + CONFIG_CRYPTO_PCOMP=y \ + CONFIG_CRYPTO_PCOMP2 + FILES:=$(LINUX_DIR)/crypto/pcompress.ko + AUTOLOAD:=$(call AutoLoad,09,pcompress) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-pcompress)) + + +define KernelPackage/crypto-rsa + TITLE:=RSA algorithm + DEPENDS:=@!LINUX_3_18 +kmod-crypto-manager + KCONFIG:= CONFIG_CRYPTO_RSA + HIDDEN:=1 + FILES:= \ + $(LINUX_DIR)/lib/asn1_decoder.ko \ + $(LINUX_DIR)/lib/mpi/mpi.ko \ + $(LINUX_DIR)/crypto/akcipher.ko \ + $(LINUX_DIR)/crypto/rsa_generic.ko + AUTOLOAD:=$(call AutoLoad,10,rsa_generic) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-rsa)) + + +define KernelPackage/crypto-rng + TITLE:=CryptoAPI random number generation + DEPENDS:=+kmod-crypto-hash +kmod-crypto-hmac +kmod-crypto-sha256 + KCONFIG:= \ + CONFIG_CRYPTO_DRBG \ + CONFIG_CRYPTO_DRBG_HMAC=y \ + CONFIG_CRYPTO_DRBG_HASH=n \ + CONFIG_CRYPTO_DRBG_MENU \ + CONFIG_CRYPTO_JITTERENTROPY \ + CONFIG_CRYPTO_RNG2 + FILES:= \ + $(LINUX_DIR)/crypto/drbg.ko@ge4.2 \ + $(LINUX_DIR)/crypto/jitterentropy_rng.ko@ge4.2 \ + $(LINUX_DIR)/crypto/krng.ko@lt4.2 \ + $(LINUX_DIR)/crypto/rng.ko + AUTOLOAD:=$(call AutoLoad,09,drbg@ge4.2 jitterentropy_rng@ge4.2 krng@lt4.2 rng) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-rng)) + + +define KernelPackage/crypto-seqiv + TITLE:=CryptoAPI Sequence Number IV Generator + DEPENDS:=+kmod-crypto-aead +kmod-crypto-rng + KCONFIG:=CONFIG_CRYPTO_SEQIV + FILES:=$(LINUX_DIR)/crypto/seqiv.ko + AUTOLOAD:=$(call AutoLoad,09,seqiv) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-seqiv)) + + define KernelPackage/crypto-sha1 TITLE:=SHA1 digest CryptoAPI module DEPENDS:=+kmod-crypto-hash @@ -607,62 +646,6 @@ endef $(eval $(call KernelPackage,crypto-sha512)) -define KernelPackage/crypto-misc - TITLE:=Other CryptoAPI modules - DEPENDS:=+kmod-crypto-manager - KCONFIG:= \ - CONFIG_CRYPTO_ANUBIS \ - CONFIG_CRYPTO_BLOWFISH \ - CONFIG_CRYPTO_CAMELLIA \ - CONFIG_CRYPTO_CAST5 \ - CONFIG_CRYPTO_CAST6 \ - CONFIG_CRYPTO_FCRYPT \ - CONFIG_CRYPTO_KHAZAD \ - CONFIG_CRYPTO_SERPENT \ - CONFIG_CRYPTO_TEA \ - CONFIG_CRYPTO_TGR192 \ - CONFIG_CRYPTO_TWOFISH \ - CONFIG_CRYPTO_TWOFISH_COMMON \ - CONFIG_CRYPTO_TWOFISH_586 \ - CONFIG_CRYPTO_WP512 - FILES:= \ - $(LINUX_DIR)/crypto/anubis.ko \ - $(LINUX_DIR)/crypto/camellia_generic.ko \ - $(LINUX_DIR)/crypto/cast_common.ko \ - $(LINUX_DIR)/crypto/cast5_generic.ko \ - $(LINUX_DIR)/crypto/cast6_generic.ko \ - $(LINUX_DIR)/crypto/khazad.ko \ - $(LINUX_DIR)/crypto/tea.ko \ - $(LINUX_DIR)/crypto/tgr192.ko \ - $(LINUX_DIR)/crypto/twofish_common.ko \ - $(LINUX_DIR)/crypto/wp512.ko \ - $(LINUX_DIR)/crypto/twofish_generic.ko \ - $(LINUX_DIR)/crypto/blowfish_common.ko \ - $(LINUX_DIR)/crypto/blowfish_generic.ko \ - $(LINUX_DIR)/crypto/serpent_generic.ko - $(call AddDepends/crypto) -endef - -ifndef CONFIG_TARGET_x86_64 - define KernelPackage/crypto-misc/x86 - FILES+=$(LINUX_DIR)/arch/x86/crypto/twofish-i586.ko - endef -endif - -$(eval $(call KernelPackage,crypto-misc)) - - -define KernelPackage/crypto-null - TITLE:=Null CryptoAPI module - KCONFIG:=CONFIG_CRYPTO_NULL - FILES:=$(LINUX_DIR)/crypto/crypto_null.ko - AUTOLOAD:=$(call AutoLoad,09,crypto_null) - $(call AddDepends/crypto, +kmod-crypto-hash) -endef - -$(eval $(call KernelPackage,crypto-null)) - - define KernelPackage/crypto-test TITLE:=Test CryptoAPI module KCONFIG:=CONFIG_CRYPTO_TEST @@ -673,6 +656,34 @@ endef $(eval $(call KernelPackage,crypto-test)) +define KernelPackage/crypto-user + TITLE:=CryptoAPI userspace interface + DEPENDS:=+kmod-crypto-hash +kmod-crypto-manager + KCONFIG:= \ + CONFIG_CRYPTO_USER_API \ + CONFIG_CRYPTO_USER_API_HASH \ + CONFIG_CRYPTO_USER_API_SKCIPHER + FILES:= \ + $(LINUX_DIR)/crypto/af_alg.ko \ + $(LINUX_DIR)/crypto/algif_hash.ko \ + $(LINUX_DIR)/crypto/algif_skcipher.ko + AUTOLOAD:=$(call AutoLoad,09,af_alg algif_hash algif_skcipher) + $(call AddDepends/crypto) +endef + +$(eval $(call KernelPackage,crypto-user)) + + +define KernelPackage/crypto-wq + TITLE:=CryptoAPI work queue handling + KCONFIG:=CONFIG_CRYPTO_WORKQUEUE + FILES:=$(LINUX_DIR)/crypto/crypto_wq.ko + AUTOLOAD:=$(call AutoLoad,09,crypto_wq) + $(call AddDepends/crypto) +endef +$(eval $(call KernelPackage,crypto-wq)) + + define KernelPackage/crypto-xts TITLE:=XTS cipher CryptoAPI module DEPENDS:=+kmod-crypto-gf128 +kmod-crypto-manager @@ -683,3 +694,4 @@ define KernelPackage/crypto-xts endef $(eval $(call KernelPackage,crypto-xts)) + diff --git a/package/kernel/linux/modules/firewire.mk b/package/kernel/linux/modules/firewire.mk index 18b531a29..1e2d94272 100644 --- a/package/kernel/linux/modules/firewire.mk +++ b/package/kernel/linux/modules/firewire.mk @@ -22,6 +22,22 @@ endef $(eval $(call KernelPackage,firewire)) +define KernelPackage/firewire-net + SUBMENU:=$(FIREWIRE_MENU) + TITLE:=Support for IP networking over FireWire + DEPENDS:=kmod-firewire + KCONFIG:=CONFIG_FIREWIRE_NET + FILES:=$(LINUX_DIR)/drivers/firewire/firewire-net.ko + AUTOLOAD:=$(call AutoProbe,firewire-net) +endef + +define KernelPackage/firewire-net/description + Kernel support for IPv4 over FireWire +endef + +$(eval $(call KernelPackage,firewire-net)) + + define KernelPackage/firewire-ohci SUBMENU:=$(FIREWIRE_MENU) TITLE:=Support for OHCI-1394 controllers @@ -58,17 +74,3 @@ endef $(eval $(call KernelPackage,firewire-sbp2)) -define KernelPackage/firewire-net - SUBMENU:=$(FIREWIRE_MENU) - TITLE:=Support for IP networking over FireWire - DEPENDS:=kmod-firewire - KCONFIG:=CONFIG_FIREWIRE_NET - FILES:=$(LINUX_DIR)/drivers/firewire/firewire-net.ko - AUTOLOAD:=$(call AutoProbe,firewire-net) -endef - -define KernelPackage/firewire-net/description - Kernel support for IPv4 over FireWire -endef - -$(eval $(call KernelPackage,firewire-net)) diff --git a/package/kernel/linux/modules/fs.mk b/package/kernel/linux/modules/fs.mk index f75758557..8dca0f96f 100644 --- a/package/kernel/linux/modules/fs.mk +++ b/package/kernel/linux/modules/fs.mk @@ -7,25 +7,6 @@ FS_MENU:=Filesystems -define KernelPackage/fs-fscache - SUBMENU:=$(FS_MENU) - TITLE:=General filesystem local cache manager - DEPENDS:= - KCONFIG:=\ - CONFIG_FSCACHE=m \ - CONFIG_FSCACHE_STATS=y \ - CONFIG_FSCACHE_HISTOGRAM=n \ - CONFIG_FSCACHE_DEBUG=n \ - CONFIG_FSCACHE_OBJECT_LIST=n \ - CONFIG_CACHEFILES=y \ - CONFIG_CACHEFILES_DEBUG=n \ - CONFIG_CACHEFILES_HISTOGRAM=n - FILES:=$(LINUX_DIR)/fs/fscache/fscache.ko - AUTOLOAD:=$(call AutoLoad,29,fscache) -endef - -$(eval $(call KernelPackage,fs-fscache)) - define KernelPackage/fs-9p SUBMENU:=$(FS_MENU) TITLE:=Plan 9 Resource Sharing Support @@ -45,6 +26,7 @@ endef $(eval $(call KernelPackage,fs-9p)) + define KernelPackage/fs-afs SUBMENU:=$(FS_MENU) TITLE:=Andrew FileSystem client @@ -142,6 +124,7 @@ endef $(eval $(call KernelPackage,fs-configfs)) + define KernelPackage/fs-cramfs SUBMENU:=$(FS_MENU) TITLE:=Compressed RAM/ROM filesystem support @@ -158,6 +141,23 @@ endef $(eval $(call KernelPackage,fs-cramfs)) + +define KernelPackage/fs-efivarfs + SUBMENU:=$(FS_MENU) + TITLE:=efivar filesystem support + KCONFIG:=CONFIG_EFIVAR_FS + FILES:=$(LINUX_DIR)/fs/efivarfs/efivarfs.ko + DEPENDS:=@(x86_64||x86) + AUTOLOAD:=$(call Autoload,90,efivarfs) +endef + +define KernelPackage/fs-efivarfs/description + Kernel module to support efivarfs file system mountpoint. +endef + +$(eval $(call KernelPackage,fs-efivarfs)) + + define KernelPackage/fs-exportfs SUBMENU:=$(FS_MENU) TITLE:=exportfs kernel server support @@ -220,19 +220,24 @@ endef $(eval $(call KernelPackage,fs-f2fs)) -define KernelPackage/fuse +define KernelPackage/fs-fscache SUBMENU:=$(FS_MENU) - TITLE:=FUSE (Filesystem in Userspace) support - KCONFIG:= CONFIG_FUSE_FS - FILES:=$(LINUX_DIR)/fs/fuse/fuse.ko - AUTOLOAD:=$(call AutoLoad,80,fuse) + TITLE:=General filesystem local cache manager + DEPENDS:= + KCONFIG:=\ + CONFIG_FSCACHE=m \ + CONFIG_FSCACHE_STATS=y \ + CONFIG_FSCACHE_HISTOGRAM=n \ + CONFIG_FSCACHE_DEBUG=n \ + CONFIG_FSCACHE_OBJECT_LIST=n \ + CONFIG_CACHEFILES=y \ + CONFIG_CACHEFILES_DEBUG=n \ + CONFIG_CACHEFILES_HISTOGRAM=n + FILES:=$(LINUX_DIR)/fs/fscache/fscache.ko + AUTOLOAD:=$(call AutoLoad,29,fscache) endef -define KernelPackage/fuse/description - Kernel module for userspace filesystem support -endef - -$(eval $(call KernelPackage,fuse)) +$(eval $(call KernelPackage,fs-fscache)) define KernelPackage/fs-hfs @@ -284,6 +289,21 @@ endef $(eval $(call KernelPackage,fs-isofs)) +define KernelPackage/fs-jfs + SUBMENU:=$(FS_MENU) + TITLE:=JFS filesystem support + KCONFIG:=CONFIG_JFS_FS + FILES:=$(LINUX_DIR)/fs/jfs/jfs.ko + AUTOLOAD:=$(call AutoLoad,30,jfs,1) + $(call AddDepends/nls) +endef + +define KernelPackage/fs-jfs/description + Kernel module for JFS support +endef + +$(eval $(call KernelPackage,fs-jfs)) + define KernelPackage/fs-minix SUBMENU:=$(FS_MENU) TITLE:=Minix filesystem support @@ -335,37 +355,6 @@ endef $(eval $(call KernelPackage,fs-nfs)) -define KernelPackage/fs-nfs-v3 - SUBMENU:=$(FS_MENU) - TITLE:=NFS3 filesystem client support - DEPENDS:=+kmod-fs-nfs - FILES:= \ - $(LINUX_DIR)/fs/nfs/nfsv3.ko - AUTOLOAD:=$(call AutoLoad,41,nfsv3) -endef - -define KernelPackage/fs-nfs-v3/description - Kernel module for NFS v3 client support -endef - -$(eval $(call KernelPackage,fs-nfs-v3)) - -define KernelPackage/fs-nfs-v4 - SUBMENU:=$(FS_MENU) - TITLE:=NFS4 filesystem client support - DEPENDS:=+kmod-fs-nfs - KCONFIG:= \ - CONFIG_NFS_V4=y - FILES:= \ - $(LINUX_DIR)/fs/nfs/nfsv4.ko - AUTOLOAD:=$(call AutoLoad,41,nfsv4) -endef - -define KernelPackage/fs-nfs-v4/description - Kernel module for NFS v4 support -endef - -$(eval $(call KernelPackage,fs-nfs-v4)) define KernelPackage/fs-nfs-common SUBMENU:=$(FS_MENU) @@ -413,6 +402,40 @@ endef $(eval $(call KernelPackage,fs-nfs-common-rpcsec)) +define KernelPackage/fs-nfs-v3 + SUBMENU:=$(FS_MENU) + TITLE:=NFS3 filesystem client support + DEPENDS:=+kmod-fs-nfs + FILES:= \ + $(LINUX_DIR)/fs/nfs/nfsv3.ko + AUTOLOAD:=$(call AutoLoad,41,nfsv3) +endef + +define KernelPackage/fs-nfs-v3/description + Kernel module for NFS v3 client support +endef + +$(eval $(call KernelPackage,fs-nfs-v3)) + + +define KernelPackage/fs-nfs-v4 + SUBMENU:=$(FS_MENU) + TITLE:=NFS4 filesystem client support + DEPENDS:=+kmod-fs-nfs + KCONFIG:= \ + CONFIG_NFS_V4=y + FILES:= \ + $(LINUX_DIR)/fs/nfs/nfsv4.ko + AUTOLOAD:=$(call AutoLoad,41,nfsv4) +endef + +define KernelPackage/fs-nfs-v4/description + Kernel module for NFS v4 support +endef + +$(eval $(call KernelPackage,fs-nfs-v4)) + + define KernelPackage/fs-nfsd SUBMENU:=$(FS_MENU) TITLE:=NFS kernel server support @@ -532,17 +555,18 @@ endef $(eval $(call KernelPackage,fs-xfs)) -define KernelPackage/fs-jfs +define KernelPackage/fuse SUBMENU:=$(FS_MENU) - TITLE:=JFS filesystem support - KCONFIG:=CONFIG_JFS_FS - FILES:=$(LINUX_DIR)/fs/jfs/jfs.ko - AUTOLOAD:=$(call AutoLoad,30,jfs,1) - $(call AddDepends/nls) + TITLE:=FUSE (Filesystem in Userspace) support + KCONFIG:= CONFIG_FUSE_FS + FILES:=$(LINUX_DIR)/fs/fuse/fuse.ko + AUTOLOAD:=$(call AutoLoad,80,fuse) endef -define KernelPackage/fs-jfs/description - Kernel module for JFS support +define KernelPackage/fuse/description + Kernel module for userspace filesystem support endef -$(eval $(call KernelPackage,fs-jfs)) +$(eval $(call KernelPackage,fuse)) + + diff --git a/package/kernel/linux/modules/hwmon.mk b/package/kernel/linux/modules/hwmon.mk index ed05caeb7..e6dfa73de 100644 --- a/package/kernel/linux/modules/hwmon.mk +++ b/package/kernel/linux/modules/hwmon.mk @@ -29,21 +29,6 @@ define AddDepends/hwmon DEPENDS:=kmod-hwmon-core $(1) endef -define KernelPackage/hwmon-vid - TITLE:=VID/VRM/VRD voltage conversion module. - KCONFIG:=CONFIG_HWMON_VID - FILES:=$(LINUX_DIR)/drivers/hwmon/hwmon-vid.ko - AUTOLOAD:=$(call AutoLoad,41,hwmon-vid) - $(call AddDepends/hwmon,) -endef - -define KernelPackage/hwmon-vid/description - VID/VRM/VRD voltage conversion module for hardware monitoring -endef - -$(eval $(call KernelPackage,hwmon-vid)) - - define KernelPackage/hwmon-adt7410 TITLE:=ADT7410 monitoring support KCONFIG:= \ @@ -78,6 +63,21 @@ endef $(eval $(call KernelPackage,hwmon-adt7475)) +define KernelPackage/hwmon-gpiofan + TITLE:=Generic GPIO FAN support + KCONFIG:=CONFIG_SENSORS_GPIO_FAN + FILES:=$(LINUX_DIR)/drivers/hwmon/gpio-fan.ko + AUTOLOAD:=$(call AutoLoad,60,gpio-fan) + $(call AddDepends/hwmon,+kmod-i2c-core +PACKAGE_kmod-thermal:kmod-thermal) +endef + +define KernelPackage/hwmon-gpiofan/description + Kernel module for GPIO controlled FANs +endef + +$(eval $(call KernelPackage,hwmon-gpiofan)) + + define KernelPackage/hwmon-ina209 TITLE:=INA209 monitoring support KCONFIG:=CONFIG_SENSORS_INA209 @@ -93,21 +93,6 @@ endef $(eval $(call KernelPackage,hwmon-ina209)) -define KernelPackage/hwmon-nct6775 - TITLE:=NCT6106D/6775F/6776F/6779D/6791D/6792D/6793D and compatibles monitoring support - KCONFIG:=CONFIG_SENSORS_NCT6775 - FILES:=$(LINUX_DIR)/drivers/hwmon/nct6775.ko - AUTOLOAD:=$(call AutoProbe,nct6775) - $(call AddDepends/hwmon,@PCI_SUPPORT @TARGET_x86 +kmod-hwmon-vid) -endef - -define KernelPackage/hwmon-nct6775/description - Kernel module for NCT6106D/6775F/6776F/6779D/6791D/6792D/6793D thermal monitor chip -endef - -$(eval $(call KernelPackage,hwmon-nct6775)) - - define KernelPackage/hwmon-ina2xx TITLE:=INA2XX monitoring support KCONFIG:=CONFIG_SENSORS_INA2XX @@ -137,6 +122,7 @@ endef $(eval $(call KernelPackage,hwmon-it87)) + define KernelPackage/hwmon-lm63 TITLE:=LM63/64 monitoring support KCONFIG:=CONFIG_SENSORS_LM63 @@ -211,6 +197,7 @@ endef $(eval $(call KernelPackage,hwmon-lm90)) + define KernelPackage/hwmon-lm92 TITLE:=LM92 monitoring support KCONFIG:=CONFIG_SENSORS_LM92 @@ -225,6 +212,7 @@ endef $(eval $(call KernelPackage,hwmon-lm92)) + define KernelPackage/hwmon-lm95241 TITLE:=LM95241 monitoring support KCONFIG:=CONFIG_SENSORS_LM95241 @@ -239,6 +227,7 @@ endef $(eval $(call KernelPackage,hwmon-lm95241)) + define KernelPackage/hwmon-ltc4151 TITLE:=LTC4151 monitoring support KCONFIG:=CONFIG_SENSORS_LTC4151 @@ -253,19 +242,51 @@ endef $(eval $(call KernelPackage,hwmon-ltc4151)) -define KernelPackage/hwmon-sht21 - TITLE:=Sensiron SHT21 and compat. monitoring support - KCONFIG:=CONFIG_SENSORS_SHT21 - FILES:=$(LINUX_DIR)/drivers/hwmon/sht21.ko - AUTOLOAD:=$(call AutoProbe,sht21) - $(call AddDepends/hwmon,+kmod-i2c-core) + +define KernelPackage/hwmon-nct6775 + TITLE:=NCT6106D/6775F/6776F/6779D/6791D/6792D/6793D and compatibles monitoring support + KCONFIG:=CONFIG_SENSORS_NCT6775 + FILES:=$(LINUX_DIR)/drivers/hwmon/nct6775.ko + AUTOLOAD:=$(call AutoProbe,nct6775) + $(call AddDepends/hwmon,@PCI_SUPPORT @TARGET_x86 +kmod-hwmon-vid) endef -define KernelPackage/hwmon-sht21/description - Kernel module for Sensirion SHT21 and SHT25 temperature and humidity sensors chip +define KernelPackage/hwmon-nct6775/description + Kernel module for NCT6106D/6775F/6776F/6779D/6791D/6792D/6793D thermal monitor chip endef -$(eval $(call KernelPackage,hwmon-sht21)) +$(eval $(call KernelPackage,hwmon-nct6775)) + + +define KernelPackage/hwmon-pc87360 + TITLE:=PC87360 monitoring support + KCONFIG:=CONFIG_SENSORS_PC87360 + FILES:=$(LINUX_DIR)/drivers/hwmon/pc87360.ko + AUTOLOAD:=$(call AutoProbe,pc87360) + $(call AddDepends/hwmon,@TARGET_x86 +kmod-hwmon-vid) +endef + +define KernelPackage/hwmon-pc87360/description + Kernel modules for PC87360 chips +endef + +$(eval $(call KernelPackage,hwmon-pc87360)) + + +define KernelPackage/hwmon-pwmfan + TITLE:=Generic PWM FAN support + KCONFIG:=CONFIG_SENSORS_PWM_FAN + FILES:=$(LINUX_DIR)/drivers/hwmon/pwm-fan.ko + AUTOLOAD:=$(call AutoLoad,60,pwm-fan) + $(call AddDepends/hwmon, +PACKAGE_kmod-thermal:kmod-thermal) +endef + +define KernelPackage/hwmon-pwmfan/description + Kernel module for PWM controlled FANs +endef + +$(eval $(call KernelPackage,hwmon-pwmfan)) + define KernelPackage/hwmon-sch5627 TITLE:=SMSC SCH5627 monitoring support @@ -283,66 +304,20 @@ endef $(eval $(call KernelPackage,hwmon-sch5627)) -define KernelPackage/hwmon-pc87360 - TITLE:=PC87360 monitoring support - KCONFIG:=CONFIG_SENSORS_PC87360 - FILES:=$(LINUX_DIR)/drivers/hwmon/pc87360.ko - AUTOLOAD:=$(call AutoProbe,pc87360) - $(call AddDepends/hwmon,@TARGET_x86 +kmod-hwmon-vid) + +define KernelPackage/hwmon-sht21 + TITLE:=Sensiron SHT21 and compat. monitoring support + KCONFIG:=CONFIG_SENSORS_SHT21 + FILES:=$(LINUX_DIR)/drivers/hwmon/sht21.ko + AUTOLOAD:=$(call AutoProbe,sht21) + $(call AddDepends/hwmon,+kmod-i2c-core) endef -define KernelPackage/hwmon-pc87360/description - Kernel modules for PC87360 chips +define KernelPackage/hwmon-sht21/description + Kernel module for Sensirion SHT21 and SHT25 temperature and humidity sensors chip endef -$(eval $(call KernelPackage,hwmon-pc87360)) - - -define KernelPackage/hwmon-w83627hf - TITLE:=Winbond W83627HF monitoring support - KCONFIG:=CONFIG_SENSORS_W83627HF - FILES:=$(LINUX_DIR)/drivers/hwmon/w83627hf.ko - AUTOLOAD:=$(call AutoLoad,50,w83627hf) - $(call AddDepends/hwmon,@TARGET_x86 +kmod-hwmon-vid) -endef - -define KernelPackage/hwmon-w83627hf/description - Kernel module for the Winbond W83627HF chips. -endef - -$(eval $(call KernelPackage,hwmon-w83627hf)) - - -define KernelPackage/hwmon-w83627ehf - TITLE:=Winbond W83627EHF/EHG/DHG/UHG, W83667HG monitoring support - KCONFIG:=CONFIG_SENSORS_W83627EHF - FILES:=$(LINUX_DIR)/drivers/hwmon/w83627ehf.ko - AUTOLOAD:=$(call AutoProbe,w83627ehf) - $(call AddDepends/hwmon,@TARGET_x86 +kmod-hwmon-vid) -endef - -define KernelPackage/hwmon-w83627ehf/description - Kernel module for Winbond W83627EHF/EHG/DHG/UHG and W83667HG thermal monitor chip - Support for NCT6775F and NCT6776F has been removed from this driver in favour of - using the nct6775 driver to handle those chips. -endef - -$(eval $(call KernelPackage,hwmon-w83627ehf)) - - -define KernelPackage/hwmon-w83793 - TITLE:=Winbond W83793G/R monitoring support - KCONFIG:=CONFIG_SENSORS_W83793 - FILES:=$(LINUX_DIR)/drivers/hwmon/w83793.ko - AUTOLOAD:=$(call AutoProbe,w83793) - $(call AddDepends/hwmon,+kmod-i2c-core +kmod-hwmon-vid) -endef - -define KernelPackage/hwmon-w83793/description - Kernel module for the Winbond W83793G and W83793R chips. -endef - -$(eval $(call KernelPackage,hwmon-w83793)) +$(eval $(call KernelPackage,hwmon-sht21)) define KernelPackage/hwmon-tmp102 @@ -390,31 +365,65 @@ endef $(eval $(call KernelPackage,hwmon-tmp421)) -define KernelPackage/hwmon-gpiofan - TITLE:=Generic GPIO FAN support - KCONFIG:=CONFIG_SENSORS_GPIO_FAN - FILES:=$(LINUX_DIR)/drivers/hwmon/gpio-fan.ko - AUTOLOAD:=$(call AutoLoad,60,gpio-fan) - $(call AddDepends/hwmon,+kmod-i2c-core +PACKAGE_kmod-thermal:kmod-thermal) +define KernelPackage/hwmon-vid + TITLE:=VID/VRM/VRD voltage conversion module. + KCONFIG:=CONFIG_HWMON_VID + FILES:=$(LINUX_DIR)/drivers/hwmon/hwmon-vid.ko + AUTOLOAD:=$(call AutoLoad,41,hwmon-vid) + $(call AddDepends/hwmon,) endef -define KernelPackage/hwmon-gpiofan/description - Kernel module for GPIO controlled FANs +define KernelPackage/hwmon-vid/description + VID/VRM/VRD voltage conversion module for hardware monitoring endef -$(eval $(call KernelPackage,hwmon-gpiofan)) +$(eval $(call KernelPackage,hwmon-vid)) -define KernelPackage/hwmon-pwmfan - TITLE:=Generic PWM FAN support - KCONFIG:=CONFIG_SENSORS_PWM_FAN - FILES:=$(LINUX_DIR)/drivers/hwmon/pwm-fan.ko - AUTOLOAD:=$(call AutoLoad,60,pwm-fan) - $(call AddDepends/hwmon, +PACKAGE_kmod-thermal:kmod-thermal) +define KernelPackage/hwmon-w83627ehf + TITLE:=Winbond W83627EHF/EHG/DHG/UHG, W83667HG monitoring support + KCONFIG:=CONFIG_SENSORS_W83627EHF + FILES:=$(LINUX_DIR)/drivers/hwmon/w83627ehf.ko + AUTOLOAD:=$(call AutoProbe,w83627ehf) + $(call AddDepends/hwmon,@TARGET_x86 +kmod-hwmon-vid) endef -define KernelPackage/hwmon-pwmfan/description - Kernel module for PWM controlled FANs +define KernelPackage/hwmon-w83627ehf/description + Kernel module for Winbond W83627EHF/EHG/DHG/UHG and W83667HG thermal monitor chip + Support for NCT6775F and NCT6776F has been removed from this driver in favour of + using the nct6775 driver to handle those chips. endef -$(eval $(call KernelPackage,hwmon-pwmfan)) +$(eval $(call KernelPackage,hwmon-w83627ehf)) + + +define KernelPackage/hwmon-w83627hf + TITLE:=Winbond W83627HF monitoring support + KCONFIG:=CONFIG_SENSORS_W83627HF + FILES:=$(LINUX_DIR)/drivers/hwmon/w83627hf.ko + AUTOLOAD:=$(call AutoLoad,50,w83627hf) + $(call AddDepends/hwmon,@TARGET_x86 +kmod-hwmon-vid) +endef + +define KernelPackage/hwmon-w83627hf/description + Kernel module for the Winbond W83627HF chips. +endef + +$(eval $(call KernelPackage,hwmon-w83627hf)) + + +define KernelPackage/hwmon-w83793 + TITLE:=Winbond W83793G/R monitoring support + KCONFIG:=CONFIG_SENSORS_W83793 + FILES:=$(LINUX_DIR)/drivers/hwmon/w83793.ko + AUTOLOAD:=$(call AutoProbe,w83793) + $(call AddDepends/hwmon,+kmod-i2c-core +kmod-hwmon-vid) +endef + +define KernelPackage/hwmon-w83793/description + Kernel module for the Winbond W83793G and W83793R chips. +endef + +$(eval $(call KernelPackage,hwmon-w83793)) + + diff --git a/package/kernel/linux/modules/i2c.mk b/package/kernel/linux/modules/i2c.mk index 14c5b6448..4cf37dae0 100644 --- a/package/kernel/linux/modules/i2c.mk +++ b/package/kernel/linux/modules/i2c.mk @@ -24,10 +24,6 @@ I2C_CORE_MODULES:= \ CONFIG_I2C:drivers/i2c/i2c-core \ CONFIG_I2C_CHARDEV:drivers/i2c/i2c-dev -ifeq ($(CONFIG_OF),y) - I2C_CORE_MODULES+=CONFIG_OF_I2C:drivers/of/of_i2c@lt3.12 -endif - define KernelPackage/i2c-core $(call i2c_defaults,$(I2C_CORE_MODULES),51) TITLE:=I2C support @@ -104,43 +100,6 @@ endef $(eval $(call KernelPackage,i2c-gpio)) -I2C_TINY_USB_MODULES:= \ - CONFIG_I2C_TINY_USB:drivers/i2c/busses/i2c-tiny-usb - -define KernelPackage/i2c-tiny-usb - $(call i2c_defaults,$(I2C_TINY_USB_MODULES),59) - TITLE:=I2C Tiny USB adaptor - DEPENDS:=@USB_SUPPORT kmod-i2c-core +kmod-usb-core -endef - -define KernelPackage/i2c-tiny-usb/description - Kernel module for the I2C Tiny USB adaptor developed - by Till Harbaum (http://www.harbaum.org/till/i2c_tiny_usb) -endef - -$(eval $(call KernelPackage,i2c-tiny-usb)) - - -I2C_PIIX4_MODULES:= \ - CONFIG_I2C_PIIX4:drivers/i2c/busses/i2c-piix4 - -define KernelPackage/i2c-piix4 - $(call i2c_defaults,$(I2C_PIIX4_MODULES),59) - TITLE:=Intel PIIX4 and compatible I2C interfaces - DEPENDS:=@PCI_SUPPORT @TARGET_x86 kmod-i2c-core -endef - -define KernelPackage/i2c-piix4/description - Support for the Intel PIIX4 family of mainboard I2C interfaces, - specifically Intel PIIX4, Intel 440MX, ATI IXP200, ATI IXP300, - ATI IXP400, ATI SB600, ATI SB700/SP5100, ATI SB800, AMD Hudson-2, - AMD ML, AMD CZ, Serverworks OSB4, Serverworks CSB5, - Serverworks CSB6, Serverworks HT-1000, Serverworks HT-1100 and - SMSC Victory66. -endef - -$(eval $(call KernelPackage,i2c-piix4)) - I2C_I801_MODULES:= \ CONFIG_I2C_I801:drivers/i2c/busses/i2c-i801 @@ -167,22 +126,6 @@ endef $(eval $(call KernelPackage,i2c-i801)) -I2C_SMBUS_MODULES:= \ - CONFIG_I2C_SMBUS:drivers/i2c/i2c-smbus - -define KernelPackage/i2c-smbus - $(call i2c_defaults,$(I2C_SMBUS_MODULES),58) - TITLE:=SMBus-specific protocols helper - DEPENDS:=kmod-i2c-core -endef - -define KernelPackage/i2c-smbus/description - Support for the SMBus extensions to the I2C specification. -endef - -$(eval $(call KernelPackage,i2c-smbus)) - - I2C_MUX_MODULES:= \ CONFIG_I2C_MUX:drivers/i2c/i2c-mux @@ -213,6 +156,22 @@ endef $(eval $(call KernelPackage,i2c-mux-gpio)) + +I2C_MUX_PCA9541_MODULES:= \ + CONFIG_I2C_MUX_PCA9541:drivers/i2c/muxes/i2c-mux-pca9541 + +define KernelPackage/i2c-mux-pca9541 + $(call i2c_defaults,$(I2C_MUX_PCA9541_MODULES),51) + TITLE:=Philips PCA9541 I2C mux/switches + DEPENDS:=kmod-i2c-mux +endef + +define KernelPackage/i2c-mux-pca9541/description + Kernel modules for PCA9541 I2C bus mux/switching devices +endef + +$(eval $(call KernelPackage,i2c-mux-pca9541)) + I2C_MUX_PCA954x_MODULES:= \ CONFIG_I2C_MUX_PCA954x:drivers/i2c/muxes/i2c-mux-pca954x @@ -229,17 +188,58 @@ endef $(eval $(call KernelPackage,i2c-mux-pca954x)) -I2C_MUX_PCA9541_MODULES:= \ - CONFIG_I2C_MUX_PCA9541:drivers/i2c/muxes/i2c-mux-pca9541 +I2C_PIIX4_MODULES:= \ + CONFIG_I2C_PIIX4:drivers/i2c/busses/i2c-piix4 -define KernelPackage/i2c-mux-pca9541 - $(call i2c_defaults,$(I2C_MUX_PCA9541_MODULES),51) - TITLE:=Philips PCA9541 I2C mux/switches - DEPENDS:=kmod-i2c-mux +define KernelPackage/i2c-piix4 + $(call i2c_defaults,$(I2C_PIIX4_MODULES),59) + TITLE:=Intel PIIX4 and compatible I2C interfaces + DEPENDS:=@PCI_SUPPORT @TARGET_x86 kmod-i2c-core endef -define KernelPackage/i2c-mux-pca9541/description - Kernel modules for PCA9541 I2C bus mux/switching devices +define KernelPackage/i2c-piix4/description + Support for the Intel PIIX4 family of mainboard I2C interfaces, + specifically Intel PIIX4, Intel 440MX, ATI IXP200, ATI IXP300, + ATI IXP400, ATI SB600, ATI SB700/SP5100, ATI SB800, AMD Hudson-2, + AMD ML, AMD CZ, Serverworks OSB4, Serverworks CSB5, + Serverworks CSB6, Serverworks HT-1000, Serverworks HT-1100 and + SMSC Victory66. endef -$(eval $(call KernelPackage,i2c-mux-pca9541)) +$(eval $(call KernelPackage,i2c-piix4)) + + +I2C_SMBUS_MODULES:= \ + CONFIG_I2C_SMBUS:drivers/i2c/i2c-smbus + +define KernelPackage/i2c-smbus + $(call i2c_defaults,$(I2C_SMBUS_MODULES),58) + TITLE:=SMBus-specific protocols helper + DEPENDS:=kmod-i2c-core +endef + +define KernelPackage/i2c-smbus/description + Support for the SMBus extensions to the I2C specification. +endef + +$(eval $(call KernelPackage,i2c-smbus)) + + + +I2C_TINY_USB_MODULES:= \ + CONFIG_I2C_TINY_USB:drivers/i2c/busses/i2c-tiny-usb + +define KernelPackage/i2c-tiny-usb + $(call i2c_defaults,$(I2C_TINY_USB_MODULES),59) + TITLE:=I2C Tiny USB adaptor + DEPENDS:=@USB_SUPPORT kmod-i2c-core +kmod-usb-core +endef + +define KernelPackage/i2c-tiny-usb/description + Kernel module for the I2C Tiny USB adaptor developed + by Till Harbaum (http://www.harbaum.org/till/i2c_tiny_usb) +endef + +$(eval $(call KernelPackage,i2c-tiny-usb)) + + diff --git a/package/kernel/linux/modules/iio.mk b/package/kernel/linux/modules/iio.mk index 8990e5481..c35ccca1b 100644 --- a/package/kernel/linux/modules/iio.mk +++ b/package/kernel/linux/modules/iio.mk @@ -52,6 +52,21 @@ endef $(eval $(call KernelPackage,iio-ad799x)) +define KernelPackage/iio-mxs-lradc + SUBMENU:=$(IIO_MENU) + DEPENDS:=@TARGET_mxs +kmod-iio-core + TITLE:=Freescale i.MX23/i.MX28 LRADC ADC driver + KCONFIG:= \ + CONFIG_MXS_LRADC_ADC + FILES:=$(LINUX_DIR)/drivers/iio/adc/mxs-lradc-adc.ko + AUTOLOAD:=$(call AutoLoad,56,mxs-lradc-adc) +endef + +define KernelPackage/iio-mxs-lradc/description + Support for Freescale's i.MX23/i.MX28 SoC internal Low-Resolution ADC +endef + +$(eval $(call KernelPackage,iio-mxs-lradc)) define KernelPackage/iio-dht11 SUBMENU:=$(IIO_MENU) diff --git a/package/kernel/linux/modules/leds.mk b/package/kernel/linux/modules/leds.mk index 51002fb3d..7019f0477 100644 --- a/package/kernel/linux/modules/leds.mk +++ b/package/kernel/linux/modules/leds.mk @@ -32,7 +32,7 @@ define KernelPackage/ledtrig-heartbeat AUTOLOAD:=$(call AutoLoad,50,ledtrig-heartbeat) endef -define KernelPackage/ledtrig-gpio/description +define KernelPackage/ledtrig-heartbeat/description Kernel module that allows LEDs to blink like heart beat endef diff --git a/package/kernel/linux/modules/netdevices.mk b/package/kernel/linux/modules/netdevices.mk index a9740ef35..edc982d3c 100644 --- a/package/kernel/linux/modules/netdevices.mk +++ b/package/kernel/linux/modules/netdevices.mk @@ -519,9 +519,9 @@ $(eval $(call KernelPackage,e1000e)) define KernelPackage/igb SUBMENU:=$(NETWORK_DEVICES_MENU) TITLE:=Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support - DEPENDS:=@PCI_SUPPORT +kmod-i2c-core +kmod-i2c-algo-bit +kmod-ptp + DEPENDS:=@PCI_SUPPORT +kmod-i2c-core +kmod-i2c-algo-bit +kmod-ptp +kmod-hwmon-core KCONFIG:=CONFIG_IGB \ - CONFIG_IGB_HWMON=n \ + CONFIG_IGB_HWMON=y \ CONFIG_IGB_DCA=n FILES:=$(LINUX_DIR)/drivers/net/ethernet/intel/igb/igb.ko AUTOLOAD:=$(call AutoLoad,35,igb) @@ -539,7 +539,7 @@ define KernelPackage/igbvf TITLE:=Intel(R) 82576 Virtual Function Ethernet support DEPENDS:=@PCI_SUPPORT @TARGET_x86 +kmod-i2c-core +kmod-i2c-algo-bit +kmod-ptp KCONFIG:=CONFIG_IGBVF \ - CONFIG_IGB_HWMON=n \ + CONFIG_IGB_HWMON=y \ CONFIG_IGB_DCA=n FILES:=$(LINUX_DIR)/drivers/net/ethernet/intel/igbvf/igbvf.ko AUTOLOAD:=$(call AutoLoad,35,igbvf) @@ -555,10 +555,10 @@ $(eval $(call KernelPackage,igbvf)) define KernelPackage/ixgbe SUBMENU:=$(NETWORK_DEVICES_MENU) TITLE:=Intel(R) 82598/82599 PCI-Express 10 Gigabit Ethernet support - DEPENDS:=@PCI_SUPPORT +kmod-mdio +kmod-ptp + DEPENDS:=@PCI_SUPPORT +kmod-mdio +kmod-ptp +kmod-hwmon-core KCONFIG:=CONFIG_IXGBE \ CONFIG_IXGBE_VXLAN=n \ - CONFIG_IXGBE_HWMON=n \ + CONFIG_IXGBE_HWMON=y \ CONFIG_IXGBE_DCA=n FILES:=$(LINUX_DIR)/drivers/net/ethernet/intel/ixgbe/ixgbe.ko AUTOLOAD:=$(call AutoLoad,35,ixgbe) @@ -577,7 +577,7 @@ define KernelPackage/ixgbevf DEPENDS:=@PCI_SUPPORT +kmod-ixgbe KCONFIG:=CONFIG_IXGBEVF \ CONFIG_IXGBE_VXLAN=n \ - CONFIG_IXGBE_HWMON=n \ + CONFIG_IXGBE_HWMON=y \ CONFIG_IXGBE_DCA=n FILES:=$(LINUX_DIR)/drivers/net/ethernet/intel/ixgbevf/ixgbevf.ko AUTOLOAD:=$(call AutoLoad,35,ixgbevf) diff --git a/package/kernel/linux/modules/netfilter.mk b/package/kernel/linux/modules/netfilter.mk index 0d817ed7f..f296a9096 100644 --- a/package/kernel/linux/modules/netfilter.mk +++ b/package/kernel/linux/modules/netfilter.mk @@ -11,13 +11,39 @@ NF_KMOD:=1 include $(INCLUDE_DIR)/netfilter.mk +define KernelPackage/nf-reject + SUBMENU:=$(NF_MENU) + TITLE:=Netfilter IPv4 reject support + KCONFIG:= \ + CONFIG_NETFILTER=y \ + CONFIG_NETFILTER_ADVANCED=y \ + $(KCONFIG_NF_REJECT) + FILES:=$(foreach mod,$(NF_REJECT-m),$(LINUX_DIR)/net/$(mod).ko) + AUTOLOAD:=$(call AutoProbe,$(notdir $(NF_REJECT-m))) +endef + +$(eval $(call KernelPackage,nf-reject)) + + +define KernelPackage/nf-reject6 + SUBMENU:=$(NF_MENU) + TITLE:=Netfilter IPv6 reject support + KCONFIG:= \ + CONFIG_NETFILTER=y \ + CONFIG_NETFILTER_ADVANCED=y \ + $(KCONFIG_NF_REJECT6) + DEPENDS:=@IPV6 + FILES:=$(foreach mod,$(NF_REJECT6-m),$(LINUX_DIR)/net/$(mod).ko) + AUTOLOAD:=$(call AutoProbe,$(notdir $(NF_REJECT6-m))) +endef + +$(eval $(call KernelPackage,nf-reject6)) + + define KernelPackage/nf-ipt SUBMENU:=$(NF_MENU) TITLE:=Iptables core - KCONFIG:= \ - CONFIG_NETFILTER=y \ - CONFIG_NETFILTER_ADVANCED=y \ - $(KCONFIG_NF_IPT) + KCONFIG:=$(KCONFIG_NF_IPT) FILES:=$(foreach mod,$(NF_IPT-m),$(LINUX_DIR)/net/$(mod).ko) AUTOLOAD:=$(call AutoProbe,$(notdir $(NF_IPT-m))) endef @@ -31,7 +57,7 @@ define KernelPackage/nf-ipt6 KCONFIG:=$(KCONFIG_NF_IPT6) FILES:=$(foreach mod,$(NF_IPT6-m),$(LINUX_DIR)/net/$(mod).ko) AUTOLOAD:=$(call AutoProbe,$(notdir $(NF_IPT6-m))) - DEPENDS:=+kmod-nf-ipt +kmod-nf-conntrack6 + DEPENDS:=+kmod-nf-ipt endef $(eval $(call KernelPackage,nf-ipt6)) @@ -44,7 +70,7 @@ define KernelPackage/ipt-core KCONFIG:=$(KCONFIG_IPT_CORE) FILES:=$(foreach mod,$(IPT_CORE-m),$(LINUX_DIR)/net/$(mod).ko) AUTOLOAD:=$(call AutoProbe,$(notdir $(IPT_CORE-m))) - DEPENDS:=+kmod-nf-ipt + DEPENDS:=+kmod-nf-reject +kmod-nf-ipt endef define KernelPackage/ipt-core/description @@ -68,6 +94,7 @@ define KernelPackage/nf-conntrack KCONFIG:= \ CONFIG_NETFILTER=y \ CONFIG_NETFILTER_ADVANCED=y \ + CONFIG_NF_CONNTRACK_MARK=y \ CONFIG_NF_CONNTRACK_ZONES=y \ $(KCONFIG_NF_CONNTRACK) FILES:=$(foreach mod,$(NF_CONNTRACK-m),$(LINUX_DIR)/net/$(mod).ko) @@ -93,7 +120,7 @@ define KernelPackage/nf-nat SUBMENU:=$(NF_MENU) TITLE:=Netfilter NAT KCONFIG:=$(KCONFIG_NF_NAT) - DEPENDS:=+kmod-nf-conntrack +kmod-nf-ipt + DEPENDS:=+kmod-nf-conntrack FILES:=$(foreach mod,$(NF_NAT-m),$(LINUX_DIR)/net/$(mod).ko) AUTOLOAD:=$(call AutoProbe,$(notdir $(NF_NAT-m))) endef @@ -105,7 +132,7 @@ define KernelPackage/nf-nat6 SUBMENU:=$(NF_MENU) TITLE:=Netfilter IPV6-NAT KCONFIG:=$(KCONFIG_NF_NAT6) - DEPENDS:=+kmod-nf-conntrack6 +kmod-nf-ipt6 +kmod-nf-nat + DEPENDS:=+kmod-nf-conntrack6 +kmod-nf-nat FILES:=$(foreach mod,$(NF_NAT6-m),$(LINUX_DIR)/net/$(mod).ko) AUTOLOAD:=$(call AutoProbe,$(notdir $(NF_NAT6-m))) endef @@ -113,6 +140,23 @@ endef $(eval $(call KernelPackage,nf-nat6)) +define KernelPackage/nf-flow + SUBMENU:=$(NF_MENU) + TITLE:=Netfilter flowtable support + KCONFIG:= \ + CONFIG_NETFILTER_INGRESS=y \ + CONFIG_NF_FLOW_TABLE \ + CONFIG_NF_FLOW_TABLE_HW + DEPENDS:=+kmod-nf-conntrack @!LINUX_3_18 @!LINUX_4_4 @!LINUX_4_9 + FILES:= \ + $(LINUX_DIR)/net/netfilter/nf_flow_table.ko \ + $(LINUX_DIR)/net/netfilter/nf_flow_table_hw.ko + AUTOLOAD:=$(call AutoProbe,nf_flow_table nf_flow_table_hw) +endef + +$(eval $(call KernelPackage,nf-flow)) + + define AddDepends/ipt SUBMENU:=$(NF_MENU) DEPENDS+= +kmod-ipt-core $(1) @@ -160,6 +204,21 @@ endef $(eval $(call KernelPackage,ipt-conntrack-extra)) +define KernelPackage/ipt-conntrack-label + TITLE:=Module for handling connection tracking labels + KCONFIG:=$(KCONFIG_IPT_CONNTRACK_LABEL) + FILES:=$(foreach mod,$(IPT_CONNTRACK_LABEL-m),$(LINUX_DIR)/net/$(mod).ko) + AUTOLOAD:=$(call AutoProbe,$(notdir $(IPT_CONNTRACK_LABEL-m))) + $(call AddDepends/ipt,+kmod-ipt-conntrack) +endef + +define KernelPackage/ipt-conntrack-label/description + Netfilter (IPv4) module for handling connection tracking labels + Includes: + - connlabel +endef + +$(eval $(call KernelPackage,ipt-conntrack-label)) define KernelPackage/ipt-filter TITLE:=Modules for packet content inspection @@ -178,6 +237,17 @@ endef $(eval $(call KernelPackage,ipt-filter)) +define KernelPackage/ipt-offload + TITLE:=Netfilter routing/NAT offload support + KCONFIG:=CONFIG_NETFILTER_XT_TARGET_FLOWOFFLOAD + FILES:=$(foreach mod,$(IPT_FLOW-m),$(LINUX_DIR)/net/$(mod).ko) + AUTOLOAD:=$(call AutoProbe,$(notdir $(IPT_FLOW-m))) + $(call AddDepends/ipt,+kmod-nf-flow) +endef + +$(eval $(call KernelPackage,ipt-offload)) + + define KernelPackage/ipt-ipopt TITLE:=Modules for matching/changing IP packet options KCONFIG:=$(KCONFIG_IPT_IPOPT) @@ -446,10 +516,9 @@ $(eval $(call KernelPackage,ipt-nfqueue)) define KernelPackage/ipt-debug TITLE:=Module for debugging/development KCONFIG:=$(KCONFIG_IPT_DEBUG) - DEFAULT:=n FILES:=$(foreach mod,$(IPT_DEBUG-m),$(LINUX_DIR)/net/$(mod).ko) AUTOLOAD:=$(call AutoProbe,$(notdir $(IPT_DEBUG-m))) - $(call AddDepends/ipt) + $(call AddDepends/ipt,+kmod-ipt-raw +IPV6:kmod-ipt-raw6) endef define KernelPackage/ipt-debug/description @@ -477,7 +546,7 @@ $(eval $(call KernelPackage,ipt-led)) define KernelPackage/ipt-tproxy TITLE:=Transparent proxying support - DEPENDS+=+kmod-ipt-conntrack +IPV6:kmod-ip6tables + DEPENDS+=+kmod-ipt-conntrack +IPV6:kmod-nf-conntrack6 +IPV6:kmod-ip6tables KCONFIG:= \ CONFIG_NETFILTER_XT_MATCH_SOCKET \ CONFIG_NETFILTER_XT_TARGET_TPROXY @@ -636,7 +705,7 @@ $(eval $(call KernelPackage,ipt-extra)) define KernelPackage/ip6tables SUBMENU:=$(NF_MENU) TITLE:=IPv6 modules - DEPENDS:=+kmod-nf-ipt6 +kmod-ipt-core +kmod-ipt-conntrack + DEPENDS:=+kmod-nf-reject6 +kmod-nf-ipt6 +kmod-ipt-core KCONFIG:=$(KCONFIG_IPT_IPV6) FILES:=$(foreach mod,$(IPT_IPV6-m),$(LINUX_DIR)/net/$(mod).ko) AUTOLOAD:=$(call AutoLoad,42,$(notdir $(IPT_IPV6-m))) @@ -875,16 +944,12 @@ $(eval $(call KernelPackage,ipt-rpfilter)) define KernelPackage/nft-core SUBMENU:=$(NF_MENU) TITLE:=Netfilter nf_tables support - DEPENDS:=+kmod-nfnetlink +kmod-nf-conntrack6 +kmod-nf-ipt +kmod-nf-ipt6 + DEPENDS:=+kmod-nfnetlink +kmod-nf-reject +kmod-nf-reject6 +kmod-nf-conntrack6 FILES:=$(foreach mod,$(NFT_CORE-m),$(LINUX_DIR)/net/$(mod).ko) AUTOLOAD:=$(call AutoProbe,$(notdir $(NFT_CORE-m))) KCONFIG:= \ - CONFIG_NETFILTER=y \ - CONFIG_NETFILTER_ADVANCED=y \ CONFIG_NFT_COMPAT=n \ CONFIG_NFT_QUEUE=n \ - CONFIG_NF_TABLES_ARP=n \ - CONFIG_NF_TABLES_BRIDGE=n \ $(KCONFIG_NFT_CORE) endef @@ -895,10 +960,36 @@ endef $(eval $(call KernelPackage,nft-core)) +define KernelPackage/nft-arp + SUBMENU:=$(NF_MENU) + TITLE:=Netfilter nf_tables ARP table support + DEPENDS:=+kmod-nft-core + FILES:=$(foreach mod,$(NFT_ARP-m),$(LINUX_DIR)/net/$(mod).ko) + AUTOLOAD:=$(call AutoProbe,$(notdir $(NFT_ARP-m))) + KCONFIG:=$(KCONFIG_NFT_ARP) +endef + +$(eval $(call KernelPackage,nft-arp)) + + +define KernelPackage/nft-bridge + SUBMENU:=$(NF_MENU) + TITLE:=Netfilter nf_tables bridge table support + DEPENDS:=+kmod-nft-core + FILES:=$(foreach mod,$(NFT_BRIDGE-m),$(LINUX_DIR)/net/$(mod).ko) + AUTOLOAD:=$(call AutoProbe,$(notdir $(NFT_BRIDGE-m))) + KCONFIG:= \ + CONFIG_NF_LOG_BRIDGE=n \ + $(KCONFIG_NFT_BRIDGE) +endef + +$(eval $(call KernelPackage,nft-bridge)) + + define KernelPackage/nft-nat SUBMENU:=$(NF_MENU) TITLE:=Netfilter nf_tables NAT support - DEPENDS:=+kmod-nft-core +kmod-nf-nat +kmod-nf-nat6 + DEPENDS:=+kmod-nft-core +kmod-nf-nat FILES:=$(foreach mod,$(NFT_NAT-m),$(LINUX_DIR)/net/$(mod).ko) AUTOLOAD:=$(call AutoProbe,$(notdir $(NFT_NAT-m))) KCONFIG:=$(KCONFIG_NFT_NAT) @@ -907,14 +998,33 @@ endef $(eval $(call KernelPackage,nft-nat)) +define KernelPackage/nft-offload + SUBMENU:=$(NF_MENU) + TITLE:=Netfilter nf_tables routing/NAT offload support + DEPENDS:=+kmod-nf-flow +kmod-nft-nat + KCONFIG:= \ + CONFIG_NF_FLOW_TABLE_INET \ + CONFIG_NF_FLOW_TABLE_IPV4 \ + CONFIG_NF_FLOW_TABLE_IPV6 \ + CONFIG_NFT_FLOW_OFFLOAD + FILES:= \ + $(LINUX_DIR)/net/netfilter/nf_flow_table_inet.ko \ + $(LINUX_DIR)/net/ipv4/netfilter/nf_flow_table_ipv4.ko \ + $(LINUX_DIR)/net/ipv6/netfilter/nf_flow_table_ipv6.ko \ + $(LINUX_DIR)/net/netfilter/nft_flow_offload.ko + AUTOLOAD:=$(call AutoProbe,nf_flow_table_inet nf_flow_table_ipv4 nf_flow_table_ipv6 nft_flow_offload) +endef + +$(eval $(call KernelPackage,nft-offload)) + + define KernelPackage/nft-nat6 SUBMENU:=$(NF_MENU) TITLE:=Netfilter nf_tables IPv6-NAT support - DEPENDS:=+kmod-nft-core +kmod-nf-nat6 + DEPENDS:=+kmod-nft-nat +kmod-nf-nat6 FILES:=$(foreach mod,$(NFT_NAT6-m),$(LINUX_DIR)/net/$(mod).ko) AUTOLOAD:=$(call AutoProbe,$(notdir $(NFT_NAT6-m))) KCONFIG:=$(KCONFIG_NFT_NAT6) endef $(eval $(call KernelPackage,nft-nat6)) - diff --git a/package/kernel/linux/modules/netsupport.mk b/package/kernel/linux/modules/netsupport.mk index 836034ad1..ff7672063 100644 --- a/package/kernel/linux/modules/netsupport.mk +++ b/package/kernel/linux/modules/netsupport.mk @@ -42,28 +42,6 @@ endef $(eval $(call KernelPackage,atmtcp)) -define KernelPackage/appletalk - SUBMENU:=$(NETWORK_SUPPORT_MENU) - TITLE:=Appletalk protocol support - KCONFIG:= \ - CONFIG_ATALK \ - CONFIG_DEV_APPLETALK \ - CONFIG_IPDDP \ - CONFIG_IPDDP_ENCAP=y \ - CONFIG_IPDDP_DECAP=y - FILES:= \ - $(LINUX_DIR)/net/appletalk/appletalk.ko \ - $(LINUX_DIR)/drivers/net/appletalk/ipddp.ko - AUTOLOAD:=$(call AutoLoad,40,appletalk ipddp) -endef - -define KernelPackage/appletalk/description - Kernel module for AppleTalk protocol. -endef - -$(eval $(call KernelPackage,appletalk)) - - define KernelPackage/bonding SUBMENU:=$(NETWORK_SUPPORT_MENU) TITLE:=Ethernet bonding driver @@ -127,6 +105,29 @@ endef $(eval $(call KernelPackage,vxlan)) + +define KernelPackage/geneve + SUBMENU:=$(NETWORK_SUPPORT_MENU) + TITLE:=Generic Network Virtualization Encapsulation (Geneve) support + DEPENDS:= \ + +kmod-iptunnel \ + +kmod-udptunnel4 \ + +IPV6:kmod-udptunnel6 + KCONFIG:=CONFIG_GENEVE + FILES:= \ + $(LINUX_DIR)/net/ipv4/geneve.ko@le4.1 \ + $(LINUX_DIR)/drivers/net/geneve.ko@ge4.2 + AUTOLOAD:=$(call AutoLoad,13,geneve) +endef + +define KernelPackage/geneve/description + Kernel module for supporting Geneve in the Kernel. + Requires Kernel 3.18 or newer. +endef + +$(eval $(call KernelPackage,geneve)) + + define KernelPackage/capi SUBMENU:=$(NETWORK_SUPPORT_MENU) TITLE:=CAPI (ISDN) Support @@ -434,6 +435,28 @@ endef $(eval $(call KernelPackage,sit)) +define KernelPackage/fou + SUBMENU:=$(NETWORK_SUPPORT_MENU) + TITLE:=FOU and GUE decapsulation + DEPENDS:= \ + +kmod-iptunnel \ + +kmod-udptunnel4 \ + +IPV6:kmod-udptunnel6 + KCONFIG:= \ + CONFIG_NET_FOU \ + CONFIG_NET_FOU_IP_TUNNELS=y + FILES:=$(LINUX_DIR)/net/ipv4/fou.ko + AUTOLOAD:=$(call AutoProbe,fou) +endef + +define KernelPackage/fou/description + Kernel module for FOU (Foo over UDP) and GUE (Generic UDP Encapsulation) tunnelling. + Requires Kernel 3.18 or newer. +endef + +$(eval $(call KernelPackage,fou)) + + define KernelPackage/ip6-tunnel SUBMENU:=$(NETWORK_SUPPORT_MENU) TITLE:=IP-in-IPv6 tunnelling @@ -729,6 +752,7 @@ define KernelPackage/sched CONFIG_NET_SCH_DSMARK \ CONFIG_NET_SCH_FIFO \ CONFIG_NET_SCH_GRED \ + CONFIG_NET_SCH_MULTIQ \ CONFIG_NET_SCH_PRIO \ CONFIG_NET_SCH_RED \ CONFIG_NET_SCH_SFQ \ diff --git a/package/kernel/linux/modules/other.mk b/package/kernel/linux/modules/other.mk index 973e4f3e2..4aee820c9 100644 --- a/package/kernel/linux/modules/other.mk +++ b/package/kernel/linux/modules/other.mk @@ -55,6 +55,7 @@ define KernelPackage/bluetooth CONFIG_BT_HCIUART_BCM=n \ CONFIG_BT_HCIUART_INTEL=n \ CONFIG_BT_HCIUART_H4 \ + CONFIG_BT_HCIUART_NOKIA=n \ CONFIG_BT_HIDP \ CONFIG_HID_SUPPORT=y $(call AddDepends/rfkill) @@ -226,7 +227,7 @@ $(eval $(call KernelPackage,gpio-dev)) define KernelPackage/gpio-mcp23s08 SUBMENU:=$(OTHER_MENU) TITLE:=Microchip MCP23xxx I/O expander - DEPENDS:=@GPIO_SUPPORT +PACKAGE_kmod-i2c-core:kmod-i2c-core + DEPENDS:=@GPIO_SUPPORT +kmod-i2c-core KCONFIG:=CONFIG_GPIO_MCP23S08 FILES:=$(LINUX_DIR)/drivers/gpio/gpio-mcp23s08.ko AUTOLOAD:=$(call AutoLoad,40,gpio-mcp23s08) @@ -285,18 +286,53 @@ endef $(eval $(call KernelPackage,gpio-pcf857x)) -define KernelPackage/lp +define KernelPackage/ppdev SUBMENU:=$(OTHER_MENU) - TITLE:=Parallel port and line printer support + TITLE:=Parallel port support KCONFIG:= \ CONFIG_PARPORT \ - CONFIG_PRINTER \ CONFIG_PPDEV FILES:= \ $(LINUX_DIR)/drivers/parport/parport.ko \ - $(LINUX_DIR)/drivers/char/lp.ko \ $(LINUX_DIR)/drivers/char/ppdev.ko - AUTOLOAD:=$(call AutoLoad,50,parport lp ppdev) + AUTOLOAD:=$(call AutoLoad,50,parport ppdev) +endef + +$(eval $(call KernelPackage,ppdev)) + + +define KernelPackage/parport-pc + SUBMENU:=$(OTHER_MENU) + TITLE:=Parallel port interface (PC-style) support + DEPENDS:=+kmod-ppdev + KCONFIG:= \ + CONFIG_KS0108=n \ + CONFIG_PARPORT_PC \ + CONFIG_PARPORT_1284=y \ + CONFIG_PARPORT_PC_FIFO=y \ + CONFIG_PARPORT_PC_PCMCIA=n \ + CONFIG_PARPORT_PC_SUPERIO=y \ + CONFIG_PARPORT_SERIAL=n \ + CONFIG_PARIDE=n \ + CONFIG_SCSI_IMM=n \ + CONFIG_SCSI_PPA=n + FILES:= \ + $(LINUX_DIR)/drivers/parport/parport_pc.ko + AUTOLOAD:=$(call AutoLoad,51,parport_pc) +endef + +$(eval $(call KernelPackage,parport-pc)) + + +define KernelPackage/lp + SUBMENU:=$(OTHER_MENU) + TITLE:=Parallel port line printer device support + DEPENDS:=+kmod-ppdev + KCONFIG:= \ + CONFIG_PRINTER + FILES:= \ + $(LINUX_DIR)/drivers/char/lp.ko + AUTOLOAD:=$(call AutoLoad,52,lp) endef $(eval $(call KernelPackage,lp)) @@ -619,6 +655,22 @@ endef $(eval $(call KernelPackage,mtdoops)) +define KernelPackage/mtdram + SUBMENU:=$(OTHER_MENU) + TITLE:=Test MTD driver using RAM + KCONFIG:=CONFIG_MTD_MTDRAM \ + CONFIG_MTDRAM_TOTAL_SIZE=4096 \ + CONFIG_MTDRAM_ERASE_SIZE=128 + FILES:=$(LINUX_DIR)/drivers/mtd/devices/mtdram.ko +endef + +define KernelPackage/mtdram/description + Test MTD driver using RAM +endef + +$(eval $(call KernelPackage,mtdram)) + + define KernelPackage/serial-8250 SUBMENU:=$(OTHER_MENU) TITLE:=8250 UARTs diff --git a/package/kernel/linux/modules/sound.mk b/package/kernel/linux/modules/sound.mk index faee1f367..177140e0f 100644 --- a/package/kernel/linux/modules/sound.mk +++ b/package/kernel/linux/modules/sound.mk @@ -135,6 +135,22 @@ endef $(eval $(call KernelPackage,sound-seq)) +define KernelPackage/sound-ens1371 + TITLE:=(Creative) Ensoniq AudioPCI 1371 + KCONFIG:=CONFIG_SND_ENS1371 + DEPENDS:=@PCI_SUPPORT +kmod-ac97 + FILES:=$(LINUX_DIR)/sound/pci/snd-ens1371.ko + AUTOLOAD:=$(call AutoLoad,36,snd-ens1371) + $(call AddDepends/sound) +endef + +define KernelPackage/sound-ens1371/description + support for (Creative) Ensoniq AudioPCI 1371 chips +endef + +$(eval $(call KernelPackage,sound-ens1371)) + + define KernelPackage/sound-i8x0 TITLE:=Intel/SiS/nVidia/AMD/ALi AC97 Controller DEPENDS:=+kmod-ac97 diff --git a/package/kernel/linux/modules/spi.mk b/package/kernel/linux/modules/spi.mk index 1c2a789fe..01dc7dc7e 100644 --- a/package/kernel/linux/modules/spi.mk +++ b/package/kernel/linux/modules/spi.mk @@ -43,22 +43,6 @@ endef $(eval $(call KernelPackage,spi-bitbang)) -define KernelPackage/spi-gpio-old - SUBMENU:=$(SPI_MENU) - TITLE:=Old GPIO based bitbanging SPI controller (DEPRECATED) - DEPENDS:=@GPIO_SUPPORT +kmod-spi-bitbang - KCONFIG:=CONFIG_SPI_GPIO_OLD - FILES:=$(LINUX_DIR)/drivers/spi/spi_gpio_old.ko - AUTOLOAD:=$(call AutoProbe,spi_gpio_old) -endef - -define KernelPackage/spi-gpio-old/description - This package contains the GPIO based bitbanging SPI controller driver -endef - -$(eval $(call KernelPackage,spi-gpio-old)) - - define KernelPackage/spi-gpio SUBMENU:=$(SPI_MENU) TITLE:=GPIO-based bitbanging SPI Master diff --git a/package/kernel/linux/modules/usb.mk b/package/kernel/linux/modules/usb.mk index 08e3bf699..be638520a 100644 --- a/package/kernel/linux/modules/usb.mk +++ b/package/kernel/linux/modules/usb.mk @@ -71,6 +71,25 @@ endef $(eval $(call KernelPackage,usb-phy-nop)) +define KernelPackage/usb-phy-qcom-dwc3 + TITLE:=DWC3 USB QCOM PHY driver + DEPENDS:=@TARGET_ipq40xx||@TARGET_ipq806x +kmod-usb-dwc3-of-simple + KCONFIG:= CONFIG_PHY_QCOM_DWC3 + FILES:= \ + $(LINUX_DIR)/drivers/phy/phy-qcom-dwc3.ko@lt4.13 \ + $(LINUX_DIR)/drivers/phy/qualcomm/phy-qcom-dwc3.ko@ge4.13 + AUTOLOAD:=$(call AutoLoad,45,phy-qcom-dwc3,1) + $(call AddDepends/usb) +endef + +define KernelPackage/usb-phy-qcom-dwc3/description + This driver provides support for the integrated DesignWare + USB3 IP Core within the QCOM SoCs. +endef + +$(eval $(call KernelPackage,usb-phy-qcom-dwc3)) + + define KernelPackage/usb-gadget TITLE:=USB Gadget support KCONFIG:=CONFIG_USB_GADGET @@ -187,6 +206,7 @@ $(eval $(call KernelPackage,usb-gadget-mass-storage)) define KernelPackage/usb-uhci TITLE:=Support for UHCI controllers KCONFIG:= \ + CONFIG_USB_PCI=y \ CONFIG_USB_UHCI_ALT \ CONFIG_USB_UHCI_HCD FILES:=$(LINUX_DIR)/drivers/usb/host/uhci-hcd.ko @@ -236,7 +256,9 @@ $(eval $(call KernelPackage,usb-ohci,1)) define KernelPackage/usb-ohci-pci TITLE:=Support for PCI OHCI controllers DEPENDS:=@PCI_SUPPORT +kmod-usb-ohci - KCONFIG:=CONFIG_USB_OHCI_HCD_PCI + KCONFIG:= \ + CONFIG_USB_PCI=y \ + CONFIG_USB_OHCI_HCD_PCI FILES:=$(LINUX_DIR)/drivers/usb/host/ohci-pci.ko AUTOLOAD:=$(call AutoLoad,51,ohci-pci,1) $(call AddDepends/usb) @@ -324,7 +346,9 @@ $(eval $(call KernelPackage,usb2)) define KernelPackage/usb2-pci TITLE:=Support for PCI USB2 controllers DEPENDS:=@PCI_SUPPORT +kmod-usb2 - KCONFIG:=CONFIG_USB_EHCI_PCI + KCONFIG:= \ + CONFIG_USB_PCI=y \ + CONFIG_USB_EHCI_PCI FILES:=$(LINUX_DIR)/drivers/usb/host/ehci-pci.ko AUTOLOAD:=$(call AutoLoad,42,ehci-pci,1) $(call AddDepends/usb) @@ -341,6 +365,7 @@ define KernelPackage/usb-dwc2 TITLE:=DWC2 USB controller driver DEPENDS:=+USB_GADGET_SUPPORT:kmod-usb-gadget KCONFIG:= \ + CONFIG_USB_PCI=y \ CONFIG_USB_DWC2 \ CONFIG_USB_DWC2_PCI \ CONFIG_USB_DWC2_PLATFORM \ @@ -385,6 +410,23 @@ endef $(eval $(call KernelPackage,usb-dwc3)) +define KernelPackage/usb-dwc3-of-simple + TITLE:=DWC3 USB simple OF driver + DEPENDS:=@TARGET_ipq40xx||@TARGET_ipq806x +kmod-usb-dwc3 + KCONFIG:= CONFIG_USB_DWC3_OF_SIMPLE + FILES:= $(LINUX_DIR)/drivers/usb/dwc3/dwc3-of-simple.ko + AUTOLOAD:=$(call AutoLoad,53,dwc3-of-simple,1) + $(call AddDepends/usb) +endef + +define KernelPackage/usb-dwc3-of-simple/description + This driver provides generic platform glue for the integrated DesignWare + USB3 IP Core. +endef + + +$(eval $(call KernelPackage,usb-dwc3-of-simple)) + define KernelPackage/usb-acm TITLE:=Support for modems/isdn controllers KCONFIG:=CONFIG_USB_ACM @@ -1499,6 +1541,7 @@ define KernelPackage/usb3 +TARGET_bcm53xx:kmod-usb-bcma \ +TARGET_bcm53xx:kmod-phy-bcm-ns-usb3 KCONFIG:= \ + CONFIG_USB_PCI=y \ CONFIG_USB_XHCI_HCD \ CONFIG_USB_XHCI_PCI \ CONFIG_USB_XHCI_PLATFORM \ @@ -1520,7 +1563,9 @@ $(eval $(call KernelPackage,usb3)) define KernelPackage/usb-net2280 TITLE:=Support for NetChip 228x PCI USB peripheral controller - KCONFIG:= CONFIG_USB_NET2280 + KCONFIG:= \ + CONFIG_USB_PCI=y \ + CONFIG_USB_NET2280 DEPENDS:=@PCI_SUPPORT +kmod-usb-gadget FILES:=$(LINUX_DIR)/drivers/usb/gadget/udc/net2280.ko AUTOLOAD:=$(call AutoLoad,46,net2280) diff --git a/package/kernel/linux/modules/video.mk b/package/kernel/linux/modules/video.mk index 8f0f0dc9e..f76618055 100644 --- a/package/kernel/linux/modules/video.mk +++ b/package/kernel/linux/modules/video.mk @@ -204,6 +204,7 @@ define KernelPackage/drm-imx DEPENDS:=@TARGET_imx6 +kmod-drm +kmod-fb +kmod-fb-cfb-copyarea +kmod-fb-cfb-imgblt +kmod-fb-cfb-fillrect +kmod-fb-sys-fops KCONFIG:=CONFIG_DRM_IMX \ CONFIG_DRM_FBDEV_EMULATION=y \ + CONFIG_DRM_FBDEV_OVERALLOC=100 \ CONFIG_IMX_IPUV3_CORE \ CONFIG_RESET_CONTROLLER=y \ CONFIG_DRM_IMX_IPUV3 \ @@ -223,7 +224,6 @@ define KernelPackage/drm-imx FILES:= \ $(LINUX_DIR)/drivers/gpu/drm/imx/imxdrm.ko \ $(LINUX_DIR)/drivers/gpu/ipu-v3/imx-ipu-v3.ko \ - $(LINUX_DIR)/drivers/gpu/drm/imx/imx-ipuv3-crtc.ko \ $(LINUX_DIR)/drivers/video/fbdev/core/syscopyarea.ko \ $(LINUX_DIR)/drivers/video/fbdev/core/sysfillrect.ko \ $(LINUX_DIR)/drivers/video/fbdev/core/sysimgblt.ko \ @@ -242,10 +242,11 @@ define KernelPackage/drm-imx-hdmi TITLE:=Freescale i.MX HDMI DRM support DEPENDS:=+kmod-sound-core kmod-drm-imx KCONFIG:=CONFIG_DRM_IMX_HDMI \ - CONFIG_DRM_DW_HDMI_AHB_AUDIO + CONFIG_DRM_DW_HDMI_AHB_AUDIO \ + CONFIG_DRM_DW_HDMI_I2S_AUDIO FILES:= \ - $(LINUX_DIR)/drivers/gpu/drm/bridge/dw-hdmi.ko \ - $(LINUX_DIR)/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.ko \ + $(LINUX_DIR)/drivers/gpu/drm/bridge/synopsys/dw-hdmi.ko \ + $(LINUX_DIR)/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.ko \ $(LINUX_DIR)/drivers/gpu/drm/imx/dw_hdmi-imx.ko AUTOLOAD:=$(call AutoLoad,05,dw-hdmi dw-hdmi-ahb-audio.ko dw_hdmi-imx) endef @@ -267,7 +268,9 @@ define KernelPackage/drm-imx-ldb CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=n \ CONFIG_DRM_PANEL_LG_LG4573=n \ CONFIG_DRM_PANEL_LD9040=n \ - CONFIG_DRM_PANEL_S6E8AA0=n + CONFIG_DRM_PANEL_LVDS=n \ + CONFIG_DRM_PANEL_S6E8AA0=n \ + CONFIG_DRM_PANEL_SITRONIX_ST7789V=n FILES:=$(LINUX_DIR)/drivers/gpu/drm/imx/imx-ldb.ko \ $(LINUX_DIR)/drivers/gpu/drm/panel/panel-simple.ko AUTOLOAD:=$(call AutoLoad,05,imx-ldb) diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile index cf17c9f4f..22ed84139 100644 --- a/package/kernel/mac80211/Makefile +++ b/package/kernel/mac80211/Makefile @@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mac80211 PKG_VERSION:=2017-11-01 -PKG_RELEASE:=2 +PKG_RELEASE:=4 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources PKG_HASH:=8437ab7886b988c8152e7a4db30b7f41009e49a3b2cb863edd05da1ecd7eb05a @@ -1584,7 +1584,7 @@ config-$(CONFIG_PACKAGE_ATH_SPECTRAL) += ATH9K_COMMON_SPECTRAL ATH10K_SPECTRAL config-$(call config_package,ath9k) += ATH9K config-$(call config_package,ath9k-common) += ATH9K_COMMON config-$(CONFIG_TARGET_ar71xx) += ATH9K_AHB -config-$(CONFIG_TARGET_ipq806x) += ATH10K_AHB +config-$(CONFIG_TARGET_ipq40xx) += ATH10K_AHB config-$(CONFIG_PCI) += ATH9K_PCI config-$(CONFIG_ATH_USER_REGD) += ATH_USER_REGD config-$(CONFIG_ATH9K_SUPPORT_PCOEM) += ATH9K_PCOEM @@ -1821,7 +1821,7 @@ define KernelPackage/cfg80211/install $(INSTALL_DATA) ./files/lib/wifi/mac80211.sh $(1)/lib/wifi $(INSTALL_BIN) ./files/lib/netifd/wireless/mac80211.sh $(1)/lib/netifd/wireless $(INSTALL_DIR) $(1)/etc/hotplug.d/ieee80211 - $(INSTALL_DATA) ./files/mac80211.hotplug $(1)/etc/hotplug.d/ieee80211/00-wifi-detect + $(INSTALL_DATA) ./files/mac80211.hotplug $(1)/etc/hotplug.d/ieee80211/10-wifi-detect endef define KernelPackage/ipw2100/install diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index cdc155405..bf9d52ae4 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -629,17 +629,11 @@ mac80211_setup_vif() { case "$mode" in mesh) - # authsae or wpa_supplicant json_get_vars key if [ -n "$key" ]; then - if [ -e "/lib/wifi/authsae.sh" ]; then - . /lib/wifi/authsae.sh - authsae_start_interface || failed=1 - else - wireless_vif_parse_encryption - freq="$(get_freq "$phy" "$channel")" - mac80211_setup_supplicant_noctl || failed=1 - fi + wireless_vif_parse_encryption + freq="$(get_freq "$phy" "$channel")" + mac80211_setup_supplicant_noctl || failed=1 else json_get_vars mesh_id mcast_rate diff --git a/package/kernel/mac80211/files/lib/wifi/mac80211.sh b/package/kernel/mac80211/files/lib/wifi/mac80211.sh new file mode 100755 index 000000000..220ad69d7 --- /dev/null +++ b/package/kernel/mac80211/files/lib/wifi/mac80211.sh @@ -0,0 +1,141 @@ +#!/bin/sh +append DRIVERS "mac80211" + +lookup_phy() { + [ -n "$phy" ] && { + [ -d /sys/class/ieee80211/$phy ] && return + } + + local devpath + config_get devpath "$device" path + [ -n "$devpath" ] && { + for phy in $(ls /sys/class/ieee80211 2>/dev/null); do + case "$(readlink -f /sys/class/ieee80211/$phy/device)" in + *$devpath) return;; + esac + done + } + + local macaddr="$(config_get "$device" macaddr | tr 'A-Z' 'a-z')" + [ -n "$macaddr" ] && { + for _phy in /sys/class/ieee80211/*; do + [ -e "$_phy" ] || continue + + [ "$macaddr" = "$(cat ${_phy}/macaddress)" ] || continue + phy="${_phy##*/}" + return + done + } + phy= + return +} + +find_mac80211_phy() { + local device="$1" + + config_get phy "$device" phy + lookup_phy + [ -n "$phy" -a -d "/sys/class/ieee80211/$phy" ] || { + echo "PHY for wifi device $1 not found" + return 1 + } + config_set "$device" phy "$phy" + + config_get macaddr "$device" macaddr + [ -z "$macaddr" ] && { + config_set "$device" macaddr "$(cat /sys/class/ieee80211/${phy}/macaddress)" + } + + return 0 +} + +check_mac80211_device() { + config_get phy "$1" phy + [ -z "$phy" ] && { + find_mac80211_phy "$1" >/dev/null || return 0 + config_get phy "$1" phy + } + [ "$phy" = "$dev" ] && found=1 +} + +detect_mac80211() { + devidx=0 + config_load wireless + while :; do + config_get type "radio$devidx" type + [ -n "$type" ] || break + devidx=$(($devidx + 1)) + done + + for _dev in /sys/class/ieee80211/*; do + [ -e "$_dev" ] || continue + + dev="${_dev##*/}" + + found=0 + config_foreach check_mac80211_device wifi-device + [ "$found" -gt 0 ] && continue + + mode_band="g" + channel="11" + htmode="" + ht_capab="" + + iw phy "$dev" info | grep -q 'Capabilities:' && htmode=HT20 + iw phy "$dev" info | grep -q '2412 MHz' || { mode_band="a"; channel="36"; } + + vht_cap=$(iw phy "$dev" info | grep -c 'VHT Capabilities') + cap_5ghz=$(iw phy "$dev" info | grep -c "Band 2") + [ "$vht_cap" -gt 0 -a "$cap_5ghz" -gt 0 ] && { + mode_band="a"; + channel="36" + htmode="VHT80" + } + + [ -n "$htmode" ] && ht_capab="set wireless.radio${devidx}.htmode=$htmode" + + if [ -x /usr/bin/readlink -a -h /sys/class/ieee80211/${dev} ]; then + path="$(readlink -f /sys/class/ieee80211/${dev}/device)" + else + path="" + fi + if [ -n "$path" ]; then + path="${path##/sys/devices/}" + case "$path" in + platform*/pci*) path="${path##platform/}";; + esac + dev_id="set wireless.radio${devidx}.path='$path'" + else + dev_id="set wireless.radio${devidx}.macaddr=$(cat /sys/class/ieee80211/${dev}/macaddress)" + fi + + if [ $mode_band == "a" ]; then + ssid_5g="_5G" + else + ssid_5g="_2.4G" + fi + [ -f /lib/03_set_wifi_mac ] && ./lib/03_set_wifi_mac + Mac=`cat /sys/class/ieee80211/${dev}/macaddress|awk -F ":" '{print $4""$5""$6 }'| tr a-z A-Z` + Wifi_name="OpenWrt${ssid_5g}_${Mac}" + + uci -q batch <<-EOF + set wireless.radio${devidx}=wifi-device + set wireless.radio${devidx}.type=mac80211 + set wireless.radio${devidx}.channel=${channel} + set wireless.radio${devidx}.hwmode=11${mode_band} + ${dev_id} + ${ht_capab} + set wireless.radio${devidx}.noscan=1 + set wireless.radio${devidx}.disabled=0 + set wireless.default_radio${devidx}=wifi-iface + set wireless.default_radio${devidx}.device=radio${devidx} + set wireless.default_radio${devidx}.network=lan + set wireless.default_radio${devidx}.mode=ap + set wireless.default_radio${devidx}.ssid=${Wifi_name} + set wireless.default_radio${devidx}.encryption=none +EOF + uci -q commit wireless + + devidx=$(($devidx + 1)) + done +} diff --git a/package/kernel/mac80211/patches/937-ath10k-calibration-variant.patch b/package/kernel/mac80211/patches/081-ath10k-calibration-variant.patch similarity index 100% rename from package/kernel/mac80211/patches/937-ath10k-calibration-variant.patch rename to package/kernel/mac80211/patches/081-ath10k-calibration-variant.patch diff --git a/package/kernel/mac80211/patches/160-ath10k-search-all-IEs-for-variant-before-falling-back.patch b/package/kernel/mac80211/patches/160-ath10k-search-all-IEs-for-variant-before-falling-back.patch new file mode 100644 index 000000000..cac396aec --- /dev/null +++ b/package/kernel/mac80211/patches/160-ath10k-search-all-IEs-for-variant-before-falling-back.patch @@ -0,0 +1,237 @@ +From: Thomas Hebb +Subject: [PATCH] ath10k: search all IEs for variant before falling back +Date: Wed, 21 Feb 2018 11:43:39 -0500 + +commit f2593cb1b291 ("ath10k: Search SMBIOS for OEM board file +extension") added a feature to ath10k that allows Board Data File +(BDF) conflicts between multiple devices that use the same device IDs +but have different calibration requirements to be resolved by allowing +a "variant" string to be stored in SMBIOS [and later device tree, added +by commit d06f26c5c8a4 ("ath10k: search DT for qcom,ath10k-calibration- +variant")] that gets appended to the ID stored in board-2.bin. + +This original patch had a regression, however. Namely that devices with +a variant present in SMBIOS that didn't need custom BDFs could no longer +find the default BDF, which has no variant appended. The patch was +reverted and re-applied with a fix for this issue in commit 1657b8f84ed9 +("search SMBIOS for OEM board file extension"). + +But the fix to fall back to a default BDF introduced another issue: the +driver currently parses IEs in board-2.bin one by one, and for each one +it first checks to see if it matches the ID with the variant appended. +If it doesn't, it checks to see if it matches the "fallback" ID with no +variant. If a matching BDF is found at any point during this search, the +search is terminated and that BDF is used. The issue is that it's very +possible (and is currently the case for board-2.bin files present in the +ath10k-firmware repository) for the default BDF to occur in an earlier +IE than the variant-specific BDF. In this case, the current code will +happily choose the default BDF even though a better-matching BDF is +present later in the file. + +This patch fixes the issue by first searching the entire file for the ID +with variant, and searching for the fallback ID only if that search +fails. It also includes some code cleanup in the area, as +ath10k_core_fetch_board_data_api_n() no longer does its own string +mangling to remove the variant from an ID, instead leaving that job to a +new flag passed to ath10k_core_create_board_name(). + +I've tested this patch on a QCA4019 and verified that the driver behaves +correctly for 1) both fallback and variant BDFs present, 2) only fallback +BDF present, and 3) no matching BDFs present. + +Fixes: 1657b8f84ed9 ("ath10k: search SMBIOS for OEM board file extension") +Signed-off-by: Thomas Hebb +--- + drivers/net/wireless/ath/ath10k/core.c | 134 ++++++++++++++++++--------------- + 1 file changed, 72 insertions(+), 62 deletions(-) + +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -1129,14 +1129,61 @@ out: + return ret; + } + ++static int ath10k_core_search_bd(struct ath10k *ar, ++ const char *boardname, ++ const u8 *data, ++ size_t len) ++{ ++ size_t ie_len; ++ struct ath10k_fw_ie *hdr; ++ int ret = -ENOENT, ie_id; ++ ++ while (len > sizeof(struct ath10k_fw_ie)) { ++ hdr = (struct ath10k_fw_ie *)data; ++ ie_id = le32_to_cpu(hdr->id); ++ ie_len = le32_to_cpu(hdr->len); ++ ++ len -= sizeof(*hdr); ++ data = hdr->data; ++ ++ if (len < ALIGN(ie_len, 4)) { ++ ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n", ++ ie_id, ie_len, len); ++ return -EINVAL; ++ } ++ ++ switch (ie_id) { ++ case ATH10K_BD_IE_BOARD: ++ ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len, ++ boardname); ++ if (ret == -ENOENT) ++ /* no match found, continue */ ++ break; ++ ++ /* either found or error, so stop searching */ ++ goto out; ++ } ++ ++ /* jump over the padding */ ++ ie_len = ALIGN(ie_len, 4); ++ ++ len -= ie_len; ++ data += ie_len; ++ } ++ ++out: ++ /* return result of parse_bd_ie_board() or -ENOENT */ ++ return ret; ++} ++ + static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar, + const char *boardname, ++ const char *fallback_boardname, + const char *filename) + { +- size_t len, magic_len, ie_len; +- struct ath10k_fw_ie *hdr; ++ size_t len, magic_len; + const u8 *data; +- int ret, ie_id; ++ int ret; + + ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar, + ar->hw_params.fw.dir, +@@ -1174,69 +1221,23 @@ static int ath10k_core_fetch_board_data_ + data += magic_len; + len -= magic_len; + +- while (len > sizeof(struct ath10k_fw_ie)) { +- hdr = (struct ath10k_fw_ie *)data; +- ie_id = le32_to_cpu(hdr->id); +- ie_len = le32_to_cpu(hdr->len); +- +- len -= sizeof(*hdr); +- data = hdr->data; +- +- if (len < ALIGN(ie_len, 4)) { +- ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n", +- ie_id, ie_len, len); +- ret = -EINVAL; +- goto err; +- } ++ /* attempt to find boardname in the IE list */ ++ ret = ath10k_core_search_bd(ar, boardname, data, len); + +- switch (ie_id) { +- case ATH10K_BD_IE_BOARD: +- ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len, +- boardname); +- if (ret == -ENOENT && ar->id.bdf_ext[0] != '\0') { +- /* try default bdf if variant was not found */ +- char *s, *v = ",variant="; +- char boardname2[100]; +- +- strlcpy(boardname2, boardname, +- sizeof(boardname2)); +- +- s = strstr(boardname2, v); +- if (s) +- *s = '\0'; /* strip ",variant=%s" */ +- +- ret = ath10k_core_parse_bd_ie_board(ar, data, +- ie_len, +- boardname2); +- } ++ /* if we didn't find it and have a fallback name, try that */ ++ if (ret == -ENOENT && fallback_boardname) ++ ret = ath10k_core_search_bd(ar, fallback_boardname, data, len); + +- if (ret == -ENOENT) +- /* no match found, continue */ +- break; +- else if (ret) +- /* there was an error, bail out */ +- goto err; +- +- /* board data found */ +- goto out; +- } +- +- /* jump over the padding */ +- ie_len = ALIGN(ie_len, 4); +- +- len -= ie_len; +- data += ie_len; +- } +- +-out: +- if (!ar->normal_mode_fw.board_data || !ar->normal_mode_fw.board_len) { ++ if (ret == -ENOENT) { + ath10k_err(ar, + "failed to fetch board data for %s from %s/%s\n", + boardname, ar->hw_params.fw.dir, filename); + ret = -ENODATA; +- goto err; + } + ++ if (ret) ++ goto err; ++ + return 0; + + err: +@@ -1245,12 +1246,12 @@ err: + } + + static int ath10k_core_create_board_name(struct ath10k *ar, char *name, +- size_t name_len) ++ size_t name_len, bool with_variant) + { + /* strlen(',variant=') + strlen(ar->id.bdf_ext) */ + char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH] = { 0 }; + +- if (ar->id.bdf_ext[0] != '\0') ++ if (with_variant && ar->id.bdf_ext[0] != '\0') + scnprintf(variant, sizeof(variant), ",variant=%s", + ar->id.bdf_ext); + +@@ -1276,17 +1277,26 @@ out: + + static int ath10k_core_fetch_board_file(struct ath10k *ar) + { +- char boardname[100]; ++ char boardname[100], fallback_boardname[100]; + int ret; + +- ret = ath10k_core_create_board_name(ar, boardname, sizeof(boardname)); ++ ret = ath10k_core_create_board_name(ar, boardname, ++ sizeof(boardname), true); + if (ret) { + ath10k_err(ar, "failed to create board name: %d", ret); + return ret; + } + ++ ret = ath10k_core_create_board_name(ar, fallback_boardname, ++ sizeof(boardname), false); ++ if (ret) { ++ ath10k_err(ar, "failed to create fallback board name: %d", ret); ++ return ret; ++ } ++ + ar->bd_api = 2; + ret = ath10k_core_fetch_board_data_api_n(ar, boardname, ++ fallback_boardname, + ATH10K_BOARD_API2_FILE); + if (!ret) + goto success; diff --git a/package/kernel/mac80211/patches/318-ath10k-fix-build-errors-with-CONFIG_PM.patch b/package/kernel/mac80211/patches/300-v4.15-ath10k-fix-build-errors-with-CONFIG_PM.patch similarity index 100% rename from package/kernel/mac80211/patches/318-ath10k-fix-build-errors-with-CONFIG_PM.patch rename to package/kernel/mac80211/patches/300-v4.15-ath10k-fix-build-errors-with-CONFIG_PM.patch diff --git a/package/kernel/mac80211/patches/320-mac80211-properly-free-requested-but-not-started-TX-.patch b/package/kernel/mac80211/patches/301-v4.15-mac80211-properly-free-requested-but-not-started-TX-.patch similarity index 100% rename from package/kernel/mac80211/patches/320-mac80211-properly-free-requested-but-not-started-TX-.patch rename to package/kernel/mac80211/patches/301-v4.15-mac80211-properly-free-requested-but-not-started-TX-.patch diff --git a/package/kernel/mac80211/patches/302-v4.15-mac80211-mesh-drop-frames-appearing-to-be-from-us.patch b/package/kernel/mac80211/patches/302-v4.15-mac80211-mesh-drop-frames-appearing-to-be-from-us.patch new file mode 100644 index 000000000..839e92788 --- /dev/null +++ b/package/kernel/mac80211/patches/302-v4.15-mac80211-mesh-drop-frames-appearing-to-be-from-us.patch @@ -0,0 +1,25 @@ +From: Johannes Berg +Date: Thu, 4 Jan 2018 15:51:53 +0100 +Subject: [PATCH] mac80211: mesh: drop frames appearing to be from us + +If there are multiple mesh stations with the same MAC address, +they will both get confused and start throwing warnings. + +Obviously in this case nothing can actually work anyway, so just +drop frames that look like they're from ourselves early on. + +Reported-by: Gui Iribarren +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -3632,6 +3632,8 @@ static bool ieee80211_accept_frame(struc + } + return true; + case NL80211_IFTYPE_MESH_POINT: ++ if (ether_addr_equal(sdata->vif.addr, hdr->addr2)) ++ return false; + if (multicast) + return true; + return ether_addr_equal(sdata->vif.addr, hdr->addr1); diff --git a/package/kernel/mac80211/patches/303-v4.15-0001-brcmfmac-handle-FWHALT-mailbox-indication.patch b/package/kernel/mac80211/patches/303-v4.15-0001-brcmfmac-handle-FWHALT-mailbox-indication.patch new file mode 100644 index 000000000..b8f3be1c8 --- /dev/null +++ b/package/kernel/mac80211/patches/303-v4.15-0001-brcmfmac-handle-FWHALT-mailbox-indication.patch @@ -0,0 +1,60 @@ +From 2fd3877b5bb7d39782c3205a1dcda02023b8514a Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 8 Nov 2017 14:36:31 +0100 +Subject: [PATCH] brcmfmac: handle FWHALT mailbox indication + +The firmware uses a mailbox to communicate to the host what is going +on. In the driver we validate the bit received. Various people seen +the following message: + + brcmfmac: brcmf_sdio_hostmail: Unknown mailbox data content: 0x40012 + +Bit 4 is cause of this message, but this actually indicates the firmware +has halted. Handle this bit by giving a more meaningful error message. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -260,10 +260,11 @@ struct rte_console { + #define I_HMB_HOST_INT I_HMB_SW3 /* Miscellaneous Interrupt */ + + /* tohostmailboxdata */ +-#define HMB_DATA_NAKHANDLED 1 /* retransmit NAK'd frame */ +-#define HMB_DATA_DEVREADY 2 /* talk to host after enable */ +-#define HMB_DATA_FC 4 /* per prio flowcontrol update flag */ +-#define HMB_DATA_FWREADY 8 /* fw ready for protocol activity */ ++#define HMB_DATA_NAKHANDLED 0x0001 /* retransmit NAK'd frame */ ++#define HMB_DATA_DEVREADY 0x0002 /* talk to host after enable */ ++#define HMB_DATA_FC 0x0004 /* per prio flowcontrol update flag */ ++#define HMB_DATA_FWREADY 0x0008 /* fw ready for protocol activity */ ++#define HMB_DATA_FWHALT 0x0010 /* firmware halted */ + + #define HMB_DATA_FCDATA_MASK 0xff000000 + #define HMB_DATA_FCDATA_SHIFT 24 +@@ -1094,6 +1095,10 @@ static u32 brcmf_sdio_hostmail(struct br + offsetof(struct sdpcmd_regs, tosbmailbox)); + bus->sdcnt.f1regdata += 2; + ++ /* dongle indicates the firmware has halted/crashed */ ++ if (hmb_data & HMB_DATA_FWHALT) ++ brcmf_err("mailbox indicates firmware halted\n"); ++ + /* Dongle recomposed rx frames, accept them again */ + if (hmb_data & HMB_DATA_NAKHANDLED) { + brcmf_dbg(SDIO, "Dongle reports NAK handled, expect rtx of %d\n", +@@ -1151,6 +1156,7 @@ static u32 brcmf_sdio_hostmail(struct br + HMB_DATA_NAKHANDLED | + HMB_DATA_FC | + HMB_DATA_FWREADY | ++ HMB_DATA_FWHALT | + HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK)) + brcmf_err("Unknown mailbox data content: 0x%02x\n", + hmb_data); diff --git a/package/kernel/mac80211/patches/303-v4.15-0002-brcmfmac-disable-packet-filtering-in-promiscuous-mod.patch b/package/kernel/mac80211/patches/303-v4.15-0002-brcmfmac-disable-packet-filtering-in-promiscuous-mod.patch new file mode 100644 index 000000000..901663193 --- /dev/null +++ b/package/kernel/mac80211/patches/303-v4.15-0002-brcmfmac-disable-packet-filtering-in-promiscuous-mod.patch @@ -0,0 +1,133 @@ +From 6c219b0088158da839a5be63c5b3d96c145501d2 Mon Sep 17 00:00:00 2001 +From: Franky Lin +Date: Wed, 8 Nov 2017 14:36:32 +0100 +Subject: [PATCH] brcmfmac: disable packet filtering in promiscuous mode + +Disable arp and nd offload to allow all packets sending to host. + +Reported-by: Phil Elwell +Tested-by: Phil Elwell +Reviewed-by: Arend Van Spriel +Signed-off-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 41 ---------------------- + .../wireless/broadcom/brcm80211/brcmfmac/core.c | 38 ++++++++++++++++++++ + .../wireless/broadcom/brcm80211/brcmfmac/core.h | 1 + + 3 files changed, 39 insertions(+), 41 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -472,47 +472,6 @@ send_key_to_dongle(struct brcmf_if *ifp, + return err; + } + +-static s32 +-brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable) +-{ +- s32 err; +- u32 mode; +- +- if (enable) +- mode = BRCMF_ARP_OL_AGENT | BRCMF_ARP_OL_PEER_AUTO_REPLY; +- else +- mode = 0; +- +- /* Try to set and enable ARP offload feature, this may fail, then it */ +- /* is simply not supported and err 0 will be returned */ +- err = brcmf_fil_iovar_int_set(ifp, "arp_ol", mode); +- if (err) { +- brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n", +- mode, err); +- err = 0; +- } else { +- err = brcmf_fil_iovar_int_set(ifp, "arpoe", enable); +- if (err) { +- brcmf_dbg(TRACE, "failed to configure (%d) ARP offload err = %d\n", +- enable, err); +- err = 0; +- } else +- brcmf_dbg(TRACE, "successfully configured (%d) ARP offload to 0x%x\n", +- enable, mode); +- } +- +- err = brcmf_fil_iovar_int_set(ifp, "ndoe", enable); +- if (err) { +- brcmf_dbg(TRACE, "failed to configure (%d) ND offload err = %d\n", +- enable, err); +- err = 0; +- } else +- brcmf_dbg(TRACE, "successfully configured (%d) ND offload to 0x%x\n", +- enable, mode); +- +- return err; +-} +- + static void + brcmf_cfg80211_update_proto_addr_mode(struct wireless_dev *wdev) + { +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +@@ -71,6 +71,43 @@ struct brcmf_if *brcmf_get_ifp(struct br + return ifp; + } + ++void brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable) ++{ ++ s32 err; ++ u32 mode; ++ ++ if (enable) ++ mode = BRCMF_ARP_OL_AGENT | BRCMF_ARP_OL_PEER_AUTO_REPLY; ++ else ++ mode = 0; ++ ++ /* Try to set and enable ARP offload feature, this may fail, then it */ ++ /* is simply not supported and err 0 will be returned */ ++ err = brcmf_fil_iovar_int_set(ifp, "arp_ol", mode); ++ if (err) { ++ brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n", ++ mode, err); ++ } else { ++ err = brcmf_fil_iovar_int_set(ifp, "arpoe", enable); ++ if (err) { ++ brcmf_dbg(TRACE, "failed to configure (%d) ARP offload err = %d\n", ++ enable, err); ++ } else { ++ brcmf_dbg(TRACE, "successfully configured (%d) ARP offload to 0x%x\n", ++ enable, mode); ++ } ++ } ++ ++ err = brcmf_fil_iovar_int_set(ifp, "ndoe", enable); ++ if (err) { ++ brcmf_dbg(TRACE, "failed to configure (%d) ND offload err = %d\n", ++ enable, err); ++ } else { ++ brcmf_dbg(TRACE, "successfully configured (%d) ND offload to 0x%x\n", ++ enable, mode); ++ } ++} ++ + static void _brcmf_set_multicast_list(struct work_struct *work) + { + struct brcmf_if *ifp; +@@ -134,6 +171,7 @@ static void _brcmf_set_multicast_list(st + if (err < 0) + brcmf_err("Setting BRCMF_C_SET_PROMISC failed, %d\n", + err); ++ brcmf_configure_arp_nd_offload(ifp, !cmd_value); + } + + #if IS_ENABLED(CONFIG_IPV6) +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +@@ -203,6 +203,7 @@ int brcmf_netdev_wait_pend8021x(struct b + /* Return pointer to interface name */ + char *brcmf_ifname(struct brcmf_if *ifp); + struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx); ++void brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable); + int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); + struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx, + bool is_p2pdev, const char *name, u8 *mac_addr); diff --git a/package/kernel/mac80211/patches/303-v4.15-0003-brcmfmac-cleanup-brcmf_cfg80211_escan-function.patch b/package/kernel/mac80211/patches/303-v4.15-0003-brcmfmac-cleanup-brcmf_cfg80211_escan-function.patch new file mode 100644 index 000000000..ffd2db762 --- /dev/null +++ b/package/kernel/mac80211/patches/303-v4.15-0003-brcmfmac-cleanup-brcmf_cfg80211_escan-function.patch @@ -0,0 +1,131 @@ +From 8c6efda22f5f9f73fc948f517424466be01ae84d Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 8 Nov 2017 14:36:33 +0100 +Subject: [PATCH] brcmfmac: cleanup brcmf_cfg80211_escan() function + +The function brcmf_cfg80211_escan() was always called with a non-null +request parameter and null pointer for this_ssid parameter. Clean up +the function removing the dead code path. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 76 ++++------------------ + 1 file changed, 11 insertions(+), 65 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -1072,18 +1072,10 @@ brcmf_do_escan(struct brcmf_if *ifp, str + + static s32 + brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif, +- struct cfg80211_scan_request *request, +- struct cfg80211_ssid *this_ssid) ++ struct cfg80211_scan_request *request) + { +- struct brcmf_if *ifp = vif->ifp; + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); +- struct cfg80211_ssid *ssids; +- u32 passive_scan; +- bool escan_req; +- bool spec_scan; + s32 err; +- struct brcmf_ssid_le ssid_le; +- u32 SSID_len; + + brcmf_dbg(SCAN, "START ESCAN\n"); + +@@ -1101,8 +1093,8 @@ brcmf_cfg80211_escan(struct wiphy *wiphy + cfg->scan_status); + return -EAGAIN; + } +- if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) { +- brcmf_err("Connecting: status (%lu)\n", ifp->vif->sme_state); ++ if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state)) { ++ brcmf_err("Connecting: status (%lu)\n", vif->sme_state); + return -EAGAIN; + } + +@@ -1110,63 +1102,17 @@ brcmf_cfg80211_escan(struct wiphy *wiphy + if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) + vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; + +- escan_req = false; +- if (request) { +- /* scan bss */ +- ssids = request->ssids; +- escan_req = true; +- } else { +- /* scan in ibss */ +- /* we don't do escan in ibss */ +- ssids = this_ssid; +- } +- + cfg->scan_request = request; + set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); +- if (escan_req) { +- cfg->escan_info.run = brcmf_run_escan; +- err = brcmf_p2p_scan_prep(wiphy, request, vif); +- if (err) +- goto scan_out; +- +- err = brcmf_do_escan(vif->ifp, request); +- if (err) +- goto scan_out; +- } else { +- brcmf_dbg(SCAN, "ssid \"%s\", ssid_len (%d)\n", +- ssids->ssid, ssids->ssid_len); +- memset(&ssid_le, 0, sizeof(ssid_le)); +- SSID_len = min_t(u8, sizeof(ssid_le.SSID), ssids->ssid_len); +- ssid_le.SSID_len = cpu_to_le32(0); +- spec_scan = false; +- if (SSID_len) { +- memcpy(ssid_le.SSID, ssids->ssid, SSID_len); +- ssid_le.SSID_len = cpu_to_le32(SSID_len); +- spec_scan = true; +- } else +- brcmf_dbg(SCAN, "Broadcast scan\n"); + +- passive_scan = cfg->active_scan ? 0 : 1; +- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN, +- passive_scan); +- if (err) { +- brcmf_err("WLC_SET_PASSIVE_SCAN error (%d)\n", err); +- goto scan_out; +- } +- brcmf_scan_config_mpc(ifp, 0); +- err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, &ssid_le, +- sizeof(ssid_le)); +- if (err) { +- if (err == -EBUSY) +- brcmf_dbg(INFO, "BUSY: scan for \"%s\" canceled\n", +- ssid_le.SSID); +- else +- brcmf_err("WLC_SCAN error (%d)\n", err); ++ cfg->escan_info.run = brcmf_run_escan; ++ err = brcmf_p2p_scan_prep(wiphy, request, vif); ++ if (err) ++ goto scan_out; + +- brcmf_scan_config_mpc(ifp, 1); +- goto scan_out; +- } +- } ++ err = brcmf_do_escan(vif->ifp, request); ++ if (err) ++ goto scan_out; + + /* Arm scan timeout timer */ + mod_timer(&cfg->escan_timeout, jiffies + +@@ -1191,7 +1137,7 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, + if (!check_vif_up(vif)) + return -EIO; + +- err = brcmf_cfg80211_escan(wiphy, vif, request, NULL); ++ err = brcmf_cfg80211_escan(wiphy, vif, request); + + if (err) + brcmf_err("scan error (%d)\n", err); diff --git a/package/kernel/mac80211/patches/303-v4.15-0004-brcmfmac-use-msecs_to_jiffies-instead-of-calculation.patch b/package/kernel/mac80211/patches/303-v4.15-0004-brcmfmac-use-msecs_to_jiffies-instead-of-calculation.patch new file mode 100644 index 000000000..c2e3cba52 --- /dev/null +++ b/package/kernel/mac80211/patches/303-v4.15-0004-brcmfmac-use-msecs_to_jiffies-instead-of-calculation.patch @@ -0,0 +1,31 @@ +From df2d8388bc96c0f29d27d121f2a4cd054f8b3900 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 8 Nov 2017 14:36:34 +0100 +Subject: [PATCH] brcmfmac: use msecs_to_jiffies() instead of calculation using + HZ + +Minor cleanup using provided macro to convert milliseconds interval +to jiffies in brcmf_cfg80211_escan(). + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -1115,8 +1115,8 @@ brcmf_cfg80211_escan(struct wiphy *wiphy + goto scan_out; + + /* Arm scan timeout timer */ +- mod_timer(&cfg->escan_timeout, jiffies + +- BRCMF_ESCAN_TIMER_INTERVAL_MS * HZ / 1000); ++ mod_timer(&cfg->escan_timeout, ++ jiffies + msecs_to_jiffies(BRCMF_ESCAN_TIMER_INTERVAL_MS)); + + return 0; + diff --git a/package/kernel/mac80211/patches/303-v4.15-0005-brcmfmac-get-rid-of-brcmf_cfg80211_escan-function.patch b/package/kernel/mac80211/patches/303-v4.15-0005-brcmfmac-get-rid-of-brcmf_cfg80211_escan-function.patch new file mode 100644 index 000000000..575ffb018 --- /dev/null +++ b/package/kernel/mac80211/patches/303-v4.15-0005-brcmfmac-get-rid-of-brcmf_cfg80211_escan-function.patch @@ -0,0 +1,83 @@ +From 588378f15cff285ac81c929239ccba01d7f71d50 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 8 Nov 2017 14:36:35 +0100 +Subject: [PATCH] brcmfmac: get rid of brcmf_cfg80211_escan() function + +The function brcmf_cfg80211_escan() is only called by brcmf_cfg80211_scan() +so there is no reason to split in two function especially since the latter +does not do an awful lot. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 34 +++++++--------------- + 1 file changed, 10 insertions(+), 24 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -1071,13 +1071,16 @@ brcmf_do_escan(struct brcmf_if *ifp, str + } + + static s32 +-brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif, +- struct cfg80211_scan_request *request) ++brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) + { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); +- s32 err; ++ struct brcmf_cfg80211_vif *vif; ++ s32 err = 0; + +- brcmf_dbg(SCAN, "START ESCAN\n"); ++ brcmf_dbg(TRACE, "Enter\n"); ++ vif = container_of(request->wdev, struct brcmf_cfg80211_vif, wdev); ++ if (!check_vif_up(vif)) ++ return -EIO; + + if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { + brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status); +@@ -1102,6 +1105,8 @@ brcmf_cfg80211_escan(struct wiphy *wiphy + if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) + vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; + ++ brcmf_dbg(SCAN, "START ESCAN\n"); ++ + cfg->scan_request = request; + set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); + +@@ -1121,31 +1126,12 @@ brcmf_cfg80211_escan(struct wiphy *wiphy + return 0; + + scan_out: ++ brcmf_err("scan error (%d)\n", err); + clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); + cfg->scan_request = NULL; + return err; + } + +-static s32 +-brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) +-{ +- struct brcmf_cfg80211_vif *vif; +- s32 err = 0; +- +- brcmf_dbg(TRACE, "Enter\n"); +- vif = container_of(request->wdev, struct brcmf_cfg80211_vif, wdev); +- if (!check_vif_up(vif)) +- return -EIO; +- +- err = brcmf_cfg80211_escan(wiphy, vif, request); +- +- if (err) +- brcmf_err("scan error (%d)\n", err); +- +- brcmf_dbg(TRACE, "Exit\n"); +- return err; +-} +- + static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold) + { + s32 err = 0; diff --git a/package/kernel/mac80211/patches/303-v4.15-0006-brcmfmac-get-rid-of-struct-brcmf_cfg80211_info-activ.patch b/package/kernel/mac80211/patches/303-v4.15-0006-brcmfmac-get-rid-of-struct-brcmf_cfg80211_info-activ.patch new file mode 100644 index 000000000..4d4235f4b --- /dev/null +++ b/package/kernel/mac80211/patches/303-v4.15-0006-brcmfmac-get-rid-of-struct-brcmf_cfg80211_info-activ.patch @@ -0,0 +1,86 @@ +From bbf35414cd23a9d7230bfd7046e1e2c26020e7eb Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 8 Nov 2017 14:36:36 +0100 +Subject: [PATCH] brcmfmac: get rid of struct brcmf_cfg80211_info::active_scan + field + +The field struct brcmf_cfg80211_info::active_scan is set to true upon +initializing the driver instance, but it is never changed so simply +get rid of it. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 10 +--------- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h | 2 -- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 5 +---- + 3 files changed, 2 insertions(+), 15 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -1043,7 +1043,6 @@ brcmf_do_escan(struct brcmf_if *ifp, str + { + struct brcmf_cfg80211_info *cfg = ifp->drvr->config; + s32 err; +- u32 passive_scan; + struct brcmf_scan_results *results; + struct escan_info *escan = &cfg->escan_info; + +@@ -1051,13 +1050,7 @@ brcmf_do_escan(struct brcmf_if *ifp, str + escan->ifp = ifp; + escan->wiphy = cfg->wiphy; + escan->escan_state = WL_ESCAN_STATE_SCANNING; +- passive_scan = cfg->active_scan ? 0 : 1; +- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN, +- passive_scan); +- if (err) { +- brcmf_err("error (%d)\n", err); +- return err; +- } ++ + brcmf_scan_config_mpc(ifp, 0); + results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf; + results->version = 0; +@@ -5767,7 +5760,6 @@ static s32 wl_init_priv(struct brcmf_cfg + + cfg->scan_request = NULL; + cfg->pwr_save = true; +- cfg->active_scan = true; /* we do active scan per default */ + cfg->dongle_up = false; /* dongle is not up yet */ + err = brcmf_init_priv_mem(cfg); + if (err) +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h +@@ -283,7 +283,6 @@ struct brcmf_cfg80211_wowl { + * @scan_status: scan activity on the dongle. + * @pub: common driver information. + * @channel: current channel. +- * @active_scan: current scan mode. + * @int_escan_map: bucket map for which internal e-scan is done. + * @ibss_starter: indicates this sta is ibss starter. + * @pwr_save: indicate whether dongle to support power save mode. +@@ -316,7 +315,6 @@ struct brcmf_cfg80211_info { + unsigned long scan_status; + struct brcmf_pub *pub; + u32 channel; +- bool active_scan; + u32 int_escan_map; + bool ibss_starter; + bool pwr_save; +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +@@ -692,10 +692,7 @@ static s32 brcmf_p2p_escan(struct brcmf_ + + /* determine the scan engine parameters */ + sparams->bss_type = DOT11_BSSTYPE_ANY; +- if (p2p->cfg->active_scan) +- sparams->scan_type = 0; +- else +- sparams->scan_type = 1; ++ sparams->scan_type = BRCMF_SCANTYPE_ACTIVE; + + eth_broadcast_addr(sparams->bssid); + sparams->home_time = cpu_to_le32(P2PAPI_SCAN_HOME_TIME_MS); diff --git a/package/kernel/mac80211/patches/303-v4.15-0007-brcmfmac-move-configuration-of-probe-request-IEs.patch b/package/kernel/mac80211/patches/303-v4.15-0007-brcmfmac-move-configuration-of-probe-request-IEs.patch new file mode 100644 index 000000000..3ad6e79db --- /dev/null +++ b/package/kernel/mac80211/patches/303-v4.15-0007-brcmfmac-move-configuration-of-probe-request-IEs.patch @@ -0,0 +1,55 @@ +From bd99a3013bdc00f8fc7534c657b39616792b4467 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 8 Nov 2017 14:36:37 +0100 +Subject: [PATCH] brcmfmac: move configuration of probe request IEs + +The configuration of the IEs for probe requests was done in a P2P +related function, which is not very obvious. Moving it to +.scan callback function, ie. brcmf_cfg80211_scan(). + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 +++++ + drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 6 ++---- + 2 files changed, 7 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -1108,6 +1108,11 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, + if (err) + goto scan_out; + ++ err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBREQ_FLAG, ++ request->ie, request->ie_len); ++ if (err) ++ goto scan_out; ++ + err = brcmf_do_escan(vif->ifp, request); + if (err) + goto scan_out; +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +@@ -881,7 +881,7 @@ int brcmf_p2p_scan_prep(struct wiphy *wi + { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_p2p_info *p2p = &cfg->p2p; +- int err = 0; ++ int err; + + if (brcmf_p2p_scan_is_p2p_request(request)) { + /* find my listen channel */ +@@ -904,9 +904,7 @@ int brcmf_p2p_scan_prep(struct wiphy *wi + /* override .run_escan() callback. */ + cfg->escan_info.run = brcmf_p2p_run_escan; + } +- err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBREQ_FLAG, +- request->ie, request->ie_len); +- return err; ++ return 0; + } + + diff --git a/package/kernel/mac80211/patches/304-v4.15-brcmfmac-add-CLM-download-support.patch b/package/kernel/mac80211/patches/304-v4.15-brcmfmac-add-CLM-download-support.patch new file mode 100644 index 000000000..2cd5f7312 --- /dev/null +++ b/package/kernel/mac80211/patches/304-v4.15-brcmfmac-add-CLM-download-support.patch @@ -0,0 +1,434 @@ +From fdd0bd88ceaecf729db103ac8836af5805dd2dc1 Mon Sep 17 00:00:00 2001 +From: Chung-Hsien Hsu +Date: Fri, 10 Nov 2017 17:27:15 +0800 +Subject: [PATCH] brcmfmac: add CLM download support + +The firmware for brcmfmac devices includes information regarding +regulatory constraints. For certain devices this information is kept +separately in a binary form that needs to be downloaded to the device. +This patch adds support to download this so-called CLM blob file. It +uses the same naming scheme as the other firmware files with extension +of .clm_blob. + +The CLM blob file is optional. If the file does not exist, the download +process will be bypassed. It will not affect the driver loading. + +Reviewed-by: Arend van Spriel +Signed-off-by: Chung-Hsien Hsu +Signed-off-by: Kalle Valo +--- + .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 10 ++ + .../wireless/broadcom/brcm80211/brcmfmac/common.c | 157 +++++++++++++++++++++ + .../wireless/broadcom/brcm80211/brcmfmac/core.c | 2 + + .../wireless/broadcom/brcm80211/brcmfmac/core.h | 2 + + .../broadcom/brcm80211/brcmfmac/fwil_types.h | 31 ++++ + .../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 19 +++ + .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 19 +++ + .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 18 +++ + 8 files changed, 258 insertions(+) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +@@ -71,6 +71,7 @@ struct brcmf_bus_dcmd { + * @wowl_config: specify if dongle is configured for wowl when going to suspend + * @get_ramsize: obtain size of device memory. + * @get_memdump: obtain device memory dump in provided buffer. ++ * @get_fwname: obtain firmware name. + * + * This structure provides an abstract interface towards the + * bus specific driver. For control messages to common driver +@@ -87,6 +88,8 @@ struct brcmf_bus_ops { + void (*wowl_config)(struct device *dev, bool enabled); + size_t (*get_ramsize)(struct device *dev); + int (*get_memdump)(struct device *dev, void *data, size_t len); ++ int (*get_fwname)(struct device *dev, uint chip, uint chiprev, ++ unsigned char *fw_name); + }; + + +@@ -224,6 +227,13 @@ int brcmf_bus_get_memdump(struct brcmf_b + return bus->ops->get_memdump(bus->dev, data, len); + } + ++static inline ++int brcmf_bus_get_fwname(struct brcmf_bus *bus, uint chip, uint chiprev, ++ unsigned char *fw_name) ++{ ++ return bus->ops->get_fwname(bus->dev, chip, chiprev, fw_name); ++} ++ + /* + * interface functions from common layer + */ +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + #include + #include "core.h" +@@ -28,6 +29,7 @@ + #include "tracepoint.h" + #include "common.h" + #include "of.h" ++#include "firmware.h" + + MODULE_AUTHOR("Broadcom Corporation"); + MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); +@@ -104,12 +106,140 @@ void brcmf_c_set_joinpref_default(struct + brcmf_err("Set join_pref error (%d)\n", err); + } + ++static int brcmf_c_download(struct brcmf_if *ifp, u16 flag, ++ struct brcmf_dload_data_le *dload_buf, ++ u32 len) ++{ ++ s32 err; ++ ++ flag |= (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT); ++ dload_buf->flag = cpu_to_le16(flag); ++ dload_buf->dload_type = cpu_to_le16(DL_TYPE_CLM); ++ dload_buf->len = cpu_to_le32(len); ++ dload_buf->crc = cpu_to_le32(0); ++ len = sizeof(*dload_buf) + len - 1; ++ ++ err = brcmf_fil_iovar_data_set(ifp, "clmload", dload_buf, len); ++ ++ return err; ++} ++ ++static int brcmf_c_get_clm_name(struct brcmf_if *ifp, u8 *clm_name) ++{ ++ struct brcmf_bus *bus = ifp->drvr->bus_if; ++ struct brcmf_rev_info *ri = &ifp->drvr->revinfo; ++ u8 fw_name[BRCMF_FW_NAME_LEN]; ++ u8 *ptr; ++ size_t len; ++ s32 err; ++ ++ memset(fw_name, 0, BRCMF_FW_NAME_LEN); ++ err = brcmf_bus_get_fwname(bus, ri->chipnum, ri->chiprev, fw_name); ++ if (err) { ++ brcmf_err("get firmware name failed (%d)\n", err); ++ goto done; ++ } ++ ++ /* generate CLM blob file name */ ++ ptr = strrchr(fw_name, '.'); ++ if (!ptr) { ++ err = -ENOENT; ++ goto done; ++ } ++ ++ len = ptr - fw_name + 1; ++ if (len + strlen(".clm_blob") > BRCMF_FW_NAME_LEN) { ++ err = -E2BIG; ++ } else { ++ strlcpy(clm_name, fw_name, len); ++ strlcat(clm_name, ".clm_blob", BRCMF_FW_NAME_LEN); ++ } ++done: ++ return err; ++} ++ ++static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) ++{ ++ struct device *dev = ifp->drvr->bus_if->dev; ++ struct brcmf_dload_data_le *chunk_buf; ++ const struct firmware *clm = NULL; ++ u8 clm_name[BRCMF_FW_NAME_LEN]; ++ u32 chunk_len; ++ u32 datalen; ++ u32 cumulative_len; ++ u16 dl_flag = DL_BEGIN; ++ u32 status; ++ s32 err; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ memset(clm_name, 0, BRCMF_FW_NAME_LEN); ++ err = brcmf_c_get_clm_name(ifp, clm_name); ++ if (err) { ++ brcmf_err("get CLM blob file name failed (%d)\n", err); ++ return err; ++ } ++ ++ err = request_firmware(&clm, clm_name, dev); ++ if (err) { ++ if (err == -ENOENT) { ++ brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n"); ++ return 0; ++ } ++ brcmf_err("request CLM blob file failed (%d)\n", err); ++ return err; ++ } ++ ++ chunk_buf = kzalloc(sizeof(*chunk_buf) + MAX_CHUNK_LEN - 1, GFP_KERNEL); ++ if (!chunk_buf) { ++ err = -ENOMEM; ++ goto done; ++ } ++ ++ datalen = clm->size; ++ cumulative_len = 0; ++ do { ++ if (datalen > MAX_CHUNK_LEN) { ++ chunk_len = MAX_CHUNK_LEN; ++ } else { ++ chunk_len = datalen; ++ dl_flag |= DL_END; ++ } ++ memcpy(chunk_buf->data, clm->data + cumulative_len, chunk_len); ++ ++ err = brcmf_c_download(ifp, dl_flag, chunk_buf, chunk_len); ++ ++ dl_flag &= ~DL_BEGIN; ++ ++ cumulative_len += chunk_len; ++ datalen -= chunk_len; ++ } while ((datalen > 0) && (err == 0)); ++ ++ if (err) { ++ brcmf_err("clmload (%zu byte file) failed (%d); ", ++ clm->size, err); ++ /* Retrieve clmload_status and print */ ++ err = brcmf_fil_iovar_int_get(ifp, "clmload_status", &status); ++ if (err) ++ brcmf_err("get clmload_status failed (%d)\n", err); ++ else ++ brcmf_dbg(INFO, "clmload_status=%d\n", status); ++ err = -EIO; ++ } ++ ++ kfree(chunk_buf); ++done: ++ release_firmware(clm); ++ return err; ++} ++ + int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) + { + s8 eventmask[BRCMF_EVENTING_MASK_LEN]; + u8 buf[BRCMF_DCMD_SMLEN]; + struct brcmf_rev_info_le revinfo; + struct brcmf_rev_info *ri; ++ char *clmver; + char *ptr; + s32 err; + +@@ -148,6 +278,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_i + } + ri->result = err; + ++ /* Do any CLM downloading */ ++ err = brcmf_c_process_clm_blob(ifp); ++ if (err < 0) { ++ brcmf_err("download CLM blob file failed, %d\n", err); ++ goto done; ++ } ++ + /* query for 'ver' to get version info from firmware */ + memset(buf, 0, sizeof(buf)); + strcpy(buf, "ver"); +@@ -167,6 +304,26 @@ int brcmf_c_preinit_dcmds(struct brcmf_i + ptr = strrchr(buf, ' ') + 1; + strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver)); + ++ /* Query for 'clmver' to get CLM version info from firmware */ ++ memset(buf, 0, sizeof(buf)); ++ err = brcmf_fil_iovar_data_get(ifp, "clmver", buf, sizeof(buf)); ++ if (err) { ++ brcmf_dbg(TRACE, "retrieving clmver failed, %d\n", err); ++ } else { ++ clmver = (char *)buf; ++ /* store CLM version for adding it to revinfo debugfs file */ ++ memcpy(ifp->drvr->clmver, clmver, sizeof(ifp->drvr->clmver)); ++ ++ /* Replace all newline/linefeed characters with space ++ * character ++ */ ++ ptr = clmver; ++ while ((ptr = strnchr(ptr, '\n', sizeof(buf))) != NULL) ++ *ptr = ' '; ++ ++ brcmf_dbg(INFO, "CLM version = %s\n", clmver); ++ } ++ + /* set mpc */ + err = brcmf_fil_iovar_int_set(ifp, "mpc", 1); + if (err) { +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +@@ -1009,6 +1009,8 @@ static int brcmf_revinfo_read(struct seq + seq_printf(s, "anarev: %u\n", ri->anarev); + seq_printf(s, "nvramrev: %08x\n", ri->nvramrev); + ++ seq_printf(s, "clmver: %s\n", bus_if->drvr->clmver); ++ + return 0; + } + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +@@ -141,6 +141,8 @@ struct brcmf_pub { + struct notifier_block inetaddr_notifier; + struct notifier_block inet6addr_notifier; + struct brcmf_mp_device *settings; ++ ++ u8 clmver[BRCMF_DCMD_SMLEN]; + }; + + /* forward declarations */ +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +@@ -155,6 +155,21 @@ + #define BRCMF_MFP_CAPABLE 1 + #define BRCMF_MFP_REQUIRED 2 + ++/* MAX_CHUNK_LEN is the maximum length for data passing to firmware in each ++ * ioctl. It is relatively small because firmware has small maximum size input ++ * playload restriction for ioctls. ++ */ ++#define MAX_CHUNK_LEN 1400 ++ ++#define DLOAD_HANDLER_VER 1 /* Downloader version */ ++#define DLOAD_FLAG_VER_MASK 0xf000 /* Downloader version mask */ ++#define DLOAD_FLAG_VER_SHIFT 12 /* Downloader version shift */ ++ ++#define DL_BEGIN 0x0002 ++#define DL_END 0x0004 ++ ++#define DL_TYPE_CLM 2 ++ + /* join preference types for join_pref iovar */ + enum brcmf_join_pref_types { + BRCMF_JOIN_PREF_RSSI = 1, +@@ -827,6 +842,22 @@ struct brcmf_pno_macaddr_le { + }; + + /** ++ * struct brcmf_dload_data_le - data passing to firmware for downloading ++ * @flag: flags related to download data. ++ * @dload_type: type of download data. ++ * @len: length in bytes of download data. ++ * @crc: crc of download data. ++ * @data: download data. ++ */ ++struct brcmf_dload_data_le { ++ __le16 flag; ++ __le16 dload_type; ++ __le32 len; ++ __le32 crc; ++ u8 data[1]; ++}; ++ ++/** + * struct brcmf_pno_bssid_le - bssid configuration for PNO scan. + * + * @bssid: BSS network identifier. +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -1350,6 +1350,24 @@ static int brcmf_pcie_get_memdump(struct + return 0; + } + ++static int brcmf_pcie_get_fwname(struct device *dev, u32 chip, u32 chiprev, ++ u8 *fw_name) ++{ ++ struct brcmf_bus *bus_if = dev_get_drvdata(dev); ++ struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie; ++ struct brcmf_pciedev_info *devinfo = buspub->devinfo; ++ int ret = 0; ++ ++ if (devinfo->fw_name[0] != '\0') ++ strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN); ++ else ++ ret = brcmf_fw_map_chip_to_name(chip, chiprev, ++ brcmf_pcie_fwnames, ++ ARRAY_SIZE(brcmf_pcie_fwnames), ++ fw_name, NULL); ++ ++ return ret; ++} + + static const struct brcmf_bus_ops brcmf_pcie_bus_ops = { + .txdata = brcmf_pcie_tx, +@@ -1359,6 +1377,7 @@ static const struct brcmf_bus_ops brcmf_ + .wowl_config = brcmf_pcie_wowl_config, + .get_ramsize = brcmf_pcie_get_ramsize, + .get_memdump = brcmf_pcie_get_memdump, ++ .get_fwname = brcmf_pcie_get_fwname, + }; + + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -3985,6 +3985,24 @@ brcmf_sdio_watchdog(unsigned long data) + } + } + ++static int brcmf_sdio_get_fwname(struct device *dev, u32 chip, u32 chiprev, ++ u8 *fw_name) ++{ ++ struct brcmf_bus *bus_if = dev_get_drvdata(dev); ++ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ int ret = 0; ++ ++ if (sdiodev->fw_name[0] != '\0') ++ strlcpy(fw_name, sdiodev->fw_name, BRCMF_FW_NAME_LEN); ++ else ++ ret = brcmf_fw_map_chip_to_name(chip, chiprev, ++ brcmf_sdio_fwnames, ++ ARRAY_SIZE(brcmf_sdio_fwnames), ++ fw_name, NULL); ++ ++ return ret; ++} ++ + static const struct brcmf_bus_ops brcmf_sdio_bus_ops = { + .stop = brcmf_sdio_bus_stop, + .preinit = brcmf_sdio_bus_preinit, +@@ -3995,6 +4013,7 @@ static const struct brcmf_bus_ops brcmf_ + .wowl_config = brcmf_sdio_wowl_config, + .get_ramsize = brcmf_sdio_bus_get_ramsize, + .get_memdump = brcmf_sdio_bus_get_memdump, ++ .get_fwname = brcmf_sdio_get_fwname, + }; + + static void brcmf_sdio_firmware_callback(struct device *dev, int err, +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +@@ -1128,12 +1128,30 @@ static void brcmf_usb_wowl_config(struct + device_set_wakeup_enable(devinfo->dev, false); + } + ++static int brcmf_usb_get_fwname(struct device *dev, u32 chip, u32 chiprev, ++ u8 *fw_name) ++{ ++ struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); ++ int ret = 0; ++ ++ if (devinfo->fw_name[0] != '\0') ++ strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN); ++ else ++ ret = brcmf_fw_map_chip_to_name(chip, chiprev, ++ brcmf_usb_fwnames, ++ ARRAY_SIZE(brcmf_usb_fwnames), ++ fw_name, NULL); ++ ++ return ret; ++} ++ + static const struct brcmf_bus_ops brcmf_usb_bus_ops = { + .txdata = brcmf_usb_tx, + .stop = brcmf_usb_down, + .txctl = brcmf_usb_tx_ctlpkt, + .rxctl = brcmf_usb_rx_ctlpkt, + .wowl_config = brcmf_usb_wowl_config, ++ .get_fwname = brcmf_usb_get_fwname, + }; + + static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo) diff --git a/package/kernel/mac80211/patches/305-v4.15-brcmfmac-change-driver-unbind-order-of-the-sdio-func.patch b/package/kernel/mac80211/patches/305-v4.15-brcmfmac-change-driver-unbind-order-of-the-sdio-func.patch new file mode 100644 index 000000000..3649bdda4 --- /dev/null +++ b/package/kernel/mac80211/patches/305-v4.15-brcmfmac-change-driver-unbind-order-of-the-sdio-func.patch @@ -0,0 +1,37 @@ +From 5c3de777bdaf48bd0cfb43097c0d0fb85056cab7 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Sat, 25 Nov 2017 21:39:25 +0100 +Subject: [PATCH] brcmfmac: change driver unbind order of the sdio function + devices + +In the function brcmf_sdio_firmware_callback() the driver is +unbound from the sdio function devices in the error path. +However, the order in which it is done resulted in a use-after-free +issue (see brcmf_ops_sdio_remove() in bcmsdh.c). Hence change +the order and first unbind sdio function #2 device and then +unbind sdio function #1 device. + +Cc: stable@vger.kernel.org # v4.12.x +Fixes: 7a51461fc2da ("brcmfmac: unbind all devices upon failure in firmware callback") +Reported-by: Stefan Wahren +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -4121,8 +4121,8 @@ release: + sdio_release_host(sdiodev->func[1]); + fail: + brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err); +- device_release_driver(dev); + device_release_driver(&sdiodev->func[2]->dev); ++ device_release_driver(dev); + } + + struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) diff --git a/package/kernel/mac80211/patches/306-v4.15-brcmfmac-Avoid-build-error-with-make-W-1.patch b/package/kernel/mac80211/patches/306-v4.15-brcmfmac-Avoid-build-error-with-make-W-1.patch new file mode 100644 index 000000000..7344580d3 --- /dev/null +++ b/package/kernel/mac80211/patches/306-v4.15-brcmfmac-Avoid-build-error-with-make-W-1.patch @@ -0,0 +1,33 @@ +From 51ef7925e10688c57186d438e784532e063492e4 Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Thu, 23 Nov 2017 17:57:04 +0200 +Subject: [PATCH] brcmfmac: Avoid build error with make W=1 + +When I run make W=1 on gcc (Debian 7.2.0-16) 7.2.0 I got an error for +the first run, all next ones are okay. + + CC [M] drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.o +drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c:2078: error: Cannot parse struct or union! +scripts/Makefile.build:310: recipe for target 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.o' failed + +Seems like something happened with W=1 and wrong kernel doc format. +As a quick fix remove dubious /** in the code. + +Signed-off-by: Andy Shevchenko +Acked-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -2070,7 +2070,7 @@ static int brcmf_sdio_txpkt_hdalign(stru + return head_pad; + } + +-/** ++/* + * struct brcmf_skbuff_cb reserves first two bytes in sk_buff::cb for + * bus layer usage. + */ diff --git a/package/kernel/mac80211/patches/307-v4.15-brcmfmac-fix-CLM-load-error-for-legacy-chips-when-us.patch b/package/kernel/mac80211/patches/307-v4.15-brcmfmac-fix-CLM-load-error-for-legacy-chips-when-us.patch new file mode 100644 index 000000000..ead5e7214 --- /dev/null +++ b/package/kernel/mac80211/patches/307-v4.15-brcmfmac-fix-CLM-load-error-for-legacy-chips-when-us.patch @@ -0,0 +1,40 @@ +From cc124d5cc8d81985c3511892d7a6d546552ff754 Mon Sep 17 00:00:00 2001 +From: Wright Feng +Date: Tue, 16 Jan 2018 17:26:50 +0800 +Subject: [PATCH] brcmfmac: fix CLM load error for legacy chips when user + helper is enabled + +For legacy chips without CLM blob files, kernel with user helper function +returns -EAGAIN when we request_firmware(), and then driver got failed +when bringing up legacy chips. We expect the CLM blob file for legacy chip +is not existence in firmware path, but the -ENOENT error is transferred to +-EAGAIN in firmware_class.c with user helper. +Because of that, we continue with CLM data currently present in firmware +if getting error from doing request_firmware(). + +Cc: stable@vger.kernel.org # v4.15.y +Reviewed-by: Arend van Spriel +Signed-off-by: Wright Feng +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +@@ -182,12 +182,9 @@ static int brcmf_c_process_clm_blob(stru + + err = request_firmware(&clm, clm_name, dev); + if (err) { +- if (err == -ENOENT) { +- brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n"); +- return 0; +- } +- brcmf_err("request CLM blob file failed (%d)\n", err); +- return err; ++ brcmf_info("no clm_blob available(err=%d), device may have limited channels available\n", ++ err); ++ return 0; + } + + chunk_buf = kzalloc(sizeof(*chunk_buf) + MAX_CHUNK_LEN - 1, GFP_KERNEL); diff --git a/package/kernel/mac80211/patches/321-0001-ath9k-move-spectral-scan-support-under-a-separate-co.patch b/package/kernel/mac80211/patches/308-v4.16-0001-ath9k-move-spectral-scan-support-under-a-separate-co.patch similarity index 100% rename from package/kernel/mac80211/patches/321-0001-ath9k-move-spectral-scan-support-under-a-separate-co.patch rename to package/kernel/mac80211/patches/308-v4.16-0001-ath9k-move-spectral-scan-support-under-a-separate-co.patch diff --git a/package/kernel/mac80211/patches/321-0002-ath10k-move-spectral-scan-support-under-a-separate-c.patch b/package/kernel/mac80211/patches/309-v4.16-0002-ath10k-move-spectral-scan-support-under-a-separate-c.patch similarity index 100% rename from package/kernel/mac80211/patches/321-0002-ath10k-move-spectral-scan-support-under-a-separate-c.patch rename to package/kernel/mac80211/patches/309-v4.16-0002-ath10k-move-spectral-scan-support-under-a-separate-c.patch diff --git a/package/kernel/mac80211/patches/310-v4.16-ath9k-discard-undersized-packets.patch b/package/kernel/mac80211/patches/310-v4.16-ath9k-discard-undersized-packets.patch new file mode 100644 index 000000000..b2b2fcf4a --- /dev/null +++ b/package/kernel/mac80211/patches/310-v4.16-ath9k-discard-undersized-packets.patch @@ -0,0 +1,25 @@ +From: Felix Fietkau +Date: Wed, 17 Jan 2018 11:11:17 +0100 +Subject: [PATCH] ath9k: discard undersized packets + +Sometimes the hardware will push small packets that trigger a WARN_ON +in mac80211. Discard them early to avoid this issue. + +Reported-by: Stijn Tintel +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/wireless/ath/ath9k/recv.c ++++ b/drivers/net/wireless/ath/ath9k/recv.c +@@ -826,9 +826,9 @@ static int ath9k_rx_skb_preprocess(struc + sc->rx.discard_next = false; + + /* +- * Discard zero-length packets. ++ * Discard zero-length packets and packets smaller than an ACK + */ +- if (!rx_stats->rs_datalen) { ++ if (rx_stats->rs_datalen < 10) { + RX_STAT_INC(rx_len_err); + goto corrupt; + } diff --git a/package/kernel/mac80211/patches/311-v4.16-0001-brcmfmac-Fix-parameter-order-in-brcmf_sdiod_f0_write.patch b/package/kernel/mac80211/patches/311-v4.16-0001-brcmfmac-Fix-parameter-order-in-brcmf_sdiod_f0_write.patch new file mode 100644 index 000000000..616a82119 --- /dev/null +++ b/package/kernel/mac80211/patches/311-v4.16-0001-brcmfmac-Fix-parameter-order-in-brcmf_sdiod_f0_write.patch @@ -0,0 +1,39 @@ +From 1fd3ae124d5e675f57cf7e3c601fb8f7712e0329 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Mon, 13 Nov 2017 21:35:38 +0100 +Subject: [PATCH] brcmfmac: Fix parameter order in brcmf_sdiod_f0_writeb() + +All the other IO functions are the other way round in this +driver. Make this one match. + +Signed-off-by: Ian Molton +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -230,8 +230,8 @@ void brcmf_sdiod_change_state(struct brc + sdiodev->state = state; + } + +-static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, +- uint regaddr, u8 byte) ++static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, u8 byte, ++ uint regaddr) + { + int err_ret; + +@@ -269,8 +269,8 @@ static int brcmf_sdiod_request_data(stru + if (fn) + sdio_writeb(func, *(u8 *)data, addr, &ret); + else +- ret = brcmf_sdiod_f0_writeb(func, addr, +- *(u8 *)data); ++ ret = brcmf_sdiod_f0_writeb(func, *(u8 *)data, ++ addr); + } else { + if (fn) + *(u8 *)data = sdio_readb(func, addr, &ret); diff --git a/package/kernel/mac80211/patches/311-v4.16-0002-brcmfmac-Register-sizes-on-hardware-are-not-dependen.patch b/package/kernel/mac80211/patches/311-v4.16-0002-brcmfmac-Register-sizes-on-hardware-are-not-dependen.patch new file mode 100644 index 000000000..719268f8f --- /dev/null +++ b/package/kernel/mac80211/patches/311-v4.16-0002-brcmfmac-Register-sizes-on-hardware-are-not-dependen.patch @@ -0,0 +1,105 @@ +From 1e6f676f43aa4270ebc5cff8e32a55f72362e042 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Mon, 13 Nov 2017 21:35:39 +0100 +Subject: [PATCH] brcmfmac: Register sizes on hardware are not dependent on + compiler types + +The 4 IO functions in this patch are incorrect as they use compiler types +to determine how many bytes to send to the hardware. + +Signed-off-by: Ian Molton +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -264,7 +264,7 @@ static int brcmf_sdiod_request_data(stru + func = sdiodev->func[fn]; + + switch (regsz) { +- case sizeof(u8): ++ case 1: + if (write) { + if (fn) + sdio_writeb(func, *(u8 *)data, addr, &ret); +@@ -278,13 +278,13 @@ static int brcmf_sdiod_request_data(stru + *(u8 *)data = sdio_f0_readb(func, addr, &ret); + } + break; +- case sizeof(u16): ++ case 2: + if (write) + sdio_writew(func, *(u16 *)data, addr, &ret); + else + *(u16 *)data = sdio_readw(func, addr, &ret); + break; +- case sizeof(u32): ++ case 4: + if (write) + sdio_writel(func, *(u32 *)data, addr, &ret); + else +@@ -368,7 +368,7 @@ brcmf_sdiod_set_sbaddr_window(struct brc + for (i = 0; i < 3; i++) { + err = brcmf_sdiod_regrw_helper(sdiodev, + SBSDIO_FUNC1_SBADDRLOW + i, +- sizeof(u8), &addr[i], true); ++ 1, &addr[i], true); + if (err) { + brcmf_err("failed at addr: 0x%0x\n", + SBSDIO_FUNC1_SBADDRLOW + i); +@@ -407,7 +407,7 @@ u8 brcmf_sdiod_regrb(struct brcmf_sdio_d + int retval; + + brcmf_dbg(SDIO, "addr:0x%08x\n", addr); +- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data, ++ retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 1, &data, + false); + brcmf_dbg(SDIO, "data:0x%02x\n", data); + +@@ -423,10 +423,10 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_ + int retval; + + brcmf_dbg(SDIO, "addr:0x%08x\n", addr); +- retval = brcmf_sdiod_addrprep(sdiodev, sizeof(data), &addr); ++ retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr); + if (retval) + goto done; +- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data, ++ retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 4, &data, + false); + brcmf_dbg(SDIO, "data:0x%08x\n", data); + +@@ -443,7 +443,7 @@ void brcmf_sdiod_regwb(struct brcmf_sdio + int retval; + + brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data); +- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data, ++ retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 1, &data, + true); + if (ret) + *ret = retval; +@@ -455,10 +455,10 @@ void brcmf_sdiod_regwl(struct brcmf_sdio + int retval; + + brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data); +- retval = brcmf_sdiod_addrprep(sdiodev, sizeof(data), &addr); ++ retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr); + if (retval) + goto done; +- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data, ++ retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 4, &data, + true); + + done: +@@ -876,7 +876,7 @@ int brcmf_sdiod_abort(struct brcmf_sdio_ + + /* issue abort cmd52 command through F0 */ + brcmf_sdiod_request_data(sdiodev, SDIO_FUNC_0, SDIO_CCCR_ABORT, +- sizeof(t_func), &t_func, true); ++ 1, &t_func, true); + + brcmf_dbg(SDIO, "Exit\n"); + return 0; diff --git a/package/kernel/mac80211/patches/311-v4.16-0003-brcmfmac-Split-brcmf_sdiod_regrw_helper-up.patch b/package/kernel/mac80211/patches/311-v4.16-0003-brcmfmac-Split-brcmf_sdiod_regrw_helper-up.patch new file mode 100644 index 000000000..b04465ae4 --- /dev/null +++ b/package/kernel/mac80211/patches/311-v4.16-0003-brcmfmac-Split-brcmf_sdiod_regrw_helper-up.patch @@ -0,0 +1,179 @@ +From 0fcc9fe0048422d66bb906eaa73cc75e11ff7345 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Mon, 13 Nov 2017 21:35:40 +0100 +Subject: [PATCH] brcmfmac: Split brcmf_sdiod_regrw_helper() up. + +This large function is concealing a LOT of obscure logic about +how the hardware functions. Time to split it up. + +This first patch splits the function into two pieces - read and write, +doing away with the rw flag in the process. + +Signed-off-by: Ian Molton +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 94 +++++++++++++++++----- + 1 file changed, 73 insertions(+), 21 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -302,8 +302,8 @@ static int brcmf_sdiod_request_data(stru + return ret; + } + +-static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, +- u8 regsz, void *data, bool write) ++static int brcmf_sdiod_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, ++ u8 regsz, void *data) + { + u8 func; + s32 retry = 0; +@@ -324,13 +324,66 @@ static int brcmf_sdiod_regrw_helper(stru + func = SDIO_FUNC_1; + + do { +- if (!write) +- memset(data, 0, regsz); + /* for retry wait for 1 ms till bus get settled down */ + if (retry) + usleep_range(1000, 2000); ++ ++ ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz, ++ data, true); ++ ++ } while (ret != 0 && ret != -ENOMEDIUM && ++ retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); ++ ++ if (ret == -ENOMEDIUM) { ++ brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM); ++ } else if (ret != 0) { ++ /* ++ * SleepCSR register access can fail when ++ * waking up the device so reduce this noise ++ * in the logs. ++ */ ++ if (addr != SBSDIO_FUNC1_SLEEPCSR) ++ brcmf_err("failed to write data F%d@0x%05x, err: %d\n", ++ func, addr, ret); ++ else ++ brcmf_dbg(SDIO, "failed to write data F%d@0x%05x, err: %d\n", ++ func, addr, ret); ++ } ++ ++ return ret; ++} ++ ++static int brcmf_sdiod_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, ++ u8 regsz, void *data) ++{ ++ u8 func; ++ s32 retry = 0; ++ int ret; ++ ++ if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM) ++ return -ENOMEDIUM; ++ ++ /* ++ * figure out how to read the register based on address range ++ * 0x00 ~ 0x7FF: function 0 CCCR and FBR ++ * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers ++ * The rest: function 1 silicon backplane core registers ++ */ ++ if ((addr & ~REG_F0_REG_MASK) == 0) ++ func = SDIO_FUNC_0; ++ else ++ func = SDIO_FUNC_1; ++ ++ do { ++ memset(data, 0, regsz); ++ ++ /* for retry wait for 1 ms till bus get settled down */ ++ if (retry) ++ usleep_range(1000, 2000); ++ + ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz, +- data, write); ++ data, false); ++ + } while (ret != 0 && ret != -ENOMEDIUM && + retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); + +@@ -343,12 +396,13 @@ static int brcmf_sdiod_regrw_helper(stru + * in the logs. + */ + if (addr != SBSDIO_FUNC1_SLEEPCSR) +- brcmf_err("failed to %s data F%d@0x%05x, err: %d\n", +- write ? "write" : "read", func, addr, ret); ++ brcmf_err("failed to read data F%d@0x%05x, err: %d\n", ++ func, addr, ret); + else +- brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n", +- write ? "write" : "read", func, addr, ret); ++ brcmf_dbg(SDIO, "failed to read data F%d@0x%05x, err: %d\n", ++ func, addr, ret); + } ++ + return ret; + } + +@@ -366,13 +420,11 @@ brcmf_sdiod_set_sbaddr_window(struct brc + addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK; + + for (i = 0; i < 3; i++) { +- err = brcmf_sdiod_regrw_helper(sdiodev, +- SBSDIO_FUNC1_SBADDRLOW + i, +- 1, &addr[i], true); ++ brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i, addr[i], ++ &err); + if (err) { + brcmf_err("failed at addr: 0x%0x\n", + SBSDIO_FUNC1_SBADDRLOW + i); +- break; + } + } + +@@ -407,8 +459,7 @@ u8 brcmf_sdiod_regrb(struct brcmf_sdio_d + int retval; + + brcmf_dbg(SDIO, "addr:0x%08x\n", addr); +- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 1, &data, +- false); ++ retval = brcmf_sdiod_reg_read(sdiodev, addr, 1, &data); + brcmf_dbg(SDIO, "data:0x%02x\n", data); + + if (ret) +@@ -426,8 +477,9 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_ + retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr); + if (retval) + goto done; +- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 4, &data, +- false); ++ ++ retval = brcmf_sdiod_reg_read(sdiodev, addr, 4, &data); ++ + brcmf_dbg(SDIO, "data:0x%08x\n", data); + + done: +@@ -443,8 +495,8 @@ void brcmf_sdiod_regwb(struct brcmf_sdio + int retval; + + brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data); +- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 1, &data, +- true); ++ retval = brcmf_sdiod_reg_write(sdiodev, addr, 1, &data); ++ + if (ret) + *ret = retval; + } +@@ -458,8 +510,8 @@ void brcmf_sdiod_regwl(struct brcmf_sdio + retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr); + if (retval) + goto done; +- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 4, &data, +- true); ++ ++ retval = brcmf_sdiod_reg_write(sdiodev, addr, 4, &data); + + done: + if (ret) diff --git a/package/kernel/mac80211/patches/311-v4.16-0004-brcmfmac-Clean-up-brcmf_sdiod_set_sbaddr_window.patch b/package/kernel/mac80211/patches/311-v4.16-0004-brcmfmac-Clean-up-brcmf_sdiod_set_sbaddr_window.patch new file mode 100644 index 000000000..1f0488a62 --- /dev/null +++ b/package/kernel/mac80211/patches/311-v4.16-0004-brcmfmac-Clean-up-brcmf_sdiod_set_sbaddr_window.patch @@ -0,0 +1,62 @@ +From b9b0d290bc0c90a5a262bc89c9d995988ea98669 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Mon, 13 Nov 2017 21:35:41 +0100 +Subject: [PATCH] brcmfmac: Clean up brcmf_sdiod_set_sbaddr_window() + +This function sets the address of the IO window used for +SDIO accesses onto the backplane of the chip. + +It currently uses 3 separate masks despite the full mask being +defined in the code already. Remove the separate masks and clean up. + +Signed-off-by: Ian Molton +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 17 +++++------------ + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 3 --- + 2 files changed, 5 insertions(+), 15 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -410,23 +410,16 @@ static int + brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) + { + int err = 0, i; +- u8 addr[3]; ++ u32 addr; + + if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM) + return -ENOMEDIUM; + +- addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK; +- addr[1] = (address >> 16) & SBSDIO_SBADDRMID_MASK; +- addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK; ++ addr = (address & SBSDIO_SBWINDOW_MASK) >> 8; + +- for (i = 0; i < 3; i++) { +- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i, addr[i], +- &err); +- if (err) { +- brcmf_err("failed at addr: 0x%0x\n", +- SBSDIO_FUNC1_SBADDRLOW + i); +- } +- } ++ for (i = 0 ; i < 3 && !err ; i++, addr >>= 8) ++ brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i, ++ addr & 0xff, &err); + + return err; + } +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +@@ -133,9 +133,6 @@ + + /* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */ + +-#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */ +-#define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */ +-#define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */ + /* Address bits from SBADDR regs */ + #define SBSDIO_SBWINDOW_MASK 0xffff8000 + diff --git a/package/kernel/mac80211/patches/311-v4.16-0005-brcmfmac-Remove-dead-IO-code.patch b/package/kernel/mac80211/patches/311-v4.16-0005-brcmfmac-Remove-dead-IO-code.patch new file mode 100644 index 000000000..7d50ce923 --- /dev/null +++ b/package/kernel/mac80211/patches/311-v4.16-0005-brcmfmac-Remove-dead-IO-code.patch @@ -0,0 +1,91 @@ +From ea243e9077b3545f20d93884e91c50ac0719685a Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Mon, 13 Nov 2017 21:35:42 +0100 +Subject: [PATCH] brcmfmac: Remove dead IO code + +The value passed to brcmf_sdiod_addrprep() is *always* 4 +remove this parameter and the unused code to handle it. + +Signed-off-by: Ian Molton +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 18 ++++++++---------- + 1 file changed, 8 insertions(+), 10 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -425,7 +425,7 @@ brcmf_sdiod_set_sbaddr_window(struct brc + } + + static int +-brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, uint width, u32 *addr) ++brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr) + { + uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK; + int err = 0; +@@ -439,9 +439,7 @@ brcmf_sdiod_addrprep(struct brcmf_sdio_d + } + + *addr &= SBSDIO_SB_OFT_ADDR_MASK; +- +- if (width == 4) +- *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + + return 0; + } +@@ -467,7 +465,7 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_ + int retval; + + brcmf_dbg(SDIO, "addr:0x%08x\n", addr); +- retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr); ++ retval = brcmf_sdiod_addrprep(sdiodev, &addr); + if (retval) + goto done; + +@@ -500,7 +498,7 @@ void brcmf_sdiod_regwl(struct brcmf_sdio + int retval; + + brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data); +- retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr); ++ retval = brcmf_sdiod_addrprep(sdiodev, &addr); + if (retval) + goto done; + +@@ -736,7 +734,7 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd + + brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pkt->len); + +- err = brcmf_sdiod_addrprep(sdiodev, 4, &addr); ++ err = brcmf_sdiod_addrprep(sdiodev, &addr); + if (err) + goto done; + +@@ -757,7 +755,7 @@ int brcmf_sdiod_recv_chain(struct brcmf_ + brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", + addr, pktq->qlen); + +- err = brcmf_sdiod_addrprep(sdiodev, 4, &addr); ++ err = brcmf_sdiod_addrprep(sdiodev, &addr); + if (err) + goto done; + +@@ -801,7 +799,7 @@ int brcmf_sdiod_send_buf(struct brcmf_sd + + memcpy(mypkt->data, buf, nbytes); + +- err = brcmf_sdiod_addrprep(sdiodev, 4, &addr); ++ err = brcmf_sdiod_addrprep(sdiodev, &addr); + + if (!err) + err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, true, addr, +@@ -821,7 +819,7 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd + + brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pktq->qlen); + +- err = brcmf_sdiod_addrprep(sdiodev, 4, &addr); ++ err = brcmf_sdiod_addrprep(sdiodev, &addr); + if (err) + return err; + diff --git a/package/kernel/mac80211/patches/311-v4.16-0006-brcmfmac-Remove-bandaid-for-SleepCSR.patch b/package/kernel/mac80211/patches/311-v4.16-0006-brcmfmac-Remove-bandaid-for-SleepCSR.patch new file mode 100644 index 000000000..fef29fc71 --- /dev/null +++ b/package/kernel/mac80211/patches/311-v4.16-0006-brcmfmac-Remove-bandaid-for-SleepCSR.patch @@ -0,0 +1,61 @@ +From 4a3338ba2a7421db2260159cca5a27bd2ee36d00 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Mon, 13 Nov 2017 21:35:43 +0100 +Subject: [PATCH] brcmfmac: Remove bandaid for SleepCSR + +Register access code is not the place for band-aid fixes like this. +If this is a genuine problem, it should be fixed further up in the driver +stack. + +Signed-off-by: Ian Molton +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 28 +--------------------- + 1 file changed, 1 insertion(+), 27 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -334,21 +334,8 @@ static int brcmf_sdiod_reg_write(struct + } while (ret != 0 && ret != -ENOMEDIUM && + retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); + +- if (ret == -ENOMEDIUM) { ++ if (ret == -ENOMEDIUM) + brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM); +- } else if (ret != 0) { +- /* +- * SleepCSR register access can fail when +- * waking up the device so reduce this noise +- * in the logs. +- */ +- if (addr != SBSDIO_FUNC1_SLEEPCSR) +- brcmf_err("failed to write data F%d@0x%05x, err: %d\n", +- func, addr, ret); +- else +- brcmf_dbg(SDIO, "failed to write data F%d@0x%05x, err: %d\n", +- func, addr, ret); +- } + + return ret; + } +@@ -389,19 +376,6 @@ static int brcmf_sdiod_reg_read(struct b + + if (ret == -ENOMEDIUM) + brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM); +- else if (ret != 0) { +- /* +- * SleepCSR register access can fail when +- * waking up the device so reduce this noise +- * in the logs. +- */ +- if (addr != SBSDIO_FUNC1_SLEEPCSR) +- brcmf_err("failed to read data F%d@0x%05x, err: %d\n", +- func, addr, ret); +- else +- brcmf_dbg(SDIO, "failed to read data F%d@0x%05x, err: %d\n", +- func, addr, ret); +- } + + return ret; + } diff --git a/package/kernel/mac80211/patches/311-v4.16-0007-brcmfmac-Remove-brcmf_sdiod_request_data.patch b/package/kernel/mac80211/patches/311-v4.16-0007-brcmfmac-Remove-brcmf_sdiod_request_data.patch new file mode 100644 index 000000000..beaa4d3a2 --- /dev/null +++ b/package/kernel/mac80211/patches/311-v4.16-0007-brcmfmac-Remove-brcmf_sdiod_request_data.patch @@ -0,0 +1,344 @@ +From 993a98a42e6e790fd0d2bf7d55a031513c7ba7dc Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Mon, 13 Nov 2017 21:35:44 +0100 +Subject: [PATCH] brcmfmac: Remove brcmf_sdiod_request_data() + +This function is obfuscating how IO works on this chip. Remove it +and push its logic into brcmf_sdiod_reg_{read,write}(). + +Handling of -ENOMEDIUM is altered, but as that's pretty much broken anyway +we can ignore that. + +Signed-off-by: Ian Molton +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 237 ++++++++------------- + .../wireless/broadcom/brcm80211/brcmfmac/sdio.h | 2 +- + 2 files changed, 87 insertions(+), 152 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -230,6 +230,43 @@ void brcmf_sdiod_change_state(struct brc + sdiodev->state = state; + } + ++static int brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, ++ u32 address) ++{ ++ int err = 0, i; ++ u32 addr; ++ ++ if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM) ++ return -ENOMEDIUM; ++ ++ addr = (address & SBSDIO_SBWINDOW_MASK) >> 8; ++ ++ for (i = 0 ; i < 3 && !err ; i++, addr >>= 8) ++ brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i, ++ addr & 0xff, &err); ++ ++ return err; ++} ++ ++static int brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr) ++{ ++ uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK; ++ int err = 0; ++ ++ if (bar0 != sdiodev->sbwad) { ++ err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0); ++ if (err) ++ return err; ++ ++ sdiodev->sbwad = bar0; ++ } ++ ++ *addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ ++ return 0; ++} ++ + static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, u8 byte, + uint regaddr) + { +@@ -249,173 +286,84 @@ static inline int brcmf_sdiod_f0_writeb( + return err_ret; + } + +-static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn, +- u32 addr, u8 regsz, void *data, bool write) +-{ +- struct sdio_func *func; +- int ret = -EINVAL; +- +- brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", +- write, fn, addr, regsz); +- +- /* only allow byte access on F0 */ +- if (WARN_ON(regsz > 1 && !fn)) +- return -EINVAL; +- func = sdiodev->func[fn]; +- +- switch (regsz) { +- case 1: +- if (write) { +- if (fn) +- sdio_writeb(func, *(u8 *)data, addr, &ret); +- else +- ret = brcmf_sdiod_f0_writeb(func, *(u8 *)data, +- addr); +- } else { +- if (fn) +- *(u8 *)data = sdio_readb(func, addr, &ret); +- else +- *(u8 *)data = sdio_f0_readb(func, addr, &ret); +- } +- break; +- case 2: +- if (write) +- sdio_writew(func, *(u16 *)data, addr, &ret); +- else +- *(u16 *)data = sdio_readw(func, addr, &ret); +- break; +- case 4: +- if (write) +- sdio_writel(func, *(u32 *)data, addr, &ret); +- else +- *(u32 *)data = sdio_readl(func, addr, &ret); +- break; +- default: +- brcmf_err("invalid size: %d\n", regsz); +- break; +- } +- +- if (ret) +- brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n", +- write ? "write" : "read", fn, addr, ret); +- +- return ret; +-} +- + static int brcmf_sdiod_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, + u8 regsz, void *data) + { +- u8 func; +- s32 retry = 0; + int ret; + +- if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM) +- return -ENOMEDIUM; +- + /* + * figure out how to read the register based on address range + * 0x00 ~ 0x7FF: function 0 CCCR and FBR + * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers + * The rest: function 1 silicon backplane core registers ++ * f0 writes must be bytewise + */ +- if ((addr & ~REG_F0_REG_MASK) == 0) +- func = SDIO_FUNC_0; +- else +- func = SDIO_FUNC_1; + +- do { +- /* for retry wait for 1 ms till bus get settled down */ +- if (retry) +- usleep_range(1000, 2000); +- +- ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz, +- data, true); +- +- } while (ret != 0 && ret != -ENOMEDIUM && +- retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); ++ if ((addr & ~REG_F0_REG_MASK) == 0) { ++ if (WARN_ON(regsz > 1)) ++ return -EINVAL; ++ ret = brcmf_sdiod_f0_writeb(sdiodev->func[0], ++ *(u8 *)data, addr); ++ } else { ++ switch (regsz) { ++ case 1: ++ sdio_writeb(sdiodev->func[1], *(u8 *)data, addr, &ret); ++ break; ++ case 4: ++ ret = brcmf_sdiod_addrprep(sdiodev, &addr); ++ if (ret) ++ goto done; + +- if (ret == -ENOMEDIUM) +- brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM); ++ sdio_writel(sdiodev->func[1], *(u32 *)data, addr, &ret); ++ break; ++ default: ++ WARN(1, "Invalid reg size\n"); ++ ret = -EINVAL; ++ break; ++ } ++ } + ++done: + return ret; + } + + static int brcmf_sdiod_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, + u8 regsz, void *data) + { +- u8 func; +- s32 retry = 0; + int ret; + +- if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM) +- return -ENOMEDIUM; +- + /* + * figure out how to read the register based on address range + * 0x00 ~ 0x7FF: function 0 CCCR and FBR + * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers + * The rest: function 1 silicon backplane core registers ++ * f0 reads must be bytewise + */ +- if ((addr & ~REG_F0_REG_MASK) == 0) +- func = SDIO_FUNC_0; +- else +- func = SDIO_FUNC_1; +- +- do { +- memset(data, 0, regsz); +- +- /* for retry wait for 1 ms till bus get settled down */ +- if (retry) +- usleep_range(1000, 2000); +- +- ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz, +- data, false); +- +- } while (ret != 0 && ret != -ENOMEDIUM && +- retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); +- +- if (ret == -ENOMEDIUM) +- brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM); +- +- return ret; +-} +- +-static int +-brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) +-{ +- int err = 0, i; +- u32 addr; +- +- if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM) +- return -ENOMEDIUM; +- +- addr = (address & SBSDIO_SBWINDOW_MASK) >> 8; +- +- for (i = 0 ; i < 3 && !err ; i++, addr >>= 8) +- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i, +- addr & 0xff, &err); +- +- return err; +-} +- +-static int +-brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr) +-{ +- uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK; +- int err = 0; +- +- if (bar0 != sdiodev->sbwad) { +- err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0); +- if (err) +- return err; ++ if ((addr & ~REG_F0_REG_MASK) == 0) { ++ if (WARN_ON(regsz > 1)) ++ return -EINVAL; ++ *(u8 *)data = sdio_f0_readb(sdiodev->func[0], addr, &ret); ++ } else { ++ switch (regsz) { ++ case 1: ++ *(u8 *)data = sdio_readb(sdiodev->func[1], addr, &ret); ++ break; ++ case 4: ++ ret = brcmf_sdiod_addrprep(sdiodev, &addr); ++ if (ret) ++ goto done; + +- sdiodev->sbwad = bar0; ++ *(u32 *)data = sdio_readl(sdiodev->func[1], addr, &ret); ++ break; ++ default: ++ WARN(1, "Invalid reg size\n"); ++ ret = -EINVAL; ++ break; ++ } + } + +- *addr &= SBSDIO_SB_OFT_ADDR_MASK; +- *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; +- +- return 0; ++done: ++ return ret; + } + + u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) +@@ -439,15 +387,9 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_ + int retval; + + brcmf_dbg(SDIO, "addr:0x%08x\n", addr); +- retval = brcmf_sdiod_addrprep(sdiodev, &addr); +- if (retval) +- goto done; +- + retval = brcmf_sdiod_reg_read(sdiodev, addr, 4, &data); +- + brcmf_dbg(SDIO, "data:0x%08x\n", data); + +-done: + if (ret) + *ret = retval; + +@@ -472,13 +414,8 @@ void brcmf_sdiod_regwl(struct brcmf_sdio + int retval; + + brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data); +- retval = brcmf_sdiod_addrprep(sdiodev, &addr); +- if (retval) +- goto done; +- + retval = brcmf_sdiod_reg_write(sdiodev, addr, 4, &data); + +-done: + if (ret) + *ret = retval; + } +@@ -886,14 +823,12 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev + return bcmerror; + } + +-int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn) ++int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn) + { +- char t_func = (char)fn; + brcmf_dbg(SDIO, "Enter\n"); + + /* issue abort cmd52 command through F0 */ +- brcmf_sdiod_request_data(sdiodev, SDIO_FUNC_0, SDIO_CCCR_ABORT, +- 1, &t_func, true); ++ brcmf_sdiod_reg_write(sdiodev, SDIO_CCCR_ABORT, 1, &fn); + + brcmf_dbg(SDIO, "Exit\n"); + return 0; +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +@@ -339,7 +339,7 @@ int brcmf_sdiod_ramrw(struct brcmf_sdio_ + u8 *data, uint size); + + /* Issue an abort to the specified function */ +-int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn); ++int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn); + void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev); + void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev, + enum brcmf_sdiod_state state); diff --git a/package/kernel/mac80211/patches/311-v4.16-0008-brcmfmac-Fix-asymmetric-IO-functions.patch b/package/kernel/mac80211/patches/311-v4.16-0008-brcmfmac-Fix-asymmetric-IO-functions.patch new file mode 100644 index 000000000..bcf59722b --- /dev/null +++ b/package/kernel/mac80211/patches/311-v4.16-0008-brcmfmac-Fix-asymmetric-IO-functions.patch @@ -0,0 +1,28 @@ +From 3508a056a1f45d95c874fc9af8748bf4229432b6 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Mon, 13 Nov 2017 21:35:45 +0100 +Subject: [PATCH] brcmfmac: Fix asymmetric IO functions. + +Unlikely to be a problem, but brcmf_sdiod_regrl() is +not symmetric with brcmf_sdiod_regrb() in initializing +the data value on stack. Fix that. + +Signed-off-by: Ian Molton +[arend: reword the commit message a bit] +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -383,7 +383,7 @@ u8 brcmf_sdiod_regrb(struct brcmf_sdio_d + + u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) + { +- u32 data = 0; ++ u32 data; + int retval; + + brcmf_dbg(SDIO, "addr:0x%08x\n", addr); diff --git a/package/kernel/mac80211/patches/311-v4.16-0009-brcmfmac-Remove-noisy-debugging.patch b/package/kernel/mac80211/patches/311-v4.16-0009-brcmfmac-Remove-noisy-debugging.patch new file mode 100644 index 000000000..9a570450a --- /dev/null +++ b/package/kernel/mac80211/patches/311-v4.16-0009-brcmfmac-Remove-noisy-debugging.patch @@ -0,0 +1,53 @@ +From 12e3e74e2820e11d91ee44fd3a190cd80d109faa Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Mon, 13 Nov 2017 21:35:46 +0100 +Subject: [PATCH] brcmfmac: Remove noisy debugging. + +If you need debugging this low level, you're doing something wrong. +Remove these noisy debug statements so the code is more readable. + +Signed-off-by: Ian Molton +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 6 ------ + 1 file changed, 6 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -371,9 +371,7 @@ u8 brcmf_sdiod_regrb(struct brcmf_sdio_d + u8 data; + int retval; + +- brcmf_dbg(SDIO, "addr:0x%08x\n", addr); + retval = brcmf_sdiod_reg_read(sdiodev, addr, 1, &data); +- brcmf_dbg(SDIO, "data:0x%02x\n", data); + + if (ret) + *ret = retval; +@@ -386,9 +384,7 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_ + u32 data; + int retval; + +- brcmf_dbg(SDIO, "addr:0x%08x\n", addr); + retval = brcmf_sdiod_reg_read(sdiodev, addr, 4, &data); +- brcmf_dbg(SDIO, "data:0x%08x\n", data); + + if (ret) + *ret = retval; +@@ -401,7 +397,6 @@ void brcmf_sdiod_regwb(struct brcmf_sdio + { + int retval; + +- brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data); + retval = brcmf_sdiod_reg_write(sdiodev, addr, 1, &data); + + if (ret) +@@ -413,7 +408,6 @@ void brcmf_sdiod_regwl(struct brcmf_sdio + { + int retval; + +- brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data); + retval = brcmf_sdiod_reg_write(sdiodev, addr, 4, &data); + + if (ret) diff --git a/package/kernel/mac80211/patches/311-v4.16-0010-brcmfmac-Rename-bcmerror-to-err.patch b/package/kernel/mac80211/patches/311-v4.16-0010-brcmfmac-Rename-bcmerror-to-err.patch new file mode 100644 index 000000000..dd153fe6c --- /dev/null +++ b/package/kernel/mac80211/patches/311-v4.16-0010-brcmfmac-Rename-bcmerror-to-err.patch @@ -0,0 +1,58 @@ +From dd8a2d49e4ed321ab8e7b679499c3a98ccc5ca24 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Mon, 13 Nov 2017 21:35:47 +0100 +Subject: [PATCH] brcmfmac: Rename bcmerror to err + +Trivial cleanup of nasty variable name + +Signed-off-by: Ian Molton +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -746,7 +746,7 @@ int + brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, + u8 *data, uint size) + { +- int bcmerror = 0; ++ int err = 0; + struct sk_buff *pkt; + u32 sdaddr; + uint dsize; +@@ -771,8 +771,8 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev + /* Do the transfer(s) */ + while (size) { + /* Set the backplane window to include the start address */ +- bcmerror = brcmf_sdiod_set_sbaddr_window(sdiodev, address); +- if (bcmerror) ++ err = brcmf_sdiod_set_sbaddr_window(sdiodev, address); ++ if (err) + break; + + brcmf_dbg(SDIO, "%s %d bytes at offset 0x%08x in window 0x%08x\n", +@@ -785,9 +785,9 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev + skb_put(pkt, dsize); + if (write) + memcpy(pkt->data, data, dsize); +- bcmerror = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_1, write, +- sdaddr, pkt); +- if (bcmerror) { ++ err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_1, write, sdaddr, ++ pkt); ++ if (err) { + brcmf_err("membytes transfer failed\n"); + break; + } +@@ -814,7 +814,7 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev + + sdio_release_host(sdiodev->func[1]); + +- return bcmerror; ++ return err; + } + + int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn) diff --git a/package/kernel/mac80211/patches/312-v4.16-0001-brcmfmac-Split-brcmf_sdiod_buffrw-function-up.patch b/package/kernel/mac80211/patches/312-v4.16-0001-brcmfmac-Split-brcmf_sdiod_buffrw-function-up.patch new file mode 100644 index 000000000..c260b9655 --- /dev/null +++ b/package/kernel/mac80211/patches/312-v4.16-0001-brcmfmac-Split-brcmf_sdiod_buffrw-function-up.patch @@ -0,0 +1,143 @@ +From 8f13c87ccc495e30de5f58bbda967f6edd5bec53 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Fri, 8 Dec 2017 13:10:26 +0100 +Subject: [PATCH] brcmfmac: Split brcmf_sdiod_buffrw function up. + +This function needs to be split up into separate read / write variants +for clarity. + +Signed-off-by: Ian Molton +Reviewed-by: Arend van Spriel +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 67 +++++++++++++++------- + 1 file changed, 45 insertions(+), 22 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -414,8 +414,8 @@ void brcmf_sdiod_regwl(struct brcmf_sdio + *ret = retval; + } + +-static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, +- bool write, u32 addr, struct sk_buff *pkt) ++static int brcmf_sdiod_buff_read(struct brcmf_sdio_dev *sdiodev, uint fn, ++ u32 addr, struct sk_buff *pkt) + { + unsigned int req_sz; + int err; +@@ -424,18 +424,36 @@ static int brcmf_sdiod_buffrw(struct brc + req_sz = pkt->len + 3; + req_sz &= (uint)~3; + +- if (write) +- err = sdio_memcpy_toio(sdiodev->func[fn], addr, +- ((u8 *)(pkt->data)), req_sz); +- else if (fn == 1) +- err = sdio_memcpy_fromio(sdiodev->func[fn], ((u8 *)(pkt->data)), +- addr, req_sz); ++ if (fn == 1) ++ err = sdio_memcpy_fromio(sdiodev->func[fn], ++ ((u8 *)(pkt->data)), addr, req_sz); + else + /* function 2 read is FIFO operation */ +- err = sdio_readsb(sdiodev->func[fn], ((u8 *)(pkt->data)), addr, +- req_sz); ++ err = sdio_readsb(sdiodev->func[fn], ++ ((u8 *)(pkt->data)), addr, req_sz); ++ ++ if (err == -ENOMEDIUM) ++ brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM); ++ ++ return err; ++} ++ ++static int brcmf_sdiod_buff_write(struct brcmf_sdio_dev *sdiodev, uint fn, ++ u32 addr, struct sk_buff *pkt) ++{ ++ unsigned int req_sz; ++ int err; ++ ++ /* Single skb use the standard mmc interface */ ++ req_sz = pkt->len + 3; ++ req_sz &= (uint)~3; ++ ++ err = sdio_memcpy_toio(sdiodev->func[fn], addr, ++ ((u8 *)(pkt->data)), req_sz); ++ + if (err == -ENOMEDIUM) + brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM); ++ + return err; + } + +@@ -643,7 +661,7 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd + if (err) + goto done; + +- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr, pkt); ++ err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr, pkt); + + done: + return err; +@@ -665,14 +683,14 @@ int brcmf_sdiod_recv_chain(struct brcmf_ + goto done; + + if (pktq->qlen == 1) +- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr, +- pktq->next); ++ err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr, ++ pktq->next); + else if (!sdiodev->sg_support) { + glom_skb = brcmu_pkt_buf_get_skb(totlen); + if (!glom_skb) + return -ENOMEM; +- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr, +- glom_skb); ++ err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr, ++ glom_skb); + if (err) + goto done; + +@@ -707,8 +725,7 @@ int brcmf_sdiod_send_buf(struct brcmf_sd + err = brcmf_sdiod_addrprep(sdiodev, &addr); + + if (!err) +- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, true, addr, +- mypkt); ++ err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2, addr, mypkt); + + brcmu_pkt_buf_free_skb(mypkt); + return err; +@@ -730,8 +747,8 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd + + if (pktq->qlen == 1 || !sdiodev->sg_support) + skb_queue_walk(pktq, skb) { +- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, true, +- addr, skb); ++ err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2, ++ addr, skb); + if (err) + break; + } +@@ -783,10 +800,16 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev + sdaddr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + + skb_put(pkt, dsize); +- if (write) ++ ++ if (write) { + memcpy(pkt->data, data, dsize); +- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_1, write, sdaddr, +- pkt); ++ err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_1, ++ sdaddr, pkt); ++ } else { ++ err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_1, ++ sdaddr, pkt); ++ } ++ + if (err) { + brcmf_err("membytes transfer failed\n"); + break; diff --git a/package/kernel/mac80211/patches/312-v4.16-0002-brcmfmac-whitespace-fixes-in-brcmf_sdiod_send_buf.patch b/package/kernel/mac80211/patches/312-v4.16-0002-brcmfmac-whitespace-fixes-in-brcmf_sdiod_send_buf.patch new file mode 100644 index 000000000..088a6169f --- /dev/null +++ b/package/kernel/mac80211/patches/312-v4.16-0002-brcmfmac-whitespace-fixes-in-brcmf_sdiod_send_buf.patch @@ -0,0 +1,34 @@ +From 6e24dd012bfda479d0046f7995058f167e1923bc Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Fri, 8 Dec 2017 13:10:27 +0100 +Subject: [PATCH] brcmfmac: whitespace fixes in brcmf_sdiod_send_buf() + +Signed-off-by: Ian Molton +Reviewed-by: Arend van Spriel +[arend: mention function in patch subject] +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -714,6 +714,7 @@ int brcmf_sdiod_send_buf(struct brcmf_sd + int err; + + mypkt = brcmu_pkt_buf_get_skb(nbytes); ++ + if (!mypkt) { + brcmf_err("brcmu_pkt_buf_get_skb failed: len %d\n", + nbytes); +@@ -728,8 +729,8 @@ int brcmf_sdiod_send_buf(struct brcmf_sd + err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2, addr, mypkt); + + brcmu_pkt_buf_free_skb(mypkt); +- return err; + ++ return err; + } + + int brcmf_sdiod_send_pkt(struct brcmf_sdio_dev *sdiodev, diff --git a/package/kernel/mac80211/patches/312-v4.16-0003-brcmfmac-Clarify-if-using-braces.patch b/package/kernel/mac80211/patches/312-v4.16-0003-brcmfmac-Clarify-if-using-braces.patch new file mode 100644 index 000000000..a44155b61 --- /dev/null +++ b/package/kernel/mac80211/patches/312-v4.16-0003-brcmfmac-Clarify-if-using-braces.patch @@ -0,0 +1,36 @@ +From a7323378dcf1f10a98f47b744e6f65e6fd671d84 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Fri, 8 Dec 2017 13:10:28 +0100 +Subject: [PATCH] brcmfmac: Clarify if using braces. + +Whilst this if () statement is technically correct, it lacks clarity. + +Signed-off-by: Ian Molton +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -746,16 +746,17 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd + if (err) + return err; + +- if (pktq->qlen == 1 || !sdiodev->sg_support) ++ if (pktq->qlen == 1 || !sdiodev->sg_support) { + skb_queue_walk(pktq, skb) { + err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2, + addr, skb); + if (err) + break; + } +- else ++ } else { + err = brcmf_sdiod_sglist_rw(sdiodev, SDIO_FUNC_2, true, addr, + pktq); ++ } + + return err; + } diff --git a/package/kernel/mac80211/patches/312-v4.16-0004-brcmfmac-Rename-replace-old-IO-functions-with-simple.patch b/package/kernel/mac80211/patches/312-v4.16-0004-brcmfmac-Rename-replace-old-IO-functions-with-simple.patch new file mode 100644 index 000000000..7aa3de929 --- /dev/null +++ b/package/kernel/mac80211/patches/312-v4.16-0004-brcmfmac-Rename-replace-old-IO-functions-with-simple.patch @@ -0,0 +1,831 @@ +From 71bd508d7ded8c504ef05d1b4befecfe25e54cb1 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Fri, 8 Dec 2017 13:10:29 +0100 +Subject: [PATCH] brcmfmac: Rename / replace old IO functions with simpler + ones. + +Primarily this patch removes: + +brcmf_sdiod_f0_writeb() +brcmf_sdiod_reg_write() +brcmf_sdiod_reg_read() + +Since we no longer use the quirky method of deciding which function to +address via the address being accessed, take the opportunity to rename +some IO functions more in line with common kernel code. We also convert +those that map directly to sdio_{read,write}*() to macros. + +Signed-off-by: Ian Molton +Reviewed-by: Arend van Spriel +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 169 +++---------------- + .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 186 ++++++++++----------- + .../wireless/broadcom/brcm80211/brcmfmac/sdio.h | 28 +++- + 3 files changed, 138 insertions(+), 245 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -137,27 +137,27 @@ int brcmf_sdiod_intr_register(struct brc + if (sdiodev->bus_if->chip == BRCM_CC_43362_CHIP_ID) { + /* assign GPIO to SDIO core */ + addr = CORE_CC_REG(SI_ENUM_BASE, gpiocontrol); +- gpiocontrol = brcmf_sdiod_regrl(sdiodev, addr, &ret); ++ gpiocontrol = brcmf_sdiod_readl(sdiodev, addr, &ret); + gpiocontrol |= 0x2; +- brcmf_sdiod_regwl(sdiodev, addr, gpiocontrol, &ret); ++ brcmf_sdiod_writel(sdiodev, addr, gpiocontrol, &ret); + +- brcmf_sdiod_regwb(sdiodev, SBSDIO_GPIO_SELECT, 0xf, +- &ret); +- brcmf_sdiod_regwb(sdiodev, SBSDIO_GPIO_OUT, 0, &ret); +- brcmf_sdiod_regwb(sdiodev, SBSDIO_GPIO_EN, 0x2, &ret); ++ brcmf_sdiod_writeb(sdiodev, SBSDIO_GPIO_SELECT, ++ 0xf, &ret); ++ brcmf_sdiod_writeb(sdiodev, SBSDIO_GPIO_OUT, 0, &ret); ++ brcmf_sdiod_writeb(sdiodev, SBSDIO_GPIO_EN, 0x2, &ret); + } + + /* must configure SDIO_CCCR_IENx to enable irq */ +- data = brcmf_sdiod_regrb(sdiodev, SDIO_CCCR_IENx, &ret); ++ data = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_IENx, &ret); + data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; +- brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret); ++ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, data, &ret); + + /* redirect, configure and enable io for interrupt signal */ + data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; + if (pdata->oob_irq_flags & IRQF_TRIGGER_HIGH) + data |= SDIO_SEPINT_ACT_HI; +- brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); +- ++ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_SEPINT, ++ data, &ret); + sdio_release_host(sdiodev->func[1]); + } else { + brcmf_dbg(SDIO, "Entering\n"); +@@ -183,8 +183,8 @@ void brcmf_sdiod_intr_unregister(struct + + pdata = &sdiodev->settings->bus.sdio; + sdio_claim_host(sdiodev->func[1]); +- brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL); +- brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL); ++ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL); ++ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, 0, NULL); + sdio_release_host(sdiodev->func[1]); + + sdiodev->oob_irq_requested = false; +@@ -242,8 +242,8 @@ static int brcmf_sdiod_set_sbaddr_window + addr = (address & SBSDIO_SBWINDOW_MASK) >> 8; + + for (i = 0 ; i < 3 && !err ; i++, addr >>= 8) +- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i, +- addr & 0xff, &err); ++ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i, ++ addr & 0xff, &err); + + return err; + } +@@ -267,124 +267,15 @@ static int brcmf_sdiod_addrprep(struct b + return 0; + } + +-static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, u8 byte, +- uint regaddr) +-{ +- int err_ret; +- +- /* +- * Can only directly write to some F0 registers. +- * Handle CCCR_IENx and CCCR_ABORT command +- * as a special case. +- */ +- if ((regaddr == SDIO_CCCR_ABORT) || +- (regaddr == SDIO_CCCR_IENx)) +- sdio_writeb(func, byte, regaddr, &err_ret); +- else +- sdio_f0_writeb(func, byte, regaddr, &err_ret); +- +- return err_ret; +-} +- +-static int brcmf_sdiod_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, +- u8 regsz, void *data) +-{ +- int ret; +- +- /* +- * figure out how to read the register based on address range +- * 0x00 ~ 0x7FF: function 0 CCCR and FBR +- * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers +- * The rest: function 1 silicon backplane core registers +- * f0 writes must be bytewise +- */ +- +- if ((addr & ~REG_F0_REG_MASK) == 0) { +- if (WARN_ON(regsz > 1)) +- return -EINVAL; +- ret = brcmf_sdiod_f0_writeb(sdiodev->func[0], +- *(u8 *)data, addr); +- } else { +- switch (regsz) { +- case 1: +- sdio_writeb(sdiodev->func[1], *(u8 *)data, addr, &ret); +- break; +- case 4: +- ret = brcmf_sdiod_addrprep(sdiodev, &addr); +- if (ret) +- goto done; +- +- sdio_writel(sdiodev->func[1], *(u32 *)data, addr, &ret); +- break; +- default: +- WARN(1, "Invalid reg size\n"); +- ret = -EINVAL; +- break; +- } +- } +- +-done: +- return ret; +-} +- +-static int brcmf_sdiod_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, +- u8 regsz, void *data) +-{ +- int ret; +- +- /* +- * figure out how to read the register based on address range +- * 0x00 ~ 0x7FF: function 0 CCCR and FBR +- * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers +- * The rest: function 1 silicon backplane core registers +- * f0 reads must be bytewise +- */ +- if ((addr & ~REG_F0_REG_MASK) == 0) { +- if (WARN_ON(regsz > 1)) +- return -EINVAL; +- *(u8 *)data = sdio_f0_readb(sdiodev->func[0], addr, &ret); +- } else { +- switch (regsz) { +- case 1: +- *(u8 *)data = sdio_readb(sdiodev->func[1], addr, &ret); +- break; +- case 4: +- ret = brcmf_sdiod_addrprep(sdiodev, &addr); +- if (ret) +- goto done; +- +- *(u32 *)data = sdio_readl(sdiodev->func[1], addr, &ret); +- break; +- default: +- WARN(1, "Invalid reg size\n"); +- ret = -EINVAL; +- break; +- } +- } +- +-done: +- return ret; +-} +- +-u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) ++u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) + { +- u8 data; ++ u32 data = 0; + int retval; + +- retval = brcmf_sdiod_reg_read(sdiodev, addr, 1, &data); ++ retval = brcmf_sdiod_addrprep(sdiodev, &addr); + +- if (ret) +- *ret = retval; +- +- return data; +-} +- +-u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) +-{ +- u32 data; +- int retval; +- +- retval = brcmf_sdiod_reg_read(sdiodev, addr, 4, &data); ++ if (!retval) ++ data = sdio_readl(sdiodev->func[1], addr, &retval); + + if (ret) + *ret = retval; +@@ -392,23 +283,15 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_ + return data; + } + +-void brcmf_sdiod_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, +- u8 data, int *ret) ++void brcmf_sdiod_writel(struct brcmf_sdio_dev *sdiodev, u32 addr, ++ u32 data, int *ret) + { + int retval; + +- retval = brcmf_sdiod_reg_write(sdiodev, addr, 1, &data); +- +- if (ret) +- *ret = retval; +-} +- +-void brcmf_sdiod_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, +- u32 data, int *ret) +-{ +- int retval; ++ retval = brcmf_sdiod_addrprep(sdiodev, &addr); + +- retval = brcmf_sdiod_reg_write(sdiodev, addr, 4, &data); ++ if (!retval) ++ sdio_writel(sdiodev->func[1], data, addr, &retval); + + if (ret) + *ret = retval; +@@ -846,8 +729,8 @@ int brcmf_sdiod_abort(struct brcmf_sdio_ + { + brcmf_dbg(SDIO, "Enter\n"); + +- /* issue abort cmd52 command through F0 */ +- brcmf_sdiod_reg_write(sdiodev, SDIO_CCCR_ABORT, 1, &fn); ++ /* Issue abort cmd52 command through F0 */ ++ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_ABORT, fn, NULL); + + brcmf_dbg(SDIO, "Exit\n"); + return 0; +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -669,7 +669,7 @@ static int r_sdreg32(struct brcmf_sdio * + int ret; + + core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV); +- *regvar = brcmf_sdiod_regrl(bus->sdiodev, core->base + offset, &ret); ++ *regvar = brcmf_sdiod_readl(bus->sdiodev, core->base + offset, &ret); + + return ret; + } +@@ -680,7 +680,7 @@ static int w_sdreg32(struct brcmf_sdio * + int ret; + + core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV); +- brcmf_sdiod_regwl(bus->sdiodev, core->base + reg_offset, regval, &ret); ++ brcmf_sdiod_writel(bus->sdiodev, core->base + reg_offset, regval, &ret); + + return ret; + } +@@ -697,8 +697,7 @@ brcmf_sdio_kso_control(struct brcmf_sdio + + wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); + /* 1st KSO write goes to AOS wake up core if device is asleep */ +- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, +- wr_val, &err); ++ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err); + + if (on) { + /* device WAKEUP through KSO: +@@ -724,7 +723,7 @@ brcmf_sdio_kso_control(struct brcmf_sdio + * just one write attempt may fail, + * read it back until it matches written value + */ +- rd_val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, ++ rd_val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, + &err); + if (!err) { + if ((rd_val & bmask) == cmp_val) +@@ -734,9 +733,11 @@ brcmf_sdio_kso_control(struct brcmf_sdio + /* bail out upon subsequent access errors */ + if (err && (err_cnt++ > BRCMF_SDIO_MAX_ACCESS_ERRORS)) + break; ++ + udelay(KSO_WAIT_US); +- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, +- wr_val, &err); ++ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, wr_val, ++ &err); ++ + } while (try_cnt++ < MAX_KSO_ATTEMPTS); + + if (try_cnt > 2) +@@ -772,15 +773,15 @@ static int brcmf_sdio_htclk(struct brcmf + clkreq = + bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ; + +- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, +- clkreq, &err); ++ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, ++ clkreq, &err); + if (err) { + brcmf_err("HT Avail request error: %d\n", err); + return -EBADE; + } + + /* Check current status */ +- clkctl = brcmf_sdiod_regrb(bus->sdiodev, ++ clkctl = brcmf_sdiod_readb(bus->sdiodev, + SBSDIO_FUNC1_CHIPCLKCSR, &err); + if (err) { + brcmf_err("HT Avail read error: %d\n", err); +@@ -790,35 +791,34 @@ static int brcmf_sdio_htclk(struct brcmf + /* Go to pending and await interrupt if appropriate */ + if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) { + /* Allow only clock-available interrupt */ +- devctl = brcmf_sdiod_regrb(bus->sdiodev, ++ devctl = brcmf_sdiod_readb(bus->sdiodev, + SBSDIO_DEVICE_CTL, &err); + if (err) { +- brcmf_err("Devctl error setting CA: %d\n", +- err); ++ brcmf_err("Devctl error setting CA: %d\n", err); + return -EBADE; + } + + devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; +- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, +- devctl, &err); ++ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_DEVICE_CTL, ++ devctl, &err); + brcmf_dbg(SDIO, "CLKCTL: set PENDING\n"); + bus->clkstate = CLK_PENDING; + + return 0; + } else if (bus->clkstate == CLK_PENDING) { + /* Cancel CA-only interrupt filter */ +- devctl = brcmf_sdiod_regrb(bus->sdiodev, ++ devctl = brcmf_sdiod_readb(bus->sdiodev, + SBSDIO_DEVICE_CTL, &err); + devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; +- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, +- devctl, &err); ++ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_DEVICE_CTL, ++ devctl, &err); + } + + /* Otherwise, wait here (polling) for HT Avail */ + timeout = jiffies + + msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000); + while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { +- clkctl = brcmf_sdiod_regrb(bus->sdiodev, ++ clkctl = brcmf_sdiod_readb(bus->sdiodev, + SBSDIO_FUNC1_CHIPCLKCSR, + &err); + if (time_after(jiffies, timeout)) +@@ -852,16 +852,16 @@ static int brcmf_sdio_htclk(struct brcmf + + if (bus->clkstate == CLK_PENDING) { + /* Cancel CA-only interrupt filter */ +- devctl = brcmf_sdiod_regrb(bus->sdiodev, ++ devctl = brcmf_sdiod_readb(bus->sdiodev, + SBSDIO_DEVICE_CTL, &err); + devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; +- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, +- devctl, &err); ++ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_DEVICE_CTL, ++ devctl, &err); + } + + bus->clkstate = CLK_SDONLY; +- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, +- clkreq, &err); ++ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, ++ clkreq, &err); + brcmf_dbg(SDIO, "CLKCTL: turned OFF\n"); + if (err) { + brcmf_err("Failed access turning clock off: %d\n", +@@ -951,14 +951,14 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio * + + /* Going to sleep */ + if (sleep) { +- clkcsr = brcmf_sdiod_regrb(bus->sdiodev, ++ clkcsr = brcmf_sdiod_readb(bus->sdiodev, + SBSDIO_FUNC1_CHIPCLKCSR, + &err); + if ((clkcsr & SBSDIO_CSR_MASK) == 0) { + brcmf_dbg(SDIO, "no clock, set ALP\n"); +- brcmf_sdiod_regwb(bus->sdiodev, +- SBSDIO_FUNC1_CHIPCLKCSR, +- SBSDIO_ALP_AVAIL_REQ, &err); ++ brcmf_sdiod_writeb(bus->sdiodev, ++ SBSDIO_FUNC1_CHIPCLKCSR, ++ SBSDIO_ALP_AVAIL_REQ, &err); + } + err = brcmf_sdio_kso_control(bus, false); + } else { +@@ -1178,16 +1178,16 @@ static void brcmf_sdio_rxfail(struct brc + if (abort) + brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2); + +- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, +- SFC_RF_TERM, &err); ++ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, ++ &err); + bus->sdcnt.f1regdata++; + + /* Wait until the packet has been flushed (device/FIFO stable) */ + for (lastrbc = retries = 0xffff; retries > 0; retries--) { +- hi = brcmf_sdiod_regrb(bus->sdiodev, +- SBSDIO_FUNC1_RFRAMEBCHI, &err); +- lo = brcmf_sdiod_regrb(bus->sdiodev, +- SBSDIO_FUNC1_RFRAMEBCLO, &err); ++ hi = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_RFRAMEBCHI, ++ &err); ++ lo = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_RFRAMEBCLO, ++ &err); + bus->sdcnt.f1regdata += 2; + + if ((hi == 0) && (lo == 0)) +@@ -1229,12 +1229,12 @@ static void brcmf_sdio_txfail(struct brc + bus->sdcnt.tx_sderrs++; + + brcmf_sdiod_abort(sdiodev, SDIO_FUNC_2); +- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL); ++ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL); + bus->sdcnt.f1regdata++; + + for (i = 0; i < 3; i++) { +- hi = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_WFRAMEBCHI, NULL); +- lo = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_WFRAMEBCLO, NULL); ++ hi = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_WFRAMEBCHI, NULL); ++ lo = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_WFRAMEBCLO, NULL); + bus->sdcnt.f1regdata += 2; + if ((hi == 0) && (lo == 0)) + break; +@@ -2446,11 +2446,11 @@ static void brcmf_sdio_bus_stop(struct d + bus->hostintmask = 0; + + /* Force backplane clocks to assure F2 interrupt propagates */ +- saveclk = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, ++ saveclk = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, + &err); + if (!err) +- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, +- (saveclk | SBSDIO_FORCE_HT), &err); ++ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, ++ (saveclk | SBSDIO_FORCE_HT), &err); + if (err) + brcmf_err("Failed to force clock for F2: err %d\n", + err); +@@ -2509,7 +2509,7 @@ static int brcmf_sdio_intr_rstatus(struc + buscore = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV); + addr = buscore->base + offsetof(struct sdpcmd_regs, intstatus); + +- val = brcmf_sdiod_regrl(bus->sdiodev, addr, &ret); ++ val = brcmf_sdiod_readl(bus->sdiodev, addr, &ret); + bus->sdcnt.f1regdata++; + if (ret != 0) + return ret; +@@ -2519,7 +2519,7 @@ static int brcmf_sdio_intr_rstatus(struc + + /* Clear interrupts */ + if (val) { +- brcmf_sdiod_regwl(bus->sdiodev, addr, val, &ret); ++ brcmf_sdiod_writel(bus->sdiodev, addr, val, &ret); + bus->sdcnt.f1regdata++; + atomic_or(val, &bus->intstatus); + } +@@ -2545,23 +2545,23 @@ static void brcmf_sdio_dpc(struct brcmf_ + + #ifdef DEBUG + /* Check for inconsistent device control */ +- devctl = brcmf_sdiod_regrb(bus->sdiodev, +- SBSDIO_DEVICE_CTL, &err); ++ devctl = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_DEVICE_CTL, ++ &err); + #endif /* DEBUG */ + + /* Read CSR, if clock on switch to AVAIL, else ignore */ +- clkctl = brcmf_sdiod_regrb(bus->sdiodev, ++ clkctl = brcmf_sdiod_readb(bus->sdiodev, + SBSDIO_FUNC1_CHIPCLKCSR, &err); + + brcmf_dbg(SDIO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", + devctl, clkctl); + + if (SBSDIO_HTAV(clkctl)) { +- devctl = brcmf_sdiod_regrb(bus->sdiodev, ++ devctl = brcmf_sdiod_readb(bus->sdiodev, + SBSDIO_DEVICE_CTL, &err); + devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; +- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, +- devctl, &err); ++ brcmf_sdiod_writeb(bus->sdiodev, ++ SBSDIO_DEVICE_CTL, devctl, &err); + bus->clkstate = CLK_AVAIL; + } + } +@@ -3347,31 +3347,31 @@ static void brcmf_sdio_sr_init(struct br + + brcmf_dbg(TRACE, "Enter\n"); + +- val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, &err); ++ val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, &err); + if (err) { + brcmf_err("error reading SBSDIO_FUNC1_WAKEUPCTRL\n"); + return; + } + + val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT; +- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, val, &err); ++ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, val, &err); + if (err) { + brcmf_err("error writing SBSDIO_FUNC1_WAKEUPCTRL\n"); + return; + } + + /* Add CMD14 Support */ +- brcmf_sdiod_regwb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP, +- (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT | +- SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT), +- &err); ++ brcmf_sdiod_func0_wb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP, ++ (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT | ++ SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT), ++ &err); + if (err) { + brcmf_err("error writing SDIO_CCCR_BRCM_CARDCAP\n"); + return; + } + +- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, +- SBSDIO_FORCE_HT, &err); ++ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, ++ SBSDIO_FORCE_HT, &err); + if (err) { + brcmf_err("error writing SBSDIO_FUNC1_CHIPCLKCSR\n"); + return; +@@ -3394,7 +3394,7 @@ static int brcmf_sdio_kso_init(struct br + if (brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV)->rev < 12) + return 0; + +- val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, &err); ++ val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, &err); + if (err) { + brcmf_err("error reading SBSDIO_FUNC1_SLEEPCSR\n"); + return err; +@@ -3403,8 +3403,8 @@ static int brcmf_sdio_kso_init(struct br + if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) { + val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN << + SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); +- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, +- val, &err); ++ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, ++ val, &err); + if (err) { + brcmf_err("error writing SBSDIO_FUNC1_SLEEPCSR\n"); + return err; +@@ -3565,9 +3565,9 @@ static void brcmf_sdio_bus_watchdog(stru + u8 devpend; + + sdio_claim_host(bus->sdiodev->func[1]); +- devpend = brcmf_sdiod_regrb(bus->sdiodev, +- SDIO_CCCR_INTx, +- NULL); ++ devpend = brcmf_sdiod_func0_rb(bus->sdiodev, ++ SDIO_CCCR_INTx, ++ NULL); + sdio_release_host(bus->sdiodev->func[1]); + intstatus = devpend & (INTR_STATUS_FUNC1 | + INTR_STATUS_FUNC2); +@@ -3705,12 +3705,12 @@ brcmf_sdio_drivestrengthinit(struct brcm + } + } + addr = CORE_CC_REG(pmu->base, chipcontrol_addr); +- brcmf_sdiod_regwl(sdiodev, addr, 1, NULL); +- cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL); ++ brcmf_sdiod_writel(sdiodev, addr, 1, NULL); ++ cc_data_temp = brcmf_sdiod_readl(sdiodev, addr, NULL); + cc_data_temp &= ~str_mask; + drivestrength_sel <<= str_shift; + cc_data_temp |= drivestrength_sel; +- brcmf_sdiod_regwl(sdiodev, addr, cc_data_temp, NULL); ++ brcmf_sdiod_writel(sdiodev, addr, cc_data_temp, NULL); + + brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n", + str_tab[i].strength, drivestrength, cc_data_temp); +@@ -3725,7 +3725,7 @@ static int brcmf_sdio_buscoreprep(void * + + /* Try forcing SDIO core to do ALPAvail request only */ + clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; +- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); ++ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); + if (err) { + brcmf_err("error writing for HT off\n"); + return err; +@@ -3733,8 +3733,7 @@ static int brcmf_sdio_buscoreprep(void * + + /* If register supported, wait for ALPAvail and then force ALP */ + /* This may take up to 15 milliseconds */ +- clkval = brcmf_sdiod_regrb(sdiodev, +- SBSDIO_FUNC1_CHIPCLKCSR, NULL); ++ clkval = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, NULL); + + if ((clkval & ~SBSDIO_AVBITS) != clkset) { + brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n", +@@ -3742,10 +3741,11 @@ static int brcmf_sdio_buscoreprep(void * + return -EACCES; + } + +- SPINWAIT(((clkval = brcmf_sdiod_regrb(sdiodev, +- SBSDIO_FUNC1_CHIPCLKCSR, NULL)), +- !SBSDIO_ALPAV(clkval)), +- PMU_MAX_TRANSITION_DLY); ++ SPINWAIT(((clkval = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, ++ NULL)), ++ !SBSDIO_ALPAV(clkval)), ++ PMU_MAX_TRANSITION_DLY); ++ + if (!SBSDIO_ALPAV(clkval)) { + brcmf_err("timeout on ALPAV wait, clkval 0x%02x\n", + clkval); +@@ -3753,11 +3753,11 @@ static int brcmf_sdio_buscoreprep(void * + } + + clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP; +- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); ++ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); + udelay(65); + + /* Also, disable the extra SDIO pull-ups */ +- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); ++ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); + + return 0; + } +@@ -3772,7 +3772,7 @@ static void brcmf_sdio_buscore_activate( + /* clear all interrupts */ + core = brcmf_chip_get_core(chip, BCMA_CORE_SDIO_DEV); + reg_addr = core->base + offsetof(struct sdpcmd_regs, intstatus); +- brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL); ++ brcmf_sdiod_writel(sdiodev, reg_addr, 0xFFFFFFFF, NULL); + + if (rstvec) + /* Write reset vector to address 0 */ +@@ -3785,7 +3785,7 @@ static u32 brcmf_sdio_buscore_read32(voi + struct brcmf_sdio_dev *sdiodev = ctx; + u32 val, rev; + +- val = brcmf_sdiod_regrl(sdiodev, addr, NULL); ++ val = brcmf_sdiod_readl(sdiodev, addr, NULL); + if ((sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 || + sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4339) && + addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) { +@@ -3802,7 +3802,7 @@ static void brcmf_sdio_buscore_write32(v + { + struct brcmf_sdio_dev *sdiodev = ctx; + +- brcmf_sdiod_regwl(sdiodev, addr, val, NULL); ++ brcmf_sdiod_writel(sdiodev, addr, val, NULL); + } + + static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = { +@@ -3826,18 +3826,18 @@ brcmf_sdio_probe_attach(struct brcmf_sdi + sdio_claim_host(sdiodev->func[1]); + + pr_debug("F1 signature read @0x18000000=0x%4x\n", +- brcmf_sdiod_regrl(sdiodev, SI_ENUM_BASE, NULL)); ++ brcmf_sdiod_readl(sdiodev, SI_ENUM_BASE, NULL)); + + /* + * Force PLL off until brcmf_chip_attach() + * programs PLL control regs + */ + +- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, +- BRCMF_INIT_CLKCTL1, &err); ++ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, BRCMF_INIT_CLKCTL1, ++ &err); + if (!err) +- clkctl = brcmf_sdiod_regrb(sdiodev, +- SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ clkctl = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, ++ &err); + + if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) { + brcmf_err("ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n", +@@ -3897,25 +3897,25 @@ brcmf_sdio_probe_attach(struct brcmf_sdi + brcmf_sdio_drivestrengthinit(sdiodev, bus->ci, drivestrength); + + /* Set card control so an SDIO card reset does a WLAN backplane reset */ +- reg_val = brcmf_sdiod_regrb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, &err); ++ reg_val = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, &err); + if (err) + goto fail; + + reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET; + +- brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err); ++ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err); + if (err) + goto fail; + + /* set PMUControl so a backplane reset does PMU state reload */ + reg_addr = CORE_CC_REG(brcmf_chip_get_pmu(bus->ci)->base, pmucontrol); +- reg_val = brcmf_sdiod_regrl(sdiodev, reg_addr, &err); ++ reg_val = brcmf_sdiod_readl(sdiodev, reg_addr, &err); + if (err) + goto fail; + + reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT); + +- brcmf_sdiod_regwl(sdiodev, reg_addr, reg_val, &err); ++ brcmf_sdiod_writel(sdiodev, reg_addr, reg_val, &err); + if (err) + goto fail; + +@@ -4055,10 +4055,10 @@ static void brcmf_sdio_firmware_callback + goto release; + + /* Force clocks on backplane to be sure F2 interrupt propagates */ +- saveclk = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ saveclk = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, &err); + if (!err) { +- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, +- (saveclk | SBSDIO_FORCE_HT), &err); ++ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, ++ (saveclk | SBSDIO_FORCE_HT), &err); + } + if (err) { + brcmf_err("Failed to force clock for F2: err %d\n", err); +@@ -4080,7 +4080,7 @@ static void brcmf_sdio_firmware_callback + w_sdreg32(bus, bus->hostintmask, + offsetof(struct sdpcmd_regs, hostintmask)); + +- brcmf_sdiod_regwb(sdiodev, SBSDIO_WATERMARK, 8, &err); ++ brcmf_sdiod_writeb(sdiodev, SBSDIO_WATERMARK, 8, &err); + } else { + /* Disable F2 again */ + sdio_disable_func(sdiodev->func[SDIO_FUNC_2]); +@@ -4091,8 +4091,8 @@ static void brcmf_sdio_firmware_callback + brcmf_sdio_sr_init(bus); + } else { + /* Restore previous clock setting */ +- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, +- saveclk, &err); ++ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, ++ saveclk, &err); + } + + if (err == 0) { +@@ -4225,7 +4225,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru + bus->rxflow = false; + + /* Done with backplane-dependent accesses, can drop clock... */ +- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); ++ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); + + sdio_release_host(bus->sdiodev->func[1]); + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +@@ -50,6 +50,7 @@ + #define SBSDIO_NUM_FUNCTION 3 + + /* function 0 vendor specific CCCR registers */ ++ + #define SDIO_CCCR_BRCM_CARDCAP 0xf0 + #define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02 + #define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04 +@@ -131,8 +132,6 @@ + /* with b15, maps to 32-bit SB access */ + #define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 + +-/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */ +- + /* Address bits from SBADDR regs */ + #define SBSDIO_SBWINDOW_MASK 0xffff8000 + +@@ -293,13 +292,24 @@ struct sdpcmd_regs { + int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev); + void brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev); + +-/* sdio device register access interface */ +-u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); +-u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); +-void brcmf_sdiod_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, u8 data, +- int *ret); +-void brcmf_sdiod_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data, +- int *ret); ++/* SDIO device register access interface */ ++/* Accessors for SDIO Function 0 */ ++#define brcmf_sdiod_func0_rb(sdiodev, addr, r) \ ++ sdio_readb((sdiodev)->func[0], (addr), (r)) ++ ++#define brcmf_sdiod_func0_wb(sdiodev, addr, v, ret) \ ++ sdio_writeb((sdiodev)->func[0], (v), (addr), (ret)) ++ ++/* Accessors for SDIO Function 1 */ ++#define brcmf_sdiod_readb(sdiodev, addr, r) \ ++ sdio_readb((sdiodev)->func[1], (addr), (r)) ++ ++#define brcmf_sdiod_writeb(sdiodev, addr, v, ret) \ ++ sdio_writeb((sdiodev)->func[1], (v), (addr), (ret)) ++ ++u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); ++void brcmf_sdiod_writel(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data, ++ int *ret); + + /* Buffer transfer to/from device (client) core via cmd53. + * fn: function number diff --git a/package/kernel/mac80211/patches/312-v4.16-0005-brcmfmac-Tidy-register-definitions-a-little.patch b/package/kernel/mac80211/patches/312-v4.16-0005-brcmfmac-Tidy-register-definitions-a-little.patch new file mode 100644 index 000000000..e77d601a8 --- /dev/null +++ b/package/kernel/mac80211/patches/312-v4.16-0005-brcmfmac-Tidy-register-definitions-a-little.patch @@ -0,0 +1,59 @@ +From eeef8a5da781e11746347b3cd9f1942be48ebaf0 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Fri, 8 Dec 2017 13:10:30 +0100 +Subject: [PATCH] brcmfmac: Tidy register definitions a little + +Trivial tidy of register definitions. + +Signed-off-by: Ian Molton +Acked-by: Arend van Spriel +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 4 ++-- + .../net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 19 ++++++++++--------- + 2 files changed, 12 insertions(+), 11 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -153,9 +153,9 @@ int brcmf_sdiod_intr_register(struct brc + brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, data, &ret); + + /* redirect, configure and enable io for interrupt signal */ +- data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; ++ data = SDIO_CCCR_BRCM_SEPINT_MASK | SDIO_CCCR_BRCM_SEPINT_OE; + if (pdata->oob_irq_flags & IRQF_TRIGGER_HIGH) +- data |= SDIO_SEPINT_ACT_HI; ++ data |= SDIO_CCCR_BRCM_SEPINT_ACT_HI; + brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_SEPINT, + data, &ret); + sdio_release_host(sdiodev->func[1]); +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +@@ -52,16 +52,17 @@ + /* function 0 vendor specific CCCR registers */ + + #define SDIO_CCCR_BRCM_CARDCAP 0xf0 +-#define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02 +-#define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04 +-#define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC 0x08 +-#define SDIO_CCCR_BRCM_CARDCTRL 0xf1 +-#define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET 0x02 +-#define SDIO_CCCR_BRCM_SEPINT 0xf2 ++#define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT BIT(1) ++#define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT BIT(2) ++#define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC BIT(3) ++ ++#define SDIO_CCCR_BRCM_CARDCTRL 0xf1 ++#define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET BIT(1) + +-#define SDIO_SEPINT_MASK 0x01 +-#define SDIO_SEPINT_OE 0x02 +-#define SDIO_SEPINT_ACT_HI 0x04 ++#define SDIO_CCCR_BRCM_SEPINT 0xf2 ++#define SDIO_CCCR_BRCM_SEPINT_MASK BIT(0) ++#define SDIO_CCCR_BRCM_SEPINT_OE BIT(1) ++#define SDIO_CCCR_BRCM_SEPINT_ACT_HI BIT(2) + + /* function 1 miscellaneous registers */ + diff --git a/package/kernel/mac80211/patches/312-v4.16-0006-brcmfmac-Remove-brcmf_sdiod_addrprep.patch b/package/kernel/mac80211/patches/312-v4.16-0006-brcmfmac-Remove-brcmf_sdiod_addrprep.patch new file mode 100644 index 000000000..44303fa41 --- /dev/null +++ b/package/kernel/mac80211/patches/312-v4.16-0006-brcmfmac-Remove-brcmf_sdiod_addrprep.patch @@ -0,0 +1,190 @@ +From a7c3aa1509e243a09c5b1660c8702d792ca76aed Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Fri, 8 Dec 2017 13:10:31 +0100 +Subject: [PATCH] brcmfmac: Remove brcmf_sdiod_addrprep() + +This function has become trivial enough that it may as well be pushed into +its callers, which has the side-benefit of clarifying what's going on. + +Remove it, and rename brcmf_sdiod_set_sbaddr_window() to +brcmf_sdiod_set_backplane_window() as it's easier to understand. + +Signed-off-by: Ian Molton +Reviewed-by: Arend van Spriel +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 84 ++++++++++++---------- + 1 file changed, 46 insertions(+), 38 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -230,41 +230,25 @@ void brcmf_sdiod_change_state(struct brc + sdiodev->state = state; + } + +-static int brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, +- u32 address) ++static int brcmf_sdiod_set_backplane_window(struct brcmf_sdio_dev *sdiodev, ++ u32 addr) + { ++ u32 v, bar0 = addr & SBSDIO_SBWINDOW_MASK; + int err = 0, i; +- u32 addr; + +- if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM) +- return -ENOMEDIUM; ++ if (bar0 == sdiodev->sbwad) ++ return 0; + +- addr = (address & SBSDIO_SBWINDOW_MASK) >> 8; ++ v = bar0 >> 8; + +- for (i = 0 ; i < 3 && !err ; i++, addr >>= 8) ++ for (i = 0 ; i < 3 && !err ; i++, v >>= 8) + brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i, +- addr & 0xff, &err); +- +- return err; +-} +- +-static int brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr) +-{ +- uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK; +- int err = 0; +- +- if (bar0 != sdiodev->sbwad) { +- err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0); +- if (err) +- return err; ++ v & 0xff, &err); + ++ if (!err) + sdiodev->sbwad = bar0; +- } +- +- *addr &= SBSDIO_SB_OFT_ADDR_MASK; +- *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + +- return 0; ++ return err; + } + + u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) +@@ -272,11 +256,16 @@ u32 brcmf_sdiod_readl(struct brcmf_sdio_ + u32 data = 0; + int retval; + +- retval = brcmf_sdiod_addrprep(sdiodev, &addr); ++ retval = brcmf_sdiod_set_backplane_window(sdiodev, addr); ++ if (retval) ++ goto out; ++ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + +- if (!retval) +- data = sdio_readl(sdiodev->func[1], addr, &retval); ++ data = sdio_readl(sdiodev->func[1], addr, &retval); + ++out: + if (ret) + *ret = retval; + +@@ -288,11 +277,16 @@ void brcmf_sdiod_writel(struct brcmf_sdi + { + int retval; + +- retval = brcmf_sdiod_addrprep(sdiodev, &addr); ++ retval = brcmf_sdiod_set_backplane_window(sdiodev, addr); ++ if (retval) ++ goto out; ++ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + +- if (!retval) +- sdio_writel(sdiodev->func[1], data, addr, &retval); ++ sdio_writel(sdiodev->func[1], data, addr, &retval); + ++out: + if (ret) + *ret = retval; + } +@@ -540,10 +534,13 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd + + brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pkt->len); + +- err = brcmf_sdiod_addrprep(sdiodev, &addr); ++ err = brcmf_sdiod_set_backplane_window(sdiodev, addr); + if (err) + goto done; + ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ + err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr, pkt); + + done: +@@ -561,10 +558,13 @@ int brcmf_sdiod_recv_chain(struct brcmf_ + brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", + addr, pktq->qlen); + +- err = brcmf_sdiod_addrprep(sdiodev, &addr); ++ err = brcmf_sdiod_set_backplane_window(sdiodev, addr); + if (err) + goto done; + ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ + if (pktq->qlen == 1) + err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr, + pktq->next); +@@ -606,7 +606,12 @@ int brcmf_sdiod_send_buf(struct brcmf_sd + + memcpy(mypkt->data, buf, nbytes); + +- err = brcmf_sdiod_addrprep(sdiodev, &addr); ++ err = brcmf_sdiod_set_backplane_window(sdiodev, addr); ++ if (err) ++ return err; ++ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + + if (!err) + err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2, addr, mypkt); +@@ -625,10 +630,13 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd + + brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pktq->qlen); + +- err = brcmf_sdiod_addrprep(sdiodev, &addr); ++ err = brcmf_sdiod_set_backplane_window(sdiodev, addr); + if (err) + return err; + ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ + if (pktq->qlen == 1 || !sdiodev->sg_support) { + skb_queue_walk(pktq, skb) { + err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2, +@@ -673,7 +681,7 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev + /* Do the transfer(s) */ + while (size) { + /* Set the backplane window to include the start address */ +- err = brcmf_sdiod_set_sbaddr_window(sdiodev, address); ++ err = brcmf_sdiod_set_backplane_window(sdiodev, address); + if (err) + break; + +@@ -716,7 +724,7 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev + dev_kfree_skb(pkt); + + /* Return the window to backplane enumeration space for core access */ +- if (brcmf_sdiod_set_sbaddr_window(sdiodev, sdiodev->sbwad)) ++ if (brcmf_sdiod_set_backplane_window(sdiodev, sdiodev->sbwad)) + brcmf_err("FAILED to set window back to 0x%x\n", + sdiodev->sbwad); + diff --git a/package/kernel/mac80211/patches/312-v4.16-0007-brcmfmac-remove-unnecessary-call-to-brcmf_sdiod_set_.patch b/package/kernel/mac80211/patches/312-v4.16-0007-brcmfmac-remove-unnecessary-call-to-brcmf_sdiod_set_.patch new file mode 100644 index 000000000..b9410dd7d --- /dev/null +++ b/package/kernel/mac80211/patches/312-v4.16-0007-brcmfmac-remove-unnecessary-call-to-brcmf_sdiod_set_.patch @@ -0,0 +1,32 @@ +From c900072bd6faff089aa4fb7b19136a2a0fe3baf0 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Fri, 8 Dec 2017 13:10:32 +0100 +Subject: [PATCH] brcmfmac: remove unnecessary call to + brcmf_sdiod_set_backplane_window() + +All functions that might require the window address changing call +brcmf_sdiod_set_backplane_window() prior to access. Thus resetting +the window is not required. + +Signed-off-by: Ian Molton +[arend: corrected the driver prefix in the subject] +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 5 ----- + 1 file changed, 5 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -723,11 +723,6 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev + + dev_kfree_skb(pkt); + +- /* Return the window to backplane enumeration space for core access */ +- if (brcmf_sdiod_set_backplane_window(sdiodev, sdiodev->sbwad)) +- brcmf_err("FAILED to set window back to 0x%x\n", +- sdiodev->sbwad); +- + sdio_release_host(sdiodev->func[1]); + + return err; diff --git a/package/kernel/mac80211/patches/312-v4.16-0008-brcmfmac-Cleanup-offsetof.patch b/package/kernel/mac80211/patches/312-v4.16-0008-brcmfmac-Cleanup-offsetof.patch new file mode 100644 index 000000000..f9e5df550 --- /dev/null +++ b/package/kernel/mac80211/patches/312-v4.16-0008-brcmfmac-Cleanup-offsetof.patch @@ -0,0 +1,134 @@ +From e4c05fc3c0a6c79376f72f17d08014477e962ada Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Fri, 8 Dec 2017 13:10:33 +0100 +Subject: [PATCH] brcmfmac: Cleanup offsetof() + +Create a macro to make the code a bit more readable, whilst we're stuck +with using struct element offsets as register offsets. + +Signed-off-by: Ian Molton +Reviewed-by: Arend van Spriel +[arend: rename macro to SD_REG] +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 35 +++++++++------------- + 1 file changed, 14 insertions(+), 21 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -161,6 +161,8 @@ struct rte_console { + + #define CORE_BUS_REG(base, field) \ + (base + offsetof(struct sdpcmd_regs, field)) ++#define SD_REG(field) \ ++ (offsetof(struct sdpcmd_regs, field)) + + /* SDIO function 1 register CHIPCLKCSR */ + /* Force ALP request to backplane */ +@@ -1087,12 +1089,10 @@ static u32 brcmf_sdio_hostmail(struct br + brcmf_dbg(SDIO, "Enter\n"); + + /* Read mailbox data and ack that we did so */ +- ret = r_sdreg32(bus, &hmb_data, +- offsetof(struct sdpcmd_regs, tohostmailboxdata)); ++ ret = r_sdreg32(bus, &hmb_data, SD_REG(tohostmailboxdata)); + + if (ret == 0) +- w_sdreg32(bus, SMB_INT_ACK, +- offsetof(struct sdpcmd_regs, tosbmailbox)); ++ w_sdreg32(bus, SMB_INT_ACK, SD_REG(tosbmailbox)); + bus->sdcnt.f1regdata += 2; + + /* dongle indicates the firmware has halted/crashed */ +@@ -1207,8 +1207,7 @@ static void brcmf_sdio_rxfail(struct brc + + if (rtx) { + bus->sdcnt.rxrtx++; +- err = w_sdreg32(bus, SMB_NAK, +- offsetof(struct sdpcmd_regs, tosbmailbox)); ++ err = w_sdreg32(bus, SMB_NAK, SD_REG(tosbmailbox)); + + bus->sdcnt.f1regdata++; + if (err == 0) +@@ -2333,9 +2332,7 @@ static uint brcmf_sdio_sendfromq(struct + if (!bus->intr) { + /* Check device status, signal pending interrupt */ + sdio_claim_host(bus->sdiodev->func[1]); +- ret = r_sdreg32(bus, &intstatus, +- offsetof(struct sdpcmd_regs, +- intstatus)); ++ ret = r_sdreg32(bus, &intstatus, SD_REG(intstatus)); + sdio_release_host(bus->sdiodev->func[1]); + bus->sdcnt.f2txdata++; + if (ret != 0) +@@ -2441,7 +2438,7 @@ static void brcmf_sdio_bus_stop(struct d + brcmf_sdio_bus_sleep(bus, false, false); + + /* Disable and clear interrupts at the chip level also */ +- w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask)); ++ w_sdreg32(bus, 0, SD_REG(hostintmask)); + local_hostintmask = bus->hostintmask; + bus->hostintmask = 0; + +@@ -2460,8 +2457,7 @@ static void brcmf_sdio_bus_stop(struct d + sdio_disable_func(sdiodev->func[SDIO_FUNC_2]); + + /* Clear any pending interrupts now that F2 is disabled */ +- w_sdreg32(bus, local_hostintmask, +- offsetof(struct sdpcmd_regs, intstatus)); ++ w_sdreg32(bus, local_hostintmask, SD_REG(intstatus)); + + sdio_release_host(sdiodev->func[1]); + } +@@ -2507,7 +2503,7 @@ static int brcmf_sdio_intr_rstatus(struc + int ret; + + buscore = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV); +- addr = buscore->base + offsetof(struct sdpcmd_regs, intstatus); ++ addr = buscore->base + SD_REG(intstatus); + + val = brcmf_sdiod_readl(bus->sdiodev, addr, &ret); + bus->sdcnt.f1regdata++; +@@ -2584,11 +2580,9 @@ static void brcmf_sdio_dpc(struct brcmf_ + */ + if (intstatus & I_HMB_FC_CHANGE) { + intstatus &= ~I_HMB_FC_CHANGE; +- err = w_sdreg32(bus, I_HMB_FC_CHANGE, +- offsetof(struct sdpcmd_regs, intstatus)); ++ err = w_sdreg32(bus, I_HMB_FC_CHANGE, SD_REG(intstatus)); + +- err = r_sdreg32(bus, &newstatus, +- offsetof(struct sdpcmd_regs, intstatus)); ++ err = r_sdreg32(bus, &newstatus, SD_REG(intstatus)); + bus->sdcnt.f1regdata += 2; + atomic_set(&bus->fcstate, + !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE))); +@@ -3771,7 +3765,7 @@ static void brcmf_sdio_buscore_activate( + + /* clear all interrupts */ + core = brcmf_chip_get_core(chip, BCMA_CORE_SDIO_DEV); +- reg_addr = core->base + offsetof(struct sdpcmd_regs, intstatus); ++ reg_addr = core->base + SD_REG(intstatus); + brcmf_sdiod_writel(sdiodev, reg_addr, 0xFFFFFFFF, NULL); + + if (rstvec) +@@ -4067,7 +4061,7 @@ static void brcmf_sdio_firmware_callback + + /* Enable function 2 (frame transfers) */ + w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, +- offsetof(struct sdpcmd_regs, tosbmailboxdata)); ++ SD_REG(tosbmailboxdata)); + err = sdio_enable_func(sdiodev->func[SDIO_FUNC_2]); + + +@@ -4077,8 +4071,7 @@ static void brcmf_sdio_firmware_callback + if (!err) { + /* Set up the interrupt mask and enable interrupts */ + bus->hostintmask = HOSTINTMASK; +- w_sdreg32(bus, bus->hostintmask, +- offsetof(struct sdpcmd_regs, hostintmask)); ++ w_sdreg32(bus, bus->hostintmask, SD_REG(hostintmask)); + + brcmf_sdiod_writeb(sdiodev, SBSDIO_WATERMARK, 8, &err); + } else { diff --git a/package/kernel/mac80211/patches/312-v4.16-0009-brcmfmac-Remove-unused-macro.patch b/package/kernel/mac80211/patches/312-v4.16-0009-brcmfmac-Remove-unused-macro.patch new file mode 100644 index 000000000..df72a70b3 --- /dev/null +++ b/package/kernel/mac80211/patches/312-v4.16-0009-brcmfmac-Remove-unused-macro.patch @@ -0,0 +1,26 @@ +From 5cfe38f1f8d3c6b98e15b8cfde05028a3c79930b Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Fri, 8 Dec 2017 13:10:34 +0100 +Subject: [PATCH] brcmfmac: Remove unused macro. + +This macro is used exactly nowhere in the code. Delete it. + +Signed-off-by: Ian Molton +Reviewed-by: Arend van Spriel +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -159,8 +159,6 @@ struct rte_console { + /* manfid tuple length, include tuple, link bytes */ + #define SBSDIO_CIS_MANFID_TUPLE_LEN 6 + +-#define CORE_BUS_REG(base, field) \ +- (base + offsetof(struct sdpcmd_regs, field)) + #define SD_REG(field) \ + (offsetof(struct sdpcmd_regs, field)) + diff --git a/package/kernel/mac80211/patches/312-v4.16-0010-brcmfmac-Remove-repeated-calls-to-brcmf_chip_get_cor.patch b/package/kernel/mac80211/patches/312-v4.16-0010-brcmfmac-Remove-repeated-calls-to-brcmf_chip_get_cor.patch new file mode 100644 index 000000000..69fbf5c80 --- /dev/null +++ b/package/kernel/mac80211/patches/312-v4.16-0010-brcmfmac-Remove-repeated-calls-to-brcmf_chip_get_cor.patch @@ -0,0 +1,128 @@ +From 21a10846d09db3c5e3bdfb0be0fc7aa9fdc7000a Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Fri, 8 Dec 2017 13:10:35 +0100 +Subject: [PATCH] brcmfmac: Remove repeated calls to brcmf_chip_get_core() + +There is no need to repeatdly call brcmf_chip_get_core(), which +traverses a list of cores every time its called (including during +register access code!). + +Call it once, and store a pointer to the core structure. The existing +code does nto keep track of users of the cores anyway, and even so, this +will allow for easier refcounting in future. + +Signed-off-by: Ian Molton +Reviewed-by: Arend van Spriel +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 25 +++++++++++++--------- + 1 file changed, 15 insertions(+), 10 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -436,6 +436,7 @@ struct brcmf_sdio_count { + struct brcmf_sdio { + struct brcmf_sdio_dev *sdiodev; /* sdio device handler */ + struct brcmf_chip *ci; /* Chip info struct */ ++ struct brcmf_core *sdio_core; /* sdio core info struct */ + + u32 hostintmask; /* Copy of Host Interrupt Mask */ + atomic_t intstatus; /* Intstatus bits (events) pending */ +@@ -665,10 +666,9 @@ static bool data_ok(struct brcmf_sdio *b + */ + static int r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 offset) + { +- struct brcmf_core *core; ++ struct brcmf_core *core = bus->sdio_core; + int ret; + +- core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV); + *regvar = brcmf_sdiod_readl(bus->sdiodev, core->base + offset, &ret); + + return ret; +@@ -676,10 +676,9 @@ static int r_sdreg32(struct brcmf_sdio * + + static int w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset) + { +- struct brcmf_core *core; ++ struct brcmf_core *core = bus->sdio_core; + int ret; + +- core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV); + brcmf_sdiod_writel(bus->sdiodev, core->base + reg_offset, regval, &ret); + + return ret; +@@ -2495,12 +2494,11 @@ static inline void brcmf_sdio_clrintr(st + + static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) + { +- struct brcmf_core *buscore; ++ struct brcmf_core *buscore = bus->sdio_core; + u32 addr; + unsigned long val; + int ret; + +- buscore = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV); + addr = buscore->base + SD_REG(intstatus); + + val = brcmf_sdiod_readl(bus->sdiodev, addr, &ret); +@@ -3377,13 +3375,14 @@ static void brcmf_sdio_sr_init(struct br + /* enable KSO bit */ + static int brcmf_sdio_kso_init(struct brcmf_sdio *bus) + { ++ struct brcmf_core *core = bus->sdio_core; + u8 val; + int err = 0; + + brcmf_dbg(TRACE, "Enter\n"); + + /* KSO bit added in SDIO core rev 12 */ +- if (brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV)->rev < 12) ++ if (core->rev < 12) + return 0; + + val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, &err); +@@ -3412,6 +3411,7 @@ static int brcmf_sdio_bus_preinit(struct + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + struct brcmf_sdio *bus = sdiodev->bus; ++ struct brcmf_core *core = bus->sdio_core; + uint pad_size; + u32 value; + int err; +@@ -3420,7 +3420,7 @@ static int brcmf_sdio_bus_preinit(struct + * a device perspective, ie. bus:txglom affects the + * bus transfers from device to host. + */ +- if (brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV)->rev < 12) { ++ if (core->rev < 12) { + /* for sdio core rev < 12, disable txgloming */ + value = 0; + err = brcmf_iovar_data_set(dev, "bus:txglom", &value, +@@ -3758,11 +3758,10 @@ static void brcmf_sdio_buscore_activate( + u32 rstvec) + { + struct brcmf_sdio_dev *sdiodev = ctx; +- struct brcmf_core *core; ++ struct brcmf_core *core = sdiodev->bus->sdio_core; + u32 reg_addr; + + /* clear all interrupts */ +- core = brcmf_chip_get_core(chip, BCMA_CORE_SDIO_DEV); + reg_addr = core->base + SD_REG(intstatus); + brcmf_sdiod_writel(sdiodev, reg_addr, 0xFFFFFFFF, NULL); + +@@ -3843,6 +3842,12 @@ brcmf_sdio_probe_attach(struct brcmf_sdi + bus->ci = NULL; + goto fail; + } ++ ++ /* Pick up the SDIO core info struct from chip.c */ ++ bus->sdio_core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV); ++ if (!bus->sdio_core) ++ goto fail; ++ + sdiodev->settings = brcmf_get_module_param(sdiodev->dev, + BRCMF_BUSTYPE_SDIO, + bus->ci->chip, diff --git a/package/kernel/mac80211/patches/313-v4.16-0001-brcmfmac-enlarge-buffer-size-of-caps-to-512-bytes.patch b/package/kernel/mac80211/patches/313-v4.16-0001-brcmfmac-enlarge-buffer-size-of-caps-to-512-bytes.patch new file mode 100644 index 000000000..731b7eda1 --- /dev/null +++ b/package/kernel/mac80211/patches/313-v4.16-0001-brcmfmac-enlarge-buffer-size-of-caps-to-512-bytes.patch @@ -0,0 +1,44 @@ +From 7762bb134e3b40e8ee2611365775b7432190a9c7 Mon Sep 17 00:00:00 2001 +From: Wright Feng +Date: Mon, 11 Dec 2017 15:38:21 +0800 +Subject: [PATCH] brcmfmac: enlarge buffer size of caps to 512 bytes + +The buffer size of return of cap iovar is greater than 256 bytes in some +firmwares. For instance, the return size of cap iovar is 271 bytes in 4373 +13.10.246.79 firmare. It makes feature capability parsing failed because +caps buffer is default value. +So we enlarge caps buffer size to 512 bytes and add the error print for +cap iovar error. + +Signed-off-by: Wright Feng +Acked-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +@@ -130,13 +130,19 @@ static void brcmf_feat_iovar_data_set(st + } + } + ++#define MAX_CAPS_BUFFER_SIZE 512 + static void brcmf_feat_firmware_capabilities(struct brcmf_if *ifp) + { +- char caps[256]; ++ char caps[MAX_CAPS_BUFFER_SIZE]; + enum brcmf_feat_id id; +- int i; ++ int i, err; ++ ++ err = brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps)); ++ if (err) { ++ brcmf_err("could not get firmware cap (%d)\n", err); ++ return; ++ } + +- brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps)); + brcmf_dbg(INFO, "[ %s]\n", caps); + + for (i = 0; i < ARRAY_SIZE(brcmf_fwcap_map); i++) { diff --git a/package/kernel/mac80211/patches/314-v4.16-0001-brcmfmac-Remove-r-w-_sdreg32.patch b/package/kernel/mac80211/patches/314-v4.16-0001-brcmfmac-Remove-r-w-_sdreg32.patch new file mode 100644 index 000000000..291cd5d78 --- /dev/null +++ b/package/kernel/mac80211/patches/314-v4.16-0001-brcmfmac-Remove-r-w-_sdreg32.patch @@ -0,0 +1,227 @@ +From 3d110df8f74781354051e4bb1e3e97fa368b2f80 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Tue, 19 Dec 2017 13:47:07 +0100 +Subject: [PATCH] brcmfmac: Remove {r,w}_sdreg32 + +Remove yet another IO function from the code and replace with one +that already exists. + +Signed-off-by: Ian Molton +Reviewed-by: Arend van Spriel +[arend: keep address calculation, ie. (base + offset) in one line] +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 88 +++++++++++----------- + 1 file changed, 42 insertions(+), 46 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -660,30 +660,6 @@ static bool data_ok(struct brcmf_sdio *b + ((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0; + } + +-/* +- * Reads a register in the SDIO hardware block. This block occupies a series of +- * adresses on the 32 bit backplane bus. +- */ +-static int r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 offset) +-{ +- struct brcmf_core *core = bus->sdio_core; +- int ret; +- +- *regvar = brcmf_sdiod_readl(bus->sdiodev, core->base + offset, &ret); +- +- return ret; +-} +- +-static int w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset) +-{ +- struct brcmf_core *core = bus->sdio_core; +- int ret; +- +- brcmf_sdiod_writel(bus->sdiodev, core->base + reg_offset, regval, &ret); +- +- return ret; +-} +- + static int + brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on) + { +@@ -1078,6 +1054,8 @@ static void brcmf_sdio_get_console_addr( + + static u32 brcmf_sdio_hostmail(struct brcmf_sdio *bus) + { ++ struct brcmf_sdio_dev *sdiod = bus->sdiodev; ++ struct brcmf_core *core = bus->sdio_core; + u32 intstatus = 0; + u32 hmb_data; + u8 fcbits; +@@ -1086,10 +1064,14 @@ static u32 brcmf_sdio_hostmail(struct br + brcmf_dbg(SDIO, "Enter\n"); + + /* Read mailbox data and ack that we did so */ +- ret = r_sdreg32(bus, &hmb_data, SD_REG(tohostmailboxdata)); ++ hmb_data = brcmf_sdiod_readl(sdiod, ++ core->base + SD_REG(tohostmailboxdata), ++ &ret); ++ ++ if (!ret) ++ brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailbox), ++ SMB_INT_ACK, &ret); + +- if (ret == 0) +- w_sdreg32(bus, SMB_INT_ACK, SD_REG(tosbmailbox)); + bus->sdcnt.f1regdata += 2; + + /* dongle indicates the firmware has halted/crashed */ +@@ -1163,6 +1145,8 @@ static u32 brcmf_sdio_hostmail(struct br + + static void brcmf_sdio_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) + { ++ struct brcmf_sdio_dev *sdiod = bus->sdiodev; ++ struct brcmf_core *core = bus->sdio_core; + uint retries = 0; + u16 lastrbc; + u8 hi, lo; +@@ -1204,7 +1188,8 @@ static void brcmf_sdio_rxfail(struct brc + + if (rtx) { + bus->sdcnt.rxrtx++; +- err = w_sdreg32(bus, SMB_NAK, SD_REG(tosbmailbox)); ++ brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailbox), ++ SMB_NAK, &err); + + bus->sdcnt.f1regdata++; + if (err == 0) +@@ -2291,6 +2276,7 @@ static uint brcmf_sdio_sendfromq(struct + { + struct sk_buff *pkt; + struct sk_buff_head pktq; ++ u32 intstat_addr = bus->sdio_core->base + SD_REG(intstatus); + u32 intstatus = 0; + int ret = 0, prec_out, i; + uint cnt = 0; +@@ -2329,7 +2315,8 @@ static uint brcmf_sdio_sendfromq(struct + if (!bus->intr) { + /* Check device status, signal pending interrupt */ + sdio_claim_host(bus->sdiodev->func[1]); +- ret = r_sdreg32(bus, &intstatus, SD_REG(intstatus)); ++ intstatus = brcmf_sdiod_readl(bus->sdiodev, ++ intstat_addr, &ret); + sdio_release_host(bus->sdiodev->func[1]); + bus->sdcnt.f2txdata++; + if (ret != 0) +@@ -2413,12 +2400,13 @@ static int brcmf_sdio_tx_ctrlframe(struc + + static void brcmf_sdio_bus_stop(struct device *dev) + { +- u32 local_hostintmask; +- u8 saveclk; +- int err; + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + struct brcmf_sdio *bus = sdiodev->bus; ++ struct brcmf_core *core = bus->sdio_core; ++ u32 local_hostintmask; ++ u8 saveclk; ++ int err; + + brcmf_dbg(TRACE, "Enter\n"); + +@@ -2435,7 +2423,9 @@ static void brcmf_sdio_bus_stop(struct d + brcmf_sdio_bus_sleep(bus, false, false); + + /* Disable and clear interrupts at the chip level also */ +- w_sdreg32(bus, 0, SD_REG(hostintmask)); ++ brcmf_sdiod_writel(sdiodev, core->base + SD_REG(hostintmask), ++ 0, NULL); ++ + local_hostintmask = bus->hostintmask; + bus->hostintmask = 0; + +@@ -2454,7 +2444,8 @@ static void brcmf_sdio_bus_stop(struct d + sdio_disable_func(sdiodev->func[SDIO_FUNC_2]); + + /* Clear any pending interrupts now that F2 is disabled */ +- w_sdreg32(bus, local_hostintmask, SD_REG(intstatus)); ++ brcmf_sdiod_writel(sdiodev, core->base + SD_REG(intstatus), ++ local_hostintmask, NULL); + + sdio_release_host(sdiodev->func[1]); + } +@@ -2521,7 +2512,9 @@ static int brcmf_sdio_intr_rstatus(struc + + static void brcmf_sdio_dpc(struct brcmf_sdio *bus) + { ++ struct brcmf_sdio_dev *sdiod = bus->sdiodev; + u32 newstatus = 0; ++ u32 intstat_addr = bus->sdio_core->base + SD_REG(intstatus); + unsigned long intstatus; + uint txlimit = bus->txbound; /* Tx frames to send before resched */ + uint framecnt; /* Temporary counter of tx/rx frames */ +@@ -2576,9 +2569,10 @@ static void brcmf_sdio_dpc(struct brcmf_ + */ + if (intstatus & I_HMB_FC_CHANGE) { + intstatus &= ~I_HMB_FC_CHANGE; +- err = w_sdreg32(bus, I_HMB_FC_CHANGE, SD_REG(intstatus)); ++ brcmf_sdiod_writel(sdiod, intstat_addr, I_HMB_FC_CHANGE, &err); ++ ++ newstatus = brcmf_sdiod_readl(sdiod, intstat_addr, &err); + +- err = r_sdreg32(bus, &newstatus, SD_REG(intstatus)); + bus->sdcnt.f1regdata += 2; + atomic_set(&bus->fcstate, + !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE))); +@@ -4017,22 +4011,21 @@ static void brcmf_sdio_firmware_callback + const struct firmware *code, + void *nvram, u32 nvram_len) + { +- struct brcmf_bus *bus_if; +- struct brcmf_sdio_dev *sdiodev; +- struct brcmf_sdio *bus; ++ struct brcmf_bus *bus_if = dev_get_drvdata(dev); ++ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; ++ struct brcmf_sdio *bus = sdiodev->bus; ++ struct brcmf_sdio_dev *sdiod = bus->sdiodev; ++ struct brcmf_core *core = bus->sdio_core; + u8 saveclk; + + brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err); +- bus_if = dev_get_drvdata(dev); +- sdiodev = bus_if->bus_priv.sdio; ++ + if (err) + goto fail; + + if (!bus_if->drvr) + return; + +- bus = sdiodev->bus; +- + /* try to download image and nvram to the dongle */ + bus->alp_only = true; + err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len); +@@ -4063,8 +4056,9 @@ static void brcmf_sdio_firmware_callback + } + + /* Enable function 2 (frame transfers) */ +- w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, +- SD_REG(tosbmailboxdata)); ++ brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailboxdata), ++ SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, NULL); ++ + err = sdio_enable_func(sdiodev->func[SDIO_FUNC_2]); + + +@@ -4074,7 +4068,9 @@ static void brcmf_sdio_firmware_callback + if (!err) { + /* Set up the interrupt mask and enable interrupts */ + bus->hostintmask = HOSTINTMASK; +- w_sdreg32(bus, bus->hostintmask, SD_REG(hostintmask)); ++ brcmf_sdiod_writel(sdiod, core->base + SD_REG(hostintmask), ++ bus->hostintmask, NULL); ++ + + brcmf_sdiod_writeb(sdiodev, SBSDIO_WATERMARK, 8, &err); + } else { diff --git a/package/kernel/mac80211/patches/314-v4.16-0002-brcmfmac-Rename-buscore-to-core-for-consistency.patch b/package/kernel/mac80211/patches/314-v4.16-0002-brcmfmac-Rename-buscore-to-core-for-consistency.patch new file mode 100644 index 000000000..e9b562830 --- /dev/null +++ b/package/kernel/mac80211/patches/314-v4.16-0002-brcmfmac-Rename-buscore-to-core-for-consistency.patch @@ -0,0 +1,33 @@ +From dbda7dacb79a377e8ed9d38ce0e4a58b70aa9060 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Tue, 19 Dec 2017 13:47:08 +0100 +Subject: [PATCH] brcmfmac: Rename buscore to core for consistency + +Avoid confusion with unrelated _buscore labels. + +Signed-off-by: Ian Molton +Acked-by: Arend van Spriel +[arend: only do the rename] +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -2485,12 +2485,12 @@ static inline void brcmf_sdio_clrintr(st + + static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) + { +- struct brcmf_core *buscore = bus->sdio_core; ++ struct brcmf_core *core = bus->sdio_core; + u32 addr; + unsigned long val; + int ret; + +- addr = buscore->base + SD_REG(intstatus); ++ addr = core->base + SD_REG(intstatus); + + val = brcmf_sdiod_readl(bus->sdiodev, addr, &ret); + bus->sdcnt.f1regdata++; diff --git a/package/kernel/mac80211/patches/314-v4.16-0003-brcmfmac-stabilise-the-value-of-sbwad-in-use-for-som.patch b/package/kernel/mac80211/patches/314-v4.16-0003-brcmfmac-stabilise-the-value-of-sbwad-in-use-for-som.patch new file mode 100644 index 000000000..3828c320f --- /dev/null +++ b/package/kernel/mac80211/patches/314-v4.16-0003-brcmfmac-stabilise-the-value-of-sbwad-in-use-for-som.patch @@ -0,0 +1,82 @@ +From 874bb8e49b7c6368f8ff9f2566c7bd06a2249be0 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Tue, 19 Dec 2017 13:47:09 +0100 +Subject: [PATCH] brcmfmac: stabilise the value of ->sbwad in use for some xfer + routines. + +The IO functions operate within the Chipcommon IO window. Explicitly +set this, rather than relying on the last initialisation IO access to +leave it set to the right value by chance. + +Signed-off-by: Ian Molton +Acked-by: Arend van Spriel +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 8 ++++---- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 5 +++++ + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 1 + + 3 files changed, 10 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -529,7 +529,7 @@ int brcmf_sdiod_recv_buf(struct brcmf_sd + + int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt) + { +- u32 addr = sdiodev->sbwad; ++ u32 addr = sdiodev->cc_core->base; + int err = 0; + + brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pkt->len); +@@ -552,7 +552,7 @@ int brcmf_sdiod_recv_chain(struct brcmf_ + { + struct sk_buff *glom_skb = NULL; + struct sk_buff *skb; +- u32 addr = sdiodev->sbwad; ++ u32 addr = sdiodev->cc_core->base; + int err = 0; + + brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", +@@ -593,7 +593,7 @@ done: + int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes) + { + struct sk_buff *mypkt; +- u32 addr = sdiodev->sbwad; ++ u32 addr = sdiodev->cc_core->base; + int err; + + mypkt = brcmu_pkt_buf_get_skb(nbytes); +@@ -625,7 +625,7 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd + struct sk_buff_head *pktq) + { + struct sk_buff *skb; +- u32 addr = sdiodev->sbwad; ++ u32 addr = sdiodev->cc_core->base; + int err; + + brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pktq->qlen); +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -3842,6 +3842,11 @@ brcmf_sdio_probe_attach(struct brcmf_sdi + if (!bus->sdio_core) + goto fail; + ++ /* Pick up the CHIPCOMMON core info struct, for bulk IO in bcmsdh.c */ ++ sdiodev->cc_core = brcmf_chip_get_core(bus->ci, BCMA_CORE_CHIPCOMMON); ++ if (!sdiodev->cc_core) ++ goto fail; ++ + sdiodev->settings = brcmf_get_module_param(sdiodev->dev, + BRCMF_BUSTYPE_SDIO, + bus->ci->chip, +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +@@ -178,6 +178,7 @@ struct brcmf_sdio_dev { + struct sdio_func *func[SDIO_MAX_FUNCS]; + u8 num_funcs; /* Supported funcs on client */ + u32 sbwad; /* Save backplane window address */ ++ struct brcmf_core *cc_core; /* chipcommon core info struct */ + struct brcmf_sdio *bus; + struct device *dev; + struct brcmf_bus *bus_if; diff --git a/package/kernel/mac80211/patches/314-v4.16-0004-brcmfmac-Correctly-handle-accesses-to-SDIO-func0.patch b/package/kernel/mac80211/patches/314-v4.16-0004-brcmfmac-Correctly-handle-accesses-to-SDIO-func0.patch new file mode 100644 index 000000000..86b269a34 --- /dev/null +++ b/package/kernel/mac80211/patches/314-v4.16-0004-brcmfmac-Correctly-handle-accesses-to-SDIO-func0.patch @@ -0,0 +1,45 @@ +From 508422f3695bf66f7b85fb4723c22f5166003ec6 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Tue, 19 Dec 2017 13:47:10 +0100 +Subject: [PATCH] brcmfmac: Correctly handle accesses to SDIO func0 + +Rather than workaround the restrictions on func0 addressing in the +driver, set MMC_QUIRK_LENIENT_FN0 + +Signed-off-by: Ian Molton +Acked-by: Arend van Spriel +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 4 ++++ + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 4 ++-- + 2 files changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -995,6 +995,10 @@ static int brcmf_ops_sdio_probe(struct s + brcmf_dbg(SDIO, "Function#: %d\n", func->num); + + dev = &func->dev; ++ ++ /* Set MMC_QUIRK_LENIENT_FN0 for this card */ ++ func->card->quirks |= MMC_QUIRK_LENIENT_FN0; ++ + /* prohibit ACPI power management for this device */ + brcmf_sdiod_acpi_set_power_manageable(dev, 0); + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +@@ -297,10 +297,10 @@ void brcmf_sdiod_intr_unregister(struct + /* SDIO device register access interface */ + /* Accessors for SDIO Function 0 */ + #define brcmf_sdiod_func0_rb(sdiodev, addr, r) \ +- sdio_readb((sdiodev)->func[0], (addr), (r)) ++ sdio_f0_readb((sdiodev)->func[0], (addr), (r)) + + #define brcmf_sdiod_func0_wb(sdiodev, addr, v, ret) \ +- sdio_writeb((sdiodev)->func[0], (v), (addr), (ret)) ++ sdio_f0_writeb((sdiodev)->func[0], (v), (addr), (ret)) + + /* Accessors for SDIO Function 1 */ + #define brcmf_sdiod_readb(sdiodev, addr, r) \ diff --git a/package/kernel/mac80211/patches/314-v4.16-0005-brcmfmac-Remove-func0-from-function-array.patch b/package/kernel/mac80211/patches/314-v4.16-0005-brcmfmac-Remove-func0-from-function-array.patch new file mode 100644 index 000000000..715b86561 --- /dev/null +++ b/package/kernel/mac80211/patches/314-v4.16-0005-brcmfmac-Remove-func0-from-function-array.patch @@ -0,0 +1,111 @@ +From 99d7b6fdfc8c24052c92c720330d31ca1332f996 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Tue, 19 Dec 2017 13:47:11 +0100 +Subject: [PATCH] brcmfmac: Remove func0 from function array + +func0 is not provided by the mmc stack as a function when probing. +Instead providing specific access functions to read/write it. + +This prepares for a patch to remove the actual array entry itself. + +Signed-off-by: Ian Molton +Acked-by: Arend van Spriel +[arend: rephrased the commit message] +[arend: removed unrelated comment for which separate patch is warranted] +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 5 +---- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 7 ++++--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 13 ++++++------- + 3 files changed, 11 insertions(+), 14 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -1022,8 +1022,7 @@ static int brcmf_ops_sdio_probe(struct s + /* store refs to functions used. mmc_card does + * not hold the F0 function pointer. + */ +- sdiodev->func[0] = kmemdup(func, sizeof(*func), GFP_KERNEL); +- sdiodev->func[0]->num = 0; ++ sdiodev->func[0] = NULL; + sdiodev->func[1] = func->card->sdio_func[0]; + sdiodev->func[2] = func; + +@@ -1049,7 +1048,6 @@ static int brcmf_ops_sdio_probe(struct s + fail: + dev_set_drvdata(&func->dev, NULL); + dev_set_drvdata(&sdiodev->func[1]->dev, NULL); +- kfree(sdiodev->func[0]); + kfree(sdiodev); + kfree(bus_if); + return err; +@@ -1082,7 +1080,6 @@ static void brcmf_ops_sdio_remove(struct + dev_set_drvdata(&sdiodev->func[2]->dev, NULL); + + kfree(bus_if); +- kfree(sdiodev->func[0]); + kfree(sdiodev); + } + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -3771,9 +3771,10 @@ static u32 brcmf_sdio_buscore_read32(voi + u32 val, rev; + + val = brcmf_sdiod_readl(sdiodev, addr, NULL); +- if ((sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 || +- sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4339) && +- addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) { ++ ++ if ((sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 || ++ sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4339) && ++ addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) { + rev = (val & CID_REV_MASK) >> CID_REV_SHIFT; + if (rev >= 2) { + val &= ~CID_ID_MASK; +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +@@ -21,7 +21,9 @@ + #include + #include "firmware.h" + +-#define SDIO_FUNC_0 0 ++/* Maximum number of I/O funcs */ ++#define NUM_SDIO_FUNCS 3 ++ + #define SDIO_FUNC_1 1 + #define SDIO_FUNC_2 2 + +@@ -39,9 +41,6 @@ + #define INTR_STATUS_FUNC1 0x2 + #define INTR_STATUS_FUNC2 0x4 + +-/* Maximum number of I/O funcs */ +-#define SDIOD_MAX_IOFUNCS 7 +- + /* mask of register map */ + #define REG_F0_REG_MASK 0x7FF + #define REG_F1_MISC_MASK 0x1FFFF +@@ -175,7 +174,7 @@ struct brcmf_sdio; + struct brcmf_sdiod_freezer; + + struct brcmf_sdio_dev { +- struct sdio_func *func[SDIO_MAX_FUNCS]; ++ struct sdio_func *func[NUM_SDIO_FUNCS]; + u8 num_funcs; /* Supported funcs on client */ + u32 sbwad; /* Save backplane window address */ + struct brcmf_core *cc_core; /* chipcommon core info struct */ +@@ -297,10 +296,10 @@ void brcmf_sdiod_intr_unregister(struct + /* SDIO device register access interface */ + /* Accessors for SDIO Function 0 */ + #define brcmf_sdiod_func0_rb(sdiodev, addr, r) \ +- sdio_f0_readb((sdiodev)->func[0], (addr), (r)) ++ sdio_f0_readb((sdiodev)->func[1], (addr), (r)) + + #define brcmf_sdiod_func0_wb(sdiodev, addr, v, ret) \ +- sdio_f0_writeb((sdiodev)->func[0], (v), (addr), (ret)) ++ sdio_f0_writeb((sdiodev)->func[1], (v), (addr), (ret)) + + /* Accessors for SDIO Function 1 */ + #define brcmf_sdiod_readb(sdiodev, addr, r) \ diff --git a/package/kernel/mac80211/patches/314-v4.16-0006-brcmfmac-More-efficient-and-slightly-easier-to-read-.patch b/package/kernel/mac80211/patches/314-v4.16-0006-brcmfmac-More-efficient-and-slightly-easier-to-read-.patch new file mode 100644 index 000000000..71e4894b0 --- /dev/null +++ b/package/kernel/mac80211/patches/314-v4.16-0006-brcmfmac-More-efficient-and-slightly-easier-to-read-.patch @@ -0,0 +1,40 @@ +From bcadaaa097c7ec103fe75f9da41f8fe52693b644 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Tue, 19 Dec 2017 13:47:12 +0100 +Subject: [PATCH] brcmfmac: More efficient and slightly easier to read fixup + for 4339 chips + +Its more efficient to test the register we're interested in first, +potentially avoiding two more comparisons, and therefore always avoiding +one comparison per call on all other chips. + +Signed-off-by: Ian Molton +[arend: fix some checkpatch warnings] +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -3772,15 +3772,16 @@ static u32 brcmf_sdio_buscore_read32(voi + + val = brcmf_sdiod_readl(sdiodev, addr, NULL); + +- if ((sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 || +- sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4339) && +- addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) { ++ if (addr == CORE_CC_REG(SI_ENUM_BASE, chipid) && ++ (sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4339 || ++ sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339)) { + rev = (val & CID_REV_MASK) >> CID_REV_SHIFT; + if (rev >= 2) { + val &= ~CID_ID_MASK; + val |= BRCM_CC_4339_CHIP_ID; + } + } ++ + return val; + } + diff --git a/package/kernel/mac80211/patches/314-v4.16-0007-brcmfmac-Replace-function-index-with-function-pointe.patch b/package/kernel/mac80211/patches/314-v4.16-0007-brcmfmac-Replace-function-index-with-function-pointe.patch new file mode 100644 index 000000000..4354a7081 --- /dev/null +++ b/package/kernel/mac80211/patches/314-v4.16-0007-brcmfmac-Replace-function-index-with-function-pointe.patch @@ -0,0 +1,347 @@ +From 00eb62cfc5f806b003fe5d54c8b5fe9a9665482f Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Tue, 19 Dec 2017 13:47:13 +0100 +Subject: [PATCH] brcmfmac: Replace function index with function pointer + +In preparation for removing the function array, remove all code that +refers to function by index and replace with pointers to the function +itself. + +Signed-off-by: Ian Molton +Reviewed-by: Arend van Spriel +[arend: replace BUG() with WARN() macro] +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 85 ++++++++++++---------- + .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 15 ++-- + .../wireless/broadcom/brcm80211/brcmfmac/sdio.h | 6 +- + 3 files changed, 56 insertions(+), 50 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -291,8 +291,9 @@ out: + *ret = retval; + } + +-static int brcmf_sdiod_buff_read(struct brcmf_sdio_dev *sdiodev, uint fn, +- u32 addr, struct sk_buff *pkt) ++static int brcmf_sdiod_buff_read(struct brcmf_sdio_dev *sdiodev, ++ struct sdio_func *func, u32 addr, ++ struct sk_buff *pkt) + { + unsigned int req_sz; + int err; +@@ -301,13 +302,19 @@ static int brcmf_sdiod_buff_read(struct + req_sz = pkt->len + 3; + req_sz &= (uint)~3; + +- if (fn == 1) +- err = sdio_memcpy_fromio(sdiodev->func[fn], +- ((u8 *)(pkt->data)), addr, req_sz); +- else +- /* function 2 read is FIFO operation */ +- err = sdio_readsb(sdiodev->func[fn], +- ((u8 *)(pkt->data)), addr, req_sz); ++ switch (func->num) { ++ case 1: ++ err = sdio_memcpy_fromio(func, ((u8 *)(pkt->data)), addr, ++ req_sz); ++ break; ++ case 2: ++ err = sdio_readsb(func, ((u8 *)(pkt->data)), addr, req_sz); ++ break; ++ default: ++ /* bail out as things are really fishy here */ ++ WARN(1, "invalid sdio function number: %d\n", func->num); ++ err = -ENOMEDIUM; ++ }; + + if (err == -ENOMEDIUM) + brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM); +@@ -315,8 +322,9 @@ static int brcmf_sdiod_buff_read(struct + return err; + } + +-static int brcmf_sdiod_buff_write(struct brcmf_sdio_dev *sdiodev, uint fn, +- u32 addr, struct sk_buff *pkt) ++static int brcmf_sdiod_buff_write(struct brcmf_sdio_dev *sdiodev, ++ struct sdio_func *func, u32 addr, ++ struct sk_buff *pkt) + { + unsigned int req_sz; + int err; +@@ -325,8 +333,7 @@ static int brcmf_sdiod_buff_write(struct + req_sz = pkt->len + 3; + req_sz &= (uint)~3; + +- err = sdio_memcpy_toio(sdiodev->func[fn], addr, +- ((u8 *)(pkt->data)), req_sz); ++ err = sdio_memcpy_toio(func, addr, ((u8 *)(pkt->data)), req_sz); + + if (err == -ENOMEDIUM) + brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM); +@@ -337,7 +344,7 @@ static int brcmf_sdiod_buff_write(struct + /** + * brcmf_sdiod_sglist_rw - SDIO interface function for block data access + * @sdiodev: brcmfmac sdio device +- * @fn: SDIO function number ++ * @func: SDIO function + * @write: direction flag + * @addr: dongle memory address as source/destination + * @pkt: skb pointer +@@ -346,7 +353,8 @@ static int brcmf_sdiod_buff_write(struct + * stack for block data access. It assumes that the skb passed down by the + * caller has already been padded and aligned. + */ +-static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, ++static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, ++ struct sdio_func *func, + bool write, u32 addr, + struct sk_buff_head *pktlist) + { +@@ -372,7 +380,7 @@ static int brcmf_sdiod_sglist_rw(struct + req_sz = 0; + skb_queue_walk(pktlist, pkt_next) + req_sz += pkt_next->len; +- req_sz = ALIGN(req_sz, sdiodev->func[fn]->cur_blksize); ++ req_sz = ALIGN(req_sz, func->cur_blksize); + while (req_sz > PAGE_SIZE) { + pkt_next = brcmu_pkt_buf_get_skb(PAGE_SIZE); + if (pkt_next == NULL) { +@@ -391,7 +399,7 @@ static int brcmf_sdiod_sglist_rw(struct + target_list = &local_list; + } + +- func_blk_sz = sdiodev->func[fn]->cur_blksize; ++ func_blk_sz = func->cur_blksize; + max_req_sz = sdiodev->max_request_size; + max_seg_cnt = min_t(unsigned short, sdiodev->max_segment_count, + target_list->qlen); +@@ -408,10 +416,10 @@ static int brcmf_sdiod_sglist_rw(struct + mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; + mmc_cmd.opcode = SD_IO_RW_EXTENDED; + mmc_cmd.arg = write ? 1<<31 : 0; /* write flag */ +- mmc_cmd.arg |= (fn & 0x7) << 28; /* SDIO func num */ +- mmc_cmd.arg |= 1<<27; /* block mode */ ++ mmc_cmd.arg |= (func->num & 0x7) << 28; /* SDIO func num */ ++ mmc_cmd.arg |= 1 << 27; /* block mode */ + /* for function 1 the addr will be incremented */ +- mmc_cmd.arg |= (fn == 1) ? 1<<26 : 0; ++ mmc_cmd.arg |= (func->num == 1) ? 1 << 26 : 0; + mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; + mmc_req.cmd = &mmc_cmd; + mmc_req.data = &mmc_dat; +@@ -457,11 +465,11 @@ static int brcmf_sdiod_sglist_rw(struct + mmc_cmd.arg |= (addr & 0x1FFFF) << 9; /* address */ + mmc_cmd.arg |= mmc_dat.blocks & 0x1FF; /* block count */ + /* incrementing addr for function 1 */ +- if (fn == 1) ++ if (func->num == 1) + addr += req_sz; + +- mmc_set_data_timeout(&mmc_dat, sdiodev->func[fn]->card); +- mmc_wait_for_req(sdiodev->func[fn]->card->host, &mmc_req); ++ mmc_set_data_timeout(&mmc_dat, func->card); ++ mmc_wait_for_req(func->card->host, &mmc_req); + + ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error; + if (ret == -ENOMEDIUM) { +@@ -541,7 +549,7 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd + addr &= SBSDIO_SB_OFT_ADDR_MASK; + addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + +- err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr, pkt); ++ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr, pkt); + + done: + return err; +@@ -566,13 +574,13 @@ int brcmf_sdiod_recv_chain(struct brcmf_ + addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + + if (pktq->qlen == 1) +- err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr, ++ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr, + pktq->next); + else if (!sdiodev->sg_support) { + glom_skb = brcmu_pkt_buf_get_skb(totlen); + if (!glom_skb) + return -ENOMEM; +- err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr, ++ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr, + glom_skb); + if (err) + goto done; +@@ -582,8 +590,8 @@ int brcmf_sdiod_recv_chain(struct brcmf_ + skb_pull(glom_skb, skb->len); + } + } else +- err = brcmf_sdiod_sglist_rw(sdiodev, SDIO_FUNC_2, false, addr, +- pktq); ++ err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func[2], false, ++ addr, pktq); + + done: + brcmu_pkt_buf_free_skb(glom_skb); +@@ -614,7 +622,8 @@ int brcmf_sdiod_send_buf(struct brcmf_sd + addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + + if (!err) +- err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2, addr, mypkt); ++ err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[2], addr, ++ mypkt); + + brcmu_pkt_buf_free_skb(mypkt); + +@@ -639,14 +648,14 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd + + if (pktq->qlen == 1 || !sdiodev->sg_support) { + skb_queue_walk(pktq, skb) { +- err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2, ++ err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[2], + addr, skb); + if (err) + break; + } + } else { +- err = brcmf_sdiod_sglist_rw(sdiodev, SDIO_FUNC_2, true, addr, +- pktq); ++ err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func[2], true, ++ addr, pktq); + } + + return err; +@@ -696,10 +705,10 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev + + if (write) { + memcpy(pkt->data, data, dsize); +- err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_1, ++ err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[1], + sdaddr, pkt); + } else { +- err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_1, ++ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[1], + sdaddr, pkt); + } + +@@ -728,12 +737,12 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev + return err; + } + +-int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn) ++int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, struct sdio_func *func) + { + brcmf_dbg(SDIO, "Enter\n"); + + /* Issue abort cmd52 command through F0 */ +- brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_ABORT, fn, NULL); ++ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_ABORT, func->num, NULL); + + brcmf_dbg(SDIO, "Exit\n"); + return 0; +@@ -1105,7 +1114,7 @@ static int brcmf_ops_sdio_suspend(struct + + func = container_of(dev, struct sdio_func, dev); + brcmf_dbg(SDIO, "Enter: F%d\n", func->num); +- if (func->num != SDIO_FUNC_1) ++ if (func->num != 1) + return 0; + + +@@ -1134,7 +1143,7 @@ static int brcmf_ops_sdio_resume(struct + struct sdio_func *func = container_of(dev, struct sdio_func, dev); + + brcmf_dbg(SDIO, "Enter: F%d\n", func->num); +- if (func->num != SDIO_FUNC_2) ++ if (func->num != 2) + return 0; + + brcmf_sdiod_freezer_off(sdiodev); +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -1157,7 +1157,7 @@ static void brcmf_sdio_rxfail(struct brc + rtx ? ", send NAK" : ""); + + if (abort) +- brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2); ++ brcmf_sdiod_abort(bus->sdiodev, bus->sdiodev->func[2]); + + brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, + &err); +@@ -1209,7 +1209,7 @@ static void brcmf_sdio_txfail(struct brc + brcmf_err("sdio error, abort command and terminate frame\n"); + bus->sdcnt.tx_sderrs++; + +- brcmf_sdiod_abort(sdiodev, SDIO_FUNC_2); ++ brcmf_sdiod_abort(sdiodev, sdiodev->func[2]); + brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL); + bus->sdcnt.f1regdata++; + +@@ -2072,7 +2072,7 @@ static int brcmf_sdio_txpkt_prep_sg(stru + int ntail, ret; + + sdiodev = bus->sdiodev; +- blksize = sdiodev->func[SDIO_FUNC_2]->cur_blksize; ++ blksize = sdiodev->func[2]->cur_blksize; + /* sg entry alignment should be a divisor of block size */ + WARN_ON(blksize % bus->sgentry_align); + +@@ -2441,7 +2441,7 @@ static void brcmf_sdio_bus_stop(struct d + + /* Turn off the bus (F2), free any pending packets */ + brcmf_dbg(INTR, "disable SDIO interrupts\n"); +- sdio_disable_func(sdiodev->func[SDIO_FUNC_2]); ++ sdio_disable_func(sdiodev->func[2]); + + /* Clear any pending interrupts now that F2 is disabled */ + brcmf_sdiod_writel(sdiodev, core->base + SD_REG(intstatus), +@@ -4066,8 +4066,7 @@ static void brcmf_sdio_firmware_callback + brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailboxdata), + SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, NULL); + +- err = sdio_enable_func(sdiodev->func[SDIO_FUNC_2]); +- ++ err = sdio_enable_func(sdiodev->func[2]); + + brcmf_dbg(INFO, "enable F2: err=%d\n", err); + +@@ -4082,7 +4081,7 @@ static void brcmf_sdio_firmware_callback + brcmf_sdiod_writeb(sdiodev, SBSDIO_WATERMARK, 8, &err); + } else { + /* Disable F2 again */ +- sdio_disable_func(sdiodev->func[SDIO_FUNC_2]); ++ sdio_disable_func(sdiodev->func[2]); + goto release; + } + +@@ -4219,7 +4218,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru + sdio_claim_host(bus->sdiodev->func[1]); + + /* Disable F2 to clear any intermediate frame state on the dongle */ +- sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]); ++ sdio_disable_func(bus->sdiodev->func[2]); + + bus->rxflow = false; + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +@@ -45,9 +45,6 @@ + #define REG_F0_REG_MASK 0x7FF + #define REG_F1_MISC_MASK 0x1FFFF + +-/* as of sdiod rev 0, supports 3 functions */ +-#define SBSDIO_NUM_FUNCTION 3 +- + /* function 0 vendor specific CCCR registers */ + + #define SDIO_CCCR_BRCM_CARDCAP 0xf0 +@@ -350,7 +347,8 @@ int brcmf_sdiod_ramrw(struct brcmf_sdio_ + u8 *data, uint size); + + /* Issue an abort to the specified function */ +-int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn); ++int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, struct sdio_func *func); ++ + void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev); + void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev, + enum brcmf_sdiod_state state); diff --git a/package/kernel/mac80211/patches/314-v4.16-0008-brcmfmac-Clean-up-interrupt-macros.patch b/package/kernel/mac80211/patches/314-v4.16-0008-brcmfmac-Clean-up-interrupt-macros.patch new file mode 100644 index 000000000..d732c8e58 --- /dev/null +++ b/package/kernel/mac80211/patches/314-v4.16-0008-brcmfmac-Clean-up-interrupt-macros.patch @@ -0,0 +1,53 @@ +From 9c3438ed215adba7025268ee1f0b6f7a2af12316 Mon Sep 17 00:00:00 2001 +From: Ian Molton +Date: Tue, 19 Dec 2017 13:47:14 +0100 +Subject: [PATCH] brcmfmac: Clean up interrupt macros + +Make it more obvious that this code acually enables interrupts, and +provide nice definitions for the bits in the register. + +Signed-off-by: Ian Molton +Acked-by: Arend van Spriel +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 3 ++- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 8 +++++--- + 2 files changed, 7 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -149,7 +149,8 @@ int brcmf_sdiod_intr_register(struct brc + + /* must configure SDIO_CCCR_IENx to enable irq */ + data = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_IENx, &ret); +- data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; ++ data |= SDIO_CCCR_IEN_FUNC1 | SDIO_CCCR_IEN_FUNC2 | ++ SDIO_CCCR_IEN_FUNC0; + brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, data, &ret); + + /* redirect, configure and enable io for interrupt signal */ +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +@@ -24,9 +24,6 @@ + /* Maximum number of I/O funcs */ + #define NUM_SDIO_FUNCS 3 + +-#define SDIO_FUNC_1 1 +-#define SDIO_FUNC_2 2 +- + #define SDIOD_FBR_SIZE 0x100 + + /* io_en */ +@@ -52,6 +49,11 @@ + #define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT BIT(2) + #define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC BIT(3) + ++/* Interrupt enable bits for each function */ ++#define SDIO_CCCR_IEN_FUNC0 BIT(0) ++#define SDIO_CCCR_IEN_FUNC1 BIT(1) ++#define SDIO_CCCR_IEN_FUNC2 BIT(2) ++ + #define SDIO_CCCR_BRCM_CARDCTRL 0xf1 + #define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET BIT(1) + diff --git a/package/kernel/mac80211/patches/315-v4.16-0001-brcmfmac-Support-43455-save-restore-SR-feature-if-FW.patch b/package/kernel/mac80211/patches/315-v4.16-0001-brcmfmac-Support-43455-save-restore-SR-feature-if-FW.patch new file mode 100644 index 000000000..d010d23f0 --- /dev/null +++ b/package/kernel/mac80211/patches/315-v4.16-0001-brcmfmac-Support-43455-save-restore-SR-feature-if-FW.patch @@ -0,0 +1,27 @@ +From e3720dad99859251a8b0fe2807275a8afcfb560d Mon Sep 17 00:00:00 2001 +From: Double Lo +Date: Tue, 19 Dec 2017 14:56:44 +0800 +Subject: [PATCH] brcmfmac: Support 43455 save-restore (SR) feature if FW + include -sr + +This patch will add 43455 into the save-restore(SR) capable chip list, so +the SR engine will be enabled with 43455 FW which built-in the -sr +function. + +Signed-off-by: Double Lo +Signed-off-by: Wright Feng +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +@@ -1338,6 +1338,7 @@ bool brcmf_chip_sr_capable(struct brcmf_ + switch (pub->chip) { + case BRCM_CC_4354_CHIP_ID: + case BRCM_CC_4356_CHIP_ID: ++ case BRCM_CC_4345_CHIP_ID: + /* explicitly check SR engine enable bit */ + pmu_cc3_mask = BIT(2); + /* fall-through */ diff --git a/package/kernel/mac80211/patches/316-v4.16-0001-brcmfmac-Remove-array-of-functions.patch b/package/kernel/mac80211/patches/316-v4.16-0001-brcmfmac-Remove-array-of-functions.patch new file mode 100644 index 000000000..bd9de13d7 --- /dev/null +++ b/package/kernel/mac80211/patches/316-v4.16-0001-brcmfmac-Remove-array-of-functions.patch @@ -0,0 +1,1043 @@ +From c9aa7a91de740c537dc8c2f9f3d36fc651371b13 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Tue, 9 Jan 2018 13:22:52 +0100 +Subject: [PATCH] brcmfmac: Remove array of functions + +Replace the array of functions with a pair of pointers to the +relevant functions. + +Signed-off-by: Ian Molton +Acked-by: Arend van Spriel +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 115 +++++++------- + .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 168 ++++++++++----------- + .../wireless/broadcom/brcm80211/brcmfmac/sdio.h | 15 +- + 3 files changed, 146 insertions(+), 152 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -118,7 +118,7 @@ int brcmf_sdiod_intr_register(struct brc + + ret = request_irq(pdata->oob_irq_nr, brcmf_sdiod_oob_irqhandler, + pdata->oob_irq_flags, "brcmf_oob_intr", +- &sdiodev->func[1]->dev); ++ &sdiodev->func1->dev); + if (ret != 0) { + brcmf_err("request_irq failed %d\n", ret); + return ret; +@@ -132,7 +132,7 @@ int brcmf_sdiod_intr_register(struct brc + } + sdiodev->irq_wake = true; + +- sdio_claim_host(sdiodev->func[1]); ++ sdio_claim_host(sdiodev->func1); + + if (sdiodev->bus_if->chip == BRCM_CC_43362_CHIP_ID) { + /* assign GPIO to SDIO core */ +@@ -159,13 +159,13 @@ int brcmf_sdiod_intr_register(struct brc + data |= SDIO_CCCR_BRCM_SEPINT_ACT_HI; + brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_SEPINT, + data, &ret); +- sdio_release_host(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func1); + } else { + brcmf_dbg(SDIO, "Entering\n"); +- sdio_claim_host(sdiodev->func[1]); +- sdio_claim_irq(sdiodev->func[1], brcmf_sdiod_ib_irqhandler); +- sdio_claim_irq(sdiodev->func[2], brcmf_sdiod_dummy_irqhandler); +- sdio_release_host(sdiodev->func[1]); ++ sdio_claim_host(sdiodev->func1); ++ sdio_claim_irq(sdiodev->func1, brcmf_sdiod_ib_irqhandler); ++ sdio_claim_irq(sdiodev->func2, brcmf_sdiod_dummy_irqhandler); ++ sdio_release_host(sdiodev->func1); + sdiodev->sd_irq_requested = true; + } + +@@ -183,26 +183,26 @@ void brcmf_sdiod_intr_unregister(struct + struct brcmfmac_sdio_pd *pdata; + + pdata = &sdiodev->settings->bus.sdio; +- sdio_claim_host(sdiodev->func[1]); ++ sdio_claim_host(sdiodev->func1); + brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL); + brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, 0, NULL); +- sdio_release_host(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func1); + + sdiodev->oob_irq_requested = false; + if (sdiodev->irq_wake) { + disable_irq_wake(pdata->oob_irq_nr); + sdiodev->irq_wake = false; + } +- free_irq(pdata->oob_irq_nr, &sdiodev->func[1]->dev); ++ free_irq(pdata->oob_irq_nr, &sdiodev->func1->dev); + sdiodev->irq_en = false; + sdiodev->oob_irq_requested = false; + } + + if (sdiodev->sd_irq_requested) { +- sdio_claim_host(sdiodev->func[1]); +- sdio_release_irq(sdiodev->func[2]); +- sdio_release_irq(sdiodev->func[1]); +- sdio_release_host(sdiodev->func[1]); ++ sdio_claim_host(sdiodev->func1); ++ sdio_release_irq(sdiodev->func2); ++ sdio_release_irq(sdiodev->func1); ++ sdio_release_host(sdiodev->func1); + sdiodev->sd_irq_requested = false; + } + } +@@ -264,7 +264,7 @@ u32 brcmf_sdiod_readl(struct brcmf_sdio_ + addr &= SBSDIO_SB_OFT_ADDR_MASK; + addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + +- data = sdio_readl(sdiodev->func[1], addr, &retval); ++ data = sdio_readl(sdiodev->func1, addr, &retval); + + out: + if (ret) +@@ -285,7 +285,7 @@ void brcmf_sdiod_writel(struct brcmf_sdi + addr &= SBSDIO_SB_OFT_ADDR_MASK; + addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + +- sdio_writel(sdiodev->func[1], data, addr, &retval); ++ sdio_writel(sdiodev->func1, data, addr, &retval); + + out: + if (ret) +@@ -550,7 +550,7 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd + addr &= SBSDIO_SB_OFT_ADDR_MASK; + addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + +- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr, pkt); ++ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func2, addr, pkt); + + done: + return err; +@@ -575,13 +575,13 @@ int brcmf_sdiod_recv_chain(struct brcmf_ + addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + + if (pktq->qlen == 1) +- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr, ++ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func2, addr, + pktq->next); + else if (!sdiodev->sg_support) { + glom_skb = brcmu_pkt_buf_get_skb(totlen); + if (!glom_skb) + return -ENOMEM; +- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr, ++ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func2, addr, + glom_skb); + if (err) + goto done; +@@ -591,7 +591,7 @@ int brcmf_sdiod_recv_chain(struct brcmf_ + skb_pull(glom_skb, skb->len); + } + } else +- err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func[2], false, ++ err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func2, false, + addr, pktq); + + done: +@@ -623,7 +623,7 @@ int brcmf_sdiod_send_buf(struct brcmf_sd + addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + + if (!err) +- err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[2], addr, ++ err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func2, addr, + mypkt); + + brcmu_pkt_buf_free_skb(mypkt); +@@ -649,13 +649,13 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd + + if (pktq->qlen == 1 || !sdiodev->sg_support) { + skb_queue_walk(pktq, skb) { +- err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[2], ++ err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func2, + addr, skb); + if (err) + break; + } + } else { +- err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func[2], true, ++ err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func2, true, + addr, pktq); + } + +@@ -686,7 +686,7 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev + else + dsize = size; + +- sdio_claim_host(sdiodev->func[1]); ++ sdio_claim_host(sdiodev->func1); + + /* Do the transfer(s) */ + while (size) { +@@ -706,10 +706,10 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev + + if (write) { + memcpy(pkt->data, data, dsize); +- err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[1], ++ err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func1, + sdaddr, pkt); + } else { +- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[1], ++ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func1, + sdaddr, pkt); + } + +@@ -733,7 +733,7 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev + + dev_kfree_skb(pkt); + +- sdio_release_host(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func1); + + return err; + } +@@ -757,7 +757,7 @@ void brcmf_sdiod_sgtable_alloc(struct br + uint nents; + int err; + +- func = sdiodev->func[2]; ++ func = sdiodev->func2; + host = func->card->host; + sdiodev->sg_support = host->max_segs > 1; + max_blocks = min_t(uint, host->max_blk_count, 511u); +@@ -818,17 +818,17 @@ static int brcmf_sdiod_freezer_on(struct + brcmf_sdio_trigger_dpc(sdiodev->bus); + wait_event(sdiodev->freezer->thread_freeze, + atomic_read(expect) == sdiodev->freezer->frozen_count); +- sdio_claim_host(sdiodev->func[1]); ++ sdio_claim_host(sdiodev->func1); + res = brcmf_sdio_sleep(sdiodev->bus, true); +- sdio_release_host(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func1); + return res; + } + + static void brcmf_sdiod_freezer_off(struct brcmf_sdio_dev *sdiodev) + { +- sdio_claim_host(sdiodev->func[1]); ++ sdio_claim_host(sdiodev->func1); + brcmf_sdio_sleep(sdiodev->bus, false); +- sdio_release_host(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func1); + atomic_set(&sdiodev->freezer->freezing, 0); + complete_all(&sdiodev->freezer->resumed); + } +@@ -878,19 +878,19 @@ static int brcmf_sdiod_remove(struct brc + brcmf_sdiod_freezer_detach(sdiodev); + + /* Disable Function 2 */ +- sdio_claim_host(sdiodev->func[2]); +- sdio_disable_func(sdiodev->func[2]); +- sdio_release_host(sdiodev->func[2]); ++ sdio_claim_host(sdiodev->func2); ++ sdio_disable_func(sdiodev->func2); ++ sdio_release_host(sdiodev->func2); + + /* Disable Function 1 */ +- sdio_claim_host(sdiodev->func[1]); +- sdio_disable_func(sdiodev->func[1]); +- sdio_release_host(sdiodev->func[1]); ++ sdio_claim_host(sdiodev->func1); ++ sdio_disable_func(sdiodev->func1); ++ sdio_release_host(sdiodev->func1); + + sg_free_table(&sdiodev->sgtable); + sdiodev->sbwad = 0; + +- pm_runtime_allow(sdiodev->func[1]->card->host->parent); ++ pm_runtime_allow(sdiodev->func1->card->host->parent); + return 0; + } + +@@ -906,29 +906,27 @@ static int brcmf_sdiod_probe(struct brcm + { + int ret = 0; + +- sdiodev->num_funcs = 2; ++ sdio_claim_host(sdiodev->func1); + +- sdio_claim_host(sdiodev->func[1]); +- +- ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE); ++ ret = sdio_set_block_size(sdiodev->func1, SDIO_FUNC1_BLOCKSIZE); + if (ret) { + brcmf_err("Failed to set F1 blocksize\n"); +- sdio_release_host(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func1); + goto out; + } +- ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE); ++ ret = sdio_set_block_size(sdiodev->func2, SDIO_FUNC2_BLOCKSIZE); + if (ret) { + brcmf_err("Failed to set F2 blocksize\n"); +- sdio_release_host(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func1); + goto out; + } + + /* increase F2 timeout */ +- sdiodev->func[2]->enable_timeout = SDIO_WAIT_F2RDY; ++ sdiodev->func2->enable_timeout = SDIO_WAIT_F2RDY; + + /* Enable Function 1 */ +- ret = sdio_enable_func(sdiodev->func[1]); +- sdio_release_host(sdiodev->func[1]); ++ ret = sdio_enable_func(sdiodev->func1); ++ sdio_release_host(sdiodev->func1); + if (ret) { + brcmf_err("Failed to enable F1: err=%d\n", ret); + goto out; +@@ -944,7 +942,7 @@ static int brcmf_sdiod_probe(struct brcm + ret = -ENODEV; + goto out; + } +- brcmf_sdiod_host_fixup(sdiodev->func[2]->card->host); ++ brcmf_sdiod_host_fixup(sdiodev->func2->card->host); + out: + if (ret) + brcmf_sdiod_remove(sdiodev); +@@ -1032,16 +1030,15 @@ static int brcmf_ops_sdio_probe(struct s + /* store refs to functions used. mmc_card does + * not hold the F0 function pointer. + */ +- sdiodev->func[0] = NULL; +- sdiodev->func[1] = func->card->sdio_func[0]; +- sdiodev->func[2] = func; ++ sdiodev->func1 = func->card->sdio_func[0]; ++ sdiodev->func2 = func; + + sdiodev->bus_if = bus_if; + bus_if->bus_priv.sdio = sdiodev; + bus_if->proto_type = BRCMF_PROTO_BCDC; + dev_set_drvdata(&func->dev, bus_if); +- dev_set_drvdata(&sdiodev->func[1]->dev, bus_if); +- sdiodev->dev = &sdiodev->func[1]->dev; ++ dev_set_drvdata(&sdiodev->func1->dev, bus_if); ++ sdiodev->dev = &sdiodev->func1->dev; + + brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_DOWN); + +@@ -1057,7 +1054,7 @@ static int brcmf_ops_sdio_probe(struct s + + fail: + dev_set_drvdata(&func->dev, NULL); +- dev_set_drvdata(&sdiodev->func[1]->dev, NULL); ++ dev_set_drvdata(&sdiodev->func1->dev, NULL); + kfree(sdiodev); + kfree(bus_if); + return err; +@@ -1086,8 +1083,8 @@ static void brcmf_ops_sdio_remove(struct + /* only proceed with rest of cleanup if func 1 */ + brcmf_sdiod_remove(sdiodev); + +- dev_set_drvdata(&sdiodev->func[1]->dev, NULL); +- dev_set_drvdata(&sdiodev->func[2]->dev, NULL); ++ dev_set_drvdata(&sdiodev->func1->dev, NULL); ++ dev_set_drvdata(&sdiodev->func2->dev, NULL); + + kfree(bus_if); + kfree(sdiodev); +@@ -1132,7 +1129,7 @@ static int brcmf_ops_sdio_suspend(struct + else + sdio_flags |= MMC_PM_WAKE_SDIO_IRQ; + } +- if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags)) ++ if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags)) + brcmf_err("Failed to set pm_flags %x\n", sdio_flags); + return 0; + } +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -979,7 +979,7 @@ static int brcmf_sdio_readshared(struct + struct sdpcm_shared_le sh_le; + __le32 addr_le; + +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + brcmf_sdio_bus_sleep(bus, false, false); + + /* +@@ -1013,7 +1013,7 @@ static int brcmf_sdio_readshared(struct + if (rv < 0) + goto fail; + +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + + /* Endianness */ + sh->flags = le32_to_cpu(sh_le.flags); +@@ -1035,7 +1035,7 @@ static int brcmf_sdio_readshared(struct + fail: + brcmf_err("unable to obtain sdpcm_shared info: rv=%d (addr=0x%x)\n", + rv, addr); +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + return rv; + } + +@@ -1157,7 +1157,7 @@ static void brcmf_sdio_rxfail(struct brc + rtx ? ", send NAK" : ""); + + if (abort) +- brcmf_sdiod_abort(bus->sdiodev, bus->sdiodev->func[2]); ++ brcmf_sdiod_abort(bus->sdiodev, bus->sdiodev->func2); + + brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, + &err); +@@ -1209,7 +1209,7 @@ static void brcmf_sdio_txfail(struct brc + brcmf_err("sdio error, abort command and terminate frame\n"); + bus->sdcnt.tx_sderrs++; + +- brcmf_sdiod_abort(sdiodev, sdiodev->func[2]); ++ brcmf_sdiod_abort(sdiodev, sdiodev->func2); + brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL); + bus->sdcnt.f1regdata++; + +@@ -1565,10 +1565,10 @@ static u8 brcmf_sdio_rxglom(struct brcmf + * read directly into the chained packet, or allocate a large + * packet and and copy into the chain. + */ +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + errcode = brcmf_sdiod_recv_chain(bus->sdiodev, + &bus->glom, dlen); +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + bus->sdcnt.f2rxdata++; + + /* On failure, kill the superframe */ +@@ -1576,11 +1576,11 @@ static u8 brcmf_sdio_rxglom(struct brcmf + brcmf_err("glom read of %d bytes failed: %d\n", + dlen, errcode); + +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + brcmf_sdio_rxfail(bus, true, false); + bus->sdcnt.rxglomfail++; + brcmf_sdio_free_glom(bus); +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + return 0; + } + +@@ -1590,10 +1590,10 @@ static u8 brcmf_sdio_rxglom(struct brcmf + + rd_new.seq_num = rxseq; + rd_new.len = dlen; +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + errcode = brcmf_sdio_hdparse(bus, pfirst->data, &rd_new, + BRCMF_SDIO_FT_SUPER); +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + bus->cur_read.len = rd_new.len_nxtfrm << 4; + + /* Remove superframe header, remember offset */ +@@ -1609,10 +1609,10 @@ static u8 brcmf_sdio_rxglom(struct brcmf + + rd_new.len = pnext->len; + rd_new.seq_num = rxseq++; +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + errcode = brcmf_sdio_hdparse(bus, pnext->data, &rd_new, + BRCMF_SDIO_FT_SUB); +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), + pnext->data, 32, "subframe:\n"); + +@@ -1621,11 +1621,11 @@ static u8 brcmf_sdio_rxglom(struct brcmf + + if (errcode) { + /* Terminate frame on error */ +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + brcmf_sdio_rxfail(bus, true, false); + bus->sdcnt.rxglomfail++; + brcmf_sdio_free_glom(bus); +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + bus->cur_read.len = 0; + return 0; + } +@@ -1833,7 +1833,7 @@ static uint brcmf_sdio_readframes(struct + + rd->len_left = rd->len; + /* read header first for unknow frame length */ +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + if (!rd->len) { + ret = brcmf_sdiod_recv_buf(bus->sdiodev, + bus->rxhdr, BRCMF_FIRSTREAD); +@@ -1843,7 +1843,7 @@ static uint brcmf_sdio_readframes(struct + ret); + bus->sdcnt.rx_hdrfail++; + brcmf_sdio_rxfail(bus, true, true); +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + continue; + } + +@@ -1853,7 +1853,7 @@ static uint brcmf_sdio_readframes(struct + + if (brcmf_sdio_hdparse(bus, bus->rxhdr, rd, + BRCMF_SDIO_FT_NORMAL)) { +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + if (!bus->rxpending) + break; + else +@@ -1869,7 +1869,7 @@ static uint brcmf_sdio_readframes(struct + rd->len_nxtfrm = 0; + /* treat all packet as event if we don't know */ + rd->channel = SDPCM_EVENT_CHANNEL; +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + continue; + } + rd->len_left = rd->len > BRCMF_FIRSTREAD ? +@@ -1886,7 +1886,7 @@ static uint brcmf_sdio_readframes(struct + brcmf_err("brcmu_pkt_buf_get_skb failed\n"); + brcmf_sdio_rxfail(bus, false, + RETRYCHAN(rd->channel)); +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + continue; + } + skb_pull(pkt, head_read); +@@ -1894,16 +1894,16 @@ static uint brcmf_sdio_readframes(struct + + ret = brcmf_sdiod_recv_pkt(bus->sdiodev, pkt); + bus->sdcnt.f2rxdata++; +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + + if (ret < 0) { + brcmf_err("read %d bytes from channel %d failed: %d\n", + rd->len, rd->channel, ret); + brcmu_pkt_buf_free_skb(pkt); +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + brcmf_sdio_rxfail(bus, true, + RETRYCHAN(rd->channel)); +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + continue; + } + +@@ -1914,7 +1914,7 @@ static uint brcmf_sdio_readframes(struct + } else { + memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN); + rd_new.seq_num = rd->seq_num; +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + if (brcmf_sdio_hdparse(bus, bus->rxhdr, &rd_new, + BRCMF_SDIO_FT_NORMAL)) { + rd->len = 0; +@@ -1927,11 +1927,11 @@ static uint brcmf_sdio_readframes(struct + roundup(rd_new.len, 16) >> 4); + rd->len = 0; + brcmf_sdio_rxfail(bus, true, true); +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + brcmu_pkt_buf_free_skb(pkt); + continue; + } +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + rd->len_nxtfrm = rd_new.len_nxtfrm; + rd->channel = rd_new.channel; + rd->dat_offset = rd_new.dat_offset; +@@ -1947,9 +1947,9 @@ static uint brcmf_sdio_readframes(struct + rd_new.seq_num); + /* Force retry w/normal header read */ + rd->len = 0; +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + brcmf_sdio_rxfail(bus, false, true); +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + brcmu_pkt_buf_free_skb(pkt); + continue; + } +@@ -1972,9 +1972,9 @@ static uint brcmf_sdio_readframes(struct + } else { + brcmf_err("%s: glom superframe w/o " + "descriptor!\n", __func__); +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + brcmf_sdio_rxfail(bus, false, false); +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + } + /* prepare the descriptor for the next read */ + rd->len = rd->len_nxtfrm << 4; +@@ -2072,7 +2072,7 @@ static int brcmf_sdio_txpkt_prep_sg(stru + int ntail, ret; + + sdiodev = bus->sdiodev; +- blksize = sdiodev->func[2]->cur_blksize; ++ blksize = sdiodev->func2->cur_blksize; + /* sg entry alignment should be a divisor of block size */ + WARN_ON(blksize % bus->sgentry_align); + +@@ -2251,14 +2251,14 @@ static int brcmf_sdio_txpkt(struct brcmf + if (ret) + goto done; + +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + ret = brcmf_sdiod_send_pkt(bus->sdiodev, pktq); + bus->sdcnt.f2txdata++; + + if (ret < 0) + brcmf_sdio_txfail(bus); + +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + + done: + brcmf_sdio_txpkt_postp(bus, pktq); +@@ -2314,10 +2314,11 @@ static uint brcmf_sdio_sendfromq(struct + /* In poll mode, need to check for other events */ + if (!bus->intr) { + /* Check device status, signal pending interrupt */ +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + intstatus = brcmf_sdiod_readl(bus->sdiodev, + intstat_addr, &ret); +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); ++ + bus->sdcnt.f2txdata++; + if (ret != 0) + break; +@@ -2417,7 +2418,7 @@ static void brcmf_sdio_bus_stop(struct d + } + + if (sdiodev->state != BRCMF_SDIOD_NOMEDIUM) { +- sdio_claim_host(sdiodev->func[1]); ++ sdio_claim_host(sdiodev->func1); + + /* Enable clock for device interrupts */ + brcmf_sdio_bus_sleep(bus, false, false); +@@ -2441,13 +2442,13 @@ static void brcmf_sdio_bus_stop(struct d + + /* Turn off the bus (F2), free any pending packets */ + brcmf_dbg(INTR, "disable SDIO interrupts\n"); +- sdio_disable_func(sdiodev->func[2]); ++ sdio_disable_func(sdiodev->func2); + + /* Clear any pending interrupts now that F2 is disabled */ + brcmf_sdiod_writel(sdiodev, core->base + SD_REG(intstatus), + local_hostintmask, NULL); + +- sdio_release_host(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func1); + } + /* Clear the data packet queues */ + brcmu_pktq_flush(&bus->txq, true, NULL, NULL); +@@ -2522,7 +2523,7 @@ static void brcmf_sdio_dpc(struct brcmf_ + + brcmf_dbg(TRACE, "Enter\n"); + +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + + /* If waiting for HTAVAIL, check status */ + if (!bus->sr_enabled && bus->clkstate == CLK_PENDING) { +@@ -2585,7 +2586,7 @@ static void brcmf_sdio_dpc(struct brcmf_ + intstatus |= brcmf_sdio_hostmail(bus); + } + +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + + /* Generally don't ask for these, can get CRC errors... */ + if (intstatus & I_WR_OOSYNC) { +@@ -2628,7 +2629,7 @@ static void brcmf_sdio_dpc(struct brcmf_ + + if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) && + data_ok(bus)) { +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + if (bus->ctrl_frame_stat) { + err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, + bus->ctrl_frame_len); +@@ -2636,7 +2637,7 @@ static void brcmf_sdio_dpc(struct brcmf_ + wmb(); + bus->ctrl_frame_stat = false; + } +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + brcmf_sdio_wait_event_wakeup(bus); + } + /* Send queued frames (limit 1 if rx may still be pending) */ +@@ -2652,14 +2653,14 @@ static void brcmf_sdio_dpc(struct brcmf_ + brcmf_err("failed backplane access over SDIO, halting operation\n"); + atomic_set(&bus->intstatus, 0); + if (bus->ctrl_frame_stat) { +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + if (bus->ctrl_frame_stat) { + bus->ctrl_frame_err = -ENODEV; + wmb(); + bus->ctrl_frame_stat = false; + brcmf_sdio_wait_event_wakeup(bus); + } +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + } + } else if (atomic_read(&bus->intstatus) || + atomic_read(&bus->ipend) > 0 || +@@ -2874,13 +2875,13 @@ brcmf_sdio_bus_txctl(struct device *dev, + CTL_DONE_TIMEOUT); + ret = 0; + if (bus->ctrl_frame_stat) { +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + if (bus->ctrl_frame_stat) { + brcmf_dbg(SDIO, "ctrl_frame timeout\n"); + bus->ctrl_frame_stat = false; + ret = -ETIMEDOUT; + } +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + } + if (!ret) { + brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n", +@@ -3004,7 +3005,7 @@ static int brcmf_sdio_assert_info(struct + return 0; + } + +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + if (sh->assert_file_addr != 0) { + error = brcmf_sdiod_ramrw(bus->sdiodev, false, + sh->assert_file_addr, (u8 *)file, 80); +@@ -3017,7 +3018,7 @@ static int brcmf_sdio_assert_info(struct + if (error < 0) + return error; + } +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + + seq_printf(seq, "dongle assert: %s:%d: assert(%s)\n", + file, sh->assert_line, expr); +@@ -3291,7 +3292,7 @@ static int brcmf_sdio_download_firmware( + int bcmerror; + u32 rstvec; + +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + brcmf_sdio_clkctl(bus, CLK_AVAIL, false); + + rstvec = get_unaligned_le32(fw->data); +@@ -3320,7 +3321,7 @@ static int brcmf_sdio_download_firmware( + + err: + brcmf_sdio_clkctl(bus, CLK_SDONLY, false); +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + return bcmerror; + } + +@@ -3435,7 +3436,7 @@ static int brcmf_sdio_bus_preinit(struct + if (sdiodev->sg_support) { + bus->txglom = false; + value = 1; +- pad_size = bus->sdiodev->func[2]->cur_blksize << 1; ++ pad_size = bus->sdiodev->func2->cur_blksize << 1; + err = brcmf_iovar_data_set(bus->sdiodev->dev, "bus:rxglom", + &value, sizeof(u32)); + if (err < 0) { +@@ -3477,7 +3478,7 @@ static int brcmf_sdio_bus_get_memdump(st + + address = bus->ci->rambase; + offset = err = 0; +- sdio_claim_host(sdiodev->func[1]); ++ sdio_claim_host(sdiodev->func1); + while (offset < mem_size) { + len = ((offset + MEMBLOCK) < mem_size) ? MEMBLOCK : + mem_size - offset; +@@ -3493,7 +3494,7 @@ static int brcmf_sdio_bus_get_memdump(st + } + + done: +- sdio_release_host(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func1); + return err; + } + +@@ -3550,11 +3551,10 @@ static void brcmf_sdio_bus_watchdog(stru + if (!bus->dpc_triggered) { + u8 devpend; + +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + devpend = brcmf_sdiod_func0_rb(bus->sdiodev, +- SDIO_CCCR_INTx, +- NULL); +- sdio_release_host(bus->sdiodev->func[1]); ++ SDIO_CCCR_INTx, NULL); ++ sdio_release_host(bus->sdiodev->func1); + intstatus = devpend & (INTR_STATUS_FUNC1 | + INTR_STATUS_FUNC2); + } +@@ -3580,13 +3580,13 @@ static void brcmf_sdio_bus_watchdog(stru + bus->console.count += jiffies_to_msecs(BRCMF_WD_POLL); + if (bus->console.count >= bus->console_interval) { + bus->console.count -= bus->console_interval; +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + /* Make sure backplane clock is on */ + brcmf_sdio_bus_sleep(bus, false, false); + if (brcmf_sdio_readconsole(bus) < 0) + /* stop on error */ + bus->console_interval = 0; +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + } + } + #endif /* DEBUG */ +@@ -3599,11 +3599,11 @@ static void brcmf_sdio_bus_watchdog(stru + bus->idlecount++; + if (bus->idlecount > bus->idletime) { + brcmf_dbg(SDIO, "idle\n"); +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + brcmf_sdio_wd_timer(bus, false); + bus->idlecount = 0; + brcmf_sdio_bus_sleep(bus, true, false); +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + } + } else { + bus->idlecount = 0; +@@ -3773,8 +3773,8 @@ static u32 brcmf_sdio_buscore_read32(voi + val = brcmf_sdiod_readl(sdiodev, addr, NULL); + + if (addr == CORE_CC_REG(SI_ENUM_BASE, chipid) && +- (sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4339 || +- sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339)) { ++ (sdiodev->func1->device == SDIO_DEVICE_ID_BROADCOM_4339 || ++ sdiodev->func1->device == SDIO_DEVICE_ID_BROADCOM_4335_4339)) { + rev = (val & CID_REV_MASK) >> CID_REV_SHIFT; + if (rev >= 2) { + val &= ~CID_ID_MASK; +@@ -3810,7 +3810,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdi + u32 drivestrength; + + sdiodev = bus->sdiodev; +- sdio_claim_host(sdiodev->func[1]); ++ sdio_claim_host(sdiodev->func1); + + pr_debug("F1 signature read @0x18000000=0x%4x\n", + brcmf_sdiod_readl(sdiodev, SI_ENUM_BASE, NULL)); +@@ -3877,8 +3877,8 @@ brcmf_sdio_probe_attach(struct brcmf_sdi + /* wowl can be supported when KEEP_POWER is true and (WAKE_SDIO_IRQ + * is true or when platform data OOB irq is true). + */ +- if ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_KEEP_POWER) && +- ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_WAKE_SDIO_IRQ) || ++ if ((sdio_get_host_pm_caps(sdiodev->func1) & MMC_PM_KEEP_POWER) && ++ ((sdio_get_host_pm_caps(sdiodev->func1) & MMC_PM_WAKE_SDIO_IRQ) || + (sdiodev->settings->bus.sdio.oob_irq_supported))) + sdiodev->bus_if->wowl_supported = true; + #endif +@@ -3917,7 +3917,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdi + if (err) + goto fail; + +- sdio_release_host(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func1); + + brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN); + +@@ -3938,7 +3938,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdi + return true; + + fail: +- sdio_release_host(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func1); + return false; + } + +@@ -4044,7 +4044,7 @@ static void brcmf_sdio_firmware_callback + bus->sdcnt.tickcnt = 0; + brcmf_sdio_wd_timer(bus, true); + +- sdio_claim_host(sdiodev->func[1]); ++ sdio_claim_host(sdiodev->func1); + + /* Make sure backplane clock is on, needed to generate F2 interrupt */ + brcmf_sdio_clkctl(bus, CLK_AVAIL, false); +@@ -4066,7 +4066,7 @@ static void brcmf_sdio_firmware_callback + brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailboxdata), + SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, NULL); + +- err = sdio_enable_func(sdiodev->func[2]); ++ err = sdio_enable_func(sdiodev->func2); + + brcmf_dbg(INFO, "enable F2: err=%d\n", err); + +@@ -4081,7 +4081,7 @@ static void brcmf_sdio_firmware_callback + brcmf_sdiod_writeb(sdiodev, SBSDIO_WATERMARK, 8, &err); + } else { + /* Disable F2 again */ +- sdio_disable_func(sdiodev->func[2]); ++ sdio_disable_func(sdiodev->func2); + goto release; + } + +@@ -4106,7 +4106,7 @@ static void brcmf_sdio_firmware_callback + if (err != 0) + brcmf_sdio_clkctl(bus, CLK_NONE, false); + +- sdio_release_host(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func1); + + err = brcmf_bus_started(dev); + if (err != 0) { +@@ -4116,10 +4116,10 @@ static void brcmf_sdio_firmware_callback + return; + + release: +- sdio_release_host(sdiodev->func[1]); ++ sdio_release_host(sdiodev->func1); + fail: + brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err); +- device_release_driver(&sdiodev->func[2]->dev); ++ device_release_driver(&sdiodev->func2->dev); + device_release_driver(dev); + } + +@@ -4146,7 +4146,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru + + /* single-threaded workqueue */ + wq = alloc_ordered_workqueue("brcmf_wq/%s", WQ_MEM_RECLAIM, +- dev_name(&sdiodev->func[1]->dev)); ++ dev_name(&sdiodev->func1->dev)); + if (!wq) { + brcmf_err("insufficient memory to create txworkqueue\n"); + goto fail; +@@ -4173,7 +4173,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru + init_completion(&bus->watchdog_wait); + bus->watchdog_tsk = kthread_run(brcmf_sdio_watchdog_thread, + bus, "brcmf_wdog/%s", +- dev_name(&sdiodev->func[1]->dev)); ++ dev_name(&sdiodev->func1->dev)); + if (IS_ERR(bus->watchdog_tsk)) { + pr_warn("brcmf_watchdog thread failed to start\n"); + bus->watchdog_tsk = NULL; +@@ -4199,7 +4199,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru + } + + /* Query the F2 block size, set roundup accordingly */ +- bus->blocksize = bus->sdiodev->func[2]->cur_blksize; ++ bus->blocksize = bus->sdiodev->func2->cur_blksize; + bus->roundup = min(max_roundup, bus->blocksize); + + /* Allocate buffers */ +@@ -4215,17 +4215,17 @@ struct brcmf_sdio *brcmf_sdio_probe(stru + } + } + +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + + /* Disable F2 to clear any intermediate frame state on the dongle */ +- sdio_disable_func(bus->sdiodev->func[2]); ++ sdio_disable_func(bus->sdiodev->func2); + + bus->rxflow = false; + + /* Done with backplane-dependent accesses, can drop clock... */ + brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); + +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + + /* ...and initialize clock/power states */ + bus->clkstate = CLK_SDONLY; +@@ -4277,7 +4277,7 @@ void brcmf_sdio_remove(struct brcmf_sdio + + if (bus->ci) { + if (bus->sdiodev->state != BRCMF_SDIOD_NOMEDIUM) { +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + brcmf_sdio_wd_timer(bus, false); + brcmf_sdio_clkctl(bus, CLK_AVAIL, false); + /* Leave the device in state where it is +@@ -4287,7 +4287,7 @@ void brcmf_sdio_remove(struct brcmf_sdio + msleep(20); + brcmf_chip_set_passive(bus->ci); + brcmf_sdio_clkctl(bus, CLK_NONE, false); +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + } + brcmf_chip_detach(bus->ci); + } +@@ -4334,9 +4334,9 @@ int brcmf_sdio_sleep(struct brcmf_sdio * + { + int ret; + +- sdio_claim_host(bus->sdiodev->func[1]); ++ sdio_claim_host(bus->sdiodev->func1); + ret = brcmf_sdio_bus_sleep(bus, sleep, false); +- sdio_release_host(bus->sdiodev->func[1]); ++ sdio_release_host(bus->sdiodev->func1); + + return ret; + } +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +@@ -21,9 +21,6 @@ + #include + #include "firmware.h" + +-/* Maximum number of I/O funcs */ +-#define NUM_SDIO_FUNCS 3 +- + #define SDIOD_FBR_SIZE 0x100 + + /* io_en */ +@@ -173,8 +170,8 @@ struct brcmf_sdio; + struct brcmf_sdiod_freezer; + + struct brcmf_sdio_dev { +- struct sdio_func *func[NUM_SDIO_FUNCS]; +- u8 num_funcs; /* Supported funcs on client */ ++ struct sdio_func *func1; ++ struct sdio_func *func2; + u32 sbwad; /* Save backplane window address */ + struct brcmf_core *cc_core; /* chipcommon core info struct */ + struct brcmf_sdio *bus; +@@ -295,17 +292,17 @@ void brcmf_sdiod_intr_unregister(struct + /* SDIO device register access interface */ + /* Accessors for SDIO Function 0 */ + #define brcmf_sdiod_func0_rb(sdiodev, addr, r) \ +- sdio_f0_readb((sdiodev)->func[1], (addr), (r)) ++ sdio_f0_readb((sdiodev)->func1, (addr), (r)) + + #define brcmf_sdiod_func0_wb(sdiodev, addr, v, ret) \ +- sdio_f0_writeb((sdiodev)->func[1], (v), (addr), (ret)) ++ sdio_f0_writeb((sdiodev)->func1, (v), (addr), (ret)) + + /* Accessors for SDIO Function 1 */ + #define brcmf_sdiod_readb(sdiodev, addr, r) \ +- sdio_readb((sdiodev)->func[1], (addr), (r)) ++ sdio_readb((sdiodev)->func1, (addr), (r)) + + #define brcmf_sdiod_writeb(sdiodev, addr, v, ret) \ +- sdio_writeb((sdiodev)->func[1], (v), (addr), (ret)) ++ sdio_writeb((sdiodev)->func1, (v), (addr), (ret)) + + u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); + void brcmf_sdiod_writel(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data, diff --git a/package/kernel/mac80211/patches/316-v4.16-0002-brcmfmac-add-comment-block-in-brcmf_sdio_buscore_rea.patch b/package/kernel/mac80211/patches/316-v4.16-0002-brcmfmac-add-comment-block-in-brcmf_sdio_buscore_rea.patch new file mode 100644 index 000000000..dc78000be --- /dev/null +++ b/package/kernel/mac80211/patches/316-v4.16-0002-brcmfmac-add-comment-block-in-brcmf_sdio_buscore_rea.patch @@ -0,0 +1,31 @@ +From 32adbcaa5df49f1977441f7a4bf180a0bcfe9966 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Tue, 9 Jan 2018 13:22:53 +0100 +Subject: [PATCH] brcmfmac: add comment block in brcmf_sdio_buscore_read() + +In brcmf_sdio_buscore_read() there is some special handling upon +register access to chipid register of the chipcommon core. Add +comment explaining why it is done here. + +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -3772,6 +3772,13 @@ static u32 brcmf_sdio_buscore_read32(voi + + val = brcmf_sdiod_readl(sdiodev, addr, NULL); + ++ /* ++ * this is a bit of special handling if reading the chipcommon chipid ++ * register. The 4339 is a next-gen of the 4335. It uses the same ++ * SDIO device id as 4335 and the chipid register returns 4335 as well. ++ * It can be identified as 4339 by looking at the chip revision. It ++ * is corrected here so the chip.c module has the right info. ++ */ + if (addr == CORE_CC_REG(SI_ENUM_BASE, chipid) && + (sdiodev->func1->device == SDIO_DEVICE_ID_BROADCOM_4339 || + sdiodev->func1->device == SDIO_DEVICE_ID_BROADCOM_4335_4339)) { diff --git a/package/kernel/mac80211/patches/316-v4.16-0003-brcmfmac-rename-brcmf_sdiod_buff_-read-write-functio.patch b/package/kernel/mac80211/patches/316-v4.16-0003-brcmfmac-rename-brcmf_sdiod_buff_-read-write-functio.patch new file mode 100644 index 000000000..c587f413d --- /dev/null +++ b/package/kernel/mac80211/patches/316-v4.16-0003-brcmfmac-rename-brcmf_sdiod_buff_-read-write-functio.patch @@ -0,0 +1,137 @@ +From 378f6a16043e5d3346301fc618f503e97aea335b Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Tue, 9 Jan 2018 13:22:54 +0100 +Subject: [PATCH] brcmfmac: rename brcmf_sdiod_buff_{read,write}() functions + +Rename functions to brcmf_sdio_skbuff_{read,write}() as we pass an +skbuff to this function. + +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 48 +++++++++++----------- + 1 file changed, 24 insertions(+), 24 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -292,24 +292,24 @@ out: + *ret = retval; + } + +-static int brcmf_sdiod_buff_read(struct brcmf_sdio_dev *sdiodev, +- struct sdio_func *func, u32 addr, +- struct sk_buff *pkt) ++static int brcmf_sdiod_skbuff_read(struct brcmf_sdio_dev *sdiodev, ++ struct sdio_func *func, u32 addr, ++ struct sk_buff *skb) + { + unsigned int req_sz; + int err; + + /* Single skb use the standard mmc interface */ +- req_sz = pkt->len + 3; ++ req_sz = skb->len + 3; + req_sz &= (uint)~3; + + switch (func->num) { + case 1: +- err = sdio_memcpy_fromio(func, ((u8 *)(pkt->data)), addr, ++ err = sdio_memcpy_fromio(func, ((u8 *)(skb->data)), addr, + req_sz); + break; + case 2: +- err = sdio_readsb(func, ((u8 *)(pkt->data)), addr, req_sz); ++ err = sdio_readsb(func, ((u8 *)(skb->data)), addr, req_sz); + break; + default: + /* bail out as things are really fishy here */ +@@ -323,18 +323,18 @@ static int brcmf_sdiod_buff_read(struct + return err; + } + +-static int brcmf_sdiod_buff_write(struct brcmf_sdio_dev *sdiodev, +- struct sdio_func *func, u32 addr, +- struct sk_buff *pkt) ++static int brcmf_sdiod_skbuff_write(struct brcmf_sdio_dev *sdiodev, ++ struct sdio_func *func, u32 addr, ++ struct sk_buff *skb) + { + unsigned int req_sz; + int err; + + /* Single skb use the standard mmc interface */ +- req_sz = pkt->len + 3; ++ req_sz = skb->len + 3; + req_sz &= (uint)~3; + +- err = sdio_memcpy_toio(func, addr, ((u8 *)(pkt->data)), req_sz); ++ err = sdio_memcpy_toio(func, addr, ((u8 *)(skb->data)), req_sz); + + if (err == -ENOMEDIUM) + brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM); +@@ -550,7 +550,7 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd + addr &= SBSDIO_SB_OFT_ADDR_MASK; + addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + +- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func2, addr, pkt); ++ err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func2, addr, pkt); + + done: + return err; +@@ -575,14 +575,14 @@ int brcmf_sdiod_recv_chain(struct brcmf_ + addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + + if (pktq->qlen == 1) +- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func2, addr, +- pktq->next); ++ err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func2, addr, ++ pktq->next); + else if (!sdiodev->sg_support) { + glom_skb = brcmu_pkt_buf_get_skb(totlen); + if (!glom_skb) + return -ENOMEM; +- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func2, addr, +- glom_skb); ++ err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func2, addr, ++ glom_skb); + if (err) + goto done; + +@@ -623,8 +623,8 @@ int brcmf_sdiod_send_buf(struct brcmf_sd + addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + + if (!err) +- err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func2, addr, +- mypkt); ++ err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func2, addr, ++ mypkt); + + brcmu_pkt_buf_free_skb(mypkt); + +@@ -649,8 +649,8 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd + + if (pktq->qlen == 1 || !sdiodev->sg_support) { + skb_queue_walk(pktq, skb) { +- err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func2, +- addr, skb); ++ err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func2, ++ addr, skb); + if (err) + break; + } +@@ -706,11 +706,11 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev + + if (write) { + memcpy(pkt->data, data, dsize); +- err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func1, +- sdaddr, pkt); ++ err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func1, ++ sdaddr, pkt); + } else { +- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func1, +- sdaddr, pkt); ++ err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func1, ++ sdaddr, pkt); + } + + if (err) { diff --git a/package/kernel/mac80211/patches/317-v4.16-0001-brcmfmac-Use-zeroing-memory-allocator-than-allocator.patch b/package/kernel/mac80211/patches/317-v4.16-0001-brcmfmac-Use-zeroing-memory-allocator-than-allocator.patch new file mode 100644 index 000000000..b60c81a3a --- /dev/null +++ b/package/kernel/mac80211/patches/317-v4.16-0001-brcmfmac-Use-zeroing-memory-allocator-than-allocator.patch @@ -0,0 +1,59 @@ +From b7acadaf038740c43515dc1548f43d01cc92823a Mon Sep 17 00:00:00 2001 +From: Himanshu Jha +Date: Tue, 9 Jan 2018 02:15:31 +0530 +Subject: [PATCH] brcmfmac: Use zeroing memory allocator than allocator/memset + +Use dma_zalloc_coherent for allocating zeroed +memory and remove unnecessary memset function. + +Generated-by: scripts/coccinelle/api/alloc/kzalloc-simple.cocci + +Suggested-by: Luis R. Rodriguez +Signed-off-by: Himanshu Jha +Signed-off-by: Kalle Valo +--- + .../net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -1251,14 +1251,14 @@ static int brcmf_pcie_init_scratchbuffer + u64 address; + u32 addr; + +- devinfo->shared.scratch = dma_alloc_coherent(&devinfo->pdev->dev, +- BRCMF_DMA_D2H_SCRATCH_BUF_LEN, +- &devinfo->shared.scratch_dmahandle, GFP_KERNEL); ++ devinfo->shared.scratch = ++ dma_zalloc_coherent(&devinfo->pdev->dev, ++ BRCMF_DMA_D2H_SCRATCH_BUF_LEN, ++ &devinfo->shared.scratch_dmahandle, ++ GFP_KERNEL); + if (!devinfo->shared.scratch) + goto fail; + +- memset(devinfo->shared.scratch, 0, BRCMF_DMA_D2H_SCRATCH_BUF_LEN); +- + addr = devinfo->shared.tcm_base_address + + BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET; + address = (u64)devinfo->shared.scratch_dmahandle; +@@ -1268,14 +1268,14 @@ static int brcmf_pcie_init_scratchbuffer + BRCMF_SHARED_DMA_SCRATCH_LEN_OFFSET; + brcmf_pcie_write_tcm32(devinfo, addr, BRCMF_DMA_D2H_SCRATCH_BUF_LEN); + +- devinfo->shared.ringupd = dma_alloc_coherent(&devinfo->pdev->dev, +- BRCMF_DMA_D2H_RINGUPD_BUF_LEN, +- &devinfo->shared.ringupd_dmahandle, GFP_KERNEL); ++ devinfo->shared.ringupd = ++ dma_zalloc_coherent(&devinfo->pdev->dev, ++ BRCMF_DMA_D2H_RINGUPD_BUF_LEN, ++ &devinfo->shared.ringupd_dmahandle, ++ GFP_KERNEL); + if (!devinfo->shared.ringupd) + goto fail; + +- memset(devinfo->shared.ringupd, 0, BRCMF_DMA_D2H_RINGUPD_BUF_LEN); +- + addr = devinfo->shared.tcm_base_address + + BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET; + address = (u64)devinfo->shared.ringupd_dmahandle; diff --git a/package/kernel/mac80211/patches/318-v4.17-mac80211-round-IEEE80211_TX_STATUS_HEADROOM-up-to-mu.patch b/package/kernel/mac80211/patches/318-v4.17-mac80211-round-IEEE80211_TX_STATUS_HEADROOM-up-to-mu.patch new file mode 100644 index 000000000..e955cb3a2 --- /dev/null +++ b/package/kernel/mac80211/patches/318-v4.17-mac80211-round-IEEE80211_TX_STATUS_HEADROOM-up-to-mu.patch @@ -0,0 +1,26 @@ +From: Felix Fietkau +Date: Fri, 9 Feb 2018 19:46:54 +0100 +Subject: [PATCH] mac80211: round IEEE80211_TX_STATUS_HEADROOM up to multiple + of 4 + +This ensures that mac80211 allocated management frames are properly +aligned, which makes copying them more efficient. +For instance, mt76 uses iowrite32_copy to copy beacon frames to beacon +template memory on the chip. +Misaligned 32-bit accesses cause CPU exceptions on MIPS and should be +avoided. + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -4145,7 +4145,7 @@ void ieee80211_sta_uapsd_trigger(struct + * The TX headroom reserved by mac80211 for its own tx_status functions. + * This is enough for the radiotap header. + */ +-#define IEEE80211_TX_STATUS_HEADROOM 14 ++#define IEEE80211_TX_STATUS_HEADROOM ALIGN(14, 4) + + /** + * ieee80211_sta_set_buffered - inform mac80211 about driver-buffered frames diff --git a/package/kernel/mac80211/patches/319-v4.17-0001-mac80211-drop-frames-with-unexpected-DS-bits-from-fa.patch b/package/kernel/mac80211/patches/319-v4.17-0001-mac80211-drop-frames-with-unexpected-DS-bits-from-fa.patch new file mode 100644 index 000000000..a7562996b --- /dev/null +++ b/package/kernel/mac80211/patches/319-v4.17-0001-mac80211-drop-frames-with-unexpected-DS-bits-from-fa.patch @@ -0,0 +1,21 @@ +From: Felix Fietkau +Date: Fri, 23 Feb 2018 09:59:35 +0100 +Subject: [PATCH] mac80211: drop frames with unexpected DS bits from + fast-rx to slow path + +Fixes rx for 4-addr packets in AP mode + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -3928,7 +3928,7 @@ static bool ieee80211_invoke_fast_rx(str + if ((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_FROMDS | + IEEE80211_FCTL_TODS)) != + fast_rx->expected_ds_bits) +- goto drop; ++ return false; + + /* assign the key to drop unencrypted frames (later) + * and strip the IV/MIC if necessary diff --git a/package/kernel/mac80211/patches/319-v4.17-0002-mac80211-support-AP-4-addr-mode-fast-rx.patch b/package/kernel/mac80211/patches/319-v4.17-0002-mac80211-support-AP-4-addr-mode-fast-rx.patch new file mode 100644 index 000000000..3f3eb0a5e --- /dev/null +++ b/package/kernel/mac80211/patches/319-v4.17-0002-mac80211-support-AP-4-addr-mode-fast-rx.patch @@ -0,0 +1,25 @@ +From: Felix Fietkau +Date: Fri, 23 Feb 2018 10:00:22 +0100 +Subject: [PATCH] mac80211: support AP 4-addr mode fast-rx + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -3774,6 +3774,15 @@ void ieee80211_check_fast_rx(struct sta_ + !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && + (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || + !sdata->u.vlan.sta); ++ ++ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && ++ sdata->u.vlan.sta) { ++ fastrx.expected_ds_bits |= ++ cpu_to_le16(IEEE80211_FCTL_FROMDS); ++ fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr4); ++ fastrx.internal_forward = 0; ++ } ++ + break; + default: + goto clear; diff --git a/package/kernel/mac80211/patches/319-v4.17-0003-mac80211-support-fast-rx-with-incompatible-PS-capabi.patch b/package/kernel/mac80211/patches/319-v4.17-0003-mac80211-support-fast-rx-with-incompatible-PS-capabi.patch new file mode 100644 index 000000000..8c4c724ef --- /dev/null +++ b/package/kernel/mac80211/patches/319-v4.17-0003-mac80211-support-fast-rx-with-incompatible-PS-capabi.patch @@ -0,0 +1,53 @@ +From: Felix Fietkau +Date: Fri, 23 Feb 2018 10:01:53 +0100 +Subject: [PATCH] mac80211: support fast-rx with incompatible PS + capabilities when PS is disabled + +When powersave is disabled for the interface, we can do fast-rx anyway. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -2658,6 +2658,7 @@ static int ieee80211_set_power_mgmt(stru + + ieee80211_recalc_ps(local); + ieee80211_recalc_ps_vif(sdata); ++ ieee80211_check_fast_rx_iface(sdata); + + return 0; + } +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -3741,12 +3741,7 @@ void ieee80211_check_fast_rx(struct sta_ + /* 4-addr is harder to deal with, later maybe */ + if (sdata->u.mgd.use_4addr) + goto clear; +- /* software powersave is a huge mess, avoid all of it */ +- if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK)) +- goto clear; +- if (ieee80211_hw_check(&local->hw, SUPPORTS_PS) && +- !ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS)) +- goto clear; ++ + if (sta->sta.tdls) { + fastrx.da_offs = offsetof(struct ieee80211_hdr, addr1); + fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr2); +@@ -3758,6 +3753,16 @@ void ieee80211_check_fast_rx(struct sta_ + fastrx.expected_ds_bits = + cpu_to_le16(IEEE80211_FCTL_FROMDS); + } ++ ++ if (!sdata->u.mgd.powersave) ++ break; ++ ++ /* software powersave is a huge mess, avoid all of it */ ++ if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK)) ++ goto clear; ++ if (ieee80211_hw_check(&local->hw, SUPPORTS_PS) && ++ !ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS)) ++ goto clear; + break; + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_AP: diff --git a/package/kernel/mac80211/patches/319-v4.17-0004-mac80211-support-station-4-addr-mode-fast-rx.patch b/package/kernel/mac80211/patches/319-v4.17-0004-mac80211-support-station-4-addr-mode-fast-rx.patch new file mode 100644 index 000000000..97a5d8beb --- /dev/null +++ b/package/kernel/mac80211/patches/319-v4.17-0004-mac80211-support-station-4-addr-mode-fast-rx.patch @@ -0,0 +1,34 @@ +From: Felix Fietkau +Date: Fri, 23 Feb 2018 10:05:08 +0100 +Subject: [PATCH] mac80211: support station 4-addr mode fast-rx + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -3738,10 +3738,6 @@ void ieee80211_check_fast_rx(struct sta_ + + switch (sdata->vif.type) { + case NL80211_IFTYPE_STATION: +- /* 4-addr is harder to deal with, later maybe */ +- if (sdata->u.mgd.use_4addr) +- goto clear; +- + if (sta->sta.tdls) { + fastrx.da_offs = offsetof(struct ieee80211_hdr, addr1); + fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr2); +@@ -3754,6 +3750,13 @@ void ieee80211_check_fast_rx(struct sta_ + cpu_to_le16(IEEE80211_FCTL_FROMDS); + } + ++ if (sdata->u.mgd.use_4addr && !sta->sta.tdls) { ++ fastrx.expected_ds_bits |= ++ cpu_to_le16(IEEE80211_FCTL_TODS); ++ fastrx.da_offs = offsetof(struct ieee80211_hdr, addr3); ++ fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr4); ++ } ++ + if (!sdata->u.mgd.powersave) + break; + diff --git a/package/kernel/mac80211/patches/320-v4.17-mac80211-support-A-MSDU-in-fast-rx.patch b/package/kernel/mac80211/patches/320-v4.17-mac80211-support-A-MSDU-in-fast-rx.patch new file mode 100644 index 000000000..3c6d342ff --- /dev/null +++ b/package/kernel/mac80211/patches/320-v4.17-mac80211-support-A-MSDU-in-fast-rx.patch @@ -0,0 +1,256 @@ +From: Felix Fietkau +Date: Mon, 26 Feb 2018 22:09:29 +0100 +Subject: [PATCH] mac80211: support A-MSDU in fast-rx + +Only works if the IV was stripped from packets. Create a smaller +variant of ieee80211_rx_h_amsdu, which bypasses checks already done +within the fast-rx context. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2358,39 +2358,17 @@ ieee80211_deliver_skb(struct ieee80211_r + } + + static ieee80211_rx_result debug_noinline +-ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) ++__ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset) + { + struct net_device *dev = rx->sdata->dev; + struct sk_buff *skb = rx->skb; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + __le16 fc = hdr->frame_control; + struct sk_buff_head frame_list; +- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); + struct ethhdr ethhdr; + const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source; + +- if (unlikely(!ieee80211_is_data(fc))) +- return RX_CONTINUE; +- +- if (unlikely(!ieee80211_is_data_present(fc))) +- return RX_DROP_MONITOR; +- +- if (!(status->rx_flags & IEEE80211_RX_AMSDU)) +- return RX_CONTINUE; +- + if (unlikely(ieee80211_has_a4(hdr->frame_control))) { +- switch (rx->sdata->vif.type) { +- case NL80211_IFTYPE_AP_VLAN: +- if (!rx->sdata->u.vlan.sta) +- return RX_DROP_UNUSABLE; +- break; +- case NL80211_IFTYPE_STATION: +- if (!rx->sdata->u.mgd.use_4addr) +- return RX_DROP_UNUSABLE; +- break; +- default: +- return RX_DROP_UNUSABLE; +- } + check_da = NULL; + check_sa = NULL; + } else switch (rx->sdata->vif.type) { +@@ -2410,15 +2388,13 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx + break; + } + +- if (is_multicast_ether_addr(hdr->addr1)) +- return RX_DROP_UNUSABLE; +- + skb->dev = dev; + __skb_queue_head_init(&frame_list); + + if (ieee80211_data_to_8023_exthdr(skb, ðhdr, + rx->sdata->vif.addr, +- rx->sdata->vif.type)) ++ rx->sdata->vif.type, ++ data_offset)) + return RX_DROP_UNUSABLE; + + ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, +@@ -2440,6 +2416,44 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx + return RX_QUEUED; + } + ++static ieee80211_rx_result debug_noinline ++ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) ++{ ++ struct sk_buff *skb = rx->skb; ++ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; ++ __le16 fc = hdr->frame_control; ++ ++ if (!(status->rx_flags & IEEE80211_RX_AMSDU)) ++ return RX_CONTINUE; ++ ++ if (unlikely(!ieee80211_is_data(fc))) ++ return RX_CONTINUE; ++ ++ if (unlikely(!ieee80211_is_data_present(fc))) ++ return RX_DROP_MONITOR; ++ ++ if (unlikely(ieee80211_has_a4(hdr->frame_control))) { ++ switch (rx->sdata->vif.type) { ++ case NL80211_IFTYPE_AP_VLAN: ++ if (!rx->sdata->u.vlan.sta) ++ return RX_DROP_UNUSABLE; ++ break; ++ case NL80211_IFTYPE_STATION: ++ if (!rx->sdata->u.mgd.use_4addr) ++ return RX_DROP_UNUSABLE; ++ break; ++ default: ++ return RX_DROP_UNUSABLE; ++ } ++ } ++ ++ if (is_multicast_ether_addr(hdr->addr1)) ++ return RX_DROP_UNUSABLE; ++ ++ return __ieee80211_rx_h_amsdu(rx, 0); ++} ++ + #ifdef CPTCFG_MAC80211_MESH + static ieee80211_rx_result + ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) +@@ -3889,7 +3903,8 @@ static bool ieee80211_invoke_fast_rx(str + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + struct sta_info *sta = rx->sta; + int orig_len = skb->len; +- int snap_offs = ieee80211_hdrlen(hdr->frame_control); ++ int hdrlen = ieee80211_hdrlen(hdr->frame_control); ++ int snap_offs = hdrlen; + struct { + u8 snap[sizeof(rfc1042_header)]; + __be16 proto; +@@ -3920,10 +3935,6 @@ static bool ieee80211_invoke_fast_rx(str + (status->flag & FAST_RX_CRYPT_FLAGS) != FAST_RX_CRYPT_FLAGS) + return false; + +- /* we don't deal with A-MSDU deaggregation here */ +- if (status->rx_flags & IEEE80211_RX_AMSDU) +- return false; +- + if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) + return false; + +@@ -3955,21 +3966,24 @@ static bool ieee80211_invoke_fast_rx(str + snap_offs += IEEE80211_CCMP_HDR_LEN; + } + +- if (!pskb_may_pull(skb, snap_offs + sizeof(*payload))) +- goto drop; +- payload = (void *)(skb->data + snap_offs); ++ if (!(status->rx_flags & IEEE80211_RX_AMSDU)) { ++ if (!pskb_may_pull(skb, snap_offs + sizeof(*payload))) ++ goto drop; + +- if (!ether_addr_equal(payload->snap, fast_rx->rfc1042_hdr)) +- return false; ++ payload = (void *)(skb->data + snap_offs); + +- /* Don't handle these here since they require special code. +- * Accept AARP and IPX even though they should come with a +- * bridge-tunnel header - but if we get them this way then +- * there's little point in discarding them. +- */ +- if (unlikely(payload->proto == cpu_to_be16(ETH_P_TDLS) || +- payload->proto == fast_rx->control_port_protocol)) +- return false; ++ if (!ether_addr_equal(payload->snap, fast_rx->rfc1042_hdr)) ++ return false; ++ ++ /* Don't handle these here since they require special code. ++ * Accept AARP and IPX even though they should come with a ++ * bridge-tunnel header - but if we get them this way then ++ * there's little point in discarding them. ++ */ ++ if (unlikely(payload->proto == cpu_to_be16(ETH_P_TDLS) || ++ payload->proto == fast_rx->control_port_protocol)) ++ return false; ++ } + + /* after this point, don't punt to the slowpath! */ + +@@ -3983,12 +3997,6 @@ static bool ieee80211_invoke_fast_rx(str + } + + /* statistics part of ieee80211_rx_h_sta_process() */ +- stats->last_rx = jiffies; +- stats->last_rate = sta_stats_encode_rate(status); +- +- stats->fragments++; +- stats->packets++; +- + if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { + stats->last_signal = status->signal; + if (!fast_rx->uses_rss) +@@ -4017,6 +4025,20 @@ static bool ieee80211_invoke_fast_rx(str + if (rx->key && !ieee80211_has_protected(hdr->frame_control)) + goto drop; + ++ if (status->rx_flags & IEEE80211_RX_AMSDU) { ++ if (__ieee80211_rx_h_amsdu(rx, snap_offs - hdrlen) != ++ RX_QUEUED) ++ goto drop; ++ ++ return true; ++ } ++ ++ stats->last_rx = jiffies; ++ stats->last_rate = sta_stats_encode_rate(status); ++ ++ stats->fragments++; ++ stats->packets++; ++ + /* do the header conversion - first grab the addresses */ + ether_addr_copy(addrs.da, skb->data + fast_rx->da_offs); + ether_addr_copy(addrs.sa, skb->data + fast_rx->sa_offs); +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -4331,10 +4331,12 @@ unsigned int ieee80211_get_mesh_hdrlen(s + * of it being pushed into the SKB + * @addr: the device MAC address + * @iftype: the virtual interface type ++ * @data_offset: offset of payload after the 802.11 header + * Return: 0 on success. Non-zero on error. + */ + int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, +- const u8 *addr, enum nl80211_iftype iftype); ++ const u8 *addr, enum nl80211_iftype iftype, ++ u8 data_offset); + + /** + * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3 +@@ -4346,7 +4348,7 @@ int ieee80211_data_to_8023_exthdr(struct + static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, + enum nl80211_iftype iftype) + { +- return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype); ++ return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype, 0); + } + + /** +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -419,7 +419,8 @@ unsigned int ieee80211_get_mesh_hdrlen(s + EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen); + + int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, +- const u8 *addr, enum nl80211_iftype iftype) ++ const u8 *addr, enum nl80211_iftype iftype, ++ u8 data_offset) + { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct { +@@ -433,7 +434,7 @@ int ieee80211_data_to_8023_exthdr(struct + if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) + return -1; + +- hdrlen = ieee80211_hdrlen(hdr->frame_control); ++ hdrlen = ieee80211_hdrlen(hdr->frame_control) + data_offset; + if (skb->len < hdrlen + 8) + return -1; + diff --git a/package/kernel/mac80211/patches/321-v4.16-0001-brcmfmac-assure-bcdc-dcmd-api-does-not-return-value-.patch b/package/kernel/mac80211/patches/321-v4.16-0001-brcmfmac-assure-bcdc-dcmd-api-does-not-return-value-.patch new file mode 100644 index 000000000..394fbfc5b --- /dev/null +++ b/package/kernel/mac80211/patches/321-v4.16-0001-brcmfmac-assure-bcdc-dcmd-api-does-not-return-value-.patch @@ -0,0 +1,68 @@ +From 5242a5444e0b6464d7455beb55d936dd192b5e9d Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Mon, 22 Jan 2018 21:46:39 +0100 +Subject: [PATCH] brcmfmac: assure bcdc dcmd api does not return value > 0 + +The protocol layer api defines callbacks for dongle commands. +Although not really well documented these should only return an +error code in case of an error, or 0 upon success. In the bcdc +protocol it can return value above 0 and we carry a fix in the +caller of the protocol layer api. This patch makes it adhere to +the intent of the api as described above. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 6 +++++- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c | 8 +++----- + 2 files changed, 8 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c +@@ -211,6 +211,8 @@ retry: + memcpy(buf, info, len); + } + ++ ret = 0; ++ + /* Check the ERROR flag */ + if (flags & BCDC_DCMD_ERROR) + ret = le32_to_cpu(msg->status); +@@ -225,7 +227,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p + { + struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; + struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg; +- int ret = 0; ++ int ret; + u32 flags, id; + + brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len); +@@ -249,6 +251,8 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p + goto done; + } + ++ ret = 0; ++ + /* Check the ERROR flag */ + if (flags & BCDC_DCMD_ERROR) + ret = le32_to_cpu(msg->status); +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c +@@ -121,11 +121,9 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, + else + err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len); + +- if (err >= 0) +- return 0; +- +- brcmf_dbg(FIL, "Failed: %s (%d)\n", +- brcmf_fil_get_errstr((u32)(-err)), err); ++ if (err) ++ brcmf_dbg(FIL, "Failed: %s (%d)\n", ++ brcmf_fil_get_errstr((u32)(-err)), err); + + return err; + } diff --git a/package/kernel/mac80211/patches/321-v4.16-0002-brcmfmac-separate-firmware-errors-from-i-o-errors.patch b/package/kernel/mac80211/patches/321-v4.16-0002-brcmfmac-separate-firmware-errors-from-i-o-errors.patch new file mode 100644 index 000000000..28e3c1a65 --- /dev/null +++ b/package/kernel/mac80211/patches/321-v4.16-0002-brcmfmac-separate-firmware-errors-from-i-o-errors.patch @@ -0,0 +1,186 @@ +From b69c1df47281ad47bd2037a42b98f5c7115b7fd5 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Mon, 22 Jan 2018 21:46:40 +0100 +Subject: [PATCH] brcmfmac: separate firmware errors from i/o errors + +When using the firmware api it can fail simply because firmware does +not like the request or it fails due to issues in the host interface. +Currently, there is only a single error code which is confusing. So +adding a parameter to pass the firmware error separately and in case +of a firmware error always return -EBADE to user-space. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 11 ++++++----- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c | 16 +++++++++++----- + .../net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 10 ++++++---- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h | 14 ++++++++------ + 4 files changed, 31 insertions(+), 20 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c +@@ -165,7 +165,7 @@ static int brcmf_proto_bcdc_cmplt(struct + + static int + brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, +- void *buf, uint len) ++ void *buf, uint len, int *fwerr) + { + struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; + struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg; +@@ -175,6 +175,7 @@ brcmf_proto_bcdc_query_dcmd(struct brcmf + + brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len); + ++ *fwerr = 0; + ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, false); + if (ret < 0) { + brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n", +@@ -215,15 +216,14 @@ retry: + + /* Check the ERROR flag */ + if (flags & BCDC_DCMD_ERROR) +- ret = le32_to_cpu(msg->status); +- ++ *fwerr = le32_to_cpu(msg->status); + done: + return ret; + } + + static int + brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, +- void *buf, uint len) ++ void *buf, uint len, int *fwerr) + { + struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; + struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg; +@@ -232,6 +232,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p + + brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len); + ++ *fwerr = 0; + ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, true); + if (ret < 0) + goto done; +@@ -255,7 +256,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p + + /* Check the ERROR flag */ + if (flags & BCDC_DCMD_ERROR) +- ret = le32_to_cpu(msg->status); ++ *fwerr = le32_to_cpu(msg->status); + + done: + return ret; +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c +@@ -107,7 +107,7 @@ static s32 + brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) + { + struct brcmf_pub *drvr = ifp->drvr; +- s32 err; ++ s32 err, fwerr; + + if (drvr->bus_if->state != BRCMF_BUS_UP) { + brcmf_err("bus is down. we have nothing to do.\n"); +@@ -117,14 +117,20 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, + if (data != NULL) + len = min_t(uint, len, BRCMF_DCMD_MAXLEN); + if (set) +- err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd, data, len); ++ err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd, ++ data, len, &fwerr); + else +- err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len); ++ err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, ++ data, len, &fwerr); + +- if (err) ++ if (err) { + brcmf_dbg(FIL, "Failed: %s (%d)\n", + brcmf_fil_get_errstr((u32)(-err)), err); +- ++ } else if (fwerr < 0) { ++ brcmf_dbg(FIL, "Firmware error: %s (%d)\n", ++ brcmf_fil_get_errstr((u32)(-fwerr)), fwerr); ++ err = -EBADE; ++ } + return err; + } + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +@@ -477,7 +477,7 @@ static void brcmf_msgbuf_ioctl_resp_wake + + + static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx, +- uint cmd, void *buf, uint len) ++ uint cmd, void *buf, uint len, int *fwerr) + { + struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd; + struct sk_buff *skb = NULL; +@@ -485,6 +485,7 @@ static int brcmf_msgbuf_query_dcmd(struc + int err; + + brcmf_dbg(MSGBUF, "ifidx=%d, cmd=%d, len=%d\n", ifidx, cmd, len); ++ *fwerr = 0; + msgbuf->ctl_completed = false; + err = brcmf_msgbuf_tx_ioctl(drvr, ifidx, cmd, buf, len); + if (err) +@@ -508,14 +509,15 @@ static int brcmf_msgbuf_query_dcmd(struc + } + brcmu_pkt_buf_free_skb(skb); + +- return msgbuf->ioctl_resp_status; ++ *fwerr = msgbuf->ioctl_resp_status; ++ return 0; + } + + + static int brcmf_msgbuf_set_dcmd(struct brcmf_pub *drvr, int ifidx, +- uint cmd, void *buf, uint len) ++ uint cmd, void *buf, uint len, int *fwerr) + { +- return brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len); ++ return brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len, fwerr); + } + + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h +@@ -30,9 +30,9 @@ struct brcmf_proto { + int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, + struct sk_buff *skb, struct brcmf_if **ifp); + int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, +- void *buf, uint len); ++ void *buf, uint len, int *fwerr); + int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, +- uint len); ++ uint len, int *fwerr); + int (*tx_queue_data)(struct brcmf_pub *drvr, int ifidx, + struct sk_buff *skb); + int (*txdata)(struct brcmf_pub *drvr, int ifidx, u8 offset, +@@ -71,14 +71,16 @@ static inline int brcmf_proto_hdrpull(st + return drvr->proto->hdrpull(drvr, do_fws, skb, ifp); + } + static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx, +- uint cmd, void *buf, uint len) ++ uint cmd, void *buf, uint len, ++ int *fwerr) + { +- return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len); ++ return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len,fwerr); + } + static inline int brcmf_proto_set_dcmd(struct brcmf_pub *drvr, int ifidx, +- uint cmd, void *buf, uint len) ++ uint cmd, void *buf, uint len, ++ int *fwerr) + { +- return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len); ++ return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len, fwerr); + } + + static inline int brcmf_proto_tx_queue_data(struct brcmf_pub *drvr, int ifidx, diff --git a/package/kernel/mac80211/patches/322-v4.16-0001-brcmfmac-add-possibility-to-obtain-firmware-error.patch b/package/kernel/mac80211/patches/322-v4.16-0001-brcmfmac-add-possibility-to-obtain-firmware-error.patch new file mode 100644 index 000000000..e6486160f --- /dev/null +++ b/package/kernel/mac80211/patches/322-v4.16-0001-brcmfmac-add-possibility-to-obtain-firmware-error.patch @@ -0,0 +1,92 @@ +From 933897342d0714ae1c10729cbaeecea0c6178db5 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 28 Feb 2018 21:15:19 +0100 +Subject: [PATCH] brcmfmac: add possibility to obtain firmware error + +The feature module needs to evaluate the actual firmware error return +upon a control command. This adds a flag to struct brcmf_if that the +caller can set. This flag is checked to determine the error code that +needs to be returned. + +Fixes: b69c1df47281 ("brcmfmac: separate firmware errors from i/o errors") +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h | 2 ++ + drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c | 10 ++++++++++ + drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c | 3 +++ + 3 files changed, 15 insertions(+) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +@@ -181,6 +181,7 @@ enum brcmf_netif_stop_reason { + * @netif_stop_lock: spinlock for update netif_stop from multiple sources. + * @pend_8021x_cnt: tracks outstanding number of 802.1x frames. + * @pend_8021x_wait: used for signalling change in count. ++ * @fwil_fwerr: flag indicating fwil layer should return firmware error codes. + */ + struct brcmf_if { + struct brcmf_pub *drvr; +@@ -198,6 +199,7 @@ struct brcmf_if { + wait_queue_head_t pend_8021x_wait; + struct in6_addr ipv6_addr_tbl[NDOL_MAX_ENTRIES]; + u8 ipv6addr_idx; ++ bool fwil_fwerr; + }; + + int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp); +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +@@ -104,6 +104,9 @@ static void brcmf_feat_iovar_int_get(str + u32 data; + int err; + ++ /* we need to know firmware error */ ++ ifp->fwil_fwerr = true; ++ + err = brcmf_fil_iovar_int_get(ifp, name, &data); + if (err == 0) { + brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]); +@@ -112,6 +115,8 @@ static void brcmf_feat_iovar_int_get(str + brcmf_dbg(TRACE, "%s feature check failed: %d\n", + brcmf_feat_names[id], err); + } ++ ++ ifp->fwil_fwerr = false; + } + + static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp, +@@ -120,6 +125,9 @@ static void brcmf_feat_iovar_data_set(st + { + int err; + ++ /* we need to know firmware error */ ++ ifp->fwil_fwerr = true; ++ + err = brcmf_fil_iovar_data_set(ifp, name, data, len); + if (err != -BRCMF_FW_UNSUPPORTED) { + brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]); +@@ -128,6 +136,8 @@ static void brcmf_feat_iovar_data_set(st + brcmf_dbg(TRACE, "%s feature check failed: %d\n", + brcmf_feat_names[id], err); + } ++ ++ ifp->fwil_fwerr = false; + } + + #define MAX_CAPS_BUFFER_SIZE 512 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c +@@ -131,6 +131,9 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, + brcmf_fil_get_errstr((u32)(-fwerr)), fwerr); + err = -EBADE; + } ++ if (ifp->fwil_fwerr) ++ return fwerr; ++ + return err; + } + diff --git a/package/kernel/mac80211/patches/322-v4.16-0002-brcmfmac-fix-P2P_DEVICE-ethernet-address-generation.patch b/package/kernel/mac80211/patches/322-v4.16-0002-brcmfmac-fix-P2P_DEVICE-ethernet-address-generation.patch new file mode 100644 index 000000000..20e16ad23 --- /dev/null +++ b/package/kernel/mac80211/patches/322-v4.16-0002-brcmfmac-fix-P2P_DEVICE-ethernet-address-generation.patch @@ -0,0 +1,64 @@ +From 455f3e76cfc0d893585a5f358b9ddbe9c1e1e53b Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 28 Feb 2018 21:15:20 +0100 +Subject: [PATCH] brcmfmac: fix P2P_DEVICE ethernet address generation + +The firmware has a requirement that the P2P_DEVICE address should +be different from the address of the primary interface. When not +specified by user-space, the driver generates the MAC address for +the P2P_DEVICE interface using the MAC address of the primary +interface and setting the locally administered bit. However, the MAC +address of the primary interface may already have that bit set causing +the creation of the P2P_DEVICE interface to fail with -EBUSY. Fix this +by using a random address instead to determine the P2P_DEVICE address. + +Cc: stable@vger.kernel.org # 3.10.y +Reported-by: Hans de Goede +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 24 ++++++++++------------ + 1 file changed, 11 insertions(+), 13 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +@@ -462,25 +462,23 @@ static int brcmf_p2p_set_firmware(struct + * @dev_addr: optional device address. + * + * P2P needs mac addresses for P2P device and interface. If no device +- * address it specified, these are derived from the primary net device, ie. +- * the permanent ethernet address of the device. ++ * address it specified, these are derived from a random ethernet ++ * address. + */ + static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr) + { +- struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; +- bool local_admin = false; ++ bool random_addr = false; + +- if (!dev_addr || is_zero_ether_addr(dev_addr)) { +- dev_addr = pri_ifp->mac_addr; +- local_admin = true; +- } ++ if (!dev_addr || is_zero_ether_addr(dev_addr)) ++ random_addr = true; + +- /* Generate the P2P Device Address. This consists of the device's +- * primary MAC address with the locally administered bit set. ++ /* Generate the P2P Device Address obtaining a random ethernet ++ * address with the locally administered bit set. + */ +- memcpy(p2p->dev_addr, dev_addr, ETH_ALEN); +- if (local_admin) +- p2p->dev_addr[0] |= 0x02; ++ if (random_addr) ++ eth_random_addr(p2p->dev_addr); ++ else ++ memcpy(p2p->dev_addr, dev_addr, ETH_ALEN); + + /* Generate the P2P Interface Address. If the discovery and connection + * BSSCFGs need to simultaneously co-exist, then this address must be diff --git a/package/kernel/mac80211/patches/323-v4.16-0001-brcmfmac-drop-Inter-Access-Point-Protocol-packets-by.patch b/package/kernel/mac80211/patches/323-v4.16-0001-brcmfmac-drop-Inter-Access-Point-Protocol-packets-by.patch new file mode 100644 index 000000000..f25dea01d --- /dev/null +++ b/package/kernel/mac80211/patches/323-v4.16-0001-brcmfmac-drop-Inter-Access-Point-Protocol-packets-by.patch @@ -0,0 +1,157 @@ +From 1259055170287a350cad453e9eac139c81609860 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 15 Mar 2018 08:29:09 +0100 +Subject: [PATCH] brcmfmac: drop Inter-Access Point Protocol packets by default +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Testing brcmfmac with more recent firmwares resulted in AP interfaces +not working in some specific setups. Debugging resulted in discovering +support for IAPP in Broadcom's firmwares. + +Older firmwares were only generating 802.11f frames. Newer ones like: +1) 10.10 (TOB) (r663589) +2) 10.10.122.20 (r683106) +for 4366b1 and 4366c0 respectively seem to also /respect/ 802.11f frames +in the Tx path by performing a STA disassociation. + +This obsoleted standard and its implementation is something that: +1) Most people don't need / want to use +2) Can allow local DoS attacks +3) Breaks AP interfaces in some specific bridge setups + +To solve issues it can cause this commit modifies brcmfmac to drop IAPP +packets. If affects: +1) Rx path: driver won't be sending these unwanted packets up. +2) Tx path: driver will reject packets that would trigger STA + disassociation perfromed by a firmware (possible local DoS attack). + +It appears there are some Broadcom's clients/users who care about this +feature despite the drawbacks. They can switch it on using a new module +param. + +This change results in only two more comparisons (check for module param +and check for Ethernet packet length) for 99.9% of packets. Its overhead +should be very minimal. + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +Acked-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../wireless/broadcom/brcm80211/brcmfmac/common.c | 5 ++ + .../wireless/broadcom/brcm80211/brcmfmac/common.h | 1 + + .../wireless/broadcom/brcm80211/brcmfmac/core.c | 57 ++++++++++++++++++++++ + 3 files changed, 63 insertions(+) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +@@ -75,6 +75,10 @@ static int brcmf_roamoff; + module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR); + MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine"); + ++static int brcmf_iapp_enable; ++module_param_named(iapp, brcmf_iapp_enable, int, 0); ++MODULE_PARM_DESC(iapp, "Enable partial support for the obsoleted Inter-Access Point Protocol"); ++ + #ifdef DEBUG + /* always succeed brcmf_bus_started() */ + static int brcmf_ignore_probe_fail; +@@ -441,6 +445,7 @@ struct brcmf_mp_device *brcmf_get_module + settings->feature_disable = brcmf_feature_disable; + settings->fcmode = brcmf_fcmode; + settings->roamoff = !!brcmf_roamoff; ++ settings->iapp = !!brcmf_iapp_enable; + #ifdef DEBUG + settings->ignore_probe_fail = !!brcmf_ignore_probe_fail; + #endif +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +@@ -58,6 +58,7 @@ struct brcmf_mp_device { + unsigned int feature_disable; + int fcmode; + bool roamoff; ++ bool iapp; + bool ignore_probe_fail; + struct brcmfmac_pd_cc *country_codes; + union { +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +@@ -230,6 +230,37 @@ static void brcmf_netdev_set_multicast_l + schedule_work(&ifp->multicast_work); + } + ++/** ++ * brcmf_skb_is_iapp - checks if skb is an IAPP packet ++ * ++ * @skb: skb to check ++ */ ++static bool brcmf_skb_is_iapp(struct sk_buff *skb) ++{ ++ static const u8 iapp_l2_update_packet[6] __aligned(2) = { ++ 0x00, 0x01, 0xaf, 0x81, 0x01, 0x00, ++ }; ++ unsigned char *eth_data; ++#if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ++ const u16 *a, *b; ++#endif ++ ++ if (skb->len - skb->mac_len != 6 || ++ !is_multicast_ether_addr(eth_hdr(skb)->h_dest)) ++ return false; ++ ++ eth_data = skb_mac_header(skb) + ETH_HLEN; ++#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ++ return !(((*(const u32 *)eth_data) ^ (*(const u32 *)iapp_l2_update_packet)) | ++ ((*(const u16 *)(eth_data + 4)) ^ (*(const u16 *)(iapp_l2_update_packet + 4)))); ++#else ++ a = (const u16 *)eth_data; ++ b = (const u16 *)iapp_l2_update_packet; ++ ++ return !((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])); ++#endif ++} ++ + static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, + struct net_device *ndev) + { +@@ -250,6 +281,23 @@ static netdev_tx_t brcmf_netdev_start_xm + goto done; + } + ++ /* Some recent Broadcom's firmwares disassociate STA when they receive ++ * an 802.11f ADD frame. This behavior can lead to a local DoS security ++ * issue. Attacker may trigger disassociation of any STA by sending a ++ * proper Ethernet frame to the wireless interface. ++ * ++ * Moreover this feature may break AP interfaces in some specific ++ * setups. This applies e.g. to the bridge with hairpin mode enabled and ++ * IFLA_BRPORT_MCAST_TO_UCAST set. IAPP packet generated by a firmware ++ * will get passed back to the wireless interface and cause immediate ++ * disassociation of a just-connected STA. ++ */ ++ if (!drvr->settings->iapp && brcmf_skb_is_iapp(skb)) { ++ dev_kfree_skb(skb); ++ ret = -EINVAL; ++ goto done; ++ } ++ + /* Make sure there's enough writeable headroom */ + if (skb_headroom(skb) < drvr->hdrlen || skb_header_cloned(skb)) { + head_delta = max_t(int, drvr->hdrlen - skb_headroom(skb), 0); +@@ -325,6 +373,15 @@ void brcmf_txflowblock_if(struct brcmf_i + + void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb) + { ++ /* Most of Broadcom's firmwares send 802.11f ADD frame every time a new ++ * STA connects to the AP interface. This is an obsoleted standard most ++ * users don't use, so don't pass these frames up unless requested. ++ */ ++ if (!ifp->drvr->settings->iapp && brcmf_skb_is_iapp(skb)) { ++ brcmu_pkt_buf_free_skb(skb); ++ return; ++ } ++ + if (skb->pkt_type == PACKET_MULTICAST) + ifp->ndev->stats.multicast++; + diff --git a/package/kernel/mac80211/patches/324-v4.16-0001-brcmfmac-Fix-check-for-ISO3166-code.patch b/package/kernel/mac80211/patches/324-v4.16-0001-brcmfmac-Fix-check-for-ISO3166-code.patch new file mode 100644 index 000000000..d45f64ff2 --- /dev/null +++ b/package/kernel/mac80211/patches/324-v4.16-0001-brcmfmac-Fix-check-for-ISO3166-code.patch @@ -0,0 +1,29 @@ +From 9b9322db5c5a1917a66c71fe47c3848a9a31227e Mon Sep 17 00:00:00 2001 +From: Stefan Wahren +Date: Wed, 14 Mar 2018 20:02:59 +0100 +Subject: [PATCH] brcmfmac: Fix check for ISO3166 code + +The commit "regulatory: add NUL to request alpha2" increases the length of +alpha2 to 3. This causes a regression on brcmfmac, because +brcmf_cfg80211_reg_notifier() expect valid ISO3166 codes in the complete +array. So fix this accordingly. + +Fixes: 657308f73e67 ("regulatory: add NUL to request alpha2") +Signed-off-by: Stefan Wahren +Acked-by: Franky Lin +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -6803,7 +6803,7 @@ static void brcmf_cfg80211_reg_notifier( + return; + + /* ignore non-ISO3166 country codes */ +- for (i = 0; i < sizeof(req->alpha2); i++) ++ for (i = 0; i < 2; i++) + if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') { + brcmf_err("not an ISO3166 code (0x%02x 0x%02x)\n", + req->alpha2[0], req->alpha2[1]); diff --git a/package/kernel/mac80211/patches/300-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch b/package/kernel/mac80211/patches/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch similarity index 100% rename from package/kernel/mac80211/patches/300-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch rename to package/kernel/mac80211/patches/350-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch diff --git a/package/kernel/mac80211/patches/301-ath9k_hw-issue-external-reset-for-QCA955x.patch b/package/kernel/mac80211/patches/351-ath9k_hw-issue-external-reset-for-QCA955x.patch similarity index 100% rename from package/kernel/mac80211/patches/301-ath9k_hw-issue-external-reset-for-QCA955x.patch rename to package/kernel/mac80211/patches/351-ath9k_hw-issue-external-reset-for-QCA955x.patch diff --git a/package/kernel/mac80211/patches/302-ath9k_hw-set-spectral-scan-enable-bit-on-trigger-for.patch b/package/kernel/mac80211/patches/352-ath9k_hw-set-spectral-scan-enable-bit-on-trigger-for.patch similarity index 100% rename from package/kernel/mac80211/patches/302-ath9k_hw-set-spectral-scan-enable-bit-on-trigger-for.patch rename to package/kernel/mac80211/patches/352-ath9k_hw-set-spectral-scan-enable-bit-on-trigger-for.patch diff --git a/package/kernel/mac80211/patches/303-ath9k-don-t-run-periodic-and-nf-calibation-at-the-sa.patch b/package/kernel/mac80211/patches/353-ath9k-don-t-run-periodic-and-nf-calibation-at-the-sa.patch similarity index 100% rename from package/kernel/mac80211/patches/303-ath9k-don-t-run-periodic-and-nf-calibation-at-the-sa.patch rename to package/kernel/mac80211/patches/353-ath9k-don-t-run-periodic-and-nf-calibation-at-the-sa.patch diff --git a/package/kernel/mac80211/patches/304-ath9k-force-rx_clear-when-disabling-rx.patch b/package/kernel/mac80211/patches/354-ath9k-force-rx_clear-when-disabling-rx.patch similarity index 100% rename from package/kernel/mac80211/patches/304-ath9k-force-rx_clear-when-disabling-rx.patch rename to package/kernel/mac80211/patches/354-ath9k-force-rx_clear-when-disabling-rx.patch diff --git a/package/kernel/mac80211/patches/305-ath9k-limit-retries-for-powersave-response-frames.patch b/package/kernel/mac80211/patches/355-ath9k-limit-retries-for-powersave-response-frames.patch similarity index 100% rename from package/kernel/mac80211/patches/305-ath9k-limit-retries-for-powersave-response-frames.patch rename to package/kernel/mac80211/patches/355-ath9k-limit-retries-for-powersave-response-frames.patch diff --git a/package/kernel/mac80211/patches/306-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch b/package/kernel/mac80211/patches/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch similarity index 100% rename from package/kernel/mac80211/patches/306-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch rename to package/kernel/mac80211/patches/356-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch diff --git a/package/kernel/mac80211/patches/307-mac80211-add-hdrlen-to-ieee80211_tx_data.patch b/package/kernel/mac80211/patches/357-mac80211-add-hdrlen-to-ieee80211_tx_data.patch similarity index 100% rename from package/kernel/mac80211/patches/307-mac80211-add-hdrlen-to-ieee80211_tx_data.patch rename to package/kernel/mac80211/patches/357-mac80211-add-hdrlen-to-ieee80211_tx_data.patch diff --git a/package/kernel/mac80211/patches/308-mac80211-add-NEED_ALIGNED4_SKBS-hw-flag.patch b/package/kernel/mac80211/patches/358-mac80211-add-NEED_ALIGNED4_SKBS-hw-flag.patch similarity index 100% rename from package/kernel/mac80211/patches/308-mac80211-add-NEED_ALIGNED4_SKBS-hw-flag.patch rename to package/kernel/mac80211/patches/358-mac80211-add-NEED_ALIGNED4_SKBS-hw-flag.patch diff --git a/package/kernel/mac80211/patches/309-mac80211-minstrel-Enable-STBC-and-LDPC-for-VHT-Rates.patch b/package/kernel/mac80211/patches/359-mac80211-minstrel-Enable-STBC-and-LDPC-for-VHT-Rates.patch similarity index 100% rename from package/kernel/mac80211/patches/309-mac80211-minstrel-Enable-STBC-and-LDPC-for-VHT-Rates.patch rename to package/kernel/mac80211/patches/359-mac80211-minstrel-Enable-STBC-and-LDPC-for-VHT-Rates.patch diff --git a/package/kernel/mac80211/patches/310-ath9k-fix-moredata-bit-in-PS-buffered-frame-release.patch b/package/kernel/mac80211/patches/360-ath9k-fix-moredata-bit-in-PS-buffered-frame-release.patch similarity index 100% rename from package/kernel/mac80211/patches/310-ath9k-fix-moredata-bit-in-PS-buffered-frame-release.patch rename to package/kernel/mac80211/patches/360-ath9k-fix-moredata-bit-in-PS-buffered-frame-release.patch diff --git a/package/kernel/mac80211/patches/311-ath9k-clear-potentially-stale-EOSP-status-bit-in-int.patch b/package/kernel/mac80211/patches/361-ath9k-clear-potentially-stale-EOSP-status-bit-in-int.patch similarity index 100% rename from package/kernel/mac80211/patches/311-ath9k-clear-potentially-stale-EOSP-status-bit-in-int.patch rename to package/kernel/mac80211/patches/361-ath9k-clear-potentially-stale-EOSP-status-bit-in-int.patch diff --git a/package/kernel/mac80211/patches/312-ath9k-report-tx-status-on-EOSP.patch b/package/kernel/mac80211/patches/362-ath9k-report-tx-status-on-EOSP.patch similarity index 100% rename from package/kernel/mac80211/patches/312-ath9k-report-tx-status-on-EOSP.patch rename to package/kernel/mac80211/patches/362-ath9k-report-tx-status-on-EOSP.patch diff --git a/package/kernel/mac80211/patches/313-ath9k-fix-block-ack-window-tracking-issues.patch b/package/kernel/mac80211/patches/363-ath9k-fix-block-ack-window-tracking-issues.patch similarity index 100% rename from package/kernel/mac80211/patches/313-ath9k-fix-block-ack-window-tracking-issues.patch rename to package/kernel/mac80211/patches/363-ath9k-fix-block-ack-window-tracking-issues.patch diff --git a/package/kernel/mac80211/patches/314-ath9k_hw-fix-channel-maximum-power-level-test.patch b/package/kernel/mac80211/patches/364-ath9k_hw-fix-channel-maximum-power-level-test.patch similarity index 100% rename from package/kernel/mac80211/patches/314-ath9k_hw-fix-channel-maximum-power-level-test.patch rename to package/kernel/mac80211/patches/364-ath9k_hw-fix-channel-maximum-power-level-test.patch diff --git a/package/kernel/mac80211/patches/315-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch b/package/kernel/mac80211/patches/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch similarity index 100% rename from package/kernel/mac80211/patches/315-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch rename to package/kernel/mac80211/patches/365-ath9k-adjust-tx-power-reduction-for-US-regulatory-do.patch diff --git a/package/kernel/mac80211/patches/316-ath9k-fix-more-data-flag-for-buffered-multicast-pack.patch b/package/kernel/mac80211/patches/366-ath9k-fix-more-data-flag-for-buffered-multicast-pack.patch similarity index 100% rename from package/kernel/mac80211/patches/316-ath9k-fix-more-data-flag-for-buffered-multicast-pack.patch rename to package/kernel/mac80211/patches/366-ath9k-fix-more-data-flag-for-buffered-multicast-pack.patch diff --git a/package/kernel/mac80211/patches/317-Revert-ath10k-disable-wake_tx_queue-for-older-device.patch b/package/kernel/mac80211/patches/367-Revert-ath10k-disable-wake_tx_queue-for-older-device.patch similarity index 100% rename from package/kernel/mac80211/patches/317-Revert-ath10k-disable-wake_tx_queue-for-older-device.patch rename to package/kernel/mac80211/patches/367-Revert-ath10k-disable-wake_tx_queue-for-older-device.patch diff --git a/package/kernel/mac80211/patches/319-ath10k-fix-recent-bandwidth-conversion-bug.patch b/package/kernel/mac80211/patches/368-ath10k-fix-recent-bandwidth-conversion-bug.patch similarity index 100% rename from package/kernel/mac80211/patches/319-ath10k-fix-recent-bandwidth-conversion-bug.patch rename to package/kernel/mac80211/patches/368-ath10k-fix-recent-bandwidth-conversion-bug.patch diff --git a/package/kernel/mac80211/patches/369-cfg80211-use-only-1Mbps-for-basic-rates-in-mesh.patch b/package/kernel/mac80211/patches/369-cfg80211-use-only-1Mbps-for-basic-rates-in-mesh.patch new file mode 100644 index 000000000..bc4174e4c --- /dev/null +++ b/package/kernel/mac80211/patches/369-cfg80211-use-only-1Mbps-for-basic-rates-in-mesh.patch @@ -0,0 +1,55 @@ +From: Johannes Berg +Date: Tue, 30 Jan 2018 13:17:38 +0100 +Subject: [PATCH] cfg80211: use only 1Mbps for basic rates in mesh + +Mesh used to use the mandatory rates as basic rates, but we got +the calculation of mandatory rates wrong until some time ago. +Fix this this broke interoperability with older versions since +now more basic rates are required, and thus the MBSS isn't the +same and the network stops working. + +Fix this by simply using only 1Mbps as the basic rate in 2.4GHz. +Since the changed mandatory rates only affected 2.4GHz, this is +all we need to make it work again. + +Reported-and-tested-by: Matthias Schiffer +Fixes: 1bd773c077de ("wireless: set correct mandatory rate flags") +Signed-off-by: Johannes Berg +--- + net/wireless/mesh.c | 25 ++++++++++++++++++++++--- + 1 file changed, 22 insertions(+), 3 deletions(-) + +--- a/net/wireless/mesh.c ++++ b/net/wireless/mesh.c +@@ -169,9 +169,28 @@ int __cfg80211_join_mesh(struct cfg80211 + enum nl80211_bss_scan_width scan_width; + struct ieee80211_supported_band *sband = + rdev->wiphy.bands[setup->chandef.chan->band]; +- scan_width = cfg80211_chandef_to_scan_width(&setup->chandef); +- setup->basic_rates = ieee80211_mandatory_rates(sband, +- scan_width); ++ ++ if (setup->chandef.chan->band == NL80211_BAND_2GHZ) { ++ int i; ++ ++ /* ++ * Older versions selected the mandatory rates for ++ * 2.4 GHz as well, but were broken in that only ++ * 1 Mbps was regarded as a mandatory rate. Keep ++ * using just 1 Mbps as the default basic rate for ++ * mesh to be interoperable with older versions. ++ */ ++ for (i = 0; i < sband->n_bitrates; i++) { ++ if (sband->bitrates[i].bitrate == 10) { ++ setup->basic_rates = BIT(i); ++ break; ++ } ++ } ++ } else { ++ scan_width = cfg80211_chandef_to_scan_width(&setup->chandef); ++ setup->basic_rates = ieee80211_mandatory_rates(sband, ++ scan_width); ++ } + } + + err = cfg80211_chandef_dfs_required(&rdev->wiphy, diff --git a/package/kernel/mac80211/patches/370-mac80211-minstrel-remove-unnecessary-debugfs-cleanup.patch b/package/kernel/mac80211/patches/370-mac80211-minstrel-remove-unnecessary-debugfs-cleanup.patch new file mode 100644 index 000000000..14cf6641d --- /dev/null +++ b/package/kernel/mac80211/patches/370-mac80211-minstrel-remove-unnecessary-debugfs-cleanup.patch @@ -0,0 +1,150 @@ +From: Felix Fietkau +Date: Sat, 10 Feb 2018 12:41:51 +0100 +Subject: [PATCH] mac80211: minstrel: remove unnecessary debugfs cleanup + code + +debugfs entries are cleaned up by debugfs_remove_recursive already. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rc80211_minstrel.c ++++ b/net/mac80211/rc80211_minstrel.c +@@ -689,8 +689,8 @@ minstrel_alloc(struct ieee80211_hw *hw, + + #ifdef CPTCFG_MAC80211_DEBUGFS + mp->fixed_rate_idx = (u32) -1; +- mp->dbg_fixed_rate = debugfs_create_u32("fixed_rate_idx", +- S_IRUGO | S_IWUGO, debugfsdir, &mp->fixed_rate_idx); ++ debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir, ++ &mp->fixed_rate_idx); + #endif + + minstrel_init_cck_rates(mp); +@@ -701,9 +701,6 @@ minstrel_alloc(struct ieee80211_hw *hw, + static void + minstrel_free(void *priv) + { +-#ifdef CPTCFG_MAC80211_DEBUGFS +- debugfs_remove(((struct minstrel_priv *)priv)->dbg_fixed_rate); +-#endif + kfree(priv); + } + +@@ -735,7 +732,6 @@ const struct rate_control_ops mac80211_m + .free_sta = minstrel_free_sta, + #ifdef CPTCFG_MAC80211_DEBUGFS + .add_sta_debugfs = minstrel_add_sta_debugfs, +- .remove_sta_debugfs = minstrel_remove_sta_debugfs, + #endif + .get_expected_throughput = minstrel_get_expected_throughput, + }; +--- a/net/mac80211/rc80211_minstrel.h ++++ b/net/mac80211/rc80211_minstrel.h +@@ -109,11 +109,6 @@ struct minstrel_sta_info { + + /* sampling table */ + u8 *sample_table; +- +-#ifdef CPTCFG_MAC80211_DEBUGFS +- struct dentry *dbg_stats; +- struct dentry *dbg_stats_csv; +-#endif + }; + + struct minstrel_priv { +@@ -137,7 +132,6 @@ struct minstrel_priv { + * - setting will be applied on next update + */ + u32 fixed_rate_idx; +- struct dentry *dbg_fixed_rate; + #endif + }; + +@@ -156,7 +150,6 @@ minstrel_get_ewmsd10(struct minstrel_rat + + extern const struct rate_control_ops mac80211_minstrel; + void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); +-void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); + + /* Recalculate success probabilities and counters for a given rate using EWMA */ + void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs); +--- a/net/mac80211/rc80211_minstrel_debugfs.c ++++ b/net/mac80211/rc80211_minstrel_debugfs.c +@@ -214,19 +214,7 @@ minstrel_add_sta_debugfs(void *priv, voi + { + struct minstrel_sta_info *mi = priv_sta; + +- mi->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, mi, +- &minstrel_stat_fops); +- +- mi->dbg_stats_csv = debugfs_create_file("rc_stats_csv", S_IRUGO, dir, +- mi, &minstrel_stat_csv_fops); +-} +- +-void +-minstrel_remove_sta_debugfs(void *priv, void *priv_sta) +-{ +- struct minstrel_sta_info *mi = priv_sta; +- +- debugfs_remove(mi->dbg_stats); +- +- debugfs_remove(mi->dbg_stats_csv); ++ debugfs_create_file("rc_stats", S_IRUGO, dir, mi, &minstrel_stat_fops); ++ debugfs_create_file("rc_stats_csv", S_IRUGO, dir, mi, ++ &minstrel_stat_csv_fops); + } +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -1393,7 +1393,6 @@ static const struct rate_control_ops mac + .free = minstrel_ht_free, + #ifdef CPTCFG_MAC80211_DEBUGFS + .add_sta_debugfs = minstrel_ht_add_sta_debugfs, +- .remove_sta_debugfs = minstrel_ht_remove_sta_debugfs, + #endif + .get_expected_throughput = minstrel_ht_get_expected_throughput, + }; +--- a/net/mac80211/rc80211_minstrel_ht.h ++++ b/net/mac80211/rc80211_minstrel_ht.h +@@ -110,17 +110,12 @@ struct minstrel_ht_sta_priv { + struct minstrel_ht_sta ht; + struct minstrel_sta_info legacy; + }; +-#ifdef CPTCFG_MAC80211_DEBUGFS +- struct dentry *dbg_stats; +- struct dentry *dbg_stats_csv; +-#endif + void *ratelist; + void *sample_table; + bool is_ht; + }; + + void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); +-void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta); + int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate, + int prob_ewma); + +--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c ++++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c +@@ -303,17 +303,8 @@ minstrel_ht_add_sta_debugfs(void *priv, + { + struct minstrel_ht_sta_priv *msp = priv_sta; + +- msp->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, msp, +- &minstrel_ht_stat_fops); +- msp->dbg_stats_csv = debugfs_create_file("rc_stats_csv", S_IRUGO, +- dir, msp, &minstrel_ht_stat_csv_fops); +-} +- +-void +-minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta) +-{ +- struct minstrel_ht_sta_priv *msp = priv_sta; +- +- debugfs_remove(msp->dbg_stats); +- debugfs_remove(msp->dbg_stats_csv); ++ debugfs_create_file("rc_stats", S_IRUGO, dir, msp, ++ &minstrel_ht_stat_fops); ++ debugfs_create_file("rc_stats_csv", S_IRUGO, dir, msp, ++ &minstrel_ht_stat_csv_fops); + } diff --git a/package/kernel/mac80211/patches/371-mac80211-minstrel-merge-with-minstrel_ht-always-enab.patch b/package/kernel/mac80211/patches/371-mac80211-minstrel-merge-with-minstrel_ht-always-enab.patch new file mode 100644 index 000000000..a2bdfd81a --- /dev/null +++ b/package/kernel/mac80211/patches/371-mac80211-minstrel-merge-with-minstrel_ht-always-enab.patch @@ -0,0 +1,576 @@ +From: Felix Fietkau +Date: Sat, 10 Feb 2018 12:43:30 +0100 +Subject: [PATCH] mac80211: minstrel: merge with minstrel_ht, always enable + VHT support + +Legacy-only devices are not very common and the overhead of the extra +code for HT and VHT rates is not big enough to justify all those extra +lines of code to make it optional. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/Kconfig ++++ b/net/mac80211/Kconfig +@@ -25,20 +25,6 @@ config MAC80211_RC_MINSTREL + ---help--- + This option enables the 'minstrel' TX rate control algorithm + +-config MAC80211_RC_MINSTREL_HT +- bool "Minstrel 802.11n support" if EXPERT +- depends on MAC80211_RC_MINSTREL +- default y +- ---help--- +- This option enables the 'minstrel_ht' TX rate control algorithm +- +-config MAC80211_RC_MINSTREL_VHT +- bool "Minstrel 802.11ac support" if EXPERT +- depends on MAC80211_RC_MINSTREL_HT +- default n +- ---help--- +- This option enables VHT in the 'minstrel_ht' TX rate control algorithm +- + choice + prompt "Default rate control algorithm" + depends on MAC80211_HAS_RC +@@ -60,8 +46,7 @@ endchoice + + config MAC80211_RC_DEFAULT + string +- default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL && MAC80211_RC_MINSTREL_HT +- default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL ++ default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL + default "" + + endif +--- a/net/mac80211/Makefile ++++ b/net/mac80211/Makefile +@@ -50,13 +50,14 @@ mac80211-$(CONFIG_PM) += pm.o + + CFLAGS_trace.o := -I$(src) + +-rc80211_minstrel-y := rc80211_minstrel.o +-rc80211_minstrel-$(CPTCFG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o ++rc80211_minstrel-y := \ ++ rc80211_minstrel.o \ ++ rc80211_minstrel_ht.o + +-rc80211_minstrel_ht-y := rc80211_minstrel_ht.o +-rc80211_minstrel_ht-$(CPTCFG_MAC80211_DEBUGFS) += rc80211_minstrel_ht_debugfs.o ++rc80211_minstrel-$(CPTCFG_MAC80211_DEBUGFS) += \ ++ rc80211_minstrel_debugfs.o \ ++ rc80211_minstrel_ht_debugfs.o + + mac80211-$(CPTCFG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y) +-mac80211-$(CPTCFG_MAC80211_RC_MINSTREL_HT) += $(rc80211_minstrel_ht-y) + + ccflags-y += -DDEBUG +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -1252,18 +1252,12 @@ static int __init ieee80211_init(void) + if (ret) + return ret; + +- ret = rc80211_minstrel_ht_init(); +- if (ret) +- goto err_minstrel; +- + ret = ieee80211_iface_init(); + if (ret) + goto err_netdev; + + return 0; + err_netdev: +- rc80211_minstrel_ht_exit(); +- err_minstrel: + rc80211_minstrel_exit(); + + return ret; +@@ -1271,7 +1265,6 @@ static int __init ieee80211_init(void) + + static void __exit ieee80211_exit(void) + { +- rc80211_minstrel_ht_exit(); + rc80211_minstrel_exit(); + + ieee80211s_stop(); +--- a/net/mac80211/rate.h ++++ b/net/mac80211/rate.h +@@ -95,18 +95,5 @@ static inline void rc80211_minstrel_exit + } + #endif + +-#ifdef CPTCFG_MAC80211_RC_MINSTREL_HT +-int rc80211_minstrel_ht_init(void); +-void rc80211_minstrel_ht_exit(void); +-#else +-static inline int rc80211_minstrel_ht_init(void) +-{ +- return 0; +-} +-static inline void rc80211_minstrel_ht_exit(void) +-{ +-} +-#endif +- + + #endif /* IEEE80211_RATE_H */ +--- a/net/mac80211/rc80211_minstrel.c ++++ b/net/mac80211/rc80211_minstrel.c +@@ -572,138 +572,6 @@ minstrel_rate_init(void *priv, struct ie + minstrel_update_rates(mp, mi); + } + +-static void * +-minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) +-{ +- struct ieee80211_supported_band *sband; +- struct minstrel_sta_info *mi; +- struct minstrel_priv *mp = priv; +- struct ieee80211_hw *hw = mp->hw; +- int max_rates = 0; +- int i; +- +- mi = kzalloc(sizeof(struct minstrel_sta_info), gfp); +- if (!mi) +- return NULL; +- +- for (i = 0; i < NUM_NL80211_BANDS; i++) { +- sband = hw->wiphy->bands[i]; +- if (sband && sband->n_bitrates > max_rates) +- max_rates = sband->n_bitrates; +- } +- +- mi->r = kzalloc(sizeof(struct minstrel_rate) * max_rates, gfp); +- if (!mi->r) +- goto error; +- +- mi->sample_table = kmalloc(SAMPLE_COLUMNS * max_rates, gfp); +- if (!mi->sample_table) +- goto error1; +- +- mi->last_stats_update = jiffies; +- return mi; +- +-error1: +- kfree(mi->r); +-error: +- kfree(mi); +- return NULL; +-} +- +-static void +-minstrel_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta) +-{ +- struct minstrel_sta_info *mi = priv_sta; +- +- kfree(mi->sample_table); +- kfree(mi->r); +- kfree(mi); +-} +- +-static void +-minstrel_init_cck_rates(struct minstrel_priv *mp) +-{ +- static const int bitrates[4] = { 10, 20, 55, 110 }; +- struct ieee80211_supported_band *sband; +- u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef); +- int i, j; +- +- sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ]; +- if (!sband) +- return; +- +- for (i = 0, j = 0; i < sband->n_bitrates; i++) { +- struct ieee80211_rate *rate = &sband->bitrates[i]; +- +- if (rate->flags & IEEE80211_RATE_ERP_G) +- continue; +- +- if ((rate_flags & sband->bitrates[i].flags) != rate_flags) +- continue; +- +- for (j = 0; j < ARRAY_SIZE(bitrates); j++) { +- if (rate->bitrate != bitrates[j]) +- continue; +- +- mp->cck_rates[j] = i; +- break; +- } +- } +-} +- +-static void * +-minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) +-{ +- struct minstrel_priv *mp; +- +- mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC); +- if (!mp) +- return NULL; +- +- /* contention window settings +- * Just an approximation. Using the per-queue values would complicate +- * the calculations and is probably unnecessary */ +- mp->cw_min = 15; +- mp->cw_max = 1023; +- +- /* number of packets (in %) to use for sampling other rates +- * sample less often for non-mrr packets, because the overhead +- * is much higher than with mrr */ +- mp->lookaround_rate = 5; +- mp->lookaround_rate_mrr = 10; +- +- /* maximum time that the hw is allowed to stay in one MRR segment */ +- mp->segment_size = 6000; +- +- if (hw->max_rate_tries > 0) +- mp->max_retry = hw->max_rate_tries; +- else +- /* safe default, does not necessarily have to match hw properties */ +- mp->max_retry = 7; +- +- if (hw->max_rates >= 4) +- mp->has_mrr = true; +- +- mp->hw = hw; +- mp->update_interval = 100; +- +-#ifdef CPTCFG_MAC80211_DEBUGFS +- mp->fixed_rate_idx = (u32) -1; +- debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir, +- &mp->fixed_rate_idx); +-#endif +- +- minstrel_init_cck_rates(mp); +- +- return mp; +-} +- +-static void +-minstrel_free(void *priv) +-{ +- kfree(priv); +-} +- + static u32 minstrel_get_expected_throughput(void *priv_sta) + { + struct minstrel_sta_info *mi = priv_sta; +@@ -722,29 +590,8 @@ static u32 minstrel_get_expected_through + } + + const struct rate_control_ops mac80211_minstrel = { +- .name = "minstrel", + .tx_status_ext = minstrel_tx_status, + .get_rate = minstrel_get_rate, + .rate_init = minstrel_rate_init, +- .alloc = minstrel_alloc, +- .free = minstrel_free, +- .alloc_sta = minstrel_alloc_sta, +- .free_sta = minstrel_free_sta, +-#ifdef CPTCFG_MAC80211_DEBUGFS +- .add_sta_debugfs = minstrel_add_sta_debugfs, +-#endif + .get_expected_throughput = minstrel_get_expected_throughput, + }; +- +-int __init +-rc80211_minstrel_init(void) +-{ +- return ieee80211_rate_control_register(&mac80211_minstrel); +-} +- +-void +-rc80211_minstrel_exit(void) +-{ +- ieee80211_rate_control_unregister(&mac80211_minstrel); +-} +- +--- a/net/mac80211/rc80211_minstrel.h ++++ b/net/mac80211/rc80211_minstrel.h +@@ -158,7 +158,5 @@ int minstrel_get_tp_avg(struct minstrel_ + /* debugfs */ + int minstrel_stats_open(struct inode *inode, struct file *file); + int minstrel_stats_csv_open(struct inode *inode, struct file *file); +-ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos); +-int minstrel_stats_release(struct inode *inode, struct file *file); + + #endif +--- a/net/mac80211/rc80211_minstrel_debugfs.c ++++ b/net/mac80211/rc80211_minstrel_debugfs.c +@@ -54,22 +54,6 @@ + #include + #include "rc80211_minstrel.h" + +-ssize_t +-minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) +-{ +- struct minstrel_debugfs_info *ms; +- +- ms = file->private_data; +- return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len); +-} +- +-int +-minstrel_stats_release(struct inode *inode, struct file *file) +-{ +- kfree(file->private_data); +- return 0; +-} +- + int + minstrel_stats_open(struct inode *inode, struct file *file) + { +@@ -135,14 +119,6 @@ minstrel_stats_open(struct inode *inode, + return 0; + } + +-static const struct file_operations minstrel_stat_fops = { +- .owner = THIS_MODULE, +- .open = minstrel_stats_open, +- .read = minstrel_stats_read, +- .release = minstrel_stats_release, +- .llseek = default_llseek, +-}; +- + int + minstrel_stats_csv_open(struct inode *inode, struct file *file) + { +@@ -200,21 +176,3 @@ minstrel_stats_csv_open(struct inode *in + + return 0; + } +- +-static const struct file_operations minstrel_stat_csv_fops = { +- .owner = THIS_MODULE, +- .open = minstrel_stats_csv_open, +- .read = minstrel_stats_read, +- .release = minstrel_stats_release, +- .llseek = default_llseek, +-}; +- +-void +-minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir) +-{ +- struct minstrel_sta_info *mi = priv_sta; +- +- debugfs_create_file("rc_stats", S_IRUGO, dir, mi, &minstrel_stat_fops); +- debugfs_create_file("rc_stats_csv", S_IRUGO, dir, mi, +- &minstrel_stat_csv_fops); +-} +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -137,12 +137,10 @@ + } \ + } + +-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT + static bool minstrel_vht_only = true; + module_param(minstrel_vht_only, bool, 0644); + MODULE_PARM_DESC(minstrel_vht_only, + "Use only VHT rates when VHT is supported by sta."); +-#endif + + /* + * To enable sufficiently targeted rate sampling, MCS rates are divided into +@@ -171,7 +169,6 @@ const struct mcs_group minstrel_mcs_grou + + CCK_GROUP, + +-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT + VHT_GROUP(1, 0, BW_20), + VHT_GROUP(2, 0, BW_20), + VHT_GROUP(3, 0, BW_20), +@@ -195,7 +192,6 @@ const struct mcs_group minstrel_mcs_grou + VHT_GROUP(1, 1, BW_80), + VHT_GROUP(2, 1, BW_80), + VHT_GROUP(3, 1, BW_80), +-#endif + }; + + static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly; +@@ -1146,12 +1142,10 @@ minstrel_ht_update_caps(void *priv, stru + + BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != MINSTREL_GROUPS_NB); + +-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT + if (vht_cap->vht_supported) + use_vht = vht_cap->vht_mcs.tx_mcs_map != cpu_to_le16(~0); + else +-#endif +- use_vht = 0; ++ use_vht = 0; + + msp->is_ht = true; + memset(mi, 0, sizeof(*mi)); +@@ -1226,10 +1220,9 @@ minstrel_ht_update_caps(void *priv, stru + + /* HT rate */ + if (gflags & IEEE80211_TX_RC_MCS) { +-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT + if (use_vht && minstrel_vht_only) + continue; +-#endif ++ + mi->supported[i] = mcs->rx_mask[nss - 1]; + if (mi->supported[i]) + n_supported++; +@@ -1349,16 +1342,88 @@ minstrel_ht_free_sta(void *priv, struct + kfree(msp); + } + ++static void ++minstrel_ht_init_cck_rates(struct minstrel_priv *mp) ++{ ++ static const int bitrates[4] = { 10, 20, 55, 110 }; ++ struct ieee80211_supported_band *sband; ++ u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef); ++ int i, j; ++ ++ sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ]; ++ if (!sband) ++ return; ++ ++ for (i = 0, j = 0; i < sband->n_bitrates; i++) { ++ struct ieee80211_rate *rate = &sband->bitrates[i]; ++ ++ if (rate->flags & IEEE80211_RATE_ERP_G) ++ continue; ++ ++ if ((rate_flags & sband->bitrates[i].flags) != rate_flags) ++ continue; ++ ++ for (j = 0; j < ARRAY_SIZE(bitrates); j++) { ++ if (rate->bitrate != bitrates[j]) ++ continue; ++ ++ mp->cck_rates[j] = i; ++ break; ++ } ++ } ++} ++ + static void * + minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) + { +- return mac80211_minstrel.alloc(hw, debugfsdir); ++ struct minstrel_priv *mp; ++ ++ mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC); ++ if (!mp) ++ return NULL; ++ ++ /* contention window settings ++ * Just an approximation. Using the per-queue values would complicate ++ * the calculations and is probably unnecessary */ ++ mp->cw_min = 15; ++ mp->cw_max = 1023; ++ ++ /* number of packets (in %) to use for sampling other rates ++ * sample less often for non-mrr packets, because the overhead ++ * is much higher than with mrr */ ++ mp->lookaround_rate = 5; ++ mp->lookaround_rate_mrr = 10; ++ ++ /* maximum time that the hw is allowed to stay in one MRR segment */ ++ mp->segment_size = 6000; ++ ++ if (hw->max_rate_tries > 0) ++ mp->max_retry = hw->max_rate_tries; ++ else ++ /* safe default, does not necessarily have to match hw properties */ ++ mp->max_retry = 7; ++ ++ if (hw->max_rates >= 4) ++ mp->has_mrr = true; ++ ++ mp->hw = hw; ++ mp->update_interval = 100; ++ ++#ifdef CPTCFG_MAC80211_DEBUGFS ++ mp->fixed_rate_idx = (u32) -1; ++ debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir, ++ &mp->fixed_rate_idx); ++#endif ++ ++ minstrel_ht_init_cck_rates(mp); ++ ++ return mp; + } + + static void + minstrel_ht_free(void *priv) + { +- mac80211_minstrel.free(priv); ++ kfree(priv); + } + + static u32 minstrel_ht_get_expected_throughput(void *priv_sta) +@@ -1417,14 +1482,14 @@ static void __init init_sample_table(voi + } + + int __init +-rc80211_minstrel_ht_init(void) ++rc80211_minstrel_init(void) + { + init_sample_table(); + return ieee80211_rate_control_register(&mac80211_minstrel_ht); + } + + void +-rc80211_minstrel_ht_exit(void) ++rc80211_minstrel_exit(void) + { + ieee80211_rate_control_unregister(&mac80211_minstrel_ht); + } +--- a/net/mac80211/rc80211_minstrel_ht.h ++++ b/net/mac80211/rc80211_minstrel_ht.h +@@ -15,11 +15,7 @@ + */ + #define MINSTREL_MAX_STREAMS 3 + #define MINSTREL_HT_STREAM_GROUPS 4 /* BW(=2) * SGI(=2) */ +-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT + #define MINSTREL_VHT_STREAM_GROUPS 6 /* BW(=3) * SGI(=2) */ +-#else +-#define MINSTREL_VHT_STREAM_GROUPS 0 +-#endif + + #define MINSTREL_HT_GROUPS_NB (MINSTREL_MAX_STREAMS * \ + MINSTREL_HT_STREAM_GROUPS) +@@ -34,11 +30,7 @@ + #define MINSTREL_CCK_GROUP (MINSTREL_HT_GROUP_0 + MINSTREL_HT_GROUPS_NB) + #define MINSTREL_VHT_GROUP_0 (MINSTREL_CCK_GROUP + 1) + +-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT + #define MCS_GROUP_RATES 10 +-#else +-#define MCS_GROUP_RATES 8 +-#endif + + struct mcs_group { + u32 flags; +--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c ++++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c +@@ -15,6 +15,22 @@ + #include "rc80211_minstrel.h" + #include "rc80211_minstrel_ht.h" + ++static ssize_t ++minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) ++{ ++ struct minstrel_debugfs_info *ms; ++ ++ ms = file->private_data; ++ return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len); ++} ++ ++static int ++minstrel_stats_release(struct inode *inode, struct file *file) ++{ ++ kfree(file->private_data); ++ return 0; ++} ++ + static char * + minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) + { diff --git a/package/kernel/mac80211/patches/372-mac80211-minstrel-reduce-minstrel_mcs_groups-size.patch b/package/kernel/mac80211/patches/372-mac80211-minstrel-reduce-minstrel_mcs_groups-size.patch new file mode 100644 index 000000000..fa51f1be7 --- /dev/null +++ b/package/kernel/mac80211/patches/372-mac80211-minstrel-reduce-minstrel_mcs_groups-size.patch @@ -0,0 +1,358 @@ +From: Felix Fietkau +Date: Sat, 10 Feb 2018 12:45:47 +0100 +Subject: [PATCH] mac80211: minstrel: reduce minstrel_mcs_groups size + +By storing a shift value for all duration values of a group, we can +reduce precision by a neglegible amount to make it fit into a u16 value. +This improves cache footprint and reduces size: + +Before: + text data bss dec hex filename + 10024 116 0 10140 279c rc80211_minstrel_ht.o + +After: + text data bss dec hex filename + 9368 116 0 9484 250c rc80211_minstrel_ht.o + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -52,22 +52,23 @@ + _streams - 1 + + /* MCS rate information for an MCS group */ +-#define MCS_GROUP(_streams, _sgi, _ht40) \ ++#define MCS_GROUP(_streams, _sgi, _ht40, _s) \ + [GROUP_IDX(_streams, _sgi, _ht40)] = { \ + .streams = _streams, \ ++ .shift = _s, \ + .flags = \ + IEEE80211_TX_RC_MCS | \ + (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \ + (_ht40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0), \ + .duration = { \ +- MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26), \ +- MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52), \ +- MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78), \ +- MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104), \ +- MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156), \ +- MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208), \ +- MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234), \ +- MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260) \ ++ MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26) >> _s, \ ++ MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52) >> _s, \ ++ MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78) >> _s, \ ++ MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104) >> _s, \ ++ MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156) >> _s, \ ++ MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208) >> _s, \ ++ MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234) >> _s, \ ++ MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260) >> _s \ + } \ + } + +@@ -80,9 +81,10 @@ + #define BW2VBPS(_bw, r3, r2, r1) \ + (_bw == BW_80 ? r3 : _bw == BW_40 ? r2 : r1) + +-#define VHT_GROUP(_streams, _sgi, _bw) \ ++#define VHT_GROUP(_streams, _sgi, _bw, _s) \ + [VHT_GROUP_IDX(_streams, _sgi, _bw)] = { \ + .streams = _streams, \ ++ .shift = _s, \ + .flags = \ + IEEE80211_TX_RC_VHT_MCS | \ + (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \ +@@ -90,25 +92,25 @@ + _bw == BW_40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0), \ + .duration = { \ + MCS_DURATION(_streams, _sgi, \ +- BW2VBPS(_bw, 117, 54, 26)), \ ++ BW2VBPS(_bw, 117, 54, 26)) >> _s, \ + MCS_DURATION(_streams, _sgi, \ +- BW2VBPS(_bw, 234, 108, 52)), \ ++ BW2VBPS(_bw, 234, 108, 52)) >> _s, \ + MCS_DURATION(_streams, _sgi, \ +- BW2VBPS(_bw, 351, 162, 78)), \ ++ BW2VBPS(_bw, 351, 162, 78)) >> _s, \ + MCS_DURATION(_streams, _sgi, \ +- BW2VBPS(_bw, 468, 216, 104)), \ ++ BW2VBPS(_bw, 468, 216, 104)) >> _s, \ + MCS_DURATION(_streams, _sgi, \ +- BW2VBPS(_bw, 702, 324, 156)), \ ++ BW2VBPS(_bw, 702, 324, 156)) >> _s, \ + MCS_DURATION(_streams, _sgi, \ +- BW2VBPS(_bw, 936, 432, 208)), \ ++ BW2VBPS(_bw, 936, 432, 208)) >> _s, \ + MCS_DURATION(_streams, _sgi, \ +- BW2VBPS(_bw, 1053, 486, 234)), \ ++ BW2VBPS(_bw, 1053, 486, 234)) >> _s, \ + MCS_DURATION(_streams, _sgi, \ +- BW2VBPS(_bw, 1170, 540, 260)), \ ++ BW2VBPS(_bw, 1170, 540, 260)) >> _s, \ + MCS_DURATION(_streams, _sgi, \ +- BW2VBPS(_bw, 1404, 648, 312)), \ ++ BW2VBPS(_bw, 1404, 648, 312)) >> _s, \ + MCS_DURATION(_streams, _sgi, \ +- BW2VBPS(_bw, 1560, 720, 346)) \ ++ BW2VBPS(_bw, 1560, 720, 346)) >> _s \ + } \ + } + +@@ -121,19 +123,20 @@ + (CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \ + CCK_DURATION(_bitrate, _short, AVG_PKT_SIZE)) + +-#define CCK_DURATION_LIST(_short) \ +- CCK_ACK_DURATION(10, _short), \ +- CCK_ACK_DURATION(20, _short), \ +- CCK_ACK_DURATION(55, _short), \ +- CCK_ACK_DURATION(110, _short) ++#define CCK_DURATION_LIST(_short, _s) \ ++ CCK_ACK_DURATION(10, _short) >> _s, \ ++ CCK_ACK_DURATION(20, _short) >> _s, \ ++ CCK_ACK_DURATION(55, _short) >> _s, \ ++ CCK_ACK_DURATION(110, _short) >> _s + +-#define CCK_GROUP \ ++#define CCK_GROUP(_s) \ + [MINSTREL_CCK_GROUP] = { \ + .streams = 0, \ + .flags = 0, \ ++ .shift = _s, \ + .duration = { \ +- CCK_DURATION_LIST(false), \ +- CCK_DURATION_LIST(true) \ ++ CCK_DURATION_LIST(false, _s), \ ++ CCK_DURATION_LIST(true, _s) \ + } \ + } + +@@ -151,47 +154,47 @@ MODULE_PARM_DESC(minstrel_vht_only, + * BW -> SGI -> #streams + */ + const struct mcs_group minstrel_mcs_groups[] = { +- MCS_GROUP(1, 0, BW_20), +- MCS_GROUP(2, 0, BW_20), +- MCS_GROUP(3, 0, BW_20), ++ MCS_GROUP(1, 0, BW_20, 5), ++ MCS_GROUP(2, 0, BW_20, 4), ++ MCS_GROUP(3, 0, BW_20, 4), + +- MCS_GROUP(1, 1, BW_20), +- MCS_GROUP(2, 1, BW_20), +- MCS_GROUP(3, 1, BW_20), ++ MCS_GROUP(1, 1, BW_20, 5), ++ MCS_GROUP(2, 1, BW_20, 4), ++ MCS_GROUP(3, 1, BW_20, 4), + +- MCS_GROUP(1, 0, BW_40), +- MCS_GROUP(2, 0, BW_40), +- MCS_GROUP(3, 0, BW_40), ++ MCS_GROUP(1, 0, BW_40, 4), ++ MCS_GROUP(2, 0, BW_40, 4), ++ MCS_GROUP(3, 0, BW_40, 4), + +- MCS_GROUP(1, 1, BW_40), +- MCS_GROUP(2, 1, BW_40), +- MCS_GROUP(3, 1, BW_40), ++ MCS_GROUP(1, 1, BW_40, 4), ++ MCS_GROUP(2, 1, BW_40, 4), ++ MCS_GROUP(3, 1, BW_40, 4), + +- CCK_GROUP, ++ CCK_GROUP(8), + +- VHT_GROUP(1, 0, BW_20), +- VHT_GROUP(2, 0, BW_20), +- VHT_GROUP(3, 0, BW_20), ++ VHT_GROUP(1, 0, BW_20, 5), ++ VHT_GROUP(2, 0, BW_20, 4), ++ VHT_GROUP(3, 0, BW_20, 4), + +- VHT_GROUP(1, 1, BW_20), +- VHT_GROUP(2, 1, BW_20), +- VHT_GROUP(3, 1, BW_20), ++ VHT_GROUP(1, 1, BW_20, 5), ++ VHT_GROUP(2, 1, BW_20, 4), ++ VHT_GROUP(3, 1, BW_20, 4), + +- VHT_GROUP(1, 0, BW_40), +- VHT_GROUP(2, 0, BW_40), +- VHT_GROUP(3, 0, BW_40), ++ VHT_GROUP(1, 0, BW_40, 4), ++ VHT_GROUP(2, 0, BW_40, 4), ++ VHT_GROUP(3, 0, BW_40, 4), + +- VHT_GROUP(1, 1, BW_40), +- VHT_GROUP(2, 1, BW_40), +- VHT_GROUP(3, 1, BW_40), ++ VHT_GROUP(1, 1, BW_40, 4), ++ VHT_GROUP(2, 1, BW_40, 4), ++ VHT_GROUP(3, 1, BW_40, 4), + +- VHT_GROUP(1, 0, BW_80), +- VHT_GROUP(2, 0, BW_80), +- VHT_GROUP(3, 0, BW_80), ++ VHT_GROUP(1, 0, BW_80, 4), ++ VHT_GROUP(2, 0, BW_80, 4), ++ VHT_GROUP(3, 0, BW_80, 4), + +- VHT_GROUP(1, 1, BW_80), +- VHT_GROUP(2, 1, BW_80), +- VHT_GROUP(3, 1, BW_80), ++ VHT_GROUP(1, 1, BW_80, 4), ++ VHT_GROUP(2, 1, BW_80, 4), ++ VHT_GROUP(3, 1, BW_80, 4), + }; + + static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly; +@@ -307,7 +310,8 @@ minstrel_ht_get_tp_avg(struct minstrel_h + if (group != MINSTREL_CCK_GROUP) + nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); + +- nsecs += minstrel_mcs_groups[group].duration[rate]; ++ nsecs += minstrel_mcs_groups[group].duration[rate] << ++ minstrel_mcs_groups[group].shift; + + /* + * For the throughput calculation, limit the probability value to 90% to +@@ -755,12 +759,19 @@ minstrel_ht_tx_status(void *priv, struct + minstrel_ht_update_rates(mp, mi); + } + ++static inline int ++minstrel_get_duration(int index) ++{ ++ const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; ++ unsigned int duration = group->duration[index % MCS_GROUP_RATES]; ++ return duration << group->shift; ++} ++ + static void + minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, + int index) + { + struct minstrel_rate_stats *mrs; +- const struct mcs_group *group; + unsigned int tx_time, tx_time_rtscts, tx_time_data; + unsigned int cw = mp->cw_min; + unsigned int ctime = 0; +@@ -779,8 +790,7 @@ minstrel_calc_retransmit(struct minstrel + mrs->retry_count_rtscts = 2; + mrs->retry_updated = true; + +- group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; +- tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len / 1000; ++ tx_time_data = minstrel_get_duration(index) * ampdu_len / 1000; + + /* Contention time for first 2 tries */ + ctime = (t_slot * cw) >> 1; +@@ -874,20 +884,24 @@ minstrel_ht_get_max_amsdu_len(struct min + int group = mi->max_prob_rate / MCS_GROUP_RATES; + const struct mcs_group *g = &minstrel_mcs_groups[group]; + int rate = mi->max_prob_rate % MCS_GROUP_RATES; ++ unsigned int duration; + + /* Disable A-MSDU if max_prob_rate is bad */ + if (mi->groups[group].rates[rate].prob_ewma < MINSTREL_FRAC(50, 100)) + return 1; + ++ duration = g->duration[rate]; ++ duration <<= g->shift; ++ + /* If the rate is slower than single-stream MCS1, make A-MSDU limit small */ +- if (g->duration[rate] > MCS_DURATION(1, 0, 52)) ++ if (duration > MCS_DURATION(1, 0, 52)) + return 500; + + /* + * If the rate is slower than single-stream MCS4, limit A-MSDU to usual + * data packet size + */ +- if (g->duration[rate] > MCS_DURATION(1, 0, 104)) ++ if (duration > MCS_DURATION(1, 0, 104)) + return 1600; + + /* +@@ -895,7 +909,7 @@ minstrel_ht_get_max_amsdu_len(struct min + * rate success probability is less than 75%, limit A-MSDU to twice the usual + * data packet size + */ +- if (g->duration[rate] > MCS_DURATION(1, 0, 260) || ++ if (duration > MCS_DURATION(1, 0, 260) || + (minstrel_ht_get_prob_ewma(mi, mi->max_tp_rate[0]) < + MINSTREL_FRAC(75, 100))) + return 3200; +@@ -942,13 +956,6 @@ minstrel_ht_update_rates(struct minstrel + rate_control_set_rates(mp->hw, mi->sta, rates); + } + +-static inline int +-minstrel_get_duration(int index) +-{ +- const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; +- return group->duration[index % MCS_GROUP_RATES]; +-} +- + static int + minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) + { +--- a/net/mac80211/rc80211_minstrel_ht.h ++++ b/net/mac80211/rc80211_minstrel_ht.h +@@ -33,9 +33,10 @@ + #define MCS_GROUP_RATES 10 + + struct mcs_group { +- u32 flags; +- unsigned int streams; +- unsigned int duration[MCS_GROUP_RATES]; ++ u16 flags; ++ u8 streams; ++ u8 shift; ++ u16 duration[MCS_GROUP_RATES]; + }; + + extern const struct mcs_group minstrel_mcs_groups[]; +--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c ++++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c +@@ -58,6 +58,7 @@ minstrel_ht_stats_dump(struct minstrel_h + static const int bitrates[4] = { 10, 20, 55, 110 }; + int idx = i * MCS_GROUP_RATES + j; + unsigned int prob_ewmsd; ++ unsigned int duration; + + if (!(mi->supported[i] & BIT(j))) + continue; +@@ -95,7 +96,9 @@ minstrel_ht_stats_dump(struct minstrel_h + p += sprintf(p, " %3u ", idx); + + /* tx_time[rate(i)] in usec */ +- tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000); ++ duration = mg->duration[j]; ++ duration <<= mg->shift; ++ tx_time = DIV_ROUND_CLOSEST(duration, 1000); + p += sprintf(p, "%6u ", tx_time); + + tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100)); +@@ -204,6 +207,7 @@ minstrel_ht_stats_csv_dump(struct minstr + static const int bitrates[4] = { 10, 20, 55, 110 }; + int idx = i * MCS_GROUP_RATES + j; + unsigned int prob_ewmsd; ++ unsigned int duration; + + if (!(mi->supported[i] & BIT(j))) + continue; +@@ -238,7 +242,10 @@ minstrel_ht_stats_csv_dump(struct minstr + } + + p += sprintf(p, "%u,", idx); +- tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000); ++ ++ duration = mg->duration[j]; ++ duration <<= mg->shift; ++ tx_time = DIV_ROUND_CLOSEST(duration, 1000); + p += sprintf(p, "%u,", tx_time); + + tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100)); diff --git a/package/kernel/mac80211/patches/373-mac80211-minstrel-fix-using-short-preamble-CCK-rates.patch b/package/kernel/mac80211/patches/373-mac80211-minstrel-fix-using-short-preamble-CCK-rates.patch new file mode 100644 index 000000000..502d8c776 --- /dev/null +++ b/package/kernel/mac80211/patches/373-mac80211-minstrel-fix-using-short-preamble-CCK-rates.patch @@ -0,0 +1,31 @@ +From: Felix Fietkau +Date: Sat, 10 Feb 2018 13:43:07 +0100 +Subject: [PATCH] mac80211: minstrel: fix using short preamble CCK rates on + HT clients + +mi->supported[MINSTREL_CCK_GROUP] needs to be updated + +Fixes: 782dda00ab8e ("mac80211: minstrel_ht: move short preamble check out of get_rate") +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -1135,7 +1135,6 @@ minstrel_ht_update_caps(void *priv, stru + struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs; + u16 ht_cap = sta->ht_cap.cap; + struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; +- struct sta_info *sinfo = container_of(sta, struct sta_info, sta); + int use_vht; + int n_supported = 0; + int ack_dur; +@@ -1267,8 +1266,7 @@ minstrel_ht_update_caps(void *priv, stru + if (!n_supported) + goto use_legacy; + +- if (test_sta_flag(sinfo, WLAN_STA_SHORT_PREAMBLE)) +- mi->cck_supported_short |= mi->cck_supported_short << 4; ++ mi->supported[MINSTREL_CCK_GROUP] |= mi->cck_supported_short << 4; + + /* create an initial rate table with the lowest supported rates */ + minstrel_ht_update_stats(mp, mi); diff --git a/package/kernel/mac80211/patches/374-ath9k-Protect-queue-draining-by-rcu_read_lock.patch b/package/kernel/mac80211/patches/374-ath9k-Protect-queue-draining-by-rcu_read_lock.patch new file mode 100644 index 000000000..9970574e1 --- /dev/null +++ b/package/kernel/mac80211/patches/374-ath9k-Protect-queue-draining-by-rcu_read_lock.patch @@ -0,0 +1,43 @@ +From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= +Date: Fri, 2 Feb 2018 11:36:45 +0100 +Subject: [PATCH] ath9k: Protect queue draining by rcu_read_lock() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When ath9k was switched over to use the mac80211 intermediate queues, +node cleanup now drains the mac80211 queues. However, this call path is +not protected by rcu_read_lock() as it was previously entirely internal +to the driver which uses its own locking. + +This leads to a possible rcu_dereference() without holding +rcu_read_lock(); but only if a station is cleaned up while having +packets queued on the TXQ. Fix this by adding the rcu_read_lock() to the +caller in ath9k. + +Fixes: 50f08edf9809 ("ath9k: Switch to using mac80211 intermediate software queues.") +Cc: stable@vger.kernel.org +Reported-by: Ben Greear +Signed-off-by: Toke Høiland-Jørgensen +--- + +--- a/drivers/net/wireless/ath/ath9k/xmit.c ++++ b/drivers/net/wireless/ath/ath9k/xmit.c +@@ -2930,6 +2930,8 @@ void ath_tx_node_cleanup(struct ath_soft + struct ath_txq *txq; + int tidno; + ++ rcu_read_lock(); ++ + for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) { + tid = ath_node_to_tid(an, tidno); + txq = tid->txq; +@@ -2947,6 +2949,8 @@ void ath_tx_node_cleanup(struct ath_soft + if (!an->sta) + break; /* just one multicast ath_atx_tid */ + } ++ ++ rcu_read_unlock(); + } + + #ifdef CPTCFG_ATH9K_TX99 diff --git a/package/kernel/mac80211/patches/375-mac80211-minstrel-fix-CCK-rate-group-streams-value.patch b/package/kernel/mac80211/patches/375-mac80211-minstrel-fix-CCK-rate-group-streams-value.patch new file mode 100644 index 000000000..f0ffcd965 --- /dev/null +++ b/package/kernel/mac80211/patches/375-mac80211-minstrel-fix-CCK-rate-group-streams-value.patch @@ -0,0 +1,20 @@ +From: Felix Fietkau +Date: Thu, 1 Mar 2018 13:27:54 +0100 +Subject: [PATCH] mac80211: minstrel: fix CCK rate group streams value + +Fixes a harmless underflow issue when CCK rates are actively being used + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -131,7 +131,7 @@ + + #define CCK_GROUP(_s) \ + [MINSTREL_CCK_GROUP] = { \ +- .streams = 0, \ ++ .streams = 1, \ + .flags = 0, \ + .shift = _s, \ + .duration = { \ diff --git a/package/kernel/mac80211/patches/376-mac80211-minstrel-fix-sampling-reporting-of-CCK-rate.patch b/package/kernel/mac80211/patches/376-mac80211-minstrel-fix-sampling-reporting-of-CCK-rate.patch new file mode 100644 index 000000000..e0049c36e --- /dev/null +++ b/package/kernel/mac80211/patches/376-mac80211-minstrel-fix-sampling-reporting-of-CCK-rate.patch @@ -0,0 +1,58 @@ +From: Felix Fietkau +Date: Thu, 1 Mar 2018 13:28:48 +0100 +Subject: [PATCH] mac80211: minstrel: fix sampling/reporting of CCK rates + in HT mode + +Long/short preamble selection cannot be sampled separately, since it +depends on the BSS state. Because of that, sampling attempts to +currently not used preamble modes are not counted in the statistics, +which leads to CCK rates being sampled too often. + +Fix statistics accounting for long/short preamble by increasing the +index where necessary. +Fix excessive CCK rate sampling by dropping unsupported sample attempts. + +This improves throughput on 2.4 GHz channels + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -281,7 +281,8 @@ minstrel_ht_get_stats(struct minstrel_pr + break; + + /* short preamble */ +- if (!(mi->supported[group] & BIT(idx))) ++ if ((mi->supported[group] & BIT(idx + 4)) && ++ (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)) + idx += 4; + } + return &mi->groups[group].rates[idx]; +@@ -1080,18 +1081,23 @@ minstrel_ht_get_rate(void *priv, struct + return; + + sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES]; ++ sample_idx %= MCS_GROUP_RATES; ++ ++ if (sample_group == &minstrel_mcs_groups[MINSTREL_CCK_GROUP] && ++ (sample_idx >= 4) != txrc->short_preamble) ++ return; ++ + info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; + rate->count = 1; + +- if (sample_idx / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) { ++ if (sample_group == &minstrel_mcs_groups[MINSTREL_CCK_GROUP]) { + int idx = sample_idx % ARRAY_SIZE(mp->cck_rates); + rate->idx = mp->cck_rates[idx]; + } else if (sample_group->flags & IEEE80211_TX_RC_VHT_MCS) { + ieee80211_rate_set_vht(rate, sample_idx % MCS_GROUP_RATES, + sample_group->streams); + } else { +- rate->idx = sample_idx % MCS_GROUP_RATES + +- (sample_group->streams - 1) * 8; ++ rate->idx = sample_idx + (sample_group->streams - 1) * 8; + } + + rate->flags = sample_group->flags; diff --git a/package/kernel/mac80211/patches/377-mac80211-minstrel-do-not-sample-rates-3-times-slower.patch b/package/kernel/mac80211/patches/377-mac80211-minstrel-do-not-sample-rates-3-times-slower.patch new file mode 100644 index 000000000..414cb137d --- /dev/null +++ b/package/kernel/mac80211/patches/377-mac80211-minstrel-do-not-sample-rates-3-times-slower.patch @@ -0,0 +1,40 @@ +From: Felix Fietkau +Date: Sat, 3 Mar 2018 18:48:58 +0100 +Subject: [PATCH] mac80211: minstrel: do not sample rates 3 times slower than + max_prob_rate + +These rates are highly unlikely to be used quickly, even if the link +deteriorates rapidly. This improves throughput in cases where CCK rates +are not reliable enough to be skipped entirely during sampling. +Sampling these rates regularly can cost a lot of airtime. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -1004,10 +1004,13 @@ minstrel_get_sample_rate(struct minstrel + return -1; + + /* +- * Do not sample if the probability is already higher than 95% +- * to avoid wasting airtime. ++ * Do not sample if the probability is already higher than 95%, ++ * or if the rate is 3 times slower than the current max probability ++ * rate, to avoid wasting airtime. + */ +- if (mrs->prob_ewma > MINSTREL_FRAC(95, 100)) ++ sample_dur = minstrel_get_duration(sample_idx); ++ if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) || ++ minstrel_get_duration(mi->max_prob_rate) * 3 < sample_dur) + return -1; + + /* +@@ -1017,7 +1020,6 @@ minstrel_get_sample_rate(struct minstrel + + cur_max_tp_streams = minstrel_mcs_groups[tp_rate1 / + MCS_GROUP_RATES].streams; +- sample_dur = minstrel_get_duration(sample_idx); + if (sample_dur >= minstrel_get_duration(tp_rate2) && + (cur_max_tp_streams - 1 < + minstrel_mcs_groups[sample_group].streams || diff --git a/package/kernel/mac80211/patches/378-mac80211-fix-memory-accounting-with-A-MSDU-aggregati.patch b/package/kernel/mac80211/patches/378-mac80211-fix-memory-accounting-with-A-MSDU-aggregati.patch new file mode 100644 index 000000000..c64457a17 --- /dev/null +++ b/package/kernel/mac80211/patches/378-mac80211-fix-memory-accounting-with-A-MSDU-aggregati.patch @@ -0,0 +1,58 @@ +From: Felix Fietkau +Date: Thu, 8 Mar 2018 21:00:56 +0100 +Subject: [PATCH] mac80211: fix memory accounting with A-MSDU aggregation + +fq uses skb->truesize for memory usage tracking. Increments/decrements +are done on enqueue/dequeue. +When A-MSDU aggregation is performed on tx side, the packet is +aggregated with the last packet in the queue belonging to the same flow. +There are multiple bugs here: +- The truesize field of the aggregated packet isn't updated, so memory +usage is underestimated +- fq->memory_usage isn't adjusted. + +Because of the combination of both bugs, this only causes tx issues in +rare cases, mainly when the A-MSDU head needs to be reallocated. + +Fix this by adjusting both truesize of the A-MSDU head and adding the +truesize delta to fq->memory_usage. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3171,6 +3171,7 @@ static bool ieee80211_amsdu_aggregate(st + u8 max_subframes = sta->sta.max_amsdu_subframes; + int max_frags = local->hw.max_tx_fragments; + int max_amsdu_len = sta->sta.max_amsdu_len; ++ int orig_truesize; + __be16 len; + void *data; + bool ret = false; +@@ -3201,12 +3202,13 @@ static bool ieee80211_amsdu_aggregate(st + flow = fq_flow_classify(fq, tin, skb, fq_flow_get_default_func); + head = skb_peek_tail(&flow->queue); + if (!head) +- goto out; ++ goto unlock; + ++ orig_truesize = head->truesize; + orig_len = head->len; + + if (skb->len + head->len > max_amsdu_len) +- goto out; ++ goto unlock; + + if (!ieee80211_amsdu_prepare_head(sdata, fast_tx, head)) + goto out; +@@ -3249,6 +3251,9 @@ static bool ieee80211_amsdu_aggregate(st + fq_recalc_backlog(fq, tin, flow); + + out: ++ fq->memory_usage += head->truesize - orig_truesize; ++ ++unlock: + spin_unlock_bh(&fq->lock); + + return ret; diff --git a/package/kernel/mac80211/patches/402-ath_regd_optional.patch b/package/kernel/mac80211/patches/402-ath_regd_optional.patch index edd4ce26b..8fa56f40a 100644 --- a/package/kernel/mac80211/patches/402-ath_regd_optional.patch +++ b/package/kernel/mac80211/patches/402-ath_regd_optional.patch @@ -57,19 +57,7 @@ if (!wiphy->bands[NL80211_BAND_5GHZ]) return; -@@ -544,6 +559,11 @@ void ath_reg_notifier_apply(struct wiphy - ath_reg_dyn_country(wiphy, reg, request); - break; - } -+ -+ /* Prevent broken CTLs from being applied */ -+ if (IS_ENABLED(CPTCFG_ATH_USER_REGD) && -+ reg->regpair != common->reg_world_copy.regpair) -+ reg->regpair = ath_get_regpair(WOR0_WORLD); - } - EXPORT_SYMBOL(ath_reg_notifier_apply); - -@@ -639,6 +659,10 @@ ath_regd_init_wiphy(struct ath_regulator +@@ -639,6 +654,10 @@ ath_regd_init_wiphy(struct ath_regulator const struct ieee80211_regdomain *regd; wiphy->reg_notifier = reg_notifier; @@ -80,18 +68,6 @@ wiphy->regulatory_flags |= REGULATORY_STRICT_REG | REGULATORY_CUSTOM_REG; -@@ -767,10 +791,7 @@ ath_regd_init(struct ath_regulatory *reg - if (r) - return r; - -- if (ath_is_world_regd(reg)) -- memcpy(&common->reg_world_copy, reg, -- sizeof(struct ath_regulatory)); -- -+ memcpy(&common->reg_world_copy, reg, sizeof(struct ath_regulatory)); - ath_regd_init_wiphy(reg, wiphy, reg_notifier); - - return 0; --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig @@ -23,6 +23,9 @@ config WLAN_VENDOR_ATH diff --git a/package/kernel/mac80211/patches/406-ath_relax_default_regd.patch b/package/kernel/mac80211/patches/406-ath_relax_default_regd.patch index 44e8f3281..35b0f2b76 100644 --- a/package/kernel/mac80211/patches/406-ath_relax_default_regd.patch +++ b/package/kernel/mac80211/patches/406-ath_relax_default_regd.patch @@ -39,7 +39,7 @@ bool ath_is_world_regd(struct ath_regulatory *reg) { return is_wwr_sku(ath_regd_get_eepromRD(reg)); -@@ -663,6 +671,9 @@ ath_regd_init_wiphy(struct ath_regulator +@@ -658,6 +666,9 @@ ath_regd_init_wiphy(struct ath_regulator if (IS_ENABLED(CPTCFG_ATH_USER_REGD)) return 0; diff --git a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch index 2a2d2f3cd..19f0ff2ae 100644 --- a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch +++ b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch @@ -77,7 +77,7 @@ static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, const u8 *addr) { -@@ -3720,6 +3733,7 @@ const struct cfg80211_ops mac80211_confi +@@ -3721,6 +3734,7 @@ const struct cfg80211_ops mac80211_confi .set_wiphy_params = ieee80211_set_wiphy_params, .set_tx_power = ieee80211_set_tx_power, .get_tx_power = ieee80211_get_tx_power, diff --git a/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch b/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch index cc29402c0..b7bce637f 100644 --- a/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch +++ b/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch @@ -13,7 +13,7 @@ Signed-off-by: RafaÅ‚ MiÅ‚ecki --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -@@ -1198,6 +1198,7 @@ int __init brcmf_core_init(void) +@@ -1295,6 +1295,7 @@ int __init brcmf_core_init(void) { if (!schedule_work(&brcmf_driver_work)) return -EBUSY; diff --git a/package/kernel/mac80211/patches/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch b/package/kernel/mac80211/patches/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch index 7fc1e449d..1345e85f6 100644 --- a/package/kernel/mac80211/patches/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch +++ b/package/kernel/mac80211/patches/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch @@ -10,7 +10,7 @@ Signed-off-by: RafaÅ‚ MiÅ‚ecki --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -655,9 +655,37 @@ static struct wireless_dev *brcmf_cfg802 +@@ -614,9 +614,37 @@ static struct wireless_dev *brcmf_cfg802 enum nl80211_iftype type, struct vif_params *params) { diff --git a/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch b/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch index 43f8fbf67..c02d00966 100644 --- a/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch +++ b/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch @@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -2838,6 +2838,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip +@@ -2727,6 +2727,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip * preference in cfg struct to apply this to * FW later while initializing the dongle */ diff --git a/package/kernel/mac80211/patches/864-brcmfmac-do-not-use-internal-roaming-engine-by-default.patch b/package/kernel/mac80211/patches/864-brcmfmac-do-not-use-internal-roaming-engine-by-default.patch index 891c539fb..0ae012cbe 100644 --- a/package/kernel/mac80211/patches/864-brcmfmac-do-not-use-internal-roaming-engine-by-default.patch +++ b/package/kernel/mac80211/patches/864-brcmfmac-do-not-use-internal-roaming-engine-by-default.patch @@ -9,7 +9,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c -@@ -69,7 +69,11 @@ static int brcmf_fcmode; +@@ -71,7 +71,11 @@ static int brcmf_fcmode; module_param_named(fcmode, brcmf_fcmode, int, 0); MODULE_PARM_DESC(fcmode, "Mode of firmware signalled flow control"); diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile index 441f59e43..d83e38793 100644 --- a/package/kernel/mt76/Makefile +++ b/package/kernel/mt76/Makefile @@ -8,9 +8,9 @@ PKG_LICENSE_FILES:= PKG_SOURCE_URL:=https://github.com/openwrt/mt76 PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2017-12-17 -PKG_SOURCE_VERSION:=68b0cf17efe32623efd2a46d33b0b551bb78cbbe -PKG_MIRROR_HASH:=855901e5e02249f53bb943d2d5da5bb3cb357f02e4c68c6291604867e250e9bd +PKG_SOURCE_DATE:=2018-02-27 +PKG_SOURCE_VERSION:=ffa2069e78cf267ce79d7a8820aa0368161ff6e1 +PKG_MIRROR_HASH:=dee90d713e3c351ee51da51030e56867fa9bd2eac8f222734d0573223a5e0a41 PKG_MAINTAINER:=Felix Fietkau PKG_BUILD_PARALLEL:=1 diff --git a/package/kernel/mwlwifi/Makefile b/package/kernel/mwlwifi/Makefile index f8e70e54a..1613fb405 100644 --- a/package/kernel/mwlwifi/Makefile +++ b/package/kernel/mwlwifi/Makefile @@ -8,7 +8,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=mwlwifi -PKG_VERSION:=10.3.4.0-20171214 PKG_RELEASE=1 PKG_LICENSE:=ISC @@ -16,8 +15,9 @@ PKG_LICENSE_FILES:= PKG_SOURCE_URL:=https://github.com/kaloz/mwlwifi PKG_SOURCE_PROTO:=git -PKG_SOURCE_VERSION:=843d00cd9c134629b9dad7162831ec5f136399b3 -PKG_MIRROR_HASH:=080c491473f0dbe9a7cac0fa3c6d004bf2dc3bd953a9f9d074eb8876a86437c2 +PKG_SOURCE_DATE:=2018-03-05 +PKG_SOURCE_VERSION:=b1b9a9e1c1beee30a8cce4038f4109727362ebe0 +PKG_MIRROR_HASH:=720a3bc5ecb31419fdeebe02efba764ecc77815332114e97dc80f989d85a816f PKG_MAINTAINER:=Imre Kaloz PKG_BUILD_PARALLEL:=1 @@ -27,7 +27,7 @@ include $(INCLUDE_DIR)/package.mk define KernelPackage/mwlwifi SUBMENU:=Wireless Drivers - TITLE:=Marvell 88W8864 wireless driver + TITLE:=Marvell 88W8864/88W8897/88W8964 wireless driver DEPENDS:=+kmod-mac80211 +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT +@DRIVER_11W_SUPPORT @PCI_SUPPORT @TARGET_mvebu FILES:=$(PKG_BUILD_DIR)/mwlwifi.ko AUTOLOAD:=$(call AutoLoad,50,mwlwifi) @@ -49,13 +49,45 @@ define Build/Compile modules endef -define KernelPackage/mwlwifi/install +define Package/mwlwifi-firmware-default + SECTION:=firmware + CATEGORY:=Firmware + TITLE:=Marvell $(1) firmware + DEPENDS:=+kmod-mwlwifi @TARGET_mvebu +endef + +define Package/mwlwifi-firmware/install $(INSTALL_DIR) $(1)/lib/firmware $(INSTALL_DIR) $(1)/lib/firmware/mwlwifi - $(CP) $(PKG_BUILD_DIR)/bin/firmware/88W8864.bin $(1)/lib/firmware/mwlwifi/ - $(CP) $(PKG_BUILD_DIR)/bin/firmware/88W8897.bin $(1)/lib/firmware/mwlwifi/ - $(CP) $(PKG_BUILD_DIR)/bin/firmware/88W8964.bin $(1)/lib/firmware/mwlwifi/ - $(CP) $(PKG_BUILD_DIR)/bin/firmware/Marvell_license.txt $(1)/lib/firmware/mwlwifi/ + $(CP) $(PKG_BUILD_DIR)/bin/firmware/$(2) $(1)/lib/firmware/mwlwifi/ + $(CP) $(PKG_BUILD_DIR)/bin/firmware/Marvell_license.txt $(1)/lib/firmware/mwlwifi/$(2).Marvell_license.txt +endef + +define Package/mwlwifi-firmware-88w8864 +$(call Package/mwlwifi-firmware-default,88W8864) +endef + +define Package/mwlwifi-firmware-88w8864/install + $(call Package/mwlwifi-firmware/install,$(1),88W8864.bin) +endef + +define Package/mwlwifi-firmware-88w8897 +$(call Package/mwlwifi-firmware-default,88W8897) +endef + +define Package/mwlwifi-firmware-88w8897/install + $(call Package/mwlwifi-firmware/install,$(1),88W8897.bin) +endef + +define Package/mwlwifi-firmware-88w8964 +$(call Package/mwlwifi-firmware-default,88W8964) +endef + +define Package/mwlwifi-firmware-88w8964/install + $(call Package/mwlwifi-firmware/install,$(1),88W8964.bin) endef $(eval $(call KernelPackage,mwlwifi)) +$(eval $(call BuildPackage,mwlwifi-firmware-88w8864)) +$(eval $(call BuildPackage,mwlwifi-firmware-88w8897)) +$(eval $(call BuildPackage,mwlwifi-firmware-88w8964)) diff --git a/package/kernel/wrt55agv2-spidevs/Makefile b/package/kernel/wrt55agv2-spidevs/Makefile deleted file mode 100644 index d80c1e570..000000000 --- a/package/kernel/wrt55agv2-spidevs/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright (C) 2008 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=wrt55agv2-spidevs -PKG_RELEASE:=1 - -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/wrt55agv2-spidevs - SUBMENU:=Other modules - TITLE:=WRT55AG v2 SPI devices support - DEPENDS:=@TARGET_ath25 +kmod-spi-gpio-old +kmod-spi-ks8995 - FILES:=$(PKG_BUILD_DIR)/wrt55agv2_spidevs.ko -endef - -define KernelPackage/wrt55agv2-spidevs/description - Kernel module for the SPI devices on the WRT55AG v2 board. -endef - -MAKE_OPTS:= \ - $(KERNEL_MAKE_FLAGS) \ - SUBDIRS="$(PKG_BUILD_DIR)" - -define Build/Compile - $(MAKE) -C "$(LINUX_DIR)" \ - $(MAKE_OPTS) \ - modules -endef - -$(eval $(call KernelPackage,wrt55agv2-spidevs)) diff --git a/package/kernel/wrt55agv2-spidevs/src/Kconfig b/package/kernel/wrt55agv2-spidevs/src/Kconfig deleted file mode 100644 index 75e8242be..000000000 --- a/package/kernel/wrt55agv2-spidevs/src/Kconfig +++ /dev/null @@ -1,3 +0,0 @@ -config WRT55AGV2_SPIDEVS - tristate "SPI device support for the WRT55AG v2 board" - depends on SPI && MIPS_ATHEROS diff --git a/package/kernel/wrt55agv2-spidevs/src/Makefile b/package/kernel/wrt55agv2-spidevs/src/Makefile deleted file mode 100644 index 76b093930..000000000 --- a/package/kernel/wrt55agv2-spidevs/src/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-m += wrt55agv2_spidevs.o diff --git a/package/kernel/wrt55agv2-spidevs/src/wrt55agv2_spidevs.c b/package/kernel/wrt55agv2-spidevs/src/wrt55agv2_spidevs.c deleted file mode 100644 index dfb7f6abe..000000000 --- a/package/kernel/wrt55agv2-spidevs/src/wrt55agv2_spidevs.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * SPI driver for the Linksys WRT55AG v2 board. - * - * Copyright (C) 2008 Gabor Juhos - * - * This file was based on the mmc_over_gpio driver: - * Copyright 2008 Michael Buesch - * - * 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. - */ - -#include -#include -#include - -#define DRV_NAME "wrt55agv2-spidevs" -#define DRV_DESC "SPI driver for the WRT55AG v2 board" -#define DRV_VERSION "0.1.0" -#define PFX DRV_NAME ": " - -#define GPIO_PIN_MISO 1 -#define GPIO_PIN_CS 2 -#define GPIO_PIN_CLK 3 -#define GPIO_PIN_MOSI 4 - -static struct platform_device *spi_gpio_dev; - -static int __init boardinfo_setup(struct spi_board_info *bi, - struct spi_master *master, void *data) -{ - - strlcpy(bi->modalias, "spi-ks8995", sizeof(bi->modalias)); - - bi->max_speed_hz = 5000000 /* Hz */; - bi->bus_num = master->bus_num; - bi->mode = SPI_MODE_0; - - return 0; -} - -static int __init wrt55agv2_spidevs_init(void) -{ - struct spi_gpio_platform_data pdata; - int err; - - spi_gpio_dev = platform_device_alloc("spi-gpio", 0); - if (!spi_gpio_dev) { - printk(KERN_ERR PFX "no memory for spi-gpio device\n"); - return -ENOMEM; - } - - memset(&pdata, 0, sizeof(pdata)); - pdata.pin_miso = GPIO_PIN_MISO; - pdata.pin_cs = GPIO_PIN_CS; - pdata.pin_clk = GPIO_PIN_CLK; - pdata.pin_mosi = GPIO_PIN_MOSI; - pdata.cs_activelow = 1; - pdata.no_spi_delay = 1; - pdata.boardinfo_setup = boardinfo_setup; - pdata.boardinfo_setup_data = NULL; - - err = platform_device_add_data(spi_gpio_dev, &pdata, sizeof(pdata)); - if (err) - goto err_free_dev; - - err = platform_device_register(spi_gpio_dev); - if (err) { - printk(KERN_ERR PFX "unable to register device\n"); - goto err_free_pdata; - } - - return 0; - -err_free_pdata: - kfree(spi_gpio_dev->dev.platform_data); - spi_gpio_dev->dev.platform_data = NULL; - -err_free_dev: - platform_device_put(spi_gpio_dev); - return err; -} - -static void __exit wrt55agv2_spidevs_cleanup(void) -{ - if (!spi_gpio_dev) - return; - - platform_device_unregister(spi_gpio_dev); - - kfree(spi_gpio_dev->dev.platform_data); - spi_gpio_dev->dev.platform_data = NULL; - platform_device_put(spi_gpio_dev); -} - -static int __init wrt55agv2_spidevs_modinit(void) -{ - printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n"); - return wrt55agv2_spidevs_init(); -} -module_init(wrt55agv2_spidevs_modinit); - -static void __exit wrt55agv2_spidevs_modexit(void) -{ - wrt55agv2_spidevs_cleanup(); -} -module_exit(wrt55agv2_spidevs_modexit); - -MODULE_DESCRIPTION(DRV_DESC); -MODULE_VERSION(DRV_VERSION); -MODULE_AUTHOR("Gabor Juhos "); -MODULE_LICENSE("GPL v2"); - diff --git a/package/lean/amule/Makefile b/package/lean/amule/Makefile index 1dd90675a..50ccca8a3 100644 --- a/package/lean/amule/Makefile +++ b/package/lean/amule/Makefile @@ -12,6 +12,7 @@ PKG_VERSION:=2.3.2 PKG_RELEASE:=2 PKG_REV=4b87b20 + PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-r$(PKG_REV).tar.bz2 PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_SOURCE_PROTO:=git @@ -36,7 +37,7 @@ define Package/amule CATEGORY:=Network TITLE:=A multi-platform eMule-like ed2k client URL:=http://www.amule.org/ - DEPENDS:=+libpng +libpthread +libncurses +libreadline +libwxbase +libupnp \ + DEPENDS:=+libpng +libpthread +libncurses +libreadline +libwxbase +libupnp +libbfd \ $(ICONV_DEPENDS) $(INTL_DEPENDS) +!AMULE_CRYPTOPP_STATIC_LINKING:libcryptopp endef diff --git a/package/lean/autocore/Makefile b/package/lean/autocore/Makefile index 31d455343..99754385d 100644 --- a/package/lean/autocore/Makefile +++ b/package/lean/autocore/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=autocore PKG_VERSION:=1 -PKG_RELEASE:=6 +PKG_RELEASE:=8 include $(INCLUDE_DIR)/package.mk diff --git a/package/lean/autocore/files/autocore b/package/lean/autocore/files/autocore index 0b75d5d16..9462f3f28 100755 --- a/package/lean/autocore/files/autocore +++ b/package/lean/autocore/files/autocore @@ -25,10 +25,13 @@ start() done a=$(cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq) - b=$(echo -n ' x ') - c=$(cat /proc/cpuinfo | grep 'processor' | wc -l) - f=${a}${b}${c} - echo $f > /tmp/sysinfo/model + b=$(echo -n ' : ') + c=$(cat /proc/cpuinfo | grep 'core id' | sort -u | wc -l) + d=$(echo -n ' Core ') + e=$(cat /proc/cpuinfo | grep 'processor' | wc -l) + f=$(echo -n ' Thread ') + g=${a}${b}${c}${d}${e}${f} + echo $g > /tmp/sysinfo/model } diff --git a/package/lean/brook/Makefile b/package/lean/brook/Makefile new file mode 100644 index 000000000..676f963ee --- /dev/null +++ b/package/lean/brook/Makefile @@ -0,0 +1,59 @@ +# +# Copyright (C) 2015-2016 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v3. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=brook +PKG_VERSION:=1.0 +PKG_RELEASE:=20180227 + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME) + SECTION:=net + CATEGORY:=Network + TITLE:=Brook is a cross-platform proxy software + DEPENDS:= + URL:=https://github.com/txthinking/brook +endef + +define Package/$(PKG_NAME)/description +Brook is a cross-platform proxy software +endef + +define Build/Prepare +endef + +define Build/Configure +endef + +define Build/Compile +endef + +define Package/$(PKG_NAME)/install + $(INSTALL_DIR) $(1)/usr/bin + +ifeq ($(ARCH),mipsel) + $(INSTALL_BIN) ./files/7620n/brook $(1)/usr/bin/ +endif +ifeq ($(ARCH),mips) + $(INSTALL_BIN) ./files/ar71xx/brook $(1)/usr/bin/ +endif +ifeq ($(ARCH),i386) + $(INSTALL_BIN) ./files/x86/brook $(1)/usr/bin/ +endif +ifeq ($(ARCH),x86_64) + $(INSTALL_BIN) ./files/x86_64/brook $(1)/usr/bin/ +endif +ifeq ($(ARCH),arm) + $(INSTALL_BIN) ./files/arm/brook $(1)/usr/bin/ +endif +ifeq ($(ARCH),aarch64) + $(INSTALL_BIN) ./files/armv7/brook $(1)/usr/bin/ +endif +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/lean/brook/files/7620n/brook b/package/lean/brook/files/7620n/brook new file mode 100644 index 000000000..23e2d3210 Binary files /dev/null and b/package/lean/brook/files/7620n/brook differ diff --git a/package/lean/brook/files/ar71xx/brook b/package/lean/brook/files/ar71xx/brook new file mode 100644 index 000000000..f97fe0b69 Binary files /dev/null and b/package/lean/brook/files/ar71xx/brook differ diff --git a/package/lean/brook/files/arm/brook b/package/lean/brook/files/arm/brook new file mode 100644 index 000000000..f2c9781f8 Binary files /dev/null and b/package/lean/brook/files/arm/brook differ diff --git a/package/lean/brook/files/armv7/brook b/package/lean/brook/files/armv7/brook new file mode 100644 index 000000000..dee43c5f7 Binary files /dev/null and b/package/lean/brook/files/armv7/brook differ diff --git a/package/lean/brook/files/x86/brook b/package/lean/brook/files/x86/brook new file mode 100644 index 000000000..8b6d9a024 Binary files /dev/null and b/package/lean/brook/files/x86/brook differ diff --git a/package/lean/brook/files/x86_64/brook b/package/lean/brook/files/x86_64/brook new file mode 100644 index 000000000..fabd02ad3 Binary files /dev/null and b/package/lean/brook/files/x86_64/brook differ diff --git a/package/lean/default-settings/Makefile b/package/lean/default-settings/Makefile index d8170a254..e501db0ac 100644 --- a/package/lean/default-settings/Makefile +++ b/package/lean/default-settings/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=default-settings PKG_VERSION:=1.0 -PKG_RELEASE:=33 +PKG_RELEASE:=38 PKG_LICENSE:=GPLv3 PKG_LICENSE_FILES:=LICENSE diff --git a/package/lean/default-settings/files/zzz-default-settings b/package/lean/default-settings/files/zzz-default-settings index 4b11abb7e..6a643249e 100755 --- a/package/lean/default-settings/files/zzz-default-settings +++ b/package/lean/default-settings/files/zzz-default-settings @@ -46,7 +46,7 @@ sed -i '/set wireless.radio${devidx}.disabled/d' /lib/wifi/mac80211.sh wifi up sed -i '/DISTRIB_REVISION/d' /etc/openwrt_release -echo "DISTRIB_REVISION='R7.5.4 By Lean'" >> /etc/openwrt_release +echo "DISTRIB_REVISION='R7.6.1 By Lean'" >> /etc/openwrt_release sed -i '/DISTRIB_DESCRIPTION/d' /etc/openwrt_release echo "DISTRIB_DESCRIPTION='OpenWrt '" >> /etc/openwrt_release diff --git a/package/lean/default-settings/i18n/default.zh-cn.po b/package/lean/default-settings/i18n/default.zh-cn.po index e12688fca..c5167e294 100644 --- a/package/lean/default-settings/i18n/default.zh-cn.po +++ b/package/lean/default-settings/i18n/default.zh-cn.po @@ -7,8 +7,14 @@ msgstr "架构" msgid "CPU Temperature" msgstr "CPU温度" +<<<<<<< HEAD msgid "CPU Model" msgstr "处ç†å™¨åž‹å·" +======= +msgid "CPU Info" +msgstr "CPUä¿¡æ¯" + +>>>>>>> upstream/master msgid "CPU Info" msgstr "CPUä¿¡æ¯" diff --git a/package/lean/dvb/dvb-firmware/Makefile b/package/lean/dvb/dvb-firmware/Makefile new file mode 100644 index 000000000..8c6d0f0b4 --- /dev/null +++ b/package/lean/dvb/dvb-firmware/Makefile @@ -0,0 +1,40 @@ +# +# Copyright (C) 2017 McMCC +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=dvb-firmware +PKG_VERSION:=1.0 +PKG_RELEASE:=2 + +include $(INCLUDE_DIR)/package.mk + +define Package/dvb-firmware + SECTION:=dvb-firmware + CATEGORY:=Firmware + TITLE:=dvb-firmware megapack +endef + +define Package/dvb-firmware/description + dvb-firmware is specialised software that is both specific to some hardware + and also integral for its proper functioning. +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR)/firmware + $(CP) ./src/* $(PKG_BUILD_DIR)/firmware +endef + +define Build/Configure +endef + +define Build/Compile +endef + +define Package/dvb-firmware/install + $(INSTALL_DIR) $(1)/lib/firmware + $(CP) $(PKG_BUILD_DIR)/firmware/* $(1)/lib/firmware +endef + +$(eval $(call BuildPackage,dvb-firmware)) diff --git a/package/lean/dvb/dvb-firmware/src/dvb-demod-mn88472-02.fw b/package/lean/dvb/dvb-firmware/src/dvb-demod-mn88472-02.fw new file mode 100644 index 000000000..1f0177813 Binary files /dev/null and b/package/lean/dvb/dvb-firmware/src/dvb-demod-mn88472-02.fw differ diff --git a/package/lean/dvb/dvb-firmware/src/dvb-demod-mn88473-01.fw b/package/lean/dvb/dvb-firmware/src/dvb-demod-mn88473-01.fw new file mode 100644 index 000000000..1b2eceabb Binary files /dev/null and b/package/lean/dvb/dvb-firmware/src/dvb-demod-mn88473-01.fw differ diff --git a/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-01.fw b/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-01.fw new file mode 100644 index 000000000..5882a2142 Binary files /dev/null and b/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-01.fw differ diff --git a/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-02.fw b/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-02.fw new file mode 100644 index 000000000..62d627625 Binary files /dev/null and b/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-02.fw differ diff --git a/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-a20-01.fw b/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-a20-01.fw new file mode 100644 index 000000000..13f09efe2 Binary files /dev/null and b/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-a20-01.fw differ diff --git a/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-a30-01.fw b/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-a30-01.fw new file mode 100644 index 000000000..96186e7af Binary files /dev/null and b/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-a30-01.fw differ diff --git a/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-b40-01.fw b/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-b40-01.fw new file mode 100644 index 000000000..9f892cea6 Binary files /dev/null and b/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-b40-01.fw differ diff --git a/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-d60-01.fw b/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-d60-01.fw new file mode 100644 index 000000000..2a47ab535 Binary files /dev/null and b/package/lean/dvb/dvb-firmware/src/dvb-demod-si2168-d60-01.fw differ diff --git a/package/lean/dvb/dvb-firmware/src/dvb-demod-si2183-b60-01.fw b/package/lean/dvb/dvb-firmware/src/dvb-demod-si2183-b60-01.fw new file mode 100644 index 000000000..2a47ab535 Binary files /dev/null and b/package/lean/dvb/dvb-firmware/src/dvb-demod-si2183-b60-01.fw differ diff --git a/package/lean/dvb/dvb-firmware/src/dvb-fe-ds3000.fw b/package/lean/dvb/dvb-firmware/src/dvb-fe-ds3000.fw new file mode 100644 index 000000000..e239559d9 Binary files /dev/null and b/package/lean/dvb/dvb-firmware/src/dvb-fe-ds3000.fw differ diff --git a/package/lean/dvb/dvb-firmware/src/dvb-tuner-si2141-a10-01.fw b/package/lean/dvb/dvb-firmware/src/dvb-tuner-si2141-a10-01.fw new file mode 100644 index 000000000..b7be881fb Binary files /dev/null and b/package/lean/dvb/dvb-firmware/src/dvb-tuner-si2141-a10-01.fw differ diff --git a/package/lean/dvb/dvb-firmware/src/dvb-tuner-si2158-a20-01.fw b/package/lean/dvb/dvb-firmware/src/dvb-tuner-si2158-a20-01.fw new file mode 100644 index 000000000..42efbe0de Binary files /dev/null and b/package/lean/dvb/dvb-firmware/src/dvb-tuner-si2158-a20-01.fw differ diff --git a/package/lean/dvb/dvb-firmware/src/dvb-usb-dw2101.fw b/package/lean/dvb/dvb-firmware/src/dvb-usb-dw2101.fw new file mode 100644 index 000000000..05a876f92 Binary files /dev/null and b/package/lean/dvb/dvb-firmware/src/dvb-usb-dw2101.fw differ diff --git a/package/lean/dvb/dvb-firmware/src/dvb-usb-dw2102.fw b/package/lean/dvb/dvb-firmware/src/dvb-usb-dw2102.fw new file mode 100644 index 000000000..bf6020567 Binary files /dev/null and b/package/lean/dvb/dvb-firmware/src/dvb-usb-dw2102.fw differ diff --git a/package/lean/dvb/dvb-firmware/src/dvb-usb-dw2104.fw b/package/lean/dvb/dvb-firmware/src/dvb-usb-dw2104.fw new file mode 100644 index 000000000..b1fc1c95d Binary files /dev/null and b/package/lean/dvb/dvb-firmware/src/dvb-usb-dw2104.fw differ diff --git a/package/lean/dvb/dvb-firmware/src/dvb-usb-dw3101.fw b/package/lean/dvb/dvb-firmware/src/dvb-usb-dw3101.fw new file mode 100644 index 000000000..92d6b0e84 Binary files /dev/null and b/package/lean/dvb/dvb-firmware/src/dvb-usb-dw3101.fw differ diff --git a/package/lean/dvb/dvb-firmware/src/dvb-usb-tbsqbox-id5521.fw b/package/lean/dvb/dvb-firmware/src/dvb-usb-tbsqbox-id5521.fw new file mode 100644 index 000000000..969a642b4 Binary files /dev/null and b/package/lean/dvb/dvb-firmware/src/dvb-usb-tbsqbox-id5521.fw differ diff --git a/package/lean/dvb/libdvbcsa/Makefile b/package/lean/dvb/libdvbcsa/Makefile new file mode 100644 index 000000000..1bdb22213 --- /dev/null +++ b/package/lean/dvb/libdvbcsa/Makefile @@ -0,0 +1,57 @@ +# +# Copyright (C) 2014 nanpuyue +# Copyright (C) 2017 Tomasz Maciej Nowak +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk + +PKG_NAME := libdvbcsa +PKG_RELEASE := 1 + +PKG_SOURCE_PROTO := git +PKG_SOURCE_URL := https://github.com/glenvt18/libdvbcsa.git +PKG_SOURCE_VERSION := 2a1e61e569a621c55c2426f235f42c2398b7f18f + +PKG_VERSION := 1.1.0-$(shell printf '%.8s' $(PKG_SOURCE_VERSION)) +#PKG_SOURCE := $(PKG_NAME)-$(PKG_VERSION).tar.gz +#PKG_SOURCE_URL := http://download.videolan.org/pub/videolan/libdvbcsa/$(PKG_VERSION)/ +#PKG_HASH := 4db78af5cdb2641dfb1136fe3531960a477c9e3e3b6ba19a2754d046af3f456d + +PKG_LICENSE := GPL-2.0 +PKG_LICENSE_FILE := COPYING + +PKG_MAINTAINER := Tomasz Maciej Nowak + +PKG_INSTALL := 1 + +include $(INCLUDE_DIR)/package.mk + +define Package/libdvbcsa + SECTION := libs + CATEGORY := Libraries + TITLE := DVB Common Scrambling Algorithm library + URL := https://www.videolan.org/developers/libdvbcsa.html +endef + +define Package/libdvbcsa/description + libdvbcsa is a free implementation of the DVB Common Scrambling + Algorithm - DVB/CSA - with encryption and decryption capabilities +endef + +define Build/Configure + (cd $(PKG_BUILD_DIR); ./bootstrap) + $(call Build/Configure/Default) +endef + +define Build/InstallDev + $(CP) $(PKG_INSTALL_DIR)/usr $(1)/ +endef + +define Package/libdvbcsa/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libdvbcsa.so* $(1)/usr/lib/ +endef + +$(eval $(call BuildPackage,libdvbcsa)) diff --git a/package/lean/dvb/oscam/Makefile b/package/lean/dvb/oscam/Makefile new file mode 100755 index 000000000..f35f90be4 --- /dev/null +++ b/package/lean/dvb/oscam/Makefile @@ -0,0 +1,89 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=oscam +PKG_REV:=11402 +PKG_VERSION:=1.20-$(PKG_REV) +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_VERSION:=175e3c61ebf8df3611f980f88ff8b153c4f456d7 +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_URL:=http://repo.or.cz/oscam.git +PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.bz2 +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +PKG_MAINTAINER:=OSCam developers +PKG_LICENSE:=GPL-3.0 +PKG_LICENSE_FILES:=COPYING + + +PKG_BUILD_PARALLEL:=1 +PKG_USE_MIPS16:=0 + +include $(INCLUDE_DIR)/package.mk + +define Package/oscam + SECTION:=net + CATEGORY:=Network + DEPENDS:=+libopenssl +libusb-1.0 +kmod-usb-serial +kmod-usb-serial-ch341 +kmod-usb-serial-ftdi +kmod-usb-serial-pl2303 +libpcsclite +pcscd +ccid + TITLE:=OSCam is an Open Source Conditional Access Module software + URL:=http://www.streamboard.tv/oscam/ +endef + +define Package/oscam/description + OSCam is an Open Source Conditional Access Module software, + based on the very good MpCS version 0.9d created by ​dukat. +endef + +define Package/oscam/conffiles +/etc/oscam/oscam.conf +/etc/oscam/oscam.server +/etc/oscam/oscam.user +/etc/oscam/SoftCam.Key +/etc/oscam/oscam.dvbapi +endef + +CONFIGURE_CMD = ./config.sh +CONFIGURE_ARGS = \ + --enable all + +MAKE_FLAGS += \ + CONF_DIR=/etc/oscam \ + OSCAM_BIN=Distribution/oscam \ + USE_SSL=1 \ + USE_LIBUSB=1 \ + USE_PCSC=1 \ + USE_LIBCRYPTO=1 + + +define Package/oscam/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/Distribution/oscam $(1)/usr/bin/oscam + + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/oscam.init $(1)/etc/init.d/oscam + + $(INSTALL_DIR) $(1)/etc/oscam + $(INSTALL_CONF) ./files/oscam.conf $(1)/etc/oscam + $(INSTALL_CONF) ./files/oscam.server $(1)/etc/oscam + $(INSTALL_CONF) ./files/oscam.user $(1)/etc/oscam + $(INSTALL_CONF) ./files/SoftCam.Key $(1)/etc/oscam + $(INSTALL_CONF) ./files/oscam.dvbapi $(1)/etc/oscam + + +endef + + +define Package/$(PKG_NAME)/prerm + #!/bin/sh + # if run within buildroot exit + [ -n "$${IPKG_INSTROOT}" ] && exit 0 + + # stop running scripts + /etc/init.d/oscam disable + /etc/init.d/oscam stop + + exit 0 +endef + +$(eval $(call BuildPackage,oscam)) diff --git a/package/lean/dvb/oscam/files/SoftCam.Key b/package/lean/dvb/oscam/files/SoftCam.Key new file mode 100644 index 000000000..8a660e921 --- /dev/null +++ b/package/lean/dvb/oscam/files/SoftCam.Key @@ -0,0 +1,1462 @@ +# :::::::::: sat-life.info 17.06.2016 ::::::::::::::: +# <><><><><> by Serjoga latvia <><><><><><> +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#::::::: NAGRA ::::::::: +#^^^^^^^^^^^^^^^^^^^^^^^ +::::::: UNity Media ::::::: +N 1102 00 F8780ECD862D143B9B23ECFFCBB872A4 ; UnityMedia Cable TV (german) +N 1102 01 FAD9E99827B3D66B624FA382E52615E1 ; UnityMedia Cable TV (german) +N 1102 M1 C75C2FECF494F6DD71BBF898C63F7FEBA11345DF14C71EE656 BC23016C2F90A881429B82A68C095E472C997752D5890341CF 9E06691672482718750B918AAE92 ; UnityMedia Cable TV (german) +#^^^^^^^^^^^^^^^^^^^^^^^^ +::::::: Cablecom Swiss Cable TV ::::::: +N 7301 00 950B684C48CAC1B9DBBCC03162FA4726 ;Cablecom Swiss Cable TV (Switzerland) +N 7301 01 FE0C200B4B1D3302CA107133D7771D79 ;Cablecom Swiss Cable TV (Switzerland) +N 7301 M1 7544E982065D53E7CF049AF2E725544A50268DA1462F15D8A197ECE4B80FE221122F92AD56324380A04878EBF563427DD85C38645907583E23AC5153E300CF84 ;Cablecom Swiss Cable TV (switzerland) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: IRDETO2 ::::::: +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +I 060400 02 2D265F5993B812E4A73BA29A2778BEC5 ### Bulsat 39.0E +I 060400 03 B3A283325BF7A18BA8B4084BFB5F9370 ### Bulsat 39.0E +I 060400 04 1E98FD1658E5414BC32E3D37775646DF ### Bulsat 39.0E +I 060400 06 78A6823BF854E0F8886FF60C0FAA6528 ### Bulsat 39.0E +I 060400 M1 98B4DCAD44E8C9504C3F4E51692A7047 ### Bulsat 39.0E +I 060400 M2 AE652B210BF89FC69507609842FD303E ### Bulsat 39.0E +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: Viacess ::::::: +V 023800 08 955CF3C92800F39F54B93005DF826DBF , SSR/SRG Swiss (13.0°E) +V 023800 D1 0B552C11AF0A2FB8 ; Des1_Key +V 023800 X1 3D1229C2ED29C130 ; XORArray +V 023800 P1 0304000207050106 ; PermArray +V 023800 C1 DA4E0B42134F433B ; ChainArray +V 023800 T1 495EE3839DD6544AF23FC1EC7C684D973CF873926F1CF0F586DA31A1156BA69A3461A28A965DCB2A5B932757B3D34640CF1A654C20A548C3E6B97DBD104363092FC89C3D67D82EAE3600075C330E8D946AE8AD5F06E7F42BB79FAC284B250153BE217A3EFD3291440D8F501DC5A8A7147BBBED12C4BF89DBDCD162700C3A95AFB4F6B103C6FB18DDC77623E4FC4EF169AA6613294F7E240FB59E1FAB42049959D91B22B6F9351E6E6DC2909B5A52477FC082FE2C8098A358D739DE71D23B6075B00AA937746C848841CAC926F7EAE230DF79BC2DEEF305B845A019777887BAD0FAE5CE028BE1385551EFCDFF0B72D4E9168E08D5561781CC11A4E0858C64B2EB1E84CC47F20C8155 ;TransformTable +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +V 007400 08 2FB60239D4D8C4D6 ;Mezzo 13°E +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +V 021110 08 35F6B9217C2BA83F38C3C1FD23A5D321 ;Ant-1 Europe 9°E +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +V 030B00 T1 7F308A9B0B803C4B6BBFEFB041F03B58E3BCAFBEE583B415A53571952BABE9A17964A8BA8BE4E053DB6AD5511C063739D81786DD92871BD7B718E7312DDC77F3DE1AD4FC60932909703D97B9688F2C5B6221F501D0894F995028A9FD4A3F9861F71F20AD030846CF546C44DF76C18D0078F607A0F17A2E32119FF4852F4913C2599E9623EB1924EDDA25FECAF894226533579DC3A39C0E56044882BD755AACFA26A6B3E80567ECB136E6FF4D107E8CB8AAE1EE8E5FC42A9A525DC702CD72B20F88D9437D16D65ECB406D144CF9745C127CC0C9A7A49069BB0DEAC8C563AE664ED26FB57B271D6E3ECEC645D3D142E238A2B63A340AFB73911E84CC47F20C8155 ; TransformTable +V 030B00 X1 8B2908AE39B0101A ;XORTABLE +V 030B00 P1 0704020305000601 ;PERMTABLE +V 030B00 C1 FC3C5F15D7A0B437 ;CW1XOR +V 030B00 08 D92A82E3111C9AFDED4626AD0B542E5B ;TNTSat +V 030B00 09 CC72AAFE5265D6D04608E832CEB9EC4D ;TNTSat +V 030B00 0A EE2679604A7DDD32E4F8CB913500D38E ;TNTSat +V 030B00 0B 7C6A2428C020023B163E4FE024FF5D9D ;TNTSat +V 030B00 E1 F627E52F1782BE037223B0D349E0361A ;AES KEY Decrypt +V 030B00 E2 EF3CB8D36A862097A33FC47101041BE3 ;TNTSat HD SurEncryption Key +V 030B00 E4 6B1B024D36F60974973CB81FA5E8F01C ;WB2 HD SurEncryption +V 030B00 E15 127003F8E95100367A556121C779FB6E ;TNT Sat HD +V 030B00 E17 1DE5B042AD670BB16A3A76BDAD2F7AC0 +V 030B00 EC 9A3EAB0203EBFFCA85B4F18280749F56 ;WB SurEncryption Key +V 030B00 ED 2504B382B16D8C6758DB960E311E9351 ;WB2 SurEncryption Key +V 030B00 EE 349883E54D58336DCA750A878ACC5CD5 ;WB2 SD SurEncryption +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::::: VideoGuard ::::::::: +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +S 090F 00 1585C5E4B852ECF7C3D908BA224A66F282154FB218486397DC19D8519A39FCCA1C24D065A9662DD6533B86BA40EA4C6DD91E4114FE15AFC318C5F8A7A8010001 ;Viasat (4.9°E) +S 093E 00 1585C5E4B852ECF7C3D908BA224A66F282154FB218486397DC19D8519A39FCCA1C24D065A9662DD6533B86BA40EA4C6DD91E4114FE15AFC318C5F8A7A8010001 ;Viasat (4.9°E) +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::::: PowerVu ::::::::: +P 0011 00 437DD3B2A0A6D5 ;VTV HD 40.5W +P 0011 01 466B3B814138E1 ;VTV HD 40.5W +P 0013 00 437DD3B2A0A6D5 ;Gol TV HD 40.5W +P 0013 01 466B3B814138E1 ;Gol TV HD 40.5W +P 0017 00 437DD3B2A0A6D5 ;Gol TV Alternate 40.5W +P 0017 01 466B3B814138E1 ;Gol TV Alternate 40.5W + +P 9CA0 00 216447C54874C3 ;Discovery Showcase Europe HD 0.9W +P 9CA0 01 70F4D06DB57699 ;Discovery Showcase Europe HD 0.9W +P A8C0 00 216447C54874C3 ;ID Xtra Europe Russian HD 0.9W +P A8C0 01 70F4D06DB57699 ;ID Xtra Europe Russian HD 0.9W +P A8D0 00 216447C54874C3 ;ID Xtra Europe HD 0.9W +P A8D0 01 70F4D06DB57699 ;ID Xtra Europe HD 0.9W +P 5140 00 216447C54874C3 ;Historia Poland 0.9W +P 5140 01 70F4D06DB57699 ;Historia Poland 0.9W +P 5780 00 216447C54874C3 ;Discovery Iberia 0.9W +P 5780 01 70F4D06DB57699 ;Discovery Iberia 0.9W +P BB80 00 216447C54874C3 ;DTX 0.9W +P BB80 01 70F4D06DB57699 ;DTX 0.9W +P 9C60 00 216447C54874C3 ;Discovery Russia HD 0.9W +P 9C60 01 70F4D06DB57699 ;Discovery Russia HD 0.9W +P AF00 00 216447C54874C3 ;Discovery Poland HD 0.9W +P AF00 01 70F4D06DB57699 ;Discovery Poland HD 0.9W +P C830 00 216447C54874C3 ;Science Europe Russia HD 0.9W +P C830 01 70F4D06DB57699 ;Science Europe Russia HD 0.9W +P C850 00 216447C54874C3 ;Science Europe HD 0.9W +P C850 01 70F4D06DB57699 ;Science Europe HD 0.9W +P A2A0 00 216447C54874C3 ;Animal Planet Russia HD 0.9W +P A2A0 01 70F4D06DB57699 ;Animal Planet Russia HD 0.9W +P A290 00 216447C54874C3 ;Animal Planet Poland HD 0.9W +P A290 01 70F4D06DB57699 ;Animal Planet Poland HD 0.9W +P A2E0 00 216447C54874C3 ;Animal Planet HD 0.9W +P A2E0 01 70F4D06DB57699 ;Animal Planet HD 0.9W +P 0650 00 7F468E8B047CDE ;NBC Universal 0.9W +P 0650 01 679352FC3DEDF4 ;NBC Universal 0.9W + +P 0140 00 A25AE797314F61 ;HBO Hungary 4.0W +P 0140 01 4245667429DFEE ;HBO Hungary 4.0W +P 0020 00 A25AE797314F61 ;HBO Hungary 4.0W +P 0020 01 4245667429DFEE ;HBO Hungary 4.0W +P 0310 00 A25AE797314F61 ;HBO Comedy 4.0W +P 0310 01 4245667429DFEE ;HBO Comedy 4.0W +P 0330 00 A25AE797314F61 ;HBO Comedy Hungary/Czech 4.0W +P 0330 01 4245667429DFEE ;HBO Comedy Hungary/Czech 4.0W +P 0E90 00 A25AE797314F61 ;HBO Poland 4.0W +P 0E90 01 4245667429DFEE ;HBO Paland 4.0W +P 02A0 00 A25AE797314F61 ;HBO COMEDY HUNGARY, 4W +P 02A0 01 4245667429DFEE ;HBO COMEDY HUNGARY, 4W +P 0340 00 A25AE797314F61 ;HBO HUNGARY (AC3), 4W +P 0340 01 4245667429DFEE ;HBO HUNGARY (AC3), 4W +P 0CC0 00 A25AE797314F61 ;HBO 2 4.0W +P 0CC0 01 4245667429DFEE ;HBO 2 4.0W +P 00C9 00 A25AE797314F61 ;HBO2 HUNGARY, 4W +P 0C90 01 4245667429DFEE ;HBO2 HUNGARY, 4W +P 0CB0 00 A25AE797314F61 ;HBO2 OrigHu, 4W +P 0CB0 01 4245667429DFEE ;HBO2 OrigHu, 4W +P 0CA0 00 A25AE797314F61 ;HBO2 CZECH, 4W +P 0CA0 01 4245667429DFEE ;HBO2 CZECH, 4W +P 0E60 00 A25AE797314F61 ;Cinemax International 4.0W +P 0E60 01 4245667429DFEE ;Cinemax International 4.0W +P 0EC0 00 A25AE797314F61 ;Cinemax International 2 4.0W +P 0EC0 01 4245667429DFEE ;Cinemax International 2 4.0W +P 0F60 00 A25AE797314F61 ;Cinemax 2 International 4.0W +P 0F60 01 4245667429DFEE ;Cinemax 2 International 4.0W +P 0E70 00 A25AE797314F61 ;CINEMAX HUNGARY, 4W +P 0E70 01 4245667429DFEE ;CINEMAX HUNGARY, 4W +P 0F10 00 A25AE797314F61 ;CINEMAX 2 HUNGARY, 4W +P 0F10 01 4245667429DFEE ;CINEMAX 2 HUNGARY, 4W +P 0FB0 00 A25AE797314F61 ;CINEMAX 2 HUNGARY/Czech, 4W +P 0FB0 01 4245667429DFEE ;CINEMAX 2 HUNGARY/Czech, 4W +P 0F30 00 A25AE797314F61 ;CINEMAX 2 POLAND, 4W +P 0F30 01 4245667429DFEE ;CINEMAX 2 POLAND, 4W + +P 1FE0 00 B07EC58F412BD7 ;The Fight Network 15.0W +P 1FE0 01 A52E79D341F87F ;The Fight Network 15.0W + +P 00B0 00 6DADC79AAD00CF ;AFN Sports HD 9.0E +P 00B0 01 9E83D4513F3B23 ;AFN Sports HD 9.0E +P 0010 00 6DADC79AAD00CF ;AFN Sports 9.0E +P 0010 01 9E83D4513F3B23 ;AFN Sports 9.0E +P 0060 00 6DADC79AAD00CF ;AFN Sports 2 9.0E +P 0060 01 9E83D4513F3B23 ;AFN Sports 2 9.0E +P 0020 00 6DADC79AAD00CF ;AFN Prime Atlantic 9.0E +P 0020 01 9E83D4513F3B23 ;AFN Prime Atlantic 9.0E +P 0070 00 6DADC79AAD00CF ;Guide 9.0E +P 0070 01 9E83D4513F3B23 ;Guide 9.0E +P 0030 00 6DADC79AAD00CF ;Spectrum 9.0E +P 0030 01 9E83D4513F3B23 ;Spectrum 9.0E +P 0050 00 6DADC79AAD00CF ;News 9.0E +P 0050 01 9E83D4513F3B23 ;News 9.0E +P 0040 00 6DADC79AAD00CF ;Pacific 9.0E +P 0040 01 9E83D4513F3B23 ;Pacific 9.0E +P 0090 00 6DADC79AAD00CF ;Fam/Pulse 9.0E +P 0090 01 9E83D4513F3B23 ;Fam/Pulse 9.0E +P 00A0 00 6DADC79AAD00CF ;Movie 9.0E +P 00A0 01 9E83D4513F3B23 ;Movie 9.0E +P 06B0 00 6DADC79AAD00CF ;Decoder Expired 9.0E +P 06B0 01 9E83D4513F3B23 ;Decoder Expired 9.0E +P 0630 00 6DADC79AAD00CF ;Download 9.0E +P 0630 01 9E83D4513F3B23 ;Download 9.0E + +P 02C0 00 0123456789ABCD ;Snai Virtuali 1 16E +P 02C0 01 97D6968EEC34A3 ;Snai Virtuali 1 16E +P 0370 00 0123456789ABCD ;CH 55 Virtuali 3 16E +P 0370 01 97D6968EEC34A3 ;CH 55 Virtuali 3 16E + +#______________________12303 H 25548__________________________________ +P 2620 00 3AAB2C9D1A23BB ;DIVA Romania 4.9E +P 2620 01 01104AD73016C3 ;DIVA Romania 4.9E +P 1650 00 3AAB2C9D1A23BB ;CN TCM Russia 4.9E +P 1650 01 01104AD73016C3 ;CN TCM Russia 4.9E +P 1640 00 3AAB2C9D1A23BB ;CN/TCM RSEE 4.9E +P 1640 01 01104AD73016C3 ;CN/TCM RSEE 4.9E +P 26C0 00 3AAB2C9D1A23BB ;Universal Croatia-Slovenia 4.9E +P 26C0 01 01104AD73016C3 ;Universal Croatia-Slovenia 4.9E + +#______________________12322 V 27500__________________________________ +P 44C0 00 CBC3ECF15309C6 ;Discovery Turkey HD 4.9E +P 44C0 01 C19C56769B52AA ;Discovery Turkey HD 4.9E +P 1F40 00 CBC3ECF15309C6 ;Discovery Science Polska 4.9E +P 1F40 01 C19C56769B52AA ;Discovery Science Polska 4.9E +P 0640 00 CBC3ECF15309C6 ;Animal Planet Europe 4.9E +P 0640 01 C19C56769B52AA ;Animal Planet Europe 4.9E +P 0C80 00 CBC3ECF15309C6 ;Discovery central Europe 4.9E +P 0C80 01 C19C56769B52AA ;Discovery central Europe 4.9E +P 12D0 00 CBC3ECF15309C6 ;ID Europe 4.9E +P 12D0 01 C19C56769B52AA ;ID Europe 4.9E +P 1900 00 CBC3ECF15309C6 ;ID Extra Europe 4.9E +P 1900 01 C19C56769B52AA ;ID Extra Europe 4.9E +P 3850 00 CBC3ECF15309C6 ;Science Europe 4.9E +P 3850 01 C19C56769B52AA ;Science Europe 4.9E +P 1F40 00 CBC3ECF15309C6 ;Discovery World 4.9E +P 1F40 01 C19C56769B52AA ;Discovery World 4.9E +P 3E80 00 CBC3ECF15309C6 ;Discovery World 4.9E +P 3E80 01 C19C56769B52AA ;Discovery World 4.9E + +#______________________12360 V 27500_______________________________ +P 125C 00 216447C54874C3 ;Eurosport 2 Wimbledon HD 4.9E +P 125C 01 70F4D06DB57699 ;Eurosport 2 Wimbledon HD 4.9E +P 7080 00 216447C54874C3 ;Science Poland HD 4.9E +P 7080 01 70F4D06DB57699 ;Science Poland HD 4.9E +P 6A40 00 216447C54874C3 ;Animal Planet Poland HD 4.9E +P 6A40 01 70F4D06DB57699 ;Animal Planet Poland HD 4.9E +P C1C0 00 216447C54874C3 ;TLC Poland HD 4.9E & 0.9W +P C1C0 01 70F4D06DB57699 ;TLC Poland HD 4.9E & 0.9W +P 2BC0 00 216447C54874C3 ;Discovery Bulgaria 4.9E +P 2BC0 01 70F4D06DB57699 ;Discovery Bulgaria 4.9E +P B540 00 216447C54874C3 ;TLC Pan Regional 4.9E +P B540 01 70F4D06DB57699 ;TLC Pan Regional 4.9E +P 2580 00 216447C54874C3 ;Turbo Xtra Poland 4.9E +P 2580 01 70F4D06DB57699 ;Turbo Xtra Poland 4.9E +P 8340 00 216447C54874C3 ;ID Poland 4.9E +P 8340 01 70F4D06DB57699 ;ID Poland 4.9E +P 6400 00 216447C54874C3 ;ID Sweden 4.9E +P 6400 01 70F4D06DB57699 ;ID Sweden 4.9E +P 3200 00 216447C54874C3 ;TLC Balcans 4.9E +P 3200 01 70F4D06DB57699 ;TLC Balcans 4.9E +P 12C0 00 216447C54874C3 ;Discovery Channel Romania 4.9E +P 12C0 01 70F4D06DB57699 ;Discovery Channel Romania 4.9E +P 3840 00 216447C54874C3 ;Discovery Ukraine 4.9E +P 3840 01 70F4D06DB57699 ;Discovery Ukraine 4.9E +P 5DC0 00 216447C54874C3 ;Discovery Life Poland 4.9E +P 5DC0 01 70F4D06DB57699 ;Discovery Life Poland 4.9E +#______________________________________________________ +P 0930 00 C56B7706315E3F ;New Boyles Sport 4.9E +P 0930 01 DD51BECAA44C1F ;New Boyles Sport 4.9E +P 0350 00 C56B7706315E3F ;William Hill 4.9E +P 0350 01 DD51BECAA44C1F ;William Hill 4.9E +P 0560 00 C56B7706315E3F ;SIS 2 4.9E +P 0560 01 DD51BECAA44C1F ;SIS 2 4.9E +P 0170 00 C56B7706315E3F ;Coral TV2 4.9E +P 0170 01 DD51BECAA44C1F ;Coral TV2 4.9E +P 0420 00 C56B7706315E3F ;Ladbrokes 1 4.9E +P 0420 01 DD51BECAA44C1F ;Ladbrokes 1 4.9E + +P 0650 00 2E40E327BB7837 ;MTN Worldwide TV (34.5°W & 47.5°W & 57.0° & 20°W) +P 0650 01 FFFA91E97B2570 ;MTN Worldwide TV (34.5°W & 47.5°W & 57.0° & 20°W) + +P 0020 00 5A5E959C3743B7 ;SET Asia 66E +P 0020 01 C367E0F812D1DE ;SET Asia 66E +P 0050 00 5A5E959C3743B7 ;SET Middle East 66E +P 0050 01 C367E0F812D1DE ;SET Middle East 66E +P 0060 00 5A5E959C3743B7 ;Sony Max Asia 66E +P 0060 01 C367E0F812D1DE ;Sony Max Asia 66E +P 0070 00 5A5E959C3743B7 ;Sony Max UK 66E +P 0070 01 C367E0F812D1DE ;Sony Max UK 66E +P 0090 00 5A5E959C3743B7 ;Sony SAB TV Asia 66E +P 0090 01 C367E0F812D1DE ;Sony SAB TV Asia 66E +P 00A0 00 5A5E959C3743B7 ;Max Middle East 66E +P 00A0 01 C367E0F812D1DE ;Max Middle East 66E +P 00D0 00 5A5E959C3743B7 ;Sony Six 66E +P 00D0 01 C367E0F812D1DE ;Sony Six 66E +P 0320 00 5A5E959C3743B7 ;Sony Six HD 66E +P 0320 01 C367E0F812D1DE ;Sony Six HD 66E +P 0330 00 5A5E959C3743B7 ;SET Asia HD 66E +P 0330 01 C367E0F812D1DE ;SET Asia HD 66E +P 0340 00 5A5E959C3743B7 ;PIX HD 66E +P 0340 01 C367E0F812D1DE ;PIX HD 66E +P 0350 00 5A5E959C3743B7 ;AXN SA HD 66E +P 0350 01 C367E0F812D1DE ;AXN SA HD 66E +P 0360 00 5A5E959C3743B7 ;MAX SA HD 66E +P 0360 01 C367E0F812D1DE ;MAX SA HD 66E +P 0370 00 5A5E959C3743B7 ;Sony ESPN HD 66E +P 0370 01 C367E0F812D1DE ;Sony ESPN HD 66E +P 0420 00 5A5E959C3743B7 ;MAX INTERNATIONL 66E +P 0420 01 C367E0F812D1DE ;MAX INTERNATIONL 66E +P 0CA0 00 5A5E959C3743B7 ;SET INTERNATIONL 66E +P 0CA0 01 C367E0F812D1DE ;SET INTERNATIONL 66E +P 0FF0 00 5A5E959C3743B7 ;SOFTWAR 66E +P 0FF0 01 C367E0F812D1DE ;SOFTWAR 66E + +P 0150 00 113754C6C0CEE1 ;AS7 SD 1 (105.5°E) +P 0150 01 00000000000000 ;AS7 SD 1 (105.5°E) +P 0160 00 113754C6C0CEE1 ;AS7 SD 2 (105.5°E) +P 0160 01 00000000000000 ;AS7 SD 2 (105.5°E) +P 0170 00 113754C6C0CEE1 ;AS7 SD 3 (105.5°E) +P 0170 01 00000000000000 ;AS7 SD 3 (105.5°E) +P 0180 00 113754C6C0CEE1 ;AS7 SD 4 (105.5°E) +P 0180 01 00000000000000 ;AS7 SD 4 (105.5°E) +P 0470 00 113754C6C0CEE1 ;AS7 HD 1 (105.5°E) +P 0470 01 00000000000000 ;AS7 HD 1 (105.5°E) +P 0480 00 113754C6C0CEE1 ;AS7 HD 2 (105.5°E) +P 0480 01 00000000000000 ;AS7 HD 2 (105.5°E) +P 0490 00 113754C6C0CEE1 ;AS7 HD 3 (105.5°E) +P 0490 01 00000000000000 ;AS7 HD 3 (105.5°E) +P 04A0 00 113754C6C0CEE1 ;AS7 HD 4 (105.5°E) +P 04A0 01 00000000000000 ;AS7 HD 4 (105.5°E) +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::::: BISS ::::::::: +# ^^^^^^^^^^^^^^^^^^^^^^^^ +F 0009002D 00 764924E3510382D6 ;TEST (4.0°W) +F 0009002D 01 764924E3510382D6 ;TEST (4.0°W) +F 00050101 00 764924E3510382D6 ;FilmUaDrama (4.0°W) +F 00050101 01 764924E3510382D6 ;FilmUaDrama (4.0°W) +F 00060101 00 764924E3510382D6 ;FilmUAction (4.0°W +F 00060101 01 764924E3510382D6 ;FilmUAction (4.0°W) +F 00050501 00 123ABC08123ABC08 ;EuroNews (4.0°W) +F 00050501 01 123ABC08123ABC08 ;EuroNews (4.0°W) +F 00090901 00 AABBCC31CCBBAA31 ;NTV Mir (Amos 4°W) +F 00090901 01 AABBCC31CCBBAA31 ;NTV Mir (Amos 4°W) +F 00040401 00 107220A215050721 ;TV Kiev (Amos 4W) +F 00040401 01 107220A215050721 ;TV Kiev (Amos 4W) +F 00080801 00 AC1234F24321CA2E ;Inter (Amos 4°W) +F 00080801 01 AC1234F24321CA2E ;Inter (Amos 4°W) +F 00090901 00 1234AC001234AC00 ;INTER+ (4.0°W) +F 00090901 01 1234AC001234AC00 ;INTER+ (4.0°W) +F 00010101 00 AC1234004321CA00 ;Inter (4.0°W) +F 00010101 01 AC1234004321CA00 ;Inter (4.0°W) +F 00030301 00 654321C91234569C ;1+1Plus (4.0°W) +F 00030301 01 654321C91234569C ;1+1Plus (4.0°W) +F 00040401 00 1231236612312366 ;Mega (4.0°W) +F 00040401 01 1231236612312366 ;Mega (4.0°W) +F 00050501 00 130419308313049A ;Test (4.0°W ) +F 00050501 01 130419308313049A ;Test (4.0°W ) +F 000C1201 00 198313AF041983A0 ;Test 2 (4.0°W) +F 000C1201 01 198313AF041983A0 ;Test 2 (4.0°W) +F 000D0131 00 1006102611071129 ;Pershiy (4.0°W) +F 000D0131 01 1006102611071129 ;Pershiy (4.0°W) +F 000C0C01 00 1A2B3C81C3B2A116 ;Trofey (4.0°W) +F 000C0C01 01 1A2B3C81C3B2A116 ;Trofey (4.0°W) +F 00010501 00 1234569C654321C9 ;Unian TV (4°W) +F 00010501 01 1234569C654321C9 ;Unian TV (4°W) +F 000808C0 00 2222226622222266 ;TV 1 Bosnia (4W) +F 000808C0 01 2222226622222266 ;TV 1 Bosnia (4W) + +F 0028008D 00 A1B2C316D4E5F8B1 ;ERT Digital - ERT HD (3.0°E) +F 0028008D 01 A1B2C316D4E5F8B1 ;ERT Digital - ERT HD (3.0°E) +F 0014008B 00 A1B2C316D4E5F8B1 ;ERT Digital - ET2 (3.0°E) +F 0014008B 01 A1B2C316D4E5F8B1 ;ERT Digital - ET2 (3.0°E) +F 0023008E 00 A1B2C316D4E5F8B1 ;ERT Digital - ET3 (3.0°E) +F 0023008E 01 A1B2C316D4E5F8B1 ;ERT Digital - ET3 (3.0°E) +F 000A008A 00 A1B2C316D4E5F8B1 ;ERT Digital - ET1 (3.0°E) +F 000A008A 01 A1B2C316D4E5F8B1 ;ERT Digital - ET1 (3.0°E) +F 0064047E 00 1111113311111133 ;ALPHA TV Greece (3.0°E) +F 0064047E 01 1111113311111133 ;ALPHA TV Greece (3.0°E) +F 015E0550 00 1111113311111133 ;ART (3.0°E) +F 015E0550 01 1111113311111133 ;ART (3.0°E) +F 0320073A 00 1111113311111133 ;ETV (3.0°E) +F 0320073A 01 1111113311111133 ;ETV (3.0°E) +F 02580672 00 1111113311111133 ;Skai (3.0°E) +F 02580672 01 1111113311111133 ;Skai (3.0°E) +F 02BC06D7 00 1111113311111133 ;Star Channel (3.0°E) +F 02BC06D7 01 1111113311111133 ;Star Channel (3.0°E) +F 01F4060E 00 1111113311111133 ;Mega Channel (3.0°E) +F 01F4060E 01 1111113311111133 ;Mega Channel (3.0°E) +F 019005AA 00 1111113311111133 ;Macedonia TV (3.0°E) +F 019005AA 01 1111113311111133 ;Macedonia TV (3.0°E) +F 012C0546 00 1111113311111133 ;ANT 1 (3.0°E) +F 012C0546 01 1111113311111133 ;ANT 1 (3.0°E) + +F 1A131A14 00 1122336633221166 ;XSport (4.9°E) +F 1A131A14 01 1122336633221166 ;XSport (4.9°E) +F 17ED17EE 00 1A2B3CAC4D5E6F0B ;1+1 Internetional (4.9°E) +F 17ED17EE 01 1A2B3CAC4D5E6F0B ;1+1 Internetional (4.9°E) +F 182E182F 00 À5EB22B2576F5016 ;Ukraina-SD (4.9°E) +F 182E182F 01 À5EB22B2576F5016 ;Ukraina-SD (4.9°E) +F 19D219D3 00 A5EB22B2576F5016 ;TRK Ukraina (4.9°E) +F 19D219D3 01 A5EB22B2576F5016 ;TRK Ukraina (4.9°E) +F 1A0E1A0F 00 A5EB2200576F7500 ;34 Telekanal (4.9°E) +F 1A0E1A0F 01 A5EB2200576F7500 ;34 Telekanal (4.9°E) +F 1A181A19 00 A5EB22B2576F25EB ;NLO TV (4.9°E) +F 1A181A19 01 A5EB22B2576F25EB ;NLO TV (4.9°E) +F 1A221A23 00 A5EB22B2576F25EB ;Indigo (4.9°E) +F 1A221A23 01 A5EB22B2576F25EB ;Indigo (4.9°E) +F 1B4E1B4F 00 1234AC001234AC00 ;Inter+ (4.9°E) +F 1B4E1B4F 01 1234AC001234AC00 ;Inter+ (4.9°E) +F 17DE17DF 00 19090628117660E7 ;TET (4.9°E) +F 17DE17DF 01 19090628117660E7 ;TET (4.9°E) + +F 00010100 00 AABB127734CCDDDD ;Fox Sport Europe (7°E) +F 00010100 01 AABB127734CCDDDD ;Fox Sport Europe (7°E) +F 00320802 00 C7B2A51ED4E3F1A8 ;Mena Media Feed (7°E) +F 00320802 01 C7B2A51ED4E3F1A8 ;Mena Media Feed (7°E) +F 00030202 00 1FD100F000000000 ;EVN-TV ( EVN EVNTV EVN TV / EUROVISION TV / EURO VISION NEWS ) (7°E) +F 00030202 01 1FD100F000000000 ;EVN-TV ( EVN EVNTV EVN TV / EUROVISION TV / EURO VISION NEWS ) (7°E) + +F 03E60BB6 00 1A2B3C814D5E6F1A ;TEST 4 (9.0°E) +F 03E60BB6 01 1A2B3C814D5E6F1A ;TEST 4 (9.0°E) +F 03E70BB7 00 1A2B3C814D5E6F1A ;TEST 8 (9.0°E) +F 03E70BB7 01 1A2B3C814D5E6F1A ;TEST 8 (9.0°E) +F 027211F9 00 E876F04E8BA51141 ;EFB1 (9.0°E) +F 027211F9 01 E876F04E8BA51141 ;EFB1 (9.0°E) +F 042101C9 00 1111113322222266 ;ODIE (9.0°E) +F 042101C9 01 1111113322222266 ;ODIE (9.0°E) +F 002E07FE 00 E876F04E8BA51141 ;Eurofootball Gonki (9.0°E) +F 002E07FE 01 E876F04E8BA51141 ;Eurofootball Gonki (9.0°E) +F 002D07FD 00 C0379C93E08FBB2A ;Monitor Games (9.0°E) +F 002D07FD 01 C0379C93E08FBB2A ;Monitor Games (9.0°E) +F 00370807 00 E876F04E8BA51141 ;Opap TV (9.0°E) +F 00370807 01 E876F04E8BA51141 ;Opap TV (9.0°E) +F 00130731 00 2000ABCBCD2000ED ;Sat2000 (9.0E) +F 00130731 01 2000ABCBCD2000ED ;Sat2000 (9.0E) + +F 00020B0F 00 6C37BA5D492D7EF4 ;BARAEM (10°E) +F 00020B0F 01 6C37BA5D492D7EF4 ;BARAEM (10°E) +F 00010B07 00 6C37BA5D492D7EF4 ;JEEM SD (10°E) +F 00010B07 01 6C37BA5D492D7EF4 ;JEEM SD (10°E) +F 00030B19 00 6C37BA5D492D7EF4 ;JEEM HD (10°E) +F 00030B19 01 6C37BA5D492D7EF4 ;JEEM HD (10°E) +F 00080202 00 F8C5A966EBA461F0 ;NBA TV (10.0E) +F 00080202 01 F8C5A966EBA461F0 ;NBA TV (10.0E) +F 00010191 00 F87384EF72A4CDE3 ;NBA TV HD (10.0E) +F 00010191 01 F87384EF72A4CDE3 ;NBA TV HD (10.0E) +F 000E0579 00 2557AC28CE25574B ;Barca Tv (10.0E) +F 000E0579 01 2557AC28CE25574B ;Barca Tv (10.0E) +F 00070201 00 2EEA2E46FE9E59F5 ;NBA-ADHOC (10.0E) +F 00070201 01 2EEA2E46FE9E59F5 ;NBA-ADHOC (10.0E) +F 00020201 00 AE7B80A9F968AF10 ;NBA POOL EUROPE 1 (10.0°E) +F 00020201 01 AE7B80A9F968AF10 ;NBA POOL EUROPE 1 (10.0°E) +F 00040259 00 E6CC37E9DB183A2D ;IMG A Europe (10.0°E) +F 00040259 01 E6CC37E9DB183A2D ;IMG A Europe (10.0°E) +F 000301F5 00 AA8B5F9427006F96 ;USRSC Europe ESPN (10°E) +F 000301F5 01 AA8B5F9427006F96 ;USRSC Europe ESPN (10°E) +F 00050191 00 23B8EEC92B6534C4 ;Chelsea TV (10.0E) +F 00050191 01 23B8EEC92B6534C4 ;Chelsea TV (10.0E) +F 00060259 00 11C4461BCE347A7C ;Premier League HD (10.0E) +F 00060259 01 11C4461BCE347A7C ;Premier League HD (10.0E) +F 000107D1 00 205976EF823DB574 ;MUTV (9.0E-10.0E ) +F 000107D1 01 205976EF823DB574 ;MUTV (9.0E-10.0E ) +F 007B03E9 00 3D10CB184EEC7DB7 ;Service-123HD (10.0°E) +F 007B03E9 01 3D10CB184EEC7DB7 ;Service-123HD (10.0°E) +F 01C80FA1 00 D05FC9F85131B537 ;Service-456HD (10.0°E) +F 01C80FA1 01 D05FC9F85131B537 ;Service-456HD (10.0°E) +F 000307F8 00 0000232301151026 ;Sahar 1 (10.0E) +F 000307F8 01 0000232301151026 ;Sahar 1 (10.0E) +F 00040816 00 0000232301151026 ;Sahar 2 (10.0E) +F 00040816 01 0000232301151026 ;Sahar 2 (10.0E) +F 00031004 00 159ACD7CEBF614F5 ;MGM ME (10.0E) +F 00031004 01 159ACD7CEBF614F5 ;MGM ME (10.0E) +F 0001012C 00 1234569C789FFF16 ;Sharqiya News (10.0E) +F 0001012C 01 1234569C789FFF16 ;Sharqiya News (10.0E) +F 0002076E 00 0000232301151026 ;Alalam News Channel (10.0E) +F 0002076E 01 0000232301151026 ;Alalam News Channel (10.0E) +F 0005080C 00 0000232301151026 ;Al Kawthar (10.0°E) +F 0005080C 01 0000232301151026 ;Al Kawthar (10.0°E) +F 00011023 00 0000232301151026 ;iFilm (10.0°E) +F 00011023 01 0000232301151026 ;iFilm (10.0°E) +F 002A0021 00 2301234701230125 ;DEFUALT (10.0E) +F 002A0021 01 2301234701230125 ;DEFUALT (10.0E) +F 00010032 00 0204757B6840751D ;ORTC (10.0°E) +F 00010032 01 0204757B6840751D ;ORTC (10.0°E) + +F 2A2F006E 00 1A2B3C814D5E6F1A ;TEST 6 (13.0°E) +F 2A2F006E 01 1A2B3C814D5E6F1A ;TEST 6 (13.0°E) +F 00030028 00 CA50B7D131D6585F ;Al Aoula Maroc (13.0°E) +F 00030028 01 CA50B7D131D6585F ;Al Aoula Maroc (13.0°E) +F 34D2052A 00 1A2B3C814D5E6F1A ;1+1 International (13.0E) +F 34D2052A 01 1A2B3C814D5E6F1A ;1+1 International (13.0E) + +F 00010134 00 124578CF875421FC ;SIC International (16°E) +F 00010134 01 124578CF875421FC ;SIC International (16°E) +F 00100121 00 2016013727BAFFE0 ;Kombat Sport (16°E) +F 00100121 01 2016013727BAFFE0 ;Kombat Sport (16°E) +F 00010310 00 BC33584706679502 ;EUTELSAT 16A S3-01 (16°E) +F 00010310 01 BC33584706679502 ;EUTELSAT 16A S3-01 (16°E) +F 03FA070A 00 9E186D23B5A74CA8 ;HNL (16°E) +F 03FA070A 01 9E186D23B5A74CA8 ;HNL (16°E) +F 00160201 00 CDEF12CE5678905E ;National 24 Plus (16.0°E) +F 00160201 01 CDEF12CE5678905E ;National 24 Plus (16.0°E) +F 000A0101 00 458825F27453682F ;National TV (16.0°E) +F 000A0101 01 458825F27453682F ;National TV (16.0°E) +F 00010064 00 C48DAF008FDA9700 ;Kanal D1 (16.0°E) +F 00010064 01 C48DAF008FDA9700 ;Kanal D1 (16.0°E) +F 00C80200 00 71F0F0519D8C234C ;SRTV Feed (16.0°E) +F 00C80200 01 71F0F0519D8C234C ;SRTV Feed (16.0°E) +F 000E00FD 00 1111113311111133 ;Test HD (16.0°E) +F 000E00FD 01 1111113311111133 ;Test HD (16.0°E) +F 00010200 00 1B5C69E0AA08E99B ;SNAI LIVE & SNAI LIVE2 (16°E) +F 00010200 01 1B5C69E0AA08E99B ;SNAI LIVE & SNAI LIVE2 (16°E) +F 00020201 00 1B5C69E0AA08E99B ;SNAI LIVE & SNAI LIVE2 (16°E) +F 00020201 01 1B5C69E0AA08E99B ;SNAI LIVE & SNAI LIVE2 (16°E) + +F 000D0191 00 12312366456456FF ;STN Test Transcode - [ TRACE Africa ] (19.2°E) +F 000D0191 01 12312366456456FF ;STN Test Transcode - [ TRACE Africa ] (19.2°E) +F 00130192 00 12312366456456FF ;STN Test Remux - [ MA CHAINE SPORT Extreme ] (19.2°E) +F 00130192 01 12312366456456FF ;STN Test Remux - [ MA CHAINE SPORT Extreme ] (19.2°E) + +F 007F04F6 00 1A1B1C511D1E1F5A ;Sahar University Network 1 (20.0°E) +F 007F04F6 01 1A1B1C511D1E1F5A ;Sahar University Network 1 (20.0°E) +F 00750492 00 1111113311111133 ;IRIB Varzesh (20.0°E) +F 00750492 01 1111113311111133 ;IRIB Varzesh (20.0°E) + +F 00070301 00 A9E746D68358E5C0 ;Topaz 1 (21.5°E) +F 00070301 01 A9E746D68358E5C0 ;Topaz 1 (21.5°E) + +F 000103E9 00 ACDE109A0616BCD8 ;MBC MASR FEED (21.6°E) +F 000103E9 01 ACDE109A0616BCD8 ;MBC MASR FEED (21.6°E) + +F 4E860838 00 917CA5B26B78D2B5 ;Majd feed (26.0°E) +F 4E860838 01 917CA5B26B78D2B5 ;Majd feed (26.0°E) +F 000501FE 00 1111224422333388 ;TV 5 (26.0E) +F 000501FE 01 1111224422333388 ;TV 5 (26.0E) +F 00290429 00 1212123612121236 ;Drama USA (26°E) +F 00290429 01 1212123612121236 ;Drama USA (26°E) +F 00140250 00 1234569C789ABCCE ;Nilesat promo (26°E) +F 00140250 01 1234569C789ABCCE ;Nilesat promo (26°E) + +F 00010064 00 21CD07F51168017A ;ERI TV Earth (30.5°E) +F 00010064 01 21CD07F51168017A ;ERI TV Earth (30.5°E) +F 012F03EB 00 1111113311111133 ;IRIB TV 3 (30.5°E) +F 012F03EB 01 1111113311111133 ;IRIB TV 3 (30.5°E) + +F 0FA000A3 00 A4D352C91B6C28AF :SES Test(31°E) +F 0FA000A3 01 A4D352C91B6C28AF :SES Test(31°E) + +F 1C3E1C3F 00 1111113311111133 ;BTB (31.5°E) +F 1C3E1C3F 01 1111113311111133 ;BTB (31.5°E) +F 1C341C35 00 1111113311111133 ;BTB (31.5°E) +F 1C341C35 01 1111113311111133 ;BTB (31.5°E) + +F 00020055 00 1111113311111133 ;Armenia 1 TV (36°E) +F 00020055 01 1111113311111133 ;Armenia 1 TV (36°E) +F 0A100682 00 1AEF010A0EDEF1DD ;Armenia TV Region (36°E) +F 0A100682 01 1AEF010A0EDEF1DD ;Armenia TV Region (36°E) + +F 000202C7 00 1111113311111133 ;Kentron TV (39°E) +F 000202C7 01 1111113311111133 ;Kentron TV (39°E) + +F 00640065 00 0327022C106251C3 ;GTRK Nizhny Novgorod (40°E) +F 00640065 01 0327022C106251C3 ;GTRK Nizhny Novgorod (40°E) +F 00010134 00 0327022C106251C3 ;GTRK Package (40°E) +F 00010134 01 0327022C106251C3 ;GTRK Package (40°E) +F 00010021 00 0327022C106251C3 ;GTRK Vainah (40°E) +F 00010021 01 0327022C106251C3 ;GTRK Vainah (40°E) +F 00030136 00 0327022C106251C3 ;GTRK Komi Gor (40°E) +F 00030136 01 0327022C106251C3 ;GTRK Komi Gor (40°E) +F 00020201 00 0327022C106251C3 ;Rossiya 1 (0h) (40°E) +F 00020201 01 0327022C106251C3 ;Rossiya 1 (0h) (40°E) +F 00050204 00 0327022C106251C3 ;Rossiya 1 (+2h) (40°E) +F 00050204 01 0327022C106251C3 ;Rossiya 1 (+2h) (40°E) + +F 3C281130 00 F0212435149122C7 ;Nat Geo Wild HD Turkiye (42°E) +F 3C281130 01 F0212435149122C7 ;Nat Geo Wild HD Turkiye (42°E) +F 00010200 00 1012002223000326 ;TX9 (42°E) +F 00010200 01 1012002223000326 ;TX9 (42°E) +F 00020202 00 1012002223000326 ;TX10 (42°E) +F 00020202 01 1012002223000326 ;TX10 (42°E) +F 00030204 00 1012002223000326 ;TX11 (42°E) +F 00030204 01 1012002223000326 ;TX11 (42°E) +F 00040206 00 1012002223000326 ;TX12 (42°E) +F 00040206 01 1012002223000326 ;TX12 (42°E) +F 000717FF 00 DFFEFCD9FDBF18D4 ;NBA TV (42.0°E) +F 000717FF 01 DFFEFCD9FDBF18D4 ;NBA TV (42.0°E) +F 00010134 00 2012ABDDCD2012FF ;Xazar TV (42.0°E) +F 00010134 01 2012ABDDCD2012FF ;Xazar TV (42.0°E) +F 296D0645 00 1000001000000000 ;TRT World HD (42.0°E) +F 296D0645 01 1000001000000000 ;TRT World HD (42.0°E) +F 296A0642 00 1000001000000000 ;TRT HABER HD (42.0°E) +F 296A0642 01 1000001000000000 ;TRT HABER HD (42.0°E) +F 001109AB 00 1000001000000000 ;Fog TV (42.0°E) +F 001109AB 01 1000001000000000 ;Fog TV (42.0°E) +F 000B1F9A 00 3453450034534500 ;Idman_Azerbaycan (42.0°E) +F 000B1F9A 01 3453450034534500 ;Idman_Azerbaycan (42.0°E) +F 00011BB2 00 1234560065432100 ;AzTV Azerbaijan (42.0°E) +F 00011BB2 01 1234560065432100 ;AzTV Azerbaijan (42.0°E) +F 00010134 00 98B0AFF78711C65E ;NTV ANK.Buro (42.0°E) +F 00010134 01 98B0AFF78711C65E ;NTV ANK.Buro (42.0°E) +F 00070207 00 1000000000000000 ;Star TV Turkey (42.0°E) +F 00070207 01 1000000000000000 ;Star TV Turkey (42.0°E) +F 3DB80C71 00 1000001000000000 ;7/24 (42°E) +F 3DB80C71 01 1000001000000000 ;7/24 (42°E) +F 3DB91FFF 00 002123441361188C ;Intercom Radio (42.0°E) +F 3DB91FFF 01 002123441361188C ;Intercom Radio (42.0°E) +F 2BC31FFF 00 002123441361188C ;Intercom Radio (42.0°E) (42°E) +F 2BC31FFF 01 002123441361188C ;Intercom Radio (42.0°E) (42°E) +F 2BC41FFF 00 002123441361188C ;Intercom HT (Radyo) (42°E) +F 2BC41FFF 01 002123441361188C ;Intercom HT (Radyo) (42°E) +F 2BC51FFF 00 002123441361188C ;Intercom BL (Radyo) (42°E) +F 2BC51FFF 01 002123441361188C ;Intercom BL (Radyo) (42°E) +F 001A1FFF 00 1000001010000010 ;DOST FM Radyo (42.0E) +F 001A1FFF 01 1000001010000010 ;DOST FM Radyo (42.0E) +F 06121FFF 00 1000000000000000 :Fenerbahce Radyo (42.0E) +F 06121FFF 01 1000000000000000 ;Fenerbahce Radyo (42.0E) + +F 000101E1 00 1111113311111133 ;IRMAK TV (46°E) +F 000101E1 01 1111113311111133 ;IRMAK TV (46°E) +F 00010201 00 1028ACE4EB4473A2 ;CBC SPORT HD(46°E) +F 00010201 01 1028ACE4EB4473A2 ;CBC SPORT HD(46°E) +F 000103E9 00 002005250019566F ;1 TV Georgia (46.0°E) +F 000103E9 01 002005250019566F ;1 TV Georgia (46.0°E) +F 000B0835 00 0020050000195600 ;2 TV Georgia (46.0°E) +F 000B0835 01 0020050000195600 ;2 TV Georgia (46.0°E) +F 00010200 00 204710771089710A ;Region TV(46.0°E) +F 00010200 01 204710771089710A ;Region TV(46.0°E) +F 00010134 00 1234560065432100 ;AzTV Azerbaycan (46.0°E) +F 00010134 01 1234560065432100 ;AzTV Azerbaycan (46.0°E) +F 000B0198 00 345345CC345345CC ;Idman TV (46.0°E) +F 000B0198 01 345345CC345345CC ;Idman TV (46.0°E) +F 00070211 00 1234569C654321C9 ;Medeniyet TV (46.0°E) +F 00070211 01 1234569C654321C9 ;Medeniyet TV (46.0°E) +F 00031F9A 00 1212123612121236 ;ITV Azerbaycan (46.0E) +F 00031F9A 01 1212123612121236 ;ITV Azerbaycan (46.0E) +F 00020198 00 3453450034534500 ;Idman Azerbaycan (46.0°E) +F 00020198 01 3453450034534500 ;Idman Azerbaycan (46.0°E) +F 6D66006E 00 1234569Ñ654321Ñ9 ;ZDF (46°E) +F 6D66006E 01 1234569Ñ654321Ñ9 ;ZDF (46°E) + +F 02940295 00 54709155198649E8 ;TEST 1 (TV Center) (49°E) +F 02940295 01 54709155198649E8 ;TEST 1 (TV Center) (49°E) +F 05140135 00 0327022C106251C3 ;GTRK Ugoria (49°E) +F 05140135 01 0327022C106251C3 ;GTRK Ugoria (49°E) +F 00020135 00 0327022C106251C3 ;GTRK Region Tyumen (49°E) +F 00020135 01 0327022C106251C3 ;GTRK Region Tyumen (49°E) +F 00010198 00 0327022C106251C3 ;GTRK Pomorie (49°E) +F 00010198 01 0327022C106251C3 ;GTRK Pomorie (49°E) +F 00010200 00 0327022C106251C3 ;GTRK Karelija (49°E) +F 00010200 01 0327022C106251C3 ;GTRK Karelija (49°E) +F 00020201 00 0327022C106251C3 ;Rossiya 1 (0h) (49°E) +F 00020201 01 0327022C106251C3 ;Rossiya 1 (0h) (49°E) +F 00050204 00 0327022C106251C3 ;Rossiya 1 (+2h) (49°E) +F 00050204 01 0327022C106251C3 ;Rossiya 1 (+2h) (49°E) + +F 000C00C9 00 0000000000000100 ;Nash Dom (53°E) +F 000C00C9 01 0000000000000100 ;Nash Dom (53°E) +F 00060205 00 0327022C106251C3 ;Rossiya 1 (+4h) (53°E) +F 00060205 01 0327022C106251C3 ;Rossiya 1 (+4h) (53°E) +F 00020201 00 0327022C106251C3 ;Rossiya 1 (+6h) (53°E) +F 00020201 01 0327022C106251C3 ;Rossiya 1 (+6h) (53°E) +F 00050204 00 0327022C106251C3 ;Rossiya 1 (+8h) (53°E) +F 00050204 01 0327022C106251C3 ;Rossiya 1 (+8h) (53°E) + +F 00640066 00 2608396712043811 ;Match! TV (55.0°E) +F 00640066 01 2608396712043811 ;Match! TV (55.0°E) +F 01F401F6 00 0327022C106251C3 ;Rossia 1 (55.0°E) +F 01F401F6 01 0327022C106251C3 ;Rossia 1 (55.0°E) +F 00060259 00 62696E39676F7349 ;Lifestyle TV 6 (55°E) +F 00060259 01 62696E39676F7349 ;Lifestyle TV 6 (55°E) +F 000702BD 00 62696E39676F7349 ;Lifestyle TV 7 (55°E) +F 000702BD 01 62696E39676F7349 ;Lifestyle TV 7 (55°E) +F 000D0042 00 C12345006789AB00 ;STS (55°E) +F 000D0042 01 C12345006789AB00 ;STS (55°E) +F 00080036 00 ABC1238F45678935 ;Che (55°E) +F 00080036 01 ABC1238F45678935 ;Che (55°E) +F 000E002D 00 D12345006789AB00 ;Home (55°E) +F 000E002D 01 D12345006789AB00 ;Home (55°E) +F 000C002E 00 1234569C789ABCCE ;STS Love (55°E) +F 000C002E 01 1234569C789ABCCE ;STS Love (55°E) +F 0009003F 00 C12345006789AB00 ;STS +2 (55°E) Disney+7h (90°E) +F 0009003F 01 C12345006789AB00 ;STS +2 (55°E) Disney+7h (90°E) +F 000B0033 00 ABC1238F45678935 ;Che +2 (55°E) +F 000B0033 01 ABC1238F45678935 ;Che +2 (55°E) +F 000A002A 00 D12345006789AB00 ;Home +2 (55°E) +F 000A002A 01 D12345006789AB00 ;Home +2 (55°E) +F 00020026 00 6BA1E5F174BBCAF9 ;Disney +2 (55°E) +F 00020026 01 6BA1E5F174BBCAF9 ;Disney +2 (55°E) +F 00010065 00 62696E39676F7349 ;BB1 (55°E) +F 00010065 01 62696E39676F7349 ;BB1 (55°E) +F 000200C9 00 62696E39676F7349 ;BB2 (55°E) +F 000200C9 01 62696E39676F7349 ;BB2 (55°E) +F 0003012D 00 62696E39676F7349 ;BB3 (55°E) +F 0003012D 01 62696E39676F7349 ;BB3 (55°E) +F 00040191 00 62696E39676F7349 ;BB4 (55°E) +F 00040191 01 62696E39676F7349 ;BB4 (55°E) +F 000501F5 00 62696E39676F7349 ;BB5 (55°E) +F 000501F5 01 62696E39676F7349 ;BB5 (55°E) +F 00060259 00 169037DD278403AE ;Test1 (55°E) +F 00060259 01 169037DD278403AE ;Test1 (55°E) +F 000702BD 00 169037DD278403AE ;Test2 (55°E) +F 000702BD 01 169037DD278403AE ;Test2 (55°E) +F 00080321 00 169037DD278403AE ;Test3 (55°E) +F 00080321 01 169037DD278403AE ;Test3 (55°E) + +F 0001044C 00 1234569C7890ABB3 ;Armenian Public TV (60E°) +F 0001044C 01 1234569C7890ABB3 ;Armenian Public TV (60E°) +F 000204B0 00 1234569C7890ABB3 ;Shoghakat TV (60E°) +F 000204B0 01 1234569C7890ABB3 ;Shoghakat TV (60E°) +F 00030514 00 1234569C7890ABB3 ;Armenia TV Satellite (60E°) +F 00030514 01 1234569C7890ABB3 ;Armenia TV Satellite (60E°) +F 00040578 00 1234569C7890ABB3 ;Shant TV (60E°) +F 00040578 01 1234569C7890ABB3 ;Shant TV (60E°) +F 000505DC 00 1234569C7890ABB3 ;H2 (60E°) +F 000505DC 01 1234569C7890ABB3 ;H2 (60E°) +F 00060640 00 1234569C7890ABB3 ;Kentron (60E°) +F 00060640 01 1234569C7890ABB3 ;Kentron (60E°) +F 000706A4 00 1234569C7890ABB3 ;Yerkir Media (60E°) +F 000706A4 01 1234569C7890ABB3 ;Yerkir Media (60E°) +F 00080708 00 1234569C7890ABB3 ;RTR-Planeta (60E°) +F 00080708 01 1234569C7890ABB3 ;RTR-Planeta (60E°) + +#F 00010200 00 ;Stan Sport (68.5°E) +#F 00010200 01 ;Stan Sport (68.5°E) + +F 06400641 00 6BA1E5F174BBCAF9 ;Disney (75.0°E) +F 06400641 01 6BA1E5F174BBCAF9 ;Disney (75.0°E) +F 03840386 00 1234569C789ABCCE ;Mir Audio Service (75.0°E) +F 03840386 01 1234569C789ABCCE ;Mir Audio Service (75.0°E) + +F 05160CE6 00 0103050907090B1B ;Test_1302 +F 05160CE6 01 0103050907090B1B ;Test_1302 +F 04E61FFF 00 1212123612121236 ;Radio Kunel (85°E) +F 04E61FFF 01 1212123612121236 ;Radio Kunel (85°E) +F 057E0D4E 00 C12345006789AB00 ;STS +4 (85°E) +F 057E0D4E 01 C12345006789AB00 ;STS +4 (85°E) +F 05800D50 00 ABC1238F45678935 ;Peretz +4 (85°E) +F 05800D50 01 ABC1238F45678935 ;Peretz +4 (85°E) +F 057F0D4F 00 D12345006789AB00 ;Home +4 (85°E) +F 057F0D4F 01 D12345006789AB00 ;Home +4 (85°E) +F 051E0CEE 00 1234569C789ABCCE ;ÑÒÑ Love (85°E) +F 051E0CEE 01 1234569C789ABCCE ;ÑÒÑ Love (85°E) +F 0325070D 00 D12345006789AB00 ;Home 0 (85°E) +F 0325070D 01 D12345006789AB00 ;Home 0 (85°E) +F 0326070E 00 D12345006789AB00 ;Home 2 (85°E) +F 0326070E 01 D12345006789AB00 ;Home 2 (85°E) +F 00FB04E3 00 D12345006789AB00 ;Home -4 (85°E) +F 00FB04E3 01 D12345006789AB00 ;Home -4 (85°E) +F 00FC04E4 00 1234569C789ABCCE ;Home-R (85°E) +F 00FC04E4 01 1234569C789ABCCE ;Home-R (85°E) +F 00FB04E3 00 1234569C789ABCCE ;Home -7 (85°E) +F 00FB04E3 01 1234569C789ABCCE ;Home -7 (85°E) +F 03210709 00 C12345006789AB00 ;STS 0 (85°E) +F 03210709 01 C12345006789AB00 ;STS 0 (85°E) +F 0322070A 00 C12345006789AB00 ;STS 2 (85°E) +F 0322070A 01 C12345006789AB00 ;STS 2 (85°E) +F 0005003C 00 C12345006789AB00 ;STS +4 (85°E) +F 0005003C 01 C12345006789AB00 ;STS +4 (85°E) +F 00FA04E2 00 C12345006789AB00 ;STS -4 (85°E) +F 00FA04E2 01 C12345006789AB00 ;STS -4 (85°E) +F 0323070B 00 ABC1238F45678935 ;Peretz 0 (85°E) +F 0323070B 01 ABC1238F45678935 ;Peretz 0 (85°E) +F 0324070C 00 ABC1238F45678935 ;Peretz 2 (85°E) +F 0324070C 01 ABC1238F45678935 ;Peretz 2 (85°E) +F 00FD04E5 00 ABC1238F45678935 ;Perez -4 (85°E) +F 00FD04E5 01 ABC1238F45678935 ;Perez -4 (85°E) +F 0063044B 00 198313AF041983A0 ;Test-99 (85.1°E) +F 0063044B 01 198313AF041983A0 ;Test-99 (85.1°E) +F 03890771 00 BABABA2EBABABA2E ;Test Bryansk (85.1E°) +F 03890771 01 BABABA2EBABABA2E ;Test Bryansk (85.1E°) +F 04611FFF 00 1234560012345600 ;Mir Belogore radio (85.1°E) +F 04611FFF 01 1234560012345600 ;Mir Belogore radio (85.1°E) + +F 00010134 00 0327022C106251C3 ;GTRK Bira (90E°) +F 00010134 01 0327022C106251C3 ;GTRK Bira (90E°) +F 001102BD 00 2608396712043811 ;Rossia 2 (90E°) +F 001102BD 01 2608396712043811 ;Rossia 2 (90E°) +F 00010134 00 0327022C106251C3 ;GTRK Chita (90E°) +F 00010134 01 0327022C106251C3 ;GTRK Chita (90E°) +F 00010133 00 0327022C106251C3 ;GTRK Gorny Altai (90E°) +F 00010133 01 0327022C106251C3 ;GTRK Gorny Altai (90E°) +F 00010200 00 0327022C106251C3 ;GTRK Tver (90E°) +F 00010200 01 0327022C106251C3 ;GTRK Tver (90E°) +F 00010028 00 57081372163689D5 ;MUSIC BOX RU (90E°) +F 00010028 01 57081372163689D5 ;MUSIC BOX RU (90E°) +F 0002002B 00 3710468D3138036C ;MUSIC BOX TV (90E°) +F 0002002B 01 3710468D3138036C ;MUSIC BOX TV (90E°) +F 0007003C 00 C12345006789AB00 ;STS +4 (90°E) +F 0007003C 01 C12345006789AB00 ;STS +4 (90°E) +F 00090038 00 ABC1238F45678935 ;Che +4 (90°E) +F 00090038 01 ABC1238F45678935 ;Che +4 (90°E) +F 00080034 00 D12345006789AB00 ;Home +4(90°E) +F 00080034 01 D12345006789AB00 ;Home +4(90°E) +F 01B20022 00 1234569C789ABCCE ;STS Love+7 (90E°) +F 01B20022 01 1234569C789ABCCE ;STS Love+7 (90E°) +F 0007003E 00 6BA1E5F174BBCAF9 ;Disney +7 (90E°) +F 0007003E 01 6BA1E5F174BBCAF9 ;Disney +7 (90E°) +F 000A004E 00 C12345676789AB9B ;STS +7 (90E°) +F 000A004E 01 C12345676789AB9B ;STS +7 (90E°) +F 000F0051 00 ABC1238F45678935 ;Peretz +7 (90E°) +F 000F0051 01 ABC1238F45678935 ;Peretz+7 (90E°) +F 000C0055 00 D12345396789AB9B ;Home +7 (90E°) +F 000C0055 01 D12345396789AB9B ;Home +7 (90E°) +F 000D004A 00 5322017658567422 ;HUMOR TV (90E°) +F 000D004A 01 5322017658567422 ;HUMOR TV (90E°) +F 0004002B 00 A260696B7182988B ;Jug Don Tv (90E°) +F 0004002B 01 A260696B7182988B ;Jug Don Tv (90E°) +F 001111F9 00 40A73F262C34AE0E ;Test Am (90°E) +F 001111F9 01 40A73F262C34AE0E ;Test Am (90°E) +F 00120059 00 3901356F2673059E ;Football (90E°) +F 00120059 01 3901356F2673059E ;Football (90E°) +F 00090065 00 6BA1E5F174BBCAF9 ;Disney (+7h)(90°E) 11265 Í 30000 3/4 S2 +F 00090065 01 6BA1E5F174BBCAF9 ;Disney (+7h)(90°E) 11265 Í 30000 3/4 S2 +F 000A003C 00 C12345676789AB9B ;STS (+7h)(90°E) 11265 Í 30000 3/4 S2 +F 000A003C 01 C12345676789AB9B ;STS (+7h)(90°E) 11265 Í 30000 3/4 S2 +F 000B003F 00 ABC1238F45678935 ;Che+7(90°E) 11265 Í 30000 3/4 S2 +F 000B003F 01 ABC1238F45678935 ;Che+7(90°E) 11265 Í 30000 3/4 S2 +F 000C0043 00 D12345396789AB9B ;HOME+7(90°E) 11265 Í 30000 3/4 S2 +F 000C0043 01 D12345396789AB9B ;HOME+7(90°E) 11265 Í 30000 3/4 S2 +F 000D0046 00 3901350026730500 ;Football (90°Å) 11265 Í 30000 3/4 S2 +F 000D0046 01 3901350026730500 ;Football (90°Å) 11265 Í 30000 3/4 S2 + +F 00060205 00 0327022C106251C3 ;Dubl-3+RRD3 (96.5E) 3675 V 33483 +F 00060205 01 0327022C106251C3 ;Dubl-3+RRD3 (96.5E) 3675 V 33483 +F 00020201 00 0327022C106251C3 ;Rossiya 1 (+6h) (96.5E) 3875 V 33484 +F 00020201 01 0327022C106251C3 ;Rossiya 1 (+6h) (96.5E) 3875 V 33484 +F 00010580 00 0327022C106251C3 ;GTRK Novosibirsk (96.5E) 3758 V 4340 +F 00010580 01 0327022C106251C3 ;GTRK Novosibirsk (96.5E) 3758 V 4340 +F 00010134 00 0327022C106251C3 ;GTRK Altai (96.5E) 3817 V 4270 +F 00010134 01 0327022C106251C3 ;GTRK Altai (96.5E) 3817 V 4270 +F 00010060 00 0327022C106251C3 ;GTRK Tomsk (96.5E) 10979 H 3200 +F 00010060 01 0327022C106251C3 ;GTRK Tomsk (96.5E) 10979 H 3200 +F 00020201 00 0327022C106251C3 ;Dubl-2+RRD2 (96.5E) +F 00020201 01 0327022C106251C3 ;Dubl-2+RRD2 (96.5E) +F 00060205 00 0327022C106251C3 ;Dubl-3+RRD3 (96.5°E) +F 00060205 01 0327022C106251C3 ;Dubl-3+RRD3 (96.5°E) +F 00010580 00 0327022C106251C3 ;GTRK Novosibirsk (96.5°E) +F 00010580 01 0327022C106251C3 ;GTRK Novosibirsk (96.5°E) +F 00050204 00 0327022C106251C3 ;Rossiya 1 (+8h) (96.5°E) +F 00050204 01 0327022C106251C3 ;Rossiya 1 (+8h) (96.5°E) +F 00020201 00 0327022C106251C3 ;Rossiya 1 (+6h) (96.5°E) +F 00020201 01 0327022C106251C3 ;Rossiya 1 (+6h) (96.5°E) +F 00010134 00 0327022C106251C3 ;GTRK Krasnoyarsk (96.5°E) +F 00010134 01 0327022C106251C3 ;GTRK Krasnoyarsk (96.5°E) +F 00010060 00 0327022C106251C3 ;GTRK Tomsk (96.5°E) +F 00010060 01 0327022C106251C3 ;GTRK Tomsk (96.5°E) + +F 00020201 00 0327022C106251C3 ;Rossiya 1 (+6h) (103°E) +F 00020201 01 0327022C106251C3 ;Rossiya 1 (+6h) (103°E) +F 00050204 00 0327022C106251C3 ;Rossiya 1 (+8h) (103°E) +F 00050204 01 0327022C106251C3 ;Rossiya 1 (+8h) (103°E) + +F 00010134 00 0327022C106251C3 ;GTRK Magadan (140°E) +F 00010134 01 0327022C106251C3 ;GTRK Magadan (140°E) +F 00010100 00 0327022C106251C3 ;GTRK Amur (140°E) +F 00010100 01 0327022C106251C3 ;GTRK Amur (140°E) +F 00650134 00 0327022C106251C3 ;GTRK Kamchatka (140°E) +F 00650134 01 0327022C106251C3 ;GTRK Kamchatka (140°E) +F 00020204 00 0327022C106251C3 ;Rossiya 1 (+8h) (140°E) +F 00020204 01 0327022C106251C3 ;Rossiya 1 (+8h) (140°E) +F 00060201 00 0327022C106251C3 ;Rossiya 1 (+6h) (140°E) +F 00060201 01 0327022C106251C3 ;Rossiya 1 (+6h) (140°E) +F 000702BD 00 2608396712043811 ;Rossiya 2 (140°E) +F 000702BD 01 2608396712043811 ;Rossiya 2 (140°E) +F 00010201 00 0327022C106251C3 ;GTRK Sakhalin (140°E) +F 00010201 01 0327022C106251C3 ;GTRK Sakhalin (140°E) +F 033500DD 00 C12345676789AB9B ;STS (+7h) (140°E) +F 033500DD 01 C12345676789AB9B ;STS (+7h) (140°E) +F 033600DE 00 D12345396789AB9B ;Home (+7h) (140°E) +F 033600DE 01 D12345396789AB9B ;Home (+7h) (140°E) +F 033700DF 00 0327022C106251C3 ;Peretz (+7h) (140°E) +F 033700DF 01 0327022C106251C3 ;Peretz (+7h) (140°E) + +F 00010200 00 F34698D188513B14 ;ITA 473 ch1 & ITA 473 ch2 + New Freq 12715 H 7500 (5°W) +F 00010200 01 F34698D188513B14 ;ITA 473 ch1 & ITA 473 ch2 + New Freq 12715 H 7500 (5°W) +F 0065012D 00 3C4D5EE76F12AB2C ;Reversible Guadeloupe (5.0°W) +F 0065012D 01 3C4D5EE76F12AB2C ;Reversible Guadeloupe (5.0°W) + +F 12700213 00 1234569C789C3347 ;Dubai 33 (7.0°W) +F 12700213 01 1234569C789C3347 ;Dubai 33 (7.0°W) +F 000B044D 00 444333BA22211154 ;MBC Test 1 (7.0°W) +F 000B044D 01 444333BA22211154 ;MBC Test 1 (7.0°W) + +F 03850134 00 AB737C9A54D199BE ;Caribbean 901 (15.0°W) +F 03850134 01 AB737C9A54D199BE ;Caribbean 901 (15.0°W) +F 03860135 00 B86E4C72DD273E42 ;Syndication 902 (15.0°W) +F 03860135 01 B86E4C72DD273E42 ;Syndication 902 (15.0°W) + +F 000405B4 00 E876F04E8BA51141 ;EFB Ch.1 (24.5°W) +F 000405B4 01 E876F04E8BA51141 ;EFB Ch.1 (24.5°W) + +F 45401901 00 D581F94F24112D62 ;Channel 5 HD (27.5W) +F 45401901 01 D581F94F24112D62 ;Channel 5 HD (27.5W) +F 4F801D4D 00 D581F94F24112D62 ;Film 4+1 UK (27.5W) +F 4F801D4D 01 D581F94F24112D62 ;Film 4+1 UK (27.5W) +F 444017D5 00 D581F94F24112D62 ;BBC HD (27.5W) +F 444017D5 01 D581F94F24112D62 ;BBC HD (27.5W) +F 448419C9 00 D581F94F24112D62 ;BBC One HD (27.5W) +F 448419C9 01 D581F94F24112D62 ;BBC One HD (27.5W) +F 44C81839 00 D581F94F24112D62 ;ITV1 HD (27.5W) +F 44C81839 01 D581F94F24112D62 ;ITV1 HD (27.5W) +F 4500189D 00 D581F94F24112D62 ;Channel 4 HD (27.5W) +F 4500189D 01 D581F94F24112D62 ;Channel 4 HD (27.5W) +F 4CC01A2D 00 D581F94F24112D62 ;303 (27.5W) +F 4CC01A2D 01 D581F94F24112D62 ;303 (27.5W) +F 10440065 00 D581F94F24112D62 ;BBC ONE (27.5W) +F 10440065 01 D581F94F24112D62 ;BBC ONE (27.5W) +F 10BF00C9 00 D581F94F24112D62 ;BBC TWO (27.5W) +F 10BF00C9 01 D581F94F24112D62 ;BBC TWO (27.5W) +F 10C0012D 00 D581F94F24112D62 ;BBC THREE (27.5W) +F 10C0012D 01 D581F94F24112D62 ;BBC THREE (27.5W) +F 11C00191 00 D581F94F24112D62 ;BBC FOUR (27.5W) +F 11C00191 01 D581F94F24112D62 ;BBC FOUR (27.5W) +F 110001F5 00 D581F94F24112D62 ;BBC NEWS (27.5W) +F 110001F5 01 D581F94F24112D62 ;BBC NEWS (27.5W) +F 1200012D 00 D581F94F24112D62 ;CBBC (27.5W) +F 1200012D 01 D581F94F24112D62 ;CBBC (27.5W) +F 12400191 00 D581F94F24112D62 ;CBeebies (27.5W) +F 12400191 01 D581F94F24112D62 ;CBeebies (27.5W) +F 12800259 00 D581F94F24112D62 ;BBC Parliament (27.5W) +F 12800259 01 D581F94F24112D62 ;BBC Parliament (27.5W) +F 107D13ED 00 D581F94F24112D62 ;BBC ONE NI (27.5W) +F 107D13ED 01 D581F94F24112D62 ;BBC ONE NI (27.5W) +F 107C1005 00 D581F94F24112D62 ;BBC ONE Scot (27.5W) +F 107C1005 01 D581F94F24112D62 ;BBC ONE Scot (27.5W) +F 107E0C1D 00 D581F94F24112D62 ;BBC ONE Wales (27.5W) +F 107E0C1D 01 D581F94F24112D62 ;BBC ONE Wales (27.5W) +F 11401FFF 00 D581F94F24112D62 ;BBC Red Button (27.5W) +F 11401FFF 01 D581F94F24112D62 ;BBC Red Button (27.5W) + +F 00010101 00 383838A8383838A8 ;Agencia EFE (30°W) +F 00010101 01 383838A8383838A8 ;Agencia EFE (30°W) +F 001106A4 00 851267FE339412D9 ;RESUMEN 10 (30.0°W) +F 001106A4 01 851267FE339412D9 ;RESUMEN 10 (30.0°W) +F 01F40443 00 12481670326412A8 ;SD TVI Internacional (30.0°W) +F 01F40443 01 12481670326412A8 ;SD TVI Internacional (30.0°W +F 000707D7 00 F9E8D7B8C6B5A41F ;Fox Sports HD (30.0°W) +F 000707D7 01 F9E8D7B8C6B5A41F ;Fox Sports HD (30.0°W) +F 02BD1B63 00 383838A8383838A8 ;National Geographic HD (30.0°W) +F 02BD1B63 01 383838A8383838A8 ;National Geographic HD (30.0°W) +F 02BE1B6D 00 383838A8383838A8 ;National Geographic Portugal (30.0°W) +F 02BE1B6D 01 383838A8383838A8 ;National Geographic Portugal (30.0°W) +# ........................ +# ::::::::: CCW'S ::::::::: +#^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: MTV Portugal 9°E CCW's ::::::: +F 06A50969 00 ;MTV Portugal (9°E) +F 06A50969 01 ;MTV Portugal (9°E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: FreeX TV/French Lover/XTSY ::::::: +F 128F1D7F 00 ; XTSY (13.0°E) +F 128F1D7F 01 ; XTSY (13.0°E) +F 08330FA2 00 ;Free-X TV (13.0E) +F 08330FA2 01 ;Free-X TV (13.0E) +F 08320FA1 00 ;French Lover TV (13.0E) +F 08320FA1 01 ;French Lover TV (13.0E) +# ::::::: PentHause HD 9E CCW's ::::::: +F 000A0026 00 ;Penthouse HD (9.0°E) +F 000A0026 01 ;Penthouse HD (9.0°E) +F 00140027 00 ;Penthouse HD 1 (9.0°E) +F 00140027 01 ;Penthouse HD 1 (9.0°E) +F 001E0028 00 ;Penthouse HD 2 (9.0°E) +F 001E0028 01 ;Penthouse HD 2 (9.0°E +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#:::::::: CSLink & SkyLink 23E CCW's :::::::: +F 23290640 00 ;FilmBox (23.5E) +F 23290640 01 ;FilmBox (23.5E) +F 232B0641 00 ;FilmBox Extra (23.5E) +F 232B0641 01 ;FilmBox Extra (23.5E) +F 13AE00B2 00 ;NatGeo Wild Hungary (23.5E) +F 13AE00B2 01 ;NatGeo Wild Hungary (23.5E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#:::::::: MTV Networks 13E CCW's ::::::: +F 000619D0 00 ;Viacom Blink! (13.0E) +F 000619D0 01 ;Viacom Blink! (13.0E) +F 00011B59 00 ;MTV Live HD (13.0E) +F 00011B59 01 ;MTV Live HD (13.0E) +F 000A184F 00 ;Comedy Central Polska (13.0E) +F 00071803 00 ;VH1 (13.0E) +F 00071803 01 ;VH1 (13.0E) +F 00041EE0 00 ;Comedy Central Family Polska (13.0E) +F 00041EE0 01 ;Comedy Central Family Polska (13.0E) +F 000A184F 01 ;Comedy Central Polska (13.0E) +F 000B1850 00 ;Nickeladeon Europe (13.0E) +F 000B1850 01 ;Nickeladeon Europe (13.0E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: MTV Network 19.2E CCW's ::::::: +F 70021790 00 ; MTV Pulse (19.2E) +F 70021790 01 ; MTV Pulse (19.2E) +F 70031791 00 ; MTV IDOL (19.2E) +F 70031791 01 ; MTV IDOL (19.2E) +F 6FFF1B59 00 ; MTV Music (19.2E) +F 6FFF1B59 01 ; MTV Music (19.2E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: HUSTLER HD-3D/Redlight Premium/Redlight 3D-HD +F 42231E21 00 ;Redlight Premium (13.0°E) +F 42231E21 01 ;Redlight Premium (13.0°E) +F 42241D74 00 ;Redlight 3D-HD (13.0°E) +F 42241D74 01 ;Redlight 3D-HD (13.0°E) +F 42251E0B 00 ;HUSTLER HD-3D (13.0°E) +F 42251E0B 01 ;HUSTLER HD-3D (13.0°E) +F 42251ECA 00 ;HUSTLER HD-3D (13.0°E) +F 42251ECA 01 ;HUSTLER HD-3D (13.0°E) +F 42251D60 00 ;HUSTLER HD-3D (13.0°E) +F 42251D60 01 ;HUSTLER HD-3D (13.0°E) +F 42251D5F 00 ;HUSTLER HD-3D (13.0°E) +F 42251D5F 01 ;HUSTLER HD-3D (13.0°E) +F 42251D55 00 ;HUSTLER HD-3D (13.0°E) +F 42251D55 01 ;HUSTLER HD-3D (13.0°E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: SSR/SRG Swiss (TSR/RSI LA/SF 13E CCW's ::::::: +F 433102CF 00 ; SF 1 HD (13.0°E) +F 433102CF 01 ; SF 1 HD (13.0°E) +F 433202CF 00 ; SF Zwei HD (13.0°E) +F 433202CF 01 ; SF Zwei HD (13.0°E) +F 433302CF 00 ; TSR 1 HD (13.0°E) +F 433302CF 01 ; TSR 1 HD (13.0°E) +F 433402CF 00 ; TSR 2 HD (13.0°E) +F 433402CF 01 ; TSR 2 HD (13.0°E) +F 36B202CE 00 ; TSR 1 (13.0°E) +F 36B202CE 01 ; TSR 1 (13.0°E) +F 36B302CE 00 ; TSI 1 (13.0°E) +F 36B302CE 01 ; TSI 1 (13.0°E) +F 36B802CE 00 ; TSR 2 (13.0°E) +F 36B802CE 01 ; TSR 2 (13.0°E) +F 36B902CE 00 ; TSI 2 (13.0°E) +F 36B902CE 01 ; TSI 2 (13.0°E) +F 36E302CE 00 ; RSI La 1 HD (13.0°E) +F 36E302CE 01 ; RSI La 1 HD (13.0°E) +F 038502CD 00 ; SF 1 (13.0°E) +F 038502CD 01 ; SF 1 (13.0°E) +F 038B02CD 00 ; SF 2 (13.0°E) +F 038B02CD 01 ; SF 2 (13.0°E) +F 038F02CD 00 ; SFI (13.0°E) +F 038F02CD 01 ; SFI (13.0°E) +F 03B702CD 00 ; RSI La 2 HD (13.0°E) +F 03B702CD 01 ; RSI La 2 HD (13.0°E) +F 03DE02CD 00 ; HD suisse (13.0°E) +F 03DE02CD 01 ; HD suisse (13.0°E) +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#::::::: Total TV (16.0°E) CCW's ::::::: +F 032503B7 00 ;Fox Life (16.0E) +F 032503B7 01 ;Fox Life (16.0E) +F 032403B8 00 ;Fox Crime (16.0E) +F 032403B8 01 ;Fox Crime (16.0E) +F 032603B9 00 ;Nat Geographic (16.0E) +F 032603B9 01 ;Nat Geographic (16.0E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: Baby Tv 13E CCW's Keys ::::::: +F 439D0807 00 ; BABY TV (13.0E) +F 439D0807 01 ; BABY TV (13.0E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# :::::: Raduga TV 75E CCW's ::::::: +F 012C0132 00 ;ESP Russian (75°E) +F 012C0132 01 ;ESP Russian (75°E) +F 01900196 00 ;ESP2 Russian (75°E) +F 01900196 01 ;ESP2 Russian (75°E) +F 012C0131 00 ;ESP Russian (75°E) +F 012C0131 01 ;ESP Russian (75°E) +F 01900195 00 ;ESP2 Russian (75°E) +F 01900195 01 ;ESP2 Russian (75°E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#::::::: AXN Adria CCW's :::::: +F 1AC21D51 00 ;AXN Adria (16°E) +F 1AC21D51 01 ;AXN Adria (16°E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#::::::: Dozhdj/NTV 4.9E/90.0E CCW's :::::: +F 010E010F 00 ;Dozhdj 4.9E +F 010E010F 01 ;Dozhdj 4.9E +F 000A0032 00 ;NTV 4.9E +F 000A0032 01 ;NTV 4.9E +F 02710270 00 ;Dozhdj 90.0E +F 02710270 01 ;Dozhdj 90.0E +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: Telelombardia 13E CCW's +F 0E200269 00 ; Telelombardia (13.0E) +F 0E200269 01 ; Telelombardia (13.0E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: NSAB 5E CCW's ::::::: +F 19E619EF 00 ;Football (4.8E) +F 19E619EF 01 ;Football (4.8E) +F 1A041A0D 00 ;Football+ (4.8E) +F 1A041A0D 01 ;Football+ (4.8E) +F 17FC1805 00 ;Kanal Ukraina (4.8E) +F 17FC1805 01 ;Kanal Ukraina (4.8E) +F 19DC19E5 00 ;Ukraina (4.8E) +F 19DC19E5 01 ;Ukraina (4.8E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: EQUIDIA 13E CCW's ::::::: +F 043900 00 ;EQUIDIA PRO P1 13°E +F 043900 01 ;EQUIDIA PRO P1 13°E +F 043900 00 ;EQUIDIA PRO 13°E +F 043900 01 ;EQUIDIA PRO 13°E +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: Sky Italia DCW Keys (13E) ::::::: +F 2FD20516 00 ;DMAX (13.0°E) +F 2FD20516 01 ;DMAX (13.0°E) +F 2FD3051C 00 ;Frisbee (13.0°E) +F 2FD3051C 01 ;Frisbee (13.0°E) +F 2FD4051F 00 ;Radio Capital Tv (13.0°E) +F 2FD4051F 01 ;Radio Capital Tv (13.0°E) +F 2FD50519 00 ;K2 (13.0°E) +F 2FD50519 01 ;K2 (13.0°E) +F 2FDE050D 00 ;Nick Junior +1 (13.0°E) +F 2FDE050D 01 ;Nick Junior +1 (13.0°E) +F 2FE0050A 00 ;AXN +1 (13.0°E) +F 2FE0050A 01 ;AXN +1 (13.0°E) +F 2FE704FC 00 ;GXT +1 (13.0°E) +F 2FE704FC 01 ;GXT +1 (13.0°E) +F 2FE804F8 00 ;Cartoon Network +1 (13.0°E) +F 2FE804F8 01 ;Cartoon Network +1 (13.0°E) +F 2FE904FF 00 ;Boomerang +1 (13.0°E) +F 2FE904FF 01 ;Boomerang +1 (13.0°E) +F 2FF00507 00 ;Comedy Central +1 (13.0°E) +F 2FF00507 01 ;Comedy Central +1 (13.0°E) +F 2FF104F9 00 ;Nickelodeon+1 (13.0°E) +F 2FF104F9 01 ;Nickelodeon+1 (13.0°E) +F 1FAC0532 00 ;Sky News International (13.0°E) +F 1FAC0532 01 ;Sky News International (13.0°E) +F 1FBF052C 00 ;Yacht & Sail (13.0°E) +F 1FBF052C 01 ;Yacht & Sail (13.0°E) +F 1FC90522 00 ;Cult Network Italia (13.0°E) +F 1FC90522 01 ;Cult Network Italia (13.0°E) +F 2DD9070A 00 ;Sky Sport 3 Italia (13.0°E) +F 2DD9070A 01 ;Sky Sport 3 Italia (13.0°E) +F 420F008D 00 ;Primocanale(13.0E) +F 420F008D 01 ;Primocanale(13.0E) +F 420B008B 00 ;TG Norba 24(13.0E) +F 420B008B 01 ;TG Norba 24(13.0E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: Daring Tv 13E CCW's ::::::: +F 43B317FF 00 ; Daring!TV (13.0E) +F 43B317FF 01 ; Daring!TV (13.0E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: Trace Tropical HD 9E CCW's ::::::: +F 08CB09D5 00 ;Trace Tropical HD(9.0°E) +F 08CB09D5 01 ;Trace Tropical HD(9.0°E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: Sky Box Office DCW Keys ::::::: +F 14AB0503 00 ;Sky Box Office(28.2E) +F 14AB0503 01 ;Sky Box Office(28.2E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: WDS Tv CCW's ::::::: +F 01F50553 00 ;WDS TV (10°0E) +F 01F50553 01 ;WDS TV (10°0E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#::::::: MTV Trax CCW's ::::::: +F 1B6D050B 00 ; MTV Trax (28.2E) +F 1B6D050B 01 ; MTV Trax (28.2E) +#::::::: Sky Sport Active CCW's ::::::::::: +F 152305C8 00 ;1381 (28.2°E) +F 152305C8 01 ;1381 (28.2°E) +F 152405C8 00 ;1382 (28.2°E) +F 152405C8 01 ;1382 (28.2°E) +F 152505C8 00 ;1383 (28.2°E) +F 152505C8 01 ;1383 (28.2°E) +F 152605C8 00 ;1384 (28.2°E) +F 152605C8 01 ;1384 (28.2°E) +F 152705C8 00 ;1385 (28.2°E) +F 152705C8 01 ;1385 (28.2°E) +F 152805C8 00 ;1386 (28.2°E) +F 152805C8 01 ;1386 (28.2°E) +F 156905C8 00 ;1481 (28.2°E) +F 156905C8 01 ;1481 (28.2°E) +F 156A05C8 00 ;1482 (28.2°E) +F 156A05C8 01 ;1482 (28.2°E) +F 156B05C8 00 ;1483 (28.2°E) +F 156B05C8 01 ;1483 (28.2°E) +F 156C05C8 00 ;1484 (28.2°E) +F 156C05C8 01 ;1484 (28.2°E) +F 156D05C8 00 ;1485 (28.2°E) +F 156D05C8 01 ;1485 (28.2°E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: Private Spice 13.0E CCW's ::::::: +F 125102B3 00 ;Private Spice (13.0°E) +F 125102B3 01 ;Private Spice (13.0°E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: 19E CCW's ::::::: +F 0FA20565 00 ; SBS6 (19.2E) +F 0FA20565 01 ; SBS6 (19.2E) +F 0FA30566 00 ; NEÒ5 (19.2E) +F 0FA30566 01 ; NEÒ5 (19.2E) +F 0FAB0567 00 ; NED1 (19.2E) +F 0FAB0567 01 ; NED1 (19.2E) +F 0FAC0568 00 ; NED2 (19.2E) +F 0FAC0568 01 ; NED2 (19.2E) +F 0FAD0569 00 ; NED3 (19.2E) +F 0FAD0569 01 ; NED3 (19.2E) +#.......................... +# ::::::: Canal Sat 19.2E +F 7A4D0BD9 00 ;L'Equipe 21 (19.2°E) +F 7A4D0BD9 01 ;L'Equipe 21 (19.2°E) +F 24BF19AC 00 ;M6 Music Hits(19.2E) +F 24BF19AC 01 ;M6 Music Hits(19.2E) +F 24BD1998 00 ;Cinecinema Star(19.2E) +F 24BD1998 01 ;Cinecinema Star(19.2E) +F 24C01A1A 00 ;Discovery Channel France(19.2E) +F 24C01A1A 01 ;Discovery Channel France(19.2E) +F 24BC19F2 00 ;InfoSport(19.2E) +F 24BC19F2 01 ;InfoSport(19.2E) +F 24C119C1 00 ;Pink TV(19.2E) +F 24C119C1 01 ;Pink TV(19.2E) +F 24BA19DF 00 ;Se'rie Club(19.2E) +F 24BA19DF 01 ;Se'rie Club(19.2E) +F 24BE1A06 00 ;Te'le'toon(19.2E) +F 24BE1A06 01 ;Te'le'toon(19.2E) +F 24C21A9C 00 ;Te'le'toon +1(19.2E) +F 24C21A9C 01 ;Te'le'toon +1(19.2E) +F 24B91971 00 ;TPS Star(19.2E) +F 24B91971 01 ;TPS Star(19.2E) +F 6FF1191A 00 ;VH1 Classic 19.2E +F 6FF1191A 01 ;VH1 Classic 19.2E +F 6FF7180A 00 ;Game One 19.2E +F 6FF7180A 01 ;Game One 19.2E +F 6FFC180C 00 ;Nickelodeon France 19.2E +F 6FFC180C 01 ;Nickelodeon France 19.2E +F 6FFF19B2 00 ;VH1 Europe 19.2E +F 6FFF19B2 01 ;VH1 Europe 19.2E +F 6FF317B1 00 ;MTV Rocks 19.2E +F 6FF317B1 01 ;MTV Rocks 19.2E +F 6FEF190D 00 ;MTV Dance 19.2E +F 6FEF190D 01 ;MTV Dance 19.2E +F 6FEC1806 00 ;MTV France 19.2E +F 6FEC1806 01 ;MTV France 19.2E +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#::::::: Weddeng Tv and Deepam Tv 13E CCW's ::::::: +F 12350295 00 ;Wedding TV (13.0°E) +F 12350295 01 ;Wedding TV (13.0°E) +F 11FE0263 00 ;Deepam TV (13.0°E) +F 11FE0263 01 ;Deepam TV (13.0°E) +#............................... +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: SIC 16E CCW's +F 000103E9 00 ;SIC Internacional (16°E) by Serjoga latvia +F 000103E9 01 ;SIC Internacional (16°E) by Serjoga latvia +#.................................. +#^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: Dorcel TV 13.0°E CCW's ::::::: +F 227B1216 00 ;Dorcel TV (13.0°E) +F 227B1216 01 ;Dorcel TV (13.0°E) +F 2288121B 00 ;Dorcel TV (13.0°E) +F 2288121B 01 ;Dorcel TV (13.0°E) +F 37860B75 00 ;DorcelTV (13.0E) +F 37860B75 01 ;DorcelTV (13.0E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#............................................... +# ::::::: Nat Geo HD UK 16.0°E CCW's ::::::: +F 03E91BCC 00 ;Nat Geo HD UK (16.0°E) by Serjoga latvia +F 03E91BCC 01 ;Nat Geo HD UK (16.0°E) by Serjoga latvia +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ..................................................... +# ::::::: HAYAT TV SAT/HAYAT TV BIH 16.0E CCW's ::::::: +F 00010065 00 ;HAYAT TV BIH (16.0E) +F 00010065 01 ;HAYAT TV BIH (16.0E) +F 00020064 00 ;HAYAT PLUS (16.0E) +F 00020064 01 ;HAYAT PLUS (16.0E) +F 00030064 00 ;Hayat Folk TV (16.0E) +F 00030064 01 ;Hayat Folk TV (16.0E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: Hustler Tv 19.2E CCW's +F 07FA05AA 00 ;Hustler TV viaccess (19.2E) +F 07FA05AA 01 ;Hustler TV viaccess (19.2E) +F 07FA05AA 00 ;Hustler TV seca (19.2E) +F 07FA05AA 01 ;Hustler TV seca (19.2E) +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#::::::: Trace TV 13.0E CCW's ::::::: +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +F 13F10AF5 00 ;Trace TV (13.0E) +F 13F10AF5 01 ;Trace TV (13.0E) +#.......................... +#::::::: SciFi & Universal CCWs +F 3A351B9E 00 ;UNIVERSAL (13.0E) +F 3A351B9E 01 ;UNIVERSAL (13.0E) +F 3A361B9F 00 ;SCi Fi (13.0E) +F 3A361B9F 01 ;SCi Fi (13.0E) +F 3A34057B 00 ;Sport Klub (13.0E) +F 3A34057B 01 ;Sport Klub (13.0E) +#........................ +#::::::: CONTO TV CCW's::::::: +#^^^^^^^^^^^^^^^^^^^^^^^^^ +F 20EC0518 00 ;CONTO TV 2 (13.0E) +F 20EC0518 01 ;CONTO TV 2 (13.0E) +F 20EF0524 00 ;CONTO TV 4 +F 20EF0524 01 ;CONTO TV 4 +#............................... +#::::::: RTVI CCW's ::::::: +#^^^^^^^^^^^^^^^^^^^^^^^^ +F 39D20399 00 ; RTVi Europe (13.0E) +F 39D20399 01 ; RTVi Europe (13.0E) +F 39D3039B 00 ; RTVi Detskii Mir (13.0E) +F 39D3039B 01 ; RTVi Detskii Mir (13.0E) +F 39D4039A 00 ; RTVi Nashe Kino (13.0E) +F 39D4039A 01 ; RTVi Nashe Kino (13.0E) +#................................ +#::::::: Satisfaction TV CCW's ::::::: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +F 35D81777 00 ;Pink O TV (13°E) +F 35D81777 01 ;Pink O TV (13°E) +F 35C10542 00 ;Extocica TV (13°E) +F 35C10542 01 ;Extocica TV (13°E) +F 35C80548 00 ;PassionXXX (13°E) +F 35C80548 01 ;PassionXXX (13°E) +F 35C30545 00 ;SCT (13°E) +F 35C30545 01 ;SCT (13°E) +F 000A0549 00 ;SCT HD (13°E) +F 000A0549 01 ;SCT HD (13°E) +F 35C60546 00 ;CentoxCento (13°E) +F 35C60546 01 ;CentoxCento (13°E) +F 35C70547 00 ;Sesto Senso TV (13°E) +F 35C70547 01 ;Sesto Senso TV (13°E) +F 35C00541 00 ;TGirls TV (13°E) +F 35C00541 01 ;TGirls TV (13°E) +#........................................ +#::::::: Belgium Package CCW's 13E ::::::: +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +F 362F16BD 00 ;La Une (13.0E) +F 362F16BD 01 ;La Une (13.0E) +F 363016BE 00 ;La Deux (13.0E) +F 363016BE 01 ;La Deux (13.0E) +F 363116BF 00 ;RTL-TVi (13.0E) +F 363116BF 01 ;RTL-TVi (13.0E) +F 363216C0 00 ;Club-RTL (13.0°E) +F 363216C0 01 ;Club-RTL (13.0°E) +F 363316C1 00 ;Plug-RTL (13.0E) +F 39D4039A 01 ;Plug-RTL (13.0E) +F 363416C2 00 ;Disney Channel (13.0E) +F 39D4039A 01 ;Disney Channel (13.0E) +#....................................... +#::::::: JSC SPORT CCW's ::::::: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +F 20F514B8 00 ; JSC Sports +1 (13.0E) +F 20F514B8 01 ; JSC Sports +1 (13.0E) +F 20F61648 00 ; JSC Sports +2 (13.0E) +F 20F61648 01 ; JSC Sports +2 (13.0E) +F 20F71710 00 ; JSC Sports +3 (13.0E) +F 20F71710 01 ; JSC Sports +3 (13.0E) +F 20F817D8 00 ; JSC Sports +4 (13.0E) +F 20F817D8 01 ; JSC Sports +4 (13.0E) +F 20F9183C 00 ; JSC Sports +5 (13.0E) +F 20F9183C 01 ; JSC Sports +5 (13.0E) +F 20FA18A0 00 ; JSC Sports +6 (13.0E) +F 20FA18A0 01 ; JSC Sports +6 (13.0E) +F 20FB1904 00 ; JSC Sports +7 (13.0E) +F 20FB1904 01 ; JSC Sports +7 (13.0E) +F 20FC1968 00 ; JSC Sports +8 (13.0E) +F 20FC1968 01 ; JSC Sports +8 (13.0E) +F 20FD19CC 00 ; JSC Sports +9 (13.0E) +F 20FD19CC 01 ; JSC Sports +9 (13.0E) +F 20FE1A30 00 ; JSC Sports +10 (13.0E) +F 20FE1A30 01 ; JSC Sports +10 (13.0E) +F 20FF1AC7 00 ; JSC World Cup (13.0E) +F 20FF1AC7 01 ; JSC World Cup (13.0E) +#........................................... +#::::::: Rai/Tivusat 13E CCW's +F 0D491081 00 ;Rai HD (13.0E) +F 0D491081 01 ;Rai HD (13.0E) +F 0D4B1083 00 ;Rai 3 TGR FVG (13.0E) +F 0D4B1083 01 ;Rai 3 TGR FVG (13.0E) +F 0D521087 00 ;Rai 5 (13.0E) +F 0D521087 01 ;Rai 5 (13.0E) +F 0D661088 00 ;Rai yoyo (13.0E) +F 0D661088 01 ;Rai yoyo (13.0E) +#............................................. +#::::::: TV Globo 13E CCW's ::::::: +F 34D61F40 00 ;TV Globo (13.0E) +F 34D61F40 01 ;TV Globo (13.0E) +#............................................. +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: Nick Jr. 13E CCW's::::::: +F 001E0326 00 (13.0E) +F 001E0326 01 (13.0E) +#.............................................. +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: AustriaSat/HD+ CCW's::::::: +F 15191C9E 00 ;Tele 5 HD (19.2°E) +F 15191C9E 01 ;Tele 5 HD (19.2°E) +F 157F1AE2 00 ;Deluxe Music HD (19.2°E) +F 157F1AE2 01 ;Deluxe Music HD (19.2°E) +F 52741AC2 00 ;N24 HD (19.2°E) +F 52741AC2 01 ;N24 HD (19.2°E) +F 14B51AEC 00 ;ProSieben HD (19.2°E) +F 14B51AEC 01 ;ProSieben HD (19.2°E) +F 52731AC0 00 ;NICH/CC HD (19.2°E) +F 52731AC0 01 ;NICH/CC HD (19.2°E) +# .................................................. +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: Overon/M7 (SkyLink/CSLink) 23.5°E CCW's ::::::: +F 02C5044D 00 ;NatGeo Wild HD DUT (23.5°E) +F 02C5044D 01 ;NatGeo Wild HD DUT (23.5°E) +F 02C71BC7 00 ;M1 - Magyar TV (23.5°E) +F 02C71BC7 01 ;M1 - Magyar TV (23.5°E) +F 02C91BDB 00 ;Duna TV (23.5°E) +F 02C91BDB 01 ;Duna TV (23.5°E) +F 02CA1BE5 00 ;Duna World (23.5°E) +F 02CA1BE5 01 ;Duna World (23.5°E) +F 02CB1BEF 00 ;RTL Klub (23.5°E) +F 02CB1BEF 01 ;RTL Klub (23.5°E) +F 02CC1BF9 00 ;TV 2 (Hungary) (23.5°E) +F 02CC1BF9 01 ;TV 2 (Hungary) (23.5°E) +F 02CD1C03 00 ;Hir TV (23.5°E) +F 02CD1C03 01 ;Hir TV (23.5°E) +F 02CE1C0D 00 ;Magyar ATV (23.5°E) +F 02CE1C0D 01 ;Magyar ATV (23.5°E) +F 02CF1C17 00 ;Nota TV (23.5°E) +F 02CF1C17 01 ;Nota TV (23.5°E) +F 02D01C21 00 ;4!Story TV (23.5°E) +F 02D01C21 01 ;4!Story TV (23.5°E) +F 02D21C35 00 ;Viasat 3 (23.5°E) +F 02D21C35 01 ;Viasat 3 (23.5°E) +F 02D31C3F 00 ;RTL 2 Hungary (23.5°E) +F 02D31C3F 01 ;RTL 2 Hungary (23.5°E) +F 02D41C49 00 ;Super TV 2 (23.5°E) +F 02D41C49 01 ;Super TV 2 (23.5°E) +F 02D51C53 00 ;SportKlub (23.5°E) +F 02D51C53 01 ;SportKlub (23.5°E) +F 02D61C5D 00 ;Sport 1 Hungary (23.5°E) +F 02D61C5D 01 ;Sport 1 Hungary (23.5°E) +F 02D71C67 00 ;Cool TV (23.5°E) +F 02D71C67 01 ;Cool TV (23.5°E) +F 02D81C71 00 ;Digi Sport Hungary (23.5°E) +F 02D81C71 01 ;Digi Sport Hungary (23.5°E) +F 02D91C7B 00 ;Comedy Central Hungary (23.5°E) +F 02D91C7B 01 ;Comedy Central Hungary (23.5°E) +F 02DA1C85 00 ;Discovery Channel Hungary (23.5°E) +F 02DA1C85 01 ;Discovery Channel Hungary (23.5°E) +F 02DB1C8F 00 ;Sport 2 Hungary (23.5°E) +F 02DB1C8F 01 ;Sport 2 Hungary (23.5°E) +F 02DC1C99 00 ;FEM3 (23.5°E) +F 02DC1C99 01 ;FEM3 (23.5°E) +F 02F9044D 00 ;NatGeo Wild HD (23.5°E) +F 02F9044D 01 ;NatGeo Wild HD (23.5°E) +F 15EB044D 00 ;NatGeo Wild HD CZ (23.5°E) +F 15EB044D 01 ;NatGeo Wild HD CZ (23.5°E) +# ........................................................... +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: BFBS 10°E CCW's ::::::: +F 1F490BC1 00 ;09 BBC One Delay (10.0°E) +F 1F490BC1 01 ;09 BBC One Delay (10.0°E) +F 1F420BBA 00 ;02 BBC Two (10.0°E) +F 1F420BBA 01 ;02 BBC Two (10.0°E) +F 1F440BBC 00 ;04 BFBS Extra (10.0°E) +F 1F440BBC 01 ;04 BFBS Extra (10.0°E) +F 1F470BBF 00 ;07 BFBS Sport (10.0°E) +F 1F470BBF 01 ;07 BFBS Sport (10.0°E) +F 1F450BBD 00 ;05 Sky Sports 1 (10.0°E) +F 1F450BBD 01 ;05 Sky Sports 1 (10.0°E) +F 1F460BBE 00 ;Sky Sports 2) (10.0°E) +F 1F460BBE 01 ;Sky Sports 2) (10.0°E) +F 1F480BC0 00 ;08 Sky News (10.0°E) +F 1F480BC0 01 ;08 Sky News (10.0°E) +# ........................................................... +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# ::::::: TRING TV 16.0°E CCWs ::::::: +F 00320037 00 ;JOLLY HD (16.0°E) +F 00320037 01 ;JOLLY HD (16.0°E) +F 00070A32 00 ;RTV21 (16.0°E) +F 00070A32 01 ;RTV21 (16.0°E) +F 0C260C2A 00 ;RTV21 PLUS (16.0°E) +F 0C260C2A 01 ;RTV21 PLUS (16.0°E) +F 003C0041 00 ;BBF (16.0°E) +F 003C0041 01 ;BBF (16.0°E) +F 08D40A46 00 ;TRING FANTASY (16.0°E) +F 08D40A46 01 ;TRING FANTASY (16.0°E) +F 00461004 00 ;TRING HISTORY (16.0°E) +F 00461004 01 ;TRING HISTORY (16.0°E) +F 038A0775 00 ;Fox Life (16.0°E) +F 038A0775 01 ;Fox Life (16.0°E) +F 00501068 00 ;LIVING (16.0°E) +F 00501068 01 ;LIVING (16.0°E) +F 005E07CA 00 ;Agon Channel (16.0°E) +F 005E07CA 01 ;Agon Channel (16.0°E) + +F 3B630517 00 ;Eurosport 2 HD (13.0°E) +F 3B630517 01 ;Eurosport 2 HD (13.0°E) + +F 363B1421 00 ;ESP2 NE (13.0°E) +F 363B1421 01 ;ESP2 NE (13.0°E) + +F 32CA012E 00 ;ORF2 (19.2°E) +F 32CA012E 01 ;ORF2 (19.2°E) + +# ::::::: BeiN Sports 19.2°E CCWs ::::::: + +F 189D0BD7 00 ;BeIN Sport 1 HD (19.2°E) +F 189D0BD7 01 ;BeIN Sport 1 HD (19.2°E) +F 189E0BD8 00 ;BeIN Sport 2 HD (19.2°E) +F 189E0BD8 01 ;BeIN Sport 2 HD (19.2°E) +F 18A00BDA 00 ;BeIN Sport 3 HD (19.2°E) +F 18A00BDA 01 ;BeIN Sport 3 HD (19.2°E) + +# ::::::: FilBox 42°E CCWs ::::::: + +F 3EE61966 00 50CCA6C21AF69BAB ;Fightbox HD (42.0°E) +F 3EE61966 01 50CCA6C21AF69BAB ;Fightbox HD (42.0°E) +F 3EEA196A 00 3D8B26EEDEB7861B ;DaVinci Learning (42.0°E) +F 3EEA196A 01 3D8B26EEDEB7861B ;DaVinci Learning (42.0°E) + +# ::::::: Pershiy Avtomobilniy (1 Auto) 4°Ws ::::::: + +F 000B1111 00 ;Pershiy Avtomobilniy (1 Auto) (4°W) +F 000B1111 01 ;Pershiy Avtomobilniy (1 Auto) (4°W ) + + +# :::::::::: sat-life.info ::::::::::::::: +# <><><><><> by Serjoga latvia <><><><><><> diff --git a/package/lean/dvb/oscam/files/oscam.conf b/package/lean/dvb/oscam/files/oscam.conf new file mode 100755 index 000000000..7305dab93 --- /dev/null +++ b/package/lean/dvb/oscam/files/oscam.conf @@ -0,0 +1,43 @@ +# oscam.conf generated automatically by Streamboard OSCAM 1.20-unstable_svn SVN r11390 +# Read more: http://www.streamboard.tv/svn/oscam/trunk/Distribution/doc/txt/oscam.conf.txt + +[global] +logfile = /var/log/oscam/oscam.log +nice = 0 +maxlogsize = 1000 +preferlocalcards = 1 + +[cache] + +[cccam] +port = 12000 +nodeid = AC2D31EE10E41520 +version = 2.1.1 +reshare = 1 +ignorereshare = 1 +stealth = 1 + +[streamrelay] + +[dvbapi] +enabled = 1 +au = 1 +pmt_mode = 4 +request_mode = 1 +listen_port = 9000 +delayer = 80 +user = TVH +boxtype = pc + +[webif] +httpport = 8888 +httpuser = oscam +httppwd = oscam +httpshowmeminfo = 1 +httpshowuserinfo = 1 +httpshowecminfo = 1 +httpshowloadinfo = 1 +httpallowed = 0.0.0.0-255.255.255.255 +aulow = 120 +httputf8 = 1 + diff --git a/package/lean/dvb/oscam/files/oscam.dvbapi b/package/lean/dvb/oscam/files/oscam.dvbapi new file mode 100644 index 000000000..68fc1c027 --- /dev/null +++ b/package/lean/dvb/oscam/files/oscam.dvbapi @@ -0,0 +1,31 @@ +P: 0500:040620 # NTV+ (36Е) +P: 0500:041200 # NTV+ (36Е) +P: 0500:060A00 # NTV+ (36E) +P: 0500:060C00 # NTV+ (36E) +P: 0500:023100 # trk football (Shara)(5Е) +P: 0500:041200 # trk football (Shara)(5Е) +P: 0500:041700 # Dorcel TV (13Е) +P: 0500:042300 # rtvi (13Е) +P: 0500:042700 # SCT, S1-7-HQ,HD (13Е) +P: 0500:042800 # Absat/BisTV (13Е) +P: 0500:043800 # REDLIGHT HD, Redlight Premium & Daring! TV (13Е) +P: 0100:000068 # Cyfra+ 13e +P: 09CD:0 # Sky 13e +P: 1803:007001 # Polsat (13Е) +P: 1803:007101 # Polsat (13Е) +P: 1803:000000 # Polsat (13Е) +P: 090D:0 # yes 4w +P: 090F:0 # viasat baltic 5e + +# EMU +P: 2600:000000 # BISS +P: 0500:023800 # srg (EMU)(13Е) +P: 0E00:000000 # PowerVU +P: 0500:007400 +P: 0D00:000000 +P: 0D05:000000 +P: 0D02:000000 +P: 1801:000000 + +# Ignor +I:0 diff --git a/package/lean/dvb/oscam/files/oscam.init b/package/lean/dvb/oscam/files/oscam.init new file mode 100755 index 000000000..90f38202e --- /dev/null +++ b/package/lean/dvb/oscam/files/oscam.init @@ -0,0 +1,23 @@ +#!/bin/sh /etc/rc.common + +START=99 +OSCAM_PATH=/usr/bin + +[ -f /tmp/oscam ] && +{ + OSCAM_PATH=/tmp + [ -x /tmp/oscam ] || chmod +x /tmp/oscam +} + +start() { + logger "Starting Oscam" + [ -d /var/log/oscam ] || mkdir -p /var/log/oscam + service_start ${OSCAM_PATH}/oscam -b -r 2 -u +} + +stop() { + logger "Stopping Oscam" + service_stop ${OSCAM_PATH}/oscam -b -r 2 -u +} + + diff --git a/package/lean/dvb/oscam/files/oscam.server b/package/lean/dvb/oscam/files/oscam.server new file mode 100644 index 000000000..fb6b220cb --- /dev/null +++ b/package/lean/dvb/oscam/files/oscam.server @@ -0,0 +1,61 @@ +# oscam.server generated automatically by Streamboard OSCAM 1.20-unstable_svn SVN r11401 +# Read more: http://www.streamboard.tv/svn/oscam/trunk/Distribution/doc/txt/oscam.server.txt + +[reader] +label = emulator +protocol = emu +device = emulator +caid = 0D00,0D02,090F,0500,1801,0604,2600,FFFF,0E00 +detect = cd +ident = 0D00:000000,000004,000010,000014,000020,0000C0,0000C4,0000C8,0000CC;0D02:000000,00008C,0000A0,0000A4,0000A8;090F:000000;0500:000000,030B00,023800,021110,007400,007800;1801:000000,007301,001101;0604:000000;2600:000000;FFFF:000000;0E00:000000 +group = 1 +emmcache = 2,3,2,0 +emu_auproviders = 0500:030B00;0604:010200;0E00:000000 + +# Example for NTV+, all disable + +[reader] +label = reshare1 +description = TVShara1 +enable = 0 +protocol = cccam +device = s4.oscam.org,444 +user = test1 +password = test1 +inactivitytimeout = 200 +reconnecttimeout = 10 +caid = 0500 +group = 1 +cccversion = 2.3.0 +cccreshare = 1 + +[reader] +label = reshare2 +description = TVShara2 +enable = 0 +protocol = newcamd +device = s4.oscam.org,2004 +key = 0102030405060708091011121314 +user = test2 +password = test2 +inactivitytimeout = 200 +reconnecttimeout = 10 +connectoninit = 1 +caid = 0500 +ident = 0500:060A00,041200,060C00,040620 +group = 1 +cccreshare = 1 + +[reader] +label = reshare3 +description = TVShara3 +enable = 0 +protocol = cs357x +device = s4.oscam.org,333 +user = test3 +password = test3 +caid = 0500 +ident = 0500:060A00,041200,060C00,040620 +group = 1 +cccreshare = 1 + diff --git a/package/lean/dvb/oscam/files/oscam.user b/package/lean/dvb/oscam/files/oscam.user new file mode 100644 index 000000000..5e02dd83e --- /dev/null +++ b/package/lean/dvb/oscam/files/oscam.user @@ -0,0 +1,27 @@ +# oscam.user generated automatically by Streamboard OSCAM 1.20-unstable_svn SVN r11401 +# Read more: http://www.streamboard.tv/svn/oscam/trunk/Distribution/doc/txt/oscam.user.txt + +[account] +user = tvheadend_x +pwd = tvheadend_x +monlevel = 4 +au = 1 +group = 1 +max_connections = 100 +cccreshare = 1 + +[account] +user = user1 +pwd = user1 +monlevel = 4 +au = 1 +group = 1 +max_connections = 100 +cccreshare = 1 + +[account] +user = monitor +pwd = monitor +monlevel = 4 +group = 1 + diff --git a/package/lean/dvb/oscam/patches/002-config.patch b/package/lean/dvb/oscam/patches/002-config.patch new file mode 100644 index 000000000..413122177 --- /dev/null +++ b/package/lean/dvb/oscam/patches/002-config.patch @@ -0,0 +1,41 @@ +diff -ruNp trunk.orig/config.h trunk/config.h +--- trunk.orig/config.h 2018-03-25 14:31:53.147349681 +0300 ++++ trunk/config.h 2018-03-25 14:46:42.842348711 +0300 +@@ -22,7 +22,7 @@ + //#define IPV6SUPPORT 1 + #define MODULE_MONITOR 1 + +-//#define MODULE_CAMD33 1 ++#define MODULE_CAMD33 1 + #define MODULE_CAMD35 1 + #define MODULE_CAMD35_TCP 1 + #define MODULE_NEWCAMD 1 +@@ -62,10 +62,14 @@ + #define CARDREADER_STINGER 1 + #define CARDREADER_DRECAS 1 + ++#define WITH_PCSC 1 ++ + #ifdef WITH_PCSC + #define CARDREADER_PCSC 1 + #endif + ++#define WITH_LIBUSB 1 ++ + #ifdef WITH_LIBUSB + #define CARDREADER_SMART 1 + #endif +@@ -83,11 +87,11 @@ + #endif + + #ifdef WITH_STAPI +-#define CARDREADER_STAPI 1 ++//#define CARDREADER_STAPI 1 + #endif + + #ifdef WITH_STAPI5 +-#define CARDREADER_STAPI5 1 ++//#define CARDREADER_STAPI5 1 + #endif + + #ifdef READER_DRE diff --git a/package/lean/dvb/oscam/patches/003-fix_ver.patch b/package/lean/dvb/oscam/patches/003-fix_ver.patch new file mode 100644 index 000000000..fa1551952 --- /dev/null +++ b/package/lean/dvb/oscam/patches/003-fix_ver.patch @@ -0,0 +1,121 @@ +diff -ruNp trunk.patches/globals.h trunk/globals.h +--- trunk.patches/globals.h 2018-04-03 02:48:24.952386413 +0300 ++++ trunk/globals.h 2018-04-03 03:02:59.558440627 +0300 +@@ -365,6 +365,9 @@ typedef unsigned char uchar; + #ifndef CS_SVN_VERSION + # define CS_SVN_VERSION "test" + #endif ++#ifndef CS_EMU_VERSION ++# define CS_EMU_VERSION "000" ++#endif + #ifndef CS_TARGET + # define CS_TARGET "unknown" + #endif +diff -ruNp trunk.patches/Makefile trunk/Makefile +--- trunk.patches/Makefile 2018-04-03 02:44:08.318254054 +0300 ++++ trunk/Makefile 2018-04-03 03:01:12.325689204 +0300 +@@ -5,7 +5,8 @@ SHELL = /bin/sh + .PHONY: all tests help README.build README.config simple default debug config menuconfig allyesconfig allnoconfig defconfig clean distclean + + VER := $(shell ./config.sh --oscam-version) +-SVN_REV := $(shell ./config.sh --oscam-revision) ++#SVN_REV := $(shell ./config.sh --oscam-revision) ++#EMU_REV := 000 + + uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') + +@@ -35,7 +36,7 @@ ifdef USE_SSL + override USE_LIBCRYPTO=1 + endif + +-CONF_DIR = /usr/local/etc ++CONF_DIR = /opt/etc/oscam + + LIB_PTHREAD = -lpthread + LIB_DL = -ldl +@@ -52,6 +53,7 @@ endif + + override STD_LIBS := $(LIB_PTHREAD) $(LIB_DL) $(LIB_RT) + override STD_DEFS := -D'CS_SVN_VERSION="$(SVN_REV)"' ++override STD_DEFS += -D'CS_EMU_VERSION="$(EMU_REV)"' + override STD_DEFS += -D'CS_CONFDIR="$(CONF_DIR)"' + + # Compiler warnings +diff -ruNp trunk.patches/module-dvbapi.c trunk/module-dvbapi.c +--- trunk.patches/module-dvbapi.c 2018-04-03 02:48:24.956386446 +0300 ++++ trunk/module-dvbapi.c 2018-04-03 03:06:13.063827549 +0300 +@@ -533,7 +533,7 @@ int32_t dvbapi_net_send(uint32_t request + if (cfg.dvbapi_extended_cw_api == 2) + strcat(capabilities, ",e2"); + +- *info_len = snprintf((char *) &packet[size], sizeof(packet) - size, "OSCam v%s, build r%s (%s); %s", CS_VERSION, CS_SVN_VERSION, CS_TARGET, capabilities + 1); ++ *info_len = snprintf((char *) &packet[size], sizeof(packet) - size, "OSCam v%s, build r%s + EMU r%s (%s); %s", CS_VERSION, CS_SVN_VERSION, CS_EMU_VERSION, CS_TARGET, capabilities + 1); + size += *info_len; + break; + } +diff -ruNp trunk.patches/module-lcd.c trunk/module-lcd.c +--- trunk.patches/module-lcd.c 2018-04-03 02:44:10.102269013 +0300 ++++ trunk/module-lcd.c 2018-04-03 03:15:44.360059325 +0300 +@@ -81,6 +81,7 @@ static void refresh_lcd_file(void) + + fprintf(fpsave, "Version: %s\n", CS_VERSION); + fprintf(fpsave, "Revision: %s\n", CS_SVN_VERSION); ++ fprintf(fpsave, "EMU rev.: %s\n", CS_EMU_VERSION); + if(days == 0) + { fprintf(fpsave, "up: %02d:%02d:%02d\n", hours, mins, secs); } + else +diff -ruNp trunk.patches/oscam.c trunk/oscam.c +--- trunk.patches/oscam.c 2018-04-03 02:48:24.956386446 +0300 ++++ trunk/oscam.c 2018-04-03 03:10:28.813703490 +0300 +@@ -144,7 +144,7 @@ static void show_usage(void) + "| | | \\___ \\| | / _` | '_ ` _ \\\n" + "| |_| |___) | |_| (_| | | | | | |\n" + " \\___/|____/ \\___\\__,_|_| |_| |_|\n\n"); +- printf("OSCam cardserver v%s, build r%s (%s)\n", CS_VERSION, CS_SVN_VERSION, CS_TARGET); ++ printf("OSCam cardserver v%s, build r%s + EMU r%s (%s)\n", CS_VERSION, CS_SVN_VERSION, CS_EMU_VERSION, CS_TARGET); + printf("Copyright (C) 2009-2015 OSCam developers.\n"); + printf("This program is distributed under GPLv3.\n"); + printf("OSCam is based on Streamboard mp-cardserver v0.9d written by dukat\n"); +@@ -376,6 +376,7 @@ static void write_versionfile(bool use_s + } + + fprintf(fp, "Version: oscam-%s-r%s\n", CS_VERSION, CS_SVN_VERSION); ++ fprintf(fp, "EMU: r%s\n", CS_EMU_VERSION); + fprintf(fp, "Compiler: %s\n", CS_TARGET); + fprintf(fp, "Box type: %s (%s)\n", boxtype_get(), boxname_get()); + fprintf(fp, "PID: %d\n", getppid()); +@@ -634,7 +635,7 @@ static void cs_dumpstack(int32_t sig) + + fprintf(stderr, "crashed with signal %d on %swriting oscam.crash\n", sig, buf); + +- fprintf(fp, "%sOSCam cardserver v%s, build r%s (%s)\n", buf, CS_VERSION, CS_SVN_VERSION, CS_TARGET); ++ fprintf(fp, "%sOSCam cardserver v%s, build r%s + EMU r%s (%s)\n", buf, CS_VERSION, CS_SVN_VERSION, CS_EMU_VERSION, CS_TARGET); + fprintf(fp, "FATAL: Signal %d: %s Fault. Logged StackTrace:\n\n", sig, (sig == SIGSEGV) ? "Segmentation" : ((sig == SIGBUS) ? "Bus" : "Unknown")); + fclose(fp); + +diff -ruNp trunk.patches/oscam-conf.c trunk/oscam-conf.c +--- trunk.patches/oscam-conf.c 2018-04-03 02:44:10.086268878 +0300 ++++ trunk/oscam-conf.c 2018-04-03 03:13:07.970887467 +0300 +@@ -509,8 +509,8 @@ FILE *create_config_file(const char *con + cs_log("ERROR: Cannot create file \"%s\" (errno=%d %s)", temp_file, errno, strerror(errno)); + return NULL; + } +- fprintf(f, "# %s generated automatically by Streamboard OSCAM %s SVN r%s\n", +- conf_filename, CS_VERSION, CS_SVN_VERSION); ++ fprintf(f, "# %s generated automatically by Streamboard OSCAM %s SVN r%s + EMU r%s\n", ++ conf_filename, CS_VERSION, CS_SVN_VERSION, CS_EMU_VERSION); + fprintf(f, "# Read more: http://www.streamboard.tv/svn/oscam/trunk/Distribution/doc/txt/%s.txt\n\n", + conf_filename); + return f; +diff -ruNp trunk.patches/oscam-log.c trunk/oscam-log.c +--- trunk.patches/oscam-log.c 2018-04-03 02:44:09.766266195 +0300 ++++ trunk/oscam-log.c 2018-04-03 03:12:04.910417167 +0300 +@@ -232,7 +232,7 @@ int32_t cs_open_logfiles(void) + // according to syslog docu: calling closelog is not necessary and calling openlog multiple times is safe + // We use openlog to set the default syslog settings so that it's possible to allow switching syslog on and off + openlog(syslog_ident, LOG_NDELAY | LOG_PID, LOG_DAEMON); +- cs_log(">> OSCam << cardserver %s, version " CS_VERSION ", build r" CS_SVN_VERSION " (" CS_TARGET ")", starttext); ++ cs_log(">> OSCam << cardserver %s, version " CS_VERSION ", build r" CS_SVN_VERSION " + EMU r" CS_EMU_VERSION " (" CS_TARGET ")", starttext); + + return (fp <= (FILE *)0); + } diff --git a/package/lean/dvb/oscam/patches/004-oscam_emu.patch b/package/lean/dvb/oscam/patches/004-oscam_emu.patch new file mode 100644 index 000000000..bcab190d7 --- /dev/null +++ b/package/lean/dvb/oscam/patches/004-oscam_emu.patch @@ -0,0 +1,12988 @@ +diff -ruNp trunk.patches/CMakeLists.txt trunk/CMakeLists.txt +--- trunk.patches/CMakeLists.txt 2018-04-03 02:44:09.770266229 +0300 ++++ trunk/CMakeLists.txt 2018-04-03 03:20:07.654045339 +0300 +@@ -101,6 +101,7 @@ include_directories ( + ${CMAKE_CURRENT_SOURCE_DIR}/csctapi + ${CMAKE_CURRENT_SOURCE_DIR}/cscrypt + ${CMAKE_CURRENT_SOURCE_DIR}/minilzo ++ ${CMAKE_CURRENT_SOURCE_DIR}/ffdecsa + ${CMAKE_CURRENT_SOURCE_DIR}/extapi/cygwin + /usr/include/w32api + ${OPTIONAL_INCLUDE_DIR} +@@ -110,6 +111,7 @@ include_directories ( + ${CMAKE_CURRENT_SOURCE_DIR}/csctapi + ${CMAKE_CURRENT_SOURCE_DIR}/cscrypt + ${CMAKE_CURRENT_SOURCE_DIR}/minilzo ++ ${CMAKE_CURRENT_SOURCE_DIR}/ffdecsa + ${OPTIONAL_INCLUDE_DIR} + ) + endif (OSCamOperatingSystem MATCHES "Windows/Cygwin") +@@ -420,6 +422,13 @@ endif (HAVE_PCSC) + # Manage config.h based on command line parameters + # Manipulate config file based on given parameters and read unset parameters + ++execute_process (COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/config.sh --enabled WITH_EMU OUTPUT_VARIABLE CONFIG_WITH_EMU OUTPUT_STRIP_TRAILING_WHITESPACE) ++if (CONFIG_WITH_EMU MATCHES "Y" AND NOT WITH_EMU EQUAL 1) ++ add_definitions ("-DWITH_EMU") ++ set (WITH_EMU "1") ++ message(STATUS " EMU is added by config compiling with EMU") ++endif(CONFIG_WITH_EMU MATCHES "Y" AND NOT WITH_EMU EQUAL 1) ++ + execute_process (COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/config.sh --show-valid OUTPUT_VARIABLE config_vars_string OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REGEX MATCHALL "[A-Z0-9_]+" config_vars ${config_vars_string}) + +@@ -449,6 +458,7 @@ execute_process (COMMAND make --no-print + add_subdirectory (csctapi) + add_subdirectory (minilzo) + add_subdirectory (cscrypt) ++add_subdirectory (ffdecsa) + + #----------------------- file groups ------------------------------ + execute_process (COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/config.sh --enabled MODULE_CAMD33 OUTPUT_VARIABLE CAMD33 OUTPUT_STRIP_TRAILING_WHITESPACE) +@@ -498,7 +508,7 @@ add_library (${csoscam} STATIC ${csoscam + + set (exe_name "oscam") + add_executable (${exe_name} ${exe_srcs} ${exe_hdrs}) +-target_link_libraries (${exe_name} ${csoscam} ${csmodules} ${csreaders} csctapi cscrypt minilzo) ++target_link_libraries (${exe_name} ${csoscam} ${csmodules} ${csreaders} csctapi cscrypt minilzo ffdecsa) + if(HAVE_LIBRT AND HAVE_LIBUSB) + if (LIBUSBDIR) + set (libusb_link "imp_libusb") +@@ -647,6 +657,11 @@ add_definitions ("-D'CS_SVN_VERSION=\"${ + execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpmachine COMMAND tr -d '\n' OUTPUT_VARIABLE CS_TARGET) + add_definitions ("-D'CS_TARGET=\"${CS_TARGET}\"'") + #----------------------- global compile and link options ------------------------------ ++#enable sse2 on x86 ++if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)") ++ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse -msse2 -msse3") ++endif (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)") ++ + # disable warning about unused but set variables in gcc 4.6+ + if (CMAKE_COMPILER_IS_GNUCC) + execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) +@@ -731,6 +746,22 @@ endif( HAVE_LIBRT OR HAVE_LIBRT_STATIC) + + #-------------------------------------------------------------------------------- + ++if (NOT OSCamOperatingSystem MATCHES "Mac OS X") ++if (NOT DEFINED ENV{ANDROID_NDK}) ++if (NOT DEFINED ENV{ANDROID_STANDALONE_TOOLCHAIN}) ++ if(WITH_EMU) ++ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/SoftCam.Key) ++ execute_process(COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/SoftCam.Key ${CMAKE_CURRENT_BINARY_DIR}/SoftCam.Key) ++ else(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/SoftCam.Key) ++ execute_process(COMMAND touch ${CMAKE_CURRENT_BINARY_DIR}/SoftCam.Key) ++ endif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/SoftCam.Key) ++ execute_process(COMMAND touch ${CMAKE_CURRENT_BINARY_DIR}/utils/SoftCam.Key) ++ set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--format=binary -Wl,SoftCam.Key -Wl,--format=default" ) ++ endif(WITH_EMU) ++endif (NOT DEFINED ENV{ANDROID_STANDALONE_TOOLCHAIN}) ++endif (NOT DEFINED ENV{ANDROID_NDK}) ++endif (NOT OSCamOperatingSystem MATCHES "Mac OS X") ++ + #----------------------- installation ----------------------------- + + file (GLOB config_files "${CMAKE_CURRENT_SOURCE_DIR}/Distribution/oscam.*") +@@ -819,4 +850,8 @@ endif(STATIC_LIBUSB EQUAL 1) + endif(STATICLIBUSB AND NOT LIBUSBDIR) + endif (HAVE_LIBUSB) + ++if (WITH_EMU) ++ message(STATUS " Compile with EMU support") ++endif (WITH_EMU) ++ + message (STATUS "") +diff -ruNp trunk.patches/config.h trunk/config.h +--- trunk.patches/config.h 2018-04-03 02:48:33.320455383 +0300 ++++ trunk/config.h 2018-04-03 03:20:07.654045339 +0300 +@@ -1,6 +1,7 @@ + #ifndef CONFIG_H_ + #define CONFIG_H_ + ++#define WITH_EMU 1 + #define WEBIF 1 + #define WEBIF_LIVELOG 1 + #define WEBIF_JQUERY 1 +diff -ruNp trunk.patches/config.sh trunk/config.sh +--- trunk.patches/config.sh 2018-04-03 02:44:09.134260896 +0300 ++++ trunk/config.sh 2018-04-03 03:20:07.654045339 +0300 +@@ -1,6 +1,6 @@ + #!/bin/sh + +-addons="WEBIF WEBIF_LIVELOG WEBIF_JQUERY TOUCH WITH_SSL HAVE_DVBAPI READ_SDT_CHARSETS IRDETO_GUESSING CS_ANTICASC WITH_DEBUG MODULE_MONITOR WITH_LB CS_CACHEEX CW_CYCLE_CHECK LCDSUPPORT LEDSUPPORT CLOCKFIX IPV6SUPPORT" ++addons="WEBIF WEBIF_LIVELOG WEBIF_JQUERY TOUCH WITH_SSL HAVE_DVBAPI READ_SDT_CHARSETS IRDETO_GUESSING CS_ANTICASC WITH_DEBUG MODULE_MONITOR WITH_LB CS_CACHEEX CW_CYCLE_CHECK LCDSUPPORT LEDSUPPORT CLOCKFIX IPV6SUPPORT WITH_EMU" + protocols="MODULE_CAMD33 MODULE_CAMD35 MODULE_CAMD35_TCP MODULE_NEWCAMD MODULE_CCCAM MODULE_CCCSHARE MODULE_GBOX MODULE_RADEGAST MODULE_SCAM MODULE_SERIAL MODULE_CONSTCW MODULE_PANDORA MODULE_GHTTP" + readers="READER_NAGRA READER_IRDETO READER_CONAX READER_CRYPTOWORKS READER_SECA READER_VIACCESS READER_VIDEOGUARD READER_DRE READER_TONGFANG READER_BULCRYPT READER_GRIFFIN READER_DGCRYPT" + card_readers="CARDREADER_PHOENIX CARDREADER_INTERNAL CARDREADER_SC8IN1 CARDREADER_MP35 CARDREADER_SMARGO CARDREADER_DB2COM CARDREADER_STAPI CARDREADER_STAPI5 CARDREADER_STINGER CARDREADER_DRECAS" +@@ -24,6 +24,7 @@ CONFIG_CW_CYCLE_CHECK=y + # CONFIG_LEDSUPPORT=n + CONFIG_CLOCKFIX=y + # CONFIG_IPV6SUPPORT=n ++CONFIG_WITH_EMU=y + # CONFIG_MODULE_CAMD33=n + CONFIG_MODULE_CAMD35=y + CONFIG_MODULE_CAMD35_TCP=y +@@ -289,12 +290,15 @@ get_opts() { + + update_deps() { + # Calculate dependencies +- enabled_any $(get_opts readers) $(get_opts card_readers) && enable_opt WITH_CARDREADER >/dev/null +- disabled_all $(get_opts readers) $(get_opts card_readers) && disable_opt WITH_CARDREADER >/dev/null ++ enabled_any $(get_opts readers) $(get_opts card_readers) WITH_EMU && enable_opt WITH_CARDREADER >/dev/null ++ disabled_all $(get_opts readers) $(get_opts card_readers) WITH_EMU && disable_opt WITH_CARDREADER >/dev/null + disabled WEBIF && disable_opt WEBIF_LIVELOG >/dev/null + disabled WEBIF && disable_opt WEBIF_JQUERY >/dev/null + enabled MODULE_CCCSHARE && enable_opt MODULE_CCCAM >/dev/null + enabled_any CARDREADER_DB2COM CARDREADER_MP35 CARDREADER_SC8IN1 CARDREADER_STINGER && enable_opt CARDREADER_PHOENIX >/dev/null ++ enabled WITH_EMU && enable_opt READER_VIACCESS >/dev/null ++ enabled WITH_EMU && enable_opt READER_DRE >/dev/null ++ enabled WITH_EMU && enable_opt MODULE_NEWCAMD >/dev/null + } + + list_config() { +@@ -344,9 +348,9 @@ list_config() { + not_have_flag USE_LIBCRYPTO && echo "CONFIG_LIB_AES=y" || echo "# CONFIG_LIB_AES=n" + enabled MODULE_CCCAM && echo "CONFIG_LIB_RC6=y" || echo "# CONFIG_LIB_RC6=n" + not_have_flag USE_LIBCRYPTO && enabled MODULE_CCCAM && echo "CONFIG_LIB_SHA1=y" || echo "# CONFIG_LIB_SHA1=n" +- enabled_any READER_DRE MODULE_SCAM READER_VIACCESS && echo "CONFIG_LIB_DES=y" || echo "# CONFIG_LIB_DES=n" +- enabled_any MODULE_CCCAM READER_NAGRA READER_SECA && echo "CONFIG_LIB_IDEA=y" || echo "# CONFIG_LIB_IDEA=n" +- not_have_flag USE_LIBCRYPTO && enabled_any READER_CONAX READER_CRYPTOWORKS READER_NAGRA && echo "CONFIG_LIB_BIGNUM=y" || echo "# CONFIG_LIB_BIGNUM=n" ++ enabled_any READER_DRE MODULE_SCAM READER_VIACCESS WITH_EMU && echo "CONFIG_LIB_DES=y" || echo "# CONFIG_LIB_DES=n" ++ enabled_any MODULE_CCCAM READER_NAGRA READER_SECA WITH_EMU && echo "CONFIG_LIB_IDEA=y" || echo "# CONFIG_LIB_IDEA=n" ++ not_have_flag USE_LIBCRYPTO && enabled_any READER_CONAX READER_CRYPTOWORKS READER_NAGRA WITH_EMU && echo "CONFIG_LIB_BIGNUM=y" || echo "# CONFIG_LIB_BIGNUM=n" + } + + make_config_c() { +@@ -457,6 +461,7 @@ menu_addons() { + LEDSUPPORT "LED support" $(check_test "LEDSUPPORT") \ + CLOCKFIX "Clockfix (disable on old systems!)" $(check_test "CLOCKFIX") \ + IPV6SUPPORT "IPv6 support (experimental)" $(check_test "IPV6SUPPORT") \ ++ WITH_EMU "Emulator support" $(check_test "WITH_EMU") \ + 2> ${tempfile} + + opt=${?} +diff -ruNp trunk.patches/cscrypt/aes.c trunk/cscrypt/aes.c +--- trunk.patches/cscrypt/aes.c 2018-04-03 02:44:10.098268979 +0300 ++++ trunk/cscrypt/aes.c 2018-04-03 03:20:07.654045339 +0300 +@@ -1250,4 +1250,71 @@ void AES_decrypt(const unsigned char *in + rk[3]; + PUTU32(out + 12, s3); + } ++ ++void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, ++ const unsigned long length, const AES_KEY *key, ++ unsigned char *ivec, const int enc) ++{ ++ unsigned long n; ++ unsigned long len = length; ++ unsigned char tmp[AES_BLOCK_SIZE]; ++ ++ assert(in && out && key && ivec); ++ assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc)); ++ ++ if(AES_ENCRYPT == enc) ++ { ++ while(len >= AES_BLOCK_SIZE) ++ { ++ for(n=0; n < AES_BLOCK_SIZE; ++n) ++ tmp[n] = in[n] ^ ivec[n]; ++ ++ AES_encrypt(tmp, out, key); ++ memcpy(ivec, out, AES_BLOCK_SIZE); ++ len -= AES_BLOCK_SIZE; ++ in += AES_BLOCK_SIZE; ++ out += AES_BLOCK_SIZE; ++ } ++ ++ if(len) ++ { ++ for(n=0; n < len; ++n) ++ tmp[n] = in[n] ^ ivec[n]; ++ ++ for(n=len; n < AES_BLOCK_SIZE; ++n) ++ tmp[n] = ivec[n]; ++ ++ AES_encrypt(tmp, tmp, key); ++ memcpy(out, tmp, AES_BLOCK_SIZE); ++ memcpy(ivec, tmp, AES_BLOCK_SIZE); ++ } ++ } ++ else ++ { ++ while(len >= AES_BLOCK_SIZE) ++ { ++ memcpy(tmp, in, AES_BLOCK_SIZE); ++ AES_decrypt(in, out, key); ++ ++ for(n=0; n < AES_BLOCK_SIZE; ++n) ++ out[n] ^= ivec[n]; ++ ++ memcpy(ivec, tmp, AES_BLOCK_SIZE); ++ len -= AES_BLOCK_SIZE; ++ in += AES_BLOCK_SIZE; ++ out += AES_BLOCK_SIZE; ++ } ++ ++ if(len) ++ { ++ memcpy(tmp, in, AES_BLOCK_SIZE); ++ AES_decrypt(tmp, tmp, key); ++ ++ for(n=0; n < len; ++n) ++ out[n] ^= ivec[n]; ++ ++ memcpy(ivec, tmp, AES_BLOCK_SIZE); ++ } ++ } ++} + #endif +diff -ruNp trunk.patches/cscrypt/aes.h trunk/cscrypt/aes.h +--- trunk.patches/cscrypt/aes.h 2018-04-03 02:44:10.098268979 +0300 ++++ trunk/cscrypt/aes.h 2018-04-03 03:20:07.654045339 +0300 +@@ -42,6 +42,9 @@ void AES_encrypt(const unsigned char *in + void AES_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); + ++void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, ++ const unsigned long length, const AES_KEY *key, ++ unsigned char *ivec, const int enc); + #endif /* !HEADER_AES_H */ + + #endif +diff -ruNp trunk.patches/cscrypt/md5.c trunk/cscrypt/md5.c +--- trunk.patches/cscrypt/md5.c 2018-04-03 02:44:10.090268912 +0300 ++++ trunk/cscrypt/md5.c 2018-04-03 03:20:07.654045339 +0300 +@@ -25,13 +25,6 @@ + + #if !defined(WITH_SSL) && !defined(WITH_LIBCRYPTO) + +-typedef struct MD5Context +-{ +- uint32_t buf[4]; +- uint32_t bits[2]; +- uint32_t in[16]; +-} MD5_CTX; +- + #ifdef __i386__ + #define byteReverse(a, b) + #else +@@ -155,7 +148,7 @@ static void MD5_Transform(uint32_t buf[4 + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +-static void MD5_Init(MD5_CTX *ctx) ++void MD5_Init(MD5_CTX *ctx) + { + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; +@@ -170,7 +163,7 @@ static void MD5_Init(MD5_CTX *ctx) + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +-static void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, unsigned int len) ++void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, unsigned int len) + { + uint32_t t; + +@@ -219,7 +212,7 @@ static void MD5_Update(MD5_CTX *ctx, con + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +-static void MD5_Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx) ++void MD5_Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx) + { + unsigned count; + unsigned char *p; +diff -ruNp trunk.patches/cscrypt/md5.h trunk/cscrypt/md5.h +--- trunk.patches/cscrypt/md5.h 2018-04-03 02:44:10.102269013 +0300 ++++ trunk/cscrypt/md5.h 2018-04-03 03:20:07.654045339 +0300 +@@ -7,8 +7,16 @@ + #define MD5_DIGEST_LENGTH 16 + + unsigned char *MD5(const unsigned char *input, unsigned long len, unsigned char *output_hash); +-#endif + +-char *__md5_crypt(const char *text_pass, const char *salt, char *crypted_passwd); ++typedef struct MD5Context { ++ uint32_t buf[4]; ++ uint32_t bits[2]; ++ uint32_t in[16]; ++} MD5_CTX; + ++void MD5_Init(MD5_CTX *ctx); ++void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, unsigned int len); ++void MD5_Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx); ++#endif ++char *__md5_crypt(const char *text_pass, const char *salt, char *crypted_passwd); + #endif +diff -ruNp trunk.patches/csctapi/cardreaders.h trunk/csctapi/cardreaders.h +--- trunk.patches/csctapi/cardreaders.h 2018-04-03 02:44:09.226261666 +0300 ++++ trunk/csctapi/cardreaders.h 2018-04-03 03:20:07.654045339 +0300 +@@ -14,5 +14,6 @@ extern const struct s_cardreader cardrea + extern const struct s_cardreader cardreader_stapi; + extern const struct s_cardreader cardreader_stinger; + extern const struct s_cardreader cardreader_drecas; ++extern const struct s_cardreader cardreader_emu; + + #endif +diff -ruNp trunk.patches/ffdecsa/CMakeLists.txt trunk/ffdecsa/CMakeLists.txt +--- trunk.patches/ffdecsa/CMakeLists.txt 1970-01-01 03:00:00.000000000 +0300 ++++ trunk/ffdecsa/CMakeLists.txt 2018-04-03 03:20:07.654045339 +0300 +@@ -0,0 +1,8 @@ ++project (ffdecsa) ++ ++file (GLOB ffdecsa_srcs "ffdecsa.c") ++file (GLOB ffdecsa_hdrs "*.h") ++ ++set (lib_name "ffdecsa") ++ ++add_library (${lib_name} STATIC ${ffdecsa_srcs} ${ffdecsa_hdrs}) +diff -ruNp trunk.patches/ffdecsa/COPYING trunk/ffdecsa/COPYING +--- trunk.patches/ffdecsa/COPYING 1970-01-01 03:00:00.000000000 +0300 ++++ trunk/ffdecsa/COPYING 2018-04-03 03:20:07.658045369 +0300 +@@ -0,0 +1,339 @@ ++ GNU GENERAL PUBLIC LICENSE ++ Version 2, June 1991 ++ ++ Copyright (C) 1989, 1991 Free Software Foundation, Inc. ++ 675 Mass Ave, Cambridge, MA 02139, USA ++ Everyone is permitted to copy and distribute verbatim copies ++ of this license document, but changing it is not allowed. ++ ++ Preamble ++ ++ The licenses for most software are designed to take away your ++freedom to share and change it. By contrast, the GNU General Public ++License is intended to guarantee your freedom to share and change free ++software--to make sure the software is free for all its users. This ++General Public License applies to most of the Free Software ++Foundation's software and to any other program whose authors commit to ++using it. (Some other Free Software Foundation software is covered by ++the GNU Library General Public License instead.) You can apply it to ++your programs, too. ++ ++ When we speak of free software, we are referring to freedom, not ++price. Our General Public Licenses are designed to make sure that you ++have the freedom to distribute copies of free software (and charge for ++this service if you wish), that you receive source code or can get it ++if you want it, that you can change the software or use pieces of it ++in new free programs; and that you know you can do these things. ++ ++ To protect your rights, we need to make restrictions that forbid ++anyone to deny you these rights or to ask you to surrender the rights. ++These restrictions translate to certain responsibilities for you if you ++distribute copies of the software, or if you modify it. ++ ++ For example, if you distribute copies of such a program, whether ++gratis or for a fee, you must give the recipients all the rights that ++you have. You must make sure that they, too, receive or can get the ++source code. And you must show them these terms so they know their ++rights. ++ ++ We protect your rights with two steps: (1) copyright the software, and ++(2) offer you this license which gives you legal permission to copy, ++distribute and/or modify the software. ++ ++ Also, for each author's protection and ours, we want to make certain ++that everyone understands that there is no warranty for this free ++software. If the software is modified by someone else and passed on, we ++want its recipients to know that what they have is not the original, so ++that any problems introduced by others will not reflect on the original ++authors' reputations. ++ ++ Finally, any free program is threatened constantly by software ++patents. We wish to avoid the danger that redistributors of a free ++program will individually obtain patent licenses, in effect making the ++program proprietary. To prevent this, we have made it clear that any ++patent must be licensed for everyone's free use or not licensed at all. ++ ++ The precise terms and conditions for copying, distribution and ++modification follow. ++ ++ GNU GENERAL PUBLIC LICENSE ++ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ++ ++ 0. This License applies to any program or other work which contains ++a notice placed by the copyright holder saying it may be distributed ++under the terms of this General Public License. The "Program", below, ++refers to any such program or work, and a "work based on the Program" ++means either the Program or any derivative work under copyright law: ++that is to say, a work containing the Program or a portion of it, ++either verbatim or with modifications and/or translated into another ++language. (Hereinafter, translation is included without limitation in ++the term "modification".) Each licensee is addressed as "you". ++ ++Activities other than copying, distribution and modification are not ++covered by this License; they are outside its scope. The act of ++running the Program is not restricted, and the output from the Program ++is covered only if its contents constitute a work based on the ++Program (independent of having been made by running the Program). ++Whether that is true depends on what the Program does. ++ ++ 1. You may copy and distribute verbatim copies of the Program's ++source code as you receive it, in any medium, provided that you ++conspicuously and appropriately publish on each copy an appropriate ++copyright notice and disclaimer of warranty; keep intact all the ++notices that refer to this License and to the absence of any warranty; ++and give any other recipients of the Program a copy of this License ++along with the Program. ++ ++You may charge a fee for the physical act of transferring a copy, and ++you may at your option offer warranty protection in exchange for a fee. ++ ++ 2. You may modify your copy or copies of the Program or any portion ++of it, thus forming a work based on the Program, and copy and ++distribute such modifications or work under the terms of Section 1 ++above, provided that you also meet all of these conditions: ++ ++ a) You must cause the modified files to carry prominent notices ++ stating that you changed the files and the date of any change. ++ ++ b) You must cause any work that you distribute or publish, that in ++ whole or in part contains or is derived from the Program or any ++ part thereof, to be licensed as a whole at no charge to all third ++ parties under the terms of this License. ++ ++ c) If the modified program normally reads commands interactively ++ when run, you must cause it, when started running for such ++ interactive use in the most ordinary way, to print or display an ++ announcement including an appropriate copyright notice and a ++ notice that there is no warranty (or else, saying that you provide ++ a warranty) and that users may redistribute the program under ++ these conditions, and telling the user how to view a copy of this ++ License. (Exception: if the Program itself is interactive but ++ does not normally print such an announcement, your work based on ++ the Program is not required to print an announcement.) ++ ++These requirements apply to the modified work as a whole. If ++identifiable sections of that work are not derived from the Program, ++and can be reasonably considered independent and separate works in ++themselves, then this License, and its terms, do not apply to those ++sections when you distribute them as separate works. But when you ++distribute the same sections as part of a whole which is a work based ++on the Program, the distribution of the whole must be on the terms of ++this License, whose permissions for other licensees extend to the ++entire whole, and thus to each and every part regardless of who wrote it. ++ ++Thus, it is not the intent of this section to claim rights or contest ++your rights to work written entirely by you; rather, the intent is to ++exercise the right to control the distribution of derivative or ++collective works based on the Program. ++ ++In addition, mere aggregation of another work not based on the Program ++with the Program (or with a work based on the Program) on a volume of ++a storage or distribution medium does not bring the other work under ++the scope of this License. ++ ++ 3. You may copy and distribute the Program (or a work based on it, ++under Section 2) in object code or executable form under the terms of ++Sections 1 and 2 above provided that you also do one of the following: ++ ++ a) Accompany it with the complete corresponding machine-readable ++ source code, which must be distributed under the terms of Sections ++ 1 and 2 above on a medium customarily used for software interchange; or, ++ ++ b) Accompany it with a written offer, valid for at least three ++ years, to give any third party, for a charge no more than your ++ cost of physically performing source distribution, a complete ++ machine-readable copy of the corresponding source code, to be ++ distributed under the terms of Sections 1 and 2 above on a medium ++ customarily used for software interchange; or, ++ ++ c) Accompany it with the information you received as to the offer ++ to distribute corresponding source code. (This alternative is ++ allowed only for noncommercial distribution and only if you ++ received the program in object code or executable form with such ++ an offer, in accord with Subsection b above.) ++ ++The source code for a work means the preferred form of the work for ++making modifications to it. For an executable work, complete source ++code means all the source code for all modules it contains, plus any ++associated interface definition files, plus the scripts used to ++control compilation and installation of the executable. However, as a ++special exception, the source code distributed need not include ++anything that is normally distributed (in either source or binary ++form) with the major components (compiler, kernel, and so on) of the ++operating system on which the executable runs, unless that component ++itself accompanies the executable. ++ ++If distribution of executable or object code is made by offering ++access to copy from a designated place, then offering equivalent ++access to copy the source code from the same place counts as ++distribution of the source code, even though third parties are not ++compelled to copy the source along with the object code. ++ ++ 4. You may not copy, modify, sublicense, or distribute the Program ++except as expressly provided under this License. Any attempt ++otherwise to copy, modify, sublicense or distribute the Program is ++void, and will automatically terminate your rights under this License. ++However, parties who have received copies, or rights, from you under ++this License will not have their licenses terminated so long as such ++parties remain in full compliance. ++ ++ 5. You are not required to accept this License, since you have not ++signed it. However, nothing else grants you permission to modify or ++distribute the Program or its derivative works. These actions are ++prohibited by law if you do not accept this License. Therefore, by ++modifying or distributing the Program (or any work based on the ++Program), you indicate your acceptance of this License to do so, and ++all its terms and conditions for copying, distributing or modifying ++the Program or works based on it. ++ ++ 6. Each time you redistribute the Program (or any work based on the ++Program), the recipient automatically receives a license from the ++original licensor to copy, distribute or modify the Program subject to ++these terms and conditions. You may not impose any further ++restrictions on the recipients' exercise of the rights granted herein. ++You are not responsible for enforcing compliance by third parties to ++this License. ++ ++ 7. If, as a consequence of a court judgment or allegation of patent ++infringement or for any other reason (not limited to patent issues), ++conditions are imposed on you (whether by court order, agreement or ++otherwise) that contradict the conditions of this License, they do not ++excuse you from the conditions of this License. If you cannot ++distribute so as to satisfy simultaneously your obligations under this ++License and any other pertinent obligations, then as a consequence you ++may not distribute the Program at all. For example, if a patent ++license would not permit royalty-free redistribution of the Program by ++all those who receive copies directly or indirectly through you, then ++the only way you could satisfy both it and this License would be to ++refrain entirely from distribution of the Program. ++ ++If any portion of this section is held invalid or unenforceable under ++any particular circumstance, the balance of the section is intended to ++apply and the section as a whole is intended to apply in other ++circumstances. ++ ++It is not the purpose of this section to induce you to infringe any ++patents or other property right claims or to contest validity of any ++such claims; this section has the sole purpose of protecting the ++integrity of the free software distribution system, which is ++implemented by public license practices. Many people have made ++generous contributions to the wide range of software distributed ++through that system in reliance on consistent application of that ++system; it is up to the author/donor to decide if he or she is willing ++to distribute software through any other system and a licensee cannot ++impose that choice. ++ ++This section is intended to make thoroughly clear what is believed to ++be a consequence of the rest of this License. ++ ++ 8. If the distribution and/or use of the Program is restricted in ++certain countries either by patents or by copyrighted interfaces, the ++original copyright holder who places the Program under this License ++may add an explicit geographical distribution limitation excluding ++those countries, so that distribution is permitted only in or among ++countries not thus excluded. In such case, this License incorporates ++the limitation as if written in the body of this License. ++ ++ 9. The Free Software Foundation may publish revised and/or new versions ++of the General Public License from time to time. Such new versions will ++be similar in spirit to the present version, but may differ in detail to ++address new problems or concerns. ++ ++Each version is given a distinguishing version number. If the Program ++specifies a version number of this License which applies to it and "any ++later version", you have the option of following the terms and conditions ++either of that version or of any later version published by the Free ++Software Foundation. If the Program does not specify a version number of ++this License, you may choose any version ever published by the Free Software ++Foundation. ++ ++ 10. If you wish to incorporate parts of the Program into other free ++programs whose distribution conditions are different, write to the author ++to ask for permission. For software which is copyrighted by the Free ++Software Foundation, write to the Free Software Foundation; we sometimes ++make exceptions for this. Our decision will be guided by the two goals ++of preserving the free status of all derivatives of our free software and ++of promoting the sharing and reuse of software generally. ++ ++ NO WARRANTY ++ ++ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY ++FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN ++OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES ++PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED ++OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS ++TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE ++PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, ++REPAIR OR CORRECTION. ++ ++ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING ++WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR ++REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, ++INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING ++OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED ++TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY ++YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER ++PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE ++POSSIBILITY OF SUCH DAMAGES. ++ ++ END OF TERMS AND CONDITIONS ++ ++ Appendix: How to Apply These Terms to Your New Programs ++ ++ If you develop a new program, and you want it to be of the greatest ++possible use to the public, the best way to achieve this is to make it ++free software which everyone can redistribute and change under these terms. ++ ++ To do so, attach the following notices to the program. It is safest ++to attach them to the start of each source file to most effectively ++convey the exclusion of warranty; and each file should have at least ++the "copyright" line and a pointer to where the full notice is found. ++ ++ ++ Copyright (C) 19yy ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ ++Also add information on how to contact you by electronic and paper mail. ++ ++If the program is interactive, make it output a short notice like this ++when it starts in an interactive mode: ++ ++ Gnomovision version 69, Copyright (C) 19yy name of author ++ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. ++ This is free software, and you are welcome to redistribute it ++ under certain conditions; type `show c' for details. ++ ++The hypothetical commands `show w' and `show c' should show the appropriate ++parts of the General Public License. Of course, the commands you use may ++be called something other than `show w' and `show c'; they could even be ++mouse-clicks or menu items--whatever suits your program. ++ ++You should also get your employer (if you work as a programmer) or your ++school, if any, to sign a "copyright disclaimer" for the program, if ++necessary. Here is a sample; alter the names: ++ ++ Yoyodyne, Inc., hereby disclaims all copyright interest in the program ++ `Gnomovision' (which makes passes at compilers) written by James Hacker. ++ ++ , 1 April 1989 ++ Ty Coon, President of Vice ++ ++This General Public License does not permit incorporating your program into ++proprietary programs. If your program is a subroutine library, you may ++consider it more useful to permit linking proprietary applications with the ++library. If this is what you want to do, use the GNU Library General ++Public License instead of this License. +diff -ruNp trunk.patches/ffdecsa/ffdecsa.c trunk/ffdecsa/ffdecsa.c +--- trunk.patches/ffdecsa/ffdecsa.c 1970-01-01 03:00:00.000000000 +0300 ++++ trunk/ffdecsa/ffdecsa.c 2018-04-03 03:20:07.658045369 +0300 +@@ -0,0 +1,926 @@ ++/* FFdecsa -- fast decsa algorithm ++ * ++ * Copyright (C) 2003-2004 fatih89r ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++ ++#include "ffdecsa.h" ++ ++#ifndef NULL ++#define NULL 0 ++#endif ++ ++//#define DEBUG ++#ifdef DEBUG ++#define DBG(a) a ++#else ++#define DBG(a) ++#endif ++ ++//// parallelization stuff, large speed differences are possible ++// possible choices ++#define PARALLEL_32_4CHAR 320 ++#define PARALLEL_32_4CHARA 321 ++#define PARALLEL_32_INT 322 ++#define PARALLEL_64_8CHAR 640 ++#define PARALLEL_64_8CHARA 641 ++#define PARALLEL_64_2INT 642 ++#define PARALLEL_64_LONG 643 ++#define PARALLEL_64_MMX 644 ++#define PARALLEL_128_16CHAR 1280 ++#define PARALLEL_128_16CHARA 1281 ++#define PARALLEL_128_4INT 1282 ++#define PARALLEL_128_2LONG 1283 ++#define PARALLEL_128_2MMX 1284 ++#define PARALLEL_128_SSE 1285 ++#define PARALLEL_128_SSE2 1286 ++ ++//////// our choice //////////////// our choice //////////////// our choice //////////////// our choice //////// ++#ifndef PARALLEL_MODE ++ ++#if defined(__x86_64__) || defined(_M_X64) ++#define PARALLEL_MODE PARALLEL_128_SSE2 ++ ++#elif defined(__mips__) || defined(__mips) || defined(__MIPS__) ++#define PARALLEL_MODE PARALLEL_64_LONG ++ ++#elif defined(__sh__) || defined(__SH4__) ++#define PARALLEL_MODE PARALLEL_32_INT ++#define COPY_UNALIGNED_PKT ++#define MEMALIGN_VAL 4 ++ ++#else ++#define PARALLEL_MODE PARALLEL_32_INT ++#endif ++ ++#endif ++//////// our choice //////////////// our choice //////////////// our choice //////////////// our choice //////// ++ ++#include "parallel_generic.h" ++//// conditionals ++#if PARALLEL_MODE==PARALLEL_32_4CHAR ++#include "parallel_032_4char.h" ++#elif PARALLEL_MODE==PARALLEL_32_4CHARA ++#include "parallel_032_4charA.h" ++#elif PARALLEL_MODE==PARALLEL_32_INT ++#include "parallel_032_int.h" ++#elif PARALLEL_MODE==PARALLEL_64_8CHAR ++#include "parallel_064_8char.h" ++#elif PARALLEL_MODE==PARALLEL_64_8CHARA ++#include "parallel_064_8charA.h" ++#elif PARALLEL_MODE==PARALLEL_64_2INT ++#include "parallel_064_2int.h" ++#elif PARALLEL_MODE==PARALLEL_64_LONG ++#include "parallel_064_long.h" ++#elif PARALLEL_MODE==PARALLEL_64_MMX ++#include "parallel_064_mmx.h" ++#elif PARALLEL_MODE==PARALLEL_128_16CHAR ++#include "parallel_128_16char.h" ++#elif PARALLEL_MODE==PARALLEL_128_16CHARA ++#include "parallel_128_16charA.h" ++#elif PARALLEL_MODE==PARALLEL_128_4INT ++#include "parallel_128_4int.h" ++#elif PARALLEL_MODE==PARALLEL_128_2LONG ++#include "parallel_128_2long.h" ++#elif PARALLEL_MODE==PARALLEL_128_2MMX ++#include "parallel_128_2mmx.h" ++#elif PARALLEL_MODE==PARALLEL_128_SSE ++#include "parallel_128_sse.h" ++#elif PARALLEL_MODE==PARALLEL_128_SSE2 ++#include "parallel_128_sse2.h" ++#else ++#error "unknown/undefined parallel mode" ++#endif ++ ++// stuff depending on conditionals ++ ++#define BYTES_PER_GROUP (GROUP_PARALLELISM/8) ++#define BYPG BYTES_PER_GROUP ++#define BITS_PER_GROUP GROUP_PARALLELISM ++#define BIPG BITS_PER_GROUP ++ ++// platform specific ++ ++#ifdef __arm__ ++#if !defined(MEMALIGN_VAL) || MEMALIGN_VAL<4 ++#undef MEMALIGN_VAL ++#define MEMALIGN_VAL 4 ++#endif ++#define COPY_UNALIGNED_PKT ++#endif ++ ++// ++ ++#ifndef MALLOC ++#define MALLOC(X) malloc(X) ++#endif ++#ifndef FREE ++#define FREE(X) free(X) ++#endif ++#ifdef MEMALIGN_VAL ++#define MEMALIGN __attribute__((aligned(MEMALIGN_VAL))) ++#else ++#define MEMALIGN ++#endif ++ ++//// debug tool ++ ++#ifdef DEBUG ++static void dump_mem(const char *string, const unsigned char *p, int len, int linelen){ ++ int i; ++ for(i=0;i>4)&0xf; ++ iA[1]=(ck[0] )&0xf; ++ iA[2]=(ck[1]>>4)&0xf; ++ iA[3]=(ck[1] )&0xf; ++ iA[4]=(ck[2]>>4)&0xf; ++ iA[5]=(ck[2] )&0xf; ++ iA[6]=(ck[3]>>4)&0xf; ++ iA[7]=(ck[3] )&0xf; ++ iB[0]=(ck[4]>>4)&0xf; ++ iB[1]=(ck[4] )&0xf; ++ iB[2]=(ck[5]>>4)&0xf; ++ iB[3]=(ck[5] )&0xf; ++ iB[4]=(ck[6]>>4)&0xf; ++ iB[5]=(ck[6] )&0xf; ++ iB[6]=(ck[7]>>4)&0xf; ++ iB[7]=(ck[7] )&0xf; ++} ++ ++//----- stream main function ++ ++#define STREAM_INIT ++#include "stream.c" ++#undef STREAM_INIT ++ ++#define STREAM_NORMAL ++#include "stream.c" ++#undef STREAM_NORMAL ++ ++ ++//-----block decypher ++ ++//-----key schedule for block decypher ++ ++static void key_schedule_block( ++ unsigned char *ck, // [In] ck[0]-ck[7] 8 bytes | Key. ++ unsigned char *kk) // [Out] kk[0]-kk[55] 56 bytes | Key schedule. ++{ ++ static const unsigned char key_perm[0x40] = { ++ 0x12,0x24,0x09,0x07,0x2A,0x31,0x1D,0x15, 0x1C,0x36,0x3E,0x32,0x13,0x21,0x3B,0x40, ++ 0x18,0x14,0x25,0x27,0x02,0x35,0x1B,0x01, 0x22,0x04,0x0D,0x0E,0x39,0x28,0x1A,0x29, ++ 0x33,0x23,0x34,0x0C,0x16,0x30,0x1E,0x3A, 0x2D,0x1F,0x08,0x19,0x17,0x2F,0x3D,0x11, ++ 0x3C,0x05,0x38,0x2B,0x0B,0x06,0x0A,0x2C, 0x20,0x3F,0x2E,0x0F,0x03,0x26,0x10,0x37, ++ }; ++ ++ int i,j,k; ++ int bit[64]; ++ int newbit[64]; ++ int kb[7][8]; ++ ++ // 56 steps ++ // 56 key bytes kk(55)..kk(0) by key schedule from ck ++ ++ // kb(6,0) .. kb(6,7) = ck(0) .. ck(7) ++ kb[6][0] = ck[0]; ++ kb[6][1] = ck[1]; ++ kb[6][2] = ck[2]; ++ kb[6][3] = ck[3]; ++ kb[6][4] = ck[4]; ++ kb[6][5] = ck[5]; ++ kb[6][6] = ck[6]; ++ kb[6][7] = ck[7]; ++ ++ // calculate kb[5] .. kb[0] ++ for(i=5; i>=0; i--){ ++ // 64 bit perm on kb ++ for(j=0; j<8; j++){ ++ for(k=0; k<8; k++){ ++ bit[j*8+k] = (kb[i+1][j] >> (7-k)) & 1; ++ newbit[key_perm[j*8+k]-1] = bit[j*8+k]; ++ } ++ } ++ for(j=0; j<8; j++){ ++ kb[i][j] = 0; ++ for(k=0; k<8; k++){ ++ kb[i][j] |= newbit[j*8+k] << (7-k); ++ } ++ } ++ } ++ ++ // xor to give kk ++ for(i=0; i<7; i++){ ++ for(j=0; j<8; j++){ ++ kk[i*8+j] = kb[i][j] ^ i; ++ } ++ } ++ ++} ++ ++//-----block utils ++ ++static inline __attribute__((always_inline)) void trasp_N_8 (unsigned char *in,unsigned char* out,int count){ ++ int *ri=(int *)in; ++ int *ibi=(int *)out; ++ int j,i,k,g; ++ // copy and first step ++ for(g=0;g>16) | (b&0xffff0000) ; ++ } ++ } ++ } ++//dump_mem("NE2 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM); ++// now 01010101 ++ for(j=0;j<8;j+=2){ ++ for(i=0;i<1;i++){ ++ for(k=0;k>8) | (b&0xff00ff00); ++ } ++ } ++ } ++//dump_mem("NE3 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM); ++// now 00000000 ++} ++ ++static inline __attribute__((always_inline)) void trasp_8_N (unsigned char *in,unsigned char* out,int count){ ++ int *ri=(int *)in; ++ int *bdi=(int *)out; ++ int j,i,k,g; ++#define INTS_PER_ROW (GROUP_PARALLELISM/8*2) ++//dump_mem("NE1 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM); ++// now 00000000 ++ for(j=0;j<8;j+=2){ ++ for(i=0;i<1;i++){ ++ for(k=0;k>8) | (b&0xff00ff00); ++ } ++ } ++ } ++//dump_mem("NE2 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM); ++// now 01010101 ++ for(j=0;j<8;j+=4){ ++ for(i=0;i<2;i++){ ++ for(k=0;k>16) | (b&0xffff0000) ; ++ } ++ } ++ } ++//dump_mem("NE3 r[roff]",&r[roff],GROUP_PARALLELISM*8,GROUP_PARALLELISM); ++// now 01230123 ++ for(g=0;g=0;i--){ ++ { ++ MEMALIGN batch tkkmulti=kkmulti[i]; ++ batch *si=(batch *)sbox_in; ++ batch *r6_N=(batch *)(r+roff+GROUP_PARALLELISM*6); ++ for(g=0;gck,pk,8); ++// precalculations for stream ++ key_schedule_stream(key->ck,key->iA,key->iB); ++ for(by=0;by<8;by++){ ++ for(bi=0;bi<8;bi++){ ++ key->ck_g[by][bi]=(key->ck[by]&(1<iA_g[by][bi]=(key->iA[by]&(1<iB_g[by][bi]=(key->iB[by]&(1<ck,key->kk); ++ for(i=0;i<56;i++){ ++ for(j=0;jkkmulti[i])+j)=key->kk[i]; ++ } ++ } ++} ++ ++void set_control_words(void *keys, const unsigned char *ev, const unsigned char *od){ ++ schedule_key(&((struct csa_keys_t *)keys)->even,ev); ++ schedule_key(&((struct csa_keys_t *)keys)->odd,od); ++} ++ ++void set_even_control_word(void *keys, const unsigned char *pk){ ++ schedule_key(&((struct csa_keys_t *)keys)->even,pk); ++} ++ ++void set_odd_control_word(void *keys, const unsigned char *pk){ ++ schedule_key(&((struct csa_keys_t *)keys)->odd,pk); ++} ++ ++//-----get control words ++ ++void get_control_words(void *keys, unsigned char *even, unsigned char *odd){ ++ memcpy(even,&((struct csa_keys_t *)keys)->even.ck,8); ++ memcpy(odd,&((struct csa_keys_t *)keys)->odd.ck,8); ++} ++ ++//----- decrypt ++ ++int decrypt_packets(void *keys, unsigned char **cluster){ ++ // statistics, currently unused ++ int stat_no_scramble=0; ++ int stat_reserved=0; ++ int stat_decrypted[2]={0,0}; ++ int stat_decrypted_mini=0; ++ unsigned char **clst; ++ unsigned char **clst2; ++ int grouped; ++ int group_ev_od; ++ int advanced; ++ int can_advance; ++ unsigned char *g_pkt[GROUP_PARALLELISM]; ++ int g_len[GROUP_PARALLELISM]; ++ int g_offset[GROUP_PARALLELISM]; ++ int g_n[GROUP_PARALLELISM]; ++ int g_residue[GROUP_PARALLELISM]; ++ unsigned char *pkt; ++ int xc0,ev_od,len,offset,n,residue; ++ struct csa_key_t* k; ++ int i,j,iter,g; ++ int t23,tsmall; ++ int alive[24]; ++//icc craziness int pad1=0; //////////align! FIXME ++ unsigned char *encp[GROUP_PARALLELISM]; ++ MEMALIGN unsigned char stream_in[GROUP_PARALLELISM*8]; ++ MEMALIGN unsigned char stream_out[GROUP_PARALLELISM*8]; ++ MEMALIGN unsigned char ib[GROUP_PARALLELISM*8]; ++ MEMALIGN unsigned char block_out[GROUP_PARALLELISM*8]; ++#ifdef COPY_UNALIGNED_PKT ++ unsigned char *unaligned[GROUP_PARALLELISM]; ++ MEMALIGN unsigned char alignedBuff[GROUP_PARALLELISM][188]; ++#endif ++ struct stream_regs regs; ++ ++//icc craziness i=(int)&pad1;//////////align!!! FIXME ++ ++ // build a list of packets to be processed ++ clst=cluster; ++ grouped=0; ++ advanced=0; ++ can_advance=1; ++ group_ev_od=-1; // silence incorrect compiler warning ++ pkt=*clst; ++ do{ // find a new packet ++ if(grouped==GROUP_PARALLELISM){ ++ // full ++ break; ++ } ++ if(pkt==NULL){ ++ // no more ranges ++ break; ++ } ++ if(pkt>=*(clst+1)){ ++ // out of this range, try next ++ clst++;clst++; ++ pkt=*clst; ++ continue; ++ } ++ ++ do{ // handle this packet ++ xc0=pkt[3]&0xc0; ++ DBG(fprintf(stderr," exam pkt=%p, xc0=%02x, can_adv=%i\n",pkt,xc0,can_advance)); ++ if(xc0==0x00){ ++ DBG(fprintf(stderr,"skip clear pkt %p (can_advance is %i)\n",pkt,can_advance)); ++ advanced+=can_advance; ++ stat_no_scramble++; ++ break; ++ } ++ if(xc0==0x40){ ++ DBG(fprintf(stderr,"skip reserved pkt %p (can_advance is %i)\n",pkt,can_advance)); ++ advanced+=can_advance; ++ stat_reserved++; ++ break; ++ } ++ if(xc0==0x80||xc0==0xc0){ // encrypted ++ ev_od=(xc0&0x40)>>6; // 0 even, 1 odd ++ if(grouped==0) group_ev_od=ev_od; // this group will be all even (or odd) ++ if(group_ev_od==ev_od){ // could be added to group ++ pkt[3]&=0x3f; // consider it decrypted now ++ if(pkt[3]&0x20){ // incomplete packet ++ offset=4+pkt[4]+1; ++ len=188-offset; ++ n=len>>3; ++ residue=len-(n<<3); ++ if(n==0){ // decrypted==encrypted! ++ DBG(fprintf(stderr,"DECRYPTED MINI! (can_advance is %i)\n",can_advance)); ++ advanced+=can_advance; ++ stat_decrypted_mini++; ++ break; // this doesn't need more processing ++ } ++ }else{ ++ len=184; ++ offset=4; ++ n=23; ++ residue=0; ++ } ++ g_pkt[grouped]=pkt; ++ g_len[grouped]=len; ++ g_offset[grouped]=offset; ++ g_n[grouped]=n; ++ g_residue[grouped]=residue; ++ DBG(fprintf(stderr,"%2i: eo=%i pkt=%p len=%03i n=%2i residue=%i\n",grouped,ev_od,pkt,len,n,residue)); ++ grouped++; ++ advanced+=can_advance; ++ stat_decrypted[ev_od]++; ++ } ++ else{ ++ can_advance=0; ++ DBG(fprintf(stderr,"skip pkt %p and can_advance set to 0\n",pkt)); ++ break; // skip and go on ++ } ++ } ++ } while(0); ++ ++ if(can_advance){ ++ // move range start forward ++ *clst+=188; ++ } ++ // next packet, if there is one ++ pkt+=188; ++ } while(1); ++ DBG(fprintf(stderr,"-- result: grouped %i pkts, advanced %i pkts\n",grouped,advanced)); ++ ++ // delete empty ranges and compact list ++ clst2=cluster; ++ for(clst=cluster;*clst!=NULL;clst+=2){ ++ // if not empty ++ if(*clst<*(clst+1)){ ++ // it will remain ++ *clst2=*clst; ++ *(clst2+1)=*(clst+1); ++ clst2+=2; ++ } ++ } ++ *clst2=NULL; ++ ++ if(grouped==0){ ++ // no processing needed ++ return advanced; ++ } ++ ++ // sort them, longest payload first ++ // we expect many n=23 packets and a few n<23 ++ DBG(fprintf(stderr,"PRESORTING\n")); ++ for(i=0;i=0;tsmall--){ ++ if(g_n[tsmall]==23) break; ++ } ++DBG(fprintf(stderr,"tsmall after for =%i\n",tsmall)); ++ ++ if(tsmall-t23<1) break; ++ ++DBG(fprintf(stderr,"swap t23=%i,tsmall=%i\n",t23,tsmall)); ++ ++ g_swap(t23,tsmall); ++ ++ t23++; ++ tsmall--; ++DBG(fprintf(stderr,"new t23=%i,tsmall=%i\n\n",t23,tsmall)); ++ } ++ DBG(fprintf(stderr,"packets with n=23, t23=%i grouped=%i\n",t23,grouped)); ++ DBG(fprintf(stderr,"MIDSORTING\n")); ++ for(i=0;ig_n[i]){ ++ g_swap(i,j); ++ } ++ } ++ } ++ DBG(fprintf(stderr,"POSTSORTING\n")); ++ for(i=0;i=0;i--){ ++ alive[i]+=alive[i+1]; ++ } ++ DBG(fprintf(stderr,"ALIVE\n")); ++ for(i=0;i<=23;i++){ ++ DBG(fprintf(stderr,"alive%2i=%i\n",i,alive[i])); ++ } ++ ++ // choose key ++ if(group_ev_od==0){ ++ k=&((struct csa_keys_t *)keys)->even; ++ } ++ else{ ++ k=&((struct csa_keys_t *)keys)->odd; ++ } ++ ++ //INIT ++//#define INITIALIZE_UNUSED_INPUT ++#ifdef INITIALIZE_UNUSED_INPUT ++// unnecessary zeroing. ++// without this, we operate on uninitialized memory ++// when grouped>>>>ITER 0\n")); ++ iter=0; ++ stream_cypher_group_init(®s,k->iA_g,k->iB_g,stream_in); ++ // fill first ib ++ for(g=0;g0;iter++){ ++DBG(fprintf(stderr,">>>>>ITER %i\n",iter)); ++ // alive and just dead packets: calc block ++ block_decypher_group(k->kkmulti,ib,block_out,alive[iter-1]); ++DBG(dump_mem("BLO_ib ",block_out,8*alive[iter-1],8)); ++ // all packets (dead too): calc stream ++ stream_cypher_group_normal(®s,stream_out); ++//dump_mem("stream_out",stream_out,GROUP_PARALLELISM*8,BYPG); ++ ++ // alive packets: calc ib ++ for(g=0;g>>>>ITER 23\n")); ++ iter=23; ++ // calc block ++ block_decypher_group(k->kkmulti,ib,block_out,alive[iter-1]); ++DBG(dump_mem("23BLO_ib ",block_out,8*alive[iter-1],8)); ++ // just dead packets: write decrypted data ++ for(g=alive[iter];g=4?32-1:0))+j); ++ } ++} ++ ++typedef unsigned int batch; ++#define BYTES_PER_BATCH 4 ++#define B_FFN_ALL_29() 0x29292929 ++#define B_FFN_ALL_02() 0x02020202 ++#define B_FFN_ALL_04() 0x04040404 ++#define B_FFN_ALL_10() 0x10101010 ++#define B_FFN_ALL_40() 0x40404040 ++#define B_FFN_ALL_80() 0x80808080 ++ ++#define M_EMPTY() +diff -ruNp trunk.patches/ffdecsa/parallel_064_long.h trunk/ffdecsa/parallel_064_long.h +--- trunk.patches/ffdecsa/parallel_064_long.h 1970-01-01 03:00:00.000000000 +0300 ++++ trunk/ffdecsa/parallel_064_long.h 2018-04-03 03:20:07.658045369 +0300 +@@ -0,0 +1,39 @@ ++/* FFdecsa -- fast decsa algorithm ++ * ++ * Copyright (C) 2007 Dark Avenger ++ * 2003-2004 fatih89r ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include "parallel_std_def.h" ++ ++typedef unsigned long long group; ++#define GROUP_PARALLELISM 64 ++#define FF0() 0x0ULL ++#define FF1() 0xffffffffffffffffULL ++ ++typedef unsigned long long batch; ++#define BYTES_PER_BATCH 8 ++#define B_FFN_ALL_29() 0x2929292929292929ULL ++#define B_FFN_ALL_02() 0x0202020202020202ULL ++#define B_FFN_ALL_04() 0x0404040404040404ULL ++#define B_FFN_ALL_10() 0x1010101010101010ULL ++#define B_FFN_ALL_40() 0x4040404040404040ULL ++#define B_FFN_ALL_80() 0x8080808080808080ULL ++ ++#define M_EMPTY() ++ ++#include "fftable.h" +diff -ruNp trunk.patches/ffdecsa/parallel_128_sse2.h trunk/ffdecsa/parallel_128_sse2.h +--- trunk.patches/ffdecsa/parallel_128_sse2.h 1970-01-01 03:00:00.000000000 +0300 ++++ trunk/ffdecsa/parallel_128_sse2.h 2018-04-03 03:20:07.658045369 +0300 +@@ -0,0 +1,82 @@ ++/* FFdecsa -- fast decsa algorithm ++ * ++ * Copyright (C) 2007 Dark Avenger ++ * 2003-2004 fatih89r ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++ ++#define MEMALIGN_VAL 16 ++ ++union __u128i { ++ unsigned int u[4]; ++ __m128i v; ++}; ++ ++static const union __u128i ff0 = {{0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U}}; ++static const union __u128i ff1 = {{0xffffffffU, 0xffffffffU, 0xffffffffU, 0xffffffffU}}; ++ ++typedef __m128i group; ++#define GROUP_PARALLELISM 128 ++#define FF0() ff0.v ++#define FF1() ff1.v ++#define FFAND(a,b) _mm_and_si128((a),(b)) ++#define FFOR(a,b) _mm_or_si128((a),(b)) ++#define FFXOR(a,b) _mm_xor_si128((a),(b)) ++#define FFNOT(a) _mm_xor_si128((a),FF1()) ++#define MALLOC(X) _mm_malloc(X,16) ++#define FREE(X) _mm_free(X) ++ ++/* BATCH */ ++ ++static const union __u128i ff29 = {{0x29292929U, 0x29292929U, 0x29292929U, 0x29292929U}}; ++static const union __u128i ff02 = {{0x02020202U, 0x02020202U, 0x02020202U, 0x02020202U}}; ++static const union __u128i ff04 = {{0x04040404U, 0x04040404U, 0x04040404U, 0x04040404U}}; ++static const union __u128i ff10 = {{0x10101010U, 0x10101010U, 0x10101010U, 0x10101010U}}; ++static const union __u128i ff40 = {{0x40404040U, 0x40404040U, 0x40404040U, 0x40404040U}}; ++static const union __u128i ff80 = {{0x80808080U, 0x80808080U, 0x80808080U, 0x80808080U}}; ++ ++typedef __m128i batch; ++#define BYTES_PER_BATCH 16 ++#define B_FFN_ALL_29() ff29.v ++#define B_FFN_ALL_02() ff02.v ++#define B_FFN_ALL_04() ff04.v ++#define B_FFN_ALL_10() ff10.v ++#define B_FFN_ALL_40() ff40.v ++#define B_FFN_ALL_80() ff80.v ++ ++#define B_FFAND(a,b) FFAND(a,b) ++#define B_FFOR(a,b) FFOR(a,b) ++#define B_FFXOR(a,b) FFXOR(a,b) ++#define B_FFSH8L(a,n) _mm_slli_epi64((a),(n)) ++#define B_FFSH8R(a,n) _mm_srli_epi64((a),(n)) ++ ++#define M_EMPTY() ++ ++#undef BEST_SPAN ++#define BEST_SPAN 16 ++ ++#undef XOR_BEST_BY ++inline static void XOR_BEST_BY(unsigned char *d, unsigned char *s1, unsigned char *s2) ++{ ++ __m128i vs1 = _mm_load_si128((__m128i*)s1); ++ __m128i vs2 = _mm_load_si128((__m128i*)s2); ++ vs1 = _mm_xor_si128(vs1, vs2); ++ _mm_store_si128((__m128i*)d, vs1); ++} ++ ++#include "fftable.h" +diff -ruNp trunk.patches/ffdecsa/parallel_generic.h trunk/ffdecsa/parallel_generic.h +--- trunk.patches/ffdecsa/parallel_generic.h 1970-01-01 03:00:00.000000000 +0300 ++++ trunk/ffdecsa/parallel_generic.h 2018-04-03 03:20:07.658045369 +0300 +@@ -0,0 +1,102 @@ ++/* FFdecsa -- fast decsa algorithm ++ * ++ * Copyright (C) 2003-2004 fatih89r ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++ ++ ++#if 0 ++//// generics ++#define COPY4BY(d,s) do{ int *pd=(int *)(d), *ps=(int *)(s); \ ++ *pd = *ps; }while(0) ++#define COPY8BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \ ++ *pd = *ps; }while(0) ++#define COPY16BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \ ++ *pd = *ps; \ ++ *(pd+1) = *(ps+1); }while(0) ++#define COPY32BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \ ++ *pd = *ps; \ ++ *(pd+1) = *(ps+1) \ ++ *(pd+2) = *(ps+2) \ ++ *(pd+3) = *(ps+3); }while(0) ++#define XOR4BY(d,s1,s2) do{ int *pd=(int *)(d), *ps1=(int *)(s1), *ps2=(int *)(s2); \ ++ *pd = *ps1 ^ *ps2; }while(0) ++#define XOR8BY(d,s1,s2) do{ long long int *pd=(long long int *)(d), *ps1=(long long int *)(s1), *ps2=(long long int *)(s2); \ ++ *pd = *ps1 ^ *ps2; }while(0) ++#define XOR16BY(d,s1,s2) do{ long long int *pd=(long long int *)(d), *ps1=(long long int *)(s1), *ps2=(long long int *)(s2); \ ++ *pd = *ps1 ^ *ps2; \ ++ *(pd+8) = *(ps1+8) ^ *(ps2+8); }while(0) ++#define XOR32BY(d,s1,s2) do{ long long int *pd=(long long int *)(d), *ps1=(long long int *)(s1), *ps2=(long long int *)(s2); \ ++ *pd = *ps1 ^ *ps2; \ ++ *(pd+1) = *(ps1+1) ^ *(ps2+1); \ ++ *(pd+2) = *(ps1+2) ^ *(ps2+2); \ ++ *(pd+3) = *(ps1+3) ^ *(ps2+3); }while(0) ++#define XOR32BV(d,s1,s2) do{ int *const pd=(int *const)(d), *ps1=(const int *const)(s1), *ps2=(const int *const)(s2); \ ++ int z; \ ++ for(z=0;z<8;z++){ \ ++ pd[z]=ps1[z]^ps2[z]; \ ++ } \ ++ }while(0) ++#define XOREQ4BY(d,s) do{ int *pd=(int *)(d), *ps=(int *)(s); \ ++ *pd ^= *ps; }while(0) ++#define XOREQ8BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \ ++ *pd ^= *ps; }while(0) ++#define XOREQ16BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \ ++ *pd ^= *ps; \ ++ *(pd+1) ^=*(ps+1); }while(0) ++#define XOREQ32BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \ ++ *pd ^= *ps; \ ++ *(pd+1) ^=*(ps+1); \ ++ *(pd+2) ^=*(ps+2); \ ++ *(pd+3) ^=*(ps+3); }while(0) ++#define XOREQ32BY4(d,s) do{ int *pd=(int *)(d), *ps=(int *)(s); \ ++ *pd ^= *ps; \ ++ *(pd+1) ^=*(ps+1); \ ++ *(pd+2) ^=*(ps+2); \ ++ *(pd+3) ^=*(ps+3); \ ++ *(pd+4) ^=*(ps+4); \ ++ *(pd+5) ^=*(ps+5); \ ++ *(pd+6) ^=*(ps+6); \ ++ *(pd+7) ^=*(ps+7); }while(0) ++#define XOREQ32BV(d,s) do{ unsigned char *pd=(unsigned char *)(d), *ps=(unsigned char *)(s); \ ++ int z; \ ++ for(z=0;z<32;z++){ \ ++ pd[z]^=ps[z]; \ ++ } \ ++ }while(0) ++ ++#else ++#define XOR_4_BY(d,s1,s2) do{ int *pd=(int *)(d), *ps1=(int *)(s1), *ps2=(int *)(s2); \ ++ *pd = *ps1 ^ *ps2; }while(0) ++#define XOR_8_BY(d,s1,s2) do{ long long int *pd=(long long int *)(d), *ps1=(long long int *)(s1), *ps2=(long long int *)(s2); \ ++ *pd = *ps1 ^ *ps2; }while(0) ++#define XOREQ_4_BY(d,s) do{ int *pd=(int *)(d), *ps=(int *)(s); \ ++ *pd ^= *ps; }while(0) ++#define XOREQ_8_BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \ ++ *pd ^= *ps; }while(0) ++#define COPY_4_BY(d,s) do{ int *pd=(int *)(d), *ps=(int *)(s); \ ++ *pd = *ps; }while(0) ++#define COPY_8_BY(d,s) do{ long long int *pd=(long long int *)(d), *ps=(long long int *)(s); \ ++ *pd = *ps; }while(0) ++ ++#define BEST_SPAN 8 ++#define XOR_BEST_BY(d,s1,s2) do{ XOR_8_BY(d,s1,s2); }while(0); ++#define XOREQ_BEST_BY(d,s) do{ XOREQ_8_BY(d,s); }while(0); ++#define COPY_BEST_BY(d,s) do{ COPY_8_BY(d,s); }while(0); ++ ++#define END_MM do{ }while(0); ++#endif +diff -ruNp trunk.patches/ffdecsa/parallel_std_def.h trunk/ffdecsa/parallel_std_def.h +--- trunk.patches/ffdecsa/parallel_std_def.h 1970-01-01 03:00:00.000000000 +0300 ++++ trunk/ffdecsa/parallel_std_def.h 2018-04-03 03:20:07.658045369 +0300 +@@ -0,0 +1,29 @@ ++/* FFdecsa -- fast decsa algorithm ++ * ++ * Copyright (C) 2003-2004 fatih89r ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#define FFXOR(a,b) ((a)^(b)) ++#define FFAND(a,b) ((a)&(b)) ++#define FFOR(a,b) ((a)|(b)) ++#define FFNOT(a) (~(a)) ++ ++#define B_FFAND(a,b) ((a)&(b)) ++#define B_FFOR(a,b) ((a)|(b)) ++#define B_FFXOR(a,b) ((a)^(b)) ++#define B_FFSH8L(a,n) ((a)<<(n)) ++#define B_FFSH8R(a,n) ((a)>>(n)) +diff -ruNp trunk.patches/ffdecsa/stream.c trunk/ffdecsa/stream.c +--- trunk.patches/ffdecsa/stream.c 1970-01-01 03:00:00.000000000 +0300 ++++ trunk/ffdecsa/stream.c 2018-04-03 03:20:07.658045369 +0300 +@@ -0,0 +1,906 @@ ++/* FFdecsa -- fast decsa algorithm ++ * ++ * Copyright (C) 2003-2004 fatih89r ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++ ++ ++// define statics only once, when STREAM_INIT ++#ifdef STREAM_INIT ++struct stream_regs { ++ group A[32+10][4]; // 32 because we will move back (virtual shift register) ++ group B[32+10][4]; // 32 because we will move back (virtual shift register) ++ group X[4]; ++ group Y[4]; ++ group Z[4]; ++ group D[4]; ++ group E[4]; ++ group F[4]; ++ group p; ++ group q; ++ group r; ++ }; ++ ++static inline void trasp64_32_88ccw(unsigned char *data){ ++/* 64 rows of 32 bits transposition (bytes transp. - 8x8 rotate counterclockwise)*/ ++#define row ((unsigned int *)data) ++ int i,j; ++ for(j=0;j<64;j+=32){ ++ unsigned int t,b; ++ for(i=0;i<16;i++){ ++ t=row[j+i]; ++ b=row[j+16+i]; ++ row[j+i] = (t&0x0000ffff) | ((b )<<16); ++ row[j+16+i]=((t )>>16) | (b&0xffff0000) ; ++ } ++ } ++ for(j=0;j<64;j+=16){ ++ unsigned int t,b; ++ for(i=0;i<8;i++){ ++ t=row[j+i]; ++ b=row[j+8+i]; ++ row[j+i] = (t&0x00ff00ff) | ((b&0x00ff00ff)<<8); ++ row[j+8+i] =((t&0xff00ff00)>>8) | (b&0xff00ff00); ++ } ++ } ++ for(j=0;j<64;j+=8){ ++ unsigned int t,b; ++ for(i=0;i<4;i++){ ++ t=row[j+i]; ++ b=row[j+4+i]; ++ row[j+i] =((t&0x0f0f0f0f)<<4) | (b&0x0f0f0f0f); ++ row[j+4+i] = (t&0xf0f0f0f0) | ((b&0xf0f0f0f0)>>4); ++ } ++ } ++ for(j=0;j<64;j+=4){ ++ unsigned int t,b; ++ for(i=0;i<2;i++){ ++ t=row[j+i]; ++ b=row[j+2+i]; ++ row[j+i] =((t&0x33333333)<<2) | (b&0x33333333); ++ row[j+2+i] = (t&0xcccccccc) | ((b&0xcccccccc)>>2); ++ } ++ } ++ for(j=0;j<64;j+=2){ ++ unsigned int t,b; ++ for(i=0;i<1;i++){ ++ t=row[j+i]; ++ b=row[j+1+i]; ++ row[j+i] =((t&0x55555555)<<1) | (b&0x55555555); ++ row[j+1+i] = (t&0xaaaaaaaa) | ((b&0xaaaaaaaa)>>1); ++ } ++ } ++#undef row ++} ++ ++static inline void trasp64_32_88cw(unsigned char *data){ ++/* 64 rows of 32 bits transposition (bytes transp. - 8x8 rotate clockwise)*/ ++#define row ((unsigned int *)data) ++ int i,j; ++ for(j=0;j<64;j+=32){ ++ unsigned int t,b; ++ for(i=0;i<16;i++){ ++ t=row[j+i]; ++ b=row[j+16+i]; ++ row[j+i] = (t&0x0000ffff) | ((b )<<16); ++ row[j+16+i]=((t )>>16) | (b&0xffff0000) ; ++ } ++ } ++ for(j=0;j<64;j+=16){ ++ unsigned int t,b; ++ for(i=0;i<8;i++){ ++ t=row[j+i]; ++ b=row[j+8+i]; ++ row[j+i] = (t&0x00ff00ff) | ((b&0x00ff00ff)<<8); ++ row[j+8+i] =((t&0xff00ff00)>>8) | (b&0xff00ff00); ++ } ++ } ++ for(j=0;j<64;j+=8){ ++ unsigned int t,b; ++ for(i=0;i<4;i++){ ++ t=row[j+i]; ++ b=row[j+4+i]; ++ row[j+i] =((t&0xf0f0f0f0)>>4) | (b&0xf0f0f0f0); ++ row[j+4+i]= (t&0x0f0f0f0f) | ((b&0x0f0f0f0f)<<4); ++ } ++ } ++ for(j=0;j<64;j+=4){ ++ unsigned int t,b; ++ for(i=0;i<2;i++){ ++ t=row[j+i]; ++ b=row[j+2+i]; ++ row[j+i] =((t&0xcccccccc)>>2) | (b&0xcccccccc); ++ row[j+2+i]= (t&0x33333333) | ((b&0x33333333)<<2); ++ } ++ } ++ for(j=0;j<64;j+=2){ ++ unsigned int t,b; ++ for(i=0;i<1;i++){ ++ t=row[j+i]; ++ b=row[j+1+i]; ++ row[j+i] =((t&0xaaaaaaaa)>>1) | (b&0xaaaaaaaa); ++ row[j+1+i]= (t&0x55555555) | ((b&0x55555555)<<1); ++ } ++ } ++#undef row ++} ++ ++//64-64---------------------------------------------------------- ++static inline void trasp64_64_88ccw(unsigned char *data){ ++/* 64 rows of 64 bits transposition (bytes transp. - 8x8 rotate counterclockwise)*/ ++#define row ((unsigned long long int *)data) ++ int i,j; ++ for(j=0;j<64;j+=64){ ++ unsigned long long int t,b; ++ for(i=0;i<32;i++){ ++ t=row[j+i]; ++ b=row[j+32+i]; ++ row[j+i] = (t&0x00000000ffffffffULL) | ((b )<<32); ++ row[j+32+i]=((t )>>32) | (b&0xffffffff00000000ULL) ; ++ } ++ } ++ for(j=0;j<64;j+=32){ ++ unsigned long long int t,b; ++ for(i=0;i<16;i++){ ++ t=row[j+i]; ++ b=row[j+16+i]; ++ row[j+i] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16); ++ row[j+16+i]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ; ++ } ++ } ++ for(j=0;j<64;j+=16){ ++ unsigned long long int t,b; ++ for(i=0;i<8;i++){ ++ t=row[j+i]; ++ b=row[j+8+i]; ++ row[j+i] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8); ++ row[j+8+i] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL); ++ } ++ } ++ for(j=0;j<64;j+=8){ ++ unsigned long long int t,b; ++ for(i=0;i<4;i++){ ++ t=row[j+i]; ++ b=row[j+4+i]; ++ row[j+i] =((t&0x0f0f0f0f0f0f0f0fULL)<<4) | (b&0x0f0f0f0f0f0f0f0fULL); ++ row[j+4+i] = (t&0xf0f0f0f0f0f0f0f0ULL) | ((b&0xf0f0f0f0f0f0f0f0ULL)>>4); ++ } ++ } ++ for(j=0;j<64;j+=4){ ++ unsigned long long int t,b; ++ for(i=0;i<2;i++){ ++ t=row[j+i]; ++ b=row[j+2+i]; ++ row[j+i] =((t&0x3333333333333333ULL)<<2) | (b&0x3333333333333333ULL); ++ row[j+2+i] = (t&0xccccccccccccccccULL) | ((b&0xccccccccccccccccULL)>>2); ++ } ++ } ++ for(j=0;j<64;j+=2){ ++ unsigned long long int t,b; ++ for(i=0;i<1;i++){ ++ t=row[j+i]; ++ b=row[j+1+i]; ++ row[j+i] =((t&0x5555555555555555ULL)<<1) | (b&0x5555555555555555ULL); ++ row[j+1+i] = (t&0xaaaaaaaaaaaaaaaaULL) | ((b&0xaaaaaaaaaaaaaaaaULL)>>1); ++ } ++ } ++#undef row ++} ++ ++static inline void trasp64_64_88cw(unsigned char *data){ ++/* 64 rows of 64 bits transposition (bytes transp. - 8x8 rotate clockwise)*/ ++#define row ((unsigned long long int *)data) ++ int i,j; ++ for(j=0;j<64;j+=64){ ++ unsigned long long int t,b; ++ for(i=0;i<32;i++){ ++ t=row[j+i]; ++ b=row[j+32+i]; ++ row[j+i] = (t&0x00000000ffffffffULL) | ((b )<<32); ++ row[j+32+i]=((t )>>32) | (b&0xffffffff00000000ULL) ; ++ } ++ } ++ for(j=0;j<64;j+=32){ ++ unsigned long long int t,b; ++ for(i=0;i<16;i++){ ++ t=row[j+i]; ++ b=row[j+16+i]; ++ row[j+i] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16); ++ row[j+16+i]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ; ++ } ++ } ++ for(j=0;j<64;j+=16){ ++ unsigned long long int t,b; ++ for(i=0;i<8;i++){ ++ t=row[j+i]; ++ b=row[j+8+i]; ++ row[j+i] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8); ++ row[j+8+i] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL); ++ } ++ } ++ for(j=0;j<64;j+=8){ ++ unsigned long long int t,b; ++ for(i=0;i<4;i++){ ++ t=row[j+i]; ++ b=row[j+4+i]; ++ row[j+i] =((t&0xf0f0f0f0f0f0f0f0ULL)>>4) | (b&0xf0f0f0f0f0f0f0f0ULL); ++ row[j+4+i] = (t&0x0f0f0f0f0f0f0f0fULL) | ((b&0x0f0f0f0f0f0f0f0fULL)<<4); ++ } ++ } ++ for(j=0;j<64;j+=4){ ++ unsigned long long int t,b; ++ for(i=0;i<2;i++){ ++ t=row[j+i]; ++ b=row[j+2+i]; ++ row[j+i] =((t&0xccccccccccccccccULL)>>2) | (b&0xccccccccccccccccULL); ++ row[j+2+i] = (t&0x3333333333333333ULL) | ((b&0x3333333333333333ULL)<<2); ++ } ++ } ++ for(j=0;j<64;j+=2){ ++ unsigned long long int t,b; ++ for(i=0;i<1;i++){ ++ t=row[j+i]; ++ b=row[j+1+i]; ++ row[j+i] =((t&0xaaaaaaaaaaaaaaaaULL)>>1) | (b&0xaaaaaaaaaaaaaaaaULL); ++ row[j+1+i] = (t&0x5555555555555555ULL) | ((b&0x5555555555555555ULL)<<1); ++ } ++ } ++#undef row ++} ++ ++//64-128---------------------------------------------------------- ++static inline void trasp64_128_88ccw(unsigned char *data){ ++/* 64 rows of 128 bits transposition (bytes transp. - 8x8 rotate counterclockwise)*/ ++#define halfrow ((unsigned long long int *)data) ++ int i,j; ++ for(j=0;j<64;j+=64){ ++ unsigned long long int t,b; ++ for(i=0;i<32;i++){ ++ t=halfrow[2*(j+i)]; ++ b=halfrow[2*(j+32+i)]; ++ halfrow[2*(j+i)] = (t&0x00000000ffffffffULL) | ((b )<<32); ++ halfrow[2*(j+32+i)]=((t )>>32) | (b&0xffffffff00000000ULL) ; ++ t=halfrow[2*(j+i)+1]; ++ b=halfrow[2*(j+32+i)+1]; ++ halfrow[2*(j+i)+1] = (t&0x00000000ffffffffULL) | ((b )<<32); ++ halfrow[2*(j+32+i)+1]=((t )>>32) | (b&0xffffffff00000000ULL) ; ++ } ++ } ++ for(j=0;j<64;j+=32){ ++ unsigned long long int t,b; ++ for(i=0;i<16;i++){ ++ t=halfrow[2*(j+i)]; ++ b=halfrow[2*(j+16+i)]; ++ halfrow[2*(j+i)] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16); ++ halfrow[2*(j+16+i)]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ; ++ t=halfrow[2*(j+i)+1]; ++ b=halfrow[2*(j+16+i)+1]; ++ halfrow[2*(j+i)+1] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16); ++ halfrow[2*(j+16+i)+1]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ; ++ } ++ } ++ for(j=0;j<64;j+=16){ ++ unsigned long long int t,b; ++ for(i=0;i<8;i++){ ++ t=halfrow[2*(j+i)]; ++ b=halfrow[2*(j+8+i)]; ++ halfrow[2*(j+i)] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8); ++ halfrow[2*(j+8+i)] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL); ++ t=halfrow[2*(j+i)+1]; ++ b=halfrow[2*(j+8+i)+1]; ++ halfrow[2*(j+i)+1] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8); ++ halfrow[2*(j+8+i)+1] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL); ++ } ++ } ++ for(j=0;j<64;j+=8){ ++ unsigned long long int t,b; ++ for(i=0;i<4;i++){ ++ t=halfrow[2*(j+i)]; ++ b=halfrow[2*(j+4+i)]; ++ halfrow[2*(j+i)] =((t&0x0f0f0f0f0f0f0f0fULL)<<4) | (b&0x0f0f0f0f0f0f0f0fULL); ++ halfrow[2*(j+4+i)] = (t&0xf0f0f0f0f0f0f0f0ULL) | ((b&0xf0f0f0f0f0f0f0f0ULL)>>4); ++ t=halfrow[2*(j+i)+1]; ++ b=halfrow[2*(j+4+i)+1]; ++ halfrow[2*(j+i)+1] =((t&0x0f0f0f0f0f0f0f0fULL)<<4) | (b&0x0f0f0f0f0f0f0f0fULL); ++ halfrow[2*(j+4+i)+1] = (t&0xf0f0f0f0f0f0f0f0ULL) | ((b&0xf0f0f0f0f0f0f0f0ULL)>>4); ++ } ++ } ++ for(j=0;j<64;j+=4){ ++ unsigned long long int t,b; ++ for(i=0;i<2;i++){ ++ t=halfrow[2*(j+i)]; ++ b=halfrow[2*(j+2+i)]; ++ halfrow[2*(j+i)] =((t&0x3333333333333333ULL)<<2) | (b&0x3333333333333333ULL); ++ halfrow[2*(j+2+i)] = (t&0xccccccccccccccccULL) | ((b&0xccccccccccccccccULL)>>2); ++ t=halfrow[2*(j+i)+1]; ++ b=halfrow[2*(j+2+i)+1]; ++ halfrow[2*(j+i)+1] =((t&0x3333333333333333ULL)<<2) | (b&0x3333333333333333ULL); ++ halfrow[2*(j+2+i)+1] = (t&0xccccccccccccccccULL) | ((b&0xccccccccccccccccULL)>>2); ++ } ++ } ++ for(j=0;j<64;j+=2){ ++ unsigned long long int t,b; ++ for(i=0;i<1;i++){ ++ t=halfrow[2*(j+i)]; ++ b=halfrow[2*(j+1+i)]; ++ halfrow[2*(j+i)] =((t&0x5555555555555555ULL)<<1) | (b&0x5555555555555555ULL); ++ halfrow[2*(j+1+i)] = (t&0xaaaaaaaaaaaaaaaaULL) | ((b&0xaaaaaaaaaaaaaaaaULL)>>1); ++ t=halfrow[2*(j+i)+1]; ++ b=halfrow[2*(j+1+i)+1]; ++ halfrow[2*(j+i)+1] =((t&0x5555555555555555ULL)<<1) | (b&0x5555555555555555ULL); ++ halfrow[2*(j+1+i)+1] = (t&0xaaaaaaaaaaaaaaaaULL) | ((b&0xaaaaaaaaaaaaaaaaULL)>>1); ++ } ++ } ++#undef halfrow ++} ++ ++static inline void trasp64_128_88cw(unsigned char *data){ ++/* 64 rows of 128 bits transposition (bytes transp. - 8x8 rotate clockwise)*/ ++#define halfrow ((unsigned long long int *)data) ++ int i,j; ++ for(j=0;j<64;j+=64){ ++ unsigned long long int t,b; ++ for(i=0;i<32;i++){ ++ t=halfrow[2*(j+i)]; ++ b=halfrow[2*(j+32+i)]; ++ halfrow[2*(j+i)] = (t&0x00000000ffffffffULL) | ((b )<<32); ++ halfrow[2*(j+32+i)]=((t )>>32) | (b&0xffffffff00000000ULL) ; ++ t=halfrow[2*(j+i)+1]; ++ b=halfrow[2*(j+32+i)+1]; ++ halfrow[2*(j+i)+1] = (t&0x00000000ffffffffULL) | ((b )<<32); ++ halfrow[2*(j+32+i)+1]=((t )>>32) | (b&0xffffffff00000000ULL) ; ++ } ++ } ++ for(j=0;j<64;j+=32){ ++ unsigned long long int t,b; ++ for(i=0;i<16;i++){ ++ t=halfrow[2*(j+i)]; ++ b=halfrow[2*(j+16+i)]; ++ halfrow[2*(j+i)] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16); ++ halfrow[2*(j+16+i)]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ; ++ t=halfrow[2*(j+i)+1]; ++ b=halfrow[2*(j+16+i)+1]; ++ halfrow[2*(j+i)+1] = (t&0x0000ffff0000ffffULL) | ((b&0x0000ffff0000ffffULL)<<16); ++ halfrow[2*(j+16+i)+1]=((t&0xffff0000ffff0000ULL)>>16) | (b&0xffff0000ffff0000ULL) ; ++ } ++ } ++ for(j=0;j<64;j+=16){ ++ unsigned long long int t,b; ++ for(i=0;i<8;i++){ ++ t=halfrow[2*(j+i)]; ++ b=halfrow[2*(j+8+i)]; ++ halfrow[2*(j+i)] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8); ++ halfrow[2*(j+8+i)] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL); ++ t=halfrow[2*(j+i)+1]; ++ b=halfrow[2*(j+8+i)+1]; ++ halfrow[2*(j+i)+1] = (t&0x00ff00ff00ff00ffULL) | ((b&0x00ff00ff00ff00ffULL)<<8); ++ halfrow[2*(j+8+i)+1] =((t&0xff00ff00ff00ff00ULL)>>8) | (b&0xff00ff00ff00ff00ULL); ++ } ++ } ++ for(j=0;j<64;j+=8){ ++ unsigned long long int t,b; ++ for(i=0;i<4;i++){ ++ t=halfrow[2*(j+i)]; ++ b=halfrow[2*(j+4+i)]; ++ halfrow[2*(j+i)] =((t&0xf0f0f0f0f0f0f0f0ULL)>>4) | (b&0xf0f0f0f0f0f0f0f0ULL); ++ halfrow[2*(j+4+i)] = (t&0x0f0f0f0f0f0f0f0fULL) | ((b&0x0f0f0f0f0f0f0f0fULL)<<4); ++ t=halfrow[2*(j+i)+1]; ++ b=halfrow[2*(j+4+i)+1]; ++ halfrow[2*(j+i)+1] =((t&0xf0f0f0f0f0f0f0f0ULL)>>4) | (b&0xf0f0f0f0f0f0f0f0ULL); ++ halfrow[2*(j+4+i)+1] = (t&0x0f0f0f0f0f0f0f0fULL) | ((b&0x0f0f0f0f0f0f0f0fULL)<<4); ++ } ++ } ++ for(j=0;j<64;j+=4){ ++ unsigned long long int t,b; ++ for(i=0;i<2;i++){ ++ t=halfrow[2*(j+i)]; ++ b=halfrow[2*(j+2+i)]; ++ halfrow[2*(j+i)] =((t&0xccccccccccccccccULL)>>2) | (b&0xccccccccccccccccULL); ++ halfrow[2*(j+2+i)] = (t&0x3333333333333333ULL) | ((b&0x3333333333333333ULL)<<2); ++ t=halfrow[2*(j+i)+1]; ++ b=halfrow[2*(j+2+i)+1]; ++ halfrow[2*(j+i)+1] =((t&0xccccccccccccccccULL)>>2) | (b&0xccccccccccccccccULL); ++ halfrow[2*(j+2+i)+1] = (t&0x3333333333333333ULL) | ((b&0x3333333333333333ULL)<<2); ++ } ++ } ++ for(j=0;j<64;j+=2){ ++ unsigned long long int t,b; ++ for(i=0;i<1;i++){ ++ t=halfrow[2*(j+i)]; ++ b=halfrow[2*(j+1+i)]; ++ halfrow[2*(j+i)] =((t&0xaaaaaaaaaaaaaaaaULL)>>1) | (b&0xaaaaaaaaaaaaaaaaULL); ++ halfrow[2*(j+1+i)] = (t&0x5555555555555555ULL) | ((b&0x5555555555555555ULL)<<1); ++ t=halfrow[2*(j+i)+1]; ++ b=halfrow[2*(j+1+i)+1]; ++ halfrow[2*(j+i)+1] =((t&0xaaaaaaaaaaaaaaaaULL)>>1) | (b&0xaaaaaaaaaaaaaaaaULL); ++ halfrow[2*(j+1+i)+1] = (t&0x5555555555555555ULL) | ((b&0x5555555555555555ULL)<<1); ++ } ++ } ++#undef halfrow ++} ++#endif ++ ++ ++#ifdef STREAM_INIT ++void stream_cypher_group_init( ++ struct stream_regs *regs, ++ group iA[8][4], // [In] iA00,iA01,...iA73 32 groups | Derived from key. ++ group iB[8][4], // [In] iB00,iB01,...iB73 32 groups | Derived from key. ++ unsigned char *sb) // [In] (SB0,SB1,...SB7)...x32 32*8 bytes | Extra input. ++#endif ++#ifdef STREAM_NORMAL ++void stream_cypher_group_normal( ++ struct stream_regs *regs, ++ unsigned char *cb) // [Out] (CB0,CB1,...CB7)...x32 32*8 bytes | Output. ++#endif ++{ ++#ifdef STREAM_INIT ++ group in1[4]; ++ group in2[4]; ++#endif ++ group extra_B[4]; ++ group fa,fb,fc,fd,fe; ++ group s1a,s1b,s2a,s2b,s3a,s3b,s4a,s4b,s5a,s5b,s6a,s6b,s7a,s7b; ++ group next_E[4]; ++ group tmp0,tmp1,tmp2,tmp3,tmp4; ++#ifdef STREAM_INIT ++ group *sb_g=(group *)sb; ++#endif ++#ifdef STREAM_NORMAL ++ group *cb_g=(group *)cb; ++#endif ++ int aboff; ++ int i,j,k,b; ++ int dbg; ++ ++#ifdef STREAM_INIT ++ DBG(fprintf(stderr,":::::::::: BEGIN STREAM INIT\n")); ++#endif ++#ifdef STREAM_NORMAL ++ DBG(fprintf(stderr,":::::::::: BEGIN STREAM NORMAL\n")); ++#endif ++#ifdef STREAM_INIT ++for(j=0;j<64;j++){ ++ DBG(fprintf(stderr,"precall prerot stream_in[%2i]=",j)); ++ DBG(dump_mem("",sb+BYPG*j,BYPG,BYPG)); ++} ++ ++DBG(dump_mem("stream_prerot ",sb,GROUP_PARALLELISM*8,BYPG)); ++#if GROUP_PARALLELISM==32 ++trasp64_32_88ccw(sb); ++#endif ++#if GROUP_PARALLELISM==64 ++trasp64_64_88ccw(sb); ++#endif ++#if GROUP_PARALLELISM==128 ++trasp64_128_88ccw(sb); ++#endif ++DBG(dump_mem("stream_postrot",sb,GROUP_PARALLELISM*8,BYPG)); ++ ++for(j=0;j<64;j++){ ++ DBG(fprintf(stderr,"precall stream_in[%2i]=",j)); ++ DBG(dump_mem("",sb+BYPG*j,BYPG,BYPG)); ++} ++#endif ++ ++ aboff=32; ++ ++#ifdef STREAM_INIT ++ // load first 32 bits of ck into A[aboff+0]..A[aboff+7] ++ // load last 32 bits of ck into B[aboff+0]..B[aboff+7] ++ // all other regs = 0 ++ for(i=0;i<8;i++){ ++ for(b=0;b<4;b++){ ++DBG(fprintf(stderr,"dbg from iA A[%i][%i]=",i,b)); ++DBG(dump_mem("",(unsigned char *)&iA[i][b],BYPG,BYPG)); ++DBG(fprintf(stderr," dbg from iB B[%i][%i]=",i,b)); ++DBG(dump_mem("",(unsigned char *)&iB[i][b],BYPG,BYPG)); ++ regs->A[aboff+i][b]=iA[i][b]; ++ regs->B[aboff+i][b]=iB[i][b]; ++ } ++ } ++ for(b=0;b<4;b++){ ++ regs->A[aboff+8][b]=FF0(); ++ regs->A[aboff+9][b]=FF0(); ++ regs->B[aboff+8][b]=FF0(); ++ regs->B[aboff+9][b]=FF0(); ++ } ++ for(b=0;b<4;b++){ ++ regs->X[b]=FF0(); ++ regs->Y[b]=FF0(); ++ regs->Z[b]=FF0(); ++ regs->D[b]=FF0(); ++ regs->E[b]=FF0(); ++ regs->F[b]=FF0(); ++ } ++ regs->p=FF0(); ++ regs->q=FF0(); ++ regs->r=FF0(); ++#endif ++ ++for(dbg=0;dbg<4;dbg++){ ++ DBG(fprintf(stderr,"dbg A0[%i]=",dbg)); ++ DBG(dump_mem("",(unsigned char *)®s->A[aboff+0][dbg],BYPG,BYPG)); ++ DBG(fprintf(stderr,"dbg B0[%i]=",dbg)); ++ DBG(dump_mem("",(unsigned char *)®s->B[aboff+0][dbg],BYPG,BYPG)); ++} ++ ++//////////////////////////////////////////////////////////////////////////////// ++ ++ // EXTERNAL LOOP - 8 bytes per operation ++ for(i=0;i<8;i++){ ++ ++ DBG(fprintf(stderr,"--BEGIN EXTERNAL LOOP %i\n",i)); ++ ++#ifdef STREAM_INIT ++ for(b=0;b<4;b++){ ++ in1[b]=sb_g[8*i+4+b]; ++ in2[b]=sb_g[8*i+b]; ++ } ++#endif ++ ++ // INTERNAL LOOP - 2 bits per iteration ++ for(j=0; j<4; j++){ ++ ++ DBG(fprintf(stderr,"---BEGIN INTERNAL LOOP %i (EXT %i, INT %i)\n",j,i,j)); ++ ++ // from A0..A9, 35 bits are selected as inputs to 7 s-boxes ++ // 5 bits input per s-box, 2 bits output per s-box ++ ++ // we can select bits with zero masking and shifting operations ++ // and synthetize s-boxes with optimized boolean functions. ++ // this is the actual reason we do all the crazy transposition ++ // stuff to switch between normal and bit slice representations. ++ // this code really flies. ++ ++ fe=regs->A[aboff+3][0];fa=regs->A[aboff+0][2];fb=regs->A[aboff+5][1];fc=regs->A[aboff+6][3];fd=regs->A[aboff+8][0]; ++/* 1000 1110 1110 0001 : lev 7: */ //tmp0=( fa^( fb^( ( ( ( fa|fb )^fc )|( fc^fd ) )^ALL_ONES ) ) ); ++/* 1110 0010 0011 0011 : lev 6: */ //tmp1=( ( fa|fb )^( ( fc&( fa|( fb^fd ) ) )^ALL_ONES ) ); ++/* 0011 0110 1000 1101 : lev 5: */ //tmp2=( fa^( ( fb&fd )^( ( fa&fd )|fc ) ) ); ++/* 0101 0101 1001 0011 : lev 5: */ //tmp3=( ( fa&fc )^( fa^( ( fa&fb )|fd ) ) ); ++/* 1000 1110 1110 0001 : lev 7: */ tmp0=FFXOR(fa,FFXOR(fb,FFXOR(FFOR(FFXOR(FFOR(fa,fb),fc),FFXOR(fc,fd)),FF1()))); ++/* 1110 0010 0011 0011 : lev 6: */ tmp1=FFXOR(FFOR(fa,fb),FFXOR(FFAND(fc,FFOR(fa,FFXOR(fb,fd))),FF1())); ++/* 0011 0110 1000 1101 : lev 5: */ tmp2=FFXOR(fa,FFXOR(FFAND(fb,fd),FFOR(FFAND(fa,fd),fc))); ++/* 0101 0101 1001 0011 : lev 5: */ tmp3=FFXOR(FFAND(fa,fc),FFXOR(fa,FFOR(FFAND(fa,fb),fd))); ++ s1a=FFXOR(tmp0,FFAND(fe,tmp1)); ++ s1b=FFXOR(tmp2,FFAND(fe,tmp3)); ++//dump_mem("s1as1b-fe",&fe,BYPG,BYPG); ++//dump_mem("s1as1b-fa",&fa,BYPG,BYPG); ++//dump_mem("s1as1b-fb",&fb,BYPG,BYPG); ++//dump_mem("s1as1b-fc",&fc,BYPG,BYPG); ++//dump_mem("s1as1b-fd",&fd,BYPG,BYPG); ++ ++ fe=regs->A[aboff+1][1];fa=regs->A[aboff+2][2];fb=regs->A[aboff+5][3];fc=regs->A[aboff+6][0];fd=regs->A[aboff+8][1]; ++/* 1001 1110 0110 0001 : lev 6: */ //tmp0=( fa^( ( fb&( fc|fd ) )^( fc^( fd^ALL_ONES ) ) ) ); ++/* 0000 0011 0111 1011 : lev 5: */ //tmp1=( ( fa&( fb^fd ) )|( ( fa|fb )&fc ) ); ++/* 1100 0110 1101 0010 : lev 6: */ //tmp2=( ( fb&fd )^( ( fa&fd )|( fb^( fc^ALL_ONES ) ) ) ); ++/* 0001 1110 1111 0101 : lev 5: */ //tmp3=( ( fa&fd )|( fa^( fb^( fc&fd ) ) ) ); ++/* 1001 1110 0110 0001 : lev 6: */ tmp0=FFXOR(fa,FFXOR(FFAND(fb,FFOR(fc,fd)),FFXOR(fc,FFXOR(fd,FF1())))); ++/* 0000 0011 0111 1011 : lev 5: */ tmp1=FFOR(FFAND(fa,FFXOR(fb,fd)),FFAND(FFOR(fa,fb),fc)); ++/* 1100 0110 1101 0010 : lev 6: */ tmp2=FFXOR(FFAND(fb,fd),FFOR(FFAND(fa,fd),FFXOR(fb,FFXOR(fc,FF1())))); ++/* 0001 1110 1111 0101 : lev 5: */ tmp3=FFOR(FFAND(fa,fd),FFXOR(fa,FFXOR(fb,FFAND(fc,fd)))); ++ s2a=FFXOR(tmp0,FFAND(fe,tmp1)); ++ s2b=FFXOR(tmp2,FFAND(fe,tmp3)); ++ ++ fe=regs->A[aboff+0][3];fa=regs->A[aboff+1][0];fb=regs->A[aboff+4][1];fc=regs->A[aboff+4][3];fd=regs->A[aboff+5][2]; ++/* 0100 1011 1001 0110 : lev 5: */ //tmp0=( fa^( fb^( ( fc&( fa|fd ) )^fd ) ) ); ++/* 1101 0101 1000 1100 : lev 7: */ //tmp1=( ( fa&fc )^( ( fa^fd )|( ( fb|fc )^( fd^ALL_ONES ) ) ) ); ++/* 0010 0111 1101 1000 : lev 4: */ //tmp2=( fa^( ( ( fb^fc )&fd )^fc ) ); ++/* 1111 1111 1111 1111 : lev 0: */ //tmp3=ALL_ONES; ++/* 0100 1011 1001 0110 : lev 5: */ tmp0=FFXOR(fa,FFXOR(fb,FFXOR(FFAND(fc,FFOR(fa,fd)),fd))); ++/* 1101 0101 1000 1100 : lev 7: */ tmp1=FFXOR(FFAND(fa,fc),FFOR(FFXOR(fa,fd),FFXOR(FFOR(fb,fc),FFXOR(fd,FF1())))); ++/* 0010 0111 1101 1000 : lev 4: */ tmp2=FFXOR(fa,FFXOR(FFAND(FFXOR(fb,fc),fd),fc)); ++/* 1111 1111 1111 1111 : lev 0: */ tmp3=FF1(); ++ s3a=FFXOR(tmp0,FFAND(FFNOT(fe),tmp1)); ++ s3b=FFXOR(tmp2,FFAND(fe,tmp3)); ++ ++ fe=regs->A[aboff+2][3];fa=regs->A[aboff+0][1];fb=regs->A[aboff+1][3];fc=regs->A[aboff+3][2];fd=regs->A[aboff+7][0]; ++/* 1011 0101 0100 1001 : lev 7: */ //tmp0=( fa^( ( fc&( fa^fd ) )|( fb^( fc|( fd^ALL_ONES ) ) ) ) ); ++/* 0010 1101 0110 0110 : lev 6: */ //tmp1=( ( fa&fb )^( fb^( ( ( fa|fc )&fd )^fc ) ) ); ++/* 0110 0111 1101 0000 : lev 7: */ //tmp2=( fa^( ( fb&fc )|( ( ( fa&( fb^fd ) )|fc )^fd ) ) ); ++/* 1111 1111 1111 1111 : lev 0: */ //tmp3=ALL_ONES; ++/* 1011 0101 0100 1001 : lev 7: */ tmp0=FFXOR(fa,FFOR(FFAND(fc,FFXOR(fa,fd)),FFXOR(fb,FFOR(fc,FFXOR(fd,FF1()))))); ++/* 0010 1101 0110 0110 : lev 6: */ tmp1=FFXOR(FFAND(fa,fb),FFXOR(fb,FFXOR(FFAND(FFOR(fa,fc),fd),fc))); ++/* 0110 0111 1101 0000 : lev 7: */ tmp2=FFXOR(fa,FFOR(FFAND(fb,fc),FFXOR(FFOR(FFAND(fa,FFXOR(fb,fd)),fc),fd))); ++/* 1111 1111 1111 1111 : lev 0: */ tmp3=FF1(); ++ s4a=FFXOR(tmp0,FFAND(fe,FFXOR(tmp1,tmp0))); ++ s4b=FFXOR(FFXOR(s4a,tmp2),FFAND(fe,tmp3)); ++ ++ fe=regs->A[aboff+4][2];fa=regs->A[aboff+3][3];fb=regs->A[aboff+5][0];fc=regs->A[aboff+7][1];fd=regs->A[aboff+8][2]; ++/* 1000 1111 0011 0010 : lev 7: */ //tmp0=( ( ( fa&( fb|fc ) )^fb )|( ( ( fa^fc )|fd )^ALL_ONES ) ); ++/* 0110 1011 0000 1011 : lev 6: */ //tmp1=( fb^( ( fc^fd )&( fc^( fb|( fa^fd ) ) ) ) ); ++/* 0001 1010 0111 1001 : lev 6: */ //tmp2=( ( fa&fc )^( fb^( ( fb|( fa^fc ) )&fd ) ) ); ++/* 0101 1101 1101 0101 : lev 4: */ //tmp3=( ( ( fa^fb )&( fc^ALL_ONES ) )|fd ); ++/* 1000 1111 0011 0010 : lev 7: */ tmp0=FFOR(FFXOR(FFAND(fa,FFOR(fb,fc)),fb),FFXOR(FFOR(FFXOR(fa,fc),fd),FF1())); ++/* 0110 1011 0000 1011 : lev 6: */ tmp1=FFXOR(fb,FFAND(FFXOR(fc,fd),FFXOR(fc,FFOR(fb,FFXOR(fa,fd))))); ++/* 0001 1010 0111 1001 : lev 6: */ tmp2=FFXOR(FFAND(fa,fc),FFXOR(fb,FFAND(FFOR(fb,FFXOR(fa,fc)),fd))); ++/* 0101 1101 1101 0101 : lev 4: */ tmp3=FFOR(FFAND(FFXOR(fa,fb),FFXOR(fc,FF1())),fd); ++ s5a=FFXOR(tmp0,FFAND(fe,tmp1)); ++ s5b=FFXOR(tmp2,FFAND(fe,tmp3)); ++ ++ fe=regs->A[aboff+2][1];fa=regs->A[aboff+3][1];fb=regs->A[aboff+4][0];fc=regs->A[aboff+6][2];fd=regs->A[aboff+8][3]; ++/* 0011 0110 0010 1101 : lev 6: */ //tmp0=( ( ( fa&fc )&fd )^( ( fb&( fa|fd ) )^fc ) ); ++/* 1110 1110 1011 1011 : lev 3: */ //tmp1=( ( ( fa^fc )&fd )^ALL_ONES ); ++/* 0101 1000 0110 0111 : lev 6: */ //tmp2=( ( fa&( fb|fc ) )^( fb^( ( fb&fc )|fd ) ) ); ++/* 0001 0011 0000 0001 : lev 5: */ //tmp3=( fc&( ( fa&( fb^fd ) )^( fb|fd ) ) ); ++/* 0011 0110 0010 1101 : lev 6: */ tmp0=FFXOR(FFAND(FFAND(fa,fc),fd),FFXOR(FFAND(fb,FFOR(fa,fd)),fc)); ++/* 1110 1110 1011 1011 : lev 3: */ tmp1=FFXOR(FFAND(FFXOR(fa,fc),fd),FF1()); ++/* 0101 1000 0110 0111 : lev 6: */ tmp2=FFXOR(FFAND(fa,FFOR(fb,fc)),FFXOR(fb,FFOR(FFAND(fb,fc),fd))); ++/* 0001 0011 0000 0001 : lev 5: */ tmp3=FFAND(fc,FFXOR(FFAND(fa,FFXOR(fb,fd)),FFOR(fb,fd))); ++ s6a=FFXOR(tmp0,FFAND(fe,tmp1)); ++ s6b=FFXOR(tmp2,FFAND(fe,tmp3)); ++ ++ fe=regs->A[aboff+1][2];fa=regs->A[aboff+2][0];fb=regs->A[aboff+6][1];fc=regs->A[aboff+7][2];fd=regs->A[aboff+7][3]; ++/* 0111 1000 1001 0110 : lev 5: */ //tmp0=( fb^( ( fc&fd )|( fa^( fc^fd ) ) ) ); ++/* 0100 1001 0101 1011 : lev 6: */ //tmp1=( ( fb|fd )&( ( fa&fc )|( fb^( fc^fd ) ) ) ); ++/* 0100 1001 1011 1001 : lev 5: */ //tmp2=( ( fa|fb )^( ( fc&( fb|fd ) )^fd ) ); ++/* 1111 1111 1101 1101 : lev 3: */ //tmp3=( fd|( ( fa&fc )^ALL_ONES ) ); ++/* 0111 1000 1001 0110 : lev 5: */ tmp0=FFXOR(fb,FFOR(FFAND(fc,fd),FFXOR(fa,FFXOR(fc,fd)))); ++/* 0100 1001 0101 1011 : lev 6: */ tmp1=FFAND(FFOR(fb,fd),FFOR(FFAND(fa,fc),FFXOR(fb,FFXOR(fc,fd)))); ++/* 0100 1001 1011 1001 : lev 5: */ tmp2=FFXOR(FFOR(fa,fb),FFXOR(FFAND(fc,FFOR(fb,fd)),fd)); ++/* 1111 1111 1101 1101 : lev 3: */ tmp3=FFOR(fd,FFXOR(FFAND(fa,fc),FF1())); ++ s7a=FFXOR(tmp0,FFAND(fe,tmp1)); ++ s7b=FFXOR(tmp2,FFAND(fe,tmp3)); ++ ++ ++/* ++ we have just done this: ++ ++ int sbox1[0x20] = {2,0,1,1,2,3,3,0, 3,2,2,0,1,1,0,3, 0,3,3,0,2,2,1,1, 2,2,0,3,1,1,3,0}; ++ int sbox2[0x20] = {3,1,0,2,2,3,3,0, 1,3,2,1,0,0,1,2, 3,1,0,3,3,2,0,2, 0,0,1,2,2,1,3,1}; ++ int sbox3[0x20] = {2,0,1,2,2,3,3,1, 1,1,0,3,3,0,2,0, 1,3,0,1,3,0,2,2, 2,0,1,2,0,3,3,1}; ++ int sbox4[0x20] = {3,1,2,3,0,2,1,2, 1,2,0,1,3,0,0,3, 1,0,3,1,2,3,0,3, 0,3,2,0,1,2,2,1}; ++ int sbox5[0x20] = {2,0,0,1,3,2,3,2, 0,1,3,3,1,0,2,1, 2,3,2,0,0,3,1,1, 1,0,3,2,3,1,0,2}; ++ int sbox6[0x20] = {0,1,2,3,1,2,2,0, 0,1,3,0,2,3,1,3, 2,3,0,2,3,0,1,1, 2,1,1,2,0,3,3,0}; ++ int sbox7[0x20] = {0,3,2,2,3,0,0,1, 3,0,1,3,1,2,2,1, 1,0,3,3,0,1,1,2, 2,3,1,0,2,3,0,2}; ++ ++ s12 = sbox1[ (((A3>>0)&1)<<4) | (((A0>>2)&1)<<3) | (((A5>>1)&1)<<2) | (((A6>>3)&1)<<1) | (((A8>>0)&1)<<0) ] ++ |sbox2[ (((A1>>1)&1)<<4) | (((A2>>2)&1)<<3) | (((A5>>3)&1)<<2) | (((A6>>0)&1)<<1) | (((A8>>1)&1)<<0) ]; ++ s34 = sbox3[ (((A0>>3)&1)<<4) | (((A1>>0)&1)<<3) | (((A4>>1)&1)<<2) | (((A4>>3)&1)<<1) | (((A5>>2)&1)<<0) ] ++ |sbox4[ (((A2>>3)&1)<<4) | (((A0>>1)&1)<<3) | (((A1>>3)&1)<<2) | (((A3>>2)&1)<<1) | (((A7>>0)&1)<<0) ]; ++ s56 = sbox5[ (((A4>>2)&1)<<4) | (((A3>>3)&1)<<3) | (((A5>>0)&1)<<2) | (((A7>>1)&1)<<1) | (((A8>>2)&1)<<0) ] ++ |sbox6[ (((A2>>1)&1)<<4) | (((A3>>1)&1)<<3) | (((A4>>0)&1)<<2) | (((A6>>2)&1)<<1) | (((A8>>3)&1)<<0) ]; ++ s7 = sbox7[ (((A1>>2)&1)<<4) | (((A2>>0)&1)<<3) | (((A6>>1)&1)<<2) | (((A7>>2)&1)<<1) | (((A7>>3)&1)<<0) ]; ++*/ ++ ++ // use 4x4 xor to produce extra nibble for T3 ++ ++ extra_B[3]=FFXOR(FFXOR(FFXOR(regs->B[aboff+2][0],regs->B[aboff+5][1]),regs->B[aboff+6][2]),regs->B[aboff+8][3]); ++ extra_B[2]=FFXOR(FFXOR(FFXOR(regs->B[aboff+5][0],regs->B[aboff+7][1]),regs->B[aboff+2][3]),regs->B[aboff+3][2]); ++ extra_B[1]=FFXOR(FFXOR(FFXOR(regs->B[aboff+4][3],regs->B[aboff+7][2]),regs->B[aboff+3][0]),regs->B[aboff+4][1]); ++ extra_B[0]=FFXOR(FFXOR(FFXOR(regs->B[aboff+8][2],regs->B[aboff+5][3]),regs->B[aboff+2][1]),regs->B[aboff+7][0]); ++for(dbg=0;dbg<4;dbg++){ ++ DBG(fprintf(stderr,"extra_B[%i]=",dbg)); ++ DBG(dump_mem("",(unsigned char *)&extra_B[dbg],BYPG,BYPG)); ++} ++ ++ // T1 = xor all inputs ++ // in1, in2, D are only used in T1 during initialisation, not generation ++ for(b=0;b<4;b++){ ++ regs->A[aboff-1][b]=FFXOR(regs->A[aboff+9][b],regs->X[b]); ++ } ++ ++#ifdef STREAM_INIT ++ for(b=0;b<4;b++){ ++ regs->A[aboff-1][b]=FFXOR(FFXOR(regs->A[aboff-1][b],regs->D[b]),((j % 2) ? in2[b] : in1[b])); ++ } ++#endif ++ ++for(dbg=0;dbg<4;dbg++){ ++ DBG(fprintf(stderr,"next_A0[%i]=",dbg)); ++ DBG(dump_mem("",(unsigned char *)®s->A[aboff-1][dbg],BYPG,BYPG)); ++} ++ ++ // T2 = xor all inputs ++ // in1, in2 are only used in T1 during initialisation, not generation ++ // if p=0, use this, if p=1, rotate the result left ++ for(b=0;b<4;b++){ ++ regs->B[aboff-1][b]=FFXOR(FFXOR(regs->B[aboff+6][b],regs->B[aboff+9][b]),regs->Y[b]); ++ } ++ ++#ifdef STREAM_INIT ++ for(b=0;b<4;b++){ ++ regs->B[aboff-1][b]=FFXOR(regs->B[aboff-1][b],((j % 2) ? in1[b] : in2[b])); ++ } ++#endif ++ ++for(dbg=0;dbg<4;dbg++){ ++ DBG(fprintf(stderr,"next_B0[%i]=",dbg)); ++ DBG(dump_mem("",(unsigned char *)®s->B[aboff-1][dbg],BYPG,BYPG)); ++} ++ ++ // if p=1, rotate left (yes, this is what we're doing) ++ tmp3=regs->B[aboff-1][3]; ++ regs->B[aboff-1][3]=FFXOR(regs->B[aboff-1][3],FFAND(FFXOR(regs->B[aboff-1][3],regs->B[aboff-1][2]),regs->p)); ++ regs->B[aboff-1][2]=FFXOR(regs->B[aboff-1][2],FFAND(FFXOR(regs->B[aboff-1][2],regs->B[aboff-1][1]),regs->p)); ++ regs->B[aboff-1][1]=FFXOR(regs->B[aboff-1][1],FFAND(FFXOR(regs->B[aboff-1][1],regs->B[aboff-1][0]),regs->p)); ++ regs->B[aboff-1][0]=FFXOR(regs->B[aboff-1][0],FFAND(FFXOR(regs->B[aboff-1][0],tmp3),regs->p)); ++ ++for(dbg=0;dbg<4;dbg++){ ++ DBG(fprintf(stderr,"next_B0[%i]=",dbg)); ++ DBG(dump_mem("",(unsigned char *)®s->B[aboff-1][dbg],BYPG,BYPG)); ++} ++ ++ // T3 = xor all inputs ++ for(b=0;b<4;b++){ ++ regs->D[b]=FFXOR(FFXOR(regs->E[b],regs->Z[b]),extra_B[b]); ++ } ++ ++for(dbg=0;dbg<4;dbg++){ ++ DBG(fprintf(stderr,"D[%i]=",dbg)); ++ DBG(dump_mem("",(unsigned char *)®s->D[dbg],BYPG,BYPG)); ++} ++ ++ // T4 = sum, carry of Z + E + r ++ for(b=0;b<4;b++){ ++ next_E[b]=regs->F[b]; ++ } ++ ++ tmp0=FFXOR(regs->Z[0],regs->E[0]); ++ tmp1=FFAND(regs->Z[0],regs->E[0]); ++ regs->F[0]=FFXOR(regs->E[0],FFAND(regs->q,FFXOR(regs->Z[0],regs->r))); ++ tmp3=FFAND(tmp0,regs->r); ++ tmp4=FFOR(tmp1,tmp3); ++ ++ tmp0=FFXOR(regs->Z[1],regs->E[1]); ++ tmp1=FFAND(regs->Z[1],regs->E[1]); ++ regs->F[1]=FFXOR(regs->E[1],FFAND(regs->q,FFXOR(regs->Z[1],tmp4))); ++ tmp3=FFAND(tmp0,tmp4); ++ tmp4=FFOR(tmp1,tmp3); ++ ++ tmp0=FFXOR(regs->Z[2],regs->E[2]); ++ tmp1=FFAND(regs->Z[2],regs->E[2]); ++ regs->F[2]=FFXOR(regs->E[2],FFAND(regs->q,FFXOR(regs->Z[2],tmp4))); ++ tmp3=FFAND(tmp0,tmp4); ++ tmp4=FFOR(tmp1,tmp3); ++ ++ tmp0=FFXOR(regs->Z[3],regs->E[3]); ++ tmp1=FFAND(regs->Z[3],regs->E[3]); ++ regs->F[3]=FFXOR(regs->E[3],FFAND(regs->q,FFXOR(regs->Z[3],tmp4))); ++ tmp3=FFAND(tmp0,tmp4); ++ regs->r=FFXOR(regs->r,FFAND(regs->q,FFXOR(FFOR(tmp1,tmp3),regs->r))); // ultimate carry ++ ++/* ++ we have just done this: (believe it or not) ++ ++ if (q) { ++ F = Z + E + r; ++ r = (F >> 4) & 1; ++ F = F & 0x0f; ++ } ++ else { ++ F = E; ++ } ++*/ ++ for(b=0;b<4;b++){ ++ regs->E[b]=next_E[b]; ++ } ++for(dbg=0;dbg<4;dbg++){ ++ DBG(fprintf(stderr,"F[%i]=",dbg)); ++ DBG(dump_mem("",(unsigned char *)®s->F[dbg],BYPG,BYPG)); ++} ++DBG(fprintf(stderr,"r=")); ++DBG(dump_mem("",(unsigned char *)®s->r,BYPG,BYPG)); ++for(dbg=0;dbg<4;dbg++){ ++ DBG(fprintf(stderr,"E[%i]=",dbg)); ++ DBG(dump_mem("",(unsigned char *)®s->E[dbg],BYPG,BYPG)); ++} ++ ++ // this simple instruction is virtually shifting all the shift registers ++ aboff--; ++ ++/* ++ we've just done this: ++ ++ A9=A8;A8=A7;A7=A6;A6=A5;A5=A4;A4=A3;A3=A2;A2=A1;A1=A0;A0=next_A0; ++ B9=B8;B8=B7;B7=B6;B6=B5;B5=B4;B4=B3;B3=B2;B2=B1;B1=B0;B0=next_B0; ++*/ ++ ++ regs->X[0]=s1a; ++ regs->X[1]=s2a; ++ regs->X[2]=s3b; ++ regs->X[3]=s4b; ++ regs->Y[0]=s3a; ++ regs->Y[1]=s4a; ++ regs->Y[2]=s5b; ++ regs->Y[3]=s6b; ++ regs->Z[0]=s5a; ++ regs->Z[1]=s6a; ++ regs->Z[2]=s1b; ++ regs->Z[3]=s2b; ++ regs->p=s7a; ++ regs->q=s7b; ++for(dbg=0;dbg<4;dbg++){ ++ DBG(fprintf(stderr,"X[%i]=",dbg)); ++ DBG(dump_mem("",(unsigned char *)®s->X[dbg],BYPG,BYPG)); ++} ++for(dbg=0;dbg<4;dbg++){ ++ DBG(fprintf(stderr,"Y[%i]=",dbg)); ++ DBG(dump_mem("",(unsigned char *)®s->Y[dbg],BYPG,BYPG)); ++} ++for(dbg=0;dbg<4;dbg++){ ++ DBG(fprintf(stderr,"Z[%i]=",dbg)); ++ DBG(dump_mem("",(unsigned char *)®s->Z[dbg],BYPG,BYPG)); ++} ++DBG(fprintf(stderr,"p=")); ++DBG(dump_mem("",(unsigned char *)®s->p,BYPG,BYPG)); ++DBG(fprintf(stderr,"q=")); ++DBG(dump_mem("",(unsigned char *)®s->q,BYPG,BYPG)); ++ ++#ifdef STREAM_NORMAL ++ // require 4 loops per output byte ++ // 2 output bits are a function of the 4 bits of D ++ // xor 2 by 2 ++ cb_g[8*i+7-2*j]=FFXOR(regs->D[2],regs->D[3]); ++ cb_g[8*i+6-2*j]=FFXOR(regs->D[0],regs->D[1]); ++for(dbg=0;dbg<8;dbg++){ ++ DBG(fprintf(stderr,"op[%i]=",dbg)); ++ DBG(dump_mem("",(unsigned char *)&cb_g[8*i+dbg],BYPG,BYPG)); ++} ++#endif ++ ++DBG(fprintf(stderr,"---END INTERNAL LOOP\n")); ++ ++ } // INTERNAL LOOP ++ ++DBG(fprintf(stderr,"--END EXTERNAL LOOP\n")); ++ ++ } // EXTERNAL LOOP ++ ++ // move 32 steps forward, ready for next call ++ for(k=0;k<10;k++){ ++ for(b=0;b<4;b++){ ++DBG(fprintf(stderr,"moving forward AB k=%i b=%i\n",k,b)); ++ regs->A[32+k][b]=regs->A[k][b]; ++ regs->B[32+k][b]=regs->B[k][b]; ++ } ++ } ++ ++ ++//////////////////////////////////////////////////////////////////////////////// ++ ++#ifdef STREAM_NORMAL ++for(j=0;j<64;j++){ ++ DBG(fprintf(stderr,"postcall prerot cb[%2i]=",j)); ++ DBG(dump_mem("",(unsigned char *)(cb+BYPG*j),BYPG,BYPG)); ++} ++ ++#if GROUP_PARALLELISM==32 ++trasp64_32_88cw(cb); ++#endif ++#if GROUP_PARALLELISM==64 ++trasp64_64_88cw(cb); ++#endif ++#if GROUP_PARALLELISM==128 ++trasp64_128_88cw(cb); ++#endif ++ ++for(j=0;j<64;j++){ ++ DBG(fprintf(stderr,"postcall postrot cb[%2i]=",j)); ++ DBG(dump_mem("",(unsigned char *)(cb+BYPG*j),BYPG,BYPG)); ++} ++#endif ++ ++#ifdef STREAM_INIT ++ DBG(fprintf(stderr,":::::::::: END STREAM INIT\n")); ++#endif ++#ifdef STREAM_NORMAL ++ DBG(fprintf(stderr,":::::::::: END STREAM NORMAL\n")); ++#endif ++ ++} ++ +diff -ruNp trunk.patches/globals.h trunk/globals.h +--- trunk.patches/globals.h 2018-04-03 03:02:59.558440627 +0300 ++++ trunk/globals.h 2018-04-03 03:20:07.658045369 +0300 +@@ -392,17 +392,17 @@ typedef unsigned char uchar; + #define CS_ECM_RINGBUFFER_MAX 0x10 // max size for ECM last responsetimes ringbuffer. Keep this set to power of 2 values! + + // Support for multiple CWs per channel and other encryption algos +-//#define WITH_EXTENDED_CW 1 ++#define WITH_EXTENDED_CW 1 + + #if defined(READER_DRE) || defined(READER_DRECAS) || defined(READER_VIACCESS) + #define MAX_ECM_SIZE 1024 + #define MAX_EMM_SIZE 1024 + #else +-#define MAX_ECM_SIZE 596 +-#define MAX_EMM_SIZE 512 ++#define MAX_ECM_SIZE 1024 ++#define MAX_EMM_SIZE 1024 + #endif + +-#define CS_EMMCACHESIZE 512 //nr of EMMs that each reader will cache ++#define CS_EMMCACHESIZE 1024 //nr of EMMs that each reader will cache + #define MSGLOGSIZE 64 //size of string buffer for a ecm to return messages + + #define D_TRACE 0x0001 // Generate very detailed error/trace messages per routine +@@ -434,6 +434,7 @@ typedef unsigned char uchar; + #define R_SMART 0x7 // Smartreader+ + #define R_PCSC 0x8 // PCSC + #define R_DRECAS 0x9 // Reader DRECAS ++#define R_EMU 0x17 // Reader EMU + /////////////////// proxy readers after R_CS378X + #define R_CAMD35 0x20 // Reader cascading camd 3.5x + #define R_CAMD33 0x21 // Reader cascading camd 3.3x +@@ -861,6 +862,13 @@ typedef struct s_entitlement + uint32_t class; // the class needed for some systems + time_t start; // startdate + time_t end; // enddate ++#ifdef WITH_EMU ++ bool isKey; ++ bool isData; ++ char name[8]; ++ uint8_t *key; ++ uint32_t keyLength; ++#endif + } S_ENTITLEMENT; + + struct s_client ; +@@ -985,6 +993,7 @@ struct s_cardsystem + void (*post_process)(struct s_reader *); + int32_t (*get_emm_type)(struct emm_packet_t *, struct s_reader *); + int32_t (*get_emm_filter)(struct s_reader *, struct s_csystem_emm_filter **, unsigned int *); ++ int32_t (*get_emm_filter_adv)(struct s_reader *, struct s_csystem_emm_filter **, unsigned int *, uint16_t, uint32_t, uint16_t); + int32_t (*get_tunemm_filter)(struct s_reader *, struct s_csystem_emm_filter **, unsigned int *); + }; + +@@ -1717,6 +1726,14 @@ struct s_reader + #ifdef MODULE_GHTTP + uint8_t ghttp_use_ssl; + #endif ++#ifdef WITH_EMU ++ FTAB emu_auproviders; // AU providers for Emu reader ++ int8_t emu_datecodedenabled; // date-coded keys for BISS ++ char *extee36; // path to "ee36.bin" - Set by the user via the webif ++ char *extee56; // path to "ee56.bin" - Set by the user via the webif ++ uint8_t dre36_force_group; ++ uint8_t dre56_force_group; ++#endif + uint8_t cnxlastecm; // == 0 - las ecm has not been paired ecm, > 0 last ecm has been paired ecm + LLIST *emmstat; //emm stats + CS_MUTEX_LOCK emmstat_lock; +@@ -2167,6 +2184,7 @@ struct s_config + int8_t dvbapi_read_sdt; + int8_t dvbapi_write_sdt_prov; + int8_t dvbapi_extended_cw_api; ++ int8_t dvbapi_extended_cw_pids; // pid limiter + #endif + + #ifdef CS_ANTICASC +@@ -2213,6 +2231,18 @@ struct s_config + IN_ADDR_T scam_srvip; + struct s_ip *scam_allowed; + #endif ++ ++#ifdef WITH_EMU ++ char *emu_stream_source_host; ++ int32_t emu_stream_source_port; ++ char *emu_stream_source_auth_user; ++ char *emu_stream_source_auth_password; ++ int32_t emu_stream_relay_port; ++ uint32_t emu_stream_ecm_delay; ++ int8_t emu_stream_relay_enabled; ++ int8_t emu_stream_emm_enabled; ++#endif ++ + int32_t max_cache_time; //seconds ecms are stored in ecmcwcache + int32_t max_hitcache_time; //seconds hits are stored in cspec_hitcache (to detect dyn wait_time) + +@@ -2394,4 +2424,8 @@ static inline bool caid_is_bulcrypt(uint + static inline bool caid_is_dre(uint16_t caid) { return caid == 0x4AE0 || caid == 0x4AE1 || caid == 0x2710;} + const char *get_cardsystem_desc_by_caid(uint16_t caid); + ++#ifdef WITH_EMU ++FILTER* get_emu_prids_for_caid(struct s_reader *rdr, uint16_t caid); ++#endif ++ + #endif +diff -ruNp trunk.patches/Makefile trunk/Makefile +--- trunk.patches/Makefile 2018-04-03 03:01:12.325689204 +0300 ++++ trunk/Makefile 2018-04-03 03:20:07.654045339 +0300 +@@ -67,6 +67,13 @@ STRIP = $(CROSS_DIR)$(CROSS)strip + + LDFLAGS = -Wl,--gc-sections + ++TARGETHELP := $(shell $(CC) --target-help 2>&1) ++ifneq (,$(findstring sse2,$(TARGETHELP))) ++override CFLAGS += -fexpensive-optimizations -mmmx -msse -msse2 -msse3 ++else ++override CFLAGS += -fexpensive-optimizations ++endif ++ + # The linker for powerpc have bug that prevents --gc-sections from working + # Check for the linker version and if it matches disable --gc-sections + # For more information about the bug see: +@@ -270,6 +277,21 @@ SRC-$(CONFIG_CS_CACHEEX) += module-cccam + SRC-$(CONFIG_MODULE_CCCAM) += module-cccam.c + SRC-$(CONFIG_MODULE_CCCSHARE) += module-cccshare.c + SRC-$(CONFIG_MODULE_CONSTCW) += module-constcw.c ++SRC-$(CONFIG_WITH_EMU) += module-emulator.c ++SRC-$(CONFIG_WITH_EMU) += module-emulator-osemu.c ++SRC-$(CONFIG_WITH_EMU) += module-emulator-stream.c ++SRC-$(CONFIG_WITH_EMU) += ffdecsa/ffdecsa.c ++UNAME := $(shell uname -s) ++ifneq ($(UNAME),Darwin) ++ifndef ANDROID_NDK ++ifndef ANDROID_STANDALONE_TOOLCHAIN ++ifeq "$(CONFIG_WITH_EMU)" "y" ++TOUCH_SK := $(shell touch SoftCam.Key) ++override LDFLAGS += -Wl,--format=binary -Wl,SoftCam.Key -Wl,--format=default ++endif ++endif ++endif ++endif + SRC-$(CONFIG_CS_CACHEEX) += module-csp.c + SRC-$(CONFIG_CW_CYCLE_CHECK) += module-cw-cycle-check.c + SRC-$(CONFIG_WITH_AZBOX) += module-dvbapi-azbox.c +@@ -368,7 +390,7 @@ SRC := $(subst config.c,$(OBJDIR)/config + # starts the compilation. + all: + @./config.sh --use-flags "$(USE_FLAGS)" --objdir "$(OBJDIR)" --make-config.mak +- @-mkdir -p $(OBJDIR)/cscrypt $(OBJDIR)/csctapi $(OBJDIR)/minilzo $(OBJDIR)/webif ++ @-mkdir -p $(OBJDIR)/cscrypt $(OBJDIR)/csctapi $(OBJDIR)/minilzo $(OBJDIR)/ffdecsa $(OBJDIR)/webif + @-printf "\ + +-------------------------------------------------------------------------------\n\ + | OSCam ver: $(VER) rev: $(SVN_REV) target: $(TARGET)\n\ +diff -ruNp trunk.patches/module-dvbapi.c trunk/module-dvbapi.c +--- trunk.patches/module-dvbapi.c 2018-04-03 03:06:13.063827549 +0300 ++++ trunk/module-dvbapi.c 2018-04-03 03:20:07.658045369 +0300 +@@ -1471,7 +1471,15 @@ void dvbapi_start_emm_filter(int32_t dem + } + if(match) + { +- csystem = get_cardsystem_by_caid(caid); ++ if(rdr->typ == R_EMU) ++ { ++ csystem = rdr->csystem; ++ } ++ else ++ { ++ csystem = get_cardsystem_by_caid(caid); ++ } ++ + if(csystem) + { + if(caid != ncaid) +@@ -1490,7 +1498,14 @@ void dvbapi_start_emm_filter(int32_t dem + } + else if (csystem->get_emm_filter) + { +- csystem->get_emm_filter(rdr, &dmx_filter, &filter_count); ++ if(rdr->typ == R_EMU) ++ { ++ csystem->get_emm_filter_adv(rdr, &dmx_filter, &filter_count, caid, provid, demux[demux_index].program_number); ++ } ++ else ++ { ++ csystem->get_emm_filter(rdr, &dmx_filter, &filter_count); ++ } + } + } + else +@@ -2076,6 +2091,8 @@ int32_t dvbapi_start_descrambling(int32_ + er->vpid = demux[demux_id].ECMpids[pid].VPID; + er->pmtpid = demux[demux_id].pmtpid; + er->onid = demux[demux_id].onid; ++ er->tsid = demux[demux_id].tsid; ++ er->ens = demux[demux_id].enigma_namespace; + er->msgid = msgid; + + #ifdef WITH_STAPI5 +@@ -2113,19 +2130,30 @@ int32_t dvbapi_start_descrambling(int32_ + if(caid_is_fake(demux[demux_id].ECMpids[pid].CAID) || caid_is_biss(demux[demux_id].ECMpids[pid].CAID)) + { + int32_t j, n; +- er->ecmlen = 5; ++ er->ecmlen = 7; + er->ecm[0] = 0x80; // to pass the cache check it must be 0x80 or 0x81 + er->ecm[1] = 0x00; +- er->ecm[2] = 0x02; ++ er->ecm[2] = 0x04; + i2b_buf(2, er->srvid, er->ecm + 3); ++ i2b_buf(2, er->pmtpid, er->ecm + 5); + +- for(j = 0, n = 5; j < demux[demux_id].STREAMpidcount; j++, n += 2) ++ for(j = 0, n = 7; j < demux[demux_id].STREAMpidcount; j++, n += 2) + { + i2b_buf(2, demux[demux_id].STREAMpids[j], er->ecm + n); + er->ecm[2] += 2; + er->ecmlen += 2; + } + ++ er->ens &= 0x0FFFFFFF; // clear top 4 bits (in case of DVB-T/C or garbage), prepare for flagging ++ er->ens |= 0xA0000000; // flag to emu: this is the namespace, not a pid ++ ++ i2b_buf(2, er->tsid, er->ecm + 3 + er->ecm[2]); // place tsid after the last stream pid ++ i2b_buf(2, er->onid, er->ecm + 3 + er->ecm[2] + 2); // place onid right after tsid ++ i2b_buf(4, er->ens, er->ecm + 3 + er->ecm[2] + 4); // place namespace at the end of the ecm ++ ++ er->ecm[2] += 8; ++ er->ecmlen += 8; ++ + cs_log("Demuxer %d trying to descramble PID %d CAID %04X PROVID %06X ECMPID %04X ANY CHID PMTPID %04X VPID %04X", demux_id, pid, + demux[demux_id].ECMpids[pid].CAID, demux[demux_id].ECMpids[pid].PROVID, demux[demux_id].ECMpids[pid].ECM_PID, + demux[demux_id].pmtpid, demux[demux_id].ECMpids[pid].VPID); +@@ -3192,6 +3220,7 @@ int32_t dvbapi_parse_capmt(unsigned char + { + uint32_t i = 0, start_descrambling = 0; + int32_t j = 0; ++ int32_t max_pids = 64; + int32_t demux_id = -1; + uint16_t demux_index, adapter_index, pmtpid; + uint32_t ca_mask; +@@ -3354,6 +3383,12 @@ int32_t dvbapi_parse_capmt(unsigned char + uint32_t es_info_length = 0, vpid = 0; + struct s_dvbapi_priority *addentry; + ++ // pid limiter for PowerVu ++ if(demux[demux_id].ECMpids[0].CAID >> 8 == 0x0E) ++ { ++ max_pids = cfg.dvbapi_extended_cw_pids; ++ } ++ + for(i = program_info_length + program_info_start; i + 4 < length; i += es_info_length + 5) + { + uint8_t stream_type = buffer[i]; +@@ -3361,7 +3396,7 @@ int32_t dvbapi_parse_capmt(unsigned char + uint8_t is_audio = 0; + es_info_length = b2i(2, buffer + i +3)&0x0FFF; + +- if(demux[demux_id].STREAMpidcount < ECM_PIDS) ++ if(demux[demux_id].STREAMpidcount < max_pids) // was "ECM_PIDS" (pid limiter) + { + + demux[demux_id].STREAMpids[demux[demux_id].STREAMpidcount] = elementary_pid; +@@ -4375,6 +4410,7 @@ void dvbapi_process_input(int32_t demux_ + if(filtertype == TYPE_ECM) + { + uint32_t chid = 0x10000; ++ int8_t pvu_skip = 0; + ECM_REQUEST *er; + + if(len != 0) // len = 0 receiver encountered an internal bufferoverflow! +@@ -4401,9 +4437,24 @@ void dvbapi_process_input(int32_t demux_ + return; + } + +- if(curpid->table == buffer[0] && !caid_is_irdeto(curpid->CAID)) // wait for odd / even ecm change (only not for irdeto!) ++ if(curpid->CAID >> 8 == 0x0E) + { +- ++ pvu_skip = 1; ++ ++ if(sctlen - 11 > buffer[9]) ++ { ++ if(buffer[11 + buffer[9]] > curpid->pvu_counter || (curpid->pvu_counter == 255 && buffer[11 + buffer[9]] == 0) ++ || ((curpid->pvu_counter - buffer[11 + buffer[9]]) > 5)) ++ { ++ curpid->pvu_counter = buffer[11 + buffer[9]]; ++ pvu_skip = 0; ++ } ++ } ++ } ++ ++ if((curpid->table == buffer[0] && !caid_is_irdeto(curpid->CAID)) || pvu_skip) // wait for odd / even ecm change (only not for irdeto!) ++ { ++ + if(!(er = get_ecmtask())) + { + return; +@@ -4685,6 +4736,40 @@ void dvbapi_process_input(int32_t demux_ + dvbapi_stop_filternum(demux_id, filter_num, msgid); + return; + } ++ ++#ifdef WITH_EMU ++ if((demux[demux_id].demux_fd[filter_num].caid>>8) == 0x10) ++ { ++ uint32_t i; ++ uint32_t emmhash; ++ ++ if(sctlen < 4) ++ { ++ return; ++ } ++ ++ for(i=0; i+2caid>>8 != 0x0E || !cfg.emu_stream_relay_enabled) ++#endif + switch(selected_api) + { + #if defined(WITH_STAPI) || defined(WITH_STAPI5) +diff -ruNp trunk.patches/module-dvbapi.h trunk/module-dvbapi.h +--- trunk.patches/module-dvbapi.h 2018-04-03 02:48:24.956386446 +0300 ++++ trunk/module-dvbapi.h 2018-04-03 03:20:07.658045369 +0300 +@@ -136,6 +136,7 @@ struct s_ecmpids + int8_t useMultipleIndices; + uint32_t streams; + uint32_t cadata; ++ int16_t pvu_counter; + }; + + typedef struct filter_s +@@ -158,6 +159,9 @@ typedef struct filter_s + uint32_t SlotHandle[10]; + uint32_t BufferHandle[10]; + #endif ++#ifdef WITH_EMU ++ uint32_t cadata; ++#endif + } FILTERTYPE; + + struct s_emmpids +diff -ruNp trunk.patches/module-emulator.c trunk/module-emulator.c +--- trunk.patches/module-emulator.c 1970-01-01 03:00:00.000000000 +0300 ++++ trunk/module-emulator.c 2018-04-03 03:20:07.662045399 +0300 +@@ -0,0 +1,904 @@ ++#define MODULE_LOG_PREFIX "emu" ++ ++#include "globals.h" ++#include "oscam-string.h" ++#include "oscam-config.h" ++#include "oscam-conf-chk.h" ++#include "oscam-time.h" ++#include "oscam-reader.h" ++#include "module-emulator-osemu.h" ++#include "module-emulator-stream.h" ++ ++/* ++ * Readers in OSCam consist of 2 basic parts. ++ * The hardware or the device part. This is where physical smart cards are inserted ++ * and made available to OSCam. ++ * The software or the emulation part. This is where the actual card reading is done, ++ * including ecm and emm processing (i.e emulation of the various cryptosystems). ++ * In the Emu reader, the device part has no meaning, but we have to create it in ++ * order to be compatible with OSCam's reader structure. ++*/ ++ ++/* ++ * Create the Emu "emulation" part. This is of type s_cardsystem. ++ * Similar structures are found in the main sources folder (files reader-xxxxxx.c) ++ * for every cryptosystem supported by OSCam. ++ * Here we read keys from our virtual card (aka the SoftCam.Key file) and we inform ++ * OSCam about them. This is done with the emu_card_info() function. Keep in mind ++ * that Emu holds all its keys to separate structures for faster access. ++ * In addition, ECM and EMM requests are processed here, with the emu_do_ecm() and ++ * emu_do_emm() functions. ++*/ ++ ++#define CS_OK 1 ++#define CS_ERROR 0 ++ ++static uint8_t oneByte = 0x01; ++extern char cs_confdir[128]; ++ ++static void set_hexserial_to_version(struct s_reader *rdr) ++{ ++ char cVersion[32]; ++ uint32_t version = GetOSemuVersion(); ++ uint8_t hversion[2]; ++ memset(hversion, 0, 2); ++ snprintf(cVersion, sizeof(cVersion), "%04d", version); ++ CharToBin(hversion, cVersion, 4); ++ rdr->hexserial[3] = hversion[0]; ++ rdr->hexserial[4] = hversion[1]; ++} ++ ++static void set_prids(struct s_reader *rdr) ++{ ++ int32_t i, j; ++ ++ rdr->nprov = 0; ++ ++ for (i = 0; (i < rdr->emu_auproviders.nfilts) && (rdr->nprov < CS_MAXPROV); i++) ++ { ++ for (j = 0; (j < rdr->emu_auproviders.filts[i].nprids) && (rdr->nprov < CS_MAXPROV); j++) ++ { ++ i2b_buf(4, rdr->emu_auproviders.filts[i].prids[j], rdr->prid[i]); ++ rdr->nprov++; ++ } ++ } ++} ++ ++static void emu_add_entitlement(struct s_reader *rdr, uint16_t caid, uint32_t provid, uint8_t *key, char *keyName, uint32_t keyLength, uint8_t isData) ++{ ++ if (!rdr->ll_entitlements) ++ { ++ rdr->ll_entitlements = ll_create("ll_entitlements"); ++ } ++ ++ S_ENTITLEMENT *item; ++ if (cs_malloc(&item, sizeof(S_ENTITLEMENT))) ++ { ++ // fill item ++ item->caid = caid; ++ item->provid = provid; ++ item->id = 0; ++ item->class = 0; ++ item->start = 0; ++ item->end = 2147472000; ++ item->type = 0; ++ item->isKey = 1; ++ memcpy(item->name, keyName, 8); ++ item->key = key; ++ item->keyLength = keyLength; ++ item->isData = isData; ++ ++ // add item ++ ll_append(rdr->ll_entitlements, item); ++ } ++} ++ ++static void refresh_entitlements(struct s_reader *rdr) ++{ ++ uint32_t i; ++ KeyData *tmpKeyData; ++ ++ cs_clear_entitlement(rdr); ++ ++ for (i = 0; i < CwKeys.keyCount; i++) ++ { ++ emu_add_entitlement(rdr, CwKeys.EmuKeys[i].provider >> 8, CwKeys.EmuKeys[i].provider & 0xFF, ++ CwKeys.EmuKeys[i].key, CwKeys.EmuKeys[i].keyName, CwKeys.EmuKeys[i].keyLength, 0); ++ } ++ ++ for (i = 0; i < ViKeys.keyCount; i++) ++ { ++ emu_add_entitlement(rdr, 0x500, ViKeys.EmuKeys[i].provider, ViKeys.EmuKeys[i].key, ++ ViKeys.EmuKeys[i].keyName, ViKeys.EmuKeys[i].keyLength, 0); ++ } ++ ++ for (i = 0; i < NagraKeys.keyCount; i++) ++ { ++ emu_add_entitlement(rdr, 0x1801, NagraKeys.EmuKeys[i].provider, NagraKeys.EmuKeys[i].key, ++ NagraKeys.EmuKeys[i].keyName, NagraKeys.EmuKeys[i].keyLength, 0); ++ } ++ ++ for (i = 0; i < IrdetoKeys.keyCount; i++) ++ { ++ tmpKeyData = &IrdetoKeys.EmuKeys[i]; ++ do ++ { ++ emu_add_entitlement(rdr, tmpKeyData->provider >> 8, tmpKeyData->provider & 0xFF, ++ tmpKeyData->key, tmpKeyData->keyName, tmpKeyData->keyLength, 0); ++ ++ tmpKeyData = tmpKeyData->nextKey; ++ } ++ while (tmpKeyData != NULL); ++ } ++ ++ for (i = 0; i < NDSKeys.keyCount; i++) ++ { ++ emu_add_entitlement(rdr, NDSKeys.EmuKeys[i].provider, 0, NDSKeys.EmuKeys[i].key, ++ NDSKeys.EmuKeys[i].keyName, NDSKeys.EmuKeys[i].keyLength, 0); ++ } ++ ++ emu_add_entitlement(rdr, 0x090F, 0, viasat_const, "00", 64, 1); ++ emu_add_entitlement(rdr, 0x093E, 0, viasat_const, "00", 64, 1); ++ ++ for (i = 0; i < BissKeys.keyCount; i++) ++ { ++ emu_add_entitlement(rdr, 0x2600, BissKeys.EmuKeys[i].provider, BissKeys.EmuKeys[i].key, ++ BissKeys.EmuKeys[i].keyName, BissKeys.EmuKeys[i].keyLength, 0); ++ } ++ ++ emu_add_entitlement(rdr, 0xFFFF, 0, &oneByte, "00", 1, 1); ++ ++ for (i = 0; i < PowervuKeys.keyCount; i++) ++ { ++ emu_add_entitlement(rdr, 0x0E00, PowervuKeys.EmuKeys[i].provider, PowervuKeys.EmuKeys[i].key, ++ PowervuKeys.EmuKeys[i].keyName, PowervuKeys.EmuKeys[i].keyLength, 0); ++ } ++ ++ for (i = 0; i < DreKeys.keyCount; i++) ++ { ++ emu_add_entitlement(rdr, 0x4AE1, DreKeys.EmuKeys[i].provider, DreKeys.EmuKeys[i].key, ++ DreKeys.EmuKeys[i].keyName, DreKeys.EmuKeys[i].keyLength, 0); ++ } ++ ++ for (i = 0; i < TandbergKeys.keyCount; i++) ++ { ++ emu_add_entitlement(rdr, 0x1010, TandbergKeys.EmuKeys[i].provider, TandbergKeys.EmuKeys[i].key, ++ TandbergKeys.EmuKeys[i].keyName, TandbergKeys.EmuKeys[i].keyLength, 0); ++ } ++} ++ ++static int32_t emu_do_ecm(struct s_reader *rdr, const struct ecm_request_t *er, struct s_ecm_answer *ea) ++{ ++ ++ if (!ProcessECM(rdr, er->ecmlen, er->caid, er->prid, er->ecm, ea->cw, er->srvid, er->pid, &ea->cw_ex)) ++ { ++ return CS_OK; ++ } ++ ++ return CS_ERROR; ++} ++ ++static int32_t emu_do_emm(struct s_reader *rdr, struct emm_packet_t *emm) ++{ ++ uint32_t keysAdded = 0; ++ ++ if (emm->emmlen < 3) ++ { ++ return CS_ERROR; ++ } ++ ++ if (SCT_LEN(emm->emm) > emm->emmlen) ++ { ++ return CS_ERROR; ++ } ++ ++ if (!ProcessEMM(rdr, b2i(2, emm->caid), b2i(4, emm->provid), emm->emm, &keysAdded)) ++ { ++ if (keysAdded > 0) ++ { ++ refresh_entitlements(rdr); ++ } ++ ++ return CS_OK; ++ } ++ ++ return CS_ERROR; ++} ++ ++static int32_t emu_card_info(struct s_reader *rdr) ++{ ++ // Delete keys from Emu's memory ++ clear_emu_keydata(); ++ ++ // Read keys built in the OSCam-Emu binary ++#if !defined(__APPLE__) && !defined(__ANDROID__) ++ read_emu_keymemory(rdr); ++#endif ++ ++ // Read keys from SoftCam.Key file ++ set_emu_keyfile_path(cs_confdir); ++ ++ if (!read_emu_keyfile(rdr, cs_confdir)) ++ { ++ if (read_emu_keyfile(rdr, "/var/keys/")) ++ { ++ set_emu_keyfile_path("/var/keys/"); ++ } ++ } ++ ++ // Load keys from external files (set via the webif or the reader config directly) ++ read_emu_eebin(rdr->extee36, "ee36.bin"); // Read "ee36.bin" ++ read_emu_eebin(rdr->extee56, "ee56.bin"); // Read "ee56.bin" ++ read_emu_deskey(rdr->des_key, rdr->des_key_length); // Read overcrypt keys for DreCrypt ADEC ++ ++ cs_log("Total keys in memory: W:%d V:%d N:%d I:%d S:%d F:%d P:%d D:%d T:%d", \ ++ CwKeys.keyCount, ViKeys.keyCount, NagraKeys.keyCount, \ ++ IrdetoKeys.keyCount, NDSKeys.keyCount, BissKeys.keyCount, \ ++ PowervuKeys.keyCount, DreKeys.keyCount, TandbergKeys.keyCount); ++ ++ // Inform OSCam about all available keys. ++ // This is used for listing the "entitlements" in the webif's reader page. ++ refresh_entitlements(rdr); ++ ++ set_prids(rdr); ++ ++ set_hexserial_to_version(rdr); ++ ++ return CS_OK; ++} ++ ++/* ++static int32_t emu_card_init(struct s_reader *UNUSED(rdr), struct s_ATR *UNUSED(atr)) ++{ ++ return CS_ERROR; ++} ++*/ ++ ++int32_t emu_get_via3_emm_type(EMM_PACKET *ep, struct s_reader *rdr) ++{ ++ uint32_t provid = 0; ++ ++ if(ep->emm[3] == 0x90 && ep->emm[4] == 0x03) ++ { ++ provid = b2i(3, ep->emm+5); ++ provid &=0xFFFFF0; ++ i2b_buf(4, provid, ep->provid); ++ } ++ ++ switch(ep->emm[0]) ++ { ++ case 0x88: ++ ep->type = UNIQUE; ++ memset(ep->hexserial, 0, 8); ++ memcpy(ep->hexserial, ep->emm + 4, 4); ++ rdr_log_dbg(rdr, D_EMM, "UNIQUE"); ++ return 1; ++ ++ case 0x8A: ++ case 0x8B: ++ ep->type = GLOBAL; ++ rdr_log_dbg(rdr, D_EMM, "GLOBAL"); ++ return 1; ++ ++ case 0x8C: ++ case 0x8D: ++ ep->type = SHARED; ++ rdr_log_dbg(rdr, D_EMM, "SHARED (part)"); ++ // We need those packets to pass otherwise we would never ++ // be able to complete EMM reassembly ++ return 1; ++ ++ case 0x8E: ++ ep->type = SHARED; ++ rdr_log_dbg(rdr, D_EMM, "SHARED"); ++ memset(ep->hexserial, 0, 8); ++ memcpy(ep->hexserial, ep->emm + 3, 3); ++ return 1; ++ ++ default: ++ ep->type = UNKNOWN; ++ rdr_log_dbg(rdr, D_EMM, "UNKNOWN"); ++ return 1; ++ } ++} ++ ++int32_t emu_get_ird2_emm_type(EMM_PACKET *ep, struct s_reader *rdr) ++{ ++ int32_t l = (ep->emm[3] & 0x07); ++ int32_t base = (ep->emm[3] >> 3); ++ char dumprdrserial[l * 3], dumpemmserial[l * 3]; ++ ++ switch(l) ++ { ++ ++ case 0: ++ // global emm, 0 bytes addressed ++ ep->type = GLOBAL; ++ rdr_log_dbg(rdr, D_EMM, "GLOBAL base = %02x", base); ++ return 1; ++ ++ case 2: ++ // shared emm, 2 bytes addressed ++ ep->type = SHARED; ++ memset(ep->hexserial, 0, 8); ++ memcpy(ep->hexserial, ep->emm + 4, l); ++ cs_hexdump(1, rdr->hexserial, l, dumprdrserial, sizeof(dumprdrserial)); ++ cs_hexdump(1, ep->hexserial, l, dumpemmserial, sizeof(dumpemmserial)); ++ rdr_log_dbg_sensitive(rdr, D_EMM, "SHARED l = %d ep = {%s} rdr = {%s} base = %02x", l, ++ dumpemmserial, dumprdrserial, base); ++ return 1; ++ ++ case 3: ++ // unique emm, 3 bytes addressed ++ ep->type = UNIQUE; ++ memset(ep->hexserial, 0, 8); ++ memcpy(ep->hexserial, ep->emm + 4, l); ++ cs_hexdump(1, rdr->hexserial, l, dumprdrserial, sizeof(dumprdrserial)); ++ cs_hexdump(1, ep->hexserial, l, dumpemmserial, sizeof(dumpemmserial)); ++ rdr_log_dbg_sensitive(rdr, D_EMM, "UNIQUE l = %d ep = {%s} rdr = {%s} base = %02x", l, ++ dumpemmserial, dumprdrserial, base); ++ return 1; ++ ++ default: ++ ep->type = UNKNOWN; ++ rdr_log_dbg(rdr, D_EMM, "UNKNOWN"); ++ return 1; ++ } ++} ++ ++int32_t emu_get_pvu_emm_type(EMM_PACKET *ep, struct s_reader *rdr) ++{ ++ if(ep->emm[0] == 0x82) ++ { ++ ep->type = UNIQUE; ++ memset(ep->hexserial, 0, 8); ++ memcpy(ep->hexserial, ep->emm + 12, 4); ++ } ++ else ++ { ++ ep->type = UNKNOWN; ++ rdr_log_dbg(rdr, D_EMM, "UNKNOWN"); ++ } ++ return 1; ++} ++ ++int32_t emu_get_dre2_emm_type(EMM_PACKET *ep, struct s_reader *UNUSED(rdr)) ++{ ++ switch (ep->emm[0]) ++ { ++ case 0x82: ++ ep->type = GLOBAL; ++ return 1; ++ ++ case 0x86: ++ ep->type = SHARED; ++ memset(ep->hexserial, 0, 8); ++ ep->hexserial[0] = ep->emm[3]; ++ return 1; ++ ++ //case 0x87: ++ // ep->type = UNIQUE; ++ // return 1; //FIXME: no filling of ep->hexserial ++ ++ case 0x88: ++ ep->type = UNIQUE; ++ return 1; //FIXME: no filling of ep->hexserial ++ ++ case 0x91: ++ ep->type = GLOBAL; ++ return 1; ++ ++ default: ++ ep->type = UNKNOWN; ++ return 1; ++ } ++} ++ ++int32_t emu_get_tan_emm_type(EMM_PACKET *ep, struct s_reader *rdr) ++{ ++ if(ep->emm[0] == 0x82 || ep->emm[0] == 0x83) ++ { ++ ep->type = GLOBAL; ++ } ++ else ++ { ++ ep->type = UNKNOWN; ++ rdr_log_dbg(rdr, D_EMM, "UNKNOWN"); ++ } ++ return 1; ++} ++ ++static int32_t emu_get_emm_type(struct emm_packet_t *ep, struct s_reader *rdr) ++{ ++ switch(b2i(2, ep->caid)>>8) ++ { ++ case 0x05: ++ return emu_get_via3_emm_type(ep, rdr); ++ ++ case 0x06: ++ return emu_get_ird2_emm_type(ep, rdr); ++ ++ case 0x0E: ++ return emu_get_pvu_emm_type(ep, rdr); ++ ++ case 0x4A: ++ return emu_get_dre2_emm_type(ep, rdr); ++ ++ case 0x10: ++ return emu_get_tan_emm_type(ep, rdr); ++ ++ default: ++ break; ++ } ++ ++ return CS_ERROR; ++} ++ ++FILTER* get_emu_prids_for_caid(struct s_reader *rdr, uint16_t caid) ++{ ++ int32_t i; ++ ++ for(i = 0; i < rdr->emu_auproviders.nfilts; i++) ++ { ++ if(caid == rdr->emu_auproviders.filts[i].caid) ++ { ++ return &rdr->emu_auproviders.filts[i]; ++ } ++ } ++ ++ return NULL; ++} ++ ++static int32_t emu_get_via3_emm_filter(struct s_reader *UNUSED(rdr), struct s_csystem_emm_filter **emm_filters, unsigned int *filter_count, uint16_t UNUSED(caid), uint32_t UNUSED(provid)) ++{ ++ if(*emm_filters == NULL) ++ { ++ const unsigned int max_filter_count = 1; ++ ++ if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter))) ++ { return CS_ERROR; } ++ ++ struct s_csystem_emm_filter *filters = *emm_filters; ++ *filter_count = 0; ++ ++ int32_t idx = 0; ++ ++ filters[idx].type = EMM_GLOBAL; ++ filters[idx].enabled = 1; ++ filters[idx].filter[0] = 0x8A; ++ filters[idx].mask[0] = 0xFE; ++ filters[idx].filter[3] = 0x80; ++ filters[idx].mask[3] = 0x80; ++ idx++; ++ ++ *filter_count = idx; ++ } ++ ++ return CS_OK; ++} ++ ++static int32_t emu_get_ird2_emm_filter(struct s_reader* rdr, struct s_csystem_emm_filter **emm_filters, unsigned int *filter_count, uint16_t caid, uint32_t UNUSED(provid)) ++{ ++ uint8_t hexserial[3], prid[4]; ++ FILTER* emu_provids; ++ int8_t have_provid = 0, have_serial = 0; ++ int32_t i; ++ ++ if(GetIrdeto2Hexserial(caid, hexserial)) ++ { have_serial = 1; } ++ ++ emu_provids = get_emu_prids_for_caid(rdr, caid); ++ if(emu_provids != NULL && emu_provids->nprids > 0) ++ { have_provid = 1; } ++ ++ if(*emm_filters == NULL) ++ { ++ const unsigned int max_filter_count = have_serial + (2*(have_provid ? emu_provids->nprids : 0)); ++ if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter))) ++ { return CS_ERROR; } ++ ++ struct s_csystem_emm_filter *filters = *emm_filters; ++ *filter_count = 0; ++ ++ unsigned int idx = 0; ++ ++ if(have_serial) ++ { ++ filters[idx].type = EMM_UNIQUE; ++ filters[idx].enabled = 1; ++ filters[idx].filter[0] = 0x82; ++ filters[idx].mask[0] = 0xFF; ++ filters[idx].filter[1] = 0xFB; ++ filters[idx].mask[1] = 0x07; ++ memcpy(&filters[idx].filter[2], hexserial, 3); ++ memset(&filters[idx].mask[2], 0xFF, 3); ++ idx++; ++ } ++ ++ for(i=0; have_provid && inprids; i++) ++ { ++ i2b_buf(4, emu_provids->prids[i], prid); ++ ++ filters[idx].type = EMM_UNIQUE; ++ filters[idx].enabled = 1; ++ filters[idx].filter[0] = 0x82; ++ filters[idx].mask[0] = 0xFF; ++ filters[idx].filter[1] = 0xFB; ++ filters[idx].mask[1] = 0x07; ++ memcpy(&filters[idx].filter[2], &prid[1], 3); ++ memset(&filters[idx].mask[2], 0xFF, 3); ++ idx++; ++ ++ filters[idx].type = EMM_SHARED; ++ filters[idx].enabled = 1; ++ filters[idx].filter[0] = 0x82; ++ filters[idx].mask[0] = 0xFF; ++ filters[idx].filter[1] = 0xFA; ++ filters[idx].mask[1] = 0x07; ++ memcpy(&filters[idx].filter[2], &prid[1], 2); ++ memset(&filters[idx].mask[2], 0xFF, 2); ++ idx++; ++ } ++ ++ *filter_count = idx; ++ } ++ ++ return CS_OK; ++} ++ ++static int32_t emu_get_pvu_emm_filter(struct s_reader *UNUSED(rdr), struct s_csystem_emm_filter **emm_filters, unsigned int *filter_count, uint16_t UNUSED(caid), uint32_t UNUSED(provid), uint16_t srvid) ++{ ++ uint8_t hexserials[16][4]; ++ int32_t i, count = 0; ++ ++ if(!GetPowervuHexserials(srvid, hexserials, 16, &count)) ++ { return CS_ERROR; } ++ ++ if(*emm_filters == NULL) ++ { ++ const unsigned int max_filter_count = count; ++ if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter))) ++ { return CS_ERROR; } ++ ++ struct s_csystem_emm_filter *filters = *emm_filters; ++ *filter_count = 0; ++ ++ int32_t idx = 0; ++ ++ for(i=0; i>8) ++ { ++ case 0x05: ++ return emu_get_via3_emm_filter(rdr, emm_filters, filter_count, caid, provid); ++ ++ case 0x06: ++ return emu_get_ird2_emm_filter(rdr, emm_filters, filter_count, caid, provid); ++ ++ case 0x0E: ++ return emu_get_pvu_emm_filter(rdr, emm_filters, filter_count, caid, provid, srvid); ++ ++ case 0x4A: ++ return emu_get_dre2_emm_filter(rdr, emm_filters, filter_count, caid, provid); ++ ++ case 0x10: ++ return emu_get_tan_emm_filter(rdr, emm_filters, filter_count, caid, provid); ++ ++ default: ++ break; ++ } ++ ++ return CS_ERROR; ++} ++ ++const struct s_cardsystem reader_emu = ++{ ++ .desc = "emu", ++ .caids = (uint16_t[]){ 0x0D, 0x09, 0x0500, 0x18, 0x06, 0x26, 0xFFFF, 0x0E, 0x4A, 0x10, 0 }, ++ .do_ecm = emu_do_ecm, ++ .do_emm = emu_do_emm, ++ .card_info = emu_card_info, ++ //.card_init = emu_card_init, // apparently this is not needed at all ++ .get_emm_type = emu_get_emm_type, ++ .get_emm_filter = emu_get_emm_filter, // needed to pass checks ++ .get_emm_filter_adv = emu_get_emm_filter_adv, ++}; ++ ++/* ++ * Create the Emu virtual "device" part. This is of type s_cardreader. ++ * Similar structures are found in the csctapi (Card System Card Terminal API) ++ * folder for every IFD (InterFace Device), aka smart card reader. ++ * Since we have no hardware to initialize, we start our Stream Relay server ++ * with the emu_reader_init() function. ++ * At Emu shutdown, we remove keys from memory with the emu_close() function. ++*/ ++ ++#define CR_OK 0 ++#define CR_ERROR 1 ++ ++static int32_t emu_reader_init(struct s_reader *UNUSED(reader)) ++{ ++ int32_t i; ++ char authtmp[128]; ++ ++ if (cfg.emu_stream_relay_enabled && (stream_server_thread_init == 0)) ++ { ++ stream_server_thread_init = 1; ++ SAFE_MUTEX_INIT(&emu_fixed_key_srvid_mutex, NULL); ++ ++ for (i = 0; i < EMU_STREAM_SERVER_MAX_CONNECTIONS; i++) ++ { ++ SAFE_MUTEX_INIT(&emu_fixed_key_data_mutex[i], NULL); ++ ll_emu_stream_delayed_keys[i] = ll_create("ll_emu_stream_delayed_keys"); ++ memset(&emu_fixed_key_data[i], 0, sizeof(emu_stream_client_key_data)); ++ } ++ ++ start_thread("stream_key_delayer", stream_key_delayer, NULL, NULL, 1, 1); ++ cs_log("Stream key delayer initialized"); ++ ++ cs_strncpy(emu_stream_source_host, cfg.emu_stream_source_host, sizeof(emu_stream_source_host)); ++ emu_stream_source_port = cfg.emu_stream_source_port; ++ emu_stream_relay_port = cfg.emu_stream_relay_port; ++ emu_stream_emm_enabled = cfg.emu_stream_emm_enabled; ++ ++ if (cfg.emu_stream_source_auth_user && cfg.emu_stream_source_auth_password) ++ { ++ snprintf(authtmp, sizeof(authtmp), "%s:%s", cfg.emu_stream_source_auth_user, cfg.emu_stream_source_auth_password); ++ b64encode(authtmp, strlen(authtmp), &emu_stream_source_auth); ++ } ++ else ++ { ++ NULLFREE(emu_stream_source_auth); ++ } ++ ++ start_thread("stream_server", stream_server, NULL, NULL, 1, 1); ++ cs_log("Stream relay server initialized"); ++ } ++ ++ return CR_OK; ++} ++ ++static int32_t emu_close(struct s_reader *UNUSED(reader)) ++{ ++ cs_log("Reader is shutting down"); ++ ++ // Delete keys from Emu's memory ++ clear_emu_keydata(); ++ ++ return CR_OK; ++} ++ ++static int32_t emu_get_status(struct s_reader *UNUSED(reader), int32_t *in) { *in = 1; return CR_OK; } ++static int32_t emu_activate(struct s_reader *UNUSED(reader), struct s_ATR *UNUSED(atr)) { return CR_OK; } ++static int32_t emu_transmit(struct s_reader *UNUSED(reader), uint8_t *UNUSED(buffer), uint32_t UNUSED(size), uint32_t UNUSED(expectedlen), uint32_t UNUSED(delay), uint32_t UNUSED(timeout)) { return CR_OK; } ++static int32_t emu_receive(struct s_reader *UNUSED(reader), uint8_t *UNUSED(buffer), uint32_t UNUSED(size), uint32_t UNUSED(delay), uint32_t UNUSED(timeout)) { return CR_OK; } ++static int32_t emu_write_settings(struct s_reader *UNUSED(reader), struct s_cardreader_settings *UNUSED(s)) { return CR_OK; } ++static int32_t emu_card_write(struct s_reader *UNUSED(pcsc_reader),const uchar *UNUSED(buf) ,uint8_t *UNUSED(cta_res), uint16_t *UNUSED(cta_lr),int32_t UNUSED(l)) { return CR_OK; } ++static int32_t emu_set_protocol(struct s_reader *UNUSED(rdr),uint8_t *UNUSED(params),uint32_t *UNUSED(length), uint32_t UNUSED(len_request)) { return CR_OK; } ++ ++const struct s_cardreader cardreader_emu = ++{ ++ .desc = "emu", ++ .typ = R_EMU, ++ .skip_extra_atr_parsing = 1, ++ .reader_init = emu_reader_init, ++ .get_status = emu_get_status, ++ .activate = emu_activate, ++ .transmit = emu_transmit, ++ .receive = emu_receive, ++ .close = emu_close, ++ .write_settings = emu_write_settings, ++ .card_write = emu_card_write, ++ .set_protocol = emu_set_protocol, ++}; ++ ++void add_emu_reader(void) ++{ ++ // This function is called inside oscam.c and creates an emu [reader] with default ++ // settings in oscam.server file. If an emu [reader] already exists, it uses that. ++ ++ LL_ITER itr; ++ struct s_reader *rdr; ++ int8_t haveEmuReader = 0; ++ char *emuName = "emulator"; ++ char *ctab, *ftab, *emu_auproviders; ++ ++ // Check if emu [reader] entry already exists in oscam.server file and get it ++ itr = ll_iter_create(configured_readers); ++ while ((rdr = ll_iter_next(&itr))) ++ { ++ if (rdr->typ == R_EMU) ++ { ++ haveEmuReader = 1; ++ break; ++ } ++ } ++ ++ rdr = NULL; ++ ++ // If there's no emu [reader] in oscam.server, create one with default settings ++ if (!haveEmuReader) ++ { ++ if (!cs_malloc(&rdr, sizeof(struct s_reader))) ++ { ++ return; ++ } ++ ++ reader_set_defaults(rdr); ++ ++ rdr->enable = 1; ++ rdr->typ = R_EMU; ++ strncpy(rdr->label, emuName, strlen(emuName)); ++ strncpy(rdr->device, emuName, strlen(emuName)); ++ ++ // CAIDs ++ ctab = strdup("090F,0500,1801,0604,2600,FFFF,0E00,4AE1,1010"); ++ chk_caidtab(ctab, &rdr->ctab); ++ NULLFREE(ctab); ++ ++ // Idents ++ ftab = strdup("090F:000000;" ++ "0500:000000,023800,021110,007400,007800;" ++ "1801:000000,007301,001101,002111;" ++ "0604:000000;" ++ "2600:000000;" ++ "FFFF:000000;" ++ "0E00:000000;" ++ "4AE1:000011,000014,0000FE;" ++ "1010:000000;" ++ ); ++ chk_ftab(ftab, &rdr->ftab); ++ NULLFREE(ftab); ++ ++ // AU providers ++ emu_auproviders = strdup("0604:010200;0E00:000000;4AE1:000011,000014,0000FE;1010:000000;"); ++ chk_ftab(emu_auproviders, &rdr->emu_auproviders); ++ NULLFREE(emu_auproviders); ++ ++ // EMM cache ++ rdr->cachemm = 2; ++ rdr->rewritemm = 1; ++ rdr->logemm = 2; ++ rdr->deviceemm = 1; ++ ++ // User group ++ rdr->grp = 0x1ULL; ++ ++ // Add the "device" part to our emu reader ++ rdr->crdr = &cardreader_emu; ++ ++ reader_fixups_fn(rdr); ++ ll_append(configured_readers, rdr); ++ } ++ ++ // Set DVB Api delayer option ++#ifdef HAVE_DVBAPI ++ if (cfg.dvbapi_enabled && cfg.dvbapi_delayer < 60) ++ { ++ cfg.dvbapi_delayer = 60; ++ } ++#endif ++ ++ cs_log("OSCam-Emu version %d", GetOSemuVersion()); ++} +diff -ruNp trunk.patches/module-emulator-osemu.c trunk/module-emulator-osemu.c +--- trunk.patches/module-emulator-osemu.c 1970-01-01 03:00:00.000000000 +0300 ++++ trunk/module-emulator-osemu.c 2018-04-03 03:20:07.658045369 +0300 +@@ -0,0 +1,6488 @@ ++#define MODULE_LOG_PREFIX "emu" ++ ++#include "globals.h" ++#include "ffdecsa/ffdecsa.h" ++#include "cscrypt/bn.h" ++#include "cscrypt/des.h" ++#include "cscrypt/idea.h" ++#include "cscrypt/md5.h" ++ ++#ifdef WITH_EMU ++#include "oscam-aes.h" ++#include "oscam-string.h" ++#include "oscam-config.h" ++#include "oscam-conf-chk.h" ++#include "oscam-time.h" ++#include "module-newcamd-des.h" ++#include "reader-dre-common.h" ++// from reader-viaccess.c: ++void hdSurEncPhase1_D2_0F_11(uint8_t *CWs); ++void hdSurEncPhase2_D2_0F_11(uint8_t *CWs); ++void hdSurEncPhase1_D2_13_15(uint8_t *cws); ++void hdSurEncPhase2_D2_13_15(uint8_t *cws); ++#else ++#include "cscrypt/viades.h" ++#include "via3surenc.h" ++#include "dre2overcrypt.h" ++#endif ++ ++#include "module-emulator-osemu.h" ++#include "module-emulator-stream.h" ++ ++// Version info ++uint32_t GetOSemuVersion(void) ++{ ++ return atoi("$Version: 769 $"+10); ++} ++ ++/* ++ * Key DB ++ * ++ * The Emu reader gets keys from the OSCcam-Emu binary and the "SoftCam.Key" file. ++ * ++ * The keys are stored in structures of type "KeyDataContainer", one per CAS. Each ++ * container points to a dynamically allocated array of type "KeyData", which holds ++ * the actual keys. The array initially holds up to 64 keys (64 * KeyData), and it ++ * is expanded by 16 every time it's filled with keys. The "KeyDataContainer" also ++ * includes info about the number of keys it contains ("KeyCount") and the maximum ++ * number of keys it can store ("KeyMax"). ++ * ++ * The "KeyData" structure on the other hand, stores the actual key information, ++ * including the "identifier", "provider", "keyName", "key" and "keyLength". There ++ * is also a "nextKey" pointer to a similar "KeyData" structure which is only used ++ * for Irdeto multiple keys, in a linked list style structure. For all other CAS, ++ * the "nextKey" is a "NULL" pointer. ++ * ++ * For storing keys, the "SetKey" function is used. Duplicate keys are not allowed. ++ * When storing a key that is already present in the database, its "key" value is ++ * updated with the new one. For reading keys from the database, the "FindKey" ++ * function is used. To delete all keys in a container, the "DeleteKeysInContainer" ++ * function can be called. ++*/ ++ ++static char *emu_keyfile_path = NULL; ++ ++void set_emu_keyfile_path(const char *path) ++{ ++ if(emu_keyfile_path != NULL) { ++ free(emu_keyfile_path); ++ } ++ emu_keyfile_path = (char*)malloc(strlen(path)+1); ++ if(emu_keyfile_path == NULL) { ++ return; ++ } ++ memcpy(emu_keyfile_path, path, strlen(path)); ++ emu_keyfile_path[strlen(path)] = 0; ++} ++ ++int32_t CharToBin(uint8_t *out, const char *in, uint32_t inLen) ++{ ++ uint32_t i, tmp; ++ for(i=0; i= fileNameLen && strcasecmp(path+pathLength-fileNameLen, EMU_KEY_FILENAME) == 0) { ++ // cut file name ++ path[pathLength-fileNameLen] = '\0'; ++ } ++ ++ pathLength = strlen(path); ++ if(path[pathLength-1] == '/' || path[pathLength-1] == '\\') { ++ // cut trailing / ++ path[pathLength-1] = '\0'; ++ } ++ ++ pDir = opendir(path); ++ if (pDir == NULL) { ++ cs_log("Cannot open key file path: %s", path); ++ free(path); ++ return; ++ } ++ ++ while((pDirent = readdir(pDir)) != NULL) { ++ if(strcasecmp(pDirent->d_name, EMU_KEY_FILENAME) == 0) { ++ strncpy(filename, pDirent->d_name, sizeof(filename)); ++ break; ++ } ++ } ++ closedir(pDir); ++ ++ if(pDirent == NULL) { ++ strncpy(filename, EMU_KEY_FILENAME, sizeof(filename)); ++ } ++ ++ pathLength = strlen(path)+1+strlen(filename)+1; ++ filepath = (char*)malloc(pathLength); ++ if(filepath == NULL) { ++ free(path); ++ return; ++ } ++ snprintf(filepath, pathLength, "%s/%s", path, filename); ++ free(path); ++ ++ cs_log("Writing key file: %s", filepath); ++ ++ file = fopen(filepath, "a"); ++ free(filepath); ++ if(file == NULL) { ++ return; ++ } ++ ++ Date2Str(dateText, sizeof(dateText), 0, 1); ++ ++ keyValue = (char*)malloc((keyLength*2)+1); ++ if(keyValue == NULL) { ++ fclose(file); ++ return; ++ } ++ cs_hexdump(0, key, keyLength, keyValue, (keyLength*2)+1); ++ ++ if(comment) ++ { ++ snprintf(line, sizeof(line), "\n%c %.4X %s %s ; added by OSEmu %s %s\n", identifier, provider, keyName, keyValue, dateText, comment); ++ } ++ else ++ { ++ snprintf(line, sizeof(line), "\n%c %.4X %s %s ; added by OSEmu %s\n", identifier, provider, keyName, keyValue, dateText); ++ } ++ ++ cs_log("Key written: %c %.4X %s %s", identifier, provider, keyName, keyValue); ++ ++ free(keyValue); ++ ++ fwrite(line, strlen(line), 1, file); ++ fclose(file); ++} ++ ++int32_t SetKey(char identifier, uint32_t provider, char *keyName, uint8_t *orgKey, uint32_t keyLength, ++ uint8_t writeKey, char *comment, struct s_reader *rdr) ++{ ++ uint32_t i, j; ++ uint8_t *tmpKey = NULL; ++ KeyDataContainer *KeyDB; ++ KeyData *tmpKeyData, *newKeyData; ++ identifier = (char)toupper((int)identifier); ++ ++ KeyDB = GetKeyContainer(identifier); ++ if(KeyDB == NULL) { ++ return 0; ++ } ++ ++ keyName = strtoupper(keyName); ++ ++ if (identifier == 'F') // Prepare BISS keys before saving to the db ++ { ++ // Convert legacy BISS "00" & "01" keynames ++ if (0 == strcmp(keyName, "00") || 0 == strcmp(keyName, "01")) ++ { ++ keyName = "00000000"; ++ } ++ ++ // All keyNames should have a length of 8 after converting ++ if (strlen(keyName) != 8) ++ { ++ cs_log("WARNING: Wrong key format in %s: F %08X %s", EMU_KEY_FILENAME, provider, keyName); ++ return 0; ++ } ++ ++ // Verify date-coded keyName (if enabled), ignoring old (expired) keys ++ if (rdr->emu_datecodedenabled) ++ { ++ char timeStr[9]; ++ Date2Str(timeStr, sizeof(timeStr), 0, 3); ++ ++ // Reject old date-coded keys, but allow our "00000000" evergreen label ++ if (strcmp("00000000", keyName) != 0 && strcmp(timeStr, keyName) >= 0) ++ { ++ return 0; ++ } ++ } ++ } ++ ++ // fix checksum for BISS keys with a length of 6 ++ if (identifier == 'F' && keyLength == 6) ++ { ++ tmpKey = (uint8_t*)malloc(8*sizeof(uint8_t)); ++ if(tmpKey == NULL) { ++ return 0; ++ } ++ ++ tmpKey[0] = orgKey[0]; ++ tmpKey[1] = orgKey[1]; ++ tmpKey[2] = orgKey[2]; ++ tmpKey[3] = ((orgKey[0] + orgKey[1] + orgKey[2]) & 0xff); ++ tmpKey[4] = orgKey[3]; ++ tmpKey[5] = orgKey[4]; ++ tmpKey[6] = orgKey[5]; ++ tmpKey[7] = ((orgKey[3] + orgKey[4] + orgKey[5]) & 0xff); ++ ++ keyLength = 8; ++ } ++ else // All keys with a length of 8, including BISS ++ { ++ tmpKey = (uint8_t*)malloc(keyLength*sizeof(uint8_t)); ++ if(tmpKey == NULL) { ++ return 0; ++ } ++ ++ memcpy(tmpKey, orgKey, keyLength); ++ } ++ ++ // fix patched mgcamd format for Irdeto ++ if(identifier == 'I' && provider < 0xFFFF) { ++ provider = provider<<8; ++ } ++ ++ // key already exists on db, update its value ++ for(i=0; ikeyCount; i++) { ++ ++ if(KeyDB->EmuKeys[i].provider != provider) { ++ continue; ++ } ++ ++ // Don't match keyName (i.e. expiration date) for BISS ++ if(identifier != 'F' && strcmp(KeyDB->EmuKeys[i].keyName, keyName)) { ++ continue; ++ } ++ ++ // allow multiple keys for Irdeto ++ if(identifier == 'I') ++ { ++ // reject duplicates ++ tmpKeyData = &KeyDB->EmuKeys[i]; ++ do { ++ if(memcmp(tmpKeyData->key, tmpKey, tmpKeyData->keyLength < keyLength ? tmpKeyData->keyLength : keyLength) == 0) { ++ free(tmpKey); ++ return 0; ++ } ++ tmpKeyData = tmpKeyData->nextKey; ++ } ++ while(tmpKeyData != NULL); ++ ++ // add new key ++ newKeyData = (KeyData*)malloc(sizeof(KeyData)); ++ if(newKeyData == NULL) { ++ free(tmpKey); ++ return 0; ++ } ++ newKeyData->identifier = identifier; ++ newKeyData->provider = provider; ++ if(strlen(keyName) < EMU_MAX_CHAR_KEYNAME) { ++ strncpy(newKeyData->keyName, keyName, EMU_MAX_CHAR_KEYNAME); ++ } ++ else { ++ memcpy(newKeyData->keyName, keyName, EMU_MAX_CHAR_KEYNAME); ++ } ++ newKeyData->keyName[EMU_MAX_CHAR_KEYNAME-1] = 0; ++ newKeyData->key = tmpKey; ++ newKeyData->keyLength = keyLength; ++ newKeyData->nextKey = NULL; ++ ++ tmpKeyData = &KeyDB->EmuKeys[i]; ++ j = 0; ++ while(tmpKeyData->nextKey != NULL) { ++ if(j == 0xFE) ++ { ++ break; ++ } ++ tmpKeyData = tmpKeyData->nextKey; ++ j++; ++ } ++ if(tmpKeyData->nextKey) ++ { ++ NULLFREE(tmpKeyData->nextKey->key); ++ NULLFREE(tmpKeyData->nextKey); ++ } ++ tmpKeyData->nextKey = newKeyData; ++ ++ if(writeKey) { ++ WriteKeyToFile(identifier, provider, keyName, tmpKey, keyLength, comment); ++ } ++ } ++ else // identifier != 'I' ++ { ++ free(KeyDB->EmuKeys[i].key); ++ KeyDB->EmuKeys[i].key = tmpKey; ++ KeyDB->EmuKeys[i].keyLength = keyLength; ++ ++ if (identifier == 'F') // Update keyName (i.e. expiration date) for BISS ++ { ++ strncpy(KeyDB->EmuKeys[i].keyName, keyName, EMU_MAX_CHAR_KEYNAME); ++ } ++ ++ if(writeKey) { ++ WriteKeyToFile(identifier, provider, keyName, tmpKey, keyLength, comment); ++ } ++ } ++ ++ return 1; ++ } ++ ++ // key does not exist on db ++ if(KeyDB->keyCount+1 > KeyDB->keyMax) ++ { ++ if(KeyDB->EmuKeys == NULL) // db is empty ++ { ++ KeyDB->EmuKeys = (KeyData*)malloc(sizeof(KeyData)*(KeyDB->keyMax+64)); ++ if(KeyDB->EmuKeys == NULL) { ++ free(tmpKey); ++ return 0; ++ } ++ KeyDB->keyMax+=64; ++ } ++ else // db is full, expand it ++ { ++ tmpKeyData = (KeyData*)realloc(KeyDB->EmuKeys, sizeof(KeyData)*(KeyDB->keyMax+16)); ++ if(tmpKeyData == NULL) { ++ free(tmpKey); ++ return 0; ++ } ++ KeyDB->EmuKeys = tmpKeyData; ++ KeyDB->keyMax+=16; ++ } ++ } ++ ++ KeyDB->EmuKeys[KeyDB->keyCount].identifier = identifier; ++ KeyDB->EmuKeys[KeyDB->keyCount].provider = provider; ++ if(strlen(keyName) < EMU_MAX_CHAR_KEYNAME) { ++ strncpy(KeyDB->EmuKeys[KeyDB->keyCount].keyName, keyName, EMU_MAX_CHAR_KEYNAME); ++ } ++ else { ++ memcpy(KeyDB->EmuKeys[KeyDB->keyCount].keyName, keyName, EMU_MAX_CHAR_KEYNAME); ++ } ++ KeyDB->EmuKeys[KeyDB->keyCount].keyName[EMU_MAX_CHAR_KEYNAME-1] = 0; ++ KeyDB->EmuKeys[KeyDB->keyCount].key = tmpKey; ++ KeyDB->EmuKeys[KeyDB->keyCount].keyLength = keyLength; ++ KeyDB->EmuKeys[KeyDB->keyCount].nextKey = NULL; ++ KeyDB->keyCount++; ++ ++ if(writeKey) { ++ WriteKeyToFile(identifier, provider, keyName, tmpKey, keyLength, comment); ++ } ++ ++ return 1; ++} ++ ++int32_t FindKey(char identifier, uint32_t provider, uint32_t providerIgnoreMask, char *keyName, uint8_t *key, ++ uint32_t maxKeyLength, uint8_t isCriticalKey, uint32_t keyRef, uint8_t matchLength, uint32_t *getProvider) ++{ ++ uint32_t i; ++ uint16_t j; ++ uint8_t provider_matching_key_count = 0; ++ KeyDataContainer *KeyDB; ++ KeyData *tmpKeyData; ++ ++ KeyDB = GetKeyContainer(identifier); ++ if(KeyDB == NULL) { ++ return 0; ++ } ++ ++ for(i=0; ikeyCount; i++) { ++ ++ if((KeyDB->EmuKeys[i].provider & ~providerIgnoreMask) != provider) { ++ continue; ++ } ++ ++ // Don't match keyName (i.e. expiration date) for BISS ++ if(identifier != 'F' && strcmp(KeyDB->EmuKeys[i].keyName, keyName)) { ++ continue; ++ } ++ ++ //matchLength cannot be used when multiple keys are allowed ++ //for a single provider/keyName combination. ++ //Currently this is only the case for Irdeto keys. ++ if(matchLength && KeyDB->EmuKeys[i].keyLength != maxKeyLength) { ++ continue; ++ } ++ ++ if(providerIgnoreMask) { ++ if(provider_matching_key_count < keyRef) { ++ provider_matching_key_count++; ++ continue; ++ } ++ else { ++ keyRef = 0; ++ } ++ } ++ ++ tmpKeyData = &KeyDB->EmuKeys[i]; ++ ++ j = 0; ++ while(jnextKey != NULL) { ++ j++; ++ tmpKeyData = tmpKeyData->nextKey; ++ } ++ ++ if(j == keyRef) { ++ memcpy(key, tmpKeyData->key, tmpKeyData->keyLength > maxKeyLength ? maxKeyLength : tmpKeyData->keyLength); ++ if(tmpKeyData->keyLength < maxKeyLength) { ++ memset(key+tmpKeyData->keyLength, 0, maxKeyLength - tmpKeyData->keyLength); ++ } ++ ++ if (identifier == 'F') // Report the keyName of found key back to BissGetKey() ++ { ++ strncpy(keyName, tmpKeyData->keyName, EMU_MAX_CHAR_KEYNAME); ++ } ++ ++ if(getProvider != NULL) { ++ (*getProvider) = tmpKeyData->provider; ++ } ++ return 1; ++ } ++ else { ++ break; ++ } ++ } ++ ++ if (isCriticalKey) ++ { ++ cs_log("Key not found: %c %X %s", identifier, provider, keyName); ++ } ++ ++ return 0; ++} ++ ++static int32_t UpdateKey(char identifier, uint32_t provider, char *keyName, uint8_t *key, uint32_t keyLength, uint8_t writeKey, char *comment) ++{ ++ uint32_t keyRef = 0; ++ uint8_t *tmpKey = (uint8_t*)malloc(sizeof(uint8_t)*keyLength); ++ if(tmpKey == NULL) ++ { ++ return 0; ++ } ++ ++ while(FindKey(identifier, provider, 0, keyName, tmpKey, keyLength, 0, keyRef, 0, NULL)) ++ { ++ if(memcmp(tmpKey, key, keyLength) == 0) ++ { ++ free(tmpKey); ++ return 0; ++ } ++ ++ keyRef++; ++ } ++ ++ free(tmpKey); ++ return SetKey(identifier, provider, keyName, key, keyLength, writeKey, comment, NULL); ++} ++ ++static int32_t UpdateKeysByProviderMask(char identifier, uint32_t provider, uint32_t providerIgnoreMask, char *keyName, uint8_t *key, ++ uint32_t keyLength, char *comment) ++{ ++ int32_t ret = 0; ++ uint32_t foundProvider = 0; ++ uint32_t keyRef = 0; ++ uint8_t *tmpKey = (uint8_t*)malloc(sizeof(uint8_t)*keyLength); ++ if(tmpKey == NULL) ++ { ++ return 0; ++ } ++ ++ while(FindKey(identifier, (provider & ~providerIgnoreMask), providerIgnoreMask, keyName, tmpKey, keyLength, 0, keyRef, 0, &foundProvider)) ++ { ++ keyRef++; ++ ++ if(memcmp(tmpKey, key, keyLength) == 0) ++ { ++ continue; ++ } ++ ++ if(SetKey(identifier, foundProvider, keyName, key, keyLength, 1, comment, NULL)) ++ { ++ ret = 1; ++ } ++ } ++ ++ free(tmpKey); ++ return ret; ++} ++ ++int32_t DeleteKeysInContainer(char identifier) ++{ ++ // Deletes all keys stored in memory for the specified identifier, ++ // but keeps the container itself, re-initialized at { NULL, 0, 0 }. ++ // Returns the count of deleted keys. ++ ++ uint32_t oldKeyCount, i; ++ KeyData *tmpKeyData; ++ KeyDataContainer *KeyDB = GetKeyContainer(identifier); ++ ++ if (KeyDB == NULL || KeyDB->EmuKeys == NULL || KeyDB->keyCount == 0) ++ { ++ return 0; ++ } ++ ++ for (i = 0; i < KeyDB->keyCount; i++) ++ { ++ // For Irdeto multiple keys only (linked list structure) ++ while (KeyDB->EmuKeys[i].nextKey != NULL) ++ { ++ tmpKeyData = KeyDB->EmuKeys[i].nextKey; ++ KeyDB->EmuKeys[i].nextKey = KeyDB->EmuKeys[i].nextKey->nextKey; ++ free(tmpKeyData->key); // Free key ++ free(tmpKeyData); // Free KeyData ++ } ++ ++ // For single keys (all identifiers, including Irdeto) ++ free(KeyDB->EmuKeys[i].key); // Free key ++ } ++ ++ // Free the KeyData array ++ NULLFREE(KeyDB->EmuKeys); ++ oldKeyCount = KeyDB->keyCount; ++ KeyDB->keyCount = 0; ++ KeyDB->keyMax = 0; ++ ++ return oldKeyCount; ++} ++ ++void clear_emu_keydata(void) ++{ ++ uint32_t total = 0; ++ ++ total = CwKeys.keyCount; ++ total += ViKeys.keyCount; ++ total += NagraKeys.keyCount; ++ total += IrdetoKeys.keyCount; ++ total += NDSKeys.keyCount; ++ total += BissKeys.keyCount; ++ total += PowervuKeys.keyCount; ++ total += DreKeys.keyCount; ++ total += TandbergKeys.keyCount; ++ ++ if (total != 0) ++ { ++ cs_log("Freeing keys in memory: W:%d V:%d N:%d I:%d S:%d F:%d P:%d D:%d T:%d", \ ++ CwKeys.keyCount, ViKeys.keyCount, NagraKeys.keyCount, \ ++ IrdetoKeys.keyCount, NDSKeys.keyCount, BissKeys.keyCount, \ ++ PowervuKeys.keyCount, DreKeys.keyCount, TandbergKeys.keyCount); ++ ++ DeleteKeysInContainer('W'); ++ DeleteKeysInContainer('V'); ++ DeleteKeysInContainer('N'); ++ DeleteKeysInContainer('I'); ++ DeleteKeysInContainer('S'); ++ DeleteKeysInContainer('F'); ++ DeleteKeysInContainer('P'); ++ DeleteKeysInContainer('D'); ++ DeleteKeysInContainer('T'); ++ } ++} ++ ++uint8_t read_emu_keyfile(struct s_reader *rdr, const char *opath) ++{ ++ char line[1200], keyName[EMU_MAX_CHAR_KEYNAME], keyString[1026]; ++ uint32_t pathLength, provider, keyLength; ++ uint8_t *key; ++ struct dirent *pDirent; ++ DIR *pDir; ++ char *path, *filepath, filename[EMU_KEY_FILENAME_MAX_LEN+1]; ++ FILE *file = NULL; ++ char identifier; ++ uint8_t fileNameLen = strlen(EMU_KEY_FILENAME); ++ ++ pathLength = strlen(opath); ++ path = (char*)malloc(pathLength+1); ++ if(path == NULL) { ++ return 0; ++ } ++ strncpy(path, opath, pathLength+1); ++ ++ pathLength = strlen(path); ++ if(pathLength >= fileNameLen && strcasecmp(path+pathLength-fileNameLen, EMU_KEY_FILENAME) == 0) { ++ // cut file name ++ path[pathLength-fileNameLen] = '\0'; ++ } ++ ++ pathLength = strlen(path); ++ if(path[pathLength-1] == '/' || path[pathLength-1] == '\\') { ++ // cut trailing / ++ path[pathLength-1] = '\0'; ++ } ++ ++ pDir = opendir(path); ++ if (pDir == NULL) { ++ cs_log("Cannot open key file path: %s", path); ++ free(path); ++ return 0; ++ } ++ ++ while((pDirent = readdir(pDir)) != NULL) { ++ if(strcasecmp(pDirent->d_name, EMU_KEY_FILENAME) == 0) { ++ strncpy(filename, pDirent->d_name, sizeof(filename)); ++ break; ++ } ++ } ++ closedir(pDir); ++ ++ if(pDirent == NULL) { ++ cs_log("Key file not found in: %s", path); ++ free(path); ++ return 0; ++ } ++ ++ pathLength = strlen(path)+1+strlen(filename)+1; ++ filepath = (char*)malloc(pathLength); ++ if(filepath == NULL) { ++ free(path); ++ return 0; ++ } ++ snprintf(filepath, pathLength, "%s/%s", path, filename); ++ free(path); ++ ++ cs_log("Reading key file: %s", filepath); ++ ++ file = fopen(filepath, "r"); ++ free(filepath); ++ if(file == NULL) { ++ return 0; ++ } ++ ++ set_emu_keyfile_path(opath); ++ ++ while(fgets(line, 1200, file)) { ++ if(sscanf(line, "%c %8x %11s %1024s", &identifier, &provider, keyName, keyString) != 4) { ++ continue; ++ } ++ ++ keyLength = strlen(keyString)/2; ++ key = (uint8_t*)malloc(keyLength); ++ if(key == NULL) { ++ fclose(file); ++ return 0; ++ } ++ ++ if (CharToBin(key, keyString, strlen(keyString))) // Conversion OK ++ { ++ SetKey(identifier, provider, keyName, key, keyLength, 0, NULL, rdr); ++ } ++ else // Non-hex characters in keyString ++ { ++ if ((identifier != ';' && identifier != '#' && // Skip warning for comments, etc. ++ identifier != '=' && identifier != '-' && ++ identifier != ' ') && ++ !(identifier == 'F' && 0 == strncmp(keyString, "XXXXXXXXXXXX", 12))) // Skip warning for BISS 'Example key' lines ++ { ++ // Alert user regarding faulty line ++ cs_log("WARNING: non-hex value in %s at %c %04X %s %s", EMU_KEY_FILENAME, identifier, provider, keyName, keyString); ++ } ++ } ++ free(key); ++ } ++ fclose(file); ++ ++ return 1; ++} ++ ++#if !defined(__APPLE__) && !defined(__ANDROID__) ++extern uint8_t SoftCamKey_Data[] __asm__("_binary_SoftCam_Key_start"); ++extern uint8_t SoftCamKey_DataEnd[] __asm__("_binary_SoftCam_Key_end"); ++ ++void read_emu_keymemory(struct s_reader *rdr) ++{ ++ char *keyData, *line, *saveptr, keyName[EMU_MAX_CHAR_KEYNAME], keyString[1026]; ++ uint32_t provider, keyLength; ++ uint8_t *key; ++ char identifier; ++ ++ keyData = (char*)malloc(SoftCamKey_DataEnd-SoftCamKey_Data+1); ++ if(keyData == NULL) { ++ return; ++ } ++ memcpy(keyData, SoftCamKey_Data, SoftCamKey_DataEnd-SoftCamKey_Data); ++ keyData[SoftCamKey_DataEnd-SoftCamKey_Data] = 0x00; ++ ++ line = strtok_r(keyData, "\n", &saveptr); ++ while(line != NULL) { ++ if(sscanf(line, "%c %8x %11s %1024s", &identifier, &provider, keyName, keyString) != 4) { ++ line = strtok_r(NULL, "\n", &saveptr); ++ continue; ++ } ++ keyLength = strlen(keyString)/2; ++ key = (uint8_t*)malloc(keyLength); ++ if(key == NULL) { ++ free(keyData); ++ return; ++ } ++ ++ if (CharToBin(key, keyString, strlen(keyString))) // Conversion OK ++ { ++ SetKey(identifier, provider, keyName, key, keyLength, 0, NULL, rdr); ++ } ++ else // Non-hex characters in keyString ++ { ++ if ((identifier != ';' && identifier != '#' && // Skip warning for comments, etc. ++ identifier != '=' && identifier != '-' && ++ identifier != ' ') && ++ !(identifier == 'F' && 0 == strncmp(keyString, "XXXXXXXXXXXX", 12))) // Skip warning for BISS 'Example key' lines ++ { ++ // Alert user regarding faulty line ++ cs_log("WARNING: non-hex value in internal keyfile at %c %04X %s %s", identifier, provider, keyName, keyString); ++ } ++ } ++ free(key); ++ line = strtok_r(NULL, "\n", &saveptr); ++ } ++ free(keyData); ++} ++#endif ++ ++void read_emu_eebin(const char *path, const char *name) ++{ ++ char tmp[256]; ++ FILE *file = NULL; ++ uint8_t i, buffer[64][32], dummy[2][32]; ++ uint32_t prvid; ++ ++ // Set path ++ if (path != NULL) ++ { ++ snprintf(tmp, 256, "%s%s", path, name); ++ } ++ else // No path set, use SoftCam.Keys's path ++ { ++ snprintf(tmp, 256, "%s%s", emu_keyfile_path, name); ++ } ++ ++ // Read file to buffer ++ if ((file = fopen(tmp, "rb")) != NULL) ++ { ++ cs_log("Reading key file: %s", tmp); ++ ++ if (fread(buffer, 1, sizeof(buffer), file) != sizeof(buffer)) ++ { ++ cs_log("Corrupt key file: %s", tmp); ++ fclose(file); ++ return; ++ } ++ ++ fclose(file); ++ } ++ else ++ { ++ if (path != NULL) ++ { ++ cs_log("Cannot open key file: %s", tmp); ++ } ++ ++ return; ++ } ++ ++ // Save keys to db ++ memset(dummy[0], 0x00, 32); ++ memset(dummy[1], 0xFF, 32); ++ prvid = (strncmp(name, "ee36.bin", 9) == 0) ? 0x4AE111 : 0x4AE114; ++ ++ for (i = 0; i < 32; i++) // Set "3B" type keys ++ { ++ // Write keys if they have "real" values ++ if ((memcmp(buffer[i], dummy[0], 32) !=0) && (memcmp(buffer[i], dummy[1], 32) != 0)) ++ { ++ snprintf(tmp, 5, "3B%02X", i); ++ SetKey('D', prvid, tmp, buffer[i], 32, 0, NULL, NULL); ++ } ++ } ++ ++ for (i = 0; i < 32; i++) // Set "56" type keys ++ { ++ // Write keys if they have "real" values ++ if ((memcmp(buffer[32 + i], dummy[0], 32) !=0) && (memcmp(buffer[32 + i], dummy[1], 32) != 0)) ++ { ++ snprintf(tmp, 5, "56%02X", i); ++ SetKey('D', prvid, tmp, buffer[32 + i], 32, 0, NULL, NULL); ++ } ++ } ++} ++ ++void read_emu_deskey(uint8_t *dreOverKey, uint8_t len) ++{ ++ uint8_t i; ++ ++ if (len == 128) ++ { ++ cs_log("Reading DreCrypt overcrypt (ADEC) key"); ++ ++ for (i = 0; i < 16; i++) ++ { ++ SetKey('D', i, "OVER", dreOverKey + (i * 8), 8, 0, NULL, NULL); ++ } ++ } ++ else if ((len != 0 && len < 128) || len > 128) ++ { ++ cs_log("DreCrypt overcrypt (ADEC) key has wrong length"); ++ } ++} ++ ++// Shared functions ++ ++static inline uint16_t GetEcmLen(const uint8_t *ecm) ++{ ++ return (((ecm[1] & 0x0f)<< 8) | ecm[2]) +3; ++} ++ ++static void ReverseMem(uint8_t *in, int32_t len) ++{ ++ uint8_t temp; ++ int32_t i; ++ for(i = 0; i < (len / 2); i++) { ++ temp = in[i]; ++ in[i] = in[len - i - 1]; ++ in[len - i - 1] = temp; ++ } ++} ++ ++static void ReverseMemInOut(uint8_t *out, const uint8_t *in, int32_t n) ++{ ++ if(n>0) { ++ out+=n; ++ do { ++ *(--out)=*(in++); ++ } ++ while(--n); ++ } ++} ++ ++static int8_t EmuRSAInput(BIGNUM *d, const uint8_t *in, int32_t n, int8_t le) ++{ ++ int8_t result = 0; ++ ++ if(le) { ++ uint8_t *tmp = (uint8_t *)malloc(sizeof(uint8_t)*n); ++ if(tmp == NULL) { ++ return 0; ++ } ++ ReverseMemInOut(tmp,in,n); ++ result = BN_bin2bn(tmp,n,d)!=0; ++ free(tmp); ++ } ++ else { ++ result = BN_bin2bn(in,n,d)!=0; ++ } ++ return result; ++} ++ ++static int32_t EmuRSAOutput(uint8_t *out, int32_t n, BIGNUM *r, int8_t le) ++{ ++ int32_t s = BN_num_bytes(r); ++ if(s>n) { ++ uint8_t *buff = (uint8_t *)malloc(sizeof(uint8_t)*s); ++ if(buff == NULL) { ++ return 0; ++ } ++ BN_bn2bin(r,buff); ++ memcpy(out,buff+s-n,n); ++ free(buff); ++ } ++ else if(s> 1) & 0xFE)); ++ key[2] = ((tmpKey[1] << 6) | ((tmpKey[2] >> 2) & 0xFE)); ++ key[3] = ((tmpKey[2] << 5) | ((tmpKey[3] >> 3) & 0xFE)); ++ key[4] = ((tmpKey[3] << 4) | ((tmpKey[4] >> 4) & 0xFE)); ++ key[5] = ((tmpKey[4] << 3) | ((tmpKey[5] >> 5) & 0xFE)); ++ key[6] = ((tmpKey[5] << 2) | ((tmpKey[6] >> 6) & 0xFE)); ++ key[7] = (tmpKey[6] << 1); ++ ++ for (i = 0; i < 8; i++) ++ { ++ parity = 1; ++ for (j = 1; j < 8; j++) if ((key[i] >> j) & 0x1) { parity = ~parity & 0x01; } ++ key[i] |= parity; ++ } ++} ++ ++// Cryptoworks EMU ++static int8_t GetCwKey(uint8_t *buf,uint32_t ident, uint8_t keyIndex, uint32_t keyLength, uint8_t isCriticalKey) ++{ ++ ++ char keyName[EMU_MAX_CHAR_KEYNAME]; ++ uint32_t tmp; ++ ++ if((ident >> 4) == 0xD02A) { ++ keyIndex &=0xFE; // map to even number key indexes ++ } ++ if((ident >> 4) == 0xD00C) { ++ ident = 0x0D00C0; // map provider C? to C0 ++ } ++ else if(keyIndex == 6 && ((ident >> 8) == 0x0D05)) { ++ ident = 0x0D0504; // always use provider 04 system key ++ } ++ ++ tmp = keyIndex; ++ snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%.2X", tmp); ++ if(FindKey('W', ident, 0, keyName, buf, keyLength, isCriticalKey, 0, 0, NULL)) { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static const uint8_t cw_sbox1[64] = { ++ 0xD8,0xD7,0x83,0x3D,0x1C,0x8A,0xF0,0xCF,0x72,0x4C,0x4D,0xF2,0xED,0x33,0x16,0xE0, ++ 0x8F,0x28,0x7C,0x82,0x62,0x37,0xAF,0x59,0xB7,0xE0,0x00,0x3F,0x09,0x4D,0xF3,0x94, ++ 0x16,0xA5,0x58,0x83,0xF2,0x4F,0x67,0x30,0x49,0x72,0xBF,0xCD,0xBE,0x98,0x81,0x7F, ++ 0xA5,0xDA,0xA7,0x7F,0x89,0xC8,0x78,0xA7,0x8C,0x05,0x72,0x84,0x52,0x72,0x4D,0x38 ++}; ++static const uint8_t cw_sbox2[64] = { ++ 0xD8,0x35,0x06,0xAB,0xEC,0x40,0x79,0x34,0x17,0xFE,0xEA,0x47,0xA3,0x8F,0xD5,0x48, ++ 0x0A,0xBC,0xD5,0x40,0x23,0xD7,0x9F,0xBB,0x7C,0x81,0xA1,0x7A,0x14,0x69,0x6A,0x96, ++ 0x47,0xDA,0x7B,0xE8,0xA1,0xBF,0x98,0x46,0xB8,0x41,0x45,0x9E,0x5E,0x20,0xB2,0x35, ++ 0xE4,0x2F,0x9A,0xB5,0xDE,0x01,0x65,0xF8,0x0F,0xB2,0xD2,0x45,0x21,0x4E,0x2D,0xDB ++}; ++static const uint8_t cw_sbox3[64] = { ++ 0xDB,0x59,0xF4,0xEA,0x95,0x8E,0x25,0xD5,0x26,0xF2,0xDA,0x1A,0x4B,0xA8,0x08,0x25, ++ 0x46,0x16,0x6B,0xBF,0xAB,0xE0,0xD4,0x1B,0x89,0x05,0x34,0xE5,0x74,0x7B,0xBB,0x44, ++ 0xA9,0xC6,0x18,0xBD,0xE6,0x01,0x69,0x5A,0x99,0xE0,0x87,0x61,0x56,0x35,0x76,0x8E, ++ 0xF7,0xE8,0x84,0x13,0x04,0x7B,0x9B,0xA6,0x7A,0x1F,0x6B,0x5C,0xA9,0x86,0x54,0xF9 ++}; ++static const uint8_t cw_sbox4[64] = { ++ 0xBC,0xC1,0x41,0xFE,0x42,0xFB,0x3F,0x10,0xB5,0x1C,0xA6,0xC9,0xCF,0x26,0xD1,0x3F, ++ 0x02,0x3D,0x19,0x20,0xC1,0xA8,0xBC,0xCF,0x7E,0x92,0x4B,0x67,0xBC,0x47,0x62,0xD0, ++ 0x60,0x9A,0x9E,0x45,0x79,0x21,0x89,0xA9,0xC3,0x64,0x74,0x9A,0xBC,0xDB,0x43,0x66, ++ 0xDF,0xE3,0x21,0xBE,0x1E,0x16,0x73,0x5D,0xA2,0xCD,0x8C,0x30,0x67,0x34,0x9C,0xCB ++}; ++static const uint8_t AND_bit1[8] = {0x00,0x40,0x04,0x80,0x21,0x10,0x02,0x08}; ++static const uint8_t AND_bit2[8] = {0x80,0x08,0x01,0x40,0x04,0x20,0x10,0x02}; ++static const uint8_t AND_bit3[8] = {0x82,0x40,0x01,0x10,0x00,0x20,0x04,0x08}; ++static const uint8_t AND_bit4[8] = {0x02,0x10,0x04,0x40,0x80,0x08,0x01,0x20}; ++ ++static void CW_SWAP_KEY(uint8_t *key) ++{ ++ uint8_t k[8]; ++ memcpy(k, key, 8); ++ memcpy(key, key + 8, 8); ++ memcpy(key + 8, k, 8); ++} ++ ++static void CW_SWAP_DATA(uint8_t *k) ++{ ++ uint8_t d[4]; ++ memcpy(d, k + 4, 4); ++ memcpy(k + 4 ,k ,4); ++ memcpy(k, d, 4); ++} ++ ++static void CW_DES_ROUND(uint8_t *d, uint8_t *k) ++{ ++ uint8_t aa[44] = {1,0,3,1,2,2,3,2,1,3,1,1,3,0,1,2,3,1,3,2,2,0,7,6,5,4,7,6,5,7,6,5,6,7,5,7,5,7,6,6,7,5,4,4}; ++ uint8_t bb[44] = {0x80,0x08,0x10,0x02,0x08,0x40,0x01,0x20,0x40,0x80,0x04,0x10,0x04,0x01,0x01,0x02,0x20,0x20,0x02,0x01, ++ 0x80,0x04,0x02,0x02,0x08,0x02,0x10,0x80,0x01,0x20,0x08,0x80,0x01,0x08,0x40,0x01,0x02,0x80,0x10,0x40,0x40,0x10,0x08,0x01 ++ }; ++ uint8_t ff[4] = {0x02,0x10,0x04,0x04}; ++ uint8_t l[24] = {0,2,4,6,7,5,3,1,4,5,6,7,7,6,5,4,7,4,5,6,4,7,6,5}; ++ ++ uint8_t des_td[8], i, o, n, c = 1, m = 0, r = 0, *a = aa, *b = bb, *f = ff, *p1 = l, *p2 = l+8, *p3 = l+16; ++ ++ for (m = 0; m < 2; m++) { ++ for(i = 0; i < 4; i++) { ++ des_td[*p1++] = ++ (m) ? ((d[*p2++]*2) & 0x3F) | ((d[*p3++] & 0x80) ? 0x01 : 0x00): (d[*p2++]/2) | ((d[*p3++] & 0x01) ? 0x80 : 0x00); ++ } ++ } ++ ++ for (i = 0; i < 8; i++) { ++ c = (c) ? 0 : 1; ++ r = (c) ? 6 : 7; ++ n = (i) ? i-1 : 1; ++ o = (c) ? ((k[n] & *f++) ? 1 : 0) : des_td[n]; ++ for (m = 1; m < r; m++) { ++ o = (c) ? (o*2) | ((k[*a++] & *b++) ? 0x01 : 0x00) : (o/2) | ((k[*a++] & *b++) ? 0x80 : 0x00); ++ } ++ n = (i) ? n+1 : 0; ++ des_td[n] = (c) ? des_td[n] ^ o : (o ^ des_td[n] )/4; ++ } ++ ++ for( i = 0; i < 8; i++) { ++ d[0] ^= (AND_bit1[i] & cw_sbox1[des_td[i]]); ++ d[1] ^= (AND_bit2[i] & cw_sbox2[des_td[i]]); ++ d[2] ^= (AND_bit3[i] & cw_sbox3[des_td[i]]); ++ d[3] ^= (AND_bit4[i] & cw_sbox4[des_td[i]]); ++ } ++ ++ CW_SWAP_DATA(d); ++} ++ ++static void CW_48_Key(uint8_t *inkey, uint8_t *outkey, uint8_t algotype) ++{ ++ uint8_t Round_Counter, i = 8, *key128 = inkey, *key48 = inkey + 0x10; ++ Round_Counter = 7 - (algotype & 7); ++ ++ memset(outkey, 0, 16); ++ memcpy(outkey, key48, 6); ++ ++ for( ; i > Round_Counter; i--) { ++ if (i > 1) { ++ outkey[i-2] = key128[i]; ++ } ++ } ++} ++ ++static void CW_LS_DES_KEY(uint8_t *key,uint8_t Rotate_Counter) ++{ ++ uint8_t round[] = {1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,1}; ++ uint8_t i, n; ++ uint16_t k[8]; ++ ++ n = round[Rotate_Counter]; ++ ++ for (i = 0; i < 8; i++) { ++ k[i] = key[i]; ++ } ++ ++ for (i = 1; i < n + 1; i++) { ++ k[7] = (k[7]*2) | ((k[4] & 0x008) ? 1 : 0); ++ k[6] = (k[6]*2) | ((k[7] & 0xF00) ? 1 : 0); ++ k[7] &=0xff; ++ k[5] = (k[5]*2) | ((k[6] & 0xF00) ? 1 : 0); ++ k[6] &=0xff; ++ k[4] = ((k[4]*2) | ((k[5] & 0xF00) ? 1 : 0)) & 0xFF; ++ k[5] &= 0xff; ++ k[3] = (k[3]*2) | ((k[0] & 0x008) ? 1 : 0); ++ k[2] = (k[2]*2) | ((k[3] & 0xF00) ? 1 : 0); ++ k[3] &= 0xff; ++ k[1] = (k[1]*2) | ((k[2] & 0xF00) ? 1 : 0); ++ k[2] &= 0xff; ++ k[0] = ((k[0]*2) | ((k[1] & 0xF00) ? 1 : 0)) & 0xFF; ++ k[1] &= 0xff; ++ } ++ for (i = 0; i < 8; i++) { ++ key[i] = (uint8_t) k[i]; ++ } ++} ++ ++static void CW_RS_DES_KEY(uint8_t *k, uint8_t Rotate_Counter) ++{ ++ uint8_t i,c; ++ for (i = 1; i < Rotate_Counter+1; i++) { ++ c = (k[3] & 0x10) ? 0x80 : 0; ++ k[3] /= 2; ++ if (k[2] & 1) { ++ k[3] |= 0x80; ++ } ++ k[2] /= 2; ++ if (k[1] & 1) { ++ k[2] |= 0x80; ++ } ++ k[1] /= 2; ++ if (k[0] & 1) { ++ k[1] |= 0x80; ++ } ++ k[0] /= 2; ++ k[0] |= c ; ++ c = (k[7] & 0x10) ? 0x80 : 0; ++ k[7] /= 2; ++ if (k[6] & 1) { ++ k[7] |= 0x80; ++ } ++ k[6] /= 2; ++ if (k[5] & 1) { ++ k[6] |= 0x80; ++ } ++ k[5] /= 2; ++ if (k[4] & 1) { ++ k[5] |= 0x80; ++ } ++ k[4] /= 2; ++ k[4] |= c; ++ } ++} ++ ++static void CW_RS_DES_SUBKEY(uint8_t *k, uint8_t Rotate_Counter) ++{ ++ uint8_t round[] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1}; ++ CW_RS_DES_KEY(k, round[Rotate_Counter]); ++} ++ ++static void CW_PREP_KEY(uint8_t *key ) ++{ ++ uint8_t DES_key[8],j; ++ int32_t Round_Counter = 6,i,a; ++ key[7] = 6; ++ memset(DES_key, 0 , 8); ++ do { ++ a = 7; ++ i = key[7]; ++ j = key[Round_Counter]; ++ do { ++ DES_key[i] = ( (DES_key[i] * 2) | ((j & 1) ? 1: 0) ) & 0xFF; ++ j /=2; ++ i--; ++ if (i < 0) { ++ i = 6; ++ } ++ a--; ++ } ++ while (a >= 0); ++ key[7] = i; ++ Round_Counter--; ++ } ++ while ( Round_Counter >= 0 ); ++ a = DES_key[4]; ++ DES_key[4] = DES_key[6]; ++ DES_key[6] = a; ++ DES_key[7] = (DES_key[3] * 16) & 0xFF; ++ memcpy(key,DES_key,8); ++ CW_RS_DES_KEY(key,4); ++} ++ ++static void CW_L2DES(uint8_t *data, uint8_t *key, uint8_t algo) ++{ ++ uint8_t i, k0[22], k1[22]; ++ memcpy(k0,key,22); ++ memcpy(k1,key,22); ++ CW_48_Key(k0, k1,algo); ++ CW_PREP_KEY(k1); ++ for (i = 0; i< 2; i++) { ++ CW_LS_DES_KEY( k1,15); ++ CW_DES_ROUND( data ,k1); ++ } ++} ++ ++static void CW_R2DES(uint8_t *data, uint8_t *key, uint8_t algo) ++{ ++ uint8_t i, k0[22],k1[22]; ++ memcpy(k0,key,22); ++ memcpy(k1,key,22); ++ CW_48_Key(k0, k1, algo); ++ CW_PREP_KEY(k1); ++ for (i = 0; i< 2; i++) { ++ CW_LS_DES_KEY(k1,15); ++ } ++ for (i = 0; i< 2; i++) { ++ CW_DES_ROUND( data ,k1); ++ CW_RS_DES_SUBKEY(k1,1); ++ } ++ CW_SWAP_DATA(data); ++} ++ ++static void CW_DES(uint8_t *data, uint8_t *inkey, uint8_t m) ++{ ++ uint8_t key[22], i; ++ memcpy(key, inkey + 9, 8); ++ CW_PREP_KEY( key ); ++ for (i = 16; i > 0; i--) { ++ if (m == 1) { ++ CW_LS_DES_KEY(key, (uint8_t) (i-1)); ++ } ++ CW_DES_ROUND( data ,key); ++ if (m == 0) { ++ CW_RS_DES_SUBKEY(key, (uint8_t) (i-1)); ++ } ++ } ++} ++ ++static void CW_DEC_ENC(uint8_t *d, uint8_t *k, uint8_t a,uint8_t m) ++{ ++ uint8_t n = m & 1; ++ CW_L2DES(d , k, a); ++ CW_DES (d , k, n); ++ CW_R2DES(d , k, a); ++ if (m & 2) { ++ CW_SWAP_KEY(k); ++ } ++} ++ ++static void Cryptoworks3DES(uint8_t *data, uint8_t *key) ++{ ++ uint32_t ks1[32], ks2[32]; ++ ++ des_set_key(key, ks1); ++ des_set_key(key+8, ks2); ++ ++ des(data, ks1, 0); ++ des(data, ks2, 1); ++ des(data, ks1, 0); ++} ++ ++static uint8_t CryptoworksProcessNano80(uint8_t *data, uint32_t caid, int32_t provider, uint8_t *opKey, uint8_t nanoLength, uint8_t nano80Algo) ++{ ++ int32_t i, j; ++ uint8_t key[16], desKey[16], t[8], dat1[8], dat2[8], k0D00C000[16]; ++ if(nanoLength < 11) { ++ return 0; ++ } ++ if(caid == 0x0D00 && provider != 0xA0 && !GetCwKey(k0D00C000, 0x0D00C0, 0, 16, 1)) { ++ return 0; ++ } ++ ++ if(nano80Algo > 1) { ++ return 0; ++ } ++ ++ memset(t, 0, 8); ++ memcpy(dat1, data, 8); ++ ++ if(caid == 0x0D00 && provider != 0xA0) { ++ memcpy(key, k0D00C000, 16); ++ } ++ else { ++ memcpy(key, opKey, 16); ++ } ++ Cryptoworks3DES(data, key); ++ memcpy(desKey, data, 8); ++ ++ memcpy(data, dat1, 8); ++ if(caid == 0x0D00 && provider != 0xA0) { ++ memcpy(key, &k0D00C000[8], 8); ++ memcpy(&key[8], k0D00C000, 8); ++ } ++ else { ++ memcpy(key, &opKey[8], 8); ++ memcpy(&key[8], opKey, 8); ++ } ++ Cryptoworks3DES(data, key); ++ memcpy(&desKey[8], data, 8); ++ ++ for(i=8; i+7 7) { ++ if (first) { ++ CW_L2DES(signature, key, algo); ++ } ++ CW_DES(signature, key, 1); ++ ++ sigPos = 0; ++ first = 0; ++ } ++ } ++ if(sigPos > 0) { ++ CW_DES(signature, key, 1); ++ } ++ CW_R2DES(signature, key, algo); ++} ++ ++static void CryptoworksDecryptDes(uint8_t *data, uint8_t algo, uint8_t *key) ++{ ++ int32_t i; ++ uint8_t k[22], t[8]; ++ ++ algo &= 7; ++ if(algo<7) { ++ CW_DEC_ENC(data, key, algo, 0); ++ } ++ else { ++ memcpy(k, key, 22); ++ for(i=0; i<3; i++) { ++ CW_DEC_ENC(data, k, algo, i&1); ++ memcpy(t,k,8); ++ memcpy(k,k+8,8); ++ memcpy(k+8,t,8); ++ } ++ } ++} ++ ++static int8_t CryptoworksECM(uint32_t caid, uint8_t *ecm, uint8_t *cw) ++{ ++ uint32_t ident; ++ uint8_t keyIndex = 0, nanoLength, newEcmLength, key[22], signature[8], nano80Algo = 1; ++ int32_t provider = -1; ++ uint16_t i, j, ecmLen = GetEcmLen(ecm); ++ ++ if(ecmLen < 8) { ++ return 1; ++ } ++ if(ecm[7] != ecmLen - 8) { ++ return 1; ++ } ++ ++ memset(key, 0, 22); ++ ++ for(i = 8; i+1 < ecmLen; i += ecm[i+1] + 2) { ++ if(ecm[i] == 0x83 && i+2 < ecmLen) { ++ provider = ecm[i+2] & 0xFC; ++ keyIndex = ecm[i+2] & 3; ++ keyIndex = keyIndex ? 1 : 0; ++ } ++ else if(ecm[i] == 0x84 && i+3 < ecmLen) { ++ //nano80Provider = ecm[i+2] & 0xFC; ++ //nano80KeyIndex = ecm[i+2] & 3; ++ //nano80KeyIndex = nano80KeyIndex ? 1 : 0; ++ nano80Algo = ecm[i+3]; ++ } ++ } ++ ++ if(provider < 0) { ++ switch(caid) { ++ case 0x0D00: ++ provider = 0xC0; ++ break; ++ case 0x0D02: ++ provider = 0xA0; ++ break; ++ case 0x0D03: ++ provider = 0x04; ++ break; ++ case 0x0D05: ++ provider = 0x04; ++ break; ++ default: ++ return 1; ++ } ++ } ++ ++ ident = (caid << 8) | provider; ++ if(!GetCwKey(key, ident, keyIndex, 16, 1)) { ++ return 2; ++ } ++ if(!GetCwKey(&key[16], ident, 6, 6, 1)) { ++ return 2; ++ } ++ ++ for(i = 8; i+1 < ecmLen; i += ecm[i+1] + 2) { ++ if(ecm[i] == 0x80 && i+2+7 < ecmLen && i+2+ecm[i+1] <= ecmLen ++ && (provider == 0xA0 || provider == 0xC0 || provider == 0xC4 || provider == 0xC8)) { ++ nanoLength = ecm[i+1]; ++ newEcmLength = CryptoworksProcessNano80(ecm+i+2, caid, provider, key, nanoLength, nano80Algo); ++ if(newEcmLength == 0 || newEcmLength > ecmLen-(i+2+3)) { ++ return 1; ++ } ++ ecm[i+2+3] = 0x81; ++ ecm[i+2+4] = 0x70; ++ ecm[i+2+5] = newEcmLength; ++ ecm[i+2+6] = 0x81; ++ ecm[i+2+7] = 0xFF; ++ return CryptoworksECM(caid, ecm+i+2+3, cw); ++ } ++ } ++ ++ if(ecmLen - 15 < 1) { ++ return 1; ++ } ++ CryptoworksSignature(ecm + 5, ecmLen - 15, key, signature); ++ for(i = 8; i+1 < ecmLen; i += ecm[i+1]+2) { ++ switch(ecm[i]) { ++ case 0xDA: ++ case 0xDB: ++ case 0xDC: ++ if(i+2+ecm[i+1] > ecmLen) { ++ break; ++ } ++ for(j=0; j+7 ecmLen) { ++ break; ++ } ++ if(memcmp(&ecm[i+2], signature, 8)) { ++ return 6; ++ } ++ break; ++ } ++ } ++ ++ for(i = 8; i+1 < ecmLen; i += ecm[i+1]+2) { ++ switch(ecm[i]) { ++ case 0xDB: ++ if(i+2+ecm[i+1] <= ecmLen && ecm[i+1] == 16) { ++ memcpy(cw, &ecm[i+2], 16); ++ return 0; ++ } ++ break; ++ } ++ } ++ ++ return 5; ++} ++ ++// SoftNDS EMU ++static const uint8_t nds_const[]= {0x0F,0x1E,0x2D,0x3C,0x4B,0x5A,0x69,0x78,0x87,0x96,0xA5,0xB4,0xC3,0xD2,0xE1,0xF0}; ++ ++uint8_t viasat_const[]= { ++ 0x15,0x85,0xC5,0xE4,0xB8,0x52,0xEC,0xF7,0xC3,0xD9,0x08,0xBA,0x22,0x4A,0x66,0xF2, ++ 0x82,0x15,0x4F,0xB2,0x18,0x48,0x63,0x97,0xDC,0x19,0xD8,0x51,0x9A,0x39,0xFC,0xCA, ++ 0x1C,0x24,0xD0,0x65,0xA9,0x66,0x2D,0xD6,0x53,0x3B,0x86,0xBA,0x40,0xEA,0x4C,0x6D, ++ 0xD9,0x1E,0x41,0x14,0xFE,0x15,0xAF,0xC3,0x18,0xC5,0xF8,0xA7,0xA8,0x01,0x00,0x01, ++}; ++ ++static int8_t SoftNDSECM(uint16_t caid, uint8_t *ecm, uint8_t *dw) ++{ ++ int32_t i; ++ uint8_t *tDW, irdEcmLen, offsetCw = 0, offsetP2 = 0; ++ uint8_t digest[16], md5_const[64]; ++ MD5_CTX mdContext; ++ uint16_t ecmLen = GetEcmLen(ecm); ++ ++ if(ecmLen < 7) { ++ return 1; ++ } ++ ++ if(ecm[3] != 0x00 || ecm[4] != 0x00 || ecm[5] != 0x01) { ++ return 1; ++ } ++ ++ irdEcmLen = ecm[6]; ++ if(irdEcmLen < (10+3+8+4) || irdEcmLen+6 >= ecmLen) { ++ return 1; ++ } ++ ++ for(i=0; 10+i+2 < irdEcmLen; i++) { ++ if(ecm[17+i] == 0x0F && ecm[17+i+1] == 0x40 && ecm[17+i+2] == 0x00) { ++ offsetCw = 17+i+3; ++ offsetP2 = offsetCw+9; ++ } ++ } ++ ++ if(offsetCw == 0 || offsetP2 == 0) { ++ return 1; ++ } ++ ++ if(offsetP2-7+4 > irdEcmLen) { ++ return 1; ++ } ++ ++ if(caid == 0x090F || caid == 0x093E) { ++ memcpy(md5_const, viasat_const, 64); ++ } ++ else if(!FindKey('S', caid, 0, "00", md5_const, 64, 1, 0, 0, NULL)) { ++ return 2; ++ } ++ ++ memset(dw,0,16); ++ tDW = &dw[ecm[0] == 0x81 ? 8 : 0]; ++ ++ MD5_Init(&mdContext); ++ MD5_Update(&mdContext, ecm+7, 10); ++ MD5_Update(&mdContext, ecm+offsetP2, 4); ++ MD5_Update(&mdContext, md5_const, 64); ++ MD5_Update(&mdContext, nds_const, 16); ++ MD5_Final(digest, &mdContext); ++ ++ for (i=0; i<8; i++) { ++ tDW[i] = digest[i+8] ^ ecm[offsetCw+i]; ++ } ++ ++ if(((tDW[0]+tDW[1]+tDW[2])&0xFF)-tDW[3]) { ++ return 6; ++ } ++ if(((tDW[4]+tDW[5]+tDW[6])&0xFF)-tDW[7]) { ++ return 6; ++ } ++ ++ return 0; ++} ++ ++// Viaccess EMU ++static int8_t GetViaKey(uint8_t *buf, uint32_t ident, char keyName, uint32_t keyIndex, uint32_t keyLength, uint8_t isCriticalKey) ++{ ++ ++ char keyStr[EMU_MAX_CHAR_KEYNAME]; ++ snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "%c%X", keyName, keyIndex); ++ if(FindKey('V', ident, 0, keyStr, buf, keyLength, isCriticalKey, 0, 0, NULL)) { ++ return 1; ++ } ++ ++ if(ident == 0xD00040 && FindKey('V', 0x030B00, 0, keyStr, buf, keyLength, isCriticalKey, 0, 0, NULL)) { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void Via1Mod(const uint8_t* key2, uint8_t* data) ++{ ++ int32_t kb, db; ++ for (db=7; db>=0; db--) { ++ for (kb=7; kb>3; kb--) { ++ int32_t a0=kb^db; ++ int32_t pos=7; ++ if (a0&4) { ++ a0^=7; ++ pos^=7; ++ } ++ a0=(a0^(kb&3)) + (kb&3); ++ if (!(a0&4)) { ++ data[db]^=(key2[kb] ^ ((data[kb^pos]*key2[kb^4]) & 0xFF)); ++ } ++ } ++ } ++ for (db=0; db<8; db++) { ++ for (kb=0; kb<4; kb++) { ++ int32_t a0=kb^db; ++ int32_t pos=7; ++ if (a0&4) { ++ a0^=7; ++ pos^=7; ++ } ++ a0=(a0^(kb&3)) + (kb&3); ++ if (!(a0&4)) { ++ data[db]^=(key2[kb] ^ ((data[kb^pos]*key2[kb^4]) & 0xFF)); ++ } ++ } ++ } ++} ++ ++static void Via1Decode(uint8_t *data, uint8_t *key) ++{ ++ Via1Mod(key+8, data); ++ nc_des(key, DES_ECM_CRYPT, data); ++ Via1Mod(key+8, data); ++} ++ ++static void Via1Hash(uint8_t *data, uint8_t *key) ++{ ++ Via1Mod(key+8, data); ++ nc_des(key, DES_ECM_HASH, data); ++ Via1Mod(key+8, data); ++} ++ ++static inline void Via1DoHash(uint8_t *hashbuffer, uint8_t *pH, uint8_t data, uint8_t *hashkey) ++{ ++ hashbuffer[*pH] ^= data; ++ (*pH)++; ++ ++ if(*pH == 8) { ++ Via1Hash(hashbuffer, hashkey); ++ *pH = 0; ++ } ++} ++ ++static int8_t Via1Decrypt(uint8_t* ecm, uint8_t* dw, uint32_t ident, uint8_t desKeyIndex) ++{ ++ uint8_t work_key[16]; ++ uint8_t *data, *des_data1, *des_data2; ++ uint16_t ecmLen = GetEcmLen(ecm); ++ int32_t msg_pos; ++ int32_t encStart = 0, hash_start, i; ++ uint8_t signature[8], hashbuffer[8], prepared_key[16], hashkey[16]; ++ uint8_t tmp, k, pH, foundData = 0; ++ ++ if (ident == 0) { ++ return 4; ++ } ++ memset(work_key, 0, 16); ++ if(!GetViaKey(work_key, ident, '0', desKeyIndex, 8, 1)) { ++ return 2; ++ } ++ ++ if(ecmLen < 11) { ++ return 1; ++ } ++ data = ecm+9; ++ des_data1 = dw; ++ des_data2 = dw+8; ++ ++ msg_pos = 0; ++ pH = 0; ++ memset(hashbuffer, 0, sizeof(hashbuffer)); ++ memcpy(hashkey, work_key, sizeof(hashkey)); ++ memset(signature, 0, 8); ++ ++ while(9+msg_pos+2 < ecmLen) { ++ switch (data[msg_pos]) { ++ case 0xea: ++ if(9+msg_pos+2+15 < ecmLen) { ++ encStart = msg_pos + 2; ++ memcpy(des_data1, &data[msg_pos+2], 8); ++ memcpy(des_data2, &data[msg_pos+2+8], 8); ++ foundData |= 1; ++ } ++ break; ++ case 0xf0: ++ if(9+msg_pos+2+7 < ecmLen) { ++ memcpy(signature, &data[msg_pos+2], 8); ++ foundData |= 2; ++ } ++ break; ++ } ++ msg_pos += data[msg_pos+1]+2; ++ } ++ ++ if(foundData != 3) { ++ return 1; ++ } ++ ++ pH=i=0; ++ ++ if(data[0] == 0x9f && 10+data[1] <= ecmLen) { ++ Via1DoHash(hashbuffer, &pH, data[i++], hashkey); ++ Via1DoHash(hashbuffer, &pH, data[i++], hashkey); ++ ++ for (hash_start=0; hash_start < data[1]; hash_start++) { ++ Via1DoHash(hashbuffer, &pH, data[i++], hashkey); ++ } ++ ++ while (pH != 0) { ++ Via1DoHash(hashbuffer, &pH, 0, hashkey); ++ } ++ } ++ ++ if (work_key[7] == 0) { ++ for (; i < encStart + 16; i++) { ++ Via1DoHash(hashbuffer, &pH, data[i], hashkey); ++ } ++ memcpy(prepared_key, work_key, 8); ++ } ++ else { ++ prepared_key[0] = work_key[2]; ++ prepared_key[1] = work_key[3]; ++ prepared_key[2] = work_key[4]; ++ prepared_key[3] = work_key[5]; ++ prepared_key[4] = work_key[6]; ++ prepared_key[5] = work_key[0]; ++ prepared_key[6] = work_key[1]; ++ prepared_key[7] = work_key[7]; ++ memcpy(prepared_key+8, work_key+8, 8); ++ ++ if (work_key[7] & 1) { ++ for (; i < encStart; i++) { ++ Via1DoHash(hashbuffer, &pH, data[i], hashkey); ++ } ++ ++ k = ((work_key[7] & 0xf0) == 0) ? 0x5a : 0xa5; ++ ++ for (i=0; i<8; i++) { ++ tmp = des_data1[i]; ++ des_data1[i] = (k & hashbuffer[pH] ) ^ tmp; ++ Via1DoHash(hashbuffer, &pH, tmp, hashkey); ++ } ++ ++ for (i = 0; i < 8; i++) { ++ tmp = des_data2[i]; ++ des_data2[i] = (k & hashbuffer[pH] ) ^ tmp; ++ Via1DoHash(hashbuffer, &pH, tmp, hashkey); ++ } ++ } ++ else { ++ for (; i < encStart + 16; i++) { ++ Via1DoHash(hashbuffer, &pH, data[i], hashkey); ++ } ++ } ++ } ++ Via1Decode(des_data1, prepared_key); ++ Via1Decode(des_data2, prepared_key); ++ Via1Hash(hashbuffer, hashkey); ++ if(memcmp(signature, hashbuffer, 8)) { ++ return 6; ++ } ++ return 0; ++} ++ ++static int8_t Via26ProcessDw(uint8_t *indata, uint32_t ident, uint8_t desKeyIndex) ++{ ++ uint8_t pv1,pv2, i; ++ uint8_t Tmp[8], T1Key[300], P1Key[8], KeyDes1[16], KeyDes2[16], XorKey[8]; ++ uint32_t ks1[32], ks2[32]; ++ ++ if(!GetViaKey(T1Key, ident, 'T', 1, 300, 1)) { ++ return 2; ++ } ++ if(!GetViaKey(P1Key, ident, 'P', 1, 8, 1)) { ++ return 2; ++ } ++ if(!GetViaKey(KeyDes1, ident, 'D', 1, 16, 1)) { ++ return 2; ++ } ++ if(!GetViaKey(KeyDes2, ident, '0', desKeyIndex, 16, 1)) { ++ return 2; ++ } ++ if(!GetViaKey(XorKey, ident, 'X', 1, 8, 1)) { ++ return 2; ++ } ++ ++ for (i=0; i<8; i++) { ++ pv1 = indata[i]; ++ Tmp[i] = T1Key[pv1]; ++ } ++ for (i=0; i<8; i++) { ++ pv1 = P1Key[i]; ++ pv2 = Tmp[pv1]; ++ indata[i]=pv2; ++ } ++ ++ des_set_key(KeyDes1, ks1); ++ des(indata, ks1, 1); ++ ++ for (i=0; i<8; i++) { ++ indata[i] ^= XorKey[i]; ++ } ++ ++ des_set_key(KeyDes2, ks1); ++ des_set_key(KeyDes2+8, ks2); ++ des(indata, ks1, 0); ++ des(indata, ks2, 1); ++ des(indata, ks1, 0); ++ ++ for (i=0; i<8; i++) { ++ indata[i] ^= XorKey[i]; ++ } ++ ++ des_set_key(KeyDes1, ks1); ++ des(indata, ks1, 0); ++ ++ for (i=0; i<8; i++) { ++ pv1 = indata[i]; ++ pv2 = P1Key[i]; ++ Tmp[pv2] = pv1; ++ } ++ for (i=0; i<8; i++) { ++ pv1 = Tmp[i]; ++ pv2 = T1Key[pv1]; ++ indata[i] = pv2; ++ } ++ return 0; ++} ++ ++static int8_t Via26Decrypt(uint8_t* source, uint8_t* dw, uint32_t ident, uint8_t desKeyIndex) ++{ ++ uint8_t tmpData[8], C1[8]; ++ uint8_t *pXorVector; ++ int32_t i,j; ++ ++ if (ident == 0) { ++ return 4; ++ } ++ if(!GetViaKey(C1, ident, 'C', 1, 8, 1)) { ++ return 2; ++ } ++ ++ for (i=0; i<2; i++) { ++ memcpy(tmpData, source+ i*8, 8); ++ Via26ProcessDw(tmpData, ident, desKeyIndex); ++ if (i!=0) { ++ pXorVector = source; ++ } ++ else { ++ pXorVector = &C1[0]; ++ } ++ for (j=0; j<8; j++) { ++ dw[i*8+j] = tmpData[j]^pXorVector[j]; ++ } ++ } ++ return 0; ++} ++ ++static void Via3Core(uint8_t *data, uint8_t Off, uint32_t ident, uint8_t* XorKey, uint8_t* T1Key) ++{ ++ uint8_t i; ++ uint32_t lR2, lR3, lR4, lR6, lR7; ++ ++ switch (ident) { ++ case 0x032820: { ++ for (i=0; i<4; i++) { ++ data[i]^= XorKey[(Off+i) & 0x07]; ++ } ++ lR2 = (data[0]^0xBD)+data[0]; ++ lR3 = (data[3]^0xEB)+data[3]; ++ lR2 = (lR2-lR3)^data[2]; ++ lR3 = ((0x39*data[1])<<2); ++ data[4] = (lR2|lR3)+data[2]; ++ lR3 = ((((data[0]+6)^data[0]) | (data[2]<<1))^0x65)+data[0]; ++ lR2 = (data[1]^0xED)+data[1]; ++ lR7 = ((data[3]+0x29)^data[3])*lR2; ++ data[5] = lR7+lR3; ++ lR2 = ((data[2]^0x33)+data[2]) & 0x0A; ++ lR3 = (data[0]+0xAD)^data[0]; ++ lR3 = lR3+lR2; ++ lR2 = data[3]*data[3]; ++ lR7 = (lR2 | 1) + data[1]; ++ data[6] = (lR3|lR7)+data[1]; ++ lR3 = data[1] & 0x07; ++ lR2 = (lR3-data[2]) & (data[0] | lR2 |0x01); ++ data[7] = lR2+data[3]; ++ for (i=0; i<4; i++) { ++ data[i+4] = T1Key[data[i+4]]; ++ } ++ } ++ break; ++ case 0x030B00: { ++ for (i=0; i<4; i++) { ++ data[i]^= XorKey[(Off+i) & 0x07]; ++ } ++ lR6 = (data[3] + 0x6E) ^ data[3]; ++ lR6 = (lR6*(data[2] << 1)) + 0x17; ++ lR3 = (data[1] + 0x77) ^ data[1]; ++ lR4 = (data[0] + 0xD7) ^ data[0]; ++ data[4] = ((lR4 & lR3) | lR6) + data[0]; ++ lR4 = ((data[3] + 0x71) ^ data[3]) ^ 0x90; ++ lR6 = (data[1] + 0x1B) ^ data[1]; ++ lR4 = (lR4*lR6) ^ data[0]; ++ data[5] = (lR4 ^ (data[2] << 1)) + data[1]; ++ lR3 = (data[3] * data[3])| 0x01; ++ lR4 = (((data[2] ^ 0x35) + data[2]) | lR3) + data[2]; ++ lR6 = data[1] ^ (data[0] + 0x4A); ++ data[6] = lR6 + lR4; ++ lR3 = (data[0] * (data[2] << 1)) | data[1]; ++ lR4 = 0xFE - data[3]; ++ lR3 = lR4 ^ lR3; ++ data[7] = lR3 + data[3]; ++ for (i=0; i<4; i++) { ++ data[4+i] = T1Key[data[4+i]]; ++ } ++ } ++ break; ++ default: ++ break; ++ } ++} ++ ++static void Via3Fct1(uint8_t *data, uint32_t ident, uint8_t* XorKey, uint8_t* T1Key) ++{ ++ uint8_t t; ++ Via3Core(data, 0, ident, XorKey, T1Key); ++ ++ switch (ident) { ++ case 0x032820: { ++ t = data[4]; ++ data[4] = data[7]; ++ data[7] = t; ++ } ++ break; ++ case 0x030B00: { ++ t = data[5]; ++ data[5] = data[7]; ++ data[7] = t; ++ } ++ break; ++ default: ++ break; ++ } ++} ++ ++static void Via3Fct2(uint8_t *data, uint32_t ident, uint8_t* XorKey, uint8_t* T1Key) ++{ ++ uint8_t t; ++ Via3Core(data, 4, ident, XorKey, T1Key); ++ ++ switch (ident) { ++ case 0x032820: { ++ t = data[4]; ++ data[4] = data[7]; ++ data[7] = data[5]; ++ data[5] = data[6]; ++ data[6] = t; ++ } ++ break; ++ case 0x030B00: { ++ t = data[6]; ++ data[6] = data[7]; ++ data[7] = t; ++ } ++ break; ++ default: ++ break; ++ } ++} ++ ++static int8_t Via3ProcessDw(uint8_t *data, uint32_t ident, uint8_t desKeyIndex) ++{ ++ uint8_t i; ++ uint8_t tmp[8], T1Key[300], P1Key[8], KeyDes[16], XorKey[8]; ++ uint32_t ks1[32], ks2[32]; ++ ++ if(!GetViaKey(T1Key, ident, 'T', 1, 300, 1)) { ++ return 2; ++ } ++ if(!GetViaKey(P1Key, ident, 'P', 1, 8, 1)) { ++ return 2; ++ } ++ if(!GetViaKey(KeyDes, ident, '0', desKeyIndex, 16, 1)) { ++ return 2; ++ } ++ if(!GetViaKey(XorKey, ident, 'X', 1, 8, 1)) { ++ return 2; ++ } ++ ++ for (i=0; i<4; i++) { ++ tmp[i] = data[i+4]; ++ } ++ Via3Fct1(tmp, ident, XorKey, T1Key); ++ for (i=0; i<4; i++) { ++ tmp[i] = data[i]^tmp[i+4]; ++ } ++ Via3Fct2(tmp, ident, XorKey, T1Key); ++ for (i=0; i<4; i++) { ++ tmp[i]^= XorKey[i+4]; ++ } ++ for (i=0; i<4; i++) { ++ data[i] = data[i+4]^tmp[i+4]; ++ data[i+4] = tmp[i]; ++ } ++ ++ des_set_key(KeyDes, ks1); ++ des_set_key(KeyDes+8, ks2); ++ ++ des(data, ks1, 0); ++ des(data, ks2, 1); ++ des(data, ks1, 0); ++ ++ for (i=0; i<4; i++) { ++ tmp[i] = data[i+4]; ++ } ++ Via3Fct2(tmp, ident, XorKey, T1Key); ++ for (i=0; i<4; i++) { ++ tmp[i] = data[i]^tmp[i+4]; ++ } ++ Via3Fct1(tmp, ident, XorKey, T1Key); ++ for (i=0; i<4; i++) { ++ tmp[i]^= XorKey[i]; ++ } ++ for (i=0; i<4; i++) { ++ data[i] = data[i+4]^tmp[i+4]; ++ data[i+4] = tmp[i]; ++ } ++ return 0; ++} ++ ++static void Via3FinalMix(uint8_t *dw) ++{ ++ uint8_t tmp[4]; ++ ++ memcpy(tmp, dw, 4); ++ memcpy(dw, dw + 4, 4); ++ memcpy(dw + 4, tmp, 4); ++ ++ memcpy(tmp, dw + 8, 4); ++ memcpy(dw + 8, dw + 12, 4); ++ memcpy(dw + 12, tmp, 4); ++} ++ ++static int8_t Via3Decrypt(uint8_t* source, uint8_t* dw, uint32_t ident, uint8_t desKeyIndex, uint8_t aesKeyIndex, uint8_t aesMode, int8_t doFinalMix) ++{ ++ int8_t aesAfterCore = 0; ++ int8_t needsAES = (aesKeyIndex != 0xFF); ++ uint8_t tmpData[8], C1[8]; ++ uint8_t *pXorVector; ++ char aesKey[16]; ++ int32_t i, j; ++ ++ if(ident == 0) { ++ return 4; ++ } ++ if(!GetViaKey(C1, ident, 'C', 1, 8, 1)) { ++ return 2; ++ } ++ if(needsAES && !GetViaKey((uint8_t*)aesKey, ident, 'E', aesKeyIndex, 16, 1)) { ++ return 2; ++ } ++ if(aesMode == 0x0D || aesMode == 0x11 || aesMode == 0x15) { ++ aesAfterCore = 1; ++ } ++ ++ if(needsAES && !aesAfterCore) { ++ if(aesMode == 0x0F) { ++ hdSurEncPhase1_D2_0F_11(source); ++ hdSurEncPhase2_D2_0F_11(source); ++ } ++ else if(aesMode == 0x13) { ++ hdSurEncPhase1_D2_13_15(source); ++ } ++ struct aes_keys aes; ++ aes_set_key(&aes, aesKey); ++ aes_decrypt(&aes, source, 16); ++ if(aesMode == 0x0F) { ++ hdSurEncPhase1_D2_0F_11(source); ++ } ++ else if(aesMode == 0x13) { ++ hdSurEncPhase2_D2_13_15(source); ++ } ++ } ++ ++ for(i=0; i<2; i++) { ++ memcpy(tmpData, source+i*8, 8); ++ Via3ProcessDw(tmpData, ident, desKeyIndex); ++ if (i!=0) { ++ pXorVector = source; ++ } ++ else { ++ pXorVector = &C1[0]; ++ } ++ for (j=0; j<8; j++) { ++ dw[i*8+j] = tmpData[j]^pXorVector[j]; ++ } ++ } ++ ++ if(needsAES && aesAfterCore) { ++ if(aesMode == 0x11) { ++ hdSurEncPhase1_D2_0F_11(dw); ++ hdSurEncPhase2_D2_0F_11(dw); ++ } ++ else if(aesMode == 0x15) { ++ hdSurEncPhase1_D2_13_15(dw); ++ } ++ struct aes_keys aes; ++ aes_set_key(&aes, aesKey); ++ aes_decrypt(&aes, dw, 16); ++ if(aesMode == 0x11) { ++ hdSurEncPhase1_D2_0F_11(dw); ++ } ++ if(aesMode == 0x15) { ++ hdSurEncPhase2_D2_13_15(dw); ++ } ++ } ++ ++ if(ident == 0x030B00) { ++ if(doFinalMix) { ++ Via3FinalMix(dw); ++ } ++ if(!isValidDCW(dw)) { ++ return 6; ++ } ++ } ++ return 0; ++} ++ ++static int8_t ViaccessECM(uint8_t *ecm, uint8_t *dw) ++{ ++ uint32_t currentIdent = 0; ++ uint8_t nanoCmd = 0, nanoLen = 0, version = 0, providerKeyLen = 0, desKeyIndex = 0, aesMode = 0, aesKeyIndex = 0xFF; ++ int8_t doFinalMix = 0, result = 1; ++ uint16_t i = 0, keySelectPos = 0, ecmLen = GetEcmLen(ecm); ++ ++ for (i=4; i+2 ecmLen) { ++ return 1; ++ } ++ ++ switch (nanoCmd) { ++ case 0x40: ++ if (nanoLen < 0x03) { ++ break; ++ } ++ version = ecm[i]; ++ if (nanoLen == 3) { ++ currentIdent = ((ecm[i]<<16)|(ecm[i+1]<<8))|(ecm[i+2]&0xF0); ++ desKeyIndex = ecm[i+2]&0x0F; ++ keySelectPos = i+3; ++ } ++ else { ++ currentIdent = (ecm[i]<<16)|(ecm[i+1]<<8)|((ecm[i+2]>>4)&0x0F); ++ desKeyIndex = ecm[i+3]; ++ keySelectPos = i+4; ++ } ++ providerKeyLen = nanoLen; ++ break; ++ case 0x90: ++ if (nanoLen < 0x03) { ++ break; ++ } ++ version = ecm[i]; ++ currentIdent = ((ecm[i]<<16)|(ecm[i+1]<<8))|(ecm[i+2]&0xF0); ++ desKeyIndex = ecm[i+2]&0x0F; ++ keySelectPos = i+4; ++ if((version == 3) && (nanoLen > 3)) { ++ desKeyIndex = ecm[i+(nanoLen-4)]&0x0F; ++ } ++ providerKeyLen = nanoLen; ++ break; ++ case 0x80: ++ nanoLen = 0; ++ break; ++ case 0xD2: ++ if (nanoLen < 0x02) { ++ break; ++ } ++ aesMode = ecm[i]; ++ aesKeyIndex = ecm[i+1]; ++ break; ++ case 0xDD: ++ nanoLen = 0; ++ break; ++ case 0xEA: ++ if (nanoLen < 0x10) { ++ break; ++ } ++ ++ if (version < 2) { ++ return Via1Decrypt(ecm, dw, currentIdent, desKeyIndex); ++ } ++ else if (version == 2) { ++ return Via26Decrypt(ecm + i, dw, currentIdent, desKeyIndex); ++ } ++ else if (version == 3) { ++ doFinalMix = 0; ++ if (currentIdent == 0x030B00 && providerKeyLen>3) { ++ if(keySelectPos+2 >= ecmLen) { ++ break; ++ } ++ if (ecm[keySelectPos] == 0x05 && ecm[keySelectPos+1] == 0x67 && (ecm[keySelectPos+2] == 0x00 || ecm[keySelectPos+2] == 0x01)) { ++ if(ecm[keySelectPos+2] == 0x01) { ++ doFinalMix = 1; ++ } ++ } ++ else { ++ break; ++ } ++ } ++ return Via3Decrypt(ecm + i, dw, currentIdent, desKeyIndex, aesKeyIndex, aesMode, doFinalMix); ++ } ++ break; ++ default: ++ break; ++ } ++ i += nanoLen; ++ } ++ return result; ++} ++ ++// Nagra EMU ++static int8_t GetNagraKey(uint8_t *buf, uint32_t ident, char keyName, uint32_t keyIndex, uint8_t isCriticalKey) ++{ ++ char keyStr[EMU_MAX_CHAR_KEYNAME]; ++ snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "%c%X", keyName, keyIndex); ++ if(FindKey('N', ident, 0, keyStr, buf, keyName == 'M' ? 64 : 16, isCriticalKey, 0, 0, NULL)) { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int8_t Nagra2Signature(const uint8_t *vkey, const uint8_t *sig, const uint8_t *msg, int32_t len) ++{ ++ uint8_t buff[16]; ++ uint8_t iv[8]; ++ int32_t i,j; ++ ++ memcpy(buff,vkey,sizeof(buff)); ++ for(i=0; i+7=0; j--) { ++ buff[j+8]^=msg[i+j]; ++ } ++ } ++ buff[8]&=0x7F; ++ return (memcmp(sig, buff+8, 8) == 0); ++} ++ ++static int8_t DecryptNagra2ECM(uint8_t *in, uint8_t *out, const uint8_t *key, int32_t len, const uint8_t *vkey, uint8_t *keyM) ++{ ++ BIGNUM *exp, *mod; ++ uint8_t iv[8]; ++ int32_t i = 0, sign = in[0] & 0x80; ++ uint8_t binExp = 3; ++ int8_t result = 1; ++ ++ exp = BN_new(); ++ mod = BN_new(); ++ BN_bin2bn(&binExp, 1, exp); ++ BN_bin2bn(keyM, 64, mod); ++ ++ if(EmuRSA(out,in+1,64,exp,mod,1)<=0) { ++ BN_free(exp); ++ BN_free(mod); ++ return 0; ++ } ++ out[63]|=sign; ++ if(len>64) { ++ memcpy(out+64,in+65,len-64); ++ } ++ ++ memset(iv,0,sizeof(iv)); ++ if(in[0]&0x04) { ++ uint8_t key1[8], key2[8]; ++ ReverseMemInOut(key1,&key[0],8); ++ ReverseMemInOut(key2,&key[8],8); ++ ++ for(i=7; i>=0; i--) { ++ ReverseMem(out+8*i,8); ++ } ++ des_ede2_cbc_decrypt(out, iv, key1, key2, len); ++ for(i=7; i>=0; i--) { ++ ReverseMem(out+8*i,8); ++ } ++ } ++ else { ++ IDEA_KEY_SCHEDULE ek; ++ idea_set_encrypt_key(key, &ek); ++ idea_cbc_encrypt(out, out, len&~7, &ek, iv, IDEA_DECRYPT); ++ } ++ ++ ReverseMem(out,64); ++ if(result && EmuRSA(out,out,64,exp,mod,0)<=0) { ++ result = 0; ++ } ++ if(result && vkey && !Nagra2Signature(vkey,out,out+8,len-8)) { ++ result = 0; ++ } ++ ++ BN_free(exp); ++ BN_free(mod); ++ return result; ++} ++ ++static int8_t Nagra2ECM(uint8_t *ecm, uint8_t *dw) ++{ ++ uint32_t ident, identMask, tmp1, tmp2, tmp3; ++ uint8_t cmdLen, ideaKeyNr, *dec, ideaKey[16], vKey[16], m1Key[64], mecmAlgo = 0; ++ int8_t useVerifyKey = 0; ++ int32_t l=0, s; ++ uint16_t i = 0, ecmLen = GetEcmLen(ecm); ++ ++ if(ecmLen < 8) { ++ return 1; ++ } ++ cmdLen = ecm[4] - 5; ++ ident = (ecm[5] << 8) + ecm[6]; ++ ideaKeyNr = (ecm[7]&0x10)>>4; ++ if(ideaKeyNr) { ++ ideaKeyNr = 1; ++ } ++ if(ident == 1283 || ident == 1285 || ident == 1297) { ++ ident = 1281; ++ } ++ if(cmdLen <= 63 || ecmLen < cmdLen + 10) { ++ return 1; ++ } ++ ++ if(!GetNagraKey(ideaKey, ident, '0', ideaKeyNr, 1)) { ++ return 2; ++ } ++ if(GetNagraKey(vKey, ident, 'V', 0, 0)) { ++ useVerifyKey = 1; ++ } ++ if(!GetNagraKey(m1Key, ident, 'M', 1, 1)) { ++ return 2; ++ } ++ ReverseMem(m1Key, 64); ++ ++ dec = (uint8_t*)malloc(sizeof(uint8_t)*cmdLen); ++ if(dec == NULL) { ++ return 7; ++ } ++ if(!DecryptNagra2ECM(ecm+9, dec, ideaKey, cmdLen, useVerifyKey?vKey:0, m1Key)) { ++ free(dec); ++ return 1; ++ } ++ ++ for(i=(dec[14]&0x10)?16:20; i0) { ++ return 1; ++ } ++ ++ identMask = ident & 0xFF00; ++ if (identMask == 0x1100 || identMask == 0x500 || identMask == 0x3100) { ++ memcpy(&tmp1, dw, 4); ++ memcpy(&tmp2, dw + 4, 4); ++ memcpy(&tmp3, dw + 12, 4); ++ memcpy(dw, dw + 8, 4); ++ memcpy(dw + 4, &tmp3, 4); ++ memcpy(dw + 8, &tmp1, 4); ++ memcpy(dw + 12, &tmp2, 4); ++ } ++ return 0; ++} ++ ++// Irdeto EMU ++static int8_t GetIrdetoKey(uint8_t *buf, uint32_t ident, char keyName, uint32_t keyIndex, uint8_t isCriticalKey, uint32_t *keyRef) ++{ ++ char keyStr[EMU_MAX_CHAR_KEYNAME]; ++ ++ if(*keyRef > 0xFF) ++ { ++ return 0; ++ } ++ ++ snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "%c%X", keyName, keyIndex); ++ if(FindKey('I', ident, 0, keyStr, buf, 16, *keyRef > 0 ? 0 : isCriticalKey, *keyRef, 0, NULL)) { ++ (*keyRef)++; ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void Irdeto2Encrypt(uint8_t *data, const uint8_t *seed, const uint8_t *key, int32_t len) ++{ ++ const uint8_t *tmp = seed;; ++ int32_t i; ++ uint32_t ks1[32], ks2[32]; ++ ++ des_set_key(key, ks1); ++ des_set_key(key+8, ks2); ++ ++ len&=~7; ++ ++ for(i=0; i+7> 16; ++ ++ switch (pos) ++ { ++ case 29: // Rascom QAF 1R ++ case 31: // Eutelsat 3B ++ { ++ pos = 30; ++ break; ++ } ++ ++ case 49: ++ case 50: // SES 5 ++ { ++ pos = 48; // Astra 4A ++ break; ++ } ++ ++ case 215: ++ { ++ pos = 216; // Eutelsat 21B ++ break; ++ } ++ ++ case 285: // Astra 2E ++ { ++ pos = 282; // Astra 2F/2G ++ break; ++ } ++ ++ case 328: // Intelsat 28 ++ case 329: ++ case 331: // Eutelsat 33C ++ { ++ pos = 330; ++ break; ++ } ++ ++ case 359: // Eutelsat 36B ++ case 361: // Express AMU1 ++ { ++ pos = 360; ++ break; ++ } ++ ++ case 451: // Intelsat 904 ++ { ++ pos = 450; // Intelsat 12 ++ break; ++ } ++ ++ case 550: ++ case 551: // G-Sat 8/16 ++ { ++ pos = 549; // Yamal 402 ++ break; ++ } ++ ++ case 748: ++ case 749: // ABS 2A ++ { ++ pos = 750; ++ break; ++ } ++ ++ case 848: // Horizons 2 ++ case 852: // Intelsat 15 ++ { ++ pos = 850; ++ break; ++ } ++ ++ case 914: // Mesasat 3a ++ { ++ pos = 915; // Mesasat 3/3b ++ break; ++ } ++ ++ case 934: // G-Sat 17 ++ case 936: // Insat 4B ++ { ++ pos = 935; // G-Sat 15 ++ break; ++ } ++ ++ case 3600 - 911: // Nimiq 6 ++ { ++ pos = 3600 - 910; // Galaxy 17 ++ } ++ ++ case 3600 - 870: // SES 2 ++ case 3600 - 872: // TKSat 1 ++ { ++ pos = 3600 - 871; ++ break; ++ } ++ ++ case 3600 - 432: // Sky Brasil 1 ++ case 3600 - 430: // Intelsat 11 ++ { ++ pos = 3600 - 431; ++ break; ++ } ++ ++ case 3600 - 376: // Telstar 11N ++ case 3600 - 374: // NSS 10 ++ { ++ pos = 3600 - 375; ++ break; ++ } ++ ++ case 3600 - 359: // Hispasat 36W-1 ++ { ++ pos = 3600 - 360; // Eutelsat 36 West A ++ break; ++ } ++ ++ case 3600 - 81: // Eutelsat 8 West B ++ { ++ pos = 3600 - 80; ++ break; ++ } ++ ++ case 3600 - 73: // Eutelsat 7 West A ++ case 3600 - 72: ++ case 3600 - 71: ++ { ++ pos = 3600 - 70; // Nilesat 201 ++ break; ++ } ++ ++ case 3600 - 10: // Intelsat 10-02 ++ case 3600 - 9: // Thor 6 ++ case 3600 - 7: // Thor 7 ++ case 3600 - 6: // Thor 7 ++ { ++ pos = 3600 - 8; // Thor 5 ++ break; ++ } ++ } ++ ++ *namespace = (*namespace & 0xF000FFFF) | (pos << 16); ++} ++ ++static void BissAnnotate(char *buf, uint8_t len, const uint8_t *ecm, uint16_t ecmLen, uint32_t hash, int8_t isNamespaceHash, int8_t datecoded) ++{ ++ // Extract useful information to append to the "Example key ..." message. ++ // ++ // For feeds, the orbital position & frequency are usually embedded in the namespace. ++ // See https://github.com/openatv/enigma2/blob/master/lib/dvb/frontend.cpp#L496 ++ // hash = (sat.orbital_position << 16); ++ // hash |= ((sat.frequency/1000)&0xFFFF)|((sat.polarisation&1) << 15); ++ // ++ // If the onid & tsid appear to be a unique DVB identifier, enigma2 strips the frequency ++ // from our namespace. See https://github.com/openatv/enigma2/blob/master/lib/dvb/scan.cpp#L59 ++ // In that case, our annotation contains the onid:tsid:sid triplet in lieu of frequency. ++ // ++ // For the universal case, we print the number of elementary stream pids & pmtpid. ++ // The sid and current time are included for all. Examples: ++ // ++ // F 1A2B3C4D 00000000 XXXXXXXXXXXXXXXX ; 110.5W 12345H sid:0001 added: 2017-10-17 @ 13:14:15 // namespace ++ // F 1A2B3C4D 20180123 XXXXXXXXXXXXXXXX ; 33.5E ABCD:9876:1234 added: 2017-10-17 @ 13:14:15 // stripped namespace ++ // F 1A2B3C4D 20180123 XXXXXXXXXXXXXXXX ; av:5 pmt:0134 sid:0001 added: 2017-10-17 @ 13:14:15 // universal ++ ++ uint8_t pidcount; ++ uint16_t frequency, degrees, pmtpid, srvid, tsid, onid; ++ uint32_t ens; ++ char compass, polarisation, timeStr1[9], timeStr2[19]; ++ ++ if (datecoded) ++ { ++ Date2Str(timeStr1, sizeof(timeStr1), 4, 3); ++ } ++ else ++ { ++ snprintf(timeStr1, sizeof(timeStr1), "00000000"); ++ } ++ ++ Date2Str(timeStr2, sizeof(timeStr2), 0, 2); ++ ++ if (isNamespaceHash) // Namespace hash ++ { ++ ens = b2i(4, ecm + ecmLen - 4); // Namespace will be the last 4 bytes of the ecm ++ degrees = (ens >> 16) & 0x0FFF; // Remove not-a-pid flag ++ ++ if (degrees > 1800) ++ { ++ degrees = 3600 - degrees; ++ compass = 'W'; ++ } ++ else ++ { ++ compass = 'E'; ++ } ++ ++ if (0 == (ens & 0xFFFF)) // Stripped namespace hash ++ { ++ srvid = b2i(2, ecm + 3); ++ tsid = b2i(2, ecm + ecmLen - 8); ++ onid = b2i(2, ecm + ecmLen - 6); ++ // Printing degree sign "\u00B0" requires c99 standard ++ snprintf(buf, len, "F %08X %s XXXXXXXXXXXXXXXX ; %5.1f%c %04X:%04X:%04X added: %s", ++ hash, timeStr1, degrees / 10.0, compass, onid, tsid, srvid, timeStr2); ++ } ++ else // Full namespace hash ++ { ++ srvid = b2i(2, ecm + 3); ++ frequency = ens & 0x7FFF; // Remove polarity bit ++ polarisation = ens & 0x8000 ? 'V' : 'H'; ++ // Printing degree sign "\u00B0" requires c99 standard ++ snprintf(buf, len, "F %08X %s XXXXXXXXXXXXXXXX ; %5.1f%c %5d%c sid:%04X added: %s", ++ hash, timeStr1, degrees / 10.0, compass, frequency, polarisation, srvid, timeStr2); ++ } ++ } ++ else // Universal hash ++ { ++ srvid = b2i(2, ecm + 3); ++ pmtpid = b2i(2, ecm + 5); ++ pidcount = (ecmLen - 15) / 2; // video + audio pids count ++ snprintf(buf, len, "F %08X %s XXXXXXXXXXXXXXXX ; av:%d pmt:%04X sid:%04X added: %s", ++ hash, timeStr1, pidcount, pmtpid, srvid, timeStr2); ++ } ++} ++ ++static int8_t BissIsCommonHash(uint32_t hash) ++{ ++ // Check universal hash against a number of commnon universal ++ // hashes in order to warn users about potential key clashes ++ ++ switch (hash) ++ { ++ case 0xBAFCD9FD: // 0001 0020 0200 1010 1020 (most common hash) ++ return 1; ++ case 0xA6A4FBD4: // 0001 0800 0200 1010 1020 ++ return 1; ++ case 0xEFAB7A4D: // 0001 0800 1010 1020 0200 ++ return 1; ++ case 0x83FA15D1: // 0001 0020 0134 0100 0101 ++ return 1; ++ case 0x58934C38: // 0001 0800 1010 1020 1030 0200 ++ return 1; ++ case 0x2C3CEC17: // 0001 0020 0134 0100 ++ return 1; ++ case 0x73DF7F7E: // 0001 0020 0200 1010 1020 1030 ++ return 1; ++ case 0xAFA85BC8: // 0001 0020 0021 0022 0023 ++ return 1; ++ case 0x8C51F31D: // 0001 0800 0200 1010 1020 1030 1040 ++ return 1; ++ case 0xE2F9BD29: // 0001 0800 0200 1010 1020 1030 ++ return 1; ++ case 0xB9EBE0FF: // 0001 0100 0200 1010 1020 (less common hash) ++ return 1; ++ default: ++ return 0; ++ } ++} ++ ++static int8_t BissIsValidNamespace(uint32_t namespace) ++{ ++ // Note to developers: ++ // If we ever have a satellite at 0.0E, edit to allow stripped namespace ++ // '0xA0000000' with an additional test on tsid and onid being != 0 ++ ++ uint16_t orbital, frequency; ++ ++ orbital = (namespace >> 16) & 0x0FFF; ++ frequency = namespace & 0x7FFF; ++ ++ if ((namespace & 0xA0000000) != 0xA0000000) return 0; // Value isn't flagged as namespace ++ if (namespace == 0xA0000000) return 0; // Empty namespace ++ if (orbital > 3599) return 0; // Allow only DVB-S ++ if (frequency == 0) return 1; // Stripped namespace ++ if (frequency >= 3400 && frequency <= 4200) return 1; // Super extended C band ++ if (frequency >= 10700 && frequency <= 12750) return 1; // Ku band Europe ++ ++ return 0; ++} ++ ++static int8_t BissGetKey(uint32_t provider, uint8_t *key, int8_t dateCoded, int8_t printMsg) ++{ ++ // If date-coded keys are enabled in the webif, this function evaluates the expiration date ++ // of the keys found. Expired keys are not sent to BissECM(). If date-coded keys are disabled, ++ // then all keys found are sent without any evaluation. It takes the "provider" as input and ++ // outputs the "key". Returns 0 (Key not found, or expired) or 1 (Key found). ++ ++ // printMsg: 0 => No message ++ // printMsg: 1 => Print message only if key is found ++ // printMsg: 2 => Always print message, regardless if key is found or not ++ ++ char keyExpDate[9] = "00000000"; ++ ++ if (FindKey('F', provider, 0, keyExpDate, key, 8, 0, 0, 0, NULL)) // Key found ++ { ++ if (dateCoded) // Date-coded keys are enabled, evaluate expiration date ++ { ++ char currentDate[9]; ++ Date2Str(currentDate, sizeof(currentDate), 0, 3); ++ ++ if (strncmp("00000000", keyExpDate, 9) == 0 || strncmp(currentDate, keyExpDate, 9) < 0) // Evergreen or not expired ++ { ++ if (printMsg == 1 || printMsg == 2) cs_log("Key found: F %08X %s", provider, keyExpDate); ++ return 1; ++ } ++ else // Key expired ++ { ++ key = NULL; // Make sure we don't send any expired key ++ if (printMsg == 2) cs_log("Key expired: F %08X %s", provider, keyExpDate); ++ return 0; ++ } ++ } ++ else // Date-coded keys are disabled, don't evaluate expiration date ++ { ++ if (printMsg == 1 || printMsg == 2) cs_log("Key found: F %08X %s", provider, keyExpDate); ++ return 1; ++ } ++ } ++ else // Key not found ++ { ++ if (printMsg == 2) cs_log("Key not found: F %08X", provider); ++ return 0; ++ } ++} ++ ++static int8_t BissECM(struct s_reader *rdr, const uint8_t *ecm, int16_t ecmDataLen, uint8_t *dw, uint16_t srvid, uint16_t ecmpid) ++{ ++ // Oscam's fake ecm consists of [sid] [pmtpid] [pid1] [pid2] ... [pidx] [tsid] [onid] [namespace] ++ // ++ // On enigma boxes tsid, onid and namespace should be non zero, while on non-enigma ++ // boxes they are usually all zero. ++ // The emulator creates a unique channel hash using srvid and enigma namespace or ++ // srvid, tsid, onid and namespace (in case of namespace without frequency) and ++ // another weaker (not unique) hash based on every pid of the channel. This universal ++ // hash should be available on all types of stbs (enigma and non-enigma). ++ ++ // Flags inside [namespace] ++ // ++ // emu r748- : no namespace, no flag ++ // emu r749 : 0x80000000 (full namespase), 0xC0000000 (stripped namespace, injected with tsid^onid^ecmpid^0x1FFF) ++ // emu r752+ : 0xA0000000 (pure namespace, either full, stripped, or null) ++ ++ // Key searches are made in order: ++ // Highest priority / tightest test first ++ // Lowest priority / loosest test last ++ // ++ // 1st: namespace hash (only on enigma boxes) ++ // 2nd: universal hash (all box types with emu r752+) ++ // 3rd: valid tsid, onid combination ++ // 4th: faulty ecmpid (other than 0x1FFF) ++ // 5th: reverse order pid (audio, video, pmt pids) ++ // 6th: standard BISS ecmpid (0x1FFF) ++ // 7th: default "All Feeds" key ++ ++ // If enabled in the webif, a date based key search can be performed. If the expiration ++ // date has passed, the key is not sent from BissGetKey(). This search method is only ++ // used in the namespace hash, universal hash and the default "All Feeds" key. ++ ++ uint8_t ecmCopy[EMU_MAX_ECM_LEN]; ++ uint16_t ecmLen = 0, pid = 0; ++ uint32_t i, ens = 0, hash = 0; ++ char tmpBuffer1[17], tmpBuffer2[90] = "0", tmpBuffer3[90] = "0"; ++ ++ if (ecmDataLen >= 3) ++ { ++ ecmLen = GetEcmLen(ecm); ++ } ++ ++ // First try using the unique namespace hash (enigma only) ++ if (ecmLen >= 13 && ecmLen <= ecmDataLen) // ecmLen >= 13, allow patching the ecmLen for r749 ecms ++ { ++ memcpy(ecmCopy, ecm, ecmLen); ++ ens = b2i(4, ecm + ecmLen - 4); // Namespace will be the last 4 bytes ++ ++ if (BissIsValidNamespace(ens)) // An r752+ extended ecm with valid namespace ++ { ++ BissUnifyOrbitals(&ens); ++ i2b_buf(4, ens, ecmCopy + ecmLen - 4); ++ ++ for (i = 0; i < 5; i++) // Find key matching hash made with frequency modified to: f+0, then f-1, f+1, f-2, lastly f+2 ++ { ++ ecmCopy[ecmLen - 1] = (i & 1) ? ecmCopy[ecmLen - 1] - i : ecmCopy[ecmLen - 1] + i; // frequency +/- 1, 2 MHz ++ ++ if (0 != (ens & 0xFFFF)) // Full namespace - Calculate hash with srvid and namespace only ++ { ++ i2b_buf(2, srvid, ecmCopy + ecmLen - 6); // Put [srvid] right before [namespace] ++ hash = crc32(0x2600, ecmCopy + ecmLen - 6, 6); ++ } ++ else // Namespace without frequency - Calculate hash with srvid, tsid, onid and namespace ++ { ++ i2b_buf(2, srvid, ecmCopy + ecmLen - 10); // Put [srvid] right before [tsid] [onid] [namespace] sequence ++ hash = crc32(0x2600, ecmCopy + ecmLen - 10, 10); ++ } ++ ++ if (BissGetKey(hash, dw, rdr->emu_datecodedenabled, i == 0 ? 2 : 1)) // Do not print "key not found" for frequency off by 1, 2 ++ { ++ memcpy(dw + 8, dw, 8); ++ return 0; ++ } ++ ++ if (i == 0) // No key found matching our hash: create example SoftCam.Key BISS line for the live log ++ { ++ BissAnnotate(tmpBuffer2, sizeof(tmpBuffer2), ecmCopy, ecmLen, hash, 1, rdr->emu_datecodedenabled); ++ } ++ ++ if (0 == (ens & 0xFFFF)) // Namespace without frequency - Do not iterate ++ { ++ break; ++ } ++ } ++ } ++ ++ if ((ens & 0xA0000000) == 0x80000000) // r749 ecms only (exclude r752+ ecms) ++ { ++ cs_log("Hey! Network buddy, you need to upgrade your OSCam-Emu"); ++ ecmCopy[ecmLen] = 0xA0; // Patch ecm to look like r752+ ++ ecmLen += 4; ++ ecmDataLen += 4; ++ } ++ } ++ ++ // Try using the universal channel hash (namespace not available) ++ if (ecmLen >= 17 && ecmLen <= ecmDataLen) // ecmLen >= 17, length of r749 ecms has been patched to match r752+ ecms ++ { ++ ens = b2i(4, ecmCopy + ecmLen - 4); // Namespace will be last 4 bytes ++ ++ if ((ens & 0xE0000000) == 0xA0000000) // We have an r752+ style ecm which contains pmtpid ++ { ++ memcpy(ecmCopy, ecm, ecmLen - 8); // Make a new ecmCopy from the original ecm as the old ecmCopy may be altered in namespace hash (skip [tsid] [onid] [namespace]) ++ hash = crc32(0x2600, ecmCopy + 3, ecmLen - 3 - 8); // ecmCopy doesn't have [tsid] [onid] [namespace] part ++ ++ if (BissGetKey(hash, dw, rdr->emu_datecodedenabled, 2)) // Key found ++ { ++ memcpy(dw + 8, dw, 8); ++ return 0; ++ } ++ ++ // No key found matching our hash: create example SoftCam.Key BISS line for the live log ++ BissAnnotate(tmpBuffer3, sizeof(tmpBuffer3), ecmCopy, ecmLen, hash, 0, rdr->emu_datecodedenabled); ++ } ++ } ++ ++ // Try using only [tsid][onid] (useful when many channels on a transpoder use the same key) ++ if (ecmLen >= 17 && ecmLen <= ecmDataLen) // ecmLen >= 17, length of r749 ecms has been patched to match r752+ ecms ++ { ++ ens = b2i(4, ecmCopy + ecmLen - 4); // Namespace will be last 4 bytes ++ ++ // We have an r752+ style ecm with stripped namespace, thus a valid [tsid][onid] combo to use as provider ++ if ((ens & 0xE000FFFF) == 0xA0000000 && BissGetKey(b2i(4, ecm + ecmLen - 8), dw, 0, 2)) ++ { ++ memcpy(dw + 8, dw, 8); ++ return 0; ++ } ++ ++ if ((ens & 0xE0000000) == 0xA0000000) // Strip [tsid] [onid] [namespace] on r752+ ecms ++ { ++ ecmLen -= 8; ++ ecmDataLen -= 8; ++ } ++ } ++ ++ // Try using ecmpid if it seems to be faulty (should be 0x1FFF always for BISS) ++ if (ecmpid != 0x1FFF && ecmpid != 0) ++ { ++ if (BissGetKey((srvid << 16) | ecmpid, dw, 0, 2)) ++ { ++ memcpy(dw + 8, dw, 8); ++ return 0; ++ } ++ } ++ ++ // Try to get the pid from oscam's fake ecm (only search [pid1] [pid2] ... [pidx] to be compatible with emu r748-) ++ if (ecmLen >= 7 && ecmLen <= ecmDataLen) // Use >= for radio channels with just one (audio) pid ++ { ++ // Reverse search order: last pid in list first ++ // Better identifies channels where they share identical video pid but have variable counts of audio pids ++ for (i = ecmLen - 2; i >= 5; i -= 2) ++ { ++ pid = b2i(2, ecm + i); ++ ++ if (BissGetKey((srvid << 16) | pid, dw, 0, 2)) ++ { ++ memcpy(dw + 8, dw, 8); ++ return 0; ++ } ++ } ++ } ++ ++ // Try using the standard BISS ecm pid ++ if (ecmpid == 0x1FFF || ecmpid == 0) ++ { ++ if (BissGetKey((srvid << 16) | 0x1FFF, dw, 0, 2)) ++ { ++ memcpy(dw + 8, dw, 8); ++ return 0; ++ } ++ } ++ ++ // Default BISS key for events with many feeds sharing same key ++ if (ecmpid != 0 && BissGetKey(0xA11FEED5, dw, rdr->emu_datecodedenabled, 2)) // Limit to local ecms, block netwotk ecms ++ { ++ memcpy(dw + 8, dw, 8); ++ cs_hexdump(0, dw, 8, tmpBuffer1, sizeof(tmpBuffer1)); ++ cs_log("No specific match found. Using 'All Feeds' key: %s", tmpBuffer1); ++ return 0; ++ } ++ ++ // Print example key lines for available hash search methods, if no key is found ++ if (strncmp(tmpBuffer2, "0", 2)) cs_log("Example key based on namespace hash: %s", tmpBuffer2); ++ if (strncmp(tmpBuffer3, "0", 2)) cs_log("Example key based on universal hash: %s", tmpBuffer3); ++ ++ // Check if universal hash is common and warn user ++ if (BissIsCommonHash(hash)) cs_log("Feed has commonly used pids, universal hash clashes in SoftCam.Key are likely!"); ++ ++ return 2; ++} ++ ++// PowerVu Emu ++static uint8_t PowervuCrc8Calc(uint8_t *data, int len) ++{ ++ int i; ++ uint8_t crc = 0x00; ++ uint8_t crcTable[256] = {0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, ++ 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, ++ 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, ++ 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, ++ 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, ++ 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, ++ 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, ++ 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, ++ 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, ++ 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, ++ 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, ++ 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, ++ 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, ++ 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, ++ 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, ++ 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3}; ++ ++ for(i = 0; i < len; i++) ++ { ++ crc = crcTable[data[i] ^ crc]; ++ } ++ ++ return crc; ++} ++ ++static void PowervuPadData(uint8_t *data, int len, uint8_t *dataPadded) ++{ ++ int i; ++ uint8_t pad[] = {0x01, 0x02, 0x22, 0x04, 0x20, 0x2A, 0x1F, 0x03, 0x04, 0x06, 0x02, 0x0C, 0x2B, 0x2B, 0x01, 0x7B}; ++ ++ for(i = 0; i < len; i++) ++ { ++ dataPadded[i] = data[i]; ++ } ++ ++ dataPadded[len] = 0x01; ++ ++ for(i = len + 1; i < 0x2F; i++) ++ { ++ dataPadded[i] = 0x00; ++ } ++ ++ dataPadded[0x2F] = len; ++ ++ for(i = 0; i < 0x10; i++) ++ { ++ dataPadded[0x30 + i] = pad[i]; ++ } ++} ++ ++static void PowervuHashMode01CustomMD5(uint8_t *data, uint8_t *hash) ++{ ++ int i, j, s; ++ uint32_t a, b, c, d, f = 0, g; ++ ++ uint32_t T[] = {0x783E16F6, 0xC267AC13, 0xA2B17F12, 0x6B8A31A4, 0xF910654D, 0xB702DBCB, 0x266CEF60, 0x5145E47C, ++ 0xB92E00D6, 0xE80A4A64, 0x8A07FA77, 0xBA7D89A9, 0xEBED8022, 0x653AAF2B, 0xF118B03B, 0x6CC16544, ++ 0x96EB6583, 0xF4E27E35, 0x1ABB119E, 0x068D3EF2, 0xDAEAA8A5, 0x3C312A3D, 0x59538388, 0xA100772F, ++ 0xAB0165CE, 0x979959E7, 0x5DD8F53D, 0x189662BA, 0xFD021A9C, 0x6BC2D338, 0x1EFF667E, 0x40C66888, ++ 0x6E9F07FF, 0x0CEF442F, 0x82D20190, 0x4E8CAEAC, 0x0F7CB305, 0x2E73FBE7, 0x1CE884A2, 0x7A60BD52, ++ 0xC348B30D, 0x081CE3AA, 0xA12220E7, 0x38C7EC79, 0xCBD8DD3A, 0x62B4FBA5, 0xAD2A63DB, 0xE4D0852E, ++ 0x53DE980F, 0x9C8DDA59, 0xA6B4CEDE, 0xB48A7692, 0x0E2C46A4, 0xEB9367CB, 0x165D72EE, 0x75532B45, ++ 0xB9CA8E97, 0x08C8837B, 0x966F917B, 0x527515B4, 0xF27A5E5D, 0xB71E6267, 0x7603D7E6, 0x9837DD69}; // CUSTOM T ++ ++ uint8_t r[] = {0x06, 0x0A, 0x0F, 0x15, 0x05, 0x09, 0x0E, 0x14, 0x04, 0x0B, 0x10, 0x17, 0x07, 0x0C, 0x11, 0x16}; // STANDARD REORDERED ++ ++ uint8_t tIdxInit[] = {0, 1, 5, 0}; // STANDARD ++ uint8_t tIdxIncr[] = {1, 5, 3, 7}; // STANDARD ++ ++ uint32_t h[] = {0xEAD81D2E, 0xCE4DC6E9, 0xF9B5C301, 0x10325476}; // CUSTOM h0, h1, h2 STANDARD h3 ++ uint32_t dataLongs[0x10]; ++ ++ for (i = 0; i < 0x10; i++) ++ { ++ dataLongs[i] = (data[4 * i + 0] << 0) + (data[4 * i + 1] << 8) + (data[4 * i + 2] << 16) + (data[4 * i + 3] << 24); ++ } ++ ++ a = h[0]; ++ b = h[1]; ++ c = h[2]; ++ d = h[3]; ++ ++ for (i = 0; i < 4; i++) ++ { ++ g = tIdxInit[i]; ++ ++ for (j = 0; j < 16; j++) ++ { ++ if (i == 0) ++ { ++ f = (b & c) | (~b & d); ++ } ++ else if (i == 1) ++ { ++ f = (b & d) | (~d & c); ++ } ++ else if (i == 2) ++ { ++ f = (b ^ c ^ d); ++ } ++ else if (i == 3) ++ { ++ f = (~d | b) ^ c; ++ } ++ ++ f = dataLongs[g] + a + T[16 * i + j] + f; ++ ++ s = r[4 * i + (j & 3)]; ++ f = (f << s) | (f >> (32 - s)); ++ ++ a = d; ++ d = c; ++ c = b; ++ b += f; ++ ++ g = (g + tIdxIncr[i]) & 0xF; ++ } ++ } ++ ++ h[0] += a; ++ h[1] += b; ++ h[2] += c; ++ h[3] += d; ++ ++ for (i = 0; i < 4; i++) ++ { ++ hash[4 * i + 0] = h[i] >> 0; ++ hash[4 * i + 1] = h[i] >> 8; ++ hash[4 * i + 2] = h[i] >> 16; ++ hash[4 * i + 3] = h[i] >> 24; ++ } ++} ++ ++static void PowervuHashMode02(uint8_t *data, uint8_t *hash) ++{ ++ int i; ++ uint32_t a, b, c, d, e, f = 0, tmp; ++ uint32_t h[] = {0x81887F3A, 0x36CCA480, 0x99056FB1, 0x79705BAE}; ++ uint32_t dataLongs[0x50]; ++ ++ for (i = 0; i < 0x10; i++) ++ { ++ dataLongs[i] = (data[4 * i + 0] << 24) + (data[4 * i + 1] << 16) + (data[4 * i + 2] << 8) + (data[4 * i + 3] << 0); ++ } ++ ++ for (i = 0; i < 0x40; i++) ++ { ++ dataLongs[0x10 + i] = dataLongs[0x10 + i - 2]; ++ dataLongs[0x10 + i] ^= dataLongs[0x10 + i - 7]; ++ dataLongs[0x10 + i] ^= dataLongs[0x10 + i - 13]; ++ dataLongs[0x10 + i] ^= dataLongs[0x10 + i - 16]; ++ } ++ ++ a = dataLongs[0]; ++ b = dataLongs[1]; ++ c = dataLongs[2]; ++ d = dataLongs[3]; ++ e = dataLongs[4]; ++ ++ for (i = 0; i < 0x50; i++) ++ { ++ if (i < 0x15) f = (b & c) | (~b & d); ++ else if (i < 0x28) f = (b ^ c ^ d); ++ else if (i < 0x3D) f = (b & c) | (c & d) | (b & d); ++ else if (i < 0x50) f = (b ^ c ^ d); ++ ++ tmp = a; ++ a = e + f + (a << 5) + (a >> 27) + h[i / 0x14] + dataLongs[i]; ++ e = d; ++ d = c; ++ c = (b << 30) + (b >> 2); ++ b = tmp; ++ } ++ ++ dataLongs[0] += a; ++ dataLongs[1] += b; ++ dataLongs[2] += c; ++ dataLongs[3] += d; ++ ++ for (i = 0; i < 4; i++) ++ { ++ hash[4 * i + 0] = dataLongs[i] >> 24; ++ hash[4 * i + 1] = dataLongs[i] >> 16; ++ hash[4 * i + 2] = dataLongs[i] >> 8; ++ hash[4 * i + 3] = dataLongs[i] >> 0; ++ } ++} ++ ++static void PowervuHashMode03(uint8_t *data, uint8_t *hash) ++{ ++ int i, j, k, s, s2, tmp; ++ uint32_t a, b, c, d, f = 0, g; ++ uint32_t a2, b2, c2, d2, f2 = 0, g2; ++ ++ uint32_t T[] = { 0xC88F3F2E, 0x967506BA, 0xDA877A7B, 0x0DECCDFE }; ++ uint32_t T2[] = { 0x01F42668, 0x39C7CDA5, 0xD490E2FE, 0x9965235D }; ++ ++ uint8_t r[] = { 0x0B, 0x0E, 0x0F, 0x0C, 0x05, 0x08, 0x07, 0x09, 0x0B, 0x0D, 0x0E, 0x0F, 0x06, 0x07, 0x09, 0x08, ++ 0x07, 0x06, 0x08, 0x0D, 0x0B, 0x09, 0x07, 0x0F, 0x07, 0x0C, 0x0F, 0x09, 0x0B, 0x07, 0x0D, 0x0C }; ++ ++ uint8_t tIdxIncr[] = { 0x07, 0x04, 0x0D, 0x01, 0x0A, 0x06, 0x0F, 0x03, 0x0C, 0x00, 0x09, 0x05, 0x02, 0x0E, 0x0B, 0x08, ++ 0x05, 0x0D, 0x02, 0x00, 0x04, 0x09, 0x03, 0x08, 0x01, 0x0A, 0x07, 0x0B, 0x06, 0x0F, 0x0C, 0x0E }; ++ ++ uint32_t h[] = { 0xC8616857, 0x9D3F5B8E, 0x4D7B8F76, 0x97BC8D80 }; ++ ++ uint32_t dataLongs[0x50]; ++ uint32_t result[4]; ++ ++ for (i = 0; i < 0x10; i++) ++ { ++ dataLongs[i] = (data[4 * i + 0] << 24) + (data[4 * i + 1] << 16) + (data[4 * i + 2] << 8) + (data[4 * i + 3] << 0); ++ } ++ ++ a = h[0]; ++ b = h[1]; ++ c = h[2]; ++ d = h[3]; ++ ++ a2 = h[3]; ++ b2 = h[2]; ++ c2 = h[1]; ++ d2 = h[0]; ++ ++ for (i = 0; i < 4; i++) ++ { ++ for (j = 0; j < 16; j++) ++ { ++ tmp = j; ++ ++ for (k = 0; k < i; k++) ++ { ++ tmp = tIdxIncr[tmp]; ++ } ++ ++ g = 0x0F - tmp; ++ g2 = tmp; ++ ++ if (i == 0) f = (b & d) | (~d & c); ++ else if (i == 1) f = (~c | b) ^ d; ++ else if (i == 2) f = (~b & d) | (b & c); ++ else if (i == 3) f = (b ^ c ^ d); ++ ++ if (i == 0) f2 = (b2 ^ c2 ^ d2); ++ else if (i == 1) f2 = (~b2 & d2) | (b2 & c2); ++ else if (i == 2) f2 = (~c2 | b2) ^ d2; ++ else if (i == 3) f2 = (b2 & d2) | (~d2 & c2); ++ ++ f = dataLongs[g] + a + T[i] + f; ++ s = r[0x0F + (((i & 1) ^ 1) << 4) - j]; ++ f = (f << s) | (f >> (32 - s)); ++ ++ f2 = dataLongs[g2] + a2 + T2[i] + f2; ++ s2 = r[((i & 1) << 4) + j]; ++ f2 = (f2 << s2) | (f2 >> (32 - s2)); ++ ++ a = d; ++ d = (c << 10) | (c >> 22); ++ c = b; ++ b = f; ++ ++ a2 = d2; ++ d2 = (c2 << 10) | (c2 >> 22); ++ c2 = b2; ++ b2 = f2; ++ } ++ } ++ ++ result[0] = h[3] + b + a2; ++ result[1] = h[2] + c + b2; ++ result[2] = h[1] + d + c2; ++ result[3] = h[0] + a + d2; ++ ++ for (i = 0; i < 4; i++) ++ { ++ hash[4 * i + 0] = result[i] >> 0; ++ hash[4 * i + 1] = result[i] >> 8; ++ hash[4 * i + 2] = result[i] >> 16; ++ hash[4 * i + 3] = result[i] >> 24; ++ } ++} ++ ++uint8_t table04[] = { 0x02, 0x03, 0x07, 0x0B, 0x0D, 0x08, 0x00, 0x01, 0x2B, 0x2D, 0x28, 0x20, 0x21, 0x0A, 0x0C, 0x0E, ++ 0x22, 0x36, 0x23, 0x27, 0x29, 0x24, 0x25, 0x26, 0x2A, 0x3C, 0x3E, 0x3F, 0x0F, 0x2C, 0x2E, 0x2F, ++ 0x12, 0x13, 0x17, 0x1B, 0x1C, 0x18, 0x10, 0x11, 0x19, 0x14, 0x15, 0x16, 0x1A, 0x09, 0x04, 0x05, ++ 0x32, 0x33, 0x37, 0x3B, 0x06, 0x1C, 0x1E, 0x1F, 0x3D, 0x38, 0x30, 0x31, 0x39, 0x34, 0x35, 0x3A }; ++ ++uint8_t table05[] = { 0x08, 0x09, 0x0A, 0x03, 0x04, 0x3F, 0x27, 0x28, 0x29, 0x2A, 0x05, 0x0B, 0x1B, 0x1C, 0x1C, 0x1E, ++ 0x20, 0x0C, 0x0D, 0x22, 0x23, 0x24, 0x00, 0x01, 0x02, 0x06, 0x07, 0x25, 0x26, 0x0E, 0x0F, 0x21, ++ 0x10, 0x11, 0x12, 0x2E, 0x2F, 0x13, 0x14, 0x15, 0x2B, 0x2C, 0x2D, 0x16, 0x17, 0x18, 0x19, 0x1A, ++ 0x30, 0x31, 0x37, 0x3B, 0x3C, 0x3D, 0x3E, 0x1F, 0x38, 0x39, 0x32, 0x33, 0x34, 0x35, 0x36, 0x3A }; ++ ++uint8_t table06[] = { 0x00, 0x01, 0x02, 0x06, 0x07, 0x08, 0x03, 0x2A, 0x2B, 0x2C, 0x2E, 0x2F, 0x04, 0x05, 0x09, 0x0D, ++ 0x20, 0x21, 0x22, 0x26, 0x27, 0x3A, 0x3B, 0x3C, 0x3E, 0x3F, 0x10, 0x11, 0x12, 0x16, 0x17, 0x28, ++ 0x18, 0x13, 0x14, 0x15, 0x19, 0x1C, 0x1A, 0x1B, 0x1C, 0x1E, 0x1F, 0x23, 0x24, 0x25, 0x29, 0x2D, ++ 0x30, 0x31, 0x32, 0x36, 0x37, 0x38, 0x33, 0x34, 0x0A, 0x0B, 0x0C, 0x0E, 0x0F, 0x35, 0x39, 0x3D }; ++ ++uint8_t table07[] = { 0x10, 0x11, 0x12, 0x17, 0x1C, 0x1E, 0x0E, 0x38, 0x39, 0x3A, 0x13, 0x14, 0x29, 0x2A, 0x16, 0x1F, ++ 0x00, 0x01, 0x02, 0x3C, 0x3D, 0x3E, 0x3F, 0x07, 0x08, 0x09, 0x03, 0x04, 0x05, 0x06, 0x3B, 0x0A, ++ 0x20, 0x21, 0x22, 0x19, 0x1A, 0x1B, 0x1C, 0x0B, 0x0C, 0x15, 0x23, 0x24, 0x25, 0x26, 0x18, 0x0F, ++ 0x30, 0x31, 0x2B, 0x33, 0x34, 0x35, 0x36, 0x37, 0x27, 0x28, 0x2C, 0x2D, 0x2E, 0x2F, 0x32, 0x0D }; ++ ++uint8_t table08[] = { 0x10, 0x11, 0x1E, 0x17, 0x18, 0x19, 0x12, 0x13, 0x14, 0x1C, 0x1C, 0x15, 0x0D, 0x05, 0x06, 0x0A, ++ 0x00, 0x01, 0x0E, 0x07, 0x08, 0x09, 0x02, 0x2D, 0x25, 0x26, 0x2A, 0x2B, 0x2F, 0x03, 0x04, 0x0C, ++ 0x20, 0x21, 0x2E, 0x27, 0x28, 0x29, 0x30, 0x31, 0x3E, 0x37, 0x38, 0x39, 0x22, 0x23, 0x24, 0x2C, ++ 0x32, 0x33, 0x34, 0x3C, 0x3D, 0x35, 0x36, 0x3A, 0x3B, 0x0B, 0x0F, 0x16, 0x1A, 0x1B, 0x1F, 0x3F }; ++ ++uint8_t table09[] = { 0x20, 0x21, 0x24, 0x22, 0x23, 0x2A, 0x2B, 0x33, 0x35, 0x38, 0x39, 0x36, 0x2D, 0x2C, 0x2E, 0x2F, ++ 0x00, 0x01, 0x04, 0x02, 0x25, 0x28, 0x08, 0x09, 0x06, 0x07, 0x0A, 0x0B, 0x0D, 0x0C, 0x0E, 0x0F, ++ 0x10, 0x11, 0x14, 0x12, 0x13, 0x15, 0x19, 0x16, 0x29, 0x26, 0x03, 0x17, 0x1A, 0x1C, 0x1C, 0x1E, ++ 0x30, 0x31, 0x34, 0x32, 0x37, 0x3A, 0x3B, 0x3D, 0x3C, 0x3E, 0x3F, 0x1B, 0x05, 0x18, 0x27, 0x1F }; ++ ++uint8_t table0A[] = { 0x00, 0x04, 0x05, 0x0B, 0x0C, 0x06, 0x09, 0x0A, 0x0E, 0x0D, 0x0F, 0x25, 0x15, 0x1B, 0x1C, 0x16, ++ 0x10, 0x11, 0x01, 0x02, 0x03, 0x07, 0x08, 0x12, 0x13, 0x17, 0x18, 0x14, 0x23, 0x27, 0x28, 0x24, ++ 0x30, 0x31, 0x32, 0x33, 0x37, 0x38, 0x34, 0x35, 0x3B, 0x3C, 0x20, 0x21, 0x22, 0x2B, 0x2C, 0x26, ++ 0x36, 0x39, 0x3A, 0x3E, 0x3D, 0x19, 0x1A, 0x1E, 0x1C, 0x1F, 0x3F, 0x29, 0x2A, 0x2E, 0x2D, 0x2F }; ++ ++static void PowervuHashModes04to0ATables(uint8_t *data, uint8_t *hash, uint8_t *table) ++{ ++ int i; ++ ++ for (i = 0; i < 0x10; i++) ++ { ++ hash[i] = table[i]; ++ hash[i] ^= data[table[i]]; ++ hash[i] ^= table[0x10 + i]; ++ hash[i] ^= data[table[0x10 + i]]; ++ hash[i] ^= table[0x20 + i]; ++ hash[i] ^= data[table[0x20 + i]]; ++ hash[i] ^= table[0x30 + i]; ++ hash[i] ^= data[table[0x30 + i]]; ++ } ++} ++ ++static void PowervuCreateHash(uint8_t *data, int len, uint8_t *hash, int mode) ++{ ++ uint8_t dataPadded[0x40]; ++ ++ PowervuPadData(data, len, dataPadded); ++ ++ switch(mode) ++ { ++ case 1: ++ PowervuHashMode01CustomMD5(dataPadded, hash); ++ break; ++ ++ case 2: ++ PowervuHashMode02(dataPadded, hash); ++ break; ++ ++ case 3: ++ PowervuHashMode03(dataPadded, hash); ++ break; ++ ++ case 4: ++ PowervuHashModes04to0ATables(dataPadded, hash, table04); ++ break; ++ ++ case 5: ++ PowervuHashModes04to0ATables(dataPadded, hash, table05); ++ break; ++ ++ case 6: ++ PowervuHashModes04to0ATables(dataPadded, hash, table06); ++ break; ++ ++ case 7: ++ PowervuHashModes04to0ATables(dataPadded, hash, table07); ++ break; ++ ++ case 8: ++ PowervuHashModes04to0ATables(dataPadded, hash, table08); ++ break; ++ ++ case 9: ++ PowervuHashModes04to0ATables(dataPadded, hash, table09); ++ break; ++ ++ case 10: ++ PowervuHashModes04to0ATables(dataPadded, hash, table0A); ++ break; ++ ++ default: ++ cs_log("A new hash mode [%d] is in use.", mode); ++ break; ++ } ++} ++ ++static void PowervuCreateDataEcmEmm(uint8_t *emmEcm, uint8_t *pos, int lenHeader, int len, uint8_t *data) ++{ ++ int i; ++ ++ for(i = 0; i < len; i++) ++ { ++ data[i] = emmEcm[lenHeader + pos[i]]; ++ } ++} ++ ++static uint8_t PowervuCreateDataCw(uint8_t *seed, uint8_t lenSeed, uint8_t *baseCw, uint8_t val, uint8_t *seedEcmCw, uint8_t *data) ++{ ++ int i; ++ ++ for(i = 0; i < lenSeed; i++) ++ { ++ data[i] = seed[i]; ++ } ++ ++ for(i = 0; i < 7; i++) ++ { ++ data[lenSeed + i] = baseCw[i]; ++ } ++ ++ data[lenSeed + 7] = val; ++ ++ for(i = 0; i < 16; i++) ++ { ++ data[lenSeed + 7 + 1 + i] = seedEcmCw[i]; ++ } ++ ++ return lenSeed + 7 + 1 + 0x10; ++} ++ ++static uint8_t PowervuUnmaskEcm(uint8_t *ecm, uint8_t *seedEcmCw) ++{ ++ int i, l; ++ ++ uint8_t sourcePos[] = {0x04, 0x05, 0x06, 0x07, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x17, 0x1C, 0x1D, 0x1F, 0x23, ++ 0x24, 0x25, 0x26, 0x27, 0x29, 0x2C, 0x2D, 0x2E}; ++ uint8_t destPos[] = {0x08, 0x09, 0x11, 0x18, 0x19, 0x1A, 0x1B, 0x1E, 0x20, 0x21, 0x22, 0x28, 0x2A, 0x2B, 0x2F, 0x30}; ++ uint8_t seedCwPos[] = {0x07, 0x0A, 0x04, 0x0D, 0x05, 0x0E, 0x06, 0x0B, 0x10, 0x0C, 0x0F}; ++ ++ uint8_t data[0x18]; ++ uint8_t mask[0x10]; ++ uint8_t hashModeEcm; ++ uint8_t hashModeCw; ++ uint32_t crc; ++ ++ // Create seed for CW decryption ++ memset(seedEcmCw, 0, 0x10); ++ ++ int extraBytesLen = ecm[9]; ++ int startOffset = extraBytesLen + 0x0A; ++ ++ for (i = 0; i < 0x0B; i++) ++ { ++ seedEcmCw[i] = ecm[startOffset + seedCwPos[i]]; ++ } ++ ++ // Read hash mode CW ++ hashModeCw = ecm[28 + extraBytesLen] ^ PowervuCrc8Calc(seedEcmCw, 0x10); ++ ++ // Create mask for ECM decryption ++ PowervuCreateDataEcmEmm(ecm, sourcePos, startOffset, 0x18, data); ++ ++ hashModeEcm = ecm[8] ^ PowervuCrc8Calc(data, 0x18); ++ ++ PowervuCreateHash(data, 0x18, mask, hashModeEcm); ++ ++ // Fix header ++ ecm[3] &= 0x0F; ++ ecm[3] |= 0x30; ++ ecm[8] = 0x00; ++ ecm[28 + extraBytesLen] = 0x00; ++ ++ // Unmask body ++ for (i = 0; i < 0x10; i++) ++ { ++ ecm[startOffset + destPos[i]] ^= mask[i & 0x0F]; ++ } ++ ++ // Fix CRC (optional) ++ l = (((ecm[1] << 8) + ecm[2]) & 0xFFF) + 3 - 4; ++ ++ crc = fletcher_crc32(ecm, l); ++ ++ ecm[l + 0] = crc >> 24; ++ ecm[l + 1] = crc >> 16; ++ ecm[l + 2] = crc >> 8; ++ ecm[l + 3] = crc >> 0; ++ ++ return hashModeCw; ++} ++ ++static void PowervuCreateCw(uint8_t *seed, uint8_t lenSeed, uint8_t *baseCw, uint8_t val, ++ uint8_t *seedEcmCw, uint8_t *cw, int modeDesCsa, int hashMode) ++{ ++ uint8_t tableFixParity[] = {0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07, 0x08, 0x08, 0x0B, 0x0B, 0x0D, 0x0D, 0x0E, 0x0E, ++ 0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16, 0x19, 0x19, 0x1A, 0x1A, 0x1C, 0x1C, 0x1F, 0x1F, ++ 0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26, 0x29, 0x29, 0x2A, 0x2A, 0x2C, 0x2C, 0x2F, 0x2F, ++ 0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37, 0x38, 0x38, 0x3B, 0x3B, 0x3D, 0x3D, 0x3E, 0x3E, ++ 0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46, 0x49, 0x49, 0x4A, 0x4A, 0x4C, 0x4C, 0x4F, 0x4F, ++ 0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57, 0x58, 0x58, 0x5B, 0x5B, 0x5D, 0x5D, 0x5E, 0x5E, ++ 0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67, 0x68, 0x68, 0x6B, 0x6B, 0x6D, 0x6D, 0x6E, 0x6E, ++ 0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76, 0x79, 0x79, 0x7A, 0x7A, 0x7C, 0x7C, 0x7F, 0x7F, ++ 0x80, 0x80, 0x83, 0x83, 0x85, 0x85, 0x86, 0x86, 0x89, 0x89, 0x8A, 0x8A, 0x8C, 0x8C, 0x8F, 0x8F, ++ 0x91, 0x91, 0x92, 0x92, 0x94, 0x94, 0x97, 0x97, 0x98, 0x98, 0x9B, 0x9B, 0x9D, 0x9D, 0x9E, 0x9E, ++ 0xA1, 0xA1, 0xA2, 0xA2, 0xA4, 0xA4, 0xA7, 0xA7, 0xA8, 0xA8, 0xAB, 0xAB, 0xAD, 0xAD, 0xAE, 0xAE, ++ 0xB0, 0xB0, 0xB3, 0xB3, 0xB5, 0xB5, 0xB6, 0xB6, 0xB9, 0xB9, 0xBA, 0xBA, 0xBC, 0xBC, 0xBF, 0xBF, ++ 0xC1, 0xC1, 0xC2, 0xC2, 0xC4, 0xC4, 0xC7, 0xC7, 0xC8, 0xC8, 0xCB, 0xCB, 0xCD, 0xCD, 0xCE, 0xCE, ++ 0xD0, 0xD0, 0xD3, 0xD3, 0xD5, 0xD5, 0xD6, 0xD6, 0xD9, 0xD9, 0xDA, 0xDA, 0xDC, 0xDC, 0xDF, 0xDF, ++ 0xE0, 0xE0, 0xE3, 0xE3, 0xE5, 0xE5, 0xE6, 0xE6, 0xE9, 0xE9, 0xEA, 0xEA, 0xEC, 0xEC, 0xEF, 0xEF, ++ 0xF1, 0xF1, 0xF2, 0xF2, 0xF4, 0xF4, 0xF7, 0xF7, 0xF8, 0xF8, 0xFB, 0xFB, 0xFD, 0xFD, 0xFE, 0xFE}; ++ ++ uint8_t data[0x1C]; ++ uint8_t hash[0x10]; ++ uint8_t lenData; ++ int i; ++ ++ lenData = PowervuCreateDataCw(seed, lenSeed, baseCw, val, seedEcmCw, data); ++ PowervuCreateHash(data, lenData, hash, hashMode); ++ ++ for(i = 0; i < 8; i++) ++ { ++ cw[i] = hash[i]; ++ } ++ ++ if(modeDesCsa == 0) // DES - Fix Parity Bits ++ { ++ for(i = 0; i < 8; i++) ++ { ++ cw[i] = tableFixParity[cw[i]]; ++ } ++ } ++ else if(modeDesCsa == 1) // CSA - Fix Checksums ++ { ++ cw[3] = cw[0] + cw[1] + cw[2]; ++ cw[7] = cw[4] + cw[5] + cw[6]; ++ } ++} ++ ++static int8_t GetPowervuKey(uint8_t *buf, uint32_t ident, char keyName, uint32_t keyIndex, uint32_t keyLength, uint8_t isCriticalKey, uint32_t keyRef) ++{ ++ char keyStr[EMU_MAX_CHAR_KEYNAME]; ++ ++ snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "%c%X", keyName, keyIndex); ++ if(FindKey('P', ident, 0xFFFF0000, keyStr, buf, keyLength, isCriticalKey, keyRef, 0, NULL)) { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int8_t GetPowervuEmmKey(uint8_t *buf, uint32_t ident, char *keyName, uint32_t keyLength, uint8_t isCriticalKey, uint32_t keyRef, uint32_t *getProvider) ++{ ++ if(FindKey('P', ident, 0xFFFFFFFF, keyName, buf, keyLength, isCriticalKey, keyRef, 0, getProvider)) { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static const uint8_t PowerVu_A0_S_1[16] = {0x33, 0xA4, 0x44, 0x3C, 0xCA, 0x2E, 0x75, 0x7B, 0xBC, 0xE6, 0xE5, 0x35, 0xA0, 0x55, 0xC9, 0xA2}; ++static const uint8_t PowerVu_A0_S_2[16] = {0x5A, 0xB0, 0x2C, 0xBC, 0xDA, 0x32, 0xE6, 0x92, 0x40, 0x53, 0x6E, 0xF9, 0x69, 0x11, 0x1E, 0xFB}; ++static const uint8_t PowerVu_A0_S_3[16] = {0x4E, 0x18, 0x9B, 0x19, 0x79, 0xFB, 0x01, 0xFA, 0xE3, 0xE1, 0x28, 0x3D, 0x32, 0xE4, 0x92, 0xEA}; ++static const uint8_t PowerVu_A0_S_4[16] = {0x05, 0x6F, 0x37, 0x66, 0x35, 0xE1, 0x58, 0xD0, 0xB4, 0x6A, 0x97, 0xAE, 0xD8, 0x91, 0x27, 0x56}; ++static const uint8_t PowerVu_A0_S_5[16] = {0x7B, 0x26, 0xAD, 0x34, 0x3D, 0x77, 0x39, 0x51, 0xE0, 0xE0, 0x48, 0x8C, 0x39, 0xF5, 0xE8, 0x47}; ++static const uint8_t PowerVu_A0_S_6[16] = {0x74, 0xFA, 0x4D, 0x79, 0x42, 0x39, 0xD1, 0xA4, 0x99, 0xA3, 0x97, 0x07, 0xDF, 0x14, 0x3A, 0xC4}; ++static const uint8_t PowerVu_A0_S_7[16] = {0xC6, 0x1E, 0x3C, 0x24, 0x11, 0x08, 0x5D, 0x6A, 0xEB, 0x97, 0xB9, 0x25, 0xA7, 0xFA, 0xE9, 0x1A}; ++static const uint8_t PowerVu_A0_S_8[16] = {0x9A, 0xAD, 0x72, 0xD7, 0x7C, 0x68, 0x3B, 0x55, 0x1D, 0x4A, 0xA2, 0xB0, 0x38, 0xB9, 0x56, 0xD0}; ++static const uint8_t PowerVu_A0_S_9[32] = {0x61, 0xDA, 0x5F, 0xB7, 0xEB, 0xC6, 0x3F, 0x6C, 0x09, 0xF3, 0x64, 0x38, 0x33, 0x08, 0xAA, 0x15, ++ 0xCC, 0xEF, 0x22, 0x64, 0x01, 0x2C, 0x12, 0xDE, 0xF4, 0x6E, 0x3C, 0xCD, 0x1A, 0x64, 0x63, 0x7C ++ }; ++ ++static const uint8_t PowerVu_00_S_1[16] = {0x97, 0x13, 0xEB, 0x6B, 0x04, 0x5E, 0x60, 0x3A, 0xD9, 0xCC, 0x91, 0xC2, 0x5A, 0xFD, 0xBA, 0x0C}; ++static const uint8_t PowerVu_00_S_2[16] = {0x61, 0x3C, 0x03, 0xB0, 0xB5, 0x6F, 0xF8, 0x01, 0xED, 0xE0, 0xE5, 0xF3, 0x78, 0x0F, 0x0A, 0x73}; ++static const uint8_t PowerVu_00_S_3[16] = {0xFD, 0xDF, 0xD2, 0x97, 0x06, 0x14, 0x91, 0xB5, 0x36, 0xAD, 0xBC, 0xE1, 0xB3, 0x00, 0x66, 0x41}; ++static const uint8_t PowerVu_00_S_4[16] = {0x8B, 0xD9, 0x18, 0x0A, 0xED, 0xEE, 0x61, 0x34, 0x1A, 0x79, 0x80, 0x8C, 0x1E, 0x7F, 0xC5, 0x9F}; ++static const uint8_t PowerVu_00_S_5[16] = {0xB0, 0xA1, 0xF2, 0xB8, 0xEA, 0x72, 0xDD, 0xD3, 0x30, 0x65, 0x2B, 0x1E, 0xE9, 0xE1, 0x45, 0x29}; ++static const uint8_t PowerVu_00_S_6[16] = {0x5D, 0xCA, 0x53, 0x75, 0xB2, 0x24, 0xCE, 0xAF, 0x21, 0x54, 0x9E, 0xBE, 0x02, 0xA9, 0x4C, 0x5D}; ++static const uint8_t PowerVu_00_S_7[16] = {0x42, 0x66, 0x72, 0x83, 0x1B, 0x2D, 0x22, 0xC9, 0xF8, 0x4D, 0xBA, 0xCD, 0xBB, 0x20, 0xBD, 0x6B}; ++static const uint8_t PowerVu_00_S_8[16] = {0xC4, 0x0C, 0x6B, 0xD3, 0x6D, 0x94, 0x7E, 0x53, 0xCE, 0x96, 0xAC, 0x40, 0x2C, 0x7A, 0xD3, 0xA9}; ++static const uint8_t PowerVu_00_S_9[32] = {0x31, 0x82, 0x4F, 0x9B, 0xCB, 0x6F, 0x9D, 0xB7, 0xAE, 0x68, 0x0B, 0xA0, 0x93, 0x15, 0x32, 0xE2, ++ 0xED, 0xE9, 0x47, 0x29, 0xC2, 0xA8, 0x92, 0xEF, 0xBA, 0x27, 0x22, 0x57, 0x76, 0x54, 0xC0, 0x59, ++ }; ++ ++static uint8_t PowervuSbox(uint8_t *input, uint8_t mode) ++{ ++ uint8_t s_index, bit, last_index, last_bit; ++ uint8_t const *Sbox1, *Sbox2, *Sbox3, *Sbox4, *Sbox5, *Sbox6, *Sbox7, *Sbox8, *Sbox9; ++ ++ if(mode) ++ { ++ Sbox1 = PowerVu_A0_S_1; ++ Sbox2 = PowerVu_A0_S_2; ++ Sbox3 = PowerVu_A0_S_3; ++ Sbox4 = PowerVu_A0_S_4; ++ Sbox5 = PowerVu_A0_S_5; ++ Sbox6 = PowerVu_A0_S_6; ++ Sbox7 = PowerVu_A0_S_7; ++ Sbox8 = PowerVu_A0_S_8; ++ Sbox9 = PowerVu_A0_S_9; ++ } ++ else ++ { ++ Sbox1 = PowerVu_00_S_1; ++ Sbox2 = PowerVu_00_S_2; ++ Sbox3 = PowerVu_00_S_3; ++ Sbox4 = PowerVu_00_S_4; ++ Sbox5 = PowerVu_00_S_5; ++ Sbox6 = PowerVu_00_S_6; ++ Sbox7 = PowerVu_00_S_7; ++ Sbox8 = PowerVu_00_S_8; ++ Sbox9 = PowerVu_00_S_9; ++ } ++ ++ bit = (GetBit(input[2],0)<<2) | (GetBit(input[3],4)<<1) | (GetBit(input[5],3)); ++ s_index = (GetBit(input[0],0)<<3) | (GetBit(input[2],6)<<2) | (GetBit(input[2],4)<<1) | (GetBit(input[5],7)); ++ last_bit = GetBit(Sbox1[s_index],7-bit); ++ ++ bit = (GetBit(input[5],0)<<2) | (GetBit(input[4],0)<<1) | (GetBit(input[6],2)); ++ s_index = (GetBit(input[2],1)<<3) | (GetBit(input[2],2)<<2) | (GetBit(input[5],5)<<1) | (GetBit(input[5],1)); ++ last_bit = last_bit | (GetBit(Sbox2[s_index],7-bit)<<1); ++ ++ bit = (GetBit(input[6],0)<<2) | (GetBit(input[1],7)<<1) | (GetBit(input[6],7)); ++ s_index = (GetBit(input[1],3)<<3) | (GetBit(input[3],7)<<2) | (GetBit(input[1],5)<<1) | (GetBit(input[5],2)); ++ last_bit = last_bit | (GetBit(Sbox3[s_index], 7-bit)<<2); ++ ++ bit = (GetBit(input[1],0)<<2) | (GetBit(input[2],7)<<1) | (GetBit(input[2],5)); ++ s_index = (GetBit(input[6],3)<<3) | (GetBit(input[6],4)<<2) | (GetBit(input[6],6)<<1) | (GetBit(input[3],5)); ++ last_index = GetBit(Sbox4[s_index], 7-bit); ++ ++ bit = (GetBit(input[3],3)<<2) | (GetBit(input[4],6)<<1) | (GetBit(input[3],2)); ++ s_index = (GetBit(input[3],1)<<3) | (GetBit(input[4],5)<<2) | (GetBit(input[3],0)<<1) | (GetBit(input[4],7)); ++ last_index = last_index | (GetBit(Sbox5[s_index], 7-bit)<<1); ++ ++ bit = (GetBit(input[5],4)<<2) | (GetBit(input[4],4)<<1) | (GetBit(input[1],2)); ++ s_index = (GetBit(input[2],3)<<3) | (GetBit(input[6],5)<<2) | (GetBit(input[1],4)<<1) | (GetBit(input[4],1)); ++ last_index = last_index | (GetBit(Sbox6[s_index], 7-bit)<<2); ++ ++ bit = (GetBit(input[0],6)<<2) | (GetBit(input[0],7)<<1) | (GetBit(input[0],4)); ++ s_index = (GetBit(input[0],5)<<3) | (GetBit(input[0],3)<<2) | (GetBit(input[0],1)<<1) | (GetBit(input[0],2)); ++ last_index = last_index | (GetBit(Sbox7[s_index], 7-bit)<<3); ++ ++ bit = (GetBit(input[4],2)<<2) | (GetBit(input[4],3)<<1) | (GetBit(input[1],1)); ++ s_index = (GetBit(input[1],6)<<3) | (GetBit(input[6],1)<<2) | (GetBit(input[5],6)<<1) | (GetBit(input[3],6)); ++ last_index = last_index | (GetBit(Sbox8[s_index], 7-bit)<<4); ++ ++ return (GetBit(Sbox9[last_index&0x1f],7-last_bit)&1) ? 1: 0; ++} ++ ++static void PowervuDecrypt(uint8_t *data, uint32_t length, uint8_t *key, uint8_t sbox) ++{ ++ uint32_t i; ++ int32_t j, k; ++ uint8_t curByte, tmpBit; ++ ++ for(i = 0; i < length; i++) ++ { ++ curByte = data[i]; ++ ++ for(j = 7; j >= 0; j--) ++ { ++ data[i] = SetBit(data[i], j, (GetBit(curByte, j)^PowervuSbox(key, sbox))^GetBit(key[0], 7)); ++ ++ tmpBit = GetBit(data[i], j)^(GetBit(key[6], 0)); ++ if (tmpBit) ++ { ++ key[3] ^= 0x10; ++ } ++ ++ for (k = 6; k > 0; k--) ++ { ++ key[k] = (key[k]>>1) | (key[k-1]<<7); ++ } ++ key[0] = (key[0]>>1); ++ ++ key[0] = SetBit(key[0], 7, tmpBit); ++ } ++ } ++} ++ ++#define PVU_CW_VID 0 // VIDeo ++#define PVU_CW_HSD 1 // High Speed Data ++#define PVU_CW_A1 2 // Audio 1 ++#define PVU_CW_A2 3 // Audio 2 ++#define PVU_CW_A3 4 // Audio 3 ++#define PVU_CW_A4 5 // Audio 4 ++#define PVU_CW_UTL 6 // UTiLity ++#define PVU_CW_VBI 7 // Vertical Blanking Interval ++ ++#define PVU_CONVCW_VID_ECM 0x80 // VIDeo ++#define PVU_CONVCW_HSD_ECM 0x40 // High Speed Data ++#define PVU_CONVCW_A1_ECM 0x20 // Audio 1 ++#define PVU_CONVCW_A2_ECM 0x10 // Audio 2 ++#define PVU_CONVCW_A3_ECM 0x08 // Audio 3 ++#define PVU_CONVCW_A4_ECM 0x04 // Audio 4 ++#define PVU_CONVCW_UTL_ECM 0x02 // UTiLity ++#define PVU_CONVCW_VBI_ECM 0x01 // Vertical Blanking Interval ++ ++static uint8_t PowervuGetConvcwIndex(uint8_t ecmTag) ++{ ++ switch(ecmTag) ++ { ++ case PVU_CONVCW_VID_ECM: ++ return PVU_CW_VID; ++ ++ case PVU_CONVCW_HSD_ECM: ++ return PVU_CW_HSD; ++ ++ case PVU_CONVCW_A1_ECM: ++ return PVU_CW_A1; ++ ++ case PVU_CONVCW_A2_ECM: ++ return PVU_CW_A2; ++ ++ case PVU_CONVCW_A3_ECM: ++ return PVU_CW_A3; ++ ++ case PVU_CONVCW_A4_ECM: ++ return PVU_CW_A4; ++ ++ case PVU_CONVCW_UTL_ECM: ++ return PVU_CW_UTL; ++ ++ case PVU_CONVCW_VBI_ECM: ++ return PVU_CW_VBI; ++ ++ default: ++ return PVU_CW_VBI; ++ } ++} ++ ++static uint16_t PowervuGetSeedIV(uint8_t seedType, uint8_t *ecm) ++{ ++ switch(seedType) ++ { ++ case PVU_CW_VID: ++ return ((ecm[0x10] & 0x1F) <<3) | 0; ++ case PVU_CW_HSD: ++ return ((ecm[0x12] & 0x1F) <<3) | 2; ++ case PVU_CW_A1: ++ return ((ecm[0x11] & 0x3F) <<3) | 1; ++ case PVU_CW_A2: ++ return ((ecm[0x13] & 0x3F) <<3) | 1; ++ case PVU_CW_A3: ++ return ((ecm[0x19] & 0x3F) <<3) | 1; ++ case PVU_CW_A4: ++ return ((ecm[0x1A] & 0x3F) <<3) | 1;; ++ case PVU_CW_UTL: ++ return ((ecm[0x14] & 0x0F) <<3) | 4; ++ case PVU_CW_VBI: ++ return (((ecm[0x15] & 0xF8)>>3)<<3) | 5; ++ default: ++ return 0; ++ } ++} ++ ++static uint8_t PowervuExpandSeed(uint8_t seedType, uint8_t *seed) ++{ ++ uint8_t seedLength = 0, i; ++ ++ switch(seedType) ++ { ++ case PVU_CW_VID: ++ case PVU_CW_HSD: ++ seedLength = 4; ++ break; ++ case PVU_CW_A1: ++ case PVU_CW_A2: ++ case PVU_CW_A3: ++ case PVU_CW_A4: ++ seedLength = 3; ++ break; ++ case PVU_CW_UTL: ++ case PVU_CW_VBI: ++ seedLength = 2; ++ break; ++ default: ++ return seedLength; ++ } ++ ++ for(i=seedLength; i<7; i++) ++ { ++ seed[i] = seed[i%seedLength]; ++ } ++ ++ return seedLength; ++} ++ ++static void PowervuCalculateSeed(uint8_t seedType, uint8_t *ecm, uint8_t *seedBase, uint8_t *key, uint8_t *seed, uint8_t sbox) ++{ ++ uint16_t tmpSeed; ++ ++ tmpSeed = PowervuGetSeedIV(seedType, ecm+23); ++ seed[0] = (tmpSeed >> 2) & 0xFF; ++ seed[1] = ((tmpSeed & 0x3) << 6) | (seedBase[0] >> 2); ++ seed[2] = ( seedBase[0] << 6) | (seedBase[1] >> 2); ++ seed[3] = ( seedBase[1] << 6) | (seedBase[2] >> 2); ++ seed[4] = ( seedBase[2] << 6) | (seedBase[3] >> 2); ++ seed[5] = ( seedBase[3] << 6); ++ ++ PowervuDecrypt(seed, 6, key, sbox); ++ ++ seed[0] = (seed[1] << 2) | (seed[2] >> 6); ++ seed[1] = (seed[2] << 2) | (seed[3] >> 6); ++ seed[2] = (seed[3] << 2) | (seed[4] >> 6); ++ seed[3] = (seed[4] << 2) | (seed[5] >> 6); ++} ++ ++static void PowervuCalculateCw(uint8_t seedType, uint8_t *seed, uint8_t csaUsed, uint8_t *convolvedCw, ++ uint8_t *cw, uint8_t *baseCw, uint8_t *seedEcmCw, uint8_t hashModeCw, ++ uint8_t needsUnmasking, uint8_t xorMode) ++{ ++ int32_t k; ++ uint8_t seedLength, val = 0; ++ ++ seedLength = PowervuExpandSeed(seedType, seed); ++ ++ if(csaUsed) ++ { ++ if(!needsUnmasking || (hashModeCw == 0)) ++ { ++ for(k = 0; k < 7; k++) ++ { ++ seed[k] ^= baseCw[k]; ++ } ++ ++ cw[0] = seed[0] ^ convolvedCw[0]; ++ cw[1] = seed[1] ^ convolvedCw[1]; ++ cw[2] = seed[2] ^ convolvedCw[2]; ++ cw[3] = seed[3] ^ convolvedCw[3]; ++ cw[4] = seed[3] ^ convolvedCw[4]; ++ cw[5] = seed[4] ^ convolvedCw[5]; ++ cw[6] = seed[5] ^ convolvedCw[6]; ++ cw[7] = seed[6] ^ convolvedCw[7]; ++ } ++ } ++ else ++ { ++ if(xorMode == 0) ++ { ++ for(k = 0; k < 7; k++) ++ { ++ cw[k] = seed[k] ^ baseCw[k]; ++ } ++ } ++ ++ if(xorMode == 1) ++ { ++ for(k = 0; k < 3; k++) ++ { ++ cw[k] = seed[k] ^ baseCw[k]; ++ } ++ ++ for(k = 3; k < 7; k++) ++ { ++ cw[k] = baseCw[k]; ++ } ++ } ++ ++ ExpandDesKey(cw); ++ } ++ ++ if(needsUnmasking && (hashModeCw > 0)) ++ { ++ switch(seedType) ++ { ++ case PVU_CW_VID: ++ val = 0; ++ break; ++ ++ case PVU_CW_A1: ++ case PVU_CW_A2: ++ case PVU_CW_A3: ++ case PVU_CW_A4: ++ val = 1; ++ break; ++ ++ case PVU_CW_HSD: ++ val = 2; ++ break; ++ ++ case PVU_CW_UTL: ++ val = 4; ++ break; ++ ++ case PVU_CW_VBI: ++ val = 5; ++ break; ++ } ++ PowervuCreateCw(seed, seedLength, baseCw, val, seedEcmCw, cw, csaUsed, hashModeCw); ++ } ++} ++ ++#ifdef WITH_EMU ++int8_t PowervuECM(uint8_t *ecm, uint8_t *dw, uint16_t srvid, emu_stream_client_key_data *cdata, EXTENDED_CW* cw_ex) ++#else ++int8_t PowervuECM(uint8_t *ecm, uint8_t *dw, emu_stream_client_key_data *cdata) ++#endif ++{ ++ int8_t ret = 1; ++ uint16_t ecmLen = GetEcmLen(ecm); ++ uint32_t ecmCrc32; ++ uint8_t nanoCmd, nanoChecksum, keyType, fixedKey, oddKey, bid, csaUsed; ++ uint16_t nanoLen; ++ uint32_t channelId, ecmSrvid, keyIndex; ++ uint32_t i, j, k; ++ uint8_t convolvedCw[8][8]; ++ uint8_t ecmKey[7], tmpEcmKey[7], seedBase[4], baseCw[7], seed[8][8], cw[8][8]; ++ uint8_t decrypt_ok; ++ uint8_t ecmPart1[14], ecmPart2[27]; ++ uint8_t sbox; ++ uint32_t keyRef1, keyRef2; ++ uint8_t calculateAllCws; ++ uint8_t seedEcmCw[0x10]; ++ uint8_t hashModeCw = 0, needsUnmasking, xorMode; ++#ifdef WITH_EMU ++ uint8_t *dwp; ++ emu_stream_cw_item *cw_item; ++ int8_t update_global_key = 0; ++ int8_t update_global_keys[EMU_STREAM_SERVER_MAX_CONNECTIONS]; ++ ++ memset(update_global_keys, 0, sizeof(update_global_keys)); ++#endif ++ ++ if(ecmLen < 7) ++ { ++ return 1; ++ } ++ ++ needsUnmasking = (ecm[3] & 0xF0) == 0x50; ++ ++ if(needsUnmasking) ++ { ++ hashModeCw = PowervuUnmaskEcm(ecm, seedEcmCw); ++ } ++ ++ ecmCrc32 = b2i(4, ecm+ecmLen-4); ++ ++ if(fletcher_crc32(ecm, ecmLen-4) != ecmCrc32) ++ { ++ return 8; ++ } ++ ecmLen -= 4; ++ ++ for(i = 0; i < 8; i++) { ++ memset(convolvedCw[i], 0, 8); ++ } ++ ++ for(i = 3; i+3 < ecmLen; ) { ++ nanoLen = (((ecm[i] & 0x0f) << 8) | ecm[i+1]); ++ i += 2; ++ if(nanoLen > 0) ++ { ++ nanoLen--; ++ } ++ nanoCmd = ecm[i++]; ++ if(i+nanoLen > ecmLen) { ++ return 1; ++ } ++ ++ switch (nanoCmd) { ++ case 0x27: ++ if(nanoLen < 15) ++ { ++ break; ++ } ++ ++ nanoChecksum = 0; ++ for(j = 4; j < 15; j++) ++ { ++ nanoChecksum += ecm[i+j]; ++ } ++ ++ if(nanoChecksum != 0) ++ { ++ break; ++ } ++ ++ keyType = PowervuGetConvcwIndex(ecm[i+4]); ++ memcpy(convolvedCw[keyType], &ecm[i+6], 8); ++ break; ++ ++ default: ++ break; ++ } ++ i += nanoLen; ++ } ++ ++ for(i = 3; i+3 < ecmLen; ) { ++ nanoLen = (((ecm[i] & 0x0f) << 8) | ecm[i+1]); ++ i += 2; ++ if(nanoLen > 0) ++ { ++ nanoLen--; ++ } ++ nanoCmd = ecm[i++]; ++ if(i+nanoLen > ecmLen) { ++ return 1; ++ } ++ ++ switch (nanoCmd) { ++ case 0x20: ++ if(nanoLen < 54) ++ { ++ break; ++ } ++ ++ i += ecm[i + 3]; // Extra Data Length ++ ++ csaUsed = GetBit(ecm[i+7], 7); ++ fixedKey = !GetBit(ecm[i+6], 5); ++ oddKey = GetBit(ecm[i+6], 4); ++ xorMode = GetBit(ecm[i+6], 0); ++ bid = (GetBit(ecm[i+7], 1) << 1) | GetBit(ecm[i+7], 0); ++ sbox = GetBit(ecm[i+6], 3); ++ ++ keyIndex = (fixedKey << 3) | (bid << 2) | oddKey; ++ channelId = b2i(2, ecm+i+23); ++ ecmSrvid = (channelId >> 4) | ((channelId & 0xF) << 12); ++ ++ decrypt_ok = 0; ++ ++ memcpy(ecmPart1, ecm+i+8, 14); ++ memcpy(ecmPart2, ecm+i+27, 27); ++ ++ keyRef1 = 0; ++ keyRef2 = 0; ++ ++ do ++ { ++ if(!GetPowervuKey(ecmKey, ecmSrvid, '0', keyIndex, 7, 0, keyRef1++)) ++ { ++ if(!GetPowervuKey(ecmKey, channelId, '0', keyIndex, 7, 0, keyRef2++)) ++ { ++ cs_log("Key not found: P %04X 0%X", ecmSrvid, keyIndex); ++ return 2; ++ } ++ } ++ ++ PowervuDecrypt(ecm+i+8, 14, ecmKey, sbox); ++ if((ecm[i+6] != ecm[i+6+7]) || (ecm[i+6+8] != ecm[i+6+15])) ++ { ++ memcpy(ecm+i+8, ecmPart1, 14); ++ continue; ++ } ++ ++ memcpy(tmpEcmKey, ecmKey, 7); ++ ++ PowervuDecrypt(ecm+i+27, 27, ecmKey, sbox); ++ if((ecm[i+23] != ecm[i+23+29]) || (ecm[i+23+1] != ecm[i+23+30])) ++ { ++ memcpy(ecm+i+8, ecmPart1, 14); ++ memcpy(ecm+i+27, ecmPart2, 27); ++ continue; ++ } ++ ++ decrypt_ok = 1; ++ } ++ while(!decrypt_ok); ++ ++ memcpy(seedBase, ecm+i+6+2, 4); ++ ++#ifdef WITH_EMU ++ if(cdata == NULL) ++ { ++ SAFE_MUTEX_LOCK(&emu_fixed_key_srvid_mutex); ++ for(j = 0; j < EMU_STREAM_SERVER_MAX_CONNECTIONS; j++) ++ { ++ if(!stream_server_has_ecm[j] && emu_stream_cur_srvid[j] == srvid) ++ { ++ update_global_key = 1; ++ update_global_keys[j] = 1; ++ } ++ } ++ SAFE_MUTEX_UNLOCK(&emu_fixed_key_srvid_mutex); ++ } ++ ++ if(cdata != NULL || update_global_key || cw_ex != NULL) ++#else ++ if(cdata != NULL) ++#endif ++ { ++ // Calculate all seeds ++ for(j = 0; j < 8; j++) ++ { ++ memcpy(ecmKey, tmpEcmKey, 7); ++ PowervuCalculateSeed(j, ecm+i, seedBase, ecmKey, seed[j], sbox); ++ } ++ } ++ else ++ { ++ // Calculate only video seed ++ memcpy(ecmKey, tmpEcmKey, 7); ++ PowervuCalculateSeed(PVU_CW_VID, ecm+i, seedBase, ecmKey, seed[PVU_CW_VID], sbox); ++ } ++ ++ memcpy(baseCw, ecm+i+6+8, 7); ++ ++#ifdef WITH_EMU ++ calculateAllCws = cdata != NULL || update_global_key || cw_ex != NULL; ++#else ++ calculateAllCws = cdata != NULL; ++#endif ++ if(calculateAllCws) ++ { ++ // Calculate all cws ++ for(j = 0; j < 8; j++) ++ { ++ PowervuCalculateCw(j, seed[j], csaUsed, convolvedCw[j], cw[j], baseCw, ++ seedEcmCw, hashModeCw, needsUnmasking, xorMode); ++ ++ if(csaUsed) ++ { ++ for(k = 0; k < 8; k += 4) { ++ cw[j][k + 3] = ((cw[j][k] + cw[j][k + 1] + cw[j][k + 2]) & 0xff); ++ } ++ } ++ } ++ ++#ifdef WITH_EMU ++ if(update_global_key) ++ { ++ for(j = 0; j < EMU_STREAM_SERVER_MAX_CONNECTIONS; j++) ++ { ++ if(update_global_keys[j]) ++ { ++ cw_item = (emu_stream_cw_item*)malloc(sizeof(emu_stream_cw_item)); ++ if(cw_item != NULL) ++ { ++ cw_item->csa_used = csaUsed; ++ cw_item->is_even = ecm[0] == 0x80 ? 1 : 0; ++ cs_ftime(&cw_item->write_time); ++ add_ms_to_timeb(&cw_item->write_time, cfg.emu_stream_ecm_delay); ++ memcpy(cw_item->cw, cw, sizeof(cw)); ++ ll_append(ll_emu_stream_delayed_keys[j], cw_item); ++ } ++ } ++ } ++ } ++ ++ if(cdata != NULL) ++ { ++#endif ++ for(j = 0; j < 8; j++) ++ { ++ if(csaUsed) ++ { ++ if(cdata->pvu_csa_ks[j] == NULL) ++ { cdata->pvu_csa_ks[j] = get_key_struct(); } ++ ++ if(ecm[0] == 0x80) ++ { set_even_control_word(cdata->pvu_csa_ks[j], cw[j]); } ++ else ++ { set_odd_control_word(cdata->pvu_csa_ks[j], cw[j]); } ++ ++ cdata->pvu_csa_used = 1; ++ } ++ else ++ { ++ if(ecm[0] == 0x80) ++ { des_set_key(cw[j], cdata->pvu_des_ks[j][0]); } ++ else ++ { des_set_key(cw[j], cdata->pvu_des_ks[j][1]); } ++ ++ cdata->pvu_csa_used = 0; ++ } ++ } ++#ifdef WITH_EMU ++ } ++ ++ if(cw_ex != NULL) ++ { ++ cw_ex->mode = CW_MODE_MULTIPLE_CW; ++ ++ if(csaUsed) ++ { ++ cw_ex->algo = CW_ALGO_CSA; ++ cw_ex->algo_mode = CW_ALGO_MODE_ECB; ++ } ++ else ++ { ++ cw_ex->algo = CW_ALGO_DES; ++ cw_ex->algo_mode = CW_ALGO_MODE_ECB; ++ } ++ ++ for(j = 0; j < 4; j++) ++ { ++ dwp = cw_ex->audio[j]; ++ ++ memset(dwp, 0, 16); ++ ++ if(ecm[0] == 0x80) ++ { ++ memcpy(dwp, cw[PVU_CW_A1+j], 8); ++ ++ if(csaUsed) ++ { ++ for(k = 0; k < 8; k += 4) ++ { ++ dwp[k + 3] = ((dwp[k] + dwp[k + 1] + dwp[k + 2]) & 0xff); ++ } ++ } ++ } ++ else ++ { ++ memcpy(&dwp[8], cw[PVU_CW_A1+j], 8); ++ ++ if(csaUsed) ++ { ++ for(k = 8; k < 16; k += 4) ++ { ++ dwp[k + 3] = ((dwp[k] + dwp[k + 1] + dwp[k + 2]) & 0xff); ++ } ++ } ++ } ++ } ++ ++ dwp = cw_ex->data; ++ ++ memset(dwp, 0, 16); ++ ++ if(ecm[0] == 0x80) ++ { ++ memcpy(dwp, cw[PVU_CW_HSD], 8); ++ ++ if(csaUsed) ++ { ++ for(k = 0; k < 8; k += 4) ++ { ++ dwp[k + 3] = ((dwp[k] + dwp[k + 1] + dwp[k + 2]) & 0xff); ++ } ++ } ++ } ++ else ++ { ++ memcpy(&dwp[8], cw[PVU_CW_HSD], 8); ++ ++ if(csaUsed) ++ { ++ for(k = 8; k < 16; k += 4) ++ { ++ dwp[k + 3] = ((dwp[k] + dwp[k + 1] + dwp[k + 2]) & 0xff); ++ } ++ } ++ } ++ } ++#endif ++ } ++ else ++ { ++ // Calculate only video cw ++ PowervuCalculateCw(PVU_CW_VID, seed[PVU_CW_VID], csaUsed, convolvedCw[PVU_CW_VID], cw[PVU_CW_VID], baseCw, ++ seedEcmCw, hashModeCw, needsUnmasking, xorMode); ++ } ++ ++ memset(dw, 0, 16); ++ ++ if(ecm[0] == 0x80) ++ { ++ memcpy(dw, cw[PVU_CW_VID], 8); ++ ++ if(csaUsed) ++ { ++ for(k = 0; k < 8; k += 4) ++ { ++ dw[k + 3] = ((dw[k] + dw[k + 1] + dw[k + 2]) & 0xff); ++ } ++ } ++ } ++ else ++ { ++ memcpy(&dw[8], cw[PVU_CW_VID], 8); ++ ++ if(csaUsed) ++ { ++ for(k = 8; k < 16; k += 4) ++ { ++ dw[k + 3] = ((dw[k] + dw[k + 1] + dw[k + 2]) & 0xff); ++ } ++ } ++ } ++ ++ return 0; ++ ++ default: ++ break; ++ } ++ i += nanoLen; ++ } ++ ++ return ret; ++} ++ ++ ++// Drecrypt EMU ++static void DREover(const uint8_t *ECMdata, uint8_t *dw) ++{ ++ uint8_t key[8]; ++ uint32_t key_schedule[32]; ++ ++ if (ECMdata[2] >= (43 + 4) && ECMdata[40] == 0x3A && ECMdata[41] == 0x4B) ++ { ++ if (!FindKey('D', ECMdata[42] & 0x0F, 0, "OVER", key, 8, 1, 0, 0, NULL)) ++ { ++ return; ++ } ++ ++ des_set_key(key, key_schedule); ++ ++ des(dw, key_schedule, 0); // even dw post-process ++ des(dw + 8, key_schedule, 0); // odd dw post-process ++ } ++} ++ ++static uint32_t DreGostDec(uint32_t inData) ++{ ++ static uint8_t Sbox[128] = ++ { ++ 0x0E,0x04,0x0D,0x01,0x02,0x0F,0x0B,0x08,0x03,0x0A,0x06,0x0C,0x05,0x09,0x00,0x07, ++ 0x0F,0x01,0x08,0x0E,0x06,0x0B,0x03,0x04,0x09,0x07,0x02,0x0D,0x0C,0x00,0x05,0x0A, ++ 0x0A,0x00,0x09,0x0E,0x06,0x03,0x0F,0x05,0x01,0x0D,0x0C,0x07,0x0B,0x04,0x02,0x08, ++ 0x07,0x0D,0x0E,0x03,0x00,0x06,0x09,0x0A,0x01,0x02,0x08,0x05,0x0B,0x0C,0x04,0x0F, ++ 0x02,0x0C,0x04,0x01,0x07,0x0A,0x0B,0x06,0x08,0x05,0x03,0x0F,0x0D,0x00,0x0E,0x09, ++ 0x0C,0x01,0x0A,0x0F,0x09,0x02,0x06,0x08,0x00,0x0D,0x03,0x04,0x0E,0x07,0x05,0x0B, ++ 0x04,0x0B,0x02,0x0E,0x0F,0x00,0x08,0x0D,0x03,0x0C,0x09,0x07,0x05,0x0A,0x06,0x01, ++ 0x0D,0x02,0x08,0x04,0x06,0x0F,0x0B,0x01,0x0A,0x09,0x03,0x0E,0x05,0x00,0x0C,0x07 ++ }; ++ uint8_t i, j; ++ ++ for(i = 0; i < 8; i++) ++ { ++ j = (inData >> 28) & 0x0F; ++ inData = (inData << 4) | (Sbox[i * 16 + j] & 0x0F); ++ } ++ ++ inData = (inData << 11) | (inData >> 21); ++ ++ return (inData); ++} ++ ++static void DrecryptDecrypt(uint8_t *Data, uint8_t *Key) // DRE GOST 28147-89 CORE ++{ ++ int i, j; ++ uint32_t L_part = 0, R_part = 0, temp = 0; ++ ++ for(i = 0; i < 4; i++) L_part = (L_part << 8) | (Data[i] & 0xFF), R_part = (R_part << 8) | (Data[i + 4] & 0xFF); ++ ++ for(i = 0; i < 4; i++) ++ { ++ temp = ((Key[i*8+0] & 0xFF) << 24) | ((Key[i*8+1] & 0xFF) << 16) | ((Key[i*8+2] & 0xFF) << 8) | (Key[i*8+3] & 0xFF); ++ R_part ^= DreGostDec(temp + L_part); ++ temp = ((Key[i*8+4] & 0xFF) << 24) | ((Key[i*8+5] & 0xFF) << 16) | ((Key[i*8+6] & 0xFF) << 8) | (Key[i*8+7] & 0xFF); ++ L_part ^= DreGostDec(temp + R_part); ++ } ++ ++ for(j = 0; j < 3; j++) ++ { ++ for(i = 3; i >= 0; i--) ++ { ++ temp = ((Key[i*8+4] & 0xFF) << 24) | ((Key[i*8+5] & 0xFF) << 16) | ((Key[i*8+6] & 0xFF) << 8) | (Key[i*8+7] & 0xFF); ++ R_part ^= DreGostDec(temp + L_part); ++ temp = ((Key[i*8+0] & 0xFF) << 24) | ((Key[i*8+1] & 0xFF) << 16) | ((Key[i*8+2] & 0xFF) << 8) | (Key[i*8+3] & 0xFF); ++ L_part ^= DreGostDec(temp + R_part); ++ } ++ } ++ ++ for(i = 0; i < 4; i++) Data[i] = (R_part >> i*8) & 0xFF, Data[i+4] = (L_part >> i*8) & 0xFF; ++} ++ ++static void DrecryptPostCw(uint8_t* ccw) ++{ ++ uint32_t i, j; ++ uint8_t tmp[4]; ++ ++ for(i = 0; i < 4; i++) ++ { ++ for(j = 0; j < 4; j++) ++ { ++ tmp[j] = ccw[3 - j]; ++ } ++ ++ for(j = 0; j < 4; j++) ++ { ++ ccw[j] = tmp[j]; ++ } ++ ++ ccw += 4; ++ } ++} ++ ++static void DrecryptSwap(uint8_t* ccw) ++{ ++ uint32_t tmp1, tmp2; ++ ++ memcpy(&tmp1, ccw, 4); ++ memcpy(&tmp2, ccw + 4, 4); ++ ++ memcpy(ccw, ccw + 8, 8); ++ ++ memcpy(ccw + 8 , &tmp1, 4); ++ memcpy(ccw + 8 + 4, &tmp2, 4); ++} ++ ++static int8_t Drecrypt2ECM(uint32_t provId, uint8_t *ecm, uint8_t *dw) ++{ ++ uint8_t ecmDataLen, ccw[16], key[32]; ++ uint16_t ecmLen, overcryptId; ++ char keyName[EMU_MAX_CHAR_KEYNAME]; ++ ++ ecmLen = GetEcmLen(ecm); ++ ++ if (ecmLen < 3) ++ { ++ return 1; // Not supported ++ } ++ ++ ecmDataLen = ecm[2]; ++ ++ if (ecmLen < ecmDataLen + 3) ++ { ++ return 4; // Corrupt data ++ } ++ ++ switch (provId & 0xFF) ++ { ++ case 0x11: ++ { ++ if (ecm[3] == 0x56) ++ { ++ snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%02X%02X", ecm[6], ecm[5]); ++ ++ if (!FindKey('D', 0x4AE111, 0, keyName, key, 32, 1, 0, 0, NULL)) ++ { ++ return 2; ++ } ++ } ++ else ++ { ++ snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%02X%02X", ecm[6], ecm[3]); ++ ++ if (!FindKey('D', 0x4AE111, 0, keyName, key, 32, 1, 0, 0, NULL)) ++ { ++ return 2; ++ } ++ } ++ ++ break; ++ } ++ ++ case 0x14: ++ { ++ snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%02X%02X", ecm[6], ecm[5]); ++ ++ if (!FindKey('D', 0x4AE114, 0, keyName, key, 32, 1, 0, 0, NULL)) ++ { ++ return 2; ++ } ++ ++ break; ++ } ++ ++ default: ++ return 1; ++ } ++ ++ memcpy(ccw, ecm + 13, 16); ++ ++ DrecryptPostCw(key); ++ DrecryptPostCw(key + 16); ++ ++ DrecryptDecrypt(ccw, key); ++ DrecryptDecrypt(ccw + 8, key); ++ ++ if (ecm[2] >= 46 && ecm[43] == 1 && provId == 0x11) ++ { ++ DrecryptSwap(ccw); ++ overcryptId = b2i(2, &ecm[44]); ++ ++ Drecrypt2OverCW(overcryptId, ccw); ++ ++ if (isValidDCW(ccw)) ++ { ++ memcpy(dw, ccw, 16); ++ return 0; ++ } ++ ++ return 9; // ICG error ++ } ++ ++ DREover(ecm, ccw); ++ ++ if (isValidDCW(ccw)) ++ { ++ DrecryptSwap(ccw); ++ memcpy(dw, ccw, 16); ++ return 0; ++ } ++ ++ return 1; ++} ++ ++// Tandberg EMU ++static uint16_t TandbergChecksum(uint8_t *data, uint8_t length) ++{ ++ // ECM and EMM checksum calculation ++ // 1. Combine data in 2 byte groups ++ // 2. Add them together ++ // 3. Multiply result by itself (power of 7) ++ // 4. XOR with fixed value 0x17E3 ++ ++ uint8_t i; ++ uint16_t checksum = 0; ++ ++ for(i = 0; i < length; i += 2) ++ { ++ checksum += (data[i] << 8) | data[i + 1]; ++ } ++ ++ checksum = checksum * checksum * checksum * checksum * checksum * checksum * checksum; ++ checksum ^= 0x17E3; ++ ++ return checksum; ++} ++ ++static int8_t GetTandbergKey(uint32_t keyIndex, char *keyName, uint8_t *key, uint32_t keyLength) ++{ ++ // keyIndex: ecm keys --> entitlementId ++ // emm keys --> aeskeyIndex ++ // aes keys --> keyIndex ++ ++ // keyName: ecm keys --> "01" ++ // emm keys --> "MK" or "MK01" ++ // aes keys --> "AES" ++ ++ return FindKey('T', keyIndex, 0, keyName, key, keyLength, 1, 0, 0, NULL); ++} ++ ++static int8_t TandbergECM(uint8_t *ecm, uint8_t *dw) ++{ ++ uint8_t nanoType, nanoLength; ++ uint8_t* nanoData; ++ uint32_t pos = 3; ++ uint32_t entitlementId; ++ uint32_t ks[32]; ++ uint8_t ecmKey[8]; ++ uint16_t ecmLen = GetEcmLen(ecm); ++ ++ if(ecmLen < 5) ++ { ++ return 1; ++ } ++ ++ do ++ { ++ nanoType = ecm[pos]; ++ nanoLength = ecm[pos+1]; ++ ++ if(pos + 2 + nanoLength > ecmLen) ++ { ++ break; ++ } ++ ++ nanoData = ecm + pos + 2; ++ ++ // ECM validation ++ uint16_t payloadChecksum = (nanoData[nanoLength - 2] << 8) | nanoData[nanoLength - 1]; ++ uint16_t calculatedChecksum = TandbergChecksum(nanoData, nanoLength - 2); ++ ++ if(calculatedChecksum != payloadChecksum) ++ { ++ cs_log("ECM checksum error (%.4X instead of %.4X)", calculatedChecksum, payloadChecksum); ++ return 8; ++ } ++ // End of ECM validation ++ ++ switch(nanoType) ++ { ++ case 0xEC: // Director v6 (September 2017) ++ { ++ if(nanoLength != 0x28) ++ { ++ cs_log("WARNING: nanoType EC length (%d) != %d", nanoLength, 0x28); ++ break; ++ } ++ ++ entitlementId = b2i(4, nanoData); ++ ++ if(!GetTandbergKey(entitlementId, "01", ecmKey, 8)) ++ { ++ return 2; ++ } ++ ++ cs_log("Active entitlement %.4X", entitlementId); ++ ++ // Step 1 - Decrypt DES CBC with ecmKey and iv = { 0 } (equal to nanoED) ++ uint8_t encryptedData[32] = { 0 }; ++ memcpy(encryptedData, nanoData + 6, 32); ++ ++ uint8_t iv[8] = { 0 }; ++ des_cbc_decrypt(encryptedData, iv, ecmKey, 32); ++ ++ uint8_t nanoMode = nanoData[5]; ++ ++ if ((nanoMode & 0x20) == 0) // Old algo ++ { ++ // Step 2 - Create CW (equal to nano ED) ++ dw[0] = encryptedData[0x05]; ++ dw[1] = encryptedData[0x19]; ++ dw[2] = encryptedData[0x1D]; ++ ++ dw[4] = encryptedData[0x0B]; ++ dw[5] = encryptedData[0x12]; ++ dw[6] = encryptedData[0x1A]; ++ ++ dw[8] = encryptedData[0x16]; ++ dw[9] = encryptedData[0x03]; ++ dw[10] = encryptedData[0x11]; ++ ++ dw[12] = encryptedData[0x18]; ++ dw[13] = encryptedData[0x10]; ++ dw[14] = encryptedData[0x0E]; ++ ++ return 0; ++ } ++ else // New algo (overencryption with AES) ++ { ++ // Step 2 - Prepare data for AES (it is like the creation of CW in nanoED but swapped each 8 bytes) ++ uint8_t dataEC[16] = { 0 }; ++ ++ dataEC[0] = encryptedData[0x02]; ++ dataEC[1] = encryptedData[0x0E]; ++ dataEC[2] = encryptedData[0x10]; ++ dataEC[3] = encryptedData[0x18]; ++ dataEC[4] = encryptedData[0x09]; ++ dataEC[5] = encryptedData[0x11]; ++ dataEC[6] = encryptedData[0x03]; ++ dataEC[7] = encryptedData[0x16]; ++ ++ dataEC[8] = encryptedData[0x13]; ++ dataEC[9] = encryptedData[0x1A]; ++ dataEC[10] = encryptedData[0x12]; ++ dataEC[11] = encryptedData[0x0B]; ++ dataEC[12] = encryptedData[0x04]; ++ dataEC[13] = encryptedData[0x1D]; ++ dataEC[14] = encryptedData[0x19]; ++ dataEC[15] = encryptedData[0x05]; ++ ++ // Step 3 - Decrypt AES CBC with new aesKey and iv 2EBD816A5E749A708AE45ADDD84333DE ++ uint8_t aesKeyIndex = nanoMode & 0x1F; // 32 possible AES keys ++ uint8_t aesKey[16] = { 0 }; ++ ++ if(!GetTandbergKey(aesKeyIndex, "AES", aesKey, 16)) ++ { ++ return 2; ++ } ++ ++ struct aes_keys aes; ++ aes_set_key(&aes, (char *)aesKey); ++ ++ uint8_t ivAes[16] = { 0x2E, 0xBD, 0x81, 0x6A, 0x5E, 0x74, 0x9A, 0x70, 0x8A, 0xE4, 0x5A, 0xDD, 0xD8, 0x43, 0x33, 0xDE }; ++ aes_cbc_decrypt(&aes, dataEC, 16, ivAes); ++ ++ // Step 4 - Create CW (a simple swap) ++ uint8_t offset; ++ for (offset = 0; offset < 16; offset++) ++ { ++ dw[offset] = dataEC[15 - offset]; ++ } ++ ++ return 0; ++ } ++ } ++ ++ case 0xED: // ECM_TAG_CW_DESCRIPTOR ++ { ++ if(nanoLength != 0x26) ++ { ++ cs_log("WARNING: nanoType ED length (%d) != %d", nanoLength, 0x26); ++ break; ++ } ++ ++ entitlementId = b2i(4, nanoData); ++ ++ if(!GetTandbergKey(entitlementId, "01", ecmKey, 8)) ++ { ++ return 2; ++ } ++ ++ cs_log("Active entitlement %.4X", entitlementId); ++ ++ uint8_t encryptedData[32] = { 0 }; ++ memcpy(encryptedData, nanoData + 4, 32); ++ ++ uint8_t iv[8] = { 0 }; ++ des_cbc_decrypt(encryptedData, iv, ecmKey, 32); ++ ++ dw[0] = encryptedData[0x05]; ++ dw[1] = encryptedData[0x19]; ++ dw[2] = encryptedData[0x1D]; ++ dw[4] = encryptedData[0x0B]; ++ dw[5] = encryptedData[0x12]; ++ dw[6] = encryptedData[0x1A]; ++ dw[8] = encryptedData[0x16]; ++ dw[9] = encryptedData[0x03]; ++ dw[10] = encryptedData[0x11]; ++ dw[12] = encryptedData[0x18]; ++ dw[13] = encryptedData[0x10]; ++ dw[14] = encryptedData[0x0E]; ++ ++ return 0; ++ } ++ ++ case 0xEE: // ECM_TAG_CW_DESCRIPTOR ++ { ++ if(nanoLength != 0x16) ++ { ++ cs_log("WARNING: nanoType EE length (%d) != %d", nanoLength, 0x16); ++ break; ++ } ++ ++ entitlementId = b2i(4, nanoData); ++ ++ if(!GetTandbergKey(entitlementId, "01", ecmKey, 8)) ++ { ++ return 2; ++ } ++ ++ cs_log("Active entitlement %.4X", entitlementId); ++ ++ memcpy(dw, nanoData + 4 + 8, 8); // even ++ memcpy(dw + 8, nanoData + 4, 8); // odd ++ ++ des_set_key(ecmKey, ks); ++ ++ des(dw, ks, 0); ++ des(dw + 8, ks, 0); ++ ++ return 0; ++ } ++ ++ default: ++ cs_log("WARNING: nanoType %.2X not supported", nanoType); ++ break; ++ } ++ ++ pos += 2 + nanoLength; ++ ++ } while (pos < ecmLen); ++ ++ return 1; ++} ++ ++const char* GetProcessECMErrorReason(int8_t result) ++{ ++ switch(result) { ++ case 0: ++ return "No error"; ++ case 1: ++ return "ECM not supported"; ++ case 2: ++ return "Key not found"; ++ case 3: ++ return "Nano80 problem"; ++ case 4: ++ return "Corrupt data"; ++ case 5: ++ return "CW not found"; ++ case 6: ++ return "CW checksum error"; ++ case 7: ++ return "Out of memory"; ++ case 8: ++ return "ECM checksum error"; ++ case 9: ++ return "ICG error"; ++ default: ++ return "Unknown"; ++ } ++} ++ ++/* Error codes ++0 OK ++1 ECM not supported ++2 Key not found ++3 Nano80 problem ++4 Corrupt data ++5 CW not found ++6 CW checksum error ++7 Out of memory ++8 ECM checksum error ++9 ICG error ++*/ ++#ifdef WITH_EMU ++int8_t ProcessECM(struct s_reader *rdr, int16_t ecmDataLen, uint16_t caid, uint32_t provider, const uint8_t *ecm, ++ uint8_t *dw, uint16_t srvid, uint16_t ecmpid, EXTENDED_CW* cw_ex) ++#else ++int8_t ProcessECM(struct s_reader *rdr, int16_t ecmDataLen, uint16_t caid, uint32_t provider, const uint8_t *ecm, ++ uint8_t *dw, uint16_t srvid, uint16_t ecmpid) ++#endif ++{ ++ int8_t result = 1, i; ++ uint8_t ecmCopy[EMU_MAX_ECM_LEN]; ++ uint16_t ecmLen = 0; ++ ++ if(ecmDataLen < 3) { ++ // accept requests without ecm only for biss ++ if((caid>>8) != 0x26 && caid != 0xFFFF) { ++ return 1; ++ } ++ } ++ else { ++ ecmLen = GetEcmLen(ecm); ++ } ++ ++ if(ecmLen > ecmDataLen) { ++ return 1; ++ } ++ ++ if(ecmLen > EMU_MAX_ECM_LEN) { ++ return 1; ++ } ++ memcpy(ecmCopy, ecm, ecmLen); ++ ++ if((caid >> 8) == 0x0D) { ++ result = CryptoworksECM(caid, ecmCopy, dw); ++ } ++ else if((caid >> 8) == 0x09) { ++ result = SoftNDSECM(caid, ecmCopy, dw); ++ } ++ else if(caid == 0x0500) { ++ result = ViaccessECM(ecmCopy, dw); ++ } ++ else if((caid >> 8) == 0x18) { ++ result = Nagra2ECM(ecmCopy, dw); ++ } ++ else if((caid >> 8) == 0x06) { ++ result = Irdeto2ECM(caid, ecmCopy, dw); ++ } ++ else if((caid >> 8) == 0x26 || caid == 0xFFFF) { ++ result = BissECM(rdr, ecm, ecmDataLen, dw, srvid, ecmpid); ++ } ++ else if((caid >> 8) == 0x0E) { ++#ifdef WITH_EMU ++ result = PowervuECM(ecmCopy, dw, srvid, NULL, cw_ex); ++#else ++ result = PowervuECM(ecmCopy, dw, NULL); ++#endif ++ } ++ else if(caid == 0x4AE1) { ++ result = Drecrypt2ECM(provider, ecmCopy, dw); ++ } ++ else if((caid >> 8) == 0x10) { ++ result = TandbergECM(ecmCopy, dw); ++ } ++ ++ // fix dcw checksum ++ if(result == 0 && !((caid >> 8) == 0x0E)) { ++ for(i = 0; i < 16; i += 4) { ++ dw[i + 3] = ((dw[i] + dw[i + 1] + dw[i + 2]) & 0xff); ++ } ++ } ++ ++ if(result != 0) { ++ cs_log("ECM failed: %s", GetProcessECMErrorReason(result)); ++ } ++ ++ return result; ++} ++ ++// Viaccess EMM EMU ++static int8_t ViaccessEMM(uint8_t *emm, uint32_t *keysAdded) ++{ ++ uint8_t nanoCmd = 0, subNanoCmd = 0, *tmp; ++ uint16_t i = 0, j = 0, k = 0, emmLen = GetEcmLen(emm); ++ uint8_t ecmKeys[6][16], keyD0[2], emmKey[16], emmXorKey[16], provName[17]; ++ uint8_t ecmKeyCount = 0, emmKeyIndex = 0, aesMode = 0x0D; ++ uint8_t nanoLen = 0, subNanoLen = 0, haveEmmXorKey = 0, haveNewD0 = 0; ++ uint32_t ui1, ui2, ui3, ecmKeyIndex[6], provider = 0, ecmProvider = 0; ++ char keyName[EMU_MAX_CHAR_KEYNAME], keyValue[36]; ++ struct aes_keys aes; ++ ++ memset(keyD0, 0, 2); ++ memset(ecmKeyIndex, 0, sizeof(uint32_t)*6); ++ ++ for(i=3; i+2 emmLen) { ++ return 1; ++ } ++ ++ switch(nanoCmd) { ++ case 0x90: { ++ if(nanoLen < 3) { ++ break; ++ } ++ ui1 = emm[i+2]; ++ ui2 = emm[i+1]; ++ ui3 = emm[i]; ++ provider = (ui1 | (ui2 << 8) | (ui3 << 16)); ++ if(provider == 0x00D00040) { ++ ecmProvider = 0x030B00; ++ } ++ else { ++ return 1; ++ } ++ break; ++ } ++ case 0xD2: { ++ if(nanoLen < 2) { ++ break; ++ } ++ emmKeyIndex = emm[i+1]; ++ break; ++ } ++ case 0x41: { ++ if(nanoLen < 1) { ++ break; ++ } ++ if(!GetViaKey(emmKey, provider, 'M', emmKeyIndex, 16, 1)) { ++ return 2; ++ } ++ memset(provName, 0, 17); ++ memset(emmXorKey, 0, 16); ++ k = nanoLen < 16 ? nanoLen : 16; ++ memcpy(provName, &emm[i], k); ++ aes_set_key(&aes, (char*)emmKey); ++ aes_decrypt(&aes, emmXorKey, 16); ++ for(j=0; j<16; j++) { ++ provName[j] ^= emmXorKey[j]; ++ } ++ provName[k] = 0; ++ ++ if(strcmp((char*)provName, "TNTSAT") != 0 && strcmp((char*)provName, "TNTSATPRO") != 0 ++ &&strcmp((char*)provName, "CSAT V") != 0) { ++ return 1; ++ } ++ break; ++ } ++ case 0xBA: { ++ if(nanoLen < 2) { ++ break; ++ } ++ GetViaKey(keyD0, ecmProvider, 'D', 0, 2, 0); ++ ui1 = (emm[i] << 8) | emm[i+1]; ++ if( (uint32_t)((keyD0[0] << 8) | keyD0[1]) < ui1 || (keyD0[0] == 0x00 && keyD0[1] == 0x00)) { ++ keyD0[0] = emm[i]; ++ keyD0[1] = emm[i+1]; ++ haveNewD0 = 1; ++ break; ++ } ++ return 0; ++ } ++ case 0xBC: { ++ break; ++ } ++ case 0x43: { ++ if(nanoLen < 16) { ++ break; ++ } ++ memcpy(emmXorKey, &emm[i], 16); ++ haveEmmXorKey = 1; ++ break; ++ } ++ case 0x44: { ++ if(nanoLen < 3) { ++ break; ++ } ++ if (!haveEmmXorKey) { ++ memset(emmXorKey, 0, 16); ++ } ++ tmp = (uint8_t*)malloc(((nanoLen/16)+1)*16*sizeof(uint8_t)); ++ if(tmp == NULL) { ++ return 7; ++ } ++ memcpy(tmp, &emm[i], nanoLen); ++ aes_set_key(&aes, (char*)emmKey); ++ for(j=0; j 5) { ++ break; ++ } ++ for(j=i; j+2 i+nanoLen) { ++ break; ++ } ++ switch(subNanoCmd) { ++ case 0xD2: { ++ if(nanoLen < 2) { ++ break; ++ } ++ aesMode = emm[j]; ++ emmKeyIndex = emm[j+1]; ++ break; ++ } ++ case 0x01: { ++ if(nanoLen < 17) { ++ break; ++ } ++ ecmKeyIndex[ecmKeyCount] = emm[j]; ++ memcpy(&ecmKeys[ecmKeyCount], &emm[j+1], 16); ++ if(!GetViaKey(emmKey, provider, 'M', emmKeyIndex, 16, 1)) { ++ break; ++ } ++ ++ if(aesMode == 0x0F || aesMode == 0x11) { ++ hdSurEncPhase1_D2_0F_11(ecmKeys[ecmKeyCount]); ++ hdSurEncPhase2_D2_0F_11(ecmKeys[ecmKeyCount]); ++ } ++ else if(aesMode == 0x13 || aesMode == 0x15) { ++ hdSurEncPhase1_D2_13_15(ecmKeys[ecmKeyCount]); ++ } ++ aes_set_key(&aes, (char*)emmKey); ++ aes_decrypt(&aes, ecmKeys[ecmKeyCount], 16); ++ if(aesMode == 0x0F || aesMode == 0x11) { ++ hdSurEncPhase1_D2_0F_11(ecmKeys[ecmKeyCount]); ++ } ++ else if(aesMode == 0x13 || aesMode == 0x15) { ++ hdSurEncPhase2_D2_13_15(ecmKeys[ecmKeyCount]); ++ } ++ ++ ecmKeyCount++; ++ break; ++ } ++ default: ++ break; ++ } ++ j += subNanoLen; ++ } ++ break; ++ } ++ case 0xF0: { ++ if(nanoLen != 4) { ++ break; ++ } ++ ui1 = ((emm[i+2] << 8) | (emm[i+1] << 16) | (emm[i] << 24) | emm[i+3]); ++ if(fletcher_crc32(emm + 3, emmLen - 11) != ui1) { ++ return 4; ++ } ++ ++ if(haveNewD0) { ++ ++ SetKey('V', ecmProvider, "D0", keyD0, 2, 1, NULL, NULL); ++ ++ for(j=0; j>2); ++ SetKey('I', ident, keyName, &emm[i+3], 16, 1, NULL, NULL); ++ ++ (*keysAdded)++; ++ cs_hexdump(0, &emm[i+3], 16, keyValue, sizeof(keyValue)); ++ cs_log("Key found in EMM: I %06X %s %s", ident, keyName, keyValue); ++ } ++ } ++ i+=l; ++ } ++ ++ if(*keysAdded > 0) { ++ return 0; ++ } ++ } ++ ++ return 1; ++} ++ ++static int8_t Irdeto2DoEMMTypePMK(uint32_t ident, uint8_t *emm, uint8_t *keySeed, uint8_t *keyIV, uint8_t *keyPMK, ++ uint16_t emmLen, uint8_t startOffset, uint8_t length, uint32_t *keysAdded) ++{ ++ uint32_t end, i, l, j; ++ char keyName[EMU_MAX_CHAR_KEYNAME], keyValue[36]; ++ ++ Irdeto2Decrypt(&emm[startOffset], keyIV, keySeed, length); ++ ++ i = 13; ++ end = startOffset + (length-8 < 0 ? 0 : length-8); ++ ++ while(i 0) { ++ return 0; ++ } ++ } ++ ++ return 1; ++} ++ ++static const uint8_t fausto_xor[16] = { 0x22, 0x58, 0xBD, 0x85, 0x2E, 0x8E, 0x52, 0x80, 0xA3, 0x79, 0x98, 0x69, 0x68, 0xE2, 0xD8, 0x4D }; ++ ++static int8_t Irdeto2EMM(uint16_t caid, uint8_t *oemm, uint32_t *keysAdded) ++{ ++ uint8_t length, okeySeed[16], keySeed[16], keyIV[16], keyPMK[16], startOffset, emmType; ++ uint32_t ident; ++ uint32_t keySeedRef, keyIVRef, keyPMK0Ref, keyPMK1Ref, keyPMK0ERef, keyPMK1ERef; ++ uint8_t emmCopy[EMU_MAX_EMM_LEN], *emm = oemm; ++ uint16_t emmLen = GetEcmLen(emm); ++ ++ if(emmLen < 11) { ++ return 1; ++ } ++ ++ if(emm[3] == 0xC3 || emm[3] == 0xCB) { ++ emmType = 2; ++ startOffset = 11; ++ } ++ else { ++ emmType = 1; ++ startOffset = 10; ++ } ++ ++ ident = emm[startOffset-2] | caid << 8; ++ length = emm[startOffset-1]; ++ ++ ++ if(emmLen < length+startOffset) { ++ return 1; ++ } ++ ++ keySeedRef = 0; ++ while(GetIrdetoKey(okeySeed, ident, 'M', emmType == 1 ? 0 : 0xA, 1, &keySeedRef)) { ++ keyIVRef = 0; ++ while(GetIrdetoKey(keyIV, ident, 'M', 2, 1, &keyIVRef)) { ++ ++ keyPMK0Ref = 0; ++ keyPMK1Ref = 0; ++ keyPMK0ERef = 0; ++ keyPMK1ERef = 0; ++ ++ while(GetIrdetoKey(keyPMK, ident, 'M', emmType == 1 ? 3 : 0xB, 1, &keyPMK0Ref)) { ++ memcpy(keySeed, okeySeed, 16); ++ memcpy(emmCopy, oemm, emmLen); ++ emm = emmCopy; ++ if(emmType == 1) { ++ if(Irdeto2DoEMMTypeOP(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0) { ++ return 0; ++ } ++ } ++ else { ++ if(Irdeto2DoEMMTypePMK(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0) { ++ return 0; ++ } ++ } ++ } ++ ++ if(emmType == 1) { ++ while(GetIrdetoKey(keyPMK, ident, 'M', 4, 1, &keyPMK1Ref)) { ++ memcpy(keySeed, okeySeed, 16); ++ memcpy(emmCopy, oemm, emmLen); ++ emm = emmCopy; ++ if(Irdeto2DoEMMTypeOP(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0) { ++ return 0; ++ } ++ } ++ ++ while(GetIrdetoKey(keyPMK, ident, 'M', 5, 1, &keyPMK0ERef)) { ++ xxor(keyPMK, 16, keyPMK, fausto_xor); ++ memcpy(keySeed, okeySeed, 16); ++ memcpy(emmCopy, oemm, emmLen); ++ emm = emmCopy; ++ if(Irdeto2DoEMMTypeOP(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0) { ++ return 0; ++ } ++ } ++ ++ while(GetIrdetoKey(keyPMK, ident, 'M', 6, 1, &keyPMK1ERef)) { ++ xxor(keyPMK, 16, keyPMK, fausto_xor); ++ memcpy(keySeed, okeySeed, 16); ++ memcpy(emmCopy, oemm, emmLen); ++ emm = emmCopy; ++ if(Irdeto2DoEMMTypeOP(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0) { ++ return 0; ++ } ++ } ++ } ++ ++ if(keyPMK0Ref == 0 && keyPMK1Ref == 0 && keyPMK0ERef == 0 && keyPMK1ERef == 0) { ++ return 2; ++ } ++ } ++ if(keyIVRef == 0) { ++ return 2; ++ } ++ } ++ if(keySeedRef == 0) { ++ return 2; ++ } ++ ++ return 1; ++} ++ ++int32_t GetIrdeto2Hexserial(uint16_t caid, uint8_t *hexserial) ++{ ++ uint32_t i, len; ++ KeyDataContainer *KeyDB; ++ KeyData *tmpKeyData; ++ ++ KeyDB = GetKeyContainer('I'); ++ if(KeyDB == NULL) { ++ return 0; ++ } ++ ++ for(i=0; ikeyCount; i++) { ++ ++ if(KeyDB->EmuKeys[i].provider>>8 != caid) { ++ continue; ++ } ++ if(strcmp(KeyDB->EmuKeys[i].keyName, "MC")) { ++ continue; ++ } ++ ++ tmpKeyData = &KeyDB->EmuKeys[i]; ++ ++ len = tmpKeyData->keyLength; ++ if(len > 3) ++ { len = 3; } ++ ++ memcpy(hexserial+(3-len), tmpKeyData->key, len); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++ ++// PowerVu EMM EMU ++static void PowervuUnmaskEmm(uint8_t *emm) ++{ ++ int i, l; ++ ++ uint8_t sourcePos[] = {0x03, 0x0C, 0x0D, 0x11, 0x15, 0x18, 0x1D, 0x1F, 0x25, 0x2A, 0x32, 0x35, 0x3A, 0x3B, 0x3E, ++ 0x42, 0x47, 0x48, 0x53, 0x58, 0x5C, 0x61, 0x66, 0x69, 0x71, 0x72, 0x78, 0x7B, 0x81, 0x84}; ++ ++ uint8_t destPos[] = {0x02, 0x08, 0x0B, 0x0E, 0x13, 0x16, 0x1E, 0x23, 0x28, 0x2B, 0x2F, 0x33, 0x38, 0x3C, 0x40, ++ 0x44, 0x4A, 0x4D, 0x54, 0x57, 0x5A, 0x63, 0x68, 0x6A, 0x70, 0x75, 0x76, 0x7D, 0x82, 0x85}; ++ ++ uint8_t data[0x1E]; ++ uint8_t hashModeEmm; ++ uint8_t mask[0x10]; ++ uint32_t crc; ++ ++ // Create Mask for ECM decryption ++ PowervuCreateDataEcmEmm(emm, sourcePos, 0x13, 0x1E, data); ++ ++ hashModeEmm = emm[8] ^ PowervuCrc8Calc(data, 0x1E); ++ ++ PowervuCreateHash(data, 0x1E, mask, hashModeEmm); ++ ++ // Fix Header ++ emm[3] &= 0x0F; ++ emm[3] |= 0x10; ++ emm[8] = 0x00; ++ ++ // Unmask Body ++ for(i = 0; i < 0x1E; i++) ++ { ++ emm[0x13 + destPos[i]] ^= mask[i & 0x0F]; ++ } ++ ++ // Fix CRC (optional) ++ l = (((emm[1] << 8) + emm[2]) & 0xFFF) + 3 - 4; ++ crc = fletcher_crc32(emm, l); ++ ++ emm[l + 0] = crc >> 24; ++ emm[l + 1] = crc >> 16; ++ emm[l + 2] = crc >> 8; ++ emm[l + 3] = crc >> 0; ++} ++ ++static int8_t PowervuEMM(uint8_t *emm, uint32_t *keysAdded) ++{ ++ uint8_t emmInfo, emmType, decryptOk = 0; ++ uint16_t emmLen = GetEcmLen(emm); ++ uint32_t i, uniqueAddress, groupId, keyRef = 0; ++ //uint32_t emmCrc32; ++ uint8_t emmKey[7], tmpEmmKey[7], tmp[26]; ++ char keyName[EMU_MAX_CHAR_KEYNAME], keyValue[16]; ++ char uaInfo[4+8+1]; ++ ++ if(emmLen < 50) ++ { ++ return 1; ++ } ++ ++ // Check if unmasking is needed ++ if((emm[3] & 0xF0) == 0x50) ++ { ++ PowervuUnmaskEmm(emm); ++ } ++ ++ // looks like checksum does not work for all EMMs ++ //emmCrc32 = b2i(4, emm+emmLen-4); ++ // ++ //if(fletcher_crc32(emm, emmLen-4) != emmCrc32) ++ //{ ++ // return 8; ++ //} ++ emmLen -= 4; ++ ++ uniqueAddress = b2i(4, emm+12); ++ snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%.8X", uniqueAddress); ++ ++ do ++ { ++ if(!GetPowervuEmmKey(emmKey, 0, keyName, 7, 0, keyRef++, &groupId)) ++ { ++ cs_log_dbg(D_EMM, "EMM error: AU key for UA %s is missing", keyName); ++ return 2; ++ } ++ ++ for(i=19; i+27<=emmLen; i+=27) { ++ emmInfo = emm[i]; ++ ++ if(!GetBit(emmInfo, 7)) ++ { ++ continue; ++ } ++ ++ //keyNb = emm[i] & 0x0F; ++ ++ memcpy(tmp, emm+i+1, 26); ++ memcpy(tmpEmmKey, emmKey, 7); ++ PowervuDecrypt(emm+i+1, 26, tmpEmmKey, 0); ++ ++ if((emm[13] != emm[i+24]) || (emm[14] != emm[i+25]) || (emm[15] != emm[i+26])) ++ { ++ memcpy(emm+i+1, tmp, 26); ++ memcpy(tmpEmmKey, emmKey, 7); ++ PowervuDecrypt(emm+i+1, 26, tmpEmmKey, 1); ++ ++ if((emm[13] != emm[i+24]) || (emm[14] != emm[i+25]) || (emm[15] != emm[i+26])) ++ { ++ memcpy(emm+i+1, tmp, 26); ++ memcpy(tmpEmmKey, emmKey, 7); ++ continue; ++ } ++ } ++ ++ decryptOk = 1; ++ ++ emmType = emm[i+2] & 0x7F; ++ if(emmType > 1) ++ { ++ continue; ++ } ++ ++ snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%.2X", emmType); ++ snprintf(uaInfo, sizeof(uaInfo), "UA: %08X", uniqueAddress); ++ ++ if(emm[i+3] == 0 && emm[i+4] == 0) ++ { ++ cs_hexdump(0, &emm[i+3], 7, keyValue, sizeof(keyValue)); ++ cs_log("Key found in EMM: P %.4X**** %s %s -> REJECTED (looks invalid) UA: %.8X", groupId, keyName, keyValue, uniqueAddress); ++ continue; ++ } ++ ++ UpdateKeysByProviderMask('P', groupId<<16, 0x0000FFFF, keyName, &emm[i+3], 7, uaInfo); ++ ++ (*keysAdded)++; ++ cs_hexdump(0, &emm[i+3], 7, keyValue, sizeof(keyValue)); ++ cs_log("Key found in EMM: P %.4X**** %s %s ; UA: %.8X", groupId, keyName, keyValue, uniqueAddress); ++ } ++ ++ } while(!decryptOk); ++ ++ return 0; ++} ++ ++int32_t GetPowervuHexserials(uint16_t srvid, uint8_t hexserials[][4], int32_t length, int32_t* count) ++{ ++ //srvid == 0xFFFF -> get all ++ ++ uint32_t i, j; ++ uint32_t groupid; ++ int32_t len, k; ++ KeyDataContainer *KeyDB; ++ uint8_t tmp[4]; ++ int8_t alreadyAdded; ++ ++ KeyDB = GetKeyContainer('P'); ++ if(KeyDB == NULL) ++ { return 0; } ++ ++ (*count) = 0; ++ ++ for(i=0; ikeyCount && (*count)EmuKeys[i].provider <= 0x0000FFFF) // skip au keys ++ { continue; } ++ ++ if(srvid != 0xFFFF && (KeyDB->EmuKeys[i].provider & 0x0000FFFF) != srvid) ++ { continue; } ++ ++ groupid = KeyDB->EmuKeys[i].provider>>16; ++ ++ for(j=0; jkeyCount && (*count)EmuKeys[j].provider != groupid) // search au key with groupip ++ { continue; } ++ ++ len = strlen(KeyDB->EmuKeys[j].keyName); ++ ++ if(len < 3) ++ { continue;} ++ ++ if(len > 8) ++ { len = 8; } ++ ++ memset(tmp, 0, 4); ++ CharToBin(tmp+(4-(len/2)), KeyDB->EmuKeys[j].keyName, len); ++ ++ for(k=0, alreadyAdded=0; k<*count; k++) ++ { ++ if(!memcmp(hexserials[k], tmp, 4)) ++ { ++ alreadyAdded = 1; ++ break; ++ } ++ } ++ ++ if(!alreadyAdded) ++ { ++ memcpy(hexserials[*count], tmp, 4); ++ (*count)++; ++ } ++ } ++ ++ } ++ ++ return 1; ++} ++ ++// Drecrypt EMM EMU ++static int8_t DrecryptGetEmmKey(uint8_t *buf, uint32_t keyIdent, uint16_t keyName, uint8_t isCriticalKey) ++{ ++ char keyStr[EMU_MAX_CHAR_KEYNAME]; ++ snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "MK%04X", keyName); ++ return FindKey('D', keyIdent, 0, keyStr, buf, 32, isCriticalKey, 0, 0, NULL); ++} ++ ++static void DrecryptWriteEebin(const char *path, const char *name) ++{ ++ char tmp[256]; ++ FILE *file = NULL; ++ uint8_t i, buffer[64][32]; ++ uint32_t prvid; ++ ++ // Set path ++ if (path != NULL) ++ { ++ snprintf(tmp, 256, "%s%s", path, name); ++ } ++ else // No path set, use SoftCam.Keys's path ++ { ++ snprintf(tmp, 256, "%s%s", emu_keyfile_path, name); ++ } ++ ++ if ((file = fopen(tmp, "wb")) != NULL) ++ { ++ cs_log("Writing key file: %s", tmp); ++ } ++ else ++ { ++ cs_log("Error writing key file: %s", tmp); ++ return; ++ } ++ ++ // Load keys from db to buffer ++ prvid = (strncmp(name, "ee36.bin", 9) == 0) ? 0x4AE111 : 0x4AE114; ++ ++ for (i = 0; i < 32; i++) // Load "3B" type keys ++ { ++ snprintf(tmp, 5, "3B%02X", i); ++ if (!FindKey('D', prvid, 0, tmp, buffer[i], 32, 0, 0, 0, NULL)) ++ { ++ memset(buffer[i], 0xFF, 32); ++ } ++ } ++ ++ for (i = 0; i < 32; i++) // Load "56" type keys ++ { ++ snprintf(tmp, 5, "56%02X", i); ++ if (!FindKey('D', prvid, 0, tmp, buffer[32 + i], 32, 0, 0, 0, NULL)) ++ { ++ memset(buffer[32 + i], 0xFF, 32); ++ } ++ } ++ ++ // Write buffer to ee.bin file ++ fwrite(buffer, 1, sizeof(buffer), file); ++ fclose(file); ++} ++ ++static int8_t DrecryptProcessEMM(struct s_reader *rdr, uint32_t provId, uint8_t *emm, uint32_t *keysAdded) ++{ ++ uint16_t emmLen, emmDataLen; ++ uint32_t i, keyIdent; ++ uint16_t keyName; ++ uint8_t emmKey[32]; ++ uint8_t *curECMkey3B = NULL, *curECMkey56 = NULL; ++ uint8_t keynum =0, keyidx = 0, keyclass = 0, key1offset, key2offset; ++ char newKeyName[EMU_MAX_CHAR_KEYNAME], curKeyName[EMU_MAX_CHAR_KEYNAME], keyValue[100]; ++ ++ emmDataLen = GetEcmLen(emm); ++ emmLen = ((emm[1] & 0xF) << 8) | emm[2]; ++ ++ if (emmDataLen < emmLen + 3) ++ { ++ return 4; // Corrupt data ++ } ++ ++ if (emm[0] == 0x91) ++ { ++ Drecrypt2OverEMM(emm); ++ return 0; ++ } ++ else if (emm[0] == 0x82) ++ { ++ ReasmEMM82(emm); ++ return 0; ++ } ++ else if (emm[0] != 0x86) ++ { ++ return 1; // Not supported ++ } ++ ++ // Emm type 0x86 only ++ switch (emm[4]) ++ { ++ case 0x02: ++ keynum = 0x2C; ++ keyidx = 0x30; ++ keyclass = 0x26; ++ key1offset = 0x35; ++ key2offset = 0x6D; ++ break; ++ ++ case 0x4D: ++ keynum = 0x61; ++ keyidx = 0x60; ++ keyclass = 0x05; ++ key1offset = 0x62; ++ key2offset = 0x8B; ++ break; ++ ++ default: ++ return 1; // Not supported ++ } ++ ++ switch (provId & 0xFF) ++ { ++ case 0x11: ++ { ++ snprintf(curKeyName, EMU_MAX_CHAR_KEYNAME, "3B%02X", emm[keyclass]); ++ FindKey('D', 0x4AE111, 0, curKeyName, curECMkey3B, 32, 0, 0, 0, NULL); ++ ++ snprintf(curKeyName, EMU_MAX_CHAR_KEYNAME, "56%02X", emm[keyclass]); ++ FindKey('D', 0x4AE111, 0, curKeyName, curECMkey56, 32, 0, 0, 0, NULL); ++ ++ break; ++ } ++ ++ case 0x14: ++ { ++ snprintf(curKeyName, EMU_MAX_CHAR_KEYNAME, "3B%02X", emm[keyclass]); ++ FindKey('D', 0x4AE114, 0, curKeyName, curECMkey3B, 32, 0, 0, 0, NULL); ++ ++ snprintf(curKeyName, EMU_MAX_CHAR_KEYNAME, "56%02X", emm[keyclass]); ++ FindKey('D', 0x4AE114, 0, curKeyName, curECMkey56, 32, 0, 0, 0, NULL); ++ ++ break; ++ } ++ ++ default: ++ return 9; // Wrong provider ++ } ++ ++ keyIdent = (0x4AE1 << 8) | provId; ++ keyName = (emm[3] << 8) | emm[keynum]; ++ ++ if (!DrecryptGetEmmKey(emmKey, keyIdent, keyName, 1)) ++ { ++ return 2; ++ } ++ ++ // Key #1 ++ for (i = 0; i < 4; i++) ++ { ++ DrecryptDecrypt(&emm[key1offset + (i * 8)], emmKey); ++ } ++ ++ // Key #2 ++ for (i = 0; i < 4; i++) ++ { ++ DrecryptDecrypt(&emm[key2offset + (i * 8)], emmKey); ++ } ++ ++ // Key #1 ++ keyName = emm[keyidx] << 8 | emm[keyclass]; ++ snprintf(newKeyName, EMU_MAX_CHAR_KEYNAME, "%.4X", keyName); ++ ++ if (memcmp(&emm[key1offset], emm[keyidx] == 0x3b ? curECMkey3B : curECMkey56, 32) != 0) ++ { ++ memcpy(emm[keyidx] == 0x3b ? curECMkey3B : curECMkey56, &emm[key1offset], 32); ++ SetKey('D', keyIdent, newKeyName, &emm[key1offset], 32, 0, NULL, NULL); ++ (*keysAdded)++; ++ ++ cs_hexdump(0, &emm[key1offset], 32, keyValue, sizeof(keyValue)); ++ cs_log("Key found in EMM: D %.6X %s %s class %02X", keyIdent, newKeyName, keyValue, emm[keyclass]); ++ } ++ else ++ { ++ cs_log("Key %.6X %s already exists", keyIdent, newKeyName); ++ } ++ ++ // Key #2 ++ keyName = (emm[keyidx] == 0x56 ? 0x3B00 : 0x5600) | emm[keyclass]; ++ snprintf(newKeyName, EMU_MAX_CHAR_KEYNAME, "%.4X", keyName); ++ ++ if (memcmp(&emm[key2offset], emm[keyidx] == 0x3b ? curECMkey56 : curECMkey3B, 32) != 0) ++ { ++ memcpy(emm[keyidx] == 0x3b ? curECMkey56 : curECMkey3B, &emm[key2offset], 32); ++ SetKey('D', keyIdent, newKeyName, &emm[key2offset], 32, 0, NULL, NULL); ++ (*keysAdded)++; ++ ++ cs_hexdump(0, &emm[key2offset], 32, keyValue, sizeof(keyValue)); ++ cs_log("Key found in EMM: D %.6X %s %s class %02X", keyIdent, newKeyName, keyValue, emm[keyclass]); ++ } ++ else ++ { ++ cs_log("Key %.6X %s already exists", keyIdent, newKeyName); ++ } ++ ++ if (*keysAdded > 0) // Write new ecm keys to ee.bin file ++ { ++ switch (provId & 0xFF) ++ { ++ case 0x11: ++ DrecryptWriteEebin(rdr->extee36, "ee36.bin"); ++ break; ++ ++ case 0x14: ++ DrecryptWriteEebin(rdr->extee56, "ee56.bin"); ++ break; ++ ++ default: ++ cs_log("Provider %02X doesn't have a matching ee.bin file", provId & 0xFF); ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++static int8_t Drecrypt2EMM(struct s_reader *rdr, uint32_t provId, uint8_t *emm, uint32_t *keysAdded) ++{ ++ int8_t result = DrecryptProcessEMM(rdr, provId, emm, keysAdded); ++ ++ if (result == 2) ++ { ++ uint8_t keynum = 0, emmkey; ++ uint32_t i; ++ KeyDataContainer *KeyDB = GetKeyContainer('D'); ++ ++ if (KeyDB == NULL) ++ { ++ return result; ++ } ++ ++ for (i = 0; i < KeyDB->keyCount; i++) ++ { ++ if (KeyDB->EmuKeys[i].provider != ((0x4AE1 << 8) | provId)) ++ { ++ continue; ++ } ++ ++ if (strlen(KeyDB->EmuKeys[i].keyName) < 6) ++ { ++ continue; ++ } ++ ++ if (memcmp(KeyDB->EmuKeys[i].keyName, "MK", 2)) ++ { ++ continue; ++ } ++ ++ CharToBin(&keynum, KeyDB->EmuKeys[i].keyName + 4, 2); ++ emmkey = (emm[4] == 0x4D) ? emm[0x61] : emm[0x2C]; ++ ++ if (keynum == emmkey) ++ { ++ if (provId == 0x11) ++ { ++ CharToBin(&rdr->dre36_force_group, KeyDB->EmuKeys[i].keyName + 2, 2); ++ } ++ else ++ { ++ CharToBin(&rdr->dre56_force_group, KeyDB->EmuKeys[i].keyName + 2, 2); ++ } ++ ++ break; ++ } ++ } ++ } ++ ++ return result; ++} ++ ++int32_t GetDrecryptHexserials(uint16_t caid, uint32_t provid, uint8_t *hexserials, int32_t length, int32_t *count) ++{ ++ uint32_t i; ++ KeyDataContainer *KeyDB = GetKeyContainer('D'); ++ ++ if (KeyDB == NULL) ++ { ++ return 0; ++ } ++ ++ (*count) = 0; ++ ++ for (i = 0; i < KeyDB->keyCount && (*count) < length; i++) ++ { ++ ++ if (KeyDB->EmuKeys[i].provider != ((caid << 8) | provid)) ++ { ++ continue; ++ } ++ ++ if (strlen(KeyDB->EmuKeys[i].keyName) < 6) ++ { ++ continue; ++ } ++ ++ if (memcmp(KeyDB->EmuKeys[i].keyName, "MK", 2)) ++ { ++ continue; ++ } ++ ++ CharToBin(&hexserials[(*count)], KeyDB->EmuKeys[i].keyName + 2, 2); ++ ++ (*count)++; ++ } ++ ++ return 1; ++} ++ ++// Tandberg EMM EMU ++static uint8_t MixTable[] = ++{ ++ 0x12,0x78,0x4B,0x19,0x13,0x80,0x2F,0x84, ++ 0x86,0x4C,0x09,0x53,0x15,0x79,0x6B,0x49, ++ 0x10,0x4D,0x33,0x43,0x18,0x37,0x83,0x38, ++ 0x82,0x1B,0x6E,0x24,0x2A,0x85,0x3C,0x3D, ++ 0x5A,0x58,0x55,0x5D,0x20,0x41,0x65,0x51, ++ 0x0C,0x45,0x63,0x7F,0x0F,0x46,0x21,0x7C, ++ 0x2C,0x61,0x7E,0x0A,0x42,0x57,0x35,0x16, ++ 0x87,0x3B,0x4F,0x40,0x34,0x22,0x26,0x74, ++ 0x32,0x69,0x44,0x7A,0x6A,0x6D,0x0D,0x56, ++ 0x23,0x2B,0x5C,0x72,0x76,0x36,0x28,0x25, ++ 0x2E,0x52,0x5B,0x6C,0x7D,0x30,0x0B,0x5E, ++ 0x47,0x1F,0x7B,0x31,0x3E,0x11,0x77,0x1E, ++ 0x60,0x75,0x54,0x27,0x50,0x17,0x70,0x59, ++ 0x1A,0x2D,0x4A,0x67,0x3A,0x5F,0x68,0x08, ++ 0x4E,0x3F,0x29,0x6F,0x81,0x71,0x39,0x64, ++ 0x48,0x66,0x73,0x14,0x0E,0x1D,0x62,0x1C ++}; ++ ++void TandbergRotateBytes(unsigned char *in, int n) ++{ ++ if(n > 1) ++ { ++ unsigned char *e = in + n - 1; ++ do ++ { ++ unsigned char temp = *in; ++ *in++ = *e; ++ *e-- = temp; ++ } ++ while (in < e); ++ } ++} ++ ++static void TandbergECMKeyDecrypt(uint8_t* emmKey, uint8_t* tagData, uint8_t* ecmKey) ++{ ++ TandbergRotateBytes(emmKey, 8); ++ uint8_t iv[8] = { 0 }; ++ uint8_t* payLoad = tagData + 4 + 5; ++ des_cbc_decrypt(payLoad, iv, emmKey, 16); ++ ++ ecmKey[0] = payLoad[0x0F]; ++ ecmKey[1] = payLoad[0x01]; ++ ecmKey[2] = payLoad[0x0B]; ++ ecmKey[3] = payLoad[0x03]; ++ ecmKey[4] = payLoad[0x0E]; ++ ecmKey[5] = payLoad[0x04]; ++ ecmKey[6] = payLoad[0x0A]; ++ ecmKey[7] = payLoad[0x08]; ++} ++ ++static int8_t TandbergParseEMMNanoTags(uint8_t* data, uint32_t length, uint8_t keyIndex, uint32_t *keysAdded) ++{ ++ uint8_t tagType, tagLength, blockIndex; ++ uint32_t pos = 0, entitlementId; ++ int32_t i, k; ++ uint32_t ks[32]; ++ uint8_t* tagData; ++ uint8_t emmKey[8]; ++ char keyValue[17]; ++ uint8_t tagDataDecrypted[0x10][8]; ++ ++ if(length < 2) ++ { ++ return 1; ++ } ++ ++ while(pos < length) ++ { ++ tagType = data[pos]; ++ tagLength = data[pos+1]; ++ ++ if(pos + 2 + tagLength > length) ++ { ++ return 1; ++ } ++ ++ tagData = data + pos + 2; ++ ++ switch(tagType) ++ { ++ case 0xE4: // EMM_TAG_SECURITY_TABLE_DESCRIPTOR (ram emm keys) ++ { ++ uint8_t tagMode = data[pos + 2]; ++ ++ switch(tagMode) ++ { ++ case 0x01: // keySet 01 (MK01) ++ { ++ if(tagLength != 0x8A) ++ { ++ cs_log("WARNING: nanoTag E4 length (%d) != %d", tagLength, 0x8A); ++ break; ++ } ++ ++ if(!GetTandbergKey(keyIndex, "MK01", emmKey, 8)) ++ { ++ break; ++ } ++ ++ uint8_t iv[8] = { 0 }; ++ uint8_t* tagPayload = tagData + 2; ++ des_cbc_decrypt(tagPayload, iv, emmKey, 136); ++ ++ for (k = 0; k < 0x10; k++) // loop 0x10 keys ++ { ++ for (i = 0; i < 8; i++) // loop 8 bytes of key ++ { ++ tagDataDecrypted[k][i] = tagPayload[MixTable[8*k + i]]; ++ } ++ } ++ ++ blockIndex = tagData[1] & 0x03; ++ ++ for(i = 0; i < 0x10; i++) ++ { ++ SetKey('T', (blockIndex << 4) + i, "MK01", tagDataDecrypted[i], 8, 0, NULL, NULL); ++ } ++ } ++ break; ++ ++ case 0xFF: // keySet FF (MK) ++ { ++ if(tagLength != 0x82) ++ { ++ cs_log("WARNING: nanoTag E4 length (%d) != %d", tagLength, 0x82); ++ break; ++ } ++ ++ blockIndex = tagData[1] & 0x03; ++ ++ if(!GetTandbergKey(keyIndex, "MK", emmKey, 8)) ++ { ++ break; ++ } ++ ++ des_set_key(emmKey, ks); ++ ++ for(i = 0; i < 0x10; i++) ++ { ++ des(tagData + 2 + (i*8), ks, 0); ++ } ++ ++ for(i = 0; i < 0x10; i++) ++ { ++ SetKey('T', (blockIndex << 4) + i, "MK", tagData + 2 + (i*8), 8, 0, NULL, NULL); ++ } ++ } ++ break; ++ ++ default: ++ cs_log("WARNING: nanoTag E4 mode %.2X not supported", tagMode); ++ break; ++ } ++ break; ++ } ++ ++ case 0xE1: // EMM_TAG_EVENT_ENTITLEMENT_DESCRIPTOR (ecm keys) ++ { ++ uint8_t tagMode = data[pos + 2 + 4]; ++ ++ switch(tagMode) ++ { ++ case 0x00: // ecm keys from mode FF ++ { ++ if(tagLength != 0x12) ++ { ++ cs_log("WARNING: nanoTag E1 length (%d) != %d", tagLength, 0x12); ++ break; ++ } ++ ++ entitlementId = b2i(4, tagData); ++ ++ if(!GetTandbergKey(keyIndex, "MK", emmKey, 8)) ++ { ++ break; ++ } ++ ++ des_set_key(emmKey, ks); ++ des(tagData + 4 + 5, ks, 0); ++ ++ if((tagData + 4 + 5 + 7) != 0x00) // check if key looks valid (last byte 0x00) ++ { ++ break; ++ } ++ ++ if(UpdateKey('T', entitlementId, "01", tagData + 4 + 5, 8, 1, NULL)) ++ { ++ (*keysAdded)++; ++ cs_hexdump(0, tagData + 4 + 5, 8, keyValue, sizeof(keyValue)); ++ cs_log("Key found in EMM: T %.8X 01 %s", entitlementId, keyValue); ++ } ++ } ++ break; ++ ++ case 0x01: // ecm keys from mode 01 ++ { ++ if(tagLength != 0x1A) ++ { ++ cs_log("WARNING: nanoTag E1 length (%d) != %d", tagLength, 0x1A); ++ break; ++ } ++ ++ entitlementId = b2i(4, tagData); ++ ++ if(!GetTandbergKey(keyIndex, "MK01", emmKey, 8)) ++ { ++ break; ++ } ++ ++ uint8_t ecmKey[8] = { 0 }; ++ TandbergECMKeyDecrypt(emmKey, tagData, ecmKey); ++ ++ if(ecmKey[7] != 0x00) // check if key looks valid (last byte 0x00) ++ { ++ break; ++ } ++ ++ if(UpdateKey('T', entitlementId, "01", ecmKey, 8, 1, NULL)) ++ { ++ (*keysAdded)++; ++ cs_hexdump(0, ecmKey, 8, keyValue, sizeof(keyValue)); ++ cs_log("Key found in EMM: T %.8X 01 %s", entitlementId, keyValue); ++ } ++ } ++ break; ++ ++ default: ++ cs_log("WARNING: nanoTag E1 mode %.2X not supported", tagMode); ++ break; ++ } ++ break; ++ } ++ ++ default: ++ cs_log("WARNING: nanoTag %.2X not supported", tagType); ++ break; ++ } ++ ++ pos += 2 + tagLength; ++ } ++ ++ return 0; ++} ++ ++static int8_t TandbergParseEMMNanoData(uint8_t* data, uint32_t* nanoLength, uint32_t maxLength, uint8_t keyIndex, uint32_t *keysAdded) ++{ ++ uint32_t pos = 0; ++ uint16_t sectionLength; ++ int8_t ret = 0; ++ ++ if(maxLength < 2) ++ { ++ (*nanoLength) = 0; ++ return 1; ++ } ++ ++ sectionLength = ((data[pos]<<8) | data[pos+1]) & 0x0FFF; ++ ++ if(pos + 2 + sectionLength > maxLength) ++ { ++ (*nanoLength) = pos; ++ return 1; ++ } ++ ++ ret = TandbergParseEMMNanoTags(data + pos + 2, sectionLength, keyIndex, keysAdded); ++ ++ pos += 2 + sectionLength; ++ ++ (*nanoLength) = pos; ++ return ret; ++} ++ ++static int8_t TandbergEMM(uint8_t *emm, uint32_t *keysAdded) ++{ ++ uint8_t keyIndex, ret = 0; ++ uint16_t emmLen = GetEcmLen(emm); ++ uint32_t pos = 3; ++ uint32_t permissionDataType; ++ uint32_t nanoLength = 0; ++ ++ while (pos < emmLen && !ret) ++ { ++ permissionDataType = emm[pos]; ++ ++ switch(permissionDataType) ++ { ++ case 0x00: ++ { ++ break; ++ } ++ ++ case 0x01: ++ { ++ pos += 0x0A; ++ break; ++ } ++ ++ case 0x02: ++ { ++ pos += 0x26; ++ break; ++ } ++ ++ default: ++ cs_log("ERROR: unknown permissionDataType %.2X (pos: %d)", permissionDataType, pos); ++ return 1; ++ } ++ ++ if(pos+6 >= emmLen) ++ { ++ break; ++ } ++ ++ keyIndex = emm[pos+1]; ++ ++ // EMM validation ++ // Copy payload checksum bytes and then set them to zero, ++ // so they do not affect the calculated checksum. ++ uint16_t payloadChecksum = (emm[pos + 2] << 8) | emm[pos + 3]; ++ memset(emm + pos + 2, 0, 2); ++ uint16_t calculatedChecksum = TandbergChecksum(emm + 3, emmLen - 3); ++ ++ if(calculatedChecksum != payloadChecksum) ++ { ++ cs_log("EMM checksum error (%.4X instead of %.4X)", calculatedChecksum, payloadChecksum); ++ return 8; ++ } ++ // End of EMM validation ++ ++ pos += 0x04; ++ ret = TandbergParseEMMNanoData(emm + pos, &nanoLength, emmLen - pos, keyIndex, keysAdded); ++ pos += nanoLength; ++ } ++ ++ return ret; ++} ++ ++const char* GetProcessEMMErrorReason(int8_t result) ++{ ++ switch(result) { ++ case 0: ++ return "No error"; ++ case 1: ++ return "EMM not supported"; ++ case 2: ++ return "Key not found"; ++ case 3: ++ return "Nano80 problem"; ++ case 4: ++ return "Corrupt data"; ++ case 5: ++ return "Unknown"; ++ case 6: ++ return "Checksum error"; ++ case 7: ++ return "Out of memory"; ++ case 8: ++ return "EMM checksum error"; ++ case 9: ++ return "Wrong provider"; ++ default: ++ return "Unknown"; ++ } ++} ++ ++int8_t ProcessEMM(struct s_reader *rdr, uint16_t caid, uint32_t provider, const uint8_t *emm, uint32_t *keysAdded) ++{ ++ int8_t result = 1; ++ uint8_t emmCopy[EMU_MAX_EMM_LEN]; ++ uint16_t emmLen = GetEcmLen(emm); ++ ++ if(emmLen > EMU_MAX_EMM_LEN) { ++ return 1; ++ } ++ memcpy(emmCopy, emm, emmLen); ++ *keysAdded = 0; ++ ++ if(caid==0x0500) { ++ result = ViaccessEMM(emmCopy, keysAdded); ++ } ++ else if((caid>>8)==0x06) { ++ result = Irdeto2EMM(caid, emmCopy, keysAdded); ++ } ++ else if((caid>>8)==0x0E) { ++ result = PowervuEMM(emmCopy, keysAdded); ++ } ++ else if(caid==0x4AE1) { ++ result = Drecrypt2EMM(rdr, provider, emmCopy, keysAdded); ++ } ++ else if((caid>>8)==0x10) { ++ result = TandbergEMM(emmCopy, keysAdded); ++ } ++ ++ if(result != 0) { ++ cs_log_dbg(D_EMM,"EMM failed: %s", GetProcessEMMErrorReason(result)); ++ } ++ ++ return result; ++} +diff -ruNp trunk.patches/module-emulator-osemu.h trunk/module-emulator-osemu.h +--- trunk.patches/module-emulator-osemu.h 1970-01-01 03:00:00.000000000 +0300 ++++ trunk/module-emulator-osemu.h 2018-04-03 03:20:07.658045369 +0300 +@@ -0,0 +1,127 @@ ++#include "globals.h" ++#include "module-emulator-stream.h" ++ ++#ifndef EMULATOR_H_ ++#define EMULATOR_H_ ++ ++#define EMU_MAX_CHAR_KEYNAME 12 ++#define EMU_KEY_FILENAME "SoftCam.Key" ++#define EMU_KEY_FILENAME_MAX_LEN 31 ++#define EMU_MAX_ECM_LEN MAX_ECM_SIZE ++#define EMU_MAX_EMM_LEN MAX_EMM_SIZE ++ ++typedef struct KeyData KeyData; ++ ++struct KeyData ++{ ++ char identifier; ++ uint32_t provider; ++ char keyName[EMU_MAX_CHAR_KEYNAME]; ++ uint8_t *key; ++ uint32_t keyLength; ++ KeyData *nextKey; ++}; ++ ++typedef struct ++{ ++ KeyData *EmuKeys; ++ uint32_t keyCount; ++ uint32_t keyMax; ++} KeyDataContainer; ++ ++extern KeyDataContainer CwKeys; ++extern KeyDataContainer ViKeys; ++extern KeyDataContainer NagraKeys; ++extern KeyDataContainer IrdetoKeys; ++extern KeyDataContainer NDSKeys; ++extern KeyDataContainer BissKeys; ++extern KeyDataContainer PowervuKeys; ++extern KeyDataContainer DreKeys; ++extern KeyDataContainer TandbergKeys; ++extern uint8_t viasat_const[]; ++ ++uint32_t GetOSemuVersion(void); ++ ++void set_emu_keyfile_path(const char *path); ++void clear_emu_keydata(void); ++uint8_t read_emu_keyfile(struct s_reader *rdr, const char *path); ++ ++#if !defined(__APPLE__) && !defined(__ANDROID__) ++void read_emu_keymemory(struct s_reader *rdr); ++#endif ++ ++void read_emu_eebin(const char *path, const char *name); ++void read_emu_deskey(uint8_t *dreOverKey, uint8_t len); ++ ++int32_t CharToBin(uint8_t *out, const char *in, uint32_t inLen); ++ ++/* Error codes ++0 OK ++1 ECM not supported ++2 Key not found ++3 Nano80 problem ++4 Corrupt data ++5 CW not found ++6 CW checksum error ++7 Out of memory ++8 ECM checksum error ++9 ICG error ++*/ ++#ifdef WITH_EMU ++int8_t ProcessECM(struct s_reader *rdr, int16_t ecmDataLen, uint16_t caid, uint32_t provider, ++ const uint8_t *ecm, uint8_t *dw, uint16_t srvid, uint16_t ecmpid, EXTENDED_CW* cw_ex); ++#else ++int8_t ProcessECM(struct s_reader *rdr, int16_t ecmDataLen, uint16_t caid, uint32_t provider, ++ const uint8_t *ecm, uint8_t *dw, uint16_t srvid, uint16_t ecmpid); ++#endif ++ ++const char* GetProcessECMErrorReason(int8_t result); ++ ++/* Error codes ++0 OK ++1 EMM not supported ++2 Key not found ++3 Nano80 problem ++4 Corrupt data ++5 ++6 Checksum error ++7 Out of memory ++*/ ++int8_t ProcessEMM(struct s_reader *rdr, uint16_t caid, uint32_t provider, const uint8_t *emm, uint32_t *keysAdded); ++ ++const char* GetProcessEMMErrorReason(int8_t result); ++ ++// hexserial must be of type "uint8_t hexserial[3]" ++// returns 0 on error, 1 on success ++int32_t GetIrdeto2Hexserial(uint16_t caid, uint8_t* hexserial); ++ ++// hexserials must be of type "uint8_t hexserials[length][4]" ++// if srvid == 0xFFFF all serials are returned (no srvid filtering) ++// returns 0 on error, 1 on success ++int32_t GetPowervuHexserials(uint16_t srvid, uint8_t hexserials[][4], int32_t length, int32_t* count); ++ ++// hexserials must be of type "uint8_t hexserials[length]" ++// returns 0 on error, 1 on success ++int32_t GetDrecryptHexserials(uint16_t caid, uint32_t provid, uint8_t *hexserials, int32_t length, int32_t* count); ++ ++#define PVU_CW_VID 0 // VIDeo ++#define PVU_CW_HSD 1 // High Speed Data ++#define PVU_CW_A1 2 // Audio 1 ++#define PVU_CW_A2 3 // Audio 2 ++#define PVU_CW_A3 4 // Audio 3 ++#define PVU_CW_A4 5 // Audio 4 ++#define PVU_CW_UTL 6 // UTiLity ++#define PVU_CW_VBI 7 // Vertical Blanking Interval ++ ++#ifdef WITH_EMU ++int8_t PowervuECM(uint8_t *ecm, uint8_t *dw, uint16_t srvid, emu_stream_client_key_data *cdata, EXTENDED_CW* cw_ex); ++#else ++int8_t PowervuECM(uint8_t *ecm, uint8_t *dw, emu_stream_client_key_data *cdata); ++#endif ++ ++#ifdef WITH_EMU ++int32_t FindKey(char identifier, uint32_t provider, uint32_t providerIgnoreMask, char *keyName, uint8_t *key, ++ uint32_t maxKeyLength, uint8_t isCriticalKey, uint32_t keyRef, uint8_t matchLength, uint32_t *getProvider); ++#endif ++ ++#endif +diff -ruNp trunk.patches/module-emulator-stream.c trunk/module-emulator-stream.c +--- trunk.patches/module-emulator-stream.c 1970-01-01 03:00:00.000000000 +0300 ++++ trunk/module-emulator-stream.c 2018-04-03 03:20:07.658045369 +0300 +@@ -0,0 +1,1105 @@ ++#define MODULE_LOG_PREFIX "emu" ++ ++#include "globals.h" ++#include "cscrypt/des.h" ++ ++#ifdef WITH_EMU ++#include "oscam-string.h" ++#include "oscam-config.h" ++#include "oscam-time.h" ++#include "oscam-net.h" ++ ++extern int32_t exit_oscam; ++#endif ++ ++#include "ffdecsa/ffdecsa.h" ++#include "module-emulator-osemu.h" ++#include "module-emulator-stream.h" ++ ++typedef struct ++{ ++ int32_t connfd; ++ int32_t connid; ++} emu_stream_client_conn_data; ++ ++int8_t stream_server_thread_init = 0; ++char emu_stream_source_host[256] = {"127.0.0.1"}; ++int32_t emu_stream_source_port = 8001; ++char *emu_stream_source_auth = NULL; ++int32_t emu_stream_relay_port = 17999; ++int8_t emu_stream_emm_enabled = 0; ++uint32_t cluster_size = 50; ++ ++static uint8_t emu_stream_server_mutex_init = 0; ++static pthread_mutex_t emu_stream_server_mutex; ++static int32_t glistenfd, gconncount = 0, gconnfd[EMU_STREAM_SERVER_MAX_CONNECTIONS]; ++ ++#ifdef WITH_EMU ++pthread_mutex_t emu_fixed_key_srvid_mutex; ++uint16_t emu_stream_cur_srvid[EMU_STREAM_SERVER_MAX_CONNECTIONS]; ++int8_t stream_server_has_ecm[EMU_STREAM_SERVER_MAX_CONNECTIONS]; ++ ++pthread_mutex_t emu_fixed_key_data_mutex[EMU_STREAM_SERVER_MAX_CONNECTIONS]; ++emu_stream_client_key_data emu_fixed_key_data[EMU_STREAM_SERVER_MAX_CONNECTIONS]; ++LLIST *ll_emu_stream_delayed_keys[EMU_STREAM_SERVER_MAX_CONNECTIONS]; ++#endif ++ ++static void SearchTsPackets(uint8_t *buf, uint32_t bufLength, uint16_t *packetSize, uint16_t *startOffset) ++{ ++ uint32_t i; ++ ++ (*packetSize) = 0; ++ (*startOffset) = 0; ++ ++ for(i=0; i free_data_length ? free_data_length : (len-offset); ++ ++ memcpy(data+(*data_pos), buf+offset, copySize); ++ (*data_pos) += copySize; ++ ++ found_start = 0; ++ for(i=0; i < *data_pos; i++) ++ { ++ if((data[i] & table_mask) == table_id) ++ { ++ if(i != 0) ++ { ++ if((*data_pos)-i > i) ++ { memmove(data, &data[i], (*data_pos)-i); } ++ else ++ { memcpy(data, &data[i], (*data_pos)-i); } ++ ++ *data_pos -= i; ++ } ++ found_start = 1; ++ break; ++ } ++ } ++ if(!found_start) ++ { *flag = 0; return; } ++ ++ *flag = 2; ++ ++ if(*data_pos < 3) ++ { return; } ++ ++ section_length = SCT_LEN(data); ++ ++ if(section_length > data_length || section_length < min_table_length) ++ { *flag = 0; return; } ++ ++ if((*data_pos) < section_length) ++ { return; } ++ ++ func(cdata); ++ ++ found_start = 0; ++ for(i=section_length; i < *data_pos; i++) ++ { ++ if((data[i] & table_mask) == table_id) ++ { ++ if((*data_pos)-i > i) ++ { memmove(data, &data[i], (*data_pos)-i); } ++ else ++ { memcpy(data, &data[i], (*data_pos)-i); } ++ ++ *data_pos -= i; ++ found_start = 1; ++ break; ++ } ++ } ++ if(!found_start) ++ { *data_pos = 0; } ++ ++ *flag = 1; ++} ++ ++static void ParsePATData(emu_stream_client_data *cdata) ++{ ++ uint8_t* data = cdata->pat_data; ++ uint16_t section_length = SCT_LEN(data); ++ uint16_t srvid; ++ int32_t i; ++ ++ for(i=8; i+7srvid == srvid) ++ { ++ cdata->pmt_pid = b2i(2, data+i+2) & 0x1FFF; ++ cs_log_dbg(D_READER, "Stream %i found pmt pid: 0x%04X (%i)",cdata->connid, cdata->pmt_pid, cdata->pmt_pid); ++ break; ++ } ++ } ++} ++ ++static void ParsePMTData(emu_stream_client_data *cdata) ++{ ++ uint8_t* data = cdata->pmt_data; ++ ++ uint16_t section_length = SCT_LEN(data); ++ int32_t i; ++ uint16_t program_info_length = 0, es_info_length = 0; ++ uint8_t descriptor_tag = 0, descriptor_length = 0; ++ uint8_t stream_type; ++ uint16_t stream_pid, caid; ++ ++ cdata->pcr_pid = b2i(2, data+8) &0x1FFF; ++ if(cdata->pcr_pid != 0x1FFF) ++ { ++ cs_log_dbg(D_READER, "Stream %i found pcr pid: 0x%04X (%i)",cdata->connid, cdata->pcr_pid, cdata->pcr_pid); ++ } ++ ++ program_info_length = b2i(2, data+10) &0xFFF; ++ ++ if(12+program_info_length >= section_length) ++ { return; } ++ ++ for(i=12; i+1 < 12+program_info_length; i+=descriptor_length+2) ++ { ++ descriptor_tag = data[i]; ++ descriptor_length = data[i+1]; ++ ++ if(descriptor_length < 1) ++ { break; } ++ ++ if(i+1+descriptor_length >= 12+program_info_length) ++ { break; } ++ ++ if(descriptor_tag == 0x09 && descriptor_length >= 4) ++ { ++ caid = b2i(2, data+i+2); ++ ++ if(caid>>8 == 0x0E) ++ { ++ cdata->ecm_pid = b2i(2, data+i+4) &0x1FFF; ++ cs_log_dbg(D_READER, "Stream %i found ecm pid: 0x%04X (%i)", cdata->connid, cdata->ecm_pid, cdata->ecm_pid); ++ break; ++ } ++ } ++ } ++ ++ for(i=12+program_info_length; i+4video_pid = stream_pid; ++ cs_log_dbg(D_READER, "Stream %i found video pid: 0x%04X (%i)",cdata->connid, stream_pid, stream_pid); ++ } ++ ++ else if(stream_type == 0x03 || stream_type == 0x04 || stream_type == 0x05 || stream_type == 0x06 || ++ stream_type == 0x0F || stream_type == 0x11 || (stream_type >= 0x81 && stream_type <= 0x87) || stream_type == 0x8A) ++ { ++ if(cdata->audio_pid_count >= EMU_STREAM_MAX_AUDIO_SUB_TRACKS) ++ { continue; } ++ ++ cdata->audio_pids[cdata->audio_pid_count] = stream_pid; ++ cdata->audio_pid_count++; ++ cs_log_dbg(D_READER, "Stream %i found audio pid: 0x%04X (%i)", cdata->connid, stream_pid, stream_pid); ++ } ++ } ++} ++ ++static void ParseCATData(emu_stream_client_data *cdata) ++{ ++ uint8_t* data = cdata->cat_data; ++ uint32_t i; ++ ++ for(i = 8; i < (b2i(2, data + 1)&0xFFF) - 1; i += data[i + 1] + 2) ++ { ++ if(data[i] != 0x09) { continue; } ++ ++ uint16_t caid = b2i(2, data + i + 2); ++ uint16_t emm_pid = b2i(2, data + i +4)&0x1FFF; ++ ++ if(caid>>8 == 0x0E) ++ { ++ cdata->emm_pid = emm_pid; ++ cs_log_dbg(D_READER, "Stream %i found audio pid: 0x%04X (%i)", cdata->connid, emm_pid, emm_pid); ++ break; ++ } ++ } ++} ++ ++static void ParseEMMData(emu_stream_client_data *cdata) ++{ ++ uint8_t* data = cdata->emm_data; ++ uint32_t keysAdded = 0; ++ ++ ProcessEMM(NULL, 0x0E00, 0, data, &keysAdded); ++ ++ if(keysAdded) ++ { ++ cs_log("Stream %i found %i keys", cdata->connid, keysAdded); ++ } ++} ++ ++static void ParseECMData(emu_stream_client_data *cdata) ++{ ++ uint8_t* data = cdata->ecm_data; ++ uint16_t section_length = SCT_LEN(data); ++ uint8_t dcw[16]; ++ ++ if(section_length < 0xb) ++ { return; } ++ ++ if(data[0xb] > cdata->ecm_nb || (cdata->ecm_nb == 255 && data[0xb] == 0) ++ || ((cdata->ecm_nb - data[0xb]) > 5)) ++ { ++ cdata->ecm_nb = data[0xb]; ++#ifdef WITH_EMU ++ PowervuECM(data, dcw, cdata->srvid, &cdata->key, NULL); ++#else ++ PowervuECM(data, dcw, &cdata->key); ++#endif ++ } ++} ++ ++static void ParseTSPackets(emu_stream_client_data *data, uint8_t *stream_buf, uint32_t bufLength, uint16_t packetSize) ++{ ++ uint32_t i, j, k; ++ uint32_t tsHeader; ++ uint16_t pid, offset; ++ uint8_t scramblingControl, payloadStart, oddeven; ++ int8_t oddKeyUsed; ++ uint32_t *deskey; ++ uint8_t *pdata; ++ uint8_t *packetClusterA[EMU_STREAM_MAX_AUDIO_SUB_TRACKS][64]; // separate cluster arrays for video and each audio track ++ uint8_t *packetClusterV[256]; ++ void *csakeyA[EMU_STREAM_MAX_AUDIO_SUB_TRACKS] = {0}; ++ void *csakeyV = 0; ++ emu_stream_client_key_data *keydata; ++ uint32_t scrambled_packets = 0; ++ uint32_t scrambled_packetsA[EMU_STREAM_MAX_AUDIO_SUB_TRACKS] = {0}; ++ packetClusterV[0] = NULL; ++ uint32_t cs =0; // video cluster start ++ uint32_t ce =1; // video cluster end ++ uint32_t csa[EMU_STREAM_MAX_AUDIO_SUB_TRACKS] = {0}; // cluster index for audio tracks ++ ++ for(i=0; i> 8; ++ scramblingControl = tsHeader & 0xc0; ++ payloadStart = (tsHeader & 0x400000) >> 22; ++ ++ if(tsHeader & 0x20) ++ { offset = 4 + stream_buf[i+4] + 1; } ++ else ++ { offset = 4; } ++ ++ if(packetSize-offset < 1) ++ { continue; } ++ ++ if(pid == 1) ++ { ++ // set to null pid ++ stream_buf[i+1] |= 0x1f; ++ stream_buf[i+2] = 0xff; ++ ++ if(emu_stream_emm_enabled && !data->emm_pid) ++ { ++ ParseTSData(0x01, 0xFF, 8, &data->have_cat_data, data->cat_data, sizeof(data->cat_data), &data->cat_data_pos, payloadStart, ++ stream_buf+i+offset, packetSize-offset, ParseCATData, data); ++ continue; ++ } ++ } ++ ++ if(emu_stream_emm_enabled && data->emm_pid && pid == data->emm_pid) ++ { ++ // set to null pid ++ stream_buf[i+1] |= 0x1f; ++ stream_buf[i+2] = 0xff; ++ ++ ParseTSData(0x80, 0xF0, 3, &data->have_emm_data, data->emm_data, sizeof(data->emm_data), &data->emm_data_pos, payloadStart, ++ stream_buf+i+offset, packetSize-offset, ParseEMMData, data); ++ continue; ++ } ++ ++ if(pid == 0 && !data->pmt_pid) ++ { ++ ParseTSData(0x00, 0xFF, 16, &data->have_pat_data, data->pat_data, sizeof(data->pat_data), &data->pat_data_pos, payloadStart, ++ stream_buf+i+offset, packetSize-offset, ParsePATData, data); ++ continue; ++ } ++ ++ if(!data->ecm_pid && pid == data->pmt_pid) ++ { ++ ParseTSData(0x02, 0xFF, 21, &data->have_pmt_data, data->pmt_data, sizeof(data->pmt_data), &data->pmt_data_pos, payloadStart, ++ stream_buf+i+offset, packetSize-offset, ParsePMTData, data); ++ continue; ++ } ++ ++ if(data->ecm_pid && pid == data->ecm_pid) ++ { ++#ifdef WITH_EMU ++ stream_server_has_ecm[data->connid] = 1; ++#endif ++ ++ // set to null pid ++ stream_buf[i+1] |= 0x1f; ++ stream_buf[i+2] = 0xff; ++ ++ ParseTSData(0x80, 0xFE, 3, &data->have_ecm_data, data->ecm_data, sizeof(data->ecm_data), &data->ecm_data_pos, payloadStart, ++ stream_buf+i+offset, packetSize-offset, ParseECMData, data); ++ continue; ++ } ++ ++ if(scramblingControl == 0) ++ { continue; } ++ ++ if(!(stream_buf[i+3] & 0x10)) ++ { ++ stream_buf[i+3] &= 0x3F; ++ continue; ++ } ++ ++ oddKeyUsed = scramblingControl == 0xC0 ? 1 : 0; ++ ++#ifdef WITH_EMU ++ if(!stream_server_has_ecm[data->connid]) ++ { ++ keydata = &emu_fixed_key_data[data->connid]; ++ SAFE_MUTEX_LOCK(&emu_fixed_key_data_mutex[data->connid]); ++ data->key.pvu_csa_used = keydata->pvu_csa_used; ++ } ++ else ++ { ++#endif ++ keydata = &data->key; ++#ifdef WITH_EMU ++ } ++#endif ++ ++ if(keydata->pvu_csa_used) ++ { ++ oddeven = scramblingControl; // for detecting odd/even switch ++ ++ if(pid == data->video_pid) // start with video pid, since it is most dominant ++ { ++ csakeyV = keydata->pvu_csa_ks[PVU_CW_VID]; ++ ++ if(csakeyV !=NULL) ++ { ++ cs=0; ++ ce=1; ++ packetClusterV[cs] = stream_buf+i; // set first cluster start ++ packetClusterV[ce] = stream_buf+i+packetSize-1; ++ scrambled_packets=1; ++ ++ for(j = i+packetSize; j < bufLength; j += packetSize) // Now iterate through the rest of the packets and create clusters for batch decryption ++ { ++ tsHeader = b2i(4, stream_buf+j); ++ pid = (tsHeader & 0x1fff00) >> 8; ++ if(pid == data->video_pid) ++ { ++ if(oddeven != (tsHeader & 0xc0)) // changed key so stop adding clusters ++ { ++ break; ++ } ++ if(cs > ce) // First video packet for each cluster ++ { ++ packetClusterV[cs] = stream_buf+j; ++ ce = cs+1; ++ } ++ ++ scrambled_packets++; ++ } ++ else ++ { ++ if(cs < ce) // First non-video packet - need to set end of video cluster ++ { ++ packetClusterV[ce] = stream_buf+j-1; ++ cs = ce+1; ++ } ++ ++ if((tsHeader & 0xc0) == 0) { ++ continue; ++ } ++ ++ if(oddeven != (tsHeader & 0xc0)) // changed key so stop adding clusters ++ { ++ j = bufLength; // to break out of outer loop also ++ break; ++ } ++ ++ for(k = 0; k < data->audio_pid_count; k++) // Check for audio tracks and create single packet clusters ++ { ++ if(pid == data->audio_pids[k]) ++ { ++ packetClusterA[k][csa[k]] = stream_buf+j; ++ csa[k]++; ++ packetClusterA[k][csa[k]] = stream_buf+j+packetSize-1; ++ csa[k]++; ++ scrambled_packetsA[k]++; ++ } ++ } ++ } ++ } ++ ++ if( cs > ce ) // last packet was not a video packet, so set null for end of all clusters ++ { packetClusterV[cs] = NULL; } ++ else ++ { ++ if(scrambled_packets > 1) // last packet was a video packet, so set end of cluster to end of last packet ++ { ++ packetClusterV[ce] = stream_buf+j-1; ++ } ++ packetClusterV[ce+1] = NULL; // add null to end of cluster list ++ } ++ ++ while( j >= cluster_size ) ++ { j = decrypt_packets(csakeyV, packetClusterV); } ++ ++ for(k = 0; k < data->audio_pid_count; k++) ++ { ++ if(scrambled_packetsA[k]) // if audio track has scrambled packets, set null to mark end and decrypt ++ { ++ csakeyA[k] = keydata->pvu_csa_ks[PVU_CW_A1+k]; ++ packetClusterA[k][csa[k]] = NULL; ++ decrypt_packets(csakeyA[k], packetClusterA[k]); ++ csa[k]=0; ++ scrambled_packetsA[k] = 0; ++ } ++ } ++ } ++ } ++ else ++ { ++ for(j = 0; j < data->audio_pid_count; j++) ++ if(pid == data->audio_pids[j]) ++ { csakeyA[0] = keydata->pvu_csa_ks[PVU_CW_A1+j]; } ++ ++ if(csakeyA[0] != NULL) ++ { ++ packetClusterA[0][0] = stream_buf+i; ++ packetClusterA[0][1] = stream_buf+i+packetSize -1; ++ packetClusterA[0][2] = NULL; ++ decrypt_packets(csakeyA[0], packetClusterA[0]); ++ } ++ } ++ } ++ else ++ { ++ deskey = NULL; ++ ++ if(pid == data->video_pid) ++ { deskey = keydata->pvu_des_ks[PVU_CW_VID][oddKeyUsed]; } ++ else ++ { ++ for(j = 0; j < data->audio_pid_count; j++) ++ if(pid == data->audio_pids[j]) ++ { deskey = keydata->pvu_des_ks[PVU_CW_A1+j][oddKeyUsed]; } ++ } ++ ++ if(deskey == NULL) ++ { ++ deskey = keydata->pvu_des_ks[PVU_CW_HSD][oddKeyUsed]; ++ } ++ ++ for(j = offset; j+7 < 188; j += 8) ++ { ++ pdata = stream_buf+i+j; ++ des(pdata, deskey, 0); ++ } ++ ++ stream_buf[i+3] &= 0x3F; ++ } ++ ++#ifdef WITH_EMU ++ if(!stream_server_has_ecm[data->connid]) ++ { ++ SAFE_MUTEX_UNLOCK(&emu_fixed_key_data_mutex[data->connid]); ++ } ++#endif ++ } ++} ++ ++static int32_t connect_to_stream(char *http_buf, int32_t http_buf_len, char *stream_path) ++{ ++ struct sockaddr_in cservaddr; ++ IN_ADDR_T in_addr; ++ ++ int32_t streamfd = socket(AF_INET, SOCK_STREAM, 0); ++ if(streamfd == -1) ++ { return -1; } ++ ++ struct timeval tv; ++ tv.tv_sec = 2; ++ tv.tv_usec = 0; ++ if(setsockopt(streamfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv)) ++ { ++ cs_log("ERROR: setsockopt() failed for SO_RCVTIMEO"); ++ return -1; ++ } ++ ++ bzero(&cservaddr, sizeof(cservaddr)); ++ cservaddr.sin_family = AF_INET; ++ cs_resolve(emu_stream_source_host, &in_addr, NULL, NULL); ++ SIN_GET_ADDR(cservaddr) = in_addr; ++ cservaddr.sin_port = htons(emu_stream_source_port); ++ ++ if(connect(streamfd, (struct sockaddr *)&cservaddr, sizeof(cservaddr)) == -1) ++ { return -1; } ++ if(emu_stream_source_auth) ++ { ++ snprintf(http_buf, http_buf_len, "GET %s HTTP/1.1\nHost: %s:%u\n" ++ "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0\n" ++ "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n" ++ "Accept-Language: en-US\n" ++ "Authorization: Basic %s\n" ++ "Connection: keep-alive\n\n", stream_path, emu_stream_source_host, emu_stream_source_port, emu_stream_source_auth); ++ } ++ else ++ { ++ snprintf(http_buf, http_buf_len, "GET %s HTTP/1.1\nHost: %s:%u\n" ++ "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0\n" ++ "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n" ++ "Accept-Language: en-US\n" ++ "Connection: keep-alive\n\n", stream_path, emu_stream_source_host, emu_stream_source_port); ++ } ++ ++ if(send(streamfd, http_buf, strlen(http_buf), 0) == -1) ++ { return -1; } ++ ++ return streamfd; ++} ++ ++static void stream_client_disconnect(emu_stream_client_conn_data *conndata) ++{ ++ int32_t i; ++ ++#ifdef WITH_EMU ++ SAFE_MUTEX_LOCK(&emu_fixed_key_srvid_mutex); ++ emu_stream_cur_srvid[conndata->connid] = NO_SRVID_VALUE; ++ stream_server_has_ecm[conndata->connid] = 0; ++ SAFE_MUTEX_UNLOCK(&emu_fixed_key_srvid_mutex); ++#endif ++ ++ SAFE_MUTEX_LOCK(&emu_stream_server_mutex); ++ for(i=0; iconnfd) ++ { ++ gconnfd[i] = -1; ++ gconncount--; ++ } ++ } ++ SAFE_MUTEX_UNLOCK(&emu_stream_server_mutex); ++ ++ shutdown(conndata->connfd, 2); ++ close(conndata->connfd); ++ ++ cs_log("Stream client %i disconnected",conndata->connid); ++ ++ NULLFREE(conndata); ++} ++ ++static void *stream_client_handler(void *arg) ++{ ++#define EMU_DVB_MAX_TS_PACKETS 278 ++#define EMU_DVB_BUFFER_SIZE_CSA 188*EMU_DVB_MAX_TS_PACKETS ++#define EMU_DVB_BUFFER_WAIT_CSA 188*(EMU_DVB_MAX_TS_PACKETS-128) ++#define EMU_DVB_BUFFER_SIZE_DES 188*32 ++#define EMU_DVB_BUFFER_WAIT_DES 188*29 ++#define EMU_DVB_BUFFER_SIZE EMU_DVB_BUFFER_SIZE_CSA ++ ++ emu_stream_client_conn_data *conndata = (emu_stream_client_conn_data *)arg; ++ char *http_buf, stream_path[255], stream_path_copy[255]; ++ int32_t streamfd; ++ int32_t clientStatus, streamStatus; ++ uint8_t *stream_buf; ++ uint16_t packetCount = 0, packetSize = 0, startOffset = 0; ++ uint32_t remainingDataPos, remainingDataLength; ++ int32_t cur_dvb_buffer_size, cur_dvb_buffer_wait; ++ int32_t bytesRead = 0; ++ emu_stream_client_data *data; ++ int8_t streamConnectErrorCount = 0; ++ int8_t streamDataErrorCount = 0; ++ int32_t i, srvidtmp; ++ char *saveptr, *token; ++ char http_version[4]; ++ int32_t http_status_code = 0; ++ ++ cs_log("Stream client %i connected", conndata->connid); ++ ++ if(!cs_malloc(&http_buf, 1024)) ++ { ++ stream_client_disconnect(conndata); ++ return NULL; ++ } ++ ++ if(!cs_malloc(&stream_buf, EMU_DVB_BUFFER_SIZE)) ++ { ++ NULLFREE(http_buf); ++ stream_client_disconnect(conndata); ++ return NULL; ++ } ++ ++ if(!cs_malloc(&data, sizeof(emu_stream_client_data))) ++ { ++ NULLFREE(http_buf); ++ NULLFREE(stream_buf); ++ stream_client_disconnect(conndata); ++ return NULL; ++ } ++ ++ clientStatus = recv(conndata->connfd, http_buf, 1024, 0); ++ if(clientStatus < 1) ++ { ++ NULLFREE(http_buf); ++ NULLFREE(stream_buf); ++ NULLFREE(data); ++ stream_client_disconnect(conndata); ++ return NULL; ++ } ++ ++ http_buf[1023] = '\0'; ++ if(sscanf(http_buf, "GET %254s ", stream_path) < 1) ++ { ++ NULLFREE(http_buf); ++ NULLFREE(stream_buf); ++ NULLFREE(data); ++ stream_client_disconnect(conndata); ++ return NULL; ++ } ++ ++ cs_strncpy(stream_path_copy, stream_path, sizeof(stream_path)); ++ ++ token = strtok_r(stream_path_copy, ":", &saveptr); ++ ++ for(i=0; token != NULL && i<3; i++) ++ { ++ token = strtok_r(NULL, ":", &saveptr); ++ if(token == NULL) ++ { break; } ++ } ++ if(token != NULL) ++ { ++ if(sscanf(token, "%x", &srvidtmp) < 1) ++ { ++ token = NULL; ++ } ++ else ++ { ++ data->srvid = srvidtmp & 0xFFFF; ++ } ++ } ++ ++ if(token == NULL) ++ { ++ NULLFREE(http_buf); ++ NULLFREE(stream_buf); ++ NULLFREE(data); ++ stream_client_disconnect(conndata); ++ return NULL; ++ } ++ ++#ifdef WITH_EMU ++ SAFE_MUTEX_LOCK(&emu_fixed_key_srvid_mutex); ++ emu_stream_cur_srvid[conndata->connid] = data->srvid; ++ stream_server_has_ecm[conndata->connid] = 0; ++ SAFE_MUTEX_UNLOCK(&emu_fixed_key_srvid_mutex); ++#endif ++ ++ cs_log("Stream client %i request %s", conndata->connid, stream_path); ++ ++ snprintf(http_buf, 1024, "HTTP/1.0 200 OK\nConnection: Close\nContent-Type: video/mpeg\nServer: stream_enigma2\n\n"); ++ clientStatus = send(conndata->connfd, http_buf, strlen(http_buf), 0); ++ ++ data->connid = conndata->connid; ++ ++ while(!exit_oscam && clientStatus != -1 && streamConnectErrorCount < 3 && streamDataErrorCount < 15) ++ { ++ streamfd = connect_to_stream(http_buf, 1024, stream_path); ++ if(streamfd == -1) ++ { ++ cs_log("WARNING: stream client %i cannot connect to stream source", conndata->connid); ++ streamConnectErrorCount++; ++ cs_sleepms(500); ++ continue; ++ } ++ ++ streamStatus = 0; ++ bytesRead = 0; ++ ++ while(!exit_oscam && clientStatus != -1 && streamStatus != -1 && streamConnectErrorCount < 3 && streamDataErrorCount < 15) ++ { ++ if(data->key.pvu_csa_used) ++ { ++ cur_dvb_buffer_size = EMU_DVB_BUFFER_SIZE_CSA; ++ cur_dvb_buffer_wait = EMU_DVB_BUFFER_WAIT_CSA; ++ } ++ else ++ { ++ cur_dvb_buffer_size = EMU_DVB_BUFFER_SIZE_DES; ++ cur_dvb_buffer_wait = EMU_DVB_BUFFER_WAIT_DES; ++ } ++ ++ streamStatus = recv(streamfd, stream_buf+bytesRead, cur_dvb_buffer_size-bytesRead, MSG_WAITALL); ++ if(streamStatus == 0) // socket closed ++ { ++ cs_log("WARNING: stream client %i - stream source closed connection", conndata->connid); ++ streamConnectErrorCount++; ++ cs_sleepms(100); ++ break; ++ } ++ ++ if(streamStatus < 0) // error ++ { ++ if ((errno == EWOULDBLOCK) | (errno == EAGAIN)) { ++ cs_log("WARNING: stream client %i no data from stream source", conndata->connid); ++ streamDataErrorCount++; // 2 sec timeout * 15 = 30 seconds no data -> close ++ cs_sleepms(100); ++ continue; ++ } ++ ++ cs_log("WARNING: stream client %i error receiving data from stream source", conndata->connid); ++ streamConnectErrorCount++; ++ cs_sleepms(100); ++ break; ++ } ++ ++ if(streamStatus < cur_dvb_buffer_size-bytesRead) // probably just received header but no stream ++ { ++ if(!bytesRead && streamStatus > 13 && ++ sscanf((const char*)stream_buf, "HTTP/%3s %d ", http_version , &http_status_code) == 2 && ++ http_status_code != 200) ++ { ++ cs_log("ERROR: stream client %i got %d response from stream source", conndata->connid, http_status_code); ++ streamConnectErrorCount++; ++ cs_sleepms(100); ++ break; ++ } ++ else ++ { ++ cs_log_dbg(0, "WARNING: stream client %i non-full buffer from stream source", conndata->connid); ++ streamDataErrorCount++; ++ cs_sleepms(100); ++ } ++ } ++ else ++ { ++ streamDataErrorCount = 0; ++ } ++ ++ streamConnectErrorCount = 0; ++ bytesRead += streamStatus; ++ ++ if(bytesRead >= cur_dvb_buffer_wait) ++ { ++ startOffset = 0; ++ if(stream_buf[0] != 0x47 || packetSize == 0) // only search if not starting on ts packet or unknown packet size ++ { ++ SearchTsPackets(stream_buf, bytesRead, &packetSize, &startOffset); ++ } ++ if(packetSize == 0) ++ { ++ bytesRead = 0; ++ } ++ else ++ { ++ packetCount = ((bytesRead-startOffset) / packetSize); ++ ++ ParseTSPackets(data, stream_buf+startOffset, packetCount*packetSize, packetSize); ++ ++ clientStatus = send(conndata->connfd, stream_buf+startOffset, packetCount*packetSize, 0); ++ ++ remainingDataPos = startOffset+(packetCount*packetSize); ++ remainingDataLength = bytesRead-remainingDataPos; ++ ++ if(remainingDataPos < remainingDataLength) ++ { memmove(stream_buf, stream_buf+remainingDataPos, remainingDataLength); } ++ else ++ { memcpy(stream_buf, stream_buf+remainingDataPos, remainingDataLength); } ++ ++ bytesRead = remainingDataLength; ++ } ++ } ++ } ++ ++ close(streamfd); ++ } ++ ++ NULLFREE(http_buf); ++ NULLFREE(stream_buf); ++ for(i=0; i<8; i++) ++ { ++ if(data->key.pvu_csa_ks[i]) ++ { free_key_struct(data->key.pvu_csa_ks[i]); } ++ } ++ NULLFREE(data); ++ ++ stream_client_disconnect(conndata); ++ return NULL; ++} ++ ++void *stream_server(void *UNUSED(a)) ++{ ++ struct sockaddr_in servaddr, cliaddr; ++ socklen_t clilen; ++ int32_t connfd, reuse = 1, i; ++ int8_t connaccepted; ++ emu_stream_client_conn_data *conndata; ++ ++ cluster_size = get_internal_parallelism(); ++ cs_log("INFO: FFDecsa parallel mode = %d", cluster_size); ++ ++ if(!emu_stream_server_mutex_init) ++ { ++ SAFE_MUTEX_INIT(&emu_stream_server_mutex, NULL); ++ emu_stream_server_mutex_init = 1; ++ } ++ ++#ifdef WITH_EMU ++ SAFE_MUTEX_LOCK(&emu_fixed_key_srvid_mutex); ++ for(i=0; iconnfd = connfd; ++ conndata->connid = i; ++ ++ break; ++ } ++ } ++ } ++ SAFE_MUTEX_UNLOCK(&emu_stream_server_mutex); ++ } ++ ++ if(connaccepted) ++ { ++ int on = 1; ++ if(setsockopt(connfd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) ++ { ++ cs_log("ERROR: stream client %i setsockopt() failed for TCP_NODELAY", conndata->connid); ++ } ++ ++ start_thread("emu stream client", stream_client_handler, (void*)conndata, NULL, 1, 0); ++ } ++ else ++ { ++ shutdown(connfd, 2); ++ close(connfd); ++ cs_log("ERROR: stream server client dropped because of too many connections (%i)", EMU_STREAM_SERVER_MAX_CONNECTIONS); ++ } ++ ++ cs_sleepms(20); ++ } ++ ++ close(glistenfd); ++ ++ return NULL; ++} ++ ++#ifdef WITH_EMU ++void *stream_key_delayer(void *UNUSED(arg)) ++{ ++ int32_t i, j; ++ emu_stream_client_key_data* cdata; ++ LL_ITER it; ++ emu_stream_cw_item *item; ++ struct timeb t_now; ++ ++ while(!exit_oscam) ++ { ++ cs_ftime(&t_now); ++ ++ for(i=0; iwrite_time) < 0) ++ { ++ break; ++ } ++ ++ SAFE_MUTEX_LOCK(&emu_fixed_key_data_mutex[i]); ++ ++ cdata = &emu_fixed_key_data[i]; ++ ++ for(j=0; j<8; j++) ++ { ++ if(item->csa_used) ++ { ++ if(cdata->pvu_csa_ks[j] == NULL) ++ { cdata->pvu_csa_ks[j] = get_key_struct(); } ++ ++ if(item->is_even) ++ { set_even_control_word(cdata->pvu_csa_ks[j], item->cw[j]); } ++ else ++ { set_odd_control_word(cdata->pvu_csa_ks[j], item->cw[j]); } ++ ++ cdata->pvu_csa_used = 1; ++ } ++ else ++ { ++ if(item->is_even) ++ { des_set_key(item->cw[j], cdata->pvu_des_ks[j][0]); } ++ else ++ { des_set_key(item->cw[j], cdata->pvu_des_ks[j][1]); } ++ ++ cdata->pvu_csa_used = 0; ++ } ++ } ++ ++ SAFE_MUTEX_UNLOCK(&emu_fixed_key_data_mutex[i]); ++ ++ ll_iter_remove_data(&it); ++ } ++ } ++ ++ cs_sleepms(25); ++ } ++ ++ return NULL; ++} ++#endif ++ ++void stop_stream_server(void) ++{ ++ int32_t i; ++ ++ SAFE_MUTEX_LOCK(&emu_stream_server_mutex); ++ for(i=0; ityp == R_EMU) ++ { ++ usr_filter = * get_emu_prids_for_caid(aureader, cfg.ncd_ptab.ports[cl->port_idx].ncd->ncd_ftab.filts[0].caid); ++ } ++ else ++#endif + mk_user_au_ftab(aureader, &usr_filter); + } + +@@ -948,6 +955,13 @@ static int8_t newcamd_auth_client(IN_ADD + else + { memset(&mbuf[8], 0, 6); } //mbuf[8] - mbuf[13] + ++#ifdef WITH_EMU ++ if(aureader && aureader->typ == R_EMU && caid_is_dre(pufilt->caid)) ++ { ++ mbuf[10] = aureader->dre36_force_group; ++ } ++#endif ++ + mbuf[14] = pufilt->nprids; + for(j = 0; j < pufilt->nprids; j++) + { +@@ -973,7 +987,7 @@ static int8_t newcamd_auth_client(IN_ADD + int32_t k, found; + uint32_t rprid; + found = 0; +- if(pufilt->caid == aureader->caid) ++ if(pufilt->caid == aureader->caid && aureader->typ != R_EMU) + { + for(k = 0; (k < aureader->nprov); k++) + { +@@ -999,6 +1013,32 @@ static int8_t newcamd_auth_client(IN_ADD + } + } + } ++#ifdef WITH_EMU ++ else if(aureader->typ == R_EMU) ++ { ++ if(caid_is_dre(pufilt->caid)) ++ { ++ found = 1; ++ memset(&mbuf[22 + 11 * j] ,0 ,4); ++ switch((uchar)(pufilt->prids[j])) ++ { ++ case 0x11: ++ mbuf[22 + 11 * j] = aureader->dre36_force_group; ++ break; ++ case 0x14: ++ mbuf[22 + 11 * j] = aureader->dre56_force_group; ++ break; ++ case 0xfe: ++ mbuf[22 + 11 * j] = 0xED; ++ mbuf[25 + 11 * j] = 0x02; ++ break; ++ default: ++ found = 0; ++ } ++ } ++ } ++#endif ++ + if(!found) + { + mbuf[22 + 11 * j] = 0x00; +diff -ruNp trunk.patches/module-newcamd-des.c trunk/module-newcamd-des.c +--- trunk.patches/module-newcamd-des.c 2018-04-03 02:44:10.106269046 +0300 ++++ trunk/module-newcamd-des.c 2018-04-03 03:20:07.662045399 +0300 +@@ -5,10 +5,7 @@ + #define DES_IP 1 + #define DES_IP_1 2 + #define DES_RIGHT 4 +-#define DES_HASH 8 + +-#define DES_ECM_CRYPT 0 +-#define DES_ECM_HASH DES_HASH + #define DES_ECS2_DECRYPT (DES_IP | DES_IP_1 | DES_RIGHT) + #define DES_ECS2_CRYPT (DES_IP | DES_IP_1) + +@@ -356,7 +353,7 @@ static void desRound(unsigned char left[ + swap(data - 4, data); + } + +-static void nc_des(unsigned char key[], unsigned char mode, unsigned char data[]) ++void nc_des(unsigned char key[], unsigned char mode, unsigned char data[]) + { + unsigned char i; + unsigned char left[8]; +diff -ruNp trunk.patches/module-newcamd-des.h trunk/module-newcamd-des.h +--- trunk.patches/module-newcamd-des.h 2018-04-03 02:44:10.214269951 +0300 ++++ trunk/module-newcamd-des.h 2018-04-03 03:20:07.662045399 +0300 +@@ -1,8 +1,15 @@ + #ifndef MODULE_NEWCAMD_DES_H_ + #define MODULE_NEWCAMD_DES_H_ + ++#define DES_HASH 8 ++ ++#define DES_ECM_CRYPT 0 ++#define DES_ECM_HASH DES_HASH ++ + int nc_des_encrypt(unsigned char *buffer, int len, unsigned char *deskey); + int nc_des_decrypt(unsigned char *buffer, int len, unsigned char *deskey); + unsigned char *nc_des_login_key_get(unsigned char *key1, unsigned char *key2, int len, unsigned char *des16); + ++ void nc_des(unsigned char key[], unsigned char mode, unsigned char data[]); ++ + #endif +diff -ruNp trunk.patches/module-stat.c trunk/module-stat.c +--- trunk.patches/module-stat.c 2018-04-03 02:44:09.474263747 +0300 ++++ trunk/module-stat.c 2018-04-03 03:20:07.662045399 +0300 +@@ -903,7 +903,7 @@ void check_lb_auto_betatunnel_mode(ECM_R + + uint16_t get_rdr_caid(struct s_reader *rdr) + { +- if(is_network_reader(rdr)) ++ if(is_network_reader(rdr) || rdr->typ == R_EMU) + { + return 0; //reader caid is not real caid + } +@@ -1301,7 +1301,7 @@ void stat_get_best_reader(ECM_REQUEST *e + for(ea = er->matching_rdr; ea; ea = ea->next) + { + rdr = ea->reader; +- if(is_network_reader(rdr)) //reader caid is not real caid ++ if(is_network_reader(rdr) || rdr->typ == R_EMU) //reader caid is not real caid + { + prv = ea; + continue; // proxy can convert or reject +diff -ruNp trunk.patches/module-webif.c trunk/module-webif.c +--- trunk.patches/module-webif.c 2018-04-03 02:44:08.458255227 +0300 ++++ trunk/module-webif.c 2018-04-03 03:20:07.662045399 +0300 +@@ -101,6 +101,7 @@ static bool use_srvid2 = false; + #define MNU_CFG_LCD 14 + #define MNU_CFG_MONITOR 15 + #define MNU_CFG_WEBIF 16 ++#define MNU_CFG_STREAMRELAY 17 + + /* constants for files.html submenuactivating */ + #define MNU_CFG_FVERSION 0 +@@ -134,8 +135,9 @@ static bool use_srvid2 = false; + #define MNU_GBX_FSTAINF 27 + #define MNU_GBX_FEXPINF 28 + #define MNU_GBX_INFOLOG 29 ++#define MNU_CFG_FSOFTCAMKEY 30 + +-#define MNU_CFG_TOTAL_ITEMS 30 // sum of items above. Use it for "All inactive" in function calls too. ++#define MNU_CFG_TOTAL_ITEMS 31 // sum of config or files items above. Use it for "All inactive" in function calls too. + + static void set_status_info_var(struct templatevars *vars, char *varname, int no_data, char *fmt, double value) { + if (no_data) +@@ -1219,6 +1221,34 @@ static char *send_oscam_config_scam(stru + } + #endif + ++#ifdef WITH_EMU ++#include "module-emulator-stream.h" ++ ++static char *send_oscam_config_streamrelay(struct templatevars *vars, struct uriparams *params) ++{ ++ setActiveSubMenu(vars, MNU_CFG_STREAMRELAY); ++ ++ webif_save_config("streamrelay", vars, params); ++ ++ tpl_printf(vars, TPLADD, "STREAM_SOURCE_HOST", "%s", cfg.emu_stream_source_host); ++ tpl_printf(vars, TPLADD, "STREAM_SOURCE_PORT", "%d", cfg.emu_stream_source_port); ++ if(cfg.emu_stream_source_auth_user) ++ { tpl_printf(vars, TPLADD, "STREAM_SOURCE_AUTH_USER", "%s", cfg.emu_stream_source_auth_user); } ++ if(cfg.emu_stream_source_auth_password) ++ { tpl_printf(vars, TPLADD, "STREAM_SOURCE_AUTH_PASSWORD", "%s", cfg.emu_stream_source_auth_password); } ++ tpl_printf(vars, TPLADD, "STREAM_RELAY_PORT", "%d", cfg.emu_stream_relay_port); ++ tpl_printf(vars, TPLADD, "STREAM_ECM_DELAY", "%d", cfg.emu_stream_ecm_delay); ++ ++ tpl_printf(vars, TPLADD, "TMP", "STREAMRELAYENABLEDSELECTED%d", cfg.emu_stream_relay_enabled); ++ tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected"); ++ ++ tpl_printf(vars, TPLADD, "TMP", "STREAMEMMENABLEDSELECTED%d", cfg.emu_stream_emm_enabled); ++ tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected"); ++ ++ return tpl_getTpl(vars, "CONFIGSTREAMRELAY"); ++} ++#endif ++ + #ifdef MODULE_CCCAM + static char *send_oscam_config_cccam(struct templatevars *vars, struct uriparams *params) + { +@@ -1557,6 +1587,10 @@ static char *send_oscam_config_dvbapi(st + tpl_printf(vars, TPLADD, "TMP", "EXTENDEDCWAPISELECTED%d", cfg.dvbapi_extended_cw_api); + tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected"); + ++ //extended_cw_pids (pid limiter) ++ tpl_printf(vars, TPLADD, "TMP", "EXTENDEDCWPIDSSELECTED%d", cfg.dvbapi_extended_cw_pids); ++ tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected"); ++ + //write_sdt_prov + if(cfg.dvbapi_write_sdt_prov > 0) + { tpl_addVar(vars, TPLADD, "WRITESDTPROVCHECKED", "checked"); } +@@ -1634,6 +1668,9 @@ static char *send_oscam_config(struct te + #ifdef MODULE_SCAM + else if(!strcmp(part, "scam")) { return send_oscam_config_scam(vars, params); } + #endif ++#ifdef WITH_EMU ++ else if(!strcmp(part, "streamrelay")) { return send_oscam_config_streamrelay(vars, params); } ++#endif + #ifdef MODULE_CCCAM + else if(!strcmp(part, "cccam")) { return send_oscam_config_cccam(vars, params); } + #endif +@@ -2096,7 +2133,7 @@ static char *send_oscam_reader_config(st + chk_reader("services", servicelabels, rdr); + chk_reader("lb_whitelist_services", servicelabelslb, rdr); + +- if(is_network_reader(rdr)) //physical readers make trouble if re-started ++ if(is_network_reader(rdr) || rdr->typ == R_EMU) //physical readers make trouble if re-started + { + restart_cardreader(rdr, 1); + } +@@ -2674,6 +2711,31 @@ static char *send_oscam_reader_config(st + tpl_addVar(vars, TPLADD, "USERSCRIPT", rdr->userscript); + #endif + ++#ifdef WITH_EMU ++ //emu_auproviders ++ value = mk_t_ftab(&rdr->emu_auproviders); ++ tpl_addVar(vars, TPLADD, "EMUAUPROVIDERS", value); ++ free_mk_t(value); ++ ++ // Date-coded BISS keys ++ if(!apicall) ++ { ++ tpl_addVar(vars, TPLADD, "EMUDATECODEDENABLED", (rdr->emu_datecodedenabled == 1) ? "checked" : ""); ++ } ++ else ++ { ++ tpl_addVar(vars, TPLADD, "EMUDATECODEDENABLED", (rdr->emu_datecodedenabled == 1) ? "1" : "0"); ++ } ++ ++ //extee ++ tpl_addVar(vars, TPLADD, "EXTEE36", rdr->extee36); ++ tpl_addVar(vars, TPLADD, "EXTEE56", rdr->extee56); ++ ++ //dre force group ++ tpl_printf(vars, TPLADD, "DRE36FORCEGROUP","%02X", rdr->dre36_force_group); ++ tpl_printf(vars, TPLADD, "DRE56FORCEGROUP","%02X", rdr->dre56_force_group); ++#endif ++ + tpl_addVar(vars, TPLADD, "PROTOCOL", reader_get_type_desc(rdr, 0)); + + // Show only parameters which needed for the reader +@@ -2695,6 +2757,9 @@ static char *send_oscam_reader_config(st + case R_CAMD35 : + tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGCAMD35BIT")); + break; ++ case R_EMU : ++ tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGEMUBIT")); ++ break; + case R_CS378X : + tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGCS378XBIT")); + break; +@@ -4417,9 +4482,38 @@ static char *send_oscam_entitlement(stru + + tpl_addVar(vars, TPLAPPEND, "LOGHISTORY", "

New Structure:
"); + char tbuffer[83]; ++#ifdef WITH_EMU ++ char keyBuffer[1024]; ++#endif + int jsondelimiter = 0; + while((item = ll_iter_next(&itr))) + { ++#ifdef WITH_EMU ++ if(item->isKey) { ++ tpl_addVar(vars, TPLADD, "ENTSTARTDATE", ""); ++ tpl_addVar(vars, TPLADD, "ENTENDDATE", ""); ++ cs_hexdump(0, item->key, item->keyLength, keyBuffer, sizeof(keyBuffer)); ++ tpl_addVar(vars, TPLADD, "ENTEXPIERED", "e_valid"); ++ tpl_printf(vars, TPLADD, "ENTCAID", "%04X", item->caid); ++ if(item->caid == 0x2600) { ++ tpl_printf(vars, TPLADD, "ENTPROVID", "%08X", item->provid); ++ } ++ else { ++ tpl_printf(vars, TPLADD, "ENTPROVID", "%06X", item->provid); ++ } ++ tpl_addVar(vars, TPLADD, "ENTID", item->name); ++ tpl_addVar(vars, TPLADD, "ENTCLASS", keyBuffer); ++ if(item->isData) { tpl_addVar(vars, TPLADD, "ENTTYPE", "data"); } ++ else { tpl_addVar(vars, TPLADD, "ENTTYPE", "key"); } ++ tpl_addVar(vars, TPLADD, "ENTRESNAME", ""); ++ ++ if((strcmp(getParam(params, "hideexpired"), "1") != 0) || (item->end > now)) ++ { tpl_addVar(vars, TPLAPPEND, "READERENTENTRY", tpl_getTpl(vars, "ENTITLEMENTITEMBIT")); } ++ ++ continue; ++ } ++#endif ++ + localtime_r(&item->start, &start_t); + localtime_r(&item->end, &end_t); + +@@ -4895,6 +4989,9 @@ static char *send_oscam_status(struct te + #else + filtered = (type == cl->typ); + #endif ++#ifdef WITH_EMU ++ if(type == 'e' && cl->typ == 'r' && cl->reader->typ == R_EMU) filtered = 1; ++#endif + } + } + +@@ -6339,6 +6436,9 @@ static char *send_oscam_files(struct tem + { "expired.info", MNU_GBX_FEXPINF, FTYPE_GBOX }, // id 28 + { "info.log", MNU_GBX_INFOLOG, FTYPE_GBOX }, // id 29 + #endif ++#ifdef WITH_EMU ++ { "SoftCam.Key", MNU_CFG_FSOFTCAMKEY,FTYPE_CONFIG }, // id 30 ++#endif + { NULL, 0, 0 }, + }; + +@@ -6809,7 +6909,7 @@ static char *send_oscam_EMM_running(stru + else if(!proxy && rdr->csystem_active) // local active reader + { + csystem = rdr->csystem; +- caid = rdr->caid; ++ if(rdr->typ != R_EMU) caid = rdr->caid; + } + + if(csystem) +@@ -7816,8 +7916,8 @@ static int32_t readRequest(FILE * f, IN_ + memcpy(*result + bufsize, buf2, n); + bufsize += n; + +- //max request size 100kb +- if(bufsize > 102400) ++ //max request size 200kb ++ if(bufsize > 204800) + { + cs_log("error: too much data received from %s", cs_inet_ntoa(in)); + NULLFREE(*result); +diff -ruNp trunk.patches/module-webif-tpl.c trunk/module-webif-tpl.c +--- trunk.patches/module-webif-tpl.c 2018-04-03 02:44:09.754266095 +0300 ++++ trunk/module-webif-tpl.c 2018-04-03 03:20:07.662045399 +0300 +@@ -457,6 +457,7 @@ char *tpl_getUnparsedTpl(const char *nam + check_conf(WITH_SSL, ptr2); + check_conf(WITH_STAPI, ptr2); + check_conf(WITH_STAPI5, ptr2); ++ check_conf(WITH_EMU, ptr2); + } // for + if(ok == 0) + { +diff -ruNp trunk.patches/oscam-aes.c trunk/oscam-aes.c +--- trunk.patches/oscam-aes.c 2018-04-03 02:44:10.106269046 +0300 ++++ trunk/oscam-aes.c 2018-04-03 03:20:07.662045399 +0300 +@@ -37,6 +37,16 @@ void aes_encrypt_idx(struct aes_keys *ae + } + } + ++void aes_cbc_encrypt(struct aes_keys *aes, uchar *buf, int32_t n, uchar *iv) ++{ ++ AES_cbc_encrypt(buf, buf, n, &aes->aeskey_encrypt, iv, AES_ENCRYPT); ++} ++ ++void aes_cbc_decrypt(struct aes_keys *aes, uchar *buf, int32_t n, uchar *iv) ++{ ++ AES_cbc_encrypt(buf, buf, n, &aes->aeskey_decrypt, iv, AES_DECRYPT); ++} ++ + /* Creates an AES_ENTRY and adds it to the given linked list. */ + void add_aes_entry(AES_ENTRY **list, uint16_t caid, uint32_t ident, int32_t keyid, uchar *aesKey) + { +diff -ruNp trunk.patches/oscam-aes.h trunk/oscam-aes.h +--- trunk.patches/oscam-aes.h 2018-04-03 02:44:10.110269080 +0300 ++++ trunk/oscam-aes.h 2018-04-03 03:20:07.662045399 +0300 +@@ -5,6 +5,8 @@ void aes_set_key(struct aes_keys *aes, c + bool aes_set_key_alloc(struct aes_keys **aes, char *key); + void aes_decrypt(struct aes_keys *aes, uchar *buf, int32_t n); + void aes_encrypt_idx(struct aes_keys *aes, uchar *buf, int32_t n); ++void aes_cbc_encrypt(struct aes_keys *aes, uchar *buf, int32_t n, uchar *iv); ++void aes_cbc_decrypt(struct aes_keys *aes, uchar *buf, int32_t n, uchar *iv); + + void add_aes_entry(AES_ENTRY **list, uint16_t caid, uint32_t ident, int32_t keyid, uchar *aesKey); + void parse_aes_entry(AES_ENTRY **list, char *label, char *value); +diff -ruNp trunk.patches/oscam.c trunk/oscam.c +--- trunk.patches/oscam.c 2018-04-03 03:10:28.813703490 +0300 ++++ trunk/oscam.c 2018-04-03 03:20:07.662045399 +0300 +@@ -41,6 +41,11 @@ + #include "reader-common.h" + #include "module-gbox.h" + ++#ifdef WITH_EMU ++ void add_emu_reader(void); ++ void stop_stream_server(void); ++#endif ++ + #ifdef WITH_SSL + #include + #include +@@ -422,6 +427,7 @@ static void write_versionfile(bool use_s + write_conf(CW_CYCLE_CHECK, "CW Cycle Check support"); + write_conf(LCDSUPPORT, "LCD support"); + write_conf(LEDSUPPORT, "LED support"); ++ write_conf(WITH_EMU, "Emulator support"); + switch (cs_getclocktype()) { + case CLOCK_TYPE_UNKNOWN : write_conf(CLOCKFIX, "Clockfix with UNKNOWN clock"); break; + case CLOCK_TYPE_REALTIME : write_conf(CLOCKFIX, "Clockfix with realtime clock"); break; +@@ -1640,6 +1646,9 @@ const struct s_cardreader *cardreaders[] + #ifdef CARDREADER_STINGER + &cardreader_stinger, + #endif ++#ifdef WITH_EMU ++ &cardreader_emu, ++#endif + NULL + }; + +@@ -1811,6 +1820,9 @@ int32_t main(int32_t argc, char *argv[]) + + init_sidtab(); + init_readerdb(); ++#ifdef WITH_EMU ++ add_emu_reader(); ++#endif + cfg.account = init_userdb(); + init_signal(); + init_provid(); +@@ -1898,6 +1910,9 @@ int32_t main(int32_t argc, char *argv[]) + if(!cfg.gsms_dis) + { stop_sms_sender(); } + #endif ++#ifdef WITH_EMU ++ stop_stream_server(); ++#endif + webif_close(); + azbox_close(); + coolapi_close_all(); +diff -ruNp trunk.patches/oscam-chk.c trunk/oscam-chk.c +--- trunk.patches/oscam-chk.c 2018-04-03 02:44:09.470263713 +0300 ++++ trunk/oscam-chk.c 2018-04-03 03:20:07.662045399 +0300 +@@ -758,7 +758,7 @@ int32_t matching_reader(ECM_REQUEST *er, + return 0; + } + +- if(!is_network_reader(rdr) && ((rdr->caid >> 8) != ((er->caid >> 8) & 0xFF) && (rdr->caid >> 8) != ((er->ocaid >> 8) & 0xFF))) ++ if(!(rdr->typ == R_EMU) && !is_network_reader(rdr) && ((rdr->caid >> 8) != ((er->caid >> 8) & 0xFF) && (rdr->caid >> 8) != ((er->ocaid >> 8) & 0xFF))) + { + if (!rdr->csystem) + return 0; +@@ -794,7 +794,7 @@ int32_t matching_reader(ECM_REQUEST *er, + } + + //Checking ident: +- if(!chk_rfilter(er, rdr)) ++ if(!(rdr->typ == R_EMU && (er->caid>>8 == 0x26 || er->caid == 0xFFFF)) && !chk_rfilter(er, rdr)) + { + cs_log_dbg(D_TRACE, "r-filter reader %s", rdr->label); + return (0); +@@ -853,7 +853,7 @@ int32_t matching_reader(ECM_REQUEST *er, + } + + //Checking entitlements: +- if(ll_count(rdr->ll_entitlements) > 0) ++ if(ll_count(rdr->ll_entitlements) > 0 && !(rdr->typ == R_EMU)) + { + LL_ITER itr = ll_iter_create(rdr->ll_entitlements); + S_ENTITLEMENT *item; +@@ -1024,7 +1024,7 @@ int32_t chk_caid(uint16_t caid, CAIDTAB + + int32_t chk_caid_rdr(struct s_reader *rdr, uint16_t caid) + { +- if(is_network_reader(rdr)) ++ if(is_network_reader(rdr) || rdr->typ == R_EMU) + { + return 1; //reader caid is not real caid + } +diff -ruNp trunk.patches/oscam-config-global.c trunk/oscam-config-global.c +--- trunk.patches/oscam-config-global.c 2018-04-03 02:44:08.394254690 +0300 ++++ trunk/oscam-config-global.c 2018-04-03 03:20:07.662045399 +0300 +@@ -854,6 +854,30 @@ static const struct config_list scam_opt + #else + static const struct config_list scam_opts[] = { DEF_LAST_OPT }; + #endif ++ ++#ifdef WITH_EMU ++static bool streamrelay_should_save_fn(void *UNUSED(var)) ++{ ++ return 1; ++} ++static const struct config_list streamrelay_opts[] = ++{ ++ DEF_OPT_SAVE_FUNC(streamrelay_should_save_fn), ++ DEF_OPT_STR("stream_source_host" , OFS(emu_stream_source_host), "127.0.0.1"), ++ DEF_OPT_INT32("stream_source_port" , OFS(emu_stream_source_port), 8001), ++ DEF_OPT_STR("stream_source_auth_user" , OFS(emu_stream_source_auth_user), NULL), ++ DEF_OPT_STR("stream_source_auth_password" , OFS(emu_stream_source_auth_password), NULL), ++ DEF_OPT_INT32("stream_relay_port" , OFS(emu_stream_relay_port), 17999), ++ DEF_OPT_UINT32("stream_ecm_delay" , OFS(emu_stream_ecm_delay), 600), ++ DEF_OPT_INT8("stream_relay_enabled" , OFS(emu_stream_relay_enabled), 1), ++ DEF_OPT_INT8("stream_emm_enabled" , OFS(emu_stream_emm_enabled), 1), ++ DEF_LAST_OPT ++}; ++#else ++static const struct config_list streamrelay_opts[] = { DEF_LAST_OPT }; ++#endif ++ ++ + #ifdef MODULE_RADEGAST + static bool radegast_should_save_fn(void *UNUSED(var)) + { +@@ -1262,6 +1286,7 @@ static const struct config_list dvbapi_o + DEF_OPT_INT8("read_sdt" , OFS(dvbapi_read_sdt), 0), + DEF_OPT_INT8("write_sdt_prov", OFS(dvbapi_write_sdt_prov), 0), + DEF_OPT_INT8("extended_cw_api", OFS(dvbapi_extended_cw_api), 0), ++ DEF_OPT_INT8("extended_cw_pids", OFS(dvbapi_extended_cw_pids), 64), // pid limiter + DEF_OPT_FUNC("boxtype" , OFS(dvbapi_boxtype), dvbapi_boxtype_fn), + DEF_OPT_FUNC("services" , OFS(dvbapi_sidtabs.ok), dvbapi_services_fn), + // OBSOLETE OPTIONS +@@ -1315,6 +1340,7 @@ static const struct config_sections osca + { "cccam", cccam_opts }, + { "pandora", pandora_opts }, + { "scam", scam_opts }, ++ { "streamrelay", streamrelay_opts }, + { "dvbapi", dvbapi_opts }, + { "monitor", monitor_opts }, + { "webif", webif_opts }, +diff -ruNp trunk.patches/oscam-config.h trunk/oscam-config.h +--- trunk.patches/oscam-config.h 2018-04-03 02:44:09.470263713 +0300 ++++ trunk/oscam-config.h 2018-04-03 03:20:07.662045399 +0300 +@@ -22,6 +22,7 @@ void free_reader(struct s_reader *rdr + int32_t free_readerdb(void); + int32_t write_server(void); + void reload_readerdb(void); ++void reader_fixups_fn(void *var); + + void chk_sidtab(char *token, char *value, struct s_sidtab *sidtab); + int32_t init_sidtab(void); +@@ -63,7 +64,8 @@ enum ftab_fn + FTAB_FBPCAID = 0x10, + FTAB_LOCALCARDS = 0x20, + FTAB_IGNCHKSMCAID = 0x40, +- FTAB_IGNCRCCEX4USERONLYFOR = 0x80 ++ FTAB_IGNCRCCEX4USERONLYFOR = 0x80, ++ FTAB_EMUAU = 0x100 + }; + + void ftab_fn(const char *token, char *value, void *setting, long ftab_type, FILE *f); +diff -ruNp trunk.patches/oscam-config-reader.c trunk/oscam-config-reader.c +--- trunk.patches/oscam-config-reader.c 2018-04-03 02:44:09.758266128 +0300 ++++ trunk/oscam-config-reader.c 2018-04-03 03:20:07.662045399 +0300 +@@ -109,6 +109,7 @@ static void protocol_fn(const char *toke + { "newcamd525", R_NEWCAMD }, + { "newcamd524", R_NEWCAMD }, + { "drecas", R_DRECAS }, ++ { "emu", R_EMU }, + { NULL , 0 } + }, *p; + int i; +@@ -448,6 +449,9 @@ void ftab_fn(const char *token, char *va + if(ftab_type & FTAB_FBPCAID) { rdr = container_of(setting, struct s_reader, fallback_percaid); } + if(ftab_type & FTAB_LOCALCARDS) { rdr = container_of(setting, struct s_reader, localcards); } + if(ftab_type & FTAB_IGNCHKSMCAID){ rdr = container_of(setting, struct s_reader, disablecrccws_only_for); } ++#ifdef WITH_EMU ++ if(ftab_type & FTAB_EMUAU) { rdr = container_of(setting, struct s_reader, emu_auproviders); } ++#endif + if(rdr) + { rdr->changes_since_shareupdate = 1; } + } +@@ -779,7 +783,7 @@ static void cooldowntime_fn(const char * + } + + +-static void reader_fixups_fn(void *var) ++void reader_fixups_fn(void *var) + { + struct s_reader *rdr = var; + #ifdef WITH_LB +@@ -923,6 +927,14 @@ static const struct config_list reader_o + #ifdef READER_DRECAS + DEF_OPT_STR("stmkeys" , OFS(stmkeys), NULL), + #endif ++#ifdef WITH_EMU ++ DEF_OPT_FUNC_X("emu_auproviders" , OFS(emu_auproviders), ftab_fn, FTAB_READER | FTAB_EMUAU), ++ DEF_OPT_INT8("emu_datecodedenabled" , OFS(emu_datecodedenabled), 0), ++ DEF_OPT_STR("extee36" , OFS(extee36), NULL), ++ DEF_OPT_STR("extee56" , OFS(extee56), NULL), ++ DEF_OPT_HEX("dre36_force_group" , OFS(dre36_force_group), 1), ++ DEF_OPT_HEX("dre56_force_group" , OFS(dre56_force_group), 1), ++#endif + DEF_OPT_INT8("deprecated" , OFS(deprecated), 0), + DEF_OPT_INT8("audisabled" , OFS(audisabled), 0), + DEF_OPT_FUNC("auprovid" , 0, auprovid_fn), +diff -ruNp trunk.patches/oscam-ecm.c trunk/oscam-ecm.c +--- trunk.patches/oscam-ecm.c 2018-04-03 02:44:08.174252846 +0300 ++++ trunk/oscam-ecm.c 2018-04-03 03:20:07.662045399 +0300 +@@ -1585,7 +1585,7 @@ int32_t write_ecm_answer(struct s_reader + + if(reader && cw && rc < E_NOTFOUND) + { +- if(cfg.disablecrccws == 0 && reader->disablecrccws == 0) ++ if(cfg.disablecrccws == 0 && reader->disablecrccws == 0 && ((er->caid >> 8) != 0x0E)) + { + uint8_t selectedForIgnChecksum = chk_if_ignore_checksum(er, cfg.disablecrccws, &cfg.disablecrccws_only_for) + + chk_if_ignore_checksum(er, reader->disablecrccws, &reader->disablecrccws_only_for); +diff -ruNp trunk.patches/oscam-emm.c trunk/oscam-emm.c +--- trunk.patches/oscam-emm.c 2018-04-03 02:44:09.758266128 +0300 ++++ trunk/oscam-emm.c 2018-04-03 03:20:07.662045399 +0300 +@@ -50,7 +50,14 @@ static int8_t do_simple_emm_filter(struc + unsigned int j, filter_count = 0; + + // Call cardsystems emm filter +- csystem->get_emm_filter(rdr, &dmx_filter, &filter_count); ++ if(rdr->typ == R_EMU) ++ { ++ return 1; //valid emm ++ } ++ else ++ { ++ csystem->get_emm_filter(rdr, &dmx_filter, &filter_count); ++ } + + // Only check matching emmtypes: + uint8_t org_emmtype; +@@ -209,6 +216,24 @@ int32_t emm_reader_match(struct s_reader + rdr_log_dbg(reader, D_EMM, "reader auprovid = %06X fixup to %06X (ignoring last digit)", reader->auprovid, prid); + } + ++#ifdef WITH_EMU ++ if(reader->typ == R_EMU) ++ { ++ FILTER* emu_provids = get_emu_prids_for_caid(reader, caid); ++ if(emu_provids != NULL) ++ { ++ for(i = 0; i < emu_provids->nprids; i++) ++ { ++ if(provid == emu_provids->prids[i]) ++ { ++ return 1; ++ } ++ } ++ } ++ return 0; ++ } ++#endif ++ + if(prid == provid) + { + rdr_log_dbg(reader, D_EMM, "reader auprovid = %06X matching with emm provid = %06X -> SEND!", prid, provid); +diff -ruNp trunk.patches/oscam-string.c trunk/oscam-string.c +--- trunk.patches/oscam-string.c 2018-04-03 02:44:09.762266162 +0300 ++++ trunk/oscam-string.c 2018-04-03 03:20:07.662045399 +0300 +@@ -510,6 +510,62 @@ uint32_t crc32(uint32_t crc, const uint8 + return crc ^ 0xffffffffL; + } + ++static uint32_t fletcher_crc_table[256] = { ++ 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, ++ 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, ++ 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, ++ 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, ++ 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, ++ 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, ++ 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, ++ 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, ++ 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, ++ 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, ++ 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, ++ 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, ++ 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, ++ 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, ++ 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, ++ 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, ++ 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, ++ 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, ++ 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, ++ 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, ++ 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, ++ 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, ++ 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, ++ 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, ++ 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, ++ 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, ++ 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, ++ 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, ++ 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, ++ 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, ++ 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, ++ 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, ++ 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, ++ 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, ++ 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, ++ 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, ++ 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, ++ 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, ++ 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, ++ 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, ++ 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, ++ 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, ++ 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4}; ++ ++uint32_t fletcher_crc32(uint8_t *data, uint32_t len) ++{ ++ uint32_t i; ++ uint32_t crc = 0xffffffff; ++ ++ for (i=0; i> 24) ^ *data++) & 0xff]; ++ ++ return crc; ++} ++ + static uint16_t ccitt_crc_table [256] = + { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, +diff -ruNp trunk.patches/oscam-string.h trunk/oscam-string.h +--- trunk.patches/oscam-string.h 2018-04-03 02:44:10.090268912 +0300 ++++ trunk/oscam-string.h 2018-04-03 03:20:07.662045399 +0300 +@@ -37,6 +37,7 @@ void get_random_bytes_init(void); + void get_random_bytes(uint8_t *dst, uint32_t dst_len); + + uint32_t crc32(uint32_t crc, const uint8_t *buf, uint32_t len); ++uint32_t fletcher_crc32(uint8_t *data, uint32_t len); + uint16_t ccitt_crc(uint8_t *data, size_t length, uint16_t seed, uint16_t final); + uint32_t jhash(const char *key, size_t len); + +diff -ruNp trunk.patches/reader-common.c trunk/reader-common.c +--- trunk.patches/reader-common.c 2018-04-03 02:44:09.758266128 +0300 ++++ trunk/reader-common.c 2018-04-03 03:20:07.662045399 +0300 +@@ -15,6 +15,7 @@ + #include "reader-common.h" + //#include "csctapi/atr.h" + #include "csctapi/icc_async.h" ++#include "readers.h" + + extern const struct s_cardsystem *cardsystems[]; + extern char *RDR_CD_TXT[]; +@@ -142,6 +143,19 @@ void cardreader_poll_status(struct s_rea + static int32_t reader_get_cardsystem(struct s_reader *reader, ATR *atr) + { + int32_t i; ++ ++#ifdef WITH_EMU ++ if(reader->typ == R_EMU) ++ { ++ NULLFREE(reader->csystem_data); ++ rdr_log(reader, "found card system %s", reader_emu.desc); ++ reader->csystem = &reader_emu; ++ reader->csystem_active = true; ++ led_status_found_cardsystem(); ++ return (reader->csystem_active); ++ } ++#endif ++ + for(i = 0; cardsystems[i]; i++) + { + NULLFREE(reader->csystem_data); +diff -ruNp trunk.patches/readers.h trunk/readers.h +--- trunk.patches/readers.h 2018-04-03 02:44:09.762266162 +0300 ++++ trunk/readers.h 2018-04-03 03:20:07.662045399 +0300 +@@ -16,5 +16,6 @@ extern const struct s_cardsystem reader_ + extern const struct s_cardsystem reader_bulcrypt; + extern const struct s_cardsystem reader_griffin; + extern const struct s_cardsystem reader_dgcrypt; ++extern const struct s_cardsystem reader_emu; + + #endif +diff -ruNp trunk.patches/webif/config/dvbapi.html trunk/webif/config/dvbapi.html +--- trunk.patches/webif/config/dvbapi.html 2018-04-03 02:44:08.322254087 +0300 ++++ trunk/webif/config/dvbapi.html 2018-04-03 03:20:07.666045429 +0300 +@@ -53,7 +53,7 @@ + + + Write detected prov name to srvid: +- +\ Ð’ конце файла нет новой Ñтроки ++ ++ ++ Max pids for extended CWs ++ ++ ++ ++ +\ Ð’ конце файла нет новой Ñтроки +diff -ruNp trunk.patches/webif/config/menu.html trunk/webif/config/menu.html +--- trunk.patches/webif/config/menu.html 2018-04-03 02:44:08.458255227 +0300 ++++ trunk/webif/config/menu.html 2018-04-03 03:20:07.666045429 +0300 +@@ -16,6 +16,7 @@ + ##TPLCONFIGMENUDVBAPI## + ##TPLCONFIGMENULCD## + ##TPLCONFIGMENUMONITOR## ++##TPLCONFIGMENUSTREAMRELAY## +
  • WebIf
  • + + +diff -ruNp trunk.patches/webif/config/menu_streamrelay.html trunk/webif/config/menu_streamrelay.html +--- trunk.patches/webif/config/menu_streamrelay.html 1970-01-01 03:00:00.000000000 +0300 ++++ trunk/webif/config/menu_streamrelay.html 2018-04-03 03:20:07.666045429 +0300 +@@ -0,0 +1 @@ ++
  • Stream Relay
  • +diff -ruNp trunk.patches/webif/config/streamrelay.html trunk/webif/config/streamrelay.html +--- trunk.patches/webif/config/streamrelay.html 1970-01-01 03:00:00.000000000 +0300 ++++ trunk/webif/config/streamrelay.html 2018-04-03 03:20:07.666045429 +0300 +@@ -0,0 +1,25 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +\ Ð’ конце файла нет новой Ñтроки +diff -ruNp trunk.patches/webif/files/menu.html trunk/webif/files/menu.html +--- trunk.patches/webif/files/menu.html 2018-04-03 02:44:08.458255227 +0300 ++++ trunk/webif/files/menu.html 2018-04-03 03:20:07.666045429 +0300 +@@ -10,7 +10,7 @@ +
  • logfile
  • +
  • userfile
  • + ##TPLFILEMENUGBOX## +-
  • other files ++
  • other files + +
  • + +diff -ruNp trunk.patches/webif/files/menu_softcamkey.html trunk/webif/files/menu_softcamkey.html +--- trunk.patches/webif/files/menu_softcamkey.html 1970-01-01 03:00:00.000000000 +0300 ++++ trunk/webif/files/menu_softcamkey.html 2018-04-03 03:20:07.666045429 +0300 +@@ -0,0 +1 @@ ++
  • SoftCam.Key
  • +diff -ruNp trunk.patches/webif/pages_index.txt trunk/webif/pages_index.txt +--- trunk.patches/webif/pages_index.txt 2018-04-03 02:44:08.678257072 +0300 ++++ trunk/webif/pages_index.txt 2018-04-03 03:20:07.666045429 +0300 +@@ -80,11 +80,13 @@ CONFIGMENUMONITOR config/men + CONFIGMENUNEWCAMD config/menu_newcamd.html MODULE_NEWCAMD + CONFIGMENURADEGAST config/menu_radegast.html MODULE_RADEGAST + CONFIGMENUSCAM config/menu_scam.html MODULE_SCAM ++CONFIGMENUSTREAMRELAY config/menu_streamrelay.html WITH_EMU + CONFIGMENUSERIAL config/menu_serial.html MODULE_SERIAL + CONFIGMONITOR config/monitor.html MODULE_MONITOR + CONFIGNEWCAMD config/newcamd.html MODULE_NEWCAMD + CONFIGRADEGAST config/radegast.html MODULE_RADEGAST + CONFIGSCAM config/scam.html MODULE_SCAM ++CONFIGSTREAMRELAY config/streamrelay.html WITH_EMU + CONFIGSERIAL config/serial.html MODULE_SERIAL + CONFIGSERIALDEVICEBIT config/serial_devices.html MODULE_SERIAL + CONFIGWEBIF config/webif.html +@@ -118,6 +120,7 @@ FILEMENUDVBAPI files/menu + FILEMENUFAKECWS files/menu_fakecws.html CS_CACHEEX + FILEMENUGBOX files/menu_gbox.html MODULE_GBOX + FILEMENUTWIN files/menu_twin.html MODULE_SERIAL ++FILEMENUSOFTCAMKEY files/menu_softcamkey.html WITH_EMU + + AUTOCONF ghttp/autoconf.html MODULE_GHTTP + PREAUTOCONF ghttp/pre_autoconf.html MODULE_GHTTP +@@ -182,6 +185,7 @@ READERCONFIG readerconf + READEREDITCACHEEXBIT readerconfig/readerconfig_cacheexbit.html CS_CACHEEX + READERCONFIGCAMD35BIT readerconfig/readerconfig_camd35bit.html MODULE_CAMD35 + READERCONFIGCCCAMBIT readerconfig/readerconfig_cccambit.html MODULE_CCCAM ++READERCONFIGEMUBIT readerconfig/readerconfig_emubit.html WITH_EMU + READERCONFIGCS378XBIT readerconfig/readerconfig_cs378xbit.html MODULE_CAMD35_TCP + READERCONFIGGBOXBIT readerconfig/readerconfig_gboxbit.html MODULE_GBOX + READERCONFIGGHTTPBIT readerconfig/readerconfig_ghttpbit.html MODULE_GHTTP +diff -ruNp trunk.patches/webif/readerconfig/readerconfig_emubit.html trunk/webif/readerconfig/readerconfig_emubit.html +--- trunk.patches/webif/readerconfig/readerconfig_emubit.html 1970-01-01 03:00:00.000000000 +0300 ++++ trunk/webif/readerconfig/readerconfig_emubit.html 2018-04-03 03:20:07.666045429 +0300 +@@ -0,0 +1,6 @@ ++ ++ ++ ++ ++ ++ diff --git a/package/lean/dvb/tvheadend/Config.in b/package/lean/dvb/tvheadend/Config.in new file mode 100644 index 000000000..5bc1a18bc --- /dev/null +++ b/package/lean/dvb/tvheadend/Config.in @@ -0,0 +1,17 @@ +config TVHEADEND_NDMS_CWC_SUPPORT + bool "NewCamd support" + default y + +config TVHEADEND_NDMS_LINUXDVB_SUPPORT + bool "Linux DVB support" + default y + +config TVHEADEND_NDMS_DVBSCAN_SUPPORT + bool "Fetch DVB-scan data" + depends on TVHEADEND_NDMS_LINUXDVB_SUPPORT + default TVHEADEND_NDMS_LINUXDVB_SUPPORT + +config TVHEADEND_NDMS_AVAHI_SUPPORT + bool "Avahi client support" + select PACKAGE_libavahi-client + default n diff --git a/package/lean/dvb/tvheadend/Makefile b/package/lean/dvb/tvheadend/Makefile new file mode 100644 index 000000000..491f65473 --- /dev/null +++ b/package/lean/dvb/tvheadend/Makefile @@ -0,0 +1,131 @@ +# +# Copyright (C) 2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=tvheadend +PKG_VERSION:=4.2.6 +PKG_RELEASE:=1 + +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=c2a6b61d06ecf8c033f2f5be5746c146eb907d26 +# This is stable git version... +# PKG_SOURCE_VERSION:=1a0262f5870e4fabd6b9c70a7bf2ebe420bc956e +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/tvheadend/tvheadend.git +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +PKG_LICENSE:=GPL-3.0 +PKG_LICENSE_FILES:=LICENSE.md + +PKG_FIXUP:=autoreconf + +PKG_USE_MIPS16:=0 + +SHORT_GIT_VER:=$(shell echo $(PKG_SOURCE_VERSION) | cut -b -7) + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk + +define Package/tvheadend + SECTION:=multimedia + CATEGORY:=Multimedia + TITLE:=Tvheadend is a TV streaming server for Linux + DEPENDS:=+libopenssl +librt +zlib +libpcre +libdvbcsa +TVHEADEND_AVAHI_SUPPORT:libavahi-client $(ICONV_DEPENDS) + URL:=https://tvheadend.org + MAINTAINER:=Jan ÄŒermák +endef + +define Package/tvheadend/description + Tvheadend is a TV streaming server and recorder for Linux, FreeBSD and Android + supporting DVB-S, DVB-S2, DVB-C, DVB-T, ATSC, IPTV, SAT>IP and HDHomeRun as input sources. + + Tvheadend offers the HTTP (VLC, MPlayer), HTSP (Kodi, Movian) and SAT>IP streaming. +endef + +define Package/tvheadend/config + menu "Configuration" + depends on PACKAGE_tvheadend + source "$(SOURCE)/Config.in" + endmenu +endef + +ifeq ($(CONFIG_TVHEADEND_CWC_SUPPORT),) + CONFIGURE_ARGS += --disable-cwc +endif + +ifeq ($(CONFIG_TVHEADEND_LINUXDVB_SUPPORT),) + CONFIGURE_ARGS += --disable-linuxdvb +endif + +ifeq ($(CONFIG_TVHEADEND_DVBSCAN_SUPPORT),) + CONFIGURE_ARGS += --disable-dvbscan +endif + +ifeq ($(CONFIG_TVHEADEND_AVAHI_SUPPORT),) + CONFIGURE_ARGS += --disable-avahi +else + CONFIGURE_ARGS += --enable-avahi +endif + +CONFIGURE_ARGS += \ + --arch=$(ARCH) \ + --disable-dbus_1 \ + --disable-libav \ + --enable-bundle \ + --enable-dvben50221 \ + --enable-tvhcsa \ + --enable-dvbcsa \ + --enable-inotify \ + --enable-epoll \ + --enable-trace \ + --nowerror \ + --disable-dvbscan \ + --disable-avahi \ + --disable-hdhomerun_static \ + --disable-pie \ + --disable-imagecache \ + --disable-ffmpeg_static \ + --disable-libx264 \ + --disable-libx264_static \ + --disable-libx265 \ + --disable-libx265_static \ + --disable-libvpx \ + --disable-libvpx_static \ + --disable-libtheora \ + --disable-libtheora_static \ + --disable-libvorbis \ + --disable-libvorbis_static \ + --disable-libfdkaac \ + --disable-libfdkaac_static \ + --disable-nvenc \ + --disable-libmfx_static \ + --disable-timeshift + + +define Build/Prepare + $(call Build/Prepare/Default) + echo 'Tvheadend $(shell echo $(PKG_VERSION)~$(SHORT_GIT_VER)-$(PKG_RELEASE))' \ + > $(PKG_BUILD_DIR)/debian/changelog +endef + +define Package/conffiles +/etc/config/tvheadend +endef + +define Package/tvheadend/install + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/tvheadend.init $(1)/etc/init.d/tvheadend + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_CONF) ./files/tvheadend.config $(1)/etc/config/tvheadend + + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/build.linux/tvheadend $(1)/usr/bin/ +endef + +$(eval $(call BuildPackage,tvheadend)) diff --git a/package/lean/dvb/tvheadend/files/tvheadend.config b/package/lean/dvb/tvheadend/files/tvheadend.config new file mode 100644 index 000000000..62c139de5 --- /dev/null +++ b/package/lean/dvb/tvheadend/files/tvheadend.config @@ -0,0 +1,13 @@ +#config tvheadend service +# option nosyslog '0' +# option use_temp_epgdb '0' +# option config_path '/etc/tvheadend' + +config tvheadend server + option ipv6 '1' +# option bindaddr '0.0.0.0' +# option http_port '9981' +# option http_root '/tvheadend' +# option htsp_port '9982' +# option htsp_port2 '9983' +# option xspf '0' diff --git a/package/lean/dvb/tvheadend/files/tvheadend.init b/package/lean/dvb/tvheadend/files/tvheadend.init new file mode 100644 index 000000000..07d96a867 --- /dev/null +++ b/package/lean/dvb/tvheadend/files/tvheadend.init @@ -0,0 +1,71 @@ +#!/bin/sh /etc/rc.common + +START=99 +STOP=00 + +USE_PROCD=1 +PROG=/usr/bin/tvheadend + +TEMP_CONFIG=/tmp/tvheadend +PERSISTENT_CONFIG=/etc/tvheadend + +execute_first_run() { + "$PROG" -C "$1" -B -C -A >/dev/null 2>&1 +} + +ensure_config_exists() { + local config_path + + config_load tvheadend + config_get config_path service config_path + + if [ -z "$config_path" ]; then + [ -d "$PERSISTENT_CONFIG" ] || execute_first_run "$PERSISTENT_CONFIG" + else + # if the configuration directory is empty, empty config with grant-all ACL is created + [ -d "$config_path" ] && [ "$(ls -A $config_path)" ] || execute_first_run "$config_path" + fi + + # if use_temp_epgdb is enabled (default), most of the config is put to config_path + # (or /etc/config), except for epgdb.v2, which grows quite large and is write-heavy, + # so it's put into volatile tmpfs + # epgdb.v2 is created and symlinked to main config dir upon each start (if it doesn't exist) + config_get_bool use_temp_epgdb service use_temp_epgdb 1 + if [ "$use_temp_epgdb" == "1" ]; then + TEMP_EPG="${TEMP_CONFIG}/epgdb.v2" + [ ! -f "$TEMP_EPG" ] && mkdir -p "$TEMP_CONFIG" && touch "$TEMP_EPG" && chmod 700 "$TEMP_EPG" + [ -z "$config_path" ] && config_path="$PERSISTENT_CONFIG" + ln -sf "$TEMP_EPG" "${config_path}/epgdb.v2" + fi +} + +load_uci_config() { + config_load tvheadend + config_get config_path service config_path "$PERSISTENT_CONFIG" + [ -n "$config_path" ] && procd_append_param command -c "$config_path" + config_get_bool nosyslog service nosyslog 0 + [ "$nosyslog" -eq 1 ] && procd_append_param command --nosyslog + config_get_bool ipv6 server ipv6 0 + [ "$ipv6" -eq 1 ] && procd_append_param command --ipv6 + config_get bindaddr server bindaddr + [ -n "$bindaddr" ] && procd_append_param command --bindaddr "$bindaddr" + config_get http_port server http_port + [ -n "$http_port" ] && procd_append_param command --http_port "$http_port" + config_get http_root server http_root + [ -n "$http_root" ] && procd_append_param command --http_root "$http_root" + config_get htsp_port server htsp_port + [ -n "$htsp_port" ] && procd_append_param command --htsp_port "$htsp_port" + config_get htsp_port2 server htsp_port2 + [ -n "$htsp_port2" ] && procd_append_param command --htsp_port "$htsp_port2" + config_get xspf server xspf 0 + [ "$xspf" -eq 1 ] && procd_append_param command --xspf +} + +start_service() { + ensure_config_exists + procd_open_instance + procd_set_param file /etc/config/tvheadend + procd_set_param command "$PROG" -B -C + load_uci_config + procd_close_instance +} diff --git a/package/lean/dvb/tvheadend/patches/001-config.patch b/package/lean/dvb/tvheadend/patches/001-config.patch new file mode 100644 index 000000000..becfe11d9 --- /dev/null +++ b/package/lean/dvb/tvheadend/patches/001-config.patch @@ -0,0 +1,12 @@ +diff -ruN tvheadend.orig/Makefile tvheadend/Makefile +--- tvheadend.orig/Makefile 2017-10-18 16:39:58.000000000 +0300 ++++ tvheadend/Makefile 2017-12-13 00:49:51.314127208 +0300 +@@ -52,7 +52,7 @@ + CFLAGS += -Wmissing-prototypes + CFLAGS += -fms-extensions -funsigned-char -fno-strict-aliasing + CFLAGS += -D_FILE_OFFSET_BITS=64 +-CFLAGS += -I${BUILDDIR} -I${ROOTDIR}/src -I${ROOTDIR} ++CFLAGS += -I ./vendor/dvb-api/5.10 -I${BUILDDIR} -I${ROOTDIR}/src -I${ROOTDIR} + ifeq ($(CONFIG_ANDROID),yes) + LDFLAGS += -ldl -lm + else diff --git a/package/lean/dvb/tvheadend/patches/002-add-cflags.patch b/package/lean/dvb/tvheadend/patches/002-add-cflags.patch new file mode 100755 index 000000000..cbd72e0ba --- /dev/null +++ b/package/lean/dvb/tvheadend/patches/002-add-cflags.patch @@ -0,0 +1,33 @@ +commit 511fddc480c11ba55c9078e54884b584430dc41e +Author: Jaroslav Kysela +Date: Fri Jan 19 10:20:17 2018 +0100 + + Makefile: Add CFLAGS for timestamp and bundle objects, fixes #4870 + +diff --git a/Makefile b/Makefile +index f4b7deb..a6629bd 100644 +--- a/Makefile ++++ b/Makefile +@@ -764,11 +764,11 @@ $(BUILDDIR)/timestamp.c: FORCE + @echo 'const char* build_timestamp = "'$(BUILD_DATE)'";' >> $@ + + $(BUILDDIR)/timestamp.o: $(BUILDDIR)/timestamp.c +- $(pCC) -c -o $@ $< ++ $(pCC) $(CFLAGS) -c -o $@ $< + + $(BUILDDIR)/build.o: $(BUILDDIR)/build.c + @mkdir -p $(dir $@) +- $(pCC) -c -o $@ $< ++ $(pCC) $(CFLAGS) -c -o $@ $< + + # Documentation + $(BUILDDIR)/docs-timestamp: $(I18N-DOCS) support/doc/md_to_c.py +@@ -825,7 +825,7 @@ src/tvh_locale_inc.c: $(PO-FILES) + # Bundle files + $(BUILDDIR)/bundle.o: $(BUILDDIR)/bundle.c + @mkdir -p $(dir $@) +- $(pCC) -I${ROOTDIR}/src -c -o $@ $< ++ $(pCC) $(CFLAGS) -I${ROOTDIR}/src -c -o $@ $< + + $(BUILDDIR)/bundle.c: check_dvb_scan make_webui + @mkdir -p $(dir $@) diff --git a/package/lean/dvb/tvheadend/patches/006-satip_rtsp_fix.patch b/package/lean/dvb/tvheadend/patches/006-satip_rtsp_fix.patch new file mode 100644 index 000000000..901c252e0 --- /dev/null +++ b/package/lean/dvb/tvheadend/patches/006-satip_rtsp_fix.patch @@ -0,0 +1,314 @@ +diff -ruNp tvheadend.orig/src/http.c tvheadend/src/http.c +--- tvheadend.orig/src/http.c 2018-02-22 22:16:01.000000000 +0300 ++++ tvheadend/src/http.c 2018-02-26 04:03:51.584188821 +0300 +@@ -1273,10 +1273,6 @@ process_request(http_connection_t *hc, h + hc->hc_session = tvh_strdupa(v); + else + hc->hc_session = NULL; +- if(hc->hc_cseq == 0) { +- http_error(hc, HTTP_STATUS_BAD_REQUEST); +- return -1; +- } + break; + + case HTTP_VERSION_1_0: +@@ -1336,10 +1332,7 @@ process_request(http_connection_t *hc, h + case RTSP_VERSION_1_0: + if (tvhtrace_enabled()) + dump_request(hc); +- if (hc->hc_cseq) +- rval = hc->hc_process(hc, spill); +- else +- http_error(hc, HTTP_STATUS_HTTP_VERSION); ++ rval = hc->hc_process(hc, spill); + break; + + case HTTP_VERSION_1_0: +diff -ruNp tvheadend.orig/src/http.h tvheadend/src/http.h +--- tvheadend.orig/src/http.h 2018-02-22 22:16:01.000000000 +0300 ++++ tvheadend/src/http.h 2018-02-26 03:19:40.457467700 +0300 +@@ -162,6 +162,7 @@ typedef struct http_connection { + + int hc_no_output; + int hc_shutdown; ++ int hc_stream; + uint64_t hc_cseq; + char *hc_session; + +diff -ruNp tvheadend.orig/src/satip/rtsp.c tvheadend/src/satip/rtsp.c +--- tvheadend.orig/src/satip/rtsp.c 2018-02-22 22:16:01.000000000 +0300 ++++ tvheadend/src/satip/rtsp.c 2018-02-26 19:07:59.113158089 +0300 +@@ -92,6 +92,13 @@ static pthread_mutex_t rtsp_lock; + static void rtsp_close_session(session_t *rs); + static void rtsp_free_session(session_t *rs); + ++/* ++ * ++ */ ++static inline int rtsp_is_nat_active(void) ++{ ++ return rtsp_nat_ip[0] != '\0'; ++} + + /* + * +@@ -280,9 +287,10 @@ rtsp_check_urlbase(char *u) + if (strcmp(u, rtsp_ip)) { + if (rtsp_nat_ip == NULL) + return NULL; +- if (rtsp_nat_ip[0] != '*') +- if (rtsp_nat_ip[0] == '\0' || strcmp(u, rtsp_nat_ip)) ++ if (rtsp_is_nat_active()) { ++ if (rtsp_nat_ip[0] != '*' && strcmp(u, rtsp_nat_ip)) + return NULL; ++ } + } + return p ? p + 1 : u + strlen(u); + } +@@ -455,8 +463,7 @@ static void + rtsp_manage_descramble(session_t *rs) + { + idnode_set_t *found; +- mpegts_service_t *s, *snext; +- mpegts_service_t *master = (mpegts_service_t *)rs->subs->ths_raw_service; ++ mpegts_service_t *s, *master, *snext; + slave_subscription_t *sub; + mpegts_apids_t pmt_pids; + size_t si; +@@ -470,6 +477,8 @@ rtsp_manage_descramble(session_t *rs) + if (rs->mux == NULL || rs->subs == NULL) + goto end; + ++ master = (mpegts_service_t *)rs->subs->ths_raw_service; ++ + if (rs->pids.all) { + LIST_FOREACH(s, &rs->mux->mm_services, s_dvb_mux_link) + if (rtsp_validate_service(s, NULL)) +@@ -861,7 +870,7 @@ parse_pids(char *p, mpegts_apids_t *pids + while (1) { + if (x == NULL) + break; +- if (strcmp(x, "all") == 0) { ++ if (strcmp(x, "all") == 0 || strcmp(x, "8192") == 0) { + if (satip_server_conf.satip_restrict_pids_all) { + pids->all = 0; + for (pid = 1; pid <= 2; pid++) /* CAT, TSDT */ +@@ -907,7 +916,22 @@ parse_transport(http_connection_t *hc) + if (a + 1 != b) + return -1; + return a; +- } else if ((strncmp(s, "RTP/AVP/TCP;interleaved=0-1", 27) == 0) && ++ } else if (strncmp(s, "RTP/AVP/UDP;unicast;client_port=", 32) == 0) { ++ for (s += 32, u = s; isdigit(*u); u++); ++ if (*u != '-') ++ return -1; ++ a = atoi(s); ++ for (s = ++u; isdigit(*s); s++); ++ if (*s != '\0' && *s != ';') ++ return -1; ++ b = atoi(u); ++ if (a + 1 != b) ++ return -1; ++ return a; ++ } else if ((strncmp(s, "RTP/AVP/TCP;unicast;interleaved=0-1", 27) == 0) && ++ !satip_server_conf.satip_notcp_mode) { ++ return RTSP_TCP_DATA; ++ } else if ((strncmp(s, "RTP/AVP/TCP;interleaved=0-1", 35) == 0) && + !satip_server_conf.satip_notcp_mode) { + return RTSP_TCP_DATA; + } +@@ -983,12 +1007,14 @@ rtsp_parse_cmd + if (cmd == RTSP_CMD_SETUP) { + if (!rs) { + rs = rtsp_new_session(hc->hc_peer_ipstr, msys, 0, -1); ++ if (rs == NULL) goto end; + if (delsys == DVB_SYS_NONE) goto end; + if (msys == DVB_SYS_NONE) goto end; + if (!(*valid)) goto end; + alloc_stream_id = 1; + } else if (stream != rs->stream) { + rs = rtsp_new_session(hc->hc_peer_ipstr, msys, rs->nsession, stream); ++ if (rs == NULL) goto end; + if (delsys == DVB_SYS_NONE) goto end; + if (msys == DVB_SYS_NONE) goto end; + if (!(*valid)) goto end; +@@ -1017,6 +1043,8 @@ rtsp_parse_cmd + rs->rtp_peer_port = r; + rs->frontend = fe > 0 ? fe : 1; + } else { ++ if (!rs && !stream && cmd == RTSP_CMD_DESCRIBE) ++ rs = rtsp_new_session(hc->hc_peer_ipstr, msys, 0, -1); + if (!rs || stream != rs->stream) { + if (rs) + errcode = HTTP_STATUS_NOT_FOUND; +@@ -1187,6 +1215,12 @@ play: + if (mpegts_pid_dump(&rs->pids, buf + r, sizeof(buf) - r, 0, 0) == 0) + tvh_strlcatf(buf, sizeof(buf), r, ""); + ++ if (cmd == RTSP_CMD_DESCRIBE) { ++ hc->hc_session = rs->session; ++ if (!rs->stream) ++ rs->stream = 1; ++ hc->hc_stream = rs->stream; ++ } + tvhdebug(LS_SATIPS, "%i/%s/%d: %s from %s:%d %s", + rs->frontend, rs->session, rs->stream, + caller, hc->hc_peer_ipstr, ntohs(IP_PORT(*hc->hc_peer)), buf); +@@ -1294,7 +1328,8 @@ rtsp_describe_session(session_t *rs, hts + { + char buf[4096]; + +- htsbuf_qprintf(q, "a=control:stream=%d\r\n", rs->stream); ++ if (rs->stream > 0) ++ htsbuf_qprintf(q, "a=control:stream=%d\r\n", rs->stream); + htsbuf_append_str(q, "a=tool:tvheadend\r\n"); + htsbuf_append_str(q, "m=video 0 RTP/AVP 33\r\n"); + if (strchr(rtsp_ip, ':')) +@@ -1311,6 +1346,20 @@ rtsp_describe_session(session_t *rs, hts + } + } + ++static inline const char * ++rtsp_conn_ip(http_connection_t *hc, char *buf, size_t buflen, int *port) ++{ ++ const char *used_ip = rtsp_ip; ++ int used_port = rtsp_port; ++ ++ if (hc && hc->hc_self) ++ used_ip = tcp_get_str_from_ip(hc->hc_self, buf, buflen); ++ ++ *port = used_port > 0 ? used_port : 554; ++ ++ return used_ip; ++} ++ + /* + * + */ +@@ -1322,9 +1371,10 @@ rtsp_process_describe(http_connection_t + char *u = tvh_strdupa(hc->hc_url); + session_t *rs; + htsbuf_queue_t q; +- char buf[96]; ++ char buf[96], buf1[46]; ++ const char *used_ip = NULL; + int r = HTTP_STATUS_BAD_REQUEST; +- int stream, first = 1, valid; ++ int stream, first = 1, valid, used_port; + + htsbuf_queue_init(&q, 0); + +@@ -1381,10 +1431,15 @@ rtsp_process_describe(http_connection_t + http_arg_init(&args); + if (hc->hc_session) + http_arg_set(&args, "Session", hc->hc_session); +- if (stream > 0) +- snprintf(buf, sizeof(buf), "rtsp://%s/stream=%i", rtsp_ip, stream); ++ used_ip = rtsp_conn_ip(hc, buf1, sizeof(buf1), &used_port); ++ if ((stream > 0) && (used_port != 554)) ++ snprintf(buf, sizeof(buf), "rtsp://%s:%d/stream=%i", used_ip, used_port, stream); ++ else if ((stream > 0) && (used_port == 554)) ++ snprintf(buf, sizeof(buf), "rtsp://%s/stream=%i", used_ip, stream); ++ else if (used_port != 554) ++ snprintf(buf, sizeof(buf), "rtsp://%s:%d", used_ip, used_port); + else +- snprintf(buf, sizeof(buf), "rtsp://%s", rtsp_ip); ++ snprintf(buf, sizeof(buf), "rtsp://%s", used_ip); + http_arg_set(&args, "Content-Base", buf); + http_send_begin(hc); + http_send_header(hc, HTTP_STATUS_OK, "application/sdp", q.hq_size, +@@ -1408,8 +1463,9 @@ static int + rtsp_process_play(http_connection_t *hc, int cmd) + { + session_t *rs; +- int errcode = HTTP_STATUS_BAD_REQUEST, valid = 0, i, stream; +- char buf[256], *u = tvh_strdupa(hc->hc_url); ++ int errcode = HTTP_STATUS_BAD_REQUEST, valid = 0, i, stream, used_port; ++ char buf[256], buf1[46], *u = tvh_strdupa(hc->hc_url); ++ const char *used_ip = NULL; + http_arg_list_t args; + + http_arg_init(&args); +@@ -1417,7 +1473,9 @@ rtsp_process_play(http_connection_t *hc, + if ((u = rtsp_check_urlbase(u)) == NULL) + goto error2; + +- if ((stream = rtsp_parse_args(hc, u)) < 0) ++/* if ((stream = rtsp_parse_args(hc, u)) < 0) */ ++ stream = hc->hc_stream; ++ if (stream < 0) + goto error2; + + pthread_mutex_lock(&rtsp_lock); +@@ -1467,10 +1525,11 @@ rtsp_process_play(http_connection_t *hc, + snprintf(buf, sizeof(buf), "%d", rs->stream); + http_arg_set(&args, "com.ses.streamID", buf); + } else { +- if (rtsp_port != 554) +- snprintf(buf, sizeof(buf), "url=rtsp://%s:%d/stream=%d", rtsp_ip, rtsp_port, rs->stream); ++ used_ip = rtsp_conn_ip(hc, buf1, sizeof(buf1), &used_port); ++ if (used_port != 554) ++ snprintf(buf, sizeof(buf), "url=rtsp://%s:%d/stream=%d", used_ip, used_port, rs->stream); + else +- snprintf(buf, sizeof(buf), "url=rtsp://%s/stream=%d", rtsp_ip, rs->stream); ++ snprintf(buf, sizeof(buf), "url=rtsp://%s/stream=%d", used_ip, rs->stream); + http_arg_set(&args, "RTP-Info", buf); + } + +@@ -1587,9 +1646,39 @@ static void + rtsp_stream_status ( void *opaque, htsmsg_t *m ) + { + http_connection_t *hc = opaque; ++ struct session *rs = NULL; ++ htsmsg_t *c, *tcp = NULL, *udp = NULL; ++ int udpport, s32; ++ + htsmsg_add_str(m, "type", "SAT>IP"); ++ + if (hc->hc_username) + htsmsg_add_str(m, "user", hc->hc_username); ++ ++ TAILQ_FOREACH(rs, &rtsp_sessions, link) { ++ if (hc->hc_session && ++ strcmp(rs->session, hc->hc_session) == 0 && ++ strcmp(rs->peer_ipstr, hc->hc_peer_ipstr) == 0 && ++ (udpport = rs->rtp_peer_port) > 0) { ++ if (udpport == RTSP_TCP_DATA) { ++ if (rs->tcp_data == hc) { ++ s32 = htsmsg_get_s32_or_default(m, "peer_port", -1); ++ if (!tcp) tcp = htsmsg_create_list(); ++ htsmsg_add_s32(tcp, NULL, s32); ++ } ++ } else { ++ if (!udp) udp = htsmsg_create_list(); ++ htsmsg_add_s32(udp, NULL, udpport); ++ htsmsg_add_s32(udp, NULL, udpport+1); ++ } ++ } ++ } ++ if (tcp || udp) { ++ c = htsmsg_create_map(); ++ if (tcp) htsmsg_add_msg(c, "tcp", tcp); ++ if (udp) htsmsg_add_msg(c, "udp", udp); ++ htsmsg_add_msg(m, "peer_extra_ports", c); ++ } + } + + /* +@@ -1621,6 +1710,7 @@ rtsp_serve(int fd, void **opaque, struct + hc.hc_peer = peer; + hc.hc_self = self; + hc.hc_process = rtsp_process_request; ++ hc.hc_stream = -1; + hc.hc_cseq = 1; + + http_serve_requests(&hc); +@@ -1655,7 +1745,7 @@ rtsp_close_session(session_t *rs) + rs->tcp_data = NULL; + pthread_mutex_lock(&global_lock); + mpegts_pid_reset(&rs->pids); +- rtsp_clean(rs, 1); ++ rtsp_clean(rs, 0); + mtimer_disarm(&rs->timer); + pthread_mutex_unlock(&global_lock); + } diff --git a/package/lean/dvb/tvheadend/patches/008-delete-docs.patch b/package/lean/dvb/tvheadend/patches/008-delete-docs.patch new file mode 100644 index 000000000..5823268d4 --- /dev/null +++ b/package/lean/dvb/tvheadend/patches/008-delete-docs.patch @@ -0,0 +1,10 @@ +--- a/Makefile 2018-03-22 02:51:32.000000000 +0800 ++++ b/Makefile 2018-03-23 18:31:08.010773484 +0800 +@@ -834,6 +834,7 @@ + $(pCC) $(CFLAGS) -I${ROOTDIR}/src -c -o $@ $< + + $(BUILDDIR)/bundle.c: $(DVBSCAN-yes) make_webui ++ find src/webui/static/img/doc/ -delete + @mkdir -p $(dir $@) + $(pMKBUNDLE) -o $@ -d ${BUILDDIR}/bundle.d $(BUNDLE_FLAGS) $(BUNDLES:%=$(ROOTDIR)/%) + diff --git a/package/lean/heimdal/Makefile b/package/lean/heimdal/Makefile new file mode 100644 index 000000000..471e189c2 --- /dev/null +++ b/package/lean/heimdal/Makefile @@ -0,0 +1,157 @@ +# +# Copyright (C) 2009-2011 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=heimdal +PKG_VERSION:=1.5.3 +PKG_RELEASE:=1 +PKG_INSTALL:=1 + +PKG_BUILD_DEPENDS:=heimdal/host + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://www.h5l.org/dist/src/ +PKG_MD5SUM:=30b379e3de12f332fbd201131f02ffca +#PKG_FIXUP:=autoreconf + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/host-build.mk + +HOST_CONFIGURE_ARGS += \ + --disable-shared \ + --enable-static \ + --without-openldap \ + --without-capng \ + --without-sqlite3 \ + --without-libintl \ + --without-openssl \ + --without-berkeley-db \ + --without-readline \ + --without-libedit \ + --without-hesiod \ + --without-x \ + --disable-heimdal-documentation + +define Host/Compile + $(MAKE) -C $(HOST_BUILD_DIR)/include $(HOST_MAKE_FLAGS) + $(MAKE) -C $(HOST_BUILD_DIR)/lib/roken $(HOST_MAKE_FLAGS) + $(MAKE) -C $(HOST_BUILD_DIR)/lib/vers $(HOST_MAKE_FLAGS) + $(MAKE) -C $(HOST_BUILD_DIR)/lib/com_err $(HOST_MAKE_FLAGS) + $(MAKE) -C $(HOST_BUILD_DIR)/lib/asn1 $(HOST_MAKE_FLAGS) + $(MAKE) -C $(HOST_BUILD_DIR)/lib/libedit $(HOST_MAKE_FLAGS) + $(MAKE) -C $(HOST_BUILD_DIR)/lib/sl $(HOST_MAKE_FLAGS) +endef + +define Host/Install + $(INSTALL_DIR) $(STAGING_DIR)/host/bin + $(CP) $(HOST_BUILD_DIR)/lib/com_err/compile_et $(STAGING_DIR)/host/bin + $(CP) $(HOST_BUILD_DIR)/lib/asn1/asn1_compile $(STAGING_DIR)/host/bin + $(CP) $(HOST_BUILD_DIR)/lib/sl/slc $(STAGING_DIR)/host/bin +endef + +CONFIGURE_ARGS += \ + --disable-pk-init \ + --disable-kx509 \ + --disable-sqlite-cache \ + --enable-pthread-support \ + --disable-afs-support \ + --disable-ndbm-db \ + --with-cross-tools=$(STAGING_DIR_HOST)/bin \ + --disable-heimdal-documentation \ + --enable-developer \ + --with-sqlite3=yes \ + --with-sqlite3-include=$(STAGING_DIR)/usr/include \ + --with-sqlite3-lib=$(STAGING_DIR)/usr/lib \ + --with-openssl=yes \ + --with-openssl-include=$(STAGING_DIR)/usr/include \ + --with-openssl-lib=$(STAGING_DIR)/usr/lib \ + --without-x \ + --disable-afs-support \ + --disable-ndbm-db \ + --disable-mmap + +EXTRA_CFLAGS += \ + -Wno-deprecated-declarations \ + -Wno-unused-variable \ + -Wno-unused-function \ + -Wno-maybe-uninitialized \ + -Wno-return-type \ + -Wno-enum-compare + +define Build/Prepare + $(call Build/Prepare/Default) + $(CP) files/roken-h-process.pl $(PKG_BUILD_DIR)/cf +endef + +define Build/Compile +endef + + +define Package/heimdal/Default + SECTION:=network + CATEGORY:=Network + SUBMENU:=Kerberos + TITLE:=Heimdal Kerberos 5 + URL:=http://www.h5l.org +endef + +define Package/heimdal-libs + $(call Package/heimdal/Default) + TITLE+= (Libraries) + DEPENDS:=+libsqlite3 +libreadline +libncurses +libopenssl +endef + +define Package/heimdal-server + $(call Package/heimdal/Default) + TITLE+= (Server) + DEPENDS:=+heimdal-libs +endef + +define Package/heimdal-client + $(call Package/heimdal/Default) + TITLE+= (Client) + DEPENDS:=+heimdal-libs +endef + +define Package/heimdal-libs/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib +endef + +define Package/heimdal-client/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/kdestroy $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/kinit $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/kcc $(1)/usr/bin + $(CP) $(PKG_INSTALL_DIR)/usr/bin/klist $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/kpasswd $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/su $(1)/usr/bin/ksu +endef + +define Package/heimdal-server/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/kadmin $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ktutil $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/kstash $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/kdc $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/kadmind $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/kpasswdd $(1)/usr/sbin +endef + +#define Build/InstallDev +# $(INSTALL_DIR) $(1)/usr/include/heimdal +# $(CP) $(PKG_BUILD_DIR)/include/heimdal/heimdal.h $(TOOLCHAIN_DIR)/include/sys +# $(CP) $(PKG_BUILD_DIR)/include/heimdal/libheimdal.h $(1)/usr/include/heimdal +# $(INSTALL_DIR) $(1)/usr/lib/ +# $(CP) $(PKG_BUILD_DIR)/libheimdal/.libs/libheimdal.{a,so*} $(1)/usr/lib/ +#endef + +$(eval $(call HostBuild)) +$(eval $(call BuildPackage,heimdal-libs)) +$(eval $(call BuildPackage,heimdal-client)) +$(eval $(call BuildPackage,heimdal-server)) diff --git a/package/lean/heimdal/files/roken-h-process.pl b/package/lean/heimdal/files/roken-h-process.pl new file mode 100644 index 000000000..e797dd224 --- /dev/null +++ b/package/lean/heimdal/files/roken-h-process.pl @@ -0,0 +1,184 @@ +#!/usr/bin/perl + +use Getopt::Std; + +my $debug = 0; + +getopts('dc:p:o:') || die "foo"; + +if ($opt_d) { + $debug = 1; +} + +die "missing arg" if (!defined $opt_c || !defined $opt_p || !defined $opt_o); + +my %defines; +my $IN; +my $OUT; + +print "parse config.h\n" if ($debug); + +open IN, $opt_c || die "failed open ${opt_c}"; + +my @nesting; + +push @nesting, 1; + +while () { + if (m/\s*#ifdef\s+(.*)/) { + my $var = $1; + if (defined $defines{$var}) { + push @nesting, 1; + } else { + push @nesting, 0; + } + next; + } elsif (m/\s*#ifndef\s+(.*)/) { + my $var = $1; + if (defined $defines{$var}) { + push @nesting, 0; + } else { + push @nesting, 1; + } + next; + } elsif (m/\s*#else/) { + my $var = pop @nesting; + $var = !$var; + push @nesting, $var; + next; + } elsif ($nesting[$#nesting] and m/\s*#define\s+(\w+)\s+(\S+)/) { + my $res = $2; + $res = 1 if (!defined $res); + $defines{$1} = $res; + } +} + +close IN; + +if ($debug) { + foreach my $i (keys %defines) { + print "k: $i v: $defines{$i}\n"; + } +} + +open IN, "$opt_p" || die "failed open ${opt_p}"; +open OUT, ">$opt_o" || die "failed open ${opt_o}"; + +print "parse roken.h.in\n" if ($debug); + +print OUT "/* This is an OS dependent, generated file */\n"; +print OUT "\n"; +print OUT "\n"; +print OUT "#ifndef __ROKEN_H__\n"; +print OUT "#define __ROKEN_H__\n"; +print OUT "\n"; + +@nesting = (1); + +while () { + if (m/\s*#ifdef\s+(.*)/) { + my $var = $1; + if (defined $defines{$var}) { + push @nesting, 1; + } else { + push @nesting, 0; + } + next; + } elsif (m/\s*#ifndef\s+(.*)/) { + my $var = $1; + if (defined $defines{$var}) { + push @nesting, 0; + } else { + push @nesting, 1; + } + next; + } elsif (m/\s*#if\s+(.*)/) { + my $res = parse_if($1); + print "line = $res: $1\n" if ($debug); + push @nesting, $res; + next; + } elsif (m/\s*#elif\s+(.*)/) { + my $res = pop @nesting; + if ($res gt 0) { + $res = -1; + } else { + my $res = parse_if($1); + } + push @nesting, $res; + next; + } elsif (m/\s*#else/) { + my $var = pop @nesting; + $var = !$var; + push @nesting, $var; + next; + } elsif (m/\s*#endif/) { + pop @nesting; + next; + } + print "line: $_\n" if ($debug); + print "nesting dep $#{nesting}\n" if ($debug); + my $i = 0, $t = 1; + while ($i le $#nesting) { + $t = 0 if ($nesting[$i] le 0); + print "nesting $i val $nesting[$i] -> $t\n" if ($debug); + $i++; + } + if ($t) { + print OUT; + } +} + +print OUT "\n"; +print OUT "#endif /* __ROKEN_H__ */\n"; + + +close IN; + +exit 0; + +sub parse_if +{ + my ($neg, $var); + + $_ = shift; + + if (m/^\s*$/) { + print "end $_\n" if ($debug); + return 1; + } elsif (m/^\(([^&]+)\&\&(.*)\)\s*\|\|\s*\(([^&]+)\&\&(.*)\)$/) { + print "($1 and $2) or ($3 and $4)\n" if ($debug); + return ((parse_if($1) and parse_if($2)) or (parse_if($3) and parse_if($4))); + } elsif (m/^([^&]+)\&\&(.*)$/) { + print "$1 and $2\n" if ($debug); + return parse_if($1) and parse_if($2); + } elsif (m/^([^\|]+)\|\|(.*)$/) { + print "$1 or $2\n" if ($debug); + return (parse_if($1) or parse_if($2)); + } elsif (m/^\s*(\!)?\s*defined\((\w+)\)/) { + ($neg, $var) = ($1, $2); + print "def: ${neg}-defined(${var})\n" if ($debug); + my $res = defined $defines{$var}; + if ($neg eq "!") { + if ($res) { + $res = 0; + } else { + $res = 1; + } + } + print "res: $res\n" if ($debug); + return $res; + } elsif (m/^\s*(\!)?(\w+)/) { + ($neg, $var) = ($1, $2); + print "var: $neg $var\n" if ($debug); + my $res; + if (defined $defines{$var}) { + $res = $defines{$var}; + } else { + $res = 0; + } + $res = ! $res if ($neg =~ m/!/); + print "res: $res\n" if ($debug); + return $res; + } + die "failed parse: $_\n"; +} diff --git a/package/lean/heimdal/patches/001-snprintf-len.patch b/package/lean/heimdal/patches/001-snprintf-len.patch new file mode 100644 index 000000000..2b3c658f1 --- /dev/null +++ b/package/lean/heimdal/patches/001-snprintf-len.patch @@ -0,0 +1,16 @@ +--- a/lib/roken/snprintf.c ++++ b/lib/roken/snprintf.c +@@ -109,13 +109,8 @@ + + /* longest integer types */ + +-#ifdef HAVE_LONG_LONG +-typedef unsigned long long u_longest; +-typedef long long longest; +-#else + typedef unsigned long u_longest; + typedef long longest; +-#endif + + + diff --git a/package/lean/heimdal/patches/002-remove-unused-version.patch b/package/lean/heimdal/patches/002-remove-unused-version.patch new file mode 100644 index 000000000..9e25557e0 --- /dev/null +++ b/package/lean/heimdal/patches/002-remove-unused-version.patch @@ -0,0 +1,10 @@ +--- a/configure ++++ b/configure +@@ -31283,7 +31283,6 @@ + #ifndef VERSION_HIDDEN + #define VERSION_HIDDEN + #endif +-VERSION_HIDDEN const char *heimdal_long_version = "@(#)\$Version: $PACKAGE_STRING by @USER@ on @HOST@ ($host) @DATE@ \$"; + VERSION_HIDDEN const char *heimdal_version = "Heimdal 1.5.3"; + EOF + diff --git a/package/lean/heimdal/patches/010-configure-fix-cross-compiling.patch b/package/lean/heimdal/patches/010-configure-fix-cross-compiling.patch new file mode 100644 index 000000000..25120dbd4 --- /dev/null +++ b/package/lean/heimdal/patches/010-configure-fix-cross-compiling.patch @@ -0,0 +1,26 @@ +--- a/configure ++++ b/configure +@@ -1455,6 +1455,10 @@ + fi + fi + ++if test "${with_cross_tools+set}" = set; then ++ cross_compiling=yes ++fi ++ + ac_tool_prefix= + test -n "$host_alias" && ac_tool_prefix=$host_alias- + +@@ -28246,6 +28250,12 @@ + krb_cv_compile_et="no" + krb_cv_com_err_need_r="" + krb_cv_compile_et_cross=no ++ ++if test "${with_cross_tools+set}" = set; then ++ krb_cv_compile_et_cross=yes ++ krb_cv_com_err=yes ++fi ++ + if test "${COMPILE_ET}" = "compile_et"; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compile_et has the features we need" >&5 diff --git a/package/lean/heimdal/patches/100-build-fixes.patch b/package/lean/heimdal/patches/100-build-fixes.patch new file mode 100644 index 000000000..361237c8a --- /dev/null +++ b/package/lean/heimdal/patches/100-build-fixes.patch @@ -0,0 +1,42 @@ +--- a/kcm/cache.c ++++ b/kcm/cache.c +@@ -102,7 +102,7 @@ + for (p = ccache_head; p != NULL; p = p->next) { + if ((p->flags & KCM_FLAGS_VALID) == 0) + continue; +- if (memcmp(p->uuid, uuid, sizeof(uuid)) == 0) { ++ if (memcmp(p->uuid, uuid, sizeof(*uuid)) == 0) { + ret = 0; + break; + } +--- a/lib/hcrypto/engine.c ++++ b/lib/hcrypto/engine.c +@@ -88,7 +88,7 @@ + if(engine->destroy) + (*engine->destroy)(engine); + +- memset(engine, 0, sizeof(engine)); ++ memset(engine, 0, sizeof(*engine)); + engine->references = -1; + + +--- a/lib/hcrypto/md2.c ++++ b/lib/hcrypto/md2.c +@@ -130,5 +130,5 @@ + MD2_Update(m, pad, 16); + + memcpy(res, m->state, MD2_DIGEST_LENGTH); +- memset(m, 0, sizeof(m)); ++ memset(m, 0, sizeof(*m)); + } +--- a/lib/hcrypto/test_rand.c ++++ b/lib/hcrypto/test_rand.c +@@ -164,7 +164,7 @@ + + for (bit = 0; bit < 8; bit++) { + +- res = ((double)abs(len - bits[bit] * 2)) / (double)len; ++ res = abs(len - bits[bit] * 2) / (double)len; + if (res > 0.005) + errx(1, "head%d vs tail%d > 0.5%%%% %lf == %d vs %d", + bit, bit, res, len, bits[bit]); diff --git a/package/lean/luci-app-adbyby-plus/Makefile b/package/lean/luci-app-adbyby-plus/Makefile index 3a60dd9ab..4792bf7e8 100644 --- a/package/lean/luci-app-adbyby-plus/Makefile +++ b/package/lean/luci-app-adbyby-plus/Makefile @@ -10,7 +10,7 @@ LUCI_DEPENDS:=+adbyby +wget +ipset +coreutils +coreutils-nohup +dnsmasq-full LUCI_PKGARCH:=all PKG_NAME:=luci-app-adbyby-plus PKG_VERSION:=2.0 -PKG_RELEASE:=27 +PKG_RELEASE:=28 include $(TOPDIR)/feeds/luci/luci.mk diff --git a/package/lean/luci-app-adbyby-plus/root/usr/share/adbyby/blockip.conf b/package/lean/luci-app-adbyby-plus/root/usr/share/adbyby/blockip.conf index 66a76058b..55cb84b53 100644 --- a/package/lean/luci-app-adbyby-plus/root/usr/share/adbyby/blockip.conf +++ b/package/lean/luci-app-adbyby-plus/root/usr/share/adbyby/blockip.conf @@ -1 +1 @@ -1.1.1.1 +2.2.2.2 diff --git a/package/lean/luci-app-amule/root/etc/uci-defaults/luci-amule b/package/lean/luci-app-amule/root/etc/uci-defaults/luci-amule index 11b9b9cda..e1c0c0842 100755 --- a/package/lean/luci-app-amule/root/etc/uci-defaults/luci-amule +++ b/package/lean/luci-app-amule/root/etc/uci-defaults/luci-amule @@ -14,7 +14,6 @@ do grep -e ":$gid:" ${IPKG_INSTROOT}/etc/passwd || ( \ echo "amule:x:$gid:amule" >> ${IPKG_INSTROOT}/etc/group ; \ echo "amule:x:$gid:$gid:amule:/var/run/amule:/bin/false" >> ${IPKG_INSTROOT}/etc/passwd ) - sleep 1 done mkdir -p ${IPKG_INSTROOT}/etc/amule/ diff --git a/package/lean/luci-app-oscam/Makefile b/package/lean/luci-app-brook-pro/Makefile similarity index 50% rename from package/lean/luci-app-oscam/Makefile rename to package/lean/luci-app-brook-pro/Makefile index 70a12e865..aaae25d5a 100644 --- a/package/lean/luci-app-oscam/Makefile +++ b/package/lean/luci-app-brook-pro/Makefile @@ -1,16 +1,15 @@ -# -# Copyright (C) 2008-2014 The LuCI Team +# Copyright (C) 2016 Openwrt.org # # This is free software, licensed under the Apache License, Version 2.0 . # include $(TOPDIR)/rules.mk -LUCI_TITLE:=LuCI for OSCAM -LUCI_DEPENDS:=+oscam +LUCI_TITLE:=LuCI support for Brook +LUCI_DEPENDS:=+iptables-mod-tproxy +kmod-ipt-tproxy +ip +ipset-lists +brook +pdnsd-alt +coreutils +coreutils-base64 +coreutils-nohup +dnsmasq-full LUCI_PKGARCH:=all PKG_VERSION:=1.0 -PKG_RELEASE:=1 +PKG_RELEASE:=3 include $(TOPDIR)/feeds/luci/luci.mk diff --git a/package/lean/luci-app-brook-pro/luasrc/controller/brook.lua b/package/lean/luci-app-brook-pro/luasrc/controller/brook.lua new file mode 100644 index 000000000..b891c2631 --- /dev/null +++ b/package/lean/luci-app-brook-pro/luasrc/controller/brook.lua @@ -0,0 +1,9 @@ +module("luci.controller.brook", package.seeall) +function index() + if not nixio.fs.access("/etc/config/brook") then + return + end + local page + page = entry({"admin", "services", "brook"}, cbi("brook"), _("Brook Pro")) + page.dependent = true +end diff --git a/package/lean/luci-app-brook-pro/luasrc/model/cbi/brook.lua b/package/lean/luci-app-brook-pro/luasrc/model/cbi/brook.lua new file mode 100644 index 000000000..3efe70e14 --- /dev/null +++ b/package/lean/luci-app-brook-pro/luasrc/model/cbi/brook.lua @@ -0,0 +1,180 @@ + +local fs = require "nixio.fs" +local NXFS = require "nixio.fs" +local WLFS = require "nixio.fs" +local SYS = require "luci.sys" +local ND = SYS.exec("cat /etc/gfwlist/china-banned | wc -l") +local conf = "/etc/brook/base-gfwlist.txt" +local watch = "/tmp/brook_watchdog.log" +local dog = "/tmp/brookpro.log" + +local Status + +if SYS.call("pidof brook > /dev/null") == 0 then + Status = translate("Brook is Running") +else + Status = translate("Brook is Not Running") +end + +m = Map("brook") +m.title = translate("Brook Transparent Proxy") +m.description = translate("A fast secure tunnel proxy that help you get through firewalls on your router") + +s = m:section(TypedSection, "brook") +s.anonymous = true +s.description = translate(string.format("%s

    ", Status)) + +-- --------------------------------------------------- + +s:tab("basic", translate("Base Setting")) + + +switch = s:taboption("basic",Flag, "enabled", translate("Enable")) +switch.rmempty = false + +proxy_mode = s:taboption("basic",ListValue, "proxy_mode", translate("Proxy Mode")) +proxy_mode:value("M", translate("Base on GFW-List Auto Proxy Mode(Recommend)")) +proxy_mode:value("S", translate("Bypassing China Manland IP Mode(Be caution when using P2P downloadï¼)")) +proxy_mode:value("G", translate("Global Mode")) +proxy_mode:value("V", translate("Overseas users watch China video website Mode")) + +cronup = s:taboption("basic", Flag, "cron_mode", translate("Auto Update GFW-List"), + translate(string.format("GFW-List Lines: %s Lines", ND))) +cronup.default = 0 +cronup.rmempty = false + +updatead = s:taboption("basic", Button, "updatead", translate("Manually force update GFW-List"), translate("Note: It needs to download and convert the rules. The background process may takes 60-120 seconds to run.
    After completed it would automatically refresh, please do not duplicate click!")) +updatead.inputtitle = translate("Manually force update GFW-List") +updatead.inputstyle = "apply" +updatead.write = function() + SYS.call("nohup sh /etc/brook/up-gfwlist.sh > /tmp/gfwupdate.log 2>&1 &") +end + +safe_dns_tcp = s:taboption("basic",Flag, "safe_dns_tcp", translate("DNS uses TCP"), + translate("Through the server transfer mode inquires DNS pollution prevention (Safer and recommended)")) +safe_dns_tcp.rmempty = false +-- safe_dns_tcp:depends("more", "1") + +-- more_opt = s:taboption("basic",Flag, "more", translate("More Options"), +-- translate("Options for advanced users")) + +-- timeout = s:taboption("basic",Value, "timeout", translate("Timeout")) +-- timeout.datatype = "range(0,10000)" +-- timeout.placeholder = "60" +-- timeout.optional = false +-- timeout:depends("more", "1") + +-- safe_dns = s:taboption("basic",Value, "safe_dns", translate("Safe DNS"), +-- translate("8.8.8.8 or 8.8.4.4 is recommended")) +-- safe_dns.datatype = "ip4addr" +-- safe_dns.optional = false +-- safe_dns:depends("more", "1") + +-- safe_dns_port = s:taboption("basic",Value, "safe_dns_port", translate("Safe DNS Port"), +-- translate("Foreign DNS on UDP port 53 might be polluted")) +-- safe_dns_port.datatype = "range(1,65535)" +-- safe_dns_port.placeholder = "53" +-- safe_dns_port.optional = false +-- safe_dns_port:depends("more", "1") + +--fast_open =s:taboption("basic",Flag, "fast_open", translate("TCP Fast Open"), +-- translate("Enable TCP fast open, only available on kernel > 3.7.0")) + + + +s:tab("main", translate("Server Setting")) + +server = s:taboption("main",Value, "server", translate("Server Address")) +server.optional = false +server.datatype = "host" +server.rmempty = false + +server_port = s:taboption("main",Value, "server_port", translate("Server Port")) +server_port.datatype = "range(1,65535)" +server_port.optional = false +server_port.rmempty = false + +password = s:taboption("main",Value, "password", translate("Password")) +password.password = true + +s:tab("list", translate("User-defined GFW-List")) +gfwlist = s:taboption("list", TextValue, "conf") +gfwlist.description = translate("
    (!)Note: When the domain name is entered and will automatically merge with the online GFW-List. Please manually update the GFW-List list after applying.") +gfwlist.rows = 13 +gfwlist.wrap = "off" +gfwlist.cfgvalue = function(self, section) + return NXFS.readfile(conf) or "" +end +gfwlist.write = function(self, section, value) + NXFS.writefile(conf, value:gsub("\r\n", "\n")) +end + +local addipconf = "/etc/brook/addinip.txt" + +s:tab("addip", translate("GFW-List Add-in IP")) +gfwaddin = s:taboption("addip", TextValue, "addipconf") +gfwaddin.description = translate("
    (!)Note: IP add-in to GFW-List. Such as Telegram Messenger") +gfwaddin.rows = 13 +gfwaddin.wrap = "off" +gfwaddin.cfgvalue = function(self, section) + return NXFS.readfile(addipconf) or "" +end +gfwaddin.write = function(self, section, value) + NXFS.writefile(addipconf, value:gsub("\r\n", "\n")) +end + +s:tab("status", translate("Status and Tools")) +s:taboption("status", DummyValue,"opennewwindow" , + translate("")) + + +s:tab("watchdog", translate("Watchdog Log")) +log = s:taboption("watchdog", TextValue, "sylogtext") +log.template = "cbi/tvalue" +log.rows = 13 +log.wrap = "off" +log.readonly="readonly" + +function log.cfgvalue(self, section) + SYS.exec("[ -f /tmp/brook_watchdog.log ] && sed '1!G;h;$!d' /tmp/brook_watchdog.log > /tmp/brookpro.log") + return nixio.fs.readfile(dog) +end + +function log.write(self, section, value) + value = value:gsub("\r\n?", "\n") + nixio.fs.writefile(dog, value) +end + + + +t=m:section(TypedSection,"acl_rule",translate("Client Proxy Mode Settings"), +translate("Proxy mode settings can be set to specific LAN clients ( No Proxy, Global Proxy, Game Mode) . Does not need to be set by default.")) +t.template="cbi/tblsection" +t.sortable=true +t.anonymous=true +t.addremove=true +e=t:option(Value,"ipaddr",translate("IP Address")) +e.width="40%" +e.datatype="ip4addr" +e.placeholder="0.0.0.0/0" +luci.ip.neighbors({ family = 4 }, function(entry) + if entry.reachable then + e:value(entry.dest:string()) + end +end) + +e=t:option(ListValue,"filter_mode",translate("Proxy Mode")) +e.width="40%" +e.default="disable" +e.rmempty=false +e:value("disable",translate("No Proxy")) +e:value("global",translate("Global Proxy")) +e:value("game",translate("Game Mode")) + +-- --------------------------------------------------- +local apply = luci.http.formvalue("cbi.apply") +if apply then + os.execute("/etc/init.d/brookpro restart >/dev/null 2>&1 &") +end + +return m diff --git a/package/lean/luci-app-brook-pro/po/zh-cn/brook.po b/package/lean/luci-app-brook-pro/po/zh-cn/brook.po new file mode 100644 index 000000000..3e382ccb8 --- /dev/null +++ b/package/lean/luci-app-brook-pro/po/zh-cn/brook.po @@ -0,0 +1,114 @@ +msgid "Brook is Running" +msgstr "Brook 正在è¿è¡Œ" + +msgid "Brook is Not Running" +msgstr "Brook 没有è¿è¡Œ" + +msgid "Brook Transparent Proxy" +msgstr "Brook é€æ˜Žä»£ç†" + +msgid "A fast secure tunnel proxy that help you get through firewalls on your router" +msgstr "一个快速安全隧é“代ç†ï¼Œå¸®åŠ©æ‚¨ç©¿è¿‡é˜²ç«å¢™" + +msgid "Base Setting" +msgstr "基本设置" + +msgid "Proxy Mode" +msgstr "代ç†æ¨¡å¼" + +msgid "Base on GFW-List Auto Proxy Mode(Recommend)" +msgstr "基于GFW-List自动代ç†(推è)" + +msgid "Bypassing China Manland IP Mode(Be caution when using P2P downloadï¼)" +msgstr "绕过中国大陆IP地å€(P2P 下载慎用ï¼)" + +msgid "Global Mode" +msgstr "全局代ç†" + +msgid "Overseas users watch China video website Mode" +msgstr "海外用户回国看视频" + +msgid "Auto Update GFW-List" +msgstr "自动更新GFW-List" + +msgid "Manually force update GFW-List" +msgstr "手动强制更新GFW-List" + +msgid "DNS uses TCP" +msgstr "å¯ç”¨DNS TCP防污染" + +msgid "Through the server transfer mode inquires DNS pollution prevention (Safer and recommended)" +msgstr "往国外的DNS请求将通过æœåŠ¡å™¨ä¸­è½¬å‘出(更安全,推è)" + +msgid "Server Setting" +msgstr "æœåŠ¡å™¨è®¾ç½®" + +msgid "Server Address" +msgstr "æœåŠ¡å™¨åœ°å€ï¼ˆæ”¯æŒåŸŸå)" + +msgid "Server Port" +msgstr "æœåŠ¡å™¨ç«¯å£" + +msgid "Password" +msgstr "密ç " + +msgid "Encryption Method" +msgstr "加密" + +msgid "Protocol" +msgstr "åè®®" + +msgid "Protocol Param" +msgstr "åè®®å‚æ•°" + +msgid "Obfs Param" +msgstr "æ··æ·†" + +msgid "Plug-in parameters" +msgstr "æ’件å‚æ•°" + +msgid "Confusing plug-in parameters" +msgstr "æ··æ·†å‚æ•°" + +msgid "Incorrect use of this parameter will cause IP to be blocked. Please use it with care" +msgstr "ä¸æ­£ç¡®çš„使用å‚æ•°å¯èƒ½ä¼šå¯¼è‡´IP被å°ï¼Œè¯·æ³¨æ„使用" + +msgid "User-defined GFW-List" +msgstr "用户自定义GFW-List" + +msgid "
    (!)Note: When the domain name is entered and will automatically merge with the online GFW-List. Please manually update the GFW-List list after applying." +msgstr "用户自定义GFW-List将会和自动更新的自动åˆå¹¶ã€‚如果è¦æ–°åŠ å…¥åŸŸå马上生效,请应用åŽç‚¹å‡»æ‰‹åŠ¨å¼ºåˆ¶æ›´æ–°GFW-List" + +msgid "Status and Tools" +msgstr "状æ€ä¸Žå·¥å…·" + +msgid "Watchdog Log" +msgstr "守护日志" + +msgid "Client Proxy Mode Settings" +msgstr "客户端代ç†æ¨¡å¼è®¾ç½®" + +msgid "Proxy mode settings can be set to specific LAN clients ( No Proxy, Global Proxy, Game Mode) . Does not need to be set by default." +msgstr "å¯ä»¥ä¸ºå±€åŸŸç½‘客户端分别设置ä¸åŒçš„代ç†æ¨¡å¼ ( ä¸ä»£ç†, 全局代ç†, 游æˆæ¨¡å¼).默认无需设置" + +msgid "GFW-List Add-in IP" +msgstr "GFW-List附加IP" + +msgid "
    (!)Note: IP add-in to GFW-List. Such as Telegram Messenger" +msgstr "
    (!)注æ„:有些应用使用IP而ä¸æ˜¯åŸŸå,例如 Telegram Messenger ,您需è¦æŠŠIP地å€åŠ å…¥è¿™é‡Œ" + +msgid "No Proxy" +msgstr "ä¸ä»£ç†" + +msgid "Global Proxy" +msgstr "全局代ç†" + +msgid "Game Mode" +msgstr "游æˆæ¨¡å¼" + + + + + + + diff --git a/package/lean/luci-app-brook-pro/root/etc/brook.include b/package/lean/luci-app-brook-pro/root/etc/brook.include new file mode 100755 index 000000000..98cc6f43f --- /dev/null +++ b/package/lean/luci-app-brook-pro/root/etc/brook.include @@ -0,0 +1,11 @@ +#!/bin/sh + +brook_enable=$(uci get brook.@brook[0].enabled 2>/dev/null) + +if [ $brook_enable -eq 1 ]; then + if pidof brook>/dev/null; then + /etc/init.d/brookpro reload + else + /etc/init.d/brookpro restart + fi +fi diff --git a/package/lean/luci-app-brook-pro/root/etc/brook/addinip.txt b/package/lean/luci-app-brook-pro/root/etc/brook/addinip.txt new file mode 100644 index 000000000..64e2f9bb8 --- /dev/null +++ b/package/lean/luci-app-brook-pro/root/etc/brook/addinip.txt @@ -0,0 +1,7 @@ +149.154.160.0/20 +149.154.164.0/22 +149.154.168.0/21 +67.198.55.0/24 +91.108.4.0/22 +91.108.56.0/22 +109.239.140.0/24 diff --git a/package/lean/luci-app-brook-pro/root/etc/brook/base-gfwlist.txt b/package/lean/luci-app-brook-pro/root/etc/brook/base-gfwlist.txt new file mode 100644 index 000000000..9d63f387a --- /dev/null +++ b/package/lean/luci-app-brook-pro/root/etc/brook/base-gfwlist.txt @@ -0,0 +1,2940 @@ +0rz.tw +0to255.com +10musume.com +123rf.com +12bet.com +12vpn.com +141hongkong.com +173ng.com +1984bbs.com +1984bbs.org +1-apple.com.tw +1bao.org +1eew.com +1pondo.tv +2000fun.com +2008xianzhang.info +21andy.com +247realmedia.com +24smile.org +2-hand.info +2mdn.net +2shared.com +301works.org +315lz.com +32red.com +365singles.com.ar +36rain.com +4bluestones.biz +4chan.org +4pppc.gov.tw +4shared.com +4sq.com +51.ca +5i01.com +5maodang.com +64tianwang.com +64wiki.com +666kb.com +6park.com +7capture.com +881903.com +888.com +89-64.org +9001700.com +91porn.com +921.gov.tw +92ccav.com +9bis.com +9bis.net +9city.me +a5.com.ru +abc.pp.ru +abitno.linpie.com +ablwang.com +aboluowang.com +aboutgfw.com +acgkj.com +ac.jiruan.net +ac.playstation.net +actimes.com.au +aculo.us +ad1.nownews.com +addictedtocoffee.de +ads.backchina.com +adultfriendfinder.com +adultkeep.net +advanscene.com +advertfan.com +aec.gov.tw +aenhancers.com +af.mil +aftygh.gov.tw +aide.gov.tw +aiph.net +aisex.com +ait.org.tw +aiweiweiblog.com +aiweiwei.com +ajaxplorer.info +akamaihd.net +akiba-online.com +alabout.com +alasbarricadas.org +alexlur.org +aliengu.com +alkasir.com +allaboutalpha.com +allgirlsallowed.org +alliance.org.hk +allinfa.com +allinfo.com +allmovie.com +allonlinux.free.fr +all-that-is-interesting.com +al-qimmah.net +alternate-tools.com +altrec.com +alvinalexander.com +alwaysdata.com +alwaysdata.net +am730.com.hk +amazonaws.com +ameblo.jp +americangreencard.com +amiblockedornot.com +amnesty.org +amnestyusa.org +amoiist.com +amzs.me +analyze-v.com +anchorfree.com +andfaraway.net +android.com +angularjs.org +animecrazy.net +anobii.com +anontext.com +anonymizer.com +a-normal-day.com +answering-islam.org +anthonycalzadilla.com +anti.anti.cnn.googlepages.com +antidrm.hpg.ig.com.br +antiwave.net +aobo.com.au +aolchannels.aol.com +aomiwang.com +apetube.com +apiary.io +apidocs.linksalpha.com +apigee.com +api.linksalpha.com +api.proxlet.com +api.supertweet.net +app.heywire.com +app.hkatvnews.com +appledaily.com +appledaily.com.tw +apps.hloli.net +appspot.com +archive.is +archive.org +arctosia.com +areca-backup.org +army.mil +arte.gov.tw +art-or-porn.com +artsy.net +asahichinese.com +asdfg.jp +asiafriendfinder.com +asiaharvest.org +asianews.it +asianwomensfilm.de +askstudent.com +askynz.net +assembla.com +astonmartinnews.com +atchinese.com +atc.org.au +atgfw.org +atj.org.tw +atlaspost.com +atnext.com +autoproxy.org +avaaz.org +avdb.in +avidemux.org +avoision.com +awardwinningfjords.com +axureformac.com +babynet.com.hk +backchina.com +backpackers.com.tw +badassjs.com +badoo.com +baidu.jp +baixing.me +bannedbook.org +barnabu.co.uk +basetimesheightdividedby2.com +bayvoice.net +bbcchinese.com +bbc.com +bbc.co.uk +bbci.co.uk +bbcimg.co.uk +bbc.in +bbg.gov +bbs2.newsgroup.la +bbs.ecstart.com +bbsfeed.com +bbs.kimy.com.tw +bbsland.com +bbs.morbell.com +bbs.mychat.to +bbs.newsgroup.la +bbs.ozchinese.com +bbs.qmzdd.com +bbs.sina.com +bbs.skykiwi.com +bbs.tuitui.info +bb.ttv.com.tw +bcc.com.tw +bcchinese.net +bdhr.gov.tw +bd.zhe.la +bebo.com +beeg.com +beijing1989.com +beijingspring.com +benjaminste.in +berlintwitterwall.com +bestforchina.org +bestvpnservice.com +bet365.com +beta.iset.com.tw +beta.usejump.com +betfair.com +bettween.com +betvictor.com +bewww.net +beyondfirewall.com +bfnn.org +biantailajiao.com +biantailajiao.in +bigfools.com +bignews.org +bigsound.org +bill2-software.com +billywr.com +bill.zhong.pp.ru +bipic.net +bitcointalk.org +bit.ly +bitly.com +bitshare.com +bjzc.org +blinkx.com +blinw.com +blip.tv +blockcn.com +blog.birdhouseapp.com +blog.bitly.com +blogblog.com +blog.boxcar.io +blogcatalog.com +blog.davidziegler.net +blog.dayoneapp.com +blog.de +blog.dribbble.com +blog.exblog.co.jp +blog.expofutures.com +blog.fizzik.com +blog.foolsmountain.com +blogger.com +blog.gowalla.com +blog.hotpotato.com +blog.ifttt.com +blogimg.jp +blog.instagram.com +blog.instapaper.com +blog.iphone-dev.org +blog.istef.info +blog.jackjia.com +blog.joeyrobert.org +blog.kangye.org +blog.kickstarter.com +blog.kl.am +blog.klip.me +blog.lester850.info +blog.lightbox.com +bloglines.com +bloglovin.com +blog.mongodb.org +blog.openinkpot.org +blog.palm.com +blog.path.com +blog.pathtosharepoint.com +blog.pchome.com.tw +blog.pentalogic.net +blog.pikchur.com +blog.pilotmoon.com +blog.redren.com +blog.rockmelt.com +blog.romanandreg.com +blog.s135.com +blogs.icerocket.com +blog.sina.com.tw +blog.sogoo.org +blog.sparrowmailapp.com +blogspot.com +blogspot.co.uk +blogspot.de +blogspot.fr +blogspot.in +blogspot.jp +blogs.tampabay.com +blog.summify.com +blogs.yahoo.co.jp +blog.syx86.cn +blog.syx86.com +blog.taragana.com +blogtd.net +blogtd.org +blog.tiney.com +blog.topify.com +blog.usa.gov +blog.xuite.net +blog.youthwant.com.tw +blog.youxu.info +bloodshed.net +bloomberg.cn +bloomberg.com +bloomberg.de +bloomfortune.com +bmediaasia.com +bnrmetal.com +boardreader.com +bobulate.com +bolin.netfirms.com +bonbonme.com +bonjourlesgeeks.com +boobstagram.com +books.com.tw +bookshelfporn.com +botanwang.com +bot.nu +bowenpress.com +boxunblog.com +boxunclub.com +boxun.com +boxun.tv +bralio.com +branch.com +brandonhutchinson.com +braumeister.org +break.com +breakingtweets.com +briefdream.com +brightcove.com +brightkite.com +brizzly.com +broadbook.com +br.st +brucewang.net +bt95.com +btdigg.org +btrd.net +budaedu.org +bugclub.org +builtwithbootstrap.com +bullogger.com +bullog.org +businesstimes.com.cn +businessweek.com +buugaa.com +buy.yahoo.com.tw +buzzurl.jp +bwbx.io +bwsj.hk +bx.tl +c1522.mooo.com +cacnw.com +cactusvpn.com +cafepress.com +cahr.org.tw +calameo.com +calebelston.com +cams.com +cams.org.sg +canadameet.com +canyu.org +caobian.info +caochangqing.com +cao.im +cari.com.my +catch22.net +catfightpayperview.xxx +catholic.org.hk +catholic.org.tw +cbs.ntu.edu.tw +cc9007.spaces.live.com +ccavtop10.com +ccdtr.org +ccim.org +cclife.org +ccthere.com +cctongbao.com +ccue.ca +ccue.com +cdig.info +cdjp.org +cdnews.com.tw +cdn.printfriendly.com +cdp1998.org +cdp2006.org +cdp.sinica.edu.tw +cdpusa.org +cdpweb.org +cdpwu.org +cdw.com +cecc.gov +cellulo.info +cenci.tk +cenews.eu +centralnation.com +centurys.net +c-est-simple.com +cfhks.org.hk +cftfc.com +cgdepot.org +chandoo.org +change.org +changp.com +chaos.e-spacy.com +chapm25.com +chartbeat.net +chaturbate.com +chccc.gov.tw +chengmingmag.com +chenguangcheng.com +chenpokong.com +chenyehao.spaces.live.com +cherrysave.com +chevronwp7.com +chicagoncmtv.com +china101.com +china21.com +china21.org +china5000.us +chinaaffairs.org +chinaaid.me +chinaaid.net +chinaaid.org +chinaaid.us +chinachange.org +chinachannel.hk +chinacomments.org +chinadigitaltimes.net +chinaeweekly.com +chinafreepress.org +chinagate.com +chinageeks.org +chinagfw.org +chinagreenparty.org +china-green-party.spaces.live.com +chinahush.com +chinainperspective.com +chinainperspective.net +chinainperspective.org +chinainterimgov.org +chinalawandpolicy.com +chinalawtranslate.com +chinamule.com +chinamz.org +chinarightsia.org +chinasocialdemocraticparty.com +chinaso.com +chinasoul.org +chinatimes.com +chinatweeps.com +chinaway.org +china-week.com +chinaworker.info +chinaxchina.com +chinayouth.org.hk +chinayuanmin.org +chinesedailynews.com +chinese.engadget.com +chinese-hermit.net +chinese-memorial.org +chinesen.de +chinesenewsnet.com +chinesepen.org +chinese.rnw.nl +chinese.soifind.com +chinesetalks.net +chinese.wsj.com +chingcheong.com +chn.chosun.com +chrispederick.com +chrispederick.net +christianstudy.com +christiantimes.org.hk +christusrex.org +chrlawyers.hk +chrlcg-hk.org +chromeadblock.com +chrome.com +ch.shvoong.com +chubun.com +chuizi.net +chukuang.gov.tw +circlethebayfortibet.org +citizenlab.org +citizensradio.org +city9x.com +civicparty.hk +civilhrfront.org +civilmedia.tw +cjb.net +ck101.com +classicalguitarblog.net +clb.org.hk +cl.d0z.net +clientsfromhell.net +clipfish.de +cl.ly +cloudfront.net +club.backchina.com +cms.gov +cmule.com +cn2.streetvoice.com +cna.com.tw +cnavista.com.tw +cn.calameo.com +cn.dayabook.com +cnd.org +cn.fmnnow.com +cn.ibtimes.com +cnn.com +cn.news.cnyes.com +cn.streetvoice.com +cn.uncyclopedia.wikia.com +cn.voa.mobi +cochina.org +cocoapods.org +cocoa.zonble.net +code1984.com +codeboxapp.com +codeshare.io +collateralmurder.com +collateralmurder.org +comefromchina.com +comnews.gio.gov.tw +compileheart.com +connectedchina.reuters.com +connect.facebook.net +conoyo.com +contactmagazine.net +contests.twilio.com +conviva.com +cookingtothegoodlife.com +coolaler.com +coolder.com +coolloud.org.tw +corpus4u.org +corumcollege.com +cotweet.com +couchdbwiki.com +coveringweb.com +cp-house.gov.tw +cpj.org +crackle.com +crd-net.org +creaders.net +cromotc.nat.gov.tw +crossthewall.net +csdparty.com +c-spanvideo.org +css.pixnet.in +csuchen.de +cts.com.tw +cubicle17.com +cuhkacs.org +cuihua.org +cuiweiping.net +culture.tw +curvefish.com +cwb.gov.tw +cyanogenmod.org +cyberghost.natado.com +cyberghostvpn.com +cycab.gov.tw +cydia.ifuckgfw.com +cynscribe.com +cytode.us +dabr.co.uk +dabr.me +dabr.mobi +dadazim.com +dadi360.com +dafagood.com +dafahao.com +dailidaili.com +dailymotion.com +dailynews.sina.com +dajiyuan.com +dajiyuan.eu +dajusha.baywords.com +dalailama.com +dalailama.ru +dalailamaworld.com +dalianmeng.org +danke4china.net +danwei.org +daolan.net +dapu-house.gov.tw +darpa.mil +date.fm +davidslog.com +daxa.cn +dayaarmongol.ning.com +daylife.com +ddc.com.tw +deck.ly +default.secureserver.net +delcamp.net +delicious.com +democrats.org +demo.opera-mini.net +derekhsu.homeip.net +de-sci.org +designerol.com +destiny.xfiles.to +deutsche-welle.de +dev102.com +developers.box.net +deviantart.com +deviantart.net +devio.us +devpn.com +dfas.mil +df.gov.tw +diaoyuislands.org +digitalnomadsproject.org +diigo.com +dimitrik.free.fr +dipity.com +directcreative.com +discuss.com.hk +disp.cc +dit-inc.us +dizhidizhi.com +djangosnippets.org +dl.box.net +dl-laby.jp +dl.playstation.net +dlsite.com +dmcdn.net +dmtip.gov.tw +dns2go.com +dnscrypt.org +docstoc.com +dojin.com +dok-forum.net +dolc.de +dollf.com +domain.club.tw +domainhelp.search.com +dongde.com +dongtaiwang.com +dongtaiwang.net +dongyangjing.com +dontfilter.us +dontmovetochina.com +dotheyfolloweachother.com +dotplane.com +dotsub.com +doubleaf.com +doubleclick.net +dougscripts.com +dowei.org +download.syniumsoftware.com +doxygen.org +dphk.org +dpp.org.tw +drewolanoff.com +drgan.net +dropbox.com +dropboxusercontent.com +drsunacademy.com +drtuber.com +dscn.info +dtiblog.com +dtic.mil +dtiserv2.com +duckduckgo.com +duckload.com +duckmylife.com +duihuahrjournal.org +duihua.org +duoweitimes.com +duping.net +duplicati.com +dupola.com +dupola.net +dvorak.org +dw.de +dwnews.com +dwnews.net +dw-world.com +dw-world.de +dy24k.info +dynawebinc.com +dyndns.org +dzze.com +e123.hk +eamonnbrennan.com +earthquake.usgs.gov +easy-share.com +ebookbrowse.com +ebookee.com +echofon.com +ecministry.net +edicypages.com +edoors.com +edubridge.com +eevpn.com +efcc.org.hk +efksoft.com +efmoe.com +e-gold.com +eic-av.com +e-info.org.tw +electionsmeter.com +elpais.com +eltondisney.com +emacsblog.org +embr.in +emory.edu +emule-ed2k.com +emuparadise.me +enewstree.com +en.favotter.net +englishfromengland.co.uk +entermap.com +en.wikipedia.org +epochtimes-bg.com +epochtimes.co.il +epochtimes.co.kr +epochtimes.com +epochtimes.de +epochtimes.fr +epochtimes.ie +epochtimes.jp +epochtimes-romania.com +epochtimes.ru +epochtimes.se +epochtimestr.com +epochweekly.com +erabaru.net +erepublik.com +erepublik.net +erights.net +eriversoft.com +ernestmandel.org +etaiwannews.com +etizer.org +etools.ncol.com +e-traderland.net +etraining.gov.tw +ettoday.net +evchk.wikia.com +eventful.com +everyday-carry.com +exblog.jp +expatshield.com +exploader.net +extremetube.com +eyespirit.info +eyevio.jp +eyny.com +ezpc.tk +ezpeer.com +facebook.com +facebook.net +facesofnyfw.com +fail.hk +faiththedog.info +fakku.net +falsefire.com +falunart.org +falundafamuseum.org +falundafa.org +falunhr.org +famunion.com +fangbinxing.com +fangeming.com +fanglizhi.info +fangongheike.com +fangong.org +fan-qiang.com +fanqianghou.com +fanqiangyakexi.net +fanswong.com +fanyue.info +fapdu.com +farwestchina.com +farxian.com +fastpic.ru +faststone.org +favorious.com +favstar.fm +fawanghuihui.org +faydao.com +fbcdn.net +fb.com +fb.me +fbsbx.com +fc2china.com +fc2.com +f.cl.ly +fdc89.jp +feedbooks.mobi +feedburner.com +feeds2.feedburner.com +feeds.feedburner.com +feedzshare.com +feelssh.com +feer.com +felixcat.net +feministteacher.com +fengzhenghu.com +fetchvideo.com +ff.im +fflick.com +fgmtv.net +fgmtv.org +filefactory.com +files2me.com +fileserve.com +fillthesquare.org +finalion.jp +findbook.tw +finler.net +fireofliberty.org +firstfivefollowers.com +flecheinthepeche.fr +fleshbot.com +flickr.com +flickrhivemind.net +flightcaster.com +flowerofhappiness.spaces.live.com +focustaiwan.tw +focusvpn.com +fofg.org +fooooo.com +footwiball.com +forum.baby-kingdom.com +forum.cyberctm.com +forum.idsam.com +forum.iset.com.tw +forum.my903.com +forum.mymaji.com +forum.newsgroup.la +forum.nownews.com +forum.omy.sg +forum.palmislife.com +forum.pchome.com.tw +forum.setty.com.tw +forum.sina.com.hk +forum.slime.com.tw +forum.tvb.com +forum.yorkbbs.ca +fotop.net +fourface.nodesnoop.com +fourthinternational.org +foxdie.us +foxsub.com +foxtang.com +fqrouter.com +franklc.com +freakshare.com +fredwilson.vc +free4u.com.ar +freealim.com +freechal.com +freedomhouse.org +free.fr +freegao.com +freegateget.googlepages.com +free-gate.org +free-hada-now.org +freelotto.com +freeman2.com +freemoren.com +freemorenews.com +freenet-china.org +freenetproject.org +freenewscn.com +freeopenvpn.com +freeoz.org +free-ssh.com +freessh.us +freetibet.org +freevpn.nl +freewallpaper4.me +freewebs.com +freeweibo.com +freexinwen.com +freeyoutubeproxy.net +friendfeed.com +friendfeed-media.com +fring.com +fringenetwork.com +frommel.net +frontlinedefenders.org +fscked.org +fsurf.com +ftchinese.com +fuckcnnic.net +fuckgfw.com +fuckgfw.org +fulue.com +funf.tw +funp.com +furinkan.com +furl.net +futurechinaforum.org +futureme.org +futuremessage.org +fuyin.net +fw.cm +fxnetworks.com +fzh999.com +fzh999.net +gabocorp.com +gaeproxy.com +gaeproxy.googlecode.com +galenwu.com +game735.com +gamebase.com.tw +gamer.com.tw +gamez.com.tw +ganges.com +gaoming.net +gaopi.net +gaozhisheng.net +gaozhisheng.org +gardennetworks.com +gardennetworks.org +gartlive.com +gather.com +gaymap.cc +gazotube.com +gcc.org.hk +gclooney.com +g.co +gcpnews.com +gdbt.net +gdzf.org +geek-art.net +geekerhome.com +geekmade.co.uk +geekmanuals.com +generesis.com +genuitec.com +geocities.co.jp +geocities.com +geocities.jp +geohot.com +geometrictools.com +getchu.com +getcloudapp.com +get-digital-help.com +getfoxyproxy.org +getfreedur.com +getiton.com +getjetso.com +getlantern.org +getsmartlinks.com +getsocialscope.com +gfwinterceptor.googlecode.com +gfw.org.ua +ggpht.com +ggssl.com +ghost.org +ghut.org +giga-web.jp +gigporno.ru +gimpshop.com +girlbanker.com +github.com +git-scm.com +givemesomethingtoread.com +glennhilton.com +globaljihad.net +globalmuseumoncommunism.org +globalrescue.net +globalvoicesonline.org +gmail.com +gmbd.cn +gmhz.org +gmodules.com +gmozomg.izihost.org +gnci.org.hk +goagent.biz +goagent.googlecode.com +goagentplus.com +godfootsteps.org +golang.org +goldbetsports.com +goldwave.com +gongmeng.info +gongm.in +gongminliliang.com +gongwt.com +goodreaders.com +goodreads.com +goofind.com +goo.gl +googleadservices.com +google-analytics.com +googleapis.com +googlecode.com +google.co.jp +google.com +google.com.hk +google.com.sg +google.com.tw +google.com.uk +googledomains.com +googledrive.com +googleearth.com +googlehosted.com +googlelabs.com +googlemail.com +googleplus.com +googlesile.com +googlesource.com +googlesyndication.com +googletagmanager.com +googletagservices.com +googleusercontent.com +googlevideo.com +gopetition.com +gospelherald.com +gov.tw +gpass1.com +grandtrial.org +graphis.ne.jp +gravatar.com +graylog2.org +grb.gov.tw +greatfire.org +greatfirewall.biz +great-firewall.com +greatfirewallofchina.net +greatfirewallofchina.org +great-roc.org +greatroc.org +greatroc.tw +greatzhonghua.org +greenparty.org.tw +greenvpn.net +gs-discuss.com +gseeker.com +gsn-cert.nat.gov.tw +gstatic.com +gtap.googlecode.com +gtricks.com +guancha.org +gufeng521.spaces.live.com +guishan.org +gunsamerica.com +gun-world.net +guomin.us +gutteruncensored.com +gvm.com.tw +gyalwarinpoche.com +gysd.nyc.gov.tw +gzm.tv +gzone-anime.info +h1n1china.org +hacken.cc +hackthatphone.net +hahlo.com +hakkatv.org.tw +hanunyi.com +hardsextube.com +hasaowall.com +have8.com +haygo.com +hcc.gov.tw +hchcc.gov.tw +h-china.org +hdtvb.net +heartyit.com +hecaitou.net +hechaji.com +heix.pp.ru +heiyo.info +helloandroid.com +hellonewyork.us +helloqueer.com +hellotxt.com +hellouk.org +helpeachpeople.com +helplinfen.com +help.linksalpha.com +help.opera.com +helpzhuling.org +hen.bao.li +hengchuen.gov.tw +heqinglian.net +here4news.com +heungkongdiscuss.com +hgseav.com +hidden-advent.org +hidecloud.com +hideipvpn.com +hidemyass.com +higfw.com +highrockmedia.com +hihiforum.com +hihistory.net +hiitch.com +hikinggfw.org +himemix.com +himemix.net +hjclub.info +hk32168.com +hkbc.net +hkbf.org +hkchurch.org +hkdailynews.com.hk +hkday.net +hkej.com +hkepc.com +hkfront.org +hk.geocities.com +hkgolden.com +hkgreenradio.org +hkg.westkit.net +hkheadline.com +hkhkhk.com +hkjc.com +hk.jiepang.com +hkjp.easyweb.hk +hkjp.org +hk.knowledge.yahoo.com +hk.myblog.yahoo.com +hk.news.yahoo.com +hkptu.org +hk-pub.com +hk.rd.yahoo.com +hkreporter.com +hkreporter.loved.hk +hk.search.yahoo.com +hk.video.news.yahoo.com +hkwcc.org.hk +hk.yahoo.com +hkzone.org +hnjhj.com +hola.com +holyspiritspeaks.org +holz.byethost8.com +homeservershow.com +home.sina.com +home.so-net.net.tw +honeonet.spaces.live.com +hongmeimei.com +hongzhi.li +hootsuite.com +hotpot.hk +hotshame.com +hotspotshield.com +hougaige.com +howtoforge.com +hqcdp.org +hrcir.com +hrichina.org +hrw.org +hsinchu-cc.gov.tw +hsjp.net +hsselite.com +htkou.net +htl.li +ht.ly +htmldog.com +huaglad.com +huajiadi.spaces.live.com +huanghuagang.org +huaren.us +huaxia-news.com +huaxin.ph +hua-yue.net +hudatoriq.web.id +hugoroy.eu +huhamhire.com +hujiachina.spaces.live.com +hulu.com +huluim.com +humanities.uchicago.edu +hungerstrikeforaids.org +hung-ya.com +huping.net +hutianyi.net +hutong9.net +hwinfo.com +hyperrate.com +hypeshell.com +i1.hk +i2runner.com +ialmostlaugh.com +iask.bz +iask.ca +ibiblio.org +iblogserv-f.net +ibros.org +icij.org +icl-fi.org +iconpaper.org +icu-project.org +idemocracy.asia +identi.ca +idiomconnection.com +idouga.com +idv.tw +ieasynews.net +ied2k.net +ieemdai.spaces.live.com +ifan.cz.cc +ifanqiang.com +ifanr.com +ifcss.org +ifjc.org +igfw.net +ignitedetroit.net +igvita.com +ihakka.net +iicns.com +illusionfactory.com +ilove80.be +im88.tw +imageflea.com +imagesblog.gio.gov.tw +imageshack.us +imagevenue.com +imagezilla.net +ime.baidu.jp +img.ly +imkev.com +imlive.com +immigration.gov.tw +imrworldwide.com +im.tv +incredibox.fr +iner.gov.tw +initiativesforchina.org +inmediahk.net +innermongolia.org +instagram.com +interestinglaugh.com +interfaceaddiction.com +internationalrivers.org +internetdefenseleague.org +internetfreedom.org +internetpopculture.com +inxian.com +iphone4hongkong.com +iphonehacks.com +iphonix.fr +ipicture.ru +ipobar.com +ippotv.com +iptorrents.com +ipvanish.com +iredmail.org +ironbigfools.compython.net +ironicsoftware.com +ironpython.net +isaacmao.com +isgreat.org +islamicity.com +islam.org.hk +ismprofessional.net +isohunt.com +israbox.com +istockphoto.com +isunaffairs.com +isuntv.com +itaboo.info +ithelp.ithome.com.tw +itrc.gov.tw +itshidden.com +itweet.net +iu45.com +iverycd.com +ixquick.com +izaobao.us +izles.net +japan-whores.com +jayparkinsonmd.com +jbtalks.cc +jbtalks.com +jbtalks.my +jeanyim.com +jgoodies.com +jiaoyou8.com +jiehua.cz +jieshibaobao.com +jike.com +jimoparty.com +jinbushe.org +jingpin.org +jitouch.com +jkforum.net +j.mp +joachims.org +jobso.tv +joeedelman.com +journalofdemocracy.org +jpopforum.net +juliereyc.com +junauza.com +junefourth-20.net +justfreevpn.com +justtristan.com +juziyue.com +jwmusic.org +jyxf.net +jyzj.waqn.com +k2.xrea.com +kagyuoffice.org.tw +kaiyuan.de +kakao.com +kanzhongguo.com +kanzhongguo.eu +karayou.com +ka-wai.com +kcsoftwares.com +kechara.com +keepandshare.com +kendincos.net +kenengba.com +keontech.net +khcc.gov.tw +khms.gov.tw +khmusic.com.tw +killwall.com +kineox.free.fr +kingdomsalvation.org +kinghost.com +kingstone.com.tw +kissbbao.cn +kissyoutube.com +kk.gov.tw +klccab.gov.tw +klra.gov.tw +klsio.gov.tw +kmh.gov.tw +kmseh.gov.tw +knowledgerush.com +kodingen.com +kompozer.net +koolsolutions.com +koornk.com +kt.kcome.org +kui.name +kun.im +kurtmunger.com +kusocity.com +kwongwah.com.my +kyohk.net +kzeng.info +labiennale.org +ladbrokes.com +la-forum.org +lagranepoca.com +lalulalu.com +laogai.org +laomiu.com +laoyang.info +laptoplockdown.com +laqingdan.net +larsgeorge.com +lastfm.es +latelinenews.com +latimesblogs.latimes.com +lazarsearlymusic.com +leecheukyan.org +legaltech.law.com +lematin.ch +lemonde.fr +lenwhite.com +lerosua.org +lesoir.be +lesscss.org +letscorp.net +liansi.org +lianyue.net +liaowangxizang.net +liberal.org.hk +libertytimes.com.tw +lich355.megabyet.net +lidecheng.com +life.fly4ever.me +limiao.net +line.me +linglingfa.com +lingvodics.com +linkideo.com +linuxconfig.org +linux-engineer.net +linuxreviews.org +linuxtoy.org +lipuman.com +listentoyoutube.com +list.ly +listorious.com +lists.debian.org +lists.w3.org +littlebigdetails.com +liudejun.com +liuhanyu.com +liujianshu.com +liu.lu +liuxiaotong.com +liveleak.com +livestation.com +livestream.com +livevideo.com +livingonline.us +livingstream.com +lizhizhuangbi.com +lkcn.net +localpresshk.com +lockdown.com +lockestek.com +logbot.net +logiqx.com +logmike.com +log.riku.me +london.neighborhoodr.com +longhair.hk +longtermly.net +lookatgame.com +lookingglasstheatre.org +lookpic.com +lotuslight.org.tw +lovequicksilver.com +lovesphinx.tk +lrfz.com +lsd.org.hk +lsforum.net +lsmchinese.org +lsmkorean.org +lsm.org +lsxszzg.com +lua.org +lua-users.org +lungtanhr.gov.tw +luntan.zaobao.com +lupm.org +lushstories.com +lvhai.org +lyricsquote.com +mad-ar.ch +madmenunbuttoned.com +magazines.sina.com.tw +maiio.net +mail-archive.com +maiplus.com +makemymood.com +makzhou.warehouse333.com +malaysiakini.com +marc.info +marco.org +marguerite.su +marines.mil +markmilian.com +martau.com +martincartoons.com +maruta.be +marxist.com +marxist.net +marxists.org +mashable.com +mash.to +matainja.com +mathiew-badimon.com +matsu-news.gov.tw +matsushimakaede.com +maxgif.com +mayimayi.com +mcadforums.com +mcfog.com +md-t.org +mediafire.com +meetup.com +mefeedia.com +megaporn.com +megarotic.com +megavideo.com +megurineluka.com +meirixiaochao.com +melon-peach.com +memedia.cn +meme.yahoo.com +memrijttm.org +merit-times.com.tw +mesotw.com +metacafe.com +meteorshowersonline.com +metrolife.ca +mgoon.com +mgstage.com +mh4u.org +mhradio.org +michaelanti.com +michaelmarketl.com +middle-way.net +mihk.hk +mihua.org +mike.cz.cc +mimivip.com +minghui.org +minghui-school.org +mingjinglishi.com +mingjingnews.com +mingpaocanada.com +mingpao.com +mingpaomonthly.com +mingpaonews.com +mingpaony.com +mingpaosf.com +mingpaotor.com +mingpaovan.com +minimalmac.com +mininova.org +minzhuhua.net +minzhuzhongguo.org +miroguide.com +mirrorbooks.com +mitbbs.com +mixedmedialabs.com +mixero.com +mixpod.com +mixx.com +mizzmona.com +mk5000.com +mlcool.com +mmaaxx.com +mmmca.com +mobatek.net +mobile01.com +mobileways.de +mobypicture.com +moby.to +modfetish.com +moe.gov.tw +mog.com +molihua.org +mondex.org +monitorchina.org +moonriver7.files.wordpress.com +morningsun.org +m.oulove.org +movabletype.com +moviefap.com +mp3ye.eu +mpettis.com +mpfinance.com +mpinews.com +m.plixi.com +mrdoob.com +mrtweet.com +msguancha.com +m.slandr.net +m-team.cc +mthruf.com +m.tweete.net +mtw.tl +multiply.com +multiproxy.org +multiupload.com +muouju.com +muselinks.co.jp +music.jwmusic.org +muzi.com +muzi.net +muzu.tv +mvdis.gov.tw +mx981.com +myactimes.com +my-addr.com +myaudiocast.com +myav.com.tw +my.backchina.com +myboooks.googlepages.com +mychinamyhome.com +myeclipseide.com +myforum.com.hk +myforum.com.uk +myfreshnet.com +my.keso.cn +myopenid.com +my.opera.com +mypaper.pchome.com.tw +myparagliding.com +mypopescu.com +my-proxy.com +myshare.url.com.tw +mysinablog.com +myspace.com +myvlog.im.tv +naacoalition.org +naitik.net +nakido.com +namsisi.com +nanyang.com +nanyangpost.com +nanzao.com +naol.ca +national-lottery.co.uk +navicat.com +navigeaters.com +navy.mil +nccwatch.org.tw +ncdr.nat.gov.tw +nch.com.tw +ncn.org +ncree.gov.tw +nde.de +ndr.de +nekoslovakia.net +nerch.gov.tw +ner.gov.tw +nerhl.gov.tw +nertt.gov.tw +netcolony.com +netflix.com +netme.cc +networkedblogs.com +neverforget8964.org +new-3lunch.net +new-akiba.com +newcenturymc.com +newcenturynews.com +newchen.com +newgrounds.com +newlandmagazine.com.au +news100.com.tw +newsancai.com +news.atebits.com +news.backchina.com +news.bbc.co.uk +newscn.org +news.cnyes.com +newsforums.bbc.co.uk +news.ghostery.com +news.google.com.hk +newsminer.com +news.msn.com.tw +news.omy.sg +news.pchome.com.tw +newspeak.cc +newspp.org +news.sina.com.hk +news.sina.com.tw +news.singtao.ca +newstapa.org +newtaiwan.com.tw +newtalk.tw +newyorktimes.com +nexton-net.jp +nexttv.com.tw +nf.id.au +nga.mil +ngensis.com +nhri.gov.tw +nic.cz.cc +nici.nat.gov.tw +nicovideo.tw +nict.gov.tw +nighost.org +nintendium.com +nintendowifi.net +njactb.org +njuice.com +nlfreevpn.com +nmh.gov.tw +nmmba.gov.tw +nmp.gov.tw +nmtl.gov.tw +nmvttc.gov.tw +nobelprize.org +nobel.se +nobodycanstop.us +nokogiri.org +nokola.com +noobbox.com +notes.alexdong.com +novelasia.com +nownews.com +nowtorrents.com +noypf.com +npa.go.jp +npm.gov.tw +nps.gov +nrk.no +nsc.gov.tw +nspo.gov.tw +nstm.gov.tw +ntdmh.gov.tw +ntdtv.ca +ntdtv.co +ntdtv.com +ntdtv.org +ntdtv.ru +ntl.gov.tw +ntsec.gov.tw +ntuh.gov.tw +nuexpo.com +nurgo-software.com +nuvid.com +nuzcom.com +nvquan.org +nvri.gov.tw +nydus.ca +nysingtao.com +nytco.com +nyt.com +nytimes.com +nytimg.com +nzchinese.net.nz +observechina.net +oclp.hk +october-review.org +offbeatchina.com +ogaoga.org +oikos.com.tw +oiktv.com +oizoblog.com +okayfreedom.com +old-cat.net +old.nabble.com +olumpo.com +olympicwatch.org +omgili.com +omnitalk.com +on.cc +one.xthost.info +onlylady.cn +onmoon.com +onmoon.net +oopsforum.com +ooyala.com +open.com.hk +opendemocracy.net +openid.net +openleaks.org +openvpn.net +openvpn.org +openwebster.com +opml.radiotime.com +opnir.com +orientaldaily.com.my +orient-doll.com +orn.jp +orzistic.org +osfoora.com +ourdearamy.com +oursogo.com +oursteps.com.au +overlapr.com +owl.li +ow.ly +oyax.com +ozchinese.com +ozyoyo.com +pabp.gov.tw +pacificpoker.com +packages.debian.org +packetix.net +page2rss.com +page.bid.yahoo.com +pagodabox.com +paint.net +palacemoon.com +pandora.com +pandora.tv +panluan.net +panoramio.com +pao-pao.net +paperb.us +paper.li +paper-replika.com +parade.com +parislemon.com +pastebin.com +pastie.org +patehr.gov.tw +pbs.org +pbwiki.com +pbworks.com +pbxes.com +pbxes.org +pcdiscuss.com +pcdvd.com.tw +pchome.com.tw +pct.org.tw +pcworld.com +pdetails.com +pdproxy.com +peacefire.org +peacehall.com +peeasian.com +peerpong.com +pekingduck.org +penchinese.com +penchinese.net +pengyulong.com +penthouse.com +peopo.org +percy.in +perfectgirls.net +perfectvpn.net +perfspot.com +perlhowto.com +pet.gov.tw +philly.com +photofocus.com +photos.dailyme.com +photo.utom.us +phuquocservices.com +picasaweb.google.com +picidae.net +picturesocial.com +pictures.playboy.com +pidown.com +pign.net +pimg.tw +pin6.com +ping.fm +pinoy-n.com +pioneer-worker.forums-free.com +piring.com +pixanalytics.com +pixelqi.com +pixfs.net +pixnet.cc +pixnet.net +pixplug.in +pk.com +placemix.com +planetsuzy.org +playboy.com +plays.com.tw +plm.org.hk +plunder.com +plurk.com +plurktop.mmdays.com +plus28.com +plusbb.com +pmates.com +po2b.com +podictionary.com +pokerstars.com +politicalchina.org +popvote.hk +popyard.com +popyard.org +porn2.com +pornbase.org +porn.com +pornhub.com +pornmm.net +pornoxo.com +pornrapidshare.com +pornstarclub.com +porntube.com +pornvisit.com +portis21.spaces.live.com +pose.com +postadult.com +post.anyu.org +posterous.com +post.ly +powerapple.com +power.com +powercx.com +prayforchina.net +premeforwindows7.com +presentationzen.com +president.gov.tw +prestige-av.com +previewshots.com +privacybox.de +privateinternetaccess.com +privatepaste.com +privatetunnel.com +procopytips.com +program-think.spaces.live.com +prosiben.de +provideocoalition.com +proxifier.com +proxomitron.info +proxy.org +proxypy.net +proxyroad.com +prozz.net +psblog.name +psiphon.ca +psiphon.civisec.org +pts.org.tw +ptt.cc +pubu.com.tw +puffinbrowser.com +puffstore.com +pullfolio.com +pulse.yahoo.com +pure18.com +pureconcepts.net +purepdf.com +purevpn.com +putlocker.com +puttycm.free.fr +pwned.com +python.com +python.com.tw +qanote.com +qidian.ca +qienkuen.org +qi-gong.me +qiwen.lu +qixianglu.cn +qkshare.com +qoos.com +qq.co.za +qstatus.com +qtrac.eu +qtweeter.com +quadedge.com +qusi8.net +qvodzy.org +qxbbs.org +radicalparty.org +radioaustralia.net.au +radiovaticana.org +radiovncr.com +raidcall.com.tw +rangzen.org +ranyunfei.com +rapbull.net +rapidshare8.com +rapidsharedata.com +rayfme.com +rcinet.ca +rconversation.blogs.com +rdio.com +read100.com +readingtimes.com.tw +readmoo.com +realraptalk.com +recordhistory.org +redchinacn.org +redtube.com +referer.us +reflectivecode.com +relaxbbs.com +renminbao.com +renyurenquan.org +retweeteffect.com +retweetist.com +retweetrank.com +revleft.com +revsci.net +revver.com +rfachina.com +rfamobile.org +rfa.org +rferl.org +rfi.fr +rhcloud.com +riku.me +rileyguide.com +rlwlw.com +rmjdw.com +rnw.nl +robtex.com +robustnessiskey.com +rocmp.org +rojo.com +ronjoneswriter.com +roodo.com +rotten.com +rsf-chinese.org +rsf.org +rssmeme.com +rthk.hk +rthk.org.hk +rti.org.tw +ruanyifeng.com +rushbee.com +rutube.ru +ruyiseek.com +rxhj.net +s1heng.com +s8forum.com +sacom.hk +sadpanda.us +saiq.me +salvation.org.hk +samair.ru +sammyjs.org +samsoff.es +sandnoble.com +sankaizok.com +sanmin.com.tw +sapikachu.net +savemedia.com +savetibet.de +savetibet.fr +savetibet.nl +savetibet.org +savetibet.ru +savevid.com +say2.info +scanscout.com +scmpchinese.com +scmp.com +scorecardresearch.com +scribd.com +scriptspot.com +seapuff.com +secretchina.com +secretgarden.no +secure.wikimedia.org +securitykiss.com +seesmic.com +seevpn.com +seezone.net +sejie.com +sendoid.com +sendspace.com +sesawe.net +sesawe.org +sethwklein.net +sevenload.com +sex-11.com +sex3.com +sex8.cc +sexandsubmission.com +sex.com +sexhuang.com +sexhu.com +sexinsex.net +sfileydy.com +shadow.ma +shadowsocks.org +shahamat-english.com +shangfang.org +shapeservices.com +sharebee.com +sharecool.org +share.ovi.com +share.skype.com +share.youthwant.com.tw +sharkdolphin.com +sharpdaily.com.hk +sharpdaily.hk +shaunthesheep.com +sheikyermami.com +shellmix.com +shenshou.org +shenyunperformingarts.org +shenzhoufilm.com +shifeike.blog125.fc2blog.net +shinychan.com +shitaotv.org +shixiao.org +shizhao.org +shkspr.mobi +shodanhq.com +shopping.com +showbiz.omy.sg +showtime.jp +shwchurch3.com +sidelinesnews.com +sidelinessportseatery.com +simplecd.me +simplecd.org +simpleproductivityblog.com +sina.com.tw +singtao.com +singularitys.spaces.live.com +sinoants.com +sinocast.com +sinocism.com +sino-monthly.com +sinomontreal.ca +sinonet.ca +sinopitt.info +sinoquebec.com +sis001.com +sis001.us +sis.xxx +site90.net +sitebro.tw +siteks.uk.to +site.locql.com +sitemaps.org +sites.google.com +sitetag.us +siyi123123123.spaces.live.com +skimtube.com +skybet.com +skyvegas.com +slacker.com +slavasoft.com +slheng.com +slickvpn.com +slideshare.net +slinkset.com +slutload.com +smhric.org +snapchat.com +snaptu.com +sndcdn.com +sneakme.net +snooper.co.uk +sobees.com +socialwhale.com +sockslist.net +so.com +sod.co.jp +softether.co.jp +softether-download.com +softether.org +softwarebychuck.com +so-ga.net +sogclub.com +sogou.com +sogrady.me +sohcradio.com +sohfrance.org +soh.tw +sokamonline.com +solozorro.tk +somee.com +so-news.com +songjianjun.com +sonidodelaesperanza.org +sopcast.com +sopcast.org +sorting-algorithms.com +soso.com +soumo.info +soundcloud.com +soundofhope.kr +soundofhope.org +soupofmedia.com +sourceforge.net +southnews.com.tw +sowers.org.hk +space-scape.com +spankwire.com +spb.com +speckleapp.com +speedpluss.org +spencertipping.com +spinejs.com +sports.williamhill.com +spotify.com +sproutcore.com +squarespace.com +srcf.ucam.org +ssh91.com +sshtunnel.googlecode.com +sstatic.net +stag.gov.tw +standupfortibet.org +starp2p.com +startpage.com +statcounter.com +state168.com +static.apple.nextmedia.com +static.digg.com +staticflickr.com +static.nownews.com +static.soup.io +static.typepad.com +status.twhirl.org +stdtime.gov.tw +steel-storm.com +sthoo.com +stickam.com +stickeraction.com +stonegames.net +stoneip.info +stoptibetcrisis.net +storagenewsletter.com +stoweboyd.com +streamingthe.net +strongvpn.com +student.tw +stuffimreading.com +stuffimreading.net +stupidvideos.com +subacme.rerouted.org +sublexical.spaces.live.com +sufeng.org +sugarsync.com +summify.com +sun1911.com +suoluo.org +surfeasy.com.au +svwind.com +sweux.com +swift-tools.net +s.xiaod.in +sydneytoday.com +sylfoundation.org +syncback.com +sysadmin1138.net +sysresccd.org +sytes.net +szbbs.net +szetowah.org.hk +t35.com +t66y.com +taa-usa.org +tabtter.jp +tacem.org +tafaward.com +tagwalk.com +taipei.gov.tw +taipeisociety.org +taitung-house.gov.tw +taiwandaily.net +taiwankiss.com +taiwannation.50webs.com +taiwannation.com +taiwannation.com.tw +taiwannews.com.tw +taiwan-sex.com +taiwantt.org.tw +taiwanus.net +taiwanyes.com +taiwanyes.ning.com +tamiaode.tk +tanc.org +tangben.com +taolun.info +taoyuan.gov.tw +tap11.com +target.com +taweet.com +tax.nat.gov.tw +tbpic.info +tbsec.org +tbsn.org +tbsseattle.org +tchb.gov.tw +tchrd.org +t.co +tcsac.gov.tw +teamseesmic.com +teashark.com +techlifeweb.com +techparaiso.com +telecomspace.com +telegraph.co.uk +tenacy.com +thbstc.gov.tw +theampfactory.com +theappleblog.com +theatrum-belli.com +thebcomplex.com +theblemish.com +thebodyshop-usa.com +thechinabeat.org +thedailywh.at +thedieline.com +thedw.us +thegatesnotes.com +thehots.info +thehousenews.com +thehungrydudes.com +thehun.net +theinternetwishlist.com +thelifeyoucansave.com +thelius.org +thepiratebay.org +thepiratebay.se +theqii.info +thereallove.kr +thesartorialist.com +thespeeder.com +the-sun.on.cc +thetibetpost.com +thetrotskymovie.com +thevivekspot.com +thewgo.org +thisav.com +thisiswhyyouarefat.com +thkphoto.com +thomasbernhard.org +threatchaos.com +throughnightsfire.com +t.huhaitai.com +thumbzilla.com +thywords.com +tiananmenmother.org +tiananmenuniv.com +tiananmenuniv.net +tiandixing.org +tianhuayuan.com +tiantibooks.org +tianzhu.org +tibetalk.com +tibetanyouthcongress.org +tibet.at +tibet.com +tibetcorps.org +tibetfund.org +tibetjustice.org +tibet.net +tibetoffice.org +tibetonline.com +tibetonline.tv +tibet.org.tw +tibetsun.com +tibetwrites.org +tidyread.com +time.com +times.hinet.net +tinychat.com +tinypaste.com +tinypng.com +tistory.com +tjholowaychuk.com +tkcs-collins.com +tkforum.tk +t.kun.im +tmagazine.com +tmi.me +tnaflix.com +tncsec.gov.tw +t.neolee.cn +togetter.com +tokyo-247.com +tokyocn.com +tokyo-hot.com +tomayko.com +tomsc.com +tono-oka.jp +tonyyan.net +toodoc.com +toonel.net +topic.youthwant.com.tw +topnews.in +topshare.us +topshareware.com +topstyle4.com +topsy.com +tora.to +tor.blingblingsquad.net +torproject.org +torrentcrazy.com +torrentproject.se +tor.updatestar.com +torvpn.com +t.orzdream.com +tosh.comedycentral.com +touch99.com +toutfr.com +tpde.aide.gov.tw +tphcc.gov.tw +tpi.org.tw +transgressionism.org +transparency.org +travelinlocal.com +trendsmap.com +trialofccp.org +tripod.com +trouw.nl +trtc.com.tw +trt.net.tr +trulyergonomic.com +trustedbi.com +truth101.co.tv +truthcn.com +truveo.com +tsctv.net +tsemtulku.com +tsquare.tv +tsunagarumon.com +tt1069.com +tttan.com +tuanzt.com +tube8.com +tubecao.com +tube.com +tubewolf.com +tuidang.net +tuidang.org +tui.orzdream.com +tuite.googlecode.com +tumblr.awflasher.com +tumblweed.org +tumutanzi.com +tunein.com +tunnelbear.com +turbobit.net +turbotwitter.com +turningtorso.com +turntable.fm +tuxtraining.com +tvants.com +tvboxnow.com +tv.com +tvider.com +tv-intros.com +tv.on.cc +tvunetworks.com +twapperkeeper.com +twa.sh +twaud.io +twbbs.net.tw +twbbs.org +twbbs.tw +twblogger.com +tweepguide.com +tweeplike.me +tweepmag.com +tweepml.org +tweetbackup.com +tweetboard.com +tweetboner.biz +tweetdeck.com +tweetedtimes.com +tweetmeme.com +tweetmylast.fm +tweetphoto.com +tweetrans.com +tweetree.com +tweetwally.com +tweetymail.com +twftp.org +twibase.com +twibble.de +twibbon.com +twibs.com +twicsy.com +twifan.com +twiffo.com +twiggit.org +twilog.org +twimbow.com +twimg.com +twimg.edgesuite.net +tw.img.nextmedia.com +twindexx.com +twipple.jp +twistar.cc +twisternow.com +twistory.net +twit2d.com +twitbrowser.net +twitcause.com +twitese.spaces.live.com +twitgether.com +twitgoo.com +twitiq.com +twitlonger.com +twitoaster.com +twitonmsn.com +twitpic.com +twitreferral.com +twitstat.com +twittbot.net +twitter4j.org +twitter.com +twittercounter.com +twitterfeed.com +twittergadget.com +twitter.jp +twitterkr.com +twittermail.com +twittertim.es +twitthat.com +twitturk.com +twitturly.com +twitvid.com +twitzap.com +twiyia.com +tw.jiepang.com +tw.myblog.yahoo.com +tw.news.yahoo.com +tw-npo.org +tw.rd.yahoo.com +twreg.info +twstar.net +tw.streetvoice.com +twt.fm +twtkr.com +twtr2src.ogaoga.org +twtrland.com +twt.tl +twttr.com +twurl.nl +tw.voa.mobi +twyac.org +tw.yahoo.com +tycool.com +tynsoe.org +typepad.com +tzangms.com +ub0.cc +uberproxy.net +ucdc1998.org +uderzo.it +udn.com +ufreevpn.com +ugo.com +uhrp.org +uighurbiz.net +ukliferadio.co.uk +ulike.net +ultravpn.fr +ultraxs.com +unblock.cn.com +unblocksit.es +uncyclomedia.org +uncyclopedia.info +uncyclopedia.tw +unholyknight.com +uni.cc +unicode.org +uniteddaily.com.my +unix100.com +unknownspace.org +unpo.org +uocn.org +upcoming.yahoo.com +update.playstation.net +upload4u.info +upload.backchina.com +uploaded.to +uploadstation.com +upload.wikimedia.org +urlborg.com +urlparser.com +usacn.com +usfk.mil +usinfo.state.gov +usmc.mil +us.to +ustream.tv +usus.cc +uushare.com +uwants.com +uwants.net +uyghurcongress.org +uygur.org +v70.us +vaayoo.com +value-domain.com +van698.com +vanemu.cn +vanilla-jp.com +vansky.com +vapurl.com +vatn.org +vcfbuilder.org +vcf-online.org +veempiire.com +velkaepocha.sk +venbbs.com +venchina.com +ventureswell.com +veoh.com +verizon.net +verybs.com +vevo.com +vft.com.tw +vghks.gov.tw +vghtc.gov.tw +vghtpe.gov.tw +video.aol.ca +video.aol.com +video.aol.co.uk +video.ap.org +videobam.com +video.fdbox.com +video.foxbusiness.com +videomo.com +video.tiscali.it +video.yahoo.com +vidoemo.com +views.fm +viki.com +vimeocdn.com +vimeo.com +vimgolf.com +vimperator.org +vincnd.com +vinniev.com +vllcs.org +vlog.xuite.net +vmixcore.com +voacantonese.com +voachineseblog.com +voachinese.com +voagd.com +voanews.com +voatibetan.com +vocn.tv +vot.org +vpnbook.com +vpnfire.com +vpngate.jp +vpngate.net +vpnpop.com +vpnpronet.com +v-state.org +vtunnel.com +w3schools.com +waffle1999.com +wahas.com +waigaobu.com +waikeung.org +waiwaier.com +wallornot.org +wallpapercasa.com +wanderinghorse.net +wanfang.gov.tw +wangafu.net +wangjinbo.org +wanglixiong.com +wangruoshui.net +wangyi64.spaces.live.com +want-daily.com +wapedia.mobi +washeng.net +watchmygf.net +wattpad.com +wdf5.com +wearn.com +web2project.net +webbang.net +webfee.tk +weblagu.com +webmproject.org +webshots.com +websitepulse.com +webs-tv.net +webworkerdaily.com +weeewooo.net +weekmag.info +wefong.com +weiboleak.com +weigegebyc.dreamhosters.com +weijingsheng.org +weiming.info +weiquanwang.org +weisuo.ws +wellplacedpixels.com +wengewang.com +wengewang.org +wenhui.ch +wenku.com +wenxuecity.com +wenyunchao.com +wenyunchao.spaces.live.com +wepn.info +westca.com +westernwolves.com +wetplace.com +wetpussygames.com +wexiaobo.org +wezhiyong.org +wezone.net +wforum.com +whatblocked.com +whereiswerner.com +whippedass.com +whitebear.freebearblog.org +whydidyoubuymethat.com +whylover.com +whyx.org +w.idaiwan.com +wiki.cnitter.com +wiki.jqueryui.com +wiki.keso.cn +wikileaks.ch +wikileaks.de +wikileaks.eu +wikileaks.lu +wikileaks.org +wikileaks.pl +wikilivres.info +wikimapia.org +wikimedia.org.mo +wiki.moegirl.org +wikinet.org +wiki.oauth.net +wikipedia.org +wiki.phonegap.com +wikiwiki.jp +wikkii.com +williamlong.spaces.live.com +willw.net +windowsphoneme.com +winwhispers.info +wiredbytes.com +wiredpen.com +wireshark.org +wisevid.com +witnessleeteaching.com +witopia.net +wlx.sowiki.net +woeser.com +wolfax.com +womenbusiness.nyc.gov.tw +womensrightsofchina.org +woopie.jp +woopie.tv +wordboner.com +wordpress.com +wordsandturds.com +w.org +workatruna.com +worldcat.org +worldjournal.com +worstthingieverate.com +wo.tc +wowlegacy.ml +wow-life.net +woxinghuiguo.com +wozy.in +wp.com +wpoforum.com +wqlhw.com +wqyd.org +wrchina.org +wretch.cc +writer.zoho.com +wsj.com +wsj.net +wtfpeople.com +wuala.com +wuerkaixi.com +wufi.org.tw +wuguoguang.com +wujieliulan.com +wujie.net +wukangrui.net +wwitv.com +www.6v6dota.com +www.ajsands.com +www.antd.org +www.aolnews.com +www.bulbous.freeserve.co.uk +www.cmoinc.org +www.dfanning.com +www.dwheeler.com +www.eulam.com +www.exblog.jp +www.forum4hk.com +www.freetibet.org +www.getyouram.com +www.goldenmelody.com.tw +www.idlcoyote.com +www.immigration.gov.tw +www.klip.me +www.kodingen.com +www.linksalpha.com +www.loiclemeur.com +www.macrovpn.com +www.monlamit.org +www.moztw.org +www.mycould.com +www.ned.org +www.nownews.com +www.orchidbbs.com +www.owind.com +www.oxid.it +www.parkansky.com +www.powerpointninja.com +www.rnw.nl +www.somee.com +www.stackfile.com +www.supertweet.net +www.tiffanyarment.com +www.tripod.com +www.tv.com +www.twtrland.com +www.typepad.com +www.urbanoutfitters.com +www.vegorpedersen.com +www.voy.com +www.vpncup.com +www.wangruowang.org +www.wan-press.org +www.wet123.com +www.zaurus.org.uk +wzyboy.im +x1949x.com +x365x.com +xanga.com +x-art.com +xa.yimg.com +xbabe.com +xbookcn.com +xcafe.in +xcritic.com +xfm.pp.ru +xgmyd.com +xh4n.cn +xhamster.com +xiaochuncnjp.com +xiaohexie.com +xiaoma.org +xiezhua.com +xing.com +xinhuanet.org +xinmiao.com.hk +xinqimeng.over-blog.com +xinsheng.net +xinshijue.com +xinyubbs.net +xizang-zhiye.org +xjp.cc +xml-training-guide.com +xmovies.com +xmusic.fm +xnxx.com +xpdo.net +xpud.org +xskywalker.com +xtube.com +xuchao.net +xuchao.org +xuzhiyong.net +xuzhuoer.com +xvedios.com +xvideos.com +x-wall.org +xxbbx.com +x.xcity.jp +xxxx.com.au +xysblogs.org +xys.dxiong.com +xys.org +xyy69.com +xyy69.info +yahoo.cn +yahoo.com.hk +yam.com +yanghengjun.spaces.live.com +yasni.co.uk +yasukuni.or.jp +yatsen.gov.tw +ydy.com +yeelou.com +yeeyi.com +yegle.net +yezimary.spaces.live.com +yfrog.com +yhcw.net +yidio.com +yilubbs.com +yi.org +yipub.com +ym.backchina.com +yogichen.org +yong.hu +yorkbbs.ca +youdao.com +youjizz.com +youmaker.com +youpai.org +youporn.com +your-freedom.net +yousendit.com +youthbao.com +youthnetradio.org +youtu.be +youtubecn.com +youtube.com +youtube-nocookie.com +youversion.com +youxu.info +ytht.net +ytimg.com +yuanming.net +yuming.flnet.org +yunchao.net +yvesgeleyn.com +yvtc.gov.tw +yx51.net +yyii.org +yymaya.com +yzzk.com +zacebook.com +zannel.com +zaobao.com +zaobao.com.sg +zaozon.com +zarias.com +zattoo.com +zdnet.com.tw +zengjinyan.org +zengjinyan.spaces.live.com +zeutch.com +zgzcjj.net +zhanbin.net +zhao.jinhai.de +zhenghui.org +zhenlibu.info +zhinengluyou.com +zhllg.spaces.live.com +zh.m.wikipedia.org +zh.netlog.com +zhonggtuotese.net +zhongguotese.net +zhongmeng.org +zhongsou.com +zh.pokerstrategy.com +zhreader.com +zh-tw.justin.tv +zhuichaguoji.org +zh.uncyclopedia.wikia.com +zh.wikinews.org +zh.wikipedia.org +zh.wikisource.org +ziddu.com +zillionk.com +zinio.com +ziplib.com +zkaip.com +zmw.cn +zomobo.net +zonaeuropa.com +zootool.com +zoozle.net +zozotown.com +zshare.net +zsrhao.com +zuo.la +zuola.com +zvereff.com +zyzc9.com +zyzg.us diff --git a/package/lean/luci-app-brook-pro/root/etc/brook/gen-gfwlist.sh b/package/lean/luci-app-brook-pro/root/etc/brook/gen-gfwlist.sh new file mode 100755 index 000000000..050de594c --- /dev/null +++ b/package/lean/luci-app-brook-pro/root/etc/brook/gen-gfwlist.sh @@ -0,0 +1,29 @@ +#!/bin/sh -e + +generate_china_banned() +{ + if [ ! -f /tmp/gfwlist.txt ]; then + wget-ssl --no-check-certificate https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt -O /tmp/gfwlist.b64 >&2 + cat /tmp/gfwlist.b64 | base64 -d > /tmp/gfwlist.txt + rm -f /tmp/gfwlist.b64 + fi + + cat /tmp/gfwlist.txt | sort -u | + sed 's#!.\+##; s#|##g; s#@##g; s#http:\/\/##; s#https:\/\/##;' | + sed '/\*/d; /apple\.com/d; /sina\.cn/d; /sina\.com\.cn/d; /baidu\.com/d; /byr\.cn/d; /jlike\.com/d; /weibo\.com/d; /zhongsou\.com/d; /youdao\.com/d; /sogou\.com/d; /so\.com/d; /soso\.com/d; /aliyun\.com/d; /taobao\.com/d; /jd\.com/d; /qq\.com/d' | + sed '/^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$/d' | + grep '^[0-9a-zA-Z\.-]\+$' | grep '\.' | sed 's#^\.\+##' | sort -u | + awk ' +BEGIN { prev = "________"; } { + cur = $0; + if (index(cur, prev) == 1 && substr(cur, 1 + length(prev) ,1) == ".") { + } else { + print cur; + prev = cur; + } +}' | sort -u + +} + + +generate_china_banned diff --git a/package/lean/luci-app-brook-pro/root/etc/brook/ssr-watchdog b/package/lean/luci-app-brook-pro/root/etc/brook/ssr-watchdog new file mode 100755 index 000000000..a677e0f96 --- /dev/null +++ b/package/lean/luci-app-brook-pro/root/etc/brook/ssr-watchdog @@ -0,0 +1,35 @@ +#!/bin/sh + +LOGTIME=$(date "+%Y-%m-%d %H:%M:%S") +#GOOGLE=$(ping -4 www.gstatic.com -c 1 -w 5| sed '1{s/[^(]*(//;s/).*//;q}') + +#iptables -t nat -I OUTPUT -p tcp -d $GOOGLE -j REDIRECT --to-port 7070 + +#sleep 3 + +/usr/bin/wget --spider --quiet --tries=1 --timeout=3 www.gstatic.com/generate_204 + +if [ "$?" == "0" ]; then + echo '['$LOGTIME'] Brook No Problem.' +else + /usr/bin/wget --spider --quiet --tries=1 --timeout=3 www.baidu.com + if [ "$?" == "0" ]; then + echo '['$LOGTIME'] Problem decteted, restarting Brook...' + /etc/init.d/brookpro restart + else + echo '['$LOGTIME'] Network Problem. Do nothing.' + fi +fi + +#sleep 3 + +#iptables -t nat -D OUTPUT -p tcp -d $GOOGLE -j REDIRECT --to-port 7070 + + + + + + + + + diff --git a/package/lean/luci-app-brook-pro/root/etc/brook/up-gfwlist.sh b/package/lean/luci-app-brook-pro/root/etc/brook/up-gfwlist.sh new file mode 100755 index 000000000..92b134ddf --- /dev/null +++ b/package/lean/luci-app-brook-pro/root/etc/brook/up-gfwlist.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +/etc/shadowsocksr/gen-gfwlist.sh > /tmp/ol-gfw.txt + +if [ -s "/tmp/ol-gfw.txt" ];then + sort -u /etc/shadowsocksr/base-gfwlist.txt /tmp/ol-gfw.txt > /tmp/china-banned + if ( ! cmp -s /tmp/china-banned /etc/gfwlist/china-banned );then + if [ -s "/tmp/china-banned" ];then + mv /tmp/china-banned /etc/gfwlist/china-banned + echo "Update GFW-List Done!" + fi + else + echo "GFW-List No Change!" + fi +fi + +rm -f /tmp/gfwlist.txt +rm -f /tmp/ol-gfw.txt + +/etc/init.d/ssrpro restart + diff --git a/package/lean/luci-app-brook-pro/root/etc/config/brook b/package/lean/luci-app-brook-pro/root/etc/config/brook new file mode 100644 index 000000000..253c60564 --- /dev/null +++ b/package/lean/luci-app-brook-pro/root/etc/config/brook @@ -0,0 +1,13 @@ + +config brook + option gfwlist 'china-banned' + option server 'serv-ro.ddns.info' + option server_port '23143' + option password 'test.TEST' + option method 'aes-256-cfb' + option protocol 'origin' + option obfs 'plain' + option enabled '0' + option proxy_mode 'M' + option safe_dns_tcp '1' + option cron_mode '1' diff --git a/package/lean/luci-app-brook-pro/root/etc/init.d/brookpro b/package/lean/luci-app-brook-pro/root/etc/init.d/brookpro new file mode 100755 index 000000000..e13f9918f --- /dev/null +++ b/package/lean/luci-app-brook-pro/root/etc/init.d/brookpro @@ -0,0 +1,381 @@ +#!/bin/sh /etc/rc.common +# +# + +START=99 + +SS_REDIR_PORT=7070 +SS_REDIR_PIDFILE=/var/run/brook-go.pid +PDNSD_LOCAL_PORT=7453 +CRON_FILE=/etc/crontabs/root +CONFIG=brook + + +# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + # $covered_subnets, $local_addresses are not required +covered_subnets=`uci get brook.@brook[0].covered_subnets 2>/dev/null` +local_addresses=`uci get brook.@brook[0].local_addresses 2>/dev/null` + # Get LAN settings as default parameters + [ -f /lib/functions/network.sh ] && . /lib/functions/network.sh + [ -z "$covered_subnets" ] && network_get_subnet covered_subnets lan + [ -z "$local_addresses" ] && network_get_ipaddr local_addresses lan +vt_np_ipset="china" # Must be global variable + +__gfwlist_by_mode() +{ + case "$1" in + V) echo unblock-youku;; + *) echo china-banned;; + esac +} + + + +# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +start() +{ + local vt_enabled=`uci get brook.@brook[0].enabled 2>/dev/null` + local vt_server_addr=`uci get brook.@brook[0].server` + local vt_server_port=`uci get brook.@brook[0].server_port` + local vt_password=`uci get brook.@brook[0].password 2>/dev/null` + local vt_method=`uci get brook.@brook[0].method` + local vt_protocol=`uci get brook.@brook[0].protocol` + local vt_protoparam=`uci get brook.@brook[0].protoparam 2>/dev/null` + local vt_obfs=`uci get brook.@brook[0].obfs` + local vt_timeout=`uci get brook.@brook[0].timeout 2>/dev/null` + local vt_safe_dns=`uci get brook.@brook[0].safe_dns 2>/dev/null` + local vt_safe_dns_port=`uci get brook.@brook[0].safe_dns_port 2>/dev/null` + local vt_safe_dns_tcp=`uci get brook.@brook[0].safe_dns_tcp 2>/dev/null` + local vt_proxy_mode=`uci get brook.@brook[0].proxy_mode` + local obfs_param=`uci get brook.@brook[0].obfs_param 2>/dev/null` + local cron_mode=`uci get brook.@brook[0].cron_mode 2>/dev/null` + local vt_gfwlist=`__gfwlist_by_mode $vt_proxy_mode` + + [ -f /etc/init.d/pdnsd ] && /etc/init.d/pdnsd disable 2>/dev/null + + # ----------------------------------------------------------------- + if [ "$vt_enabled" = 0 ]; then + echo "WARNING: Brook is disabled." + return 1 + fi + + if [ -z "$vt_server_addr" -o -z "$vt_server_port" ]; then + echo "WARNING: Brook not fully configured, not starting." + return 1 + fi + + [ -z "$vt_proxy_mode" ] && vt_proxy_mode=M + [ -z "$vt_method" ] && vt_method=table + [ -z "$vt_timeout" ] && vt_timeout=60 + case "$vt_proxy_mode" in + M|S|G) + [ -z "$vt_safe_dns" ] && vt_safe_dns="8.8.8.8" + [ -z "$vt_safe_dns_tcp" ] && vt_safe_dns_tcp=1 + ;; + esac + [ -z "$vt_safe_dns_port" ] && vt_safe_dns_port=53 + + # ----------------------------------------------------------------- + + /usr/bin/brook tproxy -l 127.0.0.1:1080 -s $vt_server_addr:$vt_server_port -p $vt_password &>/dev/null & + + # IPv4 firewall rules + add_rule + + # ----------------------------------------------------------------- + mkdir -p /var/etc/dnsmasq-go.d + ###### Anti-pollution configuration ###### + if [ -n "$vt_safe_dns" ]; then + if [ "$vt_safe_dns_tcp" = 1 ]; then + start_pdnsd "$vt_safe_dns" + awk -vs="127.0.0.1#$PDNSD_LOCAL_PORT" '!/^$/&&!/^#/{printf("server=/%s/%s\n",$0,s)}' \ + /etc/gfwlist/$vt_gfwlist > /var/etc/dnsmasq-go.d/01-pollution.conf + else + awk -vs="$vt_safe_dns#$vt_safe_dns_port" '!/^$/&&!/^#/{printf("server=/%s/%s\n",$0,s)}' \ + /etc/gfwlist/$vt_gfwlist > /var/etc/dnsmasq-go.d/01-pollution.conf + fi + else + echo "WARNING: Not using secure DNS, DNS resolution might be polluted if you are in China." + fi + + ###### dnsmasq-to-ipset configuration ###### + case "$vt_proxy_mode" in + M|V) + awk '!/^$/&&!/^#/{printf("ipset=/%s/'"$vt_gfwlist"'\n",$0)}' \ + /etc/gfwlist/$vt_gfwlist > /var/etc/dnsmasq-go.d/02-ipset.conf + ;; + esac + + # ----------------------------------------------------------------- + ###### Restart main 'dnsmasq' service if needed ###### + if ls /var/etc/dnsmasq-go.d/* >/dev/null 2>&1; then + mkdir -p /tmp/dnsmasq.d + cat > /tmp/dnsmasq.d/dnsmasq-go.conf </dev/null + del_cron +} + +restart() +{ + KEEP_GFWLIST=Y + stop + start +} + +reload() +{ + local vt_enabled=`uci get brook.@brook[0].enabled 2>/dev/null` + local vt_server_addr=`uci get brook.@brook[0].server` + local vt_server_port=`uci get brook.@brook[0].server_port` + local vt_safe_dns=`uci get brook.@brook[0].safe_dns 2>/dev/null` + local vt_safe_dns_port=`uci get brook.@brook[0].safe_dns_port 2>/dev/null` + local vt_safe_dns_tcp=`uci get brook.@brook[0].safe_dns_tcp 2>/dev/null` + local vt_proxy_mode=`uci get brook.@brook[0].proxy_mode` + local vt_gfwlist=`__gfwlist_by_mode $vt_proxy_mode` + KEEP_GFWLIST=Y + del_rule + add_rule + if [ "$vt_safe_dns_tcp" = 1 ]; then + stop_pdnsd + start_pdnsd + fi +} + +# $1: upstream DNS server +start_pdnsd() +{ + local safe_dns="$1" + + local tcp_dns_list="208.67.222.222, 208.67.220.220" + [ -n "$safe_dns" ] && tcp_dns_list="$safe_dns,$tcp_dns_list" + + #killall -9 pdnsd 2>/dev/null && sleep 1 + kill -9 $(cat /var/run/pdnsd.pid) >/dev/null 2>&1 + + mkdir -p /var/etc /var/pdnsd + if ! test -f "/var/pdnsd/pdnsd.cache"; then + dd if=/dev/zero of="/var/pdnsd/pdnsd.cache" bs=1 count=4 2> /dev/null + chown -R nobody.nogroup /var/pdnsd + fi + + cat > /var/etc/pdnsd.conf </dev/null; then + while iptables -t nat -D OUTPUT -p tcp --dport 53 -j pdnsd_output 2>/dev/null; do :; done + iptables -t nat -X pdnsd_output + fi + killall -9 pdnsd 2>/dev/null + rm -rf /var/pdnsd + rm -f /var/etc/pdnsd.conf +} + +add_cron() +{ + sed -i '/up-gfwlist.sh/d' $CRON_FILE + sed -i '/brook_watchdog.log/d' $CRON_FILE + if [ $cron_mode -eq 1 ]; then + echo '0 5 * * * /etc/brook/up-gfwlist.sh > /tmp/gfwupdate.log 2>&1' >> $CRON_FILE + fi + echo '0 */1 * * * /etc/brook/ssr-watchdog >> /tmp/brook_watchdog.log 2>&1' >> $CRON_FILE + echo '0 1 * * 0 echo "" > /tmp/brook_watchdog.log' >> $CRON_FILE + crontab $CRON_FILE +} + +del_cron() +{ + sed -i '/up-gfwlist.sh/d' $CRON_FILE + sed -i '/brook_watchdog.log/d' $CRON_FILE + /etc/init.d/cron restart +} + + + +uci_get_by_name() { + local ret=$(uci get $CONFIG.$1.$2 2>/dev/null) + echo ${ret:=$3} +} + +uci_get_by_type() { + local index=0 + if [ -n $4 ]; then + index=$4 + fi + local ret=$(uci get $CONFIG.@$1[$index].$2 2>/dev/null) + echo ${ret:=$3} +} + +add_rule() +{ + /usr/bin/ip rule add fwmark 1 lookup 100 + iptables -t mangle -N brook_pre + iptables -t mangle -F brook_pre + iptables -t mangle -A brook_pre -m set --match-set local dst -j RETURN || { + iptables -t mangle -A brook_pre -d 0.0.0.0/8 -j RETURN + iptables -t mangle -A brook_pre -d 10.0.0.0/8 -j RETURN + iptables -t mangle -A brook_pre -d 127.0.0.0/8 -j RETURN + iptables -t mangle -A brook_pre -d 169.254.0.0/16 -j RETURN + iptables -t mangle -A brook_pre -d 172.16.0.0/12 -j RETURN + iptables -t mangle -A brook_pre -d 192.168.0.0/16 -j RETURN + iptables -t mangle -A brook_pre -d 224.0.0.0/4 -j RETURN + iptables -t mangle -A brook_pre -d 240.0.0.0/4 -j RETURN + iptables -t mangle -A brook_pre -d $vt_server_add -j RETURN + } + + iptables -t mangle -A brook_pre -j MARK --set-mark 1 + iptables -t mangle -A brook_pre -j ACCEPT + + iptables -t mangle -A PREROUTING -p tcp -m socket -j brook_pre + iptables -t mangle -A PREROUTING -p tcp -j TPROXY --tproxy-mark 0x1/0x1 --on-port 7070 + + iptables -t mangle -A PREROUTING -p udp -m socket -j brook_pre + iptables -t mangle -A PREROUTING -p udp -j TPROXY --tproxy-mark 0x1/0x1 --on-port 7070 + + iptables -N gameboost -t mangle + ipset -! create gameuser hash:ip maxelem 65536 2>/dev/null + /usr/bin/ip rule add fwmark 0x01/0x01 table 100 + /usr/bin/ip route add local 0.0.0.0/0 dev lo table 100 + iptables -t mangle -A gameboost -p udp -m set --match-set local dst -j RETURN + iptables -t mangle -A gameboost -p udp -m set --match-set china dst -j RETURN + iptables -t mangle -A gameboost -p udp --dport 53 -j RETURN + iptables -t mangle -A gameboost -p udp -j TPROXY --on-port 7070 --tproxy-mark 0x01/0x01 + iptables -t mangle -A PREROUTING -m set --match-set gameuser src -j gameboost + + for i in $(seq 0 100) + do + local ip=$(uci_get_by_type acl_rule ipaddr '' $i) + local mode=$(uci_get_by_type acl_rule filter_mode '' $i) + case "$mode" in + disable) + iptables -t nat -A brook_pre -s $ip -j RETURN + ;; + global) + iptables -t nat -A brook_pre -s $ip -p tcp -j REDIRECT --to $SS_REDIR_PORT + iptables -t nat -A brook_pre -s $ip -j RETURN + ;; + game) + iptables -t nat -A brook_pre -p tcp -s $ip -m set ! --match-set china dst -j REDIRECT --to $SS_REDIR_PORT + ipset -! add gameuser $ip + ;; + esac + done + + case "$vt_proxy_mode" in + G) : ;; + S) + iptables -t nat -A brook_pre -m set --match-set $vt_np_ipset dst -j RETURN + iptables -t nat -I OUTPUT -p tcp -m multiport --dports 80,443 -m set ! --match-set $vt_np_ipset dst -j REDIRECT --to $SS_REDIR_PORT + ;; + M) + ipset -! create $vt_gfwlist hash:ip maxelem 65536 2>/dev/null + awk '!/^$/&&!/^#/{printf("add vt_gfwlist %s'" "'\n",$0)}' /etc/brook/addinip.txt > /tmp/addinip.ipset + sed -i "s/vt_gfwlist/$vt_gfwlist/g" /tmp/addinip.ipset + ipset -! restore < /tmp/addinip.ipset + iptables -t nat -A brook_pre -m set ! --match-set $vt_gfwlist dst -j RETURN + iptables -t nat -A brook_pre -m set --match-set $vt_np_ipset dst -j RETURN + iptables -t nat -I OUTPUT -p tcp -m multiport --dports 80,443 -m set --match-set $vt_gfwlist dst -j REDIRECT --to $SS_REDIR_PORT + ;; + V) + vt_np_ipset="" + ipset -! create $vt_gfwlist hash:ip maxelem 65536 2>/dev/null + iptables -t nat -A brook_pre -m set ! --match-set $vt_gfwlist dst -j RETURN + ;; + esac + local subnet + for subnet in $covered_subnets; do + iptables -t nat -A brook_pre -s $subnet -p tcp -j REDIRECT --to $SS_REDIR_PORT + done + iptables -t nat -I PREROUTING -p tcp -j brook_pre +} + +del_rule() +{ + if iptables -t nat -F brook_pre 2>/dev/null; then + while iptables -t nat -D PREROUTING -p tcp -j brook_pre 2>/dev/null; do :; done + iptables -t nat -X brook_pre 2>/dev/null + fi + + iptables -t nat -D OUTPUT -p tcp -m multiport --dports 80,443 -m set --match-set china-banned dst -j REDIRECT --to $SS_REDIR_PORT 2>/dev/null + iptables -t nat -D OUTPUT -p tcp -m multiport --dports 80,443 -m set ! --match-set $vt_np_ipset dst -j REDIRECT --to $SS_REDIR_PORT 2>/dev/null + + /usr/bin/ip rule del fwmark 0x01/0x01 table 100 + /usr/bin/ip route del local 0.0.0.0/0 dev lo table 100 + if iptables -t mangle -F gameboost 2>/dev/null; then + while iptables -t mangle -D PREROUTING -m set --match-set gameuser src -j gameboost 2>/dev/null; do :; done + iptables -t mangle -X gameboost 2>/dev/null + fi + + ipset destroy gameuser 2>/dev/null + + + # ----------------------------------------------------------------- + [ "$KEEP_GFWLIST" = Y ] || ipset destroy "$vt_gfwlist" 2>/dev/null +} diff --git a/package/lean/luci-app-brook-pro/root/etc/uci-defaults/brook b/package/lean/luci-app-brook-pro/root/etc/uci-defaults/brook new file mode 100755 index 000000000..4b6c24549 --- /dev/null +++ b/package/lean/luci-app-brook-pro/root/etc/uci-defaults/brook @@ -0,0 +1,16 @@ +#!/bin/sh + +uci -q batch <<-EOF >/dev/null + delete firewall.brook + set firewall.brook=include + set firewall.brook.type=script + set firewall.brook.path=/etc/brook.include + set firewall.brook.reload=1 + commit firewall +EOF + +/etc/init.d/brookpro stop +/etc/init.d/brookpro disable + +rm -f /tmp/luci-indexcache +exit 0 diff --git a/package/lean/luci-app-ipsec-vpnd/Makefile b/package/lean/luci-app-ipsec-vpnd/Makefile index 1bf6299b6..0796b36c1 100644 --- a/package/lean/luci-app-ipsec-vpnd/Makefile +++ b/package/lean/luci-app-ipsec-vpnd/Makefile @@ -9,7 +9,7 @@ LUCI_TITLE:=LuCI support for IPSec VPN Server (IKEv1 with PSK and Xauth) LUCI_DEPENDS:=+strongswan-minimal +strongswan-mod-xauth-generic LUCI_PKGARCH:=all PKG_VERSION:=2.0 -PKG_RELEASE:=6 +PKG_RELEASE:=8 include $(TOPDIR)/feeds/luci/luci.mk diff --git a/package/lean/luci-app-ipsec-vpnd/root/etc/ipsec.include b/package/lean/luci-app-ipsec-vpnd/root/etc/ipsec.include index d887c623d..5c7108080 100755 --- a/package/lean/luci-app-ipsec-vpnd/root/etc/ipsec.include +++ b/package/lean/luci-app-ipsec-vpnd/root/etc/ipsec.include @@ -7,3 +7,5 @@ iptables -I FORWARD -m policy --dir in --pol ipsec --proto esp -j ACCEPT iptables -I FORWARD -m policy --dir out --pol ipsec --proto esp -j ACCEPT iptables -I INPUT -m policy --dir in --pol ipsec --proto esp -j ACCEPT iptables -I OUTPUT -m policy --dir out --pol ipsec --proto esp -j ACCEPT + +echo 1 > /proc/sys/net/ipv4/conf/br-lan/proxy_arp diff --git a/package/lean/luci-app-ipsec-vpnd/root/etc/ipsecvpn b/package/lean/luci-app-ipsec-vpnd/root/etc/ipsecvpn index 023ad2e36..18ec103d6 100755 --- a/package/lean/luci-app-ipsec-vpnd/root/etc/ipsecvpn +++ b/package/lean/luci-app-ipsec-vpnd/root/etc/ipsecvpn @@ -34,7 +34,7 @@ config setup conn xauth_psk keyexchange=ikev1 - ike=aes128-sha1-modp2048,3des-sha1-modp1536 + ike=aes128-sha1-modp2048,aes128-sha1-modp1024,3des-sha1-modp1024,3des-sha1-modp1536 esp=aes128-sha1,3des-sha1 left=%defaultroute leftauth=psk diff --git a/package/lean/luci-app-oscam/luasrc/controller/admin/sattv.lua b/package/lean/luci-app-oscam/luasrc/controller/admin/sattv.lua deleted file mode 100644 index 03f2b172f..000000000 --- a/package/lean/luci-app-oscam/luasrc/controller/admin/sattv.lua +++ /dev/null @@ -1,16 +0,0 @@ -module("luci.controller.admin.sattv", package.seeall) - -function index() - --- entry({"admin", "Others"}, cbi("sattv/epg"), i18n("Others"), 70) - - if nixio.fs.access("/etc/config/epg") then - entry({"admin", "Others"}, cbi("sattv/epg"), _("sattv"), 66).index = true - entry({"admin", "Others", "epg"}, cbi("sattv/epg"), _("EPG"), 1).i18n = "diskapply" - end - - if nixio.fs.access("/etc/config/oscam") then - entry({"admin", "Others", "oscam"}, cbi("sattv/oscam"), _("OSCAM"), 12).i18n = "diskapply" - end - -end diff --git a/package/lean/luci-app-oscam/luasrc/model/cbi/sattv/epg.lua b/package/lean/luci-app-oscam/luasrc/model/cbi/sattv/epg.lua deleted file mode 100644 index da46cad90..000000000 --- a/package/lean/luci-app-oscam/luasrc/model/cbi/sattv/epg.lua +++ /dev/null @@ -1,50 +0,0 @@ -require("luci.tools.webadmin") - ---[[ -config epg_set - option enable 1 - option time 30 - option src_url http://dm.epg.net.cn/a/epg.xml - option src_url1 http://dm1.epg.net.cn/a/epg.xml - option src_url2 http://epg.xltvrobbs.net/atmosphere/epg/epg.xml - option src_url3 http://epg1.xltvrobbs.net/atmosphere/epg/epg.xml - -]]-- - - -m = Map("epg", translate("epg_title","Set epg download address"),translate("epg_desc", -"Set epg auto download for dm500 atmosphere")) - -s = m:section(TypedSection, "epg_set", translate("epgset","settings")) -s.anonymous = true -s.addremove = false - -enable = s:option(Flag, "enable", translate("enable", "enable")) -enable.default = false -enable.optional = false -enable.rmempty = false - -interval = s:option(Value, "interval", translate("interval","interval")) -interval.default = 30 -interval.optional = false -interval.rmempty = false - - -s = m:section(TypedSection, "downaddress", translate("downaddress","downaddress")) -s.template = "cbi/tblsection" -s.anonymous = false -s.addremove = true - -enable = s:option(Flag, "addr_enable", translate("enable", "enable")) -enable.default = false -enable.optional = false -enable.rmempty = false - - -url = s:option(Value, "address", translate("dowload address","dowload address")) -url.optional = false -url.rmempty = false - - -return m - diff --git a/package/lean/luci-app-oscam/luasrc/model/cbi/sattv/oscam.lua b/package/lean/luci-app-oscam/luasrc/model/cbi/sattv/oscam.lua deleted file mode 100644 index 44a19fcfd..000000000 --- a/package/lean/luci-app-oscam/luasrc/model/cbi/sattv/oscam.lua +++ /dev/null @@ -1,67 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface - -Copyright 2011 flyzjhz - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -]]-- - - -local fs = require "nixio.fs" -local uci = require "luci.model.uci".cursor() -local lanipaddr = uci:get("network", "lan", "ipaddr") or "192.168.1.1" ---- Retrieves the output of the "get_oscam_port" command. --- @return String containing the current get_oscam_port -function get_oscam_port() - - local oscam_conf= fs.readfile("/usr/oscam/oscam.conf") - local oscam_conf_port = tonumber(oscam_conf:match("[Hh]ttppor[Tt].-= ([^\n]+)")) or "8899" - return oscam_conf_port -end - -local oscamport = get_oscam_port() - -m = Map("oscam", translate("OSCAM","OSCAM"),translate("oscam desc", -"oscam for openwrt")) - -s = m:section(TypedSection, "setting", translate("set","settings")) -s.anonymous = true -s.addremove = false - -enable = s:option(Flag, "enable", translate("enable", "enable")) -enable.default = false -enable.optional = false -enable.rmempty = false - -interval = s:option(Value, "interval", translate("interval","interval"), -translate("interval_desc","interval_desc")) -interval.optional = false -interval.rmempty = false -interval.default = 30 - -s:option(DummyValue,"oscamweb" ,translate("OSCAM Web Intelface "),translate("Open the oscam Web")) - -tmpl = s:option(Value, "_tmpl", - translate("Edit oscam configuration."), - translate("This is the content of the file '/usr/oscam/oscam.conf'")) - -tmpl.template = "cbi/tvalue" -tmpl.rows = 20 - -function tmpl.cfgvalue(self, section) - return nixio.fs.readfile("/usr/oscam/oscam.conf") -end - -function tmpl.write(self, section, value) - value = value:gsub("\r\n?", "\n") - nixio.fs.writefile("//usr/oscam/oscam.conf", value) -end - -return m - - diff --git a/package/lean/luci-app-oscam/root/etc/config/epg b/package/lean/luci-app-oscam/root/etc/config/epg deleted file mode 100644 index 9c2791f68..000000000 --- a/package/lean/luci-app-oscam/root/etc/config/epg +++ /dev/null @@ -1,13 +0,0 @@ - -config 'epg_set' - option 'enable' '0' - option 'interval' '30' - -config 'downaddress' 'epg1' - option 'addr_enable' '1' - option 'address' 'http://dm.epg.net.cn/a/epg.xml' - -config 'downaddress' 'epg2' - option 'addr_enable' '1' - option 'address' 'http://epg.xltvrobbs.net/atmosphere/epg/epg.xml' - diff --git a/package/lean/luci-app-oscam/root/etc/config/oscam b/package/lean/luci-app-oscam/root/etc/config/oscam deleted file mode 100644 index 795ea4e3c..000000000 --- a/package/lean/luci-app-oscam/root/etc/config/oscam +++ /dev/null @@ -1,4 +0,0 @@ - -config 'setting' - option 'enable' '0' - diff --git a/package/lean/luci-app-oscam/root/etc/init.d/epg b/package/lean/luci-app-oscam/root/etc/init.d/epg deleted file mode 100755 index 9b9014cdd..000000000 --- a/package/lean/luci-app-oscam/root/etc/init.d/epg +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh /etc/rc.common -# copyrights -# (1)epg dowload Script VER 0.10for openwrt by zjhzzyf - - - -START=96 - - - -start(){ - - - /usr/bin/epg start -} - -stop() { - echo "not implemented yet!" -} - -restart() { - start -} \ No newline at end of file diff --git a/package/lean/luci-app-oscam/root/etc/init.d/oscam b/package/lean/luci-app-oscam/root/etc/init.d/oscam deleted file mode 100755 index ca40a3608..000000000 --- a/package/lean/luci-app-oscam/root/etc/init.d/oscam +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh /etc/rc.common -# oscam Script VER 0.10 for openwrt by zjhzzyf - -START=94 - -. /etc/functions.sh -path="/usr/oscam/" - - -kill_oscam() -{ -local otherpids -local execute -otherpids=$(ps -a 2>&1 | grep "/usr/bin/oscam" | grep -v $$ | awk -F " " '{print $1}') -echo "$otherpids" | while read execute -do -kill -9 ${execute} -done -} - - - -oscam_start() -{ - - /usr/bin/oscam -b -c $path - echo "readdy go....." - -} - - - -start(){ -echo "game start....." - enable=$(uci get oscam.@setting[0].enable) - if [ "$enable" == "" ];then - enable=0 - fi - - [ "$enable" == "1" ]&&oscam_start - -interval=$(uci get oscam.@setting[0].interval) -oscam_cron=`cat /etc/crontabs/root | grep "/etc/init.d/oscam restart"` -if [ "$enable" == "1" -a "$interval" != "0" ]; then - oscam_new="*/${interval} * * * * /etc/init.d/oscam restart" - if [ "z${oscam_cron}" != "z${oscam_new}" ] ; then - cat /etc/crontabs/root | grep -v "/etc/init.d/oscam restart" > /tmp/crontabs_oscam - echo "" >> /tmp/crontabs_oscam - echo "*/${interval} * * * * /etc/init.d/oscam restart" >> /tmp/crontabs_oscam - cat /tmp/crontabs_oscam | grep -v ^$ > /etc/crontabs/root - /etc/init.d/cron restart - fi -else - if [ "z${oscam_cron}" != "z" ] ; then - cat /etc/crontabs/root | grep -v "/etc/init.d/oscam restart" > /tmp/crontabs_oscam - cat /tmp/crontabs_oscam | grep -v ^$ > /etc/crontabs/root - /etc/init.d/cron restart - fi - -fi -rm -f /tmp/crontabs_oscam - -} - -stop() { - kill_oscam - echo "oscam stopped" -} - - diff --git a/package/lean/luci-app-oscam/root/etc/oscam/oscam.conf b/package/lean/luci-app-oscam/root/etc/oscam/oscam.conf deleted file mode 100644 index 51abc783f..000000000 --- a/package/lean/luci-app-oscam/root/etc/oscam/oscam.conf +++ /dev/null @@ -1,39 +0,0 @@ -# oscam.conf generated automatically by Streamboard OSCAM 1.00-unstable_svn build #r4503 -# Read more: http://streamboard.gmc.to/oscam/browser/trunk/Distribution/doc/txt/oscam.conf.txt - -[global] -logfile = /dev/shm/oscam.log -disablelog = 1 -clientmaxidle = 36000 -bindwait = 5 -netprio = 9 -nice = 9 -waitforcards = 0 -lb_mode = 1 - -[monitor] -port = 9988 -nocrypt = -aulow = 120 -hideclient_to = 0 -monlevel = 255 -appendchaninfo = 0 - -[dvbapi] -enabled = 1 -au = 1 -boxtype = none -user = user1 -pmt_mode = 0 -request_mode = 0 - -[webif] -httpport = 8899 -httpuser = oscam -httppwd = oscam -httprefresh = 0 -httpallowed = 1.0.0.0-255.255.0.0 -httphideidleclients = 0 -httpreadonly = 0 -httpsavefullcfg = 0 - diff --git a/package/lean/luci-app-oscam/root/etc/oscam/oscam.server b/package/lean/luci-app-oscam/root/etc/oscam/oscam.server deleted file mode 100644 index 876103ba0..000000000 --- a/package/lean/luci-app-oscam/root/etc/oscam/oscam.server +++ /dev/null @@ -1,28 +0,0 @@ -# oscam.server generated automatically by Streamboard OSCAM 1.00-unstable_svn build #r4503 -# Read more: http://streamboard.gmc.to/oscam/browser/trunk/Distribution/doc/txt/oscam.server.txt - -[reader] -label = reshare1 -enable = 0 -protocol = cccam -device = oscam.3322.org,13111 -user = test01 -password = test01 -inactivitytimeout = 1 -reconnecttimeout = 3 -group = 1 -blockemm-unknown = 1 -blockemm-u = 1 -blockemm-s = 1 -blockemm-g = 1 -lb_weight = 100 -cccversion = 2.1.2 -cccmaxhops = 12 -ccckeepalive = 1 -audisabled = 1 -cccdisableautoblock = 1 - - - - - diff --git a/package/lean/luci-app-oscam/root/etc/oscam/oscam.user b/package/lean/luci-app-oscam/root/etc/oscam/oscam.user deleted file mode 100644 index f02c1bc84..000000000 --- a/package/lean/luci-app-oscam/root/etc/oscam/oscam.user +++ /dev/null @@ -1,6 +0,0 @@ -[account] -user = 001 -pwd = 001 -group = 1 -keepalive = 1 -uniq = 0 diff --git a/package/lean/luci-app-oscam/root/etc/uci-defaults/luci-sattv b/package/lean/luci-app-oscam/root/etc/uci-defaults/luci-sattv deleted file mode 100644 index a9e759580..000000000 --- a/package/lean/luci-app-oscam/root/etc/uci-defaults/luci-sattv +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@epg[-1] - add ucitrack epg - set ucitrack.@epg[-1].init=epg - delete ucitrack.@oscam[-1] - add ucitrack oscam - set ucitrack.@oscam[-1].init=oscam - add_list ucitrack.@oscam[-1].affects=cron - commit ucitrack -EOF -rm -f /tmp/luci-indexcache -exit 0 diff --git a/package/lean/luci-app-oscam/root/usr/bin/epg b/package/lean/luci-app-oscam/root/usr/bin/epg deleted file mode 100755 index e51b91fc4..000000000 --- a/package/lean/luci-app-oscam/root/usr/bin/epg +++ /dev/null @@ -1,199 +0,0 @@ -#!/bin/sh -# copyrights -# (1)epg dowload Script VER 0.10for openwrt by zjhzzyf - - -. /lib/functions.sh - - -epg_down() -{ - bsuc=1 - echo "File Path:"$path - filename="epg.xml" - echo "Setup FileName:"$filename - sfullfilename=`echo $path$filename` - echo "sFullFileName:"$sfullfilename - - index=0 - echo "Try Times Max:"$trytimes - while [ "$index" -lt "$trytimes" ] - do - echo "Try Times:"$index - if wget -qO- -t3 $url > $sfullfilename;then - break - fi - index=`expr $index + 1` - done - if [ "$index" -eq "$trytimes" ]; then - ErrMsg=`date` - ErrMsg=$ErrMsg" 下载é…置文件失败" - bsuc=0 - return - fi - echo "down $filename completed" -mfullfilename=`echo ${path}store/${filename}.md5` - echo "MD5 File Name:"$mfullfilename - md5old=`cat $mfullfilename` - md5old=`echo $md5old|awk '{print $1}'|tr "[a-z]" "[A-Z]"` - echo "Old File MD5:"$md5old - md5new=`/usr/bin/md5sum $sfullfilename` - md5new=`echo $md5new|awk '{print $1}'|tr "[a-z]" "[A-Z]"` - echo "New File MD5:"$md5new - if [ "$md5old" = "$md5new" ]; then - ErrMsg=`date` - ErrMsg=$ErrMsg" æ•°æ®ä¸éœ€è¦æ›´æ–°" - bsuc=1 - return - else - - counttimes=0 - suctimes=0 - counttimes=`expr $counttimes + 1` - url=$(grep -m 1 "URL" $sfullfilename |awk -F "" '{print $2}'|awk -F "" '{print $1}') - echo "Down Data URL:" $url - -filename=`echo ${url##*/}` - echo "Down File Name:"$filename - - echo "=====" -echo $url - replaces=`echo ${url%/*}` - -replaces=`echo ${replaces#*//}` - - echo replaces: $replaces - echo -e `sed -e "s#$replaces#$replaced#g" $sfullfilename` > `echo $sfullfilename` - echo "=====" - - dfullfilename=`echo $path$filename` - echo "Down Data Save File Name:"$dfullfilename - - index=0 - while [ "$index" -lt "$trytimes" ] - do - echo "Try Times:"$index - if wget -t3 -T120 -qO- $url > $dfullfilename;then - suctimes=`expr $suctimes + 1` - - break - fi - index=`expr $index + 1` - - done - - if [ "$index" -eq "$trytimes" ]; then - bsuc=0 - ErrMsg=`date` - ErrMsg=$ErrMsg" 下载"$url"失败" - - fi - - - if [ "$counttimes" -eq "$suctimes" ]; then - echo $md5new > `echo $mfullfilename` - -mount -o bind /tmp/epg/ /www/atmosphere - rm -rf ${path}/epg/* - -cp ${path}$filename ${path}/epg -cp ${path}epg.xml ${path}/epg - rm -rf ${path}$filename - rm -rf ${path}epg.xml - ErrMsg=`date` - ErrMsg=$ErrMsg" 下载EPGæ•°æ®æˆåŠŸ" - echo $ErrMsg - exit 0 - else - ErrMsg=`date` - ErrMsg= $ErrMsg " 未知原因失败" - fi - fi -} - - -epg_start() { - -config_get enable $1 enable -config_get interval $1 interval -[ "$enable" = "" ]&&enable=0 - -#make scheduler - -epg_cron=`cat /etc/crontabs/root | grep "/usr/bin/epg scheduler"` -if [ "$enable" == "1" -a "${interval}" != "0" ]; then - mkdir -p /tmp/epg/ - mkdir -p /tmp/epg/store - mkdir -p /tmp/epg/epg - mkdir -p /www/atmosphere - epg_new="*/${interval} * * * * /usr/bin/epg scheduler" - if [ "z${epg_cron}" != "z${epg_new}" ] ; then - cat /etc/crontabs/root | grep -v "/etc/init.d/epg scheduler" > /tmp/crontabs_epg - echo "*/${interval} * * * * /etc/init.d/epg scheduler" >> /tmp/crontabs_epg - echo "" >> /tmp/crontabs_epg - cat /tmp/crontabs_epg | grep -v ^$ > /etc/crontabs/root - /etc/init.d/cron restart - fi -else - if [ "z${epg_cron}" != "z" ] ; then - cat /etc/crontabs/root | grep -v "/etc/init.d/epg scheduler" > /tmp/crontabs_epg - cat /tmp/crontabs_epg | grep -v ^$ > /etc/crontabs/root - /etc/init.d/cron restart - fi -rm -f /tmp/crontabs_epg - -fi - -/etc/init.d/cron restart - -} - - -con_get_addr(){ - - config_get addr_enable $1 addr_enable - config_get address $1 address - -[ "$addr_enable" == "1" ]&&{ -url=$address -echo $url -ErrMsg=`date` -ErrMsg=$ErrMsg" 开始从"$url"下载" -echo $ErrMsg >> `echo /tmp/epglog.txt` -rm `echo $path"*"` -epg_down -echo $ErrMsg >> `echo /tmp/epglog.txt` -echo $bsuc -echo "******************************************************************" >> `echo /tmp/epglog.txt` -} -} - - - -epg_scheduler(){ - -path="/tmp/epg/" -trytimes=3 -bsuc=1 -ErrMsg="" -lan_ipaddr=$(uci get network.lan.ipaddr) -replaced="${lan_ipaddr}/atmosphere/epg" - - -} - - -config_load epg -case "$1" in - start) - config_foreach epg_start epg_set - ;; - stop) - echo "stop test " - ;; - scheduler) - epg_scheduler - config_foreach con_get_addr downaddress -;; -esac - diff --git a/package/lean/luci-app-oscam/root/usr/oscam/oscam.conf b/package/lean/luci-app-oscam/root/usr/oscam/oscam.conf deleted file mode 100644 index a552326fe..000000000 --- a/package/lean/luci-app-oscam/root/usr/oscam/oscam.conf +++ /dev/null @@ -1,37 +0,0 @@ -[global] -# Prozess -nice = -10 -pidfile = /tmp/oscam.pid -# Logging -logfile = /tmp/oscam.log -disablelog = 0 -maxlogsize = 256 -usrfile = /tmp/oscam_user.log -disableuserfile = 0 -usrfileflag = 1 -# Timeouts - If you have problems adjust or remove rows! -clienttimeout = 2000 -fallbacktimeout = 1000 -serialreadertimeout = 800 -# Sonstiges -clientdyndns = 0 -unlockparental = 1 -saveinithistory = 1 - -[monitor] -port = 15990 -nocrypt = 127.0.0.1,192.168.1.1-192.168.1.255 # "No entry for other IP's!" -aulow = 30 -hideclient_to = 0 -monlevel = 4 -appendchaninfo = 0 - -[camd35] -port = 15991 - -[webif] -httpport = 16000 -httprefresh = 0 -httpallowed = 127.0.0.1,192.168.1.1-192.168.1.255 # "No entry for other IP's!" -httphideidleclients = 0 -httpreadonly = 0 diff --git a/package/lean/luci-app-samba4/Makefile b/package/lean/luci-app-samba4/Makefile new file mode 100644 index 000000000..ea0b25506 --- /dev/null +++ b/package/lean/luci-app-samba4/Makefile @@ -0,0 +1,11 @@ +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=LuCI for Samba4 +LUCI_DEPENDS:=+samba4x-server +LUCI_PKGARCH:=all +PKG_VERSION:=1.0 +PKG_RELEASE:=1 + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature \ No newline at end of file diff --git a/package/lean/luci-app-samba4/luasrc/controller/samba4.lua b/package/lean/luci-app-samba4/luasrc/controller/samba4.lua new file mode 100644 index 000000000..936b4dbd4 --- /dev/null +++ b/package/lean/luci-app-samba4/luasrc/controller/samba4.lua @@ -0,0 +1,28 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ +]]-- + +module("luci.controller.samba4", package.seeall) + +function index() + if not nixio.fs.access("/etc/config/samba4") then + return + end + + local page + + entry({"admin", "nas"}, firstchild(), "NAS", 45).dependent = false + page = entry({"admin", "nas", "samba4"}, cbi("samba4"), _("Network Shares")) + page.dependent = true +end diff --git a/package/lean/luci-app-samba4/luasrc/model/cbi/samba4.lua b/package/lean/luci-app-samba4/luasrc/model/cbi/samba4.lua new file mode 100644 index 000000000..6f36b8bb7 --- /dev/null +++ b/package/lean/luci-app-samba4/luasrc/model/cbi/samba4.lua @@ -0,0 +1,85 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ +]]-- + +m = Map("samba4", translate("Network Shares")) + +s = m:section(TypedSection, "samba", "Samba") +s.anonymous = true + +s:tab("general", translate("General Settings")) +s:tab("template", translate("Edit Template")) + +s:taboption("general", Flag, "enabled", translate("Enabled")) +s:taboption("general", Value, "name", translate("Hostname")) +s:taboption("general", Value, "description", translate("Description")) +s:taboption("general", Value, "workgroup", translate("Workgroup")) +s:taboption("general", Flag, "homes", translate("Share home-directories")) +s:taboption("general", Flag, "disablenb", translate("Disable netbios")) +s:taboption("general", Flag, "hotplug", translate("Hotplug"), translate("Automatically add to shares when new drives attached.")) + +tmpl = s:taboption("template", Value, "_tmpl", + translate("Edit the template that is used for generating the samba configuration."), + translate("This is the content of the file '/etc/samba/smb.conf.template' from which your samba configuration will be generated. " .. + "Values enclosed by pipe symbols ('|') should not be changed. They get their values from the 'General Settings' tab.")) + +tmpl.template = "cbi/tvalue" +tmpl.rows = 20 + +function tmpl.cfgvalue(self, section) + return nixio.fs.readfile("/etc/samba/smb.conf.template") +end + +function tmpl.write(self, section, value) + value = value:gsub("\r\n?", "\n") + nixio.fs.writefile("//etc/samba/smb.conf.template", value) +end + + +s = m:section(TypedSection, "sambashare", translate("Shared Directories")) +s.anonymous = true +s.addremove = true +s.template = "cbi/tblsection" + +s:option(Value, "name", translate("Name")) +pth = s:option(Value, "path", translate("Path")) +if nixio.fs.access("/etc/config/fstab") then + pth.titleref = luci.dispatcher.build_url("admin", "system", "fstab") +end + +s:option(Value, "users", translate("Allowed users")).rmempty = true + +ro = s:option(Flag, "read_only", translate("Read-only")) +ro.rmempty = false +ro.enabled = "yes" +ro.disabled = "no" + +go = s:option(Flag, "guest_ok", translate("Allow guests")) +go.rmempty = false +go.enabled = "yes" +go.disabled = "no" + +cm = s:option(Value, "create_mask", translate("Create mask")) +cm.rmempty = true +cm.size = 4 + +dm = s:option(Value, "dir_mask", translate("Directory mask")) +dm.rmempty = true +dm.size = 4 + +function m.on_commit(self,map) + require("luci.sys").call('/sbin/reload_config') +end + +return m diff --git a/package/lean/luci-app-samba4/root/etc/hotplug.d/block/20-samba4-hotplug.sh b/package/lean/luci-app-samba4/root/etc/hotplug.d/block/20-samba4-hotplug.sh new file mode 100755 index 000000000..c357ab67e --- /dev/null +++ b/package/lean/luci-app-samba4/root/etc/hotplug.d/block/20-samba4-hotplug.sh @@ -0,0 +1,57 @@ +#!/bin/sh +# Samba自动é…置脚本,å‚考PandoraBox的脚本框架并é‡å†™ã€‚以下为原脚本作者信æ¯ï¼š +#=================================================================================== +# +# D-Team Technology Co.,Ltd. ShenZhen +# 作者:Vic +# +# +# 警告:对ç€å±å¹•çš„哥们,我们å…许你使用此脚本,但ä¸å…许你抹去作者的信æ¯,请ä¿ç•™è¿™æ®µè¯ã€‚ +#=================================================================================== +. /lib/functions.sh + +set_samba(){ + section=$(echo $get_uuid | sed 's/-//g') + + uci set samba4.${section}="sambashare" + uci set samba4.${section}.name="Disk_${device}" + uci set samba4.${section}.path="${mountpoint}" + uci set samba4.${section}.read_only="no" + uci set samba4.${section}.guest_ok="yes" + uci commit samba4 +} +set_samba_path(){ + section=$(echo $get_uuid | sed 's/-//g') + + uci set samba4.${section}.path="${mountpoint}" + uci commit samba4 +} + + +device=`basename $DEVPATH` + +case "$ACTION" in + add) + + if [ z$(uci get samba4.@samba[0].hotplug) == z1 ] + then + case "$device" in + sd*) ;; + md*) ;; + hd*);; + mmcblk*);; + *) return;; + esac + + sleep 2 + mountpoint=`sed -ne "s|^[^ ]*/$device ||; T; s/ .*//p" /proc/self/mounts` + get_uuid=`block info | grep "/dev/${device}" | awk -F "UUID=" '{print $2}'| awk -F "\"" '{print $2}'` + have_uuid=$(uci show samba4 | grep -c "$get_uuid") + [ "$have_uuid" = "0" ] && set_samba + [ "$have_uuid" -gt "0" ] && set_samba_path + /etc/init.d/samba4 restart + fi + ;; + remove) + ;; +esac diff --git a/package/lean/luci-app-sfe/Makefile b/package/lean/luci-app-sfe/Makefile index d9611a3e4..66cc4c440 100644 --- a/package/lean/luci-app-sfe/Makefile +++ b/package/lean/luci-app-sfe/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI support for SFE -LUCI_DEPENDS:=+kmod-fast-classifier +LUCI_DEPENDS:=+kmod-fast-classifier @!LINUX_4_14 LUCI_PKGARCH:=all PKG_VERSION:=1.0 PKG_RELEASE:=3 diff --git a/package/lean/luci-app-udp2raw/LICENSE b/package/lean/luci-app-udp2raw/LICENSE deleted file mode 100644 index e963df829..000000000 --- a/package/lean/luci-app-udp2raw/LICENSE +++ /dev/null @@ -1,622 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - diff --git a/package/lean/luci-app-udp2raw/Makefile b/package/lean/luci-app-udp2raw/Makefile index 8ce589eed..e9af99d7f 100644 --- a/package/lean/luci-app-udp2raw/Makefile +++ b/package/lean/luci-app-udp2raw/Makefile @@ -9,26 +9,24 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-udp2raw PKG_VERSION:=1.0.0 -PKG_RELEASE:=1 +PKG_RELEASE:=4 PKG_LICENSE:=GPLv3 PKG_LICENSE_FILES:=LICENSE PKG_MAINTAINER:=Jian Chang -PKG_BUILD_PARALLEL:=1 - include $(INCLUDE_DIR)/package.mk -define Package/luci-app-udp2raw +define Package/$(PKG_NAME) SECTION:=luci CATEGORY:=LuCI SUBMENU:=3. Applications TITLE:=LuCI Support for udp2raw-tunnel PKGARCH:=all - DEPENDS:=+udp2raw-tunnel +# DEPENDS:=+udp2raw-tunnel endef -define Package/luci-app-udp2raw/description +define Package/$(PKG_NAME)/description LuCI Support for udp2raw-tunnel. endef @@ -43,28 +41,27 @@ endef define Build/Compile endef -define Package/luci-app-udp2raw/postinst +define Package/$(PKG_NAME)/postinst #!/bin/sh if [ -z "$${IPKG_INSTROOT}" ]; then ( . /etc/uci-defaults/luci-udp2raw ) && rm -f /etc/uci-defaults/luci-udp2raw - rm -rf /tmp/luci-indexcache /tmp/luci-modulecache fi exit 0 endef -define Package/luci-app-udp2raw/conffiles -/etc/config/udp2raw +define Package/$(PKG_NAME)/conffiles + /etc/config/udp2raw endef -define Package/luci-app-udp2raw/install +define Package/$(PKG_NAME)/install $(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n $(INSTALL_DATA) $(PKG_BUILD_DIR)/udp2raw.*.lmo $(1)/usr/lib/lua/luci/i18n/ $(INSTALL_DIR) $(1)/usr/lib/lua/luci/controller $(INSTALL_DATA) ./files/luci/controller/*.lua $(1)/usr/lib/lua/luci/controller/ $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi/udp2raw $(INSTALL_DATA) ./files/luci/model/cbi/udp2raw/*.lua $(1)/usr/lib/lua/luci/model/cbi/udp2raw/ - $(INSTALL_DIR) $(1)/usr/lib/lua/luci/view - $(INSTALL_DATA) ./files/luci/view/*.htm $(1)/usr/lib/lua/luci/view/ + $(INSTALL_DIR) $(1)/usr/lib/lua/luci/view/udp2raw + $(INSTALL_DATA) ./files/luci/view/udp2raw/*.htm $(1)/usr/lib/lua/luci/view/udp2raw/ $(INSTALL_DIR) $(1)/etc/config $(INSTALL_CONF) ./files/root/etc/config/udp2raw $(1)/etc/config/udp2raw $(INSTALL_DIR) $(1)/etc/init.d @@ -73,4 +70,4 @@ define Package/luci-app-udp2raw/install $(INSTALL_BIN) ./files/root/etc/uci-defaults/luci-udp2raw $(1)/etc/uci-defaults/luci-udp2raw endef -$(eval $(call BuildPackage,luci-app-udp2raw)) +$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/lean/luci-app-udp2raw/files/luci/i18n/udp2raw.zh-cn.lmo b/package/lean/luci-app-udp2raw/files/luci/i18n/udp2raw.zh-cn.lmo index e25325de0..a73a6cf62 100644 Binary files a/package/lean/luci-app-udp2raw/files/luci/i18n/udp2raw.zh-cn.lmo and b/package/lean/luci-app-udp2raw/files/luci/i18n/udp2raw.zh-cn.lmo differ diff --git a/package/lean/luci-app-udp2raw/files/luci/i18n/udp2raw.zh-cn.po b/package/lean/luci-app-udp2raw/files/luci/i18n/udp2raw.zh-cn.po index fb20472f1..92c892bba 100644 --- a/package/lean/luci-app-udp2raw/files/luci/i18n/udp2raw.zh-cn.po +++ b/package/lean/luci-app-udp2raw/files/luci/i18n/udp2raw.zh-cn.po @@ -77,7 +77,7 @@ msgid "Cipher Mode" msgstr "加密方å¼" msgid "Auth Mode" -msgstr "认è¯æ–¹å¼" +msgstr "验è¯æ–¹å¼" msgid "Auto Rule" msgstr "自动规则" @@ -89,7 +89,7 @@ msgid "Keep Rule" msgstr "ä¿æŒè§„则" msgid "Monitor iptables and auto re-add if necessary." -msgstr "监视 iptables 并在必è¦æ—¶é‡æ–°æ·»åŠ è§„则。" +msgstr "定期检查 iptables 并在必è¦æ—¶é‡æ–°æ·»åŠ è§„则。" msgid "seq Mode" msgstr "seq 模å¼" diff --git a/package/lean/luci-app-udp2raw/files/luci/model/cbi/udp2raw/general.lua b/package/lean/luci-app-udp2raw/files/luci/model/cbi/udp2raw/general.lua index a4d343091..520f759d7 100644 --- a/package/lean/luci-app-udp2raw/files/luci/model/cbi/udp2raw/general.lua +++ b/package/lean/luci-app-udp2raw/files/luci/model/cbi/udp2raw/general.lua @@ -8,7 +8,7 @@ end if not has_bin("udp2raw") then return Map("udp2raw", "%s - %s" %{translate("udp2raw-tunnel"), - translate("Settings")}, 'udp2raw-tunnel binary file not found.') + translate("Settings")}, 'udp2raw-tunnel binary file not found. install udp2raw-tunnel package, or copy binary to /usr/bin/udp2raw manually. ') end uci:foreach("udp2raw", "servers", function(s) @@ -18,13 +18,14 @@ uci:foreach("udp2raw", "servers", function(s) end) m = Map("udp2raw", "%s - %s" %{translate("udp2raw-tunnel"), translate("Settings")}) -m:append(Template("udp2raw_status")) +m:append(Template("udp2raw/status")) s = m:section(NamedSection, "general", "general", translate("General Settings")) s.anonymous = true s.addremove = false -o = s:option(ListValue, "server", translate("Server")) +o = s:option(DynamicList, "server", translate("Server")) +o.template = "udp2raw/dynamiclist" o:value("nil", translate("Disable")) for _, s in ipairs(servers) do o:value(s.name, s.alias) end o.default = "nil" diff --git a/package/lean/luci-app-udp2raw/files/luci/model/cbi/udp2raw/servers-details.lua b/package/lean/luci-app-udp2raw/files/luci/model/cbi/udp2raw/servers-details.lua index ba961d189..de23b081f 100644 --- a/package/lean/luci-app-udp2raw/files/luci/model/cbi/udp2raw/servers-details.lua +++ b/package/lean/luci-app-udp2raw/files/luci/model/cbi/udp2raw/servers-details.lua @@ -68,13 +68,9 @@ for _, v in ipairs(auth_modes) do o:value(v, v:lower()) end o.default = "md5" o = s:option(Flag, "auto_rule", translate("Auto Rule"), translate("Auto add (and delete) iptables rule.")) -o.enabled = "1" -o.disabled = "0" o.default = "1" o = s:option(Flag, "keep_rule", translate("Keep Rule"), translate("Monitor iptables and auto re-add if necessary.")) -o.enabled = "1" -o.disabled = "0" o:depends("auto_rule", "1") o = s:option(Value, "seq_mode", translate("seq Mode"), translate("seq increase mode for faketcp.")) diff --git a/package/lean/luci-app-udp2raw/files/luci/view/udp2raw/dynamiclist.htm b/package/lean/luci-app-udp2raw/files/luci/view/udp2raw/dynamiclist.htm new file mode 100644 index 000000000..7ee3dc975 --- /dev/null +++ b/package/lean/luci-app-udp2raw/files/luci/view/udp2raw/dynamiclist.htm @@ -0,0 +1,98 @@ +<%# + Copyright (C) 2017 Jian Chang + Licensed to the public under the GNU General Public License v3. +-%> + +<%+cbi/valueheader%> + +<%- + local values = self:formvalue(section) + if not values then + values = self:cfgvalue(section) or {self.default} + end + + local function serialize_json(x, cb) + local rv, push = nil, cb + if not push then + rv = { } + push = function(tok) rv[#rv+1] = tok end + end + + if x == nil then + push("null") + elseif type(x) == "table" then + push("[") + for k = 1, #x do + if k > 1 then + push(",") + end + serialize_json(x[k], push) + end + push("]") + else + push('"%s"' % tostring(x):gsub('["%z\1-\31\\]', + function(c) return '\\u%04x' % c:byte(1) end)) + end + + if not cb then + return table.concat(rv, "") + end + end +-%> + +> + + +<%+cbi/valuefooter%> diff --git a/package/lean/luci-app-udp2raw/files/luci/view/udp2raw_status.htm b/package/lean/luci-app-udp2raw/files/luci/view/udp2raw/status.htm similarity index 100% rename from package/lean/luci-app-udp2raw/files/luci/view/udp2raw_status.htm rename to package/lean/luci-app-udp2raw/files/luci/view/udp2raw/status.htm diff --git a/package/lean/luci-app-udp2raw/files/root/etc/config/udp2raw b/package/lean/luci-app-udp2raw/files/root/etc/config/udp2raw index 8a27625ca..eaa58ee7b 100644 --- a/package/lean/luci-app-udp2raw/files/root/etc/config/udp2raw +++ b/package/lean/luci-app-udp2raw/files/root/etc/config/udp2raw @@ -1,6 +1,6 @@ config general 'general' - option server 'nil' + list server 'nil' option daemon_user 'root' config servers 'default' diff --git a/package/lean/luci-app-udp2raw/files/root/etc/init.d/udp2raw b/package/lean/luci-app-udp2raw/files/root/etc/init.d/udp2raw old mode 100755 new mode 100644 index 3733b66d6..96de10e04 --- a/package/lean/luci-app-udp2raw/files/root/etc/init.d/udp2raw +++ b/package/lean/luci-app-udp2raw/files/root/etc/init.d/udp2raw @@ -1,51 +1,86 @@ #!/bin/sh /etc/rc.common START=88 +STOP=15 USE_PROCD=1 -UDP2RAW=udp2raw +NAME=udp2raw _log() { - local level="$1" - local msg="$2" - - logger -p "daemon.${level}" -t "$UDP2RAW" "$msg" + logger -p "daemon.$1" -t "$NAME" "$2" } -gen_client_config_file() { +has_valid_server() { + local server + for server in $@; do + [ "$(uci_get $NAME $server)" = "servers" ] && return 0 + done + return 1 +} + +add_ipt_rule() { + if [ -z "$ipt_cmd" ]; then + command -v iptables >/dev/null 2>&1 || return 1 + ipt_cmd='iptables' + [ -n "$(iptables -h 2> /dev/null | grep -e '--wait')" ] && ipt_cmd="$ipt_cmd --wait" + echo "# firewall include file" > "/var/etc/$NAME.include" + else + echo "$ipt_cmd" | grep -q -e '--wait' + [ $? -ne 0 ] && sleep 2 + fi + + $ipt_cmd -I INPUT -s "$server_addr"/32 -p tcp -m tcp --sport "$server_port" -m comment --comment "${NAME}DwrW" -j DROP +} + +flush_ipt_rules() { + iptables-save -c | grep -v "${NAME}DwrW" | iptables-restore -c + [ -f "/var/etc/$NAME.include" ] && rm -f "/var/etc/$NAME.include" +} + +export_ipt_rules() { + [ -f "/var/etc/$NAME.include" ] || return + cat <<-CAT >> "/var/etc/$NAME.include" + iptables-save -c | grep -v "${NAME}DwrW" | iptables-restore -c + iptables-restore -n <<-EOF + $(iptables-save -t filter | grep -E "${NAME}DwrW|^\*|^COMMIT" | sed 's/^-A /-I /') + EOF +CAT +} + +create_config() { local config_file="$1" echo "# auto-generated config file from /etc/config/udp2raw" > $config_file echo "-c" >> $config_file echo "-l ${listen_addr}:${listen_port}" >> $config_file && _log "info" "listening on: ${listen_addr}:${listen_port}" - echo "-r ${server_addr}:${server_port}" >> $config_file && _log "info" "remote address: ${server_addr}:${server_port}" + echo "-r ${server_addr}:${server_port}" >> $config_file [ -n "$raw_mode" ] && echo "--raw-mode ${raw_mode}" >> $config_file && _log "info" "raw-mode: ${raw_mode}" [ -n "$key" ] && echo "--key ${key}" >> $config_file - [ -n "$cipher_mode" ] && echo "--cipher-mode ${cipher_mode}" >> $config_file && _log "info" "cipher-mode: ${cipher_mode}" - [ -n "$auth_mode" ] && echo "--auth-mode ${auth_mode}" >> $config_file && _log "info" "auth-mode: ${auth_mode}" + [ -n "$cipher_mode" ] && echo "--cipher-mode ${cipher_mode}" >> $config_file + [ -n "$auth_mode" ] && echo "--auth-mode ${auth_mode}" >> $config_file - [ "$auto_rule" -ne 0 ] && echo "--auto-rule" >> $config_file && _log "info" "auto-rule: true" - [ "$auto_rule" -ne 0 -a "$keep_rule" -ne 0 ] && echo "--keep-rule" >> $config_file && _log "info" "keep-rule: true" + [ $auto_rule -eq 1 -a $keep_rule -eq 1 ] && echo "--auto-rule" >> $config_file + [ $auto_rule -eq 1 -a $keep_rule -eq 1 ] && echo "--keep-rule" >> $config_file - [ -n "$seq_mode" ] && echo "--seq-mode ${seq_mode}" >> $config_file && _log "info" "seq-mode: ${seq_mode}" - [ -n "$lower_level" ] && echo "--lower-level ${lower_level}" >> $config_file && _log "info" "lower-level: ${lower_level}" + [ -n "$seq_mode" ] && echo "--seq-mode ${seq_mode}" >> $config_file + [ -n "$lower_level" ] && echo "--lower-level ${lower_level}" >> $config_file [ -n "$source_ip" ] && echo "--source-ip ${source_ip}" >> $config_file [ -n "$source_port" ] && echo "--source-port ${source_port}" >> $config_file + echo "--retry-on-error" >> $config_file [ -n "$log_level" ] && echo "--log-level ${log_level}" >> $config_file echo "--disable-color" >> $config_file - _log "info" "running from ${daemon_user} user" } validate_config_section() { - uci_validate_section "$UDP2RAW" general "$1" \ + uci_validate_section "$NAME" general "$1" \ 'server:uciname' \ 'daemon_user:string:root' } validate_server_section() { - uci_validate_section "$UDP2RAW" servers "$1" \ + uci_validate_section "$NAME" servers "$1" \ 'server_addr:host' \ 'server_port:port:8080' \ 'listen_addr:ipaddr:127.0.0.1' \ @@ -63,38 +98,30 @@ validate_server_section() { 'log_level:range(0,6)' } -start_udp2raw_instance() { - local section="$1" +start_instance() { + local server="$1" - if ! validate_config_section "$section" ; then - _log "err" "Config validate failed." - return 1 - fi - - if [ -z "$server" ] || [ "$server" = "nil" ]; then + if [ -z "$server" -o "$server" == "nil" ]; then return 0 elif ! validate_server_section "$server"; then _log "err" "Server config validation failed." return 1 - elif [ -z "$server_addr" ]; then + fi + + /sbin/validate_data "ipaddr" "$server_addr" >/dev/null 2>&1 + [ $? -ne 0 ] && server_addr=$(nslookup "$server_addr" | \ + sed -n 's/^Address[[:space:]]*[0-9]*:[[:space:]]*\(\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\)$/\1/p') + if [ -z "$server_addr" ]; then _log "err" "Server address validation failed." return 1 fi - is_ipv6_address() { - echo "$1" | grep -q ":" - } - - is_ipv6_address "$server_addr" && server_addr="[${server_addr}]" - is_ipv6_address "$listen_addr" && listen_addr="[${listen_addr}]" - - _log "notice" "udp2raw-tunnel start." [ -d /var/etc ] || mkdir -p /var/etc - local config_file=/var/etc/${UDP2RAW}.${server}.conf + local config_file="/var/etc/${NAME}.${server}.conf" + create_config "$config_file" || return 1 - if ! ( gen_client_config_file "$config_file" ); then - _log "err" "Can't create config file". - return 1 + if [ $auto_rule -eq 1 -a $keep_rule -ne 1 ]; then + add_ipt_rule || { _log "err" "added iptables rule failed."; return 1; } fi procd_open_instance @@ -102,20 +129,28 @@ start_udp2raw_instance() { procd_append_param command --conf-file "$config_file" procd_set_param respawn procd_set_param file "$config_file" - procd_set_param user "$daemon_user" - procd_set_param pidfile /var/run/${UDP2RAW}.${server}.pid + [ -n "$daemon_user" ] && procd_set_param user "$daemon_user" && _log "info" "running from ${daemon_user} user" + procd_set_param pidfile "/var/run/${NAME}.${server}.pid" procd_close_instance } service_triggers() { - procd_add_reload_trigger "$UDP2RAW" + procd_add_reload_trigger "$NAME" } start_service() { - config_load "$UDP2RAW" - config_foreach start_udp2raw_instance "general" + if ! validate_config_section "general" ; then + _log "err" "Config validate failed." + return 1 + fi + has_valid_server $server || return 1 + flush_ipt_rules + for srv in $server; do + start_instance $srv + done + export_ipt_rules } stop_service() { - _log "notice" "udp2raw-tunnel stop." + flush_ipt_rules } diff --git a/package/lean/luci-app-udp2raw/files/root/etc/init.d/udp2raw.init b/package/lean/luci-app-udp2raw/files/root/etc/init.d/udp2raw.init new file mode 100644 index 000000000..b955b62f1 --- /dev/null +++ b/package/lean/luci-app-udp2raw/files/root/etc/init.d/udp2raw.init @@ -0,0 +1,167 @@ +#!/bin/sh /etc/rc.common + +START=88 +STOP=15 + +NAME=udp2raw + +_log() { + logger -p "daemon.$1" -t "$NAME" "$2" +} + +has_valid_server() { + local server + for server in $@; do + [ "$(uci_get $NAME $server)" = "servers" ] && return 0 + done + return 1 +} + +add_ipt_rule() { + if [ -z "$ipt_cmd" ]; then + command -v iptables >/dev/null 2>&1 || return 1 + ipt_cmd='iptables' + [ -n "$(iptables -h 2> /dev/null | grep -e '--wait')" ] && ipt_cmd="$ipt_cmd --wait" + echo "# firewall include file" > "/var/etc/$NAME.include" + else + echo "$ipt_cmd" | grep -q -e '--wait' + [ $? -ne 0 ] && sleep 2 + fi + + $ipt_cmd -I INPUT -s "$server_addr"/32 -p tcp -m tcp --sport "$server_port" -m comment --comment "${NAME}DwrW" -j DROP +} + +flush_ipt_rules() { + iptables-save -c | grep -v "${NAME}DwrW" | iptables-restore -c + [ -f "/var/etc/$NAME.include" ] && rm -f "/var/etc/$NAME.include" +} + +export_ipt_rules() { + [ -f "/var/etc/$NAME.include" ] || return + cat <<-CAT >> "/var/etc/$NAME.include" + iptables-save -c | grep -v "${NAME}DwrW" | iptables-restore -c + iptables-restore -n <<-EOF + $(iptables-save -t filter | grep -E "${NAME}DwrW|^\*|^COMMIT" | sed 's/^-A /-I /') + EOF +CAT +} + +create_config() { + local config_file="$1" + echo "# auto-generated config file from /etc/config/udp2raw" > $config_file + + echo "-c" >> $config_file + echo "-l ${listen_addr}:${listen_port}" >> $config_file + echo "-r ${server_addr}:${server_port}" >> $config_file + + [ -n "$raw_mode" ] && echo "--raw-mode ${raw_mode}" >> $config_file + [ -n "$key" ] && echo "--key ${key}" >> $config_file + [ -n "$cipher_mode" ] && echo "--cipher-mode ${cipher_mode}" >> $config_file + [ -n "$auth_mode" ] && echo "--auth-mode ${auth_mode}" >> $config_file + + [ $auto_rule -eq 1 -a $keep_rule -eq 1 ] && echo "--auto-rule" >> $config_file + [ $auto_rule -eq 1 -a $keep_rule -eq 1 ] && echo "--keep-rule" >> $config_file + + [ -n "$seq_mode" ] && echo "--seq-mode ${seq_mode}" >> $config_file + [ -n "$lower_level" ] && echo "--lower-level ${lower_level}" >> $config_file + [ -n "$source_ip" ] && echo "--source-ip ${source_ip}" >> $config_file + [ -n "$source_port" ] && echo "--source-port ${source_port}" >> $config_file + echo "--retry-on-error" >> $config_file + + [ -n "$log_level" ] && echo "--log-level ${log_level}" >> $config_file + echo "--disable-color" >> $config_file +} + +validate_config_section() { + local ret=$(/sbin/validate_data "$NAME" general "$1" \ + 'server:uciname' \ + 'daemon_user:string:root' \ + 2> /dev/null) + [ $? -ne 0 ] && return 1 + eval "$ret" +} + +validate_server_section() { + local ret=$(/sbin/validate_data "$NAME" servers "$1" \ + 'server_addr:host' \ + 'server_port:port:8080' \ + 'listen_addr:ipaddr:127.0.0.1' \ + 'listen_port:port:2080' \ + 'raw_mode:or("faketcp", "udp", "icmp"):faketcp' \ + 'key:string' \ + 'cipher_mode:or("aes128cbc", "xor", "none"):aes128cbc' \ + 'auth_mode:or("md5", "crc32", "simple", "none"):md5' \ + 'auto_rule:bool:1' \ + 'keep_rule:bool:0' \ + 'seq_mode:range(0,4)' \ + 'lower_level:string' \ + 'source_ip:ipaddr' \ + 'source_port:port' \ + 'log_level:range(0,6)' \ + 2> /dev/null) + [ $? -ne 0 ] && return 1 + eval "$ret" +} + +start_instance() { + local server="$1" + + if [ -z "$server" -o "$server" == "nil" ]; then + return 0 + elif ! validate_server_section "$server"; then + _log "err" "Server config validation failed." + return 1 + fi + + /sbin/validate_data "ipaddr" "$server_addr" >/dev/null 2>&1 + [ $? -ne 0 ] && server_addr=$(nslookup "$server_addr" | \ + sed -n 's/^Address[[:space:]]*[0-9]*:[[:space:]]*\(\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\)$/\1/p') + if [ -z "$server_addr" ]; then + _log "err" "Server address validation failed." + return 1 + fi + + [ -d /var/etc ] || mkdir -p /var/etc + local config_file="/var/etc/${NAME}.${server}.conf" + create_config "$config_file" || return 1 + [ -d "/var/log/${NAME}" ] || mkdir -p "/var/log/${NAME}" + + if [ $auto_rule -eq 1 -a $keep_rule -ne 1 ]; then + add_ipt_rule || { _log "err" "added iptables rule failed."; return 1; } + fi + + /usr/bin/udp2raw --conf-file "$config_file" >> "/var/log/${NAME}/${NAME}.${server}.log" & + echo $! > "/var/run/${NAME}.${server}.pid" + return 0 +} + +start() { + pgrep "/usr/bin/${NAME}" >/dev/null 2>&1 && return + + if ! validate_config_section "general" ; then + _log "err" "Config validate failed." + return 1 + fi + has_valid_server $server || return 1 + flush_ipt_rules + for srv in $server; do + start_instance $srv + done + export_ipt_rules +} + +stop() { + local pids=$(pgrep "/usr/bin/${NAME}" 2> /dev/null) + [ $? -ne 0 ] && return + for pid in $pids; do + kill $pid >/dev/null 2>&1 + done + flush_ipt_rules + return 0 +} + +restart() { + stop + sleep 1 + start +} diff --git a/package/lean/luci-app-udp2raw/files/root/etc/uci-defaults/luci-udp2raw b/package/lean/luci-app-udp2raw/files/root/etc/uci-defaults/luci-udp2raw old mode 100755 new mode 100644 index c04688e41..c7c4dd146 --- a/package/lean/luci-app-udp2raw/files/root/etc/uci-defaults/luci-udp2raw +++ b/package/lean/luci-app-udp2raw/files/root/etc/uci-defaults/luci-udp2raw @@ -1,22 +1,26 @@ #!/bin/sh -uci -q batch <<-EOF >/dev/null +uci -q batch <<-EOF > /dev/null delete ucitrack.@udp2raw[-1] add ucitrack udp2raw set ucitrack.@udp2raw[-1].init=udp2raw commit ucitrack + delete firewall.udp2raw + set firewall.udp2raw=include + set firewall.udp2raw.type=script + set firewall.udp2raw.path=/var/etc/udp2raw.include + set firewall.udp2raw.reload=1 + commit firewall EOF general=$(uci -q get udp2raw.@general[-1]) - if [ -z "$general" ]; then uci -q add udp2raw general fi - -if [ ."$general" != ."general" ]; then - uci -q batch <<-EOF >/dev/null +if [ "$general"x != "general"x ]; then + uci -q batch <<-EOF > /dev/null rename udp2raw.@general[-1]="general" - set udp2raw.general.server="nil" + set udp2raw.@general[-1].server="nil" commit udp2raw EOF fi diff --git a/package/lean/luci-app-v2ray/Makefile b/package/lean/luci-app-v2ray/Makefile new file mode 100644 index 000000000..8fd8bd0a2 --- /dev/null +++ b/package/lean/luci-app-v2ray/Makefile @@ -0,0 +1,16 @@ +# Copyright (C) 2016 Openwrt.org +# +# This is free software, licensed under the Apache License, Version 2.0 . +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=LuCI support for V2Ray +LUCI_DEPENDS:=+iptables-mod-tproxy +kmod-ipt-tproxy +ip +ipset-lists +pdnsd-alt +coreutils +coreutils-base64 +coreutils-nohup +dnsmasq-full +ca-certificates +v2ray +LUCI_PKGARCH:=all +PKG_VERSION:=1.0 +PKG_RELEASE:=2 + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/package/lean/luci-app-v2ray/luasrc/controller/v2ray.lua b/package/lean/luci-app-v2ray/luasrc/controller/v2ray.lua new file mode 100644 index 000000000..eb891b700 --- /dev/null +++ b/package/lean/luci-app-v2ray/luasrc/controller/v2ray.lua @@ -0,0 +1,9 @@ +module("luci.controller.v2ray", package.seeall) +function index() + if not nixio.fs.access("/etc/config/v2ray") then + return + end + local page + page = entry({"admin", "services", "v2ray"}, cbi("v2ray"), _("V2Ray Pro")) + page.dependent = true +end \ No newline at end of file diff --git a/package/lean/luci-app-v2ray/luasrc/model/cbi/v2ray.lua b/package/lean/luci-app-v2ray/luasrc/model/cbi/v2ray.lua new file mode 100644 index 000000000..4471d3115 --- /dev/null +++ b/package/lean/luci-app-v2ray/luasrc/model/cbi/v2ray.lua @@ -0,0 +1,330 @@ +local fs = require "nixio.fs" +local NXFS = require "nixio.fs" +local WLFS = require "nixio.fs" +local SYS = require "luci.sys" +local ND = SYS.exec("cat /etc/gfwlist/china-banned | wc -l") +local conf = "/etc/v2ray/base-gfwlist.txt" +local watch = "/tmp/v2ray_watchdog.log" +local dog = "/tmp/v2raypro.log" +local http = luci.http +local ucursor = require "luci.model.uci".cursor() + +local Status + +if SYS.call("pidof v2ray > /dev/null") == 0 then + Status = translate("V2Ray is Running") +else + Status = translate("V2Ray is Not Running") +end + +m = Map("v2ray") +m.title = translate("V2Ray Transparent Proxy") +m.description = translate("A fast secure tunnel proxy that help you get through firewalls on your router") + +s = m:section(TypedSection, "v2ray") +s.anonymous = true +s.description = translate(string.format("%s

    ", Status)) + +-- --------------------------------------------------- + +s:tab("basic", translate("Base Setting")) + + +switch = s:taboption("basic",Flag, "enabled", translate("Enable")) +switch.rmempty = false + +proxy_mode = s:taboption("basic",ListValue, "proxy_mode", translate("Proxy Mode")) +proxy_mode:value("M", translate("Base on GFW-List Auto Proxy Mode(Recommend)")) +proxy_mode:value("S", translate("Bypassing China Manland IP Mode(Be caution when using P2P downloadï¼)")) +proxy_mode:value("G", translate("Global Mode")) +proxy_mode:value("V", translate("Overseas users watch China video website Mode")) + +cronup = s:taboption("basic", Flag, "cron_mode", translate("Auto Update GFW-List"), + translate(string.format("GFW-List Lines: %s Lines", ND))) +cronup.default = 0 +cronup.rmempty = false + +updatead = s:taboption("basic", Button, "updatead", translate("Manually force update GFW-List"), translate("Note: It needs to download and convert the rules. The background process may takes 60-120 seconds to run.
    After completed it would automatically refresh, please do not duplicate click!")) +updatead.inputtitle = translate("Manually force update GFW-List") +updatead.inputstyle = "apply" +updatead.write = function() + SYS.call("nohup sh /etc/v2ray/up-gfwlist.sh > /tmp/gfwupdate.log 2>&1 &") +end + +safe_dns_tcp = s:taboption("basic",Flag, "safe_dns_tcp", translate("DNS uses TCP"), + translate("Through the server transfer mode inquires DNS pollution prevention (Safer and recommended)")) +safe_dns_tcp.rmempty = false +-- safe_dns_tcp:depends("more", "1") + +-- more_opt = s:taboption("basic",Flag, "more", translate("More Options"), +-- translate("Options for advanced users")) + +-- timeout = s:taboption("basic",Value, "timeout", translate("Timeout")) +-- timeout.datatype = "range(0,10000)" +-- timeout.placeholder = "60" +-- timeout.optional = false +-- timeout:depends("more", "1") + +-- safe_dns = s:taboption("basic",Value, "safe_dns", translate("Safe DNS"), +-- translate("8.8.8.8 or 8.8.4.4 is recommended")) +-- safe_dns.datatype = "ip4addr" +-- safe_dns.optional = false +-- safe_dns:depends("more", "1") + +-- safe_dns_port = s:taboption("basic",Value, "safe_dns_port", translate("Safe DNS Port"), +-- translate("Foreign DNS on UDP port 53 might be polluted")) +-- safe_dns_port.datatype = "range(1,65535)" +-- safe_dns_port.placeholder = "53" +-- safe_dns_port.optional = false +-- safe_dns_port:depends("more", "1") + +--fast_open =s:taboption("basic",Flag, "fast_open", translate("TCP Fast Open"), +-- translate("Enable TCP fast open, only available on kernel > 3.7.0")) + + + +s:tab("main", translate("Server Setting")) + +use_conf_file = s:taboption("main",Flag, "use_conf_file", translate("Use Config File")) +use_conf_file.rmempty = false + +if nixio.fs.access("/usr/bin/v2ray/v2ctl") then + conf_file_type = s:taboption("main",ListValue, "conf_file_type", translate("Config File Type")) + conf_file_type:value("pb","Protobuf") +else + conf_file_type = s:taboption("main",ListValue, "conf_file_type", translate("Config File Type"), translate("Warning: Can't find v2ctl. You can only choose Protobuf.")) +end +conf_file_type:value("json","JSON") +conf_file_type:depends("use_conf_file", 1) + +conf_file_path = s:taboption("main",Value, "conf_file_path", translate("Config File Path"), + translate("If you choose to upload a new file, please do not modify and this configuration will be overwritten automatically.")) +conf_file_path:depends("use_conf_file", 1) + +upload_conf = s:taboption("main",FileUpload, "") +upload_conf.template = "cbi/other_upload2" +upload_conf:depends("use_conf_file", 1) + +um = s:taboption("main",DummyValue, "", nil) +um.template = "cbi/other_dvalue" +um:depends("use_conf_file", 1) + + + +local conf_dir, fd +conf_dir = "/etc/v2ray/" +nixio.fs.mkdir(conf_dir) +http.setfilehandler( + function(meta, chunk, eof) + if not fd then + if not meta then return end + + if meta and chunk then fd = nixio.open(conf_dir .. meta.file, "w") end + + if not fd then + um.value = translate("Create upload file error.") + return + end + end + if chunk and fd then + fd:write(chunk) + end + if eof and fd then + fd:close() + fd = nil + um.value = translate("File saved to") .. ' "/etc/v2ray/' .. meta.file .. '"' + ucursor:set("v2ray","v2ray","conf_file_path","/etc/v2ray/" .. meta.file) + ucursor:commit("v2ray") + end + end +) + +if luci.http.formvalue("upload") then + local f = luci.http.formvalue("ulfile") + if #f <= 0 then + um.value = translate("No specify upload file.") + end +end + + + + +server = s:taboption("main",Value, "address", translate("Server Address")) +server.datatype = "host" +server:depends("use_conf_file", 0) + +server_port = s:taboption("main",Value, "port", translate("Server Port")) +server_port.datatype = "range(0,65535)" +server_port:depends("use_conf_file", 0) + +id = s:taboption("main",Value, "id", translate("ID")) +id.password = true +id:depends("use_conf_file", 0) + +alterId = s:taboption("main",Value, "alterId", translate("Alter ID")) +alterId.datatype = "range(1,65535)" +alterId:depends("use_conf_file", 0) + +security = s:taboption("main",ListValue, "security", translate("Security")) +security:value("none") +security:value("auto") +security:value("aes-128-cfb") +security:value("aes-128-gcm") +security:value("chacha20-poly1305") +security:depends("use_conf_file", 0) + +network_type = s:taboption("main",ListValue, "network_type", translate("Network Type")) +network_type:value("tcp") +network_type:value("kcp") +network_type:value("ws") +network_type:depends("use_conf_file", 0) + +-- tcp settings +tcp_obfs = s:taboption("main",ListValue, "tcp_obfs", translate("TCP Obfs")) +tcp_obfs:value("none") +tcp_obfs:value("http") +tcp_obfs:depends("network_type", "tcp") + +tcp_path = s:taboption("main",DynamicList, "tcp_path", translate("TCP Obfs Path")) +tcp_path:depends("tcp_obfs", "http") + +tcp_host = s:taboption("main",DynamicList, "tcp_host", translate("TCP Obfs Header")) +tcp_host:depends("tcp_obfs", "http") +tcp_host.datatype = "host" + +-- kcp settings +kcp_obfs = s:taboption("main",ListValue, "kcp_obfs", translate("KCP Obfs")) +kcp_obfs:value("none") +kcp_obfs:value("srtp") +kcp_obfs:value("utp") +kcp_obfs:value("wechat-video") +kcp_obfs:depends("network_type", "kcp") + +kcp_mtu = s:taboption("main",Value, "kcp_mtu", translate("KCP MTU")) +kcp_mtu.datatype = "range(576,1460)" +kcp_mtu:depends("network_type", "kcp") + +kcp_tti = s:taboption("main",Value, "kcp_tti", translate("KCP TTI")) +kcp_tti.datatype = "range(10,100)" +kcp_tti:depends("network_type", "kcp") + +kcp_uplink = s:taboption("main",Value, "kcp_uplink", translate("KCP uplinkCapacity")) +kcp_uplink.datatype = "range(0,1000)" +kcp_uplink:depends("network_type", "kcp") + +kcp_downlink = s:taboption("main",Value, "kcp_downlink", translate("KCP downlinkCapacity")) +kcp_downlink.datatype = "range(0,1000)" +kcp_downlink:depends("network_type", "kcp") + +kcp_readbuf = s:taboption("main",Value, "kcp_readbuf", translate("KCP readBufferSize")) +kcp_readbuf.datatype = "range(0,100)" +kcp_readbuf:depends("network_type", "kcp") + +kcp_writebuf = s:taboption("main",Value, "kcp_writebuf", translate("KCP writeBufferSize")) +kcp_writebuf.datatype = "range(0,100)" +kcp_writebuf:depends("network_type", "kcp") + +kcp_congestion = s:taboption("main",Flag, "kcp_congestion", translate("KCP Congestion")) +kcp_congestion:depends("network_type", "kcp") + +-- websocket settings +ws_path = s:taboption("main",Value, "ws_path", translate("WebSocket Path")) +ws_path:depends("network_type", "ws") + +ws_headers = s:taboption("main",Value, "ws_headers", translate("WebSocket Header")) +ws_headers:depends("network_type", "ws") +ws_headers.datatype = "host" + +-- others +tls = s:taboption("main",Flag, "tls", translate("TLS")) +tls.rmempty = false +tls:depends("use_conf_file", 0) + +mux = s:taboption("main",Flag, "mux", translate("Mux")) +mux.rmempty = false +mux:depends("use_conf_file", 0) + + + +s:tab("list", translate("User-defined GFW-List")) +gfwlist = s:taboption("list", TextValue, "conf") +gfwlist.description = translate("
    (!)Note: When the domain name is entered and will automatically merge with the online GFW-List. Please manually update the GFW-List list after applying.") +gfwlist.rows = 13 +gfwlist.wrap = "off" +gfwlist.cfgvalue = function(self, section) + return NXFS.readfile(conf) or "" +end +gfwlist.write = function(self, section, value) + NXFS.writefile(conf, value:gsub("\r\n", "\n")) +end + +local addipconf = "/etc/v2ray/addinip.txt" + +s:tab("addip", translate("GFW-List Add-in IP")) +gfwaddin = s:taboption("addip", TextValue, "addipconf") +gfwaddin.description = translate("
    (!)Note: IP add-in to GFW-List. Such as Telegram Messenger") +gfwaddin.rows = 13 +gfwaddin.wrap = "off" +gfwaddin.cfgvalue = function(self, section) + return NXFS.readfile(addipconf) or "" +end +gfwaddin.write = function(self, section, value) + NXFS.writefile(addipconf, value:gsub("\r\n", "\n")) +end + +s:tab("status", translate("Status and Tools")) +s:taboption("status", DummyValue,"opennewwindow" , + translate("")) + + +s:tab("watchdog", translate("Watchdog Log")) +log = s:taboption("watchdog", TextValue, "sylogtext") +log.template = "cbi/tvalue" +log.rows = 13 +log.wrap = "off" +log.readonly="readonly" + +function log.cfgvalue(self, section) + SYS.exec("[ -f /tmp/v2ray_watchdog.log ] && sed '1!G;h;$!d' /tmp/v2ray_watchdog.log > /tmp/v2raypro.log") + return nixio.fs.readfile(dog) +end + +function log.write(self, section, value) + value = value:gsub("\r\n?", "\n") + nixio.fs.writefile(dog, value) +end + + + +t=m:section(TypedSection,"acl_rule",translate("Client Proxy Mode Settings"), +translate("Proxy mode settings can be set to specific LAN clients ( No Proxy, Global Proxy, Game Mode) . Does not need to be set by default.")) +t.template="cbi/tblsection" +t.sortable=true +t.anonymous=true +t.addremove=true +e=t:option(Value,"ipaddr",translate("IP Address")) +e.width="40%" +e.datatype="ip4addr" +e.placeholder="0.0.0.0/0" +luci.ip.neighbors({ family = 4 }, function(entry) + if entry.reachable then + e:value(entry.dest:string()) + end +end) + +e=t:option(ListValue,"filter_mode",translate("Proxy Mode")) +e.width="40%" +e.default="disable" +e.rmempty=false +e:value("disable",translate("No Proxy")) +e:value("global",translate("Global Proxy")) +e:value("game",translate("Game Mode")) + +-- --------------------------------------------------- +local apply = luci.http.formvalue("cbi.apply") +if apply then + os.execute("chmod +x /etc/init.d/v2raypro &") + os.execute("/etc/init.d/v2raypro restart >/dev/null 2>&1 &") +end + +return m diff --git a/package/lean/luci-app-v2ray/luasrc/view/cbi/other_upload2.htm b/package/lean/luci-app-v2ray/luasrc/view/cbi/other_upload2.htm new file mode 100644 index 000000000..322616d71 --- /dev/null +++ b/package/lean/luci-app-v2ray/luasrc/view/cbi/other_upload2.htm @@ -0,0 +1,6 @@ +<%+cbi/valueheader%> + + + + +<%+cbi/valuefooter%> diff --git a/package/lean/luci-app-v2ray/po/zh-cn/v2raypro.po b/package/lean/luci-app-v2ray/po/zh-cn/v2raypro.po new file mode 100644 index 000000000..ee3ffb44f --- /dev/null +++ b/package/lean/luci-app-v2ray/po/zh-cn/v2raypro.po @@ -0,0 +1,116 @@ +msgid "V2Ray is Running" +msgstr "V2Ray 正在è¿è¡Œ" + +msgid "V2Ray is Not Running" +msgstr "V2Ray 没有è¿è¡Œ" + +msgid "V2Ray Transparent Proxy" +msgstr "V2Ray é€æ˜Žä»£ç†" + +msgid "A fast secure tunnel proxy that help you get through firewalls on your router" +msgstr "一个快速安全隧é“代ç†ï¼Œå¸®åŠ©æ‚¨ç©¿è¿‡é˜²ç«å¢™" + +msgid "Base Setting" +msgstr "基本设置" + +msgid "Proxy Mode" +msgstr "代ç†æ¨¡å¼" + +msgid "Base on GFW-List Auto Proxy Mode(Recommend)" +msgstr "基于GFW-List自动代ç†(推è)" + +msgid "Bypassing China Manland IP Mode(Be caution when using P2P downloadï¼)" +msgstr "绕过中国大陆IP地å€(P2P 下载慎用ï¼)" + +msgid "Global Mode" +msgstr "全局代ç†" + +msgid "Overseas users watch China video website Mode" +msgstr "海外用户回国看视频" + +msgid "Auto Update GFW-List" +msgstr "自动更新GFW-List" + +msgid "Manually force update GFW-List" +msgstr "手动强制更新GFW-List" + +msgid "DNS uses TCP" +msgstr "å¯ç”¨DNS TCP防污染" + +msgid "Through the server transfer mode inquires DNS pollution prevention (Safer and recommended)" +msgstr "往国外的DNS请求将通过æœåŠ¡å™¨ä¸­è½¬å‘出(更安全,推è)" + +msgid "Server Setting" +msgstr "æœåŠ¡å™¨è®¾ç½®" + +msgid "Server Address" +msgstr "æœåŠ¡å™¨åœ°å€ï¼ˆæ”¯æŒåŸŸå)" + +msgid "Server Port" +msgstr "æœåŠ¡å™¨ç«¯å£" + +msgid "ID" +msgstr "ID" + +msgid "Alter ID" +msgstr "é¢å¤–ID" + +msgid "Security" +msgstr "加密方å¼" + +msgid "Network Type" +msgstr "传输åè®®" + +msgid "User-defined GFW-List" +msgstr "用户自定义GFW-List" + +msgid "
    (!)Note: When the domain name is entered and will automatically merge with the online GFW-List. Please manually update the GFW-List list after applying." +msgstr "用户自定义GFW-List将会和自动更新的自动åˆå¹¶ã€‚如果è¦æ–°åŠ å…¥åŸŸå马上生效,请应用åŽç‚¹å‡»æ‰‹åŠ¨å¼ºåˆ¶æ›´æ–°GFW-List" + +msgid "Status and Tools" +msgstr "状æ€ä¸Žå·¥å…·" + +msgid "Watchdog Log" +msgstr "守护日志" + +msgid "Client Proxy Mode Settings" +msgstr "客户端代ç†æ¨¡å¼è®¾ç½®" + +msgid "Proxy mode settings can be set to specific LAN clients ( No Proxy, Global Proxy, Game Mode) . Does not need to be set by default." +msgstr "å¯ä»¥ä¸ºå±€åŸŸç½‘客户端分别设置ä¸åŒçš„代ç†æ¨¡å¼ ( ä¸ä»£ç†, 全局代ç†, 游æˆæ¨¡å¼).默认无需设置" + +msgid "GFW-List Add-in IP" +msgstr "GFW-List附加IP" + +msgid "
    (!)Note: IP add-in to GFW-List. Such as Telegram Messenger" +msgstr "
    (!)注æ„:有些应用使用IP而ä¸æ˜¯åŸŸå,例如 Telegram Messenger ,您需è¦æŠŠIP地å€åŠ å…¥è¿™é‡Œ" + +msgid "No Proxy" +msgstr "ä¸ä»£ç†" + +msgid "Global Proxy" +msgstr "全局代ç†" + +msgid "Game Mode" +msgstr "游æˆæ¨¡å¼" + +msgid "Config File Type" +msgstr "é…置文件类型" + +msgid "Use Config File" +msgstr "使用é…置文件" + +msgid "Warning: Can't find v2ctl. You can only choose Protobuf." +msgstr "注æ„:没有找到 v2ctl å¯æ‰§è¡Œç¨‹åºã€‚ä½ åªèƒ½é€‰æ‹©ä½¿ç”¨ Protobuf." + +msgid "If you choose to upload a new file, please do not modify and this configuration will be overwritten automatically." +msgstr "如果你在下方选择了上传新的é…置文件,那你ä¸éœ€è¦æ”¹åŠ¨è¿™ä¸ªæ¡†æ¡†é‡Œçš„内容。上传完æˆåŽå°†ä¼šè‡ªåŠ¨å¡«å……。" + +msgid "Create upload file error." +msgstr "上传文件失败。" + +msgid "File saved to" +msgstr "文件已ä¿å­˜åˆ°" + +msgid "No specify upload file." +msgstr "未指定上传文件" diff --git a/package/lean/luci-app-v2ray/root/etc/config/v2ray b/package/lean/luci-app-v2ray/root/etc/config/v2ray new file mode 100644 index 000000000..72d28a8aa --- /dev/null +++ b/package/lean/luci-app-v2ray/root/etc/config/v2ray @@ -0,0 +1,31 @@ +config v2ray 'v2ray' + option gfwlist 'china-banned' + option enabled '0' + option proxy_mode 'M' + option safe_dns_tcp '1' + option cron_mode '1' + option address 'test.TEST' + option port '443' + option id '00755892-0921-4433-bd92-04242abd92af' + option alterId '64' + option security 'aes-128-gcm' + option network_type 'ws' + option tls '1' + option mux '1' + option tcp_obfs 'none' + list tcp_path '/' + list tcp_host 'www.baidu.com' + option kcp_obfs 'none' + option kcp_mtu '1350' + option kcp_tti '20' + option kcp_uplink '5' + option kcp_downlink '20' + option kcp_congestion '1' + option kcp_readbuf '2' + option kcp_writebuf '2' + option ws_path '/v2ray' + option ws_headers 'www.baidu.com' + + + + diff --git a/package/lean/luci-app-v2ray/root/etc/init.d/v2raypro b/package/lean/luci-app-v2ray/root/etc/init.d/v2raypro new file mode 100755 index 000000000..f3aa08630 --- /dev/null +++ b/package/lean/luci-app-v2ray/root/etc/init.d/v2raypro @@ -0,0 +1,379 @@ +#!/bin/sh /etc/rc.common + +START=99 +# local port is defined in $V2_CONF_GENERATE_LUA +SS_REDIR_PORT=7070 +SS_REDIR_PIDFILE=/var/run/v2ray-go.pid +PDNSD_LOCAL_PORT=7453 +SSRCONF=/etc/v2ray/config.json +V2_CONF_GENERATE_LUA=/etc/v2ray/gen_config.lua +CRON_FILE=/etc/crontabs/root +CONFIG=v2ray +V2RAY_EXEC_PATH=/usr/bin/v2ray/v2ray + + +# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + # $covered_subnets, $local_addresses are not required +covered_subnets=`uci get v2ray.@v2ray[0].covered_subnets 2>/dev/null` +local_addresses=`uci get v2ray.@v2ray[0].local_addresses 2>/dev/null` + # Get LAN settings as default parameters + [ -f /lib/functions/network.sh ] && . /lib/functions/network.sh + [ -z "$covered_subnets" ] && network_get_subnet covered_subnets lan + [ -z "$local_addresses" ] && network_get_ipaddr local_addresses lan +vt_np_ipset="china" # Must be global variable + +__gfwlist_by_mode() +{ + case "$1" in + V) echo unblock-youku;; + *) echo china-banned;; + esac +} + + + +# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +start() +{ + local vt_enabled=`uci get v2ray.@v2ray[0].enabled 2>/dev/null` + local vt_safe_dns=`uci get v2ray.@v2ray[0].safe_dns 2>/dev/null` + local vt_safe_dns_port=`uci get v2ray.@v2ray[0].safe_dns_port 2>/dev/null` + local vt_safe_dns_tcp=`uci get v2ray.@v2ray[0].safe_dns_tcp 2>/dev/null` + local vt_proxy_mode=`uci get v2ray.@v2ray[0].proxy_mode` + local vt_server_addr='uci get v2ray.@v2ray[0].address' + local cron_mode=`uci get v2ray.@v2ray[0].cron_mode 2>/dev/null` + local vt_gfwlist=`__gfwlist_by_mode $vt_proxy_mode` + local use_conf_file=`uci get v2ray.@v2ray[0].use_conf_file 2>/dev/null` + local conf_file_path=`uci get v2ray.@v2ray[0].conf_file_path 2>/dev/null` + local conf_file_type=`uci get v2ray.@v2ray[0].conf_file_type 2>/dev/null` + + + [ -f /etc/init.d/pdnsd ] && /etc/init.d/pdnsd disable 2>/dev/null + + # ----------------------------------------------------------------- + if [ "$vt_enabled" = 0 ]; then + echo "WARNING: V2Ray is disabled." + return 1 + fi + + [ -z "$vt_proxy_mode" ] && vt_proxy_mode=M + [ -z "$vt_method" ] && vt_method=table + [ -z "$vt_timeout" ] && vt_timeout=60 + case "$vt_proxy_mode" in + M|S|G) + [ -z "$vt_safe_dns" ] && vt_safe_dns="8.8.8.8" + [ -z "$vt_safe_dns_tcp" ] && vt_safe_dns_tcp=1 + ;; + esac + [ -z "$vt_safe_dns_port" ] && vt_safe_dns_port=53 + + # ----------------------------------------------------------------- + ###### v2ray ###### + + if [ "$use_conf_file" = 0 ]; then + /usr/bin/lua $V2_CONF_GENERATE_LUA $CONFIG $SSRCONF + $V2RAY_EXEC_PATH -config=$SSRCONF & + else + $V2RAY_EXEC_PATH -config=$conf_file_path -format=$conf_file_type & + fi + + sleep 3 + if pidof v2ray>/dev/null; then + echo "V2Ray started" + else + return 1 + fi + + # IPv4 firewall rules + add_rule + + # ----------------------------------------------------------------- + mkdir -p /var/etc/dnsmasq-go.d + ###### Anti-pollution configuration ###### + if [ -n "$vt_safe_dns" ]; then + if [ "$vt_safe_dns_tcp" = 1 ]; then + start_pdnsd "$vt_safe_dns" + awk -vs="127.0.0.1#$PDNSD_LOCAL_PORT" '!/^$/&&!/^#/{printf("server=/%s/%s\n",$0,s)}' \ + /etc/gfwlist/$vt_gfwlist > /var/etc/dnsmasq-go.d/01-pollution.conf + else + awk -vs="$vt_safe_dns#$vt_safe_dns_port" '!/^$/&&!/^#/{printf("server=/%s/%s\n",$0,s)}' \ + /etc/gfwlist/$vt_gfwlist > /var/etc/dnsmasq-go.d/01-pollution.conf + fi + else + echo "WARNING: Not using secure DNS, DNS resolution might be polluted if you are in China." + fi + + ###### dnsmasq-to-ipset configuration ###### + case "$vt_proxy_mode" in + M|V) + awk '!/^$/&&!/^#/{printf("ipset=/%s/'"$vt_gfwlist"'\n",$0)}' \ + /etc/gfwlist/$vt_gfwlist > /var/etc/dnsmasq-go.d/02-ipset.conf + ;; + esac + + # ----------------------------------------------------------------- + ###### Restart main 'dnsmasq' service if needed ###### + if ls /var/etc/dnsmasq-go.d/* >/dev/null 2>&1; then + mkdir -p /tmp/dnsmasq.d + cat > /tmp/dnsmasq.d/dnsmasq-go.conf </dev/null + del_cron +} + +restart() +{ + KEEP_GFWLIST=Y + stop + start +} + +reload() +{ + local vt_enabled=`uci get v2ray.@v2ray[0].enabled 2>/dev/null` + local vt_server_addr=`uci get v2ray.@v2ray[0].address` + local vt_safe_dns=`uci get v2ray.@v2ray[0].safe_dns 2>/dev/null` + local vt_safe_dns_port=`uci get v2ray.@v2ray[0].safe_dns_port 2>/dev/null` + local vt_safe_dns_tcp=`uci get v2ray.@v2ray[0].safe_dns_tcp 2>/dev/null` + local vt_proxy_mode=`uci get v2ray.@v2ray[0].proxy_mode` + local vt_gfwlist=`__gfwlist_by_mode $vt_proxy_mode` + KEEP_GFWLIST=Y + del_rule + add_rule + if [ "$vt_safe_dns_tcp" = 1 ]; then + stop_pdnsd + start_pdnsd + fi +} + +# $1: upstream DNS server +start_pdnsd() +{ + local safe_dns="$1" + + local tcp_dns_list="208.67.222.222, 208.67.220.220" + [ -n "$safe_dns" ] && tcp_dns_list="$safe_dns,$tcp_dns_list" + + #killall -9 pdnsd 2>/dev/null && sleep 1 + kill -9 $(cat /var/run/pdnsd.pid) >/dev/null 2>&1 + + mkdir -p /var/etc /var/pdnsd + if ! test -f "/var/pdnsd/pdnsd.cache"; then + dd if=/dev/zero of="/var/pdnsd/pdnsd.cache" bs=1 count=4 2> /dev/null + chown -R nobody.nogroup /var/pdnsd + fi + + cat > /var/etc/pdnsd.conf </dev/null; then + while iptables -t nat -D OUTPUT -p tcp --dport 53 -j pdnsd_output 2>/dev/null; do :; done + iptables -t nat -X pdnsd_output + fi + killall -9 pdnsd 2>/dev/null + rm -rf /var/pdnsd + rm -f /var/etc/pdnsd.conf +} + +add_cron() +{ + sed -i '/up-gfwlist.sh/d' $CRON_FILE + sed -i '/v2ray_watchdog.log/d' $CRON_FILE + if [ $cron_mode -eq 1 ]; then + echo '0 5 * * * /etc/v2ray/up-gfwlist.sh > /tmp/gfwupdate.log 2>&1' >> $CRON_FILE + fi + echo '0 */1 * * * /etc/v2ray/v2ray-watchdog >> /tmp/v2ray_watchdog.log 2>&1' >> $CRON_FILE + echo '0 1 * * 0 echo "" > /tmp/v2ray_watchdog.log' >> $CRON_FILE + crontab $CRON_FILE +} + +del_cron() +{ + sed -i '/up-gfwlist.sh/d' $CRON_FILE + sed -i '/v2ray_watchdog.log/d' $CRON_FILE + /etc/init.d/cron restart +} + + + +uci_get_by_name() { + local ret=$(uci get $CONFIG.$1.$2 2>/dev/null) + echo ${ret:=$3} +} + +uci_get_by_type() { + local index=0 + if [ -n $4 ]; then + index=$4 + fi + local ret=$(uci get $CONFIG.@$1[$index].$2 2>/dev/null) + echo ${ret:=$3} +} + +is_ipv6_address() +{ + echo "$1" | grep -q ":" +} + +add_rule() +{ + iptables -t nat -N v2ray_pre + iptables -t nat -F v2ray_pre + iptables -t nat -A v2ray_pre -m set --match-set local dst -j RETURN || { + iptables -t nat -A v2ray_pre -d 10.0.0.0/8 -j RETURN + iptables -t nat -A v2ray_pre -d 127.0.0.0/8 -j RETURN + iptables -t nat -A v2ray_pre -d 172.16.0.0/12 -j RETURN + iptables -t nat -A v2ray_pre -d 192.168.0.0/16 -j RETURN + iptables -t nat -A v2ray_pre -d 127.0.0.0/8 -j RETURN + iptables -t nat -A v2ray_pre -d 224.0.0.0/3 -j RETURN + } + + iptables -t nat -A v2ray_pre -d $vt_server_addr -j RETURN + + iptables -N gameboost -t mangle + ipset -! create gameuser hash:ip maxelem 65536 2>/dev/null + /usr/bin/ip rule add fwmark 0x01/0x01 table 100 + /usr/bin/ip route add local 0.0.0.0/0 dev lo table 100 + iptables -t mangle -A gameboost -p udp -m set --match-set local dst -j RETURN + iptables -t mangle -A gameboost -p udp -m set --match-set china dst -j RETURN + iptables -t mangle -A gameboost -p udp --dport 53 -j RETURN + iptables -t mangle -A gameboost -p udp -j TPROXY --on-port 7070 --tproxy-mark 0x01/0x01 + iptables -t mangle -A PREROUTING -m set --match-set gameuser src -j gameboost + + for i in $(seq 0 100) + do + local ip=$(uci_get_by_type acl_rule ipaddr '' $i) + local mode=$(uci_get_by_type acl_rule filter_mode '' $i) + case "$mode" in + disable) + iptables -t nat -A v2ray_pre -s $ip -j RETURN + ;; + global) + iptables -t nat -A v2ray_pre -s $ip -p tcp -j REDIRECT --to $SS_REDIR_PORT + iptables -t nat -A v2ray_pre -s $ip -j RETURN + ;; + game) + iptables -t nat -A v2ray_pre -p tcp -s $ip -m set ! --match-set china dst -j REDIRECT --to $SS_REDIR_PORT + ipset -! add gameuser $ip + ;; + esac + done + + case "$vt_proxy_mode" in + G) : ;; + S) + iptables -t nat -A v2ray_pre -m set --match-set $vt_np_ipset dst -j RETURN + iptables -t nat -I OUTPUT -p tcp -m multiport --dports 80,443 -m set ! --match-set $vt_np_ipset dst -j REDIRECT --to $SS_REDIR_PORT + ;; + M) + ipset -! create $vt_gfwlist hash:ip maxelem 65536 2>/dev/null + awk '!/^$/&&!/^#/{printf("add vt_gfwlist %s'" "'\n",$0)}' /etc/v2ray/addinip.txt > /tmp/addinip.ipset + sed -i "s/vt_gfwlist/$vt_gfwlist/g" /tmp/addinip.ipset + ipset -! restore < /tmp/addinip.ipset + iptables -t nat -A v2ray_pre -m set ! --match-set $vt_gfwlist dst -j RETURN + iptables -t nat -A v2ray_pre -m set --match-set $vt_np_ipset dst -j RETURN + iptables -t nat -I OUTPUT -p tcp -m multiport --dports 80,443 -m set --match-set $vt_gfwlist dst -j REDIRECT --to $SS_REDIR_PORT + ;; + V) + vt_np_ipset="" + ipset -! create $vt_gfwlist hash:ip maxelem 65536 2>/dev/null + iptables -t nat -A v2ray_pre -m set ! --match-set $vt_gfwlist dst -j RETURN + ;; + esac + local subnet + for subnet in $covered_subnets; do + iptables -t nat -A v2ray_pre -s $subnet -p tcp -j REDIRECT --to $SS_REDIR_PORT + done + iptables -t nat -I PREROUTING -p tcp -j v2ray_pre +} + +del_rule() +{ + if iptables -t nat -F v2ray_pre 2>/dev/null; then + while iptables -t nat -D PREROUTING -p tcp -j v2ray_pre 2>/dev/null; do :; done + iptables -t nat -X v2ray_pre 2>/dev/null + fi + + iptables -t nat -D OUTPUT -p tcp -m multiport --dports 80,443 -m set --match-set china-banned dst -j REDIRECT --to $SS_REDIR_PORT 2>/dev/null + iptables -t nat -D OUTPUT -p tcp -m multiport --dports 80,443 -m set ! --match-set $vt_np_ipset dst -j REDIRECT --to $SS_REDIR_PORT 2>/dev/null + + /usr/bin/ip rule del fwmark 0x01/0x01 table 100 + /usr/bin/ip route del local 0.0.0.0/0 dev lo table 100 + if iptables -t mangle -F gameboost 2>/dev/null; then + while iptables -t mangle -D PREROUTING -m set --match-set gameuser src -j gameboost 2>/dev/null; do :; done + iptables -t mangle -X gameboost 2>/dev/null + fi + + ipset destroy gameuser 2>/dev/null + + + # ----------------------------------------------------------------- + [ "$KEEP_GFWLIST" = Y ] || ipset destroy "$vt_gfwlist" 2>/dev/null +} diff --git a/package/lean/luci-app-v2ray/root/etc/uci-default/v2ray b/package/lean/luci-app-v2ray/root/etc/uci-default/v2ray new file mode 100755 index 000000000..9b377b010 --- /dev/null +++ b/package/lean/luci-app-v2ray/root/etc/uci-default/v2ray @@ -0,0 +1,16 @@ +#!/bin/sh + +uci -q batch <<-EOF >/dev/null + delete firewall.v2ray + set firewall.v2ray=include + set firewall.v2ray.type=script + set firewall.v2ray.path=/etc/v2ray.include + set firewall.v2ray.reload=1 + commit firewall +EOF + +/etc/init.d/v2raypro stop +/etc/init.d/v2raypro disable + +rm -f /tmp/luci-indexcache +exit 0 diff --git a/package/lean/luci-app-v2ray/root/etc/v2ray.include b/package/lean/luci-app-v2ray/root/etc/v2ray.include new file mode 100755 index 000000000..ca519372e --- /dev/null +++ b/package/lean/luci-app-v2ray/root/etc/v2ray.include @@ -0,0 +1,11 @@ +#!/bin/sh + +ssr_enable=$(uci get v2ray.@v2ray[0].enabled 2>/dev/null) + +if [ $ssr_enable -eq 1 ]; then + if pidof v2ray>/dev/null; then + /etc/init.d/v2raypro reload + else + /etc/init.d/v2raypro restart + fi +fi diff --git a/package/lean/luci-app-v2ray/root/etc/v2ray/addinip.txt b/package/lean/luci-app-v2ray/root/etc/v2ray/addinip.txt new file mode 100755 index 000000000..d9caab65b --- /dev/null +++ b/package/lean/luci-app-v2ray/root/etc/v2ray/addinip.txt @@ -0,0 +1,7 @@ +149.154.160.0/20 +149.154.164.0/22 +149.154.168.0/21 +67.198.55.0/24 +91.108.4.0/22 +91.108.56.0/22 +109.239.140.0/24 \ No newline at end of file diff --git a/package/lean/luci-app-v2ray/root/etc/v2ray/base-gfwlist.txt b/package/lean/luci-app-v2ray/root/etc/v2ray/base-gfwlist.txt new file mode 100755 index 000000000..607a90247 --- /dev/null +++ b/package/lean/luci-app-v2ray/root/etc/v2ray/base-gfwlist.txt @@ -0,0 +1,2940 @@ +0rz.tw +0to255.com +10musume.com +123rf.com +12bet.com +12vpn.com +141hongkong.com +173ng.com +1984bbs.com +1984bbs.org +1-apple.com.tw +1bao.org +1eew.com +1pondo.tv +2000fun.com +2008xianzhang.info +21andy.com +247realmedia.com +24smile.org +2-hand.info +2mdn.net +2shared.com +301works.org +315lz.com +32red.com +365singles.com.ar +36rain.com +4bluestones.biz +4chan.org +4pppc.gov.tw +4shared.com +4sq.com +51.ca +5i01.com +5maodang.com +64tianwang.com +64wiki.com +666kb.com +6park.com +7capture.com +881903.com +888.com +89-64.org +9001700.com +91porn.com +921.gov.tw +92ccav.com +9bis.com +9bis.net +9city.me +a5.com.ru +abc.pp.ru +abitno.linpie.com +ablwang.com +aboluowang.com +aboutgfw.com +acgkj.com +ac.jiruan.net +ac.playstation.net +actimes.com.au +aculo.us +ad1.nownews.com +addictedtocoffee.de +ads.backchina.com +adultfriendfinder.com +adultkeep.net +advanscene.com +advertfan.com +aec.gov.tw +aenhancers.com +af.mil +aftygh.gov.tw +aide.gov.tw +aiph.net +aisex.com +ait.org.tw +aiweiweiblog.com +aiweiwei.com +ajaxplorer.info +akamaihd.net +akiba-online.com +alabout.com +alasbarricadas.org +alexlur.org +aliengu.com +alkasir.com +allaboutalpha.com +allgirlsallowed.org +alliance.org.hk +allinfa.com +allinfo.com +allmovie.com +allonlinux.free.fr +all-that-is-interesting.com +al-qimmah.net +alternate-tools.com +altrec.com +alvinalexander.com +alwaysdata.com +alwaysdata.net +am730.com.hk +amazonaws.com +ameblo.jp +americangreencard.com +amiblockedornot.com +amnesty.org +amnestyusa.org +amoiist.com +amzs.me +analyze-v.com +anchorfree.com +andfaraway.net +android.com +angularjs.org +animecrazy.net +anobii.com +anontext.com +anonymizer.com +a-normal-day.com +answering-islam.org +anthonycalzadilla.com +anti.anti.cnn.googlepages.com +antidrm.hpg.ig.com.br +antiwave.net +aobo.com.au +aolchannels.aol.com +aomiwang.com +apetube.com +apiary.io +apidocs.linksalpha.com +apigee.com +api.linksalpha.com +api.proxlet.com +api.supertweet.net +app.heywire.com +app.hkatvnews.com +appledaily.com +appledaily.com.tw +apps.hloli.net +appspot.com +archive.is +archive.org +arctosia.com +areca-backup.org +army.mil +arte.gov.tw +art-or-porn.com +artsy.net +asahichinese.com +asdfg.jp +asiafriendfinder.com +asiaharvest.org +asianews.it +asianwomensfilm.de +askstudent.com +askynz.net +assembla.com +astonmartinnews.com +atchinese.com +atc.org.au +atgfw.org +atj.org.tw +atlaspost.com +atnext.com +autoproxy.org +avaaz.org +avdb.in +avidemux.org +avoision.com +awardwinningfjords.com +axureformac.com +babynet.com.hk +backchina.com +backpackers.com.tw +badassjs.com +badoo.com +baidu.jp +baixing.me +bannedbook.org +barnabu.co.uk +basetimesheightdividedby2.com +bayvoice.net +bbcchinese.com +bbc.com +bbc.co.uk +bbci.co.uk +bbcimg.co.uk +bbc.in +bbg.gov +bbs2.newsgroup.la +bbs.ecstart.com +bbsfeed.com +bbs.kimy.com.tw +bbsland.com +bbs.morbell.com +bbs.mychat.to +bbs.newsgroup.la +bbs.ozchinese.com +bbs.qmzdd.com +bbs.sina.com +bbs.skykiwi.com +bbs.tuitui.info +bb.ttv.com.tw +bcc.com.tw +bcchinese.net +bdhr.gov.tw +bd.zhe.la +bebo.com +beeg.com +beijing1989.com +beijingspring.com +benjaminste.in +berlintwitterwall.com +bestforchina.org +bestvpnservice.com +bet365.com +beta.iset.com.tw +beta.usejump.com +betfair.com +bettween.com +betvictor.com +bewww.net +beyondfirewall.com +bfnn.org +biantailajiao.com +biantailajiao.in +bigfools.com +bignews.org +bigsound.org +bill2-software.com +billywr.com +bill.zhong.pp.ru +bipic.net +bitcointalk.org +bit.ly +bitly.com +bitshare.com +bjzc.org +blinkx.com +blinw.com +blip.tv +blockcn.com +blog.birdhouseapp.com +blog.bitly.com +blogblog.com +blog.boxcar.io +blogcatalog.com +blog.davidziegler.net +blog.dayoneapp.com +blog.de +blog.dribbble.com +blog.exblog.co.jp +blog.expofutures.com +blog.fizzik.com +blog.foolsmountain.com +blogger.com +blog.gowalla.com +blog.hotpotato.com +blog.ifttt.com +blogimg.jp +blog.instagram.com +blog.instapaper.com +blog.iphone-dev.org +blog.istef.info +blog.jackjia.com +blog.joeyrobert.org +blog.kangye.org +blog.kickstarter.com +blog.kl.am +blog.klip.me +blog.lester850.info +blog.lightbox.com +bloglines.com +bloglovin.com +blog.mongodb.org +blog.openinkpot.org +blog.palm.com +blog.path.com +blog.pathtosharepoint.com +blog.pchome.com.tw +blog.pentalogic.net +blog.pikchur.com +blog.pilotmoon.com +blog.redren.com +blog.rockmelt.com +blog.romanandreg.com +blog.s135.com +blogs.icerocket.com +blog.sina.com.tw +blog.sogoo.org +blog.sparrowmailapp.com +blogspot.com +blogspot.co.uk +blogspot.de +blogspot.fr +blogspot.in +blogspot.jp +blogs.tampabay.com +blog.summify.com +blogs.yahoo.co.jp +blog.syx86.cn +blog.syx86.com +blog.taragana.com +blogtd.net +blogtd.org +blog.tiney.com +blog.topify.com +blog.usa.gov +blog.xuite.net +blog.youthwant.com.tw +blog.youxu.info +bloodshed.net +bloomberg.cn +bloomberg.com +bloomberg.de +bloomfortune.com +bmediaasia.com +bnrmetal.com +boardreader.com +bobulate.com +bolin.netfirms.com +bonbonme.com +bonjourlesgeeks.com +boobstagram.com +books.com.tw +bookshelfporn.com +botanwang.com +bot.nu +bowenpress.com +boxunblog.com +boxunclub.com +boxun.com +boxun.tv +bralio.com +branch.com +brandonhutchinson.com +braumeister.org +break.com +breakingtweets.com +briefdream.com +brightcove.com +brightkite.com +brizzly.com +broadbook.com +br.st +brucewang.net +bt95.com +btdigg.org +btrd.net +budaedu.org +bugclub.org +builtwithbootstrap.com +bullogger.com +bullog.org +businesstimes.com.cn +businessweek.com +buugaa.com +buy.yahoo.com.tw +buzzurl.jp +bwbx.io +bwsj.hk +bx.tl +c1522.mooo.com +cacnw.com +cactusvpn.com +cafepress.com +cahr.org.tw +calameo.com +calebelston.com +cams.com +cams.org.sg +canadameet.com +canyu.org +caobian.info +caochangqing.com +cao.im +cari.com.my +catch22.net +catfightpayperview.xxx +catholic.org.hk +catholic.org.tw +cbs.ntu.edu.tw +cc9007.spaces.live.com +ccavtop10.com +ccdtr.org +ccim.org +cclife.org +ccthere.com +cctongbao.com +ccue.ca +ccue.com +cdig.info +cdjp.org +cdnews.com.tw +cdn.printfriendly.com +cdp1998.org +cdp2006.org +cdp.sinica.edu.tw +cdpusa.org +cdpweb.org +cdpwu.org +cdw.com +cecc.gov +cellulo.info +cenci.tk +cenews.eu +centralnation.com +centurys.net +c-est-simple.com +cfhks.org.hk +cftfc.com +cgdepot.org +chandoo.org +change.org +changp.com +chaos.e-spacy.com +chapm25.com +chartbeat.net +chaturbate.com +chccc.gov.tw +chengmingmag.com +chenguangcheng.com +chenpokong.com +chenyehao.spaces.live.com +cherrysave.com +chevronwp7.com +chicagoncmtv.com +china101.com +china21.com +china21.org +china5000.us +chinaaffairs.org +chinaaid.me +chinaaid.net +chinaaid.org +chinaaid.us +chinachange.org +chinachannel.hk +chinacomments.org +chinadigitaltimes.net +chinaeweekly.com +chinafreepress.org +chinagate.com +chinageeks.org +chinagfw.org +chinagreenparty.org +china-green-party.spaces.live.com +chinahush.com +chinainperspective.com +chinainperspective.net +chinainperspective.org +chinainterimgov.org +chinalawandpolicy.com +chinalawtranslate.com +chinamule.com +chinamz.org +chinarightsia.org +chinasocialdemocraticparty.com +chinaso.com +chinasoul.org +chinatimes.com +chinatweeps.com +chinaway.org +china-week.com +chinaworker.info +chinaxchina.com +chinayouth.org.hk +chinayuanmin.org +chinesedailynews.com +chinese.engadget.com +chinese-hermit.net +chinese-memorial.org +chinesen.de +chinesenewsnet.com +chinesepen.org +chinese.rnw.nl +chinese.soifind.com +chinesetalks.net +chinese.wsj.com +chingcheong.com +chn.chosun.com +chrispederick.com +chrispederick.net +christianstudy.com +christiantimes.org.hk +christusrex.org +chrlawyers.hk +chrlcg-hk.org +chromeadblock.com +chrome.com +ch.shvoong.com +chubun.com +chuizi.net +chukuang.gov.tw +circlethebayfortibet.org +citizenlab.org +citizensradio.org +city9x.com +civicparty.hk +civilhrfront.org +civilmedia.tw +cjb.net +ck101.com +classicalguitarblog.net +clb.org.hk +cl.d0z.net +clientsfromhell.net +clipfish.de +cl.ly +cloudfront.net +club.backchina.com +cms.gov +cmule.com +cn2.streetvoice.com +cna.com.tw +cnavista.com.tw +cn.calameo.com +cn.dayabook.com +cnd.org +cn.fmnnow.com +cn.ibtimes.com +cnn.com +cn.news.cnyes.com +cn.streetvoice.com +cn.uncyclopedia.wikia.com +cn.voa.mobi +cochina.org +cocoapods.org +cocoa.zonble.net +code1984.com +codeboxapp.com +codeshare.io +collateralmurder.com +collateralmurder.org +comefromchina.com +comnews.gio.gov.tw +compileheart.com +connectedchina.reuters.com +connect.facebook.net +conoyo.com +contactmagazine.net +contests.twilio.com +conviva.com +cookingtothegoodlife.com +coolaler.com +coolder.com +coolloud.org.tw +corpus4u.org +corumcollege.com +cotweet.com +couchdbwiki.com +coveringweb.com +cp-house.gov.tw +cpj.org +crackle.com +crd-net.org +creaders.net +cromotc.nat.gov.tw +crossthewall.net +csdparty.com +c-spanvideo.org +css.pixnet.in +csuchen.de +cts.com.tw +cubicle17.com +cuhkacs.org +cuihua.org +cuiweiping.net +culture.tw +curvefish.com +cwb.gov.tw +cyanogenmod.org +cyberghost.natado.com +cyberghostvpn.com +cycab.gov.tw +cydia.ifuckgfw.com +cynscribe.com +cytode.us +dabr.co.uk +dabr.me +dabr.mobi +dadazim.com +dadi360.com +dafagood.com +dafahao.com +dailidaili.com +dailymotion.com +dailynews.sina.com +dajiyuan.com +dajiyuan.eu +dajusha.baywords.com +dalailama.com +dalailama.ru +dalailamaworld.com +dalianmeng.org +danke4china.net +danwei.org +daolan.net +dapu-house.gov.tw +darpa.mil +date.fm +davidslog.com +daxa.cn +dayaarmongol.ning.com +daylife.com +ddc.com.tw +deck.ly +default.secureserver.net +delcamp.net +delicious.com +democrats.org +demo.opera-mini.net +derekhsu.homeip.net +de-sci.org +designerol.com +destiny.xfiles.to +deutsche-welle.de +dev102.com +developers.box.net +deviantart.com +deviantart.net +devio.us +devpn.com +dfas.mil +df.gov.tw +diaoyuislands.org +digitalnomadsproject.org +diigo.com +dimitrik.free.fr +dipity.com +directcreative.com +discuss.com.hk +disp.cc +dit-inc.us +dizhidizhi.com +djangosnippets.org +dl.box.net +dl-laby.jp +dl.playstation.net +dlsite.com +dmcdn.net +dmtip.gov.tw +dns2go.com +dnscrypt.org +docstoc.com +dojin.com +dok-forum.net +dolc.de +dollf.com +domain.club.tw +domainhelp.search.com +dongde.com +dongtaiwang.com +dongtaiwang.net +dongyangjing.com +dontfilter.us +dontmovetochina.com +dotheyfolloweachother.com +dotplane.com +dotsub.com +doubleaf.com +doubleclick.net +dougscripts.com +dowei.org +download.syniumsoftware.com +doxygen.org +dphk.org +dpp.org.tw +drewolanoff.com +drgan.net +dropbox.com +dropboxusercontent.com +drsunacademy.com +drtuber.com +dscn.info +dtiblog.com +dtic.mil +dtiserv2.com +duckduckgo.com +duckload.com +duckmylife.com +duihuahrjournal.org +duihua.org +duoweitimes.com +duping.net +duplicati.com +dupola.com +dupola.net +dvorak.org +dw.de +dwnews.com +dwnews.net +dw-world.com +dw-world.de +dy24k.info +dynawebinc.com +dyndns.org +dzze.com +e123.hk +eamonnbrennan.com +earthquake.usgs.gov +easy-share.com +ebookbrowse.com +ebookee.com +echofon.com +ecministry.net +edicypages.com +edoors.com +edubridge.com +eevpn.com +efcc.org.hk +efksoft.com +efmoe.com +e-gold.com +eic-av.com +e-info.org.tw +electionsmeter.com +elpais.com +eltondisney.com +emacsblog.org +embr.in +emory.edu +emule-ed2k.com +emuparadise.me +enewstree.com +en.favotter.net +englishfromengland.co.uk +entermap.com +en.wikipedia.org +epochtimes-bg.com +epochtimes.co.il +epochtimes.co.kr +epochtimes.com +epochtimes.de +epochtimes.fr +epochtimes.ie +epochtimes.jp +epochtimes-romania.com +epochtimes.ru +epochtimes.se +epochtimestr.com +epochweekly.com +erabaru.net +erepublik.com +erepublik.net +erights.net +eriversoft.com +ernestmandel.org +etaiwannews.com +etizer.org +etools.ncol.com +e-traderland.net +etraining.gov.tw +ettoday.net +evchk.wikia.com +eventful.com +everyday-carry.com +exblog.jp +expatshield.com +exploader.net +extremetube.com +eyespirit.info +eyevio.jp +eyny.com +ezpc.tk +ezpeer.com +facebook.com +facebook.net +facesofnyfw.com +fail.hk +faiththedog.info +fakku.net +falsefire.com +falunart.org +falundafamuseum.org +falundafa.org +falunhr.org +famunion.com +fangbinxing.com +fangeming.com +fanglizhi.info +fangongheike.com +fangong.org +fan-qiang.com +fanqianghou.com +fanqiangyakexi.net +fanswong.com +fanyue.info +fapdu.com +farwestchina.com +farxian.com +fastpic.ru +faststone.org +favorious.com +favstar.fm +fawanghuihui.org +faydao.com +fbcdn.net +fb.com +fb.me +fbsbx.com +fc2china.com +fc2.com +f.cl.ly +fdc89.jp +feedbooks.mobi +feedburner.com +feeds2.feedburner.com +feeds.feedburner.com +feedzshare.com +feelssh.com +feer.com +felixcat.net +feministteacher.com +fengzhenghu.com +fetchvideo.com +ff.im +fflick.com +fgmtv.net +fgmtv.org +filefactory.com +files2me.com +fileserve.com +fillthesquare.org +finalion.jp +findbook.tw +finler.net +fireofliberty.org +firstfivefollowers.com +flecheinthepeche.fr +fleshbot.com +flickr.com +flickrhivemind.net +flightcaster.com +flowerofhappiness.spaces.live.com +focustaiwan.tw +focusvpn.com +fofg.org +fooooo.com +footwiball.com +forum.baby-kingdom.com +forum.cyberctm.com +forum.idsam.com +forum.iset.com.tw +forum.my903.com +forum.mymaji.com +forum.newsgroup.la +forum.nownews.com +forum.omy.sg +forum.palmislife.com +forum.pchome.com.tw +forum.setty.com.tw +forum.sina.com.hk +forum.slime.com.tw +forum.tvb.com +forum.yorkbbs.ca +fotop.net +fourface.nodesnoop.com +fourthinternational.org +foxdie.us +foxsub.com +foxtang.com +fqrouter.com +franklc.com +freakshare.com +fredwilson.vc +free4u.com.ar +freealim.com +freechal.com +freedomhouse.org +free.fr +freegao.com +freegateget.googlepages.com +free-gate.org +free-hada-now.org +freelotto.com +freeman2.com +freemoren.com +freemorenews.com +freenet-china.org +freenetproject.org +freenewscn.com +freeopenvpn.com +freeoz.org +free-ssh.com +freessh.us +freetibet.org +freevpn.nl +freewallpaper4.me +freewebs.com +freeweibo.com +freexinwen.com +freeyoutubeproxy.net +friendfeed.com +friendfeed-media.com +fring.com +fringenetwork.com +frommel.net +frontlinedefenders.org +fscked.org +fsurf.com +ftchinese.com +fuckcnnic.net +fuckgfw.com +fuckgfw.org +fulue.com +funf.tw +funp.com +furinkan.com +furl.net +futurechinaforum.org +futureme.org +futuremessage.org +fuyin.net +fw.cm +fxnetworks.com +fzh999.com +fzh999.net +gabocorp.com +gaeproxy.com +gaeproxy.googlecode.com +galenwu.com +game735.com +gamebase.com.tw +gamer.com.tw +gamez.com.tw +ganges.com +gaoming.net +gaopi.net +gaozhisheng.net +gaozhisheng.org +gardennetworks.com +gardennetworks.org +gartlive.com +gather.com +gaymap.cc +gazotube.com +gcc.org.hk +gclooney.com +g.co +gcpnews.com +gdbt.net +gdzf.org +geek-art.net +geekerhome.com +geekmade.co.uk +geekmanuals.com +generesis.com +genuitec.com +geocities.co.jp +geocities.com +geocities.jp +geohot.com +geometrictools.com +getchu.com +getcloudapp.com +get-digital-help.com +getfoxyproxy.org +getfreedur.com +getiton.com +getjetso.com +getlantern.org +getsmartlinks.com +getsocialscope.com +gfwinterceptor.googlecode.com +gfw.org.ua +ggpht.com +ggssl.com +ghost.org +ghut.org +giga-web.jp +gigporno.ru +gimpshop.com +girlbanker.com +github.com +git-scm.com +givemesomethingtoread.com +glennhilton.com +globaljihad.net +globalmuseumoncommunism.org +globalrescue.net +globalvoicesonline.org +gmail.com +gmbd.cn +gmhz.org +gmodules.com +gmozomg.izihost.org +gnci.org.hk +goagent.biz +goagent.googlecode.com +goagentplus.com +godfootsteps.org +golang.org +goldbetsports.com +goldwave.com +gongmeng.info +gongm.in +gongminliliang.com +gongwt.com +goodreaders.com +goodreads.com +goofind.com +goo.gl +googleadservices.com +google-analytics.com +googleapis.com +googlecode.com +google.co.jp +google.com +google.com.hk +google.com.sg +google.com.tw +google.com.uk +googledomains.com +googledrive.com +googleearth.com +googlehosted.com +googlelabs.com +googlemail.com +googleplus.com +googlesile.com +googlesource.com +googlesyndication.com +googletagmanager.com +googletagservices.com +googleusercontent.com +googlevideo.com +gopetition.com +gospelherald.com +gov.tw +gpass1.com +grandtrial.org +graphis.ne.jp +gravatar.com +graylog2.org +grb.gov.tw +greatfire.org +greatfirewall.biz +great-firewall.com +greatfirewallofchina.net +greatfirewallofchina.org +great-roc.org +greatroc.org +greatroc.tw +greatzhonghua.org +greenparty.org.tw +greenvpn.net +gs-discuss.com +gseeker.com +gsn-cert.nat.gov.tw +gstatic.com +gtap.googlecode.com +gtricks.com +guancha.org +gufeng521.spaces.live.com +guishan.org +gunsamerica.com +gun-world.net +guomin.us +gutteruncensored.com +gvm.com.tw +gyalwarinpoche.com +gysd.nyc.gov.tw +gzm.tv +gzone-anime.info +h1n1china.org +hacken.cc +hackthatphone.net +hahlo.com +hakkatv.org.tw +hanunyi.com +hardsextube.com +hasaowall.com +have8.com +haygo.com +hcc.gov.tw +hchcc.gov.tw +h-china.org +hdtvb.net +heartyit.com +hecaitou.net +hechaji.com +heix.pp.ru +heiyo.info +helloandroid.com +hellonewyork.us +helloqueer.com +hellotxt.com +hellouk.org +helpeachpeople.com +helplinfen.com +help.linksalpha.com +help.opera.com +helpzhuling.org +hen.bao.li +hengchuen.gov.tw +heqinglian.net +here4news.com +heungkongdiscuss.com +hgseav.com +hidden-advent.org +hidecloud.com +hideipvpn.com +hidemyass.com +higfw.com +highrockmedia.com +hihiforum.com +hihistory.net +hiitch.com +hikinggfw.org +himemix.com +himemix.net +hjclub.info +hk32168.com +hkbc.net +hkbf.org +hkchurch.org +hkdailynews.com.hk +hkday.net +hkej.com +hkepc.com +hkfront.org +hk.geocities.com +hkgolden.com +hkgreenradio.org +hkg.westkit.net +hkheadline.com +hkhkhk.com +hkjc.com +hk.jiepang.com +hkjp.easyweb.hk +hkjp.org +hk.knowledge.yahoo.com +hk.myblog.yahoo.com +hk.news.yahoo.com +hkptu.org +hk-pub.com +hk.rd.yahoo.com +hkreporter.com +hkreporter.loved.hk +hk.search.yahoo.com +hk.video.news.yahoo.com +hkwcc.org.hk +hk.yahoo.com +hkzone.org +hnjhj.com +hola.com +holyspiritspeaks.org +holz.byethost8.com +homeservershow.com +home.sina.com +home.so-net.net.tw +honeonet.spaces.live.com +hongmeimei.com +hongzhi.li +hootsuite.com +hotpot.hk +hotshame.com +hotspotshield.com +hougaige.com +howtoforge.com +hqcdp.org +hrcir.com +hrichina.org +hrw.org +hsinchu-cc.gov.tw +hsjp.net +hsselite.com +htkou.net +htl.li +ht.ly +htmldog.com +huaglad.com +huajiadi.spaces.live.com +huanghuagang.org +huaren.us +huaxia-news.com +huaxin.ph +hua-yue.net +hudatoriq.web.id +hugoroy.eu +huhamhire.com +hujiachina.spaces.live.com +hulu.com +huluim.com +humanities.uchicago.edu +hungerstrikeforaids.org +hung-ya.com +huping.net +hutianyi.net +hutong9.net +hwinfo.com +hyperrate.com +hypeshell.com +i1.hk +i2runner.com +ialmostlaugh.com +iask.bz +iask.ca +ibiblio.org +iblogserv-f.net +ibros.org +icij.org +icl-fi.org +iconpaper.org +icu-project.org +idemocracy.asia +identi.ca +idiomconnection.com +idouga.com +idv.tw +ieasynews.net +ied2k.net +ieemdai.spaces.live.com +ifan.cz.cc +ifanqiang.com +ifanr.com +ifcss.org +ifjc.org +igfw.net +ignitedetroit.net +igvita.com +ihakka.net +iicns.com +illusionfactory.com +ilove80.be +im88.tw +imageflea.com +imagesblog.gio.gov.tw +imageshack.us +imagevenue.com +imagezilla.net +ime.baidu.jp +img.ly +imkev.com +imlive.com +immigration.gov.tw +imrworldwide.com +im.tv +incredibox.fr +iner.gov.tw +initiativesforchina.org +inmediahk.net +innermongolia.org +instagram.com +interestinglaugh.com +interfaceaddiction.com +internationalrivers.org +internetdefenseleague.org +internetfreedom.org +internetpopculture.com +inxian.com +iphone4hongkong.com +iphonehacks.com +iphonix.fr +ipicture.ru +ipobar.com +ippotv.com +iptorrents.com +ipvanish.com +iredmail.org +ironbigfools.compython.net +ironicsoftware.com +ironpython.net +isaacmao.com +isgreat.org +islamicity.com +islam.org.hk +ismprofessional.net +isohunt.com +israbox.com +istockphoto.com +isunaffairs.com +isuntv.com +itaboo.info +ithelp.ithome.com.tw +itrc.gov.tw +itshidden.com +itweet.net +iu45.com +iverycd.com +ixquick.com +izaobao.us +izles.net +japan-whores.com +jayparkinsonmd.com +jbtalks.cc +jbtalks.com +jbtalks.my +jeanyim.com +jgoodies.com +jiaoyou8.com +jiehua.cz +jieshibaobao.com +jike.com +jimoparty.com +jinbushe.org +jingpin.org +jitouch.com +jkforum.net +j.mp +joachims.org +jobso.tv +joeedelman.com +journalofdemocracy.org +jpopforum.net +juliereyc.com +junauza.com +junefourth-20.net +justfreevpn.com +justtristan.com +juziyue.com +jwmusic.org +jyxf.net +jyzj.waqn.com +k2.xrea.com +kagyuoffice.org.tw +kaiyuan.de +kakao.com +kanzhongguo.com +kanzhongguo.eu +karayou.com +ka-wai.com +kcsoftwares.com +kechara.com +keepandshare.com +kendincos.net +kenengba.com +keontech.net +khcc.gov.tw +khms.gov.tw +khmusic.com.tw +killwall.com +kineox.free.fr +kingdomsalvation.org +kinghost.com +kingstone.com.tw +kissbbao.cn +kissyoutube.com +kk.gov.tw +klccab.gov.tw +klra.gov.tw +klsio.gov.tw +kmh.gov.tw +kmseh.gov.tw +knowledgerush.com +kodingen.com +kompozer.net +koolsolutions.com +koornk.com +kt.kcome.org +kui.name +kun.im +kurtmunger.com +kusocity.com +kwongwah.com.my +kyohk.net +kzeng.info +labiennale.org +ladbrokes.com +la-forum.org +lagranepoca.com +lalulalu.com +laogai.org +laomiu.com +laoyang.info +laptoplockdown.com +laqingdan.net +larsgeorge.com +lastfm.es +latelinenews.com +latimesblogs.latimes.com +lazarsearlymusic.com +leecheukyan.org +legaltech.law.com +lematin.ch +lemonde.fr +lenwhite.com +lerosua.org +lesoir.be +lesscss.org +letscorp.net +liansi.org +lianyue.net +liaowangxizang.net +liberal.org.hk +libertytimes.com.tw +lich355.megabyet.net +lidecheng.com +life.fly4ever.me +limiao.net +line.me +linglingfa.com +lingvodics.com +linkideo.com +linuxconfig.org +linux-engineer.net +linuxreviews.org +linuxtoy.org +lipuman.com +listentoyoutube.com +list.ly +listorious.com +lists.debian.org +lists.w3.org +littlebigdetails.com +liudejun.com +liuhanyu.com +liujianshu.com +liu.lu +liuxiaotong.com +liveleak.com +livestation.com +livestream.com +livevideo.com +livingonline.us +livingstream.com +lizhizhuangbi.com +lkcn.net +localpresshk.com +lockdown.com +lockestek.com +logbot.net +logiqx.com +logmike.com +log.riku.me +london.neighborhoodr.com +longhair.hk +longtermly.net +lookatgame.com +lookingglasstheatre.org +lookpic.com +lotuslight.org.tw +lovequicksilver.com +lovesphinx.tk +lrfz.com +lsd.org.hk +lsforum.net +lsmchinese.org +lsmkorean.org +lsm.org +lsxszzg.com +lua.org +lua-users.org +lungtanhr.gov.tw +luntan.zaobao.com +lupm.org +lushstories.com +lvhai.org +lyricsquote.com +mad-ar.ch +madmenunbuttoned.com +magazines.sina.com.tw +maiio.net +mail-archive.com +maiplus.com +makemymood.com +makzhou.warehouse333.com +malaysiakini.com +marc.info +marco.org +marguerite.su +marines.mil +markmilian.com +martau.com +martincartoons.com +maruta.be +marxist.com +marxist.net +marxists.org +mashable.com +mash.to +matainja.com +mathiew-badimon.com +matsu-news.gov.tw +matsushimakaede.com +maxgif.com +mayimayi.com +mcadforums.com +mcfog.com +md-t.org +mediafire.com +meetup.com +mefeedia.com +megaporn.com +megarotic.com +megavideo.com +megurineluka.com +meirixiaochao.com +melon-peach.com +memedia.cn +meme.yahoo.com +memrijttm.org +merit-times.com.tw +mesotw.com +metacafe.com +meteorshowersonline.com +metrolife.ca +mgoon.com +mgstage.com +mh4u.org +mhradio.org +michaelanti.com +michaelmarketl.com +middle-way.net +mihk.hk +mihua.org +mike.cz.cc +mimivip.com +minghui.org +minghui-school.org +mingjinglishi.com +mingjingnews.com +mingpaocanada.com +mingpao.com +mingpaomonthly.com +mingpaonews.com +mingpaony.com +mingpaosf.com +mingpaotor.com +mingpaovan.com +minimalmac.com +mininova.org +minzhuhua.net +minzhuzhongguo.org +miroguide.com +mirrorbooks.com +mitbbs.com +mixedmedialabs.com +mixero.com +mixpod.com +mixx.com +mizzmona.com +mk5000.com +mlcool.com +mmaaxx.com +mmmca.com +mobatek.net +mobile01.com +mobileways.de +mobypicture.com +moby.to +modfetish.com +moe.gov.tw +mog.com +molihua.org +mondex.org +monitorchina.org +moonriver7.files.wordpress.com +morningsun.org +m.oulove.org +movabletype.com +moviefap.com +mp3ye.eu +mpettis.com +mpfinance.com +mpinews.com +m.plixi.com +mrdoob.com +mrtweet.com +msguancha.com +m.slandr.net +m-team.cc +mthruf.com +m.tweete.net +mtw.tl +multiply.com +multiproxy.org +multiupload.com +muouju.com +muselinks.co.jp +music.jwmusic.org +muzi.com +muzi.net +muzu.tv +mvdis.gov.tw +mx981.com +myactimes.com +my-addr.com +myaudiocast.com +myav.com.tw +my.backchina.com +myboooks.googlepages.com +mychinamyhome.com +myeclipseide.com +myforum.com.hk +myforum.com.uk +myfreshnet.com +my.keso.cn +myopenid.com +my.opera.com +mypaper.pchome.com.tw +myparagliding.com +mypopescu.com +my-proxy.com +myshare.url.com.tw +mysinablog.com +myspace.com +myvlog.im.tv +naacoalition.org +naitik.net +nakido.com +namsisi.com +nanyang.com +nanyangpost.com +nanzao.com +naol.ca +national-lottery.co.uk +navicat.com +navigeaters.com +navy.mil +nccwatch.org.tw +ncdr.nat.gov.tw +nch.com.tw +ncn.org +ncree.gov.tw +nde.de +ndr.de +nekoslovakia.net +nerch.gov.tw +ner.gov.tw +nerhl.gov.tw +nertt.gov.tw +netcolony.com +netflix.com +netme.cc +networkedblogs.com +neverforget8964.org +new-3lunch.net +new-akiba.com +newcenturymc.com +newcenturynews.com +newchen.com +newgrounds.com +newlandmagazine.com.au +news100.com.tw +newsancai.com +news.atebits.com +news.backchina.com +news.bbc.co.uk +newscn.org +news.cnyes.com +newsforums.bbc.co.uk +news.ghostery.com +news.google.com.hk +newsminer.com +news.msn.com.tw +news.omy.sg +news.pchome.com.tw +newspeak.cc +newspp.org +news.sina.com.hk +news.sina.com.tw +news.singtao.ca +newstapa.org +newtaiwan.com.tw +newtalk.tw +newyorktimes.com +nexton-net.jp +nexttv.com.tw +nf.id.au +nga.mil +ngensis.com +nhri.gov.tw +nic.cz.cc +nici.nat.gov.tw +nicovideo.tw +nict.gov.tw +nighost.org +nintendium.com +nintendowifi.net +njactb.org +njuice.com +nlfreevpn.com +nmh.gov.tw +nmmba.gov.tw +nmp.gov.tw +nmtl.gov.tw +nmvttc.gov.tw +nobelprize.org +nobel.se +nobodycanstop.us +nokogiri.org +nokola.com +noobbox.com +notes.alexdong.com +novelasia.com +nownews.com +nowtorrents.com +noypf.com +npa.go.jp +npm.gov.tw +nps.gov +nrk.no +nsc.gov.tw +nspo.gov.tw +nstm.gov.tw +ntdmh.gov.tw +ntdtv.ca +ntdtv.co +ntdtv.com +ntdtv.org +ntdtv.ru +ntl.gov.tw +ntsec.gov.tw +ntuh.gov.tw +nuexpo.com +nurgo-software.com +nuvid.com +nuzcom.com +nvquan.org +nvri.gov.tw +nydus.ca +nysingtao.com +nytco.com +nyt.com +nytimes.com +nytimg.com +nzchinese.net.nz +observechina.net +oclp.hk +october-review.org +offbeatchina.com +ogaoga.org +oikos.com.tw +oiktv.com +oizoblog.com +okayfreedom.com +old-cat.net +old.nabble.com +olumpo.com +olympicwatch.org +omgili.com +omnitalk.com +on.cc +one.xthost.info +onlylady.cn +onmoon.com +onmoon.net +oopsforum.com +ooyala.com +open.com.hk +opendemocracy.net +openid.net +openleaks.org +openvpn.net +openvpn.org +openwebster.com +opml.radiotime.com +opnir.com +orientaldaily.com.my +orient-doll.com +orn.jp +orzistic.org +osfoora.com +ourdearamy.com +oursogo.com +oursteps.com.au +overlapr.com +owl.li +ow.ly +oyax.com +ozchinese.com +ozyoyo.com +pabp.gov.tw +pacificpoker.com +packages.debian.org +packetix.net +page2rss.com +page.bid.yahoo.com +pagodabox.com +paint.net +palacemoon.com +pandora.com +pandora.tv +panluan.net +panoramio.com +pao-pao.net +paperb.us +paper.li +paper-replika.com +parade.com +parislemon.com +pastebin.com +pastie.org +patehr.gov.tw +pbs.org +pbwiki.com +pbworks.com +pbxes.com +pbxes.org +pcdiscuss.com +pcdvd.com.tw +pchome.com.tw +pct.org.tw +pcworld.com +pdetails.com +pdproxy.com +peacefire.org +peacehall.com +peeasian.com +peerpong.com +pekingduck.org +penchinese.com +penchinese.net +pengyulong.com +penthouse.com +peopo.org +percy.in +perfectgirls.net +perfectvpn.net +perfspot.com +perlhowto.com +pet.gov.tw +philly.com +photofocus.com +photos.dailyme.com +photo.utom.us +phuquocservices.com +picasaweb.google.com +picidae.net +picturesocial.com +pictures.playboy.com +pidown.com +pign.net +pimg.tw +pin6.com +ping.fm +pinoy-n.com +pioneer-worker.forums-free.com +piring.com +pixanalytics.com +pixelqi.com +pixfs.net +pixnet.cc +pixnet.net +pixplug.in +pk.com +placemix.com +planetsuzy.org +playboy.com +plays.com.tw +plm.org.hk +plunder.com +plurk.com +plurktop.mmdays.com +plus28.com +plusbb.com +pmates.com +po2b.com +podictionary.com +pokerstars.com +politicalchina.org +popvote.hk +popyard.com +popyard.org +porn2.com +pornbase.org +porn.com +pornhub.com +pornmm.net +pornoxo.com +pornrapidshare.com +pornstarclub.com +porntube.com +pornvisit.com +portis21.spaces.live.com +pose.com +postadult.com +post.anyu.org +posterous.com +post.ly +powerapple.com +power.com +powercx.com +prayforchina.net +premeforwindows7.com +presentationzen.com +president.gov.tw +prestige-av.com +previewshots.com +privacybox.de +privateinternetaccess.com +privatepaste.com +privatetunnel.com +procopytips.com +program-think.spaces.live.com +prosiben.de +provideocoalition.com +proxifier.com +proxomitron.info +proxy.org +proxypy.net +proxyroad.com +prozz.net +psblog.name +psiphon.ca +psiphon.civisec.org +pts.org.tw +ptt.cc +pubu.com.tw +puffinbrowser.com +puffstore.com +pullfolio.com +pulse.yahoo.com +pure18.com +pureconcepts.net +purepdf.com +purevpn.com +putlocker.com +puttycm.free.fr +pwned.com +python.com +python.com.tw +qanote.com +qidian.ca +qienkuen.org +qi-gong.me +qiwen.lu +qixianglu.cn +qkshare.com +qoos.com +qq.co.za +qstatus.com +qtrac.eu +qtweeter.com +quadedge.com +qusi8.net +qvodzy.org +qxbbs.org +radicalparty.org +radioaustralia.net.au +radiovaticana.org +radiovncr.com +raidcall.com.tw +rangzen.org +ranyunfei.com +rapbull.net +rapidshare8.com +rapidsharedata.com +rayfme.com +rcinet.ca +rconversation.blogs.com +rdio.com +read100.com +readingtimes.com.tw +readmoo.com +realraptalk.com +recordhistory.org +redchinacn.org +redtube.com +referer.us +reflectivecode.com +relaxbbs.com +renminbao.com +renyurenquan.org +retweeteffect.com +retweetist.com +retweetrank.com +revleft.com +revsci.net +revver.com +rfachina.com +rfamobile.org +rfa.org +rferl.org +rfi.fr +rhcloud.com +riku.me +rileyguide.com +rlwlw.com +rmjdw.com +rnw.nl +robtex.com +robustnessiskey.com +rocmp.org +rojo.com +ronjoneswriter.com +roodo.com +rotten.com +rsf-chinese.org +rsf.org +rssmeme.com +rthk.hk +rthk.org.hk +rti.org.tw +ruanyifeng.com +rushbee.com +rutube.ru +ruyiseek.com +rxhj.net +s1heng.com +s8forum.com +sacom.hk +sadpanda.us +saiq.me +salvation.org.hk +samair.ru +sammyjs.org +samsoff.es +sandnoble.com +sankaizok.com +sanmin.com.tw +sapikachu.net +savemedia.com +savetibet.de +savetibet.fr +savetibet.nl +savetibet.org +savetibet.ru +savevid.com +say2.info +scanscout.com +scmpchinese.com +scmp.com +scorecardresearch.com +scribd.com +scriptspot.com +seapuff.com +secretchina.com +secretgarden.no +secure.wikimedia.org +securitykiss.com +seesmic.com +seevpn.com +seezone.net +sejie.com +sendoid.com +sendspace.com +sesawe.net +sesawe.org +sethwklein.net +sevenload.com +sex-11.com +sex3.com +sex8.cc +sexandsubmission.com +sex.com +sexhuang.com +sexhu.com +sexinsex.net +sfileydy.com +shadow.ma +shadowsocks.org +shahamat-english.com +shangfang.org +shapeservices.com +sharebee.com +sharecool.org +share.ovi.com +share.skype.com +share.youthwant.com.tw +sharkdolphin.com +sharpdaily.com.hk +sharpdaily.hk +shaunthesheep.com +sheikyermami.com +shellmix.com +shenshou.org +shenyunperformingarts.org +shenzhoufilm.com +shifeike.blog125.fc2blog.net +shinychan.com +shitaotv.org +shixiao.org +shizhao.org +shkspr.mobi +shodanhq.com +shopping.com +showbiz.omy.sg +showtime.jp +shwchurch3.com +sidelinesnews.com +sidelinessportseatery.com +simplecd.me +simplecd.org +simpleproductivityblog.com +sina.com.tw +singtao.com +singularitys.spaces.live.com +sinoants.com +sinocast.com +sinocism.com +sino-monthly.com +sinomontreal.ca +sinonet.ca +sinopitt.info +sinoquebec.com +sis001.com +sis001.us +sis.xxx +site90.net +sitebro.tw +siteks.uk.to +site.locql.com +sitemaps.org +sites.google.com +sitetag.us +siyi123123123.spaces.live.com +skimtube.com +skybet.com +skyvegas.com +slacker.com +slavasoft.com +slheng.com +slickvpn.com +slideshare.net +slinkset.com +slutload.com +smhric.org +snapchat.com +snaptu.com +sndcdn.com +sneakme.net +snooper.co.uk +sobees.com +socialwhale.com +sockslist.net +so.com +sod.co.jp +softether.co.jp +softether-download.com +softether.org +softwarebychuck.com +so-ga.net +sogclub.com +sogou.com +sogrady.me +sohcradio.com +sohfrance.org +soh.tw +sokamonline.com +solozorro.tk +somee.com +so-news.com +songjianjun.com +sonidodelaesperanza.org +sopcast.com +sopcast.org +sorting-algorithms.com +soso.com +soumo.info +soundcloud.com +soundofhope.kr +soundofhope.org +soupofmedia.com +sourceforge.net +southnews.com.tw +sowers.org.hk +space-scape.com +spankwire.com +spb.com +speckleapp.com +speedpluss.org +spencertipping.com +spinejs.com +sports.williamhill.com +spotify.com +sproutcore.com +squarespace.com +srcf.ucam.org +ssh91.com +sshtunnel.googlecode.com +sstatic.net +stag.gov.tw +standupfortibet.org +starp2p.com +startpage.com +statcounter.com +state168.com +static.apple.nextmedia.com +static.digg.com +staticflickr.com +static.nownews.com +static.soup.io +static.typepad.com +status.twhirl.org +stdtime.gov.tw +steel-storm.com +sthoo.com +stickam.com +stickeraction.com +stonegames.net +stoneip.info +stoptibetcrisis.net +storagenewsletter.com +stoweboyd.com +streamingthe.net +strongvpn.com +student.tw +stuffimreading.com +stuffimreading.net +stupidvideos.com +subacme.rerouted.org +sublexical.spaces.live.com +sufeng.org +sugarsync.com +summify.com +sun1911.com +suoluo.org +surfeasy.com.au +svwind.com +sweux.com +swift-tools.net +s.xiaod.in +sydneytoday.com +sylfoundation.org +syncback.com +sysadmin1138.net +sysresccd.org +sytes.net +szbbs.net +szetowah.org.hk +t35.com +t66y.com +taa-usa.org +tabtter.jp +tacem.org +tafaward.com +tagwalk.com +taipei.gov.tw +taipeisociety.org +taitung-house.gov.tw +taiwandaily.net +taiwankiss.com +taiwannation.50webs.com +taiwannation.com +taiwannation.com.tw +taiwannews.com.tw +taiwan-sex.com +taiwantt.org.tw +taiwanus.net +taiwanyes.com +taiwanyes.ning.com +tamiaode.tk +tanc.org +tangben.com +taolun.info +taoyuan.gov.tw +tap11.com +target.com +taweet.com +tax.nat.gov.tw +tbpic.info +tbsec.org +tbsn.org +tbsseattle.org +tchb.gov.tw +tchrd.org +t.co +tcsac.gov.tw +teamseesmic.com +teashark.com +techlifeweb.com +techparaiso.com +telecomspace.com +telegraph.co.uk +tenacy.com +thbstc.gov.tw +theampfactory.com +theappleblog.com +theatrum-belli.com +thebcomplex.com +theblemish.com +thebodyshop-usa.com +thechinabeat.org +thedailywh.at +thedieline.com +thedw.us +thegatesnotes.com +thehots.info +thehousenews.com +thehungrydudes.com +thehun.net +theinternetwishlist.com +thelifeyoucansave.com +thelius.org +thepiratebay.org +thepiratebay.se +theqii.info +thereallove.kr +thesartorialist.com +thespeeder.com +the-sun.on.cc +thetibetpost.com +thetrotskymovie.com +thevivekspot.com +thewgo.org +thisav.com +thisiswhyyouarefat.com +thkphoto.com +thomasbernhard.org +threatchaos.com +throughnightsfire.com +t.huhaitai.com +thumbzilla.com +thywords.com +tiananmenmother.org +tiananmenuniv.com +tiananmenuniv.net +tiandixing.org +tianhuayuan.com +tiantibooks.org +tianzhu.org +tibetalk.com +tibetanyouthcongress.org +tibet.at +tibet.com +tibetcorps.org +tibetfund.org +tibetjustice.org +tibet.net +tibetoffice.org +tibetonline.com +tibetonline.tv +tibet.org.tw +tibetsun.com +tibetwrites.org +tidyread.com +time.com +times.hinet.net +tinychat.com +tinypaste.com +tinypng.com +tistory.com +tjholowaychuk.com +tkcs-collins.com +tkforum.tk +t.kun.im +tmagazine.com +tmi.me +tnaflix.com +tncsec.gov.tw +t.neolee.cn +togetter.com +tokyo-247.com +tokyocn.com +tokyo-hot.com +tomayko.com +tomsc.com +tono-oka.jp +tonyyan.net +toodoc.com +toonel.net +topic.youthwant.com.tw +topnews.in +topshare.us +topshareware.com +topstyle4.com +topsy.com +tora.to +tor.blingblingsquad.net +torproject.org +torrentcrazy.com +torrentproject.se +tor.updatestar.com +torvpn.com +t.orzdream.com +tosh.comedycentral.com +touch99.com +toutfr.com +tpde.aide.gov.tw +tphcc.gov.tw +tpi.org.tw +transgressionism.org +transparency.org +travelinlocal.com +trendsmap.com +trialofccp.org +tripod.com +trouw.nl +trtc.com.tw +trt.net.tr +trulyergonomic.com +trustedbi.com +truth101.co.tv +truthcn.com +truveo.com +tsctv.net +tsemtulku.com +tsquare.tv +tsunagarumon.com +tt1069.com +tttan.com +tuanzt.com +tube8.com +tubecao.com +tube.com +tubewolf.com +tuidang.net +tuidang.org +tui.orzdream.com +tuite.googlecode.com +tumblr.awflasher.com +tumblweed.org +tumutanzi.com +tunein.com +tunnelbear.com +turbobit.net +turbotwitter.com +turningtorso.com +turntable.fm +tuxtraining.com +tvants.com +tvboxnow.com +tv.com +tvider.com +tv-intros.com +tv.on.cc +tvunetworks.com +twapperkeeper.com +twa.sh +twaud.io +twbbs.net.tw +twbbs.org +twbbs.tw +twblogger.com +tweepguide.com +tweeplike.me +tweepmag.com +tweepml.org +tweetbackup.com +tweetboard.com +tweetboner.biz +tweetdeck.com +tweetedtimes.com +tweetmeme.com +tweetmylast.fm +tweetphoto.com +tweetrans.com +tweetree.com +tweetwally.com +tweetymail.com +twftp.org +twibase.com +twibble.de +twibbon.com +twibs.com +twicsy.com +twifan.com +twiffo.com +twiggit.org +twilog.org +twimbow.com +twimg.com +twimg.edgesuite.net +tw.img.nextmedia.com +twindexx.com +twipple.jp +twistar.cc +twisternow.com +twistory.net +twit2d.com +twitbrowser.net +twitcause.com +twitese.spaces.live.com +twitgether.com +twitgoo.com +twitiq.com +twitlonger.com +twitoaster.com +twitonmsn.com +twitpic.com +twitreferral.com +twitstat.com +twittbot.net +twitter4j.org +twitter.com +twittercounter.com +twitterfeed.com +twittergadget.com +twitter.jp +twitterkr.com +twittermail.com +twittertim.es +twitthat.com +twitturk.com +twitturly.com +twitvid.com +twitzap.com +twiyia.com +tw.jiepang.com +tw.myblog.yahoo.com +tw.news.yahoo.com +tw-npo.org +tw.rd.yahoo.com +twreg.info +twstar.net +tw.streetvoice.com +twt.fm +twtkr.com +twtr2src.ogaoga.org +twtrland.com +twt.tl +twttr.com +twurl.nl +tw.voa.mobi +twyac.org +tw.yahoo.com +tycool.com +tynsoe.org +typepad.com +tzangms.com +ub0.cc +uberproxy.net +ucdc1998.org +uderzo.it +udn.com +ufreevpn.com +ugo.com +uhrp.org +uighurbiz.net +ukliferadio.co.uk +ulike.net +ultravpn.fr +ultraxs.com +unblock.cn.com +unblocksit.es +uncyclomedia.org +uncyclopedia.info +uncyclopedia.tw +unholyknight.com +uni.cc +unicode.org +uniteddaily.com.my +unix100.com +unknownspace.org +unpo.org +uocn.org +upcoming.yahoo.com +update.playstation.net +upload4u.info +upload.backchina.com +uploaded.to +uploadstation.com +upload.wikimedia.org +urlborg.com +urlparser.com +usacn.com +usfk.mil +usinfo.state.gov +usmc.mil +us.to +ustream.tv +usus.cc +uushare.com +uwants.com +uwants.net +uyghurcongress.org +uygur.org +v70.us +vaayoo.com +value-domain.com +van698.com +vanemu.cn +vanilla-jp.com +vansky.com +vapurl.com +vatn.org +vcfbuilder.org +vcf-online.org +veempiire.com +velkaepocha.sk +venbbs.com +venchina.com +ventureswell.com +veoh.com +verizon.net +verybs.com +vevo.com +vft.com.tw +vghks.gov.tw +vghtc.gov.tw +vghtpe.gov.tw +video.aol.ca +video.aol.com +video.aol.co.uk +video.ap.org +videobam.com +video.fdbox.com +video.foxbusiness.com +videomo.com +video.tiscali.it +video.yahoo.com +vidoemo.com +views.fm +viki.com +vimeocdn.com +vimeo.com +vimgolf.com +vimperator.org +vincnd.com +vinniev.com +vllcs.org +vlog.xuite.net +vmixcore.com +voacantonese.com +voachineseblog.com +voachinese.com +voagd.com +voanews.com +voatibetan.com +vocn.tv +vot.org +vpnbook.com +vpnfire.com +vpngate.jp +vpngate.net +vpnpop.com +vpnpronet.com +v-state.org +vtunnel.com +w3schools.com +waffle1999.com +wahas.com +waigaobu.com +waikeung.org +waiwaier.com +wallornot.org +wallpapercasa.com +wanderinghorse.net +wanfang.gov.tw +wangafu.net +wangjinbo.org +wanglixiong.com +wangruoshui.net +wangyi64.spaces.live.com +want-daily.com +wapedia.mobi +washeng.net +watchmygf.net +wattpad.com +wdf5.com +wearn.com +web2project.net +webbang.net +webfee.tk +weblagu.com +webmproject.org +webshots.com +websitepulse.com +webs-tv.net +webworkerdaily.com +weeewooo.net +weekmag.info +wefong.com +weiboleak.com +weigegebyc.dreamhosters.com +weijingsheng.org +weiming.info +weiquanwang.org +weisuo.ws +wellplacedpixels.com +wengewang.com +wengewang.org +wenhui.ch +wenku.com +wenxuecity.com +wenyunchao.com +wenyunchao.spaces.live.com +wepn.info +westca.com +westernwolves.com +wetplace.com +wetpussygames.com +wexiaobo.org +wezhiyong.org +wezone.net +wforum.com +whatblocked.com +whereiswerner.com +whippedass.com +whitebear.freebearblog.org +whydidyoubuymethat.com +whylover.com +whyx.org +w.idaiwan.com +wiki.cnitter.com +wiki.jqueryui.com +wiki.keso.cn +wikileaks.ch +wikileaks.de +wikileaks.eu +wikileaks.lu +wikileaks.org +wikileaks.pl +wikilivres.info +wikimapia.org +wikimedia.org.mo +wiki.moegirl.org +wikinet.org +wiki.oauth.net +wikipedia.org +wiki.phonegap.com +wikiwiki.jp +wikkii.com +williamlong.spaces.live.com +willw.net +windowsphoneme.com +winwhispers.info +wiredbytes.com +wiredpen.com +wireshark.org +wisevid.com +witnessleeteaching.com +witopia.net +wlx.sowiki.net +woeser.com +wolfax.com +womenbusiness.nyc.gov.tw +womensrightsofchina.org +woopie.jp +woopie.tv +wordboner.com +wordpress.com +wordsandturds.com +w.org +workatruna.com +worldcat.org +worldjournal.com +worstthingieverate.com +wo.tc +wowlegacy.ml +wow-life.net +woxinghuiguo.com +wozy.in +wp.com +wpoforum.com +wqlhw.com +wqyd.org +wrchina.org +wretch.cc +writer.zoho.com +wsj.com +wsj.net +wtfpeople.com +wuala.com +wuerkaixi.com +wufi.org.tw +wuguoguang.com +wujieliulan.com +wujie.net +wukangrui.net +wwitv.com +www.6v6dota.com +www.ajsands.com +www.antd.org +www.aolnews.com +www.bulbous.freeserve.co.uk +www.cmoinc.org +www.dfanning.com +www.dwheeler.com +www.eulam.com +www.exblog.jp +www.forum4hk.com +www.freetibet.org +www.getyouram.com +www.goldenmelody.com.tw +www.idlcoyote.com +www.immigration.gov.tw +www.klip.me +www.kodingen.com +www.linksalpha.com +www.loiclemeur.com +www.macrovpn.com +www.monlamit.org +www.moztw.org +www.mycould.com +www.ned.org +www.nownews.com +www.orchidbbs.com +www.owind.com +www.oxid.it +www.parkansky.com +www.powerpointninja.com +www.rnw.nl +www.somee.com +www.stackfile.com +www.supertweet.net +www.tiffanyarment.com +www.tripod.com +www.tv.com +www.twtrland.com +www.typepad.com +www.urbanoutfitters.com +www.vegorpedersen.com +www.voy.com +www.vpncup.com +www.wangruowang.org +www.wan-press.org +www.wet123.com +www.zaurus.org.uk +wzyboy.im +x1949x.com +x365x.com +xanga.com +x-art.com +xa.yimg.com +xbabe.com +xbookcn.com +xcafe.in +xcritic.com +xfm.pp.ru +xgmyd.com +xh4n.cn +xhamster.com +xiaochuncnjp.com +xiaohexie.com +xiaoma.org +xiezhua.com +xing.com +xinhuanet.org +xinmiao.com.hk +xinqimeng.over-blog.com +xinsheng.net +xinshijue.com +xinyubbs.net +xizang-zhiye.org +xjp.cc +xml-training-guide.com +xmovies.com +xmusic.fm +xnxx.com +xpdo.net +xpud.org +xskywalker.com +xtube.com +xuchao.net +xuchao.org +xuzhiyong.net +xuzhuoer.com +xvedios.com +xvideos.com +x-wall.org +xxbbx.com +x.xcity.jp +xxxx.com.au +xysblogs.org +xys.dxiong.com +xys.org +xyy69.com +xyy69.info +yahoo.cn +yahoo.com.hk +yam.com +yanghengjun.spaces.live.com +yasni.co.uk +yasukuni.or.jp +yatsen.gov.tw +ydy.com +yeelou.com +yeeyi.com +yegle.net +yezimary.spaces.live.com +yfrog.com +yhcw.net +yidio.com +yilubbs.com +yi.org +yipub.com +ym.backchina.com +yogichen.org +yong.hu +yorkbbs.ca +youdao.com +youjizz.com +youmaker.com +youpai.org +youporn.com +your-freedom.net +yousendit.com +youthbao.com +youthnetradio.org +youtu.be +youtubecn.com +youtube.com +youtube-nocookie.com +youversion.com +youxu.info +ytht.net +ytimg.com +yuanming.net +yuming.flnet.org +yunchao.net +yvesgeleyn.com +yvtc.gov.tw +yx51.net +yyii.org +yymaya.com +yzzk.com +zacebook.com +zannel.com +zaobao.com +zaobao.com.sg +zaozon.com +zarias.com +zattoo.com +zdnet.com.tw +zengjinyan.org +zengjinyan.spaces.live.com +zeutch.com +zgzcjj.net +zhanbin.net +zhao.jinhai.de +zhenghui.org +zhenlibu.info +zhinengluyou.com +zhllg.spaces.live.com +zh.m.wikipedia.org +zh.netlog.com +zhonggtuotese.net +zhongguotese.net +zhongmeng.org +zhongsou.com +zh.pokerstrategy.com +zhreader.com +zh-tw.justin.tv +zhuichaguoji.org +zh.uncyclopedia.wikia.com +zh.wikinews.org +zh.wikipedia.org +zh.wikisource.org +ziddu.com +zillionk.com +zinio.com +ziplib.com +zkaip.com +zmw.cn +zomobo.net +zonaeuropa.com +zootool.com +zoozle.net +zozotown.com +zshare.net +zsrhao.com +zuo.la +zuola.com +zvereff.com +zyzc9.com +zyzg.us \ No newline at end of file diff --git a/package/lean/luci-app-v2ray/root/etc/v2ray/gen-gfwlist.sh b/package/lean/luci-app-v2ray/root/etc/v2ray/gen-gfwlist.sh new file mode 100755 index 000000000..d1a40ed7c --- /dev/null +++ b/package/lean/luci-app-v2ray/root/etc/v2ray/gen-gfwlist.sh @@ -0,0 +1,29 @@ +#!/bin/sh -e + +generate_china_banned() +{ + if [ ! -f /tmp/gfwlist.txt ]; then + wget-ssl --no-check-certificate https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt -O /tmp/gfwlist.b64 >&2 + cat /tmp/gfwlist.b64 | base64 -d > /tmp/gfwlist.txt + rm -f /tmp/gfwlist.b64 + fi + + cat /tmp/gfwlist.txt | sort -u | + sed 's#!.\+##; s#|##g; s#@##g; s#http:\/\/##; s#https:\/\/##;' | + sed '/\*/d; /apple\.com/d; /sina\.cn/d; /sina\.com\.cn/d; /baidu\.com/d; /byr\.cn/d; /jlike\.com/d; /weibo\.com/d; /zhongsou\.com/d; /youdao\.com/d; /sogou\.com/d; /so\.com/d; /soso\.com/d; /aliyun\.com/d; /taobao\.com/d; /jd\.com/d; /qq\.com/d' | + sed '/^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$/d' | + grep '^[0-9a-zA-Z\.-]\+$' | grep '\.' | sed 's#^\.\+##' | sort -u | + awk ' +BEGIN { prev = "________"; } { + cur = $0; + if (index(cur, prev) == 1 && substr(cur, 1 + length(prev) ,1) == ".") { + } else { + print cur; + prev = cur; + } +}' | sort -u + +} + + +generate_china_banned diff --git a/package/lean/luci-app-v2ray/root/etc/v2ray/gen_config.lua b/package/lean/luci-app-v2ray/root/etc/v2ray/gen_config.lua new file mode 100644 index 000000000..b5300b26c --- /dev/null +++ b/package/lean/luci-app-v2ray/root/etc/v2ray/gen_config.lua @@ -0,0 +1,169 @@ +--[[ + Auto generate config for Project V + Author: @libc0607 +]]-- + +local conf_path, json_path = ... +conf_path = conf_path or "v2ray" +json_path = json_path or "/etc/v2ray/config.json" + +local local_listen_port = 7070 + +local cjson = require "cjson.safe" +local ucursor = require "luci.model.uci".cursor() +local lip = require "luci.ip" + +local v2ray_stream_mode = ucursor:get(conf_path, "v2ray", "network_type") -- tcp/kcp/ws + +function v2ray_get_conf_list(op) + local t = {} + for k, v in pairs(ucursor:get_list(conf_path, 'v2ray', op)) do + table.insert(t, v) + end + return t +end + +function check_addr_type(addr) + local ip = luci.ip.new(addr, 32) + if ip == nil then + return "domain" + elseif ip:is4() then + return "ipv4" + elseif ip:is6() then + return "ipv6" + end +end + +function get_ip_list_by_domain(domain) + local domain_list = {} + local cmd = io.popen("nslookup " .. domain .. " |grep Address | awk {'print $3'}") + for cmd_line in cmd:lines() do + if check_addr_type(cmd_line) == "ipv4" then + table.insert(domain_list, cmd_line) + elseif check_addr_type(cmd_line) == "ipv6" then + table.insert(domain_list, cmd_line) + end + end + return domain_list +end + +local v2ray = { + log = { + access = "", + error = "", + loglevel = "none" + }, + inbound = { + protocol = "dokodemo-door", + port = local_listen_port, + domainOverride = {"tls", "http"}, + address = "", + settings = { + network = "tcp,udp", + timeout = 30, + followRedirect = true + }, + }, + outbound = { + protocol = "vmess", + settings = { + vnext = { + [1] = { + address = ucursor:get(conf_path, "v2ray", "address"), + port = tonumber(ucursor:get(conf_path, "v2ray", "port")), + users = { + [1] = { + id = ucursor:get(conf_path, "v2ray", "id"), + alterId = tonumber(ucursor:get(conf_path, "v2ray", "alterId")), + security = ucursor:get(conf_path, "v2ray", "security") + }, + }, + }, + }, + }, + streamSettings = { + network = ucursor:get(conf_path, "v2ray", "network_type"), + security = (ucursor:get(conf_path, "v2ray", "tls") == '1') and "tls" or "none", + tcpSettings = (v2ray_stream_mode == "tcp" and ucursor:get(conf_path, "v2ray", "tcp_obfs") == "http") and { + connectionReuse = true, + header = { + type = ucursor:get(conf_path, "v2ray", "tcp_obfs"), + request = { + version = "1.1", + method = "GET", + path = v2ray_get_conf_list('tcp_path'), + headers = { + Host = v2ray_get_conf_list('tcp_host'), + User_Agent = { + "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36", + "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/53.0.2785.109 Mobile/14A456 Safari/601.1.46" + }, + Accept_Encoding = {"gzip, deflate"}, + Connection = {"keep-alive"}, + Pragma = "no-cache" + }, + }, + response = { + version = "1.1", + status = "200", + reason = "OK", + headers = { + Content_Type = {"application/octet-stream","video/mpeg"}, + Transfer_Encoding = {"chunked"}, + Connection= {"keep-alive"}, + Pragma = "no-cache" + }, + }, + } + } or nil, + + kcpSettings = (v2ray_stream_mode == "kcp") and { + mtu = tonumber(ucursor:get(conf_path, "v2ray", "kcp_mtu")), + tti = tonumber(ucursor:get(conf_path, "v2ray", "kcp_tti")), + uplinkCapacity = tonumber(ucursor:get(conf_path, "v2ray", "kcp_uplink")), + downlinkCapacity = tonumber(ucursor:get(conf_path, "v2ray", "kcp_downlink")), + congestion = (ucursor:get(conf_path, "v2ray", "kcp_congestion") == "1") and true or false, + readBufferSize = tonumber(ucursor:get(conf_path, "v2ray", "kcp_readbuf")), + writeBufferSize = tonumber(ucursor:get(conf_path, "v2ray", "kcp_writebuf")), + header = { + type = ucursor:get(conf_path, "v2ray", "kcp_obfs") + } + } or nil, + + wsSettings = (v2ray_stream_mode == "ws") and { + connectionReuse = true, + path = ucursor:get(conf_path, "v2ray", "ws_path"), + headers = (ucursor:get(conf_path, "v2ray", "ws_headers") ~= nil) and { + Host = ucursor:get(conf_path, "v2ray", "ws_headers") + } or nil, + } or nil, + }, + mux = { + enabled = (ucursor:get(conf_path, "v2ray", "mux") == "1") and true or false + }, + }, + dns = { + servers = { + "localhost" + }, + }, +} + +-- Generate config json to +local json_raw = cjson.encode(v2ray) +local json_file = io.open(json_path, "w+") +io.output(json_file) +io.write(json_raw) +io.close(json_file) + +-- change '_' to '-' +local keys_including_minus = {"User_Agent", "Content_Type", "Accept_Encoding", "Transfer_Encoding"} +local keys_corrected = {"User-Agent", "Content-Type", "Accept-Encoding", "Transfer-Encoding"} +for k, v in pairs(keys_including_minus) do + os.execute("sed -i 's/" ..v.. "/" ..keys_corrected[k].. "/g' " .. json_path) +end + +-- change "\/" to "/" +os.execute("sed -i 's/\\\\\\//\\//g' ".. json_path) + +print("V2ray config generated at " .. json_path) diff --git a/package/lean/luci-app-v2ray/root/etc/v2ray/up-gfwlist.sh b/package/lean/luci-app-v2ray/root/etc/v2ray/up-gfwlist.sh new file mode 100755 index 000000000..3e7ee5083 --- /dev/null +++ b/package/lean/luci-app-v2ray/root/etc/v2ray/up-gfwlist.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +/etc/v2ray/gen-gfwlist.sh > /tmp/ol-gfw.txt + +if [ -s "/tmp/ol-gfw.txt" ];then + sort -u /etc/v2ray/base-gfwlist.txt /tmp/ol-gfw.txt > /tmp/china-banned + if ( ! cmp -s /tmp/china-banned /etc/gfwlist/china-banned );then + if [ -s "/tmp/china-banned" ];then + mv /tmp/china-banned /etc/gfwlist/china-banned + echo "Update GFW-List Done!" + fi + else + echo "GFW-List No Change!" + fi +fi + +rm -f /tmp/gfwlist.txt +rm -f /tmp/ol-gfw.txt + +/etc/init.d/v2raypro restart diff --git a/package/lean/luci-app-v2ray/root/etc/v2ray/v2ray-watchdog b/package/lean/luci-app-v2ray/root/etc/v2ray/v2ray-watchdog new file mode 100755 index 000000000..671a24b01 --- /dev/null +++ b/package/lean/luci-app-v2ray/root/etc/v2ray/v2ray-watchdog @@ -0,0 +1,26 @@ +#!/bin/sh + +LOGTIME=$(date "+%Y-%m-%d %H:%M:%S") +#GOOGLE=$(ping -4 www.gstatic.com -c 1 -w 5| sed '1{s/[^(]*(//;s/).*//;q}') + +#iptables -t nat -I OUTPUT -p tcp -d $GOOGLE -j REDIRECT --to-port 7070 + +#sleep 3 + +/usr/bin/wget --spider --quiet --tries=1 --timeout=3 www.gstatic.com/generate_204 + +if [ "$?" == "0" ]; then + echo '['$LOGTIME'] V2Ray No Problem.' +else + /usr/bin/wget --spider --quiet --tries=1 --timeout=3 www.baidu.com + if [ "$?" == "0" ]; then + echo '['$LOGTIME'] Problem decteted, restarting V2Ray...' + /etc/init.d/v2raypro restart + else + echo '['$LOGTIME'] Network Problem. Do nothing.' + fi +fi + +#sleep 3 + +#iptables -t nat -D OUTPUT -p tcp -d $GOOGLE -j REDIRECT --to-port 7070 diff --git a/package/lean/mentohust/Makefile b/package/lean/mentohust/Makefile new file mode 100644 index 000000000..7b294ce8b --- /dev/null +++ b/package/lean/mentohust/Makefile @@ -0,0 +1,71 @@ +# +# Copyright (C) 2006-2011 Xmlad.com +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=mentohust +PKG_VERSION:=4.0 +PKG_RELEASE:=1 +PKG_REV=857f5a1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-r$(PKG_REV).tar.bz2 +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_PROTO:=git +PKG_SOURCE_VERSION:=$(PKG_REV) +PKG_SOURCE_URL:=https://github.com/hyrathb/mentohust.git + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/mentohust + SECTION:=net + CATEGORY:=Network + DEPENDS:=+libpcap + TITLE:=An CERNET client daemon + URL:=https://github.com/hyrathb/mentohust + SUBMENU:=CERNET +endef + +define Package/mentohust/description +An CERNET client daemon, +Most usually used in China collages. +endef + +define Build/Prepare + $(call Build/Prepare/Default) + # $(SED) 's/dhclient/udhcpc -i/g' $(PKG_BUILD_DIR)/src/myconfig.c +endef + +define Build/Configure + cd $(PKG_BUILD_DIR) && sh ./autogen.sh + $(call Build/Configure/Default) +endef + +CONFIGURE_ARGS += \ + --disable-encodepass \ + --disable-notify + +# XXX: CFLAGS are already set by Build/Compile/Default +MAKE_FLAGS+= \ + OFLAGS="" + +define Package/mentohust/conffiles +/etc/mentohust.conf +endef + +define Package/mentohust/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/mentohust $(1)/usr/sbin/ + chmod 755 $(1)/usr/sbin/ + $(INSTALL_DIR) $(1)/etc + $(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/mentohust.conf $(1)/etc/mentohust.conf.template +endef + +$(eval $(call BuildPackage,mentohust)) diff --git a/package/lean/minieap/Makefile b/package/lean/minieap/Makefile new file mode 100644 index 000000000..b50135b27 --- /dev/null +++ b/package/lean/minieap/Makefile @@ -0,0 +1,54 @@ +# +# Copyright (C) 2006-2011 Xmlad.com +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=minieap +PKG_VERSION:=0.9 +PKG_RELEASE:=2 +PKG_REV=71742ef + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-r$(PKG_REV).tar.bz2 +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_PROTO:=git +PKG_SOURCE_VERSION:=$(PKG_REV) +PKG_SOURCE_URL:=https://github.com/updateing/minieap.git + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/minieap + SECTION:=net + CATEGORY:=Network + DEPENDS:=+libpcap + TITLE:=Extendable 802.1x client + URL:=https://github.com/updateing/minieap + SUBMENU:=CERNET +endef + +define Package/minieap/description +Extendable 802.1x client +endef + +define Build/Prepare + $(call Build/Prepare/Default) +endef + +define Build/Install + true +endef + +define Package/minieap/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/minieap $(1)/usr/sbin/ + chmod 755 $(1)/usr/sbin/ +endef + +$(eval $(call BuildPackage,minieap)) diff --git a/package/lean/oscam/Config.in b/package/lean/oscam/Config.in deleted file mode 100644 index 2a23f71c6..000000000 --- a/package/lean/oscam/Config.in +++ /dev/null @@ -1,240 +0,0 @@ -menu "OSCam build options" - depends on PACKAGE_oscam - - -config OSCAM_USE_LIBCRYPTO - bool "Build with OpenSSL libcrypto" - help - "Use OpenSSL libcrypto instead of OSCam internal crypto functions" - default n - -config OSCAM_USE_LIBUSB - bool "Build with libusb" - default n - - - menu "Protocols" - depends on PACKAGE_oscam - - config OSCAM_MODULE_CAMD33 - bool "camd 3.3" - default n - - config OSCAM_MODULE_CAMD35 - bool "camd 3.5 UDP" - default n - - config OSCAM_MODULE_CAMD35_TCP - bool "camd 3.5 TCP" - default n - - config OSCAM_MODULE_NEWCAMD - bool "newcamd" - default n - - config OSCAM_MODULE_CCCAM - bool "CCcam" - default n - - config OSCAM_MODULE_CCCSHARE - bool "CCcam share" - default n - - config OSCAM_MODULE_GBOX - bool "gbox" - default n - - config OSCAM_MODULE_RADEGAST - bool "radegast" - default n - - config OSCAM_MODULE_SERIAL - bool "Serial" - default n - - config OSCAM_MODULE_CONSTCW - bool "constant CW" - default n - - config OSCAM_MODULE_PANDORA - bool "Pandora" - default n - - config OSCAM_MODULE_GHTTP - bool "Ghttp" - default n - - config OSCAM_MODULE_SCAM - bool "scam" - default n - - endmenu - - menu "Readers" - depends on PACKAGE_oscam - - config OSCAM_READER_NAGRA - bool "Nagravision" - default n - - config OSCAM_READER_IRDETO - bool "Irdeto" - default n - - config OSCAM_READER_CONAX - bool "Conax" - default n - - config OSCAM_READER_CRYPTOWORKS - bool "Cryptoworks" - default n - - config OSCAM_READER_SECA - bool "Seca" - default n - - config OSCAM_READER_VIACCESS - bool "Viaccess" - default n - - config OSCAM_READER_VIDEOGUARD - bool "NDS Videoguard" - default n - - config OSCAM_READER_DRE - bool "DRE Crypt" - default n - - config OSCAM_READER_TONGFANG - bool "Tongfang" - default n - - config OSCAM_READER_BULCRYPT - bool "Bulcrypt" - default n - - config OSCAM_READER_GRIFFIN - bool "Griffin" - default n - - config OSCAM_READER_DGCRYPT - bool "DGCrypt" - default n - - endmenu - - menu "Card readers" - depends on PACKAGE_oscam - - config OSCAM_USE_PCSC - bool "PCSC" - select OSCAM_USE_LIBUSB - default n - - config OSCAM_CARDREADER_PHOENIX - bool "Phoenix/mouse" - select OSCAM_USE_LIBUSB - default n - - config OSCAM_CARDREADER_SC8IN1 - bool "SC8in1" - select OSCAM_USE_LIBUSB - default n - - config OSCAM_CARDREADER_MP35 - bool "AD-Teknik MP 3.6/USB Phoenix" - select OSCAM_USE_LIBUSB - default n - - config OSCAM_CARDREADER_SMARGO - bool "Argolis Smargo Smartreader" - select OSCAM_USE_LIBUSB - default n - - config OSCAM_CARDREADER_STINGER - bool "STINGER" - select OSCAM_USE_LIBUSB - default n - - endmenu - -comment "Addons" -config OSCAM_HAVE_DVBAPI - bool "DVB API" - default y - -config OSCAM_READ_SDT_CHARSETS - bool "DVB API read-sdt charsets" - default y - -config OSCAM_IRDETO_GUESSING - bool "Irdeto guessing" - default n - -config OSCAM_CS_ANTICASC - bool "Anti cascading" - default y - -config OSCAM_WITH_DEBUG - bool "Debug messages" - default n - -config OSCAM_MODULE_MONITOR - bool "Monitor" - default n - -config OSCAM_WITH_LB - bool "Loadbalancing" - default y - -config OSCAM_S_CACHEEX - bool "Cache exchange" - default y - -config OSCAM_CW_CYCLE_CHECK - bool "CW Cycle Check" - default y - -config OSCAM_LCDSUPPORT - bool "LCD support" - default n - -config OSCAM_LEDSUPPORT - bool "LED support" - default n - -config OSCAM_CLOCKFIX - bool "Clockfix (disable on old systems!)" - default y - -config OSCAM_IPV6SUPPORT - bool "IPv6 support (experimental)" - default n - - -config OSCAM_WEBIF - bool "Web Interface" - default n - - config OSCAM_WEBIF_LIVELOG - bool "LiveLog" - depends on OSCAM_WEBIF - default n - - config OSCAM_WEBIF_JQUERY - bool "Jquery onboard (if disabled webload)" - depends on OSCAM_WEBIF - default n - - config OSCAM_TOUCH - bool "Touch Web Interface" - depends on OSCAM_WEBIF - default n - - config OSCAM_WITH_SSL - bool "SSL support" - depends on OSCAM_WEBIF - select OSCAM_USE_LIBCRYPTO - default n - -endmenu diff --git a/package/lean/oscam/Makefile b/package/lean/oscam/Makefile deleted file mode 100644 index 15b795244..000000000 --- a/package/lean/oscam/Makefile +++ /dev/null @@ -1,204 +0,0 @@ -# -# Copyright (C) 2016 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# -# $Id$ - -include $(TOPDIR)/rules.mk - -PKG_NAME:=oscam -PKG_VERSION:=1.20-$(PKG_REV) -PKG_RELEASE:=1 -PKG_REV:=2780c48789c8e1427df4078ea9b06e0b51594bbc - - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_VERSION:=$(PKG_REV) -PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) -PKG_SOURCE_URL:=https://github.com/coolsnowwolf/oscam.git -PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.bz2 -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) - -PKG_LICENSE:=GPLv3 -PKG_LICENSE_FILES:=COPYING -PKG_MAINTAINER:=tmn505 - -PKG_CONFIG_DEPENDS := \ - OSCAM_USE_LIBCRYPTO \ - OSCAM_USE_LIBUSB \ - OSCAM_USE_PCSC \ - OSCAM_WEBIF \ - OSCAM_WEBIF_LIVELOG \ - OSCAM_WEBIF_JQUERY \ - OSCAM_TOUCH \ - OSCAM_WITH_SSL \ - OSCAM_HAVE_DVBAPI \ - OSCAM_READ_SDT_CHARSETS \ - OSCAM_IRDETO_GUESSING \ - OSCAM_CS_ANTICASC \ - OSCAM_WITH_DEBUG \ - OSCAM_MODULE_MONITOR \ - OSCAM_WITH_LB \ - OSCAM_CS_CACHEEX \ - OSCAM_CW_CYCLE_CHECK \ - OSCAM_LCDSUPPORT \ - OSCAM_LEDSUPPORT \ - OSCAM_CLOCKFIX \ - OSCAM_IPV6SUPPORT \ - OSCAM_MODULE_CAMD33 \ - OSCAM_MODULE_CAMD35 \ - OSCAM_MODULE_CAMD35_TCP \ - OSCAM_MODULE_NEWCAMD \ - OSCAM_MODULE_CCCAM \ - OSCAM_MODULE_CCCSHARE \ - OSCAM_MODULE_GBOX \ - OSCAM_MODULE_RADEGAST \ - OSCAM_MODULE_SCAM \ - OSCAM_MODULE_SERIAL \ - OSCAM_MODULE_CONSTCW \ - OSCAM_MODULE_PANDORA \ - OSCAM_MODULE_GHTTP \ - OSCAM_READER_NAGRA \ - OSCAM_READER_IRDETO \ - OSCAM_READER_CONAX \ - OSCAM_READER_CRYPTOWORKS \ - OSCAM_READER_SECA \ - OSCAM_READER_VIACCESS \ - OSCAM_READER_VIDEOGUARD \ - OSCAM_READER_DRE \ - OSCAM_READER_TONGFANG \ - OSCAM_READER_BULCRYPT \ - OSCAM_READER_GRIFFIN \ - OSCAM_READER_DGCRYPT \ - OSCAM_CARDREADER_PHOENIX \ - OSCAM_CARDREADER_SC8IN1 \ - OSCAM_CARDREADER_MP35 \ - OSCAM_CARDREADER_SMARGO \ - OSCAM_CARDREADER_STINGER - -include $(INCLUDE_DIR)/package.mk - -define Package/oscam/config - source "$(SOURCE)/Config.in" -endef - -config_files=oscam.ac oscam.cacheex oscam.cert oscam.conf oscam.dvbapi oscam.guess oscam.ird oscam.provid oscam.server oscam.services oscam.srvid oscam.tiers oscam.user oscam.whitelist - -define Package/oscam/conffiles -/etc/oscam/ -endef - -define Package/oscam - SECTION:=net - CATEGORY:=Network - TITLE:=Open Source Conditional Access Modul - URL:=http://www.streamboard.tv/oscam - DEPENDS:=+OSCAM_USE_LIBCRYPTO:libopenssl +OSCAM_USE_LIBUSB:libusb-1.0 +OSCAM_USE_PCSC:pcscd -endef - -define Package/list-smargo - $(call Package/oscam) - TITLE:=List smargo readers - DEPENDS:=oscam -endef - -CONFIGURE_CMD = ./config.sh -CONFIGURE_ARGS = \ - --restore \ - $(if $(CONFIG_OSCAM_WEBIF),--enable,--disable) WEBIF \ - $(if $(CONFIG_OSCAM_WEBIF_LIVELOG),--enable,--disable) WEBIF_LIVELOG \ - $(if $(CONFIG_OSCAM_WEBIF_JQUERY),--enable,--disable) WEBIF_JQUERY \ - $(if $(CONFIG_OSCAM_TOUCH),--enable,--disable) TOUCH \ - $(if $(CONFIG_OSCAM_WITH_SSL),--enable,--disable) WITH_SSL \ - $(if $(CONFIG_OSCAM_HAVE_DVBAPI),--enable,--disable) HAVE_DVBAPI \ - $(if $(CONFIG_OSCAM_READ_SDT_CHARSETS),--enable,--disable) READ_SDT_CHARSETS \ - $(if $(CONFIG_OSCAM_IRDETO_GUESSING),--enable,--disable) IRDETO_GUESSING \ - $(if $(CONFIG_OSCAM_CS_ANTICASC),--enable,--disable) CS_ANTICASC \ - $(if $(CONFIG_OSCAM_WITH_DEBUG),--enable,--disable) WITH_DEBUG \ - $(if $(CONFIG_OSCAM_MODULE_MONITOR),--enable,--disable) MODULE_MONITOR \ - $(if $(CONFIG_OSCAM_WITH_LB),--enable,--disable) WITH_LB \ - $(if $(CONFIG_OSCAM_CS_CACHEEX),--enable,--disable) CS_CACHEEX \ - $(if $(CONFIG_OSCAM_CW_CYCLE_CHECK),--enable,--disable) CW_CYCLE_CHECK \ - $(if $(CONFIG_OSCAM_LCDSUPPORT),--enable,--disable) LCDSUPPORT \ - $(if $(CONFIG_OSCAM_LEDSUPPORT),--enable,--disable) LEDSUPPORT \ - $(if $(CONFIG_OSCAM_CLOCKFIX),--enable,--disable) CLOCKFIX \ - $(if $(CONFIG_OSCAM_IPV6SUPPORT),--enable,--disable) IPV6SUPPORT \ - $(if $(CONFIG_OSCAM_MODULE_CAMD33),--enable,--disable) MODULE_CAMD33 \ - $(if $(CONFIG_OSCAM_MODULE_CAMD35),--enable,--disable) MODULE_CAMD35 \ - $(if $(CONFIG_OSCAM_MODULE_CAMD35_TCP),--enable,--disable) MODULE_CAMD35_TCP \ - $(if $(CONFIG_OSCAM_MODULE_NEWCAMD),--enable,--disable) MODULE_NEWCAMD \ - $(if $(CONFIG_OSCAM_MODULE_CCCAM),--enable,--disable) MODULE_CCCAM \ - $(if $(CONFIG_OSCAM_MODULE_CCCSHARE),--enable,--disable) MODULE_CCCSHARE \ - $(if $(CONFIG_OSCAM_MODULE_GBOX),--enable,--disable) MODULE_GBOX \ - $(if $(CONFIG_OSCAM_MODULE_RADEGAST),--enable,--disable) MODULE_RADEGAST \ - $(if $(CONFIG_OSCAM_MODULE_SCAM),--enable,--disable) MODULE_SCAM \ - $(if $(CONFIG_OSCAM_MODULE_SERIAL),--enable,--disable) MODULE_SERIAL \ - $(if $(CONFIG_OSCAM_MODULE_CONSTCW),--enable,--disable) MODULE_CONSTCW \ - $(if $(CONFIG_OSCAM_MODULE_PANDORA),--enable,--disable) MODULE_PANDORA \ - $(if $(CONFIG_OSCAM_MODULE_GHTTP),--enable,--disable) MODULE_GHTTP \ - $(if $(CONFIG_OSCAM_READER_NAGRA),--enable,--disable) READER_NAGRA \ - $(if $(CONFIG_OSCAM_READER_IRDETO),--enable,--disable) READER_IRDETO \ - $(if $(CONFIG_OSCAM_READER_CONAX),--enable,--disable) READER_CONAX \ - $(if $(CONFIG_OSCAM_READER_CRYPTOWORKS),--enable,--disable) READER_CRYPTOWORKS \ - $(if $(CONFIG_OSCAM_READER_SECA),--enable,--disable) READER_SECA \ - $(if $(CONFIG_OSCAM_READER_VIACCESS),--enable,--disable) READER_VIACCESS \ - $(if $(CONFIG_OSCAM_READER_VIDEOGUARD),--enable,--disable) READER_VIDEOGUARD \ - $(if $(CONFIG_OSCAM_READER_DRE),--enable,--disable) READER_DRE \ - $(if $(CONFIG_OSCAM_READER_TONGFANG),--enable,--disable) READER_TONGFANG \ - $(if $(CONFIG_OSCAM_READER_BULCRYPT),--enable,--disable) READER_BULCRYPT \ - $(if $(CONFIG_OSCAM_READER_GRIFFIN),--enable,--disable) READER_GRIFFIN \ - $(if $(CONFIG_OSCAM_READER_DGCRYPT),--enable,--disable) READER_DGCRYPT \ - $(if $(CONFIG_OSCAM_CARDREADER_PHOENIX),--enable,--disable) CARDREADER_PHOENIX \ - $(if $(CONFIG_OSCAM_CARDREADER_SC8IN1),--enable,--disable) CARDREADER_SC8IN1 \ - $(if $(CONFIG_OSCAM_CARDREADER_MP35),--enable,--disable) CARDREADER_MP35 \ - $(if $(CONFIG_OSCAM_CARDREADER_SMARGO),--enable,--disable) CARDREADER_SMARGO \ - $(if $(CONFIG_OSCAM_CARDREADER_STINGER),--enable,--disable) CARDREADER_STINGER \ - --disable CARDREADER_INTERNAL_AZBOX \ - --disable CARDREADER_INTERNAL_COOLAPI \ - --disable CARDREADER_INTERNAL_COOLAPI2 \ - --disable CARDREADER_INTERNAL_SCI \ - --disable CARDREADER_DB2COM \ - --disable CARDREADER_STAPI \ - --disable CARDREADER_STAPI5 - -MAKE_FLAGS += - -ifeq ($(CONFIG_OSCAM_USE_LIBUSB),y) - MAKE_FLAGS += USE_LIBUSB=1 -endif - -ifeq ($(CONFIG_OSCAM_USE_PCSC),y) - MAKE_FLAGS += USE_PCSC=1 -endif - -ifeq ($(CONFIG_OSCAM_USE_LIBCRYPTO),y) - MAKE_FLAGS += USE_LIBCRYPTO=1 -endif - -ifeq ($(CONFIG_OSCAM_WITH_SSL),y) - MAKE_FLAGS += USE_SSL=1 -endif - -MAKE_FLAGS += CONF_DIR=/etc/oscam -MAKE_FLAGS += OSCAM_BIN=Distribution/oscam -MAKE_FLAGS += LIST_SMARGO_BIN=Distribution/list-smargo - - -define Package/oscam/install - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/Distribution/oscam $(1)/usr/sbin/oscam - $(INSTALL_DIR) $(1)/etc/oscam - $(INSTALL_DATA) $(addprefix $(PKG_BUILD_DIR)/Distribution/doc/example/,$(config_files)) $(1)/etc/oscam/ - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./files/oscam.init $(1)/etc/init.d/oscam -endef - -define Package/list-smargo/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/Distribution/list-smargo $(1)/usr/bin/list-smargo -endef - -$(eval $(call BuildPackage,oscam)) -$(eval $(call BuildPackage,list-smargo)) diff --git a/package/lean/oscam/files/oscam.init b/package/lean/oscam/files/oscam.init deleted file mode 100644 index b0bf41dc5..000000000 --- a/package/lean/oscam/files/oscam.init +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2016 OpenWrt.org - -START=50 -USE_PROCD=1 - -start_service() { - procd_open_instance - procd_set_param command /usr/sbin/oscam - procd_set_param respawn - procd_close_instance -} diff --git a/package/lean/samba4x/Makefile b/package/lean/samba4x/Makefile new file mode 100644 index 000000000..86489bf85 --- /dev/null +++ b/package/lean/samba4x/Makefile @@ -0,0 +1,283 @@ +# +# Copyright (C) 2007-2015 wongsyrone +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=samba4x +PKG_VERSION:=4.4.2 +PKG_RELEASE:=1 + +PKG_SOURCE_URL:= \ + http://download.samba.org/pub/samba/stable \ + http://ftp.samba.org/pub/samba \ + http://ftp.samba.org/pub/samba/old-versions + +PKG_SOURCE:=samba-$(PKG_VERSION).tar.gz +PKG_BUILD_DIR:=$(BUILD_DIR)/samba-$(PKG_VERSION) +PKG_MD5SUM:=03a65a3adf08ceb1636ad59d234d7f9d + +PKG_LICENSE:=GPLv3 +PKG_LICENSE_FILES:=COPYING + +PKG_BUILD_DEPENDS:=heimdal + +PKG_BUILD_PARALLEL:=1 +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk +# for "uname release type" check +include $(INCLUDE_DIR)/kernel.mk + + +define Package/samba4x-server + SECTION:=net + CATEGORY:=Network + TITLE:=Samba $(PKG_VERSION) SMB/CIFS server + URL:=http://www.samba.org/ + DEPENDS:=+zlib +libpthread +libpopt +libcap +python-light +#DEPENDS+= +libreadline +libuuid +libtirpc libtirpc +endef + +define Package/samba4x-server/description + The Samba software suite is a collection of programs that implements the + SMB protocol for UNIX systems, allowing you to serve files and printers to + Windows, NT, OS/2 and DOS clients. This protocol is sometimes also referred + to as the LanManager or Netbios protocol. +endef + + +# fix include "dbwrap/dbwrap_open.h" not found in auth/credentials/credentials_secrets.c -I$(PKG_BUILD_DIR)/source3/lib +EXTRA_CFLAGS += \ + -ffunction-sections -fdata-sections \ + -Wno-deprecated-declarations +EXTRA_LDFLAGS += -Wl,--gc-sections + +# Use host compiled python2 as interpreter +# Use target python2-config to retrive cflags, ldflags, libs, etc. +# Must have python2 patched to make python2-config works + +# _python_sysroot="$(STAGING_DIR)" \ + _python_prefix="/usr" \ + _python_exec_prefix="/usr/bin" \ + PYTHON="$(STAGING_DIR_HOST)/bin/python2" + +CONFIGURE_VARS += \ + PYTHON_CONFIG="$(STAGING_DIR)/usr/bin/python2-config" \ + python_LDFLAGS="" \ + python_LIBDIR="" + +# XXX: Be sure to take care of commas(,) or you will get 'out of range' error when waf configuring settings. +SAMBA4_IDMAP_MODULES_SHARED := idmap_ad,idmap_rid,idmap_adex,idmap_hash,idmap_tdb2, +SAMBA4_IDMAP_MODULES_STATIC := +SAMBA4_PDB_MODULES_SHARED := pdb_wbc_sam,pdb_samba4, +SAMBA4_PDB_MODULES_STATIC := pdb_smbpasswd,pdb_tdbsam, +SAMBA4_AUTH_MODULES_SHARED := auth_wbc,auth_script,auth_samba4 +SAMBA4_AUTH_MODULES_STATIC := auth_sam,auth_unix, +SAMBA4_VFS_MODULES_STATIC := vfs_default,vfs_aio_pthread + + +SAMBA4_MODULES_SHARED = "${SAMBA4_IDMAP_MODULES_SHARED}${SAMBA4_PDB_MODULES_SHARED}${SAMBA4_AUTH_MODULES_SHARED}" +SAMBA4_MODULES_STATIC = "${SAMBA4_IDMAP_MODULES_STATIC}${SAMBA4_PDB_MODULES_STATIC}${SAMBA4_AUTH_MODULES_STATIC}${SAMBA4_VFS_MODULES_STATIC}" + +# Taken from package-defaults.mk +SAMBA_CONFIGURE_ARGS += \ + --target=$(GNU_TARGET_NAME) \ + --program-prefix="" \ + --prefix=$(CONFIGURE_PREFIX) \ + --exec-prefix=$(CONFIGURE_PREFIX) \ + --bindir=$(CONFIGURE_PREFIX)/bin \ + --sbindir=$(CONFIGURE_PREFIX)/sbin \ + --libexecdir=$(CONFIGURE_PREFIX)/lib \ + --sysconfdir=/etc \ + --datadir=$(CONFIGURE_PREFIX)/share \ + --localstatedir=/var \ + --mandir=$(CONFIGURE_PREFIX)/man \ + --infodir=$(CONFIGURE_PREFIX)/info + +# Should have a look before compiling. +SAMBA43_CACHE := " \ + \nChecking simple C program: OK \ + \nrpath library support: OK \ + \n-Wl,--version-script support: OK \ + \nChecking getconf LFS_CFLAGS: NO \ + \nChecking for large file support without additional flags: OK \ + \nChecking for -D_LARGE_FILES: OK \ + \nChecking correct behavior of strtoll: NO \ + \nChecking for working strptime: OK \ + \nChecking for C99 vsnprintf: OK \ + \nChecking for HAVE_SHARED_MMAP: OK \ + \nChecking for HAVE_MREMAP: OK \ + \nChecking for HAVE_INCOHERENT_MMAP: NO \ + \nChecking for HAVE_SECURE_MKSTEMP: OK \ + \nChecking for HAVE_IFACE_GETIFADDRS: OK \ + \nChecking for kernel change notify support: OK \ + \nChecking for Linux kernel oplocks: OK \ + \nChecking for kernel share modes: OK \ + \nChecking if can we convert from CP850 to UCS-2LE: OK \ + \nChecking if can we convert from UTF-8 to UCS-2LE: OK \ + \nChecking whether we can use Linux thread-specific credentials with 32-bit system calls: OK \ + \nChecking whether we can use Linux thread-specific credentials: OK \ + \nChecking whether setreuid is available: OK \ + \nChecking whether setresuid is available: OK \ + \nChecking whether seteuid is available: OK \ + \nChecking whether fcntl locking is available: OK \ + \nChecking whether the realpath function allows a NULL argument: OK \ + \nChecking whether POSIX capabilities are available: OK \ + \nChecking for the maximum value of the 'time_t' type: NO \ + \nChecking for ftruncate extend: OK \ + \nvfs_fileid checking for statfs() and struct statfs.f_fsid: OK \ + \ngetcwd takes a NULL argument: OK \ + \nChecking value of NSIG: \"65\" \ + \nChecking value of _NSIG: \"65\" \ + \nChecking value of SIGRTMAX: \"64\" \ + \nChecking value of SIGRTMIN: \"34\" \ + \n" +# \nChecking for the maximum value of the 'time_t' type: OK <<-- check it, not for sure. It seems musl-libc don't have max time_t + +# do the renaming trick +define Build/Prepare + $(call Build/Prepare/Default) + $(SED) 's#__OPENWRT_SAMBA_MULTICALL__#$(PKG_NAME)_multicall#g' $(PKG_BUILD_DIR)/source3/wscript_build + $(CP) ./files/python2-config "$(STAGING_DIR)/usr/bin/python2-config" +endef + +define Build/Configure + (cd $(PKG_BUILD_DIR); \ + echo -e >cache.txt $(SAMBA43_CACHE) " \ + \nChecking uname release type: \"$(LINUX_VERSION)\" \ + \nChecking uname machine type: \"$(ARCH)\" \ + \nChecking uname version type: \"#1 Tue Nov 1 12:34:56 UTC 2013\" \ + \nChecking uname sysname type: \"Linux\" \ + \n" ; \ + $(CONFIGURE_VARS) \ + ./buildtools/bin/waf configure -j$(shell nproc) \ + --cross-compile \ + --cross-answers=$(PKG_BUILD_DIR)/cache.txt \ + --hostcc="$(HOSTCC)" \ + $(SAMBA_CONFIGURE_ARGS) \ + --with-lockdir=/var/lock \ + --with-logfilebase=/var/log \ + --with-piddir=/var/run \ + --with-privatedir=/etc/samba \ + --enable-fhs \ + --without-dmapi \ + --disable-glusterfs \ + --disable-rpath \ + --disable-rpath-install \ + --disable-avahi \ + --disable-cups \ + --disable-iprint \ + --disable-gnutls \ + --with-relro \ + --with-sendfile-support \ + --without-acl-support \ + --without-ads \ + --without-ad-dc \ + --without-automount \ + --without-cluster-support \ + --without-dnsupdate \ + --without-fam \ + --without-gettext \ + --without-iconv \ + --without-ldap \ + --without-pam \ + --without-pie \ + --without-regedit \ + --without-systemd \ + --without-utmp \ + --without-winbind \ + --enable-auto-reconfigure \ + --nonshared-binary=$(PKG_NAME)_multicall \ + --with-static-modules=${SAMBA4_MODULES_STATIC} \ + --with-shared-modules=${SAMBA4_MODULES_SHARED} \ + --bundled-libraries='heimdal,!asn1_compile,!compile_et,!zlib,popt,talloc,pytalloc,pytalloc-util' \ + --without-quotas \ + --with-syslog \ + --nopyc \ + --nopyo \ + ) +endef +# leftovers of samba 4.0: --with-shared-modules=pdb_tdbsam,pdb_wbc_sam,idmap_nss,nss_info_template,auth_wbc +# simple file server: --bundled-libraries=NONE --builtin-libraries=NONE +# --bundled-libraries=ALL ---> do not find libs from system, use integrated libs +# '--nonshared-binary' works like '--disable-shared-libs' in samba 4.0.26 +# or use '--builtin-libraries' to specify which library to build into. +# --nonshared-binary=smbd/smbd,nmbd/nmbd,smbpasswd,smbcontrol,smbtree,smbstatus,smbcquotas,smbcacls,nmblookup,testparm,$(PKG_NAME)_multicall + +# 'builtin-libraries' +# smbd_base samba-util tdb talloc param pdb +# seems don't need: krb5samba + +# Some important options: +# +# --with-static-modules=STATIC_MODULES +# Comma-separated list of names of modules to statically link in +# --with-shared-modules=SHARED_MODULES +# Comma-separated list of names of modules to build shared +# --private-libraries=PRIVATE_LIBS +# comma separated list of normally public libraries to build instead as private libraries. May include !LIBNAME to disable making a library private. Can be 'NONE' or 'ALL' [auto] +# --builtin-libraries=BUILTIN_LIBRARIES +# command separated list of libraries to build directly into binaries [NONE] +# --nonshared-binary=NONSHARED_BINARIES +# Disable use of shared libs for the listed binaries +# + +# Disable some libs +# --without-libtdb \ bld.SAMBA_LIBRARY('tdb', +# --without-libtalloc \ +# --without-libnetapi \ bld.SAMBA3_LIBRARY('netapi', +# --without-libsmbclient \ +# --without-libsmbsharemodes \ +# + +# speed up +# $(shell nproc) +define Build/Compile + (cd $(PKG_BUILD_DIR); \ + ./buildtools/bin/waf build \ + --targets=$(PKG_NAME)_multicall \ + -j$(shell nproc) \ + ) +endef + +# Do NOT run 'make install' since we only need the multicall binary +define Build/Install + $(RSTRIP) $(PKG_BUILD_DIR)/bin/default/source3/$(PKG_NAME)_multicall +endef + +# XXX: Make sure the name of multicall binary matches name in 111-multicall-wscript-build.patch +define Package/samba4x-server/install + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_DATA) ./files/$(PKG_NAME).config $(1)/etc/config/samba4 + $(INSTALL_DIR) $(1)/etc/samba + $(INSTALL_DATA) ./files/smb.conf.template $(1)/etc/samba + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/$(PKG_NAME).init $(1)/etc/init.d/samba4 + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/bin/default/source3/$(PKG_NAME)_multicall $(1)/usr/sbin + $(LN) $(PKG_NAME)_multicall $(1)/usr/sbin/smbd + $(LN) $(PKG_NAME)_multicall $(1)/usr/sbin/nmbd + $(LN) $(PKG_NAME)_multicall $(1)/usr/sbin/smbpasswd + $(LN) $(PKG_NAME)_multicall $(1)/usr/sbin/pdbedit + $(INSTALL_DIR) $(1)/usr/bin + $(LN) ../sbin/$(PKG_NAME)_multicall $(1)/usr/bin/smbcontrol + $(LN) ../sbin/$(PKG_NAME)_multicall $(1)/usr/bin/smbtree + $(LN) ../sbin/$(PKG_NAME)_multicall $(1)/usr/bin/smbstatus + $(LN) ../sbin/$(PKG_NAME)_multicall $(1)/usr/bin/smbcquotas + $(LN) ../sbin/$(PKG_NAME)_multicall $(1)/usr/bin/smbcacls + $(LN) ../sbin/$(PKG_NAME)_multicall $(1)/usr/bin/nmblookup + $(LN) ../sbin/$(PKG_NAME)_multicall $(1)/usr/bin/testparm +endef + +define Package/samba4x-server/conffiles +/etc/config/samba4 +/etc/samba/smb.conf.template +/etc/samba/smbpasswd +endef + + +$(eval $(call BuildPackage,$(PKG_NAME)-server)) diff --git a/package/lean/samba4x/files/python2-config b/package/lean/samba4x/files/python2-config new file mode 100755 index 000000000..f86cbe052 --- /dev/null +++ b/package/lean/samba4x/files/python2-config @@ -0,0 +1,26 @@ +#!/bin/sh +# /tree-lede/staging_dir/target-powerpc_464fp_musl-1.1.15/usr/bin/python2-config +BASEDIR=$(cd `dirname $0`;cd ..;pwd) +case "$1" in +--prefix) + echo $BASEDIR +;; +--exec-prefix) + echo $BASEDIR +;; +--includes) + echo -I$BASEDIR/include/python2.7 -I$BASEDIR/include/python2.7 +;; +--libs) + echo -lpython2.7 -lpthread -ldl -lutil -lm +;; +--cflags) + echo -I$BASEDIR/include/python2.7 -I$BASEDIR/include/python2.7 +;; +--ldflags) + echo -lpython2.7 -lpthread -ldl -lutil -lm -Xlinker -export-dynamic +;; +*) + echo 'Usage: python2-config [--prefix|--exec-prefix|--includes|--libs|--cflags|--ldflags|--help]' +;; +esac diff --git a/package/lean/samba4x/files/samba4x.config b/package/lean/samba4x/files/samba4x.config new file mode 100644 index 000000000..eaaf1a50e --- /dev/null +++ b/package/lean/samba4x/files/samba4x.config @@ -0,0 +1,7 @@ +config samba + option 'enabled' '0' + option 'name' 'OpenWrt-SMB' + option 'workgroup' 'WORKGROUP' + option 'description' 'Samba on OpenWrt' + option 'charset' 'UTF-8' + option 'homes' '1' diff --git a/package/lean/samba4x/files/samba4x.init b/package/lean/samba4x/files/samba4x.init new file mode 100755 index 000000000..5682a0a57 --- /dev/null +++ b/package/lean/samba4x/files/samba4x.init @@ -0,0 +1,162 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2008-2012 OpenWrt.org +# Copyright (C) 2015 wongsyrone + + +START=60 +USE_PROCD=1 + +smb_header() { + local interface + config_get interface $1 interface "loopback lan" + + # resolve interfaces + . /lib/functions/network.sh + local interfaces=$( + local net + for net in $interface; do + local device + network_get_device device "$net" && { + local subnet + network_get_subnet subnet "$net" && echo -n "$subnet " + network_get_subnet6 subnet "$net" && echo -n "$subnet " + } + + echo -n "${device:-$net} " + done + ) + + local name workgroup description charset domain + local hostname="$(uci_get system.@system[0].hostname)" + + config_get enabled $1 enabled "0" + config_get name $1 name "${hostname:-OpenWrt}" + config_get workgroup $1 workgroup "${hostname:-WORKGROUP}" + config_get description $1 description "Samba on ${hostname:-OpenWrt}" + config_get charset $1 charset "UTF-8" + config_get DISABLENB $1 disablenb "0" + + mkdir -p /var/etc + sed -e "s#|NAME|#$name#g" \ + -e "s#|WORKGROUP|#$workgroup#g" \ + -e "s#|DESCRIPTION|#$description#g" \ + -e "s#|INTERFACES|#$interfaces#g" \ + -e "s#|CHARSET|#$charset#g" \ + /etc/samba/smb.conf.template > /var/etc/smb.conf + + + [ "$DISABLENB" == "1" ] && echo >>/var/etc/smb.conf -e "\tdisable netbios = yes" + + [ -f /etc/krb5.keytab ] && { + KLIST=`klist -k /etc/krb5.keytab` + REALM=${KLIST##*@} + echo >>/var/etc/smb.conf -e "\tkerberos method = dedicated keytab" + echo >>/var/etc/smb.conf -e "\tdedicated keytab file = /etc/krb5.keytab" + echo >>/var/etc/smb.conf -e "\trealm = $REALM" + sed -i -e "s#workgroup = \(.*\)#workgroup = $REALM#g" /var/etc/smb.conf + workgroup=$REALM + } + + [ -S /var/run/ldapi ] && { + echo >>/var/etc/smb.conf -e "\tldapsam:trusted = yes" + echo >>/var/etc/smb.conf -e "\tldapsam:editposix = yes" + echo >>/var/etc/smb.conf -e "\tldap ssl = off" + echo >>/var/etc/smb.conf -e "\tdomain logons = yes" + sed -i -e "s#passdb backend = \(.*\)#passdb backend = ldapsam:ldapi:///#g" \ + /var/etc/smb.conf + } + + local homes + config_get_bool homes $1 homes 0 + [ $homes -gt 0 ] && { + cat <> /var/etc/smb.conf + +[homes] + comment = Home Directories + browseable = no + writable = yes + read only = no + create mask = 0750 +EOT + } + + [ -L /etc/samba/smb.conf ] || ln -nsf /var/etc/smb.conf /etc/samba/smb.conf +} + +smb_add_share() { + local name + local path + local users + #local public + local writable + local printable + local create_mask + local guest_ok + + config_get name $1 name + config_get path $1 path + config_get users $1 users + #config_get public $1 public + config_get writable $1 writable + config_get printable $1 printable + config_get create_mask $1 create_mask + config_get guest_ok $1 guest_ok + + [ -z "$name" -o -z "$path" ] && return + + echo -e "\n[$name]\n\tpath = $path" >> /var/etc/smb.conf + [ -n "$users" ] && echo -e "\tvalid users = $users" >> /var/etc/smb.conf + [ -n "$public" ] && echo -e "\tpublic = $public" >> /var/etc/smb.conf + [ -n "$writable" ] && echo -e "\twritable = $writable" >> /var/etc/smb.conf + [ -n "$printable" ] && echo -e "\tprintable = $printable" >> /var/etc/smb.conf + [ -n "$create_mask" ] && echo -e "\tcreate mask = $create_mask" >> /var/etc/smb.conf + [ -n "$guest_ok" ] && echo -e "\tguest ok = $guest_ok\n\tpublic = $guest_ok" >> /var/etc/smb.conf +} + + +init_config() { + # Create samba dirs + [ -d /var/lib/samba ] || mkdir -p /var/lib/samba + [ -d /var/cache/samba ] || mkdir -p /var/cache/samba + [ -d /var/run/samba ] || mkdir -p /var/run/samba + [ -d /var/lock ] || mkdir -p /var/lock + chmod 0755 /var/lock + + config_load samba4 + config_foreach smb_header samba + config_foreach smb_add_share sambashare +} + +reload_service() { + init_config + + killall -HUP smbd +} + +service_triggers() { + procd_add_reload_trigger samba4 +} + +start_service() { + init_config + + if [ "1" = "$enabled" ] || [ "on" = "$enabled" ] || [ "true" = "$enabled" ]; then + procd_open_instance + procd_set_param command /usr/sbin/smbd -F + procd_set_param respawn + procd_close_instance + # lower priority using renice in busybox + renice -n 2 $(pidof smbd) + + [ "$DISABLENB" != "1" ] && { + procd_open_instance + procd_set_param command /usr/sbin/nmbd -F + procd_set_param respawn + procd_close_instance + # lower priority using renice in busybox + renice -n 2 $(pidof nmbd) + } + else + echo "samba4 is disabled" + fi +} diff --git a/package/lean/samba4x/files/smb.conf.template b/package/lean/samba4x/files/smb.conf.template new file mode 100644 index 000000000..ccb5e757d --- /dev/null +++ b/package/lean/samba4x/files/smb.conf.template @@ -0,0 +1,42 @@ +[global] + netbios name = |NAME| + interfaces = |INTERFACES| + server string = |DESCRIPTION| + hosts allow = 192.168.1. 127. + unix charset = |CHARSET| + workgroup = |WORKGROUP| + passdb backend = smbpasswd + # passdb backend = tdbsam:/etc/samba/passdb.tdb + inherit owner = yes + create mask = 0777 + directory mask = 0777 + force create mode = 0777 + force directory mode = 0777 + security = user + smb encrypt = disabled + smb passwd file = /etc/samba/smbpasswd + lock directory = /var/lock + browseable = yes + domain master = yes + encrypt passwords = yes + enable core files = no + guest account = nobody + invalid users = root + local master = yes + load printers = no + map to guest = Bad User + os level = 20 + preferred master = yes + printable = no + writeable = yes + strict allocate = yes + strict locking = no + socket options = TCP_NODELAY IPTOS_LOWDELAY + use sendfile = yes + max xmit = 65535 + max connections = 8 + deadtime = 30 + dns proxy = no + aio read size = 0 + aio write size = 0 + diff --git a/package/lean/samba4x/patches/000-disable-libbsd.patch b/package/lean/samba4x/patches/000-disable-libbsd.patch new file mode 100644 index 000000000..3c22c4a51 --- /dev/null +++ b/package/lean/samba4x/patches/000-disable-libbsd.patch @@ -0,0 +1,25 @@ +Disable libbsd support, samba4 uses a global config.h for its own +codebase and that of heimdal (when building with builtin). +This causes redefinition conflicts for link(2) when both standard unistd.h +and bsd/unistd.h get included. + +Signed-off-by: Gustavo Zacarias + +--- a/lib/replace/wscript ++++ b/lib/replace/wscript +@@ -256,15 +256,6 @@ def configure(conf): + + conf.CHECK_FUNCS('prctl dirname basename') + +- # libbsd on some platforms provides strlcpy and strlcat +- if not conf.CHECK_FUNCS('strlcpy strlcat'): +- conf.CHECK_FUNCS_IN('strlcpy strlcat', 'bsd', headers='bsd/string.h', +- checklibc=True) +- if not conf.CHECK_FUNCS('getpeereid'): +- conf.CHECK_FUNCS_IN('getpeereid', 'bsd', headers='sys/types.h bsd/unistd.h') +- if not conf.CHECK_FUNCS_IN('setproctitle', 'setproctitle', headers='setproctitle.h'): +- conf.CHECK_FUNCS_IN('setproctitle', 'bsd', headers='sys/types.h bsd/unistd.h') +- + conf.CHECK_CODE(''' + struct ucred cred; + socklen_t cred_len; diff --git a/package/lean/samba4x/patches/004-pythogn-DEBUGLEVEL-undefined.patch b/package/lean/samba4x/patches/004-pythogn-DEBUGLEVEL-undefined.patch new file mode 100644 index 000000000..05cc378bb --- /dev/null +++ b/package/lean/samba4x/patches/004-pythogn-DEBUGLEVEL-undefined.patch @@ -0,0 +1,11 @@ +--- a/python/pyglue.c ++++ b/python/pyglue.c +@@ -112,7 +112,7 @@ static PyObject *py_set_debug_level(PyOb + unsigned level; + if (!PyArg_ParseTuple(args, "I", &level)) + return NULL; +- (DEBUGLEVEL) = level; ++// (DEBUGLEVEL) = level; + Py_RETURN_NONE; + } + diff --git a/package/lean/samba4x/patches/018-avoid-get-config-by-native-ncurses.patch b/package/lean/samba4x/patches/018-avoid-get-config-by-native-ncurses.patch new file mode 100644 index 000000000..66ac64a20 --- /dev/null +++ b/package/lean/samba4x/patches/018-avoid-get-config-by-native-ncurses.patch @@ -0,0 +1,22 @@ +waf trys to get package's configuration by native ncurses6-config. +it will make native header files and library be used. + +Signed-off-by: Bian Naimeng + +--- a/source3/wscript_configure_system_ncurses ++++ b/source3/wscript_configure_system_ncurses +@@ -2,14 +2,6 @@ import Logs, Options, sys + + Logs.info("Looking for ncurses features") + +-conf.find_program('ncurses5-config', var='NCURSES_CONFIG') +-if not conf.env.NCURSES_CONFIG: +- conf.find_program('ncurses6-config', var='NCURSES_CONFIG') +- +-if conf.env.NCURSES_CONFIG: +- conf.CHECK_CFG(path=conf.env.NCURSES_CONFIG, args="--cflags --libs", +- package="", uselib_store="NCURSES") +- + conf.CHECK_HEADERS('ncurses.h menu.h panel.h form.h', lib='ncurses') + + conf.CHECK_FUNCS_IN('initscr', 'ncurses') diff --git a/package/lean/samba4x/patches/020-splice-support.patch b/package/lean/samba4x/patches/020-splice-support.patch new file mode 100644 index 000000000..9dda8c8c0 --- /dev/null +++ b/package/lean/samba4x/patches/020-splice-support.patch @@ -0,0 +1,91 @@ +From d78eafdbd5ae00f77ce11f80ad142eb3c109278b Mon Sep 17 00:00:00 2001 +From: Lior Amsalem +Date: Mon, 2 Dec 2013 11:04:56 +0200 +Subject: [PATCH 1/4] samba 4.0.9 splice support + +Signed-off-by: Lior Amsalem +--- + source3/lib/recvfile.c | 46 ++++++++++++++++++++-------------------------- + 1 file changed, 20 insertions(+), 26 deletions(-) + +--- a/source3/lib/recvfile.c ++++ b/source3/lib/recvfile.c +@@ -43,6 +43,10 @@ + #define TRANSFER_BUF_SIZE (128*1024) + #endif + ++#define SPLICE_F_COPY 0 ++#define MAX_ITERATIONS 4 ++#define RECEIVE_BUF_SIZE 131072 ++ + static ssize_t default_sys_recvfile(int fromfd, + int tofd, + off_t offset, +@@ -158,10 +162,10 @@ ssize_t sys_recvfile(int fromfd, + off_t offset, + size_t count) + { +- static int pipefd[2] = { -1, -1 }; +- static bool try_splice_call = false; ++ static bool try_splice_call = true; + size_t total_written = 0; + loff_t splice_offset = offset; ++ size_t current_count; + + DEBUG(10,("sys_recvfile: from = %d, to = %d, " + "offset=%.0f, count = %lu\n", +@@ -186,20 +190,22 @@ ssize_t sys_recvfile(int fromfd, + count); + } + +- if ((pipefd[0] == -1) && (pipe(pipefd) == -1)) { +- try_splice_call = false; +- return default_sys_recvfile(fromfd, tofd, offset, count); +- } +- + while (count > 0) { +- int nread, to_write; ++ int nread, try_again; ++ ++ if (count > RECEIVE_BUF_SIZE){ ++ current_count=RECEIVE_BUF_SIZE; ++ } else { ++ current_count=count; ++ } ++ try_again = MAX_ITERATIONS; ++ do { ++ nread = splice(fromfd, NULL, tofd, &offset, current_count, SPLICE_F_COPY); ++ if (nread == -1) ++ try_again--; ++ } while(nread ==-1 && try_again); + +- nread = splice(fromfd, NULL, pipefd[1], NULL, +- MIN(count, 16384), SPLICE_F_MOVE); + if (nread == -1) { +- if (errno == EINTR) { +- continue; +- } + if (total_written == 0 && + (errno == EBADF || errno == EINVAL)) { + try_splice_call = false; +@@ -221,19 +227,7 @@ ssize_t sys_recvfile(int fromfd, + } + break; + } +- +- to_write = nread; +- while (to_write > 0) { +- int thistime; +- thistime = splice(pipefd[0], NULL, tofd, +- &splice_offset, to_write, +- SPLICE_F_MOVE); +- if (thistime == -1) { +- goto done; +- } +- to_write -= thistime; +- } +- ++ + total_written += nread; + count -= nread; + } diff --git a/package/lean/samba4x/patches/022-wscript.patch b/package/lean/samba4x/patches/022-wscript.patch new file mode 100644 index 000000000..b77cbd20a --- /dev/null +++ b/package/lean/samba4x/patches/022-wscript.patch @@ -0,0 +1,15 @@ +--- a/source3/wscript ++++ b/source3/wscript +@@ -68,6 +68,12 @@ def set_options(opt): + help=("Directory under which libcephfs is installed"), + action="store", dest='libcephfs_dir', default=None) + ++ opt.add_option('--program-suffix', ++ help=("Directory under which libcephfs is installed")) ++ ++ opt.add_option('--disable-nls', ++ help=("Directory under which libcephfs is installed")) ++ + opt.SAMBA3_ADD_OPTION('glusterfs', with_name="enable", without_name="disable", default=True) + + opt.add_option('--enable-vxfs', diff --git a/package/lean/samba4x/patches/023-wscript_perl_fixup.patch b/package/lean/samba4x/patches/023-wscript_perl_fixup.patch new file mode 100644 index 000000000..fb448f154 --- /dev/null +++ b/package/lean/samba4x/patches/023-wscript_perl_fixup.patch @@ -0,0 +1,26 @@ +From: Andrew Bartlett +Date: Wed, 26 Oct 2016 00:06:12 +0000 (+1300) +Subject: build: Fix build with perl on debian sid. +X-Git-Url: http://git.catalyst.net.nz/gw?p=samba.git;a=commitdiff_plain;h=edb109f6 + +build: Fix build with perl on debian sid. + +It appears that "." is no longer in perl_inc + +Signed-off-by: Andrew Bartlett +--- + +diff --git a/buildtools/wafsamba/samba_perl.py b/buildtools/wafsamba/samba_perl.py +index f2f176d..2e9a53a 100644 +--- a/buildtools/wafsamba/samba_perl.py ++++ b/buildtools/wafsamba/samba_perl.py +@@ -49,7 +49,8 @@ def SAMBA_CHECK_PERL(conf, mandatory=True, version=(5,0,0)): + conf.env.PERL_LIB_INSTALL_DIR = perl_lib_install_dir + + perl_inc = read_perl_config_var('print "@INC"') +- perl_inc.remove('.') ++ if '.' in perl_inc: ++ perl_inc.remove('.') + conf.start_msg("PERL_INC: ") + conf.end_msg("%s" % (perl_inc), 'GREEN') + conf.env.PERL_INC = perl_inc diff --git a/package/lean/samba4x/patches/110-multicall.patch b/package/lean/samba4x/patches/110-multicall.patch new file mode 100644 index 000000000..c5641b6e0 --- /dev/null +++ b/package/lean/samba4x/patches/110-multicall.patch @@ -0,0 +1,77 @@ +--- /dev/null ++++ b/source3/multicall.c +@@ -0,0 +1,74 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++extern int smbd_main(int argc, char **argv); ++extern int nmbd_main(int argc, char **argv); ++extern int smbpasswd_main(int argc, char **argv); ++extern int smbcontrol_main(int argc, char **argv); ++extern int smbtree_main(int argc, char **argv); ++extern int smbstatus_main(int argc, char **argv); ++extern int smbcquotas_main(int argc, char **argv); ++extern int smbcacls_main(int argc, char **argv); ++extern int nmblookup_main(int argc, char **argv); ++extern int testparm_main(int argc, char **argv); ++extern int pdbedit_main(int argc, char **argv); ++ ++static struct { ++ const char *name; ++ int (*func_main)(int argc, char **argv); ++} multicall[] = { ++ { "smbd", smbd_main }, ++ { "nmbd", nmbd_main }, ++ { "smbpasswd", smbpasswd_main }, ++ { "smbcontrol", smbcontrol_main }, ++ { "smbtree", smbtree_main }, ++ { "smbstatus", smbstatus_main }, ++ { "smbcquotas", smbcquotas_main }, ++ { "smbcacls", smbcacls_main }, ++ { "nmblookup", nmblookup_main }, ++ { "testparm", testparm_main }, ++ { "pdbedit", pdbedit_main }, ++}; ++ ++#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) ++ ++int main(int argc, char **argv) ++{ ++ unsigned int i, len; ++ extern char *__progname; ++ char path[PATH_MAX], *self; ++ ++ len = readlink("/proc/self/exe", path, sizeof(path)); ++ path[len] = 0; ++ for (i=len-2; i>0 && path[i] != '/'; --i); ++ self = path + i + 1; ++ ++ if (0 == strcmp(__progname, self)) { ++ if (argc == 1) goto usage; ++ argv++; ++ --argc; ++ __progname = argv[0]; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(multicall); i++) { ++ if (0 == strcmp(__progname, multicall[i].name)) { ++ return multicall[i].func_main(argc, argv); ++ } ++ } ++ ++usage: ++ fprintf(stderr, "%s multicall binary\nAvailable commands:\n\n", self); ++ for (i = 0; i < ARRAY_SIZE(multicall); i++) { ++ fprintf(stderr, "%s", multicall[i].name); ++ if (i != 0 && i != ARRAY_SIZE(multicall)-1) ++ fprintf(stderr, ", "); ++ } ++ fprintf(stderr, "\n"); ++ ++ return 1; ++} diff --git a/package/lean/samba4x/patches/111-multicall-wscript-build.patch b/package/lean/samba4x/patches/111-multicall-wscript-build.patch new file mode 100644 index 000000000..7671c5560 --- /dev/null +++ b/package/lean/samba4x/patches/111-multicall-wscript-build.patch @@ -0,0 +1,84 @@ +--- a/source3/wscript_build ++++ b/source3/wscript_build +@@ -1196,7 +1196,7 @@ bld.SAMBA3_BINARY('testparm', + param + popt_samba3''') + +-smbstatus_source = 'utils/status.c smbd/notify_msg.c' ++smbstatus_source = 'utils/status.c' + + if bld.CONFIG_GET("WITH_PROFILE"): + smbstatus_source += ' utils/status_profile.c' +@@ -1512,6 +1512,72 @@ bld.SAMBA3_BINARY('spotlight2sparql', + enabled=bld.env.with_spotlight, + install=False) + ++ ++bld.SAMBA3_SUBSYSTEM('SMBD_MULTI', ++ source='smbd/server.c', ++ cflags='-Dmain=smbd_main') ++ ++bld.SAMBA3_SUBSYSTEM('NMBD_MULTI', ++ source='nmbd/nmbd.c', ++ cflags='-Dmain=nmbd_main') ++ ++bld.SAMBA3_SUBSYSTEM('SMBPASSWD_MULTI', ++ source='utils/smbpasswd.c', ++ cflags='-Dmain=smbpasswd_main') ++ ++bld.SAMBA3_SUBSYSTEM('SMBCONTROL_MULTI', ++ source='utils/smbcontrol.c', ++ cflags='-Dmain=smbcontrol_main') ++ ++bld.SAMBA3_SUBSYSTEM('SMBTREE_MULTI', ++ source='utils/smbtree.c', ++ cflags='-Dmain=smbtree_main') ++ ++bld.SAMBA3_SUBSYSTEM('SMBSTATUS_MULTI', ++ source=smbstatus_source, ++ cflags='-Dmain=smbstatus_main') ++ ++bld.SAMBA3_SUBSYSTEM('SMBCQUOTAS_MULTI', ++ source='utils/smbcquotas.c', ++ cflags='-Dmain=smbcquotas_main') ++ ++bld.SAMBA3_SUBSYSTEM('SMBCACLS_MULTI', ++ source='utils/smbcacls.c lib/util_sd.c', ++ cflags='-Dmain=smbcacls_main') ++ ++bld.SAMBA3_SUBSYSTEM('NMBLOOKUP_MULTI', ++ source='utils/nmblookup.c', ++ cflags='-Dmain=nmblookup_main') ++ ++bld.SAMBA3_SUBSYSTEM('TESTPARM_MULTI', ++ source='utils/testparm.c', ++ cflags='-Dmain=testparm_main') ++ ++bld.SAMBA3_SUBSYSTEM('PDBEDIT_MULTI', ++ source='utils/pdbedit.c', ++ cflags='-Dmain=pdbedit_main') ++ ++bld.SAMBA3_BINARY('__OPENWRT_SAMBA_MULTICALL__', ++ source='''multicall.c smbd/smbd_cleanupd.c ++ nmbd/asyncdns.c nmbd/nmbd_become_dmb.c ++ nmbd/nmbd_become_lmb.c nmbd/nmbd_browserdb.c ++ nmbd/nmbd_browsesync.c nmbd/nmbd_elections.c ++ nmbd/nmbd_incomingdgrams.c nmbd/nmbd_incomingrequests.c ++ nmbd/nmbd_lmhosts.c nmbd/nmbd_logonnames.c nmbd/nmbd_mynames.c ++ nmbd/nmbd_namelistdb.c nmbd/nmbd_namequery.c ++ nmbd/nmbd_nameregister.c nmbd/nmbd_namerelease.c ++ nmbd/nmbd_nodestatus.c nmbd/nmbd_packets.c ++ nmbd/nmbd_processlogon.c nmbd/nmbd_responserecordsdb.c ++ nmbd/nmbd_sendannounce.c nmbd/nmbd_serverlistdb.c ++ nmbd/nmbd_subnetdb.c nmbd/nmbd_winsproxy.c nmbd/nmbd_winsserver.c ++ nmbd/nmbd_workgroupdb.c nmbd/nmbd_synclists.c''', ++ deps='''smbd_base SMBD_MULTI NMBD_MULTI SMBPASSWD_MULTI ++ SMBCONTROL_MULTI SMBTREE_MULTI SMBSTATUS_MULTI ++ SMBCQUOTAS_MULTI SMBCACLS_MULTI NMBLOOKUP_MULTI PDBEDIT_MULTI ++ PASSWD_UTIL PASSCHANGE TESTPARM_MULTI EPMD LSASD FSSD ++ param''', ++ install_path='${SBINDIR}') ++ + ########################## INCLUDES ################################# + + bld.RECURSE('auth') diff --git a/package/lean/samba4x/patches/120-add_missing_ifdef.patch b/package/lean/samba4x/patches/120-add_missing_ifdef.patch new file mode 100644 index 000000000..797374174 --- /dev/null +++ b/package/lean/samba4x/patches/120-add_missing_ifdef.patch @@ -0,0 +1,26 @@ +#--- a/source3/librpc/rpc/rpc_common.c +#+++ b/source3/librpc/rpc/rpc_common.c +#@@ -120,9 +120,11 @@ static bool initialize_interfaces(void) +# if (!smb_register_ndr_interface(&ndr_table_netdfs)) { +# return false; +# } +#+#ifdef DEVELOPER +# if (!smb_register_ndr_interface(&ndr_table_rpcecho)) { +# return false; +# } +#+#endif +# if (!smb_register_ndr_interface(&ndr_table_initshutdown)) { +# return false; +# } +--- a/source3/rpcclient/rpcclient.c ++++ b/source3/rpcclient/rpcclient.c +@@ -622,7 +622,9 @@ static struct cmd_set *rpcclient_command + netlogon_commands, + srvsvc_commands, + dfs_commands, ++#ifdef DEVELOPER + echo_commands, ++#endif + epmapper_commands, + shutdown_commands, + test_commands, diff --git a/package/lean/samba4x/patches/200-remove_printer_support.patch b/package/lean/samba4x/patches/200-remove_printer_support.patch new file mode 100644 index 000000000..4296534ec --- /dev/null +++ b/package/lean/samba4x/patches/200-remove_printer_support.patch @@ -0,0 +1,355 @@ +--- a/source3/rpc_server/rpc_service_setup.c ++++ b/source3/rpc_server/rpc_service_setup.c +@@ -553,10 +553,12 @@ bool dcesrv_ep_setup(struct tevent_conte + goto done; + } + ++#ifdef PRINTER_SUPPORT + ok = rpc_setup_spoolss(ev_ctx, msg_ctx); + if (!ok) { + goto done; + } ++#endif + + ok = rpc_setup_svcctl(ev_ctx, msg_ctx); + if (!ok) { +--- a/source3/rpcclient/rpcclient.c ++++ b/source3/rpcclient/rpcclient.c +@@ -618,7 +618,9 @@ static struct cmd_set *rpcclient_command + lsarpc_commands, + ds_commands, + samr_commands, ++#ifdef PRINTER_SUPPORT + spoolss_commands, ++#endif + netlogon_commands, + srvsvc_commands, + dfs_commands, +--- a/source3/rpc_server/svcctl/srv_svcctl_nt.c ++++ b/source3/rpc_server/svcctl/srv_svcctl_nt.c +@@ -86,9 +86,11 @@ bool init_service_op_table( void ) + + /* add builtin services */ + ++#ifdef PRINTER_SUPPORT + svcctl_ops[i].name = talloc_strdup( svcctl_ops, "Spooler" ); + svcctl_ops[i].ops = &spoolss_svc_ops; + i++; ++#endif + + svcctl_ops[i].name = talloc_strdup( svcctl_ops, "NETLOGON" ); + svcctl_ops[i].ops = &netlogon_svc_ops; +--- a/source3/printing/spoolssd.c ++++ b/source3/printing/spoolssd.c +@@ -614,6 +614,10 @@ pid_t start_spoolssd(struct tevent_conte + int ret; + bool ok; + ++#ifndef PRINTER_SUPPORT ++ return; ++#endif ++ + DEBUG(1, ("Forking SPOOLSS Daemon\n")); + + /* +--- a/source3/utils/net_rpc.c ++++ b/source3/utils/net_rpc.c +@@ -7987,6 +7987,10 @@ static int rpc_printer_publish(struct ne + {NULL, NULL, 0, NULL, NULL} + }; + ++#ifndef PRINTER_SUPPORT ++ return 0; ++#endif ++ + if (argc == 0) { + if (c->display_usage) { + d_printf(_("Usage:\n")); +--- a/source3/smbd/reply.c ++++ b/source3/smbd/reply.c +@@ -5765,7 +5765,11 @@ void reply_printopen(struct smb_request + return; + } + +- if (!CAN_PRINT(conn)) { ++ ++#ifdef PRINTER_SUPPORT ++ if (!CAN_PRINT(conn)) ++#endif ++ { + reply_nterror(req, NT_STATUS_ACCESS_DENIED); + END_PROFILE(SMBsplopen); + return; +@@ -5871,7 +5875,10 @@ void reply_printqueue(struct smb_request + is really quite gross and only worked when there was only + one printer - I think we should now only accept it if they + get it right (tridge) */ +- if (!CAN_PRINT(conn)) { ++#ifdef PRINTER_SUPPORT ++ if (!CAN_PRINT(conn)) ++#endif ++ { + reply_nterror(req, NT_STATUS_ACCESS_DENIED); + END_PROFILE(SMBsplretq); + return; +--- a/source3/smbd/lanman.c ++++ b/source3/smbd/lanman.c +@@ -784,6 +784,10 @@ static bool api_DosPrintQGetInfo(struct + union spoolss_JobInfo *job_info = NULL; + union spoolss_PrinterInfo printer_info; + ++#ifndef PRINTER_SUPPORT ++ return False; ++#endif ++ + if (!str1 || !str2 || !p) { + return False; + } +@@ -999,6 +1003,10 @@ static bool api_DosPrintQEnum(struct smb + union spoolss_DriverInfo *driver_info; + union spoolss_JobInfo **job_info; + ++#ifndef PRINTER_SUPPORT ++ return False; ++#endif ++ + if (!param_format || !output_format1 || !p) { + return False; + } +@@ -3114,6 +3122,10 @@ static bool api_RDosPrintJobDel(struct s + struct spoolss_DevmodeContainer devmode_ctr; + enum spoolss_JobControl command; + ++#ifndef PRINTER_SUPPORT ++ return False; ++#endif ++ + if (!str1 || !str2 || !p) { + return False; + } +@@ -3247,6 +3259,10 @@ static bool api_WPrintQueueCtrl(struct s + struct sec_desc_buf secdesc_ctr; + enum spoolss_PrinterControl command; + ++#ifndef PRINTER_SUPPORT ++ return False; ++#endif ++ + if (!str1 || !str2 || !QueueName) { + return False; + } +@@ -3413,6 +3429,10 @@ static bool api_PrintJobInfo(struct smbd + union spoolss_JobInfo info; + struct spoolss_SetJobInfo1 info1; + ++#ifndef PRINTER_SUPPORT ++ return False; ++#endif ++ + if (!str1 || !str2 || !p) { + return False; + } +@@ -4567,6 +4587,10 @@ static bool api_WPrintJobGetInfo(struct + struct spoolss_DevmodeContainer devmode_ctr; + union spoolss_JobInfo info; + ++#ifndef PRINTER_SUPPORT ++ return False; ++#endif ++ + if (!str1 || !str2 || !p) { + return False; + } +@@ -4705,6 +4729,10 @@ static bool api_WPrintJobEnumerate(struc + uint32_t count = 0; + union spoolss_JobInfo *info; + ++#ifndef PRINTER_SUPPORT ++ return False; ++#endif ++ + if (!str1 || !str2 || !p) { + return False; + } +@@ -4910,6 +4938,10 @@ static bool api_WPrintDestGetInfo(struct + struct spoolss_DevmodeContainer devmode_ctr; + union spoolss_PrinterInfo info; + ++#ifndef PRINTER_SUPPORT ++ return False; ++#endif ++ + if (!str1 || !str2 || !p) { + return False; + } +@@ -5046,6 +5078,10 @@ static bool api_WPrintDestEnum(struct sm + union spoolss_PrinterInfo *info; + uint32_t count; + ++#ifndef PRINTER_SUPPORT ++ return False; ++#endif ++ + if (!str1 || !str2 || !p) { + return False; + } +@@ -5149,6 +5185,10 @@ static bool api_WPrintDriverEnum(struct + int succnt; + struct pack_desc desc; + ++#ifndef PRINTER_SUPPORT ++ return False; ++#endif ++ + if (!str1 || !str2 || !p) { + return False; + } +@@ -5213,6 +5253,10 @@ static bool api_WPrintQProcEnum(struct s + int succnt; + struct pack_desc desc; + ++#ifndef PRINTER_SUPPORT ++ return False; ++#endif ++ + if (!str1 || !str2 || !p) { + return False; + } +@@ -5277,6 +5321,10 @@ static bool api_WPrintPortEnum(struct sm + int succnt; + struct pack_desc desc; + ++#ifndef PRINTER_SUPPORT ++ return False; ++#endif ++ + if (!str1 || !str2 || !p) { + return False; + } +--- a/source3/smbd/server_exit.c ++++ b/source3/smbd/server_exit.c +@@ -198,7 +198,9 @@ static void exit_server_common(enum serv + rpc_eventlog_shutdown(); + rpc_ntsvcs_shutdown(); + rpc_svcctl_shutdown(); ++#ifdef PRINTER_SUPPORT + rpc_spoolss_shutdown(); ++#endif + + rpc_srvsvc_shutdown(); + rpc_winreg_shutdown(); +--- a/source3/smbd/open.c ++++ b/source3/smbd/open.c +@@ -2430,6 +2430,9 @@ static NTSTATUS open_file_ntcreate(conne + * Most of the passed parameters are ignored. + */ + ++#ifndef PRINTER_SUPPORT ++ return NT_STATUS_ACCESS_DENIED; ++#endif + if (pinfo) { + *pinfo = FILE_WAS_CREATED; + } +--- a/source3/smbd/close.c ++++ b/source3/smbd/close.c +@@ -727,6 +727,9 @@ static NTSTATUS close_normal_file(struct + } + + if (fsp->print_file) { ++#ifndef PRINTER_SUPPORT ++ return NT_STATUS_OK; ++#endif + /* FIXME: return spool errors */ + print_spool_end(fsp, close_type); + file_free(req, fsp); +--- a/source3/smbd/fileio.c ++++ b/source3/smbd/fileio.c +@@ -318,6 +318,10 @@ ssize_t write_file(struct smb_request *r + uint32_t t; + int ret; + ++#ifndef PRINTER_SUPPORT ++ return -1; ++#endif ++ + ret = print_spool_write(fsp, data, n, pos, &t); + if (ret) { + errno = ret; +--- a/source3/smbd/smb2_create.c ++++ b/source3/smbd/smb2_create.c +@@ -633,7 +633,10 @@ static struct tevent_req *smbd_smb2_crea + } + + status = file_new(smb1req, smb1req->conn, &result); +- if(!NT_STATUS_IS_OK(status)) { ++#ifdef PRINTER_SUPPORT ++ if(!NT_STATUS_IS_OK(status)) ++#endif ++ { + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + } +--- a/source3/smbd/process.c ++++ b/source3/smbd/process.c +@@ -2895,8 +2895,10 @@ static bool housekeeping_fn(const struct + + change_to_root_user(); + ++#ifdef PRINTER_SUPPORT + /* update printer queue caches if necessary */ + update_monitored_printq_cache(sconn->msg_ctx); ++#endif + + /* check if we need to reload services */ + check_reload(sconn, time_mono(NULL)); +--- a/source3/smbd/server.c ++++ b/source3/smbd/server.c +@@ -1679,6 +1679,7 @@ extern void build_options(bool screen); + start_fssd(ev_ctx, msg_ctx); + } + ++#ifdef PRINTER_SUPPORT + if (!lp__disable_spoolss() && + (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) { + bool bgq = lp_parm_bool(-1, "smbd", "backgroundqueue", true); +@@ -1699,6 +1700,7 @@ extern void build_options(bool screen); + if (!printing_subsystem_init(ev_ctx, msg_ctx, false, false)) { + exit(1); + } ++#endif + } + + if (!is_daemon) { +@@ -1731,12 +1733,14 @@ extern void build_options(bool screen); + if (!open_sockets_smbd(parent, ev_ctx, msg_ctx, ports)) + exit_server("open_sockets_smbd() failed"); + ++#ifdef PRINTER_SUPPORT + /* do a printer update now that all messaging has been set up, + * before we allow clients to start connecting */ + if (!lp__disable_spoolss() && + (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) { + printing_subsystem_update(ev_ctx, msg_ctx, false); + } ++#endif + + TALLOC_FREE(frame); + /* make sure we always have a valid stackframe */ +--- a/source3/printing/pcap.c ++++ b/source3/printing/pcap.c +@@ -132,6 +132,7 @@ void pcap_cache_reload(struct tevent_con + void (*post_cache_fill_fn)(struct tevent_context *, + struct messaging_context *)) + { ++#ifdef PRINTER_SUPPORT + const char *pcap_name = lp_printcapname(); + bool pcap_reloaded = False; + bool post_cache_fill_fn_handled = false; +@@ -204,6 +205,7 @@ done: + pcap_cache_destroy_specific(&pcache); + + return; ++#endif + } + + diff --git a/package/lean/samba4x/patches/220-remove_services.patch b/package/lean/samba4x/patches/220-remove_services.patch new file mode 100644 index 000000000..34b6f36b5 --- /dev/null +++ b/package/lean/samba4x/patches/220-remove_services.patch @@ -0,0 +1,46 @@ +--- a/source3/rpc_server/rpc_service_setup.c ++++ b/source3/rpc_server/rpc_service_setup.c +@@ -560,6 +560,7 @@ bool dcesrv_ep_setup(struct tevent_conte + } + #endif + ++#ifdef EXTRA_SERVICES + ok = rpc_setup_svcctl(ev_ctx, msg_ctx); + if (!ok) { + goto done; +@@ -574,6 +575,7 @@ bool dcesrv_ep_setup(struct tevent_conte + if (!ok) { + goto done; + } ++#endif + + ok = rpc_setup_initshutdown(ev_ctx, msg_ctx); + if (!ok) { +--- a/source3/smbd/server_exit.c ++++ b/source3/smbd/server_exit.c +@@ -195,9 +195,11 @@ static void exit_server_common(enum serv + #endif + rpc_netdfs_shutdown(); + rpc_initshutdown_shutdown(); ++#ifdef EXTRA_SERVICES + rpc_eventlog_shutdown(); + rpc_ntsvcs_shutdown(); + rpc_svcctl_shutdown(); ++#endif + #ifdef PRINTER_SUPPORT + rpc_spoolss_shutdown(); + #endif +--- a/source3/rpcclient/rpcclient.c ++++ b/source3/rpcclient/rpcclient.c +@@ -631,9 +631,11 @@ static struct cmd_set *rpcclient_command + shutdown_commands, + test_commands, + wkssvc_commands, ++#ifdef EXTRA_SERVICES + ntsvcs_commands, + drsuapi_commands, + eventlog_commands, ++#endif + winreg_commands, + fss_commands, + witness_commands, diff --git a/package/lean/samba4x/patches/230-remove_winreg_support.patch b/package/lean/samba4x/patches/230-remove_winreg_support.patch new file mode 100644 index 000000000..7124d461e --- /dev/null +++ b/package/lean/samba4x/patches/230-remove_winreg_support.patch @@ -0,0 +1,101 @@ +--- a/source3/rpc_server/rpc_service_setup.c ++++ b/source3/rpc_server/rpc_service_setup.c +@@ -396,10 +396,12 @@ static bool eventlog_init_cb(void *ptr) + talloc_get_type_abort(ptr, struct messaging_context); + bool ok; + ++#ifdef WINREG_SUPPORT + ok = eventlog_init_winreg(msg_ctx); + if (!ok) { + return false; + } ++#endif + + return true; + } +@@ -506,10 +508,12 @@ bool dcesrv_ep_setup(struct tevent_conte + return false; + } + ++#ifdef WINREG_SUPPORT + ok = rpc_setup_winreg(ev_ctx, msg_ctx); + if (!ok) { + goto done; + } ++#endif + + ok = rpc_setup_srvsvc(ev_ctx, msg_ctx); + if (!ok) { +--- a/source3/smbd/server_exit.c ++++ b/source3/smbd/server_exit.c +@@ -205,7 +205,9 @@ static void exit_server_common(enum serv + #endif + + rpc_srvsvc_shutdown(); ++#ifdef WINREG_SUPPORT + rpc_winreg_shutdown(); ++#endif + + rpc_netlogon_shutdown(); + rpc_samr_shutdown(); +--- a/source3/rpc_server/svcctl/srv_svcctl_nt.c ++++ b/source3/rpc_server/svcctl/srv_svcctl_nt.c +@@ -96,9 +96,11 @@ bool init_service_op_table( void ) + svcctl_ops[i].ops = &netlogon_svc_ops; + i++; + ++#ifdef WINREG_SUPPORT + svcctl_ops[i].name = talloc_strdup( svcctl_ops, "RemoteRegistry" ); + svcctl_ops[i].ops = &winreg_svc_ops; + i++; ++#endif + + svcctl_ops[i].name = talloc_strdup( svcctl_ops, "WINS" ); + svcctl_ops[i].ops = &wins_svc_ops; +--- a/source3/services/svc_winreg_glue.c ++++ b/source3/services/svc_winreg_glue.c +@@ -88,6 +88,10 @@ struct security_descriptor *svcctl_get_s + NTSTATUS status; + WERROR result = WERR_OK; + ++#ifndef WINREG_SUPPORT ++ return NULL; ++#endif ++ + key = talloc_asprintf(mem_ctx, + "%s\\%s\\Security", + TOP_LEVEL_SERVICES_KEY, name); +@@ -161,6 +165,10 @@ bool svcctl_set_secdesc(struct messaging + NTSTATUS status; + WERROR result = WERR_OK; + ++#ifndef WINREG_SUPPORT ++ return false; ++#endif ++ + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + return false; +@@ -272,6 +280,10 @@ const char *svcctl_get_string_value(TALL + NTSTATUS status; + WERROR result = WERR_OK; + ++#ifndef WINREG_SUPPORT ++ return NULL; ++#endif ++ + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + return NULL; +--- a/source3/rpcclient/rpcclient.c ++++ b/source3/rpcclient/rpcclient.c +@@ -636,7 +636,9 @@ static struct cmd_set *rpcclient_command + drsuapi_commands, + eventlog_commands, + #endif ++#ifdef WINREG_SUPPORT + winreg_commands, ++#endif + fss_commands, + witness_commands, + clusapi_commands, diff --git a/package/lean/samba4x/patches/270-remove_registry_backend.patch b/package/lean/samba4x/patches/270-remove_registry_backend.patch new file mode 100644 index 000000000..1a91b250a --- /dev/null +++ b/package/lean/samba4x/patches/270-remove_registry_backend.patch @@ -0,0 +1,43 @@ +--- a/source3/lib/smbconf/smbconf_init.c ++++ b/source3/lib/smbconf/smbconf_init.c +@@ -68,9 +68,12 @@ sbcErr smbconf_init(TALLOC_CTX *mem_ctx, + } + } + ++#ifdef REGISTRY_BACKEND + if (strequal(backend, "registry") || strequal(backend, "reg")) { + err = smbconf_init_reg(mem_ctx, conf_ctx, path); +- } else if (strequal(backend, "file") || strequal(backend, "txt")) { ++ } else ++#endif ++ if (strequal(backend, "file") || strequal(backend, "txt")) { + err = smbconf_init_txt(mem_ctx, conf_ctx, path); + } else if (sep == NULL) { + /* +--- a/source3/lib/netapi/serverinfo.c ++++ b/source3/lib/netapi/serverinfo.c +@@ -557,7 +557,10 @@ static WERROR NetServerSetInfo_l_1005(st + return WERR_INVALID_PARAM; + } + +- if (!lp_config_backend_is_registry()) { ++#ifdef REGISTRY_BACKEND ++ if (!lp_config_backend_is_registry()) ++#endif ++ { + libnetapi_set_error_string(ctx, + "Configuration manipulation requested but not " + "supported by backend"); +--- a/source3/smbd/server.c ++++ b/source3/smbd/server.c +@@ -1599,8 +1599,10 @@ extern void build_options(bool screen); + exit_daemon("Samba cannot init server id", EACCES); + } + ++#ifdef REGISTRY_BACKEND + if (!W_ERROR_IS_OK(registry_init_full())) + exit_daemon("Samba cannot init registry", EACCES); ++#endif + + /* Open the share_info.tdb here, so we don't have to open + after the fork on every single connection. This is a small diff --git a/package/lean/samba4x/patches/280-strip_srvsvc.patch b/package/lean/samba4x/patches/280-strip_srvsvc.patch new file mode 100644 index 000000000..f88c27415 --- /dev/null +++ b/package/lean/samba4x/patches/280-strip_srvsvc.patch @@ -0,0 +1,146 @@ +--- a/source3/smbd/lanman.c ++++ b/source3/smbd/lanman.c +@@ -2206,6 +2206,10 @@ static bool api_RNetShareAdd(struct smbd + struct srvsvc_NetShareInfo2 info2; + struct dcerpc_binding_handle *b; + ++#ifndef SRVSVC_SUPPORT ++ return False; ++#endif ++ + if (!str1 || !str2 || !p) { + return False; + } +@@ -3582,10 +3586,7 @@ static bool api_RNetServerGetInfo(struct + NTSTATUS status; + WERROR werr; + TALLOC_CTX *mem_ctx = talloc_tos(); +- struct rpc_pipe_client *cli = NULL; +- union srvsvc_NetSrvInfo info; + int errcode; +- struct dcerpc_binding_handle *b; + + if (!str1 || !str2 || !p) { + return False; +@@ -3648,42 +3649,9 @@ static bool api_RNetServerGetInfo(struct + p = *rdata; + p2 = p + struct_len; + +- status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc, +- conn->session_info, +- conn->sconn->remote_address, +- conn->sconn->msg_ctx, +- &cli); +- if (!NT_STATUS_IS_OK(status)) { +- DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n", +- nt_errstr(status))); +- errcode = W_ERROR_V(ntstatus_to_werror(status)); +- goto out; +- } +- +- b = cli->binding_handle; +- +- status = dcerpc_srvsvc_NetSrvGetInfo(b, mem_ctx, +- NULL, +- 101, +- &info, +- &werr); +- if (!NT_STATUS_IS_OK(status)) { +- errcode = W_ERROR_V(ntstatus_to_werror(status)); +- goto out; +- } +- if (!W_ERROR_IS_OK(werr)) { +- errcode = W_ERROR_V(werr); +- goto out; +- } +- +- if (info.info101 == NULL) { +- errcode = W_ERROR_V(WERR_INVALID_PARAM); +- goto out; +- } +- + if (uLevel != 20) { + size_t len = 0; +- status = srvstr_push(NULL, 0, p, info.info101->server_name, 16, ++ status = srvstr_push(NULL, 0, p, lp_netbios_name(), 16, + STR_ASCII|STR_UPPER|STR_TERMINATE, &len); + if (!NT_STATUS_IS_OK(status)) { + errcode = W_ERROR_V(ntstatus_to_werror(status)); +@@ -3692,27 +3660,10 @@ static bool api_RNetServerGetInfo(struct + } + p += 16; + if (uLevel > 0) { +- SCVAL(p,0,info.info101->version_major); +- SCVAL(p,1,info.info101->version_minor); +- SIVAL(p,2,info.info101->server_type); +- +- if (mdrcnt == struct_len) { +- SIVAL(p,6,0); +- } else { +- SIVAL(p,6,PTR_DIFF(p2,*rdata)); +- if (mdrcnt - struct_len <= 0) { +- return false; +- } +- push_ascii(p2, +- info.info101->comment, +- MIN(mdrcnt - struct_len, +- MAX_SERVER_STRING_LENGTH), +- STR_TERMINATE); +- p2 = skip_string(*rdata,*rdata_len,p2); +- if (!p2) { +- return False; +- } +- } ++ SCVAL(p,0,SAMBA_MAJOR_NBT_ANNOUNCE_VERSION); ++ SCVAL(p,1,SAMBA_MINOR_NBT_ANNOUNCE_VERSION); ++ SIVAL(p,2,lp_default_server_announce()); ++ SIVAL(p,6,0); + } + + if (uLevel > 1) { +@@ -5405,6 +5356,10 @@ static bool api_RNetSessionEnum(struct s + uint32_t totalentries, resume_handle = 0; + uint32_t count = 0; + ++#ifndef SRVSVC_SUPPORT ++ return False; ++#endif ++ + if (!str1 || !str2 || !p) { + return False; + } +--- a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c ++++ b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c +@@ -1724,6 +1724,10 @@ WERROR _srvsvc_NetShareSetInfo(struct pi + TALLOC_CTX *ctx = p->mem_ctx; + union srvsvc_NetShareInfo *info = r->in.info; + ++#ifndef FULL_SRVSVC ++ return WERR_ACCESS_DENIED; ++#endif ++ + DEBUG(5,("_srvsvc_NetShareSetInfo: %d\n", __LINE__)); + + if (!r->in.share_name) { +@@ -1968,6 +1972,10 @@ WERROR _srvsvc_NetShareAdd(struct pipes_ + SMB_STRUCT_STAT st; + TALLOC_CTX *ctx = p->mem_ctx; + ++#ifndef FULL_SRVSVC ++ return WERR_ACCESS_DENIED; ++#endif ++ + DEBUG(5,("_srvsvc_NetShareAdd: %d\n", __LINE__)); + + if (r->out.parm_error) { +@@ -2159,6 +2167,10 @@ WERROR _srvsvc_NetShareDel(struct pipes_ + bool is_disk_op; + TALLOC_CTX *ctx = p->mem_ctx; + ++#ifndef FULL_SRVSVC ++ return WERR_ACCESS_DENIED; ++#endif ++ + DEBUG(5,("_srvsvc_NetShareDel: %d\n", __LINE__)); + + if (!r->in.share_name) { diff --git a/package/lean/samba4x/patches/300-assert_debug_level.patch b/package/lean/samba4x/patches/300-assert_debug_level.patch new file mode 100644 index 000000000..66fe8ee82 --- /dev/null +++ b/package/lean/samba4x/patches/300-assert_debug_level.patch @@ -0,0 +1,11 @@ +--- a/lib/util/fault.h ++++ b/lib/util/fault.h +@@ -34,7 +34,7 @@ + #define SMB_ASSERT(b) \ + do { \ + if (!(b)) { \ +- DEBUG(0,("PANIC: assert failed at %s(%d): %s\n", \ ++ DEBUG(3,("PANIC: assert failed at %s(%d): %s\n", \ + __FILE__, __LINE__, #b)); \ + smb_panic("assert failed: " #b); \ + } \ diff --git a/package/lean/samba4x/patches/320-debug_level_checks.patch b/package/lean/samba4x/patches/320-debug_level_checks.patch new file mode 100644 index 000000000..7758de7c1 --- /dev/null +++ b/package/lean/samba4x/patches/320-debug_level_checks.patch @@ -0,0 +1,22 @@ +--- a/lib/util/debug.h ++++ b/lib/util/debug.h +@@ -51,7 +51,7 @@ bool dbghdr( int level, const char *loca + * Redefine DEBUGLEVEL because so we don't have to change every source file + * that *unnecessarily* references it. + */ +-#define DEBUGLEVEL DEBUGLEVEL_CLASS[DBGC_ALL] ++#define DEBUGLEVEL 0 + + /* + * Define all new debug classes here. A class is represented by an entry in +--- a/source3/nmbd/asyncdns.c ++++ b/source3/nmbd/asyncdns.c +@@ -86,7 +86,7 @@ static void asyncdns_process(void) + struct query_record r; + unstring qname; + +- DEBUGLEVEL = -1; ++ DEBUGLEVEL_CLASS[DBGC_ALL] = -1; + + while (1) { + NTSTATUS status; diff --git a/package/lean/samba4x/patches/390-remove-auth-winbind.patch b/package/lean/samba4x/patches/390-remove-auth-winbind.patch new file mode 100644 index 000000000..49bc3f3d0 --- /dev/null +++ b/package/lean/samba4x/patches/390-remove-auth-winbind.patch @@ -0,0 +1,20 @@ +--- a/source3/auth/auth.c ++++ b/source3/auth/auth.c +@@ -476,7 +476,7 @@ NTSTATUS make_auth_context_subsystem(TAL + case ROLE_DOMAIN_MEMBER: + DEBUG(5,("Making default auth method list for server role = 'domain member'\n")); + auth_method_list = str_list_make_v3( +- talloc_tos(), "guest sam winbind:ntdomain", ++ talloc_tos(), "guest sam", + NULL); + break; + case ROLE_DOMAIN_BDC: +@@ -484,7 +484,7 @@ NTSTATUS make_auth_context_subsystem(TAL + DEBUG(5,("Making default auth method list for DC\n")); + auth_method_list = str_list_make_v3( + talloc_tos(), +- "guest sam winbind:trustdomain", ++ "guest sam", + NULL); + break; + case ROLE_STANDALONE: diff --git a/package/lean/samba4x/patches/800-ldap-sasl.patch b/package/lean/samba4x/patches/800-ldap-sasl.patch new file mode 100644 index 000000000..bd950349f --- /dev/null +++ b/package/lean/samba4x/patches/800-ldap-sasl.patch @@ -0,0 +1,76 @@ +--- a/source3/lib/smbldap.c ++++ b/source3/lib/smbldap.c +@@ -876,7 +876,15 @@ static int rebindproc_connect_with_state + Could we get a referral to a machine that we don't want to give our + username and password to? */ + +- rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret); ++ if (ldap_state->bind_secret) ++ rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret); ++ else { ++ struct berval *servercredp=NULL; ++ ++ rc = ldap_sasl_bind_s(ldap_struct, NULL, "EXTERNAL", NULL, NULL, NULL, &servercredp); ++ if (rc == LDAP_SASL_BIND_IN_PROGRESS) ++ rc = ldap_sasl_bind_s(ldap_struct, NULL, "EXTERNAL", servercredp, NULL, NULL, &servercredp); ++ } + + /* only set the last rebind timestamp when we did rebind after a + * non-read LDAP operation. That way we avoid the replication sleep +@@ -983,7 +991,15 @@ static int smbldap_connect_system(struct + rc = ldap_state->bind_callback(ldap_struct, ldap_state, ldap_state->bind_callback_data); + unbecome_root(); + } else { +- rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret); ++ if (ldap_state->bind_secret) ++ rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret); ++ else { ++ struct berval *servercredp=NULL; ++ ++ rc = ldap_sasl_bind_s(ldap_struct, NULL, "EXTERNAL", NULL, NULL, NULL, &servercredp); ++ if (rc == LDAP_SASL_BIND_IN_PROGRESS) ++ rc = ldap_sasl_bind_s(ldap_struct, NULL, "EXTERNAL", servercredp, NULL, NULL, &servercredp); ++ } + } + + if (rc != LDAP_SUCCESS) { +--- a/source3/passdb/pdb_ldap.c ++++ b/source3/passdb/pdb_ldap.c +@@ -6430,16 +6430,21 @@ static NTSTATUS pdb_init_ldapsam_common( + } + + if (!fetch_ldap_pw(&bind_dn, &bind_secret)) { +- DEBUG(0, ("pdb_init_ldapsam_common: Failed to retrieve LDAP password from secrets.tdb\n")); +- return NT_STATUS_NO_MEMORY; ++ DEBUG(1, ("pdb_init_ldapsam_common: Failed to retrieve password from secrets.tdb. Switching to SASL\n")); + } + + nt_status = smbldap_init(*pdb_method, pdb_get_tevent_context(), + location, false, bind_dn, bind_secret, + &ldap_state->smbldap_state); +- memset(bind_secret, '\0', strlen(bind_secret)); +- SAFE_FREE(bind_secret); +- SAFE_FREE(bind_dn); ++ ++ if (bind_secret) { ++ memset(bind_secret, '\0', strlen(bind_secret)); ++ SAFE_FREE(bind_secret); ++ } ++ ++ if (bind_dn) ++ SAFE_FREE(bind_dn); ++ + if ( !NT_STATUS_IS_OK(nt_status) ) { + return nt_status; + } +--- a/source3/passdb/secrets.c ++++ b/source3/passdb/secrets.c +@@ -333,7 +333,7 @@ bool fetch_ldap_pw(char **dn, char** pw) + + data=(char *)secrets_fetch(old_style_key, &size); + if ((data == NULL) || (size < sizeof(old_style_pw))) { +- DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n")); ++ DEBUG(1,("fetch_ldap_pw: neither ldap secret retrieved!\n")); + SAFE_FREE(old_style_key); + SAFE_FREE(*dn); + SAFE_FREE(data); diff --git a/package/lean/samba4x/patches/810-ldap-determine-suffix-automatically.patch b/package/lean/samba4x/patches/810-ldap-determine-suffix-automatically.patch new file mode 100644 index 000000000..c56903253 --- /dev/null +++ b/package/lean/samba4x/patches/810-ldap-determine-suffix-automatically.patch @@ -0,0 +1,77 @@ +--- a/source3/param/loadparm.c ++++ b/source3/param/loadparm.c +@@ -4487,3 +4487,17 @@ unsigned int * get_flags(void) + + return flags_list; + } ++ ++bool lp_ldap_suffix_initial() ++{ ++ if (Globals.ldap_suffix == NULL) ++ return true; ++ if (strlen(Globals.ldap_suffix) == 0) ++ return true; ++ return false; ++} ++ ++void lp_set_ldap_suffix(const char *suffix) ++{ ++ lpcfg_string_set(Globals.ctx, &Globals.ldap_suffix, suffix); ++} +--- a/source3/include/proto.h ++++ b/source3/include/proto.h +@@ -1028,6 +1028,8 @@ char* lp_perfcount_module(TALLOC_CTX *ct + void widelinks_warning(int snum); + const char *lp_ncalrpc_dir(void); + void _lp_set_server_role(int server_role); ++bool lp_ldap_suffix_initial(); ++void lp_set_ldap_suffix(const char *suffix); + + /* The following definitions come from param/loadparm_ctx.c */ + +--- a/source3/passdb/pdb_ldap_util.c ++++ b/source3/passdb/pdb_ldap_util.c +@@ -247,6 +247,34 @@ static NTSTATUS add_new_domain_info(stru + } + + /********************************************************************** ++ Autodetermine LDAP suffix ++ **********************************************************************/ ++void find_ldap_suffix(struct smbldap_state *ldap_state) ++{ ++ const char *namingCtx[] = { "namingContexts", NULL }; ++ LDAPMessage *entry = NULL, *result = NULL; ++ int rc; ++ ++ if (!lp_ldap_suffix_initial()) ++ return; ++ ++ rc = smbldap_search(ldap_state, "", LDAP_SCOPE_BASE, "(objectClass=*)", namingCtx, 0, &result); ++ if (rc != LDAP_SUCCESS) ++ return; ++ ++ entry = ldap_first_entry(ldap_state->ldap_struct, result); ++ if (entry) { ++ char **values = NULL; ++ values = ldap_get_values(ldap_state->ldap_struct, entry, namingCtx[0]); ++ if (values) { ++ lp_set_ldap_suffix(values[0]); ++ ldap_value_free(values); ++ } ++ } ++ ldap_msgfree(result); ++} ++ ++/********************************************************************** + Search for the domain info entry + *********************************************************************/ + +@@ -261,6 +289,8 @@ NTSTATUS smbldap_search_domain_info(stru + int count; + char *escape_domain_name; + ++ find_ldap_suffix(ldap_state); ++ + escape_domain_name = escape_ldap_string(talloc_tos(), domain_name); + if (!escape_domain_name) { + DEBUG(0, ("Out of memory!\n")); diff --git a/package/lean/samba4x/patches/900-musl-remove-getgrent_r-getpwent_r.patch b/package/lean/samba4x/patches/900-musl-remove-getgrent_r-getpwent_r.patch new file mode 100644 index 000000000..df0effaf1 --- /dev/null +++ b/package/lean/samba4x/patches/900-musl-remove-getgrent_r-getpwent_r.patch @@ -0,0 +1,60 @@ +--- a/source4/torture/local/nss_tests.c ++++ b/source4/torture/local/nss_tests.c +@@ -346,28 +346,6 @@ static bool test_enum_r_passwd(struct to + torture_comment(tctx, "Testing setpwent\n"); + setpwent(); + +- while (1) { +- torture_comment(tctx, "Testing getpwent_r\n"); +- +-#ifdef SOLARIS_GETPWENT_R +- ret = getpwent_r(&pwd, buffer, sizeof(buffer)); +-#else /* SOLARIS_GETPWENT_R */ +- ret = getpwent_r(&pwd, buffer, sizeof(buffer), &pwdp); +-#endif /* SOLARIS_GETPWENT_R */ +- if (ret != 0) { +- if (ret != ENOENT) { +- torture_comment(tctx, "got %d return code\n", ret); +- } +- break; +- } +- print_passwd(&pwd); +- if (pwd_array_p && num_pwd_p) { +- pwd_array = talloc_realloc(tctx, pwd_array, struct passwd, num_pwd+1); +- torture_assert(tctx, pwd_array, "out of memory"); +- copy_passwd(tctx, &pwd, &pwd_array[num_pwd]); +- num_pwd++; +- } +- } + + torture_comment(tctx, "Testing endpwent\n"); + endpwent(); +@@ -544,28 +522,6 @@ static bool test_enum_r_group(struct tor + torture_comment(tctx, "Testing setgrent\n"); + setgrent(); + +- while (1) { +- torture_comment(tctx, "Testing getgrent_r\n"); +- +-#ifdef SOLARIS_GETGRENT_R +- ret = getgrent_r(&grp, buffer, sizeof(buffer)); +-#else /* SOLARIS_GETGRENT_R */ +- ret = getgrent_r(&grp, buffer, sizeof(buffer), &grpp); +-#endif /* SOLARIS_GETGRENT_R */ +- if (ret != 0) { +- if (ret != ENOENT) { +- torture_comment(tctx, "got %d return code\n", ret); +- } +- break; +- } +- print_group(&grp); +- if (grp_array_p && num_grp_p) { +- grp_array = talloc_realloc(tctx, grp_array, struct group, num_grp+1); +- torture_assert(tctx, grp_array, "out of memory"); +- copy_group(tctx, &grp, &grp_array[num_grp]); +- num_grp++; +- } +- } + + torture_comment(tctx, "Testing endgrent\n"); + endgrent(); diff --git a/package/lean/samba4x/patches/911-musl-NETDB-fix.patch b/package/lean/samba4x/patches/911-musl-NETDB-fix.patch new file mode 100644 index 000000000..3ccc28cce --- /dev/null +++ b/package/lean/samba4x/patches/911-musl-NETDB-fix.patch @@ -0,0 +1,15 @@ +--- a/nsswitch/wins.c ++++ b/nsswitch/wins.c +@@ -39,5 +39,12 @@ static pthread_mutex_t wins_nss_mutex = + #define INADDRSZ 4 + #endif + ++#if !defined(NETDB_INTERNAL) ++# define NETDB_INTERNAL -1 /* See errno. */ ++#endif ++#if !defined(NETDB_SUCCESS) ++# define NETDB_SUCCESS 0 /* No problem. */ ++#endif ++ + NSS_STATUS _nss_wins_gethostbyname_r(const char *hostname, struct hostent *he, + char *buffer, size_t buflen, int *h_errnop); diff --git a/package/lean/samba4x/patches/912-msgsock-nvram-fix.patch b/package/lean/samba4x/patches/912-msgsock-nvram-fix.patch new file mode 100644 index 000000000..8e9d6fb95 --- /dev/null +++ b/package/lean/samba4x/patches/912-msgsock-nvram-fix.patch @@ -0,0 +1,46 @@ +--- a/source3/lib/messages.c ++++ b/source3/lib/messages.c +@@ -221,7 +221,7 @@ struct messaging_context *messaging_init + return NULL; + } + +- priv_path = private_path("msg.sock"); ++ priv_path = lock_path("msg.sock"); + if (priv_path == NULL) { + TALLOC_FREE(ctx); + return NULL; +@@ -393,6 +393,7 @@ struct server_id messaging_server_id(const struct messaging_context *msg_ctx) + NTSTATUS messaging_reinit(struct messaging_context *msg_ctx) + { + int ret; ++ char *lck_path; + + TALLOC_FREE(msg_ctx->msg_dgm_ref); + +@@ -400,9 +401,14 @@ NTSTATUS messaging_reinit(struct messaging_context *msg_ctx) + .pid = getpid(), .vnn = msg_ctx->id.vnn + }; + ++ lck_path = lock_path("msg.lock"); ++ if (lck_path == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ + msg_ctx->msg_dgm_ref = messaging_dgm_ref( + msg_ctx, msg_ctx->event_ctx, &msg_ctx->id.unique_id, +- private_path("msg.sock"), lock_path("msg.lock"), ++ lock_path("msg.sock"), lck_path, + messaging_recv_cb, msg_ctx, &ret); + + if (msg_ctx->msg_dgm_ref == NULL) { +--- a/source4/lib/messaging/messaging.c ++++ b/source4/lib/messaging/messaging.c +@@ -323,7 +323,7 @@ struct imessaging_context *imessaging_in + goto fail; + } + +- msg->sock_dir = lpcfg_private_path(msg, lp_ctx, "msg.sock"); ++ msg->sock_dir = lpcfg_lock_path(msg, lp_ctx, "msg.sock"); + if (msg->sock_dir == NULL) { + goto fail; + } diff --git a/package/lean/shadowsocksR-libev-full/Makefile b/package/lean/shadowsocksR-libev-full/Makefile index 647a909cb..f731f8b44 100644 --- a/package/lean/shadowsocksR-libev-full/Makefile +++ b/package/lean/shadowsocksR-libev-full/Makefile @@ -2,12 +2,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=shadowsocksR-libev PKG_VERSION:=2.5.1 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_RELEASE).tar.gz PKG_SOURCE_URL:=https://github.com/shadowsocksrr/shadowsocksr-libev.git PKG_SOURCE_PROTO:=git -PKG_SOURCE_VERSION:=91c72165d4e7ae92eba2d678812a8d11a037932d +PKG_SOURCE_VERSION:=bc1bbecc49ab5a9afb4ab7076f0d9359dc0493d1 PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_MAINTAINER:=breakwa11 diff --git a/package/lean/shortcut-fe/Makefile b/package/lean/shortcut-fe/Makefile index 5dcb2ac1d..61faaf0f2 100644 --- a/package/lean/shortcut-fe/Makefile +++ b/package/lean/shortcut-fe/Makefile @@ -23,7 +23,7 @@ define KernelPackage/shortcut-fe SECTION:=kernel CATEGORY:=Kernel modules SUBMENU:=Network Support - DEPENDS:=@IPV6 + DEPENDS:=@IPV6 @!LINUX_4_14 TITLE:=Kernel driver for SFE FILES:=$(PKG_BUILD_DIR)/shortcut-fe.ko $(PKG_BUILD_DIR)/shortcut-fe-ipv6.ko KCONFIG:=CONFIG_NF_CONNTRACK_EVENTS=y CONFIG_SHORTCUT_FE=y diff --git a/package/lean/v2ray/Makefile b/package/lean/v2ray/Makefile new file mode 100644 index 000000000..c8b8f4589 --- /dev/null +++ b/package/lean/v2ray/Makefile @@ -0,0 +1,115 @@ +# +# Copyright (C) 2015-2016 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v3. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=v2ray +PKG_VERSION:=v3.14 +#PKG_VERSION:=$(shell wget https://api.github.com/repos/v2ray/v2ray-core/releases/latest -q -O -|grep tag_name|awk {'print $2'}|cut -d '"' -f 2) +#PKG_RELEASE:=$(shell wget https://api.github.com/repos/v2ray/v2ray-core/releases/latest -q -O -|grep published_at|awk {'print $2'}|cut -d '"' -f 2|cut -d 'T' -f 1) +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +ifeq ($(ARCH),x86_64) + PKG_ARCH_V2RAY:=linux-64 +endif +ifeq ($(ARCH),mipsel) + PKG_ARCH_V2RAY:=linux-mipsle +endif +ifeq ($(ARCH),mips) + PKG_ARCH_V2RAY:=linux-mips +endif +ifeq ($(ARCH),i386) + PKG_ARCH_V2RAY:=linux-32 +endif +ifeq ($(ARCH),arm) + PKG_ARCH_V2RAY:=linux-arm +endif +ifeq ($(ARCH),aarch64) + PKG_ARCH_V2RAY:=linux-arm64 +endif +#PKG_SOURCE:=v2ray-$(PKG_ARCH_V2RAY).zip +#PKG_SOURCE_URL:=https://github.com/v2ray/v2ray-core/releases/download/$(PKG_VERSION) +#PKG_SOURCE_SUBDIR:=v2ray-$(PKG_VERSION)-$(V2RAY_PKG_ARCH) +#PKG_CAT:=unzip + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME) + SECTION:=net + CATEGORY:=Network + TITLE:=V2Ray is a cross-platform proxy software + DEPENDS:= + URL:=https://github.com/v2ray/v2ray-core +endef + +define Package/$(PKG_NAME)/config +menu "V2Ray Configuration" + depends on PACKAGE_v2ray + +config PACKAGE_V2RAY_INCLUDE_V2RAY + bool "Include v2ray" + default y + +config PACKAGE_V2RAY_SOFTFLOAT + bool "Use soft-float binaries (mips/mipsle only)" + depends on PACKAGE_V2RAY_INCLUDE_V2RAY + default n + +config PACKAGE_V2RAY_INCLUDE_V2CTL + bool "Include v2ctl" + depends on PACKAGE_V2RAY_INCLUDE_V2RAY + default y + +config PACKAGE_V2RAY_INCLUDE_GEOIP + bool "Include geoip.dat" + depends on PACKAGE_V2RAY_INCLUDE_V2CTL + default n + +config PACKAGE_V2RAY_INCLUDE_GEOSITE + bool "Include geosite.dat" + depends on PACKAGE_V2RAY_INCLUDE_V2CTL + default n + +endmenu +endef + +define Package/$(PKG_NAME)/description +V2Ray is a cross-platform proxy software +endef + +define Build/Prepare + + wget https://github.com/v2ray/v2ray-core/releases/download/$(PKG_VERSION)/v2ray-$(PKG_ARCH_V2RAY).zip -O $(PKG_BUILD_DIR)/v2ray-$(PKG_VERSION)-$(PKG_ARCH_V2RAY).zip + unzip -o $(PKG_BUILD_DIR)/v2ray-$(PKG_VERSION)-$(PKG_ARCH_V2RAY).zip -d $(PKG_BUILD_DIR) +ifdef CONFIG_PACKAGE_V2RAY_SOFTFLOAT + [ -f $(PKG_BUILD_DIR)/v2ray-$(PKG_VERSION)-$(PKG_ARCH_V2RAY)/v2ray_softfloat ] && mv $(PKG_BUILD_DIR)/v2ray-$(PKG_VERSION)-$(PKG_ARCH_V2RAY)/v2ray_softfloat $(PKG_BUILD_DIR)/v2ray-$(PKG_VERSION)-$(PKG_ARCH_V2RAY)/v2ray || echo "Can't find soft-float binary." + [ -f $(PKG_BUILD_DIR)/v2ray-$(PKG_VERSION)-$(PKG_ARCH_V2RAY)/v2ctl_softfloat ] && mv $(PKG_BUILD_DIR)/v2ray-$(PKG_VERSION)-$(PKG_ARCH_V2RAY)/v2ctl_softfloat $(PKG_BUILD_DIR)/v2ray-$(PKG_VERSION)-$(PKG_ARCH_V2RAY)/v2ctl || echo "Can't find soft-float binary." +endif +endef + +define Build/Configure +endef + +define Build/Compile +endef + +define Package/$(PKG_NAME)/install + $(INSTALL_DIR) $(1)/usr/bin/v2ray +ifdef CONFIG_PACKAGE_V2RAY_INCLUDE_V2RAY + $(INSTALL_BIN) $(PKG_BUILD_DIR)/v2ray-$(PKG_VERSION)-$(PKG_ARCH_V2RAY)/v2ray $(1)/usr/bin/v2ray/ +endif +ifdef CONFIG_PACKAGE_V2RAY_INCLUDE_V2CTL + $(INSTALL_BIN) $(PKG_BUILD_DIR)/v2ray-$(PKG_VERSION)-$(PKG_ARCH_V2RAY)/v2ctl $(1)/usr/bin/v2ray/ +endif +ifdef CONFIG_PACKAGE_V2RAY_INCLUDE_GEOIP + $(INSTALL_BIN) $(PKG_BUILD_DIR)/v2ray-$(PKG_VERSION)-$(PKG_ARCH_V2RAY)/geoip.dat $(1)/usr/bin/v2ray/ +endif +ifdef CONFIG_PACKAGE_V2RAY_INCLUDE_GEOSITE + $(INSTALL_BIN) $(PKG_BUILD_DIR)/v2ray-$(PKG_VERSION)-$(PKG_ARCH_V2RAY)/geosite.dat $(1)/usr/bin/v2ray/ +endif +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/libs/toolchain/Makefile b/package/libs/toolchain/Makefile index ce0acd19b..febc7c2db 100644 --- a/package/libs/toolchain/Makefile +++ b/package/libs/toolchain/Makefile @@ -83,7 +83,7 @@ endef define Package/libssp $(call Package/gcc/Default) - DEPENDS+=@SSP_SUPPORT + DEPENDS+=@GCC_LIBSSP TITLE:=GCC support library endef diff --git a/package/network/config/firewall/Makefile b/package/network/config/firewall/Makefile index 1bc2c4d1f..6bf5ee6b0 100644 --- a/package/network/config/firewall/Makefile +++ b/package/network/config/firewall/Makefile @@ -9,13 +9,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=firewall -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/firewall3.git -PKG_SOURCE_DATE:=2017-11-07 -PKG_SOURCE_VERSION:=c4309372acc7e1bef8aa230269f7da1dec790e68 -PKG_MIRROR_HASH:=1699884d8499d01e433959185f79ff9eb69704de47885b996123374b8015b422 +PKG_SOURCE_DATE:=2018-04-05 +PKG_SOURCE_VERSION:=35b3e74a184b709b8ddfaaa094919a656a6ec059 +PKG_MIRROR_HASH:=b45da27ef219d0ec17ad3426b99e83781d079996fef553e5c47b98473f33b3cc PKG_MAINTAINER:=Jo-Philipp Wich PKG_LICENSE:=ISC @@ -28,7 +28,7 @@ define Package/firewall SECTION:=net CATEGORY:=Base system TITLE:=OpenWrt C Firewall - DEPENDS:=+libubox +libubus +libuci +libip4tc +IPV6:libip6tc +libxtables +kmod-ipt-core +kmod-ipt-conntrack +kmod-ipt-nat + DEPENDS:=+libubox +libubus +libuci +libip4tc +IPV6:libip6tc +libxtables +kmod-ipt-core +kmod-ipt-conntrack +IPV6:kmod-nf-conntrack6 +kmod-ipt-nat endef define Package/firewall/description @@ -55,6 +55,8 @@ define Package/firewall/install $(INSTALL_DATA) ./files/firewall.config $(1)/etc/config/firewall $(INSTALL_DIR) $(1)/etc/ $(INSTALL_DATA) ./files/firewall.user $(1)/etc/firewall.user + $(INSTALL_DIR) $(1)/usr/share/fw3 + $(INSTALL_DATA) $(PKG_BUILD_DIR)/helpers.conf $(1)/usr/share/fw3 endef $(eval $(call BuildPackage,firewall)) diff --git a/package/network/utils/ethtool/Makefile b/package/network/utils/ethtool/Makefile new file mode 100644 index 000000000..b378ce2af --- /dev/null +++ b/package/network/utils/ethtool/Makefile @@ -0,0 +1,59 @@ +# +# Copyright (C) 2006-2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=ethtool +PKG_VERSION:=4.15 +PKG_RELEASE:=1 + +PKG_MAINTAINER:=Felix Fietkau +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=@KERNEL/software/network/ethtool +PKG_HASH:=71f7fd32483ffdc7c6c4d882e230714eb101df0a46cbe396dbeb8ac78f1ef91a + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:=COPYING + +PKG_FIXUP:=autoreconf +PKG_INSTALL:=1 +PKG_BUILD_PARALLEL:=1 + +PKG_CONFIG_DEPENDS:=ETHTOOL_PRETTY_DUMP + +include $(INCLUDE_DIR)/package.mk + +define Package/ethtool + SECTION:=net + CATEGORY:=Network + TITLE:=Display or change ethernet card settings + URL:=http://www.kernel.org/pub/software/network/ethtool/ +endef + +define Package/ethtool/description + ethtool is a small utility for examining and tuning your ethernet-based + network interface +endef + +define Package/ethtool/config + config ETHTOOL_PRETTY_DUMP + depends on PACKAGE_ethtool + bool "Enable pretty printing" +endef + +ifeq ($(CONFIG_ETHTOOL_PRETTY_DUMP),y) +CONFIGURE_ARGS += --enable-pretty-dump +else +CONFIGURE_ARGS += --disable-pretty-dump +endif + +define Package/ethtool/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/ethtool $(1)/usr/sbin +endef + +$(eval $(call BuildPackage,ethtool)) diff --git a/package/system/iucode-tool/Makefile b/package/system/iucode-tool/Makefile new file mode 100644 index 000000000..5f4cfb623 --- /dev/null +++ b/package/system/iucode-tool/Makefile @@ -0,0 +1,47 @@ +# +# Copyright (C) 2018 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=iucode-tool +PKG_VERSION:=2.3.1 +PKG_RELEASE:=1 + +PKG_SOURCE:=iucode-tool_$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=https://gitlab.com/iucode-tool/releases/raw/latest +PKG_HASH:=12b88efa4d0d95af08db05a50b3dcb217c0eb2bfc67b483779e33d498ddb2f95 + +PKG_BUILD_DEPENDS:=USE_UCLIBC:argp-standalone USE_MUSL:argp-standalone + +PKG_MAINTAINER:=Zoltan HERPAI +PKG_LICENSE:=GPL-2.0 + +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/host-build.mk + +define Package/iucode-tool + SECTION:=utils + CATEGORY:=Base system + URL:=$(PKG_SOURCE_URL) + DEPENDS:=@TARGET_x86 + TITLE:=Intel microcode loader +endef + +define Package/iucode-tool/install + $(INSTALL_DIR) $(1)/lib/firmware + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/iucode_tool $(1)/usr/bin/ +endef + +define Host/Install + $(INSTALL_BIN) $(HOST_BUILD_DIR)/iucode_tool $(STAGING_DIR_HOST)/bin/iucode_tool +endef + +$(eval $(call HostBuild)) +$(eval $(call BuildPackage,iucode-tool)) diff --git a/target/linux/ar71xx/patches-4.4/910-unaligned_access_hacks.patch b/target/linux/ar71xx/patches-4.4/910-unaligned_access_hacks.patch index 8882b1758..a8d8c15c3 100644 --- a/target/linux/ar71xx/patches-4.4/910-unaligned_access_hacks.patch +++ b/target/linux/ar71xx/patches-4.4/910-unaligned_access_hacks.patch @@ -310,7 +310,7 @@ if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c -@@ -1409,7 +1409,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str +@@ -1410,7 +1410,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str dsfield = ipv6_get_dsfield(ipv6h); if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) diff --git a/target/linux/bcm53xx/Makefile b/target/linux/bcm53xx/Makefile index 30730ea47..2af1c7e71 100644 --- a/target/linux/bcm53xx/Makefile +++ b/target/linux/bcm53xx/Makefile @@ -13,7 +13,7 @@ FEATURES:=squashfs nand usb pci pcie gpio MAINTAINER:=Hauke Mehrtens CPU_TYPE:=cortex-a9 -KERNEL_PATCHVER:=4.9 +KERNEL_PATCHVER:=4.14 define Target/Description Build firmware images for Broadcom based BCM47xx/53xx routers with ARM CPU, *not* MIPS. diff --git a/target/linux/bcm53xx/base-files/etc/diag.sh b/target/linux/bcm53xx/base-files/etc/diag.sh index a8a560cd0..1a9332327 100644 --- a/target/linux/bcm53xx/base-files/etc/diag.sh +++ b/target/linux/bcm53xx/base-files/etc/diag.sh @@ -13,7 +13,7 @@ get_status_led() { fi; # Now just pick any power LED - status_led_file=$(find /sys/class/leds/ -name "*:power:*" | head -n1) + status_led_file=$(find /sys/class/leds/ -name "*:power" | head -n1) if [ -d "$status_led_file" ]; then status_led=$(basename $status_led_file) return diff --git a/target/linux/bcm53xx/base-files/lib/upgrade/platform.sh b/target/linux/bcm53xx/base-files/lib/upgrade/platform.sh index 1a33e3a44..06451f17f 100644 --- a/target/linux/bcm53xx/base-files/lib/upgrade/platform.sh +++ b/target/linux/bcm53xx/base-files/lib/upgrade/platform.sh @@ -274,11 +274,11 @@ platform_pre_upgrade() { platform_trx_from_chk_cmd() { local header_len=$((0x$(get_magic_long_at "$1" 4))) - echo -n dd bs=$header_len skip=1 + echo -n dd skip=$header_len iflag=skip_bytes } platform_trx_from_cybertan_cmd() { - echo -n dd bs=32 skip=1 + echo -n dd skip=32 iflag=skip_bytes } platform_img_from_safeloader() { diff --git a/target/linux/bcm53xx/config-4.14 b/target/linux/bcm53xx/config-4.14 new file mode 100644 index 000000000..38738a468 --- /dev/null +++ b/target/linux/bcm53xx/config-4.14 @@ -0,0 +1,366 @@ +CONFIG_ALIGNMENT_TRAP=y +CONFIG_ARCH_BCM=y +CONFIG_ARCH_BCM_5301X=y +CONFIG_ARCH_BCM_53573=y +CONFIG_ARCH_BCM_IPROC=y +CONFIG_ARCH_CLOCKSOURCE_DATA=y +CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +CONFIG_ARCH_HAS_SET_MEMORY=y +CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y +CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MULTIPLATFORM=y +# CONFIG_ARCH_MULTI_CPU_AUTO is not set +CONFIG_ARCH_MULTI_V6_V7=y +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_NR_GPIO=0 +CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +# CONFIG_ARCH_WANTS_THP_SWAP is not set +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_ARM=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_APPENDED_DTB=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_ATAG_DTB_COMPAT is not set +# CONFIG_ARM_CPU_SUSPEND is not set +CONFIG_ARM_ERRATA_754322=y +CONFIG_ARM_ERRATA_764369=y +CONFIG_ARM_ERRATA_775420=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GLOBAL_TIMER=y +CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_ARM_HEAVY_MB=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_L1_CACHE_SHIFT_6=y +# CONFIG_ARM_LPAE is not set +CONFIG_ARM_PATCH_IDIV=y +CONFIG_ARM_PATCH_PHYS_VIRT=y +# CONFIG_ARM_SP805_WATCHDOG is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_ARM_VIRT_EXT=y +CONFIG_ATAGS=y +CONFIG_AUTO_ZRELADDR=y +CONFIG_BCM47XX_NVRAM=y +CONFIG_BCM47XX_SPROM=y +CONFIG_BCM47XX_WDT=y +CONFIG_BCMA=y +CONFIG_BCMA_BLOCKIO=y +CONFIG_BCMA_DEBUG=y +CONFIG_BCMA_DRIVER_GMAC_CMN=y +CONFIG_BCMA_DRIVER_GPIO=y +CONFIG_BCMA_DRIVER_PCI=y +CONFIG_BCMA_HOST_PCI=y +CONFIG_BCMA_HOST_PCI_POSSIBLE=y +CONFIG_BCMA_HOST_SOC=y +CONFIG_BCMA_SFLASH=y +CONFIG_BCM_NET_PHYLIB=y +CONFIG_BCM_NS_THERMAL=y +CONFIG_BGMAC=y +CONFIG_BGMAC_BCMA=y +# CONFIG_BGMAC_PLATFORM is not set +CONFIG_BLK_MQ_PCI=y +CONFIG_BOUNCE=y +CONFIG_BROADCOM_PHY=y +CONFIG_CACHE_L2X0=y +CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK=y +CONFIG_CLKSRC_MMIO=y +# CONFIG_CLK_BCM_NS2 is not set +CONFIG_CLK_BCM_NSP=y +# CONFIG_CLK_BCM_SR is not set +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_IPROC=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_HAS_ASID=y +# CONFIG_CPU_ICACHE_DISABLE is not set +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_THUMB_CAPABLE=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_V7=y +CONFIG_CRC16=y +CONFIG_CRYPTO_ACOMP2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_NULL2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_BCM_5301X=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_LL=y +CONFIG_DEBUG_LL_INCLUDE="debug/8250.S" +CONFIG_DEBUG_UART_8250=y +# CONFIG_DEBUG_UART_8250_FLOW_CONTROL is not set +CONFIG_DEBUG_UART_8250_SHIFT=0 +CONFIG_DEBUG_UART_PHYS=0x18000300 +CONFIG_DEBUG_UART_VIRT=0xf1000300 +CONFIG_DEBUG_UNCOMPRESS=y +CONFIG_DEBUG_USER=y +# CONFIG_DMA_NOOP_OPS is not set +# CONFIG_DMA_VIRT_OPS is not set +# CONFIG_DRM_LIB_RANDOM is not set +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EXPORTFS=y +CONFIG_EXTCON=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FRAME_POINTER=y +CONFIG_FUTEX_PI=y +# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IO=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_74X164=y +CONFIG_GPIO_SYSFS=y +# CONFIG_GRO_CELLS is not set +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_ARCH_AUDITSYSCALL=y +CONFIG_HAVE_ARCH_BITREVERSE=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_HAVE_ARM_SCU=y +CONFIG_HAVE_ARM_SMCCC=y +CONFIG_HAVE_ARM_TWD=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_DEBUG_KMEMLEAK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_HAVE_EBPF_JIT=y +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_HAVE_NET_DSA=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_OPTPROBES=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_SMP=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_UID16=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HZ_FIXED=0 +CONFIG_HZ_PERIODIC=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IOMMU_HELPER=y +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_WORK=y +CONFIG_LIBFDT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_MDIO_BCM_IPROC is not set +CONFIG_MDIO_BUS=y +# CONFIG_MDIO_BUS_MUX_BCM_IPROC is not set +CONFIG_MDIO_DEVICE=y +CONFIG_MFD_SYSCON=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_MIGHT_HAVE_PCI=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MTD_BCM47XXSFLASH=y +CONFIG_MTD_BCM47XX_PARTS=y +CONFIG_MTD_M25P80=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_BRCMNAND=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_PARSER_TRX=y +# CONFIG_MTD_PHYSMAP_OF is not set +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_SEAMA_FW=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MULTI_IRQ_HANDLER=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NO_BOOTMEM=y +CONFIG_NR_CPUS=2 +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_MDIO=y +CONFIG_OF_NET=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_OF_RESERVED_MEM=y +CONFIG_OLD_SIGACTION=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_PADATA=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PCI=y +CONFIG_PCIE_IPROC=y +CONFIG_PCIE_IPROC_BCMA=y +# CONFIG_PCIE_IPROC_PLATFORM is not set +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +# CONFIG_PHY_BCM_NS_USB2 is not set +# CONFIG_PHY_BCM_NS_USB3 is not set +# CONFIG_PHY_BRCM_SATA is not set +# CONFIG_PHY_NS2_USB_DRD is not set +CONFIG_PINCTRL=y +# CONFIG_PINCTRL_IPROC_GPIO is not set +# CONFIG_PINCTRL_NS2_MUX is not set +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_PL310_ERRATA_753970 is not set +# CONFIG_PL310_ERRATA_769419 is not set +CONFIG_RATIONAL=y +CONFIG_RCU_NEED_SEGCBLIST=y +CONFIG_RCU_STALL_COMMON=y +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +# CONFIG_SCHED_INFO is not set +# CONFIG_SCSI_DMA is not set +CONFIG_SERIAL_8250_FSL=y +# CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_BCM53XX=y +CONFIG_SPI_BITBANG=y +CONFIG_SPI_GPIO=y +CONFIG_SPI_MASTER=y +CONFIG_SRCU=y +CONFIG_SWCONFIG=y +CONFIG_SWCONFIG_B53=y +# CONFIG_SWCONFIG_B53_MMAP_DRIVER is not set +CONFIG_SWCONFIG_B53_PHY_DRIVER=y +CONFIG_SWCONFIG_B53_PHY_FIXUP=y +CONFIG_SWCONFIG_B53_SRAB_DRIVER=y +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SWP_EMULATE=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_OF=y +CONFIG_THIN_ARCHIVES=y +# CONFIG_THUMB2_KERNEL is not set +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +CONFIG_USB_SUPPORT=y +CONFIG_USE_OF=y +CONFIG_VECTORS_BASE=0xffff0000 +# CONFIG_VFP is not set +CONFIG_WATCHDOG_CORE=y +CONFIG_XPS=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y diff --git a/target/linux/bcm53xx/image/Makefile b/target/linux/bcm53xx/image/Makefile index eb136dd37..563a760a6 100644 --- a/target/linux/bcm53xx/image/Makefile +++ b/target/linux/bcm53xx/image/Makefile @@ -59,9 +59,7 @@ define Build/trx endef define Build/trx-serial - $(STAGING_DIR_HOST)/bin/trx \ - -o $@.new \ - -m 33554432 \ + $(STAGING_DIR_HOST)/bin/otrx create $@.new \ -f $(IMAGE_KERNEL) -a 1024 \ -f $@ -a 0x10000 -A $(KDIR)/fs_mark mv $@.new $@ @@ -72,9 +70,7 @@ define Build/trx-nand # if it grows up between releases # root: UBI with one extra block containing UBI mark to trigger erasing # rest of partition - $(STAGING_DIR_HOST)/bin/trx \ - -o $@.new \ - -m 33554432 \ + $(STAGING_DIR_HOST)/bin/otrx create $@.new \ -f $(IMAGE_KERNEL) -a 0x20000 -b 0x400000 \ -f $@ \ -A $(KDIR)/ubi_mark -a 0x20000 @@ -248,13 +244,6 @@ define Device/linksys-ea9500 endef # TARGET_DEVICES += linksys-ea9500 -define Device/phicomm-k3 - DEVICE_TITLE := PHICOMM K3 - DEVICE_PACKAGES := $(BRCMFMAC_4366C0) $(USB3_PACKAGES) + k3wifi + k3screenctrl - IMAGES := trx -endef -TARGET_DEVICES += phicomm-k3 - define Device/netgear IMAGES := chk IMAGE/chk := append-ubi | trx-nand | netgear-chk @@ -314,8 +303,10 @@ define Device/smartrg-sr400ac DEVICE_PACKAGES := $(BRCMFMAC_43602A1) $(USB3_PACKAGES) IMAGES := trx IMAGE/trx := append-rootfs | trx-serial + KERNEL_INITRAMFS_SUFFIX := .bin + KERNEL_INITRAMFS := kernel-bin | append-dtb | lzma-d16 endef -# TARGET_DEVICES += smartrg-sr400ac +TARGET_DEVICES += smartrg-sr400ac define Device/tenda-ac9 DEVICE_TITLE := Tenda AC9 @@ -323,7 +314,7 @@ define Device/tenda-ac9 IMAGES := trx IMAGE/trx := append-rootfs | trx-serial endef -# TARGET_DEVICES += tenda-ac9 +TARGET_DEVICES += tenda-ac9 define Device/tplink-archer-c5-v2 DEVICE_TITLE := TP-LINK Archer C5 V2 @@ -332,7 +323,7 @@ define Device/tplink-archer-c5-v2 IMAGE/bin := append-rootfs | bcm53xx-tplink-safeloader TPLINK_BOARD := ARCHER-C5-V2 endef -# TARGET_DEVICES += tplink-archer-c5-v2 +TARGET_DEVICES += tplink-archer-c5-v2 define Device/tplink-archer-c9-v1 DEVICE_TITLE := TP-LINK Archer C9 V1 @@ -341,6 +332,13 @@ define Device/tplink-archer-c9-v1 IMAGE/bin := append-rootfs | bcm53xx-tplink-safeloader TPLINK_BOARD := ARCHERC9 endef -# TARGET_DEVICES += tplink-archer-c9-v1 +TARGET_DEVICES += tplink-archer-c9-v1 + +define Device/phicomm-k3 + DEVICE_TITLE := PHICOMM K3 + DEVICE_PACKAGES := $(BRCMFMAC_4366C0) $(USB3_PACKAGES) k3wifi k3screenctrl + IMAGES := trx +endef +TARGET_DEVICES += phicomm-k3 $(eval $(call BuildImage)) diff --git a/target/linux/bcm53xx/modules.mk b/target/linux/bcm53xx/modules.mk index ad799b8af..2a3149b37 100644 --- a/target/linux/bcm53xx/modules.mk +++ b/target/linux/bcm53xx/modules.mk @@ -9,7 +9,9 @@ define KernelPackage/phy-bcm-ns-usb2 KCONFIG:=CONFIG_PHY_BCM_NS_USB2 DEPENDS:=@TARGET_bcm53xx SUBMENU:=$(USB_MENU) - FILES:=$(LINUX_DIR)/drivers/phy/phy-bcm-ns-usb2.ko + FILES:=\ + $(LINUX_DIR)/drivers/phy/phy-bcm-ns-usb2.ko@lt4.13 \ + $(LINUX_DIR)/drivers/phy/broadcom/phy-bcm-ns-usb2.ko@gt4.13 AUTOLOAD:=$(call AutoLoad,45,phy-bcm-ns-usb2,1) endef @@ -25,7 +27,9 @@ define KernelPackage/phy-bcm-ns-usb3 KCONFIG:=CONFIG_PHY_BCM_NS_USB3 DEPENDS:=@TARGET_bcm53xx SUBMENU:=$(USB_MENU) - FILES:=$(LINUX_DIR)/drivers/phy/phy-bcm-ns-usb3.ko + FILES:=\ + $(LINUX_DIR)/drivers/phy/phy-bcm-ns-usb3.ko@lt4.13 \ + $(LINUX_DIR)/drivers/phy/broadcom/phy-bcm-ns-usb3.ko@ge4.13 AUTOLOAD:=$(call AutoLoad,45,phy-bcm-ns-usb3,1) endef diff --git a/target/linux/bcm53xx/patches-4.14/035-v4.15-0001-ARM-dts-BCM5301X-Specify-USB-ports-for-USB-LED-of-Lu.patch b/target/linux/bcm53xx/patches-4.14/035-v4.15-0001-ARM-dts-BCM5301X-Specify-USB-ports-for-USB-LED-of-Lu.patch new file mode 100644 index 000000000..3148f6c32 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/035-v4.15-0001-ARM-dts-BCM5301X-Specify-USB-ports-for-USB-LED-of-Lu.patch @@ -0,0 +1,30 @@ +From 2460266f21f140936e627f28f28d1a4f30887ae9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 6 Oct 2017 10:52:35 +0200 +Subject: [PATCH] ARM: dts: BCM5301X: Specify USB ports for USB LED of Luxul + XWR-1200 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This info can be used by operating system to setup LED behavior. + +Reported-by: Dan Haab +Signed-off-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts ++++ b/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts +@@ -57,7 +57,8 @@ + usb { + label = "bcm53xx:green:usb"; + gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>; +- linux,default-trigger = "none"; ++ trigger-sources = <&ohci_port2>, <&ehci_port2>; ++ linux,default-trigger = "usbport"; + }; + + status { diff --git a/target/linux/bcm53xx/patches-4.14/035-v4.15-0002-ARM-dts-BCM5301X-Add-DT-for-Luxul-XBR-4500.patch b/target/linux/bcm53xx/patches-4.14/035-v4.15-0002-ARM-dts-BCM5301X-Add-DT-for-Luxul-XBR-4500.patch new file mode 100644 index 000000000..b0dd01d4e --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/035-v4.15-0002-ARM-dts-BCM5301X-Add-DT-for-Luxul-XBR-4500.patch @@ -0,0 +1,96 @@ +From 1f4b0d5596d2e3ea8e953d578ab8444ce860d35d Mon Sep 17 00:00:00 2001 +From: Dan Haab +Date: Mon, 9 Oct 2017 09:46:22 -0600 +Subject: [PATCH] ARM: dts: BCM5301X: Add DT for Luxul XBR-4500 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is BCM47094 (AKA BCM4709C0) based router with ports-on-the-front +board design. + +Signed-off-by: Dan Haab +Acked-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts | 63 +++++++++++++++++++++++++++ + 2 files changed, 64 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -101,6 +101,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm4709-tplink-archer-c9-v1.dtb \ + bcm47094-dlink-dir-885l.dtb \ + bcm47094-linksys-panamera.dtb \ ++ bcm47094-luxul-xbr-4500.dtb \ + bcm47094-luxul-xwr-3100.dtb \ + bcm47094-netgear-r8500.dtb \ + bcm94708.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts +@@ -0,0 +1,63 @@ ++/* ++ * Copyright (C) 2017 Luxul Inc. ++ * ++ * Licensed under the ISC license. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm4708.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" ++ ++/ { ++ compatible = "luxul,xbr-4500-v1", "brcm,bcm47094", "brcm,bcm4708"; ++ model = "Luxul XBR-4500 V1"; ++ ++ chosen { ++ bootargs = "earlycon"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x18000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ status { ++ label = "bcm53xx:green:status"; ++ gpios = <&chipcommon 20 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "timer"; ++ }; ++ ++ usb3 { ++ label = "bcm53xx:green:usb3"; ++ gpios = <&chipcommon 19 GPIO_ACTIVE_HIGH>; ++ trigger-sources = <&ohci_port1>, <&ehci_port1>, ++ <&xhci_port1>; ++ linux,default-trigger = "usbport"; ++ }; ++ ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ restart { ++ label = "Reset"; ++ linux,code = ; ++ gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&usb3 { ++ vcc-gpio = <&chipcommon 18 GPIO_ACTIVE_HIGH>; ++}; ++ ++&spi_nor { ++ status = "okay"; ++}; diff --git a/target/linux/bcm53xx/patches-4.14/035-v4.15-0003-ARM-dts-BCM5301X-Add-DT-for-Luxul-ABR-4500.patch b/target/linux/bcm53xx/patches-4.14/035-v4.15-0003-ARM-dts-BCM5301X-Add-DT-for-Luxul-ABR-4500.patch new file mode 100644 index 000000000..76bc739dd --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/035-v4.15-0003-ARM-dts-BCM5301X-Add-DT-for-Luxul-ABR-4500.patch @@ -0,0 +1,96 @@ +From 65f78c4c41a9b9a7637e1dda2d5e41cf26ea971c Mon Sep 17 00:00:00 2001 +From: Dan Haab +Date: Mon, 9 Oct 2017 09:46:23 -0600 +Subject: [PATCH] ARM: dts: BCM5301X: Add DT for Luxul ABR-4500 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is BCM47094 (AKA BCM4709C0) based router with rear-facing ports +board design. + +Signed-off-by: Dan Haab +Acked-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts | 63 +++++++++++++++++++++++++++ + 2 files changed, 64 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -101,6 +101,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm4709-tplink-archer-c9-v1.dtb \ + bcm47094-dlink-dir-885l.dtb \ + bcm47094-linksys-panamera.dtb \ ++ bcm47094-luxul-abr-4500.dtb \ + bcm47094-luxul-xbr-4500.dtb \ + bcm47094-luxul-xwr-3100.dtb \ + bcm47094-netgear-r8500.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts +@@ -0,0 +1,63 @@ ++/* ++ * Copyright (C) 2017 Luxul Inc. ++ * ++ * Licensed under the ISC license. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm4708.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" ++ ++/ { ++ compatible = "luxul,abr-4500-v1", "brcm,bcm47094", "brcm,bcm4708"; ++ model = "Luxul ABR-4500 V1"; ++ ++ chosen { ++ bootargs = "earlycon"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x18000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ status { ++ label = "bcm53xx:green:status"; ++ gpios = <&chipcommon 20 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "timer"; ++ }; ++ ++ usb3 { ++ label = "bcm53xx:green:usb3"; ++ gpios = <&chipcommon 19 GPIO_ACTIVE_LOW>; ++ trigger-sources = <&ohci_port1>, <&ehci_port1>, ++ <&xhci_port1>; ++ linux,default-trigger = "usbport"; ++ }; ++ ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ restart { ++ label = "Reset"; ++ linux,code = ; ++ gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&usb3 { ++ vcc-gpio = <&chipcommon 18 GPIO_ACTIVE_HIGH>; ++}; ++ ++&spi_nor { ++ status = "okay"; ++}; diff --git a/target/linux/bcm53xx/patches-4.14/035-v4.15-0004-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-810.patch b/target/linux/bcm53xx/patches-4.14/035-v4.15-0004-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-810.patch new file mode 100644 index 000000000..5cb894c36 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/035-v4.15-0004-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-810.patch @@ -0,0 +1,120 @@ +From 0aa052ce1c3340850a7e5980b6d24b3ea5779591 Mon Sep 17 00:00:00 2001 +From: Dan Haab +Date: Mon, 9 Oct 2017 09:46:59 -0600 +Subject: [PATCH] ARM: dts: BCM53573: Add DT for Luxul XAP-810 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is BCM53573 WiSoC based access point with an extra BCM43217 chipset +used for 2.4 GHz. + +Signed-off-by: Dan Haab +Acked-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm47189-luxul-xap-810.dts | 87 ++++++++++++++++++++++++++++ + 2 files changed, 88 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm47189-luxul-xap-810.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -111,6 +111,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm953012hr.dtb \ + bcm953012k.dtb + dtb-$(CONFIG_ARCH_BCM_53573) += \ ++ bcm47189-luxul-xap-810.dtb \ + bcm47189-tenda-ac9.dtb \ + bcm947189acdbmr.dtb + dtb-$(CONFIG_ARCH_BCM_63XX) += \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts +@@ -0,0 +1,87 @@ ++/* ++ * Copyright 2017 Luxul Inc. ++ * ++ * Licensed under the ISC license. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm53573.dtsi" ++ ++/ { ++ compatible = "luxul,xap-810-v1", "brcm,bcm47189", "brcm,bcm53573"; ++ model = "Luxul XAP-810 V1"; ++ ++ chosen { ++ bootargs = "earlycon"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ 5ghz { ++ label = "bcm53xx:blue:5ghz"; ++ gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ system { ++ label = "bcm53xx:green:system"; ++ gpios = <&chipcommon 15 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "timer"; ++ }; ++ }; ++ ++ pcie0_leds { ++ compatible = "gpio-leds"; ++ ++ 2ghz { ++ label = "bcm53xx:blue:2ghz"; ++ gpios = <&pcie0_chipcommon 3 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ restart { ++ label = "Reset"; ++ linux,code = ; ++ gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&pcie0 { ++ ranges = <0x00000000 0 0 0 0 0x00100000>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ++ bridge@0,0,0 { ++ reg = <0x0000 0 0 0 0>; ++ ranges = <0x00000000 0 0 0 0 0 0 0x00100000>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ++ wifi@0,1,0 { ++ reg = <0x0000 0 0 0 0>; ++ ranges = <0x00000000 0 0 0 0x00100000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ pcie0_chipcommon: chipcommon@0 { ++ reg = <0 0x1000>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-4.14/035-v4.15-0005-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-1440.patch b/target/linux/bcm53xx/patches-4.14/035-v4.15-0005-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-1440.patch new file mode 100644 index 000000000..9d43dd58d --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/035-v4.15-0005-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-1440.patch @@ -0,0 +1,83 @@ +From 7030ea600d560026b91726f2eb79c856b813afa9 Mon Sep 17 00:00:00 2001 +From: Dan Haab +Date: Mon, 9 Oct 2017 09:47:00 -0600 +Subject: [PATCH] ARM: dts: BCM53573: Add DT for Luxul XAP-1440 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is BCM53573 WiSoC based outdoor access point with an extra BCM43217 +chipset used for 2.4 GHz. + +Signed-off-by: Dan Haab +Acked-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts | 50 +++++++++++++++++++++++++++ + 2 files changed, 51 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -111,6 +111,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm953012hr.dtb \ + bcm953012k.dtb + dtb-$(CONFIG_ARCH_BCM_53573) += \ ++ bcm47189-luxul-xap-1440.dtb \ + bcm47189-luxul-xap-810.dtb \ + bcm47189-tenda-ac9.dtb \ + bcm947189acdbmr.dtb +--- /dev/null ++++ b/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts +@@ -0,0 +1,50 @@ ++/* ++ * Copyright 2017 Luxul Inc. ++ * ++ * Licensed under the ISC license. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm53573.dtsi" ++ ++/ { ++ compatible = "luxul,xap-1440-v1", "brcm,bcm47189", "brcm,bcm53573"; ++ model = "Luxul XAP-1440 V1"; ++ ++ chosen { ++ bootargs = "earlycon"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ wlan { ++ label = "bcm53xx:blue:wlan"; ++ gpios = <&chipcommon 10 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ system { ++ label = "bcm53xx:green:system"; ++ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "timer"; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ restart { ++ label = "Reset"; ++ linux,code = ; ++ gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-4.14/036-0001-ARM-dts-BCM5301X-Add-basic-DT-for-PHICOMM-K3.patch b/target/linux/bcm53xx/patches-4.14/036-0001-ARM-dts-BCM5301X-Add-basic-DT-for-PHICOMM-K3.patch new file mode 100644 index 000000000..1fc6c0442 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/036-0001-ARM-dts-BCM5301X-Add-basic-DT-for-PHICOMM-K3.patch @@ -0,0 +1,50 @@ +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -105,6 +105,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm47094-luxul-xbr-4500.dtb \ + bcm47094-luxul-xwr-3100.dtb \ + bcm47094-netgear-r8500.dtb \ ++ bcm47094-phicomm-k3.dtb \ + bcm94708.dtb \ + bcm94709.dtb \ + bcm953012er.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm47094-phicomm-k3.dts +@@ -0,0 +1,37 @@ ++/* ++* Copyright (C) 2017 Hamster Tian ++*/ ++ ++/dts-v1/; ++ ++#include "bcm47094.dtsi" ++#include "bcm5301x-nand-cs0-bch4.dtsi" ++ ++/ { ++ compatible = "phicomm,k3", "brcm,bcm47094", "brcm,bcm4708"; ++ model = "PHICOMM K3"; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200"; ++ }; ++ memory { ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x18000000>; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ restart { ++ label = "Reset"; ++ linux,code = ; ++ gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; diff --git a/target/linux/bcm53xx/patches-4.14/080-spi-bcm53xx-simplify-reading-SPI-data.patch b/target/linux/bcm53xx/patches-4.14/080-spi-bcm53xx-simplify-reading-SPI-data.patch new file mode 100644 index 000000000..ee377c491 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/080-spi-bcm53xx-simplify-reading-SPI-data.patch @@ -0,0 +1,107 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 29 Dec 2017 14:44:09 +0100 +Subject: [PATCH] spi: bcm53xx: simplify reading SPI data +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit makes transfer function use spi_transfer_is_last to +determine if currently processed transfer is the last one. Thanks to +that we finally set hardware registers properly and it makes controller +behave the way it's expected to. + +This allows simplifying read function which can now simply start reading +from the slot 0 instead of the last saved offset. It has been +successfully tested using spi_write_then_read. + +Moreover this change fixes handling messages with two writing transfers. +It's important for SPI flash devices as their drivers commonly use one +transfer for a command and another one for data. + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +--- + drivers/spi/spi-bcm53xx.c | 26 ++++++++++---------------- + 1 file changed, 10 insertions(+), 16 deletions(-) + +--- a/drivers/spi/spi-bcm53xx.c ++++ b/drivers/spi/spi-bcm53xx.c +@@ -27,8 +27,6 @@ struct bcm53xxspi { + struct bcma_device *core; + struct spi_master *master; + void __iomem *mmio_base; +- +- size_t read_offset; + bool bspi; /* Boot SPI mode with memory mapping */ + }; + +@@ -172,8 +170,6 @@ static void bcm53xxspi_buf_write(struct + + if (!cont) + bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); +- +- b53spi->read_offset = len; + } + + static void bcm53xxspi_buf_read(struct bcm53xxspi *b53spi, u8 *r_buf, +@@ -182,10 +178,10 @@ static void bcm53xxspi_buf_read(struct b + u32 tmp; + int i; + +- for (i = 0; i < b53spi->read_offset + len; i++) { ++ for (i = 0; i < len; i++) { + tmp = B53SPI_CDRAM_CONT | B53SPI_CDRAM_PCS_DISABLE_ALL | + B53SPI_CDRAM_PCS_DSCK; +- if (!cont && i == b53spi->read_offset + len - 1) ++ if (!cont && i == len - 1) + tmp &= ~B53SPI_CDRAM_CONT; + tmp &= ~0x1; + /* Command Register File */ +@@ -194,8 +190,7 @@ static void bcm53xxspi_buf_read(struct b + + /* Set queue pointers */ + bcm53xxspi_write(b53spi, B53SPI_MSPI_NEWQP, 0); +- bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, +- b53spi->read_offset + len - 1); ++ bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, len - 1); + + if (cont) + bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 1); +@@ -214,13 +209,11 @@ static void bcm53xxspi_buf_read(struct b + bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); + + for (i = 0; i < len; ++i) { +- int offset = b53spi->read_offset + i; ++ u16 reg = B53SPI_MSPI_RXRAM + 4 * (1 + i * 2); + + /* Data stored in the transmit register file LSB */ +- r_buf[i] = (u8)bcm53xxspi_read(b53spi, B53SPI_MSPI_RXRAM + 4 * (1 + offset * 2)); ++ r_buf[i] = (u8)bcm53xxspi_read(b53spi, reg); + } +- +- b53spi->read_offset = 0; + } + + static int bcm53xxspi_transfer_one(struct spi_master *master, +@@ -238,7 +231,8 @@ static int bcm53xxspi_transfer_one(struc + left = t->len; + while (left) { + size_t to_write = min_t(size_t, 16, left); +- bool cont = left - to_write > 0; ++ bool cont = !spi_transfer_is_last(master, t) || ++ left - to_write > 0; + + bcm53xxspi_buf_write(b53spi, buf, to_write, cont); + left -= to_write; +@@ -250,9 +244,9 @@ static int bcm53xxspi_transfer_one(struc + buf = (u8 *)t->rx_buf; + left = t->len; + while (left) { +- size_t to_read = min_t(size_t, 16 - b53spi->read_offset, +- left); +- bool cont = left - to_read > 0; ++ size_t to_read = min_t(size_t, 16, left); ++ bool cont = !spi_transfer_is_last(master, t) || ++ left - to_read > 0; + + bcm53xxspi_buf_read(b53spi, buf, to_read, cont); + left -= to_read; diff --git a/target/linux/bcm53xx/patches-4.14/130-ARM-dts-BCM5301X-add-missing-LEDs-for-Buffalo-WZR-90.patch b/target/linux/bcm53xx/patches-4.14/130-ARM-dts-BCM5301X-add-missing-LEDs-for-Buffalo-WZR-90.patch new file mode 100644 index 000000000..cd691f78f --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/130-ARM-dts-BCM5301X-add-missing-LEDs-for-Buffalo-WZR-90.patch @@ -0,0 +1,95 @@ +From c830b958f52fc666919439d6f8f6caa8b6844d44 Mon Sep 17 00:00:00 2001 +From: INAGAKI Hiroshi +Date: Wed, 7 Mar 2018 20:33:56 +0900 +Subject: [PATCH] ARM: dts: BCM5301X: add missing LEDs for Buffalo WZR-900DHP +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Buffalo WZR-900DHP has 8 LEDs, but there is not LED definitions in the +dts and cannot configure these LEDs. +I Added missing LED definitions for WZR-900DHP. + +Signed-off-by: INAGAKI Hiroshi +Reviewed-by: RafaÅ‚ MiÅ‚ecki +--- + arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts | 68 +++++++++++++++++++++++ + 1 file changed, 68 insertions(+) + +--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts ++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts +@@ -35,6 +35,74 @@ + 0x88000000 0x08000000>; + }; + ++ spi { ++ compatible = "spi-gpio"; ++ num-chipselects = <1>; ++ gpio-sck = <&chipcommon 7 0>; ++ gpio-mosi = <&chipcommon 4 0>; ++ cs-gpios = <&chipcommon 6 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hc595: gpio_spi@0 { ++ compatible = "fairchild,74hc595"; ++ reg = <0>; ++ registers-number = <1>; ++ spi-max-frequency = <100000>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ usb { ++ label = "bcm53xx:green:usb"; ++ gpios = <&hc595 0 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ power0 { ++ label = "bcm53xx:green:power"; ++ gpios = <&hc595 1 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-on"; ++ }; ++ ++ power1 { ++ label = "bcm53xx:red:power"; ++ gpios = <&hc595 2 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ router0 { ++ label = "bcm53xx:green:router"; ++ gpios = <&hc595 3 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-on"; ++ }; ++ ++ router1 { ++ label = "bcm53xx:amber:router"; ++ gpios = <&hc595 4 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ wan { ++ label = "bcm53xx:green:wan"; ++ gpios = <&hc595 5 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-on"; ++ }; ++ ++ wireless0 { ++ label = "bcm53xx:green:wireless"; ++ gpios = <&hc595 6 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ wireless1 { ++ label = "bcm53xx:amber:wireless"; ++ gpios = <&hc595 7 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ + gpio-keys { + compatible = "gpio-keys"; + #address-cells = <1>; diff --git a/target/linux/bcm53xx/patches-4.14/180-usb-xhci-add-support-for-performing-fake-doorbell.patch b/target/linux/bcm53xx/patches-4.14/180-usb-xhci-add-support-for-performing-fake-doorbell.patch new file mode 100644 index 000000000..9f58370a1 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/180-usb-xhci-add-support-for-performing-fake-doorbell.patch @@ -0,0 +1,137 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Sat, 1 Oct 2016 22:54:48 +0200 +Subject: [PATCH] usb: xhci: add support for performing fake doorbell + +Broadcom's Northstar XHCI controllers seem to need a special start +procedure to work correctly. There isn't any official documentation of +this, the problem is that controller doesn't detect any connected +devices with default setup. Moreover connecting USB device to controller +that doesn't run properly can cause SoC's watchdog issues. + +A workaround that was successfully tested on multiple devices is to +perform a fake doorbell. This patch adds code for doing this and enables +it on BCM4708 family. +--- + drivers/usb/host/xhci-plat.c | 6 +++++ + drivers/usb/host/xhci.c | 63 +++++++++++++++++++++++++++++++++++++++++--- + drivers/usb/host/xhci.h | 1 + + 3 files changed, 67 insertions(+), 3 deletions(-) + +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -67,12 +67,18 @@ static int xhci_priv_resume_quirk(struct + + static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) + { ++ struct platform_device *pdev = to_platform_device(dev); ++ struct device_node *node = pdev->dev.of_node; ++ + /* + * As of now platform drivers don't provide MSI support so we ensure + * here that the generic code does not try to make a pci_dev from our + * dev struct in order to setup MSI + */ + xhci->quirks |= XHCI_PLAT; ++ ++ if (node && of_machine_is_compatible("brcm,bcm4708")) ++ xhci->quirks |= XHCI_FAKE_DOORBELL; + } + + /* called during probe() after chip reset completes */ +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -153,6 +153,49 @@ int xhci_start(struct xhci_hcd *xhci) + return ret; + } + ++/** ++ * xhci_fake_doorbell - Perform a fake doorbell on a specified slot ++ * ++ * Some controllers require a fake doorbell to start correctly. Without that ++ * they simply don't detect any devices. ++ */ ++static int xhci_fake_doorbell(struct xhci_hcd *xhci, int slot_id) ++{ ++ u32 temp; ++ ++ /* Alloc a virt device for that slot */ ++ if (!xhci_alloc_virt_device(xhci, slot_id, NULL, GFP_NOIO)) { ++ xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n"); ++ return -ENOMEM; ++ } ++ ++ /* Ring fake doorbell for slot_id ep 0 */ ++ xhci_ring_ep_doorbell(xhci, slot_id, 0, 0); ++ usleep_range(1000, 1500); ++ ++ /* Read the status to check if HSE is set or not */ ++ temp = readl(&xhci->op_regs->status); ++ ++ /* Clear HSE if set */ ++ if (temp & STS_FATAL) { ++ xhci_dbg(xhci, "HSE problem detected, status: 0x%08x\n", temp); ++ temp &= ~0x1fff; ++ temp |= STS_FATAL; ++ writel(temp, &xhci->op_regs->status); ++ usleep_range(1000, 1500); ++ readl(&xhci->op_regs->status); ++ } ++ ++ /* Free virt device */ ++ xhci_free_virt_device(xhci, slot_id); ++ ++ /* We're done if controller is already running */ ++ if (readl(&xhci->op_regs->command) & CMD_RUN) ++ return 0; ++ ++ return xhci_start(xhci); ++} ++ + /* + * Reset a halted HC. + * +@@ -536,10 +579,20 @@ static int xhci_init(struct usb_hcd *hcd + + static int xhci_run_finished(struct xhci_hcd *xhci) + { +- if (xhci_start(xhci)) { +- xhci_halt(xhci); +- return -ENODEV; ++ int err; ++ ++ err = xhci_start(xhci); ++ if (err) { ++ err = -ENODEV; ++ goto err_halt; + } ++ ++ if (xhci->quirks & XHCI_FAKE_DOORBELL) { ++ err = xhci_fake_doorbell(xhci, 1); ++ if (err) ++ goto err_halt; ++ } ++ + xhci->shared_hcd->state = HC_STATE_RUNNING; + xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; + +@@ -549,6 +602,10 @@ static int xhci_run_finished(struct xhci + xhci_dbg_trace(xhci, trace_xhci_dbg_init, + "Finished xhci_run for USB3 roothub"); + return 0; ++ ++err_halt: ++ xhci_halt(xhci); ++ return err; + } + + /* +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1831,6 +1831,7 @@ struct xhci_hcd { + #define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26) + /* Reserved. It was XHCI_U2_DISABLE_WAKE */ + #define XHCI_ASMEDIA_MODIFY_FLOWCONTROL (1 << 28) ++#define XHCI_FAKE_DOORBELL (1 << 29) + #define XHCI_SUSPEND_DELAY (1 << 30) + + unsigned int num_active_eps; diff --git a/target/linux/bcm53xx/patches-4.14/300-ARM-BCM5301X-Disable-MMU-and-Dcache-during-decompres.patch b/target/linux/bcm53xx/patches-4.14/300-ARM-BCM5301X-Disable-MMU-and-Dcache-during-decompres.patch new file mode 100644 index 000000000..ef91db901 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/300-ARM-BCM5301X-Disable-MMU-and-Dcache-during-decompres.patch @@ -0,0 +1,101 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Wed, 24 Sep 2014 22:14:07 +0200 +Subject: [PATCH] ARM: BCM5301X: Disable MMU and Dcache during decompression +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Broadcom devices have broken CFE (bootloader) that leaves hardware in an +invalid state. It causes problems with booting Linux. On Northstar +devices kernel was randomly hanging in ~25% of tries during early init. +Hangs used to happen at random places in the start_kernel. On BCM53573 +kernel doesn't even seem to start booting. + +To workaround this problem we need to do following very early: +1) Clear 2 following bits in the SCTLR register: +#define CR_M (1 << 0) /* MMU enable */ +#define CR_C (1 << 2) /* Dcache enable */ +2) Flush the whole D-cache +3) Disable L2 cache + +Unfortunately this patch is not upstreamable as it does above things +unconditionally. We can't check if we are running on Broadcom platform +in any safe way and doing such hacks with ARCH_MULTI_V7 is unacceptable +as it could break other devices support. + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +--- + +--- a/arch/arm/boot/compressed/Makefile ++++ b/arch/arm/boot/compressed/Makefile +@@ -32,6 +32,11 @@ ifeq ($(CONFIG_ARCH_ACORN),y) + OBJS += ll_char_wr.o font.o + endif + ++ifeq ($(CONFIG_ARCH_BCM_5301X),y) ++OBJS += head-bcm_5301x-mpcore.o ++OBJS += cache-v7-min.o ++endif ++ + ifeq ($(CONFIG_ARCH_SA1100),y) + OBJS += head-sa1100.o + endif +--- /dev/null ++++ b/arch/arm/boot/compressed/head-bcm_5301x-mpcore.S +@@ -0,0 +1,37 @@ ++/* ++ * ++ * Platform specific tweaks. This is merged into head.S by the linker. ++ * ++ */ ++ ++#include ++#include ++#include ++ ++ .section ".start", "ax" ++ ++/* ++ * This code section is spliced into the head code by the linker ++ */ ++ ++__plat_uncompress_start: ++ ++ @ Preserve r8/r7 i.e. kernel entry values ++ mov r12, r8 ++ ++ @ Clear MMU enable and Dcache enable bits ++ mrc p15, 0, r0, c1, c0, 0 @ Read SCTLR ++ bic r0, #CR_C|CR_M ++ mcr p15, 0, r0, c1, c0, 0 @ Write SCTLR ++ nop ++ ++ @ Call the cache invalidation routine ++ bl v7_flush_dcache_all ++ nop ++ mov r0,#0 ++ ldr r3, =0x19022000 @ L2 cache controller, control reg ++ str r0, [r3, #0x100] @ Disable L2 cache ++ nop ++ ++ @ Restore ++ mov r8, r12 +--- a/arch/arm/boot/compressed/cache-v7-min.S ++++ b/arch/arm/boot/compressed/cache-v7-min.S +@@ -12,6 +12,7 @@ + + #include + #include ++#include + + __INIT + +@@ -63,7 +64,7 @@ loop2: + ARM( orr r11, r11, r9, lsl r2 ) @ factor index number into r11 + THUMB( lsl r6, r9, r2 ) + THUMB( orr r11, r11, r6 ) @ factor index number into r11 +- mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way ++ mcr p15, 0, r11, c7, c6, 2 @ clean & invalidate by set/way + subs r9, r9, #1 @ decrement the index + bge loop2 + subs r4, r4, #1 @ decrement the way diff --git a/target/linux/bcm53xx/patches-4.14/310-ARM-BCM5301X-Add-DT-for-Netgear-R7900.patch b/target/linux/bcm53xx/patches-4.14/310-ARM-BCM5301X-Add-DT-for-Netgear-R7900.patch new file mode 100644 index 000000000..5092817f0 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/310-ARM-BCM5301X-Add-DT-for-Netgear-R7900.patch @@ -0,0 +1,64 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] ARM: BCM5301X: Add DT for Netgear R7900 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +--- + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -97,6 +97,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm4709-buffalo-wxr-1900dhp.dtb \ + bcm4709-linksys-ea9200.dtb \ + bcm4709-netgear-r7000.dtb \ ++ bcm4709-netgear-r7900.dtb \ + bcm4709-netgear-r8000.dtb \ + bcm4709-tplink-archer-c9-v1.dtb \ + bcm47094-dlink-dir-885l.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm4709-netgear-r7900.dts +@@ -0,0 +1,42 @@ ++/* ++ * Broadcom BCM470X / BCM5301X ARM platform code. ++ * DTS for Netgear R7900 ++ * ++ * Copyright (C) 2016 RafaÅ‚ MiÅ‚ecki ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm4709.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" ++ ++/ { ++ compatible = "netgear,r7900", "brcm,bcm4709", "brcm,bcm4708"; ++ model = "Netgear R7900"; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x08000000>; ++ }; ++ ++ axi@18000000 { ++ usb3@23000 { ++ reg = <0x00023000 0x1000>; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; diff --git a/target/linux/bcm53xx/patches-4.14/311-ARM-BCM5301X-Add-power-button-for-Buffalo-WZR-1750DHP.patch b/target/linux/bcm53xx/patches-4.14/311-ARM-BCM5301X-Add-power-button-for-Buffalo-WZR-1750DHP.patch new file mode 100644 index 000000000..39034997f --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/311-ARM-BCM5301X-Add-power-button-for-Buffalo-WZR-1750DHP.patch @@ -0,0 +1,20 @@ +From: Felix Fietkau +Subject: [PATCH] ARM: BCM5301X: Add power button for Buffalo WZR-1750DHP + +Signed-off-by: Felix Fietkau +--- +--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts ++++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts +@@ -102,6 +102,12 @@ + #address-cells = <1>; + #size-cells = <0>; + ++ power { ++ label = "Power"; ++ linux,code = ; ++ gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>; ++ }; ++ + restart { + label = "Reset"; + linux,code = ; diff --git a/target/linux/bcm53xx/patches-4.14/320-ARM-dts-BCM5301X-Add-serial-to-the-bootargs.patch b/target/linux/bcm53xx/patches-4.14/320-ARM-dts-BCM5301X-Add-serial-to-the-bootargs.patch new file mode 100644 index 000000000..710d94f6b --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/320-ARM-dts-BCM5301X-Add-serial-to-the-bootargs.patch @@ -0,0 +1,70 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] ARM: dts: BCM5301X: Add serial= to the bootargs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It's enough to have proper stdout-path for getting serial working but +for some reason LEDE doesn't offer "Please press Enter to activate this +console." unless ttyS0 is specified. + +This is a workaround to get serial working in LEDE. + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +--- + +--- a/arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts ++++ b/arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts +@@ -13,7 +13,7 @@ + model = "TP-LINK Archer C5 V2"; + + chosen { +- bootargs = "earlycon"; ++ bootargs = "console=ttyS0,115200 earlycon"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts ++++ b/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts +@@ -14,7 +14,7 @@ + model = "Luxul ABR-4500 V1"; + + chosen { +- bootargs = "earlycon"; ++ bootargs = "console=ttyS0,115200 earlycon"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts ++++ b/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts +@@ -14,7 +14,7 @@ + model = "Luxul XBR-4500 V1"; + + chosen { +- bootargs = "earlycon"; ++ bootargs = "console=ttyS0,115200 earlycon"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts ++++ b/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts +@@ -13,7 +13,7 @@ + model = "Luxul XAP-1440 V1"; + + chosen { +- bootargs = "earlycon"; ++ bootargs = "console=ttyS0,115200 earlycon"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts ++++ b/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts +@@ -13,7 +13,7 @@ + model = "Luxul XAP-810 V1"; + + chosen { +- bootargs = "earlycon"; ++ bootargs = "console=ttyS0,115200 earlycon"; + }; + + memory { diff --git a/target/linux/bcm53xx/patches-4.14/390-Revert-ARM-dts-BCM5301X-convert-to-iProc-QSPI.patch b/target/linux/bcm53xx/patches-4.14/390-Revert-ARM-dts-BCM5301X-convert-to-iProc-QSPI.patch new file mode 100644 index 000000000..6180c88e5 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/390-Revert-ARM-dts-BCM5301X-convert-to-iProc-QSPI.patch @@ -0,0 +1,110 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 29 Dec 2017 20:26:51 +0100 +Subject: [PATCH] Revert "ARM: dts: BCM5301X: convert to iProc QSPI" + +This reverts commit 1c8f4065072387d3b6ee7adcf0dbe3c7ba80c268. + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +--- + +--- a/arch/arm/boot/dts/bcm5301x.dtsi ++++ b/arch/arm/boot/dts/bcm5301x.dtsi +@@ -337,6 +337,20 @@ + }; + }; + ++ spi@29000 { ++ reg = <0x00029000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spi_nor: spi-nor@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <20000000>; ++ linux,part-probe = "ofpart", "bcm47xxpart"; ++ status = "disabled"; ++ }; ++ }; ++ + gmac0: ethernet@24000 { + reg = <0x24000 0x800>; + }; +@@ -425,42 +439,6 @@ + brcm,nand-has-wp; + }; + +- spi@18029200 { +- compatible = "brcm,spi-bcm-qspi", "brcm,spi-nsp-qspi"; +- reg = <0x18029200 0x184>, +- <0x18029000 0x124>, +- <0x1811b408 0x004>, +- <0x180293a0 0x01c>; +- reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg"; +- interrupts = , +- , +- , +- , +- , +- , +- ; +- interrupt-names = "spi_lr_fullness_reached", +- "spi_lr_session_aborted", +- "spi_lr_impatient", +- "spi_lr_session_done", +- "spi_lr_overhead", +- "mspi_done", +- "mspi_halted"; +- clocks = <&iprocmed>; +- clock-names = "iprocmed"; +- num-cs = <2>; +- #address-cells = <1>; +- #size-cells = <0>; +- +- spi_nor: spi-nor@0 { +- compatible = "jedec,spi-nor"; +- reg = <0>; +- spi-max-frequency = <20000000>; +- linux,part-probe = "ofpart", "bcm47xxpart"; +- status = "disabled"; +- }; +- }; +- + thermal-zones { + cpu_thermal: cpu-thermal { + polling-delay-passive = <0>; +--- a/arch/arm/boot/dts/bcm953012k.dts ++++ b/arch/arm/boot/dts/bcm953012k.dts +@@ -80,32 +80,6 @@ + }; + }; + +-&spi_nor { +- status = "okay"; +- spi-max-frequency = <62500000>; +- m25p,default-addr-width = <3>; +- +- #address-cells = <1>; +- #size-cells = <1>; +- +- partition@0 { +- label = "boot"; +- reg = <0x00000000 0x000d0000>; +- }; +- partition@d000 { +- label = "env"; +- reg = <0x000d0000 0x00030000>; +- }; +- partition@100000 { +- label = "system"; +- reg = <0x00100000 0x00600000>; +- }; +- partition@700000 { +- label = "rootfs"; +- reg = <0x00700000 0x00900000>; +- }; +-}; +- + &uart0 { + status = "okay"; + }; diff --git a/target/linux/bcm53xx/patches-4.14/400-mtd-spi-nor-detect-JEDEC-incompatible-w25q128-using-.patch b/target/linux/bcm53xx/patches-4.14/400-mtd-spi-nor-detect-JEDEC-incompatible-w25q128-using-.patch new file mode 100644 index 000000000..75105261a --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/400-mtd-spi-nor-detect-JEDEC-incompatible-w25q128-using-.patch @@ -0,0 +1,34 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] mtd: spi-nor: detect JEDEC incompatible w25q128 using 0x90 + command +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some w25q128 chipsets don't support RDID (0x9f) command, they reply with +0xff-s only. To suppose such flashes fallback to the 0x90 command. + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +--- + +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -1205,6 +1205,18 @@ static const struct flash_info *spi_nor_ + } + dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n", + id[0], id[1], id[2]); ++ ++ tmp = nor->read_reg(nor, 0x90, id, SPI_NOR_MAX_ID_LEN); ++ if (tmp < 0) { ++ dev_dbg(nor->dev, " error %d reading JEDEC ID\n", tmp); ++ return ERR_PTR(tmp); ++ } ++ dev_info(nor->dev, "using Read Manufacturer / Device ID command (0x%02x) returned %02x %02x\n", ++ 0x90, id[0x03], id[0x04]); ++ if (id[0x03] == 0xef && id[0x04] == 0x17) { ++ return spi_nor_match_id("w25q128"); ++ } ++ + return ERR_PTR(-ENODEV); + } + diff --git a/target/linux/bcm53xx/patches-4.14/410-Use-brcm-bcm947xx-cfe-partitions-binding-for-Broadco.patch b/target/linux/bcm53xx/patches-4.14/410-Use-brcm-bcm947xx-cfe-partitions-binding-for-Broadco.patch new file mode 100644 index 000000000..0eae14ff9 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/410-Use-brcm-bcm947xx-cfe-partitions-binding-for-Broadco.patch @@ -0,0 +1,53 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] Use "brcm,bcm947xx-cfe-partitions" binding for Broadcom + partitions + +--- + +--- a/arch/arm/boot/dts/bcm5301x-nand-cs0.dtsi ++++ b/arch/arm/boot/dts/bcm5301x-nand-cs0.dtsi +@@ -13,6 +13,10 @@ + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; ++ ++ partitions { ++ compatible = "brcm,bcm947xx-cfe-partitions"; ++ }; + }; + }; + }; +--- a/arch/arm/boot/dts/bcm5301x.dtsi ++++ b/arch/arm/boot/dts/bcm5301x.dtsi +@@ -346,8 +346,11 @@ + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <20000000>; +- linux,part-probe = "ofpart", "bcm47xxpart"; + status = "disabled"; ++ ++ partitions { ++ compatible = "brcm,bcm947xx-cfe-partitions"; ++ }; + }; + }; + +--- a/drivers/mtd/bcm47xxpart.c ++++ b/drivers/mtd/bcm47xxpart.c +@@ -300,9 +300,16 @@ static int bcm47xxpart_parse(struct mtd_ + return curr_part; + }; + ++static const struct of_device_id bcm47xxpart_of_match_table[] = { ++ { .compatible = "brcm,bcm947xx-cfe-partitions" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, bcm47xxpart_of_match_table); ++ + static struct mtd_part_parser bcm47xxpart_mtd_parser = { + .parse_fn = bcm47xxpart_parse, + .name = "bcm47xxpart", ++ .of_match_table = bcm47xxpart_of_match_table, + }; + module_mtd_part_parser(bcm47xxpart_mtd_parser); + diff --git a/target/linux/bcm53xx/patches-4.14/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch b/target/linux/bcm53xx/patches-4.14/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch new file mode 100644 index 000000000..271d98cc8 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch @@ -0,0 +1,59 @@ +From 2a2af518266a29323cf30c3f9ba9ef2ceb1dd84b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 16 Oct 2014 20:52:16 +0200 +Subject: [PATCH] UBI: Detect EOF mark and erase all remaining blocks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +--- + drivers/mtd/ubi/attach.c | 5 +++++ + drivers/mtd/ubi/io.c | 4 ++++ + drivers/mtd/ubi/ubi.h | 1 + + 3 files changed, 10 insertions(+) + +--- a/drivers/mtd/ubi/attach.c ++++ b/drivers/mtd/ubi/attach.c +@@ -95,6 +95,9 @@ static int self_check_ai(struct ubi_devi + #define AV_ADD BIT(1) + #define AV_FIND_OR_ADD (AV_FIND | AV_ADD) + ++/* Set on finding block with 0xdeadc0de, indicates erasing all blocks behind */ ++bool erase_all_next; ++ + /** + * find_or_add_av - internal function to find a volume, add a volume or do + * both (find and add if missing). +@@ -1592,6 +1595,8 @@ int ubi_attach(struct ubi_device *ubi, i + if (!ai) + return -ENOMEM; + ++ erase_all_next = false; ++ + #ifdef CONFIG_MTD_UBI_FASTMAP + /* On small flash devices we disable fastmap in any case. */ + if ((int)mtd_div_by_eb(ubi->mtd->size, ubi->mtd) <= UBI_FM_MAX_START) { +--- a/drivers/mtd/ubi/io.c ++++ b/drivers/mtd/ubi/io.c +@@ -759,6 +759,10 @@ int ubi_io_read_ec_hdr(struct ubi_device + } + + magic = be32_to_cpu(ec_hdr->magic); ++ if (magic == 0xdeadc0de) ++ erase_all_next = true; ++ if (erase_all_next) ++ return read_err ? UBI_IO_FF_BITFLIPS : UBI_IO_FF; + if (magic != UBI_EC_HDR_MAGIC) { + if (mtd_is_eccerr(read_err)) + return UBI_IO_BAD_HDR_EBADMSG; +--- a/drivers/mtd/ubi/ubi.h ++++ b/drivers/mtd/ubi/ubi.h +@@ -822,6 +822,7 @@ extern struct mutex ubi_devices_mutex; + extern struct blocking_notifier_head ubi_notifiers; + + /* attach.c */ ++extern bool erase_all_next; + struct ubi_ainf_peb *ubi_alloc_aeb(struct ubi_attach_info *ai, int pnum, + int ec); + void ubi_free_aeb(struct ubi_attach_info *ai, struct ubi_ainf_peb *aeb); diff --git a/target/linux/bcm53xx/patches-4.14/700-b53-add-hacky-CPU-port-fixes-for-devices-not-using-p.patch b/target/linux/bcm53xx/patches-4.14/700-b53-add-hacky-CPU-port-fixes-for-devices-not-using-p.patch new file mode 100644 index 000000000..91bb4fae1 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/700-b53-add-hacky-CPU-port-fixes-for-devices-not-using-p.patch @@ -0,0 +1,52 @@ +From 4abdde3ad6bc0b3b157c4bf6ec0bf139d11d07e8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Wed, 13 May 2015 14:13:28 +0200 +Subject: [PATCH] b53: add hacky CPU port fixes for devices not using port 5 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +--- + drivers/net/phy/b53/b53_common.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/net/phy/b53/b53_common.c ++++ b/drivers/net/phy/b53/b53_common.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include "b53_regs.h" + #include "b53_priv.h" +@@ -1579,6 +1580,28 @@ static int b53_switch_init(struct b53_de + return ret; + } + ++ /* Set correct CPU port */ ++ if (of_machine_is_compatible("asus,rt-ac87u")) ++ sw_dev->cpu_port = 7; ++ else if (of_machine_is_compatible("netgear,r7900")) ++ sw_dev->cpu_port = 8; ++ else if (of_machine_is_compatible("netgear,r8000")) ++ sw_dev->cpu_port = 8; ++ else if (of_machine_is_compatible("netgear,r8500")) ++ sw_dev->cpu_port = 8; ++ ++ /* Enable extra ports */ ++ if (of_machine_is_compatible("tenda,ac9")) ++ dev->enabled_ports |= BIT(5); ++ ++ /* ++ * Workaround for devices using port 8 (connected to the 3rd iface). ++ * For some reason it doesn't work (no packets on eth2). ++ */ ++ if (of_machine_is_compatible("netgear,r7900") || ++ of_machine_is_compatible("netgear,r8000")) ++ sw_dev->cpu_port = 5; ++ + dev->enabled_ports |= BIT(sw_dev->cpu_port); + sw_dev->ports = fls(dev->enabled_ports); + diff --git a/target/linux/bcm53xx/patches-4.14/900-mtd-bcm47xxpart-add-device-specific-workarounds.patch b/target/linux/bcm53xx/patches-4.14/900-mtd-bcm47xxpart-add-device-specific-workarounds.patch new file mode 100644 index 000000000..b4a25a39d --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/900-mtd-bcm47xxpart-add-device-specific-workarounds.patch @@ -0,0 +1,56 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] mtd: bcm47xxpart: add device specific workarounds +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +--- + +--- a/drivers/mtd/bcm47xxpart.c ++++ b/drivers/mtd/bcm47xxpart.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include + +@@ -134,6 +135,36 @@ static int bcm47xxpart_parse(struct mtd_ + break; + } + ++ /* ++ * Device specific workarounds (hacks). We should use DT to ++ * define partitions but we need a working TRX firmware splitter ++ * first. ++ */ ++ if (of_machine_is_compatible("asus,rt-ac87u") && offset == 0x7ec0000) { ++ /* ++ * "asus" partition uses JFFS2 which we don't detect and ++ * we don't want to as this could affect other devices. ++ */ ++ bcm47xxpart_add_part(&parts[curr_part++], "asus", offset, MTD_WRITEABLE); ++ continue; ++ } else if (of_machine_is_compatible("tplink,archer-c5-v2") && offset == 0xe40000) { ++ /* ++ * There is a whole set of partitions (not even listed ++ * by original firmware): "default-mac", "pin", ++ * "partition-table", etc. ++ */ ++ bcm47xxpart_add_part(&parts[curr_part++], "tplink", offset, MTD_WRITEABLE); ++ continue; ++ } else if (of_machine_is_compatible("tplink,archer-c9-v1") && offset == 0xe40000) { ++ /* ++ * There is a whole set of partitions (not even listed ++ * by original firmware): "default-mac", "pin", ++ * "partition-table", etc. ++ */ ++ bcm47xxpart_add_part(&parts[curr_part++], "tplink", offset, MTD_WRITEABLE); ++ continue; ++ } ++ + /* Read beginning of the block */ + err = mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ, + &bytes_read, (uint8_t *)buf); diff --git a/target/linux/bcm53xx/patches-4.14/901-mtd-bcm47xxpart-add-partition-workaround-for-PHICOMM.patch b/target/linux/bcm53xx/patches-4.14/901-mtd-bcm47xxpart-add-partition-workaround-for-PHICOMM.patch new file mode 100644 index 000000000..501d4a329 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/901-mtd-bcm47xxpart-add-partition-workaround-for-PHICOMM.patch @@ -0,0 +1,19 @@ +Index: linux-4.14.29/drivers/mtd/bcm47xxpart.c +=================================================================== +--- linux-4.14.29.orig/drivers/mtd/bcm47xxpart.c ++++ linux-4.14.29/drivers/mtd/bcm47xxpart.c +@@ -163,6 +163,14 @@ static int bcm47xxpart_parse(struct mtd_ + */ + bcm47xxpart_add_part(&parts[curr_part++], "tplink", offset, MTD_WRITEABLE); + continue; ++ } else if (of_machine_is_compatible("phicomm,k3") && offset == 0x180000) { ++ /* ++ * This device has nvram_back, res_info, pro_info and dev_info from ++ * 0x180000 (end of nvram) to 0x400000 (start of linux). These partitions ++ * has essential information for original firwamre. We do not want these. ++ */ ++ bcm47xxpart_add_part(&parts[curr_part++], "phicomm", offset, MTD_WRITEABLE); ++ continue; + } + + /* Read beginning of the block */ diff --git a/target/linux/bcm53xx/patches-4.14/905-BCM53573-minor-hacks.patch b/target/linux/bcm53xx/patches-4.14/905-BCM53573-minor-hacks.patch new file mode 100644 index 000000000..4e0a752d6 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/905-BCM53573-minor-hacks.patch @@ -0,0 +1,88 @@ +From 6f1c62440eb6846cb8045d7a5480ec7bbe47c96f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 15 Aug 2016 10:30:41 +0200 +Subject: [PATCH] BCM53573 minor hacks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +--- + +--- a/arch/arm/boot/dts/bcm53573.dtsi ++++ b/arch/arm/boot/dts/bcm53573.dtsi +@@ -48,6 +48,15 @@ + }; + }; + ++ timer { ++ compatible = "arm,armv7-timer"; ++ interrupts = , ++ , ++ , ++ ; ++ clocks = <&ilp>; ++ }; ++ + clocks { + #address-cells = <1>; + #size-cells = <1>; +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -348,14 +348,6 @@ static int bcma_register_devices(struct + } + #endif + +-#ifdef CONFIG_BCMA_SFLASH +- if (bus->drv_cc.sflash.present) { +- err = platform_device_register(&bcma_sflash_dev); +- if (err) +- bcma_err(bus, "Error registering serial flash\n"); +- } +-#endif +- + #ifdef CONFIG_BCMA_NFLASH + if (bus->drv_cc.nflash.present) { + err = platform_device_register(&bcma_nflash_dev); +@@ -436,6 +428,14 @@ int bcma_bus_register(struct bcma_bus *b + bcma_register_core(bus, core); + } + ++#ifdef CONFIG_BCMA_SFLASH ++ if (bus->drv_cc.sflash.present) { ++ err = platform_device_register(&bcma_sflash_dev); ++ if (err) ++ bcma_err(bus, "Error registering serial flash\n"); ++ } ++#endif ++ + /* Try to get SPROM */ + err = bcma_sprom_get(bus); + if (err == -ENOENT) { +--- a/drivers/clocksource/arm_arch_timer.c ++++ b/drivers/clocksource/arm_arch_timer.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -836,6 +837,16 @@ static void arch_timer_of_configure_rate + if (of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) + arch_timer_rate = rate; + ++ /* Get clk rate through clk driver if present */ ++ if (!arch_timer_rate) { ++ struct clk *clk = of_clk_get(np, 0); ++ ++ if (!IS_ERR(clk)) { ++ if (!clk_prepare_enable(clk)) ++ arch_timer_rate = clk_get_rate(clk); ++ } ++ } ++ + /* Check the timer frequency. */ + if (arch_timer_rate == 0) + pr_warn("frequency not available\n"); diff --git a/target/linux/bcm53xx/patches-4.14/910-Revert-earlycon-initialise-baud-field-of-earlycon-de.patch b/target/linux/bcm53xx/patches-4.14/910-Revert-earlycon-initialise-baud-field-of-earlycon-de.patch new file mode 100644 index 000000000..025781a86 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/910-Revert-earlycon-initialise-baud-field-of-earlycon-de.patch @@ -0,0 +1,33 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] Revert "earlycon: initialise baud field of earlycon device + structure" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This reverts commit 31cb9a8575ca04f47ea113434d4782b695638b62. + +It broke earlycon on BCM5301X. Using: +1) uartclk 1843200 (BASE_BAUD * 16) +2) early_console_dev.baud 115200 +results in init_port() calculating UART divisor 1. That's a wrong value +(default one is 54) that breaks serial console output. + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +--- + +--- a/drivers/tty/serial/earlycon.c ++++ b/drivers/tty/serial/earlycon.c +@@ -283,12 +283,7 @@ int __init of_setup_earlycon(const struc + } + } + +- val = of_get_flat_dt_prop(node, "current-speed", NULL); +- if (val) +- early_console_dev.baud = be32_to_cpu(*val); +- + if (options) { +- early_console_dev.baud = simple_strtoul(options, NULL, 0); + strlcpy(early_console_dev.options, options, + sizeof(early_console_dev.options)); + } diff --git a/target/linux/bcm53xx/patches-4.4/049-v4.14-0003-ARM-dts-BCM53573-Add-Broadcom-BCM947189ACDBMR-board-.patch b/target/linux/bcm53xx/patches-4.4/049-v4.14-0003-ARM-dts-BCM53573-Add-Broadcom-BCM947189ACDBMR-board-.patch new file mode 100644 index 000000000..69deca161 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.4/049-v4.14-0003-ARM-dts-BCM53573-Add-Broadcom-BCM947189ACDBMR-board-.patch @@ -0,0 +1,135 @@ +From 092ccf0415c720a1e9458a46fe75f77574027a55 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli +Date: Tue, 18 Jul 2017 12:37:37 -0700 +Subject: [PATCH] ARM: dts: BCM53573: Add Broadcom BCM947189ACDBMR board + support + +Adds support for the Broadcom reference board BCM947189ACDMBR which +features the following: + +* 128MB of DRAM +* External MoCA support through a Broadcom BCM6802 chip +* 1x external Gigabit PHY through the external BCM6802 +* 1x USB 2.0 port +* 1x PCIE slot +* Few configurable buttons and LEDs + +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/Makefile | 3 +- + arch/arm/boot/dts/bcm947189acdbmr.dts | 97 +++++++++++++++++++++++++++++++++++ + 2 files changed, 99 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/boot/dts/bcm947189acdbmr.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -93,7 +93,8 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm953012hr.dtb \ + bcm953012k.dtb + dtb-$(CONFIG_ARCH_BCM_53573) += \ +- bcm47189-tenda-ac9.dtb ++ bcm47189-tenda-ac9.dtb \ ++ bcm947189acdbmr.dtb + dtb-$(CONFIG_ARCH_BCM_63XX) += \ + bcm963138dvt.dtb + dtb-$(CONFIG_ARCH_BCM_CYGNUS) += \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm947189acdbmr.dts +@@ -0,0 +1,97 @@ ++/* ++ * Copyright (C) 2017 Broadcom ++ * Author: Florian Fainelli ++ * ++ * Licensed under the ISC license. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm53573.dtsi" ++ ++/ { ++ compatible = "brcm,bcm947189acdbmr", "brcm,bcm47189", "brcm,bcm53573"; ++ model = "Broadcom BCM947189ACDBMR"; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200 earlycon"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ wps { ++ label = "bcm53xx:blue:wps"; ++ gpios = <&chipcommon 10 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ 5ghz { ++ label = "bcm53xx:blue:5ghz"; ++ gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ 2ghz { ++ label = "bcm53xx:blue:2ghz"; ++ gpios = <&chipcommon 12 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ restart { ++ label = "Reset"; ++ linux,code = ; ++ gpios = <&chipcommon 7 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ wps { ++ label = "WPS"; ++ linux,code = ; ++ gpios = <&chipcommon 9 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ spi { ++ compatible = "spi-gpio"; ++ num-chipselects = <1>; ++ gpio-sck = <&chipcommon 21 0>; ++ gpio-miso = <&chipcommon 22 0>; ++ gpio-mosi = <&chipcommon 23 0>; ++ cs-gpios = <&chipcommon 24 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* External BCM6802 MoCA chip is connected */ ++ }; ++}; ++ ++&pcie0 { ++ ranges = <0x00000000 0 0 0 0 0x00100000>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ++ bridge@0,0,0 { ++ reg = <0x0000 0 0 0 0>; ++ ranges = <0x00000000 0 0 0 0 0 0 0x00100000>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ++ wifi@0,1,0 { ++ reg = <0x0000 0 0 0 0>; ++ ranges = <0x00000000 0 0 0 0x00100000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ }; ++ }; ++}; ++ ++&usb2 { ++ vcc-gpio = <&chipcommon 8 GPIO_ACTIVE_HIGH>; ++}; diff --git a/target/linux/bcm53xx/patches-4.4/049-v4.14-0004-ARM-BCM53573-Specify-ports-for-USB-LED-for-Tenda-AC9.patch b/target/linux/bcm53xx/patches-4.4/049-v4.14-0004-ARM-BCM53573-Specify-ports-for-USB-LED-for-Tenda-AC9.patch new file mode 100644 index 000000000..75f1d1772 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.4/049-v4.14-0004-ARM-BCM53573-Specify-ports-for-USB-LED-for-Tenda-AC9.patch @@ -0,0 +1,58 @@ +From 0173b2cd6948b5b96ac4e8dbc3bcb4dd0b45c296 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 17 Aug 2017 11:05:14 +0200 +Subject: [PATCH] ARM: BCM53573: Specify ports for USB LED for Tenda AC9 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This uses trigger-sources documented in commit 80dc6e1cd85fc ("dt-bindings: +leds: document new trigger-sources property") to specify USB ports. Such an +information can be used by operating system to setup LEDs behavior. + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/bcm47189-tenda-ac9.dts | 2 ++ + arch/arm/boot/dts/bcm53573.dtsi | 4 ++++ + 2 files changed, 6 insertions(+) + +--- a/arch/arm/boot/dts/bcm47189-tenda-ac9.dts ++++ b/arch/arm/boot/dts/bcm47189-tenda-ac9.dts +@@ -26,6 +26,8 @@ + usb { + label = "bcm53xx:blue:usb"; + gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>; ++ trigger-sources = <&ohci_port1>, <&ehci_port1>; ++ linux,default-trigger = "usbport"; + }; + + wps { +--- a/arch/arm/boot/dts/bcm53573.dtsi ++++ b/arch/arm/boot/dts/bcm53573.dtsi +@@ -138,10 +138,12 @@ + + ehci_port1: port@1 { + reg = <1>; ++ #trigger-source-cells = <0>; + }; + + ehci_port2: port@2 { + reg = <2>; ++ #trigger-source-cells = <0>; + }; + }; + +@@ -158,10 +160,12 @@ + + ohci_port1: port@1 { + reg = <1>; ++ #trigger-source-cells = <0>; + }; + + ohci_port2: port@2 { + reg = <2>; ++ #trigger-source-cells = <0>; + }; + }; + }; diff --git a/target/linux/bcm53xx/patches-4.4/049-v4.15-0001-ARM-dts-BCM5301X-Specify-USB-ports-for-USB-LED-of-Lu.patch b/target/linux/bcm53xx/patches-4.4/049-v4.15-0001-ARM-dts-BCM5301X-Specify-USB-ports-for-USB-LED-of-Lu.patch new file mode 100644 index 000000000..3148f6c32 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.4/049-v4.15-0001-ARM-dts-BCM5301X-Specify-USB-ports-for-USB-LED-of-Lu.patch @@ -0,0 +1,30 @@ +From 2460266f21f140936e627f28f28d1a4f30887ae9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 6 Oct 2017 10:52:35 +0200 +Subject: [PATCH] ARM: dts: BCM5301X: Specify USB ports for USB LED of Luxul + XWR-1200 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This info can be used by operating system to setup LED behavior. + +Reported-by: Dan Haab +Signed-off-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts ++++ b/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts +@@ -57,7 +57,8 @@ + usb { + label = "bcm53xx:green:usb"; + gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>; +- linux,default-trigger = "none"; ++ trigger-sources = <&ohci_port2>, <&ehci_port2>; ++ linux,default-trigger = "usbport"; + }; + + status { diff --git a/target/linux/bcm53xx/patches-4.4/049-v4.15-0002-ARM-dts-BCM5301X-Add-DT-for-Luxul-XBR-4500.patch b/target/linux/bcm53xx/patches-4.4/049-v4.15-0002-ARM-dts-BCM5301X-Add-DT-for-Luxul-XBR-4500.patch new file mode 100644 index 000000000..fbe8f5469 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.4/049-v4.15-0002-ARM-dts-BCM5301X-Add-DT-for-Luxul-XBR-4500.patch @@ -0,0 +1,96 @@ +From 1f4b0d5596d2e3ea8e953d578ab8444ce860d35d Mon Sep 17 00:00:00 2001 +From: Dan Haab +Date: Mon, 9 Oct 2017 09:46:22 -0600 +Subject: [PATCH] ARM: dts: BCM5301X: Add DT for Luxul XBR-4500 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is BCM47094 (AKA BCM4709C0) based router with ports-on-the-front +board design. + +Signed-off-by: Dan Haab +Acked-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts | 63 +++++++++++++++++++++++++++ + 2 files changed, 64 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -85,6 +85,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm4709-tplink-archer-c9-v1.dtb \ + bcm47094-dlink-dir-885l.dtb \ + bcm47094-linksys-panamera.dtb \ ++ bcm47094-luxul-xbr-4500.dtb \ + bcm47094-luxul-xwr-3100.dtb \ + bcm47094-netgear-r8500.dtb \ + bcm94708.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts +@@ -0,0 +1,63 @@ ++/* ++ * Copyright (C) 2017 Luxul Inc. ++ * ++ * Licensed under the ISC license. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm4708.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" ++ ++/ { ++ compatible = "luxul,xbr-4500-v1", "brcm,bcm47094", "brcm,bcm4708"; ++ model = "Luxul XBR-4500 V1"; ++ ++ chosen { ++ bootargs = "earlycon"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x18000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ status { ++ label = "bcm53xx:green:status"; ++ gpios = <&chipcommon 20 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "timer"; ++ }; ++ ++ usb3 { ++ label = "bcm53xx:green:usb3"; ++ gpios = <&chipcommon 19 GPIO_ACTIVE_HIGH>; ++ trigger-sources = <&ohci_port1>, <&ehci_port1>, ++ <&xhci_port1>; ++ linux,default-trigger = "usbport"; ++ }; ++ ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ restart { ++ label = "Reset"; ++ linux,code = ; ++ gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&usb3 { ++ vcc-gpio = <&chipcommon 18 GPIO_ACTIVE_HIGH>; ++}; ++ ++&spi_nor { ++ status = "okay"; ++}; diff --git a/target/linux/bcm53xx/patches-4.4/049-v4.15-0003-ARM-dts-BCM5301X-Add-DT-for-Luxul-ABR-4500.patch b/target/linux/bcm53xx/patches-4.4/049-v4.15-0003-ARM-dts-BCM5301X-Add-DT-for-Luxul-ABR-4500.patch new file mode 100644 index 000000000..b5ba1dde1 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.4/049-v4.15-0003-ARM-dts-BCM5301X-Add-DT-for-Luxul-ABR-4500.patch @@ -0,0 +1,96 @@ +From 65f78c4c41a9b9a7637e1dda2d5e41cf26ea971c Mon Sep 17 00:00:00 2001 +From: Dan Haab +Date: Mon, 9 Oct 2017 09:46:23 -0600 +Subject: [PATCH] ARM: dts: BCM5301X: Add DT for Luxul ABR-4500 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is BCM47094 (AKA BCM4709C0) based router with rear-facing ports +board design. + +Signed-off-by: Dan Haab +Acked-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts | 63 +++++++++++++++++++++++++++ + 2 files changed, 64 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -85,6 +85,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm4709-tplink-archer-c9-v1.dtb \ + bcm47094-dlink-dir-885l.dtb \ + bcm47094-linksys-panamera.dtb \ ++ bcm47094-luxul-abr-4500.dtb \ + bcm47094-luxul-xbr-4500.dtb \ + bcm47094-luxul-xwr-3100.dtb \ + bcm47094-netgear-r8500.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts +@@ -0,0 +1,63 @@ ++/* ++ * Copyright (C) 2017 Luxul Inc. ++ * ++ * Licensed under the ISC license. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm4708.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" ++ ++/ { ++ compatible = "luxul,abr-4500-v1", "brcm,bcm47094", "brcm,bcm4708"; ++ model = "Luxul ABR-4500 V1"; ++ ++ chosen { ++ bootargs = "earlycon"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x18000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ status { ++ label = "bcm53xx:green:status"; ++ gpios = <&chipcommon 20 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "timer"; ++ }; ++ ++ usb3 { ++ label = "bcm53xx:green:usb3"; ++ gpios = <&chipcommon 19 GPIO_ACTIVE_LOW>; ++ trigger-sources = <&ohci_port1>, <&ehci_port1>, ++ <&xhci_port1>; ++ linux,default-trigger = "usbport"; ++ }; ++ ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ restart { ++ label = "Reset"; ++ linux,code = ; ++ gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&usb3 { ++ vcc-gpio = <&chipcommon 18 GPIO_ACTIVE_HIGH>; ++}; ++ ++&spi_nor { ++ status = "okay"; ++}; diff --git a/target/linux/bcm53xx/patches-4.4/049-v4.15-0004-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-810.patch b/target/linux/bcm53xx/patches-4.4/049-v4.15-0004-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-810.patch new file mode 100644 index 000000000..407537f3b --- /dev/null +++ b/target/linux/bcm53xx/patches-4.4/049-v4.15-0004-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-810.patch @@ -0,0 +1,120 @@ +From 0aa052ce1c3340850a7e5980b6d24b3ea5779591 Mon Sep 17 00:00:00 2001 +From: Dan Haab +Date: Mon, 9 Oct 2017 09:46:59 -0600 +Subject: [PATCH] ARM: dts: BCM53573: Add DT for Luxul XAP-810 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is BCM53573 WiSoC based access point with an extra BCM43217 chipset +used for 2.4 GHz. + +Signed-off-by: Dan Haab +Acked-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm47189-luxul-xap-810.dts | 87 ++++++++++++++++++++++++++++ + 2 files changed, 88 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm47189-luxul-xap-810.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -95,6 +95,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm953012hr.dtb \ + bcm953012k.dtb + dtb-$(CONFIG_ARCH_BCM_53573) += \ ++ bcm47189-luxul-xap-810.dtb \ + bcm47189-tenda-ac9.dtb \ + bcm947189acdbmr.dtb + dtb-$(CONFIG_ARCH_BCM_63XX) += \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts +@@ -0,0 +1,87 @@ ++/* ++ * Copyright 2017 Luxul Inc. ++ * ++ * Licensed under the ISC license. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm53573.dtsi" ++ ++/ { ++ compatible = "luxul,xap-810-v1", "brcm,bcm47189", "brcm,bcm53573"; ++ model = "Luxul XAP-810 V1"; ++ ++ chosen { ++ bootargs = "earlycon"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ 5ghz { ++ label = "bcm53xx:blue:5ghz"; ++ gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ system { ++ label = "bcm53xx:green:system"; ++ gpios = <&chipcommon 15 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "timer"; ++ }; ++ }; ++ ++ pcie0_leds { ++ compatible = "gpio-leds"; ++ ++ 2ghz { ++ label = "bcm53xx:blue:2ghz"; ++ gpios = <&pcie0_chipcommon 3 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ restart { ++ label = "Reset"; ++ linux,code = ; ++ gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&pcie0 { ++ ranges = <0x00000000 0 0 0 0 0x00100000>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ++ bridge@0,0,0 { ++ reg = <0x0000 0 0 0 0>; ++ ranges = <0x00000000 0 0 0 0 0 0 0x00100000>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ++ wifi@0,1,0 { ++ reg = <0x0000 0 0 0 0>; ++ ranges = <0x00000000 0 0 0 0x00100000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ pcie0_chipcommon: chipcommon@0 { ++ reg = <0 0x1000>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-4.4/049-v4.15-0005-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-1440.patch b/target/linux/bcm53xx/patches-4.4/049-v4.15-0005-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-1440.patch new file mode 100644 index 000000000..51b3dc790 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.4/049-v4.15-0005-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-1440.patch @@ -0,0 +1,83 @@ +From 7030ea600d560026b91726f2eb79c856b813afa9 Mon Sep 17 00:00:00 2001 +From: Dan Haab +Date: Mon, 9 Oct 2017 09:47:00 -0600 +Subject: [PATCH] ARM: dts: BCM53573: Add DT for Luxul XAP-1440 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is BCM53573 WiSoC based outdoor access point with an extra BCM43217 +chipset used for 2.4 GHz. + +Signed-off-by: Dan Haab +Acked-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts | 50 +++++++++++++++++++++++++++ + 2 files changed, 51 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -95,6 +95,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm953012hr.dtb \ + bcm953012k.dtb + dtb-$(CONFIG_ARCH_BCM_53573) += \ ++ bcm47189-luxul-xap-1440.dtb \ + bcm47189-luxul-xap-810.dtb \ + bcm47189-tenda-ac9.dtb \ + bcm947189acdbmr.dtb +--- /dev/null ++++ b/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts +@@ -0,0 +1,50 @@ ++/* ++ * Copyright 2017 Luxul Inc. ++ * ++ * Licensed under the ISC license. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm53573.dtsi" ++ ++/ { ++ compatible = "luxul,xap-1440-v1", "brcm,bcm47189", "brcm,bcm53573"; ++ model = "Luxul XAP-1440 V1"; ++ ++ chosen { ++ bootargs = "earlycon"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ wlan { ++ label = "bcm53xx:blue:wlan"; ++ gpios = <&chipcommon 10 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ system { ++ label = "bcm53xx:green:system"; ++ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "timer"; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ restart { ++ label = "Reset"; ++ linux,code = ; ++ gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-4.4/084-0003-spi-bcm53xx-simplify-reading-SPI-data.patch b/target/linux/bcm53xx/patches-4.4/084-0003-spi-bcm53xx-simplify-reading-SPI-data.patch new file mode 100644 index 000000000..ee377c491 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.4/084-0003-spi-bcm53xx-simplify-reading-SPI-data.patch @@ -0,0 +1,107 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 29 Dec 2017 14:44:09 +0100 +Subject: [PATCH] spi: bcm53xx: simplify reading SPI data +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit makes transfer function use spi_transfer_is_last to +determine if currently processed transfer is the last one. Thanks to +that we finally set hardware registers properly and it makes controller +behave the way it's expected to. + +This allows simplifying read function which can now simply start reading +from the slot 0 instead of the last saved offset. It has been +successfully tested using spi_write_then_read. + +Moreover this change fixes handling messages with two writing transfers. +It's important for SPI flash devices as their drivers commonly use one +transfer for a command and another one for data. + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +--- + drivers/spi/spi-bcm53xx.c | 26 ++++++++++---------------- + 1 file changed, 10 insertions(+), 16 deletions(-) + +--- a/drivers/spi/spi-bcm53xx.c ++++ b/drivers/spi/spi-bcm53xx.c +@@ -27,8 +27,6 @@ struct bcm53xxspi { + struct bcma_device *core; + struct spi_master *master; + void __iomem *mmio_base; +- +- size_t read_offset; + bool bspi; /* Boot SPI mode with memory mapping */ + }; + +@@ -172,8 +170,6 @@ static void bcm53xxspi_buf_write(struct + + if (!cont) + bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); +- +- b53spi->read_offset = len; + } + + static void bcm53xxspi_buf_read(struct bcm53xxspi *b53spi, u8 *r_buf, +@@ -182,10 +178,10 @@ static void bcm53xxspi_buf_read(struct b + u32 tmp; + int i; + +- for (i = 0; i < b53spi->read_offset + len; i++) { ++ for (i = 0; i < len; i++) { + tmp = B53SPI_CDRAM_CONT | B53SPI_CDRAM_PCS_DISABLE_ALL | + B53SPI_CDRAM_PCS_DSCK; +- if (!cont && i == b53spi->read_offset + len - 1) ++ if (!cont && i == len - 1) + tmp &= ~B53SPI_CDRAM_CONT; + tmp &= ~0x1; + /* Command Register File */ +@@ -194,8 +190,7 @@ static void bcm53xxspi_buf_read(struct b + + /* Set queue pointers */ + bcm53xxspi_write(b53spi, B53SPI_MSPI_NEWQP, 0); +- bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, +- b53spi->read_offset + len - 1); ++ bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, len - 1); + + if (cont) + bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 1); +@@ -214,13 +209,11 @@ static void bcm53xxspi_buf_read(struct b + bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); + + for (i = 0; i < len; ++i) { +- int offset = b53spi->read_offset + i; ++ u16 reg = B53SPI_MSPI_RXRAM + 4 * (1 + i * 2); + + /* Data stored in the transmit register file LSB */ +- r_buf[i] = (u8)bcm53xxspi_read(b53spi, B53SPI_MSPI_RXRAM + 4 * (1 + offset * 2)); ++ r_buf[i] = (u8)bcm53xxspi_read(b53spi, reg); + } +- +- b53spi->read_offset = 0; + } + + static int bcm53xxspi_transfer_one(struct spi_master *master, +@@ -238,7 +231,8 @@ static int bcm53xxspi_transfer_one(struc + left = t->len; + while (left) { + size_t to_write = min_t(size_t, 16, left); +- bool cont = left - to_write > 0; ++ bool cont = !spi_transfer_is_last(master, t) || ++ left - to_write > 0; + + bcm53xxspi_buf_write(b53spi, buf, to_write, cont); + left -= to_write; +@@ -250,9 +244,9 @@ static int bcm53xxspi_transfer_one(struc + buf = (u8 *)t->rx_buf; + left = t->len; + while (left) { +- size_t to_read = min_t(size_t, 16 - b53spi->read_offset, +- left); +- bool cont = left - to_read > 0; ++ size_t to_read = min_t(size_t, 16, left); ++ bool cont = !spi_transfer_is_last(master, t) || ++ left - to_read > 0; + + bcm53xxspi_buf_read(b53spi, buf, to_read, cont); + left -= to_read; diff --git a/target/linux/bcm53xx/patches-4.4/140-mtd-brcmnand-set-initial-ECC-params-based-on-info-fr.patch b/target/linux/bcm53xx/patches-4.4/140-mtd-brcmnand-set-initial-ECC-params-based-on-info-fr.patch index ea59938aa..4eba839d9 100644 --- a/target/linux/bcm53xx/patches-4.4/140-mtd-brcmnand-set-initial-ECC-params-based-on-info-fr.patch +++ b/target/linux/bcm53xx/patches-4.4/140-mtd-brcmnand-set-initial-ECC-params-based-on-info-fr.patch @@ -41,7 +41,7 @@ This should be very helpful for ppl adding new devices support. static void brcmnand_set_ecc_enabled(struct brcmnand_host *host, int en) { struct brcmnand_controller *ctrl = host->ctrl; -@@ -1997,6 +2008,9 @@ static int brcmnand_init_cs(struct brcmn +@@ -1990,6 +2001,9 @@ static int brcmnand_init_cs(struct brcmn nand_writereg(ctrl, cfg_offs, nand_readreg(ctrl, cfg_offs) & ~CFG_BUS_WIDTH); diff --git a/target/linux/bcm53xx/patches-4.4/320-ARM-dts-BCM5301X-Add-serial-to-the-bootargs.patch b/target/linux/bcm53xx/patches-4.4/320-ARM-dts-BCM5301X-Add-serial-to-the-bootargs.patch index 171e6b3bb..710d94f6b 100644 --- a/target/linux/bcm53xx/patches-4.4/320-ARM-dts-BCM5301X-Add-serial-to-the-bootargs.patch +++ b/target/linux/bcm53xx/patches-4.4/320-ARM-dts-BCM5301X-Add-serial-to-the-bootargs.patch @@ -23,4 +23,48 @@ Signed-off-by: RafaÅ‚ MiÅ‚ecki + bootargs = "console=ttyS0,115200 earlycon"; }; + memory { +--- a/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts ++++ b/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts +@@ -14,7 +14,7 @@ + model = "Luxul ABR-4500 V1"; + + chosen { +- bootargs = "earlycon"; ++ bootargs = "console=ttyS0,115200 earlycon"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts ++++ b/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts +@@ -14,7 +14,7 @@ + model = "Luxul XBR-4500 V1"; + + chosen { +- bootargs = "earlycon"; ++ bootargs = "console=ttyS0,115200 earlycon"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts ++++ b/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts +@@ -13,7 +13,7 @@ + model = "Luxul XAP-1440 V1"; + + chosen { +- bootargs = "earlycon"; ++ bootargs = "console=ttyS0,115200 earlycon"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts ++++ b/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts +@@ -13,7 +13,7 @@ + model = "Luxul XAP-810 V1"; + + chosen { +- bootargs = "earlycon"; ++ bootargs = "console=ttyS0,115200 earlycon"; + }; + memory { diff --git a/target/linux/bcm53xx/patches-4.4/406-mtd-m25p80-use-single-SPI-message-for-writing-data.patch b/target/linux/bcm53xx/patches-4.4/406-mtd-m25p80-use-single-SPI-message-for-writing-data.patch deleted file mode 100644 index d5525f622..000000000 --- a/target/linux/bcm53xx/patches-4.4/406-mtd-m25p80-use-single-SPI-message-for-writing-data.patch +++ /dev/null @@ -1,59 +0,0 @@ -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Subject: [PATCH] mtd: m25p80: use single SPI message for writing data -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -On all 3 tested Northstar devices with following flash memories: -mx25l6405d (8192 Kbytes) -mx25l12805d (16384 Kbytes) -mx25l25635e (32768 Kbytes) -I noticed writing to be broken. Not a single bit was changed leaving all -bytes set to 0xff. - -This is most likely some problem related to the SPI controller or its -driver. Using a single SPI message seems to workaround this. Of course -it's not perfect solution as copying whole data into a new buffer makes -writing slower. - -Signed-off-by: RafaÅ‚ MiÅ‚ecki ---- - ---- a/drivers/mtd/devices/m25p80.c -+++ b/drivers/mtd/devices/m25p80.c -@@ -78,6 +78,7 @@ static void m25p80_write(struct spi_nor - { - struct m25p *flash = nor->priv; - struct spi_device *spi = flash->spi; -+ u8 *command = kzalloc(MAX_CMD_SIZE + len, GFP_KERNEL); - struct spi_transfer t[2] = {}; - struct spi_message m; - int cmd_sz = m25p_cmdsz(nor); -@@ -87,20 +88,19 @@ static void m25p80_write(struct spi_nor - if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second) - cmd_sz = 1; - -- flash->command[0] = nor->program_opcode; -- m25p_addr2cmd(nor, to, flash->command); -+ command[0] = nor->program_opcode; -+ m25p_addr2cmd(nor, to, command); -+ memcpy(&command[cmd_sz], buf, len); - -- t[0].tx_buf = flash->command; -- t[0].len = cmd_sz; -+ t[0].tx_buf = command; -+ t[0].len = cmd_sz + len; - spi_message_add_tail(&t[0], &m); - -- t[1].tx_buf = buf; -- t[1].len = len; -- spi_message_add_tail(&t[1], &m); -- - spi_sync(spi, &m); - - *retlen += m.actual_length - cmd_sz; -+ -+ kfree(command); - } - - static inline unsigned int m25p80_rx_nbits(struct spi_nor *nor) diff --git a/target/linux/bcm53xx/patches-4.9/033-0022-ARM-dts-BCM5301X-Add-basic-DT-for-PHICOMM-K3.patch b/target/linux/bcm53xx/patches-4.9/033-0022-ARM-dts-BCM5301X-Add-basic-DT-for-PHICOMM-K3.patch deleted file mode 100644 index 792a394c2..000000000 --- a/target/linux/bcm53xx/patches-4.9/033-0022-ARM-dts-BCM5301X-Add-basic-DT-for-PHICOMM-K3.patch +++ /dev/null @@ -1,79 +0,0 @@ -From bf793950827142bc464eb2fd4059e1db24cc3517 Mon Sep 17 00:00:00 2001 -From: Tian Hao -Date: Sun, 2 Apr 2017 00:03:40 +0800 -Subject: [PATCH] ARM: dts: BCM5301X: Add basic DT for PHICOMM K3 - -This router has BCM4709C0, 128MB NAND flash (MX30LF1G18AC-TI), -and 512MB memory, with 3 x LAN and 1 x WAN. WL chips are -BCM4366C0 x 2. The router has a small LCD and 3 capactive keys -driven by a PIC microcontroller, which is in turn wired to -UART1 of main board. - -Everything except the LCD and wireless works. - -Signed-Off-By: Tian Hao ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/bcm47094-phicomm-k3.dts | 34 +++++++++++++++++++++++++++++++ - 2 files changed, 35 insertions(+) - create mode 100644 arch/arm/boot/dts/bcm47094-phicomm-k3.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 0f2e27a0..a5237028 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -95,6 +95,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ - bcm4709-tplink-archer-c9-v1.dtb \ - bcm47094-dlink-dir-885l.dtb \ - bcm47094-linksys-panamera.dtb \ -+ bcm47094-phicomm-k3.dtb \ - bcm47094-luxul-xwr-3100.dtb \ - bcm47094-netgear-r8500.dtb \ - bcm94708.dtb \ -diff --git a/arch/arm/boot/dts/bcm47094-phicomm-k3.dts b/arch/arm/boot/dts/bcm47094-phicomm-k3.dts -new file mode 100644 -index 00000000..ec2f9b27 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm47094-phicomm-k3.dts -@@ -0,0 +1,38 @@ -+/* -+ * Copyright (C) 2017 Hamster Tian -+ */ -+ -+/dts-v1/; -+ -+#include "bcm47094.dtsi" -+#include "bcm5301x-nand-cs0-bch4.dtsi" -+ -+/ { -+ compatible = "phicomm,k3", "brcm,bcm47094", "brcm,bcm4708"; -+ model = "PHICOMM K3"; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200"; -+ }; -+ -+ memory { -+ reg = <0x00000000 0x08000000 -+ 0x88000000 0x18000000>; -+ }; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ restart { -+ label = "Reset"; -+ linux,code = ; -+ gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+}; -+ -+&uart1 { -+ status = "okay"; -+}; --- -2.11.0 - diff --git a/target/linux/bcm53xx/patches-4.9/035-v4.14-0003-ARM-dts-BCM53573-Add-Broadcom-BCM947189ACDBMR-board-.patch b/target/linux/bcm53xx/patches-4.9/035-v4.14-0003-ARM-dts-BCM53573-Add-Broadcom-BCM947189ACDBMR-board-.patch new file mode 100644 index 000000000..1057ffcec --- /dev/null +++ b/target/linux/bcm53xx/patches-4.9/035-v4.14-0003-ARM-dts-BCM53573-Add-Broadcom-BCM947189ACDBMR-board-.patch @@ -0,0 +1,135 @@ +From 092ccf0415c720a1e9458a46fe75f77574027a55 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli +Date: Tue, 18 Jul 2017 12:37:37 -0700 +Subject: [PATCH] ARM: dts: BCM53573: Add Broadcom BCM947189ACDBMR board + support + +Adds support for the Broadcom reference board BCM947189ACDMBR which +features the following: + +* 128MB of DRAM +* External MoCA support through a Broadcom BCM6802 chip +* 1x external Gigabit PHY through the external BCM6802 +* 1x USB 2.0 port +* 1x PCIE slot +* Few configurable buttons and LEDs + +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/Makefile | 3 +- + arch/arm/boot/dts/bcm947189acdbmr.dts | 97 +++++++++++++++++++++++++++++++++++ + 2 files changed, 99 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/boot/dts/bcm947189acdbmr.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -103,7 +103,8 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm953012hr.dtb \ + bcm953012k.dtb + dtb-$(CONFIG_ARCH_BCM_53573) += \ +- bcm47189-tenda-ac9.dtb ++ bcm47189-tenda-ac9.dtb \ ++ bcm947189acdbmr.dtb + dtb-$(CONFIG_ARCH_BCM_63XX) += \ + bcm963138dvt.dtb + dtb-$(CONFIG_ARCH_BCM_CYGNUS) += \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm947189acdbmr.dts +@@ -0,0 +1,97 @@ ++/* ++ * Copyright (C) 2017 Broadcom ++ * Author: Florian Fainelli ++ * ++ * Licensed under the ISC license. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm53573.dtsi" ++ ++/ { ++ compatible = "brcm,bcm947189acdbmr", "brcm,bcm47189", "brcm,bcm53573"; ++ model = "Broadcom BCM947189ACDBMR"; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200 earlycon"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ wps { ++ label = "bcm53xx:blue:wps"; ++ gpios = <&chipcommon 10 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ 5ghz { ++ label = "bcm53xx:blue:5ghz"; ++ gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ 2ghz { ++ label = "bcm53xx:blue:2ghz"; ++ gpios = <&chipcommon 12 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ restart { ++ label = "Reset"; ++ linux,code = ; ++ gpios = <&chipcommon 7 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ wps { ++ label = "WPS"; ++ linux,code = ; ++ gpios = <&chipcommon 9 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ spi { ++ compatible = "spi-gpio"; ++ num-chipselects = <1>; ++ gpio-sck = <&chipcommon 21 0>; ++ gpio-miso = <&chipcommon 22 0>; ++ gpio-mosi = <&chipcommon 23 0>; ++ cs-gpios = <&chipcommon 24 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* External BCM6802 MoCA chip is connected */ ++ }; ++}; ++ ++&pcie0 { ++ ranges = <0x00000000 0 0 0 0 0x00100000>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ++ bridge@0,0,0 { ++ reg = <0x0000 0 0 0 0>; ++ ranges = <0x00000000 0 0 0 0 0 0 0x00100000>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ++ wifi@0,1,0 { ++ reg = <0x0000 0 0 0 0>; ++ ranges = <0x00000000 0 0 0 0x00100000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ }; ++ }; ++}; ++ ++&usb2 { ++ vcc-gpio = <&chipcommon 8 GPIO_ACTIVE_HIGH>; ++}; diff --git a/target/linux/bcm53xx/patches-4.9/035-v4.14-0004-ARM-BCM53573-Specify-ports-for-USB-LED-for-Tenda-AC9.patch b/target/linux/bcm53xx/patches-4.9/035-v4.14-0004-ARM-BCM53573-Specify-ports-for-USB-LED-for-Tenda-AC9.patch new file mode 100644 index 000000000..75f1d1772 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.9/035-v4.14-0004-ARM-BCM53573-Specify-ports-for-USB-LED-for-Tenda-AC9.patch @@ -0,0 +1,58 @@ +From 0173b2cd6948b5b96ac4e8dbc3bcb4dd0b45c296 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 17 Aug 2017 11:05:14 +0200 +Subject: [PATCH] ARM: BCM53573: Specify ports for USB LED for Tenda AC9 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This uses trigger-sources documented in commit 80dc6e1cd85fc ("dt-bindings: +leds: document new trigger-sources property") to specify USB ports. Such an +information can be used by operating system to setup LEDs behavior. + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/bcm47189-tenda-ac9.dts | 2 ++ + arch/arm/boot/dts/bcm53573.dtsi | 4 ++++ + 2 files changed, 6 insertions(+) + +--- a/arch/arm/boot/dts/bcm47189-tenda-ac9.dts ++++ b/arch/arm/boot/dts/bcm47189-tenda-ac9.dts +@@ -26,6 +26,8 @@ + usb { + label = "bcm53xx:blue:usb"; + gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>; ++ trigger-sources = <&ohci_port1>, <&ehci_port1>; ++ linux,default-trigger = "usbport"; + }; + + wps { +--- a/arch/arm/boot/dts/bcm53573.dtsi ++++ b/arch/arm/boot/dts/bcm53573.dtsi +@@ -138,10 +138,12 @@ + + ehci_port1: port@1 { + reg = <1>; ++ #trigger-source-cells = <0>; + }; + + ehci_port2: port@2 { + reg = <2>; ++ #trigger-source-cells = <0>; + }; + }; + +@@ -158,10 +160,12 @@ + + ohci_port1: port@1 { + reg = <1>; ++ #trigger-source-cells = <0>; + }; + + ohci_port2: port@2 { + reg = <2>; ++ #trigger-source-cells = <0>; + }; + }; + }; diff --git a/target/linux/bcm53xx/patches-4.9/035-v4.15-0001-ARM-dts-BCM5301X-Specify-USB-ports-for-USB-LED-of-Lu.patch b/target/linux/bcm53xx/patches-4.9/035-v4.15-0001-ARM-dts-BCM5301X-Specify-USB-ports-for-USB-LED-of-Lu.patch new file mode 100644 index 000000000..3148f6c32 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.9/035-v4.15-0001-ARM-dts-BCM5301X-Specify-USB-ports-for-USB-LED-of-Lu.patch @@ -0,0 +1,30 @@ +From 2460266f21f140936e627f28f28d1a4f30887ae9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 6 Oct 2017 10:52:35 +0200 +Subject: [PATCH] ARM: dts: BCM5301X: Specify USB ports for USB LED of Luxul + XWR-1200 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This info can be used by operating system to setup LED behavior. + +Reported-by: Dan Haab +Signed-off-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts ++++ b/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts +@@ -57,7 +57,8 @@ + usb { + label = "bcm53xx:green:usb"; + gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>; +- linux,default-trigger = "none"; ++ trigger-sources = <&ohci_port2>, <&ehci_port2>; ++ linux,default-trigger = "usbport"; + }; + + status { diff --git a/target/linux/bcm53xx/patches-4.9/035-v4.15-0002-ARM-dts-BCM5301X-Add-DT-for-Luxul-XBR-4500.patch b/target/linux/bcm53xx/patches-4.9/035-v4.15-0002-ARM-dts-BCM5301X-Add-DT-for-Luxul-XBR-4500.patch new file mode 100644 index 000000000..3d88f822c --- /dev/null +++ b/target/linux/bcm53xx/patches-4.9/035-v4.15-0002-ARM-dts-BCM5301X-Add-DT-for-Luxul-XBR-4500.patch @@ -0,0 +1,96 @@ +From 1f4b0d5596d2e3ea8e953d578ab8444ce860d35d Mon Sep 17 00:00:00 2001 +From: Dan Haab +Date: Mon, 9 Oct 2017 09:46:22 -0600 +Subject: [PATCH] ARM: dts: BCM5301X: Add DT for Luxul XBR-4500 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is BCM47094 (AKA BCM4709C0) based router with ports-on-the-front +board design. + +Signed-off-by: Dan Haab +Acked-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts | 63 +++++++++++++++++++++++++++ + 2 files changed, 64 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -95,6 +95,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm4709-tplink-archer-c9-v1.dtb \ + bcm47094-dlink-dir-885l.dtb \ + bcm47094-linksys-panamera.dtb \ ++ bcm47094-luxul-xbr-4500.dtb \ + bcm47094-luxul-xwr-3100.dtb \ + bcm47094-netgear-r8500.dtb \ + bcm94708.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts +@@ -0,0 +1,63 @@ ++/* ++ * Copyright (C) 2017 Luxul Inc. ++ * ++ * Licensed under the ISC license. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm4708.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" ++ ++/ { ++ compatible = "luxul,xbr-4500-v1", "brcm,bcm47094", "brcm,bcm4708"; ++ model = "Luxul XBR-4500 V1"; ++ ++ chosen { ++ bootargs = "earlycon"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x18000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ status { ++ label = "bcm53xx:green:status"; ++ gpios = <&chipcommon 20 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "timer"; ++ }; ++ ++ usb3 { ++ label = "bcm53xx:green:usb3"; ++ gpios = <&chipcommon 19 GPIO_ACTIVE_HIGH>; ++ trigger-sources = <&ohci_port1>, <&ehci_port1>, ++ <&xhci_port1>; ++ linux,default-trigger = "usbport"; ++ }; ++ ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ restart { ++ label = "Reset"; ++ linux,code = ; ++ gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&usb3 { ++ vcc-gpio = <&chipcommon 18 GPIO_ACTIVE_HIGH>; ++}; ++ ++&spi_nor { ++ status = "okay"; ++}; diff --git a/target/linux/bcm53xx/patches-4.9/035-v4.15-0003-ARM-dts-BCM5301X-Add-DT-for-Luxul-ABR-4500.patch b/target/linux/bcm53xx/patches-4.9/035-v4.15-0003-ARM-dts-BCM5301X-Add-DT-for-Luxul-ABR-4500.patch new file mode 100644 index 000000000..71384a783 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.9/035-v4.15-0003-ARM-dts-BCM5301X-Add-DT-for-Luxul-ABR-4500.patch @@ -0,0 +1,96 @@ +From 65f78c4c41a9b9a7637e1dda2d5e41cf26ea971c Mon Sep 17 00:00:00 2001 +From: Dan Haab +Date: Mon, 9 Oct 2017 09:46:23 -0600 +Subject: [PATCH] ARM: dts: BCM5301X: Add DT for Luxul ABR-4500 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is BCM47094 (AKA BCM4709C0) based router with rear-facing ports +board design. + +Signed-off-by: Dan Haab +Acked-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts | 63 +++++++++++++++++++++++++++ + 2 files changed, 64 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -95,6 +95,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm4709-tplink-archer-c9-v1.dtb \ + bcm47094-dlink-dir-885l.dtb \ + bcm47094-linksys-panamera.dtb \ ++ bcm47094-luxul-abr-4500.dtb \ + bcm47094-luxul-xbr-4500.dtb \ + bcm47094-luxul-xwr-3100.dtb \ + bcm47094-netgear-r8500.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts +@@ -0,0 +1,63 @@ ++/* ++ * Copyright (C) 2017 Luxul Inc. ++ * ++ * Licensed under the ISC license. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm4708.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" ++ ++/ { ++ compatible = "luxul,abr-4500-v1", "brcm,bcm47094", "brcm,bcm4708"; ++ model = "Luxul ABR-4500 V1"; ++ ++ chosen { ++ bootargs = "earlycon"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x18000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ status { ++ label = "bcm53xx:green:status"; ++ gpios = <&chipcommon 20 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "timer"; ++ }; ++ ++ usb3 { ++ label = "bcm53xx:green:usb3"; ++ gpios = <&chipcommon 19 GPIO_ACTIVE_LOW>; ++ trigger-sources = <&ohci_port1>, <&ehci_port1>, ++ <&xhci_port1>; ++ linux,default-trigger = "usbport"; ++ }; ++ ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ restart { ++ label = "Reset"; ++ linux,code = ; ++ gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&usb3 { ++ vcc-gpio = <&chipcommon 18 GPIO_ACTIVE_HIGH>; ++}; ++ ++&spi_nor { ++ status = "okay"; ++}; diff --git a/target/linux/bcm53xx/patches-4.9/035-v4.15-0004-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-810.patch b/target/linux/bcm53xx/patches-4.9/035-v4.15-0004-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-810.patch new file mode 100644 index 000000000..c0abc5f85 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.9/035-v4.15-0004-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-810.patch @@ -0,0 +1,120 @@ +From 0aa052ce1c3340850a7e5980b6d24b3ea5779591 Mon Sep 17 00:00:00 2001 +From: Dan Haab +Date: Mon, 9 Oct 2017 09:46:59 -0600 +Subject: [PATCH] ARM: dts: BCM53573: Add DT for Luxul XAP-810 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is BCM53573 WiSoC based access point with an extra BCM43217 chipset +used for 2.4 GHz. + +Signed-off-by: Dan Haab +Acked-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm47189-luxul-xap-810.dts | 87 ++++++++++++++++++++++++++++ + 2 files changed, 88 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm47189-luxul-xap-810.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -105,6 +105,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm953012hr.dtb \ + bcm953012k.dtb + dtb-$(CONFIG_ARCH_BCM_53573) += \ ++ bcm47189-luxul-xap-810.dtb \ + bcm47189-tenda-ac9.dtb \ + bcm947189acdbmr.dtb + dtb-$(CONFIG_ARCH_BCM_63XX) += \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts +@@ -0,0 +1,87 @@ ++/* ++ * Copyright 2017 Luxul Inc. ++ * ++ * Licensed under the ISC license. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm53573.dtsi" ++ ++/ { ++ compatible = "luxul,xap-810-v1", "brcm,bcm47189", "brcm,bcm53573"; ++ model = "Luxul XAP-810 V1"; ++ ++ chosen { ++ bootargs = "earlycon"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ 5ghz { ++ label = "bcm53xx:blue:5ghz"; ++ gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ system { ++ label = "bcm53xx:green:system"; ++ gpios = <&chipcommon 15 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "timer"; ++ }; ++ }; ++ ++ pcie0_leds { ++ compatible = "gpio-leds"; ++ ++ 2ghz { ++ label = "bcm53xx:blue:2ghz"; ++ gpios = <&pcie0_chipcommon 3 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ restart { ++ label = "Reset"; ++ linux,code = ; ++ gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&pcie0 { ++ ranges = <0x00000000 0 0 0 0 0x00100000>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ++ bridge@0,0,0 { ++ reg = <0x0000 0 0 0 0>; ++ ranges = <0x00000000 0 0 0 0 0 0 0x00100000>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ++ wifi@0,1,0 { ++ reg = <0x0000 0 0 0 0>; ++ ranges = <0x00000000 0 0 0 0x00100000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ pcie0_chipcommon: chipcommon@0 { ++ reg = <0 0x1000>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-4.9/035-v4.15-0005-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-1440.patch b/target/linux/bcm53xx/patches-4.9/035-v4.15-0005-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-1440.patch new file mode 100644 index 000000000..72bd695e6 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.9/035-v4.15-0005-ARM-dts-BCM53573-Add-DT-for-Luxul-XAP-1440.patch @@ -0,0 +1,83 @@ +From 7030ea600d560026b91726f2eb79c856b813afa9 Mon Sep 17 00:00:00 2001 +From: Dan Haab +Date: Mon, 9 Oct 2017 09:47:00 -0600 +Subject: [PATCH] ARM: dts: BCM53573: Add DT for Luxul XAP-1440 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is BCM53573 WiSoC based outdoor access point with an extra BCM43217 +chipset used for 2.4 GHz. + +Signed-off-by: Dan Haab +Acked-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts | 50 +++++++++++++++++++++++++++ + 2 files changed, 51 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -105,6 +105,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm953012hr.dtb \ + bcm953012k.dtb + dtb-$(CONFIG_ARCH_BCM_53573) += \ ++ bcm47189-luxul-xap-1440.dtb \ + bcm47189-luxul-xap-810.dtb \ + bcm47189-tenda-ac9.dtb \ + bcm947189acdbmr.dtb +--- /dev/null ++++ b/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts +@@ -0,0 +1,50 @@ ++/* ++ * Copyright 2017 Luxul Inc. ++ * ++ * Licensed under the ISC license. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm53573.dtsi" ++ ++/ { ++ compatible = "luxul,xap-1440-v1", "brcm,bcm47189", "brcm,bcm53573"; ++ model = "Luxul XAP-1440 V1"; ++ ++ chosen { ++ bootargs = "earlycon"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ wlan { ++ label = "bcm53xx:blue:wlan"; ++ gpios = <&chipcommon 10 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ system { ++ label = "bcm53xx:green:system"; ++ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "timer"; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ restart { ++ label = "Reset"; ++ linux,code = ; ++ gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-4.9/036-0001-ARM-dts-BCM5301X-Add-basic-DT-for-PHICOMM-K3.patch b/target/linux/bcm53xx/patches-4.9/036-0001-ARM-dts-BCM5301X-Add-basic-DT-for-PHICOMM-K3.patch new file mode 100644 index 000000000..9f8f86208 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.9/036-0001-ARM-dts-BCM5301X-Add-basic-DT-for-PHICOMM-K3.patch @@ -0,0 +1,68 @@ +From: Zhong LuFan +Subject: [PATCH] ARM: dts: BCM5301X: Add basic DT for PHICOMM K3 + +This router has BCM4709C0, 128MB NAND flash (MX30LF1G18AC-TI), +and 512MB memory, with 3 x LAN and 1 x WAN. WL chips are +BCM4366C0 x 2. The router has a small LCD and 3 capactive keys +driven by a PIC microcontroller, which is in turn wired to +UART1 of main board, No LED. + +Flash: +Enter CFE +CFE Brush Excess LEDE, you can get it from here: https://drive.google.com/file/d/0ByNlqhxfFBArb2owR05VUlVpN0E +Well, now you can brush into the trx file for the LEDE. + +The founder of the patch is: Tian Hao + +Signed-Off-By: Zhong LuFan + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -99,6 +99,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm47094-luxul-xbr-4500.dtb \ + bcm47094-luxul-xwr-3100.dtb \ + bcm47094-netgear-r8500.dtb \ ++ bcm47094-phicomm-k3.dtb \ + bcm94708.dtb \ + bcm94709.dtb \ + bcm953012er.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm47094-phicomm-k3.dts +@@ -0,0 +1,37 @@ ++/* ++* Copyright (C) 2017 Hamster Tian ++*/ ++ ++/dts-v1/; ++ ++#include "bcm47094.dtsi" ++#include "bcm5301x-nand-cs0-bch4.dtsi" ++ ++/ { ++ compatible = "phicomm,k3", "brcm,bcm47094", "brcm,bcm4708"; ++ model = "PHICOMM K3"; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200"; ++ }; ++ memory { ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x18000000>; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ restart { ++ label = "Reset"; ++ linux,code = ; ++ gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; diff --git a/target/linux/bcm53xx/patches-4.9/080-0003-spi-bcm53xx-simplify-reading-SPI-data.patch b/target/linux/bcm53xx/patches-4.9/080-0003-spi-bcm53xx-simplify-reading-SPI-data.patch new file mode 100644 index 000000000..ee377c491 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.9/080-0003-spi-bcm53xx-simplify-reading-SPI-data.patch @@ -0,0 +1,107 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 29 Dec 2017 14:44:09 +0100 +Subject: [PATCH] spi: bcm53xx: simplify reading SPI data +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit makes transfer function use spi_transfer_is_last to +determine if currently processed transfer is the last one. Thanks to +that we finally set hardware registers properly and it makes controller +behave the way it's expected to. + +This allows simplifying read function which can now simply start reading +from the slot 0 instead of the last saved offset. It has been +successfully tested using spi_write_then_read. + +Moreover this change fixes handling messages with two writing transfers. +It's important for SPI flash devices as their drivers commonly use one +transfer for a command and another one for data. + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +--- + drivers/spi/spi-bcm53xx.c | 26 ++++++++++---------------- + 1 file changed, 10 insertions(+), 16 deletions(-) + +--- a/drivers/spi/spi-bcm53xx.c ++++ b/drivers/spi/spi-bcm53xx.c +@@ -27,8 +27,6 @@ struct bcm53xxspi { + struct bcma_device *core; + struct spi_master *master; + void __iomem *mmio_base; +- +- size_t read_offset; + bool bspi; /* Boot SPI mode with memory mapping */ + }; + +@@ -172,8 +170,6 @@ static void bcm53xxspi_buf_write(struct + + if (!cont) + bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); +- +- b53spi->read_offset = len; + } + + static void bcm53xxspi_buf_read(struct bcm53xxspi *b53spi, u8 *r_buf, +@@ -182,10 +178,10 @@ static void bcm53xxspi_buf_read(struct b + u32 tmp; + int i; + +- for (i = 0; i < b53spi->read_offset + len; i++) { ++ for (i = 0; i < len; i++) { + tmp = B53SPI_CDRAM_CONT | B53SPI_CDRAM_PCS_DISABLE_ALL | + B53SPI_CDRAM_PCS_DSCK; +- if (!cont && i == b53spi->read_offset + len - 1) ++ if (!cont && i == len - 1) + tmp &= ~B53SPI_CDRAM_CONT; + tmp &= ~0x1; + /* Command Register File */ +@@ -194,8 +190,7 @@ static void bcm53xxspi_buf_read(struct b + + /* Set queue pointers */ + bcm53xxspi_write(b53spi, B53SPI_MSPI_NEWQP, 0); +- bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, +- b53spi->read_offset + len - 1); ++ bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, len - 1); + + if (cont) + bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 1); +@@ -214,13 +209,11 @@ static void bcm53xxspi_buf_read(struct b + bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); + + for (i = 0; i < len; ++i) { +- int offset = b53spi->read_offset + i; ++ u16 reg = B53SPI_MSPI_RXRAM + 4 * (1 + i * 2); + + /* Data stored in the transmit register file LSB */ +- r_buf[i] = (u8)bcm53xxspi_read(b53spi, B53SPI_MSPI_RXRAM + 4 * (1 + offset * 2)); ++ r_buf[i] = (u8)bcm53xxspi_read(b53spi, reg); + } +- +- b53spi->read_offset = 0; + } + + static int bcm53xxspi_transfer_one(struct spi_master *master, +@@ -238,7 +231,8 @@ static int bcm53xxspi_transfer_one(struc + left = t->len; + while (left) { + size_t to_write = min_t(size_t, 16, left); +- bool cont = left - to_write > 0; ++ bool cont = !spi_transfer_is_last(master, t) || ++ left - to_write > 0; + + bcm53xxspi_buf_write(b53spi, buf, to_write, cont); + left -= to_write; +@@ -250,9 +244,9 @@ static int bcm53xxspi_transfer_one(struc + buf = (u8 *)t->rx_buf; + left = t->len; + while (left) { +- size_t to_read = min_t(size_t, 16 - b53spi->read_offset, +- left); +- bool cont = left - to_read > 0; ++ size_t to_read = min_t(size_t, 16, left); ++ bool cont = !spi_transfer_is_last(master, t) || ++ left - to_read > 0; + + bcm53xxspi_buf_read(b53spi, buf, to_read, cont); + left -= to_read; diff --git a/target/linux/bcm53xx/patches-4.9/101-use-part-parser.patch b/target/linux/bcm53xx/patches-4.9/101-use-part-parser.patch deleted file mode 100644 index 4ecb8dc69..000000000 --- a/target/linux/bcm53xx/patches-4.9/101-use-part-parser.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/arch/arm/boot/dts/bcm5301x-nand-cs0.dtsi -+++ b/arch/arm/boot/dts/bcm5301x-nand-cs0.dtsi -@@ -13,6 +13,8 @@ - reg = <0>; - #address-cells = <1>; - #size-cells = <1>; -+ -+ linux,part-probe = "ofpart", "bcm47xxpart"; - }; - }; - }; diff --git a/target/linux/bcm53xx/patches-4.9/130-ARM-dts-BCM5301X-add-missing-LEDs-for-Buffalo-WZR-90.patch b/target/linux/bcm53xx/patches-4.9/130-ARM-dts-BCM5301X-add-missing-LEDs-for-Buffalo-WZR-90.patch new file mode 100644 index 000000000..cd691f78f --- /dev/null +++ b/target/linux/bcm53xx/patches-4.9/130-ARM-dts-BCM5301X-add-missing-LEDs-for-Buffalo-WZR-90.patch @@ -0,0 +1,95 @@ +From c830b958f52fc666919439d6f8f6caa8b6844d44 Mon Sep 17 00:00:00 2001 +From: INAGAKI Hiroshi +Date: Wed, 7 Mar 2018 20:33:56 +0900 +Subject: [PATCH] ARM: dts: BCM5301X: add missing LEDs for Buffalo WZR-900DHP +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Buffalo WZR-900DHP has 8 LEDs, but there is not LED definitions in the +dts and cannot configure these LEDs. +I Added missing LED definitions for WZR-900DHP. + +Signed-off-by: INAGAKI Hiroshi +Reviewed-by: RafaÅ‚ MiÅ‚ecki +--- + arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts | 68 +++++++++++++++++++++++ + 1 file changed, 68 insertions(+) + +--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts ++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts +@@ -35,6 +35,74 @@ + 0x88000000 0x08000000>; + }; + ++ spi { ++ compatible = "spi-gpio"; ++ num-chipselects = <1>; ++ gpio-sck = <&chipcommon 7 0>; ++ gpio-mosi = <&chipcommon 4 0>; ++ cs-gpios = <&chipcommon 6 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hc595: gpio_spi@0 { ++ compatible = "fairchild,74hc595"; ++ reg = <0>; ++ registers-number = <1>; ++ spi-max-frequency = <100000>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ usb { ++ label = "bcm53xx:green:usb"; ++ gpios = <&hc595 0 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ power0 { ++ label = "bcm53xx:green:power"; ++ gpios = <&hc595 1 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-on"; ++ }; ++ ++ power1 { ++ label = "bcm53xx:red:power"; ++ gpios = <&hc595 2 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ router0 { ++ label = "bcm53xx:green:router"; ++ gpios = <&hc595 3 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-on"; ++ }; ++ ++ router1 { ++ label = "bcm53xx:amber:router"; ++ gpios = <&hc595 4 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ wan { ++ label = "bcm53xx:green:wan"; ++ gpios = <&hc595 5 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-on"; ++ }; ++ ++ wireless0 { ++ label = "bcm53xx:green:wireless"; ++ gpios = <&hc595 6 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ wireless1 { ++ label = "bcm53xx:amber:wireless"; ++ gpios = <&hc595 7 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ + gpio-keys { + compatible = "gpio-keys"; + #address-cells = <1>; diff --git a/target/linux/bcm53xx/patches-4.9/320-ARM-dts-BCM5301X-Add-serial-to-the-bootargs.patch b/target/linux/bcm53xx/patches-4.9/320-ARM-dts-BCM5301X-Add-serial-to-the-bootargs.patch index 171e6b3bb..710d94f6b 100644 --- a/target/linux/bcm53xx/patches-4.9/320-ARM-dts-BCM5301X-Add-serial-to-the-bootargs.patch +++ b/target/linux/bcm53xx/patches-4.9/320-ARM-dts-BCM5301X-Add-serial-to-the-bootargs.patch @@ -23,4 +23,48 @@ Signed-off-by: RafaÅ‚ MiÅ‚ecki + bootargs = "console=ttyS0,115200 earlycon"; }; + memory { +--- a/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts ++++ b/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts +@@ -14,7 +14,7 @@ + model = "Luxul ABR-4500 V1"; + + chosen { +- bootargs = "earlycon"; ++ bootargs = "console=ttyS0,115200 earlycon"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts ++++ b/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts +@@ -14,7 +14,7 @@ + model = "Luxul XBR-4500 V1"; + + chosen { +- bootargs = "earlycon"; ++ bootargs = "console=ttyS0,115200 earlycon"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts ++++ b/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts +@@ -13,7 +13,7 @@ + model = "Luxul XAP-1440 V1"; + + chosen { +- bootargs = "earlycon"; ++ bootargs = "console=ttyS0,115200 earlycon"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts ++++ b/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts +@@ -13,7 +13,7 @@ + model = "Luxul XAP-810 V1"; + + chosen { +- bootargs = "earlycon"; ++ bootargs = "console=ttyS0,115200 earlycon"; + }; + memory { diff --git a/target/linux/bcm53xx/patches-4.9/401-mtd-m25p80-use-single-SPI-message-for-writing-data.patch b/target/linux/bcm53xx/patches-4.9/401-mtd-m25p80-use-single-SPI-message-for-writing-data.patch deleted file mode 100644 index 80c0e7877..000000000 --- a/target/linux/bcm53xx/patches-4.9/401-mtd-m25p80-use-single-SPI-message-for-writing-data.patch +++ /dev/null @@ -1,68 +0,0 @@ -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Subject: [PATCH] mtd: m25p80: use single SPI message for writing data -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -On all 3 tested Northstar devices with following flash memories: -mx25l6405d (8192 Kbytes) -mx25l12805d (16384 Kbytes) -mx25l25635e (32768 Kbytes) -I noticed writing to be broken. Not a single bit was changed leaving all -bytes set to 0xff. - -This is most likely some problem related to the SPI controller or its -driver. Using a single SPI message seems to workaround this. Of course -it's not perfect solution as copying whole data into a new buffer makes -writing slower. - -Signed-off-by: RafaÅ‚ MiÅ‚ecki ---- - ---- a/drivers/mtd/devices/m25p80.c -+++ b/drivers/mtd/devices/m25p80.c -@@ -78,6 +78,7 @@ static ssize_t m25p80_write(struct spi_n - { - struct m25p *flash = nor->priv; - struct spi_device *spi = flash->spi; -+ u8 *command = kzalloc(MAX_CMD_SIZE + len, GFP_KERNEL); - struct spi_transfer t[2] = {}; - struct spi_message m; - int cmd_sz = m25p_cmdsz(nor); -@@ -88,24 +89,26 @@ static ssize_t m25p80_write(struct spi_n - if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second) - cmd_sz = 1; - -- flash->command[0] = nor->program_opcode; -- m25p_addr2cmd(nor, to, flash->command); -+ command[0] = nor->program_opcode; -+ m25p_addr2cmd(nor, to, command); -+ memcpy(&command[cmd_sz], buf, len); - -- t[0].tx_buf = flash->command; -- t[0].len = cmd_sz; -+ t[0].tx_buf = command; -+ t[0].len = cmd_sz + len; - spi_message_add_tail(&t[0], &m); - -- t[1].tx_buf = buf; -- t[1].len = len; -- spi_message_add_tail(&t[1], &m); -- - ret = spi_sync(spi, &m); -- if (ret) -+ if (ret) { -+ kfree(command); - return ret; -+ } - - ret = m.actual_length - cmd_sz; -- if (ret < 0) -+ if (ret < 0) { -+ kfree(command); - return -EIO; -+ } -+ kfree(command); - return ret; - } - diff --git a/target/linux/bcm53xx/patches-4.9/410-Use-brcm-bcm947xx-cfe-partitions-binding-for-Broadco.patch b/target/linux/bcm53xx/patches-4.9/410-Use-brcm-bcm947xx-cfe-partitions-binding-for-Broadco.patch new file mode 100644 index 000000000..0eae14ff9 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.9/410-Use-brcm-bcm947xx-cfe-partitions-binding-for-Broadco.patch @@ -0,0 +1,53 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] Use "brcm,bcm947xx-cfe-partitions" binding for Broadcom + partitions + +--- + +--- a/arch/arm/boot/dts/bcm5301x-nand-cs0.dtsi ++++ b/arch/arm/boot/dts/bcm5301x-nand-cs0.dtsi +@@ -13,6 +13,10 @@ + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; ++ ++ partitions { ++ compatible = "brcm,bcm947xx-cfe-partitions"; ++ }; + }; + }; + }; +--- a/arch/arm/boot/dts/bcm5301x.dtsi ++++ b/arch/arm/boot/dts/bcm5301x.dtsi +@@ -346,8 +346,11 @@ + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <20000000>; +- linux,part-probe = "ofpart", "bcm47xxpart"; + status = "disabled"; ++ ++ partitions { ++ compatible = "brcm,bcm947xx-cfe-partitions"; ++ }; + }; + }; + +--- a/drivers/mtd/bcm47xxpart.c ++++ b/drivers/mtd/bcm47xxpart.c +@@ -300,9 +300,16 @@ static int bcm47xxpart_parse(struct mtd_ + return curr_part; + }; + ++static const struct of_device_id bcm47xxpart_of_match_table[] = { ++ { .compatible = "brcm,bcm947xx-cfe-partitions" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, bcm47xxpart_of_match_table); ++ + static struct mtd_part_parser bcm47xxpart_mtd_parser = { + .parse_fn = bcm47xxpart_parse, + .name = "bcm47xxpart", ++ .of_match_table = bcm47xxpart_of_match_table, + }; + module_mtd_part_parser(bcm47xxpart_mtd_parser); + diff --git a/target/linux/bcm53xx/patches-4.9/901-mtd-bcm47xxpart-add-partition-workaround-for-PHICOMM.patch b/target/linux/bcm53xx/patches-4.9/901-mtd-bcm47xxpart-add-partition-workaround-for-PHICOMM.patch index 713d0bde4..c7e3b7b7a 100644 --- a/target/linux/bcm53xx/patches-4.9/901-mtd-bcm47xxpart-add-partition-workaround-for-PHICOMM.patch +++ b/target/linux/bcm53xx/patches-4.9/901-mtd-bcm47xxpart-add-partition-workaround-for-PHICOMM.patch @@ -1,18 +1,13 @@ -From 60ef93a073b06876b06fb40b08663ad33895a3d3 Mon Sep 17 00:00:00 2001 -From: Tian Hao -Date: Sun, 2 Apr 2017 00:09:10 +0800 +From: Zhong LuFan Subject: [PATCH] mtd: bcm47xxpart: add partition workaround for PHICOMM K3 -Signed-off-by: Tian Hao ---- - drivers/mtd/bcm47xxpart.c | 8 ++++++++ - 1 file changed, 8 insertions(+) +The founder of the patch is: Tian Hao + +Signed-off-by: Zhong LuFan -diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c -index e796a804..64c6858f 100644 --- a/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/bcm47xxpart.c -@@ -270,6 +270,14 @@ static int bcm47xxpart_parse(struct mtd_info *master, +@@ -163,6 +163,14 @@ static int bcm47xxpart_parse(struct mtd_ */ bcm47xxpart_add_part(&parts[curr_part++], "tplink", offset, MTD_WRITEABLE); continue; @@ -25,8 +20,5 @@ index e796a804..64c6858f 100644 + bcm47xxpart_add_part(&parts[curr_part++], "phicomm", offset, MTD_WRITEABLE); + continue; } - + /* Read beginning of the block */ --- -2.11.0 - diff --git a/target/linux/bcm53xx/profiles/100-Generic.mk b/target/linux/bcm53xx/profiles/100-Generic.mk index d7e9005aa..b57258666 100644 --- a/target/linux/bcm53xx/profiles/100-Generic.mk +++ b/target/linux/bcm53xx/profiles/100-Generic.mk @@ -11,8 +11,9 @@ define Profile/Generic endef define Profile/Generic/Description - Package set compatible with hardware any Broadcom BCM47xx or BCM535x - SoC with a ARM CPU like the BCM4707, BCM4708, BCM4709, BCM53010 + Package set compatible with any hardware using Broadcom BCM47xx or + BCM535x SoCs with an ARM CPU like the BCM4707, BCM4708, BCM4709, + BCM53010 endef $(eval $(call Profile,Generic)) diff --git a/target/linux/generic/backport-4.14/011-kbuild-export-SUBARCH.patch b/target/linux/generic/backport-4.14/011-kbuild-export-SUBARCH.patch index 7080cd10a..0ce742959 100644 --- a/target/linux/generic/backport-4.14/011-kbuild-export-SUBARCH.patch +++ b/target/linux/generic/backport-4.14/011-kbuild-export-SUBARCH.patch @@ -10,10 +10,10 @@ Signed-off-by: Felix Fietkau --- a/Makefile +++ b/Makefile -@@ -410,8 +410,8 @@ KERNELRELEASE = $(shell cat include/conf - KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION) +@@ -433,8 +433,8 @@ KBUILD_CFLAGS_MODULE := -DMODULE + KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds + GCC_PLUGINS_CFLAGS := - export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION -export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC -export CPP AR NM STRIP OBJCOPY OBJDUMP HOSTLDFLAGS HOST_LOADLIBES +export ARCH SRCARCH SUBARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD diff --git a/target/linux/generic/backport-4.14/025-tcp-allow-drivers-to-tweak-TSQ-logic.patch b/target/linux/generic/backport-4.14/025-tcp-allow-drivers-to-tweak-TSQ-logic.patch index 0c57f2e33..89117bd87 100644 --- a/target/linux/generic/backport-4.14/025-tcp-allow-drivers-to-tweak-TSQ-logic.patch +++ b/target/linux/generic/backport-4.14/025-tcp-allow-drivers-to-tweak-TSQ-logic.patch @@ -44,9 +44,9 @@ Cc: Kir Kolyshkin * @sk_lingertime: %SO_LINGER l_linger setting * @sk_backlog: always used with the per-socket spinlock held * @sk_callback_lock: used with the callbacks in the end of this struct -@@ -448,6 +449,8 @@ struct sock { - kmemcheck_bitfield_end(flags); - +@@ -445,6 +446,8 @@ struct sock { + sk_type : 16; + #define SK_PROTOCOL_MAX U8_MAX u16 sk_gso_max_segs; +#define sk_pacing_shift sk_pacing_shift /* for backport checks */ + u8 sk_pacing_shift; @@ -55,7 +55,7 @@ Cc: Kir Kolyshkin rwlock_t sk_callback_lock; --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -2744,6 +2744,7 @@ void sock_init_data(struct socket *sock, +@@ -2739,6 +2739,7 @@ void sock_init_data(struct socket *sock, sk->sk_max_pacing_rate = ~0U; sk->sk_pacing_rate = ~0U; @@ -74,7 +74,7 @@ Cc: Kir Kolyshkin sk->sk_gso_max_size - 1 - MAX_TCP_HEADER); /* Goal is to send at least one packet per ms, -@@ -2145,7 +2145,7 @@ static bool tcp_small_queue_check(struct +@@ -2172,7 +2172,7 @@ static bool tcp_small_queue_check(struct { unsigned int limit; diff --git a/target/linux/generic/backport-4.14/040-crypto-fix-typo-in-KPP-dependency-of-CRYPTO_ECDH.patch b/target/linux/generic/backport-4.14/040-crypto-fix-typo-in-KPP-dependency-of-CRYPTO_ECDH.patch deleted file mode 100644 index b3e272066..000000000 --- a/target/linux/generic/backport-4.14/040-crypto-fix-typo-in-KPP-dependency-of-CRYPTO_ECDH.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 4b05f09db650d215632da97f2c25ceba8235102a Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens -Date: Sun, 26 Nov 2017 00:09:45 +0100 -Subject: [PATCH] crypto: fix typo in KPP dependency of CRYPTO_ECDH - -This fixes a typo in the CRYPTO_KPP dependency of CRYPTO_ECDH. - -Fixes: 3c4b23901a0c ("crypto: ecdh - Add ECDH software support") -Cc: # v4.8+ -Signed-off-by: Hauke Mehrtens ---- - crypto/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/crypto/Kconfig -+++ b/crypto/Kconfig -@@ -130,7 +130,7 @@ config CRYPTO_DH - - config CRYPTO_ECDH - tristate "ECDH algorithm" -- select CRYTPO_KPP -+ select CRYPTO_KPP - select CRYPTO_RNG_DEFAULT - help - Generic implementation of the ECDH algorithm diff --git a/target/linux/generic/backport-4.14/040-v4.17-0001-mtd-move-code-adding-master-MTD-out-of-mtd_add_devic.patch b/target/linux/generic/backport-4.14/040-v4.17-0001-mtd-move-code-adding-master-MTD-out-of-mtd_add_devic.patch new file mode 100644 index 000000000..df6429776 --- /dev/null +++ b/target/linux/generic/backport-4.14/040-v4.17-0001-mtd-move-code-adding-master-MTD-out-of-mtd_add_devic.patch @@ -0,0 +1,74 @@ +From 2c77c57d22adb05b21cdb333a0c42bdfa0e19835 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 16 Jan 2018 16:45:41 +0100 +Subject: [PATCH] mtd: move code adding master MTD out of + mtd_add_device_partitions() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This change is a small cleanup of mtd_device_parse_register(). When +using MTD_PARTITIONED_MASTER it makes sure a master MTD is registered +before dealing with partitions. The advantage of this is not mixing +code handling master MTD with code handling partitions. + +This commit doesn't change any behavior except from a slightly different +failure code path. The new code may need to call del_mtd_device when +something goes wrong. + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Boris Brezillon +--- + drivers/mtd/mtdcore.c | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -641,20 +641,12 @@ static int mtd_add_device_partitions(str + { + const struct mtd_partition *real_parts = parts->parts; + int nbparts = parts->nr_parts; +- int ret; + +- if (nbparts == 0 || IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) { +- ret = add_mtd_device(mtd); +- if (ret) +- return ret; +- } ++ if (!nbparts && !device_is_registered(&mtd->dev)) ++ return add_mtd_device(mtd); + +- if (nbparts > 0) { +- ret = add_mtd_partitions(mtd, real_parts, nbparts); +- if (ret && IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) +- del_mtd_device(mtd); +- return ret; +- } ++ if (nbparts > 0) ++ return add_mtd_partitions(mtd, real_parts, nbparts); + + return 0; + } +@@ -714,6 +706,12 @@ int mtd_device_parse_register(struct mtd + + mtd_set_dev_defaults(mtd); + ++ if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) { ++ ret = add_mtd_device(mtd); ++ if (ret) ++ return ret; ++ } ++ + memset(&parsed, 0, sizeof(parsed)); + + ret = parse_mtd_partitions(mtd, types, &parsed, parser_data); +@@ -753,6 +751,9 @@ int mtd_device_parse_register(struct mtd + out: + /* Cleanup any parsed partitions */ + mtd_part_parser_cleanup(&parsed); ++ if (ret && device_is_registered(&mtd->dev)) ++ del_mtd_device(mtd); ++ + return ret; + } + EXPORT_SYMBOL_GPL(mtd_device_parse_register); diff --git a/target/linux/generic/backport-4.14/040-v4.17-0002-mtd-get-rid-of-the-mtd_add_device_partitions.patch b/target/linux/generic/backport-4.14/040-v4.17-0002-mtd-get-rid-of-the-mtd_add_device_partitions.patch new file mode 100644 index 000000000..1042e674c --- /dev/null +++ b/target/linux/generic/backport-4.14/040-v4.17-0002-mtd-get-rid-of-the-mtd_add_device_partitions.patch @@ -0,0 +1,93 @@ +From 0dbe4ea78d69756efeb0bba0764f6bd4a9ee9567 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 16 Jan 2018 16:45:42 +0100 +Subject: [PATCH] mtd: get rid of the mtd_add_device_partitions() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This simplifies code a bit by: +1) Avoiding an extra (tiny) function +2) Checking for amount of parsed (found) partitions just once +3) Avoiding clearing/filling struct mtd_partitions manually + +With this commit proper functions are called directly from the +mtd_device_parse_register(). It doesn't need to use minor tricks like +memsetting struct to 0 to trigger an expected +mtd_add_device_partitions() behavior. + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +Signed-off-by: Boris Brezillon +--- + drivers/mtd/mtdcore.c | 43 ++++++++++++------------------------------- + 1 file changed, 12 insertions(+), 31 deletions(-) + +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -636,21 +636,6 @@ out_error: + return ret; + } + +-static int mtd_add_device_partitions(struct mtd_info *mtd, +- struct mtd_partitions *parts) +-{ +- const struct mtd_partition *real_parts = parts->parts; +- int nbparts = parts->nr_parts; +- +- if (!nbparts && !device_is_registered(&mtd->dev)) +- return add_mtd_device(mtd); +- +- if (nbparts > 0) +- return add_mtd_partitions(mtd, real_parts, nbparts); +- +- return 0; +-} +- + /* + * Set a few defaults based on the parent devices, if not provided by the + * driver +@@ -701,7 +686,7 @@ int mtd_device_parse_register(struct mtd + const struct mtd_partition *parts, + int nr_parts) + { +- struct mtd_partitions parsed; ++ struct mtd_partitions parsed = { }; + int ret; + + mtd_set_dev_defaults(mtd); +@@ -712,24 +697,20 @@ int mtd_device_parse_register(struct mtd + return ret; + } + +- memset(&parsed, 0, sizeof(parsed)); +- ++ /* Prefer parsed partitions over driver-provided fallback */ + ret = parse_mtd_partitions(mtd, types, &parsed, parser_data); +- if ((ret < 0 || parsed.nr_parts == 0) && parts && nr_parts) { +- /* Fall back to driver-provided partitions */ +- parsed = (struct mtd_partitions){ +- .parts = parts, +- .nr_parts = nr_parts, +- }; +- } else if (ret < 0) { +- /* Didn't come up with parsed OR fallback partitions */ +- pr_info("mtd: failed to find partitions; one or more parsers reports errors (%d)\n", +- ret); +- /* Don't abort on errors; we can still use unpartitioned MTD */ +- memset(&parsed, 0, sizeof(parsed)); ++ if (!ret && parsed.nr_parts) { ++ parts = parsed.parts; ++ nr_parts = parsed.nr_parts; + } + +- ret = mtd_add_device_partitions(mtd, &parsed); ++ if (nr_parts) ++ ret = add_mtd_partitions(mtd, parts, nr_parts); ++ else if (!device_is_registered(&mtd->dev)) ++ ret = add_mtd_device(mtd); ++ else ++ ret = 0; ++ + if (ret) + goto out; + diff --git a/target/linux/generic/backport-4.14/041-v4.16-0001-mtd-partitions-add-of_match_table-parser-matching.patch b/target/linux/generic/backport-4.14/041-v4.16-0001-mtd-partitions-add-of_match_table-parser-matching.patch deleted file mode 100644 index d698821f3..000000000 --- a/target/linux/generic/backport-4.14/041-v4.16-0001-mtd-partitions-add-of_match_table-parser-matching.patch +++ /dev/null @@ -1,121 +0,0 @@ -From bb2192123ec70470d6ea33f138846b175403a968 Mon Sep 17 00:00:00 2001 -From: Brian Norris -Date: Thu, 4 Jan 2018 08:05:33 +0100 -Subject: [PATCH] mtd: partitions: add of_match_table parser matching -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Partition parsers can now provide an of_match_table to enable -flash<-->parser matching via device tree as documented in the -mtd/partition.txt. - -It works by looking for a matching parser for every string in the -"compatibility" property (starting with the most specific one). - -This support is currently limited to built-in parsers as it uses -request_module() and friends. This should be sufficient for most cases -though as compiling parsers as modules isn't a common choice. - -Signed-off-by: Brian Norris -Signed-off-by: RafaÅ‚ MiÅ‚ecki -Signed-off-by: Boris Brezillon ---- - drivers/mtd/mtdpart.c | 59 ++++++++++++++++++++++++++++++++++++++++++ - include/linux/mtd/partitions.h | 1 + - 2 files changed, 60 insertions(+) - ---- a/drivers/mtd/mtdpart.c -+++ b/drivers/mtd/mtdpart.c -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - - #include "mtdcore.h" - -@@ -894,6 +895,45 @@ static int mtd_part_do_parse(struct mtd_ - } - - /** -+ * mtd_part_get_compatible_parser - find MTD parser by a compatible string -+ * -+ * @compat: compatible string describing partitions in a device tree -+ * -+ * MTD parsers can specify supported partitions by providing a table of -+ * compatibility strings. This function finds a parser that advertises support -+ * for a passed value of "compatible". -+ */ -+static struct mtd_part_parser *mtd_part_get_compatible_parser(const char *compat) -+{ -+ struct mtd_part_parser *p, *ret = NULL; -+ -+ spin_lock(&part_parser_lock); -+ -+ list_for_each_entry(p, &part_parsers, list) { -+ const struct of_device_id *matches; -+ -+ matches = p->of_match_table; -+ if (!matches) -+ continue; -+ -+ for (; matches->compatible[0]; matches++) { -+ if (!strcmp(matches->compatible, compat) && -+ try_module_get(p->owner)) { -+ ret = p; -+ break; -+ } -+ } -+ -+ if (ret) -+ break; -+ } -+ -+ spin_unlock(&part_parser_lock); -+ -+ return ret; -+} -+ -+/** - * parse_mtd_partitions - parse MTD partitions - * @master: the master partition (describes whole MTD device) - * @types: names of partition parsers to try or %NULL -@@ -919,8 +959,27 @@ int parse_mtd_partitions(struct mtd_info - struct mtd_part_parser_data *data) - { - struct mtd_part_parser *parser; -+ struct device_node *np; -+ struct property *prop; -+ const char *compat; - int ret, err = 0; - -+ np = of_get_child_by_name(mtd_get_of_node(master), "partitions"); -+ of_property_for_each_string(np, "compatible", prop, compat) { -+ parser = mtd_part_get_compatible_parser(compat); -+ if (!parser) -+ continue; -+ ret = mtd_part_do_parse(parser, master, pparts, data); -+ if (ret > 0) { -+ of_node_put(np); -+ return 0; -+ } -+ mtd_part_parser_put(parser); -+ if (ret < 0 && !err) -+ err = ret; -+ } -+ of_node_put(np); -+ - if (!types) - types = default_mtd_part_types; - ---- a/include/linux/mtd/partitions.h -+++ b/include/linux/mtd/partitions.h -@@ -77,6 +77,7 @@ struct mtd_part_parser { - struct list_head list; - struct module *owner; - const char *name; -+ const struct of_device_id *of_match_table; - int (*parse_fn)(struct mtd_info *, const struct mtd_partition **, - struct mtd_part_parser_data *); - void (*cleanup)(const struct mtd_partition *pparts, int nr_parts); diff --git a/target/linux/generic/pending-4.14/272-uapi-if_ether.h-prevent-redefinition-of-struct-ethhd.patch b/target/linux/generic/backport-4.14/272-uapi-if_ether.h-prevent-redefinition-of-struct-ethhd.patch similarity index 50% rename from target/linux/generic/pending-4.14/272-uapi-if_ether.h-prevent-redefinition-of-struct-ethhd.patch rename to target/linux/generic/backport-4.14/272-uapi-if_ether.h-prevent-redefinition-of-struct-ethhd.patch index 1dca07328..784c548c8 100644 --- a/target/linux/generic/pending-4.14/272-uapi-if_ether.h-prevent-redefinition-of-struct-ethhd.patch +++ b/target/linux/generic/backport-4.14/272-uapi-if_ether.h-prevent-redefinition-of-struct-ethhd.patch @@ -1,16 +1,20 @@ -From: David Heidelberger +From 649affd04813c43e0a72886517fcfccd63230981 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Mon, 29 Jun 2015 16:53:03 +0200 Subject: uapi/if_ether.h: prevent redefinition of struct ethhdr Musl provides its own ethhdr struct definition. Add a guard to prevent its definition of the appropriate musl header has already been included. -Signed-off-by: John Spencer -Tested-by: David Heidelberger -Signed-off-by: Jonas Gorski +glibc does not implement this header, but when glibc will implement this +they can just define __UAPI_DEF_ETHHDR 0 to make it work with the +kernel. + +Signed-off-by: Hauke Mehrtens --- - include/uapi/linux/if_ether.h | 3 +++ - include/uapi/linux/libc-compat.h | 11 +++++++++++ - 2 files changed, 14 insertions(+) + include/uapi/linux/if_ether.h | 3 +++ + include/uapi/linux/libc-compat.h | 6 ++++++ + 2 files changed, 9 insertions(+) --- a/include/uapi/linux/if_ether.h +++ b/include/uapi/linux/if_ether.h @@ -38,28 +42,14 @@ Signed-off-by: Jonas Gorski #endif /* _UAPI_LINUX_IF_ETHER_H */ --- a/include/uapi/linux/libc-compat.h +++ b/include/uapi/linux/libc-compat.h -@@ -90,6 +90,14 @@ +@@ -264,4 +264,10 @@ - #endif /* _NET_IF_H */ + #endif /* __GLIBC__ */ -+/* musl defines the ethhdr struct itself in its netinet/if_ether.h. -+ * Glibc just includes the kernel header and uses a different guard. */ -+#if defined(_NETINET_IF_ETHER_H) -+#define __UAPI_DEF_ETHHDR 0 -+#else ++/* Definitions for if_ether.h */ ++/* allow libcs like musl to deactivate this, glibc does not implement this. */ ++#ifndef __UAPI_DEF_ETHHDR +#define __UAPI_DEF_ETHHDR 1 +#endif + - /* Coordinate with libc netinet/in.h header. */ - #if defined(_NETINET_IN_H) - -@@ -185,6 +193,9 @@ - /* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */ - #define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1 - -+/* Definitions for if_ether.h */ -+#define __UAPI_DEF_ETHHDR 1 -+ - /* Definitions for in.h */ - #define __UAPI_DEF_IN_ADDR 1 - #define __UAPI_DEF_IN_IPPROTO 1 + #endif /* _UAPI_LIBC_COMPAT_H */ diff --git a/target/linux/generic/backport-4.14/300-netfilter-nf_tables-explicit-nft_set_pktinfo-call-fr.patch b/target/linux/generic/backport-4.14/300-netfilter-nf_tables-explicit-nft_set_pktinfo-call-fr.patch new file mode 100644 index 000000000..c0cb5bbeb --- /dev/null +++ b/target/linux/generic/backport-4.14/300-netfilter-nf_tables-explicit-nft_set_pktinfo-call-fr.patch @@ -0,0 +1,291 @@ +From: Pablo Neira Ayuso +Date: Sun, 10 Dec 2017 01:43:14 +0100 +Subject: [PATCH] netfilter: nf_tables: explicit nft_set_pktinfo() call from + hook path + +Instead of calling this function from the family specific variant, this +reduces the code size in the fast path for the netdev, bridge and inet +families. After this change, we must call nft_set_pktinfo() upfront from +the chain hook indirection. + +Before: + + text data bss dec hex filename + 2145 208 0 2353 931 net/netfilter/nf_tables_netdev.o + +After: + + text data bss dec hex filename + 2125 208 0 2333 91d net/netfilter/nf_tables_netdev.o + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -54,8 +54,8 @@ static inline void nft_set_pktinfo(struc + pkt->xt.state = state; + } + +-static inline void nft_set_pktinfo_proto_unspec(struct nft_pktinfo *pkt, +- struct sk_buff *skb) ++static inline void nft_set_pktinfo_unspec(struct nft_pktinfo *pkt, ++ struct sk_buff *skb) + { + pkt->tprot_set = false; + pkt->tprot = 0; +@@ -63,14 +63,6 @@ static inline void nft_set_pktinfo_proto + pkt->xt.fragoff = 0; + } + +-static inline void nft_set_pktinfo_unspec(struct nft_pktinfo *pkt, +- struct sk_buff *skb, +- const struct nf_hook_state *state) +-{ +- nft_set_pktinfo(pkt, skb, state); +- nft_set_pktinfo_proto_unspec(pkt, skb); +-} +- + /** + * struct nft_verdict - nf_tables verdict + * +--- a/include/net/netfilter/nf_tables_ipv4.h ++++ b/include/net/netfilter/nf_tables_ipv4.h +@@ -5,15 +5,11 @@ + #include + #include + +-static inline void +-nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt, +- struct sk_buff *skb, +- const struct nf_hook_state *state) ++static inline void nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt, ++ struct sk_buff *skb) + { + struct iphdr *ip; + +- nft_set_pktinfo(pkt, skb, state); +- + ip = ip_hdr(pkt->skb); + pkt->tprot_set = true; + pkt->tprot = ip->protocol; +@@ -21,10 +17,8 @@ nft_set_pktinfo_ipv4(struct nft_pktinfo + pkt->xt.fragoff = ntohs(ip->frag_off) & IP_OFFSET; + } + +-static inline int +-__nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt, +- struct sk_buff *skb, +- const struct nf_hook_state *state) ++static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt, ++ struct sk_buff *skb) + { + struct iphdr *iph, _iph; + u32 len, thoff; +@@ -52,14 +46,11 @@ __nft_set_pktinfo_ipv4_validate(struct n + return 0; + } + +-static inline void +-nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt, +- struct sk_buff *skb, +- const struct nf_hook_state *state) ++static inline void nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt, ++ struct sk_buff *skb) + { +- nft_set_pktinfo(pkt, skb, state); +- if (__nft_set_pktinfo_ipv4_validate(pkt, skb, state) < 0) +- nft_set_pktinfo_proto_unspec(pkt, skb); ++ if (__nft_set_pktinfo_ipv4_validate(pkt, skb) < 0) ++ nft_set_pktinfo_unspec(pkt, skb); + } + + extern struct nft_af_info nft_af_ipv4; +--- a/include/net/netfilter/nf_tables_ipv6.h ++++ b/include/net/netfilter/nf_tables_ipv6.h +@@ -5,20 +5,16 @@ + #include + #include + +-static inline void +-nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt, +- struct sk_buff *skb, +- const struct nf_hook_state *state) ++static inline void nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt, ++ struct sk_buff *skb) + { + unsigned int flags = IP6_FH_F_AUTH; + int protohdr, thoff = 0; + unsigned short frag_off; + +- nft_set_pktinfo(pkt, skb, state); +- + protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags); + if (protohdr < 0) { +- nft_set_pktinfo_proto_unspec(pkt, skb); ++ nft_set_pktinfo_unspec(pkt, skb); + return; + } + +@@ -28,10 +24,8 @@ nft_set_pktinfo_ipv6(struct nft_pktinfo + pkt->xt.fragoff = frag_off; + } + +-static inline int +-__nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, +- struct sk_buff *skb, +- const struct nf_hook_state *state) ++static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, ++ struct sk_buff *skb) + { + #if IS_ENABLED(CONFIG_IPV6) + unsigned int flags = IP6_FH_F_AUTH; +@@ -68,14 +62,11 @@ __nft_set_pktinfo_ipv6_validate(struct n + #endif + } + +-static inline void +-nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, +- struct sk_buff *skb, +- const struct nf_hook_state *state) ++static inline void nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt, ++ struct sk_buff *skb) + { +- nft_set_pktinfo(pkt, skb, state); +- if (__nft_set_pktinfo_ipv6_validate(pkt, skb, state) < 0) +- nft_set_pktinfo_proto_unspec(pkt, skb); ++ if (__nft_set_pktinfo_ipv6_validate(pkt, skb) < 0) ++ nft_set_pktinfo_unspec(pkt, skb); + } + + extern struct nft_af_info nft_af_ipv6; +--- a/net/bridge/netfilter/nf_tables_bridge.c ++++ b/net/bridge/netfilter/nf_tables_bridge.c +@@ -25,15 +25,17 @@ nft_do_chain_bridge(void *priv, + { + struct nft_pktinfo pkt; + ++ nft_set_pktinfo(&pkt, skb, state); ++ + switch (eth_hdr(skb)->h_proto) { + case htons(ETH_P_IP): +- nft_set_pktinfo_ipv4_validate(&pkt, skb, state); ++ nft_set_pktinfo_ipv4_validate(&pkt, skb); + break; + case htons(ETH_P_IPV6): +- nft_set_pktinfo_ipv6_validate(&pkt, skb, state); ++ nft_set_pktinfo_ipv6_validate(&pkt, skb); + break; + default: +- nft_set_pktinfo_unspec(&pkt, skb, state); ++ nft_set_pktinfo_unspec(&pkt, skb); + break; + } + +--- a/net/ipv4/netfilter/nf_tables_arp.c ++++ b/net/ipv4/netfilter/nf_tables_arp.c +@@ -21,7 +21,8 @@ nft_do_chain_arp(void *priv, + { + struct nft_pktinfo pkt; + +- nft_set_pktinfo_unspec(&pkt, skb, state); ++ nft_set_pktinfo(&pkt, skb, state); ++ nft_set_pktinfo_unspec(&pkt, skb); + + return nft_do_chain(&pkt, priv); + } +--- a/net/ipv4/netfilter/nf_tables_ipv4.c ++++ b/net/ipv4/netfilter/nf_tables_ipv4.c +@@ -24,7 +24,8 @@ static unsigned int nft_do_chain_ipv4(vo + { + struct nft_pktinfo pkt; + +- nft_set_pktinfo_ipv4(&pkt, skb, state); ++ nft_set_pktinfo(&pkt, skb, state); ++ nft_set_pktinfo_ipv4(&pkt, skb); + + return nft_do_chain(&pkt, priv); + } +--- a/net/ipv4/netfilter/nft_chain_nat_ipv4.c ++++ b/net/ipv4/netfilter/nft_chain_nat_ipv4.c +@@ -33,7 +33,8 @@ static unsigned int nft_nat_do_chain(voi + { + struct nft_pktinfo pkt; + +- nft_set_pktinfo_ipv4(&pkt, skb, state); ++ nft_set_pktinfo(&pkt, skb, state); ++ nft_set_pktinfo_ipv4(&pkt, skb); + + return nft_do_chain(&pkt, priv); + } +--- a/net/ipv4/netfilter/nft_chain_route_ipv4.c ++++ b/net/ipv4/netfilter/nft_chain_route_ipv4.c +@@ -38,7 +38,8 @@ static unsigned int nf_route_table_hook( + ip_hdrlen(skb) < sizeof(struct iphdr)) + return NF_ACCEPT; + +- nft_set_pktinfo_ipv4(&pkt, skb, state); ++ nft_set_pktinfo(&pkt, skb, state); ++ nft_set_pktinfo_ipv4(&pkt, skb); + + mark = skb->mark; + iph = ip_hdr(skb); +--- a/net/ipv6/netfilter/nf_tables_ipv6.c ++++ b/net/ipv6/netfilter/nf_tables_ipv6.c +@@ -22,7 +22,8 @@ static unsigned int nft_do_chain_ipv6(vo + { + struct nft_pktinfo pkt; + +- nft_set_pktinfo_ipv6(&pkt, skb, state); ++ nft_set_pktinfo(&pkt, skb, state); ++ nft_set_pktinfo_ipv6(&pkt, skb); + + return nft_do_chain(&pkt, priv); + } +--- a/net/ipv6/netfilter/nft_chain_nat_ipv6.c ++++ b/net/ipv6/netfilter/nft_chain_nat_ipv6.c +@@ -31,7 +31,8 @@ static unsigned int nft_nat_do_chain(voi + { + struct nft_pktinfo pkt; + +- nft_set_pktinfo_ipv6(&pkt, skb, state); ++ nft_set_pktinfo(&pkt, skb, state); ++ nft_set_pktinfo_ipv6(&pkt, skb); + + return nft_do_chain(&pkt, priv); + } +--- a/net/ipv6/netfilter/nft_chain_route_ipv6.c ++++ b/net/ipv6/netfilter/nft_chain_route_ipv6.c +@@ -33,7 +33,8 @@ static unsigned int nf_route_table_hook( + u32 mark, flowlabel; + int err; + +- nft_set_pktinfo_ipv6(&pkt, skb, state); ++ nft_set_pktinfo(&pkt, skb, state); ++ nft_set_pktinfo_ipv6(&pkt, skb); + + /* save source/dest address, mark, hoplimit, flowlabel, priority */ + memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr)); +--- a/net/netfilter/nf_tables_netdev.c ++++ b/net/netfilter/nf_tables_netdev.c +@@ -21,15 +21,17 @@ nft_do_chain_netdev(void *priv, struct s + { + struct nft_pktinfo pkt; + ++ nft_set_pktinfo(&pkt, skb, state); ++ + switch (skb->protocol) { + case htons(ETH_P_IP): +- nft_set_pktinfo_ipv4_validate(&pkt, skb, state); ++ nft_set_pktinfo_ipv4_validate(&pkt, skb); + break; + case htons(ETH_P_IPV6): +- nft_set_pktinfo_ipv6_validate(&pkt, skb, state); ++ nft_set_pktinfo_ipv6_validate(&pkt, skb); + break; + default: +- nft_set_pktinfo_unspec(&pkt, skb, state); ++ nft_set_pktinfo_unspec(&pkt, skb); + break; + } + diff --git a/target/linux/generic/backport-4.14/301-netfilter-core-only-allow-one-nat-hook-per-hook-poin.patch b/target/linux/generic/backport-4.14/301-netfilter-core-only-allow-one-nat-hook-per-hook-poin.patch new file mode 100644 index 000000000..711eca035 --- /dev/null +++ b/target/linux/generic/backport-4.14/301-netfilter-core-only-allow-one-nat-hook-per-hook-poin.patch @@ -0,0 +1,146 @@ +From: Florian Westphal +Date: Fri, 8 Dec 2017 17:01:54 +0100 +Subject: [PATCH] netfilter: core: only allow one nat hook per hook point + +The netfilter NAT core cannot deal with more than one NAT hook per hook +location (prerouting, input ...), because the NAT hooks install a NAT null +binding in case the iptables nat table (iptable_nat hooks) or the +corresponding nftables chain (nft nat hooks) doesn't specify a nat +transformation. + +Null bindings are needed to detect port collsisions between NAT-ed and +non-NAT-ed connections. + +This causes nftables NAT rules to not work when iptable_nat module is +loaded, and vice versa because nat binding has already been attached +when the second nat hook is consulted. + +The netfilter core is not really the correct location to handle this +(hooks are just hooks, the core has no notion of what kinds of side + effects a hook implements), but its the only place where we can check +for conflicts between both iptables hooks and nftables hooks without +adding dependencies. + +So add nat annotation to hook_ops to describe those hooks that will +add NAT bindings and then make core reject if such a hook already exists. +The annotation fills a padding hole, in case further restrictions appar +we might change this to a 'u8 type' instead of bool. + +iptables error if nft nat hook active: +iptables -t nat -A POSTROUTING -j MASQUERADE +iptables v1.4.21: can't initialize iptables table `nat': File exists +Perhaps iptables or your kernel needs to be upgraded. + +nftables error if iptables nat table present: +nft -f /etc/nftables/ipv4-nat +/usr/etc/nftables/ipv4-nat:3:1-2: Error: Could not process rule: File exists +table nat { +^^ + +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/linux/netfilter.h ++++ b/include/linux/netfilter.h +@@ -67,6 +67,7 @@ struct nf_hook_ops { + struct net_device *dev; + void *priv; + u_int8_t pf; ++ bool nat_hook; + unsigned int hooknum; + /* Hooks are ordered in ascending priority. */ + int priority; +--- a/net/ipv4/netfilter/iptable_nat.c ++++ b/net/ipv4/netfilter/iptable_nat.c +@@ -72,6 +72,7 @@ static const struct nf_hook_ops nf_nat_i + { + .hook = iptable_nat_ipv4_in, + .pf = NFPROTO_IPV4, ++ .nat_hook = true, + .hooknum = NF_INET_PRE_ROUTING, + .priority = NF_IP_PRI_NAT_DST, + }, +@@ -79,6 +80,7 @@ static const struct nf_hook_ops nf_nat_i + { + .hook = iptable_nat_ipv4_out, + .pf = NFPROTO_IPV4, ++ .nat_hook = true, + .hooknum = NF_INET_POST_ROUTING, + .priority = NF_IP_PRI_NAT_SRC, + }, +@@ -86,6 +88,7 @@ static const struct nf_hook_ops nf_nat_i + { + .hook = iptable_nat_ipv4_local_fn, + .pf = NFPROTO_IPV4, ++ .nat_hook = true, + .hooknum = NF_INET_LOCAL_OUT, + .priority = NF_IP_PRI_NAT_DST, + }, +@@ -93,6 +96,7 @@ static const struct nf_hook_ops nf_nat_i + { + .hook = iptable_nat_ipv4_fn, + .pf = NFPROTO_IPV4, ++ .nat_hook = true, + .hooknum = NF_INET_LOCAL_IN, + .priority = NF_IP_PRI_NAT_SRC, + }, +--- a/net/ipv6/netfilter/ip6table_nat.c ++++ b/net/ipv6/netfilter/ip6table_nat.c +@@ -74,6 +74,7 @@ static const struct nf_hook_ops nf_nat_i + { + .hook = ip6table_nat_in, + .pf = NFPROTO_IPV6, ++ .nat_hook = true, + .hooknum = NF_INET_PRE_ROUTING, + .priority = NF_IP6_PRI_NAT_DST, + }, +@@ -81,6 +82,7 @@ static const struct nf_hook_ops nf_nat_i + { + .hook = ip6table_nat_out, + .pf = NFPROTO_IPV6, ++ .nat_hook = true, + .hooknum = NF_INET_POST_ROUTING, + .priority = NF_IP6_PRI_NAT_SRC, + }, +@@ -88,12 +90,14 @@ static const struct nf_hook_ops nf_nat_i + { + .hook = ip6table_nat_local_fn, + .pf = NFPROTO_IPV6, ++ .nat_hook = true, + .hooknum = NF_INET_LOCAL_OUT, + .priority = NF_IP6_PRI_NAT_DST, + }, + /* After packet filtering, change source */ + { + .hook = ip6table_nat_fn, ++ .nat_hook = true, + .pf = NFPROTO_IPV6, + .hooknum = NF_INET_LOCAL_IN, + .priority = NF_IP6_PRI_NAT_SRC, +--- a/net/netfilter/core.c ++++ b/net/netfilter/core.c +@@ -135,6 +135,12 @@ nf_hook_entries_grow(const struct nf_hoo + ++i; + continue; + } ++ ++ if (reg->nat_hook && orig_ops[i]->nat_hook) { ++ kvfree(new); ++ return ERR_PTR(-EEXIST); ++ } ++ + if (inserted || reg->priority > orig_ops[i]->priority) { + new_ops[nhooks] = (void *)orig_ops[i]; + new->hooks[nhooks] = old->hooks[i]; +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -1400,6 +1400,8 @@ static int nf_tables_addchain(struct nft + ops->hook = hookfn; + if (afi->hook_ops_init) + afi->hook_ops_init(ops, i); ++ if (basechain->type->type == NFT_CHAIN_T_NAT) ++ ops->nat_hook = true; + } + + chain->flags |= NFT_BASE_CHAIN; diff --git a/target/linux/generic/backport-4.14/302-netfilter-nf_tables_inet-don-t-use-multihook-infrast.patch b/target/linux/generic/backport-4.14/302-netfilter-nf_tables_inet-don-t-use-multihook-infrast.patch new file mode 100644 index 000000000..17d8b21a0 --- /dev/null +++ b/target/linux/generic/backport-4.14/302-netfilter-nf_tables_inet-don-t-use-multihook-infrast.patch @@ -0,0 +1,161 @@ +From: Pablo Neira Ayuso +Date: Sat, 9 Dec 2017 15:36:24 +0100 +Subject: [PATCH] netfilter: nf_tables_inet: don't use multihook infrastructure + anymore + +Use new native NFPROTO_INET support in netfilter core, this gets rid of +ad-hoc code in the nf_tables API codebase. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_tables_ipv4.h ++++ b/include/net/netfilter/nf_tables_ipv4.h +@@ -53,6 +53,4 @@ static inline void nft_set_pktinfo_ipv4_ + nft_set_pktinfo_unspec(pkt, skb); + } + +-extern struct nft_af_info nft_af_ipv4; +- + #endif +--- a/include/net/netfilter/nf_tables_ipv6.h ++++ b/include/net/netfilter/nf_tables_ipv6.h +@@ -69,6 +69,4 @@ static inline void nft_set_pktinfo_ipv6_ + nft_set_pktinfo_unspec(pkt, skb); + } + +-extern struct nft_af_info nft_af_ipv6; +- + #endif +--- a/net/ipv4/netfilter/nf_tables_ipv4.c ++++ b/net/ipv4/netfilter/nf_tables_ipv4.c +@@ -45,7 +45,7 @@ static unsigned int nft_ipv4_output(void + return nft_do_chain_ipv4(priv, skb, state); + } + +-struct nft_af_info nft_af_ipv4 __read_mostly = { ++static struct nft_af_info nft_af_ipv4 __read_mostly = { + .family = NFPROTO_IPV4, + .nhooks = NF_INET_NUMHOOKS, + .owner = THIS_MODULE, +@@ -58,7 +58,6 @@ struct nft_af_info nft_af_ipv4 __read_mo + [NF_INET_POST_ROUTING] = nft_do_chain_ipv4, + }, + }; +-EXPORT_SYMBOL_GPL(nft_af_ipv4); + + static int nf_tables_ipv4_init_net(struct net *net) + { +--- a/net/ipv6/netfilter/nf_tables_ipv6.c ++++ b/net/ipv6/netfilter/nf_tables_ipv6.c +@@ -42,7 +42,7 @@ static unsigned int nft_ipv6_output(void + return nft_do_chain_ipv6(priv, skb, state); + } + +-struct nft_af_info nft_af_ipv6 __read_mostly = { ++static struct nft_af_info nft_af_ipv6 __read_mostly = { + .family = NFPROTO_IPV6, + .nhooks = NF_INET_NUMHOOKS, + .owner = THIS_MODULE, +@@ -55,7 +55,6 @@ struct nft_af_info nft_af_ipv6 __read_mo + [NF_INET_POST_ROUTING] = nft_do_chain_ipv6, + }, + }; +-EXPORT_SYMBOL_GPL(nft_af_ipv6); + + static int nf_tables_ipv6_init_net(struct net *net) + { +--- a/net/netfilter/nf_tables_inet.c ++++ b/net/netfilter/nf_tables_inet.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -16,26 +17,71 @@ + #include + #include + +-static void nft_inet_hook_ops_init(struct nf_hook_ops *ops, unsigned int n) ++static unsigned int nft_do_chain_inet(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) + { +- struct nft_af_info *afi; ++ struct nft_pktinfo pkt; + +- if (n == 1) +- afi = &nft_af_ipv4; +- else +- afi = &nft_af_ipv6; +- +- ops->pf = afi->family; +- if (afi->hooks[ops->hooknum]) +- ops->hook = afi->hooks[ops->hooknum]; ++ nft_set_pktinfo(&pkt, skb, state); ++ ++ switch (state->pf) { ++ case NFPROTO_IPV4: ++ nft_set_pktinfo_ipv4(&pkt, skb); ++ break; ++ case NFPROTO_IPV6: ++ nft_set_pktinfo_ipv6(&pkt, skb); ++ break; ++ default: ++ break; ++ } ++ ++ return nft_do_chain(&pkt, priv); ++} ++ ++static unsigned int nft_inet_output(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++{ ++ struct nft_pktinfo pkt; ++ ++ nft_set_pktinfo(&pkt, skb, state); ++ ++ switch (state->pf) { ++ case NFPROTO_IPV4: ++ if (unlikely(skb->len < sizeof(struct iphdr) || ++ ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) { ++ if (net_ratelimit()) ++ pr_info("ignoring short SOCK_RAW packet\n"); ++ return NF_ACCEPT; ++ } ++ nft_set_pktinfo_ipv4(&pkt, skb); ++ break; ++ case NFPROTO_IPV6: ++ if (unlikely(skb->len < sizeof(struct ipv6hdr))) { ++ if (net_ratelimit()) ++ pr_info("ignoring short SOCK_RAW packet\n"); ++ return NF_ACCEPT; ++ } ++ nft_set_pktinfo_ipv6(&pkt, skb); ++ break; ++ default: ++ break; ++ } ++ ++ return nft_do_chain(&pkt, priv); + } + + static struct nft_af_info nft_af_inet __read_mostly = { + .family = NFPROTO_INET, + .nhooks = NF_INET_NUMHOOKS, + .owner = THIS_MODULE, +- .nops = 2, +- .hook_ops_init = nft_inet_hook_ops_init, ++ .nops = 1, ++ .hooks = { ++ [NF_INET_LOCAL_IN] = nft_do_chain_inet, ++ [NF_INET_LOCAL_OUT] = nft_inet_output, ++ [NF_INET_FORWARD] = nft_do_chain_inet, ++ [NF_INET_PRE_ROUTING] = nft_do_chain_inet, ++ [NF_INET_POST_ROUTING] = nft_do_chain_inet, ++ }, + }; + + static int __net_init nf_tables_inet_init_net(struct net *net) diff --git a/target/linux/generic/backport-4.14/303-netfilter-nf_tables-remove-multihook-chains-and-fami.patch b/target/linux/generic/backport-4.14/303-netfilter-nf_tables-remove-multihook-chains-and-fami.patch new file mode 100644 index 000000000..37c63ec6c --- /dev/null +++ b/target/linux/generic/backport-4.14/303-netfilter-nf_tables-remove-multihook-chains-and-fami.patch @@ -0,0 +1,391 @@ +From: Pablo Neira Ayuso +Date: Sat, 9 Dec 2017 15:40:25 +0100 +Subject: [PATCH] netfilter: nf_tables: remove multihook chains and families + +Since NFPROTO_INET is handled from the core, we don't need to maintain +extra infrastructure in nf_tables to handle the double hook +registration, one for IPv4 and another for IPv6. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -892,8 +892,6 @@ struct nft_stats { + struct u64_stats_sync syncp; + }; + +-#define NFT_HOOK_OPS_MAX 2 +- + /** + * struct nft_base_chain - nf_tables base chain + * +@@ -905,7 +903,7 @@ struct nft_stats { + * @dev_name: device name that this base chain is attached to (if any) + */ + struct nft_base_chain { +- struct nf_hook_ops ops[NFT_HOOK_OPS_MAX]; ++ struct nf_hook_ops ops; + const struct nf_chain_type *type; + u8 policy; + u8 flags; +@@ -966,8 +964,6 @@ enum nft_af_flags { + * @owner: module owner + * @tables: used internally + * @flags: family flags +- * @nops: number of hook ops in this family +- * @hook_ops_init: initialization function for chain hook ops + * @hooks: hookfn overrides for packet validation + */ + struct nft_af_info { +@@ -977,9 +973,6 @@ struct nft_af_info { + struct module *owner; + struct list_head tables; + u32 flags; +- unsigned int nops; +- void (*hook_ops_init)(struct nf_hook_ops *, +- unsigned int); + nf_hookfn *hooks[NF_MAX_HOOKS]; + }; + +--- a/net/bridge/netfilter/nf_tables_bridge.c ++++ b/net/bridge/netfilter/nf_tables_bridge.c +@@ -46,7 +46,6 @@ static struct nft_af_info nft_af_bridge + .family = NFPROTO_BRIDGE, + .nhooks = NF_BR_NUMHOOKS, + .owner = THIS_MODULE, +- .nops = 1, + .hooks = { + [NF_BR_PRE_ROUTING] = nft_do_chain_bridge, + [NF_BR_LOCAL_IN] = nft_do_chain_bridge, +--- a/net/ipv4/netfilter/nf_tables_arp.c ++++ b/net/ipv4/netfilter/nf_tables_arp.c +@@ -31,7 +31,6 @@ static struct nft_af_info nft_af_arp __r + .family = NFPROTO_ARP, + .nhooks = NF_ARP_NUMHOOKS, + .owner = THIS_MODULE, +- .nops = 1, + .hooks = { + [NF_ARP_IN] = nft_do_chain_arp, + [NF_ARP_OUT] = nft_do_chain_arp, +--- a/net/ipv4/netfilter/nf_tables_ipv4.c ++++ b/net/ipv4/netfilter/nf_tables_ipv4.c +@@ -49,7 +49,6 @@ static struct nft_af_info nft_af_ipv4 __ + .family = NFPROTO_IPV4, + .nhooks = NF_INET_NUMHOOKS, + .owner = THIS_MODULE, +- .nops = 1, + .hooks = { + [NF_INET_LOCAL_IN] = nft_do_chain_ipv4, + [NF_INET_LOCAL_OUT] = nft_ipv4_output, +--- a/net/ipv6/netfilter/nf_tables_ipv6.c ++++ b/net/ipv6/netfilter/nf_tables_ipv6.c +@@ -46,7 +46,6 @@ static struct nft_af_info nft_af_ipv6 __ + .family = NFPROTO_IPV6, + .nhooks = NF_INET_NUMHOOKS, + .owner = THIS_MODULE, +- .nops = 1, + .hooks = { + [NF_INET_LOCAL_IN] = nft_do_chain_ipv6, + [NF_INET_LOCAL_OUT] = nft_ipv6_output, +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -139,29 +139,26 @@ static void nft_trans_destroy(struct nft + kfree(trans); + } + +-static int nf_tables_register_hooks(struct net *net, +- const struct nft_table *table, +- struct nft_chain *chain, +- unsigned int hook_nops) ++static int nf_tables_register_hook(struct net *net, ++ const struct nft_table *table, ++ struct nft_chain *chain) + { + if (table->flags & NFT_TABLE_F_DORMANT || + !nft_is_base_chain(chain)) + return 0; + +- return nf_register_net_hooks(net, nft_base_chain(chain)->ops, +- hook_nops); ++ return nf_register_net_hook(net, &nft_base_chain(chain)->ops); + } + +-static void nf_tables_unregister_hooks(struct net *net, +- const struct nft_table *table, +- struct nft_chain *chain, +- unsigned int hook_nops) ++static void nf_tables_unregister_hook(struct net *net, ++ const struct nft_table *table, ++ struct nft_chain *chain) + { + if (table->flags & NFT_TABLE_F_DORMANT || + !nft_is_base_chain(chain)) + return; + +- nf_unregister_net_hooks(net, nft_base_chain(chain)->ops, hook_nops); ++ nf_unregister_net_hook(net, &nft_base_chain(chain)->ops); + } + + static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type) +@@ -595,8 +592,7 @@ static void _nf_tables_table_disable(str + if (cnt && i++ == cnt) + break; + +- nf_unregister_net_hooks(net, nft_base_chain(chain)->ops, +- afi->nops); ++ nf_unregister_net_hook(net, &nft_base_chain(chain)->ops); + } + } + +@@ -613,8 +609,7 @@ static int nf_tables_table_enable(struct + if (!nft_is_base_chain(chain)) + continue; + +- err = nf_register_net_hooks(net, nft_base_chain(chain)->ops, +- afi->nops); ++ err = nf_register_net_hook(net, &nft_base_chain(chain)->ops); + if (err < 0) + goto err; + +@@ -1026,7 +1021,7 @@ static int nf_tables_fill_chain_info(str + + if (nft_is_base_chain(chain)) { + const struct nft_base_chain *basechain = nft_base_chain(chain); +- const struct nf_hook_ops *ops = &basechain->ops[0]; ++ const struct nf_hook_ops *ops = &basechain->ops; + struct nlattr *nest; + + nest = nla_nest_start(skb, NFTA_CHAIN_HOOK); +@@ -1252,8 +1247,8 @@ static void nf_tables_chain_destroy(stru + free_percpu(basechain->stats); + if (basechain->stats) + static_branch_dec(&nft_counters_enabled); +- if (basechain->ops[0].dev != NULL) +- dev_put(basechain->ops[0].dev); ++ if (basechain->ops.dev != NULL) ++ dev_put(basechain->ops.dev); + kfree(chain->name); + kfree(basechain); + } else { +@@ -1349,7 +1344,6 @@ static int nf_tables_addchain(struct nft + struct nft_stats __percpu *stats; + struct net *net = ctx->net; + struct nft_chain *chain; +- unsigned int i; + int err; + + if (table->use == UINT_MAX) +@@ -1388,21 +1382,18 @@ static int nf_tables_addchain(struct nft + basechain->type = hook.type; + chain = &basechain->chain; + +- for (i = 0; i < afi->nops; i++) { +- ops = &basechain->ops[i]; +- ops->pf = family; +- ops->hooknum = hook.num; +- ops->priority = hook.priority; +- ops->priv = chain; +- ops->hook = afi->hooks[ops->hooknum]; +- ops->dev = hook.dev; +- if (hookfn) +- ops->hook = hookfn; +- if (afi->hook_ops_init) +- afi->hook_ops_init(ops, i); +- if (basechain->type->type == NFT_CHAIN_T_NAT) +- ops->nat_hook = true; +- } ++ ops = &basechain->ops; ++ ops->pf = family; ++ ops->hooknum = hook.num; ++ ops->priority = hook.priority; ++ ops->priv = chain; ++ ops->hook = afi->hooks[ops->hooknum]; ++ ops->dev = hook.dev; ++ if (hookfn) ++ ops->hook = hookfn; ++ ++ if (basechain->type->type == NFT_CHAIN_T_NAT) ++ ops->nat_hook = true; + + chain->flags |= NFT_BASE_CHAIN; + basechain->policy = policy; +@@ -1420,7 +1411,7 @@ static int nf_tables_addchain(struct nft + goto err1; + } + +- err = nf_tables_register_hooks(net, table, chain, afi->nops); ++ err = nf_tables_register_hook(net, table, chain); + if (err < 0) + goto err1; + +@@ -1434,7 +1425,7 @@ static int nf_tables_addchain(struct nft + + return 0; + err2: +- nf_tables_unregister_hooks(net, table, chain, afi->nops); ++ nf_tables_unregister_hook(net, table, chain); + err1: + nf_tables_chain_destroy(chain); + +@@ -1447,14 +1438,13 @@ static int nf_tables_updchain(struct nft + const struct nlattr * const *nla = ctx->nla; + struct nft_table *table = ctx->table; + struct nft_chain *chain = ctx->chain; +- struct nft_af_info *afi = ctx->afi; + struct nft_base_chain *basechain; + struct nft_stats *stats = NULL; + struct nft_chain_hook hook; + const struct nlattr *name; + struct nf_hook_ops *ops; + struct nft_trans *trans; +- int err, i; ++ int err; + + if (nla[NFTA_CHAIN_HOOK]) { + if (!nft_is_base_chain(chain)) +@@ -1471,14 +1461,12 @@ static int nf_tables_updchain(struct nft + return -EBUSY; + } + +- for (i = 0; i < afi->nops; i++) { +- ops = &basechain->ops[i]; +- if (ops->hooknum != hook.num || +- ops->priority != hook.priority || +- ops->dev != hook.dev) { +- nft_chain_release_hook(&hook); +- return -EBUSY; +- } ++ ops = &basechain->ops; ++ if (ops->hooknum != hook.num || ++ ops->priority != hook.priority || ++ ops->dev != hook.dev) { ++ nft_chain_release_hook(&hook); ++ return -EBUSY; + } + nft_chain_release_hook(&hook); + } +@@ -5062,10 +5050,9 @@ static int nf_tables_commit(struct net * + case NFT_MSG_DELCHAIN: + list_del_rcu(&trans->ctx.chain->list); + nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN); +- nf_tables_unregister_hooks(trans->ctx.net, +- trans->ctx.table, +- trans->ctx.chain, +- trans->ctx.afi->nops); ++ nf_tables_unregister_hook(trans->ctx.net, ++ trans->ctx.table, ++ trans->ctx.chain); + break; + case NFT_MSG_NEWRULE: + nft_clear(trans->ctx.net, nft_trans_rule(trans)); +@@ -5202,10 +5189,9 @@ static int nf_tables_abort(struct net *n + } else { + trans->ctx.table->use--; + list_del_rcu(&trans->ctx.chain->list); +- nf_tables_unregister_hooks(trans->ctx.net, +- trans->ctx.table, +- trans->ctx.chain, +- trans->ctx.afi->nops); ++ nf_tables_unregister_hook(trans->ctx.net, ++ trans->ctx.table, ++ trans->ctx.chain); + } + break; + case NFT_MSG_DELCHAIN: +@@ -5306,7 +5292,7 @@ int nft_chain_validate_hooks(const struc + if (nft_is_base_chain(chain)) { + basechain = nft_base_chain(chain); + +- if ((1 << basechain->ops[0].hooknum) & hook_flags) ++ if ((1 << basechain->ops.hooknum) & hook_flags) + return 0; + + return -EOPNOTSUPP; +@@ -5788,8 +5774,7 @@ int __nft_release_basechain(struct nft_c + + BUG_ON(!nft_is_base_chain(ctx->chain)); + +- nf_tables_unregister_hooks(ctx->net, ctx->chain->table, ctx->chain, +- ctx->afi->nops); ++ nf_tables_unregister_hook(ctx->net, ctx->chain->table, ctx->chain); + list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) { + list_del(&rule->list); + ctx->chain->use--; +@@ -5818,8 +5803,7 @@ static void __nft_release_afinfo(struct + + list_for_each_entry_safe(table, nt, &afi->tables, list) { + list_for_each_entry(chain, &table->chains, list) +- nf_tables_unregister_hooks(net, table, chain, +- afi->nops); ++ nf_tables_unregister_hook(net, table, chain); + /* No packets are walking on these chains anymore. */ + ctx.table = table; + list_for_each_entry(chain, &table->chains, list) { +--- a/net/netfilter/nf_tables_inet.c ++++ b/net/netfilter/nf_tables_inet.c +@@ -74,7 +74,6 @@ static struct nft_af_info nft_af_inet __ + .family = NFPROTO_INET, + .nhooks = NF_INET_NUMHOOKS, + .owner = THIS_MODULE, +- .nops = 1, + .hooks = { + [NF_INET_LOCAL_IN] = nft_do_chain_inet, + [NF_INET_LOCAL_OUT] = nft_inet_output, +--- a/net/netfilter/nf_tables_netdev.c ++++ b/net/netfilter/nf_tables_netdev.c +@@ -43,7 +43,6 @@ static struct nft_af_info nft_af_netdev + .nhooks = NF_NETDEV_NUMHOOKS, + .owner = THIS_MODULE, + .flags = NFT_AF_NEEDS_DEV, +- .nops = 1, + .hooks = { + [NF_NETDEV_INGRESS] = nft_do_chain_netdev, + }, +@@ -98,7 +97,7 @@ static void nft_netdev_event(unsigned lo + __nft_release_basechain(ctx); + break; + case NETDEV_CHANGENAME: +- if (dev->ifindex != basechain->ops[0].dev->ifindex) ++ if (dev->ifindex != basechain->ops.dev->ifindex) + return; + + strncpy(basechain->dev_name, dev->name, IFNAMSIZ); +--- a/net/netfilter/nft_compat.c ++++ b/net/netfilter/nft_compat.c +@@ -169,7 +169,7 @@ nft_target_set_tgchk_param(struct xt_tgc + if (nft_is_base_chain(ctx->chain)) { + const struct nft_base_chain *basechain = + nft_base_chain(ctx->chain); +- const struct nf_hook_ops *ops = &basechain->ops[0]; ++ const struct nf_hook_ops *ops = &basechain->ops; + + par->hook_mask = 1 << ops->hooknum; + } else { +@@ -302,7 +302,7 @@ static int nft_target_validate(const str + if (nft_is_base_chain(ctx->chain)) { + const struct nft_base_chain *basechain = + nft_base_chain(ctx->chain); +- const struct nf_hook_ops *ops = &basechain->ops[0]; ++ const struct nf_hook_ops *ops = &basechain->ops; + + hook_mask = 1 << ops->hooknum; + if (target->hooks && !(hook_mask & target->hooks)) +@@ -383,7 +383,7 @@ nft_match_set_mtchk_param(struct xt_mtch + if (nft_is_base_chain(ctx->chain)) { + const struct nft_base_chain *basechain = + nft_base_chain(ctx->chain); +- const struct nf_hook_ops *ops = &basechain->ops[0]; ++ const struct nf_hook_ops *ops = &basechain->ops; + + par->hook_mask = 1 << ops->hooknum; + } else { +@@ -481,7 +481,7 @@ static int nft_match_validate(const stru + if (nft_is_base_chain(ctx->chain)) { + const struct nft_base_chain *basechain = + nft_base_chain(ctx->chain); +- const struct nf_hook_ops *ops = &basechain->ops[0]; ++ const struct nf_hook_ops *ops = &basechain->ops; + + hook_mask = 1 << ops->hooknum; + if (match->hooks && !(hook_mask & match->hooks)) diff --git a/target/linux/generic/backport-4.14/304-netfilter-move-checksum-indirection-to-struct-nf_ipv.patch b/target/linux/generic/backport-4.14/304-netfilter-move-checksum-indirection-to-struct-nf_ipv.patch new file mode 100644 index 000000000..b122dd55d --- /dev/null +++ b/target/linux/generic/backport-4.14/304-netfilter-move-checksum-indirection-to-struct-nf_ipv.patch @@ -0,0 +1,171 @@ +From: Pablo Neira Ayuso +Date: Mon, 27 Nov 2017 21:55:14 +0100 +Subject: [PATCH] netfilter: move checksum indirection to struct nf_ipv6_ops + +We cannot make a direct call to nf_ip6_checksum() because that would +result in autoloading the 'ipv6' module because of symbol dependencies. +Therefore, define checksum indirection in nf_ipv6_ops where this really +belongs to. + +For IPv4, we can indeed make a direct function call, which is faster, +given IPv4 is built-in in the networking code by default. Still, +CONFIG_INET=n and CONFIG_NETFILTER=y is possible, so define empty inline +stub for IPv4 in such case. + +Signed-off-by: Pablo Neira Ayuso +--- + create mode 100644 net/netfilter/utils.c + +--- a/include/linux/netfilter.h ++++ b/include/linux/netfilter.h +@@ -274,8 +274,6 @@ struct nf_queue_entry; + + struct nf_afinfo { + unsigned short family; +- __sum16 (*checksum)(struct sk_buff *skb, unsigned int hook, +- unsigned int dataoff, u_int8_t protocol); + __sum16 (*checksum_partial)(struct sk_buff *skb, + unsigned int hook, + unsigned int dataoff, +@@ -296,20 +294,9 @@ static inline const struct nf_afinfo *nf + return rcu_dereference(nf_afinfo[family]); + } + +-static inline __sum16 +-nf_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, +- u_int8_t protocol, unsigned short family) +-{ +- const struct nf_afinfo *afinfo; +- __sum16 csum = 0; +- +- rcu_read_lock(); +- afinfo = nf_get_afinfo(family); +- if (afinfo) +- csum = afinfo->checksum(skb, hook, dataoff, protocol); +- rcu_read_unlock(); +- return csum; +-} ++__sum16 nf_checksum(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, u_int8_t protocol, ++ unsigned short family); + + static inline __sum16 + nf_checksum_partial(struct sk_buff *skb, unsigned int hook, +--- a/include/linux/netfilter_ipv4.h ++++ b/include/linux/netfilter_ipv4.h +@@ -7,6 +7,16 @@ + #include + + int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned addr_type); ++ ++#ifdef CONFIG_INET + __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol); ++#else ++static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, u_int8_t protocol) ++{ ++ return 0; ++} ++#endif /* CONFIG_INET */ ++ + #endif /*__LINUX_IP_NETFILTER_H*/ +--- a/include/linux/netfilter_ipv6.h ++++ b/include/linux/netfilter_ipv6.h +@@ -19,6 +19,8 @@ struct nf_ipv6_ops { + void (*route_input)(struct sk_buff *skb); + int (*fragment)(struct net *net, struct sock *sk, struct sk_buff *skb, + int (*output)(struct net *, struct sock *, struct sk_buff *)); ++ __sum16 (*checksum)(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, u_int8_t protocol); + }; + + #ifdef CONFIG_NETFILTER +--- a/net/bridge/netfilter/nf_tables_bridge.c ++++ b/net/bridge/netfilter/nf_tables_bridge.c +@@ -106,12 +106,6 @@ static int nf_br_reroute(struct net *net + return 0; + } + +-static __sum16 nf_br_checksum(struct sk_buff *skb, unsigned int hook, +- unsigned int dataoff, u_int8_t protocol) +-{ +- return 0; +-} +- + static __sum16 nf_br_checksum_partial(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, unsigned int len, + u_int8_t protocol) +@@ -127,7 +121,6 @@ static int nf_br_route(struct net *net, + + static const struct nf_afinfo nf_br_afinfo = { + .family = AF_BRIDGE, +- .checksum = nf_br_checksum, + .checksum_partial = nf_br_checksum_partial, + .route = nf_br_route, + .saveroute = nf_br_saveroute, +--- a/net/ipv4/netfilter.c ++++ b/net/ipv4/netfilter.c +@@ -188,7 +188,6 @@ static int nf_ip_route(struct net *net, + + static const struct nf_afinfo nf_ip_afinfo = { + .family = AF_INET, +- .checksum = nf_ip_checksum, + .checksum_partial = nf_ip_checksum_partial, + .route = nf_ip_route, + .saveroute = nf_ip_saveroute, +--- a/net/ipv6/netfilter.c ++++ b/net/ipv6/netfilter.c +@@ -193,12 +193,12 @@ static __sum16 nf_ip6_checksum_partial(s + static const struct nf_ipv6_ops ipv6ops = { + .chk_addr = ipv6_chk_addr, + .route_input = ip6_route_input, +- .fragment = ip6_fragment ++ .fragment = ip6_fragment, ++ .checksum = nf_ip6_checksum, + }; + + static const struct nf_afinfo nf_ip6_afinfo = { + .family = AF_INET6, +- .checksum = nf_ip6_checksum, + .checksum_partial = nf_ip6_checksum_partial, + .route = nf_ip6_route, + .saveroute = nf_ip6_saveroute, +--- a/net/netfilter/Makefile ++++ b/net/netfilter/Makefile +@@ -1,5 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0 +-netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o ++netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o utils.o + + nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o nf_conntrack_acct.o nf_conntrack_seqadj.o + nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMEOUT) += nf_conntrack_timeout.o +--- /dev/null ++++ b/net/netfilter/utils.c +@@ -0,0 +1,26 @@ ++#include ++#include ++#include ++#include ++ ++__sum16 nf_checksum(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, u_int8_t protocol, ++ unsigned short family) ++{ ++ const struct nf_ipv6_ops *v6ops; ++ __sum16 csum = 0; ++ ++ switch (family) { ++ case AF_INET: ++ csum = nf_ip_checksum(skb, hook, dataoff, protocol); ++ break; ++ case AF_INET6: ++ v6ops = rcu_dereference(nf_ipv6_ops); ++ if (v6ops) ++ csum = v6ops->checksum(skb, hook, dataoff, protocol); ++ break; ++ } ++ ++ return csum; ++} ++EXPORT_SYMBOL_GPL(nf_checksum); diff --git a/target/linux/generic/backport-4.14/305-netfilter-move-checksum_partial-indirection-to-struc.patch b/target/linux/generic/backport-4.14/305-netfilter-move-checksum_partial-indirection-to-struc.patch new file mode 100644 index 000000000..7c22312c6 --- /dev/null +++ b/target/linux/generic/backport-4.14/305-netfilter-move-checksum_partial-indirection-to-struc.patch @@ -0,0 +1,204 @@ +From: Pablo Neira Ayuso +Date: Wed, 20 Dec 2017 16:04:18 +0100 +Subject: [PATCH] netfilter: move checksum_partial indirection to struct + nf_ipv6_ops + +We cannot make a direct call to nf_ip6_checksum_partial() because that +would result in autoloading the 'ipv6' module because of symbol +dependencies. Therefore, define checksum_partial indirection in +nf_ipv6_ops where this really belongs to. + +For IPv4, we can indeed make a direct function call, which is faster, +given IPv4 is built-in in the networking code by default. Still, +CONFIG_INET=n and CONFIG_NETFILTER=y is possible, so define empty inline +stub for IPv4 in such case. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/linux/netfilter.h ++++ b/include/linux/netfilter.h +@@ -274,11 +274,6 @@ struct nf_queue_entry; + + struct nf_afinfo { + unsigned short family; +- __sum16 (*checksum_partial)(struct sk_buff *skb, +- unsigned int hook, +- unsigned int dataoff, +- unsigned int len, +- u_int8_t protocol); + int (*route)(struct net *net, struct dst_entry **dst, + struct flowi *fl, bool strict); + void (*saveroute)(const struct sk_buff *skb, +@@ -298,22 +293,9 @@ __sum16 nf_checksum(struct sk_buff *skb, + unsigned int dataoff, u_int8_t protocol, + unsigned short family); + +-static inline __sum16 +-nf_checksum_partial(struct sk_buff *skb, unsigned int hook, +- unsigned int dataoff, unsigned int len, +- u_int8_t protocol, unsigned short family) +-{ +- const struct nf_afinfo *afinfo; +- __sum16 csum = 0; +- +- rcu_read_lock(); +- afinfo = nf_get_afinfo(family); +- if (afinfo) +- csum = afinfo->checksum_partial(skb, hook, dataoff, len, +- protocol); +- rcu_read_unlock(); +- return csum; +-} ++__sum16 nf_checksum_partial(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, unsigned int len, ++ u_int8_t protocol, unsigned short family); + + int nf_register_afinfo(const struct nf_afinfo *afinfo); + void nf_unregister_afinfo(const struct nf_afinfo *afinfo); +--- a/include/linux/netfilter_ipv4.h ++++ b/include/linux/netfilter_ipv4.h +@@ -11,12 +11,23 @@ int ip_route_me_harder(struct net *net, + #ifdef CONFIG_INET + __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol); ++__sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, unsigned int len, ++ u_int8_t protocol); + #else + static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol) + { + return 0; + } ++static inline __sum16 nf_ip_checksum_partial(struct sk_buff *skb, ++ unsigned int hook, ++ unsigned int dataoff, ++ unsigned int len, ++ u_int8_t protocol) ++{ ++ return 0; ++} + #endif /* CONFIG_INET */ + + #endif /*__LINUX_IP_NETFILTER_H*/ +--- a/include/linux/netfilter_ipv6.h ++++ b/include/linux/netfilter_ipv6.h +@@ -21,6 +21,9 @@ struct nf_ipv6_ops { + int (*output)(struct net *, struct sock *, struct sk_buff *)); + __sum16 (*checksum)(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol); ++ __sum16 (*checksum_partial)(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, unsigned int len, ++ u_int8_t protocol); + }; + + #ifdef CONFIG_NETFILTER +--- a/net/bridge/netfilter/nf_tables_bridge.c ++++ b/net/bridge/netfilter/nf_tables_bridge.c +@@ -106,13 +106,6 @@ static int nf_br_reroute(struct net *net + return 0; + } + +-static __sum16 nf_br_checksum_partial(struct sk_buff *skb, unsigned int hook, +- unsigned int dataoff, unsigned int len, +- u_int8_t protocol) +-{ +- return 0; +-} +- + static int nf_br_route(struct net *net, struct dst_entry **dst, + struct flowi *fl, bool strict __always_unused) + { +@@ -121,7 +114,6 @@ static int nf_br_route(struct net *net, + + static const struct nf_afinfo nf_br_afinfo = { + .family = AF_BRIDGE, +- .checksum_partial = nf_br_checksum_partial, + .route = nf_br_route, + .saveroute = nf_br_saveroute, + .reroute = nf_br_reroute, +--- a/net/ipv4/netfilter.c ++++ b/net/ipv4/netfilter.c +@@ -155,9 +155,9 @@ __sum16 nf_ip_checksum(struct sk_buff *s + } + EXPORT_SYMBOL(nf_ip_checksum); + +-static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook, +- unsigned int dataoff, unsigned int len, +- u_int8_t protocol) ++__sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, unsigned int len, ++ u_int8_t protocol) + { + const struct iphdr *iph = ip_hdr(skb); + __sum16 csum = 0; +@@ -175,6 +175,7 @@ static __sum16 nf_ip_checksum_partial(st + } + return csum; + } ++EXPORT_SYMBOL_GPL(nf_ip_checksum_partial); + + static int nf_ip_route(struct net *net, struct dst_entry **dst, + struct flowi *fl, bool strict __always_unused) +@@ -188,7 +189,6 @@ static int nf_ip_route(struct net *net, + + static const struct nf_afinfo nf_ip_afinfo = { + .family = AF_INET, +- .checksum_partial = nf_ip_checksum_partial, + .route = nf_ip_route, + .saveroute = nf_ip_saveroute, + .reroute = nf_ip_reroute, +--- a/net/ipv6/netfilter.c ++++ b/net/ipv6/netfilter.c +@@ -191,15 +191,15 @@ static __sum16 nf_ip6_checksum_partial(s + }; + + static const struct nf_ipv6_ops ipv6ops = { +- .chk_addr = ipv6_chk_addr, +- .route_input = ip6_route_input, +- .fragment = ip6_fragment, +- .checksum = nf_ip6_checksum, ++ .chk_addr = ipv6_chk_addr, ++ .route_input = ip6_route_input, ++ .fragment = ip6_fragment, ++ .checksum = nf_ip6_checksum, ++ .checksum_partial = nf_ip6_checksum_partial, + }; + + static const struct nf_afinfo nf_ip6_afinfo = { + .family = AF_INET6, +- .checksum_partial = nf_ip6_checksum_partial, + .route = nf_ip6_route, + .saveroute = nf_ip6_saveroute, + .reroute = nf_ip6_reroute, +--- a/net/netfilter/utils.c ++++ b/net/netfilter/utils.c +@@ -24,3 +24,27 @@ __sum16 nf_checksum(struct sk_buff *skb, + return csum; + } + EXPORT_SYMBOL_GPL(nf_checksum); ++ ++__sum16 nf_checksum_partial(struct sk_buff *skb, unsigned int hook, ++ unsigned int dataoff, unsigned int len, ++ u_int8_t protocol, unsigned short family) ++{ ++ const struct nf_ipv6_ops *v6ops; ++ __sum16 csum = 0; ++ ++ switch (family) { ++ case AF_INET: ++ csum = nf_ip_checksum_partial(skb, hook, dataoff, len, ++ protocol); ++ break; ++ case AF_INET6: ++ v6ops = rcu_dereference(nf_ipv6_ops); ++ if (v6ops) ++ csum = v6ops->checksum_partial(skb, hook, dataoff, len, ++ protocol); ++ break; ++ } ++ ++ return csum; ++} ++EXPORT_SYMBOL_GPL(nf_checksum_partial); diff --git a/target/linux/generic/backport-4.14/306-netfilter-remove-saveroute-indirection-in-struct-nf_.patch b/target/linux/generic/backport-4.14/306-netfilter-remove-saveroute-indirection-in-struct-nf_.patch new file mode 100644 index 000000000..e52f81164 --- /dev/null +++ b/target/linux/generic/backport-4.14/306-netfilter-remove-saveroute-indirection-in-struct-nf_.patch @@ -0,0 +1,232 @@ +From: Pablo Neira Ayuso +Date: Wed, 20 Dec 2017 16:12:55 +0100 +Subject: [PATCH] netfilter: remove saveroute indirection in struct nf_afinfo + +This is only used by nf_queue.c and this function comes with no symbol +dependencies with IPv6, it just refers to structure layouts. Therefore, +we can replace it by a direct function call from where it belongs. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/linux/netfilter.h ++++ b/include/linux/netfilter.h +@@ -276,8 +276,6 @@ struct nf_afinfo { + unsigned short family; + int (*route)(struct net *net, struct dst_entry **dst, + struct flowi *fl, bool strict); +- void (*saveroute)(const struct sk_buff *skb, +- struct nf_queue_entry *entry); + int (*reroute)(struct net *net, struct sk_buff *skb, + const struct nf_queue_entry *entry); + int route_key_size; +--- a/include/linux/netfilter_ipv4.h ++++ b/include/linux/netfilter_ipv4.h +@@ -6,6 +6,16 @@ + + #include + ++/* Extra routing may needed on local out, as the QUEUE target never returns ++ * control to the table. ++ */ ++struct ip_rt_info { ++ __be32 daddr; ++ __be32 saddr; ++ u_int8_t tos; ++ u_int32_t mark; ++}; ++ + int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned addr_type); + + #ifdef CONFIG_INET +--- a/include/linux/netfilter_ipv6.h ++++ b/include/linux/netfilter_ipv6.h +@@ -9,6 +9,15 @@ + + #include + ++/* Extra routing may needed on local out, as the QUEUE target never returns ++ * control to the table. ++ */ ++struct ip6_rt_info { ++ struct in6_addr daddr; ++ struct in6_addr saddr; ++ u_int32_t mark; ++}; ++ + /* + * Hook functions for ipv6 to allow xt_* modules to be built-in even + * if IPv6 is a module. +--- a/net/bridge/netfilter/nf_tables_bridge.c ++++ b/net/bridge/netfilter/nf_tables_bridge.c +@@ -95,11 +95,6 @@ static const struct nf_chain_type filter + (1 << NF_BR_POST_ROUTING), + }; + +-static void nf_br_saveroute(const struct sk_buff *skb, +- struct nf_queue_entry *entry) +-{ +-} +- + static int nf_br_reroute(struct net *net, struct sk_buff *skb, + const struct nf_queue_entry *entry) + { +@@ -115,7 +110,6 @@ static int nf_br_route(struct net *net, + static const struct nf_afinfo nf_br_afinfo = { + .family = AF_BRIDGE, + .route = nf_br_route, +- .saveroute = nf_br_saveroute, + .reroute = nf_br_reroute, + .route_key_size = 0, + }; +--- a/net/ipv4/netfilter.c ++++ b/net/ipv4/netfilter.c +@@ -80,33 +80,6 @@ int ip_route_me_harder(struct net *net, + } + EXPORT_SYMBOL(ip_route_me_harder); + +-/* +- * Extra routing may needed on local out, as the QUEUE target never +- * returns control to the table. +- */ +- +-struct ip_rt_info { +- __be32 daddr; +- __be32 saddr; +- u_int8_t tos; +- u_int32_t mark; +-}; +- +-static void nf_ip_saveroute(const struct sk_buff *skb, +- struct nf_queue_entry *entry) +-{ +- struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry); +- +- if (entry->state.hook == NF_INET_LOCAL_OUT) { +- const struct iphdr *iph = ip_hdr(skb); +- +- rt_info->tos = iph->tos; +- rt_info->daddr = iph->daddr; +- rt_info->saddr = iph->saddr; +- rt_info->mark = skb->mark; +- } +-} +- + static int nf_ip_reroute(struct net *net, struct sk_buff *skb, + const struct nf_queue_entry *entry) + { +@@ -190,7 +163,6 @@ static int nf_ip_route(struct net *net, + static const struct nf_afinfo nf_ip_afinfo = { + .family = AF_INET, + .route = nf_ip_route, +- .saveroute = nf_ip_saveroute, + .reroute = nf_ip_reroute, + .route_key_size = sizeof(struct ip_rt_info), + }; +--- a/net/ipv6/netfilter.c ++++ b/net/ipv6/netfilter.c +@@ -69,31 +69,6 @@ int ip6_route_me_harder(struct net *net, + } + EXPORT_SYMBOL(ip6_route_me_harder); + +-/* +- * Extra routing may needed on local out, as the QUEUE target never +- * returns control to the table. +- */ +- +-struct ip6_rt_info { +- struct in6_addr daddr; +- struct in6_addr saddr; +- u_int32_t mark; +-}; +- +-static void nf_ip6_saveroute(const struct sk_buff *skb, +- struct nf_queue_entry *entry) +-{ +- struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry); +- +- if (entry->state.hook == NF_INET_LOCAL_OUT) { +- const struct ipv6hdr *iph = ipv6_hdr(skb); +- +- rt_info->daddr = iph->daddr; +- rt_info->saddr = iph->saddr; +- rt_info->mark = skb->mark; +- } +-} +- + static int nf_ip6_reroute(struct net *net, struct sk_buff *skb, + const struct nf_queue_entry *entry) + { +@@ -201,7 +176,6 @@ static const struct nf_ipv6_ops ipv6ops + static const struct nf_afinfo nf_ip6_afinfo = { + .family = AF_INET6, + .route = nf_ip6_route, +- .saveroute = nf_ip6_saveroute, + .reroute = nf_ip6_reroute, + .route_key_size = sizeof(struct ip6_rt_info), + }; +--- a/net/netfilter/nf_queue.c ++++ b/net/netfilter/nf_queue.c +@@ -10,6 +10,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -111,6 +113,35 @@ unsigned int nf_queue_nf_hook_drop(struc + } + EXPORT_SYMBOL_GPL(nf_queue_nf_hook_drop); + ++static void nf_ip_saveroute(const struct sk_buff *skb, ++ struct nf_queue_entry *entry) ++{ ++ struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry); ++ ++ if (entry->state.hook == NF_INET_LOCAL_OUT) { ++ const struct iphdr *iph = ip_hdr(skb); ++ ++ rt_info->tos = iph->tos; ++ rt_info->daddr = iph->daddr; ++ rt_info->saddr = iph->saddr; ++ rt_info->mark = skb->mark; ++ } ++} ++ ++static void nf_ip6_saveroute(const struct sk_buff *skb, ++ struct nf_queue_entry *entry) ++{ ++ struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry); ++ ++ if (entry->state.hook == NF_INET_LOCAL_OUT) { ++ const struct ipv6hdr *iph = ipv6_hdr(skb); ++ ++ rt_info->daddr = iph->daddr; ++ rt_info->saddr = iph->saddr; ++ rt_info->mark = skb->mark; ++ } ++} ++ + static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state, + const struct nf_hook_entries *entries, + unsigned int index, unsigned int queuenum) +@@ -147,7 +178,16 @@ static int __nf_queue(struct sk_buff *sk + + nf_queue_entry_get_refs(entry); + skb_dst_force(skb); +- afinfo->saveroute(skb, entry); ++ ++ switch (entry->state.pf) { ++ case AF_INET: ++ nf_ip_saveroute(skb, entry); ++ break; ++ case AF_INET6: ++ nf_ip6_saveroute(skb, entry); ++ break; ++ } ++ + status = qh->outfn(entry, queuenum); + + if (status < 0) { diff --git a/target/linux/generic/backport-4.14/307-netfilter-move-route-indirection-to-struct-nf_ipv6_o.patch b/target/linux/generic/backport-4.14/307-netfilter-move-route-indirection-to-struct-nf_ipv6_o.patch new file mode 100644 index 000000000..fe60a7903 --- /dev/null +++ b/target/linux/generic/backport-4.14/307-netfilter-move-route-indirection-to-struct-nf_ipv6_o.patch @@ -0,0 +1,349 @@ +From: Pablo Neira Ayuso +Date: Mon, 27 Nov 2017 22:29:52 +0100 +Subject: [PATCH] netfilter: move route indirection to struct nf_ipv6_ops + +We cannot make a direct call to nf_ip6_route() because that would result +in autoloading the 'ipv6' module because of symbol dependencies. +Therefore, define route indirection in nf_ipv6_ops where this really +belongs to. + +For IPv4, we can indeed make a direct function call, which is faster, +given IPv4 is built-in in the networking code by default. Still, +CONFIG_INET=n and CONFIG_NETFILTER=y is possible, so define empty inline +stub for IPv4 in such case. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/linux/netfilter.h ++++ b/include/linux/netfilter.h +@@ -274,8 +274,6 @@ struct nf_queue_entry; + + struct nf_afinfo { + unsigned short family; +- int (*route)(struct net *net, struct dst_entry **dst, +- struct flowi *fl, bool strict); + int (*reroute)(struct net *net, struct sk_buff *skb, + const struct nf_queue_entry *entry); + int route_key_size; +@@ -294,6 +292,8 @@ __sum16 nf_checksum(struct sk_buff *skb, + __sum16 nf_checksum_partial(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, unsigned int len, + u_int8_t protocol, unsigned short family); ++int nf_route(struct net *net, struct dst_entry **dst, struct flowi *fl, ++ bool strict, unsigned short family); + + int nf_register_afinfo(const struct nf_afinfo *afinfo); + void nf_unregister_afinfo(const struct nf_afinfo *afinfo); +--- a/include/linux/netfilter_ipv4.h ++++ b/include/linux/netfilter_ipv4.h +@@ -24,6 +24,8 @@ __sum16 nf_ip_checksum(struct sk_buff *s + __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, unsigned int len, + u_int8_t protocol); ++int nf_ip_route(struct net *net, struct dst_entry **dst, struct flowi *fl, ++ bool strict); + #else + static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol) +@@ -38,6 +40,11 @@ static inline __sum16 nf_ip_checksum_par + { + return 0; + } ++static inline int nf_ip_route(struct net *net, struct dst_entry **dst, ++ struct flowi *fl, bool strict) ++{ ++ return -EOPNOTSUPP; ++} + #endif /* CONFIG_INET */ + + #endif /*__LINUX_IP_NETFILTER_H*/ +--- a/include/linux/netfilter_ipv6.h ++++ b/include/linux/netfilter_ipv6.h +@@ -33,6 +33,8 @@ struct nf_ipv6_ops { + __sum16 (*checksum_partial)(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, unsigned int len, + u_int8_t protocol); ++ int (*route)(struct net *net, struct dst_entry **dst, struct flowi *fl, ++ bool strict); + }; + + #ifdef CONFIG_NETFILTER +--- a/net/bridge/netfilter/nf_tables_bridge.c ++++ b/net/bridge/netfilter/nf_tables_bridge.c +@@ -101,15 +101,8 @@ static int nf_br_reroute(struct net *net + return 0; + } + +-static int nf_br_route(struct net *net, struct dst_entry **dst, +- struct flowi *fl, bool strict __always_unused) +-{ +- return 0; +-} +- + static const struct nf_afinfo nf_br_afinfo = { + .family = AF_BRIDGE, +- .route = nf_br_route, + .reroute = nf_br_reroute, + .route_key_size = 0, + }; +--- a/net/ipv4/netfilter.c ++++ b/net/ipv4/netfilter.c +@@ -150,8 +150,8 @@ __sum16 nf_ip_checksum_partial(struct sk + } + EXPORT_SYMBOL_GPL(nf_ip_checksum_partial); + +-static int nf_ip_route(struct net *net, struct dst_entry **dst, +- struct flowi *fl, bool strict __always_unused) ++int nf_ip_route(struct net *net, struct dst_entry **dst, struct flowi *fl, ++ bool strict __always_unused) + { + struct rtable *rt = ip_route_output_key(net, &fl->u.ip4); + if (IS_ERR(rt)) +@@ -159,10 +159,10 @@ static int nf_ip_route(struct net *net, + *dst = &rt->dst; + return 0; + } ++EXPORT_SYMBOL_GPL(nf_ip_route); + + static const struct nf_afinfo nf_ip_afinfo = { + .family = AF_INET, +- .route = nf_ip_route, + .reroute = nf_ip_reroute, + .route_key_size = sizeof(struct ip_rt_info), + }; +--- a/net/ipv6/netfilter.c ++++ b/net/ipv6/netfilter.c +@@ -171,11 +171,11 @@ static const struct nf_ipv6_ops ipv6ops + .fragment = ip6_fragment, + .checksum = nf_ip6_checksum, + .checksum_partial = nf_ip6_checksum_partial, ++ .route = nf_ip6_route, + }; + + static const struct nf_afinfo nf_ip6_afinfo = { + .family = AF_INET6, +- .route = nf_ip6_route, + .reroute = nf_ip6_reroute, + .route_key_size = sizeof(struct ip6_rt_info), + }; +--- a/net/ipv6/netfilter/nft_fib_ipv6.c ++++ b/net/ipv6/netfilter/nft_fib_ipv6.c +@@ -60,7 +60,6 @@ static u32 __nft_fib6_eval_type(const st + { + const struct net_device *dev = NULL; + const struct nf_ipv6_ops *v6ops; +- const struct nf_afinfo *afinfo; + int route_err, addrtype; + struct rt6_info *rt; + struct flowi6 fl6 = { +@@ -69,8 +68,8 @@ static u32 __nft_fib6_eval_type(const st + }; + u32 ret = 0; + +- afinfo = nf_get_afinfo(NFPROTO_IPV6); +- if (!afinfo) ++ v6ops = nf_get_ipv6_ops(); ++ if (!v6ops) + return RTN_UNREACHABLE; + + if (priv->flags & NFTA_FIB_F_IIF) +@@ -80,12 +79,11 @@ static u32 __nft_fib6_eval_type(const st + + nft_fib6_flowi_init(&fl6, priv, pkt, dev, iph); + +- v6ops = nf_get_ipv6_ops(); +- if (dev && v6ops && v6ops->chk_addr(nft_net(pkt), &fl6.daddr, dev, true)) ++ if (dev && v6ops->chk_addr(nft_net(pkt), &fl6.daddr, dev, true)) + ret = RTN_LOCAL; + +- route_err = afinfo->route(nft_net(pkt), (struct dst_entry **)&rt, +- flowi6_to_flowi(&fl6), false); ++ route_err = v6ops->route(nft_net(pkt), (struct dst_entry **)&rt, ++ flowi6_to_flowi(&fl6), false); + if (route_err) + goto err; + +--- a/net/netfilter/nf_conntrack_h323_main.c ++++ b/net/netfilter/nf_conntrack_h323_main.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -732,14 +733,8 @@ static int callforward_do_filter(struct + const union nf_inet_addr *dst, + u_int8_t family) + { +- const struct nf_afinfo *afinfo; + int ret = 0; + +- /* rcu_read_lock()ed by nf_hook_thresh */ +- afinfo = nf_get_afinfo(family); +- if (!afinfo) +- return 0; +- + switch (family) { + case AF_INET: { + struct flowi4 fl1, fl2; +@@ -750,10 +745,10 @@ static int callforward_do_filter(struct + + memset(&fl2, 0, sizeof(fl2)); + fl2.daddr = dst->ip; +- if (!afinfo->route(net, (struct dst_entry **)&rt1, +- flowi4_to_flowi(&fl1), false)) { +- if (!afinfo->route(net, (struct dst_entry **)&rt2, +- flowi4_to_flowi(&fl2), false)) { ++ if (!nf_ip_route(net, (struct dst_entry **)&rt1, ++ flowi4_to_flowi(&fl1), false)) { ++ if (!nf_ip_route(net, (struct dst_entry **)&rt2, ++ flowi4_to_flowi(&fl2), false)) { + if (rt_nexthop(rt1, fl1.daddr) == + rt_nexthop(rt2, fl2.daddr) && + rt1->dst.dev == rt2->dst.dev) +@@ -766,18 +761,23 @@ static int callforward_do_filter(struct + } + #if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6) + case AF_INET6: { +- struct flowi6 fl1, fl2; ++ const struct nf_ipv6_ops *v6ops; + struct rt6_info *rt1, *rt2; ++ struct flowi6 fl1, fl2; ++ ++ v6ops = nf_get_ipv6_ops(); ++ if (!v6ops) ++ return 0; + + memset(&fl1, 0, sizeof(fl1)); + fl1.daddr = src->in6; + + memset(&fl2, 0, sizeof(fl2)); + fl2.daddr = dst->in6; +- if (!afinfo->route(net, (struct dst_entry **)&rt1, +- flowi6_to_flowi(&fl1), false)) { +- if (!afinfo->route(net, (struct dst_entry **)&rt2, +- flowi6_to_flowi(&fl2), false)) { ++ if (!v6ops->route(net, (struct dst_entry **)&rt1, ++ flowi6_to_flowi(&fl1), false)) { ++ if (!v6ops->route(net, (struct dst_entry **)&rt2, ++ flowi6_to_flowi(&fl2), false)) { + if (ipv6_addr_equal(rt6_nexthop(rt1, &fl1.daddr), + rt6_nexthop(rt2, &fl2.daddr)) && + rt1->dst.dev == rt2->dst.dev) +--- a/net/netfilter/nft_rt.c ++++ b/net/netfilter/nft_rt.c +@@ -27,7 +27,7 @@ static u16 get_tcpmss(const struct nft_p + { + u32 minlen = sizeof(struct ipv6hdr), mtu = dst_mtu(skbdst); + const struct sk_buff *skb = pkt->skb; +- const struct nf_afinfo *ai; ++ struct dst_entry *dst = NULL; + struct flowi fl; + + memset(&fl, 0, sizeof(fl)); +@@ -43,15 +43,10 @@ static u16 get_tcpmss(const struct nft_p + break; + } + +- ai = nf_get_afinfo(nft_pf(pkt)); +- if (ai) { +- struct dst_entry *dst = NULL; +- +- ai->route(nft_net(pkt), &dst, &fl, false); +- if (dst) { +- mtu = min(mtu, dst_mtu(dst)); +- dst_release(dst); +- } ++ nf_route(nft_net(pkt), &dst, &fl, false, nft_pf(pkt)); ++ if (dst) { ++ mtu = min(mtu, dst_mtu(dst)); ++ dst_release(dst); + } + + if (mtu <= minlen || mtu > 0xffff) +--- a/net/netfilter/utils.c ++++ b/net/netfilter/utils.c +@@ -48,3 +48,24 @@ __sum16 nf_checksum_partial(struct sk_bu + return csum; + } + EXPORT_SYMBOL_GPL(nf_checksum_partial); ++ ++int nf_route(struct net *net, struct dst_entry **dst, struct flowi *fl, ++ bool strict, unsigned short family) ++{ ++ const struct nf_ipv6_ops *v6ops; ++ int ret = 0; ++ ++ switch (family) { ++ case AF_INET: ++ ret = nf_ip_route(net, dst, fl, strict); ++ break; ++ case AF_INET6: ++ v6ops = rcu_dereference(nf_ipv6_ops); ++ if (v6ops) ++ ret = v6ops->route(net, dst, fl, strict); ++ break; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(nf_route); +--- a/net/netfilter/xt_TCPMSS.c ++++ b/net/netfilter/xt_TCPMSS.c +@@ -48,7 +48,6 @@ static u_int32_t tcpmss_reverse_mtu(stru + unsigned int family) + { + struct flowi fl; +- const struct nf_afinfo *ai; + struct rtable *rt = NULL; + u_int32_t mtu = ~0U; + +@@ -62,10 +61,8 @@ static u_int32_t tcpmss_reverse_mtu(stru + memset(fl6, 0, sizeof(*fl6)); + fl6->daddr = ipv6_hdr(skb)->saddr; + } +- ai = nf_get_afinfo(family); +- if (ai != NULL) +- ai->route(net, (struct dst_entry **)&rt, &fl, false); + ++ nf_route(net, (struct dst_entry **)&rt, &fl, false, family); + if (rt != NULL) { + mtu = dst_mtu(&rt->dst); + dst_release(&rt->dst); +--- a/net/netfilter/xt_addrtype.c ++++ b/net/netfilter/xt_addrtype.c +@@ -36,7 +36,7 @@ MODULE_ALIAS("ip6t_addrtype"); + static u32 match_lookup_rt6(struct net *net, const struct net_device *dev, + const struct in6_addr *addr, u16 mask) + { +- const struct nf_afinfo *afinfo; ++ const struct nf_ipv6_ops *v6ops; + struct flowi6 flow; + struct rt6_info *rt; + u32 ret = 0; +@@ -47,17 +47,14 @@ static u32 match_lookup_rt6(struct net * + if (dev) + flow.flowi6_oif = dev->ifindex; + +- afinfo = nf_get_afinfo(NFPROTO_IPV6); +- if (afinfo != NULL) { +- const struct nf_ipv6_ops *v6ops; +- ++ v6ops = nf_get_ipv6_ops(); ++ if (v6ops) { + if (dev && (mask & XT_ADDRTYPE_LOCAL)) { +- v6ops = nf_get_ipv6_ops(); +- if (v6ops && v6ops->chk_addr(net, addr, dev, true)) ++ if (v6ops->chk_addr(net, addr, dev, true)) + ret = XT_ADDRTYPE_LOCAL; + } +- route_err = afinfo->route(net, (struct dst_entry **)&rt, +- flowi6_to_flowi(&flow), false); ++ route_err = v6ops->route(net, (struct dst_entry **)&rt, ++ flowi6_to_flowi(&flow), false); + } else { + route_err = 1; + } diff --git a/target/linux/generic/backport-4.14/308-netfilter-move-reroute-indirection-to-struct-nf_ipv6.patch b/target/linux/generic/backport-4.14/308-netfilter-move-reroute-indirection-to-struct-nf_ipv6.patch new file mode 100644 index 000000000..2ffb39d9a --- /dev/null +++ b/target/linux/generic/backport-4.14/308-netfilter-move-reroute-indirection-to-struct-nf_ipv6.patch @@ -0,0 +1,223 @@ +From: Pablo Neira Ayuso +Date: Mon, 27 Nov 2017 22:50:26 +0100 +Subject: [PATCH] netfilter: move reroute indirection to struct nf_ipv6_ops + +We cannot make a direct call to nf_ip6_reroute() because that would result +in autoloading the 'ipv6' module because of symbol dependencies. +Therefore, define reroute indirection in nf_ipv6_ops where this really +belongs to. + +For IPv4, we can indeed make a direct function call, which is faster, +given IPv4 is built-in in the networking code by default. Still, +CONFIG_INET=n and CONFIG_NETFILTER=y is possible, so define empty inline +stub for IPv4 in such case. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/linux/netfilter.h ++++ b/include/linux/netfilter.h +@@ -274,8 +274,6 @@ struct nf_queue_entry; + + struct nf_afinfo { + unsigned short family; +- int (*reroute)(struct net *net, struct sk_buff *skb, +- const struct nf_queue_entry *entry); + int route_key_size; + }; + +@@ -294,6 +292,7 @@ __sum16 nf_checksum_partial(struct sk_bu + u_int8_t protocol, unsigned short family); + int nf_route(struct net *net, struct dst_entry **dst, struct flowi *fl, + bool strict, unsigned short family); ++int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry); + + int nf_register_afinfo(const struct nf_afinfo *afinfo); + void nf_unregister_afinfo(const struct nf_afinfo *afinfo); +--- a/include/linux/netfilter_ipv4.h ++++ b/include/linux/netfilter_ipv4.h +@@ -18,6 +18,8 @@ struct ip_rt_info { + + int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned addr_type); + ++struct nf_queue_entry; ++ + #ifdef CONFIG_INET + __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol); +@@ -26,6 +28,7 @@ __sum16 nf_ip_checksum_partial(struct sk + u_int8_t protocol); + int nf_ip_route(struct net *net, struct dst_entry **dst, struct flowi *fl, + bool strict); ++int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry); + #else + static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol) +@@ -45,6 +48,11 @@ static inline int nf_ip_route(struct net + { + return -EOPNOTSUPP; + } ++static inline int nf_ip_reroute(struct sk_buff *skb, ++ const struct nf_queue_entry *entry) ++{ ++ return -EOPNOTSUPP; ++} + #endif /* CONFIG_INET */ + + #endif /*__LINUX_IP_NETFILTER_H*/ +--- a/include/linux/netfilter_ipv6.h ++++ b/include/linux/netfilter_ipv6.h +@@ -18,6 +18,8 @@ struct ip6_rt_info { + u_int32_t mark; + }; + ++struct nf_queue_entry; ++ + /* + * Hook functions for ipv6 to allow xt_* modules to be built-in even + * if IPv6 is a module. +@@ -35,6 +37,7 @@ struct nf_ipv6_ops { + u_int8_t protocol); + int (*route)(struct net *net, struct dst_entry **dst, struct flowi *fl, + bool strict); ++ int (*reroute)(struct sk_buff *skb, const struct nf_queue_entry *entry); + }; + + #ifdef CONFIG_NETFILTER +--- a/net/bridge/netfilter/nf_tables_bridge.c ++++ b/net/bridge/netfilter/nf_tables_bridge.c +@@ -95,15 +95,8 @@ static const struct nf_chain_type filter + (1 << NF_BR_POST_ROUTING), + }; + +-static int nf_br_reroute(struct net *net, struct sk_buff *skb, +- const struct nf_queue_entry *entry) +-{ +- return 0; +-} +- + static const struct nf_afinfo nf_br_afinfo = { + .family = AF_BRIDGE, +- .reroute = nf_br_reroute, + .route_key_size = 0, + }; + +--- a/net/ipv4/netfilter.c ++++ b/net/ipv4/netfilter.c +@@ -80,8 +80,7 @@ int ip_route_me_harder(struct net *net, + } + EXPORT_SYMBOL(ip_route_me_harder); + +-static int nf_ip_reroute(struct net *net, struct sk_buff *skb, +- const struct nf_queue_entry *entry) ++int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry) + { + const struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry); + +@@ -92,10 +91,12 @@ static int nf_ip_reroute(struct net *net + skb->mark == rt_info->mark && + iph->daddr == rt_info->daddr && + iph->saddr == rt_info->saddr)) +- return ip_route_me_harder(net, skb, RTN_UNSPEC); ++ return ip_route_me_harder(entry->state.net, skb, ++ RTN_UNSPEC); + } + return 0; + } ++EXPORT_SYMBOL_GPL(nf_ip_reroute); + + __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol) +@@ -163,7 +164,6 @@ EXPORT_SYMBOL_GPL(nf_ip_route); + + static const struct nf_afinfo nf_ip_afinfo = { + .family = AF_INET, +- .reroute = nf_ip_reroute, + .route_key_size = sizeof(struct ip_rt_info), + }; + +--- a/net/ipv6/netfilter.c ++++ b/net/ipv6/netfilter.c +@@ -69,7 +69,7 @@ int ip6_route_me_harder(struct net *net, + } + EXPORT_SYMBOL(ip6_route_me_harder); + +-static int nf_ip6_reroute(struct net *net, struct sk_buff *skb, ++static int nf_ip6_reroute(struct sk_buff *skb, + const struct nf_queue_entry *entry) + { + struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry); +@@ -79,7 +79,7 @@ static int nf_ip6_reroute(struct net *ne + if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) || + !ipv6_addr_equal(&iph->saddr, &rt_info->saddr) || + skb->mark != rt_info->mark) +- return ip6_route_me_harder(net, skb); ++ return ip6_route_me_harder(entry->state.net, skb); + } + return 0; + } +@@ -172,11 +172,11 @@ static const struct nf_ipv6_ops ipv6ops + .checksum = nf_ip6_checksum, + .checksum_partial = nf_ip6_checksum_partial, + .route = nf_ip6_route, ++ .reroute = nf_ip6_reroute, + }; + + static const struct nf_afinfo nf_ip6_afinfo = { + .family = AF_INET6, +- .reroute = nf_ip6_reroute, + .route_key_size = sizeof(struct ip6_rt_info), + }; + +--- a/net/netfilter/nf_queue.c ++++ b/net/netfilter/nf_queue.c +@@ -250,7 +250,6 @@ void nf_reinject(struct nf_queue_entry * + const struct nf_hook_entry *hook_entry; + const struct nf_hook_entries *hooks; + struct sk_buff *skb = entry->skb; +- const struct nf_afinfo *afinfo; + const struct net *net; + unsigned int i; + int err; +@@ -277,8 +276,7 @@ void nf_reinject(struct nf_queue_entry * + verdict = nf_hook_entry_hookfn(hook_entry, skb, &entry->state); + + if (verdict == NF_ACCEPT) { +- afinfo = nf_get_afinfo(entry->state.pf); +- if (!afinfo || afinfo->reroute(entry->state.net, skb, entry) < 0) ++ if (nf_reroute(skb, entry) < 0) + verdict = NF_DROP; + } + +--- a/net/netfilter/utils.c ++++ b/net/netfilter/utils.c +@@ -2,6 +2,7 @@ + #include + #include + #include ++#include + + __sum16 nf_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol, +@@ -69,3 +70,21 @@ int nf_route(struct net *net, struct dst + return ret; + } + EXPORT_SYMBOL_GPL(nf_route); ++ ++int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry) ++{ ++ const struct nf_ipv6_ops *v6ops; ++ int ret = 0; ++ ++ switch (entry->state.pf) { ++ case AF_INET: ++ ret = nf_ip_reroute(skb, entry); ++ break; ++ case AF_INET6: ++ v6ops = rcu_dereference(nf_ipv6_ops); ++ if (v6ops) ++ ret = v6ops->reroute(skb, entry); ++ break; ++ } ++ return ret; ++} diff --git a/target/linux/generic/backport-4.14/309-netfilter-remove-route_key_size-field-in-struct-nf_a.patch b/target/linux/generic/backport-4.14/309-netfilter-remove-route_key_size-field-in-struct-nf_a.patch new file mode 100644 index 000000000..1b571252b --- /dev/null +++ b/target/linux/generic/backport-4.14/309-netfilter-remove-route_key_size-field-in-struct-nf_a.patch @@ -0,0 +1,94 @@ +From: Pablo Neira Ayuso +Date: Mon, 27 Nov 2017 22:58:37 +0100 +Subject: [PATCH] netfilter: remove route_key_size field in struct nf_afinfo + +This is only needed by nf_queue, place this code where it belongs. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/linux/netfilter.h ++++ b/include/linux/netfilter.h +@@ -274,7 +274,6 @@ struct nf_queue_entry; + + struct nf_afinfo { + unsigned short family; +- int route_key_size; + }; + + extern const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO]; +--- a/net/ipv4/netfilter.c ++++ b/net/ipv4/netfilter.c +@@ -164,7 +164,6 @@ EXPORT_SYMBOL_GPL(nf_ip_route); + + static const struct nf_afinfo nf_ip_afinfo = { + .family = AF_INET, +- .route_key_size = sizeof(struct ip_rt_info), + }; + + static int __init ipv4_netfilter_init(void) +--- a/net/ipv6/netfilter.c ++++ b/net/ipv6/netfilter.c +@@ -177,7 +177,6 @@ static const struct nf_ipv6_ops ipv6ops + + static const struct nf_afinfo nf_ip6_afinfo = { + .family = AF_INET6, +- .route_key_size = sizeof(struct ip6_rt_info), + }; + + int __init ipv6_netfilter_init(void) +--- a/net/netfilter/nf_queue.c ++++ b/net/netfilter/nf_queue.c +@@ -15,6 +15,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -148,9 +150,9 @@ static int __nf_queue(struct sk_buff *sk + { + int status = -ENOENT; + struct nf_queue_entry *entry = NULL; +- const struct nf_afinfo *afinfo; + const struct nf_queue_handler *qh; + struct net *net = state->net; ++ unsigned int route_key_size; + + /* QUEUE == DROP if no one is waiting, to be safe. */ + qh = rcu_dereference(net->nf.queue_handler); +@@ -159,11 +161,19 @@ static int __nf_queue(struct sk_buff *sk + goto err; + } + +- afinfo = nf_get_afinfo(state->pf); +- if (!afinfo) +- goto err; ++ switch (state->pf) { ++ case AF_INET: ++ route_key_size = sizeof(struct ip_rt_info); ++ break; ++ case AF_INET6: ++ route_key_size = sizeof(struct ip6_rt_info); ++ break; ++ default: ++ route_key_size = 0; ++ break; ++ } + +- entry = kmalloc(sizeof(*entry) + afinfo->route_key_size, GFP_ATOMIC); ++ entry = kmalloc(sizeof(*entry) + route_key_size, GFP_ATOMIC); + if (!entry) { + status = -ENOMEM; + goto err; +@@ -173,7 +183,7 @@ static int __nf_queue(struct sk_buff *sk + .skb = skb, + .state = *state, + .hook_index = index, +- .size = sizeof(*entry) + afinfo->route_key_size, ++ .size = sizeof(*entry) + route_key_size, + }; + + nf_queue_entry_get_refs(entry); diff --git a/target/linux/generic/backport-4.14/310-netfilter-remove-struct-nf_afinfo-and-its-helper-fun.patch b/target/linux/generic/backport-4.14/310-netfilter-remove-struct-nf_afinfo-and-its-helper-fun.patch new file mode 100644 index 000000000..6d19743df --- /dev/null +++ b/target/linux/generic/backport-4.14/310-netfilter-remove-struct-nf_afinfo-and-its-helper-fun.patch @@ -0,0 +1,173 @@ +From: Pablo Neira Ayuso +Date: Sat, 9 Dec 2017 17:05:53 +0100 +Subject: [PATCH] netfilter: remove struct nf_afinfo and its helper functions + +This abstraction has no clients anymore, remove it. + +This is what remains from previous authors, so correct copyright +statement after recent modifications and code removal. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/linux/netfilter.h ++++ b/include/linux/netfilter.h +@@ -272,16 +272,6 @@ int skb_make_writable(struct sk_buff *sk + struct flowi; + struct nf_queue_entry; + +-struct nf_afinfo { +- unsigned short family; +-}; +- +-extern const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO]; +-static inline const struct nf_afinfo *nf_get_afinfo(unsigned short family) +-{ +- return rcu_dereference(nf_afinfo[family]); +-} +- + __sum16 nf_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol, + unsigned short family); +@@ -293,9 +283,6 @@ int nf_route(struct net *net, struct dst + bool strict, unsigned short family); + int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry); + +-int nf_register_afinfo(const struct nf_afinfo *afinfo); +-void nf_unregister_afinfo(const struct nf_afinfo *afinfo); +- + #include + extern void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *); + +--- a/net/bridge/netfilter/nf_tables_bridge.c ++++ b/net/bridge/netfilter/nf_tables_bridge.c +@@ -95,30 +95,23 @@ static const struct nf_chain_type filter + (1 << NF_BR_POST_ROUTING), + }; + +-static const struct nf_afinfo nf_br_afinfo = { +- .family = AF_BRIDGE, +- .route_key_size = 0, +-}; +- + static int __init nf_tables_bridge_init(void) + { + int ret; + +- nf_register_afinfo(&nf_br_afinfo); + ret = nft_register_chain_type(&filter_bridge); + if (ret < 0) +- goto err1; ++ return ret; + + ret = register_pernet_subsys(&nf_tables_bridge_net_ops); + if (ret < 0) +- goto err2; ++ goto err_register_subsys; + + return ret; + +-err2: ++err_register_subsys: + nft_unregister_chain_type(&filter_bridge); +-err1: +- nf_unregister_afinfo(&nf_br_afinfo); ++ + return ret; + } + +@@ -126,7 +119,6 @@ static void __exit nf_tables_bridge_exit + { + unregister_pernet_subsys(&nf_tables_bridge_net_ops); + nft_unregister_chain_type(&filter_bridge); +- nf_unregister_afinfo(&nf_br_afinfo); + } + + module_init(nf_tables_bridge_init); +--- a/net/ipv4/netfilter.c ++++ b/net/ipv4/netfilter.c +@@ -161,13 +161,3 @@ int nf_ip_route(struct net *net, struct + return 0; + } + EXPORT_SYMBOL_GPL(nf_ip_route); +- +-static const struct nf_afinfo nf_ip_afinfo = { +- .family = AF_INET, +-}; +- +-static int __init ipv4_netfilter_init(void) +-{ +- return nf_register_afinfo(&nf_ip_afinfo); +-} +-subsys_initcall(ipv4_netfilter_init); +--- a/net/ipv6/netfilter.c ++++ b/net/ipv6/netfilter.c +@@ -175,14 +175,10 @@ static const struct nf_ipv6_ops ipv6ops + .reroute = nf_ip6_reroute, + }; + +-static const struct nf_afinfo nf_ip6_afinfo = { +- .family = AF_INET6, +-}; +- + int __init ipv6_netfilter_init(void) + { + RCU_INIT_POINTER(nf_ipv6_ops, &ipv6ops); +- return nf_register_afinfo(&nf_ip6_afinfo); ++ return 0; + } + + /* This can be called from inet6_init() on errors, so it cannot +@@ -191,5 +187,4 @@ int __init ipv6_netfilter_init(void) + void ipv6_netfilter_fini(void) + { + RCU_INIT_POINTER(nf_ipv6_ops, NULL); +- nf_unregister_afinfo(&nf_ip6_afinfo); + } +--- a/net/netfilter/core.c ++++ b/net/netfilter/core.c +@@ -4,8 +4,7 @@ + * Thanks to Rob `CmdrTaco' Malda for not influencing this code in any + * way. + * +- * Rusty Russell (C)2000 -- This code is GPL. +- * Patrick McHardy (c) 2006-2012 ++ * This code is GPL. + */ + #include + #include +@@ -28,34 +27,12 @@ + + #include "nf_internals.h" + +-static DEFINE_MUTEX(afinfo_mutex); +- +-const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly; +-EXPORT_SYMBOL(nf_afinfo); + const struct nf_ipv6_ops __rcu *nf_ipv6_ops __read_mostly; + EXPORT_SYMBOL_GPL(nf_ipv6_ops); + + DEFINE_PER_CPU(bool, nf_skb_duplicated); + EXPORT_SYMBOL_GPL(nf_skb_duplicated); + +-int nf_register_afinfo(const struct nf_afinfo *afinfo) +-{ +- mutex_lock(&afinfo_mutex); +- RCU_INIT_POINTER(nf_afinfo[afinfo->family], afinfo); +- mutex_unlock(&afinfo_mutex); +- return 0; +-} +-EXPORT_SYMBOL_GPL(nf_register_afinfo); +- +-void nf_unregister_afinfo(const struct nf_afinfo *afinfo) +-{ +- mutex_lock(&afinfo_mutex); +- RCU_INIT_POINTER(nf_afinfo[afinfo->family], NULL); +- mutex_unlock(&afinfo_mutex); +- synchronize_rcu(); +-} +-EXPORT_SYMBOL_GPL(nf_unregister_afinfo); +- + #ifdef HAVE_JUMP_LABEL + struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS]; + EXPORT_SYMBOL(nf_hooks_needed); diff --git a/target/linux/generic/backport-4.14/311-netfilter-nf_tables_arp-don-t-set-forward-chain.patch b/target/linux/generic/backport-4.14/311-netfilter-nf_tables_arp-don-t-set-forward-chain.patch new file mode 100644 index 000000000..10ce26dc8 --- /dev/null +++ b/target/linux/generic/backport-4.14/311-netfilter-nf_tables_arp-don-t-set-forward-chain.patch @@ -0,0 +1,20 @@ +From: Pablo Neira Ayuso +Date: Sun, 10 Dec 2017 01:42:58 +0100 +Subject: [PATCH] netfilter: nf_tables_arp: don't set forward chain + +46928a0b49f3 ("netfilter: nf_tables: remove multihook chains and +families") already removed this, this is a leftover. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/ipv4/netfilter/nf_tables_arp.c ++++ b/net/ipv4/netfilter/nf_tables_arp.c +@@ -34,7 +34,6 @@ static struct nft_af_info nft_af_arp __r + .hooks = { + [NF_ARP_IN] = nft_do_chain_arp, + [NF_ARP_OUT] = nft_do_chain_arp, +- [NF_ARP_FORWARD] = nft_do_chain_arp, + }, + }; + diff --git a/target/linux/generic/backport-4.14/312-netfilter-nf_tables-remove-hooks-from-family-definit.patch b/target/linux/generic/backport-4.14/312-netfilter-nf_tables-remove-hooks-from-family-definit.patch new file mode 100644 index 000000000..dd969c12a --- /dev/null +++ b/target/linux/generic/backport-4.14/312-netfilter-nf_tables-remove-hooks-from-family-definit.patch @@ -0,0 +1,233 @@ +From: Pablo Neira Ayuso +Date: Sat, 9 Dec 2017 15:43:17 +0100 +Subject: [PATCH] netfilter: nf_tables: remove hooks from family definition + +They don't belong to the family definition, move them to the filter +chain type definition instead. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -870,7 +870,7 @@ enum nft_chain_type { + * @family: address family + * @owner: module owner + * @hook_mask: mask of valid hooks +- * @hooks: hookfn overrides ++ * @hooks: array of hook functions + */ + struct nf_chain_type { + const char *name; +@@ -964,7 +964,6 @@ enum nft_af_flags { + * @owner: module owner + * @tables: used internally + * @flags: family flags +- * @hooks: hookfn overrides for packet validation + */ + struct nft_af_info { + struct list_head list; +@@ -973,7 +972,6 @@ struct nft_af_info { + struct module *owner; + struct list_head tables; + u32 flags; +- nf_hookfn *hooks[NF_MAX_HOOKS]; + }; + + int nft_register_afinfo(struct net *, struct nft_af_info *); +--- a/net/bridge/netfilter/nf_tables_bridge.c ++++ b/net/bridge/netfilter/nf_tables_bridge.c +@@ -46,13 +46,6 @@ static struct nft_af_info nft_af_bridge + .family = NFPROTO_BRIDGE, + .nhooks = NF_BR_NUMHOOKS, + .owner = THIS_MODULE, +- .hooks = { +- [NF_BR_PRE_ROUTING] = nft_do_chain_bridge, +- [NF_BR_LOCAL_IN] = nft_do_chain_bridge, +- [NF_BR_FORWARD] = nft_do_chain_bridge, +- [NF_BR_LOCAL_OUT] = nft_do_chain_bridge, +- [NF_BR_POST_ROUTING] = nft_do_chain_bridge, +- }, + }; + + static int nf_tables_bridge_init_net(struct net *net) +@@ -93,6 +86,13 @@ static const struct nf_chain_type filter + (1 << NF_BR_FORWARD) | + (1 << NF_BR_LOCAL_OUT) | + (1 << NF_BR_POST_ROUTING), ++ .hooks = { ++ [NF_BR_PRE_ROUTING] = nft_do_chain_bridge, ++ [NF_BR_LOCAL_IN] = nft_do_chain_bridge, ++ [NF_BR_FORWARD] = nft_do_chain_bridge, ++ [NF_BR_LOCAL_OUT] = nft_do_chain_bridge, ++ [NF_BR_POST_ROUTING] = nft_do_chain_bridge, ++ }, + }; + + static int __init nf_tables_bridge_init(void) +--- a/net/ipv4/netfilter/nf_tables_arp.c ++++ b/net/ipv4/netfilter/nf_tables_arp.c +@@ -31,10 +31,6 @@ static struct nft_af_info nft_af_arp __r + .family = NFPROTO_ARP, + .nhooks = NF_ARP_NUMHOOKS, + .owner = THIS_MODULE, +- .hooks = { +- [NF_ARP_IN] = nft_do_chain_arp, +- [NF_ARP_OUT] = nft_do_chain_arp, +- }, + }; + + static int nf_tables_arp_init_net(struct net *net) +@@ -72,6 +68,10 @@ static const struct nf_chain_type filter + .owner = THIS_MODULE, + .hook_mask = (1 << NF_ARP_IN) | + (1 << NF_ARP_OUT), ++ .hooks = { ++ [NF_ARP_IN] = nft_do_chain_arp, ++ [NF_ARP_OUT] = nft_do_chain_arp, ++ }, + }; + + static int __init nf_tables_arp_init(void) +--- a/net/ipv4/netfilter/nf_tables_ipv4.c ++++ b/net/ipv4/netfilter/nf_tables_ipv4.c +@@ -49,13 +49,6 @@ static struct nft_af_info nft_af_ipv4 __ + .family = NFPROTO_IPV4, + .nhooks = NF_INET_NUMHOOKS, + .owner = THIS_MODULE, +- .hooks = { +- [NF_INET_LOCAL_IN] = nft_do_chain_ipv4, +- [NF_INET_LOCAL_OUT] = nft_ipv4_output, +- [NF_INET_FORWARD] = nft_do_chain_ipv4, +- [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4, +- [NF_INET_POST_ROUTING] = nft_do_chain_ipv4, +- }, + }; + + static int nf_tables_ipv4_init_net(struct net *net) +@@ -96,6 +89,13 @@ static const struct nf_chain_type filter + (1 << NF_INET_FORWARD) | + (1 << NF_INET_PRE_ROUTING) | + (1 << NF_INET_POST_ROUTING), ++ .hooks = { ++ [NF_INET_LOCAL_IN] = nft_do_chain_ipv4, ++ [NF_INET_LOCAL_OUT] = nft_ipv4_output, ++ [NF_INET_FORWARD] = nft_do_chain_ipv4, ++ [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4, ++ [NF_INET_POST_ROUTING] = nft_do_chain_ipv4, ++ }, + }; + + static int __init nf_tables_ipv4_init(void) +--- a/net/ipv6/netfilter/nf_tables_ipv6.c ++++ b/net/ipv6/netfilter/nf_tables_ipv6.c +@@ -46,13 +46,6 @@ static struct nft_af_info nft_af_ipv6 __ + .family = NFPROTO_IPV6, + .nhooks = NF_INET_NUMHOOKS, + .owner = THIS_MODULE, +- .hooks = { +- [NF_INET_LOCAL_IN] = nft_do_chain_ipv6, +- [NF_INET_LOCAL_OUT] = nft_ipv6_output, +- [NF_INET_FORWARD] = nft_do_chain_ipv6, +- [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6, +- [NF_INET_POST_ROUTING] = nft_do_chain_ipv6, +- }, + }; + + static int nf_tables_ipv6_init_net(struct net *net) +@@ -93,6 +86,13 @@ static const struct nf_chain_type filter + (1 << NF_INET_FORWARD) | + (1 << NF_INET_PRE_ROUTING) | + (1 << NF_INET_POST_ROUTING), ++ .hooks = { ++ [NF_INET_LOCAL_IN] = nft_do_chain_ipv6, ++ [NF_INET_LOCAL_OUT] = nft_ipv6_output, ++ [NF_INET_FORWARD] = nft_do_chain_ipv6, ++ [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6, ++ [NF_INET_POST_ROUTING] = nft_do_chain_ipv6, ++ }, + }; + + static int __init nf_tables_ipv6_init(void) +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -1352,7 +1352,6 @@ static int nf_tables_addchain(struct nft + if (nla[NFTA_CHAIN_HOOK]) { + struct nft_chain_hook hook; + struct nf_hook_ops *ops; +- nf_hookfn *hookfn; + + err = nft_chain_parse_hook(net, nla, afi, &hook, create); + if (err < 0) +@@ -1378,7 +1377,6 @@ static int nf_tables_addchain(struct nft + static_branch_inc(&nft_counters_enabled); + } + +- hookfn = hook.type->hooks[hook.num]; + basechain->type = hook.type; + chain = &basechain->chain; + +@@ -1387,10 +1385,8 @@ static int nf_tables_addchain(struct nft + ops->hooknum = hook.num; + ops->priority = hook.priority; + ops->priv = chain; +- ops->hook = afi->hooks[ops->hooknum]; ++ ops->hook = hook.type->hooks[ops->hooknum]; + ops->dev = hook.dev; +- if (hookfn) +- ops->hook = hookfn; + + if (basechain->type->type == NFT_CHAIN_T_NAT) + ops->nat_hook = true; +--- a/net/netfilter/nf_tables_inet.c ++++ b/net/netfilter/nf_tables_inet.c +@@ -74,13 +74,6 @@ static struct nft_af_info nft_af_inet __ + .family = NFPROTO_INET, + .nhooks = NF_INET_NUMHOOKS, + .owner = THIS_MODULE, +- .hooks = { +- [NF_INET_LOCAL_IN] = nft_do_chain_inet, +- [NF_INET_LOCAL_OUT] = nft_inet_output, +- [NF_INET_FORWARD] = nft_do_chain_inet, +- [NF_INET_PRE_ROUTING] = nft_do_chain_inet, +- [NF_INET_POST_ROUTING] = nft_do_chain_inet, +- }, + }; + + static int __net_init nf_tables_inet_init_net(struct net *net) +@@ -121,6 +114,13 @@ static const struct nf_chain_type filter + (1 << NF_INET_FORWARD) | + (1 << NF_INET_PRE_ROUTING) | + (1 << NF_INET_POST_ROUTING), ++ .hooks = { ++ [NF_INET_LOCAL_IN] = nft_do_chain_inet, ++ [NF_INET_LOCAL_OUT] = nft_inet_output, ++ [NF_INET_FORWARD] = nft_do_chain_inet, ++ [NF_INET_PRE_ROUTING] = nft_do_chain_inet, ++ [NF_INET_POST_ROUTING] = nft_do_chain_inet, ++ }, + }; + + static int __init nf_tables_inet_init(void) +--- a/net/netfilter/nf_tables_netdev.c ++++ b/net/netfilter/nf_tables_netdev.c +@@ -43,9 +43,6 @@ static struct nft_af_info nft_af_netdev + .nhooks = NF_NETDEV_NUMHOOKS, + .owner = THIS_MODULE, + .flags = NFT_AF_NEEDS_DEV, +- .hooks = { +- [NF_NETDEV_INGRESS] = nft_do_chain_netdev, +- }, + }; + + static int nf_tables_netdev_init_net(struct net *net) +@@ -82,6 +79,9 @@ static const struct nf_chain_type nft_fi + .family = NFPROTO_NETDEV, + .owner = THIS_MODULE, + .hook_mask = (1 << NF_NETDEV_INGRESS), ++ .hooks = { ++ [NF_NETDEV_INGRESS] = nft_do_chain_netdev, ++ }, + }; + + static void nft_netdev_event(unsigned long event, struct net_device *dev, diff --git a/target/linux/generic/backport-4.14/313-netfilter-remove-defensive-check-on-malformed-packet.patch b/target/linux/generic/backport-4.14/313-netfilter-remove-defensive-check-on-malformed-packet.patch new file mode 100644 index 000000000..30b0bc70d --- /dev/null +++ b/target/linux/generic/backport-4.14/313-netfilter-remove-defensive-check-on-malformed-packet.patch @@ -0,0 +1,302 @@ +From: Pablo Neira Ayuso +Date: Sat, 30 Dec 2017 22:41:46 +0100 +Subject: [PATCH] netfilter: remove defensive check on malformed packets from + raw sockets + +Users cannot forge malformed IPv4/IPv6 headers via raw sockets that they +can inject into the stack. Specifically, not for IPv4 since 55888dfb6ba7 +("AF_RAW: Augment raw_send_hdrinc to expand skb to fit iphdr->ihl +(v2)"). IPv6 raw sockets also ensure that packets have a well-formed +IPv6 header available in the skbuff. + +At quick glance, br_netfilter also validates layer 3 headers and it +drops malformed both IPv4 and IPv6 packets. + +Therefore, let's remove this defensive check all over the place. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/ipv4/netfilter/iptable_filter.c ++++ b/net/ipv4/netfilter/iptable_filter.c +@@ -38,12 +38,6 @@ static unsigned int + iptable_filter_hook(void *priv, struct sk_buff *skb, + const struct nf_hook_state *state) + { +- if (state->hook == NF_INET_LOCAL_OUT && +- (skb->len < sizeof(struct iphdr) || +- ip_hdrlen(skb) < sizeof(struct iphdr))) +- /* root is playing with raw sockets. */ +- return NF_ACCEPT; +- + return ipt_do_table(skb, state, state->net->ipv4.iptable_filter); + } + +--- a/net/ipv4/netfilter/iptable_mangle.c ++++ b/net/ipv4/netfilter/iptable_mangle.c +@@ -49,11 +49,6 @@ ipt_mangle_out(struct sk_buff *skb, cons + u_int32_t mark; + int err; + +- /* root is playing with raw sockets. */ +- if (skb->len < sizeof(struct iphdr) || +- ip_hdrlen(skb) < sizeof(struct iphdr)) +- return NF_ACCEPT; +- + /* Save things which could affect route */ + mark = skb->mark; + iph = ip_hdr(skb); +--- a/net/ipv4/netfilter/iptable_raw.c ++++ b/net/ipv4/netfilter/iptable_raw.c +@@ -26,12 +26,6 @@ static unsigned int + iptable_raw_hook(void *priv, struct sk_buff *skb, + const struct nf_hook_state *state) + { +- if (state->hook == NF_INET_LOCAL_OUT && +- (skb->len < sizeof(struct iphdr) || +- ip_hdrlen(skb) < sizeof(struct iphdr))) +- /* root is playing with raw sockets. */ +- return NF_ACCEPT; +- + return ipt_do_table(skb, state, state->net->ipv4.iptable_raw); + } + +--- a/net/ipv4/netfilter/iptable_security.c ++++ b/net/ipv4/netfilter/iptable_security.c +@@ -43,12 +43,6 @@ static unsigned int + iptable_security_hook(void *priv, struct sk_buff *skb, + const struct nf_hook_state *state) + { +- if (state->hook == NF_INET_LOCAL_OUT && +- (skb->len < sizeof(struct iphdr) || +- ip_hdrlen(skb) < sizeof(struct iphdr))) +- /* Somebody is playing with raw sockets. */ +- return NF_ACCEPT; +- + return ipt_do_table(skb, state, state->net->ipv4.iptable_security); + } + +--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c ++++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +@@ -154,11 +154,6 @@ static unsigned int ipv4_conntrack_local + struct sk_buff *skb, + const struct nf_hook_state *state) + { +- /* root is playing with raw sockets. */ +- if (skb->len < sizeof(struct iphdr) || +- ip_hdrlen(skb) < sizeof(struct iphdr)) +- return NF_ACCEPT; +- + if (ip_is_fragment(ip_hdr(skb))) /* IP_NODEFRAG setsockopt set */ + return NF_ACCEPT; + +--- a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c ++++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +@@ -355,11 +355,6 @@ nf_nat_ipv4_out(void *priv, struct sk_bu + #endif + unsigned int ret; + +- /* root is playing with raw sockets. */ +- if (skb->len < sizeof(struct iphdr) || +- ip_hdrlen(skb) < sizeof(struct iphdr)) +- return NF_ACCEPT; +- + ret = nf_nat_ipv4_fn(priv, skb, state, do_chain); + #ifdef CONFIG_XFRM + if (ret != NF_DROP && ret != NF_STOLEN && +@@ -395,11 +390,6 @@ nf_nat_ipv4_local_fn(void *priv, struct + unsigned int ret; + int err; + +- /* root is playing with raw sockets. */ +- if (skb->len < sizeof(struct iphdr) || +- ip_hdrlen(skb) < sizeof(struct iphdr)) +- return NF_ACCEPT; +- + ret = nf_nat_ipv4_fn(priv, skb, state, do_chain); + if (ret != NF_DROP && ret != NF_STOLEN && + (ct = nf_ct_get(skb, &ctinfo)) != NULL) { +--- a/net/ipv4/netfilter/nf_tables_ipv4.c ++++ b/net/ipv4/netfilter/nf_tables_ipv4.c +@@ -30,21 +30,6 @@ static unsigned int nft_do_chain_ipv4(vo + return nft_do_chain(&pkt, priv); + } + +-static unsigned int nft_ipv4_output(void *priv, +- struct sk_buff *skb, +- const struct nf_hook_state *state) +-{ +- if (unlikely(skb->len < sizeof(struct iphdr) || +- ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) { +- if (net_ratelimit()) +- pr_info("nf_tables_ipv4: ignoring short SOCK_RAW " +- "packet\n"); +- return NF_ACCEPT; +- } +- +- return nft_do_chain_ipv4(priv, skb, state); +-} +- + static struct nft_af_info nft_af_ipv4 __read_mostly = { + .family = NFPROTO_IPV4, + .nhooks = NF_INET_NUMHOOKS, +@@ -91,7 +76,7 @@ static const struct nf_chain_type filter + (1 << NF_INET_POST_ROUTING), + .hooks = { + [NF_INET_LOCAL_IN] = nft_do_chain_ipv4, +- [NF_INET_LOCAL_OUT] = nft_ipv4_output, ++ [NF_INET_LOCAL_OUT] = nft_do_chain_ipv4, + [NF_INET_FORWARD] = nft_do_chain_ipv4, + [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4, + [NF_INET_POST_ROUTING] = nft_do_chain_ipv4, +--- a/net/ipv4/netfilter/nft_chain_route_ipv4.c ++++ b/net/ipv4/netfilter/nft_chain_route_ipv4.c +@@ -33,11 +33,6 @@ static unsigned int nf_route_table_hook( + const struct iphdr *iph; + int err; + +- /* root is playing with raw sockets. */ +- if (skb->len < sizeof(struct iphdr) || +- ip_hdrlen(skb) < sizeof(struct iphdr)) +- return NF_ACCEPT; +- + nft_set_pktinfo(&pkt, skb, state); + nft_set_pktinfo_ipv4(&pkt, skb); + +--- a/net/ipv6/netfilter/ip6table_mangle.c ++++ b/net/ipv6/netfilter/ip6table_mangle.c +@@ -42,14 +42,6 @@ ip6t_mangle_out(struct sk_buff *skb, con + u_int8_t hop_limit; + u_int32_t flowlabel, mark; + int err; +-#if 0 +- /* root is playing with raw sockets. */ +- if (skb->len < sizeof(struct iphdr) || +- ip_hdrlen(skb) < sizeof(struct iphdr)) { +- net_warn_ratelimited("ip6t_hook: happy cracking\n"); +- return NF_ACCEPT; +- } +-#endif + + /* save source/dest address, mark, hoplimit, flowlabel, priority, */ + memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr)); +--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c ++++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +@@ -176,11 +176,6 @@ static unsigned int ipv6_conntrack_local + struct sk_buff *skb, + const struct nf_hook_state *state) + { +- /* root is playing with raw sockets. */ +- if (skb->len < sizeof(struct ipv6hdr)) { +- net_notice_ratelimited("ipv6_conntrack_local: packet too short\n"); +- return NF_ACCEPT; +- } + return nf_conntrack_in(state->net, PF_INET6, state->hook, skb); + } + +--- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c ++++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c +@@ -372,10 +372,6 @@ nf_nat_ipv6_out(void *priv, struct sk_bu + #endif + unsigned int ret; + +- /* root is playing with raw sockets. */ +- if (skb->len < sizeof(struct ipv6hdr)) +- return NF_ACCEPT; +- + ret = nf_nat_ipv6_fn(priv, skb, state, do_chain); + #ifdef CONFIG_XFRM + if (ret != NF_DROP && ret != NF_STOLEN && +@@ -411,10 +407,6 @@ nf_nat_ipv6_local_fn(void *priv, struct + unsigned int ret; + int err; + +- /* root is playing with raw sockets. */ +- if (skb->len < sizeof(struct ipv6hdr)) +- return NF_ACCEPT; +- + ret = nf_nat_ipv6_fn(priv, skb, state, do_chain); + if (ret != NF_DROP && ret != NF_STOLEN && + (ct = nf_ct_get(skb, &ctinfo)) != NULL) { +--- a/net/ipv6/netfilter/nf_tables_ipv6.c ++++ b/net/ipv6/netfilter/nf_tables_ipv6.c +@@ -28,20 +28,6 @@ static unsigned int nft_do_chain_ipv6(vo + return nft_do_chain(&pkt, priv); + } + +-static unsigned int nft_ipv6_output(void *priv, +- struct sk_buff *skb, +- const struct nf_hook_state *state) +-{ +- if (unlikely(skb->len < sizeof(struct ipv6hdr))) { +- if (net_ratelimit()) +- pr_info("nf_tables_ipv6: ignoring short SOCK_RAW " +- "packet\n"); +- return NF_ACCEPT; +- } +- +- return nft_do_chain_ipv6(priv, skb, state); +-} +- + static struct nft_af_info nft_af_ipv6 __read_mostly = { + .family = NFPROTO_IPV6, + .nhooks = NF_INET_NUMHOOKS, +@@ -88,7 +74,7 @@ static const struct nf_chain_type filter + (1 << NF_INET_POST_ROUTING), + .hooks = { + [NF_INET_LOCAL_IN] = nft_do_chain_ipv6, +- [NF_INET_LOCAL_OUT] = nft_ipv6_output, ++ [NF_INET_LOCAL_OUT] = nft_do_chain_ipv6, + [NF_INET_FORWARD] = nft_do_chain_ipv6, + [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6, + [NF_INET_POST_ROUTING] = nft_do_chain_ipv6, +--- a/net/netfilter/nf_tables_inet.c ++++ b/net/netfilter/nf_tables_inet.c +@@ -38,38 +38,6 @@ static unsigned int nft_do_chain_inet(vo + return nft_do_chain(&pkt, priv); + } + +-static unsigned int nft_inet_output(void *priv, struct sk_buff *skb, +- const struct nf_hook_state *state) +-{ +- struct nft_pktinfo pkt; +- +- nft_set_pktinfo(&pkt, skb, state); +- +- switch (state->pf) { +- case NFPROTO_IPV4: +- if (unlikely(skb->len < sizeof(struct iphdr) || +- ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) { +- if (net_ratelimit()) +- pr_info("ignoring short SOCK_RAW packet\n"); +- return NF_ACCEPT; +- } +- nft_set_pktinfo_ipv4(&pkt, skb); +- break; +- case NFPROTO_IPV6: +- if (unlikely(skb->len < sizeof(struct ipv6hdr))) { +- if (net_ratelimit()) +- pr_info("ignoring short SOCK_RAW packet\n"); +- return NF_ACCEPT; +- } +- nft_set_pktinfo_ipv6(&pkt, skb); +- break; +- default: +- break; +- } +- +- return nft_do_chain(&pkt, priv); +-} +- + static struct nft_af_info nft_af_inet __read_mostly = { + .family = NFPROTO_INET, + .nhooks = NF_INET_NUMHOOKS, +@@ -116,7 +84,7 @@ static const struct nf_chain_type filter + (1 << NF_INET_POST_ROUTING), + .hooks = { + [NF_INET_LOCAL_IN] = nft_do_chain_inet, +- [NF_INET_LOCAL_OUT] = nft_inet_output, ++ [NF_INET_LOCAL_OUT] = nft_do_chain_inet, + [NF_INET_FORWARD] = nft_do_chain_inet, + [NF_INET_PRE_ROUTING] = nft_do_chain_inet, + [NF_INET_POST_ROUTING] = nft_do_chain_inet, diff --git a/target/linux/generic/backport-4.14/314-netfilter-meta-secpath-support.patch b/target/linux/generic/backport-4.14/314-netfilter-meta-secpath-support.patch new file mode 100644 index 000000000..d755c17fc --- /dev/null +++ b/target/linux/generic/backport-4.14/314-netfilter-meta-secpath-support.patch @@ -0,0 +1,101 @@ +From: Florian Westphal +Date: Wed, 6 Dec 2017 16:18:16 +0100 +Subject: [PATCH] netfilter: meta: secpath support + +replacement for iptables "-m policy --dir in --policy {ipsec,none}". + +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/uapi/linux/netfilter/nf_tables.h ++++ b/include/uapi/linux/netfilter/nf_tables.h +@@ -777,6 +777,7 @@ enum nft_exthdr_attributes { + * @NFT_META_OIFGROUP: packet output interface group + * @NFT_META_CGROUP: socket control group (skb->sk->sk_classid) + * @NFT_META_PRANDOM: a 32bit pseudo-random number ++ * @NFT_META_SECPATH: boolean, secpath_exists (!!skb->sp) + */ + enum nft_meta_keys { + NFT_META_LEN, +@@ -804,6 +805,7 @@ enum nft_meta_keys { + NFT_META_OIFGROUP, + NFT_META_CGROUP, + NFT_META_PRANDOM, ++ NFT_META_SECPATH, + }; + + /** +--- a/net/netfilter/nft_meta.c ++++ b/net/netfilter/nft_meta.c +@@ -210,6 +210,11 @@ void nft_meta_get_eval(const struct nft_ + *dest = prandom_u32_state(state); + break; + } ++#ifdef CONFIG_XFRM ++ case NFT_META_SECPATH: ++ nft_reg_store8(dest, !!skb->sp); ++ break; ++#endif + default: + WARN_ON(1); + goto err; +@@ -308,6 +313,11 @@ int nft_meta_get_init(const struct nft_c + prandom_init_once(&nft_prandom_state); + len = sizeof(u32); + break; ++#ifdef CONFIG_XFRM ++ case NFT_META_SECPATH: ++ len = sizeof(u8); ++ break; ++#endif + default: + return -EOPNOTSUPP; + } +@@ -318,6 +328,38 @@ int nft_meta_get_init(const struct nft_c + } + EXPORT_SYMBOL_GPL(nft_meta_get_init); + ++static int nft_meta_get_validate(const struct nft_ctx *ctx, ++ const struct nft_expr *expr, ++ const struct nft_data **data) ++{ ++#ifdef CONFIG_XFRM ++ const struct nft_meta *priv = nft_expr_priv(expr); ++ unsigned int hooks; ++ ++ if (priv->key != NFT_META_SECPATH) ++ return 0; ++ ++ switch (ctx->afi->family) { ++ case NFPROTO_NETDEV: ++ hooks = 1 << NF_NETDEV_INGRESS; ++ break; ++ case NFPROTO_IPV4: ++ case NFPROTO_IPV6: ++ case NFPROTO_INET: ++ hooks = (1 << NF_INET_PRE_ROUTING) | ++ (1 << NF_INET_LOCAL_IN) | ++ (1 << NF_INET_FORWARD); ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return nft_chain_validate_hooks(ctx->chain, hooks); ++#else ++ return 0; ++#endif ++} ++ + int nft_meta_set_validate(const struct nft_ctx *ctx, + const struct nft_expr *expr, + const struct nft_data **data) +@@ -434,6 +476,7 @@ static const struct nft_expr_ops nft_met + .eval = nft_meta_get_eval, + .init = nft_meta_get_init, + .dump = nft_meta_get_dump, ++ .validate = nft_meta_get_validate, + }; + + static const struct nft_expr_ops nft_meta_set_ops = { diff --git a/target/linux/generic/backport-4.14/315-netfilter-conntrack-move-nf_ct_netns_-get-put-to-cor.patch b/target/linux/generic/backport-4.14/315-netfilter-conntrack-move-nf_ct_netns_-get-put-to-cor.patch new file mode 100644 index 000000000..7f6e90470 --- /dev/null +++ b/target/linux/generic/backport-4.14/315-netfilter-conntrack-move-nf_ct_netns_-get-put-to-cor.patch @@ -0,0 +1,142 @@ +From: Pablo Neira Ayuso +Date: Fri, 3 Nov 2017 16:26:32 +0100 +Subject: [PATCH] netfilter: conntrack: move nf_ct_netns_{get,put}() to core + +So we can call this from other expression that need conntrack in place +to work. + +Signed-off-by: Pablo Neira Ayuso +Acked-by: Florian Westphal +--- + +--- a/net/netfilter/nf_conntrack_proto.c ++++ b/net/netfilter/nf_conntrack_proto.c +@@ -125,7 +125,7 @@ void nf_ct_l3proto_module_put(unsigned s + } + EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put); + +-int nf_ct_netns_get(struct net *net, u8 nfproto) ++static int nf_ct_netns_do_get(struct net *net, u8 nfproto) + { + const struct nf_conntrack_l3proto *l3proto; + int ret; +@@ -150,9 +150,33 @@ int nf_ct_netns_get(struct net *net, u8 + + return ret; + } ++ ++int nf_ct_netns_get(struct net *net, u8 nfproto) ++{ ++ int err; ++ ++ if (nfproto == NFPROTO_INET) { ++ err = nf_ct_netns_do_get(net, NFPROTO_IPV4); ++ if (err < 0) ++ goto err1; ++ err = nf_ct_netns_do_get(net, NFPROTO_IPV6); ++ if (err < 0) ++ goto err2; ++ } else { ++ err = nf_ct_netns_do_get(net, nfproto); ++ if (err < 0) ++ goto err1; ++ } ++ return 0; ++ ++err2: ++ nf_ct_netns_put(net, NFPROTO_IPV4); ++err1: ++ return err; ++} + EXPORT_SYMBOL_GPL(nf_ct_netns_get); + +-void nf_ct_netns_put(struct net *net, u8 nfproto) ++static void nf_ct_netns_do_put(struct net *net, u8 nfproto) + { + const struct nf_conntrack_l3proto *l3proto; + +@@ -171,6 +195,15 @@ void nf_ct_netns_put(struct net *net, u8 + + nf_ct_l3proto_module_put(nfproto); + } ++ ++void nf_ct_netns_put(struct net *net, uint8_t nfproto) ++{ ++ if (nfproto == NFPROTO_INET) { ++ nf_ct_netns_do_put(net, NFPROTO_IPV4); ++ nf_ct_netns_do_put(net, NFPROTO_IPV6); ++ } else ++ nf_ct_netns_do_put(net, nfproto); ++} + EXPORT_SYMBOL_GPL(nf_ct_netns_put); + + const struct nf_conntrack_l4proto * +--- a/net/netfilter/nft_ct.c ++++ b/net/netfilter/nft_ct.c +@@ -312,39 +312,6 @@ static const struct nla_policy nft_ct_po + [NFTA_CT_SREG] = { .type = NLA_U32 }, + }; + +-static int nft_ct_netns_get(struct net *net, uint8_t family) +-{ +- int err; +- +- if (family == NFPROTO_INET) { +- err = nf_ct_netns_get(net, NFPROTO_IPV4); +- if (err < 0) +- goto err1; +- err = nf_ct_netns_get(net, NFPROTO_IPV6); +- if (err < 0) +- goto err2; +- } else { +- err = nf_ct_netns_get(net, family); +- if (err < 0) +- goto err1; +- } +- return 0; +- +-err2: +- nf_ct_netns_put(net, NFPROTO_IPV4); +-err1: +- return err; +-} +- +-static void nft_ct_netns_put(struct net *net, uint8_t family) +-{ +- if (family == NFPROTO_INET) { +- nf_ct_netns_put(net, NFPROTO_IPV4); +- nf_ct_netns_put(net, NFPROTO_IPV6); +- } else +- nf_ct_netns_put(net, family); +-} +- + #ifdef CONFIG_NF_CONNTRACK_ZONES + static void nft_ct_tmpl_put_pcpu(void) + { +@@ -489,7 +456,7 @@ static int nft_ct_get_init(const struct + if (err < 0) + return err; + +- err = nft_ct_netns_get(ctx->net, ctx->afi->family); ++ err = nf_ct_netns_get(ctx->net, ctx->afi->family); + if (err < 0) + return err; + +@@ -583,7 +550,7 @@ static int nft_ct_set_init(const struct + if (err < 0) + goto err1; + +- err = nft_ct_netns_get(ctx->net, ctx->afi->family); ++ err = nf_ct_netns_get(ctx->net, ctx->afi->family); + if (err < 0) + goto err1; + +@@ -606,7 +573,7 @@ static void nft_ct_set_destroy(const str + struct nft_ct *priv = nft_expr_priv(expr); + + __nft_ct_set_destroy(ctx, priv); +- nft_ct_netns_put(ctx->net, ctx->afi->family); ++ nf_ct_netns_put(ctx->net, ctx->afi->family); + } + + static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr) diff --git a/target/linux/generic/backport-4.14/320-netfilter-nf_conntrack-add-IPS_OFFLOAD-status-bit.patch b/target/linux/generic/backport-4.14/320-netfilter-nf_conntrack-add-IPS_OFFLOAD-status-bit.patch new file mode 100644 index 000000000..9d6ce9808 --- /dev/null +++ b/target/linux/generic/backport-4.14/320-netfilter-nf_conntrack-add-IPS_OFFLOAD-status-bit.patch @@ -0,0 +1,169 @@ +From: Pablo Neira Ayuso +Date: Sun, 7 Jan 2018 01:03:56 +0100 +Subject: [PATCH] netfilter: nf_conntrack: add IPS_OFFLOAD status bit + +This new bit tells us that the conntrack entry is owned by the flow +table offload infrastructure. + + # cat /proc/net/nf_conntrack + ipv4 2 tcp 6 src=10.141.10.2 dst=147.75.205.195 sport=36392 dport=443 src=147.75.205.195 dst=192.168.2.195 sport=443 dport=36392 [OFFLOAD] mark=0 zone=0 use=2 + +Note the [OFFLOAD] tag in the listing. + +The timer of such conntrack entries look like stopped from userspace. +In practise, to make sure the conntrack entry does not go away, the +conntrack timer is periodically set to an arbitrary large value that +gets refreshed on every iteration from the garbage collector, so it +never expires- and they display no internal state in the case of TCP +flows. This allows us to save a bitcheck from the packet path via +nf_ct_is_expired(). + +Conntrack entries that have been offloaded to the flow table +infrastructure cannot be deleted/flushed via ctnetlink. The flow table +infrastructure is also responsible for releasing this conntrack entry. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/uapi/linux/netfilter/nf_conntrack_common.h ++++ b/include/uapi/linux/netfilter/nf_conntrack_common.h +@@ -101,12 +101,16 @@ enum ip_conntrack_status { + IPS_HELPER_BIT = 13, + IPS_HELPER = (1 << IPS_HELPER_BIT), + ++ /* Conntrack has been offloaded to flow table. */ ++ IPS_OFFLOAD_BIT = 14, ++ IPS_OFFLOAD = (1 << IPS_OFFLOAD_BIT), ++ + /* Be careful here, modifying these bits can make things messy, + * so don't let users modify them directly. + */ + IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK | + IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING | +- IPS_SEQ_ADJUST | IPS_TEMPLATE), ++ IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_OFFLOAD), + + __IPS_MAX_BIT = 14, + }; +--- a/net/netfilter/nf_conntrack_core.c ++++ b/net/netfilter/nf_conntrack_core.c +@@ -901,6 +901,9 @@ static unsigned int early_drop_list(stru + hlist_nulls_for_each_entry_rcu(h, n, head, hnnode) { + tmp = nf_ct_tuplehash_to_ctrack(h); + ++ if (test_bit(IPS_OFFLOAD_BIT, &tmp->status)) ++ continue; ++ + if (nf_ct_is_expired(tmp)) { + nf_ct_gc_expired(tmp); + continue; +@@ -975,6 +978,18 @@ static bool gc_worker_can_early_drop(con + return false; + } + ++#define DAY (86400 * HZ) ++ ++/* Set an arbitrary timeout large enough not to ever expire, this save ++ * us a check for the IPS_OFFLOAD_BIT from the packet path via ++ * nf_ct_is_expired(). ++ */ ++static void nf_ct_offload_timeout(struct nf_conn *ct) ++{ ++ if (nf_ct_expires(ct) < DAY / 2) ++ ct->timeout = nfct_time_stamp + DAY; ++} ++ + static void gc_worker(struct work_struct *work) + { + unsigned int min_interval = max(HZ / GC_MAX_BUCKETS_DIV, 1u); +@@ -1011,6 +1026,11 @@ static void gc_worker(struct work_struct + tmp = nf_ct_tuplehash_to_ctrack(h); + + scanned++; ++ if (test_bit(IPS_OFFLOAD_BIT, &tmp->status)) { ++ nf_ct_offload_timeout(tmp); ++ continue; ++ } ++ + if (nf_ct_is_expired(tmp)) { + nf_ct_gc_expired(tmp); + expired_count++; +--- a/net/netfilter/nf_conntrack_netlink.c ++++ b/net/netfilter/nf_conntrack_netlink.c +@@ -1105,6 +1105,14 @@ static const struct nla_policy ct_nla_po + .len = NF_CT_LABELS_MAX_SIZE }, + }; + ++static int ctnetlink_flush_iterate(struct nf_conn *ct, void *data) ++{ ++ if (test_bit(IPS_OFFLOAD_BIT, &ct->status)) ++ return 0; ++ ++ return ctnetlink_filter_match(ct, data); ++} ++ + static int ctnetlink_flush_conntrack(struct net *net, + const struct nlattr * const cda[], + u32 portid, int report) +@@ -1117,7 +1125,7 @@ static int ctnetlink_flush_conntrack(str + return PTR_ERR(filter); + } + +- nf_ct_iterate_cleanup_net(net, ctnetlink_filter_match, filter, ++ nf_ct_iterate_cleanup_net(net, ctnetlink_flush_iterate, filter, + portid, report); + kfree(filter); + +@@ -1163,6 +1171,11 @@ static int ctnetlink_del_conntrack(struc + + ct = nf_ct_tuplehash_to_ctrack(h); + ++ if (test_bit(IPS_OFFLOAD_BIT, &ct->status)) { ++ nf_ct_put(ct); ++ return -EBUSY; ++ } ++ + if (cda[CTA_ID]) { + u_int32_t id = ntohl(nla_get_be32(cda[CTA_ID])); + if (id != (u32)(unsigned long)ct) { +--- a/net/netfilter/nf_conntrack_proto_tcp.c ++++ b/net/netfilter/nf_conntrack_proto_tcp.c +@@ -305,6 +305,9 @@ static bool tcp_invert_tuple(struct nf_c + /* Print out the private part of the conntrack. */ + static void tcp_print_conntrack(struct seq_file *s, struct nf_conn *ct) + { ++ if (test_bit(IPS_OFFLOAD_BIT, &ct->status)) ++ return; ++ + seq_printf(s, "%s ", tcp_conntrack_names[ct->proto.tcp.state]); + } + #endif +--- a/net/netfilter/nf_conntrack_standalone.c ++++ b/net/netfilter/nf_conntrack_standalone.c +@@ -309,10 +309,12 @@ static int ct_seq_show(struct seq_file * + WARN_ON(!l4proto); + + ret = -ENOSPC; +- seq_printf(s, "%-8s %u %-8s %u %ld ", ++ seq_printf(s, "%-8s %u %-8s %u ", + l3proto_name(l3proto->l3proto), nf_ct_l3num(ct), +- l4proto_name(l4proto->l4proto), nf_ct_protonum(ct), +- nf_ct_expires(ct) / HZ); ++ l4proto_name(l4proto->l4proto), nf_ct_protonum(ct)); ++ ++ if (!test_bit(IPS_OFFLOAD_BIT, &ct->status)) ++ seq_printf(s, "%ld ", nf_ct_expires(ct) / HZ); + + if (l4proto->print_conntrack) + l4proto->print_conntrack(s, ct); +@@ -339,7 +341,9 @@ static int ct_seq_show(struct seq_file * + if (seq_print_acct(s, ct, IP_CT_DIR_REPLY)) + goto release; + +- if (test_bit(IPS_ASSURED_BIT, &ct->status)) ++ if (test_bit(IPS_OFFLOAD_BIT, &ct->status)) ++ seq_puts(s, "[OFFLOAD] "); ++ else if (test_bit(IPS_ASSURED_BIT, &ct->status)) + seq_puts(s, "[ASSURED] "); + + if (seq_has_overflowed(s)) diff --git a/target/linux/generic/backport-4.14/321-netfilter-nf_tables-add-flow-table-netlink-frontend.patch b/target/linux/generic/backport-4.14/321-netfilter-nf_tables-add-flow-table-netlink-frontend.patch new file mode 100644 index 000000000..2a5025855 --- /dev/null +++ b/target/linux/generic/backport-4.14/321-netfilter-nf_tables-add-flow-table-netlink-frontend.patch @@ -0,0 +1,1079 @@ +From: Pablo Neira Ayuso +Date: Sun, 7 Jan 2018 01:04:07 +0100 +Subject: [PATCH] netfilter: nf_tables: add flow table netlink frontend + +This patch introduces a netlink control plane to create, delete and dump +flow tables. Flow tables are identified by name, this name is used from +rules to refer to an specific flow table. Flow tables use the rhashtable +class and a generic garbage collector to remove expired entries. + +This also adds the infrastructure to add different flow table types, so +we can add one for each layer 3 protocol family. + +Signed-off-by: Pablo Neira Ayuso +--- + create mode 100644 include/net/netfilter/nf_flow_table.h + +--- /dev/null ++++ b/include/net/netfilter/nf_flow_table.h +@@ -0,0 +1,23 @@ ++#ifndef _NF_FLOW_TABLE_H ++#define _NF_FLOW_TABLE_H ++ ++#include ++ ++struct nf_flowtable; ++ ++struct nf_flowtable_type { ++ struct list_head list; ++ int family; ++ void (*gc)(struct work_struct *work); ++ const struct rhashtable_params *params; ++ nf_hookfn *hook; ++ struct module *owner; ++}; ++ ++struct nf_flowtable { ++ struct rhashtable rhashtable; ++ const struct nf_flowtable_type *type; ++ struct delayed_work gc_work; ++}; ++ ++#endif /* _FLOW_OFFLOAD_H */ +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + + #define NFT_JUMP_STACK_SIZE 16 +@@ -933,6 +934,7 @@ unsigned int nft_do_chain(struct nft_pkt + * @chains: chains in the table + * @sets: sets in the table + * @objects: stateful objects in the table ++ * @flowtables: flow tables in the table + * @hgenerator: handle generator state + * @use: number of chain references to this table + * @flags: table flag (see enum nft_table_flags) +@@ -944,6 +946,7 @@ struct nft_table { + struct list_head chains; + struct list_head sets; + struct list_head objects; ++ struct list_head flowtables; + u64 hgenerator; + u32 use; + u16 flags:14, +@@ -1075,6 +1078,44 @@ int nft_register_obj(struct nft_object_t + void nft_unregister_obj(struct nft_object_type *obj_type); + + /** ++ * struct nft_flowtable - nf_tables flow table ++ * ++ * @list: flow table list node in table list ++ * @table: the table the flow table is contained in ++ * @name: name of this flow table ++ * @hooknum: hook number ++ * @priority: hook priority ++ * @ops_len: number of hooks in array ++ * @genmask: generation mask ++ * @use: number of references to this flow table ++ * @data: rhashtable and garbage collector ++ * @ops: array of hooks ++ */ ++struct nft_flowtable { ++ struct list_head list; ++ struct nft_table *table; ++ char *name; ++ int hooknum; ++ int priority; ++ int ops_len; ++ u32 genmask:2, ++ use:30; ++ /* runtime data below here */ ++ struct nf_hook_ops *ops ____cacheline_aligned; ++ struct nf_flowtable data; ++}; ++ ++struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table, ++ const struct nlattr *nla, ++ u8 genmask); ++void nft_flow_table_iterate(struct net *net, ++ void (*iter)(struct nf_flowtable *flowtable, void *data), ++ void *data); ++ ++void nft_register_flowtable_type(struct nf_flowtable_type *type); ++void nft_unregister_flowtable_type(struct nf_flowtable_type *type); ++ ++/** + * struct nft_traceinfo - nft tracing information and state + * + * @pkt: pktinfo currently processed +@@ -1310,4 +1351,11 @@ struct nft_trans_obj { + #define nft_trans_obj(trans) \ + (((struct nft_trans_obj *)trans->data)->obj) + ++struct nft_trans_flowtable { ++ struct nft_flowtable *flowtable; ++}; ++ ++#define nft_trans_flowtable(trans) \ ++ (((struct nft_trans_flowtable *)trans->data)->flowtable) ++ + #endif /* _NET_NF_TABLES_H */ +--- a/include/uapi/linux/netfilter/nf_tables.h ++++ b/include/uapi/linux/netfilter/nf_tables.h +@@ -92,6 +92,9 @@ enum nft_verdicts { + * @NFT_MSG_GETOBJ: get a stateful object (enum nft_obj_attributes) + * @NFT_MSG_DELOBJ: delete a stateful object (enum nft_obj_attributes) + * @NFT_MSG_GETOBJ_RESET: get and reset a stateful object (enum nft_obj_attributes) ++ * @NFT_MSG_NEWFLOWTABLE: add new flow table (enum nft_flowtable_attributes) ++ * @NFT_MSG_GETFLOWTABLE: get flow table (enum nft_flowtable_attributes) ++ * @NFT_MSG_DELFLOWTABLE: delete flow table (enum nft_flowtable_attributes) + */ + enum nf_tables_msg_types { + NFT_MSG_NEWTABLE, +@@ -116,6 +119,9 @@ enum nf_tables_msg_types { + NFT_MSG_GETOBJ, + NFT_MSG_DELOBJ, + NFT_MSG_GETOBJ_RESET, ++ NFT_MSG_NEWFLOWTABLE, ++ NFT_MSG_GETFLOWTABLE, ++ NFT_MSG_DELFLOWTABLE, + NFT_MSG_MAX, + }; + +@@ -1310,6 +1316,53 @@ enum nft_object_attributes { + #define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1) + + /** ++ * enum nft_flowtable_attributes - nf_tables flow table netlink attributes ++ * ++ * @NFTA_FLOWTABLE_TABLE: name of the table containing the expression (NLA_STRING) ++ * @NFTA_FLOWTABLE_NAME: name of this flow table (NLA_STRING) ++ * @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32) ++ * @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32) ++ */ ++enum nft_flowtable_attributes { ++ NFTA_FLOWTABLE_UNSPEC, ++ NFTA_FLOWTABLE_TABLE, ++ NFTA_FLOWTABLE_NAME, ++ NFTA_FLOWTABLE_HOOK, ++ NFTA_FLOWTABLE_USE, ++ __NFTA_FLOWTABLE_MAX ++}; ++#define NFTA_FLOWTABLE_MAX (__NFTA_FLOWTABLE_MAX - 1) ++ ++/** ++ * enum nft_flowtable_hook_attributes - nf_tables flow table hook netlink attributes ++ * ++ * @NFTA_FLOWTABLE_HOOK_NUM: netfilter hook number (NLA_U32) ++ * @NFTA_FLOWTABLE_HOOK_PRIORITY: netfilter hook priority (NLA_U32) ++ * @NFTA_FLOWTABLE_HOOK_DEVS: input devices this flow table is bound to (NLA_NESTED) ++ */ ++enum nft_flowtable_hook_attributes { ++ NFTA_FLOWTABLE_HOOK_UNSPEC, ++ NFTA_FLOWTABLE_HOOK_NUM, ++ NFTA_FLOWTABLE_HOOK_PRIORITY, ++ NFTA_FLOWTABLE_HOOK_DEVS, ++ __NFTA_FLOWTABLE_HOOK_MAX ++}; ++#define NFTA_FLOWTABLE_HOOK_MAX (__NFTA_FLOWTABLE_HOOK_MAX - 1) ++ ++/** ++ * enum nft_device_attributes - nf_tables device netlink attributes ++ * ++ * @NFTA_DEVICE_NAME: name of this device (NLA_STRING) ++ */ ++enum nft_devices_attributes { ++ NFTA_DEVICE_UNSPEC, ++ NFTA_DEVICE_NAME, ++ __NFTA_DEVICE_MAX ++}; ++#define NFTA_DEVICE_MAX (__NFTA_DEVICE_MAX - 1) ++ ++ ++/** + * enum nft_trace_attributes - nf_tables trace netlink attributes + * + * @NFTA_TRACE_TABLE: name of the table (NLA_STRING) +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -24,6 +25,7 @@ + + static LIST_HEAD(nf_tables_expressions); + static LIST_HEAD(nf_tables_objects); ++static LIST_HEAD(nf_tables_flowtables); + + /** + * nft_register_afinfo - register nf_tables address family info +@@ -345,6 +347,40 @@ static int nft_delobj(struct nft_ctx *ct + return err; + } + ++static int nft_trans_flowtable_add(struct nft_ctx *ctx, int msg_type, ++ struct nft_flowtable *flowtable) ++{ ++ struct nft_trans *trans; ++ ++ trans = nft_trans_alloc(ctx, msg_type, ++ sizeof(struct nft_trans_flowtable)); ++ if (trans == NULL) ++ return -ENOMEM; ++ ++ if (msg_type == NFT_MSG_NEWFLOWTABLE) ++ nft_activate_next(ctx->net, flowtable); ++ ++ nft_trans_flowtable(trans) = flowtable; ++ list_add_tail(&trans->list, &ctx->net->nft.commit_list); ++ ++ return 0; ++} ++ ++static int nft_delflowtable(struct nft_ctx *ctx, ++ struct nft_flowtable *flowtable) ++{ ++ int err; ++ ++ err = nft_trans_flowtable_add(ctx, NFT_MSG_DELFLOWTABLE, flowtable); ++ if (err < 0) ++ return err; ++ ++ nft_deactivate_next(ctx->net, flowtable); ++ ctx->table->use--; ++ ++ return err; ++} ++ + /* + * Tables + */ +@@ -728,6 +764,7 @@ static int nf_tables_newtable(struct net + INIT_LIST_HEAD(&table->chains); + INIT_LIST_HEAD(&table->sets); + INIT_LIST_HEAD(&table->objects); ++ INIT_LIST_HEAD(&table->flowtables); + table->flags = flags; + + nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); +@@ -749,10 +786,11 @@ err1: + + static int nft_flush_table(struct nft_ctx *ctx) + { +- int err; ++ struct nft_flowtable *flowtable, *nft; + struct nft_chain *chain, *nc; + struct nft_object *obj, *ne; + struct nft_set *set, *ns; ++ int err; + + list_for_each_entry(chain, &ctx->table->chains, list) { + if (!nft_is_active_next(ctx->net, chain)) +@@ -778,6 +816,12 @@ static int nft_flush_table(struct nft_ct + goto out; + } + ++ list_for_each_entry_safe(flowtable, nft, &ctx->table->flowtables, list) { ++ err = nft_delflowtable(ctx, flowtable); ++ if (err < 0) ++ goto out; ++ } ++ + list_for_each_entry_safe(obj, ne, &ctx->table->objects, list) { + err = nft_delobj(ctx, obj); + if (err < 0) +@@ -4767,6 +4811,605 @@ static void nf_tables_obj_notify(const s + ctx->afi->family, ctx->report, GFP_KERNEL); + } + ++/* ++ * Flow tables ++ */ ++void nft_register_flowtable_type(struct nf_flowtable_type *type) ++{ ++ nfnl_lock(NFNL_SUBSYS_NFTABLES); ++ list_add_tail_rcu(&type->list, &nf_tables_flowtables); ++ nfnl_unlock(NFNL_SUBSYS_NFTABLES); ++} ++EXPORT_SYMBOL_GPL(nft_register_flowtable_type); ++ ++void nft_unregister_flowtable_type(struct nf_flowtable_type *type) ++{ ++ nfnl_lock(NFNL_SUBSYS_NFTABLES); ++ list_del_rcu(&type->list); ++ nfnl_unlock(NFNL_SUBSYS_NFTABLES); ++} ++EXPORT_SYMBOL_GPL(nft_unregister_flowtable_type); ++ ++static const struct nla_policy nft_flowtable_policy[NFTA_FLOWTABLE_MAX + 1] = { ++ [NFTA_FLOWTABLE_TABLE] = { .type = NLA_STRING, ++ .len = NFT_NAME_MAXLEN - 1 }, ++ [NFTA_FLOWTABLE_NAME] = { .type = NLA_STRING, ++ .len = NFT_NAME_MAXLEN - 1 }, ++ [NFTA_FLOWTABLE_HOOK] = { .type = NLA_NESTED }, ++}; ++ ++struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table, ++ const struct nlattr *nla, ++ u8 genmask) ++{ ++ struct nft_flowtable *flowtable; ++ ++ list_for_each_entry(flowtable, &table->flowtables, list) { ++ if (!nla_strcmp(nla, flowtable->name) && ++ nft_active_genmask(flowtable, genmask)) ++ return flowtable; ++ } ++ return ERR_PTR(-ENOENT); ++} ++EXPORT_SYMBOL_GPL(nf_tables_flowtable_lookup); ++ ++#define NFT_FLOWTABLE_DEVICE_MAX 8 ++ ++static int nf_tables_parse_devices(const struct nft_ctx *ctx, ++ const struct nlattr *attr, ++ struct net_device *dev_array[], int *len) ++{ ++ const struct nlattr *tmp; ++ struct net_device *dev; ++ char ifname[IFNAMSIZ]; ++ int rem, n = 0, err; ++ ++ nla_for_each_nested(tmp, attr, rem) { ++ if (nla_type(tmp) != NFTA_DEVICE_NAME) { ++ err = -EINVAL; ++ goto err1; ++ } ++ ++ nla_strlcpy(ifname, tmp, IFNAMSIZ); ++ dev = dev_get_by_name(ctx->net, ifname); ++ if (!dev) { ++ err = -ENOENT; ++ goto err1; ++ } ++ ++ dev_array[n++] = dev; ++ if (n == NFT_FLOWTABLE_DEVICE_MAX) { ++ err = -EFBIG; ++ goto err1; ++ } ++ } ++ if (!len) ++ return -EINVAL; ++ ++ err = 0; ++err1: ++ *len = n; ++ return err; ++} ++ ++static const struct nla_policy nft_flowtable_hook_policy[NFTA_FLOWTABLE_HOOK_MAX + 1] = { ++ [NFTA_FLOWTABLE_HOOK_NUM] = { .type = NLA_U32 }, ++ [NFTA_FLOWTABLE_HOOK_PRIORITY] = { .type = NLA_U32 }, ++ [NFTA_FLOWTABLE_HOOK_DEVS] = { .type = NLA_NESTED }, ++}; ++ ++static int nf_tables_flowtable_parse_hook(const struct nft_ctx *ctx, ++ const struct nlattr *attr, ++ struct nft_flowtable *flowtable) ++{ ++ struct net_device *dev_array[NFT_FLOWTABLE_DEVICE_MAX]; ++ struct nlattr *tb[NFTA_FLOWTABLE_HOOK_MAX + 1]; ++ struct nf_hook_ops *ops; ++ int hooknum, priority; ++ int err, n = 0, i; ++ ++ err = nla_parse_nested(tb, NFTA_FLOWTABLE_HOOK_MAX, attr, ++ nft_flowtable_hook_policy, NULL); ++ if (err < 0) ++ return err; ++ ++ if (!tb[NFTA_FLOWTABLE_HOOK_NUM] || ++ !tb[NFTA_FLOWTABLE_HOOK_PRIORITY] || ++ !tb[NFTA_FLOWTABLE_HOOK_DEVS]) ++ return -EINVAL; ++ ++ hooknum = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_NUM])); ++ if (hooknum >= ctx->afi->nhooks) ++ return -EINVAL; ++ ++ priority = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_PRIORITY])); ++ ++ err = nf_tables_parse_devices(ctx, tb[NFTA_FLOWTABLE_HOOK_DEVS], ++ dev_array, &n); ++ if (err < 0) ++ goto err1; ++ ++ ops = kzalloc(sizeof(struct nf_hook_ops) * n, GFP_KERNEL); ++ if (!ops) { ++ err = -ENOMEM; ++ goto err1; ++ } ++ ++ flowtable->ops = ops; ++ flowtable->ops_len = n; ++ ++ for (i = 0; i < n; i++) { ++ flowtable->ops[i].pf = NFPROTO_NETDEV; ++ flowtable->ops[i].hooknum = hooknum; ++ flowtable->ops[i].priority = priority; ++ flowtable->ops[i].priv = &flowtable->data.rhashtable; ++ flowtable->ops[i].hook = flowtable->data.type->hook; ++ flowtable->ops[i].dev = dev_array[i]; ++ } ++ ++ err = 0; ++err1: ++ for (i = 0; i < n; i++) ++ dev_put(dev_array[i]); ++ ++ return err; ++} ++ ++static const struct nf_flowtable_type * ++__nft_flowtable_type_get(const struct nft_af_info *afi) ++{ ++ const struct nf_flowtable_type *type; ++ ++ list_for_each_entry(type, &nf_tables_flowtables, list) { ++ if (afi->family == type->family) ++ return type; ++ } ++ return NULL; ++} ++ ++static const struct nf_flowtable_type * ++nft_flowtable_type_get(const struct nft_af_info *afi) ++{ ++ const struct nf_flowtable_type *type; ++ ++ type = __nft_flowtable_type_get(afi); ++ if (type != NULL && try_module_get(type->owner)) ++ return type; ++ ++#ifdef CONFIG_MODULES ++ if (type == NULL) { ++ nfnl_unlock(NFNL_SUBSYS_NFTABLES); ++ request_module("nf-flowtable-%u", afi->family); ++ nfnl_lock(NFNL_SUBSYS_NFTABLES); ++ if (__nft_flowtable_type_get(afi)) ++ return ERR_PTR(-EAGAIN); ++ } ++#endif ++ return ERR_PTR(-ENOENT); ++} ++ ++void nft_flow_table_iterate(struct net *net, ++ void (*iter)(struct nf_flowtable *flowtable, void *data), ++ void *data) ++{ ++ struct nft_flowtable *flowtable; ++ const struct nft_af_info *afi; ++ const struct nft_table *table; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(afi, &net->nft.af_info, list) { ++ list_for_each_entry_rcu(table, &afi->tables, list) { ++ list_for_each_entry_rcu(flowtable, &table->flowtables, list) { ++ iter(&flowtable->data, data); ++ } ++ } ++ } ++ rcu_read_unlock(); ++} ++EXPORT_SYMBOL_GPL(nft_flow_table_iterate); ++ ++static void nft_unregister_flowtable_net_hooks(struct net *net, ++ struct nft_flowtable *flowtable) ++{ ++ int i; ++ ++ for (i = 0; i < flowtable->ops_len; i++) { ++ if (!flowtable->ops[i].dev) ++ continue; ++ ++ nf_unregister_net_hook(net, &flowtable->ops[i]); ++ } ++} ++ ++static int nf_tables_newflowtable(struct net *net, struct sock *nlsk, ++ struct sk_buff *skb, ++ const struct nlmsghdr *nlh, ++ const struct nlattr * const nla[], ++ struct netlink_ext_ack *extack) ++{ ++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ++ const struct nf_flowtable_type *type; ++ u8 genmask = nft_genmask_next(net); ++ int family = nfmsg->nfgen_family; ++ struct nft_flowtable *flowtable; ++ struct nft_af_info *afi; ++ struct nft_table *table; ++ struct nft_ctx ctx; ++ int err, i, k; ++ ++ if (!nla[NFTA_FLOWTABLE_TABLE] || ++ !nla[NFTA_FLOWTABLE_NAME] || ++ !nla[NFTA_FLOWTABLE_HOOK]) ++ return -EINVAL; ++ ++ afi = nf_tables_afinfo_lookup(net, family, true); ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++ table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++ flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], ++ genmask); ++ if (IS_ERR(flowtable)) { ++ err = PTR_ERR(flowtable); ++ if (err != -ENOENT) ++ return err; ++ } else { ++ if (nlh->nlmsg_flags & NLM_F_EXCL) ++ return -EEXIST; ++ ++ return 0; ++ } ++ ++ nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); ++ ++ flowtable = kzalloc(sizeof(*flowtable), GFP_KERNEL); ++ if (!flowtable) ++ return -ENOMEM; ++ ++ flowtable->table = table; ++ flowtable->name = nla_strdup(nla[NFTA_FLOWTABLE_NAME], GFP_KERNEL); ++ if (!flowtable->name) { ++ err = -ENOMEM; ++ goto err1; ++ } ++ ++ type = nft_flowtable_type_get(afi); ++ if (IS_ERR(type)) { ++ err = PTR_ERR(type); ++ goto err2; ++ } ++ ++ flowtable->data.type = type; ++ err = rhashtable_init(&flowtable->data.rhashtable, type->params); ++ if (err < 0) ++ goto err3; ++ ++ err = nf_tables_flowtable_parse_hook(&ctx, nla[NFTA_FLOWTABLE_HOOK], ++ flowtable); ++ if (err < 0) ++ goto err3; ++ ++ for (i = 0; i < flowtable->ops_len; i++) { ++ err = nf_register_net_hook(net, &flowtable->ops[i]); ++ if (err < 0) ++ goto err4; ++ } ++ ++ err = nft_trans_flowtable_add(&ctx, NFT_MSG_NEWFLOWTABLE, flowtable); ++ if (err < 0) ++ goto err5; ++ ++ INIT_DEFERRABLE_WORK(&flowtable->data.gc_work, type->gc); ++ queue_delayed_work(system_power_efficient_wq, ++ &flowtable->data.gc_work, HZ); ++ ++ list_add_tail_rcu(&flowtable->list, &table->flowtables); ++ table->use++; ++ ++ return 0; ++err5: ++ i = flowtable->ops_len; ++err4: ++ for (k = i - 1; k >= 0; k--) ++ nf_unregister_net_hook(net, &flowtable->ops[i]); ++ ++ kfree(flowtable->ops); ++err3: ++ module_put(type->owner); ++err2: ++ kfree(flowtable->name); ++err1: ++ kfree(flowtable); ++ return err; ++} ++ ++static int nf_tables_delflowtable(struct net *net, struct sock *nlsk, ++ struct sk_buff *skb, ++ const struct nlmsghdr *nlh, ++ const struct nlattr * const nla[], ++ struct netlink_ext_ack *extack) ++{ ++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ++ u8 genmask = nft_genmask_next(net); ++ int family = nfmsg->nfgen_family; ++ struct nft_flowtable *flowtable; ++ struct nft_af_info *afi; ++ struct nft_table *table; ++ struct nft_ctx ctx; ++ ++ afi = nf_tables_afinfo_lookup(net, family, true); ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++ table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++ flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], ++ genmask); ++ if (IS_ERR(flowtable)) ++ return PTR_ERR(flowtable); ++ if (flowtable->use > 0) ++ return -EBUSY; ++ ++ nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); ++ ++ return nft_delflowtable(&ctx, flowtable); ++} ++ ++static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net, ++ u32 portid, u32 seq, int event, ++ u32 flags, int family, ++ struct nft_flowtable *flowtable) ++{ ++ struct nlattr *nest, *nest_devs; ++ struct nfgenmsg *nfmsg; ++ struct nlmsghdr *nlh; ++ int i; ++ ++ event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); ++ nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags); ++ if (nlh == NULL) ++ goto nla_put_failure; ++ ++ nfmsg = nlmsg_data(nlh); ++ nfmsg->nfgen_family = family; ++ nfmsg->version = NFNETLINK_V0; ++ nfmsg->res_id = htons(net->nft.base_seq & 0xffff); ++ ++ if (nla_put_string(skb, NFTA_FLOWTABLE_TABLE, flowtable->table->name) || ++ nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) || ++ nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use))) ++ goto nla_put_failure; ++ ++ nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK); ++ if (nla_put_be32(skb, NFTA_FLOWTABLE_HOOK_NUM, htonl(flowtable->hooknum)) || ++ nla_put_be32(skb, NFTA_FLOWTABLE_HOOK_PRIORITY, htonl(flowtable->priority))) ++ goto nla_put_failure; ++ ++ nest_devs = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK_DEVS); ++ if (!nest_devs) ++ goto nla_put_failure; ++ ++ for (i = 0; i < flowtable->ops_len; i++) { ++ if (flowtable->ops[i].dev && ++ nla_put_string(skb, NFTA_DEVICE_NAME, ++ flowtable->ops[i].dev->name)) ++ goto nla_put_failure; ++ } ++ nla_nest_end(skb, nest_devs); ++ nla_nest_end(skb, nest); ++ ++ nlmsg_end(skb, nlh); ++ return 0; ++ ++nla_put_failure: ++ nlmsg_trim(skb, nlh); ++ return -1; ++} ++ ++struct nft_flowtable_filter { ++ char *table; ++}; ++ ++static int nf_tables_dump_flowtable(struct sk_buff *skb, ++ struct netlink_callback *cb) ++{ ++ const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); ++ struct nft_flowtable_filter *filter = cb->data; ++ unsigned int idx = 0, s_idx = cb->args[0]; ++ struct net *net = sock_net(skb->sk); ++ int family = nfmsg->nfgen_family; ++ struct nft_flowtable *flowtable; ++ const struct nft_af_info *afi; ++ const struct nft_table *table; ++ ++ rcu_read_lock(); ++ cb->seq = net->nft.base_seq; ++ ++ list_for_each_entry_rcu(afi, &net->nft.af_info, list) { ++ if (family != NFPROTO_UNSPEC && family != afi->family) ++ continue; ++ ++ list_for_each_entry_rcu(table, &afi->tables, list) { ++ list_for_each_entry_rcu(flowtable, &table->flowtables, list) { ++ if (!nft_is_active(net, flowtable)) ++ goto cont; ++ if (idx < s_idx) ++ goto cont; ++ if (idx > s_idx) ++ memset(&cb->args[1], 0, ++ sizeof(cb->args) - sizeof(cb->args[0])); ++ if (filter && filter->table[0] && ++ strcmp(filter->table, table->name)) ++ goto cont; ++ ++ if (nf_tables_fill_flowtable_info(skb, net, NETLINK_CB(cb->skb).portid, ++ cb->nlh->nlmsg_seq, ++ NFT_MSG_NEWFLOWTABLE, ++ NLM_F_MULTI | NLM_F_APPEND, ++ afi->family, flowtable) < 0) ++ goto done; ++ ++ nl_dump_check_consistent(cb, nlmsg_hdr(skb)); ++cont: ++ idx++; ++ } ++ } ++ } ++done: ++ rcu_read_unlock(); ++ ++ cb->args[0] = idx; ++ return skb->len; ++} ++ ++static int nf_tables_dump_flowtable_done(struct netlink_callback *cb) ++{ ++ struct nft_flowtable_filter *filter = cb->data; ++ ++ if (!filter) ++ return 0; ++ ++ kfree(filter->table); ++ kfree(filter); ++ ++ return 0; ++} ++ ++static struct nft_flowtable_filter * ++nft_flowtable_filter_alloc(const struct nlattr * const nla[]) ++{ ++ struct nft_flowtable_filter *filter; ++ ++ filter = kzalloc(sizeof(*filter), GFP_KERNEL); ++ if (!filter) ++ return ERR_PTR(-ENOMEM); ++ ++ if (nla[NFTA_FLOWTABLE_TABLE]) { ++ filter->table = nla_strdup(nla[NFTA_FLOWTABLE_TABLE], ++ GFP_KERNEL); ++ if (!filter->table) { ++ kfree(filter); ++ return ERR_PTR(-ENOMEM); ++ } ++ } ++ return filter; ++} ++ ++static int nf_tables_getflowtable(struct net *net, struct sock *nlsk, ++ struct sk_buff *skb, ++ const struct nlmsghdr *nlh, ++ const struct nlattr * const nla[], ++ struct netlink_ext_ack *extack) ++{ ++ const struct nfgenmsg *nfmsg = nlmsg_data(nlh); ++ u8 genmask = nft_genmask_cur(net); ++ int family = nfmsg->nfgen_family; ++ struct nft_flowtable *flowtable; ++ const struct nft_af_info *afi; ++ const struct nft_table *table; ++ struct sk_buff *skb2; ++ int err; ++ ++ if (nlh->nlmsg_flags & NLM_F_DUMP) { ++ struct netlink_dump_control c = { ++ .dump = nf_tables_dump_flowtable, ++ .done = nf_tables_dump_flowtable_done, ++ }; ++ ++ if (nla[NFTA_FLOWTABLE_TABLE]) { ++ struct nft_flowtable_filter *filter; ++ ++ filter = nft_flowtable_filter_alloc(nla); ++ if (IS_ERR(filter)) ++ return -ENOMEM; ++ ++ c.data = filter; ++ } ++ return netlink_dump_start(nlsk, skb, nlh, &c); ++ } ++ ++ if (!nla[NFTA_FLOWTABLE_NAME]) ++ return -EINVAL; ++ ++ afi = nf_tables_afinfo_lookup(net, family, false); ++ if (IS_ERR(afi)) ++ return PTR_ERR(afi); ++ ++ table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(table); ++ ++ flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], ++ genmask); ++ if (IS_ERR(table)) ++ return PTR_ERR(flowtable); ++ ++ skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); ++ if (!skb2) ++ return -ENOMEM; ++ ++ err = nf_tables_fill_flowtable_info(skb2, net, NETLINK_CB(skb).portid, ++ nlh->nlmsg_seq, ++ NFT_MSG_NEWFLOWTABLE, 0, family, ++ flowtable); ++ if (err < 0) ++ goto err; ++ ++ return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid); ++err: ++ kfree_skb(skb2); ++ return err; ++} ++ ++static void nf_tables_flowtable_notify(struct nft_ctx *ctx, ++ struct nft_flowtable *flowtable, ++ int event) ++{ ++ struct sk_buff *skb; ++ int err; ++ ++ if (ctx->report && ++ !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES)) ++ return; ++ ++ skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); ++ if (skb == NULL) ++ goto err; ++ ++ err = nf_tables_fill_flowtable_info(skb, ctx->net, ctx->portid, ++ ctx->seq, event, 0, ++ ctx->afi->family, flowtable); ++ if (err < 0) { ++ kfree_skb(skb); ++ goto err; ++ } ++ ++ nfnetlink_send(skb, ctx->net, ctx->portid, NFNLGRP_NFTABLES, ++ ctx->report, GFP_KERNEL); ++ return; ++err: ++ nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS); ++} ++ ++static void nft_flowtable_destroy(void *ptr, void *arg) ++{ ++ kfree(ptr); ++} ++ ++static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable) ++{ ++ cancel_delayed_work_sync(&flowtable->data.gc_work); ++ kfree(flowtable->name); ++ rhashtable_free_and_destroy(&flowtable->data.rhashtable, ++ nft_flowtable_destroy, NULL); ++ module_put(flowtable->data.type->owner); ++} ++ + static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net, + u32 portid, u32 seq) + { +@@ -4797,6 +5440,49 @@ nla_put_failure: + return -EMSGSIZE; + } + ++static void nft_flowtable_event(unsigned long event, struct net_device *dev, ++ struct nft_flowtable *flowtable) ++{ ++ int i; ++ ++ for (i = 0; i < flowtable->ops_len; i++) { ++ if (flowtable->ops[i].dev != dev) ++ continue; ++ ++ nf_unregister_net_hook(dev_net(dev), &flowtable->ops[i]); ++ flowtable->ops[i].dev = NULL; ++ break; ++ } ++} ++ ++static int nf_tables_flowtable_event(struct notifier_block *this, ++ unsigned long event, void *ptr) ++{ ++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++ struct nft_flowtable *flowtable; ++ struct nft_table *table; ++ struct nft_af_info *afi; ++ ++ if (event != NETDEV_UNREGISTER) ++ return 0; ++ ++ nfnl_lock(NFNL_SUBSYS_NFTABLES); ++ list_for_each_entry(afi, &dev_net(dev)->nft.af_info, list) { ++ list_for_each_entry(table, &afi->tables, list) { ++ list_for_each_entry(flowtable, &table->flowtables, list) { ++ nft_flowtable_event(event, dev, flowtable); ++ } ++ } ++ } ++ nfnl_unlock(NFNL_SUBSYS_NFTABLES); ++ ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block nf_tables_flowtable_notifier = { ++ .notifier_call = nf_tables_flowtable_event, ++}; ++ + static void nf_tables_gen_notify(struct net *net, struct sk_buff *skb, + int event) + { +@@ -4949,6 +5635,21 @@ static const struct nfnl_callback nf_tab + .attr_count = NFTA_OBJ_MAX, + .policy = nft_obj_policy, + }, ++ [NFT_MSG_NEWFLOWTABLE] = { ++ .call_batch = nf_tables_newflowtable, ++ .attr_count = NFTA_FLOWTABLE_MAX, ++ .policy = nft_flowtable_policy, ++ }, ++ [NFT_MSG_GETFLOWTABLE] = { ++ .call = nf_tables_getflowtable, ++ .attr_count = NFTA_FLOWTABLE_MAX, ++ .policy = nft_flowtable_policy, ++ }, ++ [NFT_MSG_DELFLOWTABLE] = { ++ .call_batch = nf_tables_delflowtable, ++ .attr_count = NFTA_FLOWTABLE_MAX, ++ .policy = nft_flowtable_policy, ++ }, + }; + + static void nft_chain_commit_update(struct nft_trans *trans) +@@ -4994,6 +5695,9 @@ static void nf_tables_commit_release(str + case NFT_MSG_DELOBJ: + nft_obj_destroy(nft_trans_obj(trans)); + break; ++ case NFT_MSG_DELFLOWTABLE: ++ nf_tables_flowtable_destroy(nft_trans_flowtable(trans)); ++ break; + } + kfree(trans); + } +@@ -5111,6 +5815,21 @@ static int nf_tables_commit(struct net * + nf_tables_obj_notify(&trans->ctx, nft_trans_obj(trans), + NFT_MSG_DELOBJ); + break; ++ case NFT_MSG_NEWFLOWTABLE: ++ nft_clear(net, nft_trans_flowtable(trans)); ++ nf_tables_flowtable_notify(&trans->ctx, ++ nft_trans_flowtable(trans), ++ NFT_MSG_NEWFLOWTABLE); ++ nft_trans_destroy(trans); ++ break; ++ case NFT_MSG_DELFLOWTABLE: ++ list_del_rcu(&nft_trans_flowtable(trans)->list); ++ nf_tables_flowtable_notify(&trans->ctx, ++ nft_trans_flowtable(trans), ++ NFT_MSG_DELFLOWTABLE); ++ nft_unregister_flowtable_net_hooks(net, ++ nft_trans_flowtable(trans)); ++ break; + } + } + +@@ -5148,6 +5867,9 @@ static void nf_tables_abort_release(stru + case NFT_MSG_NEWOBJ: + nft_obj_destroy(nft_trans_obj(trans)); + break; ++ case NFT_MSG_NEWFLOWTABLE: ++ nf_tables_flowtable_destroy(nft_trans_flowtable(trans)); ++ break; + } + kfree(trans); + } +@@ -5237,6 +5959,17 @@ static int nf_tables_abort(struct net *n + nft_clear(trans->ctx.net, nft_trans_obj(trans)); + nft_trans_destroy(trans); + break; ++ case NFT_MSG_NEWFLOWTABLE: ++ trans->ctx.table->use--; ++ list_del_rcu(&nft_trans_flowtable(trans)->list); ++ nft_unregister_flowtable_net_hooks(net, ++ nft_trans_flowtable(trans)); ++ break; ++ case NFT_MSG_DELFLOWTABLE: ++ trans->ctx.table->use++; ++ nft_clear(trans->ctx.net, nft_trans_flowtable(trans)); ++ nft_trans_destroy(trans); ++ break; + } + } + +@@ -5787,6 +6520,7 @@ EXPORT_SYMBOL_GPL(__nft_release_basechai + /* Called by nft_unregister_afinfo() from __net_exit path, nfnl_lock is held. */ + static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi) + { ++ struct nft_flowtable *flowtable, *nf; + struct nft_table *table, *nt; + struct nft_chain *chain, *nc; + struct nft_object *obj, *ne; +@@ -5800,6 +6534,9 @@ static void __nft_release_afinfo(struct + list_for_each_entry_safe(table, nt, &afi->tables, list) { + list_for_each_entry(chain, &table->chains, list) + nf_tables_unregister_hook(net, table, chain); ++ list_for_each_entry(flowtable, &table->flowtables, list) ++ nf_unregister_net_hooks(net, flowtable->ops, ++ flowtable->ops_len); + /* No packets are walking on these chains anymore. */ + ctx.table = table; + list_for_each_entry(chain, &table->chains, list) { +@@ -5810,6 +6547,11 @@ static void __nft_release_afinfo(struct + nf_tables_rule_destroy(&ctx, rule); + } + } ++ list_for_each_entry_safe(flowtable, nf, &table->flowtables, list) { ++ list_del(&flowtable->list); ++ table->use--; ++ nf_tables_flowtable_destroy(flowtable); ++ } + list_for_each_entry_safe(set, ns, &table->sets, list) { + list_del(&set->list); + table->use--; +@@ -5853,6 +6595,8 @@ static int __init nf_tables_module_init( + if (err < 0) + goto err3; + ++ register_netdevice_notifier(&nf_tables_flowtable_notifier); ++ + pr_info("nf_tables: (c) 2007-2009 Patrick McHardy \n"); + return register_pernet_subsys(&nf_tables_net_ops); + err3: +@@ -5867,6 +6611,7 @@ static void __exit nf_tables_module_exit + { + unregister_pernet_subsys(&nf_tables_net_ops); + nfnetlink_subsys_unregister(&nf_tables_subsys); ++ unregister_netdevice_notifier(&nf_tables_flowtable_notifier); + rcu_barrier(); + nf_tables_core_module_exit(); + kfree(info); diff --git a/target/linux/generic/backport-4.14/322-netfilter-add-generic-flow-table-infrastructure.patch b/target/linux/generic/backport-4.14/322-netfilter-add-generic-flow-table-infrastructure.patch new file mode 100644 index 000000000..d811ef006 --- /dev/null +++ b/target/linux/generic/backport-4.14/322-netfilter-add-generic-flow-table-infrastructure.patch @@ -0,0 +1,586 @@ +From: Pablo Neira Ayuso +Date: Sun, 7 Jan 2018 01:04:11 +0100 +Subject: [PATCH] netfilter: add generic flow table infrastructure + +This patch defines the API to interact with flow tables, this allows to +add, delete and lookup for entries in the flow table. This also adds the +generic garbage code that removes entries that have expired, ie. no +traffic has been seen for a while. + +Users of the flow table infrastructure can delete entries via +flow_offload_dead(), which sets the dying bit, this signals the garbage +collector to release an entry from user context. + +Signed-off-by: Pablo Neira Ayuso +--- + create mode 100644 net/netfilter/nf_flow_table.c + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -1,7 +1,12 @@ + #ifndef _NF_FLOW_TABLE_H + #define _NF_FLOW_TABLE_H + ++#include ++#include ++#include + #include ++#include ++#include + + struct nf_flowtable; + +@@ -20,4 +25,93 @@ struct nf_flowtable { + struct delayed_work gc_work; + }; + ++enum flow_offload_tuple_dir { ++ FLOW_OFFLOAD_DIR_ORIGINAL, ++ FLOW_OFFLOAD_DIR_REPLY, ++ __FLOW_OFFLOAD_DIR_MAX = FLOW_OFFLOAD_DIR_REPLY, ++}; ++#define FLOW_OFFLOAD_DIR_MAX (__FLOW_OFFLOAD_DIR_MAX + 1) ++ ++struct flow_offload_tuple { ++ union { ++ struct in_addr src_v4; ++ struct in6_addr src_v6; ++ }; ++ union { ++ struct in_addr dst_v4; ++ struct in6_addr dst_v6; ++ }; ++ struct { ++ __be16 src_port; ++ __be16 dst_port; ++ }; ++ ++ int iifidx; ++ ++ u8 l3proto; ++ u8 l4proto; ++ u8 dir; ++ ++ int oifidx; ++ ++ struct dst_entry *dst_cache; ++}; ++ ++struct flow_offload_tuple_rhash { ++ struct rhash_head node; ++ struct flow_offload_tuple tuple; ++}; ++ ++#define FLOW_OFFLOAD_SNAT 0x1 ++#define FLOW_OFFLOAD_DNAT 0x2 ++#define FLOW_OFFLOAD_DYING 0x4 ++ ++struct flow_offload { ++ struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX]; ++ u32 flags; ++ union { ++ /* Your private driver data here. */ ++ u32 timeout; ++ }; ++}; ++ ++#define NF_FLOW_TIMEOUT (30 * HZ) ++ ++struct nf_flow_route { ++ struct { ++ struct dst_entry *dst; ++ int ifindex; ++ } tuple[FLOW_OFFLOAD_DIR_MAX]; ++}; ++ ++struct flow_offload *flow_offload_alloc(struct nf_conn *ct, ++ struct nf_flow_route *route); ++void flow_offload_free(struct flow_offload *flow); ++ ++int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow); ++void flow_offload_del(struct nf_flowtable *flow_table, struct flow_offload *flow); ++struct flow_offload_tuple_rhash *flow_offload_lookup(struct nf_flowtable *flow_table, ++ struct flow_offload_tuple *tuple); ++int nf_flow_table_iterate(struct nf_flowtable *flow_table, ++ void (*iter)(struct flow_offload *flow, void *data), ++ void *data); ++void nf_flow_offload_work_gc(struct work_struct *work); ++extern const struct rhashtable_params nf_flow_offload_rhash_params; ++ ++void flow_offload_dead(struct flow_offload *flow); ++ ++int nf_flow_snat_port(const struct flow_offload *flow, ++ struct sk_buff *skb, unsigned int thoff, ++ u8 protocol, enum flow_offload_tuple_dir dir); ++int nf_flow_dnat_port(const struct flow_offload *flow, ++ struct sk_buff *skb, unsigned int thoff, ++ u8 protocol, enum flow_offload_tuple_dir dir); ++ ++struct flow_ports { ++ __be16 source, dest; ++}; ++ ++#define MODULE_ALIAS_NF_FLOWTABLE(family) \ ++ MODULE_ALIAS("nf-flowtable-" __stringify(family)) ++ + #endif /* _FLOW_OFFLOAD_H */ +--- a/net/netfilter/Kconfig ++++ b/net/netfilter/Kconfig +@@ -661,6 +661,13 @@ endif # NF_TABLES_NETDEV + + endif # NF_TABLES + ++config NF_FLOW_TABLE ++ tristate "Netfilter flow table module" ++ help ++ This option adds the flow table core infrastructure. ++ ++ To compile it as a module, choose M here. ++ + config NETFILTER_XTABLES + tristate "Netfilter Xtables support (required for ip_tables)" + default m if NETFILTER_ADVANCED=n +--- a/net/netfilter/Makefile ++++ b/net/netfilter/Makefile +@@ -110,6 +110,9 @@ obj-$(CONFIG_NFT_FIB_NETDEV) += nft_fib_ + obj-$(CONFIG_NFT_DUP_NETDEV) += nft_dup_netdev.o + obj-$(CONFIG_NFT_FWD_NETDEV) += nft_fwd_netdev.o + ++# flow table infrastructure ++obj-$(CONFIG_NF_FLOW_TABLE) += nf_flow_table.o ++ + # generic X tables + obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o + +--- /dev/null ++++ b/net/netfilter/nf_flow_table.c +@@ -0,0 +1,429 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct flow_offload_entry { ++ struct flow_offload flow; ++ struct nf_conn *ct; ++ struct rcu_head rcu_head; ++}; ++ ++struct flow_offload * ++flow_offload_alloc(struct nf_conn *ct, struct nf_flow_route *route) ++{ ++ struct flow_offload_entry *entry; ++ struct flow_offload *flow; ++ ++ if (unlikely(nf_ct_is_dying(ct) || ++ !atomic_inc_not_zero(&ct->ct_general.use))) ++ return NULL; ++ ++ entry = kzalloc(sizeof(*entry), GFP_ATOMIC); ++ if (!entry) ++ goto err_ct_refcnt; ++ ++ flow = &entry->flow; ++ ++ if (!dst_hold_safe(route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst)) ++ goto err_dst_cache_original; ++ ++ if (!dst_hold_safe(route->tuple[FLOW_OFFLOAD_DIR_REPLY].dst)) ++ goto err_dst_cache_reply; ++ ++ entry->ct = ct; ++ ++ switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num) { ++ case NFPROTO_IPV4: ++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v4 = ++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.in; ++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v4 = ++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in; ++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v4 = ++ ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.in; ++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v4 = ++ ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.in; ++ break; ++ case NFPROTO_IPV6: ++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6 = ++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.in6; ++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6 = ++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in6; ++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6 = ++ ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.in6; ++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6 = ++ ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.in6; ++ break; ++ } ++ ++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.l3proto = ++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; ++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.l4proto = ++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; ++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.l3proto = ++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; ++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.l4proto = ++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; ++ ++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache = ++ route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst; ++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache = ++ route->tuple[FLOW_OFFLOAD_DIR_REPLY].dst; ++ ++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port = ++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.tcp.port; ++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_port = ++ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.tcp.port; ++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_port = ++ ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.tcp.port; ++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port = ++ ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port; ++ ++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dir = ++ FLOW_OFFLOAD_DIR_ORIGINAL; ++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dir = ++ FLOW_OFFLOAD_DIR_REPLY; ++ ++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.iifidx = ++ route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].ifindex; ++ flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.oifidx = ++ route->tuple[FLOW_OFFLOAD_DIR_REPLY].ifindex; ++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.iifidx = ++ route->tuple[FLOW_OFFLOAD_DIR_REPLY].ifindex; ++ flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.oifidx = ++ route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].ifindex; ++ ++ if (ct->status & IPS_SRC_NAT) ++ flow->flags |= FLOW_OFFLOAD_SNAT; ++ else if (ct->status & IPS_DST_NAT) ++ flow->flags |= FLOW_OFFLOAD_DNAT; ++ ++ return flow; ++ ++err_dst_cache_reply: ++ dst_release(route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst); ++err_dst_cache_original: ++ kfree(entry); ++err_ct_refcnt: ++ nf_ct_put(ct); ++ ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(flow_offload_alloc); ++ ++void flow_offload_free(struct flow_offload *flow) ++{ ++ struct flow_offload_entry *e; ++ ++ dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache); ++ dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache); ++ e = container_of(flow, struct flow_offload_entry, flow); ++ kfree(e); ++} ++EXPORT_SYMBOL_GPL(flow_offload_free); ++ ++void flow_offload_dead(struct flow_offload *flow) ++{ ++ flow->flags |= FLOW_OFFLOAD_DYING; ++} ++EXPORT_SYMBOL_GPL(flow_offload_dead); ++ ++int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) ++{ ++ flow->timeout = (u32)jiffies; ++ ++ rhashtable_insert_fast(&flow_table->rhashtable, ++ &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, ++ *flow_table->type->params); ++ rhashtable_insert_fast(&flow_table->rhashtable, ++ &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, ++ *flow_table->type->params); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(flow_offload_add); ++ ++void flow_offload_del(struct nf_flowtable *flow_table, ++ struct flow_offload *flow) ++{ ++ struct flow_offload_entry *e; ++ ++ rhashtable_remove_fast(&flow_table->rhashtable, ++ &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, ++ *flow_table->type->params); ++ rhashtable_remove_fast(&flow_table->rhashtable, ++ &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, ++ *flow_table->type->params); ++ ++ e = container_of(flow, struct flow_offload_entry, flow); ++ kfree_rcu(e, rcu_head); ++} ++EXPORT_SYMBOL_GPL(flow_offload_del); ++ ++struct flow_offload_tuple_rhash * ++flow_offload_lookup(struct nf_flowtable *flow_table, ++ struct flow_offload_tuple *tuple) ++{ ++ return rhashtable_lookup_fast(&flow_table->rhashtable, tuple, ++ *flow_table->type->params); ++} ++EXPORT_SYMBOL_GPL(flow_offload_lookup); ++ ++static void nf_flow_release_ct(const struct flow_offload *flow) ++{ ++ struct flow_offload_entry *e; ++ ++ e = container_of(flow, struct flow_offload_entry, flow); ++ nf_ct_delete(e->ct, 0, 0); ++ nf_ct_put(e->ct); ++} ++ ++int nf_flow_table_iterate(struct nf_flowtable *flow_table, ++ void (*iter)(struct flow_offload *flow, void *data), ++ void *data) ++{ ++ struct flow_offload_tuple_rhash *tuplehash; ++ struct rhashtable_iter hti; ++ struct flow_offload *flow; ++ int err; ++ ++ err = rhashtable_walk_init(&flow_table->rhashtable, &hti, GFP_KERNEL); ++ if (err) ++ return err; ++ ++ rhashtable_walk_start(&hti); ++ ++ while ((tuplehash = rhashtable_walk_next(&hti))) { ++ if (IS_ERR(tuplehash)) { ++ err = PTR_ERR(tuplehash); ++ if (err != -EAGAIN) ++ goto out; ++ ++ continue; ++ } ++ if (tuplehash->tuple.dir) ++ continue; ++ ++ flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); ++ ++ iter(flow, data); ++ } ++out: ++ rhashtable_walk_stop(&hti); ++ rhashtable_walk_exit(&hti); ++ ++ return err; ++} ++EXPORT_SYMBOL_GPL(nf_flow_table_iterate); ++ ++static inline bool nf_flow_has_expired(const struct flow_offload *flow) ++{ ++ return (__s32)(flow->timeout - (u32)jiffies) <= 0; ++} ++ ++static inline bool nf_flow_is_dying(const struct flow_offload *flow) ++{ ++ return flow->flags & FLOW_OFFLOAD_DYING; ++} ++ ++void nf_flow_offload_work_gc(struct work_struct *work) ++{ ++ struct flow_offload_tuple_rhash *tuplehash; ++ struct nf_flowtable *flow_table; ++ struct rhashtable_iter hti; ++ struct flow_offload *flow; ++ int err; ++ ++ flow_table = container_of(work, struct nf_flowtable, gc_work.work); ++ ++ err = rhashtable_walk_init(&flow_table->rhashtable, &hti, GFP_KERNEL); ++ if (err) ++ goto schedule; ++ ++ rhashtable_walk_start(&hti); ++ ++ while ((tuplehash = rhashtable_walk_next(&hti))) { ++ if (IS_ERR(tuplehash)) { ++ err = PTR_ERR(tuplehash); ++ if (err != -EAGAIN) ++ goto out; ++ ++ continue; ++ } ++ if (tuplehash->tuple.dir) ++ continue; ++ ++ flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); ++ ++ if (nf_flow_has_expired(flow) || ++ nf_flow_is_dying(flow)) { ++ flow_offload_del(flow_table, flow); ++ nf_flow_release_ct(flow); ++ } ++ } ++out: ++ rhashtable_walk_stop(&hti); ++ rhashtable_walk_exit(&hti); ++schedule: ++ queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ); ++} ++EXPORT_SYMBOL_GPL(nf_flow_offload_work_gc); ++ ++static u32 flow_offload_hash(const void *data, u32 len, u32 seed) ++{ ++ const struct flow_offload_tuple *tuple = data; ++ ++ return jhash(tuple, offsetof(struct flow_offload_tuple, dir), seed); ++} ++ ++static u32 flow_offload_hash_obj(const void *data, u32 len, u32 seed) ++{ ++ const struct flow_offload_tuple_rhash *tuplehash = data; ++ ++ return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, dir), seed); ++} ++ ++static int flow_offload_hash_cmp(struct rhashtable_compare_arg *arg, ++ const void *ptr) ++{ ++ const struct flow_offload_tuple *tuple = arg->key; ++ const struct flow_offload_tuple_rhash *x = ptr; ++ ++ if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, dir))) ++ return 1; ++ ++ return 0; ++} ++ ++const struct rhashtable_params nf_flow_offload_rhash_params = { ++ .head_offset = offsetof(struct flow_offload_tuple_rhash, node), ++ .hashfn = flow_offload_hash, ++ .obj_hashfn = flow_offload_hash_obj, ++ .obj_cmpfn = flow_offload_hash_cmp, ++ .automatic_shrinking = true, ++}; ++EXPORT_SYMBOL_GPL(nf_flow_offload_rhash_params); ++ ++static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff, ++ __be16 port, __be16 new_port) ++{ ++ struct tcphdr *tcph; ++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || ++ skb_try_make_writable(skb, thoff + sizeof(*tcph))) ++ return -1; ++ ++ tcph = (void *)(skb_network_header(skb) + thoff); ++ inet_proto_csum_replace2(&tcph->check, skb, port, new_port, true); ++ ++ return 0; ++} ++ ++static int nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff, ++ __be16 port, __be16 new_port) ++{ ++ struct udphdr *udph; ++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || ++ skb_try_make_writable(skb, thoff + sizeof(*udph))) ++ return -1; ++ ++ udph = (void *)(skb_network_header(skb) + thoff); ++ if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { ++ inet_proto_csum_replace2(&udph->check, skb, port, ++ new_port, true); ++ if (!udph->check) ++ udph->check = CSUM_MANGLED_0; ++ } ++ ++ return 0; ++} ++ ++static int nf_flow_nat_port(struct sk_buff *skb, unsigned int thoff, ++ u8 protocol, __be16 port, __be16 new_port) ++{ ++ switch (protocol) { ++ case IPPROTO_TCP: ++ if (nf_flow_nat_port_tcp(skb, thoff, port, new_port) < 0) ++ return NF_DROP; ++ break; ++ case IPPROTO_UDP: ++ if (nf_flow_nat_port_udp(skb, thoff, port, new_port) < 0) ++ return NF_DROP; ++ break; ++ } ++ ++ return 0; ++} ++ ++int nf_flow_snat_port(const struct flow_offload *flow, ++ struct sk_buff *skb, unsigned int thoff, ++ u8 protocol, enum flow_offload_tuple_dir dir) ++{ ++ struct flow_ports *hdr; ++ __be16 port, new_port; ++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*hdr)) || ++ skb_try_make_writable(skb, thoff + sizeof(*hdr))) ++ return -1; ++ ++ hdr = (void *)(skb_network_header(skb) + thoff); ++ ++ switch (dir) { ++ case FLOW_OFFLOAD_DIR_ORIGINAL: ++ port = hdr->source; ++ new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port; ++ hdr->source = new_port; ++ break; ++ case FLOW_OFFLOAD_DIR_REPLY: ++ port = hdr->dest; ++ new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port; ++ hdr->dest = new_port; ++ break; ++ default: ++ return -1; ++ } ++ ++ return nf_flow_nat_port(skb, thoff, protocol, port, new_port); ++} ++EXPORT_SYMBOL_GPL(nf_flow_snat_port); ++ ++int nf_flow_dnat_port(const struct flow_offload *flow, ++ struct sk_buff *skb, unsigned int thoff, ++ u8 protocol, enum flow_offload_tuple_dir dir) ++{ ++ struct flow_ports *hdr; ++ __be16 port, new_port; ++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*hdr)) || ++ skb_try_make_writable(skb, thoff + sizeof(*hdr))) ++ return -1; ++ ++ hdr = (void *)(skb_network_header(skb) + thoff); ++ ++ switch (dir) { ++ case FLOW_OFFLOAD_DIR_ORIGINAL: ++ port = hdr->dest; ++ new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_port; ++ hdr->dest = new_port; ++ break; ++ case FLOW_OFFLOAD_DIR_REPLY: ++ port = hdr->source; ++ new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_port; ++ hdr->source = new_port; ++ break; ++ default: ++ return -1; ++ } ++ ++ return nf_flow_nat_port(skb, thoff, protocol, port, new_port); ++} ++EXPORT_SYMBOL_GPL(nf_flow_dnat_port); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Pablo Neira Ayuso "); diff --git a/target/linux/generic/backport-4.14/323-netfilter-flow-table-support-for-IPv4.patch b/target/linux/generic/backport-4.14/323-netfilter-flow-table-support-for-IPv4.patch new file mode 100644 index 000000000..6f3617160 --- /dev/null +++ b/target/linux/generic/backport-4.14/323-netfilter-flow-table-support-for-IPv4.patch @@ -0,0 +1,334 @@ +From: Pablo Neira Ayuso +Date: Sun, 7 Jan 2018 01:04:15 +0100 +Subject: [PATCH] netfilter: flow table support for IPv4 + +This patch adds the IPv4 flow table type, that implements the datapath +flow table to forward IPv4 traffic. Rationale is: + +1) Look up for the packet in the flow table, from the ingress hook. +2) If there's a hit, decrement ttl and pass it on to the neighbour layer + for transmission. +3) If there's a miss, packet is passed up to the classic forwarding + path. + +This patch also supports layer 3 source and destination NAT. + +Signed-off-by: Pablo Neira Ayuso +--- + create mode 100644 net/ipv4/netfilter/nf_flow_table_ipv4.c + +--- a/net/ipv4/netfilter/Kconfig ++++ b/net/ipv4/netfilter/Kconfig +@@ -77,6 +77,14 @@ config NF_TABLES_ARP + + endif # NF_TABLES + ++config NF_FLOW_TABLE_IPV4 ++ select NF_FLOW_TABLE ++ tristate "Netfilter flow table IPv4 module" ++ help ++ This option adds the flow table IPv4 support. ++ ++ To compile it as a module, choose M here. ++ + config NF_DUP_IPV4 + tristate "Netfilter IPv4 packet duplication to alternate destination" + depends on !NF_CONNTRACK || NF_CONNTRACK +--- a/net/ipv4/netfilter/Makefile ++++ b/net/ipv4/netfilter/Makefile +@@ -43,6 +43,9 @@ obj-$(CONFIG_NFT_REDIR_IPV4) += nft_redi + obj-$(CONFIG_NFT_DUP_IPV4) += nft_dup_ipv4.o + obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o + ++# flow table support ++obj-$(CONFIG_NF_FLOW_TABLE_IPV4) += nf_flow_table_ipv4.o ++ + # generic IP tables + obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o + +--- /dev/null ++++ b/net/ipv4/netfilter/nf_flow_table_ipv4.c +@@ -0,0 +1,283 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++/* For layer 4 checksum field offset. */ ++#include ++#include ++ ++static int nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff, ++ __be32 addr, __be32 new_addr) ++{ ++ struct tcphdr *tcph; ++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || ++ skb_try_make_writable(skb, thoff + sizeof(*tcph))) ++ return -1; ++ ++ tcph = (void *)(skb_network_header(skb) + thoff); ++ inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr, true); ++ ++ return 0; ++} ++ ++static int nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff, ++ __be32 addr, __be32 new_addr) ++{ ++ struct udphdr *udph; ++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || ++ skb_try_make_writable(skb, thoff + sizeof(*udph))) ++ return -1; ++ ++ udph = (void *)(skb_network_header(skb) + thoff); ++ if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { ++ inet_proto_csum_replace4(&udph->check, skb, addr, ++ new_addr, true); ++ if (!udph->check) ++ udph->check = CSUM_MANGLED_0; ++ } ++ ++ return 0; ++} ++ ++static int nf_flow_nat_ip_l4proto(struct sk_buff *skb, struct iphdr *iph, ++ unsigned int thoff, __be32 addr, ++ __be32 new_addr) ++{ ++ switch (iph->protocol) { ++ case IPPROTO_TCP: ++ if (nf_flow_nat_ip_tcp(skb, thoff, addr, new_addr) < 0) ++ return NF_DROP; ++ break; ++ case IPPROTO_UDP: ++ if (nf_flow_nat_ip_udp(skb, thoff, addr, new_addr) < 0) ++ return NF_DROP; ++ break; ++ } ++ ++ return 0; ++} ++ ++static int nf_flow_snat_ip(const struct flow_offload *flow, struct sk_buff *skb, ++ struct iphdr *iph, unsigned int thoff, ++ enum flow_offload_tuple_dir dir) ++{ ++ __be32 addr, new_addr; ++ ++ switch (dir) { ++ case FLOW_OFFLOAD_DIR_ORIGINAL: ++ addr = iph->saddr; ++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v4.s_addr; ++ iph->saddr = new_addr; ++ break; ++ case FLOW_OFFLOAD_DIR_REPLY: ++ addr = iph->daddr; ++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v4.s_addr; ++ iph->daddr = new_addr; ++ break; ++ default: ++ return -1; ++ } ++ csum_replace4(&iph->check, addr, new_addr); ++ ++ return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); ++} ++ ++static int nf_flow_dnat_ip(const struct flow_offload *flow, struct sk_buff *skb, ++ struct iphdr *iph, unsigned int thoff, ++ enum flow_offload_tuple_dir dir) ++{ ++ __be32 addr, new_addr; ++ ++ switch (dir) { ++ case FLOW_OFFLOAD_DIR_ORIGINAL: ++ addr = iph->daddr; ++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v4.s_addr; ++ iph->daddr = new_addr; ++ break; ++ case FLOW_OFFLOAD_DIR_REPLY: ++ addr = iph->saddr; ++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v4.s_addr; ++ iph->saddr = new_addr; ++ break; ++ default: ++ return -1; ++ } ++ ++ return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); ++} ++ ++static int nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb, ++ enum flow_offload_tuple_dir dir) ++{ ++ struct iphdr *iph = ip_hdr(skb); ++ unsigned int thoff = iph->ihl * 4; ++ ++ if (flow->flags & FLOW_OFFLOAD_SNAT && ++ (nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 || ++ nf_flow_snat_ip(flow, skb, iph, thoff, dir) < 0)) ++ return -1; ++ if (flow->flags & FLOW_OFFLOAD_DNAT && ++ (nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir) < 0 || ++ nf_flow_dnat_ip(flow, skb, iph, thoff, dir) < 0)) ++ return -1; ++ ++ return 0; ++} ++ ++static bool ip_has_options(unsigned int thoff) ++{ ++ return thoff != sizeof(struct iphdr); ++} ++ ++static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev, ++ struct flow_offload_tuple *tuple) ++{ ++ struct flow_ports *ports; ++ unsigned int thoff; ++ struct iphdr *iph; ++ ++ if (!pskb_may_pull(skb, sizeof(*iph))) ++ return -1; ++ ++ iph = ip_hdr(skb); ++ thoff = iph->ihl * 4; ++ ++ if (ip_is_fragment(iph) || ++ unlikely(ip_has_options(thoff))) ++ return -1; ++ ++ if (iph->protocol != IPPROTO_TCP && ++ iph->protocol != IPPROTO_UDP) ++ return -1; ++ ++ thoff = iph->ihl * 4; ++ if (!pskb_may_pull(skb, thoff + sizeof(*ports))) ++ return -1; ++ ++ ports = (struct flow_ports *)(skb_network_header(skb) + thoff); ++ ++ tuple->src_v4.s_addr = iph->saddr; ++ tuple->dst_v4.s_addr = iph->daddr; ++ tuple->src_port = ports->source; ++ tuple->dst_port = ports->dest; ++ tuple->l3proto = AF_INET; ++ tuple->l4proto = iph->protocol; ++ tuple->iifidx = dev->ifindex; ++ ++ return 0; ++} ++ ++/* Based on ip_exceeds_mtu(). */ ++static bool __nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) ++{ ++ if (skb->len <= mtu) ++ return false; ++ ++ if ((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) ++ return false; ++ ++ if (skb_is_gso(skb) && skb_gso_validate_mtu(skb, mtu)) ++ return false; ++ ++ return true; ++} ++ ++static bool nf_flow_exceeds_mtu(struct sk_buff *skb, const struct rtable *rt) ++{ ++ u32 mtu; ++ ++ mtu = ip_dst_mtu_maybe_forward(&rt->dst, true); ++ if (__nf_flow_exceeds_mtu(skb, mtu)) ++ return true; ++ ++ return false; ++} ++ ++static unsigned int ++nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++{ ++ struct flow_offload_tuple_rhash *tuplehash; ++ struct nf_flowtable *flow_table = priv; ++ struct flow_offload_tuple tuple = {}; ++ enum flow_offload_tuple_dir dir; ++ struct flow_offload *flow; ++ struct net_device *outdev; ++ const struct rtable *rt; ++ struct iphdr *iph; ++ __be32 nexthop; ++ ++ if (skb->protocol != htons(ETH_P_IP)) ++ return NF_ACCEPT; ++ ++ if (nf_flow_tuple_ip(skb, state->in, &tuple) < 0) ++ return NF_ACCEPT; ++ ++ tuplehash = flow_offload_lookup(flow_table, &tuple); ++ if (tuplehash == NULL) ++ return NF_ACCEPT; ++ ++ outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.oifidx); ++ if (!outdev) ++ return NF_ACCEPT; ++ ++ dir = tuplehash->tuple.dir; ++ flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); ++ ++ rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache; ++ if (unlikely(nf_flow_exceeds_mtu(skb, rt))) ++ return NF_ACCEPT; ++ ++ if (skb_try_make_writable(skb, sizeof(*iph))) ++ return NF_DROP; ++ ++ if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) && ++ nf_flow_nat_ip(flow, skb, dir) < 0) ++ return NF_DROP; ++ ++ flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; ++ iph = ip_hdr(skb); ++ ip_decrease_ttl(iph); ++ ++ skb->dev = outdev; ++ nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); ++ neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb); ++ ++ return NF_STOLEN; ++} ++ ++static struct nf_flowtable_type flowtable_ipv4 = { ++ .family = NFPROTO_IPV4, ++ .params = &nf_flow_offload_rhash_params, ++ .gc = nf_flow_offload_work_gc, ++ .hook = nf_flow_offload_ip_hook, ++ .owner = THIS_MODULE, ++}; ++ ++static int __init nf_flow_ipv4_module_init(void) ++{ ++ nft_register_flowtable_type(&flowtable_ipv4); ++ ++ return 0; ++} ++ ++static void __exit nf_flow_ipv4_module_exit(void) ++{ ++ nft_unregister_flowtable_type(&flowtable_ipv4); ++} ++ ++module_init(nf_flow_ipv4_module_init); ++module_exit(nf_flow_ipv4_module_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Pablo Neira Ayuso "); ++MODULE_ALIAS_NF_FLOWTABLE(AF_INET); diff --git a/target/linux/generic/backport-4.14/324-netfilter-flow-table-support-for-IPv6.patch b/target/linux/generic/backport-4.14/324-netfilter-flow-table-support-for-IPv6.patch new file mode 100644 index 000000000..a5bbac44f --- /dev/null +++ b/target/linux/generic/backport-4.14/324-netfilter-flow-table-support-for-IPv6.patch @@ -0,0 +1,354 @@ +From: Pablo Neira Ayuso +Date: Sun, 7 Jan 2018 01:04:19 +0100 +Subject: [PATCH] netfilter: flow table support for IPv6 + +This patch adds the IPv6 flow table type, that implements the datapath +flow table to forward IPv6 traffic. + +This patch exports ip6_dst_mtu_forward() that is required to check for +mtu to pass up packets that need PMTUD handling to the classic +forwarding path. + +Signed-off-by: Pablo Neira Ayuso +--- + create mode 100644 net/ipv6/netfilter/nf_flow_table_ipv6.c + +--- a/include/net/ipv6.h ++++ b/include/net/ipv6.h +@@ -913,6 +913,8 @@ static inline struct sk_buff *ip6_finish + &inet6_sk(sk)->cork); + } + ++unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst); ++ + int ip6_dst_lookup(struct net *net, struct sock *sk, struct dst_entry **dst, + struct flowi6 *fl6); + struct dst_entry *ip6_dst_lookup_flow(const struct sock *sk, struct flowi6 *fl6, +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -370,7 +370,7 @@ static inline int ip6_forward_finish(str + return dst_output(net, sk, skb); + } + +-static unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) ++unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) + { + unsigned int mtu; + struct inet6_dev *idev; +@@ -390,6 +390,7 @@ static unsigned int ip6_dst_mtu_forward( + + return mtu; + } ++EXPORT_SYMBOL_GPL(ip6_dst_mtu_forward); + + static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu) + { +--- a/net/ipv6/netfilter/Kconfig ++++ b/net/ipv6/netfilter/Kconfig +@@ -71,6 +71,14 @@ config NFT_FIB_IPV6 + endif # NF_TABLES_IPV6 + endif # NF_TABLES + ++config NF_FLOW_TABLE_IPV6 ++ select NF_FLOW_TABLE ++ tristate "Netfilter flow table IPv6 module" ++ help ++ This option adds the flow table IPv6 support. ++ ++ To compile it as a module, choose M here. ++ + config NF_DUP_IPV6 + tristate "Netfilter IPv6 packet duplication to alternate destination" + depends on !NF_CONNTRACK || NF_CONNTRACK +--- a/net/ipv6/netfilter/Makefile ++++ b/net/ipv6/netfilter/Makefile +@@ -45,6 +45,9 @@ obj-$(CONFIG_NFT_REDIR_IPV6) += nft_redi + obj-$(CONFIG_NFT_DUP_IPV6) += nft_dup_ipv6.o + obj-$(CONFIG_NFT_FIB_IPV6) += nft_fib_ipv6.o + ++# flow table support ++obj-$(CONFIG_NF_FLOW_TABLE_IPV6) += nf_flow_table_ipv6.o ++ + # matches + obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o + obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o +--- /dev/null ++++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c +@@ -0,0 +1,277 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++/* For layer 4 checksum field offset. */ ++#include ++#include ++ ++static int nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff, ++ struct in6_addr *addr, ++ struct in6_addr *new_addr) ++{ ++ struct tcphdr *tcph; ++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || ++ skb_try_make_writable(skb, thoff + sizeof(*tcph))) ++ return -1; ++ ++ tcph = (void *)(skb_network_header(skb) + thoff); ++ inet_proto_csum_replace16(&tcph->check, skb, addr->s6_addr32, ++ new_addr->s6_addr32, true); ++ ++ return 0; ++} ++ ++static int nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff, ++ struct in6_addr *addr, ++ struct in6_addr *new_addr) ++{ ++ struct udphdr *udph; ++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || ++ skb_try_make_writable(skb, thoff + sizeof(*udph))) ++ return -1; ++ ++ udph = (void *)(skb_network_header(skb) + thoff); ++ if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { ++ inet_proto_csum_replace16(&udph->check, skb, addr->s6_addr32, ++ new_addr->s6_addr32, true); ++ if (!udph->check) ++ udph->check = CSUM_MANGLED_0; ++ } ++ ++ return 0; ++} ++ ++static int nf_flow_nat_ipv6_l4proto(struct sk_buff *skb, struct ipv6hdr *ip6h, ++ unsigned int thoff, struct in6_addr *addr, ++ struct in6_addr *new_addr) ++{ ++ switch (ip6h->nexthdr) { ++ case IPPROTO_TCP: ++ if (nf_flow_nat_ipv6_tcp(skb, thoff, addr, new_addr) < 0) ++ return NF_DROP; ++ break; ++ case IPPROTO_UDP: ++ if (nf_flow_nat_ipv6_udp(skb, thoff, addr, new_addr) < 0) ++ return NF_DROP; ++ break; ++ } ++ ++ return 0; ++} ++ ++static int nf_flow_snat_ipv6(const struct flow_offload *flow, ++ struct sk_buff *skb, struct ipv6hdr *ip6h, ++ unsigned int thoff, ++ enum flow_offload_tuple_dir dir) ++{ ++ struct in6_addr addr, new_addr; ++ ++ switch (dir) { ++ case FLOW_OFFLOAD_DIR_ORIGINAL: ++ addr = ip6h->saddr; ++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6; ++ ip6h->saddr = new_addr; ++ break; ++ case FLOW_OFFLOAD_DIR_REPLY: ++ addr = ip6h->daddr; ++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6; ++ ip6h->daddr = new_addr; ++ break; ++ default: ++ return -1; ++ } ++ ++ return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); ++} ++ ++static int nf_flow_dnat_ipv6(const struct flow_offload *flow, ++ struct sk_buff *skb, struct ipv6hdr *ip6h, ++ unsigned int thoff, ++ enum flow_offload_tuple_dir dir) ++{ ++ struct in6_addr addr, new_addr; ++ ++ switch (dir) { ++ case FLOW_OFFLOAD_DIR_ORIGINAL: ++ addr = ip6h->daddr; ++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6; ++ ip6h->daddr = new_addr; ++ break; ++ case FLOW_OFFLOAD_DIR_REPLY: ++ addr = ip6h->saddr; ++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6; ++ ip6h->saddr = new_addr; ++ break; ++ default: ++ return -1; ++ } ++ ++ return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); ++} ++ ++static int nf_flow_nat_ipv6(const struct flow_offload *flow, ++ struct sk_buff *skb, ++ enum flow_offload_tuple_dir dir) ++{ ++ struct ipv6hdr *ip6h = ipv6_hdr(skb); ++ unsigned int thoff = sizeof(*ip6h); ++ ++ if (flow->flags & FLOW_OFFLOAD_SNAT && ++ (nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || ++ nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) ++ return -1; ++ if (flow->flags & FLOW_OFFLOAD_DNAT && ++ (nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || ++ nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) ++ return -1; ++ ++ return 0; ++} ++ ++static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev, ++ struct flow_offload_tuple *tuple) ++{ ++ struct flow_ports *ports; ++ struct ipv6hdr *ip6h; ++ unsigned int thoff; ++ ++ if (!pskb_may_pull(skb, sizeof(*ip6h))) ++ return -1; ++ ++ ip6h = ipv6_hdr(skb); ++ ++ if (ip6h->nexthdr != IPPROTO_TCP && ++ ip6h->nexthdr != IPPROTO_UDP) ++ return -1; ++ ++ thoff = sizeof(*ip6h); ++ if (!pskb_may_pull(skb, thoff + sizeof(*ports))) ++ return -1; ++ ++ ports = (struct flow_ports *)(skb_network_header(skb) + thoff); ++ ++ tuple->src_v6 = ip6h->saddr; ++ tuple->dst_v6 = ip6h->daddr; ++ tuple->src_port = ports->source; ++ tuple->dst_port = ports->dest; ++ tuple->l3proto = AF_INET6; ++ tuple->l4proto = ip6h->nexthdr; ++ tuple->iifidx = dev->ifindex; ++ ++ return 0; ++} ++ ++/* Based on ip_exceeds_mtu(). */ ++static bool __nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) ++{ ++ if (skb->len <= mtu) ++ return false; ++ ++ if (skb_is_gso(skb) && skb_gso_validate_mtu(skb, mtu)) ++ return false; ++ ++ return true; ++} ++ ++static bool nf_flow_exceeds_mtu(struct sk_buff *skb, const struct rt6_info *rt) ++{ ++ u32 mtu; ++ ++ mtu = ip6_dst_mtu_forward(&rt->dst); ++ if (__nf_flow_exceeds_mtu(skb, mtu)) ++ return true; ++ ++ return false; ++} ++ ++static unsigned int ++nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++{ ++ struct flow_offload_tuple_rhash *tuplehash; ++ struct nf_flowtable *flow_table = priv; ++ struct flow_offload_tuple tuple = {}; ++ enum flow_offload_tuple_dir dir; ++ struct flow_offload *flow; ++ struct net_device *outdev; ++ struct in6_addr *nexthop; ++ struct ipv6hdr *ip6h; ++ struct rt6_info *rt; ++ ++ if (skb->protocol != htons(ETH_P_IPV6)) ++ return NF_ACCEPT; ++ ++ if (nf_flow_tuple_ipv6(skb, state->in, &tuple) < 0) ++ return NF_ACCEPT; ++ ++ tuplehash = flow_offload_lookup(flow_table, &tuple); ++ if (tuplehash == NULL) ++ return NF_ACCEPT; ++ ++ outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.oifidx); ++ if (!outdev) ++ return NF_ACCEPT; ++ ++ dir = tuplehash->tuple.dir; ++ flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); ++ ++ rt = (struct rt6_info *)flow->tuplehash[dir].tuple.dst_cache; ++ if (unlikely(nf_flow_exceeds_mtu(skb, rt))) ++ return NF_ACCEPT; ++ ++ if (skb_try_make_writable(skb, sizeof(*ip6h))) ++ return NF_DROP; ++ ++ if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) && ++ nf_flow_nat_ipv6(flow, skb, dir) < 0) ++ return NF_DROP; ++ ++ flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; ++ ip6h = ipv6_hdr(skb); ++ ip6h->hop_limit--; ++ ++ skb->dev = outdev; ++ nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); ++ neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb); ++ ++ return NF_STOLEN; ++} ++ ++static struct nf_flowtable_type flowtable_ipv6 = { ++ .family = NFPROTO_IPV6, ++ .params = &nf_flow_offload_rhash_params, ++ .gc = nf_flow_offload_work_gc, ++ .hook = nf_flow_offload_ipv6_hook, ++ .owner = THIS_MODULE, ++}; ++ ++static int __init nf_flow_ipv6_module_init(void) ++{ ++ nft_register_flowtable_type(&flowtable_ipv6); ++ ++ return 0; ++} ++ ++static void __exit nf_flow_ipv6_module_exit(void) ++{ ++ nft_unregister_flowtable_type(&flowtable_ipv6); ++} ++ ++module_init(nf_flow_ipv6_module_init); ++module_exit(nf_flow_ipv6_module_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Pablo Neira Ayuso "); ++MODULE_ALIAS_NF_FLOWTABLE(AF_INET6); diff --git a/target/linux/generic/backport-4.14/325-netfilter-flow-table-support-for-the-mixed-IPv4-IPv6.patch b/target/linux/generic/backport-4.14/325-netfilter-flow-table-support-for-the-mixed-IPv4-IPv6.patch new file mode 100644 index 000000000..9fcb1be98 --- /dev/null +++ b/target/linux/generic/backport-4.14/325-netfilter-flow-table-support-for-the-mixed-IPv4-IPv6.patch @@ -0,0 +1,141 @@ +From: Pablo Neira Ayuso +Date: Sun, 7 Jan 2018 01:04:22 +0100 +Subject: [PATCH] netfilter: flow table support for the mixed IPv4/IPv6 family + +This patch adds the IPv6 flow table type, that implements the datapath +flow table to forward IPv6 traffic. + +Signed-off-by: Pablo Neira Ayuso +--- + create mode 100644 net/netfilter/nf_flow_table_inet.c + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -111,6 +111,11 @@ struct flow_ports { + __be16 source, dest; + }; + ++unsigned int nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state); ++unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state); ++ + #define MODULE_ALIAS_NF_FLOWTABLE(family) \ + MODULE_ALIAS("nf-flowtable-" __stringify(family)) + +--- a/net/ipv4/netfilter/nf_flow_table_ipv4.c ++++ b/net/ipv4/netfilter/nf_flow_table_ipv4.c +@@ -202,7 +202,7 @@ static bool nf_flow_exceeds_mtu(struct s + return false; + } + +-static unsigned int ++unsigned int + nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, + const struct nf_hook_state *state) + { +@@ -254,6 +254,7 @@ nf_flow_offload_ip_hook(void *priv, stru + + return NF_STOLEN; + } ++EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook); + + static struct nf_flowtable_type flowtable_ipv4 = { + .family = NFPROTO_IPV4, +--- a/net/ipv6/netfilter/nf_flow_table_ipv6.c ++++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c +@@ -196,7 +196,7 @@ static bool nf_flow_exceeds_mtu(struct s + return false; + } + +-static unsigned int ++unsigned int + nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, + const struct nf_hook_state *state) + { +@@ -248,6 +248,7 @@ nf_flow_offload_ipv6_hook(void *priv, st + + return NF_STOLEN; + } ++EXPORT_SYMBOL_GPL(nf_flow_offload_ipv6_hook); + + static struct nf_flowtable_type flowtable_ipv6 = { + .family = NFPROTO_IPV6, +--- a/net/netfilter/Kconfig ++++ b/net/netfilter/Kconfig +@@ -661,6 +661,14 @@ endif # NF_TABLES_NETDEV + + endif # NF_TABLES + ++config NF_FLOW_TABLE_INET ++ select NF_FLOW_TABLE ++ tristate "Netfilter flow table mixed IPv4/IPv6 module" ++ help ++ This option adds the flow table mixed IPv4/IPv6 support. ++ ++ To compile it as a module, choose M here. ++ + config NF_FLOW_TABLE + tristate "Netfilter flow table module" + help +--- a/net/netfilter/Makefile ++++ b/net/netfilter/Makefile +@@ -112,6 +112,7 @@ obj-$(CONFIG_NFT_FWD_NETDEV) += nft_fwd_ + + # flow table infrastructure + obj-$(CONFIG_NF_FLOW_TABLE) += nf_flow_table.o ++obj-$(CONFIG_NF_FLOW_TABLE_INET) += nf_flow_table_inet.o + + # generic X tables + obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o +--- /dev/null ++++ b/net/netfilter/nf_flow_table_inet.c +@@ -0,0 +1,48 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static unsigned int ++nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++{ ++ switch (skb->protocol) { ++ case htons(ETH_P_IP): ++ return nf_flow_offload_ip_hook(priv, skb, state); ++ case htons(ETH_P_IPV6): ++ return nf_flow_offload_ipv6_hook(priv, skb, state); ++ } ++ ++ return NF_ACCEPT; ++} ++ ++static struct nf_flowtable_type flowtable_inet = { ++ .family = NFPROTO_INET, ++ .params = &nf_flow_offload_rhash_params, ++ .gc = nf_flow_offload_work_gc, ++ .hook = nf_flow_offload_inet_hook, ++ .owner = THIS_MODULE, ++}; ++ ++static int __init nf_flow_inet_module_init(void) ++{ ++ nft_register_flowtable_type(&flowtable_inet); ++ ++ return 0; ++} ++ ++static void __exit nf_flow_inet_module_exit(void) ++{ ++ nft_unregister_flowtable_type(&flowtable_inet); ++} ++ ++module_init(nf_flow_inet_module_init); ++module_exit(nf_flow_inet_module_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Pablo Neira Ayuso "); ++MODULE_ALIAS_NF_FLOWTABLE(1); /* NFPROTO_INET */ diff --git a/target/linux/generic/backport-4.14/326-netfilter-nf_tables-flow-offload-expression.patch b/target/linux/generic/backport-4.14/326-netfilter-nf_tables-flow-offload-expression.patch new file mode 100644 index 000000000..86f1f8a09 --- /dev/null +++ b/target/linux/generic/backport-4.14/326-netfilter-nf_tables-flow-offload-expression.patch @@ -0,0 +1,332 @@ +From: Pablo Neira Ayuso +Date: Sun, 7 Jan 2018 01:04:26 +0100 +Subject: [PATCH] netfilter: nf_tables: flow offload expression + +Add new instruction for the nf_tables VM that allows us to specify what +flows are offloaded into a given flow table via name. This new +instruction creates the flow entry and adds it to the flow table. + +Only established flows, ie. we have seen traffic in both directions, are +added to the flow table. You can still decide to offload entries at a +later stage via packet counting or checking the ct status in case you +want to offload assured conntracks. + +This new extension depends on the conntrack subsystem. + +Signed-off-by: Pablo Neira Ayuso +--- + create mode 100644 net/netfilter/nft_flow_offload.c + +--- a/include/uapi/linux/netfilter/nf_tables.h ++++ b/include/uapi/linux/netfilter/nf_tables.h +@@ -957,6 +957,17 @@ enum nft_ct_attributes { + }; + #define NFTA_CT_MAX (__NFTA_CT_MAX - 1) + ++/** ++ * enum nft_flow_attributes - ct offload expression attributes ++ * @NFTA_FLOW_TABLE_NAME: flow table name (NLA_STRING) ++ */ ++enum nft_offload_attributes { ++ NFTA_FLOW_UNSPEC, ++ NFTA_FLOW_TABLE_NAME, ++ __NFTA_FLOW_MAX, ++}; ++#define NFTA_FLOW_MAX (__NFTA_FLOW_MAX - 1) ++ + enum nft_limit_type { + NFT_LIMIT_PKTS, + NFT_LIMIT_PKT_BYTES +--- a/net/netfilter/Kconfig ++++ b/net/netfilter/Kconfig +@@ -509,6 +509,13 @@ config NFT_CT + This option adds the "ct" expression that you can use to match + connection tracking information such as the flow state. + ++config NFT_FLOW_OFFLOAD ++ depends on NF_CONNTRACK ++ tristate "Netfilter nf_tables hardware flow offload module" ++ help ++ This option adds the "flow_offload" expression that you can use to ++ choose what flows are placed into the hardware. ++ + config NFT_SET_RBTREE + tristate "Netfilter nf_tables rbtree set module" + help +--- a/net/netfilter/Makefile ++++ b/net/netfilter/Makefile +@@ -87,6 +87,7 @@ obj-$(CONFIG_NFT_META) += nft_meta.o + obj-$(CONFIG_NFT_RT) += nft_rt.o + obj-$(CONFIG_NFT_NUMGEN) += nft_numgen.o + obj-$(CONFIG_NFT_CT) += nft_ct.o ++obj-$(CONFIG_NFT_FLOW_OFFLOAD) += nft_flow_offload.o + obj-$(CONFIG_NFT_LIMIT) += nft_limit.o + obj-$(CONFIG_NFT_NAT) += nft_nat.o + obj-$(CONFIG_NFT_OBJREF) += nft_objref.o +--- /dev/null ++++ b/net/netfilter/nft_flow_offload.c +@@ -0,0 +1,264 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* for ipv4 options. */ ++#include ++#include ++#include ++#include ++#include ++ ++struct nft_flow_offload { ++ struct nft_flowtable *flowtable; ++}; ++ ++static int nft_flow_route(const struct nft_pktinfo *pkt, ++ const struct nf_conn *ct, ++ struct nf_flow_route *route, ++ enum ip_conntrack_dir dir) ++{ ++ struct dst_entry *this_dst = skb_dst(pkt->skb); ++ struct dst_entry *other_dst = NULL; ++ struct flowi fl; ++ ++ memset(&fl, 0, sizeof(fl)); ++ switch (nft_pf(pkt)) { ++ case NFPROTO_IPV4: ++ fl.u.ip4.daddr = ct->tuplehash[!dir].tuple.dst.u3.ip; ++ break; ++ case NFPROTO_IPV6: ++ fl.u.ip6.daddr = ct->tuplehash[!dir].tuple.dst.u3.in6; ++ break; ++ } ++ ++ nf_route(nft_net(pkt), &other_dst, &fl, false, nft_pf(pkt)); ++ if (!other_dst) ++ return -ENOENT; ++ ++ route->tuple[dir].dst = this_dst; ++ route->tuple[dir].ifindex = nft_in(pkt)->ifindex; ++ route->tuple[!dir].dst = other_dst; ++ route->tuple[!dir].ifindex = nft_out(pkt)->ifindex; ++ ++ return 0; ++} ++ ++static bool nft_flow_offload_skip(struct sk_buff *skb) ++{ ++ struct ip_options *opt = &(IPCB(skb)->opt); ++ ++ if (unlikely(opt->optlen)) ++ return true; ++ if (skb_sec_path(skb)) ++ return true; ++ ++ return false; ++} ++ ++static void nft_flow_offload_eval(const struct nft_expr *expr, ++ struct nft_regs *regs, ++ const struct nft_pktinfo *pkt) ++{ ++ struct nft_flow_offload *priv = nft_expr_priv(expr); ++ struct nf_flowtable *flowtable = &priv->flowtable->data; ++ enum ip_conntrack_info ctinfo; ++ struct nf_flow_route route; ++ struct flow_offload *flow; ++ enum ip_conntrack_dir dir; ++ struct nf_conn *ct; ++ int ret; ++ ++ if (nft_flow_offload_skip(pkt->skb)) ++ goto out; ++ ++ ct = nf_ct_get(pkt->skb, &ctinfo); ++ if (!ct) ++ goto out; ++ ++ switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) { ++ case IPPROTO_TCP: ++ case IPPROTO_UDP: ++ break; ++ default: ++ goto out; ++ } ++ ++ if (test_bit(IPS_HELPER_BIT, &ct->status)) ++ goto out; ++ ++ if (ctinfo == IP_CT_NEW || ++ ctinfo == IP_CT_RELATED) ++ goto out; ++ ++ if (test_and_set_bit(IPS_OFFLOAD_BIT, &ct->status)) ++ goto out; ++ ++ dir = CTINFO2DIR(ctinfo); ++ if (nft_flow_route(pkt, ct, &route, dir) < 0) ++ goto err_flow_route; ++ ++ flow = flow_offload_alloc(ct, &route); ++ if (!flow) ++ goto err_flow_alloc; ++ ++ ret = flow_offload_add(flowtable, flow); ++ if (ret < 0) ++ goto err_flow_add; ++ ++ return; ++ ++err_flow_add: ++ flow_offload_free(flow); ++err_flow_alloc: ++ dst_release(route.tuple[!dir].dst); ++err_flow_route: ++ clear_bit(IPS_OFFLOAD_BIT, &ct->status); ++out: ++ regs->verdict.code = NFT_BREAK; ++} ++ ++static int nft_flow_offload_validate(const struct nft_ctx *ctx, ++ const struct nft_expr *expr, ++ const struct nft_data **data) ++{ ++ unsigned int hook_mask = (1 << NF_INET_FORWARD); ++ ++ return nft_chain_validate_hooks(ctx->chain, hook_mask); ++} ++ ++static int nft_flow_offload_init(const struct nft_ctx *ctx, ++ const struct nft_expr *expr, ++ const struct nlattr * const tb[]) ++{ ++ struct nft_flow_offload *priv = nft_expr_priv(expr); ++ u8 genmask = nft_genmask_next(ctx->net); ++ struct nft_flowtable *flowtable; ++ ++ if (!tb[NFTA_FLOW_TABLE_NAME]) ++ return -EINVAL; ++ ++ flowtable = nf_tables_flowtable_lookup(ctx->table, ++ tb[NFTA_FLOW_TABLE_NAME], ++ genmask); ++ if (IS_ERR(flowtable)) ++ return PTR_ERR(flowtable); ++ ++ priv->flowtable = flowtable; ++ flowtable->use++; ++ ++ return nf_ct_netns_get(ctx->net, ctx->afi->family); ++} ++ ++static void nft_flow_offload_destroy(const struct nft_ctx *ctx, ++ const struct nft_expr *expr) ++{ ++ struct nft_flow_offload *priv = nft_expr_priv(expr); ++ ++ priv->flowtable->use--; ++ nf_ct_netns_put(ctx->net, ctx->afi->family); ++} ++ ++static int nft_flow_offload_dump(struct sk_buff *skb, const struct nft_expr *expr) ++{ ++ struct nft_flow_offload *priv = nft_expr_priv(expr); ++ ++ if (nla_put_string(skb, NFTA_FLOW_TABLE_NAME, priv->flowtable->name)) ++ goto nla_put_failure; ++ ++ return 0; ++ ++nla_put_failure: ++ return -1; ++} ++ ++static struct nft_expr_type nft_flow_offload_type; ++static const struct nft_expr_ops nft_flow_offload_ops = { ++ .type = &nft_flow_offload_type, ++ .size = NFT_EXPR_SIZE(sizeof(struct nft_flow_offload)), ++ .eval = nft_flow_offload_eval, ++ .init = nft_flow_offload_init, ++ .destroy = nft_flow_offload_destroy, ++ .validate = nft_flow_offload_validate, ++ .dump = nft_flow_offload_dump, ++}; ++ ++static struct nft_expr_type nft_flow_offload_type __read_mostly = { ++ .name = "flow_offload", ++ .ops = &nft_flow_offload_ops, ++ .maxattr = NFTA_FLOW_MAX, ++ .owner = THIS_MODULE, ++}; ++ ++static void flow_offload_iterate_cleanup(struct flow_offload *flow, void *data) ++{ ++ struct net_device *dev = data; ++ ++ if (dev && flow->tuplehash[0].tuple.iifidx != dev->ifindex) ++ return; ++ ++ flow_offload_dead(flow); ++} ++ ++static void nft_flow_offload_iterate_cleanup(struct nf_flowtable *flowtable, ++ void *data) ++{ ++ nf_flow_table_iterate(flowtable, flow_offload_iterate_cleanup, data); ++} ++ ++static int flow_offload_netdev_event(struct notifier_block *this, ++ unsigned long event, void *ptr) ++{ ++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++ ++ if (event != NETDEV_DOWN) ++ return NOTIFY_DONE; ++ ++ nft_flow_table_iterate(dev_net(dev), nft_flow_offload_iterate_cleanup, dev); ++ ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block flow_offload_netdev_notifier = { ++ .notifier_call = flow_offload_netdev_event, ++}; ++ ++static int __init nft_flow_offload_module_init(void) ++{ ++ int err; ++ ++ register_netdevice_notifier(&flow_offload_netdev_notifier); ++ ++ err = nft_register_expr(&nft_flow_offload_type); ++ if (err < 0) ++ goto register_expr; ++ ++ return 0; ++ ++register_expr: ++ unregister_netdevice_notifier(&flow_offload_netdev_notifier); ++ return err; ++} ++ ++static void __exit nft_flow_offload_module_exit(void) ++{ ++ struct net *net; ++ ++ nft_unregister_expr(&nft_flow_offload_type); ++ unregister_netdevice_notifier(&flow_offload_netdev_notifier); ++ rtnl_lock(); ++ for_each_net(net) ++ nft_flow_table_iterate(net, nft_flow_offload_iterate_cleanup, NULL); ++ rtnl_unlock(); ++} ++ ++module_init(nft_flow_offload_module_init); ++module_exit(nft_flow_offload_module_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Pablo Neira Ayuso "); ++MODULE_ALIAS_NFT_EXPR("flow_offload"); diff --git a/target/linux/generic/backport-4.14/327-netfilter-nf_tables-remove-nhooks-field-from-struct-.patch b/target/linux/generic/backport-4.14/327-netfilter-nf_tables-remove-nhooks-field-from-struct-.patch new file mode 100644 index 000000000..ac38477ca --- /dev/null +++ b/target/linux/generic/backport-4.14/327-netfilter-nf_tables-remove-nhooks-field-from-struct-.patch @@ -0,0 +1,113 @@ +From: Pablo Neira Ayuso +Date: Tue, 19 Dec 2017 13:53:45 +0100 +Subject: [PATCH] netfilter: nf_tables: remove nhooks field from struct + nft_af_info + +We already validate the hook through bitmask, so this check is +superfluous. When removing this, this patch is also fixing a bug in the +new flowtable codebase, since ctx->afi points to the table family +instead of the netdev family which is where the flowtable is really +hooked in. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -963,7 +963,6 @@ enum nft_af_flags { + * + * @list: used internally + * @family: address family +- * @nhooks: number of hooks in this family + * @owner: module owner + * @tables: used internally + * @flags: family flags +@@ -971,7 +970,6 @@ enum nft_af_flags { + struct nft_af_info { + struct list_head list; + int family; +- unsigned int nhooks; + struct module *owner; + struct list_head tables; + u32 flags; +--- a/net/bridge/netfilter/nf_tables_bridge.c ++++ b/net/bridge/netfilter/nf_tables_bridge.c +@@ -44,7 +44,6 @@ nft_do_chain_bridge(void *priv, + + static struct nft_af_info nft_af_bridge __read_mostly = { + .family = NFPROTO_BRIDGE, +- .nhooks = NF_BR_NUMHOOKS, + .owner = THIS_MODULE, + }; + +--- a/net/ipv4/netfilter/nf_tables_arp.c ++++ b/net/ipv4/netfilter/nf_tables_arp.c +@@ -29,7 +29,6 @@ nft_do_chain_arp(void *priv, + + static struct nft_af_info nft_af_arp __read_mostly = { + .family = NFPROTO_ARP, +- .nhooks = NF_ARP_NUMHOOKS, + .owner = THIS_MODULE, + }; + +--- a/net/ipv4/netfilter/nf_tables_ipv4.c ++++ b/net/ipv4/netfilter/nf_tables_ipv4.c +@@ -32,7 +32,6 @@ static unsigned int nft_do_chain_ipv4(vo + + static struct nft_af_info nft_af_ipv4 __read_mostly = { + .family = NFPROTO_IPV4, +- .nhooks = NF_INET_NUMHOOKS, + .owner = THIS_MODULE, + }; + +--- a/net/ipv6/netfilter/nf_tables_ipv6.c ++++ b/net/ipv6/netfilter/nf_tables_ipv6.c +@@ -30,7 +30,6 @@ static unsigned int nft_do_chain_ipv6(vo + + static struct nft_af_info nft_af_ipv6 __read_mostly = { + .family = NFPROTO_IPV6, +- .nhooks = NF_INET_NUMHOOKS, + .owner = THIS_MODULE, + }; + +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -1328,9 +1328,6 @@ static int nft_chain_parse_hook(struct n + return -EINVAL; + + hook->num = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM])); +- if (hook->num >= afi->nhooks) +- return -EINVAL; +- + hook->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY])); + + type = chain_type[afi->family][NFT_CHAIN_T_DEFAULT]; +@@ -4919,7 +4916,7 @@ static int nf_tables_flowtable_parse_hoo + return -EINVAL; + + hooknum = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_NUM])); +- if (hooknum >= ctx->afi->nhooks) ++ if (hooknum != NF_NETDEV_INGRESS) + return -EINVAL; + + priority = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_PRIORITY])); +--- a/net/netfilter/nf_tables_inet.c ++++ b/net/netfilter/nf_tables_inet.c +@@ -40,7 +40,6 @@ static unsigned int nft_do_chain_inet(vo + + static struct nft_af_info nft_af_inet __read_mostly = { + .family = NFPROTO_INET, +- .nhooks = NF_INET_NUMHOOKS, + .owner = THIS_MODULE, + }; + +--- a/net/netfilter/nf_tables_netdev.c ++++ b/net/netfilter/nf_tables_netdev.c +@@ -40,7 +40,6 @@ nft_do_chain_netdev(void *priv, struct s + + static struct nft_af_info nft_af_netdev __read_mostly = { + .family = NFPROTO_NETDEV, +- .nhooks = NF_NETDEV_NUMHOOKS, + .owner = THIS_MODULE, + .flags = NFT_AF_NEEDS_DEV, + }; diff --git a/target/linux/generic/backport-4.14/328-netfilter-nf_tables-fix-a-typo-in-nf_tables_getflowt.patch b/target/linux/generic/backport-4.14/328-netfilter-nf_tables-fix-a-typo-in-nf_tables_getflowt.patch new file mode 100644 index 000000000..dc62dd37a --- /dev/null +++ b/target/linux/generic/backport-4.14/328-netfilter-nf_tables-fix-a-typo-in-nf_tables_getflowt.patch @@ -0,0 +1,22 @@ +From: Wei Yongjun +Date: Wed, 10 Jan 2018 07:04:54 +0000 +Subject: [PATCH] netfilter: nf_tables: fix a typo in nf_tables_getflowtable() + +Fix a typo, we should check 'flowtable' instead of 'table'. + +Fixes: 3b49e2e94e6e ("netfilter: nf_tables: add flow table netlink frontend") +Signed-off-by: Wei Yongjun +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -5343,7 +5343,7 @@ static int nf_tables_getflowtable(struct + + flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], + genmask); +- if (IS_ERR(table)) ++ if (IS_ERR(flowtable)) + return PTR_ERR(flowtable); + + skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); diff --git a/target/linux/generic/backport-4.14/329-netfilter-improve-flow-table-Kconfig-dependencies.patch b/target/linux/generic/backport-4.14/329-netfilter-improve-flow-table-Kconfig-dependencies.patch new file mode 100644 index 000000000..c897c3672 --- /dev/null +++ b/target/linux/generic/backport-4.14/329-netfilter-improve-flow-table-Kconfig-dependencies.patch @@ -0,0 +1,106 @@ +From: Arnd Bergmann +Date: Wed, 10 Jan 2018 18:10:59 +0100 +Subject: [PATCH] netfilter: improve flow table Kconfig dependencies + +The newly added NF_FLOW_TABLE options cause some build failures in +randconfig kernels: + +- when CONFIG_NF_CONNTRACK is disabled, or is a loadable module but + NF_FLOW_TABLE is built-in: + + In file included from net/netfilter/nf_flow_table.c:8:0: + include/net/netfilter/nf_conntrack.h:59:22: error: field 'ct_general' has incomplete type + struct nf_conntrack ct_general; + include/net/netfilter/nf_conntrack.h: In function 'nf_ct_get': + include/net/netfilter/nf_conntrack.h:148:15: error: 'const struct sk_buff' has no member named '_nfct' + include/net/netfilter/nf_conntrack.h: In function 'nf_ct_put': + include/net/netfilter/nf_conntrack.h:157:2: error: implicit declaration of function 'nf_conntrack_put'; did you mean 'nf_ct_put'? [-Werror=implicit-function-declaration] + + net/netfilter/nf_flow_table.o: In function `nf_flow_offload_work_gc': + (.text+0x1540): undefined reference to `nf_ct_delete' + +- when CONFIG_NF_TABLES is disabled: + + In file included from net/ipv6/netfilter/nf_flow_table_ipv6.c:13:0: + include/net/netfilter/nf_tables.h: In function 'nft_gencursor_next': + include/net/netfilter/nf_tables.h:1189:14: error: 'const struct net' has no member named 'nft'; did you mean 'nf'? + + - when CONFIG_NF_FLOW_TABLE_INET is enabled, but NF_FLOW_TABLE_IPV4 + or NF_FLOW_TABLE_IPV6 are not, or are loadable modules + + net/netfilter/nf_flow_table_inet.o: In function `nf_flow_offload_inet_hook': + nf_flow_table_inet.c:(.text+0x94): undefined reference to `nf_flow_offload_ipv6_hook' + nf_flow_table_inet.c:(.text+0x40): undefined reference to `nf_flow_offload_ip_hook' + +- when CONFIG_NF_FLOW_TABLES is disabled, but the other options are + enabled: + + net/netfilter/nf_flow_table_inet.o: In function `nf_flow_offload_inet_hook': + nf_flow_table_inet.c:(.text+0x6c): undefined reference to `nf_flow_offload_ipv6_hook' + net/netfilter/nf_flow_table_inet.o: In function `nf_flow_inet_module_exit': + nf_flow_table_inet.c:(.exit.text+0x8): undefined reference to `nft_unregister_flowtable_type' + net/netfilter/nf_flow_table_inet.o: In function `nf_flow_inet_module_init': + nf_flow_table_inet.c:(.init.text+0x8): undefined reference to `nft_register_flowtable_type' + net/ipv4/netfilter/nf_flow_table_ipv4.o: In function `nf_flow_ipv4_module_exit': + nf_flow_table_ipv4.c:(.exit.text+0x8): undefined reference to `nft_unregister_flowtable_type' + net/ipv4/netfilter/nf_flow_table_ipv4.o: In function `nf_flow_ipv4_module_init': + nf_flow_table_ipv4.c:(.init.text+0x8): undefined reference to `nft_register_flowtable_type' + +This adds additional Kconfig dependencies to ensure that NF_CONNTRACK and NF_TABLES +are always visible from NF_FLOW_TABLE, and that the internal dependencies between +the four new modules are met. + +Fixes: 7c23b629a808 ("netfilter: flow table support for the mixed IPv4/IPv6 family") +Fixes: 0995210753a2 ("netfilter: flow table support for IPv6") +Fixes: 97add9f0d66d ("netfilter: flow table support for IPv4") +Signed-off-by: Arnd Bergmann +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/ipv4/netfilter/Kconfig ++++ b/net/ipv4/netfilter/Kconfig +@@ -78,8 +78,9 @@ config NF_TABLES_ARP + endif # NF_TABLES + + config NF_FLOW_TABLE_IPV4 +- select NF_FLOW_TABLE + tristate "Netfilter flow table IPv4 module" ++ depends on NF_CONNTRACK && NF_TABLES ++ select NF_FLOW_TABLE + help + This option adds the flow table IPv4 support. + +--- a/net/ipv6/netfilter/Kconfig ++++ b/net/ipv6/netfilter/Kconfig +@@ -72,8 +72,9 @@ endif # NF_TABLES_IPV6 + endif # NF_TABLES + + config NF_FLOW_TABLE_IPV6 +- select NF_FLOW_TABLE + tristate "Netfilter flow table IPv6 module" ++ depends on NF_CONNTRACK && NF_TABLES ++ select NF_FLOW_TABLE + help + This option adds the flow table IPv6 support. + +--- a/net/netfilter/Kconfig ++++ b/net/netfilter/Kconfig +@@ -669,8 +669,9 @@ endif # NF_TABLES_NETDEV + endif # NF_TABLES + + config NF_FLOW_TABLE_INET +- select NF_FLOW_TABLE + tristate "Netfilter flow table mixed IPv4/IPv6 module" ++ depends on NF_FLOW_TABLE_IPV4 && NF_FLOW_TABLE_IPV6 ++ select NF_FLOW_TABLE + help + This option adds the flow table mixed IPv4/IPv6 support. + +@@ -678,6 +679,7 @@ config NF_FLOW_TABLE_INET + + config NF_FLOW_TABLE + tristate "Netfilter flow table module" ++ depends on NF_CONNTRACK && NF_TABLES + help + This option adds the flow table core infrastructure. + diff --git a/target/linux/generic/backport-4.14/330-netfilter-nf_tables-remove-flag-field-from-struct-nf.patch b/target/linux/generic/backport-4.14/330-netfilter-nf_tables-remove-flag-field-from-struct-nf.patch new file mode 100644 index 000000000..42aa7b1b0 --- /dev/null +++ b/target/linux/generic/backport-4.14/330-netfilter-nf_tables-remove-flag-field-from-struct-nf.patch @@ -0,0 +1,59 @@ +From: Pablo Neira Ayuso +Date: Tue, 19 Dec 2017 14:07:52 +0100 +Subject: [PATCH] netfilter: nf_tables: remove flag field from struct + nft_af_info + +Replace it by a direct check for the netdev protocol family. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -954,10 +954,6 @@ struct nft_table { + char *name; + }; + +-enum nft_af_flags { +- NFT_AF_NEEDS_DEV = (1 << 0), +-}; +- + /** + * struct nft_af_info - nf_tables address family info + * +@@ -965,14 +961,12 @@ enum nft_af_flags { + * @family: address family + * @owner: module owner + * @tables: used internally +- * @flags: family flags + */ + struct nft_af_info { + struct list_head list; + int family; + struct module *owner; + struct list_head tables; +- u32 flags; + }; + + int nft_register_afinfo(struct net *, struct nft_af_info *); +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -1345,7 +1345,7 @@ static int nft_chain_parse_hook(struct n + hook->type = type; + + hook->dev = NULL; +- if (afi->flags & NFT_AF_NEEDS_DEV) { ++ if (afi->family == NFPROTO_NETDEV) { + char ifname[IFNAMSIZ]; + + if (!ha[NFTA_HOOK_DEV]) { +--- a/net/netfilter/nf_tables_netdev.c ++++ b/net/netfilter/nf_tables_netdev.c +@@ -41,7 +41,6 @@ nft_do_chain_netdev(void *priv, struct s + static struct nft_af_info nft_af_netdev __read_mostly = { + .family = NFPROTO_NETDEV, + .owner = THIS_MODULE, +- .flags = NFT_AF_NEEDS_DEV, + }; + + static int nf_tables_netdev_init_net(struct net *net) diff --git a/target/linux/generic/backport-4.14/331-netfilter-nf_tables-no-need-for-struct-nft_af_info-t.patch b/target/linux/generic/backport-4.14/331-netfilter-nf_tables-no-need-for-struct-nft_af_info-t.patch new file mode 100644 index 000000000..2b7260c53 --- /dev/null +++ b/target/linux/generic/backport-4.14/331-netfilter-nf_tables-no-need-for-struct-nft_af_info-t.patch @@ -0,0 +1,80 @@ +From: Pablo Neira Ayuso +Date: Tue, 19 Dec 2017 12:17:52 +0100 +Subject: [PATCH] netfilter: nf_tables: no need for struct nft_af_info to + enable/disable table + +nf_tables_table_enable() and nf_tables_table_disable() take a pointer to +struct nft_af_info that is never used, remove it. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -611,10 +611,7 @@ err: + return err; + } + +-static void _nf_tables_table_disable(struct net *net, +- const struct nft_af_info *afi, +- struct nft_table *table, +- u32 cnt) ++static void nft_table_disable(struct net *net, struct nft_table *table, u32 cnt) + { + struct nft_chain *chain; + u32 i = 0; +@@ -632,9 +629,7 @@ static void _nf_tables_table_disable(str + } + } + +-static int nf_tables_table_enable(struct net *net, +- const struct nft_af_info *afi, +- struct nft_table *table) ++static int nf_tables_table_enable(struct net *net, struct nft_table *table) + { + struct nft_chain *chain; + int err, i = 0; +@@ -654,15 +649,13 @@ static int nf_tables_table_enable(struct + return 0; + err: + if (i) +- _nf_tables_table_disable(net, afi, table, i); ++ nft_table_disable(net, table, i); + return err; + } + +-static void nf_tables_table_disable(struct net *net, +- const struct nft_af_info *afi, +- struct nft_table *table) ++static void nf_tables_table_disable(struct net *net, struct nft_table *table) + { +- _nf_tables_table_disable(net, afi, table, 0); ++ nft_table_disable(net, table, 0); + } + + static int nf_tables_updtable(struct nft_ctx *ctx) +@@ -691,7 +684,7 @@ static int nf_tables_updtable(struct nft + nft_trans_table_enable(trans) = false; + } else if (!(flags & NFT_TABLE_F_DORMANT) && + ctx->table->flags & NFT_TABLE_F_DORMANT) { +- ret = nf_tables_table_enable(ctx->net, ctx->afi, ctx->table); ++ ret = nf_tables_table_enable(ctx->net, ctx->table); + if (ret >= 0) { + ctx->table->flags &= ~NFT_TABLE_F_DORMANT; + nft_trans_table_enable(trans) = true; +@@ -5721,7 +5714,6 @@ static int nf_tables_commit(struct net * + if (nft_trans_table_update(trans)) { + if (!nft_trans_table_enable(trans)) { + nf_tables_table_disable(net, +- trans->ctx.afi, + trans->ctx.table); + trans->ctx.table->flags |= NFT_TABLE_F_DORMANT; + } +@@ -5883,7 +5875,6 @@ static int nf_tables_abort(struct net *n + if (nft_trans_table_update(trans)) { + if (nft_trans_table_enable(trans)) { + nf_tables_table_disable(net, +- trans->ctx.afi, + trans->ctx.table); + trans->ctx.table->flags |= NFT_TABLE_F_DORMANT; + } diff --git a/target/linux/generic/backport-4.14/332-netfilter-nf_tables-remove-struct-nft_af_info-parame.patch b/target/linux/generic/backport-4.14/332-netfilter-nf_tables-remove-struct-nft_af_info-parame.patch new file mode 100644 index 000000000..158f987fe --- /dev/null +++ b/target/linux/generic/backport-4.14/332-netfilter-nf_tables-remove-struct-nft_af_info-parame.patch @@ -0,0 +1,60 @@ +From: Pablo Neira Ayuso +Date: Tue, 19 Dec 2017 13:40:22 +0100 +Subject: [PATCH] netfilter: nf_tables: remove struct nft_af_info parameter in + nf_tables_chain_type_lookup() + +Pass family number instead, this comes in preparation for the removal of +struct nft_af_info. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -423,7 +423,7 @@ static inline u64 nf_tables_alloc_handle + static const struct nf_chain_type *chain_type[NFPROTO_NUMPROTO][NFT_CHAIN_T_MAX]; + + static const struct nf_chain_type * +-__nf_tables_chain_type_lookup(int family, const struct nlattr *nla) ++__nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family) + { + int i; + +@@ -436,22 +436,20 @@ __nf_tables_chain_type_lookup(int family + } + + static const struct nf_chain_type * +-nf_tables_chain_type_lookup(const struct nft_af_info *afi, +- const struct nlattr *nla, +- bool autoload) ++nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family, bool autoload) + { + const struct nf_chain_type *type; + +- type = __nf_tables_chain_type_lookup(afi->family, nla); ++ type = __nf_tables_chain_type_lookup(nla, family); + if (type != NULL) + return type; + #ifdef CONFIG_MODULES + if (autoload) { + nfnl_unlock(NFNL_SUBSYS_NFTABLES); +- request_module("nft-chain-%u-%.*s", afi->family, ++ request_module("nft-chain-%u-%.*s", family, + nla_len(nla), (const char *)nla_data(nla)); + nfnl_lock(NFNL_SUBSYS_NFTABLES); +- type = __nf_tables_chain_type_lookup(afi->family, nla); ++ type = __nf_tables_chain_type_lookup(nla, family); + if (type != NULL) + return ERR_PTR(-EAGAIN); + } +@@ -1325,8 +1323,8 @@ static int nft_chain_parse_hook(struct n + + type = chain_type[afi->family][NFT_CHAIN_T_DEFAULT]; + if (nla[NFTA_CHAIN_TYPE]) { +- type = nf_tables_chain_type_lookup(afi, nla[NFTA_CHAIN_TYPE], +- create); ++ type = nf_tables_chain_type_lookup(nla[NFTA_CHAIN_TYPE], ++ afi->family, create); + if (IS_ERR(type)) + return PTR_ERR(type); + } diff --git a/target/linux/generic/backport-4.14/334-netfilter-nf_tables-fix-potential-NULL-ptr-deref-in-.patch b/target/linux/generic/backport-4.14/334-netfilter-nf_tables-fix-potential-NULL-ptr-deref-in-.patch new file mode 100644 index 000000000..59c419e00 --- /dev/null +++ b/target/linux/generic/backport-4.14/334-netfilter-nf_tables-fix-potential-NULL-ptr-deref-in-.patch @@ -0,0 +1,30 @@ +From: Hangbin Liu +Date: Mon, 25 Dec 2017 11:34:54 +0800 +Subject: [PATCH] netfilter: nf_tables: fix potential NULL-ptr deref in + nf_tables_dump_obj_done() + +If there is no NFTA_OBJ_TABLE and NFTA_OBJ_TYPE, the c.data will be NULL in +nf_tables_getobj(). So before free filter->table in nf_tables_dump_obj_done(), +we need to check if filter is NULL first. + +Fixes: e46abbcc05aa ("netfilter: nf_tables: Allow table names of up to 255 chars") +Signed-off-by: Hangbin Liu +Acked-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -5262,8 +5262,10 @@ static int nf_tables_dump_flowtable_done + if (!filter) + return 0; + +- kfree(filter->table); +- kfree(filter); ++ if (filter) { ++ kfree(filter->table); ++ kfree(filter); ++ } + + return 0; + } diff --git a/target/linux/generic/backport-4.14/335-netfilter-nf_tables-add-single-table-list-for-all-fa.patch b/target/linux/generic/backport-4.14/335-netfilter-nf_tables-add-single-table-list-for-all-fa.patch new file mode 100644 index 000000000..6fedd00eb --- /dev/null +++ b/target/linux/generic/backport-4.14/335-netfilter-nf_tables-add-single-table-list-for-all-fa.patch @@ -0,0 +1,1450 @@ +From: Pablo Neira Ayuso +Date: Tue, 9 Jan 2018 02:38:03 +0100 +Subject: [PATCH] netfilter: nf_tables: add single table list for all families + +Place all existing user defined tables in struct net *, instead of +having one list per family. This saves us from one level of indentation +in netlink dump functions. + +Place pointer to struct nft_af_info in struct nft_table temporarily, as +we still need this to put back reference module reference counter on +table removal. + +This patch comes in preparation for the removal of struct nft_af_info. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -143,22 +143,22 @@ static inline void nft_data_debug(const + * struct nft_ctx - nf_tables rule/set context + * + * @net: net namespace +- * @afi: address family info + * @table: the table the chain is contained in + * @chain: the chain the rule is contained in + * @nla: netlink attributes + * @portid: netlink portID of the original message + * @seq: netlink sequence number ++ * @family: protocol family + * @report: notify via unicast netlink message + */ + struct nft_ctx { + struct net *net; +- struct nft_af_info *afi; + struct nft_table *table; + struct nft_chain *chain; + const struct nlattr * const *nla; + u32 portid; + u32 seq; ++ u8 family; + bool report; + }; + +@@ -939,6 +939,7 @@ unsigned int nft_do_chain(struct nft_pkt + * @use: number of chain references to this table + * @flags: table flag (see enum nft_table_flags) + * @genmask: generation mask ++ * @afinfo: address family info + * @name: name of the table + */ + struct nft_table { +@@ -951,6 +952,7 @@ struct nft_table { + u32 use; + u16 flags:14, + genmask:2; ++ struct nft_af_info *afi; + char *name; + }; + +@@ -960,13 +962,11 @@ struct nft_table { + * @list: used internally + * @family: address family + * @owner: module owner +- * @tables: used internally + */ + struct nft_af_info { + struct list_head list; + int family; + struct module *owner; +- struct list_head tables; + }; + + int nft_register_afinfo(struct net *, struct nft_af_info *); +--- a/include/net/netns/nftables.h ++++ b/include/net/netns/nftables.h +@@ -8,6 +8,7 @@ struct nft_af_info; + + struct netns_nftables { + struct list_head af_info; ++ struct list_head tables; + struct list_head commit_list; + struct nft_af_info *ipv4; + struct nft_af_info *ipv6; +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -37,7 +37,6 @@ static LIST_HEAD(nf_tables_flowtables); + */ + int nft_register_afinfo(struct net *net, struct nft_af_info *afi) + { +- INIT_LIST_HEAD(&afi->tables); + nfnl_lock(NFNL_SUBSYS_NFTABLES); + list_add_tail_rcu(&afi->list, &net->nft.af_info); + nfnl_unlock(NFNL_SUBSYS_NFTABLES); +@@ -99,13 +98,13 @@ static void nft_ctx_init(struct nft_ctx + struct net *net, + const struct sk_buff *skb, + const struct nlmsghdr *nlh, +- struct nft_af_info *afi, ++ u8 family, + struct nft_table *table, + struct nft_chain *chain, + const struct nlattr * const *nla) + { + ctx->net = net; +- ctx->afi = afi; ++ ctx->family = family; + ctx->table = table; + ctx->chain = chain; + ctx->nla = nla; +@@ -385,30 +384,31 @@ static int nft_delflowtable(struct nft_c + * Tables + */ + +-static struct nft_table *nft_table_lookup(const struct nft_af_info *afi, ++static struct nft_table *nft_table_lookup(const struct net *net, + const struct nlattr *nla, +- u8 genmask) ++ u8 family, u8 genmask) + { + struct nft_table *table; + +- list_for_each_entry(table, &afi->tables, list) { ++ list_for_each_entry(table, &net->nft.tables, list) { + if (!nla_strcmp(nla, table->name) && ++ table->afi->family == family && + nft_active_genmask(table, genmask)) + return table; + } + return NULL; + } + +-static struct nft_table *nf_tables_table_lookup(const struct nft_af_info *afi, ++static struct nft_table *nf_tables_table_lookup(const struct net *net, + const struct nlattr *nla, +- u8 genmask) ++ u8 family, u8 genmask) + { + struct nft_table *table; + + if (nla == NULL) + return ERR_PTR(-EINVAL); + +- table = nft_table_lookup(afi, nla, genmask); ++ table = nft_table_lookup(net, nla, family, genmask); + if (table != NULL) + return table; + +@@ -507,7 +507,7 @@ static void nf_tables_table_notify(const + goto err; + + err = nf_tables_fill_table_info(skb, ctx->net, ctx->portid, ctx->seq, +- event, 0, ctx->afi->family, ctx->table); ++ event, 0, ctx->family, ctx->table); + if (err < 0) { + kfree_skb(skb); + goto err; +@@ -524,7 +524,6 @@ static int nf_tables_dump_tables(struct + struct netlink_callback *cb) + { + const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); +- const struct nft_af_info *afi; + const struct nft_table *table; + unsigned int idx = 0, s_idx = cb->args[0]; + struct net *net = sock_net(skb->sk); +@@ -533,30 +532,27 @@ static int nf_tables_dump_tables(struct + rcu_read_lock(); + cb->seq = net->nft.base_seq; + +- list_for_each_entry_rcu(afi, &net->nft.af_info, list) { +- if (family != NFPROTO_UNSPEC && family != afi->family) ++ list_for_each_entry_rcu(table, &net->nft.tables, list) { ++ if (family != NFPROTO_UNSPEC && family != table->afi->family) + continue; + +- list_for_each_entry_rcu(table, &afi->tables, list) { +- if (idx < s_idx) +- goto cont; +- if (idx > s_idx) +- memset(&cb->args[1], 0, +- sizeof(cb->args) - sizeof(cb->args[0])); +- if (!nft_is_active(net, table)) +- continue; +- if (nf_tables_fill_table_info(skb, net, +- NETLINK_CB(cb->skb).portid, +- cb->nlh->nlmsg_seq, +- NFT_MSG_NEWTABLE, +- NLM_F_MULTI, +- afi->family, table) < 0) +- goto done; ++ if (idx < s_idx) ++ goto cont; ++ if (idx > s_idx) ++ memset(&cb->args[1], 0, ++ sizeof(cb->args) - sizeof(cb->args[0])); ++ if (!nft_is_active(net, table)) ++ continue; ++ if (nf_tables_fill_table_info(skb, net, ++ NETLINK_CB(cb->skb).portid, ++ cb->nlh->nlmsg_seq, ++ NFT_MSG_NEWTABLE, NLM_F_MULTI, ++ table->afi->family, table) < 0) ++ goto done; + +- nl_dump_check_consistent(cb, nlmsg_hdr(skb)); ++ nl_dump_check_consistent(cb, nlmsg_hdr(skb)); + cont: +- idx++; +- } ++ idx++; + } + done: + rcu_read_unlock(); +@@ -588,7 +584,8 @@ static int nf_tables_gettable(struct net + if (IS_ERR(afi)) + return PTR_ERR(afi); + +- table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME], genmask); ++ table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], afi->family, ++ genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -719,7 +716,7 @@ static int nf_tables_newtable(struct net + return PTR_ERR(afi); + + name = nla[NFTA_TABLE_NAME]; +- table = nf_tables_table_lookup(afi, name, genmask); ++ table = nf_tables_table_lookup(net, name, afi->family, genmask); + if (IS_ERR(table)) { + if (PTR_ERR(table) != -ENOENT) + return PTR_ERR(table); +@@ -729,7 +726,7 @@ static int nf_tables_newtable(struct net + if (nlh->nlmsg_flags & NLM_F_REPLACE) + return -EOPNOTSUPP; + +- nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); + return nf_tables_updtable(&ctx); + } + +@@ -756,14 +753,15 @@ static int nf_tables_newtable(struct net + INIT_LIST_HEAD(&table->sets); + INIT_LIST_HEAD(&table->objects); + INIT_LIST_HEAD(&table->flowtables); ++ table->afi = afi; + table->flags = flags; + +- nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); + err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE); + if (err < 0) + goto err4; + +- list_add_tail_rcu(&table->list, &afi->tables); ++ list_add_tail_rcu(&table->list, &net->nft.tables); + return 0; + err4: + kfree(table->name); +@@ -837,30 +835,28 @@ out: + + static int nft_flush(struct nft_ctx *ctx, int family) + { +- struct nft_af_info *afi; + struct nft_table *table, *nt; + const struct nlattr * const *nla = ctx->nla; + int err = 0; + +- list_for_each_entry(afi, &ctx->net->nft.af_info, list) { +- if (family != AF_UNSPEC && afi->family != family) ++ list_for_each_entry_safe(table, nt, &ctx->net->nft.tables, list) { ++ if (family != AF_UNSPEC && table->afi->family != family) + continue; + +- ctx->afi = afi; +- list_for_each_entry_safe(table, nt, &afi->tables, list) { +- if (!nft_is_active_next(ctx->net, table)) +- continue; ++ ctx->family = table->afi->family; + +- if (nla[NFTA_TABLE_NAME] && +- nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0) +- continue; ++ if (!nft_is_active_next(ctx->net, table)) ++ continue; + +- ctx->table = table; ++ if (nla[NFTA_TABLE_NAME] && ++ nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0) ++ continue; + +- err = nft_flush_table(ctx); +- if (err < 0) +- goto out; +- } ++ ctx->table = table; ++ ++ err = nft_flush_table(ctx); ++ if (err < 0) ++ goto out; + } + out: + return err; +@@ -878,7 +874,7 @@ static int nf_tables_deltable(struct net + int family = nfmsg->nfgen_family; + struct nft_ctx ctx; + +- nft_ctx_init(&ctx, net, skb, nlh, NULL, NULL, NULL, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, 0, NULL, NULL, nla); + if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL) + return nft_flush(&ctx, family); + +@@ -886,7 +882,8 @@ static int nf_tables_deltable(struct net + if (IS_ERR(afi)) + return PTR_ERR(afi); + +- table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME], genmask); ++ table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], afi->family, ++ genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -894,7 +891,7 @@ static int nf_tables_deltable(struct net + table->use > 0) + return -EBUSY; + +- ctx.afi = afi; ++ ctx.family = afi->family; + ctx.table = table; + + return nft_flush_table(&ctx); +@@ -906,7 +903,7 @@ static void nf_tables_table_destroy(stru + + kfree(ctx->table->name); + kfree(ctx->table); +- module_put(ctx->afi->owner); ++ module_put(ctx->table->afi->owner); + } + + int nft_register_chain_type(const struct nf_chain_type *ctype) +@@ -1107,7 +1104,7 @@ static void nf_tables_chain_notify(const + goto err; + + err = nf_tables_fill_chain_info(skb, ctx->net, ctx->portid, ctx->seq, +- event, 0, ctx->afi->family, ctx->table, ++ event, 0, ctx->family, ctx->table, + ctx->chain); + if (err < 0) { + kfree_skb(skb); +@@ -1125,7 +1122,6 @@ static int nf_tables_dump_chains(struct + struct netlink_callback *cb) + { + const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); +- const struct nft_af_info *afi; + const struct nft_table *table; + const struct nft_chain *chain; + unsigned int idx = 0, s_idx = cb->args[0]; +@@ -1135,31 +1131,30 @@ static int nf_tables_dump_chains(struct + rcu_read_lock(); + cb->seq = net->nft.base_seq; + +- list_for_each_entry_rcu(afi, &net->nft.af_info, list) { +- if (family != NFPROTO_UNSPEC && family != afi->family) ++ list_for_each_entry_rcu(table, &net->nft.tables, list) { ++ if (family != NFPROTO_UNSPEC && family != table->afi->family) + continue; + +- list_for_each_entry_rcu(table, &afi->tables, list) { +- list_for_each_entry_rcu(chain, &table->chains, list) { +- if (idx < s_idx) +- goto cont; +- if (idx > s_idx) +- memset(&cb->args[1], 0, +- sizeof(cb->args) - sizeof(cb->args[0])); +- if (!nft_is_active(net, chain)) +- continue; +- if (nf_tables_fill_chain_info(skb, net, +- NETLINK_CB(cb->skb).portid, +- cb->nlh->nlmsg_seq, +- NFT_MSG_NEWCHAIN, +- NLM_F_MULTI, +- afi->family, table, chain) < 0) +- goto done; ++ list_for_each_entry_rcu(chain, &table->chains, list) { ++ if (idx < s_idx) ++ goto cont; ++ if (idx > s_idx) ++ memset(&cb->args[1], 0, ++ sizeof(cb->args) - sizeof(cb->args[0])); ++ if (!nft_is_active(net, chain)) ++ continue; ++ if (nf_tables_fill_chain_info(skb, net, ++ NETLINK_CB(cb->skb).portid, ++ cb->nlh->nlmsg_seq, ++ NFT_MSG_NEWCHAIN, ++ NLM_F_MULTI, ++ table->afi->family, table, ++ chain) < 0) ++ goto done; + +- nl_dump_check_consistent(cb, nlmsg_hdr(skb)); ++ nl_dump_check_consistent(cb, nlmsg_hdr(skb)); + cont: +- idx++; +- } ++ idx++; + } + } + done: +@@ -1193,7 +1188,8 @@ static int nf_tables_getchain(struct net + if (IS_ERR(afi)) + return PTR_ERR(afi); + +- table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask); ++ table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], afi->family, ++ genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -1301,8 +1297,8 @@ struct nft_chain_hook { + + static int nft_chain_parse_hook(struct net *net, + const struct nlattr * const nla[], +- struct nft_af_info *afi, +- struct nft_chain_hook *hook, bool create) ++ struct nft_chain_hook *hook, u8 family, ++ bool create) + { + struct nlattr *ha[NFTA_HOOK_MAX + 1]; + const struct nf_chain_type *type; +@@ -1321,10 +1317,10 @@ static int nft_chain_parse_hook(struct n + hook->num = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM])); + hook->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY])); + +- type = chain_type[afi->family][NFT_CHAIN_T_DEFAULT]; ++ type = chain_type[family][NFT_CHAIN_T_DEFAULT]; + if (nla[NFTA_CHAIN_TYPE]) { + type = nf_tables_chain_type_lookup(nla[NFTA_CHAIN_TYPE], +- afi->family, create); ++ family, create); + if (IS_ERR(type)) + return PTR_ERR(type); + } +@@ -1336,7 +1332,7 @@ static int nft_chain_parse_hook(struct n + hook->type = type; + + hook->dev = NULL; +- if (afi->family == NFPROTO_NETDEV) { ++ if (family == NFPROTO_NETDEV) { + char ifname[IFNAMSIZ]; + + if (!ha[NFTA_HOOK_DEV]) { +@@ -1371,7 +1367,6 @@ static int nf_tables_addchain(struct nft + { + const struct nlattr * const *nla = ctx->nla; + struct nft_table *table = ctx->table; +- struct nft_af_info *afi = ctx->afi; + struct nft_base_chain *basechain; + struct nft_stats __percpu *stats; + struct net *net = ctx->net; +@@ -1385,7 +1380,7 @@ static int nf_tables_addchain(struct nft + struct nft_chain_hook hook; + struct nf_hook_ops *ops; + +- err = nft_chain_parse_hook(net, nla, afi, &hook, create); ++ err = nft_chain_parse_hook(net, nla, &hook, family, create); + if (err < 0) + return err; + +@@ -1478,7 +1473,7 @@ static int nf_tables_updchain(struct nft + if (!nft_is_base_chain(chain)) + return -EBUSY; + +- err = nft_chain_parse_hook(ctx->net, nla, ctx->afi, &hook, ++ err = nft_chain_parse_hook(ctx->net, nla, &hook, ctx->family, + create); + if (err < 0) + return err; +@@ -1571,7 +1566,8 @@ static int nf_tables_newchain(struct net + if (IS_ERR(afi)) + return PTR_ERR(afi); + +- table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask); ++ table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], afi->family, ++ genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -1611,7 +1607,7 @@ static int nf_tables_newchain(struct net + } + } + +- nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, chain, nla); + + if (chain != NULL) { + if (nlh->nlmsg_flags & NLM_F_EXCL) +@@ -1645,7 +1641,8 @@ static int nf_tables_delchain(struct net + if (IS_ERR(afi)) + return PTR_ERR(afi); + +- table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask); ++ table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], afi->family, ++ genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -1657,7 +1654,7 @@ static int nf_tables_delchain(struct net + chain->use > 0) + return -EBUSY; + +- nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, chain, nla); + + use = chain->use; + list_for_each_entry(rule, &chain->rules, list) { +@@ -1822,7 +1819,7 @@ static int nf_tables_expr_parse(const st + if (err < 0) + return err; + +- type = nft_expr_type_get(ctx->afi->family, tb[NFTA_EXPR_NAME]); ++ type = nft_expr_type_get(ctx->family, tb[NFTA_EXPR_NAME]); + if (IS_ERR(type)) + return PTR_ERR(type); + +@@ -2045,7 +2042,7 @@ static void nf_tables_rule_notify(const + goto err; + + err = nf_tables_fill_rule_info(skb, ctx->net, ctx->portid, ctx->seq, +- event, 0, ctx->afi->family, ctx->table, ++ event, 0, ctx->family, ctx->table, + ctx->chain, rule); + if (err < 0) { + kfree_skb(skb); +@@ -2069,7 +2066,6 @@ static int nf_tables_dump_rules(struct s + { + const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); + const struct nft_rule_dump_ctx *ctx = cb->data; +- const struct nft_af_info *afi; + const struct nft_table *table; + const struct nft_chain *chain; + const struct nft_rule *rule; +@@ -2080,39 +2076,37 @@ static int nf_tables_dump_rules(struct s + rcu_read_lock(); + cb->seq = net->nft.base_seq; + +- list_for_each_entry_rcu(afi, &net->nft.af_info, list) { +- if (family != NFPROTO_UNSPEC && family != afi->family) ++ list_for_each_entry_rcu(table, &net->nft.tables, list) { ++ if (family != NFPROTO_UNSPEC && family != table->afi->family) ++ continue; ++ ++ if (ctx && ctx->table && strcmp(ctx->table, table->name) != 0) + continue; + +- list_for_each_entry_rcu(table, &afi->tables, list) { +- if (ctx && ctx->table && +- strcmp(ctx->table, table->name) != 0) ++ list_for_each_entry_rcu(chain, &table->chains, list) { ++ if (ctx && ctx->chain && ++ strcmp(ctx->chain, chain->name) != 0) + continue; + +- list_for_each_entry_rcu(chain, &table->chains, list) { +- if (ctx && ctx->chain && +- strcmp(ctx->chain, chain->name) != 0) +- continue; +- +- list_for_each_entry_rcu(rule, &chain->rules, list) { +- if (!nft_is_active(net, rule)) +- goto cont; +- if (idx < s_idx) +- goto cont; +- if (idx > s_idx) +- memset(&cb->args[1], 0, +- sizeof(cb->args) - sizeof(cb->args[0])); +- if (nf_tables_fill_rule_info(skb, net, NETLINK_CB(cb->skb).portid, +- cb->nlh->nlmsg_seq, +- NFT_MSG_NEWRULE, +- NLM_F_MULTI | NLM_F_APPEND, +- afi->family, table, chain, rule) < 0) +- goto done; ++ list_for_each_entry_rcu(rule, &chain->rules, list) { ++ if (!nft_is_active(net, rule)) ++ goto cont; ++ if (idx < s_idx) ++ goto cont; ++ if (idx > s_idx) ++ memset(&cb->args[1], 0, ++ sizeof(cb->args) - sizeof(cb->args[0])); ++ if (nf_tables_fill_rule_info(skb, net, NETLINK_CB(cb->skb).portid, ++ cb->nlh->nlmsg_seq, ++ NFT_MSG_NEWRULE, ++ NLM_F_MULTI | NLM_F_APPEND, ++ table->afi->family, ++ table, chain, rule) < 0) ++ goto done; + +- nl_dump_check_consistent(cb, nlmsg_hdr(skb)); ++ nl_dump_check_consistent(cb, nlmsg_hdr(skb)); + cont: +- idx++; +- } ++ idx++; + } + } + } +@@ -2190,7 +2184,8 @@ static int nf_tables_getrule(struct net + if (IS_ERR(afi)) + return PTR_ERR(afi); + +- table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask); ++ table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], afi->family, ++ genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -2267,7 +2262,8 @@ static int nf_tables_newrule(struct net + if (IS_ERR(afi)) + return PTR_ERR(afi); + +- table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask); ++ table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], afi->family, ++ genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -2306,7 +2302,7 @@ static int nf_tables_newrule(struct net + return PTR_ERR(old_rule); + } + +- nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, chain, nla); + + n = 0; + size = 0; +@@ -2441,7 +2437,8 @@ static int nf_tables_delrule(struct net + if (IS_ERR(afi)) + return PTR_ERR(afi); + +- table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask); ++ table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], afi->family, ++ genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -2452,7 +2449,7 @@ static int nf_tables_delrule(struct net + return PTR_ERR(chain); + } + +- nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, chain, nla); + + if (chain) { + if (nla[NFTA_RULE_HANDLE]) { +@@ -2650,13 +2647,13 @@ static int nft_ctx_init_from_setattr(str + if (afi == NULL) + return -EAFNOSUPPORT; + +- table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE], +- genmask); ++ table = nf_tables_table_lookup(net, nla[NFTA_SET_TABLE], ++ afi->family, genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + } + +- nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla); ++ nft_ctx_init(ctx, net, skb, nlh, afi->family, table, NULL, nla); + return 0; + } + +@@ -2783,7 +2780,7 @@ static int nf_tables_fill_set(struct sk_ + goto nla_put_failure; + + nfmsg = nlmsg_data(nlh); +- nfmsg->nfgen_family = ctx->afi->family; ++ nfmsg->nfgen_family = ctx->family; + nfmsg->version = NFNETLINK_V0; + nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff); + +@@ -2875,10 +2872,8 @@ static int nf_tables_dump_sets(struct sk + { + const struct nft_set *set; + unsigned int idx, s_idx = cb->args[0]; +- struct nft_af_info *afi; + struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2]; + struct net *net = sock_net(skb->sk); +- int cur_family = cb->args[3]; + struct nft_ctx *ctx = cb->data, ctx_set; + + if (cb->args[1]) +@@ -2887,51 +2882,44 @@ static int nf_tables_dump_sets(struct sk + rcu_read_lock(); + cb->seq = net->nft.base_seq; + +- list_for_each_entry_rcu(afi, &net->nft.af_info, list) { +- if (ctx->afi && ctx->afi != afi) ++ list_for_each_entry_rcu(table, &net->nft.tables, list) { ++ if (ctx->family != NFPROTO_UNSPEC && ++ ctx->family != table->afi->family) + continue; + +- if (cur_family) { +- if (afi->family != cur_family) +- continue; ++ if (ctx->table && ctx->table != table) ++ continue; + +- cur_family = 0; +- } +- list_for_each_entry_rcu(table, &afi->tables, list) { +- if (ctx->table && ctx->table != table) ++ if (cur_table) { ++ if (cur_table != table) + continue; + +- if (cur_table) { +- if (cur_table != table) +- continue; ++ cur_table = NULL; ++ } ++ idx = 0; ++ list_for_each_entry_rcu(set, &table->sets, list) { ++ if (idx < s_idx) ++ goto cont; ++ if (!nft_is_active(net, set)) ++ goto cont; + +- cur_table = NULL; ++ ctx_set = *ctx; ++ ctx_set.table = table; ++ ctx_set.family = table->afi->family; ++ ++ if (nf_tables_fill_set(skb, &ctx_set, set, ++ NFT_MSG_NEWSET, ++ NLM_F_MULTI) < 0) { ++ cb->args[0] = idx; ++ cb->args[2] = (unsigned long) table; ++ goto done; + } +- idx = 0; +- list_for_each_entry_rcu(set, &table->sets, list) { +- if (idx < s_idx) +- goto cont; +- if (!nft_is_active(net, set)) +- goto cont; +- +- ctx_set = *ctx; +- ctx_set.table = table; +- ctx_set.afi = afi; +- if (nf_tables_fill_set(skb, &ctx_set, set, +- NFT_MSG_NEWSET, +- NLM_F_MULTI) < 0) { +- cb->args[0] = idx; +- cb->args[2] = (unsigned long) table; +- cb->args[3] = afi->family; +- goto done; +- } +- nl_dump_check_consistent(cb, nlmsg_hdr(skb)); ++ nl_dump_check_consistent(cb, nlmsg_hdr(skb)); + cont: +- idx++; +- } +- if (s_idx) +- s_idx = 0; ++ idx++; + } ++ if (s_idx) ++ s_idx = 0; + } + cb->args[1] = 1; + done: +@@ -3141,11 +3129,12 @@ static int nf_tables_newset(struct net * + if (IS_ERR(afi)) + return PTR_ERR(afi); + +- table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE], genmask); ++ table = nf_tables_table_lookup(net, nla[NFTA_SET_TABLE], afi->family, ++ genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +- nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); + + set = nf_tables_set_lookup(table, nla[NFTA_SET_NAME], genmask); + if (IS_ERR(set)) { +@@ -3410,12 +3399,12 @@ static int nft_ctx_init_from_elemattr(st + if (IS_ERR(afi)) + return PTR_ERR(afi); + +- table = nf_tables_table_lookup(afi, nla[NFTA_SET_ELEM_LIST_TABLE], +- genmask); ++ table = nf_tables_table_lookup(net, nla[NFTA_SET_ELEM_LIST_TABLE], ++ afi->family, genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +- nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla); ++ nft_ctx_init(ctx, net, skb, nlh, afi->family, table, NULL, nla); + return 0; + } + +@@ -3520,7 +3509,6 @@ static int nf_tables_dump_set(struct sk_ + { + struct nft_set_dump_ctx *dump_ctx = cb->data; + struct net *net = sock_net(skb->sk); +- struct nft_af_info *afi; + struct nft_table *table; + struct nft_set *set; + struct nft_set_dump_args args; +@@ -3532,21 +3520,19 @@ static int nf_tables_dump_set(struct sk_ + int event; + + rcu_read_lock(); +- list_for_each_entry_rcu(afi, &net->nft.af_info, list) { +- if (afi != dump_ctx->ctx.afi) ++ list_for_each_entry_rcu(table, &net->nft.tables, list) { ++ if (dump_ctx->ctx.family != NFPROTO_UNSPEC && ++ dump_ctx->ctx.family != table->afi->family) + continue; + +- list_for_each_entry_rcu(table, &afi->tables, list) { +- if (table != dump_ctx->ctx.table) +- continue; ++ if (table != dump_ctx->ctx.table) ++ continue; + +- list_for_each_entry_rcu(set, &table->sets, list) { +- if (set == dump_ctx->set) { +- set_found = true; +- break; +- } ++ list_for_each_entry_rcu(set, &table->sets, list) { ++ if (set == dump_ctx->set) { ++ set_found = true; ++ break; + } +- break; + } + break; + } +@@ -3566,7 +3552,7 @@ static int nf_tables_dump_set(struct sk_ + goto nla_put_failure; + + nfmsg = nlmsg_data(nlh); +- nfmsg->nfgen_family = afi->family; ++ nfmsg->nfgen_family = table->afi->family; + nfmsg->version = NFNETLINK_V0; + nfmsg->res_id = htons(net->nft.base_seq & 0xffff); + +@@ -3668,7 +3654,7 @@ static int nf_tables_fill_setelem_info(s + goto nla_put_failure; + + nfmsg = nlmsg_data(nlh); +- nfmsg->nfgen_family = ctx->afi->family; ++ nfmsg->nfgen_family = ctx->family; + nfmsg->version = NFNETLINK_V0; + nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff); + +@@ -3912,7 +3898,7 @@ static int nft_add_set_elem(struct nft_c + list_for_each_entry(binding, &set->bindings, list) { + struct nft_ctx bind_ctx = { + .net = ctx->net, +- .afi = ctx->afi, ++ .family = ctx->family, + .table = ctx->table, + .chain = (struct nft_chain *)binding->chain, + }; +@@ -4459,7 +4445,8 @@ static int nf_tables_newobj(struct net * + if (IS_ERR(afi)) + return PTR_ERR(afi); + +- table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask); ++ table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], afi->family, ++ genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -4477,7 +4464,7 @@ static int nf_tables_newobj(struct net * + return 0; + } + +- nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); + + type = nft_obj_type_get(objtype); + if (IS_ERR(type)) +@@ -4554,7 +4541,6 @@ struct nft_obj_filter { + static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) + { + const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); +- const struct nft_af_info *afi; + const struct nft_table *table; + unsigned int idx = 0, s_idx = cb->args[0]; + struct nft_obj_filter *filter = cb->data; +@@ -4569,38 +4555,37 @@ static int nf_tables_dump_obj(struct sk_ + rcu_read_lock(); + cb->seq = net->nft.base_seq; + +- list_for_each_entry_rcu(afi, &net->nft.af_info, list) { +- if (family != NFPROTO_UNSPEC && family != afi->family) ++ list_for_each_entry_rcu(table, &net->nft.tables, list) { ++ if (family != NFPROTO_UNSPEC && family != table->afi->family) + continue; + +- list_for_each_entry_rcu(table, &afi->tables, list) { +- list_for_each_entry_rcu(obj, &table->objects, list) { +- if (!nft_is_active(net, obj)) +- goto cont; +- if (idx < s_idx) +- goto cont; +- if (idx > s_idx) +- memset(&cb->args[1], 0, +- sizeof(cb->args) - sizeof(cb->args[0])); +- if (filter && filter->table[0] && +- strcmp(filter->table, table->name)) +- goto cont; +- if (filter && +- filter->type != NFT_OBJECT_UNSPEC && +- obj->ops->type->type != filter->type) +- goto cont; ++ list_for_each_entry_rcu(obj, &table->objects, list) { ++ if (!nft_is_active(net, obj)) ++ goto cont; ++ if (idx < s_idx) ++ goto cont; ++ if (idx > s_idx) ++ memset(&cb->args[1], 0, ++ sizeof(cb->args) - sizeof(cb->args[0])); ++ if (filter && filter->table[0] && ++ strcmp(filter->table, table->name)) ++ goto cont; ++ if (filter && ++ filter->type != NFT_OBJECT_UNSPEC && ++ obj->ops->type->type != filter->type) ++ goto cont; + +- if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid, +- cb->nlh->nlmsg_seq, +- NFT_MSG_NEWOBJ, +- NLM_F_MULTI | NLM_F_APPEND, +- afi->family, table, obj, reset) < 0) +- goto done; ++ if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid, ++ cb->nlh->nlmsg_seq, ++ NFT_MSG_NEWOBJ, ++ NLM_F_MULTI | NLM_F_APPEND, ++ table->afi->family, table, ++ obj, reset) < 0) ++ goto done; + +- nl_dump_check_consistent(cb, nlmsg_hdr(skb)); ++ nl_dump_check_consistent(cb, nlmsg_hdr(skb)); + cont: +- idx++; +- } ++ idx++; + } + } + done: +@@ -4687,7 +4672,8 @@ static int nf_tables_getobj(struct net * + if (IS_ERR(afi)) + return PTR_ERR(afi); + +- table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask); ++ table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], afi->family, ++ genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -4747,7 +4733,8 @@ static int nf_tables_delobj(struct net * + if (IS_ERR(afi)) + return PTR_ERR(afi); + +- table = nf_tables_table_lookup(afi, nla[NFTA_OBJ_TABLE], genmask); ++ table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], afi->family, ++ genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -4758,7 +4745,7 @@ static int nf_tables_delobj(struct net * + if (obj->use > 0) + return -EBUSY; + +- nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); + + return nft_delobj(&ctx, obj); + } +@@ -4796,7 +4783,7 @@ static void nf_tables_obj_notify(const s + struct nft_object *obj, int event) + { + nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event, +- ctx->afi->family, ctx->report, GFP_KERNEL); ++ ctx->family, ctx->report, GFP_KERNEL); + } + + /* +@@ -4986,7 +4973,7 @@ void nft_flow_table_iterate(struct net * + + rcu_read_lock(); + list_for_each_entry_rcu(afi, &net->nft.af_info, list) { +- list_for_each_entry_rcu(table, &afi->tables, list) { ++ list_for_each_entry_rcu(table, &net->nft.tables, list) { + list_for_each_entry_rcu(flowtable, &table->flowtables, list) { + iter(&flowtable->data, data); + } +@@ -5034,7 +5021,8 @@ static int nf_tables_newflowtable(struct + if (IS_ERR(afi)) + return PTR_ERR(afi); + +- table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask); ++ table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], ++ afi->family, genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -5051,7 +5039,7 @@ static int nf_tables_newflowtable(struct + return 0; + } + +- nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); + + flowtable = kzalloc(sizeof(*flowtable), GFP_KERNEL); + if (!flowtable) +@@ -5132,7 +5120,8 @@ static int nf_tables_delflowtable(struct + if (IS_ERR(afi)) + return PTR_ERR(afi); + +- table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask); ++ table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], ++ afi->family, genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -5143,7 +5132,7 @@ static int nf_tables_delflowtable(struct + if (flowtable->use > 0) + return -EBUSY; + +- nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); + + return nft_delflowtable(&ctx, flowtable); + } +@@ -5212,40 +5201,37 @@ static int nf_tables_dump_flowtable(stru + struct net *net = sock_net(skb->sk); + int family = nfmsg->nfgen_family; + struct nft_flowtable *flowtable; +- const struct nft_af_info *afi; + const struct nft_table *table; + + rcu_read_lock(); + cb->seq = net->nft.base_seq; + +- list_for_each_entry_rcu(afi, &net->nft.af_info, list) { +- if (family != NFPROTO_UNSPEC && family != afi->family) ++ list_for_each_entry_rcu(table, &net->nft.tables, list) { ++ if (family != NFPROTO_UNSPEC && family != table->afi->family) + continue; + +- list_for_each_entry_rcu(table, &afi->tables, list) { +- list_for_each_entry_rcu(flowtable, &table->flowtables, list) { +- if (!nft_is_active(net, flowtable)) +- goto cont; +- if (idx < s_idx) +- goto cont; +- if (idx > s_idx) +- memset(&cb->args[1], 0, +- sizeof(cb->args) - sizeof(cb->args[0])); +- if (filter && filter->table[0] && +- strcmp(filter->table, table->name)) +- goto cont; ++ list_for_each_entry_rcu(flowtable, &table->flowtables, list) { ++ if (!nft_is_active(net, flowtable)) ++ goto cont; ++ if (idx < s_idx) ++ goto cont; ++ if (idx > s_idx) ++ memset(&cb->args[1], 0, ++ sizeof(cb->args) - sizeof(cb->args[0])); ++ if (filter && filter->table[0] && ++ strcmp(filter->table, table->name)) ++ goto cont; + +- if (nf_tables_fill_flowtable_info(skb, net, NETLINK_CB(cb->skb).portid, +- cb->nlh->nlmsg_seq, +- NFT_MSG_NEWFLOWTABLE, +- NLM_F_MULTI | NLM_F_APPEND, +- afi->family, flowtable) < 0) +- goto done; ++ if (nf_tables_fill_flowtable_info(skb, net, NETLINK_CB(cb->skb).portid, ++ cb->nlh->nlmsg_seq, ++ NFT_MSG_NEWFLOWTABLE, ++ NLM_F_MULTI | NLM_F_APPEND, ++ table->afi->family, flowtable) < 0) ++ goto done; + +- nl_dump_check_consistent(cb, nlmsg_hdr(skb)); ++ nl_dump_check_consistent(cb, nlmsg_hdr(skb)); + cont: +- idx++; +- } ++ idx++; + } + } + done: +@@ -5330,7 +5316,8 @@ static int nf_tables_getflowtable(struct + if (IS_ERR(afi)) + return PTR_ERR(afi); + +- table = nf_tables_table_lookup(afi, nla[NFTA_FLOWTABLE_TABLE], genmask); ++ table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], ++ afi->family, genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -5373,7 +5360,7 @@ static void nf_tables_flowtable_notify(s + + err = nf_tables_fill_flowtable_info(skb, ctx->net, ctx->portid, + ctx->seq, event, 0, +- ctx->afi->family, flowtable); ++ ctx->family, flowtable); + if (err < 0) { + kfree_skb(skb); + goto err; +@@ -5451,17 +5438,14 @@ static int nf_tables_flowtable_event(str + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct nft_flowtable *flowtable; + struct nft_table *table; +- struct nft_af_info *afi; + + if (event != NETDEV_UNREGISTER) + return 0; + + nfnl_lock(NFNL_SUBSYS_NFTABLES); +- list_for_each_entry(afi, &dev_net(dev)->nft.af_info, list) { +- list_for_each_entry(table, &afi->tables, list) { +- list_for_each_entry(flowtable, &table->flowtables, list) { +- nft_flowtable_event(event, dev, flowtable); +- } ++ list_for_each_entry(table, &dev_net(dev)->nft.tables, list) { ++ list_for_each_entry(flowtable, &table->flowtables, list) { ++ nft_flowtable_event(event, dev, flowtable); + } + } + nfnl_unlock(NFNL_SUBSYS_NFTABLES); +@@ -6480,6 +6464,7 @@ EXPORT_SYMBOL_GPL(nft_data_dump); + static int __net_init nf_tables_init_net(struct net *net) + { + INIT_LIST_HEAD(&net->nft.af_info); ++ INIT_LIST_HEAD(&net->nft.tables); + INIT_LIST_HEAD(&net->nft.commit_list); + net->nft.base_seq = 1; + return 0; +@@ -6516,10 +6501,10 @@ static void __nft_release_afinfo(struct + struct nft_set *set, *ns; + struct nft_ctx ctx = { + .net = net, +- .afi = afi, ++ .family = afi->family, + }; + +- list_for_each_entry_safe(table, nt, &afi->tables, list) { ++ list_for_each_entry_safe(table, nt, &net->nft.tables, list) { + list_for_each_entry(chain, &table->chains, list) + nf_tables_unregister_hook(net, table, chain); + list_for_each_entry(flowtable, &table->flowtables, list) +--- a/net/netfilter/nf_tables_netdev.c ++++ b/net/netfilter/nf_tables_netdev.c +@@ -107,7 +107,6 @@ static int nf_tables_netdev_event(struct + unsigned long event, void *ptr) + { + struct net_device *dev = netdev_notifier_info_to_dev(ptr); +- struct nft_af_info *afi; + struct nft_table *table; + struct nft_chain *chain, *nr; + struct nft_ctx ctx = { +@@ -119,20 +118,18 @@ static int nf_tables_netdev_event(struct + return NOTIFY_DONE; + + nfnl_lock(NFNL_SUBSYS_NFTABLES); +- list_for_each_entry(afi, &dev_net(dev)->nft.af_info, list) { +- ctx.afi = afi; +- if (afi->family != NFPROTO_NETDEV) ++ list_for_each_entry(table, &ctx.net->nft.tables, list) { ++ if (table->afi->family != NFPROTO_NETDEV) + continue; + +- list_for_each_entry(table, &afi->tables, list) { +- ctx.table = table; +- list_for_each_entry_safe(chain, nr, &table->chains, list) { +- if (!nft_is_base_chain(chain)) +- continue; ++ ctx.family = table->afi->family; ++ ctx.table = table; ++ list_for_each_entry_safe(chain, nr, &table->chains, list) { ++ if (!nft_is_base_chain(chain)) ++ continue; + +- ctx.chain = chain; +- nft_netdev_event(event, dev, &ctx); +- } ++ ctx.chain = chain; ++ nft_netdev_event(event, dev, &ctx); + } + } + nfnl_unlock(NFNL_SUBSYS_NFTABLES); +--- a/net/netfilter/nft_compat.c ++++ b/net/netfilter/nft_compat.c +@@ -144,7 +144,7 @@ nft_target_set_tgchk_param(struct xt_tgc + { + par->net = ctx->net; + par->table = ctx->table->name; +- switch (ctx->afi->family) { ++ switch (ctx->family) { + case AF_INET: + entry->e4.ip.proto = proto; + entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0; +@@ -175,7 +175,7 @@ nft_target_set_tgchk_param(struct xt_tgc + } else { + par->hook_mask = 0; + } +- par->family = ctx->afi->family; ++ par->family = ctx->family; + par->nft_compat = true; + } + +@@ -267,7 +267,7 @@ nft_target_destroy(const struct nft_ctx + par.net = ctx->net; + par.target = target; + par.targinfo = info; +- par.family = ctx->afi->family; ++ par.family = ctx->family; + if (par.target->destroy != NULL) + par.target->destroy(&par); + +@@ -358,7 +358,7 @@ nft_match_set_mtchk_param(struct xt_mtch + { + par->net = ctx->net; + par->table = ctx->table->name; +- switch (ctx->afi->family) { ++ switch (ctx->family) { + case AF_INET: + entry->e4.ip.proto = proto; + entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0; +@@ -389,7 +389,7 @@ nft_match_set_mtchk_param(struct xt_mtch + } else { + par->hook_mask = 0; + } +- par->family = ctx->afi->family; ++ par->family = ctx->family; + par->nft_compat = true; + } + +@@ -446,7 +446,7 @@ nft_match_destroy(const struct nft_ctx * + par.net = ctx->net; + par.match = match; + par.matchinfo = info; +- par.family = ctx->afi->family; ++ par.family = ctx->family; + if (par.match->destroy != NULL) + par.match->destroy(&par); + +@@ -648,7 +648,7 @@ nft_match_select_ops(const struct nft_ct + + mt_name = nla_data(tb[NFTA_MATCH_NAME]); + rev = ntohl(nla_get_be32(tb[NFTA_MATCH_REV])); +- family = ctx->afi->family; ++ family = ctx->family; + + /* Re-use the existing match if it's already loaded. */ + list_for_each_entry(nft_match, &nft_match_list, head) { +@@ -733,7 +733,7 @@ nft_target_select_ops(const struct nft_c + + tg_name = nla_data(tb[NFTA_TARGET_NAME]); + rev = ntohl(nla_get_be32(tb[NFTA_TARGET_REV])); +- family = ctx->afi->family; ++ family = ctx->family; + + /* Re-use the existing target if it's already loaded. */ + list_for_each_entry(nft_target, &nft_target_list, head) { +--- a/net/netfilter/nft_ct.c ++++ b/net/netfilter/nft_ct.c +@@ -405,7 +405,7 @@ static int nft_ct_get_init(const struct + if (tb[NFTA_CT_DIRECTION] == NULL) + return -EINVAL; + +- switch (ctx->afi->family) { ++ switch (ctx->family) { + case NFPROTO_IPV4: + len = FIELD_SIZEOF(struct nf_conntrack_tuple, + src.u3.ip); +@@ -456,7 +456,7 @@ static int nft_ct_get_init(const struct + if (err < 0) + return err; + +- err = nf_ct_netns_get(ctx->net, ctx->afi->family); ++ err = nf_ct_netns_get(ctx->net, ctx->family); + if (err < 0) + return err; + +@@ -550,7 +550,7 @@ static int nft_ct_set_init(const struct + if (err < 0) + goto err1; + +- err = nf_ct_netns_get(ctx->net, ctx->afi->family); ++ err = nf_ct_netns_get(ctx->net, ctx->family); + if (err < 0) + goto err1; + +@@ -564,7 +564,7 @@ err1: + static void nft_ct_get_destroy(const struct nft_ctx *ctx, + const struct nft_expr *expr) + { +- nf_ct_netns_put(ctx->net, ctx->afi->family); ++ nf_ct_netns_put(ctx->net, ctx->family); + } + + static void nft_ct_set_destroy(const struct nft_ctx *ctx, +@@ -573,7 +573,7 @@ static void nft_ct_set_destroy(const str + struct nft_ct *priv = nft_expr_priv(expr); + + __nft_ct_set_destroy(ctx, priv); +- nf_ct_netns_put(ctx->net, ctx->afi->family); ++ nf_ct_netns_put(ctx->net, ctx->family); + } + + static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr) +@@ -734,7 +734,7 @@ static int nft_ct_helper_obj_init(const + struct nft_ct_helper_obj *priv = nft_obj_data(obj); + struct nf_conntrack_helper *help4, *help6; + char name[NF_CT_HELPER_NAME_LEN]; +- int family = ctx->afi->family; ++ int family = ctx->family; + + if (!tb[NFTA_CT_HELPER_NAME] || !tb[NFTA_CT_HELPER_L4PROTO]) + return -EINVAL; +@@ -753,14 +753,14 @@ static int nft_ct_helper_obj_init(const + + switch (family) { + case NFPROTO_IPV4: +- if (ctx->afi->family == NFPROTO_IPV6) ++ if (ctx->family == NFPROTO_IPV6) + return -EINVAL; + + help4 = nf_conntrack_helper_try_module_get(name, family, + priv->l4proto); + break; + case NFPROTO_IPV6: +- if (ctx->afi->family == NFPROTO_IPV4) ++ if (ctx->family == NFPROTO_IPV4) + return -EINVAL; + + help6 = nf_conntrack_helper_try_module_get(name, family, +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -151,7 +151,7 @@ static int nft_flow_offload_init(const s + priv->flowtable = flowtable; + flowtable->use++; + +- return nf_ct_netns_get(ctx->net, ctx->afi->family); ++ return nf_ct_netns_get(ctx->net, ctx->family); + } + + static void nft_flow_offload_destroy(const struct nft_ctx *ctx, +@@ -160,7 +160,7 @@ static void nft_flow_offload_destroy(con + struct nft_flow_offload *priv = nft_expr_priv(expr); + + priv->flowtable->use--; +- nf_ct_netns_put(ctx->net, ctx->afi->family); ++ nf_ct_netns_put(ctx->net, ctx->family); + } + + static int nft_flow_offload_dump(struct sk_buff *skb, const struct nft_expr *expr) +--- a/net/netfilter/nft_log.c ++++ b/net/netfilter/nft_log.c +@@ -112,7 +112,7 @@ static int nft_log_init(const struct nft + break; + } + +- err = nf_logger_find_get(ctx->afi->family, li->type); ++ err = nf_logger_find_get(ctx->family, li->type); + if (err < 0) + goto err1; + +@@ -133,7 +133,7 @@ static void nft_log_destroy(const struct + if (priv->prefix != nft_log_null_prefix) + kfree(priv->prefix); + +- nf_logger_put(ctx->afi->family, li->type); ++ nf_logger_put(ctx->family, li->type); + } + + static int nft_log_dump(struct sk_buff *skb, const struct nft_expr *expr) +--- a/net/netfilter/nft_masq.c ++++ b/net/netfilter/nft_masq.c +@@ -73,7 +73,7 @@ int nft_masq_init(const struct nft_ctx * + } + } + +- return nf_ct_netns_get(ctx->net, ctx->afi->family); ++ return nf_ct_netns_get(ctx->net, ctx->family); + } + EXPORT_SYMBOL_GPL(nft_masq_init); + +--- a/net/netfilter/nft_meta.c ++++ b/net/netfilter/nft_meta.c +@@ -339,7 +339,7 @@ static int nft_meta_get_validate(const s + if (priv->key != NFT_META_SECPATH) + return 0; + +- switch (ctx->afi->family) { ++ switch (ctx->family) { + case NFPROTO_NETDEV: + hooks = 1 << NF_NETDEV_INGRESS; + break; +@@ -370,7 +370,7 @@ int nft_meta_set_validate(const struct n + if (priv->key != NFT_META_PKTTYPE) + return 0; + +- switch (ctx->afi->family) { ++ switch (ctx->family) { + case NFPROTO_BRIDGE: + hooks = 1 << NF_BR_PRE_ROUTING; + break; +--- a/net/netfilter/nft_nat.c ++++ b/net/netfilter/nft_nat.c +@@ -142,7 +142,7 @@ static int nft_nat_init(const struct nft + return -EINVAL; + + family = ntohl(nla_get_be32(tb[NFTA_NAT_FAMILY])); +- if (family != ctx->afi->family) ++ if (family != ctx->family) + return -EOPNOTSUPP; + + switch (family) { +--- a/net/netfilter/nft_redir.c ++++ b/net/netfilter/nft_redir.c +@@ -75,7 +75,7 @@ int nft_redir_init(const struct nft_ctx + return -EINVAL; + } + +- return nf_ct_netns_get(ctx->net, ctx->afi->family); ++ return nf_ct_netns_get(ctx->net, ctx->family); + } + EXPORT_SYMBOL_GPL(nft_redir_init); + diff --git a/target/linux/generic/backport-4.14/336-netfilter-exit_net-cleanup-check-added.patch b/target/linux/generic/backport-4.14/336-netfilter-exit_net-cleanup-check-added.patch new file mode 100644 index 000000000..8a2dbd8d5 --- /dev/null +++ b/target/linux/generic/backport-4.14/336-netfilter-exit_net-cleanup-check-added.patch @@ -0,0 +1,100 @@ +From: Vasily Averin +Date: Sun, 12 Nov 2017 14:32:37 +0300 +Subject: [PATCH] netfilter: exit_net cleanup check added + +Be sure that lists initialized in net_init hook was return to initial +state. + +Signed-off-by: Vasily Averin +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c ++++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c +@@ -829,6 +829,7 @@ static void clusterip_net_exit(struct ne + cn->procdir = NULL; + #endif + nf_unregister_net_hook(net, &cip_arp_ops); ++ WARN_ON_ONCE(!list_empty(&cn->configs)); + } + + static struct pernet_operations clusterip_net_ops = { +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -6470,6 +6470,12 @@ static int __net_init nf_tables_init_net + return 0; + } + ++static void __net_exit nf_tables_exit_net(struct net *net) ++{ ++ WARN_ON_ONCE(!list_empty(&net->nft.af_info)); ++ WARN_ON_ONCE(!list_empty(&net->nft.commit_list)); ++} ++ + int __nft_release_basechain(struct nft_ctx *ctx) + { + struct nft_rule *rule, *nr; +@@ -6547,6 +6553,7 @@ static void __nft_release_afinfo(struct + + static struct pernet_operations nf_tables_net_ops = { + .init = nf_tables_init_net, ++ .exit = nf_tables_exit_net, + }; + + static int __init nf_tables_module_init(void) +--- a/net/netfilter/nfnetlink_log.c ++++ b/net/netfilter/nfnetlink_log.c +@@ -1093,10 +1093,15 @@ static int __net_init nfnl_log_net_init( + + static void __net_exit nfnl_log_net_exit(struct net *net) + { ++ struct nfnl_log_net *log = nfnl_log_pernet(net); ++ unsigned int i; ++ + #ifdef CONFIG_PROC_FS + remove_proc_entry("nfnetlink_log", net->nf.proc_netfilter); + #endif + nf_log_unset(net, &nfulnl_logger); ++ for (i = 0; i < INSTANCE_BUCKETS; i++) ++ WARN_ON_ONCE(!hlist_empty(&log->instance_table[i])); + } + + static struct pernet_operations nfnl_log_net_ops = { +--- a/net/netfilter/nfnetlink_queue.c ++++ b/net/netfilter/nfnetlink_queue.c +@@ -1512,10 +1512,15 @@ static int __net_init nfnl_queue_net_ini + + static void __net_exit nfnl_queue_net_exit(struct net *net) + { ++ struct nfnl_queue_net *q = nfnl_queue_pernet(net); ++ unsigned int i; ++ + nf_unregister_queue_handler(net); + #ifdef CONFIG_PROC_FS + remove_proc_entry("nfnetlink_queue", net->nf.proc_netfilter); + #endif ++ for (i = 0; i < INSTANCE_BUCKETS; i++) ++ WARN_ON_ONCE(!hlist_empty(&q->instance_table[i])); + } + + static void nfnl_queue_net_exit_batch(struct list_head *net_exit_list) +--- a/net/netfilter/x_tables.c ++++ b/net/netfilter/x_tables.c +@@ -1719,8 +1719,17 @@ static int __net_init xt_net_init(struct + return 0; + } + ++static void __net_exit xt_net_exit(struct net *net) ++{ ++ int i; ++ ++ for (i = 0; i < NFPROTO_NUMPROTO; i++) ++ WARN_ON_ONCE(!list_empty(&net->xt.tables[i])); ++} ++ + static struct pernet_operations xt_net_ops = { + .init = xt_net_init, ++ .exit = xt_net_exit, + }; + + static int __init xt_init(void) diff --git a/target/linux/generic/backport-4.14/337-netfilter-nf_tables-get-rid-of-pernet-families.patch b/target/linux/generic/backport-4.14/337-netfilter-nf_tables-get-rid-of-pernet-families.patch new file mode 100644 index 000000000..87f804af0 --- /dev/null +++ b/target/linux/generic/backport-4.14/337-netfilter-nf_tables-get-rid-of-pernet-families.patch @@ -0,0 +1,598 @@ +From: Pablo Neira Ayuso +Date: Tue, 9 Jan 2018 02:42:11 +0100 +Subject: [PATCH] netfilter: nf_tables: get rid of pernet families + +Now that we have a single table list for each netns, we can get rid of +one pointer per family and the global afinfo list, thus, shrinking +struct netns for nftables that now becomes 64 bytes smaller. + +And call __nft_release_afinfo() from __net_exit path accordingly to +release netnamespace objects on removal. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -969,8 +969,8 @@ struct nft_af_info { + struct module *owner; + }; + +-int nft_register_afinfo(struct net *, struct nft_af_info *); +-void nft_unregister_afinfo(struct net *, struct nft_af_info *); ++int nft_register_afinfo(struct nft_af_info *); ++void nft_unregister_afinfo(struct nft_af_info *); + + int nft_register_chain_type(const struct nf_chain_type *); + void nft_unregister_chain_type(const struct nf_chain_type *); +--- a/include/net/netns/nftables.h ++++ b/include/net/netns/nftables.h +@@ -7,15 +7,8 @@ + struct nft_af_info; + + struct netns_nftables { +- struct list_head af_info; + struct list_head tables; + struct list_head commit_list; +- struct nft_af_info *ipv4; +- struct nft_af_info *ipv6; +- struct nft_af_info *inet; +- struct nft_af_info *arp; +- struct nft_af_info *bridge; +- struct nft_af_info *netdev; + unsigned int base_seq; + u8 gencursor; + }; +--- a/net/bridge/netfilter/nf_tables_bridge.c ++++ b/net/bridge/netfilter/nf_tables_bridge.c +@@ -47,34 +47,6 @@ static struct nft_af_info nft_af_bridge + .owner = THIS_MODULE, + }; + +-static int nf_tables_bridge_init_net(struct net *net) +-{ +- net->nft.bridge = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); +- if (net->nft.bridge == NULL) +- return -ENOMEM; +- +- memcpy(net->nft.bridge, &nft_af_bridge, sizeof(nft_af_bridge)); +- +- if (nft_register_afinfo(net, net->nft.bridge) < 0) +- goto err; +- +- return 0; +-err: +- kfree(net->nft.bridge); +- return -ENOMEM; +-} +- +-static void nf_tables_bridge_exit_net(struct net *net) +-{ +- nft_unregister_afinfo(net, net->nft.bridge); +- kfree(net->nft.bridge); +-} +- +-static struct pernet_operations nf_tables_bridge_net_ops = { +- .init = nf_tables_bridge_init_net, +- .exit = nf_tables_bridge_exit_net, +-}; +- + static const struct nf_chain_type filter_bridge = { + .name = "filter", + .type = NFT_CHAIN_T_DEFAULT, +@@ -98,17 +70,17 @@ static int __init nf_tables_bridge_init( + { + int ret; + +- ret = nft_register_chain_type(&filter_bridge); ++ ret = nft_register_afinfo(&nft_af_bridge); + if (ret < 0) + return ret; + +- ret = register_pernet_subsys(&nf_tables_bridge_net_ops); ++ ret = nft_register_chain_type(&filter_bridge); + if (ret < 0) +- goto err_register_subsys; ++ goto err_register_chain; + + return ret; + +-err_register_subsys: ++err_register_chain: + nft_unregister_chain_type(&filter_bridge); + + return ret; +@@ -116,8 +88,8 @@ err_register_subsys: + + static void __exit nf_tables_bridge_exit(void) + { +- unregister_pernet_subsys(&nf_tables_bridge_net_ops); + nft_unregister_chain_type(&filter_bridge); ++ nft_unregister_afinfo(&nft_af_bridge); + } + + module_init(nf_tables_bridge_init); +--- a/net/ipv4/netfilter/nf_tables_arp.c ++++ b/net/ipv4/netfilter/nf_tables_arp.c +@@ -32,34 +32,6 @@ static struct nft_af_info nft_af_arp __r + .owner = THIS_MODULE, + }; + +-static int nf_tables_arp_init_net(struct net *net) +-{ +- net->nft.arp = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); +- if (net->nft.arp== NULL) +- return -ENOMEM; +- +- memcpy(net->nft.arp, &nft_af_arp, sizeof(nft_af_arp)); +- +- if (nft_register_afinfo(net, net->nft.arp) < 0) +- goto err; +- +- return 0; +-err: +- kfree(net->nft.arp); +- return -ENOMEM; +-} +- +-static void nf_tables_arp_exit_net(struct net *net) +-{ +- nft_unregister_afinfo(net, net->nft.arp); +- kfree(net->nft.arp); +-} +- +-static struct pernet_operations nf_tables_arp_net_ops = { +- .init = nf_tables_arp_init_net, +- .exit = nf_tables_arp_exit_net, +-}; +- + static const struct nf_chain_type filter_arp = { + .name = "filter", + .type = NFT_CHAIN_T_DEFAULT, +@@ -77,21 +49,26 @@ static int __init nf_tables_arp_init(voi + { + int ret; + +- ret = nft_register_chain_type(&filter_arp); ++ ret = nft_register_afinfo(&nft_af_arp); + if (ret < 0) + return ret; + +- ret = register_pernet_subsys(&nf_tables_arp_net_ops); ++ ret = nft_register_chain_type(&filter_arp); + if (ret < 0) +- nft_unregister_chain_type(&filter_arp); ++ goto err_register_chain; ++ ++ return 0; ++ ++err_register_chain: ++ nft_unregister_chain_type(&filter_arp); + + return ret; + } + + static void __exit nf_tables_arp_exit(void) + { +- unregister_pernet_subsys(&nf_tables_arp_net_ops); + nft_unregister_chain_type(&filter_arp); ++ nft_unregister_afinfo(&nft_af_arp); + } + + module_init(nf_tables_arp_init); +--- a/net/ipv4/netfilter/nf_tables_ipv4.c ++++ b/net/ipv4/netfilter/nf_tables_ipv4.c +@@ -35,34 +35,6 @@ static struct nft_af_info nft_af_ipv4 __ + .owner = THIS_MODULE, + }; + +-static int nf_tables_ipv4_init_net(struct net *net) +-{ +- net->nft.ipv4 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); +- if (net->nft.ipv4 == NULL) +- return -ENOMEM; +- +- memcpy(net->nft.ipv4, &nft_af_ipv4, sizeof(nft_af_ipv4)); +- +- if (nft_register_afinfo(net, net->nft.ipv4) < 0) +- goto err; +- +- return 0; +-err: +- kfree(net->nft.ipv4); +- return -ENOMEM; +-} +- +-static void nf_tables_ipv4_exit_net(struct net *net) +-{ +- nft_unregister_afinfo(net, net->nft.ipv4); +- kfree(net->nft.ipv4); +-} +- +-static struct pernet_operations nf_tables_ipv4_net_ops = { +- .init = nf_tables_ipv4_init_net, +- .exit = nf_tables_ipv4_exit_net, +-}; +- + static const struct nf_chain_type filter_ipv4 = { + .name = "filter", + .type = NFT_CHAIN_T_DEFAULT, +@@ -86,21 +58,25 @@ static int __init nf_tables_ipv4_init(vo + { + int ret; + +- ret = nft_register_chain_type(&filter_ipv4); ++ ret = nft_register_afinfo(&nft_af_ipv4); + if (ret < 0) + return ret; + +- ret = register_pernet_subsys(&nf_tables_ipv4_net_ops); ++ ret = nft_register_chain_type(&filter_ipv4); + if (ret < 0) +- nft_unregister_chain_type(&filter_ipv4); ++ goto err_register_chain; ++ ++ return 0; + ++err_register_chain: ++ nft_unregister_afinfo(&nft_af_ipv4); + return ret; + } + + static void __exit nf_tables_ipv4_exit(void) + { +- unregister_pernet_subsys(&nf_tables_ipv4_net_ops); + nft_unregister_chain_type(&filter_ipv4); ++ nft_unregister_afinfo(&nft_af_ipv4); + } + + module_init(nf_tables_ipv4_init); +--- a/net/ipv6/netfilter/nf_tables_ipv6.c ++++ b/net/ipv6/netfilter/nf_tables_ipv6.c +@@ -33,34 +33,6 @@ static struct nft_af_info nft_af_ipv6 __ + .owner = THIS_MODULE, + }; + +-static int nf_tables_ipv6_init_net(struct net *net) +-{ +- net->nft.ipv6 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); +- if (net->nft.ipv6 == NULL) +- return -ENOMEM; +- +- memcpy(net->nft.ipv6, &nft_af_ipv6, sizeof(nft_af_ipv6)); +- +- if (nft_register_afinfo(net, net->nft.ipv6) < 0) +- goto err; +- +- return 0; +-err: +- kfree(net->nft.ipv6); +- return -ENOMEM; +-} +- +-static void nf_tables_ipv6_exit_net(struct net *net) +-{ +- nft_unregister_afinfo(net, net->nft.ipv6); +- kfree(net->nft.ipv6); +-} +- +-static struct pernet_operations nf_tables_ipv6_net_ops = { +- .init = nf_tables_ipv6_init_net, +- .exit = nf_tables_ipv6_exit_net, +-}; +- + static const struct nf_chain_type filter_ipv6 = { + .name = "filter", + .type = NFT_CHAIN_T_DEFAULT, +@@ -84,20 +56,24 @@ static int __init nf_tables_ipv6_init(vo + { + int ret; + +- ret = nft_register_chain_type(&filter_ipv6); ++ ret = nft_register_afinfo(&nft_af_ipv6); + if (ret < 0) + return ret; + +- ret = register_pernet_subsys(&nf_tables_ipv6_net_ops); ++ ret = nft_register_chain_type(&filter_ipv6); + if (ret < 0) +- nft_unregister_chain_type(&filter_ipv6); ++ goto err_register_chain; ++ ++ return 0; + ++err_register_chain: ++ nft_unregister_afinfo(&nft_af_ipv6); + return ret; + } + + static void __exit nf_tables_ipv6_exit(void) + { +- unregister_pernet_subsys(&nf_tables_ipv6_net_ops); ++ nft_unregister_afinfo(&nft_af_ipv6); + nft_unregister_chain_type(&filter_ipv6); + } + +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -26,6 +26,7 @@ + static LIST_HEAD(nf_tables_expressions); + static LIST_HEAD(nf_tables_objects); + static LIST_HEAD(nf_tables_flowtables); ++static LIST_HEAD(nf_tables_af_info); + + /** + * nft_register_afinfo - register nf_tables address family info +@@ -35,17 +36,15 @@ static LIST_HEAD(nf_tables_flowtables); + * Register the address family for use with nf_tables. Returns zero on + * success or a negative errno code otherwise. + */ +-int nft_register_afinfo(struct net *net, struct nft_af_info *afi) ++int nft_register_afinfo(struct nft_af_info *afi) + { + nfnl_lock(NFNL_SUBSYS_NFTABLES); +- list_add_tail_rcu(&afi->list, &net->nft.af_info); ++ list_add_tail_rcu(&afi->list, &nf_tables_af_info); + nfnl_unlock(NFNL_SUBSYS_NFTABLES); + return 0; + } + EXPORT_SYMBOL_GPL(nft_register_afinfo); + +-static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi); +- + /** + * nft_unregister_afinfo - unregister nf_tables address family info + * +@@ -53,10 +52,9 @@ static void __nft_release_afinfo(struct + * + * Unregister the address family for use with nf_tables. + */ +-void nft_unregister_afinfo(struct net *net, struct nft_af_info *afi) ++void nft_unregister_afinfo(struct nft_af_info *afi) + { + nfnl_lock(NFNL_SUBSYS_NFTABLES); +- __nft_release_afinfo(net, afi); + list_del_rcu(&afi->list); + nfnl_unlock(NFNL_SUBSYS_NFTABLES); + } +@@ -66,7 +64,7 @@ static struct nft_af_info *nft_afinfo_lo + { + struct nft_af_info *afi; + +- list_for_each_entry(afi, &net->nft.af_info, list) { ++ list_for_each_entry(afi, &nf_tables_af_info, list) { + if (afi->family == family) + return afi; + } +@@ -4968,15 +4966,12 @@ void nft_flow_table_iterate(struct net * + void *data) + { + struct nft_flowtable *flowtable; +- const struct nft_af_info *afi; + const struct nft_table *table; + + rcu_read_lock(); +- list_for_each_entry_rcu(afi, &net->nft.af_info, list) { +- list_for_each_entry_rcu(table, &net->nft.tables, list) { +- list_for_each_entry_rcu(flowtable, &table->flowtables, list) { +- iter(&flowtable->data, data); +- } ++ list_for_each_entry_rcu(table, &net->nft.tables, list) { ++ list_for_each_entry_rcu(flowtable, &table->flowtables, list) { ++ iter(&flowtable->data, data); + } + } + rcu_read_unlock(); +@@ -6461,21 +6456,6 @@ int nft_data_dump(struct sk_buff *skb, i + } + EXPORT_SYMBOL_GPL(nft_data_dump); + +-static int __net_init nf_tables_init_net(struct net *net) +-{ +- INIT_LIST_HEAD(&net->nft.af_info); +- INIT_LIST_HEAD(&net->nft.tables); +- INIT_LIST_HEAD(&net->nft.commit_list); +- net->nft.base_seq = 1; +- return 0; +-} +- +-static void __net_exit nf_tables_exit_net(struct net *net) +-{ +- WARN_ON_ONCE(!list_empty(&net->nft.af_info)); +- WARN_ON_ONCE(!list_empty(&net->nft.commit_list)); +-} +- + int __nft_release_basechain(struct nft_ctx *ctx) + { + struct nft_rule *rule, *nr; +@@ -6496,8 +6476,7 @@ int __nft_release_basechain(struct nft_c + } + EXPORT_SYMBOL_GPL(__nft_release_basechain); + +-/* Called by nft_unregister_afinfo() from __net_exit path, nfnl_lock is held. */ +-static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi) ++static void __nft_release_afinfo(struct net *net) + { + struct nft_flowtable *flowtable, *nf; + struct nft_table *table, *nt; +@@ -6507,10 +6486,11 @@ static void __nft_release_afinfo(struct + struct nft_set *set, *ns; + struct nft_ctx ctx = { + .net = net, +- .family = afi->family, + }; + + list_for_each_entry_safe(table, nt, &net->nft.tables, list) { ++ ctx.family = table->afi->family; ++ + list_for_each_entry(chain, &table->chains, list) + nf_tables_unregister_hook(net, table, chain); + list_for_each_entry(flowtable, &table->flowtables, list) +@@ -6551,6 +6531,21 @@ static void __nft_release_afinfo(struct + } + } + ++static int __net_init nf_tables_init_net(struct net *net) ++{ ++ INIT_LIST_HEAD(&net->nft.tables); ++ INIT_LIST_HEAD(&net->nft.commit_list); ++ net->nft.base_seq = 1; ++ return 0; ++} ++ ++static void __net_exit nf_tables_exit_net(struct net *net) ++{ ++ __nft_release_afinfo(net); ++ WARN_ON_ONCE(!list_empty(&net->nft.tables)); ++ WARN_ON_ONCE(!list_empty(&net->nft.commit_list)); ++} ++ + static struct pernet_operations nf_tables_net_ops = { + .init = nf_tables_init_net, + .exit = nf_tables_exit_net, +--- a/net/netfilter/nf_tables_inet.c ++++ b/net/netfilter/nf_tables_inet.c +@@ -43,34 +43,6 @@ static struct nft_af_info nft_af_inet __ + .owner = THIS_MODULE, + }; + +-static int __net_init nf_tables_inet_init_net(struct net *net) +-{ +- net->nft.inet = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); +- if (net->nft.inet == NULL) +- return -ENOMEM; +- memcpy(net->nft.inet, &nft_af_inet, sizeof(nft_af_inet)); +- +- if (nft_register_afinfo(net, net->nft.inet) < 0) +- goto err; +- +- return 0; +- +-err: +- kfree(net->nft.inet); +- return -ENOMEM; +-} +- +-static void __net_exit nf_tables_inet_exit_net(struct net *net) +-{ +- nft_unregister_afinfo(net, net->nft.inet); +- kfree(net->nft.inet); +-} +- +-static struct pernet_operations nf_tables_inet_net_ops = { +- .init = nf_tables_inet_init_net, +- .exit = nf_tables_inet_exit_net, +-}; +- + static const struct nf_chain_type filter_inet = { + .name = "filter", + .type = NFT_CHAIN_T_DEFAULT, +@@ -94,21 +66,24 @@ static int __init nf_tables_inet_init(vo + { + int ret; + +- ret = nft_register_chain_type(&filter_inet); +- if (ret < 0) ++ if (nft_register_afinfo(&nft_af_inet) < 0) + return ret; + +- ret = register_pernet_subsys(&nf_tables_inet_net_ops); ++ ret = nft_register_chain_type(&filter_inet); + if (ret < 0) +- nft_unregister_chain_type(&filter_inet); ++ goto err_register_chain; ++ ++ return ret; + ++err_register_chain: ++ nft_unregister_afinfo(&nft_af_inet); + return ret; + } + + static void __exit nf_tables_inet_exit(void) + { +- unregister_pernet_subsys(&nf_tables_inet_net_ops); + nft_unregister_chain_type(&filter_inet); ++ nft_unregister_afinfo(&nft_af_inet); + } + + module_init(nf_tables_inet_init); +--- a/net/netfilter/nf_tables_netdev.c ++++ b/net/netfilter/nf_tables_netdev.c +@@ -43,34 +43,6 @@ static struct nft_af_info nft_af_netdev + .owner = THIS_MODULE, + }; + +-static int nf_tables_netdev_init_net(struct net *net) +-{ +- net->nft.netdev = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); +- if (net->nft.netdev == NULL) +- return -ENOMEM; +- +- memcpy(net->nft.netdev, &nft_af_netdev, sizeof(nft_af_netdev)); +- +- if (nft_register_afinfo(net, net->nft.netdev) < 0) +- goto err; +- +- return 0; +-err: +- kfree(net->nft.netdev); +- return -ENOMEM; +-} +- +-static void nf_tables_netdev_exit_net(struct net *net) +-{ +- nft_unregister_afinfo(net, net->nft.netdev); +- kfree(net->nft.netdev); +-} +- +-static struct pernet_operations nf_tables_netdev_net_ops = { +- .init = nf_tables_netdev_init_net, +- .exit = nf_tables_netdev_exit_net, +-}; +- + static const struct nf_chain_type nft_filter_chain_netdev = { + .name = "filter", + .type = NFT_CHAIN_T_DEFAULT, +@@ -145,32 +117,32 @@ static int __init nf_tables_netdev_init( + { + int ret; + +- ret = nft_register_chain_type(&nft_filter_chain_netdev); +- if (ret) ++ if (nft_register_afinfo(&nft_af_netdev) < 0) + return ret; + +- ret = register_pernet_subsys(&nf_tables_netdev_net_ops); ++ ret = nft_register_chain_type(&nft_filter_chain_netdev); + if (ret) +- goto err1; ++ goto err_register_chain_type; + + ret = register_netdevice_notifier(&nf_tables_netdev_notifier); + if (ret) +- goto err2; ++ goto err_register_netdevice_notifier; + + return 0; + +-err2: +- unregister_pernet_subsys(&nf_tables_netdev_net_ops); +-err1: ++err_register_netdevice_notifier: + nft_unregister_chain_type(&nft_filter_chain_netdev); ++err_register_chain_type: ++ nft_unregister_afinfo(&nft_af_netdev); ++ + return ret; + } + + static void __exit nf_tables_netdev_exit(void) + { + unregister_netdevice_notifier(&nf_tables_netdev_notifier); +- unregister_pernet_subsys(&nf_tables_netdev_net_ops); + nft_unregister_chain_type(&nft_filter_chain_netdev); ++ nft_unregister_afinfo(&nft_af_netdev); + } + + module_init(nf_tables_netdev_init); diff --git a/target/linux/generic/backport-4.14/338-netfilter-nf_tables-get-rid-of-struct-nft_af_info-ab.patch b/target/linux/generic/backport-4.14/338-netfilter-nf_tables-get-rid-of-struct-nft_af_info-ab.patch new file mode 100644 index 000000000..73cdab0be --- /dev/null +++ b/target/linux/generic/backport-4.14/338-netfilter-nf_tables-get-rid-of-struct-nft_af_info-ab.patch @@ -0,0 +1,1204 @@ +From: Pablo Neira Ayuso +Date: Tue, 9 Jan 2018 02:48:47 +0100 +Subject: [PATCH] netfilter: nf_tables: get rid of struct nft_af_info + abstraction + +Remove the infrastructure to register/unregister nft_af_info structure, +this structure stores no useful information anymore. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -950,28 +950,12 @@ struct nft_table { + struct list_head flowtables; + u64 hgenerator; + u32 use; +- u16 flags:14, ++ u16 family:6, ++ flags:8, + genmask:2; +- struct nft_af_info *afi; + char *name; + }; + +-/** +- * struct nft_af_info - nf_tables address family info +- * +- * @list: used internally +- * @family: address family +- * @owner: module owner +- */ +-struct nft_af_info { +- struct list_head list; +- int family; +- struct module *owner; +-}; +- +-int nft_register_afinfo(struct nft_af_info *); +-void nft_unregister_afinfo(struct nft_af_info *); +- + int nft_register_chain_type(const struct nf_chain_type *); + void nft_unregister_chain_type(const struct nf_chain_type *); + +@@ -1139,9 +1123,6 @@ void nft_trace_notify(struct nft_tracein + #define nft_dereference(p) \ + nfnl_dereference(p, NFNL_SUBSYS_NFTABLES) + +-#define MODULE_ALIAS_NFT_FAMILY(family) \ +- MODULE_ALIAS("nft-afinfo-" __stringify(family)) +- + #define MODULE_ALIAS_NFT_CHAIN(family, name) \ + MODULE_ALIAS("nft-chain-" __stringify(family) "-" name) + +--- a/net/bridge/netfilter/nf_tables_bridge.c ++++ b/net/bridge/netfilter/nf_tables_bridge.c +@@ -42,11 +42,6 @@ nft_do_chain_bridge(void *priv, + return nft_do_chain(&pkt, priv); + } + +-static struct nft_af_info nft_af_bridge __read_mostly = { +- .family = NFPROTO_BRIDGE, +- .owner = THIS_MODULE, +-}; +- + static const struct nf_chain_type filter_bridge = { + .name = "filter", + .type = NFT_CHAIN_T_DEFAULT, +@@ -68,28 +63,12 @@ static const struct nf_chain_type filter + + static int __init nf_tables_bridge_init(void) + { +- int ret; +- +- ret = nft_register_afinfo(&nft_af_bridge); +- if (ret < 0) +- return ret; +- +- ret = nft_register_chain_type(&filter_bridge); +- if (ret < 0) +- goto err_register_chain; +- +- return ret; +- +-err_register_chain: +- nft_unregister_chain_type(&filter_bridge); +- +- return ret; ++ return nft_register_chain_type(&filter_bridge); + } + + static void __exit nf_tables_bridge_exit(void) + { + nft_unregister_chain_type(&filter_bridge); +- nft_unregister_afinfo(&nft_af_bridge); + } + + module_init(nf_tables_bridge_init); +@@ -97,4 +76,4 @@ module_exit(nf_tables_bridge_exit); + + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Patrick McHardy "); +-MODULE_ALIAS_NFT_FAMILY(AF_BRIDGE); ++MODULE_ALIAS_NFT_CHAIN(AF_BRIDGE, "filter"); +--- a/net/ipv4/netfilter/nf_tables_arp.c ++++ b/net/ipv4/netfilter/nf_tables_arp.c +@@ -27,11 +27,6 @@ nft_do_chain_arp(void *priv, + return nft_do_chain(&pkt, priv); + } + +-static struct nft_af_info nft_af_arp __read_mostly = { +- .family = NFPROTO_ARP, +- .owner = THIS_MODULE, +-}; +- + static const struct nf_chain_type filter_arp = { + .name = "filter", + .type = NFT_CHAIN_T_DEFAULT, +@@ -47,28 +42,12 @@ static const struct nf_chain_type filter + + static int __init nf_tables_arp_init(void) + { +- int ret; +- +- ret = nft_register_afinfo(&nft_af_arp); +- if (ret < 0) +- return ret; +- +- ret = nft_register_chain_type(&filter_arp); +- if (ret < 0) +- goto err_register_chain; +- +- return 0; +- +-err_register_chain: +- nft_unregister_chain_type(&filter_arp); +- +- return ret; ++ return nft_register_chain_type(&filter_arp); + } + + static void __exit nf_tables_arp_exit(void) + { + nft_unregister_chain_type(&filter_arp); +- nft_unregister_afinfo(&nft_af_arp); + } + + module_init(nf_tables_arp_init); +@@ -76,4 +55,4 @@ module_exit(nf_tables_arp_exit); + + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Patrick McHardy "); +-MODULE_ALIAS_NFT_FAMILY(3); /* NFPROTO_ARP */ ++MODULE_ALIAS_NFT_CHAIN(3, "filter"); /* NFPROTO_ARP */ +--- a/net/ipv4/netfilter/nf_tables_ipv4.c ++++ b/net/ipv4/netfilter/nf_tables_ipv4.c +@@ -30,11 +30,6 @@ static unsigned int nft_do_chain_ipv4(vo + return nft_do_chain(&pkt, priv); + } + +-static struct nft_af_info nft_af_ipv4 __read_mostly = { +- .family = NFPROTO_IPV4, +- .owner = THIS_MODULE, +-}; +- + static const struct nf_chain_type filter_ipv4 = { + .name = "filter", + .type = NFT_CHAIN_T_DEFAULT, +@@ -56,27 +51,12 @@ static const struct nf_chain_type filter + + static int __init nf_tables_ipv4_init(void) + { +- int ret; +- +- ret = nft_register_afinfo(&nft_af_ipv4); +- if (ret < 0) +- return ret; +- +- ret = nft_register_chain_type(&filter_ipv4); +- if (ret < 0) +- goto err_register_chain; +- +- return 0; +- +-err_register_chain: +- nft_unregister_afinfo(&nft_af_ipv4); +- return ret; ++ return nft_register_chain_type(&filter_ipv4); + } + + static void __exit nf_tables_ipv4_exit(void) + { + nft_unregister_chain_type(&filter_ipv4); +- nft_unregister_afinfo(&nft_af_ipv4); + } + + module_init(nf_tables_ipv4_init); +@@ -84,4 +64,4 @@ module_exit(nf_tables_ipv4_exit); + + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Patrick McHardy "); +-MODULE_ALIAS_NFT_FAMILY(AF_INET); ++MODULE_ALIAS_NFT_CHAIN(AF_INET, "filter"); +--- a/net/ipv6/netfilter/nf_tables_ipv6.c ++++ b/net/ipv6/netfilter/nf_tables_ipv6.c +@@ -28,11 +28,6 @@ static unsigned int nft_do_chain_ipv6(vo + return nft_do_chain(&pkt, priv); + } + +-static struct nft_af_info nft_af_ipv6 __read_mostly = { +- .family = NFPROTO_IPV6, +- .owner = THIS_MODULE, +-}; +- + static const struct nf_chain_type filter_ipv6 = { + .name = "filter", + .type = NFT_CHAIN_T_DEFAULT, +@@ -54,26 +49,11 @@ static const struct nf_chain_type filter + + static int __init nf_tables_ipv6_init(void) + { +- int ret; +- +- ret = nft_register_afinfo(&nft_af_ipv6); +- if (ret < 0) +- return ret; +- +- ret = nft_register_chain_type(&filter_ipv6); +- if (ret < 0) +- goto err_register_chain; +- +- return 0; +- +-err_register_chain: +- nft_unregister_afinfo(&nft_af_ipv6); +- return ret; ++ return nft_register_chain_type(&filter_ipv6); + } + + static void __exit nf_tables_ipv6_exit(void) + { +- nft_unregister_afinfo(&nft_af_ipv6); + nft_unregister_chain_type(&filter_ipv6); + } + +@@ -82,4 +62,4 @@ module_exit(nf_tables_ipv6_exit); + + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Patrick McHardy "); +-MODULE_ALIAS_NFT_FAMILY(AF_INET6); ++MODULE_ALIAS_NFT_CHAIN(AF_INET6, "filter"); +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -26,71 +26,6 @@ + static LIST_HEAD(nf_tables_expressions); + static LIST_HEAD(nf_tables_objects); + static LIST_HEAD(nf_tables_flowtables); +-static LIST_HEAD(nf_tables_af_info); +- +-/** +- * nft_register_afinfo - register nf_tables address family info +- * +- * @afi: address family info to register +- * +- * Register the address family for use with nf_tables. Returns zero on +- * success or a negative errno code otherwise. +- */ +-int nft_register_afinfo(struct nft_af_info *afi) +-{ +- nfnl_lock(NFNL_SUBSYS_NFTABLES); +- list_add_tail_rcu(&afi->list, &nf_tables_af_info); +- nfnl_unlock(NFNL_SUBSYS_NFTABLES); +- return 0; +-} +-EXPORT_SYMBOL_GPL(nft_register_afinfo); +- +-/** +- * nft_unregister_afinfo - unregister nf_tables address family info +- * +- * @afi: address family info to unregister +- * +- * Unregister the address family for use with nf_tables. +- */ +-void nft_unregister_afinfo(struct nft_af_info *afi) +-{ +- nfnl_lock(NFNL_SUBSYS_NFTABLES); +- list_del_rcu(&afi->list); +- nfnl_unlock(NFNL_SUBSYS_NFTABLES); +-} +-EXPORT_SYMBOL_GPL(nft_unregister_afinfo); +- +-static struct nft_af_info *nft_afinfo_lookup(struct net *net, int family) +-{ +- struct nft_af_info *afi; +- +- list_for_each_entry(afi, &nf_tables_af_info, list) { +- if (afi->family == family) +- return afi; +- } +- return NULL; +-} +- +-static struct nft_af_info * +-nf_tables_afinfo_lookup(struct net *net, int family, bool autoload) +-{ +- struct nft_af_info *afi; +- +- afi = nft_afinfo_lookup(net, family); +- if (afi != NULL) +- return afi; +-#ifdef CONFIG_MODULES +- if (autoload) { +- nfnl_unlock(NFNL_SUBSYS_NFTABLES); +- request_module("nft-afinfo-%u", family); +- nfnl_lock(NFNL_SUBSYS_NFTABLES); +- afi = nft_afinfo_lookup(net, family); +- if (afi != NULL) +- return ERR_PTR(-EAGAIN); +- } +-#endif +- return ERR_PTR(-EAFNOSUPPORT); +-} + + static void nft_ctx_init(struct nft_ctx *ctx, + struct net *net, +@@ -390,7 +325,7 @@ static struct nft_table *nft_table_looku + + list_for_each_entry(table, &net->nft.tables, list) { + if (!nla_strcmp(nla, table->name) && +- table->afi->family == family && ++ table->family == family && + nft_active_genmask(table, genmask)) + return table; + } +@@ -531,7 +466,7 @@ static int nf_tables_dump_tables(struct + cb->seq = net->nft.base_seq; + + list_for_each_entry_rcu(table, &net->nft.tables, list) { +- if (family != NFPROTO_UNSPEC && family != table->afi->family) ++ if (family != NFPROTO_UNSPEC && family != table->family) + continue; + + if (idx < s_idx) +@@ -545,7 +480,7 @@ static int nf_tables_dump_tables(struct + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, + NFT_MSG_NEWTABLE, NLM_F_MULTI, +- table->afi->family, table) < 0) ++ table->family, table) < 0) + goto done; + + nl_dump_check_consistent(cb, nlmsg_hdr(skb)); +@@ -565,7 +500,6 @@ static int nf_tables_gettable(struct net + { + const struct nfgenmsg *nfmsg = nlmsg_data(nlh); + u8 genmask = nft_genmask_cur(net); +- const struct nft_af_info *afi; + const struct nft_table *table; + struct sk_buff *skb2; + int family = nfmsg->nfgen_family; +@@ -578,11 +512,7 @@ static int nf_tables_gettable(struct net + return netlink_dump_start(nlsk, skb, nlh, &c); + } + +- afi = nf_tables_afinfo_lookup(net, family, false); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- +- table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], afi->family, ++ table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], family, + genmask); + if (IS_ERR(table)) + return PTR_ERR(table); +@@ -702,19 +632,14 @@ static int nf_tables_newtable(struct net + const struct nfgenmsg *nfmsg = nlmsg_data(nlh); + u8 genmask = nft_genmask_next(net); + const struct nlattr *name; +- struct nft_af_info *afi; + struct nft_table *table; + int family = nfmsg->nfgen_family; + u32 flags = 0; + struct nft_ctx ctx; + int err; + +- afi = nf_tables_afinfo_lookup(net, family, true); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- + name = nla[NFTA_TABLE_NAME]; +- table = nf_tables_table_lookup(net, name, afi->family, genmask); ++ table = nf_tables_table_lookup(net, name, family, genmask); + if (IS_ERR(table)) { + if (PTR_ERR(table) != -ENOENT) + return PTR_ERR(table); +@@ -724,7 +649,7 @@ static int nf_tables_newtable(struct net + if (nlh->nlmsg_flags & NLM_F_REPLACE) + return -EOPNOTSUPP; + +- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); + return nf_tables_updtable(&ctx); + } + +@@ -734,40 +659,34 @@ static int nf_tables_newtable(struct net + return -EINVAL; + } + +- err = -EAFNOSUPPORT; +- if (!try_module_get(afi->owner)) +- goto err1; +- + err = -ENOMEM; + table = kzalloc(sizeof(*table), GFP_KERNEL); + if (table == NULL) +- goto err2; ++ goto err_kzalloc; + + table->name = nla_strdup(name, GFP_KERNEL); + if (table->name == NULL) +- goto err3; ++ goto err_strdup; + + INIT_LIST_HEAD(&table->chains); + INIT_LIST_HEAD(&table->sets); + INIT_LIST_HEAD(&table->objects); + INIT_LIST_HEAD(&table->flowtables); +- table->afi = afi; ++ table->family = family; + table->flags = flags; + +- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); + err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE); + if (err < 0) +- goto err4; ++ goto err_trans; + + list_add_tail_rcu(&table->list, &net->nft.tables); + return 0; +-err4: ++err_trans: + kfree(table->name); +-err3: ++err_strdup: + kfree(table); +-err2: +- module_put(afi->owner); +-err1: ++err_kzalloc: + return err; + } + +@@ -838,10 +757,10 @@ static int nft_flush(struct nft_ctx *ctx + int err = 0; + + list_for_each_entry_safe(table, nt, &ctx->net->nft.tables, list) { +- if (family != AF_UNSPEC && table->afi->family != family) ++ if (family != AF_UNSPEC && table->family != family) + continue; + +- ctx->family = table->afi->family; ++ ctx->family = table->family; + + if (!nft_is_active_next(ctx->net, table)) + continue; +@@ -867,7 +786,6 @@ static int nf_tables_deltable(struct net + { + const struct nfgenmsg *nfmsg = nlmsg_data(nlh); + u8 genmask = nft_genmask_next(net); +- struct nft_af_info *afi; + struct nft_table *table; + int family = nfmsg->nfgen_family; + struct nft_ctx ctx; +@@ -876,11 +794,7 @@ static int nf_tables_deltable(struct net + if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL) + return nft_flush(&ctx, family); + +- afi = nf_tables_afinfo_lookup(net, family, false); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- +- table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], afi->family, ++ table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], family, + genmask); + if (IS_ERR(table)) + return PTR_ERR(table); +@@ -889,7 +803,7 @@ static int nf_tables_deltable(struct net + table->use > 0) + return -EBUSY; + +- ctx.family = afi->family; ++ ctx.family = family; + ctx.table = table; + + return nft_flush_table(&ctx); +@@ -901,7 +815,6 @@ static void nf_tables_table_destroy(stru + + kfree(ctx->table->name); + kfree(ctx->table); +- module_put(ctx->table->afi->owner); + } + + int nft_register_chain_type(const struct nf_chain_type *ctype) +@@ -1130,7 +1043,7 @@ static int nf_tables_dump_chains(struct + cb->seq = net->nft.base_seq; + + list_for_each_entry_rcu(table, &net->nft.tables, list) { +- if (family != NFPROTO_UNSPEC && family != table->afi->family) ++ if (family != NFPROTO_UNSPEC && family != table->family) + continue; + + list_for_each_entry_rcu(chain, &table->chains, list) { +@@ -1146,7 +1059,7 @@ static int nf_tables_dump_chains(struct + cb->nlh->nlmsg_seq, + NFT_MSG_NEWCHAIN, + NLM_F_MULTI, +- table->afi->family, table, ++ table->family, table, + chain) < 0) + goto done; + +@@ -1168,7 +1081,6 @@ static int nf_tables_getchain(struct net + { + const struct nfgenmsg *nfmsg = nlmsg_data(nlh); + u8 genmask = nft_genmask_cur(net); +- const struct nft_af_info *afi; + const struct nft_table *table; + const struct nft_chain *chain; + struct sk_buff *skb2; +@@ -1182,11 +1094,7 @@ static int nf_tables_getchain(struct net + return netlink_dump_start(nlsk, skb, nlh, &c); + } + +- afi = nf_tables_afinfo_lookup(net, family, false); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- +- table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], afi->family, ++ table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, + genmask); + if (IS_ERR(table)) + return PTR_ERR(table); +@@ -1550,7 +1458,6 @@ static int nf_tables_newchain(struct net + const struct nlattr * uninitialized_var(name); + u8 genmask = nft_genmask_next(net); + int family = nfmsg->nfgen_family; +- struct nft_af_info *afi; + struct nft_table *table; + struct nft_chain *chain; + u8 policy = NF_ACCEPT; +@@ -1560,11 +1467,7 @@ static int nf_tables_newchain(struct net + + create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; + +- afi = nf_tables_afinfo_lookup(net, family, true); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- +- table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], afi->family, ++ table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, + genmask); + if (IS_ERR(table)) + return PTR_ERR(table); +@@ -1605,7 +1508,7 @@ static int nf_tables_newchain(struct net + } + } + +- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, chain, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla); + + if (chain != NULL) { + if (nlh->nlmsg_flags & NLM_F_EXCL) +@@ -1626,7 +1529,6 @@ static int nf_tables_delchain(struct net + { + const struct nfgenmsg *nfmsg = nlmsg_data(nlh); + u8 genmask = nft_genmask_next(net); +- struct nft_af_info *afi; + struct nft_table *table; + struct nft_chain *chain; + struct nft_rule *rule; +@@ -1635,11 +1537,7 @@ static int nf_tables_delchain(struct net + u32 use; + int err; + +- afi = nf_tables_afinfo_lookup(net, family, false); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- +- table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], afi->family, ++ table = nf_tables_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, + genmask); + if (IS_ERR(table)) + return PTR_ERR(table); +@@ -1652,7 +1550,7 @@ static int nf_tables_delchain(struct net + chain->use > 0) + return -EBUSY; + +- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, chain, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla); + + use = chain->use; + list_for_each_entry(rule, &chain->rules, list) { +@@ -2075,7 +1973,7 @@ static int nf_tables_dump_rules(struct s + cb->seq = net->nft.base_seq; + + list_for_each_entry_rcu(table, &net->nft.tables, list) { +- if (family != NFPROTO_UNSPEC && family != table->afi->family) ++ if (family != NFPROTO_UNSPEC && family != table->family) + continue; + + if (ctx && ctx->table && strcmp(ctx->table, table->name) != 0) +@@ -2098,7 +1996,7 @@ static int nf_tables_dump_rules(struct s + cb->nlh->nlmsg_seq, + NFT_MSG_NEWRULE, + NLM_F_MULTI | NLM_F_APPEND, +- table->afi->family, ++ table->family, + table, chain, rule) < 0) + goto done; + +@@ -2134,7 +2032,6 @@ static int nf_tables_getrule(struct net + { + const struct nfgenmsg *nfmsg = nlmsg_data(nlh); + u8 genmask = nft_genmask_cur(net); +- const struct nft_af_info *afi; + const struct nft_table *table; + const struct nft_chain *chain; + const struct nft_rule *rule; +@@ -2178,11 +2075,7 @@ static int nf_tables_getrule(struct net + return netlink_dump_start(nlsk, skb, nlh, &c); + } + +- afi = nf_tables_afinfo_lookup(net, family, false); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- +- table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], afi->family, ++ table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], family, + genmask); + if (IS_ERR(table)) + return PTR_ERR(table); +@@ -2240,7 +2133,7 @@ static int nf_tables_newrule(struct net + { + const struct nfgenmsg *nfmsg = nlmsg_data(nlh); + u8 genmask = nft_genmask_next(net); +- struct nft_af_info *afi; ++ int family = nfmsg->nfgen_family; + struct nft_table *table; + struct nft_chain *chain; + struct nft_rule *rule, *old_rule = NULL; +@@ -2256,11 +2149,7 @@ static int nf_tables_newrule(struct net + + create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; + +- afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, create); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- +- table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], afi->family, ++ table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], family, + genmask); + if (IS_ERR(table)) + return PTR_ERR(table); +@@ -2300,7 +2189,7 @@ static int nf_tables_newrule(struct net + return PTR_ERR(old_rule); + } + +- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, chain, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla); + + n = 0; + size = 0; +@@ -2424,18 +2313,13 @@ static int nf_tables_delrule(struct net + { + const struct nfgenmsg *nfmsg = nlmsg_data(nlh); + u8 genmask = nft_genmask_next(net); +- struct nft_af_info *afi; + struct nft_table *table; + struct nft_chain *chain = NULL; + struct nft_rule *rule; + int family = nfmsg->nfgen_family, err = 0; + struct nft_ctx ctx; + +- afi = nf_tables_afinfo_lookup(net, family, false); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- +- table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], afi->family, ++ table = nf_tables_table_lookup(net, nla[NFTA_RULE_TABLE], family, + genmask); + if (IS_ERR(table)) + return PTR_ERR(table); +@@ -2447,7 +2331,7 @@ static int nf_tables_delrule(struct net + return PTR_ERR(chain); + } + +- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, chain, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla); + + if (chain) { + if (nla[NFTA_RULE_HANDLE]) { +@@ -2632,26 +2516,17 @@ static int nft_ctx_init_from_setattr(str + u8 genmask) + { + const struct nfgenmsg *nfmsg = nlmsg_data(nlh); +- struct nft_af_info *afi = NULL; ++ int family = nfmsg->nfgen_family; + struct nft_table *table = NULL; + +- if (nfmsg->nfgen_family != NFPROTO_UNSPEC) { +- afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- } +- + if (nla[NFTA_SET_TABLE] != NULL) { +- if (afi == NULL) +- return -EAFNOSUPPORT; +- + table = nf_tables_table_lookup(net, nla[NFTA_SET_TABLE], +- afi->family, genmask); ++ family, genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + } + +- nft_ctx_init(ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla); + return 0; + } + +@@ -2882,7 +2757,7 @@ static int nf_tables_dump_sets(struct sk + + list_for_each_entry_rcu(table, &net->nft.tables, list) { + if (ctx->family != NFPROTO_UNSPEC && +- ctx->family != table->afi->family) ++ ctx->family != table->family) + continue; + + if (ctx->table && ctx->table != table) +@@ -2903,7 +2778,7 @@ static int nf_tables_dump_sets(struct sk + + ctx_set = *ctx; + ctx_set.table = table; +- ctx_set.family = table->afi->family; ++ ctx_set.family = table->family; + + if (nf_tables_fill_set(skb, &ctx_set, set, + NFT_MSG_NEWSET, +@@ -3015,8 +2890,8 @@ static int nf_tables_newset(struct net * + { + const struct nfgenmsg *nfmsg = nlmsg_data(nlh); + u8 genmask = nft_genmask_next(net); ++ int family = nfmsg->nfgen_family; + const struct nft_set_ops *ops; +- struct nft_af_info *afi; + struct nft_table *table; + struct nft_set *set; + struct nft_ctx ctx; +@@ -3123,16 +2998,12 @@ static int nf_tables_newset(struct net * + + create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; + +- afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, create); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- +- table = nf_tables_table_lookup(net, nla[NFTA_SET_TABLE], afi->family, ++ table = nf_tables_table_lookup(net, nla[NFTA_SET_TABLE], family, + genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); + + set = nf_tables_set_lookup(table, nla[NFTA_SET_NAME], genmask); + if (IS_ERR(set)) { +@@ -3390,19 +3261,15 @@ static int nft_ctx_init_from_elemattr(st + u8 genmask) + { + const struct nfgenmsg *nfmsg = nlmsg_data(nlh); +- struct nft_af_info *afi; ++ int family = nfmsg->nfgen_family; + struct nft_table *table; + +- afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- + table = nf_tables_table_lookup(net, nla[NFTA_SET_ELEM_LIST_TABLE], +- afi->family, genmask); ++ family, genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +- nft_ctx_init(ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla); + return 0; + } + +@@ -3520,7 +3387,7 @@ static int nf_tables_dump_set(struct sk_ + rcu_read_lock(); + list_for_each_entry_rcu(table, &net->nft.tables, list) { + if (dump_ctx->ctx.family != NFPROTO_UNSPEC && +- dump_ctx->ctx.family != table->afi->family) ++ dump_ctx->ctx.family != table->family) + continue; + + if (table != dump_ctx->ctx.table) +@@ -3550,7 +3417,7 @@ static int nf_tables_dump_set(struct sk_ + goto nla_put_failure; + + nfmsg = nlmsg_data(nlh); +- nfmsg->nfgen_family = table->afi->family; ++ nfmsg->nfgen_family = table->family; + nfmsg->version = NFNETLINK_V0; + nfmsg->res_id = htons(net->nft.base_seq & 0xffff); + +@@ -4427,7 +4294,6 @@ static int nf_tables_newobj(struct net * + const struct nft_object_type *type; + u8 genmask = nft_genmask_next(net); + int family = nfmsg->nfgen_family; +- struct nft_af_info *afi; + struct nft_table *table; + struct nft_object *obj; + struct nft_ctx ctx; +@@ -4439,11 +4305,7 @@ static int nf_tables_newobj(struct net * + !nla[NFTA_OBJ_DATA]) + return -EINVAL; + +- afi = nf_tables_afinfo_lookup(net, family, true); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- +- table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], afi->family, ++ table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family, + genmask); + if (IS_ERR(table)) + return PTR_ERR(table); +@@ -4462,7 +4324,7 @@ static int nf_tables_newobj(struct net * + return 0; + } + +- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); + + type = nft_obj_type_get(objtype); + if (IS_ERR(type)) +@@ -4554,7 +4416,7 @@ static int nf_tables_dump_obj(struct sk_ + cb->seq = net->nft.base_seq; + + list_for_each_entry_rcu(table, &net->nft.tables, list) { +- if (family != NFPROTO_UNSPEC && family != table->afi->family) ++ if (family != NFPROTO_UNSPEC && family != table->family) + continue; + + list_for_each_entry_rcu(obj, &table->objects, list) { +@@ -4577,7 +4439,7 @@ static int nf_tables_dump_obj(struct sk_ + cb->nlh->nlmsg_seq, + NFT_MSG_NEWOBJ, + NLM_F_MULTI | NLM_F_APPEND, +- table->afi->family, table, ++ table->family, table, + obj, reset) < 0) + goto done; + +@@ -4635,7 +4497,6 @@ static int nf_tables_getobj(struct net * + const struct nfgenmsg *nfmsg = nlmsg_data(nlh); + u8 genmask = nft_genmask_cur(net); + int family = nfmsg->nfgen_family; +- const struct nft_af_info *afi; + const struct nft_table *table; + struct nft_object *obj; + struct sk_buff *skb2; +@@ -4666,11 +4527,7 @@ static int nf_tables_getobj(struct net * + !nla[NFTA_OBJ_TYPE]) + return -EINVAL; + +- afi = nf_tables_afinfo_lookup(net, family, false); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- +- table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], afi->family, ++ table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family, + genmask); + if (IS_ERR(table)) + return PTR_ERR(table); +@@ -4717,7 +4574,6 @@ static int nf_tables_delobj(struct net * + const struct nfgenmsg *nfmsg = nlmsg_data(nlh); + u8 genmask = nft_genmask_next(net); + int family = nfmsg->nfgen_family; +- struct nft_af_info *afi; + struct nft_table *table; + struct nft_object *obj; + struct nft_ctx ctx; +@@ -4727,11 +4583,7 @@ static int nf_tables_delobj(struct net * + !nla[NFTA_OBJ_NAME]) + return -EINVAL; + +- afi = nf_tables_afinfo_lookup(net, family, true); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- +- table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], afi->family, ++ table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family, + genmask); + if (IS_ERR(table)) + return PTR_ERR(table); +@@ -4743,7 +4595,7 @@ static int nf_tables_delobj(struct net * + if (obj->use > 0) + return -EBUSY; + +- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); + + return nft_delobj(&ctx, obj); + } +@@ -4928,33 +4780,31 @@ err1: + return err; + } + +-static const struct nf_flowtable_type * +-__nft_flowtable_type_get(const struct nft_af_info *afi) ++static const struct nf_flowtable_type *__nft_flowtable_type_get(u8 family) + { + const struct nf_flowtable_type *type; + + list_for_each_entry(type, &nf_tables_flowtables, list) { +- if (afi->family == type->family) ++ if (family == type->family) + return type; + } + return NULL; + } + +-static const struct nf_flowtable_type * +-nft_flowtable_type_get(const struct nft_af_info *afi) ++static const struct nf_flowtable_type *nft_flowtable_type_get(u8 family) + { + const struct nf_flowtable_type *type; + +- type = __nft_flowtable_type_get(afi); ++ type = __nft_flowtable_type_get(family); + if (type != NULL && try_module_get(type->owner)) + return type; + + #ifdef CONFIG_MODULES + if (type == NULL) { + nfnl_unlock(NFNL_SUBSYS_NFTABLES); +- request_module("nf-flowtable-%u", afi->family); ++ request_module("nf-flowtable-%u", family); + nfnl_lock(NFNL_SUBSYS_NFTABLES); +- if (__nft_flowtable_type_get(afi)) ++ if (__nft_flowtable_type_get(family)) + return ERR_PTR(-EAGAIN); + } + #endif +@@ -5002,7 +4852,6 @@ static int nf_tables_newflowtable(struct + u8 genmask = nft_genmask_next(net); + int family = nfmsg->nfgen_family; + struct nft_flowtable *flowtable; +- struct nft_af_info *afi; + struct nft_table *table; + struct nft_ctx ctx; + int err, i, k; +@@ -5012,12 +4861,8 @@ static int nf_tables_newflowtable(struct + !nla[NFTA_FLOWTABLE_HOOK]) + return -EINVAL; + +- afi = nf_tables_afinfo_lookup(net, family, true); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- + table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], +- afi->family, genmask); ++ family, genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -5034,7 +4879,7 @@ static int nf_tables_newflowtable(struct + return 0; + } + +- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); + + flowtable = kzalloc(sizeof(*flowtable), GFP_KERNEL); + if (!flowtable) +@@ -5047,7 +4892,7 @@ static int nf_tables_newflowtable(struct + goto err1; + } + +- type = nft_flowtable_type_get(afi); ++ type = nft_flowtable_type_get(family); + if (IS_ERR(type)) { + err = PTR_ERR(type); + goto err2; +@@ -5107,16 +4952,11 @@ static int nf_tables_delflowtable(struct + u8 genmask = nft_genmask_next(net); + int family = nfmsg->nfgen_family; + struct nft_flowtable *flowtable; +- struct nft_af_info *afi; + struct nft_table *table; + struct nft_ctx ctx; + +- afi = nf_tables_afinfo_lookup(net, family, true); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- + table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], +- afi->family, genmask); ++ family, genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -5127,7 +4967,7 @@ static int nf_tables_delflowtable(struct + if (flowtable->use > 0) + return -EBUSY; + +- nft_ctx_init(&ctx, net, skb, nlh, afi->family, table, NULL, nla); ++ nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); + + return nft_delflowtable(&ctx, flowtable); + } +@@ -5202,7 +5042,7 @@ static int nf_tables_dump_flowtable(stru + cb->seq = net->nft.base_seq; + + list_for_each_entry_rcu(table, &net->nft.tables, list) { +- if (family != NFPROTO_UNSPEC && family != table->afi->family) ++ if (family != NFPROTO_UNSPEC && family != table->family) + continue; + + list_for_each_entry_rcu(flowtable, &table->flowtables, list) { +@@ -5221,7 +5061,7 @@ static int nf_tables_dump_flowtable(stru + cb->nlh->nlmsg_seq, + NFT_MSG_NEWFLOWTABLE, + NLM_F_MULTI | NLM_F_APPEND, +- table->afi->family, flowtable) < 0) ++ table->family, flowtable) < 0) + goto done; + + nl_dump_check_consistent(cb, nlmsg_hdr(skb)); +@@ -5281,7 +5121,6 @@ static int nf_tables_getflowtable(struct + u8 genmask = nft_genmask_cur(net); + int family = nfmsg->nfgen_family; + struct nft_flowtable *flowtable; +- const struct nft_af_info *afi; + const struct nft_table *table; + struct sk_buff *skb2; + int err; +@@ -5307,12 +5146,8 @@ static int nf_tables_getflowtable(struct + if (!nla[NFTA_FLOWTABLE_NAME]) + return -EINVAL; + +- afi = nf_tables_afinfo_lookup(net, family, false); +- if (IS_ERR(afi)) +- return PTR_ERR(afi); +- + table = nf_tables_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], +- afi->family, genmask); ++ family, genmask); + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -6476,7 +6311,7 @@ int __nft_release_basechain(struct nft_c + } + EXPORT_SYMBOL_GPL(__nft_release_basechain); + +-static void __nft_release_afinfo(struct net *net) ++static void __nft_release_tables(struct net *net) + { + struct nft_flowtable *flowtable, *nf; + struct nft_table *table, *nt; +@@ -6489,7 +6324,7 @@ static void __nft_release_afinfo(struct + }; + + list_for_each_entry_safe(table, nt, &net->nft.tables, list) { +- ctx.family = table->afi->family; ++ ctx.family = table->family; + + list_for_each_entry(chain, &table->chains, list) + nf_tables_unregister_hook(net, table, chain); +@@ -6541,7 +6376,7 @@ static int __net_init nf_tables_init_net + + static void __net_exit nf_tables_exit_net(struct net *net) + { +- __nft_release_afinfo(net); ++ __nft_release_tables(net); + WARN_ON_ONCE(!list_empty(&net->nft.tables)); + WARN_ON_ONCE(!list_empty(&net->nft.commit_list)); + } +--- a/net/netfilter/nf_tables_inet.c ++++ b/net/netfilter/nf_tables_inet.c +@@ -38,11 +38,6 @@ static unsigned int nft_do_chain_inet(vo + return nft_do_chain(&pkt, priv); + } + +-static struct nft_af_info nft_af_inet __read_mostly = { +- .family = NFPROTO_INET, +- .owner = THIS_MODULE, +-}; +- + static const struct nf_chain_type filter_inet = { + .name = "filter", + .type = NFT_CHAIN_T_DEFAULT, +@@ -64,26 +59,12 @@ static const struct nf_chain_type filter + + static int __init nf_tables_inet_init(void) + { +- int ret; +- +- if (nft_register_afinfo(&nft_af_inet) < 0) +- return ret; +- +- ret = nft_register_chain_type(&filter_inet); +- if (ret < 0) +- goto err_register_chain; +- +- return ret; +- +-err_register_chain: +- nft_unregister_afinfo(&nft_af_inet); +- return ret; ++ return nft_register_chain_type(&filter_inet); + } + + static void __exit nf_tables_inet_exit(void) + { + nft_unregister_chain_type(&filter_inet); +- nft_unregister_afinfo(&nft_af_inet); + } + + module_init(nf_tables_inet_init); +@@ -91,4 +72,4 @@ module_exit(nf_tables_inet_exit); + + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Patrick McHardy "); +-MODULE_ALIAS_NFT_FAMILY(1); ++MODULE_ALIAS_NFT_CHAIN(1, "filter"); +--- a/net/netfilter/nf_tables_netdev.c ++++ b/net/netfilter/nf_tables_netdev.c +@@ -38,11 +38,6 @@ nft_do_chain_netdev(void *priv, struct s + return nft_do_chain(&pkt, priv); + } + +-static struct nft_af_info nft_af_netdev __read_mostly = { +- .family = NFPROTO_NETDEV, +- .owner = THIS_MODULE, +-}; +- + static const struct nf_chain_type nft_filter_chain_netdev = { + .name = "filter", + .type = NFT_CHAIN_T_DEFAULT, +@@ -91,10 +86,10 @@ static int nf_tables_netdev_event(struct + + nfnl_lock(NFNL_SUBSYS_NFTABLES); + list_for_each_entry(table, &ctx.net->nft.tables, list) { +- if (table->afi->family != NFPROTO_NETDEV) ++ if (table->family != NFPROTO_NETDEV) + continue; + +- ctx.family = table->afi->family; ++ ctx.family = table->family; + ctx.table = table; + list_for_each_entry_safe(chain, nr, &table->chains, list) { + if (!nft_is_base_chain(chain)) +@@ -117,12 +112,9 @@ static int __init nf_tables_netdev_init( + { + int ret; + +- if (nft_register_afinfo(&nft_af_netdev) < 0) +- return ret; +- + ret = nft_register_chain_type(&nft_filter_chain_netdev); + if (ret) +- goto err_register_chain_type; ++ return ret; + + ret = register_netdevice_notifier(&nf_tables_netdev_notifier); + if (ret) +@@ -132,8 +124,6 @@ static int __init nf_tables_netdev_init( + + err_register_netdevice_notifier: + nft_unregister_chain_type(&nft_filter_chain_netdev); +-err_register_chain_type: +- nft_unregister_afinfo(&nft_af_netdev); + + return ret; + } +@@ -142,7 +132,6 @@ static void __exit nf_tables_netdev_exit + { + unregister_netdevice_notifier(&nf_tables_netdev_notifier); + nft_unregister_chain_type(&nft_filter_chain_netdev); +- nft_unregister_afinfo(&nft_af_netdev); + } + + module_init(nf_tables_netdev_init); +@@ -150,4 +139,4 @@ module_exit(nf_tables_netdev_exit); + + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Pablo Neira Ayuso "); +-MODULE_ALIAS_NFT_FAMILY(5); /* NFPROTO_NETDEV */ ++MODULE_ALIAS_NFT_CHAIN(5, "filter"); /* NFPROTO_NETDEV */ diff --git a/target/linux/generic/backport-4.14/339-netfilter-nft_flow_offload-wait-for-garbage-collecto.patch b/target/linux/generic/backport-4.14/339-netfilter-nft_flow_offload-wait-for-garbage-collecto.patch new file mode 100644 index 000000000..acca41ae3 --- /dev/null +++ b/target/linux/generic/backport-4.14/339-netfilter-nft_flow_offload-wait-for-garbage-collecto.patch @@ -0,0 +1,47 @@ +From: Pablo Neira Ayuso +Date: Thu, 1 Feb 2018 18:49:00 +0100 +Subject: [PATCH] netfilter: nft_flow_offload: wait for garbage collector + to run after cleanup + +If netdevice goes down, then flowtable entries are scheduled to be +removed. Wait for garbage collector to have a chance to run so it can +delete them from the hashtable. + +The flush call might sleep, so hold the nfnl mutex from +nft_flow_table_iterate() instead of rcu read side lock. The use of the +nfnl mutex is also implicitly fixing races between updates via nfnetlink +and netdevice event. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -4818,13 +4818,13 @@ void nft_flow_table_iterate(struct net * + struct nft_flowtable *flowtable; + const struct nft_table *table; + +- rcu_read_lock(); +- list_for_each_entry_rcu(table, &net->nft.tables, list) { +- list_for_each_entry_rcu(flowtable, &table->flowtables, list) { ++ nfnl_lock(NFNL_SUBSYS_NFTABLES); ++ list_for_each_entry(table, &net->nft.tables, list) { ++ list_for_each_entry(flowtable, &table->flowtables, list) { + iter(&flowtable->data, data); + } + } +- rcu_read_unlock(); ++ nfnl_unlock(NFNL_SUBSYS_NFTABLES); + } + EXPORT_SYMBOL_GPL(nft_flow_table_iterate); + +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -208,6 +208,7 @@ static void nft_flow_offload_iterate_cle + void *data) + { + nf_flow_table_iterate(flowtable, flow_offload_iterate_cleanup, data); ++ flush_delayed_work(&flowtable->gc_work); + } + + static int flow_offload_netdev_event(struct notifier_block *this, diff --git a/target/linux/generic/backport-4.14/340-netfilter-nft_flow_offload-no-need-to-flush-entries-.patch b/target/linux/generic/backport-4.14/340-netfilter-nft_flow_offload-no-need-to-flush-entries-.patch new file mode 100644 index 000000000..539550d54 --- /dev/null +++ b/target/linux/generic/backport-4.14/340-netfilter-nft_flow_offload-no-need-to-flush-entries-.patch @@ -0,0 +1,29 @@ +From: Pablo Neira Ayuso +Date: Thu, 1 Feb 2018 18:49:01 +0100 +Subject: [PATCH] netfilter: nft_flow_offload: no need to flush entries on + module removal + +nft_flow_offload module removal does not require to flush existing +flowtables, it is valid to remove this module while keeping flowtables +around. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -247,14 +247,8 @@ register_expr: + + static void __exit nft_flow_offload_module_exit(void) + { +- struct net *net; +- + nft_unregister_expr(&nft_flow_offload_type); + unregister_netdevice_notifier(&flow_offload_netdev_notifier); +- rtnl_lock(); +- for_each_net(net) +- nft_flow_table_iterate(net, nft_flow_offload_iterate_cleanup, NULL); +- rtnl_unlock(); + } + + module_init(nft_flow_offload_module_init); diff --git a/target/linux/generic/backport-4.14/341-netfilter-nft_flow_offload-move-flowtable-cleanup-ro.patch b/target/linux/generic/backport-4.14/341-netfilter-nft_flow_offload-move-flowtable-cleanup-ro.patch new file mode 100644 index 000000000..9ee0ad593 --- /dev/null +++ b/target/linux/generic/backport-4.14/341-netfilter-nft_flow_offload-move-flowtable-cleanup-ro.patch @@ -0,0 +1,97 @@ +From: Pablo Neira Ayuso +Date: Tue, 23 Jan 2018 17:46:09 +0100 +Subject: [PATCH] netfilter: nft_flow_offload: move flowtable cleanup + routines to nf_flow_table + +Move the flowtable cleanup routines to nf_flow_table and expose the +nf_flow_table_cleanup() helper function. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -95,6 +95,9 @@ struct flow_offload_tuple_rhash *flow_of + int nf_flow_table_iterate(struct nf_flowtable *flow_table, + void (*iter)(struct flow_offload *flow, void *data), + void *data); ++ ++void nf_flow_table_cleanup(struct net *net, struct net_device *dev); ++ + void nf_flow_offload_work_gc(struct work_struct *work); + extern const struct rhashtable_params nf_flow_offload_rhash_params; + +--- a/net/netfilter/nf_flow_table.c ++++ b/net/netfilter/nf_flow_table.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -425,5 +426,28 @@ int nf_flow_dnat_port(const struct flow_ + } + EXPORT_SYMBOL_GPL(nf_flow_dnat_port); + ++static void nf_flow_table_do_cleanup(struct flow_offload *flow, void *data) ++{ ++ struct net_device *dev = data; ++ ++ if (dev && flow->tuplehash[0].tuple.iifidx != dev->ifindex) ++ return; ++ ++ flow_offload_dead(flow); ++} ++ ++static void nf_flow_table_iterate_cleanup(struct nf_flowtable *flowtable, ++ void *data) ++{ ++ nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, data); ++ flush_delayed_work(&flowtable->gc_work); ++} ++ ++void nf_flow_table_cleanup(struct net *net, struct net_device *dev) ++{ ++ nft_flow_table_iterate(net, nf_flow_table_iterate_cleanup, dev); ++} ++EXPORT_SYMBOL_GPL(nf_flow_table_cleanup); ++ + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Pablo Neira Ayuso "); +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -194,23 +194,6 @@ static struct nft_expr_type nft_flow_off + .owner = THIS_MODULE, + }; + +-static void flow_offload_iterate_cleanup(struct flow_offload *flow, void *data) +-{ +- struct net_device *dev = data; +- +- if (dev && flow->tuplehash[0].tuple.iifidx != dev->ifindex) +- return; +- +- flow_offload_dead(flow); +-} +- +-static void nft_flow_offload_iterate_cleanup(struct nf_flowtable *flowtable, +- void *data) +-{ +- nf_flow_table_iterate(flowtable, flow_offload_iterate_cleanup, data); +- flush_delayed_work(&flowtable->gc_work); +-} +- + static int flow_offload_netdev_event(struct notifier_block *this, + unsigned long event, void *ptr) + { +@@ -219,7 +202,7 @@ static int flow_offload_netdev_event(str + if (event != NETDEV_DOWN) + return NOTIFY_DONE; + +- nft_flow_table_iterate(dev_net(dev), nft_flow_offload_iterate_cleanup, dev); ++ nf_flow_table_cleanup(dev_net(dev), dev); + + return NOTIFY_DONE; + } diff --git a/target/linux/generic/backport-4.14/342-netfilter-nf_tables-fix-flowtable-free.patch b/target/linux/generic/backport-4.14/342-netfilter-nf_tables-fix-flowtable-free.patch new file mode 100644 index 000000000..b16eff678 --- /dev/null +++ b/target/linux/generic/backport-4.14/342-netfilter-nf_tables-fix-flowtable-free.patch @@ -0,0 +1,140 @@ +From: Pablo Neira Ayuso +Date: Mon, 5 Feb 2018 21:44:50 +0100 +Subject: [PATCH] netfilter: nf_tables: fix flowtable free + +Every flow_offload entry is added into the table twice. Because of this, +rhashtable_free_and_destroy can't be used, since it would call kfree for +each flow_offload object twice. + +This patch adds a call to nf_flow_table_iterate_cleanup() to schedule +removal of entries, then there is an explicitly invocation of the +garbage collector to clean up resources. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -14,6 +14,7 @@ struct nf_flowtable_type { + struct list_head list; + int family; + void (*gc)(struct work_struct *work); ++ void (*free)(struct nf_flowtable *ft); + const struct rhashtable_params *params; + nf_hookfn *hook; + struct module *owner; +@@ -98,6 +99,7 @@ int nf_flow_table_iterate(struct nf_flow + + void nf_flow_table_cleanup(struct net *net, struct net_device *dev); + ++void nf_flow_table_free(struct nf_flowtable *flow_table); + void nf_flow_offload_work_gc(struct work_struct *work); + extern const struct rhashtable_params nf_flow_offload_rhash_params; + +--- a/net/ipv4/netfilter/nf_flow_table_ipv4.c ++++ b/net/ipv4/netfilter/nf_flow_table_ipv4.c +@@ -260,6 +260,7 @@ static struct nf_flowtable_type flowtabl + .family = NFPROTO_IPV4, + .params = &nf_flow_offload_rhash_params, + .gc = nf_flow_offload_work_gc, ++ .free = nf_flow_table_free, + .hook = nf_flow_offload_ip_hook, + .owner = THIS_MODULE, + }; +--- a/net/ipv6/netfilter/nf_flow_table_ipv6.c ++++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c +@@ -254,6 +254,7 @@ static struct nf_flowtable_type flowtabl + .family = NFPROTO_IPV6, + .params = &nf_flow_offload_rhash_params, + .gc = nf_flow_offload_work_gc, ++ .free = nf_flow_table_free, + .hook = nf_flow_offload_ipv6_hook, + .owner = THIS_MODULE, + }; +--- a/net/netfilter/nf_flow_table.c ++++ b/net/netfilter/nf_flow_table.c +@@ -232,19 +232,16 @@ static inline bool nf_flow_is_dying(cons + return flow->flags & FLOW_OFFLOAD_DYING; + } + +-void nf_flow_offload_work_gc(struct work_struct *work) ++static int nf_flow_offload_gc_step(struct nf_flowtable *flow_table) + { + struct flow_offload_tuple_rhash *tuplehash; +- struct nf_flowtable *flow_table; + struct rhashtable_iter hti; + struct flow_offload *flow; + int err; + +- flow_table = container_of(work, struct nf_flowtable, gc_work.work); +- + err = rhashtable_walk_init(&flow_table->rhashtable, &hti, GFP_KERNEL); + if (err) +- goto schedule; ++ return 0; + + rhashtable_walk_start(&hti); + +@@ -270,7 +267,16 @@ void nf_flow_offload_work_gc(struct work + out: + rhashtable_walk_stop(&hti); + rhashtable_walk_exit(&hti); +-schedule: ++ ++ return 1; ++} ++ ++void nf_flow_offload_work_gc(struct work_struct *work) ++{ ++ struct nf_flowtable *flow_table; ++ ++ flow_table = container_of(work, struct nf_flowtable, gc_work.work); ++ nf_flow_offload_gc_step(flow_table); + queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ); + } + EXPORT_SYMBOL_GPL(nf_flow_offload_work_gc); +@@ -449,5 +455,12 @@ void nf_flow_table_cleanup(struct net *n + } + EXPORT_SYMBOL_GPL(nf_flow_table_cleanup); + ++void nf_flow_table_free(struct nf_flowtable *flow_table) ++{ ++ nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL); ++ WARN_ON(!nf_flow_offload_gc_step(flow_table)); ++} ++EXPORT_SYMBOL_GPL(nf_flow_table_free); ++ + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Pablo Neira Ayuso "); +--- a/net/netfilter/nf_flow_table_inet.c ++++ b/net/netfilter/nf_flow_table_inet.c +@@ -24,6 +24,7 @@ static struct nf_flowtable_type flowtabl + .family = NFPROTO_INET, + .params = &nf_flow_offload_rhash_params, + .gc = nf_flow_offload_work_gc, ++ .free = nf_flow_table_free, + .hook = nf_flow_offload_inet_hook, + .owner = THIS_MODULE, + }; +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -5203,17 +5203,12 @@ err: + nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS); + } + +-static void nft_flowtable_destroy(void *ptr, void *arg) +-{ +- kfree(ptr); +-} +- + static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable) + { + cancel_delayed_work_sync(&flowtable->data.gc_work); + kfree(flowtable->name); +- rhashtable_free_and_destroy(&flowtable->data.rhashtable, +- nft_flowtable_destroy, NULL); ++ flowtable->data.type->free(&flowtable->data); ++ rhashtable_destroy(&flowtable->data.rhashtable); + module_put(flowtable->data.type->owner); + } + diff --git a/target/linux/generic/backport-4.14/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch b/target/linux/generic/backport-4.14/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch new file mode 100644 index 000000000..7f35cd7c6 --- /dev/null +++ b/target/linux/generic/backport-4.14/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch @@ -0,0 +1,96 @@ +From: Pablo Neira Ayuso +Date: Thu, 25 Jan 2018 12:58:55 +0100 +Subject: [PATCH] netfilter: nft_flow_offload: handle netdevice events from + nf_flow_table + +Move the code that deals with device events to the core. + +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/netfilter/nf_flow_table.c ++++ b/net/netfilter/nf_flow_table.c +@@ -462,5 +462,35 @@ void nf_flow_table_free(struct nf_flowta + } + EXPORT_SYMBOL_GPL(nf_flow_table_free); + ++static int nf_flow_table_netdev_event(struct notifier_block *this, ++ unsigned long event, void *ptr) ++{ ++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++ ++ if (event != NETDEV_DOWN) ++ return NOTIFY_DONE; ++ ++ nf_flow_table_cleanup(dev_net(dev), dev); ++ ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block flow_offload_netdev_notifier = { ++ .notifier_call = nf_flow_table_netdev_event, ++}; ++ ++static int __init nf_flow_table_module_init(void) ++{ ++ return register_netdevice_notifier(&flow_offload_netdev_notifier); ++} ++ ++static void __exit nf_flow_table_module_exit(void) ++{ ++ unregister_netdevice_notifier(&flow_offload_netdev_notifier); ++} ++ ++module_init(nf_flow_table_module_init); ++module_exit(nf_flow_table_module_exit); ++ + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Pablo Neira Ayuso "); +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -194,44 +194,14 @@ static struct nft_expr_type nft_flow_off + .owner = THIS_MODULE, + }; + +-static int flow_offload_netdev_event(struct notifier_block *this, +- unsigned long event, void *ptr) +-{ +- struct net_device *dev = netdev_notifier_info_to_dev(ptr); +- +- if (event != NETDEV_DOWN) +- return NOTIFY_DONE; +- +- nf_flow_table_cleanup(dev_net(dev), dev); +- +- return NOTIFY_DONE; +-} +- +-static struct notifier_block flow_offload_netdev_notifier = { +- .notifier_call = flow_offload_netdev_event, +-}; +- + static int __init nft_flow_offload_module_init(void) + { +- int err; +- +- register_netdevice_notifier(&flow_offload_netdev_notifier); +- +- err = nft_register_expr(&nft_flow_offload_type); +- if (err < 0) +- goto register_expr; +- +- return 0; +- +-register_expr: +- unregister_netdevice_notifier(&flow_offload_netdev_notifier); +- return err; ++ return nft_register_expr(&nft_flow_offload_type); + } + + static void __exit nft_flow_offload_module_exit(void) + { + nft_unregister_expr(&nft_flow_offload_type); +- unregister_netdevice_notifier(&flow_offload_netdev_notifier); + } + + module_init(nft_flow_offload_module_init); diff --git a/target/linux/generic/backport-4.14/344-netfilter-nf_tables-allocate-handle-and-delete-objec.patch b/target/linux/generic/backport-4.14/344-netfilter-nf_tables-allocate-handle-and-delete-objec.patch new file mode 100644 index 000000000..97778a99f --- /dev/null +++ b/target/linux/generic/backport-4.14/344-netfilter-nf_tables-allocate-handle-and-delete-objec.patch @@ -0,0 +1,468 @@ +From: Harsha Sharma +Date: Wed, 27 Dec 2017 00:59:00 +0530 +Subject: [PATCH] netfilter: nf_tables: allocate handle and delete objects via + handle + +This patch allows deletion of objects via unique handle which can be +listed via '-a' option. + +Signed-off-by: Harsha Sharma +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -369,6 +369,7 @@ void nft_unregister_set(struct nft_set_t + * @list: table set list node + * @bindings: list of set bindings + * @name: name of the set ++ * @handle: unique handle of the set + * @ktype: key type (numeric type defined by userspace, not used in the kernel) + * @dtype: data type (verdict or numeric type defined by userspace) + * @objtype: object type (see NFT_OBJECT_* definitions) +@@ -391,6 +392,7 @@ struct nft_set { + struct list_head list; + struct list_head bindings; + char *name; ++ u64 handle; + u32 ktype; + u32 dtype; + u32 objtype; +@@ -936,6 +938,7 @@ unsigned int nft_do_chain(struct nft_pkt + * @objects: stateful objects in the table + * @flowtables: flow tables in the table + * @hgenerator: handle generator state ++ * @handle: table handle + * @use: number of chain references to this table + * @flags: table flag (see enum nft_table_flags) + * @genmask: generation mask +@@ -949,6 +952,7 @@ struct nft_table { + struct list_head objects; + struct list_head flowtables; + u64 hgenerator; ++ u64 handle; + u32 use; + u16 family:6, + flags:8, +@@ -973,9 +977,9 @@ int nft_verdict_dump(struct sk_buff *skb + * @name: name of this stateful object + * @genmask: generation mask + * @use: number of references to this stateful object +- * @data: object data, layout depends on type ++ * @handle: unique object handle + * @ops: object operations +- * @data: pointer to object data ++ * @data: object data, layout depends on type + */ + struct nft_object { + struct list_head list; +@@ -983,6 +987,7 @@ struct nft_object { + struct nft_table *table; + u32 genmask:2, + use:30; ++ u64 handle; + /* runtime data below here */ + const struct nft_object_ops *ops ____cacheline_aligned; + unsigned char data[] +@@ -1064,6 +1069,7 @@ void nft_unregister_obj(struct nft_objec + * @ops_len: number of hooks in array + * @genmask: generation mask + * @use: number of references to this flow table ++ * @handle: unique object handle + * @data: rhashtable and garbage collector + * @ops: array of hooks + */ +@@ -1076,6 +1082,7 @@ struct nft_flowtable { + int ops_len; + u32 genmask:2, + use:30; ++ u64 handle; + /* runtime data below here */ + struct nf_hook_ops *ops ____cacheline_aligned; + struct nf_flowtable data; +--- a/include/uapi/linux/netfilter/nf_tables.h ++++ b/include/uapi/linux/netfilter/nf_tables.h +@@ -174,6 +174,8 @@ enum nft_table_attributes { + NFTA_TABLE_NAME, + NFTA_TABLE_FLAGS, + NFTA_TABLE_USE, ++ NFTA_TABLE_HANDLE, ++ NFTA_TABLE_PAD, + __NFTA_TABLE_MAX + }; + #define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1) +@@ -317,6 +319,7 @@ enum nft_set_desc_attributes { + * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32) + * @NFTA_SET_USERDATA: user data (NLA_BINARY) + * @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*) ++ * @NFTA_SET_HANDLE: set handle (NLA_U64) + */ + enum nft_set_attributes { + NFTA_SET_UNSPEC, +@@ -335,6 +338,7 @@ enum nft_set_attributes { + NFTA_SET_USERDATA, + NFTA_SET_PAD, + NFTA_SET_OBJ_TYPE, ++ NFTA_SET_HANDLE, + __NFTA_SET_MAX + }; + #define NFTA_SET_MAX (__NFTA_SET_MAX - 1) +@@ -1314,6 +1318,7 @@ enum nft_ct_helper_attributes { + * @NFTA_OBJ_TYPE: stateful object type (NLA_U32) + * @NFTA_OBJ_DATA: stateful object data (NLA_NESTED) + * @NFTA_OBJ_USE: number of references to this expression (NLA_U32) ++ * @NFTA_OBJ_HANDLE: object handle (NLA_U64) + */ + enum nft_object_attributes { + NFTA_OBJ_UNSPEC, +@@ -1322,6 +1327,8 @@ enum nft_object_attributes { + NFTA_OBJ_TYPE, + NFTA_OBJ_DATA, + NFTA_OBJ_USE, ++ NFTA_OBJ_HANDLE, ++ NFTA_OBJ_PAD, + __NFTA_OBJ_MAX + }; + #define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1) +@@ -1333,6 +1340,7 @@ enum nft_object_attributes { + * @NFTA_FLOWTABLE_NAME: name of this flow table (NLA_STRING) + * @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32) + * @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32) ++ * @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64) + */ + enum nft_flowtable_attributes { + NFTA_FLOWTABLE_UNSPEC, +@@ -1340,6 +1348,8 @@ enum nft_flowtable_attributes { + NFTA_FLOWTABLE_NAME, + NFTA_FLOWTABLE_HOOK, + NFTA_FLOWTABLE_USE, ++ NFTA_FLOWTABLE_HANDLE, ++ NFTA_FLOWTABLE_PAD, + __NFTA_FLOWTABLE_MAX + }; + #define NFTA_FLOWTABLE_MAX (__NFTA_FLOWTABLE_MAX - 1) +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -26,6 +26,7 @@ + static LIST_HEAD(nf_tables_expressions); + static LIST_HEAD(nf_tables_objects); + static LIST_HEAD(nf_tables_flowtables); ++static u64 table_handle; + + static void nft_ctx_init(struct nft_ctx *ctx, + struct net *net, +@@ -332,6 +333,20 @@ static struct nft_table *nft_table_looku + return NULL; + } + ++static struct nft_table *nft_table_lookup_byhandle(const struct net *net, ++ const struct nlattr *nla, ++ u8 genmask) ++{ ++ struct nft_table *table; ++ ++ list_for_each_entry(table, &net->nft.tables, list) { ++ if (be64_to_cpu(nla_get_be64(nla)) == table->handle && ++ nft_active_genmask(table, genmask)) ++ return table; ++ } ++ return NULL; ++} ++ + static struct nft_table *nf_tables_table_lookup(const struct net *net, + const struct nlattr *nla, + u8 family, u8 genmask) +@@ -348,6 +363,22 @@ static struct nft_table *nf_tables_table + return ERR_PTR(-ENOENT); + } + ++static struct nft_table *nf_tables_table_lookup_byhandle(const struct net *net, ++ const struct nlattr *nla, ++ u8 genmask) ++{ ++ struct nft_table *table; ++ ++ if (nla == NULL) ++ return ERR_PTR(-EINVAL); ++ ++ table = nft_table_lookup_byhandle(net, nla, genmask); ++ if (table != NULL) ++ return table; ++ ++ return ERR_PTR(-ENOENT); ++} ++ + static inline u64 nf_tables_alloc_handle(struct nft_table *table) + { + return ++table->hgenerator; +@@ -394,6 +425,7 @@ static const struct nla_policy nft_table + [NFTA_TABLE_NAME] = { .type = NLA_STRING, + .len = NFT_TABLE_MAXNAMELEN - 1 }, + [NFTA_TABLE_FLAGS] = { .type = NLA_U32 }, ++ [NFTA_TABLE_HANDLE] = { .type = NLA_U64 }, + }; + + static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net, +@@ -415,7 +447,9 @@ static int nf_tables_fill_table_info(str + + if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) || + nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)) || +- nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use))) ++ nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use)) || ++ nla_put_be64(skb, NFTA_TABLE_HANDLE, cpu_to_be64(table->handle), ++ NFTA_TABLE_PAD)) + goto nla_put_failure; + + nlmsg_end(skb, nlh); +@@ -674,6 +708,7 @@ static int nf_tables_newtable(struct net + INIT_LIST_HEAD(&table->flowtables); + table->family = family; + table->flags = flags; ++ table->handle = ++table_handle; + + nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); + err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE); +@@ -791,11 +826,18 @@ static int nf_tables_deltable(struct net + struct nft_ctx ctx; + + nft_ctx_init(&ctx, net, skb, nlh, 0, NULL, NULL, nla); +- if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL) ++ if (family == AF_UNSPEC || ++ (!nla[NFTA_TABLE_NAME] && !nla[NFTA_TABLE_HANDLE])) + return nft_flush(&ctx, family); + +- table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], family, +- genmask); ++ if (nla[NFTA_TABLE_HANDLE]) ++ table = nf_tables_table_lookup_byhandle(net, ++ nla[NFTA_TABLE_HANDLE], ++ genmask); ++ else ++ table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], ++ family, genmask); ++ + if (IS_ERR(table)) + return PTR_ERR(table); + +@@ -1534,6 +1576,7 @@ static int nf_tables_delchain(struct net + struct nft_rule *rule; + int family = nfmsg->nfgen_family; + struct nft_ctx ctx; ++ u64 handle; + u32 use; + int err; + +@@ -1542,7 +1585,12 @@ static int nf_tables_delchain(struct net + if (IS_ERR(table)) + return PTR_ERR(table); + +- chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask); ++ if (nla[NFTA_CHAIN_HANDLE]) { ++ handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE])); ++ chain = nf_tables_chain_lookup_byhandle(table, handle, genmask); ++ } else { ++ chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask); ++ } + if (IS_ERR(chain)) + return PTR_ERR(chain); + +@@ -2503,6 +2551,7 @@ static const struct nla_policy nft_set_p + [NFTA_SET_USERDATA] = { .type = NLA_BINARY, + .len = NFT_USERDATA_MAXLEN }, + [NFTA_SET_OBJ_TYPE] = { .type = NLA_U32 }, ++ [NFTA_SET_HANDLE] = { .type = NLA_U64 }, + }; + + static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = { +@@ -2546,6 +2595,22 @@ static struct nft_set *nf_tables_set_loo + return ERR_PTR(-ENOENT); + } + ++static struct nft_set *nf_tables_set_lookup_byhandle(const struct nft_table *table, ++ const struct nlattr *nla, u8 genmask) ++{ ++ struct nft_set *set; ++ ++ if (nla == NULL) ++ return ERR_PTR(-EINVAL); ++ ++ list_for_each_entry(set, &table->sets, list) { ++ if (be64_to_cpu(nla_get_be64(nla)) == set->handle && ++ nft_active_genmask(set, genmask)) ++ return set; ++ } ++ return ERR_PTR(-ENOENT); ++} ++ + static struct nft_set *nf_tables_set_lookup_byid(const struct net *net, + const struct nlattr *nla, + u8 genmask) +@@ -2661,6 +2726,9 @@ static int nf_tables_fill_set(struct sk_ + goto nla_put_failure; + if (nla_put_string(skb, NFTA_SET_NAME, set->name)) + goto nla_put_failure; ++ if (nla_put_be64(skb, NFTA_SET_HANDLE, cpu_to_be64(set->handle), ++ NFTA_SET_PAD)) ++ goto nla_put_failure; + if (set->flags != 0) + if (nla_put_be32(skb, NFTA_SET_FLAGS, htonl(set->flags))) + goto nla_put_failure; +@@ -3069,6 +3137,7 @@ static int nf_tables_newset(struct net * + set->udata = udata; + set->timeout = timeout; + set->gc_int = gc_int; ++ set->handle = nf_tables_alloc_handle(table); + + err = ops->init(set, &desc, nla); + if (err < 0) +@@ -3126,7 +3195,10 @@ static int nf_tables_delset(struct net * + if (err < 0) + return err; + +- set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask); ++ if (nla[NFTA_SET_HANDLE]) ++ set = nf_tables_set_lookup_byhandle(ctx.table, nla[NFTA_SET_HANDLE], genmask); ++ else ++ set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask); + if (IS_ERR(set)) + return PTR_ERR(set); + +@@ -4182,6 +4254,21 @@ struct nft_object *nf_tables_obj_lookup( + } + EXPORT_SYMBOL_GPL(nf_tables_obj_lookup); + ++struct nft_object *nf_tables_obj_lookup_byhandle(const struct nft_table *table, ++ const struct nlattr *nla, ++ u32 objtype, u8 genmask) ++{ ++ struct nft_object *obj; ++ ++ list_for_each_entry(obj, &table->objects, list) { ++ if (be64_to_cpu(nla_get_be64(nla)) == obj->handle && ++ objtype == obj->ops->type->type && ++ nft_active_genmask(obj, genmask)) ++ return obj; ++ } ++ return ERR_PTR(-ENOENT); ++} ++ + static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = { + [NFTA_OBJ_TABLE] = { .type = NLA_STRING, + .len = NFT_TABLE_MAXNAMELEN - 1 }, +@@ -4189,6 +4276,7 @@ static const struct nla_policy nft_obj_p + .len = NFT_OBJ_MAXNAMELEN - 1 }, + [NFTA_OBJ_TYPE] = { .type = NLA_U32 }, + [NFTA_OBJ_DATA] = { .type = NLA_NESTED }, ++ [NFTA_OBJ_HANDLE] = { .type = NLA_U64}, + }; + + static struct nft_object *nft_obj_init(const struct nft_ctx *ctx, +@@ -4336,6 +4424,8 @@ static int nf_tables_newobj(struct net * + goto err1; + } + obj->table = table; ++ obj->handle = nf_tables_alloc_handle(table); ++ + obj->name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL); + if (!obj->name) { + err = -ENOMEM; +@@ -4382,7 +4472,9 @@ static int nf_tables_fill_obj_info(struc + nla_put_string(skb, NFTA_OBJ_NAME, obj->name) || + nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) || + nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) || +- nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset)) ++ nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset) || ++ nla_put_be64(skb, NFTA_OBJ_HANDLE, cpu_to_be64(obj->handle), ++ NFTA_OBJ_PAD)) + goto nla_put_failure; + + nlmsg_end(skb, nlh); +@@ -4580,7 +4672,7 @@ static int nf_tables_delobj(struct net * + u32 objtype; + + if (!nla[NFTA_OBJ_TYPE] || +- !nla[NFTA_OBJ_NAME]) ++ (!nla[NFTA_OBJ_NAME] && !nla[NFTA_OBJ_HANDLE])) + return -EINVAL; + + table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family, +@@ -4589,7 +4681,12 @@ static int nf_tables_delobj(struct net * + return PTR_ERR(table); + + objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); +- obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask); ++ if (nla[NFTA_OBJ_HANDLE]) ++ obj = nf_tables_obj_lookup_byhandle(table, nla[NFTA_OBJ_HANDLE], ++ objtype, genmask); ++ else ++ obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], ++ objtype, genmask); + if (IS_ERR(obj)) + return PTR_ERR(obj); + if (obj->use > 0) +@@ -4661,6 +4758,7 @@ static const struct nla_policy nft_flowt + [NFTA_FLOWTABLE_NAME] = { .type = NLA_STRING, + .len = NFT_NAME_MAXLEN - 1 }, + [NFTA_FLOWTABLE_HOOK] = { .type = NLA_NESTED }, ++ [NFTA_FLOWTABLE_HANDLE] = { .type = NLA_U64 }, + }; + + struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table, +@@ -4678,6 +4776,20 @@ struct nft_flowtable *nf_tables_flowtabl + } + EXPORT_SYMBOL_GPL(nf_tables_flowtable_lookup); + ++struct nft_flowtable * ++nf_tables_flowtable_lookup_byhandle(const struct nft_table *table, ++ const struct nlattr *nla, u8 genmask) ++{ ++ struct nft_flowtable *flowtable; ++ ++ list_for_each_entry(flowtable, &table->flowtables, list) { ++ if (be64_to_cpu(nla_get_be64(nla)) == flowtable->handle && ++ nft_active_genmask(flowtable, genmask)) ++ return flowtable; ++ } ++ return ERR_PTR(-ENOENT); ++} ++ + #define NFT_FLOWTABLE_DEVICE_MAX 8 + + static int nf_tables_parse_devices(const struct nft_ctx *ctx, +@@ -4886,6 +4998,8 @@ static int nf_tables_newflowtable(struct + return -ENOMEM; + + flowtable->table = table; ++ flowtable->handle = nf_tables_alloc_handle(table); ++ + flowtable->name = nla_strdup(nla[NFTA_FLOWTABLE_NAME], GFP_KERNEL); + if (!flowtable->name) { + err = -ENOMEM; +@@ -4960,8 +5074,14 @@ static int nf_tables_delflowtable(struct + if (IS_ERR(table)) + return PTR_ERR(table); + +- flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], +- genmask); ++ if (nla[NFTA_FLOWTABLE_HANDLE]) ++ flowtable = nf_tables_flowtable_lookup_byhandle(table, ++ nla[NFTA_FLOWTABLE_HANDLE], ++ genmask); ++ else ++ flowtable = nf_tables_flowtable_lookup(table, ++ nla[NFTA_FLOWTABLE_NAME], ++ genmask); + if (IS_ERR(flowtable)) + return PTR_ERR(flowtable); + if (flowtable->use > 0) +@@ -4994,7 +5114,9 @@ static int nf_tables_fill_flowtable_info + + if (nla_put_string(skb, NFTA_FLOWTABLE_TABLE, flowtable->table->name) || + nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) || +- nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use))) ++ nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) || ++ nla_put_be64(skb, NFTA_FLOWTABLE_HANDLE, cpu_to_be64(flowtable->handle), ++ NFTA_FLOWTABLE_PAD)) + goto nla_put_failure; + + nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK); diff --git a/target/linux/generic/backport-4.14/345-netfilter-nf_flow_offload-fix-use-after-free-and-a-r.patch b/target/linux/generic/backport-4.14/345-netfilter-nf_flow_offload-fix-use-after-free-and-a-r.patch new file mode 100644 index 000000000..331f22d19 --- /dev/null +++ b/target/linux/generic/backport-4.14/345-netfilter-nf_flow_offload-fix-use-after-free-and-a-r.patch @@ -0,0 +1,95 @@ +From: Felix Fietkau +Date: Wed, 7 Feb 2018 09:23:25 +0100 +Subject: [PATCH] netfilter: nf_flow_offload: fix use-after-free and a resource + leak + +flow_offload_del frees the flow, so all associated resource must be +freed before. + +Since the ct entry in struct flow_offload_entry was allocated by +flow_offload_alloc, it should be freed by flow_offload_free to take care +of the error handling path when flow_offload_add fails. + +While at it, make flow_offload_del static, since it should never be +called directly, only from the gc step + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -90,7 +90,6 @@ struct flow_offload *flow_offload_alloc( + void flow_offload_free(struct flow_offload *flow); + + int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow); +-void flow_offload_del(struct nf_flowtable *flow_table, struct flow_offload *flow); + struct flow_offload_tuple_rhash *flow_offload_lookup(struct nf_flowtable *flow_table, + struct flow_offload_tuple *tuple); + int nf_flow_table_iterate(struct nf_flowtable *flow_table, +--- a/net/netfilter/nf_flow_table.c ++++ b/net/netfilter/nf_flow_table.c +@@ -125,7 +125,9 @@ void flow_offload_free(struct flow_offlo + dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache); + dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache); + e = container_of(flow, struct flow_offload_entry, flow); +- kfree(e); ++ nf_ct_delete(e->ct, 0, 0); ++ nf_ct_put(e->ct); ++ kfree_rcu(e, rcu_head); + } + EXPORT_SYMBOL_GPL(flow_offload_free); + +@@ -149,11 +151,9 @@ int flow_offload_add(struct nf_flowtable + } + EXPORT_SYMBOL_GPL(flow_offload_add); + +-void flow_offload_del(struct nf_flowtable *flow_table, +- struct flow_offload *flow) ++static void flow_offload_del(struct nf_flowtable *flow_table, ++ struct flow_offload *flow) + { +- struct flow_offload_entry *e; +- + rhashtable_remove_fast(&flow_table->rhashtable, + &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, + *flow_table->type->params); +@@ -161,10 +161,8 @@ void flow_offload_del(struct nf_flowtabl + &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, + *flow_table->type->params); + +- e = container_of(flow, struct flow_offload_entry, flow); +- kfree_rcu(e, rcu_head); ++ flow_offload_free(flow); + } +-EXPORT_SYMBOL_GPL(flow_offload_del); + + struct flow_offload_tuple_rhash * + flow_offload_lookup(struct nf_flowtable *flow_table, +@@ -175,15 +173,6 @@ flow_offload_lookup(struct nf_flowtable + } + EXPORT_SYMBOL_GPL(flow_offload_lookup); + +-static void nf_flow_release_ct(const struct flow_offload *flow) +-{ +- struct flow_offload_entry *e; +- +- e = container_of(flow, struct flow_offload_entry, flow); +- nf_ct_delete(e->ct, 0, 0); +- nf_ct_put(e->ct); +-} +- + int nf_flow_table_iterate(struct nf_flowtable *flow_table, + void (*iter)(struct flow_offload *flow, void *data), + void *data) +@@ -259,10 +248,8 @@ static int nf_flow_offload_gc_step(struc + flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); + + if (nf_flow_has_expired(flow) || +- nf_flow_is_dying(flow)) { ++ nf_flow_is_dying(flow)) + flow_offload_del(flow_table, flow); +- nf_flow_release_ct(flow); +- } + } + out: + rhashtable_walk_stop(&hti); diff --git a/target/linux/generic/backport-4.14/346-netfilter-flowtable-infrastructure-depends-on-NETFIL.patch b/target/linux/generic/backport-4.14/346-netfilter-flowtable-infrastructure-depends-on-NETFIL.patch new file mode 100644 index 000000000..5267fd2f6 --- /dev/null +++ b/target/linux/generic/backport-4.14/346-netfilter-flowtable-infrastructure-depends-on-NETFIL.patch @@ -0,0 +1,73 @@ +From: Pablo Neira Ayuso +Date: Wed, 31 Jan 2018 18:13:39 +0100 +Subject: [PATCH] netfilter: flowtable infrastructure depends on + NETFILTER_INGRESS + +config NF_FLOW_TABLE depends on NETFILTER_INGRESS. If users forget to +enable this toggle, flowtable registration fails with EOPNOTSUPP. + +Moreover, turn 'select NF_FLOW_TABLE' in every flowtable family flavour +into dependency instead, otherwise this new dependency on +NETFILTER_INGRESS causes a warning. This also allows us to remove the +explicit dependency between family flowtables <-> NF_TABLES and +NF_CONNTRACK, given they depend on the NF_FLOW_TABLE core that already +expresses the general dependencies for this new infrastructure. + +Moreover, NF_FLOW_TABLE_INET depends on NF_FLOW_TABLE_IPV4 and +NF_FLOWTABLE_IPV6, which already depends on NF_FLOW_TABLE. So we can get +rid of direct dependency with NF_FLOW_TABLE. + +In general, let's avoid 'select', it just makes things more complicated. + +Reported-by: John Crispin +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/ipv4/netfilter/Kconfig ++++ b/net/ipv4/netfilter/Kconfig +@@ -79,8 +79,7 @@ endif # NF_TABLES + + config NF_FLOW_TABLE_IPV4 + tristate "Netfilter flow table IPv4 module" +- depends on NF_CONNTRACK && NF_TABLES +- select NF_FLOW_TABLE ++ depends on NF_FLOW_TABLE + help + This option adds the flow table IPv4 support. + +--- a/net/ipv6/netfilter/Kconfig ++++ b/net/ipv6/netfilter/Kconfig +@@ -73,8 +73,7 @@ endif # NF_TABLES + + config NF_FLOW_TABLE_IPV6 + tristate "Netfilter flow table IPv6 module" +- depends on NF_CONNTRACK && NF_TABLES +- select NF_FLOW_TABLE ++ depends on NF_FLOW_TABLE + help + This option adds the flow table IPv6 support. + +--- a/net/netfilter/Kconfig ++++ b/net/netfilter/Kconfig +@@ -670,8 +670,8 @@ endif # NF_TABLES + + config NF_FLOW_TABLE_INET + tristate "Netfilter flow table mixed IPv4/IPv6 module" +- depends on NF_FLOW_TABLE_IPV4 && NF_FLOW_TABLE_IPV6 +- select NF_FLOW_TABLE ++ depends on NF_FLOW_TABLE_IPV4 ++ depends on NF_FLOW_TABLE_IPV6 + help + This option adds the flow table mixed IPv4/IPv6 support. + +@@ -679,7 +679,9 @@ config NF_FLOW_TABLE_INET + + config NF_FLOW_TABLE + tristate "Netfilter flow table module" +- depends on NF_CONNTRACK && NF_TABLES ++ depends on NETFILTER_INGRESS ++ depends on NF_CONNTRACK ++ depends on NF_TABLES + help + This option adds the flow table core infrastructure. + diff --git a/target/linux/generic/backport-4.14/347-netfilter-remove-duplicated-include.patch b/target/linux/generic/backport-4.14/347-netfilter-remove-duplicated-include.patch new file mode 100644 index 000000000..c8a097272 --- /dev/null +++ b/target/linux/generic/backport-4.14/347-netfilter-remove-duplicated-include.patch @@ -0,0 +1,29 @@ +From: Wei Yongjun +Date: Wed, 10 Jan 2018 13:06:46 +0000 +Subject: [PATCH] netfilter: remove duplicated include + +Signed-off-by: Wei Yongjun +Signed-off-by: Pablo Neira Ayuso +--- + +--- a/net/ipv6/netfilter/nf_flow_table_ipv6.c ++++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c +@@ -5,7 +5,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- a/net/netfilter/nf_queue.c ++++ b/net/netfilter/nf_queue.c +@@ -15,8 +15,6 @@ + #include + #include + #include +-#include +-#include + #include + #include + #include diff --git a/target/linux/generic/backport-4.14/348-netfilter-nf_flow_table-use-IP_CT_DIR_-values-for-FL.patch b/target/linux/generic/backport-4.14/348-netfilter-nf_flow_table-use-IP_CT_DIR_-values-for-FL.patch new file mode 100644 index 000000000..382b33c07 --- /dev/null +++ b/target/linux/generic/backport-4.14/348-netfilter-nf_flow_table-use-IP_CT_DIR_-values-for-FL.patch @@ -0,0 +1,35 @@ +From: Felix Fietkau +Date: Fri, 16 Feb 2018 09:41:18 +0100 +Subject: [PATCH] netfilter: nf_flow_table: use IP_CT_DIR_* values for + FLOW_OFFLOAD_DIR_* + +Simplifies further code cleanups + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + #include + + struct nf_flowtable; +@@ -27,11 +28,10 @@ struct nf_flowtable { + }; + + enum flow_offload_tuple_dir { +- FLOW_OFFLOAD_DIR_ORIGINAL, +- FLOW_OFFLOAD_DIR_REPLY, +- __FLOW_OFFLOAD_DIR_MAX = FLOW_OFFLOAD_DIR_REPLY, ++ FLOW_OFFLOAD_DIR_ORIGINAL = IP_CT_DIR_ORIGINAL, ++ FLOW_OFFLOAD_DIR_REPLY = IP_CT_DIR_REPLY, ++ FLOW_OFFLOAD_DIR_MAX = IP_CT_DIR_MAX + }; +-#define FLOW_OFFLOAD_DIR_MAX (__FLOW_OFFLOAD_DIR_MAX + 1) + + struct flow_offload_tuple { + union { diff --git a/target/linux/generic/backport-4.14/349-netfilter-nf_flow_table-clean-up-flow_offload_alloc.patch b/target/linux/generic/backport-4.14/349-netfilter-nf_flow_table-clean-up-flow_offload_alloc.patch new file mode 100644 index 000000000..39ea757f0 --- /dev/null +++ b/target/linux/generic/backport-4.14/349-netfilter-nf_flow_table-clean-up-flow_offload_alloc.patch @@ -0,0 +1,118 @@ +From: Felix Fietkau +Date: Fri, 16 Feb 2018 09:42:32 +0100 +Subject: [PATCH] netfilter: nf_flow_table: clean up flow_offload_alloc + +Reduce code duplication and make it much easier to read + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nf_flow_table.c ++++ b/net/netfilter/nf_flow_table.c +@@ -16,6 +16,38 @@ struct flow_offload_entry { + struct rcu_head rcu_head; + }; + ++static void ++flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct, ++ struct nf_flow_route *route, ++ enum flow_offload_tuple_dir dir) ++{ ++ struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple; ++ struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple; ++ ++ ft->dir = dir; ++ ++ switch (ctt->src.l3num) { ++ case NFPROTO_IPV4: ++ ft->src_v4 = ctt->src.u3.in; ++ ft->dst_v4 = ctt->dst.u3.in; ++ break; ++ case NFPROTO_IPV6: ++ ft->src_v6 = ctt->src.u3.in6; ++ ft->dst_v6 = ctt->dst.u3.in6; ++ break; ++ } ++ ++ ft->l3proto = ctt->src.l3num; ++ ft->l4proto = ctt->dst.protonum; ++ ft->src_port = ctt->src.u.tcp.port; ++ ft->dst_port = ctt->dst.u.tcp.port; ++ ++ ft->iifidx = route->tuple[dir].ifindex; ++ ft->oifidx = route->tuple[!dir].ifindex; ++ ++ ft->dst_cache = route->tuple[dir].dst; ++} ++ + struct flow_offload * + flow_offload_alloc(struct nf_conn *ct, struct nf_flow_route *route) + { +@@ -40,65 +72,8 @@ flow_offload_alloc(struct nf_conn *ct, s + + entry->ct = ct; + +- switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num) { +- case NFPROTO_IPV4: +- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v4 = +- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.in; +- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v4 = +- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in; +- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v4 = +- ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.in; +- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v4 = +- ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.in; +- break; +- case NFPROTO_IPV6: +- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6 = +- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.in6; +- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6 = +- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in6; +- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6 = +- ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.in6; +- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6 = +- ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.in6; +- break; +- } +- +- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.l3proto = +- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; +- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.l4proto = +- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; +- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.l3proto = +- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; +- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.l4proto = +- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; +- +- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache = +- route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst; +- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache = +- route->tuple[FLOW_OFFLOAD_DIR_REPLY].dst; +- +- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port = +- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.tcp.port; +- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_port = +- ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.tcp.port; +- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_port = +- ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.tcp.port; +- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port = +- ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port; +- +- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dir = +- FLOW_OFFLOAD_DIR_ORIGINAL; +- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dir = +- FLOW_OFFLOAD_DIR_REPLY; +- +- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.iifidx = +- route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].ifindex; +- flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.oifidx = +- route->tuple[FLOW_OFFLOAD_DIR_REPLY].ifindex; +- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.iifidx = +- route->tuple[FLOW_OFFLOAD_DIR_REPLY].ifindex; +- flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.oifidx = +- route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].ifindex; ++ flow_offload_fill_dir(flow, ct, route, FLOW_OFFLOAD_DIR_ORIGINAL); ++ flow_offload_fill_dir(flow, ct, route, FLOW_OFFLOAD_DIR_REPLY); + + if (ct->status & IPS_SRC_NAT) + flow->flags |= FLOW_OFFLOAD_SNAT; diff --git a/target/linux/generic/backport-4.14/350-ipv6-make-ip6_dst_mtu_forward-inline.patch b/target/linux/generic/backport-4.14/350-ipv6-make-ip6_dst_mtu_forward-inline.patch new file mode 100644 index 000000000..3a0275bd3 --- /dev/null +++ b/target/linux/generic/backport-4.14/350-ipv6-make-ip6_dst_mtu_forward-inline.patch @@ -0,0 +1,80 @@ +From: Felix Fietkau +Date: Fri, 16 Feb 2018 10:54:24 +0100 +Subject: [PATCH] ipv6: make ip6_dst_mtu_forward inline + +Removes a direct dependency on ipv6.ko + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/ip6_route.h ++++ b/include/net/ip6_route.h +@@ -252,4 +252,26 @@ static inline bool rt6_duplicate_nexthop + ipv6_addr_equal(&a->rt6i_gateway, &b->rt6i_gateway) && + !lwtunnel_cmp_encap(a->dst.lwtstate, b->dst.lwtstate); + } ++ ++static inline unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) ++{ ++ unsigned int mtu; ++ struct inet6_dev *idev; ++ ++ if (dst_metric_locked(dst, RTAX_MTU)) { ++ mtu = dst_metric_raw(dst, RTAX_MTU); ++ if (mtu) ++ return mtu; ++ } ++ ++ mtu = IPV6_MIN_MTU; ++ rcu_read_lock(); ++ idev = __in6_dev_get(dst->dev); ++ if (idev) ++ mtu = idev->cnf.mtu6; ++ rcu_read_unlock(); ++ ++ return mtu; ++} ++ + #endif +--- a/include/net/ipv6.h ++++ b/include/net/ipv6.h +@@ -913,8 +913,6 @@ static inline struct sk_buff *ip6_finish + &inet6_sk(sk)->cork); + } + +-unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst); +- + int ip6_dst_lookup(struct net *net, struct sock *sk, struct dst_entry **dst, + struct flowi6 *fl6); + struct dst_entry *ip6_dst_lookup_flow(const struct sock *sk, struct flowi6 *fl6, +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -370,28 +370,6 @@ static inline int ip6_forward_finish(str + return dst_output(net, sk, skb); + } + +-unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) +-{ +- unsigned int mtu; +- struct inet6_dev *idev; +- +- if (dst_metric_locked(dst, RTAX_MTU)) { +- mtu = dst_metric_raw(dst, RTAX_MTU); +- if (mtu) +- return mtu; +- } +- +- mtu = IPV6_MIN_MTU; +- rcu_read_lock(); +- idev = __in6_dev_get(dst->dev); +- if (idev) +- mtu = idev->cnf.mtu6; +- rcu_read_unlock(); +- +- return mtu; +-} +-EXPORT_SYMBOL_GPL(ip6_dst_mtu_forward); +- + static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu) + { + if (skb->len <= mtu) diff --git a/target/linux/generic/backport-4.14/351-netfilter-nf_flow_table-cache-mtu-in-struct-flow_off.patch b/target/linux/generic/backport-4.14/351-netfilter-nf_flow_table-cache-mtu-in-struct-flow_off.patch new file mode 100644 index 000000000..e2015e72a --- /dev/null +++ b/target/linux/generic/backport-4.14/351-netfilter-nf_flow_table-cache-mtu-in-struct-flow_off.patch @@ -0,0 +1,145 @@ +From: Felix Fietkau +Date: Fri, 16 Feb 2018 10:57:23 +0100 +Subject: [PATCH] netfilter: nf_flow_table: cache mtu in struct + flow_offload_tuple + +Reduces the number of cache lines touched in the offload forwarding path + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -55,6 +55,8 @@ struct flow_offload_tuple { + + int oifidx; + ++ u16 mtu; ++ + struct dst_entry *dst_cache; + }; + +--- a/net/ipv4/netfilter/nf_flow_table_ipv4.c ++++ b/net/ipv4/netfilter/nf_flow_table_ipv4.c +@@ -177,7 +177,7 @@ static int nf_flow_tuple_ip(struct sk_bu + } + + /* Based on ip_exceeds_mtu(). */ +-static bool __nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) ++static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) + { + if (skb->len <= mtu) + return false; +@@ -191,17 +191,6 @@ static bool __nf_flow_exceeds_mtu(const + return true; + } + +-static bool nf_flow_exceeds_mtu(struct sk_buff *skb, const struct rtable *rt) +-{ +- u32 mtu; +- +- mtu = ip_dst_mtu_maybe_forward(&rt->dst, true); +- if (__nf_flow_exceeds_mtu(skb, mtu)) +- return true; +- +- return false; +-} +- + unsigned int + nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, + const struct nf_hook_state *state) +@@ -232,9 +221,9 @@ nf_flow_offload_ip_hook(void *priv, stru + + dir = tuplehash->tuple.dir; + flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); +- + rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache; +- if (unlikely(nf_flow_exceeds_mtu(skb, rt))) ++ ++ if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) + return NF_ACCEPT; + + if (skb_try_make_writable(skb, sizeof(*iph))) +--- a/net/ipv6/netfilter/nf_flow_table_ipv6.c ++++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c +@@ -173,7 +173,7 @@ static int nf_flow_tuple_ipv6(struct sk_ + } + + /* Based on ip_exceeds_mtu(). */ +-static bool __nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) ++static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) + { + if (skb->len <= mtu) + return false; +@@ -184,17 +184,6 @@ static bool __nf_flow_exceeds_mtu(const + return true; + } + +-static bool nf_flow_exceeds_mtu(struct sk_buff *skb, const struct rt6_info *rt) +-{ +- u32 mtu; +- +- mtu = ip6_dst_mtu_forward(&rt->dst); +- if (__nf_flow_exceeds_mtu(skb, mtu)) +- return true; +- +- return false; +-} +- + unsigned int + nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, + const struct nf_hook_state *state) +@@ -225,9 +214,9 @@ nf_flow_offload_ipv6_hook(void *priv, st + + dir = tuplehash->tuple.dir; + flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); +- + rt = (struct rt6_info *)flow->tuplehash[dir].tuple.dst_cache; +- if (unlikely(nf_flow_exceeds_mtu(skb, rt))) ++ ++ if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) + return NF_ACCEPT; + + if (skb_try_make_writable(skb, sizeof(*ip6h))) +--- a/net/netfilter/nf_flow_table.c ++++ b/net/netfilter/nf_flow_table.c +@@ -4,6 +4,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -23,6 +25,7 @@ flow_offload_fill_dir(struct flow_offloa + { + struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple; + struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple; ++ struct dst_entry *dst = route->tuple[dir].dst; + + ft->dir = dir; + +@@ -30,10 +33,12 @@ flow_offload_fill_dir(struct flow_offloa + case NFPROTO_IPV4: + ft->src_v4 = ctt->src.u3.in; + ft->dst_v4 = ctt->dst.u3.in; ++ ft->mtu = ip_dst_mtu_maybe_forward(dst, true); + break; + case NFPROTO_IPV6: + ft->src_v6 = ctt->src.u3.in6; + ft->dst_v6 = ctt->dst.u3.in6; ++ ft->mtu = ip6_dst_mtu_forward(dst); + break; + } + +@@ -44,8 +49,7 @@ flow_offload_fill_dir(struct flow_offloa + + ft->iifidx = route->tuple[dir].ifindex; + ft->oifidx = route->tuple[!dir].ifindex; +- +- ft->dst_cache = route->tuple[dir].dst; ++ ft->dst_cache = dst; + } + + struct flow_offload * diff --git a/target/linux/generic/backport-4.14/352-netfilter-nf_flow_table-rename-nf_flow_table.c-to-nf.patch b/target/linux/generic/backport-4.14/352-netfilter-nf_flow_table-rename-nf_flow_table.c-to-nf.patch new file mode 100644 index 000000000..5df56dd64 --- /dev/null +++ b/target/linux/generic/backport-4.14/352-netfilter-nf_flow_table-rename-nf_flow_table.c-to-nf.patch @@ -0,0 +1,952 @@ +From: Felix Fietkau +Date: Fri, 16 Feb 2018 11:08:47 +0100 +Subject: [PATCH] netfilter: nf_flow_table: rename nf_flow_table.c to + nf_flow_table_core.c + +Preparation for adding more code to the same module + +Signed-off-by: Felix Fietkau +--- + rename net/netfilter/{nf_flow_table.c => nf_flow_table_core.c} (100%) + +--- a/net/netfilter/Makefile ++++ b/net/netfilter/Makefile +@@ -113,6 +113,8 @@ obj-$(CONFIG_NFT_FWD_NETDEV) += nft_fwd_ + + # flow table infrastructure + obj-$(CONFIG_NF_FLOW_TABLE) += nf_flow_table.o ++nf_flow_table-objs := nf_flow_table_core.o ++ + obj-$(CONFIG_NF_FLOW_TABLE_INET) += nf_flow_table_inet.o + + # generic X tables +--- a/net/netfilter/nf_flow_table.c ++++ /dev/null +@@ -1,462 +0,0 @@ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-struct flow_offload_entry { +- struct flow_offload flow; +- struct nf_conn *ct; +- struct rcu_head rcu_head; +-}; +- +-static void +-flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct, +- struct nf_flow_route *route, +- enum flow_offload_tuple_dir dir) +-{ +- struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple; +- struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple; +- struct dst_entry *dst = route->tuple[dir].dst; +- +- ft->dir = dir; +- +- switch (ctt->src.l3num) { +- case NFPROTO_IPV4: +- ft->src_v4 = ctt->src.u3.in; +- ft->dst_v4 = ctt->dst.u3.in; +- ft->mtu = ip_dst_mtu_maybe_forward(dst, true); +- break; +- case NFPROTO_IPV6: +- ft->src_v6 = ctt->src.u3.in6; +- ft->dst_v6 = ctt->dst.u3.in6; +- ft->mtu = ip6_dst_mtu_forward(dst); +- break; +- } +- +- ft->l3proto = ctt->src.l3num; +- ft->l4proto = ctt->dst.protonum; +- ft->src_port = ctt->src.u.tcp.port; +- ft->dst_port = ctt->dst.u.tcp.port; +- +- ft->iifidx = route->tuple[dir].ifindex; +- ft->oifidx = route->tuple[!dir].ifindex; +- ft->dst_cache = dst; +-} +- +-struct flow_offload * +-flow_offload_alloc(struct nf_conn *ct, struct nf_flow_route *route) +-{ +- struct flow_offload_entry *entry; +- struct flow_offload *flow; +- +- if (unlikely(nf_ct_is_dying(ct) || +- !atomic_inc_not_zero(&ct->ct_general.use))) +- return NULL; +- +- entry = kzalloc(sizeof(*entry), GFP_ATOMIC); +- if (!entry) +- goto err_ct_refcnt; +- +- flow = &entry->flow; +- +- if (!dst_hold_safe(route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst)) +- goto err_dst_cache_original; +- +- if (!dst_hold_safe(route->tuple[FLOW_OFFLOAD_DIR_REPLY].dst)) +- goto err_dst_cache_reply; +- +- entry->ct = ct; +- +- flow_offload_fill_dir(flow, ct, route, FLOW_OFFLOAD_DIR_ORIGINAL); +- flow_offload_fill_dir(flow, ct, route, FLOW_OFFLOAD_DIR_REPLY); +- +- if (ct->status & IPS_SRC_NAT) +- flow->flags |= FLOW_OFFLOAD_SNAT; +- else if (ct->status & IPS_DST_NAT) +- flow->flags |= FLOW_OFFLOAD_DNAT; +- +- return flow; +- +-err_dst_cache_reply: +- dst_release(route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst); +-err_dst_cache_original: +- kfree(entry); +-err_ct_refcnt: +- nf_ct_put(ct); +- +- return NULL; +-} +-EXPORT_SYMBOL_GPL(flow_offload_alloc); +- +-void flow_offload_free(struct flow_offload *flow) +-{ +- struct flow_offload_entry *e; +- +- dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache); +- dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache); +- e = container_of(flow, struct flow_offload_entry, flow); +- nf_ct_delete(e->ct, 0, 0); +- nf_ct_put(e->ct); +- kfree_rcu(e, rcu_head); +-} +-EXPORT_SYMBOL_GPL(flow_offload_free); +- +-void flow_offload_dead(struct flow_offload *flow) +-{ +- flow->flags |= FLOW_OFFLOAD_DYING; +-} +-EXPORT_SYMBOL_GPL(flow_offload_dead); +- +-int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) +-{ +- flow->timeout = (u32)jiffies; +- +- rhashtable_insert_fast(&flow_table->rhashtable, +- &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, +- *flow_table->type->params); +- rhashtable_insert_fast(&flow_table->rhashtable, +- &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, +- *flow_table->type->params); +- return 0; +-} +-EXPORT_SYMBOL_GPL(flow_offload_add); +- +-static void flow_offload_del(struct nf_flowtable *flow_table, +- struct flow_offload *flow) +-{ +- rhashtable_remove_fast(&flow_table->rhashtable, +- &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, +- *flow_table->type->params); +- rhashtable_remove_fast(&flow_table->rhashtable, +- &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, +- *flow_table->type->params); +- +- flow_offload_free(flow); +-} +- +-struct flow_offload_tuple_rhash * +-flow_offload_lookup(struct nf_flowtable *flow_table, +- struct flow_offload_tuple *tuple) +-{ +- return rhashtable_lookup_fast(&flow_table->rhashtable, tuple, +- *flow_table->type->params); +-} +-EXPORT_SYMBOL_GPL(flow_offload_lookup); +- +-int nf_flow_table_iterate(struct nf_flowtable *flow_table, +- void (*iter)(struct flow_offload *flow, void *data), +- void *data) +-{ +- struct flow_offload_tuple_rhash *tuplehash; +- struct rhashtable_iter hti; +- struct flow_offload *flow; +- int err; +- +- err = rhashtable_walk_init(&flow_table->rhashtable, &hti, GFP_KERNEL); +- if (err) +- return err; +- +- rhashtable_walk_start(&hti); +- +- while ((tuplehash = rhashtable_walk_next(&hti))) { +- if (IS_ERR(tuplehash)) { +- err = PTR_ERR(tuplehash); +- if (err != -EAGAIN) +- goto out; +- +- continue; +- } +- if (tuplehash->tuple.dir) +- continue; +- +- flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); +- +- iter(flow, data); +- } +-out: +- rhashtable_walk_stop(&hti); +- rhashtable_walk_exit(&hti); +- +- return err; +-} +-EXPORT_SYMBOL_GPL(nf_flow_table_iterate); +- +-static inline bool nf_flow_has_expired(const struct flow_offload *flow) +-{ +- return (__s32)(flow->timeout - (u32)jiffies) <= 0; +-} +- +-static inline bool nf_flow_is_dying(const struct flow_offload *flow) +-{ +- return flow->flags & FLOW_OFFLOAD_DYING; +-} +- +-static int nf_flow_offload_gc_step(struct nf_flowtable *flow_table) +-{ +- struct flow_offload_tuple_rhash *tuplehash; +- struct rhashtable_iter hti; +- struct flow_offload *flow; +- int err; +- +- err = rhashtable_walk_init(&flow_table->rhashtable, &hti, GFP_KERNEL); +- if (err) +- return 0; +- +- rhashtable_walk_start(&hti); +- +- while ((tuplehash = rhashtable_walk_next(&hti))) { +- if (IS_ERR(tuplehash)) { +- err = PTR_ERR(tuplehash); +- if (err != -EAGAIN) +- goto out; +- +- continue; +- } +- if (tuplehash->tuple.dir) +- continue; +- +- flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); +- +- if (nf_flow_has_expired(flow) || +- nf_flow_is_dying(flow)) +- flow_offload_del(flow_table, flow); +- } +-out: +- rhashtable_walk_stop(&hti); +- rhashtable_walk_exit(&hti); +- +- return 1; +-} +- +-void nf_flow_offload_work_gc(struct work_struct *work) +-{ +- struct nf_flowtable *flow_table; +- +- flow_table = container_of(work, struct nf_flowtable, gc_work.work); +- nf_flow_offload_gc_step(flow_table); +- queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ); +-} +-EXPORT_SYMBOL_GPL(nf_flow_offload_work_gc); +- +-static u32 flow_offload_hash(const void *data, u32 len, u32 seed) +-{ +- const struct flow_offload_tuple *tuple = data; +- +- return jhash(tuple, offsetof(struct flow_offload_tuple, dir), seed); +-} +- +-static u32 flow_offload_hash_obj(const void *data, u32 len, u32 seed) +-{ +- const struct flow_offload_tuple_rhash *tuplehash = data; +- +- return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, dir), seed); +-} +- +-static int flow_offload_hash_cmp(struct rhashtable_compare_arg *arg, +- const void *ptr) +-{ +- const struct flow_offload_tuple *tuple = arg->key; +- const struct flow_offload_tuple_rhash *x = ptr; +- +- if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, dir))) +- return 1; +- +- return 0; +-} +- +-const struct rhashtable_params nf_flow_offload_rhash_params = { +- .head_offset = offsetof(struct flow_offload_tuple_rhash, node), +- .hashfn = flow_offload_hash, +- .obj_hashfn = flow_offload_hash_obj, +- .obj_cmpfn = flow_offload_hash_cmp, +- .automatic_shrinking = true, +-}; +-EXPORT_SYMBOL_GPL(nf_flow_offload_rhash_params); +- +-static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff, +- __be16 port, __be16 new_port) +-{ +- struct tcphdr *tcph; +- +- if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || +- skb_try_make_writable(skb, thoff + sizeof(*tcph))) +- return -1; +- +- tcph = (void *)(skb_network_header(skb) + thoff); +- inet_proto_csum_replace2(&tcph->check, skb, port, new_port, true); +- +- return 0; +-} +- +-static int nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff, +- __be16 port, __be16 new_port) +-{ +- struct udphdr *udph; +- +- if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || +- skb_try_make_writable(skb, thoff + sizeof(*udph))) +- return -1; +- +- udph = (void *)(skb_network_header(skb) + thoff); +- if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { +- inet_proto_csum_replace2(&udph->check, skb, port, +- new_port, true); +- if (!udph->check) +- udph->check = CSUM_MANGLED_0; +- } +- +- return 0; +-} +- +-static int nf_flow_nat_port(struct sk_buff *skb, unsigned int thoff, +- u8 protocol, __be16 port, __be16 new_port) +-{ +- switch (protocol) { +- case IPPROTO_TCP: +- if (nf_flow_nat_port_tcp(skb, thoff, port, new_port) < 0) +- return NF_DROP; +- break; +- case IPPROTO_UDP: +- if (nf_flow_nat_port_udp(skb, thoff, port, new_port) < 0) +- return NF_DROP; +- break; +- } +- +- return 0; +-} +- +-int nf_flow_snat_port(const struct flow_offload *flow, +- struct sk_buff *skb, unsigned int thoff, +- u8 protocol, enum flow_offload_tuple_dir dir) +-{ +- struct flow_ports *hdr; +- __be16 port, new_port; +- +- if (!pskb_may_pull(skb, thoff + sizeof(*hdr)) || +- skb_try_make_writable(skb, thoff + sizeof(*hdr))) +- return -1; +- +- hdr = (void *)(skb_network_header(skb) + thoff); +- +- switch (dir) { +- case FLOW_OFFLOAD_DIR_ORIGINAL: +- port = hdr->source; +- new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port; +- hdr->source = new_port; +- break; +- case FLOW_OFFLOAD_DIR_REPLY: +- port = hdr->dest; +- new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port; +- hdr->dest = new_port; +- break; +- default: +- return -1; +- } +- +- return nf_flow_nat_port(skb, thoff, protocol, port, new_port); +-} +-EXPORT_SYMBOL_GPL(nf_flow_snat_port); +- +-int nf_flow_dnat_port(const struct flow_offload *flow, +- struct sk_buff *skb, unsigned int thoff, +- u8 protocol, enum flow_offload_tuple_dir dir) +-{ +- struct flow_ports *hdr; +- __be16 port, new_port; +- +- if (!pskb_may_pull(skb, thoff + sizeof(*hdr)) || +- skb_try_make_writable(skb, thoff + sizeof(*hdr))) +- return -1; +- +- hdr = (void *)(skb_network_header(skb) + thoff); +- +- switch (dir) { +- case FLOW_OFFLOAD_DIR_ORIGINAL: +- port = hdr->dest; +- new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_port; +- hdr->dest = new_port; +- break; +- case FLOW_OFFLOAD_DIR_REPLY: +- port = hdr->source; +- new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_port; +- hdr->source = new_port; +- break; +- default: +- return -1; +- } +- +- return nf_flow_nat_port(skb, thoff, protocol, port, new_port); +-} +-EXPORT_SYMBOL_GPL(nf_flow_dnat_port); +- +-static void nf_flow_table_do_cleanup(struct flow_offload *flow, void *data) +-{ +- struct net_device *dev = data; +- +- if (dev && flow->tuplehash[0].tuple.iifidx != dev->ifindex) +- return; +- +- flow_offload_dead(flow); +-} +- +-static void nf_flow_table_iterate_cleanup(struct nf_flowtable *flowtable, +- void *data) +-{ +- nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, data); +- flush_delayed_work(&flowtable->gc_work); +-} +- +-void nf_flow_table_cleanup(struct net *net, struct net_device *dev) +-{ +- nft_flow_table_iterate(net, nf_flow_table_iterate_cleanup, dev); +-} +-EXPORT_SYMBOL_GPL(nf_flow_table_cleanup); +- +-void nf_flow_table_free(struct nf_flowtable *flow_table) +-{ +- nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL); +- WARN_ON(!nf_flow_offload_gc_step(flow_table)); +-} +-EXPORT_SYMBOL_GPL(nf_flow_table_free); +- +-static int nf_flow_table_netdev_event(struct notifier_block *this, +- unsigned long event, void *ptr) +-{ +- struct net_device *dev = netdev_notifier_info_to_dev(ptr); +- +- if (event != NETDEV_DOWN) +- return NOTIFY_DONE; +- +- nf_flow_table_cleanup(dev_net(dev), dev); +- +- return NOTIFY_DONE; +-} +- +-static struct notifier_block flow_offload_netdev_notifier = { +- .notifier_call = nf_flow_table_netdev_event, +-}; +- +-static int __init nf_flow_table_module_init(void) +-{ +- return register_netdevice_notifier(&flow_offload_netdev_notifier); +-} +- +-static void __exit nf_flow_table_module_exit(void) +-{ +- unregister_netdevice_notifier(&flow_offload_netdev_notifier); +-} +- +-module_init(nf_flow_table_module_init); +-module_exit(nf_flow_table_module_exit); +- +-MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("Pablo Neira Ayuso "); +--- /dev/null ++++ b/net/netfilter/nf_flow_table_core.c +@@ -0,0 +1,462 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct flow_offload_entry { ++ struct flow_offload flow; ++ struct nf_conn *ct; ++ struct rcu_head rcu_head; ++}; ++ ++static void ++flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct, ++ struct nf_flow_route *route, ++ enum flow_offload_tuple_dir dir) ++{ ++ struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple; ++ struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple; ++ struct dst_entry *dst = route->tuple[dir].dst; ++ ++ ft->dir = dir; ++ ++ switch (ctt->src.l3num) { ++ case NFPROTO_IPV4: ++ ft->src_v4 = ctt->src.u3.in; ++ ft->dst_v4 = ctt->dst.u3.in; ++ ft->mtu = ip_dst_mtu_maybe_forward(dst, true); ++ break; ++ case NFPROTO_IPV6: ++ ft->src_v6 = ctt->src.u3.in6; ++ ft->dst_v6 = ctt->dst.u3.in6; ++ ft->mtu = ip6_dst_mtu_forward(dst); ++ break; ++ } ++ ++ ft->l3proto = ctt->src.l3num; ++ ft->l4proto = ctt->dst.protonum; ++ ft->src_port = ctt->src.u.tcp.port; ++ ft->dst_port = ctt->dst.u.tcp.port; ++ ++ ft->iifidx = route->tuple[dir].ifindex; ++ ft->oifidx = route->tuple[!dir].ifindex; ++ ft->dst_cache = dst; ++} ++ ++struct flow_offload * ++flow_offload_alloc(struct nf_conn *ct, struct nf_flow_route *route) ++{ ++ struct flow_offload_entry *entry; ++ struct flow_offload *flow; ++ ++ if (unlikely(nf_ct_is_dying(ct) || ++ !atomic_inc_not_zero(&ct->ct_general.use))) ++ return NULL; ++ ++ entry = kzalloc(sizeof(*entry), GFP_ATOMIC); ++ if (!entry) ++ goto err_ct_refcnt; ++ ++ flow = &entry->flow; ++ ++ if (!dst_hold_safe(route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst)) ++ goto err_dst_cache_original; ++ ++ if (!dst_hold_safe(route->tuple[FLOW_OFFLOAD_DIR_REPLY].dst)) ++ goto err_dst_cache_reply; ++ ++ entry->ct = ct; ++ ++ flow_offload_fill_dir(flow, ct, route, FLOW_OFFLOAD_DIR_ORIGINAL); ++ flow_offload_fill_dir(flow, ct, route, FLOW_OFFLOAD_DIR_REPLY); ++ ++ if (ct->status & IPS_SRC_NAT) ++ flow->flags |= FLOW_OFFLOAD_SNAT; ++ else if (ct->status & IPS_DST_NAT) ++ flow->flags |= FLOW_OFFLOAD_DNAT; ++ ++ return flow; ++ ++err_dst_cache_reply: ++ dst_release(route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst); ++err_dst_cache_original: ++ kfree(entry); ++err_ct_refcnt: ++ nf_ct_put(ct); ++ ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(flow_offload_alloc); ++ ++void flow_offload_free(struct flow_offload *flow) ++{ ++ struct flow_offload_entry *e; ++ ++ dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache); ++ dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache); ++ e = container_of(flow, struct flow_offload_entry, flow); ++ nf_ct_delete(e->ct, 0, 0); ++ nf_ct_put(e->ct); ++ kfree_rcu(e, rcu_head); ++} ++EXPORT_SYMBOL_GPL(flow_offload_free); ++ ++void flow_offload_dead(struct flow_offload *flow) ++{ ++ flow->flags |= FLOW_OFFLOAD_DYING; ++} ++EXPORT_SYMBOL_GPL(flow_offload_dead); ++ ++int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) ++{ ++ flow->timeout = (u32)jiffies; ++ ++ rhashtable_insert_fast(&flow_table->rhashtable, ++ &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, ++ *flow_table->type->params); ++ rhashtable_insert_fast(&flow_table->rhashtable, ++ &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, ++ *flow_table->type->params); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(flow_offload_add); ++ ++static void flow_offload_del(struct nf_flowtable *flow_table, ++ struct flow_offload *flow) ++{ ++ rhashtable_remove_fast(&flow_table->rhashtable, ++ &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, ++ *flow_table->type->params); ++ rhashtable_remove_fast(&flow_table->rhashtable, ++ &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, ++ *flow_table->type->params); ++ ++ flow_offload_free(flow); ++} ++ ++struct flow_offload_tuple_rhash * ++flow_offload_lookup(struct nf_flowtable *flow_table, ++ struct flow_offload_tuple *tuple) ++{ ++ return rhashtable_lookup_fast(&flow_table->rhashtable, tuple, ++ *flow_table->type->params); ++} ++EXPORT_SYMBOL_GPL(flow_offload_lookup); ++ ++int nf_flow_table_iterate(struct nf_flowtable *flow_table, ++ void (*iter)(struct flow_offload *flow, void *data), ++ void *data) ++{ ++ struct flow_offload_tuple_rhash *tuplehash; ++ struct rhashtable_iter hti; ++ struct flow_offload *flow; ++ int err; ++ ++ err = rhashtable_walk_init(&flow_table->rhashtable, &hti, GFP_KERNEL); ++ if (err) ++ return err; ++ ++ rhashtable_walk_start(&hti); ++ ++ while ((tuplehash = rhashtable_walk_next(&hti))) { ++ if (IS_ERR(tuplehash)) { ++ err = PTR_ERR(tuplehash); ++ if (err != -EAGAIN) ++ goto out; ++ ++ continue; ++ } ++ if (tuplehash->tuple.dir) ++ continue; ++ ++ flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); ++ ++ iter(flow, data); ++ } ++out: ++ rhashtable_walk_stop(&hti); ++ rhashtable_walk_exit(&hti); ++ ++ return err; ++} ++EXPORT_SYMBOL_GPL(nf_flow_table_iterate); ++ ++static inline bool nf_flow_has_expired(const struct flow_offload *flow) ++{ ++ return (__s32)(flow->timeout - (u32)jiffies) <= 0; ++} ++ ++static inline bool nf_flow_is_dying(const struct flow_offload *flow) ++{ ++ return flow->flags & FLOW_OFFLOAD_DYING; ++} ++ ++static int nf_flow_offload_gc_step(struct nf_flowtable *flow_table) ++{ ++ struct flow_offload_tuple_rhash *tuplehash; ++ struct rhashtable_iter hti; ++ struct flow_offload *flow; ++ int err; ++ ++ err = rhashtable_walk_init(&flow_table->rhashtable, &hti, GFP_KERNEL); ++ if (err) ++ return 0; ++ ++ rhashtable_walk_start(&hti); ++ ++ while ((tuplehash = rhashtable_walk_next(&hti))) { ++ if (IS_ERR(tuplehash)) { ++ err = PTR_ERR(tuplehash); ++ if (err != -EAGAIN) ++ goto out; ++ ++ continue; ++ } ++ if (tuplehash->tuple.dir) ++ continue; ++ ++ flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); ++ ++ if (nf_flow_has_expired(flow) || ++ nf_flow_is_dying(flow)) ++ flow_offload_del(flow_table, flow); ++ } ++out: ++ rhashtable_walk_stop(&hti); ++ rhashtable_walk_exit(&hti); ++ ++ return 1; ++} ++ ++void nf_flow_offload_work_gc(struct work_struct *work) ++{ ++ struct nf_flowtable *flow_table; ++ ++ flow_table = container_of(work, struct nf_flowtable, gc_work.work); ++ nf_flow_offload_gc_step(flow_table); ++ queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ); ++} ++EXPORT_SYMBOL_GPL(nf_flow_offload_work_gc); ++ ++static u32 flow_offload_hash(const void *data, u32 len, u32 seed) ++{ ++ const struct flow_offload_tuple *tuple = data; ++ ++ return jhash(tuple, offsetof(struct flow_offload_tuple, dir), seed); ++} ++ ++static u32 flow_offload_hash_obj(const void *data, u32 len, u32 seed) ++{ ++ const struct flow_offload_tuple_rhash *tuplehash = data; ++ ++ return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, dir), seed); ++} ++ ++static int flow_offload_hash_cmp(struct rhashtable_compare_arg *arg, ++ const void *ptr) ++{ ++ const struct flow_offload_tuple *tuple = arg->key; ++ const struct flow_offload_tuple_rhash *x = ptr; ++ ++ if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, dir))) ++ return 1; ++ ++ return 0; ++} ++ ++const struct rhashtable_params nf_flow_offload_rhash_params = { ++ .head_offset = offsetof(struct flow_offload_tuple_rhash, node), ++ .hashfn = flow_offload_hash, ++ .obj_hashfn = flow_offload_hash_obj, ++ .obj_cmpfn = flow_offload_hash_cmp, ++ .automatic_shrinking = true, ++}; ++EXPORT_SYMBOL_GPL(nf_flow_offload_rhash_params); ++ ++static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff, ++ __be16 port, __be16 new_port) ++{ ++ struct tcphdr *tcph; ++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || ++ skb_try_make_writable(skb, thoff + sizeof(*tcph))) ++ return -1; ++ ++ tcph = (void *)(skb_network_header(skb) + thoff); ++ inet_proto_csum_replace2(&tcph->check, skb, port, new_port, true); ++ ++ return 0; ++} ++ ++static int nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff, ++ __be16 port, __be16 new_port) ++{ ++ struct udphdr *udph; ++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || ++ skb_try_make_writable(skb, thoff + sizeof(*udph))) ++ return -1; ++ ++ udph = (void *)(skb_network_header(skb) + thoff); ++ if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { ++ inet_proto_csum_replace2(&udph->check, skb, port, ++ new_port, true); ++ if (!udph->check) ++ udph->check = CSUM_MANGLED_0; ++ } ++ ++ return 0; ++} ++ ++static int nf_flow_nat_port(struct sk_buff *skb, unsigned int thoff, ++ u8 protocol, __be16 port, __be16 new_port) ++{ ++ switch (protocol) { ++ case IPPROTO_TCP: ++ if (nf_flow_nat_port_tcp(skb, thoff, port, new_port) < 0) ++ return NF_DROP; ++ break; ++ case IPPROTO_UDP: ++ if (nf_flow_nat_port_udp(skb, thoff, port, new_port) < 0) ++ return NF_DROP; ++ break; ++ } ++ ++ return 0; ++} ++ ++int nf_flow_snat_port(const struct flow_offload *flow, ++ struct sk_buff *skb, unsigned int thoff, ++ u8 protocol, enum flow_offload_tuple_dir dir) ++{ ++ struct flow_ports *hdr; ++ __be16 port, new_port; ++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*hdr)) || ++ skb_try_make_writable(skb, thoff + sizeof(*hdr))) ++ return -1; ++ ++ hdr = (void *)(skb_network_header(skb) + thoff); ++ ++ switch (dir) { ++ case FLOW_OFFLOAD_DIR_ORIGINAL: ++ port = hdr->source; ++ new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port; ++ hdr->source = new_port; ++ break; ++ case FLOW_OFFLOAD_DIR_REPLY: ++ port = hdr->dest; ++ new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port; ++ hdr->dest = new_port; ++ break; ++ default: ++ return -1; ++ } ++ ++ return nf_flow_nat_port(skb, thoff, protocol, port, new_port); ++} ++EXPORT_SYMBOL_GPL(nf_flow_snat_port); ++ ++int nf_flow_dnat_port(const struct flow_offload *flow, ++ struct sk_buff *skb, unsigned int thoff, ++ u8 protocol, enum flow_offload_tuple_dir dir) ++{ ++ struct flow_ports *hdr; ++ __be16 port, new_port; ++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*hdr)) || ++ skb_try_make_writable(skb, thoff + sizeof(*hdr))) ++ return -1; ++ ++ hdr = (void *)(skb_network_header(skb) + thoff); ++ ++ switch (dir) { ++ case FLOW_OFFLOAD_DIR_ORIGINAL: ++ port = hdr->dest; ++ new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_port; ++ hdr->dest = new_port; ++ break; ++ case FLOW_OFFLOAD_DIR_REPLY: ++ port = hdr->source; ++ new_port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_port; ++ hdr->source = new_port; ++ break; ++ default: ++ return -1; ++ } ++ ++ return nf_flow_nat_port(skb, thoff, protocol, port, new_port); ++} ++EXPORT_SYMBOL_GPL(nf_flow_dnat_port); ++ ++static void nf_flow_table_do_cleanup(struct flow_offload *flow, void *data) ++{ ++ struct net_device *dev = data; ++ ++ if (dev && flow->tuplehash[0].tuple.iifidx != dev->ifindex) ++ return; ++ ++ flow_offload_dead(flow); ++} ++ ++static void nf_flow_table_iterate_cleanup(struct nf_flowtable *flowtable, ++ void *data) ++{ ++ nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, data); ++ flush_delayed_work(&flowtable->gc_work); ++} ++ ++void nf_flow_table_cleanup(struct net *net, struct net_device *dev) ++{ ++ nft_flow_table_iterate(net, nf_flow_table_iterate_cleanup, dev); ++} ++EXPORT_SYMBOL_GPL(nf_flow_table_cleanup); ++ ++void nf_flow_table_free(struct nf_flowtable *flow_table) ++{ ++ nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL); ++ WARN_ON(!nf_flow_offload_gc_step(flow_table)); ++} ++EXPORT_SYMBOL_GPL(nf_flow_table_free); ++ ++static int nf_flow_table_netdev_event(struct notifier_block *this, ++ unsigned long event, void *ptr) ++{ ++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++ ++ if (event != NETDEV_DOWN) ++ return NOTIFY_DONE; ++ ++ nf_flow_table_cleanup(dev_net(dev), dev); ++ ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block flow_offload_netdev_notifier = { ++ .notifier_call = nf_flow_table_netdev_event, ++}; ++ ++static int __init nf_flow_table_module_init(void) ++{ ++ return register_netdevice_notifier(&flow_offload_netdev_notifier); ++} ++ ++static void __exit nf_flow_table_module_exit(void) ++{ ++ unregister_netdevice_notifier(&flow_offload_netdev_notifier); ++} ++ ++module_init(nf_flow_table_module_init); ++module_exit(nf_flow_table_module_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Pablo Neira Ayuso "); diff --git a/target/linux/generic/backport-4.14/353-netfilter-nf_flow_table-move-ipv4-offload-hook-code-.patch b/target/linux/generic/backport-4.14/353-netfilter-nf_flow_table-move-ipv4-offload-hook-code-.patch new file mode 100644 index 000000000..e25a66f93 --- /dev/null +++ b/target/linux/generic/backport-4.14/353-netfilter-nf_flow_table-move-ipv4-offload-hook-code-.patch @@ -0,0 +1,522 @@ +From: Felix Fietkau +Date: Sat, 17 Feb 2018 11:49:44 +0100 +Subject: [PATCH] netfilter: nf_flow_table: move ipv4 offload hook code to + nf_flow_table + +Allows some minor code sharing with the ipv6 hook code and is also +useful as preparation for adding iptables support for offload + +Signed-off-by: Felix Fietkau +--- + create mode 100644 net/netfilter/nf_flow_table_ip.c + +--- a/net/ipv4/netfilter/nf_flow_table_ipv4.c ++++ b/net/ipv4/netfilter/nf_flow_table_ipv4.c +@@ -2,248 +2,8 @@ + #include + #include + #include +-#include +-#include +-#include +-#include +-#include + #include + #include +-/* For layer 4 checksum field offset. */ +-#include +-#include +- +-static int nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff, +- __be32 addr, __be32 new_addr) +-{ +- struct tcphdr *tcph; +- +- if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || +- skb_try_make_writable(skb, thoff + sizeof(*tcph))) +- return -1; +- +- tcph = (void *)(skb_network_header(skb) + thoff); +- inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr, true); +- +- return 0; +-} +- +-static int nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff, +- __be32 addr, __be32 new_addr) +-{ +- struct udphdr *udph; +- +- if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || +- skb_try_make_writable(skb, thoff + sizeof(*udph))) +- return -1; +- +- udph = (void *)(skb_network_header(skb) + thoff); +- if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { +- inet_proto_csum_replace4(&udph->check, skb, addr, +- new_addr, true); +- if (!udph->check) +- udph->check = CSUM_MANGLED_0; +- } +- +- return 0; +-} +- +-static int nf_flow_nat_ip_l4proto(struct sk_buff *skb, struct iphdr *iph, +- unsigned int thoff, __be32 addr, +- __be32 new_addr) +-{ +- switch (iph->protocol) { +- case IPPROTO_TCP: +- if (nf_flow_nat_ip_tcp(skb, thoff, addr, new_addr) < 0) +- return NF_DROP; +- break; +- case IPPROTO_UDP: +- if (nf_flow_nat_ip_udp(skb, thoff, addr, new_addr) < 0) +- return NF_DROP; +- break; +- } +- +- return 0; +-} +- +-static int nf_flow_snat_ip(const struct flow_offload *flow, struct sk_buff *skb, +- struct iphdr *iph, unsigned int thoff, +- enum flow_offload_tuple_dir dir) +-{ +- __be32 addr, new_addr; +- +- switch (dir) { +- case FLOW_OFFLOAD_DIR_ORIGINAL: +- addr = iph->saddr; +- new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v4.s_addr; +- iph->saddr = new_addr; +- break; +- case FLOW_OFFLOAD_DIR_REPLY: +- addr = iph->daddr; +- new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v4.s_addr; +- iph->daddr = new_addr; +- break; +- default: +- return -1; +- } +- csum_replace4(&iph->check, addr, new_addr); +- +- return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); +-} +- +-static int nf_flow_dnat_ip(const struct flow_offload *flow, struct sk_buff *skb, +- struct iphdr *iph, unsigned int thoff, +- enum flow_offload_tuple_dir dir) +-{ +- __be32 addr, new_addr; +- +- switch (dir) { +- case FLOW_OFFLOAD_DIR_ORIGINAL: +- addr = iph->daddr; +- new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v4.s_addr; +- iph->daddr = new_addr; +- break; +- case FLOW_OFFLOAD_DIR_REPLY: +- addr = iph->saddr; +- new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v4.s_addr; +- iph->saddr = new_addr; +- break; +- default: +- return -1; +- } +- +- return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); +-} +- +-static int nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb, +- enum flow_offload_tuple_dir dir) +-{ +- struct iphdr *iph = ip_hdr(skb); +- unsigned int thoff = iph->ihl * 4; +- +- if (flow->flags & FLOW_OFFLOAD_SNAT && +- (nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 || +- nf_flow_snat_ip(flow, skb, iph, thoff, dir) < 0)) +- return -1; +- if (flow->flags & FLOW_OFFLOAD_DNAT && +- (nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir) < 0 || +- nf_flow_dnat_ip(flow, skb, iph, thoff, dir) < 0)) +- return -1; +- +- return 0; +-} +- +-static bool ip_has_options(unsigned int thoff) +-{ +- return thoff != sizeof(struct iphdr); +-} +- +-static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev, +- struct flow_offload_tuple *tuple) +-{ +- struct flow_ports *ports; +- unsigned int thoff; +- struct iphdr *iph; +- +- if (!pskb_may_pull(skb, sizeof(*iph))) +- return -1; +- +- iph = ip_hdr(skb); +- thoff = iph->ihl * 4; +- +- if (ip_is_fragment(iph) || +- unlikely(ip_has_options(thoff))) +- return -1; +- +- if (iph->protocol != IPPROTO_TCP && +- iph->protocol != IPPROTO_UDP) +- return -1; +- +- thoff = iph->ihl * 4; +- if (!pskb_may_pull(skb, thoff + sizeof(*ports))) +- return -1; +- +- ports = (struct flow_ports *)(skb_network_header(skb) + thoff); +- +- tuple->src_v4.s_addr = iph->saddr; +- tuple->dst_v4.s_addr = iph->daddr; +- tuple->src_port = ports->source; +- tuple->dst_port = ports->dest; +- tuple->l3proto = AF_INET; +- tuple->l4proto = iph->protocol; +- tuple->iifidx = dev->ifindex; +- +- return 0; +-} +- +-/* Based on ip_exceeds_mtu(). */ +-static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) +-{ +- if (skb->len <= mtu) +- return false; +- +- if ((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) +- return false; +- +- if (skb_is_gso(skb) && skb_gso_validate_mtu(skb, mtu)) +- return false; +- +- return true; +-} +- +-unsigned int +-nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, +- const struct nf_hook_state *state) +-{ +- struct flow_offload_tuple_rhash *tuplehash; +- struct nf_flowtable *flow_table = priv; +- struct flow_offload_tuple tuple = {}; +- enum flow_offload_tuple_dir dir; +- struct flow_offload *flow; +- struct net_device *outdev; +- const struct rtable *rt; +- struct iphdr *iph; +- __be32 nexthop; +- +- if (skb->protocol != htons(ETH_P_IP)) +- return NF_ACCEPT; +- +- if (nf_flow_tuple_ip(skb, state->in, &tuple) < 0) +- return NF_ACCEPT; +- +- tuplehash = flow_offload_lookup(flow_table, &tuple); +- if (tuplehash == NULL) +- return NF_ACCEPT; +- +- outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.oifidx); +- if (!outdev) +- return NF_ACCEPT; +- +- dir = tuplehash->tuple.dir; +- flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); +- rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache; +- +- if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) +- return NF_ACCEPT; +- +- if (skb_try_make_writable(skb, sizeof(*iph))) +- return NF_DROP; +- +- if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) && +- nf_flow_nat_ip(flow, skb, dir) < 0) +- return NF_DROP; +- +- flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; +- iph = ip_hdr(skb); +- ip_decrease_ttl(iph); +- +- skb->dev = outdev; +- nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); +- neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb); +- +- return NF_STOLEN; +-} +-EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook); + + static struct nf_flowtable_type flowtable_ipv4 = { + .family = NFPROTO_IPV4, +--- a/net/netfilter/Makefile ++++ b/net/netfilter/Makefile +@@ -113,7 +113,7 @@ obj-$(CONFIG_NFT_FWD_NETDEV) += nft_fwd_ + + # flow table infrastructure + obj-$(CONFIG_NF_FLOW_TABLE) += nf_flow_table.o +-nf_flow_table-objs := nf_flow_table_core.o ++nf_flow_table-objs := nf_flow_table_core.o nf_flow_table_ip.o + + obj-$(CONFIG_NF_FLOW_TABLE_INET) += nf_flow_table_inet.o + +--- /dev/null ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -0,0 +1,245 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++/* For layer 4 checksum field offset. */ ++#include ++#include ++ ++static int nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff, ++ __be32 addr, __be32 new_addr) ++{ ++ struct tcphdr *tcph; ++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || ++ skb_try_make_writable(skb, thoff + sizeof(*tcph))) ++ return -1; ++ ++ tcph = (void *)(skb_network_header(skb) + thoff); ++ inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr, true); ++ ++ return 0; ++} ++ ++static int nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff, ++ __be32 addr, __be32 new_addr) ++{ ++ struct udphdr *udph; ++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || ++ skb_try_make_writable(skb, thoff + sizeof(*udph))) ++ return -1; ++ ++ udph = (void *)(skb_network_header(skb) + thoff); ++ if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { ++ inet_proto_csum_replace4(&udph->check, skb, addr, ++ new_addr, true); ++ if (!udph->check) ++ udph->check = CSUM_MANGLED_0; ++ } ++ ++ return 0; ++} ++ ++static int nf_flow_nat_ip_l4proto(struct sk_buff *skb, struct iphdr *iph, ++ unsigned int thoff, __be32 addr, ++ __be32 new_addr) ++{ ++ switch (iph->protocol) { ++ case IPPROTO_TCP: ++ if (nf_flow_nat_ip_tcp(skb, thoff, addr, new_addr) < 0) ++ return NF_DROP; ++ break; ++ case IPPROTO_UDP: ++ if (nf_flow_nat_ip_udp(skb, thoff, addr, new_addr) < 0) ++ return NF_DROP; ++ break; ++ } ++ ++ return 0; ++} ++ ++static int nf_flow_snat_ip(const struct flow_offload *flow, struct sk_buff *skb, ++ struct iphdr *iph, unsigned int thoff, ++ enum flow_offload_tuple_dir dir) ++{ ++ __be32 addr, new_addr; ++ ++ switch (dir) { ++ case FLOW_OFFLOAD_DIR_ORIGINAL: ++ addr = iph->saddr; ++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v4.s_addr; ++ iph->saddr = new_addr; ++ break; ++ case FLOW_OFFLOAD_DIR_REPLY: ++ addr = iph->daddr; ++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v4.s_addr; ++ iph->daddr = new_addr; ++ break; ++ default: ++ return -1; ++ } ++ csum_replace4(&iph->check, addr, new_addr); ++ ++ return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); ++} ++ ++static int nf_flow_dnat_ip(const struct flow_offload *flow, struct sk_buff *skb, ++ struct iphdr *iph, unsigned int thoff, ++ enum flow_offload_tuple_dir dir) ++{ ++ __be32 addr, new_addr; ++ ++ switch (dir) { ++ case FLOW_OFFLOAD_DIR_ORIGINAL: ++ addr = iph->daddr; ++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v4.s_addr; ++ iph->daddr = new_addr; ++ break; ++ case FLOW_OFFLOAD_DIR_REPLY: ++ addr = iph->saddr; ++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v4.s_addr; ++ iph->saddr = new_addr; ++ break; ++ default: ++ return -1; ++ } ++ ++ return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); ++} ++ ++static int nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb, ++ enum flow_offload_tuple_dir dir) ++{ ++ struct iphdr *iph = ip_hdr(skb); ++ unsigned int thoff = iph->ihl * 4; ++ ++ if (flow->flags & FLOW_OFFLOAD_SNAT && ++ (nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 || ++ nf_flow_snat_ip(flow, skb, iph, thoff, dir) < 0)) ++ return -1; ++ if (flow->flags & FLOW_OFFLOAD_DNAT && ++ (nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir) < 0 || ++ nf_flow_dnat_ip(flow, skb, iph, thoff, dir) < 0)) ++ return -1; ++ ++ return 0; ++} ++ ++static bool ip_has_options(unsigned int thoff) ++{ ++ return thoff != sizeof(struct iphdr); ++} ++ ++static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev, ++ struct flow_offload_tuple *tuple) ++{ ++ struct flow_ports *ports; ++ unsigned int thoff; ++ struct iphdr *iph; ++ ++ if (!pskb_may_pull(skb, sizeof(*iph))) ++ return -1; ++ ++ iph = ip_hdr(skb); ++ thoff = iph->ihl * 4; ++ ++ if (ip_is_fragment(iph) || ++ unlikely(ip_has_options(thoff))) ++ return -1; ++ ++ if (iph->protocol != IPPROTO_TCP && ++ iph->protocol != IPPROTO_UDP) ++ return -1; ++ ++ thoff = iph->ihl * 4; ++ if (!pskb_may_pull(skb, thoff + sizeof(*ports))) ++ return -1; ++ ++ ports = (struct flow_ports *)(skb_network_header(skb) + thoff); ++ ++ tuple->src_v4.s_addr = iph->saddr; ++ tuple->dst_v4.s_addr = iph->daddr; ++ tuple->src_port = ports->source; ++ tuple->dst_port = ports->dest; ++ tuple->l3proto = AF_INET; ++ tuple->l4proto = iph->protocol; ++ tuple->iifidx = dev->ifindex; ++ ++ return 0; ++} ++ ++/* Based on ip_exceeds_mtu(). */ ++static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) ++{ ++ if (skb->len <= mtu) ++ return false; ++ ++ if ((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) ++ return false; ++ ++ if (skb_is_gso(skb) && skb_gso_validate_mtu(skb, mtu)) ++ return false; ++ ++ return true; ++} ++ ++unsigned int ++nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++{ ++ struct flow_offload_tuple_rhash *tuplehash; ++ struct nf_flowtable *flow_table = priv; ++ struct flow_offload_tuple tuple = {}; ++ enum flow_offload_tuple_dir dir; ++ struct flow_offload *flow; ++ struct net_device *outdev; ++ const struct rtable *rt; ++ struct iphdr *iph; ++ __be32 nexthop; ++ ++ if (skb->protocol != htons(ETH_P_IP)) ++ return NF_ACCEPT; ++ ++ if (nf_flow_tuple_ip(skb, state->in, &tuple) < 0) ++ return NF_ACCEPT; ++ ++ tuplehash = flow_offload_lookup(flow_table, &tuple); ++ if (tuplehash == NULL) ++ return NF_ACCEPT; ++ ++ outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.oifidx); ++ if (!outdev) ++ return NF_ACCEPT; ++ ++ dir = tuplehash->tuple.dir; ++ flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); ++ rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache; ++ ++ if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) ++ return NF_ACCEPT; ++ ++ if (skb_try_make_writable(skb, sizeof(*iph))) ++ return NF_DROP; ++ ++ if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) && ++ nf_flow_nat_ip(flow, skb, dir) < 0) ++ return NF_DROP; ++ ++ flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; ++ iph = ip_hdr(skb); ++ ip_decrease_ttl(iph); ++ ++ skb->dev = outdev; ++ nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); ++ neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb); ++ ++ return NF_STOLEN; ++} ++EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook); diff --git a/target/linux/generic/backport-4.14/354-netfilter-nf_flow_table-move-ip-header-check-out-of-.patch b/target/linux/generic/backport-4.14/354-netfilter-nf_flow_table-move-ip-header-check-out-of-.patch new file mode 100644 index 000000000..4ee553243 --- /dev/null +++ b/target/linux/generic/backport-4.14/354-netfilter-nf_flow_table-move-ip-header-check-out-of-.patch @@ -0,0 +1,32 @@ +From: Felix Fietkau +Date: Sat, 17 Feb 2018 11:51:20 +0100 +Subject: [PATCH] netfilter: nf_flow_table: move ip header check out of + nf_flow_exceeds_mtu + +Allows the function to be shared with the IPv6 hook code + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -181,9 +181,6 @@ static bool nf_flow_exceeds_mtu(const st + if (skb->len <= mtu) + return false; + +- if ((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) +- return false; +- + if (skb_is_gso(skb) && skb_gso_validate_mtu(skb, mtu)) + return false; + +@@ -222,7 +219,8 @@ nf_flow_offload_ip_hook(void *priv, stru + flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); + rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache; + +- if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) ++ if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)) && ++ (ip_hdr(skb)->frag_off & htons(IP_DF)) != 0) + return NF_ACCEPT; + + if (skb_try_make_writable(skb, sizeof(*iph))) diff --git a/target/linux/generic/backport-4.14/355-netfilter-nf_flow_table-move-ipv6-offload-hook-code-.patch b/target/linux/generic/backport-4.14/355-netfilter-nf_flow_table-move-ipv6-offload-hook-code-.patch new file mode 100644 index 000000000..20ab0ed50 --- /dev/null +++ b/target/linux/generic/backport-4.14/355-netfilter-nf_flow_table-move-ipv6-offload-hook-code-.patch @@ -0,0 +1,483 @@ +From: Felix Fietkau +Date: Sat, 17 Feb 2018 11:55:51 +0100 +Subject: [PATCH] netfilter: nf_flow_table: move ipv6 offload hook code to + nf_flow_table + +Useful as preparation for adding iptables support for offload + +Signed-off-by: Felix Fietkau +--- + +--- a/net/ipv6/netfilter/nf_flow_table_ipv6.c ++++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c +@@ -3,240 +3,8 @@ + #include + #include + #include +-#include +-#include +-#include +-#include +-#include + #include + #include +-/* For layer 4 checksum field offset. */ +-#include +-#include +- +-static int nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff, +- struct in6_addr *addr, +- struct in6_addr *new_addr) +-{ +- struct tcphdr *tcph; +- +- if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || +- skb_try_make_writable(skb, thoff + sizeof(*tcph))) +- return -1; +- +- tcph = (void *)(skb_network_header(skb) + thoff); +- inet_proto_csum_replace16(&tcph->check, skb, addr->s6_addr32, +- new_addr->s6_addr32, true); +- +- return 0; +-} +- +-static int nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff, +- struct in6_addr *addr, +- struct in6_addr *new_addr) +-{ +- struct udphdr *udph; +- +- if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || +- skb_try_make_writable(skb, thoff + sizeof(*udph))) +- return -1; +- +- udph = (void *)(skb_network_header(skb) + thoff); +- if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { +- inet_proto_csum_replace16(&udph->check, skb, addr->s6_addr32, +- new_addr->s6_addr32, true); +- if (!udph->check) +- udph->check = CSUM_MANGLED_0; +- } +- +- return 0; +-} +- +-static int nf_flow_nat_ipv6_l4proto(struct sk_buff *skb, struct ipv6hdr *ip6h, +- unsigned int thoff, struct in6_addr *addr, +- struct in6_addr *new_addr) +-{ +- switch (ip6h->nexthdr) { +- case IPPROTO_TCP: +- if (nf_flow_nat_ipv6_tcp(skb, thoff, addr, new_addr) < 0) +- return NF_DROP; +- break; +- case IPPROTO_UDP: +- if (nf_flow_nat_ipv6_udp(skb, thoff, addr, new_addr) < 0) +- return NF_DROP; +- break; +- } +- +- return 0; +-} +- +-static int nf_flow_snat_ipv6(const struct flow_offload *flow, +- struct sk_buff *skb, struct ipv6hdr *ip6h, +- unsigned int thoff, +- enum flow_offload_tuple_dir dir) +-{ +- struct in6_addr addr, new_addr; +- +- switch (dir) { +- case FLOW_OFFLOAD_DIR_ORIGINAL: +- addr = ip6h->saddr; +- new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6; +- ip6h->saddr = new_addr; +- break; +- case FLOW_OFFLOAD_DIR_REPLY: +- addr = ip6h->daddr; +- new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6; +- ip6h->daddr = new_addr; +- break; +- default: +- return -1; +- } +- +- return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); +-} +- +-static int nf_flow_dnat_ipv6(const struct flow_offload *flow, +- struct sk_buff *skb, struct ipv6hdr *ip6h, +- unsigned int thoff, +- enum flow_offload_tuple_dir dir) +-{ +- struct in6_addr addr, new_addr; +- +- switch (dir) { +- case FLOW_OFFLOAD_DIR_ORIGINAL: +- addr = ip6h->daddr; +- new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6; +- ip6h->daddr = new_addr; +- break; +- case FLOW_OFFLOAD_DIR_REPLY: +- addr = ip6h->saddr; +- new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6; +- ip6h->saddr = new_addr; +- break; +- default: +- return -1; +- } +- +- return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); +-} +- +-static int nf_flow_nat_ipv6(const struct flow_offload *flow, +- struct sk_buff *skb, +- enum flow_offload_tuple_dir dir) +-{ +- struct ipv6hdr *ip6h = ipv6_hdr(skb); +- unsigned int thoff = sizeof(*ip6h); +- +- if (flow->flags & FLOW_OFFLOAD_SNAT && +- (nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || +- nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) +- return -1; +- if (flow->flags & FLOW_OFFLOAD_DNAT && +- (nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || +- nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) +- return -1; +- +- return 0; +-} +- +-static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev, +- struct flow_offload_tuple *tuple) +-{ +- struct flow_ports *ports; +- struct ipv6hdr *ip6h; +- unsigned int thoff; +- +- if (!pskb_may_pull(skb, sizeof(*ip6h))) +- return -1; +- +- ip6h = ipv6_hdr(skb); +- +- if (ip6h->nexthdr != IPPROTO_TCP && +- ip6h->nexthdr != IPPROTO_UDP) +- return -1; +- +- thoff = sizeof(*ip6h); +- if (!pskb_may_pull(skb, thoff + sizeof(*ports))) +- return -1; +- +- ports = (struct flow_ports *)(skb_network_header(skb) + thoff); +- +- tuple->src_v6 = ip6h->saddr; +- tuple->dst_v6 = ip6h->daddr; +- tuple->src_port = ports->source; +- tuple->dst_port = ports->dest; +- tuple->l3proto = AF_INET6; +- tuple->l4proto = ip6h->nexthdr; +- tuple->iifidx = dev->ifindex; +- +- return 0; +-} +- +-/* Based on ip_exceeds_mtu(). */ +-static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) +-{ +- if (skb->len <= mtu) +- return false; +- +- if (skb_is_gso(skb) && skb_gso_validate_mtu(skb, mtu)) +- return false; +- +- return true; +-} +- +-unsigned int +-nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, +- const struct nf_hook_state *state) +-{ +- struct flow_offload_tuple_rhash *tuplehash; +- struct nf_flowtable *flow_table = priv; +- struct flow_offload_tuple tuple = {}; +- enum flow_offload_tuple_dir dir; +- struct flow_offload *flow; +- struct net_device *outdev; +- struct in6_addr *nexthop; +- struct ipv6hdr *ip6h; +- struct rt6_info *rt; +- +- if (skb->protocol != htons(ETH_P_IPV6)) +- return NF_ACCEPT; +- +- if (nf_flow_tuple_ipv6(skb, state->in, &tuple) < 0) +- return NF_ACCEPT; +- +- tuplehash = flow_offload_lookup(flow_table, &tuple); +- if (tuplehash == NULL) +- return NF_ACCEPT; +- +- outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.oifidx); +- if (!outdev) +- return NF_ACCEPT; +- +- dir = tuplehash->tuple.dir; +- flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); +- rt = (struct rt6_info *)flow->tuplehash[dir].tuple.dst_cache; +- +- if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) +- return NF_ACCEPT; +- +- if (skb_try_make_writable(skb, sizeof(*ip6h))) +- return NF_DROP; +- +- if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) && +- nf_flow_nat_ipv6(flow, skb, dir) < 0) +- return NF_DROP; +- +- flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; +- ip6h = ipv6_hdr(skb); +- ip6h->hop_limit--; +- +- skb->dev = outdev; +- nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); +- neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb); +- +- return NF_STOLEN; +-} +-EXPORT_SYMBOL_GPL(nf_flow_offload_ipv6_hook); + + static struct nf_flowtable_type flowtable_ipv6 = { + .family = NFPROTO_IPV6, +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -4,8 +4,11 @@ + #include + #include + #include ++#include + #include + #include ++#include ++#include + #include + #include + /* For layer 4 checksum field offset. */ +@@ -241,3 +244,215 @@ nf_flow_offload_ip_hook(void *priv, stru + return NF_STOLEN; + } + EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook); ++ ++static int nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff, ++ struct in6_addr *addr, ++ struct in6_addr *new_addr) ++{ ++ struct tcphdr *tcph; ++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || ++ skb_try_make_writable(skb, thoff + sizeof(*tcph))) ++ return -1; ++ ++ tcph = (void *)(skb_network_header(skb) + thoff); ++ inet_proto_csum_replace16(&tcph->check, skb, addr->s6_addr32, ++ new_addr->s6_addr32, true); ++ ++ return 0; ++} ++ ++static int nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff, ++ struct in6_addr *addr, ++ struct in6_addr *new_addr) ++{ ++ struct udphdr *udph; ++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || ++ skb_try_make_writable(skb, thoff + sizeof(*udph))) ++ return -1; ++ ++ udph = (void *)(skb_network_header(skb) + thoff); ++ if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { ++ inet_proto_csum_replace16(&udph->check, skb, addr->s6_addr32, ++ new_addr->s6_addr32, true); ++ if (!udph->check) ++ udph->check = CSUM_MANGLED_0; ++ } ++ ++ return 0; ++} ++ ++static int nf_flow_nat_ipv6_l4proto(struct sk_buff *skb, struct ipv6hdr *ip6h, ++ unsigned int thoff, struct in6_addr *addr, ++ struct in6_addr *new_addr) ++{ ++ switch (ip6h->nexthdr) { ++ case IPPROTO_TCP: ++ if (nf_flow_nat_ipv6_tcp(skb, thoff, addr, new_addr) < 0) ++ return NF_DROP; ++ break; ++ case IPPROTO_UDP: ++ if (nf_flow_nat_ipv6_udp(skb, thoff, addr, new_addr) < 0) ++ return NF_DROP; ++ break; ++ } ++ ++ return 0; ++} ++ ++static int nf_flow_snat_ipv6(const struct flow_offload *flow, ++ struct sk_buff *skb, struct ipv6hdr *ip6h, ++ unsigned int thoff, ++ enum flow_offload_tuple_dir dir) ++{ ++ struct in6_addr addr, new_addr; ++ ++ switch (dir) { ++ case FLOW_OFFLOAD_DIR_ORIGINAL: ++ addr = ip6h->saddr; ++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6; ++ ip6h->saddr = new_addr; ++ break; ++ case FLOW_OFFLOAD_DIR_REPLY: ++ addr = ip6h->daddr; ++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6; ++ ip6h->daddr = new_addr; ++ break; ++ default: ++ return -1; ++ } ++ ++ return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); ++} ++ ++static int nf_flow_dnat_ipv6(const struct flow_offload *flow, ++ struct sk_buff *skb, struct ipv6hdr *ip6h, ++ unsigned int thoff, ++ enum flow_offload_tuple_dir dir) ++{ ++ struct in6_addr addr, new_addr; ++ ++ switch (dir) { ++ case FLOW_OFFLOAD_DIR_ORIGINAL: ++ addr = ip6h->daddr; ++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6; ++ ip6h->daddr = new_addr; ++ break; ++ case FLOW_OFFLOAD_DIR_REPLY: ++ addr = ip6h->saddr; ++ new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6; ++ ip6h->saddr = new_addr; ++ break; ++ default: ++ return -1; ++ } ++ ++ return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); ++} ++ ++static int nf_flow_nat_ipv6(const struct flow_offload *flow, ++ struct sk_buff *skb, ++ enum flow_offload_tuple_dir dir) ++{ ++ struct ipv6hdr *ip6h = ipv6_hdr(skb); ++ unsigned int thoff = sizeof(*ip6h); ++ ++ if (flow->flags & FLOW_OFFLOAD_SNAT && ++ (nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || ++ nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) ++ return -1; ++ if (flow->flags & FLOW_OFFLOAD_DNAT && ++ (nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 || ++ nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir) < 0)) ++ return -1; ++ ++ return 0; ++} ++ ++static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev, ++ struct flow_offload_tuple *tuple) ++{ ++ struct flow_ports *ports; ++ struct ipv6hdr *ip6h; ++ unsigned int thoff; ++ ++ if (!pskb_may_pull(skb, sizeof(*ip6h))) ++ return -1; ++ ++ ip6h = ipv6_hdr(skb); ++ ++ if (ip6h->nexthdr != IPPROTO_TCP && ++ ip6h->nexthdr != IPPROTO_UDP) ++ return -1; ++ ++ thoff = sizeof(*ip6h); ++ if (!pskb_may_pull(skb, thoff + sizeof(*ports))) ++ return -1; ++ ++ ports = (struct flow_ports *)(skb_network_header(skb) + thoff); ++ ++ tuple->src_v6 = ip6h->saddr; ++ tuple->dst_v6 = ip6h->daddr; ++ tuple->src_port = ports->source; ++ tuple->dst_port = ports->dest; ++ tuple->l3proto = AF_INET6; ++ tuple->l4proto = ip6h->nexthdr; ++ tuple->iifidx = dev->ifindex; ++ ++ return 0; ++} ++ ++unsigned int ++nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++{ ++ struct flow_offload_tuple_rhash *tuplehash; ++ struct nf_flowtable *flow_table = priv; ++ struct flow_offload_tuple tuple = {}; ++ enum flow_offload_tuple_dir dir; ++ struct flow_offload *flow; ++ struct net_device *outdev; ++ struct in6_addr *nexthop; ++ struct ipv6hdr *ip6h; ++ struct rt6_info *rt; ++ ++ if (skb->protocol != htons(ETH_P_IPV6)) ++ return NF_ACCEPT; ++ ++ if (nf_flow_tuple_ipv6(skb, state->in, &tuple) < 0) ++ return NF_ACCEPT; ++ ++ tuplehash = flow_offload_lookup(flow_table, &tuple); ++ if (tuplehash == NULL) ++ return NF_ACCEPT; ++ ++ outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.oifidx); ++ if (!outdev) ++ return NF_ACCEPT; ++ ++ dir = tuplehash->tuple.dir; ++ flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); ++ rt = (struct rt6_info *)flow->tuplehash[dir].tuple.dst_cache; ++ ++ if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) ++ return NF_ACCEPT; ++ ++ if (skb_try_make_writable(skb, sizeof(*ip6h))) ++ return NF_DROP; ++ ++ if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) && ++ nf_flow_nat_ipv6(flow, skb, dir) < 0) ++ return NF_DROP; ++ ++ flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; ++ ip6h = ipv6_hdr(skb); ++ ip6h->hop_limit--; ++ ++ skb->dev = outdev; ++ nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); ++ neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb); ++ ++ return NF_STOLEN; ++} ++EXPORT_SYMBOL_GPL(nf_flow_offload_ipv6_hook); diff --git a/target/linux/generic/backport-4.14/356-netfilter-nf_flow_table-relax-mixed-ipv4-ipv6-flowta.patch b/target/linux/generic/backport-4.14/356-netfilter-nf_flow_table-relax-mixed-ipv4-ipv6-flowta.patch new file mode 100644 index 000000000..7d4bdc6d8 --- /dev/null +++ b/target/linux/generic/backport-4.14/356-netfilter-nf_flow_table-relax-mixed-ipv4-ipv6-flowta.patch @@ -0,0 +1,23 @@ +From: Felix Fietkau +Date: Sat, 17 Feb 2018 12:02:28 +0100 +Subject: [PATCH] netfilter: nf_flow_table: relax mixed ipv4/ipv6 flowtable + dependencies + +Since the offload hook code was moved, this table no longer depends on +the IPv4 and IPv6 flowtable modules + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/Kconfig ++++ b/net/netfilter/Kconfig +@@ -670,8 +670,7 @@ endif # NF_TABLES + + config NF_FLOW_TABLE_INET + tristate "Netfilter flow table mixed IPv4/IPv6 module" +- depends on NF_FLOW_TABLE_IPV4 +- depends on NF_FLOW_TABLE_IPV6 ++ depends on NF_FLOW_TABLE + help + This option adds the flow table mixed IPv4/IPv6 support. + diff --git a/target/linux/generic/backport-4.14/357-netfilter-nf_flow_table-move-init-code-to-nf_flow_ta.patch b/target/linux/generic/backport-4.14/357-netfilter-nf_flow_table-move-init-code-to-nf_flow_ta.patch new file mode 100644 index 000000000..c783884f8 --- /dev/null +++ b/target/linux/generic/backport-4.14/357-netfilter-nf_flow_table-move-init-code-to-nf_flow_ta.patch @@ -0,0 +1,298 @@ +From: Felix Fietkau +Date: Sun, 18 Feb 2018 18:16:31 +0100 +Subject: [PATCH] netfilter: nf_flow_table: move init code to + nf_flow_table_core.c + +Reduces duplication of .gc and .params in flowtable type definitions and +makes the API clearer + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -14,9 +14,8 @@ struct nf_flowtable; + struct nf_flowtable_type { + struct list_head list; + int family; +- void (*gc)(struct work_struct *work); ++ int (*init)(struct nf_flowtable *ft); + void (*free)(struct nf_flowtable *ft); +- const struct rhashtable_params *params; + nf_hookfn *hook; + struct module *owner; + }; +@@ -100,9 +99,8 @@ int nf_flow_table_iterate(struct nf_flow + + void nf_flow_table_cleanup(struct net *net, struct net_device *dev); + ++int nf_flow_table_init(struct nf_flowtable *flow_table); + void nf_flow_table_free(struct nf_flowtable *flow_table); +-void nf_flow_offload_work_gc(struct work_struct *work); +-extern const struct rhashtable_params nf_flow_offload_rhash_params; + + void flow_offload_dead(struct flow_offload *flow); + +--- a/net/ipv4/netfilter/nf_flow_table_ipv4.c ++++ b/net/ipv4/netfilter/nf_flow_table_ipv4.c +@@ -7,8 +7,7 @@ + + static struct nf_flowtable_type flowtable_ipv4 = { + .family = NFPROTO_IPV4, +- .params = &nf_flow_offload_rhash_params, +- .gc = nf_flow_offload_work_gc, ++ .init = nf_flow_table_init, + .free = nf_flow_table_free, + .hook = nf_flow_offload_ip_hook, + .owner = THIS_MODULE, +--- a/net/ipv6/netfilter/nf_flow_table_ipv6.c ++++ b/net/ipv6/netfilter/nf_flow_table_ipv6.c +@@ -8,8 +8,7 @@ + + static struct nf_flowtable_type flowtable_ipv6 = { + .family = NFPROTO_IPV6, +- .params = &nf_flow_offload_rhash_params, +- .gc = nf_flow_offload_work_gc, ++ .init = nf_flow_table_init, + .free = nf_flow_table_free, + .hook = nf_flow_offload_ipv6_hook, + .owner = THIS_MODULE, +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -116,16 +116,50 @@ void flow_offload_dead(struct flow_offlo + } + EXPORT_SYMBOL_GPL(flow_offload_dead); + ++static u32 flow_offload_hash(const void *data, u32 len, u32 seed) ++{ ++ const struct flow_offload_tuple *tuple = data; ++ ++ return jhash(tuple, offsetof(struct flow_offload_tuple, dir), seed); ++} ++ ++static u32 flow_offload_hash_obj(const void *data, u32 len, u32 seed) ++{ ++ const struct flow_offload_tuple_rhash *tuplehash = data; ++ ++ return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, dir), seed); ++} ++ ++static int flow_offload_hash_cmp(struct rhashtable_compare_arg *arg, ++ const void *ptr) ++{ ++ const struct flow_offload_tuple *tuple = arg->key; ++ const struct flow_offload_tuple_rhash *x = ptr; ++ ++ if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, dir))) ++ return 1; ++ ++ return 0; ++} ++ ++static const struct rhashtable_params nf_flow_offload_rhash_params = { ++ .head_offset = offsetof(struct flow_offload_tuple_rhash, node), ++ .hashfn = flow_offload_hash, ++ .obj_hashfn = flow_offload_hash_obj, ++ .obj_cmpfn = flow_offload_hash_cmp, ++ .automatic_shrinking = true, ++}; ++ + int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) + { + flow->timeout = (u32)jiffies; + + rhashtable_insert_fast(&flow_table->rhashtable, + &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, +- *flow_table->type->params); ++ nf_flow_offload_rhash_params); + rhashtable_insert_fast(&flow_table->rhashtable, + &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, +- *flow_table->type->params); ++ nf_flow_offload_rhash_params); + return 0; + } + EXPORT_SYMBOL_GPL(flow_offload_add); +@@ -135,10 +169,10 @@ static void flow_offload_del(struct nf_f + { + rhashtable_remove_fast(&flow_table->rhashtable, + &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, +- *flow_table->type->params); ++ nf_flow_offload_rhash_params); + rhashtable_remove_fast(&flow_table->rhashtable, + &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, +- *flow_table->type->params); ++ nf_flow_offload_rhash_params); + + flow_offload_free(flow); + } +@@ -148,7 +182,7 @@ flow_offload_lookup(struct nf_flowtable + struct flow_offload_tuple *tuple) + { + return rhashtable_lookup_fast(&flow_table->rhashtable, tuple, +- *flow_table->type->params); ++ nf_flow_offload_rhash_params); + } + EXPORT_SYMBOL_GPL(flow_offload_lookup); + +@@ -237,7 +271,7 @@ out: + return 1; + } + +-void nf_flow_offload_work_gc(struct work_struct *work) ++static void nf_flow_offload_work_gc(struct work_struct *work) + { + struct nf_flowtable *flow_table; + +@@ -245,42 +279,6 @@ void nf_flow_offload_work_gc(struct work + nf_flow_offload_gc_step(flow_table); + queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ); + } +-EXPORT_SYMBOL_GPL(nf_flow_offload_work_gc); +- +-static u32 flow_offload_hash(const void *data, u32 len, u32 seed) +-{ +- const struct flow_offload_tuple *tuple = data; +- +- return jhash(tuple, offsetof(struct flow_offload_tuple, dir), seed); +-} +- +-static u32 flow_offload_hash_obj(const void *data, u32 len, u32 seed) +-{ +- const struct flow_offload_tuple_rhash *tuplehash = data; +- +- return jhash(&tuplehash->tuple, offsetof(struct flow_offload_tuple, dir), seed); +-} +- +-static int flow_offload_hash_cmp(struct rhashtable_compare_arg *arg, +- const void *ptr) +-{ +- const struct flow_offload_tuple *tuple = arg->key; +- const struct flow_offload_tuple_rhash *x = ptr; +- +- if (memcmp(&x->tuple, tuple, offsetof(struct flow_offload_tuple, dir))) +- return 1; +- +- return 0; +-} +- +-const struct rhashtable_params nf_flow_offload_rhash_params = { +- .head_offset = offsetof(struct flow_offload_tuple_rhash, node), +- .hashfn = flow_offload_hash, +- .obj_hashfn = flow_offload_hash_obj, +- .obj_cmpfn = flow_offload_hash_cmp, +- .automatic_shrinking = true, +-}; +-EXPORT_SYMBOL_GPL(nf_flow_offload_rhash_params); + + static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff, + __be16 port, __be16 new_port) +@@ -398,6 +396,24 @@ int nf_flow_dnat_port(const struct flow_ + } + EXPORT_SYMBOL_GPL(nf_flow_dnat_port); + ++int nf_flow_table_init(struct nf_flowtable *flowtable) ++{ ++ int err; ++ ++ INIT_DEFERRABLE_WORK(&flowtable->gc_work, nf_flow_offload_work_gc); ++ ++ err = rhashtable_init(&flowtable->rhashtable, ++ &nf_flow_offload_rhash_params); ++ if (err < 0) ++ return err; ++ ++ queue_delayed_work(system_power_efficient_wq, ++ &flowtable->gc_work, HZ); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nf_flow_table_init); ++ + static void nf_flow_table_do_cleanup(struct flow_offload *flow, void *data) + { + struct net_device *dev = data; +@@ -423,8 +439,10 @@ EXPORT_SYMBOL_GPL(nf_flow_table_cleanup) + + void nf_flow_table_free(struct nf_flowtable *flow_table) + { ++ cancel_delayed_work_sync(&flow_table->gc_work); + nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL); + WARN_ON(!nf_flow_offload_gc_step(flow_table)); ++ rhashtable_destroy(&flow_table->rhashtable); + } + EXPORT_SYMBOL_GPL(nf_flow_table_free); + +--- a/net/netfilter/nf_flow_table_inet.c ++++ b/net/netfilter/nf_flow_table_inet.c +@@ -22,8 +22,7 @@ nf_flow_offload_inet_hook(void *priv, st + + static struct nf_flowtable_type flowtable_inet = { + .family = NFPROTO_INET, +- .params = &nf_flow_offload_rhash_params, +- .gc = nf_flow_offload_work_gc, ++ .init = nf_flow_table_init, + .free = nf_flow_table_free, + .hook = nf_flow_offload_inet_hook, + .owner = THIS_MODULE, +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -5013,40 +5013,38 @@ static int nf_tables_newflowtable(struct + } + + flowtable->data.type = type; +- err = rhashtable_init(&flowtable->data.rhashtable, type->params); ++ err = type->init(&flowtable->data); + if (err < 0) + goto err3; + + err = nf_tables_flowtable_parse_hook(&ctx, nla[NFTA_FLOWTABLE_HOOK], + flowtable); + if (err < 0) +- goto err3; ++ goto err4; + + for (i = 0; i < flowtable->ops_len; i++) { + err = nf_register_net_hook(net, &flowtable->ops[i]); + if (err < 0) +- goto err4; ++ goto err5; + } + + err = nft_trans_flowtable_add(&ctx, NFT_MSG_NEWFLOWTABLE, flowtable); + if (err < 0) +- goto err5; +- +- INIT_DEFERRABLE_WORK(&flowtable->data.gc_work, type->gc); +- queue_delayed_work(system_power_efficient_wq, +- &flowtable->data.gc_work, HZ); ++ goto err6; + + list_add_tail_rcu(&flowtable->list, &table->flowtables); + table->use++; + + return 0; +-err5: ++err6: + i = flowtable->ops_len; +-err4: ++err5: + for (k = i - 1; k >= 0; k--) + nf_unregister_net_hook(net, &flowtable->ops[i]); + + kfree(flowtable->ops); ++err4: ++ flowtable->data.type->free(&flowtable->data); + err3: + module_put(type->owner); + err2: +@@ -5327,10 +5325,8 @@ err: + + static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable) + { +- cancel_delayed_work_sync(&flowtable->data.gc_work); + kfree(flowtable->name); + flowtable->data.type->free(&flowtable->data); +- rhashtable_destroy(&flowtable->data.rhashtable); + module_put(flowtable->data.type->owner); + } + diff --git a/target/linux/generic/backport-4.14/358-netfilter-nf_flow_table-fix-priv-pointer-for-netdev-.patch b/target/linux/generic/backport-4.14/358-netfilter-nf_flow_table-fix-priv-pointer-for-netdev-.patch new file mode 100644 index 000000000..d4b746d0e --- /dev/null +++ b/target/linux/generic/backport-4.14/358-netfilter-nf_flow_table-fix-priv-pointer-for-netdev-.patch @@ -0,0 +1,22 @@ +From: Felix Fietkau +Date: Tue, 20 Feb 2018 14:48:51 +0100 +Subject: [PATCH] netfilter: nf_flow_table: fix priv pointer for netdev hook + +The offload ip hook expects a pointer to the flowtable, not to the +rhashtable. Since the rhashtable is the first member, this is safe for +the moment, but breaks as soon as the structure layout changes + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -4879,7 +4879,7 @@ static int nf_tables_flowtable_parse_hoo + flowtable->ops[i].pf = NFPROTO_NETDEV; + flowtable->ops[i].hooknum = hooknum; + flowtable->ops[i].priority = priority; +- flowtable->ops[i].priv = &flowtable->data.rhashtable; ++ flowtable->ops[i].priv = &flowtable->data; + flowtable->ops[i].hook = flowtable->data.type->hook; + flowtable->ops[i].dev = dev_array[i]; + } diff --git a/target/linux/generic/backport-4.14/359-netfilter-nf_flow_table-track-flow-tables-in-nf_flow.patch b/target/linux/generic/backport-4.14/359-netfilter-nf_flow_table-track-flow-tables-in-nf_flow.patch new file mode 100644 index 000000000..ad7d81f4f --- /dev/null +++ b/target/linux/generic/backport-4.14/359-netfilter-nf_flow_table-track-flow-tables-in-nf_flow.patch @@ -0,0 +1,114 @@ +From: Felix Fietkau +Date: Tue, 20 Feb 2018 14:08:14 +0100 +Subject: [PATCH] netfilter: nf_flow_table: track flow tables in nf_flow_table + directly + +Avoids having nf_flow_table depend on nftables (useful for future +iptables backport work) + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -21,6 +21,7 @@ struct nf_flowtable_type { + }; + + struct nf_flowtable { ++ struct list_head list; + struct rhashtable rhashtable; + const struct nf_flowtable_type *type; + struct delayed_work gc_work; +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -1091,9 +1091,6 @@ struct nft_flowtable { + struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table, + const struct nlattr *nla, + u8 genmask); +-void nft_flow_table_iterate(struct net *net, +- void (*iter)(struct nf_flowtable *flowtable, void *data), +- void *data); + + void nft_register_flowtable_type(struct nf_flowtable_type *type); + void nft_unregister_flowtable_type(struct nf_flowtable_type *type); +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -18,6 +18,9 @@ struct flow_offload_entry { + struct rcu_head rcu_head; + }; + ++static DEFINE_MUTEX(flowtable_lock); ++static LIST_HEAD(flowtables); ++ + static void + flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct, + struct nf_flow_route *route, +@@ -410,6 +413,10 @@ int nf_flow_table_init(struct nf_flowtab + queue_delayed_work(system_power_efficient_wq, + &flowtable->gc_work, HZ); + ++ mutex_lock(&flowtable_lock); ++ list_add(&flowtable->list, &flowtables); ++ mutex_unlock(&flowtable_lock); ++ + return 0; + } + EXPORT_SYMBOL_GPL(nf_flow_table_init); +@@ -425,20 +432,28 @@ static void nf_flow_table_do_cleanup(str + } + + static void nf_flow_table_iterate_cleanup(struct nf_flowtable *flowtable, +- void *data) ++ struct net_device *dev) + { +- nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, data); ++ nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, dev); + flush_delayed_work(&flowtable->gc_work); + } + + void nf_flow_table_cleanup(struct net *net, struct net_device *dev) + { +- nft_flow_table_iterate(net, nf_flow_table_iterate_cleanup, dev); ++ struct nf_flowtable *flowtable; ++ ++ mutex_lock(&flowtable_lock); ++ list_for_each_entry(flowtable, &flowtables, list) ++ nf_flow_table_iterate_cleanup(flowtable, dev); ++ mutex_unlock(&flowtable_lock); + } + EXPORT_SYMBOL_GPL(nf_flow_table_cleanup); + + void nf_flow_table_free(struct nf_flowtable *flow_table) + { ++ mutex_lock(&flowtable_lock); ++ list_del(&flow_table->list); ++ mutex_unlock(&flowtable_lock); + cancel_delayed_work_sync(&flow_table->gc_work); + nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL); + WARN_ON(!nf_flow_offload_gc_step(flow_table)); +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -4923,23 +4923,6 @@ static const struct nf_flowtable_type *n + return ERR_PTR(-ENOENT); + } + +-void nft_flow_table_iterate(struct net *net, +- void (*iter)(struct nf_flowtable *flowtable, void *data), +- void *data) +-{ +- struct nft_flowtable *flowtable; +- const struct nft_table *table; +- +- nfnl_lock(NFNL_SUBSYS_NFTABLES); +- list_for_each_entry(table, &net->nft.tables, list) { +- list_for_each_entry(flowtable, &table->flowtables, list) { +- iter(&flowtable->data, data); +- } +- } +- nfnl_unlock(NFNL_SUBSYS_NFTABLES); +-} +-EXPORT_SYMBOL_GPL(nft_flow_table_iterate); +- + static void nft_unregister_flowtable_net_hooks(struct net *net, + struct nft_flowtable *flowtable) + { diff --git a/target/linux/generic/backport-4.14/360-netfilter-nf_flow_table-make-flow_offload_dead-inlin.patch b/target/linux/generic/backport-4.14/360-netfilter-nf_flow_table-make-flow_offload_dead-inlin.patch new file mode 100644 index 000000000..d33400c72 --- /dev/null +++ b/target/linux/generic/backport-4.14/360-netfilter-nf_flow_table-make-flow_offload_dead-inlin.patch @@ -0,0 +1,38 @@ +From: Felix Fietkau +Date: Sun, 25 Feb 2018 15:37:27 +0100 +Subject: [PATCH] netfilter: nf_flow_table: make flow_offload_dead inline + +It is too trivial to keep as a separate exported function + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -103,7 +103,10 @@ void nf_flow_table_cleanup(struct net *n + int nf_flow_table_init(struct nf_flowtable *flow_table); + void nf_flow_table_free(struct nf_flowtable *flow_table); + +-void flow_offload_dead(struct flow_offload *flow); ++static inline void flow_offload_dead(struct flow_offload *flow) ++{ ++ flow->flags |= FLOW_OFFLOAD_DYING; ++} + + int nf_flow_snat_port(const struct flow_offload *flow, + struct sk_buff *skb, unsigned int thoff, +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -113,12 +113,6 @@ void flow_offload_free(struct flow_offlo + } + EXPORT_SYMBOL_GPL(flow_offload_free); + +-void flow_offload_dead(struct flow_offload *flow) +-{ +- flow->flags |= FLOW_OFFLOAD_DYING; +-} +-EXPORT_SYMBOL_GPL(flow_offload_dead); +- + static u32 flow_offload_hash(const void *data, u32 len, u32 seed) + { + const struct flow_offload_tuple *tuple = data; diff --git a/target/linux/generic/backport-4.14/361-netfilter-nf_flow_table-add-a-new-flow-state-for-tea.patch b/target/linux/generic/backport-4.14/361-netfilter-nf_flow_table-add-a-new-flow-state-for-tea.patch new file mode 100644 index 000000000..30cebfac6 --- /dev/null +++ b/target/linux/generic/backport-4.14/361-netfilter-nf_flow_table-add-a-new-flow-state-for-tea.patch @@ -0,0 +1,83 @@ +From: Felix Fietkau +Date: Sun, 25 Feb 2018 15:38:31 +0100 +Subject: [PATCH] netfilter: nf_flow_table: add a new flow state for + tearing down offloading + +Will be used to tear down the offload entry while keeping the conntrack +entry alive. + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -68,6 +68,7 @@ struct flow_offload_tuple_rhash { + #define FLOW_OFFLOAD_SNAT 0x1 + #define FLOW_OFFLOAD_DNAT 0x2 + #define FLOW_OFFLOAD_DYING 0x4 ++#define FLOW_OFFLOAD_TEARDOWN 0x8 + + struct flow_offload { + struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX]; +@@ -103,6 +104,7 @@ void nf_flow_table_cleanup(struct net *n + int nf_flow_table_init(struct nf_flowtable *flow_table); + void nf_flow_table_free(struct nf_flowtable *flow_table); + ++void flow_offload_teardown(struct flow_offload *flow); + static inline void flow_offload_dead(struct flow_offload *flow) + { + flow->flags |= FLOW_OFFLOAD_DYING; +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -174,6 +174,12 @@ static void flow_offload_del(struct nf_f + flow_offload_free(flow); + } + ++void flow_offload_teardown(struct flow_offload *flow) ++{ ++ flow->flags |= FLOW_OFFLOAD_TEARDOWN; ++} ++EXPORT_SYMBOL_GPL(flow_offload_teardown); ++ + struct flow_offload_tuple_rhash * + flow_offload_lookup(struct nf_flowtable *flow_table, + struct flow_offload_tuple *tuple) +@@ -226,11 +232,6 @@ static inline bool nf_flow_has_expired(c + return (__s32)(flow->timeout - (u32)jiffies) <= 0; + } + +-static inline bool nf_flow_is_dying(const struct flow_offload *flow) +-{ +- return flow->flags & FLOW_OFFLOAD_DYING; +-} +- + static int nf_flow_offload_gc_step(struct nf_flowtable *flow_table) + { + struct flow_offload_tuple_rhash *tuplehash; +@@ -258,7 +259,8 @@ static int nf_flow_offload_gc_step(struc + flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); + + if (nf_flow_has_expired(flow) || +- nf_flow_is_dying(flow)) ++ (flow->flags & (FLOW_OFFLOAD_DYING | ++ FLOW_OFFLOAD_TEARDOWN))) + flow_offload_del(flow_table, flow); + } + out: +@@ -419,10 +421,14 @@ static void nf_flow_table_do_cleanup(str + { + struct net_device *dev = data; + +- if (dev && flow->tuplehash[0].tuple.iifidx != dev->ifindex) ++ if (!dev) { ++ flow_offload_teardown(flow); + return; ++ } + +- flow_offload_dead(flow); ++ if (flow->tuplehash[0].tuple.iifidx == dev->ifindex || ++ flow->tuplehash[1].tuple.iifidx == dev->ifindex) ++ flow_offload_dead(flow); + } + + static void nf_flow_table_iterate_cleanup(struct nf_flowtable *flowtable, diff --git a/target/linux/generic/backport-4.14/362-netfilter-nf_flow_table-in-flow_offload_lookup-skip-.patch b/target/linux/generic/backport-4.14/362-netfilter-nf_flow_table-in-flow_offload_lookup-skip-.patch new file mode 100644 index 000000000..d14ac97a5 --- /dev/null +++ b/target/linux/generic/backport-4.14/362-netfilter-nf_flow_table-in-flow_offload_lookup-skip-.patch @@ -0,0 +1,36 @@ +From: Felix Fietkau +Date: Sun, 25 Feb 2018 15:39:56 +0100 +Subject: [PATCH] netfilter: nf_flow_table: in flow_offload_lookup, skip + entries being deleted + +Preparation for sending flows back to the slow path + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -184,8 +184,21 @@ struct flow_offload_tuple_rhash * + flow_offload_lookup(struct nf_flowtable *flow_table, + struct flow_offload_tuple *tuple) + { +- return rhashtable_lookup_fast(&flow_table->rhashtable, tuple, +- nf_flow_offload_rhash_params); ++ struct flow_offload_tuple_rhash *tuplehash; ++ struct flow_offload *flow; ++ int dir; ++ ++ tuplehash = rhashtable_lookup_fast(&flow_table->rhashtable, tuple, ++ nf_flow_offload_rhash_params); ++ if (!tuplehash) ++ return NULL; ++ ++ dir = tuplehash->tuple.dir; ++ flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); ++ if (flow->flags & (FLOW_OFFLOAD_DYING | FLOW_OFFLOAD_TEARDOWN)) ++ return NULL; ++ ++ return tuplehash; + } + EXPORT_SYMBOL_GPL(flow_offload_lookup); + diff --git a/target/linux/generic/backport-4.14/363-netfilter-nf_flow_table-add-support-for-sending-flow.patch b/target/linux/generic/backport-4.14/363-netfilter-nf_flow_table-add-support-for-sending-flow.patch new file mode 100644 index 000000000..905880fea --- /dev/null +++ b/target/linux/generic/backport-4.14/363-netfilter-nf_flow_table-add-support-for-sending-flow.patch @@ -0,0 +1,99 @@ +From: Felix Fietkau +Date: Sun, 25 Feb 2018 15:41:11 +0100 +Subject: [PATCH] netfilter: nf_flow_table: add support for sending flows + back to the slow path + +Reset the timeout. For TCP, also set the state to indicate to use the +next incoming packets to reset window tracking. +This allows the slow path to take over again once the offload state has +been torn down + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -100,6 +100,43 @@ err_ct_refcnt: + } + EXPORT_SYMBOL_GPL(flow_offload_alloc); + ++static void flow_offload_fixup_tcp(struct ip_ct_tcp *tcp) ++{ ++ tcp->state = TCP_CONNTRACK_ESTABLISHED; ++ tcp->seen[0].td_maxwin = 0; ++ tcp->seen[1].td_maxwin = 0; ++} ++ ++static void flow_offload_fixup_ct_state(struct nf_conn *ct) ++{ ++ const struct nf_conntrack_l4proto *l4proto; ++ struct net *net = nf_ct_net(ct); ++ unsigned int *timeouts; ++ unsigned int timeout; ++ int l4num; ++ ++ l4num = nf_ct_protonum(ct); ++ if (l4num == IPPROTO_TCP) ++ flow_offload_fixup_tcp(&ct->proto.tcp); ++ ++ l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), l4num); ++ if (!l4proto) ++ return; ++ ++ timeouts = l4proto->get_timeouts(net); ++ if (!timeouts) ++ return; ++ ++ if (l4num == IPPROTO_TCP) ++ timeout = timeouts[TCP_CONNTRACK_ESTABLISHED]; ++ else if (l4num == IPPROTO_UDP) ++ timeout = timeouts[UDP_CT_REPLIED]; ++ else ++ return; ++ ++ ct->timeout = nfct_time_stamp + timeout; ++} ++ + void flow_offload_free(struct flow_offload *flow) + { + struct flow_offload_entry *e; +@@ -107,7 +144,8 @@ void flow_offload_free(struct flow_offlo + dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache); + dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache); + e = container_of(flow, struct flow_offload_entry, flow); +- nf_ct_delete(e->ct, 0, 0); ++ if (flow->flags & FLOW_OFFLOAD_DYING) ++ nf_ct_delete(e->ct, 0, 0); + nf_ct_put(e->ct); + kfree_rcu(e, rcu_head); + } +@@ -164,6 +202,8 @@ EXPORT_SYMBOL_GPL(flow_offload_add); + static void flow_offload_del(struct nf_flowtable *flow_table, + struct flow_offload *flow) + { ++ struct flow_offload_entry *e; ++ + rhashtable_remove_fast(&flow_table->rhashtable, + &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, + nf_flow_offload_rhash_params); +@@ -171,12 +211,20 @@ static void flow_offload_del(struct nf_f + &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, + nf_flow_offload_rhash_params); + ++ e = container_of(flow, struct flow_offload_entry, flow); ++ clear_bit(IPS_OFFLOAD_BIT, &e->ct->status); ++ + flow_offload_free(flow); + } + + void flow_offload_teardown(struct flow_offload *flow) + { ++ struct flow_offload_entry *e; ++ + flow->flags |= FLOW_OFFLOAD_TEARDOWN; ++ ++ e = container_of(flow, struct flow_offload_entry, flow); ++ flow_offload_fixup_ct_state(e->ct); + } + EXPORT_SYMBOL_GPL(flow_offload_teardown); + diff --git a/target/linux/generic/backport-4.14/364-netfilter-nf_flow_table-tear-down-TCP-flows-if-RST-o.patch b/target/linux/generic/backport-4.14/364-netfilter-nf_flow_table-tear-down-TCP-flows-if-RST-o.patch new file mode 100644 index 000000000..8b0024cd8 --- /dev/null +++ b/target/linux/generic/backport-4.14/364-netfilter-nf_flow_table-tear-down-TCP-flows-if-RST-o.patch @@ -0,0 +1,81 @@ +From: Felix Fietkau +Date: Sun, 25 Feb 2018 15:42:58 +0100 +Subject: [PATCH] netfilter: nf_flow_table: tear down TCP flows if RST or + FIN was seen + +Allow the slow path to handle the shutdown of the connection with proper +timeouts + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -15,6 +15,23 @@ + #include + #include + ++static int nf_flow_tcp_state_check(struct flow_offload *flow, ++ struct sk_buff *skb, unsigned int thoff) ++{ ++ struct tcphdr *tcph; ++ ++ if (!pskb_may_pull(skb, thoff + sizeof(*tcph))) ++ return -1; ++ ++ tcph = (void *)(skb_network_header(skb) + thoff); ++ if (unlikely(tcph->fin || tcph->rst)) { ++ flow_offload_teardown(flow); ++ return -1; ++ } ++ ++ return 0; ++} ++ + static int nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff, + __be32 addr, __be32 new_addr) + { +@@ -118,10 +135,9 @@ static int nf_flow_dnat_ip(const struct + } + + static int nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb, +- enum flow_offload_tuple_dir dir) ++ unsigned int thoff, enum flow_offload_tuple_dir dir) + { + struct iphdr *iph = ip_hdr(skb); +- unsigned int thoff = iph->ihl * 4; + + if (flow->flags & FLOW_OFFLOAD_SNAT && + (nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 || +@@ -201,6 +217,7 @@ nf_flow_offload_ip_hook(void *priv, stru + struct flow_offload *flow; + struct net_device *outdev; + const struct rtable *rt; ++ unsigned int thoff; + struct iphdr *iph; + __be32 nexthop; + +@@ -229,8 +246,12 @@ nf_flow_offload_ip_hook(void *priv, stru + if (skb_try_make_writable(skb, sizeof(*iph))) + return NF_DROP; + ++ thoff = ip_hdr(skb)->ihl * 4; ++ if (nf_flow_tcp_state_check(flow, skb, thoff)) ++ return NF_ACCEPT; ++ + if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) && +- nf_flow_nat_ip(flow, skb, dir) < 0) ++ nf_flow_nat_ip(flow, skb, thoff, dir) < 0) + return NF_DROP; + + flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; +@@ -438,6 +459,9 @@ nf_flow_offload_ipv6_hook(void *priv, st + if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) + return NF_ACCEPT; + ++ if (nf_flow_tcp_state_check(flow, skb, sizeof(*ip6h))) ++ return NF_ACCEPT; ++ + if (skb_try_make_writable(skb, sizeof(*ip6h))) + return NF_DROP; + diff --git a/target/linux/generic/backport-4.14/365-netfilter-nf_flow_table-fix-checksum-when-handling-D.patch b/target/linux/generic/backport-4.14/365-netfilter-nf_flow_table-fix-checksum-when-handling-D.patch new file mode 100644 index 000000000..372c8d59e --- /dev/null +++ b/target/linux/generic/backport-4.14/365-netfilter-nf_flow_table-fix-checksum-when-handling-D.patch @@ -0,0 +1,19 @@ +From: Felix Fietkau +Date: Sun, 25 Feb 2018 17:22:55 +0100 +Subject: [PATCH] netfilter: nf_flow_table: fix checksum when handling DNAT + +Add a missing call to csum_replace4 like on SNAT + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -130,6 +130,7 @@ static int nf_flow_dnat_ip(const struct + default: + return -1; + } ++ csum_replace4(&iph->check, addr, new_addr); + + return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); + } diff --git a/target/linux/generic/backport-4.14/366-netfilter-nf_flow_table-clean-up-and-fix-dst-handlin.patch b/target/linux/generic/backport-4.14/366-netfilter-nf_flow_table-clean-up-and-fix-dst-handlin.patch new file mode 100644 index 000000000..491f05785 --- /dev/null +++ b/target/linux/generic/backport-4.14/366-netfilter-nf_flow_table-clean-up-and-fix-dst-handlin.patch @@ -0,0 +1,89 @@ +From: Felix Fietkau +Date: Thu, 15 Mar 2018 18:21:43 +0100 +Subject: [PATCH] netfilter: nf_flow_table: clean up and fix dst handling + +dst handling in the code is inconsistent and possibly wrong. In my test, +skb_dst(skb) holds the dst entry after routing but before NAT, so the +code could possibly return the same dst entry for both directions of a +connection. +Additionally, there was some confusion over the dst entry vs the address +passed as parameter to rt_nexthop/rt6_nexthop. + +Do an explicit dst lookup for both ends of the connection and always use +the source address for it. When running the IP hook, use the dst entry +for the opposite direction for determining the route. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -238,7 +238,7 @@ nf_flow_offload_ip_hook(void *priv, stru + + dir = tuplehash->tuple.dir; + flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); +- rt = (const struct rtable *)flow->tuplehash[dir].tuple.dst_cache; ++ rt = (const struct rtable *)flow->tuplehash[!dir].tuple.dst_cache; + + if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)) && + (ip_hdr(skb)->frag_off & htons(IP_DF)) != 0) +@@ -455,7 +455,7 @@ nf_flow_offload_ipv6_hook(void *priv, st + + dir = tuplehash->tuple.dir; + flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); +- rt = (struct rt6_info *)flow->tuplehash[dir].tuple.dst_cache; ++ rt = (struct rt6_info *)flow->tuplehash[!dir].tuple.dst_cache; + + if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) + return NF_ACCEPT; +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -17,27 +17,38 @@ struct nft_flow_offload { + struct nft_flowtable *flowtable; + }; + +-static int nft_flow_route(const struct nft_pktinfo *pkt, +- const struct nf_conn *ct, +- struct nf_flow_route *route, +- enum ip_conntrack_dir dir) ++static struct dst_entry * ++nft_flow_dst(const struct nf_conn *ct, enum ip_conntrack_dir dir, ++ const struct nft_pktinfo *pkt) + { +- struct dst_entry *this_dst = skb_dst(pkt->skb); +- struct dst_entry *other_dst = NULL; ++ struct dst_entry *dst; + struct flowi fl; + + memset(&fl, 0, sizeof(fl)); + switch (nft_pf(pkt)) { + case NFPROTO_IPV4: +- fl.u.ip4.daddr = ct->tuplehash[!dir].tuple.dst.u3.ip; ++ fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip; + break; + case NFPROTO_IPV6: +- fl.u.ip6.daddr = ct->tuplehash[!dir].tuple.dst.u3.in6; ++ fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6; + break; + } + +- nf_route(nft_net(pkt), &other_dst, &fl, false, nft_pf(pkt)); +- if (!other_dst) ++ nf_route(nft_net(pkt), &dst, &fl, false, nft_pf(pkt)); ++ ++ return dst; ++} ++ ++static int nft_flow_route(const struct nft_pktinfo *pkt, ++ const struct nf_conn *ct, ++ struct nf_flow_route *route, ++ enum ip_conntrack_dir dir) ++{ ++ struct dst_entry *this_dst, *other_dst; ++ ++ this_dst = nft_flow_dst(ct, dir, pkt); ++ other_dst = nft_flow_dst(ct, !dir, pkt); ++ if (!this_dst || !other_dst) + return -ENOENT; + + route->tuple[dir].dst = this_dst; diff --git a/target/linux/generic/backport-4.14/367-netfilter-nf_flow_table-add-missing-condition-for-TC.patch b/target/linux/generic/backport-4.14/367-netfilter-nf_flow_table-add-missing-condition-for-TC.patch new file mode 100644 index 000000000..2a470f77e --- /dev/null +++ b/target/linux/generic/backport-4.14/367-netfilter-nf_flow_table-add-missing-condition-for-TC.patch @@ -0,0 +1,48 @@ +From: Felix Fietkau +Date: Fri, 23 Mar 2018 17:15:22 +0100 +Subject: [PATCH] netfilter: nf_flow_table: add missing condition for TCP state + check + +Avoid looking at unrelated fields in UDP packets + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -15,11 +15,14 @@ + #include + #include + +-static int nf_flow_tcp_state_check(struct flow_offload *flow, +- struct sk_buff *skb, unsigned int thoff) ++static int nf_flow_state_check(struct flow_offload *flow, int proto, ++ struct sk_buff *skb, unsigned int thoff) + { + struct tcphdr *tcph; + ++ if (proto != IPPROTO_TCP) ++ return 0; ++ + if (!pskb_may_pull(skb, thoff + sizeof(*tcph))) + return -1; + +@@ -248,7 +251,7 @@ nf_flow_offload_ip_hook(void *priv, stru + return NF_DROP; + + thoff = ip_hdr(skb)->ihl * 4; +- if (nf_flow_tcp_state_check(flow, skb, thoff)) ++ if (nf_flow_state_check(flow, ip_hdr(skb)->protocol, skb, thoff)) + return NF_ACCEPT; + + if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) && +@@ -460,7 +463,8 @@ nf_flow_offload_ipv6_hook(void *priv, st + if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) + return NF_ACCEPT; + +- if (nf_flow_tcp_state_check(flow, skb, sizeof(*ip6h))) ++ if (nf_flow_state_check(flow, ipv6_hdr(skb)->nexthdr, skb, ++ sizeof(*ip6h))) + return NF_ACCEPT; + + if (skb_try_make_writable(skb, sizeof(*ip6h))) diff --git a/target/linux/generic/backport-4.14/368-netfilter-nf_flow_table-fix-offloading-connections-w.patch b/target/linux/generic/backport-4.14/368-netfilter-nf_flow_table-fix-offloading-connections-w.patch new file mode 100644 index 000000000..f3d83a153 --- /dev/null +++ b/target/linux/generic/backport-4.14/368-netfilter-nf_flow_table-fix-offloading-connections-w.patch @@ -0,0 +1,23 @@ +From: Felix Fietkau +Date: Fri, 23 Mar 2018 19:12:30 +0100 +Subject: [PATCH] netfilter: nf_flow_table: fix offloading connections with + SNAT+DNAT + +Pass all NAT types to the flow offload struct, otherwise parts of the +address/port pair do not get translated properly, causing connection +stalls + +Signed-off-by: Felix Fietkau +--- + +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -84,7 +84,7 @@ flow_offload_alloc(struct nf_conn *ct, s + + if (ct->status & IPS_SRC_NAT) + flow->flags |= FLOW_OFFLOAD_SNAT; +- else if (ct->status & IPS_DST_NAT) ++ if (ct->status & IPS_DST_NAT) + flow->flags |= FLOW_OFFLOAD_DNAT; + + return flow; diff --git a/target/linux/generic/backport-4.9/023-2-smsc75xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/backport-4.9/023-2-smsc75xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch deleted file mode 100644 index 99d98e101..000000000 --- a/target/linux/generic/backport-4.9/023-2-smsc75xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch +++ /dev/null @@ -1,36 +0,0 @@ -From b7c6d2675899cfff0180412c63fc9cbd5bacdb4d Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Wed, 19 Apr 2017 09:59:21 -0700 -Subject: [PATCH] smsc75xx: use skb_cow_head() to deal with cloned skbs - -We need to ensure there is enough headroom to push extra header, -but we also need to check if we are allowed to change headers. - -skb_cow_head() is the proper helper to deal with this. - -Fixes: d0cad871703b ("smsc75xx: SMSC LAN75xx USB gigabit ethernet adapter driver") -Signed-off-by: Eric Dumazet -Cc: James Hughes -Signed-off-by: David S. Miller ---- - drivers/net/usb/smsc75xx.c | 8 ++------ - 1 file changed, 2 insertions(+), 6 deletions(-) - ---- a/drivers/net/usb/smsc75xx.c -+++ b/drivers/net/usb/smsc75xx.c -@@ -2205,13 +2205,9 @@ static struct sk_buff *smsc75xx_tx_fixup - { - u32 tx_cmd_a, tx_cmd_b; - -- if (skb_headroom(skb) < SMSC75XX_TX_OVERHEAD) { -- struct sk_buff *skb2 = -- skb_copy_expand(skb, SMSC75XX_TX_OVERHEAD, 0, flags); -+ if (skb_cow_head(skb, SMSC75XX_TX_OVERHEAD)) { - dev_kfree_skb_any(skb); -- skb = skb2; -- if (!skb) -- return NULL; -+ return NULL; - } - - tx_cmd_a = (u32)(skb->len & TX_CMD_A_LEN) | TX_CMD_A_FCS; diff --git a/target/linux/generic/backport-4.9/023-3-cx82310_eth-use-skb_cow_head-to-deal-with-cloned-skb.patch b/target/linux/generic/backport-4.9/023-3-cx82310_eth-use-skb_cow_head-to-deal-with-cloned-skb.patch deleted file mode 100644 index aee8aa980..000000000 --- a/target/linux/generic/backport-4.9/023-3-cx82310_eth-use-skb_cow_head-to-deal-with-cloned-skb.patch +++ /dev/null @@ -1,35 +0,0 @@ -From a9e840a2081ed28c2b7caa6a9a0041c950b3c37d Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Wed, 19 Apr 2017 09:59:22 -0700 -Subject: [PATCH] cx82310_eth: use skb_cow_head() to deal with cloned skbs - -We need to ensure there is enough headroom to push extra header, -but we also need to check if we are allowed to change headers. - -skb_cow_head() is the proper helper to deal with this. - -Fixes: cc28a20e77b2 ("introduce cx82310_eth: Conexant CX82310-based ADSL router USB ethernet driver") -Signed-off-by: Eric Dumazet -Cc: James Hughes -Signed-off-by: David S. Miller ---- - drivers/net/usb/cx82310_eth.c | 7 ++----- - 1 file changed, 2 insertions(+), 5 deletions(-) - ---- a/drivers/net/usb/cx82310_eth.c -+++ b/drivers/net/usb/cx82310_eth.c -@@ -293,12 +293,9 @@ static struct sk_buff *cx82310_tx_fixup( - { - int len = skb->len; - -- if (skb_headroom(skb) < 2) { -- struct sk_buff *skb2 = skb_copy_expand(skb, 2, 0, flags); -+ if (skb_cow_head(skb, 2)) { - dev_kfree_skb_any(skb); -- skb = skb2; -- if (!skb) -- return NULL; -+ return NULL; - } - skb_push(skb, 2); - diff --git a/target/linux/generic/backport-4.9/023-4-sr9700-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/backport-4.9/023-4-sr9700-use-skb_cow_head-to-deal-with-cloned-skbs.patch deleted file mode 100644 index 4d0fcf6fc..000000000 --- a/target/linux/generic/backport-4.9/023-4-sr9700-use-skb_cow_head-to-deal-with-cloned-skbs.patch +++ /dev/null @@ -1,37 +0,0 @@ -From d532c1082f68176363ed766d09bf187616e282fe Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Wed, 19 Apr 2017 09:59:23 -0700 -Subject: [PATCH] sr9700: use skb_cow_head() to deal with cloned skbs - -We need to ensure there is enough headroom to push extra header, -but we also need to check if we are allowed to change headers. - -skb_cow_head() is the proper helper to deal with this. - -Fixes: c9b37458e956 ("USB2NET : SR9700 : One chip USB 1.1 USB2NET SR9700Device Driver Support") -Signed-off-by: Eric Dumazet -Cc: James Hughes -Signed-off-by: David S. Miller ---- - drivers/net/usb/sr9700.c | 9 ++------- - 1 file changed, 2 insertions(+), 7 deletions(-) - ---- a/drivers/net/usb/sr9700.c -+++ b/drivers/net/usb/sr9700.c -@@ -456,14 +456,9 @@ static struct sk_buff *sr9700_tx_fixup(s - - len = skb->len; - -- if (skb_headroom(skb) < SR_TX_OVERHEAD) { -- struct sk_buff *skb2; -- -- skb2 = skb_copy_expand(skb, SR_TX_OVERHEAD, 0, flags); -+ if (skb_cow_head(skb, SR_TX_OVERHEAD)) { - dev_kfree_skb_any(skb); -- skb = skb2; -- if (!skb) -- return NULL; -+ return NULL; - } - - __skb_push(skb, SR_TX_OVERHEAD); diff --git a/target/linux/generic/backport-4.9/023-5-lan78xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/backport-4.9/023-5-lan78xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch deleted file mode 100644 index ea8279940..000000000 --- a/target/linux/generic/backport-4.9/023-5-lan78xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch +++ /dev/null @@ -1,38 +0,0 @@ -From d4ca73591916b760478d2b04334d5dcadc028e9c Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Wed, 19 Apr 2017 09:59:24 -0700 -Subject: [PATCH] lan78xx: use skb_cow_head() to deal with cloned skbs - -We need to ensure there is enough headroom to push extra header, -but we also need to check if we are allowed to change headers. - -skb_cow_head() is the proper helper to deal with this. - -Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver") -Signed-off-by: Eric Dumazet -Cc: James Hughes -Cc: Woojung Huh -Signed-off-by: David S. Miller ---- - drivers/net/usb/lan78xx.c | 9 ++------- - 1 file changed, 2 insertions(+), 7 deletions(-) - ---- a/drivers/net/usb/lan78xx.c -+++ b/drivers/net/usb/lan78xx.c -@@ -2419,14 +2419,9 @@ static struct sk_buff *lan78xx_tx_prep(s - { - u32 tx_cmd_a, tx_cmd_b; - -- if (skb_headroom(skb) < TX_OVERHEAD) { -- struct sk_buff *skb2; -- -- skb2 = skb_copy_expand(skb, TX_OVERHEAD, 0, flags); -+ if (skb_cow_head(skb, TX_OVERHEAD)) { - dev_kfree_skb_any(skb); -- skb = skb2; -- if (!skb) -- return NULL; -+ return NULL; - } - - if (lan78xx_linearize(skb) < 0) diff --git a/target/linux/generic/backport-4.9/067-v4.11-mtd-nand-Add-Winbond-manufacturer-id.patch b/target/linux/generic/backport-4.9/067-v4.11-mtd-nand-Add-Winbond-manufacturer-id.patch new file mode 100644 index 000000000..cbab378b2 --- /dev/null +++ b/target/linux/generic/backport-4.9/067-v4.11-mtd-nand-Add-Winbond-manufacturer-id.patch @@ -0,0 +1,34 @@ +From a4077ce5871304f8a78f80b74b18b6052a410f1a Mon Sep 17 00:00:00 2001 +From: "Andrey Jr. Melnikov" +Date: Thu, 8 Dec 2016 19:57:08 +0300 +Subject: [PATCH] mtd: nand: Add Winbond manufacturer id + +Add WINBOND manufacturer id. + +Signed-off-by: Andrey Jr. Melnikov +Signed-off-by: Boris Brezillon +--- + drivers/mtd/nand/nand_ids.c | 1 + + include/linux/mtd/nand.h | 1 + + 2 files changed, 2 insertions(+) + +--- a/drivers/mtd/nand/nand_ids.c ++++ b/drivers/mtd/nand/nand_ids.c +@@ -182,6 +182,7 @@ struct nand_manufacturers nand_manuf_ids + {NAND_MFR_SANDISK, "SanDisk"}, + {NAND_MFR_INTEL, "Intel"}, + {NAND_MFR_ATO, "ATO"}, ++ {NAND_MFR_WINBOND, "Winbond"}, + {0x0, "Unknown"} + }; + +--- a/include/linux/mtd/nand.h ++++ b/include/linux/mtd/nand.h +@@ -928,6 +928,7 @@ static inline void nand_set_controller_d + #define NAND_MFR_SANDISK 0x45 + #define NAND_MFR_INTEL 0x89 + #define NAND_MFR_ATO 0x9b ++#define NAND_MFR_WINBOND 0xef + + /* The maximum expected count of bytes in the NAND ID sequence */ + #define NAND_MAX_ID_LEN 8 diff --git a/target/linux/generic/backport-4.9/090-net-generalize-napi_complete_done.patch b/target/linux/generic/backport-4.9/090-net-generalize-napi_complete_done.patch index aaa743519..5c6e334b1 100644 --- a/target/linux/generic/backport-4.9/090-net-generalize-napi_complete_done.patch +++ b/target/linux/generic/backport-4.9/090-net-generalize-napi_complete_done.patch @@ -1095,7 +1095,7 @@ Signed-off-by: David S. Miller dma_intr_ena = smsc9420_reg_read(pd, DMAC_INTR_ENA); --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -2678,7 +2678,7 @@ static int stmmac_poll(struct napi_struc +@@ -2684,7 +2684,7 @@ static int stmmac_poll(struct napi_struc work_done = stmmac_rx(priv, budget); if (work_done < budget) { diff --git a/target/linux/generic/config-4.14 b/target/linux/generic/config-4.14 index fa389bf8c..a27198335 100644 --- a/target/linux/generic/config-4.14 +++ b/target/linux/generic/config-4.14 @@ -433,6 +433,7 @@ CONFIG_BASE_FULL=y CONFIG_BASE_SMALL=0 # CONFIG_BATMAN_ADV is not set # CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_BQ27XXX_HDQ is not set # CONFIG_BATTERY_DS2760 is not set # CONFIG_BATTERY_DS2780 is not set # CONFIG_BATTERY_DS2781 is not set @@ -461,6 +462,7 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_BCMGENET is not set # CONFIG_BCM_IPROC_ADC is not set # CONFIG_BCM_KONA_USB2_PHY is not set +# CONFIG_BCM_SBA_RAID is not set # CONFIG_BDI_SWITCH is not set # CONFIG_BE2ISCSI is not set # CONFIG_BE2NET is not set @@ -590,6 +592,7 @@ CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT=3 CONFIG_BOOT_RAW=y CONFIG_BPF=y # CONFIG_BPF_JIT is not set +# CONFIG_BPF_JIT_ALWAYS_ON is not set # CONFIG_BPF_STREAM_PARSER is not set CONFIG_BPF_SYSCALL=y # CONFIG_BPQETHER is not set @@ -702,6 +705,7 @@ CONFIG_CARDBUS=y # CONFIG_CARDMAN_4040 is not set # CONFIG_CARL9170 is not set # CONFIG_CASSINI is not set +# CONFIG_CAVIUM_CPT is not set # CONFIG_CAVIUM_ERRATUM_22375 is not set # CONFIG_CAVIUM_ERRATUM_23144 is not set # CONFIG_CAVIUM_ERRATUM_23154 is not set @@ -711,8 +715,8 @@ CONFIG_CARDBUS=y # CONFIG_CB710_CORE is not set # CONFIG_CC10001_ADC is not set # CONFIG_CCS811 is not set -# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_CC_STACKPROTECTOR is not set CONFIG_CC_STACKPROTECTOR_NONE=y # CONFIG_CC_STACKPROTECTOR_REGULAR is not set @@ -725,6 +729,7 @@ CONFIG_CC_STACKPROTECTOR_NONE=y # CONFIG_CGROUPS is not set # CONFIG_CGROUP_BPF is not set # CONFIG_CGROUP_DEBUG is not set +# CONFIG_CGROUP_NET_CLASSID is not set # CONFIG_CGROUP_NET_PRIO is not set # CONFIG_CGROUP_RDMA is not set # CONFIG_CHARGER_BQ2415X is not set @@ -803,6 +808,8 @@ CONFIG_CMDLINE="" # CONFIG_COMMON_CLK_SI5351 is not set # CONFIG_COMMON_CLK_SI570 is not set # CONFIG_COMMON_CLK_VC5 is not set +# CONFIG_COMMON_CLK_VERSATILE is not set +# CONFIG_COMMON_CLK_XGENE is not set # CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set # CONFIG_COMPACTION is not set # CONFIG_COMPAL_LAPTOP is not set @@ -890,6 +897,7 @@ CONFIG_CRYPTO_BLKCIPHER2=y # CONFIG_CRYPTO_DEV_ATMEL_AES is not set # CONFIG_CRYPTO_DEV_ATMEL_SHA is not set # CONFIG_CRYPTO_DEV_ATMEL_TDES is not set +# CONFIG_CRYPTO_DEV_CAVIUM_ZIP is not set # CONFIG_CRYPTO_DEV_CCP is not set # CONFIG_CRYPTO_DEV_CCREE is not set # CONFIG_CRYPTO_DEV_FSL_CAAM is not set @@ -907,6 +915,7 @@ CONFIG_CRYPTO_BLKCIPHER2=y # CONFIG_CRYPTO_DEV_QAT_DH895xCC is not set # CONFIG_CRYPTO_DEV_QAT_DH895xCCVF is not set # CONFIG_CRYPTO_DEV_QCE is not set +# CONFIG_CRYPTO_DEV_SAFEXCEL is not set # CONFIG_CRYPTO_DEV_SAHARA is not set # CONFIG_CRYPTO_DEV_TALITOS is not set # CONFIG_CRYPTO_DEV_VIRTIO is not set @@ -1079,6 +1088,7 @@ CONFIG_DEVPORT=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_DEVTMPFS is not set # CONFIG_DEVTMPFS_MOUNT is not set +# CONFIG_DEV_DAX is not set # CONFIG_DGAP is not set # CONFIG_DGNC is not set # CONFIG_DHT11 is not set @@ -1181,6 +1191,7 @@ CONFIG_DQL=y # CONFIG_DRM_SII902X is not set # CONFIG_DRM_SIL_SII8620 is not set # CONFIG_DRM_STI is not set +# CONFIG_DRM_STM is not set # CONFIG_DRM_TILCDC is not set # CONFIG_DRM_TINYDRM is not set # CONFIG_DRM_TI_TFP410 is not set @@ -1269,6 +1280,7 @@ CONFIG_EXPERT=y CONFIG_EXT4_USE_FOR_EXT2=y # CONFIG_EXTCON is not set # CONFIG_EXTCON_ADC_JACK is not set +# CONFIG_EXTCON_AXP288 is not set # CONFIG_EXTCON_GPIO is not set # CONFIG_EXTCON_INTEL_INT3496 is not set # CONFIG_EXTCON_MAX3355 is not set @@ -1522,6 +1534,7 @@ CONFIG_GENERIC_NET_UTILS=y # CONFIG_HAMRADIO is not set # CONFIG_HAPPYMEAL is not set # CONFIG_HARDENED_USERCOPY is not set +# CONFIG_HARDEN_BRANCH_PREDICTOR is not set # CONFIG_HARDLOCKUP_DETECTOR is not set # CONFIG_HAVE_AOUT is not set CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y @@ -1690,6 +1703,7 @@ CONFIG_HW_PERF_EVENTS=y # CONFIG_HW_RANDOM is not set # CONFIG_HW_RANDOM_AMD is not set # CONFIG_HW_RANDOM_ATMEL is not set +# CONFIG_HW_RANDOM_CAVIUM is not set # CONFIG_HW_RANDOM_EXYNOS is not set # CONFIG_HW_RANDOM_GEODE is not set # CONFIG_HW_RANDOM_INTEL is not set @@ -2609,6 +2623,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_MMC_BLOCK is not set CONFIG_MMC_BLOCK_BOUNCE=y CONFIG_MMC_BLOCK_MINORS=8 +# CONFIG_MMC_CAVIUM_THUNDERX is not set # CONFIG_MMC_CB710 is not set # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_DW is not set @@ -2801,6 +2816,7 @@ CONFIG_MTD_SPLIT=y # CONFIG_MTD_SPLIT_FIRMWARE is not set CONFIG_MTD_SPLIT_FIRMWARE_NAME="firmware" # CONFIG_MTD_SPLIT_FIT_FW is not set +# CONFIG_MTD_SPLIT_JIMAGE_FW is not set # CONFIG_MTD_SPLIT_LZMA_FW is not set # CONFIG_MTD_SPLIT_MINOR_FW is not set # CONFIG_MTD_SPLIT_SEAMA_FW is not set @@ -2975,6 +2991,7 @@ CONFIG_NET_CORE=y # CONFIG_NET_DSA_MV88E6XXX is not set # CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set # CONFIG_NET_DSA_QCA8K is not set +# CONFIG_NET_DSA_SMSC_LAN9303_I2C is not set # CONFIG_NET_DSA_SMSC_LAN9303_MDIO is not set # CONFIG_NET_DSA_TAG_DSA is not set # CONFIG_NET_DSA_TAG_EDSA is not set @@ -3132,6 +3149,7 @@ CONFIG_NFS_V3=y # CONFIG_NFT_DUP_IPV6 is not set # CONFIG_NFT_FIB_IPV4 is not set # CONFIG_NFT_FIB_IPV6 is not set +# CONFIG_NFT_FLOW_OFFLOAD is not set # CONFIG_NFT_OBJREF is not set # CONFIG_NFT_RT is not set # CONFIG_NFT_SET_BITMAP is not set @@ -3164,6 +3182,7 @@ CONFIG_NF_CONNTRACK_PROCFS=y # CONFIG_NF_DEFRAG_IPV4 is not set # CONFIG_NF_DUP_IPV4 is not set # CONFIG_NF_DUP_IPV6 is not set +# CONFIG_NF_FLOW_TABLE is not set # CONFIG_NF_LOG_ARP is not set # CONFIG_NF_LOG_IPV4 is not set # CONFIG_NF_LOG_NETDEV is not set @@ -3264,6 +3283,7 @@ CONFIG_NMI_LOG_BUF_SHIFT=13 # CONFIG_NTP_PPS is not set # CONFIG_NVM is not set # CONFIG_NVMEM is not set +# CONFIG_NVMEM_BCM_OCOTP is not set # CONFIG_NVMEM_IMX_OCOTP is not set # CONFIG_NVME_FC is not set # CONFIG_NVME_TARGET is not set @@ -3391,6 +3411,7 @@ CONFIG_PARTITION_ADVANCED=y # CONFIG_PCIE_DW_PLAT is not set # CONFIG_PCIE_ECRC is not set # CONFIG_PCIE_IPROC is not set +# CONFIG_PCIE_KIRIN is not set # CONFIG_PCIE_PTM is not set # CONFIG_PCIPCWATCHDOG is not set # CONFIG_PCI_ATMEL is not set @@ -3401,6 +3422,7 @@ CONFIG_PARTITION_ADVANCED=y # CONFIG_PCI_ENDPOINT_TEST is not set # CONFIG_PCI_FTPCI100 is not set # CONFIG_PCI_HERMES is not set +# CONFIG_PCI_HISI is not set # CONFIG_PCI_HOST_GENERIC is not set # CONFIG_PCI_HOST_THUNDER_ECAM is not set # CONFIG_PCI_HOST_THUNDER_PEM is not set @@ -3414,6 +3436,7 @@ CONFIG_PCI_QUIRKS=y # CONFIG_PCI_STUB is not set # CONFIG_PCI_SW_SWITCHTEC is not set CONFIG_PCI_SYSCALL=y +# CONFIG_PCI_XGENE is not set # CONFIG_PCMCIA is not set # CONFIG_PCMCIA_3C574 is not set # CONFIG_PCMCIA_3C589 is not set @@ -3457,6 +3480,7 @@ CONFIG_PCI_SYSCALL=y # CONFIG_PHY_PXA_28NM_USB2 is not set # CONFIG_PHY_QCOM_DWC3 is not set # CONFIG_PHY_SAMSUNG_USB2 is not set +# CONFIG_PHY_XGENE is not set # CONFIG_PI433 is not set # CONFIG_PID_IN_CONTEXTIDR is not set # CONFIG_PID_NS is not set @@ -3569,9 +3593,11 @@ CONFIG_PWRSEQ_EMMC=y CONFIG_PWRSEQ_SIMPLE=y # CONFIG_QCA7000 is not set # CONFIG_QCA7000_SPI is not set +# CONFIG_QCA7000_UART is not set # CONFIG_QCOM_EMAC is not set # CONFIG_QCOM_FALKOR_ERRATUM_1003 is not set # CONFIG_QCOM_FALKOR_ERRATUM_1009 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_E1041 is not set # CONFIG_QCOM_HIDMA is not set # CONFIG_QCOM_HIDMA_MGMT is not set # CONFIG_QCOM_QDF2400_ERRATUM_0065 is not set @@ -4486,6 +4512,7 @@ CONFIG_SND_PROC_FS=y # CONFIG_SND_SOC_MEDIATEK is not set # CONFIG_SND_SOC_MPC5200_AC97 is not set # CONFIG_SND_SOC_MPC5200_I2S is not set +# CONFIG_SND_SOC_MSM8916_WCD_ANALOG is not set # CONFIG_SND_SOC_MSM8916_WCD_DIGITAL is not set # CONFIG_SND_SOC_MT2701 is not set # CONFIG_SND_SOC_MT8173 is not set @@ -4719,6 +4746,7 @@ CONFIG_SWAP=y # CONFIG_SWCONFIG_B53 is not set # CONFIG_SWCONFIG_B53_SPI_DRIVER is not set # CONFIG_SWCONFIG_LEDS is not set +# CONFIG_SW_SYNC is not set # CONFIG_SX9500 is not set # CONFIG_SXGBE_ETH is not set # CONFIG_SYNCLINK_CS is not set @@ -4943,7 +4971,7 @@ CONFIG_TMPFS_XATTR=y # CONFIG_TRACER_SNAPSHOT is not set # CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP is not set # CONFIG_TRACE_BRANCH_PROFILING is not set -# CONFIG_TRACE_ENUM_MAP_FILE is not set +# CONFIG_TRACE_EVAL_MAP_FILE is not set CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_TRACE_SINK is not set # CONFIG_TRACING_EVENTS_GPIO is not set @@ -4974,6 +5002,7 @@ CONFIG_TTY=y # CONFIG_UACCESS_WITH_MEMCPY is not set # CONFIG_UBIFS_ATIME_SUPPORT is not set # CONFIG_UBIFS_FS_ENCRYPTION is not set +CONFIG_UBIFS_FS_FORMAT4=y # CONFIG_UBIFS_FS_SECURITY is not set # CONFIG_UBSAN is not set # CONFIG_UCB1400_CORE is not set @@ -4992,6 +5021,7 @@ CONFIG_UNIX=y CONFIG_UNIX98_PTYS=y # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_UNIX_DIAG is not set +# CONFIG_UNMAP_KERNEL_AT_EL0 is not set # CONFIG_UNUSED_SYMBOLS is not set # CONFIG_UPROBES is not set # CONFIG_UPROBE_EVENT is not set diff --git a/target/linux/generic/hack-4.14/202-reduce_module_size.patch b/target/linux/generic/hack-4.14/202-reduce_module_size.patch index d3e014f41..7d67e847c 100644 --- a/target/linux/generic/hack-4.14/202-reduce_module_size.patch +++ b/target/linux/generic/hack-4.14/202-reduce_module_size.patch @@ -13,7 +13,7 @@ Signed-off-by: Felix Fietkau --- a/Makefile +++ b/Makefile -@@ -402,7 +402,7 @@ KBUILD_AFLAGS_KERNEL := +@@ -430,7 +430,7 @@ KBUILD_AFLAGS_KERNEL := KBUILD_CFLAGS_KERNEL := KBUILD_AFLAGS_MODULE := -DMODULE KBUILD_CFLAGS_MODULE := -DMODULE @@ -21,4 +21,4 @@ Signed-off-by: Felix Fietkau +KBUILD_LDFLAGS_MODULE = -T $(srctree)/scripts/module-common.lds $(if $(CONFIG_PROFILING),,-s) GCC_PLUGINS_CFLAGS := - # Read KERNELRELEASE from include/config/kernel.release (if it exists) + export ARCH SRCARCH SUBARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD diff --git a/target/linux/generic/hack-4.14/204-module_strip.patch b/target/linux/generic/hack-4.14/204-module_strip.patch index 2141cfef9..db65062fc 100644 --- a/target/linux/generic/hack-4.14/204-module_strip.patch +++ b/target/linux/generic/hack-4.14/204-module_strip.patch @@ -98,7 +98,7 @@ Signed-off-by: Felix Fietkau --- a/init/Kconfig +++ b/init/Kconfig -@@ -1896,6 +1896,13 @@ config TRIM_UNUSED_KSYMS +@@ -1903,6 +1903,13 @@ config TRIM_UNUSED_KSYMS If unsure, or if you need to build out-of-tree modules, say N. @@ -114,7 +114,7 @@ Signed-off-by: Felix Fietkau config MODULES_TREE_LOOKUP --- a/kernel/module.c +++ b/kernel/module.c -@@ -2997,9 +2997,11 @@ static struct module *setup_load_info(st +@@ -3006,9 +3006,11 @@ static struct module *setup_load_info(st static int check_modinfo(struct module *mod, struct load_info *info, int flags) { @@ -127,14 +127,14 @@ Signed-off-by: Felix Fietkau if (flags & MODULE_INIT_IGNORE_VERMAGIC) modmagic = NULL; -@@ -3020,6 +3022,7 @@ static int check_modinfo(struct module * +@@ -3029,6 +3031,7 @@ static int check_modinfo(struct module * mod->name); add_taint_module(mod, TAINT_OOT_MODULE, LOCKDEP_STILL_OK); } +#endif - if (get_modinfo(info, "staging")) { - add_taint_module(mod, TAINT_CRAP, LOCKDEP_STILL_OK); + check_modinfo_retpoline(mod, info); + --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1982,7 +1982,9 @@ static void read_symbols(char *modname) @@ -158,7 +158,7 @@ Signed-off-by: Felix Fietkau buf_printf(b, "\n"); buf_printf(b, "__visible struct module __this_module\n"); buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n"); -@@ -2161,16 +2165,20 @@ static void add_header(struct buffer *b, +@@ -2161,8 +2165,10 @@ static void add_header(struct buffer *b, static void add_intree_flag(struct buffer *b, int is_intree) { @@ -168,6 +168,9 @@ Signed-off-by: Felix Fietkau +#endif } + /* Cannot check for assembler */ +@@ -2175,10 +2181,12 @@ static void add_retpoline(struct buffer + static void add_staging_flag(struct buffer *b, const char *name) { +#ifndef CONFIG_MODULE_STRIPPED @@ -179,7 +182,7 @@ Signed-off-by: Felix Fietkau } /** -@@ -2269,11 +2277,13 @@ static void add_depends(struct buffer *b +@@ -2277,11 +2285,13 @@ static void add_depends(struct buffer *b static void add_srcversion(struct buffer *b, struct module *mod) { @@ -193,7 +196,7 @@ Signed-off-by: Felix Fietkau } static void write_if_changed(struct buffer *b, const char *fname) -@@ -2509,7 +2519,9 @@ int main(int argc, char **argv) +@@ -2518,7 +2528,9 @@ int main(int argc, char **argv) add_staging_flag(&buf, mod->name); err |= add_versions(&buf, mod); add_depends(&buf, mod, modules); diff --git a/target/linux/generic/hack-4.14/207-disable-modorder.patch b/target/linux/generic/hack-4.14/207-disable-modorder.patch index 4afed16a0..8f99cde61 100644 --- a/target/linux/generic/hack-4.14/207-disable-modorder.patch +++ b/target/linux/generic/hack-4.14/207-disable-modorder.patch @@ -15,7 +15,7 @@ Signed-off-by: Felix Fietkau --- a/Makefile +++ b/Makefile -@@ -1212,7 +1212,6 @@ all: modules +@@ -1233,7 +1233,6 @@ all: modules PHONY += modules modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin @@ -23,7 +23,7 @@ Signed-off-by: Felix Fietkau @$(kecho) ' Building modules, stage 2.'; $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost -@@ -1241,7 +1240,6 @@ _modinst_: +@@ -1262,7 +1261,6 @@ _modinst_: rm -f $(MODLIB)/build ; \ ln -s $(CURDIR) $(MODLIB)/build ; \ fi diff --git a/target/linux/generic/hack-4.14/220-gc_sections.patch b/target/linux/generic/hack-4.14/220-gc_sections.patch index e06ddb80d..ef7cd6f89 100644 --- a/target/linux/generic/hack-4.14/220-gc_sections.patch +++ b/target/linux/generic/hack-4.14/220-gc_sections.patch @@ -21,9 +21,9 @@ Signed-off-by: Gabor Juhos --- a/Makefile +++ b/Makefile -@@ -405,6 +405,11 @@ KBUILD_CFLAGS_MODULE := -DMODULE - KBUILD_LDFLAGS_MODULE = -T $(srctree)/scripts/module-common.lds $(if $(CONFIG_PROFILING),,-s) - GCC_PLUGINS_CFLAGS := +@@ -272,6 +272,11 @@ else + scripts/Kbuild.include: ; + include scripts/Kbuild.include +ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION +KBUILD_CFLAGS_KERNEL += $(call cc-option,-ffunction-sections,) @@ -33,7 +33,7 @@ Signed-off-by: Gabor Juhos # Read KERNELRELEASE from include/config/kernel.release (if it exists) KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null) KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION) -@@ -784,11 +789,6 @@ ifdef CONFIG_DEBUG_SECTION_MISMATCH +@@ -787,11 +792,6 @@ ifdef CONFIG_DEBUG_SECTION_MISMATCH KBUILD_CFLAGS += $(call cc-option, -fno-inline-functions-called-once) endif diff --git a/target/linux/generic/hack-4.14/221-module_exports.patch b/target/linux/generic/hack-4.14/221-module_exports.patch index 9fafc9fae..2f59d6e93 100644 --- a/target/linux/generic/hack-4.14/221-module_exports.patch +++ b/target/linux/generic/hack-4.14/221-module_exports.patch @@ -90,7 +90,7 @@ Signed-off-by: Felix Fietkau __used \ --- a/scripts/Makefile.build +++ b/scripts/Makefile.build -@@ -420,7 +420,7 @@ targets += $(extra-y) $(MAKECMDGOALS) $( +@@ -434,7 +434,7 @@ targets += $(extra-y) $(MAKECMDGOALS) $( # Linker scripts preprocessor (.lds.S -> .lds) # --------------------------------------------------------------------------- quiet_cmd_cpp_lds_S = LDS $@ diff --git a/target/linux/generic/hack-4.14/250-netfilter_depends.patch b/target/linux/generic/hack-4.14/250-netfilter_depends.patch index 17068f7da..6f6e1be5e 100644 --- a/target/linux/generic/hack-4.14/250-netfilter_depends.patch +++ b/target/linux/generic/hack-4.14/250-netfilter_depends.patch @@ -17,7 +17,7 @@ Signed-off-by: Felix Fietkau depends on NETFILTER_ADVANCED help H.323 is a VoIP signalling protocol from ITU-T. As one of the most -@@ -1012,7 +1011,6 @@ config NETFILTER_XT_TARGET_SECMARK +@@ -1037,7 +1036,6 @@ config NETFILTER_XT_TARGET_SECMARK config NETFILTER_XT_TARGET_TCPMSS tristate '"TCPMSS" target support' diff --git a/target/linux/generic/hack-4.14/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch b/target/linux/generic/hack-4.14/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch new file mode 100644 index 000000000..860a7e03c --- /dev/null +++ b/target/linux/generic/hack-4.14/300-MIPS-r4k_cache-use-more-efficient-cache-blast.patch @@ -0,0 +1,66 @@ +From: Ben Menchaca +Date: Fri, 7 Jun 2013 18:35:22 -0500 +Subject: MIPS: r4k_cache: use more efficient cache blast + +Optimize the compiler output for larger cache blast cases that are +common for DMA-based networking. + +Signed-off-by: Ben Menchaca +Signed-off-by: Felix Fietkau +--- +--- a/arch/mips/include/asm/r4kcache.h ++++ b/arch/mips/include/asm/r4kcache.h +@@ -682,16 +682,48 @@ static inline void prot##extra##blast_## + unsigned long end) \ + { \ + unsigned long lsize = cpu_##desc##_line_size(); \ ++ unsigned long lsize_2 = lsize * 2; \ ++ unsigned long lsize_3 = lsize * 3; \ ++ unsigned long lsize_4 = lsize * 4; \ ++ unsigned long lsize_5 = lsize * 5; \ ++ unsigned long lsize_6 = lsize * 6; \ ++ unsigned long lsize_7 = lsize * 7; \ ++ unsigned long lsize_8 = lsize * 8; \ + unsigned long addr = start & ~(lsize - 1); \ +- unsigned long aend = (end - 1) & ~(lsize - 1); \ ++ unsigned long aend = (end + lsize - 1) & ~(lsize - 1); \ ++ int lines = (aend - addr) / lsize; \ + \ + __##pfx##flush_prologue \ + \ +- while (1) { \ ++ while (lines >= 8) { \ ++ prot##cache_op(hitop, addr); \ ++ prot##cache_op(hitop, addr + lsize); \ ++ prot##cache_op(hitop, addr + lsize_2); \ ++ prot##cache_op(hitop, addr + lsize_3); \ ++ prot##cache_op(hitop, addr + lsize_4); \ ++ prot##cache_op(hitop, addr + lsize_5); \ ++ prot##cache_op(hitop, addr + lsize_6); \ ++ prot##cache_op(hitop, addr + lsize_7); \ ++ addr += lsize_8; \ ++ lines -= 8; \ ++ } \ ++ \ ++ if (lines & 0x4) { \ ++ prot##cache_op(hitop, addr); \ ++ prot##cache_op(hitop, addr + lsize); \ ++ prot##cache_op(hitop, addr + lsize_2); \ ++ prot##cache_op(hitop, addr + lsize_3); \ ++ addr += lsize_4; \ ++ } \ ++ \ ++ if (lines & 0x2) { \ ++ prot##cache_op(hitop, addr); \ ++ prot##cache_op(hitop, addr + lsize); \ ++ addr += lsize_2; \ ++ } \ ++ \ ++ if (lines & 0x1) { \ + prot##cache_op(hitop, addr); \ +- if (addr == aend) \ +- break; \ +- addr += lsize; \ + } \ + \ + __##pfx##flush_epilogue \ diff --git a/target/linux/generic/hack-4.14/641-bridge_port_isolate.patch b/target/linux/generic/hack-4.14/641-bridge_port_isolate.patch index ab9f47657..538dbd16b 100644 --- a/target/linux/generic/hack-4.14/641-bridge_port_isolate.patch +++ b/target/linux/generic/hack-4.14/641-bridge_port_isolate.patch @@ -29,7 +29,7 @@ Signed-off-by: Felix Fietkau void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, bool local_rcv, bool local_orig) { -+ if (to->flags & BR_ISOLATE_MODE) ++ if (to->flags & BR_ISOLATE_MODE && !local_orig) + to = NULL; + if (to && should_deliver(to, skb)) { diff --git a/target/linux/generic/hack-4.14/650-netfilter-add-xt_OFFLOAD-target.patch b/target/linux/generic/hack-4.14/650-netfilter-add-xt_OFFLOAD-target.patch new file mode 100644 index 000000000..7f78d521f --- /dev/null +++ b/target/linux/generic/hack-4.14/650-netfilter-add-xt_OFFLOAD-target.patch @@ -0,0 +1,496 @@ +From: Felix Fietkau +Date: Tue, 20 Feb 2018 15:56:02 +0100 +Subject: [PATCH] netfilter: add xt_OFFLOAD target + +Signed-off-by: Felix Fietkau +--- + create mode 100644 net/netfilter/xt_OFFLOAD.c + +--- a/net/ipv4/netfilter/Kconfig ++++ b/net/ipv4/netfilter/Kconfig +@@ -75,8 +75,6 @@ config NF_TABLES_ARP + help + This option enables the ARP support for nf_tables. + +-endif # NF_TABLES +- + config NF_FLOW_TABLE_IPV4 + tristate "Netfilter flow table IPv4 module" + depends on NF_FLOW_TABLE +@@ -85,6 +83,8 @@ config NF_FLOW_TABLE_IPV4 + + To compile it as a module, choose M here. + ++endif # NF_TABLES ++ + config NF_DUP_IPV4 + tristate "Netfilter IPv4 packet duplication to alternate destination" + depends on !NF_CONNTRACK || NF_CONNTRACK +--- a/net/ipv6/netfilter/Kconfig ++++ b/net/ipv6/netfilter/Kconfig +@@ -69,7 +69,6 @@ config NFT_FIB_IPV6 + multicast or blackhole. + + endif # NF_TABLES_IPV6 +-endif # NF_TABLES + + config NF_FLOW_TABLE_IPV6 + tristate "Netfilter flow table IPv6 module" +@@ -79,6 +78,8 @@ config NF_FLOW_TABLE_IPV6 + + To compile it as a module, choose M here. + ++endif # NF_TABLES ++ + config NF_DUP_IPV6 + tristate "Netfilter IPv6 packet duplication to alternate destination" + depends on !NF_CONNTRACK || NF_CONNTRACK +--- a/net/netfilter/Kconfig ++++ b/net/netfilter/Kconfig +@@ -665,8 +665,6 @@ config NFT_FIB_NETDEV + + endif # NF_TABLES_NETDEV + +-endif # NF_TABLES +- + config NF_FLOW_TABLE_INET + tristate "Netfilter flow table mixed IPv4/IPv6 module" + depends on NF_FLOW_TABLE +@@ -675,11 +673,12 @@ config NF_FLOW_TABLE_INET + + To compile it as a module, choose M here. + ++endif # NF_TABLES ++ + config NF_FLOW_TABLE + tristate "Netfilter flow table module" + depends on NETFILTER_INGRESS + depends on NF_CONNTRACK +- depends on NF_TABLES + help + This option adds the flow table core infrastructure. + +@@ -968,6 +967,15 @@ config NETFILTER_XT_TARGET_NOTRACK + depends on NETFILTER_ADVANCED + select NETFILTER_XT_TARGET_CT + ++config NETFILTER_XT_TARGET_FLOWOFFLOAD ++ tristate '"FLOWOFFLOAD" target support' ++ depends on NF_FLOW_TABLE ++ depends on NETFILTER_INGRESS ++ help ++ This option adds a `FLOWOFFLOAD' target, which uses the nf_flow_offload ++ module to speed up processing of packets by bypassing the usual ++ netfilter chains ++ + config NETFILTER_XT_TARGET_RATEEST + tristate '"RATEEST" target support' + depends on NETFILTER_ADVANCED +--- a/net/netfilter/Makefile ++++ b/net/netfilter/Makefile +@@ -134,6 +134,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIF + obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o + obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o + obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o ++obj-$(CONFIG_NETFILTER_XT_TARGET_FLOWOFFLOAD) += xt_FLOWOFFLOAD.o + obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o + obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o + obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o +--- /dev/null ++++ b/net/netfilter/xt_FLOWOFFLOAD.c +@@ -0,0 +1,365 @@ ++/* ++ * Copyright (C) 2018 Felix Fietkau ++ * ++ * 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. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static struct nf_flowtable nf_flowtable; ++static HLIST_HEAD(hooks); ++static DEFINE_SPINLOCK(hooks_lock); ++static struct delayed_work hook_work; ++ ++struct xt_flowoffload_hook { ++ struct hlist_node list; ++ struct nf_hook_ops ops; ++ struct net *net; ++ bool registered; ++ bool used; ++}; ++ ++static unsigned int ++xt_flowoffload_net_hook(void *priv, struct sk_buff *skb, ++ const struct nf_hook_state *state) ++{ ++ switch (skb->protocol) { ++ case htons(ETH_P_IP): ++ return nf_flow_offload_ip_hook(priv, skb, state); ++ case htons(ETH_P_IPV6): ++ return nf_flow_offload_ipv6_hook(priv, skb, state); ++ } ++ ++ return NF_ACCEPT; ++} ++ ++static int ++xt_flowoffload_create_hook(struct net_device *dev) ++{ ++ struct xt_flowoffload_hook *hook; ++ struct nf_hook_ops *ops; ++ ++ hook = kzalloc(sizeof(*hook), GFP_ATOMIC); ++ if (!hook) ++ return -ENOMEM; ++ ++ ops = &hook->ops; ++ ops->pf = NFPROTO_NETDEV; ++ ops->hooknum = NF_NETDEV_INGRESS; ++ ops->priority = 10; ++ ops->priv = &nf_flowtable; ++ ops->hook = xt_flowoffload_net_hook; ++ ops->dev = dev; ++ ++ hlist_add_head(&hook->list, &hooks); ++ mod_delayed_work(system_power_efficient_wq, &hook_work, 0); ++ ++ return 0; ++} ++ ++static struct xt_flowoffload_hook * ++flow_offload_lookup_hook(struct net_device *dev) ++{ ++ struct xt_flowoffload_hook *hook; ++ ++ hlist_for_each_entry(hook, &hooks, list) { ++ if (hook->ops.dev == dev) ++ return hook; ++ } ++ ++ return NULL; ++} ++ ++static void ++xt_flowoffload_check_device(struct net_device *dev) ++{ ++ struct xt_flowoffload_hook *hook; ++ ++ spin_lock_bh(&hooks_lock); ++ hook = flow_offload_lookup_hook(dev); ++ if (hook) ++ hook->used = true; ++ else ++ xt_flowoffload_create_hook(dev); ++ spin_unlock_bh(&hooks_lock); ++} ++ ++static void ++xt_flowoffload_register_hooks(void) ++{ ++ struct xt_flowoffload_hook *hook; ++ ++restart: ++ hlist_for_each_entry(hook, &hooks, list) { ++ if (hook->registered) ++ continue; ++ ++ hook->registered = true; ++ hook->net = dev_net(hook->ops.dev); ++ spin_unlock_bh(&hooks_lock); ++ nf_register_net_hook(hook->net, &hook->ops); ++ spin_lock_bh(&hooks_lock); ++ goto restart; ++ } ++ ++} ++ ++static void ++xt_flowoffload_cleanup_hooks(void) ++{ ++ struct xt_flowoffload_hook *hook; ++ ++restart: ++ hlist_for_each_entry(hook, &hooks, list) { ++ if (hook->used || !hook->registered) ++ continue; ++ ++ hlist_del(&hook->list); ++ spin_unlock_bh(&hooks_lock); ++ nf_unregister_net_hook(hook->net, &hook->ops); ++ kfree(hook); ++ spin_lock_bh(&hooks_lock); ++ goto restart; ++ } ++ ++} ++ ++static void ++xt_flowoffload_check_hook(struct flow_offload *flow, void *data) ++{ ++ struct flow_offload_tuple *tuple = &flow->tuplehash[0].tuple; ++ struct xt_flowoffload_hook *hook; ++ bool *found = data; ++ ++ spin_lock_bh(&hooks_lock); ++ hlist_for_each_entry(hook, &hooks, list) { ++ if (hook->ops.dev->ifindex != tuple->iifidx && ++ hook->ops.dev->ifindex != tuple->oifidx) ++ continue; ++ ++ hook->used = true; ++ *found = true; ++ } ++ spin_unlock_bh(&hooks_lock); ++} ++ ++static void ++xt_flowoffload_hook_work(struct work_struct *work) ++{ ++ struct xt_flowoffload_hook *hook; ++ bool found = false; ++ int err; ++ ++ spin_lock_bh(&hooks_lock); ++ xt_flowoffload_register_hooks(); ++ hlist_for_each_entry(hook, &hooks, list) ++ hook->used = false; ++ spin_unlock_bh(&hooks_lock); ++ ++ err = nf_flow_table_iterate(&nf_flowtable, xt_flowoffload_check_hook, ++ &found); ++ if (err && err != -EAGAIN) ++ goto out; ++ ++ spin_lock_bh(&hooks_lock); ++ xt_flowoffload_cleanup_hooks(); ++ spin_unlock_bh(&hooks_lock); ++ ++out: ++ if (found) ++ queue_delayed_work(system_power_efficient_wq, &hook_work, HZ); ++} ++ ++static bool ++xt_flowoffload_skip(struct sk_buff *skb) ++{ ++ struct ip_options *opt = &(IPCB(skb)->opt); ++ ++ if (unlikely(opt->optlen)) ++ return true; ++ if (skb_sec_path(skb)) ++ return true; ++ ++ return false; ++} ++ ++static struct dst_entry * ++xt_flowoffload_dst(const struct nf_conn *ct, enum ip_conntrack_dir dir, ++ const struct xt_action_param *par) ++{ ++ struct dst_entry *dst = NULL; ++ struct flowi fl; ++ ++ memset(&fl, 0, sizeof(fl)); ++ switch (xt_family(par)) { ++ case NFPROTO_IPV4: ++ fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip; ++ break; ++ case NFPROTO_IPV6: ++ fl.u.ip6.saddr = ct->tuplehash[dir].tuple.dst.u3.in6; ++ fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6; ++ break; ++ } ++ ++ nf_route(xt_net(par), &dst, &fl, false, xt_family(par)); ++ ++ return dst; ++} ++ ++static int ++xt_flowoffload_route(struct sk_buff *skb, const struct nf_conn *ct, ++ const struct xt_action_param *par, ++ struct nf_flow_route *route, enum ip_conntrack_dir dir) ++{ ++ struct dst_entry *this_dst, *other_dst; ++ ++ this_dst = xt_flowoffload_dst(ct, dir, par); ++ other_dst = xt_flowoffload_dst(ct, !dir, par); ++ if (!this_dst || !other_dst) ++ return -ENOENT; ++ ++ route->tuple[dir].dst = this_dst; ++ route->tuple[dir].ifindex = xt_in(par)->ifindex; ++ route->tuple[!dir].dst = other_dst; ++ route->tuple[!dir].ifindex = xt_out(par)->ifindex; ++ ++ return 0; ++} ++ ++static unsigned int ++flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par) ++{ ++ const struct xt_flowoffload_target_info *info = par->targinfo; ++ enum ip_conntrack_info ctinfo; ++ enum ip_conntrack_dir dir; ++ struct nf_flow_route route; ++ struct flow_offload *flow; ++ struct nf_conn *ct; ++ ++ if (xt_flowoffload_skip(skb)) ++ return XT_CONTINUE; ++ ++ ct = nf_ct_get(skb, &ctinfo); ++ if (ct == NULL) ++ return XT_CONTINUE; ++ ++ switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) { ++ case IPPROTO_TCP: ++ if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) ++ return XT_CONTINUE; ++ break; ++ case IPPROTO_UDP: ++ break; ++ default: ++ return XT_CONTINUE; ++ } ++ ++ if (test_bit(IPS_HELPER_BIT, &ct->status)) ++ return XT_CONTINUE; ++ ++ if (ctinfo == IP_CT_NEW || ++ ctinfo == IP_CT_RELATED) ++ return XT_CONTINUE; ++ ++ if (!xt_in(par) || !xt_out(par)) ++ return XT_CONTINUE; ++ ++ if (test_and_set_bit(IPS_OFFLOAD_BIT, &ct->status)) ++ return XT_CONTINUE; ++ ++ dir = CTINFO2DIR(ctinfo); ++ ++ if (xt_flowoffload_route(skb, ct, par, &route, dir) < 0) ++ goto err_flow_route; ++ ++ flow = flow_offload_alloc(ct, &route); ++ if (!flow) ++ goto err_flow_alloc; ++ ++ if (flow_offload_add(&nf_flowtable, flow) < 0) ++ goto err_flow_add; ++ ++ xt_flowoffload_check_device(xt_in(par)); ++ xt_flowoffload_check_device(xt_out(par)); ++ ++ if (info->flags & XT_FLOWOFFLOAD_HW) ++ nf_flow_offload_hw_add(xt_net(par), flow, ct); ++ ++ return XT_CONTINUE; ++ ++err_flow_add: ++ flow_offload_free(flow); ++err_flow_alloc: ++ dst_release(route.tuple[!dir].dst); ++err_flow_route: ++ clear_bit(IPS_OFFLOAD_BIT, &ct->status); ++ return XT_CONTINUE; ++} ++ ++ ++static int flowoffload_chk(const struct xt_tgchk_param *par) ++{ ++ struct xt_flowoffload_target_info *info = par->targinfo; ++ ++ if (info->flags & ~XT_FLOWOFFLOAD_MASK) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static struct xt_target offload_tg_reg __read_mostly = { ++ .family = NFPROTO_UNSPEC, ++ .name = "FLOWOFFLOAD", ++ .revision = 0, ++ .targetsize = sizeof(struct xt_flowoffload_target_info), ++ .usersize = sizeof(struct xt_flowoffload_target_info), ++ .checkentry = flowoffload_chk, ++ .target = flowoffload_tg, ++ .me = THIS_MODULE, ++}; ++ ++static int xt_flowoffload_table_init(struct nf_flowtable *table) ++{ ++ table->flags = NF_FLOWTABLE_F_HW; ++ nf_flow_table_init(table); ++ return 0; ++} ++ ++static void xt_flowoffload_table_cleanup(struct nf_flowtable *table) ++{ ++ nf_flow_table_free(table); ++} ++ ++static int __init xt_flowoffload_tg_init(void) ++{ ++ int ret; ++ ++ INIT_DELAYED_WORK(&hook_work, xt_flowoffload_hook_work); ++ ++ ret = xt_flowoffload_table_init(&nf_flowtable); ++ if (ret) ++ return ret; ++ ++ ret = xt_register_target(&offload_tg_reg); ++ if (ret) ++ xt_flowoffload_table_cleanup(&nf_flowtable); ++ ++ return ret; ++} ++ ++static void __exit xt_flowoffload_tg_exit(void) ++{ ++ xt_unregister_target(&offload_tg_reg); ++ xt_flowoffload_table_cleanup(&nf_flowtable); ++} ++ ++MODULE_LICENSE("GPL"); ++module_init(xt_flowoffload_tg_init); ++module_exit(xt_flowoffload_tg_exit); +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -6,7 +6,6 @@ + #include + #include + #include +-#include + #include + #include + #include +--- /dev/null ++++ b/include/uapi/linux/netfilter/xt_FLOWOFFLOAD.h +@@ -0,0 +1,17 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++#ifndef _XT_FLOWOFFLOAD_H ++#define _XT_FLOWOFFLOAD_H ++ ++#include ++ ++enum { ++ XT_FLOWOFFLOAD_HW = 1 << 0, ++ ++ XT_FLOWOFFLOAD_MASK = XT_FLOWOFFLOAD_HW ++}; ++ ++struct xt_flowoffload_target_info { ++ __u32 flags; ++}; ++ ++#endif /* _XT_FLOWOFFLOAD_H */ diff --git a/target/linux/generic/hack-4.14/660-fq_codel_defaults.patch b/target/linux/generic/hack-4.14/660-fq_codel_defaults.patch index 3e27351fa..b923a2d20 100644 --- a/target/linux/generic/hack-4.14/660-fq_codel_defaults.patch +++ b/target/linux/generic/hack-4.14/660-fq_codel_defaults.patch @@ -13,7 +13,7 @@ Signed-off-by: Felix Fietkau --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c -@@ -465,7 +465,11 @@ static int fq_codel_init(struct Qdisc *s +@@ -471,7 +471,11 @@ static int fq_codel_init(struct Qdisc *s sch->limit = 10*1024; q->flows_cnt = 1024; diff --git a/target/linux/generic/hack-4.14/661-use_fq_codel_by_default.patch b/target/linux/generic/hack-4.14/661-use_fq_codel_by_default.patch index ae911db87..7c724c0af 100644 --- a/target/linux/generic/hack-4.14/661-use_fq_codel_by_default.patch +++ b/target/linux/generic/hack-4.14/661-use_fq_codel_by_default.patch @@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h -@@ -369,12 +369,13 @@ extern struct Qdisc_ops noop_qdisc_ops; +@@ -368,12 +368,13 @@ extern struct Qdisc_ops noop_qdisc_ops; extern struct Qdisc_ops pfifo_fast_ops; extern struct Qdisc_ops mq_qdisc_ops; extern struct Qdisc_ops noqueue_qdisc_ops; @@ -55,7 +55,7 @@ Signed-off-by: Felix Fietkau register_qdisc(&pfifo_head_drop_qdisc_ops); --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c -@@ -694,7 +694,7 @@ static const struct Qdisc_class_ops fq_c +@@ -700,7 +700,7 @@ static const struct Qdisc_class_ops fq_c .walk = fq_codel_walk, }; @@ -64,7 +64,7 @@ Signed-off-by: Felix Fietkau .cl_ops = &fq_codel_class_ops, .id = "fq_codel", .priv_size = sizeof(struct fq_codel_sched_data), -@@ -709,6 +709,7 @@ static struct Qdisc_ops fq_codel_qdisc_o +@@ -715,6 +715,7 @@ static struct Qdisc_ops fq_codel_qdisc_o .dump_stats = fq_codel_dump_stats, .owner = THIS_MODULE, }; @@ -83,7 +83,7 @@ Signed-off-by: Felix Fietkau EXPORT_SYMBOL(default_qdisc_ops); /* Main transmission queue. */ -@@ -764,7 +764,7 @@ static void attach_one_default_qdisc(str +@@ -760,7 +760,7 @@ static void attach_one_default_qdisc(str void *_unused) { struct Qdisc *qdisc; diff --git a/target/linux/generic/hack-4.14/702-phy_add_aneg_done_function.patch b/target/linux/generic/hack-4.14/702-phy_add_aneg_done_function.patch index 9c249ca4c..0453112a1 100644 --- a/target/linux/generic/hack-4.14/702-phy_add_aneg_done_function.patch +++ b/target/linux/generic/hack-4.14/702-phy_add_aneg_done_function.patch @@ -15,7 +15,7 @@ --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -1437,6 +1437,9 @@ int genphy_update_link(struct phy_device +@@ -1458,6 +1458,9 @@ int genphy_update_link(struct phy_device { int status; diff --git a/target/linux/generic/hack-4.14/721-phy_packets.patch b/target/linux/generic/hack-4.14/721-phy_packets.patch index 07e6e9da6..62d029517 100644 --- a/target/linux/generic/hack-4.14/721-phy_packets.patch +++ b/target/linux/generic/hack-4.14/721-phy_packets.patch @@ -56,7 +56,7 @@ Signed-off-by: Felix Fietkau */ --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -2494,6 +2494,10 @@ static inline int pskb_trim(struct sk_bu +@@ -2491,6 +2491,10 @@ static inline int pskb_trim(struct sk_bu return (len < skb->len) ? __pskb_trim(skb, len) : 0; } @@ -67,7 +67,7 @@ Signed-off-by: Felix Fietkau /** * pskb_trim_unique - remove end from a paged unique (not cloned) buffer * @skb: buffer to alter -@@ -2624,16 +2628,6 @@ static inline struct sk_buff *dev_alloc_ +@@ -2621,16 +2625,6 @@ static inline struct sk_buff *dev_alloc_ } @@ -101,7 +101,7 @@ Signed-off-by: Felix Fietkau help --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -2975,10 +2975,20 @@ static int xmit_one(struct sk_buff *skb, +@@ -2982,10 +2982,20 @@ static int xmit_one(struct sk_buff *skb, if (!list_empty(&ptype_all) || !list_empty(&dev->ptype_all)) dev_queue_xmit_nit(skb, dev); @@ -128,7 +128,7 @@ Signed-off-by: Felix Fietkau } --- a/net/core/skbuff.c +++ b/net/core/skbuff.c -@@ -64,6 +64,7 @@ +@@ -63,6 +63,7 @@ #include #include #include @@ -136,7 +136,7 @@ Signed-off-by: Felix Fietkau #include #include -@@ -503,6 +504,22 @@ skb_fail: +@@ -499,6 +500,22 @@ skb_fail: } EXPORT_SYMBOL(__napi_alloc_skb); diff --git a/target/linux/generic/hack-4.14/901-debloat_sock_diag.patch b/target/linux/generic/hack-4.14/901-debloat_sock_diag.patch index d854865d6..29071d63c 100644 --- a/target/linux/generic/hack-4.14/901-debloat_sock_diag.patch +++ b/target/linux/generic/hack-4.14/901-debloat_sock_diag.patch @@ -61,7 +61,7 @@ Signed-off-by: Felix Fietkau struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie) { struct dst_entry *dst = __sk_dst_get(sk); -@@ -1597,9 +1609,11 @@ void sk_destruct(struct sock *sk) +@@ -1595,9 +1607,11 @@ void sk_destruct(struct sock *sk) static void __sk_free(struct sock *sk) { diff --git a/target/linux/generic/hack-4.14/902-debloat_proc.patch b/target/linux/generic/hack-4.14/902-debloat_proc.patch index e291da516..4f5fb7022 100644 --- a/target/linux/generic/hack-4.14/902-debloat_proc.patch +++ b/target/linux/generic/hack-4.14/902-debloat_proc.patch @@ -232,7 +232,7 @@ Signed-off-by: Felix Fietkau return -ENOMEM; --- a/mm/vmalloc.c +++ b/mm/vmalloc.c -@@ -2765,6 +2765,8 @@ static const struct file_operations proc +@@ -2769,6 +2769,8 @@ static const struct file_operations proc static int __init proc_vmalloc_init(void) { @@ -327,7 +327,7 @@ Signed-off-by: Felix Fietkau --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -3383,6 +3383,8 @@ static __net_initdata struct pernet_oper +@@ -3378,6 +3378,8 @@ static __net_initdata struct pernet_oper static int __init proto_init(void) { @@ -393,7 +393,7 @@ Signed-off-by: Felix Fietkau --- a/net/ipv4/route.c +++ b/net/ipv4/route.c -@@ -424,6 +424,9 @@ static struct pernet_operations ip_rt_pr +@@ -427,6 +427,9 @@ static struct pernet_operations ip_rt_pr static int __init ip_rt_proc_init(void) { diff --git a/target/linux/generic/hack-4.14/904-debloat_dma_buf.patch b/target/linux/generic/hack-4.14/904-debloat_dma_buf.patch index 8f1a3bca8..e71590933 100644 --- a/target/linux/generic/hack-4.14/904-debloat_dma_buf.patch +++ b/target/linux/generic/hack-4.14/904-debloat_dma_buf.patch @@ -13,7 +13,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig -@@ -243,7 +243,7 @@ config SOC_BUS +@@ -246,7 +246,7 @@ config SOC_BUS source "drivers/base/regmap/Kconfig" config DMA_SHARED_BUFFER @@ -21,7 +21,7 @@ Signed-off-by: Felix Fietkau + tristate default n select ANON_INODES - help + select IRQ_WORK --- a/drivers/dma-buf/Makefile +++ b/drivers/dma-buf/Makefile @@ -1,3 +1,7 @@ @@ -54,7 +54,7 @@ Signed-off-by: Felix Fietkau +MODULE_LICENSE("GPL"); --- a/kernel/sched/core.c +++ b/kernel/sched/core.c -@@ -2146,6 +2146,7 @@ int wake_up_state(struct task_struct *p, +@@ -2147,6 +2147,7 @@ int wake_up_state(struct task_struct *p, { return try_to_wake_up(p, state, 0); } diff --git a/target/linux/generic/hack-4.9/204-module_strip.patch b/target/linux/generic/hack-4.9/204-module_strip.patch index fd07cca06..e36846adb 100644 --- a/target/linux/generic/hack-4.9/204-module_strip.patch +++ b/target/linux/generic/hack-4.9/204-module_strip.patch @@ -137,7 +137,7 @@ Signed-off-by: Felix Fietkau add_taint_module(mod, TAINT_CRAP, LOCKDEP_STILL_OK); --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c -@@ -1964,7 +1964,9 @@ static void read_symbols(char *modname) +@@ -1965,7 +1965,9 @@ static void read_symbols(char *modname) symname = remove_dot(info.strtab + sym->st_name); handle_modversions(mod, &info, sym, symname); @@ -147,7 +147,7 @@ Signed-off-by: Felix Fietkau } if (!is_vmlinux(modname) || (is_vmlinux(modname) && vmlinux_section_warnings)) -@@ -2108,7 +2110,9 @@ static void add_header(struct buffer *b, +@@ -2109,7 +2111,9 @@ static void add_header(struct buffer *b, buf_printf(b, "#include \n"); buf_printf(b, "#include \n"); buf_printf(b, "\n"); @@ -157,7 +157,7 @@ Signed-off-by: Felix Fietkau buf_printf(b, "\n"); buf_printf(b, "__visible struct module __this_module\n"); buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n"); -@@ -2125,16 +2129,20 @@ static void add_header(struct buffer *b, +@@ -2126,16 +2130,20 @@ static void add_header(struct buffer *b, static void add_intree_flag(struct buffer *b, int is_intree) { @@ -178,7 +178,7 @@ Signed-off-by: Felix Fietkau } /* In kernel, this size is defined in linux/module.h; -@@ -2238,11 +2246,13 @@ static void add_depends(struct buffer *b +@@ -2239,11 +2247,13 @@ static void add_depends(struct buffer *b static void add_srcversion(struct buffer *b, struct module *mod) { @@ -192,7 +192,7 @@ Signed-off-by: Felix Fietkau } static void write_if_changed(struct buffer *b, const char *fname) -@@ -2476,7 +2486,9 @@ int main(int argc, char **argv) +@@ -2477,7 +2487,9 @@ int main(int argc, char **argv) add_staging_flag(&buf, mod->name); err |= add_versions(&buf, mod); add_depends(&buf, mod, modules); diff --git a/target/linux/generic/hack-4.9/710-phy-add-mdio_register_board_info.patch b/target/linux/generic/hack-4.9/710-phy-add-mdio_register_board_info.patch index 55607bc6e..217cf4a48 100644 --- a/target/linux/generic/hack-4.9/710-phy-add-mdio_register_board_info.patch +++ b/target/linux/generic/hack-4.9/710-phy-add-mdio_register_board_info.patch @@ -50,7 +50,7 @@ phy_device_free(phydev); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -859,6 +859,23 @@ void mdio_bus_exit(void); +@@ -870,6 +870,23 @@ void mdio_bus_exit(void); extern struct bus_type mdio_bus_type; diff --git a/target/linux/generic/hack-4.9/904-debloat_dma_buf.patch b/target/linux/generic/hack-4.9/904-debloat_dma_buf.patch index 4f432c356..81db6dcb3 100644 --- a/target/linux/generic/hack-4.9/904-debloat_dma_buf.patch +++ b/target/linux/generic/hack-4.9/904-debloat_dma_buf.patch @@ -13,7 +13,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig -@@ -241,7 +241,7 @@ config SOC_BUS +@@ -244,7 +244,7 @@ config SOC_BUS source "drivers/base/regmap/Kconfig" config DMA_SHARED_BUFFER diff --git a/target/linux/generic/pending-4.14/101-clocksource-mips-gic-timer-fix-clocksource-counter-w.patch b/target/linux/generic/pending-4.14/101-clocksource-mips-gic-timer-fix-clocksource-counter-w.patch new file mode 100644 index 000000000..a554aa112 --- /dev/null +++ b/target/linux/generic/pending-4.14/101-clocksource-mips-gic-timer-fix-clocksource-counter-w.patch @@ -0,0 +1,23 @@ +From: Felix Fietkau +Date: Wed, 21 Feb 2018 13:40:12 +0100 +Subject: [PATCH] clocksource: mips-gic-timer: fix clocksource counter width + +This code needs to use ffs instead of fls on the mask to determine the +shift for reading the GIC_CONFIG_COUNTBITS field. + +Fixes: e07127a077c7 ("clocksource: mips-gic-timer: Use new GIC accessor functions") +Cc: Paul Burton +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/clocksource/mips-gic-timer.c ++++ b/drivers/clocksource/mips-gic-timer.c +@@ -164,7 +164,7 @@ static int __init __gic_clocksource_init + + /* Set clocksource mask. */ + count_width = read_gic_config() & GIC_CONFIG_COUNTBITS; +- count_width >>= __fls(GIC_CONFIG_COUNTBITS); ++ count_width >>= __ffs(GIC_CONFIG_COUNTBITS); + count_width *= 4; + count_width += 32; + gic_clocksource.mask = CLOCKSOURCE_MASK(count_width); diff --git a/target/linux/generic/pending-4.14/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch b/target/linux/generic/pending-4.14/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch index fbf998138..5ee89be5a 100644 --- a/target/linux/generic/pending-4.14/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch +++ b/target/linux/generic/pending-4.14/120-Fix-alloc_node_mem_map-with-ARCH_PFN_OFFSET-calcu.patch @@ -71,7 +71,7 @@ Signed-off-by: Tobias Wolf --- a/mm/page_alloc.c +++ b/mm/page_alloc.c -@@ -6170,7 +6170,7 @@ static void __ref alloc_node_mem_map(str +@@ -6147,7 +6147,7 @@ static void __ref alloc_node_mem_map(str mem_map = NODE_DATA(0)->node_mem_map; #if defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) || defined(CONFIG_FLATMEM) if (page_to_pfn(mem_map) != pgdat->node_start_pfn) diff --git a/target/linux/generic/pending-4.14/160-0001-mtd-partitions-add-of_match_table-parser-matching-fo.patch b/target/linux/generic/pending-4.14/160-0001-mtd-partitions-add-of_match_table-parser-matching-fo.patch new file mode 100644 index 000000000..3334203d8 --- /dev/null +++ b/target/linux/generic/pending-4.14/160-0001-mtd-partitions-add-of_match_table-parser-matching-fo.patch @@ -0,0 +1,194 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 30 Jan 2018 11:55:16 +0100 +Subject: [PATCH V10 1/3] mtd: partitions: add of_match_table parser matching + for the "ofpart" type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In order to properly support compatibility strings as described in the +bindings/mtd/partition.txt "ofpart" type should be treated as an +indication for looking into OF. MTD should check "compatible" property +and search for a matching parser rather than blindly trying the one +supporting "fixed-partitions". + +It also means that existing "fixed-partitions" parser should get renamed +to use a more meaningful name. + +This commit achievies that aim by introducing a new mtd_part_of_parse(). +It works by looking for a matching parser for every string in the +"compatibility" property (starting with the most specific one). + +Please note that driver-specified parsers still take a precedence. It's +assumed that driver providing a parser type has a good reason for that +(e.g. having platform data with device-specific info). Also doing +otherwise could break existing setups. The same applies to using default +parsers (including "cmdlinepart") as some overwrite DT data with cmdline +argument. + +Partition parsers can now provide an of_match_table to enable +flash<-->parser matching via device tree as documented in the +mtd/partition.txt. + +This support is currently limited to built-in parsers as it uses +request_module() and friends. This should be sufficient for most cases +though as compiling parsers as modules isn't a common choice. + +Signed-off-by: Brian Norris +Signed-off-by: RafaÅ‚ MiÅ‚ecki +Tested-by: Peter Rosin +--- + +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + #include "mtdcore.h" + +@@ -894,6 +895,92 @@ static int mtd_part_do_parse(struct mtd_ + } + + /** ++ * mtd_part_get_compatible_parser - find MTD parser by a compatible string ++ * ++ * @compat: compatible string describing partitions in a device tree ++ * ++ * MTD parsers can specify supported partitions by providing a table of ++ * compatibility strings. This function finds a parser that advertises support ++ * for a passed value of "compatible". ++ */ ++static struct mtd_part_parser *mtd_part_get_compatible_parser(const char *compat) ++{ ++ struct mtd_part_parser *p, *ret = NULL; ++ ++ spin_lock(&part_parser_lock); ++ ++ list_for_each_entry(p, &part_parsers, list) { ++ const struct of_device_id *matches; ++ ++ matches = p->of_match_table; ++ if (!matches) ++ continue; ++ ++ for (; matches->compatible[0]; matches++) { ++ if (!strcmp(matches->compatible, compat) && ++ try_module_get(p->owner)) { ++ ret = p; ++ break; ++ } ++ } ++ ++ if (ret) ++ break; ++ } ++ ++ spin_unlock(&part_parser_lock); ++ ++ return ret; ++} ++ ++static int mtd_part_of_parse(struct mtd_info *master, ++ struct mtd_partitions *pparts) ++{ ++ struct mtd_part_parser *parser; ++ struct device_node *np; ++ struct property *prop; ++ const char *compat; ++ const char *fixed = "ofpart"; ++ int ret, err = 0; ++ ++ np = of_get_child_by_name(mtd_get_of_node(master), "partitions"); ++ of_property_for_each_string(np, "compatible", prop, compat) { ++ parser = mtd_part_get_compatible_parser(compat); ++ if (!parser) ++ continue; ++ ret = mtd_part_do_parse(parser, master, pparts, NULL); ++ if (ret > 0) { ++ of_node_put(np); ++ return ret; ++ } ++ mtd_part_parser_put(parser); ++ if (ret < 0 && !err) ++ err = ret; ++ } ++ of_node_put(np); ++ ++ /* ++ * For backward compatibility we have to try the "ofpart" ++ * parser. It supports old DT format with partitions specified as a ++ * direct subnodes of a flash device DT node without any compatibility ++ * specified we could match. ++ */ ++ parser = mtd_part_parser_get(fixed); ++ if (!parser && !request_module("%s", fixed)) ++ parser = mtd_part_parser_get(fixed); ++ if (parser) { ++ ret = mtd_part_do_parse(parser, master, pparts, NULL); ++ if (ret > 0) ++ return ret; ++ mtd_part_parser_put(parser); ++ if (ret < 0 && !err) ++ err = ret; ++ } ++ ++ return err; ++} ++ ++/** + * parse_mtd_partitions - parse MTD partitions + * @master: the master partition (describes whole MTD device) + * @types: names of partition parsers to try or %NULL +@@ -925,19 +1012,30 @@ int parse_mtd_partitions(struct mtd_info + types = default_mtd_part_types; + + for ( ; *types; types++) { +- pr_debug("%s: parsing partitions %s\n", master->name, *types); +- parser = mtd_part_parser_get(*types); +- if (!parser && !request_module("%s", *types)) ++ /* ++ * ofpart is a special type that means OF partitioning info ++ * should be used. It requires a bit different logic so it is ++ * handled in a separated function. ++ */ ++ if (!strcmp(*types, "ofpart")) { ++ ret = mtd_part_of_parse(master, pparts); ++ } else { ++ pr_debug("%s: parsing partitions %s\n", master->name, ++ *types); + parser = mtd_part_parser_get(*types); +- pr_debug("%s: got parser %s\n", master->name, +- parser ? parser->name : NULL); +- if (!parser) +- continue; +- ret = mtd_part_do_parse(parser, master, pparts, data); ++ if (!parser && !request_module("%s", *types)) ++ parser = mtd_part_parser_get(*types); ++ pr_debug("%s: got parser %s\n", master->name, ++ parser ? parser->name : NULL); ++ if (!parser) ++ continue; ++ ret = mtd_part_do_parse(parser, master, pparts, data); ++ if (ret <= 0) ++ mtd_part_parser_put(parser); ++ } + /* Found partitions! */ + if (ret > 0) + return 0; +- mtd_part_parser_put(parser); + /* + * Stash the first error we see; only report it if no parser + * succeeds +--- a/include/linux/mtd/partitions.h ++++ b/include/linux/mtd/partitions.h +@@ -77,6 +77,7 @@ struct mtd_part_parser { + struct list_head list; + struct module *owner; + const char *name; ++ const struct of_device_id *of_match_table; + int (*parse_fn)(struct mtd_info *, const struct mtd_partition **, + struct mtd_part_parser_data *); + void (*cleanup)(const struct mtd_partition *pparts, int nr_parts); diff --git a/target/linux/generic/pending-4.14/160-0002-mtd-rename-ofpart-parser-to-fixed-partitions-as-it-f.patch b/target/linux/generic/pending-4.14/160-0002-mtd-rename-ofpart-parser-to-fixed-partitions-as-it-f.patch new file mode 100644 index 000000000..c38065563 --- /dev/null +++ b/target/linux/generic/pending-4.14/160-0002-mtd-rename-ofpart-parser-to-fixed-partitions-as-it-f.patch @@ -0,0 +1,68 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 30 Jan 2018 12:09:58 +0100 +Subject: [PATCH V10 2/3] mtd: rename "ofpart" parser to "fixed-partitions" as + it fits it better +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Type "ofpart" means that OF should be used to get partitioning info and +this driver supports "fixed-partitions" binding only. Renaming it should +lead to less confusion especially when parsers for new compatibility +strings start to appear. + +Signed-off-by: RafaÅ‚ MiÅ‚ecki +--- + +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -940,7 +940,7 @@ static int mtd_part_of_parse(struct mtd_ + struct device_node *np; + struct property *prop; + const char *compat; +- const char *fixed = "ofpart"; ++ const char *fixed = "fixed-partitions"; + int ret, err = 0; + + np = of_get_child_by_name(mtd_get_of_node(master), "partitions"); +@@ -960,7 +960,7 @@ static int mtd_part_of_parse(struct mtd_ + of_node_put(np); + + /* +- * For backward compatibility we have to try the "ofpart" ++ * For backward compatibility we have to try the "fixed-partitions" + * parser. It supports old DT format with partitions specified as a + * direct subnodes of a flash device DT node without any compatibility + * specified we could match. +--- a/drivers/mtd/ofpart.c ++++ b/drivers/mtd/ofpart.c +@@ -25,9 +25,9 @@ static bool node_has_compatible(struct d + return of_get_property(pp, "compatible", NULL); + } + +-static int parse_ofpart_partitions(struct mtd_info *master, +- const struct mtd_partition **pparts, +- struct mtd_part_parser_data *data) ++static int parse_fixed_partitions(struct mtd_info *master, ++ const struct mtd_partition **pparts, ++ struct mtd_part_parser_data *data) + { + struct mtd_partition *parts; + struct device_node *mtd_node; +@@ -141,8 +141,8 @@ ofpart_none: + } + + static struct mtd_part_parser ofpart_parser = { +- .parse_fn = parse_ofpart_partitions, +- .name = "ofpart", ++ .parse_fn = parse_fixed_partitions, ++ .name = "fixed-partitions", + }; + + static int parse_ofoldpart_partitions(struct mtd_info *master, +@@ -229,4 +229,5 @@ MODULE_AUTHOR("Vitaly Wool, David Gibson + * with the same name. Since we provide the ofoldpart parser, we should have + * the corresponding alias. + */ ++MODULE_ALIAS("fixed-partitions"); + MODULE_ALIAS("ofoldpart"); diff --git a/target/linux/generic/backport-4.14/041-v4.16-0002-mtd-ofpart-add-of_match_table-with-fixed-partitions.patch b/target/linux/generic/pending-4.14/160-0003-mtd-ofpart-add-of_match_table-with-fixed-partitions.patch similarity index 77% rename from target/linux/generic/backport-4.14/041-v4.16-0002-mtd-ofpart-add-of_match_table-with-fixed-partitions.patch rename to target/linux/generic/pending-4.14/160-0003-mtd-ofpart-add-of_match_table-with-fixed-partitions.patch index 2092cc28f..08f048f42 100644 --- a/target/linux/generic/backport-4.14/041-v4.16-0002-mtd-ofpart-add-of_match_table-with-fixed-partitions.patch +++ b/target/linux/generic/pending-4.14/160-0003-mtd-ofpart-add-of_match_table-with-fixed-partitions.patch @@ -1,7 +1,7 @@ -From 4ac9222778478a00c7fc9d347b7ed1e0e595120d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 4 Jan 2018 08:05:34 +0100 -Subject: [PATCH] mtd: ofpart: add of_match_table with "fixed-partitions" +Subject: [PATCH V10 3/3] mtd: ofpart: add of_match_table with + "fixed-partitions" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -17,10 +17,7 @@ This matches existing bindings documentation. Signed-off-by: RafaÅ‚ MiÅ‚ecki Reviewed-by: Brian Norris Tested-by: Brian Norris -Signed-off-by: Boris Brezillon --- - drivers/mtd/ofpart.c | 7 +++++++ - 1 file changed, 7 insertions(+) --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c @@ -35,8 +32,8 @@ Signed-off-by: Boris Brezillon +MODULE_DEVICE_TABLE(of, parse_ofpart_match_table); + static struct mtd_part_parser ofpart_parser = { - .parse_fn = parse_ofpart_partitions, - .name = "ofpart", + .parse_fn = parse_fixed_partitions, + .name = "fixed-partitions", + .of_match_table = parse_ofpart_match_table, }; diff --git a/target/linux/generic/pending-4.14/160-mtd-part-add-generic-parsing-of-linux-part-probe.patch b/target/linux/generic/pending-4.14/161-mtd-part-add-generic-parsing-of-linux-part-probe.patch similarity index 93% rename from target/linux/generic/pending-4.14/160-mtd-part-add-generic-parsing-of-linux-part-probe.patch rename to target/linux/generic/pending-4.14/161-mtd-part-add-generic-parsing-of-linux-part-probe.patch index e57214ba0..6379ff33f 100644 --- a/target/linux/generic/pending-4.14/160-mtd-part-add-generic-parsing-of-linux-part-probe.patch +++ b/target/linux/generic/pending-4.14/161-mtd-part-add-generic-parsing-of-linux-part-probe.patch @@ -137,9 +137,9 @@ Signed-off-by: Hauke Mehrtens * Do not forget to update 'parse_mtd_partitions()' kerneldoc comment if you * are changing this array! */ -@@ -963,6 +990,13 @@ int parse_mtd_partitions(struct mtd_info - struct property *prop; - const char *compat; +@@ -1007,6 +1034,13 @@ int parse_mtd_partitions(struct mtd_info + { + struct mtd_part_parser *parser; int ret, err = 0; + const char *const *types_of = NULL; + @@ -149,9 +149,9 @@ Signed-off-by: Hauke Mehrtens + types = types_of; + } - np = of_get_child_by_name(mtd_get_of_node(master), "partitions"); - of_property_for_each_string(np, "compatible", prop, compat) { -@@ -1004,6 +1038,7 @@ int parse_mtd_partitions(struct mtd_info + if (!types) + types = default_mtd_part_types; +@@ -1043,6 +1077,7 @@ int parse_mtd_partitions(struct mtd_info if (ret < 0 && !err) err = ret; } diff --git a/target/linux/generic/pending-4.14/180-net-phy-at803x-add-support-for-AT8032.patch b/target/linux/generic/pending-4.14/180-net-phy-at803x-add-support-for-AT8032.patch index 3b1a41a23..86a03f225 100644 --- a/target/linux/generic/pending-4.14/180-net-phy-at803x-add-support-for-AT8032.patch +++ b/target/linux/generic/pending-4.14/180-net-phy-at803x-add-support-for-AT8032.patch @@ -16,7 +16,7 @@ Signed-off-by: Felix Fietkau #define ATH8035_PHY_ID 0x004dd072 #define AT803X_PHY_ID_MASK 0xffffffef -@@ -260,7 +261,8 @@ static int at803x_probe(struct phy_devic +@@ -256,7 +257,8 @@ static int at803x_probe(struct phy_devic if (!priv) return -ENOMEM; @@ -26,7 +26,7 @@ Signed-off-by: Felix Fietkau goto does_not_require_reset_workaround; gpiod_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); -@@ -336,7 +338,7 @@ static void at803x_link_change_notify(st +@@ -332,7 +334,7 @@ static void at803x_link_change_notify(st struct at803x_priv *priv = phydev->priv; /* @@ -35,7 +35,7 @@ Signed-off-by: Felix Fietkau * signalled. This is necessary to circumvent a hardware bug that * occurs when the cable is unplugged while TX packets are pending * in the FIFO. In such cases, the FIFO enters an error mode it -@@ -448,6 +450,24 @@ static struct phy_driver at803x_driver[] +@@ -444,6 +446,24 @@ static struct phy_driver at803x_driver[] .aneg_done = at803x_aneg_done, .ack_interrupt = &at803x_ack_interrupt, .config_intr = &at803x_config_intr, @@ -60,7 +60,7 @@ Signed-off-by: Felix Fietkau } }; module_phy_driver(at803x_driver); -@@ -455,6 +475,7 @@ module_phy_driver(at803x_driver); +@@ -451,6 +471,7 @@ module_phy_driver(at803x_driver); static struct mdio_device_id __maybe_unused atheros_tbl[] = { { ATH8030_PHY_ID, AT803X_PHY_ID_MASK }, { ATH8031_PHY_ID, AT803X_PHY_ID_MASK }, diff --git a/target/linux/generic/pending-4.14/181-net-usb-add-lte-modem-wistron-neweb-d18q1.patch b/target/linux/generic/pending-4.14/181-net-usb-add-lte-modem-wistron-neweb-d18q1.patch new file mode 100644 index 000000000..4bc7d29b5 --- /dev/null +++ b/target/linux/generic/pending-4.14/181-net-usb-add-lte-modem-wistron-neweb-d18q1.patch @@ -0,0 +1,61 @@ +From d4c4bc11353f3bea6754f7d21e3612c9f32d1d64 Mon Sep 17 00:00:00 2001 +From: Giuseppe Lippolis +Date: Mon, 26 Mar 2018 16:34:39 +0200 +Subject: [PATCH] net-usb: add qmi_wwan if on lte modem wistron neweb d18q1 + +This modem is embedded on dlink dwr-921 router. + The oem configuration states: + + T: Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 0 + D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 + P: Vendor=1435 ProdID=0918 Rev= 2.32 + S: Manufacturer=Android + S: Product=Android + S: SerialNumber=0123456789ABCDEF + C:* #Ifs= 7 Cfg#= 1 Atr=80 MxPwr=500mA + I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option + E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms + E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms + I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) + E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms + E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms + I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option + E: Ad=84(I) Atr=03(Int.) MxPS= 64 Ivl=32ms + E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms + E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms + I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan + E: Ad=86(I) Atr=03(Int.) MxPS= 64 Ivl=32ms + E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms + E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms + I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan + E: Ad=88(I) Atr=03(Int.) MxPS= 64 Ivl=32ms + E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms + E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms + I:* If#= 5 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan + E: Ad=8a(I) Atr=03(Int.) MxPS= 64 Ivl=32ms + E: Ad=89(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms + E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms + I:* If#= 6 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=(none) + E: Ad=8b(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms + E: Ad=07(O) Atr=02(Bulk) MxPS= 512 Ivl=125us + +Tested on openwrt distribution + +Signed-off-by: Giuseppe Lippolis +Signed-off-by: David S. Miller +--- + drivers/net/usb/qmi_wwan.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -1104,6 +1104,9 @@ static const struct usb_device_id produc + {QMI_FIXED_INTF(0x0846, 0x68a2, 8)}, + {QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */ + {QMI_FIXED_INTF(0x12d1, 0x14ac, 1)}, /* Huawei E1820 */ ++ {QMI_FIXED_INTF(0x1435, 0xd181, 3)}, /* Wistron NeWeb D18Q1 */ ++ {QMI_FIXED_INTF(0x1435, 0xd181, 4)}, /* Wistron NeWeb D18Q1 */ ++ {QMI_FIXED_INTF(0x1435, 0xd181, 5)}, /* Wistron NeWeb D18Q1 */ + {QMI_FIXED_INTF(0x16d8, 0x6003, 0)}, /* CMOTech 6003 */ + {QMI_FIXED_INTF(0x16d8, 0x6007, 0)}, /* CMOTech CHE-628S */ + {QMI_FIXED_INTF(0x16d8, 0x6008, 0)}, /* CMOTech CMU-301 */ diff --git a/target/linux/generic/pending-4.14/182-net-qmi_wwan-add-BroadMobi-BM806U-2020-2033.patch b/target/linux/generic/pending-4.14/182-net-qmi_wwan-add-BroadMobi-BM806U-2020-2033.patch new file mode 100644 index 000000000..3b849466c --- /dev/null +++ b/target/linux/generic/pending-4.14/182-net-qmi_wwan-add-BroadMobi-BM806U-2020-2033.patch @@ -0,0 +1,28 @@ +From 743989254ea9f132517806d8893ca9b6cf9dc86b Mon Sep 17 00:00:00 2001 +From: Pawel Dembicki +Date: Sat, 24 Mar 2018 22:08:14 +0100 +Subject: [PATCH] net: qmi_wwan: add BroadMobi BM806U 2020:2033 + +BroadMobi BM806U is an Qualcomm MDM9225 based 3G/4G modem. +Tested hardware BM806U is mounted on D-Link DWR-921-C3 router. +The USB id is added to qmi_wwan.c to allow QMI communication with +the BM806U. + +Tested on 4.14 kernel and OpenWRT. + +Signed-off-by: Pawel Dembicki +Signed-off-by: David S. Miller +--- + drivers/net/usb/qmi_wwan.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -1183,6 +1183,7 @@ static const struct usb_device_id produc + {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */ + {QMI_FIXED_INTF(0x2001, 0x7e19, 4)}, /* D-Link DWM-221 B1 */ + {QMI_FIXED_INTF(0x2001, 0x7e35, 4)}, /* D-Link DWM-222 */ ++ {QMI_FIXED_INTF(0x2020, 0x2033, 4)}, /* BroadMobi BM806U */ + {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)}, /* Sierra Wireless MC7700 */ + {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */ + {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ diff --git a/target/linux/generic/pending-4.14/201-extra_optimization.patch b/target/linux/generic/pending-4.14/201-extra_optimization.patch index 81f7e2664..3c3353c7d 100644 --- a/target/linux/generic/pending-4.14/201-extra_optimization.patch +++ b/target/linux/generic/pending-4.14/201-extra_optimization.patch @@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau --- a/Makefile +++ b/Makefile -@@ -638,12 +638,12 @@ KBUILD_CFLAGS += $(call cc-disable-warni +@@ -650,12 +650,12 @@ KBUILD_CFLAGS += $(call cc-disable-warni ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE KBUILD_CFLAGS += $(call cc-option,-Oz,-Os) diff --git a/target/linux/generic/pending-4.14/270-uapi-kernel.h-glibc-specific-inclusion-of-sysinfo.h.patch b/target/linux/generic/pending-4.14/270-uapi-kernel.h-glibc-specific-inclusion-of-sysinfo.h.patch deleted file mode 100644 index 9ec8daf88..000000000 --- a/target/linux/generic/pending-4.14/270-uapi-kernel.h-glibc-specific-inclusion-of-sysinfo.h.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: David Heidelberger -Subject: uapi/kernel.h: glibc specific inclusion of sysinfo.h - -including sysinfo.h from kernel.h makes no sense whatsoever, -but removing it breaks glibc's userspace header, -which includes kernel.h instead of sysinfo.h from their sys/sysinfo.h. -this seems to be a historical mistake. -on musl, including any header that uses kernel.h directly or indirectly -plus sys/sysinfo.h will produce a compile error due to redefinition of -struct sysinfo from sys/sysinfo.h. -so for now, only include it on glibc or when including from kernel -in order not to break their headers. - -Signed-off-by: John Spencer -Signed-off-by: David Heidelberger -Signed-off-by: Jonas Gorski ---- - include/uapi/linux/kernel.h | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/include/uapi/linux/kernel.h -+++ b/include/uapi/linux/kernel.h -@@ -2,7 +2,9 @@ - #ifndef _UAPI_LINUX_KERNEL_H - #define _UAPI_LINUX_KERNEL_H - -+#if defined(__KERNEL__) || defined( __GLIBC__) - #include -+#endif - - /* - * 'kernel.h' contains some often-used function prototypes etc diff --git a/target/linux/generic/pending-4.14/271-uapi-libc-compat.h-do-not-rely-on-__GLIBC__.patch b/target/linux/generic/pending-4.14/271-uapi-libc-compat.h-do-not-rely-on-__GLIBC__.patch deleted file mode 100644 index 9ae148da4..000000000 --- a/target/linux/generic/pending-4.14/271-uapi-libc-compat.h-do-not-rely-on-__GLIBC__.patch +++ /dev/null @@ -1,105 +0,0 @@ -From: David Heidelberger -Subject: uapi/libc-compat.h: do not rely on __GLIBC__ - -Musl provides the same structs as glibc, but does not provide a define to -allow its detection. Since the absence of __GLIBC__ also can mean that it -is included from the kernel, change the __GLIBC__ detection to -!__KERNEL__, which should always be true when included from userspace. - -Signed-off-by: John Spencer -Tested-by: David Heidelberger -Signed-off-by: Jonas Gorski ---- - include/uapi/linux/libc-compat.h | 18 +++++++++--------- - 1 file changed, 9 insertions(+), 9 deletions(-) - ---- a/include/uapi/linux/libc-compat.h -+++ b/include/uapi/linux/libc-compat.h -@@ -49,13 +49,13 @@ - #ifndef _UAPI_LIBC_COMPAT_H - #define _UAPI_LIBC_COMPAT_H - --/* We have included glibc headers... */ --#if defined(__GLIBC__) -+/* We have included libc headers... */ -+#if !defined(__KERNEL__) - --/* Coordinate with glibc net/if.h header. */ --#if defined(_NET_IF_H) && defined(__USE_MISC) -+/* Coordinate with libc net/if.h header. */ -+#if defined(_NET_IF_H) && (!defined(__GLIBC__) || defined(__USE_MISC)) - --/* GLIBC headers included first so don't define anything -+/* LIBC headers included first so don't define anything - * that would already be defined. */ - - #define __UAPI_DEF_IF_IFCONF 0 -@@ -66,7 +66,11 @@ - #define __UAPI_DEF_IF_NET_DEVICE_FLAGS 0 - /* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */ - #ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO -+#ifdef __GLIBC__ - #define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1 -+#else -+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 0 -+#endif - #endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */ - - #else /* _NET_IF_H */ -@@ -86,10 +90,10 @@ - - #endif /* _NET_IF_H */ - --/* Coordinate with glibc netinet/in.h header. */ -+/* Coordinate with libc netinet/in.h header. */ - #if defined(_NETINET_IN_H) - --/* GLIBC headers included first so don't define anything -+/* LIBC headers included first so don't define anything - * that would already be defined. */ - #define __UAPI_DEF_IN_ADDR 0 - #define __UAPI_DEF_IN_IPPROTO 0 -@@ -103,7 +107,7 @@ - * if the glibc code didn't define them. This guard matches - * the guard in glibc/inet/netinet/in.h which defines the - * additional in6_addr macros e.g. s6_addr16, and s6_addr32. */ --#if defined(__USE_MISC) || defined (__USE_GNU) -+#if !defined(__GLIBC__) || defined(__USE_MISC) || defined (__USE_GNU) - #define __UAPI_DEF_IN6_ADDR_ALT 0 - #else - #define __UAPI_DEF_IN6_ADDR_ALT 1 -@@ -118,7 +122,7 @@ - #else - - /* Linux headers included first, and we must define everything -- * we need. The expectation is that glibc will check the -+ * we need. The expectation is that the libc will check the - * __UAPI_DEF_* defines and adjust appropriately. */ - #define __UAPI_DEF_IN_ADDR 1 - #define __UAPI_DEF_IN_IPPROTO 1 -@@ -128,7 +132,7 @@ - #define __UAPI_DEF_IN_CLASS 1 - - #define __UAPI_DEF_IN6_ADDR 1 --/* We unconditionally define the in6_addr macros and glibc must -+/* We unconditionally define the in6_addr macros and the libc must - * coordinate. */ - #define __UAPI_DEF_IN6_ADDR_ALT 1 - #define __UAPI_DEF_SOCKADDR_IN6 1 -@@ -169,7 +173,7 @@ - /* If we did not see any headers from any supported C libraries, - * or we are being included in the kernel, then define everything - * that we need. */ --#else /* !defined(__GLIBC__) */ -+#else /* defined(__KERNEL__) */ - - /* Definitions for if.h */ - #define __UAPI_DEF_IF_IFCONF 1 -@@ -209,6 +213,6 @@ - /* Definitions for xattr.h */ - #define __UAPI_DEF_XATTR 1 - --#endif /* __GLIBC__ */ -+#endif /* __KERNEL__ */ - - #endif /* _UAPI_LIBC_COMPAT_H */ diff --git a/target/linux/generic/pending-4.14/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch b/target/linux/generic/pending-4.14/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch index 5cdcc2b24..86aed4f0f 100644 --- a/target/linux/generic/pending-4.14/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch +++ b/target/linux/generic/pending-4.14/330-MIPS-kexec-Accept-command-line-parameters-from-users.patch @@ -24,7 +24,7 @@ Signed-off-by: Yousong Zhou - -extern unsigned long kexec_start_address; -extern unsigned long kexec_indirection_page; -+#include ++#include +#include "machine_kexec.h" int (*_machine_kexec_prepare)(struct kimage *) = NULL; diff --git a/target/linux/generic/pending-4.14/401-mtd-add-support-for-different-partition-parser-types.patch b/target/linux/generic/pending-4.14/401-mtd-add-support-for-different-partition-parser-types.patch index 7481225be..182d8d474 100644 --- a/target/linux/generic/pending-4.14/401-mtd-add-support-for-different-partition-parser-types.patch +++ b/target/linux/generic/pending-4.14/401-mtd-add-support-for-different-partition-parser-types.patch @@ -9,7 +9,7 @@ Signed-off-by: Gabor Juhos --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c -@@ -1093,6 +1093,62 @@ void mtd_part_parser_cleanup(struct mtd_ +@@ -1132,6 +1132,62 @@ void mtd_part_parser_cleanup(struct mtd_ } } diff --git a/target/linux/generic/pending-4.14/404-mtd-add-more-helper-functions.patch b/target/linux/generic/pending-4.14/404-mtd-add-more-helper-functions.patch index a4fb15586..9b2fcac93 100644 --- a/target/linux/generic/pending-4.14/404-mtd-add-more-helper-functions.patch +++ b/target/linux/generic/pending-4.14/404-mtd-add-more-helper-functions.patch @@ -29,7 +29,7 @@ Signed-off-by: Gabor Juhos #ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME #define SPLIT_FIRMWARE_NAME CONFIG_MTD_SPLIT_FIRMWARE_NAME #else -@@ -1203,6 +1214,24 @@ int mtd_is_partition(const struct mtd_in +@@ -1242,6 +1253,24 @@ int mtd_is_partition(const struct mtd_in } EXPORT_SYMBOL_GPL(mtd_is_partition); diff --git a/target/linux/generic/pending-4.14/450-mtd-m25p80-allow-fallback-from-spi_flash_read-to-reg.patch b/target/linux/generic/pending-4.14/450-mtd-m25p80-allow-fallback-from-spi_flash_read-to-reg.patch new file mode 100644 index 000000000..accd63df5 --- /dev/null +++ b/target/linux/generic/pending-4.14/450-mtd-m25p80-allow-fallback-from-spi_flash_read-to-reg.patch @@ -0,0 +1,36 @@ +From: Felix Fietkau +Date: Fri, 23 Feb 2018 17:12:16 +0100 +Subject: [PATCH] mtd: m25p80: allow fallback from spi_flash_read to regular + SPI transfer + +Some flash controllers, e.g. on the ath79 platform can support a fast +flash read via memory mapping, but only if the flash chip is in +3-byte address mode. + +Since spi_flash_read_supported does not have access to the same data as +spi_flash_read, the driver can't detect an unsupported call until m25p80 +has decided to use spi_flash_read. + +Allow the driver to indicate a fallback to a regular SPI transfer by +returning -EOPNOTSUPP + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/mtd/devices/m25p80.c ++++ b/drivers/mtd/devices/m25p80.c +@@ -170,9 +170,11 @@ static ssize_t m25p80_read(struct spi_no + msg.data_nbits = data_nbits; + + ret = spi_flash_read(spi, &msg); +- if (ret < 0) +- return ret; +- return msg.retlen; ++ if (ret != -EOPNOTSUPP) { ++ if (ret < 0) ++ return ret; ++ return msg.retlen; ++ } + } + + spi_message_init(&m); diff --git a/target/linux/generic/pending-4.14/450-mtd-spi-nor-allow-NOR-driver-to-write-fewer-bytes-th.patch b/target/linux/generic/pending-4.14/450-mtd-spi-nor-allow-NOR-driver-to-write-fewer-bytes-th.patch new file mode 100644 index 000000000..50ed2be3d --- /dev/null +++ b/target/linux/generic/pending-4.14/450-mtd-spi-nor-allow-NOR-driver-to-write-fewer-bytes-th.patch @@ -0,0 +1,36 @@ +From: Felix Fietkau +Date: Thu, 22 Feb 2018 11:11:57 +0100 +Subject: [PATCH] mtd: spi-nor: allow NOR driver to write fewer bytes than + requested + +The write size can be constrained by the maximum message/transfer size +of the SPI controller. Only check for ret = 0 to avoid an infinite loop. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -1371,7 +1371,7 @@ static int spi_nor_write(struct mtd_info + + write_enable(nor); + ret = nor->write(nor, addr, page_remain, buf + i); +- if (ret < 0) ++ if (ret <= 0) + goto write_err; + written = ret; + +@@ -1380,13 +1380,6 @@ static int spi_nor_write(struct mtd_info + goto write_err; + *retlen += written; + i += written; +- if (written != page_remain) { +- dev_err(nor->dev, +- "While writing %zu bytes written %zd bytes\n", +- page_remain, written); +- ret = -EIO; +- goto write_err; +- } + } + + write_err: diff --git a/target/linux/generic/pending-4.14/465-m25p80-mx-disable-software-protection.patch b/target/linux/generic/pending-4.14/465-m25p80-mx-disable-software-protection.patch index 89d38ec30..dc71e9d54 100644 --- a/target/linux/generic/pending-4.14/465-m25p80-mx-disable-software-protection.patch +++ b/target/linux/generic/pending-4.14/465-m25p80-mx-disable-software-protection.patch @@ -8,7 +8,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -2715,6 +2715,7 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -2708,6 +2708,7 @@ int spi_nor_scan(struct spi_nor *nor, co if (JEDEC_MFR(info) == SNOR_MFR_ATMEL || JEDEC_MFR(info) == SNOR_MFR_INTEL || diff --git a/target/linux/generic/pending-4.14/466-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch b/target/linux/generic/pending-4.14/466-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch index b7877297a..fc5cf6232 100644 --- a/target/linux/generic/pending-4.14/466-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch +++ b/target/linux/generic/pending-4.14/466-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch @@ -17,7 +17,7 @@ Signed-off-by: Matthias Schiffer --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -2717,6 +2717,7 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -2710,6 +2710,7 @@ int spi_nor_scan(struct spi_nor *nor, co JEDEC_MFR(info) == SNOR_MFR_INTEL || JEDEC_MFR(info) == SNOR_MFR_MACRONIX || JEDEC_MFR(info) == SNOR_MFR_SST || @@ -25,7 +25,7 @@ Signed-off-by: Matthias Schiffer info->flags & SPI_NOR_HAS_LOCK) { write_enable(nor); write_sr(nor, 0); -@@ -2735,7 +2736,8 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -2728,7 +2729,8 @@ int spi_nor_scan(struct spi_nor *nor, co /* NOR protection support for STmicro/Micron chips and similar */ if (JEDEC_MFR(info) == SNOR_MFR_MICRON || diff --git a/target/linux/generic/pending-4.14/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch b/target/linux/generic/pending-4.14/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch index 10db289cc..88775041c 100644 --- a/target/linux/generic/pending-4.14/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch +++ b/target/linux/generic/pending-4.14/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch @@ -39,7 +39,7 @@ Signed-off-by: Felix Fietkau depends on ARCH_AT91 || (ARM && COMPILE_TEST) --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -2562,10 +2562,12 @@ static int spi_nor_select_erase(struct s +@@ -2555,10 +2555,12 @@ static int spi_nor_select_erase(struct s #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS /* prefer "small sector" erase if possible */ diff --git a/target/linux/generic/pending-4.14/478-mtd-spi-nor-Add-support-for-XM25QH64A-and-XM25QH128A.patch b/target/linux/generic/pending-4.14/478-mtd-spi-nor-Add-support-for-XM25QH64A-and-XM25QH128A.patch new file mode 100644 index 000000000..b7361d2ab --- /dev/null +++ b/target/linux/generic/pending-4.14/478-mtd-spi-nor-Add-support-for-XM25QH64A-and-XM25QH128A.patch @@ -0,0 +1,30 @@ +From b02f3405c935a28200db26b63e42086057565cf4 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sat, 31 Mar 2018 20:09:54 +0200 +Subject: [PATCH] mtd: spi-nor: Add support for XM25QH64A and XM25QH128A + +These devices are produced by Wuhan Xinxin Semiconductor Manufacturing +Corp. (XMC) and found on some routers from Chinese manufactures. + +The data sheets can be found here: +http://www.xmcwh.com/Uploads/2018-03-01/5a9799e4cb355.pdf +http://www.xmcwh.com/Uploads/2018-02-05/5a77e6dbe968b.pdf + +Signed-off-by: Hauke Mehrtens +--- + drivers/mtd/spi-nor/spi-nor.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -1181,6 +1181,10 @@ static const struct flash_info spi_nor_i + { "3S400AN", S3AN_INFO(0x1f2400, 256, 264) }, + { "3S700AN", S3AN_INFO(0x1f2500, 512, 264) }, + { "3S1400AN", S3AN_INFO(0x1f2600, 512, 528) }, ++ ++ /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */ ++ { "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { }, + }; + diff --git a/target/linux/generic/pending-4.14/491-ubi-auto-create-ubiblock-device-for-rootfs.patch b/target/linux/generic/pending-4.14/491-ubi-auto-create-ubiblock-device-for-rootfs.patch index f8dc1bcb2..cb2d52561 100644 --- a/target/linux/generic/pending-4.14/491-ubi-auto-create-ubiblock-device-for-rootfs.patch +++ b/target/linux/generic/pending-4.14/491-ubi-auto-create-ubiblock-device-for-rootfs.patch @@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c -@@ -625,6 +625,44 @@ static void __init ubiblock_create_from_ +@@ -633,6 +633,44 @@ static void __init ubiblock_create_from_ } } @@ -53,7 +53,7 @@ Signed-off-by: Daniel Golle static void ubiblock_remove_all(void) { struct ubiblock *next; -@@ -655,6 +693,10 @@ int __init ubiblock_init(void) +@@ -665,6 +703,10 @@ int __init ubiblock_init(void) */ ubiblock_create_from_param(); diff --git a/target/linux/generic/pending-4.14/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch b/target/linux/generic/pending-4.14/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch index 69a35c25e..3c82a064e 100644 --- a/target/linux/generic/pending-4.14/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch +++ b/target/linux/generic/pending-4.14/492-try-auto-mounting-ubi0-rootfs-in-init-do_mounts.c.patch @@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle --- a/init/do_mounts.c +++ b/init/do_mounts.c -@@ -438,7 +438,28 @@ retry: +@@ -437,7 +437,28 @@ retry: out: put_page(page); } @@ -38,7 +38,7 @@ Signed-off-by: Daniel Golle #ifdef CONFIG_ROOT_NFS #define NFSROOT_TIMEOUT_MIN 5 -@@ -532,6 +553,10 @@ void __init mount_root(void) +@@ -531,6 +552,10 @@ void __init mount_root(void) change_floppy("root floppy"); } #endif diff --git a/target/linux/generic/pending-4.14/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch b/target/linux/generic/pending-4.14/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch index 06cd1b62a..1bb53ada7 100644 --- a/target/linux/generic/pending-4.14/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch +++ b/target/linux/generic/pending-4.14/493-ubi-set-ROOT_DEV-to-ubiblock-rootfs-if-unset.patch @@ -17,9 +17,9 @@ Signed-off-by: Daniel Golle #include "ubi-media.h" #include "ubi.h" @@ -445,6 +446,15 @@ int ubiblock_create(struct ubi_volume_in - add_disk(dev->gd); dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)", dev->ubi_num, dev->vol_id, vi->name); + mutex_unlock(&devices_mutex); + + if (!strcmp(vi->name, "rootfs") && + IS_ENABLED(CONFIG_MTD_ROOTFS_ROOT_DEV) && diff --git a/target/linux/generic/pending-4.14/553-ubifs-Add-option-to-create-UBI-FS-version-4-on-empty.patch b/target/linux/generic/pending-4.14/553-ubifs-Add-option-to-create-UBI-FS-version-4-on-empty.patch new file mode 100644 index 000000000..4b413996f --- /dev/null +++ b/target/linux/generic/pending-4.14/553-ubifs-Add-option-to-create-UBI-FS-version-4-on-empty.patch @@ -0,0 +1,63 @@ +From 93c33e6a7f3b0aef99d02252e6232a3d8b80f2d5 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sun, 21 Jan 2018 15:47:50 +0100 +Subject: ubifs: Add option to create UBI FS version 4 on empty UBI volume + +Instead of creating an ubifs file system with format version 5 by +default on empty UBI volumes add a compile option to create an older ubi +with file system format version 4 instated. This allows it to be mount +as a volume on kernel versions < 4.10, which does not support format +version 5. +We saw that some people can not access their older data when they +downgraded from kernel 4.14 to kernel 4.9 to prevent this this option +would help. + +Signed-off-by: Hauke Mehrtens +--- + fs/ubifs/Kconfig | 13 +++++++++++++ + fs/ubifs/sb.c | 6 ++++++ + 2 files changed, 19 insertions(+) + +--- a/fs/ubifs/Kconfig ++++ b/fs/ubifs/Kconfig +@@ -74,3 +74,16 @@ config UBIFS_FS_SECURITY + the extended attribute support in advance. + + If you are not using a security module, say N. ++ ++config UBIFS_FS_FORMAT4 ++ bool "Use file system format version 4 for new file systems" ++ depends on UBIFS_FS ++ help ++ Instead of creating new file systems with the new ubifs file ++ system version 5, use the old format version 4 for implicitly ++ by the driver created file systems on an empty UBI volume. This ++ makes it possible to mount these file systems also with kernel ++ versions before 4.10. The driver will still support file system ++ format version 5 for ubifs file systems created with version 5. ++ ++ If you are unsure, say N. +--- a/fs/ubifs/sb.c ++++ b/fs/ubifs/sb.c +@@ -176,7 +176,9 @@ static int create_default_filesystem(str + tmp64 = (long long)max_buds * c->leb_size; + if (big_lpt) + sup_flags |= UBIFS_FLG_BIGLPT; ++#ifndef CONFIG_UBIFS_FS_FORMAT4 + sup_flags |= UBIFS_FLG_DOUBLE_HASH; ++#endif + + sup->ch.node_type = UBIFS_SB_NODE; + sup->key_hash = UBIFS_KEY_HASH_R5; +@@ -192,7 +194,11 @@ static int create_default_filesystem(str + sup->jhead_cnt = cpu_to_le32(DEFAULT_JHEADS_CNT); + sup->fanout = cpu_to_le32(DEFAULT_FANOUT); + sup->lsave_cnt = cpu_to_le32(c->lsave_cnt); ++#ifdef CONFIG_UBIFS_FS_FORMAT4 ++ sup->fmt_version = cpu_to_le32(4); ++#else + sup->fmt_version = cpu_to_le32(UBIFS_FORMAT_VERSION); ++#endif + sup->time_gran = cpu_to_le32(DEFAULT_TIME_GRAN); + if (c->mount_opts.override_compr) + sup->default_compr = cpu_to_le16(c->mount_opts.compr_type); diff --git a/target/linux/generic/pending-4.14/600-netfilter_conntrack_flush.patch b/target/linux/generic/pending-4.14/600-netfilter_conntrack_flush.patch index f39ed62dc..10da96b7e 100644 --- a/target/linux/generic/pending-4.14/600-netfilter_conntrack_flush.patch +++ b/target/linux/generic/pending-4.14/600-netfilter_conntrack_flush.patch @@ -17,7 +17,7 @@ Signed-off-by: Felix Fietkau #include #ifdef CONFIG_SYSCTL #include -@@ -377,10 +378,66 @@ static int ct_open(struct inode *inode, +@@ -381,10 +382,66 @@ static int ct_open(struct inode *inode, sizeof(struct ct_iter_state)); } @@ -84,7 +84,7 @@ Signed-off-by: Felix Fietkau .llseek = seq_lseek, .release = seq_release_net, }; -@@ -484,7 +541,7 @@ static int nf_conntrack_standalone_init_ +@@ -488,7 +545,7 @@ static int nf_conntrack_standalone_init_ kuid_t root_uid; kgid_t root_gid; diff --git a/target/linux/generic/pending-4.14/610-netfilter_match_bypass_default_checks.patch b/target/linux/generic/pending-4.14/610-netfilter_match_bypass_default_checks.patch index 0a3c0f967..ec269b6cd 100644 --- a/target/linux/generic/pending-4.14/610-netfilter_match_bypass_default_checks.patch +++ b/target/linux/generic/pending-4.14/610-netfilter_match_bypass_default_checks.patch @@ -59,7 +59,7 @@ Signed-off-by: Felix Fietkau static bool ip_checkentry(const struct ipt_ip *ip) { -@@ -532,6 +558,8 @@ find_check_entry(struct ipt_entry *e, st +@@ -537,6 +563,8 @@ find_check_entry(struct ipt_entry *e, st struct xt_mtchk_param mtpar; struct xt_entry_match *ematch; @@ -68,7 +68,7 @@ Signed-off-by: Felix Fietkau if (!xt_percpu_counter_alloc(alloc_state, &e->counters)) return -ENOMEM; -@@ -812,6 +840,7 @@ copy_entries_to_user(unsigned int total_ +@@ -817,6 +845,7 @@ copy_entries_to_user(unsigned int total_ const struct xt_table_info *private = table->private; int ret = 0; const void *loc_cpu_entry; @@ -76,7 +76,7 @@ Signed-off-by: Felix Fietkau counters = alloc_counters(table); if (IS_ERR(counters)) -@@ -839,6 +868,14 @@ copy_entries_to_user(unsigned int total_ +@@ -844,6 +873,14 @@ copy_entries_to_user(unsigned int total_ goto free_counters; } @@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau for (i = sizeof(struct ipt_entry); i < e->target_offset; i += m->u.match_size) { -@@ -1219,12 +1256,15 @@ compat_copy_entry_to_user(struct ipt_ent +@@ -1224,12 +1261,15 @@ compat_copy_entry_to_user(struct ipt_ent compat_uint_t origsize; const struct xt_entry_match *ematch; int ret = 0; diff --git a/target/linux/generic/pending-4.14/613-netfilter_optional_tcp_window_check.patch b/target/linux/generic/pending-4.14/613-netfilter_optional_tcp_window_check.patch index 3ded90168..69c165bb4 100644 --- a/target/linux/generic/pending-4.14/613-netfilter_optional_tcp_window_check.patch +++ b/target/linux/generic/pending-4.14/613-netfilter_optional_tcp_window_check.patch @@ -18,7 +18,7 @@ Signed-off-by: Felix Fietkau /* "Be conservative in what you do, be liberal in what you accept from others." If it's non-zero, we mark only out of window RST segments as INVALID. */ -@@ -505,6 +508,9 @@ static bool tcp_in_window(const struct n +@@ -508,6 +511,9 @@ static bool tcp_in_window(const struct n s32 receiver_offset; bool res, in_recv_win; @@ -28,7 +28,7 @@ Signed-off-by: Felix Fietkau /* * Get the required data from the packet. */ -@@ -1486,6 +1492,13 @@ static struct ctl_table tcp_sysctl_table +@@ -1489,6 +1495,13 @@ static struct ctl_table tcp_sysctl_table .mode = 0644, .proc_handler = proc_dointvec, }, diff --git a/target/linux/generic/pending-4.14/620-net_sched-codel-do-not-defer-queue-length-update.patch b/target/linux/generic/pending-4.14/620-net_sched-codel-do-not-defer-queue-length-update.patch new file mode 100644 index 000000000..b3c35ee35 --- /dev/null +++ b/target/linux/generic/pending-4.14/620-net_sched-codel-do-not-defer-queue-length-update.patch @@ -0,0 +1,86 @@ +From: Konstantin Khlebnikov +Date: Mon, 21 Aug 2017 11:14:14 +0300 +Subject: [PATCH] net_sched/codel: do not defer queue length update + +When codel wants to drop last packet in ->dequeue() it cannot call +qdisc_tree_reduce_backlog() right away - it will notify parent qdisc +about zero qlen and HTB/HFSC will deactivate class. The same class will +be deactivated second time by caller of ->dequeue(). Currently codel and +fq_codel defer update. This triggers warning in HFSC when it's qlen != 0 +but there is no active classes. + +This patch update parent queue length immediately: just temporary increase +qlen around qdisc_tree_reduce_backlog() to prevent first class deactivation +if we have skb to return. + +This might open another problem in HFSC - now operation peek could fail and +deactivate parent class. + +Signed-off-by: Konstantin Khlebnikov +Link: https://bugzilla.kernel.org/show_bug.cgi?id=109581 +--- + +--- a/net/sched/sch_codel.c ++++ b/net/sched/sch_codel.c +@@ -95,11 +95,17 @@ static struct sk_buff *codel_qdisc_deque + &q->stats, qdisc_pkt_len, codel_get_enqueue_time, + drop_func, dequeue_func); + +- /* We cant call qdisc_tree_reduce_backlog() if our qlen is 0, +- * or HTB crashes. Defer it for next round. ++ /* If our qlen is 0 qdisc_tree_reduce_backlog() will deactivate ++ * parent class, dequeue in parent qdisc will do the same if we ++ * return skb. Temporary increment qlen if we have skb. + */ +- if (q->stats.drop_count && sch->q.qlen) { +- qdisc_tree_reduce_backlog(sch, q->stats.drop_count, q->stats.drop_len); ++ if (q->stats.drop_count) { ++ if (skb) ++ sch->q.qlen++; ++ qdisc_tree_reduce_backlog(sch, q->stats.drop_count, ++ q->stats.drop_len); ++ if (skb) ++ sch->q.qlen--; + q->stats.drop_count = 0; + q->stats.drop_len = 0; + } +--- a/net/sched/sch_fq_codel.c ++++ b/net/sched/sch_fq_codel.c +@@ -316,6 +316,21 @@ begin: + flow->dropped += q->cstats.drop_count - prev_drop_count; + flow->dropped += q->cstats.ecn_mark - prev_ecn_mark; + ++ /* If our qlen is 0 qdisc_tree_reduce_backlog() will deactivate ++ * parent class, dequeue in parent qdisc will do the same if we ++ * return skb. Temporary increment qlen if we have skb. ++ */ ++ if (q->cstats.drop_count) { ++ if (skb) ++ sch->q.qlen++; ++ qdisc_tree_reduce_backlog(sch, q->cstats.drop_count, ++ q->cstats.drop_len); ++ if (skb) ++ sch->q.qlen--; ++ q->cstats.drop_count = 0; ++ q->cstats.drop_len = 0; ++ } ++ + if (!skb) { + /* force a pass through old_flows to prevent starvation */ + if ((head == &q->new_flows) && !list_empty(&q->old_flows)) +@@ -326,15 +341,6 @@ begin: + } + qdisc_bstats_update(sch, skb); + flow->deficit -= qdisc_pkt_len(skb); +- /* We cant call qdisc_tree_reduce_backlog() if our qlen is 0, +- * or HTB crashes. Defer it for next round. +- */ +- if (q->cstats.drop_count && sch->q.qlen) { +- qdisc_tree_reduce_backlog(sch, q->cstats.drop_count, +- q->cstats.drop_len); +- q->cstats.drop_count = 0; +- q->cstats.drop_len = 0; +- } + return skb; + } + diff --git a/target/linux/generic/pending-4.14/640-netfilter-nf_flow_table-add-hardware-offload-support.patch b/target/linux/generic/pending-4.14/640-netfilter-nf_flow_table-add-hardware-offload-support.patch new file mode 100644 index 000000000..7dc4a010c --- /dev/null +++ b/target/linux/generic/pending-4.14/640-netfilter-nf_flow_table-add-hardware-offload-support.patch @@ -0,0 +1,580 @@ +From: Pablo Neira Ayuso +Date: Thu, 11 Jan 2018 16:32:00 +0100 +Subject: [PATCH] netfilter: nf_flow_table: add hardware offload support + +This patch adds the infrastructure to offload flows to hardware, in case +the nic/switch comes with built-in flow tables capabilities. + +If the hardware comes with no hardware flow tables or they have +limitations in terms of features, the existing infrastructure falls back +to the software flow table implementation. + +The software flow table garbage collector skips entries that resides in +the hardware, so the hardware will be responsible for releasing this +flow table entry too via flow_offload_dead(). + +Hardware configuration, either to add or to delete entries, is done from +the hardware offload workqueue, to ensure this is done from user context +given that we may sleep when grabbing the mdio mutex. + +Signed-off-by: Pablo Neira Ayuso +--- + create mode 100644 net/netfilter/nf_flow_table_hw.c + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -826,6 +826,13 @@ struct xfrmdev_ops { + }; + #endif + ++struct flow_offload; ++ ++enum flow_offload_type { ++ FLOW_OFFLOAD_ADD = 0, ++ FLOW_OFFLOAD_DEL, ++}; ++ + /* + * This structure defines the management hooks for network devices. + * The following hooks can be defined; unless noted otherwise, they are +@@ -1057,6 +1064,10 @@ struct xfrmdev_ops { + * int (*ndo_bridge_dellink)(struct net_device *dev, struct nlmsghdr *nlh, + * u16 flags); + * ++ * int (*ndo_flow_offload)(enum flow_offload_type type, ++ * struct flow_offload *flow); ++ * Adds/deletes flow entry to/from net device flowtable. ++ * + * int (*ndo_change_carrier)(struct net_device *dev, bool new_carrier); + * Called to change device carrier. Soft-devices (like dummy, team, etc) + * which do not represent real hardware may define this to allow their +@@ -1281,6 +1292,8 @@ struct net_device_ops { + int (*ndo_bridge_dellink)(struct net_device *dev, + struct nlmsghdr *nlh, + u16 flags); ++ int (*ndo_flow_offload)(enum flow_offload_type type, ++ struct flow_offload *flow); + int (*ndo_change_carrier)(struct net_device *dev, + bool new_carrier); + int (*ndo_get_phys_port_id)(struct net_device *dev, +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -20,11 +20,17 @@ struct nf_flowtable_type { + struct module *owner; + }; + ++enum nf_flowtable_flags { ++ NF_FLOWTABLE_F_HW = 0x1, ++}; ++ + struct nf_flowtable { + struct list_head list; + struct rhashtable rhashtable; + const struct nf_flowtable_type *type; ++ u32 flags; + struct delayed_work gc_work; ++ possible_net_t ft_net; + }; + + enum flow_offload_tuple_dir { +@@ -69,6 +75,7 @@ struct flow_offload_tuple_rhash { + #define FLOW_OFFLOAD_DNAT 0x2 + #define FLOW_OFFLOAD_DYING 0x4 + #define FLOW_OFFLOAD_TEARDOWN 0x8 ++#define FLOW_OFFLOAD_HW 0x10 + + struct flow_offload { + struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX]; +@@ -126,6 +133,22 @@ unsigned int nf_flow_offload_ip_hook(voi + unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, + const struct nf_hook_state *state); + ++void nf_flow_offload_hw_add(struct net *net, struct flow_offload *flow, ++ struct nf_conn *ct); ++void nf_flow_offload_hw_del(struct net *net, struct flow_offload *flow); ++ ++struct nf_flow_table_hw { ++ struct module *owner; ++ void (*add)(struct net *net, struct flow_offload *flow, ++ struct nf_conn *ct); ++ void (*del)(struct net *net, struct flow_offload *flow); ++}; ++ ++int nf_flow_table_hw_register(const struct nf_flow_table_hw *offload); ++void nf_flow_table_hw_unregister(const struct nf_flow_table_hw *offload); ++ ++extern struct work_struct nf_flow_offload_hw_work; ++ + #define MODULE_ALIAS_NF_FLOWTABLE(family) \ + MODULE_ALIAS("nf-flowtable-" __stringify(family)) + +--- a/include/uapi/linux/netfilter/nf_tables.h ++++ b/include/uapi/linux/netfilter/nf_tables.h +@@ -1341,6 +1341,7 @@ enum nft_object_attributes { + * @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32) + * @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32) + * @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64) ++ * @NFTA_FLOWTABLE_FLAGS: flags (NLA_U32) + */ + enum nft_flowtable_attributes { + NFTA_FLOWTABLE_UNSPEC, +@@ -1350,6 +1351,7 @@ enum nft_flowtable_attributes { + NFTA_FLOWTABLE_USE, + NFTA_FLOWTABLE_HANDLE, + NFTA_FLOWTABLE_PAD, ++ NFTA_FLOWTABLE_FLAGS, + __NFTA_FLOWTABLE_MAX + }; + #define NFTA_FLOWTABLE_MAX (__NFTA_FLOWTABLE_MAX - 1) +--- a/net/netfilter/Kconfig ++++ b/net/netfilter/Kconfig +@@ -686,6 +686,15 @@ config NF_FLOW_TABLE + + To compile it as a module, choose M here. + ++config NF_FLOW_TABLE_HW ++ tristate "Netfilter flow table hardware offload module" ++ depends on NF_FLOW_TABLE ++ help ++ This option adds hardware offload support for the flow table core ++ infrastructure. ++ ++ To compile it as a module, choose M here. ++ + config NETFILTER_XTABLES + tristate "Netfilter Xtables support (required for ip_tables)" + default m if NETFILTER_ADVANCED=n +--- a/net/netfilter/Makefile ++++ b/net/netfilter/Makefile +@@ -116,6 +116,7 @@ obj-$(CONFIG_NF_FLOW_TABLE) += nf_flow_t + nf_flow_table-objs := nf_flow_table_core.o nf_flow_table_ip.o + + obj-$(CONFIG_NF_FLOW_TABLE_INET) += nf_flow_table_inet.o ++obj-$(CONFIG_NF_FLOW_TABLE_HW) += nf_flow_table_hw.o + + # generic X tables + obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -199,10 +199,16 @@ int flow_offload_add(struct nf_flowtable + } + EXPORT_SYMBOL_GPL(flow_offload_add); + ++static inline bool nf_flow_in_hw(const struct flow_offload *flow) ++{ ++ return flow->flags & FLOW_OFFLOAD_HW; ++} ++ + static void flow_offload_del(struct nf_flowtable *flow_table, + struct flow_offload *flow) + { + struct flow_offload_entry *e; ++ struct net *net = read_pnet(&flow_table->ft_net); + + rhashtable_remove_fast(&flow_table->rhashtable, + &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node, +@@ -214,6 +220,9 @@ static void flow_offload_del(struct nf_f + e = container_of(flow, struct flow_offload_entry, flow); + clear_bit(IPS_OFFLOAD_BIT, &e->ct->status); + ++ if (nf_flow_in_hw(flow)) ++ nf_flow_offload_hw_del(net, flow); ++ + flow_offload_free(flow); + } + +@@ -307,6 +316,7 @@ static int nf_flow_offload_gc_step(struc + rhashtable_walk_start(&hti); + + while ((tuplehash = rhashtable_walk_next(&hti))) { ++ bool teardown; + if (IS_ERR(tuplehash)) { + err = PTR_ERR(tuplehash); + if (err != -EAGAIN) +@@ -319,9 +329,13 @@ static int nf_flow_offload_gc_step(struc + + flow = container_of(tuplehash, struct flow_offload, tuplehash[0]); + +- if (nf_flow_has_expired(flow) || +- (flow->flags & (FLOW_OFFLOAD_DYING | +- FLOW_OFFLOAD_TEARDOWN))) ++ teardown = flow->flags & (FLOW_OFFLOAD_DYING | ++ FLOW_OFFLOAD_TEARDOWN); ++ ++ if (nf_flow_in_hw(flow) && !teardown) ++ continue; ++ ++ if (nf_flow_has_expired(flow) || teardown) + flow_offload_del(flow_table, flow); + } + out: +@@ -456,10 +470,43 @@ int nf_flow_dnat_port(const struct flow_ + } + EXPORT_SYMBOL_GPL(nf_flow_dnat_port); + ++static const struct nf_flow_table_hw __rcu *nf_flow_table_hw_hook __read_mostly; ++ ++static int nf_flow_offload_hw_init(struct nf_flowtable *flow_table) ++{ ++ const struct nf_flow_table_hw *offload; ++ ++ if (!rcu_access_pointer(nf_flow_table_hw_hook)) ++ request_module("nf-flow-table-hw"); ++ ++ rcu_read_lock(); ++ offload = rcu_dereference(nf_flow_table_hw_hook); ++ if (!offload) ++ goto err_no_hw_offload; ++ ++ if (!try_module_get(offload->owner)) ++ goto err_no_hw_offload; ++ ++ rcu_read_unlock(); ++ ++ return 0; ++ ++err_no_hw_offload: ++ rcu_read_unlock(); ++ ++ return -EOPNOTSUPP; ++} ++ + int nf_flow_table_init(struct nf_flowtable *flowtable) + { + int err; + ++ if (flowtable->flags & NF_FLOWTABLE_F_HW) { ++ err = nf_flow_offload_hw_init(flowtable); ++ if (err) ++ return err; ++ } ++ + INIT_DEFERRABLE_WORK(&flowtable->gc_work, nf_flow_offload_work_gc); + + err = rhashtable_init(&flowtable->rhashtable, +@@ -497,6 +544,8 @@ static void nf_flow_table_iterate_cleanu + { + nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, dev); + flush_delayed_work(&flowtable->gc_work); ++ if (flowtable->flags & NF_FLOWTABLE_F_HW) ++ flush_work(&nf_flow_offload_hw_work); + } + + void nf_flow_table_cleanup(struct net *net, struct net_device *dev) +@@ -510,6 +559,26 @@ void nf_flow_table_cleanup(struct net *n + } + EXPORT_SYMBOL_GPL(nf_flow_table_cleanup); + ++struct work_struct nf_flow_offload_hw_work; ++EXPORT_SYMBOL_GPL(nf_flow_offload_hw_work); ++ ++/* Give the hardware workqueue the chance to remove entries from hardware.*/ ++static void nf_flow_offload_hw_free(struct nf_flowtable *flowtable) ++{ ++ const struct nf_flow_table_hw *offload; ++ ++ flush_work(&nf_flow_offload_hw_work); ++ ++ rcu_read_lock(); ++ offload = rcu_dereference(nf_flow_table_hw_hook); ++ if (!offload) { ++ rcu_read_unlock(); ++ return; ++ } ++ module_put(offload->owner); ++ rcu_read_unlock(); ++} ++ + void nf_flow_table_free(struct nf_flowtable *flow_table) + { + mutex_lock(&flowtable_lock); +@@ -519,9 +588,58 @@ void nf_flow_table_free(struct nf_flowta + nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL); + WARN_ON(!nf_flow_offload_gc_step(flow_table)); + rhashtable_destroy(&flow_table->rhashtable); ++ if (flow_table->flags & NF_FLOWTABLE_F_HW) ++ nf_flow_offload_hw_free(flow_table); + } + EXPORT_SYMBOL_GPL(nf_flow_table_free); + ++/* Must be called from user context. */ ++void nf_flow_offload_hw_add(struct net *net, struct flow_offload *flow, ++ struct nf_conn *ct) ++{ ++ const struct nf_flow_table_hw *offload; ++ ++ rcu_read_lock(); ++ offload = rcu_dereference(nf_flow_table_hw_hook); ++ if (offload) ++ offload->add(net, flow, ct); ++ rcu_read_unlock(); ++} ++EXPORT_SYMBOL_GPL(nf_flow_offload_hw_add); ++ ++/* Must be called from user context. */ ++void nf_flow_offload_hw_del(struct net *net, struct flow_offload *flow) ++{ ++ const struct nf_flow_table_hw *offload; ++ ++ rcu_read_lock(); ++ offload = rcu_dereference(nf_flow_table_hw_hook); ++ if (offload) ++ offload->del(net, flow); ++ rcu_read_unlock(); ++} ++EXPORT_SYMBOL_GPL(nf_flow_offload_hw_del); ++ ++int nf_flow_table_hw_register(const struct nf_flow_table_hw *offload) ++{ ++ if (rcu_access_pointer(nf_flow_table_hw_hook)) ++ return -EBUSY; ++ ++ rcu_assign_pointer(nf_flow_table_hw_hook, offload); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nf_flow_table_hw_register); ++ ++void nf_flow_table_hw_unregister(const struct nf_flow_table_hw *offload) ++{ ++ WARN_ON(rcu_access_pointer(nf_flow_table_hw_hook) != offload); ++ rcu_assign_pointer(nf_flow_table_hw_hook, NULL); ++ ++ synchronize_rcu(); ++} ++EXPORT_SYMBOL_GPL(nf_flow_table_hw_unregister); ++ + static int nf_flow_table_netdev_event(struct notifier_block *this, + unsigned long event, void *ptr) + { +--- /dev/null ++++ b/net/netfilter/nf_flow_table_hw.c +@@ -0,0 +1,169 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static DEFINE_SPINLOCK(flow_offload_hw_pending_list_lock); ++static LIST_HEAD(flow_offload_hw_pending_list); ++ ++static DEFINE_MUTEX(nf_flow_offload_hw_mutex); ++ ++struct flow_offload_hw { ++ struct list_head list; ++ enum flow_offload_type type; ++ struct flow_offload *flow; ++ struct nf_conn *ct; ++ possible_net_t flow_hw_net; ++}; ++ ++static int do_flow_offload_hw(struct net *net, struct flow_offload *flow, ++ int type) ++{ ++ struct net_device *indev; ++ int ret, ifindex; ++ ++ ifindex = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.iifidx; ++ indev = dev_get_by_index(net, ifindex); ++ if (WARN_ON(!indev)) ++ return 0; ++ ++ mutex_lock(&nf_flow_offload_hw_mutex); ++ ret = indev->netdev_ops->ndo_flow_offload(type, flow); ++ mutex_unlock(&nf_flow_offload_hw_mutex); ++ ++ dev_put(indev); ++ ++ return ret; ++} ++ ++static void flow_offload_hw_work_add(struct flow_offload_hw *offload) ++{ ++ struct net *net; ++ int ret; ++ ++ if (nf_ct_is_dying(offload->ct)) ++ return; ++ ++ net = read_pnet(&offload->flow_hw_net); ++ ret = do_flow_offload_hw(net, offload->flow, FLOW_OFFLOAD_ADD); ++ if (ret >= 0) ++ offload->flow->flags |= FLOW_OFFLOAD_HW; ++} ++ ++static void flow_offload_hw_work_del(struct flow_offload_hw *offload) ++{ ++ struct net *net = read_pnet(&offload->flow_hw_net); ++ ++ do_flow_offload_hw(net, offload->flow, FLOW_OFFLOAD_DEL); ++} ++ ++static void flow_offload_hw_work(struct work_struct *work) ++{ ++ struct flow_offload_hw *offload, *next; ++ LIST_HEAD(hw_offload_pending); ++ ++ spin_lock_bh(&flow_offload_hw_pending_list_lock); ++ list_replace_init(&flow_offload_hw_pending_list, &hw_offload_pending); ++ spin_unlock_bh(&flow_offload_hw_pending_list_lock); ++ ++ list_for_each_entry_safe(offload, next, &hw_offload_pending, list) { ++ switch (offload->type) { ++ case FLOW_OFFLOAD_ADD: ++ flow_offload_hw_work_add(offload); ++ break; ++ case FLOW_OFFLOAD_DEL: ++ flow_offload_hw_work_del(offload); ++ break; ++ } ++ if (offload->ct) ++ nf_conntrack_put(&offload->ct->ct_general); ++ list_del(&offload->list); ++ kfree(offload); ++ } ++} ++ ++static void flow_offload_queue_work(struct flow_offload_hw *offload) ++{ ++ spin_lock_bh(&flow_offload_hw_pending_list_lock); ++ list_add_tail(&offload->list, &flow_offload_hw_pending_list); ++ spin_unlock_bh(&flow_offload_hw_pending_list_lock); ++ ++ schedule_work(&nf_flow_offload_hw_work); ++} ++ ++static void flow_offload_hw_add(struct net *net, struct flow_offload *flow, ++ struct nf_conn *ct) ++{ ++ struct flow_offload_hw *offload; ++ ++ offload = kmalloc(sizeof(struct flow_offload_hw), GFP_ATOMIC); ++ if (!offload) ++ return; ++ ++ nf_conntrack_get(&ct->ct_general); ++ offload->type = FLOW_OFFLOAD_ADD; ++ offload->ct = ct; ++ offload->flow = flow; ++ write_pnet(&offload->flow_hw_net, net); ++ ++ flow_offload_queue_work(offload); ++} ++ ++static void flow_offload_hw_del(struct net *net, struct flow_offload *flow) ++{ ++ struct flow_offload_hw *offload; ++ ++ offload = kmalloc(sizeof(struct flow_offload_hw), GFP_ATOMIC); ++ if (!offload) ++ return; ++ ++ offload->type = FLOW_OFFLOAD_DEL; ++ offload->ct = NULL; ++ offload->flow = flow; ++ write_pnet(&offload->flow_hw_net, net); ++ ++ flow_offload_queue_work(offload); ++} ++ ++static const struct nf_flow_table_hw flow_offload_hw = { ++ .add = flow_offload_hw_add, ++ .del = flow_offload_hw_del, ++ .owner = THIS_MODULE, ++}; ++ ++static int __init nf_flow_table_hw_module_init(void) ++{ ++ INIT_WORK(&nf_flow_offload_hw_work, flow_offload_hw_work); ++ nf_flow_table_hw_register(&flow_offload_hw); ++ ++ return 0; ++} ++ ++static void __exit nf_flow_table_hw_module_exit(void) ++{ ++ struct flow_offload_hw *offload, *next; ++ LIST_HEAD(hw_offload_pending); ++ ++ nf_flow_table_hw_unregister(&flow_offload_hw); ++ cancel_work_sync(&nf_flow_offload_hw_work); ++ ++ list_for_each_entry_safe(offload, next, &hw_offload_pending, list) { ++ if (offload->ct) ++ nf_conntrack_put(&offload->ct->ct_general); ++ list_del(&offload->list); ++ kfree(offload); ++ } ++} ++ ++module_init(nf_flow_table_hw_module_init); ++module_exit(nf_flow_table_hw_module_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Pablo Neira Ayuso "); ++MODULE_ALIAS("nf-flow-table-hw"); +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -4866,6 +4866,14 @@ static int nf_tables_flowtable_parse_hoo + if (err < 0) + goto err1; + ++ for (i = 0; i < n; i++) { ++ if (flowtable->data.flags & NF_FLOWTABLE_F_HW && ++ !dev_array[i]->netdev_ops->ndo_flow_offload) { ++ err = -EOPNOTSUPP; ++ goto err1; ++ } ++ } ++ + ops = kzalloc(sizeof(struct nf_hook_ops) * n, GFP_KERNEL); + if (!ops) { + err = -ENOMEM; +@@ -4996,10 +5004,19 @@ static int nf_tables_newflowtable(struct + } + + flowtable->data.type = type; ++ write_pnet(&flowtable->data.ft_net, net); ++ + err = type->init(&flowtable->data); + if (err < 0) + goto err3; + ++ if (nla[NFTA_FLOWTABLE_FLAGS]) { ++ flowtable->data.flags = ++ ntohl(nla_get_be32(nla[NFTA_FLOWTABLE_FLAGS])); ++ if (flowtable->data.flags & ~NF_FLOWTABLE_F_HW) ++ goto err4; ++ } ++ + err = nf_tables_flowtable_parse_hook(&ctx, nla[NFTA_FLOWTABLE_HOOK], + flowtable); + if (err < 0) +@@ -5097,7 +5114,8 @@ static int nf_tables_fill_flowtable_info + nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) || + nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) || + nla_put_be64(skb, NFTA_FLOWTABLE_HANDLE, cpu_to_be64(flowtable->handle), +- NFTA_FLOWTABLE_PAD)) ++ NFTA_FLOWTABLE_PAD) || ++ nla_put_be32(skb, NFTA_FLOWTABLE_FLAGS, htonl(flowtable->data.flags))) + goto nla_put_failure; + + nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK); +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -121,6 +121,9 @@ static void nft_flow_offload_eval(const + if (ret < 0) + goto err_flow_add; + ++ if (flowtable->flags & NF_FLOWTABLE_F_HW) ++ nf_flow_offload_hw_add(nft_net(pkt), flow, ct); ++ + return; + + err_flow_add: diff --git a/target/linux/generic/pending-4.14/641-netfilter-nf_flow_table-support-hw-offload-through-v.patch b/target/linux/generic/pending-4.14/641-netfilter-nf_flow_table-support-hw-offload-through-v.patch new file mode 100644 index 000000000..58359731f --- /dev/null +++ b/target/linux/generic/pending-4.14/641-netfilter-nf_flow_table-support-hw-offload-through-v.patch @@ -0,0 +1,302 @@ +From: Felix Fietkau +Date: Thu, 15 Mar 2018 20:46:31 +0100 +Subject: [PATCH] netfilter: nf_flow_table: support hw offload through + virtual interfaces + +There are hardware offload devices that support offloading VLANs and +PPPoE devices. Additionally, it is useful to be able to offload packets +routed through bridge interfaces as well. +Add support for finding the path to the offload device through these +virtual interfaces, while collecting useful parameters for the offload +device, like VLAN ID/protocol, PPPoE session and Ethernet MAC address. + +Signed-off-by: Felix Fietkau +--- + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -827,6 +827,7 @@ struct xfrmdev_ops { + #endif + + struct flow_offload; ++struct flow_offload_hw_path; + + enum flow_offload_type { + FLOW_OFFLOAD_ADD = 0, +@@ -1064,8 +1065,15 @@ enum flow_offload_type { + * int (*ndo_bridge_dellink)(struct net_device *dev, struct nlmsghdr *nlh, + * u16 flags); + * ++ * int (*ndo_flow_offload_check)(struct flow_offload_hw_path *path); ++ * For virtual devices like bridges, vlan, and pppoe, fill in the ++ * underlying network device that can be used for offloading connections. ++ * Return an error if offloading is not supported. ++ * + * int (*ndo_flow_offload)(enum flow_offload_type type, +- * struct flow_offload *flow); ++ * struct flow_offload *flow, ++ * struct flow_offload_hw_path *src, ++ * struct flow_offload_hw_path *dest); + * Adds/deletes flow entry to/from net device flowtable. + * + * int (*ndo_change_carrier)(struct net_device *dev, bool new_carrier); +@@ -1292,8 +1300,11 @@ struct net_device_ops { + int (*ndo_bridge_dellink)(struct net_device *dev, + struct nlmsghdr *nlh, + u16 flags); ++ int (*ndo_flow_offload_check)(struct flow_offload_hw_path *path); + int (*ndo_flow_offload)(enum flow_offload_type type, +- struct flow_offload *flow); ++ struct flow_offload *flow, ++ struct flow_offload_hw_path *src, ++ struct flow_offload_hw_path *dest); + int (*ndo_change_carrier)(struct net_device *dev, + bool new_carrier); + int (*ndo_get_phys_port_id)(struct net_device *dev, +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -86,6 +86,21 @@ struct flow_offload { + }; + }; + ++#define FLOW_OFFLOAD_PATH_ETHERNET BIT(0) ++#define FLOW_OFFLOAD_PATH_VLAN BIT(1) ++#define FLOW_OFFLOAD_PATH_PPPOE BIT(2) ++ ++struct flow_offload_hw_path { ++ struct net_device *dev; ++ u32 flags; ++ ++ u8 eth_src[ETH_ALEN]; ++ u8 eth_dest[ETH_ALEN]; ++ u16 vlan_proto; ++ u16 vlan_id; ++ u16 pppoe_sid; ++}; ++ + #define NF_FLOW_TIMEOUT (30 * HZ) + + struct nf_flow_route { +--- a/net/netfilter/nf_flow_table_hw.c ++++ b/net/netfilter/nf_flow_table_hw.c +@@ -19,48 +19,75 @@ struct flow_offload_hw { + enum flow_offload_type type; + struct flow_offload *flow; + struct nf_conn *ct; +- possible_net_t flow_hw_net; ++ ++ struct flow_offload_hw_path src; ++ struct flow_offload_hw_path dest; + }; + +-static int do_flow_offload_hw(struct net *net, struct flow_offload *flow, +- int type) ++static void flow_offload_check_ethernet(struct flow_offload_tuple *tuple, ++ struct flow_offload_hw_path *path) + { +- struct net_device *indev; +- int ret, ifindex; ++ struct net_device *dev = path->dev; ++ struct neighbour *n; + +- ifindex = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.iifidx; +- indev = dev_get_by_index(net, ifindex); +- if (WARN_ON(!indev)) +- return 0; ++ if (dev->type != ARPHRD_ETHER) ++ return; + +- mutex_lock(&nf_flow_offload_hw_mutex); +- ret = indev->netdev_ops->ndo_flow_offload(type, flow); +- mutex_unlock(&nf_flow_offload_hw_mutex); ++ memcpy(path->eth_src, path->dev->dev_addr, ETH_ALEN); ++ n = dst_neigh_lookup(tuple->dst_cache, &tuple->src_v4); ++ if (!n) ++ return; + +- dev_put(indev); ++ memcpy(path->eth_dest, n->ha, ETH_ALEN); ++ path->flags |= FLOW_OFFLOAD_PATH_ETHERNET; ++ neigh_release(n); ++} + +- return ret; ++static int flow_offload_check_path(struct net *net, ++ struct flow_offload_tuple *tuple, ++ struct flow_offload_hw_path *path) ++{ ++ struct net_device *dev; ++ ++ dev = dev_get_by_index_rcu(net, tuple->iifidx); ++ if (!dev) ++ return -ENOENT; ++ ++ path->dev = dev; ++ flow_offload_check_ethernet(tuple, path); ++ ++ if (dev->netdev_ops->ndo_flow_offload_check) ++ return dev->netdev_ops->ndo_flow_offload_check(path); ++ ++ return 0; + } + +-static void flow_offload_hw_work_add(struct flow_offload_hw *offload) ++static int do_flow_offload_hw(struct flow_offload_hw *offload) + { +- struct net *net; ++ struct net_device *src_dev = offload->src.dev; ++ struct net_device *dest_dev = offload->dest.dev; + int ret; + +- if (nf_ct_is_dying(offload->ct)) +- return; ++ ret = src_dev->netdev_ops->ndo_flow_offload(offload->type, ++ offload->flow, ++ &offload->src, ++ &offload->dest); + +- net = read_pnet(&offload->flow_hw_net); +- ret = do_flow_offload_hw(net, offload->flow, FLOW_OFFLOAD_ADD); +- if (ret >= 0) +- offload->flow->flags |= FLOW_OFFLOAD_HW; ++ /* restore devices in case the driver mangled them */ ++ offload->src.dev = src_dev; ++ offload->dest.dev = dest_dev; ++ ++ return ret; + } + +-static void flow_offload_hw_work_del(struct flow_offload_hw *offload) ++static void flow_offload_hw_free(struct flow_offload_hw *offload) + { +- struct net *net = read_pnet(&offload->flow_hw_net); +- +- do_flow_offload_hw(net, offload->flow, FLOW_OFFLOAD_DEL); ++ dev_put(offload->src.dev); ++ dev_put(offload->dest.dev); ++ if (offload->ct) ++ nf_conntrack_put(&offload->ct->ct_general); ++ list_del(&offload->list); ++ kfree(offload); + } + + static void flow_offload_hw_work(struct work_struct *work) +@@ -73,18 +100,22 @@ static void flow_offload_hw_work(struct + spin_unlock_bh(&flow_offload_hw_pending_list_lock); + + list_for_each_entry_safe(offload, next, &hw_offload_pending, list) { ++ mutex_lock(&nf_flow_offload_hw_mutex); + switch (offload->type) { + case FLOW_OFFLOAD_ADD: +- flow_offload_hw_work_add(offload); ++ if (nf_ct_is_dying(offload->ct)) ++ break; ++ ++ if (do_flow_offload_hw(offload) >= 0) ++ offload->flow->flags |= FLOW_OFFLOAD_HW; + break; + case FLOW_OFFLOAD_DEL: +- flow_offload_hw_work_del(offload); ++ do_flow_offload_hw(offload); + break; + } +- if (offload->ct) +- nf_conntrack_put(&offload->ct->ct_general); +- list_del(&offload->list); +- kfree(offload); ++ mutex_unlock(&nf_flow_offload_hw_mutex); ++ ++ flow_offload_hw_free(offload); + } + } + +@@ -97,20 +128,55 @@ static void flow_offload_queue_work(stru + schedule_work(&nf_flow_offload_hw_work); + } + ++static struct flow_offload_hw * ++flow_offload_hw_prepare(struct net *net, struct flow_offload *flow) ++{ ++ struct flow_offload_hw_path src = {}; ++ struct flow_offload_hw_path dest = {}; ++ struct flow_offload_tuple *tuple; ++ struct flow_offload_hw *offload = NULL; ++ ++ rcu_read_lock_bh(); ++ ++ tuple = &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple; ++ if (flow_offload_check_path(net, tuple, &src)) ++ goto out; ++ ++ tuple = &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple; ++ if (flow_offload_check_path(net, tuple, &dest)) ++ goto out; ++ ++ if (!src.dev->netdev_ops->ndo_flow_offload) ++ goto out; ++ ++ offload = kzalloc(sizeof(struct flow_offload_hw), GFP_ATOMIC); ++ if (!offload) ++ goto out; ++ ++ dev_hold(src.dev); ++ dev_hold(dest.dev); ++ offload->src = src; ++ offload->dest = dest; ++ offload->flow = flow; ++ ++out: ++ rcu_read_unlock_bh(); ++ ++ return offload; ++} ++ + static void flow_offload_hw_add(struct net *net, struct flow_offload *flow, + struct nf_conn *ct) + { + struct flow_offload_hw *offload; + +- offload = kmalloc(sizeof(struct flow_offload_hw), GFP_ATOMIC); ++ offload = flow_offload_hw_prepare(net, flow); + if (!offload) + return; + + nf_conntrack_get(&ct->ct_general); + offload->type = FLOW_OFFLOAD_ADD; + offload->ct = ct; +- offload->flow = flow; +- write_pnet(&offload->flow_hw_net, net); + + flow_offload_queue_work(offload); + } +@@ -119,14 +185,11 @@ static void flow_offload_hw_del(struct n + { + struct flow_offload_hw *offload; + +- offload = kmalloc(sizeof(struct flow_offload_hw), GFP_ATOMIC); ++ offload = flow_offload_hw_prepare(net, flow); + if (!offload) + return; + + offload->type = FLOW_OFFLOAD_DEL; +- offload->ct = NULL; +- offload->flow = flow; +- write_pnet(&offload->flow_hw_net, net); + + flow_offload_queue_work(offload); + } +@@ -153,12 +216,8 @@ static void __exit nf_flow_table_hw_modu + nf_flow_table_hw_unregister(&flow_offload_hw); + cancel_work_sync(&nf_flow_offload_hw_work); + +- list_for_each_entry_safe(offload, next, &hw_offload_pending, list) { +- if (offload->ct) +- nf_conntrack_put(&offload->ct->ct_general); +- list_del(&offload->list); +- kfree(offload); +- } ++ list_for_each_entry_safe(offload, next, &hw_offload_pending, list) ++ flow_offload_hw_free(offload); + } + + module_init(nf_flow_table_hw_module_init); diff --git a/target/linux/generic/pending-4.14/642-net-8021q-support-hardware-flow-table-offload.patch b/target/linux/generic/pending-4.14/642-net-8021q-support-hardware-flow-table-offload.patch new file mode 100644 index 000000000..cda2e0ffd --- /dev/null +++ b/target/linux/generic/pending-4.14/642-net-8021q-support-hardware-flow-table-offload.patch @@ -0,0 +1,56 @@ +From: Felix Fietkau +Date: Thu, 15 Mar 2018 20:49:58 +0100 +Subject: [PATCH] net: 8021q: support hardware flow table offload + +Add the VLAN ID and protocol information + +Signed-off-by: Felix Fietkau +--- + +--- a/net/8021q/vlan_dev.c ++++ b/net/8021q/vlan_dev.c +@@ -29,8 +29,10 @@ + #include + #include + #include ++#include + #include + #include ++#include + + #include "vlan.h" + #include "vlanproc.h" +@@ -762,6 +764,25 @@ static int vlan_dev_get_iflink(const str + return real_dev->ifindex; + } + ++static int vlan_dev_flow_offload_check(struct flow_offload_hw_path *path) ++{ ++ struct net_device *dev = path->dev; ++ struct vlan_dev_priv *vlan = vlan_dev_priv(dev); ++ ++ if (path->flags & FLOW_OFFLOAD_PATH_VLAN) ++ return -EEXIST; ++ ++ path->flags |= FLOW_OFFLOAD_PATH_VLAN; ++ path->vlan_proto = vlan->vlan_proto; ++ path->vlan_id = vlan->vlan_id; ++ path->dev = vlan->real_dev; ++ ++ if (vlan->real_dev->netdev_ops->ndo_flow_offload_check) ++ return vlan->real_dev->netdev_ops->ndo_flow_offload_check(path); ++ ++ return 0; ++} ++ + static const struct ethtool_ops vlan_ethtool_ops = { + .get_link_ksettings = vlan_ethtool_get_link_ksettings, + .get_drvinfo = vlan_ethtool_get_drvinfo, +@@ -799,6 +820,7 @@ static const struct net_device_ops vlan_ + .ndo_fix_features = vlan_dev_fix_features, + .ndo_get_lock_subclass = vlan_dev_get_lock_subclass, + .ndo_get_iflink = vlan_dev_get_iflink, ++ .ndo_flow_offload_check = vlan_dev_flow_offload_check, + }; + + static void vlan_dev_free(struct net_device *dev) diff --git a/target/linux/generic/pending-4.14/643-net-bridge-support-hardware-flow-table-offload.patch b/target/linux/generic/pending-4.14/643-net-bridge-support-hardware-flow-table-offload.patch new file mode 100644 index 000000000..3158714f5 --- /dev/null +++ b/target/linux/generic/pending-4.14/643-net-bridge-support-hardware-flow-table-offload.patch @@ -0,0 +1,55 @@ +From: Felix Fietkau +Date: Thu, 15 Mar 2018 20:50:37 +0100 +Subject: [PATCH] net: bridge: support hardware flow table offload + +Look up the real device and pass it on + +Signed-off-by: Felix Fietkau +--- + +--- a/net/bridge/br_device.c ++++ b/net/bridge/br_device.c +@@ -18,6 +18,8 @@ + #include + #include + #include ++#include ++#include + + #include + #include "br_private.h" +@@ -340,6 +342,26 @@ static const struct ethtool_ops br_ethto + .get_link = ethtool_op_get_link, + }; + ++static int br_flow_offload_check(struct flow_offload_hw_path *path) ++{ ++ struct net_device *dev = path->dev; ++ struct net_bridge *br = netdev_priv(dev); ++ struct net_bridge_fdb_entry *dst; ++ ++ if (!(path->flags & FLOW_OFFLOAD_PATH_ETHERNET)) ++ return -EINVAL; ++ ++ dst = br_fdb_find_rcu(br, path->eth_dest, path->vlan_id); ++ if (!dst || !dst->dst) ++ return -ENOENT; ++ ++ path->dev = dst->dst->dev; ++ if (path->dev->netdev_ops->ndo_flow_offload_check) ++ return path->dev->netdev_ops->ndo_flow_offload_check(path); ++ ++ return 0; ++} ++ + static const struct net_device_ops br_netdev_ops = { + .ndo_open = br_dev_open, + .ndo_stop = br_dev_stop, +@@ -367,6 +389,7 @@ static const struct net_device_ops br_ne + .ndo_bridge_setlink = br_setlink, + .ndo_bridge_dellink = br_dellink, + .ndo_features_check = passthru_features_check, ++ .ndo_flow_offload_check = br_flow_offload_check, + }; + + static struct device_type br_type = { diff --git a/target/linux/generic/pending-4.14/644-net-pppoe-support-hardware-flow-table-offload.patch b/target/linux/generic/pending-4.14/644-net-pppoe-support-hardware-flow-table-offload.patch new file mode 100644 index 000000000..9259fe8df --- /dev/null +++ b/target/linux/generic/pending-4.14/644-net-pppoe-support-hardware-flow-table-offload.patch @@ -0,0 +1,110 @@ +From: Felix Fietkau +Date: Thu, 15 Mar 2018 21:15:00 +0100 +Subject: [PATCH] net: pppoe: support hardware flow table offload + +Pass on the PPPoE session ID and the remote MAC address + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -56,6 +56,9 @@ + #include + #include + ++#include ++#include ++ + #define PPP_VERSION "2.4.2" + + /* +@@ -1383,12 +1386,33 @@ static void ppp_dev_priv_destructor(stru + ppp_destroy_interface(ppp); + } + ++static int ppp_flow_offload_check(struct flow_offload_hw_path *path) ++{ ++ struct ppp *ppp = netdev_priv(path->dev); ++ struct ppp_channel *chan; ++ struct channel *pch; ++ ++ if (ppp->flags & SC_MULTILINK) ++ return -EOPNOTSUPP; ++ ++ if (list_empty(&ppp->channels)) ++ return -ENODEV; ++ ++ pch = list_first_entry(&ppp->channels, struct channel, clist); ++ chan = pch->chan; ++ if (!chan->ops->flow_offload_check) ++ return -EOPNOTSUPP; ++ ++ return chan->ops->flow_offload_check(chan, path); ++} ++ + static const struct net_device_ops ppp_netdev_ops = { + .ndo_init = ppp_dev_init, + .ndo_uninit = ppp_dev_uninit, + .ndo_start_xmit = ppp_start_xmit, + .ndo_do_ioctl = ppp_net_ioctl, + .ndo_get_stats64 = ppp_get_stats64, ++ .ndo_flow_offload_check = ppp_flow_offload_check, + }; + + static struct device_type ppp_type = { +--- a/drivers/net/ppp/pppoe.c ++++ b/drivers/net/ppp/pppoe.c +@@ -77,6 +77,8 @@ + #include + #include + #include ++#include ++#include + + #include + #include +@@ -970,8 +972,32 @@ static int pppoe_xmit(struct ppp_channel + return __pppoe_xmit(sk, skb); + } + ++static int pppoe_flow_offload_check(struct ppp_channel *chan, ++ struct flow_offload_hw_path *path) ++{ ++ struct sock *sk = (struct sock *)chan->private; ++ struct pppox_sock *po = pppox_sk(sk); ++ struct net_device *dev = po->pppoe_dev; ++ ++ if (sock_flag(sk, SOCK_DEAD) || ++ !(sk->sk_state & PPPOX_CONNECTED) || !dev) ++ return -ENODEV; ++ ++ path->dev = po->pppoe_dev; ++ path->flags |= FLOW_OFFLOAD_PATH_PPPOE; ++ memcpy(path->eth_src, po->pppoe_dev->dev_addr, ETH_ALEN); ++ memcpy(path->eth_dest, po->pppoe_pa.remote, ETH_ALEN); ++ path->pppoe_sid = be16_to_cpu(po->num); ++ ++ if (path->dev->netdev_ops->ndo_flow_offload_check) ++ return path->dev->netdev_ops->ndo_flow_offload_check(path); ++ ++ return 0; ++} ++ + static const struct ppp_channel_ops pppoe_chan_ops = { + .start_xmit = pppoe_xmit, ++ .flow_offload_check = pppoe_flow_offload_check, + }; + + static int pppoe_recvmsg(struct socket *sock, struct msghdr *m, +--- a/include/linux/ppp_channel.h ++++ b/include/linux/ppp_channel.h +@@ -32,6 +32,8 @@ struct ppp_channel_ops { + int (*start_xmit)(struct ppp_channel *, struct sk_buff *); + /* Handle an ioctl call that has come in via /dev/ppp. */ + int (*ioctl)(struct ppp_channel *, unsigned int, unsigned long); ++ ++ int (*flow_offload_check)(struct ppp_channel *, struct flow_offload_hw_path *); + }; + + struct ppp_channel { diff --git a/target/linux/generic/pending-4.14/645-netfilter-nf_flow_table-rework-hardware-offload-time.patch b/target/linux/generic/pending-4.14/645-netfilter-nf_flow_table-rework-hardware-offload-time.patch new file mode 100644 index 000000000..8da15bc33 --- /dev/null +++ b/target/linux/generic/pending-4.14/645-netfilter-nf_flow_table-rework-hardware-offload-time.patch @@ -0,0 +1,37 @@ +From: Felix Fietkau +Date: Sun, 25 Mar 2018 21:10:55 +0200 +Subject: [PATCH] netfilter: nf_flow_table: rework hardware offload timeout + handling + +Some offload implementations send keepalive packets + explicit +notifications of TCP FIN/RST packets. In this case it is more convenient +to simply let the driver update flow->timeout handling and use the +regular flow offload gc step. + +For drivers that manage their own lifetime, a separate flag can be set +to avoid gc timeouts. + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -76,6 +76,7 @@ struct flow_offload_tuple_rhash { + #define FLOW_OFFLOAD_DYING 0x4 + #define FLOW_OFFLOAD_TEARDOWN 0x8 + #define FLOW_OFFLOAD_HW 0x10 ++#define FLOW_OFFLOAD_KEEP 0x20 + + struct flow_offload { + struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX]; +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -332,7 +332,7 @@ static int nf_flow_offload_gc_step(struc + teardown = flow->flags & (FLOW_OFFLOAD_DYING | + FLOW_OFFLOAD_TEARDOWN); + +- if (nf_flow_in_hw(flow) && !teardown) ++ if ((flow->flags & FLOW_OFFLOAD_KEEP) && !teardown) + continue; + + if (nf_flow_has_expired(flow) || teardown) diff --git a/target/linux/generic/pending-4.14/650-pppoe_header_pad.patch b/target/linux/generic/pending-4.14/650-pppoe_header_pad.patch deleted file mode 100644 index 3115073b5..000000000 --- a/target/linux/generic/pending-4.14/650-pppoe_header_pad.patch +++ /dev/null @@ -1,29 +0,0 @@ -From: Felix Fietkau -Subject: pppoe: add extra padding for the header (useful for drivers that need headroom) - -lede-commit 6517a757ec711fc3354b857e273e2621042f3c7a -Signed-off-by: Felix Fietkau ---- - drivers/net/ppp/pppoe.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/ppp/pppoe.c -+++ b/drivers/net/ppp/pppoe.c -@@ -861,7 +861,7 @@ static int pppoe_sendmsg(struct socket * - goto end; - - -- skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32, -+ skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32 + NET_SKB_PAD, - 0, GFP_KERNEL); - if (!skb) { - error = -ENOMEM; -@@ -869,7 +869,7 @@ static int pppoe_sendmsg(struct socket * - } - - /* Reserve space for headers. */ -- skb_reserve(skb, dev->hard_header_len); -+ skb_reserve(skb, dev->hard_header_len + NET_SKB_PAD); - skb_reset_network_header(skb); - - skb->dev = dev; diff --git a/target/linux/generic/pending-4.14/655-increase_skb_pad.patch b/target/linux/generic/pending-4.14/655-increase_skb_pad.patch index 515c69f81..88069581a 100644 --- a/target/linux/generic/pending-4.14/655-increase_skb_pad.patch +++ b/target/linux/generic/pending-4.14/655-increase_skb_pad.patch @@ -9,7 +9,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -2458,7 +2458,7 @@ static inline int pskb_network_may_pull( +@@ -2455,7 +2455,7 @@ static inline int pskb_network_may_pull( * NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8) */ #ifndef NET_SKB_PAD diff --git a/target/linux/generic/pending-4.14/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch b/target/linux/generic/pending-4.14/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch index a114acda9..c544f7af1 100644 --- a/target/linux/generic/pending-4.14/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch +++ b/target/linux/generic/pending-4.14/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch @@ -300,7 +300,7 @@ Signed-off-by: Steven Barth /** * ip6_tnl_addr_conflict - compare packet addresses to tunnel's own * @t: the outgoing tunnel device -@@ -1295,6 +1435,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str +@@ -1301,6 +1441,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str { struct ip6_tnl *t = netdev_priv(dev); struct ipv6hdr *ipv6h = ipv6_hdr(skb); @@ -308,7 +308,7 @@ Signed-off-by: Steven Barth int encap_limit = -1; __u16 offset; struct flowi6 fl6; -@@ -1357,6 +1498,18 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str +@@ -1363,6 +1504,18 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); @@ -327,7 +327,7 @@ Signed-off-by: Steven Barth if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) return -1; -@@ -1485,6 +1638,14 @@ ip6_tnl_change(struct ip6_tnl *t, const +@@ -1491,6 +1644,14 @@ ip6_tnl_change(struct ip6_tnl *t, const t->parms.link = p->link; t->parms.proto = p->proto; t->parms.fwmark = p->fwmark; @@ -342,7 +342,7 @@ Signed-off-by: Steven Barth dst_cache_reset(&t->dst_cache); ip6_tnl_link_config(t); return 0; -@@ -1523,6 +1684,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_ +@@ -1529,6 +1690,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_ p->flowinfo = u->flowinfo; p->link = u->link; p->proto = u->proto; @@ -350,7 +350,7 @@ Signed-off-by: Steven Barth memcpy(p->name, u->name, sizeof(u->name)); } -@@ -1904,6 +2066,15 @@ static int ip6_tnl_validate(struct nlatt +@@ -1910,6 +2072,15 @@ static int ip6_tnl_validate(struct nlatt return 0; } @@ -366,7 +366,7 @@ Signed-off-by: Steven Barth static void ip6_tnl_netlink_parms(struct nlattr *data[], struct __ip6_tnl_parm *parms) { -@@ -1941,6 +2112,46 @@ static void ip6_tnl_netlink_parms(struct +@@ -1947,6 +2118,46 @@ static void ip6_tnl_netlink_parms(struct if (data[IFLA_IPTUN_FWMARK]) parms->fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]); @@ -413,7 +413,7 @@ Signed-off-by: Steven Barth } static bool ip6_tnl_netlink_encap_parms(struct nlattr *data[], -@@ -2052,6 +2263,12 @@ static void ip6_tnl_dellink(struct net_d +@@ -2058,6 +2269,12 @@ static void ip6_tnl_dellink(struct net_d static size_t ip6_tnl_get_size(const struct net_device *dev) { @@ -426,7 +426,7 @@ Signed-off-by: Steven Barth return /* IFLA_IPTUN_LINK */ nla_total_size(4) + -@@ -2081,6 +2298,24 @@ static size_t ip6_tnl_get_size(const str +@@ -2087,6 +2304,24 @@ static size_t ip6_tnl_get_size(const str nla_total_size(0) + /* IFLA_IPTUN_FWMARK */ nla_total_size(4) + @@ -451,7 +451,7 @@ Signed-off-by: Steven Barth 0; } -@@ -2088,6 +2323,9 @@ static int ip6_tnl_fill_info(struct sk_b +@@ -2094,6 +2329,9 @@ static int ip6_tnl_fill_info(struct sk_b { struct ip6_tnl *tunnel = netdev_priv(dev); struct __ip6_tnl_parm *parm = &tunnel->parms; @@ -461,7 +461,7 @@ Signed-off-by: Steven Barth if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) || nla_put_in6_addr(skb, IFLA_IPTUN_LOCAL, &parm->laddr) || -@@ -2097,9 +2335,27 @@ static int ip6_tnl_fill_info(struct sk_b +@@ -2103,9 +2341,27 @@ static int ip6_tnl_fill_info(struct sk_b nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) || nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags) || nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->proto) || @@ -490,7 +490,7 @@ Signed-off-by: Steven Barth if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE, tunnel->encap.type) || nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT, tunnel->encap.sport) || nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT, tunnel->encap.dport) || -@@ -2139,6 +2395,7 @@ static const struct nla_policy ip6_tnl_p +@@ -2145,6 +2401,7 @@ static const struct nla_policy ip6_tnl_p [IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 }, [IFLA_IPTUN_COLLECT_METADATA] = { .type = NLA_FLAG }, [IFLA_IPTUN_FWMARK] = { .type = NLA_U32 }, diff --git a/target/linux/generic/pending-4.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-4.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch index 9a088c461..39346886e 100644 --- a/target/linux/generic/pending-4.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +++ b/target/linux/generic/pending-4.14/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -141,7 +141,7 @@ Signed-off-by: Jonas Gorski static const struct rt6_info ip6_blk_hole_entry_template = { .dst = { .__refcnt = ATOMIC_INIT(1), -@@ -2037,6 +2054,11 @@ static struct rt6_info *ip6_route_info_c +@@ -2038,6 +2055,11 @@ static struct rt6_info *ip6_route_info_c rt->dst.output = ip6_pkt_prohibit_out; rt->dst.input = ip6_pkt_prohibit; break; @@ -153,7 +153,7 @@ Signed-off-by: Jonas Gorski case RTN_THROW: case RTN_UNREACHABLE: default: -@@ -2762,6 +2784,17 @@ static int ip6_pkt_prohibit_out(struct n +@@ -2763,6 +2785,17 @@ static int ip6_pkt_prohibit_out(struct n return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); } @@ -171,7 +171,7 @@ Signed-off-by: Jonas Gorski /* * Allocate a dst for local (unicast / anycast) address. */ -@@ -2996,7 +3029,8 @@ static int rtm_to_fib6_config(struct sk_ +@@ -2997,7 +3030,8 @@ static int rtm_to_fib6_config(struct sk_ if (rtm->rtm_type == RTN_UNREACHABLE || rtm->rtm_type == RTN_BLACKHOLE || rtm->rtm_type == RTN_PROHIBIT || @@ -181,7 +181,7 @@ Signed-off-by: Jonas Gorski cfg->fc_flags |= RTF_REJECT; if (rtm->rtm_type == RTN_LOCAL) -@@ -3486,6 +3520,9 @@ static int rt6_fill_node(struct net *net +@@ -3487,6 +3521,9 @@ static int rt6_fill_node(struct net *net case -EACCES: rtm->rtm_type = RTN_PROHIBIT; break; @@ -191,7 +191,7 @@ Signed-off-by: Jonas Gorski case -EAGAIN: rtm->rtm_type = RTN_THROW; break; -@@ -3804,6 +3841,8 @@ static int ip6_route_dev_notify(struct n +@@ -3805,6 +3842,8 @@ static int ip6_route_dev_notify(struct n #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.ip6_prohibit_entry->dst.dev = dev; net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); @@ -200,7 +200,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.dev = dev; net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); #endif -@@ -4031,6 +4070,17 @@ static int __net_init ip6_route_net_init +@@ -4032,6 +4071,17 @@ static int __net_init ip6_route_net_init net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, ip6_template_metrics, true); @@ -218,7 +218,7 @@ Signed-off-by: Jonas Gorski #endif net->ipv6.sysctl.flush_delay = 0; -@@ -4049,6 +4099,8 @@ out: +@@ -4050,6 +4100,8 @@ out: return ret; #ifdef CONFIG_IPV6_MULTIPLE_TABLES @@ -227,7 +227,7 @@ Signed-off-by: Jonas Gorski out_ip6_prohibit_entry: kfree(net->ipv6.ip6_prohibit_entry); out_ip6_null_entry: -@@ -4066,6 +4118,7 @@ static void __net_exit ip6_route_net_exi +@@ -4067,6 +4119,7 @@ static void __net_exit ip6_route_net_exi #ifdef CONFIG_IPV6_MULTIPLE_TABLES kfree(net->ipv6.ip6_prohibit_entry); kfree(net->ipv6.ip6_blk_hole_entry); @@ -235,7 +235,7 @@ Signed-off-by: Jonas Gorski #endif dst_entries_destroy(&net->ipv6.ip6_dst_ops); } -@@ -4139,6 +4192,9 @@ void __init ip6_route_init_special_entri +@@ -4140,6 +4193,9 @@ void __init ip6_route_init_special_entri init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); diff --git a/target/linux/generic/pending-4.14/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/target/linux/generic/pending-4.14/680-NET-skip-GRO-for-foreign-MAC-addresses.patch index e7fb83cee..9ac505e85 100644 --- a/target/linux/generic/pending-4.14/680-NET-skip-GRO-for-foreign-MAC-addresses.patch +++ b/target/linux/generic/pending-4.14/680-NET-skip-GRO-for-foreign-MAC-addresses.patch @@ -22,7 +22,7 @@ Signed-off-by: Felix Fietkau #endif --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -780,6 +780,7 @@ struct sk_buff { +@@ -777,6 +777,7 @@ struct sk_buff { __u8 tc_redirected:1; __u8 tc_from_ingress:1; #endif @@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau __u16 tc_index; /* traffic control index */ --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -4757,6 +4757,9 @@ static enum gro_result dev_gro_receive(s +@@ -4783,6 +4783,9 @@ static enum gro_result dev_gro_receive(s enum gro_result ret; int grow; @@ -42,7 +42,7 @@ Signed-off-by: Felix Fietkau if (netif_elide_gro(skb->dev)) goto normal; -@@ -6227,6 +6230,48 @@ static void __netdev_adjacent_dev_unlink +@@ -6253,6 +6256,48 @@ static void __netdev_adjacent_dev_unlink &upper_dev->adj_list.lower); } @@ -91,16 +91,23 @@ Signed-off-by: Felix Fietkau static int __netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev, bool master, void *upper_priv, void *upper_info) -@@ -6342,6 +6387,8 @@ void netdev_upper_dev_unlink(struct net_ +@@ -6291,6 +6336,7 @@ static int __netdev_upper_dev_link(struc + if (ret) + return ret; + ++ netdev_update_addr_mask(dev); + ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev, + &changeupper_info.info); + ret = notifier_to_errno(ret); +@@ -6368,6 +6414,7 @@ void netdev_upper_dev_unlink(struct net_ __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); -+ netdev_update_addr_mask(dev); + netdev_update_addr_mask(dev); call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev, &changeupper_info.info); } -@@ -6912,6 +6959,7 @@ int dev_set_mac_address(struct net_devic +@@ -6938,6 +6985,7 @@ int dev_set_mac_address(struct net_devic if (err) return err; dev->addr_assign_type = NET_ADDR_SET; diff --git a/target/linux/generic/pending-4.14/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-4.14/703-phy-add-detach-callback-to-struct-phy_driver.patch index 3d5f8fc5e..11436a216 100644 --- a/target/linux/generic/pending-4.14/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/target/linux/generic/pending-4.14/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -1095,6 +1095,9 @@ void phy_detach(struct phy_device *phyde +@@ -1102,6 +1102,9 @@ void phy_detach(struct phy_device *phyde struct module *ndev_owner = dev->dev.parent->driver->owner; struct mii_bus *bus; diff --git a/target/linux/generic/pending-4.14/734-net-phy-at803x-allow-to-configure-via-pdata.patch b/target/linux/generic/pending-4.14/734-net-phy-at803x-allow-to-configure-via-pdata.patch index 19dea170c..a217f750b 100644 --- a/target/linux/generic/pending-4.14/734-net-phy-at803x-allow-to-configure-via-pdata.patch +++ b/target/linux/generic/pending-4.14/734-net-phy-at803x-allow-to-configure-via-pdata.patch @@ -48,7 +48,7 @@ Signed-off-by: Gabor Juhos }; struct at803x_context { -@@ -277,8 +285,16 @@ does_not_require_reset_workaround: +@@ -273,8 +281,16 @@ does_not_require_reset_workaround: return 0; } @@ -65,7 +65,7 @@ Signed-off-by: Gabor Juhos int ret; ret = genphy_config_init(phydev); -@@ -299,6 +315,26 @@ static int at803x_config_init(struct phy +@@ -295,6 +311,26 @@ static int at803x_config_init(struct phy return ret; } @@ -92,7 +92,7 @@ Signed-off-by: Gabor Juhos return 0; } -@@ -336,6 +372,8 @@ static int at803x_config_intr(struct phy +@@ -332,6 +368,8 @@ static int at803x_config_intr(struct phy static void at803x_link_change_notify(struct phy_device *phydev) { struct at803x_priv *priv = phydev->priv; @@ -101,7 +101,7 @@ Signed-off-by: Gabor Juhos /* * Conduct a hardware reset for AT8030/2 every time a link loss is -@@ -364,6 +402,24 @@ static void at803x_link_change_notify(st +@@ -360,6 +398,24 @@ static void at803x_link_change_notify(st } else { priv->phy_reset = false; } diff --git a/target/linux/generic/pending-4.14/735-net-phy-at803x-fix-at8033-sgmii-mode.patch b/target/linux/generic/pending-4.14/735-net-phy-at803x-fix-at8033-sgmii-mode.patch index 3c686623b..9a2f93a6f 100644 --- a/target/linux/generic/pending-4.14/735-net-phy-at803x-fix-at8033-sgmii-mode.patch +++ b/target/linux/generic/pending-4.14/735-net-phy-at803x-fix-at8033-sgmii-mode.patch @@ -24,7 +24,7 @@ Signed-off-by: Roman Yeryomin #define AT803X_MODE_CFG_MASK 0x0F #define AT803X_MODE_CFG_SGMII 0x01 -@@ -296,6 +300,27 @@ static int at803x_config_init(struct phy +@@ -292,6 +296,27 @@ static int at803x_config_init(struct phy { struct at803x_platform_data *pdata; int ret; diff --git a/target/linux/generic/pending-4.14/811-pci_disable_usb_common_quirks.patch b/target/linux/generic/pending-4.14/811-pci_disable_usb_common_quirks.patch index 005c25d04..410a26759 100644 --- a/target/linux/generic/pending-4.14/811-pci_disable_usb_common_quirks.patch +++ b/target/linux/generic/pending-4.14/811-pci_disable_usb_common_quirks.patch @@ -48,14 +48,11 @@ Signed-off-by: Felix Fietkau static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask) { u16 cmd; -@@ -1158,6 +1173,7 @@ static void quirk_usb_early_handoff(stru +@@ -1178,3 +1193,4 @@ bool usb_xhci_needs_pci_reset(struct pci + return false; } - DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_SERIAL_USB, 8, quirk_usb_early_handoff); + EXPORT_SYMBOL_GPL(usb_xhci_needs_pci_reset); +#endif - - bool usb_xhci_needs_pci_reset(struct pci_dev *pdev) - { --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h @@ -5,6 +5,9 @@ @@ -68,7 +65,7 @@ Signed-off-by: Felix Fietkau int usb_amd_find_chipset_info(void); int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev); bool usb_amd_hang_symptom_quirk(void); -@@ -19,12 +22,25 @@ void sb800_prefetch(struct device *dev, +@@ -19,12 +22,29 @@ void sb800_prefetch(struct device *dev, bool usb_xhci_needs_pci_reset(struct pci_dev *pdev); #else struct pci_dev; @@ -91,6 +88,10 @@ Signed-off-by: Felix Fietkau static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {} static inline void sb800_prefetch(struct device *dev, int on) {} +static inline void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev) {} ++static inline bool usb_xhci_needs_pci_reset(struct pci_dev *pdev) ++{ ++ return false; ++} #endif /* CONFIG_USB_PCI */ #endif /* __LINUX_USB_PCI_QUIRKS_H */ diff --git a/target/linux/generic/pending-4.14/821-usb-Remove-annoying-warning-about-bogus-URB.patch b/target/linux/generic/pending-4.14/821-usb-Remove-annoying-warning-about-bogus-URB.patch deleted file mode 100644 index c14e67959..000000000 --- a/target/linux/generic/pending-4.14/821-usb-Remove-annoying-warning-about-bogus-URB.patch +++ /dev/null @@ -1,76 +0,0 @@ -From: Alexey Brodkin -Subject: usb: Remove annoying warning about bogus URB - -When ath9k-htc Wi-Fi dongle is used with generic OHCI controller -infinite stream of warnings appears in debug console like this: --------------------------->8---------------------- -usb 1-1: new full-speed USB device number 2 using ohci-platform -usb 1-1: ath9k_htc: Firmware ath9k_htc/htc_9271-1.4.0.fw requested -usb 1-1: ath9k_htc: Transferred FW: ath9k_htc/htc_9271-1.4.0.fw, size: -51008 -------------[ cut here ]------------ -WARNING: CPU: 0 PID: 19 at drivers/usb/core/urb.c:449 -usb_submit_urb+0x1b4/0x498() -usb 1-1: BOGUS urb xfer, pipe 1 != type 3 -Modules linked in: -CPU: 0 PID: 19 Comm: kworker/0:1 Not tainted -4.4.0-rc4-00017-g00e2d79-dirty #3 -Workqueue: events request_firmware_work_func - -Stack Trace: - arc_unwind_core.constprop.1+0xa4/0x110 ----[ end trace 649ef8c342817fc2 ]--- -------------[ cut here ]------------ -WARNING: CPU: 0 PID: 19 at drivers/usb/core/urb.c:449 -usb_submit_urb+0x1b4/0x498() -usb 1-1: BOGUS urb xfer, pipe 1 != type 3 -Modules linked in: -CPU: 0 PID: 19 Comm: kworker/0:1 Tainted: G W -4.4.0-rc4-00017-g00e2d79-dirty #3 -Workqueue: events request_firmware_work_func - -Stack Trace: - arc_unwind_core.constprop.1+0xa4/0x110 ----[ end trace 649ef8c342817fc3 ]--- -------------[ cut here ]------------ --------------------------->8---------------------- - -There're some discussions in mailing lists proposing to disable -that particular check alltogether and magically all seem to work -fine with muted warning. - -Anyways new thread on that regard could be found here: -http://lists.infradead.org/pipermail/linux-snps-arc/2016-July/001310.html - -Let's see what comes out of that new discussion, hopefully patching -of generic USB stuff won't be required then. - -Signed-off-by: Alexey Brodkin ---- - drivers/usb/core/urb.c | 5 ----- - 1 file changed, 5 deletions(-) - ---- a/drivers/usb/core/urb.c -+++ b/drivers/usb/core/urb.c -@@ -326,9 +326,6 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb); - */ - int usb_submit_urb(struct urb *urb, gfp_t mem_flags) - { -- static int pipetypes[4] = { -- PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT -- }; - int xfertype, max; - struct usb_device *dev; - struct usb_host_endpoint *ep; -@@ -443,11 +440,6 @@ int usb_submit_urb(struct urb *urb, gfp_ - * cause problems in HCDs if they get it wrong. - */ - -- /* Check that the pipe's type matches the endpoint's type */ -- if (usb_pipetype(urb->pipe) != pipetypes[xfertype]) -- dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n", -- usb_pipetype(urb->pipe), pipetypes[xfertype]); -- - /* Check against a simple/standard policy */ - allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT | URB_DIR_MASK | - URB_FREE_BUFFER); diff --git a/target/linux/generic/pending-4.14/834-ledtrig-libata.patch b/target/linux/generic/pending-4.14/834-ledtrig-libata.patch index 8597a936f..83bc42fe3 100644 --- a/target/linux/generic/pending-4.14/834-ledtrig-libata.patch +++ b/target/linux/generic/pending-4.14/834-ledtrig-libata.patch @@ -65,7 +65,7 @@ Signed-off-by: Daniel Golle /** * ata_build_rw_tf - Build ATA taskfile for given read/write request * @tf: Target ATA taskfile -@@ -5089,6 +5102,9 @@ struct ata_queued_cmd *ata_qc_new_init(s +@@ -5111,6 +5124,9 @@ struct ata_queued_cmd *ata_qc_new_init(s if (tag < 0) return NULL; } @@ -75,7 +75,7 @@ Signed-off-by: Daniel Golle qc = __ata_qc_from_tag(ap, tag); qc->tag = tag; -@@ -5991,6 +6007,9 @@ struct ata_port *ata_port_alloc(struct a +@@ -6012,6 +6028,9 @@ struct ata_port *ata_port_alloc(struct a ap->stats.unhandled_irq = 1; ap->stats.idle_irq = 1; #endif @@ -85,7 +85,7 @@ Signed-off-by: Daniel Golle ata_sff_port_init(ap); return ap; -@@ -6012,6 +6031,12 @@ static void ata_host_release(struct devi +@@ -6033,6 +6052,12 @@ static void ata_host_release(struct devi kfree(ap->pmp_link); kfree(ap->slave_link); @@ -98,7 +98,7 @@ Signed-off-by: Daniel Golle kfree(ap); host->ports[i] = NULL; } -@@ -6458,7 +6483,23 @@ int ata_host_register(struct ata_host *h +@@ -6479,7 +6504,23 @@ int ata_host_register(struct ata_host *h host->ports[i]->print_id = atomic_inc_return(&ata_print_id); host->ports[i]->local_port_no = i + 1; } diff --git a/target/linux/generic/pending-4.14/920-mangle_bootargs.patch b/target/linux/generic/pending-4.14/920-mangle_bootargs.patch index ec5ec6b52..adeb9f12f 100644 --- a/target/linux/generic/pending-4.14/920-mangle_bootargs.patch +++ b/target/linux/generic/pending-4.14/920-mangle_bootargs.patch @@ -13,7 +13,7 @@ Signed-off-by: Imre Kaloz --- a/init/Kconfig +++ b/init/Kconfig -@@ -1420,6 +1420,15 @@ config EMBEDDED +@@ -1427,6 +1427,15 @@ config EMBEDDED an embedded system so certain expert options are available for configuration. @@ -31,7 +31,7 @@ Signed-off-by: Imre Kaloz help --- a/init/main.c +++ b/init/main.c -@@ -360,6 +360,29 @@ static inline void setup_nr_cpu_ids(void +@@ -359,6 +359,29 @@ static inline void setup_nr_cpu_ids(void static inline void smp_prepare_cpus(unsigned int maxcpus) { } #endif @@ -61,7 +61,7 @@ Signed-off-by: Imre Kaloz /* * We need to store the untouched command line for future reference. * We also need to store the touched command line since the parameter -@@ -541,6 +564,7 @@ asmlinkage __visible void __init start_k +@@ -540,6 +563,7 @@ asmlinkage __visible void __init start_k add_device_randomness(command_line, strlen(command_line)); boot_init_stack_canary(); mm_init_cpumask(&init_mm); diff --git a/target/linux/generic/pending-4.4/030-2-smsc75xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/pending-4.4/030-2-smsc75xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch deleted file mode 100644 index 6312f0f73..000000000 --- a/target/linux/generic/pending-4.4/030-2-smsc75xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch +++ /dev/null @@ -1,36 +0,0 @@ -From b7c6d2675899cfff0180412c63fc9cbd5bacdb4d Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Wed, 19 Apr 2017 09:59:21 -0700 -Subject: [PATCH] smsc75xx: use skb_cow_head() to deal with cloned skbs - -We need to ensure there is enough headroom to push extra header, -but we also need to check if we are allowed to change headers. - -skb_cow_head() is the proper helper to deal with this. - -Fixes: d0cad871703b ("smsc75xx: SMSC LAN75xx USB gigabit ethernet adapter driver") -Signed-off-by: Eric Dumazet -Cc: James Hughes -Signed-off-by: David S. Miller ---- - drivers/net/usb/smsc75xx.c | 8 ++------ - 1 file changed, 2 insertions(+), 6 deletions(-) - ---- a/drivers/net/usb/smsc75xx.c -+++ b/drivers/net/usb/smsc75xx.c -@@ -2193,13 +2193,9 @@ static struct sk_buff *smsc75xx_tx_fixup - { - u32 tx_cmd_a, tx_cmd_b; - -- if (skb_headroom(skb) < SMSC75XX_TX_OVERHEAD) { -- struct sk_buff *skb2 = -- skb_copy_expand(skb, SMSC75XX_TX_OVERHEAD, 0, flags); -+ if (skb_cow_head(skb, SMSC75XX_TX_OVERHEAD)) { - dev_kfree_skb_any(skb); -- skb = skb2; -- if (!skb) -- return NULL; -+ return NULL; - } - - tx_cmd_a = (u32)(skb->len & TX_CMD_A_LEN) | TX_CMD_A_FCS; diff --git a/target/linux/generic/pending-4.4/030-3-cx82310_eth-use-skb_cow_head-to-deal-with-cloned-skb.patch b/target/linux/generic/pending-4.4/030-3-cx82310_eth-use-skb_cow_head-to-deal-with-cloned-skb.patch deleted file mode 100644 index aee8aa980..000000000 --- a/target/linux/generic/pending-4.4/030-3-cx82310_eth-use-skb_cow_head-to-deal-with-cloned-skb.patch +++ /dev/null @@ -1,35 +0,0 @@ -From a9e840a2081ed28c2b7caa6a9a0041c950b3c37d Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Wed, 19 Apr 2017 09:59:22 -0700 -Subject: [PATCH] cx82310_eth: use skb_cow_head() to deal with cloned skbs - -We need to ensure there is enough headroom to push extra header, -but we also need to check if we are allowed to change headers. - -skb_cow_head() is the proper helper to deal with this. - -Fixes: cc28a20e77b2 ("introduce cx82310_eth: Conexant CX82310-based ADSL router USB ethernet driver") -Signed-off-by: Eric Dumazet -Cc: James Hughes -Signed-off-by: David S. Miller ---- - drivers/net/usb/cx82310_eth.c | 7 ++----- - 1 file changed, 2 insertions(+), 5 deletions(-) - ---- a/drivers/net/usb/cx82310_eth.c -+++ b/drivers/net/usb/cx82310_eth.c -@@ -293,12 +293,9 @@ static struct sk_buff *cx82310_tx_fixup( - { - int len = skb->len; - -- if (skb_headroom(skb) < 2) { -- struct sk_buff *skb2 = skb_copy_expand(skb, 2, 0, flags); -+ if (skb_cow_head(skb, 2)) { - dev_kfree_skb_any(skb); -- skb = skb2; -- if (!skb) -- return NULL; -+ return NULL; - } - skb_push(skb, 2); - diff --git a/target/linux/generic/pending-4.4/030-4-sr9700-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/pending-4.4/030-4-sr9700-use-skb_cow_head-to-deal-with-cloned-skbs.patch deleted file mode 100644 index 4d0fcf6fc..000000000 --- a/target/linux/generic/pending-4.4/030-4-sr9700-use-skb_cow_head-to-deal-with-cloned-skbs.patch +++ /dev/null @@ -1,37 +0,0 @@ -From d532c1082f68176363ed766d09bf187616e282fe Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Wed, 19 Apr 2017 09:59:23 -0700 -Subject: [PATCH] sr9700: use skb_cow_head() to deal with cloned skbs - -We need to ensure there is enough headroom to push extra header, -but we also need to check if we are allowed to change headers. - -skb_cow_head() is the proper helper to deal with this. - -Fixes: c9b37458e956 ("USB2NET : SR9700 : One chip USB 1.1 USB2NET SR9700Device Driver Support") -Signed-off-by: Eric Dumazet -Cc: James Hughes -Signed-off-by: David S. Miller ---- - drivers/net/usb/sr9700.c | 9 ++------- - 1 file changed, 2 insertions(+), 7 deletions(-) - ---- a/drivers/net/usb/sr9700.c -+++ b/drivers/net/usb/sr9700.c -@@ -456,14 +456,9 @@ static struct sk_buff *sr9700_tx_fixup(s - - len = skb->len; - -- if (skb_headroom(skb) < SR_TX_OVERHEAD) { -- struct sk_buff *skb2; -- -- skb2 = skb_copy_expand(skb, SR_TX_OVERHEAD, 0, flags); -+ if (skb_cow_head(skb, SR_TX_OVERHEAD)) { - dev_kfree_skb_any(skb); -- skb = skb2; -- if (!skb) -- return NULL; -+ return NULL; - } - - __skb_push(skb, SR_TX_OVERHEAD); diff --git a/target/linux/generic/pending-4.4/030-5-lan78xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/target/linux/generic/pending-4.4/030-5-lan78xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch deleted file mode 100644 index 4f9604164..000000000 --- a/target/linux/generic/pending-4.4/030-5-lan78xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch +++ /dev/null @@ -1,38 +0,0 @@ -From d4ca73591916b760478d2b04334d5dcadc028e9c Mon Sep 17 00:00:00 2001 -From: Eric Dumazet -Date: Wed, 19 Apr 2017 09:59:24 -0700 -Subject: [PATCH] lan78xx: use skb_cow_head() to deal with cloned skbs - -We need to ensure there is enough headroom to push extra header, -but we also need to check if we are allowed to change headers. - -skb_cow_head() is the proper helper to deal with this. - -Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver") -Signed-off-by: Eric Dumazet -Cc: James Hughes -Cc: Woojung Huh -Signed-off-by: David S. Miller ---- - drivers/net/usb/lan78xx.c | 9 ++------- - 1 file changed, 2 insertions(+), 7 deletions(-) - ---- a/drivers/net/usb/lan78xx.c -+++ b/drivers/net/usb/lan78xx.c -@@ -2050,14 +2050,9 @@ static struct sk_buff *lan78xx_tx_prep(s - { - u32 tx_cmd_a, tx_cmd_b; - -- if (skb_headroom(skb) < TX_OVERHEAD) { -- struct sk_buff *skb2; -- -- skb2 = skb_copy_expand(skb, TX_OVERHEAD, 0, flags); -+ if (skb_cow_head(skb, TX_OVERHEAD)) { - dev_kfree_skb_any(skb); -- skb = skb2; -- if (!skb) -- return NULL; -+ return NULL; - } - - if (lan78xx_linearize(skb) < 0) diff --git a/target/linux/generic/pending-4.4/067-v4.11-mtd-nand-Add-Winbond-manufacturer-id.patch b/target/linux/generic/pending-4.4/067-v4.11-mtd-nand-Add-Winbond-manufacturer-id.patch new file mode 100644 index 000000000..d102d89b2 --- /dev/null +++ b/target/linux/generic/pending-4.4/067-v4.11-mtd-nand-Add-Winbond-manufacturer-id.patch @@ -0,0 +1,34 @@ +From a4077ce5871304f8a78f80b74b18b6052a410f1a Mon Sep 17 00:00:00 2001 +From: "Andrey Jr. Melnikov" +Date: Thu, 8 Dec 2016 19:57:08 +0300 +Subject: [PATCH] mtd: nand: Add Winbond manufacturer id + +Add WINBOND manufacturer id. + +Signed-off-by: Andrey Jr. Melnikov +Signed-off-by: Boris Brezillon +--- + drivers/mtd/nand/nand_ids.c | 1 + + include/linux/mtd/nand.h | 1 + + 2 files changed, 2 insertions(+) + +--- a/drivers/mtd/nand/nand_ids.c ++++ b/drivers/mtd/nand/nand_ids.c +@@ -181,6 +181,7 @@ struct nand_manufacturers nand_manuf_ids + {NAND_MFR_SANDISK, "SanDisk"}, + {NAND_MFR_INTEL, "Intel"}, + {NAND_MFR_ATO, "ATO"}, ++ {NAND_MFR_WINBOND, "Winbond"}, + {0x0, "Unknown"} + }; + +--- a/include/linux/mtd/nand.h ++++ b/include/linux/mtd/nand.h +@@ -736,6 +736,7 @@ struct nand_chip { + #define NAND_MFR_SANDISK 0x45 + #define NAND_MFR_INTEL 0x89 + #define NAND_MFR_ATO 0x9b ++#define NAND_MFR_WINBOND 0xef + + /* The maximum expected count of bytes in the NAND ID sequence */ + #define NAND_MAX_ID_LEN 8 diff --git a/target/linux/generic/pending-4.4/450-mtd-nand-allow-to-use-platform-specific-chip-fixup.patch b/target/linux/generic/pending-4.4/450-mtd-nand-allow-to-use-platform-specific-chip-fixup.patch index 3ce7f13dc..b1072047c 100644 --- a/target/linux/generic/pending-4.4/450-mtd-nand-allow-to-use-platform-specific-chip-fixup.patch +++ b/target/linux/generic/pending-4.4/450-mtd-nand-allow-to-use-platform-specific-chip-fixup.patch @@ -5,7 +5,7 @@ --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h -@@ -863,6 +863,7 @@ struct platform_nand_chip { +@@ -864,6 +864,7 @@ struct platform_nand_chip { unsigned int options; unsigned int bbt_options; const char **part_probe_types; diff --git a/target/linux/generic/pending-4.4/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch b/target/linux/generic/pending-4.4/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch index c402e0429..303d83121 100644 --- a/target/linux/generic/pending-4.4/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch +++ b/target/linux/generic/pending-4.4/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch @@ -296,7 +296,7 @@ Signed-off-by: Steven Barth __skb_tunnel_rx(skb, t->dev, t->net); -@@ -1247,6 +1384,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str +@@ -1248,6 +1385,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str __u32 mtu; u8 tproto; int err; @@ -304,7 +304,7 @@ Signed-off-by: Steven Barth tproto = ACCESS_ONCE(t->parms.proto); if ((tproto != IPPROTO_IPV6 && tproto != 0) || -@@ -1277,6 +1415,18 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str +@@ -1278,6 +1416,18 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) fl6.flowi6_mark = skb->mark; @@ -323,7 +323,7 @@ Signed-off-by: Steven Barth err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); if (err != 0) { if (err == -EMSGSIZE) -@@ -1391,6 +1541,14 @@ ip6_tnl_change(struct ip6_tnl *t, const +@@ -1392,6 +1542,14 @@ ip6_tnl_change(struct ip6_tnl *t, const t->parms.flowinfo = p->flowinfo; t->parms.link = p->link; t->parms.proto = p->proto; @@ -338,7 +338,7 @@ Signed-off-by: Steven Barth ip6_tnl_dst_reset(t); ip6_tnl_link_config(t); return 0; -@@ -1429,6 +1587,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_ +@@ -1430,6 +1588,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_ p->flowinfo = u->flowinfo; p->link = u->link; p->proto = u->proto; @@ -346,7 +346,7 @@ Signed-off-by: Steven Barth memcpy(p->name, u->name, sizeof(u->name)); } -@@ -1724,6 +1883,15 @@ static int ip6_tnl_validate(struct nlatt +@@ -1725,6 +1884,15 @@ static int ip6_tnl_validate(struct nlatt return 0; } @@ -362,7 +362,7 @@ Signed-off-by: Steven Barth static void ip6_tnl_netlink_parms(struct nlattr *data[], struct __ip6_tnl_parm *parms) { -@@ -1755,6 +1923,46 @@ static void ip6_tnl_netlink_parms(struct +@@ -1756,6 +1924,46 @@ static void ip6_tnl_netlink_parms(struct if (data[IFLA_IPTUN_PROTO]) parms->proto = nla_get_u8(data[IFLA_IPTUN_PROTO]); @@ -409,7 +409,7 @@ Signed-off-by: Steven Barth } static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev, -@@ -1807,6 +2015,12 @@ static void ip6_tnl_dellink(struct net_d +@@ -1808,6 +2016,12 @@ static void ip6_tnl_dellink(struct net_d static size_t ip6_tnl_get_size(const struct net_device *dev) { @@ -422,7 +422,7 @@ Signed-off-by: Steven Barth return /* IFLA_IPTUN_LINK */ nla_total_size(4) + -@@ -1824,6 +2038,24 @@ static size_t ip6_tnl_get_size(const str +@@ -1825,6 +2039,24 @@ static size_t ip6_tnl_get_size(const str nla_total_size(4) + /* IFLA_IPTUN_PROTO */ nla_total_size(1) + @@ -447,7 +447,7 @@ Signed-off-by: Steven Barth 0; } -@@ -1831,6 +2063,9 @@ static int ip6_tnl_fill_info(struct sk_b +@@ -1832,6 +2064,9 @@ static int ip6_tnl_fill_info(struct sk_b { struct ip6_tnl *tunnel = netdev_priv(dev); struct __ip6_tnl_parm *parm = &tunnel->parms; @@ -457,7 +457,7 @@ Signed-off-by: Steven Barth if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) || nla_put_in6_addr(skb, IFLA_IPTUN_LOCAL, &parm->laddr) || -@@ -1839,8 +2074,27 @@ static int ip6_tnl_fill_info(struct sk_b +@@ -1840,8 +2075,27 @@ static int ip6_tnl_fill_info(struct sk_b nla_put_u8(skb, IFLA_IPTUN_ENCAP_LIMIT, parm->encap_limit) || nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) || nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags) || @@ -486,7 +486,7 @@ Signed-off-by: Steven Barth return 0; nla_put_failure: -@@ -1864,6 +2118,7 @@ static const struct nla_policy ip6_tnl_p +@@ -1865,6 +2119,7 @@ static const struct nla_policy ip6_tnl_p [IFLA_IPTUN_FLOWINFO] = { .type = NLA_U32 }, [IFLA_IPTUN_FLAGS] = { .type = NLA_U32 }, [IFLA_IPTUN_PROTO] = { .type = NLA_U8 }, diff --git a/target/linux/generic/pending-4.4/701-phy_extension.patch b/target/linux/generic/pending-4.4/701-phy_extension.patch index 6cb3fdfd4..39b8fd466 100644 --- a/target/linux/generic/pending-4.4/701-phy_extension.patch +++ b/target/linux/generic/pending-4.4/701-phy_extension.patch @@ -53,7 +53,7 @@ * @phydev: the phy_device struct --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -796,6 +796,7 @@ void phy_start_machine(struct phy_device +@@ -807,6 +807,7 @@ void phy_start_machine(struct phy_device void phy_stop_machine(struct phy_device *phydev); int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd); int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd); diff --git a/target/linux/generic/pending-4.4/710-phy-add-mdio_register_board_info.patch b/target/linux/generic/pending-4.4/710-phy-add-mdio_register_board_info.patch index 4886dd0e3..d78f3d48a 100644 --- a/target/linux/generic/pending-4.4/710-phy-add-mdio_register_board_info.patch +++ b/target/linux/generic/pending-4.4/710-phy-add-mdio_register_board_info.patch @@ -46,7 +46,7 @@ phy_device_free(phydev); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -835,6 +835,23 @@ void mdio_bus_exit(void); +@@ -846,6 +846,23 @@ void mdio_bus_exit(void); extern struct bus_type mdio_bus_type; diff --git a/target/linux/generic/pending-4.4/902-debloat_proc.patch b/target/linux/generic/pending-4.4/902-debloat_proc.patch index f7718bc5b..4f874e598 100644 --- a/target/linux/generic/pending-4.4/902-debloat_proc.patch +++ b/target/linux/generic/pending-4.4/902-debloat_proc.patch @@ -1,6 +1,6 @@ --- a/fs/locks.c +++ b/fs/locks.c -@@ -2712,6 +2712,8 @@ static const struct file_operations proc +@@ -2716,6 +2716,8 @@ static const struct file_operations proc static int __init proc_locks_init(void) { diff --git a/target/linux/generic/pending-4.4/904-debloat_dma_buf.patch b/target/linux/generic/pending-4.4/904-debloat_dma_buf.patch index eac39669d..b9fdad9c1 100644 --- a/target/linux/generic/pending-4.4/904-debloat_dma_buf.patch +++ b/target/linux/generic/pending-4.4/904-debloat_dma_buf.patch @@ -1,6 +1,6 @@ --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig -@@ -229,7 +229,7 @@ config SOC_BUS +@@ -232,7 +232,7 @@ config SOC_BUS source "drivers/base/regmap/Kconfig" config DMA_SHARED_BUFFER diff --git a/target/linux/generic/pending-4.9/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch b/target/linux/generic/pending-4.9/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch index 1c5b9c3b2..e1c1de360 100644 --- a/target/linux/generic/pending-4.9/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch +++ b/target/linux/generic/pending-4.9/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch @@ -39,7 +39,7 @@ Signed-off-by: Felix Fietkau depends on ARCH_AT91 || (ARM && COMPILE_TEST) --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -1640,10 +1640,12 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -1642,10 +1642,12 @@ int spi_nor_scan(struct spi_nor *nor, co #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS /* prefer "small sector" erase if possible */ diff --git a/target/linux/generic/pending-4.9/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch b/target/linux/generic/pending-4.9/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch index ee58c2c5e..0941b79b6 100644 --- a/target/linux/generic/pending-4.9/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch +++ b/target/linux/generic/pending-4.9/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch @@ -300,7 +300,7 @@ Signed-off-by: Steven Barth /** * ip6_tnl_addr_conflict - compare packet addresses to tunnel's own * @t: the outgoing tunnel device -@@ -1286,6 +1426,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str +@@ -1287,6 +1427,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str { struct ip6_tnl *t = netdev_priv(dev); struct ipv6hdr *ipv6h = ipv6_hdr(skb); @@ -308,7 +308,7 @@ Signed-off-by: Steven Barth int encap_limit = -1; __u16 offset; struct flowi6 fl6; -@@ -1344,6 +1485,18 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str +@@ -1345,6 +1486,18 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str fl6.flowi6_mark = skb->mark; } @@ -327,7 +327,7 @@ Signed-off-by: Steven Barth if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) return -1; -@@ -1471,6 +1624,14 @@ ip6_tnl_change(struct ip6_tnl *t, const +@@ -1472,6 +1625,14 @@ ip6_tnl_change(struct ip6_tnl *t, const t->parms.flowinfo = p->flowinfo; t->parms.link = p->link; t->parms.proto = p->proto; @@ -342,7 +342,7 @@ Signed-off-by: Steven Barth dst_cache_reset(&t->dst_cache); ip6_tnl_link_config(t); return 0; -@@ -1509,6 +1670,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_ +@@ -1510,6 +1671,7 @@ ip6_tnl_parm_from_user(struct __ip6_tnl_ p->flowinfo = u->flowinfo; p->link = u->link; p->proto = u->proto; @@ -350,7 +350,7 @@ Signed-off-by: Steven Barth memcpy(p->name, u->name, sizeof(u->name)); } -@@ -1886,6 +2048,15 @@ static int ip6_tnl_validate(struct nlatt +@@ -1887,6 +2049,15 @@ static int ip6_tnl_validate(struct nlatt return 0; } @@ -366,7 +366,7 @@ Signed-off-by: Steven Barth static void ip6_tnl_netlink_parms(struct nlattr *data[], struct __ip6_tnl_parm *parms) { -@@ -1920,6 +2091,46 @@ static void ip6_tnl_netlink_parms(struct +@@ -1921,6 +2092,46 @@ static void ip6_tnl_netlink_parms(struct if (data[IFLA_IPTUN_COLLECT_METADATA]) parms->collect_md = true; @@ -413,7 +413,7 @@ Signed-off-by: Steven Barth } static bool ip6_tnl_netlink_encap_parms(struct nlattr *data[], -@@ -2029,6 +2240,12 @@ static void ip6_tnl_dellink(struct net_d +@@ -2030,6 +2241,12 @@ static void ip6_tnl_dellink(struct net_d static size_t ip6_tnl_get_size(const struct net_device *dev) { @@ -426,7 +426,7 @@ Signed-off-by: Steven Barth return /* IFLA_IPTUN_LINK */ nla_total_size(4) + -@@ -2056,6 +2273,24 @@ static size_t ip6_tnl_get_size(const str +@@ -2057,6 +2274,24 @@ static size_t ip6_tnl_get_size(const str nla_total_size(2) + /* IFLA_IPTUN_COLLECT_METADATA */ nla_total_size(0) + @@ -451,7 +451,7 @@ Signed-off-by: Steven Barth 0; } -@@ -2063,6 +2298,9 @@ static int ip6_tnl_fill_info(struct sk_b +@@ -2064,6 +2299,9 @@ static int ip6_tnl_fill_info(struct sk_b { struct ip6_tnl *tunnel = netdev_priv(dev); struct __ip6_tnl_parm *parm = &tunnel->parms; @@ -461,7 +461,7 @@ Signed-off-by: Steven Barth if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) || nla_put_in6_addr(skb, IFLA_IPTUN_LOCAL, &parm->laddr) || -@@ -2071,9 +2309,27 @@ static int ip6_tnl_fill_info(struct sk_b +@@ -2072,9 +2310,27 @@ static int ip6_tnl_fill_info(struct sk_b nla_put_u8(skb, IFLA_IPTUN_ENCAP_LIMIT, parm->encap_limit) || nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) || nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags) || @@ -490,7 +490,7 @@ Signed-off-by: Steven Barth if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE, tunnel->encap.type) || nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT, tunnel->encap.sport) || nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT, tunnel->encap.dport) || -@@ -2111,6 +2367,7 @@ static const struct nla_policy ip6_tnl_p +@@ -2112,6 +2368,7 @@ static const struct nla_policy ip6_tnl_p [IFLA_IPTUN_ENCAP_SPORT] = { .type = NLA_U16 }, [IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 }, [IFLA_IPTUN_COLLECT_METADATA] = { .type = NLA_FLAG }, diff --git a/target/linux/generic/pending-4.9/701-phy_extension.patch b/target/linux/generic/pending-4.9/701-phy_extension.patch index b480b1d78..4569336bf 100644 --- a/target/linux/generic/pending-4.9/701-phy_extension.patch +++ b/target/linux/generic/pending-4.9/701-phy_extension.patch @@ -62,7 +62,7 @@ Signed-off-by: John Crispin * @phydev: the phy_device struct --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -816,6 +816,7 @@ int phy_ethtool_ksettings_get(struct phy +@@ -827,6 +827,7 @@ int phy_ethtool_ksettings_get(struct phy struct ethtool_link_ksettings *cmd); int phy_ethtool_ksettings_set(struct phy_device *phydev, const struct ethtool_link_ksettings *cmd); diff --git a/target/linux/ipq40xx/Makefile b/target/linux/ipq40xx/Makefile new file mode 100644 index 000000000..e5bbdf40c --- /dev/null +++ b/target/linux/ipq40xx/Makefile @@ -0,0 +1,21 @@ +include $(TOPDIR)/rules.mk + +ARCH:=arm +BOARD:=ipq40xx +BOARDNAME:=Qualcomm Atheros IPQ40XX +FEATURES:=squashfs fpu ramdisk nand +CPU_TYPE:=cortex-a7 +CPU_SUBTYPE:=neon-vfpv4 +MAINTAINER:=John Crispin + +KERNEL_PATCHVER:=4.14 + +KERNELNAME:=zImage Image dtbs + +include $(INCLUDE_DIR)/target.mk +DEFAULT_PACKAGES += \ + kmod-leds-gpio kmod-gpio-button-hotplug swconfig \ + kmod-ath10k wpad-mini \ + kmod-usb3 kmod-usb-dwc3-of-simple kmod-usb-phy-qcom-dwc3 \ + +$(eval $(call BuildTarget)) diff --git a/target/linux/ipq40xx/base-files/etc/board.d/01_leds b/target/linux/ipq40xx/base-files/etc/board.d/01_leds new file mode 100755 index 000000000..9771fa391 --- /dev/null +++ b/target/linux/ipq40xx/base-files/etc/board.d/01_leds @@ -0,0 +1,48 @@ +#!/bin/sh +# +# Copyright (C) 2015 OpenWrt.org +# + +. /lib/functions/uci-defaults.sh + +board_config_update + +board=$(board_name) +boardname="${board##*,}" + +case "$board" in +asus,rt-ac58u) + ucidef_set_led_wlan "wlan2g" "WLAN2G" "${boardname}:blue:wlan2G" "phy0tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "${boardname}:blue:wlan5G" "phy1tpt" + ucidef_set_led_usbport "usb" "USB" "${boardname}:blue:usb" "usb1-port1" "usb2-port1" "usb3-port1" "usb4-port1" + ucidef_set_led_switch "wan" "WAN" "${boardname}:blue:wan" "switch0" "0x20" + ucidef_set_led_switch "lan" "LAN" "${boardname}:blue:lan" "switch0" "0x1e" + ;; +asus,rt-acrh17) + ucidef_set_led_default "status" "STATUS" "${boardname}:blue:status" "1" + ucidef_set_led_wlan "wlan2g" "WLAN2G" "${boardname}:blue:wlan2g" "phy1tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "${boardname}:blue:wlan5g" "phy0tpt" + ucidef_set_led_switch "wan" "WAN(blue)" "${boardname}:blue:wan" "switch0" "0x20" + ucidef_set_led_switch "lan1" "LAN1" "${boardname}:blue:lan1" "switch0" "0x02" + ucidef_set_led_switch "lan2" "LAN2" "${boardname}:blue:lan2" "switch0" "0x04" + ucidef_set_led_switch "lan3" "LAN3" "${boardname}:blue:lan3" "switch0" "0x08" + ucidef_set_led_switch "lan4" "LAN4" "${boardname}:blue:lan4" "switch0" "0x10" + ;; +avm,fritzbox-4040) + ucidef_set_led_wlan "wlan" "WLAN" "fritz4040:green:wlan" "phy0tpt" "phy1tpt" + ucidef_set_led_switch "wan" "WAN" "fritz4040:green:wan" "switch0" "0x20" + ucidef_set_led_switch "lan" "LAN" "fritz4040:green:lan" "switch0" "0x1e" + ;; +glinet,gl-b1300) + ucidef_set_led_wlan "wlan" "WLAN" "${boardname}:green:wlan" "phy0tpt" + ;; +meraki,mr33) + ucidef_set_interface_lan "eth0" + ;; +*) + ;; +esac + +board_config_flush + +exit 0 diff --git a/target/linux/ipq40xx/base-files/etc/board.d/02_network b/target/linux/ipq40xx/base-files/etc/board.d/02_network new file mode 100755 index 000000000..081681efe --- /dev/null +++ b/target/linux/ipq40xx/base-files/etc/board.d/02_network @@ -0,0 +1,57 @@ +#!/bin/sh +# +# Copyright (c) 2015 The Linux Foundation. All rights reserved. +# Copyright (c) 2011-2015 OpenWrt.org +# + +. /lib/functions/uci-defaults.sh +. /lib/functions/system.sh + +board_config_update + +board=$(board_name) + +case "$board" in +asus,rt-ac58u) + CI_UBIPART=UBI_DEV + wan_mac_addr=$(mtd_get_mac_binary_ubi Factory 20486) + lan_mac_addr=$(mtd_get_mac_binary_ubi Factory 4102) + ucidef_add_switch "switch0" \ + "0t@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "5:wan" + ucidef_set_interface_macaddr "lan" "$lan_mac_addr" + ucidef_set_interface_macaddr "wan" "$wan_mac_addr" + ;; +asus,rt-acrh17) + CI_UBIPART=UBI_DEV + lan_mac_addr=$(mtd_get_mac_binary_ubi Factory 4102) + wan_mac_addr=$(mtd_get_mac_binary_ubi Factory 36870) + ucidef_add_switch "switch0" \ + "0t@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "5:wan" + ucidef_set_interface_macaddr "lan" "$lan_mac_addr" + ucidef_set_interface_macaddr "wan" "$wan_mac_addr" + ;; +avm,fritzbox-4040) + ucidef_add_switch "switch0" \ + "0t@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "5:wan" + ;; +glinet,gl-b1300) + ucidef_add_switch "switch0" \ + "0t@eth0" "3:lan" "4:lan" "5:wan" + ;; +compex,wpj428|\ +openmesh,a42) + ucidef_add_switch "switch0" \ + "0t@eth0" "4:lan" "5:wan" + ;; + +meraki,mr33) + ucidef_set_interface_lan "eth0" + ;; +*) + echo "Unsupported hardware. Network interfaces not intialized" + ;; +esac + +board_config_flush + +exit 0 diff --git a/target/linux/ipq40xx/base-files/etc/board.d/03_gpio_switches b/target/linux/ipq40xx/base-files/etc/board.d/03_gpio_switches new file mode 100755 index 000000000..4e306a94a --- /dev/null +++ b/target/linux/ipq40xx/base-files/etc/board.d/03_gpio_switches @@ -0,0 +1,17 @@ +#!/bin/sh + +. /lib/functions/uci-defaults.sh + +board_config_update + +board=$(board_name) + +case "$board" in +compex,wpj428) + ucidef_add_gpio_switch "sim_card_select" "SIM card select" "3" "0" + ;; +esac + +board_config_flush + +exit 0 diff --git a/target/linux/ipq40xx/base-files/etc/diag.sh b/target/linux/ipq40xx/base-files/etc/diag.sh new file mode 100755 index 000000000..4cfe6325f --- /dev/null +++ b/target/linux/ipq40xx/base-files/etc/diag.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +. /lib/functions/leds.sh + +boot="$(get_dt_led boot)" +failsafe="$(get_dt_led failsafe)" +running="$(get_dt_led running)" +upgrade="$(get_dt_led upgrade)" + +set_state() { + status_led="$boot" + + case "$1" in + preinit) + status_led_blink_preinit + ;; + failsafe) + status_led_off + [ -n "$running" ] && { + status_led="$running" + status_led_off + } + status_led="$failsafe" + status_led_blink_failsafe + ;; + preinit_regular) + status_led_blink_preinit_regular + ;; + upgrade) + [ -n "$running" ] && { + status_led="$upgrade" + status_led_blink_preinit_regular + } + ;; + done) + status_led_off + [ -n "$running" ] && { + status_led="$running" + status_led_on + } + ;; + esac +} diff --git a/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata new file mode 100644 index 000000000..b4640c91b --- /dev/null +++ b/target/linux/ipq40xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata @@ -0,0 +1,173 @@ +#!/bin/sh + +# xor multiple hex values of the same length +xor() { + local val + local ret="0x$1" + local retlen=${#1} + + shift + while [ -n "$1" ]; do + val="0x$1" + ret=$((ret ^ val)) + shift + done + + printf "%0${retlen}x" "$ret" +} + +ath10kcal_die() { + echo "ath10cal: " "$*" + exit 1 +} + +ath10kcal_extract() { + local part=$1 + local offset=$2 + local count=$3 + local mtd + + mtd=$(find_mtd_chardev $part) + [ -n "$mtd" ] || \ + ath10kcal_die "no mtd device found for partition $part" + + dd if=$mtd of=/lib/firmware/$FIRMWARE bs=1 skip=$offset count=$count 2>/dev/null || \ + ath10kcal_die "failed to extract calibration data from $mtd" +} + +ath10kcal_ubi_extract() { + local part=$1 + local offset=$2 + local count=$3 + local ubidev + local ubi + + . /lib/upgrade/nand.sh + + ubidev=$(nand_find_ubi $CI_UBIPART) + ubi=$(nand_find_volume $ubidev $part) + [ -n "$ubi" ] || \ + ath10kcal_die "no UBI volume found for $part" + + dd if=/dev/$ubi of=/lib/firmware/$FIRMWARE bs=1 skip=$offset count=$count 2>/dev/null || \ + ath10kcal_die "failed to extract from $ubi" +} + +ath10kcal_patch_mac() { + local mac=$1 + + [ -z "$mac" ] && return + + macaddr_2bin $mac | dd of=/lib/firmware/$FIRMWARE conv=notrunc bs=1 seek=6 count=6 +} + +ath10kcal_patch_mac_crc() { + local mac=$1 + local mac_offset=6 + local chksum_offset=2 + local xor_mac + local xor_fw_mac + local xor_fw_chksum + + xor_fw_mac=$(hexdump -v -n 6 -s $mac_offset -e '/1 "%02x"' /lib/firmware/$FIRMWARE) + xor_fw_mac="${xor_fw_mac:0:4} ${xor_fw_mac:4:4} ${xor_fw_mac:8:4}" + + ath10kcal_patch_mac "$mac" && { + xor_mac=${mac//:/} + xor_mac="${xor_mac:0:4} ${xor_mac:4:4} ${xor_mac:8:4}" + + xor_fw_chksum=$(hexdump -v -n 2 -s $chksum_offset -e '/1 "%02x"' /lib/firmware/$FIRMWARE) + xor_fw_chksum=$(xor $xor_fw_chksum $xor_fw_mac $xor_mac) + + printf "%b" "\x${xor_fw_chksum:0:2}\x${xor_fw_chksum:2:2}" | \ + dd of=/lib/firmware/$FIRMWARE conv=notrunc bs=1 seek=$chksum_offset count=2 + } +} + +ath10kcal_is_caldata_valid() { + local expected="$1" + + magic=$(hexdump -v -n 2 -e '1/1 "%02x"' /lib/firmware/$FIRMWARE) + [[ "$magic" == "$expected" ]] + return $? +} + +[ -e /lib/firmware/$FIRMWARE ] && exit 0 + +. /lib/functions.sh +. /lib/functions/system.sh + +board=$(board_name) + + +case "$FIRMWARE" in +"ath10k/cal-pci-0000:01:00.0.bin") + case "$board" in + meraki,mr33) + ath10kcal_ubi_extract "ART" 36864 2116 + ath10kcal_is_caldata_valid "4408" || ath10kcal_extract "ART" 36864 2116 + ath10kcal_patch_mac $(macaddr_add $(get_mac_binary "/sys/bus/i2c/devices/0-0050/eeprom" 102) +1) + ;; + esac + ;; +"ath10k/pre-cal-ahb-a000000.wifi.bin") + case "$board" in + asus,rt-acrh17|\ + asus,rt-ac58u) + CI_UBIPART=UBI_DEV + ath10kcal_ubi_extract "Factory" 4096 12064 + ;; + avm,fritzbox-4040) + /usr/bin/fritz_cal_extract -i 1 -s 0x400 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader_config") + ;; + glinet,gl-b1300 |\ + qcom,ap-dk01.1-c1) + ath10kcal_extract "ART" 4096 12064 + ;; + meraki,mr33) + ath10kcal_ubi_extract "ART" 4096 12064 + ath10kcal_is_caldata_valid "202f" || ath10kcal_extract "ART" 4096 12064 + ath10kcal_patch_mac_crc $(macaddr_add $(get_mac_binary "/sys/bus/i2c/devices/0-0050/eeprom" 102) +2) + ;; + compex,wpj428 |\ + openmesh,a42) + ath10kcal_extract "0:ART" 4096 12064 + ;; + esac + ;; +"ath10k/pre-cal-ahb-a800000.wifi.bin") + case "$board" in + asus,rt-ac58u) + CI_UBIPART=UBI_DEV + ath10kcal_ubi_extract "Factory" 20480 12064 + ;; + avm,fritzbox-4040) + /usr/bin/fritz_cal_extract -i 1 -s 0x400 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader_config") + ;; + glinet,gl-b1300 |\ + qcom,ap-dk01.1-c1) + ath10kcal_extract "ART" 20480 12064 + ;; + meraki,mr33) + ath10kcal_ubi_extract "ART" 20480 12064 + ath10kcal_is_caldata_valid "202f" || ath10kcal_extract "ART" 20480 12064 + ath10kcal_patch_mac_crc $(macaddr_add $(get_mac_binary "/sys/bus/i2c/devices/0-0050/eeprom" 102) +3) + ;; + compex,wpj428 |\ + openmesh,a42) + ath10kcal_extract "0:ART" 20480 12064 + ;; + esac + ;; +"ath10k/pre-cal-pci-0000:01:00.0.bin") + case "$board" in + asus,rt-acrh17) + CI_UBIPART=UBI_DEV + ath10kcal_ubi_extract "Factory" 36864 12064 + ;; + esac + ;; +*) + exit 1 + ;; +esac diff --git a/target/linux/ipq40xx/base-files/etc/hotplug.d/net/16_adjust_network b/target/linux/ipq40xx/base-files/etc/hotplug.d/net/16_adjust_network new file mode 100644 index 000000000..7aa4f6f72 --- /dev/null +++ b/target/linux/ipq40xx/base-files/etc/hotplug.d/net/16_adjust_network @@ -0,0 +1,7 @@ +#!/bin/sh + +[ -f /lib/adjust_network.sh ] && { + . /lib/adjust_network.sh + + adjust_eth_queue +} diff --git a/target/linux/ipq40xx/base-files/etc/init.d/adjust_network b/target/linux/ipq40xx/base-files/etc/init.d/adjust_network new file mode 100755 index 000000000..788b833ff --- /dev/null +++ b/target/linux/ipq40xx/base-files/etc/init.d/adjust_network @@ -0,0 +1,18 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2006-2011 OpenWrt.org + +START=11 +STOP=98 + +adjust_smp_affinity() { + test -f /lib/adjust_network.sh && { + . /lib/adjust_network.sh + + adjust_edma_smp_affinity + adjust_radio_smp_affinity + } +} + +boot() { + adjust_smp_affinity +} diff --git a/target/linux/ipq40xx/base-files/etc/inittab b/target/linux/ipq40xx/base-files/etc/inittab new file mode 100644 index 000000000..809bba5e5 --- /dev/null +++ b/target/linux/ipq40xx/base-files/etc/inittab @@ -0,0 +1,4 @@ +# Copyright (c) 2013 The Linux Foundation. All rights reserved. +::sysinit:/etc/init.d/rcS S boot +::shutdown:/etc/init.d/rcS K shutdown +ttyMSM0::askfirst:/usr/libexec/login.sh diff --git a/target/linux/ipq40xx/base-files/lib/adjust_network.sh b/target/linux/ipq40xx/base-files/lib/adjust_network.sh new file mode 100644 index 000000000..95ffedc04 --- /dev/null +++ b/target/linux/ipq40xx/base-files/lib/adjust_network.sh @@ -0,0 +1,86 @@ +#!/bin/sh +# this scripts is used for adjust cpu's choice of interrupts. +# + +################################################ +# Adjust smp_affinity of edma +# Globals: +# None +# Arguments: +# None +# Returns: +# None +# Remark: +# execute only once on start-up. +################################################ +adjust_edma_smp_affinity() { + grep -q edma_eth_ /proc/interrupts || return 0 + local nr=`cat /proc/cpuinfo | grep processor | wc -l` + local cpu=0 + local tx_irq_num + + for tx_num in `seq 0 1 15` ; do + cpu=`printf "%x" $((1<<((tx_num/4+3)%nr)))` + tx_irq_num=`grep -m1 edma_eth_tx$tx_num /proc/interrupts | cut -d ':' -f 1 | tail -n1 | tr -d ' '` + [ -n "$tx_irq_num" ] && echo $cpu > /proc/irq/$tx_irq_num/smp_affinity + done + + for rx_num in `seq 0 1 7` ; do + cpu=`printf "%x" $((1<<((rx_num/2)%nr)))` + rx_irq_num=`grep -m1 edma_eth_rx$rx_num /proc/interrupts | cut -d ':' -f 1 | tail -n1 | tr -d ' '` + [ -n "$rx_irq_num" ] && echo $cpu > /proc/irq/$rx_irq_num/smp_affinity + done +} + +################################################ +# Adjust smp_affinity of ath10k for 2G and 5G +# Globals: +# None +# Arguments: +# None +# Returns: +# None +# Remark: +# execute only once on start-up. +################################################ +adjust_radio_smp_affinity() { + local irqs="`grep -E 'ath10k' /proc/interrupts | cut -d ':' -f 1 | tr -d ' '`" + local nr=`cat /proc/cpuinfo | grep processor | wc -l` + local idx=2 + + for irq in $irqs; do + cpu=`printf "%x" $((1<<((idx)%nr)))` + echo $cpu > /proc/irq/$irq/smp_affinity + idx=$((idx+1)) + done +} + +################################################ +# Adjust queue of eth +# Globals: +# None +# Arguments: +# None +# Returns: +# None +# Remark: +# Each network reboot needs to be executed. +################################################ +adjust_eth_queue() { + local nr=`cat /proc/cpuinfo | grep processor | wc -l` + local cpu=`printf "%x" $(((1< $exps + echo 256 > `dirname $exps`/rps_flow_cnt + done + which ethtool >/dev/null 2>&1 && ethtool -K $eth gro off + done + + echo 1024 > /proc/sys/net/core/rps_sock_flow_entries +} diff --git a/target/linux/ipq40xx/base-files/lib/preinit/05_set_iface_mac_ipq40xx.sh b/target/linux/ipq40xx/base-files/lib/preinit/05_set_iface_mac_ipq40xx.sh new file mode 100644 index 000000000..909bb0813 --- /dev/null +++ b/target/linux/ipq40xx/base-files/lib/preinit/05_set_iface_mac_ipq40xx.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +. /lib/functions.sh + +preinit_set_mac_address() { + case $(board_name) in + asus,rt-acrh17|\ + asus,rt-ac58u) + CI_UBIPART=UBI_DEV + mac=$(mtd_get_mac_binary_ubi Factory 4102) + ifconfig eth0 hw ether $mac 2>/dev/null + ;; + meraki,mr33) + mac_lan=$(get_mac_binary "/sys/bus/i2c/devices/0-0050/eeprom" 102) + [ -n "$mac_lan" ] && ip link set dev eth0 address "$mac_lan" + ;; + esac +} + +boot_hook_add preinit_main preinit_set_mac_address diff --git a/target/linux/ipq40xx/base-files/lib/upgrade/openmesh.sh b/target/linux/ipq40xx/base-files/lib/upgrade/openmesh.sh new file mode 100644 index 000000000..71ab247ea --- /dev/null +++ b/target/linux/ipq40xx/base-files/lib/upgrade/openmesh.sh @@ -0,0 +1,110 @@ +# The U-Boot loader of the OpenMesh devices requires image sizes and +# checksums to be provided in the U-Boot environment. +# The OpenMesh devices come with 2 main partitions - while one is active +# sysupgrade will flash the other. The boot order is changed to boot the +# newly flashed partition. If the new partition can't be booted due to +# upgrade failures the previously used partition is loaded. + +platform_do_upgrade_openmesh() { + local tar_file="$1" + local restore_backup + local primary_kernel_mtd + + local setenv_script="/tmp/fw_env_upgrade" + + local kernel_mtd="$(find_mtd_index $PART_NAME)" + local kernel_offset="$(cat /sys/class/mtd/mtd${kernel_mtd}/offset)" + local total_size="$(cat /sys/class/mtd/mtd${kernel_mtd}/size)" + + # detect to which flash region the new image is written to. + # + # 1. check what is the mtd index for the first flash region on this + # device + # 2. check if the target partition ("inactive") has the mtd index of + # the first flash region + # + # - when it is: the new bootseq will be 1,2 and the first region is + # modified + # - when it isnt: bootseq will be 2,1 and the second region is + # modified + # + # The detection has to be done via the hardcoded mtd partition because + # the current boot might be done with the fallback region. Let us + # assume that the current bootseq is 1,2. The bootloader detected that + # the image in flash region 1 is corrupt and thus switches to flash + # region 2. The bootseq in the u-boot-env is now still the same and + # the sysupgrade code can now only rely on the actual mtd indexes and + # not the bootseq variable to detect the currently booted flash + # region/image. + # + # In the above example, an implementation which uses bootseq ("1,2") to + # detect the currently booted image would assume that region 1 is booted + # and then overwrite the variables for the wrong flash region (aka the + # one which isn't modified). This could result in a device which doesn't + # boot anymore to Linux until it was reflashed with ap51-flash. + local next_boot_part="1" + case "$(board_name)" in + openmesh,a42) + primary_kernel_mtd=8 + ;; + *) + echo "failed to detect primary kernel mtd partition for board" + return 1 + ;; + esac + [ "$kernel_mtd" = "$primary_kernel_mtd" ] || next_boot_part="2" + + local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$') + board_dir=${board_dir%/} + + local kernel_length=$(tar xf $tar_file ${board_dir}/kernel -O | wc -c) + local rootfs_length=$(tar xf $tar_file ${board_dir}/root -O | wc -c) + # rootfs without EOF marker + rootfs_length=$((rootfs_length-4)) + + local kernel_md5=$(tar xf $tar_file ${board_dir}/kernel -O | md5sum); kernel_md5="${kernel_md5%% *}" + # md5 checksum of rootfs with EOF marker + local rootfs_md5=$(tar xf $tar_file ${board_dir}/root -O | dd bs=1 count=$rootfs_length | md5sum); rootfs_md5="${rootfs_md5%% *}" + + # + # add tar support to get_image() to use default_do_upgrade() instead? + # + + # take care of restoring a saved config + [ "$SAVE_CONFIG" -eq 1 ] && restore_backup="${MTD_CONFIG_ARGS} -j ${CONF_TAR}" + + # write concatinated kernel + rootfs to flash + tar xf $tar_file ${board_dir}/kernel ${board_dir}/root -O | \ + mtd $restore_backup write - $PART_NAME + + # prepare new u-boot env + if [ "$next_boot_part" = "1" ]; then + echo "bootseq 1,2" > $setenv_script + else + echo "bootseq 2,1" > $setenv_script + fi + + printf "kernel_size_%i 0x%08x\n" $next_boot_part $kernel_length >> $setenv_script + printf "vmlinux_start_addr 0x%08x\n" ${kernel_offset} >> $setenv_script + printf "vmlinux_size 0x%08x\n" ${kernel_length} >> $setenv_script + printf "vmlinux_checksum %s\n" ${kernel_md5} >> $setenv_script + + printf "rootfs_size_%i 0x%08x\n" $next_boot_part $((total_size-kernel_length)) >> $setenv_script + printf "rootfs_start_addr 0x%08x\n" $((kernel_offset+kernel_length)) >> $setenv_script + printf "rootfs_size 0x%08x\n" ${rootfs_length} >> $setenv_script + printf "rootfs_checksum %s\n" ${rootfs_md5} >> $setenv_script + + # store u-boot env changes + fw_setenv -s $setenv_script || { + echo "failed to update U-Boot environment" + return 1 + } +} + +# create /var/lock for the lock "fw_setenv.lock" of fw_setenv +# the rest is copied using ipq806x's RAMFS_COPY_BIN and RAMFS_COPY_DATA +platform_add_ramfs_ubootenv() +{ + mkdir -p $RAM_ROOT/var/lock +} +append sysupgrade_pre_upgrade platform_add_ramfs_ubootenv diff --git a/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh b/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh new file mode 100644 index 000000000..80efb3514 --- /dev/null +++ b/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh @@ -0,0 +1,185 @@ +PART_NAME=firmware +REQUIRE_IMAGE_METADATA=1 + +RAMFS_COPY_BIN='fw_printenv fw_setenv' +RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock' + +ubi_kill_if_exist() { + local ubidev="$( nand_find_ubi "$CI_UBIPART" )" + local c_ubivol="$( nand_find_volume $ubidev $1 )" + umount -f /dev/$c_ubivol 2>/dev/null + [ "$c_ubivol" ] && ubirmvol /dev/$ubidev -N $1 || true + echo "Partition $1 removed." +} + +# idea from @981213 +# Tar sysupgrade for ASUS RT-AC82U/RT-AC58U +# An ubi repartition is required due to the strange partition table created by Asus. +# We create all the factory partitions to make sure that the U-boot tftp recovery still works. +# The reserved kernel partition size should be enough to put the factory image in. +asus_nand_upgrade_tar() { + local kpart_size="$1" + local tar_file="$2" + + local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$') + board_dir=${board_dir%/} + + local kernel_length=`(tar xf $tar_file ${board_dir}/kernel -O | wc -c) 2> /dev/null` + local rootfs_length=`(tar xf $tar_file ${board_dir}/root -O | wc -c) 2> /dev/null` + + local mtdnum="$( find_mtd_index "$CI_UBIPART" )" + if [ ! "$mtdnum" ]; then + echo "cannot find ubi mtd partition $CI_UBIPART" + return 1 + fi + + local ubidev="$( nand_find_ubi "$CI_UBIPART" )" + if [ ! "$ubidev" ]; then + ubiattach -m "$mtdnum" + sync + ubidev="$( nand_find_ubi "$CI_UBIPART" )" + fi + + if [ ! "$ubidev" ]; then + echo "cannot find ubi device $CI_UBIPART" + return 1 + fi + + local root_ubivol="$( nand_find_volume $ubidev rootfs )" + # remove ubiblock device of rootfs + local root_ubiblk="ubiblock${root_ubivol:-3}" + if [ "$root_ubivol" -a -e "/dev/$root_ubiblk" ]; then + echo "removing $root_ubiblk" + if ! ubiblock -r /dev/$root_ubivol; then + echo "cannot remove $root_ubiblk" + return 1; + fi + fi + + ubi_kill_if_exist linux + ubi_kill_if_exist linux2 + ubi_kill_if_exist rootfs + ubi_kill_if_exist rootfs_data + ubi_kill_if_exist jffs2 + + ubimkvol /dev/$ubidev -N linux -s $kpart_size + ubimkvol /dev/$ubidev -N linux2 -s $kpart_size + ubimkvol /dev/$ubidev -N jffs2 -s 2539520 + ubimkvol /dev/$ubidev -N rootfs -s $rootfs_length + ubimkvol /dev/$ubidev -N rootfs_data -m + + local kern_ubivol="$(nand_find_volume $ubidev $CI_KERNPART)" + echo "Kernel at $kern_ubivol.Writing..." + tar xf $tar_file ${board_dir}/kernel -O | \ + ubiupdatevol /dev/$kern_ubivol -s $kernel_length - + echo "Done." + + local root_ubivol="$(nand_find_volume $ubidev rootfs)" + echo "Rootfs at $root_ubivol.Writing..." + tar xf $tar_file ${board_dir}/root -O | \ + ubiupdatevol /dev/$root_ubivol -s $rootfs_length - + echo "Done." + + nand_do_upgrade_success +} + +# idea from @981213 +# Factory image sysupgrade for ASUS RT-AC82U/RT-AC58U +# Delete all the partitions we created before, create "linux" partition and write factory image in. +# Skip the first 64bytes which is an uImage header to verify the firmware. +# The kernel partition size should be the original one. +asus_nand_upgrade_factory() { + local kpart_size="$1" + local fw_file="$2" + + local mtdnum="$( find_mtd_index "$CI_UBIPART" )" + if [ ! "$mtdnum" ]; then + echo "cannot find ubi mtd partition $CI_UBIPART" + return 1 + fi + + local ubidev="$( nand_find_ubi "$CI_UBIPART" )" + if [ ! "$ubidev" ]; then + ubiattach -m "$mtdnum" + sync + ubidev="$( nand_find_ubi "$CI_UBIPART" )" + fi + + if [ ! "$ubidev" ]; then + echo "cannot find ubi device $CI_UBIPART" + return 1 + fi + + local root_ubivol="$( nand_find_volume $ubidev rootfs )" + # remove ubiblock device of rootfs + local root_ubiblk="ubiblock${root_ubivol:-3}" + if [ "$root_ubivol" -a -e "/dev/$root_ubiblk" ]; then + echo "removing $root_ubiblk" + if ! ubiblock -r /dev/$root_ubivol; then + echo "cannot remove $root_ubiblk" + return 1; + fi + fi + + ubi_kill_if_exist linux + ubi_kill_if_exist linux2 + ubi_kill_if_exist rootfs + ubi_kill_if_exist rootfs_data + ubi_kill_if_exist jffs2 + + ubimkvol /dev/$ubidev -N linux -s $kpart_size + + local kern_ubivol="$(nand_find_volume $ubidev $CI_KERNPART)" + echo "Asus linux at $kern_ubivol.Writing..." + ubiupdatevol /dev/$kern_ubivol --skip=64 $fw_file + echo "Done." + + umount -a + reboot -f +} + +platform_check_image() { + return 0; +} + +platform_do_upgrade() { + case "$(board_name)" in + asus,rt-acrh17|\ + asus,rt-ac58u) + local magic=$(get_magic_long "$1") + CI_UBIPART="UBI_DEV" + CI_KERNPART="linux" + if [ "$magic" == "27051956" ]; then + echo "Got Asus factory image." + asus_nand_upgrade_factory 50409472 "$1" + else + asus_nand_upgrade_tar 20951040 "$1" + fi + ;; + openmesh,a42) + PART_NAME="inactive" + platform_do_upgrade_openmesh "$ARGV" + ;; + meraki,mr33) + CI_KERNPART="part.safe" + nand_do_upgrade "$1" + ;; + *) + default_do_upgrade "$ARGV" + ;; + esac +} + +platform_nand_pre_upgrade() { + case "$(board_name)" in + meraki,mr33) + CI_KERNPART="part.safe" + ;; + esac +} + +blink_led() { + . /etc/diag.sh; set_state upgrade +} + +append sysupgrade_pre_upgrade blink_led diff --git a/target/linux/ipq40xx/config-4.14 b/target/linux/ipq40xx/config-4.14 new file mode 100644 index 000000000..1bba06176 --- /dev/null +++ b/target/linux/ipq40xx/config-4.14 @@ -0,0 +1,489 @@ +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_APQ_GCC_8084 is not set +# CONFIG_APQ_MMCC_8084 is not set +CONFIG_AR40XX_PHY=y +CONFIG_ARCH_CLOCKSOURCE_DATA=y +CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +CONFIG_ARCH_HAS_SET_MEMORY=y +CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y +CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_IPQ40XX=y +# CONFIG_ARCH_MDM9615 is not set +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +# CONFIG_ARCH_MSM8960 is not set +# CONFIG_ARCH_MSM8974 is not set +# CONFIG_ARCH_MSM8X60 is not set +CONFIG_ARCH_MULTIPLATFORM=y +# CONFIG_ARCH_MULTI_CPU_AUTO is not set +CONFIG_ARCH_MULTI_V6_V7=y +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_NR_GPIO=0 +CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y +CONFIG_ARCH_QCOM=y +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +# CONFIG_ARCH_WANTS_THP_SWAP is not set +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_ARM=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_APPENDED_DTB=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_ATAG_DTB_COMPAT is not set +CONFIG_ARM_CPUIDLE=y +CONFIG_ARM_CPU_SUSPEND=y +# CONFIG_ARM_CPU_TOPOLOGY is not set +CONFIG_ARM_GIC=y +CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_L1_CACHE_SHIFT_6=y +# CONFIG_ARM_LPAE is not set +CONFIG_ARM_PATCH_IDIV=y +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_ARM_QCOM_CPUIDLE=y +# CONFIG_ARM_SMMU is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_ARM_UNWIND=y +CONFIG_ARM_VIRT_EXT=y +CONFIG_AT803X_PHY=y +CONFIG_AUTO_ZRELADDR=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BOUNCE=y +CONFIG_BUS_TOPOLOGY_ADHOC=y +# CONFIG_CACHE_L2X0 is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLKSRC_QCOM=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_QCOM=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +# CONFIG_CPU_BIG_ENDIAN is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_HAS_ASID=y +# CONFIG_CPU_ICACHE_DISABLE is not set +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_PM=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_THERMAL=y +CONFIG_CPU_THUMB_CAPABLE=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_V7=y +CONFIG_CRC16=y +# CONFIG_CRC32_SARWATE is not set +CONFIG_CRC32_SLICEBY8=y +CONFIG_CRYPTO_ACOMP2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_DEV_QCE=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_NULL2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_XTS=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +# CONFIG_DEBUG_UART_8250 is not set +# CONFIG_DEBUG_USER is not set +CONFIG_DMADEVICES=y +CONFIG_DMA_ENGINE=y +# CONFIG_DMA_NOOP_OPS is not set +CONFIG_DMA_OF=y +CONFIG_DMA_SHARED_BUFFER=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +# CONFIG_DMA_VIRT_OPS is not set +# CONFIG_DRM_LIB_RANDOM is not set +CONFIG_DTC=y +CONFIG_DT_IDLE_STATES=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EEPROM_AT24=y +CONFIG_ESSEDMA=y +CONFIG_EXPORTFS=y +CONFIG_EXTCON=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FUTEX_PI=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IO=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_WATCHDOG=y +# CONFIG_GPIO_WATCHDOG_ARCH_INITCALL is not set +# CONFIG_GRO_CELLS is not set +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_ARCH_AUDITSYSCALL=y +CONFIG_HAVE_ARCH_BITREVERSE=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_HAVE_ARM_SMCCC=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_DEBUG_KMEMLEAK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_HAVE_EBPF_JIT=y +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_HAVE_NET_DSA=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_OPTPROBES=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_SMP=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_UID16=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_MSM=y +CONFIG_HZ_FIXED=0 +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_QUP=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IOMMU_HELPER=y +# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set +# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set +CONFIG_IOMMU_SUPPORT=y +CONFIG_IPQ_GCC_4019=y +# CONFIG_IPQ_GCC_806X is not set +# CONFIG_IPQ_GCC_8074 is not set +# CONFIG_IPQ_LCC_806X is not set +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_WORK=y +CONFIG_LEDS_LP5562=y +CONFIG_LEDS_LP55XX_COMMON=y +CONFIG_LIBFDT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MDIO_BITBANG=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_GPIO=y +CONFIG_MDIO_IPQ40XX=y +# CONFIG_MDM_GCC_9615 is not set +# CONFIG_MDM_LCC_9615 is not set +# CONFIG_MFD_QCOM_RPM is not set +# CONFIG_MFD_SPMI_PMIC is not set +CONFIG_MFD_SYSCON=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_MIGHT_HAVE_PCI=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MSM_BUS_SCALING=y +# CONFIG_MSM_GCC_8660 is not set +# CONFIG_MSM_GCC_8916 is not set +# CONFIG_MSM_GCC_8960 is not set +# CONFIG_MSM_GCC_8974 is not set +# CONFIG_MSM_GCC_8994 is not set +# CONFIG_MSM_GCC_8996 is not set +# CONFIG_MSM_LCC_8960 is not set +# CONFIG_MSM_MMCC_8960 is not set +# CONFIG_MSM_MMCC_8974 is not set +# CONFIG_MSM_MMCC_8996 is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_M25P80=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_QCOM=y +CONFIG_MTD_SPINAND_MT29F=y +CONFIG_MTD_SPINAND_ONDIEECC=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_FIT_FW=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MULTI_IRQ_HANDLER=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEON=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_QCA8K=y +CONFIG_NET_DSA_TAG_QCA=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_PTP_CLASSIFY=y +CONFIG_NET_SWITCHDEV=y +CONFIG_NLS=y +CONFIG_NO_BOOTMEM=y +CONFIG_NO_HZ=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=4 +CONFIG_NVMEM=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_MDIO=y +CONFIG_OF_NET=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_OF_RESERVED_MEM=y +CONFIG_OLD_SIGACTION=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OPTEE=y +CONFIG_PADATA=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_HOST=y +CONFIG_PCIE_QCOM=y +CONFIG_PCI_DISABLE_COMMON_QUIRKS=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +# CONFIG_PHY_QCOM_APQ8064_SATA is not set +# CONFIG_PHY_QCOM_IPQ806X_SATA is not set +# CONFIG_PHY_QCOM_QMP is not set +# CONFIG_PHY_QCOM_QUSB2 is not set +# CONFIG_PHY_QCOM_UFS is not set +CONFIG_PINCTRL=y +# CONFIG_PINCTRL_APQ8064 is not set +# CONFIG_PINCTRL_APQ8084 is not set +CONFIG_PINCTRL_IPQ4019=y +# CONFIG_PINCTRL_IPQ8064 is not set +# CONFIG_PINCTRL_IPQ8074 is not set +# CONFIG_PINCTRL_MDM9615 is not set +CONFIG_PINCTRL_MSM=y +# CONFIG_PINCTRL_MSM8660 is not set +# CONFIG_PINCTRL_MSM8916 is not set +# CONFIG_PINCTRL_MSM8960 is not set +# CONFIG_PINCTRL_MSM8994 is not set +# CONFIG_PINCTRL_MSM8996 is not set +# CONFIG_PINCTRL_QCOM_SPMI_PMIC is not set +# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set +CONFIG_PM_OPP=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_MSM=y +CONFIG_POWER_SUPPLY=y +CONFIG_PPS=y +CONFIG_PRINTK_TIME=y +CONFIG_PTP_1588_CLOCK=y +CONFIG_QCOM_BAM_DMA=y +# CONFIG_QCOM_EBI2 is not set +# CONFIG_QCOM_GSBI is not set +# CONFIG_QCOM_IOMMU is not set +CONFIG_QCOM_PM=y +CONFIG_QCOM_QFPROM=y +CONFIG_QCOM_SCM=y +CONFIG_QCOM_SCM_32=y +CONFIG_QCOM_SMEM=y +# CONFIG_QCOM_SMP2P is not set +# CONFIG_QCOM_SMSM is not set +CONFIG_QCOM_TCSR=y +# CONFIG_QCOM_TSENS is not set +CONFIG_QCOM_WDT=y +# CONFIG_QRTR is not set +CONFIG_RAS=y +CONFIG_RATIONAL=y +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +CONFIG_RCU_NEED_SEGCBLIST=y +CONFIG_RCU_STALL_COMMON=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_SPI=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_REGULATOR_QCOM_SPMI is not set +CONFIG_REGULATOR_VCTRL=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RFS_ACCEL=y +# CONFIG_RPMSG_QCOM_SMD is not set +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_DRV_CMOS is not set +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +# CONFIG_SCHED_INFO is not set +# CONFIG_SCSI_DMA is not set +CONFIG_SERIAL_8250_FSL=y +# CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SERIAL_MSM=y +CONFIG_SERIAL_MSM_CONSOLE=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_QUP=y +CONFIG_SPMI=y +CONFIG_SPMI_MSM_PMIC_ARB=y +CONFIG_SRCU=y +CONFIG_SWCONFIG=y +CONFIG_SWCONFIG_LEDS=y +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SWP_EMULATE=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_TEE=y +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_OF=y +CONFIG_THIN_ARCHIVES=y +# CONFIG_THUMB2_KERNEL is not set +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +CONFIG_USB=y +CONFIG_USB_COMMON=y +# CONFIG_USB_EHCI_HCD is not set +CONFIG_USB_IPQ4019_PHY=y +CONFIG_USB_PHY=y +# CONFIG_USB_QCOM_8X16_PHY is not set +CONFIG_USB_SUPPORT=y +CONFIG_USE_OF=y +CONFIG_VDSO=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_WATCHDOG_CORE=y +CONFIG_XPS=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-nbg6617.dts b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4018-a42.dts similarity index 53% rename from target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-nbg6617.dts rename to target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4018-a42.dts index b58f4dbe3..8c01d4118 100644 --- a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-nbg6617.dts +++ b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4018-a42.dts @@ -1,4 +1,5 @@ /* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2017, Sven Eckelmann * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,19 +15,107 @@ * */ -#include "qcom-ipq4019-ap.dk01.1.dtsi" +#include "qcom-ipq4019.dtsi" #include "qcom-ipq4019-bus.dtsi" #include #include #include / { - model = "ZyXEL NBG6617"; - compatible = "zyxel,nbg6617", "qcom,ipq4019"; + model = "OpenMesh A42"; + compatible = "openmesh,a42", "qcom,ipq4019"; - memory { - device_type = "memory"; - reg = <0x80000000 0x10000000>; + reserved-memory { + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges; + + tz_apps@87b80000 { + reg = <0x87b80000 0x280000>; + no-map; + }; + + smem@87e00000 { + reg = <0x87e00000 0x080000>; + no-map; + }; + + tz@87e80000 { + reg = <0x87e80000 0x180000>; + no-map; + }; + }; + + soc { + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2: usb2@60f8800 { + status = "okay"; + }; + + serial@78af000 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; + linux,code = ; + }; }; aliases { @@ -36,173 +125,101 @@ led-upgrade = &power; }; - reserved-memory { - #address-cells = <0x1>; - #size-cells = <0x1>; - ranges; - - rsvd1@87000000 { - reg = <0x87000000 0x0500000>; - no-map; - }; - - wifi_dump@87500000 { - reg = <0x87500000 0x600000>; - no-map; - }; - - rsvd2@87B00000 { - reg = <0x87b00000 0x500000>; - no-map; - }; - }; - - soc { - pinctrl@0x01000000 { - led_pinmux { - mux { - pins = "gpio0", "gpio1", "gpio3", "gpio5", "gpio58"; - drive-strength = <0x8>; - bias-pull-up; - output-high; - }; - }; - }; - - tcsr@194b000 { - /* select hostmode */ - compatible = "qcom,tcsr"; - reg = <0x194b000 0x100>; - qcom,usb-hsphy-mode-select = ; - status = "ok"; - }; - - ess_tcsr@1953000 { - compatible = "qcom,tcsr"; - reg = <0x1953000 0x1000>; - qcom,ess-interface-select = ; - }; - - - tcsr@1949000 { - compatible = "qcom,tcsr"; - reg = <0x1949000 0x100>; - qcom,wifi_glb_cfg = ; - }; - - tcsr@1957000 { - compatible = "qcom,tcsr"; - reg = <0x1957000 0x100>; - qcom,wifi_noc_memtype_m0_m2 = ; - }; - - counter@4a1000 { - compatible = "qcom,qca-gcnt"; - reg = <0x4a1000 0x4>; - }; - - mdio@90000 { - status = "okay"; - }; - - ess-switch@c000000 { - status = "okay"; - }; - - ess-psgmii@98000 { - status = "okay"; - }; - - edma@c080000 { - status = "okay"; - }; - - wifi@a000000 { - status = "okay"; - }; - - wifi@a800000 { - status = "okay"; - }; - - cryptobam: dma@8e04000 { - status = "okay"; - }; - - crypto@8e3a000 { - status = "okay"; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - - wlan { - label = "wlan"; - gpios = <&tlmm 0x2 GPIO_ACTIVE_HIGH>; - linux,code = ; - }; - - wps { - label = "wps"; - gpios = <&tlmm 0x3f GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - reset { - label = "reset"; - gpios = <&tlmm 0x4 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; - gpio-leds { compatible = "gpio-leds"; - power: power { - label = "nbg6617:green:power"; - gpios = <&tlmm 0x3 GPIO_ACTIVE_HIGH>; + red { + label = "a42:red:status"; + gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "default-off"; }; - wps { - label = "nbg6617:green:wps"; - gpios = <&tlmm 0x1 GPIO_ACTIVE_HIGH>; + power: green { + label = "a42:green:status"; + gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; }; - wlan2G { - label = "nbg6617:green:wlan2G"; - gpios = <&tlmm 0x3a GPIO_ACTIVE_HIGH>; + blue { + label = "a42:blue:status"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "default-off"; }; + }; - wlan5G { - label = "nbg6617:green:wlan5G"; - gpios = <&tlmm 0x5 GPIO_ACTIVE_HIGH>; + watchdog { + compatible = "linux,wdt-gpio"; + gpios = <&tlmm 5 GPIO_ACTIVE_LOW>; + hw_algo = "toggle"; + /* hw_margin_ms is actually 300s but driver limits it to 60s */ + hw_margin_ms = <60000>; + always-running; + }; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + pin_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; }; }; }; +&blsp_dma { + status = "okay"; +}; -&spi_0 { /* BLSP1 QUP1 */ - status = "ok"; - - mx25l25635e@0 { - status = "disabled"; - }; - - n25q128a11@0 { - status = "okay"; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition0@0 { - label = "all"; - reg = <0x00000000 0x08000000>; - read-only; /* for now */ - }; - }; +&spi_0 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + /* partitions are passed via bootloader */ }; }; + +&cryptobam { + status = "okay"; +}; + +&gmac0 { + vlan_tag = <1 0x31>; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + qcom,ath10k-calibration-variant = "OM-A42"; +}; + +&wifi1 { + status = "okay"; + qcom,ath10k-calibration-variant = "OM-A42"; +}; diff --git a/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4018-fritz4040.dts b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4018-fritz4040.dts new file mode 100644 index 000000000..4b5cbcac3 --- /dev/null +++ b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4018-fritz4040.dts @@ -0,0 +1,322 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "qcom-ipq4019.dtsi" +#include "qcom-ipq4019-bus.dtsi" +#include +#include +#include + +/ { + model = "AVM FRITZ!Box 4040"; + compatible = "avm,fritzbox-4040", "qcom,ipq4019"; + + aliases { + led-boot = &power; + led-failsafe = &flash; + led-running = &power; + led-upgrade = &flash; + }; + + reserved-memory { + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges; + + tz_apps@87b80000 { + reg = <0x87b80000 0x280000>; + reusable; + }; + + smem@87e00000 { + reg = <0x87e00000 0x080000>; + no-map; + }; + + tz@87e80000 { + reg = <0x87e80000 0x180000>; + no-map; + }; + }; + + soc { + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + }; + + serial@78af000 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + usb3@8af8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + wifi@a000000 { + status = "okay"; + }; + + wifi@a800000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + qca8075: ess-switch@c000000 { + status = "okay"; + + #gpio-cells = <2>; + gpio-controller; + + enable-usb-power { + gpio-hog; + line-name = "enable USB3 power"; + gpios = <7 GPIO_ACTIVE_HIGH>; + output-high; + }; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + wlan { + label = "wlan"; + gpios = <&tlmm 58 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wlan { + label = "fritz4040:green:wlan"; + gpios = <&qca8075 1 GPIO_ACTIVE_HIGH>; + }; + + panic: info_red { + label = "fritz4040:red:info"; + gpios = <&qca8075 3 GPIO_ACTIVE_HIGH>; + panic-indicator; + }; + + wan { + label = "fritz4040:green:wan"; + gpios = <&qca8075 5 GPIO_ACTIVE_HIGH>; + }; + + power: power { + label = "fritz4040:green:power"; + gpios = <&qca8075 11 GPIO_ACTIVE_HIGH>; + }; + + lan { + label = "fritz4040:green:lan"; + gpios = <&qca8075 13 GPIO_ACTIVE_HIGH>; + }; + + flash: info_amber { + label = "fritz4040:amber:info"; + gpios = <&qca8075 15 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + mux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + + mux_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp_dma { + status = "okay"; +}; + +&spi_0 { /* BLSP1 QUP1 */ + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + mx25l25635f@0 { + compatible = "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + spi-max-frequency = <24000000>; + status = "okay"; + m25p,fast-read; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition0@0 { + label = "SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition1@40000 { + label = "MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + partition2@60000 { + label = "QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + partition3@c0000 { + label = "CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + partition4@d0000 { + label = "DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + partition5@e0000 { + label = "APPSBLENV"; /* uboot env - empty */ + reg = <0x000e0000 0x00010000>; + read-only; + }; + partition6@f0000 { + label = "urlader"; /* APPSBL */ + reg = <0x000f0000 0x0002dc000>; + read-only; + }; + partition7@11dc00 { + /* make a backup of this partition! */ + label = "urlader_config"; + reg = <0x0011dc00 0x00002400>; + read-only; + }; + partition8@120000 { + label = "tffs1"; + reg = <0x00120000 0x00080000>; + read-only; + }; + partition9@1a0000 { + label = "tffs2"; + reg = <0x001a0000 0x00080000>; + read-only; + }; + partition10@220000 { + label = "uboot"; + reg = <0x00220000 0x00080000>; + read-only; + }; + partition11@2A0000 { + label = "firmware"; + reg = <0x002a0000 0x01c60000>; + }; + partition12@1f00000 { + label = "jffs2"; + reg = <0x01f00000 0x00100000>; + }; + }; + }; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; diff --git a/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4018-rt-ac58u.dts b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4018-rt-ac58u.dts new file mode 100644 index 000000000..446da0451 --- /dev/null +++ b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4018-rt-ac58u.dts @@ -0,0 +1,314 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "qcom-ipq4019.dtsi" +#include "qcom-ipq4019-bus.dtsi" +#include +#include +#include + +/ { + model = "ASUS RT-AC58U"; + compatible = "asus,rt-ac58u", "qcom,ipq4019"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x8000000>; + }; + + aliases { + led-boot = &power; + led-failsafe = &power; + led-running = &power; + led-upgrade = &power; + }; + + reserved-memory { + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges; + + smem@87e00000 { + reg = <0x87e00000 0x080000>; + no-map; + }; + + tz@87e80000 { + reg = <0x87e80000 0x180000>; + no-map; + }; + }; + + soc { + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + }; + + serial@78af000 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + usb3@8af8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + wifi@a000000 { + status = "okay"; + qcom,ath10k-calibration-variant = "ASUS-RT-AC58U"; + }; + + wifi@a800000 { + status = "okay"; + qcom,ath10k-calibration-variant = "ASUS-RT-AC58U"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 4 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power: status { + label = "rt-ac58u:blue:status"; + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + }; + + wan { + label = "rt-ac58u:blue:wan"; + gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; + }; + + wlan2G { + label = "rt-ac58u:blue:wlan2G"; + gpios = <&tlmm 58 GPIO_ACTIVE_HIGH>; + }; + + wan5G { + label = "rt-ac58u:blue:wlan5G"; + gpios = <&tlmm 5 GPIO_ACTIVE_HIGH>; + }; + + usb { + label = "rt-ac58u:blue:usb"; + gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; + }; + + lan { + label = "rt-ac58u:blue:lan"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&cryptobam { + status = "okay"; +}; + +&blsp_dma { + status = "okay"; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + mux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + + mux_cs { + function = "gpio"; + pins = "gpio54", "gpio59"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&spi_0 { /* BLSP1 QUP1 */ + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>, + <&tlmm 59 GPIO_ACTIVE_HIGH>; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <0>; + /* + * U-boot looks for "n25q128a11" node, + * if we don't have it, it will spit out the following warning: + * "ipq: fdt fixup unable to find compatible node". + */ + compatible = "jedec,spi-nor"; + reg = <0>; + linux,modalias = "m25p80", "mx25l1606e", "n25q128a11"; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition0@0 { + label = "SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition1@40000 { + label = "MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + partition2@60000 { + label = "QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + partition3@c0000 { + label = "CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + partition4@d0000 { + label = "DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + partition5@e0000 { + label = "APPSBLENV"; /* uboot env*/ + reg = <0x000e0000 0x00010000>; + read-only; + }; + partition5@f0000 { + label = "APPSBL"; /* uboot */ + reg = <0x000f0000 0x00080000>; + read-only; + }; + partition5@170000 { + label = "ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + /* 0x00180000 - 0x00200000 unused */ + }; + }; + + mt29f@1 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "spinand,mt29f"; + reg = <1>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition0@0 { + label = "ubi"; + reg = <0x00000000 0x08000000>; + }; + }; + }; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; diff --git a/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c1.dts b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c1.dts new file mode 100644 index 000000000..47202d28f --- /dev/null +++ b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c1.dts @@ -0,0 +1,21 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "qcom-ipq4019-ap.dk04.1.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. IPQ40xx/AP-DK04.1-C1"; +}; diff --git a/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi new file mode 100644 index 000000000..eeadc075d --- /dev/null +++ b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi @@ -0,0 +1,177 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "qcom-ipq4019.dtsi" +#include + +/ { + model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK04.1"; + compatible = "qcom,ipq4019"; + + soc { + pinctrl@1000000 { + serial_0_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + serial_1_pins: serial1_pinmux { + mux { + pins = "gpio8", "gpio9"; + function = "blsp_uart1"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; + }; + pinmux_cs { + function = "gpio"; + pins = "gpio12"; + }; + pinconf { + pins = "gpio13", "gpio14", "gpio15"; + drive-strength = <12>; + bias-disable; + }; + pinconf_cs { + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + + i2c_0_pins: i2c_0_pinmux { + pinmux { + function = "blsp_i2c0"; + pins = "gpio10", "gpio11"; + }; + pinconf { + pins = "gpio10", "gpio11"; + drive-strength = <16>; + bias-disable; + }; + }; + + nand_pins: nand_pins { + + pullups { + pins = "gpio52", "gpio53", "gpio58", + "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; + }; + + blsp_dma: dma@7884000 { + status = "okay"; + }; + + spi_0: spi@78b5000 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>; + + mx25l25635e@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + compatible = "mx25l25635e"; + spi-max-frequency = <24000000>; + }; + }; + + i2c_0: i2c@78b7000 { /* BLSP1 QUP2 */ + pinctrl-0 = <&i2c_0_pins>; + pinctrl-names = "default"; + + status = "okay"; + }; + + serial@78af000 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + serial@78b0000 { + pinctrl-0 = <&serial_1_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + usb3_ss_phy: ssphy@9a000 { + status = "okay"; + }; + + usb3_hs_phy: hsphy@a6000 { + status = "okay"; + }; + + usb3: usb3@8af8800 { + status = "okay"; + }; + + usb2_hs_phy: hsphy@a8000 { + status = "okay"; + }; + + usb2: usb2@60f8800 { + status = "okay"; + }; + + cryptobam: dma@8e04000 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + qpic_bam: dma@7984000 { + status = "okay"; + }; + + nand: qpic-nand@79b0000 { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + }; +}; diff --git a/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4019-bus.dtsi b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4019-bus.dtsi new file mode 100644 index 000000000..169505973 --- /dev/null +++ b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4019-bus.dtsi @@ -0,0 +1,1142 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include + +/ { + +soc { + ad_hoc_bus: ad-hoc-bus { + compatible = "qcom,msm-bus-device"; + reg = <0x580000 0x14000>, + <0x500000 0x11000>; + reg-names = "snoc-base", "pcnoc-base"; + + /*Buses*/ + + fab_pcnoc: fab-pcnoc { + cell-id = ; + label = "fab-pcnoc"; + qcom,fab-dev; + qcom,base-name = "pcnoc-base"; + qcom,bypass-qos-prg; + qcom,bus-type = <1>; + qcom,qos-off = <0x1000>; + qcom,base-offset = <0x0>; + clocks = <>; + }; + + fab_snoc: fab-snoc { + cell-id = ; + label = "fab-snoc"; + qcom,fab-dev; + qcom,base-name = "snoc-base"; + qcom,bypass-qos-prg; + qcom,bus-type = <1>; + qcom,qos-off = <0x80>; + qcom,base-offset = <0x0>; + clocks = <>; + }; + + /*Masters*/ + + mas_blsp_bam: mas-blsp-bam { + cell-id = ; + label = "mas-blsp-bam"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = <&pcnoc_m_0>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_tcsr &slv_mdio &slv_adss_cfg + &slv_fephy_cfg &slv_wss1_apu_cfg &slv_ddrc_mpu1_cfg + &slv_ddrc_mpu0_cfg &slv_qpic_cfg &slv_ddrc_cfg + &slv_pcnoc_cfg &slv_ess_apu_cfg &slv_imem_cfg + &slv_srif &slv_prng &slv_qdss_cfg + &slv_wss0_apu_cfg &slv_ddrc_apu_cfg &slv_gcnt + &slv_tlmm &slv_wss0_vmidmt_cfg &slv_prng_apu_cfg + &slv_boot_rom &slv_security &slv_spdm + &slv_pcnoc_mpu_cfg &slv_ddrc_mpu2_cfg &slv_ess_vmidmt_cfg + &slv_qhss_apu_cfg &slv_adss_vmidmt_cfg &slv_clk_ctl + &slv_adss_apu &slv_blsp_cfg &slv_usb2_cfg + &slv_srvc_pcnoc &slv_snoc_mpu_cfg &slv_wss1_vmidmt_cfg + &slv_sdcc_cfg &slv_snoc_cfg>; + }; + + mas_usb2_bam: mas-usb2-bam { + cell-id = ; + label = "mas-usb2-bam"; + qcom,buswidth = <8>; + qcom,ap-owned; + qcom,qport = <15>; + qcom,qos-mode = "fixed"; + qcom,connections = <&slv_pcnoc_snoc>; + qcom,prio1 = <1>; + qcom,prio0 = <1>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_tcsr &slv_mdio &slv_adss_cfg + &slv_fephy_cfg &slv_wss1_apu_cfg &slv_ddrc_mpu1_cfg + &slv_ddrc_mpu0_cfg &slv_qpic_cfg &slv_ddrc_cfg + &slv_pcnoc_cfg &slv_ess_apu_cfg &slv_imem_cfg + &slv_srif &slv_prng &slv_qdss_cfg + &slv_wss0_apu_cfg &slv_ddrc_apu_cfg &slv_gcnt + &slv_tlmm &slv_wss0_vmidmt_cfg &slv_prng_apu_cfg + &slv_boot_rom &slv_security &slv_spdm + &slv_pcnoc_mpu_cfg &slv_ddrc_mpu2_cfg &slv_ess_vmidmt_cfg + &slv_qhss_apu_cfg &slv_adss_vmidmt_cfg &slv_clk_ctl + &slv_adss_apu &slv_blsp_cfg &slv_usb2_cfg + &slv_srvc_pcnoc &slv_snoc_mpu_cfg &slv_wss1_vmidmt_cfg + &slv_sdcc_cfg &slv_snoc_cfg>; + }; + + mas_adss_dma0: mas-adss-dma0 { + cell-id = ; + label = "mas-adss-dma0"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = <&pcnoc_m_1>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_tcsr &slv_mdio &slv_adss_cfg + &slv_fephy_cfg &slv_wss1_apu_cfg &slv_ddrc_mpu1_cfg + &slv_ddrc_mpu0_cfg &slv_qpic_cfg &slv_ddrc_cfg + &slv_pcnoc_cfg &slv_ess_apu_cfg &slv_imem_cfg + &slv_srif &slv_prng &slv_qdss_cfg + &slv_wss0_apu_cfg &slv_ddrc_apu_cfg &slv_gcnt + &slv_tlmm &slv_wss0_vmidmt_cfg &slv_prng_apu_cfg + &slv_boot_rom &slv_security &slv_spdm + &slv_pcnoc_mpu_cfg &slv_ddrc_mpu2_cfg &slv_ess_vmidmt_cfg + &slv_qhss_apu_cfg &slv_adss_vmidmt_cfg &slv_clk_ctl + &slv_adss_apu &slv_blsp_cfg &slv_usb2_cfg + &slv_srvc_pcnoc &slv_snoc_mpu_cfg &slv_wss1_vmidmt_cfg + &slv_sdcc_cfg &slv_snoc_cfg>; + }; + + mas_adss_dma1: mas-adss-dma1 { + cell-id = ; + label = "mas-adss-dma1"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = <&pcnoc_m_1>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_tcsr &slv_mdio &slv_adss_cfg + &slv_fephy_cfg &slv_wss1_apu_cfg &slv_ddrc_mpu1_cfg + &slv_ddrc_mpu0_cfg &slv_qpic_cfg &slv_ddrc_cfg + &slv_pcnoc_cfg &slv_ess_apu_cfg &slv_imem_cfg + &slv_srif &slv_prng &slv_qdss_cfg + &slv_wss0_apu_cfg &slv_ddrc_apu_cfg &slv_gcnt + &slv_tlmm &slv_wss0_vmidmt_cfg &slv_prng_apu_cfg + &slv_boot_rom &slv_security &slv_spdm + &slv_pcnoc_mpu_cfg &slv_ddrc_mpu2_cfg &slv_ess_vmidmt_cfg + &slv_qhss_apu_cfg &slv_adss_vmidmt_cfg &slv_clk_ctl + &slv_adss_apu &slv_blsp_cfg &slv_usb2_cfg + &slv_srvc_pcnoc &slv_snoc_mpu_cfg &slv_wss1_vmidmt_cfg + &slv_sdcc_cfg &slv_snoc_cfg>; + }; + + mas_adss_dma2: mas-adss-dma2 { + cell-id = ; + label = "mas-adss-dma2"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = <&pcnoc_m_1>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_tcsr &slv_mdio &slv_adss_cfg + &slv_fephy_cfg &slv_wss1_apu_cfg &slv_ddrc_mpu1_cfg + &slv_ddrc_mpu0_cfg &slv_qpic_cfg &slv_ddrc_cfg + &slv_pcnoc_cfg &slv_ess_apu_cfg &slv_imem_cfg + &slv_srif &slv_prng &slv_qdss_cfg + &slv_wss0_apu_cfg &slv_ddrc_apu_cfg &slv_gcnt + &slv_tlmm &slv_wss0_vmidmt_cfg &slv_prng_apu_cfg + &slv_boot_rom &slv_security &slv_spdm + &slv_pcnoc_mpu_cfg &slv_ddrc_mpu2_cfg &slv_ess_vmidmt_cfg + &slv_qhss_apu_cfg &slv_adss_vmidmt_cfg &slv_clk_ctl + &slv_adss_apu &slv_blsp_cfg &slv_usb2_cfg + &slv_srvc_pcnoc &slv_snoc_mpu_cfg &slv_wss1_vmidmt_cfg + &slv_sdcc_cfg &slv_snoc_cfg>; + }; + + mas_adss_dma3: mas-adss-dma3 { + cell-id = ; + label = "mas-adss-dma3"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = <&pcnoc_m_1>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_tcsr &slv_mdio &slv_adss_cfg + &slv_fephy_cfg &slv_wss1_apu_cfg &slv_ddrc_mpu1_cfg + &slv_ddrc_mpu0_cfg &slv_qpic_cfg &slv_ddrc_cfg + &slv_pcnoc_cfg &slv_ess_apu_cfg &slv_imem_cfg + &slv_srif &slv_prng &slv_qdss_cfg + &slv_wss0_apu_cfg &slv_ddrc_apu_cfg &slv_gcnt + &slv_tlmm &slv_wss0_vmidmt_cfg &slv_prng_apu_cfg + &slv_boot_rom &slv_security &slv_spdm + &slv_pcnoc_mpu_cfg &slv_ddrc_mpu2_cfg &slv_ess_vmidmt_cfg + &slv_qhss_apu_cfg &slv_adss_vmidmt_cfg &slv_clk_ctl + &slv_adss_apu &slv_blsp_cfg &slv_usb2_cfg + &slv_srvc_pcnoc &slv_snoc_mpu_cfg &slv_wss1_vmidmt_cfg + &slv_sdcc_cfg &slv_snoc_cfg>; + }; + + mas_qpic_bam: mas-qpic-bam { + cell-id = ; + label = "mas-qpic-bam"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = <&pcnoc_m_0>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_tcsr &slv_mdio &slv_adss_cfg + &slv_fephy_cfg &slv_wss1_apu_cfg &slv_ddrc_mpu1_cfg + &slv_ddrc_mpu0_cfg &slv_qpic_cfg &slv_ddrc_cfg + &slv_pcnoc_cfg &slv_ess_apu_cfg &slv_imem_cfg + &slv_srif &slv_prng &slv_qdss_cfg + &slv_wss0_apu_cfg &slv_ddrc_apu_cfg &slv_gcnt + &slv_tlmm &slv_wss0_vmidmt_cfg &slv_prng_apu_cfg + &slv_boot_rom &slv_security &slv_spdm + &slv_pcnoc_mpu_cfg &slv_ddrc_mpu2_cfg &slv_ess_vmidmt_cfg + &slv_qhss_apu_cfg &slv_adss_vmidmt_cfg &slv_clk_ctl + &slv_adss_apu &slv_blsp_cfg &slv_usb2_cfg + &slv_srvc_pcnoc &slv_snoc_mpu_cfg &slv_wss1_vmidmt_cfg + &slv_sdcc_cfg &slv_snoc_cfg>; + }; + + mas_spdm: mas-spdm { + cell-id = ; + label = "mas-spdm"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = <&pcnoc_m_0>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_tcsr &slv_mdio &slv_adss_cfg + &slv_fephy_cfg &slv_wss1_apu_cfg &slv_ddrc_mpu1_cfg + &slv_ddrc_mpu0_cfg &slv_qpic_cfg &slv_ddrc_cfg + &slv_pcnoc_cfg &slv_ess_apu_cfg &slv_imem_cfg + &slv_srif &slv_prng &slv_qdss_cfg + &slv_wss0_apu_cfg &slv_ddrc_apu_cfg &slv_gcnt + &slv_tlmm &slv_wss0_vmidmt_cfg &slv_prng_apu_cfg + &slv_boot_rom &slv_security &slv_spdm + &slv_pcnoc_mpu_cfg &slv_ddrc_mpu2_cfg &slv_ess_vmidmt_cfg + &slv_qhss_apu_cfg &slv_adss_vmidmt_cfg &slv_clk_ctl + &slv_adss_apu &slv_blsp_cfg &slv_usb2_cfg + &slv_srvc_pcnoc &slv_snoc_mpu_cfg &slv_wss1_vmidmt_cfg + &slv_sdcc_cfg &slv_snoc_cfg>; + }; + + mas_pcnoc_cfg: mas-pcnoc-cfg { + cell-id = ; + label = "mas-pcnoc-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = <&slv_srvc_pcnoc>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + }; + + mas_tic: mas-tic { + cell-id = ; + label = "mas-tic"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = <&pcnoc_int_0 &slv_pcnoc_snoc>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + }; + + mas_sdcc_bam: mas-sdcc-bam { + cell-id = ; + label = "mas-sdcc-bam"; + qcom,buswidth = <8>; + qcom,ap-owned; + qcom,qport = <14>; + qcom,qos-mode = "fixed"; + qcom,connections = <&slv_pcnoc_snoc>; + qcom,prio1 = <0>; + qcom,prio0 = <0>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_tcsr &slv_mdio &slv_adss_cfg + &slv_fephy_cfg &slv_wss1_apu_cfg &slv_ddrc_mpu1_cfg + &slv_ddrc_mpu0_cfg &slv_qpic_cfg &slv_ddrc_cfg + &slv_pcnoc_cfg &slv_ess_apu_cfg &slv_imem_cfg + &slv_srif &slv_prng &slv_qdss_cfg + &slv_wss0_apu_cfg &slv_ddrc_apu_cfg &slv_gcnt + &slv_tlmm &slv_wss0_vmidmt_cfg &slv_prng_apu_cfg + &slv_boot_rom &slv_security &slv_spdm + &slv_pcnoc_mpu_cfg &slv_ddrc_mpu2_cfg &slv_ess_vmidmt_cfg + &slv_qhss_apu_cfg &slv_adss_vmidmt_cfg &slv_clk_ctl + &slv_adss_apu &slv_blsp_cfg &slv_usb2_cfg + &slv_srvc_pcnoc &slv_snoc_mpu_cfg &slv_wss1_vmidmt_cfg + &slv_sdcc_cfg &slv_snoc_cfg>; + }; + + mas_snoc_pcnoc: mas-snoc-pcnoc { + cell-id = ; + label = "mas-snoc-pcnoc"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,qport = <16>; + qcom,qos-mode = "fixed"; + qcom,connections = <&pcnoc_int_0>; + qcom,prio1 = <0>; + qcom,prio0 = <0>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + }; + + mas_qdss_dap: mas-qdss-dap { + cell-id = ; + label = "mas-qdss-dap"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = <&pcnoc_int_0 &slv_pcnoc_snoc>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + }; + + mas_ddrc_snoc: mas-ddrc-snoc { + cell-id = ; + label = "mas-ddrc-snoc"; + qcom,buswidth = <16>; + qcom,ap-owned; + qcom,connections = <&snoc_int_0 &snoc_int_1 + &slv_pcie>; + qcom,bus-dev = <&fab_snoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_snoc_ddrc_m1 &slv_srvc_snoc>; + }; + + mas_wss_0: mas-wss-0 { + cell-id = ; + label = "mas-wss-0"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,qport = <26>; + qcom,qos-mode = "fixed"; + qcom,connections = <&snoc_int_0 &slv_snoc_ddrc_m1>; + qcom,prio1 = <0>; + qcom,prio0 = <0>; + qcom,bus-dev = <&fab_snoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_usb3_cfg &slv_ess_cfg &slv_pcie + &slv_wss1_cfg &slv_wss0_cfg &slv_crypto_cfg + &slv_srvc_snoc>; + }; + + mas_wss_1: mas-wss-1 { + cell-id = ; + label = "mas-wss-1"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,qport = <27>; + qcom,qos-mode = "fixed"; + qcom,connections = <&snoc_int_0 &slv_snoc_ddrc_m1>; + qcom,prio1 = <0>; + qcom,prio0 = <0>; + qcom,bus-dev = <&fab_snoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_usb3_cfg &slv_ess_cfg &slv_pcie + &slv_wss1_cfg &slv_wss0_cfg &slv_crypto_cfg + &slv_srvc_snoc>; + }; + + mas_crypto: mas-crypto { + cell-id = ; + label = "mas-crypto"; + qcom,buswidth = <8>; + qcom,ap-owned; + qcom,qport = <5>; + qcom,qos-mode = "fixed"; + qcom,connections = <&snoc_int_0 &snoc_int_1 + &slv_snoc_ddrc_m1>; + qcom,prio1 = <0>; + qcom,prio0 = <0>; + qcom,bus-dev = <&fab_snoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_usb3_cfg &slv_ess_cfg &slv_a7ss + &slv_pcie &slv_qdss_stm &slv_crypto_cfg + &slv_srvc_snoc>; + }; + + mas_ess: mas-ess { + cell-id = ; + label = "mas-ess"; + qcom,buswidth = <8>; + qcom,ap-owned; + qcom,qport = <44>; + qcom,qos-mode = "fixed"; + qcom,connections = <&snoc_int_0 &slv_snoc_ddrc_m1>; + qcom,prio1 = <0>; + qcom,prio0 = <0>; + qcom,bus-dev = <&fab_snoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_usb3_cfg &slv_ess_cfg &slv_a7ss + &slv_pcie &slv_qdss_stm &slv_wss1_cfg + &slv_wss0_cfg &slv_crypto_cfg &slv_srvc_snoc>; + }; + + mas_pcie: mas-pcie { + cell-id = ; + label = "mas-pcie"; + qcom,buswidth = <8>; + qcom,ap-owned; + qcom,qport = <6>; + qcom,qos-mode = "fixed"; + qcom,connections = <&snoc_int_0 &slv_snoc_ddrc_m1>; + qcom,prio1 = <0>; + qcom,prio0 = <0>; + qcom,bus-dev = <&fab_snoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_usb3_cfg &slv_ess_cfg &slv_pcie + &slv_qdss_stm &slv_wss1_cfg &slv_wss0_cfg + &slv_crypto_cfg &slv_srvc_snoc>; + }; + + mas_usb3: mas-usb3 { + cell-id = ; + label = "mas-usb3"; + qcom,buswidth = <8>; + qcom,ap-owned; + qcom,qport = <7>; + qcom,qos-mode = "fixed"; + qcom,connections = <&snoc_int_0 &slv_snoc_ddrc_m1>; + qcom,prio1 = <0>; + qcom,prio0 = <0>; + qcom,bus-dev = <&fab_snoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_usb3_cfg &slv_ess_cfg &slv_a7ss + &slv_pcie &slv_qdss_stm &slv_wss1_cfg + &slv_wss0_cfg &slv_crypto_cfg &slv_srvc_snoc>; + }; + + mas_qdss_etr: mas-qdss-etr { + cell-id = ; + label = "mas-qdss-etr"; + qcom,buswidth = <8>; + qcom,ap-owned; + qcom,qport = <544>; + qcom,qos-mode = "fixed"; + qcom,connections = <&qdss_int>; + qcom,prio1 = <0>; + qcom,prio0 = <0>; + qcom,bus-dev = <&fab_snoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_usb3_cfg &slv_ess_cfg &slv_a7ss + &slv_pcie &slv_qdss_stm &slv_wss1_cfg + &slv_wss0_cfg &slv_crypto_cfg &slv_srvc_snoc>; + }; + + mas_qdss_bamndp: mas-qdss-bamndp { + cell-id = ; + label = "mas-qdss-bamndp"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,qport = <576>; + qcom,qos-mode = "fixed"; + qcom,connections = <&qdss_int>; + qcom,prio1 = <0>; + qcom,prio0 = <0>; + qcom,bus-dev = <&fab_snoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_usb3_cfg &slv_ess_cfg &slv_a7ss + &slv_pcie &slv_qdss_stm &slv_wss1_cfg + &slv_wss0_cfg &slv_crypto_cfg &slv_srvc_snoc>; + }; + + mas_pcnoc_snoc: mas-pcnoc-snoc { + cell-id = ; + label = "mas-pcnoc-snoc"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,qport = <384>; + qcom,qos-mode = "fixed"; + qcom,connections = <&snoc_int_0 &snoc_int_1 + &slv_snoc_ddrc_m1>; + qcom,prio1 = <0>; + qcom,prio0 = <0>; + qcom,bus-dev = <&fab_snoc>; + qcom,mas-rpm-id = ; + qcom,blacklist = <&slv_srvc_snoc>; + }; + + mas_snoc_cfg: mas-snoc-cfg { + cell-id = ; + label = "mas-snoc-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = <&slv_srvc_snoc>; + qcom,bus-dev = <&fab_snoc>; + qcom,mas-rpm-id = ; + }; + + /*Internal nodes*/ + + + pcnoc_m_0: pcnoc-m-0 { + cell-id = ; + label = "pcnoc-m-0"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,qport = <12>; + qcom,qos-mode = "fixed"; + qcom,connections = <&slv_pcnoc_snoc>; + qcom,prio1 = <1>; + qcom,prio0 = <1>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,slv-rpm-id = ; + }; + + pcnoc_m_1: pcnoc-m-1 { + cell-id = ; + label = "pcnoc-m-1"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,qport = <13>; + qcom,qos-mode = "fixed"; + qcom,connections = <&slv_pcnoc_snoc>; + qcom,prio1 = <1>; + qcom,prio0 = <1>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,slv-rpm-id = ; + }; + + pcnoc_int_0: pcnoc-int-0 { + cell-id = ; + label = "pcnoc-int-0"; + qcom,buswidth = <8>; + qcom,ap-owned; + qcom,connections = < &pcnoc_s_1 &pcnoc_s_2 &pcnoc_s_0 + &pcnoc_s_4 &pcnoc_s_5 + &pcnoc_s_6 &pcnoc_s_7 + &pcnoc_s_8 &pcnoc_s_9 + &pcnoc_s_3>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,slv-rpm-id = ; + }; + + pcnoc_s_0: pcnoc-s-0 { + cell-id = ; + label = "pcnoc-s-0"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = <&slv_clk_ctl &slv_tcsr &slv_security + &slv_tlmm>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,slv-rpm-id = ; + }; + + pcnoc_s_1: pcnoc-s-1 { + cell-id = ; + label = "pcnoc-s-1"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = < &slv_prng_apu_cfg &slv_prng&slv_imem_cfg>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,slv-rpm-id = ; + }; + + pcnoc_s_2: pcnoc-s-2 { + cell-id = ; + label = "pcnoc-s-2"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = < &slv_spdm &slv_pcnoc_mpu_cfg &slv_pcnoc_cfg + &slv_boot_rom>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,slv-rpm-id = ; + }; + + pcnoc_s_3: pcnoc-s-3 { + cell-id = ; + label = "pcnoc-s-3"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = < &slv_qdss_cfg&slv_gcnt &slv_snoc_cfg + &slv_snoc_mpu_cfg>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,slv-rpm-id = ; + }; + + pcnoc_s_4: pcnoc-s-4 { + cell-id = ; + label = "pcnoc-s-4"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = <&slv_adss_cfg &slv_adss_vmidmt_cfg &slv_adss_apu>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,slv-rpm-id = ; + }; + + pcnoc_s_5: pcnoc-s-5 { + cell-id = ; + label = "pcnoc-s-5"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = <&slv_qhss_apu_cfg &slv_fephy_cfg &slv_mdio + &slv_srif>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,slv-rpm-id = ; + }; + + pcnoc_s_6: pcnoc-s-6 { + cell-id = ; + label = "pcnoc-s-6"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = < &slv_ddrc_mpu0_cfg &slv_ddrc_apu_cfg &slv_ddrc_mpu2_cfg + &slv_ddrc_cfg &slv_ddrc_mpu1_cfg>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,slv-rpm-id = ; + }; + + pcnoc_s_7: pcnoc-s-7 { + cell-id = ; + label = "pcnoc-s-7"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = < &slv_ess_apu_cfg &slv_usb2_cfg&slv_ess_vmidmt_cfg>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,slv-rpm-id = ; + }; + + pcnoc_s_8: pcnoc-s-8 { + cell-id = ; + label = "pcnoc-s-8"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = < &slv_sdcc_cfg &slv_qpic_cfg&slv_blsp_cfg>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,slv-rpm-id = ; + }; + + pcnoc_s_9: pcnoc-s-9 { + cell-id = ; + label = "pcnoc-s-9"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,connections = < &slv_wss1_apu_cfg &slv_wss1_vmidmt_cfg&slv_wss0_vmidmt_cfg + &slv_wss0_apu_cfg>; + qcom,bus-dev = <&fab_pcnoc>; + qcom,mas-rpm-id = ; + qcom,slv-rpm-id = ; + }; + + snoc_int_0: snoc-int-0 { + cell-id = ; + label = "snoc-int-0"; + qcom,buswidth = <8>; + qcom,ap-owned; + qcom,connections = < &slv_ocimem&slv_qdss_stm>; + qcom,bus-dev = <&fab_snoc>; + qcom,mas-rpm-id = ; + qcom,slv-rpm-id = ; + }; + + snoc_int_1: snoc-int-1 { + cell-id = ; + label = "snoc-int-1"; + qcom,buswidth = <8>; + qcom,ap-owned; + qcom,connections = < &slv_crypto_cfg &slv_a7ss &slv_ess_cfg + &slv_usb3_cfg &slv_wss1_cfg + &slv_wss0_cfg>; + qcom,bus-dev = <&fab_snoc>; + qcom,mas-rpm-id = ; + qcom,slv-rpm-id = ; + }; + + qdss_int: qdss-int { + cell-id = ; + label = "qdss-int"; + qcom,buswidth = <8>; + qcom,ap-owned; + qcom,connections = <&snoc_int_0 &slv_snoc_ddrc_m1>; + qcom,bus-dev = <&fab_snoc>; + qcom,mas-rpm-id = ; + qcom,slv-rpm-id = ; + }; + /*Slaves*/ + + slv_clk_ctl:slv-clk-ctl { + cell-id = ; + label = "slv-clk-ctl"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_security:slv-security { + cell-id = ; + label = "slv-security"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_tcsr:slv-tcsr { + cell-id = ; + label = "slv-tcsr"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_tlmm:slv-tlmm { + cell-id = ; + label = "slv-tlmm"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_imem_cfg:slv-imem-cfg { + cell-id = ; + label = "slv-imem-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_prng:slv-prng { + cell-id = ; + label = "slv-prng"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_prng_apu_cfg:slv-prng-apu-cfg { + cell-id = ; + label = "slv-prng-apu-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_boot_rom:slv-boot-rom { + cell-id = ; + label = "slv-boot-rom"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_spdm:slv-spdm { + cell-id = ; + label = "slv-spdm"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_pcnoc_cfg:slv-pcnoc-cfg { + cell-id = ; + label = "slv-pcnoc-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_pcnoc_mpu_cfg:slv-pcnoc-mpu-cfg { + cell-id = ; + label = "slv-pcnoc-mpu-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_gcnt:slv-gcnt { + cell-id = ; + label = "slv-gcnt"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_qdss_cfg:slv-qdss-cfg { + cell-id = ; + label = "slv-qdss-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_snoc_cfg:slv-snoc-cfg { + cell-id = ; + label = "slv-snoc-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_snoc_mpu_cfg:slv-snoc-mpu-cfg { + cell-id = ; + label = "slv-snoc-mpu-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_adss_cfg:slv-adss-cfg { + cell-id = ; + label = "slv-adss-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_adss_apu:slv-adss-apu { + cell-id = ; + label = "slv-adss-apu"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_adss_vmidmt_cfg:slv-adss-vmidmt-cfg { + cell-id = ; + label = "slv-adss-vmidmt-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_qhss_apu_cfg:slv-qhss-apu-cfg { + cell-id = ; + label = "slv-qhss-apu-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_mdio:slv-mdio { + cell-id = ; + label = "slv-mdio"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_fephy_cfg:slv-fephy-cfg { + cell-id = ; + label = "slv-fephy-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_srif:slv-srif { + cell-id = ; + label = "slv-srif"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_ddrc_cfg:slv-ddrc-cfg { + cell-id = ; + label = "slv-ddrc-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_ddrc_apu_cfg:slv-ddrc-apu-cfg { + cell-id = ; + label = "slv-ddrc-apu-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_ddrc_mpu0_cfg:slv-ddrc-mpu0-cfg { + cell-id = ; + label = "slv-ddrc-mpu0-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_ddrc_mpu1_cfg:slv-ddrc-mpu1-cfg { + cell-id = ; + label = "slv-ddrc-mpu1-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_ddrc_mpu2_cfg:slv-ddrc-mpu2-cfg { + cell-id = ; + label = "slv-ddrc-mpu2-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_ess_vmidmt_cfg:slv-ess-vmidmt-cfg { + cell-id = ; + label = "slv-ess-vmidmt-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_ess_apu_cfg:slv-ess-apu-cfg { + cell-id = ; + label = "slv-ess-apu-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_usb2_cfg:slv-usb2-cfg { + cell-id = ; + label = "slv-usb2-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_blsp_cfg:slv-blsp-cfg { + cell-id = ; + label = "slv-blsp-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_qpic_cfg:slv-qpic-cfg { + cell-id = ; + label = "slv-qpic-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_sdcc_cfg:slv-sdcc-cfg { + cell-id = ; + label = "slv-sdcc-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_wss0_vmidmt_cfg:slv-wss0-vmidmt-cfg { + cell-id = ; + label = "slv-wss0-vmidmt-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_wss0_apu_cfg:slv-wss0-apu-cfg { + cell-id = ; + label = "slv-wss0-apu-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_wss1_vmidmt_cfg:slv-wss1-vmidmt-cfg { + cell-id = ; + label = "slv-wss1-vmidmt-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_wss1_apu_cfg:slv-wss1-apu-cfg { + cell-id = ; + label = "slv-wss1-apu-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_pcnoc_snoc:slv-pcnoc-snoc { + cell-id = ; + label = "slv-pcnoc-snoc"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_srvc_pcnoc:slv-srvc-pcnoc { + cell-id = ; + label = "slv-srvc-pcnoc"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_pcnoc>; + qcom,slv-rpm-id = ; + }; + + slv_snoc_ddrc_m1:slv-snoc-ddrc-m1 { + cell-id = ; + label = "slv-snoc-ddrc-m1"; + qcom,buswidth = <8>; + qcom,ap-owned; + qcom,bus-dev = <&fab_snoc>; + qcom,slv-rpm-id = ; + }; + + slv_a7ss:slv-a7ss { + cell-id = ; + label = "slv-a7ss"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_snoc>; + qcom,slv-rpm-id = ; + }; + + slv_ocimem:slv-ocimem { + cell-id = ; + label = "slv-ocimem"; + qcom,buswidth = <8>; + qcom,ap-owned; + qcom,bus-dev = <&fab_snoc>; + qcom,slv-rpm-id = ; + }; + + slv_wss0_cfg:slv-wss0-cfg { + cell-id = ; + label = "slv-wss0-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_snoc>; + qcom,slv-rpm-id = ; + }; + + slv_wss1_cfg:slv-wss1-cfg { + cell-id = ; + label = "slv-wss1-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_snoc>; + qcom,slv-rpm-id = ; + }; + + slv_pcie:slv-pcie { + cell-id = ; + label = "slv-pcie"; + qcom,buswidth = <8>; + qcom,ap-owned; + qcom,bus-dev = <&fab_snoc>; + qcom,slv-rpm-id = ; + }; + + slv_usb3_cfg:slv-usb3-cfg { + cell-id = ; + label = "slv-usb3-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_snoc>; + qcom,slv-rpm-id = ; + }; + + slv_crypto_cfg:slv-crypto-cfg { + cell-id = ; + label = "slv-crypto-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_snoc>; + qcom,slv-rpm-id = ; + }; + + slv_ess_cfg:slv-ess-cfg { + cell-id = ; + label = "slv-ess-cfg"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_snoc>; + qcom,slv-rpm-id = ; + }; + + slv_qdss_stm:slv-qdss-stm { + cell-id = ; + label = "slv-qdss-stm"; + qcom,buswidth = <4>; + qcom,ap-owned; + qcom,bus-dev = <&fab_snoc>; + qcom,slv-rpm-id = ; + }; + + slv_srvc_snoc:slv-srvc-snoc { + cell-id = ; + label = "slv-srvc-snoc"; + qcom,buswidth = <8>; + qcom,ap-owned; + qcom,bus-dev = <&fab_snoc>; + qcom,slv-rpm-id = ; + }; + }; +}; + +}; diff --git a/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4019-rt-acrh17.dts b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4019-rt-acrh17.dts new file mode 100644 index 000000000..6ee749942 --- /dev/null +++ b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4019-rt-acrh17.dts @@ -0,0 +1,244 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "qcom-ipq4019-ap.dk04.1.dtsi" +#include "qcom-ipq4019-bus.dtsi" +#include +#include +#include + +/ { + model = "ASUS RT-ACRH17"; + compatible = "asus,rt-acrh17", "qcom,ipq4019"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; + + aliases { + led-boot = &power; + led-failsafe = &power; + led-running = &power; + led-upgrade = &power; + }; + + reserved-memory { + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges; + + rsvd1@87E00000 { + reg = <0x87e00000 0x200000>; + no-map; + }; + }; + + soc { + spi_0: spi@78b5000 { + status = "disabled"; + }; + + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "ok"; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + + wifi0: wifi@a000000 { + status = "ok"; + core-id = <0x0>; + qca,msi_addr = <0x0b006040>; + qca,msi_base = <0x40>; + wifi_led_num = <2>; /* Wifi 2G */ + wifi_led_source = <0>; /* source id 0 */ + qcom,mtd-name = "0:ART"; + qcom,cal-offset = <0x1000>; + qcom,cal-len = <12064>; + }; + + wifi1: wifi@a800000 { + status = "disabled"; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&tlmm 11 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power: status { + label = "rt-acrh17:blue:status"; + gpios = <&tlmm 40 GPIO_ACTIVE_LOW>; + }; + + lan1 { + label = "rt-acrh17:blue:lan1"; + gpios = <&tlmm 45 GPIO_ACTIVE_LOW>; + }; + + lan2 { + label = "rt-acrh17:blue:lan2"; + gpios = <&tlmm 43 GPIO_ACTIVE_LOW>; + }; + + lan3 { + label = "rt-acrh17:blue:lan3"; + gpios = <&tlmm 42 GPIO_ACTIVE_LOW>; + }; + + lan4 { + label = "rt-acrh17:blue:lan4"; + gpios = <&tlmm 49 GPIO_ACTIVE_LOW>; + }; + + wan_blue { + label = "rt-acrh17:blue:wan"; + gpios = <&tlmm 61 GPIO_ACTIVE_HIGH>; + }; + + wan_red { + label = "rt-acrh17:red:wan"; + gpios = <&tlmm 68 GPIO_ACTIVE_HIGH>; + }; + + wlan2g { + label = "rt-acrh17:blue:wlan2g"; + gpios = <&tlmm 52 GPIO_ACTIVE_LOW>; + }; + + wlan5g { + label = "rt-acrh17:blue:wlan5g"; + gpios = <&tlmm 54 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "Bootloader"; + reg = <0x000000000000 0x000000400000>; + read-only; + }; + partition@1 { + label = "UBI_DEV"; + reg = <0x000000400000 0x000007C00000>; + }; + }; + }; +}; + +&pcie0 { + status = "okay"; + perst-gpio = <&tlmm 38 GPIO_ACTIVE_LOW>; + wake-gpio = <&tlmm 50 GPIO_ACTIVE_LOW>; + clkreq-gpio = <&tlmm 39 GPIO_ACTIVE_LOW>; +}; + +&qpic_bam { + status = "okay"; +}; + +&nand_pins { + pullups { + pins = "gpio53", "gpio58", + "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio55", "gpio56", + "gpio57", "gpio60", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio69"; + function = "qpic"; + bias-pull-down; + }; +}; + +&i2c_0_pins { + pinmux { + function = "blsp_i2c0"; + pins = "gpio10"; + }; + pinconf { + pins = "gpio10"; + drive-strength = <16>; + bias-disable; + }; +}; diff --git a/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4028-wpj428.dts b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4028-wpj428.dts new file mode 100644 index 000000000..00fc24dba --- /dev/null +++ b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4028-wpj428.dts @@ -0,0 +1,279 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2017, Christian Mehlis + * Copyright (c) 2017-2018, Sven Eckelmann + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "qcom-ipq4019.dtsi" +#include "qcom-ipq4019-bus.dtsi" +#include +#include +#include + +/ { + model = "Compex WPJ428"; + compatible = "compex,wpj428", "qcom,ipq4019"; + + reserved-memory { + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges; + + tz_apps@87b80000 { + reg = <0x87b80000 0x280000>; + no-map; + }; + + smem@87e00000 { + reg = <0x87e00000 0x080000>; + no-map; + }; + + tz@87e80000 { + reg = <0x87e80000 0x180000>; + no-map; + }; + }; + + soc { + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2: usb2@60f8800 { + status = "okay"; + }; + + serial@78af000 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + usb3: usb3@8af8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + switch_lan_bmp = <0x10>; + switch_wan_bmp = <0x20>; + + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + aliases { + led-boot = &status; + led-failsafe = &status; + led-upgrade = &status; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status: rss4 { + label = "wpj428:green:rss4"; + gpios = <&tlmm 5 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + rss3 { + label = "wpj428:green:rss3"; + gpios = <&tlmm 4 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + + beeper: beeper { + compatible = "gpio-beeper"; + gpios = <&tlmm 58 GPIO_ACTIVE_HIGH>; + }; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pin { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + pin_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&spi_0 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition0@0 { + label = "0:SBL1"; + reg = <0x00000000 0x00040000>; + read-only; + }; + partition1@40000 { + label = "0:MIBIB"; + reg = <0x00040000 0x00020000>; + read-only; + }; + partition2@60000 { + label = "0:QSEE"; + reg = <0x00060000 0x00060000>; + read-only; + }; + partition3@c0000 { + label = "0:CDT"; + reg = <0x000c0000 0x00010000>; + read-only; + }; + partition4@d0000 { + label = "0:DDRPARAMS"; + reg = <0x000d0000 0x00010000>; + read-only; + }; + partition5@e0000 { + label = "0:APPSBLENV"; /* uboot env*/ + reg = <0x000e0000 0x00010000>; + read-only; + }; + partition5@f0000 { + label = "0:APPSBL"; /* uboot */ + reg = <0x000f0000 0x00080000>; + read-only; + }; + partition5@170000 { + label = "0:ART"; + reg = <0x00170000 0x00010000>; + read-only; + }; + partition6@180000 { + label = "firmware"; + reg = <0x00180000 0x01e80000>; + }; + }; + }; +}; + +&cryptobam { + status = "okay"; +}; + +&gmac0 { + vlan_tag = <1 0x31>; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; +}; + +&wifi1 { + status = "okay"; +}; diff --git a/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4029-gl-b1300.dts b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4029-gl-b1300.dts new file mode 100644 index 000000000..401a133b8 --- /dev/null +++ b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4029-gl-b1300.dts @@ -0,0 +1,314 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "GL.iNet GL-B1300"; + compatible = "glinet,gl-b1300", "qcom,ipq4019"; + + aliases { + led-boot = &power; + led-failsafe = &power; + led-running = &power; + led-upgrade = &power; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; + + reserved-memory { + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges; + + apps_bl@87000000 { + reg = <0x87000000 0x400000>; + no-map; + }; + + sbl@87400000 { + reg = <0x87400000 0x100000>; + no-map; + }; + + cnss_debug@87500000 { + reg = <0x87500000 0x600000>; + no-map; + }; + + cpu_context_dump@87b00000 { + reg = <0x87b00000 0x080000>; + no-map; + }; + + tz_apps@87b80000 { + reg = <0x87b80000 0x280000>; + no-map; + }; + + smem@87e00000 { + reg = <0x87e00000 0x080000>; + no-map; + }; + + tz@87e80000 { + reg = <0x87e80000 0x180000>; + no-map; + }; + }; + + soc { + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "okay"; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + usb2@60f8800 { + status = "okay"; + }; + + serial@78af000 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + usb3@8af8800 { + status = "okay"; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + switch_lan_bmp = <0x18>; + switch_wan_bmp = <0x20>; + }; + + edma@c080000 { + status = "okay"; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + wps { + label = "wps"; + gpios = <&tlmm 5 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + reset { + label = "reset"; + gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power: power { + label = "gl-b1300:green:power"; + gpios = <&tlmm 4 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + mesh { + label = "gl-b1300:green:mesh"; + gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; + }; + + wlan { + label = "gl-b1300:green:wlan"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&spi_0 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>; + + mx25l25635f@0 { + compatible = "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + spi-max-frequency = <24000000>; + + SBL1@0 { + label = "SBL1"; + reg = <0x0 0x40000>; + read-only; + }; + + MIBIB@40000 { + label = "MIBIB"; + reg = <0x40000 0x20000>; + read-only; + }; + + QSEE@60000 { + label = "QSEE"; + reg = <0x60000 0x60000>; + read-only; + }; + + CDT@c0000 { + label = "CDT"; + reg = <0xc0000 0x10000>; + read-only; + }; + + DDRPARAMS@d0000 { + label = "DDRPARAMS"; + reg = <0xd0000 0x10000>; + read-only; + }; + + APPSBLENV@e0000 { + label = "APPSBLENV"; + reg = <0xe0000 0x10000>; + read-only; + }; + + APPSBL@f0000 { + label = "APPSBL"; + reg = <0xf0000 0x80000>; + read-only; + }; + + ART@170000 { + label = "ART"; + reg = <0x170000 0x10000>; + read-only; + }; + + firmware@180000 { + label = "firmware"; + reg = <0x180000 0x1e80000>; + }; + }; +}; + +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + }; + pinmux_cs { + function = "gpio"; + pins = "gpio54"; + }; + pinconf { + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + pinconf_cs { + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&gmac0 { + vlan_tag = <1 0x39>; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&wifi0 { + status = "okay"; +}; + +&wifi1 { + status = "okay"; +}; diff --git a/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4029-mr33.dts b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4029-mr33.dts new file mode 100644 index 000000000..a709ae96b --- /dev/null +++ b/target/linux/ipq40xx/files-4.14/arch/arm/boot/dts/qcom-ipq4029-mr33.dts @@ -0,0 +1,402 @@ +/* + * Device Tree Source for Meraki MR33 (Stinkbug) + * + * Copyright (C) 2017 Chris Blake + * Copyright (C) 2017 Christian Lamparter + * + * Based on Cisco Meraki DTS from GPL release r25-linux-3.14-20170427 + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without + * any warranty of any kind, whether express or implied. + */ + +#include "qcom-ipq4019.dtsi" +#include "qcom-ipq4019-bus.dtsi" +#include +#include +#include + +/ { + model = "Meraki MR33 Access Point"; + compatible = "meraki,mr33", "qcom,ipq4019"; + + aliases { + led-boot = &status_green; + led-failsafe = &status_red; + led-running = &status_green; + led-upgrade = &power_orange; + }; + + /* Do we really need this defined? */ + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; + + reserved-memory { + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges; + + tz_apps@87b80000 { + reg = <0x87b80000 0x280000>; + reusable; + }; + + smem@87e00000 { + reg = <0x87e00000 0x080000>; + no-map; + }; + + tz@87e80000 { + reg = <0x87e80000 0x180000>; + no-map; + }; + }; + + soc { + mdio@90000 { + status = "okay"; + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + /delete-node/ ethernet-phy@0; + /delete-node/ ethernet-phy@2; + /delete-node/ ethernet-phy@3; + /delete-node/ ethernet-phy@4; + }; + + /* It is a 56-bit counter that supplies the count to the ARM arch + timers and without upstream driver */ + counter@4a1000 { + compatible = "qcom,qca-gcnt"; + reg = <0x4a1000 0x4>; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + serial@78af000 { + pinctrl-0 = <&serial_0_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + serial@78b0000 { + pinctrl-0 = <&serial_1_pins>; + pinctrl-names = "default"; + status = "okay"; + + bluetooth { + compatible = "ti,cc2650"; + enable-gpios = <&tlmm 12 GPIO_ACTIVE_LOW>; + }; + }; + + crypto@8e3a000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "okay"; + }; + + ess-switch@c000000 { + switch_mac_mode = <0x3>; /* mac mode for RGMII RMII */ + switch_lan_bmp = <0x0>; /* lan port bitmap */ + switch_wan_bmp = <0x10>; /* wan port bitmap */ + }; + + edma@c080000 { + qcom,single-phy; + qcom,num_gmac = <1>; + phy-mode = "rgmii-rxid"; + status = "okay"; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power_orange: power { + label = "mr33:orange:power"; + gpios = <&tlmm 49 GPIO_ACTIVE_LOW>; + panic-indicator; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&gmac0 { + qcom,phy_mdio_addr = <1>; + qcom,poll_required = <1>; + vlan_tag = <0 0x20>; +}; + +&i2c_0 { + pinctrl-0 = <&i2c_0_pins>; + pinctrl-names = "default"; + status = "okay"; + at24@50 { + compatible = "atmel,24c64"; + pagesize = <32>; + reg = <0x50>; + read-only; /* This holds our MAC & Meraki board-data */ + }; +}; + +&i2c_1 { + pinctrl-0 = <&i2c_1_pins>; + pinctrl-names = "default"; + status = "okay"; + + lp5562@30 { + enable-gpio = <&tlmm 48 GPIO_ACTIVE_HIGH>; + compatible = "ti,lp5562"; + clock-mode = /bits/8 <2>; + reg = <0x30>; + + /* RGB led */ + status_red: chan0 { + chan-name = "mr33:red:status"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + }; + + status_green: chan1 { + chan-name = "mr33:green:status"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + }; + + chan2 { + chan-name = "mr33:blue:status"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + }; + + chan3 { + chan-name = "mr33:white:status"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + }; + }; +}; + +&nand { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + + nand@0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "sbl1"; + reg = <0x000000000000 0x000000100000>; + read-only; + }; + partition@1 { + label = "mibib"; + reg = <0x000000100000 0x000000100000>; + read-only; + }; + partition@2 { + label = "bootconfig"; + reg = <0x000000200000 0x000000100000>; + read-only; + }; + partition@3 { + label = "qsee"; + reg = <0x000000300000 0x000000100000>; + read-only; + }; + partition@4 { + label = "qsee_alt"; + reg = <0x000000400000 0x000000100000>; + read-only; + }; + partition@5 { + label = "cdt"; + reg = <0x000000500000 0x000000080000>; + read-only; + }; + partition@6 { + label = "cdt_alt"; + reg = <0x000000580000 0x000000080000>; + read-only; + }; + partition@7 { + label = "ddrparams"; + reg = <0x000000600000 0x000000080000>; + read-only; + }; + partition@8 { + label = "u-boot"; + reg = <0x000000700000 0x000000200000>; + read-only; + }; + partition@9 { + label = "u-boot-backup"; + reg = <0x000000900000 0x000000200000>; + read-only; + }; + partition@10 { + label = "ART"; + reg = <0x000000b00000 0x000000080000>; + read-only; + }; + partition@11 { + label = "ubi"; + reg = <0x000000c00000 0x000007000000>; + }; + }; + }; +}; + +&pcie0 { + status = "okay"; + perst-gpio = <&tlmm 38 GPIO_ACTIVE_LOW>; + wake-gpio = <&tlmm 50 GPIO_ACTIVE_LOW>; +}; + +&qpic_bam { + status = "okay"; +}; + +&tlmm { + /* + * GPIO43 should be 0/1 whenever the unit is + * powered through PoE or AC-Adapter. + * That said, playing with this seems to + * reset the AP. + */ + + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio6"; + function = "mdio"; + bias-pull-up; + }; + mux_2 { + pins = "gpio7"; + function = "mdc"; + bias-pull-up; + }; + }; + + serial_0_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + serial_1_pins: serial1_pinmux { + mux { + /* We use the i2c-0 pins for serial_1 */ + pins = "gpio8", "gpio9"; + function = "blsp_uart1"; + bias-disable; + }; + }; + + i2c_0_pins: i2c_0_pinmux { + pinmux { + function = "blsp_i2c0"; + pins = "gpio20", "gpio21"; + }; + pinconf { + pins = "gpio20", "gpio21"; + drive-strength = <16>; + bias-disable; + }; + }; + + i2c_1_pins: i2c_1_pinmux { + pinmux { + function = "blsp_i2c1"; + pins = "gpio34", "gpio35"; + }; + pinconf { + pins = "gpio34", "gpio35"; + drive-strength = <16>; + bias-disable; + }; + }; + + nand_pins: nand_pins { + /* + * There are 18 pins. 15 pins are common between LCD and NAND. + * The QPIC controller arbitrates between LCD and NAND. Of the + * remaining 4, 2 are for NAND and 2 are for LCD exclusively. + * + * The meraki source hints that the bluetooth module claims + * pin 52 as well. But sadly, there's no data whenever this + * is a NAND or LCD exclusive pin or not. + */ + + pullups { + pins = "gpio52", "gpio53", "gpio58", + "gpio59"; + function = "qpic"; + bias-pull-up; + }; + + pulldowns { + pins = "gpio54", "gpio55", "gpio56", + "gpio57", "gpio60", "gpio61", + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; + function = "qpic"; + bias-pull-down; + }; + }; +}; + +&wifi0 { + status = "okay"; + /* qcom,ath10k-calibration-variant = "MERAKI-MR33"; */ +}; + +&wifi1 { + status = "okay"; + /* qcom,ath10k-calibration-variant = "MERAKI-MR33"; */ +}; diff --git a/target/linux/ipq40xx/image/Makefile b/target/linux/ipq40xx/image/Makefile new file mode 100644 index 000000000..8b7d46e55 --- /dev/null +++ b/target/linux/ipq40xx/image/Makefile @@ -0,0 +1,166 @@ +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/image.mk + +define Device/Default + PROFILES := Default + KERNEL_DEPENDS = $$(wildcard $(DTS_DIR)/$$(DEVICE_DTS).dts) + KERNEL_INITRAMFS_PREFIX := $$(IMG_PREFIX)-$(1)-initramfs + KERNEL_PREFIX := $$(IMAGE_PREFIX) + KERNEL_LOADADDR := 0x80208000 + SUPPORTED_DEVICES := $(subst _,$(comma),$(1)) + IMAGE/sysupgrade.bin = sysupgrade-tar | append-metadata + IMAGE/sysupgrade.bin/squashfs := +endef + +define Device/FitImage + KERNEL_SUFFIX := -fit-uImage.itb + KERNEL = kernel-bin | gzip | fit gzip $$(DTS_DIR)/$$(DEVICE_DTS).dtb + KERNEL_NAME := Image +endef + +define Device/FitImageLzma + KERNEL_SUFFIX := -fit-uImage.itb + KERNEL = kernel-bin | lzma | fit lzma $$(DTS_DIR)/$$(DEVICE_DTS).dtb + KERNEL_NAME := Image +endef + +define Device/UbiFit + KERNEL_IN_UBI := 1 + IMAGES := nand-factory.ubi nand-sysupgrade.bin + IMAGE/nand-factory.ubi := append-ubi + IMAGE/nand-sysupgrade.bin := sysupgrade-tar | append-metadata +endef + + +define Device/asus_rt-ac58u + $(call Device/FitImageLzma) + DEVICE_DTS := qcom-ipq4018-rt-ac58u + BLOCKSIZE := 128k + PAGESIZE := 2048 + DTB_SIZE := 65536 + DEVICE_TITLE := Asus RT-AC58U + IMAGE_SIZE := 20439364 + FILESYSTEMS := squashfs +# Someone - in their infinite wisdom - decided to put the firmware +# version in front of the image name \03\00\00\04 => Version 3.0.0.4 +# Since u-boot works with strings we either need another fixup step +# to add a version... or we are very careful not to add '\0' into that +# string and call it a day.... Yeah, we do the latter! + UIMAGE_NAME:=$(shell echo -e '\03\01\01\01RT-AC58U') + KERNEL_INITRAMFS := $$(KERNEL) | uImage none + KERNEL_INITRAMFS_SUFFIX := -factory.trx + IMAGES := sysupgrade.bin + DEVICE_PACKAGES := ipq-wifi-asus_rt-ac58u kmod-usb-ledtrig-usbport +endef +TARGET_DEVICES += asus_rt-ac58u + +define Device/asus_rt-acrh17 + $(call Device/FitImageLzma) + DEVICE_DTS := qcom-ipq4019-rt-acrh17 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DTB_SIZE := 65536 + DEVICE_TITLE := Asus RT-ACRH17 + IMAGE_SIZE := 20439364 + FILESYSTEMS := squashfs + UIMAGE_NAME:=$(shell echo -e '\03\01\01\01RT-AC82U') + KERNEL_INITRAMFS := $$(KERNEL) | uImage none + KERNEL_INITRAMFS_SUFFIX := -factory.trx + IMAGES := sysupgrade.bin + DEVICE_PACKAGES := ath10k-firmware-qca4019 ath10k-firmware-qca9984 +endef +TARGET_DEVICES += asus_rt-acrh17 + +define Device/avm_fritzbox-4040 + $(call Device/FitImageLzma) + DEVICE_DTS := qcom-ipq4018-fritz4040 + BOARD_NAME := fritz4040 + DEVICE_TITLE := AVM Fritz!Box 4040 + IMAGE_SIZE := 29753344 + IMAGES = sysupgrade.bin + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata + DEVICE_PACKAGES := ipq-wifi-avm_fritzbox-4040 fritz-tffs fritz-caldata u-boot-fritz4040 +endef +TARGET_DEVICES += avm_fritzbox-4040 + +define Device/compex_wpj428 + $(call Device/FitImage) + DEVICE_DTS := qcom-ipq4028-wpj428 + DEVICE_DTS_CONFIG := config@4 + BLOCKSIZE := 64k + DEVICE_TITLE := Compex WPJ428 + IMAGE_SIZE := 31232k + KERNEL_SIZE := 4096k + IMAGES = sysupgrade.bin + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata + DEVICE_PACKAGES := ath10k-firmware-qca4019 kmod-gpio-beeper +endef +TARGET_DEVICES += compex_wpj428 + +define Device/glinet_gl-b1300 + $(call Device/FitImage) + DEVICE_TITLE := GL.iNet GL-B1300 + BOARD_NAME := gl-b1300 + DEVICE_DTS := qcom-ipq4029-gl-b1300 + KERNEL_SIZE := 4096k + IMAGE_SIZE := 26624k + IMAGES := sysupgrade.bin + IMAGE/sysupgrade.bin := append-kernel |append-rootfs | pad-rootfs | append-metadata + DEVICE_PACKAGES := ipq-wifi-glinet_gl-b1300 +endef +TARGET_DEVICES += glinet_gl-b1300 + +define Device/meraki_mr33 + $(call Device/FitImage) + DEVICE_DTS := qcom-ipq4029-mr33 + BLOCKSIZE := 131072 + PAGESIZE := 2048 + DEVICE_TITLE := Cisco Meraki MR33 + IMAGES = sysupgrade.bin + DEVICE_PACKAGES := -swconfig ipq-wifi-meraki_mr33 ath10k-firmware-qca9887 +endef +TARGET_DEVICES += meraki_mr33 + +define Device/openmesh_a42 + $(call Device/FitImageLzma) + DEVICE_DTS := qcom-ipq4018-a42 + DEVICE_DTS_CONFIG := config@om.a42 + BLOCKSIZE := 64k + DEVICE_TITLE := OpenMesh A42 + KERNEL = kernel-bin | lzma | fit lzma $$(DTS_DIR)/$$(DEVICE_DTS).dtb | pad-to $$(BLOCKSIZE) + IMAGE_SIZE := 15616k + IMAGES = factory.bin sysupgrade.bin + IMAGE/factory.bin := append-rootfs | pad-rootfs | openmesh-image ce_type=A42 + IMAGE/sysupgrade.bin/squashfs := append-rootfs | pad-rootfs | sysupgrade-tar rootfs=$$$$@ | append-metadata + DEVICE_PACKAGES := ath10k-firmware-qca4019 uboot-envtools +endef +TARGET_DEVICES += openmesh_a42 + +define Device/qcom_ap-dk01.1-c1 + DEVICE_TITLE := QCA AP-DK01.1-C1 + BOARD_NAME := ap-dk01.1-c1 + DEVICE_DTS := qcom-ipq4019-ap.dk01.1-c1 + KERNEL_INSTALL := 1 + KERNEL_SIZE := 4096k + IMAGE_SIZE := 26624k + $(call Device/FitImage) + IMAGES := sysupgrade.bin + IMAGE/sysupgrade.bin := append-kernel | pad-to $$$${KERNEL_SIZE} | append-rootfs | pad-rootfs | append-metadata + DEVICE_PACKAGES := ath10k-firmware-qca4019 +endef +TARGET_DEVICES += qcom_ap-dk01.1-c1 + +define Device/qcom_ap-dk04.1-c1 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_DTS := qcom-ipq4019-ap.dk04.1-c1 + KERNEL_INSTALL := 1 + KERNEL_SIZE := 4048k + BLOCKSIZE := 128k + PAGESIZE := 2048 + BOARD_NAME := ap-dk04.1-c1 + DEVICE_TITLE := QCA AP-DK04.1-C1 +endef +TARGET_DEVICES += qcom_ap-dk04.1-c1 + +$(eval $(call BuildImage)) diff --git a/target/linux/ipq40xx/patches-4.14/017-qcom-ipq4019-add-cpu-operating-points-for-cpufreq-su.patch b/target/linux/ipq40xx/patches-4.14/017-qcom-ipq4019-add-cpu-operating-points-for-cpufreq-su.patch new file mode 100644 index 000000000..03e9021a4 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/017-qcom-ipq4019-add-cpu-operating-points-for-cpufreq-su.patch @@ -0,0 +1,77 @@ +From 18c3b42575a154343831aec0637aab00e19440e1 Mon Sep 17 00:00:00 2001 +From: Matthew McClintock +Date: Thu, 17 Mar 2016 15:01:09 -0500 +Subject: [PATCH 17/69] qcom: ipq4019: add cpu operating points for cpufreq + support + +This adds some operating points for cpu frequeny scaling + +Signed-off-by: Matthew McClintock +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 34 ++++++++++++++++++++++++++-------- + 1 file changed, 26 insertions(+), 8 deletions(-) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -40,14 +40,7 @@ + reg = <0x0>; + clocks = <&gcc GCC_APPS_CLK_SRC>; + clock-frequency = <0>; +- operating-points = < +- /* kHz uV (fixed) */ +- 48000 1100000 +- 200000 1100000 +- 500000 1100000 +- 666000 1100000 +- >; +- clock-latency = <256000>; ++ operating-points-v2 = <&cpu0_opp_table>; + }; + + cpu@1 { +@@ -59,6 +52,7 @@ + reg = <0x1>; + clocks = <&gcc GCC_APPS_CLK_SRC>; + clock-frequency = <0>; ++ operating-points-v2 = <&cpu0_opp_table>; + }; + + cpu@2 { +@@ -70,6 +64,7 @@ + reg = <0x2>; + clocks = <&gcc GCC_APPS_CLK_SRC>; + clock-frequency = <0>; ++ operating-points-v2 = <&cpu0_opp_table>; + }; + + cpu@3 { +@@ -81,6 +76,29 @@ + reg = <0x3>; + clocks = <&gcc GCC_APPS_CLK_SRC>; + clock-frequency = <0>; ++ operating-points-v2 = <&cpu0_opp_table>; ++ }; ++ }; ++ ++ cpu0_opp_table: opp_table0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-48000000 { ++ opp-hz = /bits/ 64 <48000000>; ++ clock-latency-ns = <256000>; ++ }; ++ opp-200000000 { ++ opp-hz = /bits/ 64 <200000000>; ++ clock-latency-ns = <256000>; ++ }; ++ opp-500000000 { ++ opp-hz = /bits/ 64 <500000000>; ++ clock-latency-ns = <256000>; ++ }; ++ opp-716000000 { ++ opp-hz = /bits/ 64 <716000000>; ++ clock-latency-ns = <256000>; + }; + }; + diff --git a/target/linux/ipq40xx/patches-4.14/030-mtd-nand-Use-standard-large-page-OOB-layout-when-usi.patch b/target/linux/ipq40xx/patches-4.14/030-mtd-nand-Use-standard-large-page-OOB-layout-when-usi.patch new file mode 100644 index 000000000..67dee7092 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/030-mtd-nand-Use-standard-large-page-OOB-layout-when-usi.patch @@ -0,0 +1,47 @@ +From 882fd1577cbe7812ae3a48988180c5f0fda475ca Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Sat, 26 Aug 2017 17:19:15 +0200 +Subject: [PATCH] mtd: nand: Use standard large page OOB layout when using + NAND_ECC_NONE + +Use the core's large page OOB layout functions when not reserving any +space for ECC bytes in the OOB layout. Fix ->nand_ooblayout_ecc_lp() +to return -ERANGE instead of a zero length in this case. + +Signed-off-by: Miquel Raynal +Signed-off-by: Boris Brezillon +--- + drivers/mtd/nand/nand_base.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -115,7 +115,7 @@ static int nand_ooblayout_ecc_lp(struct + struct nand_chip *chip = mtd_to_nand(mtd); + struct nand_ecc_ctrl *ecc = &chip->ecc; + +- if (section) ++ if (section || !ecc->total) + return -ERANGE; + + oobregion->length = ecc->total; +@@ -4712,6 +4712,19 @@ int nand_scan_tail(struct mtd_info *mtd) + mtd_set_ooblayout(mtd, &nand_ooblayout_lp_hamming_ops); + break; + default: ++ /* ++ * Expose the whole OOB area to users if ECC_NONE ++ * is passed. We could do that for all kind of ++ * ->oobsize, but we must keep the old large/small ++ * page with ECC layout when ->oobsize <= 128 for ++ * compatibility reasons. ++ */ ++ if (ecc->mode == NAND_ECC_NONE) { ++ mtd_set_ooblayout(mtd, ++ &nand_ooblayout_lp_ops); ++ break; ++ } ++ + WARN(1, "No oob scheme defined for oobsize %d\n", + mtd->oobsize); + ret = -EINVAL; diff --git a/target/linux/ipq40xx/patches-4.14/031-mtd-nand-use-usual-return-values-for-the-erase-hook.patch b/target/linux/ipq40xx/patches-4.14/031-mtd-nand-use-usual-return-values-for-the-erase-hook.patch new file mode 100644 index 000000000..962baeb2b --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/031-mtd-nand-use-usual-return-values-for-the-erase-hook.patch @@ -0,0 +1,48 @@ +From eb94555e9e97c9983461214046b4d72c4ab4ba70 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Thu, 30 Nov 2017 18:01:28 +0100 +Subject: [PATCH] mtd: nand: use usual return values for the ->erase() hook + +Avoid using specific defined values for checking returned status of the +->erase() hook. Instead, use usual negative error values on failure, +zero otherwise. + +Signed-off-by: Miquel Raynal +Acked-by: Masahiro Yamada +Signed-off-by: Boris Brezillon +--- + drivers/mtd/nand/denali.c | 2 +- + drivers/mtd/nand/docg4.c | 7 ++++++- + drivers/mtd/nand/nand_base.c | 10 ++++++++-- + 3 files changed, 15 insertions(+), 4 deletions(-) + +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -2994,11 +2994,17 @@ out: + static int single_erase(struct mtd_info *mtd, int page) + { + struct nand_chip *chip = mtd_to_nand(mtd); ++ int status; ++ + /* Send commands to erase a block */ + chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); + chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); + +- return chip->waitfunc(mtd, chip); ++ status = chip->waitfunc(mtd, chip); ++ if (status < 0) ++ return status; ++ ++ return status & NAND_STATUS_FAIL ? -EIO : 0; + } + + /** +@@ -3082,7 +3088,7 @@ int nand_erase_nand(struct mtd_info *mtd + status = chip->erase(mtd, page & chip->pagemask); + + /* See if block erase succeeded */ +- if (status & NAND_STATUS_FAIL) { ++ if (status) { + pr_debug("%s: failed erase, page 0x%08x\n", + __func__, page); + instr->state = MTD_ERASE_FAILED; diff --git a/target/linux/ipq40xx/patches-4.14/040-dmaengine-qcom-bam-Process-multiple-pending-descript.patch b/target/linux/ipq40xx/patches-4.14/040-dmaengine-qcom-bam-Process-multiple-pending-descript.patch new file mode 100644 index 000000000..dca516e87 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/040-dmaengine-qcom-bam-Process-multiple-pending-descript.patch @@ -0,0 +1,395 @@ +From 6b4faeac05bc0b91616b921191cb054d1376f3b4 Mon Sep 17 00:00:00 2001 +From: Sricharan R +Date: Mon, 28 Aug 2017 20:30:24 +0530 +Subject: [PATCH] dmaengine: qcom-bam: Process multiple pending descriptors + +The bam dmaengine has a circular FIFO to which we +add hw descriptors that describes the transaction. +The FIFO has space for about 4096 hw descriptors. + +Currently we add one descriptor and wait for it to +complete with interrupt and then add the next pending +descriptor. In this way, the FIFO is underutilized +since only one descriptor is processed at a time, although +there is space in FIFO for the BAM to process more. + +Instead keep adding descriptors to FIFO till its full, +that allows BAM to continue to work on the next descriptor +immediately after signalling completion interrupt for the +previous descriptor. + +Also when the client has not set the DMA_PREP_INTERRUPT for +a descriptor, then do not configure BAM to trigger a interrupt +upon completion of that descriptor. This way we get a interrupt +only for the descriptor for which DMA_PREP_INTERRUPT was +requested and there signal completion of all the previous completed +descriptors. So we still do callbacks for all requested descriptors, +but just that the number of interrupts are reduced. + +CURRENT: + + ------ ------- --------------- + |DES 0| |DESC 1| |DESC 2 + INT | + ------ ------- --------------- + | | | + | | | +INTERRUPT: (INT) (INT) (INT) +CALLBACK: (CB) (CB) (CB) + + MTD_SPEEDTEST READ PAGE: 3560 KiB/s + MTD_SPEEDTEST WRITE PAGE: 2664 KiB/s + IOZONE READ: 2456 KB/s + IOZONE WRITE: 1230 KB/s + + bam dma interrupts (after tests): 96508 + +CHANGE: + + ------ ------- ------------- + |DES 0| |DESC 1 |DESC 2 + INT | + ------ ------- -------------- + | + | + (INT) + (CB for 0, 1, 2) + + MTD_SPEEDTEST READ PAGE: 3860 KiB/s + MTD_SPEEDTEST WRITE PAGE: 2837 KiB/s + IOZONE READ: 2677 KB/s + IOZONE WRITE: 1308 KB/s + + bam dma interrupts (after tests): 58806 + +Signed-off-by: Sricharan R +Reviewed-by: Andy Gross +Tested-by: Abhishek Sahu +Signed-off-by: Vinod Koul +--- + drivers/dma/qcom/bam_dma.c | 169 +++++++++++++++++++++++++++++---------------- + 1 file changed, 109 insertions(+), 60 deletions(-) + +--- a/drivers/dma/qcom/bam_dma.c ++++ b/drivers/dma/qcom/bam_dma.c +@@ -46,6 +46,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -78,6 +79,8 @@ struct bam_async_desc { + + struct bam_desc_hw *curr_desc; + ++ /* list node for the desc in the bam_chan list of descriptors */ ++ struct list_head desc_node; + enum dma_transfer_direction dir; + size_t length; + struct bam_desc_hw desc[0]; +@@ -347,6 +350,8 @@ static const struct reg_offset_data bam_ + #define BAM_DESC_FIFO_SIZE SZ_32K + #define MAX_DESCRIPTORS (BAM_DESC_FIFO_SIZE / sizeof(struct bam_desc_hw) - 1) + #define BAM_FIFO_SIZE (SZ_32K - 8) ++#define IS_BUSY(chan) (CIRC_SPACE(bchan->tail, bchan->head,\ ++ MAX_DESCRIPTORS + 1) == 0) + + struct bam_chan { + struct virt_dma_chan vc; +@@ -356,8 +361,6 @@ struct bam_chan { + /* configuration from device tree */ + u32 id; + +- struct bam_async_desc *curr_txd; /* current running dma */ +- + /* runtime configuration */ + struct dma_slave_config slave; + +@@ -372,6 +375,8 @@ struct bam_chan { + unsigned int initialized; /* is the channel hw initialized? */ + unsigned int paused; /* is the channel paused? */ + unsigned int reconfigure; /* new slave config? */ ++ /* list of descriptors currently processed */ ++ struct list_head desc_list; + + struct list_head node; + }; +@@ -539,7 +544,7 @@ static void bam_free_chan(struct dma_cha + + vchan_free_chan_resources(to_virt_chan(chan)); + +- if (bchan->curr_txd) { ++ if (!list_empty(&bchan->desc_list)) { + dev_err(bchan->bdev->dev, "Cannot free busy channel\n"); + goto err; + } +@@ -632,8 +637,6 @@ static struct dma_async_tx_descriptor *b + + if (flags & DMA_PREP_INTERRUPT) + async_desc->flags |= DESC_FLAG_EOT; +- else +- async_desc->flags |= DESC_FLAG_INT; + + async_desc->num_desc = num_alloc; + async_desc->curr_desc = async_desc->desc; +@@ -684,14 +687,16 @@ err_out: + static int bam_dma_terminate_all(struct dma_chan *chan) + { + struct bam_chan *bchan = to_bam_chan(chan); ++ struct bam_async_desc *async_desc, *tmp; + unsigned long flag; + LIST_HEAD(head); + + /* remove all transactions, including active transaction */ + spin_lock_irqsave(&bchan->vc.lock, flag); +- if (bchan->curr_txd) { +- list_add(&bchan->curr_txd->vd.node, &bchan->vc.desc_issued); +- bchan->curr_txd = NULL; ++ list_for_each_entry_safe(async_desc, tmp, ++ &bchan->desc_list, desc_node) { ++ list_add(&async_desc->vd.node, &bchan->vc.desc_issued); ++ list_del(&async_desc->desc_node); + } + + vchan_get_all_descriptors(&bchan->vc, &head); +@@ -763,9 +768,9 @@ static int bam_resume(struct dma_chan *c + */ + static u32 process_channel_irqs(struct bam_device *bdev) + { +- u32 i, srcs, pipe_stts; ++ u32 i, srcs, pipe_stts, offset, avail; + unsigned long flags; +- struct bam_async_desc *async_desc; ++ struct bam_async_desc *async_desc, *tmp; + + srcs = readl_relaxed(bam_addr(bdev, 0, BAM_IRQ_SRCS_EE)); + +@@ -785,27 +790,40 @@ static u32 process_channel_irqs(struct b + writel_relaxed(pipe_stts, bam_addr(bdev, i, BAM_P_IRQ_CLR)); + + spin_lock_irqsave(&bchan->vc.lock, flags); +- async_desc = bchan->curr_txd; + +- if (async_desc) { +- async_desc->num_desc -= async_desc->xfer_len; +- async_desc->curr_desc += async_desc->xfer_len; +- bchan->curr_txd = NULL; ++ offset = readl_relaxed(bam_addr(bdev, i, BAM_P_SW_OFSTS)) & ++ P_SW_OFSTS_MASK; ++ offset /= sizeof(struct bam_desc_hw); ++ ++ /* Number of bytes available to read */ ++ avail = CIRC_CNT(offset, bchan->head, MAX_DESCRIPTORS + 1); ++ ++ list_for_each_entry_safe(async_desc, tmp, ++ &bchan->desc_list, desc_node) { ++ /* Not enough data to read */ ++ if (avail < async_desc->xfer_len) ++ break; + + /* manage FIFO */ + bchan->head += async_desc->xfer_len; + bchan->head %= MAX_DESCRIPTORS; + ++ async_desc->num_desc -= async_desc->xfer_len; ++ async_desc->curr_desc += async_desc->xfer_len; ++ avail -= async_desc->xfer_len; ++ + /* +- * if complete, process cookie. Otherwise ++ * if complete, process cookie. Otherwise + * push back to front of desc_issued so that + * it gets restarted by the tasklet + */ +- if (!async_desc->num_desc) ++ if (!async_desc->num_desc) { + vchan_cookie_complete(&async_desc->vd); +- else ++ } else { + list_add(&async_desc->vd.node, +- &bchan->vc.desc_issued); ++ &bchan->vc.desc_issued); ++ } ++ list_del(&async_desc->desc_node); + } + + spin_unlock_irqrestore(&bchan->vc.lock, flags); +@@ -867,6 +885,7 @@ static enum dma_status bam_tx_status(str + struct dma_tx_state *txstate) + { + struct bam_chan *bchan = to_bam_chan(chan); ++ struct bam_async_desc *async_desc; + struct virt_dma_desc *vd; + int ret; + size_t residue = 0; +@@ -882,11 +901,17 @@ static enum dma_status bam_tx_status(str + + spin_lock_irqsave(&bchan->vc.lock, flags); + vd = vchan_find_desc(&bchan->vc, cookie); +- if (vd) ++ if (vd) { + residue = container_of(vd, struct bam_async_desc, vd)->length; +- else if (bchan->curr_txd && bchan->curr_txd->vd.tx.cookie == cookie) +- for (i = 0; i < bchan->curr_txd->num_desc; i++) +- residue += bchan->curr_txd->curr_desc[i].size; ++ } else { ++ list_for_each_entry(async_desc, &bchan->desc_list, desc_node) { ++ if (async_desc->vd.tx.cookie != cookie) ++ continue; ++ ++ for (i = 0; i < async_desc->num_desc; i++) ++ residue += async_desc->curr_desc[i].size; ++ } ++ } + + spin_unlock_irqrestore(&bchan->vc.lock, flags); + +@@ -927,63 +952,86 @@ static void bam_start_dma(struct bam_cha + { + struct virt_dma_desc *vd = vchan_next_desc(&bchan->vc); + struct bam_device *bdev = bchan->bdev; +- struct bam_async_desc *async_desc; ++ struct bam_async_desc *async_desc = NULL; + struct bam_desc_hw *desc; + struct bam_desc_hw *fifo = PTR_ALIGN(bchan->fifo_virt, + sizeof(struct bam_desc_hw)); + int ret; ++ unsigned int avail; ++ struct dmaengine_desc_callback cb; + + lockdep_assert_held(&bchan->vc.lock); + + if (!vd) + return; + +- list_del(&vd->node); +- +- async_desc = container_of(vd, struct bam_async_desc, vd); +- bchan->curr_txd = async_desc; +- + ret = pm_runtime_get_sync(bdev->dev); + if (ret < 0) + return; + +- /* on first use, initialize the channel hardware */ +- if (!bchan->initialized) +- bam_chan_init_hw(bchan, async_desc->dir); +- +- /* apply new slave config changes, if necessary */ +- if (bchan->reconfigure) +- bam_apply_new_config(bchan, async_desc->dir); ++ while (vd && !IS_BUSY(bchan)) { ++ list_del(&vd->node); + +- desc = bchan->curr_txd->curr_desc; ++ async_desc = container_of(vd, struct bam_async_desc, vd); + +- if (async_desc->num_desc > MAX_DESCRIPTORS) +- async_desc->xfer_len = MAX_DESCRIPTORS; +- else +- async_desc->xfer_len = async_desc->num_desc; ++ /* on first use, initialize the channel hardware */ ++ if (!bchan->initialized) ++ bam_chan_init_hw(bchan, async_desc->dir); + +- /* set any special flags on the last descriptor */ +- if (async_desc->num_desc == async_desc->xfer_len) +- desc[async_desc->xfer_len - 1].flags |= +- cpu_to_le16(async_desc->flags); +- else +- desc[async_desc->xfer_len - 1].flags |= +- cpu_to_le16(DESC_FLAG_INT); ++ /* apply new slave config changes, if necessary */ ++ if (bchan->reconfigure) ++ bam_apply_new_config(bchan, async_desc->dir); ++ ++ desc = async_desc->curr_desc; ++ avail = CIRC_SPACE(bchan->tail, bchan->head, ++ MAX_DESCRIPTORS + 1); ++ ++ if (async_desc->num_desc > avail) ++ async_desc->xfer_len = avail; ++ else ++ async_desc->xfer_len = async_desc->num_desc; ++ ++ /* set any special flags on the last descriptor */ ++ if (async_desc->num_desc == async_desc->xfer_len) ++ desc[async_desc->xfer_len - 1].flags |= ++ cpu_to_le16(async_desc->flags); + +- if (bchan->tail + async_desc->xfer_len > MAX_DESCRIPTORS) { +- u32 partial = MAX_DESCRIPTORS - bchan->tail; ++ vd = vchan_next_desc(&bchan->vc); + +- memcpy(&fifo[bchan->tail], desc, +- partial * sizeof(struct bam_desc_hw)); +- memcpy(fifo, &desc[partial], (async_desc->xfer_len - partial) * ++ dmaengine_desc_get_callback(&async_desc->vd.tx, &cb); ++ ++ /* ++ * An interrupt is generated at this desc, if ++ * - FIFO is FULL. ++ * - No more descriptors to add. ++ * - If a callback completion was requested for this DESC, ++ * In this case, BAM will deliver the completion callback ++ * for this desc and continue processing the next desc. ++ */ ++ if (((avail <= async_desc->xfer_len) || !vd || ++ dmaengine_desc_callback_valid(&cb)) && ++ !(async_desc->flags & DESC_FLAG_EOT)) ++ desc[async_desc->xfer_len - 1].flags |= ++ cpu_to_le16(DESC_FLAG_INT); ++ ++ if (bchan->tail + async_desc->xfer_len > MAX_DESCRIPTORS) { ++ u32 partial = MAX_DESCRIPTORS - bchan->tail; ++ ++ memcpy(&fifo[bchan->tail], desc, ++ partial * sizeof(struct bam_desc_hw)); ++ memcpy(fifo, &desc[partial], ++ (async_desc->xfer_len - partial) * + sizeof(struct bam_desc_hw)); +- } else { +- memcpy(&fifo[bchan->tail], desc, +- async_desc->xfer_len * sizeof(struct bam_desc_hw)); +- } ++ } else { ++ memcpy(&fifo[bchan->tail], desc, ++ async_desc->xfer_len * ++ sizeof(struct bam_desc_hw)); ++ } + +- bchan->tail += async_desc->xfer_len; +- bchan->tail %= MAX_DESCRIPTORS; ++ bchan->tail += async_desc->xfer_len; ++ bchan->tail %= MAX_DESCRIPTORS; ++ list_add_tail(&async_desc->desc_node, &bchan->desc_list); ++ } + + /* ensure descriptor writes and dma start not reordered */ + wmb(); +@@ -1012,7 +1060,7 @@ static void dma_tasklet(unsigned long da + bchan = &bdev->channels[i]; + spin_lock_irqsave(&bchan->vc.lock, flags); + +- if (!list_empty(&bchan->vc.desc_issued) && !bchan->curr_txd) ++ if (!list_empty(&bchan->vc.desc_issued) && !IS_BUSY(bchan)) + bam_start_dma(bchan); + spin_unlock_irqrestore(&bchan->vc.lock, flags); + } +@@ -1033,7 +1081,7 @@ static void bam_issue_pending(struct dma + spin_lock_irqsave(&bchan->vc.lock, flags); + + /* if work pending and idle, start a transaction */ +- if (vchan_issue_pending(&bchan->vc) && !bchan->curr_txd) ++ if (vchan_issue_pending(&bchan->vc) && !IS_BUSY(bchan)) + bam_start_dma(bchan); + + spin_unlock_irqrestore(&bchan->vc.lock, flags); +@@ -1133,6 +1181,7 @@ static void bam_channel_init(struct bam_ + + vchan_init(&bchan->vc, &bdev->common); + bchan->vc.desc_free = bam_dma_free_desc; ++ INIT_LIST_HEAD(&bchan->desc_list); + } + + static const struct of_device_id bam_of_match[] = { diff --git a/target/linux/ipq40xx/patches-4.14/050-0002-mtd-nand-qcom-add-command-elements-in-BAM-transactio.patch b/target/linux/ipq40xx/patches-4.14/050-0002-mtd-nand-qcom-add-command-elements-in-BAM-transactio.patch new file mode 100644 index 000000000..1a32cc376 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/050-0002-mtd-nand-qcom-add-command-elements-in-BAM-transactio.patch @@ -0,0 +1,89 @@ +From 8c4cdce8b1ab044a2ee1d86d5a086f67e32b3c10 Mon Sep 17 00:00:00 2001 +From: Abhishek Sahu +Date: Mon, 25 Sep 2017 13:21:25 +0530 +Subject: [PATCH 2/7] mtd: nand: qcom: add command elements in BAM transaction + +All the QPIC register read/write through BAM DMA requires +command descriptor which contains the array of command elements. + +Reviewed-by: Archit Taneja +Signed-off-by: Abhishek Sahu +Signed-off-by: Boris Brezillon +--- + drivers/mtd/nand/qcom_nandc.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/nand/qcom_nandc.c ++++ b/drivers/mtd/nand/qcom_nandc.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + /* NANDc reg offsets */ + #define NAND_FLASH_CMD 0x00 +@@ -199,6 +200,7 @@ nandc_set_reg(nandc, NAND_READ_LOCATION_ + */ + #define dev_cmd_reg_addr(nandc, reg) ((nandc)->props->dev_cmd_reg_start + (reg)) + ++#define QPIC_PER_CW_CMD_ELEMENTS 32 + #define QPIC_PER_CW_CMD_SGL 32 + #define QPIC_PER_CW_DATA_SGL 8 + +@@ -221,8 +223,13 @@ nandc_set_reg(nandc, NAND_READ_LOCATION_ + /* + * This data type corresponds to the BAM transaction which will be used for all + * NAND transfers. ++ * @bam_ce - the array of BAM command elements + * @cmd_sgl - sgl for NAND BAM command pipe + * @data_sgl - sgl for NAND BAM consumer/producer pipe ++ * @bam_ce_pos - the index in bam_ce which is available for next sgl ++ * @bam_ce_start - the index in bam_ce which marks the start position ce ++ * for current sgl. It will be used for size calculation ++ * for current sgl + * @cmd_sgl_pos - current index in command sgl. + * @cmd_sgl_start - start index in command sgl. + * @tx_sgl_pos - current index in data sgl for tx. +@@ -231,8 +238,11 @@ nandc_set_reg(nandc, NAND_READ_LOCATION_ + * @rx_sgl_start - start index in data sgl for rx. + */ + struct bam_transaction { ++ struct bam_cmd_element *bam_ce; + struct scatterlist *cmd_sgl; + struct scatterlist *data_sgl; ++ u32 bam_ce_pos; ++ u32 bam_ce_start; + u32 cmd_sgl_pos; + u32 cmd_sgl_start; + u32 tx_sgl_pos; +@@ -462,7 +472,8 @@ alloc_bam_transaction(struct qcom_nand_c + + bam_txn_size = + sizeof(*bam_txn) + num_cw * +- ((sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL) + ++ ((sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS) + ++ (sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL) + + (sizeof(*bam_txn->data_sgl) * QPIC_PER_CW_DATA_SGL)); + + bam_txn_buf = devm_kzalloc(nandc->dev, bam_txn_size, GFP_KERNEL); +@@ -472,6 +483,10 @@ alloc_bam_transaction(struct qcom_nand_c + bam_txn = bam_txn_buf; + bam_txn_buf += sizeof(*bam_txn); + ++ bam_txn->bam_ce = bam_txn_buf; ++ bam_txn_buf += ++ sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS * num_cw; ++ + bam_txn->cmd_sgl = bam_txn_buf; + bam_txn_buf += + sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL * num_cw; +@@ -489,6 +504,8 @@ static void clear_bam_transaction(struct + if (!nandc->props->is_bam) + return; + ++ bam_txn->bam_ce_pos = 0; ++ bam_txn->bam_ce_start = 0; + bam_txn->cmd_sgl_pos = 0; + bam_txn->cmd_sgl_start = 0; + bam_txn->tx_sgl_pos = 0; diff --git a/target/linux/ipq40xx/patches-4.14/050-0003-mtd-nand-qcom-support-for-command-descriptor-formati.patch b/target/linux/ipq40xx/patches-4.14/050-0003-mtd-nand-qcom-support-for-command-descriptor-formati.patch new file mode 100644 index 000000000..8dd209b91 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/050-0003-mtd-nand-qcom-support-for-command-descriptor-formati.patch @@ -0,0 +1,201 @@ +From 8d6b6d7e135e9bbfc923d34a45cb0e72695e63ed Mon Sep 17 00:00:00 2001 +From: Abhishek Sahu +Date: Mon, 25 Sep 2017 13:21:26 +0530 +Subject: [PATCH 3/7] mtd: nand: qcom: support for command descriptor formation + +1. Add the function for command descriptor preparation which will + be used only by BAM DMA and it will form the DMA descriptors + containing command elements +2. DMA_PREP_CMD flag should be used for forming command DMA + descriptors + +Reviewed-by: Archit Taneja +Signed-off-by: Abhishek Sahu +Signed-off-by: Boris Brezillon +--- + drivers/mtd/nand/qcom_nandc.c | 108 +++++++++++++++++++++++++++++++++++------- + 1 file changed, 92 insertions(+), 16 deletions(-) + +--- a/drivers/mtd/nand/qcom_nandc.c ++++ b/drivers/mtd/nand/qcom_nandc.c +@@ -200,6 +200,14 @@ nandc_set_reg(nandc, NAND_READ_LOCATION_ + */ + #define dev_cmd_reg_addr(nandc, reg) ((nandc)->props->dev_cmd_reg_start + (reg)) + ++/* Returns the NAND register physical address */ ++#define nandc_reg_phys(chip, offset) ((chip)->base_phys + (offset)) ++ ++/* Returns the dma address for reg read buffer */ ++#define reg_buf_dma_addr(chip, vaddr) \ ++ ((chip)->reg_read_dma + \ ++ ((uint8_t *)(vaddr) - (uint8_t *)(chip)->reg_read_buf)) ++ + #define QPIC_PER_CW_CMD_ELEMENTS 32 + #define QPIC_PER_CW_CMD_SGL 32 + #define QPIC_PER_CW_DATA_SGL 8 +@@ -317,7 +325,8 @@ struct nandc_regs { + * controller + * @dev: parent device + * @base: MMIO base +- * @base_dma: physical base address of controller registers ++ * @base_phys: physical base address of controller registers ++ * @base_dma: dma base address of controller registers + * @core_clk: controller clock + * @aon_clk: another controller clock + * +@@ -350,6 +359,7 @@ struct qcom_nand_controller { + struct device *dev; + + void __iomem *base; ++ phys_addr_t base_phys; + dma_addr_t base_dma; + + struct clk *core_clk; +@@ -751,6 +761,66 @@ static int prepare_bam_async_desc(struct + } + + /* ++ * Prepares the command descriptor for BAM DMA which will be used for NAND ++ * register reads and writes. The command descriptor requires the command ++ * to be formed in command element type so this function uses the command ++ * element from bam transaction ce array and fills the same with required ++ * data. A single SGL can contain multiple command elements so ++ * NAND_BAM_NEXT_SGL will be used for starting the separate SGL ++ * after the current command element. ++ */ ++static int prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, bool read, ++ int reg_off, const void *vaddr, ++ int size, unsigned int flags) ++{ ++ int bam_ce_size; ++ int i, ret; ++ struct bam_cmd_element *bam_ce_buffer; ++ struct bam_transaction *bam_txn = nandc->bam_txn; ++ ++ bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_pos]; ++ ++ /* fill the command desc */ ++ for (i = 0; i < size; i++) { ++ if (read) ++ bam_prep_ce(&bam_ce_buffer[i], ++ nandc_reg_phys(nandc, reg_off + 4 * i), ++ BAM_READ_COMMAND, ++ reg_buf_dma_addr(nandc, ++ (__le32 *)vaddr + i)); ++ else ++ bam_prep_ce_le32(&bam_ce_buffer[i], ++ nandc_reg_phys(nandc, reg_off + 4 * i), ++ BAM_WRITE_COMMAND, ++ *((__le32 *)vaddr + i)); ++ } ++ ++ bam_txn->bam_ce_pos += size; ++ ++ /* use the separate sgl after this command */ ++ if (flags & NAND_BAM_NEXT_SGL) { ++ bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_start]; ++ bam_ce_size = (bam_txn->bam_ce_pos - ++ bam_txn->bam_ce_start) * ++ sizeof(struct bam_cmd_element); ++ sg_set_buf(&bam_txn->cmd_sgl[bam_txn->cmd_sgl_pos], ++ bam_ce_buffer, bam_ce_size); ++ bam_txn->cmd_sgl_pos++; ++ bam_txn->bam_ce_start = bam_txn->bam_ce_pos; ++ ++ if (flags & NAND_BAM_NWD) { ++ ret = prepare_bam_async_desc(nandc, nandc->cmd_chan, ++ DMA_PREP_FENCE | ++ DMA_PREP_CMD); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++/* + * Prepares the data descriptor for BAM DMA which will be used for NAND + * data reads and writes. + */ +@@ -868,19 +938,22 @@ static int read_reg_dma(struct qcom_nand + { + bool flow_control = false; + void *vaddr; +- int size; + +- if (first == NAND_READ_ID || first == NAND_FLASH_STATUS) +- flow_control = true; ++ vaddr = nandc->reg_read_buf + nandc->reg_read_pos; ++ nandc->reg_read_pos += num_regs; + + if (first == NAND_DEV_CMD_VLD || first == NAND_DEV_CMD1) + first = dev_cmd_reg_addr(nandc, first); + +- size = num_regs * sizeof(u32); +- vaddr = nandc->reg_read_buf + nandc->reg_read_pos; +- nandc->reg_read_pos += num_regs; ++ if (nandc->props->is_bam) ++ return prep_bam_dma_desc_cmd(nandc, true, first, vaddr, ++ num_regs, flags); ++ ++ if (first == NAND_READ_ID || first == NAND_FLASH_STATUS) ++ flow_control = true; + +- return prep_adm_dma_desc(nandc, true, first, vaddr, size, flow_control); ++ return prep_adm_dma_desc(nandc, true, first, vaddr, ++ num_regs * sizeof(u32), flow_control); + } + + /* +@@ -897,13 +970,9 @@ static int write_reg_dma(struct qcom_nan + bool flow_control = false; + struct nandc_regs *regs = nandc->regs; + void *vaddr; +- int size; + + vaddr = offset_to_nandc_reg(regs, first); + +- if (first == NAND_FLASH_CMD) +- flow_control = true; +- + if (first == NAND_ERASED_CW_DETECT_CFG) { + if (flags & NAND_ERASED_CW_SET) + vaddr = ®s->erased_cw_detect_cfg_set; +@@ -920,10 +989,15 @@ static int write_reg_dma(struct qcom_nan + if (first == NAND_DEV_CMD_VLD_RESTORE || first == NAND_DEV_CMD_VLD) + first = dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD); + +- size = num_regs * sizeof(u32); ++ if (nandc->props->is_bam) ++ return prep_bam_dma_desc_cmd(nandc, false, first, vaddr, ++ num_regs, flags); ++ ++ if (first == NAND_FLASH_CMD) ++ flow_control = true; + +- return prep_adm_dma_desc(nandc, false, first, vaddr, size, +- flow_control); ++ return prep_adm_dma_desc(nandc, false, first, vaddr, ++ num_regs * sizeof(u32), flow_control); + } + + /* +@@ -1187,7 +1261,8 @@ static int submit_descs(struct qcom_nand + } + + if (bam_txn->cmd_sgl_pos > bam_txn->cmd_sgl_start) { +- r = prepare_bam_async_desc(nandc, nandc->cmd_chan, 0); ++ r = prepare_bam_async_desc(nandc, nandc->cmd_chan, ++ DMA_PREP_CMD); + if (r) + return r; + } +@@ -2722,6 +2797,7 @@ static int qcom_nandc_probe(struct platf + if (IS_ERR(nandc->base)) + return PTR_ERR(nandc->base); + ++ nandc->base_phys = res->start; + nandc->base_dma = phys_to_dma(dev, (phys_addr_t)res->start); + + nandc->core_clk = devm_clk_get(dev, "core"); diff --git a/target/linux/ipq40xx/patches-4.14/050-0004-mtd-nand-provide-several-helpers-to-do-common-NAND-o.patch b/target/linux/ipq40xx/patches-4.14/050-0004-mtd-nand-provide-several-helpers-to-do-common-NAND-o.patch new file mode 100644 index 000000000..03dcb0755 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/050-0004-mtd-nand-provide-several-helpers-to-do-common-NAND-o.patch @@ -0,0 +1,1586 @@ +commit 97d90da8a886949f09bb4754843fb0b504956ad2 +Author: Boris Brezillon +Date: Thu Nov 30 18:01:29 2017 +0100 + + mtd: nand: provide several helpers to do common NAND operations + + This is part of the process of removing direct calls to ->cmdfunc() + outside of the core in order to introduce a better interface to execute + NAND operations. + + Here we provide several helpers and make use of them to remove all + direct calls to ->cmdfunc(). This way, we can easily modify those + helpers to make use of the new ->exec_op() interface when available. + + Signed-off-by: Boris Brezillon + [miquel.raynal@free-electrons.com: rebased and fixed some conflicts] + Signed-off-by: Miquel Raynal + Acked-by: Masahiro Yamada + +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -561,14 +561,19 @@ static int nand_block_markbad_lowlevel(s + static int nand_check_wp(struct mtd_info *mtd) + { + struct nand_chip *chip = mtd_to_nand(mtd); ++ u8 status; ++ int ret; + + /* Broken xD cards report WP despite being writable */ + if (chip->options & NAND_BROKEN_XD) + return 0; + + /* Check the WP bit */ +- chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); +- return (chip->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1; ++ ret = nand_status_op(chip, &status); ++ if (ret) ++ return ret; ++ ++ return status & NAND_STATUS_WP ? 0 : 1; + } + + /** +@@ -667,10 +672,17 @@ EXPORT_SYMBOL_GPL(nand_wait_ready); + static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo) + { + register struct nand_chip *chip = mtd_to_nand(mtd); ++ int ret; + + timeo = jiffies + msecs_to_jiffies(timeo); + do { +- if ((chip->read_byte(mtd) & NAND_STATUS_READY)) ++ u8 status; ++ ++ ret = nand_read_data_op(chip, &status, sizeof(status), true); ++ if (ret) ++ return; ++ ++ if (status & NAND_STATUS_READY) + break; + touch_softlockup_watchdog(); + } while (time_before(jiffies, timeo)); +@@ -1021,7 +1033,15 @@ static void panic_nand_wait(struct mtd_i + if (chip->dev_ready(mtd)) + break; + } else { +- if (chip->read_byte(mtd) & NAND_STATUS_READY) ++ int ret; ++ u8 status; ++ ++ ret = nand_read_data_op(chip, &status, sizeof(status), ++ true); ++ if (ret) ++ return; ++ ++ if (status & NAND_STATUS_READY) + break; + } + mdelay(1); +@@ -1038,8 +1058,9 @@ static void panic_nand_wait(struct mtd_i + static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) + { + +- int status; + unsigned long timeo = 400; ++ u8 status; ++ int ret; + + /* + * Apply this short delay always to ensure that we do wait tWB in any +@@ -1047,7 +1068,9 @@ static int nand_wait(struct mtd_info *mt + */ + ndelay(100); + +- chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); ++ ret = nand_status_op(chip, NULL); ++ if (ret) ++ return ret; + + if (in_interrupt() || oops_in_progress) + panic_nand_wait(mtd, chip, timeo); +@@ -1058,14 +1081,22 @@ static int nand_wait(struct mtd_info *mt + if (chip->dev_ready(mtd)) + break; + } else { +- if (chip->read_byte(mtd) & NAND_STATUS_READY) ++ ret = nand_read_data_op(chip, &status, ++ sizeof(status), true); ++ if (ret) ++ return ret; ++ ++ if (status & NAND_STATUS_READY) + break; + } + cond_resched(); + } while (time_before(jiffies, timeo)); + } + +- status = (int)chip->read_byte(mtd); ++ ret = nand_read_data_op(chip, &status, sizeof(status), true); ++ if (ret) ++ return ret; ++ + /* This can happen if in case of timeout or buggy dev_ready */ + WARN_ON(!(status & NAND_STATUS_READY)); + return status; +@@ -1220,6 +1251,516 @@ static void nand_release_data_interface( + } + + /** ++ * nand_read_page_op - Do a READ PAGE operation ++ * @chip: The NAND chip ++ * @page: page to read ++ * @offset_in_page: offset within the page ++ * @buf: buffer used to store the data ++ * @len: length of the buffer ++ * ++ * This function issues a READ PAGE operation. ++ * This function does not select/unselect the CS line. ++ * ++ * Returns 0 on success, a negative error code otherwise. ++ */ ++int nand_read_page_op(struct nand_chip *chip, unsigned int page, ++ unsigned int offset_in_page, void *buf, unsigned int len) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ ++ if (len && !buf) ++ return -EINVAL; ++ ++ if (offset_in_page + len > mtd->writesize + mtd->oobsize) ++ return -EINVAL; ++ ++ chip->cmdfunc(mtd, NAND_CMD_READ0, offset_in_page, page); ++ if (len) ++ chip->read_buf(mtd, buf, len); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nand_read_page_op); ++ ++/** ++ * nand_read_param_page_op - Do a READ PARAMETER PAGE operation ++ * @chip: The NAND chip ++ * @page: parameter page to read ++ * @buf: buffer used to store the data ++ * @len: length of the buffer ++ * ++ * This function issues a READ PARAMETER PAGE operation. ++ * This function does not select/unselect the CS line. ++ * ++ * Returns 0 on success, a negative error code otherwise. ++ */ ++static int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf, ++ unsigned int len) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ unsigned int i; ++ u8 *p = buf; ++ ++ if (len && !buf) ++ return -EINVAL; ++ ++ chip->cmdfunc(mtd, NAND_CMD_PARAM, page, -1); ++ for (i = 0; i < len; i++) ++ p[i] = chip->read_byte(mtd); ++ ++ return 0; ++} ++ ++/** ++ * nand_change_read_column_op - Do a CHANGE READ COLUMN operation ++ * @chip: The NAND chip ++ * @offset_in_page: offset within the page ++ * @buf: buffer used to store the data ++ * @len: length of the buffer ++ * @force_8bit: force 8-bit bus access ++ * ++ * This function issues a CHANGE READ COLUMN operation. ++ * This function does not select/unselect the CS line. ++ * ++ * Returns 0 on success, a negative error code otherwise. ++ */ ++int nand_change_read_column_op(struct nand_chip *chip, ++ unsigned int offset_in_page, void *buf, ++ unsigned int len, bool force_8bit) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ ++ if (len && !buf) ++ return -EINVAL; ++ ++ if (offset_in_page + len > mtd->writesize + mtd->oobsize) ++ return -EINVAL; ++ ++ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset_in_page, -1); ++ if (len) ++ chip->read_buf(mtd, buf, len); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nand_change_read_column_op); ++ ++/** ++ * nand_read_oob_op - Do a READ OOB operation ++ * @chip: The NAND chip ++ * @page: page to read ++ * @offset_in_oob: offset within the OOB area ++ * @buf: buffer used to store the data ++ * @len: length of the buffer ++ * ++ * This function issues a READ OOB operation. ++ * This function does not select/unselect the CS line. ++ * ++ * Returns 0 on success, a negative error code otherwise. ++ */ ++int nand_read_oob_op(struct nand_chip *chip, unsigned int page, ++ unsigned int offset_in_oob, void *buf, unsigned int len) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ ++ if (len && !buf) ++ return -EINVAL; ++ ++ if (offset_in_oob + len > mtd->oobsize) ++ return -EINVAL; ++ ++ chip->cmdfunc(mtd, NAND_CMD_READOOB, offset_in_oob, page); ++ if (len) ++ chip->read_buf(mtd, buf, len); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nand_read_oob_op); ++ ++/** ++ * nand_prog_page_begin_op - starts a PROG PAGE operation ++ * @chip: The NAND chip ++ * @page: page to write ++ * @offset_in_page: offset within the page ++ * @buf: buffer containing the data to write to the page ++ * @len: length of the buffer ++ * ++ * This function issues the first half of a PROG PAGE operation. ++ * This function does not select/unselect the CS line. ++ * ++ * Returns 0 on success, a negative error code otherwise. ++ */ ++int nand_prog_page_begin_op(struct nand_chip *chip, unsigned int page, ++ unsigned int offset_in_page, const void *buf, ++ unsigned int len) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ ++ if (len && !buf) ++ return -EINVAL; ++ ++ if (offset_in_page + len > mtd->writesize + mtd->oobsize) ++ return -EINVAL; ++ ++ chip->cmdfunc(mtd, NAND_CMD_SEQIN, offset_in_page, page); ++ ++ if (buf) ++ chip->write_buf(mtd, buf, len); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nand_prog_page_begin_op); ++ ++/** ++ * nand_prog_page_end_op - ends a PROG PAGE operation ++ * @chip: The NAND chip ++ * ++ * This function issues the second half of a PROG PAGE operation. ++ * This function does not select/unselect the CS line. ++ * ++ * Returns 0 on success, a negative error code otherwise. ++ */ ++int nand_prog_page_end_op(struct nand_chip *chip) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ int status; ++ ++ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); ++ ++ status = chip->waitfunc(mtd, chip); ++ if (status & NAND_STATUS_FAIL) ++ return -EIO; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nand_prog_page_end_op); ++ ++/** ++ * nand_prog_page_op - Do a full PROG PAGE operation ++ * @chip: The NAND chip ++ * @page: page to write ++ * @offset_in_page: offset within the page ++ * @buf: buffer containing the data to write to the page ++ * @len: length of the buffer ++ * ++ * This function issues a full PROG PAGE operation. ++ * This function does not select/unselect the CS line. ++ * ++ * Returns 0 on success, a negative error code otherwise. ++ */ ++int nand_prog_page_op(struct nand_chip *chip, unsigned int page, ++ unsigned int offset_in_page, const void *buf, ++ unsigned int len) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ int status; ++ ++ if (!len || !buf) ++ return -EINVAL; ++ ++ if (offset_in_page + len > mtd->writesize + mtd->oobsize) ++ return -EINVAL; ++ ++ chip->cmdfunc(mtd, NAND_CMD_SEQIN, offset_in_page, page); ++ chip->write_buf(mtd, buf, len); ++ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); ++ ++ status = chip->waitfunc(mtd, chip); ++ if (status & NAND_STATUS_FAIL) ++ return -EIO; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nand_prog_page_op); ++ ++/** ++ * nand_change_write_column_op - Do a CHANGE WRITE COLUMN operation ++ * @chip: The NAND chip ++ * @offset_in_page: offset within the page ++ * @buf: buffer containing the data to send to the NAND ++ * @len: length of the buffer ++ * @force_8bit: force 8-bit bus access ++ * ++ * This function issues a CHANGE WRITE COLUMN operation. ++ * This function does not select/unselect the CS line. ++ * ++ * Returns 0 on success, a negative error code otherwise. ++ */ ++int nand_change_write_column_op(struct nand_chip *chip, ++ unsigned int offset_in_page, ++ const void *buf, unsigned int len, ++ bool force_8bit) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ ++ if (len && !buf) ++ return -EINVAL; ++ ++ if (offset_in_page + len > mtd->writesize + mtd->oobsize) ++ return -EINVAL; ++ ++ chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset_in_page, -1); ++ if (len) ++ chip->write_buf(mtd, buf, len); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nand_change_write_column_op); ++ ++/** ++ * nand_readid_op - Do a READID operation ++ * @chip: The NAND chip ++ * @addr: address cycle to pass after the READID command ++ * @buf: buffer used to store the ID ++ * @len: length of the buffer ++ * ++ * This function sends a READID command and reads back the ID returned by the ++ * NAND. ++ * This function does not select/unselect the CS line. ++ * ++ * Returns 0 on success, a negative error code otherwise. ++ */ ++int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf, ++ unsigned int len) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ unsigned int i; ++ u8 *id = buf; ++ ++ if (len && !buf) ++ return -EINVAL; ++ ++ chip->cmdfunc(mtd, NAND_CMD_READID, addr, -1); ++ ++ for (i = 0; i < len; i++) ++ id[i] = chip->read_byte(mtd); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nand_readid_op); ++ ++/** ++ * nand_status_op - Do a STATUS operation ++ * @chip: The NAND chip ++ * @status: out variable to store the NAND status ++ * ++ * This function sends a STATUS command and reads back the status returned by ++ * the NAND. ++ * This function does not select/unselect the CS line. ++ * ++ * Returns 0 on success, a negative error code otherwise. ++ */ ++int nand_status_op(struct nand_chip *chip, u8 *status) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ ++ chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); ++ if (status) ++ *status = chip->read_byte(mtd); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nand_status_op); ++ ++/** ++ * nand_exit_status_op - Exit a STATUS operation ++ * @chip: The NAND chip ++ * ++ * This function sends a READ0 command to cancel the effect of the STATUS ++ * command to avoid reading only the status until a new read command is sent. ++ * ++ * This function does not select/unselect the CS line. ++ * ++ * Returns 0 on success, a negative error code otherwise. ++ */ ++int nand_exit_status_op(struct nand_chip *chip) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ ++ chip->cmdfunc(mtd, NAND_CMD_READ0, -1, -1); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nand_exit_status_op); ++ ++/** ++ * nand_erase_op - Do an erase operation ++ * @chip: The NAND chip ++ * @eraseblock: block to erase ++ * ++ * This function sends an ERASE command and waits for the NAND to be ready ++ * before returning. ++ * This function does not select/unselect the CS line. ++ * ++ * Returns 0 on success, a negative error code otherwise. ++ */ ++int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ unsigned int page = eraseblock << ++ (chip->phys_erase_shift - chip->page_shift); ++ int status; ++ ++ chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); ++ chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); ++ ++ status = chip->waitfunc(mtd, chip); ++ if (status < 0) ++ return status; ++ ++ if (status & NAND_STATUS_FAIL) ++ return -EIO; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nand_erase_op); ++ ++/** ++ * nand_set_features_op - Do a SET FEATURES operation ++ * @chip: The NAND chip ++ * @feature: feature id ++ * @data: 4 bytes of data ++ * ++ * This function sends a SET FEATURES command and waits for the NAND to be ++ * ready before returning. ++ * This function does not select/unselect the CS line. ++ * ++ * Returns 0 on success, a negative error code otherwise. ++ */ ++static int nand_set_features_op(struct nand_chip *chip, u8 feature, ++ const void *data) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ const u8 *params = data; ++ int i, status; ++ ++ chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, feature, -1); ++ for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) ++ chip->write_byte(mtd, params[i]); ++ ++ status = chip->waitfunc(mtd, chip); ++ if (status & NAND_STATUS_FAIL) ++ return -EIO; ++ ++ return 0; ++} ++ ++/** ++ * nand_get_features_op - Do a GET FEATURES operation ++ * @chip: The NAND chip ++ * @feature: feature id ++ * @data: 4 bytes of data ++ * ++ * This function sends a GET FEATURES command and waits for the NAND to be ++ * ready before returning. ++ * This function does not select/unselect the CS line. ++ * ++ * Returns 0 on success, a negative error code otherwise. ++ */ ++static int nand_get_features_op(struct nand_chip *chip, u8 feature, ++ void *data) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ u8 *params = data; ++ int i; ++ ++ chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, feature, -1); ++ for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) ++ params[i] = chip->read_byte(mtd); ++ ++ return 0; ++} ++ ++/** ++ * nand_reset_op - Do a reset operation ++ * @chip: The NAND chip ++ * ++ * This function sends a RESET command and waits for the NAND to be ready ++ * before returning. ++ * This function does not select/unselect the CS line. ++ * ++ * Returns 0 on success, a negative error code otherwise. ++ */ ++int nand_reset_op(struct nand_chip *chip) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ ++ chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nand_reset_op); ++ ++/** ++ * nand_read_data_op - Read data from the NAND ++ * @chip: The NAND chip ++ * @buf: buffer used to store the data ++ * @len: length of the buffer ++ * @force_8bit: force 8-bit bus access ++ * ++ * This function does a raw data read on the bus. Usually used after launching ++ * another NAND operation like nand_read_page_op(). ++ * This function does not select/unselect the CS line. ++ * ++ * Returns 0 on success, a negative error code otherwise. ++ */ ++int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len, ++ bool force_8bit) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ ++ if (!len || !buf) ++ return -EINVAL; ++ ++ if (force_8bit) { ++ u8 *p = buf; ++ unsigned int i; ++ ++ for (i = 0; i < len; i++) ++ p[i] = chip->read_byte(mtd); ++ } else { ++ chip->read_buf(mtd, buf, len); ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nand_read_data_op); ++ ++/** ++ * nand_write_data_op - Write data from the NAND ++ * @chip: The NAND chip ++ * @buf: buffer containing the data to send on the bus ++ * @len: length of the buffer ++ * @force_8bit: force 8-bit bus access ++ * ++ * This function does a raw data write on the bus. Usually used after launching ++ * another NAND operation like nand_write_page_begin_op(). ++ * This function does not select/unselect the CS line. ++ * ++ * Returns 0 on success, a negative error code otherwise. ++ */ ++int nand_write_data_op(struct nand_chip *chip, const void *buf, ++ unsigned int len, bool force_8bit) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ ++ if (!len || !buf) ++ return -EINVAL; ++ ++ if (force_8bit) { ++ const u8 *p = buf; ++ unsigned int i; ++ ++ for (i = 0; i < len; i++) ++ chip->write_byte(mtd, p[i]); ++ } else { ++ chip->write_buf(mtd, buf, len); ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(nand_write_data_op); ++ ++/** + * nand_reset - Reset and initialize a NAND device + * @chip: The NAND chip + * @chipnr: Internal die id +@@ -1240,8 +1781,10 @@ int nand_reset(struct nand_chip *chip, i + * interface settings, hence this weird ->select_chip() dance. + */ + chip->select_chip(mtd, chipnr); +- chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); ++ ret = nand_reset_op(chip); + chip->select_chip(mtd, -1); ++ if (ret) ++ return ret; + + chip->select_chip(mtd, chipnr); + ret = nand_setup_data_interface(chip, chipnr); +@@ -1397,9 +1940,19 @@ EXPORT_SYMBOL(nand_check_erased_ecc_chun + int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf, int oob_required, int page) + { +- chip->read_buf(mtd, buf, mtd->writesize); +- if (oob_required) +- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); ++ int ret; ++ ++ ret = nand_read_data_op(chip, buf, mtd->writesize, false); ++ if (ret) ++ return ret; ++ ++ if (oob_required) { ++ ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize, ++ false); ++ if (ret) ++ return ret; ++ } ++ + return 0; + } + EXPORT_SYMBOL(nand_read_page_raw); +@@ -1421,29 +1974,46 @@ static int nand_read_page_raw_syndrome(s + int eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + uint8_t *oob = chip->oob_poi; +- int steps, size; ++ int steps, size, ret; + + for (steps = chip->ecc.steps; steps > 0; steps--) { +- chip->read_buf(mtd, buf, eccsize); ++ ret = nand_read_data_op(chip, buf, eccsize, false); ++ if (ret) ++ return ret; ++ + buf += eccsize; + + if (chip->ecc.prepad) { +- chip->read_buf(mtd, oob, chip->ecc.prepad); ++ ret = nand_read_data_op(chip, oob, chip->ecc.prepad, ++ false); ++ if (ret) ++ return ret; ++ + oob += chip->ecc.prepad; + } + +- chip->read_buf(mtd, oob, eccbytes); ++ ret = nand_read_data_op(chip, oob, eccbytes, false); ++ if (ret) ++ return ret; ++ + oob += eccbytes; + + if (chip->ecc.postpad) { +- chip->read_buf(mtd, oob, chip->ecc.postpad); ++ ret = nand_read_data_op(chip, oob, chip->ecc.postpad, ++ false); ++ if (ret) ++ return ret; ++ + oob += chip->ecc.postpad; + } + } + + size = mtd->oobsize - (oob - chip->oob_poi); +- if (size) +- chip->read_buf(mtd, oob, size); ++ if (size) { ++ ret = nand_read_data_op(chip, oob, size, false); ++ if (ret) ++ return ret; ++ } + + return 0; + } +@@ -1532,7 +2102,9 @@ static int nand_read_subpage(struct mtd_ + chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1); + + p = bufpoi + data_col_addr; +- chip->read_buf(mtd, p, datafrag_len); ++ ret = nand_read_data_op(chip, p, datafrag_len, false); ++ if (ret) ++ return ret; + + /* Calculate ECC */ + for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) +@@ -1550,8 +2122,11 @@ static int nand_read_subpage(struct mtd_ + gaps = 1; + + if (gaps) { +- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); +- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); ++ ret = nand_change_read_column_op(chip, mtd->writesize, ++ chip->oob_poi, mtd->oobsize, ++ false); ++ if (ret) ++ return ret; + } else { + /* + * Send the command to read the particular ECC bytes take care +@@ -1565,9 +2140,12 @@ static int nand_read_subpage(struct mtd_ + (busw - 1)) + aligned_len++; + +- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, +- mtd->writesize + aligned_pos, -1); +- chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len); ++ ret = nand_change_read_column_op(chip, ++ mtd->writesize + aligned_pos, ++ &chip->oob_poi[aligned_pos], ++ aligned_len, false); ++ if (ret) ++ return ret; + } + + ret = mtd_ooblayout_get_eccbytes(mtd, chip->buffers->ecccode, +@@ -1624,10 +2202,17 @@ static int nand_read_page_hwecc(struct m + + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + chip->ecc.hwctl(mtd, NAND_ECC_READ); +- chip->read_buf(mtd, p, eccsize); ++ ++ ret = nand_read_data_op(chip, p, eccsize, false); ++ if (ret) ++ return ret; ++ + chip->ecc.calculate(mtd, p, &ecc_calc[i]); + } +- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); ++ ++ ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize, false); ++ if (ret) ++ return ret; + + ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, + chip->ecc.total); +@@ -1686,9 +2271,13 @@ static int nand_read_page_hwecc_oob_firs + unsigned int max_bitflips = 0; + + /* Read the OOB area first */ +- chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); +- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); +- chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); ++ ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize); ++ if (ret) ++ return ret; ++ ++ ret = nand_read_page_op(chip, page, 0, NULL, 0); ++ if (ret) ++ return ret; + + ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, + chip->ecc.total); +@@ -1699,7 +2288,11 @@ static int nand_read_page_hwecc_oob_firs + int stat; + + chip->ecc.hwctl(mtd, NAND_ECC_READ); +- chip->read_buf(mtd, p, eccsize); ++ ++ ret = nand_read_data_op(chip, p, eccsize, false); ++ if (ret) ++ return ret; ++ + chip->ecc.calculate(mtd, p, &ecc_calc[i]); + + stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL); +@@ -1736,7 +2329,7 @@ static int nand_read_page_hwecc_oob_firs + static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf, int oob_required, int page) + { +- int i, eccsize = chip->ecc.size; ++ int ret, i, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + int eccpadbytes = eccbytes + chip->ecc.prepad + chip->ecc.postpad; +@@ -1748,21 +2341,36 @@ static int nand_read_page_syndrome(struc + int stat; + + chip->ecc.hwctl(mtd, NAND_ECC_READ); +- chip->read_buf(mtd, p, eccsize); ++ ++ ret = nand_read_data_op(chip, p, eccsize, false); ++ if (ret) ++ return ret; + + if (chip->ecc.prepad) { +- chip->read_buf(mtd, oob, chip->ecc.prepad); ++ ret = nand_read_data_op(chip, oob, chip->ecc.prepad, ++ false); ++ if (ret) ++ return ret; ++ + oob += chip->ecc.prepad; + } + + chip->ecc.hwctl(mtd, NAND_ECC_READSYN); +- chip->read_buf(mtd, oob, eccbytes); ++ ++ ret = nand_read_data_op(chip, oob, eccbytes, false); ++ if (ret) ++ return ret; ++ + stat = chip->ecc.correct(mtd, p, oob, NULL); + + oob += eccbytes; + + if (chip->ecc.postpad) { +- chip->read_buf(mtd, oob, chip->ecc.postpad); ++ ret = nand_read_data_op(chip, oob, chip->ecc.postpad, ++ false); ++ if (ret) ++ return ret; ++ + oob += chip->ecc.postpad; + } + +@@ -1786,8 +2394,11 @@ static int nand_read_page_syndrome(struc + + /* Calculate remaining oob bytes */ + i = mtd->oobsize - (oob - chip->oob_poi); +- if (i) +- chip->read_buf(mtd, oob, i); ++ if (i) { ++ ret = nand_read_data_op(chip, oob, i, false); ++ if (ret) ++ return ret; ++ } + + return max_bitflips; + } +@@ -1908,8 +2519,11 @@ static int nand_do_read_ops(struct mtd_i + __func__, buf); + + read_retry: +- if (nand_standard_page_accessors(&chip->ecc)) +- chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); ++ if (nand_standard_page_accessors(&chip->ecc)) { ++ ret = nand_read_page_op(chip, page, 0, NULL, 0); ++ if (ret) ++ break; ++ } + + /* + * Now read the page into the buffer. Absent an error, +@@ -2068,9 +2682,7 @@ static int nand_read(struct mtd_info *mt + */ + int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page) + { +- chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); +- chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); +- return 0; ++ return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize); + } + EXPORT_SYMBOL(nand_read_oob_std); + +@@ -2088,25 +2700,43 @@ int nand_read_oob_syndrome(struct mtd_in + int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; + int eccsize = chip->ecc.size; + uint8_t *bufpoi = chip->oob_poi; +- int i, toread, sndrnd = 0, pos; ++ int i, toread, sndrnd = 0, pos, ret; ++ ++ ret = nand_read_page_op(chip, page, chip->ecc.size, NULL, 0); ++ if (ret) ++ return ret; + +- chip->cmdfunc(mtd, NAND_CMD_READ0, chip->ecc.size, page); + for (i = 0; i < chip->ecc.steps; i++) { + if (sndrnd) { ++ int ret; ++ + pos = eccsize + i * (eccsize + chunk); + if (mtd->writesize > 512) +- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, pos, -1); ++ ret = nand_change_read_column_op(chip, pos, ++ NULL, 0, ++ false); + else +- chip->cmdfunc(mtd, NAND_CMD_READ0, pos, page); ++ ret = nand_read_page_op(chip, page, pos, NULL, ++ 0); ++ ++ if (ret) ++ return ret; + } else + sndrnd = 1; + toread = min_t(int, length, chunk); +- chip->read_buf(mtd, bufpoi, toread); ++ ++ ret = nand_read_data_op(chip, bufpoi, toread, false); ++ if (ret) ++ return ret; ++ + bufpoi += toread; + length -= toread; + } +- if (length > 0) +- chip->read_buf(mtd, bufpoi, length); ++ if (length > 0) { ++ ret = nand_read_data_op(chip, bufpoi, length, false); ++ if (ret) ++ return ret; ++ } + + return 0; + } +@@ -2120,18 +2750,8 @@ EXPORT_SYMBOL(nand_read_oob_syndrome); + */ + int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page) + { +- int status = 0; +- const uint8_t *buf = chip->oob_poi; +- int length = mtd->oobsize; +- +- chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page); +- chip->write_buf(mtd, buf, length); +- /* Send command to program the OOB data */ +- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); +- +- status = chip->waitfunc(mtd, chip); +- +- return status & NAND_STATUS_FAIL ? -EIO : 0; ++ return nand_prog_page_op(chip, page, mtd->writesize, chip->oob_poi, ++ mtd->oobsize); + } + EXPORT_SYMBOL(nand_write_oob_std); + +@@ -2147,7 +2767,7 @@ int nand_write_oob_syndrome(struct mtd_i + { + int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; + int eccsize = chip->ecc.size, length = mtd->oobsize; +- int i, len, pos, status = 0, sndcmd = 0, steps = chip->ecc.steps; ++ int ret, i, len, pos, sndcmd = 0, steps = chip->ecc.steps; + const uint8_t *bufpoi = chip->oob_poi; + + /* +@@ -2161,7 +2781,10 @@ int nand_write_oob_syndrome(struct mtd_i + } else + pos = eccsize; + +- chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page); ++ ret = nand_prog_page_begin_op(chip, page, pos, NULL, 0); ++ if (ret) ++ return ret; ++ + for (i = 0; i < steps; i++) { + if (sndcmd) { + if (mtd->writesize <= 512) { +@@ -2170,28 +2793,40 @@ int nand_write_oob_syndrome(struct mtd_i + len = eccsize; + while (len > 0) { + int num = min_t(int, len, 4); +- chip->write_buf(mtd, (uint8_t *)&fill, +- num); ++ ++ ret = nand_write_data_op(chip, &fill, ++ num, false); ++ if (ret) ++ return ret; ++ + len -= num; + } + } else { + pos = eccsize + i * (eccsize + chunk); +- chip->cmdfunc(mtd, NAND_CMD_RNDIN, pos, -1); ++ ret = nand_change_write_column_op(chip, pos, ++ NULL, 0, ++ false); ++ if (ret) ++ return ret; + } + } else + sndcmd = 1; + len = min_t(int, length, chunk); +- chip->write_buf(mtd, bufpoi, len); ++ ++ ret = nand_write_data_op(chip, bufpoi, len, false); ++ if (ret) ++ return ret; ++ + bufpoi += len; + length -= len; + } +- if (length > 0) +- chip->write_buf(mtd, bufpoi, length); +- +- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); +- status = chip->waitfunc(mtd, chip); ++ if (length > 0) { ++ ret = nand_write_data_op(chip, bufpoi, length, false); ++ if (ret) ++ return ret; ++ } + +- return status & NAND_STATUS_FAIL ? -EIO : 0; ++ return nand_prog_page_end_op(chip); + } + EXPORT_SYMBOL(nand_write_oob_syndrome); + +@@ -2346,9 +2981,18 @@ static int nand_read_oob(struct mtd_info + int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf, int oob_required, int page) + { +- chip->write_buf(mtd, buf, mtd->writesize); +- if (oob_required) +- chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); ++ int ret; ++ ++ ret = nand_write_data_op(chip, buf, mtd->writesize, false); ++ if (ret) ++ return ret; ++ ++ if (oob_required) { ++ ret = nand_write_data_op(chip, chip->oob_poi, mtd->oobsize, ++ false); ++ if (ret) ++ return ret; ++ } + + return 0; + } +@@ -2372,29 +3016,46 @@ static int nand_write_page_raw_syndrome( + int eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + uint8_t *oob = chip->oob_poi; +- int steps, size; ++ int steps, size, ret; + + for (steps = chip->ecc.steps; steps > 0; steps--) { +- chip->write_buf(mtd, buf, eccsize); ++ ret = nand_write_data_op(chip, buf, eccsize, false); ++ if (ret) ++ return ret; ++ + buf += eccsize; + + if (chip->ecc.prepad) { +- chip->write_buf(mtd, oob, chip->ecc.prepad); ++ ret = nand_write_data_op(chip, oob, chip->ecc.prepad, ++ false); ++ if (ret) ++ return ret; ++ + oob += chip->ecc.prepad; + } + +- chip->write_buf(mtd, oob, eccbytes); ++ ret = nand_write_data_op(chip, oob, eccbytes, false); ++ if (ret) ++ return ret; ++ + oob += eccbytes; + + if (chip->ecc.postpad) { +- chip->write_buf(mtd, oob, chip->ecc.postpad); ++ ret = nand_write_data_op(chip, oob, chip->ecc.postpad, ++ false); ++ if (ret) ++ return ret; ++ + oob += chip->ecc.postpad; + } + } + + size = mtd->oobsize - (oob - chip->oob_poi); +- if (size) +- chip->write_buf(mtd, oob, size); ++ if (size) { ++ ret = nand_write_data_op(chip, oob, size, false); ++ if (ret) ++ return ret; ++ } + + return 0; + } +@@ -2448,7 +3109,11 @@ static int nand_write_page_hwecc(struct + + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + chip->ecc.hwctl(mtd, NAND_ECC_WRITE); +- chip->write_buf(mtd, p, eccsize); ++ ++ ret = nand_write_data_op(chip, p, eccsize, false); ++ if (ret) ++ return ret; ++ + chip->ecc.calculate(mtd, p, &ecc_calc[i]); + } + +@@ -2457,7 +3122,9 @@ static int nand_write_page_hwecc(struct + if (ret) + return ret; + +- chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); ++ ret = nand_write_data_op(chip, chip->oob_poi, mtd->oobsize, false); ++ if (ret) ++ return ret; + + return 0; + } +@@ -2493,7 +3160,9 @@ static int nand_write_subpage_hwecc(stru + chip->ecc.hwctl(mtd, NAND_ECC_WRITE); + + /* write data (untouched subpages already masked by 0xFF) */ +- chip->write_buf(mtd, buf, ecc_size); ++ ret = nand_write_data_op(chip, buf, ecc_size, false); ++ if (ret) ++ return ret; + + /* mask ECC of un-touched subpages by padding 0xFF */ + if ((step < start_step) || (step > end_step)) +@@ -2520,7 +3189,9 @@ static int nand_write_subpage_hwecc(stru + return ret; + + /* write OOB buffer to NAND device */ +- chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); ++ ret = nand_write_data_op(chip, chip->oob_poi, mtd->oobsize, false); ++ if (ret) ++ return ret; + + return 0; + } +@@ -2547,31 +3218,49 @@ static int nand_write_page_syndrome(stru + int eccsteps = chip->ecc.steps; + const uint8_t *p = buf; + uint8_t *oob = chip->oob_poi; ++ int ret; + + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { +- + chip->ecc.hwctl(mtd, NAND_ECC_WRITE); +- chip->write_buf(mtd, p, eccsize); ++ ++ ret = nand_write_data_op(chip, p, eccsize, false); ++ if (ret) ++ return ret; + + if (chip->ecc.prepad) { +- chip->write_buf(mtd, oob, chip->ecc.prepad); ++ ret = nand_write_data_op(chip, oob, chip->ecc.prepad, ++ false); ++ if (ret) ++ return ret; ++ + oob += chip->ecc.prepad; + } + + chip->ecc.calculate(mtd, p, oob); +- chip->write_buf(mtd, oob, eccbytes); ++ ++ ret = nand_write_data_op(chip, oob, eccbytes, false); ++ if (ret) ++ return ret; ++ + oob += eccbytes; + + if (chip->ecc.postpad) { +- chip->write_buf(mtd, oob, chip->ecc.postpad); ++ ret = nand_write_data_op(chip, oob, chip->ecc.postpad, ++ false); ++ if (ret) ++ return ret; ++ + oob += chip->ecc.postpad; + } + } + + /* Calculate remaining oob bytes */ + i = mtd->oobsize - (oob - chip->oob_poi); +- if (i) +- chip->write_buf(mtd, oob, i); ++ if (i) { ++ ret = nand_write_data_op(chip, oob, i, false); ++ if (ret) ++ return ret; ++ } + + return 0; + } +@@ -2599,8 +3288,11 @@ static int nand_write_page(struct mtd_in + else + subpage = 0; + +- if (nand_standard_page_accessors(&chip->ecc)) +- chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); ++ if (nand_standard_page_accessors(&chip->ecc)) { ++ status = nand_prog_page_begin_op(chip, page, 0, NULL, 0); ++ if (status) ++ return status; ++ } + + if (unlikely(raw)) + status = chip->ecc.write_page_raw(mtd, chip, buf, +@@ -2615,13 +3307,8 @@ static int nand_write_page(struct mtd_in + if (status < 0) + return status; + +- if (nand_standard_page_accessors(&chip->ecc)) { +- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); +- +- status = chip->waitfunc(mtd, chip); +- if (status & NAND_STATUS_FAIL) +- return -EIO; +- } ++ if (nand_standard_page_accessors(&chip->ecc)) ++ return nand_prog_page_end_op(chip); + + return 0; + } +@@ -2994,17 +3681,12 @@ out: + static int single_erase(struct mtd_info *mtd, int page) + { + struct nand_chip *chip = mtd_to_nand(mtd); +- int status; ++ unsigned int eraseblock; + + /* Send commands to erase a block */ +- chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); +- chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); +- +- status = chip->waitfunc(mtd, chip); +- if (status < 0) +- return status; ++ eraseblock = page >> (chip->phys_erase_shift - chip->page_shift); + +- return status & NAND_STATUS_FAIL ? -EIO : 0; ++ return nand_erase_op(chip, eraseblock); + } + + /** +@@ -3231,22 +3913,12 @@ static int nand_max_bad_blocks(struct mt + static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip, + int addr, uint8_t *subfeature_param) + { +- int status; +- int i; +- + if (!chip->onfi_version || + !(le16_to_cpu(chip->onfi_params.opt_cmd) + & ONFI_OPT_CMD_SET_GET_FEATURES)) + return -EINVAL; + +- chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1); +- for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) +- chip->write_byte(mtd, subfeature_param[i]); +- +- status = chip->waitfunc(mtd, chip); +- if (status & NAND_STATUS_FAIL) +- return -EIO; +- return 0; ++ return nand_set_features_op(chip, addr, subfeature_param); + } + + /** +@@ -3259,17 +3931,12 @@ static int nand_onfi_set_features(struct + static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip, + int addr, uint8_t *subfeature_param) + { +- int i; +- + if (!chip->onfi_version || + !(le16_to_cpu(chip->onfi_params.opt_cmd) + & ONFI_OPT_CMD_SET_GET_FEATURES)) + return -EINVAL; + +- chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1); +- for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) +- *subfeature_param++ = chip->read_byte(mtd); +- return 0; ++ return nand_get_features_op(chip, addr, subfeature_param); + } + + /** +@@ -3412,12 +4079,11 @@ static u16 onfi_crc16(u16 crc, u8 const + static int nand_flash_detect_ext_param_page(struct nand_chip *chip, + struct nand_onfi_params *p) + { +- struct mtd_info *mtd = nand_to_mtd(chip); + struct onfi_ext_param_page *ep; + struct onfi_ext_section *s; + struct onfi_ext_ecc_info *ecc; + uint8_t *cursor; +- int ret = -EINVAL; ++ int ret; + int len; + int i; + +@@ -3427,14 +4093,18 @@ static int nand_flash_detect_ext_param_p + return -ENOMEM; + + /* Send our own NAND_CMD_PARAM. */ +- chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1); ++ ret = nand_read_param_page_op(chip, 0, NULL, 0); ++ if (ret) ++ goto ext_out; + + /* Use the Change Read Column command to skip the ONFI param pages. */ +- chip->cmdfunc(mtd, NAND_CMD_RNDOUT, +- sizeof(*p) * p->num_of_param_pages , -1); ++ ret = nand_change_read_column_op(chip, ++ sizeof(*p) * p->num_of_param_pages, ++ ep, len, true); ++ if (ret) ++ goto ext_out; + +- /* Read out the Extended Parameter Page. */ +- chip->read_buf(mtd, (uint8_t *)ep, len); ++ ret = -EINVAL; + if ((onfi_crc16(ONFI_CRC_BASE, ((uint8_t *)ep) + 2, len - 2) + != le16_to_cpu(ep->crc))) { + pr_debug("fail in the CRC.\n"); +@@ -3487,19 +4157,23 @@ static int nand_flash_detect_onfi(struct + { + struct mtd_info *mtd = nand_to_mtd(chip); + struct nand_onfi_params *p = &chip->onfi_params; +- int i, j; +- int val; ++ char id[4]; ++ int i, ret, val; + + /* Try ONFI for unknown chip or LP */ +- chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1); +- if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' || +- chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I') ++ ret = nand_readid_op(chip, 0x20, id, sizeof(id)); ++ if (ret || strncmp(id, "ONFI", 4)) ++ return 0; ++ ++ ret = nand_read_param_page_op(chip, 0, NULL, 0); ++ if (ret) + return 0; + +- chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1); + for (i = 0; i < 3; i++) { +- for (j = 0; j < sizeof(*p); j++) +- ((uint8_t *)p)[j] = chip->read_byte(mtd); ++ ret = nand_read_data_op(chip, p, sizeof(*p), true); ++ if (ret) ++ return 0; ++ + if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) == + le16_to_cpu(p->crc)) { + break; +@@ -3590,20 +4264,22 @@ static int nand_flash_detect_jedec(struc + struct mtd_info *mtd = nand_to_mtd(chip); + struct nand_jedec_params *p = &chip->jedec_params; + struct jedec_ecc_info *ecc; +- int val; +- int i, j; ++ char id[5]; ++ int i, val, ret; + + /* Try JEDEC for unknown chip or LP */ +- chip->cmdfunc(mtd, NAND_CMD_READID, 0x40, -1); +- if (chip->read_byte(mtd) != 'J' || chip->read_byte(mtd) != 'E' || +- chip->read_byte(mtd) != 'D' || chip->read_byte(mtd) != 'E' || +- chip->read_byte(mtd) != 'C') ++ ret = nand_readid_op(chip, 0x40, id, sizeof(id)); ++ if (ret || strncmp(id, "JEDEC", sizeof(id))) ++ return 0; ++ ++ ret = nand_read_param_page_op(chip, 0x40, NULL, 0); ++ if (ret) + return 0; + +- chip->cmdfunc(mtd, NAND_CMD_PARAM, 0x40, -1); + for (i = 0; i < 3; i++) { +- for (j = 0; j < sizeof(*p); j++) +- ((uint8_t *)p)[j] = chip->read_byte(mtd); ++ ret = nand_read_data_op(chip, p, sizeof(*p), true); ++ if (ret) ++ return 0; + + if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 510) == + le16_to_cpu(p->crc)) +@@ -3882,8 +4558,7 @@ static int nand_detect(struct nand_chip + { + const struct nand_manufacturer *manufacturer; + struct mtd_info *mtd = nand_to_mtd(chip); +- int busw; +- int i; ++ int busw, ret; + u8 *id_data = chip->id.data; + u8 maf_id, dev_id; + +@@ -3891,17 +4566,21 @@ static int nand_detect(struct nand_chip + * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx) + * after power-up. + */ +- nand_reset(chip, 0); ++ ret = nand_reset(chip, 0); ++ if (ret) ++ return ret; + + /* Select the device */ + chip->select_chip(mtd, 0); + + /* Send the command for reading device ID */ +- chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); ++ ret = nand_readid_op(chip, 0, id_data, 2); ++ if (ret) ++ return ret; + + /* Read manufacturer and device IDs */ +- maf_id = chip->read_byte(mtd); +- dev_id = chip->read_byte(mtd); ++ maf_id = id_data[0]; ++ dev_id = id_data[1]; + + /* + * Try again to make sure, as some systems the bus-hold or other +@@ -3910,11 +4589,10 @@ static int nand_detect(struct nand_chip + * not match, ignore the device completely. + */ + +- chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); +- + /* Read entire ID string */ +- for (i = 0; i < ARRAY_SIZE(chip->id.data); i++) +- id_data[i] = chip->read_byte(mtd); ++ ret = nand_readid_op(chip, 0, id_data, sizeof(chip->id.data)); ++ if (ret) ++ return ret; + + if (id_data[0] != maf_id || id_data[1] != dev_id) { + pr_info("second ID read did not match %02x,%02x against %02x,%02x\n", +@@ -4238,15 +4916,16 @@ int nand_scan_ident(struct mtd_info *mtd + + /* Check for a chip array */ + for (i = 1; i < maxchips; i++) { ++ u8 id[2]; ++ + /* See comment in nand_get_flash_type for reset */ + nand_reset(chip, i); + + chip->select_chip(mtd, i); + /* Send the command for reading device ID */ +- chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); ++ nand_readid_op(chip, 0, id, sizeof(id)); + /* Read manufacturer and device IDs */ +- if (nand_maf_id != chip->read_byte(mtd) || +- nand_dev_id != chip->read_byte(mtd)) { ++ if (nand_maf_id != id[0] || nand_dev_id != id[1]) { + chip->select_chip(mtd, -1); + break; + } +--- a/drivers/mtd/nand/qcom_nandc.c ++++ b/drivers/mtd/nand/qcom_nandc.c +@@ -1990,7 +1990,7 @@ static int qcom_nandc_write_oob(struct m + struct nand_ecc_ctrl *ecc = &chip->ecc; + u8 *oob = chip->oob_poi; + int data_size, oob_size; +- int ret, status = 0; ++ int ret; + + host->use_ecc = true; + +@@ -2027,11 +2027,7 @@ static int qcom_nandc_write_oob(struct m + return -EIO; + } + +- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); +- +- status = chip->waitfunc(mtd, chip); +- +- return status & NAND_STATUS_FAIL ? -EIO : 0; ++ return nand_prog_page_end_op(chip); + } + + static int qcom_nandc_block_bad(struct mtd_info *mtd, loff_t ofs) +@@ -2081,7 +2077,7 @@ static int qcom_nandc_block_markbad(stru + struct qcom_nand_host *host = to_qcom_nand_host(chip); + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + struct nand_ecc_ctrl *ecc = &chip->ecc; +- int page, ret, status = 0; ++ int page, ret; + + clear_read_regs(nandc); + clear_bam_transaction(nandc); +@@ -2114,11 +2110,7 @@ static int qcom_nandc_block_markbad(stru + return -EIO; + } + +- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); +- +- status = chip->waitfunc(mtd, chip); +- +- return status & NAND_STATUS_FAIL ? -EIO : 0; ++ return nand_prog_page_end_op(chip); + } + + /* +--- a/include/linux/mtd/rawnand.h ++++ b/include/linux/mtd/rawnand.h +@@ -1313,6 +1313,35 @@ int nand_write_page_raw(struct mtd_info + /* Reset and initialize a NAND device */ + int nand_reset(struct nand_chip *chip, int chipnr); + ++/* NAND operation helpers */ ++int nand_reset_op(struct nand_chip *chip); ++int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf, ++ unsigned int len); ++int nand_status_op(struct nand_chip *chip, u8 *status); ++int nand_exit_status_op(struct nand_chip *chip); ++int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock); ++int nand_read_page_op(struct nand_chip *chip, unsigned int page, ++ unsigned int offset_in_page, void *buf, unsigned int len); ++int nand_change_read_column_op(struct nand_chip *chip, ++ unsigned int offset_in_page, void *buf, ++ unsigned int len, bool force_8bit); ++int nand_read_oob_op(struct nand_chip *chip, unsigned int page, ++ unsigned int offset_in_page, void *buf, unsigned int len); ++int nand_prog_page_begin_op(struct nand_chip *chip, unsigned int page, ++ unsigned int offset_in_page, const void *buf, ++ unsigned int len); ++int nand_prog_page_end_op(struct nand_chip *chip); ++int nand_prog_page_op(struct nand_chip *chip, unsigned int page, ++ unsigned int offset_in_page, const void *buf, ++ unsigned int len); ++int nand_change_write_column_op(struct nand_chip *chip, ++ unsigned int offset_in_page, const void *buf, ++ unsigned int len, bool force_8bit); ++int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len, ++ bool force_8bit); ++int nand_write_data_op(struct nand_chip *chip, const void *buf, ++ unsigned int len, bool force_8bit); ++ + /* Free resources held by the NAND device */ + void nand_cleanup(struct nand_chip *chip); + diff --git a/target/linux/ipq40xx/patches-4.14/050-0005-mtd-nand-force-drivers-to-explicitly-send-READ-PROG-.patch b/target/linux/ipq40xx/patches-4.14/050-0005-mtd-nand-force-drivers-to-explicitly-send-READ-PROG-.patch new file mode 100644 index 000000000..e7e2e798a --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/050-0005-mtd-nand-force-drivers-to-explicitly-send-READ-PROG-.patch @@ -0,0 +1,94 @@ +From 25f815f66a141436df8a4c45e5d2765272aea2ac Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 30 Nov 2017 18:01:30 +0100 +Subject: [PATCH 5/7] mtd: nand: force drivers to explicitly send READ/PROG + commands + +The core currently send the READ0 and SEQIN+PAGEPROG commands in +nand_do_read/write_ops(). This is inconsistent with +->read/write_oob[_raw]() hooks behavior which are expected to send +these commands. + +There's already a flag (NAND_ECC_CUSTOM_PAGE_ACCESS) to inform the core +that a specific controller wants to send the READ/SEQIN+PAGEPROG +commands on its own, but it's an opt-in flag, and existing drivers are +unlikely to be updated to pass it. + +Moreover, some controllers cannot dissociate the READ/PAGEPROG commands +from the associated data transfer and ECC engine activation, and +developers have to hack things in their ->cmdfunc() implementation to +handle such complex cases, or have to accept the perf penalty of sending +twice the same command. +To address this problem we are planning on adding a new interface which +is passed all information about a NAND operation (including the amount +of data to transfer) and replacing all calls to ->cmdfunc() to calls to +this new ->exec_op() hook. But, in order to do that, we need to have all +->cmdfunc() calls placed near their associated ->read/write_buf/byte() +calls. + +Modify the core and relevant drivers to make NAND_ECC_CUSTOM_PAGE_ACCESS +the default case, and remove this flag. + +Signed-off-by: Boris Brezillon +[miquel.raynal@free-electrons.com: tested, fixed and rebased on nand/next] +Signed-off-by: Miquel Raynal +Acked-by: Masahiro Yamada +--- + drivers/mtd/nand/qcom_nandc.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/drivers/mtd/nand/qcom_nandc.c ++++ b/drivers/mtd/nand/qcom_nandc.c +@@ -1725,6 +1725,7 @@ static int qcom_nandc_read_page(struct m + u8 *data_buf, *oob_buf = NULL; + int ret; + ++ nand_read_page_op(chip, page, 0, NULL, 0); + data_buf = buf; + oob_buf = oob_required ? chip->oob_poi : NULL; + +@@ -1750,6 +1751,7 @@ static int qcom_nandc_read_page_raw(stru + int i, ret; + int read_loc; + ++ nand_read_page_op(chip, page, 0, NULL, 0); + data_buf = buf; + oob_buf = chip->oob_poi; + +@@ -1850,6 +1852,8 @@ static int qcom_nandc_write_page(struct + u8 *data_buf, *oob_buf; + int i, ret; + ++ nand_prog_page_begin_op(chip, page, 0, NULL, 0); ++ + clear_read_regs(nandc); + clear_bam_transaction(nandc); + +@@ -1902,6 +1906,9 @@ static int qcom_nandc_write_page(struct + + free_descs(nandc); + ++ if (!ret) ++ ret = nand_prog_page_end_op(chip); ++ + return ret; + } + +@@ -1916,6 +1923,7 @@ static int qcom_nandc_write_page_raw(str + u8 *data_buf, *oob_buf; + int i, ret; + ++ nand_prog_page_begin_op(chip, page, 0, NULL, 0); + clear_read_regs(nandc); + clear_bam_transaction(nandc); + +@@ -1970,6 +1978,9 @@ static int qcom_nandc_write_page_raw(str + + free_descs(nandc); + ++ if (!ret) ++ ret = nand_prog_page_end_op(chip); ++ + return ret; + } + diff --git a/target/linux/ipq40xx/patches-4.14/050-0006-mtd-nand-qcom-Add-a-NULL-check-for-devm_kasprintf.patch b/target/linux/ipq40xx/patches-4.14/050-0006-mtd-nand-qcom-Add-a-NULL-check-for-devm_kasprintf.patch new file mode 100644 index 000000000..4ddc0148a --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/050-0006-mtd-nand-qcom-Add-a-NULL-check-for-devm_kasprintf.patch @@ -0,0 +1,26 @@ +From 069f05346d01e7298939f16533953cdf52370be3 Mon Sep 17 00:00:00 2001 +From: Fabio Estevam +Date: Fri, 5 Jan 2018 18:02:55 -0200 +Subject: [PATCH 6/7] mtd: nand: qcom: Add a NULL check for devm_kasprintf() + +devm_kasprintf() may fail, so we should better add a NULL check +and propagate an error on failure. + +Signed-off-by: Fabio Estevam +Signed-off-by: Boris Brezillon +--- + drivers/mtd/nand/qcom_nandc.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/mtd/nand/qcom_nandc.c ++++ b/drivers/mtd/nand/qcom_nandc.c +@@ -2639,6 +2639,9 @@ static int qcom_nand_host_init(struct qc + + nand_set_flash_node(chip, dn); + mtd->name = devm_kasprintf(dev, GFP_KERNEL, "qcom_nand.%d", host->cs); ++ if (!mtd->name) ++ return -ENOMEM; ++ + mtd->owner = THIS_MODULE; + mtd->dev.parent = dev; + diff --git a/target/linux/ipq40xx/patches-4.14/059-ARM-cpuidle-Add-cpuidle-support-for-QCOM-cpus.patch b/target/linux/ipq40xx/patches-4.14/059-ARM-cpuidle-Add-cpuidle-support-for-QCOM-cpus.patch new file mode 100644 index 000000000..5bd58c813 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/059-ARM-cpuidle-Add-cpuidle-support-for-QCOM-cpus.patch @@ -0,0 +1,29 @@ +From 04ca10340f1b4d92e849724d322a7ca225d11539 Mon Sep 17 00:00:00 2001 +From: Lina Iyer +Date: Wed, 25 Mar 2015 14:25:29 -0600 +Subject: [PATCH 59/69] ARM: cpuidle: Add cpuidle support for QCOM cpus + +Define ARM_QCOM_CPUIDLE config item to enable cpuidle support. + +Cc: Stephen Boyd +Cc: Arnd Bergmann +Cc: Kevin Hilman +Cc: Daniel Lezcano +Signed-off-by: Lina Iyer +--- + drivers/cpuidle/Kconfig.arm | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/cpuidle/Kconfig.arm ++++ b/drivers/cpuidle/Kconfig.arm +@@ -75,3 +75,10 @@ config ARM_MVEBU_V7_CPUIDLE + depends on ARCH_MVEBU && !ARM64 + help + Select this to enable cpuidle on Armada 370, 38x and XP processors. ++ ++config ARM_QCOM_CPUIDLE ++ bool "CPU Idle Driver for QCOM processors" ++ depends on ARCH_QCOM ++ select ARM_CPUIDLE ++ help ++ Select this to enable cpuidle on QCOM processors. diff --git a/target/linux/ipq40xx/patches-4.14/069-arm-boot-add-dts-files.patch b/target/linux/ipq40xx/patches-4.14/069-arm-boot-add-dts-files.patch new file mode 100644 index 000000000..134197fe0 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/069-arm-boot-add-dts-files.patch @@ -0,0 +1,28 @@ +From 8f68331e14dff9a101f2d0e1d6bec84a031f27ee Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 9 Mar 2017 11:03:18 +0100 +Subject: [PATCH 69/69] arm: boot: add dts files + +Signed-off-by: John Crispin +--- + arch/arm/boot/dts/Makefile | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -697,7 +697,15 @@ dtb-$(CONFIG_ARCH_QCOM) += \ + qcom-apq8074-dragonboard.dtb \ + qcom-apq8084-ifc6540.dtb \ + qcom-apq8084-mtp.dtb \ ++ qcom-ipq4018-a42.dtb \ ++ qcom-ipq4018-fritz4040.dtb \ ++ qcom-ipq4018-rt-ac58u.dtb \ + qcom-ipq4019-ap.dk01.1-c1.dtb \ ++ qcom-ipq4019-ap.dk04.1-c1.dtb \ ++ qcom-ipq4019-rt-acrh17.dtb \ ++ qcom-ipq4028-wpj428.dtb \ ++ qcom-ipq4029-gl-b1300.dtb \ ++ qcom-ipq4029-mr33.dtb \ + qcom-ipq8064-ap148.dtb \ + qcom-msm8660-surf.dtb \ + qcom-msm8960-cdp.dtb \ diff --git a/target/linux/ipq40xx/patches-4.14/070-qcom-spm-fix-probe-order.patch b/target/linux/ipq40xx/patches-4.14/070-qcom-spm-fix-probe-order.patch new file mode 100644 index 000000000..b7e375dfb --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/070-qcom-spm-fix-probe-order.patch @@ -0,0 +1,16 @@ +Check for SCM availability before attempting to use SPM + +Signed-off-by: Felix Fietkau + +--- a/drivers/soc/qcom/spm.c ++++ b/drivers/soc/qcom/spm.c +@@ -219,6 +219,9 @@ static int __init qcom_cpuidle_init(stru + cpumask_t mask; + bool use_scm_power_down = false; + ++ if (!qcom_scm_is_available()) ++ return -EPROBE_DEFER; ++ + for (i = 0; ; i++) { + state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i); + if (!state_node) diff --git a/target/linux/ipq40xx/patches-4.14/101-ARM-dts-ipq4019-Add-a-few-peripheral-nodes.patch b/target/linux/ipq40xx/patches-4.14/101-ARM-dts-ipq4019-Add-a-few-peripheral-nodes.patch new file mode 100644 index 000000000..0f039f206 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/101-ARM-dts-ipq4019-Add-a-few-peripheral-nodes.patch @@ -0,0 +1,188 @@ +From patchwork Mon Jan 29 05:11:16 2018 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [02/15] ARM: dts: ipq4019: Add a few peripheral nodes +From: Sricharan R +X-Patchwork-Id: 10189263 +Message-Id: <1517202689-14212-3-git-send-email-sricharan@codeaurora.org> +To: robh+dt@kernel.org, robh@kernel.org, mark.rutland@arm.com, + linux@armlinux.org.uk, andy.gross@linaro.org, david.brown@linaro.org, + catalin.marinas@arm.com, will.deacon@arm.com, sboyd@codeaurora.org, + bjorn.andersson@linaro.org, devicetree@vger.kernel.org, + linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, + linux-arm-msm@vger.kernel.org, linux-soc@vger.kernel.org +Cc: sricharan@codeaurora.org +Date: Mon, 29 Jan 2018 10:41:16 +0530 + +Now with the driver updates for some peripherals being there, +add i2c, spi, pcie, bam, qpic-nand, scm nodes to enhance the available +peripheral support. + +Signed-off-by: Sricharan R +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 134 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 134 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -25,7 +25,9 @@ + + aliases { + spi0 = &spi_0; ++ spi1 = &spi_1; + i2c0 = &i2c_0; ++ i2c1 = &i2c_1; + }; + + cpus { +@@ -190,6 +192,22 @@ + clock-names = "core", "iface"; + #address-cells = <1>; + #size-cells = <0>; ++ dmas = <&blsp_dma 5>, <&blsp_dma 4>; ++ dma-names = "rx", "tx"; ++ status = "disabled"; ++ }; ++ ++ spi_1: spi@78b6000 { /* BLSP1 QUP2 */ ++ compatible = "qcom,spi-qup-v2.2.1"; ++ reg = <0x78b6000 0x600>; ++ interrupts = ; ++ clocks = <&gcc GCC_BLSP1_QUP2_SPI_APPS_CLK>, ++ <&gcc GCC_BLSP1_AHB_CLK>; ++ clock-names = "core", "iface"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ dmas = <&blsp_dma 7>, <&blsp_dma 6>; ++ dma-names = "rx", "tx"; + status = "disabled"; + }; + +@@ -202,9 +220,24 @@ + clock-names = "iface", "core"; + #address-cells = <1>; + #size-cells = <0>; ++ dmas = <&blsp_dma 9>, <&blsp_dma 8>; ++ dma-names = "rx", "tx"; + status = "disabled"; + }; + ++ i2c_1: i2c@78b8000 { /* BLSP1 QUP4 */ ++ compatible = "qcom,i2c-qup-v2.2.1"; ++ reg = <0x78b8000 0x600>; ++ interrupts = ; ++ clocks = <&gcc GCC_BLSP1_AHB_CLK>, ++ <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>; ++ clock-names = "iface", "core"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ dmas = <&blsp_dma 11>, <&blsp_dma 10>; ++ dma-names = "rx", "tx"; ++ status = "disabled"; ++ }; + + cryptobam: dma@8e04000 { + compatible = "qcom,bam-v1.7.0"; +@@ -311,6 +344,101 @@ + reg = <0x4ab000 0x4>; + }; + ++ pcie0: pci@40000000 { ++ compatible = "qcom,pcie-ipq4019", "snps,dw-pcie"; ++ reg = <0x40000000 0xf1d ++ 0x40000f20 0xa8 ++ 0x80000 0x2000 ++ 0x40100000 0x1000>; ++ reg-names = "dbi", "elbi", "parf", "config"; ++ device_type = "pci"; ++ linux,pci-domain = <0>; ++ bus-range = <0x00 0xff>; ++ num-lanes = <1>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ++ ranges = <0x81000000 0 0x40200000 0x40200000 0 0x00100000 ++ 0x82000000 0 0x48000000 0x48000000 0 0x10000000>; ++ ++ interrupts = ; ++ interrupt-names = "msi"; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 0x7>; ++ interrupt-map = <0 0 0 1 &intc 0 142 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ ++ <0 0 0 2 &intc 0 143 IRQ_TYPE_LEVEL_HIGH>, /* int_b */ ++ <0 0 0 3 &intc 0 144 IRQ_TYPE_LEVEL_HIGH>, /* int_c */ ++ <0 0 0 4 &intc 0 145 IRQ_TYPE_LEVEL_HIGH>; /* int_d */ ++ clocks = <&gcc GCC_PCIE_AHB_CLK>, ++ <&gcc GCC_PCIE_AXI_M_CLK>, ++ <&gcc GCC_PCIE_AXI_S_CLK>; ++ clock-names = "aux", ++ "master_bus", ++ "slave_bus"; ++ ++ resets = <&gcc PCIE_AXI_M_ARES>, ++ <&gcc PCIE_AXI_S_ARES>, ++ <&gcc PCIE_PIPE_ARES>, ++ <&gcc PCIE_AXI_M_VMIDMT_ARES>, ++ <&gcc PCIE_AXI_S_XPU_ARES>, ++ <&gcc PCIE_PARF_XPU_ARES>, ++ <&gcc PCIE_PHY_ARES>, ++ <&gcc PCIE_AXI_M_STICKY_ARES>, ++ <&gcc PCIE_PIPE_STICKY_ARES>, ++ <&gcc PCIE_PWR_ARES>, ++ <&gcc PCIE_AHB_ARES>, ++ <&gcc PCIE_PHY_AHB_ARES>; ++ reset-names = "axi_m", ++ "axi_s", ++ "pipe", ++ "axi_m_vmid", ++ "axi_s_xpu", ++ "parf", ++ "phy", ++ "axi_m_sticky", ++ "pipe_sticky", ++ "pwr", ++ "ahb", ++ "phy_ahb"; ++ ++ status = "disabled"; ++ }; ++ ++ qpic_bam: dma@7984000 { ++ compatible = "qcom,bam-v1.7.0"; ++ reg = <0x7984000 0x1a000>; ++ interrupts = ; ++ clocks = <&gcc GCC_QPIC_CLK>; ++ clock-names = "bam_clk"; ++ #dma-cells = <1>; ++ qcom,ee = <0>; ++ status = "disabled"; ++ }; ++ ++ nand: qpic-nand@79b0000 { ++ compatible = "qcom,ipq4019-nand"; ++ reg = <0x79b0000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clocks = <&gcc GCC_QPIC_CLK>, ++ <&gcc GCC_QPIC_AHB_CLK>; ++ clock-names = "core", "aon"; ++ ++ dmas = <&qpic_bam 0>, ++ <&qpic_bam 1>, ++ <&qpic_bam 2>; ++ dma-names = "tx", "rx", "cmd"; ++ status = "disabled"; ++ ++ nand@0 { ++ reg = <0>; ++ ++ nand-ecc-strength = <4>; ++ nand-ecc-step-size = <512>; ++ nand-bus-width = <8>; ++ }; ++ }; ++ + wifi0: wifi@a000000 { + compatible = "qcom,ipq4019-wifi"; + reg = <0xa000000 0x200000>; diff --git a/target/linux/ipq40xx/patches-4.14/102-ARM-dts-ipq4019-fix-PCI-range.patch b/target/linux/ipq40xx/patches-4.14/102-ARM-dts-ipq4019-fix-PCI-range.patch new file mode 100644 index 000000000..eaccb00bb --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/102-ARM-dts-ipq4019-fix-PCI-range.patch @@ -0,0 +1,23 @@ +From 561a7e69d2811f236266ff9222a1e683ebf8b9e0 Mon Sep 17 00:00:00 2001 +From: Mathias Kresin +Date: Thu, 1 Mar 2018 20:50:29 +0100 +Subject: [PATCH] ARM: dts: ipq4019: fix PCI range + +The PCI range is invalid and PCI attached devices doen't work. + +Signed-off-by: Mathias Kresin +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -359,7 +359,7 @@ + #size-cells = <2>; + + ranges = <0x81000000 0 0x40200000 0x40200000 0 0x00100000 +- 0x82000000 0 0x48000000 0x48000000 0 0x10000000>; ++ 0x82000000 0 0x40300000 0x40300000 0 0x400000>; + + interrupts = ; + interrupt-names = "msi"; diff --git a/target/linux/ipq40xx/patches-4.14/104-mtd-nand-add-Winbond-manufacturer-and-chip.patch b/target/linux/ipq40xx/patches-4.14/104-mtd-nand-add-Winbond-manufacturer-and-chip.patch new file mode 100644 index 000000000..295bc163b --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/104-mtd-nand-add-Winbond-manufacturer-and-chip.patch @@ -0,0 +1,38 @@ +From 07b6d0cdbbda8c917480eceaec668f09e4cf24a5 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Mon, 14 Nov 2016 23:49:22 +0100 +Subject: [PATCH] mtd: nand: add Winbond manufacturer and chip + +This patch adds the W25N01GV NAND to the table of +known devices. Without this patch the device gets detected: + +nand: device found, Manufacturer ID: 0xef, Chip ID: 0xaa +nand: Unknown NAND 256MiB 1,8V 8-bit +nand: 256 MiB, SLC, erase size: 64 KiB, page size: 1024, OOB size : 16 + +Whereas the u-boot identifies it as: +spi_nand: spi_nand_flash_probe SF NAND ID 00:ef:aa:21 +SF: Detected W25N01GV with page size 2 KiB, total 128 MiB + +Due to the page size discrepancy, it's impossible to attach +ubi volumes on the device. + +Signed-off-by: Christian Lamparter +--- + drivers/mtd/nand/nand_ids.c | 4 ++++ + include/linux/mtd/nand.h | 1 + + 2 files changed, 5 insertions(+) + +--- a/drivers/mtd/nand/nand_ids.c ++++ b/drivers/mtd/nand/nand_ids.c +@@ -54,6 +54,10 @@ struct nand_flash_dev nand_flash_ids[] = + { .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} }, + SZ_8K, SZ_8K, SZ_2M, NAND_NEED_SCRAMBLING, 6, 640, + NAND_ECC_INFO(40, SZ_1K), 4 }, ++ {"W25N01GV 1G 3.3V 8-bit", ++ { .id = {0xef, 0xaa} }, ++ SZ_2K, SZ_128, SZ_128K, NAND_NO_SUBPAGE_WRITE, ++ 2, 64, NAND_ECC_INFO(1, SZ_512) }, + + LEGACY_ID_NAND("NAND 4MiB 5V 8-bit", 0x6B, 4, SZ_8K, SP_OPTIONS), + LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS), diff --git a/target/linux/ipq40xx/patches-4.14/305-qcom-ipq4019-use-v2-of-the-kpss-bringup-mechanism.patch b/target/linux/ipq40xx/patches-4.14/305-qcom-ipq4019-use-v2-of-the-kpss-bringup-mechanism.patch new file mode 100644 index 000000000..1d08b9de7 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/305-qcom-ipq4019-use-v2-of-the-kpss-bringup-mechanism.patch @@ -0,0 +1,109 @@ +From 6a6c067b7ce2b3de4efbafddc134afbea3ddc1a3 Mon Sep 17 00:00:00 2001 +From: Matthew McClintock +Date: Fri, 8 Apr 2016 15:26:10 -0500 +Subject: [PATCH] qcom: ipq4019: use v2 of the kpss bringup mechanism + +v1 was the incorrect choice here and sometimes the board +would not come up properly. + +Signed-off-by: Matthew McClintock +Signed-off-by: Christian Lamparter +--- +Changes: + - moved L2-Cache to be a subnode of cpu0 +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 32 ++++++++++++++++++++++++-------- + 1 file changed, 24 insertions(+), 8 deletions(-) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -36,19 +36,27 @@ + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; +- enable-method = "qcom,kpss-acc-v1"; ++ enable-method = "qcom,kpss-acc-v2"; ++ next-level-cache = <&L2>; + qcom,acc = <&acc0>; + qcom,saw = <&saw0>; + reg = <0x0>; + clocks = <&gcc GCC_APPS_CLK_SRC>; + clock-frequency = <0>; + operating-points-v2 = <&cpu0_opp_table>; ++ ++ L2: l2-cache { ++ compatible = "qcom,arch-cache"; ++ cache-level = <2>; ++ qcom,saw = <&saw_l2>; ++ }; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; +- enable-method = "qcom,kpss-acc-v1"; ++ enable-method = "qcom,kpss-acc-v2"; ++ next-level-cache = <&L2>; + qcom,acc = <&acc1>; + qcom,saw = <&saw1>; + reg = <0x1>; +@@ -60,7 +68,8 @@ + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; +- enable-method = "qcom,kpss-acc-v1"; ++ enable-method = "qcom,kpss-acc-v2"; ++ next-level-cache = <&L2>; + qcom,acc = <&acc2>; + qcom,saw = <&saw2>; + reg = <0x2>; +@@ -72,7 +81,8 @@ + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; +- enable-method = "qcom,kpss-acc-v1"; ++ enable-method = "qcom,kpss-acc-v2"; ++ next-level-cache = <&L2>; + qcom,acc = <&acc3>; + qcom,saw = <&saw3>; + reg = <0x3>; +@@ -264,22 +274,22 @@ + }; + + acc0: clock-controller@b088000 { +- compatible = "qcom,kpss-acc-v1"; ++ compatible = "qcom,kpss-acc-v2"; + reg = <0x0b088000 0x1000>, <0xb008000 0x1000>; + }; + + acc1: clock-controller@b098000 { +- compatible = "qcom,kpss-acc-v1"; ++ compatible = "qcom,kpss-acc-v2"; + reg = <0x0b098000 0x1000>, <0xb008000 0x1000>; + }; + + acc2: clock-controller@b0a8000 { +- compatible = "qcom,kpss-acc-v1"; ++ compatible = "qcom,kpss-acc-v2"; + reg = <0x0b0a8000 0x1000>, <0xb008000 0x1000>; + }; + + acc3: clock-controller@b0b8000 { +- compatible = "qcom,kpss-acc-v1"; ++ compatible = "qcom,kpss-acc-v2"; + reg = <0x0b0b8000 0x1000>, <0xb008000 0x1000>; + }; + +@@ -307,6 +317,12 @@ + regulator; + }; + ++ saw_l2: regulator@b012000 { ++ compatible = "qcom,saw2"; ++ reg = <0xb012000 0x1000>; ++ regulator; ++ }; ++ + serial@78af000 { + compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm"; + reg = <0x78af000 0x200>; diff --git a/target/linux/ipq40xx/patches-4.14/306-qcom-ipq4019-add-USB-nodes-to-ipq4019-SoC-device-tre.patch b/target/linux/ipq40xx/patches-4.14/306-qcom-ipq4019-add-USB-nodes-to-ipq4019-SoC-device-tre.patch new file mode 100644 index 000000000..cd0f14eaf --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/306-qcom-ipq4019-add-USB-nodes-to-ipq4019-SoC-device-tre.patch @@ -0,0 +1,130 @@ +From ea5f4d6f4716f3a0bb4fc3614b7a0e8c0df1cb81 Mon Sep 17 00:00:00 2001 +From: Matthew McClintock +Date: Thu, 17 Mar 2016 16:22:28 -0500 +Subject: [PATCH] qcom: ipq4019: add USB nodes to ipq4019 SoC device tree + +This adds the SoC nodes to the ipq4019 device tree and +enable it for the DK01.1 board. + +Signed-off-by: Matthew McClintock +Signed-off-by: Christian Lamparter +--- +Changes: + - replaced space with tab + - added sleep and mock_utmi clocks + - added registers for usb2 and usb3 parent node + - changed compatible to qca,ipa4019-dwc3 + - updated usb2 and usb3 names + (included the reg - in case they become necessary later) +--- + arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi | 20 ++++++++ + arch/arm/boot/dts/qcom-ipq4019.dtsi | 71 +++++++++++++++++++++++++++ + 2 files changed, 91 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi +@@ -101,5 +101,25 @@ + wifi@a800000 { + status = "ok"; + }; ++ ++ usb3_ss_phy: ssphy@9a000 { ++ status = "ok"; ++ }; ++ ++ usb3_hs_phy: hsphy@a6000 { ++ status = "ok"; ++ }; ++ ++ usb3: usb3@8af8800 { ++ status = "ok"; ++ }; ++ ++ usb2_hs_phy: hsphy@a8000 { ++ status = "ok"; ++ }; ++ ++ usb2: usb2@60f8800 { ++ status = "ok"; ++ }; + }; + }; +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -538,5 +538,76 @@ + "legacy"; + status = "disabled"; + }; ++ ++ usb3_ss_phy: ssphy@9a000 { ++ compatible = "qca,uni-ssphy"; ++ reg = <0x9a000 0x800>; ++ reg-names = "phy_base"; ++ resets = <&gcc USB3_UNIPHY_PHY_ARES>; ++ reset-names = "por_rst"; ++ status = "disabled"; ++ }; ++ ++ usb3_hs_phy: hsphy@a6000 { ++ compatible = "qca,baldur-usb3-hsphy"; ++ reg = <0xa6000 0x40>; ++ reg-names = "phy_base"; ++ resets = <&gcc USB3_HSPHY_POR_ARES>, <&gcc USB3_HSPHY_S_ARES>; ++ reset-names = "por_rst", "srif_rst"; ++ status = "disabled"; ++ }; ++ ++ usb3@8af8800 { ++ compatible = "qca,ipq4019-dwc3"; ++ reg = <0x8af8800 0x100>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ clocks = <&gcc GCC_USB3_MASTER_CLK>, ++ <&gcc GCC_USB3_SLEEP_CLK>, ++ <&gcc GCC_USB3_MOCK_UTMI_CLK>; ++ clock-names = "master", "sleep", "mock_utmi"; ++ ranges; ++ status = "disabled"; ++ ++ dwc3@8a00000 { ++ compatible = "snps,dwc3"; ++ reg = <0x8a00000 0xf8000>; ++ interrupts = <0 132 0>; ++ usb-phy = <&usb3_hs_phy>, <&usb3_ss_phy>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ dr_mode = "host"; ++ }; ++ }; ++ ++ usb2_hs_phy: hsphy@a8000 { ++ compatible = "qca,baldur-usb2-hsphy"; ++ reg = <0xa8000 0x40>; ++ reg-names = "phy_base"; ++ resets = <&gcc USB2_HSPHY_POR_ARES>, <&gcc USB2_HSPHY_S_ARES>; ++ reset-names = "por_rst", "srif_rst"; ++ status = "disabled"; ++ }; ++ ++ usb2@60f8800 { ++ compatible = "qca,ipq4019-dwc3"; ++ reg = <0x60f8800 0x100>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ clocks = <&gcc GCC_USB2_MASTER_CLK>, ++ <&gcc GCC_USB2_SLEEP_CLK>, ++ <&gcc GCC_USB2_MOCK_UTMI_CLK>; ++ clock-names = "master", "sleep", "mock_utmi"; ++ ranges; ++ status = "disabled"; ++ ++ dwc3@6000000 { ++ compatible = "snps,dwc3"; ++ reg = <0x6000000 0xf8000>; ++ interrupts = <0 136 0>; ++ usb-phy = <&usb2_hs_phy>; ++ phy-names = "usb2-phy"; ++ dr_mode = "host"; ++ }; ++ }; + }; + }; diff --git a/target/linux/ipq40xx/patches-4.14/307-ARM-qcom-Add-IPQ4019-SoC-support.patch b/target/linux/ipq40xx/patches-4.14/307-ARM-qcom-Add-IPQ4019-SoC-support.patch new file mode 100644 index 000000000..1dc1c97c7 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/307-ARM-qcom-Add-IPQ4019-SoC-support.patch @@ -0,0 +1,35 @@ +From e7748d641ae37081e2034869491f1629461ae13c Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sat, 19 Nov 2016 00:58:18 +0100 +Subject: [PATCH] ARM: qcom: Add IPQ4019 SoC support + +Add support for the Qualcomm Atheros IPQ4019 SoC. + +Signed-off-by: Christian Lamparter +--- + arch/arm/Makefile | 1 + + arch/arm/mach-qcom/Kconfig | 5 +++++ + 2 files changed, 6 insertions(+) + +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -149,6 +149,7 @@ textofs-$(CONFIG_SA1111) := 0x00208000 + endif + textofs-$(CONFIG_ARCH_MSM8X60) := 0x00208000 + textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000 ++textofs-$(CONFIG_ARCH_IPQ40XX) := 0x00208000 + textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000 + + # Machine directory name. This list is sorted alphanumerically +--- a/arch/arm/mach-qcom/Kconfig ++++ b/arch/arm/mach-qcom/Kconfig +@@ -27,4 +27,9 @@ config ARCH_MDM9615 + bool "Enable support for MDM9615" + select CLKSRC_QCOM + ++config ARCH_IPQ40XX ++ bool "Enable support for IPQ40XX" ++ select CLKSRC_QCOM ++ select HAVE_ARM_ARCH_TIMER ++ + endif diff --git a/target/linux/ipq40xx/patches-4.14/310-msm-adhoc-bus-support.patch b/target/linux/ipq40xx/patches-4.14/310-msm-adhoc-bus-support.patch new file mode 100644 index 000000000..cd9fd895c --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/310-msm-adhoc-bus-support.patch @@ -0,0 +1,11026 @@ +From: Christian Lamparter +Subject: BUS: add MSM_BUS +--- a/drivers/bus/Makefile ++++ b/drivers/bus/Makefile +@@ -11,6 +11,7 @@ obj-$(CONFIG_BRCMSTB_GISB_ARB) += brcmst + obj-$(CONFIG_IMX_WEIM) += imx-weim.o + obj-$(CONFIG_MIPS_CDMM) += mips_cdmm.o + obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o ++obj-$(CONFIG_BUS_TOPOLOGY_ADHOC)+= msm_bus/ + + # Interconnect bus driver for OMAP SoCs. + obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o +--- a/drivers/bus/Kconfig ++++ b/drivers/bus/Kconfig +@@ -93,6 +93,8 @@ config MVEBU_MBUS + Driver needed for the MBus configuration on Marvell EBU SoCs + (Kirkwood, Dove, Orion5x, MV78XX0 and Armada 370/XP). + ++source "drivers/bus/msm_bus/Kconfig" ++ + config OMAP_INTERCONNECT + tristate "OMAP INTERCONNECT DRIVER" + depends on ARCH_OMAP2PLUS +--- /dev/null ++++ b/include/dt-bindings/msm/msm-bus-ids.h +@@ -0,0 +1,869 @@ ++/* Copyright (c) 2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __MSM_BUS_IDS_H ++#define __MSM_BUS_IDS_H ++ ++/* Topology related enums */ ++#define MSM_BUS_FAB_DEFAULT 0 ++#define MSM_BUS_FAB_APPSS 0 ++#define MSM_BUS_FAB_SYSTEM 1024 ++#define MSM_BUS_FAB_MMSS 2048 ++#define MSM_BUS_FAB_SYSTEM_FPB 3072 ++#define MSM_BUS_FAB_CPSS_FPB 4096 ++ ++#define MSM_BUS_FAB_BIMC 0 ++#define MSM_BUS_FAB_SYS_NOC 1024 ++#define MSM_BUS_FAB_MMSS_NOC 2048 ++#define MSM_BUS_FAB_OCMEM_NOC 3072 ++#define MSM_BUS_FAB_PERIPH_NOC 4096 ++#define MSM_BUS_FAB_CONFIG_NOC 5120 ++#define MSM_BUS_FAB_OCMEM_VNOC 6144 ++#define MSM_BUS_FAB_MMSS_AHB 2049 ++#define MSM_BUS_FAB_A0_NOC 6145 ++#define MSM_BUS_FAB_A1_NOC 6146 ++#define MSM_BUS_FAB_A2_NOC 6147 ++ ++#define MSM_BUS_MASTER_FIRST 1 ++#define MSM_BUS_MASTER_AMPSS_M0 1 ++#define MSM_BUS_MASTER_AMPSS_M1 2 ++#define MSM_BUS_APPSS_MASTER_FAB_MMSS 3 ++#define MSM_BUS_APPSS_MASTER_FAB_SYSTEM 4 ++#define MSM_BUS_SYSTEM_MASTER_FAB_APPSS 5 ++#define MSM_BUS_MASTER_SPS 6 ++#define MSM_BUS_MASTER_ADM_PORT0 7 ++#define MSM_BUS_MASTER_ADM_PORT1 8 ++#define MSM_BUS_SYSTEM_MASTER_ADM1_PORT0 9 ++#define MSM_BUS_MASTER_ADM1_PORT1 10 ++#define MSM_BUS_MASTER_LPASS_PROC 11 ++#define MSM_BUS_MASTER_MSS_PROCI 12 ++#define MSM_BUS_MASTER_MSS_PROCD 13 ++#define MSM_BUS_MASTER_MSS_MDM_PORT0 14 ++#define MSM_BUS_MASTER_LPASS 15 ++#define MSM_BUS_SYSTEM_MASTER_CPSS_FPB 16 ++#define MSM_BUS_SYSTEM_MASTER_SYSTEM_FPB 17 ++#define MSM_BUS_SYSTEM_MASTER_MMSS_FPB 18 ++#define MSM_BUS_MASTER_ADM1_CI 19 ++#define MSM_BUS_MASTER_ADM0_CI 20 ++#define MSM_BUS_MASTER_MSS_MDM_PORT1 21 ++#define MSM_BUS_MASTER_MDP_PORT0 22 ++#define MSM_BUS_MASTER_MDP_PORT1 23 ++#define MSM_BUS_MMSS_MASTER_ADM1_PORT0 24 ++#define MSM_BUS_MASTER_ROTATOR 25 ++#define MSM_BUS_MASTER_GRAPHICS_3D 26 ++#define MSM_BUS_MASTER_JPEG_DEC 27 ++#define MSM_BUS_MASTER_GRAPHICS_2D_CORE0 28 ++#define MSM_BUS_MASTER_VFE 29 ++#define MSM_BUS_MASTER_VPE 30 ++#define MSM_BUS_MASTER_JPEG_ENC 31 ++#define MSM_BUS_MASTER_GRAPHICS_2D_CORE1 32 ++#define MSM_BUS_MMSS_MASTER_APPS_FAB 33 ++#define MSM_BUS_MASTER_HD_CODEC_PORT0 34 ++#define MSM_BUS_MASTER_HD_CODEC_PORT1 35 ++#define MSM_BUS_MASTER_SPDM 36 ++#define MSM_BUS_MASTER_RPM 37 ++#define MSM_BUS_MASTER_MSS 38 ++#define MSM_BUS_MASTER_RIVA 39 ++#define MSM_BUS_MASTER_SNOC_VMEM 40 ++#define MSM_BUS_MASTER_MSS_SW_PROC 41 ++#define MSM_BUS_MASTER_MSS_FW_PROC 42 ++#define MSM_BUS_MASTER_HMSS 43 ++#define MSM_BUS_MASTER_GSS_NAV 44 ++#define MSM_BUS_MASTER_PCIE 45 ++#define MSM_BUS_MASTER_SATA 46 ++#define MSM_BUS_MASTER_CRYPTO 47 ++#define MSM_BUS_MASTER_VIDEO_CAP 48 ++#define MSM_BUS_MASTER_GRAPHICS_3D_PORT1 49 ++#define MSM_BUS_MASTER_VIDEO_ENC 50 ++#define MSM_BUS_MASTER_VIDEO_DEC 51 ++#define MSM_BUS_MASTER_LPASS_AHB 52 ++#define MSM_BUS_MASTER_QDSS_BAM 53 ++#define MSM_BUS_MASTER_SNOC_CFG 54 ++#define MSM_BUS_MASTER_CRYPTO_CORE0 55 ++#define MSM_BUS_MASTER_CRYPTO_CORE1 56 ++#define MSM_BUS_MASTER_MSS_NAV 57 ++#define MSM_BUS_MASTER_OCMEM_DMA 58 ++#define MSM_BUS_MASTER_WCSS 59 ++#define MSM_BUS_MASTER_QDSS_ETR 60 ++#define MSM_BUS_MASTER_USB3 61 ++#define MSM_BUS_MASTER_JPEG 62 ++#define MSM_BUS_MASTER_VIDEO_P0 63 ++#define MSM_BUS_MASTER_VIDEO_P1 64 ++#define MSM_BUS_MASTER_MSS_PROC 65 ++#define MSM_BUS_MASTER_JPEG_OCMEM 66 ++#define MSM_BUS_MASTER_MDP_OCMEM 67 ++#define MSM_BUS_MASTER_VIDEO_P0_OCMEM 68 ++#define MSM_BUS_MASTER_VIDEO_P1_OCMEM 69 ++#define MSM_BUS_MASTER_VFE_OCMEM 70 ++#define MSM_BUS_MASTER_CNOC_ONOC_CFG 71 ++#define MSM_BUS_MASTER_RPM_INST 72 ++#define MSM_BUS_MASTER_RPM_DATA 73 ++#define MSM_BUS_MASTER_RPM_SYS 74 ++#define MSM_BUS_MASTER_DEHR 75 ++#define MSM_BUS_MASTER_QDSS_DAP 76 ++#define MSM_BUS_MASTER_TIC 77 ++#define MSM_BUS_MASTER_SDCC_1 78 ++#define MSM_BUS_MASTER_SDCC_3 79 ++#define MSM_BUS_MASTER_SDCC_4 80 ++#define MSM_BUS_MASTER_SDCC_2 81 ++#define MSM_BUS_MASTER_TSIF 82 ++#define MSM_BUS_MASTER_BAM_DMA 83 ++#define MSM_BUS_MASTER_BLSP_2 84 ++#define MSM_BUS_MASTER_USB_HSIC 85 ++#define MSM_BUS_MASTER_BLSP_1 86 ++#define MSM_BUS_MASTER_USB_HS 87 ++#define MSM_BUS_MASTER_PNOC_CFG 88 ++#define MSM_BUS_MASTER_V_OCMEM_GFX3D 89 ++#define MSM_BUS_MASTER_IPA 90 ++#define MSM_BUS_MASTER_QPIC 91 ++#define MSM_BUS_MASTER_MDPE 92 ++#define MSM_BUS_MASTER_USB_HS2 93 ++#define MSM_BUS_MASTER_VPU 94 ++#define MSM_BUS_MASTER_UFS 95 ++#define MSM_BUS_MASTER_BCAST 96 ++#define MSM_BUS_MASTER_CRYPTO_CORE2 97 ++#define MSM_BUS_MASTER_EMAC 98 ++#define MSM_BUS_MASTER_VPU_1 99 ++#define MSM_BUS_MASTER_PCIE_1 100 ++#define MSM_BUS_MASTER_USB3_1 101 ++#define MSM_BUS_MASTER_CNOC_MNOC_MMSS_CFG 102 ++#define MSM_BUS_MASTER_CNOC_MNOC_CFG 103 ++#define MSM_BUS_MASTER_TCU_0 104 ++#define MSM_BUS_MASTER_TCU_1 105 ++#define MSM_BUS_MASTER_CPP 106 ++#define MSM_BUS_MASTER_AUDIO 107 ++#define MSM_BUS_MASTER_PCIE_2 108 ++#define MSM_BUS_MASTER_BLSP_BAM 109 ++#define MSM_BUS_MASTER_USB2_BAM 110 ++#define MSM_BUS_MASTER_ADDS_DMA0 111 ++#define MSM_BUS_MASTER_ADDS_DMA1 112 ++#define MSM_BUS_MASTER_ADDS_DMA2 113 ++#define MSM_BUS_MASTER_ADDS_DMA3 114 ++#define MSM_BUS_MASTER_QPIC_BAM 115 ++#define MSM_BUS_MASTER_SDCC_BAM 116 ++#define MSM_BUS_MASTER_DDRC_SNOC 117 ++#define MSM_BUS_MASTER_WSS_0 118 ++#define MSM_BUS_MASTER_WSS_1 119 ++#define MSM_BUS_MASTER_ESS 120 ++#define MSM_BUS_MASTER_QDSS_BAMNDP 121 ++#define MSM_BUS_MASTER_QDSS_SNOC_CFG 122 ++#define MSM_BUS_MASTER_LAST 130 ++ ++#define MSM_BUS_SYSTEM_FPB_MASTER_SYSTEM MSM_BUS_SYSTEM_MASTER_SYSTEM_FPB ++#define MSM_BUS_CPSS_FPB_MASTER_SYSTEM MSM_BUS_SYSTEM_MASTER_CPSS_FPB ++ ++#define MSM_BUS_SNOC_MM_INT_0 10000 ++#define MSM_BUS_SNOC_MM_INT_1 10001 ++#define MSM_BUS_SNOC_MM_INT_2 10002 ++#define MSM_BUS_SNOC_MM_INT_BIMC 10003 ++#define MSM_BUS_SNOC_INT_0 10004 ++#define MSM_BUS_SNOC_INT_1 10005 ++#define MSM_BUS_SNOC_INT_BIMC 10006 ++#define MSM_BUS_SNOC_BIMC_0_MAS 10007 ++#define MSM_BUS_SNOC_BIMC_1_MAS 10008 ++#define MSM_BUS_SNOC_QDSS_INT 10009 ++#define MSM_BUS_PNOC_SNOC_MAS 10010 ++#define MSM_BUS_PNOC_SNOC_SLV 10011 ++#define MSM_BUS_PNOC_INT_0 10012 ++#define MSM_BUS_PNOC_INT_1 10013 ++#define MSM_BUS_PNOC_M_0 10014 ++#define MSM_BUS_PNOC_M_1 10015 ++#define MSM_BUS_BIMC_SNOC_MAS 10016 ++#define MSM_BUS_BIMC_SNOC_SLV 10017 ++#define MSM_BUS_PNOC_SLV_0 10018 ++#define MSM_BUS_PNOC_SLV_1 10019 ++#define MSM_BUS_PNOC_SLV_2 10020 ++#define MSM_BUS_PNOC_SLV_3 10021 ++#define MSM_BUS_PNOC_SLV_4 10022 ++#define MSM_BUS_PNOC_SLV_8 10023 ++#define MSM_BUS_PNOC_SLV_9 10024 ++#define MSM_BUS_SNOC_BIMC_0_SLV 10025 ++#define MSM_BUS_SNOC_BIMC_1_SLV 10026 ++#define MSM_BUS_MNOC_BIMC_MAS 10027 ++#define MSM_BUS_MNOC_BIMC_SLV 10028 ++#define MSM_BUS_BIMC_MNOC_MAS 10029 ++#define MSM_BUS_BIMC_MNOC_SLV 10030 ++#define MSM_BUS_SNOC_BIMC_MAS 10031 ++#define MSM_BUS_SNOC_BIMC_SLV 10032 ++#define MSM_BUS_CNOC_SNOC_MAS 10033 ++#define MSM_BUS_CNOC_SNOC_SLV 10034 ++#define MSM_BUS_SNOC_CNOC_MAS 10035 ++#define MSM_BUS_SNOC_CNOC_SLV 10036 ++#define MSM_BUS_OVNOC_SNOC_MAS 10037 ++#define MSM_BUS_OVNOC_SNOC_SLV 10038 ++#define MSM_BUS_SNOC_OVNOC_MAS 10039 ++#define MSM_BUS_SNOC_OVNOC_SLV 10040 ++#define MSM_BUS_SNOC_PNOC_MAS 10041 ++#define MSM_BUS_SNOC_PNOC_SLV 10042 ++#define MSM_BUS_BIMC_INT_APPS_EBI 10043 ++#define MSM_BUS_BIMC_INT_APPS_SNOC 10044 ++#define MSM_BUS_SNOC_BIMC_2_MAS 10045 ++#define MSM_BUS_SNOC_BIMC_2_SLV 10046 ++#define MSM_BUS_PNOC_SLV_5 10047 ++#define MSM_BUS_PNOC_SLV_6 10048 ++#define MSM_BUS_PNOC_INT_2 10049 ++#define MSM_BUS_PNOC_INT_3 10050 ++#define MSM_BUS_PNOC_INT_4 10051 ++#define MSM_BUS_PNOC_INT_5 10052 ++#define MSM_BUS_PNOC_INT_6 10053 ++#define MSM_BUS_PNOC_INT_7 10054 ++#define MSM_BUS_BIMC_SNOC_1_MAS 10055 ++#define MSM_BUS_BIMC_SNOC_1_SLV 10056 ++#define MSM_BUS_PNOC_A1NOC_MAS 10057 ++#define MSM_BUS_PNOC_A1NOC_SLV 10058 ++#define MSM_BUS_CNOC_A1NOC_MAS 10059 ++#define MSM_BUS_A0NOC_SNOC_MAS 10060 ++#define MSM_BUS_A0NOC_SNOC_SLV 10061 ++#define MSM_BUS_A1NOC_SNOC_SLV 10062 ++#define MSM_BUS_A1NOC_SNOC_MAS 10063 ++#define MSM_BUS_A2NOC_SNOC_MAS 10064 ++#define MSM_BUS_A2NOC_SNOC_SLV 10065 ++#define MSM_BUS_PNOC_SLV_7 10066 ++#define MSM_BUS_INT_LAST 10067 ++ ++#define MSM_BUS_SLAVE_FIRST 512 ++#define MSM_BUS_SLAVE_EBI_CH0 512 ++#define MSM_BUS_SLAVE_EBI_CH1 513 ++#define MSM_BUS_SLAVE_AMPSS_L2 514 ++#define MSM_BUS_APPSS_SLAVE_FAB_MMSS 515 ++#define MSM_BUS_APPSS_SLAVE_FAB_SYSTEM 516 ++#define MSM_BUS_SYSTEM_SLAVE_FAB_APPS 517 ++#define MSM_BUS_SLAVE_SPS 518 ++#define MSM_BUS_SLAVE_SYSTEM_IMEM 519 ++#define MSM_BUS_SLAVE_AMPSS 520 ++#define MSM_BUS_SLAVE_MSS 521 ++#define MSM_BUS_SLAVE_LPASS 522 ++#define MSM_BUS_SYSTEM_SLAVE_CPSS_FPB 523 ++#define MSM_BUS_SYSTEM_SLAVE_SYSTEM_FPB 524 ++#define MSM_BUS_SYSTEM_SLAVE_MMSS_FPB 525 ++#define MSM_BUS_SLAVE_CORESIGHT 526 ++#define MSM_BUS_SLAVE_RIVA 527 ++#define MSM_BUS_SLAVE_SMI 528 ++#define MSM_BUS_MMSS_SLAVE_FAB_APPS 529 ++#define MSM_BUS_MMSS_SLAVE_FAB_APPS_1 530 ++#define MSM_BUS_SLAVE_MM_IMEM 531 ++#define MSM_BUS_SLAVE_CRYPTO 532 ++#define MSM_BUS_SLAVE_SPDM 533 ++#define MSM_BUS_SLAVE_RPM 534 ++#define MSM_BUS_SLAVE_RPM_MSG_RAM 535 ++#define MSM_BUS_SLAVE_MPM 536 ++#define MSM_BUS_SLAVE_PMIC1_SSBI1_A 537 ++#define MSM_BUS_SLAVE_PMIC1_SSBI1_B 538 ++#define MSM_BUS_SLAVE_PMIC1_SSBI1_C 539 ++#define MSM_BUS_SLAVE_PMIC2_SSBI2_A 540 ++#define MSM_BUS_SLAVE_PMIC2_SSBI2_B 541 ++#define MSM_BUS_SLAVE_GSBI1_UART 542 ++#define MSM_BUS_SLAVE_GSBI2_UART 543 ++#define MSM_BUS_SLAVE_GSBI3_UART 544 ++#define MSM_BUS_SLAVE_GSBI4_UART 545 ++#define MSM_BUS_SLAVE_GSBI5_UART 546 ++#define MSM_BUS_SLAVE_GSBI6_UART 547 ++#define MSM_BUS_SLAVE_GSBI7_UART 548 ++#define MSM_BUS_SLAVE_GSBI8_UART 549 ++#define MSM_BUS_SLAVE_GSBI9_UART 550 ++#define MSM_BUS_SLAVE_GSBI10_UART 551 ++#define MSM_BUS_SLAVE_GSBI11_UART 552 ++#define MSM_BUS_SLAVE_GSBI12_UART 553 ++#define MSM_BUS_SLAVE_GSBI1_QUP 554 ++#define MSM_BUS_SLAVE_GSBI2_QUP 555 ++#define MSM_BUS_SLAVE_GSBI3_QUP 556 ++#define MSM_BUS_SLAVE_GSBI4_QUP 557 ++#define MSM_BUS_SLAVE_GSBI5_QUP 558 ++#define MSM_BUS_SLAVE_GSBI6_QUP 559 ++#define MSM_BUS_SLAVE_GSBI7_QUP 560 ++#define MSM_BUS_SLAVE_GSBI8_QUP 561 ++#define MSM_BUS_SLAVE_GSBI9_QUP 562 ++#define MSM_BUS_SLAVE_GSBI10_QUP 563 ++#define MSM_BUS_SLAVE_GSBI11_QUP 564 ++#define MSM_BUS_SLAVE_GSBI12_QUP 565 ++#define MSM_BUS_SLAVE_EBI2_NAND 566 ++#define MSM_BUS_SLAVE_EBI2_CS0 567 ++#define MSM_BUS_SLAVE_EBI2_CS1 568 ++#define MSM_BUS_SLAVE_EBI2_CS2 569 ++#define MSM_BUS_SLAVE_EBI2_CS3 570 ++#define MSM_BUS_SLAVE_EBI2_CS4 571 ++#define MSM_BUS_SLAVE_EBI2_CS5 572 ++#define MSM_BUS_SLAVE_USB_FS1 573 ++#define MSM_BUS_SLAVE_USB_FS2 574 ++#define MSM_BUS_SLAVE_TSIF 575 ++#define MSM_BUS_SLAVE_MSM_TSSC 576 ++#define MSM_BUS_SLAVE_MSM_PDM 577 ++#define MSM_BUS_SLAVE_MSM_DIMEM 578 ++#define MSM_BUS_SLAVE_MSM_TCSR 579 ++#define MSM_BUS_SLAVE_MSM_PRNG 580 ++#define MSM_BUS_SLAVE_GSS 581 ++#define MSM_BUS_SLAVE_SATA 582 ++#define MSM_BUS_SLAVE_USB3 583 ++#define MSM_BUS_SLAVE_WCSS 584 ++#define MSM_BUS_SLAVE_OCIMEM 585 ++#define MSM_BUS_SLAVE_SNOC_OCMEM 586 ++#define MSM_BUS_SLAVE_SERVICE_SNOC 587 ++#define MSM_BUS_SLAVE_QDSS_STM 588 ++#define MSM_BUS_SLAVE_CAMERA_CFG 589 ++#define MSM_BUS_SLAVE_DISPLAY_CFG 590 ++#define MSM_BUS_SLAVE_OCMEM_CFG 591 ++#define MSM_BUS_SLAVE_CPR_CFG 592 ++#define MSM_BUS_SLAVE_CPR_XPU_CFG 593 ++#define MSM_BUS_SLAVE_MISC_CFG 594 ++#define MSM_BUS_SLAVE_MISC_XPU_CFG 595 ++#define MSM_BUS_SLAVE_VENUS_CFG 596 ++#define MSM_BUS_SLAVE_MISC_VENUS_CFG 597 ++#define MSM_BUS_SLAVE_GRAPHICS_3D_CFG 598 ++#define MSM_BUS_SLAVE_MMSS_CLK_CFG 599 ++#define MSM_BUS_SLAVE_MMSS_CLK_XPU_CFG 600 ++#define MSM_BUS_SLAVE_MNOC_MPU_CFG 601 ++#define MSM_BUS_SLAVE_ONOC_MPU_CFG 602 ++#define MSM_BUS_SLAVE_SERVICE_MNOC 603 ++#define MSM_BUS_SLAVE_OCMEM 604 ++#define MSM_BUS_SLAVE_SERVICE_ONOC 605 ++#define MSM_BUS_SLAVE_SDCC_1 606 ++#define MSM_BUS_SLAVE_SDCC_3 607 ++#define MSM_BUS_SLAVE_SDCC_2 608 ++#define MSM_BUS_SLAVE_SDCC_4 609 ++#define MSM_BUS_SLAVE_BAM_DMA 610 ++#define MSM_BUS_SLAVE_BLSP_2 611 ++#define MSM_BUS_SLAVE_USB_HSIC 612 ++#define MSM_BUS_SLAVE_BLSP_1 613 ++#define MSM_BUS_SLAVE_USB_HS 614 ++#define MSM_BUS_SLAVE_PDM 615 ++#define MSM_BUS_SLAVE_PERIPH_APU_CFG 616 ++#define MSM_BUS_SLAVE_PNOC_MPU_CFG 617 ++#define MSM_BUS_SLAVE_PRNG 618 ++#define MSM_BUS_SLAVE_SERVICE_PNOC 619 ++#define MSM_BUS_SLAVE_CLK_CTL 620 ++#define MSM_BUS_SLAVE_CNOC_MSS 621 ++#define MSM_BUS_SLAVE_SECURITY 622 ++#define MSM_BUS_SLAVE_TCSR 623 ++#define MSM_BUS_SLAVE_TLMM 624 ++#define MSM_BUS_SLAVE_CRYPTO_0_CFG 625 ++#define MSM_BUS_SLAVE_CRYPTO_1_CFG 626 ++#define MSM_BUS_SLAVE_IMEM_CFG 627 ++#define MSM_BUS_SLAVE_MESSAGE_RAM 628 ++#define MSM_BUS_SLAVE_BIMC_CFG 629 ++#define MSM_BUS_SLAVE_BOOT_ROM 630 ++#define MSM_BUS_SLAVE_CNOC_MNOC_MMSS_CFG 631 ++#define MSM_BUS_SLAVE_PMIC_ARB 632 ++#define MSM_BUS_SLAVE_SPDM_WRAPPER 633 ++#define MSM_BUS_SLAVE_DEHR_CFG 634 ++#define MSM_BUS_SLAVE_QDSS_CFG 635 ++#define MSM_BUS_SLAVE_RBCPR_CFG 636 ++#define MSM_BUS_SLAVE_RBCPR_QDSS_APU_CFG 637 ++#define MSM_BUS_SLAVE_SNOC_MPU_CFG 638 ++#define MSM_BUS_SLAVE_CNOC_ONOC_CFG 639 ++#define MSM_BUS_SLAVE_CNOC_MNOC_CFG 640 ++#define MSM_BUS_SLAVE_PNOC_CFG 641 ++#define MSM_BUS_SLAVE_SNOC_CFG 642 ++#define MSM_BUS_SLAVE_EBI1_DLL_CFG 643 ++#define MSM_BUS_SLAVE_PHY_APU_CFG 644 ++#define MSM_BUS_SLAVE_EBI1_PHY_CFG 645 ++#define MSM_BUS_SLAVE_SERVICE_CNOC 646 ++#define MSM_BUS_SLAVE_IPS_CFG 647 ++#define MSM_BUS_SLAVE_QPIC 648 ++#define MSM_BUS_SLAVE_DSI_CFG 649 ++#define MSM_BUS_SLAVE_UFS_CFG 650 ++#define MSM_BUS_SLAVE_RBCPR_CX_CFG 651 ++#define MSM_BUS_SLAVE_RBCPR_MX_CFG 652 ++#define MSM_BUS_SLAVE_PCIE_CFG 653 ++#define MSM_BUS_SLAVE_USB_PHYS_CFG 654 ++#define MSM_BUS_SLAVE_VIDEO_CAP_CFG 655 ++#define MSM_BUS_SLAVE_AVSYNC_CFG 656 ++#define MSM_BUS_SLAVE_CRYPTO_2_CFG 657 ++#define MSM_BUS_SLAVE_VPU_CFG 658 ++#define MSM_BUS_SLAVE_BCAST_CFG 659 ++#define MSM_BUS_SLAVE_KLM_CFG 660 ++#define MSM_BUS_SLAVE_GENI_IR_CFG 661 ++#define MSM_BUS_SLAVE_OCMEM_GFX 662 ++#define MSM_BUS_SLAVE_CATS_128 663 ++#define MSM_BUS_SLAVE_OCMEM_64 664 ++#define MSM_BUS_SLAVE_PCIE_0 665 ++#define MSM_BUS_SLAVE_PCIE_1 666 ++#define MSM_BUS_SLAVE_PCIE_0_CFG 667 ++#define MSM_BUS_SLAVE_PCIE_1_CFG 668 ++#define MSM_BUS_SLAVE_SRVC_MNOC 669 ++#define MSM_BUS_SLAVE_USB_HS2 670 ++#define MSM_BUS_SLAVE_AUDIO 671 ++#define MSM_BUS_SLAVE_TCU 672 ++#define MSM_BUS_SLAVE_APPSS 673 ++#define MSM_BUS_SLAVE_PCIE_PARF 674 ++#define MSM_BUS_SLAVE_USB3_PHY_CFG 675 ++#define MSM_BUS_SLAVE_IPA_CFG 676 ++#define MSM_BUS_SLAVE_A0NOC_SNOC 677 ++#define MSM_BUS_SLAVE_A1NOC_SNOC 678 ++#define MSM_BUS_SLAVE_A2NOC_SNOC 679 ++#define MSM_BUS_SLAVE_HMSS_L3 680 ++#define MSM_BUS_SLAVE_PIMEM_CFG 681 ++#define MSM_BUS_SLAVE_DCC_CFG 682 ++#define MSM_BUS_SLAVE_QDSS_RBCPR_APU_CFG 683 ++#define MSM_BUS_SLAVE_PCIE_2_CFG 684 ++#define MSM_BUS_SLAVE_PCIE20_AHB2PHY 685 ++#define MSM_BUS_SLAVE_A0NOC_CFG 686 ++#define MSM_BUS_SLAVE_A1NOC_CFG 687 ++#define MSM_BUS_SLAVE_A2NOC_CFG 688 ++#define MSM_BUS_SLAVE_A1NOC_MPU_CFG 689 ++#define MSM_BUS_SLAVE_A2NOC_MPU_CFG 690 ++#define MSM_BUS_SLAVE_A0NOC_SMMU_CFG 691 ++#define MSM_BUS_SLAVE_A1NOC_SMMU_CFG 692 ++#define MSM_BUS_SLAVE_A2NOC_SMMU_CFG 693 ++#define MSM_BUS_SLAVE_LPASS_SMMU_CFG 694 ++#define MSM_BUS_SLAVE_MMAGIC_CFG 695 ++#define MSM_BUS_SLAVE_VENUS_THROTTLE_CFG 696 ++#define MSM_BUS_SLAVE_SSC_CFG 697 ++#define MSM_BUS_SLAVE_DSA_CFG 698 ++#define MSM_BUS_SLAVE_DSA_MPU_CFG 699 ++#define MSM_BUS_SLAVE_DISPLAY_THROTTLE_CFG 700 ++#define MSM_BUS_SLAVE_SMMU_CPP_CFG 701 ++#define MSM_BUS_SLAVE_SMMU_JPEG_CFG 702 ++#define MSM_BUS_SLAVE_SMMU_MDP_CFG 703 ++#define MSM_BUS_SLAVE_SMMU_ROTATOR_CFG 704 ++#define MSM_BUS_SLAVE_SMMU_VENUS_CFG 705 ++#define MSM_BUS_SLAVE_SMMU_VFE_CFG 706 ++#define MSM_BUS_SLAVE_A0NOC_MPU_CFG 707 ++#define MSM_BUS_SLAVE_VMEM_CFG 708 ++#define MSM_BUS_SLAVE_CAMERA_THROTTLE_CFG 700 ++#define MSM_BUS_SLAVE_VMEM 709 ++#define MSM_BUS_SLAVE_AHB2PHY 710 ++#define MSM_BUS_SLAVE_PIMEM 711 ++#define MSM_BUS_SLAVE_SNOC_VMEM 712 ++#define MSM_BUS_SLAVE_PCIE_2 713 ++#define MSM_BUS_SLAVE_RBCPR_MX 714 ++#define MSM_BUS_SLAVE_RBCPR_CX 715 ++#define MSM_BUS_SLAVE_PRNG_APU_CFG 716 ++#define MSM_BUS_SLAVE_PERIPH_MPU_CFG 717 ++#define MSM_BUS_SLAVE_GCNT 718 ++#define MSM_BUS_SLAVE_ADSS_CFG 719 ++#define MSM_BUS_SLAVE_ADSS_VMIDMT_CFG 720 ++#define MSM_BUS_SLAVE_QHSS_APU_CFG 721 ++#define MSM_BUS_SLAVE_MDIO 722 ++#define MSM_BUS_SLAVE_FEPHY_CFG 723 ++#define MSM_BUS_SLAVE_SRIF 724 ++#define MSM_BUS_SLAVE_LAST 730 ++#define MSM_BUS_SLAVE_DDRC_CFG 731 ++#define MSM_BUS_SLAVE_DDRC_APU_CFG 732 ++#define MSM_BUS_SLAVE_MPU0_CFG 733 ++#define MSM_BUS_SLAVE_MPU1_CFG 734 ++#define MSM_BUS_SLAVE_MPU2_CFG 734 ++#define MSM_BUS_SLAVE_ESS_VMIDMT_CFG 735 ++#define MSM_BUS_SLAVE_ESS_APU_CFG 736 ++#define MSM_BUS_SLAVE_USB2_CFG 737 ++#define MSM_BUS_SLAVE_BLSP_CFG 738 ++#define MSM_BUS_SLAVE_QPIC_CFG 739 ++#define MSM_BUS_SLAVE_SDCC_CFG 740 ++#define MSM_BUS_SLAVE_WSS0_VMIDMT_CFG 741 ++#define MSM_BUS_SLAVE_WSS0_APU_CFG 742 ++#define MSM_BUS_SLAVE_WSS1_VMIDMT_CFG 743 ++#define MSM_BUS_SLAVE_WSS1_APU_CFG 744 ++#define MSM_BUS_SLAVE_SRVC_PCNOC 745 ++#define MSM_BUS_SLAVE_SNOC_DDRC 746 ++#define MSM_BUS_SLAVE_A7SS 747 ++#define MSM_BUS_SLAVE_WSS0_CFG 748 ++#define MSM_BUS_SLAVE_WSS1_CFG 749 ++#define MSM_BUS_SLAVE_PCIE 750 ++#define MSM_BUS_SLAVE_USB3_CFG 751 ++#define MSM_BUS_SLAVE_CRYPTO_CFG 752 ++#define MSM_BUS_SLAVE_ESS_CFG 753 ++#define MSM_BUS_SLAVE_SRVC_SNOC 754 ++ ++#define MSM_BUS_SYSTEM_FPB_SLAVE_SYSTEM MSM_BUS_SYSTEM_SLAVE_SYSTEM_FPB ++#define MSM_BUS_CPSS_FPB_SLAVE_SYSTEM MSM_BUS_SYSTEM_SLAVE_CPSS_FPB ++ ++/* ++ * ID's used in RPM messages ++ */ ++#define ICBID_MASTER_APPSS_PROC 0 ++#define ICBID_MASTER_MSS_PROC 1 ++#define ICBID_MASTER_MNOC_BIMC 2 ++#define ICBID_MASTER_SNOC_BIMC 3 ++#define ICBID_MASTER_SNOC_BIMC_0 ICBID_MASTER_SNOC_BIMC ++#define ICBID_MASTER_CNOC_MNOC_MMSS_CFG 4 ++#define ICBID_MASTER_CNOC_MNOC_CFG 5 ++#define ICBID_MASTER_GFX3D 6 ++#define ICBID_MASTER_JPEG 7 ++#define ICBID_MASTER_MDP 8 ++#define ICBID_MASTER_MDP0 ICBID_MASTER_MDP ++#define ICBID_MASTER_MDPS ICBID_MASTER_MDP ++#define ICBID_MASTER_VIDEO 9 ++#define ICBID_MASTER_VIDEO_P0 ICBID_MASTER_VIDEO ++#define ICBID_MASTER_VIDEO_P1 10 ++#define ICBID_MASTER_VFE 11 ++#define ICBID_MASTER_CNOC_ONOC_CFG 12 ++#define ICBID_MASTER_JPEG_OCMEM 13 ++#define ICBID_MASTER_MDP_OCMEM 14 ++#define ICBID_MASTER_VIDEO_P0_OCMEM 15 ++#define ICBID_MASTER_VIDEO_P1_OCMEM 16 ++#define ICBID_MASTER_VFE_OCMEM 17 ++#define ICBID_MASTER_LPASS_AHB 18 ++#define ICBID_MASTER_QDSS_BAM 19 ++#define ICBID_MASTER_SNOC_CFG 20 ++#define ICBID_MASTER_BIMC_SNOC 21 ++#define ICBID_MASTER_CNOC_SNOC 22 ++#define ICBID_MASTER_CRYPTO 23 ++#define ICBID_MASTER_CRYPTO_CORE0 ICBID_MASTER_CRYPTO ++#define ICBID_MASTER_CRYPTO_CORE1 24 ++#define ICBID_MASTER_LPASS_PROC 25 ++#define ICBID_MASTER_MSS 26 ++#define ICBID_MASTER_MSS_NAV 27 ++#define ICBID_MASTER_OCMEM_DMA 28 ++#define ICBID_MASTER_PNOC_SNOC 29 ++#define ICBID_MASTER_WCSS 30 ++#define ICBID_MASTER_QDSS_ETR 31 ++#define ICBID_MASTER_USB3 32 ++#define ICBID_MASTER_USB3_0 ICBID_MASTER_USB3 ++#define ICBID_MASTER_SDCC_1 33 ++#define ICBID_MASTER_SDCC_3 34 ++#define ICBID_MASTER_SDCC_2 35 ++#define ICBID_MASTER_SDCC_4 36 ++#define ICBID_MASTER_TSIF 37 ++#define ICBID_MASTER_BAM_DMA 38 ++#define ICBID_MASTER_BLSP_2 39 ++#define ICBID_MASTER_USB_HSIC 40 ++#define ICBID_MASTER_BLSP_1 41 ++#define ICBID_MASTER_USB_HS 42 ++#define ICBID_MASTER_USB_HS1 ICBID_MASTER_USB_HS ++#define ICBID_MASTER_PNOC_CFG 43 ++#define ICBID_MASTER_SNOC_PNOC 44 ++#define ICBID_MASTER_RPM_INST 45 ++#define ICBID_MASTER_RPM_DATA 46 ++#define ICBID_MASTER_RPM_SYS 47 ++#define ICBID_MASTER_DEHR 48 ++#define ICBID_MASTER_QDSS_DAP 49 ++#define ICBID_MASTER_SPDM 50 ++#define ICBID_MASTER_TIC 51 ++#define ICBID_MASTER_SNOC_CNOC 52 ++#define ICBID_MASTER_GFX3D_OCMEM 53 ++#define ICBID_MASTER_GFX3D_GMEM ICBID_MASTER_GFX3D_OCMEM ++#define ICBID_MASTER_OVIRT_SNOC 54 ++#define ICBID_MASTER_SNOC_OVIRT 55 ++#define ICBID_MASTER_SNOC_GVIRT ICBID_MASTER_SNOC_OVIRT ++#define ICBID_MASTER_ONOC_OVIRT 56 ++#define ICBID_MASTER_USB_HS2 57 ++#define ICBID_MASTER_QPIC 58 ++#define ICBID_MASTER_IPA 59 ++#define ICBID_MASTER_DSI 60 ++#define ICBID_MASTER_MDP1 61 ++#define ICBID_MASTER_MDPE ICBID_MASTER_MDP1 ++#define ICBID_MASTER_VPU_PROC 62 ++#define ICBID_MASTER_VPU 63 ++#define ICBID_MASTER_VPU0 ICBID_MASTER_VPU ++#define ICBID_MASTER_CRYPTO_CORE2 64 ++#define ICBID_MASTER_PCIE_0 65 ++#define ICBID_MASTER_PCIE_1 66 ++#define ICBID_MASTER_SATA 67 ++#define ICBID_MASTER_UFS 68 ++#define ICBID_MASTER_USB3_1 69 ++#define ICBID_MASTER_VIDEO_OCMEM 70 ++#define ICBID_MASTER_VPU1 71 ++#define ICBID_MASTER_VCAP 72 ++#define ICBID_MASTER_EMAC 73 ++#define ICBID_MASTER_BCAST 74 ++#define ICBID_MASTER_MMSS_PROC 75 ++#define ICBID_MASTER_SNOC_BIMC_1 76 ++#define ICBID_MASTER_SNOC_PCNOC 77 ++#define ICBID_MASTER_AUDIO 78 ++#define ICBID_MASTER_MM_INT_0 79 ++#define ICBID_MASTER_MM_INT_1 80 ++#define ICBID_MASTER_MM_INT_2 81 ++#define ICBID_MASTER_MM_INT_BIMC 82 ++#define ICBID_MASTER_MSS_INT 83 ++#define ICBID_MASTER_PCNOC_CFG 84 ++#define ICBID_MASTER_PCNOC_INT_0 85 ++#define ICBID_MASTER_PCNOC_INT_1 86 ++#define ICBID_MASTER_PCNOC_M_0 87 ++#define ICBID_MASTER_PCNOC_M_1 88 ++#define ICBID_MASTER_PCNOC_S_0 89 ++#define ICBID_MASTER_PCNOC_S_1 90 ++#define ICBID_MASTER_PCNOC_S_2 91 ++#define ICBID_MASTER_PCNOC_S_3 92 ++#define ICBID_MASTER_PCNOC_S_4 93 ++#define ICBID_MASTER_PCNOC_S_6 94 ++#define ICBID_MASTER_PCNOC_S_7 95 ++#define ICBID_MASTER_PCNOC_S_8 96 ++#define ICBID_MASTER_PCNOC_S_9 97 ++#define ICBID_MASTER_QDSS_INT 98 ++#define ICBID_MASTER_SNOC_INT_0 99 ++#define ICBID_MASTER_SNOC_INT_1 100 ++#define ICBID_MASTER_SNOC_INT_BIMC 101 ++#define ICBID_MASTER_TCU_0 102 ++#define ICBID_MASTER_TCU_1 103 ++#define ICBID_MASTER_BIMC_INT_0 104 ++#define ICBID_MASTER_BIMC_INT_1 105 ++#define ICBID_MASTER_CAMERA 106 ++#define ICBID_MASTER_RICA 107 ++#define ICBID_MASTER_PCNOC_S_5 129 ++#define ICBID_MASTER_PCNOC_INT_2 124 ++#define ICBID_MASTER_PCNOC_INT_3 125 ++#define ICBID_MASTER_PCNOC_INT_4 126 ++#define ICBID_MASTER_PCNOC_INT_5 127 ++#define ICBID_MASTER_PCNOC_INT_6 128 ++#define ICBID_MASTER_PCIE_2 119 ++#define ICBID_MASTER_MASTER_CNOC_A1NOC 116 ++#define ICBID_MASTER_A0NOC_SNOC 110 ++#define ICBID_MASTER_A1NOC_SNOC 111 ++#define ICBID_MASTER_A2NOC_SNOC 112 ++#define ICBID_MASTER_PNOC_A1NOC 117 ++#define ICBID_MASTER_ROTATOR 120 ++#define ICBID_MASTER_SNOC_VMEM 114 ++#define ICBID_MASTER_VENUS_VMEM 121 ++#define ICBID_MASTER_HMSS 118 ++#define ICBID_MASTER_BIMC_SNOC_1 109 ++#define ICBID_MASTER_CNOC_A1NOC 116 ++#define ICBID_MASTER_CPP 115 ++#define ICBID_MASTER_BLSP_BAM 130 ++#define ICBID_MASTER_USB2_BAM 131 ++#define ICBID_MASTER_ADSS_DMA0 132 ++#define ICBID_MASTER_ADSS_DMA1 133 ++#define ICBID_MASTER_ADSS_DMA2 134 ++#define ICBID_MASTER_ADSS_DMA3 135 ++#define ICBID_MASTER_QPIC_BAM 136 ++#define ICBID_MASTER_SDCC_BAM 137 ++#define ICBID_MASTER_DDRC_SNOC 138 ++#define ICBID_MASTER_WSS_0 139 ++#define ICBID_MASTER_WSS_1 140 ++#define ICBID_MASTER_ESS 141 ++#define ICBID_MASTER_PCIE 142 ++#define ICBID_MASTER_QDSS_BAMNDP 143 ++#define ICBID_MASTER_QDSS_SNOC_CFG 144 ++ ++#define ICBID_SLAVE_EBI1 0 ++#define ICBID_SLAVE_APPSS_L2 1 ++#define ICBID_SLAVE_BIMC_SNOC 2 ++#define ICBID_SLAVE_CAMERA_CFG 3 ++#define ICBID_SLAVE_DISPLAY_CFG 4 ++#define ICBID_SLAVE_OCMEM_CFG 5 ++#define ICBID_SLAVE_CPR_CFG 6 ++#define ICBID_SLAVE_CPR_XPU_CFG 7 ++#define ICBID_SLAVE_MISC_CFG 8 ++#define ICBID_SLAVE_MISC_XPU_CFG 9 ++#define ICBID_SLAVE_VENUS_CFG 10 ++#define ICBID_SLAVE_GFX3D_CFG 11 ++#define ICBID_SLAVE_MMSS_CLK_CFG 12 ++#define ICBID_SLAVE_MMSS_CLK_XPU_CFG 13 ++#define ICBID_SLAVE_MNOC_MPU_CFG 14 ++#define ICBID_SLAVE_ONOC_MPU_CFG 15 ++#define ICBID_SLAVE_MNOC_BIMC 16 ++#define ICBID_SLAVE_SERVICE_MNOC 17 ++#define ICBID_SLAVE_OCMEM 18 ++#define ICBID_SLAVE_GMEM ICBID_SLAVE_OCMEM ++#define ICBID_SLAVE_SERVICE_ONOC 19 ++#define ICBID_SLAVE_APPSS 20 ++#define ICBID_SLAVE_LPASS 21 ++#define ICBID_SLAVE_USB3 22 ++#define ICBID_SLAVE_USB3_0 ICBID_SLAVE_USB3 ++#define ICBID_SLAVE_WCSS 23 ++#define ICBID_SLAVE_SNOC_BIMC 24 ++#define ICBID_SLAVE_SNOC_BIMC_0 ICBID_SLAVE_SNOC_BIMC ++#define ICBID_SLAVE_SNOC_CNOC 25 ++#define ICBID_SLAVE_IMEM 26 ++#define ICBID_SLAVE_OCIMEM ICBID_SLAVE_IMEM ++#define ICBID_SLAVE_SNOC_OVIRT 27 ++#define ICBID_SLAVE_SNOC_GVIRT ICBID_SLAVE_SNOC_OVIRT ++#define ICBID_SLAVE_SNOC_PNOC 28 ++#define ICBID_SLAVE_SNOC_PCNOC ICBID_SLAVE_SNOC_PNOC ++#define ICBID_SLAVE_SERVICE_SNOC 29 ++#define ICBID_SLAVE_QDSS_STM 30 ++#define ICBID_SLAVE_SDCC_1 31 ++#define ICBID_SLAVE_SDCC_3 32 ++#define ICBID_SLAVE_SDCC_2 33 ++#define ICBID_SLAVE_SDCC_4 34 ++#define ICBID_SLAVE_TSIF 35 ++#define ICBID_SLAVE_BAM_DMA 36 ++#define ICBID_SLAVE_BLSP_2 37 ++#define ICBID_SLAVE_USB_HSIC 38 ++#define ICBID_SLAVE_BLSP_1 39 ++#define ICBID_SLAVE_USB_HS 40 ++#define ICBID_SLAVE_USB_HS1 ICBID_SLAVE_USB_HS ++#define ICBID_SLAVE_PDM 41 ++#define ICBID_SLAVE_PERIPH_APU_CFG 42 ++#define ICBID_SLAVE_PNOC_MPU_CFG 43 ++#define ICBID_SLAVE_PRNG 44 ++#define ICBID_SLAVE_PNOC_SNOC 45 ++#define ICBID_SLAVE_PCNOC_SNOC ICBID_SLAVE_PNOC_SNOC ++#define ICBID_SLAVE_SERVICE_PNOC 46 ++#define ICBID_SLAVE_CLK_CTL 47 ++#define ICBID_SLAVE_CNOC_MSS 48 ++#define ICBID_SLAVE_PCNOC_MSS ICBID_SLAVE_CNOC_MSS ++#define ICBID_SLAVE_SECURITY 49 ++#define ICBID_SLAVE_TCSR 50 ++#define ICBID_SLAVE_TLMM 51 ++#define ICBID_SLAVE_CRYPTO_0_CFG 52 ++#define ICBID_SLAVE_CRYPTO_1_CFG 53 ++#define ICBID_SLAVE_IMEM_CFG 54 ++#define ICBID_SLAVE_MESSAGE_RAM 55 ++#define ICBID_SLAVE_BIMC_CFG 56 ++#define ICBID_SLAVE_BOOT_ROM 57 ++#define ICBID_SLAVE_CNOC_MNOC_MMSS_CFG 58 ++#define ICBID_SLAVE_PMIC_ARB 59 ++#define ICBID_SLAVE_SPDM_WRAPPER 60 ++#define ICBID_SLAVE_DEHR_CFG 61 ++#define ICBID_SLAVE_MPM 62 ++#define ICBID_SLAVE_QDSS_CFG 63 ++#define ICBID_SLAVE_RBCPR_CFG 64 ++#define ICBID_SLAVE_RBCPR_CX_CFG ICBID_SLAVE_RBCPR_CFG ++#define ICBID_SLAVE_RBCPR_QDSS_APU_CFG 65 ++#define ICBID_SLAVE_CNOC_MNOC_CFG 66 ++#define ICBID_SLAVE_SNOC_MPU_CFG 67 ++#define ICBID_SLAVE_CNOC_ONOC_CFG 68 ++#define ICBID_SLAVE_PNOC_CFG 69 ++#define ICBID_SLAVE_SNOC_CFG 70 ++#define ICBID_SLAVE_EBI1_DLL_CFG 71 ++#define ICBID_SLAVE_PHY_APU_CFG 72 ++#define ICBID_SLAVE_EBI1_PHY_CFG 73 ++#define ICBID_SLAVE_RPM 74 ++#define ICBID_SLAVE_CNOC_SNOC 75 ++#define ICBID_SLAVE_SERVICE_CNOC 76 ++#define ICBID_SLAVE_OVIRT_SNOC 77 ++#define ICBID_SLAVE_OVIRT_OCMEM 78 ++#define ICBID_SLAVE_USB_HS2 79 ++#define ICBID_SLAVE_QPIC 80 ++#define ICBID_SLAVE_IPS_CFG 81 ++#define ICBID_SLAVE_DSI_CFG 82 ++#define ICBID_SLAVE_USB3_1 83 ++#define ICBID_SLAVE_PCIE_0 84 ++#define ICBID_SLAVE_PCIE_1 85 ++#define ICBID_SLAVE_PSS_SMMU_CFG 86 ++#define ICBID_SLAVE_CRYPTO_2_CFG 87 ++#define ICBID_SLAVE_PCIE_0_CFG 88 ++#define ICBID_SLAVE_PCIE_1_CFG 89 ++#define ICBID_SLAVE_SATA_CFG 90 ++#define ICBID_SLAVE_SPSS_GENI_IR 91 ++#define ICBID_SLAVE_UFS_CFG 92 ++#define ICBID_SLAVE_AVSYNC_CFG 93 ++#define ICBID_SLAVE_VPU_CFG 94 ++#define ICBID_SLAVE_USB_PHY_CFG 95 ++#define ICBID_SLAVE_RBCPR_MX_CFG 96 ++#define ICBID_SLAVE_PCIE_PARF 97 ++#define ICBID_SLAVE_VCAP_CFG 98 ++#define ICBID_SLAVE_EMAC_CFG 99 ++#define ICBID_SLAVE_BCAST_CFG 100 ++#define ICBID_SLAVE_KLM_CFG 101 ++#define ICBID_SLAVE_DISPLAY_PWM 102 ++#define ICBID_SLAVE_GENI 103 ++#define ICBID_SLAVE_SNOC_BIMC_1 104 ++#define ICBID_SLAVE_AUDIO 105 ++#define ICBID_SLAVE_CATS_0 106 ++#define ICBID_SLAVE_CATS_1 107 ++#define ICBID_SLAVE_MM_INT_0 108 ++#define ICBID_SLAVE_MM_INT_1 109 ++#define ICBID_SLAVE_MM_INT_2 110 ++#define ICBID_SLAVE_MM_INT_BIMC 111 ++#define ICBID_SLAVE_MMU_MODEM_XPU_CFG 112 ++#define ICBID_SLAVE_MSS_INT 113 ++#define ICBID_SLAVE_PCNOC_INT_0 114 ++#define ICBID_SLAVE_PCNOC_INT_1 115 ++#define ICBID_SLAVE_PCNOC_M_0 116 ++#define ICBID_SLAVE_PCNOC_M_1 117 ++#define ICBID_SLAVE_PCNOC_S_0 118 ++#define ICBID_SLAVE_PCNOC_S_1 119 ++#define ICBID_SLAVE_PCNOC_S_2 120 ++#define ICBID_SLAVE_PCNOC_S_3 121 ++#define ICBID_SLAVE_PCNOC_S_4 122 ++#define ICBID_SLAVE_PCNOC_S_6 123 ++#define ICBID_SLAVE_PCNOC_S_7 124 ++#define ICBID_SLAVE_PCNOC_S_8 125 ++#define ICBID_SLAVE_PCNOC_S_9 126 ++#define ICBID_SLAVE_PRNG_XPU_CFG 127 ++#define ICBID_SLAVE_QDSS_INT 128 ++#define ICBID_SLAVE_RPM_XPU_CFG 129 ++#define ICBID_SLAVE_SNOC_INT_0 130 ++#define ICBID_SLAVE_SNOC_INT_1 131 ++#define ICBID_SLAVE_SNOC_INT_BIMC 132 ++#define ICBID_SLAVE_TCU 133 ++#define ICBID_SLAVE_BIMC_INT_0 134 ++#define ICBID_SLAVE_BIMC_INT_1 135 ++#define ICBID_SLAVE_RICA_CFG 136 ++#define ICBID_SLAVE_PCNOC_S_5 189 ++#define ICBID_SLAVE_PCNOC_S_7 124 ++#define ICBID_SLAVE_PCNOC_INT_2 184 ++#define ICBID_SLAVE_PCNOC_INT_3 185 ++#define ICBID_SLAVE_PCNOC_INT_4 186 ++#define ICBID_SLAVE_PCNOC_INT_5 187 ++#define ICBID_SLAVE_PCNOC_INT_6 188 ++#define ICBID_SLAVE_USB3_PHY_CFG 182 ++#define ICBID_SLAVE_IPA_CFG 183 ++ ++#define ICBID_SLAVE_A0NOC_SNOC 141 ++#define ICBID_SLAVE_A1NOC_SNOC 142 ++#define ICBID_SLAVE_A2NOC_SNOC 143 ++#define ICBID_SLAVE_BIMC_SNOC_1 138 ++#define ICBID_SLAVE_PIMEM 167 ++#define ICBID_SLAVE_PIMEM_CFG 168 ++#define ICBID_SLAVE_DCC_CFG 155 ++#define ICBID_SLAVE_QDSS_RBCPR_APU_CFG 168 ++#define ICBID_SLAVE_A0NOC_CFG 144 ++#define ICBID_SLAVE_PCIE_2_CFG 165 ++#define ICBID_SLAVE_PCIE20_AHB2PHY 163 ++#define ICBID_SLAVE_PCIE_2 164 ++#define ICBID_SLAVE_A1NOC_CFG 147 ++#define ICBID_SLAVE_A1NOC_MPU_CFG 148 ++#define ICBID_SLAVE_A1NOC_SMMU_CFG 149 ++#define ICBID_SLAVE_A2NOC_CFG 150 ++#define ICBID_SLAVE_A2NOC_MPU_CFG 151 ++#define ICBID_SLAVE_A2NOC_SMMU_CFG 152 ++#define ICBID_SLAVE_AHB2PHY 153 ++#define ICBID_SLAVE_HMSS_L3 161 ++#define ICBID_SLAVE_LPASS_SMMU_CFG 161 ++#define ICBID_SLAVE_MMAGIC_CFG 162 ++#define ICBID_SLAVE_SSC_CFG 177 ++#define ICBID_SLAVE_VENUS_THROTTLE_CFG 178 ++#define ICBID_SLAVE_DISPLAY_THROTTLE_CFG 156 ++#define ICBID_SLAVE_CAMERA_THROTTLE_CFG 154 ++#define ICBID_SLAVE_DSA_CFG 157 ++#define ICBID_SLAVE_DSA_MPU_CFG 158 ++#define ICBID_SLAVE_SMMU_CPP_CFG 171 ++#define ICBID_SLAVE_SMMU_JPEG_CFG 172 ++#define ICBID_SLAVE_SMMU_MDP_CFG 173 ++#define ICBID_SLAVE_SMMU_ROTATOR_CFG 174 ++#define ICBID_SLAVE_SMMU_VENUS_CFG 175 ++#define ICBID_SLAVE_SMMU_VFE_CFG 176 ++#define ICBID_SLAVE_A0NOC_MPU_CFG 145 ++#define ICBID_SLAVE_A0NOC_SMMU_CFG 146 ++#define ICBID_SLAVE_VMEM_CFG 180 ++#define ICBID_SLAVE_VMEM 179 ++#define ICBID_SLAVE_PNOC_A1NOC 139 ++#define ICBID_SLAVE_SNOC_VMEM 140 ++#define ICBID_SLAVE_RBCPR_MX 170 ++#define ICBID_SLAVE_RBCPR_CX 169 ++#define ICBID_SLAVE_PRNG_APU_CFG 190 ++#define ICBID_SLAVE_PERIPH_MPU_CFG 191 ++#define ICBID_SLAVE_GCNT 192 ++#define ICBID_SLAVE_ADSS_CFG 193 ++#define ICBID_SLAVE_ADSS_APU 194 ++#define ICBID_SLAVE_ADSS_VMIDMT_CFG 195 ++#define ICBID_SLAVE_QHSS_APU_CFG 196 ++#define ICBID_SLAVE_MDIO 197 ++#define ICBID_SLAVE_FEPHY_CFG 198 ++#define ICBID_SLAVE_SRIF 199 ++#define ICBID_SLAVE_DDRC_CFG 200 ++#define ICBID_SLAVE_DDRC_APU_CFG 201 ++#define ICBID_SLAVE_DDRC_MPU0_CFG 202 ++#define ICBID_SLAVE_DDRC_MPU1_CFG 203 ++#define ICBID_SLAVE_DDRC_MPU2_CFG 210 ++#define ICBID_SLAVE_ESS_VMIDMT_CFG 211 ++#define ICBID_SLAVE_ESS_APU_CFG 212 ++#define ICBID_SLAVE_USB2_CFG 213 ++#define ICBID_SLAVE_BLSP_CFG 214 ++#define ICBID_SLAVE_QPIC_CFG 215 ++#define ICBID_SLAVE_SDCC_CFG 216 ++#define ICBID_SLAVE_WSS0_VMIDMT_CFG 217 ++#define ICBID_SLAVE_WSS0_APU_CFG 218 ++#define ICBID_SLAVE_WSS1_VMIDMT_CFG 219 ++#define ICBID_SLAVE_WSS1_APU_CFG 220 ++#define ICBID_SLAVE_SRVC_PCNOC 221 ++#define ICBID_SLAVE_SNOC_DDRC 222 ++#define ICBID_SLAVE_A7SS 223 ++#define ICBID_SLAVE_WSS0_CFG 224 ++#define ICBID_SLAVE_WSS1_CFG 225 ++#define ICBID_SLAVE_PCIE 226 ++#define ICBID_SLAVE_USB3_CFG 227 ++#define ICBID_SLAVE_CRYPTO_CFG 228 ++#define ICBID_SLAVE_ESS_CFG 229 ++#define ICBID_SLAVE_SRVC_SNOC 230 ++#endif +--- /dev/null ++++ b/include/dt-bindings/msm/msm-bus-rule-ops.h +@@ -0,0 +1,32 @@ ++/* Copyright (c) 2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __MSM_BUS_RULE_OPS_H ++#define __MSM_BUS_RULE_OPS_H ++ ++#define FLD_IB 0 ++#define FLD_AB 1 ++#define FLD_CLK 2 ++ ++#define OP_LE 0 ++#define OP_LT 1 ++#define OP_GE 2 ++#define OP_GT 3 ++#define OP_NOOP 4 ++ ++#define RULE_STATE_NOT_APPLIED 0 ++#define RULE_STATE_APPLIED 1 ++ ++#define THROTTLE_ON 0 ++#define THROTTLE_OFF 1 ++ ++#endif +--- /dev/null ++++ b/drivers/bus/msm_bus/Kconfig +@@ -0,0 +1,19 @@ ++config BUS_TOPOLOGY_ADHOC ++ bool "ad-hoc bus scaling topology" ++ depends on ARCH_QCOM ++ default n ++ help ++ This option enables a driver that can handle adhoc bus topologies. ++ Adhoc bus topology driver allows one to many connections and maintains ++ directionality of connections by explicitly listing device connections ++ thus avoiding illegal routes. ++ ++config MSM_BUS_SCALING ++ bool "Bus scaling driver" ++ depends on BUS_TOPOLOGY_ADHOC ++ default n ++ help ++ This option enables bus scaling on MSM devices. Bus scaling ++ allows devices to request the clocks be set to rates sufficient ++ for the active devices needs without keeping the clocks at max ++ frequency when a slower speed is sufficient. +--- /dev/null ++++ b/drivers/bus/msm_bus/Makefile +@@ -0,0 +1,12 @@ ++# ++# Makefile for msm-bus driver specific files ++# ++obj-y += msm_bus_bimc.o msm_bus_noc.o msm_bus_core.o msm_bus_client_api.o \ ++ msm_bus_id.o ++obj-$(CONFIG_OF) += msm_bus_of.o ++ ++obj-y += msm_bus_fabric_adhoc.o msm_bus_arb_adhoc.o msm_bus_rules.o ++obj-$(CONFIG_OF) += msm_bus_of_adhoc.o ++obj-$(CONFIG_CORESIGHT) += msm_buspm_coresight_adhoc.o ++ ++obj-$(CONFIG_DEBUG_FS) += msm_bus_dbg.o +--- /dev/null ++++ b/drivers/bus/msm_bus/msm-bus-board.h +@@ -0,0 +1,198 @@ ++/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __ASM_ARCH_MSM_BUS_BOARD_H ++#define __ASM_ARCH_MSM_BUS_BOARD_H ++ ++#include ++#include ++ ++enum context { ++ DUAL_CTX, ++ ACTIVE_CTX, ++ NUM_CTX ++}; ++ ++struct msm_bus_fabric_registration { ++ unsigned int id; ++ const char *name; ++ struct msm_bus_node_info *info; ++ unsigned int len; ++ int ahb; ++ const char *fabclk[NUM_CTX]; ++ const char *iface_clk; ++ unsigned int offset; ++ unsigned int haltid; ++ unsigned int rpm_enabled; ++ unsigned int nmasters; ++ unsigned int nslaves; ++ unsigned int ntieredslaves; ++ bool il_flag; ++ const struct msm_bus_board_algorithm *board_algo; ++ int hw_sel; ++ void *hw_data; ++ uint32_t qos_freq; ++ uint32_t qos_baseoffset; ++ u64 nr_lim_thresh; ++ uint32_t eff_fact; ++ uint32_t qos_delta; ++ bool virt; ++}; ++ ++struct msm_bus_device_node_registration { ++ struct msm_bus_node_device_type *info; ++ unsigned int num_devices; ++ bool virt; ++}; ++ ++enum msm_bus_bw_tier_type { ++ MSM_BUS_BW_TIER1 = 1, ++ MSM_BUS_BW_TIER2, ++ MSM_BUS_BW_COUNT, ++ MSM_BUS_BW_SIZE = 0x7FFFFFFF, ++}; ++ ++struct msm_bus_halt_vector { ++ uint32_t haltval; ++ uint32_t haltmask; ++}; ++ ++extern struct msm_bus_fabric_registration msm_bus_apps_fabric_pdata; ++extern struct msm_bus_fabric_registration msm_bus_sys_fabric_pdata; ++extern struct msm_bus_fabric_registration msm_bus_mm_fabric_pdata; ++extern struct msm_bus_fabric_registration msm_bus_sys_fpb_pdata; ++extern struct msm_bus_fabric_registration msm_bus_cpss_fpb_pdata; ++extern struct msm_bus_fabric_registration msm_bus_def_fab_pdata; ++ ++extern struct msm_bus_fabric_registration msm_bus_8960_apps_fabric_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8960_sys_fabric_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8960_mm_fabric_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8960_sg_mm_fabric_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8960_sys_fpb_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8960_cpss_fpb_pdata; ++ ++extern struct msm_bus_fabric_registration msm_bus_8064_apps_fabric_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8064_sys_fabric_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8064_mm_fabric_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8064_sys_fpb_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8064_cpss_fpb_pdata; ++ ++extern struct msm_bus_fabric_registration msm_bus_9615_sys_fabric_pdata; ++extern struct msm_bus_fabric_registration msm_bus_9615_def_fab_pdata; ++ ++extern struct msm_bus_fabric_registration msm_bus_8930_apps_fabric_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8930_sys_fabric_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8930_mm_fabric_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8930_sys_fpb_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8930_cpss_fpb_pdata; ++ ++extern struct msm_bus_fabric_registration msm_bus_8974_sys_noc_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8974_mmss_noc_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8974_bimc_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8974_ocmem_noc_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8974_periph_noc_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8974_config_noc_pdata; ++extern struct msm_bus_fabric_registration msm_bus_8974_ocmem_vnoc_pdata; ++ ++extern struct msm_bus_fabric_registration msm_bus_9625_sys_noc_pdata; ++extern struct msm_bus_fabric_registration msm_bus_9625_bimc_pdata; ++extern struct msm_bus_fabric_registration msm_bus_9625_periph_noc_pdata; ++extern struct msm_bus_fabric_registration msm_bus_9625_config_noc_pdata; ++ ++extern int msm_bus_device_match_adhoc(struct device *dev, void *id); ++ ++void msm_bus_rpm_set_mt_mask(void); ++int msm_bus_board_rpm_get_il_ids(uint16_t *id); ++int msm_bus_board_get_iid(int id); ++ ++#define NFAB_MSM8226 6 ++#define NFAB_MSM8610 5 ++ ++/* ++ * These macros specify the convention followed for allocating ++ * ids to fabrics, masters and slaves for 8x60. ++ * ++ * A node can be identified as a master/slave/fabric by using ++ * these ids. ++ */ ++#define FABRIC_ID_KEY 1024 ++#define SLAVE_ID_KEY ((FABRIC_ID_KEY) >> 1) ++#define MAX_FAB_KEY 7168 /* OR(All fabric ids) */ ++#define INT_NODE_START 10000 ++ ++#define GET_FABID(id) ((id) & MAX_FAB_KEY) ++ ++#define NODE_ID(id) ((id) & (FABRIC_ID_KEY - 1)) ++#define IS_SLAVE(id) ((NODE_ID(id)) >= SLAVE_ID_KEY ? 1 : 0) ++#define CHECK_ID(iid, id) (((iid & id) != id) ? -ENXIO : iid) ++ ++/* ++ * The following macros are used to format the data for port halt ++ * and unhalt requests. ++ */ ++#define MSM_BUS_CLK_HALT 0x1 ++#define MSM_BUS_CLK_HALT_MASK 0x1 ++#define MSM_BUS_CLK_HALT_FIELDSIZE 0x1 ++#define MSM_BUS_CLK_UNHALT 0x0 ++ ++#define MSM_BUS_MASTER_SHIFT(master, fieldsize) \ ++ ((master) * (fieldsize)) ++ ++#define MSM_BUS_SET_BITFIELD(word, fieldmask, fieldvalue) \ ++ { \ ++ (word) &= ~(fieldmask); \ ++ (word) |= (fieldvalue); \ ++ } ++ ++ ++#define MSM_BUS_MASTER_HALT(u32haltmask, u32haltval, master) \ ++ MSM_BUS_SET_BITFIELD(u32haltmask, \ ++ MSM_BUS_CLK_HALT_MASK< ++ ++ ++#endif /*__ASM_ARCH_MSM_BUS_BOARD_H */ +--- /dev/null ++++ b/drivers/bus/msm_bus/msm-bus.h +@@ -0,0 +1,139 @@ ++/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _ARCH_ARM_MACH_MSM_BUS_H ++#define _ARCH_ARM_MACH_MSM_BUS_H ++ ++#include ++#include ++#include ++ ++/* ++ * Macros for clients to convert their data to ib and ab ++ * Ws : Time window over which to transfer the data in SECONDS ++ * Bs : Size of the data block in bytes ++ * Per : Recurrence period ++ * Tb : Throughput bandwidth to prevent stalling ++ * R : Ratio of actual bandwidth used to Tb ++ * Ib : Instantaneous bandwidth ++ * Ab : Arbitrated bandwidth ++ * ++ * IB_RECURRBLOCK and AB_RECURRBLOCK: ++ * These are used if the requirement is to transfer a ++ * recurring block of data over a known time window. ++ * ++ * IB_THROUGHPUTBW and AB_THROUGHPUTBW: ++ * These are used for CPU style masters. Here the requirement ++ * is to have minimum throughput bandwidth available to avoid ++ * stalling. ++ */ ++#define IB_RECURRBLOCK(Ws, Bs) ((Ws) == 0 ? 0 : ((Bs)/(Ws))) ++#define AB_RECURRBLOCK(Ws, Per) ((Ws) == 0 ? 0 : ((Bs)/(Per))) ++#define IB_THROUGHPUTBW(Tb) (Tb) ++#define AB_THROUGHPUTBW(Tb, R) ((Tb) * (R)) ++ ++struct msm_bus_vectors { ++ int src; /* Master */ ++ int dst; /* Slave */ ++ uint64_t ab; /* Arbitrated bandwidth */ ++ uint64_t ib; /* Instantaneous bandwidth */ ++}; ++ ++struct msm_bus_paths { ++ int num_paths; ++ struct msm_bus_vectors *vectors; ++}; ++ ++struct msm_bus_scale_pdata { ++ struct msm_bus_paths *usecase; ++ int num_usecases; ++ const char *name; ++ /* ++ * If the active_only flag is set to 1, the BW request is applied ++ * only when at least one CPU is active (powered on). If the flag ++ * is set to 0, then the BW request is always applied irrespective ++ * of the CPU state. ++ */ ++ unsigned int active_only; ++}; ++ ++/* Scaling APIs */ ++ ++/* ++ * This function returns a handle to the client. This should be used to ++ * call msm_bus_scale_client_update_request. ++ * The function returns 0 if bus driver is unable to register a client ++ */ ++ ++#if (defined(CONFIG_MSM_BUS_SCALING) || defined(CONFIG_BUS_TOPOLOGY_ADHOC)) ++int __init msm_bus_fabric_init_driver(void); ++uint32_t msm_bus_scale_register_client(struct msm_bus_scale_pdata *pdata); ++int msm_bus_scale_client_update_request(uint32_t cl, unsigned int index); ++void msm_bus_scale_unregister_client(uint32_t cl); ++/* AXI Port configuration APIs */ ++int msm_bus_axi_porthalt(int master_port); ++int msm_bus_axi_portunhalt(int master_port); ++ ++#else ++static inline int __init msm_bus_fabric_init_driver(void) { return 0; } ++ ++static inline uint32_t ++msm_bus_scale_register_client(struct msm_bus_scale_pdata *pdata) ++{ ++ return 1; ++} ++ ++static inline int ++msm_bus_scale_client_update_request(uint32_t cl, unsigned int index) ++{ ++ return 0; ++} ++ ++static inline void ++msm_bus_scale_unregister_client(uint32_t cl) ++{ ++} ++ ++static inline int msm_bus_axi_porthalt(int master_port) ++{ ++ return 0; ++} ++ ++static inline int msm_bus_axi_portunhalt(int master_port) ++{ ++ return 0; ++} ++#endif ++ ++#if defined(CONFIG_OF) && defined(CONFIG_MSM_BUS_SCALING) ++struct msm_bus_scale_pdata *msm_bus_pdata_from_node( ++ struct platform_device *pdev, struct device_node *of_node); ++struct msm_bus_scale_pdata *msm_bus_cl_get_pdata(struct platform_device *pdev); ++void msm_bus_cl_clear_pdata(struct msm_bus_scale_pdata *pdata); ++#else ++static inline struct msm_bus_scale_pdata ++*msm_bus_cl_get_pdata(struct platform_device *pdev) ++{ ++ return NULL; ++} ++ ++static inline struct msm_bus_scale_pdata *msm_bus_pdata_from_node( ++ struct platform_device *pdev, struct device_node *of_node) ++{ ++ return NULL; ++} ++ ++static inline void msm_bus_cl_clear_pdata(struct msm_bus_scale_pdata *pdata) ++{ ++} ++#endif ++#endif /*_ARCH_ARM_MACH_MSM_BUS_H*/ +--- /dev/null ++++ b/drivers/bus/msm_bus/msm_bus_adhoc.h +@@ -0,0 +1,141 @@ ++/* Copyright (c) 2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _ARCH_ARM_MACH_MSM_BUS_ADHOC_H ++#define _ARCH_ARM_MACH_MSM_BUS_ADHOC_H ++ ++#include ++#include ++#include "msm-bus-board.h" ++#include "msm-bus.h" ++#include "msm_bus_rules.h" ++#include "msm_bus_core.h" ++ ++struct msm_bus_node_device_type; ++struct link_node { ++ uint64_t lnode_ib[NUM_CTX]; ++ uint64_t lnode_ab[NUM_CTX]; ++ int next; ++ struct device *next_dev; ++ struct list_head link; ++ uint32_t in_use; ++}; ++ ++/* New types introduced for adhoc topology */ ++struct msm_bus_noc_ops { ++ int (*qos_init)(struct msm_bus_node_device_type *dev, ++ void __iomem *qos_base, uint32_t qos_off, ++ uint32_t qos_delta, uint32_t qos_freq); ++ int (*set_bw)(struct msm_bus_node_device_type *dev, ++ void __iomem *qos_base, uint32_t qos_off, ++ uint32_t qos_delta, uint32_t qos_freq); ++ int (*limit_mport)(struct msm_bus_node_device_type *dev, ++ void __iomem *qos_base, uint32_t qos_off, ++ uint32_t qos_delta, uint32_t qos_freq, bool enable_lim, ++ uint64_t lim_bw); ++ bool (*update_bw_reg)(int mode); ++}; ++ ++struct nodebw { ++ uint64_t ab[NUM_CTX]; ++ bool dirty; ++}; ++ ++struct msm_bus_fab_device_type { ++ void __iomem *qos_base; ++ phys_addr_t pqos_base; ++ size_t qos_range; ++ uint32_t base_offset; ++ uint32_t qos_freq; ++ uint32_t qos_off; ++ uint32_t util_fact; ++ uint32_t vrail_comp; ++ struct msm_bus_noc_ops noc_ops; ++ enum msm_bus_hw_sel bus_type; ++ bool bypass_qos_prg; ++}; ++ ++struct qos_params_type { ++ int mode; ++ unsigned int prio_lvl; ++ unsigned int prio_rd; ++ unsigned int prio_wr; ++ unsigned int prio1; ++ unsigned int prio0; ++ unsigned int gp; ++ unsigned int thmp; ++ unsigned int ws; ++ int cur_mode; ++ u64 bw_buffer; ++}; ++ ++struct msm_bus_node_info_type { ++ const char *name; ++ unsigned int id; ++ int mas_rpm_id; ++ int slv_rpm_id; ++ int num_ports; ++ int num_qports; ++ int *qport; ++ struct qos_params_type qos_params; ++ unsigned int num_connections; ++ unsigned int num_blist; ++ bool is_fab_dev; ++ bool virt_dev; ++ bool is_traversed; ++ unsigned int *connections; ++ unsigned int *black_listed_connections; ++ struct device **dev_connections; ++ struct device **black_connections; ++ unsigned int bus_device_id; ++ struct device *bus_device; ++ unsigned int buswidth; ++ struct rule_update_path_info rule; ++ uint64_t lim_bw; ++ uint32_t util_fact; ++ uint32_t vrail_comp; ++}; ++ ++struct msm_bus_node_device_type { ++ struct msm_bus_node_info_type *node_info; ++ struct msm_bus_fab_device_type *fabdev; ++ int num_lnodes; ++ struct link_node *lnode_list; ++ uint64_t cur_clk_hz[NUM_CTX]; ++ struct nodebw node_ab; ++ struct list_head link; ++ unsigned int ap_owned; ++ struct nodeclk clk[NUM_CTX]; ++ struct nodeclk qos_clk; ++}; ++ ++int msm_bus_enable_limiter(struct msm_bus_node_device_type *nodedev, ++ bool throttle_en, uint64_t lim_bw); ++int msm_bus_update_clks(struct msm_bus_node_device_type *nodedev, ++ int ctx, int **dirty_nodes, int *num_dirty); ++int msm_bus_commit_data(int *dirty_nodes, int ctx, int num_dirty); ++int msm_bus_update_bw(struct msm_bus_node_device_type *nodedev, int ctx, ++ int64_t add_bw, int **dirty_nodes, int *num_dirty); ++void *msm_bus_realloc_devmem(struct device *dev, void *p, size_t old_size, ++ size_t new_size, gfp_t flags); ++ ++extern struct msm_bus_device_node_registration ++ *msm_bus_of_to_pdata(struct platform_device *pdev); ++extern void msm_bus_arb_setops_adhoc(struct msm_bus_arb_ops *arb_ops); ++extern int msm_bus_bimc_set_ops(struct msm_bus_node_device_type *bus_dev); ++extern int msm_bus_noc_set_ops(struct msm_bus_node_device_type *bus_dev); ++extern int msm_bus_of_get_static_rules(struct platform_device *pdev, ++ struct bus_rule_type **static_rule); ++extern int msm_rules_update_path(struct list_head *input_list, ++ struct list_head *output_list); ++extern void print_all_rules(void); ++#endif /* _ARCH_ARM_MACH_MSM_BUS_ADHOC_H */ +--- /dev/null ++++ b/drivers/bus/msm_bus/msm_bus_arb_adhoc.c +@@ -0,0 +1,998 @@ ++/* Copyright (c) 2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is Mree software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "msm-bus.h" ++#include "msm_bus_core.h" ++#include "msm_bus_adhoc.h" ++ ++#define NUM_CL_HANDLES 50 ++#define NUM_LNODES 3 ++ ++struct bus_search_type { ++ struct list_head link; ++ struct list_head node_list; ++}; ++ ++struct handle_type { ++ int num_entries; ++ struct msm_bus_client **cl_list; ++}; ++ ++static struct handle_type handle_list; ++struct list_head input_list; ++struct list_head apply_list; ++ ++DEFINE_MUTEX(msm_bus_adhoc_lock); ++ ++static bool chk_bl_list(struct list_head *black_list, unsigned int id) ++{ ++ struct msm_bus_node_device_type *bus_node = NULL; ++ ++ list_for_each_entry(bus_node, black_list, link) { ++ if (bus_node->node_info->id == id) ++ return true; ++ } ++ return false; ++} ++ ++static void copy_remaining_nodes(struct list_head *edge_list, struct list_head ++ *traverse_list, struct list_head *route_list) ++{ ++ struct bus_search_type *search_node; ++ ++ if (list_empty(edge_list) && list_empty(traverse_list)) ++ return; ++ ++ search_node = kzalloc(sizeof(struct bus_search_type), GFP_KERNEL); ++ INIT_LIST_HEAD(&search_node->node_list); ++ list_splice_init(edge_list, traverse_list); ++ list_splice_init(traverse_list, &search_node->node_list); ++ list_add_tail(&search_node->link, route_list); ++} ++ ++/* ++ * Duplicate instantiaion from msm_bus_arb.c. Todo there needs to be a ++ * "util" file for these common func/macros. ++ * ++ * */ ++uint64_t msm_bus_div64(unsigned int w, uint64_t bw) ++{ ++ uint64_t *b = &bw; ++ ++ if ((bw > 0) && (bw < w)) ++ return 1; ++ ++ switch (w) { ++ case 0: ++ WARN(1, "AXI: Divide by 0 attempted\n"); ++ case 1: return bw; ++ case 2: return (bw >> 1); ++ case 4: return (bw >> 2); ++ case 8: return (bw >> 3); ++ case 16: return (bw >> 4); ++ case 32: return (bw >> 5); ++ } ++ ++ do_div(*b, w); ++ return *b; ++} ++ ++int msm_bus_device_match_adhoc(struct device *dev, void *id) ++{ ++ int ret = 0; ++ struct msm_bus_node_device_type *bnode = dev->platform_data; ++ ++ if (bnode) ++ ret = (bnode->node_info->id == *(unsigned int *)id); ++ else ++ ret = 0; ++ ++ return ret; ++} ++ ++static int gen_lnode(struct device *dev, ++ int next_hop, int prev_idx) ++{ ++ struct link_node *lnode; ++ struct msm_bus_node_device_type *cur_dev = NULL; ++ int lnode_idx = -1; ++ ++ if (!dev) ++ goto exit_gen_lnode; ++ ++ cur_dev = dev->platform_data; ++ if (!cur_dev) { ++ MSM_BUS_ERR("%s: Null device ptr", __func__); ++ goto exit_gen_lnode; ++ } ++ ++ if (!cur_dev->num_lnodes) { ++ cur_dev->lnode_list = devm_kzalloc(dev, ++ sizeof(struct link_node) * NUM_LNODES, ++ GFP_KERNEL); ++ if (!cur_dev->lnode_list) ++ goto exit_gen_lnode; ++ ++ lnode = cur_dev->lnode_list; ++ cur_dev->num_lnodes = NUM_LNODES; ++ lnode_idx = 0; ++ } else { ++ int i; ++ for (i = 0; i < cur_dev->num_lnodes; i++) { ++ if (!cur_dev->lnode_list[i].in_use) ++ break; ++ } ++ ++ if (i < cur_dev->num_lnodes) { ++ lnode = &cur_dev->lnode_list[i]; ++ lnode_idx = i; ++ } else { ++ struct link_node *realloc_list; ++ size_t cur_size = sizeof(struct link_node) * ++ cur_dev->num_lnodes; ++ ++ cur_dev->num_lnodes += NUM_LNODES; ++ realloc_list = msm_bus_realloc_devmem( ++ dev, ++ cur_dev->lnode_list, ++ cur_size, ++ sizeof(struct link_node) * ++ cur_dev->num_lnodes, GFP_KERNEL); ++ ++ if (!realloc_list) ++ goto exit_gen_lnode; ++ ++ cur_dev->lnode_list = realloc_list; ++ lnode = &cur_dev->lnode_list[i]; ++ lnode_idx = i; ++ } ++ } ++ ++ lnode->in_use = 1; ++ if (next_hop == cur_dev->node_info->id) { ++ lnode->next = -1; ++ lnode->next_dev = NULL; ++ } else { ++ lnode->next = prev_idx; ++ lnode->next_dev = bus_find_device(&msm_bus_type, NULL, ++ (void *) &next_hop, ++ msm_bus_device_match_adhoc); ++ } ++ ++ memset(lnode->lnode_ib, 0, sizeof(uint64_t) * NUM_CTX); ++ memset(lnode->lnode_ab, 0, sizeof(uint64_t) * NUM_CTX); ++ ++exit_gen_lnode: ++ return lnode_idx; ++} ++ ++static int remove_lnode(struct msm_bus_node_device_type *cur_dev, ++ int lnode_idx) ++{ ++ int ret = 0; ++ ++ if (!cur_dev) { ++ MSM_BUS_ERR("%s: Null device ptr", __func__); ++ ret = -ENODEV; ++ goto exit_remove_lnode; ++ } ++ ++ if (lnode_idx != -1) { ++ if (!cur_dev->num_lnodes || ++ (lnode_idx > (cur_dev->num_lnodes - 1))) { ++ MSM_BUS_ERR("%s: Invalid Idx %d, num_lnodes %d", ++ __func__, lnode_idx, cur_dev->num_lnodes); ++ ret = -ENODEV; ++ goto exit_remove_lnode; ++ } ++ ++ cur_dev->lnode_list[lnode_idx].next = -1; ++ cur_dev->lnode_list[lnode_idx].next_dev = NULL; ++ cur_dev->lnode_list[lnode_idx].in_use = 0; ++ } ++ ++exit_remove_lnode: ++ return ret; ++} ++ ++static int prune_path(struct list_head *route_list, int dest, int src, ++ struct list_head *black_list, int found) ++{ ++ struct bus_search_type *search_node, *temp_search_node; ++ struct msm_bus_node_device_type *bus_node; ++ struct list_head *bl_list; ++ struct list_head *temp_bl_list; ++ int search_dev_id = dest; ++ struct device *dest_dev = bus_find_device(&msm_bus_type, NULL, ++ (void *) &dest, ++ msm_bus_device_match_adhoc); ++ int lnode_hop = -1; ++ ++ if (!found) ++ goto reset_links; ++ ++ if (!dest_dev) { ++ MSM_BUS_ERR("%s: Can't find dest dev %d", __func__, dest); ++ goto exit_prune_path; ++ } ++ ++ lnode_hop = gen_lnode(dest_dev, search_dev_id, lnode_hop); ++ ++ list_for_each_entry_reverse(search_node, route_list, link) { ++ list_for_each_entry(bus_node, &search_node->node_list, link) { ++ unsigned int i; ++ for (i = 0; i < bus_node->node_info->num_connections; ++ i++) { ++ if (bus_node->node_info->connections[i] == ++ search_dev_id) { ++ dest_dev = bus_find_device( ++ &msm_bus_type, ++ NULL, ++ (void *) ++ &bus_node->node_info-> ++ id, ++ msm_bus_device_match_adhoc); ++ ++ if (!dest_dev) { ++ lnode_hop = -1; ++ goto reset_links; ++ } ++ ++ lnode_hop = gen_lnode(dest_dev, ++ search_dev_id, ++ lnode_hop); ++ search_dev_id = ++ bus_node->node_info->id; ++ break; ++ } ++ } ++ } ++ } ++reset_links: ++ list_for_each_entry_safe(search_node, temp_search_node, route_list, ++ link) { ++ list_for_each_entry(bus_node, &search_node->node_list, ++ link) ++ bus_node->node_info->is_traversed = false; ++ ++ list_del(&search_node->link); ++ kfree(search_node); ++ } ++ ++ list_for_each_safe(bl_list, temp_bl_list, black_list) ++ list_del(bl_list); ++ ++exit_prune_path: ++ return lnode_hop; ++} ++ ++static void setup_bl_list(struct msm_bus_node_device_type *node, ++ struct list_head *black_list) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < node->node_info->num_blist; i++) { ++ struct msm_bus_node_device_type *bdev; ++ bdev = node->node_info->black_connections[i]->platform_data; ++ list_add_tail(&bdev->link, black_list); ++ } ++} ++ ++static int getpath(int src, int dest) ++{ ++ struct list_head traverse_list; ++ struct list_head edge_list; ++ struct list_head route_list; ++ struct list_head black_list; ++ struct device *src_dev = bus_find_device(&msm_bus_type, NULL, ++ (void *) &src, ++ msm_bus_device_match_adhoc); ++ struct msm_bus_node_device_type *src_node; ++ struct bus_search_type *search_node; ++ int found = 0; ++ int depth_index = 0; ++ int first_hop = -1; ++ ++ INIT_LIST_HEAD(&traverse_list); ++ INIT_LIST_HEAD(&edge_list); ++ INIT_LIST_HEAD(&route_list); ++ INIT_LIST_HEAD(&black_list); ++ ++ if (!src_dev) { ++ MSM_BUS_ERR("%s: Cannot locate src dev %d", __func__, src); ++ goto exit_getpath; ++ } ++ ++ src_node = src_dev->platform_data; ++ if (!src_node) { ++ MSM_BUS_ERR("%s:Fatal, Source dev %d not found", __func__, src); ++ goto exit_getpath; ++ } ++ list_add_tail(&src_node->link, &traverse_list); ++ ++ while ((!found && !list_empty(&traverse_list))) { ++ struct msm_bus_node_device_type *bus_node = NULL; ++ /* Locate dest_id in the traverse list */ ++ list_for_each_entry(bus_node, &traverse_list, link) { ++ if (bus_node->node_info->id == dest) { ++ found = 1; ++ break; ++ } ++ } ++ ++ if (!found) { ++ unsigned int i; ++ /* Setup the new edge list */ ++ list_for_each_entry(bus_node, &traverse_list, link) { ++ /* Setup list of black-listed nodes */ ++ setup_bl_list(bus_node, &black_list); ++ ++ for (i = 0; i < bus_node->node_info-> ++ num_connections; i++) { ++ bool skip; ++ struct msm_bus_node_device_type ++ *node_conn; ++ node_conn = bus_node->node_info-> ++ dev_connections[i]-> ++ platform_data; ++ if (node_conn->node_info-> ++ is_traversed) { ++ MSM_BUS_ERR("Circ Path %d\n", ++ node_conn->node_info->id); ++ goto reset_traversed; ++ } ++ skip = chk_bl_list(&black_list, ++ bus_node->node_info-> ++ connections[i]); ++ if (!skip) { ++ list_add_tail(&node_conn->link, ++ &edge_list); ++ node_conn->node_info-> ++ is_traversed = true; ++ } ++ } ++ } ++ ++ /* Keep tabs of the previous search list */ ++ search_node = kzalloc(sizeof(struct bus_search_type), ++ GFP_KERNEL); ++ INIT_LIST_HEAD(&search_node->node_list); ++ list_splice_init(&traverse_list, ++ &search_node->node_list); ++ /* Add the previous search list to a route list */ ++ list_add_tail(&search_node->link, &route_list); ++ /* Advancing the list depth */ ++ depth_index++; ++ list_splice_init(&edge_list, &traverse_list); ++ } ++ } ++reset_traversed: ++ copy_remaining_nodes(&edge_list, &traverse_list, &route_list); ++ first_hop = prune_path(&route_list, dest, src, &black_list, found); ++ ++exit_getpath: ++ return first_hop; ++} ++ ++static uint64_t arbitrate_bus_req(struct msm_bus_node_device_type *bus_dev, ++ int ctx) ++{ ++ int i; ++ uint64_t max_ib = 0; ++ uint64_t sum_ab = 0; ++ uint64_t bw_max_hz; ++ struct msm_bus_node_device_type *fab_dev = NULL; ++ uint32_t util_fact = 0; ++ uint32_t vrail_comp = 0; ++ ++ /* Find max ib */ ++ for (i = 0; i < bus_dev->num_lnodes; i++) { ++ max_ib = max(max_ib, bus_dev->lnode_list[i].lnode_ib[ctx]); ++ sum_ab += bus_dev->lnode_list[i].lnode_ab[ctx]; ++ } ++ /* ++ * Account for Util factor and vrail comp. The new aggregation ++ * formula is: ++ * Freq_hz = max((sum(ab) * util_fact)/num_chan, max(ib)/vrail_comp) ++ * / bus-width ++ * util_fact and vrail comp are obtained from fabric/Node's dts ++ * properties. ++ * They default to 100 if absent. ++ */ ++ fab_dev = bus_dev->node_info->bus_device->platform_data; ++ /* Don't do this for virtual fabrics */ ++ if (fab_dev && fab_dev->fabdev) { ++ util_fact = bus_dev->node_info->util_fact ? ++ bus_dev->node_info->util_fact : ++ fab_dev->fabdev->util_fact; ++ vrail_comp = bus_dev->node_info->vrail_comp ? ++ bus_dev->node_info->vrail_comp : ++ fab_dev->fabdev->vrail_comp; ++ sum_ab *= util_fact; ++ sum_ab = msm_bus_div64(100, sum_ab); ++ max_ib *= 100; ++ max_ib = msm_bus_div64(vrail_comp, max_ib); ++ } ++ ++ /* Account for multiple channels if any */ ++ if (bus_dev->node_info->num_qports > 1) ++ sum_ab = msm_bus_div64(bus_dev->node_info->num_qports, ++ sum_ab); ++ ++ if (!bus_dev->node_info->buswidth) { ++ MSM_BUS_WARN("No bus width found for %d. Using default\n", ++ bus_dev->node_info->id); ++ bus_dev->node_info->buswidth = 8; ++ } ++ ++ bw_max_hz = max(max_ib, sum_ab); ++ bw_max_hz = msm_bus_div64(bus_dev->node_info->buswidth, ++ bw_max_hz); ++ ++ return bw_max_hz; ++} ++ ++static void del_inp_list(struct list_head *list) ++{ ++ struct rule_update_path_info *rule_node; ++ struct rule_update_path_info *rule_node_tmp; ++ ++ list_for_each_entry_safe(rule_node, rule_node_tmp, list, link) ++ list_del(&rule_node->link); ++} ++ ++static void del_op_list(struct list_head *list) ++{ ++ struct rule_apply_rcm_info *rule; ++ struct rule_apply_rcm_info *rule_tmp; ++ ++ list_for_each_entry_safe(rule, rule_tmp, list, link) ++ list_del(&rule->link); ++} ++ ++static int msm_bus_apply_rules(struct list_head *list, bool after_clk_commit) ++{ ++ struct rule_apply_rcm_info *rule; ++ struct device *dev = NULL; ++ struct msm_bus_node_device_type *dev_info = NULL; ++ int ret = 0; ++ bool throttle_en = false; ++ ++ list_for_each_entry(rule, list, link) { ++ if (!rule) ++ break; ++ ++ if (rule && (rule->after_clk_commit != after_clk_commit)) ++ continue; ++ ++ dev = bus_find_device(&msm_bus_type, NULL, ++ (void *) &rule->id, ++ msm_bus_device_match_adhoc); ++ ++ if (!dev) { ++ MSM_BUS_ERR("Can't find dev node for %d", rule->id); ++ continue; ++ } ++ dev_info = dev->platform_data; ++ ++ throttle_en = ((rule->throttle == THROTTLE_ON) ? true : false); ++ ret = msm_bus_enable_limiter(dev_info, throttle_en, ++ rule->lim_bw); ++ if (ret) ++ MSM_BUS_ERR("Failed to set limiter for %d", rule->id); ++ } ++ ++ return ret; ++} ++ ++static uint64_t get_node_aggab(struct msm_bus_node_device_type *bus_dev) ++{ ++ int i; ++ int ctx; ++ uint64_t max_agg_ab = 0; ++ uint64_t agg_ab = 0; ++ ++ for (ctx = 0; ctx < NUM_CTX; ctx++) { ++ for (i = 0; i < bus_dev->num_lnodes; i++) ++ agg_ab += bus_dev->lnode_list[i].lnode_ab[ctx]; ++ ++ if (bus_dev->node_info->num_qports > 1) ++ agg_ab = msm_bus_div64(bus_dev->node_info->num_qports, ++ agg_ab); ++ ++ max_agg_ab = max(max_agg_ab, agg_ab); ++ } ++ ++ return max_agg_ab; ++} ++ ++static uint64_t get_node_ib(struct msm_bus_node_device_type *bus_dev) ++{ ++ int i; ++ int ctx; ++ uint64_t max_ib = 0; ++ ++ for (ctx = 0; ctx < NUM_CTX; ctx++) { ++ for (i = 0; i < bus_dev->num_lnodes; i++) ++ max_ib = max(max_ib, ++ bus_dev->lnode_list[i].lnode_ib[ctx]); ++ } ++ return max_ib; ++} ++ ++static int update_path(int src, int dest, uint64_t req_ib, uint64_t req_bw, ++ uint64_t cur_ib, uint64_t cur_bw, int src_idx, int ctx) ++{ ++ struct device *src_dev = NULL; ++ struct device *next_dev = NULL; ++ struct link_node *lnode = NULL; ++ struct msm_bus_node_device_type *dev_info = NULL; ++ int curr_idx; ++ int ret = 0; ++ int *dirty_nodes = NULL; ++ int num_dirty = 0; ++ struct rule_update_path_info *rule_node; ++ bool rules_registered = msm_rule_are_rules_registered(); ++ ++ src_dev = bus_find_device(&msm_bus_type, NULL, ++ (void *) &src, ++ msm_bus_device_match_adhoc); ++ ++ if (!src_dev) { ++ MSM_BUS_ERR("%s: Can't find source device %d", __func__, src); ++ ret = -ENODEV; ++ goto exit_update_path; ++ } ++ ++ next_dev = src_dev; ++ ++ if (src_idx < 0) { ++ MSM_BUS_ERR("%s: Invalid lnode idx %d", __func__, src_idx); ++ ret = -ENXIO; ++ goto exit_update_path; ++ } ++ curr_idx = src_idx; ++ ++ INIT_LIST_HEAD(&input_list); ++ INIT_LIST_HEAD(&apply_list); ++ ++ while (next_dev) { ++ dev_info = next_dev->platform_data; ++ ++ if (curr_idx >= dev_info->num_lnodes) { ++ MSM_BUS_ERR("%s: Invalid lnode Idx %d num lnodes %d", ++ __func__, curr_idx, dev_info->num_lnodes); ++ ret = -ENXIO; ++ goto exit_update_path; ++ } ++ ++ lnode = &dev_info->lnode_list[curr_idx]; ++ lnode->lnode_ib[ctx] = req_ib; ++ lnode->lnode_ab[ctx] = req_bw; ++ ++ dev_info->cur_clk_hz[ctx] = arbitrate_bus_req(dev_info, ctx); ++ ++ /* Start updating the clocks at the first hop. ++ * Its ok to figure out the aggregated ++ * request at this node. ++ */ ++ if (src_dev != next_dev) { ++ ret = msm_bus_update_clks(dev_info, ctx, &dirty_nodes, ++ &num_dirty); ++ if (ret) { ++ MSM_BUS_ERR("%s: Failed to update clks dev %d", ++ __func__, dev_info->node_info->id); ++ goto exit_update_path; ++ } ++ } ++ ++ ret = msm_bus_update_bw(dev_info, ctx, req_bw, &dirty_nodes, ++ &num_dirty); ++ if (ret) { ++ MSM_BUS_ERR("%s: Failed to update bw dev %d", ++ __func__, dev_info->node_info->id); ++ goto exit_update_path; ++ } ++ ++ if (rules_registered) { ++ rule_node = &dev_info->node_info->rule; ++ rule_node->id = dev_info->node_info->id; ++ rule_node->ib = get_node_ib(dev_info); ++ rule_node->ab = get_node_aggab(dev_info); ++ rule_node->clk = max(dev_info->cur_clk_hz[ACTIVE_CTX], ++ dev_info->cur_clk_hz[DUAL_CTX]); ++ list_add_tail(&rule_node->link, &input_list); ++ } ++ ++ next_dev = lnode->next_dev; ++ curr_idx = lnode->next; ++ } ++ ++ if (rules_registered) { ++ msm_rules_update_path(&input_list, &apply_list); ++ msm_bus_apply_rules(&apply_list, false); ++ } ++ ++ msm_bus_commit_data(dirty_nodes, ctx, num_dirty); ++ ++ if (rules_registered) { ++ msm_bus_apply_rules(&apply_list, true); ++ del_inp_list(&input_list); ++ del_op_list(&apply_list); ++ } ++exit_update_path: ++ return ret; ++} ++ ++static int remove_path(int src, int dst, uint64_t cur_ib, uint64_t cur_ab, ++ int src_idx, int active_only) ++{ ++ struct device *src_dev = NULL; ++ struct device *next_dev = NULL; ++ struct link_node *lnode = NULL; ++ struct msm_bus_node_device_type *dev_info = NULL; ++ int ret = 0; ++ int cur_idx = src_idx; ++ int next_idx; ++ ++ /* Update the current path to zero out all request from ++ * this cient on all paths ++ */ ++ ++ ret = update_path(src, dst, 0, 0, cur_ib, cur_ab, src_idx, ++ active_only); ++ if (ret) { ++ MSM_BUS_ERR("%s: Error zeroing out path ctx %d", ++ __func__, ACTIVE_CTX); ++ goto exit_remove_path; ++ } ++ ++ src_dev = bus_find_device(&msm_bus_type, NULL, ++ (void *) &src, ++ msm_bus_device_match_adhoc); ++ if (!src_dev) { ++ MSM_BUS_ERR("%s: Can't find source device %d", __func__, src); ++ ret = -ENODEV; ++ goto exit_remove_path; ++ } ++ ++ next_dev = src_dev; ++ ++ while (next_dev) { ++ dev_info = next_dev->platform_data; ++ lnode = &dev_info->lnode_list[cur_idx]; ++ next_idx = lnode->next; ++ next_dev = lnode->next_dev; ++ remove_lnode(dev_info, cur_idx); ++ cur_idx = next_idx; ++ } ++ ++exit_remove_path: ++ return ret; ++} ++ ++static void getpath_debug(int src, int curr, int active_only) ++{ ++ struct device *dev_node; ++ struct device *dev_it; ++ unsigned int hop = 1; ++ int idx; ++ struct msm_bus_node_device_type *devinfo; ++ int i; ++ ++ dev_node = bus_find_device(&msm_bus_type, NULL, ++ (void *) &src, ++ msm_bus_device_match_adhoc); ++ ++ if (!dev_node) { ++ MSM_BUS_ERR("SRC NOT FOUND %d", src); ++ return; ++ } ++ ++ idx = curr; ++ devinfo = dev_node->platform_data; ++ dev_it = dev_node; ++ ++ MSM_BUS_ERR("Route list Src %d", src); ++ while (dev_it) { ++ struct msm_bus_node_device_type *busdev = ++ devinfo->node_info->bus_device->platform_data; ++ ++ MSM_BUS_ERR("Hop[%d] at Device %d ctx %d", hop, ++ devinfo->node_info->id, active_only); ++ ++ for (i = 0; i < NUM_CTX; i++) { ++ MSM_BUS_ERR("dev info sel ib %llu", ++ devinfo->cur_clk_hz[i]); ++ MSM_BUS_ERR("dev info sel ab %llu", ++ devinfo->node_ab.ab[i]); ++ } ++ ++ dev_it = devinfo->lnode_list[idx].next_dev; ++ idx = devinfo->lnode_list[idx].next; ++ if (dev_it) ++ devinfo = dev_it->platform_data; ++ ++ MSM_BUS_ERR("Bus Device %d", busdev->node_info->id); ++ MSM_BUS_ERR("Bus Clock %llu", busdev->clk[active_only].rate); ++ ++ if (idx < 0) ++ break; ++ hop++; ++ } ++} ++ ++static void unregister_client_adhoc(uint32_t cl) ++{ ++ int i; ++ struct msm_bus_scale_pdata *pdata; ++ int lnode, src, curr, dest; ++ uint64_t cur_clk, cur_bw; ++ struct msm_bus_client *client; ++ ++ mutex_lock(&msm_bus_adhoc_lock); ++ if (!cl) { ++ MSM_BUS_ERR("%s: Null cl handle passed unregister\n", ++ __func__); ++ goto exit_unregister_client; ++ } ++ client = handle_list.cl_list[cl]; ++ pdata = client->pdata; ++ if (!pdata) { ++ MSM_BUS_ERR("%s: Null pdata passed to unregister\n", ++ __func__); ++ goto exit_unregister_client; ++ } ++ ++ curr = client->curr; ++ if (curr >= pdata->num_usecases) { ++ MSM_BUS_ERR("Invalid index Defaulting curr to 0"); ++ curr = 0; ++ } ++ ++ MSM_BUS_DBG("%s: Unregistering client %p", __func__, client); ++ ++ for (i = 0; i < pdata->usecase->num_paths; i++) { ++ src = client->pdata->usecase[curr].vectors[i].src; ++ dest = client->pdata->usecase[curr].vectors[i].dst; ++ ++ lnode = client->src_pnode[i]; ++ cur_clk = client->pdata->usecase[curr].vectors[i].ib; ++ cur_bw = client->pdata->usecase[curr].vectors[i].ab; ++ remove_path(src, dest, cur_clk, cur_bw, lnode, ++ pdata->active_only); ++ } ++ msm_bus_dbg_client_data(client->pdata, MSM_BUS_DBG_UNREGISTER, cl); ++ kfree(client->src_pnode); ++ kfree(client); ++ handle_list.cl_list[cl] = NULL; ++exit_unregister_client: ++ mutex_unlock(&msm_bus_adhoc_lock); ++ return; ++} ++ ++static int alloc_handle_lst(int size) ++{ ++ int ret = 0; ++ struct msm_bus_client **t_cl_list; ++ ++ if (!handle_list.num_entries) { ++ t_cl_list = kzalloc(sizeof(struct msm_bus_client *) ++ * NUM_CL_HANDLES, GFP_KERNEL); ++ if (ZERO_OR_NULL_PTR(t_cl_list)) { ++ ret = -ENOMEM; ++ MSM_BUS_ERR("%s: Failed to allocate handles list", ++ __func__); ++ goto exit_alloc_handle_lst; ++ } ++ handle_list.cl_list = t_cl_list; ++ handle_list.num_entries += NUM_CL_HANDLES; ++ } else { ++ t_cl_list = krealloc(handle_list.cl_list, ++ sizeof(struct msm_bus_client *) * ++ handle_list.num_entries + NUM_CL_HANDLES, ++ GFP_KERNEL); ++ if (ZERO_OR_NULL_PTR(t_cl_list)) { ++ ret = -ENOMEM; ++ MSM_BUS_ERR("%s: Failed to allocate handles list", ++ __func__); ++ goto exit_alloc_handle_lst; ++ } ++ ++ memset(&handle_list.cl_list[handle_list.num_entries], 0, ++ NUM_CL_HANDLES * sizeof(struct msm_bus_client *)); ++ handle_list.num_entries += NUM_CL_HANDLES; ++ handle_list.cl_list = t_cl_list; ++ } ++exit_alloc_handle_lst: ++ return ret; ++} ++ ++static uint32_t gen_handle(struct msm_bus_client *client) ++{ ++ uint32_t handle = 0; ++ int i; ++ int ret = 0; ++ ++ for (i = 0; i < handle_list.num_entries; i++) { ++ if (i && !handle_list.cl_list[i]) { ++ handle = i; ++ break; ++ } ++ } ++ ++ if (!handle) { ++ ret = alloc_handle_lst(NUM_CL_HANDLES); ++ ++ if (ret) { ++ MSM_BUS_ERR("%s: Failed to allocate handle list", ++ __func__); ++ goto exit_gen_handle; ++ } ++ handle = i + 1; ++ } ++ handle_list.cl_list[handle] = client; ++exit_gen_handle: ++ return handle; ++} ++ ++static uint32_t register_client_adhoc(struct msm_bus_scale_pdata *pdata) ++{ ++ int src, dest; ++ int i; ++ struct msm_bus_client *client = NULL; ++ int *lnode; ++ uint32_t handle = 0; ++ ++ mutex_lock(&msm_bus_adhoc_lock); ++ client = kzalloc(sizeof(struct msm_bus_client), GFP_KERNEL); ++ if (!client) { ++ MSM_BUS_ERR("%s: Error allocating client data", __func__); ++ goto exit_register_client; ++ } ++ client->pdata = pdata; ++ ++ lnode = kzalloc(pdata->usecase->num_paths * sizeof(int), GFP_KERNEL); ++ if (ZERO_OR_NULL_PTR(lnode)) { ++ MSM_BUS_ERR("%s: Error allocating pathnode ptr!", __func__); ++ goto exit_register_client; ++ } ++ client->src_pnode = lnode; ++ ++ for (i = 0; i < pdata->usecase->num_paths; i++) { ++ src = pdata->usecase->vectors[i].src; ++ dest = pdata->usecase->vectors[i].dst; ++ ++ if ((src < 0) || (dest < 0)) { ++ MSM_BUS_ERR("%s:Invalid src/dst.src %d dest %d", ++ __func__, src, dest); ++ goto exit_register_client; ++ } ++ ++ lnode[i] = getpath(src, dest); ++ if (lnode[i] < 0) { ++ MSM_BUS_ERR("%s:Failed to find path.src %d dest %d", ++ __func__, src, dest); ++ goto exit_register_client; ++ } ++ } ++ ++ handle = gen_handle(client); ++ msm_bus_dbg_client_data(client->pdata, MSM_BUS_DBG_REGISTER, ++ handle); ++ MSM_BUS_DBG("%s:Client handle %d %s", __func__, handle, ++ client->pdata->name); ++exit_register_client: ++ mutex_unlock(&msm_bus_adhoc_lock); ++ return handle; ++} ++ ++static int update_request_adhoc(uint32_t cl, unsigned int index) ++{ ++ int i, ret = 0; ++ struct msm_bus_scale_pdata *pdata; ++ int lnode, src, curr, dest; ++ uint64_t req_clk, req_bw, curr_clk, curr_bw; ++ struct msm_bus_client *client; ++ const char *test_cl = "Null"; ++ bool log_transaction = false; ++ ++ mutex_lock(&msm_bus_adhoc_lock); ++ ++ if (!cl) { ++ MSM_BUS_ERR("%s: Invalid client handle %d", __func__, cl); ++ ret = -ENXIO; ++ goto exit_update_request; ++ } ++ ++ client = handle_list.cl_list[cl]; ++ pdata = client->pdata; ++ if (!pdata) { ++ MSM_BUS_ERR("%s: Client data Null.[client didn't register]", ++ __func__); ++ ret = -ENXIO; ++ goto exit_update_request; ++ } ++ ++ if (index >= pdata->num_usecases) { ++ MSM_BUS_ERR("Client %u passed invalid index: %d\n", ++ cl, index); ++ ret = -ENXIO; ++ goto exit_update_request; ++ } ++ ++ if (client->curr == index) { ++ MSM_BUS_DBG("%s: Not updating client request idx %d unchanged", ++ __func__, index); ++ goto exit_update_request; ++ } ++ ++ curr = client->curr; ++ client->curr = index; ++ ++ if (!strcmp(test_cl, pdata->name)) ++ log_transaction = true; ++ ++ MSM_BUS_DBG("%s: cl: %u index: %d curr: %d num_paths: %d\n", __func__, ++ cl, index, client->curr, client->pdata->usecase->num_paths); ++ ++ for (i = 0; i < pdata->usecase->num_paths; i++) { ++ src = client->pdata->usecase[index].vectors[i].src; ++ dest = client->pdata->usecase[index].vectors[i].dst; ++ ++ lnode = client->src_pnode[i]; ++ req_clk = client->pdata->usecase[index].vectors[i].ib; ++ req_bw = client->pdata->usecase[index].vectors[i].ab; ++ if (curr < 0) { ++ curr_clk = 0; ++ curr_bw = 0; ++ } else { ++ curr_clk = client->pdata->usecase[curr].vectors[i].ib; ++ curr_bw = client->pdata->usecase[curr].vectors[i].ab; ++ MSM_BUS_DBG("%s:ab: %llu ib: %llu\n", __func__, ++ curr_bw, curr_clk); ++ } ++ ++ ret = update_path(src, dest, req_clk, req_bw, ++ curr_clk, curr_bw, lnode, pdata->active_only); ++ ++ if (ret) { ++ MSM_BUS_ERR("%s: Update path failed! %d ctx %d\n", ++ __func__, ret, ACTIVE_CTX); ++ goto exit_update_request; ++ } ++ ++ if (log_transaction) ++ getpath_debug(src, lnode, pdata->active_only); ++ } ++ msm_bus_dbg_client_data(client->pdata, index , cl); ++exit_update_request: ++ mutex_unlock(&msm_bus_adhoc_lock); ++ return ret; ++} ++ ++/** ++ * msm_bus_arb_setops_adhoc() : Setup the bus arbitration ops ++ * @ arb_ops: pointer to the arb ops. ++ */ ++void msm_bus_arb_setops_adhoc(struct msm_bus_arb_ops *arb_ops) ++{ ++ arb_ops->register_client = register_client_adhoc; ++ arb_ops->update_request = update_request_adhoc; ++ arb_ops->unregister_client = unregister_client_adhoc; ++} +--- /dev/null ++++ b/drivers/bus/msm_bus/msm_bus_bimc.c +@@ -0,0 +1,2112 @@ ++/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#define pr_fmt(fmt) "AXI: BIMC: %s(): " fmt, __func__ ++ ++#include ++#include ++#include "msm-bus-board.h" ++#include "msm_bus_core.h" ++#include "msm_bus_bimc.h" ++#include "msm_bus_adhoc.h" ++#include ++ ++enum msm_bus_bimc_slave_block { ++ SLAVE_BLOCK_RESERVED = 0, ++ SLAVE_BLOCK_SLAVE_WAY, ++ SLAVE_BLOCK_XPU, ++ SLAVE_BLOCK_ARBITER, ++ SLAVE_BLOCK_SCMO, ++}; ++ ++enum bke_sw { ++ BKE_OFF = 0, ++ BKE_ON = 1, ++}; ++ ++/* M_Generic */ ++ ++#define M_REG_BASE(b) ((b) + 0x00008000) ++ ++#define M_COMPONENT_INFO_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000000) ++enum bimc_m_component_info { ++ M_COMPONENT_INFO_RMSK = 0xffffff, ++ M_COMPONENT_INFO_INSTANCE_BMSK = 0xff0000, ++ M_COMPONENT_INFO_INSTANCE_SHFT = 0x10, ++ M_COMPONENT_INFO_SUB_TYPE_BMSK = 0xff00, ++ M_COMPONENT_INFO_SUB_TYPE_SHFT = 0x8, ++ M_COMPONENT_INFO_TYPE_BMSK = 0xff, ++ M_COMPONENT_INFO_TYPE_SHFT = 0x0, ++}; ++ ++#define M_CONFIG_INFO_0_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000020) ++enum bimc_m_config_info_0 { ++ M_CONFIG_INFO_0_RMSK = 0xff00ffff, ++ M_CONFIG_INFO_0_SYNC_MODE_BMSK = 0xff000000, ++ M_CONFIG_INFO_0_SYNC_MODE_SHFT = 0x18, ++ M_CONFIG_INFO_0_CONNECTION_TYPE_BMSK = 0xff00, ++ M_CONFIG_INFO_0_CONNECTION_TYPE_SHFT = 0x8, ++ M_CONFIG_INFO_0_FUNC_BMSK = 0xff, ++ M_CONFIG_INFO_0_FUNC_SHFT = 0x0, ++}; ++ ++#define M_CONFIG_INFO_1_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000030) ++enum bimc_m_config_info_1 { ++ M_CONFIG_INFO_1_RMSK = 0xffffffff, ++ M_CONFIG_INFO_1_SWAY_CONNECTIVITY_BMSK = 0xffffffff, ++ M_CONFIG_INFO_1_SWAY_CONNECTIVITY_SHFT = 0x0, ++}; ++ ++#define M_CONFIG_INFO_2_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000040) ++enum bimc_m_config_info_2 { ++ M_CONFIG_INFO_2_RMSK = 0xffffffff, ++ M_CONFIG_INFO_2_M_DATA_WIDTH_BMSK = 0xffff0000, ++ M_CONFIG_INFO_2_M_DATA_WIDTH_SHFT = 0x10, ++ M_CONFIG_INFO_2_M_TID_WIDTH_BMSK = 0xff00, ++ M_CONFIG_INFO_2_M_TID_WIDTH_SHFT = 0x8, ++ M_CONFIG_INFO_2_M_MID_WIDTH_BMSK = 0xff, ++ M_CONFIG_INFO_2_M_MID_WIDTH_SHFT = 0x0, ++}; ++ ++#define M_CONFIG_INFO_3_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000050) ++enum bimc_m_config_info_3 { ++ M_CONFIG_INFO_3_RMSK = 0xffffffff, ++ M_CONFIG_INFO_3_RCH_DEPTH_BMSK = 0xff000000, ++ M_CONFIG_INFO_3_RCH_DEPTH_SHFT = 0x18, ++ M_CONFIG_INFO_3_BCH_DEPTH_BMSK = 0xff0000, ++ M_CONFIG_INFO_3_BCH_DEPTH_SHFT = 0x10, ++ M_CONFIG_INFO_3_WCH_DEPTH_BMSK = 0xff00, ++ M_CONFIG_INFO_3_WCH_DEPTH_SHFT = 0x8, ++ M_CONFIG_INFO_3_ACH_DEPTH_BMSK = 0xff, ++ M_CONFIG_INFO_3_ACH_DEPTH_SHFT = 0x0, ++}; ++ ++#define M_CONFIG_INFO_4_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000060) ++enum bimc_m_config_info_4 { ++ M_CONFIG_INFO_4_RMSK = 0xffff, ++ M_CONFIG_INFO_4_REORDER_BUF_DEPTH_BMSK = 0xff00, ++ M_CONFIG_INFO_4_REORDER_BUF_DEPTH_SHFT = 0x8, ++ M_CONFIG_INFO_4_REORDER_TABLE_DEPTH_BMSK = 0xff, ++ M_CONFIG_INFO_4_REORDER_TABLE_DEPTH_SHFT = 0x0, ++}; ++ ++#define M_CONFIG_INFO_5_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000070) ++enum bimc_m_config_info_5 { ++ M_CONFIG_INFO_5_RMSK = 0x111, ++ M_CONFIG_INFO_5_MP2ARB_PIPELINE_EN_BMSK = 0x100, ++ M_CONFIG_INFO_5_MP2ARB_PIPELINE_EN_SHFT = 0x8, ++ M_CONFIG_INFO_5_MPBUF_PIPELINE_EN_BMSK = 0x10, ++ M_CONFIG_INFO_5_MPBUF_PIPELINE_EN_SHFT = 0x4, ++ M_CONFIG_INFO_5_M2MP_PIPELINE_EN_BMSK = 0x1, ++ M_CONFIG_INFO_5_M2MP_PIPELINE_EN_SHFT = 0x0, ++}; ++ ++#define M_INT_STATUS_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000100) ++enum bimc_m_int_status { ++ M_INT_STATUS_RMSK = 0x3, ++}; ++ ++#define M_INT_CLR_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000108) ++enum bimc_m_int_clr { ++ M_INT_CLR_RMSK = 0x3, ++}; ++ ++#define M_INT_EN_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x0000010c) ++enum bimc_m_int_en { ++ M_INT_EN_RMSK = 0x3, ++}; ++ ++#define M_CLK_CTRL_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000200) ++enum bimc_m_clk_ctrl { ++ M_CLK_CTRL_RMSK = 0x3, ++ M_CLK_CTRL_MAS_CLK_GATING_EN_BMSK = 0x2, ++ M_CLK_CTRL_MAS_CLK_GATING_EN_SHFT = 0x1, ++ M_CLK_CTRL_CORE_CLK_GATING_EN_BMSK = 0x1, ++ M_CLK_CTRL_CORE_CLK_GATING_EN_SHFT = 0x0, ++}; ++ ++#define M_MODE_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000210) ++enum bimc_m_mode { ++ M_MODE_RMSK = 0xf0000011, ++ M_MODE_WR_GATHER_BEATS_BMSK = 0xf0000000, ++ M_MODE_WR_GATHER_BEATS_SHFT = 0x1c, ++ M_MODE_NARROW_WR_BMSK = 0x10, ++ M_MODE_NARROW_WR_SHFT = 0x4, ++ M_MODE_ORDERING_MODEL_BMSK = 0x1, ++ M_MODE_ORDERING_MODEL_SHFT = 0x0, ++}; ++ ++#define M_PRIOLVL_OVERRIDE_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000230) ++enum bimc_m_priolvl_override { ++ M_PRIOLVL_OVERRIDE_RMSK = 0x301, ++ M_PRIOLVL_OVERRIDE_BMSK = 0x300, ++ M_PRIOLVL_OVERRIDE_SHFT = 0x8, ++ M_PRIOLVL_OVERRIDE_OVERRIDE_PRIOLVL_BMSK = 0x1, ++ M_PRIOLVL_OVERRIDE_OVERRIDE_PRIOLVL_SHFT = 0x0, ++}; ++ ++#define M_RD_CMD_OVERRIDE_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000240) ++enum bimc_m_read_command_override { ++ M_RD_CMD_OVERRIDE_RMSK = 0x3071f7f, ++ M_RD_CMD_OVERRIDE_AREQPRIO_BMSK = 0x3000000, ++ M_RD_CMD_OVERRIDE_AREQPRIO_SHFT = 0x18, ++ M_RD_CMD_OVERRIDE_AMEMTYPE_BMSK = 0x70000, ++ M_RD_CMD_OVERRIDE_AMEMTYPE_SHFT = 0x10, ++ M_RD_CMD_OVERRIDE_ATRANSIENT_BMSK = 0x1000, ++ M_RD_CMD_OVERRIDE_ATRANSIENT_SHFT = 0xc, ++ M_RD_CMD_OVERRIDE_ASHARED_BMSK = 0x800, ++ M_RD_CMD_OVERRIDE_ASHARED_SHFT = 0xb, ++ M_RD_CMD_OVERRIDE_AREDIRECT_BMSK = 0x400, ++ M_RD_CMD_OVERRIDE_AREDIRECT_SHFT = 0xa, ++ M_RD_CMD_OVERRIDE_AOOO_BMSK = 0x200, ++ M_RD_CMD_OVERRIDE_AOOO_SHFT = 0x9, ++ M_RD_CMD_OVERRIDE_AINNERSHARED_BMSK = 0x100, ++ M_RD_CMD_OVERRIDE_AINNERSHARED_SHFT = 0x8, ++ M_RD_CMD_OVERRIDE_OVERRIDE_AREQPRIO_BMSK = 0x40, ++ M_RD_CMD_OVERRIDE_OVERRIDE_AREQPRIO_SHFT = 0x6, ++ M_RD_CMD_OVERRIDE_OVERRIDE_ATRANSIENT_BMSK = 0x20, ++ M_RD_CMD_OVERRIDE_OVERRIDE_ATRANSIENT_SHFT = 0x5, ++ M_RD_CMD_OVERRIDE_OVERRIDE_AMEMTYPE_BMSK = 0x10, ++ M_RD_CMD_OVERRIDE_OVERRIDE_AMEMTYPE_SHFT = 0x4, ++ M_RD_CMD_OVERRIDE_OVERRIDE_ASHARED_BMSK = 0x8, ++ M_RD_CMD_OVERRIDE_OVERRIDE_ASHARED_SHFT = 0x3, ++ M_RD_CMD_OVERRIDE_OVERRIDE_AREDIRECT_BMSK = 0x4, ++ M_RD_CMD_OVERRIDE_OVERRIDE_AREDIRECT_SHFT = 0x2, ++ M_RD_CMD_OVERRIDE_OVERRIDE_AOOO_BMSK = 0x2, ++ M_RD_CMD_OVERRIDE_OVERRIDE_AOOO_SHFT = 0x1, ++ M_RD_CMD_OVERRIDE_OVERRIDE_AINNERSHARED_BMSK = 0x1, ++ M_RD_CMD_OVERRIDE_OVERRIDE_AINNERSHARED_SHFT = 0x0, ++}; ++ ++#define M_WR_CMD_OVERRIDE_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000250) ++enum bimc_m_write_command_override { ++ M_WR_CMD_OVERRIDE_RMSK = 0x3071f7f, ++ M_WR_CMD_OVERRIDE_AREQPRIO_BMSK = 0x3000000, ++ M_WR_CMD_OVERRIDE_AREQPRIO_SHFT = 0x18, ++ M_WR_CMD_OVERRIDE_AMEMTYPE_BMSK = 0x70000, ++ M_WR_CMD_OVERRIDE_AMEMTYPE_SHFT = 0x10, ++ M_WR_CMD_OVERRIDE_ATRANSIENT_BMSK = 0x1000, ++ M_WR_CMD_OVERRIDE_ATRANSIENT_SHFT = 0xc, ++ M_WR_CMD_OVERRIDE_ASHARED_BMSK = 0x800, ++ M_WR_CMD_OVERRIDE_ASHARED_SHFT = 0xb, ++ M_WR_CMD_OVERRIDE_AREDIRECT_BMSK = 0x400, ++ M_WR_CMD_OVERRIDE_AREDIRECT_SHFT = 0xa, ++ M_WR_CMD_OVERRIDE_AOOO_BMSK = 0x200, ++ M_WR_CMD_OVERRIDE_AOOO_SHFT = 0x9, ++ M_WR_CMD_OVERRIDE_AINNERSHARED_BMSK = 0x100, ++ M_WR_CMD_OVERRIDE_AINNERSHARED_SHFT = 0x8, ++ M_WR_CMD_OVERRIDE_OVERRIDE_AREQPRIO_BMSK = 0x40, ++ M_WR_CMD_OVERRIDE_OVERRIDE_AREQPRIO_SHFT = 0x6, ++ M_WR_CMD_OVERRIDE_OVERRIDE_ATRANSIENT_BMSK = 0x20, ++ M_WR_CMD_OVERRIDE_OVERRIDE_ATRANSIENT_SHFT = 0x5, ++ M_WR_CMD_OVERRIDE_OVERRIDE_AMEMTYPE_BMSK = 0x10, ++ M_WR_CMD_OVERRIDE_OVERRIDE_AMEMTYPE_SHFT = 0x4, ++ M_WR_CMD_OVERRIDE_OVERRIDE_ASHARED_BMSK = 0x8, ++ M_WR_CMD_OVERRIDE_OVERRIDE_ASHARED_SHFT = 0x3, ++ M_WR_CMD_OVERRIDE_OVERRIDE_AREDIRECT_BMSK = 0x4, ++ M_WR_CMD_OVERRIDE_OVERRIDE_AREDIRECT_SHFT = 0x2, ++ M_WR_CMD_OVERRIDE_OVERRIDE_AOOO_BMSK = 0x2, ++ M_WR_CMD_OVERRIDE_OVERRIDE_AOOO_SHFT = 0x1, ++ M_WR_CMD_OVERRIDE_OVERRIDE_AINNERSHARED_BMSK = 0x1, ++ M_WR_CMD_OVERRIDE_OVERRIDE_AINNERSHARED_SHFT = 0x0, ++}; ++ ++#define M_BKE_EN_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000300) ++enum bimc_m_bke_en { ++ M_BKE_EN_RMSK = 0x1, ++ M_BKE_EN_EN_BMSK = 0x1, ++ M_BKE_EN_EN_SHFT = 0x0, ++}; ++ ++/* Grant Period registers */ ++#define M_BKE_GP_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000304) ++enum bimc_m_bke_grant_period { ++ M_BKE_GP_RMSK = 0x3ff, ++ M_BKE_GP_GP_BMSK = 0x3ff, ++ M_BKE_GP_GP_SHFT = 0x0, ++}; ++ ++/* Grant count register. ++ * The Grant count register represents a signed 16 bit ++ * value, range 0-0x7fff ++ */ ++#define M_BKE_GC_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000308) ++enum bimc_m_bke_grant_count { ++ M_BKE_GC_RMSK = 0xffff, ++ M_BKE_GC_GC_BMSK = 0xffff, ++ M_BKE_GC_GC_SHFT = 0x0, ++}; ++ ++/* Threshold High Registers */ ++#define M_BKE_THH_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000320) ++enum bimc_m_bke_thresh_high { ++ M_BKE_THH_RMSK = 0xffff, ++ M_BKE_THH_THRESH_BMSK = 0xffff, ++ M_BKE_THH_THRESH_SHFT = 0x0, ++}; ++ ++/* Threshold Medium Registers */ ++#define M_BKE_THM_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000324) ++enum bimc_m_bke_thresh_medium { ++ M_BKE_THM_RMSK = 0xffff, ++ M_BKE_THM_THRESH_BMSK = 0xffff, ++ M_BKE_THM_THRESH_SHFT = 0x0, ++}; ++ ++/* Threshold Low Registers */ ++#define M_BKE_THL_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000328) ++enum bimc_m_bke_thresh_low { ++ M_BKE_THL_RMSK = 0xffff, ++ M_BKE_THL_THRESH_BMSK = 0xffff, ++ M_BKE_THL_THRESH_SHFT = 0x0, ++}; ++ ++#define M_BKE_HEALTH_0_CONFIG_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000340) ++enum bimc_m_bke_health_0 { ++ M_BKE_HEALTH_0_CONFIG_RMSK = 0x80000303, ++ M_BKE_HEALTH_0_CONFIG_LIMIT_CMDS_BMSK = 0x80000000, ++ M_BKE_HEALTH_0_CONFIG_LIMIT_CMDS_SHFT = 0x1f, ++ M_BKE_HEALTH_0_CONFIG_AREQPRIO_BMSK = 0x300, ++ M_BKE_HEALTH_0_CONFIG_AREQPRIO_SHFT = 0x8, ++ M_BKE_HEALTH_0_CONFIG_PRIOLVL_BMSK = 0x3, ++ M_BKE_HEALTH_0_CONFIG_PRIOLVL_SHFT = 0x0, ++}; ++ ++#define M_BKE_HEALTH_1_CONFIG_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000344) ++enum bimc_m_bke_health_1 { ++ M_BKE_HEALTH_1_CONFIG_RMSK = 0x80000303, ++ M_BKE_HEALTH_1_CONFIG_LIMIT_CMDS_BMSK = 0x80000000, ++ M_BKE_HEALTH_1_CONFIG_LIMIT_CMDS_SHFT = 0x1f, ++ M_BKE_HEALTH_1_CONFIG_AREQPRIO_BMSK = 0x300, ++ M_BKE_HEALTH_1_CONFIG_AREQPRIO_SHFT = 0x8, ++ M_BKE_HEALTH_1_CONFIG_PRIOLVL_BMSK = 0x3, ++ M_BKE_HEALTH_1_CONFIG_PRIOLVL_SHFT = 0x0, ++}; ++ ++#define M_BKE_HEALTH_2_CONFIG_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000348) ++enum bimc_m_bke_health_2 { ++ M_BKE_HEALTH_2_CONFIG_RMSK = 0x80000303, ++ M_BKE_HEALTH_2_CONFIG_LIMIT_CMDS_BMSK = 0x80000000, ++ M_BKE_HEALTH_2_CONFIG_LIMIT_CMDS_SHFT = 0x1f, ++ M_BKE_HEALTH_2_CONFIG_AREQPRIO_BMSK = 0x300, ++ M_BKE_HEALTH_2_CONFIG_AREQPRIO_SHFT = 0x8, ++ M_BKE_HEALTH_2_CONFIG_PRIOLVL_BMSK = 0x3, ++ M_BKE_HEALTH_2_CONFIG_PRIOLVL_SHFT = 0x0, ++}; ++ ++#define M_BKE_HEALTH_3_CONFIG_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x0000034c) ++enum bimc_m_bke_health_3 { ++ M_BKE_HEALTH_3_CONFIG_RMSK = 0x303, ++ M_BKE_HEALTH_3_CONFIG_AREQPRIO_BMSK = 0x300, ++ M_BKE_HEALTH_3_CONFIG_AREQPRIO_SHFT = 0x8, ++ M_BKE_HEALTH_3_CONFIG_PRIOLVL_BMSK = 0x3, ++ M_BKE_HEALTH_3_CONFIG_PRIOLVL_SHFT = 0x0, ++}; ++ ++#define M_BUF_STATUS_ADDR(b, n) \ ++ (M_REG_BASE(b) + (0x4000 * (n)) + 0x00000400) ++enum bimc_m_buf_status { ++ M_BUF_STATUS_RMSK = 0xf03f030, ++ M_BUF_STATUS_RCH_DATA_WR_FULL_BMSK = 0x8000000, ++ M_BUF_STATUS_RCH_DATA_WR_FULL_SHFT = 0x1b, ++ M_BUF_STATUS_RCH_DATA_WR_EMPTY_BMSK = 0x4000000, ++ M_BUF_STATUS_RCH_DATA_WR_EMPTY_SHFT = 0x1a, ++ M_BUF_STATUS_RCH_CTRL_WR_FULL_BMSK = 0x2000000, ++ M_BUF_STATUS_RCH_CTRL_WR_FULL_SHFT = 0x19, ++ M_BUF_STATUS_RCH_CTRL_WR_EMPTY_BMSK = 0x1000000, ++ M_BUF_STATUS_RCH_CTRL_WR_EMPTY_SHFT = 0x18, ++ M_BUF_STATUS_BCH_WR_FULL_BMSK = 0x20000, ++ M_BUF_STATUS_BCH_WR_FULL_SHFT = 0x11, ++ M_BUF_STATUS_BCH_WR_EMPTY_BMSK = 0x10000, ++ M_BUF_STATUS_BCH_WR_EMPTY_SHFT = 0x10, ++ M_BUF_STATUS_WCH_DATA_RD_FULL_BMSK = 0x8000, ++ M_BUF_STATUS_WCH_DATA_RD_FULL_SHFT = 0xf, ++ M_BUF_STATUS_WCH_DATA_RD_EMPTY_BMSK = 0x4000, ++ M_BUF_STATUS_WCH_DATA_RD_EMPTY_SHFT = 0xe, ++ M_BUF_STATUS_WCH_CTRL_RD_FULL_BMSK = 0x2000, ++ M_BUF_STATUS_WCH_CTRL_RD_FULL_SHFT = 0xd, ++ M_BUF_STATUS_WCH_CTRL_RD_EMPTY_BMSK = 0x1000, ++ M_BUF_STATUS_WCH_CTRL_RD_EMPTY_SHFT = 0xc, ++ M_BUF_STATUS_ACH_RD_FULL_BMSK = 0x20, ++ M_BUF_STATUS_ACH_RD_FULL_SHFT = 0x5, ++ M_BUF_STATUS_ACH_RD_EMPTY_BMSK = 0x10, ++ M_BUF_STATUS_ACH_RD_EMPTY_SHFT = 0x4, ++}; ++/*BIMC Generic */ ++ ++#define S_REG_BASE(b) ((b) + 0x00048000) ++ ++#define S_COMPONENT_INFO_ADDR(b, n) \ ++ (S_REG_BASE(b) + (0x8000 * (n)) + 0x00000000) ++enum bimc_s_component_info { ++ S_COMPONENT_INFO_RMSK = 0xffffff, ++ S_COMPONENT_INFO_INSTANCE_BMSK = 0xff0000, ++ S_COMPONENT_INFO_INSTANCE_SHFT = 0x10, ++ S_COMPONENT_INFO_SUB_TYPE_BMSK = 0xff00, ++ S_COMPONENT_INFO_SUB_TYPE_SHFT = 0x8, ++ S_COMPONENT_INFO_TYPE_BMSK = 0xff, ++ S_COMPONENT_INFO_TYPE_SHFT = 0x0, ++}; ++ ++#define S_HW_INFO_ADDR(b, n) \ ++ (S_REG_BASE(b) + (0x80000 * (n)) + 0x00000010) ++enum bimc_s_hw_info { ++ S_HW_INFO_RMSK = 0xffffffff, ++ S_HW_INFO_MAJOR_BMSK = 0xff000000, ++ S_HW_INFO_MAJOR_SHFT = 0x18, ++ S_HW_INFO_BRANCH_BMSK = 0xff0000, ++ S_HW_INFO_BRANCH_SHFT = 0x10, ++ S_HW_INFO_MINOR_BMSK = 0xff00, ++ S_HW_INFO_MINOR_SHFT = 0x8, ++ S_HW_INFO_ECO_BMSK = 0xff, ++ S_HW_INFO_ECO_SHFT = 0x0, ++}; ++ ++ ++/* S_SCMO_GENERIC */ ++ ++#define S_SCMO_REG_BASE(b) ((b) + 0x00048000) ++ ++#define S_SCMO_CONFIG_INFO_0_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000020) ++enum bimc_s_scmo_config_info_0 { ++ S_SCMO_CONFIG_INFO_0_RMSK = 0xffffffff, ++ S_SCMO_CONFIG_INFO_0_DATA_WIDTH_BMSK = 0xffff0000, ++ S_SCMO_CONFIG_INFO_0_DATA_WIDTH_SHFT = 0x10, ++ S_SCMO_CONFIG_INFO_0_TID_WIDTH_BMSK = 0xff00, ++ S_SCMO_CONFIG_INFO_0_TID_WIDTH_SHFT = 0x8, ++ S_SCMO_CONFIG_INFO_0_MID_WIDTH_BMSK = 0xff, ++ S_SCMO_CONFIG_INFO_0_MID_WIDTH_SHFT = 0x0, ++}; ++ ++#define S_SCMO_CONFIG_INFO_1_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000030) ++enum bimc_s_scmo_config_info_1 { ++ S_SCMO_CONFIG_INFO_1_RMSK = 0xffffffff, ++ S_SCMO_CONFIG_INFO_1_MPORT_CONNECTIVITY_BMSK = 0xffffffff, ++ S_SCMO_CONFIG_INFO_1_MPORT_CONNECTIVITY_SHFT = 0x0, ++}; ++ ++#define S_SCMO_CONFIG_INFO_2_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000040) ++enum bimc_s_scmo_config_info_2 { ++ S_SCMO_CONFIG_INFO_2_RMSK = 0xff00ff, ++ S_SCMO_CONFIG_INFO_2_NUM_GLOBAL_MONS_BMSK = 0xff0000, ++ S_SCMO_CONFIG_INFO_2_NUM_GLOBAL_MONS_SHFT = 0x10, ++ S_SCMO_CONFIG_INFO_2_VMID_WIDTH_BMSK = 0xff, ++ S_SCMO_CONFIG_INFO_2_VMID_WIDTH_SHFT = 0x0, ++}; ++ ++#define S_SCMO_CONFIG_INFO_3_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000050) ++enum bimc_s_scmo_config_info_3 { ++ S_SCMO_CONFIG_INFO_3_RMSK = 0xffffffff, ++ S_SCMO_CONFIG_INFO_3_RCH0_CTRL_DEPTH_BMSK = 0xff000000, ++ S_SCMO_CONFIG_INFO_3_RCH0_CTRL_DEPTH_SHFT = 0x18, ++ S_SCMO_CONFIG_INFO_3_RCH0_DEPTH_BMSK = 0xff0000, ++ S_SCMO_CONFIG_INFO_3_RCH0_DEPTH_SHFT = 0x10, ++ S_SCMO_CONFIG_INFO_3_BCH_DEPTH_BMSK = 0xff00, ++ S_SCMO_CONFIG_INFO_3_BCH_DEPTH_SHFT = 0x8, ++ S_SCMO_CONFIG_INFO_3_WCH_DEPTH_BMSK = 0xff, ++ S_SCMO_CONFIG_INFO_3_WCH_DEPTH_SHFT = 0x0, ++}; ++ ++#define S_SCMO_CONFIG_INFO_4_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000060) ++enum bimc_s_scmo_config_info_4 { ++ S_SCMO_CONFIG_INFO_4_RMSK = 0xffff, ++ S_SCMO_CONFIG_INFO_4_RCH1_CTRL_DEPTH_BMSK = 0xff00, ++ S_SCMO_CONFIG_INFO_4_RCH1_CTRL_DEPTH_SHFT = 0x8, ++ S_SCMO_CONFIG_INFO_4_RCH1_DEPTH_BMSK = 0xff, ++ S_SCMO_CONFIG_INFO_4_RCH1_DEPTH_SHFT = 0x0, ++}; ++ ++#define S_SCMO_CONFIG_INFO_5_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000070) ++enum bimc_s_scmo_config_info_5 { ++ S_SCMO_CONFIG_INFO_5_RMSK = 0xffff, ++ S_SCMO_CONFIG_INFO_5_DPE_CQ_DEPTH_BMSK = 0xff00, ++ S_SCMO_CONFIG_INFO_5_DPE_CQ_DEPTH_SHFT = 0x8, ++ S_SCMO_CONFIG_INFO_5_DDR_BUS_WIDTH_BMSK = 0xff, ++ S_SCMO_CONFIG_INFO_5_DDR_BUS_WIDTH_SHFT = 0x0, ++}; ++ ++#define S_SCMO_CONFIG_INFO_6_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000080) ++enum bimc_s_scmo_config_info_6 { ++ S_SCMO_CONFIG_INFO_6_RMSK = 0x1111, ++ S_SCMO_CONFIG_INFO_6_WBUFC_PIPE_BMSK = 0x1000, ++ S_SCMO_CONFIG_INFO_6_WBUFC_PIPE_SHFT = 0xc, ++ S_SCMO_CONFIG_INFO_6_RDOPT_PIPE_BMSK = 0x100, ++ S_SCMO_CONFIG_INFO_6_RDOPT_PIPE_SHFT = 0x8, ++ S_SCMO_CONFIG_INFO_6_ACHAN_INTF_PIPE_BMSK = 0x10, ++ S_SCMO_CONFIG_INFO_6_ACHAN_INTF_PIPE_SHFT = 0x4, ++ S_SCMO_CONFIG_INFO_6_ADDR_DECODE_HT_BMSK = 0x1, ++ S_SCMO_CONFIG_INFO_6_ADDR_DECODE_HT_SHFT = 0x0, ++}; ++ ++#define S_SCMO_INT_STATUS_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000100) ++enum bimc_s_scmo_int_status { ++ S_SCMO_INT_STATUS_RMSK = 0x1, ++ S_SCMO_INT_STATUS_ERR_OCCURED_BMSK = 0x1, ++ S_SCMO_INT_STATUS_ERR_OCCURED_SHFT = 0x0, ++}; ++ ++#define S_SCMO_INT_CLR_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000108) ++enum bimc_s_scmo_int_clr { ++ S_SCMO_INT_CLR_RMSK = 0x1, ++ S_SCMO_INT_CLR_IRQ_CLR_BMSK = 0x1, ++ S_SCMO_INT_CLR_IRQ_CLR_SHFT = 0x0, ++}; ++ ++#define S_SCMO_INT_EN_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x0000010c) ++enum bimc_s_scmo_int_en { ++ S_SCMO_INT_EN_RMSK = 0x1, ++ S_SCMO_INT_EN_IRQ_EN_BMSK = 0x1, ++ S_SCMO_INT_EN_IRQ_EN_SHFT = 0x0, ++}; ++ ++#define S_SCMO_ESYN_ADDR_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000120) ++enum bimc_s_scmo_esyn_addr { ++ S_SCMO_ESYN_ADDR_RMSK = 0xffffffff, ++ S_SCMO_ESYN_ADDR_ESYN_ADDR_ERR_ADDR_BMSK = 0xffffffff, ++ S_SCMO_ESYN_ADDR_ESYN_ADDR_ERR_ADDR_SHFT = 0x0, ++}; ++ ++#define S_SCMO_ESYN_APACKET_0_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000128) ++enum bimc_s_scmo_esyn_apacket_0 { ++ S_SCMO_ESYN_APACKET_0_RMSK = 0xff1fffff, ++ S_SCMO_ESYN_APACKET_0_ERR_ATID_BMSK = 0xff000000, ++ S_SCMO_ESYN_APACKET_0_ERR_ATID_SHFT = 0x18, ++ S_SCMO_ESYN_APACKET_0_ERR_AVMID_BMSK = 0x1f0000, ++ S_SCMO_ESYN_APACKET_0_ERR_AVMID_SHFT = 0x10, ++ S_SCMO_ESYN_APACKET_0_ERR_AMID_BMSK = 0xffff, ++ S_SCMO_ESYN_APACKET_0_ERR_AMID_SHFT = 0x0, ++}; ++ ++#define S_SCMO_ESYN_APACKET_1_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x0000012c) ++enum bimc_s_scmo_esyn_apacket_1 { ++ S_SCMO_ESYN_APACKET_1_RMSK = 0x10ff117, ++ S_SCMO_ESYN_APACKET_1_ERR_CODE_BMSK = 0x1000000, ++ S_SCMO_ESYN_APACKET_1_ERR_CODE_SHFT = 0x18, ++ S_SCMO_ESYN_APACKET_1_ERR_ALEN_BMSK = 0xf0000, ++ S_SCMO_ESYN_APACKET_1_ERR_ALEN_SHFT = 0x10, ++ S_SCMO_ESYN_APACKET_1_ERR_ASIZE_BMSK = 0xe000, ++ S_SCMO_ESYN_APACKET_1_ERR_ASIZE_SHFT = 0xd, ++ S_SCMO_ESYN_APACKET_1_ERR_ABURST_BMSK = 0x1000, ++ S_SCMO_ESYN_APACKET_1_ERR_ABURST_SHFT = 0xc, ++ S_SCMO_ESYN_APACKET_1_ERR_AEXCLUSIVE_BMSK = 0x100, ++ S_SCMO_ESYN_APACKET_1_ERR_AEXCLUSIVE_SHFT = 0x8, ++ S_SCMO_ESYN_APACKET_1_ERR_APRONTS_BMSK = 0x10, ++ S_SCMO_ESYN_APACKET_1_ERR_APRONTS_SHFT = 0x4, ++ S_SCMO_ESYN_APACKET_1_ERR_AOOORD_BMSK = 0x4, ++ S_SCMO_ESYN_APACKET_1_ERR_AOOORD_SHFT = 0x2, ++ S_SCMO_ESYN_APACKET_1_ERR_AOOOWR_BMSK = 0x2, ++ S_SCMO_ESYN_APACKET_1_ERR_AOOOWR_SHFT = 0x1, ++ S_SCMO_ESYN_APACKET_1_ERR_AWRITE_BMSK = 0x1, ++ S_SCMO_ESYN_APACKET_1_ERR_AWRITE_SHFT = 0x0, ++}; ++ ++#define S_SCMO_CLK_CTRL_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000200) ++enum bimc_s_scmo_clk_ctrl { ++ S_SCMO_CLK_CTRL_RMSK = 0xffff1111, ++ S_SCMO_CLK_CTRL_PEN_CMD_CG_EN_BMSK = 0x10000, ++ S_SCMO_CLK_CTRL_PEN_CMD_CG_EN_SHFT = 0x10, ++ S_SCMO_CLK_CTRL_RCH_CG_EN_BMSK = 0x1000, ++ S_SCMO_CLK_CTRL_RCH_CG_EN_SHFT = 0xc, ++ S_SCMO_CLK_CTRL_FLUSH_CG_EN_BMSK = 0x100, ++ S_SCMO_CLK_CTRL_FLUSH_CG_EN_SHFT = 0x8, ++ S_SCMO_CLK_CTRL_WCH_CG_EN_BMSK = 0x10, ++ S_SCMO_CLK_CTRL_WCH_CG_EN_SHFT = 0x4, ++ S_SCMO_CLK_CTRL_ACH_CG_EN_BMSK = 0x1, ++ S_SCMO_CLK_CTRL_ACH_CG_EN_SHFT = 0x0, ++}; ++ ++#define S_SCMO_SLV_INTERLEAVE_CFG_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000400) ++enum bimc_s_scmo_slv_interleave_cfg { ++ S_SCMO_SLV_INTERLEAVE_CFG_RMSK = 0xff, ++ S_SCMO_SLV_INTERLEAVE_CFG_INTERLEAVE_CS1_BMSK = 0x10, ++ S_SCMO_SLV_INTERLEAVE_CFG_INTERLEAVE_CS1_SHFT = 0x4, ++ S_SCMO_SLV_INTERLEAVE_CFG_INTERLEAVE_CS0_BMSK = 0x1, ++ S_SCMO_SLV_INTERLEAVE_CFG_INTERLEAVE_CS0_SHFT = 0x0, ++}; ++ ++#define S_SCMO_ADDR_BASE_CSn_ADDR(b, n, o) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000410 + 0x4 * (o)) ++enum bimc_s_scmo_addr_base_csn { ++ S_SCMO_ADDR_BASE_CSn_RMSK = 0xffff, ++ S_SCMO_ADDR_BASE_CSn_MAXn = 1, ++ S_SCMO_ADDR_BASE_CSn_ADDR_BASE_BMSK = 0xfc, ++ S_SCMO_ADDR_BASE_CSn_ADDR_BASE_SHFT = 0x2, ++}; ++ ++#define S_SCMO_ADDR_MAP_CSn_ADDR(b, n, o) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000420 + 0x4 * (o)) ++enum bimc_s_scmo_addr_map_csn { ++ S_SCMO_ADDR_MAP_CSn_RMSK = 0xffff, ++ S_SCMO_ADDR_MAP_CSn_MAXn = 1, ++ S_SCMO_ADDR_MAP_CSn_RANK_EN_BMSK = 0x8000, ++ S_SCMO_ADDR_MAP_CSn_RANK_EN_SHFT = 0xf, ++ S_SCMO_ADDR_MAP_CSn_ADDR_MODE_BMSK = 0x1000, ++ S_SCMO_ADDR_MAP_CSn_ADDR_MODE_SHFT = 0xc, ++ S_SCMO_ADDR_MAP_CSn_BANK_SIZE_BMSK = 0x100, ++ S_SCMO_ADDR_MAP_CSn_BANK_SIZE_SHFT = 0x8, ++ S_SCMO_ADDR_MAP_CSn_ROW_SIZE_BMSK = 0x30, ++ S_SCMO_ADDR_MAP_CSn_ROW_SIZE_SHFT = 0x4, ++ S_SCMO_ADDR_MAP_CSn_COL_SIZE_BMSK = 0x3, ++ S_SCMO_ADDR_MAP_CSn_COL_SIZE_SHFT = 0x0, ++}; ++ ++#define S_SCMO_ADDR_MASK_CSn_ADDR(b, n, o) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000430 + 0x4 * (0)) ++enum bimc_s_scmo_addr_mask_csn { ++ S_SCMO_ADDR_MASK_CSn_RMSK = 0xffff, ++ S_SCMO_ADDR_MASK_CSn_MAXn = 1, ++ S_SCMO_ADDR_MASK_CSn_ADDR_MASK_BMSK = 0xfc, ++ S_SCMO_ADDR_MASK_CSn_ADDR_MASK_SHFT = 0x2, ++}; ++ ++#define S_SCMO_SLV_STATUS_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000450) ++enum bimc_s_scmo_slv_status { ++ S_SCMO_SLV_STATUS_RMSK = 0xff3, ++ S_SCMO_SLV_STATUS_GLOBAL_MONS_IN_USE_BMSK = 0xff0, ++ S_SCMO_SLV_STATUS_GLOBAL_MONS_IN_USE_SHFT = 0x4, ++ S_SCMO_SLV_STATUS_SLAVE_IDLE_BMSK = 0x3, ++ S_SCMO_SLV_STATUS_SLAVE_IDLE_SHFT = 0x0, ++}; ++ ++#define S_SCMO_CMD_BUF_CFG_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000500) ++enum bimc_s_scmo_cmd_buf_cfg { ++ S_SCMO_CMD_BUF_CFG_RMSK = 0xf1f, ++ S_SCMO_CMD_BUF_CFG_CMD_ORDERING_BMSK = 0x300, ++ S_SCMO_CMD_BUF_CFG_CMD_ORDERING_SHFT = 0x8, ++ S_SCMO_CMD_BUF_CFG_HP_CMD_AREQPRIO_MAP_BMSK = 0x10, ++ S_SCMO_CMD_BUF_CFG_HP_CMD_AREQPRIO_MAP_SHFT = 0x4, ++ S_SCMO_CMD_BUF_CFG_HP_CMD_Q_DEPTH_BMSK = 0x7, ++ S_SCMO_CMD_BUF_CFG_HP_CMD_Q_DEPTH_SHFT = 0x0, ++}; ++ ++#define S_SCM_CMD_BUF_STATUS_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000520) ++enum bimc_s_scm_cmd_buf_status { ++ S_SCMO_CMD_BUF_STATUS_RMSK = 0x77, ++ S_SCMO_CMD_BUF_STATUS_HP_CMD_BUF_ENTRIES_IN_USE_BMSK = 0x70, ++ S_SCMO_CMD_BUF_STATUS_HP_CMD_BUF_ENTRIES_IN_USE_SHFT = 0x4, ++ S_SCMO_CMD_BUF_STATUS_LP_CMD_BUF_ENTRIES_IN_USE_BMSK = 0x7, ++ S_SCMO_CMD_BUF_STATUS_LP_CMD_BUF_ENTRIES_IN_USE_SHFT = 0x0, ++}; ++ ++#define S_SCMO_RCH_SEL_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000540) ++enum bimc_s_scmo_rch_sel { ++ S_SCMO_RCH_SEL_RMSK = 0xffffffff, ++ S_SCMO_CMD_BUF_STATUS_RCH_PORTS_BMSK = 0xffffffff, ++ S_SCMO_CMD_BUF_STATUS_RCH_PORTS_SHFT = 0x0, ++}; ++ ++#define S_SCMO_RCH_BKPR_CFG_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000544) ++enum bimc_s_scmo_rch_bkpr_cfg { ++ S_SCMO_RCH_BKPR_CFG_RMSK = 0xffffffff, ++ S_SCMO_RCH_BKPR_CFG_RCH1_FIFO_BKPR_HI_TH_BMSK = 0x3f000000, ++ S_SCMO_RCH_BKPR_CFG_RCH1_FIFO_BKPR_HI_TH_SHFT = 0x18, ++ S_SCMO_RCH_BKPR_CFG_RCH1_FIFO_BKPR_LO_TH_BMSK = 0x3f0000, ++ S_SCMO_RCH_BKPR_CFG_RCH1_FIFO_BKPR_LO_TH_SHFT = 0x10, ++ S_SCMO_RCH_BKPR_CFG_RCH0_FIFO_BKPR_HI_TH_BMSK = 0x3f00, ++ S_SCMO_RCH_BKPR_CFG_RCH0_FIFO_BKPR_HI_TH_SHFT = 0x8, ++ S_SCMO_RCH_BKPR_CFG_RCH0_FIFO_BKPR_LO_TH_BMSK = 0x3f, ++ S_SCMO_RCH_BKPR_CFG_RCH0_FIFO_BKPR_LO_TH_SHFT = 0x0, ++}; ++ ++#define S_SCMO_RCH_STATUS_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000560) ++enum bimc_s_scmo_rch_status { ++ S_SCMO_RCH_STATUS_RMSK = 0x33333, ++ S_SCMO_RCH_STATUS_PRQ_FIFO_FULL_BMSK = 0x20000, ++ S_SCMO_RCH_STATUS_PRQ_FIFO_FULL_SHFT = 0x11, ++ S_SCMO_RCH_STATUS_PRQ_FIFO_EMPTY_BMSK = 0x10000, ++ S_SCMO_RCH_STATUS_PRQ_FIFO_EMPTY_SHFT = 0x10, ++ S_SCMO_RCH_STATUS_RCH1_QUAL_FIFO_FULL_BMSK = 0x2000, ++ S_SCMO_RCH_STATUS_RCH1_QUAL_FIFO_FULL_SHFT = 0xd, ++ S_SCMO_RCH_STATUS_RCH1_QUAL_FIFO_EMPTY_BMSK = 0x1000, ++ S_SCMO_RCH_STATUS_RCH1_QUAL_FIFO_EMPTY_SHFT = 0xc, ++ S_SCMO_RCH_STATUS_RCH1_DATA_FIFO_FULL_BMSK = 0x200, ++ S_SCMO_RCH_STATUS_RCH1_DATA_FIFO_FULL_SHFT = 0x9, ++ S_SCMO_RCH_STATUS_RCH1_DATA_FIFO_EMPTY_BMSK = 0x100, ++ S_SCMO_RCH_STATUS_RCH1_DATA_FIFO_EMPTY_SHFT = 0x8, ++ S_SCMO_RCH_STATUS_RCH0_QUAL_FIFO_FULL_BMSK = 0x20, ++ S_SCMO_RCH_STATUS_RCH0_QUAL_FIFO_FULL_SHFT = 0x5, ++ S_SCMO_RCH_STATUS_RCH0_QUAL_FIFO_EMPTY_BMSK = 0x10, ++ S_SCMO_RCH_STATUS_RCH0_QUAL_FIFO_EMPTY_SHFT = 0x4, ++ S_SCMO_RCH_STATUS_RCH0_DATA_FIFO_FULL_BMSK = 0x2, ++ S_SCMO_RCH_STATUS_RCH0_DATA_FIFO_FULL_SHFT = 0x1, ++ S_SCMO_RCH_STATUS_RCH0_DATA_FIFO_EMPTY_BMSK = 0x1, ++ S_SCMO_RCH_STATUS_RCH0_DATA_FIFO_EMPTY_SHFT = 0x0, ++}; ++ ++#define S_SCMO_WCH_BUF_CFG_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000580) ++enum bimc_s_scmo_wch_buf_cfg { ++ S_SCMO_WCH_BUF_CFG_RMSK = 0xff, ++ S_SCMO_WCH_BUF_CFG_WRITE_BLOCK_READ_BMSK = 0x10, ++ S_SCMO_WCH_BUF_CFG_WRITE_BLOCK_READ_SHFT = 0x4, ++ S_SCMO_WCH_BUF_CFG_COALESCE_EN_BMSK = 0x1, ++ S_SCMO_WCH_BUF_CFG_COALESCE_EN_SHFT = 0x0, ++}; ++ ++#define S_SCMO_WCH_STATUS_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x000005a0) ++enum bimc_s_scmo_wch_status { ++ S_SCMO_WCH_STATUS_RMSK = 0x333, ++ S_SCMO_WCH_STATUS_BRESP_FIFO_FULL_BMSK = 0x200, ++ S_SCMO_WCH_STATUS_BRESP_FIFO_FULL_SHFT = 0x9, ++ S_SCMO_WCH_STATUS_BRESP_FIFO_EMPTY_BMSK = 0x100, ++ S_SCMO_WCH_STATUS_BRESP_FIFO_EMPTY_SHFT = 0x8, ++ S_SCMO_WCH_STATUS_WDATA_FIFO_FULL_BMSK = 0x20, ++ S_SCMO_WCH_STATUS_WDATA_FIFO_FULL_SHFT = 0x5, ++ S_SCMO_WCH_STATUS_WDATA_FIFO_EMPTY_BMSK = 0x10, ++ S_SCMO_WCH_STATUS_WDATA_FIFO_EMPTY_SHFT = 0x4, ++ S_SCMO_WCH_STATUS_WBUF_FULL_BMSK = 0x2, ++ S_SCMO_WCH_STATUS_WBUF_FULL_SHFT = 0x1, ++ S_SCMO_WCH_STATUS_WBUF_EMPTY_BMSK = 0x1, ++ S_SCMO_WCH_STATUS_WBUF_EMPTY_SHFT = 0x0, ++}; ++ ++#define S_SCMO_FLUSH_CFG_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x000005c0) ++enum bimc_s_scmo_flush_cfg { ++ S_SCMO_FLUSH_CFG_RMSK = 0xffffffff, ++ S_SCMO_FLUSH_CFG_FLUSH_IN_ORDER_BMSK = 0x10000000, ++ S_SCMO_FLUSH_CFG_FLUSH_IN_ORDER_SHFT = 0x1c, ++ S_SCMO_FLUSH_CFG_FLUSH_IDLE_DELAY_BMSK = 0x3ff0000, ++ S_SCMO_FLUSH_CFG_FLUSH_IDLE_DELAY_SHFT = 0x10, ++ S_SCMO_FLUSH_CFG_FLUSH_UPPER_LIMIT_BMSK = 0xf00, ++ S_SCMO_FLUSH_CFG_FLUSH_UPPER_LIMIT_SHFT = 0x8, ++ S_SCMO_FLUSH_CFG_FLUSH_LOWER_LIMIT_BMSK = 0xf, ++ S_SCMO_FLUSH_CFG_FLUSH_LOWER_LIMIT_SHFT = 0x0, ++}; ++ ++#define S_SCMO_FLUSH_CMD_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x000005c4) ++enum bimc_s_scmo_flush_cmd { ++ S_SCMO_FLUSH_CMD_RMSK = 0xf, ++ S_SCMO_FLUSH_CMD_FLUSH_ALL_BUF_BMSK = 0x3, ++ S_SCMO_FLUSH_CMD_FLUSH_ALL_BUF_SHFT = 0x0, ++}; ++ ++#define S_SCMO_CMD_OPT_CFG0_ADDR(b, n) \ ++ (S_SCM0_REG_BASE(b) + (0x8000 * (n)) + 0x00000700) ++enum bimc_s_scmo_cmd_opt_cfg0 { ++ S_SCMO_CMD_OPT_CFG0_RMSK = 0xffffff, ++ S_SCMO_CMD_OPT_CFG0_IGNORE_BANK_UNAVL_BMSK = 0x100000, ++ S_SCMO_CMD_OPT_CFG0_IGNORE_BANK_UNAVL_SHFT = 0x14, ++ S_SCMO_CMD_OPT_CFG0_MASK_CMDOUT_PRI_BMSK = 0x10000, ++ S_SCMO_CMD_OPT_CFG0_MASK_CMDOUT_PRI_SHFT = 0x10, ++ S_SCMO_CMD_OPT_CFG0_DPE_CMD_REORDERING_BMSK = 0x1000, ++ S_SCMO_CMD_OPT_CFG0_DPE_CMD_REORDERING_SHFT = 0xc, ++ S_SCMO_CMD_OPT_CFG0_WR_OPT_EN_BMSK = 0x100, ++ S_SCMO_CMD_OPT_CFG0_WR_OPT_EN_SHFT = 0x8, ++ S_SCMO_CMD_OPT_CFG0_RD_OPT_EN_BMSK = 0x10, ++ S_SCMO_CMD_OPT_CFG0_RD_OPT_EN_SHFT = 0x4, ++ S_SCMO_CMD_OPT_CFG0_PAGE_MGMT_POLICY_BMSK = 0x1, ++ S_SCMO_CMD_OPT_CFG0_PAGE_MGMT_POLICY_SHFT = 0x0, ++}; ++ ++#define S_SCMO_CMD_OPT_CFG1_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000704) ++enum bimc_s_scmo_cmd_opt_cfg1 { ++ S_SCMO_CMD_OPT_CFG1_RMSK = 0xffffffff, ++ S_SCMO_CMD_OPT_CFG1_HSTP_CMD_TIMEOUT_BMSK = 0x1f000000, ++ S_SCMO_CMD_OPT_CFG1_HSTP_CMD_TIMEOUT_SHFT = 0x18, ++ S_SCMO_CMD_OPT_CFG1_HP_CMD_TIMEOUT_BMSK = 0x1f0000, ++ S_SCMO_CMD_OPT_CFG1_HP_CMD_TIMEOUT_SHFT = 0x10, ++ S_SCMO_CMD_OPT_CFG1_MP_CMD_TIMEOUT_BMSK = 0x1f00, ++ S_SCMO_CMD_OPT_CFG1_MP_CMD_TIMEOUT_SHFT = 0x8, ++ S_SCMO_CMD_OPT_CFG1_LP_CMD_TIMEOUT_BMSK = 0x1f, ++ S_SCMO_CMD_OPT_CFG1_LP_CMD_TIMEOUT_SHFT = 0x0, ++}; ++ ++#define S_SCMO_CMD_OPT_CFG2_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x00000708) ++enum bimc_s_scmo_cmd_opt_cfg2 { ++ S_SCMO_CMD_OPT_CFG2_RMSK = 0xff, ++ S_SCMO_CMD_OPT_CFG2_RWOPT_CMD_TIMEOUT_BMSK = 0xf, ++ S_SCMO_CMD_OPT_CFG2_RWOPT_CMD_TIMEOUT_SHFT = 0x0, ++}; ++ ++#define S_SCMO_CMD_OPT_CFG3_ADDR(b, n) \ ++ (S_SCMO_REG_BASE(b) + (0x8000 * (n)) + 0x0000070c) ++enum bimc_s_scmo_cmd_opt_cfg3 { ++ S_SCMO_CMD_OPT_CFG3_RMSK = 0xff, ++ S_SCMO_CMD_OPT_CFG3_FLUSH_CMD_TIMEOUT_BMSK = 0xf, ++ S_SCMO_CMD_OPT_CFG3_FLUSH_CMD_TIMEOUT_SHFT = 0x0, ++}; ++ ++/* S_SWAY_GENERIC */ ++#define S_SWAY_REG_BASE(b) ((b) + 0x00048000) ++ ++#define S_SWAY_CONFIG_INFO_0_ADDR(b, n) \ ++ (S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000020) ++enum bimc_s_sway_config_info_0 { ++ S_SWAY_CONFIG_INFO_0_RMSK = 0xff0000ff, ++ S_SWAY_CONFIG_INFO_0_SYNC_MODE_BMSK = 0xff000000, ++ S_SWAY_CONFIG_INFO_0_SYNC_MODE_SHFT = 0x18, ++ S_SWAY_CONFIG_INFO_0_FUNC_BMSK = 0xff, ++ S_SWAY_CONFIG_INFO_0_FUNC_SHFT = 0x0, ++}; ++ ++#define S_SWAY_CONFIG_INFO_1_ADDR(b, n) \ ++ (S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000030) ++enum bimc_s_sway_config_info_1 { ++ S_SWAY_CONFIG_INFO_1_RMSK = 0xffffffff, ++ S_SWAY_CONFIG_INFO_1_MPORT_CONNECTIVITY_BMSK = 0xffffffff, ++ S_SWAY_CONFIG_INFO_1_MPORT_CONNECTIVITY_SHFT = 0x0, ++}; ++ ++#define S_SWAY_CONFIG_INFO_2_ADDR(b, n) \ ++ (S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000040) ++enum bimc_s_sway_config_info_2 { ++ S_SWAY_CONFIG_INFO_2_RMSK = 0xffff0000, ++ S_SWAY_CONFIG_INFO_2_MPORT_CONNECTIVITY_BMSK = 0xffff0000, ++ S_SWAY_CONFIG_INFO_2_MPORT_CONNECTIVITY_SHFT = 0x10, ++}; ++ ++#define S_SWAY_CONFIG_INFO_3_ADDR(b, n) \ ++ (S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000050) ++enum bimc_s_sway_config_info_3 { ++ S_SWAY_CONFIG_INFO_3_RMSK = 0xffffffff, ++ S_SWAY_CONFIG_INFO_3_RCH0_DEPTH_BMSK = 0xff000000, ++ S_SWAY_CONFIG_INFO_3_RCH0_DEPTH_SHFT = 0x18, ++ S_SWAY_CONFIG_INFO_3_BCH_DEPTH_BMSK = 0xff0000, ++ S_SWAY_CONFIG_INFO_3_BCH_DEPTH_SHFT = 0x10, ++ S_SWAY_CONFIG_INFO_3_WCH_DEPTH_BMSK = 0xff, ++ S_SWAY_CONFIG_INFO_3_WCH_DEPTH_SHFT = 0x0, ++}; ++ ++#define S_SWAY_CONFIG_INFO_4_ADDR(b, n) \ ++ (S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000060) ++enum bimc_s_sway_config_info_4 { ++ S_SWAY_CONFIG_INFO_4_RMSK = 0x800000ff, ++ S_SWAY_CONFIG_INFO_4_DUAL_RCH_EN_BMSK = 0x80000000, ++ S_SWAY_CONFIG_INFO_4_DUAL_RCH_EN_SHFT = 0x1f, ++ S_SWAY_CONFIG_INFO_4_RCH1_DEPTH_BMSK = 0xff, ++ S_SWAY_CONFIG_INFO_4_RCH1_DEPTH_SHFT = 0x0, ++}; ++ ++#define S_SWAY_CONFIG_INFO_5_ADDR(b, n) \ ++ (S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000070) ++enum bimc_s_sway_config_info_5 { ++ S_SWAY_CONFIG_INFO_5_RMSK = 0x800000ff, ++ S_SWAY_CONFIG_INFO_5_QCH_EN_BMSK = 0x80000000, ++ S_SWAY_CONFIG_INFO_5_QCH_EN_SHFT = 0x1f, ++ S_SWAY_CONFIG_INFO_5_QCH_DEPTH_BMSK = 0xff, ++ S_SWAY_CONFIG_INFO_5_QCH_DEPTH_SHFT = 0x0, ++}; ++ ++#define S_SWAY_CONFIG_INFO_6_ADDR(b, n) \ ++ (S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000080) ++enum bimc_s_sway_config_info_6 { ++ S_SWAY_CONFIG_INFO_6_RMSK = 0x1, ++ S_SWAY_CONFIG_INFO_6_S2SW_PIPELINE_EN_BMSK = 0x1, ++ S_SWAY_CONFIG_INFO_6_S2SW_PIPELINE_EN_SHFT = 0x0, ++}; ++ ++#define S_SWAY_INT_STATUS_ADDR(b, n) \ ++ (S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000100) ++enum bimc_s_sway_int_status { ++ S_SWAY_INT_STATUS_RMSK = 0x3, ++ S_SWAY_INT_STATUS_RFU_BMSK = 0x3, ++ S_SWAY_INT_STATUS_RFU_SHFT = 0x0, ++}; ++ ++#define S_SWAY_INT_CLR_ADDR(b, n) \ ++ (S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000108) ++enum bimc_s_sway_int_clr { ++ S_SWAY_INT_CLR_RMSK = 0x3, ++ S_SWAY_INT_CLR_RFU_BMSK = 0x3, ++ S_SWAY_INT_CLR_RFU_SHFT = 0x0, ++}; ++ ++ ++#define S_SWAY_INT_EN_ADDR(b, n) \ ++ (S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x0000010c) ++enum bimc_s_sway_int_en { ++ S_SWAY_INT_EN_RMSK = 0x3, ++ S_SWAY_INT_EN_RFU_BMSK = 0x3, ++ S_SWAY_INT_EN_RFU_SHFT = 0x0, ++}; ++ ++#define S_SWAY_CLK_CTRL_ADDR(b, n) \ ++ (S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000200) ++enum bimc_s_sway_clk_ctrl { ++ S_SWAY_CLK_CTRL_RMSK = 0x3, ++ S_SWAY_CLK_CTRL_SLAVE_CLK_GATING_EN_BMSK = 0x2, ++ S_SWAY_CLK_CTRL_SLAVE_CLK_GATING_EN_SHFT = 0x1, ++ S_SWAY_CLK_CTRL_CORE_CLK_GATING_EN_BMSK = 0x1, ++ S_SWAY_CLK_CTRL_CORE_CLK_GATING_EN_SHFT = 0x0, ++}; ++ ++#define S_SWAY_RCH_SEL_ADDR(b, n) \ ++ (S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000210) ++enum bimc_s_sway_rch_sel { ++ S_SWAY_RCH_SEL_RMSK = 0x7f, ++ S_SWAY_RCH_SEL_UNUSED_BMSK = 0x7f, ++ S_SWAY_RCH_SEL_UNUSED_SHFT = 0x0, ++}; ++ ++ ++#define S_SWAY_MAX_OUTSTANDING_REQS_ADDR(b, n) \ ++ (S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000220) ++enum bimc_s_sway_max_outstanding_reqs { ++ S_SWAY_MAX_OUTSTANDING_REQS_RMSK = 0xffff, ++ S_SWAY_MAX_OUTSTANDING_REQS_WRITE_BMSK = 0xff00, ++ S_SWAY_MAX_OUTSTANDING_REQS_WRITE_SHFT = 0x8, ++ S_SWAY_MAX_OUTSTANDING_REQS_READ_BMSK = 0xff, ++ S_SWAY_MAX_OUTSTANDING_REQS_READ_SHFT = 0x0, ++}; ++ ++ ++#define S_SWAY_BUF_STATUS_0_ADDR(b, n) \ ++ (S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000400) ++enum bimc_s_sway_buf_status_0 { ++ S_SWAY_BUF_STATUS_0_RMSK = 0xf0300f03, ++ S_SWAY_BUF_STATUS_0_RCH0_DATA_RD_FULL_BMSK = 0x80000000, ++ S_SWAY_BUF_STATUS_0_RCH0_DATA_RD_FULL_SHFT = 0x1f, ++ S_SWAY_BUF_STATUS_0_RCH0_DATA_RD_EMPTY_BMSK = 0x40000000, ++ S_SWAY_BUF_STATUS_0_RCH0_DATA_RD_EMPTY_SHFT = 0x1e, ++ S_SWAY_BUF_STATUS_0_RCH0_CTRL_RD_FULL_BMSK = 0x20000000, ++ S_SWAY_BUF_STATUS_0_RCH0_CTRL_RD_FULL_SHFT = 0x1d, ++ S_SWAY_BUF_STATUS_0_RCH0_CTRL_RD_EMPTY_BMSK = 0x10000000, ++ S_SWAY_BUF_STATUS_0_RCH0_CTRL_RD_EMPTY_SHFT = 0x1c, ++ S_SWAY_BUF_STATUS_0_BCH_RD_FULL_BMSK = 0x200000, ++ S_SWAY_BUF_STATUS_0_BCH_RD_FULL_SHFT = 0x15, ++ S_SWAY_BUF_STATUS_0_BCH_RD_EMPTY_BMSK = 0x100000, ++ S_SWAY_BUF_STATUS_0_BCH_RD_EMPTY_SHFT = 0x14, ++ S_SWAY_BUF_STATUS_0_WCH_DATA_WR_FULL_BMSK = 0x800, ++ S_SWAY_BUF_STATUS_0_WCH_DATA_WR_FULL_SHFT = 0xb, ++ S_SWAY_BUF_STATUS_0_WCH_DATA_WR_EMPTY_BMSK = 0x400, ++ S_SWAY_BUF_STATUS_0_WCH_DATA_WR_EMPTY_SHFT = 0xa, ++ S_SWAY_BUF_STATUS_0_WCH_CTRL_WR_FULL_BMSK = 0x200, ++ S_SWAY_BUF_STATUS_0_WCH_CTRL_WR_FULL_SHFT = 0x9, ++ S_SWAY_BUF_STATUS_0_WCH_CTRL_WR_EMPTY_BMSK = 0x100, ++ S_SWAY_BUF_STATUS_0_WCH_CTRL_WR_EMPTY_SHFT = 0x8, ++ S_SWAY_BUF_STATUS_0_ACH_WR_FULL_BMSK = 0x2, ++ S_SWAY_BUF_STATUS_0_ACH_WR_FULL_SHFT = 0x1, ++ S_SWAY_BUF_STATUS_0_ACH_WR_EMPTY_BMSK = 0x1, ++ S_SWAY_BUF_STATUS_0_ACH_WR_EMPTY_SHFT = 0x0, ++}; ++ ++#define S_SWAY_BUF_STATUS_1_ADDR(b, n) \ ++ (S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000410) ++enum bimc_s_sway_buf_status_1 { ++ S_SWAY_BUF_STATUS_1_RMSK = 0xf0, ++ S_SWAY_BUF_STATUS_1_RCH1_DATA_RD_FULL_BMSK = 0x80, ++ S_SWAY_BUF_STATUS_1_RCH1_DATA_RD_FULL_SHFT = 0x7, ++ S_SWAY_BUF_STATUS_1_RCH1_DATA_RD_EMPTY_BMSK = 0x40, ++ S_SWAY_BUF_STATUS_1_RCH1_DATA_RD_EMPTY_SHFT = 0x6, ++ S_SWAY_BUF_STATUS_1_RCH1_CTRL_RD_FULL_BMSK = 0x20, ++ S_SWAY_BUF_STATUS_1_RCH1_CTRL_RD_FULL_SHFT = 0x5, ++ S_SWAY_BUF_STATUS_1_RCH1_CTRL_RD_EMPTY_BMSK = 0x10, ++ S_SWAY_BUF_STATUS_1_RCH1_CTRL_RD_EMPTY_SHFT = 0x4, ++}; ++ ++#define S_SWAY_BUF_STATUS_2_ADDR(b, n) \ ++ (S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000420) ++enum bimc_s_sway_buf_status_2 { ++ S_SWAY_BUF_STATUS_2_RMSK = 0x30, ++ S_SWAY_BUF_STATUS_2_QCH_RD_FULL_BMSK = 0x20, ++ S_SWAY_BUF_STATUS_2_QCH_RD_FULL_SHFT = 0x5, ++ S_SWAY_BUF_STATUS_2_QCH_RD_EMPTY_BMSK = 0x10, ++ S_SWAY_BUF_STATUS_2_QCH_RD_EMPTY_SHFT = 0x4, ++}; ++ ++/* S_ARB_GENERIC */ ++ ++#define S_ARB_REG_BASE(b) ((b) + 0x00049000) ++ ++#define S_ARB_COMPONENT_INFO_ADDR(b, n) \ ++ (S_SWAY_REG_BASE(b) + (0x8000 * (n)) + 0x00000000) ++enum bimc_s_arb_component_info { ++ S_ARB_COMPONENT_INFO_RMSK = 0xffffff, ++ S_ARB_COMPONENT_INFO_INSTANCE_BMSK = 0xff0000, ++ S_ARB_COMPONENT_INFO_INSTANCE_SHFT = 0x10, ++ S_ARB_COMPONENT_INFO_SUB_TYPE_BMSK = 0xff00, ++ S_ARB_COMPONENT_INFO_SUB_TYPE_SHFT = 0x8, ++ S_ARB_COMPONENT_INFO_TYPE_BMSK = 0xff, ++ S_ARB_COMPONENT_INFO_TYPE_SHFT = 0x0, ++}; ++ ++#define S_ARB_CONFIG_INFO_0_ADDR(b, n) \ ++ (S_ARB_REG_BASE(b) + (0x8000 * (n)) + 0x00000020) ++enum bimc_s_arb_config_info_0 { ++ S_ARB_CONFIG_INFO_0_RMSK = 0x800000ff, ++ S_ARB_CONFIG_INFO_0_ARB2SW_PIPELINE_EN_BMSK = 0x80000000, ++ S_ARB_CONFIG_INFO_0_ARB2SW_PIPELINE_EN_SHFT = 0x1f, ++ S_ARB_CONFIG_INFO_0_FUNC_BMSK = 0xff, ++ S_ARB_CONFIG_INFO_0_FUNC_SHFT = 0x0, ++}; ++ ++#define S_ARB_CONFIG_INFO_1_ADDR(b, n) \ ++ (S_ARB_REG_BASE(b) + (0x8000 * (n)) + 0x00000030) ++enum bimc_s_arb_config_info_1 { ++ S_ARB_CONFIG_INFO_1_RMSK = 0xffffffff, ++ S_ARB_CONFIG_INFO_1_MPORT_CONNECTIVITY_BMSK = 0xffffffff, ++ S_ARB_CONFIG_INFO_1_MPORT_CONNECTIVITY_SHFT = 0x0, ++}; ++ ++#define S_ARB_CLK_CTRL_ADDR(b) \ ++ (S_ARB_REG_BASE(b) + (0x8000 * (n)) + 0x00000200) ++enum bimc_s_arb_clk_ctrl { ++ S_ARB_CLK_CTRL_RMSK = 0x1, ++ S_ARB_CLK_CTRL_SLAVE_CLK_GATING_EN_BMSK = 0x2, ++ S_ARB_CLK_CTRL_SLAVE_CLK_GATING_EN_SHFT = 0x1, ++ S_ARB_CLK_CTRL_CORE_CLK_GATING_EN_BMSK = 0x1, ++ S_ARB_CLK_CTRL_CORE_CLK_GATING_EN_SHFT = 0x0, ++ S_ARB_CLK_CTRL_CLK_GATING_EN_BMSK = 0x1, ++ S_ARB_CLK_CTRL_CLK_GATING_EN_SHFT = 0x0, ++}; ++ ++#define S_ARB_MODE_ADDR(b, n) \ ++ (S_ARB_REG_BASE(b) + (0x8000 * (n)) + 0x00000210) ++enum bimc_s_arb_mode { ++ S_ARB_MODE_RMSK = 0xf0000001, ++ S_ARB_MODE_WR_GRANTS_AHEAD_BMSK = 0xf0000000, ++ S_ARB_MODE_WR_GRANTS_AHEAD_SHFT = 0x1c, ++ S_ARB_MODE_PRIO_RR_EN_BMSK = 0x1, ++ S_ARB_MODE_PRIO_RR_EN_SHFT = 0x0, ++}; ++ ++#define BKE_HEALTH_MASK \ ++ (M_BKE_HEALTH_0_CONFIG_LIMIT_CMDS_BMSK |\ ++ M_BKE_HEALTH_0_CONFIG_AREQPRIO_BMSK |\ ++ M_BKE_HEALTH_0_CONFIG_PRIOLVL_BMSK) ++ ++#define BKE_HEALTH_VAL(limit, areq, plvl) \ ++ ((((limit) << M_BKE_HEALTH_0_CONFIG_LIMIT_CMDS_SHFT) & \ ++ M_BKE_HEALTH_0_CONFIG_LIMIT_CMDS_BMSK) | \ ++ (((areq) << M_BKE_HEALTH_0_CONFIG_AREQPRIO_SHFT) & \ ++ M_BKE_HEALTH_0_CONFIG_AREQPRIO_BMSK) | \ ++ (((plvl) << M_BKE_HEALTH_0_CONFIG_PRIOLVL_SHFT) & \ ++ M_BKE_HEALTH_0_CONFIG_PRIOLVL_BMSK)) ++ ++#define MAX_GRANT_PERIOD \ ++ (M_BKE_GP_GP_BMSK >> \ ++ M_BKE_GP_GP_SHFT) ++ ++#define MAX_GC \ ++ (M_BKE_GC_GC_BMSK >> \ ++ (M_BKE_GC_GC_SHFT + 1)) ++ ++static int bimc_div(int64_t *a, uint32_t b) ++{ ++ if ((*a > 0) && (*a < b)) { ++ *a = 0; ++ return 1; ++ } else { ++ return do_div(*a, b); ++ } ++} ++ ++#define ENABLE(val) ((val) == 1 ? 1 : 0) ++void msm_bus_bimc_set_mas_clk_gate(struct msm_bus_bimc_info *binfo, ++ uint32_t mas_index, struct msm_bus_bimc_clk_gate *bgate) ++{ ++ uint32_t val, mask, reg_val; ++ void __iomem *addr; ++ ++ reg_val = readl_relaxed(M_CLK_CTRL_ADDR(binfo->base, ++ mas_index)) & M_CLK_CTRL_RMSK; ++ addr = M_CLK_CTRL_ADDR(binfo->base, mas_index); ++ mask = (M_CLK_CTRL_MAS_CLK_GATING_EN_BMSK | ++ M_CLK_CTRL_CORE_CLK_GATING_EN_BMSK); ++ val = (bgate->core_clk_gate_en << ++ M_CLK_CTRL_MAS_CLK_GATING_EN_SHFT) | ++ bgate->port_clk_gate_en; ++ writel_relaxed(((reg_val & (~mask)) | (val & mask)), addr); ++ /* Ensure clock gating enable mask is set before exiting */ ++ wmb(); ++} ++ ++void msm_bus_bimc_arb_en(struct msm_bus_bimc_info *binfo, ++ uint32_t slv_index, bool en) ++{ ++ uint32_t reg_val, reg_mask_val, enable, val; ++ ++ reg_mask_val = (readl_relaxed(S_ARB_CONFIG_INFO_0_ADDR(binfo-> ++ base, slv_index)) & S_ARB_CONFIG_INFO_0_FUNC_BMSK) ++ >> S_ARB_CONFIG_INFO_0_FUNC_SHFT; ++ enable = ENABLE(en); ++ val = enable << S_ARB_MODE_PRIO_RR_EN_SHFT; ++ if (reg_mask_val == BIMC_ARB_MODE_PRIORITY_RR) { ++ reg_val = readl_relaxed(S_ARB_CONFIG_INFO_0_ADDR(binfo-> ++ base, slv_index)) & S_ARB_MODE_RMSK; ++ writel_relaxed(((reg_val & (~(S_ARB_MODE_PRIO_RR_EN_BMSK))) | ++ (val & S_ARB_MODE_PRIO_RR_EN_BMSK)), ++ S_ARB_MODE_ADDR(binfo->base, slv_index)); ++ /* Ensure arbitration mode is set before returning */ ++ wmb(); ++ } ++} ++ ++static void set_qos_mode(void __iomem *baddr, uint32_t index, uint32_t val0, ++ uint32_t val1, uint32_t val2) ++{ ++ uint32_t reg_val, val; ++ ++ reg_val = readl_relaxed(M_PRIOLVL_OVERRIDE_ADDR(baddr, ++ index)) & M_PRIOLVL_OVERRIDE_RMSK; ++ val = val0 << M_PRIOLVL_OVERRIDE_OVERRIDE_PRIOLVL_SHFT; ++ writel_relaxed(((reg_val & ~(M_PRIOLVL_OVERRIDE_OVERRIDE_PRIOLVL_BMSK)) ++ | (val & M_PRIOLVL_OVERRIDE_OVERRIDE_PRIOLVL_BMSK)), ++ M_PRIOLVL_OVERRIDE_ADDR(baddr, index)); ++ reg_val = readl_relaxed(M_RD_CMD_OVERRIDE_ADDR(baddr, index)) & ++ M_RD_CMD_OVERRIDE_RMSK; ++ val = val1 << M_RD_CMD_OVERRIDE_OVERRIDE_AREQPRIO_SHFT; ++ writel_relaxed(((reg_val & ~(M_RD_CMD_OVERRIDE_OVERRIDE_AREQPRIO_BMSK ++ )) | (val & M_RD_CMD_OVERRIDE_OVERRIDE_AREQPRIO_BMSK)), ++ M_RD_CMD_OVERRIDE_ADDR(baddr, index)); ++ reg_val = readl_relaxed(M_WR_CMD_OVERRIDE_ADDR(baddr, index)) & ++ M_WR_CMD_OVERRIDE_RMSK; ++ val = val2 << M_WR_CMD_OVERRIDE_OVERRIDE_AREQPRIO_SHFT; ++ writel_relaxed(((reg_val & ~(M_WR_CMD_OVERRIDE_OVERRIDE_AREQPRIO_BMSK ++ )) | (val & M_WR_CMD_OVERRIDE_OVERRIDE_AREQPRIO_BMSK)), ++ M_WR_CMD_OVERRIDE_ADDR(baddr, index)); ++ /* Ensure the priority register writes go through */ ++ wmb(); ++} ++ ++static void msm_bus_bimc_set_qos_mode(void __iomem *base, ++ uint32_t mas_index, uint8_t qmode_sel) ++{ ++ uint32_t reg_val, val; ++ ++ switch (qmode_sel) { ++ case BIMC_QOS_MODE_FIXED: ++ reg_val = readl_relaxed(M_BKE_EN_ADDR(base, ++ mas_index)); ++ writel_relaxed((reg_val & (~M_BKE_EN_EN_BMSK)), ++ M_BKE_EN_ADDR(base, mas_index)); ++ /* Ensure that the book-keeping register writes ++ * go through before setting QoS mode. ++ * QoS mode registers might write beyond 1K ++ * boundary in future ++ */ ++ wmb(); ++ set_qos_mode(base, mas_index, 1, 1, 1); ++ break; ++ ++ case BIMC_QOS_MODE_BYPASS: ++ reg_val = readl_relaxed(M_BKE_EN_ADDR(base, ++ mas_index)); ++ writel_relaxed((reg_val & (~M_BKE_EN_EN_BMSK)), ++ M_BKE_EN_ADDR(base, mas_index)); ++ /* Ensure that the book-keeping register writes ++ * go through before setting QoS mode. ++ * QoS mode registers might write beyond 1K ++ * boundary in future ++ */ ++ wmb(); ++ set_qos_mode(base, mas_index, 0, 0, 0); ++ break; ++ ++ case BIMC_QOS_MODE_REGULATOR: ++ case BIMC_QOS_MODE_LIMITER: ++ set_qos_mode(base, mas_index, 0, 0, 0); ++ reg_val = readl_relaxed(M_BKE_EN_ADDR(base, ++ mas_index)); ++ val = 1 << M_BKE_EN_EN_SHFT; ++ /* Ensure that the book-keeping register writes ++ * go through before setting QoS mode. ++ * QoS mode registers might write beyond 1K ++ * boundary in future ++ */ ++ wmb(); ++ writel_relaxed(((reg_val & (~M_BKE_EN_EN_BMSK)) | (val & ++ M_BKE_EN_EN_BMSK)), M_BKE_EN_ADDR(base, ++ mas_index)); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void set_qos_prio_rl(void __iomem *addr, uint32_t rmsk, ++ uint8_t index, struct msm_bus_bimc_qos_mode *qmode) ++{ ++ uint32_t reg_val, val0, val; ++ ++ /* Note, addr is already passed with right mas_index */ ++ reg_val = readl_relaxed(addr) & rmsk; ++ val0 = BKE_HEALTH_VAL(qmode->rl.qhealth[index].limit_commands, ++ qmode->rl.qhealth[index].areq_prio, ++ qmode->rl.qhealth[index].prio_level); ++ val = ((reg_val & (~(BKE_HEALTH_MASK))) | (val0 & BKE_HEALTH_MASK)); ++ writel_relaxed(val, addr); ++ /* Ensure that priority for regulator/limiter modes are ++ * set before returning ++ */ ++ wmb(); ++ ++} ++ ++static void msm_bus_bimc_set_qos_prio(void __iomem *base, ++ uint32_t mas_index, uint8_t qmode_sel, ++ struct msm_bus_bimc_qos_mode *qmode) ++{ ++ uint32_t reg_val, val; ++ ++ switch (qmode_sel) { ++ case BIMC_QOS_MODE_FIXED: ++ reg_val = readl_relaxed(M_PRIOLVL_OVERRIDE_ADDR( ++ base, mas_index)) & M_PRIOLVL_OVERRIDE_RMSK; ++ val = qmode->fixed.prio_level << ++ M_PRIOLVL_OVERRIDE_SHFT; ++ writel_relaxed(((reg_val & ++ ~(M_PRIOLVL_OVERRIDE_BMSK)) | (val ++ & M_PRIOLVL_OVERRIDE_BMSK)), ++ M_PRIOLVL_OVERRIDE_ADDR(base, mas_index)); ++ ++ reg_val = readl_relaxed(M_RD_CMD_OVERRIDE_ADDR( ++ base, mas_index)) & M_RD_CMD_OVERRIDE_RMSK; ++ val = qmode->fixed.areq_prio_rd << ++ M_RD_CMD_OVERRIDE_AREQPRIO_SHFT; ++ writel_relaxed(((reg_val & ~(M_RD_CMD_OVERRIDE_AREQPRIO_BMSK)) ++ | (val & M_RD_CMD_OVERRIDE_AREQPRIO_BMSK)), ++ M_RD_CMD_OVERRIDE_ADDR(base, mas_index)); ++ ++ reg_val = readl_relaxed(M_WR_CMD_OVERRIDE_ADDR( ++ base, mas_index)) & M_WR_CMD_OVERRIDE_RMSK; ++ val = qmode->fixed.areq_prio_wr << ++ M_WR_CMD_OVERRIDE_AREQPRIO_SHFT; ++ writel_relaxed(((reg_val & ~(M_WR_CMD_OVERRIDE_AREQPRIO_BMSK)) ++ | (val & M_WR_CMD_OVERRIDE_AREQPRIO_BMSK)), ++ M_WR_CMD_OVERRIDE_ADDR(base, mas_index)); ++ /* Ensure that fixed mode register writes go through ++ * before returning ++ */ ++ wmb(); ++ break; ++ ++ case BIMC_QOS_MODE_REGULATOR: ++ case BIMC_QOS_MODE_LIMITER: ++ set_qos_prio_rl(M_BKE_HEALTH_3_CONFIG_ADDR(base, ++ mas_index), M_BKE_HEALTH_3_CONFIG_RMSK, 3, qmode); ++ set_qos_prio_rl(M_BKE_HEALTH_2_CONFIG_ADDR(base, ++ mas_index), M_BKE_HEALTH_2_CONFIG_RMSK, 2, qmode); ++ set_qos_prio_rl(M_BKE_HEALTH_1_CONFIG_ADDR(base, ++ mas_index), M_BKE_HEALTH_1_CONFIG_RMSK, 1, qmode); ++ set_qos_prio_rl(M_BKE_HEALTH_0_CONFIG_ADDR(base, ++ mas_index), M_BKE_HEALTH_0_CONFIG_RMSK, 0 , qmode); ++ break; ++ case BIMC_QOS_MODE_BYPASS: ++ default: ++ break; ++ } ++} ++ ++static void set_qos_bw_regs(void __iomem *baddr, uint32_t mas_index, ++ int32_t th, int32_t tm, int32_t tl, uint32_t gp, ++ uint32_t gc) ++{ ++ int32_t reg_val, val; ++ int32_t bke_reg_val; ++ int16_t val2; ++ ++ /* Disable BKE before writing to registers as per spec */ ++ bke_reg_val = readl_relaxed(M_BKE_EN_ADDR(baddr, mas_index)); ++ writel_relaxed((bke_reg_val & ~(M_BKE_EN_EN_BMSK)), ++ M_BKE_EN_ADDR(baddr, mas_index)); ++ ++ /* Write values of registers calculated */ ++ reg_val = readl_relaxed(M_BKE_GP_ADDR(baddr, mas_index)) ++ & M_BKE_GP_RMSK; ++ val = gp << M_BKE_GP_GP_SHFT; ++ writel_relaxed(((reg_val & ~(M_BKE_GP_GP_BMSK)) | (val & ++ M_BKE_GP_GP_BMSK)), M_BKE_GP_ADDR(baddr, mas_index)); ++ ++ reg_val = readl_relaxed(M_BKE_GC_ADDR(baddr, mas_index)) & ++ M_BKE_GC_RMSK; ++ val = gc << M_BKE_GC_GC_SHFT; ++ writel_relaxed(((reg_val & ~(M_BKE_GC_GC_BMSK)) | (val & ++ M_BKE_GC_GC_BMSK)), M_BKE_GC_ADDR(baddr, mas_index)); ++ ++ reg_val = readl_relaxed(M_BKE_THH_ADDR(baddr, mas_index)) & ++ M_BKE_THH_RMSK; ++ val = th << M_BKE_THH_THRESH_SHFT; ++ writel_relaxed(((reg_val & ~(M_BKE_THH_THRESH_BMSK)) | (val & ++ M_BKE_THH_THRESH_BMSK)), M_BKE_THH_ADDR(baddr, mas_index)); ++ ++ reg_val = readl_relaxed(M_BKE_THM_ADDR(baddr, mas_index)) & ++ M_BKE_THM_RMSK; ++ val2 = tm << M_BKE_THM_THRESH_SHFT; ++ writel_relaxed(((reg_val & ~(M_BKE_THM_THRESH_BMSK)) | (val2 & ++ M_BKE_THM_THRESH_BMSK)), M_BKE_THM_ADDR(baddr, mas_index)); ++ ++ reg_val = readl_relaxed(M_BKE_THL_ADDR(baddr, mas_index)) & ++ M_BKE_THL_RMSK; ++ val2 = tl << M_BKE_THL_THRESH_SHFT; ++ writel_relaxed(((reg_val & ~(M_BKE_THL_THRESH_BMSK)) | ++ (val2 & M_BKE_THL_THRESH_BMSK)), M_BKE_THL_ADDR(baddr, ++ mas_index)); ++ ++ /* Ensure that all bandwidth register writes have completed ++ * before returning ++ */ ++ wmb(); ++} ++ ++static void msm_bus_bimc_set_qos_bw(void __iomem *base, uint32_t qos_freq, ++ uint32_t mas_index, struct msm_bus_bimc_qos_bw *qbw) ++{ ++ uint32_t bke_en; ++ ++ /* Validate QOS Frequency */ ++ if (qos_freq == 0) { ++ MSM_BUS_DBG("Zero frequency\n"); ++ return; ++ } ++ ++ /* Get enable bit for BKE before programming the period */ ++ bke_en = (readl_relaxed(M_BKE_EN_ADDR(base, mas_index)) & ++ M_BKE_EN_EN_BMSK) >> M_BKE_EN_EN_SHFT; ++ ++ /* Only calculate if there's a requested bandwidth and window */ ++ if (qbw->bw && qbw->ws) { ++ int64_t th, tm, tl; ++ uint32_t gp, gc; ++ int64_t gp_nominal, gp_required, gp_calc, data, temp; ++ int64_t win = qbw->ws * qos_freq; ++ temp = win; ++ /* ++ * Calculate nominal grant period defined by requested ++ * window size. ++ * Ceil this value to max grant period. ++ */ ++ bimc_div(&temp, 1000000); ++ gp_nominal = min_t(uint64_t, MAX_GRANT_PERIOD, temp); ++ /* ++ * Calculate max window size, defined by bw request. ++ * Units: (KHz, MB/s) ++ */ ++ gp_calc = MAX_GC * qos_freq * 1000; ++ gp_required = gp_calc; ++ bimc_div(&gp_required, qbw->bw); ++ ++ /* User min of two grant periods */ ++ gp = min_t(int64_t, gp_nominal, gp_required); ++ ++ /* Calculate bandwith in grants and ceil. */ ++ temp = qbw->bw * gp; ++ data = qos_freq * 1000; ++ bimc_div(&temp, data); ++ gc = min_t(int64_t, MAX_GC, temp); ++ ++ /* Calculate thresholds */ ++ th = qbw->bw - qbw->thh; ++ tm = qbw->bw - qbw->thm; ++ tl = qbw->bw - qbw->thl; ++ ++ th = th * gp; ++ bimc_div(&th, data); ++ tm = tm * gp; ++ bimc_div(&tm, data); ++ tl = tl * gp; ++ bimc_div(&tl, data); ++ ++ MSM_BUS_DBG("BIMC: BW: mas_index: %d, th: %llu tm: %llu\n", ++ mas_index, th, tm); ++ MSM_BUS_DBG("BIMC: tl: %llu gp:%u gc: %u bke_en: %u\n", ++ tl, gp, gc, bke_en); ++ set_qos_bw_regs(base, mas_index, th, tm, tl, gp, gc); ++ } else ++ /* Clear bandwidth registers */ ++ set_qos_bw_regs(base, mas_index, 0, 0, 0, 0, 0); ++} ++ ++static int msm_bus_bimc_allocate_commit_data(struct msm_bus_fabric_registration ++ *fab_pdata, void **cdata, int ctx) ++{ ++ struct msm_bus_bimc_commit **cd = (struct msm_bus_bimc_commit **)cdata; ++ struct msm_bus_bimc_info *binfo = ++ (struct msm_bus_bimc_info *)fab_pdata->hw_data; ++ ++ MSM_BUS_DBG("Allocating BIMC commit data\n"); ++ *cd = kzalloc(sizeof(struct msm_bus_bimc_commit), GFP_KERNEL); ++ if (!*cd) { ++ MSM_BUS_DBG("Couldn't alloc mem for cdata\n"); ++ return -ENOMEM; ++ } ++ ++ (*cd)->mas = binfo->cdata[ctx].mas; ++ (*cd)->slv = binfo->cdata[ctx].slv; ++ ++ return 0; ++} ++ ++static void *msm_bus_bimc_allocate_bimc_data(struct platform_device *pdev, ++ struct msm_bus_fabric_registration *fab_pdata) ++{ ++ struct resource *bimc_mem; ++ struct resource *bimc_io; ++ struct msm_bus_bimc_info *binfo; ++ int i; ++ ++ MSM_BUS_DBG("Allocating BIMC data\n"); ++ binfo = kzalloc(sizeof(struct msm_bus_bimc_info), GFP_KERNEL); ++ if (!binfo) { ++ WARN(!binfo, "Couldn't alloc mem for bimc_info\n"); ++ return NULL; ++ } ++ ++ binfo->qos_freq = fab_pdata->qos_freq; ++ ++ binfo->params.nmasters = fab_pdata->nmasters; ++ binfo->params.nslaves = fab_pdata->nslaves; ++ binfo->params.bus_id = fab_pdata->id; ++ ++ for (i = 0; i < NUM_CTX; i++) { ++ binfo->cdata[i].mas = kzalloc(sizeof(struct ++ msm_bus_node_hw_info) * fab_pdata->nmasters * 2, ++ GFP_KERNEL); ++ if (!binfo->cdata[i].mas) { ++ MSM_BUS_ERR("Couldn't alloc mem for bimc master hw\n"); ++ kfree(binfo); ++ return NULL; ++ } ++ ++ binfo->cdata[i].slv = kzalloc(sizeof(struct ++ msm_bus_node_hw_info) * fab_pdata->nslaves * 2, ++ GFP_KERNEL); ++ if (!binfo->cdata[i].slv) { ++ MSM_BUS_DBG("Couldn't alloc mem for bimc slave hw\n"); ++ kfree(binfo->cdata[i].mas); ++ kfree(binfo); ++ return NULL; ++ } ++ } ++ ++ if (fab_pdata->virt) { ++ MSM_BUS_DBG("Don't get memory regions for virtual fabric\n"); ++ goto skip_mem; ++ } ++ ++ bimc_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!bimc_mem) { ++ MSM_BUS_ERR("Cannot get BIMC Base address\n"); ++ kfree(binfo); ++ return NULL; ++ } ++ ++ bimc_io = request_mem_region(bimc_mem->start, ++ resource_size(bimc_mem), pdev->name); ++ if (!bimc_io) { ++ MSM_BUS_ERR("BIMC memory unavailable\n"); ++ kfree(binfo); ++ return NULL; ++ } ++ ++ binfo->base = ioremap(bimc_mem->start, resource_size(bimc_mem)); ++ if (!binfo->base) { ++ MSM_BUS_ERR("IOremap failed for BIMC!\n"); ++ release_mem_region(bimc_mem->start, resource_size(bimc_mem)); ++ kfree(binfo); ++ return NULL; ++ } ++ ++skip_mem: ++ fab_pdata->hw_data = (void *)binfo; ++ return (void *)binfo; ++} ++ ++static void free_commit_data(void *cdata) ++{ ++ struct msm_bus_bimc_commit *cd = (struct msm_bus_bimc_commit *)cdata; ++ ++ kfree(cd->mas); ++ kfree(cd->slv); ++ kfree(cd); ++} ++ ++static void bke_switch( ++ void __iomem *baddr, uint32_t mas_index, bool req, int mode) ++{ ++ uint32_t reg_val, val, cur_val; ++ ++ val = req << M_BKE_EN_EN_SHFT; ++ reg_val = readl_relaxed(M_BKE_EN_ADDR(baddr, mas_index)); ++ cur_val = reg_val & M_BKE_EN_RMSK; ++ if (val == cur_val) ++ return; ++ ++ if (!req && mode == BIMC_QOS_MODE_FIXED) ++ set_qos_mode(baddr, mas_index, 1, 1, 1); ++ ++ writel_relaxed(((reg_val & ~(M_BKE_EN_EN_BMSK)) | (val & ++ M_BKE_EN_EN_BMSK)), M_BKE_EN_ADDR(baddr, mas_index)); ++ /* Make sure BKE on/off goes through before changing priorities */ ++ wmb(); ++ ++ if (req) ++ set_qos_mode(baddr, mas_index, 0, 0, 0); ++} ++ ++static void bimc_set_static_qos_bw(void __iomem *base, unsigned int qos_freq, ++ int mport, struct msm_bus_bimc_qos_bw *qbw) ++{ ++ int32_t bw_mbps, thh = 0, thm, thl, gc; ++ int32_t gp; ++ u64 temp; ++ ++ if (qos_freq == 0) { ++ MSM_BUS_DBG("No QoS Frequency.\n"); ++ return; ++ } ++ ++ if (!(qbw->bw && qbw->gp)) { ++ MSM_BUS_DBG("No QoS Bandwidth or Window size\n"); ++ return; ++ } ++ ++ /* Convert bandwidth to MBPS */ ++ temp = qbw->bw; ++ bimc_div(&temp, 1000000); ++ bw_mbps = temp; ++ ++ /* Grant period in clock cycles ++ * Grant period from bandwidth structure ++ * is in nano seconds, QoS freq is in KHz. ++ * Divide by 1000 to get clock cycles. ++ */ ++ gp = (qos_freq * qbw->gp) / (1000 * NSEC_PER_USEC); ++ ++ /* Grant count = BW in MBps * Grant period ++ * in micro seconds ++ */ ++ gc = bw_mbps * (qbw->gp / NSEC_PER_USEC); ++ gc = min(gc, MAX_GC); ++ ++ /* Medium threshold = -((Medium Threshold percentage * ++ * Grant count) / 100) ++ */ ++ thm = -((qbw->thmp * gc) / 100); ++ qbw->thm = thm; ++ ++ /* Low threshold = -(Grant count) */ ++ thl = -gc; ++ qbw->thl = thl; ++ ++ MSM_BUS_DBG("%s: BKE parameters: gp %d, gc %d, thm %d thl %d thh %d", ++ __func__, gp, gc, thm, thl, thh); ++ ++ trace_bus_bke_params(gc, gp, thl, thm, thl); ++ set_qos_bw_regs(base, mport, thh, thm, thl, gp, gc); ++} ++ ++static void msm_bus_bimc_config_master( ++ struct msm_bus_fabric_registration *fab_pdata, ++ struct msm_bus_inode_info *info, ++ uint64_t req_clk, uint64_t req_bw) ++{ ++ int mode, i, ports; ++ struct msm_bus_bimc_info *binfo; ++ uint64_t bw = 0; ++ ++ binfo = (struct msm_bus_bimc_info *)fab_pdata->hw_data; ++ ports = info->node_info->num_mports; ++ ++ /** ++ * Here check the details of dual configuration. ++ * Take actions based on different modes. ++ * Check for threshold if limiter mode, etc. ++ */ ++ ++ if (req_clk <= info->node_info->th[0]) { ++ mode = info->node_info->mode; ++ bw = info->node_info->bimc_bw[0]; ++ } else if ((info->node_info->num_thresh > 1) && ++ (req_clk <= info->node_info->th[1])) { ++ mode = info->node_info->mode; ++ bw = info->node_info->bimc_bw[1]; ++ } else ++ mode = info->node_info->mode_thresh; ++ ++ switch (mode) { ++ case BIMC_QOS_MODE_BYPASS: ++ case BIMC_QOS_MODE_FIXED: ++ for (i = 0; i < ports; i++) ++ bke_switch(binfo->base, info->node_info->qport[i], ++ BKE_OFF, mode); ++ break; ++ case BIMC_QOS_MODE_REGULATOR: ++ case BIMC_QOS_MODE_LIMITER: ++ for (i = 0; i < ports; i++) { ++ /* If not in fixed mode, update bandwidth */ ++ if ((info->node_info->cur_lim_bw != bw) ++ && (mode != BIMC_QOS_MODE_FIXED)) { ++ struct msm_bus_bimc_qos_bw qbw; ++ qbw.ws = info->node_info->ws; ++ qbw.bw = bw; ++ qbw.gp = info->node_info->bimc_gp; ++ qbw.thmp = info->node_info->bimc_thmp; ++ bimc_set_static_qos_bw(binfo->base, ++ binfo->qos_freq, ++ info->node_info->qport[i], &qbw); ++ info->node_info->cur_lim_bw = bw; ++ MSM_BUS_DBG("%s: Qos is %d reqclk %llu bw %llu", ++ __func__, mode, req_clk, bw); ++ } ++ bke_switch(binfo->base, info->node_info->qport[i], ++ BKE_ON, mode); ++ } ++ break; ++ default: ++ break; ++ } ++} ++ ++static void msm_bus_bimc_update_bw(struct msm_bus_inode_info *hop, ++ struct msm_bus_inode_info *info, ++ struct msm_bus_fabric_registration *fab_pdata, ++ void *sel_cdata, int *master_tiers, ++ int64_t add_bw) ++{ ++ struct msm_bus_bimc_info *binfo; ++ struct msm_bus_bimc_qos_bw qbw; ++ int i; ++ int64_t bw; ++ int ports = info->node_info->num_mports; ++ struct msm_bus_bimc_commit *sel_cd = ++ (struct msm_bus_bimc_commit *)sel_cdata; ++ ++ MSM_BUS_DBG("BIMC: Update bw for ID %d, with IID: %d: %lld\n", ++ info->node_info->id, info->node_info->priv_id, add_bw); ++ ++ binfo = (struct msm_bus_bimc_info *)fab_pdata->hw_data; ++ ++ if (info->node_info->num_mports == 0) { ++ MSM_BUS_DBG("BIMC: Skip Master BW\n"); ++ goto skip_mas_bw; ++ } ++ ++ ports = info->node_info->num_mports; ++ bw = INTERLEAVED_BW(fab_pdata, add_bw, ports); ++ ++ for (i = 0; i < ports; i++) { ++ sel_cd->mas[info->node_info->masterp[i]].bw += bw; ++ sel_cd->mas[info->node_info->masterp[i]].hw_id = ++ info->node_info->mas_hw_id; ++ MSM_BUS_DBG("BIMC: Update mas_bw for ID: %d -> %llu\n", ++ info->node_info->priv_id, ++ sel_cd->mas[info->node_info->masterp[i]].bw); ++ if (info->node_info->hw_sel == MSM_BUS_RPM) ++ sel_cd->mas[info->node_info->masterp[i]].dirty = 1; ++ else { ++ if (!info->node_info->qport) { ++ MSM_BUS_DBG("No qos ports to update!\n"); ++ break; ++ } ++ if (!(info->node_info->mode == BIMC_QOS_MODE_REGULATOR) ++ || (info->node_info->mode == ++ BIMC_QOS_MODE_LIMITER)) { ++ MSM_BUS_DBG("Skip QoS reg programming\n"); ++ break; ++ } ++ ++ MSM_BUS_DBG("qport: %d\n", info->node_info->qport[i]); ++ qbw.bw = sel_cd->mas[info->node_info->masterp[i]].bw; ++ qbw.ws = info->node_info->ws; ++ /* Threshold low = 90% of bw */ ++ qbw.thl = div_s64((90 * bw), 100); ++ /* Threshold medium = bw */ ++ qbw.thm = bw; ++ /* Threshold high = 10% more than bw */ ++ qbw.thh = div_s64((110 * bw), 100); ++ /* Check if info is a shared master. ++ * If it is, mark it dirty ++ * If it isn't, then set QOS Bandwidth. ++ * Also if dual-conf is set, don't program bw regs. ++ **/ ++ if (!info->node_info->dual_conf && ++ ((info->node_info->mode == BIMC_QOS_MODE_LIMITER) || ++ (info->node_info->mode == BIMC_QOS_MODE_REGULATOR))) ++ msm_bus_bimc_set_qos_bw(binfo->base, ++ binfo->qos_freq, ++ info->node_info->qport[i], &qbw); ++ } ++ } ++ ++skip_mas_bw: ++ ports = hop->node_info->num_sports; ++ MSM_BUS_DBG("BIMC: ID: %d, Sports: %d\n", hop->node_info->priv_id, ++ ports); ++ ++ for (i = 0; i < ports; i++) { ++ sel_cd->slv[hop->node_info->slavep[i]].bw += add_bw; ++ sel_cd->slv[hop->node_info->slavep[i]].hw_id = ++ hop->node_info->slv_hw_id; ++ MSM_BUS_DBG("BIMC: Update slave_bw: ID: %d -> %llu\n", ++ hop->node_info->priv_id, ++ sel_cd->slv[hop->node_info->slavep[i]].bw); ++ MSM_BUS_DBG("BIMC: Update slave_bw: index: %d\n", ++ hop->node_info->slavep[i]); ++ /* Check if hop is a shared slave. ++ * If it is, mark it dirty ++ * If it isn't, then nothing to be done as the ++ * slaves are in bypass mode. ++ **/ ++ if (hop->node_info->hw_sel == MSM_BUS_RPM) { ++ MSM_BUS_DBG("Slave dirty: %d, slavep: %d\n", ++ hop->node_info->priv_id, ++ hop->node_info->slavep[i]); ++ sel_cd->slv[hop->node_info->slavep[i]].dirty = 1; ++ } ++ } ++} ++ ++static int msm_bus_bimc_commit(struct msm_bus_fabric_registration ++ *fab_pdata, void *hw_data, void **cdata) ++{ ++ MSM_BUS_DBG("\nReached BIMC Commit\n"); ++ msm_bus_remote_hw_commit(fab_pdata, hw_data, cdata); ++ return 0; ++} ++ ++static void msm_bus_bimc_config_limiter( ++ struct msm_bus_fabric_registration *fab_pdata, ++ struct msm_bus_inode_info *info) ++{ ++ struct msm_bus_bimc_info *binfo; ++ int mode, i, ports; ++ ++ binfo = (struct msm_bus_bimc_info *)fab_pdata->hw_data; ++ ports = info->node_info->num_mports; ++ ++ if (!info->node_info->qport) { ++ MSM_BUS_DBG("No QoS Ports to init\n"); ++ return; ++ } ++ ++ if (info->cur_lim_bw) ++ mode = BIMC_QOS_MODE_LIMITER; ++ else ++ mode = info->node_info->mode; ++ ++ switch (mode) { ++ case BIMC_QOS_MODE_BYPASS: ++ case BIMC_QOS_MODE_FIXED: ++ for (i = 0; i < ports; i++) ++ bke_switch(binfo->base, info->node_info->qport[i], ++ BKE_OFF, mode); ++ break; ++ case BIMC_QOS_MODE_REGULATOR: ++ case BIMC_QOS_MODE_LIMITER: ++ if (info->cur_lim_bw != info->cur_prg_bw) { ++ MSM_BUS_DBG("Enabled BKE throttling node %d to %llu\n", ++ info->node_info->id, info->cur_lim_bw); ++ trace_bus_bimc_config_limiter(info->node_info->id, ++ info->cur_lim_bw); ++ for (i = 0; i < ports; i++) { ++ /* If not in fixed mode, update bandwidth */ ++ struct msm_bus_bimc_qos_bw qbw; ++ ++ qbw.ws = info->node_info->ws; ++ qbw.bw = info->cur_lim_bw; ++ qbw.gp = info->node_info->bimc_gp; ++ qbw.thmp = info->node_info->bimc_thmp; ++ bimc_set_static_qos_bw(binfo->base, ++ binfo->qos_freq, ++ info->node_info->qport[i], &qbw); ++ bke_switch(binfo->base, ++ info->node_info->qport[i], ++ BKE_ON, mode); ++ info->cur_prg_bw = qbw.bw; ++ } ++ } ++ break; ++ default: ++ break; ++ } ++} ++ ++static void bimc_init_mas_reg(struct msm_bus_bimc_info *binfo, ++ struct msm_bus_inode_info *info, ++ struct msm_bus_bimc_qos_mode *qmode, int mode) ++{ ++ int i; ++ ++ switch (mode) { ++ case BIMC_QOS_MODE_FIXED: ++ qmode->fixed.prio_level = info->node_info->prio_lvl; ++ qmode->fixed.areq_prio_rd = info->node_info->prio_rd; ++ qmode->fixed.areq_prio_wr = info->node_info->prio_wr; ++ break; ++ case BIMC_QOS_MODE_LIMITER: ++ qmode->rl.qhealth[0].limit_commands = 1; ++ qmode->rl.qhealth[1].limit_commands = 0; ++ qmode->rl.qhealth[2].limit_commands = 0; ++ qmode->rl.qhealth[3].limit_commands = 0; ++ break; ++ default: ++ break; ++ } ++ ++ if (!info->node_info->qport) { ++ MSM_BUS_DBG("No QoS Ports to init\n"); ++ return; ++ } ++ ++ for (i = 0; i < info->node_info->num_mports; i++) { ++ /* If not in bypass mode, update priority */ ++ if (mode != BIMC_QOS_MODE_BYPASS) { ++ msm_bus_bimc_set_qos_prio(binfo->base, ++ info->node_info-> ++ qport[i], mode, qmode); ++ ++ /* If not in fixed mode, update bandwidth */ ++ if (mode != BIMC_QOS_MODE_FIXED) { ++ struct msm_bus_bimc_qos_bw qbw; ++ qbw.ws = info->node_info->ws; ++ qbw.bw = info->node_info->bimc_bw[0]; ++ qbw.gp = info->node_info->bimc_gp; ++ qbw.thmp = info->node_info->bimc_thmp; ++ bimc_set_static_qos_bw(binfo->base, ++ binfo->qos_freq, ++ info->node_info->qport[i], &qbw); ++ } ++ } ++ ++ /* set mode */ ++ msm_bus_bimc_set_qos_mode(binfo->base, ++ info->node_info->qport[i], ++ mode); ++ } ++} ++ ++static void init_health_regs(struct msm_bus_bimc_info *binfo, ++ struct msm_bus_inode_info *info, ++ struct msm_bus_bimc_qos_mode *qmode, ++ int mode) ++{ ++ int i; ++ ++ if (mode == BIMC_QOS_MODE_LIMITER) { ++ qmode->rl.qhealth[0].limit_commands = 1; ++ qmode->rl.qhealth[1].limit_commands = 0; ++ qmode->rl.qhealth[2].limit_commands = 0; ++ qmode->rl.qhealth[3].limit_commands = 0; ++ ++ if (!info->node_info->qport) { ++ MSM_BUS_DBG("No QoS Ports to init\n"); ++ return; ++ } ++ ++ for (i = 0; i < info->node_info->num_mports; i++) { ++ /* If not in bypass mode, update priority */ ++ if (mode != BIMC_QOS_MODE_BYPASS) ++ msm_bus_bimc_set_qos_prio(binfo->base, ++ info->node_info->qport[i], mode, qmode); ++ } ++ } ++} ++ ++ ++static int msm_bus_bimc_mas_init(struct msm_bus_bimc_info *binfo, ++ struct msm_bus_inode_info *info) ++{ ++ struct msm_bus_bimc_qos_mode *qmode; ++ qmode = kzalloc(sizeof(struct msm_bus_bimc_qos_mode), ++ GFP_KERNEL); ++ if (!qmode) { ++ MSM_BUS_WARN("Couldn't alloc prio data for node: %d\n", ++ info->node_info->id); ++ return -ENOMEM; ++ } ++ ++ info->hw_data = (void *)qmode; ++ ++ /** ++ * If the master supports dual configuration, ++ * configure registers for both modes ++ */ ++ if (info->node_info->dual_conf) ++ bimc_init_mas_reg(binfo, info, qmode, ++ info->node_info->mode_thresh); ++ else if (info->node_info->nr_lim) ++ init_health_regs(binfo, info, qmode, BIMC_QOS_MODE_LIMITER); ++ ++ bimc_init_mas_reg(binfo, info, qmode, info->node_info->mode); ++ return 0; ++} ++ ++static void msm_bus_bimc_node_init(void *hw_data, ++ struct msm_bus_inode_info *info) ++{ ++ struct msm_bus_bimc_info *binfo = ++ (struct msm_bus_bimc_info *)hw_data; ++ ++ if (!IS_SLAVE(info->node_info->priv_id) && ++ (info->node_info->hw_sel != MSM_BUS_RPM)) ++ msm_bus_bimc_mas_init(binfo, info); ++} ++ ++static int msm_bus_bimc_port_halt(uint32_t haltid, uint8_t mport) ++{ ++ return 0; ++} ++ ++static int msm_bus_bimc_port_unhalt(uint32_t haltid, uint8_t mport) ++{ ++ return 0; ++} ++ ++static int msm_bus_bimc_limit_mport(struct msm_bus_node_device_type *info, ++ void __iomem *qos_base, uint32_t qos_off, ++ uint32_t qos_delta, uint32_t qos_freq, ++ bool enable_lim, u64 lim_bw) ++{ ++ int mode; ++ int i; ++ ++ if (ZERO_OR_NULL_PTR(info->node_info->qport)) { ++ MSM_BUS_DBG("No QoS Ports to limit\n"); ++ return 0; ++ } ++ ++ if (enable_lim && lim_bw) { ++ mode = BIMC_QOS_MODE_LIMITER; ++ ++ if (!info->node_info->lim_bw) { ++ struct msm_bus_bimc_qos_mode qmode; ++ qmode.rl.qhealth[0].limit_commands = 1; ++ qmode.rl.qhealth[1].limit_commands = 0; ++ qmode.rl.qhealth[2].limit_commands = 0; ++ qmode.rl.qhealth[3].limit_commands = 0; ++ ++ for (i = 0; i < info->node_info->num_qports; i++) { ++ /* If not in bypass mode, update priority */ ++ if (mode != BIMC_QOS_MODE_BYPASS) ++ msm_bus_bimc_set_qos_prio(qos_base, ++ info->node_info->qport[i], mode, ++ &qmode); ++ } ++ } ++ ++ for (i = 0; i < info->node_info->num_qports; i++) { ++ struct msm_bus_bimc_qos_bw qbw; ++ /* If not in fixed mode, update bandwidth */ ++ if ((info->node_info->lim_bw != lim_bw)) { ++ qbw.ws = info->node_info->qos_params.ws; ++ qbw.bw = lim_bw; ++ qbw.gp = info->node_info->qos_params.gp; ++ qbw.thmp = info->node_info->qos_params.thmp; ++ bimc_set_static_qos_bw(qos_base, qos_freq, ++ info->node_info->qport[i], &qbw); ++ } ++ bke_switch(qos_base, info->node_info->qport[i], ++ BKE_ON, mode); ++ } ++ info->node_info->lim_bw = lim_bw; ++ } else { ++ mode = info->node_info->qos_params.mode; ++ for (i = 0; i < info->node_info->num_qports; i++) { ++ bke_switch(qos_base, info->node_info->qport[i], ++ BKE_OFF, mode); ++ } ++ } ++ info->node_info->qos_params.cur_mode = mode; ++ return 0; ++} ++ ++static bool msm_bus_bimc_update_bw_reg(int mode) ++{ ++ bool ret = false; ++ ++ if ((mode == BIMC_QOS_MODE_LIMITER) ++ || (mode == BIMC_QOS_MODE_REGULATOR)) ++ ret = true; ++ ++ return ret; ++} ++ ++static int msm_bus_bimc_qos_init(struct msm_bus_node_device_type *info, ++ void __iomem *qos_base, ++ uint32_t qos_off, uint32_t qos_delta, ++ uint32_t qos_freq) ++{ ++ int i; ++ struct msm_bus_bimc_qos_mode qmode; ++ ++ switch (info->node_info->qos_params.mode) { ++ case BIMC_QOS_MODE_FIXED: ++ qmode.fixed.prio_level = info->node_info->qos_params.prio_lvl; ++ qmode.fixed.areq_prio_rd = info->node_info->qos_params.prio_rd; ++ qmode.fixed.areq_prio_wr = info->node_info->qos_params.prio_wr; ++ break; ++ case BIMC_QOS_MODE_LIMITER: ++ qmode.rl.qhealth[0].limit_commands = 1; ++ qmode.rl.qhealth[1].limit_commands = 0; ++ qmode.rl.qhealth[2].limit_commands = 0; ++ qmode.rl.qhealth[3].limit_commands = 0; ++ break; ++ default: ++ break; ++ } ++ ++ if (ZERO_OR_NULL_PTR(info->node_info->qport)) { ++ MSM_BUS_DBG("No QoS Ports to init\n"); ++ return 0; ++ } ++ ++ for (i = 0; i < info->node_info->num_qports; i++) { ++ /* If not in bypass mode, update priority */ ++ if (info->node_info->qos_params.mode != BIMC_QOS_MODE_BYPASS) ++ msm_bus_bimc_set_qos_prio(qos_base, info->node_info-> ++ qport[i], info->node_info->qos_params.mode, ++ &qmode); ++ ++ /* set mode */ ++ if (info->node_info->qos_params.mode == BIMC_QOS_MODE_LIMITER) ++ bke_switch(qos_base, info->node_info->qport[i], ++ BKE_OFF, BIMC_QOS_MODE_FIXED); ++ else ++ msm_bus_bimc_set_qos_mode(qos_base, ++ info->node_info->qport[i], ++ info->node_info->qos_params.mode); ++ } ++ ++ return 0; ++} ++ ++static int msm_bus_bimc_set_bw(struct msm_bus_node_device_type *dev, ++ void __iomem *qos_base, uint32_t qos_off, ++ uint32_t qos_delta, uint32_t qos_freq) ++{ ++ struct msm_bus_bimc_qos_bw qbw; ++ int i; ++ int64_t bw = 0; ++ int ret = 0; ++ struct msm_bus_node_info_type *info = dev->node_info; ++ ++ if (info && info->num_qports && ++ ((info->qos_params.mode == BIMC_QOS_MODE_LIMITER) || ++ (info->qos_params.mode == BIMC_QOS_MODE_REGULATOR))) { ++ bw = msm_bus_div64(info->num_qports, ++ dev->node_ab.ab[DUAL_CTX]); ++ ++ for (i = 0; i < info->num_qports; i++) { ++ MSM_BUS_DBG("BIMC: Update mas_bw for ID: %d -> %llu\n", ++ info->id, bw); ++ ++ if (!info->qport) { ++ MSM_BUS_DBG("No qos ports to update!\n"); ++ break; ++ } ++ ++ qbw.bw = bw + info->qos_params.bw_buffer; ++ trace_bus_bimc_config_limiter(info->id, bw); ++ ++ /* Default to gp of 5us */ ++ qbw.gp = (info->qos_params.gp ? ++ info->qos_params.gp : 5000); ++ /* Default to thmp of 50% */ ++ qbw.thmp = (info->qos_params.thmp ? ++ info->qos_params.thmp : 50); ++ /* ++ * If the BW vote is 0 then set the QoS mode to ++ * Fixed. ++ */ ++ if (bw) { ++ bimc_set_static_qos_bw(qos_base, qos_freq, ++ info->qport[i], &qbw); ++ bke_switch(qos_base, info->qport[i], ++ BKE_ON, info->qos_params.mode); ++ } else { ++ bke_switch(qos_base, info->qport[i], ++ BKE_OFF, BIMC_QOS_MODE_FIXED); ++ } ++ } ++ } ++ return ret; ++} ++ ++int msm_bus_bimc_hw_init(struct msm_bus_fabric_registration *pdata, ++ struct msm_bus_hw_algorithm *hw_algo) ++{ ++ /* Set interleaving to true by default */ ++ MSM_BUS_DBG("\nInitializing BIMC...\n"); ++ pdata->il_flag = true; ++ hw_algo->allocate_commit_data = msm_bus_bimc_allocate_commit_data; ++ hw_algo->allocate_hw_data = msm_bus_bimc_allocate_bimc_data; ++ hw_algo->node_init = msm_bus_bimc_node_init; ++ hw_algo->free_commit_data = free_commit_data; ++ hw_algo->update_bw = msm_bus_bimc_update_bw; ++ hw_algo->commit = msm_bus_bimc_commit; ++ hw_algo->port_halt = msm_bus_bimc_port_halt; ++ hw_algo->port_unhalt = msm_bus_bimc_port_unhalt; ++ hw_algo->config_master = msm_bus_bimc_config_master; ++ hw_algo->config_limiter = msm_bus_bimc_config_limiter; ++ hw_algo->update_bw_reg = msm_bus_bimc_update_bw_reg; ++ /* BIMC slaves are shared. Slave registers are set through RPM */ ++ if (!pdata->ahb) ++ pdata->rpm_enabled = 1; ++ return 0; ++} ++ ++int msm_bus_bimc_set_ops(struct msm_bus_node_device_type *bus_dev) ++{ ++ if (!bus_dev) ++ return -ENODEV; ++ else { ++ bus_dev->fabdev->noc_ops.qos_init = msm_bus_bimc_qos_init; ++ bus_dev->fabdev->noc_ops.set_bw = msm_bus_bimc_set_bw; ++ bus_dev->fabdev->noc_ops.limit_mport = msm_bus_bimc_limit_mport; ++ bus_dev->fabdev->noc_ops.update_bw_reg = ++ msm_bus_bimc_update_bw_reg; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(msm_bus_bimc_set_ops); +--- /dev/null ++++ b/drivers/bus/msm_bus/msm_bus_bimc.h +@@ -0,0 +1,127 @@ ++/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _ARCH_ARM_MACH_MSM_BUS_BIMC_H ++#define _ARCH_ARM_MACH_MSM_BUS_BIMC_H ++ ++struct msm_bus_bimc_params { ++ uint32_t bus_id; ++ uint32_t addr_width; ++ uint32_t data_width; ++ uint32_t nmasters; ++ uint32_t nslaves; ++}; ++ ++struct msm_bus_bimc_commit { ++ struct msm_bus_node_hw_info *mas; ++ struct msm_bus_node_hw_info *slv; ++}; ++ ++struct msm_bus_bimc_info { ++ void __iomem *base; ++ uint32_t base_addr; ++ uint32_t qos_freq; ++ struct msm_bus_bimc_params params; ++ struct msm_bus_bimc_commit cdata[NUM_CTX]; ++}; ++ ++struct msm_bus_bimc_node { ++ uint32_t conn_mask; ++ uint32_t data_width; ++ uint8_t slv_arb_mode; ++}; ++ ++enum msm_bus_bimc_arb_mode { ++ BIMC_ARB_MODE_RR = 0, ++ BIMC_ARB_MODE_PRIORITY_RR, ++ BIMC_ARB_MODE_TIERED_RR, ++}; ++ ++ ++enum msm_bus_bimc_interleave { ++ BIMC_INTERLEAVE_NONE = 0, ++ BIMC_INTERLEAVE_ODD, ++ BIMC_INTERLEAVE_EVEN, ++}; ++ ++struct msm_bus_bimc_slave_seg { ++ bool enable; ++ uint64_t start_addr; ++ uint64_t seg_size; ++ uint8_t interleave; ++}; ++ ++enum msm_bus_bimc_qos_mode_type { ++ BIMC_QOS_MODE_FIXED = 0, ++ BIMC_QOS_MODE_LIMITER, ++ BIMC_QOS_MODE_BYPASS, ++ BIMC_QOS_MODE_REGULATOR, ++}; ++ ++struct msm_bus_bimc_qos_health { ++ bool limit_commands; ++ uint32_t areq_prio; ++ uint32_t prio_level; ++}; ++ ++struct msm_bus_bimc_mode_fixed { ++ uint32_t prio_level; ++ uint32_t areq_prio_rd; ++ uint32_t areq_prio_wr; ++}; ++ ++struct msm_bus_bimc_mode_rl { ++ uint8_t qhealthnum; ++ struct msm_bus_bimc_qos_health qhealth[4]; ++}; ++ ++struct msm_bus_bimc_qos_mode { ++ uint8_t mode; ++ struct msm_bus_bimc_mode_fixed fixed; ++ struct msm_bus_bimc_mode_rl rl; ++}; ++ ++struct msm_bus_bimc_qos_bw { ++ uint64_t bw; /* bw is in Bytes/sec */ ++ uint32_t ws; /* Window size in nano seconds*/ ++ int64_t thh; /* Threshold high, bytes per second */ ++ int64_t thm; /* Threshold medium, bytes per second */ ++ int64_t thl; /* Threshold low, bytes per second */ ++ u32 gp; /* Grant Period in micro seconds */ ++ u32 thmp; /* Threshold medium in percentage */ ++}; ++ ++struct msm_bus_bimc_clk_gate { ++ bool core_clk_gate_en; ++ bool arb_clk_gate_en; /* For arbiter */ ++ bool port_clk_gate_en; /* For regs on BIMC core clock */ ++}; ++ ++void msm_bus_bimc_set_slave_seg(struct msm_bus_bimc_info *binfo, ++ uint32_t slv_index, uint32_t seg_index, ++ struct msm_bus_bimc_slave_seg *bsseg); ++void msm_bus_bimc_set_slave_clk_gate(struct msm_bus_bimc_info *binfo, ++ uint32_t slv_index, struct msm_bus_bimc_clk_gate *bgate); ++void msm_bus_bimc_set_mas_clk_gate(struct msm_bus_bimc_info *binfo, ++ uint32_t mas_index, struct msm_bus_bimc_clk_gate *bgate); ++void msm_bus_bimc_arb_en(struct msm_bus_bimc_info *binfo, ++ uint32_t slv_index, bool en); ++void msm_bus_bimc_get_params(struct msm_bus_bimc_info *binfo, ++ struct msm_bus_bimc_params *params); ++void msm_bus_bimc_get_mas_params(struct msm_bus_bimc_info *binfo, ++ uint32_t mas_index, struct msm_bus_bimc_node *mparams); ++void msm_bus_bimc_get_slv_params(struct msm_bus_bimc_info *binfo, ++ uint32_t slv_index, struct msm_bus_bimc_node *sparams); ++bool msm_bus_bimc_get_arb_en(struct msm_bus_bimc_info *binfo, ++ uint32_t slv_index); ++ ++#endif /*_ARCH_ARM_MACH_MSM_BUS_BIMC_H*/ +--- /dev/null ++++ b/drivers/bus/msm_bus/msm_bus_client_api.c +@@ -0,0 +1,83 @@ ++/* Copyright (c) 2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "msm-bus.h" ++#include "msm_bus_core.h" ++ ++struct msm_bus_arb_ops arb_ops; ++ ++/** ++ * msm_bus_scale_register_client() - Register the clients with the msm bus ++ * driver ++ * @pdata: Platform data of the client, containing src, dest, ab, ib. ++ * Return non-zero value in case of success, 0 in case of failure. ++ * ++ * Client data contains the vectors specifying arbitrated bandwidth (ab) ++ * and instantaneous bandwidth (ib) requested between a particular ++ * src and dest. ++ */ ++uint32_t msm_bus_scale_register_client(struct msm_bus_scale_pdata *pdata) ++{ ++ if (arb_ops.register_client) ++ return arb_ops.register_client(pdata); ++ else { ++ pr_err("%s: Bus driver not ready.", ++ __func__); ++ return 0; ++ } ++} ++EXPORT_SYMBOL(msm_bus_scale_register_client); ++ ++/** ++ * msm_bus_scale_client_update_request() - Update the request for bandwidth ++ * from a particular client ++ * ++ * cl: Handle to the client ++ * index: Index into the vector, to which the bw and clock values need to be ++ * updated ++ */ ++int msm_bus_scale_client_update_request(uint32_t cl, unsigned int index) ++{ ++ if (arb_ops.update_request) ++ return arb_ops.update_request(cl, index); ++ else { ++ pr_err("%s: Bus driver not ready.", ++ __func__); ++ return -EPROBE_DEFER; ++ } ++} ++EXPORT_SYMBOL(msm_bus_scale_client_update_request); ++ ++/** ++ * msm_bus_scale_unregister_client() - Unregister the client from the bus driver ++ * @cl: Handle to the client ++ */ ++void msm_bus_scale_unregister_client(uint32_t cl) ++{ ++ if (arb_ops.unregister_client) ++ arb_ops.unregister_client(cl); ++ else { ++ pr_err("%s: Bus driver not ready.", ++ __func__); ++ } ++} ++EXPORT_SYMBOL(msm_bus_scale_unregister_client); +--- /dev/null ++++ b/drivers/bus/msm_bus/msm_bus_core.c +@@ -0,0 +1,125 @@ ++/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "msm-bus-board.h" ++#include "msm-bus.h" ++#include "msm_bus_core.h" ++ ++static atomic_t num_fab = ATOMIC_INIT(0); ++ ++int msm_bus_get_num_fab(void) ++{ ++ return atomic_read(&num_fab); ++} ++ ++int msm_bus_device_match(struct device *dev, void *id) ++{ ++ struct msm_bus_fabric_device *fabdev = to_msm_bus_fabric_device(dev); ++ ++ if (!fabdev) { ++ MSM_BUS_WARN("Fabric %p returning 0\n", fabdev); ++ return 0; ++ } ++ return fabdev->id == *(int *)id; ++} ++ ++static void msm_bus_release(struct device *device) ++{ ++} ++ ++struct bus_type msm_bus_type = { ++ .name = "msm-bus-type", ++}; ++EXPORT_SYMBOL(msm_bus_type); ++ ++/** ++ * msm_bus_get_fabric_device() - This function is used to search for ++ * the fabric device on the bus ++ * @fabid: Fabric id ++ * Function returns: Pointer to the fabric device ++ */ ++struct msm_bus_fabric_device *msm_bus_get_fabric_device(int fabid) ++{ ++ struct device *dev; ++ struct msm_bus_fabric_device *fabric; ++ dev = bus_find_device(&msm_bus_type, NULL, (void *)&fabid, ++ msm_bus_device_match); ++ if (!dev) ++ return NULL; ++ fabric = to_msm_bus_fabric_device(dev); ++ return fabric; ++} ++ ++/** ++ * msm_bus_fabric_device_register() - Registers a fabric on msm bus ++ * @fabdev: Fabric device to be registered ++ */ ++int msm_bus_fabric_device_register(struct msm_bus_fabric_device *fabdev) ++{ ++ int ret = 0; ++ fabdev->dev.bus = &msm_bus_type; ++ fabdev->dev.release = msm_bus_release; ++ ret = dev_set_name(&fabdev->dev, fabdev->name); ++ if (ret) { ++ MSM_BUS_ERR("error setting dev name\n"); ++ goto err; ++ } ++ ++ ret = device_register(&fabdev->dev); ++ if (ret < 0) { ++ MSM_BUS_ERR("error registering device%d %s\n", ++ ret, fabdev->name); ++ goto err; ++ } ++ atomic_inc(&num_fab); ++err: ++ return ret; ++} ++ ++/** ++ * msm_bus_fabric_device_unregister() - Unregisters the fabric ++ * devices from the msm bus ++ */ ++void msm_bus_fabric_device_unregister(struct msm_bus_fabric_device *fabdev) ++{ ++ device_unregister(&fabdev->dev); ++ atomic_dec(&num_fab); ++} ++ ++static void __exit msm_bus_exit(void) ++{ ++ bus_unregister(&msm_bus_type); ++} ++ ++static int __init msm_bus_init(void) ++{ ++ int retval = 0; ++ retval = bus_register(&msm_bus_type); ++ if (retval) ++ MSM_BUS_ERR("bus_register error! %d\n", ++ retval); ++ return retval; ++} ++postcore_initcall(msm_bus_init); ++module_exit(msm_bus_exit); ++MODULE_LICENSE("GPL v2"); ++MODULE_VERSION("0.2"); ++MODULE_ALIAS("platform:msm_bus"); +--- /dev/null ++++ b/drivers/bus/msm_bus/msm_bus_core.h +@@ -0,0 +1,375 @@ ++/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _ARCH_ARM_MACH_MSM_BUS_CORE_H ++#define _ARCH_ARM_MACH_MSM_BUS_CORE_H ++ ++#include ++#include ++#include ++#include ++#include "msm-bus-board.h" ++#include "msm-bus.h" ++ ++#define MSM_BUS_DBG(msg, ...) \ ++ pr_debug(msg, ## __VA_ARGS__) ++#define MSM_BUS_ERR(msg, ...) \ ++ pr_err(msg, ## __VA_ARGS__) ++#define MSM_BUS_WARN(msg, ...) \ ++ pr_warn(msg, ## __VA_ARGS__) ++#define MSM_FAB_ERR(msg, ...) \ ++ dev_err(&fabric->fabdev.dev, msg, ## __VA_ARGS__) ++ ++#define IS_MASTER_VALID(mas) \ ++ (((mas >= MSM_BUS_MASTER_FIRST) && (mas <= MSM_BUS_MASTER_LAST)) \ ++ ? 1 : 0) ++#define IS_SLAVE_VALID(slv) \ ++ (((slv >= MSM_BUS_SLAVE_FIRST) && (slv <= MSM_BUS_SLAVE_LAST)) ? 1 : 0) ++ ++#define INTERLEAVED_BW(fab_pdata, bw, ports) \ ++ ((fab_pdata->il_flag) ? ((bw < 0) \ ++ ? -msm_bus_div64((ports), (-bw)) : msm_bus_div64((ports), (bw))) : (bw)) ++#define INTERLEAVED_VAL(fab_pdata, n) \ ++ ((fab_pdata->il_flag) ? (n) : 1) ++#define KBTOB(a) (a * 1000ULL) ++ ++enum msm_bus_dbg_op_type { ++ MSM_BUS_DBG_UNREGISTER = -2, ++ MSM_BUS_DBG_REGISTER, ++ MSM_BUS_DBG_OP = 1, ++}; ++ ++enum msm_bus_hw_sel { ++ MSM_BUS_RPM = 0, ++ MSM_BUS_NOC, ++ MSM_BUS_BIMC, ++}; ++ ++struct msm_bus_arb_ops { ++ uint32_t (*register_client)(struct msm_bus_scale_pdata *pdata); ++ int (*update_request)(uint32_t cl, unsigned int index); ++ void (*unregister_client)(uint32_t cl); ++}; ++ ++enum { ++ SLAVE_NODE, ++ MASTER_NODE, ++ CLK_NODE, ++ NR_LIM_NODE, ++}; ++ ++ ++extern struct bus_type msm_bus_type; ++extern struct msm_bus_arb_ops arb_ops; ++extern void msm_bus_arb_setops_legacy(struct msm_bus_arb_ops *arb_ops); ++ ++struct msm_bus_node_info { ++ unsigned int id; ++ unsigned int priv_id; ++ unsigned int mas_hw_id; ++ unsigned int slv_hw_id; ++ int gateway; ++ int *masterp; ++ int *qport; ++ int num_mports; ++ int *slavep; ++ int num_sports; ++ int *tier; ++ int num_tiers; ++ int ahb; ++ int hw_sel; ++ const char *slaveclk[NUM_CTX]; ++ const char *memclk[NUM_CTX]; ++ const char *iface_clk_node; ++ unsigned int buswidth; ++ unsigned int ws; ++ unsigned int mode; ++ unsigned int perm_mode; ++ unsigned int prio_lvl; ++ unsigned int prio_rd; ++ unsigned int prio_wr; ++ unsigned int prio1; ++ unsigned int prio0; ++ unsigned int num_thresh; ++ u64 *th; ++ u64 cur_lim_bw; ++ unsigned int mode_thresh; ++ bool dual_conf; ++ u64 *bimc_bw; ++ bool nr_lim; ++ u32 ff; ++ bool rt_mas; ++ u32 bimc_gp; ++ u32 bimc_thmp; ++ u64 floor_bw; ++ const char *name; ++}; ++ ++struct path_node { ++ uint64_t clk[NUM_CTX]; ++ uint64_t bw[NUM_CTX]; ++ uint64_t *sel_clk; ++ uint64_t *sel_bw; ++ int next; ++}; ++ ++struct msm_bus_link_info { ++ uint64_t clk[NUM_CTX]; ++ uint64_t *sel_clk; ++ uint64_t memclk; ++ int64_t bw[NUM_CTX]; ++ int64_t *sel_bw; ++ int *tier; ++ int num_tiers; ++}; ++ ++struct nodeclk { ++ struct clk *clk; ++ uint64_t rate; ++ bool dirty; ++ bool enable; ++}; ++ ++struct msm_bus_inode_info { ++ struct msm_bus_node_info *node_info; ++ uint64_t max_bw; ++ uint64_t max_clk; ++ uint64_t cur_lim_bw; ++ uint64_t cur_prg_bw; ++ struct msm_bus_link_info link_info; ++ int num_pnodes; ++ struct path_node *pnode; ++ int commit_index; ++ struct nodeclk nodeclk[NUM_CTX]; ++ struct nodeclk memclk[NUM_CTX]; ++ struct nodeclk iface_clk; ++ void *hw_data; ++}; ++ ++struct msm_bus_node_hw_info { ++ bool dirty; ++ unsigned int hw_id; ++ uint64_t bw; ++}; ++ ++struct msm_bus_hw_algorithm { ++ int (*allocate_commit_data)(struct msm_bus_fabric_registration ++ *fab_pdata, void **cdata, int ctx); ++ void *(*allocate_hw_data)(struct platform_device *pdev, ++ struct msm_bus_fabric_registration *fab_pdata); ++ void (*node_init)(void *hw_data, struct msm_bus_inode_info *info); ++ void (*free_commit_data)(void *cdata); ++ void (*update_bw)(struct msm_bus_inode_info *hop, ++ struct msm_bus_inode_info *info, ++ struct msm_bus_fabric_registration *fab_pdata, ++ void *sel_cdata, int *master_tiers, ++ int64_t add_bw); ++ void (*fill_cdata_buffer)(int *curr, char *buf, const int max_size, ++ void *cdata, int nmasters, int nslaves, int ntslaves); ++ int (*commit)(struct msm_bus_fabric_registration ++ *fab_pdata, void *hw_data, void **cdata); ++ int (*port_unhalt)(uint32_t haltid, uint8_t mport); ++ int (*port_halt)(uint32_t haltid, uint8_t mport); ++ void (*config_master)(struct msm_bus_fabric_registration *fab_pdata, ++ struct msm_bus_inode_info *info, ++ uint64_t req_clk, uint64_t req_bw); ++ void (*config_limiter)(struct msm_bus_fabric_registration *fab_pdata, ++ struct msm_bus_inode_info *info); ++ bool (*update_bw_reg)(int mode); ++}; ++ ++struct msm_bus_fabric_device { ++ int id; ++ const char *name; ++ struct device dev; ++ const struct msm_bus_fab_algorithm *algo; ++ const struct msm_bus_board_algorithm *board_algo; ++ struct msm_bus_hw_algorithm hw_algo; ++ int visited; ++ int num_nr_lim; ++ u64 nr_lim_thresh; ++ u32 eff_fact; ++}; ++#define to_msm_bus_fabric_device(d) container_of(d, \ ++ struct msm_bus_fabric_device, d) ++ ++struct msm_bus_fabric { ++ struct msm_bus_fabric_device fabdev; ++ int ahb; ++ void *cdata[NUM_CTX]; ++ bool arb_dirty; ++ bool clk_dirty; ++ struct radix_tree_root fab_tree; ++ int num_nodes; ++ struct list_head gateways; ++ struct msm_bus_inode_info info; ++ struct msm_bus_fabric_registration *pdata; ++ void *hw_data; ++}; ++#define to_msm_bus_fabric(d) container_of(d, \ ++ struct msm_bus_fabric, d) ++ ++ ++struct msm_bus_fab_algorithm { ++ int (*update_clks)(struct msm_bus_fabric_device *fabdev, ++ struct msm_bus_inode_info *pme, int index, ++ uint64_t curr_clk, uint64_t req_clk, ++ uint64_t bwsum, int flag, int ctx, ++ unsigned int cl_active_flag); ++ int (*port_halt)(struct msm_bus_fabric_device *fabdev, int portid); ++ int (*port_unhalt)(struct msm_bus_fabric_device *fabdev, int portid); ++ int (*commit)(struct msm_bus_fabric_device *fabdev); ++ struct msm_bus_inode_info *(*find_node)(struct msm_bus_fabric_device ++ *fabdev, int id); ++ struct msm_bus_inode_info *(*find_gw_node)(struct msm_bus_fabric_device ++ *fabdev, int id); ++ struct list_head *(*get_gw_list)(struct msm_bus_fabric_device *fabdev); ++ void (*update_bw)(struct msm_bus_fabric_device *fabdev, struct ++ msm_bus_inode_info * hop, struct msm_bus_inode_info *info, ++ int64_t add_bw, int *master_tiers, int ctx); ++ void (*config_master)(struct msm_bus_fabric_device *fabdev, ++ struct msm_bus_inode_info *info, uint64_t req_clk, ++ uint64_t req_bw); ++ void (*config_limiter)(struct msm_bus_fabric_device *fabdev, ++ struct msm_bus_inode_info *info); ++}; ++ ++struct msm_bus_board_algorithm { ++ int board_nfab; ++ void (*assign_iids)(struct msm_bus_fabric_registration *fabreg, ++ int fabid); ++ int (*get_iid)(int id); ++}; ++ ++/** ++ * Used to store the list of fabrics and other info to be ++ * maintained outside the fabric structure. ++ * Used while calculating path, and to find fabric ptrs ++ */ ++struct msm_bus_fabnodeinfo { ++ struct list_head list; ++ struct msm_bus_inode_info *info; ++}; ++ ++struct msm_bus_client { ++ int id; ++ struct msm_bus_scale_pdata *pdata; ++ int *src_pnode; ++ int curr; ++}; ++ ++uint64_t msm_bus_div64(unsigned int width, uint64_t bw); ++int msm_bus_fabric_device_register(struct msm_bus_fabric_device *fabric); ++void msm_bus_fabric_device_unregister(struct msm_bus_fabric_device *fabric); ++struct msm_bus_fabric_device *msm_bus_get_fabric_device(int fabid); ++int msm_bus_get_num_fab(void); ++ ++ ++int msm_bus_hw_fab_init(struct msm_bus_fabric_registration *pdata, ++ struct msm_bus_hw_algorithm *hw_algo); ++void msm_bus_board_init(struct msm_bus_fabric_registration *pdata); ++void msm_bus_board_set_nfab(struct msm_bus_fabric_registration *pdata, ++ int nfab); ++#if defined(CONFIG_MSM_RPM_SMD) ++int msm_bus_rpm_hw_init(struct msm_bus_fabric_registration *pdata, ++ struct msm_bus_hw_algorithm *hw_algo); ++int msm_bus_remote_hw_commit(struct msm_bus_fabric_registration ++ *fab_pdata, void *hw_data, void **cdata); ++void msm_bus_rpm_fill_cdata_buffer(int *curr, char *buf, const int max_size, ++ void *cdata, int nmasters, int nslaves, int ntslaves); ++#else ++static inline int msm_bus_rpm_hw_init(struct msm_bus_fabric_registration *pdata, ++ struct msm_bus_hw_algorithm *hw_algo) ++{ ++ return 0; ++} ++static inline int msm_bus_remote_hw_commit(struct msm_bus_fabric_registration ++ *fab_pdata, void *hw_data, void **cdata) ++{ ++ return 0; ++} ++static inline void msm_bus_rpm_fill_cdata_buffer(int *curr, char *buf, ++ const int max_size, void *cdata, int nmasters, int nslaves, ++ int ntslaves) ++{ ++} ++#endif ++ ++int msm_bus_noc_hw_init(struct msm_bus_fabric_registration *pdata, ++ struct msm_bus_hw_algorithm *hw_algo); ++int msm_bus_bimc_hw_init(struct msm_bus_fabric_registration *pdata, ++ struct msm_bus_hw_algorithm *hw_algo); ++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_MSM_BUS_SCALING) ++void msm_bus_dbg_client_data(struct msm_bus_scale_pdata *pdata, int index, ++ uint32_t cl); ++void msm_bus_dbg_commit_data(const char *fabname, void *cdata, ++ int nmasters, int nslaves, int ntslaves, int op); ++#else ++static inline void msm_bus_dbg_client_data(struct msm_bus_scale_pdata *pdata, ++ int index, uint32_t cl) ++{ ++} ++static inline void msm_bus_dbg_commit_data(const char *fabname, ++ void *cdata, int nmasters, int nslaves, int ntslaves, ++ int op) ++{ ++} ++#endif ++ ++#ifdef CONFIG_CORESIGHT ++int msmbus_coresight_init(struct platform_device *pdev); ++void msmbus_coresight_remove(struct platform_device *pdev); ++int msmbus_coresight_init_adhoc(struct platform_device *pdev, ++ struct device_node *of_node); ++void msmbus_coresight_remove_adhoc(struct platform_device *pdev); ++#else ++static inline int msmbus_coresight_init(struct platform_device *pdev) ++{ ++ return 0; ++} ++ ++static inline void msmbus_coresight_remove(struct platform_device *pdev) ++{ ++} ++ ++static inline int msmbus_coresight_init_adhoc(struct platform_device *pdev, ++ struct device_node *of_node) ++{ ++ return 0; ++} ++ ++static inline void msmbus_coresight_remove_adhoc(struct platform_device *pdev) ++{ ++} ++#endif ++ ++ ++#ifdef CONFIG_OF ++void msm_bus_of_get_nfab(struct platform_device *pdev, ++ struct msm_bus_fabric_registration *pdata); ++struct msm_bus_fabric_registration ++ *msm_bus_of_get_fab_data(struct platform_device *pdev); ++#else ++static inline void msm_bus_of_get_nfab(struct platform_device *pdev, ++ struct msm_bus_fabric_registration *pdata) ++{ ++ return; ++} ++ ++static inline struct msm_bus_fabric_registration ++ *msm_bus_of_get_fab_data(struct platform_device *pdev) ++{ ++ return NULL; ++} ++#endif ++ ++#endif /*_ARCH_ARM_MACH_MSM_BUS_CORE_H*/ +--- /dev/null ++++ b/drivers/bus/msm_bus/msm_bus_dbg.c +@@ -0,0 +1,810 @@ ++/* Copyright (c) 2010-2012, 2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ */ ++ ++#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "msm-bus-board.h" ++#include "msm-bus.h" ++#include "msm_bus_rules.h" ++#include "msm_bus_core.h" ++#include "msm_bus_adhoc.h" ++ ++#define CREATE_TRACE_POINTS ++#include ++ ++#define MAX_BUFF_SIZE 4096 ++#define FILL_LIMIT 128 ++ ++static struct dentry *clients; ++static struct dentry *dir; ++static DEFINE_MUTEX(msm_bus_dbg_fablist_lock); ++struct msm_bus_dbg_state { ++ uint32_t cl; ++ uint8_t enable; ++ uint8_t current_index; ++} clstate; ++ ++struct msm_bus_cldata { ++ const struct msm_bus_scale_pdata *pdata; ++ int index; ++ uint32_t clid; ++ int size; ++ struct dentry *file; ++ struct list_head list; ++ char buffer[MAX_BUFF_SIZE]; ++}; ++ ++struct msm_bus_fab_list { ++ const char *name; ++ int size; ++ struct dentry *file; ++ struct list_head list; ++ char buffer[MAX_BUFF_SIZE]; ++}; ++ ++static char *rules_buf; ++ ++LIST_HEAD(fabdata_list); ++LIST_HEAD(cl_list); ++ ++/** ++ * The following structures and funtions are used for ++ * the test-client which can be created at run-time. ++ */ ++ ++static struct msm_bus_vectors init_vectors[1]; ++static struct msm_bus_vectors current_vectors[1]; ++static struct msm_bus_vectors requested_vectors[1]; ++ ++static struct msm_bus_paths shell_client_usecases[] = { ++ { ++ .num_paths = ARRAY_SIZE(init_vectors), ++ .vectors = init_vectors, ++ }, ++ { ++ .num_paths = ARRAY_SIZE(current_vectors), ++ .vectors = current_vectors, ++ }, ++ { ++ .num_paths = ARRAY_SIZE(requested_vectors), ++ .vectors = requested_vectors, ++ }, ++}; ++ ++static struct msm_bus_scale_pdata shell_client = { ++ .usecase = shell_client_usecases, ++ .num_usecases = ARRAY_SIZE(shell_client_usecases), ++ .name = "test-client", ++}; ++ ++static void msm_bus_dbg_init_vectors(void) ++{ ++ init_vectors[0].src = -1; ++ init_vectors[0].dst = -1; ++ init_vectors[0].ab = 0; ++ init_vectors[0].ib = 0; ++ current_vectors[0].src = -1; ++ current_vectors[0].dst = -1; ++ current_vectors[0].ab = 0; ++ current_vectors[0].ib = 0; ++ requested_vectors[0].src = -1; ++ requested_vectors[0].dst = -1; ++ requested_vectors[0].ab = 0; ++ requested_vectors[0].ib = 0; ++ clstate.enable = 0; ++ clstate.current_index = 0; ++} ++ ++static int msm_bus_dbg_update_cl_request(uint32_t cl) ++{ ++ int ret = 0; ++ ++ if (clstate.current_index < 2) ++ clstate.current_index = 2; ++ else { ++ clstate.current_index = 1; ++ current_vectors[0].ab = requested_vectors[0].ab; ++ current_vectors[0].ib = requested_vectors[0].ib; ++ } ++ ++ if (clstate.enable) { ++ MSM_BUS_DBG("Updating request for shell client, index: %d\n", ++ clstate.current_index); ++ ret = msm_bus_scale_client_update_request(clstate.cl, ++ clstate.current_index); ++ } else ++ MSM_BUS_DBG("Enable bit not set. Skipping update request\n"); ++ ++ return ret; ++} ++ ++static void msm_bus_dbg_unregister_client(uint32_t cl) ++{ ++ MSM_BUS_DBG("Unregistering shell client\n"); ++ msm_bus_scale_unregister_client(clstate.cl); ++ clstate.cl = 0; ++} ++ ++static uint32_t msm_bus_dbg_register_client(void) ++{ ++ int ret = 0; ++ ++ if (init_vectors[0].src != requested_vectors[0].src) { ++ MSM_BUS_DBG("Shell client master changed. Unregistering\n"); ++ msm_bus_dbg_unregister_client(clstate.cl); ++ } ++ if (init_vectors[0].dst != requested_vectors[0].dst) { ++ MSM_BUS_DBG("Shell client slave changed. Unregistering\n"); ++ msm_bus_dbg_unregister_client(clstate.cl); ++ } ++ ++ current_vectors[0].src = init_vectors[0].src; ++ requested_vectors[0].src = init_vectors[0].src; ++ current_vectors[0].dst = init_vectors[0].dst; ++ requested_vectors[0].dst = init_vectors[0].dst; ++ ++ if (!clstate.enable) { ++ MSM_BUS_DBG("Enable bit not set, skipping registration: cl " ++ "%d\n", clstate.cl); ++ return 0; ++ } ++ ++ if (clstate.cl) { ++ MSM_BUS_DBG("Client registered, skipping registration\n"); ++ return clstate.cl; ++ } ++ ++ MSM_BUS_DBG("Registering shell client\n"); ++ ret = msm_bus_scale_register_client(&shell_client); ++ return ret; ++} ++ ++static int msm_bus_dbg_mas_get(void *data, u64 *val) ++{ ++ *val = init_vectors[0].src; ++ MSM_BUS_DBG("Get master: %llu\n", *val); ++ return 0; ++} ++ ++static int msm_bus_dbg_mas_set(void *data, u64 val) ++{ ++ init_vectors[0].src = val; ++ MSM_BUS_DBG("Set master: %llu\n", val); ++ clstate.cl = msm_bus_dbg_register_client(); ++ return 0; ++} ++DEFINE_SIMPLE_ATTRIBUTE(shell_client_mas_fops, msm_bus_dbg_mas_get, ++ msm_bus_dbg_mas_set, "%llu\n"); ++ ++static int msm_bus_dbg_slv_get(void *data, u64 *val) ++{ ++ *val = init_vectors[0].dst; ++ MSM_BUS_DBG("Get slave: %llu\n", *val); ++ return 0; ++} ++ ++static int msm_bus_dbg_slv_set(void *data, u64 val) ++{ ++ init_vectors[0].dst = val; ++ MSM_BUS_DBG("Set slave: %llu\n", val); ++ clstate.cl = msm_bus_dbg_register_client(); ++ return 0; ++} ++DEFINE_SIMPLE_ATTRIBUTE(shell_client_slv_fops, msm_bus_dbg_slv_get, ++ msm_bus_dbg_slv_set, "%llu\n"); ++ ++static int msm_bus_dbg_ab_get(void *data, u64 *val) ++{ ++ *val = requested_vectors[0].ab; ++ MSM_BUS_DBG("Get ab: %llu\n", *val); ++ return 0; ++} ++ ++static int msm_bus_dbg_ab_set(void *data, u64 val) ++{ ++ requested_vectors[0].ab = val; ++ MSM_BUS_DBG("Set ab: %llu\n", val); ++ return 0; ++} ++DEFINE_SIMPLE_ATTRIBUTE(shell_client_ab_fops, msm_bus_dbg_ab_get, ++ msm_bus_dbg_ab_set, "%llu\n"); ++ ++static int msm_bus_dbg_ib_get(void *data, u64 *val) ++{ ++ *val = requested_vectors[0].ib; ++ MSM_BUS_DBG("Get ib: %llu\n", *val); ++ return 0; ++} ++ ++static int msm_bus_dbg_ib_set(void *data, u64 val) ++{ ++ requested_vectors[0].ib = val; ++ MSM_BUS_DBG("Set ib: %llu\n", val); ++ return 0; ++} ++DEFINE_SIMPLE_ATTRIBUTE(shell_client_ib_fops, msm_bus_dbg_ib_get, ++ msm_bus_dbg_ib_set, "%llu\n"); ++ ++static int msm_bus_dbg_en_get(void *data, u64 *val) ++{ ++ *val = clstate.enable; ++ MSM_BUS_DBG("Get enable: %llu\n", *val); ++ return 0; ++} ++ ++static int msm_bus_dbg_en_set(void *data, u64 val) ++{ ++ int ret = 0; ++ ++ clstate.enable = val; ++ if (clstate.enable) { ++ if (!clstate.cl) { ++ MSM_BUS_DBG("client: %u\n", clstate.cl); ++ clstate.cl = msm_bus_dbg_register_client(); ++ if (clstate.cl) ++ ret = msm_bus_dbg_update_cl_request(clstate.cl); ++ } else { ++ MSM_BUS_DBG("update request for cl: %u\n", clstate.cl); ++ ret = msm_bus_dbg_update_cl_request(clstate.cl); ++ } ++ } ++ ++ MSM_BUS_DBG("Set enable: %llu\n", val); ++ return ret; ++} ++DEFINE_SIMPLE_ATTRIBUTE(shell_client_en_fops, msm_bus_dbg_en_get, ++ msm_bus_dbg_en_set, "%llu\n"); ++ ++/** ++ * The following funtions are used for viewing the client data ++ * and changing the client request at run-time ++ */ ++ ++static ssize_t client_data_read(struct file *file, char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ int bsize = 0; ++ uint32_t cl = (uint32_t)(uintptr_t)file->private_data; ++ struct msm_bus_cldata *cldata = NULL; ++ int found = 0; ++ ++ list_for_each_entry(cldata, &cl_list, list) { ++ if (cldata->clid == cl) { ++ found = 1; ++ break; ++ } ++ } ++ if (!found) ++ return 0; ++ ++ bsize = cldata->size; ++ return simple_read_from_buffer(buf, count, ppos, ++ cldata->buffer, bsize); ++} ++ ++static int client_data_open(struct inode *inode, struct file *file) ++{ ++ file->private_data = inode->i_private; ++ return 0; ++} ++ ++static const struct file_operations client_data_fops = { ++ .open = client_data_open, ++ .read = client_data_read, ++}; ++ ++struct dentry *msm_bus_dbg_create(const char *name, mode_t mode, ++ struct dentry *dent, uint32_t clid) ++{ ++ if (dent == NULL) { ++ MSM_BUS_DBG("debugfs not ready yet\n"); ++ return NULL; ++ } ++ return debugfs_create_file(name, mode, dent, (void *)(uintptr_t)clid, ++ &client_data_fops); ++} ++ ++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_MSM_BUS_SCALING) ++static int msm_bus_dbg_record_client(const struct msm_bus_scale_pdata *pdata, ++ int index, uint32_t clid, struct dentry *file) ++{ ++ struct msm_bus_cldata *cldata; ++ ++ cldata = kmalloc(sizeof(struct msm_bus_cldata), GFP_KERNEL); ++ if (!cldata) { ++ MSM_BUS_DBG("Failed to allocate memory for client data\n"); ++ return -ENOMEM; ++ } ++ cldata->pdata = pdata; ++ cldata->index = index; ++ cldata->clid = clid; ++ cldata->file = file; ++ cldata->size = 0; ++ list_add_tail(&cldata->list, &cl_list); ++ return 0; ++} ++ ++static void msm_bus_dbg_free_client(uint32_t clid) ++{ ++ struct msm_bus_cldata *cldata = NULL; ++ ++ list_for_each_entry(cldata, &cl_list, list) { ++ if (cldata->clid == clid) { ++ debugfs_remove(cldata->file); ++ list_del(&cldata->list); ++ kfree(cldata); ++ break; ++ } ++ } ++} ++ ++static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata, ++ int index, uint32_t clid) ++{ ++ int i = 0, j; ++ char *buf = NULL; ++ struct msm_bus_cldata *cldata = NULL; ++ struct timespec ts; ++ int found = 0; ++ ++ list_for_each_entry(cldata, &cl_list, list) { ++ if (cldata->clid == clid) { ++ found = 1; ++ break; ++ } ++ } ++ ++ if (!found) ++ return -ENOENT; ++ ++ if (cldata->file == NULL) { ++ if (pdata->name == NULL) { ++ MSM_BUS_DBG("Client doesn't have a name\n"); ++ return -EINVAL; ++ } ++ cldata->file = msm_bus_dbg_create(pdata->name, S_IRUGO, ++ clients, clid); ++ } ++ ++ if (cldata->size < (MAX_BUFF_SIZE - FILL_LIMIT)) ++ i = cldata->size; ++ else { ++ i = 0; ++ cldata->size = 0; ++ } ++ buf = cldata->buffer; ++ ts = ktime_to_timespec(ktime_get()); ++ i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n%d.%d\n", ++ (int)ts.tv_sec, (int)ts.tv_nsec); ++ i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "curr : %d\n", index); ++ i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "masters: "); ++ ++ for (j = 0; j < pdata->usecase->num_paths; j++) ++ i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "%d ", ++ pdata->usecase[index].vectors[j].src); ++ i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\nslaves : "); ++ for (j = 0; j < pdata->usecase->num_paths; j++) ++ i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "%d ", ++ pdata->usecase[index].vectors[j].dst); ++ i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\nab : "); ++ for (j = 0; j < pdata->usecase->num_paths; j++) ++ i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "%llu ", ++ pdata->usecase[index].vectors[j].ab); ++ i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\nib : "); ++ for (j = 0; j < pdata->usecase->num_paths; j++) ++ i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "%llu ", ++ pdata->usecase[index].vectors[j].ib); ++ i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n"); ++ ++ for (j = 0; j < pdata->usecase->num_paths; j++) ++ trace_bus_update_request((int)ts.tv_sec, (int)ts.tv_nsec, ++ pdata->name, index, ++ pdata->usecase[index].vectors[j].src, ++ pdata->usecase[index].vectors[j].dst, ++ pdata->usecase[index].vectors[j].ab, ++ pdata->usecase[index].vectors[j].ib); ++ ++ cldata->size = i; ++ return i; ++} ++#endif ++ ++static int msm_bus_dbg_update_request(struct msm_bus_cldata *cldata, int index) ++{ ++ int ret = 0; ++ ++ if ((index < 0) || (index > cldata->pdata->num_usecases)) { ++ MSM_BUS_DBG("Invalid index!\n"); ++ return -EINVAL; ++ } ++ ret = msm_bus_scale_client_update_request(cldata->clid, index); ++ return ret; ++} ++ ++static ssize_t msm_bus_dbg_update_request_write(struct file *file, ++ const char __user *ubuf, size_t cnt, loff_t *ppos) ++{ ++ struct msm_bus_cldata *cldata; ++ unsigned long index = 0; ++ int ret = 0; ++ char *chid; ++ char *buf = kmalloc((sizeof(char) * (cnt + 1)), GFP_KERNEL); ++ int found = 0; ++ ++ if (!buf || IS_ERR(buf)) { ++ MSM_BUS_ERR("Memory allocation for buffer failed\n"); ++ return -ENOMEM; ++ } ++ if (cnt == 0) { ++ kfree(buf); ++ return 0; ++ } ++ if (copy_from_user(buf, ubuf, cnt)) { ++ kfree(buf); ++ return -EFAULT; ++ } ++ buf[cnt] = '\0'; ++ chid = buf; ++ MSM_BUS_DBG("buffer: %s\n size: %zu\n", buf, sizeof(ubuf)); ++ ++ list_for_each_entry(cldata, &cl_list, list) { ++ if (strnstr(chid, cldata->pdata->name, cnt)) { ++ found = 1; ++ cldata = cldata; ++ strsep(&chid, " "); ++ if (chid) { ++ ret = kstrtoul(chid, 10, &index); ++ if (ret) { ++ MSM_BUS_DBG("Index conversion" ++ " failed\n"); ++ return -EFAULT; ++ } ++ } else { ++ MSM_BUS_DBG("Error parsing input. Index not" ++ " found\n"); ++ found = 0; ++ } ++ break; ++ } ++ } ++ ++ if (found) ++ msm_bus_dbg_update_request(cldata, index); ++ kfree(buf); ++ return cnt; ++} ++ ++/** ++ * The following funtions are used for viewing the commit data ++ * for each fabric ++ */ ++static ssize_t fabric_data_read(struct file *file, char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct msm_bus_fab_list *fablist = NULL; ++ int bsize = 0; ++ ssize_t ret; ++ const char *name = file->private_data; ++ int found = 0; ++ ++ mutex_lock(&msm_bus_dbg_fablist_lock); ++ list_for_each_entry(fablist, &fabdata_list, list) { ++ if (strcmp(fablist->name, name) == 0) { ++ found = 1; ++ break; ++ } ++ } ++ if (!found) ++ return -ENOENT; ++ bsize = fablist->size; ++ ret = simple_read_from_buffer(buf, count, ppos, ++ fablist->buffer, bsize); ++ mutex_unlock(&msm_bus_dbg_fablist_lock); ++ return ret; ++} ++ ++static const struct file_operations fabric_data_fops = { ++ .open = client_data_open, ++ .read = fabric_data_read, ++}; ++ ++static ssize_t rules_dbg_read(struct file *file, char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ ssize_t ret; ++ memset(rules_buf, 0, MAX_BUFF_SIZE); ++ print_rules_buf(rules_buf, MAX_BUFF_SIZE); ++ ret = simple_read_from_buffer(buf, count, ppos, ++ rules_buf, MAX_BUFF_SIZE); ++ return ret; ++} ++ ++static int rules_dbg_open(struct inode *inode, struct file *file) ++{ ++ file->private_data = inode->i_private; ++ return 0; ++} ++ ++static const struct file_operations rules_dbg_fops = { ++ .open = rules_dbg_open, ++ .read = rules_dbg_read, ++}; ++ ++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_MSM_BUS_SCALING) ++static int msm_bus_dbg_record_fabric(const char *fabname, struct dentry *file) ++{ ++ struct msm_bus_fab_list *fablist; ++ int ret = 0; ++ ++ mutex_lock(&msm_bus_dbg_fablist_lock); ++ fablist = kmalloc(sizeof(struct msm_bus_fab_list), GFP_KERNEL); ++ if (!fablist) { ++ MSM_BUS_DBG("Failed to allocate memory for commit data\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ fablist->name = fabname; ++ fablist->size = 0; ++ list_add_tail(&fablist->list, &fabdata_list); ++err: ++ mutex_unlock(&msm_bus_dbg_fablist_lock); ++ return ret; ++} ++ ++static void msm_bus_dbg_free_fabric(const char *fabname) ++{ ++ struct msm_bus_fab_list *fablist = NULL; ++ ++ mutex_lock(&msm_bus_dbg_fablist_lock); ++ list_for_each_entry(fablist, &fabdata_list, list) { ++ if (strcmp(fablist->name, fabname) == 0) { ++ debugfs_remove(fablist->file); ++ list_del(&fablist->list); ++ kfree(fablist); ++ break; ++ } ++ } ++ mutex_unlock(&msm_bus_dbg_fablist_lock); ++} ++ ++static int msm_bus_dbg_fill_fab_buffer(const char *fabname, ++ void *cdata, int nmasters, int nslaves, ++ int ntslaves) ++{ ++ int i; ++ char *buf = NULL; ++ struct msm_bus_fab_list *fablist = NULL; ++ struct timespec ts; ++ int found = 0; ++ ++ mutex_lock(&msm_bus_dbg_fablist_lock); ++ list_for_each_entry(fablist, &fabdata_list, list) { ++ if (strcmp(fablist->name, fabname) == 0) { ++ found = 1; ++ break; ++ } ++ } ++ if (!found) ++ return -ENOENT; ++ ++ if (fablist->file == NULL) { ++ MSM_BUS_DBG("Fabric dbg entry does not exist\n"); ++ mutex_unlock(&msm_bus_dbg_fablist_lock); ++ return -EFAULT; ++ } ++ ++ if (fablist->size < MAX_BUFF_SIZE - 256) ++ i = fablist->size; ++ else { ++ i = 0; ++ fablist->size = 0; ++ } ++ buf = fablist->buffer; ++ mutex_unlock(&msm_bus_dbg_fablist_lock); ++ ts = ktime_to_timespec(ktime_get()); ++ i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n%d.%d\n", ++ (int)ts.tv_sec, (int)ts.tv_nsec); ++ ++ msm_bus_rpm_fill_cdata_buffer(&i, buf, MAX_BUFF_SIZE, cdata, ++ nmasters, nslaves, ntslaves); ++ i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n"); ++ mutex_lock(&msm_bus_dbg_fablist_lock); ++ fablist->size = i; ++ mutex_unlock(&msm_bus_dbg_fablist_lock); ++ return 0; ++} ++#endif ++ ++static const struct file_operations msm_bus_dbg_update_request_fops = { ++ .open = client_data_open, ++ .write = msm_bus_dbg_update_request_write, ++}; ++ ++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_MSM_BUS_SCALING) ++/** ++ * msm_bus_dbg_client_data() - Add debug data for clients ++ * @pdata: Platform data of the client ++ * @index: The current index or operation to be performed ++ * @clid: Client handle obtained during registration ++ */ ++void msm_bus_dbg_client_data(struct msm_bus_scale_pdata *pdata, int index, ++ uint32_t clid) ++{ ++ struct dentry *file = NULL; ++ ++ if (index == MSM_BUS_DBG_REGISTER) { ++ msm_bus_dbg_record_client(pdata, index, clid, file); ++ if (!pdata->name) { ++ MSM_BUS_DBG("Cannot create debugfs entry. Null name\n"); ++ return; ++ } ++ } else if (index == MSM_BUS_DBG_UNREGISTER) { ++ msm_bus_dbg_free_client(clid); ++ MSM_BUS_DBG("Client %d unregistered\n", clid); ++ } else ++ msm_bus_dbg_fill_cl_buffer(pdata, index, clid); ++} ++EXPORT_SYMBOL(msm_bus_dbg_client_data); ++ ++/** ++ * msm_bus_dbg_commit_data() - Add commit data from fabrics ++ * @fabname: Fabric name specified in platform data ++ * @cdata: Commit Data ++ * @nmasters: Number of masters attached to fabric ++ * @nslaves: Number of slaves attached to fabric ++ * @ntslaves: Number of tiered slaves attached to fabric ++ * @op: Operation to be performed ++ */ ++void msm_bus_dbg_commit_data(const char *fabname, void *cdata, ++ int nmasters, int nslaves, int ntslaves, int op) ++{ ++ struct dentry *file = NULL; ++ ++ if (op == MSM_BUS_DBG_REGISTER) ++ msm_bus_dbg_record_fabric(fabname, file); ++ else if (op == MSM_BUS_DBG_UNREGISTER) ++ msm_bus_dbg_free_fabric(fabname); ++ else ++ msm_bus_dbg_fill_fab_buffer(fabname, cdata, nmasters, ++ nslaves, ntslaves); ++} ++EXPORT_SYMBOL(msm_bus_dbg_commit_data); ++#endif ++ ++static int __init msm_bus_debugfs_init(void) ++{ ++ struct dentry *commit, *shell_client, *rules_dbg; ++ struct msm_bus_fab_list *fablist; ++ struct msm_bus_cldata *cldata = NULL; ++ uint64_t val = 0; ++ ++ dir = debugfs_create_dir("msm-bus-dbg", NULL); ++ if ((!dir) || IS_ERR(dir)) { ++ MSM_BUS_ERR("Couldn't create msm-bus-dbg\n"); ++ goto err; ++ } ++ ++ clients = debugfs_create_dir("client-data", dir); ++ if ((!dir) || IS_ERR(dir)) { ++ MSM_BUS_ERR("Couldn't create clients\n"); ++ goto err; ++ } ++ ++ shell_client = debugfs_create_dir("shell-client", dir); ++ if ((!dir) || IS_ERR(dir)) { ++ MSM_BUS_ERR("Couldn't create clients\n"); ++ goto err; ++ } ++ ++ commit = debugfs_create_dir("commit-data", dir); ++ if ((!dir) || IS_ERR(dir)) { ++ MSM_BUS_ERR("Couldn't create commit\n"); ++ goto err; ++ } ++ ++ rules_dbg = debugfs_create_dir("rules-dbg", dir); ++ if ((!rules_dbg) || IS_ERR(rules_dbg)) { ++ MSM_BUS_ERR("Couldn't create rules-dbg\n"); ++ goto err; ++ } ++ ++ if (debugfs_create_file("print_rules", S_IRUGO | S_IWUSR, ++ rules_dbg, &val, &rules_dbg_fops) == NULL) ++ goto err; ++ ++ if (debugfs_create_file("update_request", S_IRUGO | S_IWUSR, ++ shell_client, &val, &shell_client_en_fops) == NULL) ++ goto err; ++ if (debugfs_create_file("ib", S_IRUGO | S_IWUSR, shell_client, &val, ++ &shell_client_ib_fops) == NULL) ++ goto err; ++ if (debugfs_create_file("ab", S_IRUGO | S_IWUSR, shell_client, &val, ++ &shell_client_ab_fops) == NULL) ++ goto err; ++ if (debugfs_create_file("slv", S_IRUGO | S_IWUSR, shell_client, ++ &val, &shell_client_slv_fops) == NULL) ++ goto err; ++ if (debugfs_create_file("mas", S_IRUGO | S_IWUSR, shell_client, ++ &val, &shell_client_mas_fops) == NULL) ++ goto err; ++ if (debugfs_create_file("update-request", S_IRUGO | S_IWUSR, ++ clients, NULL, &msm_bus_dbg_update_request_fops) == NULL) ++ goto err; ++ ++ rules_buf = kzalloc(MAX_BUFF_SIZE, GFP_KERNEL); ++ if (!rules_buf) { ++ MSM_BUS_ERR("Failed to alloc rules_buf"); ++ goto err; ++ } ++ ++ list_for_each_entry(cldata, &cl_list, list) { ++ if (cldata->pdata->name == NULL) { ++ MSM_BUS_DBG("Client name not found\n"); ++ continue; ++ } ++ cldata->file = msm_bus_dbg_create(cldata-> ++ pdata->name, S_IRUGO, clients, cldata->clid); ++ } ++ ++ mutex_lock(&msm_bus_dbg_fablist_lock); ++ list_for_each_entry(fablist, &fabdata_list, list) { ++ fablist->file = debugfs_create_file(fablist->name, S_IRUGO, ++ commit, (void *)fablist->name, &fabric_data_fops); ++ if (fablist->file == NULL) { ++ MSM_BUS_DBG("Cannot create files for commit data\n"); ++ kfree(rules_buf); ++ goto err; ++ } ++ } ++ mutex_unlock(&msm_bus_dbg_fablist_lock); ++ ++ msm_bus_dbg_init_vectors(); ++ return 0; ++err: ++ debugfs_remove_recursive(dir); ++ return -ENODEV; ++} ++late_initcall(msm_bus_debugfs_init); ++ ++static void __exit msm_bus_dbg_teardown(void) ++{ ++ struct msm_bus_fab_list *fablist = NULL, *fablist_temp; ++ struct msm_bus_cldata *cldata = NULL, *cldata_temp; ++ ++ debugfs_remove_recursive(dir); ++ list_for_each_entry_safe(cldata, cldata_temp, &cl_list, list) { ++ list_del(&cldata->list); ++ kfree(cldata); ++ } ++ mutex_lock(&msm_bus_dbg_fablist_lock); ++ list_for_each_entry_safe(fablist, fablist_temp, &fabdata_list, list) { ++ list_del(&fablist->list); ++ kfree(fablist); ++ } ++ kfree(rules_buf); ++ mutex_unlock(&msm_bus_dbg_fablist_lock); ++} ++module_exit(msm_bus_dbg_teardown); ++MODULE_DESCRIPTION("Debugfs for msm bus scaling client"); ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Gagan Mac "); +--- /dev/null ++++ b/drivers/bus/msm_bus/msm_bus_fabric_adhoc.c +@@ -0,0 +1,1281 @@ ++/* Copyright (c) 2014, Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rpm-smd.h" ++#include "msm_bus_core.h" ++#include "msm_bus_adhoc.h" ++#include "msm_bus_noc.h" ++#include "msm_bus_bimc.h" ++ ++ssize_t vrail_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct msm_bus_node_info_type *node_info = NULL; ++ struct msm_bus_node_device_type *bus_node = NULL; ++ ++ bus_node = dev->platform_data; ++ if (!bus_node) ++ return -EINVAL; ++ node_info = bus_node->node_info; ++ ++ return snprintf(buf, PAGE_SIZE, "%u", node_info->vrail_comp); ++} ++ ++ssize_t vrail_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct msm_bus_node_info_type *node_info = NULL; ++ struct msm_bus_node_device_type *bus_node = NULL; ++ int ret = 0; ++ ++ bus_node = dev->platform_data; ++ if (!bus_node) ++ return -EINVAL; ++ node_info = bus_node->node_info; ++ ++ ret = sscanf(buf, "%u", &node_info->vrail_comp); ++ if (ret != 1) ++ return -EINVAL; ++ return count; ++} ++ ++DEVICE_ATTR(vrail, 0600, vrail_show, vrail_store); ++ ++struct static_rules_type { ++ int num_rules; ++ struct bus_rule_type *rules; ++}; ++ ++static struct static_rules_type static_rules; ++ ++static int enable_nodeclk(struct nodeclk *nclk) ++{ ++ int ret = 0; ++ ++ if (!nclk->enable) { ++ ret = clk_prepare_enable(nclk->clk); ++ ++ if (ret) { ++ MSM_BUS_ERR("%s: failed to enable clk ", __func__); ++ nclk->enable = false; ++ } else ++ nclk->enable = true; ++ } ++ return ret; ++} ++ ++static int disable_nodeclk(struct nodeclk *nclk) ++{ ++ int ret = 0; ++ ++ if (nclk->enable) { ++ clk_disable_unprepare(nclk->clk); ++ nclk->enable = false; ++ } ++ return ret; ++} ++ ++static int setrate_nodeclk(struct nodeclk *nclk, long rate) ++{ ++ int ret = 0; ++ ++ ret = clk_set_rate(nclk->clk, rate); ++ ++ if (ret) ++ MSM_BUS_ERR("%s: failed to setrate clk", __func__); ++ return ret; ++} ++ ++static int msm_bus_agg_fab_clks(struct device *bus_dev, void *data) ++{ ++ struct msm_bus_node_device_type *node = NULL; ++ int ret = 0; ++ int ctx = *(int *)data; ++ ++ if (ctx >= NUM_CTX) { ++ MSM_BUS_ERR("%s: Invalid Context %d", __func__, ctx); ++ goto exit_agg_fab_clks; ++ } ++ ++ node = bus_dev->platform_data; ++ if (!node) { ++ MSM_BUS_ERR("%s: Can't get device info", __func__); ++ goto exit_agg_fab_clks; ++ } ++ ++ if (!node->node_info->is_fab_dev) { ++ struct msm_bus_node_device_type *bus_dev = NULL; ++ ++ bus_dev = node->node_info->bus_device->platform_data; ++ ++ if (node->cur_clk_hz[ctx] >= bus_dev->cur_clk_hz[ctx]) ++ bus_dev->cur_clk_hz[ctx] = node->cur_clk_hz[ctx]; ++ } ++ ++exit_agg_fab_clks: ++ return ret; ++} ++ ++static int msm_bus_reset_fab_clks(struct device *bus_dev, void *data) ++{ ++ struct msm_bus_node_device_type *node = NULL; ++ int ret = 0; ++ int ctx = *(int *)data; ++ ++ if (ctx >= NUM_CTX) { ++ MSM_BUS_ERR("%s: Invalid Context %d", __func__, ctx); ++ goto exit_reset_fab_clks; ++ } ++ ++ node = bus_dev->platform_data; ++ if (!node) { ++ MSM_BUS_ERR("%s: Can't get device info", __func__); ++ goto exit_reset_fab_clks; ++ } ++ ++ if (node->node_info->is_fab_dev) { ++ node->cur_clk_hz[ctx] = 0; ++ MSM_BUS_DBG("Resetting for node %d", node->node_info->id); ++ } ++exit_reset_fab_clks: ++ return ret; ++} ++ ++ ++static int send_rpm_msg(struct device *device) ++{ ++ int ret = 0; ++ int ctx; ++ int rsc_type; ++ struct msm_bus_node_device_type *ndev = ++ device->platform_data; ++ struct msm_rpm_kvp rpm_kvp; ++ ++ if (!ndev) { ++ MSM_BUS_ERR("%s: Error getting node info.", __func__); ++ ret = -ENODEV; ++ goto exit_send_rpm_msg; ++ } ++ ++ rpm_kvp.length = sizeof(uint64_t); ++ rpm_kvp.key = RPM_MASTER_FIELD_BW; ++ ++ for (ctx = MSM_RPM_CTX_ACTIVE_SET; ctx <= MSM_RPM_CTX_SLEEP_SET; ++ ctx++) { ++ if (ctx == MSM_RPM_CTX_ACTIVE_SET) ++ rpm_kvp.data = ++ (uint8_t *)&ndev->node_ab.ab[MSM_RPM_CTX_ACTIVE_SET]; ++ else { ++ rpm_kvp.data = ++ (uint8_t *) &ndev->node_ab.ab[MSM_RPM_CTX_SLEEP_SET]; ++ } ++ ++ if (ndev->node_info->mas_rpm_id != -1) { ++ rsc_type = RPM_BUS_MASTER_REQ; ++ ret = msm_rpm_send_message(ctx, rsc_type, ++ ndev->node_info->mas_rpm_id, &rpm_kvp, 1); ++ if (ret) { ++ MSM_BUS_ERR("%s: Failed to send RPM message:", ++ __func__); ++ MSM_BUS_ERR("%s:Node Id %d RPM id %d", ++ __func__, ndev->node_info->id, ++ ndev->node_info->mas_rpm_id); ++ goto exit_send_rpm_msg; ++ } ++ } ++ ++ if (ndev->node_info->slv_rpm_id != -1) { ++ rsc_type = RPM_BUS_SLAVE_REQ; ++ ret = msm_rpm_send_message(ctx, rsc_type, ++ ndev->node_info->slv_rpm_id, &rpm_kvp, 1); ++ if (ret) { ++ MSM_BUS_ERR("%s: Failed to send RPM message:", ++ __func__); ++ MSM_BUS_ERR("%s: Node Id %d RPM id %d", ++ __func__, ndev->node_info->id, ++ ndev->node_info->slv_rpm_id); ++ goto exit_send_rpm_msg; ++ } ++ } ++ } ++exit_send_rpm_msg: ++ return ret; ++} ++ ++static int flush_bw_data(struct device *node_device, int ctx) ++{ ++ struct msm_bus_node_device_type *node_info; ++ int ret = 0; ++ ++ node_info = node_device->platform_data; ++ if (!node_info) { ++ MSM_BUS_ERR("%s: Unable to find bus device for device", ++ __func__); ++ ret = -ENODEV; ++ goto exit_flush_bw_data; ++ } ++ ++ if (node_info->node_ab.dirty) { ++ if (node_info->ap_owned) { ++ struct msm_bus_node_device_type *bus_device = ++ node_info->node_info->bus_device->platform_data; ++ struct msm_bus_fab_device_type *fabdev = ++ bus_device->fabdev; ++ ++ if (fabdev && fabdev->noc_ops.update_bw_reg && ++ fabdev->noc_ops.update_bw_reg ++ (node_info->node_info->qos_params.mode)) ++ ret = fabdev->noc_ops.set_bw(node_info, ++ fabdev->qos_base, ++ fabdev->base_offset, ++ fabdev->qos_off, ++ fabdev->qos_freq); ++ } else { ++ ret = send_rpm_msg(node_device); ++ ++ if (ret) ++ MSM_BUS_ERR("%s: Failed to send RPM msg for%d", ++ __func__, node_info->node_info->id); ++ } ++ node_info->node_ab.dirty = false; ++ } ++ ++exit_flush_bw_data: ++ return ret; ++ ++} ++ ++static int flush_clk_data(struct device *node_device, int ctx) ++{ ++ struct msm_bus_node_device_type *node; ++ struct nodeclk *nodeclk = NULL; ++ int ret = 0; ++ ++ node = node_device->platform_data; ++ if (!node) { ++ MSM_BUS_ERR("Unable to find bus device"); ++ ret = -ENODEV; ++ goto exit_flush_clk_data; ++ } ++ ++ nodeclk = &node->clk[ctx]; ++ if (node->node_info->is_fab_dev) { ++ if (nodeclk->rate != node->cur_clk_hz[ctx]) { ++ nodeclk->rate = node->cur_clk_hz[ctx]; ++ nodeclk->dirty = true; ++ } ++ } ++ ++ if (nodeclk && nodeclk->clk && nodeclk->dirty) { ++ long rounded_rate; ++ ++ if (nodeclk->rate) { ++ rounded_rate = clk_round_rate(nodeclk->clk, ++ nodeclk->rate); ++ ret = setrate_nodeclk(nodeclk, rounded_rate); ++ ++ if (ret) { ++ MSM_BUS_ERR("%s: Failed to set_rate %lu for %d", ++ __func__, rounded_rate, ++ node->node_info->id); ++ ret = -ENODEV; ++ goto exit_flush_clk_data; ++ } ++ ++ ret = enable_nodeclk(nodeclk); ++ } else ++ ret = disable_nodeclk(nodeclk); ++ ++ if (ret) { ++ MSM_BUS_ERR("%s: Failed to enable for %d", __func__, ++ node->node_info->id); ++ ret = -ENODEV; ++ goto exit_flush_clk_data; ++ } ++ MSM_BUS_DBG("%s: Updated %d clk to %llu", __func__, ++ node->node_info->id, nodeclk->rate); ++ ++ } ++exit_flush_clk_data: ++ /* Reset the aggregated clock rate for fab devices*/ ++ if (node && node->node_info->is_fab_dev) ++ node->cur_clk_hz[ctx] = 0; ++ ++ if (nodeclk) ++ nodeclk->dirty = 0; ++ return ret; ++} ++ ++int msm_bus_commit_data(int *dirty_nodes, int ctx, int num_dirty) ++{ ++ int ret = 0; ++ int i = 0; ++ ++ /* Aggregate the bus clocks */ ++ bus_for_each_dev(&msm_bus_type, NULL, (void *)&ctx, ++ msm_bus_agg_fab_clks); ++ ++ for (i = 0; i < num_dirty; i++) { ++ struct device *node_device = ++ bus_find_device(&msm_bus_type, NULL, ++ (void *)&dirty_nodes[i], ++ msm_bus_device_match_adhoc); ++ ++ if (!node_device) { ++ MSM_BUS_ERR("Can't find device for %d", dirty_nodes[i]); ++ continue; ++ } ++ ++ ret = flush_bw_data(node_device, ctx); ++ if (ret) ++ MSM_BUS_ERR("%s: Error flushing bw data for node %d", ++ __func__, dirty_nodes[i]); ++ ++ ret = flush_clk_data(node_device, ctx); ++ if (ret) ++ MSM_BUS_ERR("%s: Error flushing clk data for node %d", ++ __func__, dirty_nodes[i]); ++ } ++ kfree(dirty_nodes); ++ /* Aggregate the bus clocks */ ++ bus_for_each_dev(&msm_bus_type, NULL, (void *)&ctx, ++ msm_bus_reset_fab_clks); ++ return ret; ++} ++ ++void *msm_bus_realloc_devmem(struct device *dev, void *p, size_t old_size, ++ size_t new_size, gfp_t flags) ++{ ++ void *ret; ++ size_t copy_size = old_size; ++ ++ if (!new_size) { ++ devm_kfree(dev, p); ++ return ZERO_SIZE_PTR; ++ } ++ ++ if (new_size < old_size) ++ copy_size = new_size; ++ ++ ret = devm_kzalloc(dev, new_size, flags); ++ if (!ret) { ++ MSM_BUS_ERR("%s: Error Reallocating memory", __func__); ++ goto exit_realloc_devmem; ++ } ++ ++ memcpy(ret, p, copy_size); ++ devm_kfree(dev, p); ++exit_realloc_devmem: ++ return ret; ++} ++ ++ ++static int add_dirty_node(int **dirty_nodes, int id, int *num_dirty) ++{ ++ int i; ++ int found = 0; ++ int ret = 0; ++ int *dnode = NULL; ++ ++ for (i = 0; i < *num_dirty; i++) { ++ if ((*dirty_nodes)[i] == id) { ++ found = 1; ++ break; ++ } ++ } ++ ++ if (!found) { ++ (*num_dirty)++; ++ dnode = ++ krealloc(*dirty_nodes, sizeof(int) * (*num_dirty), ++ GFP_KERNEL); ++ ++ if (ZERO_OR_NULL_PTR(dnode)) { ++ MSM_BUS_ERR("%s: Failure allocating dirty nodes array", ++ __func__); ++ ret = -ENOMEM; ++ } else { ++ *dirty_nodes = dnode; ++ (*dirty_nodes)[(*num_dirty) - 1] = id; ++ } ++ } ++ ++ return ret; ++} ++ ++int msm_bus_update_bw(struct msm_bus_node_device_type *nodedev, int ctx, ++ int64_t add_bw, int **dirty_nodes, int *num_dirty) ++{ ++ int ret = 0; ++ int i, j; ++ uint64_t cur_ab_slp = 0; ++ uint64_t cur_ab_act = 0; ++ ++ if (nodedev->node_info->virt_dev) ++ goto exit_update_bw; ++ ++ for (i = 0; i < NUM_CTX; i++) { ++ for (j = 0; j < nodedev->num_lnodes; j++) { ++ if (i == DUAL_CTX) { ++ cur_ab_act += ++ nodedev->lnode_list[j].lnode_ab[i]; ++ cur_ab_slp += ++ nodedev->lnode_list[j].lnode_ab[i]; ++ } else ++ cur_ab_act += ++ nodedev->lnode_list[j].lnode_ab[i]; ++ } ++ } ++ ++ if (nodedev->node_ab.ab[MSM_RPM_CTX_ACTIVE_SET] != cur_ab_act) { ++ nodedev->node_ab.ab[MSM_RPM_CTX_ACTIVE_SET] = cur_ab_act; ++ nodedev->node_ab.ab[MSM_RPM_CTX_SLEEP_SET] = cur_ab_slp; ++ nodedev->node_ab.dirty = true; ++ ret = add_dirty_node(dirty_nodes, nodedev->node_info->id, ++ num_dirty); ++ ++ if (ret) { ++ MSM_BUS_ERR("%s: Failed to add dirty node %d", __func__, ++ nodedev->node_info->id); ++ goto exit_update_bw; ++ } ++ } ++ ++exit_update_bw: ++ return ret; ++} ++ ++int msm_bus_update_clks(struct msm_bus_node_device_type *nodedev, ++ int ctx, int **dirty_nodes, int *num_dirty) ++{ ++ int status = 0; ++ struct nodeclk *nodeclk; ++ struct nodeclk *busclk; ++ struct msm_bus_node_device_type *bus_info = NULL; ++ uint64_t req_clk; ++ ++ bus_info = nodedev->node_info->bus_device->platform_data; ++ ++ if (!bus_info) { ++ MSM_BUS_ERR("%s: Unable to find bus device for device %d", ++ __func__, nodedev->node_info->id); ++ status = -ENODEV; ++ goto exit_set_clks; ++ } ++ ++ req_clk = nodedev->cur_clk_hz[ctx]; ++ busclk = &bus_info->clk[ctx]; ++ ++ if (busclk->rate != req_clk) { ++ busclk->rate = req_clk; ++ busclk->dirty = 1; ++ MSM_BUS_DBG("%s: Modifying bus clk %d Rate %llu", __func__, ++ bus_info->node_info->id, req_clk); ++ status = add_dirty_node(dirty_nodes, bus_info->node_info->id, ++ num_dirty); ++ ++ if (status) { ++ MSM_BUS_ERR("%s: Failed to add dirty node %d", __func__, ++ bus_info->node_info->id); ++ goto exit_set_clks; ++ } ++ } ++ ++ req_clk = nodedev->cur_clk_hz[ctx]; ++ nodeclk = &nodedev->clk[ctx]; ++ ++ if (IS_ERR_OR_NULL(nodeclk)) ++ goto exit_set_clks; ++ ++ if (!nodeclk->dirty || (nodeclk->dirty && (nodeclk->rate < req_clk))) { ++ nodeclk->rate = req_clk; ++ nodeclk->dirty = 1; ++ MSM_BUS_DBG("%s: Modifying node clk %d Rate %llu", __func__, ++ nodedev->node_info->id, req_clk); ++ status = add_dirty_node(dirty_nodes, nodedev->node_info->id, ++ num_dirty); ++ if (status) { ++ MSM_BUS_ERR("%s: Failed to add dirty node %d", __func__, ++ nodedev->node_info->id); ++ goto exit_set_clks; ++ } ++ } ++ ++exit_set_clks: ++ return status; ++} ++ ++static void msm_bus_fab_init_noc_ops(struct msm_bus_node_device_type *bus_dev) ++{ ++ switch (bus_dev->fabdev->bus_type) { ++ case MSM_BUS_NOC: ++ msm_bus_noc_set_ops(bus_dev); ++ break; ++ case MSM_BUS_BIMC: ++ msm_bus_bimc_set_ops(bus_dev); ++ break; ++ default: ++ MSM_BUS_ERR("%s: Invalid Bus type", __func__); ++ } ++} ++ ++static int msm_bus_qos_disable_clk(struct msm_bus_node_device_type *node, ++ int disable_bus_qos_clk) ++{ ++ struct msm_bus_node_device_type *bus_node = NULL; ++ int ret = 0; ++ ++ if (!node) { ++ ret = -ENXIO; ++ goto exit_disable_qos_clk; ++ } ++ ++ bus_node = node->node_info->bus_device->platform_data; ++ ++ if (!bus_node) { ++ ret = -ENXIO; ++ goto exit_disable_qos_clk; ++ } ++ ++ if (disable_bus_qos_clk) ++ ret = disable_nodeclk(&bus_node->clk[DUAL_CTX]); ++ ++ if (ret) { ++ MSM_BUS_ERR("%s: Failed to disable bus clk, node %d", ++ __func__, node->node_info->id); ++ goto exit_disable_qos_clk; ++ } ++ ++ if (!IS_ERR_OR_NULL(node->qos_clk.clk)) { ++ ret = disable_nodeclk(&node->qos_clk); ++ ++ if (ret) { ++ MSM_BUS_ERR("%s: Failed to disable mas qos clk,node %d", ++ __func__, node->node_info->id); ++ goto exit_disable_qos_clk; ++ } ++ } ++ ++exit_disable_qos_clk: ++ return ret; ++} ++ ++static int msm_bus_qos_enable_clk(struct msm_bus_node_device_type *node) ++{ ++ struct msm_bus_node_device_type *bus_node = NULL; ++ long rounded_rate; ++ int ret = 0; ++ int bus_qos_enabled = 0; ++ ++ if (!node) { ++ ret = -ENXIO; ++ goto exit_enable_qos_clk; ++ } ++ ++ bus_node = node->node_info->bus_device->platform_data; ++ ++ if (!bus_node) { ++ ret = -ENXIO; ++ goto exit_enable_qos_clk; ++ } ++ ++ /* Check if the bus clk is already set before trying to set it ++ * Do this only during ++ * a. Bootup ++ * b. Only for bus clks ++ **/ ++ if (!clk_get_rate(bus_node->clk[DUAL_CTX].clk)) { ++ rounded_rate = clk_round_rate(bus_node->clk[DUAL_CTX].clk, 1); ++ ret = setrate_nodeclk(&bus_node->clk[DUAL_CTX], rounded_rate); ++ if (ret) { ++ MSM_BUS_ERR("%s: Failed to set bus clk, node %d", ++ __func__, node->node_info->id); ++ goto exit_enable_qos_clk; ++ } ++ ++ ret = enable_nodeclk(&bus_node->clk[DUAL_CTX]); ++ if (ret) { ++ MSM_BUS_ERR("%s: Failed to enable bus clk, node %d", ++ __func__, node->node_info->id); ++ goto exit_enable_qos_clk; ++ } ++ bus_qos_enabled = 1; ++ } ++ ++ if (!IS_ERR_OR_NULL(node->qos_clk.clk)) { ++ rounded_rate = clk_round_rate(node->qos_clk.clk, 1); ++ ret = setrate_nodeclk(&node->qos_clk, rounded_rate); ++ if (ret) { ++ MSM_BUS_ERR("%s: Failed to enable mas qos clk, node %d", ++ __func__, node->node_info->id); ++ goto exit_enable_qos_clk; ++ } ++ ++ ret = enable_nodeclk(&node->qos_clk); ++ if (ret) { ++ MSM_BUS_ERR("Err enable mas qos clk, node %d ret %d", ++ node->node_info->id, ret); ++ goto exit_enable_qos_clk; ++ } ++ } ++ ret = bus_qos_enabled; ++ ++exit_enable_qos_clk: ++ return ret; ++} ++ ++int msm_bus_enable_limiter(struct msm_bus_node_device_type *node_dev, ++ bool enable, uint64_t lim_bw) ++{ ++ int ret = 0; ++ struct msm_bus_node_device_type *bus_node_dev; ++ ++ if (!node_dev) { ++ MSM_BUS_ERR("No device specified"); ++ ret = -ENXIO; ++ goto exit_enable_limiter; ++ } ++ ++ if (!node_dev->ap_owned) { ++ MSM_BUS_ERR("Device is not AP owned %d.", ++ node_dev->node_info->id); ++ ret = -ENXIO; ++ goto exit_enable_limiter; ++ } ++ ++ bus_node_dev = node_dev->node_info->bus_device->platform_data; ++ if (!bus_node_dev) { ++ MSM_BUS_ERR("Unable to get bus device infofor %d", ++ node_dev->node_info->id); ++ ret = -ENXIO; ++ goto exit_enable_limiter; ++ } ++ if (bus_node_dev->fabdev && ++ bus_node_dev->fabdev->noc_ops.limit_mport) { ++ ret = msm_bus_qos_enable_clk(node_dev); ++ if (ret < 0) { ++ MSM_BUS_ERR("Can't Enable QoS clk %d", ++ node_dev->node_info->id); ++ goto exit_enable_limiter; ++ } ++ bus_node_dev->fabdev->noc_ops.limit_mport( ++ node_dev, ++ bus_node_dev->fabdev->qos_base, ++ bus_node_dev->fabdev->base_offset, ++ bus_node_dev->fabdev->qos_off, ++ bus_node_dev->fabdev->qos_freq, ++ enable, lim_bw); ++ msm_bus_qos_disable_clk(node_dev, ret); ++ } ++ ++exit_enable_limiter: ++ return ret; ++} ++ ++static int msm_bus_dev_init_qos(struct device *dev, void *data) ++{ ++ int ret = 0; ++ struct msm_bus_node_device_type *node_dev = NULL; ++ ++ node_dev = dev->platform_data; ++ ++ if (!node_dev) { ++ MSM_BUS_ERR("%s: Unable to get node device info" , __func__); ++ ret = -ENXIO; ++ goto exit_init_qos; ++ } ++ ++ MSM_BUS_DBG("Device = %d", node_dev->node_info->id); ++ ++ if (node_dev->ap_owned) { ++ struct msm_bus_node_device_type *bus_node_info; ++ ++ bus_node_info = node_dev->node_info->bus_device->platform_data; ++ ++ if (!bus_node_info) { ++ MSM_BUS_ERR("%s: Unable to get bus device infofor %d", ++ __func__, ++ node_dev->node_info->id); ++ ret = -ENXIO; ++ goto exit_init_qos; ++ } ++ ++ if (bus_node_info->fabdev && ++ bus_node_info->fabdev->noc_ops.qos_init) { ++ int ret = 0; ++ ++ if (node_dev->ap_owned && ++ (node_dev->node_info->qos_params.mode) != -1) { ++ ++ if (bus_node_info->fabdev->bypass_qos_prg) ++ goto exit_init_qos; ++ ++ ret = msm_bus_qos_enable_clk(node_dev); ++ if (ret < 0) { ++ MSM_BUS_ERR("Can't Enable QoS clk %d", ++ node_dev->node_info->id); ++ goto exit_init_qos; ++ } ++ ++ bus_node_info->fabdev->noc_ops.qos_init( ++ node_dev, ++ bus_node_info->fabdev->qos_base, ++ bus_node_info->fabdev->base_offset, ++ bus_node_info->fabdev->qos_off, ++ bus_node_info->fabdev->qos_freq); ++ msm_bus_qos_disable_clk(node_dev, ret); ++ } ++ } else ++ MSM_BUS_ERR("%s: Skipping QOS init for %d", ++ __func__, node_dev->node_info->id); ++ } ++exit_init_qos: ++ return ret; ++} ++ ++static int msm_bus_fabric_init(struct device *dev, ++ struct msm_bus_node_device_type *pdata) ++{ ++ struct msm_bus_fab_device_type *fabdev; ++ struct msm_bus_node_device_type *node_dev = NULL; ++ int ret = 0; ++ ++ node_dev = dev->platform_data; ++ if (!node_dev) { ++ MSM_BUS_ERR("%s: Unable to get bus device info" , __func__); ++ ret = -ENXIO; ++ goto exit_fabric_init; ++ } ++ ++ if (node_dev->node_info->virt_dev) { ++ MSM_BUS_ERR("%s: Skip Fab init for virtual device %d", __func__, ++ node_dev->node_info->id); ++ goto exit_fabric_init; ++ } ++ ++ fabdev = devm_kzalloc(dev, sizeof(struct msm_bus_fab_device_type), ++ GFP_KERNEL); ++ if (!fabdev) { ++ MSM_BUS_ERR("Fabric alloc failed\n"); ++ ret = -ENOMEM; ++ goto exit_fabric_init; ++ } ++ ++ node_dev->fabdev = fabdev; ++ fabdev->pqos_base = pdata->fabdev->pqos_base; ++ fabdev->qos_range = pdata->fabdev->qos_range; ++ fabdev->base_offset = pdata->fabdev->base_offset; ++ fabdev->qos_off = pdata->fabdev->qos_off; ++ fabdev->qos_freq = pdata->fabdev->qos_freq; ++ fabdev->bus_type = pdata->fabdev->bus_type; ++ fabdev->bypass_qos_prg = pdata->fabdev->bypass_qos_prg; ++ fabdev->util_fact = pdata->fabdev->util_fact; ++ fabdev->vrail_comp = pdata->fabdev->vrail_comp; ++ msm_bus_fab_init_noc_ops(node_dev); ++ ++ fabdev->qos_base = devm_ioremap(dev, ++ fabdev->pqos_base, fabdev->qos_range); ++ if (!fabdev->qos_base) { ++ MSM_BUS_ERR("%s: Error remapping address 0x%zx :bus device %d", ++ __func__, ++ (size_t)fabdev->pqos_base, node_dev->node_info->id); ++ ret = -ENOMEM; ++ goto exit_fabric_init; ++ } ++ ++ /*if (msmbus_coresight_init(pdev)) ++ pr_warn("Coresight support absent for bus: %d\n", pdata->id);*/ ++exit_fabric_init: ++ return ret; ++} ++ ++static int msm_bus_init_clk(struct device *bus_dev, ++ struct msm_bus_node_device_type *pdata) ++{ ++ unsigned int ctx; ++ int ret = 0; ++ struct msm_bus_node_device_type *node_dev = bus_dev->platform_data; ++ ++ for (ctx = 0; ctx < NUM_CTX; ctx++) { ++ if (!IS_ERR_OR_NULL(pdata->clk[ctx].clk)) { ++ node_dev->clk[ctx].clk = pdata->clk[ctx].clk; ++ node_dev->clk[ctx].enable = false; ++ node_dev->clk[ctx].dirty = false; ++ MSM_BUS_ERR("%s: Valid node clk node %d ctx %d", ++ __func__, node_dev->node_info->id, ctx); ++ } ++ } ++ ++ if (!IS_ERR_OR_NULL(pdata->qos_clk.clk)) { ++ node_dev->qos_clk.clk = pdata->qos_clk.clk; ++ node_dev->qos_clk.enable = false; ++ MSM_BUS_ERR("%s: Valid Iface clk node %d", __func__, ++ node_dev->node_info->id); ++ } ++ ++ return ret; ++} ++ ++static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, ++ struct device *bus_dev) ++{ ++ int ret = 0; ++ struct msm_bus_node_info_type *node_info = NULL; ++ struct msm_bus_node_info_type *pdata_node_info = NULL; ++ struct msm_bus_node_device_type *bus_node = NULL; ++ ++ bus_node = bus_dev->platform_data; ++ ++ if (!bus_node || !pdata) { ++ ret = -ENXIO; ++ MSM_BUS_ERR("%s: Invalid pointers pdata %p, bus_node %p", ++ __func__, pdata, bus_node); ++ goto exit_copy_node_info; ++ } ++ ++ node_info = bus_node->node_info; ++ pdata_node_info = pdata->node_info; ++ ++ node_info->name = pdata_node_info->name; ++ node_info->id = pdata_node_info->id; ++ node_info->bus_device_id = pdata_node_info->bus_device_id; ++ node_info->mas_rpm_id = pdata_node_info->mas_rpm_id; ++ node_info->slv_rpm_id = pdata_node_info->slv_rpm_id; ++ node_info->num_connections = pdata_node_info->num_connections; ++ node_info->num_blist = pdata_node_info->num_blist; ++ node_info->num_qports = pdata_node_info->num_qports; ++ node_info->buswidth = pdata_node_info->buswidth; ++ node_info->virt_dev = pdata_node_info->virt_dev; ++ node_info->is_fab_dev = pdata_node_info->is_fab_dev; ++ node_info->qos_params.mode = pdata_node_info->qos_params.mode; ++ node_info->qos_params.prio1 = pdata_node_info->qos_params.prio1; ++ node_info->qos_params.prio0 = pdata_node_info->qos_params.prio0; ++ node_info->qos_params.prio_lvl = pdata_node_info->qos_params.prio_lvl; ++ node_info->qos_params.prio_rd = pdata_node_info->qos_params.prio_rd; ++ node_info->qos_params.prio_wr = pdata_node_info->qos_params.prio_wr; ++ node_info->qos_params.gp = pdata_node_info->qos_params.gp; ++ node_info->qos_params.thmp = pdata_node_info->qos_params.thmp; ++ node_info->qos_params.ws = pdata_node_info->qos_params.ws; ++ node_info->qos_params.bw_buffer = pdata_node_info->qos_params.bw_buffer; ++ node_info->util_fact = pdata_node_info->util_fact; ++ node_info->vrail_comp = pdata_node_info->vrail_comp; ++ ++ node_info->dev_connections = devm_kzalloc(bus_dev, ++ sizeof(struct device *) * ++ pdata_node_info->num_connections, ++ GFP_KERNEL); ++ if (!node_info->dev_connections) { ++ MSM_BUS_ERR("%s:Bus dev connections alloc failed\n", __func__); ++ ret = -ENOMEM; ++ goto exit_copy_node_info; ++ } ++ ++ node_info->connections = devm_kzalloc(bus_dev, ++ sizeof(int) * pdata_node_info->num_connections, ++ GFP_KERNEL); ++ if (!node_info->connections) { ++ MSM_BUS_ERR("%s:Bus connections alloc failed\n", __func__); ++ devm_kfree(bus_dev, node_info->dev_connections); ++ ret = -ENOMEM; ++ goto exit_copy_node_info; ++ } ++ ++ memcpy(node_info->connections, ++ pdata_node_info->connections, ++ sizeof(int) * pdata_node_info->num_connections); ++ ++ node_info->black_connections = devm_kzalloc(bus_dev, ++ sizeof(struct device *) * ++ pdata_node_info->num_blist, ++ GFP_KERNEL); ++ if (!node_info->black_connections) { ++ MSM_BUS_ERR("%s: Bus black connections alloc failed\n", ++ __func__); ++ devm_kfree(bus_dev, node_info->dev_connections); ++ devm_kfree(bus_dev, node_info->connections); ++ ret = -ENOMEM; ++ goto exit_copy_node_info; ++ } ++ ++ node_info->black_listed_connections = devm_kzalloc(bus_dev, ++ pdata_node_info->num_blist * sizeof(int), ++ GFP_KERNEL); ++ if (!node_info->black_listed_connections) { ++ MSM_BUS_ERR("%s:Bus black list connections alloc failed\n", ++ __func__); ++ devm_kfree(bus_dev, node_info->black_connections); ++ devm_kfree(bus_dev, node_info->dev_connections); ++ devm_kfree(bus_dev, node_info->connections); ++ ret = -ENOMEM; ++ goto exit_copy_node_info; ++ } ++ ++ memcpy(node_info->black_listed_connections, ++ pdata_node_info->black_listed_connections, ++ sizeof(int) * pdata_node_info->num_blist); ++ ++ node_info->qport = devm_kzalloc(bus_dev, ++ sizeof(int) * pdata_node_info->num_qports, ++ GFP_KERNEL); ++ if (!node_info->qport) { ++ MSM_BUS_ERR("%s:Bus qport allocation failed\n", __func__); ++ devm_kfree(bus_dev, node_info->dev_connections); ++ devm_kfree(bus_dev, node_info->connections); ++ devm_kfree(bus_dev, node_info->black_listed_connections); ++ ret = -ENOMEM; ++ goto exit_copy_node_info; ++ } ++ ++ memcpy(node_info->qport, ++ pdata_node_info->qport, ++ sizeof(int) * pdata_node_info->num_qports); ++ ++exit_copy_node_info: ++ return ret; ++} ++ ++static struct device *msm_bus_device_init( ++ struct msm_bus_node_device_type *pdata) ++{ ++ struct device *bus_dev = NULL; ++ struct msm_bus_node_device_type *bus_node = NULL; ++ struct msm_bus_node_info_type *node_info = NULL; ++ int ret = 0; ++ ++ bus_dev = kzalloc(sizeof(struct device), GFP_KERNEL); ++ if (!bus_dev) { ++ MSM_BUS_ERR("%s:Device alloc failed\n", __func__); ++ bus_dev = NULL; ++ goto exit_device_init; ++ } ++ /** ++ * Init here so we can use devm calls ++ */ ++ device_initialize(bus_dev); ++ ++ bus_node = devm_kzalloc(bus_dev, ++ sizeof(struct msm_bus_node_device_type), GFP_KERNEL); ++ if (!bus_node) { ++ MSM_BUS_ERR("%s:Bus node alloc failed\n", __func__); ++ kfree(bus_dev); ++ bus_dev = NULL; ++ goto exit_device_init; ++ } ++ ++ node_info = devm_kzalloc(bus_dev, ++ sizeof(struct msm_bus_node_info_type), GFP_KERNEL); ++ if (!node_info) { ++ MSM_BUS_ERR("%s:Bus node info alloc failed\n", __func__); ++ devm_kfree(bus_dev, bus_node); ++ kfree(bus_dev); ++ bus_dev = NULL; ++ goto exit_device_init; ++ } ++ ++ bus_node->node_info = node_info; ++ bus_node->ap_owned = pdata->ap_owned; ++ bus_dev->platform_data = bus_node; ++ ++ if (msm_bus_copy_node_info(pdata, bus_dev) < 0) { ++ devm_kfree(bus_dev, bus_node); ++ devm_kfree(bus_dev, node_info); ++ kfree(bus_dev); ++ bus_dev = NULL; ++ goto exit_device_init; ++ } ++ ++ bus_dev->bus = &msm_bus_type; ++ dev_set_name(bus_dev, bus_node->node_info->name); ++ ++ ret = device_add(bus_dev); ++ if (ret < 0) { ++ MSM_BUS_ERR("%s: Error registering device %d", ++ __func__, pdata->node_info->id); ++ devm_kfree(bus_dev, bus_node); ++ devm_kfree(bus_dev, node_info->dev_connections); ++ devm_kfree(bus_dev, node_info->connections); ++ devm_kfree(bus_dev, node_info->black_connections); ++ devm_kfree(bus_dev, node_info->black_listed_connections); ++ devm_kfree(bus_dev, node_info); ++ kfree(bus_dev); ++ bus_dev = NULL; ++ goto exit_device_init; ++ } ++ device_create_file(bus_dev, &dev_attr_vrail); ++ ++exit_device_init: ++ return bus_dev; ++} ++ ++static int msm_bus_setup_dev_conn(struct device *bus_dev, void *data) ++{ ++ struct msm_bus_node_device_type *bus_node = NULL; ++ int ret = 0; ++ int j; ++ ++ bus_node = bus_dev->platform_data; ++ if (!bus_node) { ++ MSM_BUS_ERR("%s: Can't get device info", __func__); ++ ret = -ENODEV; ++ goto exit_setup_dev_conn; ++ } ++ ++ /* Setup parent bus device for this node */ ++ if (!bus_node->node_info->is_fab_dev) { ++ struct device *bus_parent_device = ++ bus_find_device(&msm_bus_type, NULL, ++ (void *)&bus_node->node_info->bus_device_id, ++ msm_bus_device_match_adhoc); ++ ++ if (!bus_parent_device) { ++ MSM_BUS_ERR("%s: Error finding parentdev %d parent %d", ++ __func__, ++ bus_node->node_info->id, ++ bus_node->node_info->bus_device_id); ++ ret = -ENXIO; ++ goto exit_setup_dev_conn; ++ } ++ bus_node->node_info->bus_device = bus_parent_device; ++ } ++ ++ bus_node->node_info->is_traversed = false; ++ ++ for (j = 0; j < bus_node->node_info->num_connections; j++) { ++ bus_node->node_info->dev_connections[j] = ++ bus_find_device(&msm_bus_type, NULL, ++ (void *)&bus_node->node_info->connections[j], ++ msm_bus_device_match_adhoc); ++ ++ if (!bus_node->node_info->dev_connections[j]) { ++ MSM_BUS_ERR("%s: Error finding conn %d for device %d", ++ __func__, bus_node->node_info->connections[j], ++ bus_node->node_info->id); ++ ret = -ENODEV; ++ goto exit_setup_dev_conn; ++ } ++ } ++ ++ for (j = 0; j < bus_node->node_info->num_blist; j++) { ++ bus_node->node_info->black_connections[j] = ++ bus_find_device(&msm_bus_type, NULL, ++ (void *)&bus_node->node_info-> ++ black_listed_connections[j], ++ msm_bus_device_match_adhoc); ++ ++ if (!bus_node->node_info->black_connections[j]) { ++ MSM_BUS_ERR("%s: Error finding conn %d for device %d\n", ++ __func__, bus_node->node_info-> ++ black_listed_connections[j], ++ bus_node->node_info->id); ++ ret = -ENODEV; ++ goto exit_setup_dev_conn; ++ } ++ } ++ ++exit_setup_dev_conn: ++ return ret; ++} ++ ++static int msm_bus_node_debug(struct device *bus_dev, void *data) ++{ ++ int j; ++ int ret = 0; ++ struct msm_bus_node_device_type *bus_node = NULL; ++ ++ bus_node = bus_dev->platform_data; ++ if (!bus_node) { ++ MSM_BUS_ERR("%s: Can't get device info", __func__); ++ ret = -ENODEV; ++ goto exit_node_debug; ++ } ++ ++ MSM_BUS_DBG("Device = %d buswidth %u", bus_node->node_info->id, ++ bus_node->node_info->buswidth); ++ for (j = 0; j < bus_node->node_info->num_connections; j++) { ++ struct msm_bus_node_device_type *bdev = ++ (struct msm_bus_node_device_type *) ++ bus_node->node_info->dev_connections[j]->platform_data; ++ MSM_BUS_DBG("\n\t Connection[%d] %d", j, bdev->node_info->id); ++ } ++ ++exit_node_debug: ++ return ret; ++} ++ ++static int msm_bus_device_probe(struct platform_device *pdev) ++{ ++ unsigned int i, ret; ++ struct msm_bus_device_node_registration *pdata; ++ ++ /* If possible, get pdata from device-tree */ ++ if (pdev->dev.of_node) ++ pdata = msm_bus_of_to_pdata(pdev); ++ else { ++ pdata = (struct msm_bus_device_node_registration *)pdev-> ++ dev.platform_data; ++ } ++ ++ if (IS_ERR_OR_NULL(pdata)) { ++ MSM_BUS_ERR("No platform data found"); ++ ret = -ENODATA; ++ goto exit_device_probe; ++ } ++ ++ for (i = 0; i < pdata->num_devices; i++) { ++ struct device *node_dev = NULL; ++ ++ node_dev = msm_bus_device_init(&pdata->info[i]); ++ ++ if (!node_dev) { ++ MSM_BUS_ERR("%s: Error during dev init for %d", ++ __func__, pdata->info[i].node_info->id); ++ ret = -ENXIO; ++ goto exit_device_probe; ++ } ++ ++ ret = msm_bus_init_clk(node_dev, &pdata->info[i]); ++ /*Is this a fabric device ?*/ ++ if (pdata->info[i].node_info->is_fab_dev) { ++ MSM_BUS_DBG("%s: %d is a fab", __func__, ++ pdata->info[i].node_info->id); ++ ret = msm_bus_fabric_init(node_dev, &pdata->info[i]); ++ if (ret) { ++ MSM_BUS_ERR("%s: Error intializing fab %d", ++ __func__, pdata->info[i].node_info->id); ++ goto exit_device_probe; ++ } ++ } ++ } ++ ++ ret = bus_for_each_dev(&msm_bus_type, NULL, NULL, ++ msm_bus_setup_dev_conn); ++ if (ret) { ++ MSM_BUS_ERR("%s: Error setting up dev connections", __func__); ++ goto exit_device_probe; ++ } ++ ++ ret = bus_for_each_dev(&msm_bus_type, NULL, NULL, msm_bus_dev_init_qos); ++ if (ret) { ++ MSM_BUS_ERR("%s: Error during qos init", __func__); ++ goto exit_device_probe; ++ } ++ ++ bus_for_each_dev(&msm_bus_type, NULL, NULL, msm_bus_node_debug); ++ ++ /* Register the arb layer ops */ ++ msm_bus_arb_setops_adhoc(&arb_ops); ++ devm_kfree(&pdev->dev, pdata->info); ++ devm_kfree(&pdev->dev, pdata); ++exit_device_probe: ++ return ret; ++} ++ ++static int msm_bus_device_rules_probe(struct platform_device *pdev) ++{ ++ struct bus_rule_type *rule_data = NULL; ++ int num_rules = 0; ++ ++ num_rules = msm_bus_of_get_static_rules(pdev, &rule_data); ++ ++ if (!rule_data) ++ goto exit_rules_probe; ++ ++ msm_rule_register(num_rules, rule_data, NULL); ++ static_rules.num_rules = num_rules; ++ static_rules.rules = rule_data; ++ pdev->dev.platform_data = &static_rules; ++ ++exit_rules_probe: ++ return 0; ++} ++ ++int msm_bus_device_rules_remove(struct platform_device *pdev) ++{ ++ struct static_rules_type *static_rules = NULL; ++ ++ static_rules = pdev->dev.platform_data; ++ if (static_rules) ++ msm_rule_unregister(static_rules->num_rules, ++ static_rules->rules, NULL); ++ return 0; ++} ++ ++static int msm_bus_free_dev(struct device *dev, void *data) ++{ ++ struct msm_bus_node_device_type *bus_node = NULL; ++ ++ bus_node = dev->platform_data; ++ ++ if (bus_node) ++ MSM_BUS_ERR("\n%s: Removing device %d", __func__, ++ bus_node->node_info->id); ++ device_unregister(dev); ++ return 0; ++} ++ ++int msm_bus_device_remove(struct platform_device *pdev) ++{ ++ bus_for_each_dev(&msm_bus_type, NULL, NULL, msm_bus_free_dev); ++ return 0; ++} ++ ++static struct of_device_id rules_match[] = { ++ {.compatible = "qcom,msm-bus-static-bw-rules"}, ++ {} ++}; ++ ++static struct platform_driver msm_bus_rules_driver = { ++ .probe = msm_bus_device_rules_probe, ++ .remove = msm_bus_device_rules_remove, ++ .driver = { ++ .name = "msm_bus_rules_device", ++ .owner = THIS_MODULE, ++ .of_match_table = rules_match, ++ }, ++}; ++ ++static struct of_device_id fabric_match[] = { ++ {.compatible = "qcom,msm-bus-device"}, ++ {} ++}; ++ ++static struct platform_driver msm_bus_device_driver = { ++ .probe = msm_bus_device_probe, ++ .remove = msm_bus_device_remove, ++ .driver = { ++ .name = "msm_bus_device", ++ .owner = THIS_MODULE, ++ .of_match_table = fabric_match, ++ }, ++}; ++ ++int __init msm_bus_device_init_driver(void) ++{ ++ int rc; ++ ++ MSM_BUS_ERR("msm_bus_fabric_init_driver\n"); ++ rc = platform_driver_register(&msm_bus_device_driver); ++ ++ if (rc) { ++ MSM_BUS_ERR("Failed to register bus device driver"); ++ return rc; ++ } ++ return platform_driver_register(&msm_bus_rules_driver); ++} ++subsys_initcall(msm_bus_device_init_driver); +--- /dev/null ++++ b/drivers/bus/msm_bus/msm_bus_id.c +@@ -0,0 +1,94 @@ ++/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include "msm-bus.h" ++#include "msm-bus-board.h" ++#include "msm_bus_core.h" ++#include "msm_bus_noc.h" ++#include "msm_bus_bimc.h" ++ ++static uint32_t master_iids[MSM_BUS_MASTER_LAST]; ++static uint32_t slave_iids[MSM_BUS_SLAVE_LAST - SLAVE_ID_KEY]; ++ ++static void msm_bus_assign_iids(struct msm_bus_fabric_registration ++ *fabreg, int fabid) ++{ ++ int i; ++ for (i = 0; i < fabreg->len; i++) { ++ if (!fabreg->info[i].gateway) { ++ fabreg->info[i].priv_id = fabid + fabreg->info[i].id; ++ if (fabreg->info[i].id < SLAVE_ID_KEY) { ++ if (fabreg->info[i].id >= MSM_BUS_MASTER_LAST) { ++ WARN(1, "id %d exceeds array size!\n", ++ fabreg->info[i].id); ++ continue; ++ } ++ ++ master_iids[fabreg->info[i].id] = ++ fabreg->info[i].priv_id; ++ } else { ++ if ((fabreg->info[i].id - SLAVE_ID_KEY) >= ++ (MSM_BUS_SLAVE_LAST - SLAVE_ID_KEY)) { ++ WARN(1, "id %d exceeds array size!\n", ++ fabreg->info[i].id); ++ continue; ++ } ++ ++ slave_iids[fabreg->info[i].id - (SLAVE_ID_KEY)] ++ = fabreg->info[i].priv_id; ++ } ++ } else { ++ fabreg->info[i].priv_id = fabreg->info[i].id; ++ } ++ } ++} ++ ++static int msm_bus_get_iid(int id) ++{ ++ if ((id < SLAVE_ID_KEY && id >= MSM_BUS_MASTER_LAST) || ++ id >= MSM_BUS_SLAVE_LAST) { ++ MSM_BUS_ERR("Cannot get iid. Invalid id %d passed\n", id); ++ return -EINVAL; ++ } ++ ++ return CHECK_ID(((id < SLAVE_ID_KEY) ? master_iids[id] : ++ slave_iids[id - SLAVE_ID_KEY]), id); ++} ++ ++static struct msm_bus_board_algorithm msm_bus_id_algo = { ++ .get_iid = msm_bus_get_iid, ++ .assign_iids = msm_bus_assign_iids, ++}; ++ ++int msm_bus_board_rpm_get_il_ids(uint16_t *id) ++{ ++ return -ENXIO; ++} ++ ++void msm_bus_board_init(struct msm_bus_fabric_registration *pdata) ++{ ++ pdata->board_algo = &msm_bus_id_algo; ++} ++ ++void msm_bus_board_set_nfab(struct msm_bus_fabric_registration *pdata, ++ int nfab) ++{ ++ if (nfab <= 0) ++ return; ++ ++ msm_bus_id_algo.board_nfab = nfab; ++} +--- /dev/null ++++ b/drivers/bus/msm_bus/msm_bus_noc.c +@@ -0,0 +1,770 @@ ++/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#define pr_fmt(fmt) "AXI: NOC: %s(): " fmt, __func__ ++ ++#include ++#include ++#include "msm-bus-board.h" ++#include "msm_bus_core.h" ++#include "msm_bus_noc.h" ++#include "msm_bus_adhoc.h" ++ ++/* NOC_QOS generic */ ++#define __CLZ(x) ((8 * sizeof(uint32_t)) - 1 - __fls(x)) ++#define SAT_SCALE 16 /* 16 bytes minimum for saturation */ ++#define BW_SCALE 256 /* 1/256 byte per cycle unit */ ++#define QOS_DEFAULT_BASEOFFSET 0x00003000 ++#define QOS_DEFAULT_DELTA 0x80 ++#define MAX_BW_FIELD (NOC_QOS_BWn_BW_BMSK >> NOC_QOS_BWn_BW_SHFT) ++#define MAX_SAT_FIELD (NOC_QOS_SATn_SAT_BMSK >> NOC_QOS_SATn_SAT_SHFT) ++ ++#define NOC_QOS_REG_BASE(b, o) ((b) + (o)) ++ ++#define NOC_QOS_ID_COREIDn_ADDR(b, o, n, d) \ ++ (NOC_QOS_REG_BASE(b, o) + (d) * (n)) ++enum noc_qos_id_coreidn { ++ NOC_QOS_ID_COREIDn_RMSK = 0xffffffff, ++ NOC_QOS_ID_COREIDn_MAXn = 32, ++ NOC_QOS_ID_COREIDn_CORECHSUM_BMSK = 0xffffff00, ++ NOC_QOS_ID_COREIDn_CORECHSUM_SHFT = 0x8, ++ NOC_QOS_ID_COREIDn_CORETYPEID_BMSK = 0xff, ++ NOC_QOS_ID_COREIDn_CORETYPEID_SHFT = 0x0, ++}; ++ ++#define NOC_QOS_ID_REVISIONIDn_ADDR(b, o, n, d) \ ++ (NOC_QOS_REG_BASE(b, o) + 0x4 + (d) * (n)) ++enum noc_qos_id_revisionidn { ++ NOC_QOS_ID_REVISIONIDn_RMSK = 0xffffffff, ++ NOC_QOS_ID_REVISIONIDn_MAXn = 32, ++ NOC_QOS_ID_REVISIONIDn_FLEXNOCID_BMSK = 0xffffff00, ++ NOC_QOS_ID_REVISIONIDn_FLEXNOCID_SHFT = 0x8, ++ NOC_QOS_ID_REVISIONIDn_USERID_BMSK = 0xff, ++ NOC_QOS_ID_REVISIONIDn_USERID_SHFT = 0x0, ++}; ++ ++#define NOC_QOS_PRIORITYn_ADDR(b, o, n, d) \ ++ (NOC_QOS_REG_BASE(b, o) + 0x8 + (d) * (n)) ++enum noc_qos_id_priorityn { ++ NOC_QOS_PRIORITYn_RMSK = 0x0000000f, ++ NOC_QOS_PRIORITYn_MAXn = 32, ++ NOC_QOS_PRIORITYn_P1_BMSK = 0xc, ++ NOC_QOS_PRIORITYn_P1_SHFT = 0x2, ++ NOC_QOS_PRIORITYn_P0_BMSK = 0x3, ++ NOC_QOS_PRIORITYn_P0_SHFT = 0x0, ++}; ++ ++#define NOC_QOS_MODEn_ADDR(b, o, n, d) \ ++ (NOC_QOS_REG_BASE(b, o) + 0xC + (d) * (n)) ++enum noc_qos_id_moden_rmsk { ++ NOC_QOS_MODEn_RMSK = 0x00000003, ++ NOC_QOS_MODEn_MAXn = 32, ++ NOC_QOS_MODEn_MODE_BMSK = 0x3, ++ NOC_QOS_MODEn_MODE_SHFT = 0x0, ++}; ++ ++#define NOC_QOS_BWn_ADDR(b, o, n, d) \ ++ (NOC_QOS_REG_BASE(b, o) + 0x10 + (d) * (n)) ++enum noc_qos_id_bwn { ++ NOC_QOS_BWn_RMSK = 0x0000ffff, ++ NOC_QOS_BWn_MAXn = 32, ++ NOC_QOS_BWn_BW_BMSK = 0xffff, ++ NOC_QOS_BWn_BW_SHFT = 0x0, ++}; ++ ++/* QOS Saturation registers */ ++#define NOC_QOS_SATn_ADDR(b, o, n, d) \ ++ (NOC_QOS_REG_BASE(b, o) + 0x14 + (d) * (n)) ++enum noc_qos_id_saturationn { ++ NOC_QOS_SATn_RMSK = 0x000003ff, ++ NOC_QOS_SATn_MAXn = 32, ++ NOC_QOS_SATn_SAT_BMSK = 0x3ff, ++ NOC_QOS_SATn_SAT_SHFT = 0x0, ++}; ++ ++static int noc_div(uint64_t *a, uint32_t b) ++{ ++ if ((*a > 0) && (*a < b)) ++ return 1; ++ else ++ return do_div(*a, b); ++} ++ ++/** ++ * Calculates bw hardware is using from register values ++ * bw returned is in bytes/sec ++ */ ++static uint64_t noc_bw(uint32_t bw_field, uint32_t qos_freq) ++{ ++ uint64_t res; ++ uint32_t rem, scale; ++ ++ res = 2 * qos_freq * bw_field; ++ scale = BW_SCALE * 1000; ++ rem = noc_div(&res, scale); ++ MSM_BUS_DBG("NOC: Calculated bw: %llu\n", res * 1000000ULL); ++ return res * 1000000ULL; ++} ++ ++static uint32_t noc_bw_ceil(long int bw_field, uint32_t qos_freq) ++{ ++ uint64_t bw_temp = 2 * qos_freq * bw_field; ++ uint32_t scale = 1000 * BW_SCALE; ++ noc_div(&bw_temp, scale); ++ return bw_temp * 1000000; ++} ++#define MAX_BW(timebase) noc_bw_ceil(MAX_BW_FIELD, (timebase)) ++ ++/** ++ * Calculates ws hardware is using from register values ++ * ws returned is in nanoseconds ++ */ ++static uint32_t noc_ws(uint64_t bw, uint32_t sat, uint32_t qos_freq) ++{ ++ if (bw && qos_freq) { ++ uint32_t bwf = bw * qos_freq; ++ uint64_t scale = 1000000000000LL * BW_SCALE * ++ SAT_SCALE * sat; ++ noc_div(&scale, bwf); ++ MSM_BUS_DBG("NOC: Calculated ws: %llu\n", scale); ++ return scale; ++ } ++ ++ return 0; ++} ++#define MAX_WS(bw, timebase) noc_ws((bw), MAX_SAT_FIELD, (timebase)) ++ ++/* Calculate bandwidth field value for requested bandwidth */ ++static uint32_t noc_bw_field(uint64_t bw, uint32_t qos_freq) ++{ ++ uint32_t bw_field = 0; ++ ++ if (bw) { ++ uint32_t rem; ++ uint64_t bw_capped = min_t(uint64_t, bw, MAX_BW(qos_freq)); ++ uint64_t bwc = bw_capped * BW_SCALE; ++ uint64_t qf = 2 * qos_freq * 1000; ++ ++ rem = noc_div(&bwc, qf); ++ bw_field = (uint32_t)min_t(uint64_t, bwc, MAX_BW_FIELD); ++ } ++ ++ MSM_BUS_DBG("NOC: bw_field: %u\n", bw_field); ++ return bw_field; ++} ++ ++static uint32_t noc_sat_field(uint64_t bw, uint32_t ws, uint32_t qos_freq) ++{ ++ uint32_t sat_field = 0, win; ++ ++ if (bw) { ++ /* Limit to max bw and scale bw to 100 KB increments */ ++ uint64_t tbw, tscale; ++ uint64_t bw_scaled = min_t(uint64_t, bw, MAX_BW(qos_freq)); ++ uint32_t rem = noc_div(&bw_scaled, 100000); ++ ++ /** ++ * Calculate saturation from windows size. ++ * WS must be at least one arb period. ++ * Saturation must not exceed max field size ++ * ++ * Bandwidth is in 100KB increments ++ * Window size is in ns ++ * qos_freq is in KHz ++ */ ++ win = max(ws, 1000000 / qos_freq); ++ tbw = bw_scaled * win * qos_freq; ++ tscale = 10000000ULL * BW_SCALE * SAT_SCALE; ++ rem = noc_div(&tbw, tscale); ++ sat_field = (uint32_t)min_t(uint64_t, tbw, MAX_SAT_FIELD); ++ } ++ ++ MSM_BUS_DBG("NOC: sat_field: %d\n", sat_field); ++ return sat_field; ++} ++ ++static void noc_set_qos_mode(void __iomem *base, uint32_t qos_off, ++ uint32_t mport, uint32_t qos_delta, uint8_t mode, ++ uint8_t perm_mode) ++{ ++ if (mode < NOC_QOS_MODE_MAX && ++ ((1 << mode) & perm_mode)) { ++ uint32_t reg_val; ++ ++ reg_val = readl_relaxed(NOC_QOS_MODEn_ADDR(base, qos_off, ++ mport, qos_delta)) & NOC_QOS_MODEn_RMSK; ++ writel_relaxed(((reg_val & (~(NOC_QOS_MODEn_MODE_BMSK))) | ++ (mode & NOC_QOS_MODEn_MODE_BMSK)), ++ NOC_QOS_MODEn_ADDR(base, qos_off, mport, qos_delta)); ++ } ++ /* Ensure qos mode is set before exiting */ ++ wmb(); ++} ++ ++static void noc_set_qos_priority(void __iomem *base, uint32_t qos_off, ++ uint32_t mport, uint32_t qos_delta, ++ struct msm_bus_noc_qos_priority *priority) ++{ ++ uint32_t reg_val, val; ++ ++ reg_val = readl_relaxed(NOC_QOS_PRIORITYn_ADDR(base, qos_off, mport, ++ qos_delta)) & NOC_QOS_PRIORITYn_RMSK; ++ val = priority->p1 << NOC_QOS_PRIORITYn_P1_SHFT; ++ writel_relaxed(((reg_val & (~(NOC_QOS_PRIORITYn_P1_BMSK))) | ++ (val & NOC_QOS_PRIORITYn_P1_BMSK)), ++ NOC_QOS_PRIORITYn_ADDR(base, qos_off, mport, qos_delta)); ++ ++ reg_val = readl_relaxed(NOC_QOS_PRIORITYn_ADDR(base, qos_off, mport, ++ qos_delta)) ++ & NOC_QOS_PRIORITYn_RMSK; ++ writel_relaxed(((reg_val & (~(NOC_QOS_PRIORITYn_P0_BMSK))) | ++ (priority->p0 & NOC_QOS_PRIORITYn_P0_BMSK)), ++ NOC_QOS_PRIORITYn_ADDR(base, qos_off, mport, qos_delta)); ++ /* Ensure qos priority is set before exiting */ ++ wmb(); ++} ++ ++static void msm_bus_noc_set_qos_bw(void __iomem *base, uint32_t qos_off, ++ uint32_t qos_freq, uint32_t mport, uint32_t qos_delta, ++ uint8_t perm_mode, struct msm_bus_noc_qos_bw *qbw) ++{ ++ uint32_t reg_val, val, mode; ++ ++ if (!qos_freq) { ++ MSM_BUS_DBG("Zero QoS Freq\n"); ++ return; ++ } ++ ++ ++ /* If Limiter or Regulator modes are not supported, bw not available*/ ++ if (perm_mode & (NOC_QOS_PERM_MODE_LIMITER | ++ NOC_QOS_PERM_MODE_REGULATOR)) { ++ uint32_t bw_val = noc_bw_field(qbw->bw, qos_freq); ++ uint32_t sat_val = noc_sat_field(qbw->bw, qbw->ws, ++ qos_freq); ++ ++ MSM_BUS_DBG("NOC: BW: perm_mode: %d bw_val: %d, sat_val: %d\n", ++ perm_mode, bw_val, sat_val); ++ /* ++ * If in Limiter/Regulator mode, first go to fixed mode. ++ * Clear QoS accumulator ++ **/ ++ mode = readl_relaxed(NOC_QOS_MODEn_ADDR(base, qos_off, ++ mport, qos_delta)) & NOC_QOS_MODEn_MODE_BMSK; ++ if (mode == NOC_QOS_MODE_REGULATOR || mode == ++ NOC_QOS_MODE_LIMITER) { ++ reg_val = readl_relaxed(NOC_QOS_MODEn_ADDR( ++ base, qos_off, mport, qos_delta)); ++ val = NOC_QOS_MODE_FIXED; ++ writel_relaxed((reg_val & (~(NOC_QOS_MODEn_MODE_BMSK))) ++ | (val & NOC_QOS_MODEn_MODE_BMSK), ++ NOC_QOS_MODEn_ADDR(base, qos_off, mport, ++ qos_delta)); ++ } ++ ++ reg_val = readl_relaxed(NOC_QOS_BWn_ADDR(base, qos_off, mport, ++ qos_delta)); ++ val = bw_val << NOC_QOS_BWn_BW_SHFT; ++ writel_relaxed(((reg_val & (~(NOC_QOS_BWn_BW_BMSK))) | ++ (val & NOC_QOS_BWn_BW_BMSK)), ++ NOC_QOS_BWn_ADDR(base, qos_off, mport, qos_delta)); ++ ++ MSM_BUS_DBG("NOC: BW: Wrote value: 0x%x\n", ((reg_val & ++ (~NOC_QOS_BWn_BW_BMSK)) | (val & ++ NOC_QOS_BWn_BW_BMSK))); ++ ++ reg_val = readl_relaxed(NOC_QOS_SATn_ADDR(base, qos_off, ++ mport, qos_delta)); ++ val = sat_val << NOC_QOS_SATn_SAT_SHFT; ++ writel_relaxed(((reg_val & (~(NOC_QOS_SATn_SAT_BMSK))) | ++ (val & NOC_QOS_SATn_SAT_BMSK)), ++ NOC_QOS_SATn_ADDR(base, qos_off, mport, qos_delta)); ++ ++ MSM_BUS_DBG("NOC: SAT: Wrote value: 0x%x\n", ((reg_val & ++ (~NOC_QOS_SATn_SAT_BMSK)) | (val & ++ NOC_QOS_SATn_SAT_BMSK))); ++ ++ /* Set mode back to what it was initially */ ++ reg_val = readl_relaxed(NOC_QOS_MODEn_ADDR(base, qos_off, ++ mport, qos_delta)); ++ writel_relaxed((reg_val & (~(NOC_QOS_MODEn_MODE_BMSK))) ++ | (mode & NOC_QOS_MODEn_MODE_BMSK), ++ NOC_QOS_MODEn_ADDR(base, qos_off, mport, qos_delta)); ++ /* Ensure that all writes for bandwidth registers have ++ * completed before returning ++ */ ++ wmb(); ++ } ++} ++ ++uint8_t msm_bus_noc_get_qos_mode(void __iomem *base, uint32_t qos_off, ++ uint32_t mport, uint32_t qos_delta, uint32_t mode, uint32_t perm_mode) ++{ ++ if (NOC_QOS_MODES_ALL_PERM == perm_mode) ++ return readl_relaxed(NOC_QOS_MODEn_ADDR(base, qos_off, ++ mport, qos_delta)) & NOC_QOS_MODEn_MODE_BMSK; ++ else ++ return 31 - __CLZ(mode & ++ NOC_QOS_MODES_ALL_PERM); ++} ++ ++void msm_bus_noc_get_qos_priority(void __iomem *base, uint32_t qos_off, ++ uint32_t mport, uint32_t qos_delta, ++ struct msm_bus_noc_qos_priority *priority) ++{ ++ priority->p1 = (readl_relaxed(NOC_QOS_PRIORITYn_ADDR(base, qos_off, ++ mport, qos_delta)) & NOC_QOS_PRIORITYn_P1_BMSK) >> ++ NOC_QOS_PRIORITYn_P1_SHFT; ++ ++ priority->p0 = (readl_relaxed(NOC_QOS_PRIORITYn_ADDR(base, qos_off, ++ mport, qos_delta)) & NOC_QOS_PRIORITYn_P0_BMSK) >> ++ NOC_QOS_PRIORITYn_P0_SHFT; ++} ++ ++void msm_bus_noc_get_qos_bw(void __iomem *base, uint32_t qos_off, ++ uint32_t qos_freq, ++ uint32_t mport, uint32_t qos_delta, uint8_t perm_mode, ++ struct msm_bus_noc_qos_bw *qbw) ++{ ++ if (perm_mode & (NOC_QOS_PERM_MODE_LIMITER | ++ NOC_QOS_PERM_MODE_REGULATOR)) { ++ uint32_t bw_val = readl_relaxed(NOC_QOS_BWn_ADDR( ++ base, qos_off, mport, qos_delta)) & NOC_QOS_BWn_BW_BMSK; ++ uint32_t sat = readl_relaxed(NOC_QOS_SATn_ADDR( ++ base, qos_off, mport, qos_delta)) ++ & NOC_QOS_SATn_SAT_BMSK; ++ ++ qbw->bw = noc_bw(bw_val, qos_freq); ++ qbw->ws = noc_ws(qbw->bw, sat, qos_freq); ++ } else { ++ qbw->bw = 0; ++ qbw->ws = 0; ++ } ++} ++ ++static int msm_bus_noc_mas_init(struct msm_bus_noc_info *ninfo, ++ struct msm_bus_inode_info *info) ++{ ++ int i; ++ struct msm_bus_noc_qos_priority *prio; ++ prio = kzalloc(sizeof(struct msm_bus_noc_qos_priority), ++ GFP_KERNEL); ++ if (!prio) { ++ MSM_BUS_WARN("Couldn't alloc prio data for node: %d\n", ++ info->node_info->id); ++ return -ENOMEM; ++ } ++ ++ prio->read_prio = info->node_info->prio_rd; ++ prio->write_prio = info->node_info->prio_wr; ++ prio->p1 = info->node_info->prio1; ++ prio->p0 = info->node_info->prio0; ++ info->hw_data = (void *)prio; ++ ++ if (!info->node_info->qport) { ++ MSM_BUS_DBG("No QoS Ports to init\n"); ++ return 0; ++ } ++ ++ for (i = 0; i < info->node_info->num_mports; i++) { ++ if (info->node_info->mode != NOC_QOS_MODE_BYPASS) { ++ noc_set_qos_priority(ninfo->base, ninfo->qos_baseoffset, ++ info->node_info->qport[i], ninfo->qos_delta, ++ prio); ++ ++ if (info->node_info->mode != NOC_QOS_MODE_FIXED) { ++ struct msm_bus_noc_qos_bw qbw; ++ qbw.ws = info->node_info->ws; ++ qbw.bw = 0; ++ msm_bus_noc_set_qos_bw(ninfo->base, ++ ninfo->qos_baseoffset, ++ ninfo->qos_freq, info->node_info-> ++ qport[i], ninfo->qos_delta, ++ info->node_info->perm_mode, ++ &qbw); ++ } ++ } ++ ++ noc_set_qos_mode(ninfo->base, ninfo->qos_baseoffset, ++ info->node_info->qport[i], ninfo->qos_delta, ++ info->node_info->mode, ++ info->node_info->perm_mode); ++ } ++ ++ return 0; ++} ++ ++static void msm_bus_noc_node_init(void *hw_data, ++ struct msm_bus_inode_info *info) ++{ ++ struct msm_bus_noc_info *ninfo = ++ (struct msm_bus_noc_info *)hw_data; ++ ++ if (!IS_SLAVE(info->node_info->priv_id)) ++ if (info->node_info->hw_sel != MSM_BUS_RPM) ++ msm_bus_noc_mas_init(ninfo, info); ++} ++ ++static int msm_bus_noc_allocate_commit_data(struct msm_bus_fabric_registration ++ *fab_pdata, void **cdata, int ctx) ++{ ++ struct msm_bus_noc_commit **cd = (struct msm_bus_noc_commit **)cdata; ++ struct msm_bus_noc_info *ninfo = ++ (struct msm_bus_noc_info *)fab_pdata->hw_data; ++ ++ *cd = kzalloc(sizeof(struct msm_bus_noc_commit), GFP_KERNEL); ++ if (!*cd) { ++ MSM_BUS_DBG("Couldn't alloc mem for cdata\n"); ++ return -ENOMEM; ++ } ++ ++ (*cd)->mas = ninfo->cdata[ctx].mas; ++ (*cd)->slv = ninfo->cdata[ctx].slv; ++ ++ return 0; ++} ++ ++static void *msm_bus_noc_allocate_noc_data(struct platform_device *pdev, ++ struct msm_bus_fabric_registration *fab_pdata) ++{ ++ struct resource *noc_mem; ++ struct resource *noc_io; ++ struct msm_bus_noc_info *ninfo; ++ int i; ++ ++ ninfo = kzalloc(sizeof(struct msm_bus_noc_info), GFP_KERNEL); ++ if (!ninfo) { ++ MSM_BUS_DBG("Couldn't alloc mem for noc info\n"); ++ return NULL; ++ } ++ ++ ninfo->nmasters = fab_pdata->nmasters; ++ ninfo->nqos_masters = fab_pdata->nmasters; ++ ninfo->nslaves = fab_pdata->nslaves; ++ ninfo->qos_freq = fab_pdata->qos_freq; ++ ++ if (!fab_pdata->qos_baseoffset) ++ ninfo->qos_baseoffset = QOS_DEFAULT_BASEOFFSET; ++ else ++ ninfo->qos_baseoffset = fab_pdata->qos_baseoffset; ++ ++ if (!fab_pdata->qos_delta) ++ ninfo->qos_delta = QOS_DEFAULT_DELTA; ++ else ++ ninfo->qos_delta = fab_pdata->qos_delta; ++ ++ ninfo->mas_modes = kzalloc(sizeof(uint32_t) * fab_pdata->nmasters, ++ GFP_KERNEL); ++ if (!ninfo->mas_modes) { ++ MSM_BUS_DBG("Couldn't alloc mem for noc master-modes\n"); ++ kfree(ninfo); ++ return NULL; ++ } ++ ++ for (i = 0; i < NUM_CTX; i++) { ++ ninfo->cdata[i].mas = kzalloc(sizeof(struct ++ msm_bus_node_hw_info) * fab_pdata->nmasters * 2, ++ GFP_KERNEL); ++ if (!ninfo->cdata[i].mas) { ++ MSM_BUS_DBG("Couldn't alloc mem for noc master-bw\n"); ++ kfree(ninfo->mas_modes); ++ kfree(ninfo); ++ return NULL; ++ } ++ ++ ninfo->cdata[i].slv = kzalloc(sizeof(struct ++ msm_bus_node_hw_info) * fab_pdata->nslaves * 2, ++ GFP_KERNEL); ++ if (!ninfo->cdata[i].slv) { ++ MSM_BUS_DBG("Couldn't alloc mem for noc master-bw\n"); ++ kfree(ninfo->cdata[i].mas); ++ goto err; ++ } ++ } ++ ++ /* If it's a virtual fabric, don't get memory info */ ++ if (fab_pdata->virt) ++ goto skip_mem; ++ ++ noc_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!noc_mem && !fab_pdata->virt) { ++ MSM_BUS_ERR("Cannot get NoC Base address\n"); ++ goto err; ++ } ++ ++ noc_io = request_mem_region(noc_mem->start, ++ resource_size(noc_mem), pdev->name); ++ if (!noc_io) { ++ MSM_BUS_ERR("NoC memory unavailable\n"); ++ goto err; ++ } ++ ++ ninfo->base = ioremap(noc_mem->start, resource_size(noc_mem)); ++ if (!ninfo->base) { ++ MSM_BUS_ERR("IOremap failed for NoC!\n"); ++ release_mem_region(noc_mem->start, resource_size(noc_mem)); ++ goto err; ++ } ++ ++skip_mem: ++ fab_pdata->hw_data = (void *)ninfo; ++ return (void *)ninfo; ++ ++err: ++ kfree(ninfo->mas_modes); ++ kfree(ninfo); ++ return NULL; ++} ++ ++static void free_commit_data(void *cdata) ++{ ++ struct msm_bus_noc_commit *cd = (struct msm_bus_noc_commit *)cdata; ++ ++ kfree(cd->mas); ++ kfree(cd->slv); ++ kfree(cd); ++} ++ ++static bool msm_bus_noc_update_bw_reg(int mode) ++{ ++ bool ret = false; ++ ++ if ((mode == NOC_QOS_MODE_LIMITER) || ++ (mode == NOC_QOS_MODE_REGULATOR)) ++ ret = true; ++ ++ return ret; ++} ++ ++static void msm_bus_noc_update_bw(struct msm_bus_inode_info *hop, ++ struct msm_bus_inode_info *info, ++ struct msm_bus_fabric_registration *fab_pdata, ++ void *sel_cdata, int *master_tiers, ++ int64_t add_bw) ++{ ++ struct msm_bus_noc_info *ninfo; ++ struct msm_bus_noc_qos_bw qos_bw; ++ int i, ports; ++ int64_t bw; ++ struct msm_bus_noc_commit *sel_cd = ++ (struct msm_bus_noc_commit *)sel_cdata; ++ ++ ninfo = (struct msm_bus_noc_info *)fab_pdata->hw_data; ++ if (!ninfo->qos_freq) { ++ MSM_BUS_DBG("NOC: No qos frequency to update bw\n"); ++ return; ++ } ++ ++ if (info->node_info->num_mports == 0) { ++ MSM_BUS_DBG("NOC: Skip Master BW\n"); ++ goto skip_mas_bw; ++ } ++ ++ ports = info->node_info->num_mports; ++ bw = INTERLEAVED_BW(fab_pdata, add_bw, ports); ++ ++ MSM_BUS_DBG("NOC: Update bw for: %d: %lld\n", ++ info->node_info->priv_id, add_bw); ++ for (i = 0; i < ports; i++) { ++ sel_cd->mas[info->node_info->masterp[i]].bw += bw; ++ sel_cd->mas[info->node_info->masterp[i]].hw_id = ++ info->node_info->mas_hw_id; ++ MSM_BUS_DBG("NOC: Update mas_bw: ID: %d, BW: %llu ports:%d\n", ++ info->node_info->priv_id, ++ sel_cd->mas[info->node_info->masterp[i]].bw, ++ ports); ++ /* Check if info is a shared master. ++ * If it is, mark it dirty ++ * If it isn't, then set QOS Bandwidth ++ **/ ++ if (info->node_info->hw_sel == MSM_BUS_RPM) ++ sel_cd->mas[info->node_info->masterp[i]].dirty = 1; ++ else { ++ if (!info->node_info->qport) { ++ MSM_BUS_DBG("No qos ports to update!\n"); ++ break; ++ } ++ ++ if (!(info->node_info->mode == NOC_QOS_MODE_REGULATOR) ++ || (info->node_info->mode == ++ NOC_QOS_MODE_LIMITER)) { ++ MSM_BUS_DBG("Skip QoS reg programming\n"); ++ break; ++ } ++ qos_bw.bw = sel_cd->mas[info->node_info->masterp[i]]. ++ bw; ++ qos_bw.ws = info->node_info->ws; ++ msm_bus_noc_set_qos_bw(ninfo->base, ++ ninfo->qos_baseoffset, ++ ninfo->qos_freq, ++ info->node_info->qport[i], ninfo->qos_delta, ++ info->node_info->perm_mode, &qos_bw); ++ MSM_BUS_DBG("NOC: QoS: Update mas_bw: ws: %u\n", ++ qos_bw.ws); ++ } ++ } ++ ++skip_mas_bw: ++ ports = hop->node_info->num_sports; ++ for (i = 0; i < ports; i++) { ++ sel_cd->slv[hop->node_info->slavep[i]].bw += add_bw; ++ sel_cd->slv[hop->node_info->slavep[i]].hw_id = ++ hop->node_info->slv_hw_id; ++ MSM_BUS_DBG("NOC: Update slave_bw for ID: %d -> %llu\n", ++ hop->node_info->priv_id, ++ sel_cd->slv[hop->node_info->slavep[i]].bw); ++ MSM_BUS_DBG("NOC: Update slave_bw for hw_id: %d, index: %d\n", ++ hop->node_info->slv_hw_id, hop->node_info->slavep[i]); ++ /* Check if hop is a shared slave. ++ * If it is, mark it dirty ++ * If it isn't, then nothing to be done as the ++ * slaves are in bypass mode. ++ **/ ++ if (hop->node_info->hw_sel == MSM_BUS_RPM) ++ sel_cd->slv[hop->node_info->slavep[i]].dirty = 1; ++ } ++} ++ ++static int msm_bus_noc_commit(struct msm_bus_fabric_registration ++ *fab_pdata, void *hw_data, void **cdata) ++{ ++ MSM_BUS_DBG("\nReached NOC Commit\n"); ++ msm_bus_remote_hw_commit(fab_pdata, hw_data, cdata); ++ return 0; ++} ++ ++static int msm_bus_noc_port_halt(uint32_t haltid, uint8_t mport) ++{ ++ return 0; ++} ++ ++static int msm_bus_noc_port_unhalt(uint32_t haltid, uint8_t mport) ++{ ++ return 0; ++} ++ ++static int msm_bus_noc_qos_init(struct msm_bus_node_device_type *info, ++ void __iomem *qos_base, ++ uint32_t qos_off, uint32_t qos_delta, ++ uint32_t qos_freq) ++{ ++ struct msm_bus_noc_qos_priority prio; ++ int ret = 0; ++ int i; ++ ++ prio.p1 = info->node_info->qos_params.prio1; ++ prio.p0 = info->node_info->qos_params.prio0; ++ ++ if (!info->node_info->qport) { ++ MSM_BUS_DBG("No QoS Ports to init\n"); ++ ret = 0; ++ goto err_qos_init; ++ } ++ ++ for (i = 0; i < info->node_info->num_qports; i++) { ++ if (info->node_info->qos_params.mode != NOC_QOS_MODE_BYPASS) { ++ noc_set_qos_priority(qos_base, qos_off, ++ info->node_info->qport[i], qos_delta, ++ &prio); ++ ++ if (info->node_info->qos_params.mode != ++ NOC_QOS_MODE_FIXED) { ++ struct msm_bus_noc_qos_bw qbw; ++ qbw.ws = info->node_info->qos_params.ws; ++ qbw.bw = 0; ++ msm_bus_noc_set_qos_bw(qos_base, qos_off, ++ qos_freq, ++ info->node_info->qport[i], ++ qos_delta, ++ info->node_info->qos_params.mode, ++ &qbw); ++ } ++ } ++ ++ noc_set_qos_mode(qos_base, qos_off, info->node_info->qport[i], ++ qos_delta, info->node_info->qos_params.mode, ++ (1 << info->node_info->qos_params.mode)); ++ } ++err_qos_init: ++ return ret; ++} ++ ++static int msm_bus_noc_set_bw(struct msm_bus_node_device_type *dev, ++ void __iomem *qos_base, ++ uint32_t qos_off, uint32_t qos_delta, ++ uint32_t qos_freq) ++{ ++ int ret = 0; ++ uint64_t bw = 0; ++ int i; ++ struct msm_bus_node_info_type *info = dev->node_info; ++ ++ if (info && info->num_qports && ++ ((info->qos_params.mode == NOC_QOS_MODE_REGULATOR) || ++ (info->qos_params.mode == ++ NOC_QOS_MODE_LIMITER))) { ++ struct msm_bus_noc_qos_bw qos_bw; ++ ++ bw = msm_bus_div64(info->num_qports, ++ dev->node_ab.ab[DUAL_CTX]); ++ ++ for (i = 0; i < info->num_qports; i++) { ++ if (!info->qport) { ++ MSM_BUS_DBG("No qos ports to update!\n"); ++ break; ++ } ++ ++ qos_bw.bw = bw; ++ qos_bw.ws = info->qos_params.ws; ++ msm_bus_noc_set_qos_bw(qos_base, qos_off, qos_freq, ++ info->qport[i], qos_delta, ++ info->qos_params.mode, &qos_bw); ++ MSM_BUS_DBG("NOC: QoS: Update mas_bw: ws: %u\n", ++ qos_bw.ws); ++ } ++ } ++ return ret; ++} ++int msm_bus_noc_hw_init(struct msm_bus_fabric_registration *pdata, ++ struct msm_bus_hw_algorithm *hw_algo) ++{ ++ /* Set interleaving to true by default */ ++ pdata->il_flag = true; ++ hw_algo->allocate_commit_data = msm_bus_noc_allocate_commit_data; ++ hw_algo->allocate_hw_data = msm_bus_noc_allocate_noc_data; ++ hw_algo->node_init = msm_bus_noc_node_init; ++ hw_algo->free_commit_data = free_commit_data; ++ hw_algo->update_bw = msm_bus_noc_update_bw; ++ hw_algo->commit = msm_bus_noc_commit; ++ hw_algo->port_halt = msm_bus_noc_port_halt; ++ hw_algo->port_unhalt = msm_bus_noc_port_unhalt; ++ hw_algo->update_bw_reg = msm_bus_noc_update_bw_reg; ++ hw_algo->config_master = NULL; ++ hw_algo->config_limiter = NULL; ++ ++ return 0; ++} ++ ++int msm_bus_noc_set_ops(struct msm_bus_node_device_type *bus_dev) ++{ ++ if (!bus_dev) ++ return -ENODEV; ++ else { ++ bus_dev->fabdev->noc_ops.qos_init = msm_bus_noc_qos_init; ++ bus_dev->fabdev->noc_ops.set_bw = msm_bus_noc_set_bw; ++ bus_dev->fabdev->noc_ops.limit_mport = NULL; ++ bus_dev->fabdev->noc_ops.update_bw_reg = ++ msm_bus_noc_update_bw_reg; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(msm_bus_noc_set_ops); +--- /dev/null ++++ b/drivers/bus/msm_bus/msm_bus_noc.h +@@ -0,0 +1,76 @@ ++/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _ARCH_ARM_MACH_MSM_BUS_BIMC_H ++#define _ARCH_ARM_MACH_MSM_BUS_BIMC_H ++ ++enum msm_bus_noc_qos_mode_type { ++ NOC_QOS_MODE_FIXED = 0, ++ NOC_QOS_MODE_LIMITER, ++ NOC_QOS_MODE_BYPASS, ++ NOC_QOS_MODE_REGULATOR, ++ NOC_QOS_MODE_MAX, ++}; ++ ++enum msm_bus_noc_qos_mode_perm { ++ NOC_QOS_PERM_MODE_FIXED = (1 << NOC_QOS_MODE_FIXED), ++ NOC_QOS_PERM_MODE_LIMITER = (1 << NOC_QOS_MODE_LIMITER), ++ NOC_QOS_PERM_MODE_BYPASS = (1 << NOC_QOS_MODE_BYPASS), ++ NOC_QOS_PERM_MODE_REGULATOR = (1 << NOC_QOS_MODE_REGULATOR), ++}; ++ ++#define NOC_QOS_MODES_ALL_PERM (NOC_QOS_PERM_MODE_FIXED | \ ++ NOC_QOS_PERM_MODE_LIMITER | NOC_QOS_PERM_MODE_BYPASS | \ ++ NOC_QOS_PERM_MODE_REGULATOR) ++ ++struct msm_bus_noc_commit { ++ struct msm_bus_node_hw_info *mas; ++ struct msm_bus_node_hw_info *slv; ++}; ++ ++struct msm_bus_noc_info { ++ void __iomem *base; ++ uint32_t base_addr; ++ uint32_t nmasters; ++ uint32_t nqos_masters; ++ uint32_t nslaves; ++ uint32_t qos_freq; /* QOS Clock in KHz */ ++ uint32_t qos_baseoffset; ++ uint32_t qos_delta; ++ uint32_t *mas_modes; ++ struct msm_bus_noc_commit cdata[NUM_CTX]; ++}; ++ ++struct msm_bus_noc_qos_priority { ++ uint32_t high_prio; ++ uint32_t low_prio; ++ uint32_t read_prio; ++ uint32_t write_prio; ++ uint32_t p1; ++ uint32_t p0; ++}; ++ ++struct msm_bus_noc_qos_bw { ++ uint64_t bw; /* Bandwidth in bytes per second */ ++ uint32_t ws; /* Window size in nano seconds */ ++}; ++ ++void msm_bus_noc_init(struct msm_bus_noc_info *ninfo); ++uint8_t msm_bus_noc_get_qos_mode(void __iomem *base, uint32_t qos_off, ++ uint32_t mport, uint32_t qos_delta, uint32_t mode, uint32_t perm_mode); ++void msm_bus_noc_get_qos_priority(void __iomem *base, uint32_t qos_off, ++ uint32_t mport, uint32_t qos_delta, ++ struct msm_bus_noc_qos_priority *qprio); ++void msm_bus_noc_get_qos_bw(void __iomem *base, uint32_t qos_off, ++ uint32_t qos_freq, uint32_t mport, uint32_t qos_delta, ++ uint8_t perm_mode, struct msm_bus_noc_qos_bw *qbw); ++#endif /*_ARCH_ARM_MACH_MSM_BUS_NOC_H */ +--- /dev/null ++++ b/drivers/bus/msm_bus/msm_bus_of.c +@@ -0,0 +1,705 @@ ++/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "msm-bus.h" ++#include "msm-bus-board.h" ++#include "msm_bus_core.h" ++ ++static const char * const hw_sel_name[] = {"RPM", "NoC", "BIMC", NULL}; ++static const char * const mode_sel_name[] = {"Fixed", "Limiter", "Bypass", ++ "Regulator", NULL}; ++ ++static int get_num(const char *const str[], const char *name) ++{ ++ int i = 0; ++ ++ do { ++ if (!strcmp(name, str[i])) ++ return i; ++ ++ i++; ++ } while (str[i] != NULL); ++ ++ pr_err("Error: string %s not found\n", name); ++ return -EINVAL; ++} ++ ++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_MSM_BUS_SCALING) ++static struct msm_bus_scale_pdata *get_pdata(struct platform_device *pdev, ++ struct device_node *of_node) ++{ ++ struct msm_bus_scale_pdata *pdata = NULL; ++ struct msm_bus_paths *usecase = NULL; ++ int i = 0, j, ret, num_usecases = 0, num_paths, len; ++ const uint32_t *vec_arr = NULL; ++ bool mem_err = false; ++ ++ if (!pdev) { ++ pr_err("Error: Null Platform device\n"); ++ return NULL; ++ } ++ ++ pdata = devm_kzalloc(&pdev->dev, sizeof(struct msm_bus_scale_pdata), ++ GFP_KERNEL); ++ if (!pdata) { ++ pr_err("Error: Memory allocation for pdata failed\n"); ++ mem_err = true; ++ goto err; ++ } ++ ++ ret = of_property_read_string(of_node, "qcom,msm-bus,name", ++ &pdata->name); ++ if (ret) { ++ pr_err("Error: Client name not found\n"); ++ goto err; ++ } ++ ++ ret = of_property_read_u32(of_node, "qcom,msm-bus,num-cases", ++ &num_usecases); ++ if (ret) { ++ pr_err("Error: num-usecases not found\n"); ++ goto err; ++ } ++ ++ pdata->num_usecases = num_usecases; ++ ++ if (of_property_read_bool(of_node, "qcom,msm-bus,active-only")) ++ pdata->active_only = 1; ++ else { ++ pr_debug("active_only flag absent.\n"); ++ pr_debug("Using dual context by default\n"); ++ } ++ ++ usecase = devm_kzalloc(&pdev->dev, (sizeof(struct msm_bus_paths) * ++ pdata->num_usecases), GFP_KERNEL); ++ if (!usecase) { ++ pr_err("Error: Memory allocation for paths failed\n"); ++ mem_err = true; ++ goto err; ++ } ++ ++ ret = of_property_read_u32(of_node, "qcom,msm-bus,num-paths", ++ &num_paths); ++ if (ret) { ++ pr_err("Error: num_paths not found\n"); ++ goto err; ++ } ++ ++ vec_arr = of_get_property(of_node, "qcom,msm-bus,vectors-KBps", &len); ++ if (vec_arr == NULL) { ++ pr_err("Error: Vector array not found\n"); ++ goto err; ++ } ++ ++ if (len != num_usecases * num_paths * sizeof(uint32_t) * 4) { ++ pr_err("Error: Length-error on getting vectors\n"); ++ goto err; ++ } ++ ++ for (i = 0; i < num_usecases; i++) { ++ usecase[i].num_paths = num_paths; ++ usecase[i].vectors = devm_kzalloc(&pdev->dev, num_paths * ++ sizeof(struct msm_bus_vectors), GFP_KERNEL); ++ if (!usecase[i].vectors) { ++ mem_err = true; ++ pr_err("Error: Mem alloc failure in vectors\n"); ++ goto err; ++ } ++ ++ for (j = 0; j < num_paths; j++) { ++ int index = ((i * num_paths) + j) * 4; ++ usecase[i].vectors[j].src = be32_to_cpu(vec_arr[index]); ++ usecase[i].vectors[j].dst = ++ be32_to_cpu(vec_arr[index + 1]); ++ usecase[i].vectors[j].ab = (uint64_t) ++ KBTOB(be32_to_cpu(vec_arr[index + 2])); ++ usecase[i].vectors[j].ib = (uint64_t) ++ KBTOB(be32_to_cpu(vec_arr[index + 3])); ++ } ++ } ++ ++ pdata->usecase = usecase; ++ return pdata; ++err: ++ if (mem_err) { ++ for (; i > 0; i--) ++ kfree(usecase[i-1].vectors); ++ ++ kfree(usecase); ++ kfree(pdata); ++ } ++ ++ return NULL; ++} ++ ++/** ++ * msm_bus_cl_get_pdata() - Generate bus client data from device tree ++ * provided by clients. ++ * ++ * of_node: Device tree node to extract information from ++ * ++ * The function returns a valid pointer to the allocated bus-scale-pdata ++ * if the vectors were correctly read from the client's device node. ++ * Any error in reading or parsing the device node will return NULL ++ * to the caller. ++ */ ++struct msm_bus_scale_pdata *msm_bus_cl_get_pdata(struct platform_device *pdev) ++{ ++ struct device_node *of_node; ++ struct msm_bus_scale_pdata *pdata = NULL; ++ ++ if (!pdev) { ++ pr_err("Error: Null Platform device\n"); ++ return NULL; ++ } ++ ++ of_node = pdev->dev.of_node; ++ pdata = get_pdata(pdev, of_node); ++ if (!pdata) { ++ pr_err("client has to provide missing entry for successful registration\n"); ++ return NULL; ++ } ++ ++ return pdata; ++} ++EXPORT_SYMBOL(msm_bus_cl_get_pdata); ++ ++/** ++ * msm_bus_cl_pdata_from_node() - Generate bus client data from device tree ++ * node provided by clients. This function should be used when a client ++ * driver needs to register multiple bus-clients from a single device-tree ++ * node associated with the platform-device. ++ * ++ * of_node: The subnode containing information about the bus scaling ++ * data ++ * ++ * pdev: Platform device associated with the device-tree node ++ * ++ * The function returns a valid pointer to the allocated bus-scale-pdata ++ * if the vectors were correctly read from the client's device node. ++ * Any error in reading or parsing the device node will return NULL ++ * to the caller. ++ */ ++struct msm_bus_scale_pdata *msm_bus_pdata_from_node( ++ struct platform_device *pdev, struct device_node *of_node) ++{ ++ struct msm_bus_scale_pdata *pdata = NULL; ++ ++ if (!pdev) { ++ pr_err("Error: Null Platform device\n"); ++ return NULL; ++ } ++ ++ if (!of_node) { ++ pr_err("Error: Null of_node passed to bus driver\n"); ++ return NULL; ++ } ++ ++ pdata = get_pdata(pdev, of_node); ++ if (!pdata) { ++ pr_err("client has to provide missing entry for successful registration\n"); ++ return NULL; ++ } ++ ++ return pdata; ++} ++EXPORT_SYMBOL(msm_bus_pdata_from_node); ++ ++/** ++ * msm_bus_cl_clear_pdata() - Clear pdata allocated from device-tree ++ * of_node: Device tree node to extract information from ++ */ ++void msm_bus_cl_clear_pdata(struct msm_bus_scale_pdata *pdata) ++{ ++ int i; ++ ++ for (i = 0; i < pdata->num_usecases; i++) ++ kfree(pdata->usecase[i].vectors); ++ ++ kfree(pdata->usecase); ++ kfree(pdata); ++} ++EXPORT_SYMBOL(msm_bus_cl_clear_pdata); ++#endif ++ ++static int *get_arr(struct platform_device *pdev, ++ const struct device_node *node, const char *prop, ++ int *nports) ++{ ++ int size = 0, ret; ++ int *arr = NULL; ++ ++ if (of_get_property(node, prop, &size)) { ++ *nports = size / sizeof(int); ++ } else { ++ pr_debug("Property %s not available\n", prop); ++ *nports = 0; ++ return NULL; ++ } ++ ++ if (!size) { ++ *nports = 0; ++ return NULL; ++ } ++ ++ arr = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); ++ if (ZERO_OR_NULL_PTR(arr)) { ++ pr_err("Error: Failed to alloc mem for %s\n", prop); ++ return NULL; ++ } ++ ++ ret = of_property_read_u32_array(node, prop, (u32 *)arr, *nports); ++ if (ret) { ++ pr_err("Error in reading property: %s\n", prop); ++ goto err; ++ } ++ ++ return arr; ++err: ++ devm_kfree(&pdev->dev, arr); ++ return NULL; ++} ++ ++static u64 *get_th_params(struct platform_device *pdev, ++ const struct device_node *node, const char *prop, ++ int *nports) ++{ ++ int size = 0, ret; ++ u64 *ret_arr = NULL; ++ int *arr = NULL; ++ int i; ++ ++ if (of_get_property(node, prop, &size)) { ++ *nports = size / sizeof(int); ++ } else { ++ pr_debug("Property %s not available\n", prop); ++ *nports = 0; ++ return NULL; ++ } ++ ++ if (!size) { ++ *nports = 0; ++ return NULL; ++ } ++ ++ ret_arr = devm_kzalloc(&pdev->dev, (*nports * sizeof(u64)), ++ GFP_KERNEL); ++ if (ZERO_OR_NULL_PTR(ret_arr)) { ++ pr_err("Error: Failed to alloc mem for ret arr %s\n", prop); ++ return NULL; ++ } ++ ++ arr = kzalloc(size, GFP_KERNEL); ++ if ((ZERO_OR_NULL_PTR(arr))) { ++ pr_err("Error: Failed to alloc temp mem for %s\n", prop); ++ return NULL; ++ } ++ ++ ret = of_property_read_u32_array(node, prop, (u32 *)arr, *nports); ++ if (ret) { ++ pr_err("Error in reading property: %s\n", prop); ++ goto err; ++ } ++ ++ for (i = 0; i < *nports; i++) ++ ret_arr[i] = (uint64_t)KBTOB(arr[i]); ++ ++ MSM_BUS_DBG("%s: num entries %d prop %s", __func__, *nports, prop); ++ ++ for (i = 0; i < *nports; i++) ++ MSM_BUS_DBG("Th %d val %llu", i, ret_arr[i]); ++ ++ kfree(arr); ++ return ret_arr; ++err: ++ kfree(arr); ++ devm_kfree(&pdev->dev, ret_arr); ++ return NULL; ++} ++ ++static struct msm_bus_node_info *get_nodes(struct device_node *of_node, ++ struct platform_device *pdev, ++ struct msm_bus_fabric_registration *pdata) ++{ ++ struct msm_bus_node_info *info; ++ struct device_node *child_node = NULL; ++ int i = 0, ret; ++ int num_bw = 0; ++ u32 temp; ++ ++ for_each_child_of_node(of_node, child_node) { ++ i++; ++ } ++ ++ pdata->len = i; ++ info = (struct msm_bus_node_info *) ++ devm_kzalloc(&pdev->dev, sizeof(struct msm_bus_node_info) * ++ pdata->len, GFP_KERNEL); ++ if (ZERO_OR_NULL_PTR(info)) { ++ pr_err("Failed to alloc memory for nodes: %d\n", pdata->len); ++ goto err; ++ } ++ ++ i = 0; ++ child_node = NULL; ++ for_each_child_of_node(of_node, child_node) { ++ const char *sel_str; ++ ++ ret = of_property_read_string(child_node, "label", ++ &info[i].name); ++ if (ret) ++ pr_err("Error reading node label\n"); ++ ++ ret = of_property_read_u32(child_node, "cell-id", &info[i].id); ++ if (ret) { ++ pr_err("Error reading node id\n"); ++ goto err; ++ } ++ ++ if (of_property_read_bool(child_node, "qcom,gateway")) ++ info[i].gateway = 1; ++ ++ of_property_read_u32(child_node, "qcom,mas-hw-id", ++ &info[i].mas_hw_id); ++ ++ of_property_read_u32(child_node, "qcom,slv-hw-id", ++ &info[i].slv_hw_id); ++ info[i].masterp = get_arr(pdev, child_node, ++ "qcom,masterp", &info[i].num_mports); ++ /* No need to store number of qports */ ++ info[i].qport = get_arr(pdev, child_node, ++ "qcom,qport", &ret); ++ pdata->nmasters += info[i].num_mports; ++ ++ ++ info[i].slavep = get_arr(pdev, child_node, ++ "qcom,slavep", &info[i].num_sports); ++ pdata->nslaves += info[i].num_sports; ++ ++ ++ info[i].tier = get_arr(pdev, child_node, ++ "qcom,tier", &info[i].num_tiers); ++ ++ if (of_property_read_bool(child_node, "qcom,ahb")) ++ info[i].ahb = 1; ++ ++ ret = of_property_read_string(child_node, "qcom,hw-sel", ++ &sel_str); ++ if (ret) ++ info[i].hw_sel = 0; ++ else { ++ ret = get_num(hw_sel_name, sel_str); ++ if (ret < 0) { ++ pr_err("Invalid hw-sel\n"); ++ goto err; ++ } ++ ++ info[i].hw_sel = ret; ++ } ++ ++ of_property_read_u32(child_node, "qcom,buswidth", ++ &info[i].buswidth); ++ of_property_read_u32(child_node, "qcom,ws", &info[i].ws); ++ ++ info[i].dual_conf = ++ of_property_read_bool(child_node, "qcom,dual-conf"); ++ ++ ++ info[i].th = get_th_params(pdev, child_node, "qcom,thresh", ++ &info[i].num_thresh); ++ ++ info[i].bimc_bw = get_th_params(pdev, child_node, ++ "qcom,bimc,bw", &num_bw); ++ ++ if (num_bw != info[i].num_thresh) { ++ pr_err("%s:num_bw %d must equal num_thresh %d", ++ __func__, num_bw, info[i].num_thresh); ++ pr_err("%s:Err setting up dual conf for %s", ++ __func__, info[i].name); ++ goto err; ++ } ++ ++ of_property_read_u32(child_node, "qcom,bimc,gp", ++ &info[i].bimc_gp); ++ of_property_read_u32(child_node, "qcom,bimc,thmp", ++ &info[i].bimc_thmp); ++ ++ ret = of_property_read_string(child_node, "qcom,mode-thresh", ++ &sel_str); ++ if (ret) ++ info[i].mode_thresh = 0; ++ else { ++ ret = get_num(mode_sel_name, sel_str); ++ if (ret < 0) { ++ pr_err("Unknown mode :%s\n", sel_str); ++ goto err; ++ } ++ ++ info[i].mode_thresh = ret; ++ MSM_BUS_DBG("AXI: THreshold mode set: %d\n", ++ info[i].mode_thresh); ++ } ++ ++ ret = of_property_read_string(child_node, "qcom,mode", ++ &sel_str); ++ ++ if (ret) ++ info[i].mode = 0; ++ else { ++ ret = get_num(mode_sel_name, sel_str); ++ if (ret < 0) { ++ pr_err("Unknown mode :%s\n", sel_str); ++ goto err; ++ } ++ ++ info[i].mode = ret; ++ } ++ ++ info[i].nr_lim = ++ of_property_read_bool(child_node, "qcom,nr-lim"); ++ ++ ret = of_property_read_u32(child_node, "qcom,ff", ++ &info[i].ff); ++ if (ret) { ++ pr_debug("fudge factor not present %d", info[i].id); ++ info[i].ff = 0; ++ } ++ ++ ret = of_property_read_u32(child_node, "qcom,floor-bw", ++ &temp); ++ if (ret) { ++ pr_debug("fabdev floor bw not present %d", info[i].id); ++ info[i].floor_bw = 0; ++ } else { ++ info[i].floor_bw = KBTOB(temp); ++ } ++ ++ info[i].rt_mas = ++ of_property_read_bool(child_node, "qcom,rt-mas"); ++ ++ ret = of_property_read_string(child_node, "qcom,perm-mode", ++ &sel_str); ++ if (ret) ++ info[i].perm_mode = 0; ++ else { ++ ret = get_num(mode_sel_name, sel_str); ++ if (ret < 0) ++ goto err; ++ ++ info[i].perm_mode = 1 << ret; ++ } ++ ++ of_property_read_u32(child_node, "qcom,prio-lvl", ++ &info[i].prio_lvl); ++ of_property_read_u32(child_node, "qcom,prio-rd", ++ &info[i].prio_rd); ++ of_property_read_u32(child_node, "qcom,prio-wr", ++ &info[i].prio_wr); ++ of_property_read_u32(child_node, "qcom,prio0", &info[i].prio0); ++ of_property_read_u32(child_node, "qcom,prio1", &info[i].prio1); ++ ret = of_property_read_string(child_node, "qcom,slaveclk-dual", ++ &info[i].slaveclk[DUAL_CTX]); ++ if (!ret) ++ pr_debug("Got slaveclk_dual: %s\n", ++ info[i].slaveclk[DUAL_CTX]); ++ else ++ info[i].slaveclk[DUAL_CTX] = NULL; ++ ++ ret = of_property_read_string(child_node, ++ "qcom,slaveclk-active", &info[i].slaveclk[ACTIVE_CTX]); ++ if (!ret) ++ pr_debug("Got slaveclk_active\n"); ++ else ++ info[i].slaveclk[ACTIVE_CTX] = NULL; ++ ++ ret = of_property_read_string(child_node, "qcom,memclk-dual", ++ &info[i].memclk[DUAL_CTX]); ++ if (!ret) ++ pr_debug("Got memclk_dual\n"); ++ else ++ info[i].memclk[DUAL_CTX] = NULL; ++ ++ ret = of_property_read_string(child_node, "qcom,memclk-active", ++ &info[i].memclk[ACTIVE_CTX]); ++ if (!ret) ++ pr_debug("Got memclk_active\n"); ++ else ++ info[i].memclk[ACTIVE_CTX] = NULL; ++ ++ ret = of_property_read_string(child_node, "qcom,iface-clk-node", ++ &info[i].iface_clk_node); ++ if (!ret) ++ pr_debug("Got iface_clk_node\n"); ++ else ++ info[i].iface_clk_node = NULL; ++ ++ pr_debug("Node name: %s\n", info[i].name); ++ of_node_put(child_node); ++ i++; ++ } ++ ++ pr_debug("Bus %d added: %d masters\n", pdata->id, pdata->nmasters); ++ pr_debug("Bus %d added: %d slaves\n", pdata->id, pdata->nslaves); ++ return info; ++err: ++ return NULL; ++} ++ ++void msm_bus_of_get_nfab(struct platform_device *pdev, ++ struct msm_bus_fabric_registration *pdata) ++{ ++ struct device_node *of_node; ++ int ret, nfab = 0; ++ ++ if (!pdev) { ++ pr_err("Error: Null platform device\n"); ++ return; ++ } ++ ++ of_node = pdev->dev.of_node; ++ ret = of_property_read_u32(of_node, "qcom,nfab", ++ &nfab); ++ if (!ret) ++ pr_debug("Fab_of: Read number of buses: %u\n", nfab); ++ ++ msm_bus_board_set_nfab(pdata, nfab); ++} ++ ++struct msm_bus_fabric_registration ++ *msm_bus_of_get_fab_data(struct platform_device *pdev) ++{ ++ struct device_node *of_node; ++ struct msm_bus_fabric_registration *pdata; ++ bool mem_err = false; ++ int ret = 0; ++ const char *sel_str; ++ u32 temp; ++ ++ if (!pdev) { ++ pr_err("Error: Null platform device\n"); ++ return NULL; ++ } ++ ++ of_node = pdev->dev.of_node; ++ pdata = devm_kzalloc(&pdev->dev, ++ sizeof(struct msm_bus_fabric_registration), GFP_KERNEL); ++ if (!pdata) { ++ pr_err("Error: Memory allocation for pdata failed\n"); ++ mem_err = true; ++ goto err; ++ } ++ ++ ret = of_property_read_string(of_node, "label", &pdata->name); ++ if (ret) { ++ pr_err("Error: label not found\n"); ++ goto err; ++ } ++ pr_debug("Fab_of: Read name: %s\n", pdata->name); ++ ++ ret = of_property_read_u32(of_node, "cell-id", ++ &pdata->id); ++ if (ret) { ++ pr_err("Error: num-usecases not found\n"); ++ goto err; ++ } ++ pr_debug("Fab_of: Read id: %u\n", pdata->id); ++ ++ if (of_property_read_bool(of_node, "qcom,ahb")) ++ pdata->ahb = 1; ++ ++ ret = of_property_read_string(of_node, "qcom,fabclk-dual", ++ &pdata->fabclk[DUAL_CTX]); ++ if (ret) { ++ pr_debug("fabclk_dual not available\n"); ++ pdata->fabclk[DUAL_CTX] = NULL; ++ } else ++ pr_debug("Fab_of: Read clk dual ctx: %s\n", ++ pdata->fabclk[DUAL_CTX]); ++ ret = of_property_read_string(of_node, "qcom,fabclk-active", ++ &pdata->fabclk[ACTIVE_CTX]); ++ if (ret) { ++ pr_debug("Error: fabclk_active not available\n"); ++ pdata->fabclk[ACTIVE_CTX] = NULL; ++ } else ++ pr_debug("Fab_of: Read clk act ctx: %s\n", ++ pdata->fabclk[ACTIVE_CTX]); ++ ++ ret = of_property_read_u32(of_node, "qcom,ntieredslaves", ++ &pdata->ntieredslaves); ++ if (ret) { ++ pr_err("Error: ntieredslaves not found\n"); ++ goto err; ++ } ++ ++ ret = of_property_read_u32(of_node, "qcom,qos-freq", &pdata->qos_freq); ++ if (ret) ++ pr_debug("qos_freq not available\n"); ++ ++ ret = of_property_read_string(of_node, "qcom,hw-sel", &sel_str); ++ if (ret) { ++ pr_err("Error: hw_sel not found\n"); ++ goto err; ++ } else { ++ ret = get_num(hw_sel_name, sel_str); ++ if (ret < 0) ++ goto err; ++ ++ pdata->hw_sel = ret; ++ } ++ ++ if (of_property_read_bool(of_node, "qcom,virt")) ++ pdata->virt = true; ++ ++ ret = of_property_read_u32(of_node, "qcom,qos-baseoffset", ++ &pdata->qos_baseoffset); ++ if (ret) ++ pr_debug("%s:qos_baseoffset not available\n", __func__); ++ ++ ret = of_property_read_u32(of_node, "qcom,qos-delta", ++ &pdata->qos_delta); ++ if (ret) ++ pr_debug("%s:qos_delta not available\n", __func__); ++ ++ if (of_property_read_bool(of_node, "qcom,rpm-en")) ++ pdata->rpm_enabled = 1; ++ ++ ret = of_property_read_u32(of_node, "qcom,nr-lim-thresh", ++ &temp); ++ ++ if (ret) { ++ pr_err("nr-lim threshold not specified"); ++ pdata->nr_lim_thresh = 0; ++ } else { ++ pdata->nr_lim_thresh = KBTOB(temp); ++ } ++ ++ ret = of_property_read_u32(of_node, "qcom,eff-fact", ++ &pdata->eff_fact); ++ if (ret) { ++ pr_err("Fab eff-factor not present"); ++ pdata->eff_fact = 0; ++ } ++ ++ pdata->info = get_nodes(of_node, pdev, pdata); ++ return pdata; ++err: ++ return NULL; ++} ++EXPORT_SYMBOL(msm_bus_of_get_fab_data); +--- /dev/null ++++ b/drivers/bus/msm_bus/msm_bus_of_adhoc.c +@@ -0,0 +1,641 @@ ++/* Copyright (c) 2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "msm-bus.h" ++#include "msm-bus-board.h" ++#include "msm_bus_rules.h" ++#include "msm_bus_core.h" ++#include "msm_bus_adhoc.h" ++ ++#define DEFAULT_QOS_FREQ 19200 ++#define DEFAULT_UTIL_FACT 100 ++#define DEFAULT_VRAIL_COMP 100 ++ ++static int get_qos_mode(struct platform_device *pdev, ++ struct device_node *node, const char *qos_mode) ++{ ++ const char *qos_names[] = {"fixed", "limiter", "bypass", "regulator"}; ++ int i = 0; ++ int ret = -1; ++ ++ if (!qos_mode) ++ goto exit_get_qos_mode; ++ ++ for (i = 0; i < ARRAY_SIZE(qos_names); i++) { ++ if (!strcmp(qos_mode, qos_names[i])) ++ break; ++ } ++ if (i == ARRAY_SIZE(qos_names)) ++ dev_err(&pdev->dev, "Cannot match mode qos %s using Bypass", ++ qos_mode); ++ else ++ ret = i; ++ ++exit_get_qos_mode: ++ return ret; ++} ++ ++static int *get_arr(struct platform_device *pdev, ++ struct device_node *node, const char *prop, ++ int *nports) ++{ ++ int size = 0, ret; ++ int *arr = NULL; ++ ++ if (of_get_property(node, prop, &size)) { ++ *nports = size / sizeof(int); ++ } else { ++ dev_dbg(&pdev->dev, "Property %s not available\n", prop); ++ *nports = 0; ++ return NULL; ++ } ++ ++ arr = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); ++ if ((size > 0) && ZERO_OR_NULL_PTR(arr)) { ++ dev_err(&pdev->dev, "Error: Failed to alloc mem for %s\n", ++ prop); ++ return NULL; ++ } ++ ++ ret = of_property_read_u32_array(node, prop, (u32 *)arr, *nports); ++ if (ret) { ++ dev_err(&pdev->dev, "Error in reading property: %s\n", prop); ++ goto arr_err; ++ } ++ ++ return arr; ++arr_err: ++ devm_kfree(&pdev->dev, arr); ++ return NULL; ++} ++ ++static struct msm_bus_fab_device_type *get_fab_device_info( ++ struct device_node *dev_node, ++ struct platform_device *pdev) ++{ ++ struct msm_bus_fab_device_type *fab_dev; ++ unsigned int ret; ++ struct resource *res; ++ const char *base_name; ++ ++ fab_dev = devm_kzalloc(&pdev->dev, ++ sizeof(struct msm_bus_fab_device_type), ++ GFP_KERNEL); ++ if (!fab_dev) { ++ dev_err(&pdev->dev, ++ "Error: Unable to allocate memory for fab_dev\n"); ++ return NULL; ++ } ++ ++ ret = of_property_read_string(dev_node, "qcom,base-name", &base_name); ++ if (ret) { ++ dev_err(&pdev->dev, "Error: Unable to get base address name\n"); ++ goto fab_dev_err; ++ } ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, base_name); ++ if (!res) { ++ dev_err(&pdev->dev, "Error getting qos base addr %s\n", ++ base_name); ++ goto fab_dev_err; ++ } ++ fab_dev->pqos_base = res->start; ++ fab_dev->qos_range = resource_size(res); ++ fab_dev->bypass_qos_prg = of_property_read_bool(dev_node, ++ "qcom,bypass-qos-prg"); ++ ++ ret = of_property_read_u32(dev_node, "qcom,base-offset", ++ &fab_dev->base_offset); ++ if (ret) ++ dev_dbg(&pdev->dev, "Bus base offset is missing\n"); ++ ++ ret = of_property_read_u32(dev_node, "qcom,qos-off", ++ &fab_dev->qos_off); ++ if (ret) ++ dev_dbg(&pdev->dev, "Bus qos off is missing\n"); ++ ++ ++ ret = of_property_read_u32(dev_node, "qcom,bus-type", ++ &fab_dev->bus_type); ++ if (ret) { ++ dev_warn(&pdev->dev, "Bus type is missing\n"); ++ goto fab_dev_err; ++ } ++ ++ ret = of_property_read_u32(dev_node, "qcom,qos-freq", ++ &fab_dev->qos_freq); ++ if (ret) { ++ dev_dbg(&pdev->dev, "Bus qos freq is missing\n"); ++ fab_dev->qos_freq = DEFAULT_QOS_FREQ; ++ } ++ ++ ret = of_property_read_u32(dev_node, "qcom,util-fact", ++ &fab_dev->util_fact); ++ if (ret) { ++ dev_info(&pdev->dev, "Util-fact is missing, default to %d\n", ++ DEFAULT_UTIL_FACT); ++ fab_dev->util_fact = DEFAULT_UTIL_FACT; ++ } ++ ++ ret = of_property_read_u32(dev_node, "qcom,vrail-comp", ++ &fab_dev->vrail_comp); ++ if (ret) { ++ dev_info(&pdev->dev, "Vrail-comp is missing, default to %d\n", ++ DEFAULT_VRAIL_COMP); ++ fab_dev->vrail_comp = DEFAULT_VRAIL_COMP; ++ } ++ ++ return fab_dev; ++ ++fab_dev_err: ++ devm_kfree(&pdev->dev, fab_dev); ++ fab_dev = 0; ++ return NULL; ++} ++ ++static void get_qos_params( ++ struct device_node * const dev_node, ++ struct platform_device * const pdev, ++ struct msm_bus_node_info_type *node_info) ++{ ++ const char *qos_mode = NULL; ++ unsigned int ret; ++ unsigned int temp; ++ ++ ret = of_property_read_string(dev_node, "qcom,qos-mode", &qos_mode); ++ ++ if (ret) ++ node_info->qos_params.mode = -1; ++ else ++ node_info->qos_params.mode = get_qos_mode(pdev, dev_node, ++ qos_mode); ++ ++ of_property_read_u32(dev_node, "qcom,prio-lvl", ++ &node_info->qos_params.prio_lvl); ++ ++ of_property_read_u32(dev_node, "qcom,prio1", ++ &node_info->qos_params.prio1); ++ ++ of_property_read_u32(dev_node, "qcom,prio0", ++ &node_info->qos_params.prio0); ++ ++ of_property_read_u32(dev_node, "qcom,prio-rd", ++ &node_info->qos_params.prio_rd); ++ ++ of_property_read_u32(dev_node, "qcom,prio-wr", ++ &node_info->qos_params.prio_wr); ++ ++ of_property_read_u32(dev_node, "qcom,gp", ++ &node_info->qos_params.gp); ++ ++ of_property_read_u32(dev_node, "qcom,thmp", ++ &node_info->qos_params.thmp); ++ ++ of_property_read_u32(dev_node, "qcom,ws", ++ &node_info->qos_params.ws); ++ ++ ret = of_property_read_u32(dev_node, "qcom,bw_buffer", &temp); ++ ++ if (ret) ++ node_info->qos_params.bw_buffer = 0; ++ else ++ node_info->qos_params.bw_buffer = KBTOB(temp); ++ ++} ++ ++ ++static struct msm_bus_node_info_type *get_node_info_data( ++ struct device_node * const dev_node, ++ struct platform_device * const pdev) ++{ ++ struct msm_bus_node_info_type *node_info; ++ unsigned int ret; ++ int size; ++ int i; ++ struct device_node *con_node; ++ struct device_node *bus_dev; ++ ++ node_info = devm_kzalloc(&pdev->dev, ++ sizeof(struct msm_bus_node_info_type), ++ GFP_KERNEL); ++ if (!node_info) { ++ dev_err(&pdev->dev, ++ "Error: Unable to allocate memory for node_info\n"); ++ return NULL; ++ } ++ ++ ret = of_property_read_u32(dev_node, "cell-id", &node_info->id); ++ if (ret) { ++ dev_warn(&pdev->dev, "Bus node is missing cell-id\n"); ++ goto node_info_err; ++ } ++ ret = of_property_read_string(dev_node, "label", &node_info->name); ++ if (ret) { ++ dev_warn(&pdev->dev, "Bus node is missing name\n"); ++ goto node_info_err; ++ } ++ node_info->qport = get_arr(pdev, dev_node, "qcom,qport", ++ &node_info->num_qports); ++ ++ if (of_get_property(dev_node, "qcom,connections", &size)) { ++ node_info->num_connections = size / sizeof(int); ++ node_info->connections = devm_kzalloc(&pdev->dev, size, ++ GFP_KERNEL); ++ } else { ++ node_info->num_connections = 0; ++ node_info->connections = 0; ++ } ++ ++ for (i = 0; i < node_info->num_connections; i++) { ++ con_node = of_parse_phandle(dev_node, "qcom,connections", i); ++ if (IS_ERR_OR_NULL(con_node)) ++ goto node_info_err; ++ ++ if (of_property_read_u32(con_node, "cell-id", ++ &node_info->connections[i])) ++ goto node_info_err; ++ of_node_put(con_node); ++ } ++ ++ if (of_get_property(dev_node, "qcom,blacklist", &size)) { ++ node_info->num_blist = size/sizeof(u32); ++ node_info->black_listed_connections = devm_kzalloc(&pdev->dev, ++ size, GFP_KERNEL); ++ } else { ++ node_info->num_blist = 0; ++ node_info->black_listed_connections = 0; ++ } ++ ++ for (i = 0; i < node_info->num_blist; i++) { ++ con_node = of_parse_phandle(dev_node, "qcom,blacklist", i); ++ if (IS_ERR_OR_NULL(con_node)) ++ goto node_info_err; ++ ++ if (of_property_read_u32(con_node, "cell-id", ++ &node_info->black_listed_connections[i])) ++ goto node_info_err; ++ of_node_put(con_node); ++ } ++ ++ bus_dev = of_parse_phandle(dev_node, "qcom,bus-dev", 0); ++ if (!IS_ERR_OR_NULL(bus_dev)) { ++ if (of_property_read_u32(bus_dev, "cell-id", ++ &node_info->bus_device_id)) { ++ dev_err(&pdev->dev, "Can't find bus device. Node %d", ++ node_info->id); ++ goto node_info_err; ++ } ++ ++ of_node_put(bus_dev); ++ } else ++ dev_dbg(&pdev->dev, "Can't find bdev phandle for %d", ++ node_info->id); ++ ++ node_info->is_fab_dev = of_property_read_bool(dev_node, "qcom,fab-dev"); ++ node_info->virt_dev = of_property_read_bool(dev_node, "qcom,virt-dev"); ++ ++ ret = of_property_read_u32(dev_node, "qcom,buswidth", ++ &node_info->buswidth); ++ if (ret) { ++ dev_dbg(&pdev->dev, "Using default 8 bytes %d", node_info->id); ++ node_info->buswidth = 8; ++ } ++ ++ ret = of_property_read_u32(dev_node, "qcom,mas-rpm-id", ++ &node_info->mas_rpm_id); ++ if (ret) { ++ dev_dbg(&pdev->dev, "mas rpm id is missing\n"); ++ node_info->mas_rpm_id = -1; ++ } ++ ++ ret = of_property_read_u32(dev_node, "qcom,slv-rpm-id", ++ &node_info->slv_rpm_id); ++ if (ret) { ++ dev_dbg(&pdev->dev, "slv rpm id is missing\n"); ++ node_info->slv_rpm_id = -1; ++ } ++ ret = of_property_read_u32(dev_node, "qcom,util-fact", ++ &node_info->util_fact); ++ if (ret) ++ node_info->util_fact = 0; ++ ret = of_property_read_u32(dev_node, "qcom,vrail-comp", ++ &node_info->vrail_comp); ++ if (ret) ++ node_info->vrail_comp = 0; ++ get_qos_params(dev_node, pdev, node_info); ++ ++ return node_info; ++ ++node_info_err: ++ devm_kfree(&pdev->dev, node_info); ++ node_info = 0; ++ return NULL; ++} ++ ++static unsigned int get_bus_node_device_data( ++ struct device_node * const dev_node, ++ struct platform_device * const pdev, ++ struct msm_bus_node_device_type * const node_device) ++{ ++ node_device->node_info = get_node_info_data(dev_node, pdev); ++ if (IS_ERR_OR_NULL(node_device->node_info)) { ++ dev_err(&pdev->dev, "Error: Node info missing\n"); ++ return -ENODATA; ++ } ++ node_device->ap_owned = of_property_read_bool(dev_node, ++ "qcom,ap-owned"); ++ ++ if (node_device->node_info->is_fab_dev) { ++ dev_dbg(&pdev->dev, "Dev %d\n", node_device->node_info->id); ++ ++ if (!node_device->node_info->virt_dev) { ++ node_device->fabdev = ++ get_fab_device_info(dev_node, pdev); ++ if (IS_ERR_OR_NULL(node_device->fabdev)) { ++ dev_err(&pdev->dev, ++ "Error: Fabric device info missing\n"); ++ devm_kfree(&pdev->dev, node_device->node_info); ++ return -ENODATA; ++ } ++ } ++ node_device->clk[DUAL_CTX].clk = of_clk_get_by_name(dev_node, ++ "bus_clk"); ++ ++ if (IS_ERR_OR_NULL(node_device->clk[DUAL_CTX].clk)) ++ dev_dbg(&pdev->dev, ++ "%s:Failed to get bus clk for bus%d ctx%d", ++ __func__, node_device->node_info->id, ++ DUAL_CTX); ++ ++ node_device->clk[ACTIVE_CTX].clk = of_clk_get_by_name(dev_node, ++ "bus_a_clk"); ++ if (IS_ERR_OR_NULL(node_device->clk[ACTIVE_CTX].clk)) ++ dev_err(&pdev->dev, ++ "Failed to get bus clk for bus%d ctx%d", ++ node_device->node_info->id, ACTIVE_CTX); ++ if (msmbus_coresight_init_adhoc(pdev, dev_node)) ++ dev_warn(&pdev->dev, ++ "Coresight support absent for bus: %d\n", ++ node_device->node_info->id); ++ } else { ++ node_device->qos_clk.clk = of_clk_get_by_name(dev_node, ++ "bus_qos_clk"); ++ ++ if (IS_ERR_OR_NULL(node_device->qos_clk.clk)) ++ dev_dbg(&pdev->dev, ++ "%s:Failed to get bus qos clk for mas%d", ++ __func__, node_device->node_info->id); ++ ++ node_device->clk[DUAL_CTX].clk = of_clk_get_by_name(dev_node, ++ "node_clk"); ++ ++ if (IS_ERR_OR_NULL(node_device->clk[DUAL_CTX].clk)) ++ dev_dbg(&pdev->dev, ++ "%s:Failed to get bus clk for bus%d ctx%d", ++ __func__, node_device->node_info->id, ++ DUAL_CTX); ++ ++ } ++ return 0; ++} ++ ++struct msm_bus_device_node_registration ++ *msm_bus_of_to_pdata(struct platform_device *pdev) ++{ ++ struct device_node *of_node, *child_node; ++ struct msm_bus_device_node_registration *pdata; ++ unsigned int i = 0, j; ++ unsigned int ret; ++ ++ if (!pdev) { ++ pr_err("Error: Null platform device\n"); ++ return NULL; ++ } ++ ++ of_node = pdev->dev.of_node; ++ ++ pdata = devm_kzalloc(&pdev->dev, ++ sizeof(struct msm_bus_device_node_registration), ++ GFP_KERNEL); ++ if (!pdata) { ++ dev_err(&pdev->dev, ++ "Error: Memory allocation for pdata failed\n"); ++ return NULL; ++ } ++ ++ pdata->num_devices = of_get_child_count(of_node); ++ ++ pdata->info = devm_kzalloc(&pdev->dev, ++ sizeof(struct msm_bus_node_device_type) * ++ pdata->num_devices, GFP_KERNEL); ++ ++ if (!pdata->info) { ++ dev_err(&pdev->dev, ++ "Error: Memory allocation for pdata->info failed\n"); ++ goto node_reg_err; ++ } ++ ++ ret = 0; ++ for_each_child_of_node(of_node, child_node) { ++ ret = get_bus_node_device_data(child_node, pdev, ++ &pdata->info[i]); ++ if (ret) { ++ dev_err(&pdev->dev, "Error: unable to initialize bus nodes\n"); ++ goto node_reg_err_1; ++ } ++ i++; ++ } ++ ++ dev_dbg(&pdev->dev, "bus topology:\n"); ++ for (i = 0; i < pdata->num_devices; i++) { ++ dev_dbg(&pdev->dev, "id %d\nnum_qports %d\nnum_connections %d", ++ pdata->info[i].node_info->id, ++ pdata->info[i].node_info->num_qports, ++ pdata->info[i].node_info->num_connections); ++ dev_dbg(&pdev->dev, "\nbus_device_id %d\n buswidth %d\n", ++ pdata->info[i].node_info->bus_device_id, ++ pdata->info[i].node_info->buswidth); ++ for (j = 0; j < pdata->info[i].node_info->num_connections; ++ j++) { ++ dev_dbg(&pdev->dev, "connection[%d]: %d\n", j, ++ pdata->info[i].node_info->connections[j]); ++ } ++ for (j = 0; j < pdata->info[i].node_info->num_blist; ++ j++) { ++ dev_dbg(&pdev->dev, "black_listed_node[%d]: %d\n", j, ++ pdata->info[i].node_info-> ++ black_listed_connections[j]); ++ } ++ if (pdata->info[i].fabdev) ++ dev_dbg(&pdev->dev, "base_addr %zu\nbus_type %d\n", ++ (size_t)pdata->info[i]. ++ fabdev->pqos_base, ++ pdata->info[i].fabdev->bus_type); ++ } ++ return pdata; ++ ++node_reg_err_1: ++ devm_kfree(&pdev->dev, pdata->info); ++node_reg_err: ++ devm_kfree(&pdev->dev, pdata); ++ pdata = NULL; ++ return NULL; ++} ++ ++static int msm_bus_of_get_ids(struct platform_device *pdev, ++ struct device_node *dev_node, int **dev_ids, ++ int *num_ids, char *prop_name) ++{ ++ int ret = 0; ++ int size, i; ++ struct device_node *rule_node; ++ int *ids = NULL; ++ ++ if (of_get_property(dev_node, prop_name, &size)) { ++ *num_ids = size / sizeof(int); ++ ids = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); ++ } else { ++ dev_err(&pdev->dev, "No rule nodes, skipping node"); ++ ret = -ENXIO; ++ goto exit_get_ids; ++ } ++ ++ *dev_ids = ids; ++ for (i = 0; i < *num_ids; i++) { ++ rule_node = of_parse_phandle(dev_node, prop_name, i); ++ if (IS_ERR_OR_NULL(rule_node)) { ++ dev_err(&pdev->dev, "Can't get rule node id"); ++ ret = -ENXIO; ++ goto err_get_ids; ++ } ++ ++ if (of_property_read_u32(rule_node, "cell-id", ++ &ids[i])) { ++ dev_err(&pdev->dev, "Can't get rule node id"); ++ ret = -ENXIO; ++ goto err_get_ids; ++ } ++ of_node_put(rule_node); ++ } ++exit_get_ids: ++ return ret; ++err_get_ids: ++ devm_kfree(&pdev->dev, ids); ++ of_node_put(rule_node); ++ ids = NULL; ++ return ret; ++} ++ ++int msm_bus_of_get_static_rules(struct platform_device *pdev, ++ struct bus_rule_type **static_rules) ++{ ++ int ret = 0; ++ struct device_node *of_node, *child_node; ++ int num_rules = 0; ++ int rule_idx = 0; ++ int bw_fld = 0; ++ int i; ++ struct bus_rule_type *static_rule = NULL; ++ ++ of_node = pdev->dev.of_node; ++ num_rules = of_get_child_count(of_node); ++ static_rule = devm_kzalloc(&pdev->dev, ++ sizeof(struct bus_rule_type) * num_rules, ++ GFP_KERNEL); ++ ++ if (IS_ERR_OR_NULL(static_rule)) { ++ ret = -ENOMEM; ++ goto exit_static_rules; ++ } ++ ++ *static_rules = static_rule; ++ for_each_child_of_node(of_node, child_node) { ++ ret = msm_bus_of_get_ids(pdev, child_node, ++ &static_rule[rule_idx].src_id, ++ &static_rule[rule_idx].num_src, ++ "qcom,src-nodes"); ++ ++ ret = msm_bus_of_get_ids(pdev, child_node, ++ &static_rule[rule_idx].dst_node, ++ &static_rule[rule_idx].num_dst, ++ "qcom,dest-node"); ++ ++ ret = of_property_read_u32(child_node, "qcom,src-field", ++ &static_rule[rule_idx].src_field); ++ if (ret) { ++ dev_err(&pdev->dev, "src-field missing"); ++ ret = -ENXIO; ++ goto err_static_rules; ++ } ++ ++ ret = of_property_read_u32(child_node, "qcom,src-op", ++ &static_rule[rule_idx].op); ++ if (ret) { ++ dev_err(&pdev->dev, "src-op missing"); ++ ret = -ENXIO; ++ goto err_static_rules; ++ } ++ ++ ret = of_property_read_u32(child_node, "qcom,mode", ++ &static_rule[rule_idx].mode); ++ if (ret) { ++ dev_err(&pdev->dev, "mode missing"); ++ ret = -ENXIO; ++ goto err_static_rules; ++ } ++ ++ ret = of_property_read_u32(child_node, "qcom,thresh", &bw_fld); ++ if (ret) { ++ dev_err(&pdev->dev, "thresh missing"); ++ ret = -ENXIO; ++ goto err_static_rules; ++ } else ++ static_rule[rule_idx].thresh = KBTOB(bw_fld); ++ ++ ret = of_property_read_u32(child_node, "qcom,dest-bw", ++ &bw_fld); ++ if (ret) ++ static_rule[rule_idx].dst_bw = 0; ++ else ++ static_rule[rule_idx].dst_bw = KBTOB(bw_fld); ++ ++ rule_idx++; ++ } ++ ret = rule_idx; ++exit_static_rules: ++ return ret; ++err_static_rules: ++ for (i = 0; i < num_rules; i++) { ++ if (!IS_ERR_OR_NULL(static_rule)) { ++ if (!IS_ERR_OR_NULL(static_rule[i].src_id)) ++ devm_kfree(&pdev->dev, ++ static_rule[i].src_id); ++ if (!IS_ERR_OR_NULL(static_rule[i].dst_node)) ++ devm_kfree(&pdev->dev, ++ static_rule[i].dst_node); ++ devm_kfree(&pdev->dev, static_rule); ++ } ++ } ++ devm_kfree(&pdev->dev, *static_rules); ++ static_rules = NULL; ++ return ret; ++} +--- /dev/null ++++ b/drivers/bus/msm_bus/msm_bus_rules.c +@@ -0,0 +1,624 @@ ++/* Copyright (c) 2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include "msm-bus-board.h" ++#include "msm_bus_rules.h" ++#include ++ ++struct node_vote_info { ++ int id; ++ u64 ib; ++ u64 ab; ++ u64 clk; ++}; ++ ++struct rules_def { ++ int rule_id; ++ int num_src; ++ int state; ++ struct node_vote_info *src_info; ++ struct bus_rule_type rule_ops; ++ bool state_change; ++ struct list_head link; ++}; ++ ++struct rule_node_info { ++ int id; ++ void *data; ++ struct raw_notifier_head rule_notify_list; ++ int cur_rule; ++ int num_rules; ++ struct list_head node_rules; ++ struct list_head link; ++ struct rule_apply_rcm_info apply; ++}; ++ ++DEFINE_MUTEX(msm_bus_rules_lock); ++static LIST_HEAD(node_list); ++static struct rule_node_info *get_node(u32 id, void *data); ++ ++#define LE(op1, op2) (op1 <= op2) ++#define LT(op1, op2) (op1 < op2) ++#define GE(op1, op2) (op1 >= op2) ++#define GT(op1, op2) (op1 > op2) ++#define NB_ID (0x201) ++ ++static struct rule_node_info *get_node(u32 id, void *data) ++{ ++ struct rule_node_info *node_it = NULL; ++ struct rule_node_info *node_match = NULL; ++ ++ list_for_each_entry(node_it, &node_list, link) { ++ if (node_it->id == id) { ++ if ((id == NB_ID)) { ++ if ((node_it->data == data)) { ++ node_match = node_it; ++ break; ++ } ++ } else { ++ node_match = node_it; ++ break; ++ } ++ } ++ } ++ return node_match; ++} ++ ++static struct rule_node_info *gen_node(u32 id, void *data) ++{ ++ struct rule_node_info *node_it = NULL; ++ struct rule_node_info *node_match = NULL; ++ ++ list_for_each_entry(node_it, &node_list, link) { ++ if (node_it->id == id) { ++ node_match = node_it; ++ break; ++ } ++ } ++ ++ if (!node_match) { ++ node_match = kzalloc(sizeof(struct rule_node_info), GFP_KERNEL); ++ if (!node_match) { ++ pr_err("%s: Cannot allocate memory", __func__); ++ goto exit_node_match; ++ } ++ ++ node_match->id = id; ++ node_match->cur_rule = -1; ++ node_match->num_rules = 0; ++ node_match->data = data; ++ list_add_tail(&node_match->link, &node_list); ++ INIT_LIST_HEAD(&node_match->node_rules); ++ RAW_INIT_NOTIFIER_HEAD(&node_match->rule_notify_list); ++ pr_debug("Added new node %d to list\n", id); ++ } ++exit_node_match: ++ return node_match; ++} ++ ++static bool do_compare_op(u64 op1, u64 op2, int op) ++{ ++ bool ret = false; ++ ++ switch (op) { ++ case OP_LE: ++ ret = LE(op1, op2); ++ break; ++ case OP_LT: ++ ret = LT(op1, op2); ++ break; ++ case OP_GT: ++ ret = GT(op1, op2); ++ break; ++ case OP_GE: ++ ret = GE(op1, op2); ++ break; ++ case OP_NOOP: ++ ret = true; ++ break; ++ default: ++ pr_info("Invalid OP %d", op); ++ break; ++ } ++ return ret; ++} ++ ++static void update_src_id_vote(struct rule_update_path_info *inp_node, ++ struct rule_node_info *rule_node) ++{ ++ struct rules_def *rule; ++ int i; ++ ++ list_for_each_entry(rule, &rule_node->node_rules, link) { ++ for (i = 0; i < rule->num_src; i++) { ++ if (rule->src_info[i].id == inp_node->id) { ++ rule->src_info[i].ib = inp_node->ib; ++ rule->src_info[i].ab = inp_node->ab; ++ rule->src_info[i].clk = inp_node->clk; ++ } ++ } ++ } ++} ++ ++static u64 get_field(struct rules_def *rule, int src_id) ++{ ++ u64 field = 0; ++ int i; ++ ++ for (i = 0; i < rule->num_src; i++) { ++ switch (rule->rule_ops.src_field) { ++ case FLD_IB: ++ field += rule->src_info[i].ib; ++ break; ++ case FLD_AB: ++ field += rule->src_info[i].ab; ++ break; ++ case FLD_CLK: ++ field += rule->src_info[i].clk; ++ break; ++ } ++ } ++ ++ return field; ++} ++ ++static bool check_rule(struct rules_def *rule, ++ struct rule_update_path_info *inp) ++{ ++ bool ret = false; ++ ++ if (!rule) ++ return ret; ++ ++ switch (rule->rule_ops.op) { ++ case OP_LE: ++ case OP_LT: ++ case OP_GT: ++ case OP_GE: ++ { ++ u64 src_field = get_field(rule, inp->id); ++ if (!src_field) ++ ret = false; ++ else ++ ret = do_compare_op(src_field, rule->rule_ops.thresh, ++ rule->rule_ops.op); ++ break; ++ } ++ default: ++ pr_err("Unsupported op %d", rule->rule_ops.op); ++ break; ++ } ++ return ret; ++} ++ ++static void match_rule(struct rule_update_path_info *inp_node, ++ struct rule_node_info *node) ++{ ++ struct rules_def *rule; ++ int i; ++ ++ list_for_each_entry(rule, &node->node_rules, link) { ++ for (i = 0; i < rule->num_src; i++) { ++ if (rule->src_info[i].id == inp_node->id) { ++ if (check_rule(rule, inp_node)) { ++ trace_bus_rules_matches(node->cur_rule, ++ inp_node->id, inp_node->ab, ++ inp_node->ib, inp_node->clk); ++ if (rule->state == ++ RULE_STATE_NOT_APPLIED) ++ rule->state_change = true; ++ rule->state = RULE_STATE_APPLIED; ++ } else { ++ if (rule->state == ++ RULE_STATE_APPLIED) ++ rule->state_change = true; ++ rule->state = RULE_STATE_NOT_APPLIED; ++ } ++ } ++ } ++ } ++} ++ ++static void apply_rule(struct rule_node_info *node, ++ struct list_head *output_list) ++{ ++ struct rules_def *rule; ++ ++ node->cur_rule = -1; ++ list_for_each_entry(rule, &node->node_rules, link) { ++ if ((rule->state == RULE_STATE_APPLIED) && ++ (node->cur_rule == -1)) ++ node->cur_rule = rule->rule_id; ++ ++ if (node->id == NB_ID) { ++ if (rule->state_change) { ++ rule->state_change = false; ++ raw_notifier_call_chain(&node->rule_notify_list, ++ rule->state, (void *)&rule->rule_ops); ++ } ++ } else { ++ if ((rule->state == RULE_STATE_APPLIED) && ++ (node->cur_rule == rule->rule_id)) { ++ node->apply.id = rule->rule_ops.dst_node[0]; ++ node->apply.throttle = rule->rule_ops.mode; ++ node->apply.lim_bw = rule->rule_ops.dst_bw; ++ list_add_tail(&node->apply.link, output_list); ++ } ++ rule->state_change = false; ++ } ++ } ++ ++} ++ ++int msm_rules_update_path(struct list_head *input_list, ++ struct list_head *output_list) ++{ ++ int ret = 0; ++ struct rule_update_path_info *inp_node; ++ struct rule_node_info *node_it = NULL; ++ ++ mutex_lock(&msm_bus_rules_lock); ++ list_for_each_entry(inp_node, input_list, link) { ++ list_for_each_entry(node_it, &node_list, link) { ++ update_src_id_vote(inp_node, node_it); ++ match_rule(inp_node, node_it); ++ } ++ } ++ ++ list_for_each_entry(node_it, &node_list, link) ++ apply_rule(node_it, output_list); ++ ++ mutex_unlock(&msm_bus_rules_lock); ++ return ret; ++} ++ ++static bool ops_equal(int op1, int op2) ++{ ++ bool ret = false; ++ ++ switch (op1) { ++ case OP_GT: ++ case OP_GE: ++ case OP_LT: ++ case OP_LE: ++ if (abs(op1 - op2) <= 1) ++ ret = true; ++ break; ++ default: ++ ret = (op1 == op2); ++ } ++ ++ return ret; ++} ++ ++static int node_rules_compare(void *priv, struct list_head *a, ++ struct list_head *b) ++{ ++ struct rules_def *ra = container_of(a, struct rules_def, link); ++ struct rules_def *rb = container_of(b, struct rules_def, link); ++ int ret = -1; ++ int64_t th_diff = 0; ++ ++ ++ if (ra->rule_ops.mode == rb->rule_ops.mode) { ++ if (ops_equal(ra->rule_ops.op, rb->rule_ops.op)) { ++ if ((ra->rule_ops.op == OP_LT) || ++ (ra->rule_ops.op == OP_LE)) { ++ th_diff = ra->rule_ops.thresh - ++ rb->rule_ops.thresh; ++ if (th_diff > 0) ++ ret = 1; ++ else ++ ret = -1; ++ } else if ((ra->rule_ops.op == OP_GT) || ++ (ra->rule_ops.op == OP_GE)) { ++ th_diff = rb->rule_ops.thresh - ++ ra->rule_ops.thresh; ++ if (th_diff > 0) ++ ret = 1; ++ else ++ ret = -1; ++ } ++ } else ++ ret = ra->rule_ops.op - rb->rule_ops.op; ++ } else if ((ra->rule_ops.mode == THROTTLE_OFF) && ++ (rb->rule_ops.mode == THROTTLE_ON)) { ++ ret = 1; ++ } else if ((ra->rule_ops.mode == THROTTLE_ON) && ++ (rb->rule_ops.mode == THROTTLE_OFF)) { ++ ret = -1; ++ } ++ ++ return ret; ++} ++ ++static void print_rules(struct rule_node_info *node_it) ++{ ++ struct rules_def *node_rule = NULL; ++ int i; ++ ++ if (!node_it) { ++ pr_err("%s: no node for found", __func__); ++ return; ++ } ++ ++ pr_info("\n Now printing rules for Node %d cur rule %d\n", ++ node_it->id, node_it->cur_rule); ++ list_for_each_entry(node_rule, &node_it->node_rules, link) { ++ pr_info("\n num Rules %d rule Id %d\n", ++ node_it->num_rules, node_rule->rule_id); ++ pr_info("Rule: src_field %d\n", node_rule->rule_ops.src_field); ++ for (i = 0; i < node_rule->rule_ops.num_src; i++) ++ pr_info("Rule: src %d\n", ++ node_rule->rule_ops.src_id[i]); ++ for (i = 0; i < node_rule->rule_ops.num_dst; i++) ++ pr_info("Rule: dst %d dst_bw %llu\n", ++ node_rule->rule_ops.dst_node[i], ++ node_rule->rule_ops.dst_bw); ++ pr_info("Rule: thresh %llu op %d mode %d State %d\n", ++ node_rule->rule_ops.thresh, ++ node_rule->rule_ops.op, ++ node_rule->rule_ops.mode, ++ node_rule->state); ++ } ++} ++ ++void print_all_rules(void) ++{ ++ struct rule_node_info *node_it = NULL; ++ ++ list_for_each_entry(node_it, &node_list, link) ++ print_rules(node_it); ++} ++ ++void print_rules_buf(char *buf, int max_buf) ++{ ++ struct rule_node_info *node_it = NULL; ++ struct rules_def *node_rule = NULL; ++ int i; ++ int cnt = 0; ++ ++ list_for_each_entry(node_it, &node_list, link) { ++ cnt += scnprintf(buf + cnt, max_buf - cnt, ++ "\n Now printing rules for Node %d cur_rule %d\n", ++ node_it->id, node_it->cur_rule); ++ list_for_each_entry(node_rule, &node_it->node_rules, link) { ++ cnt += scnprintf(buf + cnt, max_buf - cnt, ++ "\nNum Rules:%d ruleId %d STATE:%d change:%d\n", ++ node_it->num_rules, node_rule->rule_id, ++ node_rule->state, node_rule->state_change); ++ cnt += scnprintf(buf + cnt, max_buf - cnt, ++ "Src_field %d\n", ++ node_rule->rule_ops.src_field); ++ for (i = 0; i < node_rule->rule_ops.num_src; i++) ++ cnt += scnprintf(buf + cnt, max_buf - cnt, ++ "Src %d Cur Ib %llu Ab %llu\n", ++ node_rule->rule_ops.src_id[i], ++ node_rule->src_info[i].ib, ++ node_rule->src_info[i].ab); ++ for (i = 0; i < node_rule->rule_ops.num_dst; i++) ++ cnt += scnprintf(buf + cnt, max_buf - cnt, ++ "Dst %d dst_bw %llu\n", ++ node_rule->rule_ops.dst_node[0], ++ node_rule->rule_ops.dst_bw); ++ cnt += scnprintf(buf + cnt, max_buf - cnt, ++ "Thresh %llu op %d mode %d\n", ++ node_rule->rule_ops.thresh, ++ node_rule->rule_ops.op, ++ node_rule->rule_ops.mode); ++ } ++ } ++} ++ ++static int copy_rule(struct bus_rule_type *src, struct rules_def *node_rule, ++ struct notifier_block *nb) ++{ ++ int i; ++ int ret = 0; ++ ++ memcpy(&node_rule->rule_ops, src, ++ sizeof(struct bus_rule_type)); ++ node_rule->rule_ops.src_id = kzalloc( ++ (sizeof(int) * node_rule->rule_ops.num_src), ++ GFP_KERNEL); ++ if (!node_rule->rule_ops.src_id) { ++ pr_err("%s:Failed to allocate for src_id", ++ __func__); ++ return -ENOMEM; ++ } ++ memcpy(node_rule->rule_ops.src_id, src->src_id, ++ sizeof(int) * src->num_src); ++ ++ ++ if (!nb) { ++ node_rule->rule_ops.dst_node = kzalloc( ++ (sizeof(int) * node_rule->rule_ops.num_dst), ++ GFP_KERNEL); ++ if (!node_rule->rule_ops.dst_node) { ++ pr_err("%s:Failed to allocate for src_id", ++ __func__); ++ return -ENOMEM; ++ } ++ memcpy(node_rule->rule_ops.dst_node, src->dst_node, ++ sizeof(int) * src->num_dst); ++ } ++ ++ node_rule->num_src = src->num_src; ++ node_rule->src_info = kzalloc( ++ (sizeof(struct node_vote_info) * node_rule->rule_ops.num_src), ++ GFP_KERNEL); ++ if (!node_rule->src_info) { ++ pr_err("%s:Failed to allocate for src_id", ++ __func__); ++ return -ENOMEM; ++ } ++ for (i = 0; i < src->num_src; i++) ++ node_rule->src_info[i].id = src->src_id[i]; ++ ++ return ret; ++} ++ ++void msm_rule_register(int num_rules, struct bus_rule_type *rule, ++ struct notifier_block *nb) ++{ ++ struct rule_node_info *node = NULL; ++ int i, j; ++ struct rules_def *node_rule = NULL; ++ int num_dst = 0; ++ ++ if (!rule) ++ return; ++ ++ mutex_lock(&msm_bus_rules_lock); ++ for (i = 0; i < num_rules; i++) { ++ if (nb) ++ num_dst = 1; ++ else ++ num_dst = rule[i].num_dst; ++ ++ for (j = 0; j < num_dst; j++) { ++ int id = 0; ++ ++ if (nb) ++ id = NB_ID; ++ else ++ id = rule[i].dst_node[j]; ++ ++ node = gen_node(id, nb); ++ if (!node) { ++ pr_info("Error getting rule"); ++ goto exit_rule_register; ++ } ++ node_rule = kzalloc(sizeof(struct rules_def), ++ GFP_KERNEL); ++ if (!node_rule) { ++ pr_err("%s: Failed to allocate for rule", ++ __func__); ++ goto exit_rule_register; ++ } ++ ++ if (copy_rule(&rule[i], node_rule, nb)) { ++ pr_err("Error copying rule"); ++ goto exit_rule_register; ++ } ++ ++ node_rule->rule_id = node->num_rules++; ++ if (nb) ++ node->data = nb; ++ ++ list_add_tail(&node_rule->link, &node->node_rules); ++ } ++ } ++ list_sort(NULL, &node->node_rules, node_rules_compare); ++ ++ if (nb) ++ raw_notifier_chain_register(&node->rule_notify_list, nb); ++exit_rule_register: ++ mutex_unlock(&msm_bus_rules_lock); ++ return; ++} ++ ++static int comp_rules(struct bus_rule_type *rulea, struct bus_rule_type *ruleb) ++{ ++ int ret = 1; ++ ++ if (rulea->num_src == ruleb->num_src) ++ ret = memcmp(rulea->src_id, ruleb->src_id, ++ (sizeof(int) * rulea->num_src)); ++ if (!ret && (rulea->num_dst == ruleb->num_dst)) ++ ret = memcmp(rulea->dst_node, ruleb->dst_node, ++ (sizeof(int) * rulea->num_dst)); ++ if (!ret && (rulea->dst_bw == ruleb->dst_bw) && ++ (rulea->op == ruleb->op) && (rulea->thresh == ruleb->thresh)) ++ ret = 0; ++ ++ return ret; ++} ++ ++void msm_rule_unregister(int num_rules, struct bus_rule_type *rule, ++ struct notifier_block *nb) ++{ ++ int i; ++ struct rule_node_info *node = NULL; ++ struct rule_node_info *node_tmp = NULL; ++ struct rules_def *node_rule; ++ struct rules_def *node_rule_tmp; ++ bool match_found = false; ++ ++ if (!rule) ++ return; ++ ++ mutex_lock(&msm_bus_rules_lock); ++ if (nb) { ++ node = get_node(NB_ID, nb); ++ if (!node) { ++ pr_err("%s: Can't find node", __func__); ++ goto exit_unregister_rule; ++ } ++ ++ list_for_each_entry_safe(node_rule, node_rule_tmp, ++ &node->node_rules, link) { ++ list_del(&node_rule->link); ++ kfree(node_rule); ++ node->num_rules--; ++ } ++ raw_notifier_chain_unregister(&node->rule_notify_list, nb); ++ } else { ++ for (i = 0; i < num_rules; i++) { ++ match_found = false; ++ ++ list_for_each_entry(node, &node_list, link) { ++ list_for_each_entry_safe(node_rule, ++ node_rule_tmp, &node->node_rules, link) { ++ if (comp_rules(&node_rule->rule_ops, ++ &rule[i]) == 0) { ++ list_del(&node_rule->link); ++ kfree(node_rule); ++ match_found = true; ++ node->num_rules--; ++ list_sort(NULL, ++ &node->node_rules, ++ node_rules_compare); ++ break; ++ } ++ } ++ } ++ } ++ } ++ ++ list_for_each_entry_safe(node, node_tmp, ++ &node_list, link) { ++ if (!node->num_rules) { ++ pr_debug("Deleting Rule node %d", node->id); ++ list_del(&node->link); ++ kfree(node); ++ } ++ } ++exit_unregister_rule: ++ mutex_unlock(&msm_bus_rules_lock); ++} ++ ++bool msm_rule_are_rules_registered(void) ++{ ++ bool ret = false; ++ ++ if (list_empty(&node_list)) ++ ret = false; ++ else ++ ret = true; ++ ++ return ret; ++} ++ +--- /dev/null ++++ b/drivers/bus/msm_bus/msm_bus_rules.h +@@ -0,0 +1,77 @@ ++/* Copyright (c) 2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _ARCH_ARM_MACH_MSM_BUS_RULES_H ++#define _ARCH_ARM_MACH_MSM_BUS_RULES_H ++ ++#include ++#include ++#include ++#include ++ ++#define MAX_NODES (5) ++ ++struct rule_update_path_info { ++ u32 id; ++ u64 ab; ++ u64 ib; ++ u64 clk; ++ struct list_head link; ++}; ++ ++struct rule_apply_rcm_info { ++ u32 id; ++ u64 lim_bw; ++ int throttle; ++ bool after_clk_commit; ++ struct list_head link; ++}; ++ ++struct bus_rule_type { ++ int num_src; ++ int *src_id; ++ int src_field; ++ int op; ++ u64 thresh; ++ int num_dst; ++ int *dst_node; ++ u64 dst_bw; ++ int mode; ++ void *client_data; ++}; ++ ++#if (defined(CONFIG_BUS_TOPOLOGY_ADHOC)) ++void msm_rule_register(int num_rules, struct bus_rule_type *rule, ++ struct notifier_block *nb); ++void msm_rule_unregister(int num_rules, struct bus_rule_type *rule, ++ struct notifier_block *nb); ++void print_rules_buf(char *buf, int count); ++bool msm_rule_are_rules_registered(void); ++#else ++static inline void msm_rule_register(int num_rules, struct bus_rule_type *rule, ++ struct notifier_block *nb) ++{ ++} ++static inline void msm_rule_unregister(int num_rules, ++ struct bus_rule_type *rule, ++ struct notifier_block *nb) ++{ ++} ++static inline void print_rules_buf(char *buf, int count) ++{ ++} ++static inline bool msm_rule_are_rules_registered(void) ++{ ++ return false; ++} ++#endif /* defined(CONFIG_BUS_TOPOLOGY_ADHOC) */ ++#endif /* _ARCH_ARM_MACH_MSM_BUS_RULES_H */ +--- /dev/null ++++ b/drivers/bus/msm_bus/msm_buspm_coresight_adhoc.c +@@ -0,0 +1,189 @@ ++/* Copyright (c) 2014 The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct msmbus_coresight_adhoc_clock_drvdata { ++ int id; ++ struct clk *clk; ++ struct list_head list; ++}; ++ ++struct msmbus_coresight_adhoc_drvdata { ++ struct device *dev; ++ struct coresight_device *csdev; ++ struct coresight_desc *desc; ++ struct list_head clocks; ++}; ++ ++static int msmbus_coresight_enable_adhoc(struct coresight_device *csdev) ++{ ++ struct msmbus_coresight_adhoc_clock_drvdata *clk; ++ struct msmbus_coresight_adhoc_drvdata *drvdata = ++ dev_get_drvdata(csdev->dev.parent); ++ long rate; ++ ++ list_for_each_entry(clk, &drvdata->clocks, list) { ++ if (clk->id == csdev->id) { ++ rate = clk_round_rate(clk->clk, 1L); ++ clk_set_rate(clk->clk, rate); ++ return clk_prepare_enable(clk->clk); ++ } ++ } ++ ++ return -ENOENT; ++} ++ ++static void msmbus_coresight_disable_adhoc(struct coresight_device *csdev) ++{ ++ struct msmbus_coresight_adhoc_clock_drvdata *clk; ++ struct msmbus_coresight_adhoc_drvdata *drvdata = ++ dev_get_drvdata(csdev->dev.parent); ++ ++ list_for_each_entry(clk, &drvdata->clocks, list) { ++ if (clk->id == csdev->id) ++ clk_disable_unprepare(clk->clk); ++ } ++} ++ ++static const struct coresight_ops_source msmbus_coresight_adhoc_source_ops = { ++ .enable = msmbus_coresight_enable_adhoc, ++ .disable = msmbus_coresight_disable_adhoc, ++}; ++ ++static const struct coresight_ops msmbus_coresight_cs_ops = { ++ .source_ops = &msmbus_coresight_adhoc_source_ops, ++}; ++ ++void msmbus_coresight_remove_adhoc(struct platform_device *pdev) ++{ ++ struct msmbus_coresight_adhoc_clock_drvdata *clk, *next_clk; ++ struct msmbus_coresight_adhoc_drvdata *drvdata = ++ platform_get_drvdata(pdev); ++ ++ msmbus_coresight_disable_adhoc(drvdata->csdev); ++ coresight_unregister(drvdata->csdev); ++ list_for_each_entry_safe(clk, next_clk, &drvdata->clocks, list) { ++ list_del(&clk->list); ++ devm_kfree(&pdev->dev, clk); ++ } ++ devm_kfree(&pdev->dev, drvdata->desc); ++ devm_kfree(&pdev->dev, drvdata); ++ platform_set_drvdata(pdev, NULL); ++} ++EXPORT_SYMBOL(msmbus_coresight_remove_adhoc); ++ ++static int buspm_of_get_clk_adhoc(struct device_node *of_node, ++ struct msmbus_coresight_adhoc_drvdata *drvdata, int id) ++{ ++ struct msmbus_coresight_adhoc_clock_drvdata *clk; ++ clk = devm_kzalloc(drvdata->dev, sizeof(*clk), GFP_KERNEL); ++ ++ if (!clk) ++ return -ENOMEM; ++ ++ clk->id = id; ++ ++ clk->clk = of_clk_get_by_name(of_node, "bus_clk"); ++ if (IS_ERR(clk->clk)) { ++ pr_err("Error: unable to get clock for coresight node %d\n", ++ id); ++ goto err; ++ } ++ ++ list_add(&clk->list, &drvdata->clocks); ++ return 0; ++ ++err: ++ devm_kfree(drvdata->dev, clk); ++ return -EINVAL; ++} ++ ++int msmbus_coresight_init_adhoc(struct platform_device *pdev, ++ struct device_node *of_node) ++{ ++ int ret; ++ struct device *dev = &pdev->dev; ++ struct coresight_platform_data *pdata; ++ struct msmbus_coresight_adhoc_drvdata *drvdata; ++ struct coresight_desc *desc; ++ ++ pdata = of_get_coresight_platform_data(dev, of_node); ++ if (IS_ERR(pdata)) ++ return PTR_ERR(pdata); ++ ++ drvdata = platform_get_drvdata(pdev); ++ if (IS_ERR_OR_NULL(drvdata)) { ++ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); ++ if (!drvdata) { ++ pr_err("coresight: Alloc for drvdata failed\n"); ++ return -ENOMEM; ++ } ++ INIT_LIST_HEAD(&drvdata->clocks); ++ drvdata->dev = &pdev->dev; ++ platform_set_drvdata(pdev, drvdata); ++ } ++ ret = buspm_of_get_clk_adhoc(of_node, drvdata, pdata->id); ++ if (ret) { ++ pr_err("Error getting clocks\n"); ++ ret = -ENXIO; ++ goto err1; ++ } ++ ++ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); ++ if (!desc) { ++ pr_err("coresight: Error allocating memory\n"); ++ ret = -ENOMEM; ++ goto err1; ++ } ++ ++ desc->type = CORESIGHT_DEV_TYPE_SOURCE; ++ desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_BUS; ++ desc->ops = &msmbus_coresight_cs_ops; ++ desc->pdata = pdata; ++ desc->dev = &pdev->dev; ++ desc->owner = THIS_MODULE; ++ drvdata->desc = desc; ++ drvdata->csdev = coresight_register(desc); ++ if (IS_ERR(drvdata->csdev)) { ++ pr_err("coresight: Coresight register failed\n"); ++ ret = PTR_ERR(drvdata->csdev); ++ goto err0; ++ } ++ ++ dev_info(dev, "msmbus_coresight initialized\n"); ++ ++ return 0; ++err0: ++ devm_kfree(dev, desc); ++err1: ++ devm_kfree(dev, drvdata); ++ platform_set_drvdata(pdev, NULL); ++ return ret; ++} ++EXPORT_SYMBOL(msmbus_coresight_init_adhoc); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("MSM BusPM Adhoc CoreSight Driver"); +--- /dev/null ++++ b/drivers/bus/msm_bus/rpm-smd.h +@@ -0,0 +1,268 @@ ++/* Copyright (c) 2012, 2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ */ ++ ++#ifndef __ARCH_ARM_MACH_MSM_RPM_SMD_H ++#define __ARCH_ARM_MACH_MSM_RPM_SMD_H ++ ++/** ++ * enum msm_rpm_set - RPM enumerations for sleep/active set ++ * %MSM_RPM_CTX_SET_0: Set resource parameters for active mode. ++ * %MSM_RPM_CTX_SET_SLEEP: Set resource parameters for sleep. ++ */ ++enum msm_rpm_set { ++ MSM_RPM_CTX_ACTIVE_SET, ++ MSM_RPM_CTX_SLEEP_SET, ++}; ++ ++struct msm_rpm_request; ++ ++struct msm_rpm_kvp { ++ uint32_t key; ++ uint32_t length; ++ uint8_t *data; ++}; ++#ifdef CONFIG_MSM_RPM_SMD ++/** ++ * msm_rpm_request() - Creates a parent element to identify the ++ * resource on the RPM, that stores the KVPs for different fields modified ++ * for a hardware resource ++ * ++ * @set: if the device is setting the active/sleep set parameter ++ * for the resource ++ * @rsc_type: unsigned 32 bit integer that identifies the type of the resource ++ * @rsc_id: unsigned 32 bit that uniquely identifies a resource within a type ++ * @num_elements: number of KVPs pairs associated with the resource ++ * ++ * returns pointer to a msm_rpm_request on success, NULL on error ++ */ ++struct msm_rpm_request *msm_rpm_create_request( ++ enum msm_rpm_set set, uint32_t rsc_type, ++ uint32_t rsc_id, int num_elements); ++ ++/** ++ * msm_rpm_request_noirq() - Creates a parent element to identify the ++ * resource on the RPM, that stores the KVPs for different fields modified ++ * for a hardware resource. This function is similar to msm_rpm_create_request ++ * except that it has to be called with interrupts masked. ++ * ++ * @set: if the device is setting the active/sleep set parameter ++ * for the resource ++ * @rsc_type: unsigned 32 bit integer that identifies the type of the resource ++ * @rsc_id: unsigned 32 bit that uniquely identifies a resource within a type ++ * @num_elements: number of KVPs pairs associated with the resource ++ * ++ * returns pointer to a msm_rpm_request on success, NULL on error ++ */ ++struct msm_rpm_request *msm_rpm_create_request_noirq( ++ enum msm_rpm_set set, uint32_t rsc_type, ++ uint32_t rsc_id, int num_elements); ++ ++/** ++ * msm_rpm_add_kvp_data() - Adds a Key value pair to a existing RPM resource. ++ * ++ * @handle: RPM resource handle to which the data should be appended ++ * @key: unsigned integer identify the parameter modified ++ * @data: byte array that contains the value corresponding to key. ++ * @size: size of data in bytes. ++ * ++ * returns 0 on success or errno ++ */ ++int msm_rpm_add_kvp_data(struct msm_rpm_request *handle, ++ uint32_t key, const uint8_t *data, int size); ++ ++/** ++ * msm_rpm_add_kvp_data_noirq() - Adds a Key value pair to a existing RPM ++ * resource. This function is similar to msm_rpm_add_kvp_data except that it ++ * has to be called with interrupts masked. ++ * ++ * @handle: RPM resource handle to which the data should be appended ++ * @key: unsigned integer identify the parameter modified ++ * @data: byte array that contains the value corresponding to key. ++ * @size: size of data in bytes. ++ * ++ * returns 0 on success or errno ++ */ ++int msm_rpm_add_kvp_data_noirq(struct msm_rpm_request *handle, ++ uint32_t key, const uint8_t *data, int size); ++ ++/** msm_rpm_free_request() - clean up the RPM request handle created with ++ * msm_rpm_create_request ++ * ++ * @handle: RPM resource handle to be cleared. ++ */ ++ ++void msm_rpm_free_request(struct msm_rpm_request *handle); ++ ++/** ++ * msm_rpm_send_request() - Send the RPM messages using SMD. The function ++ * assigns a message id before sending the data out to the RPM. RPM hardware ++ * uses the message id to acknowledge the messages. ++ * ++ * @handle: pointer to the msm_rpm_request for the resource being modified. ++ * ++ * returns non-zero message id on success and zero on a failed transaction. ++ * The drivers use message id to wait for ACK from RPM. ++ */ ++int msm_rpm_send_request(struct msm_rpm_request *handle); ++ ++/** ++ * msm_rpm_send_request_noirq() - Send the RPM messages using SMD. The ++ * function assigns a message id before sending the data out to the RPM. ++ * RPM hardware uses the message id to acknowledge the messages. This function ++ * is similar to msm_rpm_send_request except that it has to be called with ++ * interrupts masked. ++ * ++ * @handle: pointer to the msm_rpm_request for the resource being modified. ++ * ++ * returns non-zero message id on success and zero on a failed transaction. ++ * The drivers use message id to wait for ACK from RPM. ++ */ ++int msm_rpm_send_request_noirq(struct msm_rpm_request *handle); ++ ++/** ++ * msm_rpm_wait_for_ack() - A blocking call that waits for acknowledgment of ++ * a message from RPM. ++ * ++ * @msg_id: the return from msm_rpm_send_requests ++ * ++ * returns 0 on success or errno ++ */ ++int msm_rpm_wait_for_ack(uint32_t msg_id); ++ ++/** ++ * msm_rpm_wait_for_ack_noirq() - A blocking call that waits for acknowledgment ++ * of a message from RPM. This function is similar to msm_rpm_wait_for_ack ++ * except that it has to be called with interrupts masked. ++ * ++ * @msg_id: the return from msm_rpm_send_request ++ * ++ * returns 0 on success or errno ++ */ ++int msm_rpm_wait_for_ack_noirq(uint32_t msg_id); ++ ++/** ++ * msm_rpm_send_message() -Wrapper function for clients to send data given an ++ * array of key value pairs. ++ * ++ * @set: if the device is setting the active/sleep set parameter ++ * for the resource ++ * @rsc_type: unsigned 32 bit integer that identifies the type of the resource ++ * @rsc_id: unsigned 32 bit that uniquely identifies a resource within a type ++ * @kvp: array of KVP data. ++ * @nelem: number of KVPs pairs associated with the message. ++ * ++ * returns 0 on success and errno on failure. ++ */ ++int msm_rpm_send_message(enum msm_rpm_set set, uint32_t rsc_type, ++ uint32_t rsc_id, struct msm_rpm_kvp *kvp, int nelems); ++ ++/** ++ * msm_rpm_send_message_noirq() -Wrapper function for clients to send data ++ * given an array of key value pairs. This function is similar to the ++ * msm_rpm_send_message() except that it has to be called with interrupts ++ * disabled. Clients should choose the irq version when possible for system ++ * performance. ++ * ++ * @set: if the device is setting the active/sleep set parameter ++ * for the resource ++ * @rsc_type: unsigned 32 bit integer that identifies the type of the resource ++ * @rsc_id: unsigned 32 bit that uniquely identifies a resource within a type ++ * @kvp: array of KVP data. ++ * @nelem: number of KVPs pairs associated with the message. ++ * ++ * returns 0 on success and errno on failure. ++ */ ++int msm_rpm_send_message_noirq(enum msm_rpm_set set, uint32_t rsc_type, ++ uint32_t rsc_id, struct msm_rpm_kvp *kvp, int nelems); ++ ++/** ++ * msm_rpm_driver_init() - Initialization function that registers for a ++ * rpm platform driver. ++ * ++ * returns 0 on success. ++ */ ++int __init msm_rpm_driver_init(void); ++ ++#else ++ ++static inline struct msm_rpm_request *msm_rpm_create_request( ++ enum msm_rpm_set set, uint32_t rsc_type, ++ uint32_t rsc_id, int num_elements) ++{ ++ return NULL; ++} ++ ++static inline struct msm_rpm_request *msm_rpm_create_request_noirq( ++ enum msm_rpm_set set, uint32_t rsc_type, ++ uint32_t rsc_id, int num_elements) ++{ ++ return NULL; ++ ++} ++static inline uint32_t msm_rpm_add_kvp_data(struct msm_rpm_request *handle, ++ uint32_t key, const uint8_t *data, int count) ++{ ++ return 0; ++} ++static inline uint32_t msm_rpm_add_kvp_data_noirq( ++ struct msm_rpm_request *handle, uint32_t key, ++ const uint8_t *data, int count) ++{ ++ return 0; ++} ++ ++static inline void msm_rpm_free_request(struct msm_rpm_request *handle) ++{ ++ return; ++} ++ ++static inline int msm_rpm_send_request(struct msm_rpm_request *handle) ++{ ++ return 0; ++} ++ ++static inline int msm_rpm_send_request_noirq(struct msm_rpm_request *handle) ++{ ++ return 0; ++ ++} ++ ++static inline int msm_rpm_send_message(enum msm_rpm_set set, uint32_t rsc_type, ++ uint32_t rsc_id, struct msm_rpm_kvp *kvp, int nelems) ++{ ++ return 0; ++} ++ ++static inline int msm_rpm_send_message_noirq(enum msm_rpm_set set, ++ uint32_t rsc_type, uint32_t rsc_id, struct msm_rpm_kvp *kvp, ++ int nelems) ++{ ++ return 0; ++} ++ ++static inline int msm_rpm_wait_for_ack(uint32_t msg_id) ++{ ++ return 0; ++ ++} ++static inline int msm_rpm_wait_for_ack_noirq(uint32_t msg_id) ++{ ++ return 0; ++} ++ ++static inline int __init msm_rpm_driver_init(void) ++{ ++ return 0; ++} ++#endif ++#endif /*__ARCH_ARM_MACH_MSM_RPM_SMD_H*/ +--- /dev/null ++++ b/include/trace/events/trace_msm_bus.h +@@ -0,0 +1,163 @@ ++/* Copyright (c) 2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM msm_bus ++ ++#if !defined(_TRACE_MSM_BUS_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_MSM_BUS_H ++ ++#include ++ ++TRACE_EVENT(bus_update_request, ++ ++ TP_PROTO(int sec, int nsec, const char *name, unsigned int index, ++ int src, int dest, unsigned long long ab, ++ unsigned long long ib), ++ ++ TP_ARGS(sec, nsec, name, index, src, dest, ab, ib), ++ ++ TP_STRUCT__entry( ++ __field(int, sec) ++ __field(int, nsec) ++ __string(name, name) ++ __field(u32, index) ++ __field(int, src) ++ __field(int, dest) ++ __field(u64, ab) ++ __field(u64, ib) ++ ), ++ ++ TP_fast_assign( ++ __entry->sec = sec; ++ __entry->nsec = nsec; ++ __assign_str(name, name); ++ __entry->index = index; ++ __entry->src = src; ++ __entry->dest = dest; ++ __entry->ab = ab; ++ __entry->ib = ib; ++ ), ++ ++ TP_printk("time= %d.%d name=%s index=%u src=%d dest=%d ab=%llu ib=%llu", ++ __entry->sec, ++ __entry->nsec, ++ __get_str(name), ++ (unsigned int)__entry->index, ++ __entry->src, ++ __entry->dest, ++ (unsigned long long)__entry->ab, ++ (unsigned long long)__entry->ib) ++); ++ ++TRACE_EVENT(bus_bimc_config_limiter, ++ ++ TP_PROTO(int mas_id, unsigned long long cur_lim_bw), ++ ++ TP_ARGS(mas_id, cur_lim_bw), ++ ++ TP_STRUCT__entry( ++ __field(int, mas_id) ++ __field(u64, cur_lim_bw) ++ ), ++ ++ TP_fast_assign( ++ __entry->mas_id = mas_id; ++ __entry->cur_lim_bw = cur_lim_bw; ++ ), ++ ++ TP_printk("Master=%d cur_lim_bw=%llu", ++ __entry->mas_id, ++ (unsigned long long)__entry->cur_lim_bw) ++); ++ ++TRACE_EVENT(bus_avail_bw, ++ ++ TP_PROTO(unsigned long long cur_bimc_bw, unsigned long long cur_mdp_bw), ++ ++ TP_ARGS(cur_bimc_bw, cur_mdp_bw), ++ ++ TP_STRUCT__entry( ++ __field(u64, cur_bimc_bw) ++ __field(u64, cur_mdp_bw) ++ ), ++ ++ TP_fast_assign( ++ __entry->cur_bimc_bw = cur_bimc_bw; ++ __entry->cur_mdp_bw = cur_mdp_bw; ++ ), ++ ++ TP_printk("cur_bimc_bw = %llu cur_mdp_bw = %llu", ++ (unsigned long long)__entry->cur_bimc_bw, ++ (unsigned long long)__entry->cur_mdp_bw) ++); ++ ++TRACE_EVENT(bus_rules_matches, ++ ++ TP_PROTO(int node_id, int rule_id, unsigned long long node_ab, ++ unsigned long long node_ib, unsigned long long node_clk), ++ ++ TP_ARGS(node_id, rule_id, node_ab, node_ib, node_clk), ++ ++ TP_STRUCT__entry( ++ __field(int, node_id) ++ __field(int, rule_id) ++ __field(u64, node_ab) ++ __field(u64, node_ib) ++ __field(u64, node_clk) ++ ), ++ ++ TP_fast_assign( ++ __entry->node_id = node_id; ++ __entry->rule_id = rule_id; ++ __entry->node_ab = node_ab; ++ __entry->node_ib = node_ib; ++ __entry->node_clk = node_clk; ++ ), ++ ++ TP_printk("Rule match node%d rule%d node-ab%llu:ib%llu:clk%llu", ++ __entry->node_id, __entry->rule_id, ++ (unsigned long long)__entry->node_ab, ++ (unsigned long long)__entry->node_ib, ++ (unsigned long long)__entry->node_clk) ++); ++ ++TRACE_EVENT(bus_bke_params, ++ ++ TP_PROTO(u32 gc, u32 gp, u32 thl, u32 thm, u32 thh), ++ ++ TP_ARGS(gc, gp, thl, thm, thh), ++ ++ TP_STRUCT__entry( ++ __field(u32, gc) ++ __field(u32, gp) ++ __field(u32, thl) ++ __field(u32, thm) ++ __field(u32, thh) ++ ), ++ ++ TP_fast_assign( ++ __entry->gc = gc; ++ __entry->gp = gp; ++ __entry->thl = thl; ++ __entry->thm = thm; ++ __entry->thh = thh; ++ ), ++ ++ TP_printk("BKE Params GC=0x%x GP=0x%x THL=0x%x THM=0x%x THH=0x%x", ++ __entry->gc, __entry->gp, __entry->thl, __entry->thm, ++ __entry->thh) ++); ++ ++#endif ++#define TRACE_INCLUDE_FILE trace_msm_bus ++#include diff --git a/target/linux/ipq40xx/patches-4.14/400-mtd-ubi-add-quirk-to-autoload-ubi-on-rt-ac58u.patch b/target/linux/ipq40xx/patches-4.14/400-mtd-ubi-add-quirk-to-autoload-ubi-on-rt-ac58u.patch new file mode 100644 index 000000000..86cb45461 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/400-mtd-ubi-add-quirk-to-autoload-ubi-on-rt-ac58u.patch @@ -0,0 +1,29 @@ +From b8f3a7ccbeca5bdbd1b6210b94b38d3fef2dd0bd Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Thu, 19 Jan 2017 01:57:22 +0100 +Subject: [PATCH 16/38] mtd: ubi: add auto_attach HACK for the ASUS RT-AC58U + +This patch adds a hack that allows UBI's autoattach feature +to work with the custom ASUS UBI_DEV partition name. + +This is necessary because the vendor's u-boot doesn't leave +the bootargs / cmdline alone, so the it can't be overwritten +easily otherwise. + +Signed-off-by: Christian Lamparter +--- + drivers/mtd/ubi/build.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/mtd/ubi/build.c ++++ b/drivers/mtd/ubi/build.c +@@ -1170,6 +1170,9 @@ static void __init ubi_auto_attach(void) + mtd = open_mtd_device("ubi"); + if (IS_ERR(mtd)) + mtd = open_mtd_device("data"); ++ /* Hack for the Asus RT-AC58U */ ++ if (IS_ERR(mtd)) ++ mtd = open_mtd_device("UBI_DEV"); + + if (!IS_ERR(mtd)) { + size_t len; diff --git a/target/linux/ipq40xx/patches-4.14/605-net-IPQ4019-needs-rfs-vlan_tag-callbacks-in.patch b/target/linux/ipq40xx/patches-4.14/605-net-IPQ4019-needs-rfs-vlan_tag-callbacks-in.patch new file mode 100644 index 000000000..a52fe2832 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/605-net-IPQ4019-needs-rfs-vlan_tag-callbacks-in.patch @@ -0,0 +1,53 @@ +From 7c129254adb1093d10a62ed7bf7b956fcc6ffe34 Mon Sep 17 00:00:00 2001 +From: Rakesh Nair +Date: Wed, 20 Jul 2016 15:02:01 +0530 +Subject: [PATCH] net: IPQ4019 needs rfs/vlan_tag callbacks in + netdev_ops + +Add callback support to get default vlan tag and register +receive flow steering filter. + +Used by IPQ4019 ess-edma driver. + +BUG=chrome-os-partner:33096 +TEST=none + +Change-Id: I266070e4a0fbe4a0d9966fe79a71e50ec4f26c75 +Signed-off-by: Rakesh Nair +Reviewed-on: https://chromium-review.googlesource.com/362203 +Commit-Ready: Grant Grundler +Tested-by: Grant Grundler +Reviewed-by: Grant Grundler +--- + include/linux/netdevice.h | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -713,6 +713,16 @@ struct xps_map { + #define XPS_MIN_MAP_ALLOC ((L1_CACHE_ALIGN(offsetof(struct xps_map, queues[1])) \ + - sizeof(struct xps_map)) / sizeof(u16)) + ++#ifdef CONFIG_RFS_ACCEL ++typedef int (*set_rfs_filter_callback_t)(struct net_device *dev, ++ __be32 src, ++ __be32 dst, ++ __be16 sport, ++ __be16 dport, ++ u8 proto, ++ u16 rxq_index, ++ u32 action); ++#endif + /* + * This structure holds all XPS maps for device. Maps are indexed by CPU. + */ +@@ -1239,6 +1249,9 @@ struct net_device_ops { + const struct sk_buff *skb, + u16 rxq_index, + u32 flow_id); ++ int (*ndo_register_rfs_filter)(struct net_device *dev, ++ set_rfs_filter_callback_t set_filter); ++ int (*ndo_get_default_vlan_tag)(struct net_device *net); + #endif + int (*ndo_add_slave)(struct net_device *dev, + struct net_device *slave_dev); diff --git a/target/linux/ipq40xx/patches-4.14/700-net-add-qualcomm-mdio-and-phy.patch b/target/linux/ipq40xx/patches-4.14/700-net-add-qualcomm-mdio-and-phy.patch new file mode 100644 index 000000000..c6e715510 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/700-net-add-qualcomm-mdio-and-phy.patch @@ -0,0 +1,2690 @@ +From 5a71a2005a2e1e6bbe36f00386c495ad6626beb2 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Thu, 19 Jan 2017 01:59:43 +0100 +Subject: [PATCH 30/38] NET: add qualcomm mdio and PHY + +--- + drivers/net/phy/Kconfig | 14 ++++++++++++++ + drivers/net/phy/Makefile | 2 ++ + 2 files changed, 16 insertions(+) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -481,6 +481,20 @@ config XILINX_GMII2RGMII + the Reduced Gigabit Media Independent Interface(RGMII) between + Ethernet physical media devices and the Gigabit Ethernet controller. + ++config MDIO_IPQ40XX ++ tristate "Qualcomm Atheros ipq40xx MDIO interface" ++ depends on HAS_IOMEM && OF ++ ---help--- ++ This driver supports the MDIO interface found in Qualcomm ++ Atheros ipq40xx Soc chip. ++ ++config AR40XX_PHY ++ tristate "Driver for Qualcomm Atheros IPQ40XX switches" ++ depends on HAS_IOMEM && OF ++ select SWCONFIG ++ ---help--- ++ This is the driver for Qualcomm Atheros IPQ40XX ESS switches. ++ + endif # PHYLIB + + config MICREL_KS8995MA +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -48,6 +48,7 @@ obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium + obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o + obj-$(CONFIG_MDIO_HISI_FEMAC) += mdio-hisi-femac.o + obj-$(CONFIG_MDIO_I2C) += mdio-i2c.o ++obj-$(CONFIG_MDIO_IPQ40XX) += mdio-ipq40xx.o + obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o + obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o + obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o +@@ -60,6 +61,7 @@ obj-y += $(sfp-obj-y) $(sfp-obj-m) + + obj-$(CONFIG_AMD_PHY) += amd.o + obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o ++obj-$(CONFIG_AR40XX_PHY) += ar40xx.o + obj-$(CONFIG_AT803X_PHY) += at803x.o + obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o + obj-$(CONFIG_BCM7XXX_PHY) += bcm7xxx.o +--- /dev/null ++++ b/drivers/net/phy/ar40xx.c +@@ -0,0 +1,2090 @@ ++/* ++ * Copyright (c) 2016, The Linux Foundation. All rights reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for ++ * any purpose with or without fee is hereby granted, provided that the ++ * above copyright notice and this permission notice appear in all copies. ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT ++ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ar40xx.h" ++ ++static struct ar40xx_priv *ar40xx_priv; ++ ++#define MIB_DESC(_s , _o, _n) \ ++ { \ ++ .size = (_s), \ ++ .offset = (_o), \ ++ .name = (_n), \ ++ } ++ ++static const struct ar40xx_mib_desc ar40xx_mibs[] = { ++ MIB_DESC(1, AR40XX_STATS_RXBROAD, "RxBroad"), ++ MIB_DESC(1, AR40XX_STATS_RXPAUSE, "RxPause"), ++ MIB_DESC(1, AR40XX_STATS_RXMULTI, "RxMulti"), ++ MIB_DESC(1, AR40XX_STATS_RXFCSERR, "RxFcsErr"), ++ MIB_DESC(1, AR40XX_STATS_RXALIGNERR, "RxAlignErr"), ++ MIB_DESC(1, AR40XX_STATS_RXRUNT, "RxRunt"), ++ MIB_DESC(1, AR40XX_STATS_RXFRAGMENT, "RxFragment"), ++ MIB_DESC(1, AR40XX_STATS_RX64BYTE, "Rx64Byte"), ++ MIB_DESC(1, AR40XX_STATS_RX128BYTE, "Rx128Byte"), ++ MIB_DESC(1, AR40XX_STATS_RX256BYTE, "Rx256Byte"), ++ MIB_DESC(1, AR40XX_STATS_RX512BYTE, "Rx512Byte"), ++ MIB_DESC(1, AR40XX_STATS_RX1024BYTE, "Rx1024Byte"), ++ MIB_DESC(1, AR40XX_STATS_RX1518BYTE, "Rx1518Byte"), ++ MIB_DESC(1, AR40XX_STATS_RXMAXBYTE, "RxMaxByte"), ++ MIB_DESC(1, AR40XX_STATS_RXTOOLONG, "RxTooLong"), ++ MIB_DESC(2, AR40XX_STATS_RXGOODBYTE, "RxGoodByte"), ++ MIB_DESC(2, AR40XX_STATS_RXBADBYTE, "RxBadByte"), ++ MIB_DESC(1, AR40XX_STATS_RXOVERFLOW, "RxOverFlow"), ++ MIB_DESC(1, AR40XX_STATS_FILTERED, "Filtered"), ++ MIB_DESC(1, AR40XX_STATS_TXBROAD, "TxBroad"), ++ MIB_DESC(1, AR40XX_STATS_TXPAUSE, "TxPause"), ++ MIB_DESC(1, AR40XX_STATS_TXMULTI, "TxMulti"), ++ MIB_DESC(1, AR40XX_STATS_TXUNDERRUN, "TxUnderRun"), ++ MIB_DESC(1, AR40XX_STATS_TX64BYTE, "Tx64Byte"), ++ MIB_DESC(1, AR40XX_STATS_TX128BYTE, "Tx128Byte"), ++ MIB_DESC(1, AR40XX_STATS_TX256BYTE, "Tx256Byte"), ++ MIB_DESC(1, AR40XX_STATS_TX512BYTE, "Tx512Byte"), ++ MIB_DESC(1, AR40XX_STATS_TX1024BYTE, "Tx1024Byte"), ++ MIB_DESC(1, AR40XX_STATS_TX1518BYTE, "Tx1518Byte"), ++ MIB_DESC(1, AR40XX_STATS_TXMAXBYTE, "TxMaxByte"), ++ MIB_DESC(1, AR40XX_STATS_TXOVERSIZE, "TxOverSize"), ++ MIB_DESC(2, AR40XX_STATS_TXBYTE, "TxByte"), ++ MIB_DESC(1, AR40XX_STATS_TXCOLLISION, "TxCollision"), ++ MIB_DESC(1, AR40XX_STATS_TXABORTCOL, "TxAbortCol"), ++ MIB_DESC(1, AR40XX_STATS_TXMULTICOL, "TxMultiCol"), ++ MIB_DESC(1, AR40XX_STATS_TXSINGLECOL, "TxSingleCol"), ++ MIB_DESC(1, AR40XX_STATS_TXEXCDEFER, "TxExcDefer"), ++ MIB_DESC(1, AR40XX_STATS_TXDEFER, "TxDefer"), ++ MIB_DESC(1, AR40XX_STATS_TXLATECOL, "TxLateCol"), ++}; ++ ++static u32 ++ar40xx_read(struct ar40xx_priv *priv, int reg) ++{ ++ return readl(priv->hw_addr + reg); ++} ++ ++static u32 ++ar40xx_psgmii_read(struct ar40xx_priv *priv, int reg) ++{ ++ return readl(priv->psgmii_hw_addr + reg); ++} ++ ++static void ++ar40xx_write(struct ar40xx_priv *priv, int reg, u32 val) ++{ ++ writel(val, priv->hw_addr + reg); ++} ++ ++static u32 ++ar40xx_rmw(struct ar40xx_priv *priv, int reg, u32 mask, u32 val) ++{ ++ u32 ret; ++ ++ ret = ar40xx_read(priv, reg); ++ ret &= ~mask; ++ ret |= val; ++ ar40xx_write(priv, reg, ret); ++ return ret; ++} ++ ++static void ++ar40xx_psgmii_write(struct ar40xx_priv *priv, int reg, u32 val) ++{ ++ writel(val, priv->psgmii_hw_addr + reg); ++} ++ ++static void ++ar40xx_phy_dbg_write(struct ar40xx_priv *priv, int phy_addr, ++ u16 dbg_addr, u16 dbg_data) ++{ ++ struct mii_bus *bus = priv->mii_bus; ++ ++ mutex_lock(&bus->mdio_lock); ++ bus->write(bus, phy_addr, AR40XX_MII_ATH_DBG_ADDR, dbg_addr); ++ bus->write(bus, phy_addr, AR40XX_MII_ATH_DBG_DATA, dbg_data); ++ mutex_unlock(&bus->mdio_lock); ++} ++ ++static void ++ar40xx_phy_dbg_read(struct ar40xx_priv *priv, int phy_addr, ++ u16 dbg_addr, u16 *dbg_data) ++{ ++ struct mii_bus *bus = priv->mii_bus; ++ ++ mutex_lock(&bus->mdio_lock); ++ bus->write(bus, phy_addr, AR40XX_MII_ATH_DBG_ADDR, dbg_addr); ++ *dbg_data = bus->read(bus, phy_addr, AR40XX_MII_ATH_DBG_DATA); ++ mutex_unlock(&bus->mdio_lock); ++} ++ ++static void ++ar40xx_phy_mmd_write(struct ar40xx_priv *priv, u32 phy_id, ++ u16 mmd_num, u16 reg_id, u16 reg_val) ++{ ++ struct mii_bus *bus = priv->mii_bus; ++ ++ mutex_lock(&bus->mdio_lock); ++ bus->write(bus, phy_id, ++ AR40XX_MII_ATH_MMD_ADDR, mmd_num); ++ bus->write(bus, phy_id, ++ AR40XX_MII_ATH_MMD_DATA, reg_id); ++ bus->write(bus, phy_id, ++ AR40XX_MII_ATH_MMD_ADDR, ++ 0x4000 | mmd_num); ++ bus->write(bus, phy_id, ++ AR40XX_MII_ATH_MMD_DATA, reg_val); ++ mutex_unlock(&bus->mdio_lock); ++} ++ ++static u16 ++ar40xx_phy_mmd_read(struct ar40xx_priv *priv, u32 phy_id, ++ u16 mmd_num, u16 reg_id) ++{ ++ u16 value; ++ struct mii_bus *bus = priv->mii_bus; ++ ++ mutex_lock(&bus->mdio_lock); ++ bus->write(bus, phy_id, ++ AR40XX_MII_ATH_MMD_ADDR, mmd_num); ++ bus->write(bus, phy_id, ++ AR40XX_MII_ATH_MMD_DATA, reg_id); ++ bus->write(bus, phy_id, ++ AR40XX_MII_ATH_MMD_ADDR, ++ 0x4000 | mmd_num); ++ value = bus->read(bus, phy_id, AR40XX_MII_ATH_MMD_DATA); ++ mutex_unlock(&bus->mdio_lock); ++ return value; ++} ++ ++/* Start of swconfig support */ ++ ++static void ++ar40xx_phy_poll_reset(struct ar40xx_priv *priv) ++{ ++ u32 i, in_reset, retries = 500; ++ struct mii_bus *bus = priv->mii_bus; ++ ++ /* Assume RESET was recently issued to some or all of the phys */ ++ in_reset = GENMASK(AR40XX_NUM_PHYS - 1, 0); ++ ++ while (retries--) { ++ /* 1ms should be plenty of time. ++ * 802.3 spec allows for a max wait time of 500ms ++ */ ++ usleep_range(1000, 2000); ++ ++ for (i = 0; i < AR40XX_NUM_PHYS; i++) { ++ int val; ++ ++ /* skip devices which have completed reset */ ++ if (!(in_reset & BIT(i))) ++ continue; ++ ++ val = mdiobus_read(bus, i, MII_BMCR); ++ if (val < 0) ++ continue; ++ ++ /* mark when phy is no longer in reset state */ ++ if (!(val & BMCR_RESET)) ++ in_reset &= ~BIT(i); ++ } ++ ++ if (!in_reset) ++ return; ++ } ++ ++ dev_warn(&bus->dev, "Failed to reset all phys! (in_reset: 0x%x)\n", ++ in_reset); ++} ++ ++static void ++ar40xx_phy_init(struct ar40xx_priv *priv) ++{ ++ int i; ++ struct mii_bus *bus; ++ u16 val; ++ ++ bus = priv->mii_bus; ++ for (i = 0; i < AR40XX_NUM_PORTS - 1; i++) { ++ ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_0, &val); ++ val &= ~AR40XX_PHY_MANU_CTRL_EN; ++ ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_0, val); ++ mdiobus_write(bus, i, ++ MII_ADVERTISE, ADVERTISE_ALL | ++ ADVERTISE_PAUSE_CAP | ++ ADVERTISE_PAUSE_ASYM); ++ mdiobus_write(bus, i, MII_CTRL1000, ADVERTISE_1000FULL); ++ mdiobus_write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); ++ } ++ ++ ar40xx_phy_poll_reset(priv); ++} ++ ++static void ++ar40xx_port_phy_linkdown(struct ar40xx_priv *priv) ++{ ++ struct mii_bus *bus; ++ int i; ++ u16 val; ++ ++ bus = priv->mii_bus; ++ for (i = 0; i < AR40XX_NUM_PORTS - 1; i++) { ++ mdiobus_write(bus, i, MII_CTRL1000, 0); ++ mdiobus_write(bus, i, MII_ADVERTISE, 0); ++ mdiobus_write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); ++ ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_0, &val); ++ val |= AR40XX_PHY_MANU_CTRL_EN; ++ ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_0, val); ++ /* disable transmit */ ++ ar40xx_phy_dbg_read(priv, i, AR40XX_PHY_DEBUG_2, &val); ++ val &= 0xf00f; ++ ar40xx_phy_dbg_write(priv, i, AR40XX_PHY_DEBUG_2, val); ++ } ++} ++ ++static void ++ar40xx_set_mirror_regs(struct ar40xx_priv *priv) ++{ ++ int port; ++ ++ /* reset all mirror registers */ ++ ar40xx_rmw(priv, AR40XX_REG_FWD_CTRL0, ++ AR40XX_FWD_CTRL0_MIRROR_PORT, ++ (0xF << AR40XX_FWD_CTRL0_MIRROR_PORT_S)); ++ for (port = 0; port < AR40XX_NUM_PORTS; port++) { ++ ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(port), ++ AR40XX_PORT_LOOKUP_ING_MIRROR_EN, 0); ++ ++ ar40xx_rmw(priv, AR40XX_REG_PORT_HOL_CTRL1(port), ++ AR40XX_PORT_HOL_CTRL1_EG_MIRROR_EN, 0); ++ } ++ ++ /* now enable mirroring if necessary */ ++ if (priv->source_port >= AR40XX_NUM_PORTS || ++ priv->monitor_port >= AR40XX_NUM_PORTS || ++ priv->source_port == priv->monitor_port) { ++ return; ++ } ++ ++ ar40xx_rmw(priv, AR40XX_REG_FWD_CTRL0, ++ AR40XX_FWD_CTRL0_MIRROR_PORT, ++ (priv->monitor_port << AR40XX_FWD_CTRL0_MIRROR_PORT_S)); ++ ++ if (priv->mirror_rx) ++ ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(priv->source_port), 0, ++ AR40XX_PORT_LOOKUP_ING_MIRROR_EN); ++ ++ if (priv->mirror_tx) ++ ar40xx_rmw(priv, AR40XX_REG_PORT_HOL_CTRL1(priv->source_port), ++ 0, AR40XX_PORT_HOL_CTRL1_EG_MIRROR_EN); ++} ++ ++static int ++ar40xx_sw_get_ports(struct switch_dev *dev, struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ u8 ports = priv->vlan_table[val->port_vlan]; ++ int i; ++ ++ val->len = 0; ++ for (i = 0; i < dev->ports; i++) { ++ struct switch_port *p; ++ ++ if (!(ports & BIT(i))) ++ continue; ++ ++ p = &val->value.ports[val->len++]; ++ p->id = i; ++ if ((priv->vlan_tagged & BIT(i)) || ++ (priv->pvid[i] != val->port_vlan)) ++ p->flags = BIT(SWITCH_PORT_FLAG_TAGGED); ++ else ++ p->flags = 0; ++ } ++ return 0; ++} ++ ++static int ++ar40xx_sw_set_ports(struct switch_dev *dev, struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ u8 *vt = &priv->vlan_table[val->port_vlan]; ++ int i; ++ ++ *vt = 0; ++ for (i = 0; i < val->len; i++) { ++ struct switch_port *p = &val->value.ports[i]; ++ ++ if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED)) { ++ if (val->port_vlan == priv->pvid[p->id]) ++ priv->vlan_tagged |= BIT(p->id); ++ } else { ++ priv->vlan_tagged &= ~BIT(p->id); ++ priv->pvid[p->id] = val->port_vlan; ++ } ++ ++ *vt |= BIT(p->id); ++ } ++ return 0; ++} ++ ++static int ++ar40xx_reg_wait(struct ar40xx_priv *priv, u32 reg, u32 mask, u32 val, ++ unsigned timeout) ++{ ++ int i; ++ ++ for (i = 0; i < timeout; i++) { ++ u32 t; ++ ++ t = ar40xx_read(priv, reg); ++ if ((t & mask) == val) ++ return 0; ++ ++ usleep_range(1000, 2000); ++ } ++ ++ return -ETIMEDOUT; ++} ++ ++static int ++ar40xx_mib_op(struct ar40xx_priv *priv, u32 op) ++{ ++ int ret; ++ ++ lockdep_assert_held(&priv->mib_lock); ++ ++ /* Capture the hardware statistics for all ports */ ++ ar40xx_rmw(priv, AR40XX_REG_MIB_FUNC, ++ AR40XX_MIB_FUNC, (op << AR40XX_MIB_FUNC_S)); ++ ++ /* Wait for the capturing to complete. */ ++ ret = ar40xx_reg_wait(priv, AR40XX_REG_MIB_FUNC, ++ AR40XX_MIB_BUSY, 0, 10); ++ ++ return ret; ++} ++ ++static void ++ar40xx_mib_fetch_port_stat(struct ar40xx_priv *priv, int port, bool flush) ++{ ++ unsigned int base; ++ u64 *mib_stats; ++ int i; ++ u32 num_mibs = ARRAY_SIZE(ar40xx_mibs); ++ ++ WARN_ON(port >= priv->dev.ports); ++ ++ lockdep_assert_held(&priv->mib_lock); ++ ++ base = AR40XX_REG_PORT_STATS_START + ++ AR40XX_REG_PORT_STATS_LEN * port; ++ ++ mib_stats = &priv->mib_stats[port * num_mibs]; ++ if (flush) { ++ u32 len; ++ ++ len = num_mibs * sizeof(*mib_stats); ++ memset(mib_stats, 0, len); ++ return; ++ } ++ for (i = 0; i < num_mibs; i++) { ++ const struct ar40xx_mib_desc *mib; ++ u64 t; ++ ++ mib = &ar40xx_mibs[i]; ++ t = ar40xx_read(priv, base + mib->offset); ++ if (mib->size == 2) { ++ u64 hi; ++ ++ hi = ar40xx_read(priv, base + mib->offset + 4); ++ t |= hi << 32; ++ } ++ ++ mib_stats[i] += t; ++ } ++} ++ ++static int ++ar40xx_mib_capture(struct ar40xx_priv *priv) ++{ ++ return ar40xx_mib_op(priv, AR40XX_MIB_FUNC_CAPTURE); ++} ++ ++static int ++ar40xx_mib_flush(struct ar40xx_priv *priv) ++{ ++ return ar40xx_mib_op(priv, AR40XX_MIB_FUNC_FLUSH); ++} ++ ++static int ++ar40xx_sw_set_reset_mibs(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ unsigned int len; ++ int ret; ++ u32 num_mibs = ARRAY_SIZE(ar40xx_mibs); ++ ++ mutex_lock(&priv->mib_lock); ++ ++ len = priv->dev.ports * num_mibs * sizeof(*priv->mib_stats); ++ memset(priv->mib_stats, 0, len); ++ ret = ar40xx_mib_flush(priv); ++ ++ mutex_unlock(&priv->mib_lock); ++ return ret; ++} ++ ++static int ++ar40xx_sw_set_vlan(struct switch_dev *dev, const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ ++ priv->vlan = !!val->value.i; ++ return 0; ++} ++ ++static int ++ar40xx_sw_get_vlan(struct switch_dev *dev, const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ ++ val->value.i = priv->vlan; ++ return 0; ++} ++ ++static int ++ar40xx_sw_set_mirror_rx_enable(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ ++ mutex_lock(&priv->reg_mutex); ++ priv->mirror_rx = !!val->value.i; ++ ar40xx_set_mirror_regs(priv); ++ mutex_unlock(&priv->reg_mutex); ++ ++ return 0; ++} ++ ++static int ++ar40xx_sw_get_mirror_rx_enable(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ ++ mutex_lock(&priv->reg_mutex); ++ val->value.i = priv->mirror_rx; ++ mutex_unlock(&priv->reg_mutex); ++ return 0; ++} ++ ++static int ++ar40xx_sw_set_mirror_tx_enable(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ ++ mutex_lock(&priv->reg_mutex); ++ priv->mirror_tx = !!val->value.i; ++ ar40xx_set_mirror_regs(priv); ++ mutex_unlock(&priv->reg_mutex); ++ ++ return 0; ++} ++ ++static int ++ar40xx_sw_get_mirror_tx_enable(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ ++ mutex_lock(&priv->reg_mutex); ++ val->value.i = priv->mirror_tx; ++ mutex_unlock(&priv->reg_mutex); ++ return 0; ++} ++ ++static int ++ar40xx_sw_set_mirror_monitor_port(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ ++ mutex_lock(&priv->reg_mutex); ++ priv->monitor_port = val->value.i; ++ ar40xx_set_mirror_regs(priv); ++ mutex_unlock(&priv->reg_mutex); ++ ++ return 0; ++} ++ ++static int ++ar40xx_sw_get_mirror_monitor_port(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ ++ mutex_lock(&priv->reg_mutex); ++ val->value.i = priv->monitor_port; ++ mutex_unlock(&priv->reg_mutex); ++ return 0; ++} ++ ++static int ++ar40xx_sw_set_mirror_source_port(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ ++ mutex_lock(&priv->reg_mutex); ++ priv->source_port = val->value.i; ++ ar40xx_set_mirror_regs(priv); ++ mutex_unlock(&priv->reg_mutex); ++ ++ return 0; ++} ++ ++static int ++ar40xx_sw_get_mirror_source_port(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ ++ mutex_lock(&priv->reg_mutex); ++ val->value.i = priv->source_port; ++ mutex_unlock(&priv->reg_mutex); ++ return 0; ++} ++ ++static int ++ar40xx_sw_set_linkdown(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ ++ if (val->value.i == 1) ++ ar40xx_port_phy_linkdown(priv); ++ else ++ ar40xx_phy_init(priv); ++ ++ return 0; ++} ++ ++static int ++ar40xx_sw_set_port_reset_mib(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ int port; ++ int ret; ++ ++ port = val->port_vlan; ++ if (port >= dev->ports) ++ return -EINVAL; ++ ++ mutex_lock(&priv->mib_lock); ++ ret = ar40xx_mib_capture(priv); ++ if (ret) ++ goto unlock; ++ ++ ar40xx_mib_fetch_port_stat(priv, port, true); ++ ++unlock: ++ mutex_unlock(&priv->mib_lock); ++ return ret; ++} ++ ++static int ++ar40xx_sw_get_port_mib(struct switch_dev *dev, ++ const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ u64 *mib_stats; ++ int port; ++ int ret; ++ char *buf = priv->buf; ++ int i, len = 0; ++ u32 num_mibs = ARRAY_SIZE(ar40xx_mibs); ++ ++ port = val->port_vlan; ++ if (port >= dev->ports) ++ return -EINVAL; ++ ++ mutex_lock(&priv->mib_lock); ++ ret = ar40xx_mib_capture(priv); ++ if (ret) ++ goto unlock; ++ ++ ar40xx_mib_fetch_port_stat(priv, port, false); ++ ++ len += snprintf(buf + len, sizeof(priv->buf) - len, ++ "Port %d MIB counters\n", ++ port); ++ ++ mib_stats = &priv->mib_stats[port * num_mibs]; ++ for (i = 0; i < num_mibs; i++) ++ len += snprintf(buf + len, sizeof(priv->buf) - len, ++ "%-12s: %llu\n", ++ ar40xx_mibs[i].name, ++ mib_stats[i]); ++ ++ val->value.s = buf; ++ val->len = len; ++ ++unlock: ++ mutex_unlock(&priv->mib_lock); ++ return ret; ++} ++ ++static int ++ar40xx_sw_set_vid(struct switch_dev *dev, const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ ++ priv->vlan_id[val->port_vlan] = val->value.i; ++ return 0; ++} ++ ++static int ++ar40xx_sw_get_vid(struct switch_dev *dev, const struct switch_attr *attr, ++ struct switch_val *val) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ ++ val->value.i = priv->vlan_id[val->port_vlan]; ++ return 0; ++} ++ ++static int ++ar40xx_sw_get_pvid(struct switch_dev *dev, int port, int *vlan) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ *vlan = priv->pvid[port]; ++ return 0; ++} ++ ++static int ++ar40xx_sw_set_pvid(struct switch_dev *dev, int port, int vlan) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ ++ /* make sure no invalid PVIDs get set */ ++ if (vlan >= dev->vlans) ++ return -EINVAL; ++ ++ priv->pvid[port] = vlan; ++ return 0; ++} ++ ++static void ++ar40xx_read_port_link(struct ar40xx_priv *priv, int port, ++ struct switch_port_link *link) ++{ ++ u32 status; ++ u32 speed; ++ ++ memset(link, 0, sizeof(*link)); ++ ++ status = ar40xx_read(priv, AR40XX_REG_PORT_STATUS(port)); ++ ++ link->aneg = !!(status & AR40XX_PORT_AUTO_LINK_EN); ++ if (link->aneg || (port != AR40XX_PORT_CPU)) ++ link->link = !!(status & AR40XX_PORT_STATUS_LINK_UP); ++ else ++ link->link = true; ++ ++ if (!link->link) ++ return; ++ ++ link->duplex = !!(status & AR40XX_PORT_DUPLEX); ++ link->tx_flow = !!(status & AR40XX_PORT_STATUS_TXFLOW); ++ link->rx_flow = !!(status & AR40XX_PORT_STATUS_RXFLOW); ++ ++ speed = (status & AR40XX_PORT_SPEED) >> ++ AR40XX_PORT_STATUS_SPEED_S; ++ ++ switch (speed) { ++ case AR40XX_PORT_SPEED_10M: ++ link->speed = SWITCH_PORT_SPEED_10; ++ break; ++ case AR40XX_PORT_SPEED_100M: ++ link->speed = SWITCH_PORT_SPEED_100; ++ break; ++ case AR40XX_PORT_SPEED_1000M: ++ link->speed = SWITCH_PORT_SPEED_1000; ++ break; ++ default: ++ link->speed = SWITCH_PORT_SPEED_UNKNOWN; ++ break; ++ } ++} ++ ++static int ++ar40xx_sw_get_port_link(struct switch_dev *dev, int port, ++ struct switch_port_link *link) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ ++ ar40xx_read_port_link(priv, port, link); ++ return 0; ++} ++ ++static const struct switch_attr ar40xx_sw_attr_globals[] = { ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "enable_vlan", ++ .description = "Enable VLAN mode", ++ .set = ar40xx_sw_set_vlan, ++ .get = ar40xx_sw_get_vlan, ++ .max = 1 ++ }, ++ { ++ .type = SWITCH_TYPE_NOVAL, ++ .name = "reset_mibs", ++ .description = "Reset all MIB counters", ++ .set = ar40xx_sw_set_reset_mibs, ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "enable_mirror_rx", ++ .description = "Enable mirroring of RX packets", ++ .set = ar40xx_sw_set_mirror_rx_enable, ++ .get = ar40xx_sw_get_mirror_rx_enable, ++ .max = 1 ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "enable_mirror_tx", ++ .description = "Enable mirroring of TX packets", ++ .set = ar40xx_sw_set_mirror_tx_enable, ++ .get = ar40xx_sw_get_mirror_tx_enable, ++ .max = 1 ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "mirror_monitor_port", ++ .description = "Mirror monitor port", ++ .set = ar40xx_sw_set_mirror_monitor_port, ++ .get = ar40xx_sw_get_mirror_monitor_port, ++ .max = AR40XX_NUM_PORTS - 1 ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "mirror_source_port", ++ .description = "Mirror source port", ++ .set = ar40xx_sw_set_mirror_source_port, ++ .get = ar40xx_sw_get_mirror_source_port, ++ .max = AR40XX_NUM_PORTS - 1 ++ }, ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "linkdown", ++ .description = "Link down all the PHYs", ++ .set = ar40xx_sw_set_linkdown, ++ .max = 1 ++ }, ++}; ++ ++static const struct switch_attr ar40xx_sw_attr_port[] = { ++ { ++ .type = SWITCH_TYPE_NOVAL, ++ .name = "reset_mib", ++ .description = "Reset single port MIB counters", ++ .set = ar40xx_sw_set_port_reset_mib, ++ }, ++ { ++ .type = SWITCH_TYPE_STRING, ++ .name = "mib", ++ .description = "Get port's MIB counters", ++ .set = NULL, ++ .get = ar40xx_sw_get_port_mib, ++ }, ++}; ++ ++const struct switch_attr ar40xx_sw_attr_vlan[] = { ++ { ++ .type = SWITCH_TYPE_INT, ++ .name = "vid", ++ .description = "VLAN ID (0-4094)", ++ .set = ar40xx_sw_set_vid, ++ .get = ar40xx_sw_get_vid, ++ .max = 4094, ++ }, ++}; ++ ++/* End of swconfig support */ ++ ++static int ++ar40xx_wait_bit(struct ar40xx_priv *priv, int reg, u32 mask, u32 val) ++{ ++ int timeout = 20; ++ u32 t; ++ ++ while (1) { ++ t = ar40xx_read(priv, reg); ++ if ((t & mask) == val) ++ return 0; ++ ++ if (timeout-- <= 0) ++ break; ++ ++ usleep_range(10, 20); ++ } ++ ++ pr_err("ar40xx: timeout for reg %08x: %08x & %08x != %08x\n", ++ (unsigned int)reg, t, mask, val); ++ return -ETIMEDOUT; ++} ++ ++static int ++ar40xx_atu_flush(struct ar40xx_priv *priv) ++{ ++ int ret; ++ ++ ret = ar40xx_wait_bit(priv, AR40XX_REG_ATU_FUNC, ++ AR40XX_ATU_FUNC_BUSY, 0); ++ if (!ret) ++ ar40xx_write(priv, AR40XX_REG_ATU_FUNC, ++ AR40XX_ATU_FUNC_OP_FLUSH | ++ AR40XX_ATU_FUNC_BUSY); ++ ++ return ret; ++} ++ ++static void ++ar40xx_ess_reset(struct ar40xx_priv *priv) ++{ ++ reset_control_assert(priv->ess_rst); ++ mdelay(10); ++ reset_control_deassert(priv->ess_rst); ++ /* Waiting for all inner tables init done. ++ * It cost 5~10ms. ++ */ ++ mdelay(10); ++ ++ pr_info("ESS reset ok!\n"); ++} ++ ++/* Start of psgmii self test */ ++ ++static void ++ar40xx_malibu_psgmii_ess_reset(struct ar40xx_priv *priv) ++{ ++ u32 n; ++ struct mii_bus *bus = priv->mii_bus; ++ /* reset phy psgmii */ ++ /* fix phy psgmii RX 20bit */ ++ mdiobus_write(bus, 5, 0x0, 0x005b); ++ /* reset phy psgmii */ ++ mdiobus_write(bus, 5, 0x0, 0x001b); ++ /* release reset phy psgmii */ ++ mdiobus_write(bus, 5, 0x0, 0x005b); ++ ++ for (n = 0; n < AR40XX_PSGMII_CALB_NUM; n++) { ++ u16 status; ++ ++ status = ar40xx_phy_mmd_read(priv, 5, 1, 0x28); ++ if (status & BIT(0)) ++ break; ++ /* Polling interval to check PSGMII PLL in malibu is ready ++ * the worst time is 8.67ms ++ * for 25MHz reference clock ++ * [512+(128+2048)*49]*80ns+100us ++ */ ++ mdelay(2); ++ } ++ ++ /*check malibu psgmii calibration done end..*/ ++ ++ /*freeze phy psgmii RX CDR*/ ++ mdiobus_write(bus, 5, 0x1a, 0x2230); ++ ++ ar40xx_ess_reset(priv); ++ ++ /*check psgmii calibration done start*/ ++ for (n = 0; n < AR40XX_PSGMII_CALB_NUM; n++) { ++ u32 status; ++ ++ status = ar40xx_psgmii_read(priv, 0xa0); ++ if (status & BIT(0)) ++ break; ++ /* Polling interval to check PSGMII PLL in ESS is ready */ ++ mdelay(2); ++ } ++ ++ /* check dakota psgmii calibration done end..*/ ++ ++ /* relesae phy psgmii RX CDR */ ++ mdiobus_write(bus, 5, 0x1a, 0x3230); ++ /* release phy psgmii RX 20bit */ ++ mdiobus_write(bus, 5, 0x0, 0x005f); ++} ++ ++static void ++ar40xx_psgmii_single_phy_testing(struct ar40xx_priv *priv, int phy) ++{ ++ int j; ++ u32 tx_ok, tx_error; ++ u32 rx_ok, rx_error; ++ u32 tx_ok_high16; ++ u32 rx_ok_high16; ++ u32 tx_all_ok, rx_all_ok; ++ struct mii_bus *bus = priv->mii_bus; ++ ++ mdiobus_write(bus, phy, 0x0, 0x9000); ++ mdiobus_write(bus, phy, 0x0, 0x4140); ++ ++ for (j = 0; j < AR40XX_PSGMII_CALB_NUM; j++) { ++ u16 status; ++ ++ status = mdiobus_read(bus, phy, 0x11); ++ if (status & AR40XX_PHY_SPEC_STATUS_LINK) ++ break; ++ /* the polling interval to check if the PHY link up or not ++ * maxwait_timer: 750 ms +/-10 ms ++ * minwait_timer : 1 us +/- 0.1us ++ * time resides in minwait_timer ~ maxwait_timer ++ * see IEEE 802.3 section 40.4.5.2 ++ */ ++ mdelay(8); ++ } ++ ++ /* enable check */ ++ ar40xx_phy_mmd_write(priv, phy, 7, 0x8029, 0x0000); ++ ar40xx_phy_mmd_write(priv, phy, 7, 0x8029, 0x0003); ++ ++ /* start traffic */ ++ ar40xx_phy_mmd_write(priv, phy, 7, 0x8020, 0xa000); ++ /* wait for all traffic end ++ * 4096(pkt num)*1524(size)*8ns(125MHz)=49.9ms ++ */ ++ mdelay(50); ++ ++ /* check counter */ ++ tx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802e); ++ tx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802d); ++ tx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802f); ++ rx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802b); ++ rx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802a); ++ rx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802c); ++ tx_all_ok = tx_ok + (tx_ok_high16 << 16); ++ rx_all_ok = rx_ok + (rx_ok_high16 << 16); ++ if (tx_all_ok == 0x1000 && tx_error == 0) { ++ /* success */ ++ priv->phy_t_status &= (~BIT(phy)); ++ } else { ++ pr_info("PHY %d single test PSGMII issue happen!\n", phy); ++ priv->phy_t_status |= BIT(phy); ++ } ++ ++ mdiobus_write(bus, phy, 0x0, 0x1840); ++} ++ ++static void ++ar40xx_psgmii_all_phy_testing(struct ar40xx_priv *priv) ++{ ++ int phy, j; ++ struct mii_bus *bus = priv->mii_bus; ++ ++ mdiobus_write(bus, 0x1f, 0x0, 0x9000); ++ mdiobus_write(bus, 0x1f, 0x0, 0x4140); ++ ++ for (j = 0; j < AR40XX_PSGMII_CALB_NUM; j++) { ++ for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { ++ u16 status; ++ ++ status = mdiobus_read(bus, phy, 0x11); ++ if (!(status & BIT(10))) ++ break; ++ } ++ ++ if (phy >= (AR40XX_NUM_PORTS - 1)) ++ break; ++ /* The polling interva to check if the PHY link up or not */ ++ mdelay(8); ++ } ++ /* enable check */ ++ ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8029, 0x0000); ++ ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8029, 0x0003); ++ ++ /* start traffic */ ++ ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8020, 0xa000); ++ /* wait for all traffic end ++ * 4096(pkt num)*1524(size)*8ns(125MHz)=49.9ms ++ */ ++ mdelay(50); ++ ++ for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { ++ u32 tx_ok, tx_error; ++ u32 rx_ok, rx_error; ++ u32 tx_ok_high16; ++ u32 rx_ok_high16; ++ u32 tx_all_ok, rx_all_ok; ++ ++ /* check counter */ ++ tx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802e); ++ tx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802d); ++ tx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802f); ++ rx_ok = ar40xx_phy_mmd_read(priv, phy, 7, 0x802b); ++ rx_ok_high16 = ar40xx_phy_mmd_read(priv, phy, 7, 0x802a); ++ rx_error = ar40xx_phy_mmd_read(priv, phy, 7, 0x802c); ++ tx_all_ok = tx_ok + (tx_ok_high16<<16); ++ rx_all_ok = rx_ok + (rx_ok_high16<<16); ++ if (tx_all_ok == 0x1000 && tx_error == 0) { ++ /* success */ ++ priv->phy_t_status &= ~BIT(phy + 8); ++ } else { ++ pr_info("PHY%d test see issue!\n", phy); ++ priv->phy_t_status |= BIT(phy + 8); ++ } ++ } ++ ++ pr_debug("PHY all test 0x%x \r\n", priv->phy_t_status); ++} ++ ++void ++ar40xx_psgmii_self_test(struct ar40xx_priv *priv) ++{ ++ u32 i, phy; ++ struct mii_bus *bus = priv->mii_bus; ++ ++ ar40xx_malibu_psgmii_ess_reset(priv); ++ ++ /* switch to access MII reg for copper */ ++ mdiobus_write(bus, 4, 0x1f, 0x8500); ++ for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { ++ /*enable phy mdio broadcast write*/ ++ ar40xx_phy_mmd_write(priv, phy, 7, 0x8028, 0x801f); ++ } ++ /* force no link by power down */ ++ mdiobus_write(bus, 0x1f, 0x0, 0x1840); ++ /*packet number*/ ++ ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8021, 0x1000); ++ ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8062, 0x05e0); ++ ++ /*fix mdi status */ ++ mdiobus_write(bus, 0x1f, 0x10, 0x6800); ++ for (i = 0; i < AR40XX_PSGMII_CALB_NUM; i++) { ++ priv->phy_t_status = 0; ++ ++ for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { ++ ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(phy + 1), ++ AR40XX_PORT_LOOKUP_LOOPBACK, ++ AR40XX_PORT_LOOKUP_LOOPBACK); ++ } ++ ++ for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) ++ ar40xx_psgmii_single_phy_testing(priv, phy); ++ ++ ar40xx_psgmii_all_phy_testing(priv); ++ ++ if (priv->phy_t_status) ++ ar40xx_malibu_psgmii_ess_reset(priv); ++ else ++ break; ++ } ++ ++ if (i >= AR40XX_PSGMII_CALB_NUM) ++ pr_info("PSGMII cannot recover\n"); ++ else ++ pr_debug("PSGMII recovered after %d times reset\n", i); ++ ++ /* configuration recover */ ++ /* packet number */ ++ ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8021, 0x0); ++ /* disable check */ ++ ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8029, 0x0); ++ /* disable traffic */ ++ ar40xx_phy_mmd_write(priv, 0x1f, 7, 0x8020, 0x0); ++} ++ ++void ++ar40xx_psgmii_self_test_clean(struct ar40xx_priv *priv) ++{ ++ int phy; ++ struct mii_bus *bus = priv->mii_bus; ++ ++ /* disable phy internal loopback */ ++ mdiobus_write(bus, 0x1f, 0x10, 0x6860); ++ mdiobus_write(bus, 0x1f, 0x0, 0x9040); ++ ++ for (phy = 0; phy < AR40XX_NUM_PORTS - 1; phy++) { ++ /* disable mac loop back */ ++ ar40xx_rmw(priv, AR40XX_REG_PORT_LOOKUP(phy + 1), ++ AR40XX_PORT_LOOKUP_LOOPBACK, 0); ++ /* disable phy mdio broadcast write */ ++ ar40xx_phy_mmd_write(priv, phy, 7, 0x8028, 0x001f); ++ } ++ ++ /* clear fdb entry */ ++ ar40xx_atu_flush(priv); ++} ++ ++/* End of psgmii self test */ ++ ++static void ++ar40xx_mac_mode_init(struct ar40xx_priv *priv, u32 mode) ++{ ++ if (mode == PORT_WRAPPER_PSGMII) { ++ ar40xx_psgmii_write(priv, AR40XX_PSGMII_MODE_CONTROL, 0x2200); ++ ar40xx_psgmii_write(priv, AR40XX_PSGMIIPHY_TX_CONTROL, 0x8380); ++ } ++} ++ ++static ++int ar40xx_cpuport_setup(struct ar40xx_priv *priv) ++{ ++ u32 t; ++ ++ t = AR40XX_PORT_STATUS_TXFLOW | ++ AR40XX_PORT_STATUS_RXFLOW | ++ AR40XX_PORT_TXHALF_FLOW | ++ AR40XX_PORT_DUPLEX | ++ AR40XX_PORT_SPEED_1000M; ++ ar40xx_write(priv, AR40XX_REG_PORT_STATUS(0), t); ++ usleep_range(10, 20); ++ ++ t |= AR40XX_PORT_TX_EN | ++ AR40XX_PORT_RX_EN; ++ ar40xx_write(priv, AR40XX_REG_PORT_STATUS(0), t); ++ ++ return 0; ++} ++ ++static void ++ar40xx_init_port(struct ar40xx_priv *priv, int port) ++{ ++ u32 t; ++ ++ ar40xx_rmw(priv, AR40XX_REG_PORT_STATUS(port), ++ AR40XX_PORT_AUTO_LINK_EN, 0); ++ ++ ar40xx_write(priv, AR40XX_REG_PORT_HEADER(port), 0); ++ ++ ar40xx_write(priv, AR40XX_REG_PORT_VLAN0(port), 0); ++ ++ t = AR40XX_PORT_VLAN1_OUT_MODE_UNTOUCH << AR40XX_PORT_VLAN1_OUT_MODE_S; ++ ar40xx_write(priv, AR40XX_REG_PORT_VLAN1(port), t); ++ ++ t = AR40XX_PORT_LOOKUP_LEARN; ++ t |= AR40XX_PORT_STATE_FORWARD << AR40XX_PORT_LOOKUP_STATE_S; ++ ar40xx_write(priv, AR40XX_REG_PORT_LOOKUP(port), t); ++} ++ ++void ++ar40xx_init_globals(struct ar40xx_priv *priv) ++{ ++ u32 t; ++ ++ /* enable CPU port and disable mirror port */ ++ t = AR40XX_FWD_CTRL0_CPU_PORT_EN | ++ AR40XX_FWD_CTRL0_MIRROR_PORT; ++ ar40xx_write(priv, AR40XX_REG_FWD_CTRL0, t); ++ ++ /* forward multicast and broadcast frames to CPU */ ++ t = (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_UC_FLOOD_S) | ++ (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_MC_FLOOD_S) | ++ (AR40XX_PORTS_ALL << AR40XX_FWD_CTRL1_BC_FLOOD_S); ++ ar40xx_write(priv, AR40XX_REG_FWD_CTRL1, t); ++ ++ /* enable jumbo frames */ ++ ar40xx_rmw(priv, AR40XX_REG_MAX_FRAME_SIZE, ++ AR40XX_MAX_FRAME_SIZE_MTU, 9018 + 8 + 2); ++ ++ /* Enable MIB counters */ ++ ar40xx_rmw(priv, AR40XX_REG_MODULE_EN, 0, ++ AR40XX_MODULE_EN_MIB); ++ ++ /* Disable AZ */ ++ ar40xx_write(priv, AR40XX_REG_EEE_CTRL, 0); ++ ++ /* set flowctrl thershold for cpu port */ ++ t = (AR40XX_PORT0_FC_THRESH_ON_DFLT << 16) | ++ AR40XX_PORT0_FC_THRESH_OFF_DFLT; ++ ar40xx_write(priv, AR40XX_REG_PORT_FLOWCTRL_THRESH(0), t); ++} ++ ++static void ++ar40xx_malibu_init(struct ar40xx_priv *priv) ++{ ++ int i; ++ struct mii_bus *bus; ++ u16 val; ++ ++ bus = priv->mii_bus; ++ ++ /* war to enable AZ transmitting ability */ ++ ar40xx_phy_mmd_write(priv, AR40XX_PSGMII_ID, 1, ++ AR40XX_MALIBU_PSGMII_MODE_CTRL, ++ AR40XX_MALIBU_PHY_PSGMII_MODE_CTRL_ADJUST_VAL); ++ for (i = 0; i < AR40XX_NUM_PORTS - 1; i++) { ++ /* change malibu control_dac */ ++ val = ar40xx_phy_mmd_read(priv, i, 7, ++ AR40XX_MALIBU_PHY_MMD7_DAC_CTRL); ++ val &= ~AR40XX_MALIBU_DAC_CTRL_MASK; ++ val |= AR40XX_MALIBU_DAC_CTRL_VALUE; ++ ar40xx_phy_mmd_write(priv, i, 7, ++ AR40XX_MALIBU_PHY_MMD7_DAC_CTRL, val); ++ if (i == AR40XX_MALIBU_PHY_LAST_ADDR) { ++ /* to avoid goes into hibernation */ ++ val = ar40xx_phy_mmd_read(priv, i, 3, ++ AR40XX_MALIBU_PHY_RLP_CTRL); ++ val &= (~(1<<1)); ++ ar40xx_phy_mmd_write(priv, i, 3, ++ AR40XX_MALIBU_PHY_RLP_CTRL, val); ++ } ++ } ++ ++ /* adjust psgmii serdes tx amp */ ++ mdiobus_write(bus, AR40XX_PSGMII_ID, AR40XX_PSGMII_TX_DRIVER_1_CTRL, ++ AR40XX_MALIBU_PHY_PSGMII_REDUCE_SERDES_TX_AMP); ++} ++ ++static int ++ar40xx_hw_init(struct ar40xx_priv *priv) ++{ ++ u32 i; ++ ++ ar40xx_ess_reset(priv); ++ ++ if (priv->mii_bus) ++ ar40xx_malibu_init(priv); ++ else ++ return -1; ++ ++ ar40xx_psgmii_self_test(priv); ++ ar40xx_psgmii_self_test_clean(priv); ++ ++ ar40xx_mac_mode_init(priv, priv->mac_mode); ++ ++ for (i = 0; i < priv->dev.ports; i++) ++ ar40xx_init_port(priv, i); ++ ++ ar40xx_init_globals(priv); ++ ++ return 0; ++} ++ ++/* Start of qm error WAR */ ++ ++static ++int ar40xx_force_1g_full(struct ar40xx_priv *priv, u32 port_id) ++{ ++ u32 reg; ++ ++ if (port_id < 0 || port_id > 6) ++ return -1; ++ ++ reg = AR40XX_REG_PORT_STATUS(port_id); ++ return ar40xx_rmw(priv, reg, AR40XX_PORT_SPEED, ++ (AR40XX_PORT_SPEED_1000M | AR40XX_PORT_DUPLEX)); ++} ++ ++static ++int ar40xx_get_qm_status(struct ar40xx_priv *priv, ++ u32 port_id, u32 *qm_buffer_err) ++{ ++ u32 reg; ++ u32 qm_val; ++ ++ if (port_id < 1 || port_id > 5) { ++ *qm_buffer_err = 0; ++ return -1; ++ } ++ ++ if (port_id < 4) { ++ reg = AR40XX_REG_QM_PORT0_3_QNUM; ++ ar40xx_write(priv, AR40XX_REG_QM_DEBUG_ADDR, reg); ++ qm_val = ar40xx_read(priv, AR40XX_REG_QM_DEBUG_VALUE); ++ /* every 8 bits for each port */ ++ *qm_buffer_err = (qm_val >> (port_id * 8)) & 0xFF; ++ } else { ++ reg = AR40XX_REG_QM_PORT4_6_QNUM; ++ ar40xx_write(priv, AR40XX_REG_QM_DEBUG_ADDR, reg); ++ qm_val = ar40xx_read(priv, AR40XX_REG_QM_DEBUG_VALUE); ++ /* every 8 bits for each port */ ++ *qm_buffer_err = (qm_val >> ((port_id-4) * 8)) & 0xFF; ++ } ++ ++ return 0; ++} ++ ++static void ++ar40xx_sw_mac_polling_task(struct ar40xx_priv *priv) ++{ ++ static int task_count; ++ u32 i; ++ u32 reg, value; ++ u32 link, speed, duplex; ++ u32 qm_buffer_err; ++ u16 port_phy_status[AR40XX_NUM_PORTS]; ++ static u32 qm_err_cnt[AR40XX_NUM_PORTS] = {0, 0, 0, 0, 0, 0}; ++ static u32 link_cnt[AR40XX_NUM_PORTS] = {0, 0, 0, 0, 0, 0}; ++ struct mii_bus *bus = NULL; ++ ++ if (!priv || !priv->mii_bus) ++ return; ++ ++ bus = priv->mii_bus; ++ ++ ++task_count; ++ ++ for (i = 1; i < AR40XX_NUM_PORTS; ++i) { ++ port_phy_status[i] = ++ mdiobus_read(bus, i-1, AR40XX_PHY_SPEC_STATUS); ++ speed = link = duplex = port_phy_status[i]; ++ speed &= AR40XX_PHY_SPEC_STATUS_SPEED; ++ speed >>= 14; ++ link &= AR40XX_PHY_SPEC_STATUS_LINK; ++ link >>= 10; ++ duplex &= AR40XX_PHY_SPEC_STATUS_DUPLEX; ++ duplex >>= 13; ++ ++ if (link != priv->ar40xx_port_old_link[i]) { ++ ++link_cnt[i]; ++ /* Up --> Down */ ++ if ((priv->ar40xx_port_old_link[i] == ++ AR40XX_PORT_LINK_UP) && ++ (link == AR40XX_PORT_LINK_DOWN)) { ++ /* LINK_EN disable(MAC force mode)*/ ++ reg = AR40XX_REG_PORT_STATUS(i); ++ ar40xx_rmw(priv, reg, ++ AR40XX_PORT_AUTO_LINK_EN, 0); ++ ++ /* Check queue buffer */ ++ qm_err_cnt[i] = 0; ++ ar40xx_get_qm_status(priv, i, &qm_buffer_err); ++ if (qm_buffer_err) { ++ priv->ar40xx_port_qm_buf[i] = ++ AR40XX_QM_NOT_EMPTY; ++ } else { ++ u16 phy_val = 0; ++ ++ priv->ar40xx_port_qm_buf[i] = ++ AR40XX_QM_EMPTY; ++ ar40xx_force_1g_full(priv, i); ++ /* Ref:QCA8337 Datasheet,Clearing ++ * MENU_CTRL_EN prevents phy to ++ * stuck in 100BT mode when ++ * bringing up the link ++ */ ++ ar40xx_phy_dbg_read(priv, i-1, ++ AR40XX_PHY_DEBUG_0, ++ &phy_val); ++ phy_val &= (~AR40XX_PHY_MANU_CTRL_EN); ++ ar40xx_phy_dbg_write(priv, i-1, ++ AR40XX_PHY_DEBUG_0, ++ phy_val); ++ } ++ priv->ar40xx_port_old_link[i] = link; ++ } else if ((priv->ar40xx_port_old_link[i] == ++ AR40XX_PORT_LINK_DOWN) && ++ (link == AR40XX_PORT_LINK_UP)) { ++ /* Down --> Up */ ++ if (priv->port_link_up[i] < 1) { ++ ++priv->port_link_up[i]; ++ } else { ++ /* Change port status */ ++ reg = AR40XX_REG_PORT_STATUS(i); ++ value = ar40xx_read(priv, reg); ++ priv->port_link_up[i] = 0; ++ ++ value &= ~(AR40XX_PORT_DUPLEX | ++ AR40XX_PORT_SPEED); ++ value |= speed | (duplex ? BIT(6) : 0); ++ ar40xx_write(priv, reg, value); ++ /* clock switch need such time ++ * to avoid glitch ++ */ ++ usleep_range(100, 200); ++ ++ value |= AR40XX_PORT_AUTO_LINK_EN; ++ ar40xx_write(priv, reg, value); ++ /* HW need such time to make sure link ++ * stable before enable MAC ++ */ ++ usleep_range(100, 200); ++ ++ if (speed == AR40XX_PORT_SPEED_100M) { ++ u16 phy_val = 0; ++ /* Enable @100M, if down to 10M ++ * clock will change smoothly ++ */ ++ ar40xx_phy_dbg_read(priv, i-1, ++ 0, ++ &phy_val); ++ phy_val |= ++ AR40XX_PHY_MANU_CTRL_EN; ++ ar40xx_phy_dbg_write(priv, i-1, ++ 0, ++ phy_val); ++ } ++ priv->ar40xx_port_old_link[i] = link; ++ } ++ } ++ } ++ ++ if (priv->ar40xx_port_qm_buf[i] == AR40XX_QM_NOT_EMPTY) { ++ /* Check QM */ ++ ar40xx_get_qm_status(priv, i, &qm_buffer_err); ++ if (qm_buffer_err) { ++ ++qm_err_cnt[i]; ++ } else { ++ priv->ar40xx_port_qm_buf[i] = ++ AR40XX_QM_EMPTY; ++ qm_err_cnt[i] = 0; ++ ar40xx_force_1g_full(priv, i); ++ } ++ } ++ } ++} ++ ++static void ++ar40xx_qm_err_check_work_task(struct work_struct *work) ++{ ++ struct ar40xx_priv *priv = container_of(work, struct ar40xx_priv, ++ qm_dwork.work); ++ ++ mutex_lock(&priv->qm_lock); ++ ++ ar40xx_sw_mac_polling_task(priv); ++ ++ mutex_unlock(&priv->qm_lock); ++ ++ schedule_delayed_work(&priv->qm_dwork, ++ msecs_to_jiffies(AR40XX_QM_WORK_DELAY)); ++} ++ ++static int ++ar40xx_qm_err_check_work_start(struct ar40xx_priv *priv) ++{ ++ mutex_init(&priv->qm_lock); ++ ++ INIT_DELAYED_WORK(&priv->qm_dwork, ar40xx_qm_err_check_work_task); ++ ++ schedule_delayed_work(&priv->qm_dwork, ++ msecs_to_jiffies(AR40XX_QM_WORK_DELAY)); ++ ++ return 0; ++} ++ ++/* End of qm error WAR */ ++ ++static int ++ar40xx_vlan_init(struct ar40xx_priv *priv) ++{ ++ int port; ++ unsigned long bmp; ++ ++ /* By default Enable VLAN */ ++ priv->vlan = 1; ++ priv->vlan_table[AR40XX_LAN_VLAN] = priv->cpu_bmp | priv->lan_bmp; ++ priv->vlan_table[AR40XX_WAN_VLAN] = priv->cpu_bmp | priv->wan_bmp; ++ priv->vlan_tagged = priv->cpu_bmp; ++ bmp = priv->lan_bmp; ++ for_each_set_bit(port, &bmp, AR40XX_NUM_PORTS) ++ priv->pvid[port] = AR40XX_LAN_VLAN; ++ ++ bmp = priv->wan_bmp; ++ for_each_set_bit(port, &bmp, AR40XX_NUM_PORTS) ++ priv->pvid[port] = AR40XX_WAN_VLAN; ++ ++ return 0; ++} ++ ++static void ++ar40xx_mib_work_func(struct work_struct *work) ++{ ++ struct ar40xx_priv *priv; ++ int err; ++ ++ priv = container_of(work, struct ar40xx_priv, mib_work.work); ++ ++ mutex_lock(&priv->mib_lock); ++ ++ err = ar40xx_mib_capture(priv); ++ if (err) ++ goto next_port; ++ ++ ar40xx_mib_fetch_port_stat(priv, priv->mib_next_port, false); ++ ++next_port: ++ priv->mib_next_port++; ++ if (priv->mib_next_port >= priv->dev.ports) ++ priv->mib_next_port = 0; ++ ++ mutex_unlock(&priv->mib_lock); ++ ++ schedule_delayed_work(&priv->mib_work, ++ msecs_to_jiffies(AR40XX_MIB_WORK_DELAY)); ++} ++ ++static void ++ar40xx_setup_port(struct ar40xx_priv *priv, int port, u32 members) ++{ ++ u32 t; ++ u32 egress, ingress; ++ u32 pvid = priv->vlan_id[priv->pvid[port]]; ++ ++ if (priv->vlan) { ++ egress = AR40XX_PORT_VLAN1_OUT_MODE_UNMOD; ++ ingress = AR40XX_IN_SECURE; ++ } else { ++ egress = AR40XX_PORT_VLAN1_OUT_MODE_UNTOUCH; ++ ingress = AR40XX_IN_PORT_ONLY; ++ } ++ ++ t = pvid << AR40XX_PORT_VLAN0_DEF_SVID_S; ++ t |= pvid << AR40XX_PORT_VLAN0_DEF_CVID_S; ++ ar40xx_write(priv, AR40XX_REG_PORT_VLAN0(port), t); ++ ++ t = AR40XX_PORT_VLAN1_PORT_VLAN_PROP; ++ t |= egress << AR40XX_PORT_VLAN1_OUT_MODE_S; ++ ar40xx_write(priv, AR40XX_REG_PORT_VLAN1(port), t); ++ ++ t = members; ++ t |= AR40XX_PORT_LOOKUP_LEARN; ++ t |= ingress << AR40XX_PORT_LOOKUP_IN_MODE_S; ++ t |= AR40XX_PORT_STATE_FORWARD << AR40XX_PORT_LOOKUP_STATE_S; ++ ar40xx_write(priv, AR40XX_REG_PORT_LOOKUP(port), t); ++} ++ ++static void ++ar40xx_vtu_op(struct ar40xx_priv *priv, u32 op, u32 val) ++{ ++ if (ar40xx_wait_bit(priv, AR40XX_REG_VTU_FUNC1, ++ AR40XX_VTU_FUNC1_BUSY, 0)) ++ return; ++ ++ if ((op & AR40XX_VTU_FUNC1_OP) == AR40XX_VTU_FUNC1_OP_LOAD) ++ ar40xx_write(priv, AR40XX_REG_VTU_FUNC0, val); ++ ++ op |= AR40XX_VTU_FUNC1_BUSY; ++ ar40xx_write(priv, AR40XX_REG_VTU_FUNC1, op); ++} ++ ++static void ++ar40xx_vtu_load_vlan(struct ar40xx_priv *priv, u32 vid, u32 port_mask) ++{ ++ u32 op; ++ u32 val; ++ int i; ++ ++ op = AR40XX_VTU_FUNC1_OP_LOAD | (vid << AR40XX_VTU_FUNC1_VID_S); ++ val = AR40XX_VTU_FUNC0_VALID | AR40XX_VTU_FUNC0_IVL; ++ for (i = 0; i < AR40XX_NUM_PORTS; i++) { ++ u32 mode; ++ ++ if ((port_mask & BIT(i)) == 0) ++ mode = AR40XX_VTU_FUNC0_EG_MODE_NOT; ++ else if (priv->vlan == 0) ++ mode = AR40XX_VTU_FUNC0_EG_MODE_KEEP; ++ else if ((priv->vlan_tagged & BIT(i)) || ++ (priv->vlan_id[priv->pvid[i]] != vid)) ++ mode = AR40XX_VTU_FUNC0_EG_MODE_TAG; ++ else ++ mode = AR40XX_VTU_FUNC0_EG_MODE_UNTAG; ++ ++ val |= mode << AR40XX_VTU_FUNC0_EG_MODE_S(i); ++ } ++ ar40xx_vtu_op(priv, op, val); ++} ++ ++static void ++ar40xx_vtu_flush(struct ar40xx_priv *priv) ++{ ++ ar40xx_vtu_op(priv, AR40XX_VTU_FUNC1_OP_FLUSH, 0); ++} ++ ++static int ++ar40xx_sw_hw_apply(struct switch_dev *dev) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ u8 portmask[AR40XX_NUM_PORTS]; ++ int i, j; ++ ++ mutex_lock(&priv->reg_mutex); ++ /* flush all vlan entries */ ++ ar40xx_vtu_flush(priv); ++ ++ memset(portmask, 0, sizeof(portmask)); ++ if (priv->vlan) { ++ for (j = 0; j < AR40XX_MAX_VLANS; j++) { ++ u8 vp = priv->vlan_table[j]; ++ ++ if (!vp) ++ continue; ++ ++ for (i = 0; i < dev->ports; i++) { ++ u8 mask = BIT(i); ++ ++ if (vp & mask) ++ portmask[i] |= vp & ~mask; ++ } ++ ++ ar40xx_vtu_load_vlan(priv, priv->vlan_id[j], ++ priv->vlan_table[j]); ++ } ++ } else { ++ /* 8021q vlan disabled */ ++ for (i = 0; i < dev->ports; i++) { ++ if (i == AR40XX_PORT_CPU) ++ continue; ++ ++ portmask[i] = BIT(AR40XX_PORT_CPU); ++ portmask[AR40XX_PORT_CPU] |= BIT(i); ++ } ++ } ++ ++ /* update the port destination mask registers and tag settings */ ++ for (i = 0; i < dev->ports; i++) ++ ar40xx_setup_port(priv, i, portmask[i]); ++ ++ ar40xx_set_mirror_regs(priv); ++ ++ mutex_unlock(&priv->reg_mutex); ++ return 0; ++} ++ ++static int ++ar40xx_sw_reset_switch(struct switch_dev *dev) ++{ ++ struct ar40xx_priv *priv = swdev_to_ar40xx(dev); ++ int i, rv; ++ ++ mutex_lock(&priv->reg_mutex); ++ memset(&priv->vlan, 0, sizeof(struct ar40xx_priv) - ++ offsetof(struct ar40xx_priv, vlan)); ++ ++ for (i = 0; i < AR40XX_MAX_VLANS; i++) ++ priv->vlan_id[i] = i; ++ ++ ar40xx_vlan_init(priv); ++ ++ priv->mirror_rx = false; ++ priv->mirror_tx = false; ++ priv->source_port = 0; ++ priv->monitor_port = 0; ++ ++ mutex_unlock(&priv->reg_mutex); ++ ++ rv = ar40xx_sw_hw_apply(dev); ++ return rv; ++} ++ ++static int ++ar40xx_start(struct ar40xx_priv *priv) ++{ ++ int ret; ++ ++ ret = ar40xx_hw_init(priv); ++ if (ret) ++ return ret; ++ ++ ret = ar40xx_sw_reset_switch(&priv->dev); ++ if (ret) ++ return ret; ++ ++ /* at last, setup cpu port */ ++ ret = ar40xx_cpuport_setup(priv); ++ if (ret) ++ return ret; ++ ++ schedule_delayed_work(&priv->mib_work, ++ msecs_to_jiffies(AR40XX_MIB_WORK_DELAY)); ++ ++ ar40xx_qm_err_check_work_start(priv); ++ ++ return 0; ++} ++ ++static const struct switch_dev_ops ar40xx_sw_ops = { ++ .attr_global = { ++ .attr = ar40xx_sw_attr_globals, ++ .n_attr = ARRAY_SIZE(ar40xx_sw_attr_globals), ++ }, ++ .attr_port = { ++ .attr = ar40xx_sw_attr_port, ++ .n_attr = ARRAY_SIZE(ar40xx_sw_attr_port), ++ }, ++ .attr_vlan = { ++ .attr = ar40xx_sw_attr_vlan, ++ .n_attr = ARRAY_SIZE(ar40xx_sw_attr_vlan), ++ }, ++ .get_port_pvid = ar40xx_sw_get_pvid, ++ .set_port_pvid = ar40xx_sw_set_pvid, ++ .get_vlan_ports = ar40xx_sw_get_ports, ++ .set_vlan_ports = ar40xx_sw_set_ports, ++ .apply_config = ar40xx_sw_hw_apply, ++ .reset_switch = ar40xx_sw_reset_switch, ++ .get_port_link = ar40xx_sw_get_port_link, ++}; ++ ++/* Start of phy driver support */ ++ ++static const u32 ar40xx_phy_ids[] = { ++ 0x004dd0b1, ++ 0x004dd0b2, /* AR40xx */ ++}; ++ ++static bool ++ar40xx_phy_match(u32 phy_id) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(ar40xx_phy_ids); i++) ++ if (phy_id == ar40xx_phy_ids[i]) ++ return true; ++ ++ return false; ++} ++ ++static bool ++is_ar40xx_phy(struct mii_bus *bus) ++{ ++ unsigned i; ++ ++ for (i = 0; i < 4; i++) { ++ u32 phy_id; ++ ++ phy_id = mdiobus_read(bus, i, MII_PHYSID1) << 16; ++ phy_id |= mdiobus_read(bus, i, MII_PHYSID2); ++ if (!ar40xx_phy_match(phy_id)) ++ return false; ++ } ++ ++ return true; ++} ++ ++static int ++ar40xx_phy_probe(struct phy_device *phydev) ++{ ++ if (!is_ar40xx_phy(phydev->mdio.bus)) ++ return -ENODEV; ++ ++ ar40xx_priv->mii_bus = phydev->mdio.bus; ++ phydev->priv = ar40xx_priv; ++ if (phydev->mdio.addr == 0) ++ ar40xx_priv->phy = phydev; ++ ++ phydev->supported |= SUPPORTED_1000baseT_Full; ++ phydev->advertising |= ADVERTISED_1000baseT_Full; ++ return 0; ++} ++ ++static void ++ar40xx_phy_remove(struct phy_device *phydev) ++{ ++ ar40xx_priv->mii_bus = NULL; ++ phydev->priv = NULL; ++} ++ ++static int ++ar40xx_phy_config_init(struct phy_device *phydev) ++{ ++ return 0; ++} ++ ++static int ++ar40xx_phy_read_status(struct phy_device *phydev) ++{ ++ if (phydev->mdio.addr != 0) ++ return genphy_read_status(phydev); ++ ++ return 0; ++} ++ ++static int ++ar40xx_phy_config_aneg(struct phy_device *phydev) ++{ ++ if (phydev->mdio.addr == 0) ++ return 0; ++ ++ return genphy_config_aneg(phydev); ++} ++ ++static struct phy_driver ar40xx_phy_driver = { ++ .phy_id = 0x004d0000, ++ .name = "QCA Malibu", ++ .phy_id_mask = 0xffff0000, ++ .features = PHY_BASIC_FEATURES, ++ .probe = ar40xx_phy_probe, ++ .remove = ar40xx_phy_remove, ++ .config_init = ar40xx_phy_config_init, ++ .config_aneg = ar40xx_phy_config_aneg, ++ .read_status = ar40xx_phy_read_status, ++}; ++ ++static uint16_t ar40xx_gpio_get_phy(unsigned int offset) ++{ ++ return offset / 4; ++} ++ ++static uint16_t ar40xx_gpio_get_reg(unsigned int offset) ++{ ++ return 0x8074 + offset % 4; ++} ++ ++static void ar40xx_gpio_set(struct gpio_chip *gc, unsigned int offset, ++ int value) ++{ ++ struct ar40xx_priv *priv = gpiochip_get_data(gc); ++ ++ ar40xx_phy_mmd_write(priv, ar40xx_gpio_get_phy(offset), 0x7, ++ ar40xx_gpio_get_reg(offset), ++ value ? 0xA000 : 0x8000); ++} ++ ++static int ar40xx_gpio_get(struct gpio_chip *gc, unsigned offset) ++{ ++ struct ar40xx_priv *priv = gpiochip_get_data(gc); ++ ++ return ar40xx_phy_mmd_read(priv, ar40xx_gpio_get_phy(offset), 0x7, ++ ar40xx_gpio_get_reg(offset)) == 0xA000; ++} ++ ++static int ar40xx_gpio_get_dir(struct gpio_chip *gc, unsigned offset) ++{ ++ return 0; /* only out direction */ ++} ++ ++static int ar40xx_gpio_dir_out(struct gpio_chip *gc, unsigned offset, ++ int value) ++{ ++ /* ++ * the direction out value is used to set the initial value. ++ * support of this function is required by leds-gpio.c ++ */ ++ ar40xx_gpio_set(gc, offset, value); ++ return 0; ++} ++ ++static void ar40xx_register_gpio(struct device *pdev, ++ struct ar40xx_priv *priv, ++ struct device_node *switch_node) ++{ ++ struct gpio_chip *gc; ++ int err; ++ ++ gc = devm_kzalloc(pdev, sizeof(*gc), GFP_KERNEL); ++ if (!gc) ++ return; ++ ++ gc->label = "ar40xx_gpio", ++ gc->base = -1, ++ gc->ngpio = 5 /* mmd 0 - 4 */ * 4 /* 0x8074 - 0x8077 */, ++ gc->parent = pdev; ++ gc->owner = THIS_MODULE; ++ ++ gc->get_direction = ar40xx_gpio_get_dir; ++ gc->direction_output = ar40xx_gpio_dir_out; ++ gc->get = ar40xx_gpio_get; ++ gc->set = ar40xx_gpio_set; ++ gc->can_sleep = true; ++ gc->label = priv->dev.name; ++ gc->of_node = switch_node; ++ ++ err = devm_gpiochip_add_data(pdev, gc, priv); ++ if (err != 0) ++ dev_err(pdev, "Failed to register gpio %d.\n", err); ++} ++ ++/* End of phy driver support */ ++ ++/* Platform driver probe function */ ++ ++static int ar40xx_probe(struct platform_device *pdev) ++{ ++ struct device_node *switch_node; ++ struct device_node *psgmii_node; ++ const __be32 *mac_mode; ++ struct clk *ess_clk; ++ struct switch_dev *swdev; ++ struct ar40xx_priv *priv; ++ u32 len; ++ u32 num_mibs; ++ struct resource psgmii_base = {0}; ++ struct resource switch_base = {0}; ++ int ret; ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, priv); ++ ar40xx_priv = priv; ++ ++ switch_node = of_node_get(pdev->dev.of_node); ++ if (of_address_to_resource(switch_node, 0, &switch_base) != 0) ++ return -EIO; ++ ++ priv->hw_addr = devm_ioremap_resource(&pdev->dev, &switch_base); ++ if (IS_ERR(priv->hw_addr)) { ++ dev_err(&pdev->dev, "Failed to ioremap switch_base!\n"); ++ return PTR_ERR(priv->hw_addr); ++ } ++ ++ /*psgmii dts get*/ ++ psgmii_node = of_find_node_by_name(NULL, "ess-psgmii"); ++ if (!psgmii_node) { ++ dev_err(&pdev->dev, "Failed to find ess-psgmii node!\n"); ++ return -EINVAL; ++ } ++ ++ if (of_address_to_resource(psgmii_node, 0, &psgmii_base) != 0) ++ return -EIO; ++ ++ priv->psgmii_hw_addr = devm_ioremap_resource(&pdev->dev, &psgmii_base); ++ if (IS_ERR(priv->psgmii_hw_addr)) { ++ dev_err(&pdev->dev, "psgmii ioremap fail!\n"); ++ return PTR_ERR(priv->psgmii_hw_addr); ++ } ++ ++ mac_mode = of_get_property(switch_node, "switch_mac_mode", &len); ++ if (!mac_mode) { ++ dev_err(&pdev->dev, "Failed to read switch_mac_mode\n"); ++ return -EINVAL; ++ } ++ priv->mac_mode = be32_to_cpup(mac_mode); ++ ++ ess_clk = of_clk_get_by_name(switch_node, "ess_clk"); ++ if (ess_clk) ++ clk_prepare_enable(ess_clk); ++ ++ priv->ess_rst = devm_reset_control_get(&pdev->dev, "ess_rst"); ++ if (IS_ERR(priv->ess_rst)) { ++ dev_err(&pdev->dev, "Failed to get ess_rst control!\n"); ++ return PTR_ERR(priv->ess_rst); ++ } ++ ++ if (of_property_read_u32(switch_node, "switch_cpu_bmp", ++ &priv->cpu_bmp) || ++ of_property_read_u32(switch_node, "switch_lan_bmp", ++ &priv->lan_bmp) || ++ of_property_read_u32(switch_node, "switch_wan_bmp", ++ &priv->wan_bmp)) { ++ dev_err(&pdev->dev, "Failed to read port properties\n"); ++ return -EIO; ++ } ++ ++ ret = phy_driver_register(&ar40xx_phy_driver, THIS_MODULE); ++ if (ret) { ++ dev_err(&pdev->dev, "Failed to register ar40xx phy driver!\n"); ++ return -EIO; ++ } ++ ++ mutex_init(&priv->reg_mutex); ++ mutex_init(&priv->mib_lock); ++ INIT_DELAYED_WORK(&priv->mib_work, ar40xx_mib_work_func); ++ ++ /* register switch */ ++ swdev = &priv->dev; ++ ++ swdev->alias = dev_name(&priv->mii_bus->dev); ++ ++ swdev->cpu_port = AR40XX_PORT_CPU; ++ swdev->name = "QCA AR40xx"; ++ swdev->vlans = AR40XX_MAX_VLANS; ++ swdev->ports = AR40XX_NUM_PORTS; ++ swdev->ops = &ar40xx_sw_ops; ++ ret = register_switch(swdev, NULL); ++ if (ret) ++ goto err_unregister_phy; ++ ++ num_mibs = ARRAY_SIZE(ar40xx_mibs); ++ len = priv->dev.ports * num_mibs * ++ sizeof(*priv->mib_stats); ++ priv->mib_stats = devm_kzalloc(&pdev->dev, len, GFP_KERNEL); ++ if (!priv->mib_stats) { ++ ret = -ENOMEM; ++ goto err_unregister_switch; ++ } ++ ++ ar40xx_start(priv); ++ ++ if (of_property_read_bool(switch_node, "gpio-controller")) ++ ar40xx_register_gpio(&pdev->dev, ar40xx_priv, switch_node); ++ ++ return 0; ++ ++err_unregister_switch: ++ unregister_switch(&priv->dev); ++err_unregister_phy: ++ phy_driver_unregister(&ar40xx_phy_driver); ++ platform_set_drvdata(pdev, NULL); ++ return ret; ++} ++ ++static int ar40xx_remove(struct platform_device *pdev) ++{ ++ struct ar40xx_priv *priv = platform_get_drvdata(pdev); ++ ++ cancel_delayed_work_sync(&priv->qm_dwork); ++ cancel_delayed_work_sync(&priv->mib_work); ++ ++ unregister_switch(&priv->dev); ++ ++ phy_driver_unregister(&ar40xx_phy_driver); ++ ++ return 0; ++} ++ ++static const struct of_device_id ar40xx_of_mtable[] = { ++ {.compatible = "qcom,ess-switch" }, ++ {} ++}; ++ ++struct platform_driver ar40xx_drv = { ++ .probe = ar40xx_probe, ++ .remove = ar40xx_remove, ++ .driver = { ++ .name = "ar40xx", ++ .of_match_table = ar40xx_of_mtable, ++ }, ++}; ++ ++module_platform_driver(ar40xx_drv); ++ ++MODULE_DESCRIPTION("IPQ40XX ESS driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +--- /dev/null ++++ b/drivers/net/phy/ar40xx.h +@@ -0,0 +1,337 @@ ++/* ++ * Copyright (c) 2016, The Linux Foundation. All rights reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for ++ * any purpose with or without fee is hereby granted, provided that the ++ * above copyright notice and this permission notice appear in all copies. ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT ++ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ #ifndef __AR40XX_H ++#define __AR40XX_H ++ ++#define AR40XX_MAX_VLANS 128 ++#define AR40XX_NUM_PORTS 6 ++#define AR40XX_NUM_PHYS 5 ++ ++#define BITS(_s, _n) (((1UL << (_n)) - 1) << _s) ++ ++struct ar40xx_priv { ++ struct switch_dev dev; ++ ++ u8 __iomem *hw_addr; ++ u8 __iomem *psgmii_hw_addr; ++ u32 mac_mode; ++ struct reset_control *ess_rst; ++ u32 cpu_bmp; ++ u32 lan_bmp; ++ u32 wan_bmp; ++ ++ struct mii_bus *mii_bus; ++ struct phy_device *phy; ++ ++ /* mutex for qm task */ ++ struct mutex qm_lock; ++ struct delayed_work qm_dwork; ++ u32 port_link_up[AR40XX_NUM_PORTS]; ++ u32 ar40xx_port_old_link[AR40XX_NUM_PORTS]; ++ u32 ar40xx_port_qm_buf[AR40XX_NUM_PORTS]; ++ ++ u32 phy_t_status; ++ ++ /* mutex for switch reg access */ ++ struct mutex reg_mutex; ++ ++ /* mutex for mib task */ ++ struct mutex mib_lock; ++ struct delayed_work mib_work; ++ int mib_next_port; ++ u64 *mib_stats; ++ ++ char buf[2048]; ++ ++ /* all fields below will be cleared on reset */ ++ bool vlan; ++ u16 vlan_id[AR40XX_MAX_VLANS]; ++ u8 vlan_table[AR40XX_MAX_VLANS]; ++ u8 vlan_tagged; ++ u16 pvid[AR40XX_NUM_PORTS]; ++ ++ /* mirror */ ++ bool mirror_rx; ++ bool mirror_tx; ++ int source_port; ++ int monitor_port; ++}; ++ ++#define AR40XX_PORT_LINK_UP 1 ++#define AR40XX_PORT_LINK_DOWN 0 ++#define AR40XX_QM_NOT_EMPTY 1 ++#define AR40XX_QM_EMPTY 0 ++ ++#define AR40XX_LAN_VLAN 1 ++#define AR40XX_WAN_VLAN 2 ++ ++enum ar40xx_port_wrapper_cfg { ++ PORT_WRAPPER_PSGMII = 0, ++}; ++ ++struct ar40xx_mib_desc { ++ u32 size; ++ u32 offset; ++ const char *name; ++}; ++ ++#define AR40XX_PORT_CPU 0 ++ ++#define AR40XX_PSGMII_MODE_CONTROL 0x1b4 ++#define AR40XX_PSGMII_ATHR_CSCO_MODE_25M BIT(0) ++ ++#define AR40XX_PSGMIIPHY_TX_CONTROL 0x288 ++ ++#define AR40XX_MII_ATH_MMD_ADDR 0x0d ++#define AR40XX_MII_ATH_MMD_DATA 0x0e ++#define AR40XX_MII_ATH_DBG_ADDR 0x1d ++#define AR40XX_MII_ATH_DBG_DATA 0x1e ++ ++#define AR40XX_STATS_RXBROAD 0x00 ++#define AR40XX_STATS_RXPAUSE 0x04 ++#define AR40XX_STATS_RXMULTI 0x08 ++#define AR40XX_STATS_RXFCSERR 0x0c ++#define AR40XX_STATS_RXALIGNERR 0x10 ++#define AR40XX_STATS_RXRUNT 0x14 ++#define AR40XX_STATS_RXFRAGMENT 0x18 ++#define AR40XX_STATS_RX64BYTE 0x1c ++#define AR40XX_STATS_RX128BYTE 0x20 ++#define AR40XX_STATS_RX256BYTE 0x24 ++#define AR40XX_STATS_RX512BYTE 0x28 ++#define AR40XX_STATS_RX1024BYTE 0x2c ++#define AR40XX_STATS_RX1518BYTE 0x30 ++#define AR40XX_STATS_RXMAXBYTE 0x34 ++#define AR40XX_STATS_RXTOOLONG 0x38 ++#define AR40XX_STATS_RXGOODBYTE 0x3c ++#define AR40XX_STATS_RXBADBYTE 0x44 ++#define AR40XX_STATS_RXOVERFLOW 0x4c ++#define AR40XX_STATS_FILTERED 0x50 ++#define AR40XX_STATS_TXBROAD 0x54 ++#define AR40XX_STATS_TXPAUSE 0x58 ++#define AR40XX_STATS_TXMULTI 0x5c ++#define AR40XX_STATS_TXUNDERRUN 0x60 ++#define AR40XX_STATS_TX64BYTE 0x64 ++#define AR40XX_STATS_TX128BYTE 0x68 ++#define AR40XX_STATS_TX256BYTE 0x6c ++#define AR40XX_STATS_TX512BYTE 0x70 ++#define AR40XX_STATS_TX1024BYTE 0x74 ++#define AR40XX_STATS_TX1518BYTE 0x78 ++#define AR40XX_STATS_TXMAXBYTE 0x7c ++#define AR40XX_STATS_TXOVERSIZE 0x80 ++#define AR40XX_STATS_TXBYTE 0x84 ++#define AR40XX_STATS_TXCOLLISION 0x8c ++#define AR40XX_STATS_TXABORTCOL 0x90 ++#define AR40XX_STATS_TXMULTICOL 0x94 ++#define AR40XX_STATS_TXSINGLECOL 0x98 ++#define AR40XX_STATS_TXEXCDEFER 0x9c ++#define AR40XX_STATS_TXDEFER 0xa0 ++#define AR40XX_STATS_TXLATECOL 0xa4 ++ ++#define AR40XX_REG_MODULE_EN 0x030 ++#define AR40XX_MODULE_EN_MIB BIT(0) ++ ++#define AR40XX_REG_MIB_FUNC 0x034 ++#define AR40XX_MIB_BUSY BIT(17) ++#define AR40XX_MIB_CPU_KEEP BIT(20) ++#define AR40XX_MIB_FUNC BITS(24, 3) ++#define AR40XX_MIB_FUNC_S 24 ++#define AR40XX_MIB_FUNC_NO_OP 0x0 ++#define AR40XX_MIB_FUNC_FLUSH 0x1 ++ ++#define AR40XX_REG_PORT_STATUS(_i) (0x07c + (_i) * 4) ++#define AR40XX_PORT_SPEED BITS(0, 2) ++#define AR40XX_PORT_STATUS_SPEED_S 0 ++#define AR40XX_PORT_TX_EN BIT(2) ++#define AR40XX_PORT_RX_EN BIT(3) ++#define AR40XX_PORT_STATUS_TXFLOW BIT(4) ++#define AR40XX_PORT_STATUS_RXFLOW BIT(5) ++#define AR40XX_PORT_DUPLEX BIT(6) ++#define AR40XX_PORT_TXHALF_FLOW BIT(7) ++#define AR40XX_PORT_STATUS_LINK_UP BIT(8) ++#define AR40XX_PORT_AUTO_LINK_EN BIT(9) ++#define AR40XX_PORT_STATUS_FLOW_CONTROL BIT(12) ++ ++#define AR40XX_REG_MAX_FRAME_SIZE 0x078 ++#define AR40XX_MAX_FRAME_SIZE_MTU BITS(0, 14) ++ ++#define AR40XX_REG_PORT_HEADER(_i) (0x09c + (_i) * 4) ++ ++#define AR40XX_REG_EEE_CTRL 0x100 ++#define AR40XX_EEE_CTRL_DISABLE_PHY(_i) BIT(4 + (_i) * 2) ++ ++#define AR40XX_REG_PORT_VLAN0(_i) (0x420 + (_i) * 0x8) ++#define AR40XX_PORT_VLAN0_DEF_SVID BITS(0, 12) ++#define AR40XX_PORT_VLAN0_DEF_SVID_S 0 ++#define AR40XX_PORT_VLAN0_DEF_CVID BITS(16, 12) ++#define AR40XX_PORT_VLAN0_DEF_CVID_S 16 ++ ++#define AR40XX_REG_PORT_VLAN1(_i) (0x424 + (_i) * 0x8) ++#define AR40XX_PORT_VLAN1_PORT_VLAN_PROP BIT(6) ++#define AR40XX_PORT_VLAN1_OUT_MODE BITS(12, 2) ++#define AR40XX_PORT_VLAN1_OUT_MODE_S 12 ++#define AR40XX_PORT_VLAN1_OUT_MODE_UNMOD 0 ++#define AR40XX_PORT_VLAN1_OUT_MODE_UNTAG 1 ++#define AR40XX_PORT_VLAN1_OUT_MODE_TAG 2 ++#define AR40XX_PORT_VLAN1_OUT_MODE_UNTOUCH 3 ++ ++#define AR40XX_REG_VTU_FUNC0 0x0610 ++#define AR40XX_VTU_FUNC0_EG_MODE BITS(4, 14) ++#define AR40XX_VTU_FUNC0_EG_MODE_S(_i) (4 + (_i) * 2) ++#define AR40XX_VTU_FUNC0_EG_MODE_KEEP 0 ++#define AR40XX_VTU_FUNC0_EG_MODE_UNTAG 1 ++#define AR40XX_VTU_FUNC0_EG_MODE_TAG 2 ++#define AR40XX_VTU_FUNC0_EG_MODE_NOT 3 ++#define AR40XX_VTU_FUNC0_IVL BIT(19) ++#define AR40XX_VTU_FUNC0_VALID BIT(20) ++ ++#define AR40XX_REG_VTU_FUNC1 0x0614 ++#define AR40XX_VTU_FUNC1_OP BITS(0, 3) ++#define AR40XX_VTU_FUNC1_OP_NOOP 0 ++#define AR40XX_VTU_FUNC1_OP_FLUSH 1 ++#define AR40XX_VTU_FUNC1_OP_LOAD 2 ++#define AR40XX_VTU_FUNC1_OP_PURGE 3 ++#define AR40XX_VTU_FUNC1_OP_REMOVE_PORT 4 ++#define AR40XX_VTU_FUNC1_OP_GET_NEXT 5 ++#define AR40XX7_VTU_FUNC1_OP_GET_ONE 6 ++#define AR40XX_VTU_FUNC1_FULL BIT(4) ++#define AR40XX_VTU_FUNC1_PORT BIT(8, 4) ++#define AR40XX_VTU_FUNC1_PORT_S 8 ++#define AR40XX_VTU_FUNC1_VID BIT(16, 12) ++#define AR40XX_VTU_FUNC1_VID_S 16 ++#define AR40XX_VTU_FUNC1_BUSY BIT(31) ++ ++#define AR40XX_REG_FWD_CTRL0 0x620 ++#define AR40XX_FWD_CTRL0_CPU_PORT_EN BIT(10) ++#define AR40XX_FWD_CTRL0_MIRROR_PORT BITS(4, 4) ++#define AR40XX_FWD_CTRL0_MIRROR_PORT_S 4 ++ ++#define AR40XX_REG_FWD_CTRL1 0x624 ++#define AR40XX_FWD_CTRL1_UC_FLOOD BITS(0, 7) ++#define AR40XX_FWD_CTRL1_UC_FLOOD_S 0 ++#define AR40XX_FWD_CTRL1_MC_FLOOD BITS(8, 7) ++#define AR40XX_FWD_CTRL1_MC_FLOOD_S 8 ++#define AR40XX_FWD_CTRL1_BC_FLOOD BITS(16, 7) ++#define AR40XX_FWD_CTRL1_BC_FLOOD_S 16 ++#define AR40XX_FWD_CTRL1_IGMP BITS(24, 7) ++#define AR40XX_FWD_CTRL1_IGMP_S 24 ++ ++#define AR40XX_REG_PORT_LOOKUP(_i) (0x660 + (_i) * 0xc) ++#define AR40XX_PORT_LOOKUP_MEMBER BITS(0, 7) ++#define AR40XX_PORT_LOOKUP_IN_MODE BITS(8, 2) ++#define AR40XX_PORT_LOOKUP_IN_MODE_S 8 ++#define AR40XX_PORT_LOOKUP_STATE BITS(16, 3) ++#define AR40XX_PORT_LOOKUP_STATE_S 16 ++#define AR40XX_PORT_LOOKUP_LEARN BIT(20) ++#define AR40XX_PORT_LOOKUP_LOOPBACK BIT(21) ++#define AR40XX_PORT_LOOKUP_ING_MIRROR_EN BIT(25) ++ ++#define AR40XX_REG_ATU_FUNC 0x60c ++#define AR40XX_ATU_FUNC_OP BITS(0, 4) ++#define AR40XX_ATU_FUNC_OP_NOOP 0x0 ++#define AR40XX_ATU_FUNC_OP_FLUSH 0x1 ++#define AR40XX_ATU_FUNC_OP_LOAD 0x2 ++#define AR40XX_ATU_FUNC_OP_PURGE 0x3 ++#define AR40XX_ATU_FUNC_OP_FLUSH_LOCKED 0x4 ++#define AR40XX_ATU_FUNC_OP_FLUSH_UNICAST 0x5 ++#define AR40XX_ATU_FUNC_OP_GET_NEXT 0x6 ++#define AR40XX_ATU_FUNC_OP_SEARCH_MAC 0x7 ++#define AR40XX_ATU_FUNC_OP_CHANGE_TRUNK 0x8 ++#define AR40XX_ATU_FUNC_BUSY BIT(31) ++ ++#define AR40XX_REG_QM_DEBUG_ADDR 0x820 ++#define AR40XX_REG_QM_DEBUG_VALUE 0x824 ++#define AR40XX_REG_QM_PORT0_3_QNUM 0x1d ++#define AR40XX_REG_QM_PORT4_6_QNUM 0x1e ++ ++#define AR40XX_REG_PORT_HOL_CTRL1(_i) (0x974 + (_i) * 0x8) ++#define AR40XX_PORT_HOL_CTRL1_EG_MIRROR_EN BIT(16) ++ ++#define AR40XX_REG_PORT_FLOWCTRL_THRESH(_i) (0x9b0 + (_i) * 0x4) ++#define AR40XX_PORT0_FC_THRESH_ON_DFLT 0x60 ++#define AR40XX_PORT0_FC_THRESH_OFF_DFLT 0x90 ++ ++#define AR40XX_PHY_DEBUG_0 0 ++#define AR40XX_PHY_MANU_CTRL_EN BIT(12) ++ ++#define AR40XX_PHY_DEBUG_2 2 ++ ++#define AR40XX_PHY_SPEC_STATUS 0x11 ++#define AR40XX_PHY_SPEC_STATUS_LINK BIT(10) ++#define AR40XX_PHY_SPEC_STATUS_DUPLEX BIT(13) ++#define AR40XX_PHY_SPEC_STATUS_SPEED BITS(14, 2) ++ ++/* port forwarding state */ ++enum { ++ AR40XX_PORT_STATE_DISABLED = 0, ++ AR40XX_PORT_STATE_BLOCK = 1, ++ AR40XX_PORT_STATE_LISTEN = 2, ++ AR40XX_PORT_STATE_LEARN = 3, ++ AR40XX_PORT_STATE_FORWARD = 4 ++}; ++ ++/* ingress 802.1q mode */ ++enum { ++ AR40XX_IN_PORT_ONLY = 0, ++ AR40XX_IN_PORT_FALLBACK = 1, ++ AR40XX_IN_VLAN_ONLY = 2, ++ AR40XX_IN_SECURE = 3 ++}; ++ ++/* egress 802.1q mode */ ++enum { ++ AR40XX_OUT_KEEP = 0, ++ AR40XX_OUT_STRIP_VLAN = 1, ++ AR40XX_OUT_ADD_VLAN = 2 ++}; ++ ++/* port speed */ ++enum { ++ AR40XX_PORT_SPEED_10M = 0, ++ AR40XX_PORT_SPEED_100M = 1, ++ AR40XX_PORT_SPEED_1000M = 2, ++ AR40XX_PORT_SPEED_ERR = 3, ++}; ++ ++#define AR40XX_MIB_WORK_DELAY 2000 /* msecs */ ++ ++#define AR40XX_QM_WORK_DELAY 100 ++ ++#define AR40XX_MIB_FUNC_CAPTURE 0x3 ++ ++#define AR40XX_REG_PORT_STATS_START 0x1000 ++#define AR40XX_REG_PORT_STATS_LEN 0x100 ++ ++#define AR40XX_PORTS_ALL 0x3f ++ ++#define AR40XX_PSGMII_ID 5 ++#define AR40XX_PSGMII_CALB_NUM 100 ++#define AR40XX_MALIBU_PSGMII_MODE_CTRL 0x6d ++#define AR40XX_MALIBU_PHY_PSGMII_MODE_CTRL_ADJUST_VAL 0x220c ++#define AR40XX_MALIBU_PHY_MMD7_DAC_CTRL 0x801a ++#define AR40XX_MALIBU_DAC_CTRL_MASK 0x380 ++#define AR40XX_MALIBU_DAC_CTRL_VALUE 0x280 ++#define AR40XX_MALIBU_PHY_RLP_CTRL 0x805a ++#define AR40XX_PSGMII_TX_DRIVER_1_CTRL 0xb ++#define AR40XX_MALIBU_PHY_PSGMII_REDUCE_SERDES_TX_AMP 0x8a ++#define AR40XX_MALIBU_PHY_LAST_ADDR 4 ++ ++static inline struct ar40xx_priv * ++swdev_to_ar40xx(struct switch_dev *swdev) ++{ ++ return container_of(swdev, struct ar40xx_priv, dev); ++} ++ ++#endif +--- /dev/null ++++ b/drivers/net/phy/mdio-ipq40xx.c +@@ -0,0 +1,203 @@ ++/* ++ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for ++ * any purpose with or without fee is hereby granted, provided that the ++ * above copyright notice and this permission notice appear in all copies. ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT ++ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MDIO_CTRL_0_REG 0x40 ++#define MDIO_CTRL_1_REG 0x44 ++#define MDIO_CTRL_2_REG 0x48 ++#define MDIO_CTRL_3_REG 0x4c ++#define MDIO_CTRL_4_REG 0x50 ++#define MDIO_CTRL_4_ACCESS_BUSY BIT(16) ++#define MDIO_CTRL_4_ACCESS_START BIT(8) ++#define MDIO_CTRL_4_ACCESS_CODE_READ 0 ++#define MDIO_CTRL_4_ACCESS_CODE_WRITE 1 ++#define CTRL_0_REG_DEFAULT_VALUE 0x150FF ++ ++#define IPQ40XX_MDIO_RETRY 1000 ++#define IPQ40XX_MDIO_DELAY 10 ++ ++struct ipq40xx_mdio_data { ++ struct mii_bus *mii_bus; ++ void __iomem *membase; ++ int phy_irq[PHY_MAX_ADDR]; ++ struct device *dev; ++}; ++ ++static int ipq40xx_mdio_wait_busy(struct ipq40xx_mdio_data *am) ++{ ++ int i; ++ ++ for (i = 0; i < IPQ40XX_MDIO_RETRY; i++) { ++ unsigned int busy; ++ ++ busy = readl(am->membase + MDIO_CTRL_4_REG) & ++ MDIO_CTRL_4_ACCESS_BUSY; ++ if (!busy) ++ return 0; ++ ++ /* BUSY might take to be cleard by 15~20 times of loop */ ++ udelay(IPQ40XX_MDIO_DELAY); ++ } ++ ++ dev_err(am->dev, "%s: MDIO operation timed out\n", am->mii_bus->name); ++ ++ return -ETIMEDOUT; ++} ++ ++static int ipq40xx_mdio_read(struct mii_bus *bus, int mii_id, int regnum) ++{ ++ struct ipq40xx_mdio_data *am = bus->priv; ++ int value = 0; ++ unsigned int cmd = 0; ++ ++ lockdep_assert_held(&bus->mdio_lock); ++ ++ if (ipq40xx_mdio_wait_busy(am)) ++ return -ETIMEDOUT; ++ ++ /* issue the phy address and reg */ ++ writel((mii_id << 8) | regnum, am->membase + MDIO_CTRL_1_REG); ++ ++ cmd = MDIO_CTRL_4_ACCESS_START|MDIO_CTRL_4_ACCESS_CODE_READ; ++ ++ /* issue read command */ ++ writel(cmd, am->membase + MDIO_CTRL_4_REG); ++ ++ /* Wait read complete */ ++ if (ipq40xx_mdio_wait_busy(am)) ++ return -ETIMEDOUT; ++ ++ /* Read data */ ++ value = readl(am->membase + MDIO_CTRL_3_REG); ++ ++ return value; ++} ++ ++static int ipq40xx_mdio_write(struct mii_bus *bus, int mii_id, int regnum, ++ u16 value) ++{ ++ struct ipq40xx_mdio_data *am = bus->priv; ++ unsigned int cmd = 0; ++ ++ lockdep_assert_held(&bus->mdio_lock); ++ ++ if (ipq40xx_mdio_wait_busy(am)) ++ return -ETIMEDOUT; ++ ++ /* issue the phy address and reg */ ++ writel((mii_id << 8) | regnum, am->membase + MDIO_CTRL_1_REG); ++ ++ /* issue write data */ ++ writel(value, am->membase + MDIO_CTRL_2_REG); ++ ++ cmd = MDIO_CTRL_4_ACCESS_START|MDIO_CTRL_4_ACCESS_CODE_WRITE; ++ /* issue write command */ ++ writel(cmd, am->membase + MDIO_CTRL_4_REG); ++ ++ /* Wait write complete */ ++ if (ipq40xx_mdio_wait_busy(am)) ++ return -ETIMEDOUT; ++ ++ return 0; ++} ++ ++static int ipq40xx_mdio_probe(struct platform_device *pdev) ++{ ++ struct ipq40xx_mdio_data *am; ++ struct resource *res; ++ int i; ++ ++ am = devm_kzalloc(&pdev->dev, sizeof(*am), GFP_KERNEL); ++ if (!am) ++ return -ENOMEM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "no iomem resource found\n"); ++ return -ENXIO; ++ } ++ ++ am->membase = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(am->membase)) { ++ dev_err(&pdev->dev, "unable to ioremap registers\n"); ++ return PTR_ERR(am->membase); ++ } ++ ++ am->mii_bus = devm_mdiobus_alloc(&pdev->dev); ++ if (!am->mii_bus) ++ return -ENOMEM; ++ ++ writel(CTRL_0_REG_DEFAULT_VALUE, am->membase + MDIO_CTRL_0_REG); ++ ++ am->mii_bus->name = "ipq40xx_mdio"; ++ am->mii_bus->read = ipq40xx_mdio_read; ++ am->mii_bus->write = ipq40xx_mdio_write; ++ memcpy(am->mii_bus->irq, am->phy_irq, sizeof(am->phy_irq)); ++ am->mii_bus->priv = am; ++ am->mii_bus->parent = &pdev->dev; ++ snprintf(am->mii_bus->id, MII_BUS_ID_SIZE, "%s", dev_name(&pdev->dev)); ++ ++ for (i = 0; i < PHY_MAX_ADDR; i++) ++ am->phy_irq[i] = PHY_POLL; ++ ++ am->dev = &pdev->dev; ++ platform_set_drvdata(pdev, am); ++ ++ /* edma_axi_probe() use "am" drvdata. ++ * ipq40xx_mdio_probe() must be called first. ++ */ ++ return of_mdiobus_register(am->mii_bus, pdev->dev.of_node); ++} ++ ++static int ipq40xx_mdio_remove(struct platform_device *pdev) ++{ ++ struct ipq40xx_mdio_data *am = platform_get_drvdata(pdev); ++ ++ mdiobus_unregister(am->mii_bus); ++ return 0; ++} ++ ++static const struct of_device_id ipq40xx_mdio_dt_ids[] = { ++ { .compatible = "qcom,ipq4019-mdio" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ipq40xx_mdio_dt_ids); ++ ++static struct platform_driver ipq40xx_mdio_driver = { ++ .probe = ipq40xx_mdio_probe, ++ .remove = ipq40xx_mdio_remove, ++ .driver = { ++ .name = "ipq40xx-mdio", ++ .of_match_table = ipq40xx_mdio_dt_ids, ++ }, ++}; ++ ++module_platform_driver(ipq40xx_mdio_driver); ++ ++#define DRV_VERSION "1.0" ++ ++MODULE_DESCRIPTION("IPQ40XX MDIO interface driver"); ++MODULE_AUTHOR("Qualcomm Atheros"); ++MODULE_VERSION(DRV_VERSION); ++MODULE_LICENSE("Dual BSD/GPL"); diff --git a/target/linux/ipq40xx/patches-4.14/701-dts-ipq4019-add-mdio-node.patch b/target/linux/ipq40xx/patches-4.14/701-dts-ipq4019-add-mdio-node.patch new file mode 100644 index 000000000..112c921db --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/701-dts-ipq4019-add-mdio-node.patch @@ -0,0 +1,52 @@ +From 09ed737593f71bcca08a537a6c15264a1a6add08 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sun, 20 Nov 2016 01:10:33 +0100 +Subject: [PATCH] dts: ipq4019: add mdio node for ethernet + +This patch adds the mdio device-tree node. +This is where the switch is connected to, so it's needed +for the ethernet interfaces. + +Note: The driver isn't anywhere close to be upstream, +so the info might change. +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -539,6 +539,34 @@ + status = "disabled"; + }; + ++ mdio@90000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "qcom,ipq4019-mdio"; ++ reg = <0x90000 0x64>; ++ status = "disabled"; ++ ++ ethernet-phy@0 { ++ reg = <0>; ++ }; ++ ++ ethernet-phy@1 { ++ reg = <1>; ++ }; ++ ++ ethernet-phy@2 { ++ reg = <2>; ++ }; ++ ++ ethernet-phy@3 { ++ reg = <3>; ++ }; ++ ++ ethernet-phy@4 { ++ reg = <4>; ++ }; ++ }; ++ + usb3_ss_phy: ssphy@9a000 { + compatible = "qca,uni-ssphy"; + reg = <0x9a000 0x800>; diff --git a/target/linux/ipq40xx/patches-4.14/702-dts-ipq4019-add-PHY-switch-nodes.patch b/target/linux/ipq40xx/patches-4.14/702-dts-ipq4019-add-PHY-switch-nodes.patch new file mode 100644 index 000000000..7ad9edbe9 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/702-dts-ipq4019-add-PHY-switch-nodes.patch @@ -0,0 +1,46 @@ +From 9deeec35dd3b628b95624e41d4e04acf728991ba Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sun, 20 Nov 2016 02:20:54 +0100 +Subject: [PATCH] dts: ipq4019: add PHY/switch nodes + +This patch adds both the "qcom,ess-switch" and "qcom,ess-psgmii" +nodes which are needed for the ar40xx.c driver to initialize the +switch. + +Signed-off-by: Christian Lamparter +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -567,6 +567,29 @@ + }; + }; + ++ ess-switch@c000000 { ++ compatible = "qcom,ess-switch"; ++ reg = <0xc000000 0x80000>; ++ switch_access_mode = "local bus"; ++ resets = <&gcc ESS_RESET>; ++ reset-names = "ess_rst"; ++ clocks = <&gcc GCC_ESS_CLK>; ++ clock-names = "ess_clk"; ++ switch_cpu_bmp = <0x1>; ++ switch_lan_bmp = <0x1e>; ++ switch_wan_bmp = <0x20>; ++ switch_mac_mode = <0>; /* PORT_WRAPPER_PSGMII */ ++ switch_initvlas = <0x7c 0x54>; ++ status = "disabled"; ++ }; ++ ++ ess-psgmii@98000 { ++ compatible = "qcom,ess-psgmii"; ++ reg = <0x98000 0x800>; ++ psgmii_access_mode = "local bus"; ++ status = "disabled"; ++ }; ++ + usb3_ss_phy: ssphy@9a000 { + compatible = "qca,uni-ssphy"; + reg = <0x9a000 0x800>; diff --git a/target/linux/ipq40xx/patches-4.14/710-net-add-qualcomm-essedma-ethernet-driver.patch b/target/linux/ipq40xx/patches-4.14/710-net-add-qualcomm-essedma-ethernet-driver.patch new file mode 100644 index 000000000..e304911f1 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/710-net-add-qualcomm-essedma-ethernet-driver.patch @@ -0,0 +1,4578 @@ +From 12e9319da1adacac92930c899c99f0e1970cac11 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Thu, 19 Jan 2017 02:01:31 +0100 +Subject: [PATCH 33/38] NET: add qualcomm essedma ethernet driver + +Signed-off-by: Christian Lamparter +--- + drivers/net/ethernet/qualcomm/Kconfig | 9 +++++++++ + drivers/net/ethernet/qualcomm/Makefile | 1 + + 2 files changed, 10 insertions(+) + +--- a/drivers/net/ethernet/qualcomm/Kconfig ++++ b/drivers/net/ethernet/qualcomm/Kconfig +@@ -61,4 +61,13 @@ config QCOM_EMAC + + source "drivers/net/ethernet/qualcomm/rmnet/Kconfig" + ++config ESSEDMA ++ tristate "Qualcomm Atheros ESS Edma support" ++ ---help--- ++ This driver supports ethernet edma adapter. ++ Say Y to build this driver. ++ ++ To compile this driver as a module, choose M here. The module ++ will be called essedma.ko. ++ + endif # NET_VENDOR_QUALCOMM +--- a/drivers/net/ethernet/qualcomm/Makefile ++++ b/drivers/net/ethernet/qualcomm/Makefile +@@ -10,5 +10,6 @@ obj-$(CONFIG_QCA7000_UART) += qcauart.o + qcauart-objs := qca_uart.o + + obj-y += emac/ ++obj-$(CONFIG_ESSEDMA) += essedma/ + + obj-$(CONFIG_RMNET) += rmnet/ +--- /dev/null ++++ b/drivers/net/ethernet/qualcomm/essedma/Makefile +@@ -0,0 +1,9 @@ ++# ++## Makefile for the Qualcomm Atheros ethernet edma driver ++# ++ ++ ++obj-$(CONFIG_ESSEDMA) += essedma.o ++ ++essedma-objs := edma_axi.o edma.o edma_ethtool.o ++ +--- /dev/null ++++ b/drivers/net/ethernet/qualcomm/essedma/edma.c +@@ -0,0 +1,2143 @@ ++/* ++ * Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for ++ * any purpose with or without fee is hereby granted, provided that the ++ * above copyright notice and this permission notice appear in all copies. ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT ++ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include "ess_edma.h" ++#include "edma.h" ++ ++extern struct net_device *edma_netdev[EDMA_MAX_PORTID_SUPPORTED]; ++bool edma_stp_rstp; ++u16 edma_ath_eth_type; ++ ++/* edma_skb_priority_offset() ++ * get edma skb priority ++ */ ++static unsigned int edma_skb_priority_offset(struct sk_buff *skb) ++{ ++ return (skb->priority >> 2) & 1; ++} ++ ++/* edma_alloc_tx_ring() ++ * Allocate Tx descriptors ring ++ */ ++static int edma_alloc_tx_ring(struct edma_common_info *edma_cinfo, ++ struct edma_tx_desc_ring *etdr) ++{ ++ struct platform_device *pdev = edma_cinfo->pdev; ++ ++ /* Initialize ring */ ++ etdr->size = sizeof(struct edma_sw_desc) * etdr->count; ++ etdr->sw_next_to_fill = 0; ++ etdr->sw_next_to_clean = 0; ++ ++ /* Allocate SW descriptors */ ++ etdr->sw_desc = vzalloc(etdr->size); ++ if (!etdr->sw_desc) { ++ dev_err(&pdev->dev, "buffer alloc of tx ring failed=%p", etdr); ++ return -ENOMEM; ++ } ++ ++ /* Allocate HW descriptors */ ++ etdr->hw_desc = dma_alloc_coherent(&pdev->dev, etdr->size, &etdr->dma, ++ GFP_KERNEL); ++ if (!etdr->hw_desc) { ++ dev_err(&pdev->dev, "descriptor allocation for tx ring failed"); ++ vfree(etdr->sw_desc); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++/* edma_free_tx_ring() ++ * Free tx rings allocated by edma_alloc_tx_rings ++ */ ++static void edma_free_tx_ring(struct edma_common_info *edma_cinfo, ++ struct edma_tx_desc_ring *etdr) ++{ ++ struct platform_device *pdev = edma_cinfo->pdev; ++ ++ if (likely(etdr->dma)) ++ dma_free_coherent(&pdev->dev, etdr->size, etdr->hw_desc, ++ etdr->dma); ++ ++ vfree(etdr->sw_desc); ++ etdr->sw_desc = NULL; ++} ++ ++/* edma_alloc_rx_ring() ++ * allocate rx descriptor ring ++ */ ++static int edma_alloc_rx_ring(struct edma_common_info *edma_cinfo, ++ struct edma_rfd_desc_ring *erxd) ++{ ++ struct platform_device *pdev = edma_cinfo->pdev; ++ ++ erxd->size = sizeof(struct edma_sw_desc) * erxd->count; ++ erxd->sw_next_to_fill = 0; ++ erxd->sw_next_to_clean = 0; ++ ++ /* Allocate SW descriptors */ ++ erxd->sw_desc = vzalloc(erxd->size); ++ if (!erxd->sw_desc) ++ return -ENOMEM; ++ ++ /* Alloc HW descriptors */ ++ erxd->hw_desc = dma_alloc_coherent(&pdev->dev, erxd->size, &erxd->dma, ++ GFP_KERNEL); ++ if (!erxd->hw_desc) { ++ vfree(erxd->sw_desc); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++/* edma_free_rx_ring() ++ * Free rx ring allocated by alloc_rx_ring ++ */ ++static void edma_free_rx_ring(struct edma_common_info *edma_cinfo, ++ struct edma_rfd_desc_ring *rxdr) ++{ ++ struct platform_device *pdev = edma_cinfo->pdev; ++ ++ if (likely(rxdr->dma)) ++ dma_free_coherent(&pdev->dev, rxdr->size, rxdr->hw_desc, ++ rxdr->dma); ++ ++ vfree(rxdr->sw_desc); ++ rxdr->sw_desc = NULL; ++} ++ ++/* edma_configure_tx() ++ * Configure transmission control data ++ */ ++static void edma_configure_tx(struct edma_common_info *edma_cinfo) ++{ ++ u32 txq_ctrl_data; ++ ++ txq_ctrl_data = (EDMA_TPD_BURST << EDMA_TXQ_NUM_TPD_BURST_SHIFT); ++ txq_ctrl_data |= EDMA_TXQ_CTRL_TPD_BURST_EN; ++ txq_ctrl_data |= (EDMA_TXF_BURST << EDMA_TXQ_TXF_BURST_NUM_SHIFT); ++ edma_write_reg(EDMA_REG_TXQ_CTRL, txq_ctrl_data); ++} ++ ++ ++/* edma_configure_rx() ++ * configure reception control data ++ */ ++static void edma_configure_rx(struct edma_common_info *edma_cinfo) ++{ ++ struct edma_hw *hw = &edma_cinfo->hw; ++ u32 rss_type, rx_desc1, rxq_ctrl_data; ++ ++ /* Set RSS type */ ++ rss_type = hw->rss_type; ++ edma_write_reg(EDMA_REG_RSS_TYPE, rss_type); ++ ++ /* Set RFD burst number */ ++ rx_desc1 = (EDMA_RFD_BURST << EDMA_RXQ_RFD_BURST_NUM_SHIFT); ++ ++ /* Set RFD prefetch threshold */ ++ rx_desc1 |= (EDMA_RFD_THR << EDMA_RXQ_RFD_PF_THRESH_SHIFT); ++ ++ /* Set RFD in host ring low threshold to generte interrupt */ ++ rx_desc1 |= (EDMA_RFD_LTHR << EDMA_RXQ_RFD_LOW_THRESH_SHIFT); ++ edma_write_reg(EDMA_REG_RX_DESC1, rx_desc1); ++ ++ /* Set Rx FIFO threshold to start to DMA data to host */ ++ rxq_ctrl_data = EDMA_FIFO_THRESH_128_BYTE; ++ ++ /* Set RX remove vlan bit */ ++ rxq_ctrl_data |= EDMA_RXQ_CTRL_RMV_VLAN; ++ ++ edma_write_reg(EDMA_REG_RXQ_CTRL, rxq_ctrl_data); ++} ++ ++/* edma_alloc_rx_buf() ++ * does skb allocation for the received packets. ++ */ ++static int edma_alloc_rx_buf(struct edma_common_info ++ *edma_cinfo, ++ struct edma_rfd_desc_ring *erdr, ++ int cleaned_count, int queue_id) ++{ ++ struct platform_device *pdev = edma_cinfo->pdev; ++ struct edma_rx_free_desc *rx_desc; ++ struct edma_sw_desc *sw_desc; ++ struct sk_buff *skb; ++ unsigned int i; ++ u16 prod_idx, length; ++ u32 reg_data; ++ ++ if (cleaned_count > erdr->count) { ++ dev_err(&pdev->dev, "Incorrect cleaned_count %d", ++ cleaned_count); ++ return -1; ++ } ++ ++ i = erdr->sw_next_to_fill; ++ ++ while (cleaned_count) { ++ sw_desc = &erdr->sw_desc[i]; ++ length = edma_cinfo->rx_head_buffer_len; ++ ++ if (sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_REUSE) { ++ skb = sw_desc->skb; ++ } else { ++ /* alloc skb */ ++ skb = netdev_alloc_skb(edma_netdev[0], length); ++ if (!skb) { ++ /* Better luck next round */ ++ break; ++ } ++ } ++ ++ if (edma_cinfo->page_mode) { ++ struct page *pg = alloc_page(GFP_ATOMIC); ++ ++ if (!pg) { ++ dev_kfree_skb_any(skb); ++ break; ++ } ++ ++ sw_desc->dma = dma_map_page(&pdev->dev, pg, 0, ++ edma_cinfo->rx_page_buffer_len, ++ DMA_FROM_DEVICE); ++ if (dma_mapping_error(&pdev->dev, ++ sw_desc->dma)) { ++ __free_page(pg); ++ dev_kfree_skb_any(skb); ++ break; ++ } ++ ++ skb_fill_page_desc(skb, 0, pg, 0, ++ edma_cinfo->rx_page_buffer_len); ++ sw_desc->flags = EDMA_SW_DESC_FLAG_SKB_FRAG; ++ sw_desc->length = edma_cinfo->rx_page_buffer_len; ++ } else { ++ sw_desc->dma = dma_map_single(&pdev->dev, skb->data, ++ length, DMA_FROM_DEVICE); ++ if (dma_mapping_error(&pdev->dev, ++ sw_desc->dma)) { ++ dev_kfree_skb_any(skb); ++ break; ++ } ++ ++ sw_desc->flags = EDMA_SW_DESC_FLAG_SKB_HEAD; ++ sw_desc->length = length; ++ } ++ ++ /* Update the buffer info */ ++ sw_desc->skb = skb; ++ rx_desc = (&((struct edma_rx_free_desc *)(erdr->hw_desc))[i]); ++ rx_desc->buffer_addr = cpu_to_le64(sw_desc->dma); ++ if (++i == erdr->count) ++ i = 0; ++ cleaned_count--; ++ } ++ ++ erdr->sw_next_to_fill = i; ++ ++ if (i == 0) ++ prod_idx = erdr->count - 1; ++ else ++ prod_idx = i - 1; ++ ++ /* Update the producer index */ ++ edma_read_reg(EDMA_REG_RFD_IDX_Q(queue_id), ®_data); ++ reg_data &= ~EDMA_RFD_PROD_IDX_BITS; ++ reg_data |= prod_idx; ++ edma_write_reg(EDMA_REG_RFD_IDX_Q(queue_id), reg_data); ++ return cleaned_count; ++} ++ ++/* edma_init_desc() ++ * update descriptor ring size, buffer and producer/consumer index ++ */ ++static void edma_init_desc(struct edma_common_info *edma_cinfo) ++{ ++ struct edma_rfd_desc_ring *rfd_ring; ++ struct edma_tx_desc_ring *etdr; ++ int i = 0, j = 0; ++ u32 data = 0; ++ u16 hw_cons_idx = 0; ++ ++ /* Set the base address of every TPD ring. */ ++ for (i = 0; i < edma_cinfo->num_tx_queues; i++) { ++ etdr = edma_cinfo->tpd_ring[i]; ++ ++ /* Update descriptor ring base address */ ++ edma_write_reg(EDMA_REG_TPD_BASE_ADDR_Q(i), (u32)etdr->dma); ++ edma_read_reg(EDMA_REG_TPD_IDX_Q(i), &data); ++ ++ /* Calculate hardware consumer index */ ++ hw_cons_idx = (data >> EDMA_TPD_CONS_IDX_SHIFT) & 0xffff; ++ etdr->sw_next_to_fill = hw_cons_idx; ++ etdr->sw_next_to_clean = hw_cons_idx; ++ data &= ~(EDMA_TPD_PROD_IDX_MASK << EDMA_TPD_PROD_IDX_SHIFT); ++ data |= hw_cons_idx; ++ ++ /* update producer index */ ++ edma_write_reg(EDMA_REG_TPD_IDX_Q(i), data); ++ ++ /* update SW consumer index register */ ++ edma_write_reg(EDMA_REG_TX_SW_CONS_IDX_Q(i), hw_cons_idx); ++ ++ /* Set TPD ring size */ ++ edma_write_reg(EDMA_REG_TPD_RING_SIZE, ++ edma_cinfo->tx_ring_count & ++ EDMA_TPD_RING_SIZE_MASK); ++ } ++ ++ for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { ++ rfd_ring = edma_cinfo->rfd_ring[j]; ++ /* Update Receive Free descriptor ring base address */ ++ edma_write_reg(EDMA_REG_RFD_BASE_ADDR_Q(j), ++ (u32)(rfd_ring->dma)); ++ j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); ++ } ++ ++ data = edma_cinfo->rx_head_buffer_len; ++ if (edma_cinfo->page_mode) ++ data = edma_cinfo->rx_page_buffer_len; ++ ++ data &= EDMA_RX_BUF_SIZE_MASK; ++ data <<= EDMA_RX_BUF_SIZE_SHIFT; ++ ++ /* Update RFD ring size and RX buffer size */ ++ data |= (edma_cinfo->rx_ring_count & EDMA_RFD_RING_SIZE_MASK) ++ << EDMA_RFD_RING_SIZE_SHIFT; ++ ++ edma_write_reg(EDMA_REG_RX_DESC0, data); ++ ++ /* Disable TX FIFO low watermark and high watermark */ ++ edma_write_reg(EDMA_REG_TXF_WATER_MARK, 0); ++ ++ /* Load all of base address above */ ++ edma_read_reg(EDMA_REG_TX_SRAM_PART, &data); ++ data |= 1 << EDMA_LOAD_PTR_SHIFT; ++ edma_write_reg(EDMA_REG_TX_SRAM_PART, data); ++} ++ ++/* edma_receive_checksum ++ * Api to check checksum on receive packets ++ */ ++static void edma_receive_checksum(struct edma_rx_return_desc *rd, ++ struct sk_buff *skb) ++{ ++ skb_checksum_none_assert(skb); ++ ++ /* check the RRD IP/L4 checksum bit to see if ++ * its set, which in turn indicates checksum ++ * failure. ++ */ ++ if (rd->rrd6 & EDMA_RRD_CSUM_FAIL_MASK) ++ return; ++ ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++} ++ ++/* edma_clean_rfd() ++ * clean up rx resourcers on error ++ */ ++static void edma_clean_rfd(struct edma_rfd_desc_ring *erdr, u16 index) ++{ ++ struct edma_rx_free_desc *rx_desc; ++ struct edma_sw_desc *sw_desc; ++ ++ rx_desc = (&((struct edma_rx_free_desc *)(erdr->hw_desc))[index]); ++ sw_desc = &erdr->sw_desc[index]; ++ if (sw_desc->skb) { ++ dev_kfree_skb_any(sw_desc->skb); ++ sw_desc->skb = NULL; ++ } ++ ++ memset(rx_desc, 0, sizeof(struct edma_rx_free_desc)); ++} ++ ++/* edma_rx_complete_fraglist() ++ * Complete Rx processing for fraglist skbs ++ */ ++static void edma_rx_complete_stp_rstp(struct sk_buff *skb, int port_id, struct edma_rx_return_desc *rd) ++{ ++ int i; ++ u32 priority; ++ u16 port_type; ++ u8 mac_addr[EDMA_ETH_HDR_LEN]; ++ ++ port_type = (rd->rrd1 >> EDMA_RRD_PORT_TYPE_SHIFT) ++ & EDMA_RRD_PORT_TYPE_MASK; ++ /* if port type is 0x4, then only proceed with ++ * other stp/rstp calculation ++ */ ++ if (port_type == EDMA_RX_ATH_HDR_RSTP_PORT_TYPE) { ++ u8 bpdu_mac[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00}; ++ ++ /* calculate the frame priority */ ++ priority = (rd->rrd1 >> EDMA_RRD_PRIORITY_SHIFT) ++ & EDMA_RRD_PRIORITY_MASK; ++ ++ for (i = 0; i < EDMA_ETH_HDR_LEN; i++) ++ mac_addr[i] = skb->data[i]; ++ ++ /* Check if destination mac addr is bpdu addr */ ++ if (!memcmp(mac_addr, bpdu_mac, 6)) { ++ /* destination mac address is BPDU ++ * destination mac address, then add ++ * atheros header to the packet. ++ */ ++ u16 athr_hdr = (EDMA_RX_ATH_HDR_VERSION << EDMA_RX_ATH_HDR_VERSION_SHIFT) | ++ (priority << EDMA_RX_ATH_HDR_PRIORITY_SHIFT) | ++ (EDMA_RX_ATH_HDR_RSTP_PORT_TYPE << EDMA_RX_ATH_PORT_TYPE_SHIFT) | port_id; ++ skb_push(skb, 4); ++ memcpy(skb->data, mac_addr, EDMA_ETH_HDR_LEN); ++ *(uint16_t *)&skb->data[12] = htons(edma_ath_eth_type); ++ *(uint16_t *)&skb->data[14] = htons(athr_hdr); ++ } ++ } ++} ++ ++/* ++ * edma_rx_complete_fraglist() ++ * Complete Rx processing for fraglist skbs ++ */ ++static int edma_rx_complete_fraglist(struct sk_buff *skb, u16 num_rfds, u16 length, u32 sw_next_to_clean, ++ u16 *cleaned_count, struct edma_rfd_desc_ring *erdr, struct edma_common_info *edma_cinfo) ++{ ++ struct platform_device *pdev = edma_cinfo->pdev; ++ struct edma_hw *hw = &edma_cinfo->hw; ++ struct sk_buff *skb_temp; ++ struct edma_sw_desc *sw_desc; ++ int i; ++ u16 size_remaining; ++ ++ skb->data_len = 0; ++ skb->tail += (hw->rx_head_buff_size - 16); ++ skb->len = skb->truesize = length; ++ size_remaining = length - (hw->rx_head_buff_size - 16); ++ ++ /* clean-up all related sw_descs */ ++ for (i = 1; i < num_rfds; i++) { ++ struct sk_buff *skb_prev; ++ sw_desc = &erdr->sw_desc[sw_next_to_clean]; ++ skb_temp = sw_desc->skb; ++ ++ dma_unmap_single(&pdev->dev, sw_desc->dma, ++ sw_desc->length, DMA_FROM_DEVICE); ++ ++ if (size_remaining < hw->rx_head_buff_size) ++ skb_put(skb_temp, size_remaining); ++ else ++ skb_put(skb_temp, hw->rx_head_buff_size); ++ ++ /* ++ * If we are processing the first rfd, we link ++ * skb->frag_list to the skb corresponding to the ++ * first RFD ++ */ ++ if (i == 1) ++ skb_shinfo(skb)->frag_list = skb_temp; ++ else ++ skb_prev->next = skb_temp; ++ skb_prev = skb_temp; ++ skb_temp->next = NULL; ++ ++ skb->data_len += skb_temp->len; ++ size_remaining -= skb_temp->len; ++ ++ /* Increment SW index */ ++ sw_next_to_clean = (sw_next_to_clean + 1) & (erdr->count - 1); ++ (*cleaned_count)++; ++ } ++ ++ return sw_next_to_clean; ++} ++ ++/* edma_rx_complete_paged() ++ * Complete Rx processing for paged skbs ++ */ ++static int edma_rx_complete_paged(struct sk_buff *skb, u16 num_rfds, u16 length, u32 sw_next_to_clean, ++ u16 *cleaned_count, struct edma_rfd_desc_ring *erdr, struct edma_common_info *edma_cinfo) ++{ ++ struct platform_device *pdev = edma_cinfo->pdev; ++ struct sk_buff *skb_temp; ++ struct edma_sw_desc *sw_desc; ++ int i; ++ u16 size_remaining; ++ ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[0]; ++ ++ /* Setup skbuff fields */ ++ skb->len = length; ++ ++ if (likely(num_rfds <= 1)) { ++ skb->data_len = length; ++ skb->truesize += edma_cinfo->rx_page_buffer_len; ++ skb_fill_page_desc(skb, 0, skb_frag_page(frag), ++ 16, length); ++ } else { ++ frag->size -= 16; ++ skb->data_len = frag->size; ++ skb->truesize += edma_cinfo->rx_page_buffer_len; ++ size_remaining = length - frag->size; ++ ++ skb_fill_page_desc(skb, 0, skb_frag_page(frag), ++ 16, frag->size); ++ ++ /* clean-up all related sw_descs */ ++ for (i = 1; i < num_rfds; i++) { ++ sw_desc = &erdr->sw_desc[sw_next_to_clean]; ++ skb_temp = sw_desc->skb; ++ frag = &skb_shinfo(skb_temp)->frags[0]; ++ dma_unmap_page(&pdev->dev, sw_desc->dma, ++ sw_desc->length, DMA_FROM_DEVICE); ++ ++ if (size_remaining < edma_cinfo->rx_page_buffer_len) ++ frag->size = size_remaining; ++ ++ skb_fill_page_desc(skb, i, skb_frag_page(frag), ++ 0, frag->size); ++ ++ skb_shinfo(skb_temp)->nr_frags = 0; ++ dev_kfree_skb_any(skb_temp); ++ ++ skb->data_len += frag->size; ++ skb->truesize += edma_cinfo->rx_page_buffer_len; ++ size_remaining -= frag->size; ++ ++ /* Increment SW index */ ++ sw_next_to_clean = (sw_next_to_clean + 1) & (erdr->count - 1); ++ (*cleaned_count)++; ++ } ++ } ++ ++ return sw_next_to_clean; ++} ++ ++/* ++ * edma_rx_complete() ++ * Main api called from the poll function to process rx packets. ++ */ ++static void edma_rx_complete(struct edma_common_info *edma_cinfo, ++ int *work_done, int work_to_do, int queue_id, ++ struct napi_struct *napi) ++{ ++ struct platform_device *pdev = edma_cinfo->pdev; ++ struct edma_rfd_desc_ring *erdr = edma_cinfo->rfd_ring[queue_id]; ++ struct net_device *netdev; ++ struct edma_adapter *adapter; ++ struct edma_sw_desc *sw_desc; ++ struct sk_buff *skb; ++ struct edma_rx_return_desc *rd; ++ u16 hash_type, rrd[8], cleaned_count = 0, length = 0, num_rfds = 1, ++ sw_next_to_clean, hw_next_to_clean = 0, vlan = 0, ret_count = 0; ++ u32 data = 0; ++ u8 *vaddr; ++ int port_id, i, drop_count = 0; ++ u32 priority; ++ u16 count = erdr->count, rfd_avail; ++ u8 queue_to_rxid[8] = {0, 0, 1, 1, 2, 2, 3, 3}; ++ ++ sw_next_to_clean = erdr->sw_next_to_clean; ++ ++ edma_read_reg(EDMA_REG_RFD_IDX_Q(queue_id), &data); ++ hw_next_to_clean = (data >> EDMA_RFD_CONS_IDX_SHIFT) & ++ EDMA_RFD_CONS_IDX_MASK; ++ ++ do { ++ while (sw_next_to_clean != hw_next_to_clean) { ++ if (!work_to_do) ++ break; ++ ++ sw_desc = &erdr->sw_desc[sw_next_to_clean]; ++ skb = sw_desc->skb; ++ ++ /* Unmap the allocated buffer */ ++ if (likely(sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_HEAD)) ++ dma_unmap_single(&pdev->dev, sw_desc->dma, ++ sw_desc->length, DMA_FROM_DEVICE); ++ else ++ dma_unmap_page(&pdev->dev, sw_desc->dma, ++ sw_desc->length, DMA_FROM_DEVICE); ++ ++ /* Get RRD */ ++ if (edma_cinfo->page_mode) { ++ vaddr = kmap_atomic(skb_frag_page(&skb_shinfo(skb)->frags[0])); ++ memcpy((uint8_t *)&rrd[0], vaddr, 16); ++ rd = (struct edma_rx_return_desc *)rrd; ++ kunmap_atomic(vaddr); ++ } else { ++ rd = (struct edma_rx_return_desc *)skb->data; ++ } ++ ++ /* Check if RRD is valid */ ++ if (!(rd->rrd7 & EDMA_RRD_DESC_VALID)) { ++ edma_clean_rfd(erdr, sw_next_to_clean); ++ sw_next_to_clean = (sw_next_to_clean + 1) & ++ (erdr->count - 1); ++ cleaned_count++; ++ continue; ++ } ++ ++ /* Get the number of RFDs from RRD */ ++ num_rfds = rd->rrd1 & EDMA_RRD_NUM_RFD_MASK; ++ ++ /* Get Rx port ID from switch */ ++ port_id = (rd->rrd1 >> EDMA_PORT_ID_SHIFT) & EDMA_PORT_ID_MASK; ++ if ((!port_id) || (port_id > EDMA_MAX_PORTID_SUPPORTED)) { ++ dev_err(&pdev->dev, "Invalid RRD source port bit set"); ++ for (i = 0; i < num_rfds; i++) { ++ edma_clean_rfd(erdr, sw_next_to_clean); ++ sw_next_to_clean = (sw_next_to_clean + 1) & (erdr->count - 1); ++ cleaned_count++; ++ } ++ continue; ++ } ++ ++ /* check if we have a sink for the data we receive. ++ * If the interface isn't setup, we have to drop the ++ * incoming data for now. ++ */ ++ netdev = edma_cinfo->portid_netdev_lookup_tbl[port_id]; ++ if (!netdev) { ++ edma_clean_rfd(erdr, sw_next_to_clean); ++ sw_next_to_clean = (sw_next_to_clean + 1) & ++ (erdr->count - 1); ++ cleaned_count++; ++ continue; ++ } ++ adapter = netdev_priv(netdev); ++ ++ /* This code is added to handle a usecase where high ++ * priority stream and a low priority stream are ++ * received simultaneously on DUT. The problem occurs ++ * if one of the Rx rings is full and the corresponding ++ * core is busy with other stuff. This causes ESS CPU ++ * port to backpressure all incoming traffic including ++ * high priority one. We monitor free descriptor count ++ * on each CPU and whenever it reaches threshold (< 80), ++ * we drop all low priority traffic and let only high ++ * priotiy traffic pass through. We can hence avoid ++ * ESS CPU port to send backpressure on high priroity ++ * stream. ++ */ ++ priority = (rd->rrd1 >> EDMA_RRD_PRIORITY_SHIFT) ++ & EDMA_RRD_PRIORITY_MASK; ++ if (likely(!priority && !edma_cinfo->page_mode && (num_rfds <= 1))) { ++ rfd_avail = (count + sw_next_to_clean - hw_next_to_clean - 1) & (count - 1); ++ if (rfd_avail < EDMA_RFD_AVAIL_THR) { ++ sw_desc->flags = EDMA_SW_DESC_FLAG_SKB_REUSE; ++ sw_next_to_clean = (sw_next_to_clean + 1) & (erdr->count - 1); ++ adapter->stats.rx_dropped++; ++ cleaned_count++; ++ drop_count++; ++ if (drop_count == 3) { ++ work_to_do--; ++ (*work_done)++; ++ drop_count = 0; ++ } ++ if (cleaned_count == EDMA_RX_BUFFER_WRITE) { ++ /* If buffer clean count reaches 16, we replenish HW buffers. */ ++ ret_count = edma_alloc_rx_buf(edma_cinfo, erdr, cleaned_count, queue_id); ++ edma_write_reg(EDMA_REG_RX_SW_CONS_IDX_Q(queue_id), ++ sw_next_to_clean); ++ cleaned_count = ret_count; ++ } ++ continue; ++ } ++ } ++ ++ work_to_do--; ++ (*work_done)++; ++ ++ /* Increment SW index */ ++ sw_next_to_clean = (sw_next_to_clean + 1) & ++ (erdr->count - 1); ++ ++ cleaned_count++; ++ ++ /* Get the packet size and allocate buffer */ ++ length = rd->rrd6 & EDMA_RRD_PKT_SIZE_MASK; ++ ++ if (edma_cinfo->page_mode) { ++ /* paged skb */ ++ sw_next_to_clean = edma_rx_complete_paged(skb, num_rfds, length, sw_next_to_clean, &cleaned_count, erdr, edma_cinfo); ++ if (!pskb_may_pull(skb, ETH_HLEN)) { ++ dev_kfree_skb_any(skb); ++ continue; ++ } ++ } else { ++ /* single or fraglist skb */ ++ ++ /* Addition of 16 bytes is required, as in the packet ++ * first 16 bytes are rrd descriptors, so actual data ++ * starts from an offset of 16. ++ */ ++ skb_reserve(skb, 16); ++ if (likely((num_rfds <= 1) || !edma_cinfo->fraglist_mode)) { ++ skb_put(skb, length); ++ } else { ++ sw_next_to_clean = edma_rx_complete_fraglist(skb, num_rfds, length, sw_next_to_clean, &cleaned_count, erdr, edma_cinfo); ++ } ++ } ++ ++ if (edma_stp_rstp) { ++ edma_rx_complete_stp_rstp(skb, port_id, rd); ++ } ++ ++ skb->protocol = eth_type_trans(skb, netdev); ++ ++ /* Record Rx queue for RFS/RPS and fill flow hash from HW */ ++ skb_record_rx_queue(skb, queue_to_rxid[queue_id]); ++ if (netdev->features & NETIF_F_RXHASH) { ++ hash_type = (rd->rrd5 >> EDMA_HASH_TYPE_SHIFT); ++ if ((hash_type > EDMA_HASH_TYPE_START) && (hash_type < EDMA_HASH_TYPE_END)) ++ skb_set_hash(skb, rd->rrd2, PKT_HASH_TYPE_L4); ++ } ++ ++#ifdef CONFIG_NF_FLOW_COOKIE ++ skb->flow_cookie = rd->rrd3 & EDMA_RRD_FLOW_COOKIE_MASK; ++#endif ++ edma_receive_checksum(rd, skb); ++ ++ /* Process VLAN HW acceleration indication provided by HW */ ++ if (unlikely(adapter->default_vlan_tag != rd->rrd4)) { ++ vlan = rd->rrd4; ++ if (likely(rd->rrd7 & EDMA_RRD_CVLAN)) ++ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan); ++ else if (rd->rrd1 & EDMA_RRD_SVLAN) ++ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021AD), vlan); ++ } ++ ++ /* Update rx statistics */ ++ adapter->stats.rx_packets++; ++ adapter->stats.rx_bytes += length; ++ ++ /* Check if we reached refill threshold */ ++ if (cleaned_count == EDMA_RX_BUFFER_WRITE) { ++ ret_count = edma_alloc_rx_buf(edma_cinfo, erdr, cleaned_count, queue_id); ++ edma_write_reg(EDMA_REG_RX_SW_CONS_IDX_Q(queue_id), ++ sw_next_to_clean); ++ cleaned_count = ret_count; ++ } ++ ++ /* At this point skb should go to stack */ ++ napi_gro_receive(napi, skb); ++ } ++ ++ /* Check if we still have NAPI budget */ ++ if (!work_to_do) ++ break; ++ ++ /* Read index once again since we still have NAPI budget */ ++ edma_read_reg(EDMA_REG_RFD_IDX_Q(queue_id), &data); ++ hw_next_to_clean = (data >> EDMA_RFD_CONS_IDX_SHIFT) & ++ EDMA_RFD_CONS_IDX_MASK; ++ } while (hw_next_to_clean != sw_next_to_clean); ++ ++ erdr->sw_next_to_clean = sw_next_to_clean; ++ ++ /* Refill here in case refill threshold wasn't reached */ ++ if (likely(cleaned_count)) { ++ ret_count = edma_alloc_rx_buf(edma_cinfo, erdr, cleaned_count, queue_id); ++ if (ret_count) ++ dev_dbg(&pdev->dev, "Not all buffers was reallocated"); ++ edma_write_reg(EDMA_REG_RX_SW_CONS_IDX_Q(queue_id), ++ erdr->sw_next_to_clean); ++ } ++} ++ ++/* edma_delete_rfs_filter() ++ * Remove RFS filter from switch ++ */ ++static int edma_delete_rfs_filter(struct edma_adapter *adapter, ++ struct edma_rfs_filter_node *filter_node) ++{ ++ int res = -1; ++ ++ struct flow_keys *keys = &filter_node->keys; ++ ++ if (likely(adapter->set_rfs_rule)) ++ res = (*adapter->set_rfs_rule)(adapter->netdev, ++ flow_get_u32_src(keys), flow_get_u32_dst(keys), ++ keys->ports.src, keys->ports.dst, ++ keys->basic.ip_proto, filter_node->rq_id, 0); ++ ++ return res; ++} ++ ++/* edma_add_rfs_filter() ++ * Add RFS filter to switch ++ */ ++static int edma_add_rfs_filter(struct edma_adapter *adapter, ++ struct flow_keys *keys, u16 rq, ++ struct edma_rfs_filter_node *filter_node) ++{ ++ int res = -1; ++ ++ struct flow_keys *dest_keys = &filter_node->keys; ++ ++ memcpy(dest_keys, &filter_node->keys, sizeof(*dest_keys)); ++/* ++ dest_keys->control = keys->control; ++ dest_keys->basic = keys->basic; ++ dest_keys->addrs = keys->addrs; ++ dest_keys->ports = keys->ports; ++ dest_keys.ip_proto = keys->ip_proto; ++*/ ++ /* Call callback registered by ESS driver */ ++ if (likely(adapter->set_rfs_rule)) ++ res = (*adapter->set_rfs_rule)(adapter->netdev, flow_get_u32_src(keys), ++ flow_get_u32_dst(keys), keys->ports.src, keys->ports.dst, ++ keys->basic.ip_proto, rq, 1); ++ ++ return res; ++} ++ ++/* edma_rfs_key_search() ++ * Look for existing RFS entry ++ */ ++static struct edma_rfs_filter_node *edma_rfs_key_search(struct hlist_head *h, ++ struct flow_keys *key) ++{ ++ struct edma_rfs_filter_node *p; ++ ++ hlist_for_each_entry(p, h, node) ++ if (flow_get_u32_src(&p->keys) == flow_get_u32_src(key) && ++ flow_get_u32_dst(&p->keys) == flow_get_u32_dst(key) && ++ p->keys.ports.src == key->ports.src && ++ p->keys.ports.dst == key->ports.dst && ++ p->keys.basic.ip_proto == key->basic.ip_proto) ++ return p; ++ return NULL; ++} ++ ++/* edma_initialise_rfs_flow_table() ++ * Initialise EDMA RFS flow table ++ */ ++static void edma_initialise_rfs_flow_table(struct edma_adapter *adapter) ++{ ++ int i; ++ ++ spin_lock_init(&adapter->rfs.rfs_ftab_lock); ++ ++ /* Initialize EDMA flow hash table */ ++ for (i = 0; i < EDMA_RFS_FLOW_ENTRIES; i++) ++ INIT_HLIST_HEAD(&adapter->rfs.hlist_head[i]); ++ ++ adapter->rfs.max_num_filter = EDMA_RFS_FLOW_ENTRIES; ++ adapter->rfs.filter_available = adapter->rfs.max_num_filter; ++ adapter->rfs.hashtoclean = 0; ++ ++ /* Add timer to get periodic RFS updates from OS */ ++ init_timer(&adapter->rfs.expire_rfs); ++ adapter->rfs.expire_rfs.function = edma_flow_may_expire; ++ adapter->rfs.expire_rfs.data = (unsigned long)adapter; ++ mod_timer(&adapter->rfs.expire_rfs, jiffies + HZ / 4); ++} ++ ++/* edma_free_rfs_flow_table() ++ * Free EDMA RFS flow table ++ */ ++static void edma_free_rfs_flow_table(struct edma_adapter *adapter) ++{ ++ int i; ++ ++ /* Remove sync timer */ ++ del_timer_sync(&adapter->rfs.expire_rfs); ++ spin_lock_bh(&adapter->rfs.rfs_ftab_lock); ++ ++ /* Free EDMA RFS table entries */ ++ adapter->rfs.filter_available = 0; ++ ++ /* Clean-up EDMA flow hash table */ ++ for (i = 0; i < EDMA_RFS_FLOW_ENTRIES; i++) { ++ struct hlist_head *hhead; ++ struct hlist_node *tmp; ++ struct edma_rfs_filter_node *filter_node; ++ int res; ++ ++ hhead = &adapter->rfs.hlist_head[i]; ++ hlist_for_each_entry_safe(filter_node, tmp, hhead, node) { ++ res = edma_delete_rfs_filter(adapter, filter_node); ++ if (res < 0) ++ dev_warn(&adapter->netdev->dev, ++ "EDMA going down but RFS entry %d not allowed to be flushed by Switch", ++ filter_node->flow_id); ++ hlist_del(&filter_node->node); ++ kfree(filter_node); ++ } ++ } ++ spin_unlock_bh(&adapter->rfs.rfs_ftab_lock); ++} ++ ++/* edma_tx_unmap_and_free() ++ * clean TX buffer ++ */ ++static inline void edma_tx_unmap_and_free(struct platform_device *pdev, ++ struct edma_sw_desc *sw_desc) ++{ ++ struct sk_buff *skb = sw_desc->skb; ++ ++ if (likely((sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_HEAD) || ++ (sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_FRAGLIST))) ++ /* unmap_single for skb head area */ ++ dma_unmap_single(&pdev->dev, sw_desc->dma, ++ sw_desc->length, DMA_TO_DEVICE); ++ else if (sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_FRAG) ++ /* unmap page for paged fragments */ ++ dma_unmap_page(&pdev->dev, sw_desc->dma, ++ sw_desc->length, DMA_TO_DEVICE); ++ ++ if (likely(sw_desc->flags & EDMA_SW_DESC_FLAG_LAST)) ++ dev_kfree_skb_any(skb); ++ ++ sw_desc->flags = 0; ++} ++ ++/* edma_tx_complete() ++ * Used to clean tx queues and update hardware and consumer index ++ */ ++static void edma_tx_complete(struct edma_common_info *edma_cinfo, int queue_id) ++{ ++ struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[queue_id]; ++ struct edma_sw_desc *sw_desc; ++ struct platform_device *pdev = edma_cinfo->pdev; ++ int i; ++ ++ u16 sw_next_to_clean = etdr->sw_next_to_clean; ++ u16 hw_next_to_clean; ++ u32 data = 0; ++ ++ edma_read_reg(EDMA_REG_TPD_IDX_Q(queue_id), &data); ++ hw_next_to_clean = (data >> EDMA_TPD_CONS_IDX_SHIFT) & EDMA_TPD_CONS_IDX_MASK; ++ ++ /* clean the buffer here */ ++ while (sw_next_to_clean != hw_next_to_clean) { ++ sw_desc = &etdr->sw_desc[sw_next_to_clean]; ++ edma_tx_unmap_and_free(pdev, sw_desc); ++ sw_next_to_clean = (sw_next_to_clean + 1) & (etdr->count - 1); ++ } ++ ++ etdr->sw_next_to_clean = sw_next_to_clean; ++ ++ /* update the TPD consumer index register */ ++ edma_write_reg(EDMA_REG_TX_SW_CONS_IDX_Q(queue_id), sw_next_to_clean); ++ ++ /* Wake the queue if queue is stopped and netdev link is up */ ++ for (i = 0; i < EDMA_MAX_NETDEV_PER_QUEUE && etdr->nq[i] ; i++) { ++ if (netif_tx_queue_stopped(etdr->nq[i])) { ++ if ((etdr->netdev[i]) && netif_carrier_ok(etdr->netdev[i])) ++ netif_tx_wake_queue(etdr->nq[i]); ++ } ++ } ++} ++ ++/* edma_get_tx_buffer() ++ * Get sw_desc corresponding to the TPD ++ */ ++static struct edma_sw_desc *edma_get_tx_buffer(struct edma_common_info *edma_cinfo, ++ struct edma_tx_desc *tpd, int queue_id) ++{ ++ struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[queue_id]; ++ return &etdr->sw_desc[tpd - (struct edma_tx_desc *)etdr->hw_desc]; ++} ++ ++/* edma_get_next_tpd() ++ * Return a TPD descriptor for transfer ++ */ ++static struct edma_tx_desc *edma_get_next_tpd(struct edma_common_info *edma_cinfo, ++ int queue_id) ++{ ++ struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[queue_id]; ++ u16 sw_next_to_fill = etdr->sw_next_to_fill; ++ struct edma_tx_desc *tpd_desc = ++ (&((struct edma_tx_desc *)(etdr->hw_desc))[sw_next_to_fill]); ++ ++ etdr->sw_next_to_fill = (etdr->sw_next_to_fill + 1) & (etdr->count - 1); ++ ++ return tpd_desc; ++} ++ ++/* edma_tpd_available() ++ * Check number of free TPDs ++ */ ++static inline u16 edma_tpd_available(struct edma_common_info *edma_cinfo, ++ int queue_id) ++{ ++ struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[queue_id]; ++ ++ u16 sw_next_to_fill; ++ u16 sw_next_to_clean; ++ u16 count = 0; ++ ++ sw_next_to_clean = etdr->sw_next_to_clean; ++ sw_next_to_fill = etdr->sw_next_to_fill; ++ ++ if (likely(sw_next_to_clean <= sw_next_to_fill)) ++ count = etdr->count; ++ ++ return count + sw_next_to_clean - sw_next_to_fill - 1; ++} ++ ++/* edma_tx_queue_get() ++ * Get the starting number of the queue ++ */ ++static inline int edma_tx_queue_get(struct edma_adapter *adapter, ++ struct sk_buff *skb, int txq_id) ++{ ++ /* skb->priority is used as an index to skb priority table ++ * and based on packet priority, correspong queue is assigned. ++ */ ++ return adapter->tx_start_offset[txq_id] + edma_skb_priority_offset(skb); ++} ++ ++/* edma_tx_update_hw_idx() ++ * update the producer index for the ring transmitted ++ */ ++static void edma_tx_update_hw_idx(struct edma_common_info *edma_cinfo, ++ struct sk_buff *skb, int queue_id) ++{ ++ struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[queue_id]; ++ u32 tpd_idx_data; ++ ++ /* Read and update the producer index */ ++ edma_read_reg(EDMA_REG_TPD_IDX_Q(queue_id), &tpd_idx_data); ++ tpd_idx_data &= ~EDMA_TPD_PROD_IDX_BITS; ++ tpd_idx_data |= (etdr->sw_next_to_fill & EDMA_TPD_PROD_IDX_MASK) ++ << EDMA_TPD_PROD_IDX_SHIFT; ++ ++ edma_write_reg(EDMA_REG_TPD_IDX_Q(queue_id), tpd_idx_data); ++} ++ ++/* edma_rollback_tx() ++ * Function to retrieve tx resources in case of error ++ */ ++static void edma_rollback_tx(struct edma_adapter *adapter, ++ struct edma_tx_desc *start_tpd, int queue_id) ++{ ++ struct edma_tx_desc_ring *etdr = adapter->edma_cinfo->tpd_ring[queue_id]; ++ struct edma_sw_desc *sw_desc; ++ struct edma_tx_desc *tpd = NULL; ++ u16 start_index, index; ++ ++ start_index = start_tpd - (struct edma_tx_desc *)(etdr->hw_desc); ++ ++ index = start_index; ++ while (index != etdr->sw_next_to_fill) { ++ tpd = (&((struct edma_tx_desc *)(etdr->hw_desc))[index]); ++ sw_desc = &etdr->sw_desc[index]; ++ edma_tx_unmap_and_free(adapter->pdev, sw_desc); ++ memset(tpd, 0, sizeof(struct edma_tx_desc)); ++ if (++index == etdr->count) ++ index = 0; ++ } ++ etdr->sw_next_to_fill = start_index; ++} ++ ++/* edma_tx_map_and_fill() ++ * gets called from edma_xmit_frame ++ * ++ * This is where the dma of the buffer to be transmitted ++ * gets mapped ++ */ ++static int edma_tx_map_and_fill(struct edma_common_info *edma_cinfo, ++ struct edma_adapter *adapter, struct sk_buff *skb, int queue_id, ++ unsigned int flags_transmit, u16 from_cpu, u16 dp_bitmap, ++ bool packet_is_rstp, int nr_frags) ++{ ++ struct edma_sw_desc *sw_desc = NULL; ++ struct platform_device *pdev = edma_cinfo->pdev; ++ struct edma_tx_desc *tpd = NULL, *start_tpd = NULL; ++ struct sk_buff *iter_skb; ++ int i = 0; ++ u32 word1 = 0, word3 = 0, lso_word1 = 0, svlan_tag = 0; ++ u16 buf_len, lso_desc_len = 0; ++ ++ /* It should either be a nr_frags skb or fraglist skb but not both */ ++ BUG_ON(nr_frags && skb_has_frag_list(skb)); ++ ++ if (skb_is_gso(skb)) { ++ /* TODO: What additional checks need to be performed here */ ++ if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) { ++ lso_word1 |= EDMA_TPD_IPV4_EN; ++ ip_hdr(skb)->check = 0; ++ tcp_hdr(skb)->check = ~csum_tcpudp_magic(ip_hdr(skb)->saddr, ++ ip_hdr(skb)->daddr, 0, IPPROTO_TCP, 0); ++ } else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) { ++ lso_word1 |= EDMA_TPD_LSO_V2_EN; ++ ipv6_hdr(skb)->payload_len = 0; ++ tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, ++ &ipv6_hdr(skb)->daddr, 0, IPPROTO_TCP, 0); ++ } else ++ return -EINVAL; ++ ++ lso_word1 |= EDMA_TPD_LSO_EN | ((skb_shinfo(skb)->gso_size & EDMA_TPD_MSS_MASK) << EDMA_TPD_MSS_SHIFT) | ++ (skb_transport_offset(skb) << EDMA_TPD_HDR_SHIFT); ++ } else if (flags_transmit & EDMA_HW_CHECKSUM) { ++ u8 css, cso; ++ cso = skb_checksum_start_offset(skb); ++ css = cso + skb->csum_offset; ++ ++ word1 |= (EDMA_TPD_CUSTOM_CSUM_EN); ++ word1 |= (cso >> 1) << EDMA_TPD_HDR_SHIFT; ++ word1 |= ((css >> 1) << EDMA_TPD_CUSTOM_CSUM_SHIFT); ++ } ++ ++ if (skb->protocol == htons(ETH_P_PPP_SES)) ++ word1 |= EDMA_TPD_PPPOE_EN; ++ ++ if (flags_transmit & EDMA_VLAN_TX_TAG_INSERT_FLAG) { ++ switch(skb->vlan_proto) { ++ case htons(ETH_P_8021Q): ++ word3 |= (1 << EDMA_TX_INS_CVLAN); ++ word3 |= skb_vlan_tag_get(skb) << EDMA_TX_CVLAN_TAG_SHIFT; ++ break; ++ case htons(ETH_P_8021AD): ++ word1 |= (1 << EDMA_TX_INS_SVLAN); ++ svlan_tag = skb_vlan_tag_get(skb) << EDMA_TX_SVLAN_TAG_SHIFT; ++ break; ++ default: ++ dev_err(&pdev->dev, "no ctag or stag present\n"); ++ goto vlan_tag_error; ++ } ++ } else if (flags_transmit & EDMA_VLAN_TX_TAG_INSERT_DEFAULT_FLAG) { ++ word3 |= (1 << EDMA_TX_INS_CVLAN); ++ word3 |= (adapter->default_vlan_tag) << EDMA_TX_CVLAN_TAG_SHIFT; ++ } ++ ++ if (packet_is_rstp) { ++ word3 |= dp_bitmap << EDMA_TPD_PORT_BITMAP_SHIFT; ++ word3 |= from_cpu << EDMA_TPD_FROM_CPU_SHIFT; ++ } else { ++ word3 |= adapter->dp_bitmap << EDMA_TPD_PORT_BITMAP_SHIFT; ++ } ++ ++ buf_len = skb_headlen(skb); ++ ++ if (lso_word1) { ++ if (lso_word1 & EDMA_TPD_LSO_V2_EN) { ++ ++ /* IPv6 LSOv2 descriptor */ ++ start_tpd = tpd = edma_get_next_tpd(edma_cinfo, queue_id); ++ sw_desc = edma_get_tx_buffer(edma_cinfo, tpd, queue_id); ++ sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_NONE; ++ ++ /* LSOv2 descriptor overrides addr field to pass length */ ++ tpd->addr = cpu_to_le16(skb->len); ++ tpd->svlan_tag = svlan_tag; ++ tpd->word1 = word1 | lso_word1; ++ tpd->word3 = word3; ++ } ++ ++ tpd = edma_get_next_tpd(edma_cinfo, queue_id); ++ if (!start_tpd) ++ start_tpd = tpd; ++ sw_desc = edma_get_tx_buffer(edma_cinfo, tpd, queue_id); ++ ++ /* The last buffer info contain the skb address, ++ * so skb will be freed after unmap ++ */ ++ sw_desc->length = lso_desc_len; ++ sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_HEAD; ++ ++ sw_desc->dma = dma_map_single(&adapter->pdev->dev, ++ skb->data, buf_len, DMA_TO_DEVICE); ++ if (dma_mapping_error(&pdev->dev, sw_desc->dma)) ++ goto dma_error; ++ ++ tpd->addr = cpu_to_le32(sw_desc->dma); ++ tpd->len = cpu_to_le16(buf_len); ++ ++ tpd->svlan_tag = svlan_tag; ++ tpd->word1 = word1 | lso_word1; ++ tpd->word3 = word3; ++ ++ /* The last buffer info contain the skb address, ++ * so it will be freed after unmap ++ */ ++ sw_desc->length = lso_desc_len; ++ sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_HEAD; ++ ++ buf_len = 0; ++ } ++ ++ if (likely(buf_len)) { ++ ++ /* TODO Do not dequeue descriptor if there is a potential error */ ++ tpd = edma_get_next_tpd(edma_cinfo, queue_id); ++ ++ if (!start_tpd) ++ start_tpd = tpd; ++ ++ sw_desc = edma_get_tx_buffer(edma_cinfo, tpd, queue_id); ++ ++ /* The last buffer info contain the skb address, ++ * so it will be free after unmap ++ */ ++ sw_desc->length = buf_len; ++ sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_HEAD; ++ sw_desc->dma = dma_map_single(&adapter->pdev->dev, ++ skb->data, buf_len, DMA_TO_DEVICE); ++ if (dma_mapping_error(&pdev->dev, sw_desc->dma)) ++ goto dma_error; ++ ++ tpd->addr = cpu_to_le32(sw_desc->dma); ++ tpd->len = cpu_to_le16(buf_len); ++ ++ tpd->svlan_tag = svlan_tag; ++ tpd->word1 = word1 | lso_word1; ++ tpd->word3 = word3; ++ } ++ ++ /* Walk through all paged fragments */ ++ while (nr_frags--) { ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ++ buf_len = skb_frag_size(frag); ++ tpd = edma_get_next_tpd(edma_cinfo, queue_id); ++ sw_desc = edma_get_tx_buffer(edma_cinfo, tpd, queue_id); ++ sw_desc->length = buf_len; ++ sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_FRAG; ++ ++ sw_desc->dma = skb_frag_dma_map(&pdev->dev, frag, 0, buf_len, DMA_TO_DEVICE); ++ ++ if (dma_mapping_error(NULL, sw_desc->dma)) ++ goto dma_error; ++ ++ tpd->addr = cpu_to_le32(sw_desc->dma); ++ tpd->len = cpu_to_le16(buf_len); ++ ++ tpd->svlan_tag = svlan_tag; ++ tpd->word1 = word1 | lso_word1; ++ tpd->word3 = word3; ++ i++; ++ } ++ ++ /* Walk through all fraglist skbs */ ++ skb_walk_frags(skb, iter_skb) { ++ buf_len = iter_skb->len; ++ tpd = edma_get_next_tpd(edma_cinfo, queue_id); ++ sw_desc = edma_get_tx_buffer(edma_cinfo, tpd, queue_id); ++ sw_desc->length = buf_len; ++ sw_desc->dma = dma_map_single(&adapter->pdev->dev, ++ iter_skb->data, buf_len, DMA_TO_DEVICE); ++ ++ if (dma_mapping_error(NULL, sw_desc->dma)) ++ goto dma_error; ++ ++ tpd->addr = cpu_to_le32(sw_desc->dma); ++ tpd->len = cpu_to_le16(buf_len); ++ tpd->svlan_tag = svlan_tag; ++ tpd->word1 = word1 | lso_word1; ++ tpd->word3 = word3; ++ sw_desc->flags |= EDMA_SW_DESC_FLAG_SKB_FRAGLIST; ++ } ++ ++ if (tpd) ++ tpd->word1 |= 1 << EDMA_TPD_EOP_SHIFT; ++ ++ sw_desc->skb = skb; ++ sw_desc->flags |= EDMA_SW_DESC_FLAG_LAST; ++ ++ return 0; ++ ++dma_error: ++ edma_rollback_tx(adapter, start_tpd, queue_id); ++ dev_err(&pdev->dev, "TX DMA map failed\n"); ++vlan_tag_error: ++ return -ENOMEM; ++} ++ ++/* edma_check_link() ++ * check Link status ++ */ ++static int edma_check_link(struct edma_adapter *adapter) ++{ ++ struct phy_device *phydev = adapter->phydev; ++ ++ if (!(adapter->poll_required)) ++ return __EDMA_LINKUP; ++ ++ if (phydev->link) ++ return __EDMA_LINKUP; ++ ++ return __EDMA_LINKDOWN; ++} ++ ++/* edma_adjust_link() ++ * check for edma link status ++ */ ++void edma_adjust_link(struct net_device *netdev) ++{ ++ int status; ++ struct edma_adapter *adapter = netdev_priv(netdev); ++ struct phy_device *phydev = adapter->phydev; ++ ++ if (!test_bit(__EDMA_UP, &adapter->state_flags)) ++ return; ++ ++ status = edma_check_link(adapter); ++ ++ if (status == __EDMA_LINKUP && adapter->link_state == __EDMA_LINKDOWN) { ++ dev_info(&adapter->pdev->dev, "%s: GMAC Link is up with phy_speed=%d\n", netdev->name, phydev->speed); ++ adapter->link_state = __EDMA_LINKUP; ++ netif_carrier_on(netdev); ++ if (netif_running(netdev)) ++ netif_tx_wake_all_queues(netdev); ++ } else if (status == __EDMA_LINKDOWN && adapter->link_state == __EDMA_LINKUP) { ++ dev_info(&adapter->pdev->dev, "%s: GMAC Link is down\n", netdev->name); ++ adapter->link_state = __EDMA_LINKDOWN; ++ netif_carrier_off(netdev); ++ netif_tx_stop_all_queues(netdev); ++ } ++} ++ ++/* edma_get_stats() ++ * Statistics api used to retreive the tx/rx statistics ++ */ ++struct net_device_stats *edma_get_stats(struct net_device *netdev) ++{ ++ struct edma_adapter *adapter = netdev_priv(netdev); ++ ++ return &adapter->stats; ++} ++ ++/* edma_xmit() ++ * Main api to be called by the core for packet transmission ++ */ ++netdev_tx_t edma_xmit(struct sk_buff *skb, ++ struct net_device *net_dev) ++{ ++ struct edma_adapter *adapter = netdev_priv(net_dev); ++ struct edma_common_info *edma_cinfo = adapter->edma_cinfo; ++ struct edma_tx_desc_ring *etdr; ++ u16 from_cpu, dp_bitmap, txq_id; ++ int ret, nr_frags = 0, num_tpds_needed = 1, queue_id; ++ unsigned int flags_transmit = 0; ++ bool packet_is_rstp = false; ++ struct netdev_queue *nq = NULL; ++ ++ if (skb_shinfo(skb)->nr_frags) { ++ nr_frags = skb_shinfo(skb)->nr_frags; ++ num_tpds_needed += nr_frags; ++ } else if (skb_has_frag_list(skb)) { ++ struct sk_buff *iter_skb; ++ ++ skb_walk_frags(skb, iter_skb) ++ num_tpds_needed++; ++ } ++ ++ if (num_tpds_needed > EDMA_MAX_SKB_FRAGS) { ++ dev_err(&net_dev->dev, ++ "skb received with fragments %d which is more than %lu", ++ num_tpds_needed, EDMA_MAX_SKB_FRAGS); ++ dev_kfree_skb_any(skb); ++ adapter->stats.tx_errors++; ++ return NETDEV_TX_OK; ++ } ++ ++ if (edma_stp_rstp) { ++ u16 ath_hdr, ath_eth_type; ++ u8 mac_addr[EDMA_ETH_HDR_LEN]; ++ ath_eth_type = ntohs(*(uint16_t *)&skb->data[12]); ++ if (ath_eth_type == edma_ath_eth_type) { ++ packet_is_rstp = true; ++ ath_hdr = htons(*(uint16_t *)&skb->data[14]); ++ dp_bitmap = ath_hdr & EDMA_TX_ATH_HDR_PORT_BITMAP_MASK; ++ from_cpu = (ath_hdr & EDMA_TX_ATH_HDR_FROM_CPU_MASK) >> EDMA_TX_ATH_HDR_FROM_CPU_SHIFT; ++ memcpy(mac_addr, skb->data, EDMA_ETH_HDR_LEN); ++ ++ skb_pull(skb, 4); ++ ++ memcpy(skb->data, mac_addr, EDMA_ETH_HDR_LEN); ++ } ++ } ++ ++ /* this will be one of the 4 TX queues exposed to linux kernel */ ++ txq_id = skb_get_queue_mapping(skb); ++ queue_id = edma_tx_queue_get(adapter, skb, txq_id); ++ etdr = edma_cinfo->tpd_ring[queue_id]; ++ nq = netdev_get_tx_queue(net_dev, txq_id); ++ ++ local_bh_disable(); ++ /* Tx is not handled in bottom half context. Hence, we need to protect ++ * Tx from tasks and bottom half ++ */ ++ ++ if (num_tpds_needed > edma_tpd_available(edma_cinfo, queue_id)) { ++ /* not enough descriptor, just stop queue */ ++ netif_tx_stop_queue(nq); ++ local_bh_enable(); ++ dev_dbg(&net_dev->dev, "Not enough descriptors available"); ++ edma_cinfo->edma_ethstats.tx_desc_error++; ++ return NETDEV_TX_BUSY; ++ } ++ ++ /* Check and mark VLAN tag offload */ ++ if (skb_vlan_tag_present(skb)) ++ flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_FLAG; ++ else if (adapter->default_vlan_tag) ++ flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_DEFAULT_FLAG; ++ ++ /* Check and mark checksum offload */ ++ if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) ++ flags_transmit |= EDMA_HW_CHECKSUM; ++ ++ /* Map and fill descriptor for Tx */ ++ ret = edma_tx_map_and_fill(edma_cinfo, adapter, skb, queue_id, ++ flags_transmit, from_cpu, dp_bitmap, packet_is_rstp, nr_frags); ++ if (ret) { ++ dev_kfree_skb_any(skb); ++ adapter->stats.tx_errors++; ++ goto netdev_okay; ++ } ++ ++ /* Update SW producer index */ ++ edma_tx_update_hw_idx(edma_cinfo, skb, queue_id); ++ ++ /* update tx statistics */ ++ adapter->stats.tx_packets++; ++ adapter->stats.tx_bytes += skb->len; ++ ++netdev_okay: ++ local_bh_enable(); ++ return NETDEV_TX_OK; ++} ++ ++/* ++ * edma_flow_may_expire() ++ * Timer function called periodically to delete the node ++ */ ++void edma_flow_may_expire(unsigned long data) ++{ ++ struct edma_adapter *adapter = (struct edma_adapter *)data; ++ int j; ++ ++ spin_lock_bh(&adapter->rfs.rfs_ftab_lock); ++ for (j = 0; j < EDMA_RFS_EXPIRE_COUNT_PER_CALL; j++) { ++ struct hlist_head *hhead; ++ struct hlist_node *tmp; ++ struct edma_rfs_filter_node *n; ++ bool res; ++ ++ hhead = &adapter->rfs.hlist_head[adapter->rfs.hashtoclean++]; ++ hlist_for_each_entry_safe(n, tmp, hhead, node) { ++ res = rps_may_expire_flow(adapter->netdev, n->rq_id, ++ n->flow_id, n->filter_id); ++ if (res) { ++ int ret; ++ ret = edma_delete_rfs_filter(adapter, n); ++ if (ret < 0) ++ dev_dbg(&adapter->netdev->dev, ++ "RFS entry %d not allowed to be flushed by Switch", ++ n->flow_id); ++ else { ++ hlist_del(&n->node); ++ kfree(n); ++ adapter->rfs.filter_available++; ++ } ++ } ++ } ++ } ++ ++ adapter->rfs.hashtoclean = adapter->rfs.hashtoclean & (EDMA_RFS_FLOW_ENTRIES - 1); ++ spin_unlock_bh(&adapter->rfs.rfs_ftab_lock); ++ mod_timer(&adapter->rfs.expire_rfs, jiffies + HZ / 4); ++} ++ ++/* edma_rx_flow_steer() ++ * Called by core to to steer the flow to CPU ++ */ ++int edma_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, ++ u16 rxq, u32 flow_id) ++{ ++ struct flow_keys keys; ++ struct edma_rfs_filter_node *filter_node; ++ struct edma_adapter *adapter = netdev_priv(dev); ++ u16 hash_tblid; ++ int res; ++ ++ if (skb->protocol == htons(ETH_P_IPV6)) { ++ dev_err(&adapter->pdev->dev, "IPv6 not supported\n"); ++ res = -EINVAL; ++ goto no_protocol_err; ++ } ++ ++ /* Dissect flow parameters ++ * We only support IPv4 + TCP/UDP ++ */ ++ res = skb_flow_dissect_flow_keys(skb, &keys, 0); ++ if (!((keys.basic.ip_proto == IPPROTO_TCP) || (keys.basic.ip_proto == IPPROTO_UDP))) { ++ res = -EPROTONOSUPPORT; ++ goto no_protocol_err; ++ } ++ ++ /* Check if table entry exists */ ++ hash_tblid = skb_get_hash_raw(skb) & EDMA_RFS_FLOW_ENTRIES_MASK; ++ ++ spin_lock_bh(&adapter->rfs.rfs_ftab_lock); ++ filter_node = edma_rfs_key_search(&adapter->rfs.hlist_head[hash_tblid], &keys); ++ ++ if (filter_node) { ++ if (rxq == filter_node->rq_id) { ++ res = -EEXIST; ++ goto out; ++ } else { ++ res = edma_delete_rfs_filter(adapter, filter_node); ++ if (res < 0) ++ dev_warn(&adapter->netdev->dev, ++ "Cannot steer flow %d to different queue", ++ filter_node->flow_id); ++ else { ++ adapter->rfs.filter_available++; ++ res = edma_add_rfs_filter(adapter, &keys, rxq, filter_node); ++ if (res < 0) { ++ dev_warn(&adapter->netdev->dev, ++ "Cannot steer flow %d to different queue", ++ filter_node->flow_id); ++ } else { ++ adapter->rfs.filter_available--; ++ filter_node->rq_id = rxq; ++ filter_node->filter_id = res; ++ } ++ } ++ } ++ } else { ++ if (adapter->rfs.filter_available == 0) { ++ res = -EBUSY; ++ goto out; ++ } ++ ++ filter_node = kmalloc(sizeof(*filter_node), GFP_ATOMIC); ++ if (!filter_node) { ++ res = -ENOMEM; ++ goto out; ++ } ++ ++ res = edma_add_rfs_filter(adapter, &keys, rxq, filter_node); ++ if (res < 0) { ++ kfree(filter_node); ++ goto out; ++ } ++ ++ adapter->rfs.filter_available--; ++ filter_node->rq_id = rxq; ++ filter_node->filter_id = res; ++ filter_node->flow_id = flow_id; ++ filter_node->keys = keys; ++ INIT_HLIST_NODE(&filter_node->node); ++ hlist_add_head(&filter_node->node, &adapter->rfs.hlist_head[hash_tblid]); ++ } ++ ++out: ++ spin_unlock_bh(&adapter->rfs.rfs_ftab_lock); ++no_protocol_err: ++ return res; ++} ++ ++/* edma_register_rfs_filter() ++ * Add RFS filter callback ++ */ ++int edma_register_rfs_filter(struct net_device *netdev, ++ set_rfs_filter_callback_t set_filter) ++{ ++ struct edma_adapter *adapter = netdev_priv(netdev); ++ ++ spin_lock_bh(&adapter->rfs.rfs_ftab_lock); ++ ++ if (adapter->set_rfs_rule) { ++ spin_unlock_bh(&adapter->rfs.rfs_ftab_lock); ++ return -1; ++ } ++ ++ adapter->set_rfs_rule = set_filter; ++ spin_unlock_bh(&adapter->rfs.rfs_ftab_lock); ++ ++ return 0; ++} ++ ++/* edma_alloc_tx_rings() ++ * Allocate rx rings ++ */ ++int edma_alloc_tx_rings(struct edma_common_info *edma_cinfo) ++{ ++ struct platform_device *pdev = edma_cinfo->pdev; ++ int i, err = 0; ++ ++ for (i = 0; i < edma_cinfo->num_tx_queues; i++) { ++ err = edma_alloc_tx_ring(edma_cinfo, edma_cinfo->tpd_ring[i]); ++ if (err) { ++ dev_err(&pdev->dev, "Tx Queue alloc %u failed\n", i); ++ return err; ++ } ++ } ++ ++ return 0; ++} ++ ++/* edma_free_tx_rings() ++ * Free tx rings ++ */ ++void edma_free_tx_rings(struct edma_common_info *edma_cinfo) ++{ ++ int i; ++ ++ for (i = 0; i < edma_cinfo->num_tx_queues; i++) ++ edma_free_tx_ring(edma_cinfo, edma_cinfo->tpd_ring[i]); ++} ++ ++/* edma_free_tx_resources() ++ * Free buffers associated with tx rings ++ */ ++void edma_free_tx_resources(struct edma_common_info *edma_cinfo) ++{ ++ struct edma_tx_desc_ring *etdr; ++ struct edma_sw_desc *sw_desc; ++ struct platform_device *pdev = edma_cinfo->pdev; ++ int i, j; ++ ++ for (i = 0; i < edma_cinfo->num_tx_queues; i++) { ++ etdr = edma_cinfo->tpd_ring[i]; ++ for (j = 0; j < EDMA_TX_RING_SIZE; j++) { ++ sw_desc = &etdr->sw_desc[j]; ++ if (sw_desc->flags & (EDMA_SW_DESC_FLAG_SKB_HEAD | ++ EDMA_SW_DESC_FLAG_SKB_FRAG | EDMA_SW_DESC_FLAG_SKB_FRAGLIST)) ++ edma_tx_unmap_and_free(pdev, sw_desc); ++ } ++ } ++} ++ ++/* edma_alloc_rx_rings() ++ * Allocate rx rings ++ */ ++int edma_alloc_rx_rings(struct edma_common_info *edma_cinfo) ++{ ++ struct platform_device *pdev = edma_cinfo->pdev; ++ int i, j, err = 0; ++ ++ for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { ++ err = edma_alloc_rx_ring(edma_cinfo, edma_cinfo->rfd_ring[j]); ++ if (err) { ++ dev_err(&pdev->dev, "Rx Queue alloc%u failed\n", i); ++ return err; ++ } ++ j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); ++ } ++ ++ return 0; ++} ++ ++/* edma_free_rx_rings() ++ * free rx rings ++ */ ++void edma_free_rx_rings(struct edma_common_info *edma_cinfo) ++{ ++ int i, j; ++ ++ for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { ++ edma_free_rx_ring(edma_cinfo, edma_cinfo->rfd_ring[j]); ++ j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); ++ } ++} ++ ++/* edma_free_queues() ++ * Free the queues allocaated ++ */ ++void edma_free_queues(struct edma_common_info *edma_cinfo) ++{ ++ int i , j; ++ ++ for (i = 0; i < edma_cinfo->num_tx_queues; i++) { ++ if (edma_cinfo->tpd_ring[i]) ++ kfree(edma_cinfo->tpd_ring[i]); ++ edma_cinfo->tpd_ring[i] = NULL; ++ } ++ ++ for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { ++ if (edma_cinfo->rfd_ring[j]) ++ kfree(edma_cinfo->rfd_ring[j]); ++ edma_cinfo->rfd_ring[j] = NULL; ++ j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); ++ } ++ ++ edma_cinfo->num_rx_queues = 0; ++ edma_cinfo->num_tx_queues = 0; ++ ++ return; ++} ++ ++/* edma_free_rx_resources() ++ * Free buffers associated with tx rings ++ */ ++void edma_free_rx_resources(struct edma_common_info *edma_cinfo) ++{ ++ struct edma_rfd_desc_ring *erdr; ++ struct edma_sw_desc *sw_desc; ++ struct platform_device *pdev = edma_cinfo->pdev; ++ int i, j, k; ++ ++ for (i = 0, k = 0; i < edma_cinfo->num_rx_queues; i++) { ++ erdr = edma_cinfo->rfd_ring[k]; ++ for (j = 0; j < EDMA_RX_RING_SIZE; j++) { ++ sw_desc = &erdr->sw_desc[j]; ++ if (likely(sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_HEAD)) { ++ dma_unmap_single(&pdev->dev, sw_desc->dma, ++ sw_desc->length, DMA_FROM_DEVICE); ++ edma_clean_rfd(erdr, j); ++ } else if ((sw_desc->flags & EDMA_SW_DESC_FLAG_SKB_FRAG)) { ++ dma_unmap_page(&pdev->dev, sw_desc->dma, ++ sw_desc->length, DMA_FROM_DEVICE); ++ edma_clean_rfd(erdr, j); ++ } ++ } ++ k += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); ++ ++ } ++} ++ ++/* edma_alloc_queues_tx() ++ * Allocate memory for all rings ++ */ ++int edma_alloc_queues_tx(struct edma_common_info *edma_cinfo) ++{ ++ int i; ++ ++ for (i = 0; i < edma_cinfo->num_tx_queues; i++) { ++ struct edma_tx_desc_ring *etdr; ++ etdr = kzalloc(sizeof(struct edma_tx_desc_ring), GFP_KERNEL); ++ if (!etdr) ++ goto err; ++ etdr->count = edma_cinfo->tx_ring_count; ++ edma_cinfo->tpd_ring[i] = etdr; ++ } ++ ++ return 0; ++err: ++ edma_free_queues(edma_cinfo); ++ return -1; ++} ++ ++/* edma_alloc_queues_rx() ++ * Allocate memory for all rings ++ */ ++int edma_alloc_queues_rx(struct edma_common_info *edma_cinfo) ++{ ++ int i, j; ++ ++ for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { ++ struct edma_rfd_desc_ring *rfd_ring; ++ rfd_ring = kzalloc(sizeof(struct edma_rfd_desc_ring), ++ GFP_KERNEL); ++ if (!rfd_ring) ++ goto err; ++ rfd_ring->count = edma_cinfo->rx_ring_count; ++ edma_cinfo->rfd_ring[j] = rfd_ring; ++ j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); ++ } ++ return 0; ++err: ++ edma_free_queues(edma_cinfo); ++ return -1; ++} ++ ++/* edma_clear_irq_status() ++ * Clear interrupt status ++ */ ++void edma_clear_irq_status() ++{ ++ edma_write_reg(EDMA_REG_RX_ISR, 0xff); ++ edma_write_reg(EDMA_REG_TX_ISR, 0xffff); ++ edma_write_reg(EDMA_REG_MISC_ISR, 0x1fff); ++ edma_write_reg(EDMA_REG_WOL_ISR, 0x1); ++}; ++ ++/* edma_configure() ++ * Configure skb, edma interrupts and control register. ++ */ ++int edma_configure(struct edma_common_info *edma_cinfo) ++{ ++ struct edma_hw *hw = &edma_cinfo->hw; ++ u32 intr_modrt_data; ++ u32 intr_ctrl_data = 0; ++ int i, j, ret_count; ++ ++ edma_read_reg(EDMA_REG_INTR_CTRL, &intr_ctrl_data); ++ intr_ctrl_data &= ~(1 << EDMA_INTR_SW_IDX_W_TYP_SHIFT); ++ intr_ctrl_data |= hw->intr_sw_idx_w << EDMA_INTR_SW_IDX_W_TYP_SHIFT; ++ edma_write_reg(EDMA_REG_INTR_CTRL, intr_ctrl_data); ++ ++ edma_clear_irq_status(); ++ ++ /* Clear any WOL status */ ++ edma_write_reg(EDMA_REG_WOL_CTRL, 0); ++ intr_modrt_data = (EDMA_TX_IMT << EDMA_IRQ_MODRT_TX_TIMER_SHIFT); ++ intr_modrt_data |= (EDMA_RX_IMT << EDMA_IRQ_MODRT_RX_TIMER_SHIFT); ++ edma_write_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, intr_modrt_data); ++ edma_configure_tx(edma_cinfo); ++ edma_configure_rx(edma_cinfo); ++ ++ /* Allocate the RX buffer */ ++ for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { ++ struct edma_rfd_desc_ring *ring = edma_cinfo->rfd_ring[j]; ++ ret_count = edma_alloc_rx_buf(edma_cinfo, ring, ring->count, j); ++ if (ret_count) { ++ dev_dbg(&edma_cinfo->pdev->dev, "not all rx buffers allocated\n"); ++ } ++ j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); ++ } ++ ++ /* Configure descriptor Ring */ ++ edma_init_desc(edma_cinfo); ++ return 0; ++} ++ ++/* edma_irq_enable() ++ * Enable default interrupt generation settings ++ */ ++void edma_irq_enable(struct edma_common_info *edma_cinfo) ++{ ++ struct edma_hw *hw = &edma_cinfo->hw; ++ int i, j; ++ ++ edma_write_reg(EDMA_REG_RX_ISR, 0xff); ++ for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { ++ edma_write_reg(EDMA_REG_RX_INT_MASK_Q(j), hw->rx_intr_mask); ++ j += ((edma_cinfo->num_rx_queues == 4) ? 2 : 1); ++ } ++ edma_write_reg(EDMA_REG_TX_ISR, 0xffff); ++ for (i = 0; i < edma_cinfo->num_tx_queues; i++) ++ edma_write_reg(EDMA_REG_TX_INT_MASK_Q(i), hw->tx_intr_mask); ++} ++ ++/* edma_irq_disable() ++ * Disable Interrupt ++ */ ++void edma_irq_disable(struct edma_common_info *edma_cinfo) ++{ ++ int i; ++ ++ for (i = 0; i < EDMA_MAX_RECEIVE_QUEUE; i++) ++ edma_write_reg(EDMA_REG_RX_INT_MASK_Q(i), 0x0); ++ ++ for (i = 0; i < EDMA_MAX_TRANSMIT_QUEUE; i++) ++ edma_write_reg(EDMA_REG_TX_INT_MASK_Q(i), 0x0); ++ edma_write_reg(EDMA_REG_MISC_IMR, 0); ++ edma_write_reg(EDMA_REG_WOL_IMR, 0); ++} ++ ++/* edma_free_irqs() ++ * Free All IRQs ++ */ ++void edma_free_irqs(struct edma_adapter *adapter) ++{ ++ struct edma_common_info *edma_cinfo = adapter->edma_cinfo; ++ int i, j; ++ int k = ((edma_cinfo->num_rx_queues == 4) ? 1 : 2); ++ ++ for (i = 0; i < CONFIG_NR_CPUS; i++) { ++ for (j = edma_cinfo->edma_percpu_info[i].tx_start; j < (edma_cinfo->edma_percpu_info[i].tx_start + 4); j++) ++ free_irq(edma_cinfo->tx_irq[j], &edma_cinfo->edma_percpu_info[i]); ++ ++ for (j = edma_cinfo->edma_percpu_info[i].rx_start; j < (edma_cinfo->edma_percpu_info[i].rx_start + k); j++) ++ free_irq(edma_cinfo->rx_irq[j], &edma_cinfo->edma_percpu_info[i]); ++ } ++} ++ ++/* edma_enable_rx_ctrl() ++ * Enable RX queue control ++ */ ++void edma_enable_rx_ctrl(struct edma_hw *hw) ++{ ++ u32 data; ++ ++ edma_read_reg(EDMA_REG_RXQ_CTRL, &data); ++ data |= EDMA_RXQ_CTRL_EN; ++ edma_write_reg(EDMA_REG_RXQ_CTRL, data); ++} ++ ++ ++/* edma_enable_tx_ctrl() ++ * Enable TX queue control ++ */ ++void edma_enable_tx_ctrl(struct edma_hw *hw) ++{ ++ u32 data; ++ ++ edma_read_reg(EDMA_REG_TXQ_CTRL, &data); ++ data |= EDMA_TXQ_CTRL_TXQ_EN; ++ edma_write_reg(EDMA_REG_TXQ_CTRL, data); ++} ++ ++/* edma_stop_rx_tx() ++ * Disable RX/TQ Queue control ++ */ ++void edma_stop_rx_tx(struct edma_hw *hw) ++{ ++ u32 data; ++ ++ edma_read_reg(EDMA_REG_RXQ_CTRL, &data); ++ data &= ~EDMA_RXQ_CTRL_EN; ++ edma_write_reg(EDMA_REG_RXQ_CTRL, data); ++ edma_read_reg(EDMA_REG_TXQ_CTRL, &data); ++ data &= ~EDMA_TXQ_CTRL_TXQ_EN; ++ edma_write_reg(EDMA_REG_TXQ_CTRL, data); ++} ++ ++/* edma_reset() ++ * Reset the EDMA ++ */ ++int edma_reset(struct edma_common_info *edma_cinfo) ++{ ++ struct edma_hw *hw = &edma_cinfo->hw; ++ ++ edma_irq_disable(edma_cinfo); ++ ++ edma_clear_irq_status(); ++ ++ edma_stop_rx_tx(hw); ++ ++ return 0; ++} ++ ++/* edma_fill_netdev() ++ * Fill netdev for each etdr ++ */ ++int edma_fill_netdev(struct edma_common_info *edma_cinfo, int queue_id, ++ int dev, int txq_id) ++{ ++ struct edma_tx_desc_ring *etdr; ++ int i = 0; ++ ++ etdr = edma_cinfo->tpd_ring[queue_id]; ++ ++ while (etdr->netdev[i]) ++ i++; ++ ++ if (i >= EDMA_MAX_NETDEV_PER_QUEUE) ++ return -1; ++ ++ /* Populate the netdev associated with the tpd ring */ ++ etdr->netdev[i] = edma_netdev[dev]; ++ etdr->nq[i] = netdev_get_tx_queue(edma_netdev[dev], txq_id); ++ ++ return 0; ++} ++ ++/* edma_set_mac() ++ * Change the Ethernet Address of the NIC ++ */ ++int edma_set_mac_addr(struct net_device *netdev, void *p) ++{ ++ struct sockaddr *addr = p; ++ ++ if (!is_valid_ether_addr(addr->sa_data)) ++ return -EINVAL; ++ ++ if (netif_running(netdev)) ++ return -EBUSY; ++ ++ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); ++ return 0; ++} ++ ++/* edma_set_stp_rstp() ++ * set stp/rstp ++ */ ++void edma_set_stp_rstp(bool rstp) ++{ ++ edma_stp_rstp = rstp; ++} ++ ++/* edma_assign_ath_hdr_type() ++ * assign atheros header eth type ++ */ ++void edma_assign_ath_hdr_type(int eth_type) ++{ ++ edma_ath_eth_type = eth_type & EDMA_ETH_TYPE_MASK; ++} ++ ++/* edma_get_default_vlan_tag() ++ * Used by other modules to get the default vlan tag ++ */ ++int edma_get_default_vlan_tag(struct net_device *netdev) ++{ ++ struct edma_adapter *adapter = netdev_priv(netdev); ++ ++ if (adapter->default_vlan_tag) ++ return adapter->default_vlan_tag; ++ ++ return 0; ++} ++ ++/* edma_open() ++ * gets called when netdevice is up, start the queue. ++ */ ++int edma_open(struct net_device *netdev) ++{ ++ struct edma_adapter *adapter = netdev_priv(netdev); ++ struct platform_device *pdev = adapter->edma_cinfo->pdev; ++ ++ netif_tx_start_all_queues(netdev); ++ edma_initialise_rfs_flow_table(adapter); ++ set_bit(__EDMA_UP, &adapter->state_flags); ++ ++ /* if Link polling is enabled, in our case enabled for WAN, then ++ * do a phy start, else always set link as UP ++ */ ++ if (adapter->poll_required) { ++ if (!IS_ERR(adapter->phydev)) { ++ phy_start(adapter->phydev); ++ phy_start_aneg(adapter->phydev); ++ adapter->link_state = __EDMA_LINKDOWN; ++ } else { ++ dev_dbg(&pdev->dev, "Invalid PHY device for a link polled interface\n"); ++ } ++ } else { ++ adapter->link_state = __EDMA_LINKUP; ++ netif_carrier_on(netdev); ++ } ++ ++ return 0; ++} ++ ++ ++/* edma_close() ++ * gets called when netdevice is down, stops the queue. ++ */ ++int edma_close(struct net_device *netdev) ++{ ++ struct edma_adapter *adapter = netdev_priv(netdev); ++ ++ edma_free_rfs_flow_table(adapter); ++ netif_carrier_off(netdev); ++ netif_tx_stop_all_queues(netdev); ++ ++ if (adapter->poll_required) { ++ if (!IS_ERR(adapter->phydev)) ++ phy_stop(adapter->phydev); ++ } ++ ++ adapter->link_state = __EDMA_LINKDOWN; ++ ++ /* Set GMAC state to UP before link state is checked ++ */ ++ clear_bit(__EDMA_UP, &adapter->state_flags); ++ ++ return 0; ++} ++ ++/* edma_poll ++ * polling function that gets called when the napi gets scheduled. ++ * ++ * Main sequence of task performed in this api ++ * is clear irq status -> clear_tx_irq -> clean_rx_irq-> ++ * enable interrupts. ++ */ ++int edma_poll(struct napi_struct *napi, int budget) ++{ ++ struct edma_per_cpu_queues_info *edma_percpu_info = container_of(napi, ++ struct edma_per_cpu_queues_info, napi); ++ struct edma_common_info *edma_cinfo = edma_percpu_info->edma_cinfo; ++ u32 reg_data; ++ u32 shadow_rx_status, shadow_tx_status; ++ int queue_id; ++ int i, work_done = 0; ++ ++ /* Store the Rx/Tx status by ANDing it with ++ * appropriate CPU RX?TX mask ++ */ ++ edma_read_reg(EDMA_REG_RX_ISR, ®_data); ++ edma_percpu_info->rx_status |= reg_data & edma_percpu_info->rx_mask; ++ shadow_rx_status = edma_percpu_info->rx_status; ++ edma_read_reg(EDMA_REG_TX_ISR, ®_data); ++ edma_percpu_info->tx_status |= reg_data & edma_percpu_info->tx_mask; ++ shadow_tx_status = edma_percpu_info->tx_status; ++ ++ /* Every core will have a start, which will be computed ++ * in probe and stored in edma_percpu_info->tx_start variable. ++ * We will shift the status bit by tx_start to obtain ++ * status bits for the core on which the current processing ++ * is happening. Since, there are 4 tx queues per core, ++ * we will run the loop till we get the correct queue to clear. ++ */ ++ while (edma_percpu_info->tx_status) { ++ queue_id = ffs(edma_percpu_info->tx_status) - 1; ++ edma_tx_complete(edma_cinfo, queue_id); ++ edma_percpu_info->tx_status &= ~(1 << queue_id); ++ } ++ ++ /* Every core will have a start, which will be computed ++ * in probe and stored in edma_percpu_info->tx_start variable. ++ * We will shift the status bit by tx_start to obtain ++ * status bits for the core on which the current processing ++ * is happening. Since, there are 4 tx queues per core, we ++ * will run the loop till we get the correct queue to clear. ++ */ ++ while (edma_percpu_info->rx_status) { ++ queue_id = ffs(edma_percpu_info->rx_status) - 1; ++ edma_rx_complete(edma_cinfo, &work_done, ++ budget, queue_id, napi); ++ ++ if (likely(work_done < budget)) ++ edma_percpu_info->rx_status &= ~(1 << queue_id); ++ else ++ break; ++ } ++ ++ /* Clear the status register, to avoid the interrupts to ++ * reoccur.This clearing of interrupt status register is ++ * done here as writing to status register only takes place ++ * once the producer/consumer index has been updated to ++ * reflect that the packet transmission/reception went fine. ++ */ ++ edma_write_reg(EDMA_REG_RX_ISR, shadow_rx_status); ++ edma_write_reg(EDMA_REG_TX_ISR, shadow_tx_status); ++ ++ /* If budget not fully consumed, exit the polling mode */ ++ if (likely(work_done < budget)) { ++ napi_complete(napi); ++ ++ /* re-enable the interrupts */ ++ for (i = 0; i < edma_cinfo->num_rxq_per_core; i++) ++ edma_write_reg(EDMA_REG_RX_INT_MASK_Q(edma_percpu_info->rx_start + i), 0x1); ++ for (i = 0; i < edma_cinfo->num_txq_per_core; i++) ++ edma_write_reg(EDMA_REG_TX_INT_MASK_Q(edma_percpu_info->tx_start + i), 0x1); ++ } ++ ++ return work_done; ++} ++ ++/* edma interrupt() ++ * interrupt handler ++ */ ++irqreturn_t edma_interrupt(int irq, void *dev) ++{ ++ struct edma_per_cpu_queues_info *edma_percpu_info = (struct edma_per_cpu_queues_info *) dev; ++ struct edma_common_info *edma_cinfo = edma_percpu_info->edma_cinfo; ++ int i; ++ ++ /* Unmask the TX/RX interrupt register */ ++ for (i = 0; i < edma_cinfo->num_rxq_per_core; i++) ++ edma_write_reg(EDMA_REG_RX_INT_MASK_Q(edma_percpu_info->rx_start + i), 0x0); ++ ++ for (i = 0; i < edma_cinfo->num_txq_per_core; i++) ++ edma_write_reg(EDMA_REG_TX_INT_MASK_Q(edma_percpu_info->tx_start + i), 0x0); ++ ++ napi_schedule(&edma_percpu_info->napi); ++ ++ return IRQ_HANDLED; ++} +--- /dev/null ++++ b/drivers/net/ethernet/qualcomm/essedma/edma.h +@@ -0,0 +1,446 @@ ++/* ++ * Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for ++ * any purpose with or without fee is hereby granted, provided that the ++ * above copyright notice and this permission notice appear in all copies. ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT ++ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _EDMA_H_ ++#define _EDMA_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "ess_edma.h" ++ ++#define EDMA_CPU_CORES_SUPPORTED 4 ++#define EDMA_MAX_PORTID_SUPPORTED 5 ++#define EDMA_MAX_VLAN_SUPPORTED EDMA_MAX_PORTID_SUPPORTED ++#define EDMA_MAX_PORTID_BITMAP_INDEX (EDMA_MAX_PORTID_SUPPORTED + 1) ++#define EDMA_MAX_PORTID_BITMAP_SUPPORTED 0x1f /* 0001_1111 = 0x1f */ ++#define EDMA_MAX_NETDEV_PER_QUEUE 4 /* 3 Netdev per queue, 1 space for indexing */ ++ ++#define EDMA_MAX_RECEIVE_QUEUE 8 ++#define EDMA_MAX_TRANSMIT_QUEUE 16 ++ ++/* WAN/LAN adapter number */ ++#define EDMA_WAN 0 ++#define EDMA_LAN 1 ++ ++/* VLAN tag */ ++#define EDMA_LAN_DEFAULT_VLAN 1 ++#define EDMA_WAN_DEFAULT_VLAN 2 ++ ++#define EDMA_DEFAULT_GROUP1_VLAN 1 ++#define EDMA_DEFAULT_GROUP2_VLAN 2 ++#define EDMA_DEFAULT_GROUP3_VLAN 3 ++#define EDMA_DEFAULT_GROUP4_VLAN 4 ++#define EDMA_DEFAULT_GROUP5_VLAN 5 ++ ++/* Queues exposed to linux kernel */ ++#define EDMA_NETDEV_TX_QUEUE 4 ++#define EDMA_NETDEV_RX_QUEUE 4 ++ ++/* Number of queues per core */ ++#define EDMA_NUM_TXQ_PER_CORE 4 ++#define EDMA_NUM_RXQ_PER_CORE 2 ++ ++#define EDMA_TPD_EOP_SHIFT 31 ++ ++#define EDMA_PORT_ID_SHIFT 12 ++#define EDMA_PORT_ID_MASK 0x7 ++ ++/* tpd word 3 bit 18-28 */ ++#define EDMA_TPD_PORT_BITMAP_SHIFT 18 ++ ++#define EDMA_TPD_FROM_CPU_SHIFT 25 ++ ++#define EDMA_FROM_CPU_MASK 0x80 ++#define EDMA_SKB_PRIORITY_MASK 0x38 ++ ++/* TX/RX descriptor ring count */ ++/* should be a power of 2 */ ++#define EDMA_RX_RING_SIZE 128 ++#define EDMA_TX_RING_SIZE 128 ++ ++/* Flags used in paged/non paged mode */ ++#define EDMA_RX_HEAD_BUFF_SIZE_JUMBO 256 ++#define EDMA_RX_HEAD_BUFF_SIZE 1540 ++ ++/* MAX frame size supported by switch */ ++#define EDMA_MAX_JUMBO_FRAME_SIZE 9216 ++ ++/* Configurations */ ++#define EDMA_INTR_CLEAR_TYPE 0 ++#define EDMA_INTR_SW_IDX_W_TYPE 0 ++#define EDMA_FIFO_THRESH_TYPE 0 ++#define EDMA_RSS_TYPE 0 ++#define EDMA_RX_IMT 0x0020 ++#define EDMA_TX_IMT 0x0050 ++#define EDMA_TPD_BURST 5 ++#define EDMA_TXF_BURST 0x100 ++#define EDMA_RFD_BURST 8 ++#define EDMA_RFD_THR 16 ++#define EDMA_RFD_LTHR 0 ++ ++/* RX/TX per CPU based mask/shift */ ++#define EDMA_TX_PER_CPU_MASK 0xF ++#define EDMA_RX_PER_CPU_MASK 0x3 ++#define EDMA_TX_PER_CPU_MASK_SHIFT 0x2 ++#define EDMA_RX_PER_CPU_MASK_SHIFT 0x1 ++#define EDMA_TX_CPU_START_SHIFT 0x2 ++#define EDMA_RX_CPU_START_SHIFT 0x1 ++ ++/* FLags used in transmit direction */ ++#define EDMA_HW_CHECKSUM 0x00000001 ++#define EDMA_VLAN_TX_TAG_INSERT_FLAG 0x00000002 ++#define EDMA_VLAN_TX_TAG_INSERT_DEFAULT_FLAG 0x00000004 ++ ++#define EDMA_SW_DESC_FLAG_LAST 0x1 ++#define EDMA_SW_DESC_FLAG_SKB_HEAD 0x2 ++#define EDMA_SW_DESC_FLAG_SKB_FRAG 0x4 ++#define EDMA_SW_DESC_FLAG_SKB_FRAGLIST 0x8 ++#define EDMA_SW_DESC_FLAG_SKB_NONE 0x10 ++#define EDMA_SW_DESC_FLAG_SKB_REUSE 0x20 ++ ++ ++#define EDMA_MAX_SKB_FRAGS (MAX_SKB_FRAGS + 1) ++ ++/* Ethtool specific list of EDMA supported features */ ++#define EDMA_SUPPORTED_FEATURES (SUPPORTED_10baseT_Half \ ++ | SUPPORTED_10baseT_Full \ ++ | SUPPORTED_100baseT_Half \ ++ | SUPPORTED_100baseT_Full \ ++ | SUPPORTED_1000baseT_Full) ++ ++/* Recevie side atheros Header */ ++#define EDMA_RX_ATH_HDR_VERSION 0x2 ++#define EDMA_RX_ATH_HDR_VERSION_SHIFT 14 ++#define EDMA_RX_ATH_HDR_PRIORITY_SHIFT 11 ++#define EDMA_RX_ATH_PORT_TYPE_SHIFT 6 ++#define EDMA_RX_ATH_HDR_RSTP_PORT_TYPE 0x4 ++ ++/* Transmit side atheros Header */ ++#define EDMA_TX_ATH_HDR_PORT_BITMAP_MASK 0x7F ++#define EDMA_TX_ATH_HDR_FROM_CPU_MASK 0x80 ++#define EDMA_TX_ATH_HDR_FROM_CPU_SHIFT 7 ++ ++#define EDMA_TXQ_START_CORE0 8 ++#define EDMA_TXQ_START_CORE1 12 ++#define EDMA_TXQ_START_CORE2 0 ++#define EDMA_TXQ_START_CORE3 4 ++ ++#define EDMA_TXQ_IRQ_MASK_CORE0 0x0F00 ++#define EDMA_TXQ_IRQ_MASK_CORE1 0xF000 ++#define EDMA_TXQ_IRQ_MASK_CORE2 0x000F ++#define EDMA_TXQ_IRQ_MASK_CORE3 0x00F0 ++ ++#define EDMA_ETH_HDR_LEN 12 ++#define EDMA_ETH_TYPE_MASK 0xFFFF ++ ++#define EDMA_RX_BUFFER_WRITE 16 ++#define EDMA_RFD_AVAIL_THR 80 ++ ++#define EDMA_GMAC_NO_MDIO_PHY PHY_MAX_ADDR ++ ++extern int ssdk_rfs_ipct_rule_set(__be32 ip_src, __be32 ip_dst, ++ __be16 sport, __be16 dport, ++ uint8_t proto, u16 loadbalance, bool action); ++struct edma_ethtool_statistics { ++ u32 tx_q0_pkt; ++ u32 tx_q1_pkt; ++ u32 tx_q2_pkt; ++ u32 tx_q3_pkt; ++ u32 tx_q4_pkt; ++ u32 tx_q5_pkt; ++ u32 tx_q6_pkt; ++ u32 tx_q7_pkt; ++ u32 tx_q8_pkt; ++ u32 tx_q9_pkt; ++ u32 tx_q10_pkt; ++ u32 tx_q11_pkt; ++ u32 tx_q12_pkt; ++ u32 tx_q13_pkt; ++ u32 tx_q14_pkt; ++ u32 tx_q15_pkt; ++ u32 tx_q0_byte; ++ u32 tx_q1_byte; ++ u32 tx_q2_byte; ++ u32 tx_q3_byte; ++ u32 tx_q4_byte; ++ u32 tx_q5_byte; ++ u32 tx_q6_byte; ++ u32 tx_q7_byte; ++ u32 tx_q8_byte; ++ u32 tx_q9_byte; ++ u32 tx_q10_byte; ++ u32 tx_q11_byte; ++ u32 tx_q12_byte; ++ u32 tx_q13_byte; ++ u32 tx_q14_byte; ++ u32 tx_q15_byte; ++ u32 rx_q0_pkt; ++ u32 rx_q1_pkt; ++ u32 rx_q2_pkt; ++ u32 rx_q3_pkt; ++ u32 rx_q4_pkt; ++ u32 rx_q5_pkt; ++ u32 rx_q6_pkt; ++ u32 rx_q7_pkt; ++ u32 rx_q0_byte; ++ u32 rx_q1_byte; ++ u32 rx_q2_byte; ++ u32 rx_q3_byte; ++ u32 rx_q4_byte; ++ u32 rx_q5_byte; ++ u32 rx_q6_byte; ++ u32 rx_q7_byte; ++ u32 tx_desc_error; ++}; ++ ++struct edma_mdio_data { ++ struct mii_bus *mii_bus; ++ void __iomem *membase; ++ int phy_irq[PHY_MAX_ADDR]; ++}; ++ ++/* EDMA LINK state */ ++enum edma_link_state { ++ __EDMA_LINKUP, /* Indicate link is UP */ ++ __EDMA_LINKDOWN /* Indicate link is down */ ++}; ++ ++/* EDMA GMAC state */ ++enum edma_gmac_state { ++ __EDMA_UP /* use to indicate GMAC is up */ ++}; ++ ++/* edma transmit descriptor */ ++struct edma_tx_desc { ++ __le16 len; /* full packet including CRC */ ++ __le16 svlan_tag; /* vlan tag */ ++ __le32 word1; /* byte 4-7 */ ++ __le32 addr; /* address of buffer */ ++ __le32 word3; /* byte 12 */ ++}; ++ ++/* edma receive return descriptor */ ++struct edma_rx_return_desc { ++ u16 rrd0; ++ u16 rrd1; ++ u16 rrd2; ++ u16 rrd3; ++ u16 rrd4; ++ u16 rrd5; ++ u16 rrd6; ++ u16 rrd7; ++}; ++ ++/* RFD descriptor */ ++struct edma_rx_free_desc { ++ __le32 buffer_addr; /* buffer address */ ++}; ++ ++/* edma hw specific data */ ++struct edma_hw { ++ u32 __iomem *hw_addr; /* inner register address */ ++ struct edma_adapter *adapter; /* netdevice adapter */ ++ u32 rx_intr_mask; /*rx interrupt mask */ ++ u32 tx_intr_mask; /* tx interrupt nask */ ++ u32 misc_intr_mask; /* misc interrupt mask */ ++ u32 wol_intr_mask; /* wake on lan interrupt mask */ ++ bool intr_clear_type; /* interrupt clear */ ++ bool intr_sw_idx_w; /* interrupt software index */ ++ u32 rx_head_buff_size; /* Rx buffer size */ ++ u8 rss_type; /* rss protocol type */ ++}; ++ ++/* edma_sw_desc stores software descriptor ++ * SW descriptor has 1:1 map with HW descriptor ++ */ ++struct edma_sw_desc { ++ struct sk_buff *skb; ++ dma_addr_t dma; /* dma address */ ++ u16 length; /* Tx/Rx buffer length */ ++ u32 flags; ++}; ++ ++/* per core related information */ ++struct edma_per_cpu_queues_info { ++ struct napi_struct napi; /* napi associated with the core */ ++ u32 tx_mask; /* tx interrupt mask */ ++ u32 rx_mask; /* rx interrupt mask */ ++ u32 tx_status; /* tx interrupt status */ ++ u32 rx_status; /* rx interrupt status */ ++ u32 tx_start; /* tx queue start */ ++ u32 rx_start; /* rx queue start */ ++ struct edma_common_info *edma_cinfo; /* edma common info */ ++}; ++ ++/* edma specific common info */ ++struct edma_common_info { ++ struct edma_tx_desc_ring *tpd_ring[16]; /* 16 Tx queues */ ++ struct edma_rfd_desc_ring *rfd_ring[8]; /* 8 Rx queues */ ++ struct platform_device *pdev; /* device structure */ ++ struct net_device *netdev[EDMA_MAX_PORTID_SUPPORTED]; ++ struct net_device *portid_netdev_lookup_tbl[EDMA_MAX_PORTID_BITMAP_INDEX]; ++ struct ctl_table_header *edma_ctl_table_hdr; ++ int num_gmac; ++ struct edma_ethtool_statistics edma_ethstats; /* ethtool stats */ ++ int num_rx_queues; /* number of rx queue */ ++ u32 num_tx_queues; /* number of tx queue */ ++ u32 tx_irq[16]; /* number of tx irq */ ++ u32 rx_irq[8]; /* number of rx irq */ ++ u32 from_cpu; /* from CPU TPD field */ ++ u32 num_rxq_per_core; /* Rx queues per core */ ++ u32 num_txq_per_core; /* Tx queues per core */ ++ u16 tx_ring_count; /* Tx ring count */ ++ u16 rx_ring_count; /* Rx ring*/ ++ u16 rx_head_buffer_len; /* rx buffer length */ ++ u16 rx_page_buffer_len; /* rx buffer length */ ++ u32 page_mode; /* Jumbo frame supported flag */ ++ u32 fraglist_mode; /* fraglist supported flag */ ++ struct edma_hw hw; /* edma hw specific structure */ ++ struct edma_per_cpu_queues_info edma_percpu_info[CONFIG_NR_CPUS]; /* per cpu information */ ++ spinlock_t stats_lock; /* protect edma stats area for updation */ ++}; ++ ++/* transimit packet descriptor (tpd) ring */ ++struct edma_tx_desc_ring { ++ struct netdev_queue *nq[EDMA_MAX_NETDEV_PER_QUEUE]; /* Linux queue index */ ++ struct net_device *netdev[EDMA_MAX_NETDEV_PER_QUEUE]; ++ /* Array of netdevs associated with the tpd ring */ ++ void *hw_desc; /* descriptor ring virtual address */ ++ struct edma_sw_desc *sw_desc; /* buffer associated with ring */ ++ int netdev_bmp; /* Bitmap for per-ring netdevs */ ++ u32 size; /* descriptor ring length in bytes */ ++ u16 count; /* number of descriptors in the ring */ ++ dma_addr_t dma; /* descriptor ring physical address */ ++ u16 sw_next_to_fill; /* next Tx descriptor to fill */ ++ u16 sw_next_to_clean; /* next Tx descriptor to clean */ ++}; ++ ++/* receive free descriptor (rfd) ring */ ++struct edma_rfd_desc_ring { ++ void *hw_desc; /* descriptor ring virtual address */ ++ struct edma_sw_desc *sw_desc; /* buffer associated with ring */ ++ u16 size; /* bytes allocated to sw_desc */ ++ u16 count; /* number of descriptors in the ring */ ++ dma_addr_t dma; /* descriptor ring physical address */ ++ u16 sw_next_to_fill; /* next descriptor to fill */ ++ u16 sw_next_to_clean; /* next descriptor to clean */ ++}; ++ ++/* edma_rfs_flter_node - rfs filter node in hash table */ ++struct edma_rfs_filter_node { ++ struct flow_keys keys; ++ u32 flow_id; /* flow_id of filter provided by kernel */ ++ u16 filter_id; /* filter id of filter returned by adaptor */ ++ u16 rq_id; /* desired rq index */ ++ struct hlist_node node; /* edma rfs list node */ ++}; ++ ++/* edma_rfs_flow_tbl - rfs flow table */ ++struct edma_rfs_flow_table { ++ u16 max_num_filter; /* Maximum number of filters edma supports */ ++ u16 hashtoclean; /* hash table index to clean next */ ++ int filter_available; /* Number of free filters available */ ++ struct hlist_head hlist_head[EDMA_RFS_FLOW_ENTRIES]; ++ spinlock_t rfs_ftab_lock; ++ struct timer_list expire_rfs; /* timer function for edma_rps_may_expire_flow */ ++}; ++ ++/* EDMA net device structure */ ++struct edma_adapter { ++ struct net_device *netdev; /* netdevice */ ++ struct platform_device *pdev; /* platform device */ ++ struct edma_common_info *edma_cinfo; /* edma common info */ ++ struct phy_device *phydev; /* Phy device */ ++ struct edma_rfs_flow_table rfs; /* edma rfs flow table */ ++ struct net_device_stats stats; /* netdev statistics */ ++ set_rfs_filter_callback_t set_rfs_rule; ++ u32 flags;/* status flags */ ++ unsigned long state_flags; /* GMAC up/down flags */ ++ u32 forced_speed; /* link force speed */ ++ u32 forced_duplex; /* link force duplex */ ++ u32 link_state; /* phy link state */ ++ u32 phy_mdio_addr; /* PHY device address on MII interface */ ++ u32 poll_required; /* check if link polling is required */ ++ u32 tx_start_offset[CONFIG_NR_CPUS]; /* tx queue start */ ++ u32 default_vlan_tag; /* vlan tag */ ++ u32 dp_bitmap; ++ uint8_t phy_id[MII_BUS_ID_SIZE + 3]; ++}; ++ ++int edma_alloc_queues_tx(struct edma_common_info *edma_cinfo); ++int edma_alloc_queues_rx(struct edma_common_info *edma_cinfo); ++int edma_open(struct net_device *netdev); ++int edma_close(struct net_device *netdev); ++void edma_free_tx_resources(struct edma_common_info *edma_c_info); ++void edma_free_rx_resources(struct edma_common_info *edma_c_info); ++int edma_alloc_tx_rings(struct edma_common_info *edma_cinfo); ++int edma_alloc_rx_rings(struct edma_common_info *edma_cinfo); ++void edma_free_tx_rings(struct edma_common_info *edma_cinfo); ++void edma_free_rx_rings(struct edma_common_info *edma_cinfo); ++void edma_free_queues(struct edma_common_info *edma_cinfo); ++void edma_irq_disable(struct edma_common_info *edma_cinfo); ++int edma_reset(struct edma_common_info *edma_cinfo); ++int edma_poll(struct napi_struct *napi, int budget); ++netdev_tx_t edma_xmit(struct sk_buff *skb, ++ struct net_device *netdev); ++int edma_configure(struct edma_common_info *edma_cinfo); ++void edma_irq_enable(struct edma_common_info *edma_cinfo); ++void edma_enable_tx_ctrl(struct edma_hw *hw); ++void edma_enable_rx_ctrl(struct edma_hw *hw); ++void edma_stop_rx_tx(struct edma_hw *hw); ++void edma_free_irqs(struct edma_adapter *adapter); ++irqreturn_t edma_interrupt(int irq, void *dev); ++void edma_write_reg(u16 reg_addr, u32 reg_value); ++void edma_read_reg(u16 reg_addr, volatile u32 *reg_value); ++struct net_device_stats *edma_get_stats(struct net_device *netdev); ++int edma_set_mac_addr(struct net_device *netdev, void *p); ++int edma_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, ++ u16 rxq, u32 flow_id); ++int edma_register_rfs_filter(struct net_device *netdev, ++ set_rfs_filter_callback_t set_filter); ++void edma_flow_may_expire(unsigned long data); ++void edma_set_ethtool_ops(struct net_device *netdev); ++void edma_set_stp_rstp(bool tag); ++void edma_assign_ath_hdr_type(int tag); ++int edma_get_default_vlan_tag(struct net_device *netdev); ++void edma_adjust_link(struct net_device *netdev); ++int edma_fill_netdev(struct edma_common_info *edma_cinfo, int qid, int num, int txq_id); ++void edma_read_append_stats(struct edma_common_info *edma_cinfo); ++void edma_change_tx_coalesce(int usecs); ++void edma_change_rx_coalesce(int usecs); ++void edma_get_tx_rx_coalesce(u32 *reg_val); ++void edma_clear_irq_status(void); ++#endif /* _EDMA_H_ */ +--- /dev/null ++++ b/drivers/net/ethernet/qualcomm/essedma/edma_axi.c +@@ -0,0 +1,1220 @@ ++/* ++ * Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for ++ * any purpose with or without fee is hereby granted, provided that the ++ * above copyright notice and this permission notice appear in all copies. ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT ++ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include "edma.h" ++#include "ess_edma.h" ++ ++/* Weight round robin and virtual QID mask */ ++#define EDMA_WRR_VID_SCTL_MASK 0xffff ++ ++/* Weight round robin and virtual QID shift */ ++#define EDMA_WRR_VID_SCTL_SHIFT 16 ++ ++char edma_axi_driver_name[] = "ess_edma"; ++static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | ++ NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP; ++ ++static u32 edma_hw_addr; ++ ++struct timer_list edma_stats_timer; ++ ++char edma_tx_irq[16][64]; ++char edma_rx_irq[8][64]; ++struct net_device *edma_netdev[EDMA_MAX_PORTID_SUPPORTED]; ++static u16 tx_start[4] = {EDMA_TXQ_START_CORE0, EDMA_TXQ_START_CORE1, ++ EDMA_TXQ_START_CORE2, EDMA_TXQ_START_CORE3}; ++static u32 tx_mask[4] = {EDMA_TXQ_IRQ_MASK_CORE0, EDMA_TXQ_IRQ_MASK_CORE1, ++ EDMA_TXQ_IRQ_MASK_CORE2, EDMA_TXQ_IRQ_MASK_CORE3}; ++ ++static u32 edma_default_ltag __read_mostly = EDMA_LAN_DEFAULT_VLAN; ++static u32 edma_default_wtag __read_mostly = EDMA_WAN_DEFAULT_VLAN; ++static u32 edma_default_group1_vtag __read_mostly = EDMA_DEFAULT_GROUP1_VLAN; ++static u32 edma_default_group2_vtag __read_mostly = EDMA_DEFAULT_GROUP2_VLAN; ++static u32 edma_default_group3_vtag __read_mostly = EDMA_DEFAULT_GROUP3_VLAN; ++static u32 edma_default_group4_vtag __read_mostly = EDMA_DEFAULT_GROUP4_VLAN; ++static u32 edma_default_group5_vtag __read_mostly = EDMA_DEFAULT_GROUP5_VLAN; ++static u32 edma_rss_idt_val = EDMA_RSS_IDT_VALUE; ++static u32 edma_rss_idt_idx; ++ ++static int edma_weight_assigned_to_q __read_mostly; ++static int edma_queue_to_virtual_q __read_mostly; ++static bool edma_enable_rstp __read_mostly; ++static int edma_athr_hdr_eth_type __read_mostly; ++ ++static int page_mode; ++module_param(page_mode, int, 0); ++MODULE_PARM_DESC(page_mode, "enable page mode"); ++ ++static int overwrite_mode; ++module_param(overwrite_mode, int, 0); ++MODULE_PARM_DESC(overwrite_mode, "overwrite default page_mode setting"); ++ ++static int jumbo_mru = EDMA_RX_HEAD_BUFF_SIZE; ++module_param(jumbo_mru, int, 0); ++MODULE_PARM_DESC(jumbo_mru, "enable fraglist support"); ++ ++static int num_rxq = 4; ++module_param(num_rxq, int, 0); ++MODULE_PARM_DESC(num_rxq, "change the number of rx queues"); ++ ++void edma_write_reg(u16 reg_addr, u32 reg_value) ++{ ++ writel(reg_value, ((void __iomem *)(edma_hw_addr + reg_addr))); ++} ++ ++void edma_read_reg(u16 reg_addr, volatile u32 *reg_value) ++{ ++ *reg_value = readl((void __iomem *)(edma_hw_addr + reg_addr)); ++} ++ ++/* edma_change_tx_coalesce() ++ * change tx interrupt moderation timer ++ */ ++void edma_change_tx_coalesce(int usecs) ++{ ++ u32 reg_value; ++ ++ /* Here, we right shift the value from the user by 1, this is ++ * done because IMT resolution timer is 2usecs. 1 count ++ * of this register corresponds to 2 usecs. ++ */ ++ edma_read_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, ®_value); ++ reg_value = ((reg_value & 0xffff) | ((usecs >> 1) << 16)); ++ edma_write_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, reg_value); ++} ++ ++/* edma_change_rx_coalesce() ++ * change rx interrupt moderation timer ++ */ ++void edma_change_rx_coalesce(int usecs) ++{ ++ u32 reg_value; ++ ++ /* Here, we right shift the value from the user by 1, this is ++ * done because IMT resolution timer is 2usecs. 1 count ++ * of this register corresponds to 2 usecs. ++ */ ++ edma_read_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, ®_value); ++ reg_value = ((reg_value & 0xffff0000) | (usecs >> 1)); ++ edma_write_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, reg_value); ++} ++ ++/* edma_get_tx_rx_coalesce() ++ * Get tx/rx interrupt moderation value ++ */ ++void edma_get_tx_rx_coalesce(u32 *reg_val) ++{ ++ edma_read_reg(EDMA_REG_IRQ_MODRT_TIMER_INIT, reg_val); ++} ++ ++void edma_read_append_stats(struct edma_common_info *edma_cinfo) ++{ ++ uint32_t *p; ++ int i; ++ u32 stat; ++ ++ spin_lock(&edma_cinfo->stats_lock); ++ p = (uint32_t *)&(edma_cinfo->edma_ethstats); ++ ++ for (i = 0; i < EDMA_MAX_TRANSMIT_QUEUE; i++) { ++ edma_read_reg(EDMA_REG_TX_STAT_PKT_Q(i), &stat); ++ *p += stat; ++ p++; ++ } ++ ++ for (i = 0; i < EDMA_MAX_TRANSMIT_QUEUE; i++) { ++ edma_read_reg(EDMA_REG_TX_STAT_BYTE_Q(i), &stat); ++ *p += stat; ++ p++; ++ } ++ ++ for (i = 0; i < EDMA_MAX_RECEIVE_QUEUE; i++) { ++ edma_read_reg(EDMA_REG_RX_STAT_PKT_Q(i), &stat); ++ *p += stat; ++ p++; ++ } ++ ++ for (i = 0; i < EDMA_MAX_RECEIVE_QUEUE; i++) { ++ edma_read_reg(EDMA_REG_RX_STAT_BYTE_Q(i), &stat); ++ *p += stat; ++ p++; ++ } ++ ++ spin_unlock(&edma_cinfo->stats_lock); ++} ++ ++static void edma_statistics_timer(unsigned long data) ++{ ++ struct edma_common_info *edma_cinfo = (struct edma_common_info *)data; ++ ++ edma_read_append_stats(edma_cinfo); ++ ++ mod_timer(&edma_stats_timer, jiffies + 1*HZ); ++} ++ ++static int edma_enable_stp_rstp(struct ctl_table *table, int write, ++ void __user *buffer, size_t *lenp, ++ loff_t *ppos) ++{ ++ int ret; ++ ++ ret = proc_dointvec(table, write, buffer, lenp, ppos); ++ if (write) ++ edma_set_stp_rstp(edma_enable_rstp); ++ ++ return ret; ++} ++ ++static int edma_ath_hdr_eth_type(struct ctl_table *table, int write, ++ void __user *buffer, size_t *lenp, ++ loff_t *ppos) ++{ ++ int ret; ++ ++ ret = proc_dointvec(table, write, buffer, lenp, ppos); ++ if (write) ++ edma_assign_ath_hdr_type(edma_athr_hdr_eth_type); ++ ++ return ret; ++} ++ ++static int edma_change_default_lan_vlan(struct ctl_table *table, int write, ++ void __user *buffer, size_t *lenp, ++ loff_t *ppos) ++{ ++ struct edma_adapter *adapter; ++ int ret; ++ ++ if (!edma_netdev[1]) { ++ pr_err("Netdevice for default_lan does not exist\n"); ++ return -1; ++ } ++ ++ adapter = netdev_priv(edma_netdev[1]); ++ ++ ret = proc_dointvec(table, write, buffer, lenp, ppos); ++ ++ if (write) ++ adapter->default_vlan_tag = edma_default_ltag; ++ ++ return ret; ++} ++ ++static int edma_change_default_wan_vlan(struct ctl_table *table, int write, ++ void __user *buffer, size_t *lenp, ++ loff_t *ppos) ++{ ++ struct edma_adapter *adapter; ++ int ret; ++ ++ if (!edma_netdev[0]) { ++ pr_err("Netdevice for default_wan does not exist\n"); ++ return -1; ++ } ++ ++ adapter = netdev_priv(edma_netdev[0]); ++ ++ ret = proc_dointvec(table, write, buffer, lenp, ppos); ++ ++ if (write) ++ adapter->default_vlan_tag = edma_default_wtag; ++ ++ return ret; ++} ++ ++static int edma_change_group1_vtag(struct ctl_table *table, int write, ++ void __user *buffer, size_t *lenp, ++ loff_t *ppos) ++{ ++ struct edma_adapter *adapter; ++ struct edma_common_info *edma_cinfo; ++ int ret; ++ ++ if (!edma_netdev[0]) { ++ pr_err("Netdevice for Group 1 does not exist\n"); ++ return -1; ++ } ++ ++ adapter = netdev_priv(edma_netdev[0]); ++ edma_cinfo = adapter->edma_cinfo; ++ ++ ret = proc_dointvec(table, write, buffer, lenp, ppos); ++ ++ if (write) ++ adapter->default_vlan_tag = edma_default_group1_vtag; ++ ++ return ret; ++} ++ ++static int edma_change_group2_vtag(struct ctl_table *table, int write, ++ void __user *buffer, size_t *lenp, ++ loff_t *ppos) ++{ ++ struct edma_adapter *adapter; ++ struct edma_common_info *edma_cinfo; ++ int ret; ++ ++ if (!edma_netdev[1]) { ++ pr_err("Netdevice for Group 2 does not exist\n"); ++ return -1; ++ } ++ ++ adapter = netdev_priv(edma_netdev[1]); ++ edma_cinfo = adapter->edma_cinfo; ++ ++ ret = proc_dointvec(table, write, buffer, lenp, ppos); ++ ++ if (write) ++ adapter->default_vlan_tag = edma_default_group2_vtag; ++ ++ return ret; ++} ++ ++static int edma_change_group3_vtag(struct ctl_table *table, int write, ++ void __user *buffer, size_t *lenp, ++ loff_t *ppos) ++{ ++ struct edma_adapter *adapter; ++ struct edma_common_info *edma_cinfo; ++ int ret; ++ ++ if (!edma_netdev[2]) { ++ pr_err("Netdevice for Group 3 does not exist\n"); ++ return -1; ++ } ++ ++ adapter = netdev_priv(edma_netdev[2]); ++ edma_cinfo = adapter->edma_cinfo; ++ ++ ret = proc_dointvec(table, write, buffer, lenp, ppos); ++ ++ if (write) ++ adapter->default_vlan_tag = edma_default_group3_vtag; ++ ++ return ret; ++} ++ ++static int edma_change_group4_vtag(struct ctl_table *table, int write, ++ void __user *buffer, size_t *lenp, ++ loff_t *ppos) ++{ ++ struct edma_adapter *adapter; ++ struct edma_common_info *edma_cinfo; ++ int ret; ++ ++ if (!edma_netdev[3]) { ++ pr_err("Netdevice for Group 4 does not exist\n"); ++ return -1; ++ } ++ ++ adapter = netdev_priv(edma_netdev[3]); ++ edma_cinfo = adapter->edma_cinfo; ++ ++ ret = proc_dointvec(table, write, buffer, lenp, ppos); ++ ++ if (write) ++ adapter->default_vlan_tag = edma_default_group4_vtag; ++ ++ return ret; ++} ++ ++static int edma_change_group5_vtag(struct ctl_table *table, int write, ++ void __user *buffer, size_t *lenp, ++ loff_t *ppos) ++{ ++ struct edma_adapter *adapter; ++ struct edma_common_info *edma_cinfo; ++ int ret; ++ ++ if (!edma_netdev[4]) { ++ pr_err("Netdevice for Group 5 does not exist\n"); ++ return -1; ++ } ++ ++ adapter = netdev_priv(edma_netdev[4]); ++ edma_cinfo = adapter->edma_cinfo; ++ ++ ret = proc_dointvec(table, write, buffer, lenp, ppos); ++ ++ if (write) ++ adapter->default_vlan_tag = edma_default_group5_vtag; ++ ++ return ret; ++} ++ ++static int edma_set_rss_idt_value(struct ctl_table *table, int write, ++ void __user *buffer, size_t *lenp, ++ loff_t *ppos) ++{ ++ int ret; ++ ++ ret = proc_dointvec(table, write, buffer, lenp, ppos); ++ if (write && !ret) ++ edma_write_reg(EDMA_REG_RSS_IDT(edma_rss_idt_idx), ++ edma_rss_idt_val); ++ return ret; ++} ++ ++static int edma_set_rss_idt_idx(struct ctl_table *table, int write, ++ void __user *buffer, size_t *lenp, ++ loff_t *ppos) ++{ ++ int ret; ++ u32 old_value = edma_rss_idt_idx; ++ ++ ret = proc_dointvec(table, write, buffer, lenp, ppos); ++ if (!write || ret) ++ return ret; ++ ++ if (edma_rss_idt_idx >= EDMA_NUM_IDT) { ++ pr_err("Invalid RSS indirection table index %d\n", ++ edma_rss_idt_idx); ++ edma_rss_idt_idx = old_value; ++ return -EINVAL; ++ } ++ return ret; ++} ++ ++static int edma_weight_assigned_to_queues(struct ctl_table *table, int write, ++ void __user *buffer, size_t *lenp, ++ loff_t *ppos) ++{ ++ int ret, queue_id, weight; ++ u32 reg_data, data, reg_addr; ++ ++ ret = proc_dointvec(table, write, buffer, lenp, ppos); ++ if (write) { ++ queue_id = edma_weight_assigned_to_q & EDMA_WRR_VID_SCTL_MASK; ++ if (queue_id < 0 || queue_id > 15) { ++ pr_err("queue_id not within desired range\n"); ++ return -EINVAL; ++ } ++ ++ weight = edma_weight_assigned_to_q >> EDMA_WRR_VID_SCTL_SHIFT; ++ if (weight < 0 || weight > 0xF) { ++ pr_err("queue_id not within desired range\n"); ++ return -EINVAL; ++ } ++ ++ data = weight << EDMA_WRR_SHIFT(queue_id); ++ ++ reg_addr = EDMA_REG_WRR_CTRL_Q0_Q3 + (queue_id & ~0x3); ++ edma_read_reg(reg_addr, ®_data); ++ reg_data &= ~(1 << EDMA_WRR_SHIFT(queue_id)); ++ edma_write_reg(reg_addr, data | reg_data); ++ } ++ ++ return ret; ++} ++ ++static int edma_queue_to_virtual_queue_map(struct ctl_table *table, int write, ++ void __user *buffer, size_t *lenp, ++ loff_t *ppos) ++{ ++ int ret, queue_id, virtual_qid; ++ u32 reg_data, data, reg_addr; ++ ++ ret = proc_dointvec(table, write, buffer, lenp, ppos); ++ if (write) { ++ queue_id = edma_queue_to_virtual_q & EDMA_WRR_VID_SCTL_MASK; ++ if (queue_id < 0 || queue_id > 15) { ++ pr_err("queue_id not within desired range\n"); ++ return -EINVAL; ++ } ++ ++ virtual_qid = edma_queue_to_virtual_q >> ++ EDMA_WRR_VID_SCTL_SHIFT; ++ if (virtual_qid < 0 || virtual_qid > 8) { ++ pr_err("queue_id not within desired range\n"); ++ return -EINVAL; ++ } ++ ++ data = virtual_qid << EDMA_VQ_ID_SHIFT(queue_id); ++ ++ reg_addr = EDMA_REG_VQ_CTRL0 + (queue_id & ~0x3); ++ edma_read_reg(reg_addr, ®_data); ++ reg_data &= ~(1 << EDMA_VQ_ID_SHIFT(queue_id)); ++ edma_write_reg(reg_addr, data | reg_data); ++ } ++ ++ return ret; ++} ++ ++static struct ctl_table edma_table[] = { ++ { ++ .procname = "default_lan_tag", ++ .data = &edma_default_ltag, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = edma_change_default_lan_vlan ++ }, ++ { ++ .procname = "default_wan_tag", ++ .data = &edma_default_wtag, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = edma_change_default_wan_vlan ++ }, ++ { ++ .procname = "weight_assigned_to_queues", ++ .data = &edma_weight_assigned_to_q, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = edma_weight_assigned_to_queues ++ }, ++ { ++ .procname = "queue_to_virtual_queue_map", ++ .data = &edma_queue_to_virtual_q, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = edma_queue_to_virtual_queue_map ++ }, ++ { ++ .procname = "enable_stp_rstp", ++ .data = &edma_enable_rstp, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = edma_enable_stp_rstp ++ }, ++ { ++ .procname = "athr_hdr_eth_type", ++ .data = &edma_athr_hdr_eth_type, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = edma_ath_hdr_eth_type ++ }, ++ { ++ .procname = "default_group1_vlan_tag", ++ .data = &edma_default_group1_vtag, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = edma_change_group1_vtag ++ }, ++ { ++ .procname = "default_group2_vlan_tag", ++ .data = &edma_default_group2_vtag, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = edma_change_group2_vtag ++ }, ++ { ++ .procname = "default_group3_vlan_tag", ++ .data = &edma_default_group3_vtag, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = edma_change_group3_vtag ++ }, ++ { ++ .procname = "default_group4_vlan_tag", ++ .data = &edma_default_group4_vtag, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = edma_change_group4_vtag ++ }, ++ { ++ .procname = "default_group5_vlan_tag", ++ .data = &edma_default_group5_vtag, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = edma_change_group5_vtag ++ }, ++ { ++ .procname = "edma_rss_idt_value", ++ .data = &edma_rss_idt_val, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = edma_set_rss_idt_value ++ }, ++ { ++ .procname = "edma_rss_idt_idx", ++ .data = &edma_rss_idt_idx, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = edma_set_rss_idt_idx ++ }, ++ {} ++}; ++ ++/* edma_axi_netdev_ops ++ * Describe the operations supported by registered netdevices ++ * ++ * static const struct net_device_ops edma_axi_netdev_ops = { ++ * .ndo_open = edma_open, ++ * .ndo_stop = edma_close, ++ * .ndo_start_xmit = edma_xmit_frame, ++ * .ndo_set_mac_address = edma_set_mac_addr, ++ * } ++ */ ++static const struct net_device_ops edma_axi_netdev_ops = { ++ .ndo_open = edma_open, ++ .ndo_stop = edma_close, ++ .ndo_start_xmit = edma_xmit, ++ .ndo_set_mac_address = edma_set_mac_addr, ++#ifdef CONFIG_RFS_ACCEL ++ .ndo_rx_flow_steer = edma_rx_flow_steer, ++ .ndo_register_rfs_filter = edma_register_rfs_filter, ++ .ndo_get_default_vlan_tag = edma_get_default_vlan_tag, ++#endif ++ .ndo_get_stats = edma_get_stats, ++}; ++ ++/* edma_axi_probe() ++ * Initialise an adapter identified by a platform_device structure. ++ * ++ * The OS initialization, configuring of the adapter private structure, ++ * and a hardware reset occur in the probe. ++ */ ++static int edma_axi_probe(struct platform_device *pdev) ++{ ++ struct edma_common_info *edma_cinfo; ++ struct edma_hw *hw; ++ struct edma_adapter *adapter[EDMA_MAX_PORTID_SUPPORTED]; ++ struct resource *res; ++ struct device_node *np = pdev->dev.of_node; ++ struct device_node *pnp; ++ struct device_node *mdio_node = NULL; ++ struct platform_device *mdio_plat = NULL; ++ struct mii_bus *miibus = NULL; ++ struct edma_mdio_data *mdio_data = NULL; ++ int i, j, k, err = 0; ++ int portid_bmp; ++ int idx = 0, idx_mac = 0; ++ ++ if (CONFIG_NR_CPUS != EDMA_CPU_CORES_SUPPORTED) { ++ dev_err(&pdev->dev, "Invalid CPU Cores\n"); ++ return -EINVAL; ++ } ++ ++ if ((num_rxq != 4) && (num_rxq != 8)) { ++ dev_err(&pdev->dev, "Invalid RX queue, edma probe failed\n"); ++ return -EINVAL; ++ } ++ edma_cinfo = kzalloc(sizeof(struct edma_common_info), GFP_KERNEL); ++ if (!edma_cinfo) { ++ err = -ENOMEM; ++ goto err_alloc; ++ } ++ ++ edma_cinfo->pdev = pdev; ++ ++ of_property_read_u32(np, "qcom,num_gmac", &edma_cinfo->num_gmac); ++ if (edma_cinfo->num_gmac > EDMA_MAX_PORTID_SUPPORTED) { ++ pr_err("Invalid DTSI Entry for qcom,num_gmac\n"); ++ err = -EINVAL; ++ goto err_cinfo; ++ } ++ ++ /* Initialize the netdev array before allocation ++ * to avoid double free ++ */ ++ for (i = 0 ; i < edma_cinfo->num_gmac ; i++) ++ edma_netdev[i] = NULL; ++ ++ for (i = 0 ; i < edma_cinfo->num_gmac ; i++) { ++ edma_netdev[i] = alloc_etherdev_mqs(sizeof(struct edma_adapter), ++ EDMA_NETDEV_TX_QUEUE, EDMA_NETDEV_RX_QUEUE); ++ ++ if (!edma_netdev[i]) { ++ dev_err(&pdev->dev, ++ "net device alloc fails for index=%d\n", i); ++ err = -ENODEV; ++ goto err_ioremap; ++ } ++ ++ SET_NETDEV_DEV(edma_netdev[i], &pdev->dev); ++ platform_set_drvdata(pdev, edma_netdev[i]); ++ edma_cinfo->netdev[i] = edma_netdev[i]; ++ } ++ ++ /* Fill ring details */ ++ edma_cinfo->num_tx_queues = EDMA_MAX_TRANSMIT_QUEUE; ++ edma_cinfo->num_txq_per_core = (EDMA_MAX_TRANSMIT_QUEUE / 4); ++ edma_cinfo->tx_ring_count = EDMA_TX_RING_SIZE; ++ ++ /* Update num rx queues based on module parameter */ ++ edma_cinfo->num_rx_queues = num_rxq; ++ edma_cinfo->num_rxq_per_core = ((num_rxq == 4) ? 1 : 2); ++ ++ edma_cinfo->rx_ring_count = EDMA_RX_RING_SIZE; ++ ++ hw = &edma_cinfo->hw; ++ ++ /* Fill HW defaults */ ++ hw->tx_intr_mask = EDMA_TX_IMR_NORMAL_MASK; ++ hw->rx_intr_mask = EDMA_RX_IMR_NORMAL_MASK; ++ ++ of_property_read_u32(np, "qcom,page-mode", &edma_cinfo->page_mode); ++ of_property_read_u32(np, "qcom,rx_head_buf_size", ++ &hw->rx_head_buff_size); ++ ++ if (overwrite_mode) { ++ dev_info(&pdev->dev, "page mode overwritten"); ++ edma_cinfo->page_mode = page_mode; ++ } ++ ++ if (jumbo_mru) ++ edma_cinfo->fraglist_mode = 1; ++ ++ if (edma_cinfo->page_mode) ++ hw->rx_head_buff_size = EDMA_RX_HEAD_BUFF_SIZE_JUMBO; ++ else if (edma_cinfo->fraglist_mode) ++ hw->rx_head_buff_size = jumbo_mru; ++ else if (!hw->rx_head_buff_size) ++ hw->rx_head_buff_size = EDMA_RX_HEAD_BUFF_SIZE; ++ ++ hw->misc_intr_mask = 0; ++ hw->wol_intr_mask = 0; ++ ++ hw->intr_clear_type = EDMA_INTR_CLEAR_TYPE; ++ hw->intr_sw_idx_w = EDMA_INTR_SW_IDX_W_TYPE; ++ ++ /* configure RSS type to the different protocol that can be ++ * supported ++ */ ++ hw->rss_type = EDMA_RSS_TYPE_IPV4TCP | EDMA_RSS_TYPE_IPV6_TCP | ++ EDMA_RSS_TYPE_IPV4_UDP | EDMA_RSS_TYPE_IPV6UDP | ++ EDMA_RSS_TYPE_IPV4 | EDMA_RSS_TYPE_IPV6; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ edma_cinfo->hw.hw_addr = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(edma_cinfo->hw.hw_addr)) { ++ err = PTR_ERR(edma_cinfo->hw.hw_addr); ++ goto err_ioremap; ++ } ++ ++ edma_hw_addr = (u32)edma_cinfo->hw.hw_addr; ++ ++ /* Parse tx queue interrupt number from device tree */ ++ for (i = 0; i < edma_cinfo->num_tx_queues; i++) ++ edma_cinfo->tx_irq[i] = platform_get_irq(pdev, i); ++ ++ /* Parse rx queue interrupt number from device tree ++ * Here we are setting j to point to the point where we ++ * left tx interrupt parsing(i.e 16) and run run the loop ++ * from 0 to 7 to parse rx interrupt number. ++ */ ++ for (i = 0, j = edma_cinfo->num_tx_queues, k = 0; ++ i < edma_cinfo->num_rx_queues; i++) { ++ edma_cinfo->rx_irq[k] = platform_get_irq(pdev, j); ++ k += ((num_rxq == 4) ? 2 : 1); ++ j += ((num_rxq == 4) ? 2 : 1); ++ } ++ ++ edma_cinfo->rx_head_buffer_len = edma_cinfo->hw.rx_head_buff_size; ++ edma_cinfo->rx_page_buffer_len = PAGE_SIZE; ++ ++ err = edma_alloc_queues_tx(edma_cinfo); ++ if (err) { ++ dev_err(&pdev->dev, "Allocation of TX queue failed\n"); ++ goto err_tx_qinit; ++ } ++ ++ err = edma_alloc_queues_rx(edma_cinfo); ++ if (err) { ++ dev_err(&pdev->dev, "Allocation of RX queue failed\n"); ++ goto err_rx_qinit; ++ } ++ ++ err = edma_alloc_tx_rings(edma_cinfo); ++ if (err) { ++ dev_err(&pdev->dev, "Allocation of TX resources failed\n"); ++ goto err_tx_rinit; ++ } ++ ++ err = edma_alloc_rx_rings(edma_cinfo); ++ if (err) { ++ dev_err(&pdev->dev, "Allocation of RX resources failed\n"); ++ goto err_rx_rinit; ++ } ++ ++ /* Initialize netdev and netdev bitmap for transmit descriptor rings */ ++ for (i = 0; i < edma_cinfo->num_tx_queues; i++) { ++ struct edma_tx_desc_ring *etdr = edma_cinfo->tpd_ring[i]; ++ int j; ++ ++ etdr->netdev_bmp = 0; ++ for (j = 0; j < EDMA_MAX_NETDEV_PER_QUEUE; j++) { ++ etdr->netdev[j] = NULL; ++ etdr->nq[j] = NULL; ++ } ++ } ++ ++ if (of_property_read_bool(np, "qcom,mdio_supported")) { ++ mdio_node = of_find_compatible_node(NULL, NULL, ++ "qcom,ipq4019-mdio"); ++ if (!mdio_node) { ++ dev_err(&pdev->dev, "cannot find mdio node by phandle"); ++ err = -EIO; ++ goto err_mdiobus_init_fail; ++ } ++ ++ mdio_plat = of_find_device_by_node(mdio_node); ++ if (!mdio_plat) { ++ dev_err(&pdev->dev, ++ "cannot find platform device from mdio node"); ++ of_node_put(mdio_node); ++ err = -EIO; ++ goto err_mdiobus_init_fail; ++ } ++ ++ mdio_data = dev_get_drvdata(&mdio_plat->dev); ++ if (!mdio_data) { ++ dev_err(&pdev->dev, ++ "cannot get mii bus reference from device data"); ++ of_node_put(mdio_node); ++ err = -EIO; ++ goto err_mdiobus_init_fail; ++ } ++ ++ miibus = mdio_data->mii_bus; ++ } ++ ++ for_each_available_child_of_node(np, pnp) { ++ const char *mac_addr; ++ ++ /* this check is needed if parent and daughter dts have ++ * different number of gmac nodes ++ */ ++ if (idx_mac == edma_cinfo->num_gmac) { ++ of_node_put(np); ++ break; ++ } ++ ++ mac_addr = of_get_mac_address(pnp); ++ if (mac_addr) ++ memcpy(edma_netdev[idx_mac]->dev_addr, mac_addr, ETH_ALEN); ++ ++ idx_mac++; ++ } ++ ++ /* Populate the adapter structure register the netdevice */ ++ for (i = 0; i < edma_cinfo->num_gmac; i++) { ++ int k, m; ++ ++ adapter[i] = netdev_priv(edma_netdev[i]); ++ adapter[i]->netdev = edma_netdev[i]; ++ adapter[i]->pdev = pdev; ++ for (j = 0; j < CONFIG_NR_CPUS; j++) { ++ m = i % 2; ++ adapter[i]->tx_start_offset[j] = ++ ((j << EDMA_TX_CPU_START_SHIFT) + (m << 1)); ++ /* Share the queues with available net-devices. ++ * For instance , with 5 net-devices ++ * eth0/eth2/eth4 will share q0,q1,q4,q5,q8,q9,q12,q13 ++ * and eth1/eth3 will get the remaining. ++ */ ++ for (k = adapter[i]->tx_start_offset[j]; k < ++ (adapter[i]->tx_start_offset[j] + 2); k++) { ++ if (edma_fill_netdev(edma_cinfo, k, i, j)) { ++ pr_err("Netdev overflow Error\n"); ++ goto err_register; ++ } ++ } ++ } ++ ++ adapter[i]->edma_cinfo = edma_cinfo; ++ edma_netdev[i]->netdev_ops = &edma_axi_netdev_ops; ++ edma_netdev[i]->max_mtu = 9000; ++ edma_netdev[i]->features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM ++ | NETIF_F_HW_VLAN_CTAG_TX ++ | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_SG | ++ NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GRO; ++ edma_netdev[i]->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM | ++ NETIF_F_HW_VLAN_CTAG_RX ++ | NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | ++ NETIF_F_GRO; ++ edma_netdev[i]->vlan_features = NETIF_F_HW_CSUM | NETIF_F_SG | ++ NETIF_F_TSO | NETIF_F_TSO6 | ++ NETIF_F_GRO; ++ edma_netdev[i]->wanted_features = NETIF_F_HW_CSUM | NETIF_F_SG | ++ NETIF_F_TSO | NETIF_F_TSO6 | ++ NETIF_F_GRO; ++ ++#ifdef CONFIG_RFS_ACCEL ++ edma_netdev[i]->features |= NETIF_F_RXHASH | NETIF_F_NTUPLE; ++ edma_netdev[i]->hw_features |= NETIF_F_RXHASH | NETIF_F_NTUPLE; ++ edma_netdev[i]->vlan_features |= NETIF_F_RXHASH | NETIF_F_NTUPLE; ++ edma_netdev[i]->wanted_features |= NETIF_F_RXHASH | NETIF_F_NTUPLE; ++#endif ++ edma_set_ethtool_ops(edma_netdev[i]); ++ ++ /* This just fill in some default MAC address ++ */ ++ if (!is_valid_ether_addr(edma_netdev[i]->dev_addr)) { ++ random_ether_addr(edma_netdev[i]->dev_addr); ++ pr_info("EDMA using MAC@ - using"); ++ pr_info("%02x:%02x:%02x:%02x:%02x:%02x\n", ++ *(edma_netdev[i]->dev_addr), ++ *(edma_netdev[i]->dev_addr + 1), ++ *(edma_netdev[i]->dev_addr + 2), ++ *(edma_netdev[i]->dev_addr + 3), ++ *(edma_netdev[i]->dev_addr + 4), ++ *(edma_netdev[i]->dev_addr + 5)); ++ } ++ ++ err = register_netdev(edma_netdev[i]); ++ if (err) ++ goto err_register; ++ ++ /* carrier off reporting is important to ++ * ethtool even BEFORE open ++ */ ++ netif_carrier_off(edma_netdev[i]); ++ ++ /* Allocate reverse irq cpu mapping structure for ++ * receive queues ++ */ ++#ifdef CONFIG_RFS_ACCEL ++ edma_netdev[i]->rx_cpu_rmap = ++ alloc_irq_cpu_rmap(EDMA_NETDEV_RX_QUEUE); ++ if (!edma_netdev[i]->rx_cpu_rmap) { ++ err = -ENOMEM; ++ goto err_rmap_alloc_fail; ++ } ++#endif ++ } ++ ++ for (i = 0; i < EDMA_MAX_PORTID_BITMAP_INDEX; i++) ++ edma_cinfo->portid_netdev_lookup_tbl[i] = NULL; ++ ++ for_each_available_child_of_node(np, pnp) { ++ const uint32_t *vlan_tag = NULL; ++ int len; ++ ++ /* this check is needed if parent and daughter dts have ++ * different number of gmac nodes ++ */ ++ if (idx == edma_cinfo->num_gmac) ++ break; ++ ++ /* Populate port-id to netdev lookup table */ ++ vlan_tag = of_get_property(pnp, "vlan_tag", &len); ++ if (!vlan_tag) { ++ pr_err("Vlan tag parsing Failed.\n"); ++ goto err_rmap_alloc_fail; ++ } ++ ++ adapter[idx]->default_vlan_tag = of_read_number(vlan_tag, 1); ++ vlan_tag++; ++ portid_bmp = of_read_number(vlan_tag, 1); ++ adapter[idx]->dp_bitmap = portid_bmp; ++ ++ portid_bmp = portid_bmp >> 1; /* We ignore CPU Port bit 0 */ ++ while (portid_bmp) { ++ int port_bit = ffs(portid_bmp); ++ ++ if (port_bit > EDMA_MAX_PORTID_SUPPORTED) ++ goto err_rmap_alloc_fail; ++ edma_cinfo->portid_netdev_lookup_tbl[port_bit] = ++ edma_netdev[idx]; ++ portid_bmp &= ~(1 << (port_bit - 1)); ++ } ++ ++ if (!of_property_read_u32(pnp, "qcom,poll_required", ++ &adapter[idx]->poll_required)) { ++ if (adapter[idx]->poll_required) { ++ of_property_read_u32(pnp, "qcom,phy_mdio_addr", ++ &adapter[idx]->phy_mdio_addr); ++ of_property_read_u32(pnp, "qcom,forced_speed", ++ &adapter[idx]->forced_speed); ++ of_property_read_u32(pnp, "qcom,forced_duplex", ++ &adapter[idx]->forced_duplex); ++ ++ /* create a phyid using MDIO bus id ++ * and MDIO bus address ++ */ ++ snprintf(adapter[idx]->phy_id, ++ MII_BUS_ID_SIZE + 3, PHY_ID_FMT, ++ miibus->id, ++ adapter[idx]->phy_mdio_addr); ++ } ++ } else { ++ adapter[idx]->poll_required = 0; ++ adapter[idx]->forced_speed = SPEED_1000; ++ adapter[idx]->forced_duplex = DUPLEX_FULL; ++ } ++ ++ idx++; ++ } ++ ++ edma_cinfo->edma_ctl_table_hdr = register_net_sysctl(&init_net, ++ "net/edma", ++ edma_table); ++ if (!edma_cinfo->edma_ctl_table_hdr) { ++ dev_err(&pdev->dev, "edma sysctl table hdr not registered\n"); ++ goto err_unregister_sysctl_tbl; ++ } ++ ++ /* Disable all 16 Tx and 8 rx irqs */ ++ edma_irq_disable(edma_cinfo); ++ ++ err = edma_reset(edma_cinfo); ++ if (err) { ++ err = -EIO; ++ goto err_reset; ++ } ++ ++ /* populate per_core_info, do a napi_Add, request 16 TX irqs, ++ * 8 RX irqs, do a napi enable ++ */ ++ for (i = 0; i < CONFIG_NR_CPUS; i++) { ++ u8 rx_start; ++ ++ edma_cinfo->edma_percpu_info[i].napi.state = 0; ++ ++ netif_napi_add(edma_netdev[0], ++ &edma_cinfo->edma_percpu_info[i].napi, ++ edma_poll, 64); ++ napi_enable(&edma_cinfo->edma_percpu_info[i].napi); ++ edma_cinfo->edma_percpu_info[i].tx_mask = tx_mask[i]; ++ edma_cinfo->edma_percpu_info[i].rx_mask = EDMA_RX_PER_CPU_MASK ++ << (i << EDMA_RX_PER_CPU_MASK_SHIFT); ++ edma_cinfo->edma_percpu_info[i].tx_start = tx_start[i]; ++ edma_cinfo->edma_percpu_info[i].rx_start = ++ i << EDMA_RX_CPU_START_SHIFT; ++ rx_start = i << EDMA_RX_CPU_START_SHIFT; ++ edma_cinfo->edma_percpu_info[i].tx_status = 0; ++ edma_cinfo->edma_percpu_info[i].rx_status = 0; ++ edma_cinfo->edma_percpu_info[i].edma_cinfo = edma_cinfo; ++ ++ /* Request irq per core */ ++ for (j = edma_cinfo->edma_percpu_info[i].tx_start; ++ j < tx_start[i] + 4; j++) { ++ sprintf(&edma_tx_irq[j][0], "edma_eth_tx%d", j); ++ err = request_irq(edma_cinfo->tx_irq[j], ++ edma_interrupt, ++ 0, ++ &edma_tx_irq[j][0], ++ &edma_cinfo->edma_percpu_info[i]); ++ if (err) ++ goto err_reset; ++ } ++ ++ for (j = edma_cinfo->edma_percpu_info[i].rx_start; ++ j < (rx_start + ++ ((edma_cinfo->num_rx_queues == 4) ? 1 : 2)); ++ j++) { ++ sprintf(&edma_rx_irq[j][0], "edma_eth_rx%d", j); ++ err = request_irq(edma_cinfo->rx_irq[j], ++ edma_interrupt, ++ 0, ++ &edma_rx_irq[j][0], ++ &edma_cinfo->edma_percpu_info[i]); ++ if (err) ++ goto err_reset; ++ } ++ ++#ifdef CONFIG_RFS_ACCEL ++ for (j = edma_cinfo->edma_percpu_info[i].rx_start; ++ j < rx_start + 2; j += 2) { ++ err = irq_cpu_rmap_add(edma_netdev[0]->rx_cpu_rmap, ++ edma_cinfo->rx_irq[j]); ++ if (err) ++ goto err_rmap_add_fail; ++ } ++#endif ++ } ++ ++ /* Used to clear interrupt status, allocate rx buffer, ++ * configure edma descriptors registers ++ */ ++ err = edma_configure(edma_cinfo); ++ if (err) { ++ err = -EIO; ++ goto err_configure; ++ } ++ ++ /* Configure RSS indirection table. ++ * 128 hash will be configured in the following ++ * pattern: hash{0,1,2,3} = {Q0,Q2,Q4,Q6} respectively ++ * and so on ++ */ ++ for (i = 0; i < EDMA_NUM_IDT; i++) ++ edma_write_reg(EDMA_REG_RSS_IDT(i), EDMA_RSS_IDT_VALUE); ++ ++ /* Configure load balance mapping table. ++ * 4 table entry will be configured according to the ++ * following pattern: load_balance{0,1,2,3} = {Q0,Q1,Q3,Q4} ++ * respectively. ++ */ ++ edma_write_reg(EDMA_REG_LB_RING, EDMA_LB_REG_VALUE); ++ ++ /* Configure Virtual queue for Tx rings ++ * User can also change this value runtime through ++ * a sysctl ++ */ ++ edma_write_reg(EDMA_REG_VQ_CTRL0, EDMA_VQ_REG_VALUE); ++ edma_write_reg(EDMA_REG_VQ_CTRL1, EDMA_VQ_REG_VALUE); ++ ++ /* Configure Max AXI Burst write size to 128 bytes*/ ++ edma_write_reg(EDMA_REG_AXIW_CTRL_MAXWRSIZE, ++ EDMA_AXIW_MAXWRSIZE_VALUE); ++ ++ /* Enable All 16 tx and 8 rx irq mask */ ++ edma_irq_enable(edma_cinfo); ++ edma_enable_tx_ctrl(&edma_cinfo->hw); ++ edma_enable_rx_ctrl(&edma_cinfo->hw); ++ ++ for (i = 0; i < edma_cinfo->num_gmac; i++) { ++ if (adapter[i]->poll_required) { ++ adapter[i]->phydev = ++ phy_connect(edma_netdev[i], ++ (const char *)adapter[i]->phy_id, ++ &edma_adjust_link, ++ PHY_INTERFACE_MODE_SGMII); ++ if (IS_ERR(adapter[i]->phydev)) { ++ dev_dbg(&pdev->dev, "PHY attach FAIL"); ++ err = -EIO; ++ goto edma_phy_attach_fail; ++ } else { ++ adapter[i]->phydev->advertising |= ++ ADVERTISED_Pause | ++ ADVERTISED_Asym_Pause; ++ adapter[i]->phydev->supported |= ++ SUPPORTED_Pause | ++ SUPPORTED_Asym_Pause; ++ } ++ } else { ++ adapter[i]->phydev = NULL; ++ } ++ } ++ ++ spin_lock_init(&edma_cinfo->stats_lock); ++ ++ init_timer(&edma_stats_timer); ++ edma_stats_timer.expires = jiffies + 1*HZ; ++ edma_stats_timer.data = (unsigned long)edma_cinfo; ++ edma_stats_timer.function = edma_statistics_timer; /* timer handler */ ++ add_timer(&edma_stats_timer); ++ ++ return 0; ++ ++edma_phy_attach_fail: ++ miibus = NULL; ++err_configure: ++#ifdef CONFIG_RFS_ACCEL ++ for (i = 0; i < edma_cinfo->num_gmac; i++) { ++ free_irq_cpu_rmap(adapter[i]->netdev->rx_cpu_rmap); ++ adapter[i]->netdev->rx_cpu_rmap = NULL; ++ } ++#endif ++err_rmap_add_fail: ++ edma_free_irqs(adapter[0]); ++ for (i = 0; i < CONFIG_NR_CPUS; i++) ++ napi_disable(&edma_cinfo->edma_percpu_info[i].napi); ++err_reset: ++err_unregister_sysctl_tbl: ++err_rmap_alloc_fail: ++ for (i = 0; i < edma_cinfo->num_gmac; i++) ++ unregister_netdev(edma_netdev[i]); ++err_register: ++err_mdiobus_init_fail: ++ edma_free_rx_rings(edma_cinfo); ++err_rx_rinit: ++ edma_free_tx_rings(edma_cinfo); ++err_tx_rinit: ++ edma_free_queues(edma_cinfo); ++err_rx_qinit: ++err_tx_qinit: ++ iounmap(edma_cinfo->hw.hw_addr); ++err_ioremap: ++ for (i = 0; i < edma_cinfo->num_gmac; i++) { ++ if (edma_netdev[i]) ++ free_netdev(edma_netdev[i]); ++ } ++err_cinfo: ++ kfree(edma_cinfo); ++err_alloc: ++ return err; ++} ++ ++/* edma_axi_remove() ++ * Device Removal Routine ++ * ++ * edma_axi_remove is called by the platform subsystem to alert the driver ++ * that it should release a platform device. ++ */ ++static int edma_axi_remove(struct platform_device *pdev) ++{ ++ struct edma_adapter *adapter = netdev_priv(edma_netdev[0]); ++ struct edma_common_info *edma_cinfo = adapter->edma_cinfo; ++ struct edma_hw *hw = &edma_cinfo->hw; ++ int i; ++ ++ for (i = 0; i < edma_cinfo->num_gmac; i++) ++ unregister_netdev(edma_netdev[i]); ++ ++ edma_stop_rx_tx(hw); ++ for (i = 0; i < CONFIG_NR_CPUS; i++) ++ napi_disable(&edma_cinfo->edma_percpu_info[i].napi); ++ ++ edma_irq_disable(edma_cinfo); ++ edma_write_reg(EDMA_REG_RX_ISR, 0xff); ++ edma_write_reg(EDMA_REG_TX_ISR, 0xffff); ++#ifdef CONFIG_RFS_ACCEL ++ for (i = 0; i < edma_cinfo->num_gmac; i++) { ++ free_irq_cpu_rmap(edma_netdev[i]->rx_cpu_rmap); ++ edma_netdev[i]->rx_cpu_rmap = NULL; ++ } ++#endif ++ ++ for (i = 0; i < edma_cinfo->num_gmac; i++) { ++ struct edma_adapter *adapter = netdev_priv(edma_netdev[i]); ++ ++ if (adapter->phydev) ++ phy_disconnect(adapter->phydev); ++ } ++ ++ del_timer_sync(&edma_stats_timer); ++ edma_free_irqs(adapter); ++ unregister_net_sysctl_table(edma_cinfo->edma_ctl_table_hdr); ++ edma_free_tx_resources(edma_cinfo); ++ edma_free_rx_resources(edma_cinfo); ++ edma_free_tx_rings(edma_cinfo); ++ edma_free_rx_rings(edma_cinfo); ++ edma_free_queues(edma_cinfo); ++ for (i = 0; i < edma_cinfo->num_gmac; i++) ++ free_netdev(edma_netdev[i]); ++ ++ kfree(edma_cinfo); ++ ++ return 0; ++} ++ ++static const struct of_device_id edma_of_mtable[] = { ++ {.compatible = "qcom,ess-edma" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, edma_of_mtable); ++ ++static struct platform_driver edma_axi_driver = { ++ .driver = { ++ .name = edma_axi_driver_name, ++ .of_match_table = edma_of_mtable, ++ }, ++ .probe = edma_axi_probe, ++ .remove = edma_axi_remove, ++}; ++ ++module_platform_driver(edma_axi_driver); ++ ++MODULE_AUTHOR("Qualcomm Atheros Inc"); ++MODULE_DESCRIPTION("QCA ESS EDMA driver"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/net/ethernet/qualcomm/essedma/edma_ethtool.c +@@ -0,0 +1,374 @@ ++/* ++ * Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for ++ * any purpose with or without fee is hereby granted, provided that the ++ * above copyright notice and this permission notice appear in all copies. ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT ++ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include "edma.h" ++ ++struct edma_ethtool_stats { ++ uint8_t stat_string[ETH_GSTRING_LEN]; ++ uint32_t stat_offset; ++}; ++ ++#define EDMA_STAT(m) offsetof(struct edma_ethtool_statistics, m) ++#define DRVINFO_LEN 32 ++ ++/* Array of strings describing statistics ++ */ ++static const struct edma_ethtool_stats edma_gstrings_stats[] = { ++ {"tx_q0_pkt", EDMA_STAT(tx_q0_pkt)}, ++ {"tx_q1_pkt", EDMA_STAT(tx_q1_pkt)}, ++ {"tx_q2_pkt", EDMA_STAT(tx_q2_pkt)}, ++ {"tx_q3_pkt", EDMA_STAT(tx_q3_pkt)}, ++ {"tx_q4_pkt", EDMA_STAT(tx_q4_pkt)}, ++ {"tx_q5_pkt", EDMA_STAT(tx_q5_pkt)}, ++ {"tx_q6_pkt", EDMA_STAT(tx_q6_pkt)}, ++ {"tx_q7_pkt", EDMA_STAT(tx_q7_pkt)}, ++ {"tx_q8_pkt", EDMA_STAT(tx_q8_pkt)}, ++ {"tx_q9_pkt", EDMA_STAT(tx_q9_pkt)}, ++ {"tx_q10_pkt", EDMA_STAT(tx_q10_pkt)}, ++ {"tx_q11_pkt", EDMA_STAT(tx_q11_pkt)}, ++ {"tx_q12_pkt", EDMA_STAT(tx_q12_pkt)}, ++ {"tx_q13_pkt", EDMA_STAT(tx_q13_pkt)}, ++ {"tx_q14_pkt", EDMA_STAT(tx_q14_pkt)}, ++ {"tx_q15_pkt", EDMA_STAT(tx_q15_pkt)}, ++ {"tx_q0_byte", EDMA_STAT(tx_q0_byte)}, ++ {"tx_q1_byte", EDMA_STAT(tx_q1_byte)}, ++ {"tx_q2_byte", EDMA_STAT(tx_q2_byte)}, ++ {"tx_q3_byte", EDMA_STAT(tx_q3_byte)}, ++ {"tx_q4_byte", EDMA_STAT(tx_q4_byte)}, ++ {"tx_q5_byte", EDMA_STAT(tx_q5_byte)}, ++ {"tx_q6_byte", EDMA_STAT(tx_q6_byte)}, ++ {"tx_q7_byte", EDMA_STAT(tx_q7_byte)}, ++ {"tx_q8_byte", EDMA_STAT(tx_q8_byte)}, ++ {"tx_q9_byte", EDMA_STAT(tx_q9_byte)}, ++ {"tx_q10_byte", EDMA_STAT(tx_q10_byte)}, ++ {"tx_q11_byte", EDMA_STAT(tx_q11_byte)}, ++ {"tx_q12_byte", EDMA_STAT(tx_q12_byte)}, ++ {"tx_q13_byte", EDMA_STAT(tx_q13_byte)}, ++ {"tx_q14_byte", EDMA_STAT(tx_q14_byte)}, ++ {"tx_q15_byte", EDMA_STAT(tx_q15_byte)}, ++ {"rx_q0_pkt", EDMA_STAT(rx_q0_pkt)}, ++ {"rx_q1_pkt", EDMA_STAT(rx_q1_pkt)}, ++ {"rx_q2_pkt", EDMA_STAT(rx_q2_pkt)}, ++ {"rx_q3_pkt", EDMA_STAT(rx_q3_pkt)}, ++ {"rx_q4_pkt", EDMA_STAT(rx_q4_pkt)}, ++ {"rx_q5_pkt", EDMA_STAT(rx_q5_pkt)}, ++ {"rx_q6_pkt", EDMA_STAT(rx_q6_pkt)}, ++ {"rx_q7_pkt", EDMA_STAT(rx_q7_pkt)}, ++ {"rx_q0_byte", EDMA_STAT(rx_q0_byte)}, ++ {"rx_q1_byte", EDMA_STAT(rx_q1_byte)}, ++ {"rx_q2_byte", EDMA_STAT(rx_q2_byte)}, ++ {"rx_q3_byte", EDMA_STAT(rx_q3_byte)}, ++ {"rx_q4_byte", EDMA_STAT(rx_q4_byte)}, ++ {"rx_q5_byte", EDMA_STAT(rx_q5_byte)}, ++ {"rx_q6_byte", EDMA_STAT(rx_q6_byte)}, ++ {"rx_q7_byte", EDMA_STAT(rx_q7_byte)}, ++ {"tx_desc_error", EDMA_STAT(tx_desc_error)}, ++}; ++ ++#define EDMA_STATS_LEN ARRAY_SIZE(edma_gstrings_stats) ++ ++/* edma_get_strset_count() ++ * Get strset count ++ */ ++static int edma_get_strset_count(struct net_device *netdev, ++ int sset) ++{ ++ switch (sset) { ++ case ETH_SS_STATS: ++ return EDMA_STATS_LEN; ++ default: ++ netdev_dbg(netdev, "%s: Invalid string set", __func__); ++ return -EOPNOTSUPP; ++ } ++} ++ ++ ++/* edma_get_strings() ++ * get stats string ++ */ ++static void edma_get_strings(struct net_device *netdev, uint32_t stringset, ++ uint8_t *data) ++{ ++ uint8_t *p = data; ++ uint32_t i; ++ ++ switch (stringset) { ++ case ETH_SS_STATS: ++ for (i = 0; i < EDMA_STATS_LEN; i++) { ++ memcpy(p, edma_gstrings_stats[i].stat_string, ++ min((size_t)ETH_GSTRING_LEN, ++ strlen(edma_gstrings_stats[i].stat_string) ++ + 1)); ++ p += ETH_GSTRING_LEN; ++ } ++ break; ++ } ++} ++ ++/* edma_get_ethtool_stats() ++ * Get ethtool statistics ++ */ ++static void edma_get_ethtool_stats(struct net_device *netdev, ++ struct ethtool_stats *stats, uint64_t *data) ++{ ++ struct edma_adapter *adapter = netdev_priv(netdev); ++ struct edma_common_info *edma_cinfo = adapter->edma_cinfo; ++ int i; ++ uint8_t *p = NULL; ++ ++ edma_read_append_stats(edma_cinfo); ++ ++ for(i = 0; i < EDMA_STATS_LEN; i++) { ++ p = (uint8_t *)&(edma_cinfo->edma_ethstats) + ++ edma_gstrings_stats[i].stat_offset; ++ data[i] = *(uint32_t *)p; ++ } ++} ++ ++/* edma_get_drvinfo() ++ * get edma driver info ++ */ ++static void edma_get_drvinfo(struct net_device *dev, ++ struct ethtool_drvinfo *info) ++{ ++ strlcpy(info->driver, "ess_edma", DRVINFO_LEN); ++ strlcpy(info->bus_info, "axi", ETHTOOL_BUSINFO_LEN); ++} ++ ++/* edma_nway_reset() ++ * Reset the phy, if available. ++ */ ++static int edma_nway_reset(struct net_device *netdev) ++{ ++ return -EINVAL; ++} ++ ++/* edma_get_wol() ++ * get wake on lan info ++ */ ++static void edma_get_wol(struct net_device *netdev, ++ struct ethtool_wolinfo *wol) ++{ ++ wol->supported = 0; ++ wol->wolopts = 0; ++} ++ ++/* edma_get_msglevel() ++ * get message level. ++ */ ++static uint32_t edma_get_msglevel(struct net_device *netdev) ++{ ++ return 0; ++} ++ ++/* edma_get_settings() ++ * Get edma settings ++ */ ++static int edma_get_settings(struct net_device *netdev, ++ struct ethtool_cmd *ecmd) ++{ ++ struct edma_adapter *adapter = netdev_priv(netdev); ++ ++ if (adapter->poll_required) { ++ struct phy_device *phydev = NULL; ++ uint16_t phyreg; ++ ++ if ((adapter->forced_speed != SPEED_UNKNOWN) ++ && !(adapter->poll_required)) ++ return -EPERM; ++ ++ phydev = adapter->phydev; ++ ++ ecmd->advertising = phydev->advertising; ++ ecmd->autoneg = phydev->autoneg; ++ ++ if (adapter->link_state == __EDMA_LINKDOWN) { ++ ecmd->speed = SPEED_UNKNOWN; ++ ecmd->duplex = DUPLEX_UNKNOWN; ++ } else { ++ ecmd->speed = phydev->speed; ++ ecmd->duplex = phydev->duplex; ++ } ++ ++ ecmd->phy_address = adapter->phy_mdio_addr; ++ ++ phyreg = (uint16_t)phy_read(adapter->phydev, MII_LPA); ++ if (phyreg & LPA_10HALF) ++ ecmd->lp_advertising |= ADVERTISED_10baseT_Half; ++ ++ if (phyreg & LPA_10FULL) ++ ecmd->lp_advertising |= ADVERTISED_10baseT_Full; ++ ++ if (phyreg & LPA_100HALF) ++ ecmd->lp_advertising |= ADVERTISED_100baseT_Half; ++ ++ if (phyreg & LPA_100FULL) ++ ecmd->lp_advertising |= ADVERTISED_100baseT_Full; ++ ++ phyreg = (uint16_t)phy_read(adapter->phydev, MII_STAT1000); ++ if (phyreg & LPA_1000HALF) ++ ecmd->lp_advertising |= ADVERTISED_1000baseT_Half; ++ ++ if (phyreg & LPA_1000FULL) ++ ecmd->lp_advertising |= ADVERTISED_1000baseT_Full; ++ } else { ++ /* If the speed/duplex for this GMAC is forced and we ++ * are not polling for link state changes, return the ++ * values as specified by platform. This will be true ++ * for GMACs connected to switch, and interfaces that ++ * do not use a PHY. ++ */ ++ if (!(adapter->poll_required)) { ++ if (adapter->forced_speed != SPEED_UNKNOWN) { ++ /* set speed and duplex */ ++ ethtool_cmd_speed_set(ecmd, SPEED_1000); ++ ecmd->duplex = DUPLEX_FULL; ++ ++ /* Populate capabilities advertised by self */ ++ ecmd->advertising = 0; ++ ecmd->autoneg = 0; ++ ecmd->port = PORT_TP; ++ ecmd->transceiver = XCVR_EXTERNAL; ++ } else { ++ /* non link polled and non ++ * forced speed/duplex interface ++ */ ++ return -EIO; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++/* edma_set_settings() ++ * Set EDMA settings ++ */ ++static int edma_set_settings(struct net_device *netdev, ++ struct ethtool_cmd *ecmd) ++{ ++ struct edma_adapter *adapter = netdev_priv(netdev); ++ struct phy_device *phydev = NULL; ++ ++ if ((adapter->forced_speed != SPEED_UNKNOWN) && ++ !adapter->poll_required) ++ return -EPERM; ++ ++ phydev = adapter->phydev; ++ phydev->advertising = ecmd->advertising; ++ phydev->autoneg = ecmd->autoneg; ++ phydev->speed = ethtool_cmd_speed(ecmd); ++ phydev->duplex = ecmd->duplex; ++ ++ genphy_config_aneg(phydev); ++ ++ return 0; ++} ++ ++/* edma_get_coalesce ++ * get interrupt mitigation ++ */ ++static int edma_get_coalesce(struct net_device *netdev, ++ struct ethtool_coalesce *ec) ++{ ++ u32 reg_val; ++ ++ edma_get_tx_rx_coalesce(®_val); ++ ++ /* We read the Interrupt Moderation Timer(IMT) register value, ++ * use lower 16 bit for rx and higher 16 bit for Tx. We do a ++ * left shift by 1, because IMT resolution timer is 2usecs. ++ * Hence the value given by the register is multiplied by 2 to ++ * get the actual time in usecs. ++ */ ++ ec->tx_coalesce_usecs = (((reg_val >> 16) & 0xffff) << 1); ++ ec->rx_coalesce_usecs = ((reg_val & 0xffff) << 1); ++ ++ return 0; ++} ++ ++/* edma_set_coalesce ++ * set interrupt mitigation ++ */ ++static int edma_set_coalesce(struct net_device *netdev, ++ struct ethtool_coalesce *ec) ++{ ++ if (ec->tx_coalesce_usecs) ++ edma_change_tx_coalesce(ec->tx_coalesce_usecs); ++ if (ec->rx_coalesce_usecs) ++ edma_change_rx_coalesce(ec->rx_coalesce_usecs); ++ ++ return 0; ++} ++ ++/* edma_set_priv_flags() ++ * Set EDMA private flags ++ */ ++static int edma_set_priv_flags(struct net_device *netdev, u32 flags) ++{ ++ return 0; ++} ++ ++/* edma_get_priv_flags() ++ * get edma driver flags ++ */ ++static u32 edma_get_priv_flags(struct net_device *netdev) ++{ ++ return 0; ++} ++ ++/* edma_get_ringparam() ++ * get ring size ++ */ ++static void edma_get_ringparam(struct net_device *netdev, ++ struct ethtool_ringparam *ring) ++{ ++ struct edma_adapter *adapter = netdev_priv(netdev); ++ struct edma_common_info *edma_cinfo = adapter->edma_cinfo; ++ ++ ring->tx_max_pending = edma_cinfo->tx_ring_count; ++ ring->rx_max_pending = edma_cinfo->rx_ring_count; ++} ++ ++/* Ethtool operations ++ */ ++static const struct ethtool_ops edma_ethtool_ops = { ++ .get_drvinfo = &edma_get_drvinfo, ++ .get_link = ðtool_op_get_link, ++ .get_msglevel = &edma_get_msglevel, ++ .nway_reset = &edma_nway_reset, ++ .get_wol = &edma_get_wol, ++ .get_settings = &edma_get_settings, ++ .set_settings = &edma_set_settings, ++ .get_strings = &edma_get_strings, ++ .get_sset_count = &edma_get_strset_count, ++ .get_ethtool_stats = &edma_get_ethtool_stats, ++ .get_coalesce = &edma_get_coalesce, ++ .set_coalesce = &edma_set_coalesce, ++ .get_priv_flags = edma_get_priv_flags, ++ .set_priv_flags = edma_set_priv_flags, ++ .get_ringparam = edma_get_ringparam, ++}; ++ ++/* edma_set_ethtool_ops ++ * Set ethtool operations ++ */ ++void edma_set_ethtool_ops(struct net_device *netdev) ++{ ++ netdev->ethtool_ops = &edma_ethtool_ops; ++} +--- /dev/null ++++ b/drivers/net/ethernet/qualcomm/essedma/ess_edma.h +@@ -0,0 +1,332 @@ ++/* ++ * Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for ++ * any purpose with or without fee is hereby granted, provided that the ++ * above copyright notice and this permission notice appear in all copies. ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT ++ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _ESS_EDMA_H_ ++#define _ESS_EDMA_H_ ++ ++#include ++ ++struct edma_adapter; ++struct edma_hw; ++ ++/* register definition */ ++#define EDMA_REG_MAS_CTRL 0x0 ++#define EDMA_REG_TIMEOUT_CTRL 0x004 ++#define EDMA_REG_DBG0 0x008 ++#define EDMA_REG_DBG1 0x00C ++#define EDMA_REG_SW_CTRL0 0x100 ++#define EDMA_REG_SW_CTRL1 0x104 ++ ++/* Interrupt Status Register */ ++#define EDMA_REG_RX_ISR 0x200 ++#define EDMA_REG_TX_ISR 0x208 ++#define EDMA_REG_MISC_ISR 0x210 ++#define EDMA_REG_WOL_ISR 0x218 ++ ++#define EDMA_MISC_ISR_RX_URG_Q(x) (1 << x) ++ ++#define EDMA_MISC_ISR_AXIR_TIMEOUT 0x00000100 ++#define EDMA_MISC_ISR_AXIR_ERR 0x00000200 ++#define EDMA_MISC_ISR_TXF_DEAD 0x00000400 ++#define EDMA_MISC_ISR_AXIW_ERR 0x00000800 ++#define EDMA_MISC_ISR_AXIW_TIMEOUT 0x00001000 ++ ++#define EDMA_WOL_ISR 0x00000001 ++ ++/* Interrupt Mask Register */ ++#define EDMA_REG_MISC_IMR 0x214 ++#define EDMA_REG_WOL_IMR 0x218 ++ ++#define EDMA_RX_IMR_NORMAL_MASK 0x1 ++#define EDMA_TX_IMR_NORMAL_MASK 0x1 ++#define EDMA_MISC_IMR_NORMAL_MASK 0x80001FFF ++#define EDMA_WOL_IMR_NORMAL_MASK 0x1 ++ ++/* Edma receive consumer index */ ++#define EDMA_REG_RX_SW_CONS_IDX_Q(x) (0x220 + ((x) << 2)) /* x is the queue id */ ++/* Edma transmit consumer index */ ++#define EDMA_REG_TX_SW_CONS_IDX_Q(x) (0x240 + ((x) << 2)) /* x is the queue id */ ++ ++/* IRQ Moderator Initial Timer Register */ ++#define EDMA_REG_IRQ_MODRT_TIMER_INIT 0x280 ++#define EDMA_IRQ_MODRT_TIMER_MASK 0xFFFF ++#define EDMA_IRQ_MODRT_RX_TIMER_SHIFT 0 ++#define EDMA_IRQ_MODRT_TX_TIMER_SHIFT 16 ++ ++/* Interrupt Control Register */ ++#define EDMA_REG_INTR_CTRL 0x284 ++#define EDMA_INTR_CLR_TYP_SHIFT 0 ++#define EDMA_INTR_SW_IDX_W_TYP_SHIFT 1 ++#define EDMA_INTR_CLEAR_TYPE_W1 0 ++#define EDMA_INTR_CLEAR_TYPE_R 1 ++ ++/* RX Interrupt Mask Register */ ++#define EDMA_REG_RX_INT_MASK_Q(x) (0x300 + ((x) << 2)) /* x = queue id */ ++ ++/* TX Interrupt mask register */ ++#define EDMA_REG_TX_INT_MASK_Q(x) (0x340 + ((x) << 2)) /* x = queue id */ ++ ++/* Load Ptr Register ++ * Software sets this bit after the initialization of the head and tail ++ */ ++#define EDMA_REG_TX_SRAM_PART 0x400 ++#define EDMA_LOAD_PTR_SHIFT 16 ++ ++/* TXQ Control Register */ ++#define EDMA_REG_TXQ_CTRL 0x404 ++#define EDMA_TXQ_CTRL_IP_OPTION_EN 0x10 ++#define EDMA_TXQ_CTRL_TXQ_EN 0x20 ++#define EDMA_TXQ_CTRL_ENH_MODE 0x40 ++#define EDMA_TXQ_CTRL_LS_8023_EN 0x80 ++#define EDMA_TXQ_CTRL_TPD_BURST_EN 0x100 ++#define EDMA_TXQ_CTRL_LSO_BREAK_EN 0x200 ++#define EDMA_TXQ_NUM_TPD_BURST_MASK 0xF ++#define EDMA_TXQ_TXF_BURST_NUM_MASK 0xFFFF ++#define EDMA_TXQ_NUM_TPD_BURST_SHIFT 0 ++#define EDMA_TXQ_TXF_BURST_NUM_SHIFT 16 ++ ++#define EDMA_REG_TXF_WATER_MARK 0x408 /* In 8-bytes */ ++#define EDMA_TXF_WATER_MARK_MASK 0x0FFF ++#define EDMA_TXF_LOW_WATER_MARK_SHIFT 0 ++#define EDMA_TXF_HIGH_WATER_MARK_SHIFT 16 ++#define EDMA_TXQ_CTRL_BURST_MODE_EN 0x80000000 ++ ++/* WRR Control Register */ ++#define EDMA_REG_WRR_CTRL_Q0_Q3 0x40c ++#define EDMA_REG_WRR_CTRL_Q4_Q7 0x410 ++#define EDMA_REG_WRR_CTRL_Q8_Q11 0x414 ++#define EDMA_REG_WRR_CTRL_Q12_Q15 0x418 ++ ++/* Weight round robin(WRR), it takes queue as input, and computes ++ * starting bits where we need to write the weight for a particular ++ * queue ++ */ ++#define EDMA_WRR_SHIFT(x) (((x) * 5) % 20) ++ ++/* Tx Descriptor Control Register */ ++#define EDMA_REG_TPD_RING_SIZE 0x41C ++#define EDMA_TPD_RING_SIZE_SHIFT 0 ++#define EDMA_TPD_RING_SIZE_MASK 0xFFFF ++ ++/* Transmit descriptor base address */ ++#define EDMA_REG_TPD_BASE_ADDR_Q(x) (0x420 + ((x) << 2)) /* x = queue id */ ++ ++/* TPD Index Register */ ++#define EDMA_REG_TPD_IDX_Q(x) (0x460 + ((x) << 2)) /* x = queue id */ ++ ++#define EDMA_TPD_PROD_IDX_BITS 0x0000FFFF ++#define EDMA_TPD_CONS_IDX_BITS 0xFFFF0000 ++#define EDMA_TPD_PROD_IDX_MASK 0xFFFF ++#define EDMA_TPD_CONS_IDX_MASK 0xFFFF ++#define EDMA_TPD_PROD_IDX_SHIFT 0 ++#define EDMA_TPD_CONS_IDX_SHIFT 16 ++ ++/* TX Virtual Queue Mapping Control Register */ ++#define EDMA_REG_VQ_CTRL0 0x4A0 ++#define EDMA_REG_VQ_CTRL1 0x4A4 ++ ++/* Virtual QID shift, it takes queue as input, and computes ++ * Virtual QID position in virtual qid control register ++ */ ++#define EDMA_VQ_ID_SHIFT(i) (((i) * 3) % 24) ++ ++/* Virtual Queue Default Value */ ++#define EDMA_VQ_REG_VALUE 0x240240 ++ ++/* Tx side Port Interface Control Register */ ++#define EDMA_REG_PORT_CTRL 0x4A8 ++#define EDMA_PAD_EN_SHIFT 15 ++ ++/* Tx side VLAN Configuration Register */ ++#define EDMA_REG_VLAN_CFG 0x4AC ++ ++#define EDMA_TX_CVLAN 16 ++#define EDMA_TX_INS_CVLAN 17 ++#define EDMA_TX_CVLAN_TAG_SHIFT 0 ++ ++#define EDMA_TX_SVLAN 14 ++#define EDMA_TX_INS_SVLAN 15 ++#define EDMA_TX_SVLAN_TAG_SHIFT 16 ++ ++/* Tx Queue Packet Statistic Register */ ++#define EDMA_REG_TX_STAT_PKT_Q(x) (0x700 + ((x) << 3)) /* x = queue id */ ++ ++#define EDMA_TX_STAT_PKT_MASK 0xFFFFFF ++ ++/* Tx Queue Byte Statistic Register */ ++#define EDMA_REG_TX_STAT_BYTE_Q(x) (0x704 + ((x) << 3)) /* x = queue id */ ++ ++/* Load Balance Based Ring Offset Register */ ++#define EDMA_REG_LB_RING 0x800 ++#define EDMA_LB_RING_ENTRY_MASK 0xff ++#define EDMA_LB_RING_ID_MASK 0x7 ++#define EDMA_LB_RING_PROFILE_ID_MASK 0x3 ++#define EDMA_LB_RING_ENTRY_BIT_OFFSET 8 ++#define EDMA_LB_RING_ID_OFFSET 0 ++#define EDMA_LB_RING_PROFILE_ID_OFFSET 3 ++#define EDMA_LB_REG_VALUE 0x6040200 ++ ++/* Load Balance Priority Mapping Register */ ++#define EDMA_REG_LB_PRI_START 0x804 ++#define EDMA_REG_LB_PRI_END 0x810 ++#define EDMA_LB_PRI_REG_INC 4 ++#define EDMA_LB_PRI_ENTRY_BIT_OFFSET 4 ++#define EDMA_LB_PRI_ENTRY_MASK 0xf ++ ++/* RSS Priority Mapping Register */ ++#define EDMA_REG_RSS_PRI 0x820 ++#define EDMA_RSS_PRI_ENTRY_MASK 0xf ++#define EDMA_RSS_RING_ID_MASK 0x7 ++#define EDMA_RSS_PRI_ENTRY_BIT_OFFSET 4 ++ ++/* RSS Indirection Register */ ++#define EDMA_REG_RSS_IDT(x) (0x840 + ((x) << 2)) /* x = No. of indirection table */ ++#define EDMA_NUM_IDT 16 ++#define EDMA_RSS_IDT_VALUE 0x64206420 ++ ++/* Default RSS Ring Register */ ++#define EDMA_REG_DEF_RSS 0x890 ++#define EDMA_DEF_RSS_MASK 0x7 ++ ++/* RSS Hash Function Type Register */ ++#define EDMA_REG_RSS_TYPE 0x894 ++#define EDMA_RSS_TYPE_NONE 0x01 ++#define EDMA_RSS_TYPE_IPV4TCP 0x02 ++#define EDMA_RSS_TYPE_IPV6_TCP 0x04 ++#define EDMA_RSS_TYPE_IPV4_UDP 0x08 ++#define EDMA_RSS_TYPE_IPV6UDP 0x10 ++#define EDMA_RSS_TYPE_IPV4 0x20 ++#define EDMA_RSS_TYPE_IPV6 0x40 ++#define EDMA_RSS_HASH_MODE_MASK 0x7f ++ ++#define EDMA_REG_RSS_HASH_VALUE 0x8C0 ++ ++#define EDMA_REG_RSS_TYPE_RESULT 0x8C4 ++ ++#define EDMA_HASH_TYPE_START 0 ++#define EDMA_HASH_TYPE_END 5 ++#define EDMA_HASH_TYPE_SHIFT 12 ++ ++#define EDMA_RFS_FLOW_ENTRIES 1024 ++#define EDMA_RFS_FLOW_ENTRIES_MASK (EDMA_RFS_FLOW_ENTRIES - 1) ++#define EDMA_RFS_EXPIRE_COUNT_PER_CALL 128 ++ ++/* RFD Base Address Register */ ++#define EDMA_REG_RFD_BASE_ADDR_Q(x) (0x950 + ((x) << 2)) /* x = queue id */ ++ ++/* RFD Index Register */ ++#define EDMA_REG_RFD_IDX_Q(x) (0x9B0 + ((x) << 2)) ++ ++#define EDMA_RFD_PROD_IDX_BITS 0x00000FFF ++#define EDMA_RFD_CONS_IDX_BITS 0x0FFF0000 ++#define EDMA_RFD_PROD_IDX_MASK 0xFFF ++#define EDMA_RFD_CONS_IDX_MASK 0xFFF ++#define EDMA_RFD_PROD_IDX_SHIFT 0 ++#define EDMA_RFD_CONS_IDX_SHIFT 16 ++ ++/* Rx Descriptor Control Register */ ++#define EDMA_REG_RX_DESC0 0xA10 ++#define EDMA_RFD_RING_SIZE_MASK 0xFFF ++#define EDMA_RX_BUF_SIZE_MASK 0xFFFF ++#define EDMA_RFD_RING_SIZE_SHIFT 0 ++#define EDMA_RX_BUF_SIZE_SHIFT 16 ++ ++#define EDMA_REG_RX_DESC1 0xA14 ++#define EDMA_RXQ_RFD_BURST_NUM_MASK 0x3F ++#define EDMA_RXQ_RFD_PF_THRESH_MASK 0x1F ++#define EDMA_RXQ_RFD_LOW_THRESH_MASK 0xFFF ++#define EDMA_RXQ_RFD_BURST_NUM_SHIFT 0 ++#define EDMA_RXQ_RFD_PF_THRESH_SHIFT 8 ++#define EDMA_RXQ_RFD_LOW_THRESH_SHIFT 16 ++ ++/* RXQ Control Register */ ++#define EDMA_REG_RXQ_CTRL 0xA18 ++#define EDMA_FIFO_THRESH_TYPE_SHIF 0 ++#define EDMA_FIFO_THRESH_128_BYTE 0x0 ++#define EDMA_FIFO_THRESH_64_BYTE 0x1 ++#define EDMA_RXQ_CTRL_RMV_VLAN 0x00000002 ++#define EDMA_RXQ_CTRL_EN 0x0000FF00 ++ ++/* AXI Burst Size Config */ ++#define EDMA_REG_AXIW_CTRL_MAXWRSIZE 0xA1C ++#define EDMA_AXIW_MAXWRSIZE_VALUE 0x0 ++ ++/* Rx Statistics Register */ ++#define EDMA_REG_RX_STAT_BYTE_Q(x) (0xA30 + ((x) << 2)) /* x = queue id */ ++#define EDMA_REG_RX_STAT_PKT_Q(x) (0xA50 + ((x) << 2)) /* x = queue id */ ++ ++/* WoL Pattern Length Register */ ++#define EDMA_REG_WOL_PATTERN_LEN0 0xC00 ++#define EDMA_WOL_PT_LEN_MASK 0xFF ++#define EDMA_WOL_PT0_LEN_SHIFT 0 ++#define EDMA_WOL_PT1_LEN_SHIFT 8 ++#define EDMA_WOL_PT2_LEN_SHIFT 16 ++#define EDMA_WOL_PT3_LEN_SHIFT 24 ++ ++#define EDMA_REG_WOL_PATTERN_LEN1 0xC04 ++#define EDMA_WOL_PT4_LEN_SHIFT 0 ++#define EDMA_WOL_PT5_LEN_SHIFT 8 ++#define EDMA_WOL_PT6_LEN_SHIFT 16 ++ ++/* WoL Control Register */ ++#define EDMA_REG_WOL_CTRL 0xC08 ++#define EDMA_WOL_WK_EN 0x00000001 ++#define EDMA_WOL_MG_EN 0x00000002 ++#define EDMA_WOL_PT0_EN 0x00000004 ++#define EDMA_WOL_PT1_EN 0x00000008 ++#define EDMA_WOL_PT2_EN 0x00000010 ++#define EDMA_WOL_PT3_EN 0x00000020 ++#define EDMA_WOL_PT4_EN 0x00000040 ++#define EDMA_WOL_PT5_EN 0x00000080 ++#define EDMA_WOL_PT6_EN 0x00000100 ++ ++/* MAC Control Register */ ++#define EDMA_REG_MAC_CTRL0 0xC20 ++#define EDMA_REG_MAC_CTRL1 0xC24 ++ ++/* WoL Pattern Register */ ++#define EDMA_REG_WOL_PATTERN_START 0x5000 ++#define EDMA_PATTERN_PART_REG_OFFSET 0x40 ++ ++ ++/* TX descriptor fields */ ++#define EDMA_TPD_HDR_SHIFT 0 ++#define EDMA_TPD_PPPOE_EN 0x00000100 ++#define EDMA_TPD_IP_CSUM_EN 0x00000200 ++#define EDMA_TPD_TCP_CSUM_EN 0x0000400 ++#define EDMA_TPD_UDP_CSUM_EN 0x00000800 ++#define EDMA_TPD_CUSTOM_CSUM_EN 0x00000C00 ++#define EDMA_TPD_LSO_EN 0x00001000 ++#define EDMA_TPD_LSO_V2_EN 0x00002000 ++#define EDMA_TPD_IPV4_EN 0x00010000 ++#define EDMA_TPD_MSS_MASK 0x1FFF ++#define EDMA_TPD_MSS_SHIFT 18 ++#define EDMA_TPD_CUSTOM_CSUM_SHIFT 18 ++ ++/* RRD descriptor fields */ ++#define EDMA_RRD_NUM_RFD_MASK 0x000F ++#define EDMA_RRD_SVLAN 0x8000 ++#define EDMA_RRD_FLOW_COOKIE_MASK 0x07FF; ++ ++#define EDMA_RRD_PKT_SIZE_MASK 0x3FFF ++#define EDMA_RRD_CSUM_FAIL_MASK 0xC000 ++#define EDMA_RRD_CVLAN 0x0001 ++#define EDMA_RRD_DESC_VALID 0x8000 ++ ++#define EDMA_RRD_PRIORITY_SHIFT 4 ++#define EDMA_RRD_PRIORITY_MASK 0x7 ++#define EDMA_RRD_PORT_TYPE_SHIFT 7 ++#define EDMA_RRD_PORT_TYPE_MASK 0x1F ++#endif /* _ESS_EDMA_H_ */ diff --git a/target/linux/ipq40xx/patches-4.14/711-dts-ipq4019-add-ethernet-essedma-node.patch b/target/linux/ipq40xx/patches-4.14/711-dts-ipq4019-add-ethernet-essedma-node.patch new file mode 100644 index 000000000..285cafd6d --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/711-dts-ipq4019-add-ethernet-essedma-node.patch @@ -0,0 +1,92 @@ +From c611d3780fa101662a822d10acf8feb04ca97409 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sun, 20 Nov 2016 01:01:10 +0100 +Subject: [PATCH] dts: ipq4019: add ethernet essedma node + +This patch adds the device-tree node for the ethernet +interfaces. + +Note: The driver isn't anywhere close to be upstream, +so the info might change. + +Signed-off-by: Christian Lamparter +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 60 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 60 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -28,6 +28,8 @@ + spi1 = &spi_1; + i2c0 = &i2c_0; + i2c1 = &i2c_1; ++ ethernet0 = &gmac0; ++ ethernet1 = &gmac1; + }; + + cpus { +@@ -590,6 +592,64 @@ + status = "disabled"; + }; + ++ edma@c080000 { ++ compatible = "qcom,ess-edma"; ++ reg = <0xc080000 0x8000>; ++ qcom,page-mode = <0>; ++ qcom,rx_head_buf_size = <1540>; ++ qcom,mdio_supported; ++ qcom,poll_required = <1>; ++ qcom,num_gmac = <2>; ++ interrupts = <0 65 IRQ_TYPE_EDGE_RISING ++ 0 66 IRQ_TYPE_EDGE_RISING ++ 0 67 IRQ_TYPE_EDGE_RISING ++ 0 68 IRQ_TYPE_EDGE_RISING ++ 0 69 IRQ_TYPE_EDGE_RISING ++ 0 70 IRQ_TYPE_EDGE_RISING ++ 0 71 IRQ_TYPE_EDGE_RISING ++ 0 72 IRQ_TYPE_EDGE_RISING ++ 0 73 IRQ_TYPE_EDGE_RISING ++ 0 74 IRQ_TYPE_EDGE_RISING ++ 0 75 IRQ_TYPE_EDGE_RISING ++ 0 76 IRQ_TYPE_EDGE_RISING ++ 0 77 IRQ_TYPE_EDGE_RISING ++ 0 78 IRQ_TYPE_EDGE_RISING ++ 0 79 IRQ_TYPE_EDGE_RISING ++ 0 80 IRQ_TYPE_EDGE_RISING ++ 0 240 IRQ_TYPE_EDGE_RISING ++ 0 241 IRQ_TYPE_EDGE_RISING ++ 0 242 IRQ_TYPE_EDGE_RISING ++ 0 243 IRQ_TYPE_EDGE_RISING ++ 0 244 IRQ_TYPE_EDGE_RISING ++ 0 245 IRQ_TYPE_EDGE_RISING ++ 0 246 IRQ_TYPE_EDGE_RISING ++ 0 247 IRQ_TYPE_EDGE_RISING ++ 0 248 IRQ_TYPE_EDGE_RISING ++ 0 249 IRQ_TYPE_EDGE_RISING ++ 0 250 IRQ_TYPE_EDGE_RISING ++ 0 251 IRQ_TYPE_EDGE_RISING ++ 0 252 IRQ_TYPE_EDGE_RISING ++ 0 253 IRQ_TYPE_EDGE_RISING ++ 0 254 IRQ_TYPE_EDGE_RISING ++ 0 255 IRQ_TYPE_EDGE_RISING>; ++ ++ status = "disabled"; ++ ++ gmac0: gmac0 { ++ local-mac-address = [00 00 00 00 00 00]; ++ vlan_tag = <1 0x1f>; ++ }; ++ ++ gmac1: gmac1 { ++ local-mac-address = [00 00 00 00 00 00]; ++ qcom,phy_mdio_addr = <4>; ++ qcom,poll_required = <1>; ++ qcom,forced_speed = <1000>; ++ qcom,forced_duplex = <1>; ++ vlan_tag = <2 0x20>; ++ }; ++ }; ++ + usb3_ss_phy: ssphy@9a000 { + compatible = "qca,uni-ssphy"; + reg = <0x9a000 0x800>; diff --git a/target/linux/ipq40xx/patches-4.14/712-mr33-essedma.patch b/target/linux/ipq40xx/patches-4.14/712-mr33-essedma.patch new file mode 100644 index 000000000..6be30070d --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/712-mr33-essedma.patch @@ -0,0 +1,340 @@ +--- a/drivers/net/ethernet/qualcomm/essedma/edma_axi.c ++++ b/drivers/net/ethernet/qualcomm/essedma/edma_axi.c +@@ -17,6 +17,11 @@ + #include + #include + #include ++#include ++#include ++#include ++#include ++#include + #include "edma.h" + #include "ess_edma.h" + +@@ -83,7 +88,103 @@ void edma_read_reg(u16 reg_addr, volatil + *reg_value = readl((void __iomem *)(edma_hw_addr + reg_addr)); + } + +-/* edma_change_tx_coalesce() ++static void ess_write_reg(struct edma_common_info *edma, u16 reg_addr, u32 reg_value) ++{ ++ writel(reg_value, ((void __iomem *) ++ ((unsigned long)edma->ess_hw_addr + reg_addr))); ++} ++ ++static void ess_read_reg(struct edma_common_info *edma, u16 reg_addr, ++ volatile u32 *reg_value) ++{ ++ *reg_value = readl((void __iomem *) ++ ((unsigned long)edma->ess_hw_addr + reg_addr)); ++} ++ ++static int ess_reset(struct edma_common_info *edma) ++{ ++ struct device_node *switch_node = NULL; ++ struct reset_control *ess_rst; ++ u32 regval; ++ ++ switch_node = of_find_node_by_name(NULL, "ess-switch"); ++ if (!switch_node) { ++ pr_err("switch-node not found\n"); ++ return -EINVAL; ++ } ++ ++ ess_rst = of_reset_control_get(switch_node, "ess_rst"); ++ of_node_put(switch_node); ++ ++ if (IS_ERR(ess_rst)) { ++ pr_err("failed to find ess_rst!\n"); ++ return -ENOENT; ++ } ++ ++ reset_control_assert(ess_rst); ++ msleep(10); ++ reset_control_deassert(ess_rst); ++ msleep(100); ++ reset_control_put(ess_rst); ++ ++ /* Enable only port 5 <--> port 0 ++ * bits 0:6 bitmap of ports it can fwd to */ ++#define SET_PORT_BMP(r,v) \ ++ ess_read_reg(edma, r, ®val); \ ++ ess_write_reg(edma, r, ((regval & ~0x3F) | v)); ++ ++ SET_PORT_BMP(ESS_PORT0_LOOKUP_CTRL,0x20); ++ SET_PORT_BMP(ESS_PORT1_LOOKUP_CTRL,0x00); ++ SET_PORT_BMP(ESS_PORT2_LOOKUP_CTRL,0x00); ++ SET_PORT_BMP(ESS_PORT3_LOOKUP_CTRL,0x00); ++ SET_PORT_BMP(ESS_PORT4_LOOKUP_CTRL,0x00); ++ SET_PORT_BMP(ESS_PORT5_LOOKUP_CTRL,0x01); ++ ess_write_reg(edma, ESS_RGMII_CTRL, 0x400); ++ ess_write_reg(edma, ESS_PORT0_STATUS, ESS_PORT_1G_FDX); ++ ess_write_reg(edma, ESS_PORT5_STATUS, ESS_PORT_1G_FDX); ++ ess_write_reg(edma, ESS_PORT0_HEADER_CTRL, 0); ++#undef SET_PORT_BMP ++ ++ /* forward multicast and broadcast frames to CPU */ ++ ess_write_reg(edma, ESS_FWD_CTRL1, ++ (ESS_PORTS_ALL << ESS_FWD_CTRL1_UC_FLOOD_S) | ++ (ESS_PORTS_ALL << ESS_FWD_CTRL1_MC_FLOOD_S) | ++ (ESS_PORTS_ALL << ESS_FWD_CTRL1_BC_FLOOD_S)); ++ ++ return 0; ++} ++ ++void ess_set_port_status_speed(struct edma_common_info *edma, ++ struct phy_device *phydev, uint8_t port_id) ++{ ++ uint16_t reg_off = ESS_PORT0_STATUS + (4 * port_id); ++ uint32_t reg_val = 0; ++ ++ ess_read_reg(edma, reg_off, ®_val); ++ ++ /* reset the speed bits [0:1] */ ++ reg_val &= ~ESS_PORT_STATUS_SPEED_INV; ++ ++ /* set the new speed */ ++ switch(phydev->speed) { ++ case SPEED_1000: reg_val |= ESS_PORT_STATUS_SPEED_1000; break; ++ case SPEED_100: reg_val |= ESS_PORT_STATUS_SPEED_100; break; ++ case SPEED_10: reg_val |= ESS_PORT_STATUS_SPEED_10; break; ++ default: reg_val |= ESS_PORT_STATUS_SPEED_INV; break; ++ } ++ ++ /* check full/half duplex */ ++ if (phydev->duplex) { ++ reg_val |= ESS_PORT_STATUS_DUPLEX_MODE; ++ } else { ++ reg_val &= ~ESS_PORT_STATUS_DUPLEX_MODE; ++ } ++ ++ ess_write_reg(edma, reg_off, reg_val); ++} ++ ++/* ++ * edma_change_tx_coalesce() + * change tx interrupt moderation timer + */ + void edma_change_tx_coalesce(int usecs) +@@ -551,6 +652,31 @@ static struct ctl_table edma_table[] = { + {} + }; + ++static int ess_parse(struct edma_common_info *edma) ++{ ++ struct device_node *switch_node; ++ int ret = -EINVAL; ++ ++ switch_node = of_find_node_by_name(NULL, "ess-switch"); ++ if (!switch_node) { ++ pr_err("cannot find ess-switch node\n"); ++ goto out; ++ } ++ ++ edma->ess_hw_addr = of_io_request_and_map(switch_node, ++ 0, KBUILD_MODNAME); ++ if (!edma->ess_hw_addr) { ++ pr_err("%s ioremap fail.", __func__); ++ goto out; ++ } ++ ++ edma->ess_clk = of_clk_get_by_name(switch_node, "ess_clk"); ++ ret = clk_prepare_enable(edma->ess_clk); ++out: ++ of_node_put(switch_node); ++ return ret; ++} ++ + /* edma_axi_netdev_ops + * Describe the operations supported by registered netdevices + * +@@ -786,6 +912,17 @@ static int edma_axi_probe(struct platfor + miibus = mdio_data->mii_bus; + } + ++ if (of_property_read_bool(np, "qcom,single-phy") && ++ edma_cinfo->num_gmac == 1) { ++ err = ess_parse(edma_cinfo); ++ if (!err) ++ err = ess_reset(edma_cinfo); ++ if (err) ++ goto err_single_phy_init; ++ else ++ edma_cinfo->is_single_phy = true; ++ } ++ + for_each_available_child_of_node(np, pnp) { + const char *mac_addr; + +@@ -1074,11 +1211,15 @@ static int edma_axi_probe(struct platfor + + for (i = 0; i < edma_cinfo->num_gmac; i++) { + if (adapter[i]->poll_required) { ++ int phy_mode = of_get_phy_mode(np); ++ ++ if (phy_mode < 0) ++ phy_mode = PHY_INTERFACE_MODE_SGMII; + adapter[i]->phydev = + phy_connect(edma_netdev[i], + (const char *)adapter[i]->phy_id, + &edma_adjust_link, +- PHY_INTERFACE_MODE_SGMII); ++ phy_mode); + if (IS_ERR(adapter[i]->phydev)) { + dev_dbg(&pdev->dev, "PHY attach FAIL"); + err = -EIO; +@@ -1125,6 +1266,9 @@ err_rmap_alloc_fail: + for (i = 0; i < edma_cinfo->num_gmac; i++) + unregister_netdev(edma_netdev[i]); + err_register: ++err_single_phy_init: ++ iounmap(edma_cinfo->ess_hw_addr); ++ clk_disable_unprepare(edma_cinfo->ess_clk); + err_mdiobus_init_fail: + edma_free_rx_rings(edma_cinfo); + err_rx_rinit: +@@ -1185,6 +1329,8 @@ static int edma_axi_remove(struct platfo + del_timer_sync(&edma_stats_timer); + edma_free_irqs(adapter); + unregister_net_sysctl_table(edma_cinfo->edma_ctl_table_hdr); ++ iounmap(edma_cinfo->ess_hw_addr); ++ clk_disable_unprepare(edma_cinfo->ess_clk); + edma_free_tx_resources(edma_cinfo); + edma_free_rx_resources(edma_cinfo); + edma_free_tx_rings(edma_cinfo); +--- a/drivers/net/ethernet/qualcomm/essedma/edma.c ++++ b/drivers/net/ethernet/qualcomm/essedma/edma.c +@@ -161,8 +161,10 @@ static void edma_configure_rx(struct edm + /* Set Rx FIFO threshold to start to DMA data to host */ + rxq_ctrl_data = EDMA_FIFO_THRESH_128_BYTE; + +- /* Set RX remove vlan bit */ +- rxq_ctrl_data |= EDMA_RXQ_CTRL_RMV_VLAN; ++ if (!edma_cinfo->is_single_phy) { ++ /* Set RX remove vlan bit */ ++ rxq_ctrl_data |= EDMA_RXQ_CTRL_RMV_VLAN; ++ } + + edma_write_reg(EDMA_REG_RXQ_CTRL, rxq_ctrl_data); + } +@@ -1295,6 +1297,10 @@ void edma_adjust_link(struct net_device + if (status == __EDMA_LINKUP && adapter->link_state == __EDMA_LINKDOWN) { + dev_info(&adapter->pdev->dev, "%s: GMAC Link is up with phy_speed=%d\n", netdev->name, phydev->speed); + adapter->link_state = __EDMA_LINKUP; ++ if (adapter->edma_cinfo->is_single_phy) { ++ ess_set_port_status_speed(adapter->edma_cinfo, phydev, ++ ffs(adapter->dp_bitmap) - 1); ++ } + netif_carrier_on(netdev); + if (netif_running(netdev)) + netif_tx_wake_all_queues(netdev); +@@ -1388,10 +1394,12 @@ netdev_tx_t edma_xmit(struct sk_buff *sk + } + + /* Check and mark VLAN tag offload */ +- if (skb_vlan_tag_present(skb)) +- flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_FLAG; +- else if (adapter->default_vlan_tag) +- flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_DEFAULT_FLAG; ++ if (!adapter->edma_cinfo->is_single_phy) { ++ if (unlikely(skb_vlan_tag_present(skb))) ++ flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_FLAG; ++ else if (adapter->default_vlan_tag) ++ flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_DEFAULT_FLAG; ++ } + + /* Check and mark checksum offload */ + if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) +--- a/drivers/net/ethernet/qualcomm/essedma/edma.h ++++ b/drivers/net/ethernet/qualcomm/essedma/edma.h +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -331,6 +332,10 @@ struct edma_common_info { + struct edma_hw hw; /* edma hw specific structure */ + struct edma_per_cpu_queues_info edma_percpu_info[CONFIG_NR_CPUS]; /* per cpu information */ + spinlock_t stats_lock; /* protect edma stats area for updation */ ++ ++ bool is_single_phy; ++ void __iomem *ess_hw_addr; ++ struct clk *ess_clk; + }; + + /* transimit packet descriptor (tpd) ring */ +@@ -443,4 +448,6 @@ void edma_change_tx_coalesce(int usecs); + void edma_change_rx_coalesce(int usecs); + void edma_get_tx_rx_coalesce(u32 *reg_val); + void edma_clear_irq_status(void); ++void ess_set_port_status_speed(struct edma_common_info *edma_cinfo, ++ struct phy_device *phydev, uint8_t port_id); + #endif /* _EDMA_H_ */ +--- a/drivers/net/ethernet/qualcomm/essedma/ess_edma.h ++++ b/drivers/net/ethernet/qualcomm/essedma/ess_edma.h +@@ -329,4 +329,61 @@ struct edma_hw; + #define EDMA_RRD_PRIORITY_MASK 0x7 + #define EDMA_RRD_PORT_TYPE_SHIFT 7 + #define EDMA_RRD_PORT_TYPE_MASK 0x1F ++ ++#define ESS_RGMII_CTRL 0x0004 ++ ++/* Port status registers */ ++#define ESS_PORT0_STATUS 0x007C ++#define ESS_PORT1_STATUS 0x0080 ++#define ESS_PORT2_STATUS 0x0084 ++#define ESS_PORT3_STATUS 0x0088 ++#define ESS_PORT4_STATUS 0x008C ++#define ESS_PORT5_STATUS 0x0090 ++ ++#define ESS_PORT_STATUS_HDX_FLOW_CTL 0x80 ++#define ESS_PORT_STATUS_DUPLEX_MODE 0x40 ++#define ESS_PORT_STATUS_RX_FLOW_EN 0x20 ++#define ESS_PORT_STATUS_TX_FLOW_EN 0x10 ++#define ESS_PORT_STATUS_RX_MAC_EN 0x08 ++#define ESS_PORT_STATUS_TX_MAC_EN 0x04 ++#define ESS_PORT_STATUS_SPEED_INV 0x03 ++#define ESS_PORT_STATUS_SPEED_1000 0x02 ++#define ESS_PORT_STATUS_SPEED_100 0x01 ++#define ESS_PORT_STATUS_SPEED_10 0x00 ++ ++#define ESS_PORT_1G_FDX (ESS_PORT_STATUS_DUPLEX_MODE | ESS_PORT_STATUS_RX_FLOW_EN | \ ++ ESS_PORT_STATUS_TX_FLOW_EN | ESS_PORT_STATUS_RX_MAC_EN | \ ++ ESS_PORT_STATUS_TX_MAC_EN | ESS_PORT_STATUS_SPEED_1000) ++ ++#define PHY_STATUS_REG 0x11 ++#define PHY_STATUS_SPEED 0xC000 ++#define PHY_STATUS_SPEED_SHIFT 14 ++#define PHY_STATUS_DUPLEX 0x2000 ++#define PHY_STATUS_DUPLEX_SHIFT 13 ++#define PHY_STATUS_SPEED_DUPLEX_RESOLVED 0x0800 ++#define PHY_STATUS_CARRIER 0x0400 ++#define PHY_STATUS_CARRIER_SHIFT 10 ++ ++/* Port lookup control registers */ ++#define ESS_PORT0_LOOKUP_CTRL 0x0660 ++#define ESS_PORT1_LOOKUP_CTRL 0x066C ++#define ESS_PORT2_LOOKUP_CTRL 0x0678 ++#define ESS_PORT3_LOOKUP_CTRL 0x0684 ++#define ESS_PORT4_LOOKUP_CTRL 0x0690 ++#define ESS_PORT5_LOOKUP_CTRL 0x069C ++ ++#define ESS_PORT0_HEADER_CTRL 0x009C ++ ++#define ESS_PORTS_ALL 0x3f ++ ++#define ESS_FWD_CTRL1 0x0624 ++#define ESS_FWD_CTRL1_UC_FLOOD BITS(0, 7) ++#define ESS_FWD_CTRL1_UC_FLOOD_S 0 ++#define ESS_FWD_CTRL1_MC_FLOOD BITS(8, 7) ++#define ESS_FWD_CTRL1_MC_FLOOD_S 8 ++#define ESS_FWD_CTRL1_BC_FLOOD BITS(16, 7) ++#define ESS_FWD_CTRL1_BC_FLOOD_S 16 ++#define ESS_FWD_CTRL1_IGMP BITS(24, 7) ++#define ESS_FWD_CTRL1_IGMP_S 24 ++ + #endif /* _ESS_EDMA_H_ */ diff --git a/target/linux/ipq40xx/patches-4.14/713-0001-essedma-fixup-ethernet-driver-rx-bug.patch b/target/linux/ipq40xx/patches-4.14/713-0001-essedma-fixup-ethernet-driver-rx-bug.patch new file mode 100644 index 000000000..75267b688 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/713-0001-essedma-fixup-ethernet-driver-rx-bug.patch @@ -0,0 +1,144 @@ +From 0bcfbe3c613d6ed8044404bc1cc3c29ff961d89c Mon Sep 17 00:00:00 2001 +From: Chen Minqiang +Date: Thu, 15 Mar 2018 04:59:57 +0800 +Subject: [PATCH 1/2] essedma: fixup ethernet driver rx bug + + - modify the error rx ring full conditions + - in rare cases, out of memory allocation failure causes the receive queues stop + we use the timer to re-alloc rx rings under these circumstances + +Signed-off-by: Chen Minqiang +--- + drivers/net/ethernet/qualcomm/essedma/edma.c | 51 ++++++++++++++++++++++-- + drivers/net/ethernet/qualcomm/essedma/edma.h | 3 ++ + drivers/net/ethernet/qualcomm/essedma/edma_axi.c | 8 ++++ + 3 files changed, 58 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/qualcomm/essedma/edma.c b/drivers/net/ethernet/qualcomm/essedma/edma.c +index fecc0ba..3f1da93 100644 +--- a/drivers/net/ethernet/qualcomm/essedma/edma.c ++++ b/drivers/net/ethernet/qualcomm/essedma/edma.c +@@ -530,6 +530,47 @@ static int edma_rx_complete_paged(struct sk_buff *skb, u16 num_rfds, u16 length, + return sw_next_to_clean; + } + ++static int edma_rfd_desc_unused(struct edma_rfd_desc_ring *erdr) ++{ ++ if (erdr->sw_next_to_clean > erdr->sw_next_to_fill) ++ return erdr->sw_next_to_clean - erdr->sw_next_to_fill - 1; ++ return erdr->count + erdr->sw_next_to_clean - erdr->sw_next_to_fill - 1; ++} ++ ++void edma_rx_realloc(unsigned long data) ++{ ++ struct edma_per_cpu_queues_info *edma_percpu_info = (struct edma_per_cpu_queues_info *)data; ++ struct edma_common_info *edma_cinfo = edma_percpu_info->edma_cinfo; ++ s32 status = edma_percpu_info->rx_realloc_status; ++ ++ while (status) { ++ int queue_id; ++ int ret_count; ++ struct edma_rfd_desc_ring *erdr; ++ ++ queue_id = ffs(status) - 1; ++ erdr = edma_cinfo->rfd_ring[queue_id]; ++ ret_count = edma_alloc_rx_buf(edma_cinfo, erdr, edma_rfd_desc_unused(erdr), queue_id); ++ if (ret_count == 0) { ++ edma_percpu_info->rx_realloc_status &= ~(1 << queue_id); ++ } ++ status &= ~(1 << queue_id); ++ } ++ ++ if (edma_percpu_info->rx_realloc_status) { ++ mod_timer(&edma_percpu_info->rx_realloc_timer, jiffies + HZ); ++ } ++} ++ ++static inline void edma_realloc_timer_start(struct napi_struct *napi, int queue_id) ++{ ++ struct edma_per_cpu_queues_info *edma_percpu_info = container_of(napi, ++ struct edma_per_cpu_queues_info, napi); ++ ++ edma_percpu_info->rx_realloc_status |= (1 << queue_id); ++ mod_timer(&edma_percpu_info->rx_realloc_timer, jiffies + 5 * HZ); /* restart alloc in 5 secs */ ++} ++ + /* + * edma_rx_complete() + * Main api called from the poll function to process rx packets. +@@ -754,10 +795,12 @@ static void edma_rx_complete(struct edma_common_info *edma_cinfo, + erdr->sw_next_to_clean = sw_next_to_clean; + + /* Refill here in case refill threshold wasn't reached */ +- if (likely(cleaned_count)) { +- ret_count = edma_alloc_rx_buf(edma_cinfo, erdr, cleaned_count, queue_id); +- if (ret_count) ++ if (edma_rfd_desc_unused(erdr)) { ++ ret_count = edma_alloc_rx_buf(edma_cinfo, erdr, edma_rfd_desc_unused(erdr), queue_id); ++ if (ret_count) { + dev_dbg(&pdev->dev, "Not all buffers was reallocated"); ++ edma_realloc_timer_start(napi, queue_id); ++ } + edma_write_reg(EDMA_REG_RX_SW_CONS_IDX_Q(queue_id), + erdr->sw_next_to_clean); + } +@@ -1801,7 +1844,7 @@ int edma_configure(struct edma_common_info *edma_cinfo) + /* Allocate the RX buffer */ + for (i = 0, j = 0; i < edma_cinfo->num_rx_queues; i++) { + struct edma_rfd_desc_ring *ring = edma_cinfo->rfd_ring[j]; +- ret_count = edma_alloc_rx_buf(edma_cinfo, ring, ring->count, j); ++ ret_count = edma_alloc_rx_buf(edma_cinfo, ring, edma_rfd_desc_unused(ring), j); + if (ret_count) { + dev_dbg(&edma_cinfo->pdev->dev, "not all rx buffers allocated\n"); + } +diff --git a/drivers/net/ethernet/qualcomm/essedma/edma.h b/drivers/net/ethernet/qualcomm/essedma/edma.h +index 5d6dc73..29c8379 100644 +--- a/drivers/net/ethernet/qualcomm/essedma/edma.h ++++ b/drivers/net/ethernet/qualcomm/essedma/edma.h +@@ -304,6 +304,8 @@ struct edma_per_cpu_queues_info { + u32 tx_start; /* tx queue start */ + u32 rx_start; /* rx queue start */ + struct edma_common_info *edma_cinfo; /* edma common info */ ++ u32 rx_realloc_status; ++ struct timer_list rx_realloc_timer; + }; + + /* edma specific common info */ +@@ -448,6 +450,7 @@ void edma_change_tx_coalesce(int usecs); + void edma_change_rx_coalesce(int usecs); + void edma_get_tx_rx_coalesce(u32 *reg_val); + void edma_clear_irq_status(void); ++void edma_rx_realloc(unsigned long data); + void ess_set_port_status_speed(struct edma_common_info *edma_cinfo, + struct phy_device *phydev, uint8_t port_id); + #endif /* _EDMA_H_ */ +diff --git a/drivers/net/ethernet/qualcomm/essedma/edma_axi.c b/drivers/net/ethernet/qualcomm/essedma/edma_axi.c +index 81fc1e1..d9f8b52 100644 +--- a/drivers/net/ethernet/qualcomm/essedma/edma_axi.c ++++ b/drivers/net/ethernet/qualcomm/essedma/edma_axi.c +@@ -1131,6 +1131,11 @@ static int edma_axi_probe(struct platform_device *pdev) + edma_cinfo->edma_percpu_info[i].rx_status = 0; + edma_cinfo->edma_percpu_info[i].edma_cinfo = edma_cinfo; + ++ edma_cinfo->edma_percpu_info[i].rx_realloc_status = 0; ++ init_timer(&edma_cinfo->edma_percpu_info[i].rx_realloc_timer); ++ edma_cinfo->edma_percpu_info[i].rx_realloc_timer.function = edma_rx_realloc; ++ edma_cinfo->edma_percpu_info[i].rx_realloc_timer.data = (unsigned long)&edma_cinfo->edma_percpu_info[i]; ++ + /* Request irq per core */ + for (j = edma_cinfo->edma_percpu_info[i].tx_start; + j < tx_start[i] + 4; j++) { +@@ -1259,7 +1264,10 @@ err_configure: + err_rmap_add_fail: + edma_free_irqs(adapter[0]); + for (i = 0; i < CONFIG_NR_CPUS; i++) ++ { + napi_disable(&edma_cinfo->edma_percpu_info[i].napi); ++ del_timer_sync(&edma_cinfo->edma_percpu_info[i].rx_realloc_timer); ++ } + err_reset: + err_unregister_sysctl_tbl: + err_rmap_alloc_fail: +-- +2.7.4 + diff --git a/target/linux/ipq40xx/patches-4.14/713-0002-essedma-refine-txq-to-be-adaptive-of-cpus-and-netdev.patch b/target/linux/ipq40xx/patches-4.14/713-0002-essedma-refine-txq-to-be-adaptive-of-cpus-and-netdev.patch new file mode 100644 index 000000000..6c6ef84ab --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/713-0002-essedma-refine-txq-to-be-adaptive-of-cpus-and-netdev.patch @@ -0,0 +1,223 @@ +From 7be0cb35513b07bf74d93d052d57b12e2c654b43 Mon Sep 17 00:00:00 2001 +From: Chen Minqiang +Date: Thu, 15 Mar 2018 05:04:37 +0800 +Subject: [PATCH 2/2] essedma: refine txq to be adaptive of cpus and netdev + + - use 4 queue for each cpu if only 1 netdev + - use all 16 txqueue if only 1 netdev + +Signed-off-by: Chen Minqiang +--- + drivers/net/ethernet/qualcomm/essedma/edma.c | 22 +++++-------- + drivers/net/ethernet/qualcomm/essedma/edma.h | 5 +-- + drivers/net/ethernet/qualcomm/essedma/edma_axi.c | 40 ++++++++++++++---------- + 3 files changed, 35 insertions(+), 32 deletions(-) + +diff --git a/drivers/net/ethernet/qualcomm/essedma/edma.c b/drivers/net/ethernet/qualcomm/essedma/edma.c +index 3f1da93..05f9ce9 100644 +--- a/drivers/net/ethernet/qualcomm/essedma/edma.c ++++ b/drivers/net/ethernet/qualcomm/essedma/edma.c +@@ -22,14 +22,6 @@ extern struct net_device *edma_netdev[EDMA_MAX_PORTID_SUPPORTED]; + bool edma_stp_rstp; + u16 edma_ath_eth_type; + +-/* edma_skb_priority_offset() +- * get edma skb priority +- */ +-static unsigned int edma_skb_priority_offset(struct sk_buff *skb) +-{ +- return (skb->priority >> 2) & 1; +-} +- + /* edma_alloc_tx_ring() + * Allocate Tx descriptors ring + */ +@@ -1042,13 +1034,14 @@ static inline u16 edma_tpd_available(struct edma_common_info *edma_cinfo, + /* edma_tx_queue_get() + * Get the starting number of the queue + */ +-static inline int edma_tx_queue_get(struct edma_adapter *adapter, ++static inline int edma_tx_queue_get(struct edma_common_info *edma_cinfo, struct edma_adapter *adapter, + struct sk_buff *skb, int txq_id) + { + /* skb->priority is used as an index to skb priority table + * and based on packet priority, correspong queue is assigned. ++ * FIXME we just simple use jiffies for time base balance + */ +- return adapter->tx_start_offset[txq_id] + edma_skb_priority_offset(skb); ++ return adapter->tx_start_offset[txq_id] + (jiffies % edma_cinfo->num_txq_per_core_netdev); + } + + /* edma_tx_update_hw_idx() +@@ -1417,8 +1410,9 @@ netdev_tx_t edma_xmit(struct sk_buff *skb, + } + + /* this will be one of the 4 TX queues exposed to linux kernel */ +- txq_id = skb_get_queue_mapping(skb); +- queue_id = edma_tx_queue_get(adapter, skb, txq_id); ++ /* XXX what if num_online_cpus() > EDMA_CPU_CORES_SUPPORTED */ ++ txq_id = smp_processor_id() % EDMA_CPU_CORES_SUPPORTED; ++ queue_id = edma_tx_queue_get(edma_cinfo, adapter, skb, txq_id); + etdr = edma_cinfo->tpd_ring[queue_id]; + nq = netdev_get_tx_queue(net_dev, txq_id); + +@@ -1899,8 +1893,8 @@ void edma_free_irqs(struct edma_adapter *adapter) + int i, j; + int k = ((edma_cinfo->num_rx_queues == 4) ? 1 : 2); + +- for (i = 0; i < CONFIG_NR_CPUS; i++) { +- for (j = edma_cinfo->edma_percpu_info[i].tx_start; j < (edma_cinfo->edma_percpu_info[i].tx_start + 4); j++) ++ for (i = 0; i < num_online_cpus() && i < EDMA_CPU_CORES_SUPPORTED; i++) { ++ for (j = edma_cinfo->edma_percpu_info[i].tx_start; j < (edma_cinfo->edma_percpu_info[i].tx_start + edma_cinfo->num_txq_per_core); j++) + free_irq(edma_cinfo->tx_irq[j], &edma_cinfo->edma_percpu_info[i]); + + for (j = edma_cinfo->edma_percpu_info[i].rx_start; j < (edma_cinfo->edma_percpu_info[i].rx_start + k); j++) +diff --git a/drivers/net/ethernet/qualcomm/essedma/edma.h b/drivers/net/ethernet/qualcomm/essedma/edma.h +index 29c8379..2ba43e0 100644 +--- a/drivers/net/ethernet/qualcomm/essedma/edma.h ++++ b/drivers/net/ethernet/qualcomm/essedma/edma.h +@@ -325,6 +325,7 @@ struct edma_common_info { + u32 from_cpu; /* from CPU TPD field */ + u32 num_rxq_per_core; /* Rx queues per core */ + u32 num_txq_per_core; /* Tx queues per core */ ++ u32 num_txq_per_core_netdev; /* Tx queues per core per netdev */ + u16 tx_ring_count; /* Tx ring count */ + u16 rx_ring_count; /* Rx ring*/ + u16 rx_head_buffer_len; /* rx buffer length */ +@@ -332,7 +333,7 @@ struct edma_common_info { + u32 page_mode; /* Jumbo frame supported flag */ + u32 fraglist_mode; /* fraglist supported flag */ + struct edma_hw hw; /* edma hw specific structure */ +- struct edma_per_cpu_queues_info edma_percpu_info[CONFIG_NR_CPUS]; /* per cpu information */ ++ struct edma_per_cpu_queues_info edma_percpu_info[EDMA_CPU_CORES_SUPPORTED]; /* per cpu information */ + spinlock_t stats_lock; /* protect edma stats area for updation */ + + bool is_single_phy; +@@ -401,7 +402,7 @@ struct edma_adapter { + u32 link_state; /* phy link state */ + u32 phy_mdio_addr; /* PHY device address on MII interface */ + u32 poll_required; /* check if link polling is required */ +- u32 tx_start_offset[CONFIG_NR_CPUS]; /* tx queue start */ ++ u32 tx_start_offset[EDMA_CPU_CORES_SUPPORTED]; /* tx queue start */ + u32 default_vlan_tag; /* vlan tag */ + u32 dp_bitmap; + uint8_t phy_id[MII_BUS_ID_SIZE + 3]; +diff --git a/drivers/net/ethernet/qualcomm/essedma/edma_axi.c b/drivers/net/ethernet/qualcomm/essedma/edma_axi.c +index d9f8b52..5824680 100644 +--- a/drivers/net/ethernet/qualcomm/essedma/edma_axi.c ++++ b/drivers/net/ethernet/qualcomm/essedma/edma_axi.c +@@ -721,11 +721,7 @@ static int edma_axi_probe(struct platform_device *pdev) + int i, j, k, err = 0; + int portid_bmp; + int idx = 0, idx_mac = 0; +- +- if (CONFIG_NR_CPUS != EDMA_CPU_CORES_SUPPORTED) { +- dev_err(&pdev->dev, "Invalid CPU Cores\n"); +- return -EINVAL; +- } ++ int netdev_group = 2; + + if ((num_rxq != 4) && (num_rxq != 8)) { + dev_err(&pdev->dev, "Invalid RX queue, edma probe failed\n"); +@@ -749,7 +745,7 @@ static int edma_axi_probe(struct platform_device *pdev) + /* Initialize the netdev array before allocation + * to avoid double free + */ +- for (i = 0 ; i < edma_cinfo->num_gmac ; i++) ++ for (i = 0 ; i < EDMA_MAX_PORTID_SUPPORTED; i++) + edma_netdev[i] = NULL; + + for (i = 0 ; i < edma_cinfo->num_gmac ; i++) { +@@ -770,8 +766,11 @@ static int edma_axi_probe(struct platform_device *pdev) + + /* Fill ring details */ + edma_cinfo->num_tx_queues = EDMA_MAX_TRANSMIT_QUEUE; +- edma_cinfo->num_txq_per_core = (EDMA_MAX_TRANSMIT_QUEUE / 4); ++ edma_cinfo->num_txq_per_core = (EDMA_MAX_TRANSMIT_QUEUE / num_online_cpus()); ++ edma_cinfo->num_txq_per_core_netdev = (EDMA_MAX_TRANSMIT_QUEUE / netdev_group / num_online_cpus()); + edma_cinfo->tx_ring_count = EDMA_TX_RING_SIZE; ++ if (edma_cinfo->num_txq_per_core == 0) ++ edma_cinfo->num_txq_per_core = 1; + + /* Update num rx queues based on module parameter */ + edma_cinfo->num_rx_queues = num_rxq; +@@ -941,6 +940,13 @@ static int edma_axi_probe(struct platform_device *pdev) + idx_mac++; + } + ++ if (edma_cinfo->num_gmac == 1) { ++ netdev_group = 1; ++ edma_cinfo->num_txq_per_core_netdev = (EDMA_MAX_TRANSMIT_QUEUE / netdev_group / num_online_cpus()); ++ } ++ if (edma_cinfo->num_txq_per_core_netdev == 0) ++ edma_cinfo->num_txq_per_core_netdev = 1; ++ + /* Populate the adapter structure register the netdevice */ + for (i = 0; i < edma_cinfo->num_gmac; i++) { + int k, m; +@@ -948,17 +954,16 @@ static int edma_axi_probe(struct platform_device *pdev) + adapter[i] = netdev_priv(edma_netdev[i]); + adapter[i]->netdev = edma_netdev[i]; + adapter[i]->pdev = pdev; +- for (j = 0; j < CONFIG_NR_CPUS; j++) { +- m = i % 2; +- adapter[i]->tx_start_offset[j] = +- ((j << EDMA_TX_CPU_START_SHIFT) + (m << 1)); ++ for (j = 0; j < num_online_cpus() && j < EDMA_CPU_CORES_SUPPORTED; j++) { ++ m = i % netdev_group; ++ adapter[i]->tx_start_offset[j] = j * edma_cinfo->num_txq_per_core + m * edma_cinfo->num_txq_per_core_netdev; + /* Share the queues with available net-devices. + * For instance , with 5 net-devices + * eth0/eth2/eth4 will share q0,q1,q4,q5,q8,q9,q12,q13 + * and eth1/eth3 will get the remaining. + */ + for (k = adapter[i]->tx_start_offset[j]; k < +- (adapter[i]->tx_start_offset[j] + 2); k++) { ++ (adapter[i]->tx_start_offset[j] + edma_cinfo->num_txq_per_core_netdev); k++) { + if (edma_fill_netdev(edma_cinfo, k, i, j)) { + pr_err("Netdev overflow Error\n"); + goto err_register; +@@ -1111,9 +1116,12 @@ static int edma_axi_probe(struct platform_device *pdev) + /* populate per_core_info, do a napi_Add, request 16 TX irqs, + * 8 RX irqs, do a napi enable + */ +- for (i = 0; i < CONFIG_NR_CPUS; i++) { ++ for (i = 0; i < num_online_cpus() && i < EDMA_MAX_TRANSMIT_QUEUE; i++) { + u8 rx_start; + ++ tx_mask[i] = (0xFFFF >> (16 - edma_cinfo->num_txq_per_core)) << (i * edma_cinfo->num_txq_per_core); ++ tx_start[i] = i * edma_cinfo->num_txq_per_core; ++ + edma_cinfo->edma_percpu_info[i].napi.state = 0; + + netif_napi_add(edma_netdev[0], +@@ -1138,7 +1146,7 @@ static int edma_axi_probe(struct platform_device *pdev) + + /* Request irq per core */ + for (j = edma_cinfo->edma_percpu_info[i].tx_start; +- j < tx_start[i] + 4; j++) { ++ j < tx_start[i] + edma_cinfo->num_txq_per_core; j++) { + sprintf(&edma_tx_irq[j][0], "edma_eth_tx%d", j); + err = request_irq(edma_cinfo->tx_irq[j], + edma_interrupt, +@@ -1263,7 +1271,7 @@ err_configure: + #endif + err_rmap_add_fail: + edma_free_irqs(adapter[0]); +- for (i = 0; i < CONFIG_NR_CPUS; i++) ++ for (i = 0; i < num_online_cpus() && i < EDMA_CPU_CORES_SUPPORTED; i++) + { + napi_disable(&edma_cinfo->edma_percpu_info[i].napi); + del_timer_sync(&edma_cinfo->edma_percpu_info[i].rx_realloc_timer); +@@ -1314,7 +1322,7 @@ static int edma_axi_remove(struct platform_device *pdev) + unregister_netdev(edma_netdev[i]); + + edma_stop_rx_tx(hw); +- for (i = 0; i < CONFIG_NR_CPUS; i++) ++ for (i = 0; i < num_online_cpus() && i < EDMA_CPU_CORES_SUPPORTED; i++) + napi_disable(&edma_cinfo->edma_percpu_info[i].napi); + + edma_irq_disable(edma_cinfo); +-- +2.7.4 + diff --git a/target/linux/ipq40xx/patches-4.14/820-qcom-ipq4019-Add-IPQ4019-USB-HS-SS-PHY-drivers.patch b/target/linux/ipq40xx/patches-4.14/820-qcom-ipq4019-Add-IPQ4019-USB-HS-SS-PHY-drivers.patch new file mode 100644 index 000000000..47291fea0 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/820-qcom-ipq4019-Add-IPQ4019-USB-HS-SS-PHY-drivers.patch @@ -0,0 +1,429 @@ +From e73682ec4455c34f3f3edc7f40d90ed297521012 Mon Sep 17 00:00:00 2001 +From: Senthilkumar N L +Date: Tue, 6 Jan 2015 12:52:23 +0530 +Subject: [PATCH] qcom: ipq4019: Add IPQ4019 USB HS/SS PHY drivers + +These drivers handles control and configuration of the HS +and SS USB PHY transceivers. + +Signed-off-by: Senthilkumar N L +Signed-off-by: Christian Lamparter + +--- +Changed: + - replaced spaces with tabs + - remove emulation and host variables +--- + drivers/usb/phy/Kconfig | 11 ++ + drivers/usb/phy/Makefile | 2 + + drivers/usb/phy/phy-qca-baldur.c | 233 +++++++++++++++++++++++++++++++++++++++ + drivers/usb/phy/phy-qca-uniphy.c | 141 +++++++++++++++++++++++ + 4 files changed, 387 insertions(+) + create mode 100644 drivers/usb/phy/phy-qca-baldur.c + create mode 100644 drivers/usb/phy/phy-qca-uniphy.c + +--- a/drivers/usb/phy/Kconfig ++++ b/drivers/usb/phy/Kconfig +@@ -188,6 +188,17 @@ config USB_MXS_PHY + + MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x. + ++config USB_IPQ4019_PHY ++ tristate "IPQ4019 PHY wrappers support" ++ depends on (USB || USB_GADGET) && ARCH_QCOM ++ select USB_PHY ++ help ++ Enable this to support the USB PHY transceivers on QCA961x chips. ++ It handles PHY initialization, clock management required after ++ resetting the hardware and power management. ++ This driver is required even for peripheral only or host only ++ mode configurations. ++ + config USB_ULPI + bool "Generic ULPI Transceiver Driver" + depends on ARM || ARM64 +--- a/drivers/usb/phy/Makefile ++++ b/drivers/usb/phy/Makefile +@@ -21,6 +21,8 @@ obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio + obj-$(CONFIG_USB_ISP1301) += phy-isp1301.o + obj-$(CONFIG_USB_MSM_OTG) += phy-msm-usb.o + obj-$(CONFIG_USB_QCOM_8X16_PHY) += phy-qcom-8x16-usb.o ++obj-$(CONFIG_USB_IPQ4019_PHY) += phy-qca-baldur.o ++obj-$(CONFIG_USB_IPQ4019_PHY) += phy-qca-uniphy.o + obj-$(CONFIG_USB_MV_OTG) += phy-mv-usb.o + obj-$(CONFIG_USB_MXS_PHY) += phy-mxs-usb.o + obj-$(CONFIG_USB_ULPI) += phy-ulpi.o +--- /dev/null ++++ b/drivers/usb/phy/phy-qca-baldur.c +@@ -0,0 +1,233 @@ ++/* Copyright (c) 2015, The Linux Foundation. All rights reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/** ++ * USB Hardware registers ++ */ ++#define PHY_CTRL0_ADDR 0x000 ++#define PHY_CTRL1_ADDR 0x004 ++#define PHY_CTRL2_ADDR 0x008 ++#define PHY_CTRL3_ADDR 0x00C ++#define PHY_CTRL4_ADDR 0x010 ++#define PHY_MISC_ADDR 0x024 ++#define PHY_IPG_ADDR 0x030 ++ ++#define PHY_CTRL0_VAL 0xA4600015 ++#define PHY_CTRL1_VAL 0x09500000 ++#define PHY_CTRL2_VAL 0x00058180 ++#define PHY_CTRL3_VAL 0x6DB6DCD6 ++#define PHY_CTRL4_VAL 0x836DB6DB ++#define PHY_MISC_VAL 0x3803FB0C ++#define PHY_IPG_VAL 0x47323232 ++ ++#define USB30_HS_PHY_HOST_MODE (0x01 << 21) ++#define USB20_HS_PHY_HOST_MODE (0x01 << 5) ++ ++/* used to differentiate between USB3 HS and USB2 HS PHY */ ++struct qca_baldur_hs_data { ++ unsigned int usb3_hs_phy; ++ unsigned int phy_config_offset; ++}; ++ ++struct qca_baldur_hs_phy { ++ struct device *dev; ++ struct usb_phy phy; ++ ++ void __iomem *base; ++ void __iomem *qscratch_base; ++ ++ struct reset_control *por_rst; ++ struct reset_control *srif_rst; ++ ++ const struct qca_baldur_hs_data *data; ++}; ++ ++#define phy_to_dw_phy(x) container_of((x), struct qca_baldur_hs_phy, phy) ++ ++static int qca_baldur_phy_read(struct usb_phy *x, u32 reg) ++{ ++ struct qca_baldur_hs_phy *phy = phy_to_dw_phy(x); ++ ++ return readl(phy->base + reg); ++} ++ ++static int qca_baldur_phy_write(struct usb_phy *x, u32 val, u32 reg) ++{ ++ struct qca_baldur_hs_phy *phy = phy_to_dw_phy(x); ++ ++ writel(val, phy->base + reg); ++ return 0; ++} ++ ++static int qca_baldur_hs_phy_init(struct usb_phy *x) ++{ ++ struct qca_baldur_hs_phy *phy = phy_to_dw_phy(x); ++ ++ /* assert HS PHY POR reset */ ++ reset_control_assert(phy->por_rst); ++ msleep(10); ++ ++ /* assert HS PHY SRIF reset */ ++ reset_control_assert(phy->srif_rst); ++ msleep(10); ++ ++ /* deassert HS PHY SRIF reset and program HS PHY registers */ ++ reset_control_deassert(phy->srif_rst); ++ msleep(10); ++ ++ /* perform PHY register writes */ ++ writel(PHY_CTRL0_VAL, phy->base + PHY_CTRL0_ADDR); ++ writel(PHY_CTRL1_VAL, phy->base + PHY_CTRL1_ADDR); ++ writel(PHY_CTRL2_VAL, phy->base + PHY_CTRL2_ADDR); ++ writel(PHY_CTRL3_VAL, phy->base + PHY_CTRL3_ADDR); ++ writel(PHY_CTRL4_VAL, phy->base + PHY_CTRL4_ADDR); ++ writel(PHY_MISC_VAL, phy->base + PHY_MISC_ADDR); ++ writel(PHY_IPG_VAL, phy->base + PHY_IPG_ADDR); ++ ++ msleep(10); ++ ++ /* de-assert USB3 HS PHY POR reset */ ++ reset_control_deassert(phy->por_rst); ++ ++ return 0; ++} ++ ++static int qca_baldur_hs_get_resources(struct qca_baldur_hs_phy *phy) ++{ ++ struct platform_device *pdev = to_platform_device(phy->dev); ++ struct resource *res; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ phy->base = devm_ioremap_resource(phy->dev, res); ++ if (IS_ERR(phy->base)) ++ return PTR_ERR(phy->base); ++ ++ phy->por_rst = devm_reset_control_get(phy->dev, "por_rst"); ++ if (IS_ERR(phy->por_rst)) ++ return PTR_ERR(phy->por_rst); ++ ++ phy->srif_rst = devm_reset_control_get(phy->dev, "srif_rst"); ++ if (IS_ERR(phy->srif_rst)) ++ return PTR_ERR(phy->srif_rst); ++ ++ return 0; ++} ++ ++static void qca_baldur_hs_put_resources(struct qca_baldur_hs_phy *phy) ++{ ++ reset_control_assert(phy->srif_rst); ++ reset_control_assert(phy->por_rst); ++} ++ ++static int qca_baldur_hs_remove(struct platform_device *pdev) ++{ ++ struct qca_baldur_hs_phy *phy = platform_get_drvdata(pdev); ++ ++ usb_remove_phy(&phy->phy); ++ return 0; ++} ++ ++static void qca_baldur_hs_phy_shutdown(struct usb_phy *x) ++{ ++ struct qca_baldur_hs_phy *phy = phy_to_dw_phy(x); ++ ++ qca_baldur_hs_put_resources(phy); ++} ++ ++static struct usb_phy_io_ops qca_baldur_io_ops = { ++ .read = qca_baldur_phy_read, ++ .write = qca_baldur_phy_write, ++}; ++ ++static const struct qca_baldur_hs_data usb3_hs_data = { ++ .usb3_hs_phy = 1, ++ .phy_config_offset = USB30_HS_PHY_HOST_MODE, ++}; ++ ++static const struct qca_baldur_hs_data usb2_hs_data = { ++ .usb3_hs_phy = 0, ++ .phy_config_offset = USB20_HS_PHY_HOST_MODE, ++}; ++ ++static const struct of_device_id qca_baldur_hs_id_table[] = { ++ { .compatible = "qca,baldur-usb3-hsphy", .data = &usb3_hs_data }, ++ { .compatible = "qca,baldur-usb2-hsphy", .data = &usb2_hs_data }, ++ { /* Sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, qca_baldur_hs_id_table); ++ ++static int qca_baldur_hs_probe(struct platform_device *pdev) ++{ ++ const struct of_device_id *match; ++ struct qca_baldur_hs_phy *phy; ++ int err; ++ ++ match = of_match_device(qca_baldur_hs_id_table, &pdev->dev); ++ if (!match) ++ return -ENODEV; ++ ++ phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); ++ if (!phy) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, phy); ++ phy->dev = &pdev->dev; ++ ++ phy->data = match->data; ++ ++ err = qca_baldur_hs_get_resources(phy); ++ if (err < 0) { ++ dev_err(&pdev->dev, "failed to request resources: %d\n", err); ++ return err; ++ } ++ ++ phy->phy.dev = phy->dev; ++ phy->phy.label = "qca-baldur-hsphy"; ++ phy->phy.init = qca_baldur_hs_phy_init; ++ phy->phy.shutdown = qca_baldur_hs_phy_shutdown; ++ phy->phy.type = USB_PHY_TYPE_USB2; ++ phy->phy.io_ops = &qca_baldur_io_ops; ++ ++ err = usb_add_phy_dev(&phy->phy); ++ return err; ++} ++ ++static struct platform_driver qca_baldur_hs_driver = { ++ .probe = qca_baldur_hs_probe, ++ .remove = qca_baldur_hs_remove, ++ .driver = { ++ .name = "qca-baldur-hsphy", ++ .owner = THIS_MODULE, ++ .of_match_table = qca_baldur_hs_id_table, ++ }, ++}; ++ ++module_platform_driver(qca_baldur_hs_driver); ++ ++MODULE_ALIAS("platform:qca-baldur-hsphy"); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("USB3 QCA BALDUR HSPHY driver"); +--- /dev/null ++++ b/drivers/usb/phy/phy-qca-uniphy.c +@@ -0,0 +1,135 @@ ++/* Copyright (c) 2015, The Linux Foundation. All rights reserved. ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct qca_uni_ss_phy { ++ struct usb_phy phy; ++ struct device *dev; ++ ++ void __iomem *base; ++ ++ struct reset_control *por_rst; ++}; ++ ++#define phy_to_dw_phy(x) container_of((x), struct qca_uni_ss_phy, phy) ++ ++static void qca_uni_ss_phy_shutdown(struct usb_phy *x) ++{ ++ struct qca_uni_ss_phy *phy = phy_to_dw_phy(x); ++ ++ /* assert SS PHY POR reset */ ++ reset_control_assert(phy->por_rst); ++} ++ ++static int qca_uni_ss_phy_init(struct usb_phy *x) ++{ ++ struct qca_uni_ss_phy *phy = phy_to_dw_phy(x); ++ ++ /* assert SS PHY POR reset */ ++ reset_control_assert(phy->por_rst); ++ ++ msleep(20); ++ ++ /* deassert SS PHY POR reset */ ++ reset_control_deassert(phy->por_rst); ++ ++ return 0; ++} ++ ++static int qca_uni_ss_get_resources(struct platform_device *pdev, ++ struct qca_uni_ss_phy *phy) ++{ ++ struct resource *res; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ phy->base = devm_ioremap_resource(phy->dev, res); ++ if (IS_ERR(phy->base)) ++ return PTR_ERR(phy->base); ++ ++ phy->por_rst = devm_reset_control_get(phy->dev, "por_rst"); ++ if (IS_ERR(phy->por_rst)) ++ return PTR_ERR(phy->por_rst); ++ ++ return 0; ++} ++ ++static int qca_uni_ss_remove(struct platform_device *pdev) ++{ ++ struct qca_uni_ss_phy *phy = platform_get_drvdata(pdev); ++ ++ usb_remove_phy(&phy->phy); ++ return 0; ++} ++ ++static const struct of_device_id qca_uni_ss_id_table[] = { ++ { .compatible = "qca,uni-ssphy" }, ++ { /* Sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, qca_uni_ss_id_table); ++ ++static int qca_uni_ss_probe(struct platform_device *pdev) ++{ ++ struct qca_uni_ss_phy *phy; ++ int ret; ++ ++ phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); ++ if (!phy) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, phy); ++ phy->dev = &pdev->dev; ++ ++ ret = qca_uni_ss_get_resources(pdev, phy); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "failed to request resources: %d\n", ret); ++ return ret; ++ } ++ ++ phy->phy.dev = phy->dev; ++ phy->phy.label = "qca-uni-ssphy"; ++ phy->phy.init = qca_uni_ss_phy_init; ++ phy->phy.shutdown = qca_uni_ss_phy_shutdown; ++ phy->phy.type = USB_PHY_TYPE_USB3; ++ ++ ret = usb_add_phy_dev(&phy->phy); ++ return ret; ++} ++ ++static struct platform_driver qca_uni_ss_driver = { ++ .probe = qca_uni_ss_probe, ++ .remove = qca_uni_ss_remove, ++ .driver = { ++ .name = "qca-uni-ssphy", ++ .owner = THIS_MODULE, ++ .of_match_table = qca_uni_ss_id_table, ++ }, ++}; ++ ++module_platform_driver(qca_uni_ss_driver); ++ ++MODULE_ALIAS("platform:qca-uni-ssphy"); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("USB3 QCA UNI SSPHY driver"); diff --git a/target/linux/ipq40xx/patches-4.14/830-usb-dwc3-register-qca-ipq4019-dwc3-in-dwc3-of-simple.patch b/target/linux/ipq40xx/patches-4.14/830-usb-dwc3-register-qca-ipq4019-dwc3-in-dwc3-of-simple.patch new file mode 100644 index 000000000..e9b33446d --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/830-usb-dwc3-register-qca-ipq4019-dwc3-in-dwc3-of-simple.patch @@ -0,0 +1,25 @@ +From 08c18ab774368feb610d1eb952957bb1bb35129f Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sat, 19 Nov 2016 00:52:35 +0100 +Subject: [PATCH 37/38] usb: dwc3: register qca,ipq4019-dwc3 in dwc3-of-simple + +For host mode, the dwc3 found in the IPQ4019 can be driven +by the dwc3-of-simple module. It will get more tricky for +OTG since they'll need to enable VBUS and reconfigure the +registers. + +Signed-off-by: Christian Lamparter +--- + drivers/usb/dwc3/dwc3-of-simple.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/usb/dwc3/dwc3-of-simple.c ++++ b/drivers/usb/dwc3/dwc3-of-simple.c +@@ -176,6 +176,7 @@ static const struct dev_pm_ops dwc3_of_s + + static const struct of_device_id of_dwc3_simple_match[] = { + { .compatible = "qcom,dwc3" }, ++ { .compatible = "qca,ipq4019-dwc3" }, + { .compatible = "rockchip,rk3399-dwc3" }, + { .compatible = "xlnx,zynqmp-dwc3" }, + { .compatible = "cavium,octeon-7130-usb-uctl" }, diff --git a/target/linux/ipq40xx/patches-4.14/850-soc-add-qualcomm-syscon.patch b/target/linux/ipq40xx/patches-4.14/850-soc-add-qualcomm-syscon.patch new file mode 100644 index 000000000..59e277c34 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/850-soc-add-qualcomm-syscon.patch @@ -0,0 +1,177 @@ +From: Christian Lamparter +Subject: SoC: add qualcomm syscon +--- a/drivers/soc/qcom/Makefile ++++ b/drivers/soc/qcom/Makefile +@@ -9,3 +9,4 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_st + obj-$(CONFIG_QCOM_SMP2P) += smp2p.o + obj-$(CONFIG_QCOM_SMSM) += smsm.o + obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o ++obj-$(CONFIG_QCOM_TCSR) += qcom_tcsr.o +--- a/drivers/soc/qcom/Kconfig ++++ b/drivers/soc/qcom/Kconfig +@@ -78,6 +78,13 @@ config QCOM_SMSM + Say yes here to support the Qualcomm Shared Memory State Machine. + The state machine is represented by bits in shared memory. + ++config QCOM_TCSR ++ tristate "QCOM Top Control and Status Registers" ++ depends on ARCH_QCOM ++ help ++ Say y here to enable TCSR support. The TCSR provides control ++ functions for various peripherals. ++ + config QCOM_WCNSS_CTRL + tristate "Qualcomm WCNSS control driver" + depends on ARCH_QCOM +--- /dev/null ++++ b/drivers/soc/qcom/qcom_tcsr.c +@@ -0,0 +1,98 @@ ++/* ++ * Copyright (c) 2014, The Linux foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License rev 2 and ++ * only rev 2 as published by the free Software foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or fITNESS fOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TCSR_USB_PORT_SEL 0xb0 ++#define TCSR_USB_HSPHY_CONFIG 0xC ++ ++#define TCSR_ESS_INTERFACE_SEL_OFFSET 0x0 ++#define TCSR_ESS_INTERFACE_SEL_MASK 0xf ++ ++#define TCSR_WIFI0_GLB_CFG_OFFSET 0x0 ++#define TCSR_WIFI1_GLB_CFG_OFFSET 0x4 ++#define TCSR_PNOC_SNOC_MEMTYPE_M0_M2 0x4 ++ ++static int tcsr_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ const struct device_node *node = pdev->dev.of_node; ++ void __iomem *base; ++ u32 val; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ if (!of_property_read_u32(node, "qcom,usb-ctrl-select", &val)) { ++ dev_err(&pdev->dev, "setting usb port select = %d\n", val); ++ writel(val, base + TCSR_USB_PORT_SEL); ++ } ++ ++ if (!of_property_read_u32(node, "qcom,usb-hsphy-mode-select", &val)) { ++ dev_info(&pdev->dev, "setting usb hs phy mode select = %x\n", val); ++ writel(val, base + TCSR_USB_HSPHY_CONFIG); ++ } ++ ++ if (!of_property_read_u32(node, "qcom,ess-interface-select", &val)) { ++ u32 tmp = 0; ++ dev_info(&pdev->dev, "setting ess interface select = %x\n", val); ++ tmp = readl(base + TCSR_ESS_INTERFACE_SEL_OFFSET); ++ tmp = tmp & (~TCSR_ESS_INTERFACE_SEL_MASK); ++ tmp = tmp | (val&TCSR_ESS_INTERFACE_SEL_MASK); ++ writel(tmp, base + TCSR_ESS_INTERFACE_SEL_OFFSET); ++ } ++ ++ if (!of_property_read_u32(node, "qcom,wifi_glb_cfg", &val)) { ++ dev_info(&pdev->dev, "setting wifi_glb_cfg = %x\n", val); ++ writel(val, base + TCSR_WIFI0_GLB_CFG_OFFSET); ++ writel(val, base + TCSR_WIFI1_GLB_CFG_OFFSET); ++ } ++ ++ if (!of_property_read_u32(node, "qcom,wifi_noc_memtype_m0_m2", &val)) { ++ dev_info(&pdev->dev, ++ "setting wifi_noc_memtype_m0_m2 = %x\n", val); ++ writel(val, base + TCSR_PNOC_SNOC_MEMTYPE_M0_M2); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id tcsr_dt_match[] = { ++ { .compatible = "qcom,tcsr", }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(of, tcsr_dt_match); ++ ++static struct platform_driver tcsr_driver = { ++ .driver = { ++ .name = "tcsr", ++ .owner = THIS_MODULE, ++ .of_match_table = tcsr_dt_match, ++ }, ++ .probe = tcsr_probe, ++}; ++ ++module_platform_driver(tcsr_driver); ++ ++MODULE_AUTHOR("Andy Gross "); ++MODULE_DESCRIPTION("QCOM TCSR driver"); ++MODULE_LICENSE("GPL v2"); +--- /dev/null ++++ b/include/dt-bindings/soc/qcom,tcsr.h +@@ -0,0 +1,48 @@ ++/* Copyright (c) 2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#ifndef __DT_BINDINGS_QCOM_TCSR_H ++#define __DT_BINDINGS_QCOM_TCSR_H ++ ++#define TCSR_USB_SELECT_USB3_P0 0x1 ++#define TCSR_USB_SELECT_USB3_P1 0x2 ++#define TCSR_USB_SELECT_USB3_DUAL 0x3 ++ ++/* IPQ40xx HS PHY Mode Select */ ++#define TCSR_USB_HSPHY_HOST_MODE 0x00E700E7 ++#define TCSR_USB_HSPHY_DEVICE_MODE 0x00C700E7 ++ ++/* IPQ40xx ess interface mode select */ ++#define TCSR_ESS_PSGMII 0 ++#define TCSR_ESS_PSGMII_RGMII5 1 ++#define TCSR_ESS_PSGMII_RMII0 2 ++#define TCSR_ESS_PSGMII_RMII1 4 ++#define TCSR_ESS_PSGMII_RMII0_RMII1 6 ++#define TCSR_ESS_PSGMII_RGMII4 9 ++ ++/* ++ * IPQ40xx WiFi Global Config ++ * Bit 30:AXID_EN ++ * Enable AXI master bus Axid translating to confirm all txn submitted by order ++ * Bit 24: Use locally generated socslv_wxi_bvalid ++ * 1: use locally generate socslv_wxi_bvalid for performance. ++ * 0: use SNOC socslv_wxi_bvalid. ++ */ ++#define TCSR_WIFI_GLB_CFG 0x41000000 ++ ++/* IPQ40xx MEM_TYPE_SEL_M0_M2 Select Bit 26:24 - 2 NORMAL */ ++#define TCSR_WIFI_NOC_MEMTYPE_M0_M2 0x02222222 ++ ++/* TCSR A/B REG */ ++#define IPQ806X_TCSR_REG_A_ADM_CRCI_MUX_SEL 0 ++#define IPQ806X_TCSR_REG_B_ADM_CRCI_MUX_SEL 1 ++ ++#endif diff --git a/target/linux/ipq40xx/patches-4.14/864-03-dts-ipq4019-ap-dk01-add-tcsr-config-to-dtsi.patch b/target/linux/ipq40xx/patches-4.14/864-03-dts-ipq4019-ap-dk01-add-tcsr-config-to-dtsi.patch new file mode 100644 index 000000000..f17176061 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/864-03-dts-ipq4019-ap-dk01-add-tcsr-config-to-dtsi.patch @@ -0,0 +1,42 @@ +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi +@@ -15,12 +15,39 @@ + */ + + #include "qcom-ipq4019.dtsi" ++#include + + / { + model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK01.1"; + compatible = "qcom,ipq4019"; + + soc { ++ tcsr@194b000 { ++ /* select hostmode */ ++ compatible = "qcom,tcsr"; ++ reg = <0x194b000 0x100>; ++ qcom,usb-hsphy-mode-select = ; ++ status = "ok"; ++ }; ++ ++ ess_tcsr@1953000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1953000 0x1000>; ++ qcom,ess-interface-select = ; ++ }; ++ ++ tcsr@1949000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1949000 0x100>; ++ qcom,wifi_glb_cfg = ; ++ }; ++ ++ tcsr@1957000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1957000 0x100>; ++ qcom,wifi_noc_memtype_m0_m2 = ; ++ }; ++ + rng@22000 { + status = "ok"; + }; diff --git a/target/linux/ipq40xx/patches-4.14/864-05-dts-ipq4019-ap-dk01-remove-spi-chip-node-from-dtsi.patch b/target/linux/ipq40xx/patches-4.14/864-05-dts-ipq4019-ap-dk01-remove-spi-chip-node-from-dtsi.patch new file mode 100644 index 000000000..5cbb79cb1 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/864-05-dts-ipq4019-ap-dk01-remove-spi-chip-node-from-dtsi.patch @@ -0,0 +1,17 @@ +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi +@@ -93,14 +93,6 @@ + pinctrl-names = "default"; + status = "ok"; + cs-gpios = <&tlmm 54 0>; +- +- mx25l25635e@0 { +- #address-cells = <1>; +- #size-cells = <1>; +- reg = <0>; +- compatible = "mx25l25635e"; +- spi-max-frequency = <24000000>; +- }; + }; + + serial@78af000 { diff --git a/target/linux/ipq40xx/patches-4.14/864-07-dts-ipq4019-ap-dk01.1-c1-add-spi-and-ram-nodes.patch b/target/linux/ipq40xx/patches-4.14/864-07-dts-ipq4019-ap-dk01.1-c1-add-spi-and-ram-nodes.patch new file mode 100644 index 000000000..e9d262069 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/864-07-dts-ipq4019-ap-dk01.1-c1-add-spi-and-ram-nodes.patch @@ -0,0 +1,115 @@ +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts +@@ -19,4 +19,112 @@ + / { + model = "Qualcomm Technologies, Inc. IPQ40xx/AP-DK01.1-C1"; + ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x10000000>; ++ }; ++ ++ reserved-memory { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ ranges; ++ ++ apps_bl@87000000 { ++ reg = <0x87000000 0x400000>; ++ no-map; ++ }; ++ ++ sbl@87400000 { ++ reg = <0x87400000 0x100000>; ++ no-map; ++ }; ++ ++ cnss_debug@87500000 { ++ reg = <0x87500000 0x600000>; ++ no-map; ++ }; ++ ++ cpu_context_dump@87b00000 { ++ reg = <0x87b00000 0x080000>; ++ no-map; ++ }; ++ ++ tz_apps@87b80000 { ++ reg = <0x87b80000 0x280000>; ++ no-map; ++ }; ++ ++ smem@87e00000 { ++ reg = <0x87e00000 0x080000>; ++ no-map; ++ }; ++ ++ tz@87e80000 { ++ reg = <0x87e80000 0x180000>; ++ no-map; ++ }; ++ }; ++}; ++ ++&spi_0 { ++ mx25l25635f@0 { ++ compatible = "mx25l25635f", "jedec,spi-nor"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0>; ++ spi-max-frequency = <24000000>; ++ ++ SBL1@0 { ++ label = "SBL1"; ++ reg = <0x0 0x40000>; ++ read-only; ++ }; ++ MIBIB@40000 { ++ label = "MIBIB"; ++ reg = <0x40000 0x20000>; ++ read-only; ++ }; ++ QSEE@60000 { ++ label = "QSEE"; ++ reg = <0x60000 0x60000>; ++ read-only; ++ }; ++ CDT@c0000 { ++ label = "CDT"; ++ reg = <0xc0000 0x10000>; ++ read-only; ++ }; ++ DDRPARAMS@d0000 { ++ label = "DDRPARAMS"; ++ reg = <0xd0000 0x10000>; ++ read-only; ++ }; ++ APPSBLENV@e0000 { ++ label = "APPSBLENV"; ++ reg = <0xe0000 0x10000>; ++ read-only; ++ }; ++ APPSBL@f0000 { ++ label = "APPSBL"; ++ reg = <0xf0000 0x80000>; ++ read-only; ++ }; ++ ART@170000 { ++ label = "ART"; ++ reg = <0x170000 0x10000>; ++ read-only; ++ }; ++ kernel@180000 { ++ label = "kernel"; ++ reg = <0x180000 0x400000>; ++ }; ++ rootfs@580000 { ++ label = "rootfs"; ++ reg = <0x580000 0x1600000>; ++ }; ++ firmware@180000 { ++ label = "firmware"; ++ reg = <0x180000 0x1a00000>; ++ }; ++ }; + }; diff --git a/target/linux/ipq40xx/patches-4.14/864-08-dts-ipq4019-ap-dk01.1-c1-add-compatible-string.patch b/target/linux/ipq40xx/patches-4.14/864-08-dts-ipq4019-ap-dk01.1-c1-add-compatible-string.patch new file mode 100644 index 000000000..2d4ff3104 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/864-08-dts-ipq4019-ap-dk01.1-c1-add-compatible-string.patch @@ -0,0 +1,10 @@ +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts +@@ -18,6 +18,7 @@ + + / { + model = "Qualcomm Technologies, Inc. IPQ40xx/AP-DK01.1-C1"; ++ compatible = "qcom,ap-dk01.1-c1", "qcom,ap-dk01.2-c1", "qcom,ipq4019"; + + memory { + device_type = "memory"; diff --git a/target/linux/ipq40xx/patches-4.14/900-clk-fix.patch b/target/linux/ipq40xx/patches-4.14/900-clk-fix.patch new file mode 100644 index 000000000..1c6b8c831 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/900-clk-fix.patch @@ -0,0 +1,111 @@ +From 12e9319da1adacac92930c899c99f0e1970cac11 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Thu, 11 Mar 2018 14:41:31 +0100 +Subject: [PATCH] clk: fix apss cpu overclocking + +There's an interaction issue between the clk changes:" +clk: qcom: ipq4019: Add the apss cpu pll divider clock node +clk: qcom: ipq4019: remove fixed clocks and add pll clocks +" and the cpufreq-dt. + +cpufreq-dt is now spamming the kernel-log with the following: + +[ 1099.190658] cpu cpu0: dev_pm_opp_set_rate: failed to find current OPP +for freq 761142857 (-34) + +This only happens on certain devices like the Compex WPJ428 +and AVM FritzBox!4040. However, other devices like the Asus +RT-AC58U and Meraki MR33 work just fine. + +The issue stem from the fact that all higher CPU-Clocks +are achieved by switching the clock-parent to the P_DDRPLLAPSS +(ddrpllapss). Which is set by Qualcomm's proprietary bootcode +as part of the DDR calibration. + +For example, the FB4040 uses 256 MiB Nanya NT5CC128M16IP clocked +at round 533 MHz (ddrpllsdcc = 190285714 Hz). + +whereas the 128 MiB Nanya NT5CC64M16GP-DI in the ASUS RT-AC58U is +clocked at a slightly higher 537 MHz ( ddrpllsdcc = 192000000 Hz). + +This patch attempts to fix the issue by modifying +clk_cpu_div_round_rate(), clk_cpu_div_set_rate(), clk_cpu_div_recalc_rate() +to use a new qcom_find_freq_close() function, which returns the closest +matching frequency, instead of the next higher. This way, the SoC in +the FB4040 (with its max clock speed of 710.4 MHz) will no longer +try to overclock to 761 MHz. + +Fixes: d83dcacea18 ("clk: qcom: ipq4019: Add the apss cpu pll divider clock node") +Signed-off-by: Christian Lamparter +--- +--- a/drivers/clk/qcom/gcc-ipq4019.c ++++ b/drivers/clk/qcom/gcc-ipq4019.c +@@ -1253,6 +1253,29 @@ static const struct clk_fepll_vco gcc_fe + .reg = 0x2f020, + }; + ++ ++const struct freq_tbl *qcom_find_freq_close(const struct freq_tbl *f, ++ unsigned long rate) ++{ ++ const struct freq_tbl *last = NULL; ++ ++ for ( ; f->freq; f++) { ++ if (rate == f->freq) ++ return f; ++ ++ if (f->freq > rate) { ++ if (!last || ++ (f->freq - rate) < (rate - last->freq)) ++ return f; ++ else ++ return last; ++ } ++ last = f; ++ } ++ ++ return last; ++} ++ + /* + * Round rate function for APSS CPU PLL Clock divider. + * It looks up the frequency table and returns the next higher frequency +@@ -1265,7 +1288,7 @@ static long clk_cpu_div_round_rate(struc + struct clk_hw *p_hw; + const struct freq_tbl *f; + +- f = qcom_find_freq(pll->freq_tbl, rate); ++ f = qcom_find_freq_close(pll->freq_tbl, rate); + if (!f) + return -EINVAL; + +@@ -1288,7 +1311,7 @@ static int clk_cpu_div_set_rate(struct c + u32 mask; + int ret; + +- f = qcom_find_freq(pll->freq_tbl, rate); ++ f = qcom_find_freq_close(pll->freq_tbl, rate); + if (!f) + return -EINVAL; + +@@ -1315,6 +1338,7 @@ static unsigned long + clk_cpu_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { ++ const struct freq_tbl *f; + struct clk_fepll *pll = to_clk_fepll(hw); + u32 cdiv, pre_div; + u64 rate; +@@ -1335,7 +1359,11 @@ clk_cpu_div_recalc_rate(struct clk_hw *h + rate = clk_fepll_vco_calc_rate(pll, parent_rate) * 2; + do_div(rate, pre_div); + +- return rate; ++ f = qcom_find_freq_close(pll->freq_tbl, rate); ++ if (!f) ++ return rate; ++ ++ return f->freq; + }; + + static const struct clk_ops clk_regmap_cpu_div_ops = { diff --git a/target/linux/ipq40xx/patches-4.14/901-essedma-disable-default-vlan-tagging.patch b/target/linux/ipq40xx/patches-4.14/901-essedma-disable-default-vlan-tagging.patch new file mode 100644 index 000000000..ec339c479 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.14/901-essedma-disable-default-vlan-tagging.patch @@ -0,0 +1,82 @@ +From 42b508d91b7f51b054f383e3aa42089ccab9300d Mon Sep 17 00:00:00 2001 +From: Chen Minqiang +Date: Thu, 15 Mar 2018 05:33:46 +0800 +Subject: [PATCH] essedma: disable default vlan tagging + +The essedma driver has its own unique take on VLAN management +and its configuration. In the original SDK, each VLAN is +assigned one virtual ethernet netdev. + +However, this is non-standard. So, this patch does away +with the default_vlan_tag property the driver is using +and therefore forces the user to use the kernel's vlan +feature. + +This patch also removes the "qcom,poll_required = <1>;" from +the essedma node. + +Signed-off-by: Christian Lamparter +Signed-off-by: Chen Minqiang +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 5 ++--- + drivers/net/ethernet/qualcomm/essedma/edma.c | 14 +++++--------- + 2 files changed, 7 insertions(+), 12 deletions(-) + +diff --git a/arch/arm/boot/dts/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom-ipq4019.dtsi +index 3c4617f..7c3af8e 100644 +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -598,8 +598,7 @@ + qcom,page-mode = <0>; + qcom,rx_head_buf_size = <1540>; + qcom,mdio_supported; +- qcom,poll_required = <1>; +- qcom,num_gmac = <2>; ++ qcom,num_gmac = <1>; + interrupts = <0 65 IRQ_TYPE_EDGE_RISING + 0 66 IRQ_TYPE_EDGE_RISING + 0 67 IRQ_TYPE_EDGE_RISING +@@ -637,7 +636,7 @@ + + gmac0: gmac0 { + local-mac-address = [00 00 00 00 00 00]; +- vlan_tag = <1 0x1f>; ++ vlan_tag = <1 0x3f>; + }; + + gmac1: gmac1 { +diff --git a/drivers/net/ethernet/qualcomm/essedma/edma.c b/drivers/net/ethernet/qualcomm/essedma/edma.c +index 05f9ce9..a3c0d66 100644 +--- a/drivers/net/ethernet/qualcomm/essedma/edma.c ++++ b/drivers/net/ethernet/qualcomm/essedma/edma.c +@@ -750,13 +750,11 @@ static void edma_rx_complete(struct edma_common_info *edma_cinfo, + edma_receive_checksum(rd, skb); + + /* Process VLAN HW acceleration indication provided by HW */ +- if (unlikely(adapter->default_vlan_tag != rd->rrd4)) { +- vlan = rd->rrd4; +- if (likely(rd->rrd7 & EDMA_RRD_CVLAN)) +- __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan); +- else if (rd->rrd1 & EDMA_RRD_SVLAN) +- __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021AD), vlan); +- } ++ vlan = rd->rrd4; ++ if (likely(rd->rrd7 & EDMA_RRD_CVLAN)) ++ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan); ++ else if (rd->rrd1 & EDMA_RRD_SVLAN) ++ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021AD), vlan); + + /* Update rx statistics */ + adapter->stats.rx_packets++; +@@ -1434,8 +1432,6 @@ netdev_tx_t edma_xmit(struct sk_buff *skb, + if (!adapter->edma_cinfo->is_single_phy) { + if (unlikely(skb_vlan_tag_present(skb))) + flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_FLAG; +- else if (adapter->default_vlan_tag) +- flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_DEFAULT_FLAG; + } + + /* Check and mark checksum offload */ +-- +2.7.4 + diff --git a/target/linux/ipq40xx/profiles/00-default.mk b/target/linux/ipq40xx/profiles/00-default.mk new file mode 100644 index 000000000..f6ded8544 --- /dev/null +++ b/target/linux/ipq40xx/profiles/00-default.mk @@ -0,0 +1,9 @@ +define Profile/Default + NAME:=Default Profile + PRIORITY:=1 +endef + +define Profile/Default/Description + Default package set compatible with most boards. +endef +$(eval $(call Profile,Default)) diff --git a/target/linux/ipq806x/base-files/etc/board.d/01_leds b/target/linux/ipq806x/base-files/etc/board.d/01_leds index 9d5f7fde0..8e897141a 100755 --- a/target/linux/ipq806x/base-files/etc/board.d/01_leds +++ b/target/linux/ipq806x/base-files/etc/board.d/01_leds @@ -8,56 +8,57 @@ board_config_update board=$(board_name) +boardname="${board##*,}" case "$board" in -c2600) - ucidef_set_led_usbport "usb1" "USB 1" "${board}:white:usb_2" "usb1-port1" "usb2-port1" - ucidef_set_led_usbport "usb2" "USB 2" "${board}:white:usb_4" "usb3-port1" "usb4-port1" - ucidef_set_led_switch "wan" "wan" "${board}:white:wan" "switch0" "0x20" - ucidef_set_led_switch "lan" "lan" "${board}:white:lan" "switch0" "0x1e" +asus,rt-acrh17) + ucidef_set_led_default "status" "STATUS" "${boardname}:blue:status" "1" + ucidef_set_led_wlan "wlan2g" "WLAN2G" "${boardname}:blue:wlan2g" "phy1tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "${boardname}:blue:wlan5g" "phy0tpt" + ucidef_set_led_switch "wan" "WAN(blue)" "${boardname}:blue:wan" "switch0" "0x20" + ucidef_set_led_switch "lan1" "LAN1" "${boardname}:blue:lan1" "switch0" "0x02" + ucidef_set_led_switch "lan2" "LAN2" "${boardname}:blue:lan2" "switch0" "0x04" + ucidef_set_led_switch "lan3" "LAN3" "${boardname}:blue:lan3" "switch0" "0x08" + ucidef_set_led_switch "lan4" "LAN4" "${boardname}:blue:lan4" "switch0" "0x10" ;; -d7800 |\ -r7500 |\ -r7500v2 |\ -r7800) - ucidef_set_led_usbport "usb1" "USB 1" "${board}:white:usb1" "usb1-port1" "usb2-port1" - ucidef_set_led_usbport "usb2" "USB 2" "${board}:white:usb2" "usb3-port1" "usb4-port1" - ucidef_set_led_netdev "wan" "WAN" "${board}:white:wan" "eth0" - ucidef_set_led_ide "esata" "eSATA" "${board}:white:esata" - ;; -fritz4040) - ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" "phy1tpt" - ucidef_set_led_switch "wan" "WAN" "${board}:green:wan" "switch0" "0x20" - ucidef_set_led_switch "lan" "LAN" "${board}:green:lan" "switch0" "0x1e" - ;; -nbg6817) - ucidef_set_led_wlan "wlan2g" "WLAN2G" "$board:amber:wifi2g" "phy1tpt" - ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:amber:wifi5g" "phy0tpt" - ucidef_set_led_netdev "wan" "WAN" "$board:white:internet" "eth1" - ;; -rt-acrh17) - ucidef_set_led_default "status" "STATUS" "${board}:blue:status" "1" - ucidef_set_led_wlan "wlan2g" "WLAN2G" "${board}:blue:wlan2g" "phy0tpt" - ucidef_set_led_wlan "wlan5g" "WLAN5G" "${board}:blue:wlan5g" "phy1tpt" - ucidef_set_led_switch "wan" "WAN(blue)" "${board}:blue:wan" "switch0" "0x20" - ucidef_set_led_switch "lan1" "LAN1" "${board}:blue:lan1" "switch0" "0x02" - ucidef_set_led_switch "lan2" "LAN2" "${board}:blue:lan2" "switch0" "0x04" - ucidef_set_led_switch "lan3" "LAN3" "${board}:blue:lan3" "switch0" "0x08" - ucidef_set_led_switch "lan4" "LAN4" "${board}:blue:lan4" "switch0" "0x10" - ;; -rt-ac58u) +asus,rt-ac58u) ucidef_set_led_wlan "wlan2g" "WLAN2G" "$board:blue:wlan2G" "phy0tpt" ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:blue:wlan5G" "phy1tpt" ucidef_set_led_switch "wan" "WAN" "${board}:blue:wan" "switch0" "0x20" ucidef_set_led_usbport "usb" "USB" "${board}:blue:usb" "usb1-port1" "usb2-port1" "usb3-port1" "usb4-port1" ucidef_set_led_switch "lan" "LAN" "${board}:blue:lan" "switch0" "0x1e" ;; -vr2600v) - ucidef_set_led_usbport "usb" "USB" "${board}:white:usb" "usb1-port1" "usb2-port1" "usb3-port1" "usb4-port1" - ucidef_set_led_switch "lan" "lan" "${board}:white:lan" "switch0" "0x1e" - ucidef_set_led_wlan "wlan2g" "WLAN2G" "${board}:white:wlan2g" "phy0tpt" - ucidef_set_led_wlan "wlan5g" "WLAN5G" "${board}:white:wlan5g" "phy1tpt" - ucidef_set_led_switch "wan" "wan" "${board}:white:wan" "switch0" "0x20" +avm,fritzbox-4040) + ucidef_set_led_wlan "wlan" "WLAN" "fritz4040:green:wlan" "phy0tpt" "phy1tpt" + ucidef_set_led_netdev "wan" "WAN" "fritz4040:green:wan" "eth1" + ucidef_set_led_switch "lan" "LAN" "fritz4040:green:lan" "switch0" "0x1e" + ;; +netgear,d7800 |\ +netgear,r7500 |\ +netgear,r7500v2 |\ +netgear,r7800) + ucidef_set_led_usbport "usb1" "USB 1" "${boardname}:white:usb1" "usb1-port1" "usb2-port1" + ucidef_set_led_usbport "usb2" "USB 2" "${boardname}:white:usb2" "usb3-port1" "usb4-port1" + ucidef_set_led_netdev "wan" "WAN" "${boardname}:white:wan" "eth0" + ucidef_set_led_ide "esata" "eSATA" "${boardname}:white:esata" + ;; +tplink,c2600) + ucidef_set_led_usbport "usb1" "USB 1" "${boardname}:white:usb_2" "usb1-port1" "usb2-port1" + ucidef_set_led_usbport "usb2" "USB 2" "${boardname}:white:usb_4" "usb3-port1" "usb4-port1" + ucidef_set_led_switch "wan" "wan" "${boardname}:white:wan" "switch0" "0x20" + ucidef_set_led_switch "lan" "lan" "${boardname}:white:lan" "switch0" "0x1e" + ;; +tplink,vr2600v) + ucidef_set_led_usbport "usb" "USB" "${boardname}:white:usb" "usb1-port1" "usb2-port1" "usb3-port1" "usb4-port1" + ucidef_set_led_switch "lan" "lan" "${boardname}:white:lan" "switch0" "0x1e" + ucidef_set_led_wlan "wlan2g" "WLAN2G" "${boardname}:white:wlan2g" "phy0tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "${boardname}:white:wlan5g" "phy1tpt" + ucidef_set_led_switch "wan" "wan" "${boardname}:white:wan" "switch0" "0x20" + ;; +zyxel,nbg6817) + ucidef_set_led_wlan "wlan2g" "WLAN2G" "${boardname}:amber:wifi2g" "phy1tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "${boardname}:amber:wifi5g" "phy0tpt" + ucidef_set_led_netdev "wan" "WAN" "${boardname}:white:internet" "eth1" ;; *) ;; diff --git a/target/linux/ipq806x/base-files/etc/board.d/02_network b/target/linux/ipq806x/base-files/etc/board.d/02_network index f69638f03..f8d7f7469 100755 --- a/target/linux/ipq806x/base-files/etc/board.d/02_network +++ b/target/linux/ipq806x/base-files/etc/board.d/02_network @@ -12,48 +12,7 @@ board_config_update board=$(board_name) case "$board" in -ap148 |\ -d7800 |\ -r7500 |\ -r7500v2 |\ -r7800 |\ -vr2600v) - ucidef_add_switch "switch0" \ - "1:lan" "2:lan" "3:lan" "4:lan" "6@eth1" "5:wan" "0@eth0" - ;; -c2600) - ucidef_add_switch "switch0" \ - "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" "6@eth1" "5:wan" "0@eth0" - ;; -db149) - ucidef_set_interface_lan "eth1 eth2 eth3" - ucidef_add_switch "switch0" \ - "1:lan" "2:lan" "3:lan" "4:lan" "6u@eth1" "5:wan" "0u@eth0" - ;; -ea8500) - - hw_mac_addr=$(mtd_get_mac_ascii devinfo hw_mac_addr) - ucidef_add_switch "switch0" \ - "0@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "5:wan" - ucidef_set_interface_macaddr "lan" "$hw_mac_addr" - ucidef_set_interface_macaddr "wan" "$hw_mac_addr" - ;; -fritz4040) - lan_mac_addr=$(ipq40xx_get_dt_mac 0) - wan_mac_addr=$(ipq40xx_get_dt_mac 1) - ucidef_add_switch "switch0" \ - "0t@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "5:wan" - ucidef_set_interface_macaddr "lan" "$lan_mac_addr" - ucidef_set_interface_macaddr "wan" "$wan_mac_addr" - ;; -nbg6817) - hw_mac_addr=$(mtd_get_mac_ascii 0:APPSBLENV ethaddr) - ucidef_add_switch "switch0" \ - "1:lan" "2:lan" "3:lan" "4:lan" "6@eth1" "5:wan" "0@eth0" - ucidef_set_interface_macaddr "lan" "$hw_mac_addr" - ucidef_set_interface_macaddr "wan" "$(macaddr_add $hw_mac_addr 1)" - ;; -rt-acrh17) +asus,rt-acrh17) CI_UBIPART=UBI_DEV lan_mac_addr=$(mtd_get_mac_binary_ubi Factory 4102) wan_mac_addr=$(mtd_get_mac_binary_ubi Factory 36870) @@ -62,7 +21,7 @@ rt-acrh17) ucidef_set_interface_macaddr "lan" "$lan_mac_addr" ucidef_set_interface_macaddr "wan" "$wan_mac_addr" ;; -rt-ac58u) +asus,rt-ac58u) CI_UBIPART=UBI_DEV wan_mac_addr=$(mtd_get_mac_binary_ubi Factory 20486) lan_mac_addr=$(mtd_get_mac_binary_ubi Factory 4102) @@ -71,6 +30,46 @@ rt-ac58u) ucidef_set_interface_macaddr "lan" "$lan_mac_addr" ucidef_set_interface_macaddr "wan" "$wan_mac_addr" ;; +avm,fritzbox-4040) + ucidef_set_interfaces_lan_wan "eth0" "eth1" + ucidef_add_switch "switch0" \ + "0@eth0" "1:lan" "2:lan" "3:lan" "4:lan" + ;; +linksys,ea8500) + hw_mac_addr=$(mtd_get_mac_ascii devinfo hw_mac_addr) + ucidef_add_switch "switch0" \ + "0@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "5:wan" + ucidef_set_interface_macaddr "lan" "$hw_mac_addr" + ucidef_set_interface_macaddr "wan" "$hw_mac_addr" + ;; +netgear,d7800 |\ +netgear,r7500 |\ +netgear,r7500v2 |\ +netgear,r7800 |\ +qcom,ipq8064-ap148 |\ +tplink,vr2600v) + ucidef_add_switch "switch0" \ + "1:lan" "2:lan" "3:lan" "4:lan" "6@eth1" "5:wan" "0@eth0" + ;; +openmesh,a42) + ucidef_set_interfaces_lan_wan "eth1" "eth0" + ;; +qcom,ipq8064-db149) + ucidef_set_interface_lan "eth1 eth2 eth3" + ucidef_add_switch "switch0" \ + "1:lan" "2:lan" "3:lan" "4:lan" "6u@eth1" "5:wan" "0u@eth0" + ;; +tplink,c2600) + ucidef_add_switch "switch0" \ + "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" "6@eth1" "5:wan" "0@eth0" + ;; +zyxel,nbg6817) + hw_mac_addr=$(mtd_get_mac_ascii 0:APPSBLENV ethaddr) + ucidef_add_switch "switch0" \ + "1:lan" "2:lan" "3:lan" "4:lan" "6@eth1" "5:wan" "0@eth0" + ucidef_set_interface_macaddr "lan" "$(macaddr_add $hw_mac_addr 2)" + ucidef_set_interface_macaddr "wan" "$(macaddr_add $hw_mac_addr 3)" + ;; *) echo "Unsupported hardware. Network interfaces not intialized" ;; diff --git a/target/linux/ipq806x/base-files/etc/diag.sh b/target/linux/ipq806x/base-files/etc/diag.sh index 7c9a9d082..df4afd936 100755 --- a/target/linux/ipq806x/base-files/etc/diag.sh +++ b/target/linux/ipq806x/base-files/etc/diag.sh @@ -2,12 +2,11 @@ # Copyright (C) 2016 Henryk Heisig hyniu@o2.pl . /lib/functions/leds.sh -. /lib/ipq806x.sh -boot="$(ipq806x_get_dt_led boot)" -failsafe="$(ipq806x_get_dt_led failsafe)" -running="$(ipq806x_get_dt_led running)" -upgrade="$(ipq806x_get_dt_led upgrade)" +boot="$(get_dt_led boot)" +failsafe="$(get_dt_led failsafe)" +running="$(get_dt_led running)" +upgrade="$(get_dt_led upgrade)" set_state() { status_led="$boot" diff --git a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata index 22de2de82..45d4788a2 100644 --- a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +++ b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata @@ -62,81 +62,97 @@ board=$(board_name) case "$FIRMWARE" in "ath10k/pre-cal-ahb-a000000.wifi.bin") case "$board" in - rt-acrh17 |\ - rt-ac58u) + asus,rt-acrh17) + CI_UBIPART=UBI_DEV + . /lib/upgrade/nand.sh + ath10kcal_ubi_extract "Factory" 4096 12064 + ;; + asus,rt-ac58u) . /lib/upgrade/nand.sh CI_UBIPART=UBI_DEV ath10kcal_ubi_extract "Factory" 4096 12064 ;; - fritz4040) + avm,fritzbox-4040) /usr/bin/fritz_cal_extract -i 1 -s 0x400 -e 0x207 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader_config") ;; + openmesh,a42) + ath10kcal_extract "0:ART" 4096 12064 + ;; + qcom,ap-dk01.1-c1) + ath10kcal_extract "ART" 4096 12064 + ;; esac ;; "ath10k/pre-cal-ahb-a800000.wifi.bin") case "$board" in - rt-ac58u) + asus,rt-ac58u) . /lib/upgrade/nand.sh CI_UBIPART=UBI_DEV ath10kcal_ubi_extract "Factory" 20480 12064 ;; - fritz4040) + avm,fritzbox-4040) /usr/bin/fritz_cal_extract -i 1 -s 0x400 -e 0x208 -l 12064 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader_config") ;; + openmesh,a42) + ath10kcal_extract "0:ART" 20480 12064 + ;; + qcom,ap-dk01.1-c1) + ath10kcal_extract "ART" 20480 12064 + ;; esac ;; "ath10k/pre-cal-pci-0000:01:00.0.bin") case $board in - rt-acrh17) + asus,rt-acrh17) CI_UBIPART=UBI_DEV . /lib/upgrade/nand.sh ath10kcal_ubi_extract "Factory" 36864 12064 ;; - c2600) - ath10kcal_extract "radio" 4096 12064 -# ath10kcal_patch_mac $(macaddr_add $(mtd_get_mac_binary default-mac 8) -1) - ;; - d7800 |\ - r7500v2 |\ - r7800) - ath10kcal_extract "art" 4096 12064 - ;; - ea8500) + linksys,ea8500) hw_mac_addr=$(mtd_get_mac_ascii devinfo hw_mac_addr) ath10kcal_extract "art" 4096 12064 ;; - nbg6817) - ath10kcal_extract "0:ART" 4096 12064 + netgear,d7800 |\ + netgear,r7500v2 |\ + netgear,r7800) + ath10kcal_extract "art" 4096 12064 ;; - vr2600v) + tplink,c2600) + ath10kcal_extract "radio" 4096 12064 +# ath10kcal_patch_mac $(macaddr_add $(mtd_get_mac_binary default-mac 8) -1) + ;; + tplink,vr2600v) ath10kcal_extract "ART" 4096 12064 ;; + zyxel,nbg6817) + ath10kcal_extract "0:ART" 4096 12064 + ;; esac ;; "ath10k/pre-cal-pci-0001:01:00.0.bin") case $board in - c2600) - ath10kcal_extract "radio" 20480 12064 -# ath10kcal_patch_mac $(macaddr_add $(mtd_get_mac_binary default-mac 8) -2) - ;; - d7800 |\ - r7500v2 |\ - r7800) - ath10kcal_extract "art" 20480 12064 - ;; - ea8500) + linksys,ea8500) hw_mac_addr=$(mtd_get_mac_ascii devinfo hw_mac_addr) ath10kcal_extract "art" 20480 12064 ;; - nbg6817) - ath10kcal_extract "0:ART" 20480 12064 + netgear,d7800 |\ + netgear,r7500v2 |\ + netgear,r7800) + ath10kcal_extract "art" 20480 12064 ;; - vr2600v) + tplink,c2600) + ath10kcal_extract "radio" 20480 12064 +# ath10kcal_patch_mac $(macaddr_add $(mtd_get_mac_binary default-mac 8) -2) + ;; + tplink,vr2600v) ath10kcal_extract "ART" 20480 12064 ;; + zyxel,nbg6817) + ath10kcal_extract "0:ART" 20480 12064 + ;; esac ;; *) diff --git a/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac b/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac index fee56cd66..7e31c3856 100644 --- a/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac +++ b/target/linux/ipq806x/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac @@ -12,20 +12,23 @@ PHYNBR=${DEVPATH##*/phy} board=$(board_name) case "$board" in - c2600) - echo $(macaddr_add $(mtd_get_mac_binary default-mac 8) $(($PHYNBR - 1)) ) > /sys${DEVPATH}/macaddress - ;; - d7800 |\ - r7500v2 |\ - r7800) - echo $(macaddr_add $(mtd_get_mac_binary art 6) $(($PHYNBR + 1)) ) > /sys${DEVPATH}/macaddress - ;; - ea8500) + linksys,ea8500) echo $(macaddr_add $(mtd_get_mac_ascii devinfo hw_mac_addr) $(($PHYNBR + 1)) ) > /sys${DEVPATH}/macaddress ;; - vr2600v) + netgear,d7800 |\ + netgear,r7500v2 |\ + netgear,r7800) + echo $(macaddr_add $(mtd_get_mac_binary art 6) $(($PHYNBR + 1)) ) > /sys${DEVPATH}/macaddress + ;; + tplink,c2600) + echo $(macaddr_add $(mtd_get_mac_binary default-mac 8) $(($PHYNBR - 1)) ) > /sys${DEVPATH}/macaddress + ;; + tplink,vr2600v) echo $(macaddr_add $(mtd_get_mac_binary default-mac 0) $(($PHYNBR - 1)) ) > /sys${DEVPATH}/macaddress ;; + zyxel,nbg6817) + echo $(macaddr_add $(mtd_get_mac_ascii 0:APPSBLENV ethaddr) $((1 - $PHYNBR)) ) > /sys${DEVPATH}/macaddress + ;; *) ;; esac diff --git a/target/linux/ipq806x/base-files/etc/init.d/linksys_recovery b/target/linux/ipq806x/base-files/etc/init.d/linksys_recovery index 4d94f1f76..6b4b38ec7 100755 --- a/target/linux/ipq806x/base-files/etc/init.d/linksys_recovery +++ b/target/linux/ipq806x/base-files/etc/init.d/linksys_recovery @@ -6,7 +6,7 @@ boot() { . /lib/functions.sh case $(board_name) in - ea8500) + linksys,ea8500) # make sure auto_recovery in uboot is always on AUTO_RECOVERY_ENA="`fw_printenv -n auto_recovery`" if [ "$AUTO_RECOVERY_ENA" != "yes" ] ; then diff --git a/target/linux/ipq806x/base-files/etc/init.d/set_cpu_affinity b/target/linux/ipq806x/base-files/etc/init.d/set_cpu_affinity deleted file mode 100755 index 01290eee9..000000000 --- a/target/linux/ipq806x/base-files/etc/init.d/set_cpu_affinity +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=99 - -set_irq_affinity() { - local name="$1" - local val="$2" - -case "$name" in -wifi0) - local irq_wifi0=`grep -E -m1 'ath10k_ahb|qcom-pcie-msi' /proc/interrupts | cut -d: -f1 | tail -n1 | tr -d ' '` - [ -n "$irq_wifi0" ] || echo "$name irq not found." - echo "$val" > "/proc/irq/$irq_wifi0/smp_affinity" - ;; -wifi1) - local irq_wifi1=`grep -E -m2 'ath10k_ahb|qcom-pcie-msi' /proc/interrupts | cut -d: -f1 | tail -n1 | tr -d ' '` - [ -n "$irq_wifi1" ] || echo "$name irq not found." - echo "$val" > "/proc/irq/$irq_wifi1/smp_affinity" - ;; -wifi2) - local irq_wifi1=`grep -E -m3 'ath10k_ahb|qcom-pcie-msi' /proc/interrupts | cut -d: -f1 | tail -n1 | tr -d ' '` - [ -n "$irq_wifi1" ] || echo "$name irq not found." - echo "$val" > "/proc/irq/$irq_wifi1/smp_affinity" - ;; -*) - local irq=`grep -m 1 "$name" /proc/interrupts | cut -d: -f1 | sed 's, *,,'` - [ -n "$irq" ] || echo "$name irq not found." - echo "$val" > "/proc/irq/$irq/smp_affinity" - ;; -esac -} - -start() { - -. /lib/functions.sh - -local board=$(board_name) - -case "$board" in -rt-ac58u |\ -fritz4040) - set_irq_affinity edma_eth_tx4 2 - set_irq_affinity edma_eth_tx5 2 - set_irq_affinity edma_eth_tx6 2 - set_irq_affinity edma_eth_tx7 2 - set_irq_affinity edma_eth_rx2 2 - set_irq_affinity edma_eth_tx8 4 - set_irq_affinity edma_eth_tx9 4 - set_irq_affinity edma_eth_tx10 4 - set_irq_affinity edma_eth_tx11 4 - set_irq_affinity edma_eth_rx4 4 - set_irq_affinity edma_eth_tx12 8 - set_irq_affinity edma_eth_tx13 8 - set_irq_affinity edma_eth_tx14 8 - set_irq_affinity edma_eth_tx15 8 - set_irq_affinity edma_eth_rx6 8 - set_irq_affinity wifi0 2 - set_irq_affinity wifi1 4 - set_irq_affinity wifi2 8 - ;; -ap148 |\ -c2600 |\ -db149 |\ -d7800 |\ -ea8500 |\ -nbg6817 |\ -r7500 |\ -r7500v2 |\ -r7800 |\ -vr2600v) - set_irq_affinity eth0 2 - set_irq_affinity eth1 2 - set_irq_affinity wifi0 2 - ;; -*) - echo "Unsupported hardware. CPU affinity is not adjusted." - ;; -esac -} diff --git a/target/linux/ipq806x/base-files/lib/ipq806x.sh b/target/linux/ipq806x/base-files/lib/ipq806x.sh deleted file mode 100644 index c4af88b00..000000000 --- a/target/linux/ipq806x/base-files/lib/ipq806x.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2014 The Linux Foundation. All rights reserved. -# Copyright (C) 2011 OpenWrt.org -# - -IPQ806X_BOARD_NAME= -IPQ806X_MODEL= - -ipq806x_board_detect() { - local machine - local name - - machine=$(cat /proc/device-tree/model) - - case "$machine" in - *"AP148") - name="ap148" - ;; - *"4040") - name="fritz4040" - ;; - *"C2600") - name="c2600" - ;; - *"D7800") - name="d7800" - ;; - *"DB149") - name="db149" - ;; - *"NBG6817") - name="nbg6817" - ;; - *"R7500") - name="r7500" - ;; - *"R7500v2") - name="r7500v2" - ;; - *"Linksys EA8500"*) - name="ea8500" - ;; - *"R7800") - name="r7800" - ;; - *"RT-ACRH17") - name="rt-acrh17" - ;; - *"RT-AC58U") - name="rt-ac58u" - ;; - *"VR2600v") - name="vr2600v" - ;; - esac - - [ -z "$name" ] && name="unknown" - - [ -z "$IPQ806X_BOARD_NAME" ] && IPQ806X_BOARD_NAME="$name" - [ -z "$IPQ806X_MODEL" ] && IPQ806X_MODEL="$machine" - - [ -e "/tmp/sysinfo/" ] || mkdir -p "/tmp/sysinfo/" - - echo "$IPQ806X_BOARD_NAME" > /tmp/sysinfo/board_name - echo "$IPQ806X_MODEL" > /tmp/sysinfo/model -} - -ipq806x_get_dt_led() { - local label - local ledpath - local basepath="/proc/device-tree" - local nodepath="$basepath/aliases/led-$1" - - [ -f "$nodepath" ] && ledpath=$(cat "$nodepath") - [ -n "$ledpath" ] && label=$(cat "$basepath$ledpath/label") - - echo "$label" -} - -ipq40xx_get_dt_mac() { - local mac - local ethpath - local basepath="/sys/firmware/devicetree/base" - local nodepath="$basepath/aliases/ethernet$1" - - [ -f "$nodepath" ] && ethpath=$(cat "$nodepath") - [ -n "$ethpath" ] && mac=$(cat "$basepath$ethpath/local-mac-address") - - echo "$mac" | hexdump -v -n 6 -e '5/1 "%02x:" 1/1 "%02x"' $part 2>/dev/null -} diff --git a/target/linux/ipq806x/base-files/lib/preinit/01_preinit_do_ipq806x.sh b/target/linux/ipq806x/base-files/lib/preinit/01_preinit_do_ipq806x.sh deleted file mode 100644 index 785f1ebb8..000000000 --- a/target/linux/ipq806x/base-files/lib/preinit/01_preinit_do_ipq806x.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2014 The Linux Foundation. All rights reserved. -# - -do_ipq806x() { - . /lib/ipq806x.sh - - ipq806x_board_detect -} - -boot_hook_add preinit_main do_ipq806x diff --git a/target/linux/ipq806x/base-files/lib/preinit/06_set_iface_mac b/target/linux/ipq806x/base-files/lib/preinit/06_set_iface_mac index d08f26558..f0c7dda87 100644 --- a/target/linux/ipq806x/base-files/lib/preinit/06_set_iface_mac +++ b/target/linux/ipq806x/base-files/lib/preinit/06_set_iface_mac @@ -9,10 +9,12 @@ preinit_set_mac_address() { . /lib/functions.sh case $(board_name) in - rt-acrh17) + asus,rt-ac58u|\ + asus,rt-acrh17) CI_UBIPART=UBI_DEV mac=$(mtd_get_mac_binary_ubi Factory 4102) ifconfig eth0 hw ether $mac 2>/dev/null + ;; esac } diff --git a/target/linux/ipq806x/base-files/lib/upgrade/openmesh.sh b/target/linux/ipq806x/base-files/lib/upgrade/openmesh.sh new file mode 100644 index 000000000..a2c79d9e4 --- /dev/null +++ b/target/linux/ipq806x/base-files/lib/upgrade/openmesh.sh @@ -0,0 +1,110 @@ +# The U-Boot loader of the OpenMesh devices requires image sizes and +# checksums to be provided in the U-Boot environment. +# The OpenMesh devices come with 2 main partitions - while one is active +# sysupgrade will flash the other. The boot order is changed to boot the +# newly flashed partition. If the new partition can't be booted due to +# upgrade failures the previously used partition is loaded. + +platform_do_upgrade_openmesh() { + local tar_file="$1" + local restore_backup + local primary_kernel_mtd + + local setenv_script="/tmp/fw_env_upgrade" + + local kernel_mtd="$(find_mtd_index $PART_NAME)" + local kernel_offset="$(cat /sys/class/mtd/mtd${kernel_mtd}/offset)" + local total_size="$(cat /sys/class/mtd/mtd${kernel_mtd}/size)" + + # detect to which flash region the new image is written to. + # + # 1. check what is the mtd index for the first flash region on this + # device + # 2. check if the target partition ("inactive") has the mtd index of + # the first flash region + # + # - when it is: the new bootseq will be 1,2 and the first region is + # modified + # - when it isnt: bootseq will be 2,1 and the second region is + # modified + # + # The detection has to be done via the hardcoded mtd partition because + # the current boot might be done with the fallback region. Let us + # assume that the current bootseq is 1,2. The bootloader detected that + # the image in flash region 1 is corrupt and thus switches to flash + # region 2. The bootseq in the u-boot-env is now still the same and + # the sysupgrade code can now only rely on the actual mtd indexes and + # not the bootseq variable to detect the currently booted flash + # region/image. + # + # In the above example, an implementation which uses bootseq ("1,2") to + # detect the currently booted image would assume that region 1 is booted + # and then overwrite the variables for the wrong flash region (aka the + # one which isn't modified). This could result in a device which doesn't + # boot anymore to Linux until it was reflashed with ap51-flash. + local next_boot_part="1" + case "$(board_name)" in + openmesh,a42) + primary_kernel_mtd=8 + ;; + *) + echo "failed to detect primary kernel mtd partition for board" + return 1 + ;; + esac + [ "$kernel_mtd" = "$primary_kernel_mtd" ] || next_boot_part="2" + + local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$') + board_dir=${board_dir%/} + + local kernel_length=$(tar xf $tar_file ${board_dir}/kernel -O | wc -c) + local rootfs_length=$(tar xf $tar_file ${board_dir}/root -O | wc -c) + # rootfs without EOF marker + rootfs_length=$((rootfs_length-4)) + + local kernel_md5=$(tar xf $tar_file ${board_dir}/kernel -O | md5sum); kernel_md5="${kernel_md5%% *}" + # md5 checksum of rootfs with EOF marker + local rootfs_md5=$(tar xf $tar_file ${board_dir}/root -O | dd bs=1 count=$rootfs_length | md5sum); rootfs_md5="${rootfs_md5%% *}" + + # + # add tar support to get_image() to use default_do_upgrade() instead? + # + + # take care of restoring a saved config + [ "$SAVE_CONFIG" -eq 1 ] && restore_backup="${MTD_CONFIG_ARGS} -j ${CONF_TAR}" + + # write concatinated kernel + rootfs to flash + tar xf $tar_file ${board_dir}/kernel ${board_dir}/root -O | \ + mtd $restore_backup write - $PART_NAME + + # prepare new u-boot env + if [ "$next_boot_part" = "1" ]; then + echo "bootseq 1,2" > $setenv_script + else + echo "bootseq 2,1" > $setenv_script + fi + + printf "kernel_size_%i 0x%08x\n" $next_boot_part $kernel_length >> $setenv_script + printf "vmlinux_start_addr 0x%08x\n" ${kernel_offset} >> $setenv_script + printf "vmlinux_size 0x%08x\n" ${kernel_length} >> $setenv_script + printf "vmlinux_checksum %s\n" ${kernel_md5} >> $setenv_script + + printf "rootfs_size_%i 0x%08x\n" $next_boot_part $((total_size-kernel_length)) >> $setenv_script + printf "rootfs_start_addr 0x%08x\n" $((kernel_offset+kernel_length)) >> $setenv_script + printf "rootfs_size 0x%08x\n" ${rootfs_length} >> $setenv_script + printf "rootfs_checksum %s\n" ${rootfs_md5} >> $setenv_script + + # store u-boot env changes + fw_setenv -s $setenv_script || { + echo "failed to update U-Boot environment" + return 1 + } +} + +# create /var/lock for the lock "fw_setenv.lock" of fw_setenv +# the rest is copied using ipq806x's RAMFS_COPY_BIN and RAMFS_COPY_DATA +platform_add_ramfs_ubootenv() +{ + mkdir -p $RAM_ROOT/var/lock +} +append sysupgrade_pre_upgrade platform_add_ramfs_ubootenv diff --git a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh index 797caf061..571c9cc8a 100644 --- a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh +++ b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh @@ -5,38 +5,16 @@ RAMFS_COPY_BIN='fw_printenv fw_setenv' RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock' platform_check_image() { - local board=$(board_name) - - case "$board" in - rt-acrh17 |\ - rt-ac58u) - CI_UBIPART="UBI_DEV" - local ubidev=$(nand_find_ubi $CI_UBIPART) - local asus_root=$(nand_find_volume $ubidev jffs2) - - [ -n "$asus_root" ] || return 0 - - cat << EOF -jffs2 partition is still present. -There's probably no space left -to install the filesystem. - -You need to delete the jffs2 partition first: -# ubirmvol /dev/ubi0 --name=jffs2 - -Once this is done. Retry. -EOF - return 1 - ;; - esac - return 0 + return 0; } platform_do_upgrade() { case "$(board_name)" in - rt-acrh17) + asus,rt-ac58u|\ + asus,rt-acrh17) CI_UBIPART="UBI_DEV" CI_KERNPART="linux" + local ubidev=$(nand_find_ubi $CI_UBIPART) local jffs2=$(nand_find_volume $ubidev jffs2) local linux2=$(nand_find_volume $ubidev linux2) @@ -44,33 +22,32 @@ platform_do_upgrade() { [ -n "$linux2" ] && ubirmvol /dev/$ubidev --name=linux2 nand_do_upgrade "$1" ;; - ap148 |\ - ap-dk04.1-c1 |\ - d7800 |\ - nbg6817 |\ - r7500 |\ - r7500v2 |\ - r7800) + linksys,ea8500) + platform_do_upgrade_linksys "$ARGV" + ;; + netgear,d7800 |\ + netgear,r7500 |\ + netgear,r7500v2 |\ + netgear,r7800 |\ + qcom,ap-dk04.1-c1 |\ + qcom,ipq8064-ap148 |\ + zyxel,nbg6817) nand_do_upgrade "$ARGV" ;; - c2600) + openmesh,a42) + PART_NAME="inactive" + platform_do_upgrade_openmesh "$ARGV" + ;; + tplink,c2600) PART_NAME="os-image:rootfs" MTD_CONFIG_ARGS="-s 0x200000" default_do_upgrade "$ARGV" ;; - ea8500) - platform_do_upgrade_linksys "$ARGV" - ;; - vr2600v) + tplink,vr2600v) PART_NAME="kernel:rootfs" MTD_CONFIG_ARGS="-s 0x200000" default_do_upgrade "$ARGV" ;; - rt-ac58u) - CI_UBIPART="UBI_DEV" - CI_KERNPART="linux" - nand_do_upgrade "$1" - ;; *) default_do_upgrade "$ARGV" ;; @@ -79,13 +56,13 @@ platform_do_upgrade() { platform_nand_pre_upgrade() { case "$(board_name)" in - nbg6817) - zyxel_do_upgrade "$1" - ;; - rt-ac58u) + asus,rt-ac58u) CI_UBIPART="UBI_DEV" CI_KERNPART="linux" ;; + zyxel,nbg6817) + zyxel_do_upgrade "$1" + ;; esac } diff --git a/target/linux/ipq806x/base-files/lib/upgrade/zyxel.sh b/target/linux/ipq806x/base-files/lib/upgrade/zyxel.sh index 166bc052c..3efef8f0b 100644 --- a/target/linux/ipq806x/base-files/lib/upgrade/zyxel.sh +++ b/target/linux/ipq806x/base-files/lib/upgrade/zyxel.sh @@ -19,9 +19,8 @@ zyxel_get_rootfs() { zyxel_do_flash() { local tar_file=$1 - local board=$2 - local kernel=$3 - local rootfs=$4 + local kernel=$2 + local rootfs=$3 # keep sure its unbound losetup --detach-all || { @@ -29,14 +28,18 @@ zyxel_do_flash() { reboot -f } + # use the first found directory in the tar archive + local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$') + board_dir=${board_dir%/} + echo "flashing kernel to /dev/${kernel}" - tar xf $tar_file sysupgrade-$board/kernel -O >/dev/$kernel + tar xf $tar_file ${board_dir}/kernel -O >/dev/$kernel echo "flashing rootfs to ${rootfs}" - tar xf $tar_file sysupgrade-$board/root -O >"${rootfs}" + tar xf $tar_file ${board_dir}/root -O >"${rootfs}" # a padded rootfs is needed for overlay fs creation - local offset=$(tar xf $tar_file sysupgrade-$board/root -O | wc -c) + local offset=$(tar xf $tar_file ${board_dir}/root -O | wc -c) [ $offset -lt 65536 ] && { echo Wrong size for rootfs: $offset sleep 10 @@ -74,14 +77,25 @@ zyxel_do_upgrade() { [ -b "${rootfs}" ] || return 1 case "$board" in - nbg6817) - kernel=mmcblk0p4 + zyxel,nbg6817) + case "$rootfs" in + "/dev/mmcblk0p5") + kernel=mmcblk0p4 + ;; + "/dev/mmcblk0p8") + kernel=mmcblk0p7 + ;; + *) + return 1 + ;; + esac ;; *) return 1 + ;; esac - zyxel_do_flash $tar_file $board $kernel $rootfs + zyxel_do_flash $tar_file $kernel $rootfs return 0 } diff --git a/target/linux/ipq806x/config-4.9 b/target/linux/ipq806x/config-4.9 index 6cbc3d3b1..376ffb85c 100644 --- a/target/linux/ipq806x/config-4.9 +++ b/target/linux/ipq806x/config-4.9 @@ -477,7 +477,8 @@ CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" CONFIG_USB=y CONFIG_USB_COMMON=y # CONFIG_USB_EHCI_HCD is not set -# CONFIG_USB_IPQ4019_PHY is not set +CONFIG_USB_IPQ4019_PHY=y +CONFIG_USB_PHY=y CONFIG_USB_SUPPORT=y # CONFIG_USB_UHCI_HCD is not set CONFIG_USE_OF=y @@ -493,3 +494,4 @@ CONFIG_ZBOOT_ROM_BSS=0 CONFIG_ZBOOT_ROM_TEXT=0 CONFIG_ZLIB_DEFLATE=y CONFIG_ZLIB_INFLATE=y +CONFIG_MSM_PCIE=y \ No newline at end of file diff --git a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-c2600.dts b/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-c2600.dts deleted file mode 100644 index 7eeaab155..000000000 --- a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-c2600.dts +++ /dev/null @@ -1,501 +0,0 @@ -#include "qcom-ipq8064-v1.0.dtsi" - -#include - -/ { - model = "TP-Link Archer C2600"; - compatible = "tplink,c2600", "qcom,ipq8064"; - - memory@0 { - reg = <0x42000000 0x1e000000>; - device_type = "memory"; - }; - - reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - rsvd@41200000 { - reg = <0x41200000 0x300000>; - no-map; - }; - }; - - aliases { - serial0 = &uart4; - mdio-gpio0 = &mdio0; - - led-boot = &power; - led-failsafe = &general; - led-running = &power; - led-upgrade = &general; - }; - - chosen { - linux,stdout-path = "serial0:115200n8"; - }; - - soc { - pinmux@800000 { - button_pins: button_pins { - mux { - pins = "gpio16", "gpio54", "gpio65"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - i2c4_pins: i2c4_pinmux { - mux { - pins = "gpio12", "gpio13"; - function = "gsbi4"; - drive-strength = <12>; - bias-disable; - }; - }; - - led_pins: led_pins { - mux { - pins = "gpio6", "gpio7", "gpio8", "gpio9", "gpio26", "gpio33", - "gpio53", "gpio66"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - spi_pins: spi_pins { - mux { - pins = "gpio18", "gpio19", "gpio21"; - function = "gsbi5"; - bias-pull-down; - }; - - data { - pins = "gpio18", "gpio19"; - drive-strength = <10>; - }; - - cs { - pins = "gpio20"; - function = "gpio"; - drive-strength = <10>; - bias-pull-up; - }; - - clk { - pins = "gpio21"; - drive-strength = <12>; - }; - }; - - mdio0_pins: mdio0_pins { - mux { - pins = "gpio0", "gpio1"; - function = "gpio"; - drive-strength = <8>; - bias-disable; - }; - }; - - rgmii2_pins: rgmii2_pins { - mux { - pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", - "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; - function = "rgmii2"; - drive-strength = <8>; - bias-disable; - }; - }; - - usb0_pwr_en_pin: usb0_pwr_en_pin { - mux { - pins = "gpio25"; - function = "gpio"; - drive-strength = <10>; - bias-pull-up; - output-high; - }; - }; - - usb1_pwr_en_pin: usb1_pwr_en_pin { - mux { - pins = "gpio23"; - function = "gpio"; - drive-strength = <10>; - bias-pull-up; - output-high; - }; - }; - }; - - gsbi@16300000 { - qcom,mode = ; - status = "ok"; - serial@16340000 { - status = "ok"; - }; - /* - * The i2c device on gsbi4 should not be enabled. - * On ipq806x designs gsbi4 i2c is meant for exclusive - * RPM usage. Turning this on in kernel manifests as - * i2c failure for the RPM. - */ - }; - - gsbi5: gsbi@1a200000 { - qcom,mode = ; - status = "ok"; - - spi5: spi@1a280000 { - status = "ok"; - - pinctrl-0 = <&spi_pins>; - pinctrl-names = "default"; - - cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_HIGH>; - - flash: m25p80@0 { - compatible = "jedec,spi-nor"; - #address-cells = <1>; - #size-cells = <1>; - spi-max-frequency = <50000000>; - reg = <0>; - - SBL1@0 { - label = "SBL1"; - reg = <0x0 0x20000>; - read-only; - }; - - MIBIB@20000 { - label = "MIBIB"; - reg = <0x20000 0x20000>; - read-only; - }; - - SBL2@40000 { - label = "SBL2"; - reg = <0x40000 0x20000>; - read-only; - }; - - SBL3@60000 { - label = "SBL3"; - reg = <0x60000 0x30000>; - read-only; - }; - - DDRCONFIG@90000 { - label = "DDRCONFIG"; - reg = <0x90000 0x10000>; - read-only; - }; - - SSD@a0000 { - label = "SSD"; - reg = <0xa0000 0x10000>; - read-only; - }; - - TZ@b0000 { - label = "TZ"; - reg = <0xb0000 0x30000>; - read-only; - }; - - RPM@e0000 { - label = "RPM"; - reg = <0xe0000 0x20000>; - read-only; - }; - - fs-uboot@100000 { - label = "fs-uboot"; - reg = <0x100000 0x70000>; - read-only; - }; - - uboot-env@170000 { - label = "uboot-env"; - reg = <0x170000 0x40000>; - read-only; - }; - - radio@1b0000 { - label = "radio"; - reg = <0x1b0000 0x40000>; - read-only; - }; - - os-image@1f0000 { - label = "os-image"; - reg = <0x1f0000 0x200000>; - }; - - rootfs@3f0000 { - label = "rootfs"; - reg = <0x3f0000 0x1b00000>; - }; - - defaultmac: default-mac@1ef0000 { - label = "default-mac"; - reg = <0x1ef0000 0x00200>; - read-only; - }; - - pin@1ef0200 { - label = "pin"; - reg = <0x1ef0200 0x00200>; - read-only; - }; - - product-info@1ef0400 { - label = "product-info"; - reg = <0x1ef0400 0x0fc00>; - read-only; - }; - - partition-table@1f00000 { - label = "partition-table"; - reg = <0x1f00000 0x10000>; - read-only; - }; - - soft-version@1f10000 { - label = "soft-version"; - reg = <0x1f10000 0x10000>; - read-only; - }; - - support-list@1f20000 { - label = "support-list"; - reg = <0x1f20000 0x10000>; - read-only; - }; - - profile@1f30000 { - label = "profile"; - reg = <0x1f30000 0x10000>; - read-only; - }; - - default-config@1f40000 { - label = "default-config"; - reg = <0x1f40000 0x10000>; - read-only; - }; - - user-config@1f50000 { - label = "user-config"; - reg = <0x1f50000 0x40000>; - read-only; - }; - - qos-db@1f90000 { - label = "qos-db"; - reg = <0x1f90000 0x40000>; - read-only; - }; - - usb-config@1fd0000 { - label = "usb-config"; - reg = <0x1fd0000 0x10000>; - read-only; - }; - - log@1fe0000 { - label = "log"; - reg = <0x1fe0000 0x20000>; - read-only; - }; - }; - }; - }; - - phy@100f8800 { /* USB3 port 1 HS phy */ - status = "ok"; - }; - - phy@100f8830 { /* USB3 port 1 SS phy */ - status = "ok"; - }; - - phy@110f8800 { /* USB3 port 0 HS phy */ - status = "ok"; - }; - - phy@110f8830 { /* USB3 port 0 SS phy */ - status = "ok"; - }; - - usb30@0 { - status = "ok"; - - pinctrl-0 = <&usb0_pwr_en_pin>; - pinctrl-names = "default"; - }; - - usb30@1 { - status = "ok"; - - pinctrl-0 = <&usb1_pwr_en_pin>; - pinctrl-names = "default"; - }; - - pcie0: pci@1b500000 { - status = "ok"; - phy-tx0-term-offset = <7>; - }; - - pcie1: pci@1b700000 { - status = "ok"; - phy-tx0-term-offset = <7>; - }; - - mdio0: mdio { - compatible = "virtual,mdio-gpio"; - #address-cells = <1>; - #size-cells = <0>; - gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; - pinctrl-0 = <&mdio0_pins>; - pinctrl-names = "default"; - - phy0: ethernet-phy@0 { - device_type = "ethernet-phy"; - reg = <0>; - qca,ar8327-initvals = < - 0x00004 0x7600000 /* PAD0_MODE */ - 0x00008 0x1000000 /* PAD5_MODE */ - 0x0000c 0x80 /* PAD6_MODE */ - 0x000e4 0x6a545 /* MAC_POWER_SEL */ - 0x000e0 0xc74164de /* SGMII_CTRL */ - 0x0007c 0x4e /* PORT0_STATUS */ - 0x00094 0x4e /* PORT6_STATUS */ - >; - }; - - phy4: ethernet-phy@4 { - device_type = "ethernet-phy"; - reg = <4>; - }; - }; - - gmac1: ethernet@37200000 { - status = "ok"; - phy-mode = "rgmii"; - qcom,id = <1>; - - pinctrl-0 = <&rgmii2_pins>; - pinctrl-names = "default"; - - mtd-mac-address = <&defaultmac 0x8>; - mtd-mac-address-increment = <1>; - - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - gmac2: ethernet@37400000 { - status = "ok"; - phy-mode = "sgmii"; - qcom,id = <2>; - - mtd-mac-address = <&defaultmac 0x8>; - - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - rpm@108000 { - pinctrl-0 = <&i2c4_pins>; - pinctrl-names = "default"; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - pinctrl-0 = <&button_pins>; - pinctrl-names = "default"; - - wifi { - label = "wifi"; - gpios = <&qcom_pinmux 49 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - reset { - label = "reset"; - gpios = <&qcom_pinmux 64 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - wps { - label = "wps"; - gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - ledswitch { - label = "ledswitch"; - gpios = <&qcom_pinmux 16 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; - - gpio-leds { - compatible = "gpio-leds"; - pinctrl-0 = <&led_pins>; - pinctrl-names = "default"; - - lan { - label = "c2600:white:lan"; - gpios = <&qcom_pinmux 6 GPIO_ACTIVE_HIGH>; - }; - - usb4 { - label = "c2600:white:usb_4"; - gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; - }; - - usb2 { - label = "c2600:white:usb_2"; - gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; - }; - - wps { - label = "c2600:white:wps"; - gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; - }; - - wan_amber { - label = "c2600:amber:wan"; - gpios = <&qcom_pinmux 26 GPIO_ACTIVE_LOW>; - }; - - wan_white { - label = "c2600:white:wan"; - gpios = <&qcom_pinmux 33 GPIO_ACTIVE_LOW>; - }; - - power: power { - label = "c2600:white:power"; - gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; - default-state = "keep"; - }; - - general: general { - label = "c2600:white:general"; - gpios = <&qcom_pinmux 66 GPIO_ACTIVE_HIGH>; - }; - }; -}; - -&adm_dma { - status = "ok"; -}; diff --git a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-d7800.dts b/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-d7800.dts deleted file mode 100644 index a8a613945..000000000 --- a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-d7800.dts +++ /dev/null @@ -1,406 +0,0 @@ -#include "qcom-ipq8064-v1.0.dtsi" - -#include - -/ { - model = "Netgear Nighthawk X4 D7800"; - compatible = "netgear,d7800", "qcom,ipq8064"; - - memory@0 { - reg = <0x42000000 0xe000000>; - device_type = "memory"; - }; - - reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - rsvd@41200000 { - reg = <0x41200000 0x300000>; - no-map; - }; - }; - - aliases { - serial0 = &uart4; - mdio-gpio0 = &mdio0; - - led-boot = &power_white; - led-failsafe = &power_amber; - led-running = &power_white; - led-upgrade = &power_amber; - }; - - chosen { - bootargs = "rootfstype=squashfs noinitrd"; - linux,stdout-path = "serial0:115200n8"; - }; - - soc { - pinmux@800000 { - button_pins: button_pins { - mux { - pins = "gpio6", "gpio54", "gpio65"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - i2c4_pins: i2c4_pinmux { - mux { - pins = "gpio12", "gpio13"; - function = "gsbi4"; - drive-strength = <12>; - bias-disable; - }; - }; - - led_pins: led_pins { - mux { - pins = "gpio7", "gpio8", "gpio9", "gpio22", "gpio23", - "gpio24","gpio26", "gpio53", "gpio64"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - mdio0_pins: mdio0_pins { - mux { - pins = "gpio0", "gpio1"; - function = "gpio"; - drive-strength = <8>; - bias-disable; - }; - }; - - nand_pins: nand_pins { - mux { - pins = "gpio34", "gpio35", "gpio36", - "gpio37", "gpio38", "gpio39", - "gpio40", "gpio41", "gpio42", - "gpio43", "gpio44", "gpio45", - "gpio46", "gpio47"; - function = "nand"; - drive-strength = <10>; - bias-disable; - }; - pullups { - pins = "gpio39"; - bias-pull-up; - }; - hold { - pins = "gpio40", "gpio41", "gpio42", - "gpio43", "gpio44", "gpio45", - "gpio46", "gpio47"; - bias-bus-hold; - }; - }; - - rgmii2_pins: rgmii2_pins { - mux { - pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", - "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; - function = "rgmii2"; - drive-strength = <8>; - bias-disable; - }; - }; - - usb0_pwr_en_pins: usb0_pwr_en_pins { - mux { - pins = "gpio15"; - function = "gpio"; - drive-strength = <12>; - bias-pull-down; - output-high; - }; - }; - - usb1_pwr_en_pins: usb1_pwr_en_pins { - mux { - pins = "gpio16", "gpio68"; - function = "gpio"; - drive-strength = <12>; - bias-pull-down; - output-high; - }; - }; - }; - - gsbi@16300000 { - qcom,mode = ; - status = "ok"; - serial@16340000 { - status = "ok"; - }; - /* - * The i2c device on gsbi4 should not be enabled. - * On ipq806x designs gsbi4 i2c is meant for exclusive - * RPM usage. Turning this on in kernel manifests as - * i2c failure for the RPM. - */ - }; - - sata-phy@1b400000 { - status = "ok"; - }; - - sata@29000000 { - status = "ok"; - }; - - phy@100f8800 { /* USB3 port 1 HS phy */ - status = "ok"; - }; - - phy@100f8830 { /* USB3 port 1 SS phy */ - status = "ok"; - }; - - phy@110f8800 { /* USB3 port 0 HS phy */ - status = "ok"; - }; - - phy@110f8830 { /* USB3 port 0 SS phy */ - status = "ok"; - }; - - usb30@0 { - status = "ok"; - - pinctrl-0 = <&usb0_pwr_en_pins>; - pinctrl-names = "default"; - }; - - usb30@1 { - status = "ok"; - - pinctrl-0 = <&usb1_pwr_en_pins>; - pinctrl-names = "default"; - }; - - pcie0: pci@1b500000 { - status = "ok"; - reset-gpio = <&qcom_pinmux 3 GPIO_ACTIVE_HIGH>; - pinctrl-0 = <&pcie0_pins>; - pinctrl-names = "default"; - }; - - pcie1: pci@1b700000 { - status = "ok"; - reset-gpio = <&qcom_pinmux 48 GPIO_ACTIVE_HIGH>; - pinctrl-0 = <&pcie1_pins>; - pinctrl-names = "default"; - }; - - nand@1ac00000 { - status = "ok"; - - pinctrl-0 = <&nand_pins>; - pinctrl-names = "default"; - - nand-ecc-strength = <4>; - nand-bus-width = <8>; - - #address-cells = <1>; - #size-cells = <1>; - - qcadata@0 { - label = "qcadata"; - reg = <0x0000000 0x0c80000>; - read-only; - }; - - APPSBL@c80000 { - label = "APPSBL"; - reg = <0x0c80000 0x0500000>; - read-only; - }; - - APPSBLENV@1180000 { - label = "APPSBLENV"; - reg = <0x1180000 0x0080000>; - read-only; - }; - - art: art@1200000 { - label = "art"; - reg = <0x1200000 0x0140000>; - read-only; - }; - - artbak: art@1340000 { - label = "artbak"; - reg = <0x1340000 0x0140000>; - read-only; - }; - - kernel@1480000 { - label = "kernel"; - reg = <0x1480000 0x0200000>; - }; - - ubi@1680000 { - label = "ubi"; - reg = <0x1680000 0x1E00000>; - }; - - netgear@3480000 { - label = "netgear"; - reg = <0x3480000 0x4480000>; - read-only; - }; - - reserve@7900000 { - label = "reserve"; - reg = <0x7900000 0x0700000>; - read-only; - }; - - firmware@1480000 { - label = "firmware"; - reg = <0x1480000 0x2000000>; - }; - }; - - mdio0: mdio { - compatible = "virtual,mdio-gpio"; - #address-cells = <1>; - #size-cells = <0>; - gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; - pinctrl-0 = <&mdio0_pins>; - pinctrl-names = "default"; - - phy0: ethernet-phy@0 { - device_type = "ethernet-phy"; - reg = <0>; - qca,ar8327-initvals = < - 0x00004 0x7600000 /* PAD0_MODE */ - 0x00008 0x1000000 /* PAD5_MODE */ - 0x0000c 0x80 /* PAD6_MODE */ - 0x000e4 0x6a545 /* MAC_POWER_SEL */ - 0x000e0 0xc74164de /* SGMII_CTRL */ - 0x0007c 0x4e /* PORT0_STATUS */ - 0x00094 0x4e /* PORT6_STATUS */ - >; - }; - - phy4: ethernet-phy@4 { - device_type = "ethernet-phy"; - reg = <4>; - }; - }; - - gmac1: ethernet@37200000 { - status = "ok"; - phy-mode = "rgmii"; - phy-handle = <&phy4>; - qcom,id = <1>; - - pinctrl-0 = <&rgmii2_pins>; - pinctrl-names = "default"; - - mtd-mac-address = <&art 6>; - }; - - gmac2: ethernet@37400000 { - status = "ok"; - phy-mode = "sgmii"; - qcom,id = <2>; - - mtd-mac-address = <&art 0>; - - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - rpm@108000 { - pinctrl-0 = <&i2c4_pins>; - pinctrl-names = "default"; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - pinctrl-0 = <&button_pins>; - pinctrl-names = "default"; - - wifi { - label = "wifi"; - gpios = <&qcom_pinmux 6 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - reset { - label = "reset"; - gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - wps { - label = "wps"; - gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; - - gpio-leds { - compatible = "gpio-leds"; - pinctrl-0 = <&led_pins>; - pinctrl-names = "default"; - - usb1 { - label = "d7800:white:usb1"; - gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; - }; - - usb2 { - label = "d7800:white:usb2"; - gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; - }; - - power_amber: power_amber { - label = "d7800:amber:power"; - gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; - }; - - wan_white { - label = "d7800:white:wan"; - gpios = <&qcom_pinmux 22 GPIO_ACTIVE_HIGH>; - }; - - wan_amber { - label = "d7800:amber:wan"; - gpios = <&qcom_pinmux 23 GPIO_ACTIVE_HIGH>; - }; - - wps { - label = "d7800:white:wps"; - gpios = <&qcom_pinmux 24 GPIO_ACTIVE_HIGH>; - }; - - esata { - label = "d7800:white:esata"; - gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>; - }; - - power_white: power_white { - label = "d7800:white:power"; - gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; - default-state = "keep"; - }; - - wifi { - label = "d7800:white:wifi"; - gpios = <&qcom_pinmux 64 GPIO_ACTIVE_HIGH>; - }; - }; -}; - -&adm_dma { - status = "ok"; -}; diff --git a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-ea8500.dts b/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-ea8500.dts deleted file mode 100644 index b5840e871..000000000 --- a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-ea8500.dts +++ /dev/null @@ -1,399 +0,0 @@ -#include "qcom-ipq8064-v1.0.dtsi" - -#include - -/ { - model = "Linksys EA8500 WiFi Router"; - compatible = "linksys,ea8500", "qcom,ipq8064"; - - memory@0 { - reg = <0x42000000 0x1e000000>; - device_type = "memory"; - }; - - reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - rsvd@41200000 { - reg = <0x41200000 0x300000>; - no-map; - }; - }; - - aliases { - serial0 = &uart4; - mdio-gpio0 = &mdio0; - - led-boot = &power; - led-failsafe = &power; - led-running = &power; - led-upgrade = &power; - }; - - chosen { - bootargs = "console=ttyMSM0,115200n8"; - linux,stdout-path = "serial0:115200n8"; - append-rootblock = "ubi.mtd="; /* append to bootargs adding the root deviceblock nbr from bootloader */ - }; - - soc { - pinmux@800000 { - button_pins: button_pins { - mux { - pins = "gpio65", "gpio67", "gpio68"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - i2c4_pins: i2c4_pinmux { - mux { - pins = "gpio12", "gpio13"; - function = "gsbi4"; - drive-strength = <12>; - bias-disable; - }; - }; - - led_pins: led_pins { - mux { - pins = "gpio6", "gpio53", "gpio54"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - mdio0_pins: mdio0_pins { - mux { - pins = "gpio0", "gpio1"; - function = "gpio"; - drive-strength = <8>; - bias-disable; - }; - }; - - nand_pins: nand_pins { - mux { - pins = "gpio34", "gpio35", "gpio36", - "gpio37", "gpio38", "gpio39", - "gpio40", "gpio41", "gpio42", - "gpio43", "gpio44", "gpio45", - "gpio46", "gpio47"; - function = "nand"; - drive-strength = <10>; - bias-disable; - }; - pullups { - pins = "gpio39"; - bias-pull-up; - }; - hold { - pins = "gpio40", "gpio41", "gpio42", - "gpio43", "gpio44", "gpio45", - "gpio46", "gpio47"; - bias-bus-hold; - }; - }; - - rgmii2_pins: rgmii2_pins { - mux { - pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", - "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; - function = "rgmii2"; - drive-strength = <8>; - bias-disable; - }; - }; - }; - - gsbi@16300000 { - qcom,mode = ; - status = "ok"; - serial@16340000 { - status = "ok"; - }; - /* - * The i2c device on gsbi4 should not be enabled. - * On ipq806x designs gsbi4 i2c is meant for exclusive - * RPM usage. Turning this on in kernel manifests as - * i2c failure for the RPM. - */ - }; - - sata-phy@1b400000 { - status = "ok"; - }; - - sata@29000000 { - status = "ok"; - }; - - phy@100f8800 { /* USB3 port 1 HS phy */ - status = "ok"; - }; - - phy@100f8830 { /* USB3 port 1 SS phy */ - status = "ok"; - }; - - phy@110f8800 { /* USB3 port 0 HS phy */ - status = "ok"; - }; - - phy@110f8830 { /* USB3 port 0 SS phy */ - status = "ok"; - }; - - usb30@0 { - status = "ok"; - }; - - usb30@1 { - status = "ok"; - }; - - pcie0: pci@1b500000 { - status = "ok"; - phy-tx0-term-offset = <7>; - }; - - pcie1: pci@1b700000 { - status = "ok"; - phy-tx0-term-offset = <7>; - }; - - pcie2: pci@1b900000 { - status = "ok"; - phy-tx0-term-offset = <7>; - }; - - nand@1ac00000 { - status = "ok"; - - pinctrl-0 = <&nand_pins>; - pinctrl-names = "default"; - - nand-ecc-strength = <4>; - nand-bus-width = <8>; - - #address-cells = <1>; - #size-cells = <1>; - - SBL1@0 { - label = "SBL1"; - reg = <0x0000000 0x0040000>; - read-only; - }; - - MIBIB@40000 { - label = "MIBIB"; - reg = <0x0040000 0x0140000>; - read-only; - }; - - SBL2@180000 { - label = "SBL2"; - reg = <0x0180000 0x0140000>; - read-only; - }; - - SBL3@2c0000 { - label = "SBL3"; - reg = <0x02c0000 0x0280000>; - read-only; - }; - - DDRCONFIG@540000 { - label = "DDRCONFIG"; - reg = <0x0540000 0x0120000>; - read-only; - }; - - SSD@660000 { - label = "SSD"; - reg = <0x0660000 0x0120000>; - read-only; - }; - - TZ@780000 { - label = "TZ"; - reg = <0x0780000 0x0280000>; - read-only; - }; - - RPM@a00000 { - label = "RPM"; - reg = <0x0a00000 0x0280000>; - read-only; - }; - - art: art@c80000 { - label = "art"; - reg = <0x0c80000 0x0140000>; - read-only; - }; - - APPSBL@dc0000 { - label = "APPSBL"; - reg = <0x0dc0000 0x0100000>; - read-only; - }; - - u_env@ec0000 { - label = "u_env"; - reg = <0x0ec0000 0x0040000>; - }; - - s_env@f00000 { - label = "s_env"; - reg = <0x0f00000 0x0040000>; - }; - - devinfo@f40000 { - label = "devinfo"; - reg = <0x0f40000 0x0040000>; - }; - - linux@f80000 { - label = "kernel1"; - reg = <0x0f80000 0x2800000>; /* 3 MB spill to rootfs*/ - }; - - rootfs@1280000 { - label = "rootfs1"; - reg = <0x1280000 0x2500000>; - }; - - linux2@3780000 { - label = "kernel2"; - reg = <0x3780000 0x2800000>; - }; - - rootfs2@3a80000 { - label = "rootfs2"; - reg = <0x3a80000 0x2500000>; - }; - - syscfg@5f80000 { - label = "syscfg"; - reg = <0x5f80000 0x2080000>; - }; - }; - - mdio0: mdio { - compatible = "virtual,mdio-gpio"; - #address-cells = <1>; - #size-cells = <0>; - gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; - pinctrl-0 = <&mdio0_pins>; - pinctrl-names = "default"; - - phy0: ethernet-phy@0 { - device_type = "ethernet-phy"; - reg = <0>; - qca,ar8327-initvals = < - 0x00004 0x7600000 /* PAD0_MODE */ - 0x00008 0x1000000 /* PAD5_MODE */ - 0x0000c 0x80 /* PAD6_MODE */ - 0x000e4 0x6a545 /* MAC_POWER_SEL */ - 0x000e0 0xc74164de /* SGMII_CTRL */ - 0x0007c 0x4e /* PORT0_STATUS */ - 0x00094 0x4e /* PORT6_STATUS */ - >; - }; - - phy4: ethernet-phy@4 { - device_type = "ethernet-phy"; - reg = <4>; - }; - }; - - gmac1: ethernet@37200000 { - status = "ok"; - phy-mode = "rgmii"; - qcom,id = <1>; - qcom,phy_mdio_addr = <4>; - qcom,poll_required = <1>; - qcom,rgmii_delay = <0>; - qcom,emulation = <0>; - pinctrl-0 = <&rgmii2_pins>; - pinctrl-names = "default"; - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - //lan - gmac2: ethernet@37400000 { - status = "ok"; - phy-mode = "sgmii"; - qcom,id = <2>; - qcom,phy_mdio_addr = <0>; /* none */ - qcom,poll_required = <0>; /* no polling */ - qcom,rgmii_delay = <0>; - qcom,emulation = <0>; - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - rpm@108000 { - pinctrl-0 = <&i2c4_pins>; - pinctrl-names = "default"; - }; - - adm_dma: dma@18300000 { - status = "ok"; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - pinctrl-0 = <&button_pins>; - pinctrl-names = "default"; - - wifi { - label = "wifi"; - gpios = <&qcom_pinmux 67 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - reset { - label = "reset"; - gpios = <&qcom_pinmux 68 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - wps { - label = "wps"; - gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; - - gpio-leds { - compatible = "gpio-leds"; - pinctrl-0 = <&led_pins>; - pinctrl-names = "default"; - - wps { - label = "ea8500:green:wps"; - gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; - }; - - power: power { - label = "ea8500:white:power"; - gpios = <&qcom_pinmux 6 GPIO_ACTIVE_LOW>; - default-state = "keep"; - }; - - wifi { - label = "ea8500:green:wifi"; - gpios = <&qcom_pinmux 54 GPIO_ACTIVE_HIGH>; - }; - }; -}; diff --git a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-r7500.dts b/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-r7500.dts deleted file mode 100644 index fc35df7e6..000000000 --- a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-r7500.dts +++ /dev/null @@ -1,373 +0,0 @@ -#include "qcom-ipq8064-v1.0.dtsi" - -#include - -/ { - model = "Netgear Nighthawk X4 R7500"; - compatible = "netgear,r7500", "qcom,ipq8064"; - - memory@0 { - reg = <0x42000000 0xe000000>; - device_type = "memory"; - }; - - reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - rsvd@41200000 { - reg = <0x41200000 0x300000>; - no-map; - }; - }; - - aliases { - serial0 = &uart4; - mdio-gpio0 = &mdio0; - - led-boot = &power_white; - led-failsafe = &power_amber; - led-running = &power_white; - led-upgrade = &power_amber; - }; - - chosen { - bootargs = "rootfstype=squashfs noinitrd"; - linux,stdout-path = "serial0:115200n8"; - }; - - soc { - pinmux@800000 { - button_pins: button_pins { - mux { - pins = "gpio6", "gpio54", "gpio65"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - i2c4_pins: i2c4_pinmux { - mux { - pins = "gpio12", "gpio13"; - function = "gsbi4"; - drive-strength = <12>; - bias-disable; - }; - }; - - led_pins: led_pins { - mux { - pins = "gpio7", "gpio8", "gpio9", "gpio22", "gpio23", - "gpio24","gpio26", "gpio53", "gpio64"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - mdio0_pins: mdio0_pins { - mux { - pins = "gpio0", "gpio1"; - function = "gpio"; - drive-strength = <8>; - bias-disable; - }; - }; - - nand_pins: nand_pins { - mux { - pins = "gpio34", "gpio35", "gpio36", - "gpio37", "gpio38", "gpio39", - "gpio40", "gpio41", "gpio42", - "gpio43", "gpio44", "gpio45", - "gpio46", "gpio47"; - function = "nand"; - drive-strength = <10>; - bias-disable; - }; - pullups { - pins = "gpio39"; - bias-pull-up; - }; - hold { - pins = "gpio40", "gpio41", "gpio42", - "gpio43", "gpio44", "gpio45", - "gpio46", "gpio47"; - bias-bus-hold; - }; - }; - - rgmii2_pins: rgmii2_pins { - mux { - pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", - "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; - function = "rgmii2"; - drive-strength = <8>; - bias-disable; - }; - }; - }; - - gsbi@16300000 { - qcom,mode = ; - status = "ok"; - serial@16340000 { - status = "ok"; - }; - /* - * The i2c device on gsbi4 should not be enabled. - * On ipq806x designs gsbi4 i2c is meant for exclusive - * RPM usage. Turning this on in kernel manifests as - * i2c failure for the RPM. - */ - }; - - sata-phy@1b400000 { - status = "ok"; - }; - - sata@29000000 { - status = "ok"; - }; - - phy@100f8800 { /* USB3 port 1 HS phy */ - status = "ok"; - }; - - phy@100f8830 { /* USB3 port 1 SS phy */ - status = "ok"; - }; - - phy@110f8800 { /* USB3 port 0 HS phy */ - status = "ok"; - }; - - phy@110f8830 { /* USB3 port 0 SS phy */ - status = "ok"; - }; - - usb30@0 { - status = "ok"; - }; - - usb30@1 { - status = "ok"; - }; - - pcie0: pci@1b500000 { - status = "ok"; - }; - - pcie1: pci@1b700000 { - status = "ok"; - }; - - nand@1ac00000 { - status = "ok"; - - pinctrl-0 = <&nand_pins>; - pinctrl-names = "default"; - - nand-ecc-strength = <4>; - nand-bus-width = <8>; - - #address-cells = <1>; - #size-cells = <1>; - - qcadata@0 { - label = "qcadata"; - reg = <0x0000000 0x0c80000>; - read-only; - }; - - APPSBL@c80000 { - label = "APPSBL"; - reg = <0x0c80000 0x0500000>; - read-only; - }; - - APPSBLENV@1180000 { - label = "APPSBLENV"; - reg = <0x1180000 0x0080000>; - read-only; - }; - - art: art@1200000 { - label = "art"; - reg = <0x1200000 0x0140000>; - read-only; - }; - - kernel@1340000 { - label = "kernel"; - reg = <0x1340000 0x0200000>; - }; - - ubi@1540000 { - label = "ubi"; - reg = <0x1540000 0x1800000>; - }; - - netgear@2d40000 { - label = "netgear"; - reg = <0x2d40000 0x0c00000>; - read-only; - }; - - reserve@3940000 { - label = "reserve"; - reg = <0x3940000 0x46c0000>; - read-only; - }; - - firmware@1340000 { - label = "firmware"; - reg = <0x1340000 0x1a00000>; - }; - - }; - - mdio0: mdio { - compatible = "virtual,mdio-gpio"; - #address-cells = <1>; - #size-cells = <0>; - gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; - pinctrl-0 = <&mdio0_pins>; - pinctrl-names = "default"; - - phy0: ethernet-phy@0 { - device_type = "ethernet-phy"; - reg = <0>; - qca,ar8327-initvals = < - 0x00004 0x7600000 /* PAD0_MODE */ - 0x00008 0x1000000 /* PAD5_MODE */ - 0x0000c 0x80 /* PAD6_MODE */ - 0x000e4 0x6a545 /* MAC_POWER_SEL */ - 0x000e0 0xc74164de /* SGMII_CTRL */ - 0x0007c 0x4e /* PORT0_STATUS */ - 0x00094 0x4e /* PORT6_STATUS */ - >; - }; - - phy4: ethernet-phy@4 { - device_type = "ethernet-phy"; - reg = <4>; - }; - }; - - gmac1: ethernet@37200000 { - status = "ok"; - phy-mode = "rgmii"; - qcom,id = <1>; - - pinctrl-0 = <&rgmii2_pins>; - pinctrl-names = "default"; - - mtd-mac-address = <&art 6>; - - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - gmac2: ethernet@37400000 { - status = "ok"; - phy-mode = "sgmii"; - qcom,id = <2>; - - mtd-mac-address = <&art 0>; - - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - rpm@108000 { - pinctrl-0 = <&i2c4_pins>; - pinctrl-names = "default"; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - pinctrl-0 = <&button_pins>; - pinctrl-names = "default"; - - wifi { - label = "wifi"; - gpios = <&qcom_pinmux 6 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - reset { - label = "reset"; - gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - wps { - label = "wps"; - gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; - - gpio-leds { - compatible = "gpio-leds"; - pinctrl-0 = <&led_pins>; - pinctrl-names = "default"; - - usb1 { - label = "r7500:white:usb1"; - gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; - }; - - usb2 { - label = "r7500:white:usb2"; - gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; - }; - - power_amber: power_amber { - label = "r7500:amber:power"; - gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; - }; - - wan_white { - label = "r7500:white:wan"; - gpios = <&qcom_pinmux 22 GPIO_ACTIVE_HIGH>; - }; - - wan_amber { - label = "r7500:amber:wan"; - gpios = <&qcom_pinmux 23 GPIO_ACTIVE_HIGH>; - }; - - wps { - label = "r7500:white:wps"; - gpios = <&qcom_pinmux 24 GPIO_ACTIVE_HIGH>; - }; - - esata { - label = "r7500:white:esata"; - gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>; - }; - - power_white: power_white { - label = "r7500:white:power"; - gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; - default-state = "keep"; - }; - - wifi { - label = "r7500:white:wifi"; - gpios = <&qcom_pinmux 64 GPIO_ACTIVE_HIGH>; - }; - }; -}; - -&adm_dma { - status = "ok"; -}; diff --git a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-r7500v2.dts b/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-r7500v2.dts deleted file mode 100644 index 4edfbeb72..000000000 --- a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-r7500v2.dts +++ /dev/null @@ -1,416 +0,0 @@ -#include "qcom-ipq8064-v1.0.dtsi" - -#include - -/ { - model = "Netgear Nighthawk X4 R7500v2"; - compatible = "netgear,r7500v2", "qcom,ipq8064"; - - memory@0 { - reg = <0x42000000 0x1e000000>; - device_type = "memory"; - }; - - reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - rsvd@41200000 { - reg = <0x41200000 0x300000>; - no-map; - }; - - rsvd@5fe00000 { - reg = <0x5fe00000 0x200000>; - reusable; - }; - }; - - aliases { - serial0 = &uart4; - mdio-gpio0 = &mdio0; - - led-boot = &power; - led-failsafe = &power; - led-running = &power; - led-upgrade = &power; - }; - - chosen { - bootargs = "rootfstype=squashfs noinitrd"; - linux,stdout-path = "serial0:115200n8"; - }; - - soc { - pinmux@800000 { - button_pins: button_pins { - mux { - pins = "gpio6", "gpio54", "gpio65"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - i2c4_pins: i2c4_pinmux { - mux { - pins = "gpio12", "gpio13"; - function = "gsbi4"; - drive-strength = <12>; - bias-disable; - }; - }; - - led_pins: led_pins { - mux { - pins = "gpio7", "gpio8", "gpio9", "gpio22", "gpio23", - "gpio24","gpio26", "gpio53", "gpio64"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - mdio0_pins: mdio0_pins { - mux { - pins = "gpio0", "gpio1"; - function = "gpio"; - drive-strength = <8>; - bias-disable; - }; - }; - - nand_pins: nand_pins { - mux { - pins = "gpio34", "gpio35", "gpio36", - "gpio37", "gpio38", "gpio39", - "gpio40", "gpio41", "gpio42", - "gpio43", "gpio44", "gpio45", - "gpio46", "gpio47"; - function = "nand"; - drive-strength = <10>; - bias-disable; - }; - pullups { - pins = "gpio39"; - bias-pull-up; - }; - hold { - pins = "gpio40", "gpio41", "gpio42", - "gpio43", "gpio44", "gpio45", - "gpio46", "gpio47"; - bias-bus-hold; - }; - }; - - rgmii2_pins: rgmii2_pins { - mux { - pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", - "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; - function = "rgmii2"; - drive-strength = <8>; - bias-disable; - }; - }; - - usb0_pwr_en_pins: usb0_pwr_en_pins { - mux { - pins = "gpio15"; - function = "gpio"; - drive-strength = <12>; - bias-pull-down; - output-high; - }; - }; - - usb1_pwr_en_pins: usb1_pwr_en_pins { - mux { - pins = "gpio16", "gpio68"; - function = "gpio"; - drive-strength = <12>; - bias-pull-down; - output-high; - }; - }; - }; - - gsbi@16300000 { - qcom,mode = ; - status = "ok"; - serial@16340000 { - status = "ok"; - }; - /* - * The i2c device on gsbi4 should not be enabled. - * On ipq806x designs gsbi4 i2c is meant for exclusive - * RPM usage. Turning this on in kernel manifests as - * i2c failure for the RPM. - */ - }; - - sata-phy@1b400000 { - status = "ok"; - }; - - sata@29000000 { - status = "ok"; - }; - - phy@100f8800 { /* USB3 port 1 HS phy */ - status = "ok"; - }; - - phy@100f8830 { /* USB3 port 1 SS phy */ - status = "ok"; - }; - - phy@110f8800 { /* USB3 port 0 HS phy */ - status = "ok"; - }; - - phy@110f8830 { /* USB3 port 0 SS phy */ - status = "ok"; - }; - - usb30@0 { - status = "ok"; - - pinctrl-0 = <&usb0_pwr_en_pins>; - pinctrl-names = "default"; - }; - - usb30@1 { - status = "ok"; - - pinctrl-0 = <&usb1_pwr_en_pins>; - pinctrl-names = "default"; - }; - - pcie0: pci@1b500000 { - status = "ok"; - reset-gpio = <&qcom_pinmux 3 GPIO_ACTIVE_LOW>; - pinctrl-0 = <&pcie0_pins>; - pinctrl-names = "default"; - }; - - pcie1: pci@1b700000 { - status = "ok"; - reset-gpio = <&qcom_pinmux 48 GPIO_ACTIVE_LOW>; - pinctrl-0 = <&pcie1_pins>; - pinctrl-names = "default"; - }; - - nand@1ac00000 { - status = "ok"; - - pinctrl-0 = <&nand_pins>; - pinctrl-names = "default"; - - nand-ecc-strength = <4>; - nand-bus-width = <8>; - - #address-cells = <1>; - #size-cells = <1>; - - qcadata@0 { - label = "qcadata"; - reg = <0x0000000 0x0c80000>; - read-only; - }; - - APPSBL@c80000 { - label = "APPSBL"; - reg = <0x0c80000 0x0500000>; - read-only; - }; - - APPSBLENV@1180000 { - label = "APPSBLENV"; - reg = <0x1180000 0x0080000>; - read-only; - }; - - art: art@1200000 { - label = "art"; - reg = <0x1200000 0x0140000>; - read-only; - }; - - artbak: art@1340000 { - label = "artbak"; - reg = <0x1340000 0x0140000>; - read-only; - }; - - kernel@1480000 { - label = "kernel"; - reg = <0x1480000 0x0200000>; - }; - - ubi@1680000 { - label = "ubi"; - reg = <0x1680000 0x1E00000>; - }; - - netgear@3480000 { - label = "netgear"; - reg = <0x3480000 0x4480000>; - read-only; - }; - - reserve@7900000 { - label = "reserve"; - reg = <0x7900000 0x0700000>; - read-only; - }; - - firmware@1480000 { - label = "firmware"; - reg = <0x1480000 0x2000000>; - }; - - }; - - mdio0: mdio { - compatible = "virtual,mdio-gpio"; - #address-cells = <1>; - #size-cells = <0>; - gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; - pinctrl-0 = <&mdio0_pins>; - pinctrl-names = "default"; - - phy0: ethernet-phy@0 { - device_type = "ethernet-phy"; - reg = <0>; - qca,ar8327-initvals = < - 0x00004 0x7600000 /* PAD0_MODE */ - 0x00008 0x1000000 /* PAD5_MODE */ - 0x0000c 0x80 /* PAD6_MODE */ - 0x000e4 0xaa545 /* MAC_POWER_SEL */ - 0x000e0 0xc74164de /* SGMII_CTRL */ - 0x0007c 0x4e /* PORT0_STATUS */ - 0x00094 0x4e /* PORT6_STATUS */ - >; - }; - - phy4: ethernet-phy@4 { - device_type = "ethernet-phy"; - reg = <4>; - }; - }; - - gmac1: ethernet@37200000 { - status = "ok"; - phy-mode = "rgmii"; - qcom,id = <1>; - - pinctrl-0 = <&rgmii2_pins>; - pinctrl-names = "default"; - - mtd-mac-address = <&art 6>; - - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - gmac2: ethernet@37400000 { - status = "ok"; - phy-mode = "sgmii"; - qcom,id = <2>; - - mtd-mac-address = <&art 0>; - - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - rpm@108000 { - pinctrl-0 = <&i2c4_pins>; - pinctrl-names = "default"; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - pinctrl-0 = <&button_pins>; - pinctrl-names = "default"; - - wifi { - label = "wifi"; - gpios = <&qcom_pinmux 6 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - reset { - label = "reset"; - gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - wps { - label = "wps"; - gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; - - gpio-leds { - compatible = "gpio-leds"; - pinctrl-0 = <&led_pins>; - pinctrl-names = "default"; - - usb1 { - label = "r7500v2:amber:usb1"; - gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; - }; - - usb3 { - label = "r7500v2:amber:usb3"; - gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; - }; - - status { - label = "r7500v2:amber:status"; - gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; - }; - - internet { - label = "r7500v2:white:internet"; - gpios = <&qcom_pinmux 22 GPIO_ACTIVE_HIGH>; - }; - - wan { - label = "r7500v2:white:wan"; - gpios = <&qcom_pinmux 23 GPIO_ACTIVE_HIGH>; - }; - - wps { - label = "r7500v2:white:wps"; - gpios = <&qcom_pinmux 24 GPIO_ACTIVE_HIGH>; - }; - - esata { - label = "r7500v2:white:esata"; - gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>; - }; - - power: power { - label = "r7500v2:white:power"; - gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; - default-state = "keep"; - }; - - wifi { - label = "r7500v2:white:wifi"; - gpios = <&qcom_pinmux 64 GPIO_ACTIVE_HIGH>; - }; - }; -}; - -&adm_dma { - status = "ok"; -}; diff --git a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-vr2600v.dts b/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-vr2600v.dts deleted file mode 100644 index 407c180ec..000000000 --- a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8064-vr2600v.dts +++ /dev/null @@ -1,425 +0,0 @@ -#include "qcom-ipq8064-v1.0.dtsi" - -#include - -/ { - model = "TP-Link Archer VR2600v"; - compatible = "tplink,vr2600v", "qcom,ipq8064"; - - memory@0 { - reg = <0x42000000 0x1e000000>; - device_type = "memory"; - }; - - reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - rsvd@41200000 { - reg = <0x41200000 0x300000>; - no-map; - }; - }; - - aliases { - serial0 = &uart4; - mdio-gpio0 = &mdio0; - - led-boot = &power; - led-failsafe = &general; - led-running = &power; - led-upgrade = &general; - }; - - chosen { - linux,stdout-path = "serial0:115200n8"; - }; - - soc { - pinmux@800000 { - led_pins: led_pins { - mux { - pins = "gpio7", "gpio8", "gpio9", "gpio16", "gpio17", - "gpio26", "gpio53", "gpio56", "gpio66"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - i2c4_pins: i2c4_pinmux { - mux { - pins = "gpio12", "gpio13"; - function = "gsbi4"; - drive-strength = <12>; - bias-disable; - }; - }; - - button_pins: button_pins { - mux { - pins = "gpio54", "gpio64", "gpio65", "gpio67", "gpio68"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - spi_pins: spi_pins { - mux { - pins = "gpio18", "gpio19", "gpio21"; - function = "gsbi5"; - bias-pull-down; - }; - - data { - pins = "gpio18", "gpio19"; - drive-strength = <10>; - }; - - cs { - pins = "gpio20"; - drive-strength = <10>; - bias-pull-up; - }; - - clk { - pins = "gpio21"; - drive-strength = <12>; - }; - }; - - mdio0_pins: mdio0_pins { - mux { - pins = "gpio0", "gpio1"; - function = "gpio"; - drive-strength = <8>; - bias-disable; - }; - }; - - rgmii2_pins: rgmii2_pins { - mux { - pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", - "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; - function = "rgmii2"; - drive-strength = <8>; - bias-disable; - }; - }; - }; - - gsbi@16300000 { - qcom,mode = ; - status = "ok"; - serial@16340000 { - status = "ok"; - }; - /* - * The i2c device on gsbi4 should not be enabled. - * On ipq806x designs gsbi4 i2c is meant for exclusive - * RPM usage. Turning this on in kernel manifests as - * i2c failure for the RPM. - */ - }; - - gsbi5: gsbi@1a200000 { - qcom,mode = ; - status = "ok"; - - spi4: spi@1a280000 { - status = "ok"; - - pinctrl-0 = <&spi_pins>; - pinctrl-names = "default"; - - cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_HIGH>; - - flash: W25Q128@0 { - compatible = "jedec,spi-nor"; - #address-cells = <1>; - #size-cells = <1>; - spi-max-frequency = <50000000>; - reg = <0>; - - SBL1@0 { - label = "SBL1"; - reg = <0x0 0x20000>; - read-only; - }; - - MIBIB@20000 { - label = "MIBIB"; - reg = <0x20000 0x20000>; - read-only; - }; - - SBL2@40000 { - label = "SBL2"; - reg = <0x40000 0x40000>; - read-only; - }; - - SBL3@80000 { - label = "SBL3"; - reg = <0x80000 0x80000>; - read-only; - }; - - DDRCONFIG@100000 { - label = "DDRCONFIG"; - reg = <0x100000 0x10000>; - read-only; - }; - - SSD@110000 { - label = "SSD"; - reg = <0x110000 0x10000>; - read-only; - }; - - TZ@120000 { - label = "TZ"; - reg = <0x120000 0x80000>; - read-only; - }; - - RPM@1a0000 { - label = "RPM"; - reg = <0x1a0000 0x80000>; - read-only; - }; - - APPSBL@220000 { - label = "APPSBL"; - reg = <0x220000 0x80000>; - read-only; - }; - - APPSBLENV@2a0000 { - label = "APPSBLENV"; - reg = <0x2a0000 0x40000>; - read-only; - }; - - OLDART@2e0000 { - label = "OLDART"; - reg = <0x2e0000 0x40000>; - read-only; - }; - - kernel@320000 { - label = "kernel"; - reg = <0x320000 0x200000>; - }; - - rootfs@520000 { - label = "rootfs"; - reg = <0x520000 0xa60000>; - }; - - defaultmac: default-mac@0xfaf100 { - label = "default-mac"; - reg = <0xfaf100 0x00200>; - read-only; - }; - - ART@fc0000 { - label = "ART"; - reg = <0xfc0000 0x40000>; - read-only; - }; - }; - }; - }; - - phy@100f8800 { /* USB3 port 1 HS phy */ - status = "ok"; - }; - - phy@100f8830 { /* USB3 port 1 SS phy */ - status = "ok"; - }; - - phy@110f8800 { /* USB3 port 0 HS phy */ - status = "ok"; - }; - - phy@110f8830 { /* USB3 port 0 SS phy */ - status = "ok"; - }; - - usb30@0 { - status = "ok"; - }; - - usb30@1 { - status = "ok"; - }; - - pcie0: pci@1b500000 { - status = "ok"; - phy-tx0-term-offset = <7>; - }; - - pcie1: pci@1b700000 { - status = "ok"; - phy-tx0-term-offset = <7>; - }; - - mdio0: mdio { - compatible = "virtual,mdio-gpio"; - #address-cells = <1>; - #size-cells = <0>; - gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; - pinctrl-0 = <&mdio0_pins>; - pinctrl-names = "default"; - - phy0: ethernet-phy@0 { - device_type = "ethernet-phy"; - reg = <0>; - qca,ar8327-initvals = < - 0x00004 0x7600000 /* PAD0_MODE */ - 0x00008 0x1000000 /* PAD5_MODE */ - 0x0000c 0x80 /* PAD6_MODE */ - 0x000e4 0x6a545 /* MAC_POWER_SEL */ - 0x000e0 0xc74164de /* SGMII_CTRL */ - 0x0007c 0x4e /* PORT0_STATUS */ - 0x00094 0x4e /* PORT6_STATUS */ - >; - }; - - phy4: ethernet-phy@4 { - device_type = "ethernet-phy"; - reg = <4>; - }; - }; - - gmac1: ethernet@37200000 { - status = "ok"; - phy-mode = "rgmii"; - qcom,id = <1>; - - pinctrl-0 = <&rgmii2_pins>; - pinctrl-names = "default"; - - mtd-mac-address = <&defaultmac 0>; - mtd-mac-address-increment = <1>; - - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - gmac2: ethernet@37400000 { - status = "ok"; - phy-mode = "sgmii"; - qcom,id = <2>; - - mtd-mac-address = <&defaultmac 0>; - - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - rpm@108000 { - pinctrl-0 = <&i2c4_pins>; - pinctrl-names = "default"; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - pinctrl-0 = <&button_pins>; - pinctrl-names = "default"; - - wifi { - label = "wifi"; - gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - reset { - label = "reset"; - gpios = <&qcom_pinmux 64 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - wps { - label = "wps"; - gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - dect { - label = "dect"; - gpios = <&qcom_pinmux 67 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - ledswitch { - label = "ledswitch"; - gpios = <&qcom_pinmux 68 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; - - gpio-leds { - compatible = "gpio-leds"; - pinctrl-0 = <&led_pins>; - pinctrl-names = "default"; - - dsl { - label = "vr2600v:white:dsl"; - gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; - }; - - usb { - label = "vr2600v:white:usb"; - gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; - }; - - lan { - label = "vr2600v:white:lan"; - gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; - }; - - wlan2g { - label = "vr2600v:white:wlan2g"; - gpios = <&qcom_pinmux 16 GPIO_ACTIVE_HIGH>; - }; - - wlan5g { - label = "vr2600v:white:wlan5g"; - gpios = <&qcom_pinmux 17 GPIO_ACTIVE_HIGH>; - }; - - power: power { - label = "vr2600v:white:power"; - gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>; - default-state = "keep"; - }; - - phone { - label = "vr2600v:white:phone"; - gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; - }; - - wan { - label = "vr2600v:white:wan"; - gpios = <&qcom_pinmux 56 GPIO_ACTIVE_HIGH>; - }; - - general: general { - label = "vr2600v:white:general"; - gpios = <&qcom_pinmux 66 GPIO_ACTIVE_HIGH>; - }; - }; -}; - -&adm_dma { - status = "ok"; -}; diff --git a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8065-nbg6817.dts b/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8065-nbg6817.dts deleted file mode 100644 index 4db1a3059..000000000 --- a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8065-nbg6817.dts +++ /dev/null @@ -1,388 +0,0 @@ -#include "qcom-ipq8065-v1.0.dtsi" - -#include - -/ { - model = "ZyXEL NBG6817"; - compatible = "zyxel,nbg6817", "qcom,ipq8065"; - - memory@0 { - reg = <0x42000000 0x1e000000>; - device_type = "memory"; - }; - - reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - rsvd@41200000 { - reg = <0x41200000 0x300000>; - no-map; - }; - }; - - aliases { - serial0 = &uart4; - mdio-gpio0 = &mdio0; - sdcc1 = &sdcc1; - - led-boot = &power; - led-failsafe = &power; - led-running = &power; - led-upgrade = &power; - }; - - chosen { - bootargs = "root=/dev/mmcblk0p5 rootfstype=squashfs,ext4 rootwait noinitrd"; - linux,stdout-path = "serial0:115200n8"; - }; - - soc { - pinmux@800000 { - button_pins: button_pins { - mux { - pins = "gpio6", "gpio54", "gpio65"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - i2c4_pins: i2c4_pinmux { - mux { - pins = "gpio12", "gpio13"; - function = "gsbi4"; - drive-strength = <12>; - bias-disable; - }; - }; - - led_pins: led_pins { - mux { - pins = "gpio9", "gpio26", "gpio33", "gpio64"; - function = "gpio"; - drive-strength = <2>; - bias-pull-down; - }; - }; - - mdio0_pins: mdio0_pins { - mux { - pins = "gpio0", "gpio1"; - function = "gpio"; - drive-strength = <8>; - bias-disable; - }; - - clk { - pins = "gpio1"; - input-disable; - }; - }; - - rgmii2_pins: rgmii2_pins { - mux { - pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", - "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; - function = "rgmii2"; - drive-strength = <8>; - bias-disable; - }; - - tx { - pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32" ; - input-disable; - }; - }; - - spi_pins: spi_pins { - mux { - pins = "gpio18", "gpio19", "gpio21"; - function = "gsbi5"; - drive-strength = <10>; - bias-none; - }; - - cs { - pins = "gpio20"; - drive-strength = <12>; - }; - }; - - usb0_pwr_en_pins: usb0_pwr_en_pins { - mux { - pins = "gpio16", "gpio17"; - function = "gpio"; - drive-strength = <12>; - }; - - pwr { - pins = "gpio17"; - bias-pull-down; - output-high; - }; - - ovc { - pins = "gpio16"; - bias-pull-up; - }; - }; - - usb1_pwr_en_pins: usb1_pwr_en_pins { - mux { - pins = "gpio14", "gpio15"; - function = "gpio"; - drive-strength = <12>; - }; - - pwr { - pins = "gpio14"; - bias-pull-down; - output-high; - }; - - ovc { - pins = "gpio15"; - bias-pull-up; - }; - }; - }; - - gsbi@16300000 { - qcom,mode = ; - status = "ok"; - serial@16340000 { - status = "ok"; - }; - /* - * The i2c device on gsbi4 should not be enabled. - * On ipq806x designs gsbi4 i2c is meant for exclusive - * RPM usage. Turning this on in kernel manifests as - * i2c failure for the RPM. - */ - }; - - gsbi5: gsbi@1a200000 { - qcom,mode = ; - status = "ok"; - - spi4: spi@1a280000 { - status = "ok"; - - pinctrl-0 = <&spi_pins>; - pinctrl-names = "default"; - - cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_HIGH>; - - flash: m25p80@0 { - compatible = "jedec,spi-nor"; - #address-cells = <1>; - #size-cells = <1>; - spi-max-frequency = <51200000>; - reg = <0>; - - linux,part-probe = "qcom-smem"; - }; - }; - }; - - phy@100f8800 { /* USB3 port 1 HS phy */ - status = "ok"; - }; - - phy@100f8830 { /* USB3 port 1 SS phy */ - status = "ok"; - }; - - phy@110f8800 { /* USB3 port 0 HS phy */ - status = "ok"; - }; - - phy@110f8830 { /* USB3 port 0 SS phy */ - status = "ok"; - }; - - usb30@0 { - status = "ok"; - - pinctrl-0 = <&usb0_pwr_en_pins>; - pinctrl-names = "default"; - }; - - usb30@1 { - status = "ok"; - - pinctrl-0 = <&usb1_pwr_en_pins>; - pinctrl-names = "default"; - }; - - pcie0: pci@1b500000 { - status = "ok"; - reset-gpio = <&qcom_pinmux 3 GPIO_ACTIVE_LOW>; - pinctrl-0 = <&pcie0_pins>; - pinctrl-names = "default"; - }; - - pcie1: pci@1b700000 { - status = "ok"; - reset-gpio = <&qcom_pinmux 48 GPIO_ACTIVE_LOW>; - pinctrl-0 = <&pcie1_pins>; - pinctrl-names = "default"; - }; - - mdio0: mdio { - compatible = "virtual,mdio-gpio"; - #address-cells = <1>; - #size-cells = <0>; - gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; - pinctrl-0 = <&mdio0_pins>; - pinctrl-names = "default"; - - phy0: ethernet-phy@0 { - device_type = "ethernet-phy"; - reg = <0>; - qca,ar8327-initvals = < - 0x00004 0x7600000 /* PAD0_MODE */ - 0x00008 0x1000000 /* PAD5_MODE */ - 0x0000c 0x80 /* PAD6_MODE */ - 0x000e4 0xaa545 /* MAC_POWER_SEL */ - 0x000e0 0xc74164de /* SGMII_CTRL */ - 0x0007c 0x4e /* PORT0_STATUS */ - 0x00094 0x4e /* PORT6_STATUS */ - 0x00970 0x1e864443 /* QM_PORT0_CTRL0 */ - 0x00974 0x000001c6 /* QM_PORT0_CTRL1 */ - 0x00978 0x19008643 /* QM_PORT1_CTRL0 */ - 0x0097c 0x000001c6 /* QM_PORT1_CTRL1 */ - 0x00980 0x19008643 /* QM_PORT2_CTRL0 */ - 0x00984 0x000001c6 /* QM_PORT2_CTRL1 */ - 0x00988 0x19008643 /* QM_PORT3_CTRL0 */ - 0x0098c 0x000001c6 /* QM_PORT3_CTRL1 */ - 0x00990 0x19008643 /* QM_PORT4_CTRL0 */ - 0x00994 0x000001c6 /* QM_PORT4_CTRL1 */ - 0x00998 0x1e864443 /* QM_PORT5_CTRL0 */ - 0x0099c 0x000001c6 /* QM_PORT5_CTRL1 */ - 0x009a0 0x1e864443 /* QM_PORT6_CTRL0 */ - 0x009a4 0x000001c6 /* QM_PORT6_CTRL1 */ - >; - }; - - phy4: ethernet-phy@4 { - device_type = "ethernet-phy"; - reg = <4>; - qca,ar8327-initvals = < - 0x000e4 0x6a545 /* MAC_POWER_SEL */ - 0x0000c 0x80 /* PAD6_MODE */ - >; - }; - }; - - gmac1: ethernet@37200000 { - status = "ok"; - phy-mode = "rgmii"; - qcom,id = <1>; - qcom,phy_mdio_addr = <4>; - qcom,poll_required = <0>; - qcom,rgmii_delay = <1>; - qcom,phy_mii_type = <0>; - qcom,emulation = <0>; - qcom,irq = <255>; - mdiobus = <&mdio0>; - - pinctrl-0 = <&rgmii2_pins>; - pinctrl-names = "default"; - - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - gmac2: ethernet@37400000 { - status = "ok"; - phy-mode = "sgmii"; - qcom,id = <2>; - qcom,phy_mdio_addr = <0>; /* none */ - qcom,poll_required = <0>; /* no polling */ - qcom,rgmii_delay = <0>; - qcom,phy_mii_type = <1>; - qcom,emulation = <0>; - qcom,irq = <258>; - mdiobus = <&mdio0>; - - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - rpm@108000 { - pinctrl-0 = <&i2c4_pins>; - pinctrl-names = "default"; - }; - - amba { - sdcc1: sdcc@12400000 { - status = "okay"; - }; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - pinctrl-0 = <&button_pins>; - pinctrl-names = "default"; - - wifi { - label = "wifi"; - gpios = <&qcom_pinmux 6 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - reset { - label = "reset"; - gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - wps { - label = "wps"; - gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - }; - - gpio-leds { - compatible = "gpio-leds"; - pinctrl-0 = <&led_pins>; - pinctrl-names = "default"; - - internet { - label = "nbg6817:white:internet"; - gpios = <&qcom_pinmux 64 GPIO_ACTIVE_HIGH>; - }; - - power: power { - label = "nbg6817:white:power"; - gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; - default-state = "keep"; - }; - - wifi2g { - label = "nbg6817:amber:wifi2g"; - gpios = <&qcom_pinmux 33 GPIO_ACTIVE_HIGH>; - }; - - /* wifi2g amber from the manual is missing */ - - wifi5g { - label = "nbg6817:amber:wifi5g"; - gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>; - }; - - /* wifi5g amber from the manual is missing */ - }; -}; - -&adm_dma { - status = "ok"; -}; diff --git a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8065-r7800.dts b/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8065-r7800.dts deleted file mode 100644 index 79c8334a4..000000000 --- a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8065-r7800.dts +++ /dev/null @@ -1,566 +0,0 @@ -#include "qcom-ipq8065-v1.0.dtsi" - -#include - -/ { - model = "Netgear Nighthawk X4S R7800"; - compatible = "netgear,r7800", "qcom,ipq8065", "qcom,ipq8064"; - - memory@0 { - reg = <0x42000000 0x1e000000>; - device_type = "memory"; - }; - - reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - rsvd@41200000 { - reg = <0x41200000 0x300000>; - no-map; - }; - - rsvd@5fe00000 { - reg = <0x5fe00000 0x200000>; - reusable; - }; - }; - - aliases { - serial0 = &uart4; - mdio-gpio0 = &mdio0; - - led-boot = &power_white; - led-failsafe = &power_amber; - led-running = &power_white; - led-upgrade = &power_amber; - }; - - chosen { - linux,stdout-path = "serial0:115200n8"; - }; - - soc { - pinmux@800000 { - button_pins: button_pins { - mux { - pins = "gpio6", "gpio54", "gpio65"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - i2c4_pins: i2c4_pinmux { - mux { - pins = "gpio12", "gpio13"; - function = "gsbi4"; - drive-strength = <12>; - bias-disable; - }; - }; - - led_pins: led_pins { - pins = "gpio7", "gpio8", "gpio9", "gpio22", "gpio23", - "gpio24","gpio26", "gpio53", "gpio64"; - function = "gpio"; - drive-strength = <2>; - bias-pull-down; - }; - - nand_pins: nand_pins { - mux { - pins = "gpio34", "gpio35", "gpio36", - "gpio37", "gpio38", "gpio39", - "gpio40", "gpio41", "gpio42", - "gpio43", "gpio44", "gpio45", - "gpio46", "gpio47"; - function = "nand"; - drive-strength = <10>; - bias-disable; - }; - pullups { - pins = "gpio39"; - bias-pull-up; - }; - hold { - pins = "gpio40", "gpio41", "gpio42", - "gpio43", "gpio44", "gpio45", - "gpio46", "gpio47"; - bias-bus-hold; - }; - }; - - mdio0_pins: mdio0_pins { - mux { - pins = "gpio0", "gpio1"; - function = "gpio"; - drive-strength = <8>; - bias-disable; - }; - - clk { - pins = "gpio1"; - input-disable; - }; - }; - - rgmii2_pins: rgmii2_pins { - mux { - pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", - "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; - function = "rgmii2"; - drive-strength = <8>; - bias-disable; - }; - - tx { - pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32" ; - input-disable; - }; - }; - - spi_pins: spi_pins { - mux { - pins = "gpio18", "gpio19", "gpio21"; - function = "gsbi5"; - bias-pull-down; - }; - - data { - pins = "gpio18", "gpio19"; - drive-strength = <10>; - }; - - cs { - pins = "gpio20"; - drive-strength = <10>; - bias-pull-up; - }; - - clk { - pins = "gpio21"; - drive-strength = <12>; - }; - }; - - spi6_pins: spi6_pins { - mux { - pins = "gpio55", "gpio56", "gpio58"; - function = "gsbi6"; - bias-pull-down; - }; - - mosi { - pins = "gpio55"; - drive-strength = <12>; - }; - - miso { - pins = "gpio56"; - drive-strength = <14>; - }; - - cs { - pins = "gpio57"; - drive-strength = <12>; - bias-pull-up; - }; - - clk { - pins = "gpio58"; - drive-strength = <12>; - }; - - reset { - pins = "gpio33"; - drive-strength = <10>; - bias-pull-down; - output-high; - }; - }; - - usb0_pwr_en_pins: usb0_pwr_en_pins { - mux { - pins = "gpio15"; - function = "gpio"; - drive-strength = <12>; - bias-pull-down; - output-high; - }; - }; - - usb1_pwr_en_pins: usb1_pwr_en_pins { - mux { - pins = "gpio16", "gpio68"; - function = "gpio"; - drive-strength = <12>; - bias-pull-down; - output-high; - }; - }; - }; - - gsbi@16300000 { - qcom,mode = ; - status = "ok"; - serial@16340000 { - status = "ok"; - }; - /* - * The i2c device on gsbi4 should not be enabled. - * On ipq806x designs gsbi4 i2c is meant for exclusive - * RPM usage. Turning this on in kernel manifests as - * i2c failure for the RPM. - */ - }; - - gsbi5: gsbi@1a200000 { - qcom,mode = ; - status = "ok"; - - spi5: spi@1a280000 { - status = "ok"; - - pinctrl-0 = <&spi_pins>; - pinctrl-names = "default"; - - cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_HIGH>; - - flash: m25p80@0 { - compatible = "jedec,spi-nor"; - #address-cells = <1>; - #size-cells = <1>; - spi-max-frequency = <50000000>; - reg = <0>; - - linux,part-probe = "qcom-smem"; - }; - }; - }; - - gsbi6: gsbi@16500000 { - qcom,mode = ; - status = "ok"; - spi6: spi@16580000 { - status = "ok"; - - pinctrl-0 = <&spi6_pins>; - pinctrl-names = "default"; - - cs-gpios = <&qcom_pinmux 57 GPIO_ACTIVE_HIGH>; - - spi-nor@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <6000000>; - }; - }; - }; - - sata-phy@1b400000 { - status = "ok"; - }; - - sata@29000000 { - ports-implemented = <0x1>; - status = "ok"; - }; - - phy@100f8800 { /* USB3 port 1 HS phy */ - status = "ok"; - }; - - phy@100f8830 { /* USB3 port 1 SS phy */ - status = "ok"; - }; - - phy@110f8800 { /* USB3 port 0 HS phy */ - status = "ok"; - }; - - phy@110f8830 { /* USB3 port 0 SS phy */ - status = "ok"; - }; - - usb30@0 { - status = "ok"; - - pinctrl-0 = <&usb0_pwr_en_pins>; - pinctrl-names = "default"; - }; - - usb30@1 { - status = "ok"; - - pinctrl-0 = <&usb1_pwr_en_pins>; - pinctrl-names = "default"; - }; - - pcie0: pci@1b500000 { - status = "ok"; - phy-tx0-term-offset = <7>; - }; - - pcie1: pci@1b700000 { - status = "ok"; - phy-tx0-term-offset = <7>; - }; - - nand@1ac00000 { - status = "ok"; - - pinctrl-0 = <&nand_pins>; - pinctrl-names = "default"; - - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; - nand-bus-width = <8>; - - #address-cells = <1>; - #size-cells = <1>; - - qcadata@0 { - label = "qcadata"; - reg = <0x0000000 0x0c80000>; - read-only; - }; - - APPSBL@c80000 { - label = "APPSBL"; - reg = <0x0c80000 0x0500000>; - read-only; - }; - - APPSBLENV@1180000 { - label = "APPSBLENV"; - reg = <0x1180000 0x0080000>; - read-only; - }; - - art: art@1200000 { - label = "art"; - reg = <0x1200000 0x0140000>; - read-only; - }; - - artbak: art@1340000 { - label = "artbak"; - reg = <0x1340000 0x0140000>; - read-only; - }; - - kernel@1480000 { - label = "kernel"; - reg = <0x1480000 0x0200000>; - }; - - ubi@1680000 { - label = "ubi"; - reg = <0x1680000 0x1E00000>; - }; - - netgear@3480000 { - label = "netgear"; - reg = <0x3480000 0x4480000>; - read-only; - }; - - reserve@7900000 { - label = "reserve"; - reg = <0x7900000 0x0700000>; - read-only; - }; - - firmware@1480000 { - label = "firmware"; - reg = <0x1480000 0x2000000>; - }; - }; - - mdio0: mdio { - compatible = "virtual,mdio-gpio"; - #address-cells = <1>; - #size-cells = <0>; - gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; - pinctrl-0 = <&mdio0_pins>; - pinctrl-names = "default"; - - - phy0: ethernet-phy@0 { - device_type = "ethernet-phy"; - reg = <0>; - qca,ar8327-initvals = < - 0x00004 0x7600000 /* PAD0_MODE */ - 0x00008 0x1000000 /* PAD5_MODE */ - 0x0000c 0x80 /* PAD6_MODE */ - 0x000e4 0xaa545 /* MAC_POWER_SEL */ - 0x000e0 0xc74164de /* SGMII_CTRL */ - 0x0007c 0x4e /* PORT0_STATUS */ - 0x00094 0x4e /* PORT6_STATUS */ - 0x00970 0x1e864443 /* QM_PORT0_CTRL0 */ - 0x00974 0x000001c6 /* QM_PORT0_CTRL1 */ - 0x00978 0x19008643 /* QM_PORT1_CTRL0 */ - 0x0097c 0x000001c6 /* QM_PORT1_CTRL1 */ - 0x00980 0x19008643 /* QM_PORT2_CTRL0 */ - 0x00984 0x000001c6 /* QM_PORT2_CTRL1 */ - 0x00988 0x19008643 /* QM_PORT3_CTRL0 */ - 0x0098c 0x000001c6 /* QM_PORT3_CTRL1 */ - 0x00990 0x19008643 /* QM_PORT4_CTRL0 */ - 0x00994 0x000001c6 /* QM_PORT4_CTRL1 */ - 0x00998 0x1e864443 /* QM_PORT5_CTRL0 */ - 0x0099c 0x000001c6 /* QM_PORT5_CTRL1 */ - 0x009a0 0x1e864443 /* QM_PORT6_CTRL0 */ - 0x009a4 0x000001c6 /* QM_PORT6_CTRL1 */ - >; - qca,ar8327-vlans = < - 0x1 0x5e /* VLAN1 Ports 1/2/3/4/6 */ - 0x2 0x21 /* VLAN2 Ports 0/5 */ - >; - }; - - phy4: ethernet-phy@4 { - device_type = "ethernet-phy"; - reg = <4>; - qca,ar8327-initvals = < - 0x000e4 0x6a545 /* MAC_POWER_SEL */ - 0x0000c 0x80 /* PAD6_MODE */ - >; - }; - }; - - gmac1: ethernet@37200000 { - status = "ok"; - phy-mode = "rgmii"; - qcom,id = <1>; - qcom,phy_mdio_addr = <4>; - qcom,poll_required = <0>; - qcom,rgmii_delay = <1>; - qcom,phy_mii_type = <0>; - qcom,emulation = <0>; - qcom,irq = <255>; - mdiobus = <&mdio0>; - - pinctrl-0 = <&rgmii2_pins>; - pinctrl-names = "default"; - - mtd-mac-address = <&art 6>; - - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - gmac2: ethernet@37400000 { - status = "ok"; - phy-mode = "sgmii"; - qcom,id = <2>; - qcom,phy_mdio_addr = <0>; /* none */ - qcom,poll_required = <0>; /* no polling */ - qcom,rgmii_delay = <0>; - qcom,phy_mii_type = <1>; - qcom,emulation = <0>; - qcom,irq = <258>; - mdiobus = <&mdio0>; - - mtd-mac-address = <&art 0>; - - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - rpm@108000 { - pinctrl-0 = <&i2c4_pins>; - pinctrl-names = "default"; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - pinctrl-0 = <&button_pins>; - pinctrl-names = "default"; - - wifi { - label = "wifi"; - gpios = <&qcom_pinmux 6 GPIO_ACTIVE_LOW>; - linux,code = ; - debounce-interval = <60>; - wakeup-source; - }; - - reset { - label = "reset"; - gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; - linux,code = ; - debounce-interval = <60>; - wakeup-source; - }; - - wps { - label = "wps"; - gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; - linux,code = ; - debounce-interval = <60>; - wakeup-source; - }; - }; - - gpio-leds { - compatible = "gpio-leds"; - pinctrl-0 = <&led_pins>; - pinctrl-names = "default"; - - power_white: power_white { - label = "r7800:white:power"; - gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; - default-state = "keep"; - }; - - power_amber: power_amber { - label = "r7800:amber:power"; - gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; - }; - - wan_white { - label = "r7800:white:wan"; - gpios = <&qcom_pinmux 22 GPIO_ACTIVE_HIGH>; - }; - - wan_amber { - label = "r7800:amber:wan"; - gpios = <&qcom_pinmux 23 GPIO_ACTIVE_HIGH>; - }; - - usb1 { - label = "r7800:white:usb1"; - gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; - }; - - usb2 { - label = "r7800:white:usb2"; - gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; - }; - - esata { - label = "r7800:white:esata"; - gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>; - }; - - wifi { - label = "r7800:white:wifi"; - gpios = <&qcom_pinmux 64 GPIO_ACTIVE_HIGH>; - }; - - wps { - label = "r7800:white:wps"; - gpios = <&qcom_pinmux 24 GPIO_ACTIVE_HIGH>; - }; - }; -}; - -&adm_dma { - status = "ok"; -}; diff --git a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8065-v1.0.dtsi b/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8065-v1.0.dtsi deleted file mode 100644 index 22b5338cc..000000000 --- a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8065-v1.0.dtsi +++ /dev/null @@ -1 +0,0 @@ -#include "qcom-ipq8065.dtsi" diff --git a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8065.dtsi b/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8065.dtsi deleted file mode 100644 index b3ccb2ede..000000000 --- a/target/linux/ipq806x/files-4.4/arch/arm/boot/dts/qcom-ipq8065.dtsi +++ /dev/null @@ -1,153 +0,0 @@ -#include "qcom-ipq8064.dtsi" - -/ { - model = "Qualcomm IPQ8065"; - compatible = "qcom,ipq8065", "qcom,ipq8064"; - - qcom,pvs { - qcom,pvs-format-a; - qcom,speed0-pvs0-bin-v0 = - < 1725000000 1262500 >, - < 1400000000 1175000 >, - < 1000000000 1100000 >, - < 800000000 1050000 >, - < 600000000 1000000 >, - < 384000000 975000 >; - qcom,speed0-pvs1-bin-v0 = - < 1725000000 1225000 >, - < 1400000000 1150000 >, - < 1000000000 1075000 >, - < 800000000 1025000 >, - < 600000000 975000 >, - < 384000000 950000 >; - qcom,speed0-pvs2-bin-v0 = - < 1725000000 1200000 >, - < 1400000000 1125000 >, - < 1000000000 1050000 >, - < 800000000 1000000 >, - < 600000000 950000 >, - < 384000000 925000 >; - qcom,speed0-pvs3-bin-v0 = - < 1725000000 1175000 >, - < 1400000000 1100000 >, - < 1000000000 1025000 >, - < 800000000 975000 >, - < 600000000 925000 >, - < 384000000 900000 >; - qcom,speed0-pvs4-bin-v0 = - < 1725000000 1150000 >, - < 1400000000 1075000 >, - < 1000000000 1000000 >, - < 800000000 950000 >, - < 600000000 900000 >, - < 384000000 875000 >; - qcom,speed0-pvs5-bin-v0 = - < 1725000000 1100000 >, - < 1400000000 1025000 >, - < 1000000000 950000 >, - < 800000000 900000 >, - < 600000000 850000 >, - < 384000000 825000 >; - qcom,speed0-pvs6-bin-v0 = - < 1725000000 1050000 >, - < 1400000000 975000 >, - < 1000000000 900000 >, - < 800000000 850000 >, - < 600000000 800000 >, - < 384000000 775000 >; - }; - - soc: soc { - - rpm@108000 { - - regulators { - - smb208_s2a: s2a { - regulator-min-microvolt = <775000>; - regulator-max-microvolt = <1275000>; - }; - - smb208_s2b: s2b { - regulator-min-microvolt = <775000>; - regulator-max-microvolt = <1275000>; - }; - }; - }; - - /* Temporary fixed regulator */ - vsdcc_fixed: vsdcc-regulator { - compatible = "regulator-fixed"; - regulator-name = "SDCC Power"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - sdcc1bam:dma@12402000 { - compatible = "qcom,bam-v1.3.0"; - reg = <0x12402000 0x8000>; - interrupts = <0 98 0>; - clocks = <&gcc SDC1_H_CLK>; - clock-names = "bam_clk"; - #dma-cells = <1>; - qcom,ee = <0>; - }; - - sdcc3bam:dma@12182000 { - compatible = "qcom,bam-v1.3.0"; - reg = <0x12182000 0x8000>; - interrupts = <0 96 0>; - clocks = <&gcc SDC3_H_CLK>; - clock-names = "bam_clk"; - #dma-cells = <1>; - qcom,ee = <0>; - }; - - amba { - compatible = "arm,amba-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - sdcc1: sdcc@12400000 { - status = "disabled"; - compatible = "arm,pl18x", "arm,primecell"; - arm,primecell-periphid = <0x00051180>; - reg = <0x12400000 0x2000>; - interrupts = ; - interrupt-names = "cmd_irq"; - clocks = <&gcc SDC1_CLK>, <&gcc SDC1_H_CLK>; - clock-names = "mclk", "apb_pclk"; - bus-width = <8>; - max-frequency = <96000000>; - non-removable; - cap-sd-highspeed; - cap-mmc-highspeed; - vmmc-supply = <&vsdcc_fixed>; - dmas = <&sdcc1bam 2>, <&sdcc1bam 1>; - dma-names = "tx", "rx"; - }; - - sdcc3: sdcc@12180000 { - compatible = "arm,pl18x", "arm,primecell"; - arm,primecell-periphid = <0x00051180>; - status = "disabled"; - reg = <0x12180000 0x2000>; - interrupts = ; - interrupt-names = "cmd_irq"; - clocks = <&gcc SDC3_CLK>, <&gcc SDC3_H_CLK>; - clock-names = "mclk", "apb_pclk"; - bus-width = <8>; - cap-sd-highspeed; - cap-mmc-highspeed; - max-frequency = <192000000>; - #mmc-ddr-1_8v; - sd-uhs-sdr104; - sd-uhs-ddr50; - vqmmc-supply = <&vsdcc_fixed>; - dmas = <&sdcc3bam 2>, <&sdcc3bam 1>; - dma-names = "tx", "rx"; - }; - }; - }; -}; diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-a42.dts b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-a42.dts new file mode 100644 index 000000000..887be993e --- /dev/null +++ b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-a42.dts @@ -0,0 +1,244 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2017, Sven Eckelmann + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "qcom-ipq4019.dtsi" +#include "qcom-ipq4019-bus.dtsi" +#include +#include +#include + +/ { + model = "OpenMesh A42"; + compatible = "openmesh,a42", "qcom,ipq4019"; + + reserved-memory { + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges; + + rsvd1@87000000 { + reg = <0x87000000 0x500000>; + no-map; + }; + + wifi_dump@87500000 { + reg = <0x87500000 0x600000>; + no-map; + }; + + rsvd2@87B00000 { + reg = <0x87b00000 0x500000>; + no-map; + }; + }; + + soc { + tcsr@194b000 { + /* select hostmode */ + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + status = "ok"; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + + pinctrl@1000000 { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + }; + pinmux_cs { + function = "gpio"; + pins = "gpio54"; + }; + pinconf { + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + pinconf_cs { + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + }; + + blsp_dma: dma@7884000 { + status = "ok"; + }; + + spi_0: spi@78b5000 { + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "ok"; + cs-gpios = <&tlmm 54 0>; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <24000000>; + + /* partitions are passed via bootloader */ + }; + }; + + serial@78af000 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "ok"; + }; + + cryptobam: dma@8e04000 { + status = "ok"; + }; + + crypto@8e3a000 { + status = "ok"; + }; + + watchdog@b017000 { + status = "ok"; + }; + + usb2_hs_phy: hsphy@a8000 { + status = "ok"; + }; + + usb2: usb2@60f8800 { + status = "ok"; + }; + + mdio@90000 { + status = "okay"; + }; + + ess-switch@c000000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + edma@c080000 { + status = "okay"; + }; + + wifi@a000000 { + status = "okay"; + qcom,ath10k-calibration-variant = "OM-A42"; + }; + + wifi@a800000 { + status = "okay"; + qcom,ath10k-calibration-variant = "OM-A42"; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + aliases { + led-boot = &power; + led-failsafe = &power; + led-running = &power; + led-upgrade = &power; + }; + + gpio-leds { + compatible = "gpio-leds"; + + red { + label = "a42:red:status"; + gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "default-off"; + }; + + power: green { + label = "a42:green:status"; + gpios = <&tlmm 1 GPIO_ACTIVE_HIGH>; + }; + + blue { + label = "a42:blue:status"; + gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "default-off"; + }; + }; + + watchdog { + compatible = "linux,wdt-gpio"; + gpios = <&tlmm 5 GPIO_ACTIVE_LOW>; + hw_algo = "toggle"; + /* hw_margin_ms is actually 300s but driver limits it to 60s */ + hw_margin_ms = <60000>; + always-running; + }; +}; + +&gmac0 { + qcom,phy_mdio_addr = <4>; + qcom,poll_required = <1>; + qcom,forced_speed = <1000>; + qcom,forced_duplex = <1>; + vlan_tag = <2 0x20>; +}; + +&gmac1 { + qcom,phy_mdio_addr = <3>; + qcom,poll_required = <1>; + qcom,forced_speed = <1000>; + qcom,forced_duplex = <1>; + vlan_tag = <1 0x10>; +}; diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-fritz4040.dts b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-fritz4040.dts index 45bb3c87b..f5ca3d5c5 100644 --- a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-fritz4040.dts +++ b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-fritz4040.dts @@ -14,7 +14,7 @@ * */ -#include "qcom-ipq4019-ap.dk01.1.dtsi" +#include "qcom-ipq4019.dtsi" #include "qcom-ipq4019-bus.dtsi" #include #include @@ -24,48 +24,53 @@ model = "AVM FRITZ!Box 4040"; compatible = "avm,fritzbox-4040", "qcom,ipq4019"; - reserved-memory { - #address-cells = <0x1>; - #size-cells = <0x1>; - ranges; - - rsvd1@87000000 { - reg = <0x87000000 0x500000>; - no-map; - }; - - wifi_dump@87500000 { - reg = <0x87500000 0x600000>; - no-map; - }; - - rsvd2@87B00000 { - reg = <0x87b00000 0x500000>; - no-map; - }; + aliases { + led-boot = &power; + led-failsafe = &flash; + led-running = &power; + led-upgrade = &flash; }; -/* - This also works. Maybe it could be smaller still. reserved-memory { #address-cells = <0x1>; #size-cells = <0x1>; ranges; - rsvd1@87E00000 { - reg = <0x87e00000 0x200000>; + tz_apps@87b80000 { + reg = <0x87b80000 0x280000>; + reusable; + }; + + smem@87e00000 { + reg = <0x87e00000 0x080000>; + no-map; + }; + + tz@87e80000 { + reg = <0x87e80000 0x180000>; no-map; }; }; -*/ soc { + mdio@90000 { + status = "okay"; + }; + + ess-psgmii@98000 { + status = "okay"; + }; + + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + tcsr@194b000 { - /* select hostmode */ compatible = "qcom,tcsr"; reg = <0x194b000 0x100>; qcom,usb-hsphy-mode-select = ; - status = "ok"; }; ess_tcsr@1953000 { @@ -74,28 +79,42 @@ qcom,ess-interface-select = ; }; - - tcsr@1949000 { - compatible = "qcom,tcsr"; - reg = <0x1949000 0x100>; - qcom,wifi_glb_cfg = ; - }; - tcsr@1957000 { compatible = "qcom,tcsr"; reg = <0x1957000 0x100>; qcom,wifi_noc_memtype_m0_m2 = ; }; - counter@4a1000 { - compatible = "qcom,qca-gcnt"; - reg = <0x4a1000 0x4>; + usb2@60f8800 { + status = "ok"; }; - mdio@90000 { + serial@78af000 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "ok"; + }; + + usb3@8af8800 { + status = "ok"; + }; + + crypto@8e3a000 { + status = "ok"; + }; + + wifi@a000000 { status = "okay"; }; + wifi@a800000 { + status = "okay"; + }; + + watchdog@b017000 { + status = "ok"; + }; + qca8075: ess-switch@c000000 { status = "okay"; @@ -105,34 +124,14 @@ enable-usb-power { gpio-hog; line-name = "enable USB3 power"; - gpios = <0x7 GPIO_ACTIVE_HIGH>; + gpios = <7 GPIO_ACTIVE_HIGH>; output-high; }; }; - ess-psgmii@98000 { - status = "okay"; - }; - edma@c080000 { status = "okay"; }; - - wifi@a000000 { - status = "okay"; - }; - - wifi@a800000 { - status = "okay"; - }; - - cryptobam: dma@8e04000 { - status = "okay"; - }; - - crypto@8e3a000 { - status = "okay"; - }; }; gpio-keys { @@ -140,7 +139,7 @@ wlan { label = "wlan"; - gpios = <&tlmm 0x3a GPIO_ACTIVE_LOW>; + gpios = <&tlmm 58 GPIO_ACTIVE_LOW>; linux,code = ; }; @@ -151,58 +150,85 @@ }; }; - aliases { - led-boot = &power; - led-failsafe = &flash; - led-running = &power; - led-upgrade = &flash; - }; - gpio-leds { compatible = "gpio-leds"; wlan { label = "fritz4040:green:wlan"; - gpios = <&qca8075 0x1 GPIO_ACTIVE_HIGH>; + gpios = <&qca8075 1 GPIO_ACTIVE_HIGH>; }; panic: info_red { label = "fritz4040:red:info"; - gpios = <&qca8075 0x3 GPIO_ACTIVE_HIGH>; + gpios = <&qca8075 3 GPIO_ACTIVE_HIGH>; panic-indicator; }; wan { label = "fritz4040:green:wan"; - gpios = <&qca8075 0x5 GPIO_ACTIVE_HIGH>; + gpios = <&qca8075 5 GPIO_ACTIVE_HIGH>; }; power: power { label = "fritz4040:green:power"; - gpios = <&qca8075 0xb GPIO_ACTIVE_HIGH>; + gpios = <&qca8075 11 GPIO_ACTIVE_HIGH>; }; lan { label = "fritz4040:green:lan"; - gpios = <&qca8075 0xd GPIO_ACTIVE_HIGH>; + gpios = <&qca8075 13 GPIO_ACTIVE_HIGH>; }; flash: info_amber { label = "fritz4040:amber:info"; - gpios = <&qca8075 0xf GPIO_ACTIVE_HIGH>; + gpios = <&qca8075 15 GPIO_ACTIVE_HIGH>; }; }; }; -&spi_0 { /* BLSP1 QUP1 */ - status = "ok"; - - mx25l25635e@0 { - status = "disabled"; +&tlmm { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; + function = "blsp_uart0"; + bias-disable; + }; }; + spi_0_pins: spi_0_pinmux { + mux { + function = "blsp_spi0"; + pins = "gpio55", "gpio56", "gpio57"; + drive-strength = <12>; + bias-disable; + }; + + mux_cs { + function = "gpio"; + pins = "gpio54"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&cryptobam { + status = "ok"; +}; + +&blsp_dma { + status = "ok"; +}; + +&spi_0 { /* BLSP1 QUP1 */ + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "ok"; + cs-gpios = <&tlmm 54 0>; + mx25l25635f@0 { - compatible = "mx25l25635f", "jedec,spi-nor"; + compatible = "jedec,spi-nor"; #address-cells = <1>; #size-cells = <0>; reg = <0>; @@ -273,12 +299,24 @@ }; partition11@2A0000 { label = "firmware"; - reg = <0x002A0000 0x01C60000>; + reg = <0x002a0000 0x01c60000>; }; partition12@1f00000 { label = "jffs2"; - reg = <0x01F00000 0x00100000>; + reg = <0x01f00000 0x00100000>; }; }; }; }; + +&usb3_ss_phy { + status = "ok"; +}; + +&usb3_hs_phy { + status = "ok"; +}; + +&usb2_hs_phy { + status = "ok"; +}; diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-rt-ac58u.dts b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-rt-ac58u.dts index 88abc3f48..04f48ae9d 100644 --- a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-rt-ac58u.dts +++ b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq4019-rt-ac58u.dts @@ -18,7 +18,6 @@ #include "qcom-ipq4019-bus.dtsi" #include #include -#include / { model = "ASUS RT-AC58U"; @@ -47,73 +46,6 @@ }; }; - soc { - - tcsr@194b000 { - /* select hostmode */ - compatible = "qcom,tcsr"; - reg = <0x194b000 0x100>; - qcom,usb-hsphy-mode-select = ; - status = "ok"; - }; - - ess_tcsr@1953000 { - compatible = "qcom,tcsr"; - reg = <0x1953000 0x1000>; - qcom,ess-interface-select = ; - }; - - - tcsr@1949000 { - compatible = "qcom,tcsr"; - reg = <0x1949000 0x100>; - qcom,wifi_glb_cfg = ; - }; - - tcsr@1957000 { - compatible = "qcom,tcsr"; - reg = <0x1957000 0x100>; - qcom,wifi_noc_memtype_m0_m2 = ; - }; - - counter@4a1000 { - compatible = "qcom,qca-gcnt"; - reg = <0x4a1000 0x4>; - }; - - mdio@90000 { - status = "okay"; - }; - - ess-switch@c000000 { - status = "okay"; - }; - - ess-psgmii@98000 { - status = "okay"; - }; - - edma@c080000 { - status = "okay"; - }; - - wifi@a000000 { - status = "okay"; - }; - - wifi@a800000 { - status = "okay"; - }; - - cryptobam: dma@8e04000 { - status = "okay"; - }; - - crypto@8e3a000 { - status = "okay"; - }; - }; - gpio-keys { compatible = "gpio-keys"; @@ -178,16 +110,10 @@ }; }; - &spi_0 { /* BLSP1 QUP1 */ - status = "ok"; cs-gpios = <&tlmm 54 0>, <&tlmm 59 0>; - mx25l25635e@0 { - status = "disabled"; - }; - m25p80@0 { #address-cells = <1>; #size-cells = <0>; diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-ap148.dts b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-ap148.dts index fa4f05bdb..39a0d9656 100644 --- a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-ap148.dts +++ b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-ap148.dts @@ -161,12 +161,11 @@ pcie0: pci@1b500000 { status = "ok"; - phy-tx0-term-offset = <7>; }; pcie1: pci@1b700000 { status = "ok"; - phy-tx0-term-offset = <7>; + force_gen1 = <1>; }; nand@1ac00000 { diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-c2600.dts b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-c2600.dts index 80bc5dfa0..a4fd13429 100644 --- a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-c2600.dts +++ b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-c2600.dts @@ -346,12 +346,11 @@ pcie0: pci@1b500000 { status = "ok"; - phy-tx0-term-offset = <7>; }; pcie1: pci@1b700000 { status = "ok"; - phy-tx0-term-offset = <7>; + force_gen1 = <1>; }; mdio0: mdio { diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-d7800.dts b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-d7800.dts index c1a4c82a2..b7c49cc81 100644 --- a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-d7800.dts +++ b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-d7800.dts @@ -193,6 +193,7 @@ reset-gpio = <&qcom_pinmux 48 GPIO_ACTIVE_HIGH>; pinctrl-0 = <&pcie1_pins>; pinctrl-names = "default"; + force_gen1 = <1>; }; nand@1ac00000 { diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-ea8500.dts b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-ea8500.dts index 761fa4317..a8628ff93 100644 --- a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-ea8500.dts +++ b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-ea8500.dts @@ -157,19 +157,17 @@ pcie0: pci@1b500000 { status = "ok"; - phy-tx0-term-offset = <7>; + force_gen1 = <1>; }; pcie1: pci@1b700000 { status = "ok"; - phy-tx0-term-offset = <7>; }; - + pcie2: pci@1b900000 { status = "ok"; - phy-tx0-term-offset = <7>; }; - + nand@1ac00000 { status = "ok"; diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-r7500.dts b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-r7500.dts index 2ea856d88..3445a7925 100644 --- a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-r7500.dts +++ b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-r7500.dts @@ -168,6 +168,7 @@ pcie1: pci@1b700000 { status = "ok"; + force_gen1 = <1>; }; nand@1ac00000 { diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-r7500v2.dts b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-r7500v2.dts index a21cf18be..c4b0c4b5a 100644 --- a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-r7500v2.dts +++ b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-r7500v2.dts @@ -198,6 +198,7 @@ reset-gpio = <&qcom_pinmux 48 GPIO_ACTIVE_LOW>; pinctrl-0 = <&pcie1_pins>; pinctrl-names = "default"; + force_gen1 = <1>; }; nand@1ac00000 { diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-vr2600v.dts b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-vr2600v.dts index b55a98d22..561c49aaa 100644 --- a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-vr2600v.dts +++ b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-vr2600v.dts @@ -259,12 +259,11 @@ pcie0: pci@1b500000 { status = "ok"; - phy-tx0-term-offset = <7>; }; pcie1: pci@1b700000 { status = "ok"; - phy-tx0-term-offset = <7>; + force_gen1 = <1>; }; mdio0: mdio { diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-wxr-2533dhp.dts b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-wxr-2533dhp.dts deleted file mode 100644 index 2d6957e56..000000000 --- a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064-wxr-2533dhp.dts +++ /dev/null @@ -1,448 +0,0 @@ -#include "qcom-ipq8064-v1.0.dtsi" - -#include - -/ { - model = "Buffalo WXR-2533DHP"; - compatible = "buffalo,wxr-2533dhp", "qcom,ipq8064"; - - memory@0 { - reg = <0x42000000 0x1e000000>; - device_type = "memory"; - }; - - reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - rsvd@41200000 { - reg = <0x41200000 0x300000>; - no-map; - }; - }; - - aliases { - serial0 = &uart4; - mdio-gpio0 = &mdio0; - - led-boot = &power_white; - led-failsafe = &power_orange; - led-running = &power_white; - led-upgrade = &power_orange; - }; - - chosen { - bootargs = "console=ttyMSM0,115200n8 ubi.mtd=0 ubi.block=0,1 root=/dev/ubiblock0_1 rootfstype=squashfs"; - linux,stdout-path = "serial0:115200n8"; - }; - - soc { - pinmux@800000 { - i2c4_pins: i2c4_pinmux { - mux { - pins = "gpio12", "gpio13"; - function = "gsbi4"; - drive-strength = <12>; - bias-disable; - }; - }; - - spi_pins: spi_pins { - mux { - pins = "gpio18", "gpio19", "gpio21"; - function = "gsbi5"; - drive-strength = <10>; - bias-none; - }; - }; - - nand_pins: nand_pins { - mux { - pins = "gpio34", "gpio35", "gpio36", - "gpio37", "gpio38", "gpio39", - "gpio40", "gpio41", "gpio42", - "gpio43", "gpio44", "gpio45", - "gpio46", "gpio47"; - function = "nand"; - drive-strength = <10>; - bias-disable; - }; - pullups { - pins = "gpio39"; - bias-pull-up; - }; - hold { - pins = "gpio40", "gpio41", "gpio42", - "gpio43", "gpio44", "gpio45", - "gpio46", "gpio47"; - bias-bus-hold; - }; - }; - - mdio0_pins: mdio0_pins { - mux { - pins = "gpio0", "gpio1"; - function = "gpio"; - drive-strength = <8>; - bias-disable; - }; - }; - - rgmii2_pins: rgmii2_pins { - mux { - pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", - "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; - function = "rgmii2"; - drive-strength = <8>; - bias-disable; - }; - }; - - led_pins: led_pins { - mux { - pins = "gpio7", "gpio8", "gpio9", "gpio16", "gpio22", "gpio23", - "gpio24", "gpio25", "gpio26", "gpio53"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - button_pins: button_pins { - mux { - pins = "gpio54", "gpio65"; - function = "gpio"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - }; - - nand@1ac00000 { - status = "ok"; - - pinctrl-0 = <&nand_pins>; - pinctrl-names = "default"; - - cs0 { - reg = <0>; - compatible = "qcom,nandcs"; - - nand-ecc-strength = <4>; - nand-bus-width = <8>; - nand-ecc-step-size = <512>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - rootfs@0000000 { - label = "rootfs"; - reg = <0x0000000 0x4000000>; - }; - - rootfs_1@4000000 { - label = "rootfs_1"; - reg = <0x4000000 0x4000000>; - }; - }; - }; - }; - - gsbi@16300000 { - qcom,mode = ; - status = "ok"; - - uart4: serial@16340000 { - status = "ok"; - }; - /* - * The i2c device on gsbi4 should not be enabled. - * On ipq806x designs gsbi4 i2c is meant for exclusive - * RPM usage. Turning this on in kernel manifests as - * i2c failure for the RPM. - */ - }; - - gsbi5: gsbi@1a200000 { - qcom,mode = ; - status = "ok"; - - spi5: spi@1a280000 { - status = "ok"; - - pinctrl-0 = <&spi_pins>; - pinctrl-names = "default"; - - cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_HIGH>; - - flash: m25p80@0 { - compatible = "jedec,spi-nor"; - #address-cells = <1>; - #size-cells = <1>; - spi-max-frequency = <50000000>; - reg = <0>; - - SBL1@0 { - label = "SBL1"; - reg = <0x0 0x10000>; - read-only; - }; - - MIBIB@10000 { - label = "MIBIB"; - reg = <0x10000 0x20000>; - read-only; - }; - - SBL2@30000 { - label = "SBL2"; - reg = <0x30000 0x30000>; - read-only; - }; - - SBL3@60000 { - label = "SBL3"; - reg = <0x60000 0x30000>; - read-only; - }; - - DDRCONFIG@90000 { - label = "DDRCONFIG"; - reg = <0x90000 0x10000>; - read-only; - }; - - SSD@a0000 { - label = "SSD"; - reg = <0xa0000 0x10000>; - read-only; - }; - - TZ@b0000 { - label = "TZ"; - reg = <0xb0000 0x30000>; - read-only; - }; - - RPM@e0000 { - label = "RPM"; - reg = <0xe0000 0x20000>; - read-only; - }; - - APPSBL@100000 { - label = "APPSBL"; - reg = <0x100000 0x70000>; - read-only; - }; - - APPSBLENV@170000 { - label = "APPSBLENV"; - reg = <0x170000 0x10000>; - read-only; - }; - - ART: ART@180000 { - label = "ART"; - reg = <0x180000 0x40000>; - read-only; - }; - - BOOTCONFIG@1c0000 { - label = "OLDART"; - reg = <0x1c0000 0x10000>; - read-only; - }; - - APPSBL_1@1d0000 { - label = "APPSBL_1"; - reg = <0x1d0000 0x70000>; - }; - }; - }; - }; - - phy@100f8800 { /* USB3 port 1 HS phy */ - status = "ok"; - }; - - phy@100f8830 { /* USB3 port 1 SS phy */ - status = "ok"; - }; - - phy@110f8800 { /* USB3 port 0 HS phy */ - status = "ok"; - }; - - phy@110f8830 { /* USB3 port 0 SS phy */ - status = "ok"; - }; - - usb30@0 { - status = "ok"; - }; - - usb30@1 { - status = "ok"; - }; - - pcie0: pci@1b500000 { - status = "ok"; - phy-tx0-term-offset = <7>; - }; - - pcie1: pci@1b700000 { - status = "ok"; - phy-tx0-term-offset = <7>; - }; - - mdio0: mdio { - compatible = "virtual,mdio-gpio"; - #address-cells = <1>; - #size-cells = <0>; - gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH &qcom_pinmux 0 GPIO_ACTIVE_HIGH>; - pinctrl-0 = <&mdio0_pins>; - pinctrl-names = "default"; - - phy0: ethernet-phy@0 { - device_type = "ethernet-phy"; - reg = <0>; - qca,ar8327-initvals = < - 0x00004 0x7600000 /* PAD0_MODE */ - 0x00008 0x1000000 /* PAD5_MODE */ - 0x0000c 0x80 /* PAD6_MODE */ - 0x000e4 0x6a545 /* MAC_POWER_SEL */ - 0x000e0 0xc74164de /* SGMII_CTRL */ - 0x0007c 0x4e /* PORT0_STATUS */ - 0x00094 0x4e /* PORT6_STATUS */ - >; - }; - - phy4: ethernet-phy@4 { - device_type = "ethernet-phy"; - reg = <4>; - }; - }; - - gmac1: ethernet@37200000 { - status = "ok"; - phy-mode = "rgmii"; - qcom,id = <1>; - qcom,phy_mdio_addr = <4>; - qcom,poll_required = <1>; - qcom,rgmii_delay = <0>; - qcom,emulation = <0>; - pinctrl-0 = <&rgmii2_pins>; - pinctrl-names = "default"; - mtd-mac-address = <&ART 6>; - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - //lan - gmac2: ethernet@37400000 { - status = "ok"; - phy-mode = "sgmii"; - qcom,id = <2>; - qcom,phy_mdio_addr = <0>; /* none */ - qcom,poll_required = <0>; /* no polling */ - qcom,rgmii_delay = <0>; - qcom,emulation = <0>; - mtd-mac-address = <&ART 0>; - fixed-link { - speed = <1000>; - full-duplex; - }; - }; - - rpm@108000 { - pinctrl-0 = <&i2c4_pins>; - pinctrl-names = "default"; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - pinctrl-0 = <&button_pins>; - pinctrl-names = "default"; - - reset { - label = "reset"; - gpios = <&qcom_pinmux 54 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - aoss { - label = "aoss"; - gpios = <&qcom_pinmux 65 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - }; - - gpio-leds { - compatible = "gpio-leds"; - pinctrl-0 = <&led_pins>; - pinctrl-names = "default"; - - power_white: power_white { - label = "wxr-2533dhp:white:power"; - gpios = <&qcom_pinmux 53 GPIO_ACTIVE_HIGH>; - default-state = "keep"; - }; - - power_orange: power_orange { - label = "wxr-2533dhp:orange:power"; - gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>; - default-state = "keep"; - }; - - wireless_white: wireless_white { - label = "wxr-2533dhp:white:wireless"; - gpios = <&qcom_pinmux 24 GPIO_ACTIVE_HIGH>; - }; - - wireless_orange: wireless_orange { - label = "wxr-2533dhp:orange:wireless"; - gpios = <&qcom_pinmux 23 GPIO_ACTIVE_HIGH>; - }; - - internet_white: internet_white { - label = "wxr-2533dhp:white:internet"; - gpios = <&qcom_pinmux 22 GPIO_ACTIVE_HIGH>; - }; - - internet_orange: internet_orange { - label = "wxr-2533dhp:orange:internet"; - gpios = <&qcom_pinmux 16 GPIO_ACTIVE_HIGH>; - }; - - router_white: router_white { - label = "wxr-2533dhp:white:router"; - gpios = <&qcom_pinmux 26 GPIO_ACTIVE_LOW>; - }; - - router_orange: router_orange { - label = "wxr-2533dhp:orange:router"; - gpios = <&qcom_pinmux 25 GPIO_ACTIVE_HIGH>; - }; - - usb_green: usb_green { - label = "wxr-2533dhp:green:usb"; - gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>; - }; - - guest_green: guest_green { - label = "wxr-2533dhp:green:guest"; - gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; - }; - }; -}; - -&adm_dma { - status = "ok"; -}; diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064.dtsi b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064.dtsi index 9996bd741..90f7a1018 100644 --- a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064.dtsi +++ b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8064.dtsi @@ -967,6 +967,9 @@ ranges; + resets = <&gcc USB30_0_MASTER_RESET>; + reset-names = "usb30_0_mstr_rst"; + status = "disabled"; dwc3@11000000 { @@ -989,6 +992,9 @@ ranges; + resets = <&gcc USB30_1_MASTER_RESET>; + reset-names = "usb30_1_mstr_rst"; + status = "disabled"; dwc3@10000000 { @@ -1051,6 +1057,8 @@ perst-gpios = <&qcom_pinmux 3 GPIO_ACTIVE_LOW>; + phy-tx0-term-offset = <7>; + status = "disabled"; }; @@ -1103,6 +1111,8 @@ perst-gpios = <&qcom_pinmux 48 GPIO_ACTIVE_LOW>; + phy-tx0-term-offset = <7>; + status = "disabled"; }; @@ -1155,6 +1165,8 @@ perst-gpios = <&qcom_pinmux 63 GPIO_ACTIVE_LOW>; + phy-tx0-term-offset = <7>; + status = "disabled"; }; diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8065-nbg6817.dts b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8065-nbg6817.dts index 5fe14da26..987ee852c 100644 --- a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8065-nbg6817.dts +++ b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8065-nbg6817.dts @@ -33,15 +33,16 @@ }; chosen { - bootargs = "root=/dev/mmcblk0p5 rootfstype=squashfs,ext4 rootwait noinitrd"; + bootargs = "rootfstype=squashfs,ext4 rootwait noinitrd"; linux,stdout-path = "serial0:115200n8"; + append-rootblock = "root=/dev/mmcblk0p"; }; soc { pinmux@800000 { button_pins: button_pins { mux { - pins = "gpio6", "gpio54", "gpio65"; + pins = "gpio53", "gpio54", "gpio65"; function = "gpio"; drive-strength = <2>; bias-pull-up; @@ -228,6 +229,7 @@ reset-gpio = <&qcom_pinmux 48 GPIO_ACTIVE_LOW>; pinctrl-0 = <&pcie1_pins>; pinctrl-names = "default"; + force_gen1 = <1>; }; mdio0: mdio { @@ -334,8 +336,9 @@ wifi { label = "wifi"; - gpios = <&qcom_pinmux 6 GPIO_ACTIVE_LOW>; + gpios = <&qcom_pinmux 53 GPIO_ACTIVE_LOW>; linux,code = ; + linux,input-type = ; }; reset { diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8065-r7800.dts b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8065-r7800.dts index 403054cc9..4c89dcf76 100644 --- a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8065-r7800.dts +++ b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8065-r7800.dts @@ -299,12 +299,11 @@ pcie0: pci@1b500000 { status = "ok"; - phy-tx0-term-offset = <7>; }; pcie1: pci@1b700000 { status = "ok"; - phy-tx0-term-offset = <7>; + force_gen1 = <1>; }; nand@1ac00000 { diff --git a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8065.dtsi b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8065.dtsi index b3ccb2ede..15f3b95f8 100644 --- a/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8065.dtsi +++ b/target/linux/ipq806x/files-4.9/arch/arm/boot/dts/qcom-ipq8065.dtsi @@ -75,6 +75,17 @@ }; }; + ss_phy_0: phy@110f8830 { + rx_eq = <2>; + tx_deamp_3_5db = <32>; + mpll = <0xa0>; + }; + ss_phy_1: phy@100f8830 { + rx_eq = <2>; + tx_deamp_3_5db = <32>; + mpll = <0xa0>; + }; + /* Temporary fixed regulator */ vsdcc_fixed: vsdcc-regulator { compatible = "regulator-fixed"; diff --git a/target/linux/ipq806x/image/Makefile b/target/linux/ipq806x/image/Makefile index a9353ec77..a6402cfa6 100644 --- a/target/linux/ipq806x/image/Makefile +++ b/target/linux/ipq806x/image/Makefile @@ -5,32 +5,15 @@ include $(INCLUDE_DIR)/image.mk UBIFS_OPTS = -m 2048 -e 124KiB -c 4096 -U -F -define Image/Prepare - $(CP) $(LINUX_DIR)/vmlinux $(KDIR)/$(IMG_PREFIX)-vmlinux.elf -endef - -define Image/BuildKernel - $(CP) $(KDIR)/$(IMG_PREFIX)-vmlinux.elf $(BIN_DIR) -endef - -define Image/Build/squashfs - cp $(KDIR)/root.squashfs $(KDIR)/root.squashfs-raw - $(call prepare_generic_squashfs,$(KDIR)/root.squashfs) -endef - -define Image/Build - $(call Image/Build/$(1),$(1)) - dd if=$(KDIR)/root.$(1) of=$(BIN_DIR)/$(IMG_PREFIX)-$(1)-root.img bs=2k conv=sync -endef - define Device/Default PROFILES := Default KERNEL_DEPENDS = $$(wildcard $(DTS_DIR)/$$(DEVICE_DTS).dts) KERNEL_INITRAMFS_PREFIX := $$(IMG_PREFIX)-$(1)-initramfs KERNEL_PREFIX := $$(IMAGE_PREFIX) KERNEL_LOADADDR = 0x42208000 - SUPPORTED_DEVICES = $$(BOARD_NAME) - IMAGE/sysupgrade.tar = sysupgrade-tar | append-metadata + SUPPORTED_DEVICES := $(subst _,$(comma),$(1)) + IMAGE/sysupgrade.bin = sysupgrade-tar | append-metadata + IMAGE/sysupgrade.bin/squashfs := endef define Device/LegacyImage @@ -53,29 +36,25 @@ endef define Device/UbiFit KERNEL_IN_UBI := 1 - IMAGES := nand-factory.ubi nand-sysupgrade.tar + IMAGES := nand-factory.ubi nand-sysupgrade.bin IMAGE/nand-factory.ubi := append-ubi - IMAGE/nand-sysupgrade.tar := sysupgrade-tar | append-metadata + IMAGE/nand-sysupgrade.bin := sysupgrade-tar | append-metadata endef define Device/DniImage - PROFILES += $$(DEVICE_NAME) - FILESYSTEMS := squashfs KERNEL_SUFFIX := -uImage KERNEL = kernel-bin | append-dtb | uImage none KERNEL_NAME := zImage NETGEAR_BOARD_ID := NETGEAR_HW_ID := UBINIZE_OPTS := -E 5 - IMAGES := factory.img sysupgrade.tar + IMAGES := factory.img sysupgrade.bin IMAGE/factory.img := append-kernel | pad-offset $$$$(BLOCKSIZE) 64 | append-uImage-fakeroot-hdr | pad-to $$$$(KERNEL_SIZE) | append-ubi | netgear-dni - IMAGE/sysupgrade.tar := append-kernel | pad-offset $$$$(BLOCKSIZE) 64 | append-uImage-fakeroot-hdr | sysupgrade-tar kernel=$$$$@ | append-metadata + IMAGE/sysupgrade.bin := append-kernel | pad-offset $$$$(BLOCKSIZE) 64 | append-uImage-fakeroot-hdr | sysupgrade-tar kernel=$$$$@ | append-metadata endef DEVICE_VARS += NETGEAR_BOARD_ID NETGEAR_HW_ID define Device/TpSafeImage - PROFILES += $$(DEVICE_NAME) - FILESYSTEMS := squashfs KERNEL_SUFFIX := -uImage KERNEL = kernel-bin | append-dtb | uImage none KERNEL_NAME := zImage @@ -87,91 +66,16 @@ endef DEVICE_VARS += TPLINK_BOARD_ID define Device/ZyXELImage - PROFILES += $$(DEVICE_NAME) - FILESYSTEMS := squashfs KERNEL_SUFFIX := -uImage KERNEL = kernel-bin | append-dtb | uImage none | pad-to $${KERNEL_SIZE} KERNEL_NAME := zImage - IMAGES := sysupgrade.tar mmcblk0p5-rootfs.bin mmcblk0p4-kernel.bin - IMAGE/sysupgrade.tar/squashfs := append-rootfs | pad-to $$$${BLOCKSIZE} | sysupgrade-tar rootfs=$$$$@ | append-metadata + IMAGES := sysupgrade.bin mmcblk0p5-rootfs.bin mmcblk0p4-kernel.bin + IMAGE/sysupgrade.bin/squashfs := append-rootfs | pad-to $$$${BLOCKSIZE} | sysupgrade-tar rootfs=$$$$@ | append-metadata IMAGE/mmcblk0p5-rootfs.bin := append-rootfs | pad-rootfs | pad-to $$$${BLOCKSIZE} IMAGE/mmcblk0p4-kernel.bin := append-kernel endef -define Device/AP148 - $(call Device/FitImage) - $(call Device/UbiFit) - DEVICE_DTS := qcom-ipq8064-ap148 - KERNEL_INSTALL := 1 - BLOCKSIZE := 128k - PAGESIZE := 2048 - BOARD_NAME := ap148 - DEVICE_TITLE := Qualcomm AP148 - DEVICE_PACKAGES := ath10k-firmware-qca99x0 -endef - -define Device/AP148-legacy - $(call Device/LegacyImage) - $(call Device/UbiFit) - DEVICE_DTS := qcom-ipq8064-ap148 - BLOCKSIZE := 128k - PAGESIZE := 2048 - BOARD_NAME := ap148 - DEVICE_TITLE := Qualcomm AP148 (legacy) - DEVICE_PACKAGES := ath10k-firmware-qca99x0 -endef - -define Device/C2600 - $(call Device/TpSafeImage) - DEVICE_DTS := qcom-ipq8064-c2600 - BLOCKSIZE := 128k - PAGESIZE := 2048 - BOARD_NAME := c2600 - TPLINK_BOARD_ID := C2600 - DEVICE_TITLE := TP-Link Archer C2600 - DEVICE_PACKAGES := ath10k-firmware-qca99x0 -endef - -define Device/D7800 - $(call Device/DniImage) - DEVICE_DTS := qcom-ipq8064-d7800 - KERNEL_SIZE := 2097152 - NETGEAR_BOARD_ID := D7800 - NETGEAR_HW_ID := 29764958+0+128+512+4x4+4x4 - BLOCKSIZE := 128k - PAGESIZE := 2048 - BOARD_NAME := d7800 - DEVICE_TITLE := Netgear Nighthawk X4 D7800 - DEVICE_PACKAGES := ath10k-firmware-qca99x0 -endef - -define Device/DB149 - $(call Device/FitImage) - DEVICE_DTS := qcom-ipq8064-db149 - KERNEL_INSTALL := 1 - BOARD_NAME := db149 - DEVICE_TITLE := Qualcomm DB149 - DEVICE_PACKAGES := ath10k-firmware-qca99x0 -endef - -define Device/EA8500 - $(call Device/LegacyImage) - DEVICE_DTS := qcom-ipq8064-ea8500 - PAGESIZE := 2048 - BLOCKSIZE := 128k - KERNEL_SIZE := 3072k - FILESYSTEMS := squashfs - KERNEL = kernel-bin | append-dtb | uImage none | append-uImage-fakeroot-hdr - PROFILES += $$(DEVICE_NAME) - BOARD_NAME := ea8500 - UBINIZE_OPTS := -E 5 - IMAGES := factory.bin sysupgrade.tar - IMAGE/factory.bin := append-kernel | pad-to $$$${KERNEL_SIZE} | append-ubi - DEVICE_TITLE := Linksys EA8500 - DEVICE_PACKAGES := ath10k-firmware-qca99x0 -endef - -define Device/FRITZ4040 +define Device/avm_fritzbox-4040 $(call Device/FitImageLzma) DEVICE_DTS := qcom-ipq4019-fritz4040 KERNEL_LOADADDR := 0x80208000 @@ -181,12 +85,44 @@ define Device/FRITZ4040 DEVICE_TITLE := AVM Fritz!Box 4040 IMAGE_SIZE := 29753344 IMAGES = sysupgrade.bin - FILESYSTEMS := squashfs IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata - DEVICE_PACKAGES := kmod-usb-phy-qcom-ipq4019 ipq-wifi-fritz4040 fritz-tffs fritz-caldata u-boot-fritz4040 + DEVICE_PACKAGES := ipq-wifi-avm_fritzbox-4040 fritz-tffs fritz-caldata u-boot-fritz4040 endef +TARGET_DEVICES += avm_fritzbox-4040 -define Device/R7500 +define Device/linksys_ea8500 + $(call Device/LegacyImage) + DEVICE_DTS := qcom-ipq8064-ea8500 + PAGESIZE := 2048 + BLOCKSIZE := 128k + KERNEL_SIZE := 3072k + KERNEL = kernel-bin | append-dtb | uImage none | append-uImage-fakeroot-hdr + BOARD_NAME := ea8500 + SUPPORTED_DEVICES += ea8500 + UBINIZE_OPTS := -E 5 + IMAGES := factory.bin sysupgrade.bin + IMAGE/factory.bin := append-kernel | pad-to $$$${KERNEL_SIZE} | append-ubi + DEVICE_TITLE := Linksys EA8500 + DEVICE_PACKAGES := ath10k-firmware-qca99x0 +endef +TARGET_DEVICES += linksys_ea8500 + +define Device/netgear_d7800 + $(call Device/DniImage) + DEVICE_DTS := qcom-ipq8064-d7800 + KERNEL_SIZE := 2097152 + NETGEAR_BOARD_ID := D7800 + NETGEAR_HW_ID := 29764958+0+128+512+4x4+4x4 + BLOCKSIZE := 128k + PAGESIZE := 2048 + BOARD_NAME := d7800 + SUPPORTED_DEVICES += d7800 + DEVICE_TITLE := Netgear Nighthawk X4 D7800 + DEVICE_PACKAGES := ath10k-firmware-qca99x0 +endef +TARGET_DEVICES += netgear_d7800 + +define Device/netgear_r7500 $(call Device/DniImage) DEVICE_DTS := qcom-ipq8064-r7500 KERNEL_SIZE := 2097152 @@ -195,11 +131,13 @@ define Device/R7500 BLOCKSIZE := 128k PAGESIZE := 2048 BOARD_NAME := r7500 + SUPPORTED_DEVICES += r7500 DEVICE_TITLE := Netgear Nighthawk X4 R7500 DEVICE_PACKAGES := ath10k-firmware-qca988x endef +TARGET_DEVICES += netgear_r7500 -define Device/R7500v2 +define Device/netgear_r7500v2 $(call Device/DniImage) DEVICE_DTS := qcom-ipq8064-r7500v2 KERNEL_SIZE := 2097152 @@ -208,11 +146,13 @@ define Device/R7500v2 BLOCKSIZE := 128k PAGESIZE := 2048 BOARD_NAME := r7500v2 + SUPPORTED_DEVICES += r7500v2 DEVICE_TITLE := Netgear Nighthawk X4 R7500v2 DEVICE_PACKAGES := ath10k-firmware-qca99x0 ath10k-firmware-qca988x endef +TARGET_DEVICES += netgear_r7500v2 -define Device/R7800 +define Device/netgear_r7800 $(call Device/DniImage) DEVICE_DTS := qcom-ipq8065-r7800 KERNEL_SIZE := 2097152 @@ -221,23 +161,26 @@ define Device/R7800 BLOCKSIZE := 128k PAGESIZE := 2048 BOARD_NAME := r7800 + SUPPORTED_DEVICES += r7800 DEVICE_TITLE := Netgear Nighthawk X4S R7800 DEVICE_PACKAGES := ath10k-firmware-qca9984 endef +TARGET_DEVICES += netgear_r7800 define Build/copy-file cat "$(1)" > "$@" endef -define Device/RT-AC58U +define Device/asus_rt-ac58u $(call Device/FitImageLzma) DEVICE_DTS := qcom-ipq4019-rt-ac58u + KERNEL_LOADADDR := 0x80208000 BLOCKSIZE := 128k PAGESIZE := 2048 DTB_SIZE := 65536 - BOARD_NAME := rt-ac58u - KERNEL_LOADADDR := 0x80208000 + SUPPORTED_DEVICES += rt-ac58u DEVICE_TITLE := Asus RT-AC58U + BOARD_NAME := rt-ac58u IMAGE_SIZE := 20439364 FILESYSTEMS := squashfs # Someone - in their infinite wisdom - decided to put the firmware @@ -251,8 +194,9 @@ define Device/RT-AC58U IMAGE/sysupgrade.tar := sysupgrade-tar | append-metadata DEVICE_PACKAGES := kmod-usb-phy-qcom-ipq4019 ipq-wifi-rt-ac58u endef +TARGET_DEVICES += asus_rt-ac58u -define Device/RT-ACRH17 +define Device/asus_rt-acrh17 $(call Device/FitImageLzma) DEVICE_DTS := qcom-ipq4019-rt-acrh17 BLOCKSIZE := 128k @@ -266,38 +210,43 @@ define Device/RT-ACRH17 UIMAGE_NAME:=$(shell echo -e '\03\01\01\01RT-AC82U') IMAGES = sysupgrade.tar flash-factory.trx IMAGE/flash-factory.trx := copy-file $(KDIR)/tmp/$$(KERNEL_INITRAMFS_IMAGE) | uImage none - IMAGE/sysupgrade.tar := sysupgrade-tar | append-metadata - DEVICE_PACKAGES := kmod-usb-phy-qcom-ipq4019 ath10k-firmware-qca4019 ath10k-firmware-qca9984 + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + DEVICE_PACKAGES := ath10k-firmware-qca4019 ath10k-firmware-qca9984 endef +TARGET_DEVICES += asus_rt-acrh17 -define Device/NBG6817 - DEVICE_DTS := qcom-ipq8065-nbg6817 - KERNEL_SIZE := 4096k +define Device/openmesh_a42 + $(call Device/FitImageLzma) + DEVICE_DTS := qcom-ipq4019-a42 + KERNEL_LOADADDR := 0x80208000 BLOCKSIZE := 64k - BOARD_NAME := nbg6817 - DEVICE_TITLE := ZyXEL NBG6817 - DEVICE_PACKAGES := ath10k-firmware-qca9984 e2fsprogs losetup - $(call Device/ZyXELImage) + SUPPORTED_DEVICES := openmesh,a42 + DEVICE_TITLE := OpenMesh A42 + KERNEL = kernel-bin | lzma | fit lzma $$(DTS_DIR)/$$(DEVICE_DTS).dtb | pad-to $$(BLOCKSIZE) + IMAGE_SIZE := 15616k + IMAGES = factory.bin sysupgrade.bin + IMAGE/factory.bin := append-rootfs | pad-rootfs | openmesh-image ce_type=A42 + IMAGE/sysupgrade.bin/squashfs := append-rootfs | pad-rootfs | sysupgrade-tar rootfs=$$$$@ | append-metadata + DEVICE_PACKAGES := ath10k-firmware-qca4019 uboot-envtools ipq-wifi-openmesh_a42 endef +TARGET_DEVICES += openmesh_a42 -define Device/VR2600v - PROFILES += $$(DEVICE_NAME) - FILESYSTEMS := squashfs - KERNEL_SUFFIX := -uImage - KERNEL = kernel-bin | append-dtb | uImage none - KERNEL_NAME := zImage - KERNEL_SIZE := 2097152 - DEVICE_DTS := qcom-ipq8064-vr2600v - BLOCKSIZE := 128k - PAGESIZE := 2048 - BOARD_NAME := vr2600v - DEVICE_TITLE := TP-Link Archer VR2600v - DEVICE_PACKAGES := ath10k-firmware-qca99x0 +define Device/qcom_ap-dk01.1-c1 + DEVICE_TITLE := QCA AP-DK01.1-C1 + BOARD_NAME := ap-dk01.1-c1 + DEVICE_DTS := qcom-ipq4019-ap.dk01.1-c1 + KERNEL_LOADADDR := 0x80208000 + KERNEL_INSTALL := 1 + KERNEL_SIZE := 4096k + IMAGE_SIZE := 26624k + $(call Device/FitImage) IMAGES := sysupgrade.bin - IMAGE/sysupgrade.bin := pad-extra 512 | append-kernel | pad-to $$$${KERNEL_SIZE} | append-rootfs | pad-rootfs | append-metadata + IMAGE/sysupgrade.bin := append-kernel | pad-to $$$${KERNEL_SIZE} | append-rootfs | pad-rootfs | append-metadata + DEVICE_PACKAGES := ath10k-firmware-qca4019 endef +TARGET_DEVICES += qcom_ap-dk01.1-c1 -define Device/AP-DK04.1-C1 +define Device/qcom_ap-dk04.1-c1 $(call Device/FitImage) $(call Device/UbiFit) DEVICE_DTS := qcom-ipq4019-ap.dk04.1-c1 @@ -309,10 +258,87 @@ define Device/AP-DK04.1-C1 BOARD_NAME := ap-dk04.1-c1 DEVICE_TITLE := QCA AP-DK04.1-C1 endef +TARGET_DEVICES += qcom_ap-dk04.1-c1 -TARGET_DEVICES += AP148 AP148-legacy C2600 D7800 DB149 EA8500 FRITZ4040 R7500 \ - R7500v2 R7800 RT-AC58U RT-ACRH17 NBG6817 VR2600v AP-DK04.1-C1 +define Device/qcom_ipq8064-ap148 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_DTS := qcom-ipq8064-ap148 + KERNEL_INSTALL := 1 + BLOCKSIZE := 128k + PAGESIZE := 2048 + BOARD_NAME := ap148 + SUPPORTED_DEVICES += ap148 + DEVICE_TITLE := Qualcomm AP148 + DEVICE_PACKAGES := ath10k-firmware-qca99x0 +endef +TARGET_DEVICES += qcom_ipq8064-ap148 + +define Device/qcom_ipq8064-ap148-legacy + $(call Device/LegacyImage) + $(call Device/UbiFit) + DEVICE_DTS := qcom-ipq8064-ap148 + BLOCKSIZE := 128k + PAGESIZE := 2048 + BOARD_NAME := ap148 + SUPPORTED_DEVICES := qcom,ipq8064-ap148 ap148 + DEVICE_TITLE := Qualcomm AP148 (legacy) + DEVICE_PACKAGES := ath10k-firmware-qca99x0 +endef +TARGET_DEVICES += qcom_ipq8064-ap148-legacy + +define Device/qcom_ipq8064-db149 + $(call Device/FitImage) + DEVICE_DTS := qcom-ipq8064-db149 + KERNEL_INSTALL := 1 + BOARD_NAME := db149 + DEVICE_TITLE := Qualcomm DB149 + DEVICE_PACKAGES := ath10k-firmware-qca99x0 +endef +TARGET_DEVICES += qcom_ipq8064-db149 + +define Device/tplink_c2600 + $(call Device/TpSafeImage) + DEVICE_DTS := qcom-ipq8064-c2600 + BLOCKSIZE := 128k + PAGESIZE := 2048 + BOARD_NAME := c2600 + SUPPORTED_DEVICES += c2600 + TPLINK_BOARD_ID := C2600 + DEVICE_TITLE := TP-Link Archer C2600 + DEVICE_PACKAGES := ath10k-firmware-qca99x0 +endef +TARGET_DEVICES += tplink_c2600 + +define Device/tplink_vr2600v + KERNEL_SUFFIX := -uImage + KERNEL = kernel-bin | append-dtb | uImage none + KERNEL_NAME := zImage + KERNEL_SIZE := 2097152 + DEVICE_DTS := qcom-ipq8064-vr2600v + BLOCKSIZE := 128k + PAGESIZE := 2048 + BOARD_NAME := vr2600v + SUPPORTED_DEVICES += vr2600v + DEVICE_TITLE := TP-Link Archer VR2600v + DEVICE_PACKAGES := ath10k-firmware-qca99x0 + IMAGES := sysupgrade.bin + IMAGE/sysupgrade.bin := pad-extra 512 | append-kernel | pad-to $$$${KERNEL_SIZE} | append-rootfs | pad-rootfs | append-metadata +endef +TARGET_DEVICES += tplink_vr2600v + +define Device/zyxel_nbg6817 + DEVICE_DTS := qcom-ipq8065-nbg6817 + KERNEL_SIZE := 4096k + BLOCKSIZE := 64k + BOARD_NAME := nbg6817 + SUPPORTED_DEVICES += nbg6817 + DEVICE_TITLE := ZyXEL NBG6817 + DEVICE_PACKAGES := ath10k-firmware-qca9984 e2fsprogs kmod-fs-ext4 losetup + $(call Device/ZyXELImage) +endef +TARGET_DEVICES += zyxel_nbg6817 .NOTPARALLEL: -$(eval $(call BuildImage)) \ No newline at end of file +$(eval $(call BuildImage)) diff --git a/target/linux/ipq806x/modules.mk b/target/linux/ipq806x/modules.mk index 9943bdf35..b36b2d7e3 100644 --- a/target/linux/ipq806x/modules.mk +++ b/target/linux/ipq806x/modules.mk @@ -1,35 +1,3 @@ -define KernelPackage/usb-dwc3-of-simple - TITLE:=DWC3 USB simple OF driver - DEPENDS:=+kmod-usb-dwc3 - KCONFIG:= CONFIG_USB_DWC3_OF_SIMPLE - FILES:= $(LINUX_DIR)/drivers/usb/dwc3/dwc3-of-simple.ko - AUTOLOAD:=$(call AutoLoad,53,dwc3-of-simple,1) - $(call AddDepends/usb) -endef - -define KernelPackage/usb-dwc3-of-simple/description - This driver provides generic platform glue for the integrated DesignWare - USB3 IP Core. -endef - -$(eval $(call KernelPackage,usb-dwc3-of-simple)) - -define KernelPackage/usb-phy-qcom-dwc3 - TITLE:=DWC3 USB QCOM PHY driver - DEPENDS:=@TARGET_ipq806x +kmod-usb-dwc3-of-simple - KCONFIG:= CONFIG_PHY_QCOM_DWC3 - FILES:= $(LINUX_DIR)/drivers/phy/phy-qcom-dwc3.ko - AUTOLOAD:=$(call AutoLoad,45,phy-qcom-dwc3,1) - $(call AddDepends/usb) -endef - -define KernelPackage/usb-phy-qcom-dwc3/description - This driver provides support for the integrated DesignWare - USB3 IP Core within the QCOM SoCs. -endef - -$(eval $(call KernelPackage,usb-phy-qcom-dwc3)) - define KernelPackage/usb-phy-qcom-ipq4019 TITLE:=IPQ4019 PHY wrappers support DEPENDS:=+kmod-usb-dwc3 diff --git a/target/linux/ipq806x/patches-4.9/0017-qcom-ipq4019-add-cpu-operating-points-for-cpufreq-su.patch b/target/linux/ipq806x/patches-4.9/0017-qcom-ipq4019-add-cpu-operating-points-for-cpufreq-su.patch index 5aeb93cdc..7cbd6a455 100644 --- a/target/linux/ipq806x/patches-4.9/0017-qcom-ipq4019-add-cpu-operating-points-for-cpufreq-su.patch +++ b/target/linux/ipq806x/patches-4.9/0017-qcom-ipq4019-add-cpu-operating-points-for-cpufreq-su.patch @@ -45,7 +45,7 @@ Signed-off-by: Matthew McClintock }; cpu@3 { -@@ -81,6 +76,33 @@ +@@ -81,6 +76,29 @@ reg = <0x3>; clocks = <&gcc GCC_APPS_CLK_SRC>; clock-frequency = <0>; @@ -71,10 +71,6 @@ Signed-off-by: Matthew McClintock + }; + opp@666000000 { + opp-hz = /bits/ 64 <666000000>; -+ clock-latency-ns = <256000>; -+ }; -+ opp@717000000 { -+ opp-hz = /bits/ 64 <717000000>; + clock-latency-ns = <256000>; }; }; diff --git a/target/linux/ipq806x/patches-4.9/0018-qcom-ipq4019-turn-on-DMA-for-i2c.patch b/target/linux/ipq806x/patches-4.9/0018-qcom-ipq4019-turn-on-DMA-for-i2c.patch index a580610b2..42bb4a6e3 100644 --- a/target/linux/ipq806x/patches-4.9/0018-qcom-ipq4019-turn-on-DMA-for-i2c.patch +++ b/target/linux/ipq806x/patches-4.9/0018-qcom-ipq4019-turn-on-DMA-for-i2c.patch @@ -12,7 +12,7 @@ Signed-off-by: Matthew McClintock --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -183,6 +183,8 @@ +@@ -179,6 +179,8 @@ clock-names = "iface", "core"; #address-cells = <1>; #size-cells = <0>; diff --git a/target/linux/ipq806x/patches-4.9/0019-qcom-ipq4019-use-correct-clock-for-i2c-bus-0.patch b/target/linux/ipq806x/patches-4.9/0019-qcom-ipq4019-use-correct-clock-for-i2c-bus-0.patch index 64878e2c0..54ee571cb 100644 --- a/target/linux/ipq806x/patches-4.9/0019-qcom-ipq4019-use-correct-clock-for-i2c-bus-0.patch +++ b/target/linux/ipq806x/patches-4.9/0019-qcom-ipq4019-use-correct-clock-for-i2c-bus-0.patch @@ -17,7 +17,7 @@ Signed-off-by: Matthew McClintock --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -179,7 +179,7 @@ +@@ -175,7 +175,7 @@ reg = <0x78b7000 0x6000>; interrupts = ; clocks = <&gcc GCC_BLSP1_AHB_CLK>, diff --git a/target/linux/ipq806x/patches-4.9/0020-qcom-ipq4019-enable-DMA-for-spi.patch b/target/linux/ipq806x/patches-4.9/0020-qcom-ipq4019-enable-DMA-for-spi.patch index b5a533502..c1fa5c729 100644 --- a/target/linux/ipq806x/patches-4.9/0020-qcom-ipq4019-enable-DMA-for-spi.patch +++ b/target/linux/ipq806x/patches-4.9/0020-qcom-ipq4019-enable-DMA-for-spi.patch @@ -12,7 +12,7 @@ Signed-off-by: Matthew McClintock --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -171,6 +171,8 @@ +@@ -167,6 +167,8 @@ clock-names = "core", "iface"; #address-cells = <1>; #size-cells = <0>; diff --git a/target/linux/ipq806x/patches-4.9/0022-dts-ipq4019-support-ARMv7-PMU.patch b/target/linux/ipq806x/patches-4.9/0022-dts-ipq4019-support-ARMv7-PMU.patch deleted file mode 100644 index 2acfdcf29..000000000 --- a/target/linux/ipq806x/patches-4.9/0022-dts-ipq4019-support-ARMv7-PMU.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 47f00399b195e0987c67006b329587bef0692bf4 Mon Sep 17 00:00:00 2001 -From: Thomas Pedersen -Date: Wed, 4 May 2016 12:25:41 -0700 -Subject: [PATCH 22/69] dts: ipq4019: support ARMv7 PMU - -Add support for cortex-a7-pmu present on ipq4019 SoCs. - -Signed-off-by: Thomas Pedersen -Signed-off-by: Matthew McClintock ---- - arch/arm/boot/dts/qcom-ipq4019.dtsi | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/arch/arm/boot/dts/qcom-ipq4019.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -112,6 +112,12 @@ - IRQ_TYPE_LEVEL_HIGH)>; - }; - -+ pmu { -+ compatible = "arm,cortex-a7-pmu"; -+ interrupts = ; -+ }; -+ - clocks { - sleep_clk: sleep_clk { - compatible = "fixed-clock"; diff --git a/target/linux/ipq806x/patches-4.9/0026-dts-ipq4019-Add-support-for-IPQ4019-DK04-board.patch b/target/linux/ipq806x/patches-4.9/0026-dts-ipq4019-Add-support-for-IPQ4019-DK04-board.patch index de0ea8e89..8cd3e205d 100644 --- a/target/linux/ipq806x/patches-4.9/0026-dts-ipq4019-Add-support-for-IPQ4019-DK04-board.patch +++ b/target/linux/ipq806x/patches-4.9/0026-dts-ipq4019-Add-support-for-IPQ4019-DK04-board.patch @@ -34,7 +34,7 @@ Signed-off-by: Matthew McClintock qcom-msm8960-cdp.dtb \ --- /dev/null +++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c1.dts -@@ -0,0 +1,21 @@ +@@ -0,0 +1,22 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any @@ -55,6 +55,7 @@ Signed-off-by: Matthew McClintock + +/ { + model = "Qualcomm Technologies, Inc. IPQ40xx/AP-DK04.1-C1"; ++ compatible = "qcom,ap-dk04.1-c1", "qcom,ipq4019"; +}; --- /dev/null +++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi diff --git a/target/linux/ipq806x/patches-4.9/0032-phy-add-qcom-dwc3-phy.patch b/target/linux/ipq806x/patches-4.9/0032-phy-add-qcom-dwc3-phy.patch index a15a0d3a9..bd777858e 100644 --- a/target/linux/ipq806x/patches-4.9/0032-phy-add-qcom-dwc3-phy.patch +++ b/target/linux/ipq806x/patches-4.9/0032-phy-add-qcom-dwc3-phy.patch @@ -5,10 +5,10 @@ Subject: [PATCH 32/69] phy: add qcom dwc3 phy Signed-off-by: Andy Gross --- - drivers/phy/Kconfig | 12 ++ + drivers/phy/Kconfig | 12 + drivers/phy/Makefile | 1 + - drivers/phy/phy-qcom-dwc3.c | 484 ++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 497 insertions(+) + drivers/phy/phy-qcom-dwc3.c | 575 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 588 insertions(+) create mode 100644 drivers/phy/phy-qcom-dwc3.c --- a/drivers/phy/Kconfig @@ -32,14 +32,14 @@ Signed-off-by: Andy Gross endmenu --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile -@@ -60,3 +60,4 @@ obj-$(CONFIG_PHY_PISTACHIO_USB) += phy- +@@ -60,3 +60,4 @@ obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o +obj-$(CONFIG_PHY_QCOM_DWC3) += phy-qcom-dwc3.o --- /dev/null +++ b/drivers/phy/phy-qcom-dwc3.c -@@ -0,0 +1,492 @@ +@@ -0,0 +1,575 @@ +/* Copyright (c) 2014-2015, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify @@ -99,7 +99,7 @@ Signed-off-by: Andy Gross + +/* PHY_CTRL_REG */ +#define SSUSB_CTRL_REF_USE_PAD BIT(28) -+#define SSUSB_CTRL_TEST_POWERDOWN BIT(26) ++#define SSUSB_CTRL_TEST_POWERDOWN BIT(27) +#define SSUSB_CTRL_LANE0_PWR_PRESENT BIT(24) +#define SSUSB_CTRL_SS_PHY_EN BIT(8) +#define SSUSB_CTRL_SS_PHY_RESET BIT(7) @@ -108,6 +108,33 @@ Signed-off-by: Andy Gross +#define SSPHY_CTRL_RX_OVRD_IN_HI(lane) (0x1006 + 0x100 * lane) +#define SSPHY_CTRL_TX_OVRD_DRV_LO(lane) (0x1002 + 0x100 * lane) + ++/* SSPHY SoC version specific values */ ++#define SSPHY_RX_EQ_VALUE 4 /* Override value for rx_eq */ ++#define SSPHY_TX_DEEMPH_3_5DB 23 /* Override value for transmit ++ preemphasis */ ++#define SSPHY_MPLL_VALUE 0 /* Override value for mpll */ ++ ++/* QSCRATCH PHY_PARAM_CTRL1 fields */ ++#define PHY_PARAM_CTRL1_TX_FULL_SWING_MASK 0x07f00000u ++#define PHY_PARAM_CTRL1_TX_DEEMPH_6DB_MASK 0x000fc000u ++#define PHY_PARAM_CTRL1_TX_DEEMPH_3_5DB_MASK 0x00003f00u ++#define PHY_PARAM_CTRL1_LOS_BIAS_MASK 0x000000f8u ++ ++#define PHY_PARAM_CTRL1_MASK \ ++ (PHY_PARAM_CTRL1_TX_FULL_SWING_MASK | \ ++ PHY_PARAM_CTRL1_TX_DEEMPH_6DB_MASK | \ ++ PHY_PARAM_CTRL1_TX_DEEMPH_3_5DB_MASK | \ ++ PHY_PARAM_CTRL1_LOS_BIAS_MASK) ++ ++#define PHY_PARAM_CTRL1_TX_FULL_SWING(x) \ ++ (((x) << 20) & PHY_PARAM_CTRL1_TX_FULL_SWING_MASK) ++#define PHY_PARAM_CTRL1_TX_DEEMPH_6DB(x) \ ++ (((x) << 14) & PHY_PARAM_CTRL1_TX_DEEMPH_6DB_MASK) ++#define PHY_PARAM_CTRL1_TX_DEEMPH_3_5DB(x) \ ++ (((x) << 8) & PHY_PARAM_CTRL1_TX_DEEMPH_3_5DB_MASK) ++#define PHY_PARAM_CTRL1_LOS_BIAS(x) \ ++ (((x) << 3) & PHY_PARAM_CTRL1_LOS_BIAS_MASK) ++ +/* RX OVRD IN HI bits */ +#define RX_OVRD_IN_HI_RX_RESET_OVRD BIT(13) +#define RX_OVRD_IN_HI_RX_RX_RESET BIT(12) @@ -138,6 +165,9 @@ Signed-off-by: Andy Gross + struct device *dev; + struct clk *xo_clk; + struct clk *ref_clk; ++ u32 rx_eq; ++ u32 tx_deamp_3_5db; ++ u32 mpll; +}; + +struct qcom_dwc3_phy_drvdata { @@ -269,36 +299,21 @@ Signed-off-by: Andy Gross + return ret; +} + -+static int qcom_dwc3_phy_power_on(struct phy *phy) ++static int qcom_dwc3_hs_phy_init(struct phy *phy) +{ -+ int ret; + struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy); ++ int ret; ++ u32 val; + + ret = clk_prepare_enable(phy_dwc3->xo_clk); + if (ret) + return ret; + + ret = clk_prepare_enable(phy_dwc3->ref_clk); -+ if (ret) ++ if (ret) { + clk_disable_unprepare(phy_dwc3->xo_clk); -+ -+ return ret; -+} -+ -+static int qcom_dwc3_phy_power_off(struct phy *phy) -+{ -+ struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy); -+ -+ clk_disable_unprepare(phy_dwc3->ref_clk); -+ clk_disable_unprepare(phy_dwc3->xo_clk); -+ -+ return 0; -+} -+ -+static int qcom_dwc3_hs_phy_init(struct phy *phy) -+{ -+ struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy); -+ u32 val; ++ return ret; ++ } + + /* + * HSPHY Initialization: Enable UTMI clock, select 19.2MHz fsel @@ -323,22 +338,34 @@ Signed-off-by: Andy Gross + return 0; +} + ++static int qcom_dwc3_hs_phy_exit(struct phy *phy) ++{ ++ struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy); ++ ++ clk_disable_unprepare(phy_dwc3->ref_clk); ++ clk_disable_unprepare(phy_dwc3->xo_clk); ++ ++ return 0; ++} ++ +static int qcom_dwc3_ss_phy_init(struct phy *phy) +{ + struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy); + int ret; + u32 data = 0; + ++ ret = clk_prepare_enable(phy_dwc3->xo_clk); ++ if (ret) ++ return ret; ++ ++ ret = clk_prepare_enable(phy_dwc3->ref_clk); ++ if (ret) { ++ clk_disable_unprepare(phy_dwc3->xo_clk); ++ return ret; ++ } ++ + /* reset phy */ + data = readl(phy_dwc3->base + SSUSB_PHY_CTRL_REG); -+ -+ /* Test and clear SSUSB_CTRL_TEST_POWERDOWN */ -+ if (data & SSUSB_CTRL_TEST_POWERDOWN) { -+ qcom_dwc3_phy_write_readback(phy_dwc3, SSUSB_PHY_CTRL_REG, -+ SSUSB_CTRL_TEST_POWERDOWN, 0x0); -+ data = readl(phy_dwc3->base + SSUSB_PHY_CTRL_REG); -+ } -+ + writel(data | SSUSB_CTRL_SS_PHY_RESET, + phy_dwc3->base + SSUSB_PHY_CTRL_REG); + usleep_range(2000, 2200); @@ -359,10 +386,34 @@ Signed-off-by: Andy Gross + writel(data, phy_dwc3->base + SSUSB_PHY_CTRL_REG); + + /* ++ * WORKAROUND: There is SSPHY suspend bug due to which USB enumerates ++ * in HS mode instead of SS mode. Workaround it by asserting ++ * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus mode ++ */ ++ ret = qcom_dwc3_ss_read_phycreg(phy_dwc3->base, 0x102D, &data); ++ if (ret) ++ goto err_phy_trans; ++ ++ data |= (1 << 7); ++ ret = qcom_dwc3_ss_write_phycreg(phy_dwc3, 0x102D, data); ++ if (ret) ++ goto err_phy_trans; ++ ++ ret = qcom_dwc3_ss_read_phycreg(phy_dwc3->base, 0x1010, &data); ++ if (ret) ++ goto err_phy_trans; ++ ++ data &= ~0xff0; ++ data |= 0x20; ++ ret = qcom_dwc3_ss_write_phycreg(phy_dwc3, 0x1010, data); ++ if (ret) ++ goto err_phy_trans; ++ ++ /* + * Fix RX Equalization setting as follows + * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0 + * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1 -+ * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3 ++ * LANE0.RX_OVRD_IN_HI.RX_EQ set based on SoC version + * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1 + */ + ret = qcom_dwc3_ss_read_phycreg(phy_dwc3->base, @@ -373,7 +424,7 @@ Signed-off-by: Andy Gross + data &= ~RX_OVRD_IN_HI_RX_EQ_EN; + data |= RX_OVRD_IN_HI_RX_EQ_EN_OVRD; + data &= ~RX_OVRD_IN_HI_RX_EQ_MASK; -+ data |= 0x3 << RX_OVRD_IN_HI_RX_EQ_SHIFT; ++ data |= phy_dwc3->rx_eq << RX_OVRD_IN_HI_RX_EQ_SHIFT; + data |= RX_OVRD_IN_HI_RX_EQ_OVRD; + ret = qcom_dwc3_ss_write_phycreg(phy_dwc3, + SSPHY_CTRL_RX_OVRD_IN_HI(0), data); @@ -382,8 +433,8 @@ Signed-off-by: Andy Gross + + /* + * Set EQ and TX launch amplitudes as follows -+ * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22 -+ * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127 ++ * LANE0.TX_OVRD_DRV_LO.PREEMPH set based on SoC version ++ * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 110 + * LANE0.TX_OVRD_DRV_LO.EN set to 1. + */ + ret = qcom_dwc3_ss_read_phycreg(phy_dwc3->base, @@ -392,23 +443,35 @@ Signed-off-by: Andy Gross + goto err_phy_trans; + + data &= ~TX_OVRD_DRV_LO_PREEMPH_MASK; -+ data |= 0x16 << TX_OVRD_DRV_LO_PREEMPH_SHIFT; ++ data |= phy_dwc3->tx_deamp_3_5db << TX_OVRD_DRV_LO_PREEMPH_SHIFT; + data &= ~TX_OVRD_DRV_LO_AMPLITUDE_MASK; -+ data |= 0x7f; ++ data |= 0x6E; + data |= TX_OVRD_DRV_LO_EN; + ret = qcom_dwc3_ss_write_phycreg(phy_dwc3, + SSPHY_CTRL_TX_OVRD_DRV_LO(0), data); + if (ret) + goto err_phy_trans; + ++ qcom_dwc3_ss_write_phycreg(phy_dwc3, 0x30, phy_dwc3->mpll); ++ + /* + * Set the QSCRATCH PHY_PARAM_CTRL1 parameters as follows -+ * TX_FULL_SWING [26:20] amplitude to 127 -+ * TX_DEEMPH_3_5DB [13:8] to 22 -+ * LOS_BIAS [2:0] to 0x5 ++ * TX_FULL_SWING [26:20] amplitude to 110 ++ * TX_DEEMPH_6DB [19:14] to 32 ++ * TX_DEEMPH_3_5DB [13:8] set based on SoC version ++ * LOS_BIAS [7:3] to 9 + */ ++ data = readl(phy_dwc3->base + SSUSB_PHY_PARAM_CTRL_1); ++ ++ data &= ~PHY_PARAM_CTRL1_MASK; ++ ++ data |= PHY_PARAM_CTRL1_TX_FULL_SWING(0x6e) | ++ PHY_PARAM_CTRL1_TX_DEEMPH_6DB(0x20) | ++ PHY_PARAM_CTRL1_TX_DEEMPH_3_5DB(phy_dwc3->tx_deamp_3_5db) | ++ PHY_PARAM_CTRL1_LOS_BIAS(0x9); ++ + qcom_dwc3_phy_write_readback(phy_dwc3, SSUSB_PHY_PARAM_CTRL_1, -+ 0x07f03f07, 0x07f01605); ++ PHY_PARAM_CTRL1_MASK, data); + +err_phy_trans: + return ret; @@ -428,7 +491,10 @@ Signed-off-by: Andy Gross + qcom_dwc3_phy_write_readback(phy_dwc3, SSUSB_PHY_CTRL_REG, + SSUSB_CTRL_REF_USE_PAD, 0x0); + qcom_dwc3_phy_write_readback(phy_dwc3, SSUSB_PHY_CTRL_REG, -+ SSUSB_CTRL_TEST_POWERDOWN, SSUSB_CTRL_TEST_POWERDOWN); ++ SSUSB_CTRL_TEST_POWERDOWN, 0x0); ++ ++ clk_disable_unprepare(phy_dwc3->ref_clk); ++ clk_disable_unprepare(phy_dwc3->xo_clk); + + return 0; +} @@ -436,8 +502,7 @@ Signed-off-by: Andy Gross +static const struct qcom_dwc3_phy_drvdata qcom_dwc3_hs_drvdata = { + .ops = { + .init = qcom_dwc3_hs_phy_init, -+ .power_on = qcom_dwc3_phy_power_on, -+ .power_off = qcom_dwc3_phy_power_off, ++ .exit = qcom_dwc3_hs_phy_exit, + .owner = THIS_MODULE, + }, + .clk_rate = 60000000, @@ -447,8 +512,6 @@ Signed-off-by: Andy Gross + .ops = { + .init = qcom_dwc3_ss_phy_init, + .exit = qcom_dwc3_ss_phy_exit, -+ .power_on = qcom_dwc3_phy_power_on, -+ .power_off = qcom_dwc3_phy_power_off, + .owner = THIS_MODULE, + }, + .clk_rate = 125000000, @@ -469,6 +532,7 @@ Signed-off-by: Andy Gross + struct resource *res; + const struct of_device_id *match; + const struct qcom_dwc3_phy_drvdata *data; ++ struct device_node *np; + + phy_dwc3 = devm_kzalloc(&pdev->dev, sizeof(*phy_dwc3), GFP_KERNEL); + if (!phy_dwc3) @@ -498,6 +562,25 @@ Signed-off-by: Andy Gross + phy_dwc3->xo_clk = NULL; + } + ++ /* Parse device node to probe HSIO settings */ ++ np = of_node_get(pdev->dev.of_node); ++ if (!of_compat_cmp(match->compatible, "qcom,dwc3-ss-usb-phy", ++ strlen(match->compatible))) { ++ ++ if (of_property_read_u32(np, "rx_eq", &phy_dwc3->rx_eq) || ++ of_property_read_u32(np, "tx_deamp_3_5db", ++ &phy_dwc3->tx_deamp_3_5db) || ++ of_property_read_u32(np, "mpll", &phy_dwc3->mpll)) { ++ ++ dev_err(phy_dwc3->dev, "cannot get HSIO settings from device node, using default values\n"); ++ ++ /* Default HSIO settings */ ++ phy_dwc3->rx_eq = SSPHY_RX_EQ_VALUE; ++ phy_dwc3->tx_deamp_3_5db = SSPHY_TX_DEEMPH_3_5DB; ++ phy_dwc3->mpll = SSPHY_MPLL_VALUE; ++ } ++ } ++ + generic_phy = devm_phy_create(phy_dwc3->dev, pdev->dev.of_node, + &data->ops); + diff --git a/target/linux/ipq806x/patches-4.9/0034-ARM-Add-Krait-L2-register-accessor-functions.patch b/target/linux/ipq806x/patches-4.9/0034-ARM-Add-Krait-L2-register-accessor-functions.patch index 8c69b97cc..019170b6d 100644 --- a/target/linux/ipq806x/patches-4.9/0034-ARM-Add-Krait-L2-register-accessor-functions.patch +++ b/target/linux/ipq806x/patches-4.9/0034-ARM-Add-Krait-L2-register-accessor-functions.patch @@ -1,7 +1,21 @@ -From 1d6b12f73c98ecf252743936a53242356cc50a34 Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:19 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,01/12] ARM: Add Krait L2 register accessor functions +From: Sricharan R +X-Patchwork-Id: 10102101 +Message-Id: <1512726150-7204-2-git-send-email-sricharan@codeaurora.org> +To: mturquette@baylibre.com, sboyd@codeaurora.org, + devicetree@vger.kernel.org, linux-pm@vger.kernel.org, + linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, + viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org +Cc: sricharan@codeaurora.org, Mark Rutland , + Russell King , + Courtney Cavin +Date: Fri, 8 Dec 2017 15:12:19 +0530 + From: Stephen Boyd -Date: Fri, 20 Mar 2015 23:45:20 -0700 -Subject: [PATCH 34/69] ARM: Add Krait L2 register accessor functions Krait CPUs have a handful of L2 cache controller registers that live behind a cp15 based indirection register. First you program diff --git a/target/linux/ipq806x/patches-4.9/0035-clk-mux-Split-out-register-accessors-for-reuse.patch b/target/linux/ipq806x/patches-4.9/0035-clk-mux-Split-out-register-accessors-for-reuse.patch index 426cabd4e..5a64e6c56 100644 --- a/target/linux/ipq806x/patches-4.9/0035-clk-mux-Split-out-register-accessors-for-reuse.patch +++ b/target/linux/ipq806x/patches-4.9/0035-clk-mux-Split-out-register-accessors-for-reuse.patch @@ -1,7 +1,19 @@ -From 9d381d65eae163d8f50d97a3ad9033bba176f62b Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:20 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,02/12] clk: mux: Split out register accessors for reuse +From: Sricharan R +X-Patchwork-Id: 10102103 +Message-Id: <1512726150-7204-3-git-send-email-sricharan@codeaurora.org> +To: mturquette@baylibre.com, sboyd@codeaurora.org, + devicetree@vger.kernel.org, linux-pm@vger.kernel.org, + linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, + viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org +Cc: sricharan@codeaurora.org +Date: Fri, 8 Dec 2017 15:12:20 +0530 + From: Stephen Boyd -Date: Fri, 20 Mar 2015 23:45:21 -0700 -Subject: [PATCH 35/69] clk: mux: Split out register accessors for reuse We want to reuse the logic in clk-mux.c for other clock drivers that don't use readl as register accessors. Fortunately, there @@ -12,28 +24,25 @@ that operate on an optional table and some flags so that other drivers can use the same logic. Signed-off-by: Stephen Boyd -Signed-off-by: Georgi Djakov --- - drivers/clk/clk-mux.c | 76 ++++++++++++++++++++++++++++---------------- - include/linux/clk-provider.h | 11 +++++-- - 2 files changed, 57 insertions(+), 30 deletions(-) + drivers/clk/clk-mux.c | 75 +++++++++++++++++++++++++++----------------- + include/linux/clk-provider.h | 9 ++++-- + 2 files changed, 54 insertions(+), 30 deletions(-) --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c -@@ -26,35 +26,27 @@ +@@ -26,35 +26,24 @@ * parent - parent is adjustable through clk_set_parent */ -static u8 clk_mux_get_parent(struct clk_hw *hw) -+#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw) -+ +unsigned int clk_mux_get_parent(struct clk_hw *hw, unsigned int val, + unsigned int *table, unsigned long flags) { - struct clk_mux *mux = to_clk_mux(hw); +- struct clk_mux *mux = to_clk_mux(hw); int num_parents = clk_hw_get_num_parents(hw); - u32 val; - +- - /* - * FIXME need a mux-specific flag to determine if val is bitwise or numeric - * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1 @@ -43,7 +52,7 @@ Signed-off-by: Georgi Djakov - */ - val = clk_readl(mux->reg) >> mux->shift; - val &= mux->mask; -- + - if (mux->table) { + if (table) { int i; @@ -64,7 +73,7 @@ Signed-off-by: Georgi Djakov val--; if (val >= num_parents) -@@ -62,23 +54,53 @@ static u8 clk_mux_get_parent(struct clk_ +@@ -62,23 +51,53 @@ static u8 clk_mux_get_parent(struct clk_ return val; } @@ -80,9 +89,9 @@ Signed-off-by: Georgi Djakov - if (mux->table) { - index = mux->table[index]; + /* -+ * FIXME need a mux-specific flag to determine if val is bitwise or numeric -+ * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1 -+ * to 0x7 (index starts at one) ++ * FIXME need a mux-specific flag to determine if val is bitwise or ++ * numeric e.g. sys_clkin_ck's clksel field is 3 bits wide, ++ * but ranges from 0x1 to 0x7 (index starts at one) + * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so + * val = 0x4 really means "bit 2, index starts at bit 0" + */ @@ -126,7 +135,7 @@ Signed-off-by: Georgi Djakov if (mux->lock) spin_lock_irqsave(mux->lock, flags); else -@@ -102,14 +124,14 @@ static int clk_mux_set_parent(struct clk +@@ -102,14 +121,14 @@ static int clk_mux_set_parent(struct clk } const struct clk_ops clk_mux_ops = { @@ -143,7 +152,7 @@ Signed-off-by: Georgi Djakov }; EXPORT_SYMBOL_GPL(clk_mux_ro_ops); -@@ -117,7 +139,7 @@ struct clk_hw *clk_hw_register_mux_table +@@ -117,7 +136,7 @@ struct clk_hw *clk_hw_register_mux_table const char * const *parent_names, u8 num_parents, unsigned long flags, void __iomem *reg, u8 shift, u32 mask, @@ -175,13 +184,7 @@ Signed-off-by: Georgi Djakov struct clk *clk_register_mux(struct device *dev, const char *name, const char * const *parent_names, u8 num_parents, unsigned long flags, -@@ -499,12 +504,12 @@ struct clk *clk_register_mux_table(struc - const char * const *parent_names, u8 num_parents, - unsigned long flags, - void __iomem *reg, u8 shift, u32 mask, -- u8 clk_mux_flags, u32 *table, spinlock_t *lock); -+ u8 clk_mux_flags, unsigned int *table, spinlock_t *lock); - struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name, +@@ -504,7 +509,7 @@ struct clk_hw *clk_hw_register_mux_table const char * const *parent_names, u8 num_parents, unsigned long flags, void __iomem *reg, u8 shift, u32 mask, diff --git a/target/linux/ipq806x/patches-4.9/0036-clk-Avoid-sending-high-rates-to-downstream-clocks-du.patch b/target/linux/ipq806x/patches-4.9/0036-clk-Avoid-sending-high-rates-to-downstream-clocks-du.patch deleted file mode 100644 index f4a47c7ba..000000000 --- a/target/linux/ipq806x/patches-4.9/0036-clk-Avoid-sending-high-rates-to-downstream-clocks-du.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 88e1d6d9c113fe50810d1b03eb1fdbf015e5d1bd Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Fri, 20 Mar 2015 23:45:22 -0700 -Subject: [PATCH 36/69] clk: Avoid sending high rates to downstream clocks - during set_rate - -If a clock is on and we call clk_set_rate() on it we may get into -a situation where the clock temporarily increases in rate -dramatically while we walk the tree and call .set_rate() ops. For -example, consider a case where a PLL feeds into a divider. -Initially the divider is set to divide by 1 and the PLL is -running fairly slow (100MHz). The downstream consumer of the -divider output can only handle rates =< 400 MHz, but the divider -can only choose between divisors of 1 and 4. - - +-----+ +----------------+ - | PLL |-->| div 1 or div 4 |---> consumer device - +-----+ +----------------+ - -To achieve a rate of 400MHz on the output of the divider, we -would have to set the rate of the PLL to 1.6 GHz and then divide -it by 4. The current code would set the PLL to 1.6GHz first while -the divider is still set to 1, thus causing the downstream -consumer of the clock to receive a few clock cycles of 1.6GHz -clock (far beyond it's maximum acceptable rate). We should be -changing the divider first before increasing the PLL rate to -avoid this problem. - -Therefore, set the rate of any child clocks that are increasing -in rate from their current rate so that they can increase their -dividers if necessary. We assume that there isn't such a thing as -minimum rate requirements. - -Signed-off-by: Stephen Boyd - -Conflicts: - drivers/clk/clk.c ---- - drivers/clk/clk.c | 22 +++++++++++++++------- - 1 file changed, 15 insertions(+), 7 deletions(-) - ---- a/drivers/clk/clk.c -+++ b/drivers/clk/clk.c -@@ -1466,12 +1466,12 @@ static struct clk_core *clk_propagate_ra - * walk down a subtree and set the new rates notifying the rate - * change on the way - */ --static void clk_change_rate(struct clk_core *core) -+static void -+clk_change_rate(struct clk_core *core, unsigned long best_parent_rate) - { - struct clk_core *child; - struct hlist_node *tmp; - unsigned long old_rate; -- unsigned long best_parent_rate = 0; - bool skip_set_rate = false; - struct clk_core *old_parent; - struct clk_core *parent = NULL; -@@ -1523,6 +1523,7 @@ static void clk_change_rate(struct clk_c - trace_clk_set_rate_complete(core, core->new_rate); - - core->rate = clk_recalc(core, best_parent_rate); -+ core->rate = core->new_rate; - - if (core->flags & CLK_SET_RATE_UNGATE) { - unsigned long flags; -@@ -1550,12 +1551,13 @@ static void clk_change_rate(struct clk_c - /* Skip children who will be reparented to another clock */ - if (child->new_parent && child->new_parent != core) - continue; -- clk_change_rate(child); -+ if (child->new_rate != child->rate) -+ clk_change_rate(child, core->new_rate); - } - -- /* handle the new child who might not be in core->children yet */ -- if (core->new_child) -- clk_change_rate(core->new_child); -+ /* handle the new child who might not be in clk->children yet */ -+ if (core->new_child && core->new_child->new_rate != core->new_child->rate) -+ clk_change_rate(core->new_child, core->new_rate); - } - - static int clk_core_set_rate_nolock(struct clk_core *core, -@@ -1563,6 +1565,7 @@ static int clk_core_set_rate_nolock(stru - { - struct clk_core *top, *fail_clk; - unsigned long rate = req_rate; -+ unsigned long parent_rate; - - if (!core) - return 0; -@@ -1588,8 +1591,13 @@ static int clk_core_set_rate_nolock(stru - return -EBUSY; - } - -+ if (top->parent) -+ parent_rate = top->parent->rate; -+ else -+ parent_rate = 0; -+ - /* change the rates */ -- clk_change_rate(top); -+ clk_change_rate(top, parent_rate); - - core->req_rate = req_rate; - diff --git a/target/linux/ipq806x/patches-4.9/0037-clk-Add-safe-switch-hook.patch b/target/linux/ipq806x/patches-4.9/0037-clk-Add-safe-switch-hook.patch deleted file mode 100644 index bff605f8d..000000000 --- a/target/linux/ipq806x/patches-4.9/0037-clk-Add-safe-switch-hook.patch +++ /dev/null @@ -1,158 +0,0 @@ -From a1adfb782789ae9b25c928dfe3d639288563a86c Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Fri, 20 Mar 2015 23:45:23 -0700 -Subject: [PATCH 37/69] clk: Add safe switch hook - -Sometimes clocks can't accept their parent source turning off -while the source is reprogrammed to a different rate. Most -notably CPU clocks require a way to switch away from the current -PLL they're running on, reprogram that PLL to a new rate, and -then switch back to the PLL with the new rate once they're done. -Add a hook that drivers can implement allowing them to return a -'safe parent' and 'safe frequency' that they can switch their -parent to while the upstream source is reprogrammed to support -this. - -Signed-off-by: Stephen Boyd -Signed-off-by: Georgi Djakov ---- - drivers/clk/clk.c | 73 +++++++++++++++++++++++++++++++++++++++++--- - include/linux/clk-provider.h | 2 ++ - 2 files changed, 70 insertions(+), 5 deletions(-) - ---- a/drivers/clk/clk.c -+++ b/drivers/clk/clk.c -@@ -51,9 +51,13 @@ struct clk_core { - struct clk_core **parents; - u8 num_parents; - u8 new_parent_index; -+ u8 safe_parent_index; - unsigned long rate; - unsigned long req_rate; -+ unsigned long old_rate; - unsigned long new_rate; -+ unsigned long safe_freq; -+ struct clk_core *safe_parent; - struct clk_core *new_parent; - struct clk_core *new_child; - unsigned long flags; -@@ -1310,7 +1314,9 @@ out: - static void clk_calc_subtree(struct clk_core *core, unsigned long new_rate, - struct clk_core *new_parent, u8 p_index) - { -- struct clk_core *child; -+ struct clk_core *child, *parent; -+ struct clk_hw *parent_hw; -+ unsigned long safe_freq = 0; - - core->new_rate = new_rate; - core->new_parent = new_parent; -@@ -1320,6 +1326,23 @@ static void clk_calc_subtree(struct clk_ - if (new_parent && new_parent != core->parent) - new_parent->new_child = core; - -+ if (core->ops->get_safe_parent) { -+ parent_hw = core->ops->get_safe_parent(core->hw, &safe_freq); -+ if (parent_hw) { -+ parent = parent_hw->core; -+ p_index = clk_fetch_parent_index(core, parent); -+ core->safe_parent_index = p_index; -+ core->safe_parent = parent; -+ if (safe_freq) -+ core->safe_freq = safe_freq; -+ else -+ core->safe_freq = 0; -+ } -+ } else { -+ core->safe_parent = NULL; -+ core->safe_freq = 0; -+ } -+ - hlist_for_each_entry(child, &core->children, child_node) { - child->new_rate = clk_recalc(child, new_rate); - clk_calc_subtree(child, child->new_rate, NULL, 0); -@@ -1432,14 +1455,51 @@ static struct clk_core *clk_propagate_ra - unsigned long event) - { - struct clk_core *child, *tmp_clk, *fail_clk = NULL; -+ struct clk_core *old_parent; - int ret = NOTIFY_DONE; - -- if (core->rate == core->new_rate) -+ if (core->rate == core->new_rate && event != POST_RATE_CHANGE) - return NULL; - -+ switch (event) { -+ case PRE_RATE_CHANGE: -+ if (core->safe_parent) { -+ if (core->safe_freq) -+ core->ops->set_rate_and_parent(core->hw, -+ core->safe_freq, -+ core->safe_parent->rate, -+ core->safe_parent_index); -+ else -+ core->ops->set_parent(core->hw, -+ core->safe_parent_index); -+ } -+ core->old_rate = core->rate; -+ break; -+ case POST_RATE_CHANGE: -+ if (core->safe_parent) { -+ old_parent = __clk_set_parent_before(core, -+ core->new_parent); -+ if (core->ops->set_rate_and_parent) { -+ core->ops->set_rate_and_parent(core->hw, -+ core->new_rate, -+ core->new_parent ? -+ core->new_parent->rate : 0, -+ core->new_parent_index); -+ } else if (core->ops->set_parent) { -+ core->ops->set_parent(core->hw, -+ core->new_parent_index); -+ } -+ __clk_set_parent_after(core, core->new_parent, -+ old_parent); -+ } -+ break; -+ } -+ - if (core->notifier_count) { -- ret = __clk_notify(core, event, core->rate, core->new_rate); -- if (ret & NOTIFY_STOP_MASK) -+ if (event != POST_RATE_CHANGE || core->old_rate != core->rate) -+ ret = __clk_notify(core, event, core->old_rate, -+ core->new_rate); -+ if (ret & NOTIFY_STOP_MASK && event != POST_RATE_CHANGE) - fail_clk = core; - } - -@@ -1495,7 +1555,8 @@ clk_change_rate(struct clk_core *core, u - clk_enable_unlock(flags); - } - -- if (core->new_parent && core->new_parent != core->parent) { -+ if (core->new_parent && core->new_parent != core->parent && -+ !core->safe_parent) { - old_parent = __clk_set_parent_before(core, core->new_parent); - trace_clk_set_parent(core, core->new_parent); - -@@ -1601,6 +1662,8 @@ static int clk_core_set_rate_nolock(stru - - core->req_rate = req_rate; - -+ clk_propagate_rate_change(top, POST_RATE_CHANGE); -+ - return 0; - } - ---- a/include/linux/clk-provider.h -+++ b/include/linux/clk-provider.h -@@ -206,6 +206,8 @@ struct clk_ops { - struct clk_rate_request *req); - int (*set_parent)(struct clk_hw *hw, u8 index); - u8 (*get_parent)(struct clk_hw *hw); -+ struct clk_hw *(*get_safe_parent)(struct clk_hw *hw, -+ unsigned long *safe_freq); - int (*set_rate)(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate); - int (*set_rate_and_parent)(struct clk_hw *hw, diff --git a/target/linux/ipq806x/patches-4.9/0038-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch b/target/linux/ipq806x/patches-4.9/0038-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch index e3797cfb7..70926143e 100644 --- a/target/linux/ipq806x/patches-4.9/0038-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch +++ b/target/linux/ipq806x/patches-4.9/0038-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch @@ -1,7 +1,19 @@ -From f044ffe2d612dcaa2de36c918aaab79c8db1482e Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:21 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,03/12] clk: qcom: Add support for High-Frequency PLLs (HFPLLs) +From: Sricharan R +X-Patchwork-Id: 10102083 +Message-Id: <1512726150-7204-4-git-send-email-sricharan@codeaurora.org> +To: mturquette@baylibre.com, sboyd@codeaurora.org, + devicetree@vger.kernel.org, linux-pm@vger.kernel.org, + linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, + viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org +Cc: sricharan@codeaurora.org +Date: Fri, 8 Dec 2017 15:12:21 +0530 + From: Stephen Boyd -Date: Fri, 20 Mar 2015 23:45:24 -0700 -Subject: [PATCH 38/69] clk: qcom: Add support for High-Frequency PLLs (HFPLLs) HFPLLs are the main frequency source for Krait CPU clocks. Add support for changing the rate of these PLLs. @@ -105,7 +117,7 @@ Signed-off-by: Stephen Boyd + * H/W requires a 5us delay between disabling the bypass and + * de-asserting the reset. Delay 10us just to be safe. + */ -+ udelay(10); ++ usleep_range(10, 100); + + /* De-assert active-low PLL reset. */ + regmap_update_bits(regmap, hd->mode_reg, PLL_RESET_N, PLL_RESET_N); @@ -116,7 +128,7 @@ Signed-off-by: Stephen Boyd + regmap_read(regmap, hd->status_reg, &val); + } while (!(val & BIT(hd->lock_bit))); + } else { -+ udelay(60); ++ usleep_range(60, 100); + } + + /* Enable PLL output. */ @@ -151,7 +163,7 @@ Signed-off-by: Stephen Boyd + * and assert the reset. + */ + regmap_update_bits(regmap, hd->mode_reg, -+ PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL, 0); ++ PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL, 0); +} + +static void clk_hfpll_disable(struct clk_hw *hw) @@ -252,7 +264,7 @@ Signed-off-by: Stephen Boyd + regmap_read(regmap, hd->status_reg, &status); + if (!(status & BIT(hd->lock_bit))) { + WARN(1, "HFPLL %s is ON, but not locked!\n", -+ __clk_get_name(hw->clk)); ++ __clk_get_name(hw->clk)); + clk_hfpll_disable(hw); + __clk_hfpll_init_once(hw); + } diff --git a/target/linux/ipq806x/patches-4.9/0039-clk-qcom-Add-HFPLL-driver.patch b/target/linux/ipq806x/patches-4.9/0039-clk-qcom-Add-HFPLL-driver.patch index 92266f763..d9ad391d0 100644 --- a/target/linux/ipq806x/patches-4.9/0039-clk-qcom-Add-HFPLL-driver.patch +++ b/target/linux/ipq806x/patches-4.9/0039-clk-qcom-Add-HFPLL-driver.patch @@ -1,7 +1,19 @@ -From 23f680d03e5894f494572a5162d21328bd86890c Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:22 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,04/12] clk: qcom: Add HFPLL driver +From: Sricharan R +X-Patchwork-Id: 10102079 +Message-Id: <1512726150-7204-5-git-send-email-sricharan@codeaurora.org> +To: mturquette@baylibre.com, sboyd@codeaurora.org, + devicetree@vger.kernel.org, linux-pm@vger.kernel.org, + linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, + viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org +Cc: sricharan@codeaurora.org +Date: Fri, 8 Dec 2017 15:12:22 +0530 + From: Stephen Boyd -Date: Fri, 20 Mar 2015 23:45:25 -0700 -Subject: [PATCH 39/69] clk: qcom: Add HFPLL driver On some devices (MSM8974 for example), the HFPLLs are instantiated within the Krait processor subsystem as separate @@ -10,7 +22,6 @@ provide HFPLL clocks for use by the system. Cc: Signed-off-by: Stephen Boyd -Signed-off-by: Georgi Djakov --- .../devicetree/bindings/clock/qcom,hfpll.txt | 40 ++++++++ drivers/clk/qcom/Kconfig | 8 ++ @@ -171,7 +182,7 @@ Signed-off-by: Georgi Djakov + return PTR_ERR(regmap); + + if (of_property_read_string_index(dev->of_node, "clock-output-names", -+ 0, &init.name)) ++ 0, &init.name)) + return -ENODEV; + + h->d = &hdata; diff --git a/target/linux/ipq806x/patches-4.9/0040-clk-qcom-Add-IPQ806X-s-HFPLLs.patch b/target/linux/ipq806x/patches-4.9/0040-clk-qcom-Add-IPQ806X-s-HFPLLs.patch index 8a51af79d..c3af0fa55 100644 --- a/target/linux/ipq806x/patches-4.9/0040-clk-qcom-Add-IPQ806X-s-HFPLLs.patch +++ b/target/linux/ipq806x/patches-4.9/0040-clk-qcom-Add-IPQ806X-s-HFPLLs.patch @@ -1,14 +1,26 @@ -From 0dfdf84ee3982e88a62123b3de1c094d2c0829af Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:24 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,06/12] clk: qcom: Add IPQ806X's HFPLLs +From: Sricharan R +X-Patchwork-Id: 10102047 +Message-Id: <1512726150-7204-7-git-send-email-sricharan@codeaurora.org> +To: mturquette@baylibre.com, sboyd@codeaurora.org, + devicetree@vger.kernel.org, linux-pm@vger.kernel.org, + linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, + viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org +Cc: sricharan@codeaurora.org +Date: Fri, 8 Dec 2017 15:12:24 +0530 + From: Stephen Boyd -Date: Fri, 20 Mar 2015 23:45:27 -0700 -Subject: [PATCH 40/69] clk: qcom: Add IPQ806X's HFPLLs Describe the HFPLLs present on IPQ806X devices. Signed-off-by: Stephen Boyd --- - drivers/clk/qcom/gcc-ipq806x.c | 83 ++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 83 insertions(+) + drivers/clk/qcom/gcc-ipq806x.c | 82 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 82 insertions(+) --- a/drivers/clk/qcom/gcc-ipq806x.c +++ b/drivers/clk/qcom/gcc-ipq806x.c @@ -20,7 +32,7 @@ Signed-off-by: Stephen Boyd #include "reset.h" static struct clk_pll pll0 = { -@@ -113,6 +114,85 @@ static struct clk_regmap pll8_vote = { +@@ -113,6 +114,84 @@ static struct clk_regmap pll8_vote = { }, }; @@ -101,12 +113,11 @@ Signed-off-by: Stephen Boyd + }, + .lock = __SPIN_LOCK_UNLOCKED(hfpll_l2.lock), +}; -+ + static struct clk_pll pll14 = { .l_reg = 0x31c4, .m_reg = 0x31c8, -@@ -2801,6 +2881,9 @@ static struct clk_regmap *gcc_ipq806x_cl +@@ -2801,6 +2880,9 @@ static struct clk_regmap *gcc_ipq806x_cl [UBI32_CORE2_CLK_SRC] = &ubi32_core2_src_clk.clkr, [NSSTCM_CLK_SRC] = &nss_tcm_src.clkr, [NSSTCM_CLK] = &nss_tcm_clk.clkr, diff --git a/target/linux/ipq806x/patches-4.9/0041-clk-qcom-Add-support-for-Krait-clocks.patch b/target/linux/ipq806x/patches-4.9/0041-clk-qcom-Add-support-for-Krait-clocks.patch index 902e49d60..a6d0f0d7a 100644 --- a/target/linux/ipq806x/patches-4.9/0041-clk-qcom-Add-support-for-Krait-clocks.patch +++ b/target/linux/ipq806x/patches-4.9/0041-clk-qcom-Add-support-for-Krait-clocks.patch @@ -1,7 +1,19 @@ -From b9747125a8e7633ed2701a70e32dbb0442193774 Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:25 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,07/12] clk: qcom: Add support for Krait clocks +From: Sricharan R +X-Patchwork-Id: 10102051 +Message-Id: <1512726150-7204-8-git-send-email-sricharan@codeaurora.org> +To: mturquette@baylibre.com, sboyd@codeaurora.org, + devicetree@vger.kernel.org, linux-pm@vger.kernel.org, + linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, + viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org +Cc: sricharan@codeaurora.org +Date: Fri, 8 Dec 2017 15:12:25 +0530 + From: Stephen Boyd -Date: Fri, 20 Mar 2015 23:45:28 -0700 -Subject: [PATCH 41/69] clk: qcom: Add support for Krait clocks The Krait clocks are made up of a series of muxes and a divider that choose between a fixed rate clock and dedicated HFPLLs for @@ -13,9 +25,9 @@ Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 4 ++ drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/clk-krait.c | 167 +++++++++++++++++++++++++++++++++++++++++++ - drivers/clk/qcom/clk-krait.h | 49 +++++++++++++ - 4 files changed, 221 insertions(+) + drivers/clk/qcom/clk-krait.c | 134 +++++++++++++++++++++++++++++++++++++++++++ + drivers/clk/qcom/clk-krait.h | 48 ++++++++++++++++ + 4 files changed, 187 insertions(+) create mode 100644 drivers/clk/qcom/clk-krait.c create mode 100644 drivers/clk/qcom/clk-krait.h @@ -41,7 +53,7 @@ Signed-off-by: Stephen Boyd clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o --- /dev/null +++ b/drivers/clk/qcom/clk-krait.c -@@ -0,0 +1,167 @@ +@@ -0,0 +1,134 @@ +/* + * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + * @@ -103,6 +115,7 @@ Signed-off-by: Stephen Boyd + /* Don't touch mux if CPU is off as it won't work */ + if (__clk_is_enabled(hw->clk)) + __krait_mux_set_sel(mux, sel); ++ + return 0; +} + @@ -119,44 +132,10 @@ Signed-off-by: Stephen Boyd + return clk_mux_get_parent(hw, sel, mux->parent_map, 0); +} + -+static struct clk_hw *krait_mux_get_safe_parent(struct clk_hw *hw, -+ unsigned long *safe_freq) -+{ -+ int i; -+ struct krait_mux_clk *mux = to_krait_mux_clk(hw); -+ int num_parents = clk_hw_get_num_parents(hw); -+ -+ i = mux->safe_sel; -+ for (i = 0; i < num_parents; i++) -+ if (mux->safe_sel == mux->parent_map[i]) -+ break; -+ -+ return clk_hw_get_parent_by_index(hw, i); -+} -+ -+static int krait_mux_enable(struct clk_hw *hw) -+{ -+ struct krait_mux_clk *mux = to_krait_mux_clk(hw); -+ -+ __krait_mux_set_sel(mux, mux->en_mask); -+ -+ return 0; -+} -+ -+static void krait_mux_disable(struct clk_hw *hw) -+{ -+ struct krait_mux_clk *mux = to_krait_mux_clk(hw); -+ -+ __krait_mux_set_sel(mux, mux->safe_sel); -+} -+ +const struct clk_ops krait_mux_clk_ops = { -+ .enable = krait_mux_enable, -+ .disable = krait_mux_disable, + .set_parent = krait_mux_set_parent, + .get_parent = krait_mux_get_parent, + .determine_rate = __clk_mux_determine_rate_closest, -+ .get_safe_parent = krait_mux_get_safe_parent, +}; +EXPORT_SYMBOL_GPL(krait_mux_clk_ops); + @@ -169,7 +148,7 @@ Signed-off-by: Stephen Boyd +} + +static int krait_div2_set_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long parent_rate) ++ unsigned long parent_rate) +{ + struct krait_div2_clk *d = to_krait_div2_clk(hw); + unsigned long flags; @@ -211,7 +190,7 @@ Signed-off-by: Stephen Boyd +EXPORT_SYMBOL_GPL(krait_div2_clk_ops); --- /dev/null +++ b/drivers/clk/qcom/clk-krait.h -@@ -0,0 +1,49 @@ +@@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * @@ -232,8 +211,6 @@ Signed-off-by: Stephen Boyd + +struct krait_mux_clk { + unsigned int *parent_map; -+ bool has_safe_parent; -+ u8 safe_sel; + u32 offset; + u32 mask; + u32 shift; @@ -241,6 +218,7 @@ Signed-off-by: Stephen Boyd + bool lpl; + + struct clk_hw hw; ++ struct notifier_block clk_nb; +}; + +#define to_krait_mux_clk(_hw) container_of(_hw, struct krait_mux_clk, hw) diff --git a/target/linux/ipq806x/patches-4.9/0042-clk-qcom-Add-KPSS-ACC-GCC-driver.patch b/target/linux/ipq806x/patches-4.9/0042-clk-qcom-Add-KPSS-ACC-GCC-driver.patch index c49943647..5a76fbc8b 100644 --- a/target/linux/ipq806x/patches-4.9/0042-clk-qcom-Add-KPSS-ACC-GCC-driver.patch +++ b/target/linux/ipq806x/patches-4.9/0042-clk-qcom-Add-KPSS-ACC-GCC-driver.patch @@ -1,7 +1,19 @@ -From 6039eb63fabdd6871fc70940aa98102665c78eed Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:26 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,08/12] clk: qcom: Add KPSS ACC/GCC driver +From: Sricharan R +X-Patchwork-Id: 10102023 +Message-Id: <1512726150-7204-9-git-send-email-sricharan@codeaurora.org> +To: mturquette@baylibre.com, sboyd@codeaurora.org, + devicetree@vger.kernel.org, linux-pm@vger.kernel.org, + linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, + viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org +Cc: sricharan@codeaurora.org +Date: Fri, 8 Dec 2017 15:12:26 +0530 + From: Stephen Boyd -Date: Fri, 20 Mar 2015 23:45:29 -0700 -Subject: [PATCH 42/69] clk: qcom: Add KPSS ACC/GCC driver The ACC and GCC regions present in KPSSv1 contain registers to control clocks and power to each Krait CPU and L2. For CPUfreq @@ -15,8 +27,8 @@ Signed-off-by: Stephen Boyd .../devicetree/bindings/arm/msm/qcom,kpss-gcc.txt | 28 +++++++ drivers/clk/qcom/Kconfig | 8 ++ drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/kpss-xcc.c | 95 ++++++++++++++++++++++ - 5 files changed, 139 insertions(+) + drivers/clk/qcom/kpss-xcc.c | 96 ++++++++++++++++++++++ + 5 files changed, 140 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt create mode 100644 drivers/clk/qcom/kpss-xcc.c @@ -98,7 +110,7 @@ Signed-off-by: Stephen Boyd obj-$(CONFIG_QCOM_HFPLL) += hfpll.o --- /dev/null +++ b/drivers/clk/qcom/kpss-xcc.c -@@ -0,0 +1,95 @@ +@@ -0,0 +1,96 @@ +/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify @@ -158,7 +170,8 @@ Signed-off-by: Stephen Boyd + + if (id->data) { + if (of_property_read_string_index(pdev->dev.of_node, -+ "clock-output-names", 0, &name)) ++ "clock-output-names", ++ 0, &name)) + return -ENODEV; + base += 0x14; + } else { diff --git a/target/linux/ipq806x/patches-4.9/0043-clk-qcom-Add-Krait-clock-controller-driver.patch b/target/linux/ipq806x/patches-4.9/0043-clk-qcom-Add-Krait-clock-controller-driver.patch index 7e2e41e3b..1d32b2b05 100644 --- a/target/linux/ipq806x/patches-4.9/0043-clk-qcom-Add-Krait-clock-controller-driver.patch +++ b/target/linux/ipq806x/patches-4.9/0043-clk-qcom-Add-Krait-clock-controller-driver.patch @@ -1,7 +1,19 @@ -From 7fb5976eb0231a06f484a6bde5e5fbfee7ee4f4a Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:27 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,09/12] clk: qcom: Add Krait clock controller driver +From: Sricharan R +X-Patchwork-Id: 10102061 +Message-Id: <1512726150-7204-10-git-send-email-sricharan@codeaurora.org> +To: mturquette@baylibre.com, sboyd@codeaurora.org, + devicetree@vger.kernel.org, linux-pm@vger.kernel.org, + linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, + viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org +Cc: sricharan@codeaurora.org +Date: Fri, 8 Dec 2017 15:12:27 +0530 + From: Stephen Boyd -Date: Fri, 20 Mar 2015 23:45:30 -0700 -Subject: [PATCH 43/69] clk: qcom: Add Krait clock controller driver The Krait CPU clocks are made up of a primary mux and secondary mux for each CPU and the L2, controlled via cp15 accessors. For @@ -15,8 +27,8 @@ Signed-off-by: Stephen Boyd .../devicetree/bindings/clock/qcom,krait-cc.txt | 22 ++ drivers/clk/qcom/Kconfig | 8 + drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/krait-cc.c | 352 +++++++++++++++++++++ - 4 files changed, 383 insertions(+) + drivers/clk/qcom/krait-cc.c | 350 +++++++++++++++++++++ + 4 files changed, 381 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,krait-cc.txt create mode 100644 drivers/clk/qcom/krait-cc.c @@ -71,7 +83,7 @@ Signed-off-by: Stephen Boyd +obj-$(CONFIG_KRAITCC) += krait-cc.o --- /dev/null +++ b/drivers/clk/qcom/krait-cc.c -@@ -0,0 +1,352 @@ +@@ -0,0 +1,350 @@ +/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify @@ -110,7 +122,7 @@ Signed-off-by: Stephen Boyd +}; + +static int -+krait_add_div(struct device *dev, int id, const char *s, unsigned offset) ++krait_add_div(struct device *dev, int id, const char *s, unsigned int offset) +{ + struct krait_div2_clk *div; + struct clk_init_data init = { @@ -150,8 +162,8 @@ Signed-off-by: Stephen Boyd +} + +static int -+krait_add_sec_mux(struct device *dev, int id, const char *s, unsigned offset, -+ bool unique_aux) ++krait_add_sec_mux(struct device *dev, int id, const char *s, ++ unsigned int offset, bool unique_aux) +{ + struct krait_mux_clk *mux; + static const char *sec_mux_list[] = { @@ -172,8 +184,6 @@ Signed-off-by: Stephen Boyd + + mux->offset = offset; + mux->lpl = id >= 0; -+ mux->has_safe_parent = true; -+ mux->safe_sel = 2; + mux->mask = 0x3; + mux->shift = 2; + mux->parent_map = sec_mux_map; @@ -201,7 +211,8 @@ Signed-off-by: Stephen Boyd +} + +static struct clk * -+krait_add_pri_mux(struct device *dev, int id, const char *s, unsigned offset) ++krait_add_pri_mux(struct device *dev, int id, const char *s, ++ unsigned int offset) +{ + struct krait_mux_clk *mux; + const char *p_names[3]; @@ -217,8 +228,6 @@ Signed-off-by: Stephen Boyd + if (!mux) + return ERR_PTR(-ENOMEM); + -+ mux->has_safe_parent = true; -+ mux->safe_sel = 0; + mux->mask = 0x3; + mux->shift = 0; + mux->offset = offset; @@ -264,7 +273,7 @@ Signed-off-by: Stephen Boyd +static struct clk *krait_add_clks(struct device *dev, int id, bool unique_aux) +{ + int ret; -+ unsigned offset; ++ unsigned int offset; + void *p = NULL; + const char *s; + struct clk *clk; @@ -332,7 +341,7 @@ Signed-off-by: Stephen Boyd + return -ENODEV; + + /* Rate is 1 because 0 causes problems for __clk_mux_determine_rate */ -+ clk = clk_register_fixed_rate(dev, "qsb", NULL, CLK_IS_ROOT, 1); ++ clk = clk_register_fixed_rate(dev, "qsb", NULL, 0, 1); + if (IS_ERR(clk)) + return PTR_ERR(clk); + @@ -370,7 +379,7 @@ Signed-off-by: Stephen Boyd + for_each_online_cpu(cpu) { + clk_prepare_enable(l2_pri_mux_clk); + WARN(clk_prepare_enable(clks[cpu]), -+ "Unable to turn on CPU%d clock", cpu); ++ "Unable to turn on CPU%d clock", cpu); + } + + /* @@ -401,6 +410,7 @@ Signed-off-by: Stephen Boyd + pr_info("CPU%d @ QSB rate. Forcing new rate.\n", cpu); + cur_rate = aux_rate; + } ++ + clk_set_rate(clk, aux_rate); + clk_set_rate(clk, 2); + clk_set_rate(clk, cur_rate); diff --git a/target/linux/ipq806x/patches-4.9/0044-clk-Add-safe-switch-hook.patch b/target/linux/ipq806x/patches-4.9/0044-clk-Add-safe-switch-hook.patch new file mode 100644 index 000000000..d0eddc64c --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/0044-clk-Add-safe-switch-hook.patch @@ -0,0 +1,160 @@ +From patchwork Fri Dec 8 09:42:28 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,10/12] clk: qcom: Add safe switch hook for krait mux clocks +From: Sricharan R +X-Patchwork-Id: 10102057 +Message-Id: <1512726150-7204-11-git-send-email-sricharan@codeaurora.org> +To: mturquette@baylibre.com, sboyd@codeaurora.org, + devicetree@vger.kernel.org, linux-pm@vger.kernel.org, + linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, + viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org +Cc: sricharan@codeaurora.org +Date: Fri, 8 Dec 2017 15:12:28 +0530 + +When the Hfplls are reprogrammed during the rate change, +the primary muxes which are sourced from the same hfpll +for higher frequencies, needs to be switched to the 'safe +secondary mux' as the parent for that small window. This +is done by registering a clk notifier for the muxes and +switching to the safe parent in the PRE_RATE_CHANGE notifier +and back to the original parent in the POST_RATE_CHANGE notifier. + +Signed-off-by: Sricharan R +--- + drivers/clk/qcom/clk-krait.c | 2 ++ + drivers/clk/qcom/clk-krait.h | 3 +++ + drivers/clk/qcom/krait-cc.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 61 insertions(+) + +--- a/drivers/clk/qcom/clk-krait.c ++++ b/drivers/clk/qcom/clk-krait.c +@@ -60,6 +60,8 @@ static int krait_mux_set_parent(struct c + if (__clk_is_enabled(hw->clk)) + __krait_mux_set_sel(mux, sel); + ++ mux->reparent = true; ++ + return 0; + } + +--- a/drivers/clk/qcom/clk-krait.h ++++ b/drivers/clk/qcom/clk-krait.h +@@ -23,6 +23,9 @@ struct krait_mux_clk { + u32 shift; + u32 en_mask; + bool lpl; ++ u8 safe_sel; ++ u8 old_index; ++ bool reparent; + + struct clk_hw hw; + struct notifier_block clk_nb; +--- a/drivers/clk/qcom/krait-cc.c ++++ b/drivers/clk/qcom/krait-cc.c +@@ -35,6 +35,49 @@ static unsigned int pri_mux_map[] = { + 0, + }; + ++/* ++ * Notifier function for switching the muxes to safe parent ++ * while the hfpll is getting reprogrammed. ++ */ ++static int krait_notifier_cb(struct notifier_block *nb, ++ unsigned long event, ++ void *data) ++{ ++ int ret = 0; ++ struct krait_mux_clk *mux = container_of(nb, struct krait_mux_clk, ++ clk_nb); ++ /* Switch to safe parent */ ++ if (event == PRE_RATE_CHANGE) { ++ mux->old_index = krait_mux_clk_ops.get_parent(&mux->hw); ++ ret = krait_mux_clk_ops.set_parent(&mux->hw, mux->safe_sel); ++ mux->reparent = false; ++ /* ++ * By the time POST_RATE_CHANGE notifier is called, ++ * clk framework itself would have changed the parent for the new rate. ++ * Only otherwise, put back to the old parent. ++ */ ++ } else if (event == POST_RATE_CHANGE) { ++ if (!mux->reparent) ++ ret = krait_mux_clk_ops.set_parent(&mux->hw, ++ mux->old_index); ++ } ++ ++ return notifier_from_errno(ret); ++} ++ ++static int krait_notifier_register(struct device *dev, struct clk *clk, ++ struct krait_mux_clk *mux) ++{ ++ int ret = 0; ++ ++ mux->clk_nb.notifier_call = krait_notifier_cb; ++ ret = clk_notifier_register(clk, &mux->clk_nb); ++ if (ret) ++ dev_err(dev, "failed to register clock notifier: %d\n", ret); ++ ++ return ret; ++} ++ + static int + krait_add_div(struct device *dev, int id, const char *s, unsigned int offset) + { +@@ -79,6 +122,7 @@ static int + krait_add_sec_mux(struct device *dev, int id, const char *s, + unsigned int offset, bool unique_aux) + { ++ int ret; + struct krait_mux_clk *mux; + static const char *sec_mux_list[] = { + "acpu_aux", +@@ -102,6 +146,7 @@ krait_add_sec_mux(struct device *dev, in + mux->shift = 2; + mux->parent_map = sec_mux_map; + mux->hw.init = &init; ++ mux->safe_sel = 0; + + init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s); + if (!init.name) +@@ -117,6 +162,11 @@ krait_add_sec_mux(struct device *dev, in + + clk = devm_clk_register(dev, &mux->hw); + ++ ret = krait_notifier_register(dev, clk, mux); ++ if (ret) ++ goto unique_aux; ++ ++unique_aux: + if (unique_aux) + kfree(sec_mux_list[0]); + err_aux: +@@ -128,6 +178,7 @@ static struct clk * + krait_add_pri_mux(struct device *dev, int id, const char *s, + unsigned int offset) + { ++ int ret; + struct krait_mux_clk *mux; + const char *p_names[3]; + struct clk_init_data init = { +@@ -148,6 +199,7 @@ krait_add_pri_mux(struct device *dev, in + mux->lpl = id >= 0; + mux->parent_map = pri_mux_map; + mux->hw.init = &init; ++ mux->safe_sel = 2; + + init.name = kasprintf(GFP_KERNEL, "krait%s_pri_mux", s); + if (!init.name) +@@ -173,6 +225,10 @@ krait_add_pri_mux(struct device *dev, in + + clk = devm_clk_register(dev, &mux->hw); + ++ ret = krait_notifier_register(dev, clk, mux); ++ if (ret) ++ goto err_p3; ++err_p3: + kfree(p_names[2]); + err_p2: + kfree(p_names[1]); diff --git a/target/linux/ipq806x/patches-4.9/0044-clk-qcom-krait-Remove-CLK_IS_ROOT.patch b/target/linux/ipq806x/patches-4.9/0044-clk-qcom-krait-Remove-CLK_IS_ROOT.patch deleted file mode 100644 index c3761eef5..000000000 --- a/target/linux/ipq806x/patches-4.9/0044-clk-qcom-krait-Remove-CLK_IS_ROOT.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 58f8215f1d9397f9130657cc2c15a956bd99210e Mon Sep 17 00:00:00 2001 -From: Georgi Djakov -Date: Wed, 13 Jul 2016 15:22:25 +0300 -Subject: [PATCH 44/69] clk: qcom: krait: Remove CLK_IS_ROOT - -The flag CLK_IS_ROOT is no-op now. Remove it. - -Signed-off-by: Georgi Djakov ---- - drivers/clk/qcom/krait-cc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/clk/qcom/krait-cc.c -+++ b/drivers/clk/qcom/krait-cc.c -@@ -258,7 +258,7 @@ static int krait_cc_probe(struct platfor - return -ENODEV; - - /* Rate is 1 because 0 causes problems for __clk_mux_determine_rate */ -- clk = clk_register_fixed_rate(dev, "qsb", NULL, CLK_IS_ROOT, 1); -+ clk = clk_register_fixed_rate(dev, "qsb", NULL, 0, 1); - if (IS_ERR(clk)) - return PTR_ERR(clk); - diff --git a/target/linux/ipq806x/patches-4.9/0045-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch b/target/linux/ipq806x/patches-4.9/0045-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch index f5b5ea0fd..820d13f3c 100644 --- a/target/linux/ipq806x/patches-4.9/0045-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch +++ b/target/linux/ipq806x/patches-4.9/0045-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch @@ -1,7 +1,19 @@ -From 42eea6bc2858ab9649cf6931455e391e48939685 Mon Sep 17 00:00:00 2001 +From patchwork Fri Dec 8 09:42:29 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,11/12] cpufreq: Add module to register cpufreq on Krait CPUs +From: Sricharan R +X-Patchwork-Id: 10102075 +Message-Id: <1512726150-7204-12-git-send-email-sricharan@codeaurora.org> +To: mturquette@baylibre.com, sboyd@codeaurora.org, + devicetree@vger.kernel.org, linux-pm@vger.kernel.org, + linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, + viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org +Cc: sricharan@codeaurora.org +Date: Fri, 8 Dec 2017 15:12:29 +0530 + From: Stephen Boyd -Date: Fri, 20 Mar 2015 23:45:31 -0700 -Subject: [PATCH 45/69] cpufreq: Add module to register cpufreq on Krait CPUs Register a cpufreq-generic device whenever we detect that a "qcom,krait" compatible CPU is present in DT. @@ -111,7 +123,7 @@ Signed-off-by: Stephen Boyd +#include +#include +#include -+#include ++#include "cpufreq-dt.h" + +static void __init get_krait_bin_format_a(int *speed, int *pvs, int *pvs_ver) +{ @@ -227,7 +239,7 @@ Signed-off-by: Stephen Boyd + } + + snprintf(table_name, sizeof(table_name), -+ "qcom,speed%d-pvs%d-bin-v%d", speed, pvs, pvs_ver); ++ "qcom,speed%d-pvs%d-bin-v%d", speed, pvs, pvs_ver); + + if (!of_find_property(np, table_name, &len)) + return -EINVAL; diff --git a/target/linux/ipq806x/patches-4.9/0046-cpufreq-qcom-independent-core-clocks.patch b/target/linux/ipq806x/patches-4.9/0046-cpufreq-qcom-independent-core-clocks.patch index 8d2861ce9..d767dbf5f 100644 --- a/target/linux/ipq806x/patches-4.9/0046-cpufreq-qcom-independent-core-clocks.patch +++ b/target/linux/ipq806x/patches-4.9/0046-cpufreq-qcom-independent-core-clocks.patch @@ -1,25 +1,31 @@ -ipq806x: support independent core clocks with kernel 4.9+ +From patchwork Fri Dec 8 09:42:30 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,12/12] cpufreq: dt: Reintroduce independent_clocks platform data +From: Sricharan R +X-Patchwork-Id: 10102073 +Message-Id: <1512726150-7204-13-git-send-email-sricharan@codeaurora.org> +To: mturquette@baylibre.com, sboyd@codeaurora.org, + devicetree@vger.kernel.org, linux-pm@vger.kernel.org, + linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, + viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org +Cc: sricharan@codeaurora.org +Date: Fri, 8 Dec 2017 15:12:30 +0530 -Add back support for the independent_clocks definition that has been -removed between kernel 4.4 and 4.9 by upstream commits -eb96924acddc709db58221c210ca05cd9effb1df and -e86eee6bc2aaa6b3637f6497b26beee09a91bde9 +The Platform data was removed earlier by, +'commit eb96924acddc ("cpufreq: dt: Kill platform-data")' +since there were no users at that time. +Now this is required when the each of the cpu clocks +can be scaled independently, which is the case +for krait cores. So reintroduce it. -* extend the new cpufreq_dt_platform_data definition in cpufreq-dt.h -* use new cpufreq-dt.h in qcom-cpufreq.c +Signed-off-by: Sricharan R +--- + drivers/cpufreq/cpufreq-dt.c | 7 ++++++- + drivers/cpufreq/cpufreq-dt.h | 6 ++++++ + 2 files changed, 12 insertions(+), 1 deletion(-) -Signed-off-by: Hannu Nyman - ---- a/drivers/cpufreq/cpufreq-dt.h -+++ b/drivers/cpufreq/cpufreq-dt.h -@@ -14,6 +14,7 @@ - - struct cpufreq_dt_platform_data { - bool have_governor_per_policy; -+ bool independent_clocks; - }; - - #endif /* __CPUFREQ_DT_H__ */ --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -221,7 +221,10 @@ static int cpufreq_init(struct cpufreq_p @@ -38,19 +44,23 @@ Signed-off-by: Hannu Nyman if (data && data->have_governor_per_policy) dt_cpufreq_driver.flags |= CPUFREQ_HAVE_GOVERNOR_PER_POLICY; -+ dt_cpufreq_driver.driver_data = dev_get_platdata(&pdev->dev); ++ dt_cpufreq_driver.driver_data = data; + ret = cpufreq_register_driver(&dt_cpufreq_driver); if (ret) dev_err(&pdev->dev, "failed register driver: %d\n", ret); ---- a/drivers/cpufreq/qcom-cpufreq.c -+++ b/drivers/cpufreq/qcom-cpufreq.c -@@ -20,7 +20,7 @@ - #include - #include - #include --#include -+#include "cpufreq-dt.h" +--- a/drivers/cpufreq/cpufreq-dt.h ++++ b/drivers/cpufreq/cpufreq-dt.h +@@ -13,6 +13,12 @@ + #include + + struct cpufreq_dt_platform_data { ++ /* ++ * True when each CPU has its own clock to control its ++ * frequency, false when all CPUs are controlled by a single ++ * clock. ++ */ ++ bool independent_clocks; + bool have_governor_per_policy; + }; - static void __init get_krait_bin_format_a(int *speed, int *pvs, int *pvs_ver) - { diff --git a/target/linux/ipq806x/patches-4.9/0057-clk-qcom-Add-regmap-mux-div-clocks-support.patch b/target/linux/ipq806x/patches-4.9/0057-clk-qcom-Add-regmap-mux-div-clocks-support.patch deleted file mode 100644 index c5cdc7930..000000000 --- a/target/linux/ipq806x/patches-4.9/0057-clk-qcom-Add-regmap-mux-div-clocks-support.patch +++ /dev/null @@ -1,372 +0,0 @@ -From f72c5aa18281c44945fea6181d0d816a7605505c Mon Sep 17 00:00:00 2001 -From: Georgi Djakov -Date: Wed, 18 Mar 2015 17:23:29 +0200 -Subject: [PATCH 57/69] clk: qcom: Add regmap mux-div clocks support - -Add support for hardware that can switch both parent clocks and divider -at the same time. This avoids generating intermediate frequencies from -either the old parent clock and new divider or new parent clock and -old divider combinations. - -Signed-off-by: Georgi Djakov ---- - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/clk-regmap-mux-div.c | 272 ++++++++++++++++++++++++++++++++++ - drivers/clk/qcom/clk-regmap-mux-div.h | 65 ++++++++ - 3 files changed, 338 insertions(+) - create mode 100644 drivers/clk/qcom/clk-regmap-mux-div.c - create mode 100644 drivers/clk/qcom/clk-regmap-mux-div.h - ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -9,6 +9,7 @@ clk-qcom-y += clk-rcg2.o - clk-qcom-y += clk-branch.o - clk-qcom-y += clk-regmap-divider.o - clk-qcom-y += clk-regmap-mux.o -+clk-qcom-y += clk-regmap-mux-div.o - clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-krait.o - clk-qcom-y += clk-hfpll.o - clk-qcom-y += reset.o ---- /dev/null -+++ b/drivers/clk/qcom/clk-regmap-mux-div.c -@@ -0,0 +1,272 @@ -+/* -+ * Copyright (c) 2015, Linaro Limited -+ * Copyright (c) 2014, The Linux Foundation. All rights reserved. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "clk-regmap-mux-div.h" -+ -+#define CMD_RCGR 0x0 -+#define CMD_RCGR_UPDATE BIT(0) -+#define CMD_RCGR_DIRTY_CFG BIT(4) -+#define CMD_RCGR_ROOT_OFF BIT(31) -+#define CFG_RCGR 0x4 -+ -+#define to_clk_regmap_mux_div(_hw) \ -+ container_of(to_clk_regmap(_hw), struct clk_regmap_mux_div, clkr) -+ -+int __mux_div_set_src_div(struct clk_regmap_mux_div *md, u32 src, u32 div) -+{ -+ int ret, count; -+ u32 val, mask; -+ const char *name = clk_hw_get_name(&md->clkr.hw); -+ -+ val = (div << md->hid_shift) | (src << md->src_shift); -+ mask = ((BIT(md->hid_width) - 1) << md->hid_shift) | -+ ((BIT(md->src_width) - 1) << md->src_shift); -+ -+ ret = regmap_update_bits(md->clkr.regmap, CFG_RCGR + md->reg_offset, -+ mask, val); -+ if (ret) -+ return ret; -+ -+ ret = regmap_update_bits(md->clkr.regmap, CMD_RCGR + md->reg_offset, -+ CMD_RCGR_UPDATE, CMD_RCGR_UPDATE); -+ if (ret) -+ return ret; -+ -+ /* Wait for update to take effect */ -+ for (count = 500; count > 0; count--) { -+ ret = regmap_read(md->clkr.regmap, CMD_RCGR + md->reg_offset, -+ &val); -+ if (ret) -+ return ret; -+ if (!(val & CMD_RCGR_UPDATE)) -+ return 0; -+ udelay(1); -+ } -+ -+ pr_err("%s: RCG did not update its configuration", name); -+ return -EBUSY; -+} -+ -+static void __mux_div_get_src_div(struct clk_regmap_mux_div *md, u32 *src, -+ u32 *div) -+{ -+ u32 val, __div, __src; -+ const char *name = clk_hw_get_name(&md->clkr.hw); -+ -+ regmap_read(md->clkr.regmap, CMD_RCGR + md->reg_offset, &val); -+ -+ if (val & CMD_RCGR_DIRTY_CFG) { -+ pr_err("%s: RCG configuration is pending\n", name); -+ return; -+ } -+ -+ regmap_read(md->clkr.regmap, CFG_RCGR + md->reg_offset, &val); -+ __src = (val >> md->src_shift); -+ __src &= BIT(md->src_width) - 1; -+ *src = __src; -+ -+ __div = (val >> md->hid_shift); -+ __div &= BIT(md->hid_width) - 1; -+ *div = __div; -+} -+ -+static int mux_div_enable(struct clk_hw *hw) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ -+ return __mux_div_set_src_div(md, md->src, md->div); -+} -+ -+static inline bool is_better_rate(unsigned long req, unsigned long best, -+ unsigned long new) -+{ -+ return (req <= new && new < best) || (best < req && best < new); -+} -+ -+static int mux_div_determine_rate(struct clk_hw *hw, -+ struct clk_rate_request *req) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ unsigned int i, div, max_div; -+ unsigned long actual_rate, best_rate = 0; -+ unsigned long req_rate = req->rate; -+ -+ for (i = 0; i < clk_hw_get_num_parents(hw); i++) { -+ struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i); -+ unsigned long parent_rate = clk_hw_get_rate(parent); -+ -+ max_div = BIT(md->hid_width) - 1; -+ for (div = 1; div < max_div; div++) { -+ parent_rate = mult_frac(req_rate, div, 2); -+ parent_rate = clk_hw_round_rate(parent, parent_rate); -+ actual_rate = mult_frac(parent_rate, 2, div); -+ -+ if (is_better_rate(req_rate, best_rate, actual_rate)) { -+ best_rate = actual_rate; -+ req->rate = best_rate; -+ req->best_parent_rate = parent_rate; -+ req->best_parent_hw = parent; -+ } -+ -+ if (actual_rate < req_rate || best_rate <= req_rate) -+ break; -+ } -+ } -+ -+ if (!best_rate) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static int __mux_div_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, -+ unsigned long prate, u32 src) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ int ret; -+ u32 div, max_div, best_src = 0, best_div = 0; -+ unsigned int i; -+ unsigned long actual_rate, best_rate = 0; -+ -+ for (i = 0; i < clk_hw_get_num_parents(hw); i++) { -+ struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i); -+ unsigned long parent_rate = clk_hw_get_rate(parent); -+ -+ max_div = BIT(md->hid_width) - 1; -+ for (div = 1; div < max_div; div++) { -+ parent_rate = mult_frac(rate, div, 2); -+ parent_rate = clk_hw_round_rate(parent, parent_rate); -+ actual_rate = mult_frac(parent_rate, 2, div); -+ -+ if (is_better_rate(rate, best_rate, actual_rate)) { -+ best_rate = actual_rate; -+ best_src = md->parent_map[i].cfg; -+ best_div = div - 1; -+ } -+ -+ if (actual_rate < rate || best_rate <= rate) -+ break; -+ } -+ } -+ -+ ret = __mux_div_set_src_div(md, best_src, best_div); -+ if (!ret) { -+ md->div = best_div; -+ md->src = best_src; -+ } -+ -+ return ret; -+} -+ -+static u8 mux_div_get_parent(struct clk_hw *hw) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ const char *name = clk_hw_get_name(hw); -+ u32 i, div, src = 0; -+ -+ __mux_div_get_src_div(md, &src, &div); -+ -+ for (i = 0; i < clk_hw_get_num_parents(hw); i++) -+ if (src == md->parent_map[i].cfg) -+ return i; -+ -+ pr_err("%s: Can't find parent with src %d\n", name, src); -+ return 0; -+} -+ -+static int mux_div_set_parent(struct clk_hw *hw, u8 index) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ -+ return __mux_div_set_src_div(md, md->parent_map[index].cfg, md->div); -+} -+ -+static int mux_div_set_rate(struct clk_hw *hw, -+ unsigned long rate, unsigned long prate) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ -+ return __mux_div_set_rate_and_parent(hw, rate, prate, md->src); -+} -+ -+static int mux_div_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, -+ unsigned long prate, u8 index) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ -+ return __mux_div_set_rate_and_parent(hw, rate, prate, -+ md->parent_map[index].cfg); -+} -+ -+static unsigned long mux_div_recalc_rate(struct clk_hw *hw, unsigned long prate) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ u32 div, src; -+ int i, num_parents = clk_hw_get_num_parents(hw); -+ const char *name = clk_hw_get_name(hw); -+ -+ __mux_div_get_src_div(md, &src, &div); -+ for (i = 0; i < num_parents; i++) -+ if (src == md->parent_map[i].cfg) { -+ struct clk_hw *p = clk_hw_get_parent_by_index(hw, i); -+ unsigned long parent_rate = clk_hw_get_rate(p); -+ -+ return mult_frac(parent_rate, 2, div + 1); -+ } -+ -+ pr_err("%s: Can't find parent %d\n", name, src); -+ return 0; -+} -+ -+static struct clk_hw *mux_div_get_safe_parent(struct clk_hw *hw, -+ unsigned long *safe_freq) -+{ -+ int i; -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ -+ if (md->safe_freq) -+ *safe_freq = md->safe_freq; -+ -+ for (i = 0; i < clk_hw_get_num_parents(hw); i++) -+ if (md->safe_src == md->parent_map[i].cfg) -+ break; -+ -+ return clk_hw_get_parent_by_index(hw, i); -+} -+ -+static void mux_div_disable(struct clk_hw *hw) -+{ -+ struct clk_regmap_mux_div *md = to_clk_regmap_mux_div(hw); -+ -+ __mux_div_set_src_div(md, md->safe_src, md->safe_div); -+} -+ -+const struct clk_ops clk_regmap_mux_div_ops = { -+ .enable = mux_div_enable, -+ .disable = mux_div_disable, -+ .get_parent = mux_div_get_parent, -+ .set_parent = mux_div_set_parent, -+ .set_rate = mux_div_set_rate, -+ .set_rate_and_parent = mux_div_set_rate_and_parent, -+ .determine_rate = mux_div_determine_rate, -+ .recalc_rate = mux_div_recalc_rate, -+ .get_safe_parent = mux_div_get_safe_parent, -+}; -+EXPORT_SYMBOL_GPL(clk_regmap_mux_div_ops); ---- /dev/null -+++ b/drivers/clk/qcom/clk-regmap-mux-div.h -@@ -0,0 +1,65 @@ -+/* -+ * Copyright (c) 2015, Linaro Limited -+ * Copyright (c) 2014, The Linux Foundation. All rights reserved. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#ifndef __QCOM_CLK_REGMAP_MUX_DIV_H__ -+#define __QCOM_CLK_REGMAP_MUX_DIV_H__ -+ -+#include -+#include "clk-rcg.h" -+#include "clk-regmap.h" -+ -+/** -+ * struct mux_div_clk - combined mux/divider clock -+ * @reg_offset: offset of the mux/divider register -+ * @hid_width: number of bits in half integer divider -+ * @hid_shift: lowest bit of hid value field -+ * @src_width: number of bits in source select -+ * @src_shift: lowest bit of source select field -+ * @div: the divider raw configuration value -+ * @src: the mux index which will be used if the clock is enabled -+ * @safe_src: the safe source mux value we switch to, while the main PLL is -+ * reconfigured -+ * @safe_div: the safe divider value that we set, while the main PLL is -+ * reconfigured -+ * @safe_freq: When switching rates from A to B, the mux div clock will -+ * instead switch from A -> safe_freq -> B. This allows the -+ * mux_div clock to change rates while enabled, even if this -+ * behavior is not supported by the parent clocks. -+ * If changing the rate of parent A also causes the rate of -+ * parent B to change, then safe_freq must be defined. -+ * safe_freq is expected to have a source clock which is always -+ * on and runs at only one rate. -+ * @parent_map: pointer to parent_map struct -+ * @clkr: handle between common and hardware-specific interfaces -+ */ -+ -+struct clk_regmap_mux_div { -+ u32 reg_offset; -+ u32 hid_width; -+ u32 hid_shift; -+ u32 src_width; -+ u32 src_shift; -+ u32 div; -+ u32 src; -+ u32 safe_src; -+ u32 safe_div; -+ unsigned long safe_freq; -+ const struct parent_map *parent_map; -+ struct clk_regmap clkr; -+}; -+ -+extern const struct clk_ops clk_regmap_mux_div_ops; -+int __mux_div_set_src_div(struct clk_regmap_mux_div *md, u32 src, u32 div); -+ -+#endif diff --git a/target/linux/ipq806x/patches-4.9/0062-ipq806x-gcc-Added-the-enable-regs-and-mask-for-PRNG.patch b/target/linux/ipq806x/patches-4.9/0062-ipq806x-gcc-Added-the-enable-regs-and-mask-for-PRNG.patch index a3e0a1dc5..717934315 100644 --- a/target/linux/ipq806x/patches-4.9/0062-ipq806x-gcc-Added-the-enable-regs-and-mask-for-PRNG.patch +++ b/target/linux/ipq806x/patches-4.9/0062-ipq806x-gcc-Added-the-enable-regs-and-mask-for-PRNG.patch @@ -14,7 +14,7 @@ Signed-off-by: Abhishek Sahu --- a/drivers/clk/qcom/gcc-ipq806x.c +++ b/drivers/clk/qcom/gcc-ipq806x.c -@@ -1234,6 +1234,8 @@ static struct clk_rcg prng_src = { +@@ -1233,6 +1233,8 @@ static struct clk_rcg prng_src = { .parent_map = gcc_pxo_pll8_map, }, .clkr = { diff --git a/target/linux/ipq806x/patches-4.9/0065-arm-override-compiler-flags.patch b/target/linux/ipq806x/patches-4.9/0065-arm-override-compiler-flags.patch index dd40f1371..e5af7ffa2 100644 --- a/target/linux/ipq806x/patches-4.9/0065-arm-override-compiler-flags.patch +++ b/target/linux/ipq806x/patches-4.9/0065-arm-override-compiler-flags.patch @@ -15,7 +15,7 @@ Signed-off-by: John Crispin # testing for a specific architecture or later rather impossible. arch-$(CONFIG_CPU_32v7M) =-D__LINUX_ARM_ARCH__=7 -march=armv7-m -Wa,-march=armv7-m -arch-$(CONFIG_CPU_32v7) =-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7-a,-march=armv5t -Wa$(comma)-march=armv7-a) -+arch-$(CONFIG_CPU_32v7) =-D__LINUX_ARM_ARCH__=7 -mcpu=cortex-a15 -mtune=cortex-a15 ++arch-$(CONFIG_CPU_32v7) =-D__LINUX_ARM_ARCH__=7 -mcpu=cortex-a15 arch-$(CONFIG_CPU_32v6) =-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) # Only override the compiler option if ARMv6. The ARMv6K extensions are # always available in ARMv7 diff --git a/target/linux/ipq806x/patches-4.9/0069-arm-boot-add-dts-files.patch b/target/linux/ipq806x/patches-4.9/0069-arm-boot-add-dts-files.patch index ea9e67278..3e7c91cf3 100644 --- a/target/linux/ipq806x/patches-4.9/0069-arm-boot-add-dts-files.patch +++ b/target/linux/ipq806x/patches-4.9/0069-arm-boot-add-dts-files.patch @@ -5,8 +5,8 @@ Subject: [PATCH 69/69] arm: boot: add dts files Signed-off-by: John Crispin --- - arch/arm/boot/dts/Makefile | 9 ++++++++ - 1 file changed, 9 insertions(+) + arch/arm/boot/dts/Makefile | 8 ++++++++ + 1 file changed, 8 insertions(+) --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -15,7 +15,7 @@ Signed-off-by: John Crispin qcom-ipq4019-ap.dk01.1-c1.dtb \ qcom-ipq4019-ap.dk04.1-c1.dtb \ + qcom-ipq4019-fritz4040.dtb \ -+ qcom-ipq4019-nbg6617.dtb \ ++ qcom-ipq4019-a42.dtb \ + qcom-ipq4019-rt-ac58u.dtb \ + qcom-ipq4019-rt-acrh17.dtb \ qcom-ipq8064-ap148.dtb \ diff --git a/target/linux/ipq806x/patches-4.9/0071-1-PCI-qcom-Fixed-IPQ806x-specific-clocks.patch b/target/linux/ipq806x/patches-4.9/0071-1-PCI-qcom-Fixed-IPQ806x-specific-clocks.patch new file mode 100644 index 000000000..7a315627f --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/0071-1-PCI-qcom-Fixed-IPQ806x-specific-clocks.patch @@ -0,0 +1,95 @@ +From 86655aa14304ca88a8ce8847276147dbc1a83238 Mon Sep 17 00:00:00 2001 +From: Sham Muthayyan +Date: Tue, 19 Jul 2016 18:44:49 +0530 +Subject: PCI: qcom: Fixed IPQ806x specific clocks + +Change-Id: I488e1bc707d6a22b37a338f41935e3922009ba5e +Signed-off-by: Sham Muthayyan +--- + drivers/pci/host/pcie-qcom.c | 38 +++++++++++++++++++++++++++++++++----- + 1 file changed, 33 insertions(+), 5 deletions(-) + +--- a/drivers/pci/host/pcie-qcom.c ++++ b/drivers/pci/host/pcie-qcom.c +@@ -53,6 +53,8 @@ struct qcom_pcie_resources_v0 { + struct clk *iface_clk; + struct clk *core_clk; + struct clk *phy_clk; ++ struct clk *aux_clk; ++ struct clk *ref_clk; + struct reset_control *pci_reset; + struct reset_control *axi_reset; + struct reset_control *ahb_reset; +@@ -160,6 +162,14 @@ static int qcom_pcie_get_resources_v0(st + if (IS_ERR(res->phy_clk)) + return PTR_ERR(res->phy_clk); + ++ res->aux_clk = devm_clk_get(dev, "aux"); ++ if (IS_ERR(res->aux_clk)) ++ return PTR_ERR(res->aux_clk); ++ ++ res->ref_clk = devm_clk_get(dev, "ref"); ++ if (IS_ERR(res->ref_clk)) ++ return PTR_ERR(res->ref_clk); ++ + res->pci_reset = devm_reset_control_get(dev, "pci"); + if (IS_ERR(res->pci_reset)) + return PTR_ERR(res->pci_reset); +@@ -227,6 +237,8 @@ static void qcom_pcie_deinit_v0(struct q + clk_disable_unprepare(res->iface_clk); + clk_disable_unprepare(res->core_clk); + clk_disable_unprepare(res->phy_clk); ++ clk_disable_unprepare(res->aux_clk); ++ clk_disable_unprepare(res->ref_clk); + regulator_disable(res->vdda); + regulator_disable(res->vdda_phy); + regulator_disable(res->vdda_refclk); +@@ -269,16 +281,28 @@ static int qcom_pcie_init_v0(struct qcom + goto err_assert_ahb; + } + ++ ret = clk_prepare_enable(res->core_clk); ++ if (ret) { ++ dev_err(dev, "cannot prepare/enable core clock\n"); ++ goto err_clk_core; ++ } ++ + ret = clk_prepare_enable(res->phy_clk); + if (ret) { + dev_err(dev, "cannot prepare/enable phy clock\n"); + goto err_clk_phy; + } + +- ret = clk_prepare_enable(res->core_clk); ++ ret = clk_prepare_enable(res->aux_clk); + if (ret) { +- dev_err(dev, "cannot prepare/enable core clock\n"); +- goto err_clk_core; ++ dev_err(dev, "cannot prepare/enable aux clock\n"); ++ goto err_clk_aux; ++ } ++ ++ ret = clk_prepare_enable(res->ref_clk); ++ if (ret) { ++ dev_err(dev, "cannot prepare/enable ref clock\n"); ++ goto err_clk_ref; + } + + ret = reset_control_deassert(res->ahb_reset); +@@ -327,10 +351,14 @@ static int qcom_pcie_init_v0(struct qcom + return 0; + + err_deassert_ahb: +- clk_disable_unprepare(res->core_clk); +-err_clk_core: ++ clk_disable_unprepare(res->ref_clk); ++err_clk_ref: ++ clk_disable_unprepare(res->aux_clk); ++err_clk_aux: + clk_disable_unprepare(res->phy_clk); + err_clk_phy: ++ clk_disable_unprepare(res->core_clk); ++err_clk_core: + clk_disable_unprepare(res->iface_clk); + err_assert_ahb: + regulator_disable(res->vdda_phy); diff --git a/target/linux/ipq806x/patches-4.9/0071-2-PCI-qcom-Fixed-IPQ806x-PCIE-reset-changes.patch b/target/linux/ipq806x/patches-4.9/0071-2-PCI-qcom-Fixed-IPQ806x-PCIE-reset-changes.patch new file mode 100644 index 000000000..aab4f364e --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/0071-2-PCI-qcom-Fixed-IPQ806x-PCIE-reset-changes.patch @@ -0,0 +1,85 @@ +From 490d103232287eb51c92c49a4ef8865fd0a9d59e Mon Sep 17 00:00:00 2001 +From: Sham Muthayyan +Date: Tue, 19 Jul 2016 18:58:18 +0530 +Subject: PCI: qcom: Fixed IPQ806x PCIE reset changes + +Change-Id: Ia6590e960b9754b1e8b7a51f318788cd63e9e321 +Signed-off-by: Sham Muthayyan +--- + drivers/pci/host/pcie-qcom.c | 24 +++++++++++++++++++----- + 1 file changed, 19 insertions(+), 5 deletions(-) + +--- a/drivers/pci/host/pcie-qcom.c ++++ b/drivers/pci/host/pcie-qcom.c +@@ -60,6 +60,7 @@ struct qcom_pcie_resources_v0 { + struct reset_control *ahb_reset; + struct reset_control *por_reset; + struct reset_control *phy_reset; ++ struct reset_control *ext_reset; + struct regulator *vdda; + struct regulator *vdda_phy; + struct regulator *vdda_refclk; +@@ -190,6 +191,10 @@ static int qcom_pcie_get_resources_v0(st + if (IS_ERR(res->phy_reset)) + return PTR_ERR(res->phy_reset); + ++ res->ext_reset = devm_reset_control_get(dev, "ext"); ++ if (IS_ERR(res->ext_reset)) ++ return PTR_ERR(res->ext_reset); ++ + return 0; + } + +@@ -234,6 +239,7 @@ static void qcom_pcie_deinit_v0(struct q + reset_control_assert(res->ahb_reset); + reset_control_assert(res->por_reset); + reset_control_assert(res->pci_reset); ++ reset_control_assert(res->ext_reset); + clk_disable_unprepare(res->iface_clk); + clk_disable_unprepare(res->core_clk); + clk_disable_unprepare(res->phy_clk); +@@ -251,6 +257,12 @@ static int qcom_pcie_init_v0(struct qcom + u32 val; + int ret; + ++ ret = reset_control_assert(res->ahb_reset); ++ if (ret) { ++ dev_err(dev, "cannot assert ahb reset\n"); ++ return ret; ++ } ++ + ret = regulator_enable(res->vdda); + if (ret) { + dev_err(dev, "cannot enable vdda regulator\n"); +@@ -269,16 +281,16 @@ static int qcom_pcie_init_v0(struct qcom + goto err_vdda_phy; + } + +- ret = reset_control_assert(res->ahb_reset); ++ ret = reset_control_deassert(res->ext_reset); + if (ret) { +- dev_err(dev, "cannot assert ahb reset\n"); +- goto err_assert_ahb; ++ dev_err(dev, "cannot assert ext reset\n"); ++ goto err_reset_ext; + } + + ret = clk_prepare_enable(res->iface_clk); + if (ret) { + dev_err(dev, "cannot prepare/enable iface clock\n"); +- goto err_assert_ahb; ++ goto err_iface; + } + + ret = clk_prepare_enable(res->core_clk); +@@ -360,7 +372,9 @@ err_clk_phy: + clk_disable_unprepare(res->core_clk); + err_clk_core: + clk_disable_unprepare(res->iface_clk); +-err_assert_ahb: ++err_iface: ++ reset_control_assert(res->ext_reset); ++err_reset_ext: + regulator_disable(res->vdda_phy); + err_vdda_phy: + regulator_disable(res->vdda_refclk); diff --git a/target/linux/ipq806x/patches-4.9/0071-3-PCI-qcom-Fixed-IPQ806x-PCIE-init-changes.patch b/target/linux/ipq806x/patches-4.9/0071-3-PCI-qcom-Fixed-IPQ806x-PCIE-init-changes.patch new file mode 100644 index 000000000..6c68edfe9 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/0071-3-PCI-qcom-Fixed-IPQ806x-PCIE-init-changes.patch @@ -0,0 +1,127 @@ +From eddd13215d0f2b549ebc5f0e8796d5b1231f90a0 Mon Sep 17 00:00:00 2001 +From: Sham Muthayyan +Date: Tue, 19 Jul 2016 19:58:22 +0530 +Subject: PCI: qcom: Fixed IPQ806x PCIE init changes + +Change-Id: Ic319b1aec27a47809284759f8fcb6a8815b7cf7e +Signed-off-by: Sham Muthayyan +--- + drivers/pci/host/pcie-qcom.c | 62 +++++++++++++++++++++++++++++++++++++------- + 1 file changed, 53 insertions(+), 9 deletions(-) + +--- a/drivers/pci/host/pcie-qcom.c ++++ b/drivers/pci/host/pcie-qcom.c +@@ -37,7 +37,13 @@ + #include "pcie-designware.h" + + #define PCIE20_PARF_PHY_CTRL 0x40 ++#define PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK (0x1f << 16) ++#define PHY_CTRL_PHY_TX0_TERM_OFFSET(x) (x << 16) ++ + #define PCIE20_PARF_PHY_REFCLK 0x4C ++#define REF_SSP_EN BIT(16) ++#define REF_USE_PAD BIT(12) ++ + #define PCIE20_PARF_DBI_BASE_ADDR 0x168 + #define PCIE20_PARF_SLV_ADDR_SPACE_SIZE 0x16c + #define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT 0x178 +@@ -48,6 +54,18 @@ + #define PCIE20_CAP 0x70 + + #define PERST_DELAY_US 1000 ++/* PARF registers */ ++#define PCIE20_PARF_PCS_DEEMPH 0x34 ++#define PCS_DEEMPH_TX_DEEMPH_GEN1(x) (x << 16) ++#define PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(x) (x << 8) ++#define PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(x) (x << 0) ++ ++#define PCIE20_PARF_PCS_SWING 0x38 ++#define PCS_SWING_TX_SWING_FULL(x) (x << 8) ++#define PCS_SWING_TX_SWING_LOW(x) (x << 0) ++ ++#define PCIE20_PARF_CONFIG_BITS 0x50 ++#define PHY_RX0_EQ(x) (x << 24) + + struct qcom_pcie_resources_v0 { + struct clk *iface_clk; +@@ -64,6 +82,7 @@ struct qcom_pcie_resources_v0 { + struct regulator *vdda; + struct regulator *vdda_phy; + struct regulator *vdda_refclk; ++ uint8_t phy_tx0_term_offset; + }; + + struct qcom_pcie_resources_v1 { +@@ -100,6 +119,16 @@ struct qcom_pcie { + + #define to_qcom_pcie(x) container_of(x, struct qcom_pcie, pp) + ++static inline void ++writel_masked(void __iomem *addr, u32 clear_mask, u32 set_mask) ++{ ++ u32 val = readl(addr); ++ ++ val &= ~clear_mask; ++ val |= set_mask; ++ writel(val, addr); ++} ++ + static void qcom_ep_reset_assert(struct qcom_pcie *pcie) + { + gpiod_set_value(pcie->reset, 1); +@@ -195,6 +224,10 @@ static int qcom_pcie_get_resources_v0(st + if (IS_ERR(res->ext_reset)) + return PTR_ERR(res->ext_reset); + ++ if (of_property_read_u8(dev->of_node, "phy-tx0-term-offset", ++ &res->phy_tx0_term_offset)) ++ res->phy_tx0_term_offset = 0; ++ + return 0; + } + +@@ -254,7 +287,6 @@ static int qcom_pcie_init_v0(struct qcom + { + struct qcom_pcie_resources_v0 *res = &pcie->res.v0; + struct device *dev = pcie->pp.dev; +- u32 val; + int ret; + + ret = reset_control_assert(res->ahb_reset); +@@ -323,15 +355,27 @@ static int qcom_pcie_init_v0(struct qcom + goto err_deassert_ahb; + } + +- /* enable PCIe clocks and resets */ +- val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); +- val &= ~BIT(0); +- writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); +- +- /* enable external reference clock */ +- val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK); +- val |= BIT(16); +- writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK); ++ writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0); ++ ++ /* Set Tx termination offset */ ++ writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL, ++ PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK, ++ PHY_CTRL_PHY_TX0_TERM_OFFSET(res->phy_tx0_term_offset)); ++ ++ /* PARF programming */ ++ writel(PCS_DEEMPH_TX_DEEMPH_GEN1(0x18) | ++ PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(0x18) | ++ PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(0x22), ++ pcie->parf + PCIE20_PARF_PCS_DEEMPH); ++ writel(PCS_SWING_TX_SWING_FULL(0x78) | ++ PCS_SWING_TX_SWING_LOW(0x78), ++ pcie->parf + PCIE20_PARF_PCS_SWING); ++ writel(PHY_RX0_EQ(0x4), pcie->parf + PCIE20_PARF_CONFIG_BITS); ++ ++ /* Enable reference clock */ ++ writel_masked(pcie->parf + PCIE20_PARF_PHY_REFCLK, ++ REF_USE_PAD, REF_SSP_EN); ++ + + ret = reset_control_deassert(res->phy_reset); + if (ret) { diff --git a/target/linux/ipq806x/patches-4.9/0071-4-PCIE-designware-Fixed-PCI-host-init.patch b/target/linux/ipq806x/patches-4.9/0071-4-PCIE-designware-Fixed-PCI-host-init.patch new file mode 100644 index 000000000..af9e121f8 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/0071-4-PCIE-designware-Fixed-PCI-host-init.patch @@ -0,0 +1,68 @@ +From e833cdb5c792912d459773cc23153e5d78875d34 Mon Sep 17 00:00:00 2001 +From: Sham Muthayyan +Date: Tue, 19 Jul 2016 20:05:25 +0530 +Subject: PCIE: designware: Fixed PCI host init + +Change-Id: I949b302d77199fc09342acf26b7bb45a7ec467ee +Signed-off-by: Sham Muthayyan +--- + drivers/pci/host/pcie-designware.c | 9 +++++++-- + drivers/pci/host/pcie-designware.h | 2 +- + drivers/pci/host/pcie-qcom.c | 5 +++-- + 3 files changed, 11 insertions(+), 5 deletions(-) + +--- a/drivers/pci/host/pcie-designware.c ++++ b/drivers/pci/host/pcie-designware.c +@@ -637,8 +637,13 @@ int dw_pcie_host_init(struct pcie_port * + } + } + +- if (pp->ops->host_init) +- pp->ops->host_init(pp); ++ if (pp->ops->host_init) { ++ ret = pp->ops->host_init(pp); ++ if (ret) { ++ dev_err(pp->dev, "hostinit failed\n"); ++ return 0; ++ } ++ } + + pp->root_bus_nr = pp->busn->start; + if (IS_ENABLED(CONFIG_PCI_MSI)) { +--- a/drivers/pci/host/pcie-designware.h ++++ b/drivers/pci/host/pcie-designware.h +@@ -63,7 +63,7 @@ struct pcie_host_ops { + int (*wr_other_conf)(struct pcie_port *pp, struct pci_bus *bus, + unsigned int devfn, int where, int size, u32 val); + int (*link_up)(struct pcie_port *pp); +- void (*host_init)(struct pcie_port *pp); ++ int (*host_init)(struct pcie_port *pp); + void (*msi_set_irq)(struct pcie_port *pp, int irq); + void (*msi_clear_irq)(struct pcie_port *pp, int irq); + phys_addr_t (*get_msi_addr)(struct pcie_port *pp); +--- a/drivers/pci/host/pcie-qcom.c ++++ b/drivers/pci/host/pcie-qcom.c +@@ -515,7 +515,7 @@ static int qcom_pcie_link_up(struct pcie + return !!(val & PCI_EXP_LNKSTA_DLLLA); + } + +-static void qcom_pcie_host_init(struct pcie_port *pp) ++static int qcom_pcie_host_init(struct pcie_port *pp) + { + struct qcom_pcie *pcie = to_qcom_pcie(pp); + int ret; +@@ -541,12 +541,13 @@ static void qcom_pcie_host_init(struct p + if (ret) + goto err; + +- return; ++ return 0; + err: + qcom_ep_reset_assert(pcie); + phy_power_off(pcie->phy); + err_deinit: + pcie->ops->deinit(pcie); ++ return ret; + } + + static int qcom_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, diff --git a/target/linux/ipq806x/patches-4.9/0071-5-PCI-qcom-Programming-the-PCIE-iATU-for-IPQ806x.patch b/target/linux/ipq806x/patches-4.9/0071-5-PCI-qcom-Programming-the-PCIE-iATU-for-IPQ806x.patch new file mode 100644 index 000000000..98e2b54e3 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/0071-5-PCI-qcom-Programming-the-PCIE-iATU-for-IPQ806x.patch @@ -0,0 +1,113 @@ +From d27c303e828d7e42f339a459d2abfe30c51698e9 Mon Sep 17 00:00:00 2001 +From: Sham Muthayyan +Date: Tue, 26 Jul 2016 12:28:31 +0530 +Subject: PCI: qcom: Programming the PCIE iATU for IPQ806x + +Resolved PCIE EP detection errors caused due to missing iATU programming. + +Change-Id: Ie95c0f8cb940abc0192a8a3c4e825ddba54b72fe +Signed-off-by: Sham Muthayyan +--- + drivers/pci/host/pcie-qcom.c | 77 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 77 insertions(+) + +--- a/drivers/pci/host/pcie-qcom.c ++++ b/drivers/pci/host/pcie-qcom.c +@@ -52,6 +52,29 @@ + #define PCIE20_ELBI_SYS_CTRL_LT_ENABLE BIT(0) + + #define PCIE20_CAP 0x70 ++#define PCIE20_CAP_LINKCTRLSTATUS (PCIE20_CAP + 0x10) ++ ++#define PCIE20_AXI_MSTR_RESP_COMP_CTRL0 0x818 ++#define PCIE20_AXI_MSTR_RESP_COMP_CTRL1 0x81c ++ ++#define PCIE20_PLR_IATU_VIEWPORT 0x900 ++#define PCIE20_PLR_IATU_REGION_OUTBOUND (0x0 << 31) ++#define PCIE20_PLR_IATU_REGION_INDEX(x) (x << 0) ++ ++#define PCIE20_PLR_IATU_CTRL1 0x904 ++#define PCIE20_PLR_IATU_TYPE_CFG0 (0x4 << 0) ++#define PCIE20_PLR_IATU_TYPE_MEM (0x0 << 0) ++ ++#define PCIE20_PLR_IATU_CTRL2 0x908 ++#define PCIE20_PLR_IATU_ENABLE BIT(31) ++ ++#define PCIE20_PLR_IATU_LBAR 0x90C ++#define PCIE20_PLR_IATU_UBAR 0x910 ++#define PCIE20_PLR_IATU_LAR 0x914 ++#define PCIE20_PLR_IATU_LTAR 0x918 ++#define PCIE20_PLR_IATU_UTAR 0x91c ++ ++#define MSM_PCIE_DEV_CFG_ADDR 0x01000000 + + #define PERST_DELAY_US 1000 + /* PARF registers */ +@@ -163,6 +186,57 @@ static int qcom_pcie_establish_link(stru + return dw_pcie_wait_for_link(&pcie->pp); + } + ++static void qcom_pcie_prog_viewport_cfg0(struct qcom_pcie *pcie, u32 busdev) ++{ ++ struct pcie_port *pp = &pcie->pp; ++ ++ /* ++ * program and enable address translation region 0 (device config ++ * address space); region type config; ++ * axi config address range to device config address range ++ */ ++ writel(PCIE20_PLR_IATU_REGION_OUTBOUND | ++ PCIE20_PLR_IATU_REGION_INDEX(0), ++ pcie->pp.dbi_base + PCIE20_PLR_IATU_VIEWPORT); ++ ++ writel(PCIE20_PLR_IATU_TYPE_CFG0, pcie->pp.dbi_base + PCIE20_PLR_IATU_CTRL1); ++ writel(PCIE20_PLR_IATU_ENABLE, pcie->pp.dbi_base + PCIE20_PLR_IATU_CTRL2); ++ writel(pp->cfg0_base, pcie->pp.dbi_base + PCIE20_PLR_IATU_LBAR); ++ writel((pp->cfg0_base >> 32), pcie->pp.dbi_base + PCIE20_PLR_IATU_UBAR); ++ writel((pp->cfg0_base + pp->cfg0_size - 1), ++ pcie->pp.dbi_base + PCIE20_PLR_IATU_LAR); ++ writel(busdev, pcie->pp.dbi_base + PCIE20_PLR_IATU_LTAR); ++ writel(0, pcie->pp.dbi_base + PCIE20_PLR_IATU_UTAR); ++} ++ ++static void qcom_pcie_prog_viewport_mem2_outbound(struct qcom_pcie *pcie) ++{ ++ struct pcie_port *pp = &pcie->pp; ++ ++ /* ++ * program and enable address translation region 2 (device resource ++ * address space); region type memory; ++ * axi device bar address range to device bar address range ++ */ ++ writel(PCIE20_PLR_IATU_REGION_OUTBOUND | ++ PCIE20_PLR_IATU_REGION_INDEX(2), ++ pcie->pp.dbi_base + PCIE20_PLR_IATU_VIEWPORT); ++ ++ writel(PCIE20_PLR_IATU_TYPE_MEM, pcie->pp.dbi_base + PCIE20_PLR_IATU_CTRL1); ++ writel(PCIE20_PLR_IATU_ENABLE, pcie->pp.dbi_base + PCIE20_PLR_IATU_CTRL2); ++ writel(pp->mem_base, pcie->pp.dbi_base + PCIE20_PLR_IATU_LBAR); ++ writel((pp->mem_base >> 32), pcie->pp.dbi_base + PCIE20_PLR_IATU_UBAR); ++ writel(pp->mem_base + pp->mem_size - 1, ++ pcie->pp.dbi_base + PCIE20_PLR_IATU_LAR); ++ writel(pp->mem_bus_addr, pcie->pp.dbi_base + PCIE20_PLR_IATU_LTAR); ++ writel(upper_32_bits(pp->mem_bus_addr), ++ pcie->pp.dbi_base + PCIE20_PLR_IATU_UTAR); ++ ++ /* 256B PCIE buffer setting */ ++ writel(0x1, pcie->pp.dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL0); ++ writel(0x1, pcie->pp.dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL1); ++} ++ + static int qcom_pcie_get_resources_v0(struct qcom_pcie *pcie) + { + struct qcom_pcie_resources_v0 *res = &pcie->res.v0; +@@ -404,6 +478,9 @@ static int qcom_pcie_init_v0(struct qcom + /* wait for clock acquisition */ + usleep_range(1000, 1500); + ++ qcom_pcie_prog_viewport_cfg0(pcie, MSM_PCIE_DEV_CFG_ADDR); ++ qcom_pcie_prog_viewport_mem2_outbound(pcie); ++ + return 0; + + err_deassert_ahb: diff --git a/target/linux/ipq806x/patches-4.9/0071-6-PCI-qcom-Force-GEN1-support.patch b/target/linux/ipq806x/patches-4.9/0071-6-PCI-qcom-Force-GEN1-support.patch new file mode 100644 index 000000000..91891a5b2 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/0071-6-PCI-qcom-Force-GEN1-support.patch @@ -0,0 +1,61 @@ +From 4910cfd150342ec7b038892262923c725a9c4001 Mon Sep 17 00:00:00 2001 +From: Sham Muthayyan +Date: Wed, 7 Sep 2016 16:44:28 +0530 +Subject: PCI: qcom: Force GEN1 support + +Change-Id: Ica54ddb737d7b851469deab1745f54bf431bd3f0 +Signed-off-by: Sham Muthayyan +--- + drivers/pci/host/pcie-qcom.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/pci/host/pcie-qcom.c ++++ b/drivers/pci/host/pcie-qcom.c +@@ -90,6 +90,8 @@ + #define PCIE20_PARF_CONFIG_BITS 0x50 + #define PHY_RX0_EQ(x) (x << 24) + ++#define PCIE20_LNK_CONTROL2_LINK_STATUS2 0xA0 ++ + struct qcom_pcie_resources_v0 { + struct clk *iface_clk; + struct clk *core_clk; +@@ -138,6 +140,7 @@ struct qcom_pcie { + struct phy *phy; + struct gpio_desc *reset; + struct qcom_pcie_ops *ops; ++ uint32_t force_gen1; + }; + + #define to_qcom_pcie(x) container_of(x, struct qcom_pcie, pp) +@@ -477,6 +480,11 @@ static int qcom_pcie_init_v0(struct qcom + + /* wait for clock acquisition */ + usleep_range(1000, 1500); ++ if (pcie->force_gen1) { ++ writel_relaxed((readl_relaxed( ++ pcie->pp.dbi_base + PCIE20_LNK_CONTROL2_LINK_STATUS2) | 1), ++ pcie->pp.dbi_base + PCIE20_LNK_CONTROL2_LINK_STATUS2); ++ } + + qcom_pcie_prog_viewport_cfg0(pcie, MSM_PCIE_DEV_CFG_ADDR); + qcom_pcie_prog_viewport_mem2_outbound(pcie); +@@ -666,6 +674,8 @@ static int qcom_pcie_probe(struct platfo + struct qcom_pcie *pcie; + struct pcie_port *pp; + int ret; ++ uint32_t force_gen1 = 0; ++ struct device_node *np = pdev->dev.of_node; + + pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); + if (!pcie) +@@ -678,6 +688,9 @@ static int qcom_pcie_probe(struct platfo + if (IS_ERR(pcie->reset)) + return PTR_ERR(pcie->reset); + ++ of_property_read_u32(np, "force_gen1", &force_gen1); ++ pcie->force_gen1 = force_gen1; ++ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "parf"); + pcie->parf = devm_ioremap_resource(dev, res); + if (IS_ERR(pcie->parf)) diff --git a/target/linux/ipq806x/patches-4.9/0071-7-pcie-Set-PCIE-MRRS-and-MPS-to-256B.patch b/target/linux/ipq806x/patches-4.9/0071-7-pcie-Set-PCIE-MRRS-and-MPS-to-256B.patch new file mode 100644 index 000000000..157386458 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/0071-7-pcie-Set-PCIE-MRRS-and-MPS-to-256B.patch @@ -0,0 +1,69 @@ +From edff8f777c6321ca89bb950a382f409c4a126e28 Mon Sep 17 00:00:00 2001 +From: Gokul Sriram Palanisamy +Date: Thu, 15 Dec 2016 17:38:18 +0530 +Subject: pcie: Set PCIE MRRS and MPS to 256B + +Set Max Read Request Size and Max Payload Size to 256 bytes, +per chip team recommendation. + +Change-Id: I097004be2ced1b3096ffc10c318aae0b2bb155e8 +Signed-off-by: Gokul Sriram Palanisamy +--- + drivers/pci/host/pcie-qcom.c | 37 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 37 insertions(+) + +(limited to 'drivers/pci/host/pcie-qcom.c') + +--- a/drivers/pci/host/pcie-qcom.c ++++ b/drivers/pci/host/pcie-qcom.c +@@ -92,6 +92,14 @@ + + #define PCIE20_LNK_CONTROL2_LINK_STATUS2 0xA0 + ++#define __set(v, a, b) (((v) << (b)) & GENMASK(a, b)) ++#define __mask(a, b) (((1 << ((a) + 1)) - 1) & ~((1 << (b)) - 1)) ++#define PCIE20_DEV_CAS 0x78 ++#define PCIE20_MRRS_MASK __mask(14, 12) ++#define PCIE20_MRRS(x) __set(x, 14, 12) ++#define PCIE20_MPS_MASK __mask(7, 5) ++#define PCIE20_MPS(x) __set(x, 7, 5) ++ + struct qcom_pcie_resources_v0 { + struct clk *iface_clk; + struct clk *core_clk; +@@ -745,6 +753,35 @@ static int qcom_pcie_probe(struct platfo + return 0; + } + ++static void qcom_pcie_fixup_final(struct pci_dev *dev) ++{ ++ int cap, err; ++ u16 ctl, reg_val; ++ ++ cap = pci_pcie_cap(dev); ++ if (!cap) ++ return; ++ ++ err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); ++ ++ if (err) ++ return; ++ ++ reg_val = ctl; ++ ++ if (((reg_val & PCIE20_MRRS_MASK) >> 12) > 1) ++ reg_val = (reg_val & ~(PCIE20_MRRS_MASK)) | PCIE20_MRRS(0x1); ++ ++ if (((ctl & PCIE20_MPS_MASK) >> 5) > 1) ++ reg_val = (reg_val & ~(PCIE20_MPS_MASK)) | PCIE20_MPS(0x1); ++ ++ err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, reg_val); ++ ++ if (err) ++ pr_err("pcie config write failed %d\n", err); ++} ++DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, qcom_pcie_fixup_final); ++ + static const struct of_device_id qcom_pcie_match[] = { + { .compatible = "qcom,pcie-ipq8064", .data = &ops_v0 }, + { .compatible = "qcom,pcie-apq8064", .data = &ops_v0 }, diff --git a/target/linux/ipq806x/patches-4.9/0071-8-pcie-qcom-Fixed-pcie_phy_clk-branch-issue.patch b/target/linux/ipq806x/patches-4.9/0071-8-pcie-qcom-Fixed-pcie_phy_clk-branch-issue.patch new file mode 100644 index 000000000..0f5050826 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/0071-8-pcie-qcom-Fixed-pcie_phy_clk-branch-issue.patch @@ -0,0 +1,91 @@ +From b74bab6186131eea09459eedf5d737645a3559c9 Mon Sep 17 00:00:00 2001 +From: Abhishek Sahu +Date: Thu, 22 Dec 2016 11:18:45 +0530 +Subject: pcie: qcom: Fixed pcie_phy_clk branch issue + +Following backtraces are observed in PCIe deinit operation. + + Hardware name: Qualcomm (Flattened Device Tree) + (unwind_backtrace) from [] (show_stack+0x10/0x14) + (show_stack) from [] (dump_stack+0x84/0x98) + (dump_stack) from [] (warn_slowpath_common+0x9c/0xb8) + (warn_slowpath_common) from [] (warn_slowpath_fmt+0x30/0x40) + (warn_slowpath_fmt) from [] (clk_branch_wait+0x114/0x120) + (clk_branch_wait) from [] (clk_core_disable+0xd0/0x1f4) + (clk_core_disable) from [] (clk_disable+0x24/0x30) + (clk_disable) from [] (qcom_pcie_deinit_v0+0x6c/0xb8) + (qcom_pcie_deinit_v0) from [] (qcom_pcie_host_init+0xe0/0xe8) + (qcom_pcie_host_init) from [] (dw_pcie_host_init+0x3b0/0x538) + (dw_pcie_host_init) from [] (qcom_pcie_probe+0x20c/0x2e4) + +pcie_phy_clk is generated for PCIe controller itself and the +GCC controls its branch operation. This error is coming since +the assert operations turn off the parent clock before branch +clock. Now this patch moves clk_disable_unprepare before assert +operations. + +Similarly, during probe function, the clock branch operation +should be done after dessert operation. Currently, it does not +generate any error since bootloader enables the pcie_phy_clk +but the same error is coming during probe, if bootloader +disables pcie_phy_clk. + +Change-Id: Ib29c154d10eb64363d9cc982ce5fd8107af5627d +Signed-off-by: Abhishek Sahu +--- + drivers/pci/host/pcie-qcom.c | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +--- a/drivers/pci/host/pcie-qcom.c ++++ b/drivers/pci/host/pcie-qcom.c +@@ -352,6 +352,7 @@ static void qcom_pcie_deinit_v0(struct q + { + struct qcom_pcie_resources_v0 *res = &pcie->res.v0; + ++ clk_disable_unprepare(res->phy_clk); + reset_control_assert(res->pci_reset); + reset_control_assert(res->axi_reset); + reset_control_assert(res->ahb_reset); +@@ -360,7 +361,6 @@ static void qcom_pcie_deinit_v0(struct q + reset_control_assert(res->ext_reset); + clk_disable_unprepare(res->iface_clk); + clk_disable_unprepare(res->core_clk); +- clk_disable_unprepare(res->phy_clk); + clk_disable_unprepare(res->aux_clk); + clk_disable_unprepare(res->ref_clk); + regulator_disable(res->vdda); +@@ -416,12 +416,6 @@ static int qcom_pcie_init_v0(struct qcom + goto err_clk_core; + } + +- ret = clk_prepare_enable(res->phy_clk); +- if (ret) { +- dev_err(dev, "cannot prepare/enable phy clock\n"); +- goto err_clk_phy; +- } +- + ret = clk_prepare_enable(res->aux_clk); + if (ret) { + dev_err(dev, "cannot prepare/enable aux clock\n"); +@@ -486,6 +480,12 @@ static int qcom_pcie_init_v0(struct qcom + return ret; + } + ++ ret = clk_prepare_enable(res->phy_clk); ++ if (ret) { ++ dev_err(dev, "cannot prepare/enable phy clock\n"); ++ goto err_deassert_ahb; ++ } ++ + /* wait for clock acquisition */ + usleep_range(1000, 1500); + if (pcie->force_gen1) { +@@ -504,8 +504,6 @@ err_deassert_ahb: + err_clk_ref: + clk_disable_unprepare(res->aux_clk); + err_clk_aux: +- clk_disable_unprepare(res->phy_clk); +-err_clk_phy: + clk_disable_unprepare(res->core_clk); + err_clk_core: + clk_disable_unprepare(res->iface_clk); diff --git a/target/linux/ipq806x/patches-4.9/0071-9-pcie-qcom-change-duplicate-pci-reset-to-phy-reset.patch b/target/linux/ipq806x/patches-4.9/0071-9-pcie-qcom-change-duplicate-pci-reset-to-phy-reset.patch new file mode 100644 index 000000000..a60add93c --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/0071-9-pcie-qcom-change-duplicate-pci-reset-to-phy-reset.patch @@ -0,0 +1,25 @@ +From 1a9c48123bd09f75562b6a2ee0f0a7b2d533cd45 Mon Sep 17 00:00:00 2001 +From: Abhishek Sahu +Date: Thu, 22 Dec 2016 11:50:49 +0530 +Subject: pcie: qcom: change duplicate pci reset to phy reset + +The deinit issues reset_control_assert for pci twice and +does not contain phy reset. + +Change-Id: Iba849963c7e5f9a2a1063f0e2e89635df70b8a99 +Signed-off-by: Abhishek Sahu +--- + drivers/pci/host/pcie-qcom.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/pci/host/pcie-qcom.c ++++ b/drivers/pci/host/pcie-qcom.c +@@ -353,7 +353,7 @@ static void qcom_pcie_deinit_v0(struct q + struct qcom_pcie_resources_v0 *res = &pcie->res.v0; + + clk_disable_unprepare(res->phy_clk); +- reset_control_assert(res->pci_reset); ++ reset_control_assert(res->phy_reset); + reset_control_assert(res->axi_reset); + reset_control_assert(res->ahb_reset); + reset_control_assert(res->por_reset); diff --git a/target/linux/ipq806x/patches-4.9/0071-pcie-qcom-fixes.patch b/target/linux/ipq806x/patches-4.9/0071-pcie-qcom-fixes.patch deleted file mode 100644 index dd403e295..000000000 --- a/target/linux/ipq806x/patches-4.9/0071-pcie-qcom-fixes.patch +++ /dev/null @@ -1,308 +0,0 @@ ---- a/drivers/pci/host/pcie-qcom.c -+++ b/drivers/pci/host/pcie-qcom.c -@@ -36,8 +36,50 @@ - - #include "pcie-designware.h" - -+/* DBI registers */ -+#define PCIE20_AXI_MSTR_RESP_COMP_CTRL0 0x818 -+#define PCIE20_AXI_MSTR_RESP_COMP_CTRL1 0x81c -+ -+#define PCIE20_PLR_IATU_VIEWPORT 0x900 -+#define PCIE20_PLR_IATU_REGION_OUTBOUND (0x0 << 31) -+#define PCIE20_PLR_IATU_REGION_INDEX(x) (x << 0) -+ -+#define PCIE20_PLR_IATU_CTRL1 0x904 -+#define PCIE20_PLR_IATU_TYPE_CFG0 (0x4 << 0) -+#define PCIE20_PLR_IATU_TYPE_MEM (0x0 << 0) -+ -+#define PCIE20_PLR_IATU_CTRL2 0x908 -+#define PCIE20_PLR_IATU_ENABLE BIT(31) -+ -+#define PCIE20_PLR_IATU_LBAR 0x90C -+#define PCIE20_PLR_IATU_UBAR 0x910 -+#define PCIE20_PLR_IATU_LAR 0x914 -+#define PCIE20_PLR_IATU_LTAR 0x918 -+#define PCIE20_PLR_IATU_UTAR 0x91c -+ -+#define MSM_PCIE_DEV_CFG_ADDR 0x01000000 -+ -+/* PARF registers */ -+#define PCIE20_PARF_PCS_DEEMPH 0x34 -+#define PCS_DEEMPH_TX_DEEMPH_GEN1(x) (x << 16) -+#define PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(x) (x << 8) -+#define PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(x) (x << 0) -+ -+#define PCIE20_PARF_PCS_SWING 0x38 -+#define PCS_SWING_TX_SWING_FULL(x) (x << 8) -+#define PCS_SWING_TX_SWING_LOW(x) (x << 0) -+ - #define PCIE20_PARF_PHY_CTRL 0x40 -+#define PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK (0x1f << 16) -+#define PHY_CTRL_PHY_TX0_TERM_OFFSET(x) (x << 16) -+ - #define PCIE20_PARF_PHY_REFCLK 0x4C -+#define REF_SSP_EN BIT(16) -+#define REF_USE_PAD BIT(12) -+ -+#define PCIE20_PARF_CONFIG_BITS 0x50 -+#define PHY_RX0_EQ(x) (x << 24) -+ - #define PCIE20_PARF_DBI_BASE_ADDR 0x168 - #define PCIE20_PARF_SLV_ADDR_SPACE_SIZE 0x16c - #define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT 0x178 -@@ -53,14 +95,18 @@ struct qcom_pcie_resources_v0 { - struct clk *iface_clk; - struct clk *core_clk; - struct clk *phy_clk; -+ struct clk *aux_clk; -+ struct clk *ref_clk; - struct reset_control *pci_reset; - struct reset_control *axi_reset; - struct reset_control *ahb_reset; - struct reset_control *por_reset; - struct reset_control *phy_reset; -+ struct reset_control *ext_reset; - struct regulator *vdda; - struct regulator *vdda_phy; - struct regulator *vdda_refclk; -+ uint8_t phy_tx0_term_offset; - }; - - struct qcom_pcie_resources_v1 { -@@ -82,6 +128,7 @@ struct qcom_pcie; - struct qcom_pcie_ops { - int (*get_resources)(struct qcom_pcie *pcie); - int (*init)(struct qcom_pcie *pcie); -+ void (*configure)(struct qcom_pcie *pcie); - void (*deinit)(struct qcom_pcie *pcie); - }; - -@@ -160,6 +207,14 @@ static int qcom_pcie_get_resources_v0(st - if (IS_ERR(res->phy_clk)) - return PTR_ERR(res->phy_clk); - -+ res->aux_clk = devm_clk_get(dev, "aux"); -+ if (IS_ERR(res->aux_clk)) -+ return PTR_ERR(res->aux_clk); -+ -+ res->ref_clk = devm_clk_get(dev, "ref"); -+ if (IS_ERR(res->ref_clk)) -+ return PTR_ERR(res->ref_clk); -+ - res->pci_reset = devm_reset_control_get(dev, "pci"); - if (IS_ERR(res->pci_reset)) - return PTR_ERR(res->pci_reset); -@@ -180,6 +235,14 @@ static int qcom_pcie_get_resources_v0(st - if (IS_ERR(res->phy_reset)) - return PTR_ERR(res->phy_reset); - -+ res->ext_reset = devm_reset_control_get(dev, "ext"); -+ if (IS_ERR(res->ext_reset)) -+ return PTR_ERR(res->ext_reset); -+ -+ if (of_property_read_u8(dev->of_node, "phy-tx0-term-offset", -+ &res->phy_tx0_term_offset)) -+ res->phy_tx0_term_offset = 0; -+ - return 0; - } - -@@ -223,15 +286,69 @@ static void qcom_pcie_deinit_v0(struct q - reset_control_assert(res->axi_reset); - reset_control_assert(res->ahb_reset); - reset_control_assert(res->por_reset); -- reset_control_assert(res->pci_reset); -+ reset_control_assert(res->phy_reset); -+ reset_control_assert(res->ext_reset); - clk_disable_unprepare(res->iface_clk); - clk_disable_unprepare(res->core_clk); - clk_disable_unprepare(res->phy_clk); -+ clk_disable_unprepare(res->aux_clk); -+ clk_disable_unprepare(res->ref_clk); - regulator_disable(res->vdda); - regulator_disable(res->vdda_phy); - regulator_disable(res->vdda_refclk); - } - -+static void qcom_pcie_prog_viewport_cfg0(struct qcom_pcie *pcie, u32 busdev) -+{ -+ struct pcie_port *pp = &pcie->pp; -+ -+ /* -+ * program and enable address translation region 0 (device config -+ * address space); region type config; -+ * axi config address range to device config address range -+ */ -+ writel(PCIE20_PLR_IATU_REGION_OUTBOUND | -+ PCIE20_PLR_IATU_REGION_INDEX(0), -+ pcie->pp.dbi_base + PCIE20_PLR_IATU_VIEWPORT); -+ -+ writel(PCIE20_PLR_IATU_TYPE_CFG0, pcie->pp.dbi_base + PCIE20_PLR_IATU_CTRL1); -+ writel(PCIE20_PLR_IATU_ENABLE, pcie->pp.dbi_base + PCIE20_PLR_IATU_CTRL2); -+ writel(pp->cfg0_base, pcie->pp.dbi_base + PCIE20_PLR_IATU_LBAR); -+ writel((pp->cfg0_base >> 32), pcie->pp.dbi_base + PCIE20_PLR_IATU_UBAR); -+ writel((pp->cfg0_base + pp->cfg0_size - 1), -+ pcie->pp.dbi_base + PCIE20_PLR_IATU_LAR); -+ writel(busdev, pcie->pp.dbi_base + PCIE20_PLR_IATU_LTAR); -+ writel(0, pcie->pp.dbi_base + PCIE20_PLR_IATU_UTAR); -+} -+ -+static void qcom_pcie_prog_viewport_mem2_outbound(struct qcom_pcie *pcie) -+{ -+ struct pcie_port *pp = &pcie->pp; -+ -+ /* -+ * program and enable address translation region 2 (device resource -+ * address space); region type memory; -+ * axi device bar address range to device bar address range -+ */ -+ writel(PCIE20_PLR_IATU_REGION_OUTBOUND | -+ PCIE20_PLR_IATU_REGION_INDEX(2), -+ pcie->pp.dbi_base + PCIE20_PLR_IATU_VIEWPORT); -+ -+ writel(PCIE20_PLR_IATU_TYPE_MEM, pcie->pp.dbi_base + PCIE20_PLR_IATU_CTRL1); -+ writel(PCIE20_PLR_IATU_ENABLE, pcie->pp.dbi_base + PCIE20_PLR_IATU_CTRL2); -+ writel(pp->mem_base, pcie->pp.dbi_base + PCIE20_PLR_IATU_LBAR); -+ writel((pp->mem_base >> 32), pcie->pp.dbi_base + PCIE20_PLR_IATU_UBAR); -+ writel(pp->mem_base + pp->mem_size - 1, -+ pcie->pp.dbi_base + PCIE20_PLR_IATU_LAR); -+ writel(pp->mem_bus_addr, pcie->pp.dbi_base + PCIE20_PLR_IATU_LTAR); -+ writel(upper_32_bits(pp->mem_bus_addr), -+ pcie->pp.dbi_base + PCIE20_PLR_IATU_UTAR); -+ -+ /* 256B PCIE buffer setting */ -+ writel(0x1, pcie->pp.dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL0); -+ writel(0x1, pcie->pp.dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL1); -+} -+ - static int qcom_pcie_init_v0(struct qcom_pcie *pcie) - { - struct qcom_pcie_resources_v0 *res = &pcie->res.v0; -@@ -260,13 +377,19 @@ static int qcom_pcie_init_v0(struct qcom - ret = reset_control_assert(res->ahb_reset); - if (ret) { - dev_err(dev, "cannot assert ahb reset\n"); -- goto err_assert_ahb; -+ goto err_assert_reset; -+ } -+ -+ ret = reset_control_deassert(res->ext_reset); -+ if (ret) { -+ dev_err(dev, "cannot deassert ext reset\n"); -+ goto err_assert_reset; - } - - ret = clk_prepare_enable(res->iface_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable iface clock\n"); -- goto err_assert_ahb; -+ goto err_assert_reset; - } - - ret = clk_prepare_enable(res->phy_clk); -@@ -281,22 +404,53 @@ static int qcom_pcie_init_v0(struct qcom - goto err_clk_core; - } - -+ ret = clk_prepare_enable(res->aux_clk); -+ if (ret) { -+ dev_err(dev, "cannot prepare/enable aux clock\n"); -+ goto err_clk_aux; -+ } -+ -+ ret = clk_prepare_enable(res->ref_clk); -+ if (ret) { -+ dev_err(dev, "cannot prepare/enable ref clock\n"); -+ goto err_clk_ref; -+ } -+ - ret = reset_control_deassert(res->ahb_reset); - if (ret) { - dev_err(dev, "cannot deassert ahb reset\n"); - goto err_deassert_ahb; - } -+ udelay(1); - - /* enable PCIe clocks and resets */ - val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); - val &= ~BIT(0); - writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); - -- /* enable external reference clock */ -+ /* Set Tx termination offset */ -+ val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); -+ val &= ~PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK; -+ val |= PHY_CTRL_PHY_TX0_TERM_OFFSET(res->phy_tx0_term_offset); -+ writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); -+ -+ /* PARF programming */ -+ writel(PCS_DEEMPH_TX_DEEMPH_GEN1(0x18) | -+ PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(0x18) | -+ PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(0x22), -+ pcie->parf + PCIE20_PARF_PCS_DEEMPH); -+ writel(PCS_SWING_TX_SWING_FULL(0x78) | -+ PCS_SWING_TX_SWING_LOW(0x78), -+ pcie->parf + PCIE20_PARF_PCS_SWING); -+ writel(PHY_RX0_EQ(0x4), pcie->parf + PCIE20_PARF_CONFIG_BITS); -+ -+ /* Enable reference clock */ - val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK); -- val |= BIT(16); -+ val &= ~REF_USE_PAD; -+ val |= REF_SSP_EN; - writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK); - -+ /* De-assert PHY, PCIe, POR and AXI resets */ - ret = reset_control_deassert(res->phy_reset); - if (ret) { - dev_err(dev, "cannot deassert phy reset\n"); -@@ -327,12 +481,16 @@ static int qcom_pcie_init_v0(struct qcom - return 0; - - err_deassert_ahb: -+ clk_disable_unprepare(res->ref_clk); -+err_clk_ref: -+ clk_disable_unprepare(res->aux_clk); -+err_clk_aux: - clk_disable_unprepare(res->core_clk); - err_clk_core: - clk_disable_unprepare(res->phy_clk); - err_clk_phy: - clk_disable_unprepare(res->iface_clk); --err_assert_ahb: -+err_assert_reset: - regulator_disable(res->vdda_phy); - err_vdda_phy: - regulator_disable(res->vdda_refclk); -@@ -342,6 +500,12 @@ err_refclk: - return ret; - } - -+static void qcom_pcie_configure_v0(struct qcom_pcie *pcie) -+{ -+ qcom_pcie_prog_viewport_cfg0(pcie, MSM_PCIE_DEV_CFG_ADDR); -+ qcom_pcie_prog_viewport_mem2_outbound(pcie); -+} -+ - static void qcom_pcie_deinit_v1(struct qcom_pcie *pcie) - { - struct qcom_pcie_resources_v1 *res = &pcie->res.v1; -@@ -455,6 +619,9 @@ static void qcom_pcie_host_init(struct p - if (ret) - goto err; - -+ if (pcie->ops->init) -+ pcie->ops->init(pcie); -+ - return; - err: - qcom_ep_reset_assert(pcie); -@@ -486,6 +653,7 @@ static struct pcie_host_ops qcom_pcie_dw - static const struct qcom_pcie_ops ops_v0 = { - .get_resources = qcom_pcie_get_resources_v0, - .init = qcom_pcie_init_v0, -+ .configure = qcom_pcie_configure_v0, - .deinit = qcom_pcie_deinit_v0, - }; - diff --git a/target/linux/ipq806x/patches-4.9/0074-ipq806x-usb-Control-USB-master-reset.patch b/target/linux/ipq806x/patches-4.9/0074-ipq806x-usb-Control-USB-master-reset.patch new file mode 100644 index 000000000..d5ff86829 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/0074-ipq806x-usb-Control-USB-master-reset.patch @@ -0,0 +1,75 @@ +From a86bda9f8a7965f0cedd347a9c04800eb9f41ea3 Mon Sep 17 00:00:00 2001 +From: Vasudevan Murugesan +Date: Tue, 21 Jul 2015 10:22:38 +0530 +Subject: ipq806x: usb: Control USB master reset + +During removal of the glue layer(dwc3-of-simple), +USB master reset is set to active and during insertion +it is de-activated. + +Change-Id: I537dc810f6cb2a46664ee674840145066432b957 +Signed-off-by: Vasudevan Murugesan +(cherry picked from commit 4611e13580a216812f85f0801b95442d02eeb836) +--- + drivers/usb/dwc3/dwc3-of-simple.c | 22 ++++++++++++++++++++++ + 1 file changed, 12 insertions(+) + +(limited to 'drivers/usb/dwc3/dwc3-of-simple.c') + +diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c +index f9e92ef..49bf556 100644 +--- a/drivers/usb/dwc3/dwc3-of-simple.c ++++ b/drivers/usb/dwc3/dwc3-of-simple.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -34,6 +35,8 @@ struct dwc3_of_simple { + struct device *dev; + struct clk **clks; + int num_clocks; ++ struct reset_control *mstr_rst_30_0; ++ struct reset_control *mstr_rst_30_1; + }; + + static int dwc3_of_simple_probe(struct platform_device *pdev) +@@ -89,6 +92,20 @@ static int dwc3_of_simple_probe(struct platform_device *pdev) + simple->clks[i] = clk; + } + ++ simple->mstr_rst_30_0 = devm_reset_control_get(dev, "usb30_0_mstr_rst"); ++ ++ if (!IS_ERR(simple->mstr_rst_30_0)) ++ reset_control_deassert(simple->mstr_rst_30_0); ++ else ++ dev_dbg(simple->dev, "cannot get handle for USB PHY 0 master reset control\n"); ++ ++ simple->mstr_rst_30_1 = devm_reset_control_get(dev, "usb30_1_mstr_rst"); ++ ++ if (!IS_ERR(simple->mstr_rst_30_1)) ++ reset_control_deassert(simple->mstr_rst_30_1); ++ else ++ dev_dbg(simple->dev, "cannot get handle for USB PHY 1 master reset control\n"); ++ + ret = of_platform_populate(np, NULL, NULL, dev); + if (ret) { + for (i = 0; i < simple->num_clocks; i++) { +@@ -117,6 +134,12 @@ static int dwc3_of_simple_remove(struct platform_device *pdev) + clk_put(simple->clks[i]); + } + ++ if (!IS_ERR(simple->mstr_rst_30_0)) ++ reset_control_assert(simple->mstr_rst_30_0); ++ ++ if (!IS_ERR(simple->mstr_rst_30_1)) ++ reset_control_assert(simple->mstr_rst_30_1); ++ + of_platform_depopulate(dev); + + pm_runtime_put_sync(dev); +-- +cgit v1.1 diff --git a/target/linux/ipq806x/patches-4.9/104-mtd-nand-add-Winbond-manufacturer-and-chip.patch b/target/linux/ipq806x/patches-4.9/104-mtd-nand-add-Winbond-manufacturer-and-chip.patch index 5aa37db08..d2b58a466 100644 --- a/target/linux/ipq806x/patches-4.9/104-mtd-nand-add-Winbond-manufacturer-and-chip.patch +++ b/target/linux/ipq806x/patches-4.9/104-mtd-nand-add-Winbond-manufacturer-and-chip.patch @@ -36,21 +36,3 @@ Signed-off-by: Christian Lamparter LEGACY_ID_NAND("NAND 4MiB 5V 8-bit", 0x6B, 4, SZ_8K, SP_OPTIONS), LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS), -@@ -182,6 +186,7 @@ struct nand_manufacturers nand_manuf_ids - {NAND_MFR_SANDISK, "SanDisk"}, - {NAND_MFR_INTEL, "Intel"}, - {NAND_MFR_ATO, "ATO"}, -+ {NAND_MFR_WINBOND, "Winbond"}, - {0x0, "Unknown"} - }; - ---- a/include/linux/mtd/nand.h -+++ b/include/linux/mtd/nand.h -@@ -924,6 +924,7 @@ static inline void nand_set_controller_d - #define NAND_MFR_MICRON 0x2c - #define NAND_MFR_AMD 0x01 - #define NAND_MFR_MACRONIX 0xc2 -+#define NAND_MFR_WINBOND 0xef - #define NAND_MFR_EON 0x92 - #define NAND_MFR_SANDISK 0x45 - #define NAND_MFR_INTEL 0x89 diff --git a/target/linux/ipq806x/patches-4.9/131-pinctrl-qcom-ipq4019-add-remaining-pin-definitions.patch b/target/linux/ipq806x/patches-4.9/131-pinctrl-qcom-ipq4019-add-remaining-pin-definitions.patch deleted file mode 100644 index f3ffc2e2c..000000000 --- a/target/linux/ipq806x/patches-4.9/131-pinctrl-qcom-ipq4019-add-remaining-pin-definitions.patch +++ /dev/null @@ -1,516 +0,0 @@ -From 941e3869bdeddb2bebcc52ebfd57efe014887bc6 Mon Sep 17 00:00:00 2001 -Message-Id: <941e3869bdeddb2bebcc52ebfd57efe014887bc6.1500038134.git.chunkeey@googlemail.com> -In-Reply-To: -References: -From: Ram Chandra Jangir -Date: Wed, 10 May 2017 12:51:51 +0200 -Subject: [PATCH v3 2/3] pinctrl: qcom: ipq4019: add most remaining pin - definitions -To: linux-gpio@vger.kernel.org, - devicetree@vger.kernel.org -Cc: Linus Walleij , - Rob Herring , - Mark Rutland - -This patch adds multiple pinctrl functions and mappings -for SDIO, NAND, I2S, WIFI, PCIE, LEDs, etc... that have -been missing from the current minimal version. - -This patch has been updated from the original version -that was posted by Ram Chandra Jangir on the LEDE-DEV ML: -. A short -summary of the changes are documented in the device-tree -patch of this series: -"dt-bindings: pinctrl: add most other IPQ4019 pin functions and groups" - -Cc: Bjorn Andersson -Cc: John Crispin -Signed-off-by: Ram Chandra Jangir -Signed-off-by: Christian Lamparter ---- - drivers/pinctrl/qcom/pinctrl-ipq4019.c | 431 ++++++++++++++++++++++++++------- - 1 file changed, 346 insertions(+), 85 deletions(-) - -diff --git a/drivers/pinctrl/qcom/pinctrl-ipq4019.c b/drivers/pinctrl/qcom/pinctrl-ipq4019.c -index 743d1f458205..9e7f23d29cda 100644 ---- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c -+++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c -@@ -277,12 +277,49 @@ DECLARE_QCA_GPIO_PINS(99); - - enum ipq4019_functions { - qca_mux_gpio, -- qca_mux_blsp_uart1, -+ qca_mux_aud_pin, -+ qca_mux_audio_pwm, - qca_mux_blsp_i2c0, - qca_mux_blsp_i2c1, -- qca_mux_blsp_uart0, -- qca_mux_blsp_spi1, - qca_mux_blsp_spi0, -+ qca_mux_blsp_spi1, -+ qca_mux_blsp_uart0, -+ qca_mux_blsp_uart1, -+ qca_mux_chip_rst, -+ qca_mux_i2s_rx, -+ qca_mux_i2s_spdif_in, -+ qca_mux_i2s_spdif_out, -+ qca_mux_i2s_td, -+ qca_mux_i2s_tx, -+ qca_mux_jtag, -+ qca_mux_led0, -+ qca_mux_led1, -+ qca_mux_led2, -+ qca_mux_led3, -+ qca_mux_led4, -+ qca_mux_led5, -+ qca_mux_led6, -+ qca_mux_led7, -+ qca_mux_led8, -+ qca_mux_led9, -+ qca_mux_led10, -+ qca_mux_led11, -+ qca_mux_mdc, -+ qca_mux_mdio, -+ qca_mux_pcie, -+ qca_mux_pmu, -+ qca_mux_prng_rosc, -+ qca_mux_qpic, -+ qca_mux_rgmii, -+ qca_mux_rmii, -+ qca_mux_sdio, -+ qca_mux_smart0, -+ qca_mux_smart1, -+ qca_mux_smart2, -+ qca_mux_smart3, -+ qca_mux_tm, -+ qca_mux_wifi0, -+ qca_mux_wifi1, - qca_mux_NA, - }; - -@@ -303,108 +340,331 @@ static const char * const gpio_groups[] = { - "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98", - "gpio99", - }; -- --static const char * const blsp_uart1_groups[] = { -- "gpio8", "gpio9", "gpio10", "gpio11", -+static const char * const aud_pin_groups[] = { -+ "gpio48", "gpio49", "gpio50", "gpio51", -+}; -+static const char * const audio_pwm_groups[] = { -+ "gpio30", "gpio31", "gpio32", "gpio33", "gpio64", "gpio65", "gpio66", -+ "gpio67", - }; - static const char * const blsp_i2c0_groups[] = { - "gpio10", "gpio11", "gpio20", "gpio21", "gpio58", "gpio59", - }; --static const char * const blsp_spi0_groups[] = { -- "gpio12", "gpio13", "gpio14", "gpio15", "gpio45", -- "gpio54", "gpio55", "gpio56", "gpio57", --}; - static const char * const blsp_i2c1_groups[] = { - "gpio12", "gpio13", "gpio34", "gpio35", - }; --static const char * const blsp_uart0_groups[] = { -- "gpio16", "gpio17", "gpio60", "gpio61", -+static const char * const blsp_spi0_groups[] = { -+ "gpio12", "gpio13", "gpio14", "gpio15", "gpio45", "gpio54", "gpio55", -+ "gpio56", "gpio57", - }; - static const char * const blsp_spi1_groups[] = { - "gpio44", "gpio45", "gpio46", "gpio47", - }; -+static const char * const blsp_uart0_groups[] = { -+ "gpio16", "gpio17", "gpio60", "gpio61", -+}; -+static const char * const blsp_uart1_groups[] = { -+ "gpio8", "gpio9", "gpio10", "gpio11", -+}; -+static const char * const chip_rst_groups[] = { -+ "gpio62", -+}; -+static const char * const i2s_rx_groups[] = { -+ "gpio0", "gpio1", "gpio2", "gpio20", "gpio21", "gpio22", "gpio23", -+ "gpio58", "gpio60", "gpio61", "gpio63", -+}; -+static const char * const i2s_spdif_in_groups[] = { -+ "gpio34", "gpio59", "gpio63", -+}; -+static const char * const i2s_spdif_out_groups[] = { -+ "gpio35", "gpio62", "gpio63", -+}; -+static const char * const i2s_td_groups[] = { -+ "gpio27", "gpio28", "gpio29", "gpio54", "gpio55", "gpio56", "gpio63", -+}; -+static const char * const i2s_tx_groups[] = { -+ "gpio24", "gpio25", "gpio26", "gpio52", "gpio53", "gpio57", "gpio60", -+ "gpio61", -+}; -+static const char * const jtag_groups[] = { -+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", -+}; -+static const char * const led0_groups[] = { -+ "gpio16", "gpio36", "gpio60", -+}; -+static const char * const led1_groups[] = { -+ "gpio17", "gpio37", "gpio61", -+}; -+static const char * const led2_groups[] = { -+ "gpio36", "gpio38", "gpio58", -+}; -+static const char * const led3_groups[] = { -+ "gpio39", -+}; -+static const char * const led4_groups[] = { -+ "gpio40", -+}; -+static const char * const led5_groups[] = { -+ "gpio44", -+}; -+static const char * const led6_groups[] = { -+ "gpio45", -+}; -+static const char * const led7_groups[] = { -+ "gpio46", -+}; -+static const char * const led8_groups[] = { -+ "gpio47", -+}; -+static const char * const led9_groups[] = { -+ "gpio48", -+}; -+static const char * const led10_groups[] = { -+ "gpio49", -+}; -+static const char * const led11_groups[] = { -+ "gpio50", -+}; -+static const char * const mdc_groups[] = { -+ "gpio7", "gpio52", -+}; -+static const char * const mdio_groups[] = { -+ "gpio6", "gpio53", -+}; -+static const char * const pcie_groups[] = { -+ "gpio39", "gpio52", -+}; -+static const char * const pmu_groups[] = { -+ "gpio54", "gpio55", -+}; -+static const char * const prng_rosc_groups[] = { -+ "gpio53", -+}; -+static const char * const qpic_groups[] = { -+ "gpio52", "gpio53", "gpio54", "gpio55", "gpio56", "gpio57", "gpio58", -+ "gpio59", "gpio60", "gpio61", "gpio62", "gpio63", "gpio64", "gpio65", -+ "gpio66", "gpio67", "gpio68", "gpio69", -+}; -+static const char * const rgmii_groups[] = { -+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", -+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", -+}; -+static const char * const rmii_groups[] = { -+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", -+ "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49", -+ "gpio50", "gpio51", -+}; -+static const char * const sdio_groups[] = { -+ "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29", -+ "gpio30", "gpio31", "gpio32", -+}; -+static const char * const smart0_groups[] = { -+ "gpio0", "gpio1", "gpio2", "gpio5", "gpio44", "gpio45", "gpio46", -+ "gpio47", -+}; -+static const char * const smart1_groups[] = { -+ "gpio8", "gpio9", "gpio16", "gpio17", "gpio58", "gpio59", "gpio60", -+ "gpio61", -+}; -+static const char * const smart2_groups[] = { -+ "gpio40", "gpio41", "gpio48", "gpio49", -+}; -+static const char * const smart3_groups[] = { -+ "gpio58", "gpio59", "gpio60", "gpio61", -+}; -+static const char * const tm_groups[] = { -+ "gpio52", "gpio53", "gpio54", "gpio55", "gpio56", "gpio57", "gpio58", -+ "gpio59", "gpio60", "gpio61", "gpio62", "gpio63", -+}; -+static const char * const wifi0_groups[] = { -+ "gpio37", "gpio40", "gpio41", "gpio42", "gpio50", "gpio51", "gpio52", -+ "gpio53", "gpio56", "gpio57", "gpio58", "gpio98", -+}; -+static const char * const wifi1_groups[] = { -+ "gpio37", "gpio40", "gpio41", "gpio43", "gpio50", "gpio51", "gpio52", -+ "gpio53", "gpio56", "gpio57", "gpio58", "gpio98", -+}; - - static const struct msm_function ipq4019_functions[] = { -- FUNCTION(gpio), -- FUNCTION(blsp_uart1), -+ FUNCTION(aud_pin), -+ FUNCTION(audio_pwm), - FUNCTION(blsp_i2c0), - FUNCTION(blsp_i2c1), -- FUNCTION(blsp_uart0), -- FUNCTION(blsp_spi1), - FUNCTION(blsp_spi0), -+ FUNCTION(blsp_spi1), -+ FUNCTION(blsp_uart0), -+ FUNCTION(blsp_uart1), -+ FUNCTION(chip_rst), -+ FUNCTION(gpio), -+ FUNCTION(i2s_rx), -+ FUNCTION(i2s_spdif_in), -+ FUNCTION(i2s_spdif_out), -+ FUNCTION(i2s_td), -+ FUNCTION(i2s_tx), -+ FUNCTION(jtag), -+ FUNCTION(led0), -+ FUNCTION(led1), -+ FUNCTION(led2), -+ FUNCTION(led3), -+ FUNCTION(led4), -+ FUNCTION(led5), -+ FUNCTION(led6), -+ FUNCTION(led7), -+ FUNCTION(led8), -+ FUNCTION(led9), -+ FUNCTION(led10), -+ FUNCTION(led11), -+ FUNCTION(mdc), -+ FUNCTION(mdio), -+ FUNCTION(pcie), -+ FUNCTION(pmu), -+ FUNCTION(prng_rosc), -+ FUNCTION(qpic), -+ FUNCTION(rgmii), -+ FUNCTION(rmii), -+ FUNCTION(sdio), -+ FUNCTION(smart0), -+ FUNCTION(smart1), -+ FUNCTION(smart2), -+ FUNCTION(smart3), -+ FUNCTION(tm), -+ FUNCTION(wifi0), -+ FUNCTION(wifi1), - }; - - static const struct msm_pingroup ipq4019_groups[] = { -- PINGROUP(0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(4, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(5, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(6, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(7, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(8, blsp_uart1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(9, blsp_uart1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(10, blsp_uart1, NA, NA, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(11, blsp_uart1, NA, NA, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(12, blsp_spi0, blsp_i2c1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(13, blsp_spi0, blsp_i2c1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(14, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(15, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(16, blsp_uart0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(17, blsp_uart0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(0, jtag, smart0, i2s_rx, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(1, jtag, smart0, i2s_rx, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(2, jtag, smart0, i2s_rx, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(3, jtag, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(4, jtag, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(5, jtag, smart0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA), -+ PINGROUP(6, mdio, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(7, mdc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(8, blsp_uart1, NA, NA, smart1, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(9, blsp_uart1, NA, NA, smart1, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(10, blsp_uart1, NA, NA, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(11, blsp_uart1, NA, NA, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(12, blsp_spi0, blsp_i2c1, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(13, blsp_spi0, blsp_i2c1, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(14, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA), -+ PINGROUP(15, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA), -+ PINGROUP(16, blsp_uart0, led0, smart1, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(17, blsp_uart0, led1, smart1, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), - PINGROUP(18, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), - PINGROUP(19, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(20, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(21, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(22, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(23, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(24, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(25, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(26, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(27, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(28, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(29, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(30, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(31, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(32, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(33, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(34, blsp_i2c1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(35, blsp_i2c1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(36, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(37, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(38, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(39, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(40, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(41, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(42, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(43, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(44, NA, blsp_spi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(45, NA, blsp_spi1, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(46, NA, blsp_spi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(47, NA, blsp_spi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(48, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(49, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(50, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(51, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(52, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(53, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(54, NA, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(55, NA, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(56, NA, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(57, NA, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(58, NA, NA, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(59, NA, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(60, NA, blsp_uart0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(61, NA, blsp_uart0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(62, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(63, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(64, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(65, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(66, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(67, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(68, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(69, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(20, blsp_i2c0, i2s_rx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(21, blsp_i2c0, i2s_rx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(22, rgmii, i2s_rx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA), -+ PINGROUP(23, sdio, rgmii, i2s_rx, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(24, sdio, rgmii, i2s_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(25, sdio, rgmii, i2s_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(26, sdio, rgmii, i2s_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(27, sdio, rgmii, i2s_td, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(28, sdio, rgmii, i2s_td, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(29, sdio, rgmii, i2s_td, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(30, sdio, rgmii, audio_pwm, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(31, sdio, rgmii, audio_pwm, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(32, sdio, rgmii, audio_pwm, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(33, rgmii, audio_pwm, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(34, blsp_i2c1, i2s_spdif_in, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA, NA), -+ PINGROUP(35, blsp_i2c1, i2s_spdif_out, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA, NA), -+ PINGROUP(36, rmii, led2, led0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA), -+ PINGROUP(37, rmii, wifi0, wifi1, led1, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(38, rmii, led2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA), -+ PINGROUP(39, rmii, pcie, led3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA), -+ PINGROUP(40, rmii, wifi0, wifi1, smart2, led4, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(41, rmii, wifi0, wifi1, smart2, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(42, rmii, wifi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA), -+ PINGROUP(43, rmii, wifi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA), -+ PINGROUP(44, rmii, blsp_spi1, smart0, led5, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(45, rmii, blsp_spi1, blsp_spi0, smart0, led6, NA, NA, NA, NA, -+ NA, NA, NA, NA, NA), -+ PINGROUP(46, rmii, blsp_spi1, smart0, led7, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(47, rmii, blsp_spi1, smart0, led8, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(48, rmii, aud_pin, smart2, led9, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(49, rmii, aud_pin, smart2, led10, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(50, rmii, aud_pin, wifi0, wifi1, led11, NA, NA, NA, NA, NA, -+ NA, NA, NA, NA), -+ PINGROUP(51, rmii, aud_pin, wifi0, wifi1, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA, NA), -+ PINGROUP(52, qpic, mdc, pcie, i2s_tx, NA, NA, NA, tm, wifi0, wifi1, NA, -+ NA, NA, NA), -+ PINGROUP(53, qpic, mdio, i2s_tx, prng_rosc, NA, tm, wifi0, wifi1, NA, -+ NA, NA, NA, NA, NA), -+ PINGROUP(54, qpic, blsp_spi0, i2s_td, NA, pmu, NA, NA, NA, tm, NA, NA, -+ NA, NA, NA), -+ PINGROUP(55, qpic, blsp_spi0, i2s_td, NA, pmu, NA, NA, NA, tm, NA, NA, -+ NA, NA, NA), -+ PINGROUP(56, qpic, blsp_spi0, i2s_td, NA, NA, tm, wifi0, wifi1, NA, NA, -+ NA, NA, NA, NA), -+ PINGROUP(57, qpic, blsp_spi0, i2s_tx, NA, NA, tm, wifi0, wifi1, NA, NA, -+ NA, NA, NA, NA), -+ PINGROUP(58, qpic, led2, blsp_i2c0, smart3, smart1, i2s_rx, NA, NA, tm, -+ wifi0, wifi1, NA, NA, NA), -+ PINGROUP(59, qpic, blsp_i2c0, smart3, smart1, i2s_spdif_in, NA, NA, NA, -+ NA, NA, tm, NA, NA, NA), -+ PINGROUP(60, qpic, blsp_uart0, smart1, smart3, led0, i2s_tx, i2s_rx, -+ NA, NA, NA, NA, NA, tm, NA), -+ PINGROUP(61, qpic, blsp_uart0, smart1, smart3, led1, i2s_tx, i2s_rx, -+ NA, NA, NA, NA, NA, tm, NA), -+ PINGROUP(62, qpic, chip_rst, NA, NA, i2s_spdif_out, NA, NA, NA, NA, NA, -+ tm, NA, NA, NA), -+ PINGROUP(63, qpic, NA, NA, NA, i2s_td, i2s_rx, i2s_spdif_out, -+ i2s_spdif_in, NA, NA, NA, NA, tm, NA), -+ PINGROUP(64, qpic, audio_pwm, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(65, qpic, audio_pwm, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(66, qpic, audio_pwm, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(67, qpic, audio_pwm, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA, NA), -+ PINGROUP(68, qpic, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(69, qpic, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), - PINGROUP(70, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), - PINGROUP(71, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), - PINGROUP(72, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -@@ -433,7 +693,8 @@ static const struct msm_pingroup ipq4019_groups[] = { - PINGROUP(95, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), - PINGROUP(96, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), - PINGROUP(97, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(98, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(98, wifi0, wifi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -+ NA), - PINGROUP(99, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), - }; - --- -2.13.2 - diff --git a/target/linux/ipq806x/patches-4.9/132-pinctrl-qcom-add-support-to-configure-ipq40xx-GPIO_P.patch b/target/linux/ipq806x/patches-4.9/132-pinctrl-qcom-add-support-to-configure-ipq40xx-GPIO_P.patch deleted file mode 100644 index f05ea750b..000000000 --- a/target/linux/ipq806x/patches-4.9/132-pinctrl-qcom-add-support-to-configure-ipq40xx-GPIO_P.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 895bbe5061fe2a6825503f57263a4eff9bb78a3c Mon Sep 17 00:00:00 2001 -Message-Id: <895bbe5061fe2a6825503f57263a4eff9bb78a3c.1500038134.git.chunkeey@googlemail.com> -In-Reply-To: <941e3869bdeddb2bebcc52ebfd57efe014887bc6.1500038134.git.chunkeey@googlemail.com> -References: - <941e3869bdeddb2bebcc52ebfd57efe014887bc6.1500038134.git.chunkeey@googlemail.com> -From: Ram Chandra Jangir -Date: Sun, 4 Jun 2017 21:38:21 +0200 -Subject: [PATCH v3 3/3] pinctrl: msm: add support to configure ipq40xx - GPIO_PULL bits -To: linux-gpio@vger.kernel.org, - devicetree@vger.kernel.org -Cc: Linus Walleij , - Rob Herring , - Mark Rutland - -GPIO_PULL bits configurations in TLMM_GPIO_CFG register -differs for IPQ40xx from rest of the other qcom SoCs. -As it does not support the keeper state and therefore can't -support bias-bus-hold property. - -This patch adds a pull_no_keeper setting which configures the -msm_gpio_pull bits for ipq40xx. This is required to fix the -proper configurations of gpio-pull bits for nand pins mux. - -IPQ40xx SoC: -2'b10: Internal pull up enable. -2'b11: Unsupport - -For other SoC's: -2'b10: Keeper -2'b11: Pull-Up - -Note: Due to pull_no_keeper length, all kerneldoc entries -in the msm_pinctrl_soc_data struct had to be realigned. - -Reviewed-by: Bjorn Andersson -Signed-off-by: Ram Chandra Jangir -Signed-off-by: Christian Lamparter ---- - drivers/pinctrl/qcom/pinctrl-ipq4019.c | 1 + - drivers/pinctrl/qcom/pinctrl-msm.c | 25 +++++++++++++++++++------ - drivers/pinctrl/qcom/pinctrl-msm.h | 16 +++++++++------- - 3 files changed, 29 insertions(+), 13 deletions(-) - -diff --git a/drivers/pinctrl/qcom/pinctrl-ipq4019.c b/drivers/pinctrl/qcom/pinctrl-ipq4019.c -index 9e7f23d29cda..1979b14b6fc3 100644 ---- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c -+++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c -@@ -706,6 +706,7 @@ static const struct msm_pinctrl_soc_data ipq4019_pinctrl = { - .groups = ipq4019_groups, - .ngroups = ARRAY_SIZE(ipq4019_groups), - .ngpios = 100, -+ .pull_no_keeper = true, - }; - - static int ipq4019_pinctrl_probe(struct platform_device *pdev) -diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c -index 273badd92561..e5e27d79f5ef 100644 ---- a/drivers/pinctrl/qcom/pinctrl-msm.c -+++ b/drivers/pinctrl/qcom/pinctrl-msm.c -@@ -202,10 +202,11 @@ static int msm_config_reg(struct msm_pinctrl *pctrl, - return 0; - } - --#define MSM_NO_PULL 0 --#define MSM_PULL_DOWN 1 --#define MSM_KEEPER 2 --#define MSM_PULL_UP 3 -+#define MSM_NO_PULL 0 -+#define MSM_PULL_DOWN 1 -+#define MSM_KEEPER 2 -+#define MSM_PULL_UP_NO_KEEPER 2 -+#define MSM_PULL_UP 3 - - static unsigned msm_regval_to_drive(u32 val) - { -@@ -243,10 +244,16 @@ static int msm_config_group_get(struct pinctrl_dev *pctldev, - arg = arg == MSM_PULL_DOWN; - break; - case PIN_CONFIG_BIAS_BUS_HOLD: -+ if (pctrl->soc->pull_no_keeper) -+ return -ENOTSUPP; -+ - arg = arg == MSM_KEEPER; - break; - case PIN_CONFIG_BIAS_PULL_UP: -- arg = arg == MSM_PULL_UP; -+ if (pctrl->soc->pull_no_keeper) -+ arg = arg == MSM_PULL_UP_NO_KEEPER; -+ else -+ arg = arg == MSM_PULL_UP; - break; - case PIN_CONFIG_DRIVE_STRENGTH: - arg = msm_regval_to_drive(arg); -@@ -309,10 +316,16 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev, - arg = MSM_PULL_DOWN; - break; - case PIN_CONFIG_BIAS_BUS_HOLD: -+ if (pctrl->soc->pull_no_keeper) -+ return -ENOTSUPP; -+ - arg = MSM_KEEPER; - break; - case PIN_CONFIG_BIAS_PULL_UP: -- arg = MSM_PULL_UP; -+ if (pctrl->soc->pull_no_keeper) -+ arg = MSM_PULL_UP_NO_KEEPER; -+ else -+ arg = MSM_PULL_UP; - break; - case PIN_CONFIG_DRIVE_STRENGTH: - /* Check for invalid values */ -diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h -index 54fdd04ce9d5..9b9feea540ff 100644 ---- a/drivers/pinctrl/qcom/pinctrl-msm.h -+++ b/drivers/pinctrl/qcom/pinctrl-msm.h -@@ -99,13 +99,14 @@ struct msm_pingroup { - - /** - * struct msm_pinctrl_soc_data - Qualcomm pin controller driver configuration -- * @pins: An array describing all pins the pin controller affects. -- * @npins: The number of entries in @pins. -- * @functions: An array describing all mux functions the SoC supports. -- * @nfunctions: The number of entries in @functions. -- * @groups: An array describing all pin groups the pin SoC supports. -- * @ngroups: The numbmer of entries in @groups. -- * @ngpio: The number of pingroups the driver should expose as GPIOs. -+ * @pins: An array describing all pins the pin controller affects. -+ * @npins: The number of entries in @pins. -+ * @functions: An array describing all mux functions the SoC supports. -+ * @nfunctions: The number of entries in @functions. -+ * @groups: An array describing all pin groups the pin SoC supports. -+ * @ngroups: The numbmer of entries in @groups. -+ * @ngpio: The number of pingroups the driver should expose as GPIOs. -+ * @pull_no_keeper: The SoC does not support keeper bias. - */ - struct msm_pinctrl_soc_data { - const struct pinctrl_pin_desc *pins; -@@ -115,6 +116,7 @@ struct msm_pinctrl_soc_data { - const struct msm_pingroup *groups; - unsigned ngroups; - unsigned ngpios; -+ bool pull_no_keeper; - }; - - int msm_pinctrl_probe(struct platform_device *pdev, --- -2.13.2 - diff --git a/target/linux/ipq806x/patches-4.9/140-qcom-ipq4019-fix-i2c_0-node.patch b/target/linux/ipq806x/patches-4.9/140-qcom-ipq4019-fix-i2c_0-node.patch deleted file mode 100644 index 041d8961d..000000000 --- a/target/linux/ipq806x/patches-4.9/140-qcom-ipq4019-fix-i2c_0-node.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 830a63791185f4daaecb8d1102c4ee3c9210c03c Mon Sep 17 00:00:00 2001 -From: Christian Lamparter -Date: Mon, 1 May 2017 13:42:41 +0200 -Subject: [PATCH 1/2] qcom: ipq4019: fix i2c_0 node - -This patch fixes two typos in the i2c_0 node for the ipq4019. -The register size is just 0x600. The core clock is -GCC_BLSP1_QUP1_I2C_APPS_CLK. GCC_BLSP1_QUP2_I2C_APPS_CLK is -used by the second i2c. - -Fixes: e76b4284b520ba3 ("qcom: ipq4019: add i2c node to ipq4019 SoC and DK01 device tree") - -Signed-off-by: Christian Lamparter ---- - arch/arm/boot/dts/qcom-ipq4019.dtsi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/arm/boot/dts/qcom-ipq4019.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -184,7 +184,7 @@ - - i2c_0: i2c@78b7000 { - compatible = "qcom,i2c-qup-v2.2.1"; -- reg = <0x78b7000 0x6000>; -+ reg = <0x78b7000 0x600>; - interrupts = ; - clocks = <&gcc GCC_BLSP1_AHB_CLK>, - <&gcc GCC_BLSP1_QUP1_I2C_APPS_CLK>; diff --git a/target/linux/ipq806x/patches-4.9/141-qcom-ipq4019-add-second-i2c.patch b/target/linux/ipq806x/patches-4.9/141-qcom-ipq4019-add-second-i2c.patch deleted file mode 100644 index 5f98cc909..000000000 --- a/target/linux/ipq806x/patches-4.9/141-qcom-ipq4019-add-second-i2c.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 5110346bcc17b037edd5b0193f31ad046e6242db Mon Sep 17 00:00:00 2001 -From: Christian Lamparter -Date: Mon, 1 May 2017 13:53:07 +0200 -Subject: [PATCH 2/2] qcom: ipq4019: add second i2c - -This patch adds the second i2c block to the IPQ4019 platform. -The second i2c has been successfully tested on the -Cisco Meraki MR33. - -Cc: Chris Blake -Cc: Matthew McClintock -Signed-off-by: Christian Lamparter ---- - arch/arm/boot/dts/qcom-ipq4019.dtsi | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/arch/arm/boot/dts/qcom-ipq4019.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -26,6 +26,7 @@ - aliases { - spi0 = &spi_0; - i2c0 = &i2c_0; -+ i2c1 = &i2c_1; - }; - - cpus { -@@ -196,6 +197,19 @@ - status = "disabled"; - }; - -+ i2c_1: i2c@78b8000 { -+ compatible = "qcom,i2c-qup-v2.2.1"; -+ reg = <0x78b8000 0x600>; -+ interrupts = ; -+ clocks = <&gcc GCC_BLSP1_AHB_CLK>, -+ <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>; -+ clock-names = "iface", "core"; -+ dmas = <&blsp_dma 11>, <&blsp_dma 10>; -+ dma-names = "rx", "tx"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; - - cryptobam: dma@8e04000 { - compatible = "qcom,bam-v1.7.0"; diff --git a/target/linux/ipq806x/patches-4.9/305-qcom-ipq4019-use-v2-of-the-kpss-bringup-mechanism.patch b/target/linux/ipq806x/patches-4.9/305-qcom-ipq4019-use-v2-of-the-kpss-bringup-mechanism.patch index d34f5d1f9..40f5e407b 100644 --- a/target/linux/ipq806x/patches-4.9/305-qcom-ipq4019-use-v2-of-the-kpss-bringup-mechanism.patch +++ b/target/linux/ipq806x/patches-4.9/305-qcom-ipq4019-use-v2-of-the-kpss-bringup-mechanism.patch @@ -17,7 +17,7 @@ Changes: --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -35,19 +35,27 @@ +@@ -34,19 +34,27 @@ cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a7"; @@ -47,7 +47,7 @@ Changes: qcom,acc = <&acc1>; qcom,saw = <&saw1>; reg = <0x1>; -@@ -59,7 +67,8 @@ +@@ -58,7 +66,8 @@ cpu@2 { device_type = "cpu"; compatible = "arm,cortex-a7"; @@ -57,7 +57,7 @@ Changes: qcom,acc = <&acc2>; qcom,saw = <&saw2>; reg = <0x2>; -@@ -71,7 +80,8 @@ +@@ -70,7 +79,8 @@ cpu@3 { device_type = "cpu"; compatible = "arm,cortex-a7"; @@ -67,7 +67,7 @@ Changes: qcom,acc = <&acc3>; qcom,saw = <&saw3>; reg = <0x3>; -@@ -236,22 +246,22 @@ +@@ -212,22 +222,22 @@ }; acc0: clock-controller@b088000 { @@ -94,7 +94,7 @@ Changes: reg = <0x0b0b8000 0x1000>, <0xb008000 0x1000>; }; -@@ -279,6 +289,12 @@ +@@ -255,6 +265,12 @@ regulator; }; diff --git a/target/linux/ipq806x/patches-4.9/306-qcom-ipq4019-add-USB-nodes-to-ipq4019-SoC-device-tre.patch b/target/linux/ipq806x/patches-4.9/306-qcom-ipq4019-add-USB-nodes-to-ipq4019-SoC-device-tre.patch index 22ea75299..3c3fc98a2 100644 --- a/target/linux/ipq806x/patches-4.9/306-qcom-ipq4019-add-USB-nodes-to-ipq4019-SoC-device-tre.patch +++ b/target/linux/ipq806x/patches-4.9/306-qcom-ipq4019-add-USB-nodes-to-ipq4019-SoC-device-tre.patch @@ -51,7 +51,7 @@ Changes: }; --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -331,5 +331,76 @@ +@@ -307,5 +307,76 @@ compatible = "qcom,pshold"; reg = <0x4ab000 0x4>; }; diff --git a/target/linux/ipq806x/patches-4.9/308-dts-ipq4019-add-both-IPQ4019-wifi-block-definitions.patch b/target/linux/ipq806x/patches-4.9/308-dts-ipq4019-add-both-IPQ4019-wifi-block-definitions.patch index 4b2f6c8dd..d12ca4bef 100644 --- a/target/linux/ipq806x/patches-4.9/308-dts-ipq4019-add-both-IPQ4019-wifi-block-definitions.patch +++ b/target/linux/ipq806x/patches-4.9/308-dts-ipq4019-add-both-IPQ4019-wifi-block-definitions.patch @@ -1,100 +1,57 @@ -From 45e183ad169db4e233ce8337cf8b735545151f0e Mon Sep 17 00:00:00 2001 +From 6091a49b0b06bf838fed80498c4f5f40d0fbd447 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 19 Nov 2016 01:22:46 +0100 -Subject: [PATCH] arm: dts: qcom: add both IPQ4019 wifi blocks +Subject: [PATCH] dts: ipq4019: add both IPQ4019 wifi block definitions -This patch adds and enables the device-tree definitions for -both qcom,ipq4019-wifi blocks for the IPQ4019. +The IPQ4019 has two ath10k blocks on the AHB. Both wifi's +are already supported by ath10k. -Support for these have been added into the ath10k driver since: -280e762e9c72 ("ath10k: enable ipq4019 device probe in ahb module") - -The binding documentation was added in commit: -a47aaa69de88 ("dt: bindings: add new dt entry for pre calibration in qcom, ath10k.txt") - -This has been tested on an ASUS RT-AC58U (IPQ4019), -an AVM Fritz!Box 4040 (IPQ4018), a Compex WPJ428(IPQ4028) -and a Meraki MR33 (IPQ4029). - -| a000000.wifi: qca4019 hw1.0 target 0x01000000 chip_id 0x003b00ff [...] -| a000000.wifi: kconfig debug 0 debugfs 1 tracing 0 dfs 1 testmode 1 -| a000000.wifi: firmware ver 10.4-3.4-00082 api 5 features no-p2p,mfp,[...] -| a000000.wifi: board_file api 2 bmi_id 0:16 crc32 5773b188 -| a000000.wifi: htt-ver 2.2 wmi-op 6 htt-op 4 cal pre-cal-file [...] -... -| a800000.wifi: qca4019 hw1.0 target 0x01000000 chip_id 0x003b00ff sub 0000:0000 -| a800000.wifi: kconfig debug 0 debugfs 1 tracing 0 dfs 1 testmode 1 -| a800000.wifi: firmware ver 10.4-3.4-00082 api 5 features no-p2p, [...] -| a800000.wifi: board_file api 2 bmi_id 0:17 crc32 5773b188 -| a800000.wifi: htt-ver 2.2 wmi-op 6 htt-op 4 cal pre-cal-file [...] - -Signed-off-by: Christian Lamparter +Signed-off-by: Christian Lamparter --- - arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi | 8 +++ - arch/arm/boot/dts/qcom-ipq4019.dtsi | 84 +++++++++++++++++++++++++++ - 2 files changed, 92 insertions(+) + arch/arm/boot/dts/qcom-ipq4019.dtsi | 84 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 84 insertions(+) -diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi -index c25d8f5c669d..cfa0c9970d5b 100644 ---- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi -@@ -112,5 +112,13 @@ - watchdog@b017000 { - status = "ok"; - }; -+ -+ wifi@a000000 { -+ status = "ok"; -+ }; -+ -+ wifi@a800000 { -+ status = "ok"; -+ }; - }; - }; -diff --git a/arch/arm/boot/dts/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom-ipq4019.dtsi -index d1a56331ce96..1ddcc96b510c 100644 --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -291,5 +291,89 @@ - compatible = "qcom,pshold"; - reg = <0x4ab000 0x4>; +@@ -378,5 +378,89 @@ + dr_mode = "host"; + }; }; + + wifi0: wifi@a000000 { + compatible = "qcom,ipq4019-wifi"; + reg = <0xa000000 0x200000>; -+ resets = <&gcc WIFI0_CPU_INIT_RESET>, -+ <&gcc WIFI0_RADIO_SRIF_RESET>, -+ <&gcc WIFI0_RADIO_WARM_RESET>, -+ <&gcc WIFI0_RADIO_COLD_RESET>, -+ <&gcc WIFI0_CORE_WARM_RESET>, -+ <&gcc WIFI0_CORE_COLD_RESET>; ++ resets = <&gcc WIFI0_CPU_INIT_RESET ++ &gcc WIFI0_RADIO_SRIF_RESET ++ &gcc WIFI0_RADIO_WARM_RESET ++ &gcc WIFI0_RADIO_COLD_RESET ++ &gcc WIFI0_CORE_WARM_RESET ++ &gcc WIFI0_CORE_COLD_RESET>; + reset-names = "wifi_cpu_init", "wifi_radio_srif", + "wifi_radio_warm", "wifi_radio_cold", + "wifi_core_warm", "wifi_core_cold"; -+ clocks = <&gcc GCC_WCSS2G_CLK>, -+ <&gcc GCC_WCSS2G_REF_CLK>, -+ <&gcc GCC_WCSS2G_RTC_CLK>; ++ clocks = <&gcc GCC_WCSS2G_CLK ++ &gcc GCC_WCSS2G_REF_CLK ++ &gcc GCC_WCSS2G_RTC_CLK>; + clock-names = "wifi_wcss_cmd", "wifi_wcss_ref", + "wifi_wcss_rtc"; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; ++ interrupts = <0 32 IRQ_TYPE_EDGE_RISING ++ 0 33 IRQ_TYPE_EDGE_RISING ++ 0 34 IRQ_TYPE_EDGE_RISING ++ 0 35 IRQ_TYPE_EDGE_RISING ++ 0 36 IRQ_TYPE_EDGE_RISING ++ 0 37 IRQ_TYPE_EDGE_RISING ++ 0 38 IRQ_TYPE_EDGE_RISING ++ 0 39 IRQ_TYPE_EDGE_RISING ++ 0 40 IRQ_TYPE_EDGE_RISING ++ 0 41 IRQ_TYPE_EDGE_RISING ++ 0 42 IRQ_TYPE_EDGE_RISING ++ 0 43 IRQ_TYPE_EDGE_RISING ++ 0 44 IRQ_TYPE_EDGE_RISING ++ 0 45 IRQ_TYPE_EDGE_RISING ++ 0 46 IRQ_TYPE_EDGE_RISING ++ 0 47 IRQ_TYPE_EDGE_RISING ++ 0 168 IRQ_TYPE_NONE>; + interrupt-names = "msi0", "msi1", "msi2", "msi3", + "msi4", "msi5", "msi6", "msi7", + "msi8", "msi9", "msi10", "msi11", @@ -106,37 +63,37 @@ index d1a56331ce96..1ddcc96b510c 100644 + wifi1: wifi@a800000 { + compatible = "qcom,ipq4019-wifi"; + reg = <0xa800000 0x200000>; -+ resets = <&gcc WIFI1_CPU_INIT_RESET>, -+ <&gcc WIFI1_RADIO_SRIF_RESET>, -+ <&gcc WIFI1_RADIO_WARM_RESET>, -+ <&gcc WIFI1_RADIO_COLD_RESET>, -+ <&gcc WIFI1_CORE_WARM_RESET>, -+ <&gcc WIFI1_CORE_COLD_RESET>; ++ resets = <&gcc WIFI1_CPU_INIT_RESET ++ &gcc WIFI1_RADIO_SRIF_RESET ++ &gcc WIFI1_RADIO_WARM_RESET ++ &gcc WIFI1_RADIO_COLD_RESET ++ &gcc WIFI1_CORE_WARM_RESET ++ &gcc WIFI1_CORE_COLD_RESET>; + reset-names = "wifi_cpu_init", "wifi_radio_srif", + "wifi_radio_warm", "wifi_radio_cold", + "wifi_core_warm", "wifi_core_cold"; -+ clocks = <&gcc GCC_WCSS5G_CLK>, -+ <&gcc GCC_WCSS5G_REF_CLK>, -+ <&gcc GCC_WCSS5G_RTC_CLK>; ++ clocks = <&gcc GCC_WCSS5G_CLK ++ &gcc GCC_WCSS5G_REF_CLK ++ &gcc GCC_WCSS5G_RTC_CLK>; + clock-names = "wifi_wcss_cmd", "wifi_wcss_ref", + "wifi_wcss_rtc"; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; ++ interrupts = <0 48 IRQ_TYPE_EDGE_RISING ++ 0 49 IRQ_TYPE_EDGE_RISING ++ 0 50 IRQ_TYPE_EDGE_RISING ++ 0 51 IRQ_TYPE_EDGE_RISING ++ 0 52 IRQ_TYPE_EDGE_RISING ++ 0 53 IRQ_TYPE_EDGE_RISING ++ 0 54 IRQ_TYPE_EDGE_RISING ++ 0 55 IRQ_TYPE_EDGE_RISING ++ 0 56 IRQ_TYPE_EDGE_RISING ++ 0 57 IRQ_TYPE_EDGE_RISING ++ 0 58 IRQ_TYPE_EDGE_RISING ++ 0 59 IRQ_TYPE_EDGE_RISING ++ 0 60 IRQ_TYPE_EDGE_RISING ++ 0 61 IRQ_TYPE_EDGE_RISING ++ 0 62 IRQ_TYPE_EDGE_RISING ++ 0 63 IRQ_TYPE_EDGE_RISING ++ 0 169 IRQ_TYPE_NONE>; + interrupt-names = "msi0", "msi1", "msi2", "msi3", + "msi4", "msi5", "msi6", "msi7", + "msi8", "msi9", "msi10", "msi11", @@ -146,6 +103,3 @@ index d1a56331ce96..1ddcc96b510c 100644 + }; }; }; --- -2.13.3 - diff --git a/target/linux/ipq806x/patches-4.9/309-dts-ipq4019-add-pseudo-random-number-generator.patch b/target/linux/ipq806x/patches-4.9/309-dts-ipq4019-add-pseudo-random-number-generator.patch index f53f78073..abcbb6ee5 100644 --- a/target/linux/ipq806x/patches-4.9/309-dts-ipq4019-add-pseudo-random-number-generator.patch +++ b/target/linux/ipq806x/patches-4.9/309-dts-ipq4019-add-pseudo-random-number-generator.patch @@ -13,7 +13,7 @@ Signed-off-by: Christian Lamparter --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -295,6 +295,13 @@ +@@ -271,6 +271,13 @@ regulator; }; diff --git a/target/linux/ipq806x/patches-4.9/311-dts-ARM-qcom-ipq4019-add-scm-node.patch b/target/linux/ipq806x/patches-4.9/311-dts-ARM-qcom-ipq4019-add-scm-node.patch deleted file mode 100644 index 7ac157058..000000000 --- a/target/linux/ipq806x/patches-4.9/311-dts-ARM-qcom-ipq4019-add-scm-node.patch +++ /dev/null @@ -1,25 +0,0 @@ -From: Christian Lamparter -Date: Mon, 20 Mar 2017 18:08:03 +0100 -Subject: [PATCH] dts: ARM: qcom-ipq4019: add scm node - -This patch adds the device-tree node necessary for communicating -with Qualcomm's TrustZone/Secure Execution Environment -implementation. - -Signed-off-by: Christian Lamparter ---- ---- a/arch/arm/boot/dts/qcom-ipq4019.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -137,6 +137,12 @@ - }; - }; - -+ firmware { -+ scm { -+ compatible = "qcom,scm-ipq4019", "qcom,scm-ipq40xx"; -+ }; -+ }; -+ - soc { - #address-cells = <1>; - #size-cells = <1>; diff --git a/target/linux/ipq806x/patches-4.9/312-firmware-qcom-scm-fuse-access.patch b/target/linux/ipq806x/patches-4.9/312-firmware-qcom-scm-fuse-access.patch deleted file mode 100644 index df6ecfac7..000000000 --- a/target/linux/ipq806x/patches-4.9/312-firmware-qcom-scm-fuse-access.patch +++ /dev/null @@ -1,98 +0,0 @@ ---- a/drivers/firmware/qcom_scm-32.c -+++ b/drivers/firmware/qcom_scm-32.c -@@ -578,3 +578,33 @@ int __qcom_scm_pinmux_write(u32 svc_id, - - return ret; - } -+ -+int __qcom_scm_fuse(struct device *dev, u32 address, u32 *val) -+{ -+ __le32 *otp_value; -+ dma_addr_t in; -+ int ret; -+ -+ otp_value = kzalloc(PAGE_ALIGN(sizeof(*otp_value)), GFP_KERNEL); -+ if (!otp_value) -+ return -ENOMEM; -+ -+ in = dma_map_single(dev, otp_value, sizeof(in), DMA_FROM_DEVICE); -+ -+ ret = dma_mapping_error(dev, in); -+ if (ret != 0) { -+ kfree(otp_value); -+ pr_err("DMA Mapping Error %d\n", ret); -+ return ret; -+ } -+ -+ ret = qcom_scm_call(dev, QCOM_SCM_SVC_FUSE, address, -+ &in, sizeof(in), NULL, 0); -+ -+ dma_unmap_single(dev, in, sizeof(in), DMA_FROM_DEVICE); -+ -+ *val = le32_to_cpu(*otp_value); -+ kfree(otp_value); -+ -+ return ret; -+} ---- a/drivers/firmware/qcom_scm.c -+++ b/drivers/firmware/qcom_scm.c -@@ -165,6 +165,25 @@ int qcom_scm_hdcp_req(struct qcom_scm_hd - EXPORT_SYMBOL(qcom_scm_hdcp_req); - - /** -+ * qcom_scm_fuse() - Reads a value from the OTP -+ * @address: address -+ * -+ * Returns the value of the OTP at the specified address. -+ */ -+int qcom_scm_fuse(u32 address, u32 *val) -+{ -+ int ret = qcom_scm_clk_enable(); -+ -+ if (ret) -+ return ret; -+ -+ ret = __qcom_scm_fuse(__scm->dev, address, val); -+ qcom_scm_clk_disable(); -+ return ret; -+} -+EXPORT_SYMBOL(qcom_scm_fuse); -+ -+/** - * qcom_scm_pas_supported() - Check if the peripheral authentication service is - * available for the given peripherial - * @peripheral: peripheral id ---- a/drivers/firmware/qcom_scm.h -+++ b/drivers/firmware/qcom_scm.h -@@ -63,6 +63,9 @@ extern int __qcom_scm_pas_mss_reset(str - s32 __qcom_scm_pinmux_read(u32 svc_id, u32 cmd_id, u32 arg1); - s32 __qcom_scm_pinmux_write(u32 svc_id, u32 cmd_id, u32 arg1, u32 arg2); - -+#define QCOM_SCM_SVC_FUSE 0x8 -+extern int __qcom_scm_fuse(struct device *dev, u32 address, u32 *val); -+ - /* common error codes */ - #define QCOM_SCM_V2_EBUSY -12 - #define QCOM_SCM_ENOMEM -5 ---- a/include/linux/qcom_scm.h -+++ b/include/linux/qcom_scm.h -@@ -48,4 +48,7 @@ extern u32 qcom_scm_get_version(void); - - extern s32 qcom_scm_pinmux_read(u32 arg1); - extern s32 qcom_scm_pinmux_write(u32 arg1, u32 arg2); -+ -+extern int qcom_scm_fuse(u32 address, u32 *val); -+ - #endif ---- a/drivers/firmware/qcom_scm-64.c -+++ b/drivers/firmware/qcom_scm-64.c -@@ -374,3 +374,9 @@ int __qcom_scm_pinmux_write(u32 svc_id, - { - return -ENOTSUPP; - } -+ -+int __qcom_scm_fuse(struct device *dev, u32 address, u32 *val) -+{ -+ *val = -1; -+ return -ENOTSUPP; -+} diff --git a/target/linux/ipq806x/patches-4.9/701-dts-ipq4019-add-mdio-node.patch b/target/linux/ipq806x/patches-4.9/701-dts-ipq4019-add-mdio-node.patch index 546eb3769..676da7214 100644 --- a/target/linux/ipq806x/patches-4.9/701-dts-ipq4019-add-mdio-node.patch +++ b/target/linux/ipq806x/patches-4.9/701-dts-ipq4019-add-mdio-node.patch @@ -15,7 +15,7 @@ so the info might change. --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -345,6 +345,34 @@ +@@ -315,6 +315,34 @@ reg = <0x4ab000 0x4>; }; diff --git a/target/linux/ipq806x/patches-4.9/702-dts-ipq4019-add-PHY-switch-nodes.patch b/target/linux/ipq806x/patches-4.9/702-dts-ipq4019-add-PHY-switch-nodes.patch index ee8f459e4..79031d398 100644 --- a/target/linux/ipq806x/patches-4.9/702-dts-ipq4019-add-PHY-switch-nodes.patch +++ b/target/linux/ipq806x/patches-4.9/702-dts-ipq4019-add-PHY-switch-nodes.patch @@ -14,7 +14,7 @@ Signed-off-by: Christian Lamparter --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -373,6 +373,29 @@ +@@ -343,6 +343,29 @@ }; }; diff --git a/target/linux/ipq806x/patches-4.9/711-dts-ipq4019-add-ethernet-essedma-node.patch b/target/linux/ipq806x/patches-4.9/711-dts-ipq4019-add-ethernet-essedma-node.patch index afd680d64..771ff2275 100644 --- a/target/linux/ipq806x/patches-4.9/711-dts-ipq4019-add-ethernet-essedma-node.patch +++ b/target/linux/ipq806x/patches-4.9/711-dts-ipq4019-add-ethernet-essedma-node.patch @@ -16,16 +16,16 @@ Signed-off-by: Christian Lamparter --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -27,6 +27,8 @@ +@@ -26,6 +26,8 @@ + aliases { spi0 = &spi_0; i2c0 = &i2c_0; - i2c1 = &i2c_1; + ethernet0 = &gmac0; + ethernet1 = &gmac1; }; cpus { -@@ -396,6 +398,64 @@ +@@ -366,6 +368,64 @@ status = "disabled"; }; diff --git a/target/linux/ipq806x/patches-4.9/820-qcom-ipq4019-Add-IPQ4019-USB-HS-SS-PHY-drivers.patch b/target/linux/ipq806x/patches-4.9/820-qcom-ipq4019-Add-IPQ4019-USB-HS-SS-PHY-drivers.patch index 2aa0448f8..3636c5ca0 100644 --- a/target/linux/ipq806x/patches-4.9/820-qcom-ipq4019-Add-IPQ4019-USB-HS-SS-PHY-drivers.patch +++ b/target/linux/ipq806x/patches-4.9/820-qcom-ipq4019-Add-IPQ4019-USB-HS-SS-PHY-drivers.patch @@ -291,7 +291,7 @@ Changed: +MODULE_DESCRIPTION("USB3 QCA BALDUR HSPHY driver"); --- /dev/null +++ b/drivers/usb/phy/phy-qca-uniphy.c -@@ -0,0 +1,202 @@ +@@ -0,0 +1,135 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any @@ -318,18 +318,6 @@ Changed: +#include +#include +#include -+#include -+ -+#define USB_CALIBRATION_CMD 0x10 -+#define USB3PHY_SPARE_1 0x7FC -+#define RX_LOS_1 0x7C8 -+#define MISC_SOURCE_REG 0x21c -+#define CDR_CONTROL_REG_1 0x80 -+#define PCS_INTERNAL_CONTROL14 0x364 -+#define MMD1_REG_REG_MASK (0x7F << 8) -+#define OTP_MASK (0x7F << 5) -+#define MMD1_REG_AUTOLOAD_MASK (0x1 << 7) -+#define SPARE_1_BIT14_MASK (0x1 << 14) + +struct qca_uni_ss_phy { + struct usb_phy phy; @@ -350,60 +338,6 @@ Changed: + reset_control_assert(phy->por_rst); +} + -+int qca_uni_ss_phy_usb_los_calibration(void __iomem *base) -+{ -+ int err; -+ uint32_t data, otp_val = 0; -+ -+ /* Get OTP value */ -+ err = qcom_scm_fuse(USB_CALIBRATION_CMD, &otp_val); -+ if (err < 0 || !(otp_val & OTP_MASK)) { -+ pr_err("USB Calibration Failed with error %d %d\n", err, otp_val); -+ return 0; -+ } -+ -+ pr_info("Raw USB3 Calibration value %x\n", otp_val); -+ -+ /* -+ * Read the USB3PHY_SPARE_1 register and -+ * set bit 14 to 0 -+ */ -+ data = readl_relaxed(base + USB3PHY_SPARE_1); -+ data = data & (~SPARE_1_BIT14_MASK); -+ writel(data, base + USB3PHY_SPARE_1); -+ udelay(100); -+ -+ /* -+ * Get bit 11:5 value, add with 0x14 and set to the -+ * register USB3PHY_RX_LOS_1 bit MMD1_REG_REG -+ */ -+ data = readl_relaxed(base + RX_LOS_1); -+ otp_val = ((otp_val & OTP_MASK) >> 5) + 0x14; -+ otp_val = otp_val << 8; -+ data = data & (~MMD1_REG_REG_MASK); -+ data = data | otp_val; -+ writel(data, base + RX_LOS_1); -+ udelay(100); -+ -+ /* -+ * Set bit MMD1_REG_AUTOLOAD_SEL_RX_LOS_THRES in -+ * USB3PHY_RX_LOS_1 to 1 -+ */ -+ data = readl_relaxed(base + RX_LOS_1); -+ data = data | MMD1_REG_AUTOLOAD_MASK; -+ writel(data, base + RX_LOS_1); -+ udelay(100); -+ -+ writel(0x4000, base + PCS_INTERNAL_CONTROL14); -+ udelay(100); -+ writel(0xaa0a, base + MISC_SOURCE_REG); -+ udelay(100); -+ writel(0x0202, base + CDR_CONTROL_REG_1); -+ udelay(100); -+ -+ return 0; -+} -+ +static int qca_uni_ss_phy_init(struct usb_phy *x) +{ + struct qca_uni_ss_phy *phy = phy_to_dw_phy(x); @@ -416,8 +350,7 @@ Changed: + /* deassert SS PHY POR reset */ + reset_control_deassert(phy->por_rst); + -+ /* USB LOS Calibration */ -+ return qca_uni_ss_phy_usb_los_calibration(phy->base); ++ return 0; +} + +static int qca_uni_ss_get_resources(struct platform_device *pdev, diff --git a/target/linux/ipq806x/patches-4.9/852-ipq4019-pinctrl-Updated-various-Pin-definitions.patch b/target/linux/ipq806x/patches-4.9/852-ipq4019-pinctrl-Updated-various-Pin-definitions.patch new file mode 100644 index 000000000..d0a6a26a5 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/852-ipq4019-pinctrl-Updated-various-Pin-definitions.patch @@ -0,0 +1,1328 @@ +From fc6cf61517b8b4ab4678659936fc7572f699d6e7 Mon Sep 17 00:00:00 2001 +From: Ram Chandra Jangir +Date: Tue, 28 Mar 2017 14:00:00 +0530 +Subject: [PATCH] ipq4019: pinctrl: Updated various Pin definitions + +Populate default values for various GPIO functions + +Signed-off-by: Ram Chandra Jangir +--- + drivers/pinctrl/qcom/pinctrl-ipq4019.c | 1189 +++++++++++++++++++++++++++++--- + 1 file changed, 1111 insertions(+), 78 deletions(-) + +--- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c ++++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c +@@ -276,16 +276,531 @@ DECLARE_QCA_GPIO_PINS(99); + + + enum ipq4019_functions { ++ qca_mux_rmii0_refclk, ++ qca_mux_wifi0_rfsilient0, ++ qca_mux_wifi1_rfsilient0, ++ qca_mux_smart2, ++ qca_mux_led4, ++ qca_mux_wifi0_cal, ++ qca_mux_wifi1_cal, ++ qca_mux_wifi_wci0, ++ qca_mux_rmii0_dv, ++ qca_mux_wifi_wci1, ++ qca_mux_rmii1_refclk, ++ qca_mux_blsp_spi1, ++ qca_mux_led5, ++ qca_mux_rmii10, ++ qca_mux_led6, ++ qca_mux_rmii11, ++ qca_mux_led7, ++ qca_mux_rmii1_dv, ++ qca_mux_led8, ++ qca_mux_rmii1_tx, ++ qca_mux_aud_pin, ++ qca_mux_led9, ++ qca_mux_rmii1_rx, ++ qca_mux_led10, ++ qca_mux_wifi0_rfsilient1, ++ qca_mux_wifi1_rfsilient1, ++ qca_mux_led11, ++ qca_mux_boot7, ++ qca_mux_qpic_pad, ++ qca_mux_pcie_clk, ++ qca_mux_tm_clk0, ++ qca_mux_wifi00, ++ qca_mux_wifi10, ++ qca_mux_mdio1, ++ qca_mux_prng_rosc, ++ qca_mux_dbg_out, ++ qca_mux_tm0, ++ qca_mux_wifi01, ++ qca_mux_wifi11, ++ qca_mux_atest_char3, ++ qca_mux_pmu0, ++ qca_mux_boot8, ++ qca_mux_tm1, ++ qca_mux_atest_char2, ++ qca_mux_pmu1, ++ qca_mux_boot9, ++ qca_mux_tm2, ++ qca_mux_atest_char1, ++ qca_mux_tm_ack, ++ qca_mux_wifi03, ++ qca_mux_wifi13, ++ qca_mux_qpic_pad4, ++ qca_mux_atest_char0, ++ qca_mux_tm3, ++ qca_mux_wifi02, ++ qca_mux_wifi12, ++ qca_mux_qpic_pad5, ++ qca_mux_smart3, ++ qca_mux_wcss0_dbg14, ++ qca_mux_tm4, ++ qca_mux_wifi04, ++ qca_mux_wifi14, ++ qca_mux_qpic_pad6, ++ qca_mux_wcss0_dbg15, ++ qca_mux_qdss_tracectl_a, ++ qca_mux_boot18, ++ qca_mux_tm5, ++ qca_mux_qpic_pad7, ++ qca_mux_atest_char, ++ qca_mux_wcss0_dbg4, ++ qca_mux_qdss_traceclk_a, ++ qca_mux_boot19, ++ qca_mux_tm6, ++ qca_mux_wcss0_dbg5, ++ qca_mux_qdss_cti_trig_out_a0, ++ qca_mux_boot14, ++ qca_mux_tm7, ++ qca_mux_chip_rst, ++ qca_mux_wcss0_dbg6, ++ qca_mux_qdss_cti_trig_out_b0, ++ qca_mux_boot11, ++ qca_mux_tm8, ++ qca_mux_wcss0_dbg7, ++ qca_mux_wcss1_dbg7, ++ qca_mux_boot20, ++ qca_mux_tm9, ++ qca_mux_qpic_pad1, ++ qca_mux_wcss0_dbg8, ++ qca_mux_wcss1_dbg8, ++ qca_mux_qpic_pad2, ++ qca_mux_wcss0_dbg9, ++ qca_mux_wcss1_dbg9, ++ qca_mux_qpic_pad3, ++ qca_mux_wcss0_dbg10, ++ qca_mux_wcss1_dbg10, ++ qca_mux_qpic_pad0, ++ qca_mux_wcss0_dbg11, ++ qca_mux_wcss1_dbg11, ++ qca_mux_qpic_pad8, ++ qca_mux_wcss0_dbg12, ++ qca_mux_wcss1_dbg12, ++ qca_mux_wifi034, ++ qca_mux_wifi134, ++ qca_mux_jtag_tdi, + qca_mux_gpio, ++ qca_mux_i2s_rx_bclk, ++ qca_mux_jtag_tck, ++ qca_mux_i2s_rx_fsync, ++ qca_mux_jtag_tms, ++ qca_mux_i2s_rxd, ++ qca_mux_smart0, ++ qca_mux_jtag_tdo, ++ qca_mux_jtag_rst, ++ qca_mux_jtag_trst, ++ qca_mux_mdio0, ++ qca_mux_wcss0_dbg18, ++ qca_mux_wcss1_dbg18, ++ qca_mux_qdss_tracedata_a, ++ qca_mux_mdc, ++ qca_mux_wcss0_dbg19, ++ qca_mux_wcss1_dbg19, + qca_mux_blsp_uart1, ++ qca_mux_wifi0_uart, ++ qca_mux_wifi1_uart, ++ qca_mux_smart1, ++ qca_mux_wcss0_dbg20, ++ qca_mux_wcss1_dbg20, ++ qca_mux_wifi0_uart0, ++ qca_mux_wifi1_uart0, ++ qca_mux_wcss0_dbg21, ++ qca_mux_wcss1_dbg21, + qca_mux_blsp_i2c0, ++ qca_mux_wcss0_dbg22, ++ qca_mux_wcss1_dbg22, ++ qca_mux_wcss0_dbg23, ++ qca_mux_wcss1_dbg23, ++ qca_mux_blsp_spi0, + qca_mux_blsp_i2c1, ++ qca_mux_wcss0_dbg24, ++ qca_mux_wcss1_dbg24, ++ qca_mux_wcss0_dbg25, ++ qca_mux_wcss1_dbg25, ++ qca_mux_wcss0_dbg26, ++ qca_mux_wcss1_dbg26, ++ qca_mux_wcss0_dbg, ++ qca_mux_wcss1_dbg, + qca_mux_blsp_uart0, +- qca_mux_blsp_spi1, +- qca_mux_blsp_spi0, ++ qca_mux_led0, ++ qca_mux_wcss0_dbg28, ++ qca_mux_wcss1_dbg28, ++ qca_mux_led1, ++ qca_mux_wcss0_dbg29, ++ qca_mux_wcss1_dbg29, ++ qca_mux_wifi0_uart1, ++ qca_mux_wifi1_uart1, ++ qca_mux_wcss0_dbg30, ++ qca_mux_wcss1_dbg30, ++ qca_mux_wcss0_dbg31, ++ qca_mux_wcss1_dbg31, ++ qca_mux_i2s_rx_mclk, ++ qca_mux_wcss0_dbg16, ++ qca_mux_wcss1_dbg16, ++ qca_mux_wcss0_dbg17, ++ qca_mux_wcss1_dbg17, ++ qca_mux_rgmii0, ++ qca_mux_sdio0, ++ qca_mux_rgmii1, ++ qca_mux_sdio1, ++ qca_mux_rgmii2, ++ qca_mux_i2s_tx_mclk, ++ qca_mux_sdio2, ++ qca_mux_rgmii3, ++ qca_mux_i2s_tx_bclk, ++ qca_mux_sdio3, ++ qca_mux_rgmii_rx, ++ qca_mux_i2s_tx_fsync, ++ qca_mux_sdio_clk, ++ qca_mux_rgmii_txc, ++ qca_mux_i2s_td1, ++ qca_mux_sdio_cmd, ++ qca_mux_i2s_td2, ++ qca_mux_sdio4, ++ qca_mux_i2s_td3, ++ qca_mux_sdio5, ++ qca_mux_audio_pwm0, ++ qca_mux_sdio6, ++ qca_mux_audio_pwm1, ++ qca_mux_wcss0_dbg27, ++ qca_mux_wcss1_dbg27, ++ qca_mux_sdio7, ++ qca_mux_rgmii_rxc, ++ qca_mux_audio_pwm2, ++ qca_mux_rgmii_tx, ++ qca_mux_audio_pwm3, ++ qca_mux_boot2, ++ qca_mux_i2s_spdif_in, ++ qca_mux_i2s_spdif_out, ++ qca_mux_rmii00, ++ qca_mux_led2, ++ qca_mux_rmii01, ++ qca_mux_wifi0_wci, ++ qca_mux_wifi1_wci, ++ qca_mux_boot4, ++ qca_mux_rmii0_tx, ++ qca_mux_boot5, ++ qca_mux_rmii0_rx, ++ qca_mux_pcie_clk1, ++ qca_mux_led3, ++ qca_mux_sdio_cd, + qca_mux_NA, + }; + ++static const char * const rmii0_refclk_groups[] = { ++ "gpio40", ++}; ++static const char * const wifi0_rfsilient0_groups[] = { ++ "gpio40", ++}; ++static const char * const wifi1_rfsilient0_groups[] = { ++ "gpio40", ++}; ++static const char * const smart2_groups[] = { ++ "gpio40", "gpio41", "gpio48", "gpio49", ++}; ++static const char * const led4_groups[] = { ++ "gpio40", ++}; ++static const char * const wifi0_cal_groups[] = { ++ "gpio41", "gpio51", ++}; ++static const char * const wifi1_cal_groups[] = { ++ "gpio41", "gpio51", ++}; ++static const char * const wifi_wci0_groups[] = { ++ "gpio42", ++}; ++static const char * const rmii0_dv_groups[] = { ++ "gpio43", ++}; ++static const char * const wifi_wci1_groups[] = { ++ "gpio43", ++}; ++static const char * const rmii1_refclk_groups[] = { ++ "gpio44", ++}; ++static const char * const blsp_spi1_groups[] = { ++ "gpio44", "gpio45", "gpio46", "gpio47", ++}; ++static const char * const led5_groups[] = { ++ "gpio44", ++}; ++static const char * const rmii10_groups[] = { ++ "gpio45", "gpio50", ++}; ++static const char * const led6_groups[] = { ++ "gpio45", ++}; ++static const char * const rmii11_groups[] = { ++ "gpio46", "gpio51", ++}; ++static const char * const led7_groups[] = { ++ "gpio46", ++}; ++static const char * const rmii1_dv_groups[] = { ++ "gpio47", ++}; ++static const char * const led8_groups[] = { ++ "gpio47", ++}; ++static const char * const rmii1_tx_groups[] = { ++ "gpio48", ++}; ++static const char * const aud_pin_groups[] = { ++ "gpio48", "gpio49", "gpio50", "gpio51", ++}; ++static const char * const led9_groups[] = { ++ "gpio48", ++}; ++static const char * const rmii1_rx_groups[] = { ++ "gpio49", ++}; ++static const char * const led10_groups[] = { ++ "gpio49", ++}; ++static const char * const wifi0_rfsilient1_groups[] = { ++ "gpio50", ++}; ++static const char * const wifi1_rfsilient1_groups[] = { ++ "gpio50", ++}; ++static const char * const led11_groups[] = { ++ "gpio50", ++}; ++static const char * const boot7_groups[] = { ++ "gpio51", ++}; ++static const char * const qpic_pad_groups[] = { ++ "gpio52", "gpio53", "gpio54", "gpio55", "gpio56", "gpio61", "gpio62", ++ "gpio63", "gpio69", ++}; ++static const char * const pcie_clk_groups[] = { ++ "gpio52", ++}; ++static const char * const tm_clk0_groups[] = { ++ "gpio52", ++}; ++static const char * const wifi00_groups[] = { ++ "gpio52", ++}; ++static const char * const wifi10_groups[] = { ++ "gpio52", ++}; ++static const char * const mdio1_groups[] = { ++ "gpio53", ++}; ++static const char * const prng_rosc_groups[] = { ++ "gpio53", ++}; ++static const char * const dbg_out_groups[] = { ++ "gpio53", ++}; ++static const char * const tm0_groups[] = { ++ "gpio53", ++}; ++static const char * const wifi01_groups[] = { ++ "gpio53", ++}; ++static const char * const wifi11_groups[] = { ++ "gpio53", ++}; ++static const char * const atest_char3_groups[] = { ++ "gpio54", ++}; ++static const char * const pmu0_groups[] = { ++ "gpio54", ++}; ++static const char * const boot8_groups[] = { ++ "gpio54", ++}; ++static const char * const tm1_groups[] = { ++ "gpio54", ++}; ++static const char * const atest_char2_groups[] = { ++ "gpio55", ++}; ++static const char * const pmu1_groups[] = { ++ "gpio55", ++}; ++static const char * const boot9_groups[] = { ++ "gpio55", ++}; ++static const char * const tm2_groups[] = { ++ "gpio55", ++}; ++static const char * const atest_char1_groups[] = { ++ "gpio56", ++}; ++static const char * const tm_ack_groups[] = { ++ "gpio56", ++}; ++static const char * const wifi03_groups[] = { ++ "gpio56", ++}; ++static const char * const wifi13_groups[] = { ++ "gpio56", ++}; ++static const char * const qpic_pad4_groups[] = { ++ "gpio57", ++}; ++static const char * const atest_char0_groups[] = { ++ "gpio57", ++}; ++static const char * const tm3_groups[] = { ++ "gpio57", ++}; ++static const char * const wifi02_groups[] = { ++ "gpio57", ++}; ++static const char * const wifi12_groups[] = { ++ "gpio57", ++}; ++static const char * const qpic_pad5_groups[] = { ++ "gpio58", ++}; ++static const char * const smart3_groups[] = { ++ "gpio58", "gpio59", "gpio60", "gpio61", ++}; ++static const char * const wcss0_dbg14_groups[] = { ++ "gpio58", ++}; ++static const char * const tm4_groups[] = { ++ "gpio58", ++}; ++static const char * const wifi04_groups[] = { ++ "gpio58", ++}; ++static const char * const wifi14_groups[] = { ++ "gpio58", ++}; ++static const char * const qpic_pad6_groups[] = { ++ "gpio59", ++}; ++static const char * const wcss0_dbg15_groups[] = { ++ "gpio59", ++}; ++static const char * const qdss_tracectl_a_groups[] = { ++ "gpio59", ++}; ++static const char * const boot18_groups[] = { ++ "gpio59", ++}; ++static const char * const tm5_groups[] = { ++ "gpio59", ++}; ++static const char * const qpic_pad7_groups[] = { ++ "gpio60", ++}; ++static const char * const atest_char_groups[] = { ++ "gpio60", ++}; ++static const char * const wcss0_dbg4_groups[] = { ++ "gpio60", ++}; ++static const char * const qdss_traceclk_a_groups[] = { ++ "gpio60", ++}; ++static const char * const boot19_groups[] = { ++ "gpio60", ++}; ++static const char * const tm6_groups[] = { ++ "gpio60", ++}; ++static const char * const wcss0_dbg5_groups[] = { ++ "gpio61", ++}; ++static const char * const qdss_cti_trig_out_a0_groups[] = { ++ "gpio61", ++}; ++static const char * const boot14_groups[] = { ++ "gpio61", ++}; ++static const char * const tm7_groups[] = { ++ "gpio61", ++}; ++static const char * const chip_rst_groups[] = { ++ "gpio62", ++}; ++static const char * const wcss0_dbg6_groups[] = { ++ "gpio62", ++}; ++static const char * const qdss_cti_trig_out_b0_groups[] = { ++ "gpio62", ++}; ++static const char * const boot11_groups[] = { ++ "gpio62", ++}; ++static const char * const tm8_groups[] = { ++ "gpio62", ++}; ++static const char * const wcss0_dbg7_groups[] = { ++ "gpio63", ++}; ++static const char * const wcss1_dbg7_groups[] = { ++ "gpio63", ++}; ++static const char * const boot20_groups[] = { ++ "gpio63", ++}; ++static const char * const tm9_groups[] = { ++ "gpio63", ++}; ++static const char * const qpic_pad1_groups[] = { ++ "gpio64", ++}; ++static const char * const wcss0_dbg8_groups[] = { ++ "gpio64", ++}; ++static const char * const wcss1_dbg8_groups[] = { ++ "gpio64", ++}; ++static const char * const qpic_pad2_groups[] = { ++ "gpio65", ++}; ++static const char * const wcss0_dbg9_groups[] = { ++ "gpio65", ++}; ++static const char * const wcss1_dbg9_groups[] = { ++ "gpio65", ++}; ++static const char * const qpic_pad3_groups[] = { ++ "gpio66", ++}; ++static const char * const wcss0_dbg10_groups[] = { ++ "gpio66", ++}; ++static const char * const wcss1_dbg10_groups[] = { ++ "gpio66", ++}; ++static const char * const qpic_pad0_groups[] = { ++ "gpio67", ++}; ++static const char * const wcss0_dbg11_groups[] = { ++ "gpio67", ++}; ++static const char * const wcss1_dbg11_groups[] = { ++ "gpio67", ++}; ++static const char * const qpic_pad8_groups[] = { ++ "gpio68", ++}; ++static const char * const wcss0_dbg12_groups[] = { ++ "gpio68", ++}; ++static const char * const wcss1_dbg12_groups[] = { ++ "gpio68", ++}; ++static const char * const wifi034_groups[] = { ++ "gpio98", ++}; ++static const char * const wifi134_groups[] = { ++ "gpio98", ++}; ++static const char * const jtag_tdi_groups[] = { ++ "gpio0", ++}; + static const char * const gpio_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", + "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", +@@ -303,13 +818,103 @@ static const char * const gpio_groups[] + "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98", + "gpio99", + }; +- ++static const char * const i2s_rx_bclk_groups[] = { ++ "gpio0", "gpio21", "gpio60", ++}; ++static const char * const jtag_tck_groups[] = { ++ "gpio1", ++}; ++static const char * const i2s_rx_fsync_groups[] = { ++ "gpio1", "gpio22", "gpio61", ++}; ++static const char * const jtag_tms_groups[] = { ++ "gpio2", ++}; ++static const char * const i2s_rxd_groups[] = { ++ "gpio2", "gpio23", "gpio63", ++}; ++static const char * const smart0_groups[] = { ++ "gpio0", "gpio1", "gpio2", "gpio5", "gpio44", "gpio45", "gpio46", ++ "gpio47", ++}; ++static const char * const jtag_tdo_groups[] = { ++ "gpio3", ++}; ++static const char * const jtag_rst_groups[] = { ++ "gpio4", ++}; ++static const char * const jtag_trst_groups[] = { ++ "gpio5", ++}; ++static const char * const mdio0_groups[] = { ++ "gpio6", ++}; ++static const char * const wcss0_dbg18_groups[] = { ++ "gpio6", "gpio22", "gpio39", ++}; ++static const char * const wcss1_dbg18_groups[] = { ++ "gpio6", "gpio22", "gpio39", ++}; ++static const char * const qdss_tracedata_a_groups[] = { ++ "gpio6", "gpio7", "gpio8", "gpio9", "gpio10", "gpio11", "gpio16", ++ "gpio17", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", ++ "gpio43", ++}; ++static const char * const mdc_groups[] = { ++ "gpio7", "gpio52", ++}; ++static const char * const wcss0_dbg19_groups[] = { ++ "gpio7", "gpio23", "gpio40", ++}; ++static const char * const wcss1_dbg19_groups[] = { ++ "gpio7", "gpio23", "gpio40", ++}; + static const char * const blsp_uart1_groups[] = { + "gpio8", "gpio9", "gpio10", "gpio11", + }; ++static const char * const wifi0_uart_groups[] = { ++ "gpio8", "gpio9", "gpio11", "gpio19", "gpio62", ++}; ++static const char * const wifi1_uart_groups[] = { ++ "gpio8", "gpio11", "gpio19", "gpio62", "gpio63", ++}; ++static const char * const smart1_groups[] = { ++ "gpio8", "gpio9", "gpio16", "gpio17", "gpio58", "gpio59", "gpio60", ++ "gpio61", ++}; ++static const char * const wcss0_dbg20_groups[] = { ++ "gpio8", "gpio24", "gpio41", ++}; ++static const char * const wcss1_dbg20_groups[] = { ++ "gpio8", "gpio24", "gpio41", ++}; ++static const char * const wifi0_uart0_groups[] = { ++ "gpio9", "gpio10", ++}; ++static const char * const wifi1_uart0_groups[] = { ++ "gpio9", "gpio10", ++}; ++static const char * const wcss0_dbg21_groups[] = { ++ "gpio9", "gpio25", "gpio42", ++}; ++static const char * const wcss1_dbg21_groups[] = { ++ "gpio9", "gpio25", "gpio42", ++}; + static const char * const blsp_i2c0_groups[] = { + "gpio10", "gpio11", "gpio20", "gpio21", "gpio58", "gpio59", + }; ++static const char * const wcss0_dbg22_groups[] = { ++ "gpio10", "gpio26", "gpio43", ++}; ++static const char * const wcss1_dbg22_groups[] = { ++ "gpio10", "gpio26", "gpio43", ++}; ++static const char * const wcss0_dbg23_groups[] = { ++ "gpio11", "gpio27", "gpio44", ++}; ++static const char * const wcss1_dbg23_groups[] = { ++ "gpio11", "gpio27", "gpio44", ++}; + static const char * const blsp_spi0_groups[] = { + "gpio12", "gpio13", "gpio14", "gpio15", "gpio45", + "gpio54", "gpio55", "gpio56", "gpio57", +@@ -317,94 +922,582 @@ static const char * const blsp_spi0_grou + static const char * const blsp_i2c1_groups[] = { + "gpio12", "gpio13", "gpio34", "gpio35", + }; ++static const char * const wcss0_dbg24_groups[] = { ++ "gpio12", "gpio28", "gpio45", ++}; ++static const char * const wcss1_dbg24_groups[] = { ++ "gpio12", "gpio28", "gpio45", ++}; ++static const char * const wcss0_dbg25_groups[] = { ++ "gpio13", "gpio29", "gpio46", ++}; ++static const char * const wcss1_dbg25_groups[] = { ++ "gpio13", "gpio29", "gpio46", ++}; ++static const char * const wcss0_dbg26_groups[] = { ++ "gpio14", "gpio30", "gpio47", ++}; ++static const char * const wcss1_dbg26_groups[] = { ++ "gpio14", "gpio30", "gpio47", ++}; ++static const char * const wcss0_dbg_groups[] = { ++ "gpio15", "gpio69", ++}; ++static const char * const wcss1_dbg_groups[] = { ++ "gpio15", ++}; + static const char * const blsp_uart0_groups[] = { + "gpio16", "gpio17", "gpio60", "gpio61", + }; +-static const char * const blsp_spi1_groups[] = { +- "gpio44", "gpio45", "gpio46", "gpio47", ++static const char * const led0_groups[] = { ++ "gpio16", "gpio36", "gpio60", ++}; ++static const char * const wcss0_dbg28_groups[] = { ++ "gpio16", "gpio32", "gpio49", ++}; ++static const char * const wcss1_dbg28_groups[] = { ++ "gpio16", "gpio32", "gpio49", ++}; ++static const char * const led1_groups[] = { ++ "gpio17", "gpio37", "gpio61", ++}; ++static const char * const wcss0_dbg29_groups[] = { ++ "gpio17", "gpio33", "gpio50", ++}; ++static const char * const wcss1_dbg29_groups[] = { ++ "gpio17", "gpio33", "gpio50", ++}; ++static const char * const wifi0_uart1_groups[] = { ++ "gpio18", "gpio63", ++}; ++static const char * const wifi1_uart1_groups[] = { ++ "gpio18", "gpio63", ++}; ++static const char * const wcss0_dbg30_groups[] = { ++ "gpio18", "gpio34", "gpio51", ++}; ++static const char * const wcss1_dbg30_groups[] = { ++ "gpio18", "gpio34", "gpio51", ++}; ++static const char * const wcss0_dbg31_groups[] = { ++ "gpio19", "gpio35", "gpio52", ++}; ++static const char * const wcss1_dbg31_groups[] = { ++ "gpio19", "gpio35", ++}; ++static const char * const i2s_rx_mclk_groups[] = { ++ "gpio20", "gpio58", ++}; ++static const char * const wcss0_dbg16_groups[] = { ++ "gpio20", "gpio37", ++}; ++static const char * const wcss1_dbg16_groups[] = { ++ "gpio20", "gpio37", ++}; ++static const char * const wcss0_dbg17_groups[] = { ++ "gpio21", "gpio38", ++}; ++static const char * const wcss1_dbg17_groups[] = { ++ "gpio21", "gpio38", ++}; ++static const char * const rgmii0_groups[] = { ++ "gpio22", "gpio28", ++}; ++static const char * const sdio0_groups[] = { ++ "gpio23", ++}; ++static const char * const rgmii1_groups[] = { ++ "gpio23", "gpio29", ++}; ++static const char * const sdio1_groups[] = { ++ "gpio24", ++}; ++static const char * const rgmii2_groups[] = { ++ "gpio24", "gpio30", ++}; ++static const char * const i2s_tx_mclk_groups[] = { ++ "gpio24", "gpio52", ++}; ++static const char * const sdio2_groups[] = { ++ "gpio25", ++}; ++static const char * const rgmii3_groups[] = { ++ "gpio25", "gpio31", ++}; ++static const char * const i2s_tx_bclk_groups[] = { ++ "gpio25", "gpio53", "gpio60", ++}; ++static const char * const sdio3_groups[] = { ++ "gpio26", ++}; ++static const char * const rgmii_rx_groups[] = { ++ "gpio26", ++}; ++static const char * const i2s_tx_fsync_groups[] = { ++ "gpio26", "gpio57", "gpio61", ++}; ++static const char * const sdio_clk_groups[] = { ++ "gpio27", ++}; ++static const char * const rgmii_txc_groups[] = { ++ "gpio27", ++}; ++static const char * const i2s_td1_groups[] = { ++ "gpio27", "gpio54", "gpio63", ++}; ++static const char * const sdio_cmd_groups[] = { ++ "gpio28", ++}; ++static const char * const i2s_td2_groups[] = { ++ "gpio28", "gpio55", ++}; ++static const char * const sdio4_groups[] = { ++ "gpio29", ++}; ++static const char * const i2s_td3_groups[] = { ++ "gpio29", "gpio56", ++}; ++static const char * const sdio5_groups[] = { ++ "gpio30", ++}; ++static const char * const audio_pwm0_groups[] = { ++ "gpio30", "gpio64", ++}; ++static const char * const sdio6_groups[] = { ++ "gpio31", ++}; ++static const char * const audio_pwm1_groups[] = { ++ "gpio31", "gpio65", ++}; ++static const char * const wcss0_dbg27_groups[] = { ++ "gpio31", "gpio48", ++}; ++static const char * const wcss1_dbg27_groups[] = { ++ "gpio31", "gpio48", ++}; ++static const char * const sdio7_groups[] = { ++ "gpio32", ++}; ++static const char * const rgmii_rxc_groups[] = { ++ "gpio32", ++}; ++static const char * const audio_pwm2_groups[] = { ++ "gpio32", "gpio66", ++}; ++static const char * const rgmii_tx_groups[] = { ++ "gpio33", ++}; ++static const char * const audio_pwm3_groups[] = { ++ "gpio33", "gpio67", ++}; ++static const char * const boot2_groups[] = { ++ "gpio33", ++}; ++static const char * const i2s_spdif_in_groups[] = { ++ "gpio34", "gpio59", "gpio63", ++}; ++static const char * const i2s_spdif_out_groups[] = { ++ "gpio35", "gpio62", "gpio63", ++}; ++static const char * const rmii00_groups[] = { ++ "gpio36", "gpio41", ++}; ++static const char * const led2_groups[] = { ++ "gpio36", "gpio38", "gpio58", ++}; ++static const char * const rmii01_groups[] = { ++ "gpio37", "gpio42", ++}; ++static const char * const wifi0_wci_groups[] = { ++ "gpio37", ++}; ++static const char * const wifi1_wci_groups[] = { ++ "gpio37", ++}; ++static const char * const boot4_groups[] = { ++ "gpio37", ++}; ++static const char * const rmii0_tx_groups[] = { ++ "gpio38", ++}; ++static const char * const boot5_groups[] = { ++ "gpio38", ++}; ++static const char * const rmii0_rx_groups[] = { ++ "gpio39", ++}; ++static const char * const pcie_clk1_groups[] = { ++ "gpio39", ++}; ++static const char * const led3_groups[] = { ++ "gpio39", ++}; ++static const char * const sdio_cd_groups[] = { ++ "gpio22", + }; + + static const struct msm_function ipq4019_functions[] = { ++ FUNCTION(rmii0_refclk), ++ FUNCTION(wifi0_rfsilient0), ++ FUNCTION(wifi1_rfsilient0), ++ FUNCTION(smart2), ++ FUNCTION(led4), ++ FUNCTION(wifi0_cal), ++ FUNCTION(wifi1_cal), ++ FUNCTION(wifi_wci0), ++ FUNCTION(rmii0_dv), ++ FUNCTION(wifi_wci1), ++ FUNCTION(rmii1_refclk), ++ FUNCTION(blsp_spi1), ++ FUNCTION(led5), ++ FUNCTION(rmii10), ++ FUNCTION(led6), ++ FUNCTION(rmii11), ++ FUNCTION(led7), ++ FUNCTION(rmii1_dv), ++ FUNCTION(led8), ++ FUNCTION(rmii1_tx), ++ FUNCTION(aud_pin), ++ FUNCTION(led9), ++ FUNCTION(rmii1_rx), ++ FUNCTION(led10), ++ FUNCTION(wifi0_rfsilient1), ++ FUNCTION(wifi1_rfsilient1), ++ FUNCTION(led11), ++ FUNCTION(boot7), ++ FUNCTION(qpic_pad), ++ FUNCTION(pcie_clk), ++ FUNCTION(tm_clk0), ++ FUNCTION(wifi00), ++ FUNCTION(wifi10), ++ FUNCTION(mdio1), ++ FUNCTION(prng_rosc), ++ FUNCTION(dbg_out), ++ FUNCTION(tm0), ++ FUNCTION(wifi01), ++ FUNCTION(wifi11), ++ FUNCTION(atest_char3), ++ FUNCTION(pmu0), ++ FUNCTION(boot8), ++ FUNCTION(tm1), ++ FUNCTION(atest_char2), ++ FUNCTION(pmu1), ++ FUNCTION(boot9), ++ FUNCTION(tm2), ++ FUNCTION(atest_char1), ++ FUNCTION(tm_ack), ++ FUNCTION(wifi03), ++ FUNCTION(wifi13), ++ FUNCTION(qpic_pad4), ++ FUNCTION(atest_char0), ++ FUNCTION(tm3), ++ FUNCTION(wifi02), ++ FUNCTION(wifi12), ++ FUNCTION(qpic_pad5), ++ FUNCTION(smart3), ++ FUNCTION(wcss0_dbg14), ++ FUNCTION(tm4), ++ FUNCTION(wifi04), ++ FUNCTION(wifi14), ++ FUNCTION(qpic_pad6), ++ FUNCTION(wcss0_dbg15), ++ FUNCTION(qdss_tracectl_a), ++ FUNCTION(boot18), ++ FUNCTION(tm5), ++ FUNCTION(qpic_pad7), ++ FUNCTION(atest_char), ++ FUNCTION(wcss0_dbg4), ++ FUNCTION(qdss_traceclk_a), ++ FUNCTION(boot19), ++ FUNCTION(tm6), ++ FUNCTION(wcss0_dbg5), ++ FUNCTION(qdss_cti_trig_out_a0), ++ FUNCTION(boot14), ++ FUNCTION(tm7), ++ FUNCTION(chip_rst), ++ FUNCTION(wcss0_dbg6), ++ FUNCTION(qdss_cti_trig_out_b0), ++ FUNCTION(boot11), ++ FUNCTION(tm8), ++ FUNCTION(wcss0_dbg7), ++ FUNCTION(wcss1_dbg7), ++ FUNCTION(boot20), ++ FUNCTION(tm9), ++ FUNCTION(qpic_pad1), ++ FUNCTION(wcss0_dbg8), ++ FUNCTION(wcss1_dbg8), ++ FUNCTION(qpic_pad2), ++ FUNCTION(wcss0_dbg9), ++ FUNCTION(wcss1_dbg9), ++ FUNCTION(qpic_pad3), ++ FUNCTION(wcss0_dbg10), ++ FUNCTION(wcss1_dbg10), ++ FUNCTION(qpic_pad0), ++ FUNCTION(wcss0_dbg11), ++ FUNCTION(wcss1_dbg11), ++ FUNCTION(qpic_pad8), ++ FUNCTION(wcss0_dbg12), ++ FUNCTION(wcss1_dbg12), ++ FUNCTION(wifi034), ++ FUNCTION(wifi134), ++ FUNCTION(jtag_tdi), + FUNCTION(gpio), ++ FUNCTION(i2s_rx_bclk), ++ FUNCTION(jtag_tck), ++ FUNCTION(i2s_rx_fsync), ++ FUNCTION(jtag_tms), ++ FUNCTION(i2s_rxd), ++ FUNCTION(smart0), ++ FUNCTION(jtag_tdo), ++ FUNCTION(jtag_rst), ++ FUNCTION(jtag_trst), ++ FUNCTION(mdio0), ++ FUNCTION(wcss0_dbg18), ++ FUNCTION(wcss1_dbg18), ++ FUNCTION(qdss_tracedata_a), ++ FUNCTION(mdc), ++ FUNCTION(wcss0_dbg19), ++ FUNCTION(wcss1_dbg19), + FUNCTION(blsp_uart1), ++ FUNCTION(wifi0_uart), ++ FUNCTION(wifi1_uart), ++ FUNCTION(smart1), ++ FUNCTION(wcss0_dbg20), ++ FUNCTION(wcss1_dbg20), ++ FUNCTION(wifi0_uart0), ++ FUNCTION(wifi1_uart0), ++ FUNCTION(wcss0_dbg21), ++ FUNCTION(wcss1_dbg21), + FUNCTION(blsp_i2c0), ++ FUNCTION(wcss0_dbg22), ++ FUNCTION(wcss1_dbg22), ++ FUNCTION(wcss0_dbg23), ++ FUNCTION(wcss1_dbg23), ++ FUNCTION(blsp_spi0), + FUNCTION(blsp_i2c1), ++ FUNCTION(wcss0_dbg24), ++ FUNCTION(wcss1_dbg24), ++ FUNCTION(wcss0_dbg25), ++ FUNCTION(wcss1_dbg25), ++ FUNCTION(wcss0_dbg26), ++ FUNCTION(wcss1_dbg26), ++ FUNCTION(wcss0_dbg), ++ FUNCTION(wcss1_dbg), + FUNCTION(blsp_uart0), +- FUNCTION(blsp_spi1), +- FUNCTION(blsp_spi0), ++ FUNCTION(led0), ++ FUNCTION(wcss0_dbg28), ++ FUNCTION(wcss1_dbg28), ++ FUNCTION(led1), ++ FUNCTION(wcss0_dbg29), ++ FUNCTION(wcss1_dbg29), ++ FUNCTION(wifi0_uart1), ++ FUNCTION(wifi1_uart1), ++ FUNCTION(wcss0_dbg30), ++ FUNCTION(wcss1_dbg30), ++ FUNCTION(wcss0_dbg31), ++ FUNCTION(wcss1_dbg31), ++ FUNCTION(i2s_rx_mclk), ++ FUNCTION(wcss0_dbg16), ++ FUNCTION(wcss1_dbg16), ++ FUNCTION(wcss0_dbg17), ++ FUNCTION(wcss1_dbg17), ++ FUNCTION(rgmii0), ++ FUNCTION(sdio0), ++ FUNCTION(rgmii1), ++ FUNCTION(sdio1), ++ FUNCTION(rgmii2), ++ FUNCTION(i2s_tx_mclk), ++ FUNCTION(sdio2), ++ FUNCTION(rgmii3), ++ FUNCTION(i2s_tx_bclk), ++ FUNCTION(sdio3), ++ FUNCTION(rgmii_rx), ++ FUNCTION(i2s_tx_fsync), ++ FUNCTION(sdio_clk), ++ FUNCTION(rgmii_txc), ++ FUNCTION(i2s_td1), ++ FUNCTION(sdio_cmd), ++ FUNCTION(i2s_td2), ++ FUNCTION(sdio4), ++ FUNCTION(i2s_td3), ++ FUNCTION(sdio5), ++ FUNCTION(audio_pwm0), ++ FUNCTION(sdio6), ++ FUNCTION(audio_pwm1), ++ FUNCTION(wcss0_dbg27), ++ FUNCTION(wcss1_dbg27), ++ FUNCTION(sdio7), ++ FUNCTION(rgmii_rxc), ++ FUNCTION(audio_pwm2), ++ FUNCTION(rgmii_tx), ++ FUNCTION(audio_pwm3), ++ FUNCTION(boot2), ++ FUNCTION(i2s_spdif_in), ++ FUNCTION(i2s_spdif_out), ++ FUNCTION(rmii00), ++ FUNCTION(led2), ++ FUNCTION(rmii01), ++ FUNCTION(wifi0_wci), ++ FUNCTION(wifi1_wci), ++ FUNCTION(boot4), ++ FUNCTION(rmii0_tx), ++ FUNCTION(boot5), ++ FUNCTION(rmii0_rx), ++ FUNCTION(pcie_clk1), ++ FUNCTION(led3), ++ FUNCTION(sdio_cd), + }; + + static const struct msm_pingroup ipq4019_groups[] = { +- PINGROUP(0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(4, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(5, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(6, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(7, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(8, blsp_uart1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(9, blsp_uart1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(10, blsp_uart1, NA, NA, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(11, blsp_uart1, NA, NA, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(12, blsp_spi0, blsp_i2c1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(13, blsp_spi0, blsp_i2c1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(14, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(15, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(16, blsp_uart0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(17, blsp_uart0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(18, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(19, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(20, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(21, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(22, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(23, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(24, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(25, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(26, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(27, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(28, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(29, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(30, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(31, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(32, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(33, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(34, blsp_i2c1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(35, blsp_i2c1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(36, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(37, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(38, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(39, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(40, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(41, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(42, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(43, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(44, NA, blsp_spi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(45, NA, blsp_spi1, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(46, NA, blsp_spi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(47, NA, blsp_spi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(48, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(49, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(50, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(51, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(52, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(53, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(54, NA, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(55, NA, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(56, NA, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(57, NA, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(58, NA, NA, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(59, NA, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(60, NA, blsp_uart0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(61, NA, blsp_uart0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(62, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(63, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(64, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(65, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(66, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(67, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(68, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(69, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(0, jtag_tdi, smart0, i2s_rx_bclk, NA, NA, NA, NA, NA, NA, NA, ++ NA, NA, NA, NA), ++ PINGROUP(1, jtag_tck, smart0, i2s_rx_fsync, NA, NA, NA, NA, NA, NA, NA, ++ NA, NA, NA, NA), ++ PINGROUP(2, jtag_tms, smart0, i2s_rxd, NA, NA, NA, NA, NA, NA, NA, NA, ++ NA, NA, NA), ++ PINGROUP(3, jtag_tdo, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ++ NA), ++ PINGROUP(4, jtag_rst, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ++ NA), ++ PINGROUP(5, jtag_trst, smart0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ++ NA, NA), ++ PINGROUP(6, mdio0, NA, wcss0_dbg18, wcss1_dbg18, NA, qdss_tracedata_a, ++ NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(7, mdc, NA, wcss0_dbg19, wcss1_dbg19, NA, qdss_tracedata_a, ++ NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(8, blsp_uart1, wifi0_uart, wifi1_uart, smart1, NA, ++ wcss0_dbg20, wcss1_dbg20, NA, qdss_tracedata_a, NA, NA, NA, ++ NA, NA), ++ PINGROUP(9, blsp_uart1, wifi0_uart0, wifi1_uart0, smart1, wifi0_uart, ++ NA, wcss0_dbg21, wcss1_dbg21, NA, qdss_tracedata_a, NA, NA, ++ NA, NA), ++ PINGROUP(10, blsp_uart1, wifi0_uart0, wifi1_uart0, blsp_i2c0, NA, ++ wcss0_dbg22, wcss1_dbg22, NA, qdss_tracedata_a, NA, NA, NA, ++ NA, NA), ++ PINGROUP(11, blsp_uart1, wifi0_uart, wifi1_uart, blsp_i2c0, NA, ++ wcss0_dbg23, wcss1_dbg23, NA, qdss_tracedata_a, NA, NA, NA, ++ NA, NA), ++ PINGROUP(12, blsp_spi0, blsp_i2c1, NA, wcss0_dbg24, wcss1_dbg24, NA, ++ NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(13, blsp_spi0, blsp_i2c1, NA, wcss0_dbg25, wcss1_dbg25, NA, ++ NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(14, blsp_spi0, NA, wcss0_dbg26, wcss1_dbg26, NA, NA, NA, NA, ++ NA, NA, NA, NA, NA, NA), ++ PINGROUP(15, blsp_spi0, NA, wcss0_dbg, wcss1_dbg, NA, NA, NA, NA, NA, ++ NA, NA, NA, NA, NA), ++ PINGROUP(16, blsp_uart0, led0, smart1, NA, wcss0_dbg28, wcss1_dbg28, ++ NA, qdss_tracedata_a, NA, NA, NA, NA, NA, NA), ++ PINGROUP(17, blsp_uart0, led1, smart1, NA, wcss0_dbg29, wcss1_dbg29, ++ NA, qdss_tracedata_a, NA, NA, NA, NA, NA, NA), ++ PINGROUP(18, wifi0_uart1, wifi1_uart1, NA, wcss0_dbg30, wcss1_dbg30, ++ NA, NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(19, wifi0_uart, wifi1_uart, NA, wcss0_dbg31, wcss1_dbg31, NA, ++ NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(20, blsp_i2c0, i2s_rx_mclk, NA, wcss0_dbg16, wcss1_dbg16, NA, ++ NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(21, blsp_i2c0, i2s_rx_bclk, NA, wcss0_dbg17, wcss1_dbg17, NA, ++ NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(22, rgmii0, i2s_rx_fsync, NA, wcss0_dbg18, wcss1_dbg18, NA, ++ NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(23, sdio0, rgmii1, i2s_rxd, NA, wcss0_dbg19, wcss1_dbg19, NA, ++ NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(24, sdio1, rgmii2, i2s_tx_mclk, NA, wcss0_dbg20, wcss1_dbg20, ++ NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(25, sdio2, rgmii3, i2s_tx_bclk, NA, wcss0_dbg21, wcss1_dbg21, ++ NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(26, sdio3, rgmii_rx, i2s_tx_fsync, NA, wcss0_dbg22, ++ wcss1_dbg22, NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(27, sdio_clk, rgmii_txc, i2s_td1, NA, wcss0_dbg23, ++ wcss1_dbg23, NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(28, sdio_cmd, rgmii0, i2s_td2, NA, wcss0_dbg24, wcss1_dbg24, ++ NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(29, sdio4, rgmii1, i2s_td3, NA, wcss0_dbg25, wcss1_dbg25, NA, ++ NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(30, sdio5, rgmii2, audio_pwm0, NA, wcss0_dbg26, wcss1_dbg26, ++ NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(31, sdio6, rgmii3, audio_pwm1, NA, wcss0_dbg27, wcss1_dbg27, ++ NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(32, sdio7, rgmii_rxc, audio_pwm2, NA, wcss0_dbg28, ++ wcss1_dbg28, NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(33, rgmii_tx, audio_pwm3, NA, wcss0_dbg29, wcss1_dbg29, NA, ++ boot2, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(34, blsp_i2c1, i2s_spdif_in, NA, wcss0_dbg30, wcss1_dbg30, NA, ++ NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(35, blsp_i2c1, i2s_spdif_out, NA, wcss0_dbg31, wcss1_dbg31, ++ NA, NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(36, rmii00, led2, led0, NA, NA, NA, NA, NA, NA, NA, NA, NA, ++ NA, NA), ++ PINGROUP(37, rmii01, wifi0_wci, wifi1_wci, led1, NA, NA, wcss0_dbg16, ++ wcss1_dbg16, NA, qdss_tracedata_a, boot4, NA, NA, NA), ++ PINGROUP(38, rmii0_tx, led2, NA, NA, wcss0_dbg17, wcss1_dbg17, NA, ++ qdss_tracedata_a, boot5, NA, NA, NA, NA, NA), ++ PINGROUP(39, rmii0_rx, pcie_clk1, led3, NA, NA, wcss0_dbg18, ++ wcss1_dbg18, NA, NA, qdss_tracedata_a, NA, NA, NA, NA), ++ PINGROUP(40, rmii0_refclk, wifi0_rfsilient0, wifi1_rfsilient0, smart2, ++ led4, NA, NA, wcss0_dbg19, wcss1_dbg19, NA, NA, ++ qdss_tracedata_a, NA, NA), ++ PINGROUP(41, rmii00, wifi0_cal, wifi1_cal, smart2, NA, NA, wcss0_dbg20, ++ wcss1_dbg20, NA, NA, qdss_tracedata_a, NA, NA, NA), ++ PINGROUP(42, rmii01, wifi_wci0, NA, NA, wcss0_dbg21, wcss1_dbg21, NA, ++ NA, qdss_tracedata_a, NA, NA, NA, NA, NA), ++ PINGROUP(43, rmii0_dv, wifi_wci1, NA, NA, wcss0_dbg22, wcss1_dbg22, NA, ++ NA, qdss_tracedata_a, NA, NA, NA, NA, NA), ++ PINGROUP(44, rmii1_refclk, blsp_spi1, smart0, led5, NA, NA, ++ wcss0_dbg23, wcss1_dbg23, NA, NA, NA, NA, NA, NA), ++ PINGROUP(45, rmii10, blsp_spi1, blsp_spi0, smart0, led6, NA, NA, ++ wcss0_dbg24, wcss1_dbg24, NA, NA, NA, NA, NA), ++ PINGROUP(46, rmii11, blsp_spi1, smart0, led7, NA, NA, wcss0_dbg25, ++ wcss1_dbg25, NA, NA, NA, NA, NA, NA), ++ PINGROUP(47, rmii1_dv, blsp_spi1, smart0, led8, NA, NA, wcss0_dbg26, ++ wcss1_dbg26, NA, NA, NA, NA, NA, NA), ++ PINGROUP(48, rmii1_tx, aud_pin, smart2, led9, NA, NA, wcss0_dbg27, ++ wcss1_dbg27, NA, NA, NA, NA, NA, NA), ++ PINGROUP(49, rmii1_rx, aud_pin, smart2, led10, NA, NA, wcss0_dbg28, ++ wcss1_dbg28, NA, NA, NA, NA, NA, NA), ++ PINGROUP(50, rmii10, aud_pin, wifi0_rfsilient1, wifi1_rfsilient1, ++ led11, NA, NA, wcss0_dbg29, wcss1_dbg29, NA, NA, NA, NA, NA), ++ PINGROUP(51, rmii11, aud_pin, wifi0_cal, wifi1_cal, NA, NA, ++ wcss0_dbg30, wcss1_dbg30, NA, boot7, NA, NA, NA, NA), ++ PINGROUP(52, qpic_pad, mdc, pcie_clk, i2s_tx_mclk, NA, NA, wcss0_dbg31, ++ tm_clk0, wifi00, wifi10, NA, NA, NA, NA), ++ PINGROUP(53, qpic_pad, mdio1, i2s_tx_bclk, prng_rosc, dbg_out, tm0, ++ wifi01, wifi11, NA, NA, NA, NA, NA, NA), ++ PINGROUP(54, qpic_pad, blsp_spi0, i2s_td1, atest_char3, pmu0, NA, NA, ++ boot8, tm1, NA, NA, NA, NA, NA), ++ PINGROUP(55, qpic_pad, blsp_spi0, i2s_td2, atest_char2, pmu1, NA, NA, ++ boot9, tm2, NA, NA, NA, NA, NA), ++ PINGROUP(56, qpic_pad, blsp_spi0, i2s_td3, atest_char1, NA, tm_ack, ++ wifi03, wifi13, NA, NA, NA, NA, NA, NA), ++ PINGROUP(57, qpic_pad4, blsp_spi0, i2s_tx_fsync, atest_char0, NA, tm3, ++ wifi02, wifi12, NA, NA, NA, NA, NA, NA), ++ PINGROUP(58, qpic_pad5, led2, blsp_i2c0, smart3, smart1, i2s_rx_mclk, ++ NA, wcss0_dbg14, tm4, wifi04, wifi14, NA, NA, NA), ++ PINGROUP(59, qpic_pad6, blsp_i2c0, smart3, smart1, i2s_spdif_in, NA, ++ NA, wcss0_dbg15, qdss_tracectl_a, boot18, tm5, NA, NA, NA), ++ PINGROUP(60, qpic_pad7, blsp_uart0, smart1, smart3, led0, i2s_tx_bclk, ++ i2s_rx_bclk, atest_char, NA, wcss0_dbg4, qdss_traceclk_a, ++ boot19, tm6, NA), ++ PINGROUP(61, qpic_pad, blsp_uart0, smart1, smart3, led1, i2s_tx_fsync, ++ i2s_rx_fsync, NA, NA, wcss0_dbg5, qdss_cti_trig_out_a0, ++ boot14, tm7, NA), ++ PINGROUP(62, qpic_pad, chip_rst, wifi0_uart, wifi1_uart, i2s_spdif_out, ++ NA, NA, wcss0_dbg6, qdss_cti_trig_out_b0, boot11, tm8, NA, NA, ++ NA), ++ PINGROUP(63, qpic_pad, wifi0_uart1, wifi1_uart1, wifi1_uart, i2s_td1, ++ i2s_rxd, i2s_spdif_out, i2s_spdif_in, NA, wcss0_dbg7, ++ wcss1_dbg7, boot20, tm9, NA), ++ PINGROUP(64, qpic_pad1, audio_pwm0, NA, wcss0_dbg8, wcss1_dbg8, NA, NA, ++ NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(65, qpic_pad2, audio_pwm1, NA, wcss0_dbg9, wcss1_dbg9, NA, NA, ++ NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(66, qpic_pad3, audio_pwm2, NA, wcss0_dbg10, wcss1_dbg10, NA, ++ NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(67, qpic_pad0, audio_pwm3, NA, wcss0_dbg11, wcss1_dbg11, NA, ++ NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(68, qpic_pad8, NA, wcss0_dbg12, wcss1_dbg12, NA, NA, NA, NA, ++ NA, NA, NA, NA, NA, NA), ++ PINGROUP(69, qpic_pad, NA, wcss0_dbg, NA, NA, NA, NA, NA, NA, NA, NA, ++ NA, NA, NA), + PINGROUP(70, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(71, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(72, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +@@ -433,7 +1526,8 @@ static const struct msm_pingroup ipq4019 + PINGROUP(95, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(96, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(97, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), +- PINGROUP(98, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), ++ PINGROUP(98, wifi034, wifi134, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ++ NA, NA), + PINGROUP(99, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + }; + +@@ -460,6 +1554,7 @@ static const struct of_device_id ipq4019 + static struct platform_driver ipq4019_pinctrl_driver = { + .driver = { + .name = "ipq4019-pinctrl", ++ .owner = THIS_MODULE, + .of_match_table = ipq4019_pinctrl_of_match, + }, + .probe = ipq4019_pinctrl_probe, diff --git a/target/linux/ipq806x/patches-4.9/859-msm-pinctrl-Add-support-to-configure-ipq40xx-GPIO_PU.patch b/target/linux/ipq806x/patches-4.9/859-msm-pinctrl-Add-support-to-configure-ipq40xx-GPIO_PU.patch new file mode 100644 index 000000000..07cf01b26 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/859-msm-pinctrl-Add-support-to-configure-ipq40xx-GPIO_PU.patch @@ -0,0 +1,236 @@ +From e77af7de404eb464f7da9e0daeb8b362cc66a7ba Mon Sep 17 00:00:00 2001 +From: Ram Chandra Jangir +Date: Tue, 9 May 2017 11:45:00 +0530 +Subject: [PATCH] msm: pinctrl: Add support to configure ipq40xx GPIO_PULL bits + +GPIO_PULL bits configurations in TLMM_GPIO_CFG register +differs for IPQ40xx from rest of the other qcom SoC's. +This change add support to configure the msm_gpio_pull +bits for ipq40xx, It is required to fix the proper +configurations of gpio-pull bits for nand pins mux. + +IPQ40xx SoC: +2'b10: Internal pull up enable. +2'b11: Unsupport + +For other SoC's: +2'b10: Keeper +2'b11: Pull-Up + +Signed-off-by: Ram Chandra Jangir +--- + drivers/pinctrl/qcom/pinctrl-apq8064.c | 1 + + drivers/pinctrl/qcom/pinctrl-apq8084.c | 1 + + drivers/pinctrl/qcom/pinctrl-ipq4019.c | 8 ++++++++ + drivers/pinctrl/qcom/pinctrl-ipq8064.c | 1 + + drivers/pinctrl/qcom/pinctrl-mdm9615.c | 1 + + drivers/pinctrl/qcom/pinctrl-msm.c | 21 ++++++++------------- + drivers/pinctrl/qcom/pinctrl-msm.h | 19 +++++++++++++++++++ + drivers/pinctrl/qcom/pinctrl-msm8660.c | 1 + + drivers/pinctrl/qcom/pinctrl-msm8916.c | 1 + + drivers/pinctrl/qcom/pinctrl-msm8960.c | 1 + + drivers/pinctrl/qcom/pinctrl-msm8x74.c | 1 + + 11 files changed, 43 insertions(+), 13 deletions(-) + +--- a/drivers/pinctrl/qcom/pinctrl-apq8064.c ++++ b/drivers/pinctrl/qcom/pinctrl-apq8064.c +@@ -597,6 +597,7 @@ static const struct msm_pinctrl_soc_data + .groups = apq8064_groups, + .ngroups = ARRAY_SIZE(apq8064_groups), + .ngpios = NUM_GPIO_PINGROUPS, ++ .gpio_pull = &msm_gpio_pull, + }; + + static int apq8064_pinctrl_probe(struct platform_device *pdev) +--- a/drivers/pinctrl/qcom/pinctrl-apq8084.c ++++ b/drivers/pinctrl/qcom/pinctrl-apq8084.c +@@ -1206,6 +1206,7 @@ static const struct msm_pinctrl_soc_data + .groups = apq8084_groups, + .ngroups = ARRAY_SIZE(apq8084_groups), + .ngpios = NUM_GPIO_PINGROUPS, ++ .gpio_pull = &msm_gpio_pull, + }; + + static int apq8084_pinctrl_probe(struct platform_device *pdev) +--- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c ++++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c +@@ -1531,6 +1531,13 @@ static const struct msm_pingroup ipq4019 + PINGROUP(99, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + }; + ++static const struct msm_pinctrl_gpio_pull ipq4019_gpio_pull = { ++ .no_pull = 0, ++ .pull_down = 1, ++ .keeper = 0, ++ .pull_up = 2, ++}; ++ + static const struct msm_pinctrl_soc_data ipq4019_pinctrl = { + .pins = ipq4019_pins, + .npins = ARRAY_SIZE(ipq4019_pins), +@@ -1539,6 +1546,7 @@ static const struct msm_pinctrl_soc_data + .groups = ipq4019_groups, + .ngroups = ARRAY_SIZE(ipq4019_groups), + .ngpios = 100, ++ .gpio_pull = &ipq4019_gpio_pull, + }; + + static int ipq4019_pinctrl_probe(struct platform_device *pdev) +--- a/drivers/pinctrl/qcom/pinctrl-ipq8064.c ++++ b/drivers/pinctrl/qcom/pinctrl-ipq8064.c +@@ -630,6 +630,7 @@ static const struct msm_pinctrl_soc_data + .groups = ipq8064_groups, + .ngroups = ARRAY_SIZE(ipq8064_groups), + .ngpios = NUM_GPIO_PINGROUPS, ++ .gpio_pull = &msm_gpio_pull, + }; + + static int ipq8064_pinctrl_probe(struct platform_device *pdev) +--- a/drivers/pinctrl/qcom/pinctrl-mdm9615.c ++++ b/drivers/pinctrl/qcom/pinctrl-mdm9615.c +@@ -444,6 +444,7 @@ static const struct msm_pinctrl_soc_data + .groups = mdm9615_groups, + .ngroups = ARRAY_SIZE(mdm9615_groups), + .ngpios = NUM_GPIO_PINGROUPS, ++ .gpio_pull = &msm_gpio_pull, + }; + + static int mdm9615_pinctrl_probe(struct platform_device *pdev) +--- a/drivers/pinctrl/qcom/pinctrl-msm.c ++++ b/drivers/pinctrl/qcom/pinctrl-msm.c +@@ -203,11 +203,6 @@ static int msm_config_reg(struct msm_pin + return 0; + } + +-#define MSM_NO_PULL 0 +-#define MSM_PULL_DOWN 1 +-#define MSM_KEEPER 2 +-#define MSM_PULL_UP 3 +- + static unsigned msm_regval_to_drive(u32 val) + { + return (val + 1) * 2; +@@ -238,16 +233,16 @@ static int msm_config_group_get(struct p + /* Convert register value to pinconf value */ + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: +- arg = arg == MSM_NO_PULL; ++ arg = arg == pctrl->soc->gpio_pull->no_pull; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: +- arg = arg == MSM_PULL_DOWN; ++ arg = arg == pctrl->soc->gpio_pull->pull_down; + break; + case PIN_CONFIG_BIAS_BUS_HOLD: +- arg = arg == MSM_KEEPER; ++ arg = arg == pctrl->soc->gpio_pull->keeper; + break; + case PIN_CONFIG_BIAS_PULL_UP: +- arg = arg == MSM_PULL_UP; ++ arg = arg == pctrl->soc->gpio_pull->pull_up; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + arg = msm_regval_to_drive(arg); +@@ -304,16 +299,16 @@ static int msm_config_group_set(struct p + /* Convert pinconf values to register values */ + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: +- arg = MSM_NO_PULL; ++ arg = pctrl->soc->gpio_pull->no_pull; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: +- arg = MSM_PULL_DOWN; ++ arg = pctrl->soc->gpio_pull->pull_down; + break; + case PIN_CONFIG_BIAS_BUS_HOLD: +- arg = MSM_KEEPER; ++ arg = pctrl->soc->gpio_pull->keeper; + break; + case PIN_CONFIG_BIAS_PULL_UP: +- arg = MSM_PULL_UP; ++ arg = pctrl->soc->gpio_pull->pull_up; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + /* Check for invalid values */ +--- a/drivers/pinctrl/qcom/pinctrl-msm.h ++++ b/drivers/pinctrl/qcom/pinctrl-msm.h +@@ -98,6 +98,16 @@ struct msm_pingroup { + }; + + /** ++ * struct msm_pinctrl_gpio_pull - pinctrl pull value bit field descriptor ++ */ ++struct msm_pinctrl_gpio_pull { ++ unsigned no_pull; ++ unsigned pull_down; ++ unsigned keeper; ++ unsigned pull_up; ++}; ++ ++/** + * struct msm_pinctrl_soc_data - Qualcomm pin controller driver configuration + * @pins: An array describing all pins the pin controller affects. + * @npins: The number of entries in @pins. +@@ -106,6 +116,7 @@ struct msm_pingroup { + * @groups: An array describing all pin groups the pin SoC supports. + * @ngroups: The numbmer of entries in @groups. + * @ngpio: The number of pingroups the driver should expose as GPIOs. ++ * @gpio_pull_val: The pull value bit field descriptor. + */ + struct msm_pinctrl_soc_data { + const struct pinctrl_pin_desc *pins; +@@ -115,6 +126,14 @@ struct msm_pinctrl_soc_data { + const struct msm_pingroup *groups; + unsigned ngroups; + unsigned ngpios; ++ const struct msm_pinctrl_gpio_pull *gpio_pull; ++}; ++ ++static const struct msm_pinctrl_gpio_pull msm_gpio_pull = { ++ .no_pull = 0, ++ .pull_down = 1, ++ .keeper = 2, ++ .pull_up = 3, + }; + + int msm_pinctrl_probe(struct platform_device *pdev, +--- a/drivers/pinctrl/qcom/pinctrl-msm8660.c ++++ b/drivers/pinctrl/qcom/pinctrl-msm8660.c +@@ -979,6 +979,7 @@ static const struct msm_pinctrl_soc_data + .groups = msm8660_groups, + .ngroups = ARRAY_SIZE(msm8660_groups), + .ngpios = NUM_GPIO_PINGROUPS, ++ .gpio_pull = &msm_gpio_pull, + }; + + static int msm8660_pinctrl_probe(struct platform_device *pdev) +--- a/drivers/pinctrl/qcom/pinctrl-msm8916.c ++++ b/drivers/pinctrl/qcom/pinctrl-msm8916.c +@@ -967,6 +967,7 @@ static const struct msm_pinctrl_soc_data + .groups = msm8916_groups, + .ngroups = ARRAY_SIZE(msm8916_groups), + .ngpios = NUM_GPIO_PINGROUPS, ++ .gpio_pull = &msm_gpio_pull, + }; + + static int msm8916_pinctrl_probe(struct platform_device *pdev) +--- a/drivers/pinctrl/qcom/pinctrl-msm8960.c ++++ b/drivers/pinctrl/qcom/pinctrl-msm8960.c +@@ -1244,6 +1244,7 @@ static const struct msm_pinctrl_soc_data + .groups = msm8960_groups, + .ngroups = ARRAY_SIZE(msm8960_groups), + .ngpios = NUM_GPIO_PINGROUPS, ++ .gpio_pull = &msm_gpio_pull, + }; + + static int msm8960_pinctrl_probe(struct platform_device *pdev) +--- a/drivers/pinctrl/qcom/pinctrl-msm8x74.c ++++ b/drivers/pinctrl/qcom/pinctrl-msm8x74.c +@@ -1069,6 +1069,7 @@ static const struct msm_pinctrl_soc_data + .groups = msm8x74_groups, + .ngroups = ARRAY_SIZE(msm8x74_groups), + .ngpios = NUM_GPIO_PINGROUPS, ++ .gpio_pull = &msm_gpio_pull, + }; + + static int msm8x74_pinctrl_probe(struct platform_device *pdev) diff --git a/target/linux/ipq806x/patches-4.9/863-dts-ipq4019-add-nand-and-qpic-bam-dma-node.patch b/target/linux/ipq806x/patches-4.9/863-dts-ipq4019-add-nand-and-qpic-bam-dma-node.patch index 9ea46c9d4..f054927e0 100644 --- a/target/linux/ipq806x/patches-4.9/863-dts-ipq4019-add-nand-and-qpic-bam-dma-node.patch +++ b/target/linux/ipq806x/patches-4.9/863-dts-ipq4019-add-nand-and-qpic-bam-dma-node.patch @@ -15,17 +15,78 @@ Signed-off-by: Ram Chandra Jangir --- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi -@@ -88,6 +88,26 @@ +@@ -88,6 +88,86 @@ bias-disable; }; }; + + nand_pins: nand_pins { + ++ mux_1 { ++ pins = "gpio52", "gpio53", "gpio54", ++ "gpio55", "gpio56", "gpio61", ++ "gpio62", "gpio63", "gpio69"; ++ function = "qpic_pad"; ++ bias-disable; ++ }; ++ ++ mux_2 { ++ pins = "gpio67"; ++ function = "qpic_pad0"; ++ bias-disable; ++ }; ++ ++ mux_3 { ++ pins = "gpio64"; ++ function = "qpic_pad1"; ++ bias-disable; ++ }; ++ ++ mux_4 { ++ pins = "gpio65"; ++ function = "qpic_pad2"; ++ bias-disable; ++ }; ++ ++ mux_5 { ++ pins = "gpio66"; ++ function = "qpic_pad3"; ++ bias-disable; ++ }; ++ ++ mux_6 { ++ pins = "gpio57"; ++ function = "qpic_pad4"; ++ bias-disable; ++ }; ++ ++ mux_7 { ++ pins = "gpio58"; ++ function = "qpic_pad5"; ++ bias-disable; ++ }; ++ ++ mux_8 { ++ pins = "gpio59"; ++ function = "qpic_pad6"; ++ bias-disable; ++ }; ++ ++ mux_9 { ++ pins = "gpio60"; ++ function = "qpic_pad7"; ++ bias-disable; ++ }; ++ ++ mux_10 { ++ pins = "gpio68"; ++ function = "qpic_pad8"; ++ bias-disable; ++ }; ++ + pullups { + pins = "gpio52", "gpio53", "gpio58", + "gpio59"; -+ function = "qpic"; + bias-pull-up; + }; + @@ -35,14 +96,13 @@ Signed-off-by: Ram Chandra Jangir + "gpio62", "gpio63", "gpio64", + "gpio65", "gpio66", "gpio67", + "gpio68", "gpio69"; -+ function = "qpic"; + bias-pull-down; + }; + }; }; blsp_dma: dma@7884000 { -@@ -159,5 +179,15 @@ +@@ -159,5 +239,15 @@ watchdog@b017000 { status = "ok"; }; @@ -60,7 +120,7 @@ Signed-off-by: Ram Chandra Jangir }; --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -609,5 +609,43 @@ +@@ -580,5 +580,43 @@ "legacy"; status = "disabled"; }; diff --git a/target/linux/ipq806x/patches-4.9/864-00-v3-1-2-dts-ipq4019-Fix-pinctrl-node-name.patch b/target/linux/ipq806x/patches-4.9/864-00-v3-1-2-dts-ipq4019-Fix-pinctrl-node-name.patch new file mode 100644 index 000000000..dbd5537f8 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/864-00-v3-1-2-dts-ipq4019-Fix-pinctrl-node-name.patch @@ -0,0 +1,44 @@ +From patchwork Mon Jul 3 07:47:12 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v3,1/2] dts: ipq4019: Fix pinctrl node name +From: Varadarajan Narayanan +X-Patchwork-Id: 9822099 +Message-Id: <1499068033-24000-2-git-send-email-varada@codeaurora.org> +To: andy.gross@linaro.org, david.brown@linaro.org, robh+dt@kernel.org, + mark.rutland@arm.com, linux@armlinux.org.uk, + linux-arm-msm@vger.kernel.org, + linux-soc@vger.kernel.org, devicetree@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org +Cc: Varadarajan Narayanan +Date: Mon, 3 Jul 2017 13:17:12 +0530 + +Signed-off-by: Varadarajan Narayanan +--- + arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi | 2 +- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi +@@ -40,7 +40,7 @@ + clock-frequency = <48000000>; + }; + +- pinctrl@0x01000000 { ++ pinctrl@1000000 { + serial_pins: serial_pinmux { + mux { + pins = "gpio60", "gpio61"; +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -149,7 +149,7 @@ + reg = <0x1800000 0x60000>; + }; + +- tlmm: pinctrl@0x01000000 { ++ tlmm: pinctrl@1000000 { + compatible = "qcom,ipq4019-pinctrl"; + reg = <0x01000000 0x300000>; + gpio-controller; diff --git a/target/linux/ipq806x/patches-4.9/864-00-v3-2-2-dts-ipq4019-Move-xo-and-timer-nodes-to-SoC-dtsi.patch b/target/linux/ipq806x/patches-4.9/864-00-v3-2-2-dts-ipq4019-Move-xo-and-timer-nodes-to-SoC-dtsi.patch new file mode 100644 index 000000000..3e2c39611 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/864-00-v3-2-2-dts-ipq4019-Move-xo-and-timer-nodes-to-SoC-dtsi.patch @@ -0,0 +1,78 @@ +From patchwork Mon Jul 3 07:47:13 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v3,2/2] dts: ipq4019: Move xo and timer nodes to SoC dtsi +From: Varadarajan Narayanan +X-Patchwork-Id: 9822107 +Message-Id: <1499068033-24000-3-git-send-email-varada@codeaurora.org> +To: andy.gross@linaro.org, david.brown@linaro.org, robh+dt@kernel.org, + mark.rutland@arm.com, linux@armlinux.org.uk, + linux-arm-msm@vger.kernel.org, + linux-soc@vger.kernel.org, devicetree@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org +Cc: Varadarajan Narayanan +Date: Mon, 3 Jul 2017 13:17:13 +0530 + +The node for xo and timer belong to the SoC DTS file. +Else, new board DT files may not inherit these nodes. + +Signed-off-by: Varadarajan Narayanan +--- + arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi | 19 ------------------- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 15 +++++++++++++++ + 2 files changed, 15 insertions(+), 19 deletions(-) + +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi +@@ -20,26 +20,7 @@ + model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK01.1"; + compatible = "qcom,ipq4019"; + +- clocks { +- xo: xo { +- compatible = "fixed-clock"; +- clock-frequency = <48000000>; +- #clock-cells = <0>; +- }; +- }; +- + soc { +- +- +- timer { +- compatible = "arm,armv7-timer"; +- interrupts = <1 2 0xf08>, +- <1 3 0xf08>, +- <1 4 0xf08>, +- <1 1 0xf08>; +- clock-frequency = <48000000>; +- }; +- + pinctrl@1000000 { + serial_pins: serial_pinmux { + mux { +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -126,6 +126,21 @@ + clock-frequency = <32768>; + #clock-cells = <0>; + }; ++ ++ xo: xo { ++ compatible = "fixed-clock"; ++ clock-frequency = <48000000>; ++ #clock-cells = <0>; ++ }; ++ }; ++ ++ timer { ++ compatible = "arm,armv7-timer"; ++ interrupts = <1 2 0xf08>, ++ <1 3 0xf08>, ++ <1 4 0xf08>, ++ <1 1 0xf08>; ++ clock-frequency = <48000000>; + }; + + soc { diff --git a/target/linux/ipq806x/patches-4.9/864-01-dts-ipq4019-ap-dk04-fix-pinctrl-node-name.patch b/target/linux/ipq806x/patches-4.9/864-01-dts-ipq4019-ap-dk04-fix-pinctrl-node-name.patch new file mode 100644 index 000000000..f2de6d618 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/864-01-dts-ipq4019-ap-dk04-fix-pinctrl-node-name.patch @@ -0,0 +1,11 @@ +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi +@@ -38,7 +38,7 @@ + clock-frequency = <48000000>; + }; + +- pinctrl@0x01000000 { ++ pinctrl@1000000 { + serial_0_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; diff --git a/target/linux/ipq806x/patches-4.9/864-02-dts-ipq4019-ap-dk04-remove-xo-and-timer-nodes.patch b/target/linux/ipq806x/patches-4.9/864-02-dts-ipq4019-ap-dk04-remove-xo-and-timer-nodes.patch new file mode 100644 index 000000000..dcbdb8d77 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/864-02-dts-ipq4019-ap-dk04-remove-xo-and-timer-nodes.patch @@ -0,0 +1,27 @@ +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi +@@ -20,24 +20,7 @@ + model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK04.1"; + compatible = "qcom,ipq4019"; + +- clocks { +- xo: xo { +- compatible = "fixed-clock"; +- clock-frequency = <48000000>; +- #clock-cells = <0>; +- }; +- }; +- + soc { +- timer { +- compatible = "arm,armv7-timer"; +- interrupts = <1 2 0xf08>, +- <1 3 0xf08>, +- <1 4 0xf08>, +- <1 1 0xf08>; +- clock-frequency = <48000000>; +- }; +- + pinctrl@1000000 { + serial_0_pins: serial_pinmux { + mux { diff --git a/target/linux/ipq806x/patches-4.9/864-03-dts-ipq4019-ap-dk01-add-tcsr-config-to-dtsi.patch b/target/linux/ipq806x/patches-4.9/864-03-dts-ipq4019-ap-dk01-add-tcsr-config-to-dtsi.patch new file mode 100644 index 000000000..9d11dc022 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/864-03-dts-ipq4019-ap-dk01-add-tcsr-config-to-dtsi.patch @@ -0,0 +1,42 @@ +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi +@@ -15,12 +15,39 @@ + */ + + #include "qcom-ipq4019.dtsi" ++#include + + / { + model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK01.1"; + compatible = "qcom,ipq4019"; + + soc { ++ tcsr@194b000 { ++ /* select hostmode */ ++ compatible = "qcom,tcsr"; ++ reg = <0x194b000 0x100>; ++ qcom,usb-hsphy-mode-select = ; ++ status = "ok"; ++ }; ++ ++ ess_tcsr@1953000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1953000 0x1000>; ++ qcom,ess-interface-select = ; ++ }; ++ ++ tcsr@1949000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1949000 0x100>; ++ qcom,wifi_glb_cfg = ; ++ }; ++ ++ tcsr@1957000 { ++ compatible = "qcom,tcsr"; ++ reg = <0x1957000 0x100>; ++ qcom,wifi_noc_memtype_m0_m2 = ; ++ }; ++ + pinctrl@1000000 { + serial_pins: serial_pinmux { + mux { diff --git a/target/linux/ipq806x/patches-4.9/864-04-dts-ipq4019-ap-dk01-add-network-nodes-to-dtsi.patch b/target/linux/ipq806x/patches-4.9/864-04-dts-ipq4019-ap-dk01-add-network-nodes-to-dtsi.patch new file mode 100644 index 000000000..02a102e37 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/864-04-dts-ipq4019-ap-dk01-add-network-nodes-to-dtsi.patch @@ -0,0 +1,32 @@ +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi +@@ -136,5 +136,29 @@ + usb2: usb2@60f8800 { + status = "ok"; + }; ++ ++ mdio@90000 { ++ status = "okay"; ++ }; ++ ++ ess-switch@c000000 { ++ status = "okay"; ++ }; ++ ++ ess-psgmii@98000 { ++ status = "okay"; ++ }; ++ ++ edma@c080000 { ++ status = "okay"; ++ }; ++ ++ wifi@a000000 { ++ status = "okay"; ++ }; ++ ++ wifi@a800000 { ++ status = "okay"; ++ }; + }; + }; diff --git a/target/linux/ipq806x/patches-4.9/864-05-dts-ipq4019-ap-dk01-remove-spi-chip-node-from-dtsi.patch b/target/linux/ipq806x/patches-4.9/864-05-dts-ipq4019-ap-dk01-remove-spi-chip-node-from-dtsi.patch new file mode 100644 index 000000000..0d4b80b30 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/864-05-dts-ipq4019-ap-dk01-remove-spi-chip-node-from-dtsi.patch @@ -0,0 +1,17 @@ +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi +@@ -89,14 +89,6 @@ + pinctrl-names = "default"; + status = "ok"; + cs-gpios = <&tlmm 54 0>; +- +- mx25l25635e@0 { +- #address-cells = <1>; +- #size-cells = <1>; +- reg = <0>; +- compatible = "mx25l25635e"; +- spi-max-frequency = <24000000>; +- }; + }; + + serial@78af000 { diff --git a/target/linux/ipq806x/patches-4.9/864-06-dts-ipq4019-fix-max-cpu-speed.patch b/target/linux/ipq806x/patches-4.9/864-06-dts-ipq4019-fix-max-cpu-speed.patch new file mode 100644 index 000000000..33f7f04f3 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/864-06-dts-ipq4019-fix-max-cpu-speed.patch @@ -0,0 +1,13 @@ +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -108,8 +108,8 @@ + opp-hz = /bits/ 64 <500000000>; + clock-latency-ns = <256000>; + }; +- opp@666000000 { +- opp-hz = /bits/ 64 <666000000>; ++ opp@716800000 { ++ opp-hz = /bits/ 64 <716800000>; + clock-latency-ns = <256000>; + }; + }; diff --git a/target/linux/ipq806x/patches-4.9/864-07-dts-ipq4019-ap-dk01.1-c1-add-spi-and-ram-nodes.patch b/target/linux/ipq806x/patches-4.9/864-07-dts-ipq4019-ap-dk01.1-c1-add-spi-and-ram-nodes.patch new file mode 100644 index 000000000..e9d262069 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/864-07-dts-ipq4019-ap-dk01.1-c1-add-spi-and-ram-nodes.patch @@ -0,0 +1,115 @@ +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts +@@ -19,4 +19,112 @@ + / { + model = "Qualcomm Technologies, Inc. IPQ40xx/AP-DK01.1-C1"; + ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x10000000>; ++ }; ++ ++ reserved-memory { ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; ++ ranges; ++ ++ apps_bl@87000000 { ++ reg = <0x87000000 0x400000>; ++ no-map; ++ }; ++ ++ sbl@87400000 { ++ reg = <0x87400000 0x100000>; ++ no-map; ++ }; ++ ++ cnss_debug@87500000 { ++ reg = <0x87500000 0x600000>; ++ no-map; ++ }; ++ ++ cpu_context_dump@87b00000 { ++ reg = <0x87b00000 0x080000>; ++ no-map; ++ }; ++ ++ tz_apps@87b80000 { ++ reg = <0x87b80000 0x280000>; ++ no-map; ++ }; ++ ++ smem@87e00000 { ++ reg = <0x87e00000 0x080000>; ++ no-map; ++ }; ++ ++ tz@87e80000 { ++ reg = <0x87e80000 0x180000>; ++ no-map; ++ }; ++ }; ++}; ++ ++&spi_0 { ++ mx25l25635f@0 { ++ compatible = "mx25l25635f", "jedec,spi-nor"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0>; ++ spi-max-frequency = <24000000>; ++ ++ SBL1@0 { ++ label = "SBL1"; ++ reg = <0x0 0x40000>; ++ read-only; ++ }; ++ MIBIB@40000 { ++ label = "MIBIB"; ++ reg = <0x40000 0x20000>; ++ read-only; ++ }; ++ QSEE@60000 { ++ label = "QSEE"; ++ reg = <0x60000 0x60000>; ++ read-only; ++ }; ++ CDT@c0000 { ++ label = "CDT"; ++ reg = <0xc0000 0x10000>; ++ read-only; ++ }; ++ DDRPARAMS@d0000 { ++ label = "DDRPARAMS"; ++ reg = <0xd0000 0x10000>; ++ read-only; ++ }; ++ APPSBLENV@e0000 { ++ label = "APPSBLENV"; ++ reg = <0xe0000 0x10000>; ++ read-only; ++ }; ++ APPSBL@f0000 { ++ label = "APPSBL"; ++ reg = <0xf0000 0x80000>; ++ read-only; ++ }; ++ ART@170000 { ++ label = "ART"; ++ reg = <0x170000 0x10000>; ++ read-only; ++ }; ++ kernel@180000 { ++ label = "kernel"; ++ reg = <0x180000 0x400000>; ++ }; ++ rootfs@580000 { ++ label = "rootfs"; ++ reg = <0x580000 0x1600000>; ++ }; ++ firmware@180000 { ++ label = "firmware"; ++ reg = <0x180000 0x1a00000>; ++ }; ++ }; + }; diff --git a/target/linux/ipq806x/patches-4.9/864-08-dts-ipq4019-ap-dk01.1-c1-add-compatible-string.patch b/target/linux/ipq806x/patches-4.9/864-08-dts-ipq4019-ap-dk01.1-c1-add-compatible-string.patch new file mode 100644 index 000000000..2d4ff3104 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/864-08-dts-ipq4019-ap-dk01.1-c1-add-compatible-string.patch @@ -0,0 +1,10 @@ +--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts ++++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts +@@ -18,6 +18,7 @@ + + / { + model = "Qualcomm Technologies, Inc. IPQ40xx/AP-DK01.1-C1"; ++ compatible = "qcom,ap-dk01.1-c1", "qcom,ap-dk01.2-c1", "qcom,ipq4019"; + + memory { + device_type = "memory"; diff --git a/target/linux/ipq806x/patches-4.9/900-mach-qcom-add-msm_pcie-driver.patch b/target/linux/ipq806x/patches-4.9/900-mach-qcom-add-msm_pcie-driver.patch new file mode 100644 index 000000000..be3a1af15 --- /dev/null +++ b/target/linux/ipq806x/patches-4.9/900-mach-qcom-add-msm_pcie-driver.patch @@ -0,0 +1,4883 @@ +From a0473413c8a10ea1884f2532b89e029b70e389d0 Mon Sep 17 00:00:00 2001 +From: Chen Minqiang +Date: Sat, 6 Jan 2018 13:59:06 +0800 +Subject: [PATCH 3/3] mach-qcom: add msm_pcie driver + +--- + Documentation/devicetree/bindings/pci/msm_pcie.txt | 164 ++ + arch/arm/mach-qcom/Kconfig | 8 + + arch/arm/mach-qcom/Makefile | 3 + + arch/arm/mach-qcom/include/mach/gpiomux.h | 216 ++ + arch/arm/mach-qcom/include/mach/msm_pcie.h | 134 ++ + arch/arm/mach-qcom/pcie.c | 2389 ++++++++++++++++++++ + arch/arm/mach-qcom/pcie.h | 329 +++ + arch/arm/mach-qcom/pcie_irq.c | 598 +++++ + arch/arm/mach-qcom/pcie_phy.c | 403 ++++ + arch/arm/mach-qcom/pcie_phy.h | 545 +++++ + 10 files changed, 4789 insertions(+) + create mode 100644 Documentation/devicetree/bindings/pci/msm_pcie.txt + create mode 100644 arch/arm/mach-qcom/include/mach/gpiomux.h + create mode 100644 arch/arm/mach-qcom/include/mach/msm_pcie.h + create mode 100644 arch/arm/mach-qcom/pcie.c + create mode 100644 arch/arm/mach-qcom/pcie.h + create mode 100644 arch/arm/mach-qcom/pcie_irq.c + create mode 100644 arch/arm/mach-qcom/pcie_phy.c + create mode 100644 arch/arm/mach-qcom/pcie_phy.h + +diff --git a/Documentation/devicetree/bindings/pci/msm_pcie.txt b/Documentation/devicetree/bindings/pci/msm_pcie.txt +new file mode 100644 +index 0000000..24a2be7 +--- /dev/null ++++ b/Documentation/devicetree/bindings/pci/msm_pcie.txt +@@ -0,0 +1,164 @@ ++MSM PCIe ++ ++MSM PCI express root complex ++ ++Required properties: ++ - compatible: should be "qcom,pci-msm" ++ - cell-index: defines root complex ID. ++ - #address-cells: Should provide a value of 0. ++ - reg: should contain PCIe register maps. ++ - reg-names: indicates various resources passed to driver by name. ++ Should be "parf", "phy", "dm_core", "elbi", "conf", "io", "bars". ++ These correspond to different modules within the PCIe core. ++ - interrupts: Should be in the format <0 1 2> and it is an index to the ++ interrupt-map that contains PCIe related interrupts. ++ - #interrupt-cells: Should provide a value of 1. ++ - #interrupt-map-mask: should provide a value of 0xffffffff. ++ - interrupt-map: Must create mapping for the number of interrupts ++ that are defined in above interrupts property. ++ For PCIe device node, it should define 12 mappings for ++ the corresponding PCIe interrupts supporting the specification. ++ - interrupt-names: indicates interrupts passed to driver by name. ++ Should be "int_msi", "int_a", "int_b", "int_c", "int_d", ++ "int_pls_pme", "int_pme_legacy", "int_pls_err", ++ "int_aer_legacy", "int_pls_link_up", ++ "int_pls_link_down", "int_bridge_flush_n" ++ These correspond to the standard PCIe specification to support ++ MSIs, virtual IRQ's (INT#), link state notifications. ++ - perst-gpio: PERST GPIO specified by PCIe spec. ++ - wake-gpio: WAKE GPIO specified by PCIe spec. ++ - -supply: phandle to the regulator device tree node. ++ Refer to the schematics for the corresponding voltage regulators. ++ vreg-1.8-supply: phandle to the analog supply for the PCIe controller. ++ vreg-3.3-supply: phandle to the analog supply for the PCIe controller. ++ vreg-0.9-supply: phandle to the analog supply for the PCIe controller. ++ ++Optional Properties: ++ - qcom,-voltage-level: specifies voltage levels for supply. ++ Should be specified in pairs (max, min, optimal), units uV. ++ - clkreq-gpio: CLKREQ GPIO specified by PCIe spec. ++ - pinctrl-names: The state name of the pin configuration. Only ++ support: "default" ++ - pinctrl-0: For details of pinctrl properties, please refer to: ++ "Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt" ++ - clocks: list of clock phandles ++ - clock-names: list of names of clock inputs. ++ Should be "pcie_0_pipe_clk", "pcie_0_ref_clk_src", ++ "pcie_0_aux_clk", "pcie_0_cfg_ahb_clk", ++ "pcie_0_mstr_axi_clk", "pcie_0_slv_axi_clk", ++ "pcie_0_ldo"; ++ - max-clock-frequency-hz: list of the maximum operating frequencies stored ++ in the same order of clock names; ++ - qcom,l0s-supported: L0s is supported. ++ - qcom,l1-supported: L1 is supported. ++ - qcom,l1ss-supported: L1 sub-states (L1ss) is supported. ++ - qcom,aux-clk-sync: The AUX clock is synchronous to the Core clock to ++ support L1ss. ++ - qcom,n-fts: The number of fast training sequences sent when the link state ++ is changed from L0s to L0. ++ - qcom,ep-wakeirq: The endpoint will issue wake signal when it is up, and the ++ root complex has the capability to enumerate the endpoint for this case. ++ - qcom,msi-gicm-addr: MSI address for GICv2m. ++ - qcom,msi-gicm-base: MSI IRQ base for GICv2m. ++ - qcom,ext-ref-clk: The reference clock is external. ++ - qcom,ep-latency: The time (unit: ms) to wait for the PCIe endpoint to become ++ stable after power on, before de-assert the PERST to the endpoint. ++ - qcom,tlp-rd-size: The max TLP read size (Calculation: 128 times 2 to the ++ tlp-rd-size power). ++ - Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for ++ below optional properties: ++ - qcom,msm-bus,name ++ - qcom,msm-bus,num-cases ++ - qcom,msm-bus,num-paths ++ - qcom,msm-bus,vectors-KBps ++ - qcom,scm-dev-id: If present then device id value is passed to secure channel ++ manager(scm) driver. scm driver uses this device id to restore PCIe ++ controller related security configuration after coming out of the controller ++ power collapse. ++ ++Example: ++ ++ pcie0: qcom,pcie@fc520000 { ++ compatible = "qcom,msm_pcie"; ++ cell-index = <0>; ++ #address-cells = <0>; ++ reg = <0xfc520000 0x2000>, ++ <0xfc526000 0x1000>, ++ <0xff000000 0x1000>, ++ <0xff001000 0x1000>, ++ <0xff100000 0x1000>, ++ <0xff200000 0x100000>, ++ <0xff300000 0xd00000>; ++ reg-names = "parf", "dm_core", "elbi", ++ "conf", "io", "bars"; ++ interrupt-parent = <&pcie0>; ++ interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12>; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0xffffffff>; ++ interrupt-map = <0 &intc 0 243 0 ++ 1 &intc 0 244 0 ++ 2 &intc 0 245 0 ++ 3 &intc 0 247 0 ++ 4 &intc 0 248 0 ++ 5 &intc 0 249 0 ++ 6 &intc 0 250 0 ++ 7 &intc 0 251 0 ++ 8 &intc 0 252 0 ++ 9 &intc 0 253 0 ++ 10 &intc 0 254 0 ++ 11 &intc 0 255 0>; ++ interrupt-names = "int_msi", "int_a", "int_b", "int_c", "int_d", ++ "int_pls_pme", "int_pme_legacy", "int_pls_err", ++ "int_aer_legacy", "int_pls_link_up", ++ "int_pls_link_down", "int_bridge_flush_n"; ++ perst-gpio = <&msmgpio 70 0>; ++ wake-gpio = <&msmgpio 69 0>; ++ clkreq-gpio = <&msmgpio 68 0>; ++ ++ gdsc-vdd-supply = <&gdsc_pcie_0>; ++ vreg-1.8-supply = <&pma8084_l12>; ++ vreg-0.9-supply = <&pma8084_l4>; ++ vreg-3.3-supply = <&wlan_vreg>; ++ ++ qcom,vreg-1.8-voltage-level = <1800000 1800000 1000>; ++ qcom,vreg-0.9-voltage-level = <950000 950000 24000>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie0_clkreq_default &pcie0_perst_default &pcie0_wake_default>; ++ ++ clocks = <&clock_gcc clk_gcc_pcie_0_pipe_clk>, ++ <&clock_rpm clk_ln_bb_clk>, ++ <&clock_gcc clk_gcc_pcie_0_aux_clk>, ++ <&clock_gcc clk_gcc_pcie_0_cfg_ahb_clk>, ++ <&clock_gcc clk_gcc_pcie_0_mstr_axi_clk>, ++ <&clock_gcc clk_gcc_pcie_0_slv_axi_clk>, ++ <&clock_gcc clk_pcie_0_phy_ldo>, ++ <&clock_gcc clk_gcc_pcie_phy_0_reset>; ++ ++ clock-names = "pcie_0_pipe_clk", "pcie_0_ref_clk_src", ++ "pcie_0_aux_clk", "pcie_0_cfg_ahb_clk", ++ "pcie_0_mstr_axi_clk", "pcie_0_slv_axi_clk", ++ "pcie_0_ldo"; ++ max-clock-frequency-hz = <125000000>, <0>, <1000000>, ++ <0>, <0>, <0>, <0>; ++ qcom,l0s-supported; ++ qcom,l1-supported; ++ qcom,l1ss-supported; ++ qcom,aux-clk-sync; ++ qcom,n-fts = <0x50>; ++ qcom,ep-wakeirq; ++ qcom,msi-gicm-addr = <0xf9040040>; ++ qcom,msi-gicm-base = <0x160>; ++ qcom,ext-ref-clk; ++ qcom,tlp-rd-size = <0x5>; ++ qcom,ep-latency = <100>; ++ ++ qcom,msm-bus,name = "pcie0"; ++ qcom,msm-bus,num-cases = <2>; ++ qcom,msm-bus,num-paths = <1>; ++ qcom,msm-bus,vectors-KBps = ++ <45 512 0 0>, ++ <45 512 500 800>; ++ ++ qcom,scm-dev-id = <11>; ++ }; +diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig +index b438cd0..38b4009 100644 +--- a/arch/arm/mach-qcom/Kconfig ++++ b/arch/arm/mach-qcom/Kconfig +@@ -10,6 +10,14 @@ menuconfig ARCH_QCOM + help + Support for Qualcomm's devicetree based systems. + ++config MSM_PCIE ++ bool "MSM PCIe Controller driver" ++ depends on PCI && PCI_MSI ++ select PCI_DOMAINS ++ help ++ Enables the PCIe functionality by configures PCIe core on ++ MSM chipset and by enabling the ARM PCI framework extension. ++ + if ARCH_QCOM + + config ARCH_MSM8X60 +diff --git a/arch/arm/mach-qcom/Makefile b/arch/arm/mach-qcom/Makefile +index 12878e9..542691b 100644 +--- a/arch/arm/mach-qcom/Makefile ++++ b/arch/arm/mach-qcom/Makefile +@@ -1 +1,4 @@ ++EXTRA_CFLAGS += -I$(srctree)/arch/arm/mach-qcom/include ++EXTRA_CFLAGS += -I$(srctree)/drivers/bus/msm_bus + obj-$(CONFIG_SMP) += platsmp.o ++obj-$(CONFIG_MSM_PCIE) += pcie.o pcie_irq.o pcie_phy.o +diff --git a/arch/arm/mach-qcom/include/mach/gpiomux.h b/arch/arm/mach-qcom/include/mach/gpiomux.h +new file mode 100644 +index 0000000..2278677 +--- /dev/null ++++ b/arch/arm/mach-qcom/include/mach/gpiomux.h +@@ -0,0 +1,216 @@ ++/* Copyright (c) 2010-2011,2013-2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_H ++#define __ARCH_ARM_MACH_MSM_GPIOMUX_H ++ ++#include ++#include ++ ++enum msm_gpiomux_setting { ++ GPIOMUX_ACTIVE = 0, ++ GPIOMUX_SUSPENDED, ++ GPIOMUX_NSETTINGS ++}; ++ ++enum gpiomux_drv { ++ GPIOMUX_DRV_2MA = 0, ++ GPIOMUX_DRV_4MA, ++ GPIOMUX_DRV_6MA, ++ GPIOMUX_DRV_8MA, ++ GPIOMUX_DRV_10MA, ++ GPIOMUX_DRV_12MA, ++ GPIOMUX_DRV_14MA, ++ GPIOMUX_DRV_16MA, ++}; ++ ++enum gpiomux_func { ++ GPIOMUX_FUNC_GPIO = 0, ++ GPIOMUX_FUNC_1, ++ GPIOMUX_FUNC_2, ++ GPIOMUX_FUNC_3, ++ GPIOMUX_FUNC_4, ++ GPIOMUX_FUNC_5, ++ GPIOMUX_FUNC_6, ++ GPIOMUX_FUNC_7, ++ GPIOMUX_FUNC_8, ++ GPIOMUX_FUNC_9, ++ GPIOMUX_FUNC_A, ++ GPIOMUX_FUNC_B, ++ GPIOMUX_FUNC_C, ++ GPIOMUX_FUNC_D, ++ GPIOMUX_FUNC_E, ++ GPIOMUX_FUNC_F, ++}; ++ ++enum gpiomux_pull { ++ GPIOMUX_PULL_NONE = 0, ++ GPIOMUX_PULL_DOWN, ++ GPIOMUX_PULL_KEEPER, ++ GPIOMUX_PULL_UP, ++}; ++ ++/* Direction settings are only meaningful when GPIOMUX_FUNC_GPIO is selected. ++ * This element is ignored for all other FUNC selections, as the output- ++ * enable pin is not under software control in those cases. See the SWI ++ * for your target for more details. ++ */ ++enum gpiomux_dir { ++ GPIOMUX_IN = 0, ++ GPIOMUX_OUT_HIGH, ++ GPIOMUX_OUT_LOW, ++}; ++ ++struct gpiomux_setting { ++ enum gpiomux_func func; ++ enum gpiomux_drv drv; ++ enum gpiomux_pull pull; ++ enum gpiomux_dir dir; ++}; ++ ++/** ++ * struct msm_gpiomux_config: gpiomux settings for one gpio line. ++ * ++ * A complete gpiomux config is the combination of a drive-strength, ++ * function, pull, and (sometimes) direction. For functions other than GPIO, ++ * the input/output setting is hard-wired according to the function. ++ * ++ * @gpio: The index number of the gpio being described. ++ * @settings: The settings to be installed, specifically: ++ * GPIOMUX_ACTIVE: The setting to be installed when the ++ * line is active, or its reference count is > 0. ++ * GPIOMUX_SUSPENDED: The setting to be installed when ++ * the line is suspended, or its reference count is 0. ++ */ ++struct msm_gpiomux_config { ++ unsigned gpio; ++ struct gpiomux_setting *settings[GPIOMUX_NSETTINGS]; ++}; ++ ++/** ++ * struct msm_gpiomux_configs: a collection of gpiomux configs. ++ * ++ * It is so common to manage blocks of gpiomux configs that the data structure ++ * for doing so has been standardized here as a convenience. ++ * ++ * @cfg: A pointer to the first config in an array of configs. ++ * @ncfg: The number of configs in the array. ++ */ ++struct msm_gpiomux_configs { ++ struct msm_gpiomux_config *cfg; ++ size_t ncfg; ++}; ++ ++/* Provide an enum and an API to write to misc TLMM registers */ ++enum msm_tlmm_misc_reg { ++ TLMM_ETM_MODE_REG = 0x2014, ++ TLMM_SDC2_HDRV_PULL_CTL = 0x2048, ++ TLMM_SPARE_REG = 0x2024, ++ TLMM_CDC_HDRV_CTL = 0x2054, ++ TLMM_CDC_HDRV_PULL_CTL = 0x2058, ++}; ++ ++#ifdef CONFIG_MSM_GPIOMUX ++ ++/* Before using gpiomux, initialize the subsystem by telling it how many ++ * gpios are going to be managed. Calling any other gpiomux functions before ++ * msm_gpiomux_init is unsupported. ++ */ ++int msm_gpiomux_init(size_t ngpio); ++ ++/* DT Variant of msm_gpiomux_init. This will look up the number of gpios from ++ * device tree rather than relying on NR_GPIO_IRQS ++ */ ++int msm_gpiomux_init_dt(void); ++ ++/* Install a block of gpiomux configurations in gpiomux. This is functionally ++ * identical to calling msm_gpiomux_write many times. ++ */ ++void msm_gpiomux_install(struct msm_gpiomux_config *configs, unsigned nconfigs); ++ ++/* Install a block of gpiomux configurations in gpiomux. Do not however write ++ * to hardware. Just store the settings to be retrieved at a later time ++ */ ++void msm_gpiomux_install_nowrite(struct msm_gpiomux_config *configs, ++ unsigned nconfigs); ++ ++/* Increment a gpio's reference count, possibly activating the line. */ ++int __must_check msm_gpiomux_get(unsigned gpio); ++ ++/* Decrement a gpio's reference count, possibly suspending the line. */ ++int msm_gpiomux_put(unsigned gpio); ++ ++/* Install a new setting in a gpio. To erase a slot, use NULL. ++ * The old setting that was overwritten can be passed back to the caller ++ * old_setting can be NULL if the caller is not interested in the previous ++ * setting ++ * If a previous setting was not available to return (NULL configuration) ++ * - the function returns 1 ++ * else function returns 0 ++ */ ++int msm_gpiomux_write(unsigned gpio, enum msm_gpiomux_setting which, ++ struct gpiomux_setting *setting, struct gpiomux_setting *old_setting); ++ ++/* Architecture-internal function for use by the framework only. ++ * This function can assume the following: ++ * - the gpio value has passed a bounds-check ++ * - the gpiomux spinlock has been obtained ++ * ++ * This function is not for public consumption. External users ++ * should use msm_gpiomux_write. ++ */ ++void __msm_gpiomux_write(unsigned gpio, struct gpiomux_setting val); ++ ++/* Functions that provide an API for drivers to read from and write to ++ * miscellaneous TLMM registers. ++ */ ++int msm_tlmm_misc_reg_read(enum msm_tlmm_misc_reg misc_reg); ++ ++void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg, int val); ++ ++#else ++static inline int msm_gpiomux_init(size_t ngpio) ++{ ++ return -ENOSYS; ++} ++ ++static inline void ++msm_gpiomux_install(struct msm_gpiomux_config *configs, unsigned nconfigs) {} ++ ++static inline int __must_check msm_gpiomux_get(unsigned gpio) ++{ ++ return -ENOSYS; ++} ++ ++static inline int msm_gpiomux_put(unsigned gpio) ++{ ++ return -ENOSYS; ++} ++ ++static inline int msm_gpiomux_write(unsigned gpio, ++ enum msm_gpiomux_setting which, struct gpiomux_setting *setting, ++ struct gpiomux_setting *old_setting) ++{ ++ return -ENOSYS; ++} ++ ++static inline int msm_tlmm_misc_reg_read(enum msm_tlmm_misc_reg misc_reg) ++{ ++ return -ENOSYS; ++} ++ ++static inline void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg, ++ int val) ++{ ++} ++ ++#endif ++#endif +diff --git a/arch/arm/mach-qcom/include/mach/msm_pcie.h b/arch/arm/mach-qcom/include/mach/msm_pcie.h +new file mode 100644 +index 0000000..c2fbdea +--- /dev/null ++++ b/arch/arm/mach-qcom/include/mach/msm_pcie.h +@@ -0,0 +1,134 @@ ++/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __ASM_ARCH_MSM_PCIE_H ++#define __ASM_ARCH_MSM_PCIE_H ++ ++#include ++#include ++ ++enum msm_pcie_config { ++ MSM_PCIE_CONFIG_INVALID = 0, ++ MSM_PCIE_CONFIG_NO_CFG_RESTORE = 0x1, ++ MSM_PCIE_CONFIG_LINKDOWN = 0x2, ++ MSM_PCIE_CONFIG_NO_RECOVERY = 0x4, ++}; ++ ++enum msm_pcie_pm_opt { ++ MSM_PCIE_SUSPEND, ++ MSM_PCIE_RESUME, ++ MSM_PCIE_REQ_EXIT_L1, ++}; ++ ++enum msm_pcie_event { ++ MSM_PCIE_EVENT_INVALID = 0, ++ MSM_PCIE_EVENT_LINKDOWN = 0x1, ++ MSM_PCIE_EVENT_LINKUP = 0x2, ++ MSM_PCIE_EVENT_WAKEUP = 0x4, ++ MSM_PCIE_EVENT_WAKE_RECOVERY = 0x8, ++ MSM_PCIE_EVENT_NO_ACCESS = 0x10, ++}; ++ ++enum msm_pcie_trigger { ++ MSM_PCIE_TRIGGER_CALLBACK, ++ MSM_PCIE_TRIGGER_COMPLETION, ++}; ++ ++struct msm_pcie_notify { ++ enum msm_pcie_event event; ++ void *user; ++ void *data; ++ u32 options; ++}; ++ ++struct msm_pcie_register_event { ++ u32 events; ++ void *user; ++ enum msm_pcie_trigger mode; ++ void (*callback)(struct msm_pcie_notify *notify); ++ struct msm_pcie_notify notify; ++ struct completion *completion; ++ u32 options; ++}; ++ ++/** ++ * msm_pcie_pm_control - control the power state of a PCIe link. ++ * @pm_opt: power management operation ++ * @busnr: bus number of PCIe endpoint ++ * @user: handle of the caller ++ * @data: private data from the caller ++ * @options: options for pm control ++ * ++ * This function gives PCIe endpoint device drivers the control to change ++ * the power state of a PCIe link for their device. ++ * ++ * Return: 0 on success, negative value on error ++ */ ++int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user, ++ void *data, u32 options); ++ ++/** ++ * msm_pcie_register_event - register an event with PCIe bus driver. ++ * @reg: event structure ++ * ++ * This function gives PCIe endpoint device drivers an option to register ++ * events with PCIe bus driver. ++ * ++ * Return: 0 on success, negative value on error ++ */ ++int msm_pcie_register_event(struct msm_pcie_register_event *reg); ++ ++/** ++ * msm_pcie_deregister_event - deregister an event with PCIe bus driver. ++ * @reg: event structure ++ * ++ * This function gives PCIe endpoint device drivers an option to deregister ++ * events with PCIe bus driver. ++ * ++ * Return: 0 on success, negative value on error ++ */ ++int msm_pcie_deregister_event(struct msm_pcie_register_event *reg); ++ ++/** ++ * msm_pcie_recover_config - recover config space. ++ * @dev: pci device structure ++ * ++ * This function recovers the config space of both RC and Endpoint. ++ * ++ * Return: 0 on success, negative value on error ++ */ ++int msm_pcie_recover_config(struct pci_dev *dev); ++ ++/** ++ * msm_pcie_shadow_control - control the shadowing of PCIe config space. ++ * @dev: pci device structure ++ * @enable: shadowing should be enabled or disabled ++ * ++ * This function gives PCIe endpoint device drivers the control to enable ++ * or disable the shadowing of PCIe config space. ++ * ++ * Return: 0 on success, negative value on error ++ */ ++int msm_pcie_shadow_control(struct pci_dev *dev, bool enable); ++ ++/* ++ * msm_pcie_access_control - access control to PCIe address range. ++ * @dev: pci device structure ++ * @enable: enable or disable the access ++ * ++ * This function gives PCIe endpoint device drivers the control to enable ++ * or disable the access to PCIe address range. ++ * ++ * Return: 0 on success, negative value on error ++ */ ++int msm_pcie_access_control(struct pci_dev *dev, bool enable); ++#endif +diff --git a/arch/arm/mach-qcom/pcie.c b/arch/arm/mach-qcom/pcie.c +new file mode 100644 +index 0000000..b471479 +--- /dev/null ++++ b/arch/arm/mach-qcom/pcie.c +@@ -0,0 +1,2389 @@ ++/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++/* ++ * MSM PCIe controller driver. ++ */ ++ ++#define pr_fmt(fmt) "%s: " fmt, __func__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++//#include ++#include ++#include ++#include ++#include "msm-bus.h" ++#include "msm-bus-board.h" ++ ++#include "pcie.h" ++ ++/* Root Complex Port vendor/device IDs */ ++#define PCIE_VENDOR_ID_RCP 0x17cb ++#ifdef CONFIG_ARCH_MDM9630 ++#define PCIE_DEVICE_ID_RCP 0x300 ++#else ++#define PCIE_DEVICE_ID_RCP 0x0101 ++#endif ++ ++#define PCIE20_PARF_SYS_CTRL 0x00 ++#define PCIE20_PARF_PM_CTRL 0x20 ++#define PCIE20_PARF_PM_STTS 0x24 ++#define PCIE20_PARF_PCS_DEEMPH 0x34 ++#define PCIE20_PARF_PCS_SWING 0x38 ++#define PCIE20_PARF_PHY_CTRL 0x40 ++#define PCIE20_PARF_PHY_REFCLK 0x4C ++#define PCIE20_PARF_CONFIG_BITS 0x50 ++#define PCIE20_PARF_DBI_BASE_ADDR 0x168 ++#define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT 0x178 ++#define PCIE20_PARF_Q2A_FLUSH 0x1AC ++#define PCIE20_PARF_LTSSM 0x1B0 ++ ++#define PCIE20_ELBI_VERSION 0x00 ++#define PCIE20_ELBI_SYS_CTRL 0x04 ++#define PCIE20_ELBI_SYS_STTS 0x08 ++ ++#define PCIE20_CAP 0x70 ++#define PCIE20_CAP_LINKCTRLSTATUS (PCIE20_CAP + 0x10) ++#define PCIE20_CAP_LINK_CAPABILITIES (PCIE20_CAP + 0xC) ++#define PCIE20_CAP_LINK_1 (PCIE20_CAP + 0x14) ++ ++#define PCIE20_COMMAND_STATUS 0x04 ++#define PCIE20_BUSNUMBERS 0x18 ++#define PCIE20_MEMORY_BASE_LIMIT 0x20 ++#define PCIE20_L1SUB_CONTROL1 0x158 ++#define PCIE20_EP_L1SUB_CTL1_OFFSET 0x30 ++#define PCIE20_DEVICE_CONTROL2_STATUS2 0x98 ++ ++#define PCIE20_ACK_F_ASPM_CTRL_REG 0x70C ++#define PCIE20_ACK_N_FTS 0xff00 ++#define PCIE20_GEN2_CTRL_REG 0x80C ++#define PCIE20_MISC_CONTROL_1_REG 0x8BC ++ ++#define PCIE20_PLR_IATU_VIEWPORT 0x900 ++#define PCIE20_PLR_IATU_CTRL1 0x904 ++#define PCIE20_PLR_IATU_CTRL2 0x908 ++#define PCIE20_PLR_IATU_LBAR 0x90C ++#define PCIE20_PLR_IATU_UBAR 0x910 ++#define PCIE20_PLR_IATU_LAR 0x914 ++#define PCIE20_PLR_IATU_LTAR 0x918 ++#define PCIE20_PLR_IATU_UTAR 0x91c ++ ++#define RD 0 ++#define WR 1 ++ ++/* Timing Delays */ ++#define PERST_PROPAGATION_DELAY_US_MIN 1000 ++#define PERST_PROPAGATION_DELAY_US_MAX 1005 ++#define REFCLK_STABILIZATION_DELAY_US_MIN 1000 ++#define REFCLK_STABILIZATION_DELAY_US_MAX 1500 ++#define LINK_RETRY_TIMEOUT_US_MIN 20000 ++#define LINK_RETRY_TIMEOUT_US_MAX 25000 ++#define LINK_UP_TIMEOUT_US_MIN 5000 ++#define LINK_UP_TIMEOUT_US_MAX 5100 ++#define LINK_UP_CHECK_MAX_COUNT 20 ++#define PHY_STABILIZATION_DELAY_US_MIN 995 ++#define PHY_STABILIZATION_DELAY_US_MAX 1005 ++#define REQ_EXIT_L1_DELAY_US 1 ++ ++#define PHY_READY_TIMEOUT_COUNT 10 ++#define XMLH_LINK_UP 0x400 ++#define MAX_LINK_RETRIES 5 ++#define MAX_BUS_NUM 3 ++#define MAX_PROP_SIZE 32 ++#define MAX_RC_NAME_LEN 15 ++ ++#define CMD_BME_VAL 0x4 ++#define DBI_RO_WR_EN 1 ++#define PCIE_CAP_CPL_TIMEOUT_DISABLE 0x10 ++#define LTSSM_EN (1 << 8) ++#define PCIE_CAP_ACTIVE_STATE_LINK_PM_SUPPORT_MASK 0xc00 ++#define PCIE_CAP_LINK1_VAL 0x2fd7f ++ ++/* Config Space Offsets */ ++#define BDF_OFFSET(bus, device, function) \ ++ ((bus << 24) | (device << 15) | (function << 8)) ++ ++/* debug mask sys interface */ ++static int msm_pcie_debug_mask; ++module_param_named(debug_mask, msm_pcie_debug_mask, ++ int, S_IRUGO | S_IWUSR | S_IWGRP); ++static atomic_t rc_removed; ++ ++/** ++ * PCIe driver state ++ */ ++struct pcie_drv_sta { ++ u32 rc_num; ++ u32 rc_expected; ++ u32 current_rc; ++ bool vreg_on; ++ struct mutex drv_lock; ++} pcie_drv; ++ ++/* msm pcie device data */ ++static struct msm_pcie_dev_t msm_pcie_dev[MAX_RC_NUM]; ++ ++/* regulators */ ++static struct msm_pcie_vreg_info_t msm_pcie_vreg_info[MSM_PCIE_MAX_VREG] = { ++ {NULL, "vreg-3.3", 0, 0, 0, false}, ++ {NULL, "vreg-1.8", 1800000, 1800000, 1000, true}, ++ {NULL, "vreg-0.9", 1000000, 1000000, 24000, true} ++}; ++ ++/* GPIOs */ ++static struct msm_pcie_gpio_info_t msm_pcie_gpio_info[MSM_PCIE_MAX_GPIO] = { ++ {"perst-gpio", 0, 1, 0, 0}, ++ {"wake-gpio", 0, 0, 0, 0}, ++ {"clkreq-gpio", 0, 0, 0, 0} ++}; ++ ++/* clocks */ ++static struct msm_pcie_clk_info_t ++ msm_pcie_clk_info[MAX_RC_NUM][MSM_PCIE_MAX_CLK] = { ++ { ++ {NULL, "pcie_0_cfg_ahb_clk", 0, true}, ++ {NULL, "pcie_0_mstr_axi_clk", 0, true}, ++ {NULL, "pcie_0_slv_axi_clk", 0, true}, ++ }, ++}; ++ ++/* RESETs */ ++static struct msm_pcie_rst_info_t msm_pcie_rst_info[MSM_PCIE_MAX_RESET] = { ++ {NULL, "pcie_rst_axi_m_ares"}, ++ {NULL, "pcie_rst_axi_s_ares"}, ++ {NULL, "pcie_rst_pipe_ares"}, ++ {NULL, "pcie_rst_axi_m_vmidmt_ares"}, ++ {NULL, "pcie_rst_axi_s_xpu_ares"}, ++ {NULL, "pcie_rst_parf_xpu_ares"}, ++ {NULL, "pcie_rst_phy_ares"}, ++ {NULL, "pcie_rst_axi_m_sticky_ares"}, ++ {NULL, "pcie_rst_pipe_sticky_ares"}, ++ {NULL, "pcie_rst_pwr_ares"}, ++ {NULL, "pcie_rst_ahb_res"}, ++ {NULL, "pcie_rst_phy_ahb_ares"} ++}; ++ ++/* resources */ ++static const struct msm_pcie_res_info_t msm_pcie_res_info[MSM_PCIE_MAX_RES] = { ++ {"parf", 0, 0}, ++ {"phy", 0, 0}, ++ {"dm_core", 0, 0}, ++ {"elbi", 0, 0}, ++ {"conf", 0, 0}, ++ {"io", 0, 0}, ++ {"bars", 0, 0} ++}; ++ ++/* irqs */ ++static const struct msm_pcie_irq_info_t msm_pcie_irq_info[MSM_PCIE_MAX_IRQ] = { ++ {"int_msi", 0}, ++ {"int_a", 0}, ++ {"int_b", 0}, ++ {"int_c", 0}, ++ {"int_d", 0}, ++ {"int_pls_pme", 0}, ++ {"int_pme_legacy", 0}, ++ {"int_pls_err", 0}, ++ {"int_aer_legacy", 0}, ++ {"int_pls_link_up", 0}, ++ {"int_pls_link_down", 0}, ++ {"int_bridge_flush_n", 0}, ++ {"int_wake", 0} ++}; ++ ++int msm_pcie_get_debug_mask(void) ++{ ++ return msm_pcie_debug_mask; ++} ++ ++bool msm_pcie_confirm_linkup(struct msm_pcie_dev_t *dev, ++ bool check_sw_stts, ++ bool check_ep) ++{ ++ u32 val; ++ ++ if (check_sw_stts && (dev->link_status != MSM_PCIE_LINK_ENABLED)) { ++ PCIE_DBG(dev, "PCIe: The link of RC %d is not enabled.\n", ++ dev->rc_idx); ++ return false; ++ } ++ ++ if (!(readl_relaxed(dev->dm_core + 0x80) & BIT(29))) { ++ PCIE_DBG(dev, "PCIe: The link of RC %d is not up.\n", ++ dev->rc_idx); ++ return false; ++ } ++ ++ val = readl_relaxed(dev->dm_core); ++ PCIE_DBG(dev, "PCIe: device ID and vender ID of RC %d are 0x%x.\n", ++ dev->rc_idx, val); ++ if (val == PCIE_LINK_DOWN) { ++ PCIE_ERR(dev, ++ "PCIe: The link of RC %d is not really up; device ID and vender ID of RC %d are 0x%x.\n", ++ dev->rc_idx, dev->rc_idx, val); ++ return false; ++ } ++ ++ if (check_ep) { ++ val = readl_relaxed(dev->conf); ++ PCIE_DBG(dev, ++ "PCIe: device ID and vender ID of EP of RC %d are 0x%x.\n", ++ dev->rc_idx, val); ++ if (val == PCIE_LINK_DOWN) { ++ PCIE_ERR(dev, ++ "PCIe: The link of RC %d is not really up; device ID and vender ID of EP of RC %d are 0x%x.\n", ++ dev->rc_idx, dev->rc_idx, val); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++void msm_pcie_cfg_recover(struct msm_pcie_dev_t *dev, bool rc) ++{ ++ int i; ++ u32 val = 0; ++ u32 *shadow; ++ void *cfg; ++ ++ if (rc) { ++ shadow = dev->rc_shadow; ++ cfg = dev->dm_core; ++ } else { ++ shadow = dev->ep_shadow; ++ cfg = dev->conf; ++ } ++ ++ for (i = PCIE_CONF_SPACE_DW - 1; i >= 0; i--) { ++ val = shadow[i]; ++ if (val != PCIE_CLEAR) { ++ PCIE_DBG3(dev, "PCIe: before recovery:cfg 0x%x:0x%x\n", ++ i * 4, readl_relaxed(cfg + i * 4)); ++ PCIE_DBG3(dev, "PCIe: shadow_dw[%d]:cfg 0x%x:0x%x\n", ++ i, i * 4, val); ++ writel_relaxed(val, cfg + i * 4); ++ wmb(); ++ PCIE_DBG3(dev, "PCIe: after recovery:cfg 0x%x:0x%x\n\n", ++ i * 4, readl_relaxed(cfg + i * 4)); ++ } ++ } ++ ++ readl_relaxed(dev->elbi); ++} ++ ++static void msm_pcie_write_mask(void __iomem *addr, ++ uint32_t clear_mask, uint32_t set_mask) ++{ ++ uint32_t val; ++ ++ val = (readl_relaxed(addr) & ~clear_mask) | set_mask; ++ writel_relaxed(val, addr); ++ wmb(); /* ensure data is written to hardware register */ ++} ++ ++static int msm_pcie_is_link_up(struct msm_pcie_dev_t *dev) ++{ ++ return readl_relaxed(dev->dm_core + ++ PCIE20_CAP_LINKCTRLSTATUS) & BIT(29); ++} ++ ++static inline int msm_pcie_oper_conf(struct pci_bus *bus, u32 devfn, int oper, ++ int where, int size, u32 *val) ++{ ++ uint32_t word_offset, byte_offset, mask; ++ uint32_t rd_val, wr_val; ++ struct msm_pcie_dev_t *dev; ++ void __iomem *config_base; ++ bool rc = false; ++ u32 rc_idx; ++ int rv = 0; ++ ++ dev = ((struct msm_pcie_dev_t *) ++ (((struct pci_sys_data *)bus->sysdata)->private_data)); ++ ++ if (!dev) { ++ pr_err("PCIe: No device found for this bus.\n"); ++ *val = ~0; ++ rv = PCIBIOS_DEVICE_NOT_FOUND; ++ goto out; ++ } ++ ++ /* Do the bus->number based access control since we don't support ++ ECAM mechanism */ ++ ++ switch (bus->number) { ++ case 0: ++ rc = true; ++ case 1: ++ rc_idx = dev->rc_idx; ++ break; ++ default: ++ PCIE_ERR(dev, "PCIe: unsupported bus number:%d\n", bus->number); ++ *val = ~0; ++ rv = PCIBIOS_DEVICE_NOT_FOUND; ++ goto out; ++ } ++ ++ if ((bus->number > MAX_BUS_NUM) || (devfn != 0)) { ++ PCIE_DBG3(dev, "RC%d invalid %s - bus %d devfn %d\n", rc_idx, ++ (oper == RD) ? "rd" : "wr", bus->number, devfn); ++ *val = ~0; ++ rv = PCIBIOS_DEVICE_NOT_FOUND; ++ goto out; ++ } ++ ++ spin_lock_irqsave(&dev->cfg_lock, dev->irqsave_flags); ++ ++ if (!dev->cfg_access) { ++ PCIE_DBG3(dev, ++ "Access denied for RC%d %d:0x%02x + 0x%04x[%d]\n", ++ rc_idx, bus->number, devfn, where, size); ++ *val = ~0; ++ rv = PCIBIOS_DEVICE_NOT_FOUND; ++ goto unlock; ++ } ++ ++ if (dev->link_status != MSM_PCIE_LINK_ENABLED) { ++ PCIE_DBG3(dev, ++ "Access to RC%d %d:0x%02x + 0x%04x[%d] is denied because link is down\n", ++ rc_idx, bus->number, devfn, where, size); ++ *val = ~0; ++ rv = PCIBIOS_DEVICE_NOT_FOUND; ++ goto unlock; ++ } ++ ++ /* check if the link is up for endpoint */ ++ if (!rc && !msm_pcie_is_link_up(dev)) { ++ PCIE_ERR(dev, ++ "PCIe: RC%d %s fail, link down - bus %d devfn %d\n", ++ rc_idx, (oper == RD) ? "rd" : "wr", ++ bus->number, devfn); ++ *val = ~0; ++ rv = PCIBIOS_DEVICE_NOT_FOUND; ++ goto unlock; ++ } ++ ++ word_offset = where & ~0x3; ++ byte_offset = where & 0x3; ++ mask = (~0 >> (8 * (4 - size))) << (8 * byte_offset); ++ ++ config_base = rc ? dev->dm_core : dev->conf; ++ rd_val = readl_relaxed(config_base + word_offset); ++ ++ if (oper == RD) { ++ *val = ((rd_val & mask) >> (8 * byte_offset)); ++ PCIE_DBG3(dev, ++ "RC%d %d:0x%02x + 0x%04x[%d] -> 0x%08x; rd 0x%08x\n", ++ rc_idx, bus->number, devfn, where, size, *val, rd_val); ++ } else { ++ wr_val = (rd_val & ~mask) | ++ ((*val << (8 * byte_offset)) & mask); ++ writel_relaxed(wr_val, config_base + word_offset); ++ wmb(); /* ensure config data is written to hardware register */ ++ readl_relaxed(dev->elbi); ++ ++ if (rd_val == PCIE_LINK_DOWN) { ++ PCIE_ERR(dev, ++ "Read of RC%d %d:0x%02x + 0x%04x[%d] is all FFs\n", ++ rc_idx, bus->number, devfn, where, size); ++ } else if (dev->shadow_en) { ++ if (rc) ++ dev->rc_shadow[word_offset / 4] = wr_val; ++ else ++ dev->ep_shadow[word_offset / 4] = wr_val; ++ } ++ ++ PCIE_DBG3(dev, ++ "RC%d %d:0x%02x + 0x%04x[%d] <- 0x%08x; rd 0x%08x val 0x%08x\n", ++ rc_idx, bus->number, devfn, where, size, ++ wr_val, rd_val, *val); ++ } ++ ++unlock: ++ spin_unlock_irqrestore(&dev->cfg_lock, dev->irqsave_flags); ++out: ++ return rv; ++} ++ ++static int msm_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, ++ int size, u32 *val) ++{ ++ int ret = msm_pcie_oper_conf(bus, devfn, RD, where, size, val); ++ ++ if ((bus->number == 0) && (where == PCI_CLASS_REVISION)) { ++ *val = (*val & 0xff) | (PCI_CLASS_BRIDGE_PCI << 16); ++ pr_debug("change class for RC:0x%x\n", *val); ++ } ++ ++ return ret; ++} ++ ++static int msm_pcie_wr_conf(struct pci_bus *bus, u32 devfn, ++ int where, int size, u32 val) ++{ ++ return msm_pcie_oper_conf(bus, devfn, WR, where, size, &val); ++} ++ ++static struct pci_ops msm_pcie_ops = { ++ .read = msm_pcie_rd_conf, ++ .write = msm_pcie_wr_conf, ++}; ++ ++static int msm_pcie_gpio_init(struct msm_pcie_dev_t *dev) ++{ ++ int rc = 0, i; ++ struct msm_pcie_gpio_info_t *info; ++ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++ for (i = 0; i < dev->gpio_n; i++) { ++ info = &dev->gpio[i]; ++ ++ if (!info->num) ++ continue; ++ ++ rc = gpio_request(info->num, info->name); ++ if (rc) { ++ PCIE_ERR(dev, "PCIe: RC%d can't get gpio %s; %d\n", ++ dev->rc_idx, info->name, rc); ++ break; ++ } ++ ++ if (info->out) ++ rc = gpio_direction_output(info->num, info->init); ++ else ++ rc = gpio_direction_input(info->num); ++ if (rc) { ++ PCIE_ERR(dev, ++ "PCIe: RC%d can't set direction for GPIO %s:%d\n", ++ dev->rc_idx, info->name, rc); ++ gpio_free(info->num); ++ break; ++ } ++ } ++ ++ if (rc) ++ while (i--) ++ gpio_free(dev->gpio[i].num); ++ ++ return rc; ++} ++ ++static void msm_pcie_gpio_deinit(struct msm_pcie_dev_t *dev) ++{ ++ int i; ++ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++ for (i = 0; i < dev->gpio_n; i++) ++ gpio_free(dev->gpio[i].num); ++} ++ ++int msm_pcie_vreg_init(struct msm_pcie_dev_t *dev) ++{ ++ int i, rc = 0; ++ struct regulator *vreg; ++ struct msm_pcie_vreg_info_t *info; ++ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++ for (i = 0; i < MSM_PCIE_MAX_VREG; i++) { ++ info = &dev->vreg[i]; ++ vreg = info->hdl; ++ ++ if (!vreg) ++ continue; ++ ++ PCIE_DBG2(dev, "RC%d Vreg %s is being enabled\n", ++ dev->rc_idx, info->name); ++ if (info->max_v) { ++ rc = regulator_set_voltage(vreg, ++ info->min_v, info->max_v); ++ if (rc) { ++ PCIE_ERR(dev, ++ "PCIe: RC%d can't set voltage for %s: %d\n", ++ dev->rc_idx, info->name, rc); ++ break; ++ } ++ } ++ ++ if (info->opt_mode) { ++ rc = regulator_set_mode(vreg, info->opt_mode); ++ if (rc < 0) { ++ PCIE_ERR(dev, ++ "PCIe: RC%d can't set mode for %s: %d\n", ++ dev->rc_idx, info->name, rc); ++ break; ++ } ++ } ++ ++ rc = regulator_enable(vreg); ++ if (rc) { ++ PCIE_ERR(dev, ++ "PCIe: RC%d can't enable regulator %s: %d\n", ++ dev->rc_idx, info->name, rc); ++ break; ++ } ++ } ++ ++ if (rc) ++ while (i--) { ++ struct regulator *hdl = dev->vreg[i].hdl; ++ if (hdl) ++ regulator_disable(hdl); ++ } ++ ++ return rc; ++} ++ ++static void msm_pcie_vreg_deinit(struct msm_pcie_dev_t *dev) ++{ ++ int i; ++ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++ for (i = MSM_PCIE_MAX_VREG - 1; i >= 0; i--) { ++ if (dev->vreg[i].hdl) { ++ PCIE_DBG(dev, "Vreg %s is being disabled\n", ++ dev->vreg[i].name); ++ regulator_disable(dev->vreg[i].hdl); ++ } ++ } ++} ++ ++static int msm_pcie_clk_init(struct msm_pcie_dev_t *dev) ++{ ++ int i, rc = 0; ++ struct msm_pcie_clk_info_t *info; ++ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++ rc = regulator_enable(dev->gdsc); ++ ++ if (rc) { ++ PCIE_ERR(dev, "PCIe: fail to enable GDSC for RC%d (%s)\n", ++ dev->rc_idx, dev->pdev->name); ++ return rc; ++ } ++ ++ if (dev->bus_client) { ++ rc = msm_bus_scale_client_update_request(dev->bus_client, 1); ++ if (rc) { ++ PCIE_ERR(dev, ++ "PCIe: fail to set bus bandwidth for RC%d:%d.\n", ++ dev->rc_idx, rc); ++ return rc; ++ } else { ++ PCIE_DBG2(dev, ++ "PCIe: set bus bandwidth for RC%d.\n", ++ dev->rc_idx); ++ } ++ } ++ ++ for (i = 0; i < MSM_PCIE_MAX_CLK; i++) { ++ info = &dev->clk[i]; ++ ++ if (!info->hdl) ++ continue; ++ ++ if (info->freq) { ++ rc = clk_set_rate(info->hdl, info->freq); ++ if (rc) { ++ PCIE_ERR(dev, ++ "PCIe: RC%d can't set rate for clk %s: %d.\n", ++ dev->rc_idx, info->name, rc); ++ break; ++ } else { ++ PCIE_DBG2(dev, ++ "PCIe: RC%d set rate for clk %s.\n", ++ dev->rc_idx, info->name); ++ } ++ } ++ ++ rc = clk_prepare_enable(info->hdl); ++ ++ if (rc) ++ PCIE_ERR(dev, "PCIe: RC%d failed to enable clk %s\n", ++ dev->rc_idx, info->name); ++ else ++ PCIE_DBG2(dev, "enable clk %s for RC%d.\n", ++ info->name, dev->rc_idx); ++ } ++ ++ if (rc) { ++ PCIE_DBG(dev, "RC%d disable clocks for error handling.\n", ++ dev->rc_idx); ++ while (i--) { ++ struct clk *hdl = dev->clk[i].hdl; ++ if (hdl) ++ clk_disable_unprepare(hdl); ++ } ++ ++ regulator_disable(dev->gdsc); ++ } ++ ++ return rc; ++} ++ ++static void msm_pcie_clk_deinit(struct msm_pcie_dev_t *dev) ++{ ++ int i; ++ int rc; ++ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++ for (i = 0; i < MSM_PCIE_MAX_CLK; i++) ++ if (dev->clk[i].hdl) ++ clk_disable_unprepare(dev->clk[i].hdl); ++ ++ if (dev->bus_client) { ++ rc = msm_bus_scale_client_update_request(dev->bus_client, 0); ++ if (rc) ++ PCIE_ERR(dev, ++ "PCIe: fail to relinquish bus bandwidth for RC%d:%d.\n", ++ dev->rc_idx, rc); ++ else ++ PCIE_DBG(dev, ++ "PCIe: relinquish bus bandwidth for RC%d.\n", ++ dev->rc_idx); ++ } ++ ++ regulator_disable(dev->gdsc); ++} ++ ++static void msm_pcie_controller_reset(struct msm_pcie_dev_t *dev) ++{ ++ /* Assert pcie_pipe_ares */ ++ reset_control_assert(dev->rst[MSM_PCIE_AXI_M_ARES].hdl); ++ reset_control_assert(dev->rst[MSM_PCIE_AXI_S_ARES].hdl); ++ usleep_range(10000, 12000); /* wait 12ms */ ++ ++ reset_control_assert(dev->rst[MSM_PCIE_PIPE_ARES].hdl); ++ reset_control_assert(dev->rst[MSM_PCIE_PIPE_STICKY_ARES].hdl); ++ reset_control_assert(dev->rst[MSM_PCIE_PHY_ARES].hdl); ++ reset_control_assert(dev->rst[MSM_PCIE_PHY_AHB_ARES].hdl); ++ usleep_range(10000, 12000); /* wait 12ms */ ++ ++ reset_control_assert(dev->rst[MSM_PCIE_AXI_M_STICKY_ARES].hdl); ++ reset_control_assert(dev->rst[MSM_PCIE_PWR_ARES].hdl); ++ reset_control_assert(dev->rst[MSM_PCIE_AHB_ARES].hdl); ++ usleep_range(10000, 12000); /* wait 12ms */ ++ ++ reset_control_deassert(dev->rst[MSM_PCIE_PHY_AHB_ARES].hdl); ++ reset_control_deassert(dev->rst[MSM_PCIE_PHY_ARES].hdl); ++ reset_control_deassert(dev->rst[MSM_PCIE_PIPE_ARES].hdl); ++ reset_control_deassert(dev->rst[MSM_PCIE_PIPE_STICKY_ARES].hdl); ++ usleep_range(10000, 12000); /* wait 12ms */ ++ ++ reset_control_deassert(dev->rst[MSM_PCIE_AXI_M_ARES].hdl); ++ reset_control_deassert(dev->rst[MSM_PCIE_AXI_M_STICKY_ARES].hdl); ++ reset_control_deassert(dev->rst[MSM_PCIE_AXI_S_ARES].hdl); ++ reset_control_deassert(dev->rst[MSM_PCIE_PWR_ARES].hdl); ++ reset_control_deassert(dev->rst[MSM_PCIE_AHB_ARES].hdl); ++ usleep_range(10000, 12000); /* wait 12ms */ ++ wmb(); /* ensure data is written to hw register */ ++} ++ ++static void msm_pcie_config_controller(struct msm_pcie_dev_t *dev) ++{ ++ struct resource *axi_conf = dev->res[MSM_PCIE_RES_CONF].resource; ++ u32 dev_conf, upper, lower, limit; ++ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++ if (IS_ENABLED(CONFIG_ARM_LPAE)) { ++ lower = PCIE_LOWER_ADDR(axi_conf->start); ++ upper = PCIE_UPPER_ADDR(axi_conf->start); ++ limit = PCIE_LOWER_ADDR(axi_conf->end); ++ } else { ++ lower = axi_conf->start; ++ upper = 0; ++ limit = axi_conf->end; ++ } ++ ++ dev_conf = BDF_OFFSET(1, 0, 0); ++ ++ if (dev->shadow_en) { ++ dev->rc_shadow[PCIE20_PLR_IATU_VIEWPORT / 4] = 0; ++ dev->rc_shadow[PCIE20_PLR_IATU_CTRL1 / 4] = 4; ++ dev->rc_shadow[PCIE20_PLR_IATU_LBAR / 4] = lower; ++ dev->rc_shadow[PCIE20_PLR_IATU_UBAR / 4] = upper; ++ dev->rc_shadow[PCIE20_PLR_IATU_LAR / 4] = limit; ++ dev->rc_shadow[PCIE20_PLR_IATU_LTAR / 4] = dev_conf; ++ dev->rc_shadow[PCIE20_PLR_IATU_UTAR / 4] = 0; ++ dev->rc_shadow[PCIE20_PLR_IATU_CTRL2 / 4] = BIT(31); ++ } ++ ++ /* ++ * program and enable address translation region 0 (device config ++ * address space); region type config; ++ * axi config address range to device config address range ++ */ ++ writel_relaxed(0, dev->dm_core + PCIE20_PLR_IATU_VIEWPORT); ++ /* ensure that hardware locks the region before programming it */ ++ wmb(); ++ ++ writel_relaxed(4, dev->dm_core + PCIE20_PLR_IATU_CTRL1); ++ writel_relaxed(lower, dev->dm_core + PCIE20_PLR_IATU_LBAR); ++ writel_relaxed(upper, dev->dm_core + PCIE20_PLR_IATU_UBAR); ++ writel_relaxed(limit, dev->dm_core + PCIE20_PLR_IATU_LAR); ++ writel_relaxed(dev_conf, dev->dm_core + PCIE20_PLR_IATU_LTAR); ++ writel_relaxed(0, dev->dm_core + PCIE20_PLR_IATU_UTAR); ++ writel_relaxed(BIT(31), dev->dm_core + PCIE20_PLR_IATU_CTRL2); ++ /* ensure that hardware registers the configuration */ ++ wmb(); ++ PCIE_DBG2(dev, "PCIE20_PLR_IATU_VIEWPORT:0x%x\n", ++ readl_relaxed(dev->dm_core + PCIE20_PLR_IATU_VIEWPORT)); ++ PCIE_DBG2(dev, "PCIE20_PLR_IATU_CTRL1:0x%x\n", ++ readl_relaxed(dev->dm_core + PCIE20_PLR_IATU_CTRL1)); ++ PCIE_DBG2(dev, "PCIE20_PLR_IATU_LBAR:0x%x\n", ++ readl_relaxed(dev->dm_core + PCIE20_PLR_IATU_LBAR)); ++ PCIE_DBG2(dev, "PCIE20_PLR_IATU_UBAR:0x%x\n", ++ readl_relaxed(dev->dm_core + PCIE20_PLR_IATU_UBAR)); ++ PCIE_DBG2(dev, "PCIE20_PLR_IATU_LAR:0x%x\n", ++ readl_relaxed(dev->dm_core + PCIE20_PLR_IATU_LAR)); ++ PCIE_DBG2(dev, "PCIE20_PLR_IATU_LTAR:0x%x\n", ++ readl_relaxed(dev->dm_core + PCIE20_PLR_IATU_LTAR)); ++ PCIE_DBG2(dev, "PCIE20_PLR_IATU_UTAR:0x%x\n", ++ readl_relaxed(dev->dm_core + PCIE20_PLR_IATU_UTAR)); ++ PCIE_DBG2(dev, "PCIE20_PLR_IATU_CTRL2:0x%x\n", ++ readl_relaxed(dev->dm_core + PCIE20_PLR_IATU_CTRL2)); ++ ++ /* configure N_FTS */ ++ PCIE_DBG2(dev, "Original PCIE20_ACK_F_ASPM_CTRL_REG:0x%x\n", ++ readl_relaxed(dev->dm_core + PCIE20_ACK_F_ASPM_CTRL_REG)); ++ if (!dev->n_fts) ++ msm_pcie_write_mask(dev->dm_core + PCIE20_ACK_F_ASPM_CTRL_REG, ++ 0, BIT(15)); ++ else ++ msm_pcie_write_mask(dev->dm_core + PCIE20_ACK_F_ASPM_CTRL_REG, ++ PCIE20_ACK_N_FTS, ++ dev->n_fts << 8); ++ readl_relaxed(dev->elbi); ++ ++ if (dev->shadow_en) ++ dev->rc_shadow[PCIE20_ACK_F_ASPM_CTRL_REG / 4] = ++ readl_relaxed(dev->dm_core + ++ PCIE20_ACK_F_ASPM_CTRL_REG); ++ ++ PCIE_DBG2(dev, "Updated PCIE20_ACK_F_ASPM_CTRL_REG:0x%x\n", ++ readl_relaxed(dev->dm_core + PCIE20_ACK_F_ASPM_CTRL_REG)); ++} ++ ++static void msm_pcie_config_l1ss(struct msm_pcie_dev_t *dev) ++{ ++ u32 offset = 0; ++ ++ if (!dev->rc_idx) ++ offset = PCIE20_EP_L1SUB_CTL1_OFFSET; ++ ++ /* Enable the AUX Clock and the Core Clk to be synchronous for L1SS*/ ++ if (!dev->aux_clk_sync) ++ msm_pcie_write_mask(dev->parf + ++ PCIE20_PARF_SYS_CTRL, BIT(3), 0); ++ ++ /* Enable L1SS on RC */ ++ msm_pcie_write_mask(dev->dm_core + PCIE20_CAP_LINKCTRLSTATUS, 0, ++ BIT(1)|BIT(0)); ++ msm_pcie_write_mask(dev->dm_core + PCIE20_L1SUB_CONTROL1, 0, ++ BIT(3)|BIT(2)|BIT(1)|BIT(0)); ++ msm_pcie_write_mask(dev->dm_core + PCIE20_DEVICE_CONTROL2_STATUS2, 0, ++ BIT(10)); ++ readl_relaxed(dev->elbi); ++ if (dev->shadow_en) { ++ dev->rc_shadow[PCIE20_CAP_LINKCTRLSTATUS / 4] = ++ readl_relaxed(dev->dm_core + PCIE20_CAP_LINKCTRLSTATUS); ++ dev->rc_shadow[PCIE20_L1SUB_CONTROL1 / 4] = ++ readl_relaxed(dev->dm_core + PCIE20_L1SUB_CONTROL1); ++ dev->rc_shadow[PCIE20_DEVICE_CONTROL2_STATUS2 / 4] = ++ readl_relaxed(dev->dm_core + ++ PCIE20_DEVICE_CONTROL2_STATUS2); ++ } ++ PCIE_DBG2(dev, "RC's CAP_LINKCTRLSTATUS:0x%x\n", ++ readl_relaxed(dev->dm_core + PCIE20_CAP_LINKCTRLSTATUS)); ++ PCIE_DBG2(dev, "RC's L1SUB_CONTROL1:0x%x\n", ++ readl_relaxed(dev->dm_core + PCIE20_L1SUB_CONTROL1)); ++ PCIE_DBG2(dev, "RC's DEVICE_CONTROL2_STATUS2:0x%x\n", ++ readl_relaxed(dev->dm_core + PCIE20_DEVICE_CONTROL2_STATUS2)); ++ ++ /* Enable L1SS on EP */ ++ msm_pcie_write_mask(dev->conf + PCIE20_CAP_LINKCTRLSTATUS, 0, ++ BIT(1)|BIT(0)); ++ msm_pcie_write_mask(dev->conf + PCIE20_L1SUB_CONTROL1 + ++ offset, 0, ++ BIT(3)|BIT(2)|BIT(1)|BIT(0)); ++ msm_pcie_write_mask(dev->conf + PCIE20_DEVICE_CONTROL2_STATUS2, 0, ++ BIT(10)); ++ readl_relaxed(dev->elbi); ++ if (dev->shadow_en) { ++ dev->ep_shadow[PCIE20_CAP_LINKCTRLSTATUS / 4] = ++ readl_relaxed(dev->conf + ++ PCIE20_CAP_LINKCTRLSTATUS); ++ dev->ep_shadow[PCIE20_L1SUB_CONTROL1 / 4 + offset / 4] = ++ readl_relaxed(dev->conf + ++ PCIE20_L1SUB_CONTROL1 + offset); ++ dev->ep_shadow[PCIE20_DEVICE_CONTROL2_STATUS2 / 4] = ++ readl_relaxed(dev->conf + ++ PCIE20_DEVICE_CONTROL2_STATUS2); ++ } ++ PCIE_DBG2(dev, "EP's CAP_LINKCTRLSTATUS:0x%x\n", ++ readl_relaxed(dev->conf + PCIE20_CAP_LINKCTRLSTATUS)); ++ PCIE_DBG2(dev, "EP's L1SUB_CONTROL1:0x%x\n", ++ readl_relaxed(dev->conf + PCIE20_L1SUB_CONTROL1 + ++ offset)); ++ PCIE_DBG2(dev, "EP's DEVICE_CONTROL2_STATUS2:0x%x\n", ++ readl_relaxed(dev->conf + PCIE20_DEVICE_CONTROL2_STATUS2)); ++} ++ ++static int msm_pcie_get_resources(struct msm_pcie_dev_t *dev, ++ struct platform_device *pdev) ++{ ++ int i, len, cnt, ret = 0; ++ struct msm_pcie_vreg_info_t *vreg_info; ++ struct msm_pcie_gpio_info_t *gpio_info; ++ struct msm_pcie_clk_info_t *clk_info; ++ struct msm_pcie_rst_info_t *rst_info; ++ struct resource *res; ++ struct msm_pcie_res_info_t *res_info; ++ struct msm_pcie_irq_info_t *irq_info; ++ char prop_name[MAX_PROP_SIZE]; ++ const __be32 *prop; ++ u32 *clkfreq = NULL; ++ ++ cnt = of_property_count_strings((&pdev->dev)->of_node, ++ "clock-names"); ++ if (cnt > 0) { ++ clkfreq = kzalloc(cnt * sizeof(*clkfreq), ++ GFP_KERNEL); ++ if (!clkfreq) { ++ PCIE_ERR(dev, "PCIe: memory alloc failed for RC%d\n", ++ dev->rc_idx); ++ return -ENOMEM; ++ } ++ ret = of_property_read_u32_array( ++ (&pdev->dev)->of_node, ++ "max-clock-frequency-hz", clkfreq, cnt); ++ if (ret) { ++ PCIE_ERR(dev, ++ "PCIe: invalid max-clock-frequency-hz property for RC%d:%d\n", ++ dev->rc_idx, ret); ++ goto out; ++ } ++ } ++ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++ for (i = 0; i < MSM_PCIE_MAX_VREG; i++) { ++ vreg_info = &dev->vreg[i]; ++ vreg_info->hdl = ++ devm_regulator_get(&pdev->dev, vreg_info->name); ++ ++ if (PTR_ERR(vreg_info->hdl) == -EPROBE_DEFER) { ++ PCIE_DBG(dev, "EPROBE_DEFER for VReg:%s\n", ++ vreg_info->name); ++ ret = PTR_ERR(vreg_info->hdl); ++ goto out; ++ } ++ ++ if (IS_ERR(vreg_info->hdl)) { ++ if (vreg_info->required) { ++ PCIE_DBG(dev, "Vreg %s doesn't exist\n", ++ vreg_info->name); ++ ret = PTR_ERR(vreg_info->hdl); ++ goto out; ++ } else { ++ PCIE_DBG(dev, ++ "Optional Vreg %s doesn't exist\n", ++ vreg_info->name); ++ vreg_info->hdl = NULL; ++ } ++ } else { ++ dev->vreg_n++; ++ snprintf(prop_name, MAX_PROP_SIZE, ++ "qcom,%s-voltage-level", vreg_info->name); ++ prop = of_get_property((&pdev->dev)->of_node, ++ prop_name, &len); ++ if (!prop || (len != (3 * sizeof(__be32)))) { ++ PCIE_DBG(dev, "%s %s property\n", ++ prop ? "invalid format" : ++ "no", prop_name); ++ vreg_info->hdl = NULL; ++ } else { ++ vreg_info->max_v = be32_to_cpup(&prop[0]); ++ vreg_info->min_v = be32_to_cpup(&prop[1]); ++ vreg_info->opt_mode = ++ be32_to_cpup(&prop[2]); ++ } ++ } ++ } ++ ++ dev->gdsc = devm_regulator_get(&pdev->dev, "gdsc-vdd"); ++ ++ if (IS_ERR(dev->gdsc)) { ++ PCIE_ERR(dev, "PCIe: RC%d Failed to get %s GDSC:%ld\n", ++ dev->rc_idx, dev->pdev->name, PTR_ERR(dev->gdsc)); ++ if (PTR_ERR(dev->gdsc) == -EPROBE_DEFER) ++ PCIE_DBG(dev, "PCIe: EPROBE_DEFER for %s GDSC\n", ++ dev->pdev->name); ++ ret = PTR_ERR(dev->gdsc); ++ goto out; ++ } ++ ++ dev->gpio_n = 0; ++ for (i = 0; i < MSM_PCIE_MAX_GPIO; i++) { ++ gpio_info = &dev->gpio[i]; ++ ret = of_get_named_gpio((&pdev->dev)->of_node, ++ gpio_info->name, 0); ++ if (ret >= 0) { ++ gpio_info->num = ret; ++ ret = 0; ++ dev->gpio_n++; ++ PCIE_DBG(dev, "GPIO num for %s is %d\n", ++ gpio_info->name, gpio_info->num); ++ } else { ++ goto out; ++ } ++ } ++ ++ for (i = 0; i < MSM_PCIE_MAX_CLK; i++) { ++ clk_info = &dev->clk[i]; ++ ++ clk_info->hdl = devm_clk_get(&pdev->dev, clk_info->name); ++ ++ if (IS_ERR(clk_info->hdl)) { ++ if (clk_info->required) { ++ PCIE_DBG(dev, "Clock %s isn't available:%ld\n", ++ clk_info->name, PTR_ERR(clk_info->hdl)); ++ ret = PTR_ERR(clk_info->hdl); ++ goto out; ++ } else { ++ PCIE_DBG(dev, "Ignoring Clock %s\n", ++ clk_info->name); ++ clk_info->hdl = NULL; ++ } ++ } else { ++ if (clkfreq != NULL) { ++ clk_info->freq = clkfreq[i + ++ MSM_PCIE_MAX_PIPE_CLK]; ++ PCIE_DBG(dev, "Freq of Clock %s is:%d\n", ++ clk_info->name, clk_info->freq); ++ } ++ } ++ } ++ ++ for (i = 0; i < MSM_PCIE_MAX_RESET; i++) { ++ rst_info = &dev->rst[i]; ++ ++ rst_info->hdl = devm_reset_control_get(&pdev->dev, rst_info->name); ++ ++ if (IS_ERR(rst_info->hdl)) { ++ PCIE_DBG(dev, "Reset %s isn't available:%ld\n", ++ rst_info->name, PTR_ERR(rst_info->hdl)); ++ ret = PTR_ERR(rst_info->hdl); ++ goto out; ++ } ++ } ++ ++ ++ ++ dev->bus_scale_table = msm_bus_cl_get_pdata(pdev); ++ if (!dev->bus_scale_table) { ++ PCIE_DBG(dev, "PCIe: No bus scale table for RC%d (%s)\n", ++ dev->rc_idx, dev->pdev->name); ++ dev->bus_client = 0; ++ } else { ++ dev->bus_client = ++ msm_bus_scale_register_client(dev->bus_scale_table); ++ if (!dev->bus_client) { ++ PCIE_ERR(dev, ++ "PCIe: Failed to register bus client for RC%d (%s)\n", ++ dev->rc_idx, dev->pdev->name); ++ msm_bus_cl_clear_pdata(dev->bus_scale_table); ++ ret = -ENODEV; ++ goto out; ++ } ++ } ++ ++ for (i = 0; i < MSM_PCIE_MAX_RES; i++) { ++ res_info = &dev->res[i]; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, ++ res_info->name); ++ ++ if (!res) { ++ PCIE_ERR(dev, "PCIe: RC%d can't get %s resource.\n", ++ dev->rc_idx, res_info->name); ++ ret = -ENOMEM; ++ goto out; ++ } else ++ PCIE_DBG(dev, "start addr for %s is %pa.\n", ++ res_info->name, &res->start); ++ ++ res_info->base = devm_ioremap(&pdev->dev, ++ res->start, resource_size(res)); ++ if (!res_info->base) { ++ PCIE_ERR(dev, "PCIe: RC%d can't remap %s.\n", ++ dev->rc_idx, res_info->name); ++ ret = -ENOMEM; ++ goto out; ++ } ++ res_info->resource = res; ++ } ++ ++ for (i = 0; i < MSM_PCIE_MAX_IRQ; i++) { ++ irq_info = &dev->irq[i]; ++ ++ /* Skip if wakeirq is not present in device tree */ ++ if (!dev->ep_wakeirq && (i == MSM_PCIE_INT_WAKE)) ++ continue; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, ++ irq_info->name); ++ ++ if (!res) { ++ int j; ++ for (j = 0; j < MSM_PCIE_MAX_RES; j++) { ++ iounmap(dev->res[j].base); ++ dev->res[j].base = NULL; ++ } ++ PCIE_ERR(dev, "PCIe: RC%d can't find IRQ # for %s.\n", ++ dev->rc_idx, irq_info->name); ++ ret = -ENODEV; ++ goto out; ++ } else { ++ irq_info->num = res->start; ++ PCIE_DBG(dev, "IRQ # for %s is %d.\n", irq_info->name, ++ irq_info->num); ++ } ++ } ++ ++ /* All allocations succeeded */ ++ ++ dev->wake_n = dev->irq[MSM_PCIE_INT_WAKE].num; ++ ++ dev->parf = dev->res[MSM_PCIE_RES_PARF].base; ++ dev->phy = dev->res[MSM_PCIE_RES_PHY].base; ++ dev->elbi = dev->res[MSM_PCIE_RES_ELBI].base; ++ dev->dm_core = dev->res[MSM_PCIE_RES_DM_CORE].base; ++ dev->conf = dev->res[MSM_PCIE_RES_CONF].base; ++ dev->bars = dev->res[MSM_PCIE_RES_BARS].base; ++ dev->dev_mem_res = dev->res[MSM_PCIE_RES_BARS].resource; ++ dev->dev_io_res = dev->res[MSM_PCIE_RES_IO].resource; ++ dev->dev_io_res->flags = IORESOURCE_IO; ++ ++out: ++ kfree(clkfreq); ++ return ret; ++} ++ ++static void msm_pcie_release_resources(struct msm_pcie_dev_t *dev) ++{ ++ dev->parf = NULL; ++ dev->elbi = NULL; ++ dev->dm_core = NULL; ++ dev->conf = NULL; ++ dev->bars = NULL; ++ dev->dev_mem_res = NULL; ++ dev->dev_io_res = NULL; ++} ++ ++int msm_pcie_enable(struct msm_pcie_dev_t *dev, u32 options) ++{ ++ int ret = 0; ++ uint32_t val; ++ long int retries = 0; ++ int link_check_count = 0; ++ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++ mutex_lock(&dev->setup_lock); ++ ++ if (dev->link_status == MSM_PCIE_LINK_ENABLED) { ++ PCIE_ERR(dev, "PCIe: the link of RC%d is already enabled\n", ++ dev->rc_idx); ++ goto out; ++ } ++ ++ ++ /* assert PCIe reset link to keep EP in reset */ ++ ++ PCIE_INFO(dev, "PCIe: trigger the reset of endpoint of RC%d.\n", ++ dev->rc_idx); ++ gpio_set_value(dev->gpio[MSM_PCIE_GPIO_PERST].num, ++ dev->gpio[MSM_PCIE_GPIO_PERST].on); ++ usleep_range(PERST_PROPAGATION_DELAY_US_MIN, ++ PERST_PROPAGATION_DELAY_US_MAX); ++ ++ /* enable power */ ++ ++ if (options & PM_VREG) { ++ ret = msm_pcie_vreg_init(dev); ++ if (ret) ++ goto out; ++ } ++ ++ /* enable clocks */ ++ if (options & PM_CLK) { ++ ret = msm_pcie_clk_init(dev); ++ wmb(); ++ if (ret) ++ goto clk_fail; ++ } ++ ++ /* enable PCIe clocks and resets */ ++ msm_pcie_write_mask(dev->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0); ++ ++ /* change DBI base address */ ++ writel_relaxed(0, dev->parf + PCIE20_PARF_DBI_BASE_ADDR); ++ ++ if (dev->rc_idx) ++ writel_relaxed(0x361c, dev->parf + PCIE20_PARF_SYS_CTRL); ++ else ++ writel_relaxed(0x3656, dev->parf + PCIE20_PARF_SYS_CTRL); ++ ++ writel_relaxed(0, dev->parf + PCIE20_PARF_Q2A_FLUSH); ++ ++ if (dev->use_msi) { ++ PCIE_DBG(dev, "RC%d: enable WR halt.\n", dev->rc_idx); ++ msm_pcie_write_mask(dev->parf + ++ PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT, 0, BIT(31)); ++ } ++ ++ /* init PCIe PHY */ ++ if (dev->is_emulation) ++ pcie_phy_init(dev); ++ ++ writel_relaxed(CMD_BME_VAL, dev->dm_core + PCIE20_COMMAND_STATUS); ++ writel_relaxed(DBI_RO_WR_EN, ++ dev->dm_core + PCIE20_MISC_CONTROL_1_REG); ++ writel_relaxed(PCIE_CAP_LINK1_VAL, dev->dm_core + PCIE20_CAP_LINK_1); ++ msm_pcie_write_mask(dev->dm_core + PCIE20_CAP_LINK_CAPABILITIES, ++ BIT(10) | BIT(11), 0); ++ writel_relaxed(PCIE_CAP_CPL_TIMEOUT_DISABLE, ++ dev->dm_core + PCIE20_DEVICE_CONTROL2_STATUS2); ++ writel_relaxed(LTSSM_EN, dev->parf + PCIE20_PARF_LTSSM); ++ ++ PCIE_DBG(dev, "RC%d: waiting for phy ready...\n", dev->rc_idx); ++ ++ do { ++ if (pcie_phy_is_ready(dev)) ++ break; ++ retries++; ++ usleep_range(REFCLK_STABILIZATION_DELAY_US_MIN, ++ REFCLK_STABILIZATION_DELAY_US_MAX); ++ } while (retries < PHY_READY_TIMEOUT_COUNT); ++ ++ PCIE_DBG(dev, "RC%d: number of PHY retries:%ld.\n", ++ dev->rc_idx, retries); ++ ++ if (pcie_phy_is_ready(dev)) ++ PCIE_INFO(dev, "PCIe RC%d PHY is ready!\n", dev->rc_idx); ++ else { ++ PCIE_ERR(dev, "PCIe PHY RC%d failed to come up!\n", ++ dev->rc_idx); ++ ret = -ENODEV; ++ goto link_fail; ++ } ++ ++ if (dev->ep_latency) ++ msleep(dev->ep_latency); ++ ++ /* de-assert PCIe reset link to bring EP out of reset */ ++ ++ PCIE_INFO(dev, "PCIe: Release the reset of endpoint of RC%d.\n", ++ dev->rc_idx); ++ gpio_set_value(dev->gpio[MSM_PCIE_GPIO_PERST].num, ++ 1 - dev->gpio[MSM_PCIE_GPIO_PERST].on); ++ usleep_range(PERST_PROPAGATION_DELAY_US_MIN, ++ PERST_PROPAGATION_DELAY_US_MAX); ++ ++ /* enable link training */ ++ msm_pcie_write_mask(dev->elbi + PCIE20_ELBI_SYS_CTRL, 0, BIT(0)); ++ ++ PCIE_DBG(dev, "%s", "check if link is up\n"); ++ ++ if (dev->rc_idx == 1) { ++ PCIE_DBG(dev, "optimized link training for RC%d\n", ++ dev->rc_idx); ++ /* Wait for up to 100ms for the link to come up */ ++ do { ++ usleep_range(LINK_UP_TIMEOUT_US_MIN, ++ LINK_UP_TIMEOUT_US_MAX); ++ val = readl_relaxed(dev->elbi + PCIE20_ELBI_SYS_STTS); ++ } while ((!(val & XMLH_LINK_UP) || ++ !msm_pcie_confirm_linkup(dev, false, false)) ++ && (link_check_count++ < LINK_UP_CHECK_MAX_COUNT)); ++ ++ if ((val & XMLH_LINK_UP) && ++ msm_pcie_confirm_linkup(dev, false, false)) ++ PCIE_DBG(dev, "Link is up after %d checkings\n", ++ link_check_count); ++ else ++ PCIE_DBG(dev, "Initial link training failed for RC%d\n", ++ dev->rc_idx); ++ } else { ++ PCIE_DBG(dev, "non-optimized link training for RC%d\n", ++ dev->rc_idx); ++ usleep_range(LINK_RETRY_TIMEOUT_US_MIN * 5 , ++ LINK_RETRY_TIMEOUT_US_MAX * 5); ++ val = readl_relaxed(dev->elbi + PCIE20_ELBI_SYS_STTS); ++ } ++ ++ retries = 0; ++ ++ while ((!(val & XMLH_LINK_UP) || ++ !msm_pcie_confirm_linkup(dev, false, false)) ++ && (retries < MAX_LINK_RETRIES)) { ++ PCIE_ERR(dev, "RC%d:No. %ld:LTSSM_STATE:0x%x\n", dev->rc_idx, ++ retries + 1, (val >> 0xC) & 0x1f); ++ gpio_set_value(dev->gpio[MSM_PCIE_GPIO_PERST].num, ++ dev->gpio[MSM_PCIE_GPIO_PERST].on); ++ usleep_range(PERST_PROPAGATION_DELAY_US_MIN, ++ PERST_PROPAGATION_DELAY_US_MAX); ++ gpio_set_value(dev->gpio[MSM_PCIE_GPIO_PERST].num, ++ 1 - dev->gpio[MSM_PCIE_GPIO_PERST].on); ++ usleep_range(LINK_RETRY_TIMEOUT_US_MIN, ++ LINK_RETRY_TIMEOUT_US_MAX); ++ retries++; ++ val = readl_relaxed(dev->elbi + PCIE20_ELBI_SYS_STTS); ++ } ++ ++ PCIE_DBG(dev, "number of link training retries: %ld\n", retries); ++ ++ if ((val & XMLH_LINK_UP) && ++ msm_pcie_confirm_linkup(dev, false, false)) { ++ PCIE_INFO(dev, "PCIe RC%d link initialized\n", dev->rc_idx); ++ } else { ++ PCIE_INFO(dev, "PCIe: trigger the reset of endpoint of RC%d.\n", ++ dev->rc_idx); ++ gpio_set_value(dev->gpio[MSM_PCIE_GPIO_PERST].num, ++ dev->gpio[MSM_PCIE_GPIO_PERST].on); ++ PCIE_ERR(dev, "PCIe RC%d link initialization failed\n", ++ dev->rc_idx); ++ ret = -1; ++ goto link_fail; ++ } ++ ++ msm_pcie_config_controller(dev); ++ ++ if (!dev->msi_gicm_addr) ++ msm_pcie_config_msi_controller(dev); ++ ++ if (dev->l1ss_supported) ++ msm_pcie_config_l1ss(dev); ++ ++ dev->link_status = MSM_PCIE_LINK_ENABLED; ++ dev->power_on = true; ++ dev->suspending = false; ++ goto out; ++ ++link_fail: ++ msm_pcie_clk_deinit(dev); ++clk_fail: ++ msm_pcie_vreg_deinit(dev); ++out: ++ mutex_unlock(&dev->setup_lock); ++ ++ return ret; ++} ++ ++ ++void msm_pcie_disable(struct msm_pcie_dev_t *dev, u32 options) ++{ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++ mutex_lock(&dev->setup_lock); ++ ++ if (!dev->power_on) { ++ PCIE_DBG(dev, ++ "PCIe: the link of RC%d is already power down.\n", ++ dev->rc_idx); ++ mutex_unlock(&dev->setup_lock); ++ return; ++ } ++ ++ dev->link_status = MSM_PCIE_LINK_DISABLED; ++ dev->power_on = false; ++ ++ PCIE_INFO(dev, "PCIe: trigger the reset of endpoint of RC%d.\n", ++ dev->rc_idx); ++ ++ gpio_set_value(dev->gpio[MSM_PCIE_GPIO_PERST].num, ++ dev->gpio[MSM_PCIE_GPIO_PERST].on); ++ ++ if (options & PM_CLK) { ++ msm_pcie_write_mask(dev->parf + PCIE20_PARF_PHY_CTRL, 0, ++ BIT(0)); ++ msm_pcie_clk_deinit(dev); ++ } ++ ++ if (options & PM_VREG) ++ msm_pcie_vreg_deinit(dev); ++ ++ mutex_unlock(&dev->setup_lock); ++} ++ ++static int msm_pcie_setup(int nr, struct pci_sys_data *sys) ++{ ++ struct msm_pcie_dev_t *dev = ++ (struct msm_pcie_dev_t *)(sys->private_data); ++ ++ PCIE_DBG(dev, "bus %d\n", nr); ++ /* ++ * specify linux PCI framework to allocate device memory (BARs) ++ * from msm_pcie_dev.dev_mem_res resource. ++ */ ++ sys->mem_offset = 0; ++ sys->io_offset = 0; ++ ++ pci_add_resource(&sys->resources, dev->dev_io_res); ++ pci_add_resource(&sys->resources, dev->dev_mem_res); ++ return 1; ++} ++ ++static int msm_rc_remove(struct msm_pcie_dev_t *dev) ++{ ++ msm_pcie_disable(dev, PM_PIPE_CLK | PM_CLK | PM_VREG); ++ pci_stop_root_bus(dev->pci_bus); ++ pci_remove_root_bus(dev->pci_bus); ++ dev->pci_bus = NULL; ++ dev->enumerated = false; ++ return 0; ++} ++ ++void msm_pcie_remove_bus(void) ++{ ++ int i; ++ ++ if (atomic_read(&rc_removed)) ++ return; ++ ++ for (i = 0; i < pcie_drv.rc_num; i++) { ++ pr_notice("---> Removing %d", i); ++ msm_rc_remove(&msm_pcie_dev[i]); ++ pr_notice(" ... done<---\n"); ++ } ++ ++ atomic_set(&rc_removed, 1); ++} ++ ++static struct pci_bus *msm_pcie_scan_bus(int nr, ++ struct pci_sys_data *sys) ++{ ++ struct pci_bus *bus = NULL; ++ struct msm_pcie_dev_t *dev = ++ (struct msm_pcie_dev_t *)(sys->private_data); ++ ++ PCIE_DBG(dev, "bus %d\n", nr); ++ ++ bus = pci_scan_root_bus(NULL, sys->busnr, &msm_pcie_ops, sys, ++ &sys->resources); ++ dev->pci_bus = bus; ++ ++ return bus; ++} ++ ++static int msm_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev); ++ int ret = 0; ++ ++ PCIE_DBG(pcie_dev, "rc %s slot %d pin %d\n", pcie_dev->pdev->name, ++ slot, pin); ++ ++ switch (pin) { ++ case 1: ++ ret = pcie_dev->irq[MSM_PCIE_INT_A].num; ++ break; ++ case 2: ++ ret = pcie_dev->irq[MSM_PCIE_INT_B].num; ++ break; ++ case 3: ++ ret = pcie_dev->irq[MSM_PCIE_INT_C].num; ++ break; ++ case 4: ++ ret = pcie_dev->irq[MSM_PCIE_INT_D].num; ++ break; ++ default: ++ PCIE_ERR(pcie_dev, "PCIe: RC%d: unsupported pin number.\n", ++ pcie_dev->rc_idx); ++ } ++ ++ return ret; ++} ++ ++#if 0 ++static void msm_pcie_add_bus(struct pci_bus *bus) ++{ ++ struct pci_sys_data *sys = bus->sysdata; ++ struct msm_pcie_dev_t *dev = ++ (struct msm_pcie_dev_t *)(sys->private_data); ++ ++ bus->msi = dev->msi_chip; ++} ++#endif ++ ++static struct hw_pci msm_pci[MAX_RC_NUM] = { ++ { ++ //.domain = 0, ++ .nr_controllers = 1, ++ .swizzle = pci_common_swizzle, ++ .setup = msm_pcie_setup, ++ .scan = msm_pcie_scan_bus, ++ .map_irq = msm_pcie_map_irq, ++ //.add_bus = msm_pcie_add_bus, ++ }, ++}; ++ ++int msm_pcie_rescan(void) ++{ ++ int i; ++ ++ if (!atomic_read(&rc_removed)) ++ return 0; ++ ++ for (i = 0; i < pcie_drv.rc_num; i++) { ++ /* reset the RC and enumurate devices */ ++ msm_pcie_controller_reset(&msm_pcie_dev[i]); ++ msm_pcie_enumerate(i); ++ } ++ ++ atomic_set(&rc_removed, 0); ++ ++ return 0; ++} ++ ++int msm_pcie_enumerate(u32 rc_idx) ++{ ++ int ret = 0; ++ struct msm_pcie_dev_t *dev = &msm_pcie_dev[rc_idx]; ++ ++ PCIE_DBG(dev, "Enumerate RC%d\n", rc_idx); ++ ++ if (!dev->enumerated) { ++ ret = msm_pcie_enable(dev, PM_ALL); ++ ++ /* kick start ARM PCI configuration framework */ ++ if (!ret) { ++ struct pci_dev *pcidev = NULL; ++ bool found = false; ++ u32 ids = readl_relaxed(msm_pcie_dev[rc_idx].dm_core); ++ u32 vendor_id = ids & 0xffff; ++ u32 device_id = (ids & 0xffff0000) >> 16; ++ ++ PCIE_DBG(dev, "vendor-id:0x%x device_id:0x%x\n", ++ vendor_id, device_id); ++ ++ msm_pci[rc_idx].private_data = (void **)&dev; ++ pci_common_init(&msm_pci[rc_idx]); ++ /* This has to happen only once */ ++ dev->enumerated = true; ++ ++ do { ++ pcidev = pci_get_device(vendor_id, ++ device_id, pcidev); ++ if (pcidev && (&msm_pcie_dev[rc_idx] == ++ (struct msm_pcie_dev_t *) ++ PCIE_BUS_PRIV_DATA(pcidev))) { ++ msm_pcie_dev[rc_idx].dev = pcidev; ++ found = true; ++ PCIE_DBG(&msm_pcie_dev[rc_idx], ++ "PCI device is found for RC%d\n", ++ rc_idx); ++ } ++ } while (!found && pcidev); ++ ++ if (!pcidev) { ++ PCIE_ERR(dev, ++ "PCIe: Did not find PCI device for RC%d.\n", ++ dev->rc_idx); ++ return -ENODEV; ++ } ++ } else { ++ PCIE_ERR(dev, "PCIe: failed to enable RC%d.\n", ++ dev->rc_idx); ++ } ++ } else { ++ PCIE_ERR(dev, "PCIe: RC%d has already been enumerated.\n", ++ dev->rc_idx); ++ } ++ ++ return ret; ++} ++ ++static ssize_t msm_bus_rescan_store(struct bus_type *bus, const char *buf, ++ size_t count) ++{ ++ unsigned long val; ++ ++ if (kstrtoul(buf, 0, &val) < 0) ++ return -EINVAL; ++ ++ if (val) { ++ pci_lock_rescan_remove(); ++ msm_pcie_rescan(); ++ pci_unlock_rescan_remove(); ++ } ++ return count; ++} ++static BUS_ATTR(rcrescan, (S_IWUSR|S_IWGRP), NULL, msm_bus_rescan_store); ++ ++static ssize_t msm_bus_remove_store(struct bus_type *bus, const char *buf, ++ size_t count) ++{ ++ unsigned long val; ++ ++ if (kstrtoul(buf, 0, &val) < 0) ++ return -EINVAL; ++ ++ if (val) { ++ pci_lock_rescan_remove(); ++ msm_pcie_remove_bus(); ++ pci_unlock_rescan_remove(); ++ } ++ return count; ++} ++static BUS_ATTR(rcremove, (S_IWUSR|S_IWGRP), NULL, msm_bus_remove_store); ++ ++static int msm_pcie_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ int rc_idx = -1; ++ int i; ++ ++ pr_debug("%s\n", __func__); ++ ++ mutex_lock(&pcie_drv.drv_lock); ++ ++ ret = of_property_read_u32((&pdev->dev)->of_node, ++ "qcom,ctrl-amt", &pcie_drv.rc_expected); ++ if (ret) { ++ pr_err("PCIe: does not find controller amount.\n"); ++ goto out; ++ } else { ++ if (pcie_drv.rc_expected > MAX_RC_NUM) { ++ pr_debug("Expected number of devices %d\n", ++ pcie_drv.rc_expected); ++ pr_debug("Exceeded max supported devices %d\n", ++ MAX_RC_NUM); ++ goto out; ++ } ++ pr_debug("Target has %d RC(s).\n", pcie_drv.rc_expected); ++ } ++ ++ ret = of_property_read_u32((&pdev->dev)->of_node, ++ "cell-index", &rc_idx); ++ if (ret) { ++ pr_debug("Did not find RC index.\n"); ++ goto out; ++ } else { ++ if (rc_idx >= MAX_RC_NUM) { ++ pr_err( ++ "PCIe: Invalid RC Index %d (max supported = %d)\n", ++ rc_idx, MAX_RC_NUM); ++ goto out; ++ } ++ pcie_drv.rc_num++; ++ PCIE_DBG(&msm_pcie_dev[rc_idx], "PCIe: RC index is %d.\n", ++ rc_idx); ++ } ++ ++ msm_pcie_dev[rc_idx].l1ss_supported = ++ of_property_read_bool((&pdev->dev)->of_node, ++ "qcom,l1ss-supported"); ++ PCIE_DBG(&msm_pcie_dev[rc_idx], "L1ss is %s supported.\n", ++ msm_pcie_dev[rc_idx].l1ss_supported ? "" : "not"); ++ msm_pcie_dev[rc_idx].aux_clk_sync = ++ of_property_read_bool((&pdev->dev)->of_node, ++ "qcom,aux-clk-sync"); ++ PCIE_DBG(&msm_pcie_dev[rc_idx], ++ "AUX clock is %s synchronous to Core clock.\n", ++ msm_pcie_dev[rc_idx].aux_clk_sync ? "" : "not"); ++ ++ msm_pcie_dev[rc_idx].ep_wakeirq = ++ of_property_read_bool((&pdev->dev)->of_node, ++ "qcom,ep-wakeirq"); ++ PCIE_DBG(&msm_pcie_dev[rc_idx], ++ "PCIe: EP of RC%d does %s assert wake when it is up.\n", ++ rc_idx, msm_pcie_dev[rc_idx].ep_wakeirq ? "" : "not"); ++ ++ msm_pcie_dev[rc_idx].n_fts = 0; ++ ret = of_property_read_u32((&pdev->dev)->of_node, ++ "qcom,n-fts", ++ &msm_pcie_dev[rc_idx].n_fts); ++ ++ if (ret) ++ PCIE_DBG(&msm_pcie_dev[rc_idx], ++ "n-fts does not exist. ret=%d\n", ret); ++ else ++ PCIE_DBG(&msm_pcie_dev[rc_idx], "n-fts: 0x%x.\n", ++ msm_pcie_dev[rc_idx].n_fts); ++ ++ msm_pcie_dev[rc_idx].is_emulation = ++ of_property_read_bool((&pdev->dev)->of_node, ++ "qcom,is_emulation"); ++ ++ PCIE_DBG(&msm_pcie_dev[rc_idx], "is_emulation: 0x%x.\n", ++ msm_pcie_dev[rc_idx].is_emulation); ++ ++ msm_pcie_dev[rc_idx].ext_ref_clk = ++ of_property_read_bool((&pdev->dev)->of_node, ++ "qcom,ext-ref-clk"); ++ PCIE_DBG(&msm_pcie_dev[rc_idx], "ref clk is %s.\n", ++ msm_pcie_dev[rc_idx].ext_ref_clk ? "external" : "internal"); ++ ++ msm_pcie_dev[rc_idx].ep_latency = 0; ++ ret = of_property_read_u32((&pdev->dev)->of_node, ++ "qcom,ep-latency", ++ &msm_pcie_dev[rc_idx].ep_latency); ++ if (ret) ++ PCIE_DBG(&msm_pcie_dev[rc_idx], ++ "RC%d: ep-latency does not exist.\n", ++ rc_idx); ++ else ++ PCIE_DBG(&msm_pcie_dev[rc_idx], "RC%d: ep-latency: 0x%x.\n", ++ rc_idx, msm_pcie_dev[rc_idx].ep_latency); ++ ++ msm_pcie_dev[rc_idx].msi_gicm_addr = 0; ++ msm_pcie_dev[rc_idx].msi_gicm_base = 0; ++ ret = of_property_read_u32((&pdev->dev)->of_node, ++ "qcom,msi-gicm-addr", ++ &msm_pcie_dev[rc_idx].msi_gicm_addr); ++ ++ if (ret) { ++ PCIE_DBG(&msm_pcie_dev[rc_idx], "%s", ++ "msi-gicm-addr does not exist.\n"); ++ } else { ++ PCIE_DBG(&msm_pcie_dev[rc_idx], "msi-gicm-addr: 0x%x.\n", ++ msm_pcie_dev[rc_idx].msi_gicm_addr); ++ ++ ret = of_property_read_u32((&pdev->dev)->of_node, ++ "qcom,msi-gicm-base", ++ &msm_pcie_dev[rc_idx].msi_gicm_base); ++ ++ if (ret) { ++ PCIE_ERR(&msm_pcie_dev[rc_idx], ++ "PCIe: RC%d: msi-gicm-base does not exist.\n", ++ rc_idx); ++ goto decrease_rc_num; ++ } else { ++ PCIE_DBG(&msm_pcie_dev[rc_idx], "msi-gicm-base: 0x%x\n", ++ msm_pcie_dev[rc_idx].msi_gicm_base); ++ } ++ } ++ ++ msm_pcie_dev[rc_idx].rc_idx = rc_idx; ++ msm_pcie_dev[rc_idx].pdev = pdev; ++ msm_pcie_dev[rc_idx].vreg_n = 0; ++ msm_pcie_dev[rc_idx].gpio_n = 0; ++ msm_pcie_dev[rc_idx].parf_deemph = 0; ++ msm_pcie_dev[rc_idx].parf_swing = 0; ++ msm_pcie_dev[rc_idx].link_status = MSM_PCIE_LINK_DEINIT; ++ msm_pcie_dev[rc_idx].user_suspend = false; ++ msm_pcie_dev[rc_idx].saved_state = NULL; ++ msm_pcie_dev[rc_idx].enumerated = false; ++ msm_pcie_dev[rc_idx].linkdown_counter = 0; ++ msm_pcie_dev[rc_idx].suspending = false; ++ msm_pcie_dev[rc_idx].wake_counter = 0; ++ msm_pcie_dev[rc_idx].req_exit_l1_counter = 0; ++ msm_pcie_dev[rc_idx].power_on = false; ++ msm_pcie_dev[rc_idx].use_msi = false; ++ memcpy(msm_pcie_dev[rc_idx].vreg, msm_pcie_vreg_info, ++ sizeof(msm_pcie_vreg_info)); ++ memcpy(msm_pcie_dev[rc_idx].gpio, msm_pcie_gpio_info, ++ sizeof(msm_pcie_gpio_info)); ++ memcpy(msm_pcie_dev[rc_idx].clk, msm_pcie_clk_info[rc_idx], ++ sizeof(msm_pcie_clk_info)); ++ ++ memcpy(msm_pcie_dev[rc_idx].rst, msm_pcie_rst_info, ++ sizeof(msm_pcie_rst_info)); ++ memcpy(msm_pcie_dev[rc_idx].res, msm_pcie_res_info, ++ sizeof(msm_pcie_res_info)); ++ memcpy(msm_pcie_dev[rc_idx].irq, msm_pcie_irq_info, ++ sizeof(msm_pcie_irq_info)); ++ msm_pcie_dev[rc_idx].shadow_en = true; ++ for (i = 0; i < PCIE_CONF_SPACE_DW; i++) { ++ msm_pcie_dev[rc_idx].rc_shadow[i] = PCIE_CLEAR; ++ msm_pcie_dev[rc_idx].ep_shadow[i] = PCIE_CLEAR; ++ } ++ ++ ret = msm_pcie_get_resources(&msm_pcie_dev[rc_idx], ++ msm_pcie_dev[rc_idx].pdev); ++ ++ if (ret) ++ goto decrease_rc_num; ++ ++ ret = msm_pcie_gpio_init(&msm_pcie_dev[rc_idx]); ++ if (ret) { ++ msm_pcie_release_resources(&msm_pcie_dev[rc_idx]); ++ goto decrease_rc_num; ++ } ++ ++ /* s/w reset of pcie */ ++ msm_pcie_controller_reset(&msm_pcie_dev[rc_idx]); ++ ++ /* detect uni phy before accessing the pcie registers */ ++ if (msm_pcie_dev[rc_idx].is_emulation && !pcie_phy_detect(&msm_pcie_dev[rc_idx])) { ++ ret = -ENODEV; ++ msm_pcie_release_resources(&msm_pcie_dev[rc_idx]); ++ msm_pcie_gpio_deinit(&msm_pcie_dev[rc_idx]); ++ goto decrease_rc_num; ++ } ++ ++ ret = msm_pcie_irq_init(&msm_pcie_dev[rc_idx]); ++ if (ret) { ++ msm_pcie_release_resources(&msm_pcie_dev[rc_idx]); ++ msm_pcie_gpio_deinit(&msm_pcie_dev[rc_idx]); ++ goto decrease_rc_num; ++ } ++ ++ if (msm_pcie_dev[rc_idx].ep_wakeirq) { ++ PCIE_DBG(&msm_pcie_dev[rc_idx], ++ "PCIe: RC%d will be enumerated upon WAKE signal from Endpoint.\n", ++ rc_idx); ++ mutex_unlock(&pcie_drv.drv_lock); ++ return 0; ++ } ++ ++ ret = msm_pcie_enumerate(rc_idx); ++ ++ if (ret) { ++ PCIE_ERR(&msm_pcie_dev[rc_idx], ++ "PCIe: RC%d is not enabled during bootup; it will be enumerated upon WAKE signal.\n", ++ rc_idx); ++ goto decrease_rc_num; ++ } else { ++ PCIE_ERR(&msm_pcie_dev[rc_idx], "RC%d is enabled in bootup\n", ++ rc_idx); ++ } ++ ++ PCIE_DBG(&msm_pcie_dev[rc_idx], "PCIE probed %s\n", ++ dev_name(&(pdev->dev))); ++ ++ /* create sysfs files to support power save mode */ ++ if (!rc_idx) { ++ ret = bus_create_file(&pci_bus_type, &bus_attr_rcrescan); ++ if (ret != 0) { ++ PCIE_ERR(&msm_pcie_dev[rc_idx], ++ "RC%d failed to create sysfs rcrescan file\n", ++ rc_idx); ++ } ++ ++ ret = bus_create_file(&pci_bus_type, &bus_attr_rcremove); ++ if (ret != 0) { ++ PCIE_ERR(&msm_pcie_dev[rc_idx], ++ "RC%d failed to create sysfs rcremove file\n", ++ rc_idx); ++ } ++ } ++ ++ mutex_unlock(&pcie_drv.drv_lock); ++ return 0; ++ ++decrease_rc_num: ++ pcie_drv.rc_num--; ++out: ++ PCIE_ERR(&msm_pcie_dev[rc_idx], ++ "PCIe: Driver probe failed for RC%d:%d\n", ++ rc_idx, ret); ++ mutex_unlock(&pcie_drv.drv_lock); ++ ++ return ret; ++} ++ ++static int __exit msm_pcie_remove(struct platform_device *pdev) ++{ ++ int ret = 0; ++ int rc_idx; ++ ++ pr_debug("PCIe:%s.\n", __func__); ++ ++ mutex_lock(&pcie_drv.drv_lock); ++ ++ ret = of_property_read_u32((&pdev->dev)->of_node, ++ "cell-index", &rc_idx); ++ if (ret) { ++ pr_err("%s: Did not find RC index.\n", __func__); ++ goto out; ++ } else { ++ pcie_drv.rc_num--; ++ pr_debug("%s: RC index is 0x%x.", __func__, rc_idx); ++ } ++ ++ msm_pcie_irq_deinit(&msm_pcie_dev[rc_idx]); ++ msm_pcie_vreg_deinit(&msm_pcie_dev[rc_idx]); ++ msm_pcie_clk_deinit(&msm_pcie_dev[rc_idx]); ++ msm_pcie_gpio_deinit(&msm_pcie_dev[rc_idx]); ++ msm_pcie_release_resources(&msm_pcie_dev[rc_idx]); ++ ++out: ++ mutex_unlock(&pcie_drv.drv_lock); ++ ++ return ret; ++} ++ ++static struct of_device_id msm_pcie_match[] = { ++ { .compatible = "qcom,msm_pcie", ++ }, ++ {} ++}; ++ ++static struct platform_driver msm_pcie_driver = { ++ .probe = msm_pcie_probe, ++ .remove = msm_pcie_remove, ++ .driver = { ++ .name = "msm_pcie", ++ .owner = THIS_MODULE, ++ .of_match_table = msm_pcie_match, ++ }, ++}; ++ ++static int __init pcie_init(void) ++{ ++ int ret = 0, i; ++#ifdef CONFIG_IPC_LOGGING ++ char rc_name[MAX_RC_NAME_LEN]; ++#endif ++ ++ pr_debug("pcie:%s.\n", __func__); ++ ++ pcie_drv.rc_num = 0; ++ pcie_drv.rc_expected = 0; ++ mutex_init(&pcie_drv.drv_lock); ++ ++ for (i = 0; i < MAX_RC_NUM; i++) { ++#ifdef CONFIG_IPC_LOGGING ++ snprintf(rc_name, MAX_RC_NAME_LEN, "pcie%d-short", i); ++ msm_pcie_dev[i].ipc_log = ++ ipc_log_context_create(PCIE_LOG_PAGES, rc_name, 0); ++ if (msm_pcie_dev[i].ipc_log == NULL) ++ pr_err("%s: unable to create IPC log context for %s\n", ++ __func__, rc_name); ++ else ++ PCIE_DBG(&msm_pcie_dev[i], ++ "PCIe IPC logging is enable for RC%d\n", ++ i); ++ snprintf(rc_name, MAX_RC_NAME_LEN, "pcie%d-long", i); ++ msm_pcie_dev[i].ipc_log_long = ++ ipc_log_context_create(PCIE_LOG_PAGES, rc_name, 0); ++ if (msm_pcie_dev[i].ipc_log_long == NULL) ++ pr_err("%s: unable to create IPC log context for %s\n", ++ __func__, rc_name); ++ else ++ PCIE_DBG(&msm_pcie_dev[i], ++ "PCIe IPC logging %s is enable for RC%d\n", ++ rc_name, i); ++#endif ++ ++ spin_lock_init(&msm_pcie_dev[i].cfg_lock); ++ msm_pcie_dev[i].cfg_access = true; ++ mutex_init(&msm_pcie_dev[i].setup_lock); ++ mutex_init(&msm_pcie_dev[i].recovery_lock); ++ spin_lock_init(&msm_pcie_dev[i].linkdown_lock); ++ spin_lock_init(&msm_pcie_dev[i].wakeup_lock); ++ } ++ ++ ret = platform_driver_register(&msm_pcie_driver); ++ ++ return ret; ++} ++ ++static void __exit pcie_exit(void) ++{ ++ pr_debug("pcie:%s.\n", __func__); ++ ++ platform_driver_unregister(&msm_pcie_driver); ++} ++ ++subsys_initcall_sync(pcie_init); ++module_exit(pcie_exit); ++ ++ ++/* RC do not represent the right class; set it to PCI_CLASS_BRIDGE_PCI */ ++static void msm_pcie_fixup_early(struct pci_dev *dev) ++{ ++ struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev); ++ PCIE_DBG(pcie_dev, "hdr_type %d\n", dev->hdr_type); ++ if (dev->hdr_type == 1) ++ dev->class = (dev->class & 0xff) | (PCI_CLASS_BRIDGE_PCI << 8); ++} ++DECLARE_PCI_FIXUP_EARLY(PCIE_VENDOR_ID_RCP, PCIE_DEVICE_ID_RCP, ++ msm_pcie_fixup_early); ++ ++/* Suspend the PCIe link */ ++static int msm_pcie_pm_suspend(struct pci_dev *dev, ++ void *user, void *data, u32 options) ++{ ++ int ret = 0; ++ u32 val = 0; ++ int ret_l23; ++ struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev); ++ ++ pcie_dev->suspending = true; ++ PCIE_DBG(pcie_dev, "RC%d\n", pcie_dev->rc_idx); ++ ++ if (!pcie_dev->power_on) { ++ PCIE_DBG(pcie_dev, ++ "PCIe: power of RC%d has been turned off.\n", ++ pcie_dev->rc_idx); ++ return ret; ++ } ++ ++ if (dev && !(options & MSM_PCIE_CONFIG_NO_CFG_RESTORE) ++ && msm_pcie_confirm_linkup(pcie_dev, true, true)) { ++ ret = pci_save_state(dev); ++ pcie_dev->saved_state = pci_store_saved_state(dev); ++ } ++ if (ret) { ++ PCIE_ERR(pcie_dev, "PCIe: fail to save state of RC%d:%d.\n", ++ pcie_dev->rc_idx, ret); ++ pcie_dev->suspending = false; ++ return ret; ++ } ++ ++ spin_lock_irqsave(&pcie_dev->cfg_lock, ++ pcie_dev->irqsave_flags); ++ pcie_dev->cfg_access = false; ++ spin_unlock_irqrestore(&pcie_dev->cfg_lock, ++ pcie_dev->irqsave_flags); ++ ++ msm_pcie_write_mask(pcie_dev->elbi + PCIE20_ELBI_SYS_CTRL, 0, ++ BIT(4)); ++ ++ PCIE_DBG(pcie_dev, "RC%d: PME_TURNOFF_MSG is sent out\n", ++ pcie_dev->rc_idx); ++ ++ ret_l23 = readl_poll_timeout((pcie_dev->parf ++ + PCIE20_PARF_PM_STTS), val, (val & BIT(6)), 10000, 100000); ++ ++ /* check L23_Ready */ ++ if (!ret_l23) ++ PCIE_DBG(pcie_dev, "RC%d: PM_Enter_L23 is received\n", ++ pcie_dev->rc_idx); ++ else ++ PCIE_DBG(pcie_dev, "RC%d: PM_Enter_L23 is NOT received\n", ++ pcie_dev->rc_idx); ++ ++ msm_pcie_disable(pcie_dev, PM_PIPE_CLK | PM_CLK | PM_VREG); ++ ++ return ret; ++} ++ ++static void msm_pcie_fixup_suspend(struct pci_dev *dev) ++{ ++ int ret; ++ struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev); ++ ++ PCIE_DBG(pcie_dev, "RC%d\n", pcie_dev->rc_idx); ++ ++ if (pcie_dev->link_status != MSM_PCIE_LINK_ENABLED) ++ return; ++ ++ mutex_lock(&pcie_dev->recovery_lock); ++ ++ ret = msm_pcie_pm_suspend(dev, NULL, NULL, 0); ++ if (ret) ++ PCIE_ERR(pcie_dev, "PCIe: RC%d got failure in suspend:%d.\n", ++ pcie_dev->rc_idx, ret); ++ ++ mutex_unlock(&pcie_dev->recovery_lock); ++} ++DECLARE_PCI_FIXUP_SUSPEND(PCIE_VENDOR_ID_RCP, PCIE_DEVICE_ID_RCP, ++ msm_pcie_fixup_suspend); ++ ++/* Resume the PCIe link */ ++static int msm_pcie_pm_resume(struct pci_dev *dev, ++ void *user, void *data, u32 options) ++{ ++ int ret; ++ struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev); ++ ++ PCIE_DBG(pcie_dev, "RC%d\n", pcie_dev->rc_idx); ++ ++ spin_lock_irqsave(&pcie_dev->cfg_lock, ++ pcie_dev->irqsave_flags); ++ pcie_dev->cfg_access = true; ++ spin_unlock_irqrestore(&pcie_dev->cfg_lock, ++ pcie_dev->irqsave_flags); ++ ++ ret = msm_pcie_enable(pcie_dev, PM_PIPE_CLK | PM_CLK | PM_VREG); ++ if (ret) { ++ PCIE_ERR(pcie_dev, ++ "PCIe: RC%d fail to enable PCIe link in resume.\n", ++ pcie_dev->rc_idx); ++ return ret; ++ } else { ++ pcie_dev->suspending = false; ++ PCIE_DBG(pcie_dev, ++ "dev->bus->number = %d dev->bus->primary = %d\n", ++ dev->bus->number, dev->bus->primary); ++ ++ if (!(options & MSM_PCIE_CONFIG_NO_CFG_RESTORE)) { ++ pci_load_and_free_saved_state(dev, ++ &pcie_dev->saved_state); ++ pci_restore_state(dev); ++ } ++ } ++ ++ return ret; ++} ++ ++void msm_pcie_fixup_resume(struct pci_dev *dev) ++{ ++ int ret; ++ struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev); ++ ++ PCIE_DBG(pcie_dev, "RC%d\n", pcie_dev->rc_idx); ++ ++ if ((pcie_dev->link_status != MSM_PCIE_LINK_DISABLED) || ++ pcie_dev->user_suspend) ++ return; ++ ++ mutex_lock(&pcie_dev->recovery_lock); ++ ret = msm_pcie_pm_resume(dev, NULL, NULL, 0); ++ if (ret) ++ PCIE_ERR(pcie_dev, ++ "PCIe: RC%d got failure in fixup resume:%d.\n", ++ pcie_dev->rc_idx, ret); ++ ++ mutex_unlock(&pcie_dev->recovery_lock); ++} ++DECLARE_PCI_FIXUP_RESUME(PCIE_VENDOR_ID_RCP, PCIE_DEVICE_ID_RCP, ++ msm_pcie_fixup_resume); ++ ++void msm_pcie_fixup_resume_early(struct pci_dev *dev) ++{ ++ int ret; ++ struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev); ++ ++ PCIE_DBG(pcie_dev, "RC%d\n", pcie_dev->rc_idx); ++ ++ if ((pcie_dev->link_status != MSM_PCIE_LINK_DISABLED) || ++ pcie_dev->user_suspend) ++ return; ++ ++ mutex_lock(&pcie_dev->recovery_lock); ++ ret = msm_pcie_pm_resume(dev, NULL, NULL, 0); ++ if (ret) ++ PCIE_ERR(pcie_dev, "PCIe: RC%d got failure in resume:%d.\n", ++ pcie_dev->rc_idx, ret); ++ ++ mutex_unlock(&pcie_dev->recovery_lock); ++} ++DECLARE_PCI_FIXUP_RESUME_EARLY(PCIE_VENDOR_ID_RCP, PCIE_DEVICE_ID_RCP, ++ msm_pcie_fixup_resume_early); ++ ++static void msm_pcie_fixup_final(struct pci_dev *dev) ++{ ++ struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev); ++ PCIE_DBG(pcie_dev, "RC%d\n", pcie_dev->rc_idx); ++ pcie_drv.current_rc++; ++} ++DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, msm_pcie_fixup_final); ++ ++int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user, ++ void *data, u32 options) ++{ ++ int ret = 0; ++ struct pci_dev *dev; ++ u32 rc_idx = 0; ++ ++ pr_debug("PCIe: pm_opt:%d;busnr:%d;options:%d\n", ++ pm_opt, busnr, options); ++ ++ switch (busnr) { ++ case 1: ++ if (user) { ++ struct msm_pcie_dev_t *pcie_dev ++ = PCIE_BUS_PRIV_DATA(((struct pci_dev *)user)); ++ ++ if (pcie_dev) { ++ rc_idx = pcie_dev->rc_idx; ++ PCIE_DBG(pcie_dev, ++ "PCIe: RC%d: pm_opt:%d;busnr:%d;options:%d\n", ++ rc_idx, pm_opt, busnr, options); ++ } else { ++ pr_err( ++ "PCIe: did not find RC for pci endpoint device 0x%x.\n", ++ (u32)user); ++ ret = -ENODEV; ++ goto out; ++ } ++ } ++ break; ++ default: ++ pr_err("PCIe: unsupported bus number.\n"); ++ ret = PCIBIOS_DEVICE_NOT_FOUND; ++ goto out; ++ } ++ ++ dev = msm_pcie_dev[rc_idx].dev; ++ ++ switch (pm_opt) { ++ case MSM_PCIE_SUSPEND: ++ if (msm_pcie_dev[rc_idx].link_status != MSM_PCIE_LINK_ENABLED) ++ PCIE_DBG(&msm_pcie_dev[rc_idx], ++ "PCIe: RC%d: requested to suspend when link is not enabled:%d.\n", ++ rc_idx, msm_pcie_dev[rc_idx].link_status); ++ ++ if (!msm_pcie_dev[rc_idx].power_on) { ++ PCIE_ERR(&msm_pcie_dev[rc_idx], ++ "PCIe: RC%d: requested to suspend when link is powered down:%d.\n", ++ rc_idx, msm_pcie_dev[rc_idx].link_status); ++ break; ++ } ++ ++ msm_pcie_dev[rc_idx].user_suspend = true; ++ ++ mutex_lock(&msm_pcie_dev[rc_idx].recovery_lock); ++ ++ ret = msm_pcie_pm_suspend(dev, user, data, options); ++ if (ret) { ++ PCIE_ERR(&msm_pcie_dev[rc_idx], ++ "PCIe: RC%d: user failed to suspend the link.\n", ++ rc_idx); ++ msm_pcie_dev[rc_idx].user_suspend = false; ++ } ++ ++ mutex_unlock(&msm_pcie_dev[rc_idx].recovery_lock); ++ break; ++ case MSM_PCIE_RESUME: ++ PCIE_DBG(&msm_pcie_dev[rc_idx], ++ "User of RC%d requests to resume the link\n", rc_idx); ++ if (msm_pcie_dev[rc_idx].link_status != ++ MSM_PCIE_LINK_DISABLED) { ++ PCIE_ERR(&msm_pcie_dev[rc_idx], ++ "PCIe: RC%d: requested to resume when link is not disabled:%d.\n", ++ rc_idx, msm_pcie_dev[rc_idx].link_status); ++ break; ++ } ++ ++ mutex_lock(&msm_pcie_dev[rc_idx].recovery_lock); ++ ret = msm_pcie_pm_resume(dev, user, data, options); ++ if (ret) { ++ PCIE_ERR(&msm_pcie_dev[rc_idx], ++ "PCIe: RC%d: user failed to resume the link.\n", ++ rc_idx); ++ } else { ++ PCIE_DBG(&msm_pcie_dev[rc_idx], ++ "PCIe: RC%d: user succeeded to resume the link.\n", ++ rc_idx); ++ ++ msm_pcie_dev[rc_idx].user_suspend = false; ++ } ++ ++ mutex_unlock(&msm_pcie_dev[rc_idx].recovery_lock); ++ break; ++ case MSM_PCIE_REQ_EXIT_L1: ++ msm_pcie_dev[rc_idx].req_exit_l1_counter++; ++ msm_pcie_write_mask(msm_pcie_dev[rc_idx].parf ++ + PCIE20_PARF_PM_CTRL, ++ 0, BIT(1)); ++ udelay(REQ_EXIT_L1_DELAY_US); ++ msm_pcie_write_mask(msm_pcie_dev[rc_idx].parf ++ + PCIE20_PARF_PM_CTRL, ++ BIT(1), 0); ++ break; ++ default: ++ PCIE_ERR(&msm_pcie_dev[rc_idx], ++ "PCIe: RC%d: unsupported pm operation:%d.\n", ++ rc_idx, pm_opt); ++ ret = -ENODEV; ++ goto out; ++ } ++ ++out: ++ return ret; ++} ++EXPORT_SYMBOL(msm_pcie_pm_control); ++ ++int msm_pcie_register_event(struct msm_pcie_register_event *reg) ++{ ++ int ret = 0; ++ struct msm_pcie_dev_t *pcie_dev; ++ ++ if (!reg) { ++ pr_err("PCIe: Event registration is NULL\n"); ++ return -ENODEV; ++ } ++ ++ if (!reg->user) { ++ pr_err("PCIe: User of event registration is NULL\n"); ++ return -ENODEV; ++ } ++ ++ pcie_dev = PCIE_BUS_PRIV_DATA(((struct pci_dev *)reg->user)); ++ ++ if (pcie_dev) { ++ pcie_dev->event_reg = reg; ++ PCIE_DBG(pcie_dev, ++ "Event 0x%x is registered for RC %d\n", reg->events, ++ pcie_dev->rc_idx); ++ } else { ++ PCIE_ERR(pcie_dev, ++ "PCIe: did not find RC for pci endpoint device 0x%x.\n", ++ (u32)reg->user); ++ ret = -ENODEV; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL(msm_pcie_register_event); ++ ++int msm_pcie_deregister_event(struct msm_pcie_register_event *reg) ++{ ++ int ret = 0; ++ struct msm_pcie_dev_t *pcie_dev; ++ ++ if (!reg) { ++ pr_err("PCIe: Event deregistration is NULL\n"); ++ return -ENODEV; ++ } ++ ++ if (!reg->user) { ++ pr_err("PCIe: User of event deregistration is NULL\n"); ++ return -ENODEV; ++ } ++ ++ pcie_dev = PCIE_BUS_PRIV_DATA(((struct pci_dev *)reg->user)); ++ ++ if (pcie_dev) { ++ pcie_dev->event_reg = NULL; ++ PCIE_DBG(pcie_dev, "Event is deregistered for RC %d\n", ++ pcie_dev->rc_idx); ++ } else { ++ PCIE_ERR(pcie_dev, ++ "PCIe: did not find RC for pci endpoint device 0x%x.\n", ++ (u32)reg->user); ++ ret = -ENODEV; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL(msm_pcie_deregister_event); ++ ++int msm_pcie_recover_config(struct pci_dev *dev) ++{ ++ int ret = 0; ++ struct msm_pcie_dev_t *pcie_dev; ++ ++ if (dev) { ++ pcie_dev = PCIE_BUS_PRIV_DATA(dev); ++ PCIE_DBG(pcie_dev, ++ "Recovery for the link of RC%d\n", pcie_dev->rc_idx); ++ } else { ++ pr_err("PCIe: the input pci dev is NULL.\n"); ++ return -ENODEV; ++ } ++ ++ if (msm_pcie_confirm_linkup(pcie_dev, true, true)) { ++ PCIE_DBG(pcie_dev, ++ "Recover config space of RC%d and its EP\n", ++ pcie_dev->rc_idx); ++ pcie_dev->shadow_en = false; ++ PCIE_DBG(pcie_dev, "Recover RC%d\n", pcie_dev->rc_idx); ++ msm_pcie_cfg_recover(pcie_dev, true); ++ PCIE_DBG(pcie_dev, "Recover EP of RC%d\n", pcie_dev->rc_idx); ++ msm_pcie_cfg_recover(pcie_dev, false); ++ PCIE_DBG(pcie_dev, ++ "Refreshing the saved config space in PCI framework for RC%d and its EP\n", ++ pcie_dev->rc_idx); ++ pci_save_state(pcie_dev->dev); ++ pci_save_state(dev); ++ pcie_dev->shadow_en = true; ++ PCIE_DBG(pcie_dev, "Turn on shadow for RC%d\n", ++ pcie_dev->rc_idx); ++ } else { ++ PCIE_ERR(pcie_dev, ++ "PCIe: the link of RC%d is not up yet; can't recover config space.\n", ++ pcie_dev->rc_idx); ++ ret = -ENODEV; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL(msm_pcie_recover_config); ++ ++int msm_pcie_shadow_control(struct pci_dev *dev, bool enable) ++{ ++ int ret = 0; ++ struct msm_pcie_dev_t *pcie_dev; ++ ++ if (dev) { ++ pcie_dev = PCIE_BUS_PRIV_DATA(dev); ++ PCIE_DBG(pcie_dev, ++ "Recovery for the link of RC%d\n", pcie_dev->rc_idx); ++ } else { ++ pr_err("PCIe: the input pci dev is NULL.\n"); ++ return -ENODEV; ++ } ++ ++ PCIE_DBG(pcie_dev, ++ "The shadowing of RC%d is %s enabled currently.\n", ++ pcie_dev->rc_idx, pcie_dev->shadow_en ? "" : "not"); ++ ++ pcie_dev->shadow_en = enable; ++ ++ PCIE_DBG(pcie_dev, ++ "Shadowing of RC%d is turned %s upon user's request.\n", ++ pcie_dev->rc_idx, enable ? "on" : "off"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(msm_pcie_shadow_control); ++ ++int msm_pcie_access_control(struct pci_dev *dev, bool allow_access) ++{ ++ int ret = 0; ++ struct msm_pcie_dev_t *pcie_dev; ++ ++ if (dev) { ++ pcie_dev = PCIE_BUS_PRIV_DATA(dev); ++ PCIE_DBG(pcie_dev, ++ "access control for the link of RC%d\n", ++ pcie_dev->rc_idx); ++ } else { ++ pr_err("PCIe: the input pci dev is NULL.\n"); ++ return -ENODEV; ++ } ++ ++ mutex_lock(&pcie_dev->recovery_lock); ++ ++ PCIE_DBG(pcie_dev, ++ "The config space of RC%d is %savailable currently.\n", ++ pcie_dev->rc_idx, pcie_dev->cfg_access ? "" : "un"); ++ ++ pcie_dev->cfg_access = allow_access; ++ ++ PCIE_DBG(pcie_dev, ++ "The config space of RC%d becomes %savailable upon user's request.\n", ++ pcie_dev->rc_idx, pcie_dev->cfg_access ? "" : "un"); ++ ++ mutex_unlock(&pcie_dev->recovery_lock); ++ ++ return ret; ++} ++EXPORT_SYMBOL(msm_pcie_access_control); +diff --git a/arch/arm/mach-qcom/pcie.h b/arch/arm/mach-qcom/pcie.h +new file mode 100644 +index 0000000..94c0417 +--- /dev/null ++++ b/arch/arm/mach-qcom/pcie.h +@@ -0,0 +1,329 @@ ++/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __ARCH_ARM_MACH_MSM_PCIE_H ++#define __ARCH_ARM_MACH_MSM_PCIE_H ++ ++#include ++#include ++#ifdef CONFIG_IPC_LOGGING ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++ ++#define MSM_PCIE_MAX_VREG 3 ++#define MSM_PCIE_MAX_CLK 3 ++#define MSM_PCIE_MAX_PIPE_CLK 1 ++ ++#define MAX_RC_NUM 1 ++ ++#ifdef CONFIG_ARM_LPAE ++#define PCIE_UPPER_ADDR(addr) ((u32)((addr) >> 32)) ++#else ++#define PCIE_UPPER_ADDR(addr) (0x0) ++#endif ++#define PCIE_LOWER_ADDR(addr) ((u32)((addr) & 0xffffffff)) ++ ++#define PCIE_MSI_NR_IRQS 256 ++ ++#define PCIE_LOG_PAGES (50) ++ ++#ifdef CONFIG_IPC_LOGGING ++ ++#define PCIE_DBG(dev, fmt, arg...) do { \ ++ if ((dev) && (dev)->ipc_log_long) \ ++ ipc_log_string((dev)->ipc_log_long, \ ++ "DBG1:%s: " fmt, __func__, arg); \ ++ if ((dev) && (dev)->ipc_log) \ ++ ipc_log_string((dev)->ipc_log, "%s: " fmt, __func__, arg); \ ++ if (msm_pcie_get_debug_mask()) \ ++ pr_alert("%s: " fmt, __func__, arg); \ ++ } while (0) ++ ++#define PCIE_DBG2(dev, fmt, arg...) do { \ ++ if ((dev) && (dev)->ipc_log) \ ++ ipc_log_string((dev)->ipc_log, "DBG2:%s: " fmt, __func__, arg);\ ++ if (msm_pcie_get_debug_mask()) \ ++ pr_alert("%s: " fmt, __func__, arg); \ ++ } while (0) ++ ++#define PCIE_DBG3(dev, fmt, arg...) do { \ ++ if ((dev) && (dev)->ipc_log) \ ++ ipc_log_string((dev)->ipc_log, "DBG3:%s: " fmt, __func__, arg);\ ++ if (msm_pcie_get_debug_mask()) \ ++ pr_alert("%s: " fmt, __func__, arg); \ ++ } while (0) ++ ++#define PCIE_INFO(dev, fmt, arg...) do { \ ++ if ((dev) && (dev)->ipc_log_long) \ ++ ipc_log_string((dev)->ipc_log_long, \ ++ "INFO:%s: " fmt, __func__, arg); \ ++ if ((dev) && (dev)->ipc_log) \ ++ ipc_log_string((dev)->ipc_log, "%s: " fmt, __func__, arg); \ ++ pr_info("%s: " fmt, __func__, arg); \ ++ } while (0) ++ ++#define PCIE_ERR(dev, fmt, arg...) do { \ ++ if ((dev) && (dev)->ipc_log_long) \ ++ ipc_log_string((dev)->ipc_log_long, \ ++ "ERR:%s: " fmt, __func__, arg); \ ++ if ((dev) && (dev)->ipc_log) \ ++ ipc_log_string((dev)->ipc_log, "%s: " fmt, __func__, arg); \ ++ pr_err("%s: " fmt, __func__, arg); \ ++ } while (0) ++ ++#else ++ ++#define PCIE_DBG(dev, fmt, arg...) do { \ ++ if (msm_pcie_get_debug_mask()) \ ++ pr_alert("%s: " fmt, __func__, arg); \ ++ } while (0) ++ ++#define PCIE_DBG2(dev, fmt, arg...) do { \ ++ if (msm_pcie_get_debug_mask()) \ ++ pr_alert("%s: " fmt, __func__, arg); \ ++ } while (0) ++ ++#define PCIE_DBG3(dev, fmt, arg...) do { \ ++ if (msm_pcie_get_debug_mask()) \ ++ pr_alert("%s: " fmt, __func__, arg); \ ++ } while (0) ++ ++#define PCIE_INFO(dev, fmt, arg...) do { \ ++ pr_info("%s: " fmt, __func__, arg); \ ++ } while (0) ++ ++#define PCIE_ERR(dev, fmt, arg...) do { \ ++ pr_err("%s: " fmt, __func__, arg); \ ++ } while (0) ++ ++#endif ++ ++#define PCIE_BUS_PRIV_DATA(pdev) \ ++ (((struct pci_sys_data *)pdev->bus->sysdata)->private_data) ++ ++/* PM control options */ ++#define PM_IRQ 0x1 ++#define PM_CLK 0x2 ++#define PM_GPIO 0x4 ++#define PM_VREG 0x8 ++#define PM_PIPE_CLK 0x10 ++#define PM_ALL (PM_IRQ | PM_CLK | PM_GPIO | PM_VREG | PM_PIPE_CLK) ++ ++#define PCIE_CONF_SPACE_DW 1024 ++#define PCIE_CLEAR 0xDEADBEEF ++#define PCIE_LINK_DOWN 0xFFFFFFFF ++ ++enum msm_pcie_res { ++ MSM_PCIE_RES_PARF, ++ MSM_PCIE_RES_PHY, ++ MSM_PCIE_RES_DM_CORE, ++ MSM_PCIE_RES_ELBI, ++ MSM_PCIE_RES_CONF, ++ MSM_PCIE_RES_IO, ++ MSM_PCIE_RES_BARS, ++ MSM_PCIE_MAX_RES, ++}; ++ ++enum msm_pcie_rst { ++ MSM_PCIE_AXI_M_ARES, ++ MSM_PCIE_AXI_S_ARES, ++ MSM_PCIE_PIPE_ARES, ++ MSM_PCIE_AXI_M_VMIDMT_ARES, ++ MSM_PCIE_AXI_S_XPU_ARES, ++ MSM_PCIE_PARF_XPU_ARES, ++ MSM_PCIE_PHY_ARES, ++ MSM_PCIE_AXI_M_STICKY_ARES, ++ MSM_PCIE_PIPE_STICKY_ARES, ++ MSM_PCIE_PWR_ARES, ++ MSM_PCIE_AHB_ARES, ++ MSM_PCIE_PHY_AHB_ARES, ++ MSM_PCIE_MAX_RESET, ++}; ++ ++enum msm_pcie_irq { ++ MSM_PCIE_INT_MSI, ++ MSM_PCIE_INT_A, ++ MSM_PCIE_INT_B, ++ MSM_PCIE_INT_C, ++ MSM_PCIE_INT_D, ++ MSM_PCIE_INT_PLS_PME, ++ MSM_PCIE_INT_PME_LEGACY, ++ MSM_PCIE_INT_PLS_ERR, ++ MSM_PCIE_INT_AER_LEGACY, ++ MSM_PCIE_INT_LINK_UP, ++ MSM_PCIE_INT_LINK_DOWN, ++ MSM_PCIE_INT_BRIDGE_FLUSH_N, ++ MSM_PCIE_INT_WAKE, ++ MSM_PCIE_MAX_IRQ, ++}; ++ ++/* gpios */ ++enum msm_pcie_gpio { ++ MSM_PCIE_GPIO_PERST, ++ MSM_PCIE_GPIO_WAKE, ++ MSM_PCIE_GPIO_CLKREQ, ++ MSM_PCIE_MAX_GPIO ++}; ++ ++enum msm_pcie_link_status { ++ MSM_PCIE_LINK_DEINIT, ++ MSM_PCIE_LINK_ENABLED, ++ MSM_PCIE_LINK_DISABLED ++}; ++ ++/* gpio info structure */ ++struct msm_pcie_gpio_info_t { ++ char *name; ++ uint32_t num; ++ bool out; ++ uint32_t on; ++ uint32_t init; ++}; ++ ++/* voltage regulator info structrue */ ++struct msm_pcie_vreg_info_t { ++ struct regulator *hdl; ++ char *name; ++ uint32_t max_v; ++ uint32_t min_v; ++ uint32_t opt_mode; ++ bool required; ++}; ++ ++/* reset info structure */ ++struct msm_pcie_rst_info_t { ++ struct reset_control *hdl; ++ char *name; ++}; ++ ++/* clock info structure */ ++struct msm_pcie_clk_info_t { ++ struct clk *hdl; ++ char *name; ++ u32 freq; ++ bool required; ++}; ++ ++/* resource info structure */ ++struct msm_pcie_res_info_t { ++ char *name; ++ struct resource *resource; ++ void __iomem *base; ++}; ++ ++/* irq info structrue */ ++struct msm_pcie_irq_info_t { ++ char *name; ++ uint32_t num; ++}; ++ ++/* msm pcie device structure */ ++struct msm_pcie_dev_t { ++ struct platform_device *pdev; ++ struct pci_dev *dev; ++ struct msi_controller *msi_chip; ++ struct regulator *gdsc; ++ struct msm_pcie_vreg_info_t vreg[MSM_PCIE_MAX_VREG]; ++ struct msm_pcie_gpio_info_t gpio[MSM_PCIE_MAX_GPIO]; ++ struct msm_pcie_clk_info_t clk[MSM_PCIE_MAX_CLK]; ++ struct msm_pcie_res_info_t res[MSM_PCIE_MAX_RES]; ++ struct msm_pcie_irq_info_t irq[MSM_PCIE_MAX_IRQ]; ++ struct msm_pcie_rst_info_t rst[MSM_PCIE_MAX_RESET]; ++ ++ void __iomem *parf; ++ void __iomem *phy; ++ void __iomem *elbi; ++ void __iomem *dm_core; ++ void __iomem *conf; ++ void __iomem *bars; ++ ++ uint32_t axi_bar_start; ++ uint32_t axi_bar_end; ++ ++ struct resource *dev_mem_res; ++ struct resource *dev_io_res; ++ ++ uint32_t wake_n; ++ uint32_t vreg_n; ++ uint32_t gpio_n; ++ uint32_t parf_deemph; ++ uint32_t parf_swing; ++ ++ bool cfg_access; ++ spinlock_t cfg_lock; ++ unsigned long irqsave_flags; ++ struct mutex setup_lock; ++ ++ struct irq_domain *irq_domain; ++ DECLARE_BITMAP(msi_irq_in_use, PCIE_MSI_NR_IRQS); ++ uint32_t msi_gicm_addr; ++ uint32_t msi_gicm_base; ++ bool use_msi; ++ bool is_emulation; ++ ++ enum msm_pcie_link_status link_status; ++ bool user_suspend; ++ struct pci_saved_state *saved_state; ++ ++ struct wakeup_source ws; ++ struct msm_bus_scale_pdata *bus_scale_table; ++ uint32_t bus_client; ++ ++ bool l1ss_supported; ++ bool aux_clk_sync; ++ uint32_t n_fts; ++ bool ext_ref_clk; ++ uint32_t ep_latency; ++ bool ep_wakeirq; ++ ++ uint32_t rc_idx; ++ bool enumerated; ++ struct work_struct handle_wake_work; ++ struct mutex recovery_lock; ++ spinlock_t linkdown_lock; ++ spinlock_t wakeup_lock; ++ ulong linkdown_counter; ++ bool suspending; ++ ulong wake_counter; ++ ulong req_exit_l1_counter; ++ u32 ep_shadow[PCIE_CONF_SPACE_DW]; ++ u32 rc_shadow[PCIE_CONF_SPACE_DW]; ++ bool shadow_en; ++ struct msm_pcie_register_event *event_reg; ++ bool power_on; ++ void *ipc_log; ++ void *ipc_log_long; ++ struct pci_bus *pci_bus; ++}; ++ ++extern int msm_pcie_enumerate(u32 rc_idx); ++extern int msm_pcie_enable(struct msm_pcie_dev_t *dev, u32 options); ++extern void msm_pcie_disable(struct msm_pcie_dev_t *dev, u32 options); ++extern void msm_pcie_cfg_recover(struct msm_pcie_dev_t *dev, bool rc); ++extern void msm_pcie_config_msi_controller(struct msm_pcie_dev_t *dev); ++extern int32_t msm_pcie_irq_init(struct msm_pcie_dev_t *dev); ++extern void msm_pcie_irq_deinit(struct msm_pcie_dev_t *dev); ++extern int msm_pcie_get_debug_mask(void); ++extern bool msm_pcie_confirm_linkup(struct msm_pcie_dev_t *dev, ++ bool check_sw_stts, bool check_ep); ++ ++extern void pcie_phy_init(struct msm_pcie_dev_t *dev); ++extern bool pcie_phy_is_ready(struct msm_pcie_dev_t *dev); ++extern void pcie20_uni_phy_init(struct msm_pcie_dev_t *dev); ++extern bool pcie_phy_detect(struct msm_pcie_dev_t *dev); ++ ++#endif +diff --git a/arch/arm/mach-qcom/pcie_irq.c b/arch/arm/mach-qcom/pcie_irq.c +new file mode 100644 +index 0000000..ae21d05 +--- /dev/null ++++ b/arch/arm/mach-qcom/pcie_irq.c +@@ -0,0 +1,598 @@ ++/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++/* ++ * MSM PCIe controller IRQ driver. ++ */ ++ ++#define pr_fmt(fmt) "%s: " fmt, __func__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "pcie.h" ++ ++/* Any address will do here, as it won't be dereferenced */ ++#define MSM_PCIE_MSI_PHY 0xa0000000 ++ ++#define PCIE20_MSI_CTRL_ADDR (0x820) ++#define PCIE20_MSI_CTRL_UPPER_ADDR (0x824) ++#define PCIE20_MSI_CTRL_INTR_EN (0x828) ++#define PCIE20_MSI_CTRL_INTR_MASK (0x82C) ++#define PCIE20_MSI_CTRL_INTR_STATUS (0x830) ++ ++#define PCIE20_MSI_CTRL_MAX 8 ++ ++#define LINKDOWN_INIT_WAITING_US_MIN 995 ++#define LINKDOWN_INIT_WAITING_US_MAX 1005 ++#define LINKDOWN_WAITING_US_MIN 4900 ++#define LINKDOWN_WAITING_US_MAX 5100 ++#define LINKDOWN_WAITING_COUNT 200 ++ ++static void msm_pcie_notify_client(struct msm_pcie_dev_t *dev, ++ enum msm_pcie_event event) ++{ ++ if (dev->event_reg && dev->event_reg->callback && ++ (dev->event_reg->events & event)) { ++ struct msm_pcie_notify *notify = &dev->event_reg->notify; ++ notify->event = event; ++ notify->user = dev->event_reg->user; ++ PCIE_DBG(dev, "PCIe: callback RC%d for event %d.\n", ++ dev->rc_idx, event); ++ dev->event_reg->callback(notify); ++ ++ if ((dev->event_reg->options & MSM_PCIE_CONFIG_NO_RECOVERY) && ++ (event == MSM_PCIE_EVENT_LINKDOWN)) { ++ dev->user_suspend = true; ++ PCIE_DBG(dev, ++ "PCIe: Client of RC%d will recover the link later.\n", ++ dev->rc_idx); ++ return; ++ } ++ } else { ++ PCIE_DBG2(dev, ++ "PCIe: Client of RC%d does not have registration for event %d.\n", ++ dev->rc_idx, event); ++ } ++} ++ ++static void handle_wake_func(struct work_struct *work) ++{ ++ int ret; ++ struct msm_pcie_dev_t *dev = container_of(work, struct msm_pcie_dev_t, ++ handle_wake_work); ++ ++ PCIE_DBG(dev, "PCIe: Wake work for RC%d\n", dev->rc_idx); ++ ++ mutex_lock(&dev->recovery_lock); ++ ++ if (!dev->enumerated) { ++ PCIE_DBG(dev, ++ "PCIe: Start enumeration for RC%d upon the wake from endpoint.\n", ++ dev->rc_idx); ++ ++ ret = msm_pcie_enumerate(dev->rc_idx); ++ ++ if (ret) { ++ PCIE_ERR(dev, ++ "PCIe: failed to enable RC%d upon wake request from the device.\n", ++ dev->rc_idx); ++ goto out; ++ } ++ ++ if ((dev->link_status == MSM_PCIE_LINK_ENABLED) && ++ dev->event_reg && dev->event_reg->callback && ++ (dev->event_reg->events & MSM_PCIE_EVENT_LINKUP)) { ++ struct msm_pcie_notify *notify = ++ &dev->event_reg->notify; ++ notify->event = MSM_PCIE_EVENT_LINKUP; ++ notify->user = dev->event_reg->user; ++ PCIE_DBG(dev, ++ "PCIe: Linkup callback for RC%d after enumeration is successful in wake IRQ handling\n", ++ dev->rc_idx); ++ dev->event_reg->callback(notify); ++ } else { ++ PCIE_DBG(dev, ++ "PCIe: Client of RC%d does not have registration for linkup event.\n", ++ dev->rc_idx); ++ } ++ goto out; ++ } else { ++ PCIE_ERR(dev, ++ "PCIe: The enumeration for RC%d has already been done.\n", ++ dev->rc_idx); ++ goto out; ++ } ++ ++out: ++ mutex_unlock(&dev->recovery_lock); ++} ++ ++static irqreturn_t handle_wake_irq(int irq, void *data) ++{ ++ struct msm_pcie_dev_t *dev = data; ++ unsigned long irqsave_flags; ++ ++ spin_lock_irqsave(&dev->wakeup_lock, irqsave_flags); ++ ++ dev->wake_counter++; ++ PCIE_DBG(dev, "PCIe: No. %ld wake IRQ for RC%d\n", ++ dev->wake_counter, dev->rc_idx); ++ ++ PCIE_DBG2(dev, "PCIe WAKE is asserted by Endpoint of RC%d\n", ++ dev->rc_idx); ++ ++ if (!dev->enumerated) { ++ PCIE_DBG(dev, "Start enumeating RC%d\n", dev->rc_idx); ++ schedule_work(&dev->handle_wake_work); ++ } else { ++ PCIE_DBG2(dev, "Wake up RC%d\n", dev->rc_idx); ++ __pm_stay_awake(&dev->ws); ++ __pm_relax(&dev->ws); ++ msm_pcie_notify_client(dev, MSM_PCIE_EVENT_WAKEUP); ++ } ++ ++ spin_unlock_irqrestore(&dev->wakeup_lock, irqsave_flags); ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t handle_linkdown_irq(int irq, void *data) ++{ ++ struct msm_pcie_dev_t *dev = data; ++ unsigned long irqsave_flags; ++ ++ spin_lock_irqsave(&dev->linkdown_lock, irqsave_flags); ++ ++ dev->linkdown_counter++; ++ PCIE_DBG(dev, ++ "PCIe: No. %ld linkdown IRQ for RC%d.\n", ++ dev->linkdown_counter, dev->rc_idx); ++ ++ if (!dev->enumerated || dev->link_status != MSM_PCIE_LINK_ENABLED) { ++ PCIE_DBG(dev, ++ "PCIe:Linkdown IRQ for RC%d when the link is not enabled\n", ++ dev->rc_idx); ++ } else if (dev->suspending) { ++ PCIE_DBG(dev, ++ "PCIe:the link of RC%d is suspending.\n", ++ dev->rc_idx); ++ } else { ++ dev->link_status = MSM_PCIE_LINK_DISABLED; ++ dev->shadow_en = false; ++ /* assert PERST */ ++ gpio_set_value(dev->gpio[MSM_PCIE_GPIO_PERST].num, ++ dev->gpio[MSM_PCIE_GPIO_PERST].on); ++ PCIE_ERR(dev, "PCIe link is down for RC%d\n", dev->rc_idx); ++ msm_pcie_notify_client(dev, MSM_PCIE_EVENT_LINKDOWN); ++ } ++ ++ spin_unlock_irqrestore(&dev->linkdown_lock, irqsave_flags); ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t handle_msi_irq(int irq, void *data) ++{ ++ int i, j; ++ unsigned long val; ++ struct msm_pcie_dev_t *dev = data; ++ void __iomem *ctrl_status; ++ ++ PCIE_DBG(dev, "irq=%d\n", irq); ++ ++ /* check for set bits, clear it by setting that bit ++ and trigger corresponding irq */ ++ for (i = 0; i < PCIE20_MSI_CTRL_MAX; i++) { ++ ctrl_status = dev->dm_core + ++ PCIE20_MSI_CTRL_INTR_STATUS + (i * 12); ++ ++ val = readl_relaxed(ctrl_status); ++ while (val) { ++ j = find_first_bit(&val, 32); ++ writel_relaxed(BIT(j), ctrl_status); ++ /* ensure that interrupt is cleared (acked) */ ++ wmb(); ++ generic_handle_irq( ++ irq_find_mapping(dev->irq_domain, (j + (32*i))) ++ ); ++ val = readl_relaxed(ctrl_status); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++void msm_pcie_config_msi_controller(struct msm_pcie_dev_t *dev) ++{ ++ int i; ++ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++ /* program MSI controller and enable all interrupts */ ++ writel_relaxed(MSM_PCIE_MSI_PHY, dev->dm_core + PCIE20_MSI_CTRL_ADDR); ++ writel_relaxed(0, dev->dm_core + PCIE20_MSI_CTRL_UPPER_ADDR); ++ ++ for (i = 0; i < PCIE20_MSI_CTRL_MAX; i++) ++ writel_relaxed(~0, dev->dm_core + ++ PCIE20_MSI_CTRL_INTR_EN + (i * 12)); ++ ++ /* ensure that hardware is configured before proceeding */ ++ wmb(); ++} ++ ++void msm_pcie_destroy_irq(unsigned int irq, struct msm_pcie_dev_t *pcie_dev) ++{ ++ int pos; ++ struct msm_pcie_dev_t *dev; ++ ++ if (pcie_dev) { ++ dev = pcie_dev; ++ } else { ++ dev = irq_get_chip_data(irq); ++ if (!dev) ++ return; ++ } ++ ++ if (dev->msi_gicm_addr) { ++ PCIE_DBG(dev, "destroy QGIC based irq %d\n", irq); ++ pos = irq - dev->msi_gicm_base; ++ } else { ++ PCIE_DBG(dev, "destroy default MSI irq %d\n", irq); ++ pos = irq - irq_find_mapping(dev->irq_domain, 0); ++ } ++ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++ if (!dev->msi_gicm_addr) ++ irq_dispose_mapping(irq); ++ ++ PCIE_DBG(dev, "Before clear_bit pos:%d msi_irq_in_use:%ld\n", ++ pos, *dev->msi_irq_in_use); ++ clear_bit(pos, dev->msi_irq_in_use); ++ PCIE_DBG(dev, "After clear_bit pos:%d msi_irq_in_use:%ld\n", ++ pos, *dev->msi_irq_in_use); ++} ++ ++/* hookup to linux pci msi framework */ ++void msm_pcie_teardown_msi_irq(struct msi_controller *chip, unsigned int irq) ++{ ++ pr_debug("irq %d deallocated\n", irq); ++ msm_pcie_destroy_irq(irq, NULL); ++} ++ ++#if 0 ++void msm_pcie_teardown_msi_irqs(struct pci_dev *dev) ++{ ++ struct msi_desc *entry; ++ struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev); ++ ++ PCIE_DBG(pcie_dev, "RC:%d EP: vendor_id:0x%x device_id:0x%x\n", ++ pcie_dev->rc_idx, dev->vendor, dev->device); ++ ++ pcie_dev->use_msi = false; ++ ++ list_for_each_entry(entry, &dev->msi_list, list) { ++ int i, nvec; ++ if (entry->irq == 0) ++ continue; ++ nvec = 1 << entry->msi_attrib.multiple; ++ for (i = 0; i < nvec; i++) ++ msm_pcie_destroy_irq(entry->irq + i, pcie_dev); ++ } ++} ++#endif ++ ++static void msm_pcie_msi_nop(struct irq_data *d) ++{ ++ return; ++} ++ ++static struct irq_chip pcie_msi_chip = { ++ .name = "msm-pcie-msi", ++ .irq_ack = msm_pcie_msi_nop, ++ .irq_enable = unmask_msi_irq, ++ .irq_disable = mask_msi_irq, ++ .irq_mask = mask_msi_irq, ++ .irq_unmask = unmask_msi_irq, ++}; ++ ++static int msm_pcie_create_irq(struct msm_pcie_dev_t *dev) ++{ ++ int irq, pos; ++ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++again: ++ pos = find_first_zero_bit(dev->msi_irq_in_use, PCIE_MSI_NR_IRQS); ++ ++ if (pos >= PCIE_MSI_NR_IRQS) ++ return -ENOSPC; ++ ++ PCIE_DBG(dev, "pos:%d msi_irq_in_use:%ld\n", pos, *dev->msi_irq_in_use); ++ ++ if (test_and_set_bit(pos, dev->msi_irq_in_use)) ++ goto again; ++ else ++ PCIE_DBG(dev, "test_and_set_bit is successful pos=%d\n", pos); ++ ++ irq = irq_create_mapping(dev->irq_domain, pos); ++ if (!irq) ++ return -EINVAL; ++ ++ return irq; ++} ++ ++static int arch_setup_msi_irq_default(struct pci_dev *pdev, ++ struct msi_desc *desc, int nvec) ++{ ++ int irq; ++ struct msi_msg msg; ++ struct msm_pcie_dev_t *dev = PCIE_BUS_PRIV_DATA(pdev); ++ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++ irq = msm_pcie_create_irq(dev); ++ ++ PCIE_DBG(dev, "IRQ %d is allocated.\n", irq); ++ ++ if (irq < 0) ++ return irq; ++ ++ PCIE_DBG(dev, "irq %d allocated\n", irq); ++ ++ irq_set_msi_desc(irq, desc); ++ ++ /* write msi vector and data */ ++ msg.address_hi = 0; ++ msg.address_lo = MSM_PCIE_MSI_PHY; ++ msg.data = irq - irq_find_mapping(dev->irq_domain, 0); ++ write_msi_msg(irq, &msg); ++ ++ return 0; ++} ++ ++static int msm_pcie_create_irq_qgic(struct msm_pcie_dev_t *dev) ++{ ++ int irq, pos; ++ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++again: ++ pos = find_first_zero_bit(dev->msi_irq_in_use, PCIE_MSI_NR_IRQS); ++ ++ if (pos >= PCIE_MSI_NR_IRQS) ++ return -ENOSPC; ++ ++ PCIE_DBG(dev, "pos:%d msi_irq_in_use:%ld\n", pos, *dev->msi_irq_in_use); ++ ++ if (test_and_set_bit(pos, dev->msi_irq_in_use)) ++ goto again; ++ else ++ PCIE_DBG(dev, "test_and_set_bit is successful pos=%d\n", pos); ++ ++ irq = dev->msi_gicm_base + pos; ++ if (!irq) { ++ PCIE_ERR(dev, "PCIe: RC%d failed to create QGIC MSI IRQ.\n", ++ dev->rc_idx); ++ return -EINVAL; ++ } ++ ++ return irq; ++} ++ ++static int arch_setup_msi_irq_qgic(struct pci_dev *pdev, ++ struct msi_desc *desc, int nvec) ++{ ++ int irq, index, firstirq = 0; ++ struct msi_msg msg; ++ struct msm_pcie_dev_t *dev = PCIE_BUS_PRIV_DATA(pdev); ++ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++ for (index = 0; index < nvec; index++) { ++ irq = msm_pcie_create_irq_qgic(dev); ++ PCIE_DBG(dev, "irq %d is allocated\n", irq); ++ ++ if (irq < 0) ++ return irq; ++ ++ if (index == 0) ++ firstirq = irq; ++ ++ irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING); ++ } ++ ++ /* write msi vector and data */ ++ irq_set_msi_desc(firstirq, desc); ++ msg.address_hi = 0; ++ msg.address_lo = dev->msi_gicm_addr; ++ msg.data = firstirq; ++ write_msi_msg(firstirq, &msg); ++ ++ return 0; ++} ++ ++int msm_pcie_setup_msi_irq(struct msi_controller *chip, struct pci_dev *pdev, ++ struct msi_desc *desc) ++{ ++ struct msm_pcie_dev_t *dev = PCIE_BUS_PRIV_DATA(pdev); ++ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++ if (dev->msi_gicm_addr) ++ return arch_setup_msi_irq_qgic(pdev, desc, 1); ++ else ++ return arch_setup_msi_irq_default(pdev, desc, 1); ++} ++ ++#if 0 ++static int msm_pcie_get_msi_multiple(int nvec) ++{ ++ int msi_multiple = 0; ++ ++ while (nvec) { ++ nvec = nvec >> 1; ++ msi_multiple++; ++ } ++ pr_debug("log2 number of MSI multiple:%d\n", ++ msi_multiple - 1); ++ ++ return msi_multiple - 1; ++} ++ ++int msm_pcie_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) ++{ ++ struct msi_desc *entry; ++ int ret; ++ struct msm_pcie_dev_t *pcie_dev = PCIE_BUS_PRIV_DATA(dev); ++ ++ PCIE_DBG(pcie_dev, "RC%d\n", pcie_dev->rc_idx); ++ ++ if (type != PCI_CAP_ID_MSI || nvec > 32) ++ return -ENOSPC; ++ ++ PCIE_DBG(pcie_dev, "nvec = %d\n", nvec); ++ ++ list_for_each_entry(entry, &dev->msi_list, list) { ++ entry->msi_attrib.multiple = ++ msm_pcie_get_msi_multiple(nvec); ++ ++ if (pcie_dev->msi_gicm_addr) ++ ret = arch_setup_msi_irq_qgic(dev, entry, nvec); ++ else ++ ret = arch_setup_msi_irq_default(dev, entry, nvec); ++ ++ PCIE_DBG(pcie_dev, "ret from msi_irq: %d\n", ret); ++ ++ if (ret < 0) ++ return ret; ++ if (ret > 0) ++ return -ENOSPC; ++ } ++ ++ pcie_dev->use_msi = true; ++ ++ return 0; ++} ++#endif ++ ++static int msm_pcie_msi_map(struct irq_domain *domain, unsigned int irq, ++ irq_hw_number_t hwirq) ++{ ++ irq_set_chip_and_handler (irq, &pcie_msi_chip, handle_simple_irq); ++ irq_set_chip_data(irq, domain->host_data); ++ //set_irq_flags(irq, IRQF_VALID); ++ return 0; ++} ++ ++static const struct irq_domain_ops msm_pcie_msi_ops = { ++ .map = msm_pcie_msi_map, ++}; ++ ++int32_t msm_pcie_irq_init(struct msm_pcie_dev_t *dev) ++{ ++ int rc; ++ int msi_start = 0; ++ struct device *pdev = &dev->pdev->dev; ++ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++ dev->msi_chip = kzalloc(sizeof(struct msi_controller), GFP_KERNEL); ++ if (!dev->msi_chip) ++ return -ENOMEM; ++ ++ dev->msi_chip->setup_irq = msm_pcie_setup_msi_irq; ++ dev->msi_chip->teardown_irq = msm_pcie_teardown_msi_irq; ++ ++ if (dev->ep_wakeirq) ++ wakeup_source_init(&dev->ws, "pcie_wakeup_source"); ++ ++ /* register handler for linkdown interrupt */ ++ rc = devm_request_irq(pdev, ++ dev->irq[MSM_PCIE_INT_LINK_DOWN].num, handle_linkdown_irq, ++ IRQF_TRIGGER_RISING, dev->irq[MSM_PCIE_INT_LINK_DOWN].name, ++ dev); ++ if (rc) { ++ PCIE_ERR(dev, "PCIe: Unable to request linkdown interrupt:%d\n", ++ dev->irq[MSM_PCIE_INT_LINK_DOWN].num); ++ return rc; ++ } ++ ++ /* register handler for physical MSI interrupt line */ ++ rc = devm_request_irq(pdev, ++ dev->irq[MSM_PCIE_INT_MSI].num, handle_msi_irq, ++ IRQF_TRIGGER_RISING, dev->irq[MSM_PCIE_INT_MSI].name, dev); ++ if (rc) { ++ PCIE_ERR(dev, "PCIe: RC%d: Unable to request MSI interrupt\n", ++ dev->rc_idx); ++ return rc; ++ } ++ ++ if (dev->ep_wakeirq) { ++ /* register handler for PCIE_WAKE_N interrupt line */ ++ rc = devm_request_irq(pdev, ++ dev->wake_n, handle_wake_irq, IRQF_TRIGGER_FALLING, ++ "msm_pcie_wake", dev); ++ if (rc) { ++ PCIE_ERR(dev, "PCIe: RC%d: Unable to request wake interrupt\n", ++ dev->rc_idx); ++ return rc; ++ } ++ ++ INIT_WORK(&dev->handle_wake_work, handle_wake_func); ++ ++ rc = enable_irq_wake(dev->wake_n); ++ if (rc) { ++ PCIE_ERR(dev, "PCIe: RC%d: Unable to enable wake interrupt\n", ++ dev->rc_idx); ++ return rc; ++ } ++ } ++ ++ /* Create a virtual domain of interrupts */ ++ if (!dev->msi_gicm_addr) { ++ dev->irq_domain = irq_domain_add_linear(dev->pdev->dev.of_node, ++ PCIE_MSI_NR_IRQS, &msm_pcie_msi_ops, dev); ++ ++ if (!dev->irq_domain) { ++ PCIE_ERR(dev, ++ "PCIe: RC%d: Unable to initialize irq domain\n", ++ dev->rc_idx); ++ disable_irq(dev->wake_n); ++ return PTR_ERR(dev->irq_domain); ++ } ++ ++ msi_start = irq_create_mapping(dev->irq_domain, 0); ++ } ++ ++ return 0; ++} ++ ++void msm_pcie_irq_deinit(struct msm_pcie_dev_t *dev) ++{ ++ PCIE_DBG(dev, "RC%d\n", dev->rc_idx); ++ ++ kfree(dev->msi_chip); ++ ++ if (dev->ep_wakeirq) { ++ wakeup_source_trash(&dev->ws); ++ disable_irq(dev->wake_n); ++ } ++} +diff --git a/arch/arm/mach-qcom/pcie_phy.c b/arch/arm/mach-qcom/pcie_phy.c +new file mode 100644 +index 0000000..32f3c79 +--- /dev/null ++++ b/arch/arm/mach-qcom/pcie_phy.c +@@ -0,0 +1,403 @@ ++/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++/* ++ * MSM PCIe PHY driver. ++ */ ++ ++#include ++#include ++#include "pcie.h" ++#include "pcie_phy.h" ++ ++#define MDIO_CTRL_0_REG 0x40 ++#define MDIO_CTRL_1_REG 0x44 ++#define MDIO_CTRL_2_REG 0x48 ++#define MDIO_CTRL_3_REG 0x4C ++#define MDIO_CTRL_4_REG 0x50 ++ ++#define MDIO_PCIE_PHY_ID (0x5 << 13) ++#define MDC_MODE (0x1 << 12) ++#define MDIO_CLAUSE_22 (0x0 << 8) ++#define MDIO_CLAUSE_45 (0x1 << 8) ++#define MDIO_PCIE_CLK_DIV (0xF) ++#define MDIO_MMD_ID (0x1) ++ ++#define MDIO_ACCESS_BUSY (0x1 << 16) ++#define MDIO_ACCESS_START (0x1 << 8) ++#define MDIO_TIMEOUT_STATIC 1000 ++ ++#define MDIO_ACCESS_22_WRITE (0x1) ++#define MDIO_ACCESS_22_READ (0x0) ++#define MDIO_ACCESS_45_WRITE (0x2) ++#define MDIO_ACCESS_45_READ (0x1) ++#define MDIO_ACCESS_45_READ_ADDR (0x0) ++ ++static inline void write_phy(void *base, u32 offset, u32 value) ++{ ++ writel_relaxed(value, base + offset); ++ wmb(); ++} ++ ++#ifndef CONFIG_ARCH_MDM9630 ++static inline void pcie20_phy_init_default(struct msm_pcie_dev_t *dev) ++{ ++ ++ PCIE_DBG(dev, "RC%d: Initializing 28nm QMP phy - 19.2MHz\n", ++ dev->rc_idx); ++ ++ write_phy(dev->phy, PCIE_PHY_POWER_DOWN_CONTROL, 0x03); ++ write_phy(dev->phy, QSERDES_COM_SYSCLK_EN_SEL, 0x08); ++ write_phy(dev->phy, QSERDES_COM_DEC_START1, 0x82); ++ write_phy(dev->phy, QSERDES_COM_DEC_START2, 0x03); ++ write_phy(dev->phy, QSERDES_COM_DIV_FRAC_START1, 0xd5); ++ write_phy(dev->phy, QSERDES_COM_DIV_FRAC_START2, 0xaa); ++ write_phy(dev->phy, QSERDES_COM_DIV_FRAC_START3, 0x13); ++ write_phy(dev->phy, QSERDES_COM_PLLLOCK_CMP_EN, 0x01); ++ write_phy(dev->phy, QSERDES_COM_PLLLOCK_CMP1, 0x2b); ++ write_phy(dev->phy, QSERDES_COM_PLLLOCK_CMP2, 0x68); ++ write_phy(dev->phy, QSERDES_COM_PLL_CRCTRL, 0xff); ++ write_phy(dev->phy, QSERDES_COM_PLL_CP_SETI, 0x3f); ++ write_phy(dev->phy, QSERDES_COM_PLL_IP_SETP, 0x07); ++ write_phy(dev->phy, QSERDES_COM_PLL_CP_SETP, 0x03); ++ write_phy(dev->phy, QSERDES_RX_CDR_CONTROL, 0xf3); ++ write_phy(dev->phy, QSERDES_RX_CDR_CONTROL2, 0x6b); ++ write_phy(dev->phy, QSERDES_COM_RESETSM_CNTRL, 0x10); ++ write_phy(dev->phy, QSERDES_RX_RX_TERM_HIGHZ_CM_AC_COUPLE, 0x87); ++ write_phy(dev->phy, QSERDES_RX_RX_EQ_GAIN12, 0x54); ++ write_phy(dev->phy, PCIE_PHY_POWER_STATE_CONFIG1, 0xa3); ++ write_phy(dev->phy, PCIE_PHY_POWER_STATE_CONFIG2, 0xcb); ++ write_phy(dev->phy, QSERDES_COM_PLL_RXTXEPCLK_EN, 0x10); ++ write_phy(dev->phy, PCIE_PHY_ENDPOINT_REFCLK_DRIVE, 0x10); ++ write_phy(dev->phy, PCIE_PHY_SW_RESET, 0x00); ++ write_phy(dev->phy, PCIE_PHY_START, 0x03); ++} ++#endif ++ ++#ifdef CONFIG_ARCH_MDM9630 ++void pcie_phy_init(struct msm_pcie_dev_t *dev) ++{ ++ ++ PCIE_DBG(dev, "RC%d: Initializing 28nm QMP phy - 19.2MHz\n", ++ dev->rc_idx); ++ ++ write_phy(dev->phy, PCIE_PHY_POWER_DOWN_CONTROL, 0x03); ++ ++ write_phy(dev->phy, QSERDES_COM_SYSCLK_EN_SEL_TXBAND, 0x08); ++ write_phy(dev->phy, QSERDES_COM_DEC_START1, 0x82); ++ write_phy(dev->phy, QSERDES_COM_DEC_START2, 0x03); ++ write_phy(dev->phy, QSERDES_COM_DIV_FRAC_START1, 0xD5); ++ write_phy(dev->phy, QSERDES_COM_DIV_FRAC_START2, 0xAA); ++ write_phy(dev->phy, QSERDES_COM_DIV_FRAC_START3, 0x4D); ++ write_phy(dev->phy, QSERDES_COM_PLLLOCK_CMP_EN, 0x01); ++ write_phy(dev->phy, QSERDES_COM_PLLLOCK_CMP1, 0x2B); ++ write_phy(dev->phy, QSERDES_COM_PLLLOCK_CMP2, 0x68); ++ write_phy(dev->phy, QSERDES_COM_PLL_CRCTRL, 0x7C); ++ write_phy(dev->phy, QSERDES_COM_PLL_CP_SETI, 0x02); ++ write_phy(dev->phy, QSERDES_COM_PLL_IP_SETP, 0x1F); ++ write_phy(dev->phy, QSERDES_COM_PLL_CP_SETP, 0x0F); ++ write_phy(dev->phy, QSERDES_COM_PLL_IP_SETI, 0x01); ++ write_phy(dev->phy, QSERDES_COM_IE_TRIM, 0x0F); ++ write_phy(dev->phy, QSERDES_COM_IP_TRIM, 0x0F); ++ write_phy(dev->phy, QSERDES_COM_PLL_CNTRL, 0x46); ++ ++ /* CDR Settings */ ++ write_phy(dev->phy, QSERDES_RX_CDR_CONTROL1, 0xF3); ++ write_phy(dev->phy, QSERDES_RX_CDR_CONTROL_HALF, 0x2B); ++ ++ write_phy(dev->phy, QSERDES_COM_PLL_VCOTAIL_EN, 0xE1); ++ ++ /* Calibration Settings */ ++ write_phy(dev->phy, QSERDES_COM_RESETSM_CNTRL, 0x90); ++ write_phy(dev->phy, QSERDES_COM_RESETSM_CNTRL2, 0x7); ++ ++ /* Additional writes */ ++ write_phy(dev->phy, QSERDES_COM_RES_CODE_START_SEG1, 0x20); ++ write_phy(dev->phy, QSERDES_COM_RES_CODE_CAL_CSR, 0x77); ++ write_phy(dev->phy, QSERDES_COM_RES_TRIM_CONTROL, 0x15); ++ write_phy(dev->phy, QSERDES_TX_RCV_DETECT_LVL, 0x03); ++ write_phy(dev->phy, QSERDES_RX_RX_EQ_GAIN1_LSB, 0xFF); ++ write_phy(dev->phy, QSERDES_RX_RX_EQ_GAIN1_MSB, 0x1F); ++ write_phy(dev->phy, QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF); ++ write_phy(dev->phy, QSERDES_RX_RX_EQ_GAIN2_MSB, 0x00); ++ write_phy(dev->phy, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x1A); ++ write_phy(dev->phy, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x80); ++ write_phy(dev->phy, QSERDES_RX_SIGDET_ENABLES, 0x40); ++ write_phy(dev->phy, QSERDES_RX_SIGDET_CNTRL, 0x70); ++ write_phy(dev->phy, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x06); ++ write_phy(dev->phy, QSERDES_COM_PLL_RXTXEPCLK_EN, 0x10); ++ write_phy(dev->phy, PCIE_PHY_ENDPOINT_REFCLK_DRIVE, 0x10); ++ write_phy(dev->phy, PCIE_PHY_POWER_STATE_CONFIG1, 0x23); ++ write_phy(dev->phy, PCIE_PHY_POWER_STATE_CONFIG2, 0xCB); ++ write_phy(dev->phy, QSERDES_RX_RX_RCVR_IQ_EN, 0x31); ++ ++ write_phy(dev->phy, PCIE_PHY_SW_RESET, 0x00); ++ write_phy(dev->phy, PCIE_PHY_START, 0x03); ++} ++#elif defined(CONFIG_ARCH_FSM9900) ++void pcie_phy_init(struct msm_pcie_dev_t *dev) ++{ ++ if (dev->ext_ref_clk == false) { ++ pcie20_phy_init_default(dev); ++ return; ++ } ++ ++ PCIE_DBG(dev, "RC%d: Initializing 28nm ATE phy - 100MHz\n", ++ dev->rc_idx); ++ ++ /* 1 */ ++ write_phy(dev->phy, PCIE_PHY_POWER_DOWN_CONTROL, 0x01); ++ /* 2 */ ++ write_phy(dev->phy, QSERDES_COM_SYS_CLK_CTRL, 0x3e); ++ /* 3 */ ++ write_phy(dev->phy, QSERDES_COM_PLL_CP_SETI, 0x0f); ++ /* 4 */ ++ write_phy(dev->phy, QSERDES_COM_PLL_IP_SETP, 0x23); ++ /* 5 */ ++ write_phy(dev->phy, QSERDES_COM_PLL_IP_SETI, 0x3f); ++ /* 6 */ ++ write_phy(dev->phy, QSERDES_RX_CDR_CONTROL, 0xf3); ++ /* 7 */ ++ write_phy(dev->phy, QSERDES_RX_CDR_CONTROL2, 0x6b); ++ /* 8 */ ++ write_phy(dev->phy, QSERDES_COM_RESETSM_CNTRL, 0x10); ++ /* 9 */ ++ write_phy(dev->phy, QSERDES_RX_RX_TERM_HIGHZ_CM_AC_COUPLE, 0x87); ++ /* 10 */ ++ write_phy(dev->phy, QSERDES_RX_RX_EQ_GAIN12, 0x54); ++ /* 11 */ ++ write_phy(dev->phy, PCIE_PHY_POWER_STATE_CONFIG1, 0xa3); ++ /* 12 */ ++ write_phy(dev->phy, PCIE_PHY_POWER_STATE_CONFIG2, 0x1b); ++ /* 13 */ ++ write_phy(dev->phy, PCIE_PHY_SW_RESET, 0x00); ++ /* 14 */ ++ write_phy(dev->phy, PCIE_PHY_START, 0x03); ++} ++#else ++void pcie_phy_init(struct msm_pcie_dev_t *dev) ++{ ++ if (dev->is_emulation) ++ pcie20_uni_phy_init(dev); ++ else ++ pcie20_phy_init_default(dev); ++} ++ ++#endif ++ ++bool pcie_phy_is_ready(struct msm_pcie_dev_t *dev) ++{ ++ if (!dev->is_emulation && ++ readl_relaxed(dev->phy + PCIE_PHY_PCS_STATUS) & BIT(6)) ++ return false; ++ else ++ return true; ++} ++/** ++ * Write register ++ * ++ * @base - PHY base virtual address. ++ * @offset - register offset. ++ */ ++static u32 qca_uni_phy_read(void __iomem *base, u32 offset) ++{ ++ u32 value; ++ value = readl_relaxed(base + offset); ++ return value; ++} ++ ++/** ++ * Write register ++ * @base - PHY base virtual address. ++ * @offset - register offset. ++ * @val - value to write. ++ */ ++static void qca_uni_phy_write(void __iomem *base, u32 offset, u32 val) ++{ ++ writel(val, base + offset); ++ udelay(100); ++} ++ ++static int mdio_wait(void __iomem *base) ++{ ++ unsigned int mdio_access; ++ unsigned int timeout = MDIO_TIMEOUT_STATIC; ++ ++ do { ++ mdio_access = qca_uni_phy_read(base, MDIO_CTRL_4_REG); ++ if (!timeout--) ++ return -EFAULT; ++ } while (mdio_access & MDIO_ACCESS_BUSY); ++ ++ return 0; ++} ++ ++static int mdio_mii_read(void __iomem *base, unsigned char regAddr, ++ unsigned short *data) ++{ ++ unsigned short mdio_ctl_0 = (MDIO_PCIE_PHY_ID | MDC_MODE | ++ MDIO_CLAUSE_22 | MDIO_PCIE_CLK_DIV); ++ unsigned int regVal; ++ ++ qca_uni_phy_write(base, MDIO_CTRL_0_REG, mdio_ctl_0); ++ qca_uni_phy_write(base, MDIO_CTRL_1_REG, regAddr); ++ qca_uni_phy_write(base, MDIO_CTRL_4_REG, MDIO_ACCESS_22_READ); ++ qca_uni_phy_write(base, MDIO_CTRL_4_REG, MDIO_ACCESS_22_READ | ++ MDIO_ACCESS_START); ++ ++ /* wait for access busy to be cleared */ ++ if (mdio_wait(base)) { ++ pr_err("%s MDIO Access Busy Timeout %x\n", __func__, regAddr); ++ return -EFAULT; ++ } ++ ++ regVal = qca_uni_phy_read(base, MDIO_CTRL_3_REG); ++ *data = (unsigned short)regVal; ++ return 0; ++} ++ ++static int mdio_mii_write(void __iomem *base, unsigned char regAddr, ++ unsigned short data) ++{ ++ unsigned short mdio_ctl_0 = (MDIO_PCIE_PHY_ID | MDC_MODE | ++ MDIO_CLAUSE_22 | MDIO_PCIE_CLK_DIV); ++ ++ qca_uni_phy_write(base, MDIO_CTRL_0_REG, mdio_ctl_0); ++ qca_uni_phy_write(base, MDIO_CTRL_1_REG, regAddr); ++ qca_uni_phy_write(base, MDIO_CTRL_2_REG, data); ++ qca_uni_phy_write(base, MDIO_CTRL_4_REG, MDIO_ACCESS_22_WRITE); ++ qca_uni_phy_write(base, MDIO_CTRL_4_REG, MDIO_ACCESS_22_WRITE | ++ MDIO_ACCESS_START); ++ ++ /* wait for access busy to be cleared */ ++ if (mdio_wait(base)) { ++ pr_err("%s MDIO Access Busy Timeout %x\n", __func__, regAddr); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++static int mdio_mmd_read(void __iomem *base, unsigned short regAddr, ++ unsigned short *data) ++{ ++ unsigned short mdio_ctl_0 = (MDIO_PCIE_PHY_ID | MDC_MODE | ++ MDIO_CLAUSE_45 | MDIO_PCIE_CLK_DIV); ++ unsigned int regVal; ++ ++ qca_uni_phy_write(base, MDIO_CTRL_0_REG, mdio_ctl_0); ++ qca_uni_phy_write(base, MDIO_CTRL_1_REG, MDIO_MMD_ID); ++ qca_uni_phy_write(base, MDIO_CTRL_2_REG, regAddr); ++ qca_uni_phy_write(base, MDIO_CTRL_4_REG, MDIO_ACCESS_45_READ_ADDR); ++ qca_uni_phy_write(base, MDIO_CTRL_4_REG, MDIO_ACCESS_45_READ_ADDR | ++ MDIO_ACCESS_START); ++ ++ /* wait for access busy to be cleared */ ++ if (mdio_wait(base)) { ++ pr_err("%s MDIO Access Busy Timeout %x\n", __func__, regAddr); ++ return -EFAULT; ++ } ++ ++ qca_uni_phy_write(base, MDIO_CTRL_1_REG, MDIO_MMD_ID); ++ qca_uni_phy_write(base, MDIO_CTRL_2_REG, regAddr); ++ qca_uni_phy_write(base, MDIO_CTRL_4_REG, MDIO_ACCESS_45_WRITE); ++ qca_uni_phy_write(base, MDIO_CTRL_4_REG, MDIO_ACCESS_45_WRITE | ++ MDIO_ACCESS_START); ++ ++ /* wait for access busy to be cleared */ ++ if (mdio_wait(base)) { ++ pr_err("%s MDIO Access Busy Timeout %x\n", __func__, regAddr); ++ return -EFAULT; ++ } ++ ++ regVal = qca_uni_phy_read(base, MDIO_CTRL_3_REG); ++ *data = (unsigned short)regVal; ++ ++ return 0; ++} ++ ++static int mdio_mmd_write(void __iomem *base, unsigned short regAddr, ++ unsigned short data) ++{ ++ ++ unsigned short mdio_ctl_0 = (MDIO_PCIE_PHY_ID | MDC_MODE | ++ MDIO_CLAUSE_45 | MDIO_PCIE_CLK_DIV); ++ ++ qca_uni_phy_write(base, MDIO_CTRL_0_REG, mdio_ctl_0); ++ qca_uni_phy_write(base, MDIO_CTRL_1_REG, MDIO_MMD_ID); ++ qca_uni_phy_write(base, MDIO_CTRL_2_REG, regAddr); ++ qca_uni_phy_write(base, MDIO_CTRL_4_REG, MDIO_ACCESS_45_READ_ADDR); ++ qca_uni_phy_write(base, MDIO_CTRL_4_REG, MDIO_ACCESS_45_READ_ADDR | ++ MDIO_ACCESS_START); ++ ++ /* wait for access busy to be cleared */ ++ if (mdio_wait(base)) { ++ pr_err("%s MDIO Access Busy Timeout %x\n", __func__, regAddr); ++ return -EFAULT; ++ } ++ ++ qca_uni_phy_write(base, MDIO_CTRL_2_REG, data); ++ qca_uni_phy_write(base, MDIO_CTRL_4_REG, MDIO_ACCESS_45_READ); ++ qca_uni_phy_write(base, MDIO_CTRL_4_REG, MDIO_ACCESS_45_READ | ++ MDIO_ACCESS_START); ++ ++ qca_uni_phy_write(base, MDIO_CTRL_2_REG, regAddr); ++ qca_uni_phy_write(base, MDIO_CTRL_4_REG, MDIO_ACCESS_45_WRITE); ++ qca_uni_phy_write(base, MDIO_CTRL_4_REG, MDIO_ACCESS_45_WRITE | ++ MDIO_ACCESS_START); ++ ++ /* wait for access busy to be cleared */ ++ if (mdio_wait(base)) { ++ pr_err("%s MDIO Access Busy Timeout %x\n", __func__, regAddr); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++void pcie20_uni_phy_init(struct msm_pcie_dev_t *dev) ++{ ++ unsigned short data; ++ ++ mdio_mii_write(dev->phy, 0x1, 0x801c); ++ mdio_mii_write(dev->phy, 0xb, 0x300d); ++ ++ mdio_mmd_write(dev->phy, 0x2d, 0x681a); ++ mdio_mmd_write(dev->phy, 0x7d, 0x8); ++ mdio_mmd_write(dev->phy, 0x7f, 0x5ed5); ++ mdio_mmd_write(dev->phy, 0x87, 0xaa0a); ++ mdio_mmd_write(dev->phy, 0x4, 0x0802); ++ mdio_mmd_write(dev->phy, 0x8, 0x0280); ++ mdio_mmd_write(dev->phy, 0x9, 0x8854); ++ mdio_mmd_write(dev->phy, 0xa, 0x2815); ++ mdio_mmd_write(dev->phy, 0xb, 0x0120); ++ mdio_mmd_write(dev->phy, 0xc, 0x0480); ++ mdio_mmd_write(dev->phy, 0x13, 0x8000); ++ ++ mdio_mmd_read(dev->phy, 0x7e, &data); ++ ++ mdio_mii_read(dev->phy, 0x7, &data); ++} ++ ++bool pcie_phy_detect(struct msm_pcie_dev_t *dev) ++{ ++ unsigned short data; ++ ++ mdio_mii_read(dev->phy, 0x0, &data); ++ ++ if (data == 0x7f) { ++ pr_info("PCIe UNI PHY detected\n"); ++ return true; ++ } else { ++ return false; ++ } ++} +diff --git a/arch/arm/mach-qcom/pcie_phy.h b/arch/arm/mach-qcom/pcie_phy.h +new file mode 100644 +index 0000000..99297c3 +--- /dev/null ++++ b/arch/arm/mach-qcom/pcie_phy.h +@@ -0,0 +1,545 @@ ++/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __ARCH_ARM_MACH_MSM_PCIE_PHY_H ++#define __ARCH_ARM_MACH_MSM_PCIE_PHY_H ++ ++#ifdef CONFIG_ARCH_MDM9630 ++#define QSERDES_COM_SYS_CLK_CTRL 0x000 ++#define QSERDES_COM_PLL_VCOTAIL_EN 0x004 ++#define QSERDES_COM_CMN_MODE 0x008 ++#define QSERDES_COM_IE_TRIM 0x00C ++#define QSERDES_COM_IP_TRIM 0x010 ++#define QSERDES_COM_PLL_CNTRL 0x014 ++#define QSERDES_COM_PLL_PHSEL_CONTROL 0x018 ++#define QSERDES_COM_IPTAT_TRIM_VCCA_TX_SEL 0x01C ++#define QSERDES_COM_PLL_PHSEL_DC 0x020 ++#define QSERDES_COM_PLL_IP_SETI 0x024 ++#define QSERDES_COM_CORE_CLK_IN_SYNC_SEL 0x028 ++#define QSERDES_COM_PLL_BKG_KVCO_CAL_EN 0x02C ++#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x030 ++#define QSERDES_COM_PLL_CP_SETI 0x034 ++#define QSERDES_COM_PLL_IP_SETP 0x038 ++#define QSERDES_COM_PLL_CP_SETP 0x03C ++#define QSERDES_COM_ATB_SEL1 0x040 ++#define QSERDES_COM_ATB_SEL2 0x044 ++#define QSERDES_COM_SYSCLK_EN_SEL_TXBAND 0x048 ++#define QSERDES_COM_RESETSM_CNTRL 0x04C ++#define QSERDES_COM_RESETSM_CNTRL2 0x050 ++#define QSERDES_COM_RESETSM_CNTRL3 0x054 ++#define QSERDES_COM_DIV_REF1 0x058 ++#define QSERDES_COM_DIV_REF2 0x05C ++#define QSERDES_COM_KVCO_COUNT1 0x060 ++#define QSERDES_COM_KVCO_COUNT2 0x064 ++#define QSERDES_COM_KVCO_CAL_CNTRL 0x068 ++#define QSERDES_COM_KVCO_CODE 0x06C ++#define QSERDES_COM_VREF_CFG1 0x070 ++#define QSERDES_COM_VREF_CFG2 0x074 ++#define QSERDES_COM_VREF_CFG3 0x078 ++#define QSERDES_COM_VREF_CFG4 0x07C ++#define QSERDES_COM_VREF_CFG5 0x080 ++#define QSERDES_COM_VREF_CFG6 0x084 ++#define QSERDES_COM_PLLLOCK_CMP1 0x088 ++#define QSERDES_COM_PLLLOCK_CMP2 0x08C ++#define QSERDES_COM_PLLLOCK_CMP3 0x090 ++#define QSERDES_COM_PLLLOCK_CMP_EN 0x094 ++#define QSERDES_COM_BGTC 0x098 ++#define QSERDES_COM_PLL_TEST_UPDN 0x09C ++#define QSERDES_COM_PLL_VCO_TUNE 0x0A0 ++#define QSERDES_COM_DEC_START1 0x0A4 ++#define QSERDES_COM_PLL_AMP_OS 0x0A8 ++#define QSERDES_COM_SSC_EN_CENTER 0x0AC ++#define QSERDES_COM_SSC_ADJ_PER1 0x0B0 ++#define QSERDES_COM_SSC_ADJ_PER2 0x0B4 ++#define QSERDES_COM_SSC_PER1 0x0B8 ++#define QSERDES_COM_SSC_PER2 0x0BC ++#define QSERDES_COM_SSC_STEP_SIZE1 0x0C0 ++#define QSERDES_COM_SSC_STEP_SIZE2 0x0C4 ++#define QSERDES_COM_RES_CODE_UP 0x0C8 ++#define QSERDES_COM_RES_CODE_DN 0x0CC ++#define QSERDES_COM_RES_CODE_UP_OFFSET 0x0D0 ++#define QSERDES_COM_RES_CODE_DN_OFFSET 0x0D4 ++#define QSERDES_COM_RES_CODE_START_SEG1 0x0D8 ++#define QSERDES_COM_RES_CODE_START_SEG2 0x0DC ++#define QSERDES_COM_RES_CODE_CAL_CSR 0x0E0 ++#define QSERDES_COM_RES_CODE 0x0E4 ++#define QSERDES_COM_RES_TRIM_CONTROL 0x0E8 ++#define QSERDES_COM_RES_TRIM_CONTROL2 0x0EC ++#define QSERDES_COM_RES_TRIM_EN_VCOCALDONE 0x0F0 ++#define QSERDES_COM_FAUX_EN 0x0F4 ++#define QSERDES_COM_DIV_FRAC_START1 0x0F8 ++#define QSERDES_COM_DIV_FRAC_START2 0x0FC ++#define QSERDES_COM_DIV_FRAC_START3 0x100 ++#define QSERDES_COM_DEC_START2 0x104 ++#define QSERDES_COM_PLL_RXTXEPCLK_EN 0x108 ++#define QSERDES_COM_PLL_CRCTRL 0x10C ++#define QSERDES_COM_PLL_CLKEPDIV 0x110 ++#define QSERDES_COM_PLL_FREQUPDATE 0x114 ++#define QSERDES_COM_PLL_BKGCAL_TRIM_UP 0x118 ++#define QSERDES_COM_PLL_BKGCAL_TRIM_DN 0x11C ++#define QSERDES_COM_PLL_BKGCAL_TRIM_MUX 0x120 ++#define QSERDES_COM_PLL_BKGCAL_VREF_CFG 0x124 ++#define QSERDES_COM_PLL_BKGCAL_DIV_REF1 0x128 ++#define QSERDES_COM_PLL_BKGCAL_DIV_REF2 0x12C ++#define QSERDES_COM_MUXADDR 0x130 ++#define QSERDES_COM_LOW_POWER_RO_CONTROL 0x134 ++#define QSERDES_COM_POST_DIVIDER_CONTROL 0x138 ++#define QSERDES_COM_HR_OCLK2_DIVIDER 0x13C ++#define QSERDES_COM_HR_OCLK3_DIVIDER 0x140 ++#define QSERDES_COM_PLL_VCO_HIGH 0x144 ++#define QSERDES_COM_RESET_SM 0x148 ++#define QSERDES_COM_MUXVAL 0x14C ++ ++#define QSERDES_RX_CDR_CONTROL1 0x400 ++#define QSERDES_RX_CDR_CONTROL2 0x404 ++#define QSERDES_RX_CDR_CONTROL_HALF 0x408 ++#define QSERDES_RX_CDR_CONTROL_QUARTER 0x40C ++#define QSERDES_RX_CDR_CONTROL_EIGHTH 0x410 ++#define QSERDES_RX_UCDR_FO_GAIN 0x414 ++#define QSERDES_RX_UCDR_SO_GAIN 0x418 ++#define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE 0x41C ++#define QSERDES_RX_UCDR_FO_TO_SO_DELAY 0x420 ++#define QSERDES_RX_AUX_CONTROL 0x424 ++#define QSERDES_RX_AUX_DATA_TCOARSE 0x428 ++#define QSERDES_RX_AUX_DATA_TFINE_LSB 0x42C ++#define QSERDES_RX_AUX_DATA_TFINE_MSB 0x430 ++#define QSERDES_RX_RCLK_AUXDATA_SEL 0x434 ++#define QSERDES_RX_AC_JTAG_ENABLE 0x438 ++#define QSERDES_RX_AC_JTAG_INITP 0x43C ++#define QSERDES_RX_AC_JTAG_INITN 0x440 ++#define QSERDES_RX_AC_JTAG_LVL 0x444 ++#define QSERDES_RX_AC_JTAG_MODE 0x448 ++#define QSERDES_RX_AC_JTAG_RESET 0x44C ++#define QSERDES_RX_RX_RCVR_IQ_EN 0x450 ++#define QSERDES_RX_RX_IDAC_I_DC_OFFSETS 0x454 ++#define QSERDES_RX_RX_IDAC_Q_DC_OFFSETS 0x458 ++#define QSERDES_RX_RX_IDAC_A_DC_OFFSETS 0x45C ++#define QSERDES_RX_RX_IDAC_EN 0x460 ++#define QSERDES_RX_RX_IDAC_CTRL0 0x464 ++#define QSERDES_RX_RX_IDAC_CTRL1 0x468 ++#define QSERDES_RX_RX_EOM_EN 0x46C ++#define QSERDES_RX_RX_EOM_CTRL0 0x470 ++#define QSERDES_RX_RX_EOM_CTRL1 0x474 ++#define QSERDES_RX_RX_EOM_CTRL2 0x478 ++#define QSERDES_RX_RX_EOM_CTRL3 0x47C ++#define QSERDES_RX_RX_EOM_CTRL4 0x480 ++#define QSERDES_RX_RX_EOM_CTRL5 0x484 ++#define QSERDES_RX_RX_EOM_CTRL6 0x488 ++#define QSERDES_RX_RX_EOM_CTRL7 0x48C ++#define QSERDES_RX_RX_EOM_CTRL8 0x490 ++#define QSERDES_RX_RX_EOM_CTRL9 0x494 ++#define QSERDES_RX_RX_EOM_CTRL10 0x498 ++#define QSERDES_RX_RX_EOM_CTRL11 0x49C ++#define QSERDES_RX_RX_HIGHZ_HIGHRATE 0x4A0 ++#define QSERDES_RX_RX_TERM_AC_BYPASS_DC_COUPLE_OFFSET 0x4A4 ++#define QSERDES_RX_RX_EQ_GAIN1_LSB 0x4A8 ++#define QSERDES_RX_RX_EQ_GAIN1_MSB 0x4AC ++#define QSERDES_RX_RX_EQ_GAIN2_LSB 0x4B0 ++#define QSERDES_RX_RX_EQ_GAIN2_MSB 0x4B4 ++#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1 0x4B8 ++#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 0x4BC ++#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3 0x4C0 ++#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4 0x4C4 ++#define QSERDES_RX_RX_IDAC_CAL_CONFIGURATION 0x4C8 ++#define QSERDES_RX_RX_IDAC_CAL_CONFIGURATION_2 0x4CC ++#define QSERDES_RX_RX_IDAC_TSETTLE_LOW 0x4D0 ++#define QSERDES_RX_RX_IDAC_TSETTLE_HIGH 0x4D4 ++#define QSERDES_RX_RX_IDAC_ENDSAMP_LOW 0x4D8 ++#define QSERDES_RX_RX_IDAC_ENDSAMP_HIGH 0x4DC ++#define QSERDES_RX_RX_IDAC_MIDPOINT_LOW 0x4E0 ++#define QSERDES_RX_RX_IDAC_MIDPOINT_HIGH 0x4E4 ++#define QSERDES_RX_RX_EQ_OFFSET_LSB 0x4E8 ++#define QSERDES_RX_RX_EQ_OFFSET_MSB 0x4EC ++#define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x4F0 ++#define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x4F4 ++#define QSERDES_RX_SIGDET_ENABLES 0x4F8 ++#define QSERDES_RX_SIGDET_ENABLES_2 0x4FC ++#define QSERDES_RX_SIGDET_CNTRL 0x500 ++#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL 0x504 ++#define QSERDES_RX_SIGDET_TIMER_LIMIT 0x508 ++#define QSERDES_RX_RX_BAND 0x50C ++#define QSERDES_RX_CDR_FREEZE_UP_DN 0x510 ++#define QSERDES_RX_RX_INTERFACE_MODE 0x514 ++#define QSERDES_RX_JITTER_GEN_MODE 0x518 ++#define QSERDES_RX_BUJ_AMP 0x51C ++#define QSERDES_RX_SJ_AMP1 0x520 ++#define QSERDES_RX_SJ_AMP2 0x524 ++#define QSERDES_RX_SJ_PER1 0x528 ++#define QSERDES_RX_SJ_PER2 0x52C ++#define QSERDES_RX_BUJ_STEP_FREQ1 0x530 ++#define QSERDES_RX_BUJ_STEP_FREQ2 0x534 ++#define QSERDES_RX_PPM_OFFSET1 0x538 ++#define QSERDES_RX_PPM_OFFSET2 0x53C ++#define QSERDES_RX_SIGN_PPM_PERIOD1 0x540 ++#define QSERDES_RX_SIGN_PPM_PERIOD2 0x544 ++#define QSERDES_RX_SSC_CTRL 0x548 ++#define QSERDES_RX_SSC_COUNT1 0x54C ++#define QSERDES_RX_SSC_COUNT2 0x550 ++#define QSERDES_RX_RX_ALOG_INTF_OBSV_CNTL 0x554 ++#define QSERDES_RX_PI_CTRL1 0x558 ++#define QSERDES_RX_PI_CTRL2 0x55C ++#define QSERDES_RX_PI_QUAD 0x560 ++#define QSERDES_RX_IDATA1 0x564 ++#define QSERDES_RX_IDATA2 0x568 ++#define QSERDES_RX_AUX_DATA1 0x56C ++#define QSERDES_RX_AUX_DATA2 0x570 ++#define QSERDES_RX_AC_JTAG_OUTP 0x574 ++#define QSERDES_RX_AC_JTAG_OUTN 0x578 ++#define QSERDES_RX_RX_SIGDET 0x57C ++#define QSERDES_RX_RX_VDCOFF 0x580 ++#define QSERDES_RX_IDAC_CAL_ON 0x584 ++#define QSERDES_RX_IDAC_STATUS_I 0x588 ++#define QSERDES_RX_IDAC_STATUS_Q 0x58C ++#define QSERDES_RX_IDAC_STATUS_A 0x590 ++#define QSERDES_RX_CALST_STATUS_I 0x594 ++#define QSERDES_RX_CALST_STATUS_Q 0x598 ++#define QSERDES_RX_CALST_STATUS_A 0x59C ++#define QSERDES_RX_EOM_STATUS0 0x5A0 ++#define QSERDES_RX_EOM_STATUS1 0x5A4 ++#define QSERDES_RX_EOM_STATUS2 0x5A8 ++#define QSERDES_RX_EOM_STATUS3 0x5AC ++#define QSERDES_RX_EOM_STATUS4 0x5B0 ++#define QSERDES_RX_EOM_STATUS5 0x5B4 ++#define QSERDES_RX_EOM_STATUS6 0x5B8 ++#define QSERDES_RX_EOM_STATUS7 0x5BC ++#define QSERDES_RX_EOM_STATUS8 0x5C0 ++#define QSERDES_RX_EOM_STATUS9 0x5C4 ++#define QSERDES_RX_RX_ALOG_INTF_OBSV 0x5C8 ++#define QSERDES_RX_READ_EQCODE 0x5CC ++#define QSERDES_RX_READ_OFFSETCODE 0x5D0 ++ ++#define QSERDES_TX_BIST_MODE_LANENO 0x200 ++#define QSERDES_TX_CLKBUF_ENABLE 0x204 ++#define QSERDES_TX_TX_EMP_POST1_LVL 0x208 ++#define QSERDES_TX_TX_DRV_LVL 0x20C ++#define QSERDES_TX_RESET_TSYNC_EN 0x210 ++#define QSERDES_TX_LPB_EN 0x214 ++#define QSERDES_TX_RES_CODE_UP 0x218 ++#define QSERDES_TX_RES_CODE_DN 0x21C ++#define QSERDES_TX_PERL_LENGTH1 0x220 ++#define QSERDES_TX_PERL_LENGTH2 0x224 ++#define QSERDES_TX_SERDES_BYP_EN_OUT 0x228 ++#define QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN 0x22C ++#define QSERDES_TX_PARRATE_REC_DETECT_IDLE_EN 0x230 ++#define QSERDES_TX_BIST_PATTERN1 0x234 ++#define QSERDES_TX_BIST_PATTERN2 0x238 ++#define QSERDES_TX_BIST_PATTERN3 0x23C ++#define QSERDES_TX_BIST_PATTERN4 0x240 ++#define QSERDES_TX_BIST_PATTERN5 0x244 ++#define QSERDES_TX_BIST_PATTERN6 0x248 ++#define QSERDES_TX_BIST_PATTERN7 0x24C ++#define QSERDES_TX_BIST_PATTERN8 0x250 ++#define QSERDES_TX_LANE_MODE 0x254 ++#define QSERDES_TX_IDAC_CAL_LANE_MODE 0x258 ++#define QSERDES_TX_IDAC_CAL_LANE_MODE_CONFIGURATION 0x25C ++#define QSERDES_TX_ATB_SEL1 0x260 ++#define QSERDES_TX_ATB_SEL2 0x264 ++#define QSERDES_TX_RCV_DETECT_LVL 0x268 ++#define QSERDES_TX_PRBS_SEED1 0x26C ++#define QSERDES_TX_PRBS_SEED2 0x270 ++#define QSERDES_TX_PRBS_SEED3 0x274 ++#define QSERDES_TX_PRBS_SEED4 0x278 ++#define QSERDES_TX_RESET_GEN 0x27C ++#define QSERDES_TX_TRAN_DRVR_EMP_EN 0x280 ++#define QSERDES_TX_TX_INTERFACE_MODE 0x284 ++#define QSERDES_TX_PWM_CTRL 0x288 ++#define QSERDES_TX_PWM_DATA 0x28C ++#define QSERDES_TX_PWM_ENC_DIV_CTRL 0x290 ++#define QSERDES_TX_VMODE_CTRL1 0x294 ++#define QSERDES_TX_VMODE_CTRL2 0x298 ++#define QSERDES_TX_VMODE_CTRL3 0x29C ++#define QSERDES_TX_VMODE_CTRL4 0x2A0 ++#define QSERDES_TX_VMODE_CTRL5 0x2A4 ++#define QSERDES_TX_VMODE_CTRL6 0x2A8 ++#define QSERDES_TX_VMODE_CTRL7 0x2AC ++#define QSERDES_TX_TX_ALOG_INTF_OBSV_CNTL 0x2B0 ++#define QSERDES_TX_BIST_STATUS 0x2B4 ++#define QSERDES_TX_BIST_ERROR_COUNT1 0x2B8 ++#define QSERDES_TX_BIST_ERROR_COUNT2 0x2BC ++#define QSERDES_TX_TX_ALOG_INTF_OBSV 0x2C0 ++#define QSERDES_TX_PWM_DEC_STATUS 0x2C4 ++ ++#define PCIE_PHY_SW_RESET 0x600 ++#define PCIE_PHY_POWER_DOWN_CONTROL 0x604 ++#define PCIE_PHY_START 0x608 ++#define PCIE_PHY_TXMGN_V1_V0 0x60C ++#define PCIE_PHY_TXMGN_V3_V2 0x610 ++#define PCIE_PHY_TXMGN_LS_V4 0x614 ++#define PCIE_PHY_TXDEEMPH_M6DB_V0 0x618 ++#define PCIE_PHY_TXDEEMPH_M3P5DB_V0 0x61C ++#define PCIE_PHY_TXDEEMPH_M6DB_V1 0x620 ++#define PCIE_PHY_TXDEEMPH_M3P5DB_V1 0x624 ++#define PCIE_PHY_TXDEEMPH_M6DB_V2 0x628 ++#define PCIE_PHY_TXDEEMPH_M3P5DB_V2 0x62C ++#define PCIE_PHY_TXDEEMPH_M6DB_V3 0x630 ++#define PCIE_PHY_TXDEEMPH_M3P5DB_V3 0x634 ++#define PCIE_PHY_TXDEEMPH_M6DB_V4 0x638 ++#define PCIE_PHY_TXDEEMPH_M3P5DB_V4 0x63C ++#define PCIE_PHY_TXDEEMPH_M6DB_LS 0x640 ++#define PCIE_PHY_TXDEEMPH_M3P5DB_LS 0x644 ++#define PCIE_PHY_ENDPOINT_REFCLK_DRIVE 0x648 ++#define PCIE_PHY_RX_IDLE_DTCT_CNTRL 0x64C ++#define PCIE_PHY_POWER_STATE_CONFIG1 0x650 ++#define PCIE_PHY_POWER_STATE_CONFIG2 0x654 ++#define PCIE_PHY_POWER_STATE_CONFIG3 0x658 ++#define PCIE_PHY_RCVR_DTCT_DLY_P1U2_L 0x65C ++#define PCIE_PHY_RCVR_DTCT_DLY_P1U2_H 0x660 ++#define PCIE_PHY_RCVR_DTCT_DLY_U3_L 0x664 ++#define PCIE_PHY_RCVR_DTCT_DLY_U3_H 0x668 ++#define PCIE_PHY_LOCK_DETECT_CONFIG1 0x66C ++#define PCIE_PHY_LOCK_DETECT_CONFIG2 0x670 ++#define PCIE_PHY_LOCK_DETECT_CONFIG3 0x674 ++#define PCIE_PHY_TSYNC_RSYNC_TIME 0x678 ++#define PCIE_PHY_SIGDET_LOW_2_IDLE_TIME 0x67C ++#define PCIE_PHY_BEACON_2_IDLE_TIME_L 0x680 ++#define PCIE_PHY_BEACON_2_IDLE_TIME_H 0x684 ++#define PCIE_PHY_PWRUP_RESET_DLY_TIME_SYSCLK 0x688 ++#define PCIE_PHY_PWRUP_RESET_DLY_TIME_AUXCLK 0x68C ++#define PCIE_PHY_LFPS_DET_HIGH_COUNT_VAL 0x690 ++#define PCIE_PHY_LFPS_TX_ECSTART_EQTLOCK 0x694 ++#define PCIE_PHY_LFPS_TX_END_CNT_P2U3_START 0x698 ++#define PCIE_PHY_RXEQTRAINING_WAIT_TIME 0x69C ++#define PCIE_PHY_RXEQTRAINING_RUN_TIME 0x6A0 ++#define PCIE_PHY_TXONESZEROS_RUN_LENGTH 0x6A4 ++#define PCIE_PHY_FLL_CNTRL1 0x6A8 ++#define PCIE_PHY_FLL_CNTRL2 0x6AC ++#define PCIE_PHY_FLL_CNT_VAL_L 0x6B0 ++#define PCIE_PHY_FLL_CNT_VAL_H_TOL 0x6B4 ++#define PCIE_PHY_FLL_MAN_CODE 0x6B8 ++#define PCIE_PHY_AUTONOMOUS_MODE_CTRL 0x6BC ++#define PCIE_PHY_LFPS_RXTERM_IRQ_CLEAR 0x6C0 ++#define PCIE_PHY_ARCVR_DTCT_EN_PERIOD 0x6C4 ++#define PCIE_PHY_ARCVR_DTCT_CM_DLY 0x6C8 ++#define PCIE_PHY_ALFPS_DEGLITCH_VAL 0x6CC ++#define PCIE_PHY_INSIG_SW_CTRL1 0x6D0 ++#define PCIE_PHY_INSIG_SW_CTRL2 0x6D4 ++#define PCIE_PHY_INSIG_SW_CTRL3 0x6D8 ++#define PCIE_PHY_INSIG_MX_CTRL1 0x6DC ++#define PCIE_PHY_INSIG_MX_CTRL2 0x6E0 ++#define PCIE_PHY_INSIG_MX_CTRL3 0x6E4 ++#define PCIE_PHY_TEST_CONTROL 0x6E8 ++#define PCIE_PHY_BIST_CTRL 0x6EC ++#define PCIE_PHY_PRBS_POLY0 0x6F0 ++#define PCIE_PHY_PRBS_POLY1 0x6F4 ++#define PCIE_PHY_PRBS_SEED0 0x6F8 ++#define PCIE_PHY_PRBS_SEED1 0x6FC ++#define PCIE_PHY_FIXED_PAT_CTRL 0x700 ++#define PCIE_PHY_FIXED_PAT0 0x704 ++#define PCIE_PHY_FIXED_PAT1 0x708 ++#define PCIE_PHY_FIXED_PAT2 0x70C ++#define PCIE_PHY_FIXED_PAT3 0x710 ++#define PCIE_PHY_SPARE1 0x714 ++#define PCIE_PHY_BIST_CHK_ERR_CNT_L 0x718 ++#define PCIE_PHY_BIST_CHK_ERR_CNT_H 0x71C ++#define PCIE_PHY_BIST_CHK_STATUS 0x720 ++#define PCIE_PHY_LFPS_RXTERM_IRQ_SOURCE 0x724 ++#define PCIE_PHY_PCS_STATUS 0x728 ++#define PCIE_PHY_PCS_STATUS2 0x72C ++#define PCIE_PHY_REVISION_ID0 0x730 ++#define PCIE_PHY_REVISION_ID1 0x734 ++#define PCIE_PHY_REVISION_ID2 0x738 ++#define PCIE_PHY_REVISION_ID3 0x73C ++#define PCIE_PHY_DEBUG_BUS_0_STATUS 0x740 ++#define PCIE_PHY_DEBUG_BUS_1_STATUS 0x744 ++#define PCIE_PHY_DEBUG_BUS_2_STATUS 0x748 ++#define PCIE_PHY_DEBUG_BUS_3_STATUS 0x74C ++ ++#else ++ ++#define QSERDES_COM_SYS_CLK_CTRL 0x000 ++#define QSERDES_COM_PLL_VCOTAIL_EN 0x004 ++#define QSERDES_COM_CMN_MODE 0x008 ++#define QSERDES_COM_IE_TRIM 0x00c ++#define QSERDES_COM_IP_TRIM 0x010 ++#define QSERDES_COM_PLL_CNTRL 0x014 ++#define QSERDES_COM_PLL_IP_SETI 0x018 ++#define QSERDES_COM_CORE_CLK_IN_SYNC_SEL 0x01c ++#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x020 ++#define QSERDES_COM_PLL_CP_SETI 0x024 ++#define QSERDES_COM_PLL_IP_SETP 0x028 ++#define QSERDES_COM_PLL_CP_SETP 0x02c ++#define QSERDES_COM_ATB_SEL1 0x030 ++#define QSERDES_COM_ATB_SEL2 0x034 ++#define QSERDES_COM_SYSCLK_EN_SEL 0x038 ++#define QSERDES_COM_RES_CODE_TXBAND 0x03c ++#define QSERDES_COM_RESETSM_CNTRL 0x040 ++#define QSERDES_COM_PLLLOCK_CMP1 0x044 ++#define QSERDES_COM_PLLLOCK_CMP2 0x048 ++#define QSERDES_COM_PLLLOCK_CMP3 0x04c ++#define QSERDES_COM_PLLLOCK_CMP_EN 0x050 ++#define QSERDES_COM_RES_TRIM_OFFSET 0x054 ++#define QSERDES_COM_BGTC 0x058 ++#define QSERDES_COM_PLL_TEST_UPDN_RESTRIMSTEP 0x05c ++#define QSERDES_COM_PLL_VCO_TUNE 0x060 ++#define QSERDES_COM_DEC_START1 0x064 ++#define QSERDES_COM_PLL_AMP_OS 0x068 ++#define QSERDES_COM_SSC_EN_CENTER 0x06c ++#define QSERDES_COM_SSC_ADJ_PER1 0x070 ++#define QSERDES_COM_SSC_ADJ_PER2 0x074 ++#define QSERDES_COM_SSC_PER1 0x078 ++#define QSERDES_COM_SSC_PER2 0x07c ++#define QSERDES_COM_SSC_STEP_SIZE1 0x080 ++#define QSERDES_COM_SSC_STEP_SIZE2 0x084 ++#define QSERDES_COM_RES_TRIM_SEARCH 0x088 ++#define QSERDES_COM_RES_TRIM_FREEZE 0x08c ++#define QSERDES_COM_RES_TRIM_EN_VCOCALDONE 0x090 ++#define QSERDES_COM_FAUX_EN 0x094 ++#define QSERDES_COM_DIV_FRAC_START1 0x098 ++#define QSERDES_COM_DIV_FRAC_START2 0x09c ++#define QSERDES_COM_DIV_FRAC_START3 0x0a0 ++#define QSERDES_COM_DEC_START2 0x0a4 ++#define QSERDES_COM_PLL_RXTXEPCLK_EN 0x0a8 ++#define QSERDES_COM_PLL_CRCTRL 0x0ac ++#define QSERDES_COM_PLL_CLKEPDIV 0x0b0 ++#define QSERDES_COM_PLL_FREQUPDATE 0x0b4 ++#define QSERDES_COM_PLL_VCO_HIGH 0x0b8 ++#define QSERDES_COM_RESET_SM 0x0bc ++#define QSERDES_TX_BIST_MODE_LANENO 0x200 ++#define QSERDES_TX_CLKBUF_ENABLE 0x204 ++#define QSERDES_TX_TX_EMP_POST1_LVL 0x208 ++#define QSERDES_TX_TX_DRV_LVL 0x20c ++#define QSERDES_TX_RESET_TSYNC_EN 0x210 ++#define QSERDES_TX_LPB_EN 0x214 ++#define QSERDES_TX_RES_CODE 0x218 ++#define QSERDES_TX_PERL_LENGTH1 0x21c ++#define QSERDES_TX_PERL_LENGTH2 0x220 ++#define QSERDES_TX_SERDES_BYP_EN_OUT 0x224 ++#define QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_EN 0x228 ++#define QSERDES_TX_PARRATE_REC_DETECT_IDLE_EN 0x22c ++#define QSERDES_TX_BIST_PATTERN1 0x230 ++#define QSERDES_TX_BIST_PATTERN2 0x234 ++#define QSERDES_TX_BIST_PATTERN3 0x238 ++#define QSERDES_TX_BIST_PATTERN4 0x23c ++#define QSERDES_TX_BIST_PATTERN5 0x240 ++#define QSERDES_TX_BIST_PATTERN6 0x244 ++#define QSERDES_TX_BIST_PATTERN7 0x248 ++#define QSERDES_TX_BIST_PATTERN8 0x24c ++#define QSERDES_TX_LANE_MODE 0x250 ++#define QSERDES_TX_ATB_SEL 0x254 ++#define QSERDES_TX_REC_DETECT_LVL 0x258 ++#define QSERDES_TX_PRBS_SEED1 0x25c ++#define QSERDES_TX_PRBS_SEED2 0x260 ++#define QSERDES_TX_PRBS_SEED3 0x264 ++#define QSERDES_TX_PRBS_SEED4 0x268 ++#define QSERDES_TX_RESET_GEN 0x26c ++#define QSERDES_TX_TRAN_DRVR_EMP_EN 0x270 ++#define QSERDES_TX_TX_INTERFACE_MODE 0x274 ++#define QSERDES_TX_BIST_STATUS 0x278 ++#define QSERDES_TX_BIST_ERROR_COUNT1 0x27c ++#define QSERDES_TX_BIST_ERROR_COUNT2 0x280 ++#define QSERDES_RX_CDR_CONTROL 0x400 ++#define QSERDES_RX_AUX_CONTROL 0x404 ++#define QSERDES_RX_AUX_DATA_TCODE 0x408 ++#define QSERDES_RX_RCLK_AUXDATA_SEL 0x40c ++#define QSERDES_RX_CDR_CONTROL2 0x410 ++#define QSERDES_RX_AC_JTAG_INITP 0x414 ++#define QSERDES_RX_AC_JTAG_INITN 0x418 ++#define QSERDES_RX_AC_JTAG_LVL_EN 0x41c ++#define QSERDES_RX_AC_JTAG_MODE 0x420 ++#define QSERDES_RX_AC_JTAG_RESET 0x424 ++#define QSERDES_RX_RX_IQ_RXDET_EN 0x428 ++#define QSERDES_RX_RX_TERM_HIGHZ_CM_AC_COUPLE 0x42c ++#define QSERDES_RX_RX_EQ_GAIN12 0x430 ++#define QSERDES_RX_SIGDET_CNTRL 0x434 ++#define QSERDES_RX_RX_BAND 0x438 ++#define QSERDES_RX_CDR_FREEZE_UP_DN 0x43c ++#define QSERDES_RX_RX_INTERFACE_MODE 0x440 ++#define QSERDES_RX_JITTER_GEN_MODE 0x444 ++#define QSERDES_RX_BUJ_AMP 0x448 ++#define QSERDES_RX_SJ_AMP1 0x44c ++#define QSERDES_RX_SJ_AMP2 0x450 ++#define QSERDES_RX_SJ_PER1 0x454 ++#define QSERDES_RX_SJ_PER2 0x458 ++#define QSERDES_RX_BUJ_STEP_FREQ1 0x45c ++#define QSERDES_RX_BUJ_STEP_FREQ2 0x460 ++#define QSERDES_RX_PPM_OFFSET1 0x464 ++#define QSERDES_RX_PPM_OFFSET2 0x468 ++#define QSERDES_RX_SIGN_PPM_PERIOD1 0x46c ++#define QSERDES_RX_SIGN_PPM_PERIOD2 0x470 ++#define QSERDES_RX_SSC_CTRL 0x474 ++#define QSERDES_RX_SSC_COUNT1 0x478 ++#define QSERDES_RX_SSC_COUNT2 0x47c ++#define QSERDES_RX_PWM_CNTRL1 0x480 ++#define QSERDES_RX_PWM_CNTRL2 0x484 ++#define QSERDES_RX_PWM_NDIV 0x488 ++#define QSERDES_RX_PI_CTRL1 0x48c ++#define QSERDES_RX_PI_CTRL2 0x490 ++#define QSERDES_RX_PI_QUAD 0x494 ++#define QSERDES_RX_IDATA1 0x498 ++#define QSERDES_RX_IDATA2 0x49c ++#define QSERDES_RX_AUX_DATA1 0x4a0 ++#define QSERDES_RX_AUX_DATA2 0x4a4 ++#define QSERDES_RX_AC_JTAG_OUTP 0x4a8 ++#define QSERDES_RX_AC_JTAG_OUTN 0x4ac ++#define QSERDES_RX_RX_SIGDET_PWMDECSTATUS 0x4b0 ++#define PCIE_PHY_SW_RESET 0x600 ++#define PCIE_PHY_POWER_DOWN_CONTROL 0x604 ++#define PCIE_PHY_START 0x608 ++#define PCIE_PHY_TXMGN_V1_V0 0x60c ++#define PCIE_PHY_TXMGN_V3_V2 0x610 ++#define PCIE_PHY_TXMGN_LS_V4 0x614 ++#define PCIE_PHY_TXDEEMPH_M6DB_V0 0x618 ++#define PCIE_PHY_TXDEEMPH_M3P5DB_V0 0x61c ++#define PCIE_PHY_TXDEEMPH_M6DB_V1 0x620 ++#define PCIE_PHY_TXDEEMPH_M3P5DB_V1 0x624 ++#define PCIE_PHY_TXDEEMPH_M6DB_V2 0x628 ++#define PCIE_PHY_TXDEEMPH_M3P5DB_V2 0x62c ++#define PCIE_PHY_TXDEEMPH_M6DB_V3 0x630 ++#define PCIE_PHY_TXDEEMPH_M3P5DB_V3 0x634 ++#define PCIE_PHY_TXDEEMPH_M6DB_V4 0x638 ++#define PCIE_PHY_TXDEEMPH_M3P5DB_V4 0x63c ++#define PCIE_PHY_TXDEEMPH_M6DB_LS 0x640 ++#define PCIE_PHY_TXDEEMPH_M3P5DB_LS 0x644 ++#define PCIE_PHY_ENDPOINT_REFCLK_DRIVE 0x648 ++#define PCIE_PHY_RX_IDLE_DTCT_CNTRL 0x64c ++#define PCIE_PHY_POWER_STATE_CONFIG1 0x650 ++#define PCIE_PHY_POWER_STATE_CONFIG2 0x654 ++#define PCIE_PHY_RCVR_DTCT_DLY_L 0x658 ++#define PCIE_PHY_RCVR_DTCT_DLY_H 0x65c ++#define PCIE_PHY_LOCK_DETECT_CONFIG1 0x660 ++#define PCIE_PHY_LOCK_DETECT_CONFIG2 0x664 ++#define PCIE_PHY_TSYNC_RSYNC_TIME 0x668 ++#define PCIE_PHY_SIGDET_LOW_2_IDLE_TIME 0x66c ++#define PCIE_PHY_BEACON_2_IDLE_TIME_L 0x670 ++#define PCIE_PHY_BEACON_2_IDLE_TIME_H 0x674 ++#define PCIE_PHY_PWRUP_RESET_DLY_TIME_SYSCLK 0x678 ++#define PCIE_PHY_PWRUP_RESET_DLY_TIME_AUXCLK 0x67c ++#define PCIE_PHY_INSIG_SW_CTRL1 0x680 ++#define PCIE_PHY_INSIG_SW_CTRL2 0x684 ++#define PCIE_PHY_INSIG_MX_CTRL1 0x688 ++#define PCIE_PHY_INSIG_MX_CTRL2 0x68c ++#define PCIE_PHY_TEST_CONTROL 0x690 ++#define PCIE_PHY_BIST_CTRL 0x694 ++#define PCIE_PHY_PRBS_POLY0 0x698 ++#define PCIE_PHY_PRBS_POLY1 0x69c ++#define PCIE_PHY_PRBS_SEED0 0x6a0 ++#define PCIE_PHY_PRBS_SEED1 0x6a4 ++#define PCIE_PHY_FIXED_PAT_CTRL 0x6a8 ++#define PCIE_PHY_FIXED_PAT0 0x6ac ++#define PCIE_PHY_FIXED_PAT1 0x6b0 ++#define PCIE_PHY_FIXED_PAT2 0x6b4 ++#define PCIE_PHY_FIXED_PAT3 0x6b8 ++#define PCIE_PHY_BIST_CHK_ERR_CNT_L 0x6bc ++#define PCIE_PHY_BIST_CHK_ERR_CNT_H 0x6c0 ++#define PCIE_PHY_BIST_CHK_STATUS 0x6c4 ++#define PCIE_PHY_PCS_STATUS 0x6c8 ++#define PCIE_PHY_REVISION_ID0 0x6cc ++#define PCIE_PHY_REVISION_ID1 0x6d0 ++#define PCIE_PHY_REVISION_ID2 0x6d4 ++#define PCIE_PHY_REVISION_ID3 0x6d8 ++#define PCIE_PHY_DEBUG_BUS_0_STATUS 0x6dc ++#define PCIE_PHY_DEBUG_BUS_1_STATUS 0x6e0 ++#define PCIE_PHY_DEBUG_BUS_2_STATUS 0x6e4 ++#define PCIE_PHY_DEBUG_BUS_3_STATUS 0x6e8 ++#endif ++ ++#endif +-- +2.7.4 + diff --git a/target/linux/kirkwood/patches-4.9/202-linksys-find-active-root.patch b/target/linux/kirkwood/patches-4.9/202-linksys-find-active-root.patch index 28fc153bd..cb705e60c 100644 --- a/target/linux/kirkwood/patches-4.9/202-linksys-find-active-root.patch +++ b/target/linux/kirkwood/patches-4.9/202-linksys-find-active-root.patch @@ -41,7 +41,7 @@ Signed-off-by: Imre Kaloz parts[i].name = partname; if (of_get_property(pp, "read-only", &len)) -@@ -213,6 +222,18 @@ static int __init ofpart_parser_init(voi +@@ -220,6 +229,18 @@ static int __init ofpart_parser_init(voi return 0; } diff --git a/target/linux/layerscape/patches-4.9/201-config-support-layerscape.patch b/target/linux/layerscape/patches-4.9/201-config-support-layerscape.patch index 333a9d121..ccfce1df7 100644 --- a/target/linux/layerscape/patches-4.9/201-config-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/201-config-support-layerscape.patch @@ -45,7 +45,7 @@ Signed-off-by: Yangbo Lu --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig -@@ -237,6 +237,7 @@ config GENERIC_CPU_AUTOPROBE +@@ -240,6 +240,7 @@ config GENERIC_CPU_VULNERABILITIES config SOC_BUS bool diff --git a/target/linux/layerscape/patches-4.9/401-mtd-spi-nor-support-layerscape.patch b/target/linux/layerscape/patches-4.9/401-mtd-spi-nor-support-layerscape.patch index 362777317..e4e7ff47a 100644 --- a/target/linux/layerscape/patches-4.9/401-mtd-spi-nor-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/401-mtd-spi-nor-support-layerscape.patch @@ -856,7 +856,7 @@ Signed-off-by: Yangbo Lu static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info) { int status; -@@ -1604,9 +1693,25 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -1605,9 +1694,25 @@ int spi_nor_scan(struct spi_nor *nor, co write_sr(nor, 0); spi_nor_wait_till_ready(nor); } @@ -882,7 +882,7 @@ Signed-off-by: Yangbo Lu mtd->priv = nor; mtd->type = MTD_NORFLASH; mtd->writesize = 1; -@@ -1639,6 +1744,8 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -1641,6 +1746,8 @@ int spi_nor_scan(struct spi_nor *nor, co nor->flags |= SNOR_F_USE_FSR; if (info->flags & SPI_NOR_HAS_TB) nor->flags |= SNOR_F_HAS_SR_TB; @@ -891,7 +891,7 @@ Signed-off-by: Yangbo Lu #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS /* prefer "small sector" erase if possible */ -@@ -1678,9 +1785,15 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -1680,9 +1787,15 @@ int spi_nor_scan(struct spi_nor *nor, co /* Some devices cannot do fast-read, no matter what DT tells us */ if (info->flags & SPI_NOR_NO_FR) nor->flash_read = SPI_NOR_NORMAL; @@ -910,7 +910,7 @@ Signed-off-by: Yangbo Lu ret = set_quad_mode(nor, info); if (ret) { dev_err(dev, "quad mode not supported\n"); -@@ -1693,6 +1806,9 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -1695,6 +1808,9 @@ int spi_nor_scan(struct spi_nor *nor, co /* Default commands */ switch (nor->flash_read) { diff --git a/target/linux/layerscape/patches-4.9/703-phy-support-layerscape.patch b/target/linux/layerscape/patches-4.9/703-phy-support-layerscape.patch index 81c473c4d..907fb336a 100644 --- a/target/linux/layerscape/patches-4.9/703-phy-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.9/703-phy-support-layerscape.patch @@ -1741,7 +1741,7 @@ Signed-off-by: Yangbo Lu PHY_INTERFACE_MODE_MAX, } phy_interface_t; -@@ -780,6 +781,9 @@ int phy_stop_interrupts(struct phy_devic +@@ -791,6 +792,9 @@ int phy_stop_interrupts(struct phy_devic static inline int phy_read_status(struct phy_device *phydev) { diff --git a/target/linux/mvebu/Makefile b/target/linux/mvebu/Makefile index a07aa7cf2..ee76c0b77 100644 --- a/target/linux/mvebu/Makefile +++ b/target/linux/mvebu/Makefile @@ -6,20 +6,16 @@ # include $(TOPDIR)/rules.mk -ARCH:=arm BOARD:=mvebu -BOARDNAME:=Marvell Armada 37x/38x/XP -FEATURES:=fpu usb pci pcie gpio nand squashfs -CPU_TYPE:=cortex-a9 -CPU_SUBTYPE:=vfpv3 +BOARDNAME:=Marvell EBU Armada +FEATURES:=fpu usb pci pcie gpio nand squashfs ramdisk +SUBTARGETS:=cortexa9 cortexa53 cortexa72 MAINTAINER:=Imre Kaloz -KERNEL_PATCHVER:=4.9 +KERNEL_PATCHVER:=4.14 include $(INCLUDE_DIR)/target.mk -KERNELNAME:=zImage dtbs - DEFAULT_PACKAGES += uboot-envtools kmod-gpio-button-hotplug $(eval $(call BuildTarget)) diff --git a/target/linux/mvebu/base-files/etc/board.d/02_network b/target/linux/mvebu/base-files/etc/board.d/02_network index 4fc95406c..8e57e8e1c 100755 --- a/target/linux/mvebu/base-files/etc/board.d/02_network +++ b/target/linux/mvebu/base-files/etc/board.d/02_network @@ -23,6 +23,10 @@ armada-xp-linksys-mamba) ucidef_add_switch "switch0" \ "0:lan:4" "1:lan:3" "2:lan:2" "3:lan:1" "5@eth0" "4:wan" "6@eth1" ;; +armada-385-turris-omnia) + ucidef_set_interface_lan "lan0 lan1 lan2 lan3 lan4" + ucidef_set_interface_wan "eth2" + ;; armada-388-clearfog-*) # eth0 is standalone ethernet # eth1 is switch (-pro) or standalone ethernet (-base) @@ -38,6 +42,12 @@ armada-388-clearfog-*) armada-xp-gp) ucidef_set_interface_lan "eth0 eth1 eth2 eth3" ;; +globalscale,espressobin) + ucidef_set_interfaces_lan_wan "lan0 lan1" "wan" + ;; +marvell,armada8040-mcbin) + ucidef_set_interfaces_lan_wan "eth0 eth1 eth3" "eth2" + ;; *) ucidef_set_interface_lan "eth0" ;; diff --git a/target/linux/mvebu/base-files/etc/hotplug.d/ieee80211/00-wifi-config-migrate b/target/linux/mvebu/base-files/etc/hotplug.d/ieee80211/00-wifi-config-migrate new file mode 100644 index 000000000..a8173b311 --- /dev/null +++ b/target/linux/mvebu/base-files/etc/hotplug.d/ieee80211/00-wifi-config-migrate @@ -0,0 +1,41 @@ +#!/bin/sh + +# The pcie-controller device was renamed to pcie in Linux kernel 4.14 +# commit 28fbb9c539e2 ("ARM: dts: marvell: fix PCI bus dtc warnings"). +# This script migrates the path in the UCI configuration from the old +# name to the new name and also back, when am upgrade or downgrade is +# done. It checks if the name exists before changing the configuration. +# This has to be done before the 10-wifi-detect script from mac80211 is +# executed because this would add the devices again under the new path +# name. + +. /lib/functions.sh + +PATH_CHANGED=0 + +rename_wifi_path() { + local path_old=$(uci get wireless.${1}.path) + local path_new=$(echo ${path_old} | sed "${2}") + + if [ -e "/sys/devices/platform/${path_new}" ] && [ ${path_old} != ${path_new} ] + then + uci set wireless.${1}.path=${path_new} + PATH_CHANGED=1 + fi +} + +rename_wifi_path_list() { + # migration from kernel 4.9 to 4.14 + rename_wifi_path $1 "s/soc:pcie-controller/soc:pcie/" + # migration from kernel 4.14 to 4.9 + rename_wifi_path $1 "s/soc:pcie/soc:pcie-controller/" +} + +[ "${ACTION}" = "add" ] && { + [ ! -e /etc/config/wireless ] && return + + config_load wireless + config_foreach rename_wifi_path_list wifi-device + + [ "$PATH_CHANGED" = "1" ] && uci commit wireless +} diff --git a/target/linux/mvebu/base-files/lib/mvebu.sh b/target/linux/mvebu/base-files/lib/mvebu.sh index fb3ddee4f..840cc1ca2 100755 --- a/target/linux/mvebu/base-files/lib/mvebu.sh +++ b/target/linux/mvebu/base-files/lib/mvebu.sh @@ -17,6 +17,12 @@ mvebu_board_detect() { *"Marvell Armada 370 Evaluation Board") name="armada-370-db" ;; + *"Globalscale Marvell ESPRESSOBin Board") + name="globalscale,espressobin" + ;; + *"Marvell 8040 MACHIATOBin") + name="marvell,armada8040-mcbin" + ;; *"Globalscale Mirabox") name="mirabox" ;; @@ -59,6 +65,9 @@ mvebu_board_detect() { *"SolidRun Clearfog Base A1") name="armada-388-clearfog-base" ;; + *"Turris Omnia") + name="armada-385-turris-omnia" + ;; esac [ -z "$name" ] && name="unknown" diff --git a/target/linux/mvebu/base-files/lib/preinit/06_set_iface_mac b/target/linux/mvebu/base-files/lib/preinit/06_set_iface_mac index e884351bf..b56cbf50a 100644 --- a/target/linux/mvebu/base-files/lib/preinit/06_set_iface_mac +++ b/target/linux/mvebu/base-files/lib/preinit/06_set_iface_mac @@ -11,8 +11,8 @@ preinit_set_mac_address() { case $(board_name) in armada-xp-linksys-mamba) mac=$(mtd_get_mac_ascii devinfo hw_mac_addr) - ifconfig eth0 hw ether $mac 2>/dev/null - ifconfig eth1 hw ether $mac 2>/dev/null + ip link set dev eth0 address $mac 2>/dev/null + ip link set dev eth1 address $mac 2>/dev/null ;; armada-385-linksys-caiman|armada-385-linksys-cobra|armada-385-linksys-rango|armada-385-linksys-shelby) # rename interfaces back to the way they were with 4.4 @@ -26,8 +26,8 @@ preinit_set_mac_address() { mac=$(mtd_get_mac_ascii devinfo hw_mac_addr) mac_wan=$(macaddr_setbit_la "$mac") - ifconfig eth1 hw ether $mac 2>/dev/null - ifconfig eth0 hw ether $mac_wan 2>/dev/null + ip link set dev eth1 address $mac 2>/dev/null + ip link set dev eth0 address $mac_wan 2>/dev/null ;; armada-385-db-ap|armada-388-clearfog) # rename interfaces back to the way they were with 4.4 diff --git a/target/linux/mvebu/base-files/lib/preinit/79_move_config b/target/linux/mvebu/base-files/lib/preinit/79_move_config index b0ee62a80..1735ad884 100644 --- a/target/linux/mvebu/base-files/lib/preinit/79_move_config +++ b/target/linux/mvebu/base-files/lib/preinit/79_move_config @@ -10,8 +10,9 @@ move_config() { insmod fat insmod vfat mkdir -p /boot - mount -t vfat -o rw,noatime $BOOTPART /boot + mount -o rw,noatime $BOOTPART /boot [ -f /boot/sysupgrade.tgz ] && mv -f /boot/sysupgrade.tgz / + umount /boot fi } diff --git a/target/linux/mvebu/base-files/lib/upgrade/clearfog.sh b/target/linux/mvebu/base-files/lib/upgrade/clearfog.sh deleted file mode 100644 index 5388b2219..000000000 --- a/target/linux/mvebu/base-files/lib/upgrade/clearfog.sh +++ /dev/null @@ -1,32 +0,0 @@ -get_magic_at() { - local file="$1" - local pos="$2" - get_image "$file" | dd bs=1 count=2 skip="$pos" 2>/dev/null | hexdump -v -n 2 -e '1/1 "%02x"' -} - -platform_check_image_clearfog() { - local file="$1" - local magic - - magic=$(get_magic_at "$file" 510) - [ "$magic" != "55aa" ] && { - echo "Failed to verify MBR boot signature." - return 1 - } - - return 0; -} - -platform_do_upgrade_clearfog() { - sync - get_image "$1" | dd of=/dev/mmcblk0 bs=2M conv=fsync - sleep 1 -} - -platform_copy_config_clearfog() { - mkdir -p /boot - [ -f /boot/kernel.img ] || mount -t vfat -o rw,noatime /dev/mmcblk0p1 /boot - cp -af "$CONF_TAR" /boot/ - sync - umount /boot -} diff --git a/target/linux/mvebu/base-files/lib/upgrade/platform.sh b/target/linux/mvebu/base-files/lib/upgrade/platform.sh index 8241d1edc..15c543379 100755 --- a/target/linux/mvebu/base-files/lib/upgrade/platform.sh +++ b/target/linux/mvebu/base-files/lib/upgrade/platform.sh @@ -16,8 +16,8 @@ platform_do_upgrade() { armada-385-linksys-caiman|armada-385-linksys-cobra|armada-385-linksys-rango|armada-385-linksys-shelby|armada-xp-linksys-mamba) platform_do_upgrade_linksys "$ARGV" ;; - armada-388-clearfog-base|armada-388-clearfog-pro) - platform_do_upgrade_clearfog "$ARGV" + armada-385-turris-omnia|armada-388-clearfog-base|armada-388-clearfog-pro|globalscale,espressobin|marvell,armada8040-mcbin) + platform_do_upgrade_sdcard "$ARGV" ;; *) default_do_upgrade "$ARGV" @@ -29,18 +29,8 @@ platform_copy_config() { armada-385-linksys-caiman|armada-385-linksys-cobra|armada-385-linksys-rango|armada-385-linksys-shelby|armada-xp-linksys-mamba) platform_copy_config_linksys ;; - armada-388-clearfog-base|armada-388-clearfog-pro) - platform_copy_config_clearfog "$ARGV" + armada-385-turris-omnia|armada-388-clearfog-base|armada-388-clearfog-pro|globalscale,espressobin|marvell,armada8040-mcbin) + platform_copy_config_sdcard "$ARGV" ;; esac } - -disable_watchdog() { - killall watchdog - ( ps | grep -v 'grep' | grep '/dev/watchdog' ) && { - echo 'Could not disable watchdog' - return 1 - } -} - -append sysupgrade_pre_upgrade disable_watchdog diff --git a/target/linux/mvebu/base-files/lib/upgrade/sdcard.sh b/target/linux/mvebu/base-files/lib/upgrade/sdcard.sh new file mode 100644 index 000000000..a05df834b --- /dev/null +++ b/target/linux/mvebu/base-files/lib/upgrade/sdcard.sh @@ -0,0 +1,44 @@ +get_magic_at() { + local file="$1" + local pos="$2" + get_image "$file" | dd bs=1 count=2 skip="$pos" 2>/dev/null | hexdump -v -n 2 -e '1/1 "%02x"' +} + +platform_check_image_sdcard() { + local file="$1" + local magic + + magic=$(get_magic_at "$file" 510) + [ "$magic" != "55aa" ] && { + echo "Failed to verify MBR boot signature." + return 1 + } + + return 0; +} + +platform_do_upgrade_sdcard() { + local board=$(board_name) + + sync + get_image "$1" | dd of=/dev/mmcblk0 bs=2M conv=fsync + + case "$board" in + armada-385-turris-omnia) + fw_setenv openwrt_bootargs 'earlyprintk console=ttyS0,115200 root=/dev/mmcblk0p2 rootfstype=auto rootwait' + fw_setenv openwrt_mmcload 'setenv bootargs "$openwrt_bootargs cfg80211.freg=$regdomain"; fatload mmc 0 0x01000000 zImage; fatload mmc 0 0x02000000 armada-385-turris-omnia.dtb' + fw_setenv factory_mmcload 'setenv bootargs "$bootargs cfg80211.freg=$regdomain"; btrload mmc 0 0x01000000 boot/zImage @; btrload mmc 0 0x02000000 boot/dtb @' + fw_setenv mmcboot 'run openwrt_mmcload || run factory_mmcload; bootz 0x01000000 - 0x02000000' + ;; + esac + + sleep 1 +} + +platform_copy_config_sdcard() { + mkdir -p /boot + [ -f /boot/kernel.img ] || mount -o rw,noatime /dev/mmcblk0p1 /boot + cp -af "$CONF_TAR" /boot/ + sync + umount /boot +} diff --git a/target/linux/mvebu/config-4.14 b/target/linux/mvebu/config-4.14 new file mode 100644 index 000000000..5286bf9b8 --- /dev/null +++ b/target/linux/mvebu/config-4.14 @@ -0,0 +1,497 @@ +CONFIG_AHCI_MVEBU=y +CONFIG_ALIGNMENT_TRAP=y +CONFIG_ARCH_CLOCKSOURCE_DATA=y +CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +CONFIG_ARCH_HAS_SET_MEMORY=y +CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y +CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MULTIPLATFORM=y +# CONFIG_ARCH_MULTI_CPU_AUTO is not set +CONFIG_ARCH_MULTI_V6_V7=y +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_MVEBU=y +CONFIG_ARCH_NR_GPIO=0 +CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +# CONFIG_ARCH_WANTS_THP_SWAP is not set +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_ARM=y +CONFIG_ARMADA_370_CLK=y +CONFIG_ARMADA_370_XP_IRQ=y +CONFIG_ARMADA_370_XP_TIMER=y +CONFIG_ARMADA_38X_CLK=y +CONFIG_ARMADA_THERMAL=y +CONFIG_ARMADA_XP_CLK=y +CONFIG_ARM_APPENDED_DTB=y +# CONFIG_ARM_ARMADA_37XX_CPUFREQ is not set +CONFIG_ARM_ATAG_DTB_COMPAT=y +# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set +CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_ARM_CRYPTO=y +CONFIG_ARM_ERRATA_720789=y +CONFIG_ARM_ERRATA_764369=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GLOBAL_TIMER=y +CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_ARM_HEAVY_MB=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_L1_CACHE_SHIFT_6=y +# CONFIG_ARM_LPAE is not set +CONFIG_ARM_MVEBU_V7_CPUIDLE=y +CONFIG_ARM_PATCH_IDIV=y +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_ARM_UNWIND=y +CONFIG_ARM_VIRT_EXT=y +CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=y +CONFIG_ATA=y +CONFIG_ATAGS=y +CONFIG_AUTO_ZRELADDR=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_SCSI_REQUEST=y +CONFIG_BOUNCE=y +# CONFIG_CACHE_FEROCEON_L2 is not set +CONFIG_CACHE_L2X0=y +CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +# CONFIG_CPU_BIG_ENDIAN is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_HAS_ASID=y +# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_PJ4B=y +CONFIG_CPU_PM=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_THERMAL=y +CONFIG_CPU_THUMB_CAPABLE=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_V7=y +CONFIG_CRC16=y +CONFIG_CRYPTO_ACOMP2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_AES_ARM_BS=y +# CONFIG_CRYPTO_AES_ARM_CE is not set +# CONFIG_CRYPTO_CHACHA20_NEON is not set +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32_ARM_CE is not set +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_DEV_MARVELL_CESA=y +# CONFIG_CRYPTO_GHASH_ARM_CE is not set +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_NULL2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y +# CONFIG_CRYPTO_SHA1_ARM_CE is not set +CONFIG_CRYPTO_SHA1_ARM_NEON=y +CONFIG_CRYPTO_SHA256_ARM=y +# CONFIG_CRYPTO_SHA2_ARM_CE is not set +CONFIG_CRYPTO_SHA512_ARM=y +CONFIG_CRYPTO_SIMD=y +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_ALIGN_RODATA=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_LL=y +CONFIG_DEBUG_LL_INCLUDE="debug/8250.S" +CONFIG_DEBUG_MVEBU_UART0=y +# CONFIG_DEBUG_MVEBU_UART0_ALTERNATE is not set +# CONFIG_DEBUG_MVEBU_UART1_ALTERNATE is not set +CONFIG_DEBUG_UART_8250=y +# CONFIG_DEBUG_UART_8250_FLOW_CONTROL is not set +CONFIG_DEBUG_UART_8250_SHIFT=2 +# CONFIG_DEBUG_UART_8250_WORD is not set +CONFIG_DEBUG_UART_PHYS=0xd0012000 +CONFIG_DEBUG_UART_VIRT=0xfec12000 +CONFIG_DEBUG_UNCOMPRESS=y +CONFIG_DEBUG_USER=y +CONFIG_DMADEVICES=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_ENGINE_RAID=y +# CONFIG_DMA_NOOP_OPS is not set +CONFIG_DMA_OF=y +# CONFIG_DMA_VIRT_OPS is not set +# CONFIG_DRM_LIB_RANDOM is not set +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EXPORTFS=y +CONFIG_EXT4_FS=y +CONFIG_EXTCON=y +# CONFIG_F2FS_CHECK_FS is not set +CONFIG_F2FS_FS=y +# CONFIG_F2FS_FS_SECURITY is not set +CONFIG_F2FS_FS_XATTR=y +CONFIG_F2FS_STAT_FS=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FS_MBCACHE=y +CONFIG_FUTEX_PI=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IO=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GLOB=y +CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_GENERIC=y +CONFIG_GPIO_GENERIC_PLATFORM=y +CONFIG_GPIO_MVEBU=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_GPIO_SYSFS=y +# CONFIG_GRO_CELLS is not set +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_ARCH_AUDITSYSCALL=y +CONFIG_HAVE_ARCH_BITREVERSE=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_ARM_SCU=y +CONFIG_HAVE_ARM_SMCCC=y +CONFIG_HAVE_ARM_TWD=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_DEBUG_KMEMLEAK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_HAVE_EBPF_JIT=y +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_HAVE_NET_DSA=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_OPTPROBES=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_SMP=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_UID16=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HOTPLUG_CPU=y +CONFIG_HWBM=y +CONFIG_HWMON=y +CONFIG_HZ_FIXED=0 +CONFIG_HZ_PERIODIC=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MV64XXX=y +# CONFIG_I2C_PXA is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IOMMU_HELPER=y +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_DEBUG=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_WORK=y +# CONFIG_IWMMXT is not set +CONFIG_JBD2=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PCA963X=y +CONFIG_LEDS_TLC591XX=y +CONFIG_LEDS_TRIGGER_DISK=y +CONFIG_LIBFDT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MACH_ARMADA_370=y +# CONFIG_MACH_ARMADA_375 is not set +CONFIG_MACH_ARMADA_38X=y +# CONFIG_MACH_ARMADA_39X is not set +CONFIG_MACH_ARMADA_XP=y +# CONFIG_MACH_DOVE is not set +CONFIG_MACH_MVEBU_ANY=y +CONFIG_MACH_MVEBU_V7=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MANGLE_BOOTARGS=y +CONFIG_MARVELL_PHY=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_I2C=y +CONFIG_MEMORY=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_MIGHT_HAVE_PCI=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_MVSDIO=y +CONFIG_MMC_SDHCI=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_PXAV3=y +# CONFIG_MMC_TIFM_SD is not set +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_M25P80=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_PXA3xx=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MULTI_IRQ_HANDLER=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_MVEBU_CLK_COMMON=y +CONFIG_MVEBU_CLK_COREDIV=y +CONFIG_MVEBU_CLK_CPU=y +CONFIG_MVEBU_DEVBUS=y +CONFIG_MVEBU_MBUS=y +CONFIG_MVMDIO=y +CONFIG_MVNETA=y +CONFIG_MVNETA_BM=y +CONFIG_MVNETA_BM_ENABLE=y +CONFIG_MVPP2=y +CONFIG_MVSW61XX_PHY=y +CONFIG_MV_XOR=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEON=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_MV88E6XXX=y +CONFIG_NET_DSA_MV88E6XXX_GLOBAL2=y +CONFIG_NET_DSA_TAG_DSA=y +CONFIG_NET_DSA_TAG_EDSA=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_SWITCHDEV=y +CONFIG_NLS=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_NO_BOOTMEM=y +CONFIG_NR_CPUS=4 +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_MDIO=y +CONFIG_OF_NET=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_OF_RESERVED_MEM=y +CONFIG_OLD_SIGACTION=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_ORION_WATCHDOG=y +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_PADATA=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PCI_MVEBU=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +CONFIG_PHYLINK=y +# CONFIG_PHY_MVEBU_CP110_COMPHY is not set +CONFIG_PINCTRL=y +CONFIG_PINCTRL_ARMADA_370=y +CONFIG_PINCTRL_ARMADA_38X=y +CONFIG_PINCTRL_ARMADA_XP=y +CONFIG_PINCTRL_MVEBU=y +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_PJ4B_ERRATA_4742=y +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_PL310_ERRATA_753970 is not set +# CONFIG_PL310_ERRATA_769419 is not set +CONFIG_PLAT_ORION=y +CONFIG_PM_OPP=y +CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=11 +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +CONFIG_RATIONAL=y +CONFIG_RCU_NEED_SEGCBLIST=y +CONFIG_RCU_STALL_COMMON=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_SPI=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_ARMADA38X=y +CONFIG_RTC_DRV_MV=y +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RTC_MC146818_LIB=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_SATA_MV=y +# CONFIG_SCHED_INFO is not set +CONFIG_SCSI=y +CONFIG_SENSORS_PWM_FAN=y +CONFIG_SENSORS_TMP421=y +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_MVEBU_CONSOLE=y +CONFIG_SERIAL_MVEBU_UART=y +CONFIG_SFP=y +CONFIG_SG_POOL=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_SOC_BUS=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +# CONFIG_SPI_ARMADA_3700 is not set +CONFIG_SPI_MASTER=y +CONFIG_SPI_ORION=y +CONFIG_SRAM=y +CONFIG_SRAM_EXEC=y +CONFIG_SRCU=y +CONFIG_SWCONFIG=y +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SWP_EMULATE=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THIN_ARCHIVES=y +# CONFIG_THUMB2_KERNEL is not set +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_HCD_ORION=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_LEDS_TRIGGER_USBPORT=y +CONFIG_USB_PHY=y +CONFIG_USB_STORAGE=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_MVEBU=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USE_OF=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_WATCHDOG_CORE=y +CONFIG_XPS=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y diff --git a/target/linux/mvebu/config-4.9 b/target/linux/mvebu/config-4.9 index 87040a493..743f667fb 100644 --- a/target/linux/mvebu/config-4.9 +++ b/target/linux/mvebu/config-4.9 @@ -38,6 +38,7 @@ CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y CONFIG_ARM_CPU_SUSPEND=y CONFIG_ARM_CRYPTO=y CONFIG_ARM_ERRATA_720789=y +CONFIG_ARM_ERRATA_764369=y CONFIG_ARM_GIC=y CONFIG_ARM_HAS_SG_CHAIN=y CONFIG_ARM_HEAVY_MB=y diff --git a/target/linux/mvebu/cortexa53/config-default b/target/linux/mvebu/cortexa53/config-default new file mode 100644 index 000000000..0ee5d3cca --- /dev/null +++ b/target/linux/mvebu/cortexa53/config-default @@ -0,0 +1,112 @@ +CONFIG_64BIT=y +# CONFIG_ACPI is not set +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_ARCH_HAS_FORTIFY_SOURCE=y +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y +CONFIG_ARCH_HAS_KCOV=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +# CONFIG_ARCH_OPTIONAL_KERNEL_RWX is not set +# CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT is not set +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y +CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARM64=y +# CONFIG_ARM64_16K_PAGES is not set +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_64K_PAGES is not set +CONFIG_ARM64_CONT_SHIFT=4 +# CONFIG_ARM64_CRYPTO is not set +# CONFIG_ARM64_HW_AFDBM is not set +# CONFIG_ARM64_LSE_ATOMICS is not set +CONFIG_ARM64_PAGE_SHIFT=12 +# CONFIG_ARM64_PAN is not set +# CONFIG_ARM64_PMEM is not set +# CONFIG_ARM64_PTDUMP_CORE is not set +# CONFIG_ARM64_PTDUMP_DEBUGFS is not set +# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set +# CONFIG_ARM64_SW_TTBR0_PAN is not set +# CONFIG_ARM64_UAO is not set +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_VA_BITS_39=y +# CONFIG_ARM64_VA_BITS_48 is not set +# CONFIG_ARM64_VHE is not set +CONFIG_ARMADA_37XX_CLK=y +CONFIG_ARMADA_AP806_SYSCON=y +CONFIG_ARMADA_CP110_SYSCON=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_ARMADA_37XX_CPUFREQ=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +# CONFIG_ARM_PL172_MPMC is not set +CONFIG_ARM_PSCI_FW=y +# CONFIG_ARM_SP805_WATCHDOG is not set +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +# CONFIG_COMPAT is not set +# CONFIG_DEBUG_ALIGN_RODATA is not set +CONFIG_FRAME_POINTER=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y +CONFIG_HAVE_ARCH_HUGE_VMAP=y +CONFIG_HAVE_ARCH_KASAN=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_HAVE_ARCH_VMAP_STACK=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_HAVE_CMPXCHG_LOCAL=y +CONFIG_HAVE_DEBUG_BUGVERBOSE=y +CONFIG_HAVE_GENERIC_GUP=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_HAVE_PATA_PLATFORM=y +CONFIG_HAVE_RCU_TABLE_FREE=y +# CONFIG_HUGETLBFS is not set +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_MFD_SYSCON=y +CONFIG_MMC_SDHCI_XENON=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MVEBU_GICP=y +CONFIG_MVEBU_ICU=y +CONFIG_MVEBU_ODMI=y +CONFIG_MVEBU_PIC=y +CONFIG_NEED_SG_DMA_LENGTH=y +# CONFIG_NUMA is not set +CONFIG_PARTITION_PERCPU=y +CONFIG_PCI_AARDVARK=y +CONFIG_PCI_BUS_ADDR_T_64BIT=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PINCTRL_ARMADA_37XX=y +CONFIG_PINCTRL_ARMADA_AP806=y +CONFIG_PINCTRL_ARMADA_CP110=y +CONFIG_POWER_RESET=y +CONFIG_POWER_SUPPLY=y +# CONFIG_RANDOMIZE_BASE is not set +CONFIG_REGULATOR_GPIO=y +# CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPI_ARMADA_3700=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_VMAP_STACK=y diff --git a/target/linux/mvebu/cortexa53/target.mk b/target/linux/mvebu/cortexa53/target.mk new file mode 100644 index 000000000..acc18d345 --- /dev/null +++ b/target/linux/mvebu/cortexa53/target.mk @@ -0,0 +1,15 @@ +# +# Copyright (C) 2017 Hauke Mehrtens +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +ARCH:=aarch64 +BOARDNAME:=Marvell Armada 3700LP (ARM64) +CPU_TYPE:=cortex-a53 +FEATURES+=ext4 + +KERNELNAME:=Image dtbs diff --git a/target/linux/mvebu/cortexa72/config-default b/target/linux/mvebu/cortexa72/config-default new file mode 100644 index 000000000..c793f7c5e --- /dev/null +++ b/target/linux/mvebu/cortexa72/config-default @@ -0,0 +1,120 @@ +CONFIG_64BIT=y +# CONFIG_ACPI is not set +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_ARCH_HAS_FORTIFY_SOURCE=y +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y +CONFIG_ARCH_HAS_KCOV=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +# CONFIG_ARCH_OPTIONAL_KERNEL_RWX is not set +# CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT is not set +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y +CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARM64=y +# CONFIG_ARM64_16K_PAGES is not set +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_64K_PAGES is not set +CONFIG_ARM64_CONT_SHIFT=4 +# CONFIG_ARM64_CRYPTO is not set +# CONFIG_ARM64_HW_AFDBM is not set +# CONFIG_ARM64_LSE_ATOMICS is not set +CONFIG_ARM64_PAGE_SHIFT=12 +# CONFIG_ARM64_PAN is not set +# CONFIG_ARM64_PMEM is not set +# CONFIG_ARM64_PTDUMP_CORE is not set +# CONFIG_ARM64_PTDUMP_DEBUGFS is not set +# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set +# CONFIG_ARM64_SW_TTBR0_PAN is not set +# CONFIG_ARM64_UAO is not set +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_VA_BITS_39=y +# CONFIG_ARM64_VA_BITS_48 is not set +# CONFIG_ARM64_VHE is not set +CONFIG_ARMADA_AP806_SYSCON=y +CONFIG_ARMADA_CP110_SYSCON=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +# CONFIG_ARM_PL172_MPMC is not set +CONFIG_ARM_PSCI_FW=y +# CONFIG_ARM_SP805_WATCHDOG is not set +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +# CONFIG_COMPAT is not set +# CONFIG_DEBUG_ALIGN_RODATA is not set +CONFIG_FRAME_POINTER=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y +CONFIG_HAVE_ARCH_HUGE_VMAP=y +CONFIG_HAVE_ARCH_KASAN=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_HAVE_ARCH_VMAP_STACK=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_HAVE_CMPXCHG_LOCAL=y +CONFIG_HAVE_DEBUG_BUGVERBOSE=y +CONFIG_HAVE_GENERIC_GUP=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_HAVE_PATA_PLATFORM=y +CONFIG_HAVE_RCU_TABLE_FREE=y +# CONFIG_HUGETLBFS is not set +CONFIG_I2C_MUX_PCA954x=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_MFD_SYSCON=y +CONFIG_MMC_SDHCI_XENON=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MV_XOR_V2=y +CONFIG_MVEBU_GICP=y +CONFIG_MVEBU_ICU=y +CONFIG_MVEBU_ODMI=y +CONFIG_MVEBU_PIC=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_MV88E6XXX=y +CONFIG_NET_DSA_MV88E6XXX_GLOBAL2=y +# CONFIG_NET_DSA_SMSC_LAN9303_I2C is not set +CONFIG_NET_DSA_TAG_DSA=y +CONFIG_NET_DSA_TAG_EDSA=y +CONFIG_NET_SWITCHDEV=y +# CONFIG_NUMA is not set +CONFIG_PARTITION_PERCPU=y +CONFIG_PCIEAER=y +CONFIG_PCIE_ARMADA_8K=y +# CONFIG_PCI_AARDVARK is not set +CONFIG_PCI_BUS_ADDR_T_64BIT=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHY_MVEBU_CP110_COMPHY=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PINCTRL_ARMADA_AP806=y +CONFIG_PINCTRL_ARMADA_CP110=y +CONFIG_POWER_RESET=y +CONFIG_POWER_SUPPLY=y +# CONFIG_RANDOMIZE_BASE is not set +CONFIG_REGULATOR_GPIO=y +# CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_VMAP_STACK=y diff --git a/target/linux/mvebu/cortexa72/target.mk b/target/linux/mvebu/cortexa72/target.mk new file mode 100644 index 000000000..670c402a5 --- /dev/null +++ b/target/linux/mvebu/cortexa72/target.mk @@ -0,0 +1,15 @@ +# +# Copyright (C) 2018 Sartura Ltd. +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +ARCH:=aarch64 +BOARDNAME:=Marvell Armada 7k/8k (ARM64) +CPU_TYPE:=cortex-a72 +FEATURES+=ext4 + +KERNELNAME:=Image dtbs diff --git a/target/linux/mvebu/cortexa9/target.mk b/target/linux/mvebu/cortexa9/target.mk new file mode 100644 index 000000000..2a75599bc --- /dev/null +++ b/target/linux/mvebu/cortexa9/target.mk @@ -0,0 +1,14 @@ +# +# Copyright (C) 2017 Hauke Mehrtens +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +ARCH:=arm +BOARDNAME:=Marvell Armada 37x/38x/XP +CPU_TYPE:=cortex-a9 +CPU_SUBTYPE:=vfpv3 +KERNELNAME:=zImage dtbs diff --git a/target/linux/mvebu/files/arch/arm/boot/dts/armada-385-linksys-rango.dts b/target/linux/mvebu/files-4.4/arch/arm/boot/dts/armada-385-linksys-rango.dts similarity index 99% rename from target/linux/mvebu/files/arch/arm/boot/dts/armada-385-linksys-rango.dts rename to target/linux/mvebu/files-4.4/arch/arm/boot/dts/armada-385-linksys-rango.dts index de1de79da..ac4ac1b1b 100644 --- a/target/linux/mvebu/files/arch/arm/boot/dts/armada-385-linksys-rango.dts +++ b/target/linux/mvebu/files-4.4/arch/arm/boot/dts/armada-385-linksys-rango.dts @@ -186,6 +186,8 @@ flash@d0000 { status = "okay"; num-cs = <1>; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; marvell,nand-keep-config; marvell,nand-enable-arbiter; nand-on-flash-bbt; diff --git a/target/linux/mvebu/files/arch/arm/boot/dts/armada-385-linksys-shelby.dts b/target/linux/mvebu/files-4.4/arch/arm/boot/dts/armada-385-linksys-shelby.dts similarity index 100% rename from target/linux/mvebu/files/arch/arm/boot/dts/armada-385-linksys-shelby.dts rename to target/linux/mvebu/files-4.4/arch/arm/boot/dts/armada-385-linksys-shelby.dts diff --git a/target/linux/mvebu/files-4.9/arch/arm/boot/dts/armada-385-linksys-rango.dts b/target/linux/mvebu/files-4.9/arch/arm/boot/dts/armada-385-linksys-rango.dts new file mode 100644 index 000000000..ac4ac1b1b --- /dev/null +++ b/target/linux/mvebu/files-4.9/arch/arm/boot/dts/armada-385-linksys-rango.dts @@ -0,0 +1,455 @@ +/* + * Device Tree file for the Linksys WRT3200ACM (Rango) + * + * Copyright (C) 2016 Imre Kaloz + * + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without + * any warranty of any kind, whether express or implied. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include +#include +#include "armada-385.dtsi" + +/ { + model = "Linksys WRT3200ACM"; + compatible = "linksys,rango", "linksys,armada385", "marvell,armada385", + "marvell,armada380"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x20000000>; /* 512 MB */ + }; + + soc { + ranges = ; + + internal-regs { + + spi@10600 { + status = "disabled"; + }; + + i2c@11000 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + tmp421@4c { + compatible = "ti,tmp421"; + reg = <0x4c>; + }; + + pca9635@68 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "nxp,pca9635"; + reg = <0x68>; + + wan_amber@0 { + label = "rango:amber:wan"; + reg = <0x0>; + }; + + wan_white@1 { + label = "rango:white:wan"; + reg = <0x1>; + }; + + usb2@5 { + label = "rango:white:usb2"; + reg = <0x5>; + }; + + usb3_1@6 { + label = "rango:white:usb3_1"; + reg = <0x6>; + }; + + usb3_2@7 { + label = "rango:white:usb3_2"; + reg = <0x7>; + }; + + wps_white@8 { + label = "rango:white:wps"; + reg = <0x8>; + }; + + wps_amber@9 { + label = "rango:amber:wps"; + reg = <0x9>; + }; + }; + }; + + /* J10: VCC, NC, RX, NC, TX, GND */ + serial@12000 { + status = "okay"; + }; + + ethernet@70000 { + status = "okay"; + phy-mode = "rgmii-id"; + buffer-manager = <&bm>; + bm,pool-long = <0>; + bm,pool-short = <3>; + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + ethernet@34000 { + status = "okay"; + phy-mode = "sgmii"; + buffer-manager = <&bm>; + bm,pool-long = <2>; + bm,pool-short = <3>; + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + mdio { + status = "okay"; + }; + + bm@c8000 { + status = "okay"; + }; + + sata@a8000 { + status = "okay"; + }; + + sdhci@d8000 { + pinctrl-names = "default"; + pinctrl-0 = <&sdhci_pins>; + no-1-8-v; + broken-cd; + wp-inverted; + bus-width = <8>; + status = "okay"; + }; + + /* USB part of the eSATA/USB 2.0 port */ + usb@58000 { + status = "okay"; + }; + + usb3@f8000 { + status = "okay"; + usb-phy = <&usb3_phy>; + }; + + flash@d0000 { + status = "okay"; + num-cs = <1>; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + marvell,nand-keep-config; + marvell,nand-enable-arbiter; + nand-on-flash-bbt; + + partition@0 { + label = "u-boot"; + reg = <0x0000000 0x200000>; /* 2MB */ + read-only; + }; + + partition@200000 { + label = "u_env"; + reg = <0x200000 0x20000>; /* 128KB */ + }; + + partition@220000 { + label = "s_env"; + reg = <0x220000 0x40000>; /* 256KB */ + }; + + partition@7e0000 { + label = "devinfo"; + reg = <0x7e0000 0x40000>; /* 256KB */ + read-only; + }; + + partition@820000 { + label = "sysdiag"; + reg = <0x820000 0x1e0000>; /* 1920KB */ + read-only; + }; + + /* kernel1 overlaps with rootfs1 by design */ + partition@a00000 { + label = "kernel1"; + reg = <0xa00000 0x5000000>; /* 80MB */ + }; + + partition@1000000 { + label = "rootfs1"; + reg = <0x1000000 0x4a00000>; /* 74MB */ + }; + + /* kernel2 overlaps with rootfs2 by design */ + partition@5a00000 { + label = "kernel2"; + reg = <0x5a00000 0x5000000>; /* 80MB */ + }; + + partition@6000000 { + label = "rootfs2"; + reg = <0x6000000 0x4a00000>; /* 74MB */ + }; + + /* + * 86MB, last MB is for the BBT, not writable + */ + partition@aa00000 { + label = "syscfg"; + reg = <0xaa00000 0x5600000>; + }; + + /* + * Unused area between "s_env" and "devinfo". + * Moved here because otherwise the renumbered + * partitions would break the bootloader + * supplied bootargs + */ + partition@180000 { + label = "unused_area"; + reg = <0x260000 0x5c0000>; /* 5.75MB */ + }; + }; + }; + + bm-bppi { + status = "okay"; + }; + + pcie-controller { + status = "okay"; + + pcie@1,0 { + /* Marvell 88W8964, 5GHz-only */ + status = "okay"; + + mwlwifi { + marvell,2ghz = <0>; + marvell,chainmask = <4 4>; + }; + + }; + + pcie@2,0 { + /* Marvell 88W8964, 2GHz-only */ + status = "okay"; + + mwlwifi { + marvell,5ghz = <0>; + marvell,chainmask = <4 4>; + }; + + }; + }; + }; + + usb3_phy: usb3_phy { + compatible = "usb-nop-xceiv"; + vcc-supply = <®_xhci0_vbus>; + }; + + reg_xhci0_vbus: xhci0-vbus { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&xhci0_vbus_pins>; + regulator-name = "xhci0-vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio1 15 GPIO_ACTIVE_HIGH>; + }; + + gpio_keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-0 = <&reset_key_pin &wps_key_pin>; + pinctrl-names = "default"; + + button@1 { + label = "WPS"; + linux,code = ; + gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + }; + + button@2 { + label = "Factory Reset Button"; + linux,code = ; + gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + pinctrl-0 = <&power_led_pin &sata_led_pin &wlan_2g_led_pin &wlan_5g_led_pin>; + pinctrl-names = "default"; + + sata { + label = "rango:white:sata"; + gpios = <&gpio0 21 GPIO_ACTIVE_LOW>; + linux,default-trigger = "disk-activity"; + }; + + wlan_2g { + label = "rango:white:wlan_2g"; + gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; + }; + + wlan_5g { + label = "rango:white:wlan_5g"; + gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; + }; + + power { + label = "rango:white:power"; + gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + }; + + dsa@0 { + compatible = "marvell,dsa"; + #address-cells = <2>; + #size-cells = <0>; + + dsa,ethernet = <ð2>; + dsa,mii-bus = <&mdio>; + + switch@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0>; /* MDIO address 0, switch 0 in tree */ + + port@0 { + reg = <0>; + label = "lan4"; + }; + + port@1 { + reg = <1>; + label = "lan3"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@3 { + reg = <3>; + label = "lan1"; + }; + + port@4 { + reg = <4>; + label = "wan"; + }; + + port@5 { + reg = <5>; + label = "cpu"; + }; + }; + }; + + mvsw61xx { + #address-cells = <1>; + #size-cells = <0>; + compatible = "marvell,88e6352"; + status = "okay"; + reg = <0x10>; + + mii-bus = <&mdio>; + cpu-port-0 = <5>; + cpu-port-1 = <6>; + }; + +}; + +&pinctrl { + sata_led_pin: sata-led-pin { + marvell,pins = "mpp21"; + marvell,function = "gpio"; + }; + + wps_key_pin: wps-key-pin { + marvell,pins = "mpp24"; + marvell,function = "gpio"; + }; + + reset_key_pin: reset-key-pin { + marvell,pins = "mpp29"; + marvell,function = "gpio"; + }; + + wlan_2g_led_pin: wlan-2g-led-pin { + marvell,pins = "mpp45"; + marvell,function = "gpio"; + }; + + wlan_5g_led_pin: wlan-5g-led-pin { + marvell,pins = "mpp46"; + marvell,function = "gpio"; + }; + + xhci0_vbus_pins: xhci0-vbus-pins { + marvell,pins = "mpp47"; + marvell,function = "gpio"; + }; + + power_led_pin: power-led-pin { + marvell,pins = "mpp56"; + marvell,function = "gpio"; + }; +}; diff --git a/target/linux/mvebu/files-4.9/arch/arm/boot/dts/armada-385-linksys-shelby.dts b/target/linux/mvebu/files-4.9/arch/arm/boot/dts/armada-385-linksys-shelby.dts new file mode 100644 index 000000000..f8dd193ef --- /dev/null +++ b/target/linux/mvebu/files-4.9/arch/arm/boot/dts/armada-385-linksys-shelby.dts @@ -0,0 +1,115 @@ +/* + * Device Tree file for the Linksys WRT1900ACS (Shelby) + * + * Copyright (C) 2015 Imre Kaloz + * + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without + * any warranty of any kind, whether express or implied. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "armada-385-linksys.dtsi" + +/ { + model = "Linksys WRT1900ACS"; + compatible = "linksys,shelby", "linksys,armada385", "marvell,armada385", + "marvell,armada380"; + + soc { + internal-regs{ + i2c@11000 { + + pca9635@68 { + #address-cells = <1>; + #size-cells = <0>; + + wan_amber@0 { + label = "shelby:amber:wan"; + reg = <0x0>; + }; + + wan_white@1 { + label = "shelby:white:wan"; + reg = <0x1>; + }; + + wlan_2g@2 { + label = "shelby:white:wlan_2g"; + reg = <0x2>; + }; + + wlan_5g@3 { + label = "shelby:white:wlan_5g"; + reg = <0x3>; + }; + + usb2@5 { + label = "shelby:white:usb2"; + reg = <0x5>; + }; + + usb3_1@6 { + label = "shelby:white:usb3_1"; + reg = <0x6>; + }; + + usb3_2@7 { + label = "shelby:white:usb3_2"; + reg = <0x7>; + }; + + wps_white@8 { + label = "shelby:white:wps"; + reg = <0x8>; + }; + + wps_amber@9 { + label = "shelby:amber:wps"; + reg = <0x9>; + }; + }; + }; + }; + }; + + gpio-leds { + power { + label = "shelby:white:power"; + }; + + sata { + label = "shelby:white:sata"; + linux,default-trigger = "disk-activity"; + }; + }; +}; diff --git a/target/linux/mvebu/image/Makefile b/target/linux/mvebu/image/Makefile index 989ba5084..be01623e8 100644 --- a/target/linux/mvebu/image/Makefile +++ b/target/linux/mvebu/image/Makefile @@ -13,8 +13,10 @@ include $(INCLUDE_DIR)/image.mk KERNEL_LOADADDR := 0x00008000 +SIGNATURE:=$(shell printf "%.8s" $(SOURCE_DATE_EPOCH)) + define Build/dtb - $(call Image/BuildDTB,$(DTS_DIR)/$(DEVICE_DTS).dts,$@.dtb) + $(call Image/BuildDTB,$(DTS_DIR)/$(DEVICE_DTS).dts,$@.dtb) endef # SD-Card Images: @@ -23,32 +25,61 @@ endef # Partition 1: 32768 sectors # Partition 2: 98304 sectors (configurable) -define Build/boot-scr-cfpro - rm -f $@.bootscript - mkimage -A arm -O linux -T script -C none -a 0 -e 0 -d cfpro-boot.script $@.bootscript -endef - -define Build/boot-scr-cfbase - rm -f $@.bootscript - mkimage -A arm -O linux -T script -C none -a 0 -e 0 -d cfbase-boot.script $@.bootscript +define Build/boot-scr + rm -f $@-boot.scr + sed -e 's#@ROOT@#$(SIGNATURE)#g' \ + $(DEVICE_NAME).bootscript > $@-new.bootscript + mkimage -A arm -O linux -T script -C none -a 0 -e 0 -d $@-new.bootscript $@-boot.scr endef define Build/boot-img rm -f $@.boot mkfs.fat -C $@.boot 16384 $(foreach dts,$(DEVICE_DTS), mcopy -i $@.boot $(DTS_DIR)/$(dts).dtb ::$(dts).dtb;) - mcopy -i $@.boot $(IMAGE_KERNEL) ::zImage - mcopy -i $@.boot $@.bootscript ::boot.scr + mcopy -i $@.boot $(IMAGE_KERNEL) ::$(KERNEL_NAME) + -mcopy -i $@.boot $@-boot.scr ::boot.scr +endef + +define Build/boot-img-ext4 + rm -fR $@.boot + mkdir -p $@.boot + $(foreach dts,$(DEVICE_DTS), $(CP) $(DTS_DIR)/$(dts).dtb $@.boot;) + $(CP) $(IMAGE_KERNEL) $@.boot/$(KERNEL_NAME) + -$(CP) $@-boot.scr $@.boot/boot.scr + make_ext4fs -J -l 16384K $@.bootimg $@.boot endef define Build/sdcard-img + if [ -n "$(UBOOT)" ]; then UBOOT="$(STAGING_DIR_IMAGE)/$(UBOOT)"; fi; \ ROOTFS_SIZE=$$(( $(CONFIG_TARGET_ROOTFS_PARTSIZE) * 1024 * 2 )); \ + SIGNATURE="$(SIGNATURE)" \ ./gen_mvebu_sdcard_img.sh $@ \ - "$(STAGING_DIR_IMAGE)/clearfog-u-boot-spl.kwb" \ + $$UBOOT \ c 32768 $@.boot \ 83 $$ROOTFS_SIZE $(IMAGE_ROOTFS) endef +define Build/sdcard-img-ext4 + if [ -n "$(UBOOT)" ]; then UBOOT="$(STAGING_DIR_IMAGE)/$(UBOOT)"; fi; \ + ROOTFS_SIZE=$$(( $(CONFIG_TARGET_ROOTFS_PARTSIZE) * 1024 * 2 )); \ + SIGNATURE="$(SIGNATURE)" \ + ./gen_mvebu_sdcard_img.sh $@ \ + $$UBOOT \ + 83 32768 $@.bootimg \ + 83 $$ROOTFS_SIZE $(IMAGE_ROOTFS) +endef + +define Build/omnia-medkit-initramfs + $(TAR) -c -T /dev/null -f $@ + rm -rf $(dir $(IMAGE_KERNEL))boot + mkdir -p $(dir $(IMAGE_KERNEL))boot/boot/ + cp $(KDIR)/zImage-initramfs $(dir $(IMAGE_KERNEL))boot/boot/zImage + cp $(DTS_DIR)/$(DEVICE_DTS).dtb $(dir $(IMAGE_KERNEL))boot/boot/dtb + $(TAR) -rp --numeric-owner --owner=0 --group=0 --sort=name \ + $(if $(SOURCE_DATE_EPOCH),--mtime="@$(SOURCE_DATE_EPOCH)") \ + --file=$@ -C $(dir $(IMAGE_KERNEL))boot/ . +endef + define Device/Default PROFILES := Default DEVICE_DTS := $(1) @@ -56,7 +87,9 @@ define Device/Default KERNEL_NAME := zImage KERNEL := kernel-bin | append-dtb | uImage none SUPPORTED_DEVICES = $$(DEVICE_DTS) + UBOOT := endef +DEVICE_VARS += UBOOT define Device/UBI IMAGES := sysupgrade.bin @@ -90,136 +123,8 @@ define Device/NAND-512K PAGESIZE := 4096 endef -define Device/linksys - DEVICE_TITLE := Linksys $(1) - DEVICE_PACKAGES := kmod-mwlwifi wpad-mini swconfig -endef - -define Device/armada-385-linksys - $(Device/NAND-128K) - $(Device/UBI-factory) - KERNEL_SIZE := 6144k -endef - -define Device/linksys-wrt1200ac - $(call Device/linksys,WRT1200AC (Caiman)) - $(Device/armada-385-linksys) - DEVICE_DTS := armada-385-linksys-caiman -endef -TARGET_DEVICES += linksys-wrt1200ac - -define Device/linksys-wrt1900acv2 - $(call Device/linksys,WRT1900ACv2 (Cobra)) - $(Device/armada-385-linksys) - DEVICE_DTS := armada-385-linksys-cobra -endef -TARGET_DEVICES += linksys-wrt1900acv2 - -define Device/linksys-wrt3200acm - $(call Device/linksys,WRT3200ACM (Rango)) - $(Device/armada-385-linksys) - DEVICE_DTS := armada-385-linksys-rango - DEVICE_PACKAGES += kmod-btmrvl kmod-mwifiex-sdio -endef -TARGET_DEVICES += linksys-wrt3200acm - -define Device/linksys-wrt1900acs - $(call Device/linksys,WRT1900ACS (Shelby)) - $(Device/armada-385-linksys) - DEVICE_DTS := armada-385-linksys-shelby -endef -TARGET_DEVICES += linksys-wrt1900acs - -define Device/linksys-wrt1900ac - $(call Device/linksys,WRT1900AC (Mamba)) - DEVICE_DTS := armada-xp-linksys-mamba - $(Device/NAND-128K) - $(Device/UBI-factory) - KERNEL_SIZE := 3072k -endef -TARGET_DEVICES += linksys-wrt1900ac - -define Device/openblocks-ax3-4 - $(Device/UBI-factory) - DEVICE_DTS := armada-xp-openblocks-ax3-4 - SUPPORTED_DEVICES := $(1) - BLOCKSIZE := 128k - PAGESIZE := 1 - IMAGE/factory.img := append-kernel | pad-to $$(BLOCKSIZE) | append-ubi - DEVICE_TITLE := Plat'Home OpenBlocks AX3 -endef -TARGET_DEVICES += openblocks-ax3-4 - -define Device/armada-385-db-ap - $(Device/NAND-256K) - $(Device/UBI-factory) - KERNEL_SIZE := 8192k - DEVICE_TITLE := Marvell Armada 385 DB AP (DB-88F6820-AP) -endef -TARGET_DEVICES += armada-385-db-ap - -define Device/marvell-nand - $(Device/NAND-512K) - DEVICE_TITLE := Marvell Armada $(1) -endef - -define Device/armada-370-db - $(call Device/marvell-nand,370 DB (DB-88F6710-BP-DDR3)) -endef -TARGET_DEVICES += armada-370-db - -define Device/armada-370-rd - $(call Device/marvell-nand,370 RD (RD-88F6710-A1)) -endef -TARGET_DEVICES += armada-370-rd - -define Device/armada-xp-db - $(call Device/marvell-nand,XP DB (DB-78460-BP)) -endef -TARGET_DEVICES += armada-xp-db - -define Device/armada-xp-gp - $(call Device/marvell-nand,XP GP (DB-MV784MP-GP)) -endef -TARGET_DEVICES += armada-xp-gp - -define Device/armada-388-rd - DEVICE_TITLE := Marvell Armada 388 RD (RD-88F6820-AP) - IMAGES := firmware.bin - IMAGE/firmware.bin := append-kernel | pad-to 256k | append-rootfs | pad-rootfs -endef -TARGET_DEVICES += armada-388-rd - -define Device/armada-388-clearfog-pro - KERNEL_INSTALL := 1 - KERNEL := kernel-bin - DEVICE_TITLE := SolidRun ClearFog Pro - DEVICE_PACKAGES := mkf2fs e2fsprogs swconfig kmod-fs-vfat kmod-nls-cp437 kmod-nls-iso8859-1 - IMAGES := sdcard.img.gz - IMAGE/sdcard.img.gz := boot-scr-cfpro | boot-img | sdcard-img | gzip | append-metadata - IMAGE_NAME = $$(IMAGE_PREFIX)-$$(2) - DEVICE_DTS := armada-388-clearfog-pro armada-388-clearfog-base -endef -TARGET_DEVICES += armada-388-clearfog-pro - -define Device/armada-388-clearfog-base - KERNEL_INSTALL := 1 - KERNEL := kernel-bin - DEVICE_TITLE := SolidRun ClearFog Base - DEVICE_PACKAGES := mkf2fs e2fsprogs kmod-fs-vfat kmod-nls-cp437 kmod-nls-iso8859-1 - IMAGES := sdcard.img.gz - IMAGE/sdcard.img.gz := boot-scr-cfbase | boot-img | sdcard-img | gzip | append-metadata - IMAGE_NAME = $$(IMAGE_PREFIX)-$$(2) - DEVICE_DTS := armada-388-clearfog-pro armada-388-clearfog-base -endef -TARGET_DEVICES += armada-388-clearfog-base - -define Device/globalscale-mirabox - $(Device/NAND-512K) - DEVICE_DTS := armada-370-mirabox - SUPPORTED_DEVICES := mirabox - DEVICE_TITLE := Globalscale Mirabox -endef -TARGET_DEVICES += globalscale-mirabox +include cortex-a9.mk +include cortex-a53.mk +include cortex-a72.mk $(eval $(call BuildImage)) diff --git a/target/linux/mvebu/image/cfbase-boot.script b/target/linux/mvebu/image/armada-388-clearfog-base.bootscript similarity index 63% rename from target/linux/mvebu/image/cfbase-boot.script rename to target/linux/mvebu/image/armada-388-clearfog-base.bootscript index 89fa1dc57..1755203dc 100644 --- a/target/linux/mvebu/image/cfbase-boot.script +++ b/target/linux/mvebu/image/armada-388-clearfog-base.bootscript @@ -1,19 +1,20 @@ # Standard Boot-Script # use only well-known variable names provided by U-Boot Distro boot -# This script assumes that there is a boot partition, +# This script assumes that there is a boot partition, # and that the root partition is always the next one. # Override DeviceTree for Clearfog Base # removed once U-Boot is able to detect the board variant. setenv fdtfile armada-388-clearfog-base.dtb -# generate bootargs for rootfs on MMC -if test "${devtype}" = "mmc"; then - setexpr openwrt_rootpart ${distro_bootpart} + 1 - setenv bootargs ${bootargs} root=/dev/mmcblk${devnum}p${openwrt_rootpart} rootfstype=auto rootwait -fi +# rootfs is always on the next partition +setexpr openwrt_rootpart ${distro_bootpart} + 1 -# here one could add logic for other rootfs device types such as scsi and usb +# figure out partition uuid to pass to the kernel as root= +part uuid ${devtype} ${devnum}:${openwrt_rootpart} uuid + +# generate bootargs (rootfs) +setenv bootargs ${bootargs} root=PARTUUID=${uuid} rootfstype=auto rootwait # add console= option to bootargs, if any if test -n "${console}"; then diff --git a/target/linux/mvebu/image/armada-388-clearfog-pro.bootscript b/target/linux/mvebu/image/armada-388-clearfog-pro.bootscript new file mode 100644 index 000000000..99aa14585 --- /dev/null +++ b/target/linux/mvebu/image/armada-388-clearfog-pro.bootscript @@ -0,0 +1,27 @@ +# Standard Boot-Script +# use only well-known variable names provided by U-Boot Distro boot +# This script assumes that there is a boot partition, +# and that the root partition is always the next one. + +# Override DeviceTree for Clearfog Pro +# removed once U-Boot has been updated to the new name. +setenv fdtfile armada-388-clearfog-pro.dtb + +# rootfs is always on the next partition +setexpr openwrt_rootpart ${distro_bootpart} + 1 + +# figure out partition uuid to pass to the kernel as root= +part uuid ${devtype} ${devnum}:${openwrt_rootpart} uuid + +# generate bootargs (rootfs) +setenv bootargs ${bootargs} root=PARTUUID=${uuid} rootfstype=auto rootwait + +# add console= option to bootargs, if any +if test -n "${console}"; then + setenv bootargs ${bootargs} console=${console} +fi + +echo "Booting Linux with ${bootargs}" +load ${devtype} ${devnum}:${distro_bootpart} ${fdt_addr_r} ${fdtfile} +load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} zImage +bootz ${kernel_addr_r} - ${fdt_addr_r} diff --git a/target/linux/mvebu/image/armada-macchiatobin.bootscript b/target/linux/mvebu/image/armada-macchiatobin.bootscript new file mode 100644 index 000000000..ae9fdca92 --- /dev/null +++ b/target/linux/mvebu/image/armada-macchiatobin.bootscript @@ -0,0 +1,10 @@ +setenv bootargs "root=PARTUUID=@ROOT@-02 rw rootwait" + +if test -n "${console}"; then + setenv bootargs "${bootargs} ${console}" +fi + +load mmc 1:1 ${fdt_addr} armada-8040-mcbin.dtb +load mmc 1:1 ${kernel_addr} Image + +booti ${kernel_addr} - ${fdt_addr} diff --git a/target/linux/mvebu/image/cfpro-boot.script b/target/linux/mvebu/image/cfpro-boot.script deleted file mode 100644 index 1588c1546..000000000 --- a/target/linux/mvebu/image/cfpro-boot.script +++ /dev/null @@ -1,22 +0,0 @@ -# Standard Boot-Script -# use only well-known variable names provided by U-Boot Distro boot -# This script assumes that there is a boot partition, -# and that the root partition is always the next one. - -# generate bootargs for rootfs on MMC -if test "${devtype}" = "mmc"; then - setexpr openwrt_rootpart ${distro_bootpart} + 1 - setenv bootargs ${bootargs} root=/dev/mmcblk${devnum}p${openwrt_rootpart} rootfstype=auto rootwait -fi - -# here one could add logic for other rootfs device types such as scsi and usb - -# add console= option to bootargs, if any -if test -n "${console}"; then - setenv bootargs ${bootargs} console=${console} -fi - -echo "Booting Linux with ${bootargs}" -load ${devtype} ${devnum}:${distro_bootpart} ${fdt_addr_r} ${fdtfile} -load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} zImage -bootz ${kernel_addr_r} - ${fdt_addr_r} diff --git a/target/linux/mvebu/image/cortex-a53.mk b/target/linux/mvebu/image/cortex-a53.mk new file mode 100644 index 000000000..711d2c0be --- /dev/null +++ b/target/linux/mvebu/image/cortex-a53.mk @@ -0,0 +1,16 @@ +ifeq ($(SUBTARGET),cortexa53) + +define Device/globalscale-espressobin + KERNEL_NAME := Image + KERNEL := kernel-bin + DEVICE_TITLE := ESPRESSObin (Marvell Armada 3700 Community Board) + DEVICE_PACKAGES := e2fsprogs ethtool mkf2fs kmod-fs-vfat kmod-usb2 kmod-usb3 kmod-usb-storage + IMAGES := sdcard.img.gz + IMAGE/sdcard.img.gz := boot-scr | boot-img-ext4 | sdcard-img-ext4 | gzip | append-metadata + DEVICE_DTS := armada-3720-espressobin + DTS_DIR := $(DTS_DIR)/marvell + SUPPORTED_DEVICES := globalscale,espressobin +endef +TARGET_DEVICES += globalscale-espressobin + +endif diff --git a/target/linux/mvebu/image/cortex-a72.mk b/target/linux/mvebu/image/cortex-a72.mk new file mode 100644 index 000000000..ac9cb50a8 --- /dev/null +++ b/target/linux/mvebu/image/cortex-a72.mk @@ -0,0 +1,16 @@ +ifeq ($(SUBTARGET),cortexa72) + +define Device/armada-macchiatobin + KERNEL_NAME := Image + KERNEL := kernel-bin + DEVICE_TITLE := MACCHIATObin (SolidRun Armada 8040 Community Board) + DEVICE_PACKAGES := e2fsprogs ethtool mkf2fs kmod-fs-vfat kmod-mmc + IMAGES := sdcard.img.gz + IMAGE/sdcard.img.gz := boot-scr | boot-img-ext4 | sdcard-img-ext4 | gzip | append-metadata + DEVICE_DTS := armada-8040-mcbin + DTS_DIR := $(DTS_DIR)/marvell + SUPPORTED_DEVICES := marvell,armada8040-mcbin +endef +TARGET_DEVICES += armada-macchiatobin + +endif diff --git a/target/linux/mvebu/image/cortex-a9.mk b/target/linux/mvebu/image/cortex-a9.mk new file mode 100644 index 000000000..d9defe880 --- /dev/null +++ b/target/linux/mvebu/image/cortex-a9.mk @@ -0,0 +1,164 @@ +# +# Copyright (C) 2012-2016 OpenWrt.org +# Copyright (C) 2016 LEDE-project.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +ifeq ($(SUBTARGET),cortexa9) + +define Device/linksys + DEVICE_TITLE := Linksys $(1) + DEVICE_PACKAGES := kmod-mwlwifi wpad-mini swconfig +endef + +define Device/armada-385-linksys + $(Device/NAND-128K) + $(Device/UBI-factory) + KERNEL_SIZE := 6144k +endef + +define Device/linksys-wrt1200ac + $(call Device/linksys,WRT1200AC (Caiman)) + $(Device/armada-385-linksys) + DEVICE_DTS := armada-385-linksys-caiman + DEVICE_PACKAGES += mwlwifi-firmware-88w8864 +endef +TARGET_DEVICES += linksys-wrt1200ac + +define Device/linksys-wrt1900acv2 + $(call Device/linksys,WRT1900ACv2 (Cobra)) + $(Device/armada-385-linksys) + DEVICE_DTS := armada-385-linksys-cobra + DEVICE_PACKAGES += mwlwifi-firmware-88w8864 +endef +TARGET_DEVICES += linksys-wrt1900acv2 + +define Device/linksys-wrt3200acm + $(call Device/linksys,WRT3200ACM (Rango)) + $(Device/armada-385-linksys) + DEVICE_DTS := armada-385-linksys-rango + DEVICE_PACKAGES += kmod-btmrvl kmod-mwifiex-sdio mwlwifi-firmware-88w8964 +endef +TARGET_DEVICES += linksys-wrt3200acm + +define Device/linksys-wrt1900acs + $(call Device/linksys,WRT1900ACS (Shelby)) + $(Device/armada-385-linksys) + DEVICE_DTS := armada-385-linksys-shelby + DEVICE_PACKAGES += mwlwifi-firmware-88w8864 +endef +TARGET_DEVICES += linksys-wrt1900acs + +define Device/linksys-wrt1900ac + $(call Device/linksys,WRT1900AC (Mamba)) + DEVICE_DTS := armada-xp-linksys-mamba + DEVICE_PACKAGES += mwlwifi-firmware-88w8864 + $(Device/NAND-128K) + $(Device/UBI-factory) + KERNEL_SIZE := 3072k +endef +TARGET_DEVICES += linksys-wrt1900ac + +define Device/openblocks-ax3-4 + $(Device/UBI-factory) + DEVICE_DTS := armada-xp-openblocks-ax3-4 + SUPPORTED_DEVICES := $(1) + BLOCKSIZE := 128k + PAGESIZE := 1 + IMAGE/factory.img := append-kernel | pad-to $$(BLOCKSIZE) | append-ubi + DEVICE_TITLE := Plat'Home OpenBlocks AX3 +endef +TARGET_DEVICES += openblocks-ax3-4 + +define Device/armada-385-db-ap + $(Device/NAND-256K) + $(Device/UBI-factory) + KERNEL_SIZE := 8192k + DEVICE_TITLE := Marvell Armada 385 DB AP (DB-88F6820-AP) +endef +TARGET_DEVICES += armada-385-db-ap + +define Device/marvell-nand + $(Device/NAND-512K) + DEVICE_TITLE := Marvell Armada $(1) +endef + +define Device/armada-370-db + $(call Device/marvell-nand,370 DB (DB-88F6710-BP-DDR3)) +endef +TARGET_DEVICES += armada-370-db + +define Device/armada-370-rd + $(call Device/marvell-nand,370 RD (RD-88F6710-A1)) +endef +TARGET_DEVICES += armada-370-rd + +define Device/armada-xp-db + $(call Device/marvell-nand,XP DB (DB-78460-BP)) +endef +TARGET_DEVICES += armada-xp-db + +define Device/armada-xp-gp + $(call Device/marvell-nand,XP GP (DB-MV784MP-GP)) +endef +TARGET_DEVICES += armada-xp-gp + +define Device/armada-388-rd + DEVICE_TITLE := Marvell Armada 388 RD (RD-88F6820-AP) + IMAGES := firmware.bin + IMAGE/firmware.bin := append-kernel | pad-to 256k | append-rootfs | pad-rootfs +endef +TARGET_DEVICES += armada-388-rd + +define Device/armada-388-clearfog-pro + KERNEL_INSTALL := 1 + KERNEL := kernel-bin + DEVICE_TITLE := SolidRun ClearFog Pro + DEVICE_PACKAGES := mkf2fs e2fsprogs swconfig kmod-fs-vfat kmod-nls-cp437 kmod-nls-iso8859-1 + IMAGES := sdcard.img.gz + IMAGE/sdcard.img.gz := boot-scr | boot-img | sdcard-img | gzip | append-metadata + DEVICE_DTS := armada-388-clearfog-pro armada-388-clearfog-base + SUPPORTED_DEVICES := armada-388-clearfog-pro armada-388-clearfog + UBOOT := clearfog-u-boot-spl.kwb +endef +TARGET_DEVICES += armada-388-clearfog-pro + +define Device/armada-388-clearfog-base + KERNEL_INSTALL := 1 + KERNEL := kernel-bin + DEVICE_TITLE := SolidRun ClearFog Base + DEVICE_PACKAGES := mkf2fs e2fsprogs kmod-fs-vfat kmod-nls-cp437 kmod-nls-iso8859-1 + IMAGES := sdcard.img.gz + IMAGE/sdcard.img.gz := boot-scr | boot-img | sdcard-img | gzip | append-metadata + DEVICE_DTS := armada-388-clearfog-pro armada-388-clearfog-base + UBOOT := clearfog-u-boot-spl.kwb +endef +TARGET_DEVICES += armada-388-clearfog-base + +define Device/globalscale-mirabox + $(Device/NAND-512K) + DEVICE_DTS := armada-370-mirabox + SUPPORTED_DEVICES := mirabox + DEVICE_TITLE := Globalscale Mirabox +endef +TARGET_DEVICES += globalscale-mirabox + +define Device/turris-omnia + KERNEL_INSTALL := 1 + KERNEL := kernel-bin + KERNEL_INITRAMFS := kernel-bin + DEVICE_TITLE := Turris Omnia + DEVICE_PACKAGES := \ + mkf2fs e2fsprogs kmod-fs-vfat kmod-nls-cp437 kmod-nls-iso8859-1 \ + wpad-mini kmod-ath9k kmod-ath10k ath10k-firmware-qca988x + IMAGES := $$(IMAGE_PREFIX)-sysupgrade.img.gz omnia-medkit-$$(IMAGE_PREFIX)-initramfs.tar.gz + IMAGE/$$(IMAGE_PREFIX)-sysupgrade.img.gz := boot-img | sdcard-img | gzip | append-metadata + IMAGE/omnia-medkit-$$(IMAGE_PREFIX)-initramfs.tar.gz := omnia-medkit-initramfs | gzip + IMAGE_NAME = $$(2) + DEVICE_DTS := armada-385-turris-omnia +endef +TARGET_DEVICES += turris-omnia + +endif diff --git a/target/linux/mvebu/image/gen_mvebu_sdcard_img.sh b/target/linux/mvebu/image/gen_mvebu_sdcard_img.sh index 86499eea5..67416ed80 100755 --- a/target/linux/mvebu/image/gen_mvebu_sdcard_img.sh +++ b/target/linux/mvebu/image/gen_mvebu_sdcard_img.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # # Copyright (C) 2016 Josua Mayer -# +# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 @@ -18,21 +18,27 @@ # usage() { - echo "$0 [ ]?" + echo "$0 [ ]?" } -# always require first 3 arguments +# always require first 2 or 3 arguments # then in pairs up to 8 more for a total of up to 4 partitions -if [ $# -lt 2 ] || [ $# -gt 15 ] || [ $((($# - 2) % 3)) -ne 0 ]; then - usage - exit 1 +if [ $# -lt 1 ] || [ $# -gt 14 ] || [ $((($# - 1) % 3)) -ne 0 ]; then + if [ $# -lt 2 ] || [ $# -gt 15 ] || [ $((($# - 2) % 3)) -ne 0 ]; then + usage + exit 1 + else + BOOTLOADER="$2" + fi fi set -e # parameters OUTFILE="$1"; shift -BOOTLOADER="$1"; shift +if [ -n "$BOOTLOADER" ]; then + shift +fi # generate image file printf "Creating $OUTFILE from /dev/zero: " @@ -40,7 +46,7 @@ dd if=/dev/zero of="$OUTFILE" bs=512 count=1 >/dev/null printf "Done\n" while [ "$#" -ge 3 ]; do - ptgen_args="$ptgen_args -p $(($2 / 2 + 256)) -S 0x$1" + ptgen_args="$ptgen_args -t $1 -p $(($2 / 2 + 256))" parts="$parts$3 " shift; shift; shift done @@ -50,13 +56,15 @@ sect=63 # create real partition table using fdisk printf "Creating partition table: " -set `ptgen -o "$OUTFILE" -h $head -s $sect -l 1024 $ptgen_args` +set `ptgen -o "$OUTFILE" -h $head -s $sect -l 1024 -S 0x$SIGNATURE $ptgen_args` printf "Done\n" # install bootloader -printf "Writing bootloader: " -dd of="$OUTFILE" if="$BOOTLOADER" bs=512 seek=1 conv=notrunc 2>/dev/null -printf "Done\n" +if [ -n "$BOOTLOADER" ]; then + printf "Writing bootloader: " + dd of="$OUTFILE" if="$BOOTLOADER" bs=512 seek=1 conv=notrunc 2>/dev/null + printf "Done\n" +fi i=1 while [ "$#" -ge 2 ]; do diff --git a/target/linux/mvebu/image/globalscale-espressobin.bootscript b/target/linux/mvebu/image/globalscale-espressobin.bootscript new file mode 100644 index 000000000..0d03ac851 --- /dev/null +++ b/target/linux/mvebu/image/globalscale-espressobin.bootscript @@ -0,0 +1,10 @@ +setenv bootargs "root=PARTUUID=@ROOT@-02 rw rootwait" + +if test -n "${console}"; then + setenv bootargs "${bootargs} ${console}" +fi + +load mmc 0:1 ${fdt_addr} armada-3720-espressobin.dtb +load mmc 0:1 ${kernel_addr} Image + +booti ${kernel_addr} - ${fdt_addr} diff --git a/target/linux/mvebu/patches-4.14/002-add_powertables.patch b/target/linux/mvebu/patches-4.14/002-add_powertables.patch new file mode 100644 index 000000000..c5a211dd4 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/002-add_powertables.patch @@ -0,0 +1,770 @@ +--- a/arch/arm/boot/dts/armada-385-linksys.dtsi ++++ b/arch/arm/boot/dts/armada-385-linksys.dtsi +@@ -237,11 +237,19 @@ + &pcie1 { + /* Marvell 88W8864, 5GHz-only */ + status = "okay"; ++ ++ mwlwifi { ++ marvell,2ghz = <0>; ++ }; + }; + + &pcie2 { + /* Marvell 88W8864, 2GHz-only */ + status = "okay"; ++ ++ mwlwifi { ++ marvell,5ghz = <0>; ++ }; + }; + + &pinctrl { +--- a/arch/arm/boot/dts/armada-385-linksys-caiman.dts ++++ b/arch/arm/boot/dts/armada-385-linksys-caiman.dts +@@ -169,3 +169,205 @@ + reg = <0x280000 0x680000>; /* 6.5MiB */ + }; + }; ++ ++&pcie1 { ++ mwlwifi { ++ marvell,chainmask = <2 2>; ++ marvell,powertable { ++ AU = ++ <36 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <40 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <44 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <48 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <100 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <104 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <108 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <112 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <116 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <120 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <124 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <128 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <132 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <136 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <140 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <149 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, ++ <153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, ++ <157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, ++ <161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, ++ <165 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>; ++ CA = ++ <36 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, ++ <40 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, ++ <44 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, ++ <48 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x1a 0x1a 0x18 0x17 0x19 0x19 0x17 0x15 0x18 0x18 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <165 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>; ++ CN = ++ <36 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <40 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <44 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <48 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <100 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <149 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x11 0x11 0x11 0x11 0 0xf>, ++ <153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>, ++ <157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>, ++ <161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>, ++ <165 0 0x15 0x15 0x15 0x15 0x16 0x16 0x16 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>; ++ ETSI = ++ <36 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <40 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <44 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <48 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <100 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <149 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>; ++ FCC = ++ <36 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <40 0 0x19 0x19 0x18 0x17 0x19 0x19 0x17 0x15 0x17 0x17 0x17 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <44 0 0x19 0x19 0x18 0x17 0x19 0x19 0x17 0x15 0x17 0x17 0x17 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <48 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x17 0x17 0x17 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x1a 0x1a 0x18 0x17 0x19 0x19 0x17 0x15 0x18 0x18 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <165 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>; ++ }; ++ }; ++}; ++ ++&pcie2 { ++ mwlwifi { ++ marvell,chainmask = <2 2>; ++ marvell,powertable { ++ AU = ++ <1 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>; ++ CA = ++ <1 0 0x19 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 0 0xf>, ++ <2 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <3 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <4 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <5 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <6 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <7 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <8 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <9 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <10 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <11 0 0x19 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x00 0x00 0x00 0x00 0 0xf>; ++ CN = ++ <1 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <14 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>; ++ ETSI = ++ <1 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>; ++ FCC = ++ <1 0 0x19 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x19 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x0 0x0 0x0 0x0 0 0xf>; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/armada-385-linksys-cobra.dts ++++ b/arch/arm/boot/dts/armada-385-linksys-cobra.dts +@@ -169,3 +169,205 @@ + reg = <0x280000 0x680000>; /* 6.5MiB */ + }; + }; ++ ++&pcie1 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ AU = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <104 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <108 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <112 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <116 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <120 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <124 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <128 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <132 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <136 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <140 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <149 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <153 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <157 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <161 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <165 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>; ++ CA = ++ <36 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <40 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <44 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <48 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; ++ CN = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <149 0 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <165 0 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>; ++ ETSI = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <149 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>; ++ FCC = ++ <36 0 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0 0xf>, ++ <40 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <44 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <48 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; ++ }; ++ }; ++}; ++ ++&pcie2 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ AU = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ CA = ++ <1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; ++ CN = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <14 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ ETSI = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ FCC = ++ <1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/armada-385-linksys-shelby.dts ++++ b/arch/arm/boot/dts/armada-385-linksys-shelby.dts +@@ -169,3 +169,205 @@ + reg = <0x280000 0x680000>; /* 6.5MiB */ + }; + }; ++ ++&pcie1 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ AU = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <104 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <108 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <112 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <116 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <120 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <124 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <128 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <132 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <136 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <140 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <149 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <153 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <157 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <161 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <165 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>; ++ CA = ++ <36 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <40 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <44 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <48 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; ++ CN = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <149 0 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <165 0 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>; ++ ETSI = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <149 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>; ++ FCC = ++ <36 0 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0 0xf>, ++ <40 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <44 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <48 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; ++ }; ++ }; ++}; ++ ++&pcie2 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ AU = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ CA = ++ <1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; ++ CN = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <14 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ ETSI = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ FCC = ++ <1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/armada-385-linksys-rango.dts ++++ b/arch/arm/boot/dts/armada-385-linksys-rango.dts +@@ -184,6 +184,18 @@ + }; + }; + ++&pcie1 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ }; ++}; ++ ++&pcie2 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ }; ++}; ++ + &sdhci { + pinctrl-names = "default"; + pinctrl-0 = <&sdhci_pins>; +--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts ++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +@@ -376,12 +376,100 @@ + pcie@2,0 { + /* Port 0, Lane 1 */ + status = "okay"; ++ ++ mwlwifi { ++ marvell,5ghz = <0>; ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ FCC = ++ <1 0 0x17 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x17 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>; ++ ++ ETSI = ++ <1 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>; ++ }; ++ }; + }; + + /* Second mini-PCIe port */ + pcie@3,0 { + /* Port 0, Lane 3 */ + status = "okay"; ++ ++ mwlwifi { ++ marvell,2ghz = <0>; ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ FCC = ++ <36 0 0x8 0x8 0x8 0x8 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <40 0 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <44 0 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <48 0 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <52 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, ++ <56 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, ++ <60 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, ++ <64 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, ++ <100 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <104 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <108 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <112 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <116 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <120 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <124 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <128 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <132 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <136 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <140 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <149 0 0x16 0x16 0x16 0x16 0x14 0x14 0x14 0x14 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, ++ <153 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, ++ <157 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, ++ <161 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, ++ <165 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>; ++ ++ ETSI = ++ <36 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <40 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <44 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <48 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <52 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <56 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <60 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <64 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <100 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <104 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <108 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <112 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <116 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <120 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <124 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <128 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <132 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <136 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <140 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <149 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>; ++ }; ++ }; + }; + }; + diff --git a/target/linux/mvebu/patches-4.14/003-add_switch_nodes.patch b/target/linux/mvebu/patches-4.14/003-add_switch_nodes.patch new file mode 100644 index 000000000..5d43d9f0f --- /dev/null +++ b/target/linux/mvebu/patches-4.14/003-add_switch_nodes.patch @@ -0,0 +1,40 @@ +--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts ++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +@@ -361,6 +361,16 @@ + }; + }; + }; ++ ++ mvsw61xx { ++ compatible = "marvell,88e6172"; ++ status = "okay"; ++ reg = <0x10>; ++ ++ mii-bus = <&mdio>; ++ cpu-port-0 = <5>; ++ cpu-port-1 = <6>; ++ }; + }; + + &pciec { +--- a/arch/arm/boot/dts/armada-385-linksys.dtsi ++++ b/arch/arm/boot/dts/armada-385-linksys.dtsi +@@ -113,6 +113,18 @@ + linux,default-trigger = "disk-activity"; + }; + }; ++ ++ mvsw61xx { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "marvell,88e6176"; ++ status = "okay"; ++ reg = <0x10>; ++ ++ mii-bus = <&mdio>; ++ cpu-port-0 = <5>; ++ cpu-port-1 = <6>; ++ }; + }; + + &ahci0 { diff --git a/target/linux/mvebu/patches-4.14/004-add_sata_disk_activity_trigger.patch b/target/linux/mvebu/patches-4.14/004-add_sata_disk_activity_trigger.patch new file mode 100644 index 000000000..1a2b33cb1 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/004-add_sata_disk_activity_trigger.patch @@ -0,0 +1,39 @@ +From 172230195068703b78ad5733a09492f5d6814c09 Mon Sep 17 00:00:00 2001 +From: Ansuel Smith +Date: Tue, 28 Feb 2017 14:15:50 +0100 +Subject: [PATCH] ARM: dts: armada: Add default trigger for sata led + +In others board we have the sata led set to function +with the sata led trigger by default. +This patch makes the same for these board that have sata +led but get disabled by not associating it to any trigger. + +Signed-off-by: Ansuel Smith +Acked-by: Jason Cooper +Signed-off-by: Gregory CLEMENT +--- + arch/arm/boot/dts/armada-385-linksys-caiman.dts | 1 + + arch/arm/boot/dts/armada-385-linksys-cobra.dts | 1 + + arch/arm/boot/dts/armada-xp-linksys-mamba.dts | 1 + + 3 files changed, 3 insertions(+) + +--- a/arch/arm/boot/dts/armada-385-linksys-caiman.dts ++++ b/arch/arm/boot/dts/armada-385-linksys-caiman.dts +@@ -100,6 +100,7 @@ + + sata { + label = "caiman:white:sata"; ++ linux,default-trigger = "disk-activity"; + }; + }; + +--- a/arch/arm/boot/dts/armada-385-linksys-cobra.dts ++++ b/arch/arm/boot/dts/armada-385-linksys-cobra.dts +@@ -100,6 +100,7 @@ + + sata { + label = "cobra:white:sata"; ++ linux,default-trigger = "disk-activity"; + }; + }; + diff --git a/target/linux/mvebu/patches-4.14/005-linksys_hardcode_nand_ecc_settings.patch b/target/linux/mvebu/patches-4.14/005-linksys_hardcode_nand_ecc_settings.patch new file mode 100644 index 000000000..c00e15323 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/005-linksys_hardcode_nand_ecc_settings.patch @@ -0,0 +1,17 @@ +Newer Linksys boards might come with a Winbond W29N02GV which can be +configured in different ways. Make sure we configure it the same way +as the older chips so everything keeps working. + +Signed-off-by: Imre Kaloz + +--- a/arch/arm/boot/dts/armada-385-linksys.dtsi ++++ b/arch/arm/boot/dts/armada-385-linksys.dtsi +@@ -185,6 +185,8 @@ + /* 128MiB or 256MiB */ + status = "okay"; + num-cs = <1>; ++ nand-ecc-strength = <4>; ++ nand-ecc-step-size = <512>; + marvell,nand-keep-config; + marvell,nand-enable-arbiter; + nand-on-flash-bbt; diff --git a/target/linux/mvebu/patches-4.14/100-find_active_root.patch b/target/linux/mvebu/patches-4.14/100-find_active_root.patch new file mode 100644 index 000000000..f52a5108b --- /dev/null +++ b/target/linux/mvebu/patches-4.14/100-find_active_root.patch @@ -0,0 +1,60 @@ +The WRT1900AC among other Linksys routers uses a dual-firmware layout. +Dynamically rename the active partition to "ubi". + +Signed-off-by: Imre Kaloz + +--- a/drivers/mtd/ofpart.c ++++ b/drivers/mtd/ofpart.c +@@ -25,6 +25,8 @@ static bool node_has_compatible(struct d + return of_get_property(pp, "compatible", NULL); + } + ++static int mangled_rootblock; ++ + static int parse_fixed_partitions(struct mtd_info *master, + const struct mtd_partition **pparts, + struct mtd_part_parser_data *data) +@@ -33,6 +35,7 @@ static int parse_fixed_partitions(struct + struct device_node *mtd_node; + struct device_node *ofpart_node; + const char *partname; ++ const char *owrtpart = "ubi"; + struct device_node *pp; + int nr_parts, i, ret = 0; + bool dedicated = true; +@@ -110,9 +113,13 @@ static int parse_fixed_partitions(struct + parts[i].size = of_read_number(reg + a_cells, s_cells); + parts[i].of_node = pp; + +- partname = of_get_property(pp, "label", &len); +- if (!partname) +- partname = of_get_property(pp, "name", &len); ++ if (mangled_rootblock && (i == mangled_rootblock)) { ++ partname = owrtpart; ++ } else { ++ partname = of_get_property(pp, "label", &len); ++ if (!partname) ++ partname = of_get_property(pp, "name", &len); ++ } + parts[i].name = partname; + + if (of_get_property(pp, "read-only", &len)) +@@ -219,6 +226,18 @@ static int __init ofpart_parser_init(voi + return 0; + } + ++static int __init active_root(char *str) ++{ ++ get_option(&str, &mangled_rootblock); ++ ++ if (!mangled_rootblock) ++ return 1; ++ ++ return 1; ++} ++ ++__setup("mangled_rootblock=", active_root); ++ + static void __exit ofpart_parser_exit(void) + { + deregister_mtd_parser(&ofpart_parser); diff --git a/target/linux/mvebu/patches-4.14/102-revert_i2c_delay.patch b/target/linux/mvebu/patches-4.14/102-revert_i2c_delay.patch new file mode 100644 index 000000000..77583ac0b --- /dev/null +++ b/target/linux/mvebu/patches-4.14/102-revert_i2c_delay.patch @@ -0,0 +1,15 @@ +--- a/arch/arm/boot/dts/armada-xp.dtsi ++++ b/arch/arm/boot/dts/armada-xp.dtsi +@@ -274,12 +274,10 @@ + }; + + &i2c0 { +- compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; + reg = <0x11000 0x100>; + }; + + &i2c1 { +- compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; + reg = <0x11100 0x100>; + }; + diff --git a/target/linux/mvebu/patches-4.14/103-remove-nand-driver-bug.patch b/target/linux/mvebu/patches-4.14/103-remove-nand-driver-bug.patch new file mode 100644 index 000000000..19a2a1e27 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/103-remove-nand-driver-bug.patch @@ -0,0 +1,13 @@ +Remove a BUG() call that would crash on a race condition that should +otherwise be harmless. + +--- a/drivers/mtd/nand/pxa3xx_nand.c ++++ b/drivers/mtd/nand/pxa3xx_nand.c +@@ -727,7 +727,6 @@ static void handle_data_pio(struct pxa3x + default: + dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__, + info->state); +- BUG(); + } + + /* Update buffer pointers for multi-page read/write */ diff --git a/target/linux/mvebu/patches-4.14/104-linksys_mamba_disable_keep_config.patch b/target/linux/mvebu/patches-4.14/104-linksys_mamba_disable_keep_config.patch new file mode 100644 index 000000000..f6c7239ab --- /dev/null +++ b/target/linux/mvebu/patches-4.14/104-linksys_mamba_disable_keep_config.patch @@ -0,0 +1,10 @@ +--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts ++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +@@ -200,7 +200,6 @@ + nand@d0000 { + status = "okay"; + num-cs = <1>; +- marvell,nand-keep-config; + marvell,nand-enable-arbiter; + nand-on-flash-bbt; + nand-ecc-strength = <4>; diff --git a/target/linux/mvebu/patches-4.14/110-pxa3xxx_revert_irq_thread.patch b/target/linux/mvebu/patches-4.14/110-pxa3xxx_revert_irq_thread.patch new file mode 100644 index 000000000..223ee652d --- /dev/null +++ b/target/linux/mvebu/patches-4.14/110-pxa3xxx_revert_irq_thread.patch @@ -0,0 +1,69 @@ +Revert "mtd: pxa3xx-nand: handle PIO in threaded interrupt" + +This reverts commit 24542257a3b987025d4b998ec2d15e556c98ad3f +This upstream change has been causing spurious timeouts on accesses +to the NAND flash if something else on the system is causing +significant latency. + +Nothing guarantees that the thread will run in time, so the +usual timeout is unreliable. + +Signed-off-by: Felix Fietkau + +--- a/drivers/mtd/nand/pxa3xx_nand.c ++++ b/drivers/mtd/nand/pxa3xx_nand.c +@@ -791,24 +791,11 @@ static void start_data_dma(struct pxa3xx + __func__, direction, info->dma_cookie, info->sg.length); + } + +-static irqreturn_t pxa3xx_nand_irq_thread(int irq, void *data) +-{ +- struct pxa3xx_nand_info *info = data; +- +- handle_data_pio(info); +- +- info->state = STATE_CMD_DONE; +- nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ); +- +- return IRQ_HANDLED; +-} +- + static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) + { + struct pxa3xx_nand_info *info = devid; + unsigned int status, is_completed = 0, is_ready = 0; + unsigned int ready, cmd_done; +- irqreturn_t ret = IRQ_HANDLED; + + if (info->cs == 0) { + ready = NDSR_FLASH_RDY; +@@ -850,8 +837,7 @@ static irqreturn_t pxa3xx_nand_irq(int i + } else { + info->state = (status & NDSR_RDDREQ) ? + STATE_PIO_READING : STATE_PIO_WRITING; +- ret = IRQ_WAKE_THREAD; +- goto NORMAL_IRQ_EXIT; ++ handle_data_pio(info); + } + } + if (status & cmd_done) { +@@ -896,7 +882,7 @@ static irqreturn_t pxa3xx_nand_irq(int i + if (is_ready) + complete(&info->dev_ready); + NORMAL_IRQ_EXIT: +- return ret; ++ return IRQ_HANDLED; + } + + static inline int is_buf_blank(uint8_t *buf, size_t len) +@@ -1865,9 +1851,7 @@ static int alloc_nand_resource(struct pl + /* initialize all interrupts to be disabled */ + disable_int(info, NDSR_MASK); + +- ret = request_threaded_irq(irq, pxa3xx_nand_irq, +- pxa3xx_nand_irq_thread, IRQF_ONESHOT, +- pdev->name, info); ++ ret = request_irq(irq, pxa3xx_nand_irq, 0, pdev->name, info); + if (ret < 0) { + dev_err(&pdev->dev, "failed to request IRQ: %d\n", ret); + goto fail_free_buf; diff --git a/target/linux/mvebu/patches-4.14/205-armada-385-rd-mtd-partitions.patch b/target/linux/mvebu/patches-4.14/205-armada-385-rd-mtd-partitions.patch new file mode 100644 index 000000000..e75a5eebd --- /dev/null +++ b/target/linux/mvebu/patches-4.14/205-armada-385-rd-mtd-partitions.patch @@ -0,0 +1,19 @@ +--- a/arch/arm/boot/dts/armada-388-rd.dts ++++ b/arch/arm/boot/dts/armada-388-rd.dts +@@ -140,6 +140,16 @@ + compatible = "st,m25p128", "jedec,spi-nor"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <108000000>; ++ ++ partition@0 { ++ label = "uboot"; ++ reg = <0 0x400000>; ++ }; ++ ++ partition@1 { ++ label = "firmware"; ++ reg = <0x400000 0xc00000>; ++ }; + }; + }; + diff --git a/target/linux/mvebu/patches-4.14/206-ARM-mvebu-385-ap-Add-partitions.patch b/target/linux/mvebu/patches-4.14/206-ARM-mvebu-385-ap-Add-partitions.patch new file mode 100644 index 000000000..b7af27236 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/206-ARM-mvebu-385-ap-Add-partitions.patch @@ -0,0 +1,35 @@ +From 9861f93a59142a3131870df2521eb2deb73026d7 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Tue, 13 Jan 2015 11:14:09 +0100 +Subject: [PATCH 2/2] ARM: mvebu: 385-ap: Add partitions + +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/armada-385-db-ap.dts | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/arch/arm/boot/dts/armada-385-db-ap.dts ++++ b/arch/arm/boot/dts/armada-385-db-ap.dts +@@ -181,19 +181,19 @@ + #size-cells = <1>; + + partition@0 { +- label = "U-Boot"; ++ label = "u-boot"; + reg = <0x00000000 0x00800000>; + read-only; + }; + + partition@800000 { +- label = "uImage"; ++ label = "kernel"; + reg = <0x00800000 0x00400000>; + read-only; + }; + + partition@c00000 { +- label = "Root"; ++ label = "ubi"; + reg = <0x00c00000 0x3f400000>; + }; + }; diff --git a/target/linux/mvebu/patches-4.14/210-clearfog_switch_node.patch b/target/linux/mvebu/patches-4.14/210-clearfog_switch_node.patch new file mode 100644 index 000000000..e880cc13e --- /dev/null +++ b/target/linux/mvebu/patches-4.14/210-clearfog_switch_node.patch @@ -0,0 +1,21 @@ +--- a/arch/arm/boot/dts/armada-388-clearfog.dts ++++ b/arch/arm/boot/dts/armada-388-clearfog.dts +@@ -129,6 +129,18 @@ + }; + }; + ++ mvsw61xx { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "marvell,88e6176"; ++ status = "okay"; ++ reg = <0x4>; ++ is-indirect; ++ ++ mii-bus = <&mdio>; ++ cpu-port-0 = <5>; ++ }; ++ + gpio-keys { + compatible = "gpio-keys"; + pinctrl-0 = <&rear_button_pins>; diff --git a/target/linux/mvebu/patches-4.14/220-disable-untested-dsa-boards.patch b/target/linux/mvebu/patches-4.14/220-disable-untested-dsa-boards.patch new file mode 100644 index 000000000..5df94bdfa --- /dev/null +++ b/target/linux/mvebu/patches-4.14/220-disable-untested-dsa-boards.patch @@ -0,0 +1,30 @@ +--- a/arch/arm/boot/dts/armada-385-linksys.dtsi ++++ b/arch/arm/boot/dts/armada-385-linksys.dtsi +@@ -196,6 +196,7 @@ + status = "okay"; + + switch@0 { ++ status = "disabled"; + compatible = "marvell,mv88e6085"; + #address-cells = <1>; + #size-cells = <0>; +--- a/arch/arm/boot/dts/armada-388-clearfog.dts ++++ b/arch/arm/boot/dts/armada-388-clearfog.dts +@@ -202,6 +202,7 @@ + status = "okay"; + + switch@4 { ++ status = "disabled"; + compatible = "marvell,mv88e6085"; + #address-cells = <1>; + #size-cells = <0>; +--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts ++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +@@ -516,6 +516,7 @@ + status = "okay"; + + switch@0 { ++ status = "disabled"; + compatible = "marvell,mv88e6085"; + #address-cells = <1>; + #size-cells = <0>; diff --git a/target/linux/mvebu/patches-4.14/230-armada-xp-linksys-mamba-broken-idle.patch b/target/linux/mvebu/patches-4.14/230-armada-xp-linksys-mamba-broken-idle.patch new file mode 100644 index 000000000..e82a899a7 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/230-armada-xp-linksys-mamba-broken-idle.patch @@ -0,0 +1,10 @@ +--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts ++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +@@ -563,3 +563,7 @@ + }; + }; + }; ++ ++&coherencyfab { ++ broken-idle; ++}; diff --git a/target/linux/mvebu/patches-4.14/300-mvneta-tx-queue-workaround.patch b/target/linux/mvebu/patches-4.14/300-mvneta-tx-queue-workaround.patch new file mode 100644 index 000000000..f21f8083e --- /dev/null +++ b/target/linux/mvebu/patches-4.14/300-mvneta-tx-queue-workaround.patch @@ -0,0 +1,35 @@ +The hardware queue scheduling is apparently configured with fixed +priorities, which creates a nasty fairness issue where traffic from one +CPU can starve traffic from all other CPUs. + +Work around this issue by forcing all tx packets to go through one CPU, +until this issue is fixed properly. + +Signed-off-by: Felix Fietkau +--- +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -3961,6 +3961,15 @@ static int mvneta_ethtool_set_wol(struct + return ret; + } + ++static u16 mvneta_select_queue(struct net_device *dev, struct sk_buff *skb, ++ void *accel_priv, ++ select_queue_fallback_t fallback) ++{ ++ /* XXX: hardware queue scheduling is broken, ++ * use only one queue until it is fixed */ ++ return 0; ++} ++ + static const struct net_device_ops mvneta_netdev_ops = { + .ndo_open = mvneta_open, + .ndo_stop = mvneta_stop, +@@ -3971,6 +3980,7 @@ static const struct net_device_ops mvnet + .ndo_fix_features = mvneta_fix_features, + .ndo_get_stats64 = mvneta_get_stats64, + .ndo_do_ioctl = mvneta_ioctl, ++ .ndo_select_queue = mvneta_select_queue, + }; + + static const struct ethtool_ops mvneta_eth_tool_ops = { diff --git a/target/linux/mvebu/patches-4.14/400-cpuidle-mvebu-indicate-failure-to-enter-deeper-sleep.patch b/target/linux/mvebu/patches-4.14/400-cpuidle-mvebu-indicate-failure-to-enter-deeper-sleep.patch new file mode 100644 index 000000000..29f36be46 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/400-cpuidle-mvebu-indicate-failure-to-enter-deeper-sleep.patch @@ -0,0 +1,40 @@ +From c28b2d367da8a471482e6a4aa8337ab6369a80c2 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Sat, 3 Oct 2015 09:13:05 +0100 +Subject: cpuidle: mvebu: indicate failure to enter deeper sleep states + +The cpuidle ->enter method expects the return value to be the sleep +state we entered. Returning negative numbers or other codes is not +permissible since coupled CPU idle was merged. + +At least some of the mvebu_v7_cpu_suspend() implementations return the +value from cpu_suspend(), which returns zero if the CPU vectors back +into the kernel via cpu_resume() (the success case), or the non-zero +return value of the suspend actor, or one (failure cases). + +We do not want to be returning the failure case value back to CPU idle +as that indicates that we successfully entered one of the deeper idle +states. Always return zero instead, indicating that we slept for the +shortest amount of time. + +Signed-off-by: Russell King +--- + drivers/cpuidle/cpuidle-mvebu-v7.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/cpuidle/cpuidle-mvebu-v7.c ++++ b/drivers/cpuidle/cpuidle-mvebu-v7.c +@@ -39,8 +39,12 @@ static int mvebu_v7_enter_idle(struct cp + ret = mvebu_v7_cpu_suspend(deepidle); + cpu_pm_exit(); + ++ /* ++ * If we failed to enter the desired state, indicate that we ++ * slept lightly. ++ */ + if (ret) +- return ret; ++ return 0; + + return index; + } diff --git a/target/linux/mvebu/patches-4.14/401-pci-mvebu-time-out-reset-on-link-up.patch b/target/linux/mvebu/patches-4.14/401-pci-mvebu-time-out-reset-on-link-up.patch new file mode 100644 index 000000000..504d11026 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/401-pci-mvebu-time-out-reset-on-link-up.patch @@ -0,0 +1,60 @@ +From 287b9df160b6159f8d385424904f8bac501280c1 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Sat, 9 Jul 2016 10:58:16 +0100 +Subject: pci: mvebu: time out reset on link up + +If the port reports that the link is up while we are resetting, there's +little point in waiting for the full duration. + +Signed-off-by: Russell King +--- + drivers/pci/host/pci-mvebu.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +--- a/drivers/pci/host/pci-mvebu.c ++++ b/drivers/pci/host/pci-mvebu.c +@@ -1167,6 +1167,7 @@ static int mvebu_pcie_powerup(struct mve + + if (port->reset_gpio) { + u32 reset_udelay = PCI_PM_D3COLD_WAIT * 1000; ++ unsigned int i; + + of_property_read_u32(port->dn, "reset-delay-us", + &reset_udelay); +@@ -1174,7 +1175,13 @@ static int mvebu_pcie_powerup(struct mve + udelay(100); + + gpiod_set_value_cansleep(port->reset_gpio, 0); +- msleep(reset_udelay / 1000); ++ for (i = 0; i < reset_udelay; i += 1000) { ++ if (mvebu_pcie_link_up(port)) ++ break; ++ msleep(1); ++ } ++ ++ printk("%s: reset completed in %dus\n", port->name, i); + } + + return 0; +@@ -1261,15 +1268,16 @@ static int mvebu_pcie_probe(struct platf + if (!child) + continue; + +- ret = mvebu_pcie_powerup(port); +- if (ret < 0) +- continue; +- + port->base = mvebu_pcie_map_registers(pdev, child, port); + if (IS_ERR(port->base)) { + dev_err(dev, "%s: cannot map registers\n", port->name); + port->base = NULL; +- mvebu_pcie_powerdown(port); ++ continue; ++ } ++ ++ ret = mvebu_pcie_powerup(port); ++ if (ret < 0) { ++ port->base = NULL; + continue; + } + diff --git a/target/linux/mvebu/patches-4.14/402-sfp-display-SFP-module-information.patch b/target/linux/mvebu/patches-4.14/402-sfp-display-SFP-module-information.patch new file mode 100644 index 000000000..4f9e2e29b --- /dev/null +++ b/target/linux/mvebu/patches-4.14/402-sfp-display-SFP-module-information.patch @@ -0,0 +1,290 @@ +From e76632d118659347d9261a4470d9f60bfbe0044c Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Sun, 13 Sep 2015 01:06:31 +0100 +Subject: sfp: display SFP module information + +Signed-off-by: Russell King +--- + drivers/net/phy/sfp.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 253 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -247,6 +247,184 @@ static unsigned int sfp_check(void *buf, + return check; + } + ++static const char *sfp_link_len(char *buf, size_t size, unsigned int length, ++ unsigned int multiplier) ++{ ++ if (length == 0) ++ return "unsupported/unspecified"; ++ ++ if (length == 255) { ++ *buf++ = '>'; ++ size -= 1; ++ length -= 1; ++ } ++ ++ length *= multiplier; ++ ++ if (length >= 1000) ++ snprintf(buf, size, "%u.%0*ukm", ++ length / 1000, ++ multiplier > 100 ? 1 : ++ multiplier > 10 ? 2 : 3, ++ length % 1000); ++ else ++ snprintf(buf, size, "%um", length); ++ ++ return buf; ++} ++ ++struct bitfield { ++ unsigned int mask; ++ unsigned int val; ++ const char *str; ++}; ++ ++static const struct bitfield sfp_options[] = { ++ { ++ .mask = SFP_OPTIONS_HIGH_POWER_LEVEL, ++ .val = SFP_OPTIONS_HIGH_POWER_LEVEL, ++ .str = "hpl", ++ }, { ++ .mask = SFP_OPTIONS_PAGING_A2, ++ .val = SFP_OPTIONS_PAGING_A2, ++ .str = "paginga2", ++ }, { ++ .mask = SFP_OPTIONS_RETIMER, ++ .val = SFP_OPTIONS_RETIMER, ++ .str = "retimer", ++ }, { ++ .mask = SFP_OPTIONS_COOLED_XCVR, ++ .val = SFP_OPTIONS_COOLED_XCVR, ++ .str = "cooled", ++ }, { ++ .mask = SFP_OPTIONS_POWER_DECL, ++ .val = SFP_OPTIONS_POWER_DECL, ++ .str = "powerdecl", ++ }, { ++ .mask = SFP_OPTIONS_RX_LINEAR_OUT, ++ .val = SFP_OPTIONS_RX_LINEAR_OUT, ++ .str = "rxlinear", ++ }, { ++ .mask = SFP_OPTIONS_RX_DECISION_THRESH, ++ .val = SFP_OPTIONS_RX_DECISION_THRESH, ++ .str = "rxthresh", ++ }, { ++ .mask = SFP_OPTIONS_TUNABLE_TX, ++ .val = SFP_OPTIONS_TUNABLE_TX, ++ .str = "tunabletx", ++ }, { ++ .mask = SFP_OPTIONS_RATE_SELECT, ++ .val = SFP_OPTIONS_RATE_SELECT, ++ .str = "ratesel", ++ }, { ++ .mask = SFP_OPTIONS_TX_DISABLE, ++ .val = SFP_OPTIONS_TX_DISABLE, ++ .str = "txdisable", ++ }, { ++ .mask = SFP_OPTIONS_TX_FAULT, ++ .val = SFP_OPTIONS_TX_FAULT, ++ .str = "txfault", ++ }, { ++ .mask = SFP_OPTIONS_LOS_INVERTED, ++ .val = SFP_OPTIONS_LOS_INVERTED, ++ .str = "los-", ++ }, { ++ .mask = SFP_OPTIONS_LOS_NORMAL, ++ .val = SFP_OPTIONS_LOS_NORMAL, ++ .str = "los+", ++ }, { } ++}; ++ ++static const struct bitfield diagmon[] = { ++ { ++ .mask = SFP_DIAGMON_DDM, ++ .val = SFP_DIAGMON_DDM, ++ .str = "ddm", ++ }, { ++ .mask = SFP_DIAGMON_INT_CAL, ++ .val = SFP_DIAGMON_INT_CAL, ++ .str = "intcal", ++ }, { ++ .mask = SFP_DIAGMON_EXT_CAL, ++ .val = SFP_DIAGMON_EXT_CAL, ++ .str = "extcal", ++ }, { ++ .mask = SFP_DIAGMON_RXPWR_AVG, ++ .val = SFP_DIAGMON_RXPWR_AVG, ++ .str = "rxpwravg", ++ }, { } ++}; ++ ++static const char *sfp_bitfield(char *out, size_t outsz, const struct bitfield *bits, unsigned int val) ++{ ++ char *p = out; ++ int n; ++ ++ *p = '\0'; ++ while (bits->mask) { ++ if ((val & bits->mask) == bits->val) { ++ n = snprintf(p, outsz, "%s%s", ++ out != p ? ", " : "", ++ bits->str); ++ if (n == outsz) ++ break; ++ p += n; ++ outsz -= n; ++ } ++ bits++; ++ } ++ ++ return out; ++} ++ ++static const char *sfp_connector(unsigned int connector) ++{ ++ switch (connector) { ++ case SFP_CONNECTOR_UNSPEC: ++ return "unknown/unspecified"; ++ case SFP_CONNECTOR_SC: ++ return "SC"; ++ case SFP_CONNECTOR_FIBERJACK: ++ return "Fiberjack"; ++ case SFP_CONNECTOR_LC: ++ return "LC"; ++ case SFP_CONNECTOR_MT_RJ: ++ return "MT-RJ"; ++ case SFP_CONNECTOR_MU: ++ return "MU"; ++ case SFP_CONNECTOR_SG: ++ return "SG"; ++ case SFP_CONNECTOR_OPTICAL_PIGTAIL: ++ return "Optical pigtail"; ++ case SFP_CONNECTOR_HSSDC_II: ++ return "HSSDC II"; ++ case SFP_CONNECTOR_COPPER_PIGTAIL: ++ return "Copper pigtail"; ++ default: ++ return "unknown"; ++ } ++} ++ ++static const char *sfp_encoding(unsigned int encoding) ++{ ++ switch (encoding) { ++ case SFP_ENCODING_UNSPEC: ++ return "unspecified"; ++ case SFP_ENCODING_8472_64B66B: ++ return "64b66b"; ++ case SFP_ENCODING_8B10B: ++ return "8b10b"; ++ case SFP_ENCODING_4B5B: ++ return "4b5b"; ++ case SFP_ENCODING_NRZ: ++ return "NRZ"; ++ case SFP_ENCODING_8472_MANCHESTER: ++ return "MANCHESTER"; ++ default: ++ return "unknown"; ++ } ++} ++ + /* Helpers */ + static void sfp_module_tx_disable(struct sfp *sfp) + { +@@ -415,6 +593,7 @@ static int sfp_sm_mod_probe(struct sfp * + char sn[17]; + char date[9]; + char rev[5]; ++ char options[80]; + u8 check; + int err; + +@@ -458,10 +637,83 @@ static int sfp_sm_mod_probe(struct sfp * + rev[4] = '\0'; + memcpy(sn, sfp->id.ext.vendor_sn, 16); + sn[16] = '\0'; +- memcpy(date, sfp->id.ext.datecode, 8); ++ date[0] = sfp->id.ext.datecode[4]; ++ date[1] = sfp->id.ext.datecode[5]; ++ date[2] = '-'; ++ date[3] = sfp->id.ext.datecode[2]; ++ date[4] = sfp->id.ext.datecode[3]; ++ date[5] = '-'; ++ date[6] = sfp->id.ext.datecode[0]; ++ date[7] = sfp->id.ext.datecode[1]; + date[8] = '\0'; + + dev_info(sfp->dev, "module %s %s rev %s sn %s dc %s\n", vendor, part, rev, sn, date); ++ dev_info(sfp->dev, " %s connector, encoding %s, nominal bitrate %u.%uGbps +%u%% -%u%%\n", ++ sfp_connector(sfp->id.base.connector), ++ sfp_encoding(sfp->id.base.encoding), ++ sfp->id.base.br_nominal / 10, ++ sfp->id.base.br_nominal % 10, ++ sfp->id.ext.br_max, sfp->id.ext.br_min); ++ dev_info(sfp->dev, " 1000BaseSX%c 1000BaseLX%c 1000BaseCX%c 1000BaseT%c 100BaseTLX%c 1000BaseFX%c BaseBX10%c BasePX%c\n", ++ sfp->id.base.e1000_base_sx ? '+' : '-', ++ sfp->id.base.e1000_base_lx ? '+' : '-', ++ sfp->id.base.e1000_base_cx ? '+' : '-', ++ sfp->id.base.e1000_base_t ? '+' : '-', ++ sfp->id.base.e100_base_lx ? '+' : '-', ++ sfp->id.base.e100_base_fx ? '+' : '-', ++ sfp->id.base.e_base_bx10 ? '+' : '-', ++ sfp->id.base.e_base_px ? '+' : '-'); ++ dev_info(sfp->dev, " 10GBaseSR%c 10GBaseLR%c 10GBaseLRM%c 10GBaseER%c\n", ++ sfp->id.base.e10g_base_sr ? '+' : '-', ++ sfp->id.base.e10g_base_lr ? '+' : '-', ++ sfp->id.base.e10g_base_lrm ? '+' : '-', ++ sfp->id.base.e10g_base_er ? '+' : '-'); ++ ++ if (!sfp->id.base.sfp_ct_passive && !sfp->id.base.sfp_ct_active && ++ !sfp->id.base.e1000_base_t) { ++ char len_9um[16], len_om[16]; ++ ++ dev_info(sfp->dev, " Wavelength %unm, fiber lengths:\n", ++ be16_to_cpup(&sfp->id.base.optical_wavelength)); ++ ++ if (sfp->id.base.link_len[0] == 255) ++ strcpy(len_9um, ">254km"); ++ else if (sfp->id.base.link_len[1] && sfp->id.base.link_len[1] != 255) ++ sprintf(len_9um, "%um", ++ sfp->id.base.link_len[1] * 100); ++ else if (sfp->id.base.link_len[0]) ++ sprintf(len_9um, "%ukm", sfp->id.base.link_len[0]); ++ else if (sfp->id.base.link_len[1] == 255) ++ strcpy(len_9um, ">25.4km"); ++ else ++ strcpy(len_9um, "unsupported"); ++ ++ dev_info(sfp->dev, " 9µm SM : %s\n", len_9um); ++ dev_info(sfp->dev, " 62.5µm MM OM1: %s\n", ++ sfp_link_len(len_om, sizeof(len_om), ++ sfp->id.base.link_len[3], 10)); ++ dev_info(sfp->dev, " 50µm MM OM2: %s\n", ++ sfp_link_len(len_om, sizeof(len_om), ++ sfp->id.base.link_len[2], 10)); ++ dev_info(sfp->dev, " 50µm MM OM3: %s\n", ++ sfp_link_len(len_om, sizeof(len_om), ++ sfp->id.base.link_len[5], 10)); ++ dev_info(sfp->dev, " 50µm MM OM4: %s\n", ++ sfp_link_len(len_om, sizeof(len_om), ++ sfp->id.base.link_len[4], 10)); ++ } else { ++ char len[16]; ++ dev_info(sfp->dev, " Copper length: %s\n", ++ sfp_link_len(len, sizeof(len), ++ sfp->id.base.link_len[4], 1)); ++ } ++ ++ dev_info(sfp->dev, " Options: %s\n", ++ sfp_bitfield(options, sizeof(options), sfp_options, ++ be16_to_cpu(sfp->id.ext.options))); ++ dev_info(sfp->dev, " Diagnostics: %s\n", ++ sfp_bitfield(options, sizeof(options), diagmon, ++ sfp->id.ext.diagmon)); + + /* We only support SFP modules, not the legacy GBIC modules. */ + if (sfp->id.base.phys_id != SFP_PHYS_ID_SFP || diff --git a/target/linux/mvebu/patches-4.14/403-net-mvneta-convert-to-phylink.patch b/target/linux/mvebu/patches-4.14/403-net-mvneta-convert-to-phylink.patch new file mode 100644 index 000000000..10f385461 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/403-net-mvneta-convert-to-phylink.patch @@ -0,0 +1,979 @@ +From 36f29e6cf8071fed3854d9825217ed2a3c83b990 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Wed, 16 Sep 2015 21:27:10 +0100 +Subject: net: mvneta: convert to phylink + +Convert mvneta to use phylink, which models the MAC to PHY link in +a generic, reusable form. + +Signed-off-by: Russell King + +- remove unused sync status +--- + drivers/net/ethernet/marvell/Kconfig | 2 +- + drivers/net/ethernet/marvell/mvneta.c | 594 ++++++++++++++++++++-------------- + 2 files changed, 349 insertions(+), 247 deletions(-) + +--- a/drivers/net/ethernet/marvell/Kconfig ++++ b/drivers/net/ethernet/marvell/Kconfig +@@ -60,7 +60,7 @@ config MVNETA + depends on ARCH_MVEBU || COMPILE_TEST + depends on HAS_DMA + select MVMDIO +- select FIXED_PHY ++ select PHYLINK + ---help--- + This driver supports the network interface units in the + Marvell ARMADA XP, ARMADA 370, ARMADA 38x and +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -28,7 +28,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +@@ -189,6 +189,7 @@ + #define MVNETA_GMAC_CTRL_0 0x2c00 + #define MVNETA_GMAC_MAX_RX_SIZE_SHIFT 2 + #define MVNETA_GMAC_MAX_RX_SIZE_MASK 0x7ffc ++#define MVNETA_GMAC0_PORT_1000BASE_X BIT(1) + #define MVNETA_GMAC0_PORT_ENABLE BIT(0) + #define MVNETA_GMAC_CTRL_2 0x2c08 + #define MVNETA_GMAC2_INBAND_AN_ENABLE BIT(0) +@@ -204,13 +205,19 @@ + #define MVNETA_GMAC_TX_FLOW_CTRL_ENABLE BIT(5) + #define MVNETA_GMAC_RX_FLOW_CTRL_ACTIVE BIT(6) + #define MVNETA_GMAC_TX_FLOW_CTRL_ACTIVE BIT(7) ++#define MVNETA_GMAC_AN_COMPLETE BIT(11) ++#define MVNETA_GMAC_SYNC_OK BIT(14) + #define MVNETA_GMAC_AUTONEG_CONFIG 0x2c0c + #define MVNETA_GMAC_FORCE_LINK_DOWN BIT(0) + #define MVNETA_GMAC_FORCE_LINK_PASS BIT(1) + #define MVNETA_GMAC_INBAND_AN_ENABLE BIT(2) ++#define MVNETA_GMAC_AN_BYPASS_ENABLE BIT(3) ++#define MVNETA_GMAC_INBAND_RESTART_AN BIT(4) + #define MVNETA_GMAC_CONFIG_MII_SPEED BIT(5) + #define MVNETA_GMAC_CONFIG_GMII_SPEED BIT(6) + #define MVNETA_GMAC_AN_SPEED_EN BIT(7) ++#define MVNETA_GMAC_CONFIG_FLOW_CTRL BIT(8) ++#define MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL BIT(9) + #define MVNETA_GMAC_AN_FLOW_CTRL_EN BIT(11) + #define MVNETA_GMAC_CONFIG_FULL_DUPLEX BIT(12) + #define MVNETA_GMAC_AN_DUPLEX_EN BIT(13) +@@ -237,6 +244,12 @@ + #define MVNETA_TXQ_TOKEN_SIZE_REG(q) (0x3e40 + ((q) << 2)) + #define MVNETA_TXQ_TOKEN_SIZE_MAX 0x7fffffff + ++#define MVNETA_LPI_CTRL_0 0x2cc0 ++#define MVNETA_LPI_CTRL_1 0x2cc4 ++#define MVNETA_LPI_REQUEST_ENABLE BIT(0) ++#define MVNETA_LPI_CTRL_2 0x2cc8 ++#define MVNETA_LPI_STATUS 0x2ccc ++ + #define MVNETA_CAUSE_TXQ_SENT_DESC_ALL_MASK 0xff + + /* Descriptor ring Macros */ +@@ -313,6 +326,11 @@ + #define MVNETA_RX_GET_BM_POOL_ID(rxd) \ + (((rxd)->status & MVNETA_RXD_BM_POOL_MASK) >> MVNETA_RXD_BM_POOL_SHIFT) + ++enum { ++ ETHTOOL_STAT_EEE_WAKEUP, ++ ETHTOOL_MAX_STATS, ++}; ++ + struct mvneta_statistic { + unsigned short offset; + unsigned short type; +@@ -321,6 +339,7 @@ struct mvneta_statistic { + + #define T_REG_32 32 + #define T_REG_64 64 ++#define T_SW 1 + + static const struct mvneta_statistic mvneta_statistics[] = { + { 0x3000, T_REG_64, "good_octets_received", }, +@@ -355,6 +374,7 @@ static const struct mvneta_statistic mvn + { 0x304c, T_REG_32, "broadcast_frames_sent", }, + { 0x3054, T_REG_32, "fc_sent", }, + { 0x300c, T_REG_32, "internal_mac_transmit_err", }, ++ { ETHTOOL_STAT_EEE_WAKEUP, T_SW, "eee_wakeup_errors", }, + }; + + struct mvneta_pcpu_stats { +@@ -407,20 +427,19 @@ struct mvneta_port { + u16 tx_ring_size; + u16 rx_ring_size; + +- struct mii_bus *mii_bus; +- phy_interface_t phy_interface; +- struct device_node *phy_node; +- unsigned int link; +- unsigned int duplex; +- unsigned int speed; ++ struct device_node *dn; + unsigned int tx_csum_limit; +- unsigned int use_inband_status:1; ++ struct phylink *phylink; + + struct mvneta_bm *bm_priv; + struct mvneta_bm_pool *pool_long; + struct mvneta_bm_pool *pool_short; + int bm_win_id; + ++ bool eee_enabled; ++ bool eee_active; ++ bool tx_lpi_enabled; ++ + u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)]; + + u32 indir[MVNETA_RSS_LU_TABLE_SIZE]; +@@ -1214,10 +1233,6 @@ static void mvneta_port_disable(struct m + val &= ~MVNETA_GMAC0_PORT_ENABLE; + mvreg_write(pp, MVNETA_GMAC_CTRL_0, val); + +- pp->link = 0; +- pp->duplex = -1; +- pp->speed = 0; +- + udelay(200); + } + +@@ -1277,44 +1292,6 @@ static void mvneta_set_other_mcast_table + mvreg_write(pp, MVNETA_DA_FILT_OTH_MCAST + offset, val); + } + +-static void mvneta_set_autoneg(struct mvneta_port *pp, int enable) +-{ +- u32 val; +- +- if (enable) { +- val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); +- val &= ~(MVNETA_GMAC_FORCE_LINK_PASS | +- MVNETA_GMAC_FORCE_LINK_DOWN | +- MVNETA_GMAC_AN_FLOW_CTRL_EN); +- val |= MVNETA_GMAC_INBAND_AN_ENABLE | +- MVNETA_GMAC_AN_SPEED_EN | +- MVNETA_GMAC_AN_DUPLEX_EN; +- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); +- +- val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); +- val |= MVNETA_GMAC_1MS_CLOCK_ENABLE; +- mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val); +- +- val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); +- val |= MVNETA_GMAC2_INBAND_AN_ENABLE; +- mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); +- } else { +- val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); +- val &= ~(MVNETA_GMAC_INBAND_AN_ENABLE | +- MVNETA_GMAC_AN_SPEED_EN | +- MVNETA_GMAC_AN_DUPLEX_EN); +- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); +- +- val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); +- val &= ~MVNETA_GMAC_1MS_CLOCK_ENABLE; +- mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val); +- +- val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); +- val &= ~MVNETA_GMAC2_INBAND_AN_ENABLE; +- mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); +- } +-} +- + static void mvneta_percpu_unmask_interrupt(void *arg) + { + struct mvneta_port *pp = arg; +@@ -1467,7 +1444,6 @@ static void mvneta_defaults_set(struct m + val &= ~MVNETA_PHY_POLLING_ENABLE; + mvreg_write(pp, MVNETA_UNIT_CONTROL, val); + +- mvneta_set_autoneg(pp, pp->use_inband_status); + mvneta_set_ucast_table(pp, -1); + mvneta_set_special_mcast_table(pp, -1); + mvneta_set_other_mcast_table(pp, -1); +@@ -2692,26 +2668,11 @@ static irqreturn_t mvneta_percpu_isr(int + return IRQ_HANDLED; + } + +-static int mvneta_fixed_link_update(struct mvneta_port *pp, +- struct phy_device *phy) ++static void mvneta_link_change(struct mvneta_port *pp) + { +- struct fixed_phy_status status; +- struct fixed_phy_status changed = {}; + u32 gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS); + +- status.link = !!(gmac_stat & MVNETA_GMAC_LINK_UP); +- if (gmac_stat & MVNETA_GMAC_SPEED_1000) +- status.speed = SPEED_1000; +- else if (gmac_stat & MVNETA_GMAC_SPEED_100) +- status.speed = SPEED_100; +- else +- status.speed = SPEED_10; +- status.duplex = !!(gmac_stat & MVNETA_GMAC_FULL_DUPLEX); +- changed.link = 1; +- changed.speed = 1; +- changed.duplex = 1; +- fixed_phy_update_state(phy, &status, &changed); +- return 0; ++ phylink_mac_change(pp->phylink, !!(gmac_stat & MVNETA_GMAC_LINK_UP)); + } + + /* NAPI handler +@@ -2727,7 +2688,6 @@ static int mvneta_poll(struct napi_struc + u32 cause_rx_tx; + int rx_queue; + struct mvneta_port *pp = netdev_priv(napi->dev); +- struct net_device *ndev = pp->dev; + struct mvneta_pcpu_port *port = this_cpu_ptr(pp->ports); + + if (!netif_running(pp->dev)) { +@@ -2741,12 +2701,11 @@ static int mvneta_poll(struct napi_struc + u32 cause_misc = mvreg_read(pp, MVNETA_INTR_MISC_CAUSE); + + mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0); +- if (pp->use_inband_status && (cause_misc & +- (MVNETA_CAUSE_PHY_STATUS_CHANGE | +- MVNETA_CAUSE_LINK_CHANGE | +- MVNETA_CAUSE_PSC_SYNC_CHANGE))) { +- mvneta_fixed_link_update(pp, ndev->phydev); +- } ++ ++ if (cause_misc & (MVNETA_CAUSE_PHY_STATUS_CHANGE | ++ MVNETA_CAUSE_LINK_CHANGE | ++ MVNETA_CAUSE_PSC_SYNC_CHANGE)) ++ mvneta_link_change(pp); + } + + /* Release Tx descriptors */ +@@ -3060,7 +3019,6 @@ static int mvneta_setup_txqs(struct mvne + static void mvneta_start_dev(struct mvneta_port *pp) + { + int cpu; +- struct net_device *ndev = pp->dev; + + mvneta_max_rx_size_set(pp, pp->pkt_size); + mvneta_txq_max_tx_size_set(pp, pp->pkt_size); +@@ -3088,16 +3046,15 @@ static void mvneta_start_dev(struct mvne + MVNETA_CAUSE_LINK_CHANGE | + MVNETA_CAUSE_PSC_SYNC_CHANGE); + +- phy_start(ndev->phydev); ++ phylink_start(pp->phylink); + netif_tx_start_all_queues(pp->dev); + } + + static void mvneta_stop_dev(struct mvneta_port *pp) + { + unsigned int cpu; +- struct net_device *ndev = pp->dev; + +- phy_stop(ndev->phydev); ++ phylink_stop(pp->phylink); + + if (!pp->neta_armada3700) { + for_each_online_cpu(cpu) { +@@ -3251,103 +3208,232 @@ static int mvneta_set_mac_addr(struct ne + return 0; + } + +-static void mvneta_adjust_link(struct net_device *ndev) ++static void mvneta_validate(struct net_device *ndev, unsigned long *supported, ++ struct phylink_link_state *state) ++{ ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; ++ ++ /* Allow all the expected bits */ ++ phylink_set(mask, Autoneg); ++ phylink_set_port_modes(mask); ++ ++ /* Asymmetric pause is unsupported */ ++ phylink_set(mask, Pause); ++ /* Half-duplex at speeds higher than 100Mbit is unsupported */ ++ phylink_set(mask, 1000baseT_Full); ++ phylink_set(mask, 1000baseX_Full); ++ ++ if (state->interface != PHY_INTERFACE_MODE_1000BASEX) { ++ /* 10M and 100M are only supported in non-802.3z mode */ ++ phylink_set(mask, 10baseT_Half); ++ phylink_set(mask, 10baseT_Full); ++ phylink_set(mask, 100baseT_Half); ++ phylink_set(mask, 100baseT_Full); ++ } ++ ++ bitmap_and(supported, supported, mask, ++ __ETHTOOL_LINK_MODE_MASK_NBITS); ++ bitmap_and(state->advertising, state->advertising, mask, ++ __ETHTOOL_LINK_MODE_MASK_NBITS); ++} ++ ++static int mvneta_mac_link_state(struct net_device *ndev, ++ struct phylink_link_state *state) + { + struct mvneta_port *pp = netdev_priv(ndev); +- struct phy_device *phydev = ndev->phydev; +- int status_change = 0; ++ u32 gmac_stat; + +- if (phydev->link) { +- if ((pp->speed != phydev->speed) || +- (pp->duplex != phydev->duplex)) { +- u32 val; +- +- val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); +- val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED | +- MVNETA_GMAC_CONFIG_GMII_SPEED | +- MVNETA_GMAC_CONFIG_FULL_DUPLEX); +- +- if (phydev->duplex) +- val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX; +- +- if (phydev->speed == SPEED_1000) +- val |= MVNETA_GMAC_CONFIG_GMII_SPEED; +- else if (phydev->speed == SPEED_100) +- val |= MVNETA_GMAC_CONFIG_MII_SPEED; ++ gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS); + +- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); ++ if (gmac_stat & MVNETA_GMAC_SPEED_1000) ++ state->speed = SPEED_1000; ++ else if (gmac_stat & MVNETA_GMAC_SPEED_100) ++ state->speed = SPEED_100; ++ else ++ state->speed = SPEED_10; + +- pp->duplex = phydev->duplex; +- pp->speed = phydev->speed; +- } ++ state->an_complete = !!(gmac_stat & MVNETA_GMAC_AN_COMPLETE); ++ state->link = !!(gmac_stat & MVNETA_GMAC_LINK_UP); ++ state->duplex = !!(gmac_stat & MVNETA_GMAC_FULL_DUPLEX); ++ ++ state->pause = 0; ++ if (gmac_stat & MVNETA_GMAC_RX_FLOW_CTRL_ENABLE) ++ state->pause |= MLO_PAUSE_RX; ++ if (gmac_stat & MVNETA_GMAC_TX_FLOW_CTRL_ENABLE) ++ state->pause |= MLO_PAUSE_TX; ++ ++ return 1; ++} ++ ++static void mvneta_mac_an_restart(struct net_device *ndev) ++{ ++ struct mvneta_port *pp = netdev_priv(ndev); ++ u32 gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); ++ ++ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, ++ gmac_an | MVNETA_GMAC_INBAND_RESTART_AN); ++ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, ++ gmac_an & ~MVNETA_GMAC_INBAND_RESTART_AN); ++} ++ ++static void mvneta_mac_config(struct net_device *ndev, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++ struct mvneta_port *pp = netdev_priv(ndev); ++ u32 new_ctrl0, gmac_ctrl0 = mvreg_read(pp, MVNETA_GMAC_CTRL_0); ++ u32 new_ctrl2, gmac_ctrl2 = mvreg_read(pp, MVNETA_GMAC_CTRL_2); ++ u32 new_clk, gmac_clk = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); ++ u32 new_an, gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); ++ ++ new_ctrl0 = gmac_ctrl0 & ~MVNETA_GMAC0_PORT_1000BASE_X; ++ new_ctrl2 = gmac_ctrl2 & ~MVNETA_GMAC2_INBAND_AN_ENABLE; ++ new_clk = gmac_clk & ~MVNETA_GMAC_1MS_CLOCK_ENABLE; ++ new_an = gmac_an & ~(MVNETA_GMAC_INBAND_AN_ENABLE | ++ MVNETA_GMAC_INBAND_RESTART_AN | ++ MVNETA_GMAC_CONFIG_MII_SPEED | ++ MVNETA_GMAC_CONFIG_GMII_SPEED | ++ MVNETA_GMAC_AN_SPEED_EN | ++ MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL | ++ MVNETA_GMAC_CONFIG_FLOW_CTRL | ++ MVNETA_GMAC_AN_FLOW_CTRL_EN | ++ MVNETA_GMAC_CONFIG_FULL_DUPLEX | ++ MVNETA_GMAC_AN_DUPLEX_EN); ++ ++ if (phylink_test(state->advertising, Pause)) ++ new_an |= MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL; ++ if (state->pause & MLO_PAUSE_TXRX_MASK) ++ new_an |= MVNETA_GMAC_CONFIG_FLOW_CTRL; ++ ++ if (!phylink_autoneg_inband(mode)) { ++ /* Phy or fixed speed */ ++ if (state->duplex) ++ new_an |= MVNETA_GMAC_CONFIG_FULL_DUPLEX; ++ ++ if (state->speed == SPEED_1000) ++ new_an |= MVNETA_GMAC_CONFIG_GMII_SPEED; ++ else if (state->speed == SPEED_100) ++ new_an |= MVNETA_GMAC_CONFIG_MII_SPEED; ++ } else if (state->interface == PHY_INTERFACE_MODE_SGMII) { ++ /* SGMII mode receives the state from the PHY */ ++ new_ctrl2 |= MVNETA_GMAC2_INBAND_AN_ENABLE; ++ new_clk |= MVNETA_GMAC_1MS_CLOCK_ENABLE; ++ new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN | ++ MVNETA_GMAC_FORCE_LINK_PASS)) | ++ MVNETA_GMAC_INBAND_AN_ENABLE | ++ MVNETA_GMAC_AN_SPEED_EN | ++ MVNETA_GMAC_AN_DUPLEX_EN; ++ } else { ++ /* 802.3z negotiation - only 1000base-X */ ++ new_ctrl0 |= MVNETA_GMAC0_PORT_1000BASE_X; ++ new_clk |= MVNETA_GMAC_1MS_CLOCK_ENABLE; ++ new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN | ++ MVNETA_GMAC_FORCE_LINK_PASS)) | ++ MVNETA_GMAC_INBAND_AN_ENABLE | ++ MVNETA_GMAC_CONFIG_GMII_SPEED | ++ /* The MAC only supports FD mode */ ++ MVNETA_GMAC_CONFIG_FULL_DUPLEX; ++ ++ if (state->pause & MLO_PAUSE_AN && state->an_enabled) ++ new_an |= MVNETA_GMAC_AN_FLOW_CTRL_EN; ++ } ++ ++ /* Armada 370 documentation says we can only change the port mode ++ * and in-band enable when the link is down, so force it down ++ * while making these changes. We also do this for GMAC_CTRL2 */ ++ if ((new_ctrl0 ^ gmac_ctrl0) & MVNETA_GMAC0_PORT_1000BASE_X || ++ (new_ctrl2 ^ gmac_ctrl2) & MVNETA_GMAC2_INBAND_AN_ENABLE || ++ (new_an ^ gmac_an) & MVNETA_GMAC_INBAND_AN_ENABLE) { ++ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, ++ (gmac_an & ~MVNETA_GMAC_FORCE_LINK_PASS) | ++ MVNETA_GMAC_FORCE_LINK_DOWN); ++ } ++ ++ if (new_ctrl0 != gmac_ctrl0) ++ mvreg_write(pp, MVNETA_GMAC_CTRL_0, new_ctrl0); ++ if (new_ctrl2 != gmac_ctrl2) ++ mvreg_write(pp, MVNETA_GMAC_CTRL_2, new_ctrl2); ++ if (new_clk != gmac_clk) ++ mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, new_clk); ++ if (new_an != gmac_an) ++ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, new_an); ++} ++ ++static void mvneta_set_eee(struct mvneta_port *pp, bool enable) ++{ ++ u32 lpi_ctl1; ++ ++ lpi_ctl1 = mvreg_read(pp, MVNETA_LPI_CTRL_1); ++ if (enable) ++ lpi_ctl1 |= MVNETA_LPI_REQUEST_ENABLE; ++ else ++ lpi_ctl1 &= ~MVNETA_LPI_REQUEST_ENABLE; ++ mvreg_write(pp, MVNETA_LPI_CTRL_1, lpi_ctl1); ++} ++ ++static void mvneta_mac_link_down(struct net_device *ndev, unsigned int mode) ++{ ++ struct mvneta_port *pp = netdev_priv(ndev); ++ u32 val; ++ ++ mvneta_port_down(pp); ++ ++ if (!phylink_autoneg_inband(mode)) { ++ val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); ++ val &= ~MVNETA_GMAC_FORCE_LINK_PASS; ++ val |= MVNETA_GMAC_FORCE_LINK_DOWN; ++ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); + } + +- if (phydev->link != pp->link) { +- if (!phydev->link) { +- pp->duplex = -1; +- pp->speed = 0; +- } ++ pp->eee_active = false; ++ mvneta_set_eee(pp, false); ++} ++ ++static void mvneta_mac_link_up(struct net_device *ndev, unsigned int mode, ++ struct phy_device *phy) ++{ ++ struct mvneta_port *pp = netdev_priv(ndev); ++ u32 val; + +- pp->link = phydev->link; +- status_change = 1; ++ if (!phylink_autoneg_inband(mode)) { ++ val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); ++ val &= ~MVNETA_GMAC_FORCE_LINK_DOWN; ++ val |= MVNETA_GMAC_FORCE_LINK_PASS; ++ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); + } + +- if (status_change) { +- if (phydev->link) { +- if (!pp->use_inband_status) { +- u32 val = mvreg_read(pp, +- MVNETA_GMAC_AUTONEG_CONFIG); +- val &= ~MVNETA_GMAC_FORCE_LINK_DOWN; +- val |= MVNETA_GMAC_FORCE_LINK_PASS; +- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, +- val); +- } +- mvneta_port_up(pp); +- } else { +- if (!pp->use_inband_status) { +- u32 val = mvreg_read(pp, +- MVNETA_GMAC_AUTONEG_CONFIG); +- val &= ~MVNETA_GMAC_FORCE_LINK_PASS; +- val |= MVNETA_GMAC_FORCE_LINK_DOWN; +- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, +- val); +- } +- mvneta_port_down(pp); +- } +- phy_print_status(phydev); ++ mvneta_port_up(pp); ++ ++ if (phy && pp->eee_enabled) { ++ pp->eee_active = phy_init_eee(phy, 0) >= 0; ++ mvneta_set_eee(pp, pp->eee_active && pp->tx_lpi_enabled); + } + } + ++static const struct phylink_mac_ops mvneta_phylink_ops = { ++ .validate = mvneta_validate, ++ .mac_link_state = mvneta_mac_link_state, ++ .mac_an_restart = mvneta_mac_an_restart, ++ .mac_config = mvneta_mac_config, ++ .mac_link_down = mvneta_mac_link_down, ++ .mac_link_up = mvneta_mac_link_up, ++}; ++ + static int mvneta_mdio_probe(struct mvneta_port *pp) + { +- struct phy_device *phy_dev; + struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; ++ int err = phylink_of_phy_connect(pp->phylink, pp->dn); ++ if (err) ++ netdev_err(pp->dev, "could not attach PHY\n"); + +- phy_dev = of_phy_connect(pp->dev, pp->phy_node, mvneta_adjust_link, 0, +- pp->phy_interface); +- if (!phy_dev) { +- netdev_err(pp->dev, "could not find the PHY\n"); +- return -ENODEV; +- } +- +- phy_ethtool_get_wol(phy_dev, &wol); ++ phylink_ethtool_get_wol(pp->phylink, &wol); + device_set_wakeup_capable(&pp->dev->dev, !!wol.supported); + +- phy_dev->supported &= PHY_GBIT_FEATURES; +- phy_dev->advertising = phy_dev->supported; +- +- pp->link = 0; +- pp->duplex = 0; +- pp->speed = 0; +- +- return 0; ++ return err; + } + + static void mvneta_mdio_remove(struct mvneta_port *pp) + { +- struct net_device *ndev = pp->dev; +- +- phy_disconnect(ndev->phydev); ++ phylink_disconnect_phy(pp->phylink); + } + + /* Electing a CPU must be done in an atomic way: it should be done +@@ -3626,10 +3712,9 @@ static int mvneta_stop(struct net_device + + static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + { +- if (!dev->phydev) +- return -ENOTSUPP; ++ struct mvneta_port *pp = netdev_priv(dev); + +- return phy_mii_ioctl(dev->phydev, ifr, cmd); ++ return phylink_mii_ioctl(pp->phylink, ifr, cmd); + } + + /* Ethtool methods */ +@@ -3640,44 +3725,25 @@ mvneta_ethtool_set_link_ksettings(struct + const struct ethtool_link_ksettings *cmd) + { + struct mvneta_port *pp = netdev_priv(ndev); +- struct phy_device *phydev = ndev->phydev; + +- if (!phydev) +- return -ENODEV; +- +- if ((cmd->base.autoneg == AUTONEG_ENABLE) != pp->use_inband_status) { +- u32 val; +- +- mvneta_set_autoneg(pp, cmd->base.autoneg == AUTONEG_ENABLE); +- +- if (cmd->base.autoneg == AUTONEG_DISABLE) { +- val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); +- val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED | +- MVNETA_GMAC_CONFIG_GMII_SPEED | +- MVNETA_GMAC_CONFIG_FULL_DUPLEX); +- +- if (phydev->duplex) +- val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX; ++ return phylink_ethtool_ksettings_set(pp->phylink, cmd); ++} + +- if (phydev->speed == SPEED_1000) +- val |= MVNETA_GMAC_CONFIG_GMII_SPEED; +- else if (phydev->speed == SPEED_100) +- val |= MVNETA_GMAC_CONFIG_MII_SPEED; ++/* Get link ksettings for ethtools */ ++static int ++mvneta_ethtool_get_link_ksettings(struct net_device *ndev, ++ struct ethtool_link_ksettings *cmd) ++{ ++ struct mvneta_port *pp = netdev_priv(ndev); + +- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); +- } ++ return phylink_ethtool_ksettings_get(pp->phylink, cmd); ++} + +- pp->use_inband_status = (cmd->base.autoneg == AUTONEG_ENABLE); +- netdev_info(pp->dev, "autoneg status set to %i\n", +- pp->use_inband_status); +- +- if (netif_running(ndev)) { +- mvneta_port_down(pp); +- mvneta_port_up(pp); +- } +- } ++static int mvneta_ethtool_nway_reset(struct net_device *dev) ++{ ++ struct mvneta_port *pp = netdev_priv(dev); + +- return phy_ethtool_ksettings_set(ndev->phydev, cmd); ++ return phylink_ethtool_nway_reset(pp->phylink); + } + + /* Set interrupt coalescing for ethtools */ +@@ -3769,6 +3835,22 @@ static int mvneta_ethtool_set_ringparam( + return 0; + } + ++static void mvneta_ethtool_get_pauseparam(struct net_device *dev, ++ struct ethtool_pauseparam *pause) ++{ ++ struct mvneta_port *pp = netdev_priv(dev); ++ ++ phylink_ethtool_get_pauseparam(pp->phylink, pause); ++} ++ ++static int mvneta_ethtool_set_pauseparam(struct net_device *dev, ++ struct ethtool_pauseparam *pause) ++{ ++ struct mvneta_port *pp = netdev_priv(dev); ++ ++ return phylink_ethtool_set_pauseparam(pp->phylink, pause); ++} ++ + static void mvneta_ethtool_get_strings(struct net_device *netdev, u32 sset, + u8 *data) + { +@@ -3785,26 +3867,35 @@ static void mvneta_ethtool_update_stats( + { + const struct mvneta_statistic *s; + void __iomem *base = pp->base; +- u32 high, low, val; +- u64 val64; ++ u32 high, low; ++ u64 val; + int i; + + for (i = 0, s = mvneta_statistics; + s < mvneta_statistics + ARRAY_SIZE(mvneta_statistics); + s++, i++) { ++ val = 0; ++ + switch (s->type) { + case T_REG_32: + val = readl_relaxed(base + s->offset); +- pp->ethtool_stats[i] += val; + break; + case T_REG_64: + /* Docs say to read low 32-bit then high */ + low = readl_relaxed(base + s->offset); + high = readl_relaxed(base + s->offset + 4); +- val64 = (u64)high << 32 | low; +- pp->ethtool_stats[i] += val64; ++ val = (u64)high << 32 | low; ++ break; ++ case T_SW: ++ switch (s->offset) { ++ case ETHTOOL_STAT_EEE_WAKEUP: ++ val = phylink_get_eee_err(pp->phylink); ++ break; ++ } + break; + } ++ ++ pp->ethtool_stats[i] += val; + } + } + +@@ -3939,28 +4030,65 @@ static int mvneta_ethtool_get_rxfh(struc + static void mvneta_ethtool_get_wol(struct net_device *dev, + struct ethtool_wolinfo *wol) + { +- wol->supported = 0; +- wol->wolopts = 0; ++ struct mvneta_port *pp = netdev_priv(dev); + +- if (dev->phydev) +- phy_ethtool_get_wol(dev->phydev, wol); ++ phylink_ethtool_get_wol(pp->phylink, wol); + } + + static int mvneta_ethtool_set_wol(struct net_device *dev, + struct ethtool_wolinfo *wol) + { ++ struct mvneta_port *pp = netdev_priv(dev); + int ret; + +- if (!dev->phydev) +- return -EOPNOTSUPP; +- +- ret = phy_ethtool_set_wol(dev->phydev, wol); ++ ret = phylink_ethtool_set_wol(pp->phylink, wol); + if (!ret) + device_set_wakeup_enable(&dev->dev, !!wol->wolopts); + + return ret; + } + ++static int mvneta_ethtool_get_eee(struct net_device *dev, ++ struct ethtool_eee *eee) ++{ ++ struct mvneta_port *pp = netdev_priv(dev); ++ u32 lpi_ctl0; ++ ++ lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0); ++ ++ eee->eee_enabled = pp->eee_enabled; ++ eee->eee_active = pp->eee_active; ++ eee->tx_lpi_enabled = pp->tx_lpi_enabled; ++ eee->tx_lpi_timer = (lpi_ctl0) >> 8; // * scale; ++ ++ return phylink_ethtool_get_eee(pp->phylink, eee); ++} ++ ++static int mvneta_ethtool_set_eee(struct net_device *dev, ++ struct ethtool_eee *eee) ++{ ++ struct mvneta_port *pp = netdev_priv(dev); ++ u32 lpi_ctl0; ++ ++ /* The Armada 37x documents do not give limits for this other than ++ * it being an 8-bit register. */ ++ if (eee->tx_lpi_enabled && ++ (eee->tx_lpi_timer < 0 || eee->tx_lpi_timer > 255)) ++ return -EINVAL; ++ ++ lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0); ++ lpi_ctl0 &= ~(0xff << 8); ++ lpi_ctl0 |= eee->tx_lpi_timer << 8; ++ mvreg_write(pp, MVNETA_LPI_CTRL_0, lpi_ctl0); ++ ++ pp->eee_enabled = eee->eee_enabled; ++ pp->tx_lpi_enabled = eee->tx_lpi_enabled; ++ ++ mvneta_set_eee(pp, eee->tx_lpi_enabled && eee->eee_enabled); ++ ++ return phylink_ethtool_set_eee(pp->phylink, eee); ++} ++ + static u16 mvneta_select_queue(struct net_device *dev, struct sk_buff *skb, + void *accel_priv, + select_queue_fallback_t fallback) +@@ -3984,13 +4112,15 @@ static const struct net_device_ops mvnet + }; + + static const struct ethtool_ops mvneta_eth_tool_ops = { +- .nway_reset = phy_ethtool_nway_reset, ++ .nway_reset = mvneta_ethtool_nway_reset, + .get_link = ethtool_op_get_link, + .set_coalesce = mvneta_ethtool_set_coalesce, + .get_coalesce = mvneta_ethtool_get_coalesce, + .get_drvinfo = mvneta_ethtool_get_drvinfo, + .get_ringparam = mvneta_ethtool_get_ringparam, + .set_ringparam = mvneta_ethtool_set_ringparam, ++ .get_pauseparam = mvneta_ethtool_get_pauseparam, ++ .set_pauseparam = mvneta_ethtool_set_pauseparam, + .get_strings = mvneta_ethtool_get_strings, + .get_ethtool_stats = mvneta_ethtool_get_stats, + .get_sset_count = mvneta_ethtool_get_sset_count, +@@ -3998,10 +4128,12 @@ static const struct ethtool_ops mvneta_e + .get_rxnfc = mvneta_ethtool_get_rxnfc, + .get_rxfh = mvneta_ethtool_get_rxfh, + .set_rxfh = mvneta_ethtool_set_rxfh, +- .get_link_ksettings = phy_ethtool_get_link_ksettings, ++ .get_link_ksettings = mvneta_ethtool_get_link_ksettings, + .set_link_ksettings = mvneta_ethtool_set_link_ksettings, + .get_wol = mvneta_ethtool_get_wol, + .set_wol = mvneta_ethtool_set_wol, ++ .get_eee = mvneta_ethtool_get_eee, ++ .set_eee = mvneta_ethtool_set_eee, + }; + + /* Initialize hw */ +@@ -4146,14 +4278,13 @@ static int mvneta_probe(struct platform_ + { + struct resource *res; + struct device_node *dn = pdev->dev.of_node; +- struct device_node *phy_node; + struct device_node *bm_node; + struct mvneta_port *pp; + struct net_device *dev; ++ struct phylink *phylink; + const char *dt_mac_addr; + char hw_mac_addr[ETH_ALEN]; + const char *mac_from; +- const char *managed; + int tx_csum_limit; + int phy_mode; + int err; +@@ -4169,31 +4300,11 @@ static int mvneta_probe(struct platform_ + goto err_free_netdev; + } + +- phy_node = of_parse_phandle(dn, "phy", 0); +- if (!phy_node) { +- if (!of_phy_is_fixed_link(dn)) { +- dev_err(&pdev->dev, "no PHY specified\n"); +- err = -ENODEV; +- goto err_free_irq; +- } +- +- err = of_phy_register_fixed_link(dn); +- if (err < 0) { +- dev_err(&pdev->dev, "cannot register fixed PHY\n"); +- goto err_free_irq; +- } +- +- /* In the case of a fixed PHY, the DT node associated +- * to the PHY is the Ethernet MAC DT node. +- */ +- phy_node = of_node_get(dn); +- } +- + phy_mode = of_get_phy_mode(dn); + if (phy_mode < 0) { + dev_err(&pdev->dev, "incorrect phy-mode\n"); + err = -EINVAL; +- goto err_put_phy_node; ++ goto err_free_irq; + } + + dev->tx_queue_len = MVNETA_MAX_TXD; +@@ -4204,12 +4315,7 @@ static int mvneta_probe(struct platform_ + + pp = netdev_priv(dev); + spin_lock_init(&pp->lock); +- pp->phy_node = phy_node; +- pp->phy_interface = phy_mode; +- +- err = of_property_read_string(dn, "managed", &managed); +- pp->use_inband_status = (err == 0 && +- strcmp(managed, "in-band-status") == 0); ++ pp->dn = dn; + + pp->rxq_def = rxq_def; + +@@ -4231,7 +4337,7 @@ static int mvneta_probe(struct platform_ + pp->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(pp->clk)) { + err = PTR_ERR(pp->clk); +- goto err_put_phy_node; ++ goto err_free_irq; + } + + clk_prepare_enable(pp->clk); +@@ -4357,6 +4463,14 @@ static int mvneta_probe(struct platform_ + /* 9676 == 9700 - 20 and rounding to 8 */ + dev->max_mtu = 9676; + ++ phylink = phylink_create(dev, dn, phy_mode, &mvneta_phylink_ops); ++ if (IS_ERR(phylink)) { ++ err = PTR_ERR(phylink); ++ goto err_free_stats; ++ } ++ ++ pp->phylink = phylink; ++ + err = register_netdev(dev); + if (err < 0) { + dev_err(&pdev->dev, "failed to register\n"); +@@ -4368,14 +4482,6 @@ static int mvneta_probe(struct platform_ + + platform_set_drvdata(pdev, pp->dev); + +- if (pp->use_inband_status) { +- struct phy_device *phy = of_phy_find_device(dn); +- +- mvneta_fixed_link_update(pp, phy); +- +- put_device(&phy->mdio.dev); +- } +- + return 0; + + err_netdev: +@@ -4386,16 +4492,14 @@ err_netdev: + 1 << pp->id); + } + err_free_stats: ++ if (pp->phylink) ++ phylink_destroy(pp->phylink); + free_percpu(pp->stats); + err_free_ports: + free_percpu(pp->ports); + err_clk: + clk_disable_unprepare(pp->clk_bus); + clk_disable_unprepare(pp->clk); +-err_put_phy_node: +- of_node_put(phy_node); +- if (of_phy_is_fixed_link(dn)) +- of_phy_deregister_fixed_link(dn); + err_free_irq: + irq_dispose_mapping(dev->irq); + err_free_netdev: +@@ -4407,7 +4511,6 @@ err_free_netdev: + static int mvneta_remove(struct platform_device *pdev) + { + struct net_device *dev = platform_get_drvdata(pdev); +- struct device_node *dn = pdev->dev.of_node; + struct mvneta_port *pp = netdev_priv(dev); + + unregister_netdev(dev); +@@ -4415,10 +4518,8 @@ static int mvneta_remove(struct platform + clk_disable_unprepare(pp->clk); + free_percpu(pp->ports); + free_percpu(pp->stats); +- if (of_phy_is_fixed_link(dn)) +- of_phy_deregister_fixed_link(dn); + irq_dispose_mapping(dev->irq); +- of_node_put(pp->phy_node); ++ phylink_destroy(pp->phylink); + free_netdev(dev); + + if (pp->bm_priv) { +@@ -4470,9 +4571,6 @@ static int mvneta_resume(struct device * + return err; + } + +- if (pp->use_inband_status) +- mvneta_fixed_link_update(pp, dev->phydev); +- + netif_device_attach(dev); + if (netif_running(dev)) { + mvneta_open(dev); diff --git a/target/linux/mvebu/patches-4.14/404-net-mvneta-hack-fix-phy_interface.patch b/target/linux/mvebu/patches-4.14/404-net-mvneta-hack-fix-phy_interface.patch new file mode 100644 index 000000000..906c163ac --- /dev/null +++ b/target/linux/mvebu/patches-4.14/404-net-mvneta-hack-fix-phy_interface.patch @@ -0,0 +1,28 @@ +From acdfcc7ef78c46baca1439a1cac5b73008abc672 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Tue, 16 May 2017 11:55:58 +0100 +Subject: net: mvneta: hack fix phy_interface + +Signed-off-by: Russell King +--- + drivers/net/ethernet/marvell/mvneta.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -427,6 +427,7 @@ struct mvneta_port { + u16 tx_ring_size; + u16 rx_ring_size; + ++ phy_interface_t phy_interface; + struct device_node *dn; + unsigned int tx_csum_limit; + struct phylink *phylink; +@@ -4315,6 +4316,7 @@ static int mvneta_probe(struct platform_ + + pp = netdev_priv(dev); + spin_lock_init(&pp->lock); ++ pp->phy_interface = phy_mode; + pp->dn = dn; + + pp->rxq_def = rxq_def; diff --git a/target/linux/mvebu/patches-4.14/405-net-mvneta-disable-MVNETA_CAUSE_PSC_SYNC_CHANGE-inte.patch b/target/linux/mvebu/patches-4.14/405-net-mvneta-disable-MVNETA_CAUSE_PSC_SYNC_CHANGE-inte.patch new file mode 100644 index 000000000..ddb0cc8a2 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/405-net-mvneta-disable-MVNETA_CAUSE_PSC_SYNC_CHANGE-inte.patch @@ -0,0 +1,56 @@ +From fde9e742a47606110232b7464608b6f9c0510938 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Sat, 24 Dec 2016 10:27:08 +0000 +Subject: net: mvneta: disable MVNETA_CAUSE_PSC_SYNC_CHANGE interrupt + +The PSC sync change interrupt can fire multiple times while the link is +down. As this isn't information we make use of, it's pointless having +the interrupt enabled, so let's disable this interrupt. + +Signed-off-by: Russell King +--- + drivers/net/ethernet/marvell/mvneta.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -2704,8 +2704,7 @@ static int mvneta_poll(struct napi_struc + mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0); + + if (cause_misc & (MVNETA_CAUSE_PHY_STATUS_CHANGE | +- MVNETA_CAUSE_LINK_CHANGE | +- MVNETA_CAUSE_PSC_SYNC_CHANGE)) ++ MVNETA_CAUSE_LINK_CHANGE)) + mvneta_link_change(pp); + } + +@@ -3044,8 +3043,7 @@ static void mvneta_start_dev(struct mvne + + mvreg_write(pp, MVNETA_INTR_MISC_MASK, + MVNETA_CAUSE_PHY_STATUS_CHANGE | +- MVNETA_CAUSE_LINK_CHANGE | +- MVNETA_CAUSE_PSC_SYNC_CHANGE); ++ MVNETA_CAUSE_LINK_CHANGE); + + phylink_start(pp->phylink); + netif_tx_start_all_queues(pp->dev); +@@ -3542,8 +3540,7 @@ static int mvneta_cpu_online(unsigned in + on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true); + mvreg_write(pp, MVNETA_INTR_MISC_MASK, + MVNETA_CAUSE_PHY_STATUS_CHANGE | +- MVNETA_CAUSE_LINK_CHANGE | +- MVNETA_CAUSE_PSC_SYNC_CHANGE); ++ MVNETA_CAUSE_LINK_CHANGE); + netif_tx_start_all_queues(pp->dev); + spin_unlock(&pp->lock); + return 0; +@@ -3584,8 +3581,7 @@ static int mvneta_cpu_dead(unsigned int + on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true); + mvreg_write(pp, MVNETA_INTR_MISC_MASK, + MVNETA_CAUSE_PHY_STATUS_CHANGE | +- MVNETA_CAUSE_LINK_CHANGE | +- MVNETA_CAUSE_PSC_SYNC_CHANGE); ++ MVNETA_CAUSE_LINK_CHANGE); + netif_tx_start_all_queues(pp->dev); + return 0; + } diff --git a/target/linux/mvebu/patches-4.14/406-net-mvneta-add-module-EEPROM-reading-support.patch b/target/linux/mvebu/patches-4.14/406-net-mvneta-add-module-EEPROM-reading-support.patch new file mode 100644 index 000000000..39eb33ac2 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/406-net-mvneta-add-module-EEPROM-reading-support.patch @@ -0,0 +1,44 @@ +From 2ff039aa4462c2104c210b7cf39691c612de8214 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Thu, 1 Oct 2015 23:32:39 +0100 +Subject: net: mvneta: add module EEPROM reading support + +Signed-off-by: Russell King +--- + drivers/net/ethernet/marvell/mvneta.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -4045,6 +4045,22 @@ static int mvneta_ethtool_set_wol(struct + return ret; + } + ++static int mvneta_ethtool_get_module_info(struct net_device *dev, ++ struct ethtool_modinfo *modinfo) ++{ ++ struct mvneta_port *pp = netdev_priv(dev); ++ ++ return phylink_ethtool_get_module_info(pp->phylink, modinfo); ++} ++ ++static int mvneta_ethtool_get_module_eeprom(struct net_device *dev, ++ struct ethtool_eeprom *ee, u8 *buf) ++{ ++ struct mvneta_port *pp = netdev_priv(dev); ++ ++ return phylink_ethtool_get_module_eeprom(pp->phylink, ee, buf); ++} ++ + static int mvneta_ethtool_get_eee(struct net_device *dev, + struct ethtool_eee *eee) + { +@@ -4129,6 +4145,8 @@ static const struct ethtool_ops mvneta_e + .set_link_ksettings = mvneta_ethtool_set_link_ksettings, + .get_wol = mvneta_ethtool_get_wol, + .set_wol = mvneta_ethtool_set_wol, ++ .get_module_info = mvneta_ethtool_get_module_info, ++ .get_module_eeprom = mvneta_ethtool_get_module_eeprom, + .get_eee = mvneta_ethtool_get_eee, + .set_eee = mvneta_ethtool_set_eee, + }; diff --git a/target/linux/mvebu/patches-4.14/407-phy-fixed-phy-remove-fixed_phy_update_state.patch b/target/linux/mvebu/patches-4.14/407-phy-fixed-phy-remove-fixed_phy_update_state.patch new file mode 100644 index 000000000..71c2f4555 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/407-phy-fixed-phy-remove-fixed_phy_update_state.patch @@ -0,0 +1,80 @@ +From 774ce2eda0a929f79ee398ba6d2d13fd406f31c4 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Fri, 2 Oct 2015 22:46:54 +0100 +Subject: phy: fixed-phy: remove fixed_phy_update_state() + +mvneta is the only user of fixed_phy_update_state(), which has been +converted to use phylink instead. Remove fixed_phy_update_state(). + +Reviewed-by: Florian Fainelli +Signed-off-by: Russell King +--- + drivers/net/phy/fixed_phy.c | 31 ------------------------------- + include/linux/phy_fixed.h | 9 --------- + 2 files changed, 40 deletions(-) + +--- a/drivers/net/phy/fixed_phy.c ++++ b/drivers/net/phy/fixed_phy.c +@@ -115,37 +115,6 @@ int fixed_phy_set_link_update(struct phy + } + EXPORT_SYMBOL_GPL(fixed_phy_set_link_update); + +-int fixed_phy_update_state(struct phy_device *phydev, +- const struct fixed_phy_status *status, +- const struct fixed_phy_status *changed) +-{ +- struct fixed_mdio_bus *fmb = &platform_fmb; +- struct fixed_phy *fp; +- +- if (!phydev || phydev->mdio.bus != fmb->mii_bus) +- return -EINVAL; +- +- list_for_each_entry(fp, &fmb->phys, node) { +- if (fp->addr == phydev->mdio.addr) { +- write_seqcount_begin(&fp->seqcount); +-#define _UPD(x) if (changed->x) \ +- fp->status.x = status->x +- _UPD(link); +- _UPD(speed); +- _UPD(duplex); +- _UPD(pause); +- _UPD(asym_pause); +-#undef _UPD +- fixed_phy_update(fp); +- write_seqcount_end(&fp->seqcount); +- return 0; +- } +- } +- +- return -ENOENT; +-} +-EXPORT_SYMBOL(fixed_phy_update_state); +- + int fixed_phy_add(unsigned int irq, int phy_addr, + struct fixed_phy_status *status, + int link_gpio) +--- a/include/linux/phy_fixed.h ++++ b/include/linux/phy_fixed.h +@@ -24,9 +24,6 @@ extern void fixed_phy_unregister(struct + extern int fixed_phy_set_link_update(struct phy_device *phydev, + int (*link_update)(struct net_device *, + struct fixed_phy_status *)); +-extern int fixed_phy_update_state(struct phy_device *phydev, +- const struct fixed_phy_status *status, +- const struct fixed_phy_status *changed); + #else + static inline int fixed_phy_add(unsigned int irq, int phy_id, + struct fixed_phy_status *status, +@@ -50,12 +47,6 @@ static inline int fixed_phy_set_link_upd + { + return -ENODEV; + } +-static inline int fixed_phy_update_state(struct phy_device *phydev, +- const struct fixed_phy_status *status, +- const struct fixed_phy_status *changed) +-{ +- return -ENODEV; +-} + #endif /* CONFIG_FIXED_PHY */ + + #endif /* __PHY_FIXED_H */ diff --git a/target/linux/mvebu/patches-4.14/408-sfp-move-module-eeprom-ethtool-access-into-netdev-co.patch b/target/linux/mvebu/patches-4.14/408-sfp-move-module-eeprom-ethtool-access-into-netdev-co.patch new file mode 100644 index 000000000..1960326f0 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/408-sfp-move-module-eeprom-ethtool-access-into-netdev-co.patch @@ -0,0 +1,181 @@ +From c47beb7e3f8575dfd7d58240a72c4e4e66ce5449 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Fri, 14 Apr 2017 15:26:32 +0100 +Subject: sfp: move module eeprom ethtool access into netdev core ethtool + +Signed-off-by: Russell King +--- + drivers/net/ethernet/marvell/mvneta.c | 18 ------------------ + drivers/net/phy/phylink.c | 28 ---------------------------- + drivers/net/phy/sfp-bus.c | 6 ++---- + include/linux/netdevice.h | 2 ++ + include/linux/phylink.h | 3 --- + net/core/ethtool.c | 7 +++++++ + 6 files changed, 11 insertions(+), 53 deletions(-) + +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -4045,22 +4045,6 @@ static int mvneta_ethtool_set_wol(struct + return ret; + } + +-static int mvneta_ethtool_get_module_info(struct net_device *dev, +- struct ethtool_modinfo *modinfo) +-{ +- struct mvneta_port *pp = netdev_priv(dev); +- +- return phylink_ethtool_get_module_info(pp->phylink, modinfo); +-} +- +-static int mvneta_ethtool_get_module_eeprom(struct net_device *dev, +- struct ethtool_eeprom *ee, u8 *buf) +-{ +- struct mvneta_port *pp = netdev_priv(dev); +- +- return phylink_ethtool_get_module_eeprom(pp->phylink, ee, buf); +-} +- + static int mvneta_ethtool_get_eee(struct net_device *dev, + struct ethtool_eee *eee) + { +@@ -4145,8 +4129,6 @@ static const struct ethtool_ops mvneta_e + .set_link_ksettings = mvneta_ethtool_set_link_ksettings, + .get_wol = mvneta_ethtool_get_wol, + .set_wol = mvneta_ethtool_set_wol, +- .get_module_info = mvneta_ethtool_get_module_info, +- .get_module_eeprom = mvneta_ethtool_get_module_eeprom, + .get_eee = mvneta_ethtool_get_eee, + .set_eee = mvneta_ethtool_set_eee, + }; +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -1040,34 +1040,6 @@ int phylink_ethtool_set_pauseparam(struc + } + EXPORT_SYMBOL_GPL(phylink_ethtool_set_pauseparam); + +-int phylink_ethtool_get_module_info(struct phylink *pl, +- struct ethtool_modinfo *modinfo) +-{ +- int ret = -EOPNOTSUPP; +- +- WARN_ON(!lockdep_rtnl_is_held()); +- +- if (pl->sfp_bus) +- ret = sfp_get_module_info(pl->sfp_bus, modinfo); +- +- return ret; +-} +-EXPORT_SYMBOL_GPL(phylink_ethtool_get_module_info); +- +-int phylink_ethtool_get_module_eeprom(struct phylink *pl, +- struct ethtool_eeprom *ee, u8 *buf) +-{ +- int ret = -EOPNOTSUPP; +- +- WARN_ON(!lockdep_rtnl_is_held()); +- +- if (pl->sfp_bus) +- ret = sfp_get_module_eeprom(pl->sfp_bus, ee, buf); +- +- return ret; +-} +-EXPORT_SYMBOL_GPL(phylink_ethtool_get_module_eeprom); +- + int phylink_init_eee(struct phylink *pl, bool clk_stop_enable) + { + int ret = -EPROTONOSUPPORT; +--- a/drivers/net/phy/sfp-bus.c ++++ b/drivers/net/phy/sfp-bus.c +@@ -278,6 +278,7 @@ static int sfp_register_bus(struct sfp_b + } + if (bus->started) + bus->socket_ops->start(bus->sfp); ++ bus->netdev->sfp_bus = bus; + bus->registered = true; + return 0; + } +@@ -292,14 +293,13 @@ static void sfp_unregister_bus(struct sf + if (bus->phydev && ops && ops->disconnect_phy) + ops->disconnect_phy(bus->upstream); + } ++ bus->netdev->sfp_bus = NULL; + bus->registered = false; + } + + + int sfp_get_module_info(struct sfp_bus *bus, struct ethtool_modinfo *modinfo) + { +- if (!bus->registered) +- return -ENOIOCTLCMD; + return bus->socket_ops->module_info(bus->sfp, modinfo); + } + EXPORT_SYMBOL_GPL(sfp_get_module_info); +@@ -307,8 +307,6 @@ EXPORT_SYMBOL_GPL(sfp_get_module_info); + int sfp_get_module_eeprom(struct sfp_bus *bus, struct ethtool_eeprom *ee, + u8 *data) + { +- if (!bus->registered) +- return -ENOIOCTLCMD; + return bus->socket_ops->module_eeprom(bus->sfp, ee, data); + } + EXPORT_SYMBOL_GPL(sfp_get_module_eeprom); +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -57,6 +57,7 @@ struct device; + struct phy_device; + struct dsa_switch_tree; + ++struct sfp_bus; + /* 802.11 specific */ + struct wireless_dev; + /* 802.15.4 specific */ +@@ -1908,6 +1909,7 @@ struct net_device { + struct netprio_map __rcu *priomap; + #endif + struct phy_device *phydev; ++ struct sfp_bus *sfp_bus; + struct lock_class_key *qdisc_tx_busylock; + struct lock_class_key *qdisc_running_key; + bool proto_down; +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -125,9 +125,6 @@ void phylink_ethtool_get_pauseparam(stru + struct ethtool_pauseparam *); + int phylink_ethtool_set_pauseparam(struct phylink *, + struct ethtool_pauseparam *); +-int phylink_ethtool_get_module_info(struct phylink *, struct ethtool_modinfo *); +-int phylink_ethtool_get_module_eeprom(struct phylink *, +- struct ethtool_eeprom *, u8 *); + int phylink_init_eee(struct phylink *, bool); + int phylink_get_eee_err(struct phylink *); + int phylink_ethtool_get_eee(struct phylink *, struct ethtool_eee *); +--- a/net/core/ethtool.c ++++ b/net/core/ethtool.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -2190,6 +2191,9 @@ static int __ethtool_get_module_info(str + const struct ethtool_ops *ops = dev->ethtool_ops; + struct phy_device *phydev = dev->phydev; + ++ if (dev->sfp_bus) ++ return sfp_get_module_info(dev->sfp_bus, modinfo); ++ + if (phydev && phydev->drv && phydev->drv->module_info) + return phydev->drv->module_info(phydev, modinfo); + +@@ -2224,6 +2228,9 @@ static int __ethtool_get_module_eeprom(s + const struct ethtool_ops *ops = dev->ethtool_ops; + struct phy_device *phydev = dev->phydev; + ++ if (dev->sfp_bus) ++ return sfp_get_module_eeprom(dev->sfp_bus, ee, data); ++ + if (phydev && phydev->drv && phydev->drv->module_eeprom) + return phydev->drv->module_eeprom(phydev, ee, data); + diff --git a/target/linux/mvebu/patches-4.14/409-sfp-use-netdev-sfp_bus-for-start-stop.patch b/target/linux/mvebu/patches-4.14/409-sfp-use-netdev-sfp_bus-for-start-stop.patch new file mode 100644 index 000000000..7023b57a5 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/409-sfp-use-netdev-sfp_bus-for-start-stop.patch @@ -0,0 +1,34 @@ +From 883dc66755313e133a787eba4dfde313fe33525b Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Fri, 14 Apr 2017 16:41:55 +0100 +Subject: sfp: use netdev sfp_bus for start/stop + +Signed-off-by: Russell King +--- + drivers/net/phy/phylink.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -755,8 +755,8 @@ void phylink_start(struct phylink *pl) + clear_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); + phylink_run_resolve(pl); + +- if (pl->sfp_bus) +- sfp_upstream_start(pl->sfp_bus); ++ if (pl->netdev->sfp_bus) ++ sfp_upstream_start(pl->netdev->sfp_bus); + if (pl->phydev) + phy_start(pl->phydev); + } +@@ -768,8 +768,8 @@ void phylink_stop(struct phylink *pl) + + if (pl->phydev) + phy_stop(pl->phydev); +- if (pl->sfp_bus) +- sfp_upstream_stop(pl->sfp_bus); ++ if (pl->netdev->sfp_bus) ++ sfp_upstream_stop(pl->netdev->sfp_bus); + + set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); + queue_work(system_power_efficient_wq, &pl->resolve); diff --git a/target/linux/mvebu/patches-4.14/410-sfp-hack-allow-marvell-10G-phy-support-to-use-SFP.patch b/target/linux/mvebu/patches-4.14/410-sfp-hack-allow-marvell-10G-phy-support-to-use-SFP.patch new file mode 100644 index 000000000..6ca43043f --- /dev/null +++ b/target/linux/mvebu/patches-4.14/410-sfp-hack-allow-marvell-10G-phy-support-to-use-SFP.patch @@ -0,0 +1,131 @@ +From 4a4aca08b11501cb1b2c509113bbb65eb66a1f45 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Fri, 14 Apr 2017 14:21:25 +0100 +Subject: sfp: hack: allow marvell 10G phy support to use SFP + +Allow the Marvell 10G PHY to register with the SFP bus, so that SFP+ +cages can work. This bypasses phylink, meaning that socket status +is not taken into account for the link state. Also, the tx-disable +signal must be commented out in DT for this to work... + +Signed-off-by: Russell King +--- + drivers/net/phy/marvell10g.c | 54 +++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 53 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/marvell10g.c ++++ b/drivers/net/phy/marvell10g.c +@@ -15,8 +15,10 @@ + * If both the fiber and copper ports are connected, the first to gain + * link takes priority and the other port is completely locked out. + */ ++#include + #include + #include ++#include + + enum { + MV_PCS_BASE_T = 0x0000, +@@ -38,6 +40,11 @@ enum { + MV_AN_RESULT_SPD_10000 = BIT(15), + }; + ++struct mv3310_priv { ++ struct device_node *sfp_node; ++ struct sfp_bus *sfp_bus; ++}; ++ + static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg, + u16 mask, u16 bits) + { +@@ -56,17 +63,52 @@ static int mv3310_modify(struct phy_devi + return ret < 0 ? ret : 1; + } + ++static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) ++{ ++ struct phy_device *phydev = upstream; ++ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); ++ ++ if (sfp_parse_interface(priv->sfp_bus, id) != PHY_INTERFACE_MODE_10GKR) { ++ dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static const struct sfp_upstream_ops mv3310_sfp_ops = { ++ .module_insert = mv3310_sfp_insert, ++}; ++ + static int mv3310_probe(struct phy_device *phydev) + { ++ struct mv3310_priv *priv; + u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN; + + if (!phydev->is_c45 || + (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask) + return -ENODEV; + ++ priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ dev_set_drvdata(&phydev->mdio.dev, priv); ++ ++ if (phydev->mdio.dev.of_node) ++ priv->sfp_node = of_parse_phandle(phydev->mdio.dev.of_node, ++ "sfp", 0); ++ + return 0; + } + ++static void mv3310_remove(struct phy_device *phydev) ++{ ++ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); ++ ++ if (priv->sfp_bus) ++ sfp_unregister_upstream(priv->sfp_bus); ++} ++ + /* + * Resetting the MV88X3310 causes it to become non-responsive. Avoid + * setting the reset bit(s). +@@ -78,6 +120,7 @@ static int mv3310_soft_reset(struct phy_ + + static int mv3310_config_init(struct phy_device *phydev) + { ++ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, }; + u32 mask; + int val; +@@ -166,6 +209,14 @@ static int mv3310_config_init(struct phy + phydev->supported &= mask; + phydev->advertising &= phydev->supported; + ++ /* Would be nice to do this in the probe function, but unfortunately, ++ * phylib doesn't have phydev->attached_dev set there. ++ */ ++ if (priv->sfp_node && !priv->sfp_bus) ++ priv->sfp_bus = sfp_register_upstream(priv->sfp_node, ++ phydev->attached_dev, ++ phydev, &mv3310_sfp_ops); ++ + return 0; + } + +@@ -349,12 +400,13 @@ static struct phy_driver mv3310_drivers[ + SUPPORTED_FIBRE | + SUPPORTED_10000baseT_Full | + SUPPORTED_Backplane, +- .probe = mv3310_probe, + .soft_reset = mv3310_soft_reset, + .config_init = mv3310_config_init, ++ .probe = mv3310_probe, + .config_aneg = mv3310_config_aneg, + .aneg_done = mv3310_aneg_done, + .read_status = mv3310_read_status, ++ .remove = mv3310_remove, + }, + }; + diff --git a/target/linux/mvebu/patches-4.14/411-sfp-add-sfp-compatible.patch b/target/linux/mvebu/patches-4.14/411-sfp-add-sfp-compatible.patch new file mode 100644 index 000000000..b775116cd --- /dev/null +++ b/target/linux/mvebu/patches-4.14/411-sfp-add-sfp-compatible.patch @@ -0,0 +1,24 @@ +From 3344f73509a34d2124b716efc79cd9787773018b Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Fri, 14 Apr 2017 20:17:13 +0100 +Subject: sfp: add sfp+ compatible + +Add a compatible for SFP+ cages. SFP+ cages are backwards compatible, +but the ethernet device behind them may not support the slower speeds +of SFP modules. + +Signed-off-by: Russell King +--- + drivers/net/phy/sfp.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -1136,6 +1136,7 @@ static int sfp_remove(struct platform_de + + static const struct of_device_id sfp_of_match[] = { + { .compatible = "sff,sfp", }, ++ { .compatible = "sff,sfp+", }, + { }, + }; + MODULE_DEVICE_TABLE(of, sfp_of_match); diff --git a/target/linux/mvebu/patches-4.4/470-ClearFog-renamed-upstream.patch b/target/linux/mvebu/patches-4.14/412-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch similarity index 62% rename from target/linux/mvebu/patches-4.4/470-ClearFog-renamed-upstream.patch rename to target/linux/mvebu/patches-4.14/412-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch index 3eeda9fd3..222a32382 100644 --- a/target/linux/mvebu/patches-4.4/470-ClearFog-renamed-upstream.patch +++ b/target/linux/mvebu/patches-4.14/412-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch @@ -1,30 +1,30 @@ -From b0db8cc1fe7eab722bc1f7c386132b3905d67f30 Mon Sep 17 00:00:00 2001 -From: Marko Ratkaj -Date: Fri, 7 Apr 2017 11:01:26 +0200 -Subject: [PATCH 1/2] ClearFog renamed upstream +From 8137da20701c776ad3481115305a5e8e410871ba Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Tue, 29 Nov 2016 10:15:45 +0000 +Subject: ARM: dts: armada388-clearfog: emmc on clearfog base -Signed-off-by: Marko Ratkaj +Signed-off-by: Russell King --- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/armada-388-clearfog-pro.dts | 55 +++++++++++++++++++++++++++ - 2 files changed, 56 insertions(+) - create mode 100644 arch/arm/boot/dts/armada-388-clearfog-pro.dts + arch/arm/boot/dts/armada-388-clearfog-base.dts | 1 + + .../dts/armada-38x-solidrun-microsom-emmc.dtsi | 62 ++++++++++++++++++++++ + 2 files changed, 63 insertions(+) + create mode 100644 arch/arm/boot/dts/armada-38x-solidrun-microsom-emmc.dtsi ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -924,6 +924,7 @@ dtb-$(CONFIG_MACH_ARMADA_38X) += \ - armada-385-linksys-rango.dtb \ - armada-385-linksys-shelby.dtb \ - armada-388-clearfog.dtb \ -+ armada-388-clearfog-pro.dtb \ - armada-388-db.dtb \ - armada-388-gp.dtb \ - armada-388-rd.dtb +--- a/arch/arm/boot/dts/armada-388-clearfog-base.dts ++++ b/arch/arm/boot/dts/armada-388-clearfog-base.dts +@@ -48,6 +48,7 @@ + + /dts-v1/; + #include "armada-388-clearfog.dtsi" ++#include "armada-38x-solidrun-microsom-emmc.dtsi" + + / { + model = "SolidRun Clearfog Base A1"; --- /dev/null -+++ b/arch/arm/boot/dts/armada-388-clearfog-pro.dts -@@ -0,0 +1,55 @@ ++++ b/arch/arm/boot/dts/armada-38x-solidrun-microsom-emmc.dtsi +@@ -0,0 +1,62 @@ +/* -+ * Device Tree file for SolidRun Clearfog Pro revision A1 rev 2.0 (88F6828) ++ * Device Tree file for SolidRun Armada 38x Microsom add-on for eMMC + * + * Copyright (C) 2015 Russell King + * @@ -42,17 +42,17 @@ Signed-off-by: Marko Ratkaj + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * -+ * This file is distributed in the hope that it will be useful, ++ * This file is distributed in the hope that it will be useful + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * -+ * Or, alternatively, ++ * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without -+ * restriction, including without limitation the rights to use, ++ * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following @@ -61,20 +61,27 @@ Signed-off-by: Marko Ratkaj + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ -+#include "armada-388-clearfog.dts" -+ +/ { -+ model = "SolidRun Clearfog Pro A1"; -+ compatible = "solidrun,clearfog-pro-a1", -+ "solidrun,clearfog-a1", "marvell,armada388", -+ "marvell,armada385", "marvell,armada380"; ++ soc { ++ internal-regs { ++ sdhci@d8000 { ++ bus-width = <4>; ++ no-1-8-v; ++ non-removable; ++ pinctrl-0 = <µsom_sdhci_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ wp-inverted; ++ }; ++ }; ++ }; +}; diff --git a/target/linux/mvebu/patches-4.14/413-ARM-dts-armada388-clearfog-increase-speed-of-i2c0-to.patch b/target/linux/mvebu/patches-4.14/413-ARM-dts-armada388-clearfog-increase-speed-of-i2c0-to.patch new file mode 100644 index 000000000..4aedc82fe --- /dev/null +++ b/target/linux/mvebu/patches-4.14/413-ARM-dts-armada388-clearfog-increase-speed-of-i2c0-to.patch @@ -0,0 +1,42 @@ +From 6e127081e669cf163a818dc04d590790e4ed9527 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Tue, 29 Nov 2016 20:06:44 +0000 +Subject: ARM: dts: armada388-clearfog: increase speed of i2c0 to 400kHz + +All the devices on I2C0 support fast mode, so increase the bus speed +to match. The Armada 388 is known to have a timing issue when in +standard mode, which we believe causes the ficticious device at 0x64 +to appear. + +Signed-off-by: Russell King +--- + arch/arm/boot/dts/armada-388-clearfog.dtsi | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +--- a/arch/arm/boot/dts/armada-388-clearfog.dtsi ++++ b/arch/arm/boot/dts/armada-388-clearfog.dtsi +@@ -143,8 +143,7 @@ + }; + + &i2c0 { +- /* Is there anything on this? */ +- clock-frequency = <100000>; ++ clock-frequency = <400000>; + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; + status = "okay"; +@@ -239,13 +238,11 @@ + }; + }; + +- /* The MCP3021 is 100kHz clock only */ ++ /* The MCP3021 supports standard and fast modes */ + mikrobus_adc: mcp3021@4c { + compatible = "microchip,mcp3021"; + reg = <0x4c>; + }; +- +- /* Also something at 0x64 */ + }; + + &i2c1 { diff --git a/target/linux/mvebu/patches-4.14/414-ARM-dts-armada388-clearfog-add-SFP-module-support.patch b/target/linux/mvebu/patches-4.14/414-ARM-dts-armada388-clearfog-add-SFP-module-support.patch new file mode 100644 index 000000000..52ddcb606 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/414-ARM-dts-armada388-clearfog-add-SFP-module-support.patch @@ -0,0 +1,81 @@ +From 74fa68669c88f73bceff523cb764297b7d1e132b Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Tue, 29 Nov 2016 10:13:44 +0000 +Subject: ARM: dts: armada388-clearfog: add SFP module support + +Add SFP module support for Clearfog using the SFP phylink support. + +Signed-off-by: Russell King +--- + arch/arm/boot/dts/armada-388-clearfog.dtsi | 44 ++++++++---------------------- + 1 file changed, 11 insertions(+), 33 deletions(-) + +--- a/arch/arm/boot/dts/armada-388-clearfog.dtsi ++++ b/arch/arm/boot/dts/armada-388-clearfog.dtsi +@@ -117,6 +117,15 @@ + }; + }; + }; ++ ++ sfp: sfp { ++ compatible = "sff,sfp"; ++ i2c-bus = <&i2c1>; ++ los-gpio = <&expander0 12 GPIO_ACTIVE_HIGH>; ++ mod-def0-gpio = <&expander0 15 GPIO_ACTIVE_LOW>; ++ tx-disable-gpio = <&expander0 14 GPIO_ACTIVE_HIGH>; ++ tx-fault-gpio = <&expander0 13 GPIO_ACTIVE_HIGH>; ++ }; + }; + + ð1 { +@@ -133,13 +142,10 @@ + bm,pool-long = <3>; + bm,pool-short = <1>; + buffer-manager = <&bm>; ++ managed = "in-band-status"; + phy-mode = "sgmii"; ++ sfp = <&sfp>; + status = "okay"; +- +- fixed-link { +- speed = <1000>; +- full-duplex; +- }; + }; + + &i2c0 { +@@ -208,34 +214,6 @@ + output-low; + line-name = "m.2 devslp"; + }; +- sfp_los { +- /* SFP loss of signal */ +- gpio-hog; +- gpios = <12 GPIO_ACTIVE_HIGH>; +- input; +- line-name = "sfp-los"; +- }; +- sfp_tx_fault { +- /* SFP laser fault */ +- gpio-hog; +- gpios = <13 GPIO_ACTIVE_HIGH>; +- input; +- line-name = "sfp-tx-fault"; +- }; +- sfp_tx_disable { +- /* SFP transmit disable */ +- gpio-hog; +- gpios = <14 GPIO_ACTIVE_HIGH>; +- output-low; +- line-name = "sfp-tx-disable"; +- }; +- sfp_mod_def0 { +- /* SFP module present */ +- gpio-hog; +- gpios = <15 GPIO_ACTIVE_LOW>; +- input; +- line-name = "sfp-mod-def0"; +- }; + }; + + /* The MCP3021 supports standard and fast modes */ diff --git a/target/linux/mvebu/patches-4.14/415-ARM-dts-armada388-clearfog-document-MPP-usage.patch b/target/linux/mvebu/patches-4.14/415-ARM-dts-armada388-clearfog-document-MPP-usage.patch new file mode 100644 index 000000000..0e24d08c8 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/415-ARM-dts-armada388-clearfog-document-MPP-usage.patch @@ -0,0 +1,124 @@ +From 09a0122c74ec076e08512f1b00b7ccb8a450282f Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Tue, 29 Nov 2016 10:15:43 +0000 +Subject: ARM: dts: armada388-clearfog: document MPP usage + +Signed-off-by: Russell King +--- + arch/arm/boot/dts/armada-388-clearfog-base.dts | 51 ++++++++++++++++++++++++++ + arch/arm/boot/dts/armada-388-clearfog.dts | 50 +++++++++++++++++++++++++ + 2 files changed, 101 insertions(+) + +--- a/arch/arm/boot/dts/armada-388-clearfog-base.dts ++++ b/arch/arm/boot/dts/armada-388-clearfog-base.dts +@@ -108,3 +108,54 @@ + marvell,function = "gpio"; + }; + }; ++ ++/* ++MPP ++18: pu gpio pca9655 int ++19: gpio phy reset ++20: pu gpio sd0 detect ++21: sd0:cmd ++22: pd gpio mikro int ++23: ++ ++24: ua1:rxd mikro rx ++25: ua1:txd mikro tx ++26: pu i2c1:sck ++27: pu i2c1:sda ++28: sd0:clk ++29: pd gpio mikro rst ++30: ++31: ++ ++32: ++33: ++34: ++35: ++36: ++37: sd0:d3 ++38: sd0:d0 ++39: sd0:d1 ++ ++40: sd0:d2 ++41: ++42: ++43: spi1:cs2 mikro cs ++44: gpio rear button sw3 ++45: ref:clk_out0 phy#0 clock ++46: ref:clk_out1 phy#1 clock ++47: ++ ++48: gpio J18 spare gpio ++49: gpio U10 I2C_IRQ(GNSS) ++50: gpio board id? ++51: ++52: ++53: ++54: gpio mikro pwm ++55: ++ ++56: pu spi1:mosi mikro mosi ++57: pd spi1:sck mikro sck ++58: spi1:miso mikro miso ++59: ++*/ +--- a/arch/arm/boot/dts/armada-388-clearfog.dts ++++ b/arch/arm/boot/dts/armada-388-clearfog.dts +@@ -290,3 +290,53 @@ + */ + pinctrl-0 = <&spi1_pins &clearfog_spi1_cs_pins &mikro_spi_pins>; + }; ++/* +++#define A38x_CUSTOMER_BOARD_1_MPP16_23 0x00400011 ++MPP18: gpio ? (pca9655 int?) ++MPP19: gpio ? (clkreq?) ++MPP20: gpio ? (sd0 detect) ++MPP21: sd0:cmd x sd0 ++MPP22: gpio x mikro int ++MPP23: gpio x switch irq +++#define A38x_CUSTOMER_BOARD_1_MPP24_31 0x22043333 ++MPP24: ua1:rxd x mikro rx ++MPP25: ua1:txd x mikro tx ++MPP26: i2c1:sck x mikro sck ++MPP27: i2c1:sda x mikro sda ++MPP28: sd0:clk x sd0 ++MPP29: gpio x mikro rst ++MPP30: ge1:txd2 ? (config) ++MPP31: ge1:txd3 ? (config) +++#define A38x_CUSTOMER_BOARD_1_MPP32_39 0x44400002 ++MPP32: ge1:txctl ? (unused) ++MPP33: gpio ? (pic_com0) ++MPP34: gpio x rear button (pic_com1) ++MPP35: gpio ? (pic_com2) ++MPP36: gpio ? (unused) ++MPP37: sd0:d3 x sd0 ++MPP38: sd0:d0 x sd0 ++MPP39: sd0:d1 x sd0 +++#define A38x_CUSTOMER_BOARD_1_MPP40_47 0x41144004 ++MPP40: sd0:d2 x sd0 ++MPP41: gpio x switch reset ++MPP42: gpio ? sw1-1 ++MPP43: spi1:cs2 x mikro cs ++MPP44: sata3:prsnt ? (unused) ++MPP45: ref:clk_out0 ? ++MPP46: ref:clk_out1 x switch clk ++MPP47: 4 ? (unused) +++#define A38x_CUSTOMER_BOARD_1_MPP48_55 0x40333333 ++MPP48: tdm:pclk ++MPP49: tdm:fsync ++MPP50: tdm:drx ++MPP51: tdm:dtx ++MPP52: tdm:int ++MPP53: tdm:rst ++MPP54: gpio ? (pwm) ++MPP55: spi1:cs1 x slic +++#define A38x_CUSTOMER_BOARD_1_MPP56_63 0x00004444 ++MPP56: spi1:mosi x mikro mosi ++MPP57: spi1:sck x mikro sck ++MPP58: spi1:miso x mikro miso ++MPP59: spi1:cs0 x w25q32 ++*/ diff --git a/target/linux/mvebu/patches-4.14/420-rtc-trimming-support.patch b/target/linux/mvebu/patches-4.14/420-rtc-trimming-support.patch new file mode 100644 index 000000000..2974a6976 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/420-rtc-trimming-support.patch @@ -0,0 +1,143 @@ +commit f94ffbc2c2a4128c4412bb483d0807722dfb682b +Author: Russell King +Date: Fri Sep 29 11:23:31 2017 +0100 + + rtc: armada38x: add support for trimming the RTC + + Add support for trimming the RTC using the offset mechanism. This RTC + supports two modes: low update mode and high update mode. Low update + mode has finer precision than high update mode, so we use the low mode + where possible. + + Signed-off-by: Russell King + Signed-off-by: Alexandre Belloni + +--- a/drivers/rtc/rtc-armada38x.c ++++ b/drivers/rtc/rtc-armada38x.c +@@ -28,6 +28,8 @@ + #define RTC_IRQ_AL_EN BIT(0) + #define RTC_IRQ_FREQ_EN BIT(1) + #define RTC_IRQ_FREQ_1HZ BIT(2) ++#define RTC_CCR 0x18 ++#define RTC_CCR_MODE BIT(15) + + #define RTC_TIME 0xC + #define RTC_ALARM1 0x10 +@@ -343,18 +345,117 @@ static irqreturn_t armada38x_rtc_alarm_i + return IRQ_HANDLED; + } + ++/* ++ * The information given in the Armada 388 functional spec is complex. ++ * They give two different formulas for calculating the offset value, ++ * but when considering "Offset" as an 8-bit signed integer, they both ++ * reduce down to (we shall rename "Offset" as "val" here): ++ * ++ * val = (f_ideal / f_measured - 1) / resolution where f_ideal = 32768 ++ * ++ * Converting to time, f = 1/t: ++ * val = (t_measured / t_ideal - 1) / resolution where t_ideal = 1/32768 ++ * ++ * => t_measured / t_ideal = val * resolution + 1 ++ * ++ * "offset" in the RTC interface is defined as: ++ * t = t0 * (1 + offset * 1e-9) ++ * where t is the desired period, t0 is the measured period with a zero ++ * offset, which is t_measured above. With t0 = t_measured and t = t_ideal, ++ * offset = (t_ideal / t_measured - 1) / 1e-9 ++ * ++ * => t_ideal / t_measured = offset * 1e-9 + 1 ++ * ++ * so: ++ * ++ * offset * 1e-9 + 1 = 1 / (val * resolution + 1) ++ * ++ * We want "resolution" to be an integer, so resolution = R * 1e-9, giving ++ * offset = 1e18 / (val * R + 1e9) - 1e9 ++ * val = (1e18 / (offset + 1e9) - 1e9) / R ++ * with a common transformation: ++ * f(x) = 1e18 / (x + 1e9) - 1e9 ++ * offset = f(val * R) ++ * val = f(offset) / R ++ * ++ * Armada 38x supports two modes, fine mode (954ppb) and coarse mode (3815ppb). ++ */ ++static long armada38x_ppb_convert(long ppb) ++{ ++ long div = ppb + 1000000000L; ++ ++ return div_s64(1000000000000000000LL + div / 2, div) - 1000000000L; ++} ++ ++static int armada38x_rtc_read_offset(struct device *dev, long *offset) ++{ ++ struct armada38x_rtc *rtc = dev_get_drvdata(dev); ++ unsigned long ccr, flags; ++ long ppb_cor; ++ ++ spin_lock_irqsave(&rtc->lock, flags); ++ ccr = rtc->data->read_rtc_reg(rtc, RTC_CCR); ++ spin_unlock_irqrestore(&rtc->lock, flags); ++ ++ ppb_cor = (ccr & RTC_CCR_MODE ? 3815 : 954) * (s8)ccr; ++ /* ppb_cor + 1000000000L can never be zero */ ++ *offset = armada38x_ppb_convert(ppb_cor); ++ ++ return 0; ++} ++ ++static int armada38x_rtc_set_offset(struct device *dev, long offset) ++{ ++ struct armada38x_rtc *rtc = dev_get_drvdata(dev); ++ unsigned long ccr = 0; ++ long ppb_cor, off; ++ ++ /* ++ * The maximum ppb_cor is -128 * 3815 .. 127 * 3815, but we ++ * need to clamp the input. This equates to -484270 .. 488558. ++ * Not only is this to stop out of range "off" but also to ++ * avoid the division by zero in armada38x_ppb_convert(). ++ */ ++ offset = clamp(offset, -484270L, 488558L); ++ ++ ppb_cor = armada38x_ppb_convert(offset); ++ ++ /* ++ * Use low update mode where possible, which gives a better ++ * resolution of correction. ++ */ ++ off = DIV_ROUND_CLOSEST(ppb_cor, 954); ++ if (off > 127 || off < -128) { ++ ccr = RTC_CCR_MODE; ++ off = DIV_ROUND_CLOSEST(ppb_cor, 3815); ++ } ++ ++ /* ++ * Armada 388 requires a bit pattern in bits 14..8 depending on ++ * the sign bit: { 0, ~S, S, S, S, S, S } ++ */ ++ ccr |= (off & 0x3fff) ^ 0x2000; ++ rtc_delayed_write(ccr, rtc, RTC_CCR); ++ ++ return 0; ++} ++ + static const struct rtc_class_ops armada38x_rtc_ops = { + .read_time = armada38x_rtc_read_time, + .set_time = armada38x_rtc_set_time, + .read_alarm = armada38x_rtc_read_alarm, + .set_alarm = armada38x_rtc_set_alarm, + .alarm_irq_enable = armada38x_rtc_alarm_irq_enable, ++ .read_offset = armada38x_rtc_read_offset, ++ .set_offset = armada38x_rtc_set_offset, + }; + + static const struct rtc_class_ops armada38x_rtc_ops_noirq = { + .read_time = armada38x_rtc_read_time, + .set_time = armada38x_rtc_set_time, + .read_alarm = armada38x_rtc_read_alarm, ++ .read_offset = armada38x_rtc_read_offset, ++ .set_offset = armada38x_rtc_set_offset, + }; + + static const struct armada38x_rtc_data armada38x_data = { diff --git a/target/linux/mvebu/patches-4.14/421-rtc-initialize.patch b/target/linux/mvebu/patches-4.14/421-rtc-initialize.patch new file mode 100644 index 000000000..47a5acc70 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/421-rtc-initialize.patch @@ -0,0 +1,74 @@ +Some boards like the Turris Omnia have an RTC chip that does not get +initialized. Initializing the RTC at the driver level helps get rid of +bootloader hacks that write special register values. + +--- a/drivers/rtc/rtc-armada38x.c ++++ b/drivers/rtc/rtc-armada38x.c +@@ -30,6 +30,9 @@ + #define RTC_IRQ_FREQ_1HZ BIT(2) + #define RTC_CCR 0x18 + #define RTC_CCR_MODE BIT(15) ++#define RTC_CCR_NORMAL_PPB 0x2000 ++#define RTC_TEST_CONF 0x1c ++#define RTC_TEST_CONF_MASK 0xff + + #define RTC_TIME 0xC + #define RTC_ALARM1 0x10 +@@ -91,6 +94,7 @@ struct armada38x_rtc_data { + void (*clear_isr)(struct armada38x_rtc *rtc); + void (*unmask_interrupt)(struct armada38x_rtc *rtc); + u32 alarm; ++ void (*init_rtc)(struct armada38x_rtc *rtc); + }; + + /* +@@ -202,6 +206,23 @@ static void armada38x_unmask_interrupt(s + writel(val | SOC_RTC_ALARM1_MASK, rtc->regs_soc + SOC_RTC_INTERRUPT); + } + ++static void armada38x_rtc_init(struct armada38x_rtc *rtc) ++{ ++ u32 reg; ++ ++ /* Test RTC test configuration register bits [7:0] */ ++ reg = readl(rtc->regs + RTC_TEST_CONF); ++ /* If bits [7:0] are non-zero, assume RTC was uninitialized */ ++ if (reg & RTC_TEST_CONF_MASK) { ++ rtc_delayed_write(0, rtc, RTC_TEST_CONF); ++ rtc_delayed_write(0, rtc, RTC_TIME); ++ rtc_delayed_write((RTC_STATUS_ALARM1 | RTC_STATUS_ALARM2), ++ rtc, RTC_STATUS); ++ rtc_delayed_write(RTC_CCR_NORMAL_PPB, rtc, RTC_CCR); ++ } ++ return; ++} ++ + static void armada8k_clear_isr(struct armada38x_rtc *rtc) + { + writel(RTC_8K_ALARM2, rtc->regs_soc + RTC_8K_ISR); +@@ -464,6 +485,7 @@ static const struct armada38x_rtc_data a + .clear_isr = armada38x_clear_isr, + .unmask_interrupt = armada38x_unmask_interrupt, + .alarm = ALARM1, ++ .init_rtc = armada38x_rtc_init, + }; + + static const struct armada38x_rtc_data armada8k_data = { +@@ -558,6 +580,17 @@ static __init int armada38x_rtc_probe(st + dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); + return ret; + } ++ ++ /* ++ * Try to detect if RTC is in uninitialized state. ++ * It is not definitive to know if the RTC is in an uninialized state or not, ++ * but the following call will read some bits in the RTC unit and guess if ++ * if it's in that state, and accordingly set it to sane default values. ++ */ ++ if (rtc->data->init_rtc) { ++ rtc->data->init_rtc(rtc); ++ } ++ + return 0; + } + diff --git a/target/linux/mvebu/patches-4.14/423-ARM-dts-armada-385-linksys-Disable-internal-RTC.patch b/target/linux/mvebu/patches-4.14/423-ARM-dts-armada-385-linksys-Disable-internal-RTC.patch new file mode 100644 index 000000000..040d6590b --- /dev/null +++ b/target/linux/mvebu/patches-4.14/423-ARM-dts-armada-385-linksys-Disable-internal-RTC.patch @@ -0,0 +1,28 @@ +From e1cac198fea08c31ec204bed84c279ab05d20389 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sat, 17 Mar 2018 15:22:25 +0100 +Subject: ARM: dts: armada-385-linksys: Disable internal RTC + +The internal RTC does not work correctly on these Linksys boards based +on Marvell SoCs. For me it only shows Wed Dec 31 23:59:59 1969 and for +others it is off by 3 minutes in 10 minutes running, this was reported +by multiple users. On the Linksys Mamba device the device tree comment +says that no crystal is connected to the internal RTC, this is probably +also true for the other devices. + +Signed-off-by: Hauke Mehrtens +--- + arch/arm/boot/dts/armada-385-linksys.dtsi | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/arch/arm/boot/dts/armada-385-linksys.dtsi ++++ b/arch/arm/boot/dts/armada-385-linksys.dtsi +@@ -304,3 +304,8 @@ + status = "okay"; + usb-phy = <&usb3_1_phy>; + }; ++ ++&rtc { ++ /* No crystal connected to the internal RTC */ ++ status = "disabled"; ++}; diff --git a/target/linux/mvebu/patches-4.14/450-reprobe_sfp_phy.patch b/target/linux/mvebu/patches-4.14/450-reprobe_sfp_phy.patch new file mode 100644 index 000000000..e9a3d695d --- /dev/null +++ b/target/linux/mvebu/patches-4.14/450-reprobe_sfp_phy.patch @@ -0,0 +1,94 @@ +From 28baa5e2635285b178326b301f534ed95c65dd01 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Thu, 29 Sep 2016 11:44:39 +0200 +Subject: [PATCH] sfp: retry phy probe if unsuccessful + +Some phys seem to take longer than 50 ms to come out of reset, so retry +until we find a phy. + +Signed-off-by: Jonas Gorski +--- + drivers/net/phy/sfp.c | 38 +++++++++++++++++++++++++------------- + 1 file changed, 25 insertions(+), 13 deletions(-) + +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -488,7 +488,7 @@ static void sfp_sm_phy_detach(struct sfp + sfp->mod_phy = NULL; + } + +-static void sfp_sm_probe_phy(struct sfp *sfp) ++static int sfp_sm_probe_phy(struct sfp *sfp) + { + struct phy_device *phy; + int err; +@@ -498,11 +498,11 @@ static void sfp_sm_probe_phy(struct sfp + phy = mdiobus_scan(sfp->i2c_mii, SFP_PHY_ADDR); + if (phy == ERR_PTR(-ENODEV)) { + dev_info(sfp->dev, "no PHY detected\n"); +- return; ++ return -EAGAIN; + } + if (IS_ERR(phy)) { + dev_err(sfp->dev, "mdiobus scan returned %ld\n", PTR_ERR(phy)); +- return; ++ return PTR_ERR(phy); + } + + err = sfp_add_phy(sfp->sfp_bus, phy); +@@ -510,11 +510,13 @@ static void sfp_sm_probe_phy(struct sfp + phy_device_remove(phy); + phy_device_free(phy); + dev_err(sfp->dev, "sfp_add_phy failed: %d\n", err); +- return; ++ return err; + } + + sfp->mod_phy = phy; + phy_start(phy); ++ ++ return 0; + } + + static void sfp_sm_link_up(struct sfp *sfp) +@@ -560,14 +562,9 @@ static void sfp_sm_fault(struct sfp *sfp + + static void sfp_sm_mod_init(struct sfp *sfp) + { +- sfp_module_tx_enable(sfp); ++ int ret = 0; + +- /* Wait t_init before indicating that the link is up, provided the +- * current state indicates no TX_FAULT. If TX_FAULT clears before +- * this time, that's fine too. +- */ +- sfp_sm_next(sfp, SFP_S_INIT, T_INIT_JIFFIES); +- sfp->sm_retries = 5; ++ sfp_module_tx_enable(sfp); + + /* Setting the serdes link mode is guesswork: there's no + * field in the EEPROM which indicates what mode should +@@ -581,7 +578,22 @@ static void sfp_sm_mod_init(struct sfp * + if (sfp->id.base.e1000_base_t || + sfp->id.base.e100_base_lx || + sfp->id.base.e100_base_fx) +- sfp_sm_probe_phy(sfp); ++ ret = sfp_sm_probe_phy(sfp); ++ ++ if (!ret) { ++ /* Wait t_init before indicating that the link is up, provided ++ * the current state indicates no TX_FAULT. If TX_FAULT clears ++ * this time, that's fine too. ++ */ ++ sfp_sm_next(sfp, SFP_S_INIT, T_INIT_JIFFIES); ++ sfp->sm_retries = 5; ++ return; ++ } ++ ++ if (ret == -EAGAIN) ++ sfp_sm_set_timer(sfp, T_PROBE_RETRY); ++ else ++ sfp_sm_next(sfp, SFP_S_TX_DISABLE, 0); + } + + static int sfp_sm_mod_probe(struct sfp *sfp) diff --git a/target/linux/mvebu/patches-4.14/500-clk-mvebu-armada-37xx-periph-cosmetic-changes.patch b/target/linux/mvebu/patches-4.14/500-clk-mvebu-armada-37xx-periph-cosmetic-changes.patch new file mode 100644 index 000000000..7343e01d1 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/500-clk-mvebu-armada-37xx-periph-cosmetic-changes.patch @@ -0,0 +1,78 @@ +From adf4e289dd7f801c3fe12e0e6b491e11e548cd3d Mon Sep 17 00:00:00 2001 +From: Gregory CLEMENT +Date: Thu, 30 Nov 2017 14:40:27 +0100 +Subject: clk: mvebu: armada-37xx-periph: cosmetic changes + +This patches fixes few cosmetic issues such as alignment, blank lines +and required space. + +Signed-off-by: Gregory CLEMENT +Signed-off-by: Stephen Boyd +--- + drivers/clk/mvebu/armada-37xx-periph.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +--- a/drivers/clk/mvebu/armada-37xx-periph.c ++++ b/drivers/clk/mvebu/armada-37xx-periph.c +@@ -79,6 +79,7 @@ static const struct clk_div_table clk_ta + { .val = 1, .div = 4, }, + { .val = 0, .div = 0, }, /* last entry */ + }; ++ + static const struct clk_ops clk_double_div_ops; + + #define PERIPH_GATE(_name, _bit) \ +@@ -217,7 +218,7 @@ PERIPH_CLK_FULL(counter, 23, 20, DIV_SEL + PERIPH_CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19); + PERIPH_CLK_MUX_DIV(cpu, 22, DIV_SEL0, 28, clk_table6); + +-static struct clk_periph_data data_nb[] ={ ++static struct clk_periph_data data_nb[] = { + REF_CLK_FULL_DD(mmc), + REF_CLK_FULL_DD(sata_host), + REF_CLK_FULL_DD(sec_at), +@@ -281,7 +282,7 @@ static unsigned int get_div(void __iomem + } + + static unsigned long clk_double_div_recalc_rate(struct clk_hw *hw, +- unsigned long parent_rate) ++ unsigned long parent_rate) + { + struct clk_double_div *double_div = to_clk_double_div(hw); + unsigned int div; +@@ -303,6 +304,7 @@ static const struct of_device_id armada_ + .data = data_sb, }, + { } + }; ++ + static int armada_3700_add_composite_clk(const struct clk_periph_data *data, + void __iomem *reg, spinlock_t *lock, + struct device *dev, struct clk_hw **hw) +@@ -355,9 +357,9 @@ static int armada_3700_add_composite_clk + } + + *hw = clk_hw_register_composite(dev, data->name, data->parent_names, +- data->num_parents, mux_hw, +- mux_ops, rate_hw, rate_ops, +- gate_hw, gate_ops, CLK_IGNORE_UNUSED); ++ data->num_parents, mux_hw, ++ mux_ops, rate_hw, rate_ops, ++ gate_hw, gate_ops, CLK_IGNORE_UNUSED); + + if (IS_ERR(*hw)) + return PTR_ERR(*hw); +@@ -406,12 +408,11 @@ static int armada_3700_periph_clock_prob + if (armada_3700_add_composite_clk(&data[i], reg, + &driver_data->lock, dev, hw)) + dev_err(dev, "Can't register periph clock %s\n", +- data[i].name); +- ++ data[i].name); + } + + ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, +- driver_data->hw_data); ++ driver_data->hw_data); + if (ret) { + for (i = 0; i < num_periph; i++) + clk_hw_unregister(driver_data->hw_data->hws[i]); diff --git a/target/linux/mvebu/patches-4.14/501-clk-mvebu-armada-37xx-periph-prepare-cpu-clk-to-be-u.patch b/target/linux/mvebu/patches-4.14/501-clk-mvebu-armada-37xx-periph-prepare-cpu-clk-to-be-u.patch new file mode 100644 index 000000000..f9dec9f2e --- /dev/null +++ b/target/linux/mvebu/patches-4.14/501-clk-mvebu-armada-37xx-periph-prepare-cpu-clk-to-be-u.patch @@ -0,0 +1,178 @@ +From 9818a7a4fd10f72537cdf2a5ec3402f2c245ea24 Mon Sep 17 00:00:00 2001 +From: Gregory CLEMENT +Date: Thu, 30 Nov 2017 14:40:28 +0100 +Subject: clk: mvebu: armada-37xx-periph: prepare cpu clk to be + used with DVFS + +When DVFS will be enabled then the cpu clk will use a different set of +register at run time. That means that we won't be able to use the common +callback and need to use our own ones. + +This patch prepares this change by switching on our own set of callbacks +without modifying the behavior of the clocks. + +Signed-off-by: Gregory CLEMENT +Signed-off-by: Stephen Boyd +--- + drivers/clk/mvebu/armada-37xx-periph.c | 82 ++++++++++++++++++++++++++++++---- + 1 file changed, 73 insertions(+), 9 deletions(-) + +--- a/drivers/clk/mvebu/armada-37xx-periph.c ++++ b/drivers/clk/mvebu/armada-37xx-periph.c +@@ -46,7 +46,17 @@ struct clk_double_div { + u8 shift2; + }; + ++struct clk_pm_cpu { ++ struct clk_hw hw; ++ void __iomem *reg_mux; ++ u8 shift_mux; ++ u32 mask_mux; ++ void __iomem *reg_div; ++ u8 shift_div; ++}; ++ + #define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw) ++#define to_clk_pm_cpu(_hw) container_of(_hw, struct clk_pm_cpu, hw) + + struct clk_periph_data { + const char *name; +@@ -55,6 +65,7 @@ struct clk_periph_data { + struct clk_hw *mux_hw; + struct clk_hw *rate_hw; + struct clk_hw *gate_hw; ++ struct clk_hw *muxrate_hw; + bool is_double_div; + }; + +@@ -81,6 +92,7 @@ static const struct clk_div_table clk_ta + }; + + static const struct clk_ops clk_double_div_ops; ++static const struct clk_ops clk_pm_cpu_ops; + + #define PERIPH_GATE(_name, _bit) \ + struct clk_gate gate_##_name = { \ +@@ -122,6 +134,18 @@ struct clk_divider rate_##_name = { \ + } \ + }; + ++#define PERIPH_PM_CPU(_name, _shift1, _reg, _shift2) \ ++struct clk_pm_cpu muxrate_##_name = { \ ++ .reg_mux = (void *)TBG_SEL, \ ++ .mask_mux = 3, \ ++ .shift_mux = _shift1, \ ++ .reg_div = (void *)_reg, \ ++ .shift_div = _shift2, \ ++ .hw.init = &(struct clk_init_data){ \ ++ .ops = &clk_pm_cpu_ops, \ ++ } \ ++}; ++ + #define PERIPH_CLK_FULL_DD(_name, _bit, _shift, _reg1, _reg2, _shift1, _shift2)\ + static PERIPH_GATE(_name, _bit); \ + static PERIPH_MUX(_name, _shift); \ +@@ -136,10 +160,6 @@ static PERIPH_DIV(_name, _reg, _shift1, + static PERIPH_GATE(_name, _bit); \ + static PERIPH_DIV(_name, _reg, _shift, _table); + +-#define PERIPH_CLK_MUX_DIV(_name, _shift, _reg, _shift_div, _table) \ +-static PERIPH_MUX(_name, _shift); \ +-static PERIPH_DIV(_name, _reg, _shift_div, _table); +- + #define PERIPH_CLK_MUX_DD(_name, _shift, _reg1, _reg2, _shift1, _shift2)\ + static PERIPH_MUX(_name, _shift); \ + static PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2); +@@ -180,13 +200,12 @@ static PERIPH_DOUBLEDIV(_name, _reg1, _r + .rate_hw = &rate_##_name.hw, \ + } + +-#define REF_CLK_MUX_DIV(_name) \ ++#define REF_CLK_PM_CPU(_name) \ + { .name = #_name, \ + .parent_names = (const char *[]){ "TBG-A-P", \ + "TBG-B-P", "TBG-A-S", "TBG-B-S"}, \ + .num_parents = 4, \ +- .mux_hw = &mux_##_name.hw, \ +- .rate_hw = &rate_##_name.hw, \ ++ .muxrate_hw = &muxrate_##_name.hw, \ + } + + #define REF_CLK_MUX_DD(_name) \ +@@ -216,7 +235,7 @@ PERIPH_CLK_FULL_DD(ddr_fclk, 21, 16, DIV + PERIPH_CLK_FULL(trace, 22, 18, DIV_SEL0, 20, clk_table6); + PERIPH_CLK_FULL(counter, 23, 20, DIV_SEL0, 23, clk_table6); + PERIPH_CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19); +-PERIPH_CLK_MUX_DIV(cpu, 22, DIV_SEL0, 28, clk_table6); ++static PERIPH_PM_CPU(cpu, 22, DIV_SEL0, 28); + + static struct clk_periph_data data_nb[] = { + REF_CLK_FULL_DD(mmc), +@@ -235,7 +254,7 @@ static struct clk_periph_data data_nb[] + REF_CLK_FULL(trace), + REF_CLK_FULL(counter), + REF_CLK_FULL_DD(eip97), +- REF_CLK_MUX_DIV(cpu), ++ REF_CLK_PM_CPU(cpu), + { }, + }; + +@@ -297,6 +316,37 @@ static const struct clk_ops clk_double_d + .recalc_rate = clk_double_div_recalc_rate, + }; + ++static u8 clk_pm_cpu_get_parent(struct clk_hw *hw) ++{ ++ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); ++ int num_parents = clk_hw_get_num_parents(hw); ++ u32 val; ++ ++ val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux; ++ val &= pm_cpu->mask_mux; ++ ++ if (val >= num_parents) ++ return -EINVAL; ++ ++ return val; ++} ++ ++static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); ++ unsigned int div; ++ ++ div = get_div(pm_cpu->reg_div, pm_cpu->shift_div); ++ ++ return DIV_ROUND_UP_ULL((u64)parent_rate, div); ++} ++ ++static const struct clk_ops clk_pm_cpu_ops = { ++ .get_parent = clk_pm_cpu_get_parent, ++ .recalc_rate = clk_pm_cpu_recalc_rate, ++}; ++ + static const struct of_device_id armada_3700_periph_clock_of_match[] = { + { .compatible = "marvell,armada-3700-periph-clock-nb", + .data = data_nb, }, +@@ -356,6 +406,20 @@ static int armada_3700_add_composite_clk + } + } + ++ if (data->muxrate_hw) { ++ struct clk_pm_cpu *pmcpu_clk; ++ struct clk_hw *muxrate_hw = data->muxrate_hw; ++ ++ pmcpu_clk = to_clk_pm_cpu(muxrate_hw); ++ pmcpu_clk->reg_mux = reg + (u64)pmcpu_clk->reg_mux; ++ pmcpu_clk->reg_div = reg + (u64)pmcpu_clk->reg_div; ++ ++ mux_hw = muxrate_hw; ++ rate_hw = muxrate_hw; ++ mux_ops = muxrate_hw->init->ops; ++ rate_ops = muxrate_hw->init->ops; ++ } ++ + *hw = clk_hw_register_composite(dev, data->name, data->parent_names, + data->num_parents, mux_hw, + mux_ops, rate_hw, rate_ops, diff --git a/target/linux/mvebu/patches-4.14/502-clk-mvebu-armada-37xx-periph-add-DVFS-support-for-cp.patch b/target/linux/mvebu/patches-4.14/502-clk-mvebu-armada-37xx-periph-add-DVFS-support-for-cp.patch new file mode 100644 index 000000000..2065e788a --- /dev/null +++ b/target/linux/mvebu/patches-4.14/502-clk-mvebu-armada-37xx-periph-add-DVFS-support-for-cp.patch @@ -0,0 +1,315 @@ +From 2089dc33ea0e3917465929d4020fbff3d6dbf7f4 Mon Sep 17 00:00:00 2001 +From: Gregory CLEMENT +Date: Thu, 30 Nov 2017 14:40:29 +0100 +Subject: clk: mvebu: armada-37xx-periph: add DVFS support for cpu clocks + +When DVFS is enabled the CPU clock setting is done using an other set of +registers. + +These Power Management registers are exposed through a syscon as they +will also be used by other drivers such as the cpufreq. + +This patch add the possibility to modify the CPU frequency using the +associate load level matching the target frequency. Then all the +frequency switch is handle by the hardware. + +Signed-off-by: Gregory CLEMENT +[sboyd@codeaurora.org: Grow a local variable for regmap pointer +to keep lines shorter] +Signed-off-by: Stephen Boyd +--- + drivers/clk/mvebu/armada-37xx-periph.c | 221 ++++++++++++++++++++++++++++++++- + 1 file changed, 217 insertions(+), 4 deletions(-) + +--- a/drivers/clk/mvebu/armada-37xx-periph.c ++++ b/drivers/clk/mvebu/armada-37xx-periph.c +@@ -21,9 +21,11 @@ + */ + + #include ++#include + #include + #include + #include ++#include + #include + + #define TBG_SEL 0x0 +@@ -33,6 +35,26 @@ + #define CLK_SEL 0x10 + #define CLK_DIS 0x14 + ++#define LOAD_LEVEL_NR 4 ++ ++#define ARMADA_37XX_NB_L0L1 0x18 ++#define ARMADA_37XX_NB_L2L3 0x1C ++#define ARMADA_37XX_NB_TBG_DIV_OFF 13 ++#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7 ++#define ARMADA_37XX_NB_CLK_SEL_OFF 11 ++#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1 ++#define ARMADA_37XX_NB_TBG_SEL_OFF 9 ++#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3 ++#define ARMADA_37XX_NB_CONFIG_SHIFT 16 ++#define ARMADA_37XX_NB_DYN_MOD 0x24 ++#define ARMADA_37XX_NB_DFS_EN 31 ++#define ARMADA_37XX_NB_CPU_LOAD 0x30 ++#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3 ++#define ARMADA_37XX_DVFS_LOAD_0 0 ++#define ARMADA_37XX_DVFS_LOAD_1 1 ++#define ARMADA_37XX_DVFS_LOAD_2 2 ++#define ARMADA_37XX_DVFS_LOAD_3 3 ++ + struct clk_periph_driver_data { + struct clk_hw_onecell_data *hw_data; + spinlock_t lock; +@@ -53,6 +75,7 @@ struct clk_pm_cpu { + u32 mask_mux; + void __iomem *reg_div; + u8 shift_div; ++ struct regmap *nb_pm_base; + }; + + #define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw) +@@ -316,14 +339,94 @@ static const struct clk_ops clk_double_d + .recalc_rate = clk_double_div_recalc_rate, + }; + ++static void armada_3700_pm_dvfs_update_regs(unsigned int load_level, ++ unsigned int *reg, ++ unsigned int *offset) ++{ ++ if (load_level <= ARMADA_37XX_DVFS_LOAD_1) ++ *reg = ARMADA_37XX_NB_L0L1; ++ else ++ *reg = ARMADA_37XX_NB_L2L3; ++ ++ if (load_level == ARMADA_37XX_DVFS_LOAD_0 || ++ load_level == ARMADA_37XX_DVFS_LOAD_2) ++ *offset += ARMADA_37XX_NB_CONFIG_SHIFT; ++} ++ ++static bool armada_3700_pm_dvfs_is_enabled(struct regmap *base) ++{ ++ unsigned int val, reg = ARMADA_37XX_NB_DYN_MOD; ++ ++ if (IS_ERR(base)) ++ return false; ++ ++ regmap_read(base, reg, &val); ++ ++ return !!(val & BIT(ARMADA_37XX_NB_DFS_EN)); ++} ++ ++static unsigned int armada_3700_pm_dvfs_get_cpu_div(struct regmap *base) ++{ ++ unsigned int reg = ARMADA_37XX_NB_CPU_LOAD; ++ unsigned int offset = ARMADA_37XX_NB_TBG_DIV_OFF; ++ unsigned int load_level, div; ++ ++ /* ++ * This function is always called after the function ++ * armada_3700_pm_dvfs_is_enabled, so no need to check again ++ * if the base is valid. ++ */ ++ regmap_read(base, reg, &load_level); ++ ++ /* ++ * The register and the offset inside this register accessed to ++ * read the current divider depend on the load level ++ */ ++ load_level &= ARMADA_37XX_NB_CPU_LOAD_MASK; ++ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset); ++ ++ regmap_read(base, reg, &div); ++ ++ return (div >> offset) & ARMADA_37XX_NB_TBG_DIV_MASK; ++} ++ ++static unsigned int armada_3700_pm_dvfs_get_cpu_parent(struct regmap *base) ++{ ++ unsigned int reg = ARMADA_37XX_NB_CPU_LOAD; ++ unsigned int offset = ARMADA_37XX_NB_TBG_SEL_OFF; ++ unsigned int load_level, sel; ++ ++ /* ++ * This function is always called after the function ++ * armada_3700_pm_dvfs_is_enabled, so no need to check again ++ * if the base is valid ++ */ ++ regmap_read(base, reg, &load_level); ++ ++ /* ++ * The register and the offset inside this register accessed to ++ * read the current divider depend on the load level ++ */ ++ load_level &= ARMADA_37XX_NB_CPU_LOAD_MASK; ++ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset); ++ ++ regmap_read(base, reg, &sel); ++ ++ return (sel >> offset) & ARMADA_37XX_NB_TBG_SEL_MASK; ++} ++ + static u8 clk_pm_cpu_get_parent(struct clk_hw *hw) + { + struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); + int num_parents = clk_hw_get_num_parents(hw); + u32 val; + +- val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux; +- val &= pm_cpu->mask_mux; ++ if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base)) { ++ val = armada_3700_pm_dvfs_get_cpu_parent(pm_cpu->nb_pm_base); ++ } else { ++ val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux; ++ val &= pm_cpu->mask_mux; ++ } + + if (val >= num_parents) + return -EINVAL; +@@ -331,19 +434,124 @@ static u8 clk_pm_cpu_get_parent(struct c + return val; + } + ++static int clk_pm_cpu_set_parent(struct clk_hw *hw, u8 index) ++{ ++ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); ++ struct regmap *base = pm_cpu->nb_pm_base; ++ int load_level; ++ ++ /* ++ * We set the clock parent only if the DVFS is available but ++ * not enabled. ++ */ ++ if (IS_ERR(base) || armada_3700_pm_dvfs_is_enabled(base)) ++ return -EINVAL; ++ ++ /* Set the parent clock for all the load level */ ++ for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) { ++ unsigned int reg, mask, val, ++ offset = ARMADA_37XX_NB_TBG_SEL_OFF; ++ ++ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset); ++ ++ val = index << offset; ++ mask = ARMADA_37XX_NB_TBG_SEL_MASK << offset; ++ regmap_update_bits(base, reg, mask, val); ++ } ++ return 0; ++} ++ + static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { + struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); + unsigned int div; + +- div = get_div(pm_cpu->reg_div, pm_cpu->shift_div); +- ++ if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base)) ++ div = armada_3700_pm_dvfs_get_cpu_div(pm_cpu->nb_pm_base); ++ else ++ div = get_div(pm_cpu->reg_div, pm_cpu->shift_div); + return DIV_ROUND_UP_ULL((u64)parent_rate, div); + } + ++static long clk_pm_cpu_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); ++ struct regmap *base = pm_cpu->nb_pm_base; ++ unsigned int div = *parent_rate / rate; ++ unsigned int load_level; ++ /* only available when DVFS is enabled */ ++ if (!armada_3700_pm_dvfs_is_enabled(base)) ++ return -EINVAL; ++ ++ for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) { ++ unsigned int reg, val, offset = ARMADA_37XX_NB_TBG_DIV_OFF; ++ ++ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset); ++ ++ regmap_read(base, reg, &val); ++ ++ val >>= offset; ++ val &= ARMADA_37XX_NB_TBG_DIV_MASK; ++ if (val == div) ++ /* ++ * We found a load level matching the target ++ * divider, switch to this load level and ++ * return. ++ */ ++ return *parent_rate / div; ++ } ++ ++ /* We didn't find any valid divider */ ++ return -EINVAL; ++} ++ ++static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw); ++ struct regmap *base = pm_cpu->nb_pm_base; ++ unsigned int div = parent_rate / rate; ++ unsigned int load_level; ++ ++ /* only available when DVFS is enabled */ ++ if (!armada_3700_pm_dvfs_is_enabled(base)) ++ return -EINVAL; ++ ++ for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) { ++ unsigned int reg, mask, val, ++ offset = ARMADA_37XX_NB_TBG_DIV_OFF; ++ ++ armada_3700_pm_dvfs_update_regs(load_level, ®, &offset); ++ ++ regmap_read(base, reg, &val); ++ val >>= offset; ++ val &= ARMADA_37XX_NB_TBG_DIV_MASK; ++ ++ if (val == div) { ++ /* ++ * We found a load level matching the target ++ * divider, switch to this load level and ++ * return. ++ */ ++ reg = ARMADA_37XX_NB_CPU_LOAD; ++ mask = ARMADA_37XX_NB_CPU_LOAD_MASK; ++ regmap_update_bits(base, reg, mask, load_level); ++ ++ return rate; ++ } ++ } ++ ++ /* We didn't find any valid divider */ ++ return -EINVAL; ++} ++ + static const struct clk_ops clk_pm_cpu_ops = { + .get_parent = clk_pm_cpu_get_parent, ++ .set_parent = clk_pm_cpu_set_parent, ++ .round_rate = clk_pm_cpu_round_rate, ++ .set_rate = clk_pm_cpu_set_rate, + .recalc_rate = clk_pm_cpu_recalc_rate, + }; + +@@ -409,6 +617,7 @@ static int armada_3700_add_composite_clk + if (data->muxrate_hw) { + struct clk_pm_cpu *pmcpu_clk; + struct clk_hw *muxrate_hw = data->muxrate_hw; ++ struct regmap *map; + + pmcpu_clk = to_clk_pm_cpu(muxrate_hw); + pmcpu_clk->reg_mux = reg + (u64)pmcpu_clk->reg_mux; +@@ -418,6 +627,10 @@ static int armada_3700_add_composite_clk + rate_hw = muxrate_hw; + mux_ops = muxrate_hw->init->ops; + rate_ops = muxrate_hw->init->ops; ++ ++ map = syscon_regmap_lookup_by_compatible( ++ "marvell,armada-3700-nb-pm"); ++ pmcpu_clk->nb_pm_base = map; + } + + *hw = clk_hw_register_composite(dev, data->name, data->parent_names, diff --git a/target/linux/mvebu/patches-4.14/503-cpufreq-Add-DVFS-support-for-Armada-37xx.patch b/target/linux/mvebu/patches-4.14/503-cpufreq-Add-DVFS-support-for-Armada-37xx.patch new file mode 100644 index 000000000..11562c582 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/503-cpufreq-Add-DVFS-support-for-Armada-37xx.patch @@ -0,0 +1,297 @@ +From 92ce45fb875d7c3e021cc454482fe0687ff54f29 Mon Sep 17 00:00:00 2001 +From: Gregory CLEMENT +Date: Thu, 14 Dec 2017 16:00:05 +0100 +Subject: cpufreq: Add DVFS support for Armada 37xx + +This patch adds DVFS support for the Armada 37xx SoCs + +There are up to four CPU frequency loads for Armada 37xx controlled by +the hardware. + +This driver associates the CPU load level to a frequency, then the +hardware will switch while selecting a load level. + +The hardware also can associate a voltage for each level (AVS support) +but it is not yet supported + +Tested-by: Andre Heider +Acked-by: Viresh Kumar +Signed-off-by: Gregory CLEMENT +Signed-off-by: Rafael J. Wysocki +--- + drivers/cpufreq/Kconfig.arm | 7 + + drivers/cpufreq/Makefile | 1 + + drivers/cpufreq/armada-37xx-cpufreq.c | 241 ++++++++++++++++++++++++++++++++++ + 3 files changed, 249 insertions(+) + create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c + +--- a/drivers/cpufreq/Kconfig.arm ++++ b/drivers/cpufreq/Kconfig.arm +@@ -2,6 +2,13 @@ + # ARM CPU Frequency scaling drivers + # + ++config ARM_ARMADA_37XX_CPUFREQ ++ tristate "Armada 37xx CPUFreq support" ++ depends on ARCH_MVEBU ++ help ++ This adds the CPUFreq driver support for Marvell Armada 37xx SoCs. ++ The Armada 37xx PMU supports 4 frequency and VDD levels. ++ + # big LITTLE core layer and glue drivers + config ARM_BIG_LITTLE_CPUFREQ + tristate "Generic ARM big LITTLE CPUfreq driver" +--- a/drivers/cpufreq/Makefile ++++ b/drivers/cpufreq/Makefile +@@ -52,6 +52,7 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += + # LITTLE drivers, so that it is probed last. + obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o + ++obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o + obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o + obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o + obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o +--- /dev/null ++++ b/drivers/cpufreq/armada-37xx-cpufreq.c +@@ -0,0 +1,241 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * CPU frequency scaling support for Armada 37xx platform. ++ * ++ * Copyright (C) 2017 Marvell ++ * ++ * Gregory CLEMENT ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Power management in North Bridge register set */ ++#define ARMADA_37XX_NB_L0L1 0x18 ++#define ARMADA_37XX_NB_L2L3 0x1C ++#define ARMADA_37XX_NB_TBG_DIV_OFF 13 ++#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7 ++#define ARMADA_37XX_NB_CLK_SEL_OFF 11 ++#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1 ++#define ARMADA_37XX_NB_CLK_SEL_TBG 0x1 ++#define ARMADA_37XX_NB_TBG_SEL_OFF 9 ++#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3 ++#define ARMADA_37XX_NB_VDD_SEL_OFF 6 ++#define ARMADA_37XX_NB_VDD_SEL_MASK 0x3 ++#define ARMADA_37XX_NB_CONFIG_SHIFT 16 ++#define ARMADA_37XX_NB_DYN_MOD 0x24 ++#define ARMADA_37XX_NB_CLK_SEL_EN BIT(26) ++#define ARMADA_37XX_NB_TBG_EN BIT(28) ++#define ARMADA_37XX_NB_DIV_EN BIT(29) ++#define ARMADA_37XX_NB_VDD_EN BIT(30) ++#define ARMADA_37XX_NB_DFS_EN BIT(31) ++#define ARMADA_37XX_NB_CPU_LOAD 0x30 ++#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3 ++#define ARMADA_37XX_DVFS_LOAD_0 0 ++#define ARMADA_37XX_DVFS_LOAD_1 1 ++#define ARMADA_37XX_DVFS_LOAD_2 2 ++#define ARMADA_37XX_DVFS_LOAD_3 3 ++ ++/* ++ * On Armada 37xx the Power management manages 4 level of CPU load, ++ * each level can be associated with a CPU clock source, a CPU ++ * divider, a VDD level, etc... ++ */ ++#define LOAD_LEVEL_NR 4 ++ ++struct armada_37xx_dvfs { ++ u32 cpu_freq_max; ++ u8 divider[LOAD_LEVEL_NR]; ++}; ++ ++static struct armada_37xx_dvfs armada_37xx_dvfs[] = { ++ {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} }, ++ {.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} }, ++ {.cpu_freq_max = 800*1000*1000, .divider = {1, 2, 3, 4} }, ++ {.cpu_freq_max = 600*1000*1000, .divider = {2, 4, 5, 6} }, ++}; ++ ++static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(armada_37xx_dvfs); i++) { ++ if (freq == armada_37xx_dvfs[i].cpu_freq_max) ++ return &armada_37xx_dvfs[i]; ++ } ++ ++ pr_err("Unsupported CPU frequency %d MHz\n", freq/1000000); ++ return NULL; ++} ++ ++/* ++ * Setup the four level managed by the hardware. Once the four level ++ * will be configured then the DVFS will be enabled. ++ */ ++static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base, ++ struct clk *clk, u8 *divider) ++{ ++ int load_lvl; ++ struct clk *parent; ++ ++ for (load_lvl = 0; load_lvl < LOAD_LEVEL_NR; load_lvl++) { ++ unsigned int reg, mask, val, offset = 0; ++ ++ if (load_lvl <= ARMADA_37XX_DVFS_LOAD_1) ++ reg = ARMADA_37XX_NB_L0L1; ++ else ++ reg = ARMADA_37XX_NB_L2L3; ++ ++ if (load_lvl == ARMADA_37XX_DVFS_LOAD_0 || ++ load_lvl == ARMADA_37XX_DVFS_LOAD_2) ++ offset += ARMADA_37XX_NB_CONFIG_SHIFT; ++ ++ /* Set cpu clock source, for all the level we use TBG */ ++ val = ARMADA_37XX_NB_CLK_SEL_TBG << ARMADA_37XX_NB_CLK_SEL_OFF; ++ mask = (ARMADA_37XX_NB_CLK_SEL_MASK ++ << ARMADA_37XX_NB_CLK_SEL_OFF); ++ ++ /* ++ * Set cpu divider based on the pre-computed array in ++ * order to have balanced step. ++ */ ++ val |= divider[load_lvl] << ARMADA_37XX_NB_TBG_DIV_OFF; ++ mask |= (ARMADA_37XX_NB_TBG_DIV_MASK ++ << ARMADA_37XX_NB_TBG_DIV_OFF); ++ ++ /* Set VDD divider which is actually the load level. */ ++ val |= load_lvl << ARMADA_37XX_NB_VDD_SEL_OFF; ++ mask |= (ARMADA_37XX_NB_VDD_SEL_MASK ++ << ARMADA_37XX_NB_VDD_SEL_OFF); ++ ++ val <<= offset; ++ mask <<= offset; ++ ++ regmap_update_bits(base, reg, mask, val); ++ } ++ ++ /* ++ * Set cpu clock source, for all the level we keep the same ++ * clock source that the one already configured. For this one ++ * we need to use the clock framework ++ */ ++ parent = clk_get_parent(clk); ++ clk_set_parent(clk, parent); ++} ++ ++static void __init armada37xx_cpufreq_disable_dvfs(struct regmap *base) ++{ ++ unsigned int reg = ARMADA_37XX_NB_DYN_MOD, ++ mask = ARMADA_37XX_NB_DFS_EN; ++ ++ regmap_update_bits(base, reg, mask, 0); ++} ++ ++static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base) ++{ ++ unsigned int val, reg = ARMADA_37XX_NB_CPU_LOAD, ++ mask = ARMADA_37XX_NB_CPU_LOAD_MASK; ++ ++ /* Start with the highest load (0) */ ++ val = ARMADA_37XX_DVFS_LOAD_0; ++ regmap_update_bits(base, reg, mask, val); ++ ++ /* Now enable DVFS for the CPUs */ ++ reg = ARMADA_37XX_NB_DYN_MOD; ++ mask = ARMADA_37XX_NB_CLK_SEL_EN | ARMADA_37XX_NB_TBG_EN | ++ ARMADA_37XX_NB_DIV_EN | ARMADA_37XX_NB_VDD_EN | ++ ARMADA_37XX_NB_DFS_EN; ++ ++ regmap_update_bits(base, reg, mask, mask); ++} ++ ++static int __init armada37xx_cpufreq_driver_init(void) ++{ ++ struct armada_37xx_dvfs *dvfs; ++ struct platform_device *pdev; ++ unsigned int cur_frequency; ++ struct regmap *nb_pm_base; ++ struct device *cpu_dev; ++ int load_lvl, ret; ++ struct clk *clk; ++ ++ nb_pm_base = ++ syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm"); ++ ++ if (IS_ERR(nb_pm_base)) ++ return -ENODEV; ++ ++ /* Before doing any configuration on the DVFS first, disable it */ ++ armada37xx_cpufreq_disable_dvfs(nb_pm_base); ++ ++ /* ++ * On CPU 0 register the operating points supported (which are ++ * the nominal CPU frequency and full integer divisions of ++ * it). ++ */ ++ cpu_dev = get_cpu_device(0); ++ if (!cpu_dev) { ++ dev_err(cpu_dev, "Cannot get CPU\n"); ++ return -ENODEV; ++ } ++ ++ clk = clk_get(cpu_dev, 0); ++ if (IS_ERR(clk)) { ++ dev_err(cpu_dev, "Cannot get clock for CPU0\n"); ++ return PTR_ERR(clk); ++ } ++ ++ /* Get nominal (current) CPU frequency */ ++ cur_frequency = clk_get_rate(clk); ++ if (!cur_frequency) { ++ dev_err(cpu_dev, "Failed to get clock rate for CPU\n"); ++ return -EINVAL; ++ } ++ ++ dvfs = armada_37xx_cpu_freq_info_get(cur_frequency); ++ if (!dvfs) ++ return -EINVAL; ++ ++ armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider); ++ ++ for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR; ++ load_lvl++) { ++ unsigned long freq = cur_frequency / dvfs->divider[load_lvl]; ++ ++ ret = dev_pm_opp_add(cpu_dev, freq, 0); ++ if (ret) { ++ /* clean-up the already added opp before leaving */ ++ while (load_lvl-- > ARMADA_37XX_DVFS_LOAD_0) { ++ freq = cur_frequency / dvfs->divider[load_lvl]; ++ dev_pm_opp_remove(cpu_dev, freq); ++ } ++ return ret; ++ } ++ } ++ ++ /* Now that everything is setup, enable the DVFS at hardware level */ ++ armada37xx_cpufreq_enable_dvfs(nb_pm_base); ++ ++ pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0); ++ ++ return PTR_ERR_OR_ZERO(pdev); ++} ++/* late_initcall, to guarantee the driver is loaded after A37xx clock driver */ ++late_initcall(armada37xx_cpufreq_driver_init); ++ ++MODULE_AUTHOR("Gregory CLEMENT "); ++MODULE_DESCRIPTION("Armada 37xx cpufreq driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/mvebu/patches-4.14/504-spi-a3700-Change-SPI-mode-before-asserting-chip-sele.patch b/target/linux/mvebu/patches-4.14/504-spi-a3700-Change-SPI-mode-before-asserting-chip-sele.patch new file mode 100644 index 000000000..3ac709118 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/504-spi-a3700-Change-SPI-mode-before-asserting-chip-sele.patch @@ -0,0 +1,70 @@ +From dd7aa8d4b53b3484ba31ba56f3ff1be7deb38530 Mon Sep 17 00:00:00 2001 +From: Maxime Chevallier +Date: Tue, 10 Oct 2017 10:43:18 +0200 +Subject: spi: a3700: Change SPI mode before asserting chip-select + +The spi device mode should be configured in the controller before the +chip-select is asserted, so that a clock polarity configuration change +is not interpreted as a clock tick by the device. + +This patch moves the mode setting to the 'prepare_message' function +instead of the 'transfer_one' function. + +By doing so, this patch also removes redundant code in +a3700_spi_clock_set. + +This was tested on EspressoBin board, with spidev. + +Signed-off-by: Maxime Chevallier +Signed-off-by: Mark Brown +--- + drivers/spi/spi-armada-3700.c | 17 ++++------------- + 1 file changed, 4 insertions(+), 13 deletions(-) + +--- a/drivers/spi/spi-armada-3700.c ++++ b/drivers/spi/spi-armada-3700.c +@@ -214,7 +214,7 @@ static void a3700_spi_mode_set(struct a3 + } + + static void a3700_spi_clock_set(struct a3700_spi *a3700_spi, +- unsigned int speed_hz, u16 mode) ++ unsigned int speed_hz) + { + u32 val; + u32 prescale; +@@ -239,17 +239,6 @@ static void a3700_spi_clock_set(struct a + val |= A3700_SPI_CLK_CAPT_EDGE; + spireg_write(a3700_spi, A3700_SPI_IF_TIME_REG, val); + } +- +- val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG); +- val &= ~(A3700_SPI_CLK_POL | A3700_SPI_CLK_PHA); +- +- if (mode & SPI_CPOL) +- val |= A3700_SPI_CLK_POL; +- +- if (mode & SPI_CPHA) +- val |= A3700_SPI_CLK_PHA; +- +- spireg_write(a3700_spi, A3700_SPI_IF_CFG_REG, val); + } + + static void a3700_spi_bytelen_set(struct a3700_spi *a3700_spi, unsigned int len) +@@ -431,7 +420,7 @@ static void a3700_spi_transfer_setup(str + + a3700_spi = spi_master_get_devdata(spi->master); + +- a3700_spi_clock_set(a3700_spi, xfer->speed_hz, spi->mode); ++ a3700_spi_clock_set(a3700_spi, xfer->speed_hz); + + byte_len = xfer->bits_per_word >> 3; + +@@ -592,6 +581,8 @@ static int a3700_spi_prepare_message(str + + a3700_spi_bytelen_set(a3700_spi, 4); + ++ a3700_spi_mode_set(a3700_spi, spi->mode); ++ + return 0; + } + diff --git a/target/linux/mvebu/patches-4.14/505-arm64-dts-marvell-Fix-A37xx-UART0-register-size.patch b/target/linux/mvebu/patches-4.14/505-arm64-dts-marvell-Fix-A37xx-UART0-register-size.patch new file mode 100644 index 000000000..9e2b1c14e --- /dev/null +++ b/target/linux/mvebu/patches-4.14/505-arm64-dts-marvell-Fix-A37xx-UART0-register-size.patch @@ -0,0 +1,39 @@ +From c737abc193d16e62e23e2fb585b8b7398ab380d8 Mon Sep 17 00:00:00 2001 +From: allen yan +Date: Thu, 7 Sep 2017 15:04:53 +0200 +Subject: arm64: dts: marvell: Fix A37xx UART0 register size + +Armada-37xx UART0 registers are 0x200 bytes wide. Right next to them are +the UART1 registers that should not be declared in this node. + +Update the example in DT bindings document accordingly. + +Signed-off-by: allen yan +Signed-off-by: Miquel Raynal +Signed-off-by: Gregory CLEMENT +--- + Documentation/devicetree/bindings/serial/mvebu-uart.txt | 2 +- + arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/Documentation/devicetree/bindings/serial/mvebu-uart.txt ++++ b/Documentation/devicetree/bindings/serial/mvebu-uart.txt +@@ -8,6 +8,6 @@ Required properties: + Example: + serial@12000 { + compatible = "marvell,armada-3700-uart"; +- reg = <0x12000 0x400>; ++ reg = <0x12000 0x200>; + interrupts = <43>; + }; +--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi ++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +@@ -134,7 +134,7 @@ + + uart0: serial@12000 { + compatible = "marvell,armada-3700-uart"; +- reg = <0x12000 0x400>; ++ reg = <0x12000 0x200>; + interrupts = ; + status = "disabled"; + }; diff --git a/target/linux/mvebu/patches-4.14/506-arm64-dts-marvell-armada-37xx-add-UART-clock.patch b/target/linux/mvebu/patches-4.14/506-arm64-dts-marvell-armada-37xx-add-UART-clock.patch new file mode 100644 index 000000000..47e0751c5 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/506-arm64-dts-marvell-armada-37xx-add-UART-clock.patch @@ -0,0 +1,27 @@ +From 2ff0d0b5bb397c3dc5c9b97bd0f20948f0b77740 Mon Sep 17 00:00:00 2001 +From: Miquel Raynal +Date: Fri, 13 Oct 2017 11:01:57 +0200 +Subject: arm64: dts: marvell: armada-37xx: add UART clock + +Add the missing clock property to armada-3700 UART node. + +This clock will be used to derive the prescaler value to comply with +the requested baudrate. + +Signed-off-by: Miquel Raynal +Acked-by: Gregory CLEMENT +Signed-off-by: Gregory CLEMENT +--- + arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi ++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +@@ -135,6 +135,7 @@ + uart0: serial@12000 { + compatible = "marvell,armada-3700-uart"; + reg = <0x12000 0x200>; ++ clocks = <&xtalclk>; + interrupts = ; + status = "disabled"; + }; diff --git a/target/linux/mvebu/patches-4.14/507-arm64-dts-marvell-armada-37xx-add-nodes-allowing-cpu.patch b/target/linux/mvebu/patches-4.14/507-arm64-dts-marvell-armada-37xx-add-nodes-allowing-cpu.patch new file mode 100644 index 000000000..dd3727c55 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/507-arm64-dts-marvell-armada-37xx-add-nodes-allowing-cpu.patch @@ -0,0 +1,48 @@ +From e8d66e7927b2a15310df0eb44a67d120ea147a59 Mon Sep 17 00:00:00 2001 +From: Gregory CLEMENT +Date: Thu, 14 Dec 2017 16:00:06 +0100 +Subject: arm64: dts: marvell: armada-37xx: add nodes allowing cpufreq + support + +In order to be able to use cpu freq, we need to associate a clock to each +CPU and to expose the power management registers. + +Signed-off-by: Gregory CLEMENT +--- + arch/arm64/boot/dts/marvell/armada-372x.dtsi | 1 + + arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 7 +++++++ + 2 files changed, 8 insertions(+) + +--- a/arch/arm64/boot/dts/marvell/armada-372x.dtsi ++++ b/arch/arm64/boot/dts/marvell/armada-372x.dtsi +@@ -56,6 +56,7 @@ + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x1>; ++ clocks = <&nb_periph_clk 16>; + enable-method = "psci"; + }; + }; +--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi ++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +@@ -64,6 +64,7 @@ + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0>; ++ clocks = <&nb_periph_clk 16>; + enable-method = "psci"; + }; + }; +@@ -219,6 +220,12 @@ + }; + }; + ++ nb_pm: syscon@14000 { ++ compatible = "marvell,armada-3700-nb-pm", ++ "syscon"; ++ reg = <0x14000 0x60>; ++ }; ++ + pinctrl_sb: pinctrl@18800 { + compatible = "marvell,armada3710-sb-pinctrl", + "syscon", "simple-mfd"; diff --git a/target/linux/mvebu/patches-4.14/520-arm64-dts-marvell-armada37xx-Add-eth0-alias.patch b/target/linux/mvebu/patches-4.14/520-arm64-dts-marvell-armada37xx-Add-eth0-alias.patch new file mode 100644 index 000000000..206caf2fc --- /dev/null +++ b/target/linux/mvebu/patches-4.14/520-arm64-dts-marvell-armada37xx-Add-eth0-alias.patch @@ -0,0 +1,20 @@ +From be893f672e340b56ca60f2f6c32fdd713a5852f5 Mon Sep 17 00:00:00 2001 +From: Kevin Mihelich +Date: Tue, 4 Jul 2017 19:25:28 -0600 +Subject: arm64: dts: marvell: armada37xx: Add eth0 alias + +Signed-off-by: Kevin Mihelich +--- + arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi ++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +@@ -54,6 +54,7 @@ + #size-cells = <2>; + + aliases { ++ ethernet0 = ð0; + serial0 = &uart0; + }; + diff --git a/target/linux/mvebu/patches-4.14/521-esporessobin-dt-enable-spi-nor-on-i2c.patch b/target/linux/mvebu/patches-4.14/521-esporessobin-dt-enable-spi-nor-on-i2c.patch new file mode 100644 index 000000000..3cabaa7a0 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/521-esporessobin-dt-enable-spi-nor-on-i2c.patch @@ -0,0 +1,29 @@ +--- a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts ++++ b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts +@@ -111,6 +111,26 @@ + status = "okay"; + }; + ++&spi0 { ++ status = "okay"; ++ ++ w25q32dw@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <104000000>; ++ m25,fast-read; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi_quad_pins>; ++ }; ++}; ++ ++&i2c0 { ++ status = "okay"; ++}; ++ + &mdio { + switch0: switch0@1 { + compatible = "marvell,mv88e6085"; diff --git a/target/linux/mvebu/patches-4.14/522-PCI-aardvark-fix-logic-in-PCI-configuration-read-write-functions.patch b/target/linux/mvebu/patches-4.14/522-PCI-aardvark-fix-logic-in-PCI-configuration-read-write-functions.patch new file mode 100644 index 000000000..0dead7d61 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/522-PCI-aardvark-fix-logic-in-PCI-configuration-read-write-functions.patch @@ -0,0 +1,66 @@ +From patchwork Thu Sep 28 12:58:32 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v2, 1/7] PCI: aardvark: fix logic in PCI configuration read/write + functions +X-Patchwork-Submitter: Thomas Petazzoni +X-Patchwork-Id: 819586 +Message-Id: <20170928125838.11887-2-thomas.petazzoni@free-electrons.com> +To: Bjorn Helgaas , linux-pci@vger.kernel.org +Cc: Jason Cooper , Andrew Lunn , + Sebastian Hesselbarth , Gregory Clement + , + Nadav Haklai , Hanna Hawa , + Yehuda Yitschak , + linux-arm-kernel@lists.infradead.org, Antoine Tenart + , =?utf-8?q?Miqu=C3=A8l_Raynal?= + , Victor Gu , + stable@vger.kernel.org, Thomas Petazzoni + +Date: Thu, 28 Sep 2017 14:58:32 +0200 +From: Thomas Petazzoni +List-Id: + +From: Victor Gu + +The PCI configuration space read/write functions were special casing +the situation where PCI_SLOT(devfn) != 0, and returned +PCIBIOS_DEVICE_NOT_FOUND in this case. + +However, will this is what is intended for the root bus, it is not +intended for the child busses, as it prevents discovering devices with +PCI_SLOT(x) != 0. Therefore, we return PCIBIOS_DEVICE_NOT_FOUND only +if we're on the root bus. + +Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver") +Cc: +Signed-off-by: Victor Gu +Reviewed-by: Wilson Ding +Reviewed-by: Nadav Haklai +[Thomas: tweak commit log.] +Signed-off-by: Thomas Petazzoni +--- + drivers/pci/host/pci-aardvark.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -440,7 +440,7 @@ static int advk_pcie_rd_conf(struct pci_ + u32 reg; + int ret; + +- if (PCI_SLOT(devfn) != 0) { ++ if ((bus->number == pcie->root_bus_nr) && (PCI_SLOT(devfn) != 0)) { + *val = 0xffffffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } +@@ -494,7 +494,7 @@ static int advk_pcie_wr_conf(struct pci_ + int offset; + int ret; + +- if (PCI_SLOT(devfn) != 0) ++ if ((bus->number == pcie->root_bus_nr) && (PCI_SLOT(devfn) != 0)) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (where % size) diff --git a/target/linux/mvebu/patches-4.14/523-PCI-aardvark-set-PIO_ADDR_LS-correctly-in-advk_pcie_rd_conf.patch b/target/linux/mvebu/patches-4.14/523-PCI-aardvark-set-PIO_ADDR_LS-correctly-in-advk_pcie_rd_conf.patch new file mode 100644 index 000000000..238eb5626 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/523-PCI-aardvark-set-PIO_ADDR_LS-correctly-in-advk_pcie_rd_conf.patch @@ -0,0 +1,53 @@ +From patchwork Thu Sep 28 12:58:33 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v2, + 2/7] PCI: aardvark: set PIO_ADDR_LS correctly in advk_pcie_rd_conf() +X-Patchwork-Submitter: Thomas Petazzoni +X-Patchwork-Id: 819589 +Message-Id: <20170928125838.11887-3-thomas.petazzoni@free-electrons.com> +To: Bjorn Helgaas , linux-pci@vger.kernel.org +Cc: Jason Cooper , Andrew Lunn , + Sebastian Hesselbarth , Gregory Clement + , + Nadav Haklai , Hanna Hawa , + Yehuda Yitschak , + linux-arm-kernel@lists.infradead.org, Antoine Tenart + , =?utf-8?q?Miqu=C3=A8l_Raynal?= + , Victor Gu , + stable@vger.kernel.org, Thomas Petazzoni + +Date: Thu, 28 Sep 2017 14:58:33 +0200 +From: Thomas Petazzoni +List-Id: + +From: Victor Gu + +When setting the PIO_ADDR_LS register during a configuration read, we +were properly passing the device number, function number and register +number, but not the bus number, causing issues when reading the +configuration of PCIe devices. + +Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver") +Cc: +Signed-off-by: Victor Gu +Reviewed-by: Wilson Ding +Reviewed-by: Nadav Haklai +[Thomas: tweak commit log.] +Signed-off-by: Thomas Petazzoni +--- + drivers/pci/host/pci-aardvark.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -459,7 +459,7 @@ static int advk_pcie_rd_conf(struct pci_ + advk_writel(pcie, reg, PIO_CTRL); + + /* Program the address registers */ +- reg = PCIE_BDF(devfn) | PCIE_CONF_REG(where); ++ reg = PCIE_CONF_ADDR(bus->number, devfn, where); + advk_writel(pcie, reg, PIO_ADDR_LS); + advk_writel(pcie, 0, PIO_ADDR_MS); + diff --git a/target/linux/mvebu/patches-4.14/524-PCI-aardvark-set-host-and-device-to-the-same-MAX-payload-size.patch b/target/linux/mvebu/patches-4.14/524-PCI-aardvark-set-host-and-device-to-the-same-MAX-payload-size.patch new file mode 100644 index 000000000..f7e71aa06 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/524-PCI-aardvark-set-host-and-device-to-the-same-MAX-payload-size.patch @@ -0,0 +1,137 @@ +From patchwork Thu Sep 28 12:58:34 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v2, + 3/7] PCI: aardvark: set host and device to the same MAX payload size +X-Patchwork-Submitter: Thomas Petazzoni +X-Patchwork-Id: 819587 +Message-Id: <20170928125838.11887-4-thomas.petazzoni@free-electrons.com> +To: Bjorn Helgaas , linux-pci@vger.kernel.org +Cc: Jason Cooper , Andrew Lunn , + Sebastian Hesselbarth , Gregory Clement + , + Nadav Haklai , Hanna Hawa , + Yehuda Yitschak , + linux-arm-kernel@lists.infradead.org, Antoine Tenart + , =?utf-8?q?Miqu=C3=A8l_Raynal?= + , Victor Gu , + Thomas Petazzoni +Date: Thu, 28 Sep 2017 14:58:34 +0200 +From: Thomas Petazzoni +List-Id: + +From: Victor Gu + +Since the Aardvark does not implement a PCIe root bus, the Linux PCIe +subsystem will not align the MAX payload size between the host and the +device. This patch ensures that the host and device have the same MAX +payload size, fixing a number of problems with various PCIe devices. + +This is part of fixing bug +https://bugzilla.kernel.org/show_bug.cgi?id=196339, this commit was +reported as the user to be important to get a Intel 7260 mini-PCIe +WiFi card working. + +Fixes: Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver") +Signed-off-by: Victor Gu +Reviewed-by: Evan Wang +Reviewed-by: Nadav Haklai +[Thomas: tweak commit log.] +Signed-off-by: Thomas Petazzoni +--- + drivers/pci/host/pci-aardvark.c | 60 ++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 59 insertions(+), 1 deletion(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -30,8 +30,10 @@ + #define PCIE_CORE_DEV_CTRL_STATS_REG 0xc8 + #define PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE (0 << 4) + #define PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT 5 ++#define PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ 0x2 + #define PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE (0 << 11) + #define PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT 12 ++#define PCIE_CORE_MPS_UNIT_BYTE 128 + #define PCIE_CORE_LINK_CTRL_STAT_REG 0xd0 + #define PCIE_CORE_LINK_L0S_ENTRY BIT(0) + #define PCIE_CORE_LINK_TRAINING BIT(5) +@@ -297,7 +299,8 @@ static void advk_pcie_setup_hw(struct ad + + /* Set PCIe Device Control and Status 1 PF0 register */ + reg = PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE | +- (7 << PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT) | ++ (PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ << ++ PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT) | + PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE | + PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT; + advk_writel(pcie, reg, PCIE_CORE_DEV_CTRL_STATS_REG); +@@ -879,6 +882,58 @@ out_release_res: + return err; + } + ++static int advk_pcie_find_smpss(struct pci_dev *dev, void *data) ++{ ++ u8 *smpss = data; ++ ++ if (!dev) ++ return 0; ++ ++ if (!pci_is_pcie(dev)) ++ return 0; ++ ++ if (*smpss > dev->pcie_mpss) ++ *smpss = dev->pcie_mpss; ++ ++ return 0; ++} ++ ++static int advk_pcie_bus_configure_mps(struct pci_dev *dev, void *data) ++{ ++ int mps; ++ ++ if (!dev) ++ return 0; ++ ++ if (!pci_is_pcie(dev)) ++ return 0; ++ ++ mps = PCIE_CORE_MPS_UNIT_BYTE << *(u8 *)data; ++ pcie_set_mps(dev, mps); ++ ++ return 0; ++} ++ ++static void advk_pcie_configure_mps(struct pci_bus *bus, struct advk_pcie *pcie) ++{ ++ u8 smpss = PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ; ++ u32 reg; ++ ++ /* Find the minimal supported MAX payload size */ ++ advk_pcie_find_smpss(bus->self, &smpss); ++ pci_walk_bus(bus, advk_pcie_find_smpss, &smpss); ++ ++ /* Configure RC MAX payload size */ ++ reg = advk_readl(pcie, PCIE_CORE_DEV_CTRL_STATS_REG); ++ reg &= ~PCI_EXP_DEVCTL_PAYLOAD; ++ reg |= smpss << PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT; ++ advk_writel(pcie, reg, PCIE_CORE_DEV_CTRL_STATS_REG); ++ ++ /* Configure device MAX payload size */ ++ advk_pcie_bus_configure_mps(bus->self, &smpss); ++ pci_walk_bus(bus, advk_pcie_bus_configure_mps, &smpss); ++} ++ + static int advk_pcie_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -952,6 +1007,9 @@ static int advk_pcie_probe(struct platfo + list_for_each_entry(child, &bus->children, node) + pcie_bus_configure_settings(child); + ++ /* Configure the MAX pay load size */ ++ advk_pcie_configure_mps(bus, pcie); ++ + pci_bus_add_devices(bus); + return 0; + } diff --git a/target/linux/mvebu/patches-4.14/525-PCI-aardvark-use-isr1-instead-of-isr0-interrupt-in-legacy-irq-mode.patch b/target/linux/mvebu/patches-4.14/525-PCI-aardvark-use-isr1-instead-of-isr0-interrupt-in-legacy-irq-mode.patch new file mode 100644 index 000000000..777a078ef --- /dev/null +++ b/target/linux/mvebu/patches-4.14/525-PCI-aardvark-use-isr1-instead-of-isr0-interrupt-in-legacy-irq-mode.patch @@ -0,0 +1,143 @@ +From patchwork Thu Sep 28 12:58:35 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v2, + 4/7] PCI: aardvark: use isr1 instead of isr0 interrupt in legacy irq + mode +X-Patchwork-Submitter: Thomas Petazzoni +X-Patchwork-Id: 819592 +Message-Id: <20170928125838.11887-5-thomas.petazzoni@free-electrons.com> +To: Bjorn Helgaas , linux-pci@vger.kernel.org +Cc: Jason Cooper , Andrew Lunn , + Sebastian Hesselbarth , Gregory Clement + , + Nadav Haklai , Hanna Hawa , + Yehuda Yitschak , + linux-arm-kernel@lists.infradead.org, Antoine Tenart + , =?utf-8?q?Miqu=C3=A8l_Raynal?= + , Victor Gu , + Thomas Petazzoni +Date: Thu, 28 Sep 2017 14:58:35 +0200 +From: Thomas Petazzoni +List-Id: + +From: Victor Gu + +The Aardvark has two interrupts sets: + + - first set is bit[23:16] of PCIe ISR 0 register(RD0074840h) + + - second set is bit[11:8] of PCIe ISR 1 register(RD0074848h) + +Only one set should be used, while another set should be masked. + +The second set, ISR1, is more advanced, the Legacy INT_X status bit is +asserted once Assert_INTX message is received, and de-asserted after +Deassert_INTX message is received. Therefore, it matches what the +driver is currently doing in the ->irq_mask() and ->irq_unmask() +functions. The ISR0 requires additional work to deassert the +interrupt, which the driver doesn't do currently. + +This commit resolves a number of issues with legacy interrupts. + +This is part of fixing bug +https://bugzilla.kernel.org/show_bug.cgi?id=196339, this commit was +reported as the user to be important to get a Intel 7260 mini-PCIe +WiFi card working. + +Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver") +Signed-off-by: Victor Gu +Reviewed-by: Evan Wang +Reviewed-by: Nadav Haklai +[Thomas: tweak commit log.] +Signed-off-by: Thomas Petazzoni +--- + drivers/pci/host/pci-aardvark.c | 41 ++++++++++++++++++++++++----------------- + 1 file changed, 24 insertions(+), 17 deletions(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -105,7 +105,8 @@ + #define PCIE_ISR1_MASK_REG (CONTROL_BASE_ADDR + 0x4C) + #define PCIE_ISR1_POWER_STATE_CHANGE BIT(4) + #define PCIE_ISR1_FLUSH BIT(5) +-#define PCIE_ISR1_ALL_MASK GENMASK(5, 4) ++#define PCIE_ISR1_INTX_ASSERT(val) BIT(8 + (val)) ++#define PCIE_ISR1_ALL_MASK GENMASK(11, 4) + #define PCIE_MSI_ADDR_LOW_REG (CONTROL_BASE_ADDR + 0x50) + #define PCIE_MSI_ADDR_HIGH_REG (CONTROL_BASE_ADDR + 0x54) + #define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58) +@@ -615,9 +616,9 @@ static void advk_pcie_irq_mask(struct ir + irq_hw_number_t hwirq = irqd_to_hwirq(d); + u32 mask; + +- mask = advk_readl(pcie, PCIE_ISR0_MASK_REG); +- mask |= PCIE_ISR0_INTX_ASSERT(hwirq); +- advk_writel(pcie, mask, PCIE_ISR0_MASK_REG); ++ mask = advk_readl(pcie, PCIE_ISR1_MASK_REG); ++ mask |= PCIE_ISR1_INTX_ASSERT(hwirq); ++ advk_writel(pcie, mask, PCIE_ISR1_MASK_REG); + } + + static void advk_pcie_irq_unmask(struct irq_data *d) +@@ -626,9 +627,9 @@ static void advk_pcie_irq_unmask(struct + irq_hw_number_t hwirq = irqd_to_hwirq(d); + u32 mask; + +- mask = advk_readl(pcie, PCIE_ISR0_MASK_REG); +- mask &= ~PCIE_ISR0_INTX_ASSERT(hwirq); +- advk_writel(pcie, mask, PCIE_ISR0_MASK_REG); ++ mask = advk_readl(pcie, PCIE_ISR1_MASK_REG); ++ mask &= ~PCIE_ISR1_INTX_ASSERT(hwirq); ++ advk_writel(pcie, mask, PCIE_ISR1_MASK_REG); + } + + static int advk_pcie_irq_map(struct irq_domain *h, +@@ -771,29 +772,35 @@ static void advk_pcie_handle_msi(struct + + static void advk_pcie_handle_int(struct advk_pcie *pcie) + { +- u32 val, mask, status; ++ u32 isr0_val, isr0_mask, isr0_status; ++ u32 isr1_val, isr1_mask, isr1_status; + int i, virq; + +- val = advk_readl(pcie, PCIE_ISR0_REG); +- mask = advk_readl(pcie, PCIE_ISR0_MASK_REG); +- status = val & ((~mask) & PCIE_ISR0_ALL_MASK); +- +- if (!status) { +- advk_writel(pcie, val, PCIE_ISR0_REG); ++ isr0_val = advk_readl(pcie, PCIE_ISR0_REG); ++ isr0_mask = advk_readl(pcie, PCIE_ISR0_MASK_REG); ++ isr0_status = isr0_val & ((~isr0_mask) & PCIE_ISR0_ALL_MASK); ++ ++ isr1_val = advk_readl(pcie, PCIE_ISR1_REG); ++ isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG); ++ isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK); ++ ++ if (!isr0_status && !isr1_status) { ++ advk_writel(pcie, isr0_val, PCIE_ISR0_REG); ++ advk_writel(pcie, isr1_val, PCIE_ISR1_REG); + return; + } + + /* Process MSI interrupts */ +- if (status & PCIE_ISR0_MSI_INT_PENDING) ++ if (isr0_status & PCIE_ISR0_MSI_INT_PENDING) + advk_pcie_handle_msi(pcie); + + /* Process legacy interrupts */ + for (i = 0; i < PCI_NUM_INTX; i++) { +- if (!(status & PCIE_ISR0_INTX_ASSERT(i))) ++ if (!(isr1_status & PCIE_ISR1_INTX_ASSERT(i))) + continue; + +- advk_writel(pcie, PCIE_ISR0_INTX_ASSERT(i), +- PCIE_ISR0_REG); ++ advk_writel(pcie, PCIE_ISR1_INTX_ASSERT(i), ++ PCIE_ISR1_REG); + + virq = irq_find_mapping(pcie->irq_domain, i); + generic_handle_irq(virq); diff --git a/target/linux/mvebu/patches-4.14/526-PCI-aardvark-disable-LOS-state-by-default.patch b/target/linux/mvebu/patches-4.14/526-PCI-aardvark-disable-LOS-state-by-default.patch new file mode 100644 index 000000000..0ee4af4e8 --- /dev/null +++ b/target/linux/mvebu/patches-4.14/526-PCI-aardvark-disable-LOS-state-by-default.patch @@ -0,0 +1,55 @@ +From patchwork Thu Sep 28 12:58:36 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v2,5/7] PCI: aardvark: disable LOS state by default +X-Patchwork-Submitter: Thomas Petazzoni +X-Patchwork-Id: 819590 +Message-Id: <20170928125838.11887-6-thomas.petazzoni@free-electrons.com> +To: Bjorn Helgaas , linux-pci@vger.kernel.org +Cc: Jason Cooper , Andrew Lunn , + Sebastian Hesselbarth , Gregory Clement + , + Nadav Haklai , Hanna Hawa , + Yehuda Yitschak , + linux-arm-kernel@lists.infradead.org, Antoine Tenart + , =?utf-8?q?Miqu=C3=A8l_Raynal?= + , Victor Gu , + Thomas Petazzoni +Date: Thu, 28 Sep 2017 14:58:36 +0200 +From: Thomas Petazzoni +List-Id: + +From: Victor Gu + +Some PCIe devices do not support LOS, and will cause timeouts if the +root complex forces the LOS state. This patch disables the LOS state +by default. + +This is part of fixing bug +https://bugzilla.kernel.org/show_bug.cgi?id=196339, this commit was +reported as the user to be important to get a Intel 7260 mini-PCIe +WiFi card working. + +Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver") +Signed-off-by: Victor Gu +Reviewed-by: Evan Wang +Reviewed-by: Nadav Haklai +[Thomas: tweak commit log.] +Signed-off-by: Thomas Petazzoni +--- + drivers/pci/host/pci-aardvark.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -368,8 +368,7 @@ static void advk_pcie_setup_hw(struct ad + + advk_pcie_wait_for_link(pcie); + +- reg = PCIE_CORE_LINK_L0S_ENTRY | +- (1 << PCIE_CORE_LINK_WIDTH_SHIFT); ++ reg = (1 << PCIE_CORE_LINK_WIDTH_SHIFT); + advk_writel(pcie, reg, PCIE_CORE_LINK_CTRL_STAT_REG); + + reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG); diff --git a/target/linux/mvebu/patches-4.14/527-PCI-aardvark-fix-PCIe-max-read-request-size-setting.patch b/target/linux/mvebu/patches-4.14/527-PCI-aardvark-fix-PCIe-max-read-request-size-setting.patch new file mode 100644 index 000000000..eaf7b097b --- /dev/null +++ b/target/linux/mvebu/patches-4.14/527-PCI-aardvark-fix-PCIe-max-read-request-size-setting.patch @@ -0,0 +1,63 @@ +From patchwork Thu Sep 28 12:58:37 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v2,6/7] PCI: aardvark: fix PCIe max read request size setting +X-Patchwork-Submitter: Thomas Petazzoni +X-Patchwork-Id: 819591 +Message-Id: <20170928125838.11887-7-thomas.petazzoni@free-electrons.com> +To: Bjorn Helgaas , linux-pci@vger.kernel.org +Cc: Jason Cooper , Andrew Lunn , + Sebastian Hesselbarth , Gregory Clement + , + Nadav Haklai , Hanna Hawa , + Yehuda Yitschak , + linux-arm-kernel@lists.infradead.org, Antoine Tenart + , =?utf-8?q?Miqu=C3=A8l_Raynal?= + , Evan Wang , + Thomas Petazzoni +Date: Thu, 28 Sep 2017 14:58:37 +0200 +From: Thomas Petazzoni +List-Id: + +From: Evan Wang + +There is an obvious typo issue in the definition of the PCIe maximum +read request size: a bit shift is directly used as a value, while it +should be used to shift the correct value. + +This is part of fixing bug +https://bugzilla.kernel.org/show_bug.cgi?id=196339, this commit was +reported as the user to be important to get a Intel 7260 mini-PCIe +WiFi card working. + +Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver") +Signed-off-by: Evan Wang +Reviewed-by: Victor Gu +Reviewed-by: Nadav Haklai +[Thomas: tweak commit log.] +Signed-off-by: Thomas Petazzoni +--- + drivers/pci/host/pci-aardvark.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/pci/host/pci-aardvark.c ++++ b/drivers/pci/host/pci-aardvark.c +@@ -33,6 +33,7 @@ + #define PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ 0x2 + #define PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE (0 << 11) + #define PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT 12 ++#define PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SZ 0x2 + #define PCIE_CORE_MPS_UNIT_BYTE 128 + #define PCIE_CORE_LINK_CTRL_STAT_REG 0xd0 + #define PCIE_CORE_LINK_L0S_ENTRY BIT(0) +@@ -303,7 +304,8 @@ static void advk_pcie_setup_hw(struct ad + (PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ << + PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT) | + PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE | +- PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT; ++ (PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SZ << ++ PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT); + advk_writel(pcie, reg, PCIE_CORE_DEV_CTRL_STATS_REG); + + /* Program PCIe Control 2 to disable strict ordering */ diff --git a/target/linux/mvebu/patches-4.4/120-phy-move-fixed_phy-MII-register-generation-to-a-libr.patch b/target/linux/mvebu/patches-4.4/120-phy-move-fixed_phy-MII-register-generation-to-a-libr.patch index 00745f1c9..0b5042afd 100644 --- a/target/linux/mvebu/patches-4.4/120-phy-move-fixed_phy-MII-register-generation-to-a-libr.patch +++ b/target/linux/mvebu/patches-4.4/120-phy-move-fixed_phy-MII-register-generation-to-a-libr.patch @@ -31,7 +31,7 @@ Signed-off-by: Russell King comment "MII PHY device drivers" config AQUANTIA_PHY -@@ -205,6 +208,7 @@ config RTL8306_PHY +@@ -210,6 +213,7 @@ config RTL8306_PHY config FIXED_PHY tristate "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" depends on PHYLIB diff --git a/target/linux/mvebu/patches-4.4/128-phy-export-phy_speed_to_str-for-phylink.patch b/target/linux/mvebu/patches-4.4/128-phy-export-phy_speed_to_str-for-phylink.patch index c43607029..4fa8a6afb 100644 --- a/target/linux/mvebu/patches-4.4/128-phy-export-phy_speed_to_str-for-phylink.patch +++ b/target/linux/mvebu/patches-4.4/128-phy-export-phy_speed_to_str-for-phylink.patch @@ -34,7 +34,7 @@ Signed-off-by: Russell King case PHY_##_state: \ --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -812,6 +812,7 @@ int phy_ethtool_gset(struct phy_device * +@@ -823,6 +823,7 @@ int phy_ethtool_gset(struct phy_device * int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr); int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd); int phy_start_interrupts(struct phy_device *phydev); diff --git a/target/linux/mvebu/patches-4.4/129-phy-add-I2C-mdio-bus.patch b/target/linux/mvebu/patches-4.4/129-phy-add-I2C-mdio-bus.patch index 13f8ecfcd..ad26e6b45 100644 --- a/target/linux/mvebu/patches-4.4/129-phy-add-I2C-mdio-bus.patch +++ b/target/linux/mvebu/patches-4.4/129-phy-add-I2C-mdio-bus.patch @@ -19,7 +19,7 @@ Signed-off-by: Russell King --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -233,6 +233,16 @@ config MDIO_GPIO +@@ -238,6 +238,16 @@ config MDIO_GPIO To compile this driver as a module, choose M here: the module will be called mdio-gpio. diff --git a/target/linux/mvebu/patches-4.4/132-sfp-add-phylink-based-SFP-module-support.patch b/target/linux/mvebu/patches-4.4/132-sfp-add-phylink-based-SFP-module-support.patch index 07b1766b0..dbfcaccac 100644 --- a/target/linux/mvebu/patches-4.4/132-sfp-add-phylink-based-SFP-module-support.patch +++ b/target/linux/mvebu/patches-4.4/132-sfp-add-phylink-based-SFP-module-support.patch @@ -30,7 +30,7 @@ Signed-off-by: Russell King --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -225,6 +225,11 @@ config FIXED_PHY +@@ -230,6 +230,11 @@ config FIXED_PHY Currently tested with mpc866ads and mpc8349e-mitx. @@ -44,7 +44,7 @@ Signed-off-by: Russell King help --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -61,3 +61,4 @@ obj-$(CONFIG_MDIO_MOXART) += mdio-moxart +@@ -62,3 +62,4 @@ obj-$(CONFIG_MDIO_MOXART) += mdio-moxart obj-$(CONFIG_MDIO_BCM_UNIMAC) += mdio-bcm-unimac.o obj-$(CONFIG_MICROCHIP_PHY) += microchip.o obj-$(CONFIG_MDIO_BCM_IPROC) += mdio-bcm-iproc.o diff --git a/target/linux/mvebu/patches-4.4/471-add-ClearFog-Base-device-tree-files.patch b/target/linux/mvebu/patches-4.4/471-add-ClearFog-Base-device-tree-files.patch deleted file mode 100644 index aa442d256..000000000 --- a/target/linux/mvebu/patches-4.4/471-add-ClearFog-Base-device-tree-files.patch +++ /dev/null @@ -1,540 +0,0 @@ -From b4ac5820bdc98ee24a2f73b8bd7fdf7f82db3a46 Mon Sep 17 00:00:00 2001 -From: Marko Ratkaj -Date: Fri, 7 Apr 2017 11:02:30 +0200 -Subject: [PATCH 2/2] add ClearFog Base device tree files - -Signed-off-by: Marko Ratkaj ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/armada-388-clearfog-base.dts | 161 ++++++++++++ - arch/arm/boot/dts/armada-388-clearfog.dtsi | 282 +++++++++++++++++++++ - .../dts/armada-38x-solidrun-microsom-emmc.dtsi | 62 +++++ - 4 files changed, 506 insertions(+) - create mode 100644 arch/arm/boot/dts/armada-388-clearfog-base.dts - create mode 100644 arch/arm/boot/dts/armada-388-clearfog.dtsi - create mode 100644 arch/arm/boot/dts/armada-38x-solidrun-microsom-emmc.dtsi - ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -925,6 +925,7 @@ dtb-$(CONFIG_MACH_ARMADA_38X) += \ - armada-385-linksys-shelby.dtb \ - armada-388-clearfog.dtb \ - armada-388-clearfog-pro.dtb \ -+ armada-388-clearfog-base.dtb \ - armada-388-db.dtb \ - armada-388-gp.dtb \ - armada-388-rd.dtb ---- /dev/null -+++ b/arch/arm/boot/dts/armada-388-clearfog-base.dts -@@ -0,0 +1,161 @@ -+/* -+ * Device Tree file for SolidRun Clearfog Base revision A1 rev 2.0 (88F6828) -+ * -+ * Copyright (C) 2015 Russell King -+ * -+ * This board is in development; the contents of this file work with -+ * the A1 rev 2.0 of the board, which does not represent final -+ * production board. Things will change, don't expect this file to -+ * remain compatible info the future. -+ * -+ * This file is dual-licensed: you can use it either under the terms -+ * of the GPL or the X11 license, at your option. Note that this dual -+ * licensing only applies to this file, and not this project as a -+ * whole. -+ * -+ * a) This file 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. -+ * -+ * This file is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * Or, alternatively, -+ * -+ * b) Permission is hereby granted, free of charge, to any person -+ * obtaining a copy of this software and associated documentation -+ * files (the "Software"), to deal in the Software without -+ * restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or -+ * sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following -+ * conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+/dts-v1/; -+#include "armada-388-clearfog.dtsi" -+#include "armada-38x-solidrun-microsom-emmc.dtsi" -+ -+/ { -+ model = "SolidRun Clearfog Base A1"; -+ compatible = "solidrun,clearfog-base-a1", -+ "solidrun,clearfog-a1", "marvell,armada388", -+ "marvell,armada385", "marvell,armada380"; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ pinctrl-0 = <&rear_button_pins>; -+ pinctrl-names = "default"; -+ -+ button_0 { -+ /* The rear SW3 button */ -+ label = "Rear Button"; -+ gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; -+ linux,can-disable; -+ linux,code = ; -+ }; -+ }; -+}; -+ -+ð1 { -+ phy = <&phy1>; -+}; -+ -+&gpio0 { -+ phy1_reset { -+ gpio-hog; -+ gpios = <19 GPIO_ACTIVE_LOW>; -+ output-low; -+ line-name = "phy1-reset"; -+ }; -+}; -+ -+&mdio { -+ pinctrl-0 = <&mdio_pins µsom_phy_clk_pins &clearfog_phy_pins>; -+ phy1: ethernet-phy@1 { -+ /* -+ * Annoyingly, the marvell phy driver configures the LED -+ * register, rather than preserving reset-loaded setting. -+ * We undo that rubbish here. -+ */ -+ marvell,reg-init = <3 16 0 0x101e>; -+ reg = <1>; -+ }; -+}; -+ -+&pinctrl { -+ /* phy1 reset */ -+ clearfog_phy_pins: clearfog-phy-pins { -+ marvell,pins = "mpp19"; -+ marvell,function = "gpio"; -+ }; -+ rear_button_pins: rear-button-pins { -+ marvell,pins = "mpp44"; -+ marvell,function = "gpio"; -+ }; -+}; -+ -+/* -+MPP -+18: pu gpio pca9655 int -+19: gpio phy reset -+20: pu gpio sd0 detect -+21: sd0:cmd -+22: pd gpio mikro int -+23: -+ -+24: ua1:rxd mikro rx -+25: ua1:txd mikro tx -+26: pu i2c1:sck -+27: pu i2c1:sda -+28: sd0:clk -+29: pd gpio mikro rst -+30: -+31: -+ -+32: -+33: -+34: -+35: -+36: -+37: sd0:d3 -+38: sd0:d0 -+39: sd0:d1 -+ -+40: sd0:d2 -+41: -+42: -+43: spi1:cs2 mikro cs -+44: gpio rear button sw3 -+45: ref:clk_out0 phy#0 clock -+46: ref:clk_out1 phy#1 clock -+47: -+ -+48: gpio J18 spare gpio -+49: gpio U10 I2C_IRQ(GNSS) -+50: gpio board id? -+51: -+52: -+53: -+54: gpio mikro pwm -+55: -+ -+56: pu spi1:mosi mikro mosi -+57: pd spi1:sck mikro sck -+58: spi1:miso mikro miso -+59: -+*/ ---- /dev/null -+++ b/arch/arm/boot/dts/armada-388-clearfog.dtsi -@@ -0,0 +1,282 @@ -+/* -+ * Device Tree include file for SolidRun Clearfog 88F6828 based boards -+ * -+ * Copyright (C) 2015 Russell King -+ * -+ * This board is in development; the contents of this file work with -+ * the A1 rev 2.0 of the board, which does not represent final -+ * production board. Things will change, don't expect this file to -+ * remain compatible info the future. -+ * -+ * This file is dual-licensed: you can use it either under the terms -+ * of the GPL or the X11 license, at your option. Note that this dual -+ * licensing only applies to this file, and not this project as a -+ * whole. -+ * -+ * a) This file 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. -+ * -+ * This file is distributed in the hope that it will be useful -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * Or, alternatively -+ * -+ * b) Permission is hereby granted, free of charge, to any person -+ * obtaining a copy of this software and associated documentation -+ * files (the "Software"), to deal in the Software without -+ * restriction, including without limitation the rights to use -+ * copy, modify, merge, publish, distribute, sublicense, and/or -+ * sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following -+ * conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY -+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+#include "armada-388.dtsi" -+#include "armada-38x-solidrun-microsom.dtsi" -+ -+/ { -+ aliases { -+ /* So that mvebu u-boot can update the MAC addresses */ -+ ethernet1 = ð0; -+ ethernet2 = ð1; -+ ethernet3 = ð2; -+ }; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ reg_3p3v: regulator-3p3v { -+ compatible = "regulator-fixed"; -+ regulator-name = "3P3V"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ soc { -+ internal-regs { -+ sata@a8000 { -+ /* pinctrl? */ -+ status = "okay"; -+ }; -+ -+ sata@e0000 { -+ /* pinctrl? */ -+ status = "okay"; -+ }; -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ usb@58000 { -+ /* CON3, nearest power. */ -+ status = "okay"; -+ }; -+ -+ usb3@f8000 { -+ /* CON7 */ -+ status = "okay"; -+ }; -+ }; -+ -+ pcie-controller { -+ status = "okay"; -+ /* -+ * The two PCIe units are accessible through -+ * the mini-PCIe connectors on the board. -+ */ -+ pcie@2,0 { -+ /* Port 1, Lane 0. CON3, nearest power. */ -+ reset-gpios = <&expander0 1 GPIO_ACTIVE_LOW>; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ sfp: sfp { -+ compatible = "sff,sfp"; -+ i2c-bus = <&i2c1>; -+ los-gpio = <&expander0 12 GPIO_ACTIVE_HIGH>; -+ moddef0-gpio = <&expander0 15 GPIO_ACTIVE_LOW>; -+ sfp,ethernet = <ð2>; -+ tx-disable-gpio = <&expander0 14 GPIO_ACTIVE_HIGH>; -+ tx-fault-gpio = <&expander0 13 GPIO_ACTIVE_HIGH>; -+ }; -+}; -+ -+ð1 { -+ /* ethernet@30000 */ -+ bm,pool-long = <2>; -+ bm,pool-short = <1>; -+ buffer-manager = <&bm>; -+ phy-mode = "sgmii"; -+ status = "okay"; -+}; -+ -+ð2 { -+ /* ethernet@34000 */ -+ bm,pool-long = <3>; -+ bm,pool-short = <1>; -+ buffer-manager = <&bm>; -+ managed = "in-band-status"; -+ phy-mode = "sgmii"; -+ status = "okay"; -+}; -+ -+&i2c0 { -+ clock-frequency = <400000>; -+ pinctrl-0 = <&i2c0_pins>; -+ pinctrl-names = "default"; -+ status = "okay"; -+ -+ /* -+ * PCA9655 GPIO expander, up to 1MHz clock. -+ * 0-CON3 CLKREQ# -+ * 1-CON3 PERST# -+ * 2- -+ * 3-CON3 W_DISABLE -+ * 4- -+ * 5-USB3 overcurrent -+ * 6-USB3 power -+ * 7- -+ * 8-JP4 P1 -+ * 9-JP4 P4 -+ * 10-JP4 P5 -+ * 11-m.2 DEVSLP -+ * 12-SFP_LOS -+ * 13-SFP_TX_FAULT -+ * 14-SFP_TX_DISABLE -+ * 15-SFP_MOD_DEF0 -+ */ -+ expander0: gpio-expander@20 { -+ /* -+ * This is how it should be: -+ * compatible = "onnn,pca9655", "nxp,pca9555"; -+ * but you can't do this because of the way I2C works. -+ */ -+ compatible = "nxp,pca9555"; -+ gpio-controller; -+ #gpio-cells = <2>; -+ reg = <0x20>; -+ -+ pcie1_0_clkreq { -+ gpio-hog; -+ gpios = <0 GPIO_ACTIVE_LOW>; -+ input; -+ line-name = "pcie1.0-clkreq"; -+ }; -+ pcie1_0_w_disable { -+ gpio-hog; -+ gpios = <3 GPIO_ACTIVE_LOW>; -+ output-low; -+ line-name = "pcie1.0-w-disable"; -+ }; -+ usb3_ilimit { -+ gpio-hog; -+ gpios = <5 GPIO_ACTIVE_LOW>; -+ input; -+ line-name = "usb3-current-limit"; -+ }; -+ usb3_power { -+ gpio-hog; -+ gpios = <6 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "usb3-power"; -+ }; -+ m2_devslp { -+ gpio-hog; -+ gpios = <11 GPIO_ACTIVE_HIGH>; -+ output-low; -+ line-name = "m.2 devslp"; -+ }; -+ }; -+ -+ /* The MCP3021 supports standard and fast modes */ -+ mikrobus_adc: mcp3021@4c { -+ compatible = "microchip,mcp3021"; -+ reg = <0x4c>; -+ }; -+}; -+ -+&i2c1 { -+ /* -+ * Routed to SFP, mikrobus, and PCIe. -+ * SFP limits this to 100kHz, and requires an AT24C01A/02/04 with -+ * address pins tied low, which takes addresses 0x50 and 0x51. -+ * Mikrobus doesn't specify beyond an I2C bus being present. -+ * PCIe uses ARP to assign addresses, or 0x63-0x64. -+ */ -+ clock-frequency = <100000>; -+ pinctrl-0 = <&clearfog_i2c1_pins>; -+ pinctrl-names = "default"; -+ status = "okay"; -+}; -+ -+&pinctrl { -+ clearfog_i2c1_pins: i2c1-pins { -+ /* SFP, PCIe, mSATA, mikrobus */ -+ marvell,pins = "mpp26", "mpp27"; -+ marvell,function = "i2c1"; -+ }; -+ clearfog_sdhci_cd_pins: clearfog-sdhci-cd-pins { -+ marvell,pins = "mpp20"; -+ marvell,function = "gpio"; -+ }; -+ mikro_pins: mikro-pins { -+ /* int: mpp22 rst: mpp29 */ -+ marvell,pins = "mpp22", "mpp29"; -+ marvell,function = "gpio"; -+ }; -+ mikro_spi_pins: mikro-spi-pins { -+ marvell,pins = "mpp43"; -+ marvell,function = "spi1"; -+ }; -+ mikro_uart_pins: mikro-uart-pins { -+ marvell,pins = "mpp24", "mpp25"; -+ marvell,function = "ua1"; -+ }; -+}; -+ -+&spi1 { -+ /* -+ * Add SPI CS pins for clearfog: -+ * CS0: W25Q32 (not populated on uSOM) -+ * CS1: PIC microcontroller (Pro models) -+ * CS2: mikrobus -+ */ -+ pinctrl-0 = <&spi1_pins &mikro_spi_pins>; -+ pinctrl-names = "default"; -+ status = "okay"; -+}; -+ -+&uart1 { -+ /* mikrobus uart */ -+ pinctrl-0 = <&mikro_uart_pins>; -+ pinctrl-names = "default"; -+ status = "okay"; -+}; ---- /dev/null -+++ b/arch/arm/boot/dts/armada-38x-solidrun-microsom-emmc.dtsi -@@ -0,0 +1,62 @@ -+/* -+ * Device Tree file for SolidRun Armada 38x Microsom add-on for eMMC -+ * -+ * Copyright (C) 2015 Russell King -+ * -+ * This board is in development; the contents of this file work with -+ * the A1 rev 2.0 of the board, which does not represent final -+ * production board. Things will change, don't expect this file to -+ * remain compatible info the future. -+ * -+ * This file is dual-licensed: you can use it either under the terms -+ * of the GPL or the X11 license, at your option. Note that this dual -+ * licensing only applies to this file, and not this project as a -+ * whole. -+ * -+ * a) This file 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. -+ * -+ * This file is distributed in the hope that it will be useful -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * Or, alternatively -+ * -+ * b) Permission is hereby granted, free of charge, to any person -+ * obtaining a copy of this software and associated documentation -+ * files (the "Software"), to deal in the Software without -+ * restriction, including without limitation the rights to use -+ * copy, modify, merge, publish, distribute, sublicense, and/or -+ * sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following -+ * conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY -+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ */ -+/ { -+ soc { -+ internal-regs { -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ }; -+ }; -+}; diff --git a/target/linux/mvebu/patches-4.9/100-find_active_root.patch b/target/linux/mvebu/patches-4.9/100-find_active_root.patch index d6006b744..216af28c8 100644 --- a/target/linux/mvebu/patches-4.9/100-find_active_root.patch +++ b/target/linux/mvebu/patches-4.9/100-find_active_root.patch @@ -11,10 +11,10 @@ Signed-off-by: Imre Kaloz +static int mangled_rootblock; + - static int parse_ofpart_partitions(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -@@ -33,6 +35,7 @@ static int parse_ofpart_partitions(struc + static int parse_fixed_partitions(struct mtd_info *master, + const struct mtd_partition **pparts, + struct mtd_part_parser_data *data) +@@ -33,6 +35,7 @@ static int parse_fixed_partitions(struct struct device_node *mtd_node; struct device_node *ofpart_node; const char *partname; @@ -22,7 +22,7 @@ Signed-off-by: Imre Kaloz struct device_node *pp; int nr_parts, i, ret = 0; bool dedicated = true; -@@ -110,9 +113,13 @@ static int parse_ofpart_partitions(struc +@@ -110,9 +113,13 @@ static int parse_fixed_partitions(struct parts[i].size = of_read_number(reg + a_cells, s_cells); parts[i].of_node = pp; @@ -39,7 +39,7 @@ Signed-off-by: Imre Kaloz parts[i].name = partname; if (of_get_property(pp, "read-only", &len)) -@@ -213,6 +220,18 @@ static int __init ofpart_parser_init(voi +@@ -220,6 +227,18 @@ static int __init ofpart_parser_init(voi return 0; } diff --git a/target/linux/mvebu/patches-4.9/401-net-phy-move-phy-MMD-accessors-to-phy-core.c.patch b/target/linux/mvebu/patches-4.9/401-net-phy-move-phy-MMD-accessors-to-phy-core.c.patch index 20ed3119d..481d3d5e1 100644 --- a/target/linux/mvebu/patches-4.9/401-net-phy-move-phy-MMD-accessors-to-phy-core.c.patch +++ b/target/linux/mvebu/patches-4.9/401-net-phy-move-phy-MMD-accessors-to-phy-core.c.patch @@ -272,7 +272,7 @@ Signed-off-by: Russell King /** * phy_read_mmd_indirect - reads data from the MMD registers -@@ -727,16 +720,7 @@ static inline bool phy_is_pseudo_fixed_l +@@ -738,16 +731,7 @@ static inline bool phy_is_pseudo_fixed_l * * Same rules as for phy_write(); */ diff --git a/target/linux/mvebu/patches-4.9/407-net-phy-add-802.3-clause-45-support-to-phylib.patch b/target/linux/mvebu/patches-4.9/407-net-phy-add-802.3-clause-45-support-to-phylib.patch index 0715a6a8a..fcf73e429 100644 --- a/target/linux/mvebu/patches-4.9/407-net-phy-add-802.3-clause-45-support-to-phylib.patch +++ b/target/linux/mvebu/patches-4.9/407-net-phy-add-802.3-clause-45-support-to-phylib.patch @@ -295,7 +295,7 @@ Signed-off-by: Russell King } --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -806,6 +806,8 @@ static inline const char *phydev_name(co +@@ -817,6 +817,8 @@ static inline const char *phydev_name(co void phy_attached_print(struct phy_device *phydev, const char *fmt, ...) __printf(2, 3); void phy_attached_info(struct phy_device *phydev); @@ -304,7 +304,7 @@ Signed-off-by: Russell King int genphy_config_init(struct phy_device *phydev); int genphy_setup_forced(struct phy_device *phydev); int genphy_restart_aneg(struct phy_device *phydev); -@@ -820,6 +822,16 @@ static inline int genphy_no_soft_reset(s +@@ -831,6 +833,16 @@ static inline int genphy_no_soft_reset(s { return 0; } diff --git a/target/linux/mvebu/profiles/000-Default.mk b/target/linux/mvebu/profiles/000-Default.mk index 114f758c7..4b5dbe117 100644 --- a/target/linux/mvebu/profiles/000-Default.mk +++ b/target/linux/mvebu/profiles/000-Default.mk @@ -7,7 +7,8 @@ define Profile/Default NAME:=Default Profile (all drivers) - PACKAGES:= kmod-mwlwifi wpad-mini swconfig mkf2fs e2fsprogs + PACKAGES:= kmod-mwlwifi wpad-mini swconfig mkf2fs e2fsprogs \ + mwlwifi-firmware-88w8864 mwlwifi-firmware-88w8964 endef define Profile/Default/Description diff --git a/target/linux/omap24xx/modules.mk b/target/linux/omap24xx/modules.mk index 6a6829ddf..6b7e85d79 100644 --- a/target/linux/omap24xx/modules.mk +++ b/target/linux/omap24xx/modules.mk @@ -70,7 +70,7 @@ define KernelPackage/usb-tahvo CONFIG_TAHVO_USB_HOST_BY_DEFAULT=n \ CONFIG_USB_OHCI_HCD_OMAP1=y \ CONFIG_USB_GADGET_DEBUG_FS=n - DEPENDS:=@TARGET_omap24xx +kmod-usb-musb-tusb6010 + DEPENDS:=@TARGET_omap24xx FILES:=$(LINUX_DIR)/drivers/usb/phy/phy-tahvo.ko AUTOLOAD:=$(call AutoLoad,45,phy-tahvo) $(call AddDepends/usb) diff --git a/target/linux/pistachio/patches-4.9/401-mtd-nor-support-mtd-name-from-device-tree.patch b/target/linux/pistachio/patches-4.9/401-mtd-nor-support-mtd-name-from-device-tree.patch index 9c4d04452..20ca71ea8 100644 --- a/target/linux/pistachio/patches-4.9/401-mtd-nor-support-mtd-name-from-device-tree.patch +++ b/target/linux/pistachio/patches-4.9/401-mtd-nor-support-mtd-name-from-device-tree.patch @@ -18,7 +18,7 @@ Signed-off-by: Abhimanyu Vishwakarma int ret; int i; -@@ -1605,7 +1606,12 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -1606,7 +1607,12 @@ int spi_nor_scan(struct spi_nor *nor, co spi_nor_wait_till_ready(nor); } diff --git a/target/linux/ramips/Makefile b/target/linux/ramips/Makefile index 9bcffc1ce..887b5909e 100644 --- a/target/linux/ramips/Makefile +++ b/target/linux/ramips/Makefile @@ -13,7 +13,7 @@ SUBTARGETS:=mt7620 mt7621 mt76x8 rt288x rt305x rt3883 FEATURES:=squashfs gpio MAINTAINER:=John Crispin -KERNEL_PATCHVER:=4.9 +KERNEL_PATCHVER:=4.14 define Target/Description Build firmware images for Ralink RT288x/RT3xxx based boards. diff --git a/target/linux/ramips/base-files/etc/board.d/01_leds b/target/linux/ramips/base-files/etc/board.d/01_leds index 3e26493e5..a34abbb69 100755 --- a/target/linux/ramips/base-files/etc/board.d/01_leds +++ b/target/linux/ramips/base-files/etc/board.d/01_leds @@ -60,6 +60,9 @@ alfa-network,ac1200rm) set_wifi_led "$boardname:green:wlan2g" "wlan1" ucidef_set_led_default "wps" "wps" "$boardname:green:wps" "0" ;; +alfa-network,awusfree1) + set_wifi_led "$boardname:blue:wlan" + ;; all0256n-4M|\ all0256n-8M) ucidef_set_rssimon "wlan0" "200000" "1" @@ -91,12 +94,6 @@ c108) ucidef_set_led_netdev "lan" "lan" "$boardname:green:lan" "eth0" ucidef_set_led_netdev "modem" "modem" "$boardname:green:modem" "wwan0" ;; -c20) - ucidef_set_led_switch "lan" "lan" "$boardname:blue:lan" "switch0" "0x1e" - ucidef_set_led_switch "wan" "wan" "$boardname:blue:wan" "switch0" "0x01" - set_usb_led "$boardname:blue:usb" - ucidef_set_led_netdev "wlan2g" "wlan2g" "$boardname:blue:wlan2g" "wlan0" - ;; c20i) ucidef_set_led_switch "lan" "lan" "$boardname:blue:lan" "switch0" "0x1e" ucidef_set_led_switch "wan" "wan" "$boardname:blue:wan" "switch0" "0x01" @@ -161,9 +158,15 @@ dir-615-h1) set_wifi_led "rt2800pci-phy0::radio" ;; dir-620-d1|\ +dlink,dwr-116-a1|\ mzk-ex300np) set_wifi_led "$boardname:green:wifi" ;; +dlink,dwr-921-c1) + set_wifi_led "$boardname:green:wifi" + ucidef_set_led_switch "lan" "lan" "$boardname:green:lan" "switch0" "0x0f" + ucidef_set_led_default "sigstrength" "Signal Strength" "$boardname:green:sigstrength" "0" + ;; dir-810l|\ mzk-750dhp|\ mzk-dp150n|\ @@ -193,7 +196,8 @@ fonera20n) set_usb_led "$boardname:orange:usb" set_wifi_led "$boardname:orange:wifi" ;; -gb-pc1) +gb-pc1|\ +gnubee,gb-pc2) ucidef_set_led_switch "lan1" "lan1" "$boardname:green:lan1" "switch0" "0x01" ucidef_set_led_switch "lan2" "lan2" "$boardname:green:lan2" "switch0" "0x10" ;; @@ -367,6 +371,10 @@ rt-n14u) set_wifi_led "$boardname:blue:air" set_usb_led "$boardname:blue:usb" ;; +tama,w06) + ucidef_set_led_netdev "wan" "WAN" "$boardname:green:wan" "eth0" + ucidef_set_led_wlan "wlan" "WLAN" "$boardname:green:wlan" "phy0tpt" + ;; tew-714tru) set_usb_led "$boardname:red:usb" set_wifi_led "$boardname:green:wifi" @@ -388,12 +396,34 @@ tl-wr841n-v13) ucidef_set_led_switch "lan4" "lan4" "$boardname:green:lan4" "switch0" "0x10" ucidef_set_led_switch "wan" "wan" "$boardname:green:wan" "switch0" "0x01" ;; +tplink,c20-v1) + ucidef_set_led_switch "lan" "lan" "$boardname:blue:lan" "switch0" "0x1e" + ucidef_set_led_switch "wan" "wan" "$boardname:blue:wan" "switch0" "0x01" + set_usb_led "$boardname:blue:usb" + ucidef_set_led_netdev "wlan2g" "wlan2g" "$boardname:blue:wlan2g" "wlan0" + ;; +tplink,c20-v4) + ucidef_set_led_switch "lan" "lan" "$boardname:green:lan" "switch0" "0x1e" + ucidef_set_led_switch "wan" "wan" "$boardname:green:wan" "switch0" "0x01" + ucidef_set_led_netdev "wlan2g" "wlan2g" "$boardname:green:wlan2g" "wlan0" + ;; +tplink,c50-v3) + ucidef_set_led_switch "lan" "lan" "$boardname:green:lan" "switch0" "0x1e" + ucidef_set_led_switch "wan" "wan" "$boardname:green:wan" "switch0" "0x01" + ucidef_set_led_netdev "wlan2g" "wlan2g" "$boardname:green:wlan2g" "wlan1" + set_wifi_led "$boardname:green:wlan5g" + ;; tplink,tl-mr3420-v5) set_usb_led "$boardname:green:usb" set_wifi_led "$boardname:green:wlan" ucidef_set_led_switch "lan" "lan" "$boardname:green:lan" "switch0" "0x1e" ucidef_set_led_switch "wan" "wan" "$boardname:green:wan" "switch0" "0x01" ;; +tplink,tl-wr902ac-v3) + set_usb_led "$boardname:green:usb" + ucidef_set_led_netdev "wlan2g" "wlan2g" "$boardname:green:wlan" "wlan0" + ucidef_set_led_switch "lan" "lan" "$boardname:green:lan" "switch0" "0x10" + ;; u25awf-h1) set_wifi_led "u25awf:red:wifi" ucidef_set_led_netdev "eth" "eth" "u25awf:green:lan" "eth0" @@ -486,6 +516,12 @@ zbt-we826-32M) set_wifi_led "zbt-we826:green:wifi" set_usb_led "zbt-we826:green:usb" ;; +zbtlink,zbt-we1226) + set_wifi_led "$boardname:green:wlan" + ucidef_set_led_switch "lan1" "LAN1" "$boardname:green:lan1" "switch0" "0x01" + ucidef_set_led_switch "lan2" "LAN2" "$boardname:green:lan2" "switch0" "0x02" + ucidef_set_led_switch "wan" "WAN" "$boardname:green:wan" "switch0" "0x10" + ;; zbt-wr8305rt) ucidef_set_led_default "power" "power" "$boardname:green:sys" "1" set_usb_led "$boardname:green:usb" diff --git a/target/linux/ramips/base-files/etc/board.d/02_network b/target/linux/ramips/base-files/etc/board.d/02_network index 105f5e9e3..8f3a95d3e 100755 --- a/target/linux/ramips/base-files/etc/board.d/02_network +++ b/target/linux/ramips/base-files/etc/board.d/02_network @@ -57,7 +57,8 @@ ramips_setup_interfaces() omega2p | \ timecloud|\ w150m|\ - widora-neo|\ + widora,neo-16m|\ + widora,neo-32m|\ wnce2001|\ zbt-cpe102|\ zte-q7) @@ -72,12 +73,15 @@ ramips_setup_interfaces() 3g-6200n|\ ai-br100|\ alfa-network,ac1200rm|\ + mediatek,ap-mt7621a-v60|\ d240|\ db-wrt01|\ dir-300-b7|\ dir-320-b1|\ dir-610-a1|\ dir-615-h1|\ + dlink,dwr-116-a1|\ + dlink,dwr-921-c1|\ ew1200|\ firewrt|\ hc5661a|\ @@ -107,11 +111,10 @@ ramips_setup_interfaces() u7621-06-256M-16M|\ vr500|\ wf-2881|\ + whr-g300n|\ witi|\ wl-wn575a3|\ wndr3700v5|\ - wt1520-4M|\ - wt1520-8M|\ youku-yk1|\ zbt-ape522ii|\ zbt-we1326|\ @@ -125,6 +128,27 @@ ramips_setup_interfaces() ucidef_add_switch "switch0" \ "0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "6@eth0" ;; + alfa-network,awusfree1|\ + cs-qr10|\ + d105|\ + dlink,dap-1522-a1|\ + dch-m225|\ + ex2700|\ + ex3700|\ + hpm|\ + mzk-ex300np|\ + mzk-ex750np|\ + na930|\ + pbr-d1|\ + tama,w06|\ + u25awf-h1|\ + wli-tx4-ag300n|\ + wmdr-143n|\ + wmr-300|\ + wn3000rpv3|\ + wrh-300cr) + ucidef_set_interface_lan "eth0" + ;; mir3g) ucidef_add_switch "switch0" \ "2:lan:2" "3:lan:1" "1:wan" "6t@eth0" @@ -173,6 +197,8 @@ ramips_setup_interfaces() mzk-wdpr|\ rb750gr3|\ rt-n14u|\ + tplink,c20-v4|\ + tplink,c50-v3|\ tplink,tl-mr3420-v5|\ tl-wr840n-v4|\ tl-wr840n-v5|\ @@ -184,14 +210,12 @@ ramips_setup_interfaces() wrtnode|\ wrtnode2p | \ wrtnode2r | \ - wt3020-4M|\ - wt3020-8M|\ zbt-wa05) ucidef_add_switch "switch0" \ "1:lan" "2:lan" "3:lan" "4:lan" "0:wan" "6@eth0" ;; - c20|\ - c50) + c50|\ + tplink,c20-v1) ucidef_add_switch "switch0" \ "1:lan:3" "2:lan:4" "3:lan:1" "4:lan:2" "0:wan" "6@eth0" ;; @@ -199,7 +223,8 @@ ramips_setup_interfaces() ucidef_add_switch "switch0" \ "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" "0:wan" "6@eth0" ;; - gb-pc1) + gb-pc1|\ + gnubee,gb-pc2) ucidef_add_switch "switch0" \ "0:lan" "4:lan" "6@eth0" ;; @@ -233,24 +258,6 @@ ramips_setup_interfaces() ucidef_add_switch "switch0" \ "0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "9@eth0" ;; - cs-qr10|\ - d105|\ - dch-m225|\ - ex2700|\ - ex3700|\ - hpm|\ - mzk-ex300np|\ - mzk-ex750np|\ - na930|\ - pbr-d1|\ - u25awf-h1|\ - wli-tx4-ag300n|\ - wmdr-143n|\ - wmr-300|\ - wn3000rpv3|\ - wrh-300cr) - ucidef_set_interface_lan "eth0" - ;; duzun-dm06) ucidef_add_switch "switch0" \ "1:lan" "0:wan" "6@eth0" @@ -315,7 +322,13 @@ ramips_setup_interfaces() ucidef_add_switch "switch0" \ "1:lan" "2:lan" "3:lan" "4:lan" "5:wan" "0@eth0" ;; - vonets,var11n-300) + tplink,tl-wr902ac-v3) + ucidef_add_switch "switch0" \ + "4:lan" "6@eth0" + ;; + vonets,var11n-300|\ + wt1520-4M|\ + wt1520-8M) ucidef_add_switch "switch0" \ "0:lan" "4:wan" "6@eth0" ;; @@ -348,6 +361,12 @@ ramips_setup_interfaces() ucidef_add_switch "switch0" \ "1:lan" "2:lan" "0:wan" "6@eth0" ;; + wt3020-4M|\ + wt3020-8M) + ucidef_add_switch "switch0" \ + "4:lan" "0:wan" "6@eth0" + ;; + zbtlink,zbt-we1226|\ y1) ucidef_add_switch "switch0" \ "0:lan:2" "1:lan:1" "4:wan" "6@eth0" @@ -416,10 +435,16 @@ ramips_setup_macs() lan_mac=$(mtd_get_mac_ascii factory lanmac) wan_mac=$(mtd_get_mac_ascii factory wanmac) ;; + dlink,dwr-116-a1|\ + dlink,dwr-921-c1) + wan_mac=$(jboot_config_read -m -i $(find_mtd_part "config") -o 0xE000) + lan_mac=$(macaddr_add "$wan_mac" 1) + ;; e1700) wan_mac=$(mtd_get_mac_ascii config WAN_MAC_ADDR) ;; - gl-mt300n-v2) + gl-mt300n-v2|\ + whr-g300n) wan_mac=$(mtd_get_mac_binary factory 4) ;; hc5*61|\ diff --git a/target/linux/ramips/base-files/etc/diag.sh b/target/linux/ramips/base-files/etc/diag.sh index e1d29152f..7b90f6ba1 100644 --- a/target/linux/ramips/base-files/etc/diag.sh +++ b/target/linux/ramips/base-files/etc/diag.sh @@ -38,7 +38,10 @@ get_status_led() { nbg-419n2|\ pwh2004|\ r6220|\ + tplink,c20-v4|\ + tplink,c50-v3|\ tplink,tl-mr3420-v5|\ + tplink,tl-wr902ac-v3|\ tl-wr840n-v4|\ tl-wr840n-v5|\ tl-wr841n-v13|\ @@ -76,6 +79,9 @@ get_status_led() { wrh-300cr) status_led="$boardname:green:wps" ;; + alfa-network,awusfree1) + status_led="$boardname:orange:system" + ;; all0239-3g|\ dcs-930|\ dir-300-b1|\ @@ -88,7 +94,9 @@ get_status_led() { dir-620-a1|\ dir-620-d1|\ dwr-512-b|\ + dlink,dwr-116-a1|\ gb-pc1|\ + gnubee,gb-pc2|\ hpm|\ hw550-3g|\ mac1200rv2|\ @@ -100,6 +108,9 @@ get_status_led() { zbt-wg2626) status_led="$boardname:green:status" ;; + dlink,dwr-921-c1) + status_led="$boardname:green:sigstrength" + ;; asl26555-8M|\ asl26555-16M) status_led="asl26555:green:power" @@ -124,7 +135,6 @@ get_status_led() { w502u) status_led="$boardname:blue:wps" ;; - c20|\ d240|\ dap-1350|\ na930|\ @@ -136,6 +146,7 @@ get_status_led() { rt-n14u|\ rt-n15|\ rt-n56u|\ + tplink,c20-v1|\ wl-330n|\ wl-330n3g|\ wli-tx4-ag300n|\ @@ -144,6 +155,13 @@ get_status_led() { youku-yk1) status_led="$boardname:blue:power" ;; + dlink,dap-1522-a1|\ + k2p|\ + m3|\ + mir3g|\ + miwifi-nano) + status_led="$boardname:blue:status" + ;; db-wrt01|\ esr-9753|\ pbr-d1) @@ -171,11 +189,6 @@ get_status_led() { hc5962) status_led="$boardname:white:status" ;; - k2p|\ - m3|\ - miwifi-nano) - status_led="$boardname:blue:status" - ;; linkits7688) status_led="linkit-smart-7688:orange:wifi" ;; @@ -183,15 +196,12 @@ get_status_led() { status_led="$boardname:blue:wifi" ;; gl-mt300n-v2) - status_led="$boardname:red:wlan" + status_led="$boardname:green:power" ;; m4-4M|\ m4-8M) status_led="m4:blue:status" ;; - mir3g) - status_led="$boardname:yellow:status" - ;; miwifi-mini|\ zte-q7) status_led="$boardname:red:status" @@ -286,7 +296,8 @@ get_status_led() { zbt-we2026) status_led="$boardname:red:power" ;; - widora-neo) + widora,neo-16m|\ + widora,neo-32m) status_led="widora:orange:wifi" ;; wzr-agl300nh) @@ -315,6 +326,9 @@ get_status_led() { zbt-we826-32M) status_led="zbt-we826:green:power" ;; + zbtlink,zbt-we1226) + status_led="$boardname:green:wlan" + ;; zbt-wg3526-16M|\ zbt-wg3526-32M) status_led="zbt-wg3526:green:status" diff --git a/target/linux/ramips/base-files/etc/hotplug.d/firmware/10-rt2x00-eeprom b/target/linux/ramips/base-files/etc/hotplug.d/firmware/10-rt2x00-eeprom index 1e25643cb..c0c6a3eca 100644 --- a/target/linux/ramips/base-files/etc/hotplug.d/firmware/10-rt2x00-eeprom +++ b/target/linux/ramips/base-files/etc/hotplug.d/firmware/10-rt2x00-eeprom @@ -19,6 +19,19 @@ rt2x00_eeprom_extract() { rt2x00_eeprom_die "failed to extract from $mtd" } +jboot_eeprom_extract() { + local part=$1 + local offset=$2 + local mtd + + mtd=$(find_mtd_part $part) + [ -n "$mtd" ] || \ + rt2x00_eeprom_die "no mtd device found for partition $part" + + jboot_config_read -i $mtd -o $offset -e /lib/firmware/$FIRMWARE 2>/dev/null || \ + rt2x00_eeprom_die "failed to extract from $mtd" +} + rt2x00_eeprom_set_macaddr() { local macaddr=$1 @@ -41,6 +54,13 @@ board=$(board_name) case "$FIRMWARE" in "soc_wmac.eeprom") case $board in + dlink,dwr-116-a1|\ + dlink,dwr-921-c1) + wan_mac=$(jboot_config_read -m -i $(find_mtd_part "config") -o 0xE000) + wifi_mac=$(macaddr_add "$wan_mac" 1) + jboot_eeprom_extract "config" 0xE000 + rt2x00_eeprom_set_macaddr $wifi_mac + ;; tiny-ac) wifi_mac=$(mtd_get_mac_ascii u-boot-env INIC_MAC_ADDR) rt2x00_eeprom_extract "factory" 0 512 diff --git a/target/linux/ramips/base-files/etc/uci-defaults/09_fix-seama-header b/target/linux/ramips/base-files/etc/uci-defaults/09_fix-checksum similarity index 65% rename from target/linux/ramips/base-files/etc/uci-defaults/09_fix-seama-header rename to target/linux/ramips/base-files/etc/uci-defaults/09_fix-checksum index 9533aed47..54deb5b2e 100644 --- a/target/linux/ramips/base-files/etc/uci-defaults/09_fix-seama-header +++ b/target/linux/ramips/base-files/etc/uci-defaults/09_fix-checksum @@ -5,10 +5,10 @@ . /lib/functions.sh -fix_seama_header() { +fix_checksum() { local kernel_size=$(sed -n 's/mtd[0-9]*: \([0-9a-f]*\).*"kernel".*/\1/p' /proc/mtd) - [ "$kernel_size" ] && mtd -c 0x$kernel_size fixseama firmware + [ "$kernel_size" ] && mtd -c 0x$kernel_size fix$1 firmware } board=$(board_name) @@ -18,6 +18,9 @@ cy-swr1100 | \ dch-m225 | \ dir-645 | \ dir-860l-b1) - fix_seama_header + fix_checksum seama + ;; +dlink,dap-1522-a1) + fix_checksum wrg ;; esac diff --git a/target/linux/ramips/base-files/lib/ramips.sh b/target/linux/ramips/base-files/lib/ramips.sh index e85b29361..75474fbc6 100755 --- a/target/linux/ramips/base-files/lib/ramips.sh +++ b/target/linux/ramips/base-files/lib/ramips.sh @@ -85,9 +85,6 @@ ramips_board_detect() { *"C108") name="c108" ;; - *"C20") - name="c20" - ;; *"C20i") name="c20i" ;; @@ -580,9 +577,6 @@ ramips_board_detect() { *"WHR-G300N") name="whr-g300n" ;; - *"Widora-NEO") - name="widora-neo" - ;; *"WiTi") name="witi" ;; diff --git a/target/linux/ramips/base-files/lib/upgrade/platform.sh b/target/linux/ramips/base-files/lib/upgrade/platform.sh index cd2100132..44be48437 100755 --- a/target/linux/ramips/base-files/lib/upgrade/platform.sh +++ b/target/linux/ramips/base-files/lib/upgrade/platform.sh @@ -17,11 +17,13 @@ platform_check_image() { ai-br100|\ air3gii|\ alfa-network,ac1200rm|\ + alfa-network,awusfree1|\ all0239-3g|\ all0256n-4M|\ all0256n-8M|\ all5002|\ all5003|\ + mediatek,ap-mt7621a-v60|\ ar725w|\ asl26555-8M|\ asl26555-16M|\ @@ -61,6 +63,7 @@ platform_check_image() { fonera20n|\ freestation5|\ gb-pc1|\ + gnubee,gb-pc2|\ gl-mt300a|\ gl-mt300n|\ gl-mt750|\ @@ -140,6 +143,7 @@ platform_check_image() { sap-g3200u3|\ sk-wb8|\ sl-r7205|\ + tama,w06|\ tew-638apb-v2|\ tew-691gr|\ tew-692gr|\ @@ -167,7 +171,8 @@ platform_check_image() { whr-300hp2|\ whr-600d|\ whr-g300n|\ - widora-neo|\ + widora,neo-16m|\ + widora,neo-32m|\ witi|\ wizfi630a|\ wl-330n|\ @@ -203,6 +208,7 @@ platform_check_image() { zbt-ape522ii|\ zbt-cpe102|\ zbt-wa05|\ + zbtlink,zbt-we1226|\ zbt-we1326|\ zbt-we2026|\ zbtlink,zbt-we3526|\ @@ -237,11 +243,14 @@ platform_check_image() { } return 0 ;; - c20|\ c20i|\ c50|\ mr200|\ + tplink,c20-v1|\ + tplink,c20-v4|\ + tplink,c50-v3|\ tplink,tl-mr3420-v5|\ + tplink,tl-wr902ac-v3|\ tl-wr840n-v4|\ tl-wr840n-v5|\ tl-wr841n-v13) @@ -262,11 +271,21 @@ platform_check_image() { } return 0 ;; + dlink,dwr-116-a1|\ + dlink,dwr-921-c1) + [ "$magic" != "0404242b" ] && { + echo "Invalid image type." + return 1 + } + return 0 + ;; hc5962|\ mir3g|\ - r6220) - # these boards use metadata images - return 0 + r6220|\ + ubnt-erx|\ + ubnt-erx-sfp) + nand_do_platform_check "$board" "$1" + return $?; ;; re350-v1) [ "$magic" != "01000000" ] && { @@ -275,11 +294,6 @@ platform_check_image() { } return 0 ;; - ubnt-erx|\ - ubnt-erx-sfp) - nand_do_platform_check "$board" "$1" - return $?; - ;; wcr-1166ds|\ wsr-1166) [ "$magic" != "48445230" ] && { @@ -322,17 +336,8 @@ platform_do_upgrade() { esac } -disable_watchdog() { - killall watchdog - ( ps | grep -v 'grep' | grep '/dev/watchdog' ) && { - echo 'Could not disable watchdog' - return 1 - } -} - blink_led() { . /etc/diag.sh; set_state upgrade } -append sysupgrade_pre_upgrade disable_watchdog append sysupgrade_pre_upgrade blink_led diff --git a/target/linux/ramips/dts/AC1200RM.dts b/target/linux/ramips/dts/AC1200RM.dts index 9305cb00e..9bdbf5cad 100644 --- a/target/linux/ramips/dts/AC1200RM.dts +++ b/target/linux/ramips/dts/AC1200RM.dts @@ -148,8 +148,13 @@ }; partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x1000>; + }; + + partition@031000 { label = "config"; - reg = <0x30000 0x10000>; + reg = <0x31000 0xf000>; read-only; }; diff --git a/target/linux/ramips/dts/AP-MT7621A-V60.dts b/target/linux/ramips/dts/AP-MT7621A-V60.dts new file mode 100644 index 000000000..a98d8a646 --- /dev/null +++ b/target/linux/ramips/dts/AP-MT7621A-V60.dts @@ -0,0 +1,127 @@ +/dts-v1/; + +#include "mt7621.dtsi" + +/ { + compatible = "mediatek,ap-mt7621a-v60", "mediatek,mt7621-soc"; + model = "Mediatek AP-MT7621A-V60 EVB"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x8000000>; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "Audio-I2S"; + simple-audio-card,format = "i2s"; + simple-audio-card,bitclock-master = <&dailink0_master>; + simple-audio-card,frame-master = <&dailink0_master>; + simple-audio-card,widgets = + "Microphone", "Microphone Jack", + "Headphone", "Headphone Jack"; + simple-audio-card,routing = + "LINPUT1", "Microphone Jack", + "RINPUT1", "Microphone Jack", + "Headphone Jack", "HP_L", + "Headphone Jack", "HP_R"; + simple-audio-card,mclk-fs = <256>; + + simple-audio-card,cpu { + sound-dai = <&i2s>; + }; + + dailink0_master: simple-audio-card,codec { + sound-dai = <&codec>; + }; + }; +}; + +&pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "uart2", "rgmii2"; + ralink,function = "gpio"; + }; + }; + i2s_pins: i2s { + i2s { + ralink,group = "uart3"; + ralink,function = "i2s"; + }; + }; +}; + +&i2c { + status = "okay"; + + codec: wm8960@1a { + #sound-dai-cells = <0>; + compatible = "wlf,wm8960"; + reg = <0x1a>; + wlf,shared-lrclk; + }; +}; + +&gdma { + status = "okay"; +}; + +&i2s { + #sound-dai-cells = <0>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_pins>; +}; + +&spi0 { + status = "okay"; + + mx25l6405d@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l6405d","jedec,spi-nor"; + reg = <0 0>; + spi-max-frequency = <10000000>; + m25p,chunked-io = <32>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; +}; + +&sdhci { + status = "okay"; +}; + +ðernet { + mtd-mac-address = <&factory 0x5>; +}; + +&pcie { + status = "okay"; +}; diff --git a/target/linux/ramips/dts/AWUSFREE1.dts b/target/linux/ramips/dts/AWUSFREE1.dts new file mode 100644 index 000000000..c0ffbb279 --- /dev/null +++ b/target/linux/ramips/dts/AWUSFREE1.dts @@ -0,0 +1,164 @@ +/* + * BSD LICENSE + * + * Copyright (C) 2018 Piotr Dymacz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of any + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/dts-v1/; + +#include "mt7628an.dtsi" + +#include +#include + +/ { + compatible = "alfa-network,awusfree1", "mediatek,mt7628an-soc"; + model = "ALFA Network AWUSFREE1"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + system { + label = "awusfree1:orange:system"; + gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; + }; + + wlan { + label = "awusfree1:blue:wlan"; + gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; + }; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x4000000>; + }; +}; + +&ehci { + status = "disabled"; +}; + +&esw { + mediatek,portdisable = <0x1e>; +}; + +ðernet { + mtd-mac-address = <&factory 0x2e>; +}; + +&gpio1 { + status = "okay"; +}; + +&ohci { + status = "disabled"; +}; + +&pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "p0led_an", "wdt", "wled_an"; + ralink,function = "gpio"; + }; + + ext_lna { + ralink,group = "uart1"; + ralink,function = "sw_r"; + }; + + ext_pa { + ralink,group = "i2s"; + ralink,function = "antenna"; + }; + }; +}; + +&spi0 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + m25p,chunked-io = <32>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x1000>; + }; + + partition@031000 { + label = "config"; + reg = <0x31000 0xf000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; +}; + +&wmac { + status = "okay"; + mediatek,mtd-eeprom = <&factory 0x0>; +}; diff --git a/target/linux/ramips/dts/ArcherC20.dts b/target/linux/ramips/dts/ArcherC20v1.dts similarity index 86% rename from target/linux/ramips/dts/ArcherC20.dts rename to target/linux/ramips/dts/ArcherC20v1.dts index f0281c37c..9d8a2b595 100644 --- a/target/linux/ramips/dts/ArcherC20.dts +++ b/target/linux/ramips/dts/ArcherC20v1.dts @@ -6,8 +6,8 @@ #include / { - compatible = "tplink,c20", "ralink,mt7620a-soc"; - model = "TP-Link Archer C20"; + compatible = "tplink,c20-v1", "ralink,mt7620a-soc"; + model = "TP-Link Archer C20 v1"; chosen { bootargs = "console=ttyS0,115200"; @@ -17,43 +17,43 @@ compatible = "gpio-leds"; lan { - label = "c20:blue:lan"; + label = "c20-v1:blue:lan"; gpios = <&gpio0 1 GPIO_ACTIVE_LOW>; }; power { - label = "c20:blue:power"; + label = "c20-v1:blue:power"; gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; default-state = "keep"; }; usb { - label = "c20:blue:usb"; + label = "c20-v1:blue:usb"; gpios = <&gpio2 4 GPIO_ACTIVE_LOW>; }; wan { - label = "c20:blue:wan"; + label = "c20-v1:blue:wan"; gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>; }; wan_orange { - label = "c20:orange:wan"; + label = "c20-v1:orange:wan"; gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>; }; wlan5g { - label = "c20:blue:wlan5g"; + label = "c20-v1:blue:wlan5g"; gpios = <&gpio0 17 GPIO_ACTIVE_LOW>; }; wlan2g { - label = "c20:blue:wlan2g"; + label = "c20-v1:blue:wlan2g"; gpios = <&gpio3 0 GPIO_ACTIVE_LOW>; }; wps { - label = "c20:blue:wps"; + label = "c20-v1:blue:wps"; gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; }; }; @@ -74,7 +74,8 @@ label = "rfkill"; gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; linux,code = ; - }; }; + }; + }; }; &gpio1 { @@ -178,7 +179,7 @@ mt76@0,0 { reg = <0x0000 0 0 0 0>; device_type = "pci"; - mediatek,mtd-eeprom = <&radio 32768>; + mediatek,mtd-eeprom = <&radio 0x8000>; ieee80211-freq-limit = <5000000 6000000>; mtd-mac-address = <&rom 0xf100>; mtd-mac-address-increment = <(-1)>; diff --git a/target/linux/ramips/dts/ArcherC20v4.dts b/target/linux/ramips/dts/ArcherC20v4.dts new file mode 100644 index 000000000..77f70bd84 --- /dev/null +++ b/target/linux/ramips/dts/ArcherC20v4.dts @@ -0,0 +1,101 @@ +/dts-v1/; + +#include "TPLINK-8M.dtsi" + +#include +#include + +/ { + compatible = "tplink,c20-v4", "mediatek,mt7628an-soc"; + model = "TP-Link Archer C20 v4"; + + gpio-leds { + compatible = "gpio-leds"; + + lan { + label = "c20-v4:green:lan"; + gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; + }; + + power { + label = "c20-v4:green:power"; + gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; + }; + + wan { + label = "c20-v4:green:wan"; + gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; + }; + + wan_orange { + label = "c20-v4:orange:wan"; + gpios = <&gpio0 11 GPIO_ACTIVE_LOW>; + }; + + wlan5g { + label = "c20-v4:green:wlan5g"; + gpios = <&gpio1 8 GPIO_ACTIVE_LOW>; + }; + + wlan2g { + label = "c20-v4:green:wlan2g"; + gpios = <&gpio1 7 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "c20-v4:green:wps"; + gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + rfkill { + label = "rfkill"; + gpios = <&gpio1 5 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&wmac { + mtd-mac-address-increment = <(-2)>; +}; + +ðernet { + mediatek,portmap = "wllll"; +}; + +&pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2s", "refclk", "p0led_an", "p1led_an", "p2led_an", "p3led_an", "p4led_an", "wdt"; + ralink,function = "gpio"; + }; + }; +}; + +&pcie { + status = "okay"; + + pcie-bridge { + mt76@0,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x28000>; + ieee80211-freq-limit = <5000000 6000000>; + mtd-mac-address = <&factory 0xf100>; + mtd-mac-address-increment = <(-1)>; + }; + }; +}; diff --git a/target/linux/ramips/dts/ArcherC50V3.dts b/target/linux/ramips/dts/ArcherC50V3.dts new file mode 100644 index 000000000..9dd55ef21 --- /dev/null +++ b/target/linux/ramips/dts/ArcherC50V3.dts @@ -0,0 +1,94 @@ +/dts-v1/; + +#include "TPLINK-8M.dtsi" + +#include +#include + +/ { + compatible = "tplink,c50-v3", "mediatek,mt7628an-soc"; + model = "TP-Link Archer C50 v3"; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + rfkill { + label = "rfkill"; + gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + lan { + label = "c50-v3:green:lan"; + gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; + }; + + power { + label = "c50-v3:green:power"; + gpios = <&gpio0 11 GPIO_ACTIVE_LOW>; + }; + + wan { + label = "c50-v3:green:wan"; + gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; + }; + + wan_orange { + label = "c50-v3:orange:wan"; + gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; + }; + + wlan { + label = "c50-v3:green:wlan2g"; + gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; + }; + + wlan5 { + label = "c50-v3:green:wlan5g"; + gpios = <&gpio1 8 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "c50-v3:green:wps"; + gpios = <&gpio1 7 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "gpio", "p0led_an", "p1led_an", "p2led_an", + "p3led_an", "p4led_an", "wdt", "wled_an"; + ralink,function = "gpio"; + }; + }; +}; + +&pcie { + status = "okay"; + + pcie-bridge { + mt76@0,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x28000>; + ieee80211-freq-limit = <5000000 6000000>; + mtd-mac-address = <&factory 0xf100>; + mtd-mac-address-increment = <(-1)>; + }; + }; +}; diff --git a/target/linux/ramips/dts/DAP-1522-A1.dts b/target/linux/ramips/dts/DAP-1522-A1.dts new file mode 100644 index 000000000..8f8d098bd --- /dev/null +++ b/target/linux/ramips/dts/DAP-1522-A1.dts @@ -0,0 +1,139 @@ +/dts-v1/; + +#include "rt2880.dtsi" + +#include +#include + +/ { + compatible = "dlink,dap-1522-a1", "ralink,rt2880-soc"; + model = "D-Link DAP-1522 A1"; + + cfi@bc400000 { + compatible = "cfi-flash"; + reg = <0xbc400000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "uboot"; + reg = <0x0 0x30000>; + read-only; + }; + + factory: partition@30000 { + label = "factory"; + reg = <0x30000 0x10000>; + read-only; + }; + + partition@40000 { + label = "firmware"; + reg = <0x40000 0x3a0000>; + }; + }; + + rtl8366s { + compatible = "realtek,rtl8366s"; + gpio-sda = <&gpio0 1 GPIO_ACTIVE_HIGH>; + gpio-sck = <&gpio0 2 GPIO_ACTIVE_HIGH>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + reset { + label = "reset"; + gpios = <&gpio0 9 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&gpio2 16 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + ap { + label = "ap"; + gpios = <&gpio2 13 GPIO_ACTIVE_LOW>; + linux,code = ; + linux,input-type = ; + }; + + bridge { + label = "bridge"; + gpios = <&gpio2 14 GPIO_ACTIVE_LOW>; + linux,code = ; + linux,input-type = ; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wps { + label = "dap-1522-a1:blue:wps"; + gpios = <&gpio2 17 GPIO_ACTIVE_LOW>; + }; + + ap { + label = "dap-1522-a1:blue:ap"; + gpios = <&gpio2 18 GPIO_ACTIVE_LOW>; + }; + + sta { + label = "dap-1522-a1:red:sta"; + gpios = <&gpio2 19 GPIO_ACTIVE_LOW>; + }; + + status { + label = "dap-1522-a1:blue:status"; + gpios = <&gpio2 20 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uartlite", "pci"; + ralink,function = "gpio"; + }; + }; +}; + +ðernet { + status = "okay"; + mtd-mac-address = <&factory 0x2004>; + + port@0 { + mediatek,fixed-link = <1000 1 1 1>; + }; + + mdio-bus { + status = "okay"; + + phy0: ethernet-phy@0 { + phy-mode = "mii"; + reg = <0>; + }; + }; +}; + +&wmac { + ralink,mtd-eeprom = <&factory 0x2000>; +}; diff --git a/target/linux/ramips/dts/DWR-116-A1.dts b/target/linux/ramips/dts/DWR-116-A1.dts new file mode 100644 index 000000000..928e34ea4 --- /dev/null +++ b/target/linux/ramips/dts/DWR-116-A1.dts @@ -0,0 +1,104 @@ +/dts-v1/; + +#include "mt7620n.dtsi" + +#include +#include + +/ { + compatible = "dlink,dwr-116-a1", "ralink,mt7620n-soc"; + model = "D-Link DWR-116 A1/A2"; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "wps"; + gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + reset { + label = "reset"; + gpios = <&gpio0 1 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "dwr-116-a1:green:status"; + gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; + }; + + wifi { + label = "dwr-116-a1:green:wifi"; + gpios = <&gpio3 0 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio3 { + status = "okay"; +}; + +&spi0 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partition@0 { + label = "jboot"; + reg = <0x0 0x10000>; + read-only; + }; + + partition@10000 { + label = "firmware"; + reg = <0x10000 0x7e0000>; + }; + + config: partition@7f0000 { + label = "config"; + reg = <0x7f0000 0x10000>; + read-only; + }; + }; +}; + +&ehci { + status = "okay"; +}; + +&ohci { + status = "okay"; +}; + +&pinctrl { + state_default: pinctrl0 { + default { + ralink,group = "i2c", "wled"; + ralink,function = "gpio"; + }; + }; +}; + +ðernet { + mediatek,portmap = "llllw"; + pinctrl-names = "default"; + pinctrl-0 = <&ephy_pins>; +}; diff --git a/target/linux/ramips/dts/DWR-921-C1.dts b/target/linux/ramips/dts/DWR-921-C1.dts new file mode 100644 index 000000000..dbcbc17d8 --- /dev/null +++ b/target/linux/ramips/dts/DWR-921-C1.dts @@ -0,0 +1,144 @@ +/dts-v1/; + +#include "mt7620n.dtsi" + +#include +#include + +/ { + compatible = "dlink,dwr-921-c1", "ralink,mt7620n-soc"; + model = "D-Link DWR-921 C1"; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "wps"; + gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + reset { + label = "reset"; + gpios = <&gpio0 1 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + sms { + label = "dwr-921-c1:green:sms"; + gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; + }; + + lan { + label = "dwr-921-c1:green:lan"; + gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>; + }; + + sstrengthg { + label = "dwr-921-c1:green:sigstrength"; + gpios = <&gpio2 0 GPIO_ACTIVE_LOW>; + }; + + sstrengthr { + label = "dwr-921-c1:red:sigstrength"; + gpios = <&gpio2 1 GPIO_ACTIVE_LOW>; + }; + + 4g { + label = "dwr-921-c1:green:4g"; + gpios = <&gpio2 2 GPIO_ACTIVE_LOW>; + }; + + 3g { + label = "dwr-921-c1:green:3g"; + gpios = <&gpio2 3 GPIO_ACTIVE_LOW>; + }; + + wifi { + label = "dwr-921-c1:green:wifi"; + gpios = <&gpio3 0 GPIO_ACTIVE_LOW>; + }; + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + lte_modem_enable { + gpio-export,name = "lte_modem_enable"; + gpio-export,output = <1>; + gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&gpio3 { + status = "okay"; +}; + +&spi0 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partition@0 { + label = "jboot"; + reg = <0x0 0x10000>; + read-only; + }; + + partition@10000 { + label = "firmware"; + reg = <0x10000 0xfe0000>; + }; + + config: partition@ff0000 { + label = "config"; + reg = <0xff0000 0x10000>; + read-only; + }; + }; +}; + +&ehci { + status = "okay"; +}; + +&ohci { + status = "okay"; +}; + +ðernet { + port@4 { + status = "okay"; + }; +}; + +&pinctrl { + state_default: pinctrl0 { + default { + ralink,group = "spi refclk", "i2c", "ephy", "wled"; + ralink,function = "gpio"; + }; + }; +}; diff --git a/target/linux/ramips/dts/GB-PC1.dts b/target/linux/ramips/dts/GB-PC1.dts index 664dfa1ef..47e137798 100644 --- a/target/linux/ramips/dts/GB-PC1.dts +++ b/target/linux/ramips/dts/GB-PC1.dts @@ -104,7 +104,7 @@ &cpuclock { compatible = "fixed-clock"; - clock-frequency = <90000000>; + clock-frequency = <900000000>; }; &pcie { diff --git a/target/linux/ramips/dts/GB-PC2.dts b/target/linux/ramips/dts/GB-PC2.dts new file mode 100644 index 000000000..ccaf54f3c --- /dev/null +++ b/target/linux/ramips/dts/GB-PC2.dts @@ -0,0 +1,134 @@ +/dts-v1/; + +#include "mt7621.dtsi" + +#include +#include + +/ { + compatible = "gnubee,gb-pc2", "mediatek,mt7621-soc"; + model = "GB-PC2"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x1c000000>, <0x20000000 0x4000000>; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>; + linux,code = ; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + system { + label = "gb-pc2:green:system"; + gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + }; + + status { + label = "gb-pc2:green:status"; + gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; + }; + + lan1 { + label = "gb-pc2:green:lan1"; + gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + }; + + lan2 { + label = "gb-pc2:green:lan2"; + gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + }; + + lan3-yellow { + label = "gb-pc2:yellow:lan3"; + gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + }; + + lan3-green { + label = "gb-pc2:green:lan3"; + gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + }; + + }; +}; + +&sdhci { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&sdhci_pins>; +}; + +&spi0 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + m25p,chunked-io = <32>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x1fb0000>; + }; + }; +}; + +&cpuclock { + compatible = "fixed-clock"; + clock-frequency = <900000000>; +}; + +&pcie { + status = "okay"; +}; + +ðernet { + mtd-mac-address = <&factory 0xe000>; +}; + +&pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "jtag", "rgmii3", "uart3", "wdt"; + ralink,function = "gpio"; + }; + }; +}; + diff --git a/target/linux/ramips/dts/GL-MT300N-V2.dts b/target/linux/ramips/dts/GL-MT300N-V2.dts index 8db3d4bc9..ada618f17 100644 --- a/target/linux/ramips/dts/GL-MT300N-V2.dts +++ b/target/linux/ramips/dts/GL-MT300N-V2.dts @@ -21,6 +21,12 @@ gpio-leds { compatible = "gpio-leds"; + power { + label = "gl-mt300n-v2:green:power"; + default-state = "on"; + gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; + }; + wan { label = "gl-mt300n-v2:blue:wan"; gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; @@ -73,7 +79,7 @@ &pinctrl { state_default: pinctrl0 { gpio { - ralink,group = "wdt", "gpio", "wled_an", "p0led_an", "i2s"; + ralink,group = "wdt", "gpio", "wled_an", "p0led_an", "p1led_an", "i2s"; ralink,function = "gpio"; }; }; @@ -124,6 +130,10 @@ }; }; +&uart1 { + status = "okay"; +}; + &ehci { status = "okay"; }; diff --git a/target/linux/ramips/dts/TL-MR3420V5.dts b/target/linux/ramips/dts/TL-MR3420V5.dts index fdb09dcd6..397b2e169 100644 --- a/target/linux/ramips/dts/TL-MR3420V5.dts +++ b/target/linux/ramips/dts/TL-MR3420V5.dts @@ -1,6 +1,6 @@ /dts-v1/; -#include "TL-WR84XN.dtsi" +#include "TPLINK-8M.dtsi" #include #include diff --git a/target/linux/ramips/dts/TL-WR840NV4.dts b/target/linux/ramips/dts/TL-WR840NV4.dts index f139483a4..09952e7a7 100644 --- a/target/linux/ramips/dts/TL-WR840NV4.dts +++ b/target/linux/ramips/dts/TL-WR840NV4.dts @@ -1,6 +1,6 @@ /dts-v1/; -#include "TL-WR84XN.dtsi" +#include "TPLINK-8M.dtsi" #include #include diff --git a/target/linux/ramips/dts/TL-WR840NV5.dts b/target/linux/ramips/dts/TL-WR840NV5.dts index 340f2bbd8..ecc0fedd5 100644 --- a/target/linux/ramips/dts/TL-WR840NV5.dts +++ b/target/linux/ramips/dts/TL-WR840NV5.dts @@ -65,13 +65,7 @@ partition@20000 { label = "firmware"; - reg = <0x20000 0x3c0000>; - }; - - partition@3e0000 { - label = "config"; - reg = <0x3e0000 0x10000>; - read-only; + reg = <0x20000 0x3d0000>; }; factory: partition@3f0000 { diff --git a/target/linux/ramips/dts/TL-WR841NV13.dts b/target/linux/ramips/dts/TL-WR841NV13.dts index 40f833ced..e552b4703 100644 --- a/target/linux/ramips/dts/TL-WR841NV13.dts +++ b/target/linux/ramips/dts/TL-WR841NV13.dts @@ -1,6 +1,6 @@ /dts-v1/; -#include "TL-WR84XN.dtsi" +#include "TPLINK-8M.dtsi" #include #include diff --git a/target/linux/ramips/dts/TL-WR902ACV3.dts b/target/linux/ramips/dts/TL-WR902ACV3.dts new file mode 100644 index 000000000..8ff357659 --- /dev/null +++ b/target/linux/ramips/dts/TL-WR902ACV3.dts @@ -0,0 +1,102 @@ +/dts-v1/; + +#include "TPLINK-8M.dtsi" + +#include +#include + +/ { + compatible = "tplink,tl-wr902ac-v3", "mediatek,mt7628an-soc"; + model = "TP-Link TL-WR902AC v3"; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + sw1 { + label = "sw1"; + gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + sw2 { + label = "sw2"; + gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + lan { + label = "tl-wr902ac-v3:green:lan"; + gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>; + }; + + power { + label = "tl-wr902ac-v3:green:power"; + gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; + }; + + usb { + label = "tl-wr902ac-v3:green:usb"; + gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; + }; + + wan { + label = "tl-wr902ac-v3:green:wan"; + gpios = <&gpio1 7 GPIO_ACTIVE_LOW>; + }; + + wlan { + label = "tl-wr902ac-v3:green:wlan"; + gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "tl-wr902ac-v3:green:wps"; + gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "i2s", "p0led_an", "p4led_an", "uart1", "wdt", "wled_an"; + ralink,function = "gpio"; + }; + }; +}; + +&ehci { + status = "okay"; +}; + +&ohci { + status = "okay"; +}; + +&pcie { + status = "okay"; + + pcie-bridge { + mt76@1,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x28000>; + ieee80211-freq-limit = <5000000 6000000>; + mtd-mac-address = <&factory 0xf100>; + mtd-mac-address-increment = <(-1)>; + }; + }; +}; diff --git a/target/linux/ramips/dts/TL-WR84XN.dtsi b/target/linux/ramips/dts/TPLINK-8M.dtsi similarity index 100% rename from target/linux/ramips/dts/TL-WR84XN.dtsi rename to target/linux/ramips/dts/TPLINK-8M.dtsi diff --git a/target/linux/ramips/dts/W06.dts b/target/linux/ramips/dts/W06.dts new file mode 100644 index 000000000..c29a01ff9 --- /dev/null +++ b/target/linux/ramips/dts/W06.dts @@ -0,0 +1,115 @@ +/dts-v1/; + +#include "mt7628an.dtsi" + +#include +#include + +/ { + compatible = "tama,w06", "mediatek,mt7628an-soc"; + model = "Tama W06"; + + memory@0{ + device_type = "memory"; + reg = <0x0 0x4000000>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wps { + label = "w06:green:wps"; + gpios = <&gpio0 11 GPIO_ACTIVE_LOW>; + }; + + wan { + label = "w06:green:wan"; + gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; + }; + + wireless { + label = "w06:green:wlan"; + gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&ehci { + status = "okay"; +}; + +ðernet { + mtd-mac-address = <&factory 0x28>; +}; + +&ohci { + status = "okay"; +}; + +&pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "uart1", "p0led_an", "wdt"; + ralink,function = "gpio"; + }; + }; +}; + +&spi0 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + m25p,chunked-io = <32>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xeb0000>; + }; + + partition@f00000 { + label = "user-data"; + reg = <0xf00000 0x100000>; + read-only; + }; + }; +}; + +&wmac { + status = "okay"; +}; diff --git a/target/linux/ramips/dts/WHR-G300N.dts b/target/linux/ramips/dts/WHR-G300N.dts index da861ce66..a7c28341b 100644 --- a/target/linux/ramips/dts/WHR-G300N.dts +++ b/target/linux/ramips/dts/WHR-G300N.dts @@ -107,6 +107,10 @@ }; }; +ðernet { + mtd-mac-address = <&factory 0x4>; +}; + &esw { mediatek,portmap = <0x2f>; }; diff --git a/target/linux/ramips/dts/WIDORA-NEO-16M.dts b/target/linux/ramips/dts/WIDORA-NEO-16M.dts new file mode 100644 index 000000000..726515e7e --- /dev/null +++ b/target/linux/ramips/dts/WIDORA-NEO-16M.dts @@ -0,0 +1,54 @@ +/dts-v1/; + +#include "WIDORA-NEO.dtsi" + +/ { + compatible = "widora,neo-16m", "widora,neo", "mediatek,mt7628an-soc"; + model = "Widora-NEO (16M)"; +}; + +&spi0 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&spi_pins>, <&spi_cs1_pins>; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <40000000>; + m25p,chunked-io = <31>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x0fb0000>; + }; + }; + + spidev@1 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "linux,spidev"; + reg = <1>; + spi-max-frequency = <40000000>; + }; +}; diff --git a/target/linux/ramips/dts/WIDORA-NEO-32M.dts b/target/linux/ramips/dts/WIDORA-NEO-32M.dts new file mode 100644 index 000000000..591101e3f --- /dev/null +++ b/target/linux/ramips/dts/WIDORA-NEO-32M.dts @@ -0,0 +1,54 @@ +/dts-v1/; + +#include "WIDORA-NEO.dtsi" + +/ { + compatible = "widora,neo-32m", "widora,neo", "mediatek,mt7628an-soc"; + model = "Widora-NEO (32M)"; +}; + +&spi0 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&spi_pins>, <&spi_cs1_pins>; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <40000000>; + m25p,chunked-io = <31>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x1fb0000>; + }; + }; + + spidev@1 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "linux,spidev"; + reg = <1>; + spi-max-frequency = <40000000>; + }; +}; diff --git a/target/linux/ramips/dts/WIDORA-NEO.dts b/target/linux/ramips/dts/WIDORA-NEO.dtsi similarity index 68% rename from target/linux/ramips/dts/WIDORA-NEO.dts rename to target/linux/ramips/dts/WIDORA-NEO.dtsi index 195e80605..3334c88e2 100644 --- a/target/linux/ramips/dts/WIDORA-NEO.dts +++ b/target/linux/ramips/dts/WIDORA-NEO.dtsi @@ -1,5 +1,3 @@ -/dts-v1/; - #include "mt7628an.dtsi" #include @@ -7,7 +5,6 @@ / { compatible = "widora,neo", "mediatek,mt7628an-soc"; - model = "Widora-NEO"; chosen { bootargs = "console=ttyS0,115200"; @@ -94,53 +91,6 @@ }; }; - -&spi0 { - status = "okay"; - - pinctrl-names = "default"; - pinctrl-0 = <&spi_pins>, <&spi_cs1_pins>; - - m25p80@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <40000000>; - m25p,chunked-io = <31>; - - partition@0 { - label = "u-boot"; - reg = <0x0 0x30000>; - read-only; - }; - - partition@30000 { - label = "u-boot-env"; - reg = <0x30000 0x10000>; - }; - - factory: partition@40000 { - label = "factory"; - reg = <0x40000 0x10000>; - read-only; - }; - - partition@50000 { - label = "firmware"; - reg = <0x50000 0x0fb0000>; - }; - }; - - spidev@1 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "linux,spidev"; - reg = <1>; - spi-max-frequency = <40000000>; - }; -}; - &i2c { status = "okay"; }; diff --git a/target/linux/ramips/dts/ZBT-WE1226.dts b/target/linux/ramips/dts/ZBT-WE1226.dts new file mode 100644 index 000000000..5ece7567f --- /dev/null +++ b/target/linux/ramips/dts/ZBT-WE1226.dts @@ -0,0 +1,111 @@ +/dts-v1/; +#include +#include + +#include "mt7628an.dtsi" + +/ { + compatible = "zbtlink,zbt-we1226", "mediatek,mt7628an-soc"; + model = "Zbtlink ZBT-WE1226"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x4000000>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wan { + label = "zbt-we1226:green:wan"; + gpios = <&gpio1 7 GPIO_ACTIVE_LOW>; + }; + + lan1 { + label = "zbt-we1226:green:lan1"; + gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; + }; + + lan2 { + label = "zbt-we1226:green:lan2"; + gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; + }; + + wlan { + label = "zbt-we1226:green:wlan"; + gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "p0led_an", "p1led_an", "p4led_an", "wdt", "wled_an"; + ralink,function = "gpio"; + }; + }; +}; + +&spi0 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + m25p,chunked-io = <32>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; +}; + +&wmac { + status = "okay"; + ralink,mtd-eeprom = <&factory 0x4>; +}; + +ðernet { + mtd-mac-address = <&factory 0x2e>; + mediatek,portmap = "llllw"; +}; diff --git a/target/linux/ramips/dts/mt7620a.dtsi b/target/linux/ramips/dts/mt7620a.dtsi index 882cf8810..83ff10274 100644 --- a/target/linux/ramips/dts/mt7620a.dtsi +++ b/target/linux/ramips/dts/mt7620a.dtsi @@ -35,7 +35,7 @@ #size-cells = <1>; sysc: sysc@0 { - compatible = "ralink,mt7620a-sysc", "ralink,rt3050-sysc"; + compatible = "ralink,mt7620a-sysc", "ralink,rt3050-sysc", "syscon"; reg = <0x0 0x100>; }; @@ -427,8 +427,9 @@ usbphy: usbphy { compatible = "mediatek,mt7620-usbphy"; - #phy-cells = <1>; + #phy-cells = <0>; + ralink,sysctl = <&sysc>; resets = <&rstctrl 22 &rstctrl 25>; reset-names = "host", "device"; @@ -501,7 +502,7 @@ interrupt-parent = <&intc>; interrupts = <18>; - phys = <&usbphy 1>; + phys = <&usbphy>; phy-names = "usb"; status = "disabled"; @@ -514,7 +515,7 @@ interrupt-parent = <&intc>; interrupts = <18>; - phys = <&usbphy 1>; + phys = <&usbphy>; phy-names = "usb"; status = "disabled"; diff --git a/target/linux/ramips/dts/mt7620n.dtsi b/target/linux/ramips/dts/mt7620n.dtsi index 5d3c1e3fa..4eb1dde8a 100644 --- a/target/linux/ramips/dts/mt7620n.dtsi +++ b/target/linux/ramips/dts/mt7620n.dtsi @@ -35,7 +35,7 @@ #size-cells = <1>; sysc: sysc@0 { - compatible = "ralink,mt7620a-sysc", "ralink,rt3050-sysc"; + compatible = "ralink,mt7620a-sysc", "ralink,rt3050-sysc", "syscon"; reg = <0x0 0x100>; }; @@ -269,8 +269,9 @@ usbphy: usbphy { compatible = "mediatek,mt7620-usbphy"; - #phy-cells = <1>; + #phy-cells = <0>; + ralink,sysctl = <&sysc>; resets = <&rstctrl 22 &rstctrl 25>; reset-names = "host", "device"; @@ -299,6 +300,13 @@ status = "disabled"; }; + + port@4 { + compatible = "mediatek,mt7620a-gsw-port", "mediatek,eth-port"; + reg = <4>; + + status = "disabled"; + }; }; gsw: gsw@10110000 { @@ -310,7 +318,7 @@ interrupt-parent = <&intc>; interrupts = <17>; - mediatek,port4 = "gmac"; + mediatek,port4 = "ephy"; }; ehci: ehci@101c0000 { @@ -320,7 +328,7 @@ interrupt-parent = <&intc>; interrupts = <18>; - phys = <&usbphy 1>; + phys = <&usbphy>; phy-names = "usb"; status = "disabled"; @@ -330,7 +338,7 @@ compatible = "generic-ohci"; reg = <0x101c1000 0x1000>; - phys = <&usbphy 1>; + phys = <&usbphy>; phy-names = "usb"; interrupt-parent = <&intc>; diff --git a/target/linux/ramips/dts/mt7621.dtsi b/target/linux/ramips/dts/mt7621.dtsi index d68ddf3bc..daca857f6 100644 --- a/target/linux/ramips/dts/mt7621.dtsi +++ b/target/linux/ramips/dts/mt7621.dtsi @@ -342,6 +342,7 @@ compatible = "mediatek,mt8173-xhci"; reg = <0x1e1c0000 0x1000 0x1e1d0700 0x0100>; + reg-names = "mac", "ippc"; clocks = <&sysclock>; clock-names = "sys_ck"; @@ -377,6 +378,16 @@ #size-cells = <1>; }; + hnat: hnat@1e100000 { + compatible = "mediatek,mt7623-hnat"; + reg = <0x1e100000 0x10000>; + mtketh-ppd = "eth0"; + mtketh-lan = "eth0"; + mtketh-wan = "eth0"; + resets = <&rstctrl 0>; + reset-names = "mtketh"; + }; + ethernet: ethernet@1e100000 { compatible = "mediatek,mt7621-eth"; reg = <0x1e100000 0x10000>; diff --git a/target/linux/ramips/dts/mt7628an.dtsi b/target/linux/ramips/dts/mt7628an.dtsi index b572f2ae4..b5edf506f 100644 --- a/target/linux/ramips/dts/mt7628an.dtsi +++ b/target/linux/ramips/dts/mt7628an.dtsi @@ -33,7 +33,7 @@ #size-cells = <1>; sysc: sysc@0 { - compatible = "ralink,mt7620a-sysc"; + compatible = "ralink,mt7620a-sysc", "syscon"; reg = <0x0 0x100>; }; @@ -375,8 +375,9 @@ usbphy: usbphy@10120000 { compatible = "ralink,mt7628an-usbphy", "mediatek,mt7620-usbphy"; reg = <0x10120000 0x1000>; - #phy-cells = <1>; + #phy-cells = <0>; + ralink,sysctl = <&sysc>; resets = <&rstctrl 22 &rstctrl 25>; reset-names = "host", "device"; clocks = <&clkctrl 22 &clkctrl 25>; @@ -400,7 +401,7 @@ compatible = "generic-ehci"; reg = <0x101c0000 0x1000>; - phys = <&usbphy 1>; + phys = <&usbphy>; phy-names = "usb"; interrupt-parent = <&intc>; @@ -411,7 +412,7 @@ compatible = "generic-ohci"; reg = <0x101c1000 0x1000>; - phys = <&usbphy 1>; + phys = <&usbphy>; phy-names = "usb"; interrupt-parent = <&intc>; diff --git a/target/linux/ramips/dts/rt3050.dtsi b/target/linux/ramips/dts/rt3050.dtsi index 5c69d282a..bd51838ba 100644 --- a/target/linux/ramips/dts/rt3050.dtsi +++ b/target/linux/ramips/dts/rt3050.dtsi @@ -34,7 +34,7 @@ #size-cells = <1>; sysc: sysc@0 { - compatible = "ralink,rt3050-sysc"; + compatible = "ralink,rt3050-sysc", "syscon"; reg = <0x0 0x100>; }; @@ -287,6 +287,9 @@ usbphy: usbphy { compatible = "ralink,rt3050-usbphy"; + #phy-cells = <0>; + + ralink,sysctl = <&sysc>; resets = <&rstctrl 22>; reset-names = "host"; clocks = <&clkctrl 18>; diff --git a/target/linux/ramips/dts/rt3352.dtsi b/target/linux/ramips/dts/rt3352.dtsi index 5612458f1..e6e49eeaf 100644 --- a/target/linux/ramips/dts/rt3352.dtsi +++ b/target/linux/ramips/dts/rt3352.dtsi @@ -35,7 +35,7 @@ #size-cells = <1>; sysc: sysc@0 { - compatible = "ralink,rt3352-sysc", "ralink,rt3050-sysc"; + compatible = "ralink,rt3352-sysc", "ralink,rt3050-sysc", "syscon"; reg = <0x0 0x100>; }; @@ -334,8 +334,9 @@ usbphy: usbphy { compatible = "ralink,rt3352-usbphy"; - #phy-cells = <1>; + #phy-cells = <0>; + ralink,sysctl = <&sysc>; resets = <&rstctrl 22 &rstctrl 25>; reset-names = "host", "device"; clocks = <&clkctrl 18 &clkctrl 20>; @@ -356,7 +357,7 @@ compatible = "generic-ehci"; reg = <0x101c0000 0x1000>; - phys = <&usbphy 1>; + phys = <&usbphy>; phy-names = "usb"; interrupt-parent = <&intc>; @@ -369,7 +370,7 @@ compatible = "generic-ohci"; reg = <0x101c1000 0x1000>; - phys = <&usbphy 1>; + phys = <&usbphy>; phy-names = "usb"; interrupt-parent = <&intc>; diff --git a/target/linux/ramips/dts/rt3883.dtsi b/target/linux/ramips/dts/rt3883.dtsi index 64bc56b4a..193a3ee1c 100644 --- a/target/linux/ramips/dts/rt3883.dtsi +++ b/target/linux/ramips/dts/rt3883.dtsi @@ -35,7 +35,7 @@ #size-cells = <1>; sysc: sysc@0 { - compatible = "ralink,rt3883-sysc", "ralink,rt3050-sysc"; + compatible = "ralink,rt3883-sysc", "ralink,rt3050-sysc", "syscon"; reg = <0x0 0x100>; }; @@ -427,8 +427,9 @@ usbphy: usbphy { compatible = "ralink,rt3352-usbphy"; - #phy-cells = <1>; + #phy-cells = <0>; + ralink,sysctl = <&sysc>; resets = <&rstctrl 22 &rstctrl 25>; reset-names = "host", "device"; clocks = <&clkctrl 22 &clkctrl 25>; @@ -449,7 +450,7 @@ compatible = "generic-ehci"; reg = <0x101c0000 0x1000>; - phys = <&usbphy 1>; + phys = <&usbphy>; phy-names = "usb"; interrupt-parent = <&intc>; @@ -462,7 +463,7 @@ compatible = "generic-ohci"; reg = <0x101c1000 0x1000>; - phys = <&usbphy 1>; + phys = <&usbphy>; phy-names = "usb"; interrupt-parent = <&intc>; diff --git a/target/linux/ramips/dts/rt5350.dtsi b/target/linux/ramips/dts/rt5350.dtsi index a92c11304..843ea3019 100644 --- a/target/linux/ramips/dts/rt5350.dtsi +++ b/target/linux/ramips/dts/rt5350.dtsi @@ -35,7 +35,7 @@ #size-cells = <1>; sysc: sysc@0 { - compatible = "ralink,rt5350-sysc", "ralink,rt3050-sysc"; + compatible = "ralink,rt5350-sysc", "ralink,rt3050-sysc", "syscon"; reg = <0x0 0x100>; }; @@ -324,8 +324,9 @@ usbphy: usbphy { compatible = "ralink,rt3352-usbphy"; - #phy-cells = <1>; + #phy-cells = <0>; + ralink,sysctl = <&sysc>; resets = <&rstctrl 22 &rstctrl 25>; reset-names = "host", "device"; clocks = <&clkctrl 18>; @@ -370,7 +371,7 @@ compatible = "generic-ehci"; reg = <0x101c0000 0x1000>; - phys = <&usbphy 1>; + phys = <&usbphy>; phy-names = "usb"; interrupt-parent = <&intc>; @@ -381,7 +382,7 @@ compatible = "generic-ohci"; reg = <0x101c1000 0x1000>; - phys = <&usbphy 1>; + phys = <&usbphy>; phy-names = "usb"; interrupt-parent = <&intc>; diff --git a/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/Kconfig b/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/Kconfig new file mode 100644 index 000000000..a58b0f3dc --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/Kconfig @@ -0,0 +1,16 @@ +config MTK_MMC + tristate "MTK SD/MMC" + depends on !MTD_NAND_RALINK + +config MTK_AEE_KDUMP + bool "MTK AEE KDUMP" + depends on MTK_MMC + +config MTK_MMC_CD_POLL + bool "Card Detect with Polling" + depends on MTK_MMC + +config MTK_MMC_EMMC_8BIT + bool "eMMC 8-bit support" + depends on MTK_MMC && RALINK_MT7628 + diff --git a/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/Makefile b/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/Makefile new file mode 100644 index 000000000..caead0b54 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/Makefile @@ -0,0 +1,42 @@ +# Copyright Statement: +# +# This software/firmware and related documentation ("MediaTek Software") are +# protected under relevant copyright laws. The information contained herein +# is confidential and proprietary to MediaTek Inc. and/or its licensors. +# Without the prior written permission of MediaTek inc. and/or its licensors, +# any reproduction, modification, use or disclosure of MediaTek Software, +# and information contained herein, in whole or in part, shall be strictly prohibited. +# +# MediaTek Inc. (C) 2010. All rights reserved. +# +# BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES +# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") +# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON +# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. +# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE +# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR +# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH +# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES +# THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES +# CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK +# SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR +# STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND +# CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, +# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, +# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO +# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. +# +# The following software/firmware and/or related documentation ("MediaTek Software") +# have been modified by MediaTek Inc. All revisions are subject to any receiver's +# applicable license agreements with MediaTek Inc. + +obj-$(CONFIG_MTK_MMC) += mtk_sd.o +mtk_sd-objs := sd.o dbg.o +ifeq ($(CONFIG_MTK_AEE_KDUMP),y) +EXTRA_CFLAGS += -DMT6575_SD_DEBUG +endif + +clean: + @rm -f *.o modules.order .*.cmd diff --git a/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/board.h b/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/board.h new file mode 100644 index 000000000..33bfc7b95 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/board.h @@ -0,0 +1,137 @@ +/* Copyright Statement: + * + * This software/firmware and related documentation ("MediaTek Software") are + * protected under relevant copyright laws. The information contained herein + * is confidential and proprietary to MediaTek Inc. and/or its licensors. + * Without the prior written permission of MediaTek inc. and/or its licensors, + * any reproduction, modification, use or disclosure of MediaTek Software, + * and information contained herein, in whole or in part, shall be strictly prohibited. + */ +/* MediaTek Inc. (C) 2010. All rights reserved. + * + * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON + * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE + * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR + * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH + * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES + * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES + * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK + * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR + * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND + * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, + * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, + * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO + * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * The following software/firmware and/or related documentation ("MediaTek Software") + * have been modified by MediaTek Inc. All revisions are subject to any receiver's + * applicable license agreements with MediaTek Inc. + */ + +#ifndef __ARCH_ARM_MACH_BOARD_H +#define __ARCH_ARM_MACH_BOARD_H + +#include +#include +/* --- chhung */ +// #include +// #include +/* end of chhung */ + +typedef void (*sdio_irq_handler_t)(void*); /* external irq handler */ +typedef void (*pm_callback_t)(pm_message_t state, void *data); + +#define MSDC_CD_PIN_EN (1 << 0) /* card detection pin is wired */ +#define MSDC_WP_PIN_EN (1 << 1) /* write protection pin is wired */ +#define MSDC_RST_PIN_EN (1 << 2) /* emmc reset pin is wired */ +#define MSDC_SDIO_IRQ (1 << 3) /* use internal sdio irq (bus) */ +#define MSDC_EXT_SDIO_IRQ (1 << 4) /* use external sdio irq */ +#define MSDC_REMOVABLE (1 << 5) /* removable slot */ +#define MSDC_SYS_SUSPEND (1 << 6) /* suspended by system */ +#define MSDC_HIGHSPEED (1 << 7) /* high-speed mode support */ +#define MSDC_UHS1 (1 << 8) /* uhs-1 mode support */ +#define MSDC_DDR (1 << 9) /* ddr mode support */ + + +#define MSDC_SMPL_RISING (0) +#define MSDC_SMPL_FALLING (1) + +#define MSDC_CMD_PIN (0) +#define MSDC_DAT_PIN (1) +#define MSDC_CD_PIN (2) +#define MSDC_WP_PIN (3) +#define MSDC_RST_PIN (4) + +enum { + MSDC_CLKSRC_48MHZ = 0, +// MSDC_CLKSRC_26MHZ = 0, +// MSDC_CLKSRC_197MHZ = 1, +// MSDC_CLKSRC_208MHZ = 2 +}; + +struct msdc_hw { + unsigned char clk_src; /* host clock source */ + unsigned char cmd_edge; /* command latch edge */ + unsigned char data_edge; /* data latch edge */ + unsigned char clk_drv; /* clock pad driving */ + unsigned char cmd_drv; /* command pad driving */ + unsigned char dat_drv; /* data pad driving */ + unsigned long flags; /* hardware capability flags */ + unsigned long data_pins; /* data pins */ + unsigned long data_offset; /* data address offset */ + + /* config gpio pull mode */ + void (*config_gpio_pin)(int type, int pull); + + /* external power control for card */ + void (*ext_power_on)(void); + void (*ext_power_off)(void); + + /* external sdio irq operations */ + void (*request_sdio_eirq)(sdio_irq_handler_t sdio_irq_handler, void *data); + void (*enable_sdio_eirq)(void); + void (*disable_sdio_eirq)(void); + + /* external cd irq operations */ + void (*request_cd_eirq)(sdio_irq_handler_t cd_irq_handler, void *data); + void (*enable_cd_eirq)(void); + void (*disable_cd_eirq)(void); + int (*get_cd_status)(void); + + /* power management callback for external module */ + void (*register_pm)(pm_callback_t pm_cb, void *data); +}; + +extern struct msdc_hw msdc0_hw; +extern struct msdc_hw msdc1_hw; +extern struct msdc_hw msdc2_hw; +extern struct msdc_hw msdc3_hw; + +/*GPS driver*/ +#define GPS_FLAG_FORCE_OFF 0x0001 +struct mt3326_gps_hardware { + int (*ext_power_on)(int); + int (*ext_power_off)(int); +}; +extern struct mt3326_gps_hardware mt3326_gps_hw; + +/* NAND driver */ +struct mt6575_nand_host_hw { + unsigned int nfi_bus_width; /* NFI_BUS_WIDTH */ + unsigned int nfi_access_timing; /* NFI_ACCESS_TIMING */ + unsigned int nfi_cs_num; /* NFI_CS_NUM */ + unsigned int nand_sec_size; /* NAND_SECTOR_SIZE */ + unsigned int nand_sec_shift; /* NAND_SECTOR_SHIFT */ + unsigned int nand_ecc_size; + unsigned int nand_ecc_bytes; + unsigned int nand_ecc_mode; +}; +extern struct mt6575_nand_host_hw mt6575_nand_hw; + +#endif /* __ARCH_ARM_MACH_BOARD_H */ + diff --git a/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/dbg.c b/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/dbg.c new file mode 100644 index 000000000..ae4ef0fa5 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/dbg.c @@ -0,0 +1,348 @@ +/* Copyright Statement: + * + * This software/firmware and related documentation ("MediaTek Software") are + * protected under relevant copyright laws. The information contained herein + * is confidential and proprietary to MediaTek Inc. and/or its licensors. + * Without the prior written permission of MediaTek inc. and/or its licensors, + * any reproduction, modification, use or disclosure of MediaTek Software, + * and information contained herein, in whole or in part, shall be strictly prohibited. + * + * MediaTek Inc. (C) 2010. All rights reserved. + * + * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON + * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE + * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR + * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH + * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES + * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES + * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK + * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR + * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND + * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, + * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, + * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO + * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * The following software/firmware and/or related documentation ("MediaTek Software") + * have been modified by MediaTek Inc. All revisions are subject to any receiver's + * applicable license agreements with MediaTek Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// #include /* --- by chhung */ +#include "dbg.h" +#include "mt6575_sd.h" +#include + +/* mode select */ +u32 dma_size[4]={ + 512, + 512, + 512, + 512 +}; +msdc_mode drv_mode[4]={ + MODE_SIZE_DEP, /* using DMA or not depend on the size */ + MODE_SIZE_DEP, + MODE_SIZE_DEP, + MODE_SIZE_DEP +}; + +#if defined (MT6575_SD_DEBUG) +static char cmd_buf[256]; + +/* for debug zone */ +static unsigned int sd_debug_zone[4]={ + 0, + 0, + 0, + 0 +}; + + +/* for driver profile */ +#define TICKS_ONE_MS (13000) +u32 gpt_enable = 0; +u32 sdio_pro_enable = 0; /* make sure gpt is enabled */ +u32 sdio_pro_time = 0; /* no more than 30s */ +struct sdio_profile sdio_perfomance = {0}; + +#if 0 /* --- chhung */ +void msdc_init_gpt(void) +{ + GPT_CONFIG config; + + config.num = GPT6; + config.mode = GPT_FREE_RUN; + config.clkSrc = GPT_CLK_SRC_SYS; + config.clkDiv = GPT_CLK_DIV_1; /* 13MHz GPT6 */ + + if (GPT_Config(config) == FALSE ) + return; + + GPT_Start(GPT6); +} +#endif /* end of --- */ + +u32 msdc_time_calc(u32 old_L32, u32 old_H32, u32 new_L32, u32 new_H32) +{ + u32 ret = 0; + + if (new_H32 == old_H32) { + ret = new_L32 - old_L32; + } else if(new_H32 == (old_H32 + 1)) { + if (new_L32 > old_L32) { + printk("msdc old_L<0x%x> new_L<0x%x>\n", old_L32, new_L32); + } + ret = (0xffffffff - old_L32); + ret += new_L32; + } else { + printk("msdc old_H<0x%x> new_H<0x%x>\n", old_H32, new_H32); + } + + return ret; +} + +void msdc_sdio_profile(struct sdio_profile* result) +{ + struct cmd_profile* cmd; + u32 i; + + printk("sdio === performance dump ===\n"); + printk("sdio === total execute tick<%d> time<%dms> Tx<%dB> Rx<%dB>\n", + result->total_tc, result->total_tc / TICKS_ONE_MS, + result->total_tx_bytes, result->total_rx_bytes); + + /* CMD52 Dump */ + cmd = &result->cmd52_rx; + printk("sdio === CMD52 Rx <%d>times tick<%d> Max<%d> Min<%d> Aver<%d>\n", cmd->count, cmd->tot_tc, + cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count); + cmd = &result->cmd52_tx; + printk("sdio === CMD52 Tx <%d>times tick<%d> Max<%d> Min<%d> Aver<%d>\n", cmd->count, cmd->tot_tc, + cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count); + + /* CMD53 Rx bytes + block mode */ + for (i=0; i<512; i++) { + cmd = &result->cmd53_rx_byte[i]; + if (cmd->count) { + printk("sdio<%6d><%3dB>_Rx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", cmd->count, i, cmd->tot_tc, + cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count, + cmd->tot_bytes, (cmd->tot_bytes/10)*13 / (cmd->tot_tc/10)); + } + } + for (i=0; i<100; i++) { + cmd = &result->cmd53_rx_blk[i]; + if (cmd->count) { + printk("sdio<%6d><%3d>B_Rx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", cmd->count, i, cmd->tot_tc, + cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count, + cmd->tot_bytes, (cmd->tot_bytes/10)*13 / (cmd->tot_tc/10)); + } + } + + /* CMD53 Tx bytes + block mode */ + for (i=0; i<512; i++) { + cmd = &result->cmd53_tx_byte[i]; + if (cmd->count) { + printk("sdio<%6d><%3dB>_Tx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", cmd->count, i, cmd->tot_tc, + cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count, + cmd->tot_bytes, (cmd->tot_bytes/10)*13 / (cmd->tot_tc/10)); + } + } + for (i=0; i<100; i++) { + cmd = &result->cmd53_tx_blk[i]; + if (cmd->count) { + printk("sdio<%6d><%3d>B_Tx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", cmd->count, i, cmd->tot_tc, + cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count, + cmd->tot_bytes, (cmd->tot_bytes/10)*13 / (cmd->tot_tc/10)); + } + } + + printk("sdio === performance dump done ===\n"); +} + +//========= sdio command table =========== +void msdc_performance(u32 opcode, u32 sizes, u32 bRx, u32 ticks) +{ + struct sdio_profile* result = &sdio_perfomance; + struct cmd_profile* cmd; + u32 block; + + if (sdio_pro_enable == 0) { + return; + } + + if (opcode == 52) { + cmd = bRx ? &result->cmd52_rx : &result->cmd52_tx; + } else if (opcode == 53) { + if (sizes < 512) { + cmd = bRx ? &result->cmd53_rx_byte[sizes] : &result->cmd53_tx_byte[sizes]; + } else { + block = sizes / 512; + if (block >= 99) { + printk("cmd53 error blocks\n"); + while(1); + } + cmd = bRx ? &result->cmd53_rx_blk[block] : &result->cmd53_tx_blk[block]; + } + } else { + return; + } + + /* update the members */ + if (ticks > cmd->max_tc){ + cmd->max_tc = ticks; + } + if (cmd->min_tc == 0 || ticks < cmd->min_tc) { + cmd->min_tc = ticks; + } + cmd->tot_tc += ticks; + cmd->tot_bytes += sizes; + cmd->count ++; + + if (bRx) { + result->total_rx_bytes += sizes; + } else { + result->total_tx_bytes += sizes; + } + result->total_tc += ticks; + + /* dump when total_tc > 30s */ + if (result->total_tc >= sdio_pro_time * TICKS_ONE_MS * 1000) { + msdc_sdio_profile(result); + memset(result, 0 , sizeof(struct sdio_profile)); + } +} + +//========== driver proc interface =========== +static int msdc_debug_proc_read(struct seq_file *s, void *p) +{ + seq_printf(s, "\n=========================================\n"); + seq_printf(s, "Index<0> + Id + Zone\n"); + seq_printf(s, "-> PWR<9> WRN<8> | FIO<7> OPS<6> FUN<5> CFG<4> | INT<3> RSP<2> CMD<1> DMA<0>\n"); + seq_printf(s, "-> echo 0 3 0x3ff >msdc_bebug -> host[3] debug zone set to 0x3ff\n"); + seq_printf(s, "-> MSDC[0] Zone: 0x%.8x\n", sd_debug_zone[0]); + seq_printf(s, "-> MSDC[1] Zone: 0x%.8x\n", sd_debug_zone[1]); + seq_printf(s, "-> MSDC[2] Zone: 0x%.8x\n", sd_debug_zone[2]); + seq_printf(s, "-> MSDC[3] Zone: 0x%.8x\n", sd_debug_zone[3]); + + seq_printf(s, "Index<1> + ID:4|Mode:4 + DMA_SIZE\n"); + seq_printf(s, "-> 0)PIO 1)DMA 2)SIZE\n"); + seq_printf(s, "-> echo 1 22 0x200 >msdc_bebug -> host[2] size mode, dma when >= 512\n"); + seq_printf(s, "-> MSDC[0] mode<%d> size<%d>\n", drv_mode[0], dma_size[0]); + seq_printf(s, "-> MSDC[1] mode<%d> size<%d>\n", drv_mode[1], dma_size[1]); + seq_printf(s, "-> MSDC[2] mode<%d> size<%d>\n", drv_mode[2], dma_size[2]); + seq_printf(s, "-> MSDC[3] mode<%d> size<%d>\n", drv_mode[3], dma_size[3]); + + seq_printf(s, "Index<3> + SDIO_PROFILE + TIME\n"); + seq_printf(s, "-> echo 3 1 0x1E >msdc_bebug -> enable sdio_profile, 30s\n"); + seq_printf(s, "-> SDIO_PROFILE<%d> TIME<%ds>\n", sdio_pro_enable, sdio_pro_time); + seq_printf(s, "=========================================\n\n"); + + return 0; +} + +static ssize_t msdc_debug_proc_write(struct file *file, + const char __user *buf, size_t count, loff_t *data) +{ + int ret; + + int cmd, p1, p2; + int id, zone; + int mode, size; + + if (count == 0)return -1; + if(count > 255)count = 255; + + ret = copy_from_user(cmd_buf, buf, count); + if (ret < 0)return -1; + + cmd_buf[count] = '\0'; + printk("msdc Write %s\n", cmd_buf); + + sscanf(cmd_buf, "%x %x %x", &cmd, &p1, &p2); + + if(cmd == SD_TOOL_ZONE) { + id = p1; zone = p2; zone &= 0x3ff; + printk("msdc host_id<%d> zone<0x%.8x>\n", id, zone); + if(id >=0 && id<=3){ + sd_debug_zone[id] = zone; + } + else if(id == 4){ + sd_debug_zone[0] = sd_debug_zone[1] = zone; + sd_debug_zone[2] = sd_debug_zone[3] = zone; + } + else{ + printk("msdc host_id error when set debug zone\n"); + } + } else if (cmd == SD_TOOL_DMA_SIZE) { + id = p1>>4; mode = (p1&0xf); size = p2; + if(id >=0 && id<=3){ + drv_mode[id] = mode; + dma_size[id] = p2; + } + else if(id == 4){ + drv_mode[0] = drv_mode[1] = mode; + drv_mode[2] = drv_mode[3] = mode; + dma_size[0] = dma_size[1] = p2; + dma_size[2] = dma_size[3] = p2; + } + else{ + printk("msdc host_id error when select mode\n"); + } + } else if (cmd == SD_TOOL_SDIO_PROFILE) { + if (p1 == 1) { /* enable profile */ + if (gpt_enable == 0) { + // msdc_init_gpt(); /* --- by chhung */ + gpt_enable = 1; + } + sdio_pro_enable = 1; + if (p2 == 0) p2 = 1; if (p2 >= 30) p2 = 30; + sdio_pro_time = p2 ; + } else if (p1 == 0) { + /* todo */ + sdio_pro_enable = 0; + } + } + + return count; +} + +static int msdc_debug_show(struct inode *inode, struct file *file) +{ + return single_open(file, msdc_debug_proc_read, NULL); +} + +static const struct file_operations msdc_debug_fops = { + .owner = THIS_MODULE, + .open = msdc_debug_show, + .read = seq_read, + .write = msdc_debug_proc_write, + .llseek = seq_lseek, + .release = single_release, +}; + +int msdc_debug_proc_init(void) +{ + struct proc_dir_entry *de = proc_create("msdc_debug", 0667, NULL, &msdc_debug_fops); + + if (!de || IS_ERR(de)) + printk("!! Create MSDC debug PROC fail !!\n"); + + return 0 ; +} +EXPORT_SYMBOL_GPL(msdc_debug_proc_init); +#endif diff --git a/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/dbg.h b/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/dbg.h new file mode 100644 index 000000000..e58c43129 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/dbg.h @@ -0,0 +1,156 @@ +/* Copyright Statement: + * + * This software/firmware and related documentation ("MediaTek Software") are + * protected under relevant copyright laws. The information contained herein + * is confidential and proprietary to MediaTek Inc. and/or its licensors. + * Without the prior written permission of MediaTek inc. and/or its licensors, + * any reproduction, modification, use or disclosure of MediaTek Software, + * and information contained herein, in whole or in part, shall be strictly prohibited. + * + * MediaTek Inc. (C) 2010. All rights reserved. + * + * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON + * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE + * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR + * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH + * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES + * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES + * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK + * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR + * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND + * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, + * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, + * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO + * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * The following software/firmware and/or related documentation ("MediaTek Software") + * have been modified by MediaTek Inc. All revisions are subject to any receiver's + * applicable license agreements with MediaTek Inc. + */ +#ifndef __MT_MSDC_DEUBG__ +#define __MT_MSDC_DEUBG__ + +//========================== +extern u32 sdio_pro_enable; +/* for a type command, e.g. CMD53, 2 blocks */ +struct cmd_profile { + u32 max_tc; /* Max tick count */ + u32 min_tc; + u32 tot_tc; /* total tick count */ + u32 tot_bytes; + u32 count; /* the counts of the command */ +}; + +/* dump when total_tc and total_bytes */ +struct sdio_profile { + u32 total_tc; /* total tick count of CMD52 and CMD53 */ + u32 total_tx_bytes; /* total bytes of CMD53 Tx */ + u32 total_rx_bytes; /* total bytes of CMD53 Rx */ + + /*CMD52*/ + struct cmd_profile cmd52_tx; + struct cmd_profile cmd52_rx; + + /*CMD53 in byte unit */ + struct cmd_profile cmd53_tx_byte[512]; + struct cmd_profile cmd53_rx_byte[512]; + + /*CMD53 in block unit */ + struct cmd_profile cmd53_tx_blk[100]; + struct cmd_profile cmd53_rx_blk[100]; +}; + +//========================== +typedef enum { + SD_TOOL_ZONE = 0, + SD_TOOL_DMA_SIZE = 1, + SD_TOOL_PM_ENABLE = 2, + SD_TOOL_SDIO_PROFILE = 3, +} msdc_dbg; + +typedef enum { + MODE_PIO = 0, + MODE_DMA = 1, + MODE_SIZE_DEP = 2, +} msdc_mode; +extern msdc_mode drv_mode[4]; +extern u32 dma_size[4]; + +/* Debug message event */ +#define DBG_EVT_NONE (0) /* No event */ +#define DBG_EVT_DMA (1 << 0) /* DMA related event */ +#define DBG_EVT_CMD (1 << 1) /* MSDC CMD related event */ +#define DBG_EVT_RSP (1 << 2) /* MSDC CMD RSP related event */ +#define DBG_EVT_INT (1 << 3) /* MSDC INT event */ +#define DBG_EVT_CFG (1 << 4) /* MSDC CFG event */ +#define DBG_EVT_FUC (1 << 5) /* Function event */ +#define DBG_EVT_OPS (1 << 6) /* Read/Write operation event */ +#define DBG_EVT_FIO (1 << 7) /* FIFO operation event */ +#define DBG_EVT_WRN (1 << 8) /* Warning event */ +#define DBG_EVT_PWR (1 << 9) /* Power event */ +#define DBG_EVT_ALL (0xffffffff) + +#define DBG_EVT_MASK (DBG_EVT_ALL) + +extern unsigned int sd_debug_zone[4]; +#define TAG "msdc" +#if 0 /* +++ chhung */ +#define BUG_ON(x) \ +do { \ + if (x) { \ + printk("[BUG] %s LINE:%d FILE:%s\n", #x, __LINE__, __FILE__); \ + while(1); \ + } \ +}while(0) +#endif /* end of +++ */ + +#define N_MSG(evt, fmt, args...) +/* +do { \ + if ((DBG_EVT_##evt) & sd_debug_zone[host->id]) { \ + printk(KERN_ERR TAG"%d -> "fmt" <- %s() : L<%d> PID<%s><0x%x>\n", \ + host->id, ##args , __FUNCTION__, __LINE__, current->comm, current->pid); \ + } \ +} while(0) +*/ + +#define ERR_MSG(fmt, args...) \ +do { \ + printk(KERN_ERR TAG"%d -> "fmt" <- %s() : L<%d> PID<%s><0x%x>\n", \ + host->id, ##args , __FUNCTION__, __LINE__, current->comm, current->pid); \ +} while(0); + +#if 1 +//defined CONFIG_MTK_MMC_CD_POLL +#define INIT_MSG(fmt, args...) +#define IRQ_MSG(fmt, args...) +#else +#define INIT_MSG(fmt, args...) \ +do { \ + printk(KERN_ERR TAG"%d -> "fmt" <- %s() : L<%d> PID<%s><0x%x>\n", \ + host->id, ##args , __FUNCTION__, __LINE__, current->comm, current->pid); \ +} while(0); + +/* PID in ISR in not corrent */ +#define IRQ_MSG(fmt, args...) \ +do { \ + printk(KERN_ERR TAG"%d -> "fmt" <- %s() : L<%d>\n", \ + host->id, ##args , __FUNCTION__, __LINE__); \ +} while(0); +#endif + +int msdc_debug_proc_init(void); + +#if 0 /* --- chhung */ +void msdc_init_gpt(void); +extern void GPT_GetCounter64(UINT32 *cntL32, UINT32 *cntH32); +#endif /* end of --- */ +u32 msdc_time_calc(u32 old_L32, u32 old_H32, u32 new_L32, u32 new_H32); +void msdc_performance(u32 opcode, u32 sizes, u32 bRx, u32 ticks); + +#endif diff --git a/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/mt6575_sd.h b/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/mt6575_sd.h new file mode 100644 index 000000000..bb1f60ee5 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/mt6575_sd.h @@ -0,0 +1,1002 @@ +/* Copyright Statement: + * + * This software/firmware and related documentation ("MediaTek Software") are + * protected under relevant copyright laws. The information contained herein + * is confidential and proprietary to MediaTek Inc. and/or its licensors. + * Without the prior written permission of MediaTek inc. and/or its licensors, + * any reproduction, modification, use or disclosure of MediaTek Software, + * and information contained herein, in whole or in part, shall be strictly prohibited. + */ +/* MediaTek Inc. (C) 2010. All rights reserved. + * + * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON + * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE + * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR + * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH + * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES + * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES + * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK + * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR + * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND + * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, + * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, + * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO + * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * The following software/firmware and/or related documentation ("MediaTek Software") + * have been modified by MediaTek Inc. All revisions are subject to any receiver's + * applicable license agreements with MediaTek Inc. + */ + +#ifndef MT6575_SD_H +#define MT6575_SD_H + +#include +#include +#include + +// #include /* --- by chhung */ + +/*--------------------------------------------------------------------------*/ +/* Common Macro */ +/*--------------------------------------------------------------------------*/ +#define REG_ADDR(x) ((volatile u32*)(base + OFFSET_##x)) + +/*--------------------------------------------------------------------------*/ +/* Common Definition */ +/*--------------------------------------------------------------------------*/ +#define MSDC_FIFO_SZ (128) +#define MSDC_FIFO_THD (64) // (128) +#define MSDC_NUM (4) + +#define MSDC_MS (0) +#define MSDC_SDMMC (1) + +#define MSDC_MODE_UNKNOWN (0) +#define MSDC_MODE_PIO (1) +#define MSDC_MODE_DMA_BASIC (2) +#define MSDC_MODE_DMA_DESC (3) +#define MSDC_MODE_DMA_ENHANCED (4) +#define MSDC_MODE_MMC_STREAM (5) + +#define MSDC_BUS_1BITS (0) +#define MSDC_BUS_4BITS (1) +#define MSDC_BUS_8BITS (2) + +#define MSDC_BRUST_8B (3) +#define MSDC_BRUST_16B (4) +#define MSDC_BRUST_32B (5) +#define MSDC_BRUST_64B (6) + +#define MSDC_PIN_PULL_NONE (0) +#define MSDC_PIN_PULL_DOWN (1) +#define MSDC_PIN_PULL_UP (2) +#define MSDC_PIN_KEEP (3) + +#define MSDC_MAX_SCLK (48000000) /* +/- by chhung */ +#define MSDC_MIN_SCLK (260000) + +#define MSDC_AUTOCMD12 (0x0001) +#define MSDC_AUTOCMD23 (0x0002) +#define MSDC_AUTOCMD19 (0x0003) + +#define MSDC_EMMC_BOOTMODE0 (0) /* Pull low CMD mode */ +#define MSDC_EMMC_BOOTMODE1 (1) /* Reset CMD mode */ + +enum { + RESP_NONE = 0, + RESP_R1, + RESP_R2, + RESP_R3, + RESP_R4, + RESP_R5, + RESP_R6, + RESP_R7, + RESP_R1B +}; + +/*--------------------------------------------------------------------------*/ +/* Register Offset */ +/*--------------------------------------------------------------------------*/ +#define OFFSET_MSDC_CFG (0x0) +#define OFFSET_MSDC_IOCON (0x04) +#define OFFSET_MSDC_PS (0x08) +#define OFFSET_MSDC_INT (0x0c) +#define OFFSET_MSDC_INTEN (0x10) +#define OFFSET_MSDC_FIFOCS (0x14) +#define OFFSET_MSDC_TXDATA (0x18) +#define OFFSET_MSDC_RXDATA (0x1c) +#define OFFSET_SDC_CFG (0x30) +#define OFFSET_SDC_CMD (0x34) +#define OFFSET_SDC_ARG (0x38) +#define OFFSET_SDC_STS (0x3c) +#define OFFSET_SDC_RESP0 (0x40) +#define OFFSET_SDC_RESP1 (0x44) +#define OFFSET_SDC_RESP2 (0x48) +#define OFFSET_SDC_RESP3 (0x4c) +#define OFFSET_SDC_BLK_NUM (0x50) +#define OFFSET_SDC_CSTS (0x58) +#define OFFSET_SDC_CSTS_EN (0x5c) +#define OFFSET_SDC_DCRC_STS (0x60) +#define OFFSET_EMMC_CFG0 (0x70) +#define OFFSET_EMMC_CFG1 (0x74) +#define OFFSET_EMMC_STS (0x78) +#define OFFSET_EMMC_IOCON (0x7c) +#define OFFSET_SDC_ACMD_RESP (0x80) +#define OFFSET_SDC_ACMD19_TRG (0x84) +#define OFFSET_SDC_ACMD19_STS (0x88) +#define OFFSET_MSDC_DMA_SA (0x90) +#define OFFSET_MSDC_DMA_CA (0x94) +#define OFFSET_MSDC_DMA_CTRL (0x98) +#define OFFSET_MSDC_DMA_CFG (0x9c) +#define OFFSET_MSDC_DBG_SEL (0xa0) +#define OFFSET_MSDC_DBG_OUT (0xa4) +#define OFFSET_MSDC_PATCH_BIT (0xb0) +#define OFFSET_MSDC_PATCH_BIT1 (0xb4) +#define OFFSET_MSDC_PAD_CTL0 (0xe0) +#define OFFSET_MSDC_PAD_CTL1 (0xe4) +#define OFFSET_MSDC_PAD_CTL2 (0xe8) +#define OFFSET_MSDC_PAD_TUNE (0xec) +#define OFFSET_MSDC_DAT_RDDLY0 (0xf0) +#define OFFSET_MSDC_DAT_RDDLY1 (0xf4) +#define OFFSET_MSDC_HW_DBG (0xf8) +#define OFFSET_MSDC_VERSION (0x100) +#define OFFSET_MSDC_ECO_VER (0x104) + +/*--------------------------------------------------------------------------*/ +/* Register Address */ +/*--------------------------------------------------------------------------*/ + +/* common register */ +#define MSDC_CFG REG_ADDR(MSDC_CFG) +#define MSDC_IOCON REG_ADDR(MSDC_IOCON) +#define MSDC_PS REG_ADDR(MSDC_PS) +#define MSDC_INT REG_ADDR(MSDC_INT) +#define MSDC_INTEN REG_ADDR(MSDC_INTEN) +#define MSDC_FIFOCS REG_ADDR(MSDC_FIFOCS) +#define MSDC_TXDATA REG_ADDR(MSDC_TXDATA) +#define MSDC_RXDATA REG_ADDR(MSDC_RXDATA) +#define MSDC_PATCH_BIT0 REG_ADDR(MSDC_PATCH_BIT) + +/* sdmmc register */ +#define SDC_CFG REG_ADDR(SDC_CFG) +#define SDC_CMD REG_ADDR(SDC_CMD) +#define SDC_ARG REG_ADDR(SDC_ARG) +#define SDC_STS REG_ADDR(SDC_STS) +#define SDC_RESP0 REG_ADDR(SDC_RESP0) +#define SDC_RESP1 REG_ADDR(SDC_RESP1) +#define SDC_RESP2 REG_ADDR(SDC_RESP2) +#define SDC_RESP3 REG_ADDR(SDC_RESP3) +#define SDC_BLK_NUM REG_ADDR(SDC_BLK_NUM) +#define SDC_CSTS REG_ADDR(SDC_CSTS) +#define SDC_CSTS_EN REG_ADDR(SDC_CSTS_EN) +#define SDC_DCRC_STS REG_ADDR(SDC_DCRC_STS) + +/* emmc register*/ +#define EMMC_CFG0 REG_ADDR(EMMC_CFG0) +#define EMMC_CFG1 REG_ADDR(EMMC_CFG1) +#define EMMC_STS REG_ADDR(EMMC_STS) +#define EMMC_IOCON REG_ADDR(EMMC_IOCON) + +/* auto command register */ +#define SDC_ACMD_RESP REG_ADDR(SDC_ACMD_RESP) +#define SDC_ACMD19_TRG REG_ADDR(SDC_ACMD19_TRG) +#define SDC_ACMD19_STS REG_ADDR(SDC_ACMD19_STS) + +/* dma register */ +#define MSDC_DMA_SA REG_ADDR(MSDC_DMA_SA) +#define MSDC_DMA_CA REG_ADDR(MSDC_DMA_CA) +#define MSDC_DMA_CTRL REG_ADDR(MSDC_DMA_CTRL) +#define MSDC_DMA_CFG REG_ADDR(MSDC_DMA_CFG) + +/* pad ctrl register */ +#define MSDC_PAD_CTL0 REG_ADDR(MSDC_PAD_CTL0) +#define MSDC_PAD_CTL1 REG_ADDR(MSDC_PAD_CTL1) +#define MSDC_PAD_CTL2 REG_ADDR(MSDC_PAD_CTL2) + +/* data read delay */ +#define MSDC_DAT_RDDLY0 REG_ADDR(MSDC_DAT_RDDLY0) +#define MSDC_DAT_RDDLY1 REG_ADDR(MSDC_DAT_RDDLY1) + +/* debug register */ +#define MSDC_DBG_SEL REG_ADDR(MSDC_DBG_SEL) +#define MSDC_DBG_OUT REG_ADDR(MSDC_DBG_OUT) + +/* misc register */ +#define MSDC_PATCH_BIT REG_ADDR(MSDC_PATCH_BIT) +#define MSDC_PATCH_BIT1 REG_ADDR(MSDC_PATCH_BIT1) +#define MSDC_PAD_TUNE REG_ADDR(MSDC_PAD_TUNE) +#define MSDC_HW_DBG REG_ADDR(MSDC_HW_DBG) +#define MSDC_VERSION REG_ADDR(MSDC_VERSION) +#define MSDC_ECO_VER REG_ADDR(MSDC_ECO_VER) /* ECO Version */ + +/*--------------------------------------------------------------------------*/ +/* Register Mask */ +/*--------------------------------------------------------------------------*/ + +/* MSDC_CFG mask */ +#define MSDC_CFG_MODE (0x1 << 0) /* RW */ +#define MSDC_CFG_CKPDN (0x1 << 1) /* RW */ +#define MSDC_CFG_RST (0x1 << 2) /* RW */ +#define MSDC_CFG_PIO (0x1 << 3) /* RW */ +#define MSDC_CFG_CKDRVEN (0x1 << 4) /* RW */ +#define MSDC_CFG_BV18SDT (0x1 << 5) /* RW */ +#define MSDC_CFG_BV18PSS (0x1 << 6) /* R */ +#define MSDC_CFG_CKSTB (0x1 << 7) /* R */ +#define MSDC_CFG_CKDIV (0xff << 8) /* RW */ +#define MSDC_CFG_CKMOD (0x3 << 16) /* RW */ + +/* MSDC_IOCON mask */ +#define MSDC_IOCON_SDR104CKS (0x1 << 0) /* RW */ +#define MSDC_IOCON_RSPL (0x1 << 1) /* RW */ +#define MSDC_IOCON_DSPL (0x1 << 2) /* RW */ +#define MSDC_IOCON_DDLSEL (0x1 << 3) /* RW */ +#define MSDC_IOCON_DDR50CKD (0x1 << 4) /* RW */ +#define MSDC_IOCON_DSPLSEL (0x1 << 5) /* RW */ +#define MSDC_IOCON_D0SPL (0x1 << 16) /* RW */ +#define MSDC_IOCON_D1SPL (0x1 << 17) /* RW */ +#define MSDC_IOCON_D2SPL (0x1 << 18) /* RW */ +#define MSDC_IOCON_D3SPL (0x1 << 19) /* RW */ +#define MSDC_IOCON_D4SPL (0x1 << 20) /* RW */ +#define MSDC_IOCON_D5SPL (0x1 << 21) /* RW */ +#define MSDC_IOCON_D6SPL (0x1 << 22) /* RW */ +#define MSDC_IOCON_D7SPL (0x1 << 23) /* RW */ +#define MSDC_IOCON_RISCSZ (0x3 << 24) /* RW */ + +/* MSDC_PS mask */ +#define MSDC_PS_CDEN (0x1 << 0) /* RW */ +#define MSDC_PS_CDSTS (0x1 << 1) /* R */ +#define MSDC_PS_CDDEBOUNCE (0xf << 12) /* RW */ +#define MSDC_PS_DAT (0xff << 16) /* R */ +#define MSDC_PS_CMD (0x1 << 24) /* R */ +#define MSDC_PS_WP (0x1UL<< 31) /* R */ + +/* MSDC_INT mask */ +#define MSDC_INT_MMCIRQ (0x1 << 0) /* W1C */ +#define MSDC_INT_CDSC (0x1 << 1) /* W1C */ +#define MSDC_INT_ACMDRDY (0x1 << 3) /* W1C */ +#define MSDC_INT_ACMDTMO (0x1 << 4) /* W1C */ +#define MSDC_INT_ACMDCRCERR (0x1 << 5) /* W1C */ +#define MSDC_INT_DMAQ_EMPTY (0x1 << 6) /* W1C */ +#define MSDC_INT_SDIOIRQ (0x1 << 7) /* W1C */ +#define MSDC_INT_CMDRDY (0x1 << 8) /* W1C */ +#define MSDC_INT_CMDTMO (0x1 << 9) /* W1C */ +#define MSDC_INT_RSPCRCERR (0x1 << 10) /* W1C */ +#define MSDC_INT_CSTA (0x1 << 11) /* R */ +#define MSDC_INT_XFER_COMPL (0x1 << 12) /* W1C */ +#define MSDC_INT_DXFER_DONE (0x1 << 13) /* W1C */ +#define MSDC_INT_DATTMO (0x1 << 14) /* W1C */ +#define MSDC_INT_DATCRCERR (0x1 << 15) /* W1C */ +#define MSDC_INT_ACMD19_DONE (0x1 << 16) /* W1C */ + +/* MSDC_INTEN mask */ +#define MSDC_INTEN_MMCIRQ (0x1 << 0) /* RW */ +#define MSDC_INTEN_CDSC (0x1 << 1) /* RW */ +#define MSDC_INTEN_ACMDRDY (0x1 << 3) /* RW */ +#define MSDC_INTEN_ACMDTMO (0x1 << 4) /* RW */ +#define MSDC_INTEN_ACMDCRCERR (0x1 << 5) /* RW */ +#define MSDC_INTEN_DMAQ_EMPTY (0x1 << 6) /* RW */ +#define MSDC_INTEN_SDIOIRQ (0x1 << 7) /* RW */ +#define MSDC_INTEN_CMDRDY (0x1 << 8) /* RW */ +#define MSDC_INTEN_CMDTMO (0x1 << 9) /* RW */ +#define MSDC_INTEN_RSPCRCERR (0x1 << 10) /* RW */ +#define MSDC_INTEN_CSTA (0x1 << 11) /* RW */ +#define MSDC_INTEN_XFER_COMPL (0x1 << 12) /* RW */ +#define MSDC_INTEN_DXFER_DONE (0x1 << 13) /* RW */ +#define MSDC_INTEN_DATTMO (0x1 << 14) /* RW */ +#define MSDC_INTEN_DATCRCERR (0x1 << 15) /* RW */ +#define MSDC_INTEN_ACMD19_DONE (0x1 << 16) /* RW */ + +/* MSDC_FIFOCS mask */ +#define MSDC_FIFOCS_RXCNT (0xff << 0) /* R */ +#define MSDC_FIFOCS_TXCNT (0xff << 16) /* R */ +#define MSDC_FIFOCS_CLR (0x1UL<< 31) /* RW */ + +/* SDC_CFG mask */ +#define SDC_CFG_SDIOINTWKUP (0x1 << 0) /* RW */ +#define SDC_CFG_INSWKUP (0x1 << 1) /* RW */ +#define SDC_CFG_BUSWIDTH (0x3 << 16) /* RW */ +#define SDC_CFG_SDIO (0x1 << 19) /* RW */ +#define SDC_CFG_SDIOIDE (0x1 << 20) /* RW */ +#define SDC_CFG_INTATGAP (0x1 << 21) /* RW */ +#define SDC_CFG_DTOC (0xffUL << 24) /* RW */ + +/* SDC_CMD mask */ +#define SDC_CMD_OPC (0x3f << 0) /* RW */ +#define SDC_CMD_BRK (0x1 << 6) /* RW */ +#define SDC_CMD_RSPTYP (0x7 << 7) /* RW */ +#define SDC_CMD_DTYP (0x3 << 11) /* RW */ +#define SDC_CMD_DTYP (0x3 << 11) /* RW */ +#define SDC_CMD_RW (0x1 << 13) /* RW */ +#define SDC_CMD_STOP (0x1 << 14) /* RW */ +#define SDC_CMD_GOIRQ (0x1 << 15) /* RW */ +#define SDC_CMD_BLKLEN (0xfff<< 16) /* RW */ +#define SDC_CMD_AUTOCMD (0x3 << 28) /* RW */ +#define SDC_CMD_VOLSWTH (0x1 << 30) /* RW */ + +/* SDC_STS mask */ +#define SDC_STS_SDCBUSY (0x1 << 0) /* RW */ +#define SDC_STS_CMDBUSY (0x1 << 1) /* RW */ +#define SDC_STS_SWR_COMPL (0x1 << 31) /* RW */ + +/* SDC_DCRC_STS mask */ +#define SDC_DCRC_STS_NEG (0xf << 8) /* RO */ +#define SDC_DCRC_STS_POS (0xff << 0) /* RO */ + +/* EMMC_CFG0 mask */ +#define EMMC_CFG0_BOOTSTART (0x1 << 0) /* W */ +#define EMMC_CFG0_BOOTSTOP (0x1 << 1) /* W */ +#define EMMC_CFG0_BOOTMODE (0x1 << 2) /* RW */ +#define EMMC_CFG0_BOOTACKDIS (0x1 << 3) /* RW */ +#define EMMC_CFG0_BOOTWDLY (0x7 << 12) /* RW */ +#define EMMC_CFG0_BOOTSUPP (0x1 << 15) /* RW */ + +/* EMMC_CFG1 mask */ +#define EMMC_CFG1_BOOTDATTMC (0xfffff << 0) /* RW */ +#define EMMC_CFG1_BOOTACKTMC (0xfffUL << 20) /* RW */ + +/* EMMC_STS mask */ +#define EMMC_STS_BOOTCRCERR (0x1 << 0) /* W1C */ +#define EMMC_STS_BOOTACKERR (0x1 << 1) /* W1C */ +#define EMMC_STS_BOOTDATTMO (0x1 << 2) /* W1C */ +#define EMMC_STS_BOOTACKTMO (0x1 << 3) /* W1C */ +#define EMMC_STS_BOOTUPSTATE (0x1 << 4) /* R */ +#define EMMC_STS_BOOTACKRCV (0x1 << 5) /* W1C */ +#define EMMC_STS_BOOTDATRCV (0x1 << 6) /* R */ + +/* EMMC_IOCON mask */ +#define EMMC_IOCON_BOOTRST (0x1 << 0) /* RW */ + +/* SDC_ACMD19_TRG mask */ +#define SDC_ACMD19_TRG_TUNESEL (0xf << 0) /* RW */ + +/* MSDC_DMA_CTRL mask */ +#define MSDC_DMA_CTRL_START (0x1 << 0) /* W */ +#define MSDC_DMA_CTRL_STOP (0x1 << 1) /* W */ +#define MSDC_DMA_CTRL_RESUME (0x1 << 2) /* W */ +#define MSDC_DMA_CTRL_MODE (0x1 << 8) /* RW */ +#define MSDC_DMA_CTRL_LASTBUF (0x1 << 10) /* RW */ +#define MSDC_DMA_CTRL_BRUSTSZ (0x7 << 12) /* RW */ +#define MSDC_DMA_CTRL_XFERSZ (0xffffUL << 16)/* RW */ + +/* MSDC_DMA_CFG mask */ +#define MSDC_DMA_CFG_STS (0x1 << 0) /* R */ +#define MSDC_DMA_CFG_DECSEN (0x1 << 1) /* RW */ +#define MSDC_DMA_CFG_BDCSERR (0x1 << 4) /* R */ +#define MSDC_DMA_CFG_GPDCSERR (0x1 << 5) /* R */ + +/* MSDC_PATCH_BIT mask */ +#define MSDC_PATCH_BIT_WFLSMODE (0x1 << 0) /* RW */ +#define MSDC_PATCH_BIT_ODDSUPP (0x1 << 1) /* RW */ +#define MSDC_PATCH_BIT_CKGEN_CK (0x1 << 6) /* E2: Fixed to 1 */ +#define MSDC_PATCH_BIT_IODSSEL (0x1 << 16) /* RW */ +#define MSDC_PATCH_BIT_IOINTSEL (0x1 << 17) /* RW */ +#define MSDC_PATCH_BIT_BUSYDLY (0xf << 18) /* RW */ +#define MSDC_PATCH_BIT_WDOD (0xf << 22) /* RW */ +#define MSDC_PATCH_BIT_IDRTSEL (0x1 << 26) /* RW */ +#define MSDC_PATCH_BIT_CMDFSEL (0x1 << 27) /* RW */ +#define MSDC_PATCH_BIT_INTDLSEL (0x1 << 28) /* RW */ +#define MSDC_PATCH_BIT_SPCPUSH (0x1 << 29) /* RW */ +#define MSDC_PATCH_BIT_DECRCTMO (0x1 << 30) /* RW */ + +/* MSDC_PATCH_BIT1 mask */ +#define MSDC_PATCH_BIT1_WRDAT_CRCS (0x7 << 3) +#define MSDC_PATCH_BIT1_CMD_RSP (0x7 << 0) + +/* MSDC_PAD_CTL0 mask */ +#define MSDC_PAD_CTL0_CLKDRVN (0x7 << 0) /* RW */ +#define MSDC_PAD_CTL0_CLKDRVP (0x7 << 4) /* RW */ +#define MSDC_PAD_CTL0_CLKSR (0x1 << 8) /* RW */ +#define MSDC_PAD_CTL0_CLKPD (0x1 << 16) /* RW */ +#define MSDC_PAD_CTL0_CLKPU (0x1 << 17) /* RW */ +#define MSDC_PAD_CTL0_CLKSMT (0x1 << 18) /* RW */ +#define MSDC_PAD_CTL0_CLKIES (0x1 << 19) /* RW */ +#define MSDC_PAD_CTL0_CLKTDSEL (0xf << 20) /* RW */ +#define MSDC_PAD_CTL0_CLKRDSEL (0xffUL<< 24) /* RW */ + +/* MSDC_PAD_CTL1 mask */ +#define MSDC_PAD_CTL1_CMDDRVN (0x7 << 0) /* RW */ +#define MSDC_PAD_CTL1_CMDDRVP (0x7 << 4) /* RW */ +#define MSDC_PAD_CTL1_CMDSR (0x1 << 8) /* RW */ +#define MSDC_PAD_CTL1_CMDPD (0x1 << 16) /* RW */ +#define MSDC_PAD_CTL1_CMDPU (0x1 << 17) /* RW */ +#define MSDC_PAD_CTL1_CMDSMT (0x1 << 18) /* RW */ +#define MSDC_PAD_CTL1_CMDIES (0x1 << 19) /* RW */ +#define MSDC_PAD_CTL1_CMDTDSEL (0xf << 20) /* RW */ +#define MSDC_PAD_CTL1_CMDRDSEL (0xffUL<< 24) /* RW */ + +/* MSDC_PAD_CTL2 mask */ +#define MSDC_PAD_CTL2_DATDRVN (0x7 << 0) /* RW */ +#define MSDC_PAD_CTL2_DATDRVP (0x7 << 4) /* RW */ +#define MSDC_PAD_CTL2_DATSR (0x1 << 8) /* RW */ +#define MSDC_PAD_CTL2_DATPD (0x1 << 16) /* RW */ +#define MSDC_PAD_CTL2_DATPU (0x1 << 17) /* RW */ +#define MSDC_PAD_CTL2_DATIES (0x1 << 19) /* RW */ +#define MSDC_PAD_CTL2_DATSMT (0x1 << 18) /* RW */ +#define MSDC_PAD_CTL2_DATTDSEL (0xf << 20) /* RW */ +#define MSDC_PAD_CTL2_DATRDSEL (0xffUL<< 24) /* RW */ + +/* MSDC_PAD_TUNE mask */ +#define MSDC_PAD_TUNE_DATWRDLY (0x1F << 0) /* RW */ +#define MSDC_PAD_TUNE_DATRRDLY (0x1F << 8) /* RW */ +#define MSDC_PAD_TUNE_CMDRDLY (0x1F << 16) /* RW */ +#define MSDC_PAD_TUNE_CMDRRDLY (0x1FUL << 22) /* RW */ +#define MSDC_PAD_TUNE_CLKTXDLY (0x1FUL << 27) /* RW */ + +/* MSDC_DAT_RDDLY0/1 mask */ +#define MSDC_DAT_RDDLY0_D0 (0x1F << 0) /* RW */ +#define MSDC_DAT_RDDLY0_D1 (0x1F << 8) /* RW */ +#define MSDC_DAT_RDDLY0_D2 (0x1F << 16) /* RW */ +#define MSDC_DAT_RDDLY0_D3 (0x1F << 24) /* RW */ + +#define MSDC_DAT_RDDLY1_D4 (0x1F << 0) /* RW */ +#define MSDC_DAT_RDDLY1_D5 (0x1F << 8) /* RW */ +#define MSDC_DAT_RDDLY1_D6 (0x1F << 16) /* RW */ +#define MSDC_DAT_RDDLY1_D7 (0x1F << 24) /* RW */ + +#define MSDC_CKGEN_MSDC_DLY_SEL (0x1F<<10) +#define MSDC_INT_DAT_LATCH_CK_SEL (0x7<<7) +#define MSDC_CKGEN_MSDC_CK_SEL (0x1<<6) +#define CARD_READY_FOR_DATA (1<<8) +#define CARD_CURRENT_STATE(x) ((x&0x00001E00)>>9) + +/*--------------------------------------------------------------------------*/ +/* Descriptor Structure */ +/*--------------------------------------------------------------------------*/ +typedef struct { + u32 hwo:1; /* could be changed by hw */ + u32 bdp:1; + u32 rsv0:6; + u32 chksum:8; + u32 intr:1; + u32 rsv1:15; + void *next; + void *ptr; + u32 buflen:16; + u32 extlen:8; + u32 rsv2:8; + u32 arg; + u32 blknum; + u32 cmd; +} gpd_t; + +typedef struct { + u32 eol:1; + u32 rsv0:7; + u32 chksum:8; + u32 rsv1:1; + u32 blkpad:1; + u32 dwpad:1; + u32 rsv2:13; + void *next; + void *ptr; + u32 buflen:16; + u32 rsv3:16; +} bd_t; + +/*--------------------------------------------------------------------------*/ +/* Register Debugging Structure */ +/*--------------------------------------------------------------------------*/ + +typedef struct { + u32 msdc:1; + u32 ckpwn:1; + u32 rst:1; + u32 pio:1; + u32 ckdrven:1; + u32 start18v:1; + u32 pass18v:1; + u32 ckstb:1; + u32 ckdiv:8; + u32 ckmod:2; + u32 pad:14; +} msdc_cfg_reg; +typedef struct { + u32 sdr104cksel:1; + u32 rsmpl:1; + u32 dsmpl:1; + u32 ddlysel:1; + u32 ddr50ckd:1; + u32 dsplsel:1; + u32 pad1:10; + u32 d0spl:1; + u32 d1spl:1; + u32 d2spl:1; + u32 d3spl:1; + u32 d4spl:1; + u32 d5spl:1; + u32 d6spl:1; + u32 d7spl:1; + u32 riscsz:1; + u32 pad2:7; +} msdc_iocon_reg; +typedef struct { + u32 cden:1; + u32 cdsts:1; + u32 pad1:10; + u32 cddebounce:4; + u32 dat:8; + u32 cmd:1; + u32 pad2:6; + u32 wp:1; +} msdc_ps_reg; +typedef struct { + u32 mmcirq:1; + u32 cdsc:1; + u32 pad1:1; + u32 atocmdrdy:1; + u32 atocmdtmo:1; + u32 atocmdcrc:1; + u32 dmaqempty:1; + u32 sdioirq:1; + u32 cmdrdy:1; + u32 cmdtmo:1; + u32 rspcrc:1; + u32 csta:1; + u32 xfercomp:1; + u32 dxferdone:1; + u32 dattmo:1; + u32 datcrc:1; + u32 atocmd19done:1; + u32 pad2:15; +} msdc_int_reg; +typedef struct { + u32 mmcirq:1; + u32 cdsc:1; + u32 pad1:1; + u32 atocmdrdy:1; + u32 atocmdtmo:1; + u32 atocmdcrc:1; + u32 dmaqempty:1; + u32 sdioirq:1; + u32 cmdrdy:1; + u32 cmdtmo:1; + u32 rspcrc:1; + u32 csta:1; + u32 xfercomp:1; + u32 dxferdone:1; + u32 dattmo:1; + u32 datcrc:1; + u32 atocmd19done:1; + u32 pad2:15; +} msdc_inten_reg; +typedef struct { + u32 rxcnt:8; + u32 pad1:8; + u32 txcnt:8; + u32 pad2:7; + u32 clr:1; +} msdc_fifocs_reg; +typedef struct { + u32 val; +} msdc_txdat_reg; +typedef struct { + u32 val; +} msdc_rxdat_reg; +typedef struct { + u32 sdiowkup:1; + u32 inswkup:1; + u32 pad1:14; + u32 buswidth:2; + u32 pad2:1; + u32 sdio:1; + u32 sdioide:1; + u32 intblkgap:1; + u32 pad4:2; + u32 dtoc:8; +} sdc_cfg_reg; +typedef struct { + u32 cmd:6; + u32 brk:1; + u32 rsptyp:3; + u32 pad1:1; + u32 dtype:2; + u32 rw:1; + u32 stop:1; + u32 goirq:1; + u32 blklen:12; + u32 atocmd:2; + u32 volswth:1; + u32 pad2:1; +} sdc_cmd_reg; +typedef struct { + u32 arg; +} sdc_arg_reg; +typedef struct { + u32 sdcbusy:1; + u32 cmdbusy:1; + u32 pad:29; + u32 swrcmpl:1; +} sdc_sts_reg; +typedef struct { + u32 val; +} sdc_resp0_reg; +typedef struct { + u32 val; +} sdc_resp1_reg; +typedef struct { + u32 val; +} sdc_resp2_reg; +typedef struct { + u32 val; +} sdc_resp3_reg; +typedef struct { + u32 num; +} sdc_blknum_reg; +typedef struct { + u32 sts; +} sdc_csts_reg; +typedef struct { + u32 sts; +} sdc_cstsen_reg; +typedef struct { + u32 datcrcsts:8; + u32 ddrcrcsts:4; + u32 pad:20; +} sdc_datcrcsts_reg; +typedef struct { + u32 bootstart:1; + u32 bootstop:1; + u32 bootmode:1; + u32 pad1:9; + u32 bootwaidly:3; + u32 bootsupp:1; + u32 pad2:16; +} emmc_cfg0_reg; +typedef struct { + u32 bootcrctmc:16; + u32 pad:4; + u32 bootacktmc:12; +} emmc_cfg1_reg; +typedef struct { + u32 bootcrcerr:1; + u32 bootackerr:1; + u32 bootdattmo:1; + u32 bootacktmo:1; + u32 bootupstate:1; + u32 bootackrcv:1; + u32 bootdatrcv:1; + u32 pad:25; +} emmc_sts_reg; +typedef struct { + u32 bootrst:1; + u32 pad:31; +} emmc_iocon_reg; +typedef struct { + u32 val; +} msdc_acmd_resp_reg; +typedef struct { + u32 tunesel:4; + u32 pad:28; +} msdc_acmd19_trg_reg; +typedef struct { + u32 val; +} msdc_acmd19_sts_reg; +typedef struct { + u32 addr; +} msdc_dma_sa_reg; +typedef struct { + u32 addr; +} msdc_dma_ca_reg; +typedef struct { + u32 start:1; + u32 stop:1; + u32 resume:1; + u32 pad1:5; + u32 mode:1; + u32 pad2:1; + u32 lastbuf:1; + u32 pad3:1; + u32 brustsz:3; + u32 pad4:1; + u32 xfersz:16; +} msdc_dma_ctrl_reg; +typedef struct { + u32 status:1; + u32 decsen:1; + u32 pad1:2; + u32 bdcsen:1; + u32 gpdcsen:1; + u32 pad2:26; +} msdc_dma_cfg_reg; +typedef struct { + u32 sel:16; + u32 pad2:16; +} msdc_dbg_sel_reg; +typedef struct { + u32 val; +} msdc_dbg_out_reg; +typedef struct { + u32 clkdrvn:3; + u32 rsv0:1; + u32 clkdrvp:3; + u32 rsv1:1; + u32 clksr:1; + u32 rsv2:7; + u32 clkpd:1; + u32 clkpu:1; + u32 clksmt:1; + u32 clkies:1; + u32 clktdsel:4; + u32 clkrdsel:8; +} msdc_pad_ctl0_reg; +typedef struct { + u32 cmddrvn:3; + u32 rsv0:1; + u32 cmddrvp:3; + u32 rsv1:1; + u32 cmdsr:1; + u32 rsv2:7; + u32 cmdpd:1; + u32 cmdpu:1; + u32 cmdsmt:1; + u32 cmdies:1; + u32 cmdtdsel:4; + u32 cmdrdsel:8; +} msdc_pad_ctl1_reg; +typedef struct { + u32 datdrvn:3; + u32 rsv0:1; + u32 datdrvp:3; + u32 rsv1:1; + u32 datsr:1; + u32 rsv2:7; + u32 datpd:1; + u32 datpu:1; + u32 datsmt:1; + u32 daties:1; + u32 dattdsel:4; + u32 datrdsel:8; +} msdc_pad_ctl2_reg; +typedef struct { + u32 wrrxdly:3; + u32 pad1:5; + u32 rdrxdly:8; + u32 pad2:16; +} msdc_pad_tune_reg; +typedef struct { + u32 dat0:5; + u32 rsv0:3; + u32 dat1:5; + u32 rsv1:3; + u32 dat2:5; + u32 rsv2:3; + u32 dat3:5; + u32 rsv3:3; +} msdc_dat_rddly0; +typedef struct { + u32 dat4:5; + u32 rsv4:3; + u32 dat5:5; + u32 rsv5:3; + u32 dat6:5; + u32 rsv6:3; + u32 dat7:5; + u32 rsv7:3; +} msdc_dat_rddly1; +typedef struct { + u32 dbg0sel:8; + u32 dbg1sel:6; + u32 pad1:2; + u32 dbg2sel:6; + u32 pad2:2; + u32 dbg3sel:6; + u32 pad3:2; +} msdc_hw_dbg_reg; +typedef struct { + u32 val; +} msdc_version_reg; +typedef struct { + u32 val; +} msdc_eco_ver_reg; + +struct msdc_regs { + msdc_cfg_reg msdc_cfg; /* base+0x00h */ + msdc_iocon_reg msdc_iocon; /* base+0x04h */ + msdc_ps_reg msdc_ps; /* base+0x08h */ + msdc_int_reg msdc_int; /* base+0x0ch */ + msdc_inten_reg msdc_inten; /* base+0x10h */ + msdc_fifocs_reg msdc_fifocs; /* base+0x14h */ + msdc_txdat_reg msdc_txdat; /* base+0x18h */ + msdc_rxdat_reg msdc_rxdat; /* base+0x1ch */ + u32 rsv1[4]; + sdc_cfg_reg sdc_cfg; /* base+0x30h */ + sdc_cmd_reg sdc_cmd; /* base+0x34h */ + sdc_arg_reg sdc_arg; /* base+0x38h */ + sdc_sts_reg sdc_sts; /* base+0x3ch */ + sdc_resp0_reg sdc_resp0; /* base+0x40h */ + sdc_resp1_reg sdc_resp1; /* base+0x44h */ + sdc_resp2_reg sdc_resp2; /* base+0x48h */ + sdc_resp3_reg sdc_resp3; /* base+0x4ch */ + sdc_blknum_reg sdc_blknum; /* base+0x50h */ + u32 rsv2[1]; + sdc_csts_reg sdc_csts; /* base+0x58h */ + sdc_cstsen_reg sdc_cstsen; /* base+0x5ch */ + sdc_datcrcsts_reg sdc_dcrcsta; /* base+0x60h */ + u32 rsv3[3]; + emmc_cfg0_reg emmc_cfg0; /* base+0x70h */ + emmc_cfg1_reg emmc_cfg1; /* base+0x74h */ + emmc_sts_reg emmc_sts; /* base+0x78h */ + emmc_iocon_reg emmc_iocon; /* base+0x7ch */ + msdc_acmd_resp_reg acmd_resp; /* base+0x80h */ + msdc_acmd19_trg_reg acmd19_trg; /* base+0x84h */ + msdc_acmd19_sts_reg acmd19_sts; /* base+0x88h */ + u32 rsv4[1]; + msdc_dma_sa_reg dma_sa; /* base+0x90h */ + msdc_dma_ca_reg dma_ca; /* base+0x94h */ + msdc_dma_ctrl_reg dma_ctrl; /* base+0x98h */ + msdc_dma_cfg_reg dma_cfg; /* base+0x9ch */ + msdc_dbg_sel_reg dbg_sel; /* base+0xa0h */ + msdc_dbg_out_reg dbg_out; /* base+0xa4h */ + u32 rsv5[2]; + u32 patch0; /* base+0xb0h */ + u32 patch1; /* base+0xb4h */ + u32 rsv6[10]; + msdc_pad_ctl0_reg pad_ctl0; /* base+0xe0h */ + msdc_pad_ctl1_reg pad_ctl1; /* base+0xe4h */ + msdc_pad_ctl2_reg pad_ctl2; /* base+0xe8h */ + msdc_pad_tune_reg pad_tune; /* base+0xech */ + msdc_dat_rddly0 dat_rddly0; /* base+0xf0h */ + msdc_dat_rddly1 dat_rddly1; /* base+0xf4h */ + msdc_hw_dbg_reg hw_dbg; /* base+0xf8h */ + u32 rsv7[1]; + msdc_version_reg version; /* base+0x100h */ + msdc_eco_ver_reg eco_ver; /* base+0x104h */ +}; + +struct scatterlist_ex { + u32 cmd; + u32 arg; + u32 sglen; + struct scatterlist *sg; +}; + +#define DMA_FLAG_NONE (0x00000000) +#define DMA_FLAG_EN_CHKSUM (0x00000001) +#define DMA_FLAG_PAD_BLOCK (0x00000002) +#define DMA_FLAG_PAD_DWORD (0x00000004) + +struct msdc_dma { + u32 flags; /* flags */ + u32 xfersz; /* xfer size in bytes */ + u32 sglen; /* size of scatter list */ + u32 blklen; /* block size */ + struct scatterlist *sg; /* I/O scatter list */ + struct scatterlist_ex *esg; /* extended I/O scatter list */ + u8 mode; /* dma mode */ + u8 burstsz; /* burst size */ + u8 intr; /* dma done interrupt */ + u8 padding; /* padding */ + u32 cmd; /* enhanced mode command */ + u32 arg; /* enhanced mode arg */ + u32 rsp; /* enhanced mode command response */ + u32 autorsp; /* auto command response */ + + gpd_t *gpd; /* pointer to gpd array */ + bd_t *bd; /* pointer to bd array */ + dma_addr_t gpd_addr; /* the physical address of gpd array */ + dma_addr_t bd_addr; /* the physical address of bd array */ + u32 used_gpd; /* the number of used gpd elements */ + u32 used_bd; /* the number of used bd elements */ +}; + +struct msdc_host +{ + struct msdc_hw *hw; + + struct mmc_host *mmc; /* mmc structure */ + struct mmc_command *cmd; + struct mmc_data *data; + struct mmc_request *mrq; + int cmd_rsp; + int cmd_rsp_done; + int cmd_r1b_done; + + int error; + spinlock_t lock; /* mutex */ + struct semaphore sem; + + u32 blksz; /* host block size */ + u32 base; /* host base address */ + int id; /* host id */ + int pwr_ref; /* core power reference count */ + + u32 xfer_size; /* total transferred size */ + + struct msdc_dma dma; /* dma channel */ + u32 dma_addr; /* dma transfer address */ + u32 dma_left_size; /* dma transfer left size */ + u32 dma_xfer_size; /* dma transfer size in bytes */ + int dma_xfer; /* dma transfer mode */ + + u32 timeout_ns; /* data timeout ns */ + u32 timeout_clks; /* data timeout clks */ + + atomic_t abort; /* abort transfer */ + + int irq; /* host interrupt */ + + struct tasklet_struct card_tasklet; +#if 0 + struct work_struct card_workqueue; +#else + struct delayed_work card_delaywork; +#endif + + struct completion cmd_done; + struct completion xfer_done; + struct pm_message pm_state; + + u32 mclk; /* mmc subsystem clock */ + u32 hclk; /* host clock speed */ + u32 sclk; /* SD/MS clock speed */ + u8 core_clkon; /* Host core clock on ? */ + u8 card_clkon; /* Card clock on ? */ + u8 core_power; /* core power */ + u8 power_mode; /* host power mode */ + u8 card_inserted; /* card inserted ? */ + u8 suspend; /* host suspended ? */ + u8 reserved; + u8 app_cmd; /* for app command */ + u32 app_cmd_arg; + u64 starttime; +}; + +static inline unsigned int uffs(unsigned int x) +{ + unsigned int r = 1; + + if (!x) + return 0; + if (!(x & 0xffff)) { + x >>= 16; + r += 16; + } + if (!(x & 0xff)) { + x >>= 8; + r += 8; + } + if (!(x & 0xf)) { + x >>= 4; + r += 4; + } + if (!(x & 3)) { + x >>= 2; + r += 2; + } + if (!(x & 1)) { + x >>= 1; + r += 1; + } + return r; +} +#define sdr_read8(reg) __raw_readb(reg) +#define sdr_read16(reg) __raw_readw(reg) +#define sdr_read32(reg) __raw_readl(reg) +#define sdr_write8(reg,val) __raw_writeb(val,reg) +#define sdr_write16(reg,val) __raw_writew(val,reg) +#define sdr_write32(reg,val) __raw_writel(val,reg) + +#define sdr_set_bits(reg,bs) ((*(volatile u32*)(reg)) |= (u32)(bs)) +#define sdr_clr_bits(reg,bs) ((*(volatile u32*)(reg)) &= ~((u32)(bs))) + +#define sdr_set_field(reg,field,val) \ + do { \ + volatile unsigned int tv = sdr_read32(reg); \ + tv &= ~(field); \ + tv |= ((val) << (uffs((unsigned int)field) - 1)); \ + sdr_write32(reg,tv); \ + } while(0) +#define sdr_get_field(reg,field,val) \ + do { \ + volatile unsigned int tv = sdr_read32(reg); \ + val = ((tv & (field)) >> (uffs((unsigned int)field) - 1)); \ + } while(0) + +#endif + diff --git a/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/sd.c b/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/sd.c new file mode 100644 index 000000000..3a146f646 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/sd.c @@ -0,0 +1,3056 @@ +/* Copyright Statement: + * + * This software/firmware and related documentation ("MediaTek Software") are + * protected under relevant copyright laws. The information contained herein + * is confidential and proprietary to MediaTek Inc. and/or its licensors. + * Without the prior written permission of MediaTek inc. and/or its licensors, + * any reproduction, modification, use or disclosure of MediaTek Software, + * and information contained herein, in whole or in part, shall be strictly prohibited. + * + * MediaTek Inc. (C) 2010. All rights reserved. + * + * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES + * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") + * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON + * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. + * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE + * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR + * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH + * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES + * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES + * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK + * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR + * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND + * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, + * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, + * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO + * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. + * + * The following software/firmware and/or related documentation ("MediaTek Software") + * have been modified by MediaTek Inc. All revisions are subject to any receiver's + * applicable license agreements with MediaTek Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +++ by chhung */ +#include +#include +#include +#include +#include + +#define MSDC_SMPL_FALLING (1) +#define MSDC_CD_PIN_EN (1 << 0) /* card detection pin is wired */ +#define MSDC_WP_PIN_EN (1 << 1) /* write protection pin is wired */ +#define MSDC_REMOVABLE (1 << 5) /* removable slot */ +#define MSDC_SYS_SUSPEND (1 << 6) /* suspended by system */ +#define MSDC_HIGHSPEED (1 << 7) + +//#define IRQ_SDC 14 //MT7620 /*FIXME*/ +#ifdef CONFIG_SOC_MT7621 +#define RALINK_SYSCTL_BASE 0xbe000000 +#define RALINK_MSDC_BASE 0xbe130000 +#else +#define RALINK_SYSCTL_BASE 0xb0000000 +#define RALINK_MSDC_BASE 0xb0130000 +#endif +#define IRQ_SDC 22 /*FIXME*/ + +#include +/* end of +++ */ + + +#include + +#if 0 /* --- by chhung */ +#include +#include +#include +#include +#include +//#include +//#include +//#include +#include +// #include +#endif /* end of --- */ + +#include "mt6575_sd.h" +#include "dbg.h" + +/* +++ by chhung */ +#include "board.h" +/* end of +++ */ + +#if 0 /* --- by chhung */ +#define isb() __asm__ __volatile__ ("" : : : "memory") +#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \ + : : "r" (0) : "memory") +#define dmb() __asm__ __volatile__ ("" : : : "memory") +#endif /* end of --- */ + +#define DRV_NAME "mtk-sd" + +#define HOST_MAX_NUM (1) /* +/- by chhung */ + +#if defined (CONFIG_SOC_MT7620) +#define HOST_MAX_MCLK (48000000) /* +/- by chhung */ +#elif defined (CONFIG_SOC_MT7621) +#define HOST_MAX_MCLK (50000000) /* +/- by chhung */ +#endif +#define HOST_MIN_MCLK (260000) + +#define HOST_MAX_BLKSZ (2048) + +#define MSDC_OCR_AVAIL (MMC_VDD_28_29 | MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33) + +#define GPIO_PULL_DOWN (0) +#define GPIO_PULL_UP (1) + +#if 0 /* --- by chhung */ +#define MSDC_CLKSRC_REG (0xf100000C) +#define PDN_REG (0xF1000010) +#endif /* end of --- */ + +#define DEFAULT_DEBOUNCE (8) /* 8 cycles */ +#define DEFAULT_DTOC (40) /* data timeout counter. 65536x40 sclk. */ + +#define CMD_TIMEOUT (HZ/10) /* 100ms */ +#define DAT_TIMEOUT (HZ/2 * 5) /* 500ms x5 */ + +#define MAX_DMA_CNT (64 * 1024 - 512) /* a single transaction for WIFI may be 50K*/ + +#define MAX_GPD_NUM (1 + 1) /* one null gpd */ +#define MAX_BD_NUM (1024) +#define MAX_BD_PER_GPD (MAX_BD_NUM) + +#define MAX_HW_SGMTS (MAX_BD_NUM) +#define MAX_PHY_SGMTS (MAX_BD_NUM) +#define MAX_SGMT_SZ (MAX_DMA_CNT) +#define MAX_REQ_SZ (MAX_SGMT_SZ * 8) + +static int mtk_sw_poll; + +static int cd_active_low = 1; + +//================================= +#define PERI_MSDC0_PDN (15) +//#define PERI_MSDC1_PDN (16) +//#define PERI_MSDC2_PDN (17) +//#define PERI_MSDC3_PDN (18) + +#if 0 /* --- by chhung */ +/* gate means clock power down */ +static int g_clk_gate = 0; +#define msdc_gate_clock(id) \ + do { \ + g_clk_gate &= ~(1 << ((id) + PERI_MSDC0_PDN)); \ + } while(0) +/* not like power down register. 1 means clock on. */ +#define msdc_ungate_clock(id) \ + do { \ + g_clk_gate |= 1 << ((id) + PERI_MSDC0_PDN); \ + } while(0) + +// do we need sync object or not +void msdc_clk_status(int * status) +{ + *status = g_clk_gate; +} +#endif /* end of --- */ + +/* +++ by chhung */ +struct msdc_hw msdc0_hw = { + .clk_src = 0, + .cmd_edge = MSDC_SMPL_FALLING, + .data_edge = MSDC_SMPL_FALLING, + .clk_drv = 4, + .cmd_drv = 4, + .dat_drv = 4, + .data_pins = 4, + .data_offset = 0, + .flags = MSDC_SYS_SUSPEND | MSDC_CD_PIN_EN | MSDC_REMOVABLE | MSDC_HIGHSPEED, +// .flags = MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE, +}; + +static struct resource mtk_sd_resources[] = { + [0] = { + .start = RALINK_MSDC_BASE, + .end = RALINK_MSDC_BASE+0x3fff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_SDC, /*FIXME*/ + .end = IRQ_SDC, /*FIXME*/ + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device mtk_sd_device = { + .name = "mtk-sd", + .id = 0, + .num_resources = ARRAY_SIZE(mtk_sd_resources), + .resource = mtk_sd_resources, +}; +/* end of +++ */ + +static int msdc_rsp[] = { + 0, /* RESP_NONE */ + 1, /* RESP_R1 */ + 2, /* RESP_R2 */ + 3, /* RESP_R3 */ + 4, /* RESP_R4 */ + 1, /* RESP_R5 */ + 1, /* RESP_R6 */ + 1, /* RESP_R7 */ + 7, /* RESP_R1b */ +}; + +/* For Inhanced DMA */ +#define msdc_init_gpd_ex(gpd,extlen,cmd,arg,blknum) \ + do { \ + ((gpd_t*)gpd)->extlen = extlen; \ + ((gpd_t*)gpd)->cmd = cmd; \ + ((gpd_t*)gpd)->arg = arg; \ + ((gpd_t*)gpd)->blknum = blknum; \ + }while(0) + +#define msdc_init_bd(bd, blkpad, dwpad, dptr, dlen) \ + do { \ + BUG_ON(dlen > 0xFFFFUL); \ + ((bd_t*)bd)->blkpad = blkpad; \ + ((bd_t*)bd)->dwpad = dwpad; \ + ((bd_t*)bd)->ptr = (void*)dptr; \ + ((bd_t*)bd)->buflen = dlen; \ + }while(0) + +#define msdc_txfifocnt() ((sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_TXCNT) >> 16) +#define msdc_rxfifocnt() ((sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_RXCNT) >> 0) +#define msdc_fifo_write32(v) sdr_write32(MSDC_TXDATA, (v)) +#define msdc_fifo_write8(v) sdr_write8(MSDC_TXDATA, (v)) +#define msdc_fifo_read32() sdr_read32(MSDC_RXDATA) +#define msdc_fifo_read8() sdr_read8(MSDC_RXDATA) + + +#define msdc_dma_on() sdr_clr_bits(MSDC_CFG, MSDC_CFG_PIO) +#define msdc_dma_off() sdr_set_bits(MSDC_CFG, MSDC_CFG_PIO) + +#define msdc_retry(expr,retry,cnt) \ + do { \ + int backup = cnt; \ + while (retry) { \ + if (!(expr)) break; \ + if (cnt-- == 0) { \ + retry--; mdelay(1); cnt = backup; \ + } \ + } \ + WARN_ON(retry == 0); \ + } while(0) + +#if 0 /* --- by chhung */ +#define msdc_reset() \ + do { \ + int retry = 3, cnt = 1000; \ + sdr_set_bits(MSDC_CFG, MSDC_CFG_RST); \ + dsb(); \ + msdc_retry(sdr_read32(MSDC_CFG) & MSDC_CFG_RST, retry, cnt); \ + } while(0) +#else +#define msdc_reset() \ + do { \ + int retry = 3, cnt = 1000; \ + sdr_set_bits(MSDC_CFG, MSDC_CFG_RST); \ + msdc_retry(sdr_read32(MSDC_CFG) & MSDC_CFG_RST, retry, cnt); \ + } while(0) +#endif /* end of +/- */ + +#define msdc_clr_int() \ + do { \ + volatile u32 val = sdr_read32(MSDC_INT); \ + sdr_write32(MSDC_INT, val); \ + } while(0) + +#define msdc_clr_fifo() \ + do { \ + int retry = 3, cnt = 1000; \ + sdr_set_bits(MSDC_FIFOCS, MSDC_FIFOCS_CLR); \ + msdc_retry(sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_CLR, retry, cnt); \ + } while(0) + +#define msdc_irq_save(val) \ + do { \ + val = sdr_read32(MSDC_INTEN); \ + sdr_clr_bits(MSDC_INTEN, val); \ + } while(0) + +#define msdc_irq_restore(val) \ + do { \ + sdr_set_bits(MSDC_INTEN, val); \ + } while(0) + +/* clock source for host: global */ +#if defined (CONFIG_SOC_MT7620) +static u32 hclks[] = {48000000}; /* +/- by chhung */ +#elif defined (CONFIG_SOC_MT7621) +static u32 hclks[] = {50000000}; /* +/- by chhung */ +#endif + +//============================================ +// the power for msdc host controller: global +// always keep the VMC on. +//============================================ +#define msdc_vcore_on(host) \ + do { \ + INIT_MSG("[+]VMC ref. count<%d>", ++host->pwr_ref); \ + (void)hwPowerOn(MT65XX_POWER_LDO_VMC, VOL_3300, "SD"); \ + } while (0) +#define msdc_vcore_off(host) \ + do { \ + INIT_MSG("[-]VMC ref. count<%d>", --host->pwr_ref); \ + (void)hwPowerDown(MT65XX_POWER_LDO_VMC, "SD"); \ + } while (0) + +//==================================== +// the vdd output for card: global +// always keep the VMCH on. +//==================================== +#define msdc_vdd_on(host) \ + do { \ + (void)hwPowerOn(MT65XX_POWER_LDO_VMCH, VOL_3300, "SD"); \ + } while (0) +#define msdc_vdd_off(host) \ + do { \ + (void)hwPowerDown(MT65XX_POWER_LDO_VMCH, "SD"); \ + } while (0) + +#define sdc_is_busy() (sdr_read32(SDC_STS) & SDC_STS_SDCBUSY) +#define sdc_is_cmd_busy() (sdr_read32(SDC_STS) & SDC_STS_CMDBUSY) + +#define sdc_send_cmd(cmd,arg) \ + do { \ + sdr_write32(SDC_ARG, (arg)); \ + sdr_write32(SDC_CMD, (cmd)); \ + } while(0) + +// can modify to read h/w register. +//#define is_card_present(h) ((sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 0 : 1); +#define is_card_present(h) (((struct msdc_host*)(h))->card_inserted) + +/* +++ by chhung */ +#ifndef __ASSEMBLY__ +#define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff) +#else +#define PHYSADDR(a) ((a) & 0x1fffffff) +#endif +/* end of +++ */ +static unsigned int msdc_do_command(struct msdc_host *host, + struct mmc_command *cmd, + int tune, + unsigned long timeout); + +static int msdc_tune_cmdrsp(struct msdc_host*host,struct mmc_command *cmd); + +#ifdef MT6575_SD_DEBUG +static void msdc_dump_card_status(struct msdc_host *host, u32 status) +{ + static char *state[] = { + "Idle", /* 0 */ + "Ready", /* 1 */ + "Ident", /* 2 */ + "Stby", /* 3 */ + "Tran", /* 4 */ + "Data", /* 5 */ + "Rcv", /* 6 */ + "Prg", /* 7 */ + "Dis", /* 8 */ + "Reserved", /* 9 */ + "Reserved", /* 10 */ + "Reserved", /* 11 */ + "Reserved", /* 12 */ + "Reserved", /* 13 */ + "Reserved", /* 14 */ + "I/O mode", /* 15 */ + }; + if (status & R1_OUT_OF_RANGE) + N_MSG(RSP, "[CARD_STATUS] Out of Range"); + if (status & R1_ADDRESS_ERROR) + N_MSG(RSP, "[CARD_STATUS] Address Error"); + if (status & R1_BLOCK_LEN_ERROR) + N_MSG(RSP, "[CARD_STATUS] Block Len Error"); + if (status & R1_ERASE_SEQ_ERROR) + N_MSG(RSP, "[CARD_STATUS] Erase Seq Error"); + if (status & R1_ERASE_PARAM) + N_MSG(RSP, "[CARD_STATUS] Erase Param"); + if (status & R1_WP_VIOLATION) + N_MSG(RSP, "[CARD_STATUS] WP Violation"); + if (status & R1_CARD_IS_LOCKED) + N_MSG(RSP, "[CARD_STATUS] Card is Locked"); + if (status & R1_LOCK_UNLOCK_FAILED) + N_MSG(RSP, "[CARD_STATUS] Lock/Unlock Failed"); + if (status & R1_COM_CRC_ERROR) + N_MSG(RSP, "[CARD_STATUS] Command CRC Error"); + if (status & R1_ILLEGAL_COMMAND) + N_MSG(RSP, "[CARD_STATUS] Illegal Command"); + if (status & R1_CARD_ECC_FAILED) + N_MSG(RSP, "[CARD_STATUS] Card ECC Failed"); + if (status & R1_CC_ERROR) + N_MSG(RSP, "[CARD_STATUS] CC Error"); + if (status & R1_ERROR) + N_MSG(RSP, "[CARD_STATUS] Error"); + if (status & R1_UNDERRUN) + N_MSG(RSP, "[CARD_STATUS] Underrun"); + if (status & R1_OVERRUN) + N_MSG(RSP, "[CARD_STATUS] Overrun"); + if (status & R1_CID_CSD_OVERWRITE) + N_MSG(RSP, "[CARD_STATUS] CID/CSD Overwrite"); + if (status & R1_WP_ERASE_SKIP) + N_MSG(RSP, "[CARD_STATUS] WP Eraser Skip"); + if (status & R1_CARD_ECC_DISABLED) + N_MSG(RSP, "[CARD_STATUS] Card ECC Disabled"); + if (status & R1_ERASE_RESET) + N_MSG(RSP, "[CARD_STATUS] Erase Reset"); + if (status & R1_READY_FOR_DATA) + N_MSG(RSP, "[CARD_STATUS] Ready for Data"); + if (status & R1_SWITCH_ERROR) + N_MSG(RSP, "[CARD_STATUS] Switch error"); + if (status & R1_APP_CMD) + N_MSG(RSP, "[CARD_STATUS] App Command"); + + N_MSG(RSP, "[CARD_STATUS] '%s' State", state[R1_CURRENT_STATE(status)]); +} + +static void msdc_dump_ocr_reg(struct msdc_host *host, u32 resp) +{ + if (resp & (1 << 7)) + N_MSG(RSP, "[OCR] Low Voltage Range"); + if (resp & (1 << 15)) + N_MSG(RSP, "[OCR] 2.7-2.8 volt"); + if (resp & (1 << 16)) + N_MSG(RSP, "[OCR] 2.8-2.9 volt"); + if (resp & (1 << 17)) + N_MSG(RSP, "[OCR] 2.9-3.0 volt"); + if (resp & (1 << 18)) + N_MSG(RSP, "[OCR] 3.0-3.1 volt"); + if (resp & (1 << 19)) + N_MSG(RSP, "[OCR] 3.1-3.2 volt"); + if (resp & (1 << 20)) + N_MSG(RSP, "[OCR] 3.2-3.3 volt"); + if (resp & (1 << 21)) + N_MSG(RSP, "[OCR] 3.3-3.4 volt"); + if (resp & (1 << 22)) + N_MSG(RSP, "[OCR] 3.4-3.5 volt"); + if (resp & (1 << 23)) + N_MSG(RSP, "[OCR] 3.5-3.6 volt"); + if (resp & (1 << 24)) + N_MSG(RSP, "[OCR] Switching to 1.8V Accepted (S18A)"); + if (resp & (1 << 30)) + N_MSG(RSP, "[OCR] Card Capacity Status (CCS)"); + if (resp & (1 << 31)) + N_MSG(RSP, "[OCR] Card Power Up Status (Idle)"); + else + N_MSG(RSP, "[OCR] Card Power Up Status (Busy)"); +} + +static void msdc_dump_rca_resp(struct msdc_host *host, u32 resp) +{ + u32 status = (((resp >> 15) & 0x1) << 23) | + (((resp >> 14) & 0x1) << 22) | + (((resp >> 13) & 0x1) << 19) | + (resp & 0x1fff); + + N_MSG(RSP, "[RCA] 0x%.4x", resp >> 16); + msdc_dump_card_status(host, status); +} + +static void msdc_dump_io_resp(struct msdc_host *host, u32 resp) +{ + u32 flags = (resp >> 8) & 0xFF; + char *state[] = {"DIS", "CMD", "TRN", "RFU"}; + + if (flags & (1 << 7)) + N_MSG(RSP, "[IO] COM_CRC_ERR"); + if (flags & (1 << 6)) + N_MSG(RSP, "[IO] Illgal command"); + if (flags & (1 << 3)) + N_MSG(RSP, "[IO] Error"); + if (flags & (1 << 2)) + N_MSG(RSP, "[IO] RFU"); + if (flags & (1 << 1)) + N_MSG(RSP, "[IO] Function number error"); + if (flags & (1 << 0)) + N_MSG(RSP, "[IO] Out of range"); + + N_MSG(RSP, "[IO] State: %s, Data:0x%x", state[(resp >> 12) & 0x3], resp & 0xFF); +} +#endif + +static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks) +{ + u32 base = host->base; + u32 timeout, clk_ns; + + host->timeout_ns = ns; + host->timeout_clks = clks; + + clk_ns = 1000000000UL / host->sclk; + timeout = ns / clk_ns + clks; + timeout = timeout >> 16; /* in 65536 sclk cycle unit */ + timeout = timeout > 1 ? timeout - 1 : 0; + timeout = timeout > 255 ? 255 : timeout; + + sdr_set_field(SDC_CFG, SDC_CFG_DTOC, timeout); + + N_MSG(OPS, "Set read data timeout: %dns %dclks -> %d x 65536 cycles", + ns, clks, timeout + 1); +} + +/* msdc_eirq_sdio() will be called when EIRQ(for WIFI) */ +static void msdc_eirq_sdio(void *data) +{ + struct msdc_host *host = (struct msdc_host *)data; + + N_MSG(INT, "SDIO EINT"); + + mmc_signal_sdio_irq(host->mmc); +} + +/* msdc_eirq_cd will not be used! We not using EINT for card detection. */ +static void msdc_eirq_cd(void *data) +{ + struct msdc_host *host = (struct msdc_host *)data; + + N_MSG(INT, "CD EINT"); + +#if 0 + tasklet_hi_schedule(&host->card_tasklet); +#else + schedule_delayed_work(&host->card_delaywork, HZ); +#endif +} + +#if 0 +static void msdc_tasklet_card(unsigned long arg) +{ + struct msdc_host *host = (struct msdc_host *)arg; +#else +static void msdc_tasklet_card(struct work_struct *work) +{ + struct msdc_host *host = (struct msdc_host *)container_of(work, + struct msdc_host, card_delaywork.work); +#endif + struct msdc_hw *hw = host->hw; + u32 base = host->base; + u32 inserted; + u32 status = 0; + //u32 change = 0; + + spin_lock(&host->lock); + + if (hw->get_cd_status) { // NULL + inserted = hw->get_cd_status(); + } else { + status = sdr_read32(MSDC_PS); + if (cd_active_low) + inserted = (status & MSDC_PS_CDSTS) ? 0 : 1; + else + inserted = (status & MSDC_PS_CDSTS) ? 1 : 0; + } + if (host->mmc->caps & MMC_CAP_NEEDS_POLL) + inserted = 1; + +#if 0 + change = host->card_inserted ^ inserted; + host->card_inserted = inserted; + + if (change && !host->suspend) { + if (inserted) { + host->mmc->f_max = HOST_MAX_MCLK; // work around + } + mmc_detect_change(host->mmc, msecs_to_jiffies(20)); + } +#else /* Make sure: handle the last interrupt */ + host->card_inserted = inserted; + + if (!host->suspend) { + host->mmc->f_max = HOST_MAX_MCLK; + mmc_detect_change(host->mmc, msecs_to_jiffies(20)); + } + + IRQ_MSG("card found<%s>", inserted ? "inserted" : "removed"); +#endif + + spin_unlock(&host->lock); +} + +#if 0 /* --- by chhung */ +/* For E2 only */ +static u8 clk_src_bit[4] = { + 0, 3, 5, 7 +}; + +static void msdc_select_clksrc(struct msdc_host* host, unsigned char clksrc) +{ + u32 val; + u32 base = host->base; + + BUG_ON(clksrc > 3); + INIT_MSG("set clock source to <%d>", clksrc); + + val = sdr_read32(MSDC_CLKSRC_REG); + if (sdr_read32(MSDC_ECO_VER) >= 4) { + val &= ~(0x3 << clk_src_bit[host->id]); + val |= clksrc << clk_src_bit[host->id]; + } else { + val &= ~0x3; val |= clksrc; + } + sdr_write32(MSDC_CLKSRC_REG, val); + + host->hclk = hclks[clksrc]; + host->hw->clk_src = clksrc; +} +#endif /* end of --- */ + +static void msdc_set_mclk(struct msdc_host *host, int ddr, unsigned int hz) +{ + //struct msdc_hw *hw = host->hw; + u32 base = host->base; + u32 mode; + u32 flags; + u32 div; + u32 sclk; + u32 hclk = host->hclk; + //u8 clksrc = hw->clk_src; + + if (!hz) { // set mmc system clock to 0 ? + //ERR_MSG("set mclk to 0!!!"); + msdc_reset(); + return; + } + + msdc_irq_save(flags); + +#if defined (CONFIG_MT7621_FPGA) || defined (CONFIG_MT7628_FPGA) + mode = 0x0; /* use divisor */ + if (hz >= (hclk >> 1)) { + div = 0; /* mean div = 1/2 */ + sclk = hclk >> 1; /* sclk = clk / 2 */ + } else { + div = (hclk + ((hz << 2) - 1)) / (hz << 2); + sclk = (hclk >> 2) / div; + } +#else + if (ddr) { + mode = 0x2; /* ddr mode and use divisor */ + if (hz >= (hclk >> 2)) { + div = 1; /* mean div = 1/4 */ + sclk = hclk >> 2; /* sclk = clk / 4 */ + } else { + div = (hclk + ((hz << 2) - 1)) / (hz << 2); + sclk = (hclk >> 2) / div; + } + } else if (hz >= hclk) { /* bug fix */ + mode = 0x1; /* no divisor and divisor is ignored */ + div = 0; + sclk = hclk; + } else { + mode = 0x0; /* use divisor */ + if (hz >= (hclk >> 1)) { + div = 0; /* mean div = 1/2 */ + sclk = hclk >> 1; /* sclk = clk / 2 */ + } else { + div = (hclk + ((hz << 2) - 1)) / (hz << 2); + sclk = (hclk >> 2) / div; + } + } +#endif + /* set clock mode and divisor */ + sdr_set_field(MSDC_CFG, MSDC_CFG_CKMOD, mode); + sdr_set_field(MSDC_CFG, MSDC_CFG_CKDIV, div); + + /* wait clock stable */ + while (!(sdr_read32(MSDC_CFG) & MSDC_CFG_CKSTB)); + + host->sclk = sclk; + host->mclk = hz; + msdc_set_timeout(host, host->timeout_ns, host->timeout_clks); // need? + + INIT_MSG("================"); + INIT_MSG("!!! Set<%dKHz> Source<%dKHz> -> sclk<%dKHz>", hz/1000, hclk/1000, sclk/1000); + INIT_MSG("================"); + + msdc_irq_restore(flags); +} + +/* Fix me. when need to abort */ +static void msdc_abort_data(struct msdc_host *host) +{ + u32 base = host->base; + struct mmc_command *stop = host->mrq->stop; + + ERR_MSG("Need to Abort. dma<%d>", host->dma_xfer); + + msdc_reset(); + msdc_clr_fifo(); + msdc_clr_int(); + + // need to check FIFO count 0 ? + + if (stop) { /* try to stop, but may not success */ + ERR_MSG("stop when abort CMD<%d>", stop->opcode); + (void)msdc_do_command(host, stop, 0, CMD_TIMEOUT); + } + + //if (host->mclk >= 25000000) { + // msdc_set_mclk(host, 0, host->mclk >> 1); + //} +} + +#if 0 /* --- by chhung */ +static void msdc_pin_config(struct msdc_host *host, int mode) +{ + struct msdc_hw *hw = host->hw; + u32 base = host->base; + int pull = (mode == MSDC_PIN_PULL_UP) ? GPIO_PULL_UP : GPIO_PULL_DOWN; + + /* Config WP pin */ + if (hw->flags & MSDC_WP_PIN_EN) { + if (hw->config_gpio_pin) /* NULL */ + hw->config_gpio_pin(MSDC_WP_PIN, pull); + } + + switch (mode) { + case MSDC_PIN_PULL_UP: + //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 1); /* Check & FIXME */ + //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 0); /* Check & FIXME */ + sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 1); + sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 0); + sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 1); + sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 0); + break; + case MSDC_PIN_PULL_DOWN: + //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 0); /* Check & FIXME */ + //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 1); /* Check & FIXME */ + sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 0); + sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 1); + sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 0); + sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 1); + break; + case MSDC_PIN_PULL_NONE: + default: + //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 0); /* Check & FIXME */ + //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 0); /* Check & FIXME */ + sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 0); + sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 0); + sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 0); + sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 0); + break; + } + + N_MSG(CFG, "Pins mode(%d), down(%d), up(%d)", + mode, MSDC_PIN_PULL_DOWN, MSDC_PIN_PULL_UP); +} + +void msdc_pin_reset(struct msdc_host *host, int mode) +{ + struct msdc_hw *hw = (struct msdc_hw *)host->hw; + u32 base = host->base; + int pull = (mode == MSDC_PIN_PULL_UP) ? GPIO_PULL_UP : GPIO_PULL_DOWN; + + /* Config reset pin */ + if (hw->flags & MSDC_RST_PIN_EN) { + if (hw->config_gpio_pin) /* NULL */ + hw->config_gpio_pin(MSDC_RST_PIN, pull); + + if (mode == MSDC_PIN_PULL_UP) { + sdr_clr_bits(EMMC_IOCON, EMMC_IOCON_BOOTRST); + } else { + sdr_set_bits(EMMC_IOCON, EMMC_IOCON_BOOTRST); + } + } +} + +static void msdc_core_power(struct msdc_host *host, int on) +{ + N_MSG(CFG, "Turn %s %s power (copower: %d -> %d)", + on ? "on" : "off", "core", host->core_power, on); + + if (on && host->core_power == 0) { + msdc_vcore_on(host); + host->core_power = 1; + msleep(1); + } else if (!on && host->core_power == 1) { + msdc_vcore_off(host); + host->core_power = 0; + msleep(1); + } +} + +static void msdc_host_power(struct msdc_host *host, int on) +{ + N_MSG(CFG, "Turn %s %s power ", on ? "on" : "off", "host"); + + if (on) { + //msdc_core_power(host, 1); // need do card detection. + msdc_pin_reset(host, MSDC_PIN_PULL_UP); + } else { + msdc_pin_reset(host, MSDC_PIN_PULL_DOWN); + //msdc_core_power(host, 0); + } +} + +static void msdc_card_power(struct msdc_host *host, int on) +{ + N_MSG(CFG, "Turn %s %s power ", on ? "on" : "off", "card"); + + if (on) { + msdc_pin_config(host, MSDC_PIN_PULL_UP); + if (host->hw->ext_power_on) { + host->hw->ext_power_on(); + } else { + //msdc_vdd_on(host); // need todo card detection. + } + msleep(1); + } else { + if (host->hw->ext_power_off) { + host->hw->ext_power_off(); + } else { + //msdc_vdd_off(host); + } + msdc_pin_config(host, MSDC_PIN_PULL_DOWN); + msleep(1); + } +} + +static void msdc_set_power_mode(struct msdc_host *host, u8 mode) +{ + N_MSG(CFG, "Set power mode(%d)", mode); + + if (host->power_mode == MMC_POWER_OFF && mode != MMC_POWER_OFF) { + msdc_host_power(host, 1); + msdc_card_power(host, 1); + } else if (host->power_mode != MMC_POWER_OFF && mode == MMC_POWER_OFF) { + msdc_card_power(host, 0); + msdc_host_power(host, 0); + } + host->power_mode = mode; +} +#endif /* end of --- */ + +#ifdef CONFIG_PM +/* + register as callback function of WIFI(combo_sdio_register_pm) . + can called by msdc_drv_suspend/resume too. +*/ +static void msdc_pm(pm_message_t state, void *data) +{ + struct msdc_host *host = (struct msdc_host *)data; + int evt = state.event; + + if (evt == PM_EVENT_USER_RESUME || evt == PM_EVENT_USER_SUSPEND) { + INIT_MSG("USR_%s: suspend<%d> power<%d>", + evt == PM_EVENT_USER_RESUME ? "EVENT_USER_RESUME" : "EVENT_USER_SUSPEND", + host->suspend, host->power_mode); + } + + if (evt == PM_EVENT_SUSPEND || evt == PM_EVENT_USER_SUSPEND) { + if (host->suspend) /* already suspend */ /* default 0*/ + return; + + /* for memory card. already power off by mmc */ + if (evt == PM_EVENT_SUSPEND && host->power_mode == MMC_POWER_OFF) + return; + + host->suspend = 1; + host->pm_state = state; /* default PMSG_RESUME */ + + INIT_MSG("%s Suspend", evt == PM_EVENT_SUSPEND ? "PM" : "USR"); + if(host->hw->flags & MSDC_SYS_SUSPEND) /* set for card */ + (void)mmc_suspend_host(host->mmc); + else { + // host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY; /* just for double confirm */ /* --- by chhung */ + mmc_remove_host(host->mmc); + } + } else if (evt == PM_EVENT_RESUME || evt == PM_EVENT_USER_RESUME) { + if (!host->suspend){ + //ERR_MSG("warning: already resume"); + return; + } + + /* No PM resume when USR suspend */ + if (evt == PM_EVENT_RESUME && host->pm_state.event == PM_EVENT_USER_SUSPEND) { + ERR_MSG("PM Resume when in USR Suspend"); /* won't happen. */ + return; + } + + host->suspend = 0; + host->pm_state = state; + + INIT_MSG("%s Resume", evt == PM_EVENT_RESUME ? "PM" : "USR"); + if(host->hw->flags & MSDC_SYS_SUSPEND) { /* will not set for WIFI */ + (void)mmc_resume_host(host->mmc); + } + else { + // host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY; /* --- by chhung */ + mmc_add_host(host->mmc); + } + } +} +#endif + +/*--------------------------------------------------------------------------*/ +/* mmc_host_ops members */ +/*--------------------------------------------------------------------------*/ +static unsigned int msdc_command_start(struct msdc_host *host, + struct mmc_command *cmd, + int tune, /* not used */ + unsigned long timeout) +{ + u32 base = host->base; + u32 opcode = cmd->opcode; + u32 rawcmd; + u32 wints = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | + MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | + MSDC_INT_ACMD19_DONE; + + u32 resp; + unsigned long tmo; + + /* Protocol layer does not provide response type, but our hardware needs + * to know exact type, not just size! + */ + if (opcode == MMC_SEND_OP_COND || opcode == SD_APP_OP_COND) + resp = RESP_R3; + else if (opcode == MMC_SET_RELATIVE_ADDR || opcode == SD_SEND_RELATIVE_ADDR) + resp = (mmc_cmd_type(cmd) == MMC_CMD_BCR) ? RESP_R6 : RESP_R1; + else if (opcode == MMC_FAST_IO) + resp = RESP_R4; + else if (opcode == MMC_GO_IRQ_STATE) + resp = RESP_R5; + else if (opcode == MMC_SELECT_CARD) + resp = (cmd->arg != 0) ? RESP_R1B : RESP_NONE; + else if (opcode == SD_IO_RW_DIRECT || opcode == SD_IO_RW_EXTENDED) + resp = RESP_R1; /* SDIO workaround. */ + else if (opcode == SD_SEND_IF_COND && (mmc_cmd_type(cmd) == MMC_CMD_BCR)) + resp = RESP_R1; + else { + switch (mmc_resp_type(cmd)) { + case MMC_RSP_R1: + resp = RESP_R1; + break; + case MMC_RSP_R1B: + resp = RESP_R1B; + break; + case MMC_RSP_R2: + resp = RESP_R2; + break; + case MMC_RSP_R3: + resp = RESP_R3; + break; + case MMC_RSP_NONE: + default: + resp = RESP_NONE; + break; + } + } + + cmd->error = 0; + /* rawcmd : + * vol_swt << 30 | auto_cmd << 28 | blklen << 16 | go_irq << 15 | + * stop << 14 | rw << 13 | dtype << 11 | rsptyp << 7 | brk << 6 | opcode + */ + rawcmd = opcode | msdc_rsp[resp] << 7 | host->blksz << 16; + + if (opcode == MMC_READ_MULTIPLE_BLOCK) { + rawcmd |= (2 << 11); + } else if (opcode == MMC_READ_SINGLE_BLOCK) { + rawcmd |= (1 << 11); + } else if (opcode == MMC_WRITE_MULTIPLE_BLOCK) { + rawcmd |= ((2 << 11) | (1 << 13)); + } else if (opcode == MMC_WRITE_BLOCK) { + rawcmd |= ((1 << 11) | (1 << 13)); + } else if (opcode == SD_IO_RW_EXTENDED) { + if (cmd->data->flags & MMC_DATA_WRITE) + rawcmd |= (1 << 13); + if (cmd->data->blocks > 1) + rawcmd |= (2 << 11); + else + rawcmd |= (1 << 11); + } else if (opcode == SD_IO_RW_DIRECT && cmd->flags == (unsigned int)-1) { + rawcmd |= (1 << 14); + } else if ((opcode == SD_APP_SEND_SCR) || + (opcode == SD_APP_SEND_NUM_WR_BLKS) || + (opcode == SD_SWITCH && (mmc_cmd_type(cmd) == MMC_CMD_ADTC)) || + (opcode == SD_APP_SD_STATUS && (mmc_cmd_type(cmd) == MMC_CMD_ADTC)) || + (opcode == MMC_SEND_EXT_CSD && (mmc_cmd_type(cmd) == MMC_CMD_ADTC))) { + rawcmd |= (1 << 11); + } else if (opcode == MMC_STOP_TRANSMISSION) { + rawcmd |= (1 << 14); + rawcmd &= ~(0x0FFF << 16); + } + + N_MSG(CMD, "CMD<%d><0x%.8x> Arg<0x%.8x>", opcode , rawcmd, cmd->arg); + + tmo = jiffies + timeout; + + if (opcode == MMC_SEND_STATUS) { + for (;;) { + if (!sdc_is_cmd_busy()) + break; + + if (time_after(jiffies, tmo)) { + ERR_MSG("XXX cmd_busy timeout: before CMD<%d>", opcode); + cmd->error = (unsigned int)-ETIMEDOUT; + msdc_reset(); + goto end; + } + } + }else { + for (;;) { + if (!sdc_is_busy()) + break; + if (time_after(jiffies, tmo)) { + ERR_MSG("XXX sdc_busy timeout: before CMD<%d>", opcode); + cmd->error = (unsigned int)-ETIMEDOUT; + msdc_reset(); + goto end; + } + } + } + + //BUG_ON(in_interrupt()); + host->cmd = cmd; + host->cmd_rsp = resp; + + init_completion(&host->cmd_done); + + sdr_set_bits(MSDC_INTEN, wints); + sdc_send_cmd(rawcmd, cmd->arg); + +end: + return cmd->error; +} + +static unsigned int msdc_command_resp(struct msdc_host *host, + struct mmc_command *cmd, + int tune, + unsigned long timeout) +{ + u32 base = host->base; + u32 opcode = cmd->opcode; + //u32 rawcmd; + u32 resp; + u32 wints = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | + MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | + MSDC_INT_ACMD19_DONE; + + resp = host->cmd_rsp; + + BUG_ON(in_interrupt()); + //init_completion(&host->cmd_done); + //sdr_set_bits(MSDC_INTEN, wints); + + spin_unlock(&host->lock); + if(!wait_for_completion_timeout(&host->cmd_done, 10*timeout)){ + ERR_MSG("XXX CMD<%d> wait_for_completion timeout ARG<0x%.8x>", opcode, cmd->arg); + cmd->error = (unsigned int)-ETIMEDOUT; + msdc_reset(); + } + spin_lock(&host->lock); + + sdr_clr_bits(MSDC_INTEN, wints); + host->cmd = NULL; + +//end: +#ifdef MT6575_SD_DEBUG + switch (resp) { + case RESP_NONE: + N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)", opcode, cmd->error, resp); + break; + case RESP_R2: + N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)= %.8x %.8x %.8x %.8x", + opcode, cmd->error, resp, cmd->resp[0], cmd->resp[1], + cmd->resp[2], cmd->resp[3]); + break; + default: /* Response types 1, 3, 4, 5, 6, 7(1b) */ + N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)= 0x%.8x", + opcode, cmd->error, resp, cmd->resp[0]); + if (cmd->error == 0) { + switch (resp) { + case RESP_R1: + case RESP_R1B: + msdc_dump_card_status(host, cmd->resp[0]); + break; + case RESP_R3: + msdc_dump_ocr_reg(host, cmd->resp[0]); + break; + case RESP_R5: + msdc_dump_io_resp(host, cmd->resp[0]); + break; + case RESP_R6: + msdc_dump_rca_resp(host, cmd->resp[0]); + break; + } + } + break; + } +#endif + + /* do we need to save card's RCA when SD_SEND_RELATIVE_ADDR */ + + if (!tune) { + return cmd->error; + } + + /* memory card CRC */ + if(host->hw->flags & MSDC_REMOVABLE && cmd->error == (unsigned int)(-EIO) ) { + if (sdr_read32(SDC_CMD) & 0x1800) { /* check if has data phase */ + msdc_abort_data(host); + } else { + /* do basic: reset*/ + msdc_reset(); + msdc_clr_fifo(); + msdc_clr_int(); + } + cmd->error = msdc_tune_cmdrsp(host,cmd); + } + + // check DAT0 + /* if (resp == RESP_R1B) { + while ((sdr_read32(MSDC_PS) & 0x10000) != 0x10000); + } */ + /* CMD12 Error Handle */ + + return cmd->error; +} + +static unsigned int msdc_do_command(struct msdc_host *host, + struct mmc_command *cmd, + int tune, + unsigned long timeout) +{ + if (msdc_command_start(host, cmd, tune, timeout)) + goto end; + + if (msdc_command_resp(host, cmd, tune, timeout)) + goto end; + +end: + + N_MSG(CMD, " return<%d> resp<0x%.8x>", cmd->error, cmd->resp[0]); + return cmd->error; +} + +/* The abort condition when PIO read/write + tmo: +*/ +static int msdc_pio_abort(struct msdc_host *host, struct mmc_data *data, unsigned long tmo) +{ + int ret = 0; + u32 base = host->base; + + if (atomic_read(&host->abort)) { + ret = 1; + } + + if (time_after(jiffies, tmo)) { + data->error = (unsigned int)-ETIMEDOUT; + ERR_MSG("XXX PIO Data Timeout: CMD<%d>", host->mrq->cmd->opcode); + ret = 1; + } + + if(ret) { + msdc_reset(); + msdc_clr_fifo(); + msdc_clr_int(); + ERR_MSG("msdc pio find abort"); + } + return ret; +} + +/* + Need to add a timeout, or WDT timeout, system reboot. +*/ +// pio mode data read/write +static int msdc_pio_read(struct msdc_host *host, struct mmc_data *data) +{ + struct scatterlist *sg = data->sg; + u32 base = host->base; + u32 num = data->sg_len; + u32 *ptr; + u8 *u8ptr; + u32 left = 0; + u32 count, size = 0; + u32 wints = MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR ; + unsigned long tmo = jiffies + DAT_TIMEOUT; + + sdr_set_bits(MSDC_INTEN, wints); + while (num) { + left = sg_dma_len(sg); + ptr = sg_virt(sg); + while (left) { + if ((left >= MSDC_FIFO_THD) && (msdc_rxfifocnt() >= MSDC_FIFO_THD)) { + count = MSDC_FIFO_THD >> 2; + do { + *ptr++ = msdc_fifo_read32(); + } while (--count); + left -= MSDC_FIFO_THD; + } else if ((left < MSDC_FIFO_THD) && msdc_rxfifocnt() >= left) { + while (left > 3) { + *ptr++ = msdc_fifo_read32(); + left -= 4; + } + + u8ptr = (u8 *)ptr; + while(left) { + * u8ptr++ = msdc_fifo_read8(); + left--; + } + } + + if (msdc_pio_abort(host, data, tmo)) { + goto end; + } + } + size += sg_dma_len(sg); + sg = sg_next(sg); num--; + } +end: + data->bytes_xfered += size; + N_MSG(FIO, " PIO Read<%d>bytes", size); + + sdr_clr_bits(MSDC_INTEN, wints); + if(data->error) ERR_MSG("read pio data->error<%d> left<%d> size<%d>", data->error, left, size); + return data->error; +} + +/* please make sure won't using PIO when size >= 512 + which means, memory card block read/write won't using pio + then don't need to handle the CMD12 when data error. +*/ +static int msdc_pio_write(struct msdc_host* host, struct mmc_data *data) +{ + u32 base = host->base; + struct scatterlist *sg = data->sg; + u32 num = data->sg_len; + u32 *ptr; + u8 *u8ptr; + u32 left; + u32 count, size = 0; + u32 wints = MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR ; + unsigned long tmo = jiffies + DAT_TIMEOUT; + + sdr_set_bits(MSDC_INTEN, wints); + while (num) { + left = sg_dma_len(sg); + ptr = sg_virt(sg); + + while (left) { + if (left >= MSDC_FIFO_SZ && msdc_txfifocnt() == 0) { + count = MSDC_FIFO_SZ >> 2; + do { + msdc_fifo_write32(*ptr); ptr++; + } while (--count); + left -= MSDC_FIFO_SZ; + } else if (left < MSDC_FIFO_SZ && msdc_txfifocnt() == 0) { + while (left > 3) { + msdc_fifo_write32(*ptr); ptr++; + left -= 4; + } + + u8ptr = (u8*)ptr; + while(left){ + msdc_fifo_write8(*u8ptr); u8ptr++; + left--; + } + } + + if (msdc_pio_abort(host, data, tmo)) { + goto end; + } + } + size += sg_dma_len(sg); + sg = sg_next(sg); num--; + } +end: + data->bytes_xfered += size; + N_MSG(FIO, " PIO Write<%d>bytes", size); + if(data->error) ERR_MSG("write pio data->error<%d>", data->error); + + sdr_clr_bits(MSDC_INTEN, wints); + return data->error; +} + +#if 0 /* --- by chhung */ +// DMA resume / start / stop +static void msdc_dma_resume(struct msdc_host *host) +{ + u32 base = host->base; + + sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_RESUME, 1); + + N_MSG(DMA, "DMA resume"); +} +#endif /* end of --- */ + +static void msdc_dma_start(struct msdc_host *host) +{ + u32 base = host->base; + u32 wints = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR ; + + sdr_set_bits(MSDC_INTEN, wints); + //dsb(); /* --- by chhung */ + sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_START, 1); + + N_MSG(DMA, "DMA start"); +} + +static void msdc_dma_stop(struct msdc_host *host) +{ + u32 base = host->base; + //u32 retries=500; + u32 wints = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR ; + + N_MSG(DMA, "DMA status: 0x%.8x",sdr_read32(MSDC_DMA_CFG)); + //while (sdr_read32(MSDC_DMA_CFG) & MSDC_DMA_CFG_STS); + + sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP, 1); + while (sdr_read32(MSDC_DMA_CFG) & MSDC_DMA_CFG_STS); + + //dsb(); /* --- by chhung */ + sdr_clr_bits(MSDC_INTEN, wints); /* Not just xfer_comp */ + + N_MSG(DMA, "DMA stop"); +} + +#if 0 /* --- by chhung */ +/* dump a gpd list */ +static void msdc_dma_dump(struct msdc_host *host, struct msdc_dma *dma) +{ + gpd_t *gpd = dma->gpd; + bd_t *bd = dma->bd; + bd_t *ptr; + int i = 0; + int p_to_v; + + if (dma->mode != MSDC_MODE_DMA_DESC) { + return; + } + + ERR_MSG("try to dump gpd and bd"); + + /* dump gpd */ + ERR_MSG(".gpd<0x%.8x> gpd_phy<0x%.8x>", (int)gpd, (int)dma->gpd_addr); + ERR_MSG("...hwo <%d>", gpd->hwo ); + ERR_MSG("...bdp <%d>", gpd->bdp ); + ERR_MSG("...chksum<0x%.8x>", gpd->chksum ); + //ERR_MSG("...intr <0x%.8x>", gpd->intr ); + ERR_MSG("...next <0x%.8x>", (int)gpd->next ); + ERR_MSG("...ptr <0x%.8x>", (int)gpd->ptr ); + ERR_MSG("...buflen<0x%.8x>", gpd->buflen ); + //ERR_MSG("...extlen<0x%.8x>", gpd->extlen ); + //ERR_MSG("...arg <0x%.8x>", gpd->arg ); + //ERR_MSG("...blknum<0x%.8x>", gpd->blknum ); + //ERR_MSG("...cmd <0x%.8x>", gpd->cmd ); + + /* dump bd */ + ERR_MSG(".bd<0x%.8x> bd_phy<0x%.8x> gpd_ptr<0x%.8x>", (int)bd, (int)dma->bd_addr, (int)gpd->ptr); + ptr = bd; + p_to_v = ((u32)bd - (u32)dma->bd_addr); + while (1) { + ERR_MSG(".bd[%d]", i); i++; + ERR_MSG("...eol <%d>", ptr->eol ); + ERR_MSG("...chksum<0x%.8x>", ptr->chksum ); + //ERR_MSG("...blkpad<0x%.8x>", ptr->blkpad ); + //ERR_MSG("...dwpad <0x%.8x>", ptr->dwpad ); + ERR_MSG("...next <0x%.8x>", (int)ptr->next ); + ERR_MSG("...ptr <0x%.8x>", (int)ptr->ptr ); + ERR_MSG("...buflen<0x%.8x>", (int)ptr->buflen ); + + if (ptr->eol == 1) { + break; + } + + /* find the next bd, virtual address of ptr->next */ + /* don't need to enable when use malloc */ + //BUG_ON( (ptr->next + p_to_v)!=(ptr+1) ); + //ERR_MSG(".next bd<0x%.8x><0x%.8x>", (ptr->next + p_to_v), (ptr+1)); + ptr++; + } + + ERR_MSG("dump gpd and bd finished"); +} +#endif /* end of --- */ + +/* calc checksum */ +static u8 msdc_dma_calcs(u8 *buf, u32 len) +{ + u32 i, sum = 0; + for (i = 0; i < len; i++) { + sum += buf[i]; + } + return 0xFF - (u8)sum; +} + +/* gpd bd setup + dma registers */ +static int msdc_dma_config(struct msdc_host *host, struct msdc_dma *dma) +{ + u32 base = host->base; + u32 sglen = dma->sglen; + //u32 i, j, num, bdlen, arg, xfersz; + u32 j, num, bdlen; + u8 blkpad, dwpad, chksum; + struct scatterlist *sg = dma->sg; + gpd_t *gpd; + bd_t *bd; + + switch (dma->mode) { + case MSDC_MODE_DMA_BASIC: + BUG_ON(dma->xfersz > 65535); + BUG_ON(dma->sglen != 1); + sdr_write32(MSDC_DMA_SA, PHYSADDR(sg_dma_address(sg))); + sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_LASTBUF, 1); +//#if defined (CONFIG_RALINK_MT7620) + if (ralink_soc == MT762X_SOC_MT7620A) + sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_XFERSZ, sg_dma_len(sg)); +//#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) + else + sdr_write32((volatile u32*)(RALINK_MSDC_BASE+0xa8), sg_dma_len(sg)); +//#endif + sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_BRUSTSZ, dma->burstsz); + sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_MODE, 0); + break; + case MSDC_MODE_DMA_DESC: + blkpad = (dma->flags & DMA_FLAG_PAD_BLOCK) ? 1 : 0; + dwpad = (dma->flags & DMA_FLAG_PAD_DWORD) ? 1 : 0; + chksum = (dma->flags & DMA_FLAG_EN_CHKSUM) ? 1 : 0; + + /* calculate the required number of gpd */ + num = (sglen + MAX_BD_PER_GPD - 1) / MAX_BD_PER_GPD; + BUG_ON(num !=1 ); + + gpd = dma->gpd; + bd = dma->bd; + bdlen = sglen; + + /* modify gpd*/ + //gpd->intr = 0; + gpd->hwo = 1; /* hw will clear it */ + gpd->bdp = 1; + gpd->chksum = 0; /* need to clear first. */ + gpd->chksum = (chksum ? msdc_dma_calcs((u8 *)gpd, 16) : 0); + + /* modify bd*/ + for (j = 0; j < bdlen; j++) { + msdc_init_bd(&bd[j], blkpad, dwpad, sg_dma_address(sg), sg_dma_len(sg)); + if(j == bdlen - 1) { + bd[j].eol = 1; /* the last bd */ + } else { + bd[j].eol = 0; + } + bd[j].chksum = 0; /* checksume need to clear first */ + bd[j].chksum = (chksum ? msdc_dma_calcs((u8 *)(&bd[j]), 16) : 0); + sg++; + } + + dma->used_gpd += 2; + dma->used_bd += bdlen; + + sdr_set_field(MSDC_DMA_CFG, MSDC_DMA_CFG_DECSEN, chksum); + sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_BRUSTSZ, dma->burstsz); + sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_MODE, 1); + + sdr_write32(MSDC_DMA_SA, PHYSADDR((u32)dma->gpd_addr)); + break; + + default: + break; + } + + N_MSG(DMA, "DMA_CTRL = 0x%x", sdr_read32(MSDC_DMA_CTRL)); + N_MSG(DMA, "DMA_CFG = 0x%x", sdr_read32(MSDC_DMA_CFG)); + N_MSG(DMA, "DMA_SA = 0x%x", sdr_read32(MSDC_DMA_SA)); + + return 0; +} + +static void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma, + struct scatterlist *sg, unsigned int sglen) +{ + BUG_ON(sglen > MAX_BD_NUM); /* not support currently */ + + dma->sg = sg; + dma->flags = DMA_FLAG_EN_CHKSUM; + //dma->flags = DMA_FLAG_NONE; /* CHECKME */ + dma->sglen = sglen; + dma->xfersz = host->xfer_size; + dma->burstsz = MSDC_BRUST_64B; + + if (sglen == 1 && sg_dma_len(sg) <= MAX_DMA_CNT) + dma->mode = MSDC_MODE_DMA_BASIC; + else + dma->mode = MSDC_MODE_DMA_DESC; + + N_MSG(DMA, "DMA mode<%d> sglen<%d> xfersz<%d>", dma->mode, dma->sglen, dma->xfersz); + + msdc_dma_config(host, dma); + + /*if (dma->mode == MSDC_MODE_DMA_DESC) { + //msdc_dma_dump(host, dma); + } */ +} + +/* set block number before send command */ +static void msdc_set_blknum(struct msdc_host *host, u32 blknum) +{ + u32 base = host->base; + + sdr_write32(SDC_BLK_NUM, blknum); +} + +static int msdc_do_request(struct mmc_host*mmc, struct mmc_request*mrq) +{ + struct msdc_host *host = mmc_priv(mmc); + struct mmc_command *cmd; + struct mmc_data *data; + u32 base = host->base; + //u32 intsts = 0; + unsigned int left=0; + int dma = 0, read = 1, dir = DMA_FROM_DEVICE, send_type=0; + + #define SND_DAT 0 + #define SND_CMD 1 + + BUG_ON(mmc == NULL); + BUG_ON(mrq == NULL); + + host->error = 0; + atomic_set(&host->abort, 0); + + cmd = mrq->cmd; + data = mrq->cmd->data; + +#if 0 /* --- by chhung */ + //if(host->id ==1){ + N_MSG(OPS, "enable clock!"); + msdc_ungate_clock(host->id); + //} +#endif /* end of --- */ + + if (!data) { + send_type=SND_CMD; + if (msdc_do_command(host, cmd, 1, CMD_TIMEOUT) != 0) { + goto done; + } + } else { + BUG_ON(data->blksz > HOST_MAX_BLKSZ); + send_type=SND_DAT; + + data->error = 0; + read = data->flags & MMC_DATA_READ ? 1 : 0; + host->data = data; + host->xfer_size = data->blocks * data->blksz; + host->blksz = data->blksz; + + /* deside the transfer mode */ + if (drv_mode[host->id] == MODE_PIO) { + host->dma_xfer = dma = 0; + } else if (drv_mode[host->id] == MODE_DMA) { + host->dma_xfer = dma = 1; + } else if (drv_mode[host->id] == MODE_SIZE_DEP) { + host->dma_xfer = dma = ((host->xfer_size >= dma_size[host->id]) ? 1 : 0); + } + + if (read) { + if ((host->timeout_ns != data->timeout_ns) || + (host->timeout_clks != data->timeout_clks)) { + msdc_set_timeout(host, data->timeout_ns, data->timeout_clks); + } + } + + msdc_set_blknum(host, data->blocks); + //msdc_clr_fifo(); /* no need */ + + if (dma) { + msdc_dma_on(); /* enable DMA mode first!! */ + init_completion(&host->xfer_done); + + /* start the command first*/ + if (msdc_command_start(host, cmd, 1, CMD_TIMEOUT) != 0) + goto done; + + dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + (void)dma_map_sg(mmc_dev(mmc), data->sg, data->sg_len, dir); + msdc_dma_setup(host, &host->dma, data->sg, data->sg_len); + + /* then wait command done */ + if (msdc_command_resp(host, cmd, 1, CMD_TIMEOUT) != 0) + goto done; + + /* for read, the data coming too fast, then CRC error + start DMA no business with CRC. */ + //init_completion(&host->xfer_done); + msdc_dma_start(host); + + spin_unlock(&host->lock); + if(!wait_for_completion_timeout(&host->xfer_done, DAT_TIMEOUT)){ + ERR_MSG("XXX CMD<%d> wait xfer_done<%d> timeout!!", cmd->opcode, data->blocks * data->blksz); + ERR_MSG(" DMA_SA = 0x%x", sdr_read32(MSDC_DMA_SA)); + ERR_MSG(" DMA_CA = 0x%x", sdr_read32(MSDC_DMA_CA)); + ERR_MSG(" DMA_CTRL = 0x%x", sdr_read32(MSDC_DMA_CTRL)); + ERR_MSG(" DMA_CFG = 0x%x", sdr_read32(MSDC_DMA_CFG)); + data->error = (unsigned int)-ETIMEDOUT; + + msdc_reset(); + msdc_clr_fifo(); + msdc_clr_int(); + } + spin_lock(&host->lock); + msdc_dma_stop(host); + } else { + /* Firstly: send command */ + if (msdc_do_command(host, cmd, 1, CMD_TIMEOUT) != 0) { + goto done; + } + + /* Secondly: pio data phase */ + if (read) { + if (msdc_pio_read(host, data)){ + goto done; + } + } else { + if (msdc_pio_write(host, data)) { + goto done; + } + } + + /* For write case: make sure contents in fifo flushed to device */ + if (!read) { + while (1) { + left=msdc_txfifocnt(); + if (left == 0) { + break; + } + if (msdc_pio_abort(host, data, jiffies + DAT_TIMEOUT)) { + break; + /* Fix me: what about if data error, when stop ? how to? */ + } + } + } else { + /* Fix me: read case: need to check CRC error */ + } + + /* For write case: SDCBUSY and Xfer_Comp will assert when DAT0 not busy. + For read case : SDCBUSY and Xfer_Comp will assert when last byte read out from FIFO. + */ + + /* try not to wait xfer_comp interrupt. + the next command will check SDC_BUSY. + SDC_BUSY means xfer_comp assert + */ + + } // PIO mode + + /* Last: stop transfer */ + if (data->stop){ + if (msdc_do_command(host, data->stop, 0, CMD_TIMEOUT) != 0) { + goto done; + } + } + } + +done: + if (data != NULL) { + host->data = NULL; + host->dma_xfer = 0; + if (dma != 0) { + msdc_dma_off(); + host->dma.used_bd = 0; + host->dma.used_gpd = 0; + dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len, dir); + } + host->blksz = 0; + +#if 0 // don't stop twice! + if(host->hw->flags & MSDC_REMOVABLE && data->error) { + msdc_abort_data(host); + /* reset in IRQ, stop command has issued. -> No need */ + } +#endif + + N_MSG(OPS, "CMD<%d> data<%s %s> blksz<%d> block<%d> error<%d>",cmd->opcode, (dma? "dma":"pio"), + (read ? "read ":"write") ,data->blksz, data->blocks, data->error); + } + +#if 0 /* --- by chhung */ +#if 1 + //if(host->id==1) { + if(send_type==SND_CMD) { + if(cmd->opcode == MMC_SEND_STATUS) { + if((cmd->resp[0] & CARD_READY_FOR_DATA) ||(CARD_CURRENT_STATE(cmd->resp[0]) != 7)){ + N_MSG(OPS,"disable clock, CMD13 IDLE"); + msdc_gate_clock(host->id); + } + } else { + N_MSG(OPS,"disable clock, CMD<%d>", cmd->opcode); + msdc_gate_clock(host->id); + } + } else { + if(read) { + N_MSG(OPS,"disable clock!!! Read CMD<%d>",cmd->opcode); + msdc_gate_clock(host->id); + } + } + //} +#else + msdc_gate_clock(host->id); +#endif +#endif /* end of --- */ + + if (mrq->cmd->error) host->error = 0x001; + if (mrq->data && mrq->data->error) host->error |= 0x010; + if (mrq->stop && mrq->stop->error) host->error |= 0x100; + + //if (host->error) ERR_MSG("host->error<%d>", host->error); + + return host->error; +} + +static int msdc_app_cmd(struct mmc_host *mmc, struct msdc_host *host) +{ + struct mmc_command cmd; + struct mmc_request mrq; + u32 err; + + memset(&cmd, 0, sizeof(struct mmc_command)); + cmd.opcode = MMC_APP_CMD; +#if 0 /* bug: we meet mmc->card is null when ACMD6 */ + cmd.arg = mmc->card->rca << 16; +#else + cmd.arg = host->app_cmd_arg; +#endif + cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; + + memset(&mrq, 0, sizeof(struct mmc_request)); + mrq.cmd = &cmd; cmd.mrq = &mrq; + cmd.data = NULL; + + err = msdc_do_command(host, &cmd, 0, CMD_TIMEOUT); + return err; +} + +static int msdc_tune_cmdrsp(struct msdc_host*host, struct mmc_command *cmd) +{ + int result = -1; + u32 base = host->base; + u32 rsmpl, cur_rsmpl, orig_rsmpl; + u32 rrdly, cur_rrdly = 0xffffffff, orig_rrdly; + u32 skip = 1; + + /* ==== don't support 3.0 now ==== + 1: R_SMPL[1] + 2: PAD_CMD_RESP_RXDLY[26:22] + ==========================*/ + + // save the previous tune result + sdr_get_field(MSDC_IOCON, MSDC_IOCON_RSPL, orig_rsmpl); + sdr_get_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRRDLY, orig_rrdly); + + rrdly = 0; + do { + for (rsmpl = 0; rsmpl < 2; rsmpl++) { + /* Lv1: R_SMPL[1] */ + cur_rsmpl = (orig_rsmpl + rsmpl) % 2; + if (skip == 1) { + skip = 0; + continue; + } + sdr_set_field(MSDC_IOCON, MSDC_IOCON_RSPL, cur_rsmpl); + + if (host->app_cmd) { + result = msdc_app_cmd(host->mmc, host); + if (result) { + ERR_MSG("TUNE_CMD app_cmd<%d> failed: RESP_RXDLY<%d>,R_SMPL<%d>", + host->mrq->cmd->opcode, cur_rrdly, cur_rsmpl); + continue; + } + } + result = msdc_do_command(host, cmd, 0, CMD_TIMEOUT); // not tune. + ERR_MSG("TUNE_CMD<%d> %s PAD_CMD_RESP_RXDLY[26:22]<%d> R_SMPL[1]<%d>", cmd->opcode, + (result == 0) ? "PASS" : "FAIL", cur_rrdly, cur_rsmpl); + + if (result == 0) { + return 0; + } + if (result != (unsigned int)(-EIO)) { + ERR_MSG("TUNE_CMD<%d> Error<%d> not -EIO", cmd->opcode, result); + return result; + } + + /* should be EIO */ + if (sdr_read32(SDC_CMD) & 0x1800) { /* check if has data phase */ + msdc_abort_data(host); + } + } + + /* Lv2: PAD_CMD_RESP_RXDLY[26:22] */ + cur_rrdly = (orig_rrdly + rrdly + 1) % 32; + sdr_set_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRRDLY, cur_rrdly); + }while (++rrdly < 32); + + return result; +} + +/* Support SD2.0 Only */ +static int msdc_tune_bread(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct msdc_host *host = mmc_priv(mmc); + u32 base = host->base; + u32 ddr=0; + u32 dcrc=0; + u32 rxdly, cur_rxdly0, cur_rxdly1; + u32 dsmpl, cur_dsmpl, orig_dsmpl; + u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3; + u32 cur_dat4, cur_dat5, cur_dat6, cur_dat7; + u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3; + u32 orig_dat4, orig_dat5, orig_dat6, orig_dat7; + int result = -1; + u32 skip = 1; + + sdr_get_field(MSDC_IOCON, MSDC_IOCON_DSPL, orig_dsmpl); + + /* Tune Method 2. */ + sdr_set_field(MSDC_IOCON, MSDC_IOCON_DDLSEL, 1); + + rxdly = 0; + do { + for (dsmpl = 0; dsmpl < 2; dsmpl++) { + cur_dsmpl = (orig_dsmpl + dsmpl) % 2; + if (skip == 1) { + skip = 0; + continue; + } + sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, cur_dsmpl); + + if (host->app_cmd) { + result = msdc_app_cmd(host->mmc, host); + if (result) { + ERR_MSG("TUNE_BREAD app_cmd<%d> failed", host->mrq->cmd->opcode); + continue; + } + } + result = msdc_do_request(mmc,mrq); + + sdr_get_field(SDC_DCRC_STS, SDC_DCRC_STS_POS|SDC_DCRC_STS_NEG, dcrc); /* RO */ + if (!ddr) dcrc &= ~SDC_DCRC_STS_NEG; + ERR_MSG("TUNE_BREAD<%s> dcrc<0x%x> DATRDDLY0/1<0x%x><0x%x> dsmpl<0x%x>", + (result == 0 && dcrc == 0) ? "PASS" : "FAIL", dcrc, + sdr_read32(MSDC_DAT_RDDLY0), sdr_read32(MSDC_DAT_RDDLY1), cur_dsmpl); + + /* Fix me: result is 0, but dcrc is still exist */ + if (result == 0 && dcrc == 0) { + goto done; + } else { + /* there is a case: command timeout, and data phase not processed */ + if (mrq->data->error != 0 && mrq->data->error != (unsigned int)(-EIO)) { + ERR_MSG("TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>", + result, mrq->cmd->error, mrq->data->error); + goto done; + } + } + } + + cur_rxdly0 = sdr_read32(MSDC_DAT_RDDLY0); + cur_rxdly1 = sdr_read32(MSDC_DAT_RDDLY1); + + /* E1 ECO. YD: Reverse */ + if (sdr_read32(MSDC_ECO_VER) >= 4) { + orig_dat0 = (cur_rxdly0 >> 24) & 0x1F; + orig_dat1 = (cur_rxdly0 >> 16) & 0x1F; + orig_dat2 = (cur_rxdly0 >> 8) & 0x1F; + orig_dat3 = (cur_rxdly0 >> 0) & 0x1F; + orig_dat4 = (cur_rxdly1 >> 24) & 0x1F; + orig_dat5 = (cur_rxdly1 >> 16) & 0x1F; + orig_dat6 = (cur_rxdly1 >> 8) & 0x1F; + orig_dat7 = (cur_rxdly1 >> 0) & 0x1F; + } else { + orig_dat0 = (cur_rxdly0 >> 0) & 0x1F; + orig_dat1 = (cur_rxdly0 >> 8) & 0x1F; + orig_dat2 = (cur_rxdly0 >> 16) & 0x1F; + orig_dat3 = (cur_rxdly0 >> 24) & 0x1F; + orig_dat4 = (cur_rxdly1 >> 0) & 0x1F; + orig_dat5 = (cur_rxdly1 >> 8) & 0x1F; + orig_dat6 = (cur_rxdly1 >> 16) & 0x1F; + orig_dat7 = (cur_rxdly1 >> 24) & 0x1F; + } + + if (ddr) { + cur_dat0 = (dcrc & (1 << 0) || dcrc & (1 << 8)) ? ((orig_dat0 + 1) % 32) : orig_dat0; + cur_dat1 = (dcrc & (1 << 1) || dcrc & (1 << 9)) ? ((orig_dat1 + 1) % 32) : orig_dat1; + cur_dat2 = (dcrc & (1 << 2) || dcrc & (1 << 10)) ? ((orig_dat2 + 1) % 32) : orig_dat2; + cur_dat3 = (dcrc & (1 << 3) || dcrc & (1 << 11)) ? ((orig_dat3 + 1) % 32) : orig_dat3; + } else { + cur_dat0 = (dcrc & (1 << 0)) ? ((orig_dat0 + 1) % 32) : orig_dat0; + cur_dat1 = (dcrc & (1 << 1)) ? ((orig_dat1 + 1) % 32) : orig_dat1; + cur_dat2 = (dcrc & (1 << 2)) ? ((orig_dat2 + 1) % 32) : orig_dat2; + cur_dat3 = (dcrc & (1 << 3)) ? ((orig_dat3 + 1) % 32) : orig_dat3; + } + cur_dat4 = (dcrc & (1 << 4)) ? ((orig_dat4 + 1) % 32) : orig_dat4; + cur_dat5 = (dcrc & (1 << 5)) ? ((orig_dat5 + 1) % 32) : orig_dat5; + cur_dat6 = (dcrc & (1 << 6)) ? ((orig_dat6 + 1) % 32) : orig_dat6; + cur_dat7 = (dcrc & (1 << 7)) ? ((orig_dat7 + 1) % 32) : orig_dat7; + + cur_rxdly0 = (cur_dat0 << 24) | (cur_dat1 << 16) | (cur_dat2 << 8) | (cur_dat3 << 0); + cur_rxdly1 = (cur_dat4 << 24) | (cur_dat5 << 16) | (cur_dat6 << 8) | (cur_dat7 << 0); + + sdr_write32(MSDC_DAT_RDDLY0, cur_rxdly0); + sdr_write32(MSDC_DAT_RDDLY1, cur_rxdly1); + + } while (++rxdly < 32); + +done: + return result; +} + +static int msdc_tune_bwrite(struct mmc_host *mmc,struct mmc_request *mrq) +{ + struct msdc_host *host = mmc_priv(mmc); + u32 base = host->base; + + u32 wrrdly, cur_wrrdly = 0xffffffff, orig_wrrdly; + u32 dsmpl, cur_dsmpl, orig_dsmpl; + u32 rxdly, cur_rxdly0; + u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3; + u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3; + int result = -1; + u32 skip = 1; + + // MSDC_IOCON_DDR50CKD need to check. [Fix me] + + sdr_get_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, orig_wrrdly); + sdr_get_field(MSDC_IOCON, MSDC_IOCON_DSPL, orig_dsmpl ); + + /* Tune Method 2. just DAT0 */ + sdr_set_field(MSDC_IOCON, MSDC_IOCON_DDLSEL, 1); + cur_rxdly0 = sdr_read32(MSDC_DAT_RDDLY0); + + /* E1 ECO. YD: Reverse */ + if (sdr_read32(MSDC_ECO_VER) >= 4) { + orig_dat0 = (cur_rxdly0 >> 24) & 0x1F; + orig_dat1 = (cur_rxdly0 >> 16) & 0x1F; + orig_dat2 = (cur_rxdly0 >> 8) & 0x1F; + orig_dat3 = (cur_rxdly0 >> 0) & 0x1F; + } else { + orig_dat0 = (cur_rxdly0 >> 0) & 0x1F; + orig_dat1 = (cur_rxdly0 >> 8) & 0x1F; + orig_dat2 = (cur_rxdly0 >> 16) & 0x1F; + orig_dat3 = (cur_rxdly0 >> 24) & 0x1F; + } + + rxdly = 0; + do { + wrrdly = 0; + do { + for (dsmpl = 0; dsmpl < 2; dsmpl++) { + cur_dsmpl = (orig_dsmpl + dsmpl) % 2; + if (skip == 1) { + skip = 0; + continue; + } + sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, cur_dsmpl); + + if (host->app_cmd) { + result = msdc_app_cmd(host->mmc, host); + if (result) { + ERR_MSG("TUNE_BWRITE app_cmd<%d> failed", host->mrq->cmd->opcode); + continue; + } + } + result = msdc_do_request(mmc,mrq); + + ERR_MSG("TUNE_BWRITE<%s> DSPL<%d> DATWRDLY<%d> MSDC_DAT_RDDLY0<0x%x>", + result == 0 ? "PASS" : "FAIL", + cur_dsmpl, cur_wrrdly, cur_rxdly0); + + if (result == 0) { + goto done; + } + else { + /* there is a case: command timeout, and data phase not processed */ + if (mrq->data->error != (unsigned int)(-EIO)) { + ERR_MSG("TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>", + result, mrq->cmd->error, mrq->data->error); + goto done; + } + } + } + cur_wrrdly = (orig_wrrdly + wrrdly + 1) % 32; + sdr_set_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, cur_wrrdly); + } while (++wrrdly < 32); + + cur_dat0 = (orig_dat0 + rxdly) % 32; /* only adjust bit-1 for crc */ + cur_dat1 = orig_dat1; + cur_dat2 = orig_dat2; + cur_dat3 = orig_dat3; + + cur_rxdly0 = (cur_dat0 << 24) | (cur_dat1 << 16) | (cur_dat2 << 8) | (cur_dat3 << 0); + sdr_write32(MSDC_DAT_RDDLY0, cur_rxdly0); + } while (++rxdly < 32); + +done: + return result; +} + +static int msdc_get_card_status(struct mmc_host *mmc, struct msdc_host *host, u32 *status) +{ + struct mmc_command cmd; + struct mmc_request mrq; + u32 err; + + memset(&cmd, 0, sizeof(struct mmc_command)); + cmd.opcode = MMC_SEND_STATUS; + if (mmc->card) { + cmd.arg = mmc->card->rca << 16; + } else { + ERR_MSG("cmd13 mmc card is null"); + cmd.arg = host->app_cmd_arg; + } + cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; + + memset(&mrq, 0, sizeof(struct mmc_request)); + mrq.cmd = &cmd; cmd.mrq = &mrq; + cmd.data = NULL; + + err = msdc_do_command(host, &cmd, 1, CMD_TIMEOUT); + + if (status) { + *status = cmd.resp[0]; + } + + return err; +} + +static int msdc_check_busy(struct mmc_host *mmc, struct msdc_host *host) +{ + u32 err = 0; + u32 status = 0; + + do { + err = msdc_get_card_status(mmc, host, &status); + if (err) return err; + /* need cmd12? */ + ERR_MSG("cmd<13> resp<0x%x>", status); + } while (R1_CURRENT_STATE(status) == 7); + + return err; +} + +/* failed when msdc_do_request */ +static int msdc_tune_request(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct msdc_host *host = mmc_priv(mmc); + struct mmc_command *cmd; + struct mmc_data *data; + //u32 base = host->base; + int ret=0, read; + + cmd = mrq->cmd; + data = mrq->cmd->data; + + read = data->flags & MMC_DATA_READ ? 1 : 0; + + if (read) { + if (data->error == (unsigned int)(-EIO)) { + ret = msdc_tune_bread(mmc,mrq); + } + } else { + ret = msdc_check_busy(mmc, host); + if (ret){ + ERR_MSG("XXX cmd13 wait program done failed"); + return ret; + } + /* CRC and TO */ + /* Fix me: don't care card status? */ + ret = msdc_tune_bwrite(mmc,mrq); + } + + return ret; +} + +/* ops.request */ +static void msdc_ops_request(struct mmc_host *mmc,struct mmc_request *mrq) +{ + struct msdc_host *host = mmc_priv(mmc); + + //=== for sdio profile === +#if 0 /* --- by chhung */ + u32 old_H32, old_L32, new_H32, new_L32; + u32 ticks = 0, opcode = 0, sizes = 0, bRx = 0; +#endif /* end of --- */ + + if(host->mrq){ + ERR_MSG("XXX host->mrq<0x%.8x>", (int)host->mrq); + BUG(); + } + + if (!is_card_present(host) || host->power_mode == MMC_POWER_OFF) { + ERR_MSG("cmd<%d> card<%d> power<%d>", mrq->cmd->opcode, is_card_present(host), host->power_mode); + mrq->cmd->error = (unsigned int)-ENOMEDIUM; + +#if 1 + mrq->done(mrq); // call done directly. +#else + mrq->cmd->retries = 0; // please don't retry. + mmc_request_done(mmc, mrq); +#endif + + return; + } + + /* start to process */ + spin_lock(&host->lock); +#if 0 /* --- by chhung */ + if (sdio_pro_enable) { //=== for sdio profile === + if (mrq->cmd->opcode == 52 || mrq->cmd->opcode == 53) { + GPT_GetCounter64(&old_L32, &old_H32); + } + } +#endif /* end of --- */ + + host->mrq = mrq; + + if (msdc_do_request(mmc,mrq)) { + if(host->hw->flags & MSDC_REMOVABLE && ralink_soc == MT762X_SOC_MT7621AT && mrq->data && mrq->data->error) { + msdc_tune_request(mmc,mrq); + } + } + + /* ==== when request done, check if app_cmd ==== */ + if (mrq->cmd->opcode == MMC_APP_CMD) { + host->app_cmd = 1; + host->app_cmd_arg = mrq->cmd->arg; /* save the RCA */ + } else { + host->app_cmd = 0; + //host->app_cmd_arg = 0; + } + + host->mrq = NULL; + +#if 0 /* --- by chhung */ + //=== for sdio profile === + if (sdio_pro_enable) { + if (mrq->cmd->opcode == 52 || mrq->cmd->opcode == 53) { + GPT_GetCounter64(&new_L32, &new_H32); + ticks = msdc_time_calc(old_L32, old_H32, new_L32, new_H32); + + opcode = mrq->cmd->opcode; + if (mrq->cmd->data) { + sizes = mrq->cmd->data->blocks * mrq->cmd->data->blksz; + bRx = mrq->cmd->data->flags & MMC_DATA_READ ? 1 : 0 ; + } else { + bRx = mrq->cmd->arg & 0x80000000 ? 1 : 0; + } + + if (!mrq->cmd->error) { + msdc_performance(opcode, sizes, bRx, ticks); + } + } + } +#endif /* end of --- */ + spin_unlock(&host->lock); + + mmc_request_done(mmc, mrq); + + return; +} + +/* called by ops.set_ios */ +static void msdc_set_buswidth(struct msdc_host *host, u32 width) +{ + u32 base = host->base; + u32 val = sdr_read32(SDC_CFG); + + val &= ~SDC_CFG_BUSWIDTH; + + switch (width) { + default: + case MMC_BUS_WIDTH_1: + width = 1; + val |= (MSDC_BUS_1BITS << 16); + break; + case MMC_BUS_WIDTH_4: + val |= (MSDC_BUS_4BITS << 16); + break; + case MMC_BUS_WIDTH_8: + val |= (MSDC_BUS_8BITS << 16); + break; + } + + sdr_write32(SDC_CFG, val); + + N_MSG(CFG, "Bus Width = %d", width); +} + +/* ops.set_ios */ +static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct msdc_host *host = mmc_priv(mmc); + struct msdc_hw *hw=host->hw; + u32 base = host->base; + u32 ddr = 0; + +#ifdef MT6575_SD_DEBUG + static char *vdd[] = { + "1.50v", "1.55v", "1.60v", "1.65v", "1.70v", "1.80v", "1.90v", + "2.00v", "2.10v", "2.20v", "2.30v", "2.40v", "2.50v", "2.60v", + "2.70v", "2.80v", "2.90v", "3.00v", "3.10v", "3.20v", "3.30v", + "3.40v", "3.50v", "3.60v" + }; + static char *power_mode[] = { + "OFF", "UP", "ON" + }; + static char *bus_mode[] = { + "UNKNOWN", "OPENDRAIN", "PUSHPULL" + }; + static char *timing[] = { + "LEGACY", "MMC_HS", "SD_HS" + }; + + printk("SET_IOS: CLK(%dkHz), BUS(%s), BW(%u), PWR(%s), VDD(%s), TIMING(%s)", + ios->clock / 1000, bus_mode[ios->bus_mode], + (ios->bus_width == MMC_BUS_WIDTH_4) ? 4 : 1, + power_mode[ios->power_mode], vdd[ios->vdd], timing[ios->timing]); +#endif + + msdc_set_buswidth(host, ios->bus_width); + + /* Power control ??? */ + switch (ios->power_mode) { + case MMC_POWER_OFF: + case MMC_POWER_UP: + // msdc_set_power_mode(host, ios->power_mode); /* --- by chhung */ + break; + case MMC_POWER_ON: + host->power_mode = MMC_POWER_ON; + break; + default: + break; + } + + /* Clock control */ + if (host->mclk != ios->clock) { + if(ios->clock > 25000000) { + //if (!(host->hw->flags & MSDC_REMOVABLE)) { + INIT_MSG("SD data latch edge<%d>", hw->data_edge); + sdr_set_field(MSDC_IOCON, MSDC_IOCON_RSPL, hw->cmd_edge); + sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, hw->data_edge); + //} /* for tuning debug */ + } else { /* default value */ + sdr_write32(MSDC_IOCON, 0x00000000); + // sdr_write32(MSDC_DAT_RDDLY0, 0x00000000); + sdr_write32(MSDC_DAT_RDDLY0, 0x10101010); // for MT7620 E2 and afterward + sdr_write32(MSDC_DAT_RDDLY1, 0x00000000); + // sdr_write32(MSDC_PAD_TUNE, 0x00000000); + sdr_write32(MSDC_PAD_TUNE, 0x84101010); // for MT7620 E2 and afterward + } + msdc_set_mclk(host, ddr, ios->clock); + } +} + +/* ops.get_ro */ +static int msdc_ops_get_ro(struct mmc_host *mmc) +{ + struct msdc_host *host = mmc_priv(mmc); + u32 base = host->base; + unsigned long flags; + int ro = 0; + + if (host->hw->flags & MSDC_WP_PIN_EN) { /* set for card */ + spin_lock_irqsave(&host->lock, flags); + ro = (sdr_read32(MSDC_PS) >> 31); + spin_unlock_irqrestore(&host->lock, flags); + } + return ro; +} + +/* ops.get_cd */ +static int msdc_ops_get_cd(struct mmc_host *mmc) +{ + struct msdc_host *host = mmc_priv(mmc); + u32 base = host->base; + unsigned long flags; + int present = 1; + + /* for sdio, MSDC_REMOVABLE not set, always return 1 */ + if (!(host->hw->flags & MSDC_REMOVABLE)) { + /* For sdio, read H/W always get<1>, but may timeout some times */ +#if 1 + host->card_inserted = 1; + return 1; +#else + host->card_inserted = (host->pm_state.event == PM_EVENT_USER_RESUME) ? 1 : 0; + INIT_MSG("sdio ops_get_cd<%d>", host->card_inserted); + return host->card_inserted; +#endif + } + + /* MSDC_CD_PIN_EN set for card */ + if (host->hw->flags & MSDC_CD_PIN_EN) { + spin_lock_irqsave(&host->lock, flags); +#if 0 + present = host->card_inserted; /* why not read from H/W: Fix me*/ +#else + // CD + if (cd_active_low) + present = (sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 0 : 1; + else + present = (sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 1 : 0; + if (host->mmc->caps & MMC_CAP_NEEDS_POLL) + present = 1; + host->card_inserted = present; +#endif + spin_unlock_irqrestore(&host->lock, flags); + } else { + present = 0; /* TODO? Check DAT3 pins for card detection */ + } + + INIT_MSG("ops_get_cd return<%d>", present); + return present; +} + +/* ops.enable_sdio_irq */ +static void msdc_ops_enable_sdio_irq(struct mmc_host *mmc, int enable) +{ + struct msdc_host *host = mmc_priv(mmc); + struct msdc_hw *hw = host->hw; + u32 base = host->base; + u32 tmp; + + if (hw->flags & MSDC_EXT_SDIO_IRQ) { /* yes for sdio */ + if (enable) { + hw->enable_sdio_eirq(); /* combo_sdio_enable_eirq */ + } else { + hw->disable_sdio_eirq(); /* combo_sdio_disable_eirq */ + } + } else { + ERR_MSG("XXX "); /* so never enter here */ + tmp = sdr_read32(SDC_CFG); + /* FIXME. Need to interrupt gap detection */ + if (enable) { + tmp |= (SDC_CFG_SDIOIDE | SDC_CFG_SDIOINTWKUP); + } else { + tmp &= ~(SDC_CFG_SDIOIDE | SDC_CFG_SDIOINTWKUP); + } + sdr_write32(SDC_CFG, tmp); + } +} + +static struct mmc_host_ops mt_msdc_ops = { + .request = msdc_ops_request, + .set_ios = msdc_ops_set_ios, + .get_ro = msdc_ops_get_ro, + .get_cd = msdc_ops_get_cd, + .enable_sdio_irq = msdc_ops_enable_sdio_irq, +}; + +/*--------------------------------------------------------------------------*/ +/* interrupt handler */ +/*--------------------------------------------------------------------------*/ +static irqreturn_t msdc_irq(int irq, void *dev_id) +{ + struct msdc_host *host = (struct msdc_host *)dev_id; + struct mmc_data *data = host->data; + struct mmc_command *cmd = host->cmd; + u32 base = host->base; + + u32 cmdsts = MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | MSDC_INT_CMDRDY | + MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | MSDC_INT_ACMDRDY | + MSDC_INT_ACMD19_DONE; + u32 datsts = MSDC_INT_DATCRCERR |MSDC_INT_DATTMO; + + u32 intsts = sdr_read32(MSDC_INT); + u32 inten = sdr_read32(MSDC_INTEN); inten &= intsts; + + sdr_write32(MSDC_INT, intsts); /* clear interrupts */ + /* MSG will cause fatal error */ + + /* card change interrupt */ + if (intsts & MSDC_INT_CDSC){ + if (mtk_sw_poll) + return IRQ_HANDLED; + IRQ_MSG("MSDC_INT_CDSC irq<0x%.8x>", intsts); +#if 0 /* ---/+++ by chhung: fix slot mechanical bounce issue */ + tasklet_hi_schedule(&host->card_tasklet); +#else + schedule_delayed_work(&host->card_delaywork, HZ); +#endif + /* tuning when plug card ? */ + } + + /* sdio interrupt */ + if (intsts & MSDC_INT_SDIOIRQ){ + IRQ_MSG("XXX MSDC_INT_SDIOIRQ"); /* seems not sdio irq */ + //mmc_signal_sdio_irq(host->mmc); + } + + /* transfer complete interrupt */ + if (data != NULL) { + if (inten & MSDC_INT_XFER_COMPL) { + data->bytes_xfered = host->dma.xfersz; + complete(&host->xfer_done); + } + + if (intsts & datsts) { + /* do basic reset, or stop command will sdc_busy */ + msdc_reset(); + msdc_clr_fifo(); + msdc_clr_int(); + atomic_set(&host->abort, 1); /* For PIO mode exit */ + + if (intsts & MSDC_INT_DATTMO){ + IRQ_MSG("XXX CMD<%d> MSDC_INT_DATTMO", host->mrq->cmd->opcode); + data->error = (unsigned int)-ETIMEDOUT; + } + else if (intsts & MSDC_INT_DATCRCERR){ + IRQ_MSG("XXX CMD<%d> MSDC_INT_DATCRCERR, SDC_DCRC_STS<0x%x>", host->mrq->cmd->opcode, sdr_read32(SDC_DCRC_STS)); + data->error = (unsigned int)-EIO; + } + + //if(sdr_read32(MSDC_INTEN) & MSDC_INT_XFER_COMPL) { + if (host->dma_xfer) { + complete(&host->xfer_done); /* Read CRC come fast, XFER_COMPL not enabled */ + } /* PIO mode can't do complete, because not init */ + } + } + + /* command interrupts */ + if ((cmd != NULL) && (intsts & cmdsts)) { + if ((intsts & MSDC_INT_CMDRDY) || (intsts & MSDC_INT_ACMDRDY) || + (intsts & MSDC_INT_ACMD19_DONE)) { + u32 *rsp = &cmd->resp[0]; + + switch (host->cmd_rsp) { + case RESP_NONE: + break; + case RESP_R2: + *rsp++ = sdr_read32(SDC_RESP3); *rsp++ = sdr_read32(SDC_RESP2); + *rsp++ = sdr_read32(SDC_RESP1); *rsp++ = sdr_read32(SDC_RESP0); + break; + default: /* Response types 1, 3, 4, 5, 6, 7(1b) */ + if ((intsts & MSDC_INT_ACMDRDY) || (intsts & MSDC_INT_ACMD19_DONE)) { + *rsp = sdr_read32(SDC_ACMD_RESP); + } else { + *rsp = sdr_read32(SDC_RESP0); + } + break; + } + } else if ((intsts & MSDC_INT_RSPCRCERR) || (intsts & MSDC_INT_ACMDCRCERR)) { + if(intsts & MSDC_INT_ACMDCRCERR){ + IRQ_MSG("XXX CMD<%d> MSDC_INT_ACMDCRCERR",cmd->opcode); + } + else { + IRQ_MSG("XXX CMD<%d> MSDC_INT_RSPCRCERR",cmd->opcode); + } + cmd->error = (unsigned int)-EIO; + } else if ((intsts & MSDC_INT_CMDTMO) || (intsts & MSDC_INT_ACMDTMO)) { + if(intsts & MSDC_INT_ACMDTMO){ + IRQ_MSG("XXX CMD<%d> MSDC_INT_ACMDTMO",cmd->opcode); + } + else { + IRQ_MSG("XXX CMD<%d> MSDC_INT_CMDTMO",cmd->opcode); + } + cmd->error = (unsigned int)-ETIMEDOUT; + msdc_reset(); + msdc_clr_fifo(); + msdc_clr_int(); + } + complete(&host->cmd_done); + } + + /* mmc irq interrupts */ + if (intsts & MSDC_INT_MMCIRQ) { + printk(KERN_INFO "msdc[%d] MMCIRQ: SDC_CSTS=0x%.8x\r\n", host->id, sdr_read32(SDC_CSTS)); + } + +#ifdef MT6575_SD_DEBUG + { + msdc_int_reg *int_reg = (msdc_int_reg*)&intsts; + N_MSG(INT, "IRQ_EVT(0x%x): MMCIRQ(%d) CDSC(%d), ACRDY(%d), ACTMO(%d), ACCRE(%d) AC19DN(%d)", + intsts, + int_reg->mmcirq, + int_reg->cdsc, + int_reg->atocmdrdy, + int_reg->atocmdtmo, + int_reg->atocmdcrc, + int_reg->atocmd19done); + N_MSG(INT, "IRQ_EVT(0x%x): SDIO(%d) CMDRDY(%d), CMDTMO(%d), RSPCRC(%d), CSTA(%d)", + intsts, + int_reg->sdioirq, + int_reg->cmdrdy, + int_reg->cmdtmo, + int_reg->rspcrc, + int_reg->csta); + N_MSG(INT, "IRQ_EVT(0x%x): XFCMP(%d) DXDONE(%d), DATTMO(%d), DATCRC(%d), DMAEMP(%d)", + intsts, + int_reg->xfercomp, + int_reg->dxferdone, + int_reg->dattmo, + int_reg->datcrc, + int_reg->dmaqempty); + + } +#endif + + return IRQ_HANDLED; +} + +/*--------------------------------------------------------------------------*/ +/* platform_driver members */ +/*--------------------------------------------------------------------------*/ +/* called by msdc_drv_probe/remove */ +static void msdc_enable_cd_irq(struct msdc_host *host, int enable) +{ + struct msdc_hw *hw = host->hw; + u32 base = host->base; + + /* for sdio, not set */ + if ((hw->flags & MSDC_CD_PIN_EN) == 0) { + /* Pull down card detection pin since it is not avaiable */ + /* + if (hw->config_gpio_pin) + hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_DOWN); + */ + sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN); + sdr_clr_bits(MSDC_INTEN, MSDC_INTEN_CDSC); + sdr_clr_bits(SDC_CFG, SDC_CFG_INSWKUP); + return; + } + + N_MSG(CFG, "CD IRQ Eanable(%d)", enable); + + if (enable) { + if (hw->enable_cd_eirq) { /* not set, never enter */ + hw->enable_cd_eirq(); + } else { + /* card detection circuit relies on the core power so that the core power + * shouldn't be turned off. Here adds a reference count to keep + * the core power alive. + */ + //msdc_vcore_on(host); //did in msdc_init_hw() + + if (hw->config_gpio_pin) /* NULL */ + hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_UP); + + sdr_set_field(MSDC_PS, MSDC_PS_CDDEBOUNCE, DEFAULT_DEBOUNCE); + sdr_set_bits(MSDC_PS, MSDC_PS_CDEN); + sdr_set_bits(MSDC_INTEN, MSDC_INTEN_CDSC); + sdr_set_bits(SDC_CFG, SDC_CFG_INSWKUP); /* not in document! Fix me */ + } + } else { + if (hw->disable_cd_eirq) { + hw->disable_cd_eirq(); + } else { + if (hw->config_gpio_pin) /* NULL */ + hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_DOWN); + + sdr_clr_bits(SDC_CFG, SDC_CFG_INSWKUP); + sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN); + sdr_clr_bits(MSDC_INTEN, MSDC_INTEN_CDSC); + + /* Here decreases a reference count to core power since card + * detection circuit is shutdown. + */ + //msdc_vcore_off(host); + } + } +} + +/* called by msdc_drv_probe */ +static void msdc_init_hw(struct msdc_host *host) +{ + u32 base = host->base; + struct msdc_hw *hw = host->hw; + + /* Power on */ +#if 0 /* --- by chhung */ + msdc_vcore_on(host); + msdc_pin_reset(host, MSDC_PIN_PULL_UP); + msdc_select_clksrc(host, hw->clk_src); + enable_clock(PERI_MSDC0_PDN + host->id, "SD"); + msdc_vdd_on(host); +#endif /* end of --- */ + /* Configure to MMC/SD mode */ + sdr_set_field(MSDC_CFG, MSDC_CFG_MODE, MSDC_SDMMC); + + /* Reset */ + msdc_reset(); + msdc_clr_fifo(); + + /* Disable card detection */ + sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN); + + /* Disable and clear all interrupts */ + sdr_clr_bits(MSDC_INTEN, sdr_read32(MSDC_INTEN)); + sdr_write32(MSDC_INT, sdr_read32(MSDC_INT)); + +#if 1 + /* reset tuning parameter */ + sdr_write32(MSDC_PAD_CTL0, 0x00090000); + sdr_write32(MSDC_PAD_CTL1, 0x000A0000); + sdr_write32(MSDC_PAD_CTL2, 0x000A0000); + // sdr_write32(MSDC_PAD_TUNE, 0x00000000); + sdr_write32(MSDC_PAD_TUNE, 0x84101010); // for MT7620 E2 and afterward + // sdr_write32(MSDC_DAT_RDDLY0, 0x00000000); + sdr_write32(MSDC_DAT_RDDLY0, 0x10101010); // for MT7620 E2 and afterward + sdr_write32(MSDC_DAT_RDDLY1, 0x00000000); + sdr_write32(MSDC_IOCON, 0x00000000); +#if 0 // use MT7620 default value: 0x403c004f + sdr_write32(MSDC_PATCH_BIT0, 0x003C000F); /* bit0 modified: Rx Data Clock Source: 1 -> 2.0*/ +#endif + + if (sdr_read32(MSDC_ECO_VER) >= 4) { + if (host->id == 1) { + sdr_set_field(MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_WRDAT_CRCS, 1); + sdr_set_field(MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_CMD_RSP, 1); + + /* internal clock: latch read data */ + sdr_set_bits(MSDC_PATCH_BIT0, MSDC_PATCH_BIT_CKGEN_CK); + } + } +#endif + + /* for safety, should clear SDC_CFG.SDIO_INT_DET_EN & set SDC_CFG.SDIO in + pre-loader,uboot,kernel drivers. and SDC_CFG.SDIO_INT_DET_EN will be only + set when kernel driver wants to use SDIO bus interrupt */ + /* Configure to enable SDIO mode. it's must otherwise sdio cmd5 failed */ + sdr_set_bits(SDC_CFG, SDC_CFG_SDIO); + + /* disable detect SDIO device interupt function */ + sdr_clr_bits(SDC_CFG, SDC_CFG_SDIOIDE); + + /* eneable SMT for glitch filter */ + sdr_set_bits(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKSMT); + sdr_set_bits(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDSMT); + sdr_set_bits(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATSMT); + +#if 1 + /* set clk, cmd, dat pad driving */ + sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVN, hw->clk_drv); + sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVP, hw->clk_drv); + sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVN, hw->cmd_drv); + sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVP, hw->cmd_drv); + sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVN, hw->dat_drv); + sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVP, hw->dat_drv); +#else + sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVN, 0); + sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVP, 0); + sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVN, 0); + sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVP, 0); + sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVN, 0); + sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVP, 0); +#endif + + /* set sampling edge */ + + /* write crc timeout detection */ + sdr_set_field(MSDC_PATCH_BIT0, 1 << 30, 1); + + /* Configure to default data timeout */ + sdr_set_field(SDC_CFG, SDC_CFG_DTOC, DEFAULT_DTOC); + + msdc_set_buswidth(host, MMC_BUS_WIDTH_1); + + N_MSG(FUC, "init hardware done!"); +} + +/* called by msdc_drv_remove */ +static void msdc_deinit_hw(struct msdc_host *host) +{ + u32 base = host->base; + + /* Disable and clear all interrupts */ + sdr_clr_bits(MSDC_INTEN, sdr_read32(MSDC_INTEN)); + sdr_write32(MSDC_INT, sdr_read32(MSDC_INT)); + + /* Disable card detection */ + msdc_enable_cd_irq(host, 0); + // msdc_set_power_mode(host, MMC_POWER_OFF); /* make sure power down */ /* --- by chhung */ +} + +/* init gpd and bd list in msdc_drv_probe */ +static void msdc_init_gpd_bd(struct msdc_host *host, struct msdc_dma *dma) +{ + gpd_t *gpd = dma->gpd; + bd_t *bd = dma->bd; + bd_t *ptr, *prev; + + /* we just support one gpd */ + int bdlen = MAX_BD_PER_GPD; + + /* init the 2 gpd */ + memset(gpd, 0, sizeof(gpd_t) * 2); + //gpd->next = (void *)virt_to_phys(gpd + 1); /* pointer to a null gpd, bug! kmalloc <-> virt_to_phys */ + //gpd->next = (dma->gpd_addr + 1); /* bug */ + gpd->next = (void *)((u32)dma->gpd_addr + sizeof(gpd_t)); + + //gpd->intr = 0; + gpd->bdp = 1; /* hwo, cs, bd pointer */ + //gpd->ptr = (void*)virt_to_phys(bd); + gpd->ptr = (void *)dma->bd_addr; /* physical address */ + + memset(bd, 0, sizeof(bd_t) * bdlen); + ptr = bd + bdlen - 1; + //ptr->eol = 1; /* 0 or 1 [Fix me]*/ + //ptr->next = 0; + + while (ptr != bd) { + prev = ptr - 1; + prev->next = (void *)(dma->bd_addr + sizeof(bd_t) *(ptr - bd)); + ptr = prev; + } +} + +static int msdc_drv_probe(struct platform_device *pdev) +{ + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + __iomem void *base; + struct mmc_host *mmc; + struct resource *mem; + struct msdc_host *host; + struct msdc_hw *hw; + int ret, irq; + + pdev->dev.platform_data = &msdc0_hw; + + if (of_property_read_bool(pdev->dev.of_node, "mtk,wp-en")) + msdc0_hw.flags |= MSDC_WP_PIN_EN; + + /* Allocate MMC host for this device */ + mmc = mmc_alloc_host(sizeof(struct msdc_host), &pdev->dev); + if (!mmc) return -ENOMEM; + + hw = (struct msdc_hw*)pdev->dev.platform_data; + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); + + //BUG_ON((!hw) || (!mem) || (irq < 0)); /* --- by chhung */ + + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + /* Set host parameters to mmc */ + mmc->ops = &mt_msdc_ops; + mmc->f_min = HOST_MIN_MCLK; + mmc->f_max = HOST_MAX_MCLK; + mmc->ocr_avail = MSDC_OCR_AVAIL; + + /* For sd card: MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE | MSDC_HIGHSPEED, + For sdio : MSDC_EXT_SDIO_IRQ | MSDC_HIGHSPEED */ + if (hw->flags & MSDC_HIGHSPEED) { + mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; + } + if (hw->data_pins == 4) { /* current data_pins are all 4*/ + mmc->caps |= MMC_CAP_4_BIT_DATA; + } else if (hw->data_pins == 8) { + mmc->caps |= MMC_CAP_8_BIT_DATA; + } + if ((hw->flags & MSDC_SDIO_IRQ) || (hw->flags & MSDC_EXT_SDIO_IRQ)) + mmc->caps |= MMC_CAP_SDIO_IRQ; /* yes for sdio */ + + cd_active_low = !of_property_read_bool(pdev->dev.of_node, "mediatek,cd-high"); + mtk_sw_poll = of_property_read_bool(pdev->dev.of_node, "mediatek,cd-poll"); + + if (mtk_sw_poll) + mmc->caps |= MMC_CAP_NEEDS_POLL; + + /* MMC core transfer sizes tunable parameters */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0) + mmc->max_segs = MAX_HW_SGMTS; +#else + mmc->max_hw_segs = MAX_HW_SGMTS; + mmc->max_phys_segs = MAX_PHY_SGMTS; +#endif + mmc->max_seg_size = MAX_SGMT_SZ; + mmc->max_blk_size = HOST_MAX_BLKSZ; + mmc->max_req_size = MAX_REQ_SZ; + mmc->max_blk_count = mmc->max_req_size; + + host = mmc_priv(mmc); + host->hw = hw; + host->mmc = mmc; + host->id = 0; + host->error = 0; + host->irq = irq; + host->base = (unsigned long) base; + host->mclk = 0; /* mclk: the request clock of mmc sub-system */ + host->hclk = hclks[hw->clk_src]; /* hclk: clock of clock source to msdc controller */ + host->sclk = 0; /* sclk: the really clock after divition */ + host->pm_state = PMSG_RESUME; + host->suspend = 0; + host->core_clkon = 0; + host->card_clkon = 0; + host->core_power = 0; + host->power_mode = MMC_POWER_OFF; +// host->card_inserted = hw->flags & MSDC_REMOVABLE ? 0 : 1; + host->timeout_ns = 0; + host->timeout_clks = DEFAULT_DTOC * 65536; + + host->mrq = NULL; + //init_MUTEX(&host->sem); /* we don't need to support multiple threads access */ + + host->dma.used_gpd = 0; + host->dma.used_bd = 0; + mmc_dev(mmc)->dma_mask = NULL; + + /* using dma_alloc_coherent*/ /* todo: using 1, for all 4 slots */ + host->dma.gpd = dma_alloc_coherent(NULL, MAX_GPD_NUM * sizeof(gpd_t), &host->dma.gpd_addr, GFP_KERNEL); + host->dma.bd = dma_alloc_coherent(NULL, MAX_BD_NUM * sizeof(bd_t), &host->dma.bd_addr, GFP_KERNEL); + BUG_ON((!host->dma.gpd) || (!host->dma.bd)); + msdc_init_gpd_bd(host, &host->dma); + +#if 0 + tasklet_init(&host->card_tasklet, msdc_tasklet_card, (ulong)host); +#else + INIT_DELAYED_WORK(&host->card_delaywork, msdc_tasklet_card); +#endif + spin_lock_init(&host->lock); + msdc_init_hw(host); + + if (ralink_soc == MT762X_SOC_MT7621AT) + ret = request_irq((unsigned int)irq, msdc_irq, 0, dev_name(&pdev->dev), host); + else + ret = request_irq((unsigned int)irq, msdc_irq, IRQF_TRIGGER_LOW, dev_name(&pdev->dev), host); + + if (ret) goto release; + // mt65xx_irq_unmask(irq); /* --- by chhung */ + + if (hw->flags & MSDC_CD_PIN_EN) { /* not set for sdio */ + if (hw->request_cd_eirq) { /* not set for MT6575 */ + hw->request_cd_eirq(msdc_eirq_cd, (void*)host); /* msdc_eirq_cd will not be used! */ + } + } + + if (hw->request_sdio_eirq) /* set to combo_sdio_request_eirq() for WIFI */ + hw->request_sdio_eirq(msdc_eirq_sdio, (void*)host); /* msdc_eirq_sdio() will be called when EIRQ */ + + if (hw->register_pm) {/* yes for sdio */ +#ifdef CONFIG_PM + hw->register_pm(msdc_pm, (void*)host); /* combo_sdio_register_pm() */ +#endif + if(hw->flags & MSDC_SYS_SUSPEND) { /* will not set for WIFI */ + ERR_MSG("MSDC_SYS_SUSPEND and register_pm both set"); + } + //mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY; /* pm not controlled by system but by client. */ /* --- by chhung */ + } + + platform_set_drvdata(pdev, mmc); + + ret = mmc_add_host(mmc); + if (ret) goto free_irq; + + /* Config card detection pin and enable interrupts */ + if (hw->flags & MSDC_CD_PIN_EN) { /* set for card */ + msdc_enable_cd_irq(host, 1); + } else { + msdc_enable_cd_irq(host, 0); + } + + return 0; + +free_irq: + free_irq(irq, host); +release: + platform_set_drvdata(pdev, NULL); + msdc_deinit_hw(host); + +#if 0 + tasklet_kill(&host->card_tasklet); +#else + cancel_delayed_work_sync(&host->card_delaywork); +#endif + + if (mem) + release_mem_region(mem->start, mem->end - mem->start + 1); + + mmc_free_host(mmc); + + return ret; +} + +/* 4 device share one driver, using "drvdata" to show difference */ +static int msdc_drv_remove(struct platform_device *pdev) +{ + struct mmc_host *mmc; + struct msdc_host *host; + struct resource *mem; + + mmc = platform_get_drvdata(pdev); + BUG_ON(!mmc); + + host = mmc_priv(mmc); + BUG_ON(!host); + + ERR_MSG("removed !!!"); + + platform_set_drvdata(pdev, NULL); + mmc_remove_host(host->mmc); + msdc_deinit_hw(host); + +#if 0 + tasklet_kill(&host->card_tasklet); +#else + cancel_delayed_work_sync(&host->card_delaywork); +#endif + free_irq(host->irq, host); + + dma_free_coherent(NULL, MAX_GPD_NUM * sizeof(gpd_t), host->dma.gpd, host->dma.gpd_addr); + dma_free_coherent(NULL, MAX_BD_NUM * sizeof(bd_t), host->dma.bd, host->dma.bd_addr); + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (mem) + release_mem_region(mem->start, mem->end - mem->start + 1); + + mmc_free_host(host->mmc); + + return 0; +} + +/* Fix me: Power Flow */ +#ifdef CONFIG_PM +static int msdc_drv_suspend(struct platform_device *pdev, pm_message_t state) +{ + int ret = 0; + struct mmc_host *mmc = platform_get_drvdata(pdev); + struct msdc_host *host = mmc_priv(mmc); + + if (mmc && state.event == PM_EVENT_SUSPEND && (host->hw->flags & MSDC_SYS_SUSPEND)) { /* will set for card */ + msdc_pm(state, (void*)host); + } + + return ret; +} + +static int msdc_drv_resume(struct platform_device *pdev) +{ + int ret = 0; + struct mmc_host *mmc = platform_get_drvdata(pdev); + struct msdc_host *host = mmc_priv(mmc); + struct pm_message state; + + state.event = PM_EVENT_RESUME; + if (mmc && (host->hw->flags & MSDC_SYS_SUSPEND)) {/* will set for card */ + msdc_pm(state, (void*)host); + } + + /* This mean WIFI not controller by PM */ + + return ret; +} +#endif + +static const struct of_device_id mt7620_sdhci_match[] = { + { .compatible = "ralink,mt7620-sdhci" }, + {}, +}; +MODULE_DEVICE_TABLE(of, mt7620_sdhci_match); + +static struct platform_driver mt_msdc_driver = { + .probe = msdc_drv_probe, + .remove = msdc_drv_remove, +#ifdef CONFIG_PM + .suspend = msdc_drv_suspend, + .resume = msdc_drv_resume, +#endif + .driver = { + .name = DRV_NAME, + .of_match_table = mt7620_sdhci_match, + }, +}; + +/*--------------------------------------------------------------------------*/ +/* module init/exit */ +/*--------------------------------------------------------------------------*/ +static int __init mt_msdc_init(void) +{ + int ret; +/* +++ by chhung */ + u32 reg; + +#if defined (CONFIG_MTD_ANY_RALINK) + extern int ra_check_flash_type(void); + if(ra_check_flash_type() == 2) { /* NAND */ + printk("%s: !!!!! SDXC Module Initialize Fail !!!!!", __func__); + return 0; + } +#endif + printk("MTK MSDC device init.\n"); + mtk_sd_device.dev.platform_data = &msdc0_hw; +if (ralink_soc == MT762X_SOC_MT7620A || ralink_soc == MT762X_SOC_MT7621AT) { +//#if defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) + reg = sdr_read32((volatile u32*)(RALINK_SYSCTL_BASE + 0x60)) & ~(0x3<<18); +//#if defined (CONFIG_RALINK_MT7620) + if (ralink_soc == MT762X_SOC_MT7620A) + reg |= 0x1<<18; +//#endif +} else { +//#elif defined (CONFIG_RALINK_MT7628) + /* TODO: maybe omitted when RAether already toggle AGPIO_CFG */ + reg = sdr_read32((volatile u32*)(RALINK_SYSCTL_BASE + 0x3c)); + reg |= 0x1e << 16; + sdr_write32((volatile u32*)(RALINK_SYSCTL_BASE + 0x3c), reg); + + reg = sdr_read32((volatile u32*)(RALINK_SYSCTL_BASE + 0x60)) & ~(0x3<<10); +#if defined (CONFIG_MTK_MMC_EMMC_8BIT) + reg |= 0x3<<26 | 0x3<<28 | 0x3<<30; + msdc0_hw.data_pins = 8, +#endif +//#endif +} + sdr_write32((volatile u32*)(RALINK_SYSCTL_BASE + 0x60), reg); + //platform_device_register(&mtk_sd_device); +/* end of +++ */ + + ret = platform_driver_register(&mt_msdc_driver); + if (ret) { + printk(KERN_ERR DRV_NAME ": Can't register driver"); + return ret; + } + printk(KERN_INFO DRV_NAME ": MediaTek MT6575 MSDC Driver\n"); + +#if defined (MT6575_SD_DEBUG) + msdc_debug_proc_init(); +#endif + return 0; +} + +static void __exit mt_msdc_exit(void) +{ +// platform_device_unregister(&mtk_sd_device); + platform_driver_unregister(&mt_msdc_driver); +} + +module_init(mt_msdc_init); +module_exit(mt_msdc_exit); +MODULE_LICENSE("GPL"); diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/Kconfig b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/Kconfig new file mode 100644 index 000000000..822806fd8 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/Kconfig @@ -0,0 +1,70 @@ +config NET_VENDOR_MEDIATEK + tristate "Mediatek/Ralink ethernet driver" + depends on RALINK + help + This driver supports the ethernet mac inside the Mediatek and Ralink WiSoCs + +config NET_MEDIATEK_SOC + def_tristate NET_VENDOR_MEDIATEK + +if NET_MEDIATEK_SOC +choice + prompt "MAC type" + +config NET_MEDIATEK_RT2880 + bool "RT2882" + depends on MIPS && SOC_RT288X + +config NET_MEDIATEK_RT3050 + bool "RT3050/MT7628" + depends on MIPS && (SOC_RT305X || SOC_MT7620) + +config NET_MEDIATEK_RT3883 + bool "RT3883" + depends on MIPS && SOC_RT3883 + +config NET_MEDIATEK_MT7620 + bool "MT7620" + depends on MIPS && SOC_MT7620 + +config NET_MEDIATEK_MT7621 + bool "MT7621" + depends on MIPS && SOC_MT7621 + +endchoice + +config NET_MEDIATEK_OFFLOAD + def_bool NET_MEDIATEK_SOC + depends on NET_MEDIATEK_MT7621 + +config NET_MEDIATEK_HW_QOS + def_bool NET_MEDIATEK_SOC + depends on NET_MEDIATEK_MT7623 + +config NET_MEDIATEK_MDIO + def_bool NET_MEDIATEK_SOC + depends on (NET_MEDIATEK_RT2880 || NET_MEDIATEK_RT3883 || NET_MEDIATEK_MT7620 || NET_MEDIATEK_MT7621) + select PHYLIB + +config NET_MEDIATEK_MDIO_RT2880 + def_bool NET_MEDIATEK_SOC + depends on (NET_MEDIATEK_RT2880 || NET_MEDIATEK_RT3883) + select NET_MEDIATEK_MDIO + +config NET_MEDIATEK_MDIO_MT7620 + def_bool NET_MEDIATEK_SOC + depends on (NET_MEDIATEK_MT7620 || NET_MEDIATEK_MT7621) + select NET_MEDIATEK_MDIO + +config NET_MEDIATEK_ESW_RT3050 + def_tristate NET_MEDIATEK_SOC + depends on NET_MEDIATEK_RT3050 + +config NET_MEDIATEK_GSW_MT7620 + def_tristate NET_MEDIATEK_SOC + depends on NET_MEDIATEK_MT7620 + +config NET_MEDIATEK_GSW_MT7621 + def_tristate NET_MEDIATEK_SOC + depends on NET_MEDIATEK_MT7621 +endif diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/Makefile b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/Makefile new file mode 100644 index 000000000..b038ae369 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/Makefile @@ -0,0 +1,22 @@ +# +# Makefile for the Ralink SoCs built-in ethernet macs +# + +mtk-eth-soc-y += mtk_eth_soc.o ethtool.o + +mtk-eth-soc-$(CONFIG_NET_MEDIATEK_MDIO) += mdio.o +mtk-eth-soc-$(CONFIG_NET_MEDIATEK_MDIO_RT2880) += mdio_rt2880.o +mtk-eth-soc-$(CONFIG_NET_MEDIATEK_MDIO_MT7620) += mdio_mt7620.o + +mtk-eth-soc-$(CONFIG_NET_MEDIATEK_OFFLOAD) += mtk_offload.o mtk_debugfs.o + +mtk-eth-soc-$(CONFIG_NET_MEDIATEK_RT2880) += soc_rt2880.o +mtk-eth-soc-$(CONFIG_NET_MEDIATEK_RT3050) += soc_rt3050.o +mtk-eth-soc-$(CONFIG_NET_MEDIATEK_RT3883) += soc_rt3883.o +mtk-eth-soc-$(CONFIG_NET_MEDIATEK_MT7620) += soc_mt7620.o +mtk-eth-soc-$(CONFIG_NET_MEDIATEK_MT7621) += soc_mt7621.o + +obj-$(CONFIG_NET_MEDIATEK_ESW_RT3050) += esw_rt3050.o +obj-$(CONFIG_NET_MEDIATEK_GSW_MT7620) += gsw_mt7620.o mt7530.o +obj-$(CONFIG_NET_MEDIATEK_GSW_MT7621) += gsw_mt7621.o mt7530.o +obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk-eth-soc.o diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/esw_rt3050.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/esw_rt3050.c new file mode 100644 index 000000000..6cad5856c --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/esw_rt3050.c @@ -0,0 +1,1461 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + * Copyright (C) 2016 Vittorio Gambaletta + */ + +#include +#include +#include +#include +#include + +#include + +#include "mtk_eth_soc.h" + +/* HW limitations for this switch: + * - No large frame support (PKT_MAX_LEN at most 1536) + * - Can't have untagged vlan and tagged vlan on one port at the same time, + * though this might be possible using the undocumented PPE. + */ + +#define RT305X_ESW_REG_ISR 0x00 +#define RT305X_ESW_REG_IMR 0x04 +#define RT305X_ESW_REG_FCT0 0x08 +#define RT305X_ESW_REG_PFC1 0x14 +#define RT305X_ESW_REG_ATS 0x24 +#define RT305X_ESW_REG_ATS0 0x28 +#define RT305X_ESW_REG_ATS1 0x2c +#define RT305X_ESW_REG_ATS2 0x30 +#define RT305X_ESW_REG_PVIDC(_n) (0x40 + 4 * (_n)) +#define RT305X_ESW_REG_VLANI(_n) (0x50 + 4 * (_n)) +#define RT305X_ESW_REG_VMSC(_n) (0x70 + 4 * (_n)) +#define RT305X_ESW_REG_POA 0x80 +#define RT305X_ESW_REG_FPA 0x84 +#define RT305X_ESW_REG_SOCPC 0x8c +#define RT305X_ESW_REG_POC0 0x90 +#define RT305X_ESW_REG_POC1 0x94 +#define RT305X_ESW_REG_POC2 0x98 +#define RT305X_ESW_REG_SGC 0x9c +#define RT305X_ESW_REG_STRT 0xa0 +#define RT305X_ESW_REG_PCR0 0xc0 +#define RT305X_ESW_REG_PCR1 0xc4 +#define RT305X_ESW_REG_FPA2 0xc8 +#define RT305X_ESW_REG_FCT2 0xcc +#define RT305X_ESW_REG_SGC2 0xe4 +#define RT305X_ESW_REG_P0LED 0xa4 +#define RT305X_ESW_REG_P1LED 0xa8 +#define RT305X_ESW_REG_P2LED 0xac +#define RT305X_ESW_REG_P3LED 0xb0 +#define RT305X_ESW_REG_P4LED 0xb4 +#define RT305X_ESW_REG_PXPC(_x) (0xe8 + (4 * _x)) +#define RT305X_ESW_REG_P1PC 0xec +#define RT305X_ESW_REG_P2PC 0xf0 +#define RT305X_ESW_REG_P3PC 0xf4 +#define RT305X_ESW_REG_P4PC 0xf8 +#define RT305X_ESW_REG_P5PC 0xfc + +#define RT305X_ESW_LED_LINK 0 +#define RT305X_ESW_LED_100M 1 +#define RT305X_ESW_LED_DUPLEX 2 +#define RT305X_ESW_LED_ACTIVITY 3 +#define RT305X_ESW_LED_COLLISION 4 +#define RT305X_ESW_LED_LINKACT 5 +#define RT305X_ESW_LED_DUPLCOLL 6 +#define RT305X_ESW_LED_10MACT 7 +#define RT305X_ESW_LED_100MACT 8 +/* Additional led states not in datasheet: */ +#define RT305X_ESW_LED_BLINK 10 +#define RT305X_ESW_LED_ON 12 + +#define RT305X_ESW_LINK_S 25 +#define RT305X_ESW_DUPLEX_S 9 +#define RT305X_ESW_SPD_S 0 + +#define RT305X_ESW_PCR0_WT_NWAY_DATA_S 16 +#define RT305X_ESW_PCR0_WT_PHY_CMD BIT(13) +#define RT305X_ESW_PCR0_CPU_PHY_REG_S 8 + +#define RT305X_ESW_PCR1_WT_DONE BIT(0) + +#define RT305X_ESW_ATS_TIMEOUT (5 * HZ) +#define RT305X_ESW_PHY_TIMEOUT (5 * HZ) + +#define RT305X_ESW_PVIDC_PVID_M 0xfff +#define RT305X_ESW_PVIDC_PVID_S 12 + +#define RT305X_ESW_VLANI_VID_M 0xfff +#define RT305X_ESW_VLANI_VID_S 12 + +#define RT305X_ESW_VMSC_MSC_M 0xff +#define RT305X_ESW_VMSC_MSC_S 8 + +#define RT305X_ESW_SOCPC_DISUN2CPU_S 0 +#define RT305X_ESW_SOCPC_DISMC2CPU_S 8 +#define RT305X_ESW_SOCPC_DISBC2CPU_S 16 +#define RT305X_ESW_SOCPC_CRC_PADDING BIT(25) + +#define RT305X_ESW_POC0_EN_BP_S 0 +#define RT305X_ESW_POC0_EN_FC_S 8 +#define RT305X_ESW_POC0_DIS_RMC2CPU_S 16 +#define RT305X_ESW_POC0_DIS_PORT_M 0x7f +#define RT305X_ESW_POC0_DIS_PORT_S 23 + +#define RT305X_ESW_POC2_UNTAG_EN_M 0xff +#define RT305X_ESW_POC2_UNTAG_EN_S 0 +#define RT305X_ESW_POC2_ENAGING_S 8 +#define RT305X_ESW_POC2_DIS_UC_PAUSE_S 16 + +#define RT305X_ESW_SGC2_DOUBLE_TAG_M 0x7f +#define RT305X_ESW_SGC2_DOUBLE_TAG_S 0 +#define RT305X_ESW_SGC2_LAN_PMAP_M 0x3f +#define RT305X_ESW_SGC2_LAN_PMAP_S 24 + +#define RT305X_ESW_PFC1_EN_VLAN_M 0xff +#define RT305X_ESW_PFC1_EN_VLAN_S 16 +#define RT305X_ESW_PFC1_EN_TOS_S 24 + +#define RT305X_ESW_VLAN_NONE 0xfff + +#define RT305X_ESW_GSC_BC_STROM_MASK 0x3 +#define RT305X_ESW_GSC_BC_STROM_SHIFT 4 + +#define RT305X_ESW_GSC_LED_FREQ_MASK 0x3 +#define RT305X_ESW_GSC_LED_FREQ_SHIFT 23 + +#define RT305X_ESW_POA_LINK_MASK 0x1f +#define RT305X_ESW_POA_LINK_SHIFT 25 + +#define RT305X_ESW_PORT_ST_CHG BIT(26) +#define RT305X_ESW_PORT0 0 +#define RT305X_ESW_PORT1 1 +#define RT305X_ESW_PORT2 2 +#define RT305X_ESW_PORT3 3 +#define RT305X_ESW_PORT4 4 +#define RT305X_ESW_PORT5 5 +#define RT305X_ESW_PORT6 6 + +#define RT305X_ESW_PORTS_NONE 0 + +#define RT305X_ESW_PMAP_LLLLLL 0x3f +#define RT305X_ESW_PMAP_LLLLWL 0x2f +#define RT305X_ESW_PMAP_WLLLLL 0x3e + +#define RT305X_ESW_PORTS_INTERNAL \ + (BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT1) | \ + BIT(RT305X_ESW_PORT2) | BIT(RT305X_ESW_PORT3) | \ + BIT(RT305X_ESW_PORT4)) + +#define RT305X_ESW_PORTS_NOCPU \ + (RT305X_ESW_PORTS_INTERNAL | BIT(RT305X_ESW_PORT5)) + +#define RT305X_ESW_PORTS_CPU BIT(RT305X_ESW_PORT6) + +#define RT305X_ESW_PORTS_ALL \ + (RT305X_ESW_PORTS_NOCPU | RT305X_ESW_PORTS_CPU) + +#define RT305X_ESW_NUM_VLANS 16 +#define RT305X_ESW_NUM_VIDS 4096 +#define RT305X_ESW_NUM_PORTS 7 +#define RT305X_ESW_NUM_LANWAN 6 +#define RT305X_ESW_NUM_LEDS 5 + +#define RT5350_ESW_REG_PXTPC(_x) (0x150 + (4 * _x)) +#define RT5350_EWS_REG_LED_POLARITY 0x168 +#define RT5350_RESET_EPHY BIT(24) + +enum { + /* Global attributes. */ + RT305X_ESW_ATTR_ENABLE_VLAN, + RT305X_ESW_ATTR_ALT_VLAN_DISABLE, + RT305X_ESW_ATTR_BC_STATUS, + RT305X_ESW_ATTR_LED_FREQ, + /* Port attributes. */ + RT305X_ESW_ATTR_PORT_DISABLE, + RT305X_ESW_ATTR_PORT_DOUBLETAG, + RT305X_ESW_ATTR_PORT_UNTAG, + RT305X_ESW_ATTR_PORT_LED, + RT305X_ESW_ATTR_PORT_LAN, + RT305X_ESW_ATTR_PORT_RECV_BAD, + RT305X_ESW_ATTR_PORT_RECV_GOOD, + RT5350_ESW_ATTR_PORT_TR_BAD, + RT5350_ESW_ATTR_PORT_TR_GOOD, +}; + +struct esw_port { + bool disable; + bool doubletag; + bool untag; + u8 led; + u16 pvid; +}; + +struct esw_vlan { + u8 ports; + u16 vid; +}; + +enum { + RT305X_ESW_VLAN_CONFIG_NONE = 0, + RT305X_ESW_VLAN_CONFIG_LLLLW, + RT305X_ESW_VLAN_CONFIG_WLLLL, +}; + +struct rt305x_esw { + struct device *dev; + void __iomem *base; + int irq; + + /* Protects against concurrent register r/w operations. */ + spinlock_t reg_rw_lock; + + unsigned char port_map; + unsigned char port_disable; + unsigned int reg_initval_fct2; + unsigned int reg_initval_fpa2; + unsigned int reg_led_polarity; + + struct switch_dev swdev; + bool global_vlan_enable; + bool alt_vlan_disable; + int bc_storm_protect; + int led_frequency; + struct esw_vlan vlans[RT305X_ESW_NUM_VLANS]; + struct esw_port ports[RT305X_ESW_NUM_PORTS]; + +}; + +static inline void esw_w32(struct rt305x_esw *esw, u32 val, unsigned reg) +{ + __raw_writel(val, esw->base + reg); +} + +static inline u32 esw_r32(struct rt305x_esw *esw, unsigned reg) +{ + return __raw_readl(esw->base + reg); +} + +static inline void esw_rmw_raw(struct rt305x_esw *esw, unsigned reg, + unsigned long mask, unsigned long val) +{ + unsigned long t; + + t = __raw_readl(esw->base + reg) & ~mask; + __raw_writel(t | val, esw->base + reg); +} + +static void esw_rmw(struct rt305x_esw *esw, unsigned reg, + unsigned long mask, unsigned long val) +{ + unsigned long flags; + + spin_lock_irqsave(&esw->reg_rw_lock, flags); + esw_rmw_raw(esw, reg, mask, val); + spin_unlock_irqrestore(&esw->reg_rw_lock, flags); +} + +static u32 rt305x_mii_write(struct rt305x_esw *esw, u32 phy_addr, + u32 phy_register, u32 write_data) +{ + unsigned long t_start = jiffies; + int ret = 0; + + while (1) { + if (!(esw_r32(esw, RT305X_ESW_REG_PCR1) & + RT305X_ESW_PCR1_WT_DONE)) + break; + if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) { + ret = 1; + goto out; + } + } + + write_data &= 0xffff; + esw_w32(esw, (write_data << RT305X_ESW_PCR0_WT_NWAY_DATA_S) | + (phy_register << RT305X_ESW_PCR0_CPU_PHY_REG_S) | + (phy_addr) | RT305X_ESW_PCR0_WT_PHY_CMD, + RT305X_ESW_REG_PCR0); + + t_start = jiffies; + while (1) { + if (esw_r32(esw, RT305X_ESW_REG_PCR1) & + RT305X_ESW_PCR1_WT_DONE) + break; + + if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) { + ret = 1; + break; + } + } +out: + if (ret) + dev_err(esw->dev, "ramips_eth: MDIO timeout\n"); + return ret; +} + +static unsigned esw_get_vlan_id(struct rt305x_esw *esw, unsigned vlan) +{ + unsigned s; + unsigned val; + + s = RT305X_ESW_VLANI_VID_S * (vlan % 2); + val = esw_r32(esw, RT305X_ESW_REG_VLANI(vlan / 2)); + val = (val >> s) & RT305X_ESW_VLANI_VID_M; + + return val; +} + +static void esw_set_vlan_id(struct rt305x_esw *esw, unsigned vlan, unsigned vid) +{ + unsigned s; + + s = RT305X_ESW_VLANI_VID_S * (vlan % 2); + esw_rmw(esw, + RT305X_ESW_REG_VLANI(vlan / 2), + RT305X_ESW_VLANI_VID_M << s, + (vid & RT305X_ESW_VLANI_VID_M) << s); +} + +static unsigned esw_get_pvid(struct rt305x_esw *esw, unsigned port) +{ + unsigned s, val; + + s = RT305X_ESW_PVIDC_PVID_S * (port % 2); + val = esw_r32(esw, RT305X_ESW_REG_PVIDC(port / 2)); + return (val >> s) & RT305X_ESW_PVIDC_PVID_M; +} + +static void esw_set_pvid(struct rt305x_esw *esw, unsigned port, unsigned pvid) +{ + unsigned s; + + s = RT305X_ESW_PVIDC_PVID_S * (port % 2); + esw_rmw(esw, + RT305X_ESW_REG_PVIDC(port / 2), + RT305X_ESW_PVIDC_PVID_M << s, + (pvid & RT305X_ESW_PVIDC_PVID_M) << s); +} + +static unsigned esw_get_vmsc(struct rt305x_esw *esw, unsigned vlan) +{ + unsigned s, val; + + s = RT305X_ESW_VMSC_MSC_S * (vlan % 4); + val = esw_r32(esw, RT305X_ESW_REG_VMSC(vlan / 4)); + val = (val >> s) & RT305X_ESW_VMSC_MSC_M; + + return val; +} + +static void esw_set_vmsc(struct rt305x_esw *esw, unsigned vlan, unsigned msc) +{ + unsigned s; + + s = RT305X_ESW_VMSC_MSC_S * (vlan % 4); + esw_rmw(esw, + RT305X_ESW_REG_VMSC(vlan / 4), + RT305X_ESW_VMSC_MSC_M << s, + (msc & RT305X_ESW_VMSC_MSC_M) << s); +} + +static unsigned esw_get_port_disable(struct rt305x_esw *esw) +{ + unsigned reg; + + reg = esw_r32(esw, RT305X_ESW_REG_POC0); + return (reg >> RT305X_ESW_POC0_DIS_PORT_S) & + RT305X_ESW_POC0_DIS_PORT_M; +} + +static void esw_set_port_disable(struct rt305x_esw *esw, unsigned disable_mask) +{ + unsigned old_mask; + unsigned enable_mask; + unsigned changed; + int i; + + old_mask = esw_get_port_disable(esw); + changed = old_mask ^ disable_mask; + enable_mask = old_mask & disable_mask; + + /* enable before writing to MII */ + esw_rmw(esw, RT305X_ESW_REG_POC0, + (RT305X_ESW_POC0_DIS_PORT_M << + RT305X_ESW_POC0_DIS_PORT_S), + enable_mask << RT305X_ESW_POC0_DIS_PORT_S); + + for (i = 0; i < RT305X_ESW_NUM_LEDS; i++) { + if (!(changed & (1 << i))) + continue; + if (disable_mask & (1 << i)) { + /* disable */ + rt305x_mii_write(esw, i, MII_BMCR, + BMCR_PDOWN); + } else { + /* enable */ + rt305x_mii_write(esw, i, MII_BMCR, + BMCR_FULLDPLX | + BMCR_ANENABLE | + BMCR_ANRESTART | + BMCR_SPEED100); + } + } + + /* disable after writing to MII */ + esw_rmw(esw, RT305X_ESW_REG_POC0, + (RT305X_ESW_POC0_DIS_PORT_M << + RT305X_ESW_POC0_DIS_PORT_S), + disable_mask << RT305X_ESW_POC0_DIS_PORT_S); +} + +static void esw_set_gsc(struct rt305x_esw *esw) +{ + esw_rmw(esw, RT305X_ESW_REG_SGC, + RT305X_ESW_GSC_BC_STROM_MASK << RT305X_ESW_GSC_BC_STROM_SHIFT, + esw->bc_storm_protect << RT305X_ESW_GSC_BC_STROM_SHIFT); + esw_rmw(esw, RT305X_ESW_REG_SGC, + RT305X_ESW_GSC_LED_FREQ_MASK << RT305X_ESW_GSC_LED_FREQ_SHIFT, + esw->led_frequency << RT305X_ESW_GSC_LED_FREQ_SHIFT); +} + +static int esw_apply_config(struct switch_dev *dev); + +static void esw_hw_init(struct rt305x_esw *esw) +{ + int i; + u8 port_disable = 0; + u8 port_map = RT305X_ESW_PMAP_LLLLLL; + + /* vodoo from original driver */ + esw_w32(esw, 0xC8A07850, RT305X_ESW_REG_FCT0); + esw_w32(esw, 0x00000000, RT305X_ESW_REG_SGC2); + /* Port priority 1 for all ports, vlan enabled. */ + esw_w32(esw, 0x00005555 | + (RT305X_ESW_PORTS_ALL << RT305X_ESW_PFC1_EN_VLAN_S), + RT305X_ESW_REG_PFC1); + + /* Enable all ports, Back Pressure and Flow Control */ + esw_w32(esw, ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_BP_S) | + (RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_FC_S)), + RT305X_ESW_REG_POC0); + + /* Enable Aging, and VLAN TAG removal */ + esw_w32(esw, ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC2_ENAGING_S) | + (RT305X_ESW_PORTS_NOCPU << RT305X_ESW_POC2_UNTAG_EN_S)), + RT305X_ESW_REG_POC2); + + if (esw->reg_initval_fct2) + esw_w32(esw, esw->reg_initval_fct2, RT305X_ESW_REG_FCT2); + else + esw_w32(esw, 0x0002500c, RT305X_ESW_REG_FCT2); + + /* 300s aging timer, max packet len 1536, broadcast storm prevention + * disabled, disable collision abort, mac xor48 hash, 10 packet back + * pressure jam, GMII disable was_transmit, back pressure disabled, + * 30ms led flash, unmatched IGMP as broadcast, rmc tb fault to all + * ports. + */ + esw_w32(esw, 0x0008a301, RT305X_ESW_REG_SGC); + + /* Setup SoC Port control register */ + esw_w32(esw, + (RT305X_ESW_SOCPC_CRC_PADDING | + (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISUN2CPU_S) | + (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISMC2CPU_S) | + (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISBC2CPU_S)), + RT305X_ESW_REG_SOCPC); + + /* ext phy base addr 31, enable port 5 polling, rx/tx clock skew 1, + * turbo mii off, rgmi 3.3v off + * port5: disabled + * port6: enabled, gige, full-duplex, rx/tx-flow-control + */ + if (esw->reg_initval_fpa2) + esw_w32(esw, esw->reg_initval_fpa2, RT305X_ESW_REG_FPA2); + else + esw_w32(esw, 0x3f502b28, RT305X_ESW_REG_FPA2); + esw_w32(esw, 0x00000000, RT305X_ESW_REG_FPA); + + /* Force Link/Activity on ports */ + esw_w32(esw, 0x00000005, RT305X_ESW_REG_P0LED); + esw_w32(esw, 0x00000005, RT305X_ESW_REG_P1LED); + esw_w32(esw, 0x00000005, RT305X_ESW_REG_P2LED); + esw_w32(esw, 0x00000005, RT305X_ESW_REG_P3LED); + esw_w32(esw, 0x00000005, RT305X_ESW_REG_P4LED); + + /* Copy disabled port configuration from device tree setup */ + port_disable = esw->port_disable; + + /* Disable nonexistent ports by reading the switch config + * after having enabled all possible ports above + */ + port_disable |= esw_get_port_disable(esw); + + for (i = 0; i < 6; i++) + esw->ports[i].disable = (port_disable & (1 << i)) != 0; + + if (ralink_soc == RT305X_SOC_RT3352) { + /* reset EPHY */ + fe_reset(RT5350_RESET_EPHY); + + rt305x_mii_write(esw, 0, 31, 0x8000); + for (i = 0; i < 5; i++) { + if (esw->ports[i].disable) { + rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN); + } else { + rt305x_mii_write(esw, i, MII_BMCR, + BMCR_FULLDPLX | + BMCR_ANENABLE | + BMCR_SPEED100); + } + /* TX10 waveform coefficient LSB=0 disable PHY */ + rt305x_mii_write(esw, i, 26, 0x1601); + /* TX100/TX10 AD/DA current bias */ + rt305x_mii_write(esw, i, 29, 0x7016); + /* TX100 slew rate control */ + rt305x_mii_write(esw, i, 30, 0x0038); + } + + /* select global register */ + rt305x_mii_write(esw, 0, 31, 0x0); + /* enlarge agcsel threshold 3 and threshold 2 */ + rt305x_mii_write(esw, 0, 1, 0x4a40); + /* enlarge agcsel threshold 5 and threshold 4 */ + rt305x_mii_write(esw, 0, 2, 0x6254); + /* enlarge agcsel threshold */ + rt305x_mii_write(esw, 0, 3, 0xa17f); + rt305x_mii_write(esw, 0, 12, 0x7eaa); + /* longer TP_IDL tail length */ + rt305x_mii_write(esw, 0, 14, 0x65); + /* increased squelch pulse count threshold. */ + rt305x_mii_write(esw, 0, 16, 0x0684); + /* set TX10 signal amplitude threshold to minimum */ + rt305x_mii_write(esw, 0, 17, 0x0fe0); + /* set squelch amplitude to higher threshold */ + rt305x_mii_write(esw, 0, 18, 0x40ba); + /* tune TP_IDL tail and head waveform, enable power + * down slew rate control + */ + rt305x_mii_write(esw, 0, 22, 0x253f); + /* set PLL/Receive bias current are calibrated */ + rt305x_mii_write(esw, 0, 27, 0x2fda); + /* change PLL/Receive bias current to internal(RT3350) */ + rt305x_mii_write(esw, 0, 28, 0xc410); + /* change PLL bias current to internal(RT3052_MP3) */ + rt305x_mii_write(esw, 0, 29, 0x598b); + /* select local register */ + rt305x_mii_write(esw, 0, 31, 0x8000); + } else if (ralink_soc == RT305X_SOC_RT5350) { + /* reset EPHY */ + fe_reset(RT5350_RESET_EPHY); + + /* set the led polarity */ + esw_w32(esw, esw->reg_led_polarity & 0x1F, + RT5350_EWS_REG_LED_POLARITY); + + /* local registers */ + rt305x_mii_write(esw, 0, 31, 0x8000); + for (i = 0; i < 5; i++) { + if (esw->ports[i].disable) { + rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN); + } else { + rt305x_mii_write(esw, i, MII_BMCR, + BMCR_FULLDPLX | + BMCR_ANENABLE | + BMCR_SPEED100); + } + /* TX10 waveform coefficient LSB=0 disable PHY */ + rt305x_mii_write(esw, i, 26, 0x1601); + /* TX100/TX10 AD/DA current bias */ + rt305x_mii_write(esw, i, 29, 0x7015); + /* TX100 slew rate control */ + rt305x_mii_write(esw, i, 30, 0x0038); + } + + /* global registers */ + rt305x_mii_write(esw, 0, 31, 0x0); + /* enlarge agcsel threshold 3 and threshold 2 */ + rt305x_mii_write(esw, 0, 1, 0x4a40); + /* enlarge agcsel threshold 5 and threshold 4 */ + rt305x_mii_write(esw, 0, 2, 0x6254); + /* enlarge agcsel threshold 6 */ + rt305x_mii_write(esw, 0, 3, 0xa17f); + rt305x_mii_write(esw, 0, 12, 0x7eaa); + /* longer TP_IDL tail length */ + rt305x_mii_write(esw, 0, 14, 0x65); + /* increased squelch pulse count threshold. */ + rt305x_mii_write(esw, 0, 16, 0x0684); + /* set TX10 signal amplitude threshold to minimum */ + rt305x_mii_write(esw, 0, 17, 0x0fe0); + /* set squelch amplitude to higher threshold */ + rt305x_mii_write(esw, 0, 18, 0x40ba); + /* tune TP_IDL tail and head waveform, enable power + * down slew rate control + */ + rt305x_mii_write(esw, 0, 22, 0x253f); + /* set PLL/Receive bias current are calibrated */ + rt305x_mii_write(esw, 0, 27, 0x2fda); + /* change PLL/Receive bias current to internal(RT3350) */ + rt305x_mii_write(esw, 0, 28, 0xc410); + /* change PLL bias current to internal(RT3052_MP3) */ + rt305x_mii_write(esw, 0, 29, 0x598b); + /* select local register */ + rt305x_mii_write(esw, 0, 31, 0x8000); + } else if (ralink_soc == MT762X_SOC_MT7628AN || ralink_soc == MT762X_SOC_MT7688) { + int i; + + /* reset EPHY */ + fe_reset(RT5350_RESET_EPHY); + + rt305x_mii_write(esw, 0, 31, 0x2000); /* change G2 page */ + rt305x_mii_write(esw, 0, 26, 0x0020); + + for (i = 0; i < 5; i++) { + rt305x_mii_write(esw, i, 31, 0x8000); + rt305x_mii_write(esw, i, 0, 0x3100); + rt305x_mii_write(esw, i, 30, 0xa000); + rt305x_mii_write(esw, i, 31, 0xa000); + rt305x_mii_write(esw, i, 16, 0x0606); + rt305x_mii_write(esw, i, 23, 0x0f0e); + rt305x_mii_write(esw, i, 24, 0x1610); + rt305x_mii_write(esw, i, 30, 0x1f15); + rt305x_mii_write(esw, i, 28, 0x6111); + rt305x_mii_write(esw, i, 31, 0x2000); + rt305x_mii_write(esw, i, 26, 0x0000); + } + + /* 100Base AOI setting */ + rt305x_mii_write(esw, 0, 31, 0x5000); + rt305x_mii_write(esw, 0, 19, 0x004a); + rt305x_mii_write(esw, 0, 20, 0x015a); + rt305x_mii_write(esw, 0, 21, 0x00ee); + rt305x_mii_write(esw, 0, 22, 0x0033); + rt305x_mii_write(esw, 0, 23, 0x020a); + rt305x_mii_write(esw, 0, 24, 0x0000); + rt305x_mii_write(esw, 0, 25, 0x024a); + rt305x_mii_write(esw, 0, 26, 0x035a); + rt305x_mii_write(esw, 0, 27, 0x02ee); + rt305x_mii_write(esw, 0, 28, 0x0233); + rt305x_mii_write(esw, 0, 29, 0x000a); + rt305x_mii_write(esw, 0, 30, 0x0000); + } else { + rt305x_mii_write(esw, 0, 31, 0x8000); + for (i = 0; i < 5; i++) { + if (esw->ports[i].disable) { + rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN); + } else { + rt305x_mii_write(esw, i, MII_BMCR, + BMCR_FULLDPLX | + BMCR_ANENABLE | + BMCR_SPEED100); + } + /* TX10 waveform coefficient */ + rt305x_mii_write(esw, i, 26, 0x1601); + /* TX100/TX10 AD/DA current bias */ + rt305x_mii_write(esw, i, 29, 0x7058); + /* TX100 slew rate control */ + rt305x_mii_write(esw, i, 30, 0x0018); + } + + /* PHY IOT */ + /* select global register */ + rt305x_mii_write(esw, 0, 31, 0x0); + /* tune TP_IDL tail and head waveform */ + rt305x_mii_write(esw, 0, 22, 0x052f); + /* set TX10 signal amplitude threshold to minimum */ + rt305x_mii_write(esw, 0, 17, 0x0fe0); + /* set squelch amplitude to higher threshold */ + rt305x_mii_write(esw, 0, 18, 0x40ba); + /* longer TP_IDL tail length */ + rt305x_mii_write(esw, 0, 14, 0x65); + /* select local register */ + rt305x_mii_write(esw, 0, 31, 0x8000); + } + + if (esw->port_map) + port_map = esw->port_map; + else + port_map = RT305X_ESW_PMAP_LLLLLL; + + /* Unused HW feature, but still nice to be consistent here... + * This is also exported to userspace ('lan' attribute) so it's + * conveniently usable to decide which ports go into the wan vlan by + * default. + */ + esw_rmw(esw, RT305X_ESW_REG_SGC2, + RT305X_ESW_SGC2_LAN_PMAP_M << RT305X_ESW_SGC2_LAN_PMAP_S, + port_map << RT305X_ESW_SGC2_LAN_PMAP_S); + + /* make the switch leds blink */ + for (i = 0; i < RT305X_ESW_NUM_LEDS; i++) + esw->ports[i].led = 0x05; + + /* Apply the empty config. */ + esw_apply_config(&esw->swdev); + + /* Only unmask the port change interrupt */ + esw_w32(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR); +} + +static irqreturn_t esw_interrupt(int irq, void *_esw) +{ + struct rt305x_esw *esw = (struct rt305x_esw *)_esw; + u32 status; + + status = esw_r32(esw, RT305X_ESW_REG_ISR); + if (status & RT305X_ESW_PORT_ST_CHG) { + u32 link = esw_r32(esw, RT305X_ESW_REG_POA); + + link >>= RT305X_ESW_POA_LINK_SHIFT; + link &= RT305X_ESW_POA_LINK_MASK; + dev_info(esw->dev, "link changed 0x%02X\n", link); + } + esw_w32(esw, status, RT305X_ESW_REG_ISR); + + return IRQ_HANDLED; +} + +static int esw_apply_config(struct switch_dev *dev) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + int i; + u8 disable = 0; + u8 doubletag = 0; + u8 en_vlan = 0; + u8 untag = 0; + + for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { + u32 vid, vmsc; + if (esw->global_vlan_enable) { + vid = esw->vlans[i].vid; + vmsc = esw->vlans[i].ports; + } else { + vid = RT305X_ESW_VLAN_NONE; + vmsc = RT305X_ESW_PORTS_NONE; + } + esw_set_vlan_id(esw, i, vid); + esw_set_vmsc(esw, i, vmsc); + } + + for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) { + u32 pvid; + disable |= esw->ports[i].disable << i; + if (esw->global_vlan_enable) { + doubletag |= esw->ports[i].doubletag << i; + en_vlan |= 1 << i; + untag |= esw->ports[i].untag << i; + pvid = esw->ports[i].pvid; + } else { + int x = esw->alt_vlan_disable ? 0 : 1; + doubletag |= x << i; + en_vlan |= x << i; + untag |= x << i; + pvid = 0; + } + esw_set_pvid(esw, i, pvid); + if (i < RT305X_ESW_NUM_LEDS) + esw_w32(esw, esw->ports[i].led, + RT305X_ESW_REG_P0LED + 4*i); + } + + esw_set_gsc(esw); + esw_set_port_disable(esw, disable); + esw_rmw(esw, RT305X_ESW_REG_SGC2, + (RT305X_ESW_SGC2_DOUBLE_TAG_M << + RT305X_ESW_SGC2_DOUBLE_TAG_S), + doubletag << RT305X_ESW_SGC2_DOUBLE_TAG_S); + esw_rmw(esw, RT305X_ESW_REG_PFC1, + RT305X_ESW_PFC1_EN_VLAN_M << RT305X_ESW_PFC1_EN_VLAN_S, + en_vlan << RT305X_ESW_PFC1_EN_VLAN_S); + esw_rmw(esw, RT305X_ESW_REG_POC2, + RT305X_ESW_POC2_UNTAG_EN_M << RT305X_ESW_POC2_UNTAG_EN_S, + untag << RT305X_ESW_POC2_UNTAG_EN_S); + + if (!esw->global_vlan_enable) { + /* + * Still need to put all ports into vlan 0 or they'll be + * isolated. + * NOTE: vlan 0 is special, no vlan tag is prepended + */ + esw_set_vlan_id(esw, 0, 0); + esw_set_vmsc(esw, 0, RT305X_ESW_PORTS_ALL); + } + + return 0; +} + +static int esw_reset_switch(struct switch_dev *dev) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + esw->global_vlan_enable = 0; + memset(esw->ports, 0, sizeof(esw->ports)); + memset(esw->vlans, 0, sizeof(esw->vlans)); + esw_hw_init(esw); + + return 0; +} + +static int esw_get_vlan_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + val->value.i = esw->global_vlan_enable; + + return 0; +} + +static int esw_set_vlan_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + esw->global_vlan_enable = val->value.i != 0; + + return 0; +} + +static int esw_get_alt_vlan_disable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + val->value.i = esw->alt_vlan_disable; + + return 0; +} + +static int esw_set_alt_vlan_disable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + esw->alt_vlan_disable = val->value.i != 0; + + return 0; +} + +static int +rt305x_esw_set_bc_status(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + esw->bc_storm_protect = val->value.i & RT305X_ESW_GSC_BC_STROM_MASK; + + return 0; +} + +static int +rt305x_esw_get_bc_status(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + val->value.i = esw->bc_storm_protect; + + return 0; +} + +static int +rt305x_esw_set_led_freq(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + esw->led_frequency = val->value.i & RT305X_ESW_GSC_LED_FREQ_MASK; + + return 0; +} + +static int +rt305x_esw_get_led_freq(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + val->value.i = esw->led_frequency; + + return 0; +} + +static int esw_get_port_link(struct switch_dev *dev, + int port, + struct switch_port_link *link) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + u32 speed, poa; + + if (port < 0 || port >= RT305X_ESW_NUM_PORTS) + return -EINVAL; + + poa = esw_r32(esw, RT305X_ESW_REG_POA) >> port; + + link->link = (poa >> RT305X_ESW_LINK_S) & 1; + link->duplex = (poa >> RT305X_ESW_DUPLEX_S) & 1; + if (port < RT305X_ESW_NUM_LEDS) { + speed = (poa >> RT305X_ESW_SPD_S) & 1; + } else { + if (port == RT305X_ESW_NUM_PORTS - 1) + poa >>= 1; + speed = (poa >> RT305X_ESW_SPD_S) & 3; + } + switch (speed) { + case 0: + link->speed = SWITCH_PORT_SPEED_10; + break; + case 1: + link->speed = SWITCH_PORT_SPEED_100; + break; + case 2: + case 3: /* forced gige speed can be 2 or 3 */ + link->speed = SWITCH_PORT_SPEED_1000; + break; + default: + link->speed = SWITCH_PORT_SPEED_UNKNOWN; + break; + } + + return 0; +} + +static int esw_get_port_bool(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + int idx = val->port_vlan; + u32 x, reg, shift; + + if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS) + return -EINVAL; + + switch (attr->id) { + case RT305X_ESW_ATTR_PORT_DISABLE: + reg = RT305X_ESW_REG_POC0; + shift = RT305X_ESW_POC0_DIS_PORT_S; + break; + case RT305X_ESW_ATTR_PORT_DOUBLETAG: + reg = RT305X_ESW_REG_SGC2; + shift = RT305X_ESW_SGC2_DOUBLE_TAG_S; + break; + case RT305X_ESW_ATTR_PORT_UNTAG: + reg = RT305X_ESW_REG_POC2; + shift = RT305X_ESW_POC2_UNTAG_EN_S; + break; + case RT305X_ESW_ATTR_PORT_LAN: + reg = RT305X_ESW_REG_SGC2; + shift = RT305X_ESW_SGC2_LAN_PMAP_S; + if (idx >= RT305X_ESW_NUM_LANWAN) + return -EINVAL; + break; + default: + return -EINVAL; + } + + x = esw_r32(esw, reg); + val->value.i = (x >> (idx + shift)) & 1; + + return 0; +} + +static int esw_set_port_bool(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + int idx = val->port_vlan; + + if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS || + val->value.i < 0 || val->value.i > 1) + return -EINVAL; + + switch (attr->id) { + case RT305X_ESW_ATTR_PORT_DISABLE: + esw->ports[idx].disable = val->value.i; + break; + case RT305X_ESW_ATTR_PORT_DOUBLETAG: + esw->ports[idx].doubletag = val->value.i; + break; + case RT305X_ESW_ATTR_PORT_UNTAG: + esw->ports[idx].untag = val->value.i; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int esw_get_port_recv_badgood(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + int idx = val->port_vlan; + int shift = attr->id == RT305X_ESW_ATTR_PORT_RECV_GOOD ? 0 : 16; + u32 reg; + + if (idx < 0 || idx >= RT305X_ESW_NUM_LANWAN) + return -EINVAL; + reg = esw_r32(esw, RT305X_ESW_REG_PXPC(idx)); + val->value.i = (reg >> shift) & 0xffff; + + return 0; +} + +static int +esw_get_port_tr_badgood(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + int idx = val->port_vlan; + int shift = attr->id == RT5350_ESW_ATTR_PORT_TR_GOOD ? 0 : 16; + u32 reg; + + if ((ralink_soc != RT305X_SOC_RT5350) && (ralink_soc != MT762X_SOC_MT7628AN) && (ralink_soc != MT762X_SOC_MT7688)) + return -EINVAL; + + if (idx < 0 || idx >= RT305X_ESW_NUM_LANWAN) + return -EINVAL; + + reg = esw_r32(esw, RT5350_ESW_REG_PXTPC(idx)); + val->value.i = (reg >> shift) & 0xffff; + + return 0; +} + +static int esw_get_port_led(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + int idx = val->port_vlan; + + if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS || + idx >= RT305X_ESW_NUM_LEDS) + return -EINVAL; + + val->value.i = esw_r32(esw, RT305X_ESW_REG_P0LED + 4*idx); + + return 0; +} + +static int esw_set_port_led(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + int idx = val->port_vlan; + + if (idx < 0 || idx >= RT305X_ESW_NUM_LEDS) + return -EINVAL; + + esw->ports[idx].led = val->value.i; + + return 0; +} + +static int esw_get_port_pvid(struct switch_dev *dev, int port, int *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + if (port >= RT305X_ESW_NUM_PORTS) + return -EINVAL; + + *val = esw_get_pvid(esw, port); + + return 0; +} + +static int esw_set_port_pvid(struct switch_dev *dev, int port, int val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + if (port >= RT305X_ESW_NUM_PORTS) + return -EINVAL; + + esw->ports[port].pvid = val; + + return 0; +} + +static int esw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + u32 vmsc, poc2; + int vlan_idx = -1; + int i; + + val->len = 0; + + if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS) + return -EINVAL; + + /* valid vlan? */ + for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { + if (esw_get_vlan_id(esw, i) == val->port_vlan && + esw_get_vmsc(esw, i) != RT305X_ESW_PORTS_NONE) { + vlan_idx = i; + break; + } + } + + if (vlan_idx == -1) + return -EINVAL; + + vmsc = esw_get_vmsc(esw, vlan_idx); + poc2 = esw_r32(esw, RT305X_ESW_REG_POC2); + + for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) { + struct switch_port *p; + int port_mask = 1 << i; + + if (!(vmsc & port_mask)) + continue; + + p = &val->value.ports[val->len++]; + p->id = i; + if (poc2 & (port_mask << RT305X_ESW_POC2_UNTAG_EN_S)) + p->flags = 0; + else + p->flags = 1 << SWITCH_PORT_FLAG_TAGGED; + } + + return 0; +} + +static int esw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + int ports; + int vlan_idx = -1; + int i; + + if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS || + val->len > RT305X_ESW_NUM_PORTS) + return -EINVAL; + + /* one of the already defined vlans? */ + for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { + if (esw->vlans[i].vid == val->port_vlan && + esw->vlans[i].ports != RT305X_ESW_PORTS_NONE) { + vlan_idx = i; + break; + } + } + + /* select a free slot */ + for (i = 0; vlan_idx == -1 && i < RT305X_ESW_NUM_VLANS; i++) { + if (esw->vlans[i].ports == RT305X_ESW_PORTS_NONE) + vlan_idx = i; + } + + /* bail if all slots are in use */ + if (vlan_idx == -1) + return -EINVAL; + + ports = RT305X_ESW_PORTS_NONE; + for (i = 0; i < val->len; i++) { + struct switch_port *p = &val->value.ports[i]; + int port_mask = 1 << p->id; + bool untagged = !(p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)); + + if (p->id >= RT305X_ESW_NUM_PORTS) + return -EINVAL; + + ports |= port_mask; + esw->ports[p->id].untag = untagged; + } + esw->vlans[vlan_idx].ports = ports; + if (ports == RT305X_ESW_PORTS_NONE) + esw->vlans[vlan_idx].vid = RT305X_ESW_VLAN_NONE; + else + esw->vlans[vlan_idx].vid = val->port_vlan; + + return 0; +} + +static const struct switch_attr esw_global[] = { + { + .type = SWITCH_TYPE_INT, + .name = "enable_vlan", + .description = "VLAN mode (1:enabled)", + .max = 1, + .id = RT305X_ESW_ATTR_ENABLE_VLAN, + .get = esw_get_vlan_enable, + .set = esw_set_vlan_enable, + }, + { + .type = SWITCH_TYPE_INT, + .name = "alternate_vlan_disable", + .description = "Use en_vlan instead of doubletag to disable" + " VLAN mode", + .max = 1, + .id = RT305X_ESW_ATTR_ALT_VLAN_DISABLE, + .get = esw_get_alt_vlan_disable, + .set = esw_set_alt_vlan_disable, + }, + { + .type = SWITCH_TYPE_INT, + .name = "bc_storm_protect", + .description = "Global broadcast storm protection (0:Disable, 1:64 blocks, 2:96 blocks, 3:128 blocks)", + .max = 3, + .id = RT305X_ESW_ATTR_BC_STATUS, + .get = rt305x_esw_get_bc_status, + .set = rt305x_esw_set_bc_status, + }, + { + .type = SWITCH_TYPE_INT, + .name = "led_frequency", + .description = "LED Flash frequency (0:30mS, 1:60mS, 2:240mS, 3:480mS)", + .max = 3, + .id = RT305X_ESW_ATTR_LED_FREQ, + .get = rt305x_esw_get_led_freq, + .set = rt305x_esw_set_led_freq, + } +}; + +static const struct switch_attr esw_port[] = { + { + .type = SWITCH_TYPE_INT, + .name = "disable", + .description = "Port state (1:disabled)", + .max = 1, + .id = RT305X_ESW_ATTR_PORT_DISABLE, + .get = esw_get_port_bool, + .set = esw_set_port_bool, + }, + { + .type = SWITCH_TYPE_INT, + .name = "doubletag", + .description = "Double tagging for incoming vlan packets " + "(1:enabled)", + .max = 1, + .id = RT305X_ESW_ATTR_PORT_DOUBLETAG, + .get = esw_get_port_bool, + .set = esw_set_port_bool, + }, + { + .type = SWITCH_TYPE_INT, + .name = "untag", + .description = "Untag (1:strip outgoing vlan tag)", + .max = 1, + .id = RT305X_ESW_ATTR_PORT_UNTAG, + .get = esw_get_port_bool, + .set = esw_set_port_bool, + }, + { + .type = SWITCH_TYPE_INT, + .name = "led", + .description = "LED mode (0:link, 1:100m, 2:duplex, 3:activity," + " 4:collision, 5:linkact, 6:duplcoll, 7:10mact," + " 8:100mact, 10:blink, 11:off, 12:on)", + .max = 15, + .id = RT305X_ESW_ATTR_PORT_LED, + .get = esw_get_port_led, + .set = esw_set_port_led, + }, + { + .type = SWITCH_TYPE_INT, + .name = "lan", + .description = "HW port group (0:wan, 1:lan)", + .max = 1, + .id = RT305X_ESW_ATTR_PORT_LAN, + .get = esw_get_port_bool, + }, + { + .type = SWITCH_TYPE_INT, + .name = "recv_bad", + .description = "Receive bad packet counter", + .id = RT305X_ESW_ATTR_PORT_RECV_BAD, + .get = esw_get_port_recv_badgood, + }, + { + .type = SWITCH_TYPE_INT, + .name = "recv_good", + .description = "Receive good packet counter", + .id = RT305X_ESW_ATTR_PORT_RECV_GOOD, + .get = esw_get_port_recv_badgood, + }, + { + .type = SWITCH_TYPE_INT, + .name = "tr_bad", + + .description = "Transmit bad packet counter. rt5350 only", + .id = RT5350_ESW_ATTR_PORT_TR_BAD, + .get = esw_get_port_tr_badgood, + }, + { + .type = SWITCH_TYPE_INT, + .name = "tr_good", + + .description = "Transmit good packet counter. rt5350 only", + .id = RT5350_ESW_ATTR_PORT_TR_GOOD, + .get = esw_get_port_tr_badgood, + }, +}; + +static const struct switch_attr esw_vlan[] = { +}; + +static const struct switch_dev_ops esw_ops = { + .attr_global = { + .attr = esw_global, + .n_attr = ARRAY_SIZE(esw_global), + }, + .attr_port = { + .attr = esw_port, + .n_attr = ARRAY_SIZE(esw_port), + }, + .attr_vlan = { + .attr = esw_vlan, + .n_attr = ARRAY_SIZE(esw_vlan), + }, + .get_vlan_ports = esw_get_vlan_ports, + .set_vlan_ports = esw_set_vlan_ports, + .get_port_pvid = esw_get_port_pvid, + .set_port_pvid = esw_set_port_pvid, + .get_port_link = esw_get_port_link, + .apply_config = esw_apply_config, + .reset_switch = esw_reset_switch, +}; + +static int esw_probe(struct platform_device *pdev) +{ + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + struct device_node *np = pdev->dev.of_node; + const __be32 *port_map, *port_disable, *reg_init; + struct switch_dev *swdev; + struct rt305x_esw *esw; + int ret; + + esw = devm_kzalloc(&pdev->dev, sizeof(*esw), GFP_KERNEL); + if (!esw) + return -ENOMEM; + + esw->dev = &pdev->dev; + esw->irq = irq_of_parse_and_map(np, 0); + esw->base = devm_ioremap_resource(&pdev->dev, res); + if (!esw->base) + return -EADDRNOTAVAIL; + + port_map = of_get_property(np, "mediatek,portmap", NULL); + if (port_map) + esw->port_map = be32_to_cpu(*port_map); + + port_disable = of_get_property(np, "mediatek,portdisable", NULL); + if (port_disable) + esw->port_disable = be32_to_cpu(*port_disable); + + reg_init = of_get_property(np, "ralink,fct2", NULL); + if (reg_init) + esw->reg_initval_fct2 = be32_to_cpu(*reg_init); + + reg_init = of_get_property(np, "ralink,fpa2", NULL); + if (reg_init) + esw->reg_initval_fpa2 = be32_to_cpu(*reg_init); + + reg_init = of_get_property(np, "mediatek,led_polarity", NULL); + if (reg_init) + esw->reg_led_polarity = be32_to_cpu(*reg_init); + + swdev = &esw->swdev; + swdev->of_node = pdev->dev.of_node; + swdev->name = "rt305x-esw"; + swdev->alias = "rt305x"; + swdev->cpu_port = RT305X_ESW_PORT6; + swdev->ports = RT305X_ESW_NUM_PORTS; + swdev->vlans = RT305X_ESW_NUM_VIDS; + swdev->ops = &esw_ops; + + ret = register_switch(swdev, NULL); + if (ret < 0) { + dev_err(&pdev->dev, "register_switch failed\n"); + return ret; + } + + platform_set_drvdata(pdev, esw); + + spin_lock_init(&esw->reg_rw_lock); + + esw_hw_init(esw); + + reg_init = of_get_property(np, "ralink,rgmii", NULL); + if (reg_init && be32_to_cpu(*reg_init) == 1) { + /* + * External switch connected to RGMII interface. + * Unregister the switch device after initialization. + */ + dev_err(&pdev->dev, "RGMII mode, not exporting switch device.\n"); + unregister_switch(&esw->swdev); + platform_set_drvdata(pdev, NULL); + return -ENODEV; + } + + ret = devm_request_irq(&pdev->dev, esw->irq, esw_interrupt, 0, "esw", + esw); + + if (!ret) { + esw_w32(esw, RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_ISR); + esw_w32(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR); + } + + return ret; +} + +static int esw_remove(struct platform_device *pdev) +{ + struct rt305x_esw *esw = platform_get_drvdata(pdev); + + if (esw) { + esw_w32(esw, ~0, RT305X_ESW_REG_IMR); + platform_set_drvdata(pdev, NULL); + } + + return 0; +} + +static const struct of_device_id ralink_esw_match[] = { + { .compatible = "ralink,rt3050-esw" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ralink_esw_match); + +static struct platform_driver esw_driver = { + .probe = esw_probe, + .remove = esw_remove, + .driver = { + .name = "rt3050-esw", + .owner = THIS_MODULE, + .of_match_table = ralink_esw_match, + }, +}; + +module_platform_driver(esw_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("John Crispin "); +MODULE_DESCRIPTION("Switch driver for RT305X SoC"); +MODULE_VERSION(MTK_FE_DRV_VERSION); diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/esw_rt3050.h b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/esw_rt3050.h new file mode 100644 index 000000000..b757e5d63 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/esw_rt3050.h @@ -0,0 +1,29 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#ifndef _RALINK_ESW_RT3052_H__ +#define _RALINK_ESW_RT3052_H__ + +#ifdef CONFIG_NET_MEDIATEK_ESW_RT3052 + +int __init mtk_switch_init(void); +void mtk_switch_exit(void); + +#else + +static inline int __init mtk_switch_init(void) { return 0; } +static inline void mtk_switch_exit(void) { } + +#endif +#endif diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/ethtool.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/ethtool.c new file mode 100644 index 000000000..5732c2853 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/ethtool.c @@ -0,0 +1,230 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#include "mtk_eth_soc.h" + +static const char fe_gdma_str[][ETH_GSTRING_LEN] = { +#define _FE(x...) # x, +FE_STAT_REG_DECLARE +#undef _FE +}; + +static int fe_get_link_ksettings(struct net_device *ndev, + struct ethtool_link_ksettings *cmd) +{ + struct fe_priv *priv = netdev_priv(ndev); + + if (!priv->phy_dev) + return -ENODEV; + + if (priv->phy_flags == FE_PHY_FLAG_ATTACH) { + if (phy_read_status(priv->phy_dev)) + return -ENODEV; + } + + phy_ethtool_ksettings_get(ndev->phydev, cmd); + + return 0; +} + +static int fe_set_link_ksettings(struct net_device *ndev, + const struct ethtool_link_ksettings *cmd) +{ + struct fe_priv *priv = netdev_priv(ndev); + + if (!priv->phy_dev) + goto out_sset; + + if (cmd->base.phy_address != priv->phy_dev->mdio.addr) { + if (priv->phy->phy_node[cmd->base.phy_address]) { + priv->phy_dev = priv->phy->phy[cmd->base.phy_address]; + priv->phy_flags = FE_PHY_FLAG_PORT; + } else if (priv->mii_bus && mdiobus_get_phy(priv->mii_bus, cmd->base.phy_address)) { + priv->phy_dev = mdiobus_get_phy(priv->mii_bus, cmd->base.phy_address); + priv->phy_flags = FE_PHY_FLAG_ATTACH; + } else { + goto out_sset; + } + } + + return phy_ethtool_ksettings_set(ndev->phydev, cmd); + +out_sset: + return -ENODEV; +} + +static void fe_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct fe_priv *priv = netdev_priv(dev); + struct fe_soc_data *soc = priv->soc; + + strlcpy(info->driver, priv->dev->driver->name, sizeof(info->driver)); + strlcpy(info->version, MTK_FE_DRV_VERSION, sizeof(info->version)); + strlcpy(info->bus_info, dev_name(priv->dev), sizeof(info->bus_info)); + + if (soc->reg_table[FE_REG_FE_COUNTER_BASE]) + info->n_stats = ARRAY_SIZE(fe_gdma_str); +} + +static u32 fe_get_msglevel(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + + return priv->msg_enable; +} + +static void fe_set_msglevel(struct net_device *dev, u32 value) +{ + struct fe_priv *priv = netdev_priv(dev); + + priv->msg_enable = value; +} + +static int fe_nway_reset(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + + if (!priv->phy_dev) + goto out_nway_reset; + + return genphy_restart_aneg(priv->phy_dev); + +out_nway_reset: + return -EOPNOTSUPP; +} + +static u32 fe_get_link(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + int err; + + if (!priv->phy_dev) + goto out_get_link; + + if (priv->phy_flags == FE_PHY_FLAG_ATTACH) { + err = genphy_update_link(priv->phy_dev); + if (err) + goto out_get_link; + } + + return priv->phy_dev->link; + +out_get_link: + return ethtool_op_get_link(dev); +} + +static int fe_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) +{ + struct fe_priv *priv = netdev_priv(dev); + + if ((ring->tx_pending < 2) || + (ring->rx_pending < 2) || + (ring->rx_pending > MAX_DMA_DESC) || + (ring->tx_pending > MAX_DMA_DESC)) + return -EINVAL; + + dev->netdev_ops->ndo_stop(dev); + + priv->tx_ring.tx_ring_size = BIT(fls(ring->tx_pending) - 1); + priv->rx_ring.rx_ring_size = BIT(fls(ring->rx_pending) - 1); + + dev->netdev_ops->ndo_open(dev); + + return 0; +} + +static void fe_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) +{ + struct fe_priv *priv = netdev_priv(dev); + + ring->rx_max_pending = MAX_DMA_DESC; + ring->tx_max_pending = MAX_DMA_DESC; + ring->rx_pending = priv->rx_ring.rx_ring_size; + ring->tx_pending = priv->tx_ring.tx_ring_size; +} + +static void fe_get_strings(struct net_device *dev, u32 stringset, u8 *data) +{ + switch (stringset) { + case ETH_SS_STATS: + memcpy(data, *fe_gdma_str, sizeof(fe_gdma_str)); + break; + } +} + +static int fe_get_sset_count(struct net_device *dev, int sset) +{ + switch (sset) { + case ETH_SS_STATS: + return ARRAY_SIZE(fe_gdma_str); + default: + return -EOPNOTSUPP; + } +} + +static void fe_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) +{ + struct fe_priv *priv = netdev_priv(dev); + struct fe_hw_stats *hwstats = priv->hw_stats; + u64 *data_src, *data_dst; + unsigned int start; + int i; + + if (netif_running(dev) && netif_device_present(dev)) { + if (spin_trylock(&hwstats->stats_lock)) { + fe_stats_update(priv); + spin_unlock(&hwstats->stats_lock); + } + } + + do { + data_src = &hwstats->tx_bytes; + data_dst = data; + start = u64_stats_fetch_begin_irq(&hwstats->syncp); + + for (i = 0; i < ARRAY_SIZE(fe_gdma_str); i++) + *data_dst++ = *data_src++; + + } while (u64_stats_fetch_retry_irq(&hwstats->syncp, start)); +} + +static struct ethtool_ops fe_ethtool_ops = { + .get_link_ksettings = fe_get_link_ksettings, + .set_link_ksettings = fe_set_link_ksettings, + .get_drvinfo = fe_get_drvinfo, + .get_msglevel = fe_get_msglevel, + .set_msglevel = fe_set_msglevel, + .nway_reset = fe_nway_reset, + .get_link = fe_get_link, + .set_ringparam = fe_set_ringparam, + .get_ringparam = fe_get_ringparam, +}; + +void fe_set_ethtool_ops(struct net_device *netdev) +{ + struct fe_priv *priv = netdev_priv(netdev); + struct fe_soc_data *soc = priv->soc; + + if (soc->reg_table[FE_REG_FE_COUNTER_BASE]) { + fe_ethtool_ops.get_strings = fe_get_strings; + fe_ethtool_ops.get_sset_count = fe_get_sset_count; + fe_ethtool_ops.get_ethtool_stats = fe_get_ethtool_stats; + } + + netdev->ethtool_ops = &fe_ethtool_ops; +} diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/ethtool.h b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/ethtool.h new file mode 100644 index 000000000..6fd16f0b6 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/ethtool.h @@ -0,0 +1,22 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#ifndef FE_ETHTOOL_H +#define FE_ETHTOOL_H + +#include + +void fe_set_ethtool_ops(struct net_device *netdev); + +#endif /* FE_ETHTOOL_H */ diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/gsw_mt7620.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/gsw_mt7620.c new file mode 100644 index 000000000..4093f09d4 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/gsw_mt7620.c @@ -0,0 +1,260 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "mtk_eth_soc.h" +#include "gsw_mt7620.h" + +void mtk_switch_w32(struct mt7620_gsw *gsw, u32 val, unsigned reg) +{ + iowrite32(val, gsw->base + reg); +} + +u32 mtk_switch_r32(struct mt7620_gsw *gsw, unsigned reg) +{ + return ioread32(gsw->base + reg); +} + +static irqreturn_t gsw_interrupt_mt7620(int irq, void *_priv) +{ + struct fe_priv *priv = (struct fe_priv *)_priv; + struct mt7620_gsw *gsw = (struct mt7620_gsw *)priv->soc->swpriv; + u32 status; + int i, max = (gsw->port4 == PORT4_EPHY) ? (4) : (3); + + status = mtk_switch_r32(gsw, GSW_REG_ISR); + if (status & PORT_IRQ_ST_CHG) + for (i = 0; i <= max; i++) { + u32 status = mtk_switch_r32(gsw, GSW_REG_PORT_STATUS(i)); + int link = status & 0x1; + + if (link != priv->link[i]) + mt7620_print_link_state(priv, i, link, + (status >> 2) & 3, + (status & 0x2)); + + priv->link[i] = link; + } + mt7620_handle_carrier(priv); + mtk_switch_w32(gsw, status, GSW_REG_ISR); + + return IRQ_HANDLED; +} + +static void mt7620_hw_init(struct mt7620_gsw *gsw, struct device_node *np) +{ + u32 is_BGA = (rt_sysc_r32(0x0c) >> 16) & 1; + + rt_sysc_w32(rt_sysc_r32(SYSC_REG_CFG1) | BIT(8), SYSC_REG_CFG1); + mtk_switch_w32(gsw, mtk_switch_r32(gsw, GSW_REG_CKGCR) & ~(0x3 << 4), GSW_REG_CKGCR); + + /* Enable MIB stats */ + mtk_switch_w32(gsw, mtk_switch_r32(gsw, GSW_REG_MIB_CNT_EN) | (1 << 1), GSW_REG_MIB_CNT_EN); + + if (of_property_read_bool(np, "mediatek,mt7530")) { + u32 val; + + /* turn off ephy and set phy base addr to 12 */ + mtk_switch_w32(gsw, mtk_switch_r32(gsw, GSW_REG_GPC1) | + (0x1f << 24) | (0xc << 16), + GSW_REG_GPC1); + + /* set MT7530 central align */ + val = mt7530_mdio_r32(gsw, 0x7830); + val &= ~BIT(0); + val |= BIT(1); + mt7530_mdio_w32(gsw, 0x7830, val); + + val = mt7530_mdio_r32(gsw, 0x7a40); + val &= ~BIT(30); + mt7530_mdio_w32(gsw, 0x7a40, val); + + mt7530_mdio_w32(gsw, 0x7a78, 0x855); + } else { + /* global page 4 */ + _mt7620_mii_write(gsw, 1, 31, 0x4000); + + _mt7620_mii_write(gsw, 1, 17, 0x7444); + if (is_BGA) + _mt7620_mii_write(gsw, 1, 19, 0x0114); + else + _mt7620_mii_write(gsw, 1, 19, 0x0117); + + _mt7620_mii_write(gsw, 1, 22, 0x10cf); + _mt7620_mii_write(gsw, 1, 25, 0x6212); + _mt7620_mii_write(gsw, 1, 26, 0x0777); + _mt7620_mii_write(gsw, 1, 29, 0x4000); + _mt7620_mii_write(gsw, 1, 28, 0xc077); + _mt7620_mii_write(gsw, 1, 24, 0x0000); + + /* global page 3 */ + _mt7620_mii_write(gsw, 1, 31, 0x3000); + _mt7620_mii_write(gsw, 1, 17, 0x4838); + + /* global page 2 */ + _mt7620_mii_write(gsw, 1, 31, 0x2000); + if (is_BGA) { + _mt7620_mii_write(gsw, 1, 21, 0x0515); + _mt7620_mii_write(gsw, 1, 22, 0x0053); + _mt7620_mii_write(gsw, 1, 23, 0x00bf); + _mt7620_mii_write(gsw, 1, 24, 0x0aaf); + _mt7620_mii_write(gsw, 1, 25, 0x0fad); + _mt7620_mii_write(gsw, 1, 26, 0x0fc1); + } else { + _mt7620_mii_write(gsw, 1, 21, 0x0517); + _mt7620_mii_write(gsw, 1, 22, 0x0fd2); + _mt7620_mii_write(gsw, 1, 23, 0x00bf); + _mt7620_mii_write(gsw, 1, 24, 0x0aab); + _mt7620_mii_write(gsw, 1, 25, 0x00ae); + _mt7620_mii_write(gsw, 1, 26, 0x0fff); + } + /* global page 1 */ + _mt7620_mii_write(gsw, 1, 31, 0x1000); + _mt7620_mii_write(gsw, 1, 17, 0xe7f8); + } + + /* global page 0 */ + _mt7620_mii_write(gsw, 1, 31, 0x8000); + _mt7620_mii_write(gsw, 0, 30, 0xa000); + _mt7620_mii_write(gsw, 1, 30, 0xa000); + _mt7620_mii_write(gsw, 2, 30, 0xa000); + _mt7620_mii_write(gsw, 3, 30, 0xa000); + + _mt7620_mii_write(gsw, 0, 4, 0x05e1); + _mt7620_mii_write(gsw, 1, 4, 0x05e1); + _mt7620_mii_write(gsw, 2, 4, 0x05e1); + _mt7620_mii_write(gsw, 3, 4, 0x05e1); + + /* global page 2 */ + _mt7620_mii_write(gsw, 1, 31, 0xa000); + _mt7620_mii_write(gsw, 0, 16, 0x1111); + _mt7620_mii_write(gsw, 1, 16, 0x1010); + _mt7620_mii_write(gsw, 2, 16, 0x1515); + _mt7620_mii_write(gsw, 3, 16, 0x0f0f); + + /* CPU Port6 Force Link 1G, FC ON */ + mtk_switch_w32(gsw, 0x5e33b, GSW_REG_PORT_PMCR(6)); + + /* Set Port 6 as CPU Port */ + mtk_switch_w32(gsw, 0x7f7f7fe0, 0x0010); + + /* setup port 4 */ + if (gsw->port4 == PORT4_EPHY) { + u32 val = rt_sysc_r32(SYSC_REG_CFG1); + + val |= 3 << 14; + rt_sysc_w32(val, SYSC_REG_CFG1); + _mt7620_mii_write(gsw, 4, 30, 0xa000); + _mt7620_mii_write(gsw, 4, 4, 0x05e1); + _mt7620_mii_write(gsw, 4, 16, 0x1313); + _mt7620_mii_write(gsw, 4, 0, 0x3100); + pr_info("gsw: setting port4 to ephy mode\n"); + } +} + +static const struct of_device_id mediatek_gsw_match[] = { + { .compatible = "mediatek,mt7620-gsw" }, + {}, +}; +MODULE_DEVICE_TABLE(of, mediatek_gsw_match); + +int mtk_gsw_init(struct fe_priv *priv) +{ + struct device_node *np = priv->switch_np; + struct platform_device *pdev = of_find_device_by_node(np); + struct mt7620_gsw *gsw; + + if (!pdev) + return -ENODEV; + + if (!of_device_is_compatible(np, mediatek_gsw_match->compatible)) + return -EINVAL; + + gsw = platform_get_drvdata(pdev); + priv->soc->swpriv = gsw; + + mt7620_hw_init(gsw, np); + + if (gsw->irq) { + request_irq(gsw->irq, gsw_interrupt_mt7620, 0, + "gsw", priv); + mtk_switch_w32(gsw, ~PORT_IRQ_ST_CHG, GSW_REG_IMR); + } + + return 0; +} + +static int mt7620_gsw_probe(struct platform_device *pdev) +{ + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + const char *port4 = NULL; + struct mt7620_gsw *gsw; + struct device_node *np = pdev->dev.of_node; + + gsw = devm_kzalloc(&pdev->dev, sizeof(struct mt7620_gsw), GFP_KERNEL); + if (!gsw) + return -ENOMEM; + + gsw->base = devm_ioremap_resource(&pdev->dev, res); + if (!gsw->base) + return -EADDRNOTAVAIL; + + gsw->dev = &pdev->dev; + + of_property_read_string(np, "mediatek,port4", &port4); + if (port4 && !strcmp(port4, "ephy")) + gsw->port4 = PORT4_EPHY; + else if (port4 && !strcmp(port4, "gmac")) + gsw->port4 = PORT4_EXT; + else + gsw->port4 = PORT4_EPHY; + + gsw->irq = platform_get_irq(pdev, 0); + + platform_set_drvdata(pdev, gsw); + + return 0; +} + +static int mt7620_gsw_remove(struct platform_device *pdev) +{ + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver gsw_driver = { + .probe = mt7620_gsw_probe, + .remove = mt7620_gsw_remove, + .driver = { + .name = "mt7620-gsw", + .owner = THIS_MODULE, + .of_match_table = mediatek_gsw_match, + }, +}; + +module_platform_driver(gsw_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("John Crispin "); +MODULE_DESCRIPTION("GBit switch driver for Mediatek MT7620 SoC"); +MODULE_VERSION(MTK_FE_DRV_VERSION); diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/gsw_mt7620.h b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/gsw_mt7620.h new file mode 100644 index 000000000..ae0b6de02 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/gsw_mt7620.h @@ -0,0 +1,127 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#ifndef _RALINK_GSW_MT7620_H__ +#define _RALINK_GSW_MT7620_H__ + +#define GSW_REG_PHY_TIMEOUT (5 * HZ) + +#ifdef CONFIG_SOC_MT7621 +#define MT7620A_GSW_REG_PIAC 0x0004 +#else +#define MT7620A_GSW_REG_PIAC 0x7004 +#endif + +#define GSW_NUM_VLANS 16 +#define GSW_NUM_VIDS 4096 +#define GSW_NUM_PORTS 7 +#define GSW_PORT6 6 + +#define GSW_MDIO_ACCESS BIT(31) +#define GSW_MDIO_READ BIT(19) +#define GSW_MDIO_WRITE BIT(18) +#define GSW_MDIO_START BIT(16) +#define GSW_MDIO_ADDR_SHIFT 20 +#define GSW_MDIO_REG_SHIFT 25 + +#define GSW_REG_MIB_CNT_EN 0x4000 + +#define GSW_REG_PORT_PMCR(x) (0x3000 + (x * 0x100)) +#define GSW_REG_PORT_STATUS(x) (0x3008 + (x * 0x100)) +#define GSW_REG_SMACCR0 0x3fE4 +#define GSW_REG_SMACCR1 0x3fE8 +#define GSW_REG_CKGCR 0x3ff0 + +#define GSW_REG_IMR 0x7008 +#define GSW_REG_ISR 0x700c +#define GSW_REG_GPC1 0x7014 + +#define GSW_REG_MAC_P0_MCR 0x100 +#define GSW_REG_MAC_P1_MCR 0x200 + +// Global MAC control register +#define GSW_REG_GMACCR 0x30E0 + +#define SYSC_REG_CHIP_REV_ID 0x0c +#define SYSC_REG_CFG1 0x14 +#define RST_CTRL_MCM BIT(2) +#define SYSC_PAD_RGMII2_MDIO 0x58 +#define SYSC_GPIO_MODE 0x60 + +#define PORT_IRQ_ST_CHG 0x7f + +#ifdef CONFIG_SOC_MT7621 +#define ESW_PHY_POLLING 0x0000 +#else +#define ESW_PHY_POLLING 0x7000 +#endif + +#define PMCR_IPG BIT(18) +#define PMCR_MAC_MODE BIT(16) +#define PMCR_FORCE BIT(15) +#define PMCR_TX_EN BIT(14) +#define PMCR_RX_EN BIT(13) +#define PMCR_BACKOFF BIT(9) +#define PMCR_BACKPRES BIT(8) +#define PMCR_RX_FC BIT(5) +#define PMCR_TX_FC BIT(4) +#define PMCR_SPEED(_x) (_x << 2) +#define PMCR_DUPLEX BIT(1) +#define PMCR_LINK BIT(0) + +#define PHY_AN_EN BIT(31) +#define PHY_PRE_EN BIT(30) +#define PMY_MDC_CONF(_x) ((_x & 0x3f) << 24) + + +enum { + /* Global attributes. */ + GSW_ATTR_ENABLE_VLAN, + /* Port attributes. */ + GSW_ATTR_PORT_UNTAG, +}; + +enum { + PORT4_EPHY = 0, + PORT4_EXT, +}; + +struct mt7620_gsw { + struct device *dev; + void __iomem *base; + int irq; + int port4; + unsigned long int autopoll; +}; + +void mtk_switch_w32(struct mt7620_gsw *gsw, u32 val, unsigned reg); +u32 mtk_switch_r32(struct mt7620_gsw *gsw, unsigned reg); +int mtk_gsw_init(struct fe_priv *priv); + +int mt7620_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val); +int mt7620_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg); +void mt7620_mdio_link_adjust(struct fe_priv *priv, int port); +int mt7620_has_carrier(struct fe_priv *priv); +void mt7620_print_link_state(struct fe_priv *priv, int port, int link, + int speed, int duplex); + +void mt7530_mdio_w32(struct mt7620_gsw *gsw, u32 reg, u32 val); +u32 mt7530_mdio_r32(struct mt7620_gsw *gsw, u32 reg); + +u32 _mt7620_mii_write(struct mt7620_gsw *gsw, u32 phy_addr, + u32 phy_register, u32 write_data); +u32 _mt7620_mii_read(struct mt7620_gsw *gsw, int phy_addr, int phy_reg); +void mt7620_handle_carrier(struct fe_priv *priv); + +#endif diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/gsw_mt7621.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/gsw_mt7621.c new file mode 100644 index 000000000..9d5fe6efe --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/gsw_mt7621.c @@ -0,0 +1,281 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "mtk_eth_soc.h" +#include "gsw_mt7620.h" + +void mtk_switch_w32(struct mt7620_gsw *gsw, u32 val, unsigned reg) +{ + iowrite32(val, gsw->base + reg); +} + +u32 mtk_switch_r32(struct mt7620_gsw *gsw, unsigned reg) +{ + return ioread32(gsw->base + reg); +} + +static irqreturn_t gsw_interrupt_mt7621(int irq, void *_priv) +{ + struct fe_priv *priv = (struct fe_priv *)_priv; + struct mt7620_gsw *gsw = (struct mt7620_gsw *)priv->soc->swpriv; + u32 reg, i; + + reg = mt7530_mdio_r32(gsw, 0x700c); + mt7530_mdio_w32(gsw, 0x700c, reg); + + for (i = 0; i < 5; i++) + if (reg & BIT(i)) { + unsigned int link; + + link = mt7530_mdio_r32(gsw, + 0x3008 + (i * 0x100)) & 0x1; + + if (link != priv->link[i]) { + priv->link[i] = link; + if (link) + netdev_info(priv->netdev, + "port %d link up\n", i); + else + netdev_info(priv->netdev, + "port %d link down\n", i); + } + } + + mt7620_handle_carrier(priv); + + return IRQ_HANDLED; +} + +static void mt7621_hw_init(struct mt7620_gsw *gsw, struct device_node *np) +{ + u32 i; + u32 val; + + /* wardware reset the switch */ + fe_reset(RST_CTRL_MCM); + mdelay(10); + + /* reduce RGMII2 PAD driving strength */ + rt_sysc_m32(3 << 4, 0, SYSC_PAD_RGMII2_MDIO); + + /* gpio mux - RGMII1=Normal mode */ + rt_sysc_m32(BIT(14), 0, SYSC_GPIO_MODE); + + /* set GMAC1 RGMII mode */ + rt_sysc_m32(3 << 12, 0, SYSC_REG_CFG1); + + /* enable MDIO to control MT7530 */ + rt_sysc_m32(3 << 12, 0, SYSC_GPIO_MODE); + + /* turn off all PHYs */ + for (i = 0; i <= 4; i++) { + val = _mt7620_mii_read(gsw, i, 0x0); + val |= BIT(11); + _mt7620_mii_write(gsw, i, 0x0, val); + } + + /* reset the switch */ + mt7530_mdio_w32(gsw, 0x7000, 0x3); + usleep_range(10, 20); + + if ((rt_sysc_r32(SYSC_REG_CHIP_REV_ID) & 0xFFFF) == 0x0101) { + /* (GE1, Force 1000M/FD, FC ON, MAX_RX_LENGTH 1536) */ + mtk_switch_w32(gsw, 0x2305e30b, GSW_REG_MAC_P0_MCR); + mt7530_mdio_w32(gsw, 0x3600, 0x5e30b); + } else { + /* (GE1, Force 1000M/FD, FC ON, MAX_RX_LENGTH 1536) */ + mtk_switch_w32(gsw, 0x2305e33b, GSW_REG_MAC_P0_MCR); + mt7530_mdio_w32(gsw, 0x3600, 0x5e33b); + } + + /* (GE2, Link down) */ + mtk_switch_w32(gsw, 0x8000, GSW_REG_MAC_P1_MCR); + + /* Set switch max RX frame length to 2k */ + mt7530_mdio_w32(gsw, GSW_REG_GMACCR, 0x3F0B); + + /* Enable Port 6, P5 as GMAC5, P5 disable */ + val = mt7530_mdio_r32(gsw, 0x7804); + val &= ~BIT(8); + val |= BIT(6) | BIT(13) | BIT(16); + mt7530_mdio_w32(gsw, 0x7804, val); + + val = rt_sysc_r32(0x10); + val = (val >> 6) & 0x7; + if (val >= 6) { + /* 25Mhz Xtal - do nothing */ + } else if (val >= 3) { + /* 40Mhz */ + + /* disable MT7530 core clock */ + _mt7620_mii_write(gsw, 0, 13, 0x1f); + _mt7620_mii_write(gsw, 0, 14, 0x410); + _mt7620_mii_write(gsw, 0, 13, 0x401f); + _mt7620_mii_write(gsw, 0, 14, 0x0); + + /* disable MT7530 PLL */ + _mt7620_mii_write(gsw, 0, 13, 0x1f); + _mt7620_mii_write(gsw, 0, 14, 0x40d); + _mt7620_mii_write(gsw, 0, 13, 0x401f); + _mt7620_mii_write(gsw, 0, 14, 0x2020); + + /* for MT7530 core clock = 500Mhz */ + _mt7620_mii_write(gsw, 0, 13, 0x1f); + _mt7620_mii_write(gsw, 0, 14, 0x40e); + _mt7620_mii_write(gsw, 0, 13, 0x401f); + _mt7620_mii_write(gsw, 0, 14, 0x119); + + /* enable MT7530 PLL */ + _mt7620_mii_write(gsw, 0, 13, 0x1f); + _mt7620_mii_write(gsw, 0, 14, 0x40d); + _mt7620_mii_write(gsw, 0, 13, 0x401f); + _mt7620_mii_write(gsw, 0, 14, 0x2820); + + usleep_range(20, 40); + + /* enable MT7530 core clock */ + _mt7620_mii_write(gsw, 0, 13, 0x1f); + _mt7620_mii_write(gsw, 0, 14, 0x410); + _mt7620_mii_write(gsw, 0, 13, 0x401f); + } else { + /* 20Mhz Xtal - TODO */ + } + + /* RGMII */ + _mt7620_mii_write(gsw, 0, 14, 0x1); + + /* set MT7530 central align */ + val = mt7530_mdio_r32(gsw, 0x7830); + val &= ~BIT(0); + val |= BIT(1); + mt7530_mdio_w32(gsw, 0x7830, val); + val = mt7530_mdio_r32(gsw, 0x7a40); + val &= ~BIT(30); + mt7530_mdio_w32(gsw, 0x7a40, val); + mt7530_mdio_w32(gsw, 0x7a78, 0x855); + + /* delay setting for 10/1000M */ + mt7530_mdio_w32(gsw, 0x7b00, 0x102); + mt7530_mdio_w32(gsw, 0x7b04, 0x14); + + /* lower Tx Driving*/ + mt7530_mdio_w32(gsw, 0x7a54, 0x44); + mt7530_mdio_w32(gsw, 0x7a5c, 0x44); + mt7530_mdio_w32(gsw, 0x7a64, 0x44); + mt7530_mdio_w32(gsw, 0x7a6c, 0x44); + mt7530_mdio_w32(gsw, 0x7a74, 0x44); + mt7530_mdio_w32(gsw, 0x7a7c, 0x44); + + /* turn on all PHYs */ + for (i = 0; i <= 4; i++) { + val = _mt7620_mii_read(gsw, i, 0); + val &= ~BIT(11); + _mt7620_mii_write(gsw, i, 0, val); + } + + /* enable irq */ + mt7530_mdio_w32(gsw, 0x7008, 0x1f); + val = mt7530_mdio_r32(gsw, 0x7808); + val |= 3 << 16; + mt7530_mdio_w32(gsw, 0x7808, val); +} + +static const struct of_device_id mediatek_gsw_match[] = { + { .compatible = "mediatek,mt7621-gsw" }, + {}, +}; +MODULE_DEVICE_TABLE(of, mediatek_gsw_match); + +int mtk_gsw_init(struct fe_priv *priv) +{ + struct device_node *np = priv->switch_np; + struct platform_device *pdev = of_find_device_by_node(np); + struct mt7620_gsw *gsw; + + if (!pdev) + return -ENODEV; + + if (!of_device_is_compatible(np, mediatek_gsw_match->compatible)) + return -EINVAL; + + gsw = platform_get_drvdata(pdev); + priv->soc->swpriv = gsw; + + if (gsw->irq) { + request_irq(gsw->irq, gsw_interrupt_mt7621, 0, + "gsw", priv); + disable_irq(gsw->irq); + } + + mt7621_hw_init(gsw, np); + + if (gsw->irq) + enable_irq(gsw->irq); + + return 0; +} + +static int mt7621_gsw_probe(struct platform_device *pdev) +{ + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + struct mt7620_gsw *gsw; + + gsw = devm_kzalloc(&pdev->dev, sizeof(struct mt7620_gsw), GFP_KERNEL); + if (!gsw) + return -ENOMEM; + + gsw->base = devm_ioremap_resource(&pdev->dev, res); + if (!gsw->base) + return -EADDRNOTAVAIL; + + gsw->dev = &pdev->dev; + gsw->irq = platform_get_irq(pdev, 0); + + platform_set_drvdata(pdev, gsw); + + return 0; +} + +static int mt7621_gsw_remove(struct platform_device *pdev) +{ + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver gsw_driver = { + .probe = mt7621_gsw_probe, + .remove = mt7621_gsw_remove, + .driver = { + .name = "mt7621-gsw", + .owner = THIS_MODULE, + .of_match_table = mediatek_gsw_match, + }, +}; + +module_platform_driver(gsw_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("John Crispin "); +MODULE_DESCRIPTION("GBit switch driver for Mediatek MT7621 SoC"); +MODULE_VERSION(MTK_FE_DRV_VERSION); diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mdio.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mdio.c new file mode 100644 index 000000000..c01055227 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mdio.c @@ -0,0 +1,259 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#include +#include +#include +#include +#include + +#include "mtk_eth_soc.h" +#include "mdio.h" + +static int fe_mdio_reset(struct mii_bus *bus) +{ + /* TODO */ + return 0; +} + +static void fe_phy_link_adjust(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + unsigned long flags; + int i; + + spin_lock_irqsave(&priv->phy->lock, flags); + for (i = 0; i < 8; i++) { + if (priv->phy->phy_node[i]) { + struct phy_device *phydev = priv->phy->phy[i]; + int status_change = 0; + + if (phydev->link) + if (priv->phy->duplex[i] != phydev->duplex || + priv->phy->speed[i] != phydev->speed) + status_change = 1; + + if (phydev->link != priv->link[i]) + status_change = 1; + + switch (phydev->speed) { + case SPEED_1000: + case SPEED_100: + case SPEED_10: + priv->link[i] = phydev->link; + priv->phy->duplex[i] = phydev->duplex; + priv->phy->speed[i] = phydev->speed; + + if (status_change && + priv->soc->mdio_adjust_link) + priv->soc->mdio_adjust_link(priv, i); + break; + } + } + } +} + +int fe_connect_phy_node(struct fe_priv *priv, struct device_node *phy_node) +{ + const __be32 *_port = NULL; + struct phy_device *phydev; + int phy_mode, port; + + _port = of_get_property(phy_node, "reg", NULL); + + if (!_port || (be32_to_cpu(*_port) >= 0x20)) { + pr_err("%s: invalid port id\n", phy_node->name); + return -EINVAL; + } + port = be32_to_cpu(*_port); + phy_mode = of_get_phy_mode(phy_node); + if (phy_mode < 0) { + dev_err(priv->dev, "incorrect phy-mode %d\n", phy_mode); + priv->phy->phy_node[port] = NULL; + return -EINVAL; + } + + phydev = of_phy_connect(priv->netdev, phy_node, fe_phy_link_adjust, + 0, phy_mode); + if (IS_ERR(phydev)) { + dev_err(priv->dev, "could not connect to PHY\n"); + priv->phy->phy_node[port] = NULL; + return PTR_ERR(phydev); + } + + phydev->supported &= PHY_GBIT_FEATURES; + phydev->advertising = phydev->supported; + phydev->no_auto_carrier_off = 1; + + dev_info(priv->dev, + "connected port %d to PHY at %s [uid=%08x, driver=%s]\n", + port, dev_name(&phydev->mdio.dev), phydev->phy_id, + phydev->drv->name); + + priv->phy->phy[port] = phydev; + priv->link[port] = 0; + + return 0; +} + +static void phy_init(struct fe_priv *priv, struct phy_device *phy) +{ + phy_attach(priv->netdev, dev_name(&phy->mdio.dev), PHY_INTERFACE_MODE_MII); + + phy->autoneg = AUTONEG_ENABLE; + phy->speed = 0; + phy->duplex = 0; + phy->supported &= PHY_BASIC_FEATURES; + phy->advertising = phy->supported | ADVERTISED_Autoneg; + + phy_start_aneg(phy); +} + +static int fe_phy_connect(struct fe_priv *priv) +{ + int i; + + for (i = 0; i < 8; i++) { + if (priv->phy->phy_node[i]) { + if (!priv->phy_dev) { + priv->phy_dev = priv->phy->phy[i]; + priv->phy_flags = FE_PHY_FLAG_PORT; + } + } else if (priv->mii_bus && mdiobus_get_phy(priv->mii_bus, i)) { + phy_init(priv, mdiobus_get_phy(priv->mii_bus, i)); + if (!priv->phy_dev) { + priv->phy_dev = mdiobus_get_phy(priv->mii_bus, i); + priv->phy_flags = FE_PHY_FLAG_ATTACH; + } + } + } + + return 0; +} + +static void fe_phy_disconnect(struct fe_priv *priv) +{ + unsigned long flags; + int i; + + for (i = 0; i < 8; i++) + if (priv->phy->phy_fixed[i]) { + spin_lock_irqsave(&priv->phy->lock, flags); + priv->link[i] = 0; + if (priv->soc->mdio_adjust_link) + priv->soc->mdio_adjust_link(priv, i); + spin_unlock_irqrestore(&priv->phy->lock, flags); + } else if (priv->phy->phy[i]) { + phy_disconnect(priv->phy->phy[i]); + } else if (priv->mii_bus && mdiobus_get_phy(priv->mii_bus, i)) { + phy_detach(mdiobus_get_phy(priv->mii_bus, i)); + } +} + +static void fe_phy_start(struct fe_priv *priv) +{ + unsigned long flags; + int i; + + for (i = 0; i < 8; i++) { + if (priv->phy->phy_fixed[i]) { + spin_lock_irqsave(&priv->phy->lock, flags); + priv->link[i] = 1; + if (priv->soc->mdio_adjust_link) + priv->soc->mdio_adjust_link(priv, i); + spin_unlock_irqrestore(&priv->phy->lock, flags); + } else if (priv->phy->phy[i]) { + phy_start(priv->phy->phy[i]); + } + } +} + +static void fe_phy_stop(struct fe_priv *priv) +{ + unsigned long flags; + int i; + + for (i = 0; i < 8; i++) + if (priv->phy->phy_fixed[i]) { + spin_lock_irqsave(&priv->phy->lock, flags); + priv->link[i] = 0; + if (priv->soc->mdio_adjust_link) + priv->soc->mdio_adjust_link(priv, i); + spin_unlock_irqrestore(&priv->phy->lock, flags); + } else if (priv->phy->phy[i]) { + phy_stop(priv->phy->phy[i]); + } +} + +static struct fe_phy phy_ralink = { + .connect = fe_phy_connect, + .disconnect = fe_phy_disconnect, + .start = fe_phy_start, + .stop = fe_phy_stop, +}; + +int fe_mdio_init(struct fe_priv *priv) +{ + struct device_node *mii_np; + int err; + + if (!priv->soc->mdio_read || !priv->soc->mdio_write) + return 0; + + spin_lock_init(&phy_ralink.lock); + priv->phy = &phy_ralink; + + mii_np = of_get_child_by_name(priv->dev->of_node, "mdio-bus"); + if (!mii_np) { + dev_err(priv->dev, "no %s child node found", "mdio-bus"); + return -ENODEV; + } + + if (!of_device_is_available(mii_np)) { + err = 0; + goto err_put_node; + } + + priv->mii_bus = mdiobus_alloc(); + if (!priv->mii_bus) { + err = -ENOMEM; + goto err_put_node; + } + + priv->mii_bus->name = "mdio"; + priv->mii_bus->read = priv->soc->mdio_read; + priv->mii_bus->write = priv->soc->mdio_write; + priv->mii_bus->reset = fe_mdio_reset; + priv->mii_bus->priv = priv; + priv->mii_bus->parent = priv->dev; + + snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s", mii_np->name); + err = of_mdiobus_register(priv->mii_bus, mii_np); + if (err) + goto err_free_bus; + + return 0; + +err_free_bus: + kfree(priv->mii_bus); +err_put_node: + of_node_put(mii_np); + priv->mii_bus = NULL; + return err; +} + +void fe_mdio_cleanup(struct fe_priv *priv) +{ + if (!priv->mii_bus) + return; + + mdiobus_unregister(priv->mii_bus); + of_node_put(priv->mii_bus->dev.of_node); + kfree(priv->mii_bus); +} diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mdio.h b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mdio.h new file mode 100644 index 000000000..498cf144e --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mdio.h @@ -0,0 +1,27 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#ifndef _RALINK_MDIO_H__ +#define _RALINK_MDIO_H__ + +#ifdef CONFIG_NET_MEDIATEK_MDIO +int fe_mdio_init(struct fe_priv *priv); +void fe_mdio_cleanup(struct fe_priv *priv); +int fe_connect_phy_node(struct fe_priv *priv, + struct device_node *phy_node); +#else +static inline int fe_mdio_init(struct fe_priv *priv) { return 0; } +static inline void fe_mdio_cleanup(struct fe_priv *priv) {} +#endif +#endif diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mdio_mt7620.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mdio_mt7620.c new file mode 100644 index 000000000..9efe7896a --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mdio_mt7620.c @@ -0,0 +1,168 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#include +#include +#include + +#include "mtk_eth_soc.h" +#include "gsw_mt7620.h" +#include "mdio.h" + +static int mt7620_mii_busy_wait(struct mt7620_gsw *gsw) +{ + unsigned long t_start = jiffies; + + while (1) { + if (!(mtk_switch_r32(gsw, MT7620A_GSW_REG_PIAC) & GSW_MDIO_ACCESS)) + return 0; + if (time_after(jiffies, t_start + GSW_REG_PHY_TIMEOUT)) + break; + } + + dev_err(gsw->dev, "mdio: MDIO timeout\n"); + return -1; +} + +u32 _mt7620_mii_write(struct mt7620_gsw *gsw, u32 phy_addr, + u32 phy_register, u32 write_data) +{ + if (mt7620_mii_busy_wait(gsw)) + return -1; + + write_data &= 0xffff; + + mtk_switch_w32(gsw, GSW_MDIO_ACCESS | GSW_MDIO_START | GSW_MDIO_WRITE | + (phy_register << GSW_MDIO_REG_SHIFT) | + (phy_addr << GSW_MDIO_ADDR_SHIFT) | write_data, + MT7620A_GSW_REG_PIAC); + + if (mt7620_mii_busy_wait(gsw)) + return -1; + + return 0; +} + +u32 _mt7620_mii_read(struct mt7620_gsw *gsw, int phy_addr, int phy_reg) +{ + u32 d; + + if (mt7620_mii_busy_wait(gsw)) + return 0xffff; + + mtk_switch_w32(gsw, GSW_MDIO_ACCESS | GSW_MDIO_START | GSW_MDIO_READ | + (phy_reg << GSW_MDIO_REG_SHIFT) | + (phy_addr << GSW_MDIO_ADDR_SHIFT), + MT7620A_GSW_REG_PIAC); + + if (mt7620_mii_busy_wait(gsw)) + return 0xffff; + + d = mtk_switch_r32(gsw, MT7620A_GSW_REG_PIAC) & 0xffff; + + return d; +} + +int mt7620_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val) +{ + struct fe_priv *priv = bus->priv; + struct mt7620_gsw *gsw = (struct mt7620_gsw *)priv->soc->swpriv; + + return _mt7620_mii_write(gsw, phy_addr, phy_reg, val); +} + +int mt7620_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg) +{ + struct fe_priv *priv = bus->priv; + struct mt7620_gsw *gsw = (struct mt7620_gsw *)priv->soc->swpriv; + + return _mt7620_mii_read(gsw, phy_addr, phy_reg); +} + +void mt7530_mdio_w32(struct mt7620_gsw *gsw, u32 reg, u32 val) +{ + _mt7620_mii_write(gsw, 0x1f, 0x1f, (reg >> 6) & 0x3ff); + _mt7620_mii_write(gsw, 0x1f, (reg >> 2) & 0xf, val & 0xffff); + _mt7620_mii_write(gsw, 0x1f, 0x10, val >> 16); +} + +u32 mt7530_mdio_r32(struct mt7620_gsw *gsw, u32 reg) +{ + u16 high, low; + + _mt7620_mii_write(gsw, 0x1f, 0x1f, (reg >> 6) & 0x3ff); + low = _mt7620_mii_read(gsw, 0x1f, (reg >> 2) & 0xf); + high = _mt7620_mii_read(gsw, 0x1f, 0x10); + + return (high << 16) | (low & 0xffff); +} + +static unsigned char *fe_speed_str(int speed) +{ + switch (speed) { + case 2: + case SPEED_1000: + return "1000"; + case 1: + case SPEED_100: + return "100"; + case 0: + case SPEED_10: + return "10"; + } + + return "? "; +} + +int mt7620_has_carrier(struct fe_priv *priv) +{ + struct mt7620_gsw *gsw = (struct mt7620_gsw *)priv->soc->swpriv; + int i; + + for (i = 0; i < GSW_PORT6; i++) + if (mtk_switch_r32(gsw, GSW_REG_PORT_STATUS(i)) & 0x1) + return 1; + return 0; +} + + +void mt7620_handle_carrier(struct fe_priv *priv) +{ + if (!priv->phy) + return; + + if (mt7620_has_carrier(priv)) + netif_carrier_on(priv->netdev); + else + netif_carrier_off(priv->netdev); +} + +void mt7620_print_link_state(struct fe_priv *priv, int port, int link, + int speed, int duplex) +{ + if (link) + netdev_info(priv->netdev, "port %d link up (%sMbps/%s duplex)\n", + port, fe_speed_str(speed), + (duplex) ? "Full" : "Half"); + else + netdev_info(priv->netdev, "port %d link down\n", port); +} + +void mt7620_mdio_link_adjust(struct fe_priv *priv, int port) +{ + mt7620_print_link_state(priv, port, priv->link[port], + priv->phy->speed[port], + (priv->phy->duplex[port] == DUPLEX_FULL)); + mt7620_handle_carrier(priv); +} diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mdio_rt2880.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mdio_rt2880.c new file mode 100644 index 000000000..e53fd7f62 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mdio_rt2880.c @@ -0,0 +1,222 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#include +#include +#include +#include +#include + +#include "mtk_eth_soc.h" +#include "mdio_rt2880.h" +#include "mdio.h" + +#define FE_MDIO_RETRY 1000 + +static unsigned char *rt2880_speed_str(struct fe_priv *priv) +{ + switch (priv->phy->speed[0]) { + case SPEED_1000: + return "1000"; + case SPEED_100: + return "100"; + case SPEED_10: + return "10"; + } + + return "?"; +} + +void rt2880_mdio_link_adjust(struct fe_priv *priv, int port) +{ + u32 mdio_cfg; + + if (!priv->link[0]) { + netif_carrier_off(priv->netdev); + netdev_info(priv->netdev, "link down\n"); + return; + } + + mdio_cfg = FE_MDIO_CFG_TX_CLK_SKEW_200 | + FE_MDIO_CFG_RX_CLK_SKEW_200 | + FE_MDIO_CFG_GP1_FRC_EN; + + if (priv->phy->duplex[0] == DUPLEX_FULL) + mdio_cfg |= FE_MDIO_CFG_GP1_DUPLEX; + + if (priv->phy->tx_fc[0]) + mdio_cfg |= FE_MDIO_CFG_GP1_FC_TX; + + if (priv->phy->rx_fc[0]) + mdio_cfg |= FE_MDIO_CFG_GP1_FC_RX; + + switch (priv->phy->speed[0]) { + case SPEED_10: + mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_10; + break; + case SPEED_100: + mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_100; + break; + case SPEED_1000: + mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_1000; + break; + default: + BUG(); + } + + fe_w32(mdio_cfg, FE_MDIO_CFG); + + netif_carrier_on(priv->netdev); + netdev_info(priv->netdev, "link up (%sMbps/%s duplex)\n", + rt2880_speed_str(priv), + (priv->phy->duplex[0] == DUPLEX_FULL) ? "Full" : "Half"); +} + +static int rt2880_mdio_wait_ready(struct fe_priv *priv) +{ + int retries; + + retries = FE_MDIO_RETRY; + while (1) { + u32 t; + + t = fe_r32(FE_MDIO_ACCESS); + if ((t & BIT(31)) == 0) + return 0; + + if (retries-- == 0) + break; + + udelay(1); + } + + dev_err(priv->dev, "MDIO operation timed out\n"); + return -ETIMEDOUT; +} + +int rt2880_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg) +{ + struct fe_priv *priv = bus->priv; + int err; + u32 t; + + err = rt2880_mdio_wait_ready(priv); + if (err) + return 0xffff; + + t = (phy_addr << 24) | (phy_reg << 16); + fe_w32(t, FE_MDIO_ACCESS); + t |= BIT(31); + fe_w32(t, FE_MDIO_ACCESS); + + err = rt2880_mdio_wait_ready(priv); + if (err) + return 0xffff; + + pr_debug("%s: addr=%04x, reg=%04x, value=%04x\n", __func__, + phy_addr, phy_reg, fe_r32(FE_MDIO_ACCESS) & 0xffff); + + return fe_r32(FE_MDIO_ACCESS) & 0xffff; +} + +int rt2880_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val) +{ + struct fe_priv *priv = bus->priv; + int err; + u32 t; + + pr_debug("%s: addr=%04x, reg=%04x, value=%04x\n", __func__, + phy_addr, phy_reg, fe_r32(FE_MDIO_ACCESS) & 0xffff); + + err = rt2880_mdio_wait_ready(priv); + if (err) + return err; + + t = (1 << 30) | (phy_addr << 24) | (phy_reg << 16) | val; + fe_w32(t, FE_MDIO_ACCESS); + t |= BIT(31); + fe_w32(t, FE_MDIO_ACCESS); + + return rt2880_mdio_wait_ready(priv); +} + +void rt2880_port_init(struct fe_priv *priv, struct device_node *np) +{ + const __be32 *id = of_get_property(np, "reg", NULL); + const __be32 *link; + int size; + int phy_mode; + + if (!id || (be32_to_cpu(*id) != 0)) { + pr_err("%s: invalid port id\n", np->name); + return; + } + + priv->phy->phy_fixed[0] = of_get_property(np, + "mediatek,fixed-link", &size); + if (priv->phy->phy_fixed[0] && + (size != (4 * sizeof(*priv->phy->phy_fixed[0])))) { + pr_err("%s: invalid fixed link property\n", np->name); + priv->phy->phy_fixed[0] = NULL; + return; + } + + phy_mode = of_get_phy_mode(np); + switch (phy_mode) { + case PHY_INTERFACE_MODE_RGMII: + break; + case PHY_INTERFACE_MODE_MII: + break; + case PHY_INTERFACE_MODE_RMII: + break; + default: + if (!priv->phy->phy_fixed[0]) + dev_err(priv->dev, "port %d - invalid phy mode\n", + priv->phy->speed[0]); + break; + } + + priv->phy->phy_node[0] = of_parse_phandle(np, "phy-handle", 0); + if (!priv->phy->phy_node[0] && !priv->phy->phy_fixed[0]) + return; + + if (priv->phy->phy_fixed[0]) { + link = priv->phy->phy_fixed[0]; + priv->phy->speed[0] = be32_to_cpup(link++); + priv->phy->duplex[0] = be32_to_cpup(link++); + priv->phy->tx_fc[0] = be32_to_cpup(link++); + priv->phy->rx_fc[0] = be32_to_cpup(link++); + + priv->link[0] = 1; + switch (priv->phy->speed[0]) { + case SPEED_10: + break; + case SPEED_100: + break; + case SPEED_1000: + break; + default: + dev_err(priv->dev, "invalid link speed: %d\n", + priv->phy->speed[0]); + priv->phy->phy_fixed[0] = 0; + return; + } + dev_info(priv->dev, "using fixed link parameters\n"); + rt2880_mdio_link_adjust(priv, 0); + return; + } + + if (priv->phy->phy_node[0] && mdiobus_get_phy(priv->mii_bus, 0)) + fe_connect_phy_node(priv, priv->phy->phy_node[0]); +} diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mdio_rt2880.h b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mdio_rt2880.h new file mode 100644 index 000000000..70e344283 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mdio_rt2880.h @@ -0,0 +1,23 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#ifndef _RALINK_MDIO_RT2880_H__ +#define _RALINK_MDIO_RT2880_H__ + +void rt2880_mdio_link_adjust(struct fe_priv *priv, int port); +int rt2880_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg); +int rt2880_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val); +void rt2880_port_init(struct fe_priv *priv, struct device_node *np); + +#endif diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mt7530.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mt7530.c new file mode 100644 index 000000000..5216cb5c6 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mt7530.c @@ -0,0 +1,979 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2013 John Crispin + * Copyright (C) 2016 Vitaly Chekryzhev <13hakta@gmail.com> + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mt7530.h" + +#define MT7530_CPU_PORT 6 +#define MT7530_NUM_PORTS 8 +#ifdef CONFIG_SOC_MT7621 +#define MT7530_NUM_VLANS 4095 +#else +#define MT7530_NUM_VLANS 16 +#endif +#define MT7530_MAX_VID 4095 +#define MT7530_MIN_VID 0 + +#define MT7530_PORT_MIB_TXB_ID 2 /* TxGOC */ +#define MT7530_PORT_MIB_RXB_ID 6 /* RxGOC */ + +#define MT7621_PORT_MIB_TXB_ID 18 /* TxByte */ +#define MT7621_PORT_MIB_RXB_ID 37 /* RxByte */ + +/* registers */ +#define REG_ESW_VLAN_VTCR 0x90 +#define REG_ESW_VLAN_VAWD1 0x94 +#define REG_ESW_VLAN_VAWD2 0x98 +#define REG_ESW_VLAN_VTIM(x) (0x100 + 4 * ((x) / 2)) + +#define REG_ESW_VLAN_VAWD1_IVL_MAC BIT(30) +#define REG_ESW_VLAN_VAWD1_VTAG_EN BIT(28) +#define REG_ESW_VLAN_VAWD1_VALID BIT(0) + +/* vlan egress mode */ +enum { + ETAG_CTRL_UNTAG = 0, + ETAG_CTRL_TAG = 2, + ETAG_CTRL_SWAP = 1, + ETAG_CTRL_STACK = 3, +}; + +#define REG_ESW_PORT_PCR(x) (0x2004 | ((x) << 8)) +#define REG_ESW_PORT_PVC(x) (0x2010 | ((x) << 8)) +#define REG_ESW_PORT_PPBV1(x) (0x2014 | ((x) << 8)) + +#define REG_HWTRAP 0x7804 + +#define MIB_DESC(_s , _o, _n) \ + { \ + .size = (_s), \ + .offset = (_o), \ + .name = (_n), \ + } + +struct mt7xxx_mib_desc { + unsigned int size; + unsigned int offset; + const char *name; +}; + +static const struct mt7xxx_mib_desc mt7620_mibs[] = { + MIB_DESC(1, MT7620_MIB_STATS_PPE_AC_BCNT0, "PPE_AC_BCNT0"), + MIB_DESC(1, MT7620_MIB_STATS_PPE_AC_PCNT0, "PPE_AC_PCNT0"), + MIB_DESC(1, MT7620_MIB_STATS_PPE_AC_BCNT63, "PPE_AC_BCNT63"), + MIB_DESC(1, MT7620_MIB_STATS_PPE_AC_PCNT63, "PPE_AC_PCNT63"), + MIB_DESC(1, MT7620_MIB_STATS_PPE_MTR_CNT0, "PPE_MTR_CNT0"), + MIB_DESC(1, MT7620_MIB_STATS_PPE_MTR_CNT63, "PPE_MTR_CNT63"), + MIB_DESC(1, MT7620_MIB_STATS_GDM1_TX_GBCNT, "GDM1_TX_GBCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM1_TX_GPCNT, "GDM1_TX_GPCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM1_TX_SKIPCNT, "GDM1_TX_SKIPCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM1_TX_COLCNT, "GDM1_TX_COLCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_GBCNT1, "GDM1_RX_GBCNT1"), + MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_GPCNT1, "GDM1_RX_GPCNT1"), + MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_OERCNT, "GDM1_RX_OERCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_FERCNT, "GDM1_RX_FERCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_SERCNT, "GDM1_RX_SERCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_LERCNT, "GDM1_RX_LERCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_CERCNT, "GDM1_RX_CERCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_FCCNT, "GDM1_RX_FCCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM2_TX_GBCNT, "GDM2_TX_GBCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM2_TX_GPCNT, "GDM2_TX_GPCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM2_TX_SKIPCNT, "GDM2_TX_SKIPCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM2_TX_COLCNT, "GDM2_TX_COLCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_GBCNT, "GDM2_RX_GBCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_GPCNT, "GDM2_RX_GPCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_OERCNT, "GDM2_RX_OERCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_FERCNT, "GDM2_RX_FERCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_SERCNT, "GDM2_RX_SERCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_LERCNT, "GDM2_RX_LERCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_CERCNT, "GDM2_RX_CERCNT"), + MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_FCCNT, "GDM2_RX_FCCNT") +}; + +static const struct mt7xxx_mib_desc mt7620_port_mibs[] = { + MIB_DESC(1, MT7620_MIB_STATS_PORT_TGPCN, "TxGPC"), + MIB_DESC(1, MT7620_MIB_STATS_PORT_TBOCN, "TxBOC"), + MIB_DESC(1, MT7620_MIB_STATS_PORT_TGOCN, "TxGOC"), + MIB_DESC(1, MT7620_MIB_STATS_PORT_TEPCN, "TxEPC"), + MIB_DESC(1, MT7620_MIB_STATS_PORT_RGPCN, "RxGPC"), + MIB_DESC(1, MT7620_MIB_STATS_PORT_RBOCN, "RxBOC"), + MIB_DESC(1, MT7620_MIB_STATS_PORT_RGOCN, "RxGOC"), + MIB_DESC(1, MT7620_MIB_STATS_PORT_REPC1N, "RxEPC1"), + MIB_DESC(1, MT7620_MIB_STATS_PORT_REPC2N, "RxEPC2") +}; + +static const struct mt7xxx_mib_desc mt7621_mibs[] = { + MIB_DESC(1, MT7621_STATS_TDPC, "TxDrop"), + MIB_DESC(1, MT7621_STATS_TCRC, "TxCRC"), + MIB_DESC(1, MT7621_STATS_TUPC, "TxUni"), + MIB_DESC(1, MT7621_STATS_TMPC, "TxMulti"), + MIB_DESC(1, MT7621_STATS_TBPC, "TxBroad"), + MIB_DESC(1, MT7621_STATS_TCEC, "TxCollision"), + MIB_DESC(1, MT7621_STATS_TSCEC, "TxSingleCol"), + MIB_DESC(1, MT7621_STATS_TMCEC, "TxMultiCol"), + MIB_DESC(1, MT7621_STATS_TDEC, "TxDefer"), + MIB_DESC(1, MT7621_STATS_TLCEC, "TxLateCol"), + MIB_DESC(1, MT7621_STATS_TXCEC, "TxExcCol"), + MIB_DESC(1, MT7621_STATS_TPPC, "TxPause"), + MIB_DESC(1, MT7621_STATS_TL64PC, "Tx64Byte"), + MIB_DESC(1, MT7621_STATS_TL65PC, "Tx65Byte"), + MIB_DESC(1, MT7621_STATS_TL128PC, "Tx128Byte"), + MIB_DESC(1, MT7621_STATS_TL256PC, "Tx256Byte"), + MIB_DESC(1, MT7621_STATS_TL512PC, "Tx512Byte"), + MIB_DESC(1, MT7621_STATS_TL1024PC, "Tx1024Byte"), + MIB_DESC(2, MT7621_STATS_TOC, "TxByte"), + MIB_DESC(1, MT7621_STATS_RDPC, "RxDrop"), + MIB_DESC(1, MT7621_STATS_RFPC, "RxFiltered"), + MIB_DESC(1, MT7621_STATS_RUPC, "RxUni"), + MIB_DESC(1, MT7621_STATS_RMPC, "RxMulti"), + MIB_DESC(1, MT7621_STATS_RBPC, "RxBroad"), + MIB_DESC(1, MT7621_STATS_RAEPC, "RxAlignErr"), + MIB_DESC(1, MT7621_STATS_RCEPC, "RxCRC"), + MIB_DESC(1, MT7621_STATS_RUSPC, "RxUnderSize"), + MIB_DESC(1, MT7621_STATS_RFEPC, "RxFragment"), + MIB_DESC(1, MT7621_STATS_ROSPC, "RxOverSize"), + MIB_DESC(1, MT7621_STATS_RJEPC, "RxJabber"), + MIB_DESC(1, MT7621_STATS_RPPC, "RxPause"), + MIB_DESC(1, MT7621_STATS_RL64PC, "Rx64Byte"), + MIB_DESC(1, MT7621_STATS_RL65PC, "Rx65Byte"), + MIB_DESC(1, MT7621_STATS_RL128PC, "Rx128Byte"), + MIB_DESC(1, MT7621_STATS_RL256PC, "Rx256Byte"), + MIB_DESC(1, MT7621_STATS_RL512PC, "Rx512Byte"), + MIB_DESC(1, MT7621_STATS_RL1024PC, "Rx1024Byte"), + MIB_DESC(2, MT7621_STATS_ROC, "RxByte"), + MIB_DESC(1, MT7621_STATS_RDPC_CTRL, "RxCtrlDrop"), + MIB_DESC(1, MT7621_STATS_RDPC_ING, "RxIngDrop"), + MIB_DESC(1, MT7621_STATS_RDPC_ARL, "RxARLDrop") +}; + +enum { + /* Global attributes. */ + MT7530_ATTR_ENABLE_VLAN, +}; + +struct mt7530_port_entry { + u16 pvid; +}; + +struct mt7530_vlan_entry { + u16 vid; + u8 member; + u8 etags; +}; + +struct mt7530_priv { + void __iomem *base; + struct mii_bus *bus; + struct switch_dev swdev; + + bool global_vlan_enable; + struct mt7530_vlan_entry vlan_entries[MT7530_NUM_VLANS]; + struct mt7530_port_entry port_entries[MT7530_NUM_PORTS]; +}; + +struct mt7530_mapping { + char *name; + u16 pvids[MT7530_NUM_PORTS]; + u8 members[MT7530_NUM_VLANS]; + u8 etags[MT7530_NUM_VLANS]; + u16 vids[MT7530_NUM_VLANS]; +} mt7530_defaults[] = { + { + .name = "llllw", + .pvids = { 1, 1, 1, 1, 2, 1, 1 }, + .members = { 0, 0x6f, 0x50 }, + .etags = { 0, 0x40, 0x40 }, + .vids = { 0, 1, 2 }, + }, { + .name = "wllll", + .pvids = { 2, 1, 1, 1, 1, 1, 1 }, + .members = { 0, 0x7e, 0x41 }, + .etags = { 0, 0x40, 0x40 }, + .vids = { 0, 1, 2 }, + }, { + .name = "lwlll", + .pvids = { 1, 2, 1, 1, 1, 1, 1 }, + .members = { 0, 0x7d, 0x42 }, + .etags = { 0, 0x40, 0x40 }, + .vids = { 0, 1, 2 }, + }, +}; + +struct mt7530_mapping* +mt7530_find_mapping(struct device_node *np) +{ + const char *map; + int i; + + if (of_property_read_string(np, "mediatek,portmap", &map)) + return NULL; + + for (i = 0; i < ARRAY_SIZE(mt7530_defaults); i++) + if (!strcmp(map, mt7530_defaults[i].name)) + return &mt7530_defaults[i]; + + return NULL; +} + +static void +mt7530_apply_mapping(struct mt7530_priv *mt7530, struct mt7530_mapping *map) +{ + int i = 0; + + for (i = 0; i < MT7530_NUM_PORTS; i++) + mt7530->port_entries[i].pvid = map->pvids[i]; + + for (i = 0; i < MT7530_NUM_VLANS; i++) { + mt7530->vlan_entries[i].member = map->members[i]; + mt7530->vlan_entries[i].etags = map->etags[i]; + mt7530->vlan_entries[i].vid = map->vids[i]; + } +} + +static int +mt7530_reset_switch(struct switch_dev *dev) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + int i; + + memset(priv->port_entries, 0, sizeof(priv->port_entries)); + memset(priv->vlan_entries, 0, sizeof(priv->vlan_entries)); + + /* set default vid of each vlan to the same number of vlan, so the vid + * won't need be set explicitly. + */ + for (i = 0; i < MT7530_NUM_VLANS; i++) { + priv->vlan_entries[i].vid = i; + } + + return 0; +} + +static int +mt7530_get_vlan_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + + val->value.i = priv->global_vlan_enable; + + return 0; +} + +static int +mt7530_set_vlan_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + + priv->global_vlan_enable = val->value.i != 0; + + return 0; +} + +static u32 +mt7530_r32(struct mt7530_priv *priv, u32 reg) +{ + u32 val; + if (priv->bus) { + u16 high, low; + + mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff); + low = mdiobus_read(priv->bus, 0x1f, (reg >> 2) & 0xf); + high = mdiobus_read(priv->bus, 0x1f, 0x10); + + return (high << 16) | (low & 0xffff); + } + + val = ioread32(priv->base + reg); + pr_debug("MT7530 MDIO Read [%04x]=%08x\n", reg, val); + + return val; +} + +static void +mt7530_w32(struct mt7530_priv *priv, u32 reg, u32 val) +{ + if (priv->bus) { + mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff); + mdiobus_write(priv->bus, 0x1f, (reg >> 2) & 0xf, val & 0xffff); + mdiobus_write(priv->bus, 0x1f, 0x10, val >> 16); + return; + } + + pr_debug("MT7530 MDIO Write[%04x]=%08x\n", reg, val); + iowrite32(val, priv->base + reg); +} + +static void +mt7530_vtcr(struct mt7530_priv *priv, u32 cmd, u32 val) +{ + int i; + + mt7530_w32(priv, REG_ESW_VLAN_VTCR, BIT(31) | (cmd << 12) | val); + + for (i = 0; i < 20; i++) { + u32 val = mt7530_r32(priv, REG_ESW_VLAN_VTCR); + + if ((val & BIT(31)) == 0) + break; + + udelay(1000); + } + if (i == 20) + printk("mt7530: vtcr timeout\n"); +} + +static int +mt7530_get_port_pvid(struct switch_dev *dev, int port, int *val) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + + if (port >= MT7530_NUM_PORTS) + return -EINVAL; + + *val = mt7530_r32(priv, REG_ESW_PORT_PPBV1(port)); + *val &= 0xfff; + + return 0; +} + +static int +mt7530_set_port_pvid(struct switch_dev *dev, int port, int pvid) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + + if (port >= MT7530_NUM_PORTS) + return -EINVAL; + + if (pvid < MT7530_MIN_VID || pvid > MT7530_MAX_VID) + return -EINVAL; + + priv->port_entries[port].pvid = pvid; + + return 0; +} + +static int +mt7530_get_vlan_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + u32 member; + u32 etags; + int i; + + val->len = 0; + + if (val->port_vlan < 0 || val->port_vlan >= MT7530_NUM_VLANS) + return -EINVAL; + + mt7530_vtcr(priv, 0, val->port_vlan); + + member = mt7530_r32(priv, REG_ESW_VLAN_VAWD1); + member >>= 16; + member &= 0xff; + + etags = mt7530_r32(priv, REG_ESW_VLAN_VAWD2); + + for (i = 0; i < MT7530_NUM_PORTS; i++) { + struct switch_port *p; + int etag; + + if (!(member & BIT(i))) + continue; + + p = &val->value.ports[val->len++]; + p->id = i; + + etag = (etags >> (i * 2)) & 0x3; + + if (etag == ETAG_CTRL_TAG) + p->flags |= BIT(SWITCH_PORT_FLAG_TAGGED); + else if (etag != ETAG_CTRL_UNTAG) + printk("vlan egress tag control neither untag nor tag.\n"); + } + + return 0; +} + +static int +mt7530_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + u8 member = 0; + u8 etags = 0; + int i; + + if (val->port_vlan < 0 || val->port_vlan >= MT7530_NUM_VLANS || + val->len > MT7530_NUM_PORTS) + return -EINVAL; + + for (i = 0; i < val->len; i++) { + struct switch_port *p = &val->value.ports[i]; + + if (p->id >= MT7530_NUM_PORTS) + return -EINVAL; + + member |= BIT(p->id); + + if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED)) + etags |= BIT(p->id); + } + priv->vlan_entries[val->port_vlan].member = member; + priv->vlan_entries[val->port_vlan].etags = etags; + + return 0; +} + +static int +mt7530_set_vid(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + int vlan; + u16 vid; + + vlan = val->port_vlan; + vid = (u16)val->value.i; + + if (vlan < 0 || vlan >= MT7530_NUM_VLANS) + return -EINVAL; + + if (vid < MT7530_MIN_VID || vid > MT7530_MAX_VID) + return -EINVAL; + + priv->vlan_entries[vlan].vid = vid; + return 0; +} + +static int +mt7621_get_vid(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) +{ + val->value.i = val->port_vlan; + return 0; +} + +static int +mt7530_get_vid(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + u32 vid; + int vlan; + + vlan = val->port_vlan; + + vid = mt7530_r32(priv, REG_ESW_VLAN_VTIM(vlan)); + if (vlan & 1) + vid = vid >> 12; + vid &= 0xfff; + + val->value.i = vid; + return 0; +} + +static void +mt7530_write_vlan_entry(struct mt7530_priv *priv, int vlan, u16 vid, + u8 ports, u8 etags) +{ + int port; + u32 val; + +#ifndef CONFIG_SOC_MT7621 + /* vid of vlan */ + val = mt7530_r32(priv, REG_ESW_VLAN_VTIM(vlan)); + if (vlan % 2 == 0) { + val &= 0xfff000; + val |= vid; + } else { + val &= 0xfff; + val |= (vid << 12); + } + mt7530_w32(priv, REG_ESW_VLAN_VTIM(vlan), val); +#endif + + /* vlan port membership */ + if (ports) + mt7530_w32(priv, REG_ESW_VLAN_VAWD1, REG_ESW_VLAN_VAWD1_IVL_MAC | + REG_ESW_VLAN_VAWD1_VTAG_EN | (ports << 16) | + REG_ESW_VLAN_VAWD1_VALID); + else + mt7530_w32(priv, REG_ESW_VLAN_VAWD1, 0); + + /* egress mode */ + val = 0; + for (port = 0; port < MT7530_NUM_PORTS; port++) { + if (etags & BIT(port)) + val |= ETAG_CTRL_TAG << (port * 2); + else + val |= ETAG_CTRL_UNTAG << (port * 2); + } + mt7530_w32(priv, REG_ESW_VLAN_VAWD2, val); + + /* write to vlan table */ +#ifdef CONFIG_SOC_MT7621 + mt7530_vtcr(priv, 1, vid); +#else + mt7530_vtcr(priv, 1, vlan); +#endif +} + +static int +mt7530_apply_config(struct switch_dev *dev) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + int i, j; + u8 tag_ports; + u8 untag_ports; + + if (!priv->global_vlan_enable) { + for (i = 0; i < MT7530_NUM_PORTS; i++) + mt7530_w32(priv, REG_ESW_PORT_PCR(i), 0x00400000); + + mt7530_w32(priv, REG_ESW_PORT_PCR(MT7530_CPU_PORT), 0x00ff0000); + + for (i = 0; i < MT7530_NUM_PORTS; i++) + mt7530_w32(priv, REG_ESW_PORT_PVC(i), 0x810000c0); + + return 0; + } + + /* set all ports as security mode */ + for (i = 0; i < MT7530_NUM_PORTS; i++) + mt7530_w32(priv, REG_ESW_PORT_PCR(i), 0x00ff0003); + + /* check if a port is used in tag/untag vlan egress mode */ + tag_ports = 0; + untag_ports = 0; + + for (i = 0; i < MT7530_NUM_VLANS; i++) { + u8 member = priv->vlan_entries[i].member; + u8 etags = priv->vlan_entries[i].etags; + + if (!member) + continue; + + for (j = 0; j < MT7530_NUM_PORTS; j++) { + if (!(member & BIT(j))) + continue; + + if (etags & BIT(j)) + tag_ports |= 1u << j; + else + untag_ports |= 1u << j; + } + } + + /* set all untag-only ports as transparent and the rest as user port */ + for (i = 0; i < MT7530_NUM_PORTS; i++) { + u32 pvc_mode = 0x81000000; + + if (untag_ports & BIT(i) && !(tag_ports & BIT(i))) + pvc_mode = 0x810000c0; + + mt7530_w32(priv, REG_ESW_PORT_PVC(i), pvc_mode); + } + + /* first clear the swtich vlan table */ + for (i = 0; i < MT7530_NUM_VLANS; i++) + mt7530_write_vlan_entry(priv, i, i, 0, 0); + + /* now program only vlans with members to avoid + clobbering remapped entries in later iterations */ + for (i = 0; i < MT7530_NUM_VLANS; i++) { + u16 vid = priv->vlan_entries[i].vid; + u8 member = priv->vlan_entries[i].member; + u8 etags = priv->vlan_entries[i].etags; + + if (member) + mt7530_write_vlan_entry(priv, i, vid, member, etags); + } + + /* Port Default PVID */ + for (i = 0; i < MT7530_NUM_PORTS; i++) { + int vlan = priv->port_entries[i].pvid; + u16 pvid = 0; + u32 val; + + if (vlan < MT7530_NUM_VLANS && priv->vlan_entries[vlan].member) + pvid = priv->vlan_entries[vlan].vid; + + val = mt7530_r32(priv, REG_ESW_PORT_PPBV1(i)); + val &= ~0xfff; + val |= pvid; + mt7530_w32(priv, REG_ESW_PORT_PPBV1(i), val); + } + + return 0; +} + +static int +mt7530_get_port_link(struct switch_dev *dev, int port, + struct switch_port_link *link) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + u32 speed, pmsr; + + if (port < 0 || port >= MT7530_NUM_PORTS) + return -EINVAL; + + pmsr = mt7530_r32(priv, 0x3008 + (0x100 * port)); + + link->link = pmsr & 1; + link->duplex = (pmsr >> 1) & 1; + speed = (pmsr >> 2) & 3; + + switch (speed) { + case 0: + link->speed = SWITCH_PORT_SPEED_10; + break; + case 1: + link->speed = SWITCH_PORT_SPEED_100; + break; + case 2: + case 3: /* forced gige speed can be 2 or 3 */ + link->speed = SWITCH_PORT_SPEED_1000; + break; + default: + link->speed = SWITCH_PORT_SPEED_UNKNOWN; + break; + } + + return 0; +} + +static u64 get_mib_counter(struct mt7530_priv *priv, int i, int port) +{ + unsigned int port_base; + u64 lo; + + port_base = MT7621_MIB_COUNTER_BASE + + MT7621_MIB_COUNTER_PORT_OFFSET * port; + + lo = mt7530_r32(priv, port_base + mt7621_mibs[i].offset); + if (mt7621_mibs[i].size == 2) { + u64 hi; + + hi = mt7530_r32(priv, port_base + mt7621_mibs[i].offset + 4); + lo |= hi << 32; + } + + return lo; +} + +static int mt7621_sw_get_port_mib(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + static char buf[4096]; + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + int i, len = 0; + + if (val->port_vlan >= MT7530_NUM_PORTS) + return -EINVAL; + + len += snprintf(buf + len, sizeof(buf) - len, + "Port %d MIB counters\n", val->port_vlan); + + for (i = 0; i < ARRAY_SIZE(mt7621_mibs); ++i) { + u64 counter; + len += snprintf(buf + len, sizeof(buf) - len, + "%-11s: ", mt7621_mibs[i].name); + counter = get_mib_counter(priv, i, val->port_vlan); + len += snprintf(buf + len, sizeof(buf) - len, "%llu\n", + counter); + } + + val->value.s = buf; + val->len = len; + return 0; +} + +static u64 get_mib_counter_7620(struct mt7530_priv *priv, int i) +{ + return mt7530_r32(priv, MT7620_MIB_COUNTER_BASE + mt7620_mibs[i].offset); +} + +static u64 get_mib_counter_port_7620(struct mt7530_priv *priv, int i, int port) +{ + return mt7530_r32(priv, + MT7620_MIB_COUNTER_BASE_PORT + + (MT7620_MIB_COUNTER_PORT_OFFSET * port) + + mt7620_port_mibs[i].offset); +} + +static int mt7530_sw_get_mib(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + static char buf[4096]; + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + int i, len = 0; + + len += snprintf(buf + len, sizeof(buf) - len, "Switch MIB counters\n"); + + for (i = 0; i < ARRAY_SIZE(mt7620_mibs); ++i) { + u64 counter; + len += snprintf(buf + len, sizeof(buf) - len, + "%-11s: ", mt7620_mibs[i].name); + counter = get_mib_counter_7620(priv, i); + len += snprintf(buf + len, sizeof(buf) - len, "%llu\n", + counter); + } + + val->value.s = buf; + val->len = len; + return 0; +} + +static int mt7530_sw_get_port_mib(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + static char buf[4096]; + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + int i, len = 0; + + if (val->port_vlan >= MT7530_NUM_PORTS) + return -EINVAL; + + len += snprintf(buf + len, sizeof(buf) - len, + "Port %d MIB counters\n", val->port_vlan); + + for (i = 0; i < ARRAY_SIZE(mt7620_port_mibs); ++i) { + u64 counter; + len += snprintf(buf + len, sizeof(buf) - len, + "%-11s: ", mt7620_port_mibs[i].name); + counter = get_mib_counter_port_7620(priv, i, val->port_vlan); + len += snprintf(buf + len, sizeof(buf) - len, "%llu\n", + counter); + } + + val->value.s = buf; + val->len = len; + return 0; +} + +static int mt7530_get_port_stats(struct switch_dev *dev, int port, + struct switch_port_stats *stats) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + + if (port < 0 || port >= MT7530_NUM_PORTS) + return -EINVAL; + + stats->tx_bytes = get_mib_counter_port_7620(priv, MT7530_PORT_MIB_TXB_ID, port); + stats->rx_bytes = get_mib_counter_port_7620(priv, MT7530_PORT_MIB_RXB_ID, port); + + return 0; +} + +static int mt7621_get_port_stats(struct switch_dev *dev, int port, + struct switch_port_stats *stats) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + + if (port < 0 || port >= MT7530_NUM_PORTS) + return -EINVAL; + + stats->tx_bytes = get_mib_counter(priv, MT7621_PORT_MIB_TXB_ID, port); + stats->rx_bytes = get_mib_counter(priv, MT7621_PORT_MIB_RXB_ID, port); + + return 0; +} + +static const struct switch_attr mt7530_global[] = { + { + .type = SWITCH_TYPE_INT, + .name = "enable_vlan", + .description = "VLAN mode (1:enabled)", + .max = 1, + .id = MT7530_ATTR_ENABLE_VLAN, + .get = mt7530_get_vlan_enable, + .set = mt7530_set_vlan_enable, + }, { + .type = SWITCH_TYPE_STRING, + .name = "mib", + .description = "Get MIB counters for switch", + .get = mt7530_sw_get_mib, + .set = NULL, + }, +}; + +static const struct switch_attr mt7621_port[] = { + { + .type = SWITCH_TYPE_STRING, + .name = "mib", + .description = "Get MIB counters for port", + .get = mt7621_sw_get_port_mib, + .set = NULL, + }, +}; + +static const struct switch_attr mt7621_vlan[] = { + { + .type = SWITCH_TYPE_INT, + .name = "vid", + .description = "VLAN ID (0-4094)", + .set = mt7530_set_vid, + .get = mt7621_get_vid, + .max = 4094, + }, +}; + +static const struct switch_attr mt7530_port[] = { + { + .type = SWITCH_TYPE_STRING, + .name = "mib", + .description = "Get MIB counters for port", + .get = mt7530_sw_get_port_mib, + .set = NULL, + }, +}; + +static const struct switch_attr mt7530_vlan[] = { + { + .type = SWITCH_TYPE_INT, + .name = "vid", + .description = "VLAN ID (0-4094)", + .set = mt7530_set_vid, + .get = mt7530_get_vid, + .max = 4094, + }, +}; + +static const struct switch_dev_ops mt7621_ops = { + .attr_global = { + .attr = mt7530_global, + .n_attr = ARRAY_SIZE(mt7530_global), + }, + .attr_port = { + .attr = mt7621_port, + .n_attr = ARRAY_SIZE(mt7621_port), + }, + .attr_vlan = { + .attr = mt7621_vlan, + .n_attr = ARRAY_SIZE(mt7621_vlan), + }, + .get_vlan_ports = mt7530_get_vlan_ports, + .set_vlan_ports = mt7530_set_vlan_ports, + .get_port_pvid = mt7530_get_port_pvid, + .set_port_pvid = mt7530_set_port_pvid, + .get_port_link = mt7530_get_port_link, + .get_port_stats = mt7621_get_port_stats, + .apply_config = mt7530_apply_config, + .reset_switch = mt7530_reset_switch, +}; + +static const struct switch_dev_ops mt7530_ops = { + .attr_global = { + .attr = mt7530_global, + .n_attr = ARRAY_SIZE(mt7530_global), + }, + .attr_port = { + .attr = mt7530_port, + .n_attr = ARRAY_SIZE(mt7530_port), + }, + .attr_vlan = { + .attr = mt7530_vlan, + .n_attr = ARRAY_SIZE(mt7530_vlan), + }, + .get_vlan_ports = mt7530_get_vlan_ports, + .set_vlan_ports = mt7530_set_vlan_ports, + .get_port_pvid = mt7530_get_port_pvid, + .set_port_pvid = mt7530_set_port_pvid, + .get_port_link = mt7530_get_port_link, + .get_port_stats = mt7530_get_port_stats, + .apply_config = mt7530_apply_config, + .reset_switch = mt7530_reset_switch, +}; + +int +mt7530_probe(struct device *dev, void __iomem *base, struct mii_bus *bus, int vlan) +{ + struct switch_dev *swdev; + struct mt7530_priv *mt7530; + struct mt7530_mapping *map; + int ret; + + mt7530 = devm_kzalloc(dev, sizeof(struct mt7530_priv), GFP_KERNEL); + if (!mt7530) + return -ENOMEM; + + mt7530->base = base; + mt7530->bus = bus; + mt7530->global_vlan_enable = vlan; + + swdev = &mt7530->swdev; + if (bus) { + swdev->alias = "mt7530"; + swdev->name = "mt7530"; + } else if (IS_ENABLED(CONFIG_SOC_MT7621)) { + swdev->alias = "mt7621"; + swdev->name = "mt7621"; + } else { + swdev->alias = "mt7620"; + swdev->name = "mt7620"; + } + swdev->cpu_port = MT7530_CPU_PORT; + swdev->ports = MT7530_NUM_PORTS; + swdev->vlans = MT7530_NUM_VLANS; + if (IS_ENABLED(CONFIG_SOC_MT7621)) + swdev->ops = &mt7621_ops; + else + swdev->ops = &mt7530_ops; + + ret = register_switch(swdev, NULL); + if (ret) { + dev_err(dev, "failed to register mt7530\n"); + return ret; + } + + + map = mt7530_find_mapping(dev->of_node); + if (map) + mt7530_apply_mapping(mt7530, map); + mt7530_apply_config(swdev); + + /* magic vodoo */ + if (!IS_ENABLED(CONFIG_SOC_MT7621) && bus && mt7530_r32(mt7530, REG_HWTRAP) != 0x1117edf) { + dev_info(dev, "fixing up MHWTRAP register - bootloader probably played with it\n"); + mt7530_w32(mt7530, REG_HWTRAP, 0x1117edf); + } + dev_info(dev, "loaded %s driver\n", swdev->name); + + return 0; +} diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mt7530.h b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mt7530.h new file mode 100644 index 000000000..cf725c2f2 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mt7530.h @@ -0,0 +1,186 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2013 John Crispin + * Copyright (C) 2016 Vitaly Chekryzhev <13hakta@gmail.com> + */ + +#ifndef _MT7530_H__ +#define _MT7530_H__ + +#define MT7620_MIB_COUNTER_BASE_PORT 0x4000 +#define MT7620_MIB_COUNTER_PORT_OFFSET 0x100 +#define MT7620_MIB_COUNTER_BASE 0x1010 + +/* PPE Accounting Group #0 Byte Counter */ +#define MT7620_MIB_STATS_PPE_AC_BCNT0 0x000 + +/* PPE Accounting Group #0 Packet Counter */ +#define MT7620_MIB_STATS_PPE_AC_PCNT0 0x004 + +/* PPE Accounting Group #63 Byte Counter */ +#define MT7620_MIB_STATS_PPE_AC_BCNT63 0x1F8 + +/* PPE Accounting Group #63 Packet Counter */ +#define MT7620_MIB_STATS_PPE_AC_PCNT63 0x1FC + +/* PPE Meter Group #0 */ +#define MT7620_MIB_STATS_PPE_MTR_CNT0 0x200 + +/* PPE Meter Group #63 */ +#define MT7620_MIB_STATS_PPE_MTR_CNT63 0x2FC + +/* Transmit good byte count for CPU GDM */ +#define MT7620_MIB_STATS_GDM1_TX_GBCNT 0x300 + +/* Transmit good packet count for CPU GDM (exclude flow control frames) */ +#define MT7620_MIB_STATS_GDM1_TX_GPCNT 0x304 + +/* Transmit abort count for CPU GDM */ +#define MT7620_MIB_STATS_GDM1_TX_SKIPCNT 0x308 + +/* Transmit collision count for CPU GDM */ +#define MT7620_MIB_STATS_GDM1_TX_COLCNT 0x30C + +/* Received good byte count for CPU GDM */ +#define MT7620_MIB_STATS_GDM1_RX_GBCNT1 0x320 + +/* Received good packet count for CPU GDM (exclude flow control frame) */ +#define MT7620_MIB_STATS_GDM1_RX_GPCNT1 0x324 + +/* Received overflow error packet count for CPU GDM */ +#define MT7620_MIB_STATS_GDM1_RX_OERCNT 0x328 + +/* Received FCS error packet count for CPU GDM */ +#define MT7620_MIB_STATS_GDM1_RX_FERCNT 0x32C + +/* Received too short error packet count for CPU GDM */ +#define MT7620_MIB_STATS_GDM1_RX_SERCNT 0x330 + +/* Received too long error packet count for CPU GDM */ +#define MT7620_MIB_STATS_GDM1_RX_LERCNT 0x334 + +/* Received IP/TCP/UDP checksum error packet count for CPU GDM */ +#define MT7620_MIB_STATS_GDM1_RX_CERCNT 0x338 + +/* Received flow control pkt count for CPU GDM */ +#define MT7620_MIB_STATS_GDM1_RX_FCCNT 0x33C + +/* Transmit good byte count for PPE GDM */ +#define MT7620_MIB_STATS_GDM2_TX_GBCNT 0x340 + +/* Transmit good packet count for PPE GDM (exclude flow control frames) */ +#define MT7620_MIB_STATS_GDM2_TX_GPCNT 0x344 + +/* Transmit abort count for PPE GDM */ +#define MT7620_MIB_STATS_GDM2_TX_SKIPCNT 0x348 + +/* Transmit collision count for PPE GDM */ +#define MT7620_MIB_STATS_GDM2_TX_COLCNT 0x34C + +/* Received good byte count for PPE GDM */ +#define MT7620_MIB_STATS_GDM2_RX_GBCNT 0x360 + +/* Received good packet count for PPE GDM (exclude flow control frame) */ +#define MT7620_MIB_STATS_GDM2_RX_GPCNT 0x364 + +/* Received overflow error packet count for PPE GDM */ +#define MT7620_MIB_STATS_GDM2_RX_OERCNT 0x368 + +/* Received FCS error packet count for PPE GDM */ +#define MT7620_MIB_STATS_GDM2_RX_FERCNT 0x36C + +/* Received too short error packet count for PPE GDM */ +#define MT7620_MIB_STATS_GDM2_RX_SERCNT 0x370 + +/* Received too long error packet count for PPE GDM */ +#define MT7620_MIB_STATS_GDM2_RX_LERCNT 0x374 + +/* Received IP/TCP/UDP checksum error packet count for PPE GDM */ +#define MT7620_MIB_STATS_GDM2_RX_CERCNT 0x378 + +/* Received flow control pkt count for PPE GDM */ +#define MT7620_MIB_STATS_GDM2_RX_FCCNT 0x37C + +/* Tx Packet Counter of Port n */ +#define MT7620_MIB_STATS_PORT_TGPCN 0x10 + +/* Tx Bad Octet Counter of Port n */ +#define MT7620_MIB_STATS_PORT_TBOCN 0x14 + +/* Tx Good Octet Counter of Port n */ +#define MT7620_MIB_STATS_PORT_TGOCN 0x18 + +/* Tx Event Packet Counter of Port n */ +#define MT7620_MIB_STATS_PORT_TEPCN 0x1C + +/* Rx Packet Counter of Port n */ +#define MT7620_MIB_STATS_PORT_RGPCN 0x20 + +/* Rx Bad Octet Counter of Port n */ +#define MT7620_MIB_STATS_PORT_RBOCN 0x24 + +/* Rx Good Octet Counter of Port n */ +#define MT7620_MIB_STATS_PORT_RGOCN 0x28 + +/* Rx Event Packet Counter of Port n */ +#define MT7620_MIB_STATS_PORT_REPC1N 0x2C + +/* Rx Event Packet Counter of Port n */ +#define MT7620_MIB_STATS_PORT_REPC2N 0x30 + +#define MT7621_MIB_COUNTER_BASE 0x4000 +#define MT7621_MIB_COUNTER_PORT_OFFSET 0x100 +#define MT7621_STATS_TDPC 0x00 +#define MT7621_STATS_TCRC 0x04 +#define MT7621_STATS_TUPC 0x08 +#define MT7621_STATS_TMPC 0x0C +#define MT7621_STATS_TBPC 0x10 +#define MT7621_STATS_TCEC 0x14 +#define MT7621_STATS_TSCEC 0x18 +#define MT7621_STATS_TMCEC 0x1C +#define MT7621_STATS_TDEC 0x20 +#define MT7621_STATS_TLCEC 0x24 +#define MT7621_STATS_TXCEC 0x28 +#define MT7621_STATS_TPPC 0x2C +#define MT7621_STATS_TL64PC 0x30 +#define MT7621_STATS_TL65PC 0x34 +#define MT7621_STATS_TL128PC 0x38 +#define MT7621_STATS_TL256PC 0x3C +#define MT7621_STATS_TL512PC 0x40 +#define MT7621_STATS_TL1024PC 0x44 +#define MT7621_STATS_TOC 0x48 +#define MT7621_STATS_RDPC 0x60 +#define MT7621_STATS_RFPC 0x64 +#define MT7621_STATS_RUPC 0x68 +#define MT7621_STATS_RMPC 0x6C +#define MT7621_STATS_RBPC 0x70 +#define MT7621_STATS_RAEPC 0x74 +#define MT7621_STATS_RCEPC 0x78 +#define MT7621_STATS_RUSPC 0x7C +#define MT7621_STATS_RFEPC 0x80 +#define MT7621_STATS_ROSPC 0x84 +#define MT7621_STATS_RJEPC 0x88 +#define MT7621_STATS_RPPC 0x8C +#define MT7621_STATS_RL64PC 0x90 +#define MT7621_STATS_RL65PC 0x94 +#define MT7621_STATS_RL128PC 0x98 +#define MT7621_STATS_RL256PC 0x9C +#define MT7621_STATS_RL512PC 0xA0 +#define MT7621_STATS_RL1024PC 0xA4 +#define MT7621_STATS_ROC 0xA8 +#define MT7621_STATS_RDPC_CTRL 0xB0 +#define MT7621_STATS_RDPC_ING 0xB4 +#define MT7621_STATS_RDPC_ARL 0xB8 + +int mt7530_probe(struct device *dev, void __iomem *base, struct mii_bus *bus, int vlan); + +#endif diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_debugfs.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_debugfs.c new file mode 100644 index 000000000..2938119e8 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_debugfs.c @@ -0,0 +1,115 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2014-2016 Sean Wang + * Copyright (C) 2016-2017 John Crispin + */ + +#include "mtk_offload.h" + +static const char *mtk_foe_entry_state_str[] = { + "INVALID", + "UNBIND", + "BIND", + "FIN" +}; + +static const char *mtk_foe_packet_type_str[] = { + "IPV4_HNAPT", + "IPV4_HNAT", + "IPV6_1T_ROUTE", + "IPV4_DSLITE", + "IPV6_3T_ROUTE", + "IPV6_5T_ROUTE", + "IPV6_6RD", +}; + +#define IPV4_HNAPT 0 +#define IPV4_HNAT 1 +#define IS_IPV4_HNAPT(x) (((x)->bfib1.pkt_type == IPV4_HNAPT) ? 1: 0) +struct mtk_eth *_eth; +#define es(entry) (mtk_foe_entry_state_str[entry->bfib1.state]) +//#define ei(entry, end) (MTK_PPE_TBL_SZ - (int)(end - entry)) +#define ei(entry, end) (MTK_PPE_ENTRY_CNT - (int)(end - entry)) +#define pt(entry) (mtk_foe_packet_type_str[entry->ipv4_hnapt.bfib1.pkt_type]) + +static int mtk_ppe_debugfs_foe_show(struct seq_file *m, void *private) +{ + struct mtk_eth *eth = _eth; + struct mtk_foe_entry *entry, *end; + int i = 0; + + entry = eth->foe_table; + end = eth->foe_table + MTK_PPE_ENTRY_CNT; + + while (entry < end) { + if (IS_IPV4_HNAPT(entry)) { + __be32 saddr = htonl(entry->ipv4_hnapt.sip); + __be32 daddr = htonl(entry->ipv4_hnapt.dip); + __be32 nsaddr = htonl(entry->ipv4_hnapt.new_sip); + __be32 ndaddr = htonl(entry->ipv4_hnapt.new_dip); + unsigned char h_dest[ETH_ALEN]; + unsigned char h_source[ETH_ALEN]; + + *((u32*) h_source) = swab32(entry->ipv4_hnapt.smac_hi); + *((u16*) &h_source[4]) = swab16(entry->ipv4_hnapt.smac_lo); + *((u32*) h_dest) = swab32(entry->ipv4_hnapt.dmac_hi); + *((u16*) &h_dest[4]) = swab16(entry->ipv4_hnapt.dmac_lo); + seq_printf(m, + "(%x)0x%05x|state=%s|type=%s|" + "%pI4:%d->%pI4:%d=>%pI4:%d->%pI4:%d|%pM=>%pM|" + "etype=0x%04x|info1=0x%x|info2=0x%x|" + "vlan1=%d|vlan2=%d\n", + i, + ei(entry, end), es(entry), pt(entry), + &saddr, entry->ipv4_hnapt.sport, + &daddr, entry->ipv4_hnapt.dport, + &nsaddr, entry->ipv4_hnapt.new_sport, + &ndaddr, entry->ipv4_hnapt.new_dport, h_source, + h_dest, ntohs(entry->ipv4_hnapt.etype), + entry->ipv4_hnapt.info_blk1, + entry->ipv4_hnapt.info_blk2, + entry->ipv4_hnapt.vlan1, + entry->ipv4_hnapt.vlan2); + } else + seq_printf(m, "0x%05x state=%s\n", + ei(entry, end), es(entry)); + entry++; + i++; + } + + return 0; +} + +static int mtk_ppe_debugfs_foe_open(struct inode *inode, struct file *file) +{ + return single_open(file, mtk_ppe_debugfs_foe_show, file->private_data); +} + +static const struct file_operations mtk_ppe_debugfs_foe_fops = { + .open = mtk_ppe_debugfs_foe_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +int mtk_ppe_debugfs_init(struct mtk_eth *eth) +{ + struct dentry *root; + + _eth = eth; + + root = debugfs_create_dir("mtk_ppe", NULL); + if (!root) + return -ENOMEM; + + debugfs_create_file("all_entry", S_IRUGO, root, eth, &mtk_ppe_debugfs_foe_fops); + + return 0; +} diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_eth_soc.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_eth_soc.c new file mode 100644 index 000000000..49505eab8 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_eth_soc.c @@ -0,0 +1,1647 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "mtk_eth_soc.h" +#include "mdio.h" +#include "ethtool.h" + +#define MAX_RX_LENGTH 1536 +#define FE_RX_ETH_HLEN (VLAN_ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN) +#define FE_RX_HLEN (NET_SKB_PAD + FE_RX_ETH_HLEN + NET_IP_ALIGN) +#define DMA_DUMMY_DESC 0xffffffff +#define FE_DEFAULT_MSG_ENABLE \ + (NETIF_MSG_DRV | \ + NETIF_MSG_PROBE | \ + NETIF_MSG_LINK | \ + NETIF_MSG_TIMER | \ + NETIF_MSG_IFDOWN | \ + NETIF_MSG_IFUP | \ + NETIF_MSG_RX_ERR | \ + NETIF_MSG_TX_ERR) + +#define TX_DMA_DESP2_DEF (TX_DMA_LS0 | TX_DMA_DONE) +#define TX_DMA_DESP4_DEF (TX_DMA_QN(3) | TX_DMA_PN(1)) +#define NEXT_TX_DESP_IDX(X) (((X) + 1) & (ring->tx_ring_size - 1)) +#define NEXT_RX_DESP_IDX(X) (((X) + 1) & (ring->rx_ring_size - 1)) + +#define SYSC_REG_RSTCTRL 0x34 + +static int fe_msg_level = -1; +module_param_named(msg_level, fe_msg_level, int, 0); +MODULE_PARM_DESC(msg_level, "Message level (-1=defaults,0=none,...,16=all)"); + +static const u16 fe_reg_table_default[FE_REG_COUNT] = { + [FE_REG_PDMA_GLO_CFG] = FE_PDMA_GLO_CFG, + [FE_REG_PDMA_RST_CFG] = FE_PDMA_RST_CFG, + [FE_REG_DLY_INT_CFG] = FE_DLY_INT_CFG, + [FE_REG_TX_BASE_PTR0] = FE_TX_BASE_PTR0, + [FE_REG_TX_MAX_CNT0] = FE_TX_MAX_CNT0, + [FE_REG_TX_CTX_IDX0] = FE_TX_CTX_IDX0, + [FE_REG_TX_DTX_IDX0] = FE_TX_DTX_IDX0, + [FE_REG_RX_BASE_PTR0] = FE_RX_BASE_PTR0, + [FE_REG_RX_MAX_CNT0] = FE_RX_MAX_CNT0, + [FE_REG_RX_CALC_IDX0] = FE_RX_CALC_IDX0, + [FE_REG_RX_DRX_IDX0] = FE_RX_DRX_IDX0, + [FE_REG_FE_INT_ENABLE] = FE_FE_INT_ENABLE, + [FE_REG_FE_INT_STATUS] = FE_FE_INT_STATUS, + [FE_REG_FE_DMA_VID_BASE] = FE_DMA_VID0, + [FE_REG_FE_COUNTER_BASE] = FE_GDMA1_TX_GBCNT, + [FE_REG_FE_RST_GL] = FE_FE_RST_GL, +}; + +static const u16 *fe_reg_table = fe_reg_table_default; + +struct fe_work_t { + int bitnr; + void (*action)(struct fe_priv *); +}; + +static void __iomem *fe_base; + +void fe_w32(u32 val, unsigned reg) +{ + __raw_writel(val, fe_base + reg); +} + +u32 fe_r32(unsigned reg) +{ + return __raw_readl(fe_base + reg); +} + +void fe_reg_w32(u32 val, enum fe_reg reg) +{ + fe_w32(val, fe_reg_table[reg]); +} + +u32 fe_reg_r32(enum fe_reg reg) +{ + return fe_r32(fe_reg_table[reg]); +} + +void fe_m32(struct fe_priv *eth, u32 clear, u32 set, unsigned reg) +{ + u32 val; + + spin_lock(ð->page_lock); + val = __raw_readl(fe_base + reg); + val &= ~clear; + val |= set; + __raw_writel(val, fe_base + reg); + spin_unlock(ð->page_lock); +} + +void fe_reset(u32 reset_bits) +{ + u32 t; + + t = rt_sysc_r32(SYSC_REG_RSTCTRL); + t |= reset_bits; + rt_sysc_w32(t, SYSC_REG_RSTCTRL); + usleep_range(10, 20); + + t &= ~reset_bits; + rt_sysc_w32(t, SYSC_REG_RSTCTRL); + usleep_range(10, 20); +} + +static inline void fe_int_disable(u32 mask) +{ + fe_reg_w32(fe_reg_r32(FE_REG_FE_INT_ENABLE) & ~mask, + FE_REG_FE_INT_ENABLE); + /* flush write */ + fe_reg_r32(FE_REG_FE_INT_ENABLE); +} + +static inline void fe_int_enable(u32 mask) +{ + fe_reg_w32(fe_reg_r32(FE_REG_FE_INT_ENABLE) | mask, + FE_REG_FE_INT_ENABLE); + /* flush write */ + fe_reg_r32(FE_REG_FE_INT_ENABLE); +} + +static inline void fe_hw_set_macaddr(struct fe_priv *priv, unsigned char *mac) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->page_lock, flags); + fe_w32((mac[0] << 8) | mac[1], FE_GDMA1_MAC_ADRH); + fe_w32((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], + FE_GDMA1_MAC_ADRL); + spin_unlock_irqrestore(&priv->page_lock, flags); +} + +static int fe_set_mac_address(struct net_device *dev, void *p) +{ + int ret = eth_mac_addr(dev, p); + + if (!ret) { + struct fe_priv *priv = netdev_priv(dev); + + if (priv->soc->set_mac) + priv->soc->set_mac(priv, dev->dev_addr); + else + fe_hw_set_macaddr(priv, p); + } + + return ret; +} + +static inline int fe_max_frag_size(int mtu) +{ + /* make sure buf_size will be at least MAX_RX_LENGTH */ + if (mtu + FE_RX_ETH_HLEN < MAX_RX_LENGTH) + mtu = MAX_RX_LENGTH - FE_RX_ETH_HLEN; + + return SKB_DATA_ALIGN(FE_RX_HLEN + mtu) + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); +} + +static inline int fe_max_buf_size(int frag_size) +{ + int buf_size = frag_size - NET_SKB_PAD - NET_IP_ALIGN - + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + + BUG_ON(buf_size < MAX_RX_LENGTH); + return buf_size; +} + +static inline void fe_get_rxd(struct fe_rx_dma *rxd, struct fe_rx_dma *dma_rxd) +{ + rxd->rxd1 = dma_rxd->rxd1; + rxd->rxd2 = dma_rxd->rxd2; + rxd->rxd3 = dma_rxd->rxd3; + rxd->rxd4 = dma_rxd->rxd4; +} + +static inline void fe_set_txd(struct fe_tx_dma *txd, struct fe_tx_dma *dma_txd) +{ + dma_txd->txd1 = txd->txd1; + dma_txd->txd3 = txd->txd3; + dma_txd->txd4 = txd->txd4; + /* clean dma done flag last */ + dma_txd->txd2 = txd->txd2; +} + +static void fe_clean_rx(struct fe_priv *priv) +{ + int i; + struct fe_rx_ring *ring = &priv->rx_ring; + + if (ring->rx_data) { + for (i = 0; i < ring->rx_ring_size; i++) + if (ring->rx_data[i]) { + if (ring->rx_dma && ring->rx_dma[i].rxd1) + dma_unmap_single(&priv->netdev->dev, + ring->rx_dma[i].rxd1, + ring->rx_buf_size, + DMA_FROM_DEVICE); + put_page(virt_to_head_page(ring->rx_data[i])); + } + + kfree(ring->rx_data); + ring->rx_data = NULL; + } + + if (ring->rx_dma) { + dma_free_coherent(&priv->netdev->dev, + ring->rx_ring_size * sizeof(*ring->rx_dma), + ring->rx_dma, + ring->rx_phys); + ring->rx_dma = NULL; + } +} + +static int fe_alloc_rx(struct fe_priv *priv) +{ + struct net_device *netdev = priv->netdev; + struct fe_rx_ring *ring = &priv->rx_ring; + int i, pad; + + ring->rx_data = kcalloc(ring->rx_ring_size, sizeof(*ring->rx_data), + GFP_KERNEL); + if (!ring->rx_data) + goto no_rx_mem; + + for (i = 0; i < ring->rx_ring_size; i++) { + ring->rx_data[i] = netdev_alloc_frag(ring->frag_size); + if (!ring->rx_data[i]) + goto no_rx_mem; + } + + ring->rx_dma = dma_alloc_coherent(&netdev->dev, + ring->rx_ring_size * sizeof(*ring->rx_dma), + &ring->rx_phys, + GFP_ATOMIC | __GFP_ZERO); + if (!ring->rx_dma) + goto no_rx_mem; + + if (priv->flags & FE_FLAG_RX_2B_OFFSET) + pad = 0; + else + pad = NET_IP_ALIGN; + for (i = 0; i < ring->rx_ring_size; i++) { + dma_addr_t dma_addr = dma_map_single(&netdev->dev, + ring->rx_data[i] + NET_SKB_PAD + pad, + ring->rx_buf_size, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(&netdev->dev, dma_addr))) + goto no_rx_mem; + ring->rx_dma[i].rxd1 = (unsigned int)dma_addr; + + if (priv->flags & FE_FLAG_RX_SG_DMA) + ring->rx_dma[i].rxd2 = RX_DMA_PLEN0(ring->rx_buf_size); + else + ring->rx_dma[i].rxd2 = RX_DMA_LSO; + } + ring->rx_calc_idx = ring->rx_ring_size - 1; + /* make sure that all changes to the dma ring are flushed before we + * continue + */ + wmb(); + + fe_reg_w32(ring->rx_phys, FE_REG_RX_BASE_PTR0); + fe_reg_w32(ring->rx_ring_size, FE_REG_RX_MAX_CNT0); + fe_reg_w32(ring->rx_calc_idx, FE_REG_RX_CALC_IDX0); + fe_reg_w32(FE_PST_DRX_IDX0, FE_REG_PDMA_RST_CFG); + + return 0; + +no_rx_mem: + return -ENOMEM; +} + +static void fe_txd_unmap(struct device *dev, struct fe_tx_buf *tx_buf) +{ + if (tx_buf->flags & FE_TX_FLAGS_SINGLE0) { + dma_unmap_single(dev, + dma_unmap_addr(tx_buf, dma_addr0), + dma_unmap_len(tx_buf, dma_len0), + DMA_TO_DEVICE); + } else if (tx_buf->flags & FE_TX_FLAGS_PAGE0) { + dma_unmap_page(dev, + dma_unmap_addr(tx_buf, dma_addr0), + dma_unmap_len(tx_buf, dma_len0), + DMA_TO_DEVICE); + } + if (tx_buf->flags & FE_TX_FLAGS_PAGE1) + dma_unmap_page(dev, + dma_unmap_addr(tx_buf, dma_addr1), + dma_unmap_len(tx_buf, dma_len1), + DMA_TO_DEVICE); + + tx_buf->flags = 0; + if (tx_buf->skb && (tx_buf->skb != (struct sk_buff *)DMA_DUMMY_DESC)) + dev_kfree_skb_any(tx_buf->skb); + tx_buf->skb = NULL; +} + +static void fe_clean_tx(struct fe_priv *priv) +{ + int i; + struct device *dev = &priv->netdev->dev; + struct fe_tx_ring *ring = &priv->tx_ring; + + if (ring->tx_buf) { + for (i = 0; i < ring->tx_ring_size; i++) + fe_txd_unmap(dev, &ring->tx_buf[i]); + kfree(ring->tx_buf); + ring->tx_buf = NULL; + } + + if (ring->tx_dma) { + dma_free_coherent(dev, + ring->tx_ring_size * sizeof(*ring->tx_dma), + ring->tx_dma, + ring->tx_phys); + ring->tx_dma = NULL; + } + + netdev_reset_queue(priv->netdev); +} + +static int fe_alloc_tx(struct fe_priv *priv) +{ + int i; + struct fe_tx_ring *ring = &priv->tx_ring; + + ring->tx_free_idx = 0; + ring->tx_next_idx = 0; + ring->tx_thresh = max((unsigned long)ring->tx_ring_size >> 2, + MAX_SKB_FRAGS); + + ring->tx_buf = kcalloc(ring->tx_ring_size, sizeof(*ring->tx_buf), + GFP_KERNEL); + if (!ring->tx_buf) + goto no_tx_mem; + + ring->tx_dma = dma_alloc_coherent(&priv->netdev->dev, + ring->tx_ring_size * sizeof(*ring->tx_dma), + &ring->tx_phys, + GFP_ATOMIC | __GFP_ZERO); + if (!ring->tx_dma) + goto no_tx_mem; + + for (i = 0; i < ring->tx_ring_size; i++) { + if (priv->soc->tx_dma) + priv->soc->tx_dma(&ring->tx_dma[i]); + ring->tx_dma[i].txd2 = TX_DMA_DESP2_DEF; + } + /* make sure that all changes to the dma ring are flushed before we + * continue + */ + wmb(); + + fe_reg_w32(ring->tx_phys, FE_REG_TX_BASE_PTR0); + fe_reg_w32(ring->tx_ring_size, FE_REG_TX_MAX_CNT0); + fe_reg_w32(0, FE_REG_TX_CTX_IDX0); + fe_reg_w32(FE_PST_DTX_IDX0, FE_REG_PDMA_RST_CFG); + + return 0; + +no_tx_mem: + return -ENOMEM; +} + +static int fe_init_dma(struct fe_priv *priv) +{ + int err; + + err = fe_alloc_tx(priv); + if (err) + return err; + + err = fe_alloc_rx(priv); + if (err) + return err; + + return 0; +} + +static void fe_free_dma(struct fe_priv *priv) +{ + fe_clean_tx(priv); + fe_clean_rx(priv); +} + +void fe_stats_update(struct fe_priv *priv) +{ + struct fe_hw_stats *hwstats = priv->hw_stats; + unsigned int base = fe_reg_table[FE_REG_FE_COUNTER_BASE]; + u64 stats; + + u64_stats_update_begin(&hwstats->syncp); + + if (IS_ENABLED(CONFIG_SOC_MT7621)) { + hwstats->rx_bytes += fe_r32(base); + stats = fe_r32(base + 0x04); + if (stats) + hwstats->rx_bytes += (stats << 32); + hwstats->rx_packets += fe_r32(base + 0x08); + hwstats->rx_overflow += fe_r32(base + 0x10); + hwstats->rx_fcs_errors += fe_r32(base + 0x14); + hwstats->rx_short_errors += fe_r32(base + 0x18); + hwstats->rx_long_errors += fe_r32(base + 0x1c); + hwstats->rx_checksum_errors += fe_r32(base + 0x20); + hwstats->rx_flow_control_packets += fe_r32(base + 0x24); + hwstats->tx_skip += fe_r32(base + 0x28); + hwstats->tx_collisions += fe_r32(base + 0x2c); + hwstats->tx_bytes += fe_r32(base + 0x30); + stats = fe_r32(base + 0x34); + if (stats) + hwstats->tx_bytes += (stats << 32); + hwstats->tx_packets += fe_r32(base + 0x38); + } else { + hwstats->tx_bytes += fe_r32(base); + hwstats->tx_packets += fe_r32(base + 0x04); + hwstats->tx_skip += fe_r32(base + 0x08); + hwstats->tx_collisions += fe_r32(base + 0x0c); + hwstats->rx_bytes += fe_r32(base + 0x20); + hwstats->rx_packets += fe_r32(base + 0x24); + hwstats->rx_overflow += fe_r32(base + 0x28); + hwstats->rx_fcs_errors += fe_r32(base + 0x2c); + hwstats->rx_short_errors += fe_r32(base + 0x30); + hwstats->rx_long_errors += fe_r32(base + 0x34); + hwstats->rx_checksum_errors += fe_r32(base + 0x38); + hwstats->rx_flow_control_packets += fe_r32(base + 0x3c); + } + + u64_stats_update_end(&hwstats->syncp); +} + +static void fe_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *storage) +{ + struct fe_priv *priv = netdev_priv(dev); + struct fe_hw_stats *hwstats = priv->hw_stats; + unsigned int base = fe_reg_table[FE_REG_FE_COUNTER_BASE]; + unsigned int start; + + if (!base) { + netdev_stats_to_stats64(storage, &dev->stats); + return; + } + + if (netif_running(dev) && netif_device_present(dev)) { + if (spin_trylock(&hwstats->stats_lock)) { + fe_stats_update(priv); + spin_unlock(&hwstats->stats_lock); + } + } + + do { + start = u64_stats_fetch_begin_irq(&hwstats->syncp); + storage->rx_packets = hwstats->rx_packets; + storage->tx_packets = hwstats->tx_packets; + storage->rx_bytes = hwstats->rx_bytes; + storage->tx_bytes = hwstats->tx_bytes; + storage->collisions = hwstats->tx_collisions; + storage->rx_length_errors = hwstats->rx_short_errors + + hwstats->rx_long_errors; + storage->rx_over_errors = hwstats->rx_overflow; + storage->rx_crc_errors = hwstats->rx_fcs_errors; + storage->rx_errors = hwstats->rx_checksum_errors; + storage->tx_aborted_errors = hwstats->tx_skip; + } while (u64_stats_fetch_retry_irq(&hwstats->syncp, start)); + + storage->tx_errors = priv->netdev->stats.tx_errors; + storage->rx_dropped = priv->netdev->stats.rx_dropped; + storage->tx_dropped = priv->netdev->stats.tx_dropped; +} + +static int fe_vlan_rx_add_vid(struct net_device *dev, + __be16 proto, u16 vid) +{ + struct fe_priv *priv = netdev_priv(dev); + u32 idx = (vid & 0xf); + u32 vlan_cfg; + + if (!((fe_reg_table[FE_REG_FE_DMA_VID_BASE]) && + (dev->features & NETIF_F_HW_VLAN_CTAG_TX))) + return 0; + + if (test_bit(idx, &priv->vlan_map)) { + netdev_warn(dev, "disable tx vlan offload\n"); + dev->wanted_features &= ~NETIF_F_HW_VLAN_CTAG_TX; + netdev_update_features(dev); + } else { + vlan_cfg = fe_r32(fe_reg_table[FE_REG_FE_DMA_VID_BASE] + + ((idx >> 1) << 2)); + if (idx & 0x1) { + vlan_cfg &= 0xffff; + vlan_cfg |= (vid << 16); + } else { + vlan_cfg &= 0xffff0000; + vlan_cfg |= vid; + } + fe_w32(vlan_cfg, fe_reg_table[FE_REG_FE_DMA_VID_BASE] + + ((idx >> 1) << 2)); + set_bit(idx, &priv->vlan_map); + } + + return 0; +} + +static int fe_vlan_rx_kill_vid(struct net_device *dev, + __be16 proto, u16 vid) +{ + struct fe_priv *priv = netdev_priv(dev); + u32 idx = (vid & 0xf); + + if (!((fe_reg_table[FE_REG_FE_DMA_VID_BASE]) && + (dev->features & NETIF_F_HW_VLAN_CTAG_TX))) + return 0; + + clear_bit(idx, &priv->vlan_map); + + return 0; +} + +static inline u32 fe_empty_txd(struct fe_tx_ring *ring) +{ + barrier(); + return (u32)(ring->tx_ring_size - + ((ring->tx_next_idx - ring->tx_free_idx) & + (ring->tx_ring_size - 1))); +} + +static int fe_tx_map_dma(struct sk_buff *skb, struct net_device *dev, + int tx_num, struct fe_tx_ring *ring) +{ + struct fe_priv *priv = netdev_priv(dev); + struct skb_frag_struct *frag; + struct fe_tx_dma txd, *ptxd; + struct fe_tx_buf *tx_buf; + dma_addr_t mapped_addr; + unsigned int nr_frags; + u32 def_txd4; + int i, j, k, frag_size, frag_map_size, offset; + + tx_buf = &ring->tx_buf[ring->tx_next_idx]; + memset(tx_buf, 0, sizeof(*tx_buf)); + memset(&txd, 0, sizeof(txd)); + nr_frags = skb_shinfo(skb)->nr_frags; + + /* init tx descriptor */ + if (priv->soc->tx_dma) + priv->soc->tx_dma(&txd); + else + txd.txd4 = TX_DMA_DESP4_DEF; + def_txd4 = txd.txd4; + + /* TX Checksum offload */ + if (skb->ip_summed == CHECKSUM_PARTIAL) + txd.txd4 |= TX_DMA_CHKSUM; + + /* VLAN header offload */ + if (skb_vlan_tag_present(skb)) { + u16 tag = skb_vlan_tag_get(skb); + + if (IS_ENABLED(CONFIG_SOC_MT7621)) + txd.txd4 |= TX_DMA_INS_VLAN_MT7621 | tag; + else + txd.txd4 |= TX_DMA_INS_VLAN | + ((tag >> VLAN_PRIO_SHIFT) << 4) | + (tag & 0xF); + } + + /* TSO: fill MSS info in tcp checksum field */ + if (skb_is_gso(skb)) { + if (skb_cow_head(skb, 0)) { + netif_warn(priv, tx_err, dev, + "GSO expand head fail.\n"); + goto err_out; + } + if (skb_shinfo(skb)->gso_type & + (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { + txd.txd4 |= TX_DMA_TSO; + tcp_hdr(skb)->check = htons(skb_shinfo(skb)->gso_size); + } + } + + mapped_addr = dma_map_single(&dev->dev, skb->data, + skb_headlen(skb), DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(&dev->dev, mapped_addr))) + goto err_out; + txd.txd1 = mapped_addr; + txd.txd2 = TX_DMA_PLEN0(skb_headlen(skb)); + + tx_buf->flags |= FE_TX_FLAGS_SINGLE0; + dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr); + dma_unmap_len_set(tx_buf, dma_len0, skb_headlen(skb)); + + /* TX SG offload */ + j = ring->tx_next_idx; + k = 0; + for (i = 0; i < nr_frags; i++) { + offset = 0; + frag = &skb_shinfo(skb)->frags[i]; + frag_size = skb_frag_size(frag); + + while (frag_size > 0) { + frag_map_size = min(frag_size, TX_DMA_BUF_LEN); + mapped_addr = skb_frag_dma_map(&dev->dev, frag, offset, + frag_map_size, + DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(&dev->dev, mapped_addr))) + goto err_dma; + + if (k & 0x1) { + j = NEXT_TX_DESP_IDX(j); + txd.txd1 = mapped_addr; + txd.txd2 = TX_DMA_PLEN0(frag_map_size); + txd.txd4 = def_txd4; + + tx_buf = &ring->tx_buf[j]; + memset(tx_buf, 0, sizeof(*tx_buf)); + + tx_buf->flags |= FE_TX_FLAGS_PAGE0; + dma_unmap_addr_set(tx_buf, dma_addr0, + mapped_addr); + dma_unmap_len_set(tx_buf, dma_len0, + frag_map_size); + } else { + txd.txd3 = mapped_addr; + txd.txd2 |= TX_DMA_PLEN1(frag_map_size); + + tx_buf->skb = (struct sk_buff *)DMA_DUMMY_DESC; + tx_buf->flags |= FE_TX_FLAGS_PAGE1; + dma_unmap_addr_set(tx_buf, dma_addr1, + mapped_addr); + dma_unmap_len_set(tx_buf, dma_len1, + frag_map_size); + + if (!((i == (nr_frags - 1)) && + (frag_map_size == frag_size))) { + fe_set_txd(&txd, &ring->tx_dma[j]); + memset(&txd, 0, sizeof(txd)); + } + } + frag_size -= frag_map_size; + offset += frag_map_size; + k++; + } + } + + /* set last segment */ + if (k & 0x1) + txd.txd2 |= TX_DMA_LS1; + else + txd.txd2 |= TX_DMA_LS0; + fe_set_txd(&txd, &ring->tx_dma[j]); + + /* store skb to cleanup */ + tx_buf->skb = skb; + + netdev_sent_queue(dev, skb->len); + skb_tx_timestamp(skb); + + ring->tx_next_idx = NEXT_TX_DESP_IDX(j); + /* make sure that all changes to the dma ring are flushed before we + * continue + */ + wmb(); + if (unlikely(fe_empty_txd(ring) <= ring->tx_thresh)) { + netif_stop_queue(dev); + smp_mb(); + if (unlikely(fe_empty_txd(ring) > ring->tx_thresh)) + netif_wake_queue(dev); + } + + if (netif_xmit_stopped(netdev_get_tx_queue(dev, 0)) || !skb->xmit_more) + fe_reg_w32(ring->tx_next_idx, FE_REG_TX_CTX_IDX0); + + return 0; + +err_dma: + j = ring->tx_next_idx; + for (i = 0; i < tx_num; i++) { + ptxd = &ring->tx_dma[j]; + tx_buf = &ring->tx_buf[j]; + + /* unmap dma */ + fe_txd_unmap(&dev->dev, tx_buf); + + ptxd->txd2 = TX_DMA_DESP2_DEF; + j = NEXT_TX_DESP_IDX(j); + } + /* make sure that all changes to the dma ring are flushed before we + * continue + */ + wmb(); + +err_out: + return -1; +} + +static inline int fe_skb_padto(struct sk_buff *skb, struct fe_priv *priv) +{ + unsigned int len; + int ret; + + ret = 0; + if (unlikely(skb->len < VLAN_ETH_ZLEN)) { + if ((priv->flags & FE_FLAG_PADDING_64B) && + !(priv->flags & FE_FLAG_PADDING_BUG)) + return ret; + + if (skb_vlan_tag_present(skb)) + len = ETH_ZLEN; + else if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) + len = VLAN_ETH_ZLEN; + else if (!(priv->flags & FE_FLAG_PADDING_64B)) + len = ETH_ZLEN; + else + return ret; + + if (skb->len < len) { + ret = skb_pad(skb, len - skb->len); + if (ret < 0) + return ret; + skb->len = len; + skb_set_tail_pointer(skb, len); + } + } + + return ret; +} + +static inline int fe_cal_txd_req(struct sk_buff *skb) +{ + int i, nfrags; + struct skb_frag_struct *frag; + + nfrags = 1; + if (skb_is_gso(skb)) { + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + frag = &skb_shinfo(skb)->frags[i]; + nfrags += DIV_ROUND_UP(frag->size, TX_DMA_BUF_LEN); + } + } else { + nfrags += skb_shinfo(skb)->nr_frags; + } + + return DIV_ROUND_UP(nfrags, 2); +} + +static int fe_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + struct fe_tx_ring *ring = &priv->tx_ring; + struct net_device_stats *stats = &dev->stats; + int tx_num; + int len = skb->len; + + if (fe_skb_padto(skb, priv)) { + netif_warn(priv, tx_err, dev, "tx padding failed!\n"); + return NETDEV_TX_OK; + } + + tx_num = fe_cal_txd_req(skb); + if (unlikely(fe_empty_txd(ring) <= tx_num)) { + netif_stop_queue(dev); + netif_err(priv, tx_queued, dev, + "Tx Ring full when queue awake!\n"); + return NETDEV_TX_BUSY; + } + + if (fe_tx_map_dma(skb, dev, tx_num, ring) < 0) { + stats->tx_dropped++; + } else { + stats->tx_packets++; + stats->tx_bytes += len; + } + + return NETDEV_TX_OK; +} + +static int fe_poll_rx(struct napi_struct *napi, int budget, + struct fe_priv *priv, u32 rx_intr) +{ + struct net_device *netdev = priv->netdev; + struct net_device_stats *stats = &netdev->stats; + struct fe_soc_data *soc = priv->soc; + struct fe_rx_ring *ring = &priv->rx_ring; + int idx = ring->rx_calc_idx; + u32 checksum_bit; + struct sk_buff *skb; + u8 *data, *new_data; + struct fe_rx_dma *rxd, trxd; + int done = 0, pad; + + if (netdev->features & NETIF_F_RXCSUM) + checksum_bit = soc->checksum_bit; + else + checksum_bit = 0; + + if (priv->flags & FE_FLAG_RX_2B_OFFSET) + pad = 0; + else + pad = NET_IP_ALIGN; + + while (done < budget) { + unsigned int pktlen; + dma_addr_t dma_addr; + + idx = NEXT_RX_DESP_IDX(idx); + rxd = &ring->rx_dma[idx]; + data = ring->rx_data[idx]; + + fe_get_rxd(&trxd, rxd); + if (!(trxd.rxd2 & RX_DMA_DONE)) + break; + + /* alloc new buffer */ + new_data = netdev_alloc_frag(ring->frag_size); + if (unlikely(!new_data)) { + stats->rx_dropped++; + goto release_desc; + } + dma_addr = dma_map_single(&netdev->dev, + new_data + NET_SKB_PAD + pad, + ring->rx_buf_size, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(&netdev->dev, dma_addr))) { + put_page(virt_to_head_page(new_data)); + goto release_desc; + } + + /* receive data */ + skb = build_skb(data, ring->frag_size); + if (unlikely(!skb)) { + put_page(virt_to_head_page(new_data)); + goto release_desc; + } + skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN); + + dma_unmap_single(&netdev->dev, trxd.rxd1, + ring->rx_buf_size, DMA_FROM_DEVICE); + pktlen = RX_DMA_GET_PLEN0(trxd.rxd2); + skb->dev = netdev; + skb_put(skb, pktlen); + if (trxd.rxd4 & checksum_bit) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb_checksum_none_assert(skb); + skb->protocol = eth_type_trans(skb, netdev); + +#ifdef CONFIG_NET_MEDIATEK_OFFLOAD + if (mtk_offload_check_rx(priv, skb, trxd.rxd4) == 0) { +#endif + stats->rx_packets++; + stats->rx_bytes += pktlen; + + napi_gro_receive(napi, skb); +#ifdef CONFIG_NET_MEDIATEK_OFFLOAD + } else { + dev_kfree_skb(skb); + } +#endif + ring->rx_data[idx] = new_data; + rxd->rxd1 = (unsigned int)dma_addr; + +release_desc: + if (priv->flags & FE_FLAG_RX_SG_DMA) + rxd->rxd2 = RX_DMA_PLEN0(ring->rx_buf_size); + else + rxd->rxd2 = RX_DMA_LSO; + + ring->rx_calc_idx = idx; + /* make sure that all changes to the dma ring are flushed before + * we continue + */ + wmb(); + fe_reg_w32(ring->rx_calc_idx, FE_REG_RX_CALC_IDX0); + done++; + } + + if (done < budget) + fe_reg_w32(rx_intr, FE_REG_FE_INT_STATUS); + + return done; +} + +static int fe_poll_tx(struct fe_priv *priv, int budget, u32 tx_intr, + int *tx_again) +{ + struct net_device *netdev = priv->netdev; + struct device *dev = &netdev->dev; + unsigned int bytes_compl = 0; + struct sk_buff *skb; + struct fe_tx_buf *tx_buf; + int done = 0; + u32 idx, hwidx; + struct fe_tx_ring *ring = &priv->tx_ring; + + idx = ring->tx_free_idx; + hwidx = fe_reg_r32(FE_REG_TX_DTX_IDX0); + + while ((idx != hwidx) && budget) { + tx_buf = &ring->tx_buf[idx]; + skb = tx_buf->skb; + + if (!skb) + break; + + if (skb != (struct sk_buff *)DMA_DUMMY_DESC) { + bytes_compl += skb->len; + done++; + budget--; + } + fe_txd_unmap(dev, tx_buf); + idx = NEXT_TX_DESP_IDX(idx); + } + ring->tx_free_idx = idx; + + if (idx == hwidx) { + /* read hw index again make sure no new tx packet */ + hwidx = fe_reg_r32(FE_REG_TX_DTX_IDX0); + if (idx == hwidx) + fe_reg_w32(tx_intr, FE_REG_FE_INT_STATUS); + else + *tx_again = 1; + } else { + *tx_again = 1; + } + + if (done) { + netdev_completed_queue(netdev, done, bytes_compl); + smp_mb(); + if (unlikely(netif_queue_stopped(netdev) && + (fe_empty_txd(ring) > ring->tx_thresh))) + netif_wake_queue(netdev); + } + + return done; +} + +static int fe_poll(struct napi_struct *napi, int budget) +{ + struct fe_priv *priv = container_of(napi, struct fe_priv, rx_napi); + struct fe_hw_stats *hwstat = priv->hw_stats; + int tx_done, rx_done, tx_again; + u32 status, fe_status, status_reg, mask; + u32 tx_intr, rx_intr, status_intr; + + status = fe_reg_r32(FE_REG_FE_INT_STATUS); + fe_status = status; + tx_intr = priv->soc->tx_int; + rx_intr = priv->soc->rx_int; + status_intr = priv->soc->status_int; + tx_done = 0; + rx_done = 0; + tx_again = 0; + + if (fe_reg_table[FE_REG_FE_INT_STATUS2]) { + fe_status = fe_reg_r32(FE_REG_FE_INT_STATUS2); + status_reg = FE_REG_FE_INT_STATUS2; + } else { + status_reg = FE_REG_FE_INT_STATUS; + } + + if (status & tx_intr) + tx_done = fe_poll_tx(priv, budget, tx_intr, &tx_again); + + if (status & rx_intr) + rx_done = fe_poll_rx(napi, budget, priv, rx_intr); + + if (unlikely(fe_status & status_intr)) { + if (hwstat && spin_trylock(&hwstat->stats_lock)) { + fe_stats_update(priv); + spin_unlock(&hwstat->stats_lock); + } + fe_reg_w32(status_intr, status_reg); + } + + if (unlikely(netif_msg_intr(priv))) { + mask = fe_reg_r32(FE_REG_FE_INT_ENABLE); + netdev_info(priv->netdev, + "done tx %d, rx %d, intr 0x%08x/0x%x\n", + tx_done, rx_done, status, mask); + } + + if (!tx_again && (rx_done < budget)) { + status = fe_reg_r32(FE_REG_FE_INT_STATUS); + if (status & (tx_intr | rx_intr)) { + /* let napi poll again */ + rx_done = budget; + goto poll_again; + } + + napi_complete_done(napi, rx_done); + fe_int_enable(tx_intr | rx_intr); + } else { + rx_done = budget; + } + +poll_again: + return rx_done; +} + +static void fe_tx_timeout(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + struct fe_tx_ring *ring = &priv->tx_ring; + + priv->netdev->stats.tx_errors++; + netif_err(priv, tx_err, dev, + "transmit timed out\n"); + netif_info(priv, drv, dev, "dma_cfg:%08x\n", + fe_reg_r32(FE_REG_PDMA_GLO_CFG)); + netif_info(priv, drv, dev, "tx_ring=%d, " + "base=%08x, max=%u, ctx=%u, dtx=%u, fdx=%hu, next=%hu\n", + 0, fe_reg_r32(FE_REG_TX_BASE_PTR0), + fe_reg_r32(FE_REG_TX_MAX_CNT0), + fe_reg_r32(FE_REG_TX_CTX_IDX0), + fe_reg_r32(FE_REG_TX_DTX_IDX0), + ring->tx_free_idx, + ring->tx_next_idx); + netif_info(priv, drv, dev, + "rx_ring=%d, base=%08x, max=%u, calc=%u, drx=%u\n", + 0, fe_reg_r32(FE_REG_RX_BASE_PTR0), + fe_reg_r32(FE_REG_RX_MAX_CNT0), + fe_reg_r32(FE_REG_RX_CALC_IDX0), + fe_reg_r32(FE_REG_RX_DRX_IDX0)); + + if (!test_and_set_bit(FE_FLAG_RESET_PENDING, priv->pending_flags)) + schedule_work(&priv->pending_work); +} + +static irqreturn_t fe_handle_irq(int irq, void *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + u32 status, int_mask; + + status = fe_reg_r32(FE_REG_FE_INT_STATUS); + + if (unlikely(!status)) + return IRQ_NONE; + + int_mask = (priv->soc->rx_int | priv->soc->tx_int); + if (likely(status & int_mask)) { + if (likely(napi_schedule_prep(&priv->rx_napi))) { + fe_int_disable(int_mask); + __napi_schedule(&priv->rx_napi); + } + } else { + fe_reg_w32(status, FE_REG_FE_INT_STATUS); + } + + return IRQ_HANDLED; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void fe_poll_controller(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + u32 int_mask = priv->soc->tx_int | priv->soc->rx_int; + + fe_int_disable(int_mask); + fe_handle_irq(dev->irq, dev); + fe_int_enable(int_mask); +} +#endif + +int fe_set_clock_cycle(struct fe_priv *priv) +{ + unsigned long sysclk = priv->sysclk; + + sysclk /= FE_US_CYC_CNT_DIVISOR; + sysclk <<= FE_US_CYC_CNT_SHIFT; + + fe_w32((fe_r32(FE_FE_GLO_CFG) & + ~(FE_US_CYC_CNT_MASK << FE_US_CYC_CNT_SHIFT)) | + sysclk, + FE_FE_GLO_CFG); + return 0; +} + +void fe_fwd_config(struct fe_priv *priv) +{ + u32 fwd_cfg; + + fwd_cfg = fe_r32(FE_GDMA1_FWD_CFG); + + /* disable jumbo frame */ + if (priv->flags & FE_FLAG_JUMBO_FRAME) + fwd_cfg &= ~FE_GDM1_JMB_EN; + + /* set unicast/multicast/broadcast frame to cpu */ + fwd_cfg &= ~0xffff; + + fe_w32(fwd_cfg, FE_GDMA1_FWD_CFG); +} + +static void fe_rxcsum_config(bool enable) +{ + if (enable) + fe_w32(fe_r32(FE_GDMA1_FWD_CFG) | (FE_GDM1_ICS_EN | + FE_GDM1_TCS_EN | FE_GDM1_UCS_EN), + FE_GDMA1_FWD_CFG); + else + fe_w32(fe_r32(FE_GDMA1_FWD_CFG) & ~(FE_GDM1_ICS_EN | + FE_GDM1_TCS_EN | FE_GDM1_UCS_EN), + FE_GDMA1_FWD_CFG); +} + +static void fe_txcsum_config(bool enable) +{ + if (enable) + fe_w32(fe_r32(FE_CDMA_CSG_CFG) | (FE_ICS_GEN_EN | + FE_TCS_GEN_EN | FE_UCS_GEN_EN), + FE_CDMA_CSG_CFG); + else + fe_w32(fe_r32(FE_CDMA_CSG_CFG) & ~(FE_ICS_GEN_EN | + FE_TCS_GEN_EN | FE_UCS_GEN_EN), + FE_CDMA_CSG_CFG); +} + +void fe_csum_config(struct fe_priv *priv) +{ + struct net_device *dev = priv_netdev(priv); + + fe_txcsum_config((dev->features & NETIF_F_IP_CSUM)); + fe_rxcsum_config((dev->features & NETIF_F_RXCSUM)); +} + +static int fe_hw_init(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + int i, err; + + err = devm_request_irq(priv->dev, dev->irq, fe_handle_irq, 0, + dev_name(priv->dev), dev); + if (err) + return err; + + if (priv->soc->set_mac) + priv->soc->set_mac(priv, dev->dev_addr); + else + fe_hw_set_macaddr(priv, dev->dev_addr); + + /* disable delay interrupt */ + fe_reg_w32(0, FE_REG_DLY_INT_CFG); + + fe_int_disable(priv->soc->tx_int | priv->soc->rx_int); + + /* frame engine will push VLAN tag regarding to VIDX feild in Tx desc */ + if (fe_reg_table[FE_REG_FE_DMA_VID_BASE]) + for (i = 0; i < 16; i += 2) + fe_w32(((i + 1) << 16) + i, + fe_reg_table[FE_REG_FE_DMA_VID_BASE] + + (i * 2)); + + if (priv->soc->fwd_config(priv)) + netdev_err(dev, "unable to get clock\n"); + + if (fe_reg_table[FE_REG_FE_RST_GL]) { + fe_reg_w32(1, FE_REG_FE_RST_GL); + fe_reg_w32(0, FE_REG_FE_RST_GL); + } + + return 0; +} + +static int fe_open(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + unsigned long flags; + u32 val; + int err; + + err = fe_init_dma(priv); + if (err) { + fe_free_dma(priv); + return err; + } + + spin_lock_irqsave(&priv->page_lock, flags); + + val = FE_TX_WB_DDONE | FE_RX_DMA_EN | FE_TX_DMA_EN; + if (priv->flags & FE_FLAG_RX_2B_OFFSET) + val |= FE_RX_2B_OFFSET; + val |= priv->soc->pdma_glo_cfg; + fe_reg_w32(val, FE_REG_PDMA_GLO_CFG); + + spin_unlock_irqrestore(&priv->page_lock, flags); + + if (priv->phy) + priv->phy->start(priv); + + if (priv->soc->has_carrier && priv->soc->has_carrier(priv)) + netif_carrier_on(dev); + + napi_enable(&priv->rx_napi); + fe_int_enable(priv->soc->tx_int | priv->soc->rx_int); + netif_start_queue(dev); +#ifdef CONFIG_NET_MEDIATEK_OFFLOAD + mtk_ppe_probe(priv); +#endif + + return 0; +} + +static int fe_stop(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + unsigned long flags; + int i; + + netif_tx_disable(dev); + fe_int_disable(priv->soc->tx_int | priv->soc->rx_int); + napi_disable(&priv->rx_napi); + + if (priv->phy) + priv->phy->stop(priv); + + spin_lock_irqsave(&priv->page_lock, flags); + + fe_reg_w32(fe_reg_r32(FE_REG_PDMA_GLO_CFG) & + ~(FE_TX_WB_DDONE | FE_RX_DMA_EN | FE_TX_DMA_EN), + FE_REG_PDMA_GLO_CFG); + spin_unlock_irqrestore(&priv->page_lock, flags); + + /* wait dma stop */ + for (i = 0; i < 10; i++) { + if (fe_reg_r32(FE_REG_PDMA_GLO_CFG) & + (FE_TX_DMA_BUSY | FE_RX_DMA_BUSY)) { + msleep(20); + continue; + } + break; + } + + fe_free_dma(priv); + +#ifdef CONFIG_NET_MEDIATEK_OFFLOAD + mtk_ppe_remove(priv); +#endif + + return 0; +} + +static int __init fe_init(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + struct device_node *port; + const char *mac_addr; + int err; + + priv->soc->reset_fe(); + + if (priv->soc->switch_init) + if (priv->soc->switch_init(priv)) { + netdev_err(dev, "failed to initialize switch core\n"); + return -ENODEV; + } + + mac_addr = of_get_mac_address(priv->dev->of_node); + if (mac_addr) + ether_addr_copy(dev->dev_addr, mac_addr); + + /* If the mac address is invalid, use random mac address */ + if (!is_valid_ether_addr(dev->dev_addr)) { + random_ether_addr(dev->dev_addr); + dev_err(priv->dev, "generated random MAC address %pM\n", + dev->dev_addr); + } + + err = fe_mdio_init(priv); + if (err) + return err; + + if (priv->soc->port_init) + for_each_child_of_node(priv->dev->of_node, port) + if (of_device_is_compatible(port, "mediatek,eth-port") && + of_device_is_available(port)) + priv->soc->port_init(priv, port); + + if (priv->phy) { + err = priv->phy->connect(priv); + if (err) + goto err_phy_disconnect; + } + + err = fe_hw_init(dev); + if (err) + goto err_phy_disconnect; + + if ((priv->flags & FE_FLAG_HAS_SWITCH) && priv->soc->switch_config) + priv->soc->switch_config(priv); + + return 0; + +err_phy_disconnect: + if (priv->phy) + priv->phy->disconnect(priv); + fe_mdio_cleanup(priv); + + return err; +} + +static void fe_uninit(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + + if (priv->phy) + priv->phy->disconnect(priv); + fe_mdio_cleanup(priv); + + fe_reg_w32(0, FE_REG_FE_INT_ENABLE); + free_irq(dev->irq, dev); +} + +static int fe_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + struct fe_priv *priv = netdev_priv(dev); + + if (!priv->phy_dev) + return -ENODEV; + + switch (cmd) { + case SIOCETHTOOL: + return phy_ethtool_ioctl(priv->phy_dev, + (void *) ifr->ifr_data); + case SIOCGMIIPHY: + case SIOCGMIIREG: + case SIOCSMIIREG: + return phy_mii_ioctl(priv->phy_dev, ifr, cmd); + default: + break; + } + + return -EOPNOTSUPP; +} + +static int fe_change_mtu(struct net_device *dev, int new_mtu) +{ + struct fe_priv *priv = netdev_priv(dev); + int frag_size, old_mtu; + u32 fwd_cfg; + + if (!(priv->flags & FE_FLAG_JUMBO_FRAME)) + return eth_change_mtu(dev, new_mtu); + + if (IS_ENABLED(CONFIG_SOC_MT7621)) + if (new_mtu > 2048) + return -EINVAL; + + frag_size = fe_max_frag_size(new_mtu); + if (new_mtu < 68 || frag_size > PAGE_SIZE) + return -EINVAL; + + old_mtu = dev->mtu; + dev->mtu = new_mtu; + + /* return early if the buffer sizes will not change */ + if (old_mtu <= ETH_DATA_LEN && new_mtu <= ETH_DATA_LEN) + return 0; + if (old_mtu > ETH_DATA_LEN && new_mtu > ETH_DATA_LEN) + return 0; + + if (new_mtu <= ETH_DATA_LEN) + priv->rx_ring.frag_size = fe_max_frag_size(ETH_DATA_LEN); + else + priv->rx_ring.frag_size = PAGE_SIZE; + priv->rx_ring.rx_buf_size = fe_max_buf_size(priv->rx_ring.frag_size); + + if (!netif_running(dev)) + return 0; + + fe_stop(dev); + if (!IS_ENABLED(CONFIG_SOC_MT7621)) { + fwd_cfg = fe_r32(FE_GDMA1_FWD_CFG); + if (new_mtu <= ETH_DATA_LEN) { + fwd_cfg &= ~FE_GDM1_JMB_EN; + } else { + fwd_cfg &= ~(FE_GDM1_JMB_LEN_MASK << FE_GDM1_JMB_LEN_SHIFT); + fwd_cfg |= (DIV_ROUND_UP(frag_size, 1024) << + FE_GDM1_JMB_LEN_SHIFT) | FE_GDM1_JMB_EN; + } + fe_w32(fwd_cfg, FE_GDMA1_FWD_CFG); + } + + return fe_open(dev); +} + +#ifdef CONFIG_NET_MEDIATEK_OFFLOAD +static int +fe_flow_offload(enum flow_offload_type type, struct flow_offload *flow, + struct flow_offload_hw_path *src, + struct flow_offload_hw_path *dest) +{ + struct fe_priv *priv; + + if (src->dev != dest->dev) + return -EINVAL; + + priv = netdev_priv(src->dev); + + return mtk_flow_offload(priv, type, flow, src, dest); +} +#endif + +static const struct net_device_ops fe_netdev_ops = { + .ndo_init = fe_init, + .ndo_uninit = fe_uninit, + .ndo_open = fe_open, + .ndo_stop = fe_stop, + .ndo_start_xmit = fe_start_xmit, + .ndo_set_mac_address = fe_set_mac_address, + .ndo_validate_addr = eth_validate_addr, + .ndo_do_ioctl = fe_do_ioctl, + .ndo_change_mtu = fe_change_mtu, + .ndo_tx_timeout = fe_tx_timeout, + .ndo_get_stats64 = fe_get_stats64, + .ndo_vlan_rx_add_vid = fe_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = fe_vlan_rx_kill_vid, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = fe_poll_controller, +#endif +#ifdef CONFIG_NET_MEDIATEK_OFFLOAD + .ndo_flow_offload = fe_flow_offload, +#endif +}; + +static void fe_reset_pending(struct fe_priv *priv) +{ + struct net_device *dev = priv->netdev; + int err; + + rtnl_lock(); + fe_stop(dev); + + err = fe_open(dev); + if (err) { + netif_alert(priv, ifup, dev, + "Driver up/down cycle failed, closing device.\n"); + dev_close(dev); + } + rtnl_unlock(); +} + +static const struct fe_work_t fe_work[] = { + {FE_FLAG_RESET_PENDING, fe_reset_pending}, +}; + +static void fe_pending_work(struct work_struct *work) +{ + struct fe_priv *priv = container_of(work, struct fe_priv, pending_work); + int i; + bool pending; + + for (i = 0; i < ARRAY_SIZE(fe_work); i++) { + pending = test_and_clear_bit(fe_work[i].bitnr, + priv->pending_flags); + if (pending) + fe_work[i].action(priv); + } +} + +static int fe_probe(struct platform_device *pdev) +{ + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + const struct of_device_id *match; + struct fe_soc_data *soc; + struct net_device *netdev; + struct fe_priv *priv; + struct clk *sysclk; + int err, napi_weight; + + device_reset(&pdev->dev); + + match = of_match_device(of_fe_match, &pdev->dev); + soc = (struct fe_soc_data *)match->data; + + if (soc->reg_table) + fe_reg_table = soc->reg_table; + else + soc->reg_table = fe_reg_table; + + fe_base = devm_ioremap_resource(&pdev->dev, res); + if (!fe_base) { + err = -EADDRNOTAVAIL; + goto err_out; + } + + netdev = alloc_etherdev(sizeof(*priv)); + if (!netdev) { + dev_err(&pdev->dev, "alloc_etherdev failed\n"); + err = -ENOMEM; + goto err_iounmap; + } + + SET_NETDEV_DEV(netdev, &pdev->dev); + netdev->netdev_ops = &fe_netdev_ops; + netdev->base_addr = (unsigned long)fe_base; + + netdev->irq = platform_get_irq(pdev, 0); + if (netdev->irq < 0) { + dev_err(&pdev->dev, "no IRQ resource found\n"); + err = -ENXIO; + goto err_free_dev; + } + + if (soc->init_data) + soc->init_data(soc, netdev); + netdev->vlan_features = netdev->hw_features & ~NETIF_F_HW_VLAN_CTAG_TX; + netdev->features |= netdev->hw_features; + + /* fake rx vlan filter func. to support tx vlan offload func */ + if (fe_reg_table[FE_REG_FE_DMA_VID_BASE]) + netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; + + priv = netdev_priv(netdev); + spin_lock_init(&priv->page_lock); + if (fe_reg_table[FE_REG_FE_COUNTER_BASE]) { + priv->hw_stats = kzalloc(sizeof(*priv->hw_stats), GFP_KERNEL); + if (!priv->hw_stats) { + err = -ENOMEM; + goto err_free_dev; + } + spin_lock_init(&priv->hw_stats->stats_lock); + } + + sysclk = devm_clk_get(&pdev->dev, NULL); + if (!IS_ERR(sysclk)) { + priv->sysclk = clk_get_rate(sysclk); + } else if ((priv->flags & FE_FLAG_CALIBRATE_CLK)) { + dev_err(&pdev->dev, "this soc needs a clk for calibration\n"); + err = -ENXIO; + goto err_free_dev; + } + + priv->switch_np = of_parse_phandle(pdev->dev.of_node, "mediatek,switch", 0); + if ((priv->flags & FE_FLAG_HAS_SWITCH) && !priv->switch_np) { + dev_err(&pdev->dev, "failed to read switch phandle\n"); + err = -ENODEV; + goto err_free_dev; + } + + priv->netdev = netdev; + priv->dev = &pdev->dev; + priv->soc = soc; + priv->msg_enable = netif_msg_init(fe_msg_level, FE_DEFAULT_MSG_ENABLE); + priv->rx_ring.frag_size = fe_max_frag_size(ETH_DATA_LEN); + priv->rx_ring.rx_buf_size = fe_max_buf_size(priv->rx_ring.frag_size); + priv->tx_ring.tx_ring_size = NUM_DMA_DESC; + priv->rx_ring.rx_ring_size = NUM_DMA_DESC; + INIT_WORK(&priv->pending_work, fe_pending_work); + + napi_weight = 16; + if (priv->flags & FE_FLAG_NAPI_WEIGHT) { + napi_weight *= 4; + priv->tx_ring.tx_ring_size *= 4; + priv->rx_ring.rx_ring_size *= 4; + } + netif_napi_add(netdev, &priv->rx_napi, fe_poll, napi_weight); + fe_set_ethtool_ops(netdev); + + err = register_netdev(netdev); + if (err) { + dev_err(&pdev->dev, "error bringing up device\n"); + goto err_free_dev; + } + + platform_set_drvdata(pdev, netdev); + + netif_info(priv, probe, netdev, "mediatek frame engine at 0x%08lx, irq %d\n", + netdev->base_addr, netdev->irq); + + return 0; + +err_free_dev: + free_netdev(netdev); +err_iounmap: + devm_iounmap(&pdev->dev, fe_base); +err_out: + return err; +} + +static int fe_remove(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct fe_priv *priv = netdev_priv(dev); + + netif_napi_del(&priv->rx_napi); + kfree(priv->hw_stats); + + cancel_work_sync(&priv->pending_work); + + unregister_netdev(dev); + free_netdev(dev); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver fe_driver = { + .probe = fe_probe, + .remove = fe_remove, + .driver = { + .name = "mtk_soc_eth", + .owner = THIS_MODULE, + .of_match_table = of_fe_match, + }, +}; + +module_platform_driver(fe_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("John Crispin "); +MODULE_DESCRIPTION("Ethernet driver for Ralink SoC"); +MODULE_VERSION(MTK_FE_DRV_VERSION); diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_eth_soc.h b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_eth_soc.h new file mode 100644 index 000000000..dfaa5fd9e --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_eth_soc.h @@ -0,0 +1,539 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#ifndef FE_ETH_H +#define FE_ETH_H + +#include +#include +#include +#include +#include +#include +#include + +enum fe_reg { + FE_REG_PDMA_GLO_CFG = 0, + FE_REG_PDMA_RST_CFG, + FE_REG_DLY_INT_CFG, + FE_REG_TX_BASE_PTR0, + FE_REG_TX_MAX_CNT0, + FE_REG_TX_CTX_IDX0, + FE_REG_TX_DTX_IDX0, + FE_REG_RX_BASE_PTR0, + FE_REG_RX_MAX_CNT0, + FE_REG_RX_CALC_IDX0, + FE_REG_RX_DRX_IDX0, + FE_REG_FE_INT_ENABLE, + FE_REG_FE_INT_STATUS, + FE_REG_FE_DMA_VID_BASE, + FE_REG_FE_COUNTER_BASE, + FE_REG_FE_RST_GL, + FE_REG_FE_INT_STATUS2, + FE_REG_COUNT +}; + +enum fe_work_flag { + FE_FLAG_RESET_PENDING, + FE_FLAG_MAX +}; + +#define MTK_FE_DRV_VERSION "0.1.2" + +/* power of 2 to let NEXT_TX_DESP_IDX work */ +#define NUM_DMA_DESC BIT(10) +#define MAX_DMA_DESC 0xfff + +#define FE_DELAY_EN_INT 0x80 +#define FE_DELAY_MAX_INT 0x04 +#define FE_DELAY_MAX_TOUT 0x04 +#define FE_DELAY_TIME 20 +#define FE_DELAY_CHAN (((FE_DELAY_EN_INT | FE_DELAY_MAX_INT) << 8) | \ + FE_DELAY_MAX_TOUT) +#define FE_DELAY_INIT ((FE_DELAY_CHAN << 16) | FE_DELAY_CHAN) +#define FE_PSE_FQFC_CFG_INIT 0x80504000 +#define FE_PSE_FQFC_CFG_256Q 0xff908000 + +/* interrupt bits */ +#define FE_CNT_PPE_AF BIT(31) +#define FE_CNT_GDM_AF BIT(29) +#define FE_PSE_P2_FC BIT(26) +#define FE_PSE_BUF_DROP BIT(24) +#define FE_GDM_OTHER_DROP BIT(23) +#define FE_PSE_P1_FC BIT(22) +#define FE_PSE_P0_FC BIT(21) +#define FE_PSE_FQ_EMPTY BIT(20) +#define FE_GE1_STA_CHG BIT(18) +#define FE_TX_COHERENT BIT(17) +#define FE_RX_COHERENT BIT(16) +#define FE_TX_DONE_INT3 BIT(11) +#define FE_TX_DONE_INT2 BIT(10) +#define FE_TX_DONE_INT1 BIT(9) +#define FE_TX_DONE_INT0 BIT(8) +#define FE_RX_DONE_INT0 BIT(2) +#define FE_TX_DLY_INT BIT(1) +#define FE_RX_DLY_INT BIT(0) + +#define FE_RX_DONE_INT FE_RX_DONE_INT0 +#define FE_TX_DONE_INT (FE_TX_DONE_INT0 | FE_TX_DONE_INT1 | \ + FE_TX_DONE_INT2 | FE_TX_DONE_INT3) + +#define RT5350_RX_DLY_INT BIT(30) +#define RT5350_TX_DLY_INT BIT(28) +#define RT5350_RX_DONE_INT1 BIT(17) +#define RT5350_RX_DONE_INT0 BIT(16) +#define RT5350_TX_DONE_INT3 BIT(3) +#define RT5350_TX_DONE_INT2 BIT(2) +#define RT5350_TX_DONE_INT1 BIT(1) +#define RT5350_TX_DONE_INT0 BIT(0) + +#define RT5350_RX_DONE_INT (RT5350_RX_DONE_INT0 | RT5350_RX_DONE_INT1) +#define RT5350_TX_DONE_INT (RT5350_TX_DONE_INT0 | RT5350_TX_DONE_INT1 | \ + RT5350_TX_DONE_INT2 | RT5350_TX_DONE_INT3) + +/* registers */ +#define FE_FE_OFFSET 0x0000 +#define FE_GDMA_OFFSET 0x0020 +#define FE_PSE_OFFSET 0x0040 +#define FE_GDMA2_OFFSET 0x0060 +#define FE_CDMA_OFFSET 0x0080 +#define FE_DMA_VID0 0x00a8 +#define FE_PDMA_OFFSET 0x0100 +#define FE_PPE_OFFSET 0x0200 +#define FE_CMTABLE_OFFSET 0x0400 +#define FE_POLICYTABLE_OFFSET 0x1000 + +#define RT5350_PDMA_OFFSET 0x0800 +#define RT5350_SDM_OFFSET 0x0c00 + +#define FE_MDIO_ACCESS (FE_FE_OFFSET + 0x00) +#define FE_MDIO_CFG (FE_FE_OFFSET + 0x04) +#define FE_FE_GLO_CFG (FE_FE_OFFSET + 0x08) +#define FE_FE_RST_GL (FE_FE_OFFSET + 0x0C) +#define FE_FE_INT_STATUS (FE_FE_OFFSET + 0x10) +#define FE_FE_INT_ENABLE (FE_FE_OFFSET + 0x14) +#define FE_MDIO_CFG2 (FE_FE_OFFSET + 0x18) +#define FE_FOC_TS_T (FE_FE_OFFSET + 0x1C) + +#define FE_GDMA1_FWD_CFG (FE_GDMA_OFFSET + 0x00) +#define FE_GDMA1_SCH_CFG (FE_GDMA_OFFSET + 0x04) +#define FE_GDMA1_SHPR_CFG (FE_GDMA_OFFSET + 0x08) +#define FE_GDMA1_MAC_ADRL (FE_GDMA_OFFSET + 0x0C) +#define FE_GDMA1_MAC_ADRH (FE_GDMA_OFFSET + 0x10) + +#define FE_GDMA2_FWD_CFG (FE_GDMA2_OFFSET + 0x00) +#define FE_GDMA2_SCH_CFG (FE_GDMA2_OFFSET + 0x04) +#define FE_GDMA2_SHPR_CFG (FE_GDMA2_OFFSET + 0x08) +#define FE_GDMA2_MAC_ADRL (FE_GDMA2_OFFSET + 0x0C) +#define FE_GDMA2_MAC_ADRH (FE_GDMA2_OFFSET + 0x10) + +#define FE_PSE_FQ_CFG (FE_PSE_OFFSET + 0x00) +#define FE_CDMA_FC_CFG (FE_PSE_OFFSET + 0x04) +#define FE_GDMA1_FC_CFG (FE_PSE_OFFSET + 0x08) +#define FE_GDMA2_FC_CFG (FE_PSE_OFFSET + 0x0C) + +#define FE_CDMA_CSG_CFG (FE_CDMA_OFFSET + 0x00) +#define FE_CDMA_SCH_CFG (FE_CDMA_OFFSET + 0x04) + +#ifdef CONFIG_SOC_MT7621 +#define MT7620A_GDMA_OFFSET 0x0500 +#else +#define MT7620A_GDMA_OFFSET 0x0600 +#endif +#define MT7620A_GDMA1_FWD_CFG (MT7620A_GDMA_OFFSET + 0x00) +#define MT7620A_FE_GDMA1_SCH_CFG (MT7620A_GDMA_OFFSET + 0x04) +#define MT7620A_FE_GDMA1_SHPR_CFG (MT7620A_GDMA_OFFSET + 0x08) +#define MT7620A_FE_GDMA1_MAC_ADRL (MT7620A_GDMA_OFFSET + 0x0C) +#define MT7620A_FE_GDMA1_MAC_ADRH (MT7620A_GDMA_OFFSET + 0x10) + +#define RT5350_TX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x00) +#define RT5350_TX_MAX_CNT0 (RT5350_PDMA_OFFSET + 0x04) +#define RT5350_TX_CTX_IDX0 (RT5350_PDMA_OFFSET + 0x08) +#define RT5350_TX_DTX_IDX0 (RT5350_PDMA_OFFSET + 0x0C) +#define RT5350_TX_BASE_PTR1 (RT5350_PDMA_OFFSET + 0x10) +#define RT5350_TX_MAX_CNT1 (RT5350_PDMA_OFFSET + 0x14) +#define RT5350_TX_CTX_IDX1 (RT5350_PDMA_OFFSET + 0x18) +#define RT5350_TX_DTX_IDX1 (RT5350_PDMA_OFFSET + 0x1C) +#define RT5350_TX_BASE_PTR2 (RT5350_PDMA_OFFSET + 0x20) +#define RT5350_TX_MAX_CNT2 (RT5350_PDMA_OFFSET + 0x24) +#define RT5350_TX_CTX_IDX2 (RT5350_PDMA_OFFSET + 0x28) +#define RT5350_TX_DTX_IDX2 (RT5350_PDMA_OFFSET + 0x2C) +#define RT5350_TX_BASE_PTR3 (RT5350_PDMA_OFFSET + 0x30) +#define RT5350_TX_MAX_CNT3 (RT5350_PDMA_OFFSET + 0x34) +#define RT5350_TX_CTX_IDX3 (RT5350_PDMA_OFFSET + 0x38) +#define RT5350_TX_DTX_IDX3 (RT5350_PDMA_OFFSET + 0x3C) +#define RT5350_RX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x100) +#define RT5350_RX_MAX_CNT0 (RT5350_PDMA_OFFSET + 0x104) +#define RT5350_RX_CALC_IDX0 (RT5350_PDMA_OFFSET + 0x108) +#define RT5350_RX_DRX_IDX0 (RT5350_PDMA_OFFSET + 0x10C) +#define RT5350_RX_BASE_PTR1 (RT5350_PDMA_OFFSET + 0x110) +#define RT5350_RX_MAX_CNT1 (RT5350_PDMA_OFFSET + 0x114) +#define RT5350_RX_CALC_IDX1 (RT5350_PDMA_OFFSET + 0x118) +#define RT5350_RX_DRX_IDX1 (RT5350_PDMA_OFFSET + 0x11C) +#define RT5350_PDMA_GLO_CFG (RT5350_PDMA_OFFSET + 0x204) +#define RT5350_PDMA_RST_CFG (RT5350_PDMA_OFFSET + 0x208) +#define RT5350_DLY_INT_CFG (RT5350_PDMA_OFFSET + 0x20c) +#define RT5350_FE_INT_STATUS (RT5350_PDMA_OFFSET + 0x220) +#define RT5350_FE_INT_ENABLE (RT5350_PDMA_OFFSET + 0x228) +#define RT5350_PDMA_SCH_CFG (RT5350_PDMA_OFFSET + 0x280) + +#define FE_PDMA_GLO_CFG (FE_PDMA_OFFSET + 0x00) +#define FE_PDMA_RST_CFG (FE_PDMA_OFFSET + 0x04) +#define FE_PDMA_SCH_CFG (FE_PDMA_OFFSET + 0x08) +#define FE_DLY_INT_CFG (FE_PDMA_OFFSET + 0x0C) +#define FE_TX_BASE_PTR0 (FE_PDMA_OFFSET + 0x10) +#define FE_TX_MAX_CNT0 (FE_PDMA_OFFSET + 0x14) +#define FE_TX_CTX_IDX0 (FE_PDMA_OFFSET + 0x18) +#define FE_TX_DTX_IDX0 (FE_PDMA_OFFSET + 0x1C) +#define FE_TX_BASE_PTR1 (FE_PDMA_OFFSET + 0x20) +#define FE_TX_MAX_CNT1 (FE_PDMA_OFFSET + 0x24) +#define FE_TX_CTX_IDX1 (FE_PDMA_OFFSET + 0x28) +#define FE_TX_DTX_IDX1 (FE_PDMA_OFFSET + 0x2C) +#define FE_RX_BASE_PTR0 (FE_PDMA_OFFSET + 0x30) +#define FE_RX_MAX_CNT0 (FE_PDMA_OFFSET + 0x34) +#define FE_RX_CALC_IDX0 (FE_PDMA_OFFSET + 0x38) +#define FE_RX_DRX_IDX0 (FE_PDMA_OFFSET + 0x3C) +#define FE_TX_BASE_PTR2 (FE_PDMA_OFFSET + 0x40) +#define FE_TX_MAX_CNT2 (FE_PDMA_OFFSET + 0x44) +#define FE_TX_CTX_IDX2 (FE_PDMA_OFFSET + 0x48) +#define FE_TX_DTX_IDX2 (FE_PDMA_OFFSET + 0x4C) +#define FE_TX_BASE_PTR3 (FE_PDMA_OFFSET + 0x50) +#define FE_TX_MAX_CNT3 (FE_PDMA_OFFSET + 0x54) +#define FE_TX_CTX_IDX3 (FE_PDMA_OFFSET + 0x58) +#define FE_TX_DTX_IDX3 (FE_PDMA_OFFSET + 0x5C) +#define FE_RX_BASE_PTR1 (FE_PDMA_OFFSET + 0x60) +#define FE_RX_MAX_CNT1 (FE_PDMA_OFFSET + 0x64) +#define FE_RX_CALC_IDX1 (FE_PDMA_OFFSET + 0x68) +#define FE_RX_DRX_IDX1 (FE_PDMA_OFFSET + 0x6C) + +/* Switch DMA configuration */ +#define RT5350_SDM_CFG (RT5350_SDM_OFFSET + 0x00) +#define RT5350_SDM_RRING (RT5350_SDM_OFFSET + 0x04) +#define RT5350_SDM_TRING (RT5350_SDM_OFFSET + 0x08) +#define RT5350_SDM_MAC_ADRL (RT5350_SDM_OFFSET + 0x0C) +#define RT5350_SDM_MAC_ADRH (RT5350_SDM_OFFSET + 0x10) +#define RT5350_SDM_TPCNT (RT5350_SDM_OFFSET + 0x100) +#define RT5350_SDM_TBCNT (RT5350_SDM_OFFSET + 0x104) +#define RT5350_SDM_RPCNT (RT5350_SDM_OFFSET + 0x108) +#define RT5350_SDM_RBCNT (RT5350_SDM_OFFSET + 0x10C) +#define RT5350_SDM_CS_ERR (RT5350_SDM_OFFSET + 0x110) + +#define RT5350_SDM_ICS_EN BIT(16) +#define RT5350_SDM_TCS_EN BIT(17) +#define RT5350_SDM_UCS_EN BIT(18) + +/* MDIO_CFG register bits */ +#define FE_MDIO_CFG_AUTO_POLL_EN BIT(29) +#define FE_MDIO_CFG_GP1_BP_EN BIT(16) +#define FE_MDIO_CFG_GP1_FRC_EN BIT(15) +#define FE_MDIO_CFG_GP1_SPEED_10 (0 << 13) +#define FE_MDIO_CFG_GP1_SPEED_100 (1 << 13) +#define FE_MDIO_CFG_GP1_SPEED_1000 (2 << 13) +#define FE_MDIO_CFG_GP1_DUPLEX BIT(12) +#define FE_MDIO_CFG_GP1_FC_TX BIT(11) +#define FE_MDIO_CFG_GP1_FC_RX BIT(10) +#define FE_MDIO_CFG_GP1_LNK_DWN BIT(9) +#define FE_MDIO_CFG_GP1_AN_FAIL BIT(8) +#define FE_MDIO_CFG_MDC_CLK_DIV_1 (0 << 6) +#define FE_MDIO_CFG_MDC_CLK_DIV_2 (1 << 6) +#define FE_MDIO_CFG_MDC_CLK_DIV_4 (2 << 6) +#define FE_MDIO_CFG_MDC_CLK_DIV_8 (3 << 6) +#define FE_MDIO_CFG_TURBO_MII_FREQ BIT(5) +#define FE_MDIO_CFG_TURBO_MII_MODE BIT(4) +#define FE_MDIO_CFG_RX_CLK_SKEW_0 (0 << 2) +#define FE_MDIO_CFG_RX_CLK_SKEW_200 (1 << 2) +#define FE_MDIO_CFG_RX_CLK_SKEW_400 (2 << 2) +#define FE_MDIO_CFG_RX_CLK_SKEW_INV (3 << 2) +#define FE_MDIO_CFG_TX_CLK_SKEW_0 0 +#define FE_MDIO_CFG_TX_CLK_SKEW_200 1 +#define FE_MDIO_CFG_TX_CLK_SKEW_400 2 +#define FE_MDIO_CFG_TX_CLK_SKEW_INV 3 + +/* uni-cast port */ +#define FE_GDM1_JMB_LEN_MASK 0xf +#define FE_GDM1_JMB_LEN_SHIFT 28 +#define FE_GDM1_ICS_EN BIT(22) +#define FE_GDM1_TCS_EN BIT(21) +#define FE_GDM1_UCS_EN BIT(20) +#define FE_GDM1_JMB_EN BIT(19) +#define FE_GDM1_STRPCRC BIT(16) +#define FE_GDM1_UFRC_P_CPU (0 << 12) +#define FE_GDM1_UFRC_P_GDMA1 (1 << 12) +#define FE_GDM1_UFRC_P_PPE (6 << 12) + +/* checksums */ +#define FE_ICS_GEN_EN BIT(2) +#define FE_UCS_GEN_EN BIT(1) +#define FE_TCS_GEN_EN BIT(0) + +/* dma ring */ +#define FE_PST_DRX_IDX0 BIT(16) +#define FE_PST_DTX_IDX3 BIT(3) +#define FE_PST_DTX_IDX2 BIT(2) +#define FE_PST_DTX_IDX1 BIT(1) +#define FE_PST_DTX_IDX0 BIT(0) + +#define FE_RX_2B_OFFSET BIT(31) +#define FE_TX_WB_DDONE BIT(6) +#define FE_RX_DMA_BUSY BIT(3) +#define FE_TX_DMA_BUSY BIT(1) +#define FE_RX_DMA_EN BIT(2) +#define FE_TX_DMA_EN BIT(0) + +#define FE_PDMA_SIZE_4DWORDS (0 << 4) +#define FE_PDMA_SIZE_8DWORDS (1 << 4) +#define FE_PDMA_SIZE_16DWORDS (2 << 4) + +#define FE_US_CYC_CNT_MASK 0xff +#define FE_US_CYC_CNT_SHIFT 0x8 +#define FE_US_CYC_CNT_DIVISOR 1000000 + +/* rxd2 */ +#define RX_DMA_DONE BIT(31) +#define RX_DMA_LSO BIT(30) +#define RX_DMA_PLEN0(_x) (((_x) & 0x3fff) << 16) +#define RX_DMA_GET_PLEN0(_x) (((_x) >> 16) & 0x3fff) +#define RX_DMA_TAG BIT(15) +/* rxd3 */ +#define RX_DMA_TPID(_x) (((_x) >> 16) & 0xffff) +#define RX_DMA_VID(_x) ((_x) & 0xffff) +/* rxd4 */ +#define RX_DMA_L4VALID BIT(30) + +struct fe_rx_dma { + unsigned int rxd1; + unsigned int rxd2; + unsigned int rxd3; + unsigned int rxd4; +} __packed __aligned(4); + +#define TX_DMA_BUF_LEN 0x3fff +#define TX_DMA_PLEN0_MASK (TX_DMA_BUF_LEN << 16) +#define TX_DMA_PLEN0(_x) (((_x) & TX_DMA_BUF_LEN) << 16) +#define TX_DMA_PLEN1(_x) ((_x) & TX_DMA_BUF_LEN) +#define TX_DMA_GET_PLEN0(_x) (((_x) >> 16) & TX_DMA_BUF_LEN) +#define TX_DMA_GET_PLEN1(_x) ((_x) & TX_DMA_BUF_LEN) +#define TX_DMA_LS1 BIT(14) +#define TX_DMA_LS0 BIT(30) +#define TX_DMA_DONE BIT(31) + +#define TX_DMA_INS_VLAN_MT7621 BIT(16) +#define TX_DMA_INS_VLAN BIT(7) +#define TX_DMA_INS_PPPOE BIT(12) +#define TX_DMA_QN(_x) ((_x) << 16) +#define TX_DMA_PN(_x) ((_x) << 24) +#define TX_DMA_QN_MASK TX_DMA_QN(0x7) +#define TX_DMA_PN_MASK TX_DMA_PN(0x7) +#define TX_DMA_UDF BIT(20) +#define TX_DMA_CHKSUM (0x7 << 29) +#define TX_DMA_TSO BIT(28) + +/* frame engine counters */ +#define FE_PPE_AC_BCNT0 (FE_CMTABLE_OFFSET + 0x00) +#define FE_GDMA1_TX_GBCNT (FE_CMTABLE_OFFSET + 0x300) +#define FE_GDMA2_TX_GBCNT (FE_GDMA1_TX_GBCNT + 0x40) + +/* phy device flags */ +#define FE_PHY_FLAG_PORT BIT(0) +#define FE_PHY_FLAG_ATTACH BIT(1) + +struct fe_tx_dma { + unsigned int txd1; + unsigned int txd2; + unsigned int txd3; + unsigned int txd4; +} __packed __aligned(4); + +struct fe_priv; + +struct fe_phy { + /* make sure that phy operations are atomic */ + spinlock_t lock; + + struct phy_device *phy[8]; + struct device_node *phy_node[8]; + const __be32 *phy_fixed[8]; + int duplex[8]; + int speed[8]; + int tx_fc[8]; + int rx_fc[8]; + int (*connect)(struct fe_priv *priv); + void (*disconnect)(struct fe_priv *priv); + void (*start)(struct fe_priv *priv); + void (*stop)(struct fe_priv *priv); +}; + +struct fe_soc_data { + const u16 *reg_table; + + void (*init_data)(struct fe_soc_data *data, struct net_device *netdev); + void (*reset_fe)(void); + void (*set_mac)(struct fe_priv *priv, unsigned char *mac); + int (*fwd_config)(struct fe_priv *priv); + void (*tx_dma)(struct fe_tx_dma *txd); + int (*switch_init)(struct fe_priv *priv); + int (*switch_config)(struct fe_priv *priv); + void (*port_init)(struct fe_priv *priv, struct device_node *port); + int (*has_carrier)(struct fe_priv *priv); + int (*mdio_init)(struct fe_priv *priv); + void (*mdio_cleanup)(struct fe_priv *priv); + int (*mdio_write)(struct mii_bus *bus, int phy_addr, int phy_reg, + u16 val); + int (*mdio_read)(struct mii_bus *bus, int phy_addr, int phy_reg); + void (*mdio_adjust_link)(struct fe_priv *priv, int port); + + void *swpriv; + u32 pdma_glo_cfg; + u32 rx_int; + u32 tx_int; + u32 status_int; + u32 checksum_bit; +}; + +#define FE_FLAG_PADDING_64B BIT(0) +#define FE_FLAG_PADDING_BUG BIT(1) +#define FE_FLAG_JUMBO_FRAME BIT(2) +#define FE_FLAG_RX_2B_OFFSET BIT(3) +#define FE_FLAG_RX_SG_DMA BIT(4) +#define FE_FLAG_RX_VLAN_CTAG BIT(5) +#define FE_FLAG_NAPI_WEIGHT BIT(6) +#define FE_FLAG_CALIBRATE_CLK BIT(7) +#define FE_FLAG_HAS_SWITCH BIT(8) + +#define FE_STAT_REG_DECLARE \ + _FE(tx_bytes) \ + _FE(tx_packets) \ + _FE(tx_skip) \ + _FE(tx_collisions) \ + _FE(rx_bytes) \ + _FE(rx_packets) \ + _FE(rx_overflow) \ + _FE(rx_fcs_errors) \ + _FE(rx_short_errors) \ + _FE(rx_long_errors) \ + _FE(rx_checksum_errors) \ + _FE(rx_flow_control_packets) + +struct fe_hw_stats { + /* make sure that stats operations are atomic */ + spinlock_t stats_lock; + + struct u64_stats_sync syncp; +#define _FE(x) u64 x; + FE_STAT_REG_DECLARE +#undef _FE +}; + +enum fe_tx_flags { + FE_TX_FLAGS_SINGLE0 = 0x01, + FE_TX_FLAGS_PAGE0 = 0x02, + FE_TX_FLAGS_PAGE1 = 0x04, +}; + +struct fe_tx_buf { + struct sk_buff *skb; + u32 flags; + DEFINE_DMA_UNMAP_ADDR(dma_addr0); + DEFINE_DMA_UNMAP_LEN(dma_len0); + DEFINE_DMA_UNMAP_ADDR(dma_addr1); + DEFINE_DMA_UNMAP_LEN(dma_len1); +}; + +struct fe_tx_ring { + struct fe_tx_dma *tx_dma; + struct fe_tx_buf *tx_buf; + dma_addr_t tx_phys; + u16 tx_ring_size; + u16 tx_free_idx; + u16 tx_next_idx; + u16 tx_thresh; +}; + +struct fe_rx_ring { + struct fe_rx_dma *rx_dma; + u8 **rx_data; + dma_addr_t rx_phys; + u16 rx_ring_size; + u16 frag_size; + u16 rx_buf_size; + u16 rx_calc_idx; +}; + +struct fe_priv { + /* make sure that register operations are atomic */ + spinlock_t page_lock; + + struct fe_soc_data *soc; + struct net_device *netdev; + struct device_node *switch_np; + u32 msg_enable; + u32 flags; + + struct device *dev; + unsigned long sysclk; + + struct fe_rx_ring rx_ring; + struct napi_struct rx_napi; + + struct fe_tx_ring tx_ring; + + struct fe_phy *phy; + struct mii_bus *mii_bus; + struct phy_device *phy_dev; + u32 phy_flags; + + int link[8]; + + struct fe_hw_stats *hw_stats; + unsigned long vlan_map; + struct work_struct pending_work; + DECLARE_BITMAP(pending_flags, FE_FLAG_MAX); + + struct reset_control *rst_ppe; + struct mtk_foe_entry *foe_table; + dma_addr_t foe_table_phys; + struct flow_offload __rcu **foe_flow_table; +}; + +extern const struct of_device_id of_fe_match[]; + +void fe_w32(u32 val, unsigned reg); +void fe_m32(struct fe_priv *priv, u32 clear, u32 set, unsigned reg); +u32 fe_r32(unsigned reg); + +int fe_set_clock_cycle(struct fe_priv *priv); +void fe_csum_config(struct fe_priv *priv); +void fe_stats_update(struct fe_priv *priv); +void fe_fwd_config(struct fe_priv *priv); +void fe_reg_w32(u32 val, enum fe_reg reg); +u32 fe_reg_r32(enum fe_reg reg); + +void fe_reset(u32 reset_bits); + +static inline void *priv_netdev(struct fe_priv *priv) +{ + return (char *)priv - ALIGN(sizeof(struct net_device), NETDEV_ALIGN); +} + +int mtk_ppe_probe(struct fe_priv *eth); +void mtk_ppe_remove(struct fe_priv *eth); +int mtk_flow_offload(struct fe_priv *eth, + enum flow_offload_type type, + struct flow_offload *flow, + struct flow_offload_hw_path *src, + struct flow_offload_hw_path *dest); +int mtk_offload_check_rx(struct fe_priv *eth, struct sk_buff *skb, u32 rxd4); + + +#endif /* FE_ETH_H */ diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_offload.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_offload.c new file mode 100644 index 000000000..3001c081f --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_offload.c @@ -0,0 +1,526 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2018 John Crispin + */ + +#include "mtk_offload.h" + +#define INVALID 0 +#define UNBIND 1 +#define BIND 2 +#define FIN 3 + +#define IPV4_HNAPT 0 +#define IPV4_HNAT 1 + +static u32 +mtk_flow_hash_v4(struct flow_offload_tuple *tuple) +{ + u32 ports = ntohs(tuple->src_port) << 16 | ntohs(tuple->dst_port); + u32 src = ntohl(tuple->dst_v4.s_addr); + u32 dst = ntohl(tuple->src_v4.s_addr); + u32 hash = (ports & src) | ((~ports) & dst); + u32 hash_23_0 = hash & 0xffffff; + u32 hash_31_24 = hash & 0xff000000; + + hash = ports ^ src ^ dst ^ ((hash_23_0 << 8) | (hash_31_24 >> 24)); + hash = ((hash & 0xffff0000) >> 16 ) ^ (hash & 0xfffff); + hash &= 0x7ff; + hash *= 2;; + + return hash; +} + +static int +mtk_foe_prepare_v4(struct mtk_foe_entry *entry, + struct flow_offload_tuple *tuple, + struct flow_offload_tuple *dest_tuple, + struct flow_offload_hw_path *src, + struct flow_offload_hw_path *dest) +{ + int is_mcast = !!is_multicast_ether_addr(dest->eth_dest); + + if (tuple->l4proto == IPPROTO_UDP) + entry->ipv4_hnapt.bfib1.udp = 1; + + entry->ipv4_hnapt.etype = htons(ETH_P_IP); + entry->ipv4_hnapt.bfib1.pkt_type = IPV4_HNAPT; + entry->ipv4_hnapt.iblk2.fqos = 0; + entry->ipv4_hnapt.bfib1.ttl = 1; + entry->ipv4_hnapt.bfib1.cah = 1; + entry->ipv4_hnapt.bfib1.ka = 1; + entry->ipv4_hnapt.iblk2.mcast = is_mcast; + entry->ipv4_hnapt.iblk2.dscp = 0; + entry->ipv4_hnapt.iblk2.port_mg = 0x3f; + entry->ipv4_hnapt.iblk2.port_ag = 0x1f; +#ifdef CONFIG_NET_MEDIATEK_HW_QOS + entry->ipv4_hnapt.iblk2.qid = 1; + entry->ipv4_hnapt.iblk2.fqos = 1; +#endif +#ifdef CONFIG_RALINK + entry->ipv4_hnapt.iblk2.dp = 1; + if ((dest->flags & FLOW_OFFLOAD_PATH_VLAN) && (dest->vlan_id > 1)) + entry->ipv4_hnapt.iblk2.qid += 8; +#else + entry->ipv4_hnapt.iblk2.dp = (dest->dev->name[3] - '0') + 1; +#endif + + entry->ipv4_hnapt.sip = ntohl(tuple->src_v4.s_addr); + entry->ipv4_hnapt.dip = ntohl(tuple->dst_v4.s_addr); + entry->ipv4_hnapt.sport = ntohs(tuple->src_port); + entry->ipv4_hnapt.dport = ntohs(tuple->dst_port); + + entry->ipv4_hnapt.new_sip = ntohl(dest_tuple->dst_v4.s_addr); + entry->ipv4_hnapt.new_dip = ntohl(dest_tuple->src_v4.s_addr); + entry->ipv4_hnapt.new_sport = ntohs(dest_tuple->dst_port); + entry->ipv4_hnapt.new_dport = ntohs(dest_tuple->src_port); + + entry->bfib1.state = BIND; + + if (dest->flags & FLOW_OFFLOAD_PATH_PPPOE) { + entry->bfib1.psn = 1; + entry->ipv4_hnapt.etype = htons(ETH_P_PPP_SES); + entry->ipv4_hnapt.pppoe_id = dest->pppoe_sid; + } + + if (dest->flags & FLOW_OFFLOAD_PATH_VLAN) { + entry->ipv4_hnapt.vlan1 = dest->vlan_id; + entry->bfib1.vlan_layer = 1; + + switch (dest->vlan_proto) { + case htons(ETH_P_8021Q): + entry->ipv4_hnapt.bfib1.vpm = 1; + break; + case htons(ETH_P_8021AD): + entry->ipv4_hnapt.bfib1.vpm = 2; + break; + default: + return -EINVAL; + } + } + + return 0; +} + +static void +mtk_foe_set_mac(struct mtk_foe_entry *entry, u8 *smac, u8 *dmac) +{ + entry->ipv4_hnapt.dmac_hi = swab32(*((u32*) dmac)); + entry->ipv4_hnapt.dmac_lo = swab16(*((u16*) &dmac[4])); + entry->ipv4_hnapt.smac_hi = swab32(*((u32*) smac)); + entry->ipv4_hnapt.smac_lo = swab16(*((u16*) &smac[4])); +} + +static void +mtk_foe_write(struct mtk_eth *eth, u32 hash, + struct mtk_foe_entry *entry) +{ + struct mtk_foe_entry *table = (struct mtk_foe_entry *)eth->foe_table; + + memcpy(&table[hash], entry, sizeof(*entry)); +} + +int mtk_flow_offload(struct mtk_eth *eth, + enum flow_offload_type type, + struct flow_offload *flow, + struct flow_offload_hw_path *src, + struct flow_offload_hw_path *dest) +{ + struct flow_offload_tuple *otuple = &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple; + struct flow_offload_tuple *rtuple = &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple; + u32 time_stamp = mtk_r32(eth, 0x0010) & (0x7fff); + u32 ohash, rhash; + struct mtk_foe_entry orig = { + .bfib1.time_stamp = time_stamp, + .bfib1.psn = 0, + }; + struct mtk_foe_entry reply = { + .bfib1.time_stamp = time_stamp, + .bfib1.psn = 0, + }; + + if (otuple->l4proto != IPPROTO_TCP && otuple->l4proto != IPPROTO_UDP) + return -EINVAL; + + switch (otuple->l3proto) { + case AF_INET: + if (mtk_foe_prepare_v4(&orig, otuple, rtuple, src, dest) || + mtk_foe_prepare_v4(&reply, rtuple, otuple, dest, src)) + return -EINVAL; + + ohash = mtk_flow_hash_v4(otuple); + rhash = mtk_flow_hash_v4(rtuple); + break; + + case AF_INET6: + return -EINVAL; + + default: + return -EINVAL; + } + + if (type == FLOW_OFFLOAD_DEL) { + orig.bfib1.state = INVALID; + reply.bfib1.state = INVALID; + flow = NULL; + goto write; + } + + mtk_foe_set_mac(&orig, dest->eth_src, dest->eth_dest); + mtk_foe_set_mac(&reply, src->eth_src, src->eth_dest); + +write: + mtk_foe_write(eth, ohash, &orig); + mtk_foe_write(eth, rhash, &reply); + rcu_assign_pointer(eth->foe_flow_table[ohash], flow); + rcu_assign_pointer(eth->foe_flow_table[rhash], flow); + + if (type == FLOW_OFFLOAD_DEL) + synchronize_rcu(); + + return 0; +} + +#ifdef CONFIG_NET_MEDIATEK_HW_QOS + +#define QDMA_TX_SCH_TX 0x1a14 + +static void mtk_ppe_scheduler(struct mtk_eth *eth, int id, u32 rate) +{ + int exp = 0, shift = 0; + u32 reg = mtk_r32(eth, QDMA_TX_SCH_TX); + u32 val = 0; + + if (rate) + val = BIT(11); + + while (rate > 127) { + rate /= 10; + exp++; + } + + val |= (rate & 0x7f) << 4; + val |= exp & 0xf; + if (id) + shift = 16; + reg &= ~(0xffff << shift); + reg |= val << shift; + mtk_w32(eth, val, QDMA_TX_SCH_TX); +} + +#define QTX_CFG(x) (0x1800 + (x * 0x10)) +#define QTX_SCH(x) (0x1804 + (x * 0x10)) + +static void mtk_ppe_queue(struct mtk_eth *eth, int id, int sched, int weight, int resv, u32 min_rate, u32 max_rate) +{ + int max_exp = 0, min_exp = 0; + u32 reg; + + if (id >= 16) + return; + + reg = mtk_r32(eth, QTX_SCH(id)); + reg &= 0x70000000; + + if (sched) + reg |= BIT(31); + + if (min_rate) + reg |= BIT(27); + + if (max_rate) + reg |= BIT(11); + + while (max_rate > 127) { + max_rate /= 10; + max_exp++; + } + + while (min_rate > 127) { + min_rate /= 10; + min_exp++; + } + + reg |= (min_rate & 0x7f) << 20; + reg |= (min_exp & 0xf) << 16; + reg |= (weight & 0xf) << 12; + reg |= (max_rate & 0x7f) << 4; + reg |= max_exp & 0xf; + mtk_w32(eth, reg, QTX_SCH(id)); + + resv &= 0xff; + reg = mtk_r32(eth, QTX_CFG(id)); + reg &= 0xffff0000; + reg |= (resv << 8) | resv; + mtk_w32(eth, reg, QTX_CFG(id)); +} +#endif + +static int mtk_init_foe_table(struct mtk_eth *eth) +{ + if (eth->foe_table) + return 0; + + eth->foe_flow_table = devm_kcalloc(eth->dev, MTK_PPE_ENTRY_CNT, + sizeof(*eth->foe_flow_table), + GFP_KERNEL); + if (!eth->foe_flow_table) + return -EINVAL; + + /* map the FOE table */ + eth->foe_table = dmam_alloc_coherent(eth->dev, MTK_PPE_TBL_SZ, + ð->foe_table_phys, GFP_KERNEL); + if (!eth->foe_table) { + dev_err(eth->dev, "failed to allocate foe table\n"); + kfree(eth->foe_flow_table); + return -ENOMEM; + } + + + return 0; +} + +static int mtk_ppe_start(struct mtk_eth *eth) +{ + int ret; + + ret = mtk_init_foe_table(eth); + if (ret) + return ret; + + /* tell the PPE about the tables base address */ + mtk_w32(eth, eth->foe_table_phys, MTK_REG_PPE_TB_BASE); + + /* flush the table */ + memset(eth->foe_table, 0, MTK_PPE_TBL_SZ); + + /* setup hashing */ + mtk_m32(eth, + MTK_PPE_TB_CFG_HASH_MODE_MASK | MTK_PPE_TB_CFG_TBL_SZ_MASK, + MTK_PPE_TB_CFG_HASH_MODE1 | MTK_PPE_TB_CFG_TBL_SZ_4K, + MTK_REG_PPE_TB_CFG); + + /* set the default hashing seed */ + mtk_w32(eth, MTK_PPE_HASH_SEED, MTK_REG_PPE_HASH_SEED); + + /* each foe entry is 64bytes and is setup by cpu forwarding*/ + mtk_m32(eth, MTK_PPE_CAH_CTRL_X_MODE | MTK_PPE_TB_CFG_ENTRY_SZ_MASK | + MTK_PPE_TB_CFG_SMA_MASK, + MTK_PPE_TB_CFG_ENTRY_SZ_64B | MTK_PPE_TB_CFG_SMA_FWD_CPU, + MTK_REG_PPE_TB_CFG); + + /* set ip proto */ + mtk_w32(eth, 0xFFFFFFFF, MTK_REG_PPE_IP_PROT_CHK); + + /* setup caching */ + mtk_m32(eth, 0, MTK_PPE_CAH_CTRL_X_MODE, MTK_REG_PPE_CAH_CTRL); + mtk_m32(eth, MTK_PPE_CAH_CTRL_X_MODE, MTK_PPE_CAH_CTRL_EN, + MTK_REG_PPE_CAH_CTRL); + + /* enable FOE */ + mtk_m32(eth, 0, MTK_PPE_FLOW_CFG_IPV4_NAT_FRAG_EN | + MTK_PPE_FLOW_CFG_IPV4_NAPT_EN | MTK_PPE_FLOW_CFG_IPV4_NAT_EN | + MTK_PPE_FLOW_CFG_IPV4_GREK_EN, + MTK_REG_PPE_FLOW_CFG); + + /* setup flow entry un/bind aging */ + mtk_m32(eth, 0, + MTK_PPE_TB_CFG_UNBD_AGE | MTK_PPE_TB_CFG_NTU_AGE | + MTK_PPE_TB_CFG_FIN_AGE | MTK_PPE_TB_CFG_UDP_AGE | + MTK_PPE_TB_CFG_TCP_AGE, + MTK_REG_PPE_TB_CFG); + + mtk_m32(eth, MTK_PPE_UNB_AGE_MNP_MASK | MTK_PPE_UNB_AGE_DLTA_MASK, + MTK_PPE_UNB_AGE_MNP | MTK_PPE_UNB_AGE_DLTA, + MTK_REG_PPE_UNB_AGE); + mtk_m32(eth, MTK_PPE_BND_AGE0_NTU_DLTA_MASK | + MTK_PPE_BND_AGE0_UDP_DLTA_MASK, + MTK_PPE_BND_AGE0_NTU_DLTA | MTK_PPE_BND_AGE0_UDP_DLTA, + MTK_REG_PPE_BND_AGE0); + mtk_m32(eth, MTK_PPE_BND_AGE1_FIN_DLTA_MASK | + MTK_PPE_BND_AGE1_TCP_DLTA_MASK, + MTK_PPE_BND_AGE1_FIN_DLTA | MTK_PPE_BND_AGE1_TCP_DLTA, + MTK_REG_PPE_BND_AGE1); + + /* setup flow entry keep alive */ + mtk_m32(eth, MTK_PPE_TB_CFG_KA_MASK, MTK_PPE_TB_CFG_KA, + MTK_REG_PPE_TB_CFG); + mtk_w32(eth, MTK_PPE_KA_UDP | MTK_PPE_KA_TCP | MTK_PPE_KA_T, MTK_REG_PPE_KA); + + /* setup flow entry rate limit */ + mtk_w32(eth, (0x3fff << 16) | 0x3fff, MTK_REG_PPE_BIND_LMT_0); + mtk_w32(eth, MTK_PPE_NTU_KA | 0x3fff, MTK_REG_PPE_BIND_LMT_1); + mtk_m32(eth, MTK_PPE_BNDR_RATE_MASK, 1, MTK_REG_PPE_BNDR); + + /* enable the PPE */ + mtk_m32(eth, 0, MTK_PPE_GLO_CFG_EN, MTK_REG_PPE_GLO_CFG); + +#ifdef CONFIG_RALINK + /* set the default forwarding port to QDMA */ + mtk_w32(eth, 0x0, MTK_REG_PPE_DFT_CPORT); +#else + /* set the default forwarding port to QDMA */ + mtk_w32(eth, 0x55555555, MTK_REG_PPE_DFT_CPORT); +#endif + + /* drop packets with TTL=0 */ + mtk_m32(eth, 0, MTK_PPE_GLO_CFG_TTL0_DROP, MTK_REG_PPE_GLO_CFG); + + /* send all traffic from gmac to the ppe */ + mtk_m32(eth, 0xffff, 0x4444, MTK_GDMA_FWD_CFG(0)); + mtk_m32(eth, 0xffff, 0x4444, MTK_GDMA_FWD_CFG(1)); + + dev_info(eth->dev, "PPE started\n"); + +#ifdef CONFIG_NET_MEDIATEK_HW_QOS + mtk_ppe_scheduler(eth, 0, 500000); + mtk_ppe_scheduler(eth, 1, 500000); + mtk_ppe_queue(eth, 0, 0, 7, 32, 250000, 0); + mtk_ppe_queue(eth, 1, 0, 7, 32, 250000, 0); + mtk_ppe_queue(eth, 8, 1, 7, 32, 250000, 0); + mtk_ppe_queue(eth, 9, 1, 7, 32, 250000, 0); +#endif + + return 0; +} + +static int mtk_ppe_busy_wait(struct mtk_eth *eth) +{ + unsigned long t_start = jiffies; + u32 r = 0; + + while (1) { + r = mtk_r32(eth, MTK_REG_PPE_GLO_CFG); + if (!(r & MTK_PPE_GLO_CFG_BUSY)) + return 0; + if (time_after(jiffies, t_start + HZ)) + break; + usleep_range(10, 20); + } + + dev_err(eth->dev, "ppe: table busy timeout - resetting\n"); + reset_control_reset(eth->rst_ppe); + + return -ETIMEDOUT; +} + +static int mtk_ppe_stop(struct mtk_eth *eth) +{ + u32 r1 = 0, r2 = 0; + int i; + + /* discard all traffic while we disable the PPE */ + mtk_m32(eth, 0xffff, 0x7777, MTK_GDMA_FWD_CFG(0)); + mtk_m32(eth, 0xffff, 0x7777, MTK_GDMA_FWD_CFG(1)); + + if (mtk_ppe_busy_wait(eth)) + return -ETIMEDOUT; + + /* invalidate all flow table entries */ + for (i = 0; i < MTK_PPE_ENTRY_CNT; i++) + eth->foe_table[i].bfib1.state = FOE_STATE_INVALID; + + /* disable caching */ + mtk_m32(eth, 0, MTK_PPE_CAH_CTRL_X_MODE, MTK_REG_PPE_CAH_CTRL); + mtk_m32(eth, MTK_PPE_CAH_CTRL_X_MODE | MTK_PPE_CAH_CTRL_EN, 0, + MTK_REG_PPE_CAH_CTRL); + + /* flush cache has to be ahead of hnat diable --*/ + mtk_m32(eth, MTK_PPE_GLO_CFG_EN, 0, MTK_REG_PPE_GLO_CFG); + + /* disable FOE */ + mtk_m32(eth, + MTK_PPE_FLOW_CFG_IPV4_NAT_FRAG_EN | + MTK_PPE_FLOW_CFG_IPV4_NAPT_EN | MTK_PPE_FLOW_CFG_IPV4_NAT_EN | + MTK_PPE_FLOW_CFG_FUC_FOE | MTK_PPE_FLOW_CFG_FMC_FOE, + 0, MTK_REG_PPE_FLOW_CFG); + + /* disable FOE aging */ + mtk_m32(eth, 0, + MTK_PPE_TB_CFG_FIN_AGE | MTK_PPE_TB_CFG_UDP_AGE | + MTK_PPE_TB_CFG_TCP_AGE | MTK_PPE_TB_CFG_UNBD_AGE | + MTK_PPE_TB_CFG_NTU_AGE, MTK_REG_PPE_TB_CFG); + + r1 = mtk_r32(eth, 0x100); + r2 = mtk_r32(eth, 0x10c); + + dev_info(eth->dev, "0x100 = 0x%x, 0x10c = 0x%x\n", r1, r2); + + if (((r1 & 0xff00) >> 0x8) >= (r1 & 0xff) || + ((r1 & 0xff00) >> 0x8) >= (r2 & 0xff)) { + dev_info(eth->dev, "reset pse\n"); + mtk_w32(eth, 0x1, 0x4); + } + + /* set the foe entry base address to 0 */ + mtk_w32(eth, 0, MTK_REG_PPE_TB_BASE); + + if (mtk_ppe_busy_wait(eth)) + return -ETIMEDOUT; + + /* send all traffic back to the DMA engine */ +#ifdef CONFIG_RALINK + mtk_m32(eth, 0xffff, 0x0, MTK_GDMA_FWD_CFG(0)); + mtk_m32(eth, 0xffff, 0x0, MTK_GDMA_FWD_CFG(1)); +#else + mtk_m32(eth, 0xffff, 0x5555, MTK_GDMA_FWD_CFG(0)); + mtk_m32(eth, 0xffff, 0x5555, MTK_GDMA_FWD_CFG(1)); +#endif + return 0; +} + +static void mtk_offload_keepalive(struct fe_priv *eth, unsigned int hash) +{ + struct flow_offload *flow; + + rcu_read_lock(); + flow = rcu_dereference(eth->foe_flow_table[hash]); + if (flow) + flow->timeout = jiffies + 30 * HZ; + rcu_read_unlock(); +} + +int mtk_offload_check_rx(struct fe_priv *eth, struct sk_buff *skb, u32 rxd4) +{ + unsigned int hash; + + switch (FIELD_GET(MTK_RXD4_CPU_REASON, rxd4)) { + case MTK_CPU_REASON_KEEPALIVE_UC_OLD_HDR: + case MTK_CPU_REASON_KEEPALIVE_MC_NEW_HDR: + case MTK_CPU_REASON_KEEPALIVE_DUP_OLD_HDR: + hash = FIELD_GET(MTK_RXD4_FOE_ENTRY, rxd4); + mtk_offload_keepalive(eth, hash); + return -1; + case MTK_CPU_REASON_PACKET_SAMPLING: + return -1; + default: + return 0; + } +} + +int mtk_ppe_probe(struct mtk_eth *eth) +{ + int err; + + err = mtk_ppe_start(eth); + if (err) + return err; + + err = mtk_ppe_debugfs_init(eth); + if (err) + return err; + + return 0; +} + +void mtk_ppe_remove(struct mtk_eth *eth) +{ + mtk_ppe_stop(eth); +} diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_offload.h b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_offload.h new file mode 100644 index 000000000..f714c90f9 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_offload.h @@ -0,0 +1,260 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2014-2016 Sean Wang + * Copyright (C) 2016-2017 John Crispin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mtk_eth_soc.h" + +#ifdef CONFIG_RALINK +/* ramips compat */ +#define mtk_eth fe_priv +#define MTK_GDMA_FWD_CFG(x) (0x500 + (x * 0x1000)) +#define mtk_m32 fe_m32 + +static inline u32 +mtk_r32(struct mtk_eth *eth, u32 reg) +{ + return fe_r32(reg); +} + +static inline void +mtk_w32(struct mtk_eth *eth, u32 val, u32 reg) +{ + fe_w32(val, reg); +} +#endif + +#define MTK_REG_PPE_GLO_CFG 0xe00 +#define MTK_PPE_GLO_CFG_BUSY BIT(31) +#define MTK_PPE_GLO_CFG_TTL0_DROP BIT(4) +#define MTK_PPE_GLO_CFG_EN BIT(0) + +#define MTK_REG_PPE_FLOW_CFG 0xe04 +#define MTK_PPE_FLOW_CFG_IPV4_GREK_EN BIT(19) +#define MTK_PPE_FLOW_CFG_IPV4_NAT_FRAG_EN BIT(17) +#define MTK_PPE_FLOW_CFG_IPV4_NAPT_EN BIT(13) +#define MTK_PPE_FLOW_CFG_IPV4_NAT_EN BIT(12) +#define MTK_PPE_FLOW_CFG_FUC_FOE BIT(2) +#define MTK_PPE_FLOW_CFG_FMC_FOE BIT(1) + +#define MTK_REG_PPE_IP_PROT_CHK 0xe08 + +#define MTK_REG_PPE_TB_BASE 0xe20 + +#define MTK_REG_PPE_BNDR 0xe28 +#define MTK_PPE_BNDR_RATE_MASK 0xffff + +#define MTK_REG_PPE_BIND_LMT_0 0xe2C + +#define MTK_REG_PPE_BIND_LMT_1 0xe30 +#define MTK_PPE_NTU_KA BIT(16) + +#define MTK_REG_PPE_KA 0xe34 +#define MTK_PPE_KA_T BIT(0) +#define MTK_PPE_KA_TCP BIT(16) +#define MTK_PPE_KA_UDP BIT(24) + +#define MTK_REG_PPE_UNB_AGE 0xe38 +#define MTK_PPE_UNB_AGE_MNP_MASK (0xffff << 16) +#define MTK_PPE_UNB_AGE_MNP (1000 << 16) +#define MTK_PPE_UNB_AGE_DLTA_MASK 0xff +#define MTK_PPE_UNB_AGE_DLTA 3 + +#define MTK_REG_PPE_BND_AGE0 0xe3c +#define MTK_PPE_BND_AGE0_NTU_DLTA_MASK (0xffff << 16) +#define MTK_PPE_BND_AGE0_NTU_DLTA (5 << 16) +#define MTK_PPE_BND_AGE0_UDP_DLTA_MASK 0xffff +#define MTK_PPE_BND_AGE0_UDP_DLTA 5 + +#define MTK_REG_PPE_BND_AGE1 0xe40 +#define MTK_PPE_BND_AGE1_FIN_DLTA_MASK (0xffff << 16) +#define MTK_PPE_BND_AGE1_FIN_DLTA (5 << 16) +#define MTK_PPE_BND_AGE1_TCP_DLTA_MASK 0xffff +#define MTK_PPE_BND_AGE1_TCP_DLTA 5 + +#define MTK_REG_PPE_DFT_CPORT 0xe48 + +#define MTK_REG_PPE_TB_CFG 0xe1c +#define MTK_PPE_TB_CFG_X_MODE_MASK (3 << 18) +#define MTK_PPE_TB_CFG_HASH_MODE1 BIT(14) +#define MTK_PPE_TB_CFG_HASH_MODE_MASK (0x3 << 14) +#define MTK_PPE_TB_CFG_KA (3 << 12) +#define MTK_PPE_TB_CFG_KA_MASK (0x3 << 12) +#define MTK_PPE_TB_CFG_FIN_AGE BIT(11) +#define MTK_PPE_TB_CFG_UDP_AGE BIT(10) +#define MTK_PPE_TB_CFG_TCP_AGE BIT(9) +#define MTK_PPE_TB_CFG_UNBD_AGE BIT(8) +#define MTK_PPE_TB_CFG_NTU_AGE BIT(7) +#define MTK_PPE_TB_CFG_SMA_FWD_CPU (0x3 << 4) +#define MTK_PPE_TB_CFG_SMA_MASK (0x3 << 4) +#define MTK_PPE_TB_CFG_ENTRY_SZ_64B 0 +#define MTK_PPE_TB_CFG_ENTRY_SZ_MASK BIT(3) +#define MTK_PPE_TB_CFG_TBL_SZ_4K 2 +#define MTK_PPE_TB_CFG_TBL_SZ_MASK 0x7 + +#define MTK_REG_PPE_HASH_SEED 0xe44 +#define MTK_PPE_HASH_SEED 0x12345678 + + +#define MTK_REG_PPE_CAH_CTRL 0xf20 +#define MTK_PPE_CAH_CTRL_X_MODE BIT(9) +#define MTK_PPE_CAH_CTRL_EN BIT(0) + +struct mtk_foe_unbind_info_blk { + u32 time_stamp:8; + u32 pcnt:16; /* packet count */ + u32 preb:1; + u32 pkt_type:3; + u32 state:2; + u32 udp:1; + u32 sta:1; /* static entry */ +} __attribute__ ((packed)); + +struct mtk_foe_bind_info_blk { + u32 time_stamp:15; + u32 ka:1; /* keep alive */ + u32 vlan_layer:3; + u32 psn:1; /* egress packet has PPPoE session */ +#ifdef CONFIG_RALINK + u32 vpm:2; /* 0:ethertype remark, 1:0x8100(CR default) */ +#else + u32 vpm:1; /* 0:ethertype remark, 1:0x8100(CR default) */ + u32 ps:1; /* packet sampling */ +#endif + u32 cah:1; /* cacheable flag */ + u32 rmt:1; /* remove tunnel ip header (6rd/dslite only) */ + u32 ttl:1; + u32 pkt_type:3; + u32 state:2; + u32 udp:1; + u32 sta:1; /* static entry */ +} __attribute__ ((packed)); + +struct mtk_foe_info_blk2 { + u32 qid:4; /* QID in Qos Port */ + u32 fqos:1; /* force to PSE QoS port */ + u32 dp:3; /* force to PSE port x + 0:PSE,1:GSW, 2:GMAC,4:PPE,5:QDMA,7=DROP */ + u32 mcast:1; /* multicast this packet to CPU */ + u32 pcpl:1; /* OSBN */ + u32 mlen:1; /* 0:post 1:pre packet length in meter */ + u32 alen:1; /* 0:post 1:pre packet length in accounting */ + u32 port_mg:6; /* port meter group */ + u32 port_ag:6; /* port account group */ + u32 dscp:8; /* DSCP value */ +} __attribute__ ((packed)); + +struct mtk_foe_ipv4_hnapt { + union { + struct mtk_foe_bind_info_blk bfib1; + struct mtk_foe_unbind_info_blk udib1; + u32 info_blk1; + }; + u32 sip; + u32 dip; + u16 dport; + u16 sport; + union { + struct mtk_foe_info_blk2 iblk2; + u32 info_blk2; + }; + u32 new_sip; + u32 new_dip; + u16 new_dport; + u16 new_sport; + u32 resv1; + u32 resv2; + u32 resv3:26; + u32 act_dp:6; /* UDF */ + u16 vlan1; + u16 etype; + u32 dmac_hi; + u16 vlan2; + u16 dmac_lo; + u32 smac_hi; + u16 pppoe_id; + u16 smac_lo; +} __attribute__ ((packed)); + +struct mtk_foe_entry { + union { + struct mtk_foe_unbind_info_blk udib1; + struct mtk_foe_bind_info_blk bfib1; + struct mtk_foe_ipv4_hnapt ipv4_hnapt; + }; +}; + +enum mtk_foe_entry_state { + FOE_STATE_INVALID = 0, + FOE_STATE_UNBIND = 1, + FOE_STATE_BIND = 2, + FOE_STATE_FIN = 3 +}; + + +#define MTK_RXD4_FOE_ENTRY GENMASK(13, 0) +#define MTK_RXD4_CPU_REASON GENMASK(18, 14) +#define MTK_RXD4_SRC_PORT GENMASK(21, 19) +#define MTK_RXD4_ALG GENMASK(31, 22) + +enum mtk_foe_cpu_reason { + MTK_CPU_REASON_TTL_EXCEEDED = 0x02, + MTK_CPU_REASON_OPTION_HEADER = 0x03, + MTK_CPU_REASON_NO_FLOW = 0x07, + MTK_CPU_REASON_IPV4_FRAG = 0x08, + MTK_CPU_REASON_IPV4_DSLITE_FRAG = 0x09, + MTK_CPU_REASON_IPV4_DSLITE_NO_TCP_UDP = 0x0a, + MTK_CPU_REASON_IPV6_6RD_NO_TCP_UDP = 0x0b, + MTK_CPU_REASON_TCP_FIN_SYN_RST = 0x0c, + MTK_CPU_REASON_UN_HIT = 0x0d, + MTK_CPU_REASON_HIT_UNBIND = 0x0e, + MTK_CPU_REASON_HIT_UNBIND_RATE_REACHED = 0x0f, + MTK_CPU_REASON_HIT_BIND_TCP_FIN = 0x10, + MTK_CPU_REASON_HIT_TTL_1 = 0x11, + MTK_CPU_REASON_HIT_BIND_VLAN_VIOLATION = 0x12, + MTK_CPU_REASON_KEEPALIVE_UC_OLD_HDR = 0x13, + MTK_CPU_REASON_KEEPALIVE_MC_NEW_HDR = 0x14, + MTK_CPU_REASON_KEEPALIVE_DUP_OLD_HDR = 0x15, + MTK_CPU_REASON_HIT_BIND_FORCE_CPU = 0x16, + MTK_CPU_REASON_TUNNEL_OPTION_HEADER = 0x17, + MTK_CPU_REASON_MULTICAST_TO_CPU = 0x18, + MTK_CPU_REASON_MULTICAST_TO_GMAC1_CPU = 0x19, + MTK_CPU_REASON_HIT_PRE_BIND = 0x1a, + MTK_CPU_REASON_PACKET_SAMPLING = 0x1b, + MTK_CPU_REASON_EXCEED_MTU = 0x1c, + MTK_CPU_REASON_PPE_BYPASS = 0x1e, + MTK_CPU_REASON_INVALID = 0x1f, +}; + + +/* our table size is 4K */ +#define MTK_PPE_ENTRY_CNT 0x1000 +#define MTK_PPE_TBL_SZ \ + (MTK_PPE_ENTRY_CNT * sizeof(struct mtk_foe_entry)) + +int mtk_ppe_debugfs_init(struct mtk_eth *eth); + + diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/soc_mt7620.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/soc_mt7620.c new file mode 100644 index 000000000..7f728d142 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/soc_mt7620.c @@ -0,0 +1,335 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#include +#include +#include +#include + +#include + +#include +#include "mtk_eth_soc.h" +#include "gsw_mt7620.h" +#include "mt7530.h" +#include "mdio.h" + +#define MT7620A_CDMA_CSG_CFG 0x400 +#define MT7620_DMA_VID (MT7620A_CDMA_CSG_CFG | 0x30) +#define MT7621_CDMP_IG_CTRL (MT7620A_CDMA_CSG_CFG + 0x00) +#define MT7621_CDMP_EG_CTRL (MT7620A_CDMA_CSG_CFG + 0x04) +#define MT7620A_RESET_FE BIT(21) +#define MT7621_RESET_FE BIT(6) +#define MT7620A_RESET_ESW BIT(23) +#define MT7620_L4_VALID BIT(23) +#define MT7621_L4_VALID BIT(24) + +#define MT7620_TX_DMA_UDF BIT(15) +#define MT7621_TX_DMA_UDF BIT(19) +#define TX_DMA_FP_BMAP ((0xff) << 19) + +#define CDMA_ICS_EN BIT(2) +#define CDMA_UCS_EN BIT(1) +#define CDMA_TCS_EN BIT(0) + +#define GDMA_ICS_EN BIT(22) +#define GDMA_TCS_EN BIT(21) +#define GDMA_UCS_EN BIT(20) + +/* frame engine counters */ +#define MT7620_REG_MIB_OFFSET 0x1000 +#define MT7620_PPE_AC_BCNT0 (MT7620_REG_MIB_OFFSET + 0x00) +#define MT7620_GDM1_TX_GBCNT (MT7620_REG_MIB_OFFSET + 0x300) +#define MT7620_GDM2_TX_GBCNT (MT7620_GDM1_TX_GBCNT + 0x40) + +#define MT7621_REG_MIB_OFFSET 0x2000 +#define MT7621_PPE_AC_BCNT0 (MT7621_REG_MIB_OFFSET + 0x00) +#define MT7621_GDM1_TX_GBCNT (MT7621_REG_MIB_OFFSET + 0x400) +#define MT7621_GDM2_TX_GBCNT (MT7621_GDM1_TX_GBCNT + 0x40) + +#define GSW_REG_GDMA1_MAC_ADRL 0x508 +#define GSW_REG_GDMA1_MAC_ADRH 0x50C + +#define MT7621_FE_RST_GL (FE_FE_OFFSET + 0x04) +#define MT7620_FE_INT_STATUS2 (FE_FE_OFFSET + 0x08) + +/* FE_INT_STATUS reg on mt7620 define CNT_GDM1_AF at BIT(29) + * but after test it should be BIT(13). + */ +#define MT7620_FE_GDM1_AF BIT(13) +#define MT7621_FE_GDM1_AF BIT(28) +#define MT7621_FE_GDM2_AF BIT(29) + +static const u16 mt7620_reg_table[FE_REG_COUNT] = { + [FE_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG, + [FE_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG, + [FE_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG, + [FE_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0, + [FE_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0, + [FE_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0, + [FE_REG_TX_DTX_IDX0] = RT5350_TX_DTX_IDX0, + [FE_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0, + [FE_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0, + [FE_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0, + [FE_REG_RX_DRX_IDX0] = RT5350_RX_DRX_IDX0, + [FE_REG_FE_INT_ENABLE] = RT5350_FE_INT_ENABLE, + [FE_REG_FE_INT_STATUS] = RT5350_FE_INT_STATUS, + [FE_REG_FE_DMA_VID_BASE] = MT7620_DMA_VID, + [FE_REG_FE_COUNTER_BASE] = MT7620_GDM1_TX_GBCNT, + [FE_REG_FE_RST_GL] = MT7621_FE_RST_GL, + [FE_REG_FE_INT_STATUS2] = MT7620_FE_INT_STATUS2, +}; + +static int mt7620_gsw_config(struct fe_priv *priv) +{ + struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; + + /* is the mt7530 internal or external */ + if (priv->mii_bus && mdiobus_get_phy(priv->mii_bus, 0x1f)) { + mt7530_probe(priv->dev, gsw->base, NULL, 0); + mt7530_probe(priv->dev, NULL, priv->mii_bus, 1); + } else { + mt7530_probe(priv->dev, gsw->base, NULL, 1); + } + + return 0; +} + +static void mt7620_set_mac(struct fe_priv *priv, unsigned char *mac) +{ + struct mt7620_gsw *gsw = (struct mt7620_gsw *)priv->soc->swpriv; + unsigned long flags; + + spin_lock_irqsave(&priv->page_lock, flags); + mtk_switch_w32(gsw, (mac[0] << 8) | mac[1], GSW_REG_SMACCR1); + mtk_switch_w32(gsw, (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], + GSW_REG_SMACCR0); + spin_unlock_irqrestore(&priv->page_lock, flags); +} + +static void mt7620_auto_poll(struct mt7620_gsw *gsw) +{ + int phy; + int lsb = -1, msb = 0; + + for_each_set_bit(phy, &gsw->autopoll, 32) { + if (lsb < 0) + lsb = phy; + msb = phy; + } + + if (lsb == msb) + lsb--; + + mtk_switch_w32(gsw, PHY_AN_EN | PHY_PRE_EN | PMY_MDC_CONF(5) | + (msb << 8) | lsb, ESW_PHY_POLLING); +} + +static void mt7620_port_init(struct fe_priv *priv, struct device_node *np) +{ + struct mt7620_gsw *gsw = (struct mt7620_gsw *)priv->soc->swpriv; + const __be32 *_id = of_get_property(np, "reg", NULL); + int phy_mode, size, id; + int shift = 12; + u32 val, mask = 0; + int min = (gsw->port4 == PORT4_EPHY) ? (5) : (4); + + if (!_id || (be32_to_cpu(*_id) < min) || (be32_to_cpu(*_id) > 5)) { + if (_id) + pr_err("%s: invalid port id %d\n", np->name, + be32_to_cpu(*_id)); + else + pr_err("%s: invalid port id\n", np->name); + return; + } + + id = be32_to_cpu(*_id); + + if (id == 4) + shift = 14; + + priv->phy->phy_fixed[id] = of_get_property(np, "mediatek,fixed-link", + &size); + if (priv->phy->phy_fixed[id] && + (size != (4 * sizeof(*priv->phy->phy_fixed[id])))) { + pr_err("%s: invalid fixed link property\n", np->name); + priv->phy->phy_fixed[id] = NULL; + return; + } + + phy_mode = of_get_phy_mode(np); + switch (phy_mode) { + case PHY_INTERFACE_MODE_RGMII: + mask = 0; + break; + case PHY_INTERFACE_MODE_MII: + mask = 1; + break; + case PHY_INTERFACE_MODE_RMII: + mask = 2; + break; + default: + dev_err(priv->dev, "port %d - invalid phy mode\n", id); + return; + } + + priv->phy->phy_node[id] = of_parse_phandle(np, "phy-handle", 0); + if (!priv->phy->phy_node[id] && !priv->phy->phy_fixed[id]) + return; + + val = rt_sysc_r32(SYSC_REG_CFG1); + val &= ~(3 << shift); + val |= mask << shift; + rt_sysc_w32(val, SYSC_REG_CFG1); + + if (priv->phy->phy_fixed[id]) { + const __be32 *link = priv->phy->phy_fixed[id]; + int tx_fc, rx_fc; + u32 val = 0; + + priv->phy->speed[id] = be32_to_cpup(link++); + tx_fc = be32_to_cpup(link++); + rx_fc = be32_to_cpup(link++); + priv->phy->duplex[id] = be32_to_cpup(link++); + priv->link[id] = 1; + + switch (priv->phy->speed[id]) { + case SPEED_10: + val = 0; + break; + case SPEED_100: + val = 1; + break; + case SPEED_1000: + val = 2; + break; + default: + dev_err(priv->dev, "invalid link speed: %d\n", + priv->phy->speed[id]); + priv->phy->phy_fixed[id] = 0; + return; + } + val = PMCR_SPEED(val); + val |= PMCR_LINK | PMCR_BACKPRES | PMCR_BACKOFF | PMCR_RX_EN | + PMCR_TX_EN | PMCR_FORCE | PMCR_MAC_MODE | PMCR_IPG; + if (tx_fc) + val |= PMCR_TX_FC; + if (rx_fc) + val |= PMCR_RX_FC; + if (priv->phy->duplex[id]) + val |= PMCR_DUPLEX; + mtk_switch_w32(gsw, val, GSW_REG_PORT_PMCR(id)); + dev_info(priv->dev, "using fixed link parameters\n"); + return; + } + + if (priv->phy->phy_node[id] && mdiobus_get_phy(priv->mii_bus, id)) { + u32 val = PMCR_BACKPRES | PMCR_BACKOFF | PMCR_RX_EN | + PMCR_TX_EN | PMCR_MAC_MODE | PMCR_IPG; + + mtk_switch_w32(gsw, val, GSW_REG_PORT_PMCR(id)); + fe_connect_phy_node(priv, priv->phy->phy_node[id]); + gsw->autopoll |= BIT(id); + mt7620_auto_poll(gsw); + return; + } +} + +static void mt7620_fe_reset(void) +{ + fe_reset(MT7620A_RESET_FE | MT7620A_RESET_ESW); +} + +static void mt7620_rxcsum_config(bool enable) +{ + if (enable) + fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) | (GDMA_ICS_EN | + GDMA_TCS_EN | GDMA_UCS_EN), + MT7620A_GDMA1_FWD_CFG); + else + fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) & ~(GDMA_ICS_EN | + GDMA_TCS_EN | GDMA_UCS_EN), + MT7620A_GDMA1_FWD_CFG); +} + +static void mt7620_txcsum_config(bool enable) +{ + if (enable) + fe_w32(fe_r32(MT7620A_CDMA_CSG_CFG) | (CDMA_ICS_EN | + CDMA_UCS_EN | CDMA_TCS_EN), + MT7620A_CDMA_CSG_CFG); + else + fe_w32(fe_r32(MT7620A_CDMA_CSG_CFG) & ~(CDMA_ICS_EN | + CDMA_UCS_EN | CDMA_TCS_EN), + MT7620A_CDMA_CSG_CFG); +} + +static int mt7620_fwd_config(struct fe_priv *priv) +{ + struct net_device *dev = priv_netdev(priv); + + fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) & ~7, MT7620A_GDMA1_FWD_CFG); + + mt7620_txcsum_config((dev->features & NETIF_F_IP_CSUM)); + mt7620_rxcsum_config((dev->features & NETIF_F_RXCSUM)); + + return 0; +} + +static void mt7620_tx_dma(struct fe_tx_dma *txd) +{ +} + +static void mt7620_init_data(struct fe_soc_data *data, + struct net_device *netdev) +{ + struct fe_priv *priv = netdev_priv(netdev); + + priv->flags = FE_FLAG_PADDING_64B | FE_FLAG_RX_2B_OFFSET | + FE_FLAG_RX_SG_DMA | FE_FLAG_HAS_SWITCH; + + netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | + NETIF_F_HW_VLAN_CTAG_TX; + if (mt7620_get_eco() >= 5) + netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | + NETIF_F_IPV6_CSUM; +} + +static struct fe_soc_data mt7620_data = { + .init_data = mt7620_init_data, + .reset_fe = mt7620_fe_reset, + .set_mac = mt7620_set_mac, + .fwd_config = mt7620_fwd_config, + .tx_dma = mt7620_tx_dma, + .switch_init = mtk_gsw_init, + .switch_config = mt7620_gsw_config, + .port_init = mt7620_port_init, + .reg_table = mt7620_reg_table, + .pdma_glo_cfg = FE_PDMA_SIZE_16DWORDS, + .rx_int = RT5350_RX_DONE_INT, + .tx_int = RT5350_TX_DONE_INT, + .status_int = MT7620_FE_GDM1_AF, + .checksum_bit = MT7620_L4_VALID, + .has_carrier = mt7620_has_carrier, + .mdio_read = mt7620_mdio_read, + .mdio_write = mt7620_mdio_write, + .mdio_adjust_link = mt7620_mdio_link_adjust, +}; + +const struct of_device_id of_fe_match[] = { + { .compatible = "mediatek,mt7620-eth", .data = &mt7620_data }, + {}, +}; + +MODULE_DEVICE_TABLE(of, of_fe_match); diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/soc_mt7621.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/soc_mt7621.c new file mode 100644 index 000000000..00dd45e01 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/soc_mt7621.c @@ -0,0 +1,185 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#include +#include +#include +#include + +#include + +#include "mtk_eth_soc.h" +#include "gsw_mt7620.h" +#include "mt7530.h" +#include "mdio.h" + +#define MT7620A_CDMA_CSG_CFG 0x400 +#define MT7621_CDMP_IG_CTRL (MT7620A_CDMA_CSG_CFG + 0x00) +#define MT7621_CDMP_EG_CTRL (MT7620A_CDMA_CSG_CFG + 0x04) +#define MT7621_RESET_FE BIT(6) +#define MT7621_L4_VALID BIT(24) + +#define MT7621_TX_DMA_UDF BIT(19) +#define MT7621_TX_DMA_FPORT BIT(25) + +#define CDMA_ICS_EN BIT(2) +#define CDMA_UCS_EN BIT(1) +#define CDMA_TCS_EN BIT(0) + +#define GDMA_ICS_EN BIT(22) +#define GDMA_TCS_EN BIT(21) +#define GDMA_UCS_EN BIT(20) + +/* frame engine counters */ +#define MT7621_REG_MIB_OFFSET 0x2000 +#define MT7621_PPE_AC_BCNT0 (MT7621_REG_MIB_OFFSET + 0x00) +#define MT7621_GDM1_TX_GBCNT (MT7621_REG_MIB_OFFSET + 0x400) +#define MT7621_GDM2_TX_GBCNT (MT7621_GDM1_TX_GBCNT + 0x40) + +#define GSW_REG_GDMA1_MAC_ADRL 0x508 +#define GSW_REG_GDMA1_MAC_ADRH 0x50C + +#define MT7621_FE_RST_GL (FE_FE_OFFSET + 0x04) +#define MT7620_FE_INT_STATUS2 (FE_FE_OFFSET + 0x08) + +/* FE_INT_STATUS reg on mt7620 define CNT_GDM1_AF at BIT(29) + * but after test it should be BIT(13). + */ +#define MT7620_FE_GDM1_AF BIT(13) +#define MT7621_FE_GDM1_AF BIT(28) +#define MT7621_FE_GDM2_AF BIT(29) + +static const u16 mt7621_reg_table[FE_REG_COUNT] = { + [FE_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG, + [FE_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG, + [FE_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG, + [FE_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0, + [FE_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0, + [FE_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0, + [FE_REG_TX_DTX_IDX0] = RT5350_TX_DTX_IDX0, + [FE_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0, + [FE_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0, + [FE_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0, + [FE_REG_RX_DRX_IDX0] = RT5350_RX_DRX_IDX0, + [FE_REG_FE_INT_ENABLE] = RT5350_FE_INT_ENABLE, + [FE_REG_FE_INT_STATUS] = RT5350_FE_INT_STATUS, + [FE_REG_FE_DMA_VID_BASE] = 0, + [FE_REG_FE_COUNTER_BASE] = MT7621_GDM1_TX_GBCNT, + [FE_REG_FE_RST_GL] = MT7621_FE_RST_GL, + [FE_REG_FE_INT_STATUS2] = MT7620_FE_INT_STATUS2, +}; + +static int mt7621_gsw_config(struct fe_priv *priv) +{ + if (priv->mii_bus && mdiobus_get_phy(priv->mii_bus, 0x1f)) + mt7530_probe(priv->dev, NULL, priv->mii_bus, 1); + + return 0; +} + +static void mt7621_fe_reset(void) +{ + fe_reset(MT7621_RESET_FE); +} + +static void mt7621_rxcsum_config(bool enable) +{ + if (enable) + fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) | (GDMA_ICS_EN | + GDMA_TCS_EN | GDMA_UCS_EN), + MT7620A_GDMA1_FWD_CFG); + else + fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) & ~(GDMA_ICS_EN | + GDMA_TCS_EN | GDMA_UCS_EN), + MT7620A_GDMA1_FWD_CFG); +} + +static void mt7621_rxvlan_config(bool enable) +{ + if (enable) + fe_w32(1, MT7621_CDMP_EG_CTRL); + else + fe_w32(0, MT7621_CDMP_EG_CTRL); +} + +static int mt7621_fwd_config(struct fe_priv *priv) +{ + struct net_device *dev = priv_netdev(priv); + + fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) & ~0xffff, + MT7620A_GDMA1_FWD_CFG); + + /* mt7621 doesn't have txcsum config */ + mt7621_rxcsum_config((dev->features & NETIF_F_RXCSUM)); + mt7621_rxvlan_config(priv->flags & FE_FLAG_RX_VLAN_CTAG); + + return 0; +} + +static void mt7621_tx_dma(struct fe_tx_dma *txd) +{ + txd->txd4 = MT7621_TX_DMA_FPORT; +} + +static void mt7621_init_data(struct fe_soc_data *data, + struct net_device *netdev) +{ + struct fe_priv *priv = netdev_priv(netdev); + + priv->flags = FE_FLAG_PADDING_64B | FE_FLAG_RX_2B_OFFSET | + FE_FLAG_RX_SG_DMA | FE_FLAG_NAPI_WEIGHT | + FE_FLAG_HAS_SWITCH | FE_FLAG_JUMBO_FRAME; + + netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | + NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_TSO | + NETIF_F_TSO6 | NETIF_F_IPV6_CSUM; +} + +static void mt7621_set_mac(struct fe_priv *priv, unsigned char *mac) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->page_lock, flags); + fe_w32((mac[0] << 8) | mac[1], GSW_REG_GDMA1_MAC_ADRH); + fe_w32((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], + GSW_REG_GDMA1_MAC_ADRL); + spin_unlock_irqrestore(&priv->page_lock, flags); +} + +static struct fe_soc_data mt7621_data = { + .init_data = mt7621_init_data, + .reset_fe = mt7621_fe_reset, + .set_mac = mt7621_set_mac, + .fwd_config = mt7621_fwd_config, + .tx_dma = mt7621_tx_dma, + .switch_init = mtk_gsw_init, + .switch_config = mt7621_gsw_config, + .reg_table = mt7621_reg_table, + .pdma_glo_cfg = FE_PDMA_SIZE_16DWORDS, + .rx_int = RT5350_RX_DONE_INT, + .tx_int = RT5350_TX_DONE_INT, + .status_int = (MT7621_FE_GDM1_AF | MT7621_FE_GDM2_AF), + .checksum_bit = MT7621_L4_VALID, + .has_carrier = mt7620_has_carrier, + .mdio_read = mt7620_mdio_read, + .mdio_write = mt7620_mdio_write, + .mdio_adjust_link = mt7620_mdio_link_adjust, +}; + +const struct of_device_id of_fe_match[] = { + { .compatible = "mediatek,mt7621-eth", .data = &mt7621_data }, + {}, +}; + +MODULE_DEVICE_TABLE(of, of_fe_match); diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/soc_rt2880.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/soc_rt2880.c new file mode 100644 index 000000000..6c89c997d --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/soc_rt2880.c @@ -0,0 +1,76 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#include + +#include + +#include "mtk_eth_soc.h" +#include "mdio_rt2880.h" + +#define RT2880_RESET_FE BIT(18) + +static void rt2880_init_data(struct fe_soc_data *data, + struct net_device *netdev) +{ + struct fe_priv *priv = netdev_priv(netdev); + + priv->flags = FE_FLAG_PADDING_64B | FE_FLAG_PADDING_BUG | + FE_FLAG_JUMBO_FRAME | FE_FLAG_CALIBRATE_CLK; + netdev->hw_features = NETIF_F_SG | NETIF_F_HW_VLAN_CTAG_TX; + /* this should work according to the datasheet but actually does not*/ + /* netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; */ +} + +void rt2880_fe_reset(void) +{ + fe_reset(RT2880_RESET_FE); +} + +static int rt2880_fwd_config(struct fe_priv *priv) +{ + int ret; + + ret = fe_set_clock_cycle(priv); + if (ret) + return ret; + + fe_fwd_config(priv); + fe_w32(FE_PSE_FQFC_CFG_INIT, FE_PSE_FQ_CFG); + fe_csum_config(priv); + + return ret; +} + +struct fe_soc_data rt2880_data = { + .init_data = rt2880_init_data, + .reset_fe = rt2880_fe_reset, + .fwd_config = rt2880_fwd_config, + .pdma_glo_cfg = FE_PDMA_SIZE_8DWORDS, + .checksum_bit = RX_DMA_L4VALID, + .rx_int = FE_RX_DONE_INT, + .tx_int = FE_TX_DONE_INT, + .status_int = FE_CNT_GDM_AF, + .mdio_read = rt2880_mdio_read, + .mdio_write = rt2880_mdio_write, + .mdio_adjust_link = rt2880_mdio_link_adjust, + .port_init = rt2880_port_init, +}; + +const struct of_device_id of_fe_match[] = { + { .compatible = "ralink,rt2880-eth", .data = &rt2880_data }, + {}, +}; + +MODULE_DEVICE_TABLE(of, of_fe_match); diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/soc_rt3050.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/soc_rt3050.c new file mode 100644 index 000000000..914b81410 --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/soc_rt3050.c @@ -0,0 +1,158 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#include + +#include + +#include "mtk_eth_soc.h" +#include "mdio_rt2880.h" + +#define RT305X_RESET_FE BIT(21) +#define RT305X_RESET_ESW BIT(23) + +static const u16 rt5350_reg_table[FE_REG_COUNT] = { + [FE_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG, + [FE_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG, + [FE_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG, + [FE_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0, + [FE_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0, + [FE_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0, + [FE_REG_TX_DTX_IDX0] = RT5350_TX_DTX_IDX0, + [FE_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0, + [FE_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0, + [FE_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0, + [FE_REG_RX_DRX_IDX0] = RT5350_RX_DRX_IDX0, + [FE_REG_FE_INT_ENABLE] = RT5350_FE_INT_ENABLE, + [FE_REG_FE_INT_STATUS] = RT5350_FE_INT_STATUS, + [FE_REG_FE_RST_GL] = 0, + [FE_REG_FE_DMA_VID_BASE] = 0, +}; + +static void rt305x_init_data(struct fe_soc_data *data, + struct net_device *netdev) +{ + struct fe_priv *priv = netdev_priv(netdev); + + priv->flags = FE_FLAG_PADDING_64B | FE_FLAG_PADDING_BUG | + FE_FLAG_CALIBRATE_CLK | FE_FLAG_HAS_SWITCH; + netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX; +} + +static int rt3050_fwd_config(struct fe_priv *priv) +{ + int ret; + + if (ralink_soc != RT305X_SOC_RT3052) { + ret = fe_set_clock_cycle(priv); + if (ret) + return ret; + } + + fe_fwd_config(priv); + if (ralink_soc != RT305X_SOC_RT3352) + fe_w32(FE_PSE_FQFC_CFG_INIT, FE_PSE_FQ_CFG); + fe_csum_config(priv); + + return 0; +} + +static void rt305x_fe_reset(void) +{ + fe_reset(RT305X_RESET_FE); +} + +static void rt5350_init_data(struct fe_soc_data *data, + struct net_device *netdev) +{ + struct fe_priv *priv = netdev_priv(netdev); + + priv->flags = FE_FLAG_HAS_SWITCH; + netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM; +} + +static void rt5350_set_mac(struct fe_priv *priv, unsigned char *mac) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->page_lock, flags); + fe_w32((mac[0] << 8) | mac[1], RT5350_SDM_MAC_ADRH); + fe_w32((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], + RT5350_SDM_MAC_ADRL); + spin_unlock_irqrestore(&priv->page_lock, flags); +} + +static void rt5350_rxcsum_config(bool enable) +{ + if (enable) + fe_w32(fe_r32(RT5350_SDM_CFG) | (RT5350_SDM_ICS_EN | + RT5350_SDM_TCS_EN | RT5350_SDM_UCS_EN), + RT5350_SDM_CFG); + else + fe_w32(fe_r32(RT5350_SDM_CFG) & ~(RT5350_SDM_ICS_EN | + RT5350_SDM_TCS_EN | RT5350_SDM_UCS_EN), + RT5350_SDM_CFG); +} + +static int rt5350_fwd_config(struct fe_priv *priv) +{ + struct net_device *dev = priv_netdev(priv); + + rt5350_rxcsum_config((dev->features & NETIF_F_RXCSUM)); + + return 0; +} + +static void rt5350_tx_dma(struct fe_tx_dma *txd) +{ + txd->txd4 = 0; +} + +static void rt5350_fe_reset(void) +{ + fe_reset(RT305X_RESET_FE | RT305X_RESET_ESW); +} + +static struct fe_soc_data rt3050_data = { + .init_data = rt305x_init_data, + .reset_fe = rt305x_fe_reset, + .fwd_config = rt3050_fwd_config, + .pdma_glo_cfg = FE_PDMA_SIZE_8DWORDS, + .checksum_bit = RX_DMA_L4VALID, + .rx_int = FE_RX_DONE_INT, + .tx_int = FE_TX_DONE_INT, + .status_int = FE_CNT_GDM_AF, +}; + +static struct fe_soc_data rt5350_data = { + .init_data = rt5350_init_data, + .reg_table = rt5350_reg_table, + .reset_fe = rt5350_fe_reset, + .set_mac = rt5350_set_mac, + .fwd_config = rt5350_fwd_config, + .tx_dma = rt5350_tx_dma, + .pdma_glo_cfg = FE_PDMA_SIZE_8DWORDS, + .checksum_bit = RX_DMA_L4VALID, + .rx_int = RT5350_RX_DONE_INT, + .tx_int = RT5350_TX_DONE_INT, +}; + +const struct of_device_id of_fe_match[] = { + { .compatible = "ralink,rt3050-eth", .data = &rt3050_data }, + { .compatible = "ralink,rt5350-eth", .data = &rt5350_data }, + {}, +}; + +MODULE_DEVICE_TABLE(of, of_fe_match); diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/soc_rt3883.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/soc_rt3883.c new file mode 100644 index 000000000..4935b7fbd --- /dev/null +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/soc_rt3883.c @@ -0,0 +1,75 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2009-2015 John Crispin + * Copyright (C) 2009-2015 Felix Fietkau + * Copyright (C) 2013-2015 Michael Lee + */ + +#include + +#include + +#include "mtk_eth_soc.h" +#include "mdio_rt2880.h" + +#define RT3883_RSTCTRL_FE BIT(21) + +static void rt3883_fe_reset(void) +{ + fe_reset(RT3883_RSTCTRL_FE); +} + +static int rt3883_fwd_config(struct fe_priv *priv) +{ + int ret; + + ret = fe_set_clock_cycle(priv); + if (ret) + return ret; + + fe_fwd_config(priv); + fe_w32(FE_PSE_FQFC_CFG_256Q, FE_PSE_FQ_CFG); + fe_csum_config(priv); + + return ret; +} + +static void rt3883_init_data(struct fe_soc_data *data, + struct net_device *netdev) +{ + struct fe_priv *priv = netdev_priv(netdev); + + priv->flags = FE_FLAG_PADDING_64B | FE_FLAG_PADDING_BUG | + FE_FLAG_JUMBO_FRAME | FE_FLAG_CALIBRATE_CLK; + netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX; +} + +static struct fe_soc_data rt3883_data = { + .init_data = rt3883_init_data, + .reset_fe = rt3883_fe_reset, + .fwd_config = rt3883_fwd_config, + .pdma_glo_cfg = FE_PDMA_SIZE_8DWORDS, + .rx_int = FE_RX_DONE_INT, + .tx_int = FE_TX_DONE_INT, + .status_int = FE_CNT_GDM_AF, + .checksum_bit = RX_DMA_L4VALID, + .mdio_read = rt2880_mdio_read, + .mdio_write = rt2880_mdio_write, + .mdio_adjust_link = rt2880_mdio_link_adjust, + .port_init = rt2880_port_init, +}; + +const struct of_device_id of_fe_match[] = { + { .compatible = "ralink,rt3883-eth", .data = &rt3883_data }, + {}, +}; + +MODULE_DEVICE_TABLE(of, of_fe_match); diff --git a/target/linux/ramips/image/Makefile b/target/linux/ramips/image/Makefile index ea7ce0bc9..13934c5b0 100644 --- a/target/linux/ramips/image/Makefile +++ b/target/linux/ramips/image/Makefile @@ -111,6 +111,26 @@ define Build/wrg-header mv $@.new $@ endef +# combine kernel and rootfs into one image +# mkdlinkfw + +define Build/mkdlinkfw + -$(STAGING_DIR_HOST)/bin/mkdlinkfw \ + -k $(IMAGE_KERNEL) \ + -r $(IMAGE_ROOTFS) \ + -o $@ \ + -s $(DLINK_FIRMWARE_SIZE) +endef + +define Build/mkdlinkfw-factory + -$(STAGING_DIR_HOST)/bin/mkdlinkfw \ + -m $(DLINK_ROM_ID) -f $(DLINK_FAMILY_MEMBER) \ + -F $@ \ + -o $@.new \ + -s $(DLINK_FIRMWARE_SIZE) + mv $@.new $@ +endef + # # The real magic happens inside these templates # @@ -118,7 +138,7 @@ endef # $(2), filename of image data # $(3), output filename define MkImage - $(eval imagename=$(if $(4),$(4),MIPS OpenWrt Linux-$(LINUX_VERSION))) + $(eval imagename=$(if $(4),$(4),MIPS $(VERSION_DIST) Linux-$(LINUX_VERSION))) -mkimage -A mips -O linux -T kernel -C $(1) -a $(loadaddr-y) -e $(loadaddr-y) \ -n "$(imagename)" \ -d $(2) $(3) diff --git a/target/linux/ramips/image/mt7620.mk b/target/linux/ramips/image/mt7620.mk index 6f9aa1aa6..c12a91524 100644 --- a/target/linux/ramips/image/mt7620.mk +++ b/target/linux/ramips/image/mt7620.mk @@ -2,7 +2,8 @@ # MT7620A Profiles # -DEVICE_VARS += TPLINK_FLASHLAYOUT TPLINK_HWID TPLINK_HWREV TPLINK_HWREVADD TPLINK_HVERSION +DEVICE_VARS += TPLINK_FLASHLAYOUT TPLINK_HWID TPLINK_HWREV TPLINK_HWREVADD TPLINK_HVERSION \ + DLINK_ROM_ID DLINK_FAMILY_MEMBER DLINK_FIRMWARE_SIZE define Build/elecom-header cp $@ $(KDIR)/v_0.0.0.bin @@ -31,8 +32,7 @@ define Device/alfa-network_ac1200rm DTS := AC1200RM IMAGE_SIZE := 16064k DEVICE_TITLE := ALFA Network AC1200RM - DEVICE_PACKAGES := kmod-usb2 kmod-usb-ohci - SUPPORTED_DEVICES := $(subst _,$(comma),$(1)) + DEVICE_PACKAGES := kmod-usb2 kmod-usb-ohci uboot-envtools endef TARGET_DEVICES += alfa-network_ac1200rm @@ -45,20 +45,6 @@ define Device/Archer IMAGE/sysupgrade.bin := tplink-v2-image -s -e | append-metadata endef -define Device/ArcherC20 - $(Device/Archer) - DTS := ArcherC20 - SUPPORTED_DEVICES := c20 - TPLINK_FLASHLAYOUT := 8Mmtk - TPLINK_HWID := 0xc2000001 - TPLINK_HWREV := 0x44 - TPLINK_HWREVADD := 0x1 - IMAGES += factory.bin - DEVICE_TITLE := TP-Link ArcherC20 - DEVICE_PACKAGES := kmod-usb-core kmod-usb2 kmod-usb-ledtrig-usbport -endef -TARGET_DEVICES += ArcherC20 - define Device/ArcherC20i $(Device/Archer) DTS := ArcherC20i @@ -161,6 +147,44 @@ define Device/dir-810l endef TARGET_DEVICES += dir-810l +define Device/dlink_dwr-116-a1 + DTS := DWR-116-A1 + DEVICE_TITLE := D-Link DWR-116 A1/A2 + DEVICE_PACKAGES := kmod-usb2 jboot-tools + DLINK_ROM_ID := DLK6E3803001 + DLINK_FAMILY_MEMBER := 0x6E38 + DLINK_FIRMWARE_SIZE := 0x7E0000 + KERNEL := $(KERNEL_DTB) + IMAGES += factory.bin + IMAGE/sysupgrade.bin := mkdlinkfw | pad-rootfs | append-metadata + IMAGE/factory.bin := mkdlinkfw | pad-rootfs | mkdlinkfw-factory +endef +TARGET_DEVICES += dlink_dwr-116-a1 + +define Device/dlink_dwr-921-c1 + DTS := DWR-921-C1 + IMAGE_SIZE := $(ralink_default_fw_size_16M) + DEVICE_TITLE := D-Link DWR-921 C1 + DLINK_ROM_ID := DLK6E2414001 + DLINK_FAMILY_MEMBER := 0x6E24 + DLINK_FIRMWARE_SIZE := 0xFE0000 + KERNEL := $(KERNEL_DTB) + IMAGES += factory.bin + IMAGE/sysupgrade.bin := mkdlinkfw | pad-rootfs | append-metadata + IMAGE/factory.bin := mkdlinkfw | pad-rootfs | mkdlinkfw-factory + DEVICE_PACKAGES := jboot-tools \ + kmod-usb2 kmod-usb-net-qmi-wwan kmod-usb-serial-option uqmi +endef +TARGET_DEVICES += dlink_dwr-921-c1 + +define Device/dlink_dwr-921-c3 + $(Device/dlink_dwr-921-c1) + DEVICE_TITLE := D-Link DWR-921 C3 + DLINK_ROM_ID := DLK6E2414009 + SUPPORTED_DEVICES := dlink,dwr-921-c1 +endef +TARGET_DEVICES += dlink_dwr-921-c3 + define Device/e1700 DTS := E1700 IMAGES += factory.bin @@ -433,6 +457,20 @@ define Device/tiny-ac endef TARGET_DEVICES += tiny-ac +define Device/tplink_c20-v1 + $(Device/Archer) + DTS := ArcherC20v1 + SUPPORTED_DEVICES := c20v1 + TPLINK_FLASHLAYOUT := 8Mmtk + TPLINK_HWID := 0xc2000001 + TPLINK_HWREV := 0x44 + TPLINK_HWREVADD := 0x1 + IMAGES += factory.bin + DEVICE_TITLE := TP-Link ArcherC20 v1 + DEVICE_PACKAGES := kmod-usb-core kmod-usb2 kmod-usb-ledtrig-usbport +endef +TARGET_DEVICES += tplink_c20-v1 + define Device/vonets_var11n-300 DTS := VAR11N-300 IMAGE_SIZE := $(ralink_default_fw_size_4M) diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index 8ba65a1af..18b693452 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -57,6 +57,14 @@ define Device/dir-860l-b1 endef TARGET_DEVICES += dir-860l-b1 +define Device/mediatek_ap-mt7621a-v60 + DTS := AP-MT7621A-V60 + IMAGE_SIZE := $(ralink_default_fw_size_8M) + DEVICE_TITLE := Mediatek AP-MT7621A-V60 EVB + DEVICE_PACKAGES := kmod-usb3 kmod-sdhci-mt7620 kmod-sound-mt7620 +endef +TARGET_DEVICES += mediatek_ap-mt7621a-v60 + define Device/ew1200 DTS := EW1200 IMAGE_SIZE := $(ralink_default_fw_size_16M) @@ -83,6 +91,14 @@ define Device/gb-pc1 endef TARGET_DEVICES += gb-pc1 +define Device/gnubee_gb-pc2 + DTS := GB-PC2 + DEVICE_TITLE := GnuBee Personal Cloud Two + DEVICE_PACKAGES := kmod-ata-core kmod-ata-ahci kmod-usb3 kmod-sdhci-mt7620 + IMAGE_SIZE := $(ralink_default_fw_size_32M) +endef +TARGET_DEVICES += gnubee_gb-pc2 + define Device/hc5962 DTS := HC5962 BLOCKSIZE := 128k diff --git a/target/linux/ramips/image/mt76x8.mk b/target/linux/ramips/image/mt76x8.mk index 8bbbcf6ad..c0b243c3c 100644 --- a/target/linux/ramips/image/mt76x8.mk +++ b/target/linux/ramips/image/mt76x8.mk @@ -19,6 +19,22 @@ endef DEVICE_VARS += TPLINK_FLASHLAYOUT TPLINK_HWID TPLINK_HWREV TPLINK_HWREVADD TPLINK_HVERSION +define Device/alfa-network_awusfree1 + DTS := AWUSFREE1 + IMAGE_SIZE := $(ralink_default_fw_size_8M) + DEVICE_TITLE := ALFA Network AWUSFREE1 + DEVICE_PACKAGES := uboot-envtools +endef +TARGET_DEVICES += alfa-network_awusfree1 + +define Device/tama_w06 + DTS := W06 + IMAGE_SIZE := 15040k + DEVICE_TITLE := Tama W06 + DEVICE_PACKAGES := kmod-usb2 kmod-usb-ohci +endef +TARGET_DEVICES += tama_w06 + define Device/duzun-dm06 DTS := DUZUN-DM06 DEVICE_TITLE := DuZun DM06 @@ -112,7 +128,7 @@ TARGET_DEVICES += tl-wr840n-v4 define Device/tl-wr840n-v5 DTS := TL-WR840NV5 - IMAGE_SIZE := 3840k + IMAGE_SIZE := 3904k DEVICE_TITLE := TP-Link TL-WR840N v5 TPLINK_FLASHLAYOUT := 4Mmtk TPLINK_HWID := 0x08400005 @@ -139,6 +155,32 @@ define Device/tl-wr841n-v13 endef TARGET_DEVICES += tl-wr841n-v13 +define Device/tplink_c20-v4 + $(Device/tplink) + DTS := ArcherC20v4 + IMAGE_SIZE := 7808k + DEVICE_TITLE := TP-Link ArcherC20 v4 + TPLINK_FLASHLAYOUT := 8Mmtk + TPLINK_HWID := 0xc200004 + TPLINK_HWREV := 0x1 + TPLINK_HWREVADD := 0x4 + TPLINK_HVERSION := 3 +endef +TARGET_DEVICES += tplink_c20-v4 + +define Device/tplink_c50-v3 + $(Device/tplink) + DTS := ArcherC50V3 + IMAGE_SIZE := 7808k + DEVICE_TITLE := TP-Link ArcherC50 v3 + TPLINK_FLASHLAYOUT := 8Mmtk + TPLINK_HWID := 0x001D9BA4 + TPLINK_HWREV := 0x79 + TPLINK_HWREVADD := 0x1 + TPLINK_HVERSION := 3 +endef +TARGET_DEVICES += tplink_c50-v3 + define Device/tplink_tl-mr3420-v5 $(Device/tplink) DTS := TL-MR3420V5 @@ -153,6 +195,21 @@ define Device/tplink_tl-mr3420-v5 endef TARGET_DEVICES += tplink_tl-mr3420-v5 +define Device/tplink_tl-wr902ac-v3 + $(Device/tplink) + DTS := TL-WR902ACV3 + IMAGE_SIZE := 7808k + DEVICE_TITLE := TP-Link TL-WR902AC v3 + TPLINK_FLASHLAYOUT := 8Mmtk + TPLINK_HWID := 0x000dc88f + TPLINK_HWREV := 0x89 + TPLINK_HWREVADD := 0x1 + TPLINK_HVERSION := 3 + IMAGES += factory.bin + DEVICE_PACKAGES := kmod-usb2 kmod-usb-ohci kmod-usb-ledtrig-usbport +endef +TARGET_DEVICES += tplink_tl-wr902ac-v3 + define Device/u7628-01-128M-16M DTS := U7628-01-128M-16M IMAGE_SIZE := 16064k @@ -202,13 +259,22 @@ define Device/wl-wn575a3 endef TARGET_DEVICES += wl-wn575a3 -define Device/widora-neo - DTS := WIDORA-NEO +define Device/widora_neo-16m + DTS := WIDORA-NEO-16M IMAGE_SIZE := $(ralink_default_fw_size_16M) - DEVICE_TITLE := Widora-NEO + DEVICE_TITLE := Widora-NEO (16M) + DEVICE_PACKAGES := kmod-usb2 kmod-usb-ohci + SUPPORTED_DEVICES += widora-neo +endef +TARGET_DEVICES += widora_neo-16m + +define Device/widora_neo-32m + DTS := WIDORA-NEO-32M + IMAGE_SIZE := $(ralink_default_fw_size_32M) + DEVICE_TITLE := Widora-NEO (32M) DEVICE_PACKAGES := kmod-usb2 kmod-usb-ohci endef -TARGET_DEVICES += widora-neo +TARGET_DEVICES += widora_neo-32m define Device/wrtnode2p DTS := WRTNODE2P @@ -225,3 +291,10 @@ define Device/wrtnode2r DEVICE_PACKAGES := kmod-usb2 kmod-usb-ohci endef TARGET_DEVICES += wrtnode2r + +define Device/zbtlink_zbt-we1226 + DTS := ZBT-WE1226 + IMAGE_SIZE := $(ralink_default_fw_size_8M) + DEVICE_TITLE := ZBTlink ZBT-WE1226 +endef +TARGET_DEVICES += zbtlink_zbt-we1226 diff --git a/target/linux/ramips/image/rt288x.mk b/target/linux/ramips/image/rt288x.mk index 86a506388..280ce5617 100644 --- a/target/linux/ramips/image/rt288x.mk +++ b/target/linux/ramips/image/rt288x.mk @@ -30,6 +30,22 @@ define Device/ar725w endef TARGET_DEVICES += ar725w +define Device/dlink_dap-1522-a1 + DTS := DAP-1522-A1 + BLOCKSIZE := 64k + IMAGE_SIZE := 3801088 + DEVICE_TITLE := D-Link DAP-1522 A1 + DEVICE_PACKAGES := kmod-switch-rtl8366s + KERNEL := $(KERNEL_DTB) + IMAGES += factory.bin + IMAGE/factory.bin := \ + append-kernel | pad-offset $$$$(BLOCKSIZE) 96 | \ + append-rootfs | pad-rootfs -x 96 | \ + wrg-header wapnd01_dlink_dap1522 | \ + check-size $$$$(IMAGE_SIZE) +endef +TARGET_DEVICES += dlink_dap-1522-a1 + define Device/f5d8235-v1 IMAGE_SIZE := 7744k DEVICE_TITLE := Belkin F5D8235 V1 diff --git a/target/linux/ramips/image/rt305x-legacy.mk b/target/linux/ramips/image/rt305x-legacy.mk index 173739b07..5116dfcd8 100644 --- a/target/linux/ramips/image/rt305x-legacy.mk +++ b/target/linux/ramips/image/rt305x-legacy.mk @@ -18,41 +18,6 @@ define BuildFirmware/DCS930/squashfs endef BuildFirmware/DCS930/initramfs=$(call BuildFirmware/OF/initramfs,$(1),$(2),$(3)) -# sign Buffalo images -define BuildFirmware/Buffalo - if [ -e "$(call sysupname,$(1),$(2))" ]; then \ - buffalo-enc -p $(3) -v 1.76 \ - -i $(KDIR)/vmlinux-$(2).uImage \ - -o $(KDIR)/vmlinux-$(2).uImage.enc; \ - buffalo-enc -p $(3) -v 1.76 \ - -i $(KDIR)/root.$(1) \ - -o $(KDIR)/root.$(2).enc; \ - buffalo-tag -b $(3) -p $(3) -a ram -v 1.76 -m 1.01 \ - -l mlang8 -f 1 -r EU \ - -i $(KDIR)/vmlinux-$(2).uImage.enc \ - -i $(KDIR)/root.$(2).enc \ - -o $(call imgname,$(1),$(2))-factory-EU.bin; \ - fi -endef - -# FIXME: this looks broken -buffalo_whrg300n_mtd_size=3801088 -define BuildFirmware/WHRG300N/squashfs - $(call BuildFirmware/Default4M/$(1),$(1),whr-g300n,WHR-G300N) - # the following line has a bad argument 3 ... the old Makefile was already broken - $(call BuildFirmware/Buffalo,$(1),whr-g300n,whr-g300n) - if [ -e "$(call sysupname,$(1),$(2))" ]; then \ - ( \ - echo -n -e "# Airstation FirmWare\nrun u_fw\nreset\n\n" | \ - dd bs=512 count=1 conv=sync; \ - dd if=$(call sysupname,$(1),whr-g300n); \ - ) > $(KDIR)/whr-g300n-tftp.tmp && \ - buffalo-tftp -i $(KDIR)/whr-g300n-tftp.tmp \ - -o $(call imgname,$(1),whr-g300n)-tftp.bin; \ - fi -endef -BuildFirmware/WHRG300N/initramfs=$(call BuildFirmware/OF/initramfs,$(1),whr-g300n,WHR-G300N) - kernel_size_wl341v3=917504 rootfs_size_wl341v3=2949120 define BuildFirmware/WL-341V3/squashfs @@ -84,7 +49,6 @@ endef Image/Build/Profile/DCS930=$(call BuildFirmware/DCS930/$(1),$(1),dcs-930,DCS-930) Image/Build/Profile/DCS930LB1=$(call BuildFirmware/DCS930/$(1),$(1),dcs-930l-b1,DCS-930L-B1) Image/Build/Profile/WL-341V3=$(call BuildFirmware/WL-341V3/$(1),$(1)) -Image/Build/Profile/WHRG300N=$(call BuildFirmware/WHRG300N/$(1),$(1)) define LegacyDevice/ALL02393G DEVICE_TITLE := Allnet ALL0239-3G @@ -110,9 +74,3 @@ define LegacyDevice/WL-341V3 DEVICE_TITLE := Sitecom WL-341 v3 endef LEGACY_DEVICES += WL-341V3 - - -define LegacyDevice/WHRG300N - DEVICE_TITLE := Buffalo WHR-G300N -endef -LEGACY_DEVICES += WHRG300N diff --git a/target/linux/ramips/image/rt305x.mk b/target/linux/ramips/image/rt305x.mk index 4e82eb48a..dbf15bc7d 100644 --- a/target/linux/ramips/image/rt305x.mk +++ b/target/linux/ramips/image/rt305x.mk @@ -1,6 +1,16 @@ # # RT305X Profiles # +define Build/buffalo-tftp-header + ( \ + echo -n -e "# Airstation FirmWare\nrun u_fw\nreset\n\n" | \ + dd bs=512 count=1 conv=sync; \ + dd if=$@; \ + ) > $@.tmp && \ + $(STAGING_DIR_HOST)/bin/buffalo-tftp -i $@.tmp -o $@.new + mv $@.new $@ +endef + define Build/dap-header $(STAGING_DIR_HOST)/bin/mkdapimg $(1) -i $@ -o $@.new mv $@.new $@ @@ -745,6 +755,17 @@ define Device/wcr-150gn endef TARGET_DEVICES += wcr-150gn +define Device/whr-g300n + DTS := WHR-G300N + BLOCKSIZE := 64k + IMAGE_SIZE := 3801088 + DEVICE_TITLE := Buffalo WHR-G300N + IMAGES += tftp.bin + IMAGE/tftp.bin := $$(sysupgrade_bin) | \ + check-size $$$$(IMAGE_SIZE) | buffalo-tftp-header +endef +TARGET_DEVICES += whr-g300n + define Device/wizard8800 DTS := WIZARD8800 UIMAGE_NAME:= Linux Kernel Image diff --git a/target/linux/ramips/mt7620/config-4.9 b/target/linux/ramips/mt7620/config-4.14 similarity index 84% rename from target/linux/ramips/mt7620/config-4.9 rename to target/linux/ramips/mt7620/config-4.14 index 4f8c68629..3e006e2ef 100644 --- a/target/linux/ramips/mt7620/config-4.9 +++ b/target/linux/ramips/mt7620/config-4.14 @@ -5,22 +5,31 @@ CONFIG_ARCH_HAS_ELF_RANDOMIZE=y # CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set CONFIG_ARCH_HAS_RESET_CONTROLLER=y # CONFIG_ARCH_HAS_SG_CHAIN is not set +# CONFIG_ARCH_HAS_STRICT_KERNEL_RWX is not set +# CONFIG_ARCH_HAS_STRICT_MODULE_RWX is not set CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y +CONFIG_ARCH_MMAP_RND_BITS_MAX=15 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 +# CONFIG_ARCH_OPTIONAL_KERNEL_RWX is not set +# CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT is not set CONFIG_ARCH_SUPPORTS_UPROBES=y CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_ARCH_USE_QUEUED_RWLOCKS=y +CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y +# CONFIG_ARCH_WANTS_THP_SWAP is not set CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y CONFIG_AT803X_PHY=y CONFIG_BLK_MQ_PCI=y +# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_CEVT_R4K=y CONFIG_CEVT_SYSTICK_QUIRK=y CONFIG_CLKDEV_LOOKUP=y CONFIG_CLKEVT_RT3352=y CONFIG_CLKSRC_MMIO=y -CONFIG_CLKSRC_OF=y -CONFIG_CLKSRC_PROBE=y CONFIG_CLONE_BACKWARDS=y CONFIG_CMDLINE="rootfstype=squashfs,jffs2" CONFIG_CMDLINE_BOOL=y @@ -45,16 +54,25 @@ CONFIG_CRYPTO_WORKQUEUE=y CONFIG_CSRC_R4K=y CONFIG_DEBUG_PINCTRL=y CONFIG_DMA_NONCOHERENT=y +# CONFIG_DMA_NOOP_OPS is not set +# CONFIG_DMA_VIRT_OPS is not set +# CONFIG_DRM_LIB_RANDOM is not set # CONFIG_DTB_MT7620A_EVAL is not set +# CONFIG_DTB_OMEGA2P is not set CONFIG_DTB_RT_NONE=y +# CONFIG_DTB_VOCORE2 is not set CONFIG_DTC=y CONFIG_EARLY_PRINTK=y +CONFIG_EXPORTFS=y CONFIG_FIXED_PHY=y +CONFIG_FUTEX_PI=y CONFIG_GENERIC_ATOMIC64=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_CPU_AUTOPROBE=y CONFIG_GENERIC_IO=y CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y CONFIG_GENERIC_IRQ_SHOW=y CONFIG_GENERIC_PCI_IOMAP=y CONFIG_GENERIC_PHY=y @@ -65,6 +83,7 @@ CONFIG_GPIOLIB=y # CONFIG_GPIO_MT7621 is not set CONFIG_GPIO_RALINK=y CONFIG_GPIO_SYSFS=y +# CONFIG_GRO_CELLS is not set CONFIG_HANDLE_DOMAIN_IRQ=y CONFIG_HARDWARE_WATCHPOINTS=y CONFIG_HAS_DMA=y @@ -81,6 +100,7 @@ CONFIG_HAVE_CBPF_JIT=y CONFIG_HAVE_CC_STACKPROTECTOR=y CONFIG_HAVE_CLK=y CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_COPY_THREAD_TLS=y CONFIG_HAVE_C_RECORDMCOUNT=y CONFIG_HAVE_DEBUG_KMEMLEAK=y CONFIG_HAVE_DEBUG_STACKOVERFLOW=y @@ -116,7 +136,9 @@ CONFIG_IRQ_INTC=y CONFIG_IRQ_MIPS_CPU=y CONFIG_IRQ_WORK=y CONFIG_LIBFDT=y -CONFIG_MDIO_BOARDINFO=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MFD_SYSCON=y CONFIG_MIPS=y CONFIG_MIPS_ASID_BITS=8 CONFIG_MIPS_ASID_SHIFT=0 @@ -137,12 +159,12 @@ CONFIG_MODULES_USE_ELF_REL=y # CONFIG_MTD_CFI_INTELEXT is not set CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_M25P80=y -CONFIG_MTD_NAND_MT7620=y CONFIG_MTD_PHYSMAP=y CONFIG_MTD_SPI_NOR=y CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT=16384 CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_JIMAGE_FW=y CONFIG_MTD_SPLIT_SEAMA_FW=y CONFIG_MTD_SPLIT_TPLINK_FW=y CONFIG_MTD_SPLIT_UIMAGE_FW=y @@ -180,7 +202,10 @@ CONFIG_PINCTRL_RT2880=y # CONFIG_PINCTRL_SINGLE is not set CONFIG_RALINK=y CONFIG_RALINK_WDT=y +# CONFIG_RCU_NEED_SEGCBLIST is not set # CONFIG_RCU_STALL_COMMON is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y CONFIG_RESET_CONTROLLER=y # CONFIG_SCHED_INFO is not set # CONFIG_SCSI_DMA is not set @@ -208,7 +233,11 @@ CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y CONFIG_SYS_SUPPORTS_ARBIT_HZ=y CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_THIN_ARCHIVES=y CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TINY_SRCU=y CONFIG_USB_SUPPORT=y CONFIG_USE_OF=y CONFIG_WATCHDOG_CORE=y diff --git a/target/linux/ramips/mt7621/config-4.9 b/target/linux/ramips/mt7621/config-4.14 similarity index 99% rename from target/linux/ramips/mt7621/config-4.9 rename to target/linux/ramips/mt7621/config-4.14 index f9765edaf..3a5cd4296 100644 --- a/target/linux/ramips/mt7621/config-4.9 +++ b/target/linux/ramips/mt7621/config-4.14 @@ -26,6 +26,7 @@ CONFIG_CMDLINE="rootfstype=squashfs,jffs2" CONFIG_CMDLINE_BOOL=y # CONFIG_CMDLINE_OVERRIDE is not set CONFIG_COMMON_CLK=y +# CONFIG_COMMON_CLK_BOSTON is not set CONFIG_CPU_GENERIC_DUMP_TLB=y CONFIG_CPU_HAS_PREFETCH=y CONFIG_CPU_HAS_RIXI=y diff --git a/target/linux/ramips/mt76x8/config-4.9 b/target/linux/ramips/mt76x8/config-4.14 similarity index 84% rename from target/linux/ramips/mt76x8/config-4.9 rename to target/linux/ramips/mt76x8/config-4.14 index 23ee65cd1..0939aa4d4 100644 --- a/target/linux/ramips/mt76x8/config-4.9 +++ b/target/linux/ramips/mt76x8/config-4.14 @@ -5,22 +5,31 @@ CONFIG_ARCH_HAS_ELF_RANDOMIZE=y # CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set CONFIG_ARCH_HAS_RESET_CONTROLLER=y # CONFIG_ARCH_HAS_SG_CHAIN is not set +# CONFIG_ARCH_HAS_STRICT_KERNEL_RWX is not set +# CONFIG_ARCH_HAS_STRICT_MODULE_RWX is not set CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y +CONFIG_ARCH_MMAP_RND_BITS_MAX=15 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 +# CONFIG_ARCH_OPTIONAL_KERNEL_RWX is not set +# CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT is not set CONFIG_ARCH_SUPPORTS_UPROBES=y CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_ARCH_USE_QUEUED_RWLOCKS=y +CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y +# CONFIG_ARCH_WANTS_THP_SWAP is not set CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y CONFIG_AT803X_PHY=y CONFIG_BLK_MQ_PCI=y +# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_CEVT_R4K=y CONFIG_CEVT_SYSTICK_QUIRK=y CONFIG_CLKDEV_LOOKUP=y CONFIG_CLKEVT_RT3352=y CONFIG_CLKSRC_MMIO=y -CONFIG_CLKSRC_OF=y -CONFIG_CLKSRC_PROBE=y CONFIG_CLONE_BACKWARDS=y CONFIG_CMDLINE="rootfstype=squashfs,jffs2" CONFIG_CMDLINE_BOOL=y @@ -45,16 +54,25 @@ CONFIG_CRYPTO_WORKQUEUE=y CONFIG_CSRC_R4K=y CONFIG_DEBUG_PINCTRL=y CONFIG_DMA_NONCOHERENT=y +# CONFIG_DMA_NOOP_OPS is not set +# CONFIG_DMA_VIRT_OPS is not set +# CONFIG_DRM_LIB_RANDOM is not set # CONFIG_DTB_MT7620A_EVAL is not set +# CONFIG_DTB_OMEGA2P is not set CONFIG_DTB_RT_NONE=y +# CONFIG_DTB_VOCORE2 is not set CONFIG_DTC=y CONFIG_EARLY_PRINTK=y +CONFIG_EXPORTFS=y CONFIG_FIXED_PHY=y +CONFIG_FUTEX_PI=y CONFIG_GENERIC_ATOMIC64=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_CPU_AUTOPROBE=y CONFIG_GENERIC_IO=y CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y CONFIG_GENERIC_IRQ_SHOW=y CONFIG_GENERIC_PCI_IOMAP=y CONFIG_GENERIC_PHY=y @@ -65,6 +83,7 @@ CONFIG_GPIOLIB=y CONFIG_GPIO_MT7621=y # CONFIG_GPIO_RALINK is not set CONFIG_GPIO_SYSFS=y +# CONFIG_GRO_CELLS is not set CONFIG_HANDLE_DOMAIN_IRQ=y CONFIG_HARDWARE_WATCHPOINTS=y CONFIG_HAS_DMA=y @@ -81,6 +100,7 @@ CONFIG_HAVE_CBPF_JIT=y CONFIG_HAVE_CC_STACKPROTECTOR=y CONFIG_HAVE_CLK=y CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_COPY_THREAD_TLS=y CONFIG_HAVE_C_RECORDMCOUNT=y CONFIG_HAVE_DEBUG_KMEMLEAK=y CONFIG_HAVE_DEBUG_STACKOVERFLOW=y @@ -116,7 +136,9 @@ CONFIG_IRQ_INTC=y CONFIG_IRQ_MIPS_CPU=y CONFIG_IRQ_WORK=y CONFIG_LIBFDT=y -CONFIG_MDIO_BOARDINFO=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MFD_SYSCON=y CONFIG_MIPS=y CONFIG_MIPS_ASID_BITS=8 CONFIG_MIPS_ASID_SHIFT=0 @@ -175,7 +197,10 @@ CONFIG_PINCTRL_RT2880=y # CONFIG_PINCTRL_SINGLE is not set CONFIG_RALINK=y # CONFIG_RALINK_WDT is not set +# CONFIG_RCU_NEED_SEGCBLIST is not set # CONFIG_RCU_STALL_COMMON is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y CONFIG_RESET_CONTROLLER=y # CONFIG_SCHED_INFO is not set # CONFIG_SCSI_DMA is not set @@ -204,7 +229,11 @@ CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y CONFIG_SYS_SUPPORTS_ARBIT_HZ=y CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_THIN_ARCHIVES=y CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TINY_SRCU=y CONFIG_USB_SUPPORT=y CONFIG_USE_OF=y CONFIG_WATCHDOG_CORE=y diff --git a/target/linux/ramips/patches-4.14/0004-MIPS-ralink-add-MT7621-pcie-driver.patch b/target/linux/ramips/patches-4.14/0004-MIPS-ralink-add-MT7621-pcie-driver.patch new file mode 100644 index 000000000..b6f1ce93f --- /dev/null +++ b/target/linux/ramips/patches-4.14/0004-MIPS-ralink-add-MT7621-pcie-driver.patch @@ -0,0 +1,861 @@ +From fec11d4e8dc5cc79bcd7c8fd55038ac21ac39965 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 16 Mar 2014 05:22:39 +0000 +Subject: [PATCH 04/53] MIPS: ralink: add MT7621 pcie driver + +Signed-off-by: John Crispin +--- + arch/mips/pci/Makefile | 1 + + arch/mips/pci/pci-mt7621.c | 813 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 814 insertions(+) + create mode 100644 arch/mips/pci/pci-mt7621.c + +--- a/arch/mips/pci/Makefile ++++ b/arch/mips/pci/Makefile +@@ -47,6 +47,7 @@ obj-$(CONFIG_SNI_RM) += fixup-sni.o ops + obj-$(CONFIG_LANTIQ) += fixup-lantiq.o + obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o + obj-$(CONFIG_SOC_MT7620) += pci-mt7620.o ++obj-$(CONFIG_SOC_MT7621) += pci-mt7621.o + obj-$(CONFIG_SOC_RT288X) += pci-rt2880.o + obj-$(CONFIG_SOC_RT3883) += pci-rt3883.o + obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o +--- /dev/null ++++ b/arch/mips/pci/pci-mt7621.c +@@ -0,0 +1,836 @@ ++/************************************************************************** ++ * ++ * BRIEF MODULE DESCRIPTION ++ * PCI init for Ralink RT2880 solution ++ * ++ * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw) ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN ++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ ************************************************************************** ++ * May 2007 Bruce Chang ++ * Initial Release ++ * ++ * May 2009 Bruce Chang ++ * support RT2880/RT3883 PCIe ++ * ++ * May 2011 Bruce Chang ++ * support RT6855/MT7620 PCIe ++ * ++ ************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++extern void pcie_phy_init(void); ++extern void chk_phy_pll(void); ++ ++/* ++ * These functions and structures provide the BIOS scan and mapping of the PCI ++ * devices. ++ */ ++ ++#define CONFIG_PCIE_PORT0 ++#define CONFIG_PCIE_PORT1 ++#define CONFIG_PCIE_PORT2 ++#define RALINK_PCIE0_CLK_EN (1<<24) ++#define RALINK_PCIE1_CLK_EN (1<<25) ++#define RALINK_PCIE2_CLK_EN (1<<26) ++ ++#define RALINK_PCI_CONFIG_ADDR 0x20 ++#define RALINK_PCI_CONFIG_DATA_VIRTUAL_REG 0x24 ++#define RALINK_INT_PCIE0 pcie_irq[0] ++#define RALINK_INT_PCIE1 pcie_irq[1] ++#define RALINK_INT_PCIE2 pcie_irq[2] ++#define RALINK_PCI_MEMBASE *(volatile u32 *)(RALINK_PCI_BASE + 0x0028) ++#define RALINK_PCI_IOBASE *(volatile u32 *)(RALINK_PCI_BASE + 0x002C) ++#define RALINK_PCIE0_RST (1<<24) ++#define RALINK_PCIE1_RST (1<<25) ++#define RALINK_PCIE2_RST (1<<26) ++#define RALINK_SYSCTL_BASE 0xBE000000 ++ ++#define RALINK_PCI_PCICFG_ADDR *(volatile u32 *)(RALINK_PCI_BASE + 0x0000) ++#define RALINK_PCI_PCIMSK_ADDR *(volatile u32 *)(RALINK_PCI_BASE + 0x000C) ++#define RALINK_PCI_BASE 0xBE140000 ++ ++#define RALINK_PCIEPHY_P0P1_CTL_OFFSET (RALINK_PCI_BASE + 0x9000) ++#define RT6855_PCIE0_OFFSET 0x2000 ++#define RT6855_PCIE1_OFFSET 0x3000 ++#define RT6855_PCIE2_OFFSET 0x4000 ++ ++#define RALINK_PCI0_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0010) ++#define RALINK_PCI0_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0018) ++#define RALINK_PCI0_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0030) ++#define RALINK_PCI0_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0034) ++#define RALINK_PCI0_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0038) ++#define RALINK_PCI0_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0050) ++#define RALINK_PCI0_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0060) ++#define RALINK_PCI0_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0064) ++ ++#define RALINK_PCI1_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0010) ++#define RALINK_PCI1_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0018) ++#define RALINK_PCI1_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0030) ++#define RALINK_PCI1_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0034) ++#define RALINK_PCI1_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0038) ++#define RALINK_PCI1_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0050) ++#define RALINK_PCI1_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0060) ++#define RALINK_PCI1_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0064) ++ ++#define RALINK_PCI2_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0010) ++#define RALINK_PCI2_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0018) ++#define RALINK_PCI2_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0030) ++#define RALINK_PCI2_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0034) ++#define RALINK_PCI2_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0038) ++#define RALINK_PCI2_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0050) ++#define RALINK_PCI2_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0060) ++#define RALINK_PCI2_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0064) ++ ++#define RALINK_PCIEPHY_P0P1_CTL_OFFSET (RALINK_PCI_BASE + 0x9000) ++#define RALINK_PCIEPHY_P2_CTL_OFFSET (RALINK_PCI_BASE + 0xA000) ++ ++ ++#define MV_WRITE(ofs, data) \ ++ *(volatile u32 *)(RALINK_PCI_BASE+(ofs)) = cpu_to_le32(data) ++#define MV_READ(ofs, data) \ ++ *(data) = le32_to_cpu(*(volatile u32 *)(RALINK_PCI_BASE+(ofs))) ++#define MV_READ_DATA(ofs) \ ++ le32_to_cpu(*(volatile u32 *)(RALINK_PCI_BASE+(ofs))) ++ ++#define MV_WRITE_16(ofs, data) \ ++ *(volatile u16 *)(RALINK_PCI_BASE+(ofs)) = cpu_to_le16(data) ++#define MV_READ_16(ofs, data) \ ++ *(data) = le16_to_cpu(*(volatile u16 *)(RALINK_PCI_BASE+(ofs))) ++ ++#define MV_WRITE_8(ofs, data) \ ++ *(volatile u8 *)(RALINK_PCI_BASE+(ofs)) = data ++#define MV_READ_8(ofs, data) \ ++ *(data) = *(volatile u8 *)(RALINK_PCI_BASE+(ofs)) ++ ++ ++ ++#define RALINK_PCI_MM_MAP_BASE 0x60000000 ++#define RALINK_PCI_IO_MAP_BASE 0x1e160000 ++ ++#define RALINK_SYSTEM_CONTROL_BASE 0xbe000000 ++#define GPIO_PERST ++#define ASSERT_SYSRST_PCIE(val) do { \ ++ if (*(unsigned int *)(0xbe00000c) == 0x00030101) \ ++ RALINK_RSTCTRL |= val; \ ++ else \ ++ RALINK_RSTCTRL &= ~val; \ ++ } while(0) ++#define DEASSERT_SYSRST_PCIE(val) do { \ ++ if (*(unsigned int *)(0xbe00000c) == 0x00030101) \ ++ RALINK_RSTCTRL &= ~val; \ ++ else \ ++ RALINK_RSTCTRL |= val; \ ++ } while(0) ++#define RALINK_SYSCFG1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x14) ++#define RALINK_CLKCFG1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x30) ++#define RALINK_RSTCTRL *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x34) ++#define RALINK_GPIOMODE *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x60) ++#define RALINK_PCIE_CLK_GEN *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x7c) ++#define RALINK_PCIE_CLK_GEN1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x80) ++#define PPLL_CFG1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x9c) ++#define PPLL_DRV *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0xa0) ++//RALINK_SYSCFG1 bit ++#define RALINK_PCI_HOST_MODE_EN (1<<7) ++#define RALINK_PCIE_RC_MODE_EN (1<<8) ++//RALINK_RSTCTRL bit ++#define RALINK_PCIE_RST (1<<23) ++#define RALINK_PCI_RST (1<<24) ++//RALINK_CLKCFG1 bit ++#define RALINK_PCI_CLK_EN (1<<19) ++#define RALINK_PCIE_CLK_EN (1<<21) ++//RALINK_GPIOMODE bit ++#define PCI_SLOTx2 (1<<11) ++#define PCI_SLOTx1 (2<<11) ++//MTK PCIE PLL bit ++#define PDRV_SW_SET (1<<31) ++#define LC_CKDRVPD_ (1<<19) ++ ++#define MEMORY_BASE 0x0 ++static int pcie_link_status = 0; ++ ++#define PCI_ACCESS_READ_1 0 ++#define PCI_ACCESS_READ_2 1 ++#define PCI_ACCESS_READ_4 2 ++#define PCI_ACCESS_WRITE_1 3 ++#define PCI_ACCESS_WRITE_2 4 ++#define PCI_ACCESS_WRITE_4 5 ++ ++static int pcie_irq[3]; ++ ++static int config_access(unsigned char access_type, struct pci_bus *bus, ++ unsigned int devfn, unsigned int where, u32 * data) ++{ ++ unsigned int slot = PCI_SLOT(devfn); ++ u8 func = PCI_FUNC(devfn); ++ uint32_t address_reg, data_reg; ++ unsigned int address; ++ ++ address_reg = RALINK_PCI_CONFIG_ADDR; ++ data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG; ++ ++ address = (((where&0xF00)>>8)<<24) |(bus->number << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | 0x80000000; ++ MV_WRITE(address_reg, address); ++ ++ switch(access_type) { ++ case PCI_ACCESS_WRITE_1: ++ MV_WRITE_8(data_reg+(where&0x3), *data); ++ break; ++ case PCI_ACCESS_WRITE_2: ++ MV_WRITE_16(data_reg+(where&0x3), *data); ++ break; ++ case PCI_ACCESS_WRITE_4: ++ MV_WRITE(data_reg, *data); ++ break; ++ case PCI_ACCESS_READ_1: ++ MV_READ_8( data_reg+(where&0x3), data); ++ break; ++ case PCI_ACCESS_READ_2: ++ MV_READ_16(data_reg+(where&0x3), data); ++ break; ++ case PCI_ACCESS_READ_4: ++ MV_READ(data_reg, data); ++ break; ++ default: ++ printk("no specify access type\n"); ++ break; ++ } ++ return 0; ++} ++ ++static int ++read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 * val) ++{ ++ return config_access(PCI_ACCESS_READ_1, bus, devfn, (unsigned int)where, (u32 *)val); ++} ++ ++static int ++read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 * val) ++{ ++ return config_access(PCI_ACCESS_READ_2, bus, devfn, (unsigned int)where, (u32 *)val); ++} ++ ++static int ++read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 * val) ++{ ++ return config_access(PCI_ACCESS_READ_4, bus, devfn, (unsigned int)where, (u32 *)val); ++} ++ ++static int ++write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val) ++{ ++ if (config_access(PCI_ACCESS_WRITE_1, bus, devfn, (unsigned int)where, (u32 *)&val)) ++ return -1; ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int ++write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val) ++{ ++ if (config_access(PCI_ACCESS_WRITE_2, bus, devfn, where, (u32 *)&val)) ++ return -1; ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int ++write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val) ++{ ++ if (config_access(PCI_ACCESS_WRITE_4, bus, devfn, where, &val)) ++ return -1; ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++ ++static int ++pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) ++{ ++ switch (size) { ++ case 1: ++ return read_config_byte(bus, devfn, where, (u8 *) val); ++ case 2: ++ return read_config_word(bus, devfn, where, (u16 *) val); ++ default: ++ return read_config_dword(bus, devfn, where, val); ++ } ++} ++ ++static int ++pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) ++{ ++ switch (size) { ++ case 1: ++ return write_config_byte(bus, devfn, where, (u8) val); ++ case 2: ++ return write_config_word(bus, devfn, where, (u16) val); ++ default: ++ return write_config_dword(bus, devfn, where, val); ++ } ++} ++ ++struct pci_ops mt7621_pci_ops= { ++ .read = pci_config_read, ++ .write = pci_config_write, ++}; ++ ++static struct resource mt7621_res_pci_mem1 = { ++ .name = "PCI MEM1", ++ .start = RALINK_PCI_MM_MAP_BASE, ++ .end = (u32)((RALINK_PCI_MM_MAP_BASE + (unsigned char *)0x0fffffff)), ++ .flags = IORESOURCE_MEM, ++}; ++static struct resource mt7621_res_pci_io1 = { ++ .name = "PCI I/O1", ++ .start = RALINK_PCI_IO_MAP_BASE, ++ .end = (u32)((RALINK_PCI_IO_MAP_BASE + (unsigned char *)0x0ffff)), ++ .flags = IORESOURCE_IO, ++}; ++ ++static struct pci_controller mt7621_controller = { ++ .pci_ops = &mt7621_pci_ops, ++ .mem_resource = &mt7621_res_pci_mem1, ++ .io_resource = &mt7621_res_pci_io1, ++ .mem_offset = 0x00000000UL, ++ .io_offset = 0x00000000UL, ++ .io_map_base = 0xa0000000, ++}; ++ ++static void ++read_config(unsigned long bus, unsigned long dev, unsigned long func, unsigned long reg, unsigned long *val) ++{ ++ unsigned int address_reg, data_reg, address; ++ ++ address_reg = RALINK_PCI_CONFIG_ADDR; ++ data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG; ++ address = (((reg & 0xF00)>>8)<<24) | (bus << 16) | (dev << 11) | (func << 8) | (reg & 0xfc) | 0x80000000 ; ++ MV_WRITE(address_reg, address); ++ MV_READ(data_reg, val); ++ return; ++} ++ ++static void ++write_config(unsigned long bus, unsigned long dev, unsigned long func, unsigned long reg, unsigned long val) ++{ ++ unsigned int address_reg, data_reg, address; ++ ++ address_reg = RALINK_PCI_CONFIG_ADDR; ++ data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG; ++ address = (((reg & 0xF00)>>8)<<24) | (bus << 16) | (dev << 11) | (func << 8) | (reg & 0xfc) | 0x80000000 ; ++ MV_WRITE(address_reg, address); ++ MV_WRITE(data_reg, val); ++ return; ++} ++ ++ ++int ++pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ u16 cmd; ++ u32 val; ++ int irq = 0; ++ ++ if ((dev->bus->number == 0) && (slot == 0)) { ++ write_config(0, 0, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE); ++ read_config(0, 0, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val); ++ printk("BAR0 at slot 0 = %x\n", val); ++ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); ++ } else if((dev->bus->number == 0) && (slot == 0x1)) { ++ write_config(0, 1, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE); ++ read_config(0, 1, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val); ++ printk("BAR0 at slot 1 = %x\n", val); ++ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); ++ } else if((dev->bus->number == 0) && (slot == 0x2)) { ++ write_config(0, 2, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE); ++ read_config(0, 2, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val); ++ printk("BAR0 at slot 2 = %x\n", val); ++ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); ++ } else if ((dev->bus->number == 1) && (slot == 0x0)) { ++ switch (pcie_link_status) { ++ case 2: ++ case 6: ++ irq = RALINK_INT_PCIE1; ++ break; ++ case 4: ++ irq = RALINK_INT_PCIE2; ++ break; ++ default: ++ irq = RALINK_INT_PCIE0; ++ } ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else if ((dev->bus->number == 2) && (slot == 0x0)) { ++ switch (pcie_link_status) { ++ case 5: ++ case 6: ++ irq = RALINK_INT_PCIE2; ++ break; ++ default: ++ irq = RALINK_INT_PCIE1; ++ } ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else if ((dev->bus->number == 2) && (slot == 0x1)) { ++ switch (pcie_link_status) { ++ case 5: ++ case 6: ++ irq = RALINK_INT_PCIE2; ++ break; ++ default: ++ irq = RALINK_INT_PCIE1; ++ } ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else if ((dev->bus->number ==3) && (slot == 0x0)) { ++ irq = RALINK_INT_PCIE2; ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else if ((dev->bus->number ==3) && (slot == 0x1)) { ++ irq = RALINK_INT_PCIE2; ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else if ((dev->bus->number ==3) && (slot == 0x2)) { ++ irq = RALINK_INT_PCIE2; ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else { ++ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); ++ return 0; ++ } ++ ++ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x14); //configure cache line size 0x14 ++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xFF); //configure latency timer 0x10 ++ pci_read_config_word(dev, PCI_COMMAND, &cmd); ++ cmd = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; ++ pci_write_config_word(dev, PCI_COMMAND, cmd); ++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); ++ return irq; ++} ++ ++void ++set_pcie_phy(u32 *addr, int start_b, int bits, int val) ++{ ++// printk("0x%p:", addr); ++// printk(" %x", *addr); ++ *(unsigned int *)(addr) &= ~(((1< %x\n", *addr); ++} ++ ++void ++bypass_pipe_rst(void) ++{ ++#if defined (CONFIG_PCIE_PORT0) ++ /* PCIe Port 0 */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x02c), 12, 1, 0x01); // rg_pe1_pipe_rst_b ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x02c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4] ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ /* PCIe Port 1 */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x12c), 12, 1, 0x01); // rg_pe1_pipe_rst_b ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x12c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4] ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ /* PCIe Port 2 */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x02c), 12, 1, 0x01); // rg_pe1_pipe_rst_b ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x02c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4] ++#endif ++} ++ ++void ++set_phy_for_ssc(void) ++{ ++ unsigned long reg = (*(volatile u32 *)(RALINK_SYSCTL_BASE + 0x10)); ++ ++ reg = (reg >> 6) & 0x7; ++#if defined (CONFIG_PCIE_PORT0) || defined (CONFIG_PCIE_PORT1) ++ /* Set PCIe Port0 & Port1 PHY to disable SSC */ ++ /* Debug Xtal Type */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x400), 8, 1, 0x01); // rg_pe1_frc_h_xtal_type ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x400), 9, 2, 0x00); // rg_pe1_h_xtal_type ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 0 enable control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 1 enable control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 5, 1, 0x00); // rg_pe1_phy_en //Port 0 disable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 5, 1, 0x00); // rg_pe1_phy_en //Port 1 disable ++ if(reg <= 5 && reg >= 3) { // 40MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 6, 2, 0x01); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode) ++ printk("***** Xtal 40MHz *****\n"); ++ } else { // 25MHz | 20MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 6, 2, 0x00); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode) ++ if (reg >= 6) { ++ printk("***** Xtal 25MHz *****\n"); ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4bc), 4, 2, 0x01); // RG_PE1_H_PLL_FBKSEL //Feedback clock select ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x49c), 0,31, 0x18000000); // RG_PE1_H_LCDDS_PCW_NCPO //DDS NCPO PCW (for host mode) ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a4), 0,16, 0x18d); // RG_PE1_H_LCDDS_SSC_PRD //DDS SSC dither period control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 0,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA //DDS SSC dither amplitude control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 16,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA1 //DDS SSC dither amplitude control for initial ++ } else { ++ printk("***** Xtal 20MHz *****\n"); ++ } ++ } ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a0), 5, 1, 0x01); // RG_PE1_LCDDS_CLK_PH_INV //DDS clock inversion ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 22, 2, 0x02); // RG_PE1_H_PLL_BC ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 18, 4, 0x06); // RG_PE1_H_PLL_BP ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 12, 4, 0x02); // RG_PE1_H_PLL_IR ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 8, 4, 0x01); // RG_PE1_H_PLL_IC ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4ac), 16, 3, 0x00); // RG_PE1_H_PLL_BR ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 1, 3, 0x02); // RG_PE1_PLL_DIVEN ++ if(reg <= 5 && reg >= 3) { // 40MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x414), 6, 2, 0x01); // rg_pe1_mstckdiv //value of da_pe1_mstckdiv when force mode enable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x414), 5, 1, 0x01); // rg_pe1_frc_mstckdiv //force mode enable of da_pe1_mstckdiv ++ } ++ /* Enable PHY and disable force mode */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 5, 1, 0x01); // rg_pe1_phy_en //Port 0 enable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 5, 1, 0x01); // rg_pe1_phy_en //Port 1 enable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 0 disable control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 1 disable control ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ /* Set PCIe Port2 PHY to disable SSC */ ++ /* Debug Xtal Type */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x400), 8, 1, 0x01); // rg_pe1_frc_h_xtal_type ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x400), 9, 2, 0x00); // rg_pe1_h_xtal_type ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 0 enable control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 5, 1, 0x00); // rg_pe1_phy_en //Port 0 disable ++ if(reg <= 5 && reg >= 3) { // 40MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 6, 2, 0x01); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode) ++ } else { // 25MHz | 20MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 6, 2, 0x00); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode) ++ if (reg >= 6) { // 25MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4bc), 4, 2, 0x01); // RG_PE1_H_PLL_FBKSEL //Feedback clock select ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x49c), 0,31, 0x18000000); // RG_PE1_H_LCDDS_PCW_NCPO //DDS NCPO PCW (for host mode) ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a4), 0,16, 0x18d); // RG_PE1_H_LCDDS_SSC_PRD //DDS SSC dither period control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 0,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA //DDS SSC dither amplitude control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 16,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA1 //DDS SSC dither amplitude control for initial ++ } ++ } ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a0), 5, 1, 0x01); // RG_PE1_LCDDS_CLK_PH_INV //DDS clock inversion ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 22, 2, 0x02); // RG_PE1_H_PLL_BC ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 18, 4, 0x06); // RG_PE1_H_PLL_BP ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 12, 4, 0x02); // RG_PE1_H_PLL_IR ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 8, 4, 0x01); // RG_PE1_H_PLL_IC ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4ac), 16, 3, 0x00); // RG_PE1_H_PLL_BR ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 1, 3, 0x02); // RG_PE1_PLL_DIVEN ++ if(reg <= 5 && reg >= 3) { // 40MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x414), 6, 2, 0x01); // rg_pe1_mstckdiv //value of da_pe1_mstckdiv when force mode enable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x414), 5, 1, 0x01); // rg_pe1_frc_mstckdiv //force mode enable of da_pe1_mstckdiv ++ } ++ /* Enable PHY and disable force mode */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 5, 1, 0x01); // rg_pe1_phy_en //Port 0 enable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 0 disable control ++#endif ++} ++ ++void setup_cm_memory_region(struct resource *mem_resource) ++{ ++ resource_size_t mask; ++ if (mips_cps_numiocu(0)) { ++ /* FIXME: hardware doesn't accept mask values with 1s after ++ 0s (e.g. 0xffef), so it would be great to warn if that's ++ about to happen */ ++ mask = ~(mem_resource->end - mem_resource->start); ++ ++ write_gcr_reg1_base(mem_resource->start); ++ write_gcr_reg1_mask(mask | CM_GCR_REGn_MASK_CMTGT_IOCU0); ++ printk("PCI coherence region base: 0x%08lx, mask/settings: 0x%08lx\n", ++ read_gcr_reg1_base(), ++ read_gcr_reg1_mask()); ++ } ++} ++ ++static int mt7621_pci_probe(struct platform_device *pdev) ++{ ++ unsigned long val = 0; ++ int i; ++ ++ for (i = 0; i < 3; i++) ++ pcie_irq[i] = irq_of_parse_and_map(pdev->dev.of_node, i); ++ ++ iomem_resource.start = 0; ++ iomem_resource.end= ~0; ++ ioport_resource.start= 0; ++ ioport_resource.end = ~0; ++ ++#if defined (CONFIG_PCIE_PORT0) ++ val = RALINK_PCIE0_RST; ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ val |= RALINK_PCIE1_RST; ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ val |= RALINK_PCIE2_RST; ++#endif ++ ASSERT_SYSRST_PCIE(RALINK_PCIE0_RST | RALINK_PCIE1_RST | RALINK_PCIE2_RST); ++ printk("pull PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL); ++#if defined GPIO_PERST /* add GPIO control instead of PERST_N */ /*chhung*/ ++ *(unsigned int *)(0xbe000060) &= ~(0x3<<10 | 0x3<<3); ++ *(unsigned int *)(0xbe000060) |= 0x1<<10 | 0x1<<3; ++ mdelay(100); ++ *(unsigned int *)(0xbe000600) |= 0x1<<19 | 0x1<<8 | 0x1<<7; // use GPIO19/GPIO8/GPIO7 (PERST_N/UART_RXD3/UART_TXD3) ++ mdelay(100); ++ *(unsigned int *)(0xbe000620) &= ~(0x1<<19 | 0x1<<8 | 0x1<<7); // clear DATA ++ ++ mdelay(100); ++#else ++ *(unsigned int *)(0xbe000060) &= ~0x00000c00; ++#endif ++#if defined (CONFIG_PCIE_PORT0) ++ val = RALINK_PCIE0_RST; ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ val |= RALINK_PCIE1_RST; ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ val |= RALINK_PCIE2_RST; ++#endif ++ DEASSERT_SYSRST_PCIE(val); ++ printk("release PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL); ++ ++ if ((*(unsigned int *)(0xbe00000c)&0xFFFF) == 0x0101) // MT7621 E2 ++ bypass_pipe_rst(); ++ set_phy_for_ssc(); ++ printk("release PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL); ++ ++#if defined (CONFIG_PCIE_PORT0) ++ read_config(0, 0, 0, 0x70c, &val); ++ printk("Port 0 N_FTS = %x\n", (unsigned int)val); ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ read_config(0, 1, 0, 0x70c, &val); ++ printk("Port 1 N_FTS = %x\n", (unsigned int)val); ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ read_config(0, 2, 0, 0x70c, &val); ++ printk("Port 2 N_FTS = %x\n", (unsigned int)val); ++#endif ++ ++ RALINK_RSTCTRL = (RALINK_RSTCTRL | RALINK_PCIE_RST); ++ RALINK_SYSCFG1 &= ~(0x30); ++ RALINK_SYSCFG1 |= (2<<4); ++ RALINK_PCIE_CLK_GEN &= 0x7fffffff; ++ RALINK_PCIE_CLK_GEN1 &= 0x80ffffff; ++ RALINK_PCIE_CLK_GEN1 |= 0xa << 24; ++ RALINK_PCIE_CLK_GEN |= 0x80000000; ++ mdelay(50); ++ RALINK_RSTCTRL = (RALINK_RSTCTRL & ~RALINK_PCIE_RST); ++ ++ ++#if defined GPIO_PERST /* add GPIO control instead of PERST_N */ /*chhung*/ ++ *(unsigned int *)(0xbe000620) |= 0x1<<19 | 0x1<<8 | 0x1<<7; // set DATA ++ mdelay(100); ++#else ++ RALINK_PCI_PCICFG_ADDR &= ~(1<<1); //de-assert PERST ++#endif ++ mdelay(500); ++ ++ ++ mdelay(500); ++#if defined (CONFIG_PCIE_PORT0) ++ if(( RALINK_PCI0_STATUS & 0x1) == 0) ++ { ++ printk("PCIE0 no card, disable it(RST&CLK)\n"); ++ ASSERT_SYSRST_PCIE(RALINK_PCIE0_RST); ++ RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE0_CLK_EN); ++ pcie_link_status &= ~(1<<0); ++ } else { ++ pcie_link_status |= 1<<0; ++ RALINK_PCI_PCIMSK_ADDR |= (1<<20); // enable pcie1 interrupt ++ } ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ if(( RALINK_PCI1_STATUS & 0x1) == 0) ++ { ++ printk("PCIE1 no card, disable it(RST&CLK)\n"); ++ ASSERT_SYSRST_PCIE(RALINK_PCIE1_RST); ++ RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE1_CLK_EN); ++ pcie_link_status &= ~(1<<1); ++ } else { ++ pcie_link_status |= 1<<1; ++ RALINK_PCI_PCIMSK_ADDR |= (1<<21); // enable pcie1 interrupt ++ } ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ if (( RALINK_PCI2_STATUS & 0x1) == 0) { ++ printk("PCIE2 no card, disable it(RST&CLK)\n"); ++ ASSERT_SYSRST_PCIE(RALINK_PCIE2_RST); ++ RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE2_CLK_EN); ++ pcie_link_status &= ~(1<<2); ++ } else { ++ pcie_link_status |= 1<<2; ++ RALINK_PCI_PCIMSK_ADDR |= (1<<22); // enable pcie2 interrupt ++ } ++#endif ++ if (pcie_link_status == 0) ++ return 0; ++ ++/* ++pcie(2/1/0) link status pcie2_num pcie1_num pcie0_num ++3'b000 x x x ++3'b001 x x 0 ++3'b010 x 0 x ++3'b011 x 1 0 ++3'b100 0 x x ++3'b101 1 x 0 ++3'b110 1 0 x ++3'b111 2 1 0 ++*/ ++ switch(pcie_link_status) { ++ case 2: ++ RALINK_PCI_PCICFG_ADDR &= ~0x00ff0000; ++ RALINK_PCI_PCICFG_ADDR |= 0x1 << 16; //port0 ++ RALINK_PCI_PCICFG_ADDR |= 0x0 << 20; //port1 ++ break; ++ case 4: ++ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000; ++ RALINK_PCI_PCICFG_ADDR |= 0x1 << 16; //port0 ++ RALINK_PCI_PCICFG_ADDR |= 0x2 << 20; //port1 ++ RALINK_PCI_PCICFG_ADDR |= 0x0 << 24; //port2 ++ break; ++ case 5: ++ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000; ++ RALINK_PCI_PCICFG_ADDR |= 0x0 << 16; //port0 ++ RALINK_PCI_PCICFG_ADDR |= 0x2 << 20; //port1 ++ RALINK_PCI_PCICFG_ADDR |= 0x1 << 24; //port2 ++ break; ++ case 6: ++ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000; ++ RALINK_PCI_PCICFG_ADDR |= 0x2 << 16; //port0 ++ RALINK_PCI_PCICFG_ADDR |= 0x0 << 20; //port1 ++ RALINK_PCI_PCICFG_ADDR |= 0x1 << 24; //port2 ++ break; ++ } ++ printk(" -> %x\n", RALINK_PCI_PCICFG_ADDR); ++ //printk(" RALINK_PCI_ARBCTL = %x\n", RALINK_PCI_ARBCTL); ++ ++/* ++ ioport_resource.start = mt7621_res_pci_io1.start; ++ ioport_resource.end = mt7621_res_pci_io1.end; ++*/ ++ ++ RALINK_PCI_MEMBASE = 0xffffffff; //RALINK_PCI_MM_MAP_BASE; ++ RALINK_PCI_IOBASE = RALINK_PCI_IO_MAP_BASE; ++ ++#if defined (CONFIG_PCIE_PORT0) ++ //PCIe0 ++ if((pcie_link_status & 0x1) != 0) { ++ RALINK_PCI0_BAR0SETUP_ADDR = 0x7FFF0001; //open 7FFF:2G; ENABLE ++ RALINK_PCI0_IMBASEBAR0_ADDR = MEMORY_BASE; ++ RALINK_PCI0_CLASS = 0x06040001; ++ printk("PCIE0 enabled\n"); ++ } ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ //PCIe1 ++ if ((pcie_link_status & 0x2) != 0) { ++ RALINK_PCI1_BAR0SETUP_ADDR = 0x7FFF0001; //open 7FFF:2G; ENABLE ++ RALINK_PCI1_IMBASEBAR0_ADDR = MEMORY_BASE; ++ RALINK_PCI1_CLASS = 0x06040001; ++ printk("PCIE1 enabled\n"); ++ } ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ //PCIe2 ++ if ((pcie_link_status & 0x4) != 0) { ++ RALINK_PCI2_BAR0SETUP_ADDR = 0x7FFF0001; //open 7FFF:2G; ENABLE ++ RALINK_PCI2_IMBASEBAR0_ADDR = MEMORY_BASE; ++ RALINK_PCI2_CLASS = 0x06040001; ++ printk("PCIE2 enabled\n"); ++ } ++#endif ++ ++ ++ switch(pcie_link_status) { ++ case 7: ++ read_config(0, 2, 0, 0x4, &val); ++ write_config(0, 2, 0, 0x4, val|0x4); ++ // write_config(0, 1, 0, 0x4, val|0x7); ++ read_config(0, 2, 0, 0x70c, &val); ++ val &= ~(0xff)<<8; ++ val |= 0x50<<8; ++ write_config(0, 2, 0, 0x70c, val); ++ case 3: ++ case 5: ++ case 6: ++ read_config(0, 1, 0, 0x4, &val); ++ write_config(0, 1, 0, 0x4, val|0x4); ++ // write_config(0, 1, 0, 0x4, val|0x7); ++ read_config(0, 1, 0, 0x70c, &val); ++ val &= ~(0xff)<<8; ++ val |= 0x50<<8; ++ write_config(0, 1, 0, 0x70c, val); ++ default: ++ read_config(0, 0, 0, 0x4, &val); ++ write_config(0, 0, 0, 0x4, val|0x4); //bus master enable ++ // write_config(0, 0, 0, 0x4, val|0x7); //bus master enable ++ read_config(0, 0, 0, 0x70c, &val); ++ val &= ~(0xff)<<8; ++ val |= 0x50<<8; ++ write_config(0, 0, 0, 0x70c, val); ++ } ++ ++ pci_load_of_ranges(&mt7621_controller, pdev->dev.of_node); ++ setup_cm_memory_region(mt7621_controller.mem_resource); ++ register_pci_controller(&mt7621_controller); ++ return 0; ++ ++} ++ ++int pcibios_plat_dev_init(struct pci_dev *dev) ++{ ++ return 0; ++} ++ ++static const struct of_device_id mt7621_pci_ids[] = { ++ { .compatible = "mediatek,mt7621-pci" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mt7621_pci_ids); ++ ++static struct platform_driver mt7621_pci_driver = { ++ .probe = mt7621_pci_probe, ++ .driver = { ++ .name = "mt7621-pci", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(mt7621_pci_ids), ++ }, ++}; ++ ++static int __init mt7621_pci_init(void) ++{ ++ return platform_driver_register(&mt7621_pci_driver); ++} ++ ++arch_initcall(mt7621_pci_init); diff --git a/target/linux/ramips/patches-4.14/0005-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch b/target/linux/ramips/patches-4.14/0005-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch new file mode 100644 index 000000000..773c74f4e --- /dev/null +++ b/target/linux/ramips/patches-4.14/0005-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch @@ -0,0 +1,82 @@ +From ce3d4a4111a5f7e6b4e74bceae5faa6ce388e8ec Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 14 Jul 2013 23:08:11 +0200 +Subject: [PATCH 05/53] MIPS: use set_mode() to enable/disable the cevt-r4k + irq + +Signed-off-by: John Crispin +--- + arch/mips/ralink/Kconfig | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -1,12 +1,17 @@ + # SPDX-License-Identifier: GPL-2.0 + if RALINK + ++config CEVT_SYSTICK_QUIRK ++ bool ++ default n ++ + config CLKEVT_RT3352 + bool + depends on SOC_RT305X || SOC_MT7620 + default y + select TIMER_OF + select CLKSRC_MMIO ++ select CEVT_SYSTICK_QUIRK + + config RALINK_ILL_ACC + bool +--- a/arch/mips/kernel/cevt-r4k.c ++++ b/arch/mips/kernel/cevt-r4k.c +@@ -15,6 +15,26 @@ + #include + #include + ++static int mips_state_oneshot(struct clock_event_device *evt) ++{ ++ if (!cp0_timer_irq_installed) { ++ cp0_timer_irq_installed = 1; ++ setup_irq(evt->irq, &c0_compare_irqaction); ++ } ++ ++ return 0; ++} ++ ++static int mips_state_shutdown(struct clock_event_device *evt) ++{ ++ if (cp0_timer_irq_installed) { ++ cp0_timer_irq_installed = 0; ++ remove_irq(evt->irq, &c0_compare_irqaction); ++ } ++ ++ return 0; ++} ++ + static int mips_next_event(unsigned long delta, + struct clock_event_device *evt) + { +@@ -281,17 +301,21 @@ int r4k_clockevent_init(void) + cd->rating = 300; + cd->irq = irq; + cd->cpumask = cpumask_of(cpu); ++ cd->set_state_shutdown = mips_state_shutdown; ++ cd->set_state_oneshot = mips_state_oneshot; + cd->set_next_event = mips_next_event; + cd->event_handler = mips_event_handler; + + clockevents_config_and_register(cd, mips_hpt_frequency, min_delta, 0x7fffffff); + ++#ifndef CONFIG_CEVT_SYSTICK_QUIRK + if (cp0_timer_irq_installed) + return 0; + + cp0_timer_irq_installed = 1; + + setup_irq(irq, &c0_compare_irqaction); ++#endif + + return 0; + } diff --git a/target/linux/ramips/patches-4.14/0006-MIPS-ralink-add-cpu-frequency-scaling.patch b/target/linux/ramips/patches-4.14/0006-MIPS-ralink-add-cpu-frequency-scaling.patch new file mode 100644 index 000000000..90215fbf8 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0006-MIPS-ralink-add-cpu-frequency-scaling.patch @@ -0,0 +1,200 @@ +From bd30f19a006fb52bac80c6463c49dd2f4159f4ac Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 28 Jul 2013 16:26:41 +0200 +Subject: [PATCH 06/53] MIPS: ralink: add cpu frequency scaling + +This feature will break udelay() and cause the delay loop to have longer delays +when the frequency is scaled causing a performance hit. + +Signed-off-by: John Crispin +--- + arch/mips/ralink/cevt-rt3352.c | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +--- a/arch/mips/ralink/cevt-rt3352.c ++++ b/arch/mips/ralink/cevt-rt3352.c +@@ -29,6 +29,10 @@ + /* enable the counter */ + #define CFG_CNT_EN 0x1 + ++/* mt7620 frequency scaling defines */ ++#define CLK_LUT_CFG 0x40 ++#define SLEEP_EN BIT(31) ++ + struct systick_device { + void __iomem *membase; + struct clock_event_device dev; +@@ -36,21 +40,53 @@ struct systick_device { + int freq_scale; + }; + ++static void (*systick_freq_scaling)(struct systick_device *sdev, int status); ++ + static int systick_set_oneshot(struct clock_event_device *evt); + static int systick_shutdown(struct clock_event_device *evt); + ++static inline void mt7620_freq_scaling(struct systick_device *sdev, int status) ++{ ++ if (sdev->freq_scale == status) ++ return; ++ ++ sdev->freq_scale = status; ++ ++ pr_info("%s: %s autosleep mode\n", sdev->dev.name, ++ (status) ? ("enable") : ("disable")); ++ if (status) ++ rt_sysc_w32(rt_sysc_r32(CLK_LUT_CFG) | SLEEP_EN, CLK_LUT_CFG); ++ else ++ rt_sysc_w32(rt_sysc_r32(CLK_LUT_CFG) & ~SLEEP_EN, CLK_LUT_CFG); ++} ++ ++static inline unsigned int read_count(struct systick_device *sdev) ++{ ++ return ioread32(sdev->membase + SYSTICK_COUNT); ++} ++ ++static inline unsigned int read_compare(struct systick_device *sdev) ++{ ++ return ioread32(sdev->membase + SYSTICK_COMPARE); ++} ++ ++static inline void write_compare(struct systick_device *sdev, unsigned int val) ++{ ++ iowrite32(val, sdev->membase + SYSTICK_COMPARE); ++} ++ + static int systick_next_event(unsigned long delta, + struct clock_event_device *evt) + { + struct systick_device *sdev; +- u32 count; ++ int res; + + sdev = container_of(evt, struct systick_device, dev); +- count = ioread32(sdev->membase + SYSTICK_COUNT); +- count = (count + delta) % SYSTICK_FREQ; +- iowrite32(count, sdev->membase + SYSTICK_COMPARE); ++ delta += read_count(sdev); ++ write_compare(sdev, delta); ++ res = ((int)(read_count(sdev) - delta) >= 0) ? -ETIME : 0; + +- return 0; ++ return res; + } + + static void systick_event_handler(struct clock_event_device *dev) +@@ -60,20 +96,25 @@ static void systick_event_handler(struct + + static irqreturn_t systick_interrupt(int irq, void *dev_id) + { +- struct clock_event_device *dev = (struct clock_event_device *) dev_id; ++ int ret = 0; ++ struct clock_event_device *cdev; ++ struct systick_device *sdev; + +- dev->event_handler(dev); ++ if (read_c0_cause() & STATUSF_IP7) { ++ cdev = (struct clock_event_device *) dev_id; ++ sdev = container_of(cdev, struct systick_device, dev); ++ ++ /* Clear Count/Compare Interrupt */ ++ write_compare(sdev, read_compare(sdev)); ++ cdev->event_handler(cdev); ++ ret = 1; ++ } + +- return IRQ_HANDLED; ++ return IRQ_RETVAL(ret); + } + + static struct systick_device systick = { + .dev = { +- /* +- * cevt-r4k uses 300, make sure systick +- * gets used if available +- */ +- .rating = 310, + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = systick_next_event, + .set_state_shutdown = systick_shutdown, +@@ -95,9 +136,15 @@ static int systick_shutdown(struct clock + sdev = container_of(evt, struct systick_device, dev); + + if (sdev->irq_requested) +- free_irq(systick.dev.irq, &systick_irqaction); ++ remove_irq(systick.dev.irq, &systick_irqaction); + sdev->irq_requested = 0; +- iowrite32(0, systick.membase + SYSTICK_CONFIG); ++ iowrite32(CFG_CNT_EN, systick.membase + SYSTICK_CONFIG); ++ ++ if (systick_freq_scaling) ++ systick_freq_scaling(sdev, 0); ++ ++ if (systick_freq_scaling) ++ systick_freq_scaling(sdev, 1); + + return 0; + } +@@ -117,34 +164,48 @@ static int systick_set_oneshot(struct cl + return 0; + } + ++static const struct of_device_id systick_match[] = { ++ { .compatible = "ralink,mt7620a-systick", .data = mt7620_freq_scaling}, ++ {}, ++}; ++ + static int __init ralink_systick_init(struct device_node *np) + { ++ const struct of_device_id *match; ++ int rating = 200; + int ret; + + systick.membase = of_iomap(np, 0); + if (!systick.membase) + return -ENXIO; + +- systick_irqaction.name = np->name; +- systick.dev.name = np->name; +- clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60); +- systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev); +- systick.dev.max_delta_ticks = 0x7fff; +- systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev); +- systick.dev.min_delta_ticks = 0x3; ++ match = of_match_node(systick_match, np); ++ if (match) { ++ systick_freq_scaling = match->data; ++ /* ++ * cevt-r4k uses 300, make sure systick ++ * gets used if available ++ */ ++ rating = 310; ++ } ++ ++ /* enable counter than register clock source */ ++ iowrite32(CFG_CNT_EN, systick.membase + SYSTICK_CONFIG); ++ clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name, ++ SYSTICK_FREQ, rating, 16, clocksource_mmio_readl_up); ++ ++ /* register clock event */ + systick.dev.irq = irq_of_parse_and_map(np, 0); + if (!systick.dev.irq) { + pr_err("%s: request_irq failed", np->name); + return -EINVAL; + } + +- ret = clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name, +- SYSTICK_FREQ, 301, 16, +- clocksource_mmio_readl_up); +- if (ret) +- return ret; +- +- clockevents_register_device(&systick.dev); ++ systick_irqaction.name = np->name; ++ systick.dev.name = np->name; ++ systick.dev.rating = rating; ++ systick.dev.cpumask = cpumask_of(0); ++ clockevents_config_and_register(&systick.dev, SYSTICK_FREQ, 0x3, 0x7fff); + + pr_info("%s: running - mult: %d, shift: %d\n", + np->name, systick.dev.mult, systick.dev.shift); diff --git a/target/linux/ramips/patches-4.14/0007-MIPS-ralink-copy-the-commandline-from-the-devicetree.patch b/target/linux/ramips/patches-4.14/0007-MIPS-ralink-copy-the-commandline-from-the-devicetree.patch new file mode 100644 index 000000000..c05ee8018 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0007-MIPS-ralink-copy-the-commandline-from-the-devicetree.patch @@ -0,0 +1,21 @@ +From 67b7bff0fd364c194e653f69baa623ba2141bd4c Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 4 Aug 2014 18:46:02 +0200 +Subject: [PATCH 07/53] MIPS: ralink: copy the commandline from the devicetree + +Signed-off-by: John Crispin +--- + arch/mips/ralink/of.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -82,6 +82,8 @@ void __init plat_mem_setup(void) + + __dt_setup_arch(dtb); + ++ strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); ++ + of_scan_flat_dt(early_init_dt_find_memory, NULL); + if (memory_dtb) + of_scan_flat_dt(early_init_dt_scan_memory, NULL); diff --git a/target/linux/ramips/patches-4.14/0009-PCI-MIPS-enable-PCIe-on-MT7688.patch b/target/linux/ramips/patches-4.14/0009-PCI-MIPS-enable-PCIe-on-MT7688.patch new file mode 100644 index 000000000..6ca15fe32 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0009-PCI-MIPS-enable-PCIe-on-MT7688.patch @@ -0,0 +1,28 @@ +From 7768798964eb0e4f95eaecffb93b5d0ca28a38af Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sat, 3 Jun 2017 20:00:03 +0200 +Subject: [PATCH] MIPS: pci-mt7620: enabled PCIe on MT7688 +To: linux-mips@linux-mips.org, + John Crispin +Cc: Wei Yongjun , + Ralf Baechle , + linux-mediatek@lists.infradead.org + +Use PCIe support for MT7628AN also on MT7688. +Tested on WRTNODE2R. + +Signed-off-by: Daniel Golle +--- + arch/mips/pci/pci-mt7620.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/mips/pci/pci-mt7620.c ++++ b/arch/mips/pci/pci-mt7620.c +@@ -316,6 +316,7 @@ static int mt7620_pci_probe(struct platf + break; + + case MT762X_SOC_MT7628AN: ++ case MT762X_SOC_MT7688: + if (mt7628_pci_hw_init(pdev)) + return -1; + break; diff --git a/target/linux/ramips/patches-4.14/0013-owrt-hack-fix-mt7688-cache-issue.patch b/target/linux/ramips/patches-4.14/0013-owrt-hack-fix-mt7688-cache-issue.patch new file mode 100644 index 000000000..442f3180a --- /dev/null +++ b/target/linux/ramips/patches-4.14/0013-owrt-hack-fix-mt7688-cache-issue.patch @@ -0,0 +1,28 @@ +From 5ede027f6c4a57ed25da872420508b7f1168b36b Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 7 Dec 2015 17:15:32 +0100 +Subject: [PATCH 13/53] owrt: hack: fix mt7688 cache issue + +Signed-off-by: John Crispin +--- + arch/mips/kernel/setup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/mips/kernel/setup.c ++++ b/arch/mips/kernel/setup.c +@@ -910,7 +910,6 @@ static void __init arch_mem_init(char ** + crashk_res.end - crashk_res.start + 1, + BOOTMEM_DEFAULT); + #endif +- device_tree_init(); + sparse_init(); + plat_swiotlb_setup(); + +@@ -1026,6 +1025,7 @@ void __init setup_arch(char **cmdline_p) + + cpu_cache_init(); + paging_init(); ++ device_tree_init(); + } + + unsigned long kernelsp[NR_CPUS]; diff --git a/target/linux/ramips/patches-4.14/0015-arch-mips-do-not-select-illegal-access-driver-by-def.patch b/target/linux/ramips/patches-4.14/0015-arch-mips-do-not-select-illegal-access-driver-by-def.patch new file mode 100644 index 000000000..1dc54ccf2 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0015-arch-mips-do-not-select-illegal-access-driver-by-def.patch @@ -0,0 +1,25 @@ +From 9e6ce539092a1dd605a20bf73c655a9de58d8641 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 7 Dec 2015 17:18:05 +0100 +Subject: [PATCH 15/53] arch: mips: do not select illegal access driver by + default + +Signed-off-by: John Crispin +--- + arch/mips/ralink/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -14,9 +14,9 @@ config CLKEVT_RT3352 + select CEVT_SYSTICK_QUIRK + + config RALINK_ILL_ACC +- bool ++ bool "illegal access irq" + depends on SOC_RT305X +- default y ++ default n + + config IRQ_INTC + bool diff --git a/target/linux/ramips/patches-4.14/0024-GPIO-add-named-gpio-exports.patch b/target/linux/ramips/patches-4.14/0024-GPIO-add-named-gpio-exports.patch new file mode 100644 index 000000000..0c1bc7392 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0024-GPIO-add-named-gpio-exports.patch @@ -0,0 +1,166 @@ +From 4267880319bc1a2270d352e0ded6d6386242a7ef Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 12 Aug 2014 20:49:27 +0200 +Subject: [PATCH 24/53] GPIO: add named gpio exports + +Signed-off-by: John Crispin +--- + drivers/gpio/gpiolib-of.c | 68 +++++++++++++++++++++++++++++++++++++++++ + drivers/gpio/gpiolib-sysfs.c | 10 +++++- + include/asm-generic/gpio.h | 6 ++++ + include/linux/gpio/consumer.h | 8 +++++ + 4 files changed, 91 insertions(+), 1 deletion(-) + +--- a/drivers/gpio/gpiolib-of.c ++++ b/drivers/gpio/gpiolib-of.c +@@ -23,6 +23,8 @@ + #include + #include + #include ++#include ++#include + + #include "gpiolib.h" + +@@ -506,3 +508,69 @@ void of_gpiochip_remove(struct gpio_chip + gpiochip_remove_pin_ranges(chip); + of_node_put(chip->of_node); + } ++ ++static struct of_device_id gpio_export_ids[] = { ++ { .compatible = "gpio-export" }, ++ { /* sentinel */ } ++}; ++ ++static int __init of_gpio_export_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device_node *cnp; ++ u32 val; ++ int nb = 0; ++ ++ for_each_child_of_node(np, cnp) { ++ const char *name = NULL; ++ int gpio; ++ bool dmc; ++ int max_gpio = 1; ++ int i; ++ ++ of_property_read_string(cnp, "gpio-export,name", &name); ++ ++ if (!name) ++ max_gpio = of_gpio_count(cnp); ++ ++ for (i = 0; i < max_gpio; i++) { ++ unsigned flags = 0; ++ enum of_gpio_flags of_flags; ++ ++ gpio = of_get_gpio_flags(cnp, i, &of_flags); ++ ++ if (of_flags == OF_GPIO_ACTIVE_LOW) ++ flags |= GPIOF_ACTIVE_LOW; ++ ++ if (!of_property_read_u32(cnp, "gpio-export,output", &val)) ++ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; ++ else ++ flags |= GPIOF_IN; ++ ++ if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np))) ++ continue; ++ ++ dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change"); ++ gpio_export_with_name(gpio, dmc, name); ++ nb++; ++ } ++ } ++ ++ dev_info(&pdev->dev, "%d gpio(s) exported\n", nb); ++ ++ return 0; ++} ++ ++static struct platform_driver gpio_export_driver = { ++ .driver = { ++ .name = "gpio-export", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(gpio_export_ids), ++ }, ++}; ++ ++static int __init of_gpio_export_init(void) ++{ ++ return platform_driver_probe(&gpio_export_driver, of_gpio_export_probe); ++} ++device_initcall(of_gpio_export_init); +--- a/drivers/gpio/gpiolib-sysfs.c ++++ b/drivers/gpio/gpiolib-sysfs.c +@@ -553,7 +553,7 @@ static struct class gpio_class = { + * + * Returns zero on success, else an error. + */ +-int gpiod_export(struct gpio_desc *desc, bool direction_may_change) ++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name) + { + struct gpio_chip *chip; + struct gpio_device *gdev; +@@ -615,6 +615,8 @@ int gpiod_export(struct gpio_desc *desc, + offset = gpio_chip_hwgpio(desc); + if (chip->names && chip->names[offset]) + ioname = chip->names[offset]; ++ if (name) ++ ioname = name; + + dev = device_create_with_groups(&gpio_class, &gdev->dev, + MKDEV(0, 0), data, gpio_groups, +@@ -636,6 +638,12 @@ err_unlock: + gpiod_dbg(desc, "%s: status %d\n", __func__, status); + return status; + } ++EXPORT_SYMBOL_GPL(__gpiod_export); ++ ++int gpiod_export(struct gpio_desc *desc, bool direction_may_change) ++{ ++ return __gpiod_export(desc, direction_may_change, NULL); ++} + EXPORT_SYMBOL_GPL(gpiod_export); + + static int match_export(struct device *dev, const void *desc) +--- a/include/asm-generic/gpio.h ++++ b/include/asm-generic/gpio.h +@@ -127,6 +127,12 @@ static inline int gpio_export(unsigned g + return gpiod_export(gpio_to_desc(gpio), direction_may_change); + } + ++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); ++static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name) ++{ ++ return __gpiod_export(gpio_to_desc(gpio), direction_may_change, name); ++} ++ + static inline int gpio_export_link(struct device *dev, const char *name, + unsigned gpio) + { +--- a/include/linux/gpio/consumer.h ++++ b/include/linux/gpio/consumer.h +@@ -451,6 +451,7 @@ struct gpio_desc *devm_fwnode_get_gpiod_ + + #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) + ++int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); + int gpiod_export(struct gpio_desc *desc, bool direction_may_change); + int gpiod_export_link(struct device *dev, const char *name, + struct gpio_desc *desc); +@@ -458,6 +459,13 @@ void gpiod_unexport(struct gpio_desc *de + + #else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ + ++static inline int _gpiod_export(struct gpio_desc *desc, ++ bool direction_may_change, ++ const char *name) ++{ ++ return -ENOSYS; ++} ++ + static inline int gpiod_export(struct gpio_desc *desc, + bool direction_may_change) + { diff --git a/target/linux/ramips/patches-4.14/0025-pinctrl-ralink-add-pinctrl-driver.patch b/target/linux/ramips/patches-4.14/0025-pinctrl-ralink-add-pinctrl-driver.patch new file mode 100644 index 000000000..3e5dac537 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0025-pinctrl-ralink-add-pinctrl-driver.patch @@ -0,0 +1,524 @@ +From 7adbe9a88c33c6e362a10b109d963b5500a21f00 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 09:34:05 +0100 +Subject: [PATCH 25/53] pinctrl: ralink: add pinctrl driver + +Signed-off-by: John Crispin +--- + arch/mips/Kconfig | 2 + + drivers/pinctrl/Kconfig | 5 + + drivers/pinctrl/Makefile | 1 + + drivers/pinctrl/pinctrl-rt2880.c | 474 ++++++++++++++++++++++++++++++++++++++ + 4 files changed, 482 insertions(+) + create mode 100644 drivers/pinctrl/pinctrl-rt2880.c + +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -628,6 +628,8 @@ config RALINK + select CLKDEV_LOOKUP + select ARCH_HAS_RESET_CONTROLLER + select RESET_CONTROLLER ++ select PINCTRL ++ select PINCTRL_RT2880 + + config SGI_IP22 + bool "SGI IP22 (Indy/Indigo2)" +--- a/drivers/pinctrl/Kconfig ++++ b/drivers/pinctrl/Kconfig +@@ -143,6 +143,11 @@ config PINCTRL_LPC18XX + help + Pinctrl driver for NXP LPC18xx/43xx System Control Unit (SCU). + ++config PINCTRL_RT2880 ++ bool ++ depends on RALINK ++ select PINMUX ++ + config PINCTRL_FALCON + bool + depends on SOC_FALCON +--- a/drivers/pinctrl/Makefile ++++ b/drivers/pinctrl/Makefile +@@ -28,6 +28,7 @@ obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl- + obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o + obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o + obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o ++obj-$(CONFIG_PINCTRL_RT2880) += pinctrl-rt2880.o + obj-$(CONFIG_PINCTRL_RZA1) += pinctrl-rza1.o + obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o + obj-$(CONFIG_PINCTRL_SIRF) += sirf/ +--- /dev/null ++++ b/drivers/pinctrl/pinctrl-rt2880.c +@@ -0,0 +1,472 @@ ++/* ++ * linux/drivers/pinctrl/pinctrl-rt2880.c ++ * ++ * 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 ++ * publishhed by the Free Software Foundation. ++ * ++ * Copyright (C) 2013 John Crispin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "core.h" ++ ++#define SYSC_REG_GPIO_MODE 0x60 ++#define SYSC_REG_GPIO_MODE2 0x64 ++ ++struct rt2880_priv { ++ struct device *dev; ++ ++ struct pinctrl_pin_desc *pads; ++ struct pinctrl_desc *desc; ++ ++ struct rt2880_pmx_func **func; ++ int func_count; ++ ++ struct rt2880_pmx_group *groups; ++ const char **group_names; ++ int group_count; ++ ++ uint8_t *gpio; ++ int max_pins; ++}; ++ ++static int rt2880_get_group_count(struct pinctrl_dev *pctrldev) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ return p->group_count; ++} ++ ++static const char *rt2880_get_group_name(struct pinctrl_dev *pctrldev, ++ unsigned group) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ if (group >= p->group_count) ++ return NULL; ++ ++ return p->group_names[group]; ++} ++ ++static int rt2880_get_group_pins(struct pinctrl_dev *pctrldev, ++ unsigned group, ++ const unsigned **pins, ++ unsigned *num_pins) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ if (group >= p->group_count) ++ return -EINVAL; ++ ++ *pins = p->groups[group].func[0].pins; ++ *num_pins = p->groups[group].func[0].pin_count; ++ ++ return 0; ++} ++ ++static void rt2880_pinctrl_dt_free_map(struct pinctrl_dev *pctrldev, ++ struct pinctrl_map *map, unsigned num_maps) ++{ ++ int i; ++ ++ for (i = 0; i < num_maps; i++) ++ if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN || ++ map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP) ++ kfree(map[i].data.configs.configs); ++ kfree(map); ++} ++ ++static void rt2880_pinctrl_pin_dbg_show(struct pinctrl_dev *pctrldev, ++ struct seq_file *s, ++ unsigned offset) ++{ ++ seq_printf(s, "ralink pio"); ++} ++ ++static void rt2880_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctrldev, ++ struct device_node *np, ++ struct pinctrl_map **map) ++{ ++ const char *function; ++ int func = of_property_read_string(np, "ralink,function", &function); ++ int grps = of_property_count_strings(np, "ralink,group"); ++ int i; ++ ++ if (func || !grps) ++ return; ++ ++ for (i = 0; i < grps; i++) { ++ const char *group; ++ ++ of_property_read_string_index(np, "ralink,group", i, &group); ++ ++ (*map)->type = PIN_MAP_TYPE_MUX_GROUP; ++ (*map)->name = function; ++ (*map)->data.mux.group = group; ++ (*map)->data.mux.function = function; ++ (*map)++; ++ } ++} ++ ++static int rt2880_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrldev, ++ struct device_node *np_config, ++ struct pinctrl_map **map, ++ unsigned *num_maps) ++{ ++ int max_maps = 0; ++ struct pinctrl_map *tmp; ++ struct device_node *np; ++ ++ for_each_child_of_node(np_config, np) { ++ int ret = of_property_count_strings(np, "ralink,group"); ++ ++ if (ret >= 0) ++ max_maps += ret; ++ } ++ ++ if (!max_maps) ++ return -EINVAL; ++ ++ *map = kzalloc(max_maps * sizeof(struct pinctrl_map), GFP_KERNEL); ++ if (!*map) ++ return -ENOMEM; ++ ++ tmp = *map; ++ ++ for_each_child_of_node(np_config, np) ++ rt2880_pinctrl_dt_subnode_to_map(pctrldev, np, &tmp); ++ *num_maps = max_maps; ++ ++ return 0; ++} ++ ++static const struct pinctrl_ops rt2880_pctrl_ops = { ++ .get_groups_count = rt2880_get_group_count, ++ .get_group_name = rt2880_get_group_name, ++ .get_group_pins = rt2880_get_group_pins, ++ .pin_dbg_show = rt2880_pinctrl_pin_dbg_show, ++ .dt_node_to_map = rt2880_pinctrl_dt_node_to_map, ++ .dt_free_map = rt2880_pinctrl_dt_free_map, ++}; ++ ++static int rt2880_pmx_func_count(struct pinctrl_dev *pctrldev) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ return p->func_count; ++} ++ ++static const char *rt2880_pmx_func_name(struct pinctrl_dev *pctrldev, ++ unsigned func) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ return p->func[func]->name; ++} ++ ++static int rt2880_pmx_group_get_groups(struct pinctrl_dev *pctrldev, ++ unsigned func, ++ const char * const **groups, ++ unsigned * const num_groups) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ if (p->func[func]->group_count == 1) ++ *groups = &p->group_names[p->func[func]->groups[0]]; ++ else ++ *groups = p->group_names; ++ ++ *num_groups = p->func[func]->group_count; ++ ++ return 0; ++} ++ ++static int rt2880_pmx_group_enable(struct pinctrl_dev *pctrldev, ++ unsigned func, ++ unsigned group) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ u32 mode = 0; ++ u32 reg = SYSC_REG_GPIO_MODE; ++ int i; ++ int shift; ++ ++ /* dont allow double use */ ++ if (p->groups[group].enabled) { ++ dev_err(p->dev, "%s is already enabled\n", p->groups[group].name); ++ return -EBUSY; ++ } ++ ++ p->groups[group].enabled = 1; ++ p->func[func]->enabled = 1; ++ ++ shift = p->groups[group].shift; ++ if (shift >= 32) { ++ shift -= 32; ++ reg = SYSC_REG_GPIO_MODE2; ++ } ++ mode = rt_sysc_r32(reg); ++ mode &= ~(p->groups[group].mask << shift); ++ ++ /* mark the pins as gpio */ ++ for (i = 0; i < p->groups[group].func[0].pin_count; i++) ++ p->gpio[p->groups[group].func[0].pins[i]] = 1; ++ ++ /* function 0 is gpio and needs special handling */ ++ if (func == 0) { ++ mode |= p->groups[group].gpio << shift; ++ } else { ++ for (i = 0; i < p->func[func]->pin_count; i++) ++ p->gpio[p->func[func]->pins[i]] = 0; ++ mode |= p->func[func]->value << shift; ++ } ++ rt_sysc_w32(mode, reg); ++ ++ return 0; ++} ++ ++static int rt2880_pmx_group_gpio_request_enable(struct pinctrl_dev *pctrldev, ++ struct pinctrl_gpio_range *range, ++ unsigned pin) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ if (!p->gpio[pin]) { ++ dev_err(p->dev, "pin %d is not set to gpio mux\n", pin); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static const struct pinmux_ops rt2880_pmx_group_ops = { ++ .get_functions_count = rt2880_pmx_func_count, ++ .get_function_name = rt2880_pmx_func_name, ++ .get_function_groups = rt2880_pmx_group_get_groups, ++ .set_mux = rt2880_pmx_group_enable, ++ .gpio_request_enable = rt2880_pmx_group_gpio_request_enable, ++}; ++ ++static struct pinctrl_desc rt2880_pctrl_desc = { ++ .owner = THIS_MODULE, ++ .name = "rt2880-pinmux", ++ .pctlops = &rt2880_pctrl_ops, ++ .pmxops = &rt2880_pmx_group_ops, ++}; ++ ++static struct rt2880_pmx_func gpio_func = { ++ .name = "gpio", ++}; ++ ++static int rt2880_pinmux_index(struct rt2880_priv *p) ++{ ++ struct rt2880_pmx_func **f; ++ struct rt2880_pmx_group *mux = p->groups; ++ int i, j, c = 0; ++ ++ /* count the mux functions */ ++ while (mux->name) { ++ p->group_count++; ++ mux++; ++ } ++ ++ /* allocate the group names array needed by the gpio function */ ++ p->group_names = devm_kzalloc(p->dev, sizeof(char *) * p->group_count, GFP_KERNEL); ++ if (!p->group_names) ++ return -1; ++ ++ for (i = 0; i < p->group_count; i++) { ++ p->group_names[i] = p->groups[i].name; ++ p->func_count += p->groups[i].func_count; ++ } ++ ++ /* we have a dummy function[0] for gpio */ ++ p->func_count++; ++ ++ /* allocate our function and group mapping index buffers */ ++ f = p->func = devm_kzalloc(p->dev, sizeof(struct rt2880_pmx_func) * p->func_count, GFP_KERNEL); ++ gpio_func.groups = devm_kzalloc(p->dev, sizeof(int) * p->group_count, GFP_KERNEL); ++ if (!f || !gpio_func.groups) ++ return -1; ++ ++ /* add a backpointer to the function so it knows its group */ ++ gpio_func.group_count = p->group_count; ++ for (i = 0; i < gpio_func.group_count; i++) ++ gpio_func.groups[i] = i; ++ ++ f[c] = &gpio_func; ++ c++; ++ ++ /* add remaining functions */ ++ for (i = 0; i < p->group_count; i++) { ++ for (j = 0; j < p->groups[i].func_count; j++) { ++ f[c] = &p->groups[i].func[j]; ++ f[c]->groups = devm_kzalloc(p->dev, sizeof(int), GFP_KERNEL); ++ f[c]->groups[0] = i; ++ f[c]->group_count = 1; ++ c++; ++ } ++ } ++ return 0; ++} ++ ++static int rt2880_pinmux_pins(struct rt2880_priv *p) ++{ ++ int i, j; ++ ++ /* loop over the functions and initialize the pins array. also work out the highest pin used */ ++ for (i = 0; i < p->func_count; i++) { ++ int pin; ++ ++ if (!p->func[i]->pin_count) ++ continue; ++ ++ p->func[i]->pins = devm_kzalloc(p->dev, sizeof(int) * p->func[i]->pin_count, GFP_KERNEL); ++ for (j = 0; j < p->func[i]->pin_count; j++) ++ p->func[i]->pins[j] = p->func[i]->pin_first + j; ++ ++ pin = p->func[i]->pin_first + p->func[i]->pin_count; ++ if (pin > p->max_pins) ++ p->max_pins = pin; ++ } ++ ++ /* the buffer that tells us which pins are gpio */ ++ p->gpio = devm_kzalloc(p->dev,sizeof(uint8_t) * p->max_pins, ++ GFP_KERNEL); ++ /* the pads needed to tell pinctrl about our pins */ ++ p->pads = devm_kzalloc(p->dev, ++ sizeof(struct pinctrl_pin_desc) * p->max_pins, ++ GFP_KERNEL); ++ if (!p->pads || !p->gpio ) { ++ dev_err(p->dev, "Failed to allocate gpio data\n"); ++ return -ENOMEM; ++ } ++ ++ memset(p->gpio, 1, sizeof(uint8_t) * p->max_pins); ++ for (i = 0; i < p->func_count; i++) { ++ if (!p->func[i]->pin_count) ++ continue; ++ ++ for (j = 0; j < p->func[i]->pin_count; j++) ++ p->gpio[p->func[i]->pins[j]] = 0; ++ } ++ ++ /* pin 0 is always a gpio */ ++ p->gpio[0] = 1; ++ ++ /* set the pads */ ++ for (i = 0; i < p->max_pins; i++) { ++ /* strlen("ioXY") + 1 = 5 */ ++ char *name = devm_kzalloc(p->dev, 5, GFP_KERNEL); ++ ++ if (!name) { ++ dev_err(p->dev, "Failed to allocate pad name\n"); ++ return -ENOMEM; ++ } ++ snprintf(name, 5, "io%d", i); ++ p->pads[i].number = i; ++ p->pads[i].name = name; ++ } ++ p->desc->pins = p->pads; ++ p->desc->npins = p->max_pins; ++ ++ return 0; ++} ++ ++static int rt2880_pinmux_probe(struct platform_device *pdev) ++{ ++ struct rt2880_priv *p; ++ struct pinctrl_dev *dev; ++ struct device_node *np; ++ ++ if (!rt2880_pinmux_data) ++ return -ENOSYS; ++ ++ /* setup the private data */ ++ p = devm_kzalloc(&pdev->dev, sizeof(struct rt2880_priv), GFP_KERNEL); ++ if (!p) ++ return -ENOMEM; ++ ++ p->dev = &pdev->dev; ++ p->desc = &rt2880_pctrl_desc; ++ p->groups = rt2880_pinmux_data; ++ platform_set_drvdata(pdev, p); ++ ++ /* init the device */ ++ if (rt2880_pinmux_index(p)) { ++ dev_err(&pdev->dev, "failed to load index\n"); ++ return -EINVAL; ++ } ++ if (rt2880_pinmux_pins(p)) { ++ dev_err(&pdev->dev, "failed to load pins\n"); ++ return -EINVAL; ++ } ++ dev = pinctrl_register(p->desc, &pdev->dev, p); ++ if (IS_ERR(dev)) ++ return PTR_ERR(dev); ++ ++ /* finalize by adding gpio ranges for enables gpio controllers */ ++ for_each_compatible_node(np, NULL, "ralink,rt2880-gpio") { ++ const __be32 *ngpio, *gpiobase; ++ struct pinctrl_gpio_range *range; ++ char *name; ++ ++ if (!of_device_is_available(np)) ++ continue; ++ ++ ngpio = of_get_property(np, "ralink,num-gpios", NULL); ++ gpiobase = of_get_property(np, "ralink,gpio-base", NULL); ++ if (!ngpio || !gpiobase) { ++ dev_err(&pdev->dev, "failed to load chip info\n"); ++ return -EINVAL; ++ } ++ ++ range = devm_kzalloc(p->dev, sizeof(struct pinctrl_gpio_range) + 4, GFP_KERNEL); ++ range->name = name = (char *) &range[1]; ++ sprintf(name, "pio"); ++ range->npins = __be32_to_cpu(*ngpio); ++ range->base = __be32_to_cpu(*gpiobase); ++ range->pin_base = range->base; ++ pinctrl_add_gpio_range(dev, range); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id rt2880_pinmux_match[] = { ++ { .compatible = "ralink,rt2880-pinmux" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt2880_pinmux_match); ++ ++static struct platform_driver rt2880_pinmux_driver = { ++ .probe = rt2880_pinmux_probe, ++ .driver = { ++ .name = "rt2880-pinmux", ++ .owner = THIS_MODULE, ++ .of_match_table = rt2880_pinmux_match, ++ }, ++}; ++ ++int __init rt2880_pinmux_init(void) ++{ ++ return platform_driver_register(&rt2880_pinmux_driver); ++} ++ ++core_initcall_sync(rt2880_pinmux_init); diff --git a/target/linux/ramips/patches-4.14/0026-DT-Add-documentation-for-gpio-ralink.patch b/target/linux/ramips/patches-4.14/0026-DT-Add-documentation-for-gpio-ralink.patch new file mode 100644 index 000000000..7d5f98f64 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0026-DT-Add-documentation-for-gpio-ralink.patch @@ -0,0 +1,59 @@ +From d410e5478c622c01fcf31427533df5f433df9146 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 28 Jul 2013 19:45:30 +0200 +Subject: [PATCH 26/53] DT: Add documentation for gpio-ralink + +Describe gpio-ralink binding. + +Signed-off-by: John Crispin +Cc: linux-mips@linux-mips.org +Cc: devicetree@vger.kernel.org +Cc: linux-gpio@vger.kernel.org +--- + .../devicetree/bindings/gpio/gpio-ralink.txt | 40 ++++++++++++++++++++ + 1 file changed, 40 insertions(+) + create mode 100644 Documentation/devicetree/bindings/gpio/gpio-ralink.txt + +--- /dev/null ++++ b/Documentation/devicetree/bindings/gpio/gpio-ralink.txt +@@ -0,0 +1,40 @@ ++Ralink SoC GPIO controller bindings ++ ++Required properties: ++- compatible: ++ - "ralink,rt2880-gpio" for Ralink controllers ++- #gpio-cells : Should be two. ++ - first cell is the pin number ++ - second cell is used to specify optional parameters (unused) ++- gpio-controller : Marks the device node as a GPIO controller ++- reg : Physical base address and length of the controller's registers ++- interrupt-parent: phandle to the INTC device node ++- interrupts : Specify the INTC interrupt number ++- ralink,num-gpios : Specify the number of GPIOs ++- ralink,register-map : The register layout depends on the GPIO bank and actual ++ SoC type. Register offsets need to be in this order. ++ [ INT, EDGE, RENA, FENA, DATA, DIR, POL, SET, RESET, TOGGLE ] ++ ++Optional properties: ++- ralink,gpio-base : Specify the GPIO chips base number ++ ++Example: ++ ++ gpio0: gpio@600 { ++ compatible = "ralink,rt5350-gpio", "ralink,rt2880-gpio"; ++ ++ #gpio-cells = <2>; ++ gpio-controller; ++ ++ reg = <0x600 0x34>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <6>; ++ ++ ralink,gpio-base = <0>; ++ ralink,num-gpios = <24>; ++ ralink,register-map = [ 00 04 08 0c ++ 20 24 28 2c ++ 30 34 ]; ++ ++ }; diff --git a/target/linux/ramips/patches-4.14/0027-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch b/target/linux/ramips/patches-4.14/0027-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch new file mode 100644 index 000000000..35cedf61f --- /dev/null +++ b/target/linux/ramips/patches-4.14/0027-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch @@ -0,0 +1,430 @@ +From 69fdd2c4f937796b934e89c33acde9d082e27bfd Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 4 Aug 2014 20:36:29 +0200 +Subject: [PATCH 27/53] GPIO: MIPS: ralink: add gpio driver for ralink SoC + +Add gpio driver for Ralink SoC. This driver makes the gpio core on +RT2880, RT305x, rt3352, rt3662, rt3883, rt5350 and mt7620 work. + +Signed-off-by: John Crispin +Cc: linux-mips@linux-mips.org +Cc: linux-gpio@vger.kernel.org +--- + arch/mips/include/asm/mach-ralink/gpio.h | 24 ++ + drivers/gpio/Kconfig | 6 + + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-ralink.c | 355 ++++++++++++++++++++++++++++++ + 4 files changed, 386 insertions(+) + create mode 100644 arch/mips/include/asm/mach-ralink/gpio.h + create mode 100644 drivers/gpio/gpio-ralink.c + +--- /dev/null ++++ b/arch/mips/include/asm/mach-ralink/gpio.h +@@ -0,0 +1,24 @@ ++/* ++ * Ralink SoC GPIO API support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * 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. ++ * ++ */ ++ ++#ifndef __ASM_MACH_RALINK_GPIO_H ++#define __ASM_MACH_RALINK_GPIO_H ++ ++#define ARCH_NR_GPIOS 128 ++#include ++ ++#define gpio_get_value __gpio_get_value ++#define gpio_set_value __gpio_set_value ++#define gpio_cansleep __gpio_cansleep ++#define gpio_to_irq __gpio_to_irq ++ ++#endif /* __ASM_MACH_RALINK_GPIO_H */ +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -398,6 +398,12 @@ config GPIO_REG + A 32-bit single register GPIO fixed in/out implementation. This + can be used to represent any register as a set of GPIO signals. + ++config GPIO_RALINK ++ bool "Ralink GPIO Support" ++ depends on RALINK ++ help ++ Say yes here to support the Ralink SoC GPIO device ++ + config GPIO_SPEAR_SPICS + bool "ST SPEAr13xx SPI Chip Select as GPIO support" + depends on PLAT_SPEAR +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -98,6 +98,7 @@ obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-p + obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o + obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o + obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o ++obj-$(CONFIG_GPIO_RALINK) += gpio-ralink.o + obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o + obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o + obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o +--- /dev/null ++++ b/drivers/gpio/gpio-ralink.c +@@ -0,0 +1,355 @@ ++/* ++ * 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. ++ * ++ * Copyright (C) 2009-2011 Gabor Juhos ++ * Copyright (C) 2013 John Crispin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++enum ralink_gpio_reg { ++ GPIO_REG_INT = 0, ++ GPIO_REG_EDGE, ++ GPIO_REG_RENA, ++ GPIO_REG_FENA, ++ GPIO_REG_DATA, ++ GPIO_REG_DIR, ++ GPIO_REG_POL, ++ GPIO_REG_SET, ++ GPIO_REG_RESET, ++ GPIO_REG_TOGGLE, ++ GPIO_REG_MAX ++}; ++ ++struct ralink_gpio_chip { ++ struct gpio_chip chip; ++ u8 regs[GPIO_REG_MAX]; ++ ++ spinlock_t lock; ++ void __iomem *membase; ++ struct irq_domain *domain; ++ int irq; ++ ++ u32 rising; ++ u32 falling; ++}; ++ ++#define MAP_MAX 4 ++static struct irq_domain *irq_map[MAP_MAX]; ++static int irq_map_count; ++static atomic_t irq_refcount = ATOMIC_INIT(0); ++ ++static inline struct ralink_gpio_chip *to_ralink_gpio(struct gpio_chip *chip) ++{ ++ struct ralink_gpio_chip *rg; ++ ++ rg = container_of(chip, struct ralink_gpio_chip, chip); ++ ++ return rg; ++} ++ ++static inline void rt_gpio_w32(struct ralink_gpio_chip *rg, u8 reg, u32 val) ++{ ++ iowrite32(val, rg->membase + rg->regs[reg]); ++} ++ ++static inline u32 rt_gpio_r32(struct ralink_gpio_chip *rg, u8 reg) ++{ ++ return ioread32(rg->membase + rg->regs[reg]); ++} ++ ++static void ralink_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ ++ rt_gpio_w32(rg, (value) ? GPIO_REG_SET : GPIO_REG_RESET, BIT(offset)); ++} ++ ++static int ralink_gpio_get(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ ++ return !!(rt_gpio_r32(rg, GPIO_REG_DATA) & BIT(offset)); ++} ++ ++static int ralink_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ t = rt_gpio_r32(rg, GPIO_REG_DIR); ++ t &= ~BIT(offset); ++ rt_gpio_w32(rg, GPIO_REG_DIR, t); ++ spin_unlock_irqrestore(&rg->lock, flags); ++ ++ return 0; ++} ++ ++static int ralink_gpio_direction_output(struct gpio_chip *chip, ++ unsigned offset, int value) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ ralink_gpio_set(chip, offset, value); ++ t = rt_gpio_r32(rg, GPIO_REG_DIR); ++ t |= BIT(offset); ++ rt_gpio_w32(rg, GPIO_REG_DIR, t); ++ spin_unlock_irqrestore(&rg->lock, flags); ++ ++ return 0; ++} ++ ++static int ralink_gpio_to_irq(struct gpio_chip *chip, unsigned pin) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ ++ if (rg->irq < 1) ++ return -1; ++ ++ return irq_create_mapping(rg->domain, pin); ++} ++ ++static void ralink_gpio_irq_handler(struct irq_desc *desc) ++{ ++ int i; ++ ++ for (i = 0; i < irq_map_count; i++) { ++ struct irq_domain *domain = irq_map[i]; ++ struct ralink_gpio_chip *rg; ++ unsigned long pending; ++ int bit; ++ ++ rg = (struct ralink_gpio_chip *) domain->host_data; ++ pending = rt_gpio_r32(rg, GPIO_REG_INT); ++ ++ for_each_set_bit(bit, &pending, rg->chip.ngpio) { ++ u32 map = irq_find_mapping(domain, bit); ++ generic_handle_irq(map); ++ rt_gpio_w32(rg, GPIO_REG_INT, BIT(bit)); ++ } ++ } ++} ++ ++static void ralink_gpio_irq_unmask(struct irq_data *d) ++{ ++ struct ralink_gpio_chip *rg; ++ unsigned long flags; ++ u32 rise, fall; ++ ++ rg = (struct ralink_gpio_chip *) d->domain->host_data; ++ rise = rt_gpio_r32(rg, GPIO_REG_RENA); ++ fall = rt_gpio_r32(rg, GPIO_REG_FENA); ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ rt_gpio_w32(rg, GPIO_REG_RENA, rise | (BIT(d->hwirq) & rg->rising)); ++ rt_gpio_w32(rg, GPIO_REG_FENA, fall | (BIT(d->hwirq) & rg->falling)); ++ spin_unlock_irqrestore(&rg->lock, flags); ++} ++ ++static void ralink_gpio_irq_mask(struct irq_data *d) ++{ ++ struct ralink_gpio_chip *rg; ++ unsigned long flags; ++ u32 rise, fall; ++ ++ rg = (struct ralink_gpio_chip *) d->domain->host_data; ++ rise = rt_gpio_r32(rg, GPIO_REG_RENA); ++ fall = rt_gpio_r32(rg, GPIO_REG_FENA); ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ rt_gpio_w32(rg, GPIO_REG_FENA, fall & ~BIT(d->hwirq)); ++ rt_gpio_w32(rg, GPIO_REG_RENA, rise & ~BIT(d->hwirq)); ++ spin_unlock_irqrestore(&rg->lock, flags); ++} ++ ++static int ralink_gpio_irq_type(struct irq_data *d, unsigned int type) ++{ ++ struct ralink_gpio_chip *rg; ++ u32 mask = BIT(d->hwirq); ++ ++ rg = (struct ralink_gpio_chip *) d->domain->host_data; ++ ++ if (type == IRQ_TYPE_PROBE) { ++ if ((rg->rising | rg->falling) & mask) ++ return 0; ++ ++ type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; ++ } ++ ++ if (type & IRQ_TYPE_EDGE_RISING) ++ rg->rising |= mask; ++ else ++ rg->rising &= ~mask; ++ ++ if (type & IRQ_TYPE_EDGE_FALLING) ++ rg->falling |= mask; ++ else ++ rg->falling &= ~mask; ++ ++ return 0; ++} ++ ++static struct irq_chip ralink_gpio_irq_chip = { ++ .name = "GPIO", ++ .irq_unmask = ralink_gpio_irq_unmask, ++ .irq_mask = ralink_gpio_irq_mask, ++ .irq_mask_ack = ralink_gpio_irq_mask, ++ .irq_set_type = ralink_gpio_irq_type, ++}; ++ ++static int gpio_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) ++{ ++ irq_set_chip_and_handler(irq, &ralink_gpio_irq_chip, handle_level_irq); ++ irq_set_handler_data(irq, d); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops irq_domain_ops = { ++ .xlate = irq_domain_xlate_onecell, ++ .map = gpio_map, ++}; ++ ++static void ralink_gpio_irq_init(struct device_node *np, ++ struct ralink_gpio_chip *rg) ++{ ++ if (irq_map_count >= MAP_MAX) ++ return; ++ ++ rg->irq = irq_of_parse_and_map(np, 0); ++ if (!rg->irq) ++ return; ++ ++ rg->domain = irq_domain_add_linear(np, rg->chip.ngpio, ++ &irq_domain_ops, rg); ++ if (!rg->domain) { ++ dev_err(rg->chip.parent, "irq_domain_add_linear failed\n"); ++ return; ++ } ++ ++ irq_map[irq_map_count++] = rg->domain; ++ ++ rt_gpio_w32(rg, GPIO_REG_RENA, 0x0); ++ rt_gpio_w32(rg, GPIO_REG_FENA, 0x0); ++ ++ if (!atomic_read(&irq_refcount)) ++ irq_set_chained_handler(rg->irq, ralink_gpio_irq_handler); ++ atomic_inc(&irq_refcount); ++ ++ dev_info(rg->chip.parent, "registering %d irq handlers\n", rg->chip.ngpio); ++} ++ ++static int ralink_gpio_request(struct gpio_chip *chip, unsigned offset) ++{ ++ int gpio = chip->base + offset; ++ ++ return pinctrl_request_gpio(gpio); ++} ++ ++static void ralink_gpio_free(struct gpio_chip *chip, unsigned offset) ++{ ++ int gpio = chip->base + offset; ++ ++ pinctrl_free_gpio(gpio); ++} ++ ++static int ralink_gpio_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ struct ralink_gpio_chip *rg; ++ const __be32 *ngpio, *gpiobase; ++ ++ if (!res) { ++ dev_err(&pdev->dev, "failed to find resource\n"); ++ return -ENOMEM; ++ } ++ ++ rg = devm_kzalloc(&pdev->dev, ++ sizeof(struct ralink_gpio_chip), GFP_KERNEL); ++ if (!rg) ++ return -ENOMEM; ++ ++ rg->membase = devm_ioremap_resource(&pdev->dev, res); ++ if (!rg->membase) { ++ dev_err(&pdev->dev, "cannot remap I/O memory region\n"); ++ return -ENOMEM; ++ } ++ ++ if (of_property_read_u8_array(np, "ralink,register-map", ++ rg->regs, GPIO_REG_MAX)) { ++ dev_err(&pdev->dev, "failed to read register definition\n"); ++ return -EINVAL; ++ } ++ ++ ngpio = of_get_property(np, "ralink,num-gpios", NULL); ++ if (!ngpio) { ++ dev_err(&pdev->dev, "failed to read number of pins\n"); ++ return -EINVAL; ++ } ++ ++ gpiobase = of_get_property(np, "ralink,gpio-base", NULL); ++ if (gpiobase) ++ rg->chip.base = be32_to_cpu(*gpiobase); ++ else ++ rg->chip.base = -1; ++ ++ spin_lock_init(&rg->lock); ++ ++ rg->chip.parent = &pdev->dev; ++ rg->chip.label = dev_name(&pdev->dev); ++ rg->chip.of_node = np; ++ rg->chip.ngpio = be32_to_cpu(*ngpio); ++ rg->chip.direction_input = ralink_gpio_direction_input; ++ rg->chip.direction_output = ralink_gpio_direction_output; ++ rg->chip.get = ralink_gpio_get; ++ rg->chip.set = ralink_gpio_set; ++ rg->chip.request = ralink_gpio_request; ++ rg->chip.to_irq = ralink_gpio_to_irq; ++ rg->chip.free = ralink_gpio_free; ++ ++ /* set polarity to low for all lines */ ++ rt_gpio_w32(rg, GPIO_REG_POL, 0); ++ ++ dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio); ++ ++ ralink_gpio_irq_init(np, rg); ++ ++ return gpiochip_add(&rg->chip); ++} ++ ++static const struct of_device_id ralink_gpio_match[] = { ++ { .compatible = "ralink,rt2880-gpio" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, ralink_gpio_match); ++ ++static struct platform_driver ralink_gpio_driver = { ++ .probe = ralink_gpio_probe, ++ .driver = { ++ .name = "rt2880_gpio", ++ .owner = THIS_MODULE, ++ .of_match_table = ralink_gpio_match, ++ }, ++}; ++ ++static int __init ralink_gpio_init(void) ++{ ++ return platform_driver_register(&ralink_gpio_driver); ++} ++ ++subsys_initcall(ralink_gpio_init); diff --git a/target/linux/ramips/patches-4.14/0028-GPIO-ralink-add-mt7621-gpio-controller.patch b/target/linux/ramips/patches-4.14/0028-GPIO-ralink-add-mt7621-gpio-controller.patch new file mode 100644 index 000000000..d657274ef --- /dev/null +++ b/target/linux/ramips/patches-4.14/0028-GPIO-ralink-add-mt7621-gpio-controller.patch @@ -0,0 +1,405 @@ +From 61ac7d9b4228de8c332900902c2b93189b042eab Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 11:00:32 +0100 +Subject: [PATCH 28/53] GPIO: ralink: add mt7621 gpio controller + +Signed-off-by: John Crispin +--- + arch/mips/Kconfig | 3 + + drivers/gpio/Kconfig | 6 + + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-mt7621.c | 354 ++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 364 insertions(+) + create mode 100644 drivers/gpio/gpio-mt7621.c + +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -630,6 +630,9 @@ config RALINK + select RESET_CONTROLLER + select PINCTRL + select PINCTRL_RT2880 ++ select ARCH_HAS_RESET_CONTROLLER ++ select RESET_CONTROLLER ++ select ARCH_REQUIRE_GPIOLIB + + config SGI_IP22 + bool "SGI IP22 (Indy/Indigo2)" +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -298,6 +298,12 @@ config GPIO_MENZ127 + help + Say yes here to support the MEN 16Z127 GPIO Controller + ++config GPIO_MT7621 ++ bool "Mediatek GPIO Support" ++ depends on SOC_MT7620 || SOC_MT7621 ++ help ++ Say yes here to support the Mediatek SoC GPIO device ++ + config GPIO_MM_LANTIQ + bool "Lantiq Memory mapped GPIOs" + depends on LANTIQ && SOC_XWAY +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -152,3 +152,4 @@ obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o + obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o + obj-$(CONFIG_GPIO_ZX) += gpio-zx.o + obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o ++obj-$(CONFIG_GPIO_MT7621) += gpio-mt7621.o +--- /dev/null ++++ b/drivers/gpio/gpio-mt7621.c +@@ -0,0 +1,354 @@ ++/* ++ * 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. ++ * ++ * Copyright (C) 2009-2011 Gabor Juhos ++ * Copyright (C) 2013 John Crispin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MTK_MAX_BANK 3 ++#define MTK_BANK_WIDTH 32 ++ ++enum mediatek_gpio_reg { ++ GPIO_REG_CTRL = 0, ++ GPIO_REG_POL, ++ GPIO_REG_DATA, ++ GPIO_REG_DSET, ++ GPIO_REG_DCLR, ++ GPIO_REG_REDGE, ++ GPIO_REG_FEDGE, ++ GPIO_REG_HLVL, ++ GPIO_REG_LLVL, ++ GPIO_REG_STAT, ++ GPIO_REG_EDGE, ++}; ++ ++static void __iomem *mediatek_gpio_membase; ++static int mediatek_gpio_irq; ++static struct irq_domain *mediatek_gpio_irq_domain; ++static atomic_t irq_refcount = ATOMIC_INIT(0); ++ ++struct mtk_gc { ++ struct gpio_chip chip; ++ spinlock_t lock; ++ int bank; ++ u32 rising; ++ u32 falling; ++} *gc_map[MTK_MAX_BANK]; ++ ++static inline struct mtk_gc ++*to_mediatek_gpio(struct gpio_chip *chip) ++{ ++ struct mtk_gc *mgc; ++ ++ mgc = container_of(chip, struct mtk_gc, chip); ++ ++ return mgc; ++} ++ ++static inline void ++mtk_gpio_w32(struct mtk_gc *rg, u8 reg, u32 val) ++{ ++ iowrite32(val, mediatek_gpio_membase + (reg * 0x10) + (rg->bank * 0x4)); ++} ++ ++static inline u32 ++mtk_gpio_r32(struct mtk_gc *rg, u8 reg) ++{ ++ return ioread32(mediatek_gpio_membase + (reg * 0x10) + (rg->bank * 0x4)); ++} ++ ++static void ++mediatek_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ ++ mtk_gpio_w32(rg, (value) ? GPIO_REG_DSET : GPIO_REG_DCLR, BIT(offset)); ++} ++ ++static int ++mediatek_gpio_get(struct gpio_chip *chip, unsigned offset) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ ++ return !!(mtk_gpio_r32(rg, GPIO_REG_DATA) & BIT(offset)); ++} ++ ++static int ++mediatek_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ t = mtk_gpio_r32(rg, GPIO_REG_CTRL); ++ t &= ~BIT(offset); ++ mtk_gpio_w32(rg, GPIO_REG_CTRL, t); ++ spin_unlock_irqrestore(&rg->lock, flags); ++ ++ return 0; ++} ++ ++static int ++mediatek_gpio_direction_output(struct gpio_chip *chip, ++ unsigned offset, int value) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ t = mtk_gpio_r32(rg, GPIO_REG_CTRL); ++ t |= BIT(offset); ++ mtk_gpio_w32(rg, GPIO_REG_CTRL, t); ++ mediatek_gpio_set(chip, offset, value); ++ spin_unlock_irqrestore(&rg->lock, flags); ++ ++ return 0; ++} ++ ++static int ++mediatek_gpio_get_direction(struct gpio_chip *chip, unsigned offset) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ t = mtk_gpio_r32(rg, GPIO_REG_CTRL); ++ spin_unlock_irqrestore(&rg->lock, flags); ++ ++ if (t & BIT(offset)) ++ return 0; ++ ++ return 1; ++} ++ ++static int ++mediatek_gpio_to_irq(struct gpio_chip *chip, unsigned pin) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ ++ return irq_create_mapping(mediatek_gpio_irq_domain, pin + (rg->bank * MTK_BANK_WIDTH)); ++} ++ ++static int ++mediatek_gpio_bank_probe(struct platform_device *pdev, struct device_node *bank) ++{ ++ const __be32 *id = of_get_property(bank, "reg", NULL); ++ struct mtk_gc *rg = devm_kzalloc(&pdev->dev, ++ sizeof(struct mtk_gc), GFP_KERNEL); ++ ++ if (!rg || !id || be32_to_cpu(*id) > MTK_MAX_BANK) ++ return -ENOMEM; ++ ++ gc_map[be32_to_cpu(*id)] = rg; ++ ++ memset(rg, 0, sizeof(struct mtk_gc)); ++ ++ spin_lock_init(&rg->lock); ++ ++ rg->chip.parent = &pdev->dev; ++ rg->chip.label = dev_name(&pdev->dev); ++ rg->chip.of_node = bank; ++ rg->chip.base = MTK_BANK_WIDTH * be32_to_cpu(*id); ++ rg->chip.ngpio = MTK_BANK_WIDTH; ++ rg->chip.direction_input = mediatek_gpio_direction_input; ++ rg->chip.direction_output = mediatek_gpio_direction_output; ++ rg->chip.get_direction = mediatek_gpio_get_direction; ++ rg->chip.get = mediatek_gpio_get; ++ rg->chip.set = mediatek_gpio_set; ++ if (mediatek_gpio_irq_domain) ++ rg->chip.to_irq = mediatek_gpio_to_irq; ++ rg->bank = be32_to_cpu(*id); ++ ++ /* set polarity to low for all gpios */ ++ mtk_gpio_w32(rg, GPIO_REG_POL, 0); ++ ++ dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio); ++ ++ return gpiochip_add(&rg->chip); ++} ++ ++static void ++mediatek_gpio_irq_handler(struct irq_desc *desc) ++{ ++ int i; ++ ++ for (i = 0; i < MTK_MAX_BANK; i++) { ++ struct mtk_gc *rg = gc_map[i]; ++ unsigned long pending; ++ int bit; ++ ++ if (!rg) ++ continue; ++ ++ pending = mtk_gpio_r32(rg, GPIO_REG_STAT); ++ ++ for_each_set_bit(bit, &pending, MTK_BANK_WIDTH) { ++ u32 map = irq_find_mapping(mediatek_gpio_irq_domain, (MTK_BANK_WIDTH * i) + bit); ++ ++ generic_handle_irq(map); ++ mtk_gpio_w32(rg, GPIO_REG_STAT, BIT(bit)); ++ } ++ } ++} ++ ++static void ++mediatek_gpio_irq_unmask(struct irq_data *d) ++{ ++ int pin = d->hwirq; ++ int bank = pin / 32; ++ struct mtk_gc *rg = gc_map[bank]; ++ unsigned long flags; ++ u32 rise, fall; ++ ++ if (!rg) ++ return; ++ ++ rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); ++ fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ mtk_gpio_w32(rg, GPIO_REG_REDGE, rise | (BIT(d->hwirq) & rg->rising)); ++ mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall | (BIT(d->hwirq) & rg->falling)); ++ spin_unlock_irqrestore(&rg->lock, flags); ++} ++ ++static void ++mediatek_gpio_irq_mask(struct irq_data *d) ++{ ++ int pin = d->hwirq; ++ int bank = pin / 32; ++ struct mtk_gc *rg = gc_map[bank]; ++ unsigned long flags; ++ u32 rise, fall; ++ ++ if (!rg) ++ return; ++ ++ rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); ++ fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall & ~BIT(d->hwirq)); ++ mtk_gpio_w32(rg, GPIO_REG_REDGE, rise & ~BIT(d->hwirq)); ++ spin_unlock_irqrestore(&rg->lock, flags); ++} ++ ++static int ++mediatek_gpio_irq_type(struct irq_data *d, unsigned int type) ++{ ++ int pin = d->hwirq; ++ int bank = pin / 32; ++ struct mtk_gc *rg = gc_map[bank]; ++ u32 mask = BIT(d->hwirq); ++ ++ if (!rg) ++ return -1; ++ ++ if (type == IRQ_TYPE_PROBE) { ++ if ((rg->rising | rg->falling) & mask) ++ return 0; ++ ++ type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; ++ } ++ ++ if (type & IRQ_TYPE_EDGE_RISING) ++ rg->rising |= mask; ++ else ++ rg->rising &= ~mask; ++ ++ if (type & IRQ_TYPE_EDGE_FALLING) ++ rg->falling |= mask; ++ else ++ rg->falling &= ~mask; ++ ++ return 0; ++} ++ ++static struct irq_chip mediatek_gpio_irq_chip = { ++ .name = "GPIO", ++ .irq_unmask = mediatek_gpio_irq_unmask, ++ .irq_mask = mediatek_gpio_irq_mask, ++ .irq_mask_ack = mediatek_gpio_irq_mask, ++ .irq_set_type = mediatek_gpio_irq_type, ++}; ++ ++static int ++mediatek_gpio_gpio_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) ++{ ++ irq_set_chip_and_handler(irq, &mediatek_gpio_irq_chip, handle_level_irq); ++ irq_set_handler_data(irq, d); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops irq_domain_ops = { ++ .xlate = irq_domain_xlate_onecell, ++ .map = mediatek_gpio_gpio_map, ++}; ++ ++static int ++mediatek_gpio_probe(struct platform_device *pdev) ++{ ++ struct device_node *bank, *np = pdev->dev.of_node; ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ mediatek_gpio_membase = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(mediatek_gpio_membase)) ++ return PTR_ERR(mediatek_gpio_membase); ++ ++ mediatek_gpio_irq = irq_of_parse_and_map(np, 0); ++ if (mediatek_gpio_irq) { ++ mediatek_gpio_irq_domain = irq_domain_add_linear(np, ++ MTK_MAX_BANK * MTK_BANK_WIDTH, ++ &irq_domain_ops, NULL); ++ if (!mediatek_gpio_irq_domain) ++ dev_err(&pdev->dev, "irq_domain_add_linear failed\n"); ++ } ++ ++ for_each_child_of_node(np, bank) ++ if (of_device_is_compatible(bank, "mtk,mt7621-gpio-bank")) ++ mediatek_gpio_bank_probe(pdev, bank); ++ ++ if (mediatek_gpio_irq_domain) ++ irq_set_chained_handler(mediatek_gpio_irq, mediatek_gpio_irq_handler); ++ ++ return 0; ++} ++ ++static const struct of_device_id mediatek_gpio_match[] = { ++ { .compatible = "mtk,mt7621-gpio" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mediatek_gpio_match); ++ ++static struct platform_driver mediatek_gpio_driver = { ++ .probe = mediatek_gpio_probe, ++ .driver = { ++ .name = "mt7621_gpio", ++ .owner = THIS_MODULE, ++ .of_match_table = mediatek_gpio_match, ++ }, ++}; ++ ++static int __init ++mediatek_gpio_init(void) ++{ ++ return platform_driver_register(&mediatek_gpio_driver); ++} ++ ++subsys_initcall(mediatek_gpio_init); diff --git a/target/linux/ramips/patches-4.14/0031-uvc-add-iPassion-iP2970-support.patch b/target/linux/ramips/patches-4.14/0031-uvc-add-iPassion-iP2970-support.patch new file mode 100644 index 000000000..5829b2fdd --- /dev/null +++ b/target/linux/ramips/patches-4.14/0031-uvc-add-iPassion-iP2970-support.patch @@ -0,0 +1,246 @@ +From 975e76214cd2516eb6cfff4c3eec581872645e88 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 19 Sep 2013 01:50:59 +0200 +Subject: [PATCH 31/53] uvc: add iPassion iP2970 support + +Signed-off-by: John Crispin +--- + drivers/media/usb/uvc/uvc_driver.c | 12 +++ + drivers/media/usb/uvc/uvc_status.c | 2 + + drivers/media/usb/uvc/uvc_video.c | 147 ++++++++++++++++++++++++++++++++++++ + drivers/media/usb/uvc/uvcvideo.h | 5 +- + 4 files changed, 165 insertions(+), 1 deletion(-) + +--- a/drivers/media/usb/uvc/uvc_driver.c ++++ b/drivers/media/usb/uvc/uvc_driver.c +@@ -2734,6 +2734,18 @@ static const struct usb_device_id uvc_id + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_FORCE_Y8 }, ++ /* iPassion iP2970 */ ++ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE ++ | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x1B3B, ++ .idProduct = 0x2970, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = 1, ++ .bInterfaceProtocol = 0, ++ .driver_info = UVC_QUIRK_PROBE_MINMAX ++ | UVC_QUIRK_STREAM_NO_FID ++ | UVC_QUIRK_MOTION ++ | UVC_QUIRK_SINGLE_ISO }, + /* Generic USB Video Class */ + { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) }, + { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) }, +--- a/drivers/media/usb/uvc/uvc_status.c ++++ b/drivers/media/usb/uvc/uvc_status.c +@@ -139,6 +139,7 @@ static void uvc_status_complete(struct u + switch (dev->status[0] & 0x0f) { + case UVC_STATUS_TYPE_CONTROL: + uvc_event_control(dev, dev->status, len); ++ dev->motion = 1; + break; + + case UVC_STATUS_TYPE_STREAMING: +@@ -182,6 +183,7 @@ int uvc_status_init(struct uvc_device *d + } + + pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress); ++ dev->motion = 0; + + /* For high-speed interrupt endpoints, the bInterval value is used as + * an exponent of two. Some developers forgot about it. +--- a/drivers/media/usb/uvc/uvc_video.c ++++ b/drivers/media/usb/uvc/uvc_video.c +@@ -21,6 +21,11 @@ + #include + #include + #include ++#include ++#include ++#include ++#include ++#include + + #include + +@@ -1081,9 +1086,149 @@ static void uvc_video_decode_data(struct + } + } + ++struct bh_priv { ++ unsigned long seen; ++}; ++ ++struct bh_event { ++ const char *name; ++ struct sk_buff *skb; ++ struct work_struct work; ++}; ++ ++#define BH_ERR(fmt, args...) printk(KERN_ERR "%s: " fmt, "webcam", ##args ) ++#define BH_DBG(fmt, args...) do {} while (0) ++#define BH_SKB_SIZE 2048 ++ ++extern u64 uevent_next_seqnum(void); ++static int seen = 0; ++ ++static int bh_event_add_var(struct bh_event *event, int argv, ++ const char *format, ...) ++{ ++ static char buf[128]; ++ char *s; ++ va_list args; ++ int len; ++ ++ if (argv) ++ return 0; ++ ++ va_start(args, format); ++ len = vsnprintf(buf, sizeof(buf), format, args); ++ va_end(args); ++ ++ if (len >= sizeof(buf)) { ++ BH_ERR("buffer size too small\n"); ++ WARN_ON(1); ++ return -ENOMEM; ++ } ++ ++ s = skb_put(event->skb, len + 1); ++ strcpy(s, buf); ++ ++ BH_DBG("added variable '%s'\n", s); ++ ++ return 0; ++} ++ ++static int motion_hotplug_fill_event(struct bh_event *event) ++{ ++ int s = jiffies; ++ int ret; ++ ++ if (!seen) ++ seen = jiffies; ++ ++ ret = bh_event_add_var(event, 0, "HOME=%s", "/"); ++ if (ret) ++ return ret; ++ ++ ret = bh_event_add_var(event, 0, "PATH=%s", ++ "/sbin:/bin:/usr/sbin:/usr/bin"); ++ if (ret) ++ return ret; ++ ++ ret = bh_event_add_var(event, 0, "SUBSYSTEM=usb"); ++ if (ret) ++ return ret; ++ ++ ret = bh_event_add_var(event, 0, "ACTION=motion"); ++ if (ret) ++ return ret; ++ ++ ret = bh_event_add_var(event, 0, "SEEN=%d", s - seen); ++ if (ret) ++ return ret; ++ seen = s; ++ ++ ret = bh_event_add_var(event, 0, "SEQNUM=%llu", uevent_next_seqnum()); ++ ++ return ret; ++} ++ ++static void motion_hotplug_work(struct work_struct *work) ++{ ++ struct bh_event *event = container_of(work, struct bh_event, work); ++ int ret = 0; ++ ++ event->skb = alloc_skb(BH_SKB_SIZE, GFP_KERNEL); ++ if (!event->skb) ++ goto out_free_event; ++ ++ ret = bh_event_add_var(event, 0, "%s@", "add"); ++ if (ret) ++ goto out_free_skb; ++ ++ ret = motion_hotplug_fill_event(event); ++ if (ret) ++ goto out_free_skb; ++ ++ NETLINK_CB(event->skb).dst_group = 1; ++ broadcast_uevent(event->skb, 0, 1, GFP_KERNEL); ++ ++out_free_skb: ++ if (ret) { ++ BH_ERR("work error %d\n", ret); ++ kfree_skb(event->skb); ++ } ++out_free_event: ++ kfree(event); ++} ++ ++static int motion_hotplug_create_event(void) ++{ ++ struct bh_event *event; ++ ++ event = kzalloc(sizeof(*event), GFP_KERNEL); ++ if (!event) ++ return -ENOMEM; ++ ++ event->name = "motion"; ++ ++ INIT_WORK(&event->work, (void *)(void *)motion_hotplug_work); ++ schedule_work(&event->work); ++ ++ return 0; ++} ++ ++#define MOTION_FLAG_OFFSET 4 + static void uvc_video_decode_end(struct uvc_streaming *stream, + struct uvc_buffer *buf, const __u8 *data, int len) + { ++ if ((stream->dev->quirks & UVC_QUIRK_MOTION) && ++ (data[len - 2] == 0xff) && (data[len - 1] == 0xd9)) { ++ u8 *mem; ++ buf->state = UVC_BUF_STATE_READY; ++ mem = (u8 *) (buf->mem + MOTION_FLAG_OFFSET); ++ if ( stream->dev->motion ) { ++ stream->dev->motion = 0; ++ motion_hotplug_create_event(); ++ } else { ++ *mem &= 0x7f; ++ } ++ } ++ + /* Mark the buffer as done if the EOF marker is set. */ + if (data[1] & UVC_STREAM_EOF && buf->bytesused != 0) { + uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); +@@ -1498,6 +1643,8 @@ static int uvc_init_video_isoc(struct uv + if (npackets == 0) + return -ENOMEM; + ++ if (stream->dev->quirks & UVC_QUIRK_SINGLE_ISO) ++ npackets = 1; + size = npackets * psize; + + for (i = 0; i < UVC_URBS; ++i) { +--- a/drivers/media/usb/uvc/uvcvideo.h ++++ b/drivers/media/usb/uvc/uvcvideo.h +@@ -186,7 +186,9 @@ + #define UVC_QUIRK_RESTRICT_FRAME_RATE 0x00000200 + #define UVC_QUIRK_RESTORE_CTRLS_ON_INIT 0x00000400 + #define UVC_QUIRK_FORCE_Y8 0x00000800 +- ++#define UVC_QUIRK_MOTION 0x00001000 ++#define UVC_QUIRK_SINGLE_ISO 0x00002000 ++ + /* Format flags */ + #define UVC_FMT_FLAG_COMPRESSED 0x00000001 + #define UVC_FMT_FLAG_STREAM 0x00000002 +@@ -584,6 +586,7 @@ struct uvc_device { + __u8 *status; + struct input_dev *input; + char input_phys[64]; ++ int motion; + }; + + enum uvc_handle_state { diff --git a/target/linux/ramips/patches-4.14/0032-USB-dwc2-add-device_reset.patch b/target/linux/ramips/patches-4.14/0032-USB-dwc2-add-device_reset.patch new file mode 100644 index 000000000..623eaf729 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0032-USB-dwc2-add-device_reset.patch @@ -0,0 +1,29 @@ +From a758e0870c6d1e4b0272f6e7f9efa9face5534bb Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 09:49:07 +0100 +Subject: [PATCH 32/53] USB: dwc2: add device_reset() + +Signed-off-by: John Crispin +--- + drivers/usb/dwc2/hcd.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/dwc2/hcd.c ++++ b/drivers/usb/dwc2/hcd.c +@@ -48,6 +48,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -5072,6 +5073,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hso + + retval = -ENOMEM; + ++ device_reset(hsotg->dev); ++ + hcfg = dwc2_readl(hsotg->regs + HCFG); + dev_dbg(hsotg->dev, "hcfg=%08x\n", hcfg); + diff --git a/target/linux/ramips/patches-4.14/0034-NET-multi-phy-support.patch b/target/linux/ramips/patches-4.14/0034-NET-multi-phy-support.patch new file mode 100644 index 000000000..e10f3a31a --- /dev/null +++ b/target/linux/ramips/patches-4.14/0034-NET-multi-phy-support.patch @@ -0,0 +1,59 @@ +From 0b6eb1e68290243d439ee330ea8d0b239a5aec69 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 09:38:50 +0100 +Subject: [PATCH 34/53] NET: multi phy support + +Signed-off-by: John Crispin +--- + drivers/net/phy/phy.c | 9 ++++++--- + include/linux/phy.h | 1 + + 2 files changed, 7 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -980,7 +980,10 @@ void phy_state_machine(struct work_struc + /* If the link is down, give up on negotiation for now */ + if (!phydev->link) { + phydev->state = PHY_NOLINK; +- phy_link_down(phydev, true); ++ if (!phydev->no_auto_carrier_off) ++ phy_link_down(phydev, true); ++ else ++ phy_link_down(phydev, false); + break; + } + +@@ -1067,7 +1070,10 @@ void phy_state_machine(struct work_struc + phy_link_up(phydev); + } else { + phydev->state = PHY_NOLINK; +- phy_link_down(phydev, true); ++ if (!phydev->no_auto_carrier_off) ++ phy_link_down(phydev, true); ++ else ++ phy_link_down(phydev, false); + } + + if (phy_interrupt_is_valid(phydev)) +@@ -1077,7 +1083,10 @@ void phy_state_machine(struct work_struc + case PHY_HALTED: + if (phydev->link) { + phydev->link = 0; +- phy_link_down(phydev, true); ++ if (!phydev->no_auto_carrier_off) ++ phy_link_down(phydev, true); ++ else ++ phy_link_down(phydev, false); + do_suspend = true; + } + break; +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -412,6 +412,7 @@ struct phy_device { + bool suspended; + bool sysfs_links; + bool loopback_enabled; ++ bool no_auto_carrier_off; + + enum phy_state state; + diff --git a/target/linux/ramips/patches-4.14/0036-mtd-fix-cfi-cmdset-0002-erase-status-check.patch b/target/linux/ramips/patches-4.14/0036-mtd-fix-cfi-cmdset-0002-erase-status-check.patch new file mode 100644 index 000000000..0b3a6c40e --- /dev/null +++ b/target/linux/ramips/patches-4.14/0036-mtd-fix-cfi-cmdset-0002-erase-status-check.patch @@ -0,0 +1,29 @@ +From 8e72a3a1be8f6328bd7ef491332ba541547b6086 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 15 Jul 2013 00:38:51 +0200 +Subject: [PATCH 36/53] mtd: fix cfi cmdset 0002 erase status check + +--- + drivers/mtd/chips/cfi_cmdset_0002.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -2293,7 +2293,7 @@ static int __xipram do_erase_chip(struct + chip->erase_suspended = 0; + } + +- if (chip_ready(map, adr)) ++ if (chip_good(map, adr, map_word_ff(map))) + break; + + if (time_after(jiffies, timeo)) { +@@ -2382,7 +2382,7 @@ static int __xipram do_erase_oneblock(st + chip->erase_suspended = 0; + } + +- if (chip_ready(map, adr)) { ++ if (chip_good(map, adr, map_word_ff(map))) { + xip_enable(map, chip, adr); + break; + } diff --git a/target/linux/ramips/patches-4.14/0037-mtd-cfi-cmdset-0002-force-word-write.patch b/target/linux/ramips/patches-4.14/0037-mtd-cfi-cmdset-0002-force-word-write.patch new file mode 100644 index 000000000..8ac6964cd --- /dev/null +++ b/target/linux/ramips/patches-4.14/0037-mtd-cfi-cmdset-0002-force-word-write.patch @@ -0,0 +1,70 @@ +From ee9081b2726a5ca8cde5497afdc5425e21ff8f8b Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 15 Jul 2013 00:39:21 +0200 +Subject: [PATCH 37/53] mtd: cfi cmdset 0002 force word write + +--- + drivers/mtd/chips/cfi_cmdset_0002.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -40,7 +40,7 @@ + #include + + #define AMD_BOOTLOC_BUG +-#define FORCE_WORD_WRITE 0 ++#define FORCE_WORD_WRITE 1 + + #define MAX_WORD_RETRIES 3 + +@@ -51,7 +51,9 @@ + + static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); + static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); ++#if !FORCE_WORD_WRITE + static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); ++#endif + static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *); + static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *); + static void cfi_amdstd_sync (struct mtd_info *); +@@ -202,6 +204,7 @@ static void fixup_amd_bootblock(struct m + } + #endif + ++#if !FORCE_WORD_WRITE + static void fixup_use_write_buffers(struct mtd_info *mtd) + { + struct map_info *map = mtd->priv; +@@ -211,6 +214,7 @@ static void fixup_use_write_buffers(stru + mtd->_write = cfi_amdstd_write_buffers; + } + } ++#endif /* !FORCE_WORD_WRITE */ + + /* Atmel chips don't use the same PRI format as AMD chips */ + static void fixup_convert_atmel_pri(struct mtd_info *mtd) +@@ -1791,6 +1795,7 @@ static int cfi_amdstd_write_words(struct + /* + * FIXME: interleaved mode not tested, and probably not supported! + */ ++#if !FORCE_WORD_WRITE + static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, + unsigned long adr, const u_char *buf, + int len) +@@ -1919,7 +1924,6 @@ static int __xipram do_write_buffer(stru + return ret; + } + +- + static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) + { +@@ -1994,6 +1998,7 @@ static int cfi_amdstd_write_buffers(stru + + return 0; + } ++#endif /* !FORCE_WORD_WRITE */ + + /* + * Wait for the flash chip to become ready to write data diff --git a/target/linux/ramips/patches-4.14/0039-mtd-add-mt7621-nand-support.patch b/target/linux/ramips/patches-4.14/0039-mtd-add-mt7621-nand-support.patch new file mode 100644 index 000000000..97e434466 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0039-mtd-add-mt7621-nand-support.patch @@ -0,0 +1,4480 @@ +From 0e1c4e3c97b83b4e7da65b1c56f0a7d40736ac53 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 11:05:17 +0100 +Subject: [PATCH 39/53] mtd: add mt7621 nand support + +Signed-off-by: John Crispin +--- + drivers/mtd/nand/Kconfig | 6 + + drivers/mtd/nand/Makefile | 1 + + drivers/mtd/nand/bmt.c | 750 ++++++++++++ + drivers/mtd/nand/bmt.h | 80 ++ + drivers/mtd/nand/dev-nand.c | 63 + + drivers/mtd/nand/mt6575_typedefs.h | 340 ++++++ + drivers/mtd/nand/mtk_nand2.c | 2304 +++++++++++++++++++++++++++++++++++ + drivers/mtd/nand/mtk_nand2.h | 452 +++++++ + drivers/mtd/nand/nand_base.c | 6 +- + drivers/mtd/nand/nand_bbt.c | 19 + + drivers/mtd/nand/nand_def.h | 123 ++ + drivers/mtd/nand/nand_device_list.h | 55 + + drivers/mtd/nand/partition.h | 115 ++ + 13 files changed, 4311 insertions(+), 3 deletions(-) + create mode 100644 drivers/mtd/nand/bmt.c + create mode 100644 drivers/mtd/nand/bmt.h + create mode 100644 drivers/mtd/nand/dev-nand.c + create mode 100644 drivers/mtd/nand/mt6575_typedefs.h + create mode 100644 drivers/mtd/nand/mtk_nand2.c + create mode 100644 drivers/mtd/nand/mtk_nand2.h + create mode 100644 drivers/mtd/nand/nand_def.h + create mode 100644 drivers/mtd/nand/nand_device_list.h + create mode 100644 drivers/mtd/nand/partition.h + +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -563,4 +563,10 @@ config MTD_NAND_MTK + Enables support for NAND controller on MTK SoCs. + This controller is found on mt27xx, mt81xx, mt65xx SoCs. + ++config MTK_MTD_NAND ++ tristate "Support for MTK SoC NAND controller" ++ depends on SOC_MT7621 ++ select MTD_NAND_IDS ++ select MTD_NAND_ECC ++ + endif # MTD_NAND +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -60,6 +60,7 @@ obj-$(CONFIG_MTD_NAND_HISI504) + + obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ + obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o + obj-$(CONFIG_MTD_NAND_MTK) += mtk_nand.o mtk_ecc.o ++obj-$(CONFIG_MTK_MTD_NAND) += mtk_nand2.o bmt.o + + nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o + nand-objs += nand_amd.o +--- /dev/null ++++ b/drivers/mtd/nand/bmt.c +@@ -0,0 +1,750 @@ ++#include "bmt.h" ++ ++typedef struct ++{ ++ char signature[3]; ++ u8 version; ++ u8 bad_count; // bad block count in pool ++ u8 mapped_count; // mapped block count in pool ++ u8 checksum; ++ u8 reseverd[13]; ++} phys_bmt_header; ++ ++typedef struct ++{ ++ phys_bmt_header header; ++ bmt_entry table[MAX_BMT_SIZE]; ++} phys_bmt_struct; ++ ++typedef struct ++{ ++ char signature[3]; ++} bmt_oob_data; ++ ++static char MAIN_SIGNATURE[] = "BMT"; ++static char OOB_SIGNATURE[] = "bmt"; ++#define SIGNATURE_SIZE (3) ++ ++#define MAX_DAT_SIZE 0x1000 ++#define MAX_OOB_SIZE 0x80 ++ ++static struct mtd_info *mtd_bmt; ++static struct nand_chip *nand_chip_bmt; ++#define BLOCK_SIZE_BMT (1 << nand_chip_bmt->phys_erase_shift) ++#define PAGE_SIZE_BMT (1 << nand_chip_bmt->page_shift) ++ ++#define OFFSET(block) ((block) * BLOCK_SIZE_BMT) ++#define PAGE_ADDR(block) ((block) * BLOCK_SIZE_BMT / PAGE_SIZE_BMT) ++ ++/********************************************************************* ++* Flash is splited into 2 parts, system part is for normal system * ++* system usage, size is system_block_count, another is replace pool * ++* +-------------------------------------------------+ * ++* | system_block_count | bmt_block_count | * ++* +-------------------------------------------------+ * ++*********************************************************************/ ++static u32 total_block_count; // block number in flash ++static u32 system_block_count; ++static int bmt_block_count; // bmt table size ++// static int bmt_count; // block used in bmt ++static int page_per_block; // page per count ++ ++static u32 bmt_block_index; // bmt block index ++static bmt_struct bmt; // dynamic created global bmt table ++ ++static u8 dat_buf[MAX_DAT_SIZE]; ++static u8 oob_buf[MAX_OOB_SIZE]; ++static bool pool_erased; ++ ++/*************************************************************** ++* ++* Interface adaptor for preloader/uboot/kernel ++* These interfaces operate on physical address, read/write ++* physical data. ++* ++***************************************************************/ ++int nand_read_page_bmt(u32 page, u8 * dat, u8 * oob) ++{ ++ return mtk_nand_exec_read_page(mtd_bmt, page, PAGE_SIZE_BMT, dat, oob); ++} ++ ++bool nand_block_bad_bmt(u32 offset) ++{ ++ return mtk_nand_block_bad_hw(mtd_bmt, offset); ++} ++ ++bool nand_erase_bmt(u32 offset) ++{ ++ int status; ++ if (offset < 0x20000) ++ { ++ MSG(INIT, "erase offset: 0x%x\n", offset); ++ } ++ ++ status = mtk_nand_erase_hw(mtd_bmt, offset / PAGE_SIZE_BMT); // as nand_chip structure doesn't have a erase function defined ++ if (status & NAND_STATUS_FAIL) ++ return false; ++ else ++ return true; ++} ++ ++int mark_block_bad_bmt(u32 offset) ++{ ++ return mtk_nand_block_markbad_hw(mtd_bmt, offset); //mark_block_bad_hw(offset); ++} ++ ++bool nand_write_page_bmt(u32 page, u8 * dat, u8 * oob) ++{ ++ if (mtk_nand_exec_write_page(mtd_bmt, page, PAGE_SIZE_BMT, dat, oob)) ++ return false; ++ else ++ return true; ++} ++ ++/*************************************************************** ++* * ++* static internal function * ++* * ++***************************************************************/ ++static void dump_bmt_info(bmt_struct * bmt) ++{ ++ int i; ++ ++ MSG(INIT, "BMT v%d. total %d mapping:\n", bmt->version, bmt->mapped_count); ++ for (i = 0; i < bmt->mapped_count; i++) ++ { ++ MSG(INIT, "\t0x%x -> 0x%x\n", bmt->table[i].bad_index, bmt->table[i].mapped_index); ++ } ++} ++ ++static bool match_bmt_signature(u8 * dat, u8 * oob) ++{ ++ ++ if (memcmp(dat + MAIN_SIGNATURE_OFFSET, MAIN_SIGNATURE, SIGNATURE_SIZE)) ++ { ++ return false; ++ } ++ ++ if (memcmp(oob + OOB_SIGNATURE_OFFSET, OOB_SIGNATURE, SIGNATURE_SIZE)) ++ { ++ MSG(INIT, "main signature match, oob signature doesn't match, but ignore\n"); ++ } ++ return true; ++} ++ ++static u8 cal_bmt_checksum(phys_bmt_struct * phys_table, int bmt_size) ++{ ++ int i; ++ u8 checksum = 0; ++ u8 *dat = (u8 *) phys_table; ++ ++ checksum += phys_table->header.version; ++ checksum += phys_table->header.mapped_count; ++ ++ dat += sizeof(phys_bmt_header); ++ for (i = 0; i < bmt_size * sizeof(bmt_entry); i++) ++ { ++ checksum += dat[i]; ++ } ++ ++ return checksum; ++} ++ ++ ++static int is_block_mapped(int index) ++{ ++ int i; ++ for (i = 0; i < bmt.mapped_count; i++) ++ { ++ if (index == bmt.table[i].mapped_index) ++ return i; ++ } ++ return -1; ++} ++ ++static bool is_page_used(u8 * dat, u8 * oob) ++{ ++ return ((oob[OOB_INDEX_OFFSET] != 0xFF) || (oob[OOB_INDEX_OFFSET + 1] != 0xFF)); ++} ++ ++static bool valid_bmt_data(phys_bmt_struct * phys_table) ++{ ++ int i; ++ u8 checksum = cal_bmt_checksum(phys_table, bmt_block_count); ++ ++ // checksum correct? ++ if (phys_table->header.checksum != checksum) ++ { ++ MSG(INIT, "BMT Data checksum error: %x %x\n", phys_table->header.checksum, checksum); ++ return false; ++ } ++ ++ MSG(INIT, "BMT Checksum is: 0x%x\n", phys_table->header.checksum); ++ ++ // block index correct? ++ for (i = 0; i < phys_table->header.mapped_count; i++) ++ { ++ if (phys_table->table[i].bad_index >= total_block_count || phys_table->table[i].mapped_index >= total_block_count || phys_table->table[i].mapped_index < system_block_count) ++ { ++ MSG(INIT, "index error: bad_index: %d, mapped_index: %d\n", phys_table->table[i].bad_index, phys_table->table[i].mapped_index); ++ return false; ++ } ++ } ++ ++ // pass check, valid bmt. ++ MSG(INIT, "Valid BMT, version v%d\n", phys_table->header.version); ++ return true; ++} ++ ++static void fill_nand_bmt_buffer(bmt_struct * bmt, u8 * dat, u8 * oob) ++{ ++ phys_bmt_struct phys_bmt; ++ ++ dump_bmt_info(bmt); ++ ++ // fill phys_bmt_struct structure with bmt_struct ++ memset(&phys_bmt, 0xFF, sizeof(phys_bmt)); ++ ++ memcpy(phys_bmt.header.signature, MAIN_SIGNATURE, SIGNATURE_SIZE); ++ phys_bmt.header.version = BMT_VERSION; ++ // phys_bmt.header.bad_count = bmt->bad_count; ++ phys_bmt.header.mapped_count = bmt->mapped_count; ++ memcpy(phys_bmt.table, bmt->table, sizeof(bmt_entry) * bmt_block_count); ++ ++ phys_bmt.header.checksum = cal_bmt_checksum(&phys_bmt, bmt_block_count); ++ ++ memcpy(dat + MAIN_SIGNATURE_OFFSET, &phys_bmt, sizeof(phys_bmt)); ++ memcpy(oob + OOB_SIGNATURE_OFFSET, OOB_SIGNATURE, SIGNATURE_SIZE); ++} ++ ++// return valid index if found BMT, else return 0 ++static int load_bmt_data(int start, int pool_size) ++{ ++ int bmt_index = start + pool_size - 1; // find from the end ++ phys_bmt_struct phys_table; ++ int i; ++ ++ MSG(INIT, "[%s]: begin to search BMT from block 0x%x\n", __FUNCTION__, bmt_index); ++ ++ for (bmt_index = start + pool_size - 1; bmt_index >= start; bmt_index--) ++ { ++ if (nand_block_bad_bmt(OFFSET(bmt_index))) ++ { ++ MSG(INIT, "Skip bad block: %d\n", bmt_index); ++ continue; ++ } ++ ++ if (!nand_read_page_bmt(PAGE_ADDR(bmt_index), dat_buf, oob_buf)) ++ { ++ MSG(INIT, "Error found when read block %d\n", bmt_index); ++ continue; ++ } ++ ++ if (!match_bmt_signature(dat_buf, oob_buf)) ++ { ++ continue; ++ } ++ ++ MSG(INIT, "Match bmt signature @ block: 0x%x\n", bmt_index); ++ ++ memcpy(&phys_table, dat_buf + MAIN_SIGNATURE_OFFSET, sizeof(phys_table)); ++ ++ if (!valid_bmt_data(&phys_table)) ++ { ++ MSG(INIT, "BMT data is not correct %d\n", bmt_index); ++ continue; ++ } else ++ { ++ bmt.mapped_count = phys_table.header.mapped_count; ++ bmt.version = phys_table.header.version; ++ // bmt.bad_count = phys_table.header.bad_count; ++ memcpy(bmt.table, phys_table.table, bmt.mapped_count * sizeof(bmt_entry)); ++ ++ MSG(INIT, "bmt found at block: %d, mapped block: %d\n", bmt_index, bmt.mapped_count); ++ ++ for (i = 0; i < bmt.mapped_count; i++) ++ { ++ if (!nand_block_bad_bmt(OFFSET(bmt.table[i].bad_index))) ++ { ++ MSG(INIT, "block 0x%x is not mark bad, should be power lost last time\n", bmt.table[i].bad_index); ++ mark_block_bad_bmt(OFFSET(bmt.table[i].bad_index)); ++ } ++ } ++ ++ return bmt_index; ++ } ++ } ++ ++ MSG(INIT, "bmt block not found!\n"); ++ return 0; ++} ++ ++/************************************************************************* ++* Find an available block and erase. * ++* start_from_end: if true, find available block from end of flash. * ++* else, find from the beginning of the pool * ++* need_erase: if true, all unmapped blocks in the pool will be erased * ++*************************************************************************/ ++static int find_available_block(bool start_from_end) ++{ ++ int i; // , j; ++ int block = system_block_count; ++ int direction; ++ // int avail_index = 0; ++ MSG(INIT, "Try to find_available_block, pool_erase: %d\n", pool_erased); ++ ++ // erase all un-mapped blocks in pool when finding avaliable block ++ if (!pool_erased) ++ { ++ MSG(INIT, "Erase all un-mapped blocks in pool\n"); ++ for (i = 0; i < bmt_block_count; i++) ++ { ++ if (block == bmt_block_index) ++ { ++ MSG(INIT, "Skip bmt block 0x%x\n", block); ++ continue; ++ } ++ ++ if (nand_block_bad_bmt(OFFSET(block + i))) ++ { ++ MSG(INIT, "Skip bad block 0x%x\n", block + i); ++ continue; ++ } ++//if(block==4095) ++//{ ++// continue; ++//} ++ ++ if (is_block_mapped(block + i) >= 0) ++ { ++ MSG(INIT, "Skip mapped block 0x%x\n", block + i); ++ continue; ++ } ++ ++ if (!nand_erase_bmt(OFFSET(block + i))) ++ { ++ MSG(INIT, "Erase block 0x%x failed\n", block + i); ++ mark_block_bad_bmt(OFFSET(block + i)); ++ } ++ } ++ ++ pool_erased = 1; ++ } ++ ++ if (start_from_end) ++ { ++ block = total_block_count - 1; ++ direction = -1; ++ } else ++ { ++ block = system_block_count; ++ direction = 1; ++ } ++ ++ for (i = 0; i < bmt_block_count; i++, block += direction) ++ { ++ if (block == bmt_block_index) ++ { ++ MSG(INIT, "Skip bmt block 0x%x\n", block); ++ continue; ++ } ++ ++ if (nand_block_bad_bmt(OFFSET(block))) ++ { ++ MSG(INIT, "Skip bad block 0x%x\n", block); ++ continue; ++ } ++ ++ if (is_block_mapped(block) >= 0) ++ { ++ MSG(INIT, "Skip mapped block 0x%x\n", block); ++ continue; ++ } ++ ++ MSG(INIT, "Find block 0x%x available\n", block); ++ return block; ++ } ++ ++ return 0; ++} ++ ++static unsigned short get_bad_index_from_oob(u8 * oob_buf) ++{ ++ unsigned short index; ++ memcpy(&index, oob_buf + OOB_INDEX_OFFSET, OOB_INDEX_SIZE); ++ ++ return index; ++} ++ ++void set_bad_index_to_oob(u8 * oob, u16 index) ++{ ++ memcpy(oob + OOB_INDEX_OFFSET, &index, sizeof(index)); ++} ++ ++static int migrate_from_bad(int offset, u8 * write_dat, u8 * write_oob) ++{ ++ int page; ++ int error_block = offset / BLOCK_SIZE_BMT; ++ int error_page = (offset / PAGE_SIZE_BMT) % page_per_block; ++ int to_index; ++ ++ memcpy(oob_buf, write_oob, MAX_OOB_SIZE); ++ ++ to_index = find_available_block(false); ++ ++ if (!to_index) ++ { ++ MSG(INIT, "Cannot find an available block for BMT\n"); ++ return 0; ++ } ++ ++ { // migrate error page first ++ MSG(INIT, "Write error page: 0x%x\n", error_page); ++ if (!write_dat) ++ { ++ nand_read_page_bmt(PAGE_ADDR(error_block) + error_page, dat_buf, NULL); ++ write_dat = dat_buf; ++ } ++ // memcpy(oob_buf, write_oob, MAX_OOB_SIZE); ++ ++ if (error_block < system_block_count) ++ set_bad_index_to_oob(oob_buf, error_block); // if error_block is already a mapped block, original mapping index is in OOB. ++ ++ if (!nand_write_page_bmt(PAGE_ADDR(to_index) + error_page, write_dat, oob_buf)) ++ { ++ MSG(INIT, "Write to page 0x%x fail\n", PAGE_ADDR(to_index) + error_page); ++ mark_block_bad_bmt(to_index); ++ return migrate_from_bad(offset, write_dat, write_oob); ++ } ++ } ++ ++ for (page = 0; page < page_per_block; page++) ++ { ++ if (page != error_page) ++ { ++ nand_read_page_bmt(PAGE_ADDR(error_block) + page, dat_buf, oob_buf); ++ if (is_page_used(dat_buf, oob_buf)) ++ { ++ if (error_block < system_block_count) ++ { ++ set_bad_index_to_oob(oob_buf, error_block); ++ } ++ MSG(INIT, "\tmigrate page 0x%x to page 0x%x\n", PAGE_ADDR(error_block) + page, PAGE_ADDR(to_index) + page); ++ if (!nand_write_page_bmt(PAGE_ADDR(to_index) + page, dat_buf, oob_buf)) ++ { ++ MSG(INIT, "Write to page 0x%x fail\n", PAGE_ADDR(to_index) + page); ++ mark_block_bad_bmt(to_index); ++ return migrate_from_bad(offset, write_dat, write_oob); ++ } ++ } ++ } ++ } ++ ++ MSG(INIT, "Migrate from 0x%x to 0x%x done!\n", error_block, to_index); ++ ++ return to_index; ++} ++ ++static bool write_bmt_to_flash(u8 * dat, u8 * oob) ++{ ++ bool need_erase = true; ++ MSG(INIT, "Try to write BMT\n"); ++ ++ if (bmt_block_index == 0) ++ { ++ // if we don't have index, we don't need to erase found block as it has been erased in find_available_block() ++ need_erase = false; ++ if (!(bmt_block_index = find_available_block(true))) ++ { ++ MSG(INIT, "Cannot find an available block for BMT\n"); ++ return false; ++ } ++ } ++ ++ MSG(INIT, "Find BMT block: 0x%x\n", bmt_block_index); ++ ++ // write bmt to flash ++ if (need_erase) ++ { ++ if (!nand_erase_bmt(OFFSET(bmt_block_index))) ++ { ++ MSG(INIT, "BMT block erase fail, mark bad: 0x%x\n", bmt_block_index); ++ mark_block_bad_bmt(OFFSET(bmt_block_index)); ++ // bmt.bad_count++; ++ ++ bmt_block_index = 0; ++ return write_bmt_to_flash(dat, oob); // recursive call ++ } ++ } ++ ++ if (!nand_write_page_bmt(PAGE_ADDR(bmt_block_index), dat, oob)) ++ { ++ MSG(INIT, "Write BMT data fail, need to write again\n"); ++ mark_block_bad_bmt(OFFSET(bmt_block_index)); ++ // bmt.bad_count++; ++ ++ bmt_block_index = 0; ++ return write_bmt_to_flash(dat, oob); // recursive call ++ } ++ ++ MSG(INIT, "Write BMT data to block 0x%x success\n", bmt_block_index); ++ return true; ++} ++ ++/******************************************************************* ++* Reconstruct bmt, called when found bmt info doesn't match bad ++* block info in flash. ++* ++* Return NULL for failure ++*******************************************************************/ ++bmt_struct *reconstruct_bmt(bmt_struct * bmt) ++{ ++ int i; ++ int index = system_block_count; ++ unsigned short bad_index; ++ int mapped; ++ ++ // init everything in BMT struct ++ bmt->version = BMT_VERSION; ++ bmt->bad_count = 0; ++ bmt->mapped_count = 0; ++ ++ memset(bmt->table, 0, bmt_block_count * sizeof(bmt_entry)); ++ ++ for (i = 0; i < bmt_block_count; i++, index++) ++ { ++ if (nand_block_bad_bmt(OFFSET(index))) ++ { ++ MSG(INIT, "Skip bad block: 0x%x\n", index); ++ // bmt->bad_count++; ++ continue; ++ } ++ ++ MSG(INIT, "read page: 0x%x\n", PAGE_ADDR(index)); ++ nand_read_page_bmt(PAGE_ADDR(index), dat_buf, oob_buf); ++ /* if (mtk_nand_read_page_hw(PAGE_ADDR(index), dat_buf)) ++ { ++ MSG(INIT, "Error when read block %d\n", bmt_block_index); ++ continue; ++ } */ ++ ++ if ((bad_index = get_bad_index_from_oob(oob_buf)) >= system_block_count) ++ { ++ MSG(INIT, "get bad index: 0x%x\n", bad_index); ++ if (bad_index != 0xFFFF) ++ MSG(INIT, "Invalid bad index found in block 0x%x, bad index 0x%x\n", index, bad_index); ++ continue; ++ } ++ ++ MSG(INIT, "Block 0x%x is mapped to bad block: 0x%x\n", index, bad_index); ++ ++ if (!nand_block_bad_bmt(OFFSET(bad_index))) ++ { ++ MSG(INIT, "\tbut block 0x%x is not marked as bad, invalid mapping\n", bad_index); ++ continue; // no need to erase here, it will be erased later when trying to write BMT ++ } ++ ++ if ((mapped = is_block_mapped(bad_index)) >= 0) ++ { ++ MSG(INIT, "bad block 0x%x is mapped to 0x%x, should be caused by power lost, replace with one\n", bmt->table[mapped].bad_index, bmt->table[mapped].mapped_index); ++ bmt->table[mapped].mapped_index = index; // use new one instead. ++ } else ++ { ++ // add mapping to BMT ++ bmt->table[bmt->mapped_count].bad_index = bad_index; ++ bmt->table[bmt->mapped_count].mapped_index = index; ++ bmt->mapped_count++; ++ } ++ ++ MSG(INIT, "Add mapping: 0x%x -> 0x%x to BMT\n", bad_index, index); ++ ++ } ++ ++ MSG(INIT, "Scan replace pool done, mapped block: %d\n", bmt->mapped_count); ++ // dump_bmt_info(bmt); ++ ++ // fill NAND BMT buffer ++ memset(oob_buf, 0xFF, sizeof(oob_buf)); ++ fill_nand_bmt_buffer(bmt, dat_buf, oob_buf); ++ ++ // write BMT back ++ if (!write_bmt_to_flash(dat_buf, oob_buf)) ++ { ++ MSG(INIT, "TRAGEDY: cannot find a place to write BMT!!!!\n"); ++ } ++ ++ return bmt; ++} ++ ++/******************************************************************* ++* [BMT Interface] ++* ++* Description: ++* Init bmt from nand. Reconstruct if not found or data error ++* ++* Parameter: ++* size: size of bmt and replace pool ++* ++* Return: ++* NULL for failure, and a bmt struct for success ++*******************************************************************/ ++bmt_struct *init_bmt(struct nand_chip * chip, int size) ++{ ++ struct mtk_nand_host *host; ++ ++ if (size > 0 && size < MAX_BMT_SIZE) ++ { ++ MSG(INIT, "Init bmt table, size: %d\n", size); ++ bmt_block_count = size; ++ } else ++ { ++ MSG(INIT, "Invalid bmt table size: %d\n", size); ++ return NULL; ++ } ++ nand_chip_bmt = chip; ++ system_block_count = chip->chipsize >> chip->phys_erase_shift; ++ total_block_count = bmt_block_count + system_block_count; ++ page_per_block = BLOCK_SIZE_BMT / PAGE_SIZE_BMT; ++ host = (struct mtk_nand_host *)chip->priv; ++ mtd_bmt = host->mtd; ++ ++ MSG(INIT, "mtd_bmt: %p, nand_chip_bmt: %p\n", mtd_bmt, nand_chip_bmt); ++ MSG(INIT, "bmt count: %d, system count: %d\n", bmt_block_count, system_block_count); ++ ++ // set this flag, and unmapped block in pool will be erased. ++ pool_erased = 0; ++ memset(bmt.table, 0, size * sizeof(bmt_entry)); ++ if ((bmt_block_index = load_bmt_data(system_block_count, size))) ++ { ++ MSG(INIT, "Load bmt data success @ block 0x%x\n", bmt_block_index); ++ dump_bmt_info(&bmt); ++ return &bmt; ++ } else ++ { ++ MSG(INIT, "Load bmt data fail, need re-construct!\n"); ++#ifndef __UBOOT_NAND__ // BMT is not re-constructed in UBOOT. ++ if (reconstruct_bmt(&bmt)) ++ return &bmt; ++ else ++#endif ++ return NULL; ++ } ++} ++ ++/******************************************************************* ++* [BMT Interface] ++* ++* Description: ++* Update BMT. ++* ++* Parameter: ++* offset: update block/page offset. ++* reason: update reason, see update_reason_t for reason. ++* dat/oob: data and oob buffer for write fail. ++* ++* Return: ++* Return true for success, and false for failure. ++*******************************************************************/ ++bool update_bmt(u32 offset, update_reason_t reason, u8 * dat, u8 * oob) ++{ ++ int map_index; ++ int orig_bad_block = -1; ++ // int bmt_update_index; ++ int i; ++ int bad_index = offset / BLOCK_SIZE_BMT; ++ ++#ifndef MTK_NAND_BMT ++ return false; ++#endif ++ if (reason == UPDATE_WRITE_FAIL) ++ { ++ MSG(INIT, "Write fail, need to migrate\n"); ++ if (!(map_index = migrate_from_bad(offset, dat, oob))) ++ { ++ MSG(INIT, "migrate fail\n"); ++ return false; ++ } ++ } else ++ { ++ if (!(map_index = find_available_block(false))) ++ { ++ MSG(INIT, "Cannot find block in pool\n"); ++ return false; ++ } ++ } ++ ++ // now let's update BMT ++ if (bad_index >= system_block_count) // mapped block become bad, find original bad block ++ { ++ for (i = 0; i < bmt_block_count; i++) ++ { ++ if (bmt.table[i].mapped_index == bad_index) ++ { ++ orig_bad_block = bmt.table[i].bad_index; ++ break; ++ } ++ } ++ // bmt.bad_count++; ++ MSG(INIT, "Mapped block becomes bad, orig bad block is 0x%x\n", orig_bad_block); ++ ++ bmt.table[i].mapped_index = map_index; ++ } else ++ { ++ bmt.table[bmt.mapped_count].mapped_index = map_index; ++ bmt.table[bmt.mapped_count].bad_index = bad_index; ++ bmt.mapped_count++; ++ } ++ ++ memset(oob_buf, 0xFF, sizeof(oob_buf)); ++ fill_nand_bmt_buffer(&bmt, dat_buf, oob_buf); ++ if (!write_bmt_to_flash(dat_buf, oob_buf)) ++ return false; ++ ++ mark_block_bad_bmt(offset); ++ ++ return true; ++} ++ ++/******************************************************************* ++* [BMT Interface] ++* ++* Description: ++* Given an block index, return mapped index if it's mapped, else ++* return given index. ++* ++* Parameter: ++* index: given an block index. This value cannot exceed ++* system_block_count. ++* ++* Return NULL for failure ++*******************************************************************/ ++u16 get_mapping_block_index(int index) ++{ ++ int i; ++#ifndef MTK_NAND_BMT ++ return index; ++#endif ++ if (index > system_block_count) ++ { ++ return index; ++ } ++ ++ for (i = 0; i < bmt.mapped_count; i++) ++ { ++ if (bmt.table[i].bad_index == index) ++ { ++ return bmt.table[i].mapped_index; ++ } ++ } ++ ++ return index; ++} ++#ifdef __KERNEL_NAND__ ++EXPORT_SYMBOL_GPL(init_bmt); ++EXPORT_SYMBOL_GPL(update_bmt); ++EXPORT_SYMBOL_GPL(get_mapping_block_index); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("MediaTek"); ++MODULE_DESCRIPTION("Bad Block mapping management for MediaTek NAND Flash Driver"); ++#endif +--- /dev/null ++++ b/drivers/mtd/nand/bmt.h +@@ -0,0 +1,80 @@ ++#ifndef __BMT_H__ ++#define __BMT_H__ ++ ++#include "nand_def.h" ++ ++#if defined(__PRELOADER_NAND__) ++ ++#include "nand.h" ++ ++#elif defined(__UBOOT_NAND__) ++ ++#include ++#include "mtk_nand2.h" ++ ++#elif defined(__KERNEL_NAND__) ++ ++#include ++#include ++#include ++#include "mtk_nand2.h" ++ ++#endif ++ ++ ++#define MAX_BMT_SIZE (0x80) ++#define BMT_VERSION (1) // initial version ++ ++#define MAIN_SIGNATURE_OFFSET (0) ++#define OOB_SIGNATURE_OFFSET (1) ++#define OOB_INDEX_OFFSET (29) ++#define OOB_INDEX_SIZE (2) ++#define FAKE_INDEX (0xAAAA) ++ ++typedef struct _bmt_entry_ ++{ ++ u16 bad_index; // bad block index ++ u16 mapped_index; // mapping block index in the replace pool ++} bmt_entry; ++ ++typedef enum ++{ ++ UPDATE_ERASE_FAIL, ++ UPDATE_WRITE_FAIL, ++ UPDATE_UNMAPPED_BLOCK, ++ UPDATE_REASON_COUNT, ++} update_reason_t; ++ ++typedef struct ++{ ++ bmt_entry table[MAX_BMT_SIZE]; ++ u8 version; ++ u8 mapped_count; // mapped block count in pool ++ u8 bad_count; // bad block count in pool. Not used in V1 ++} bmt_struct; ++ ++/*************************************************************** ++* * ++* Interface BMT need to use * ++* * ++***************************************************************/ ++extern bool mtk_nand_exec_read_page(struct mtd_info *mtd, u32 row, u32 page_size, u8 * dat, u8 * oob); ++extern int mtk_nand_block_bad_hw(struct mtd_info *mtd, loff_t ofs); ++extern int mtk_nand_erase_hw(struct mtd_info *mtd, int page); ++extern int mtk_nand_block_markbad_hw(struct mtd_info *mtd, loff_t ofs); ++extern int mtk_nand_exec_write_page(struct mtd_info *mtd, u32 row, u32 page_size, u8 * dat, u8 * oob); ++ ++ ++/*************************************************************** ++* * ++* Different function interface for preloader/uboot/kernel * ++* * ++***************************************************************/ ++void set_bad_index_to_oob(u8 * oob, u16 index); ++ ++ ++bmt_struct *init_bmt(struct nand_chip *nand, int size); ++bool update_bmt(u32 offset, update_reason_t reason, u8 * dat, u8 * oob); ++unsigned short get_mapping_block_index(int index); ++ ++#endif // #ifndef __BMT_H__ +--- /dev/null ++++ b/drivers/mtd/nand/dev-nand.c +@@ -0,0 +1,63 @@ ++#include ++#include ++#include ++ ++#include "mt6575_typedefs.h" ++ ++#define RALINK_NAND_CTRL_BASE 0xBE003000 ++#define NFI_base RALINK_NAND_CTRL_BASE ++#define RALINK_NANDECC_CTRL_BASE 0xBE003800 ++#define NFIECC_base RALINK_NANDECC_CTRL_BASE ++#define MT7621_NFI_IRQ_ID SURFBOARDINT_NAND ++#define MT7621_NFIECC_IRQ_ID SURFBOARDINT_NAND_ECC ++ ++#define SURFBOARDINT_NAND 22 ++#define SURFBOARDINT_NAND_ECC 23 ++ ++static struct resource MT7621_resource_nand[] = { ++ { ++ .start = NFI_base, ++ .end = NFI_base + 0x1A0, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = NFIECC_base, ++ .end = NFIECC_base + 0x150, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = MT7621_NFI_IRQ_ID, ++ .flags = IORESOURCE_IRQ, ++ }, ++ { ++ .start = MT7621_NFIECC_IRQ_ID, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device MT7621_nand_dev = { ++ .name = "MT7621-NAND", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(MT7621_resource_nand), ++ .resource = MT7621_resource_nand, ++ .dev = { ++ .platform_data = &mt7621_nand_hw, ++ }, ++}; ++ ++ ++int __init mtk_nand_register(void) ++{ ++ ++ int retval = 0; ++ ++ retval = platform_device_register(&MT7621_nand_dev); ++ if (retval != 0) { ++ printk(KERN_ERR "register nand device fail\n"); ++ return retval; ++ } ++ ++ ++ return retval; ++} ++arch_initcall(mtk_nand_register); +--- /dev/null ++++ b/drivers/mtd/nand/mt6575_typedefs.h +@@ -0,0 +1,340 @@ ++/* Copyright Statement: ++ * ++ * This software/firmware and related documentation ("MediaTek Software") are ++ * protected under relevant copyright laws. The information contained herein ++ * is confidential and proprietary to MediaTek Inc. and/or its licensors. ++ * Without the prior written permission of MediaTek inc. and/or its licensors, ++ * any reproduction, modification, use or disclosure of MediaTek Software, ++ * and information contained herein, in whole or in part, shall be strictly prohibited. ++ */ ++/* MediaTek Inc. (C) 2010. All rights reserved. ++ * ++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON ++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH ++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES ++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES ++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK ++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR ++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND ++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO ++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++ * ++ * The following software/firmware and/or related documentation ("MediaTek Software") ++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's ++ * applicable license agreements with MediaTek Inc. ++ */ ++ ++/***************************************************************************** ++* Copyright Statement: ++* -------------------- ++* This software is protected by Copyright and the information contained ++* herein is confidential. The software may not be copied and the information ++* contained herein may not be used or disclosed except with the written ++* permission of MediaTek Inc. (C) 2008 ++* ++* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON ++* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH ++* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO ++* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S ++* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. ++* ++* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE ++* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO ++* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++* ++* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE ++* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF ++* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND ++* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER ++* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC). ++* ++*****************************************************************************/ ++ ++#ifndef _MT6575_TYPEDEFS_H ++#define _MT6575_TYPEDEFS_H ++ ++#if defined (__KERNEL_NAND__) ++#include ++#else ++#define true 1 ++#define false 0 ++#define bool u8 ++#endif ++ ++// --------------------------------------------------------------------------- ++// Basic Type Definitions ++// --------------------------------------------------------------------------- ++ ++typedef volatile unsigned char *P_kal_uint8; ++typedef volatile unsigned short *P_kal_uint16; ++typedef volatile unsigned int *P_kal_uint32; ++ ++typedef long LONG; ++typedef unsigned char UBYTE; ++typedef short SHORT; ++ ++typedef signed char kal_int8; ++typedef signed short kal_int16; ++typedef signed int kal_int32; ++typedef long long kal_int64; ++typedef unsigned char kal_uint8; ++typedef unsigned short kal_uint16; ++typedef unsigned int kal_uint32; ++typedef unsigned long long kal_uint64; ++typedef char kal_char; ++ ++typedef unsigned int *UINT32P; ++typedef volatile unsigned short *UINT16P; ++typedef volatile unsigned char *UINT8P; ++typedef unsigned char *U8P; ++ ++typedef volatile unsigned char *P_U8; ++typedef volatile signed char *P_S8; ++typedef volatile unsigned short *P_U16; ++typedef volatile signed short *P_S16; ++typedef volatile unsigned int *P_U32; ++typedef volatile signed int *P_S32; ++typedef unsigned long long *P_U64; ++typedef signed long long *P_S64; ++ ++typedef unsigned char U8; ++typedef signed char S8; ++typedef unsigned short U16; ++typedef signed short S16; ++typedef unsigned int U32; ++typedef signed int S32; ++typedef unsigned long long U64; ++typedef signed long long S64; ++//typedef unsigned char bool; ++ ++typedef unsigned char UINT8; ++typedef unsigned short UINT16; ++typedef unsigned int UINT32; ++typedef unsigned short USHORT; ++typedef signed char INT8; ++typedef signed short INT16; ++typedef signed int INT32; ++typedef unsigned int DWORD; ++typedef void VOID; ++typedef unsigned char BYTE; ++typedef float FLOAT; ++ ++typedef char *LPCSTR; ++typedef short *LPWSTR; ++ ++ ++// --------------------------------------------------------------------------- ++// Constants ++// --------------------------------------------------------------------------- ++ ++#define IMPORT EXTERN ++#ifndef __cplusplus ++ #define EXTERN extern ++#else ++ #define EXTERN extern "C" ++#endif ++#define LOCAL static ++#define GLOBAL ++#define EXPORT GLOBAL ++ ++#define EQ == ++#define NEQ != ++#define AND && ++#define OR || ++#define XOR(A,B) ((!(A) AND (B)) OR ((A) AND !(B))) ++ ++#ifndef FALSE ++ #define FALSE (0) ++#endif ++ ++#ifndef TRUE ++ #define TRUE (1) ++#endif ++ ++#ifndef NULL ++ #define NULL (0) ++#endif ++ ++//enum boolean {false, true}; ++enum {RX, TX, NONE}; ++ ++#ifndef BOOL ++typedef unsigned char BOOL; ++#endif ++ ++typedef enum { ++ KAL_FALSE = 0, ++ KAL_TRUE = 1, ++} kal_bool; ++ ++ ++// --------------------------------------------------------------------------- ++// Type Casting ++// --------------------------------------------------------------------------- ++ ++#define AS_INT32(x) (*(INT32 *)((void*)x)) ++#define AS_INT16(x) (*(INT16 *)((void*)x)) ++#define AS_INT8(x) (*(INT8 *)((void*)x)) ++ ++#define AS_UINT32(x) (*(UINT32 *)((void*)x)) ++#define AS_UINT16(x) (*(UINT16 *)((void*)x)) ++#define AS_UINT8(x) (*(UINT8 *)((void*)x)) ++ ++ ++// --------------------------------------------------------------------------- ++// Register Manipulations ++// --------------------------------------------------------------------------- ++ ++#define READ_REGISTER_UINT32(reg) \ ++ (*(volatile UINT32 * const)(reg)) ++ ++#define WRITE_REGISTER_UINT32(reg, val) \ ++ (*(volatile UINT32 * const)(reg)) = (val) ++ ++#define READ_REGISTER_UINT16(reg) \ ++ (*(volatile UINT16 * const)(reg)) ++ ++#define WRITE_REGISTER_UINT16(reg, val) \ ++ (*(volatile UINT16 * const)(reg)) = (val) ++ ++#define READ_REGISTER_UINT8(reg) \ ++ (*(volatile UINT8 * const)(reg)) ++ ++#define WRITE_REGISTER_UINT8(reg, val) \ ++ (*(volatile UINT8 * const)(reg)) = (val) ++ ++#define INREG8(x) READ_REGISTER_UINT8((UINT8*)((void*)(x))) ++#define OUTREG8(x, y) WRITE_REGISTER_UINT8((UINT8*)((void*)(x)), (UINT8)(y)) ++#define SETREG8(x, y) OUTREG8(x, INREG8(x)|(y)) ++#define CLRREG8(x, y) OUTREG8(x, INREG8(x)&~(y)) ++#define MASKREG8(x, y, z) OUTREG8(x, (INREG8(x)&~(y))|(z)) ++ ++#define INREG16(x) READ_REGISTER_UINT16((UINT16*)((void*)(x))) ++#define OUTREG16(x, y) WRITE_REGISTER_UINT16((UINT16*)((void*)(x)),(UINT16)(y)) ++#define SETREG16(x, y) OUTREG16(x, INREG16(x)|(y)) ++#define CLRREG16(x, y) OUTREG16(x, INREG16(x)&~(y)) ++#define MASKREG16(x, y, z) OUTREG16(x, (INREG16(x)&~(y))|(z)) ++ ++#define INREG32(x) READ_REGISTER_UINT32((UINT32*)((void*)(x))) ++#define OUTREG32(x, y) WRITE_REGISTER_UINT32((UINT32*)((void*)(x)), (UINT32)(y)) ++#define SETREG32(x, y) OUTREG32(x, INREG32(x)|(y)) ++#define CLRREG32(x, y) OUTREG32(x, INREG32(x)&~(y)) ++#define MASKREG32(x, y, z) OUTREG32(x, (INREG32(x)&~(y))|(z)) ++ ++ ++#define DRV_Reg8(addr) INREG8(addr) ++#define DRV_WriteReg8(addr, data) OUTREG8(addr, data) ++#define DRV_SetReg8(addr, data) SETREG8(addr, data) ++#define DRV_ClrReg8(addr, data) CLRREG8(addr, data) ++ ++#define DRV_Reg16(addr) INREG16(addr) ++#define DRV_WriteReg16(addr, data) OUTREG16(addr, data) ++#define DRV_SetReg16(addr, data) SETREG16(addr, data) ++#define DRV_ClrReg16(addr, data) CLRREG16(addr, data) ++ ++#define DRV_Reg32(addr) INREG32(addr) ++#define DRV_WriteReg32(addr, data) OUTREG32(addr, data) ++#define DRV_SetReg32(addr, data) SETREG32(addr, data) ++#define DRV_ClrReg32(addr, data) CLRREG32(addr, data) ++ ++// !!! DEPRECATED, WILL BE REMOVED LATER !!! ++#define DRV_Reg(addr) DRV_Reg16(addr) ++#define DRV_WriteReg(addr, data) DRV_WriteReg16(addr, data) ++#define DRV_SetReg(addr, data) DRV_SetReg16(addr, data) ++#define DRV_ClrReg(addr, data) DRV_ClrReg16(addr, data) ++ ++ ++// --------------------------------------------------------------------------- ++// Compiler Time Deduction Macros ++// --------------------------------------------------------------------------- ++ ++#define _MASK_OFFSET_1(x, n) ((x) & 0x1) ? (n) : ++#define _MASK_OFFSET_2(x, n) _MASK_OFFSET_1((x), (n)) _MASK_OFFSET_1((x) >> 1, (n) + 1) ++#define _MASK_OFFSET_4(x, n) _MASK_OFFSET_2((x), (n)) _MASK_OFFSET_2((x) >> 2, (n) + 2) ++#define _MASK_OFFSET_8(x, n) _MASK_OFFSET_4((x), (n)) _MASK_OFFSET_4((x) >> 4, (n) + 4) ++#define _MASK_OFFSET_16(x, n) _MASK_OFFSET_8((x), (n)) _MASK_OFFSET_8((x) >> 8, (n) + 8) ++#define _MASK_OFFSET_32(x, n) _MASK_OFFSET_16((x), (n)) _MASK_OFFSET_16((x) >> 16, (n) + 16) ++ ++#define MASK_OFFSET_ERROR (0xFFFFFFFF) ++ ++#define MASK_OFFSET(x) (_MASK_OFFSET_32(x, 0) MASK_OFFSET_ERROR) ++ ++ ++// --------------------------------------------------------------------------- ++// Assertions ++// --------------------------------------------------------------------------- ++ ++#ifndef ASSERT ++ #define ASSERT(expr) BUG_ON(!(expr)) ++#endif ++ ++#ifndef NOT_IMPLEMENTED ++ #define NOT_IMPLEMENTED() BUG_ON(1) ++#endif ++ ++#define STATIC_ASSERT(pred) STATIC_ASSERT_X(pred, __LINE__) ++#define STATIC_ASSERT_X(pred, line) STATIC_ASSERT_XX(pred, line) ++#define STATIC_ASSERT_XX(pred, line) \ ++ extern char assertion_failed_at_##line[(pred) ? 1 : -1] ++ ++// --------------------------------------------------------------------------- ++// Resolve Compiler Warnings ++// --------------------------------------------------------------------------- ++ ++#define NOT_REFERENCED(x) { (x) = (x); } ++ ++ ++// --------------------------------------------------------------------------- ++// Utilities ++// --------------------------------------------------------------------------- ++ ++#define MAXIMUM(A,B) (((A)>(B))?(A):(B)) ++#define MINIMUM(A,B) (((A)<(B))?(A):(B)) ++ ++#define ARY_SIZE(x) (sizeof((x)) / sizeof((x[0]))) ++#define DVT_DELAYMACRO(u4Num) \ ++{ \ ++ UINT32 u4Count = 0 ; \ ++ for (u4Count = 0; u4Count < u4Num; u4Count++ ); \ ++} \ ++ ++#define A68351B 0 ++#define B68351B 1 ++#define B68351D 2 ++#define B68351E 3 ++#define UNKNOWN_IC_VERSION 0xFF ++ ++/* NAND driver */ ++struct mtk_nand_host_hw { ++ unsigned int nfi_bus_width; /* NFI_BUS_WIDTH */ ++ unsigned int nfi_access_timing; /* NFI_ACCESS_TIMING */ ++ unsigned int nfi_cs_num; /* NFI_CS_NUM */ ++ unsigned int nand_sec_size; /* NAND_SECTOR_SIZE */ ++ unsigned int nand_sec_shift; /* NAND_SECTOR_SHIFT */ ++ unsigned int nand_ecc_size; ++ unsigned int nand_ecc_bytes; ++ unsigned int nand_ecc_mode; ++}; ++extern struct mtk_nand_host_hw mt7621_nand_hw; ++extern unsigned int CFG_BLOCKSIZE; ++ ++#endif // _MT6575_TYPEDEFS_H ++ +--- /dev/null ++++ b/drivers/mtd/nand/mtk_nand2.c +@@ -0,0 +1,2363 @@ ++/****************************************************************************** ++* mtk_nand2.c - MTK NAND Flash Device Driver ++ * ++* Copyright 2009-2012 MediaTek Co.,Ltd. ++ * ++* DESCRIPTION: ++* This file provid the other drivers nand relative functions ++ * ++* modification history ++* ---------------------------------------- ++* v3.0, 11 Feb 2010, mtk ++* ---------------------------------------- ++******************************************************************************/ ++#include "nand_def.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "mtk_nand2.h" ++#include "nand_device_list.h" ++ ++#include "bmt.h" ++#include "partition.h" ++ ++unsigned int CFG_BLOCKSIZE; ++ ++static int shift_on_bbt = 0; ++extern void nand_bbt_set(struct mtd_info *mtd, int page, int flag); ++extern int nand_bbt_get(struct mtd_info *mtd, int page); ++int mtk_nand_read_oob_hw(struct mtd_info *mtd, struct nand_chip *chip, int page); ++ ++static const char * const probe_types[] = { "cmdlinepart", "ofpart", NULL }; ++ ++#define NAND_CMD_STATUS_MULTI 0x71 ++ ++void show_stack(struct task_struct *tsk, unsigned long *sp); ++extern void mt_irq_set_sens(unsigned int irq, unsigned int sens); ++extern void mt_irq_set_polarity(unsigned int irq,unsigned int polarity); ++ ++struct mtk_nand_host mtk_nand_host; /* include mtd_info and nand_chip structs */ ++struct mtk_nand_host_hw mt7621_nand_hw = { ++ .nfi_bus_width = 8, ++ .nfi_access_timing = NFI_DEFAULT_ACCESS_TIMING, ++ .nfi_cs_num = NFI_CS_NUM, ++ .nand_sec_size = 512, ++ .nand_sec_shift = 9, ++ .nand_ecc_size = 2048, ++ .nand_ecc_bytes = 32, ++ .nand_ecc_mode = NAND_ECC_HW, ++}; ++ ++ ++/******************************************************************************* ++ * Gloable Varible Definition ++ *******************************************************************************/ ++ ++#define NFI_ISSUE_COMMAND(cmd, col_addr, row_addr, col_num, row_num) \ ++ do { \ ++ DRV_WriteReg(NFI_CMD_REG16,cmd);\ ++ while (DRV_Reg32(NFI_STA_REG32) & STA_CMD_STATE);\ ++ DRV_WriteReg32(NFI_COLADDR_REG32, col_addr);\ ++ DRV_WriteReg32(NFI_ROWADDR_REG32, row_addr);\ ++ DRV_WriteReg(NFI_ADDRNOB_REG16, col_num | (row_num<mm) { ++ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR current->mm is NULL! tgid=0x%x, name=%s \n", current->tgid, current->comm); ++ return 0; ++ } ++ ++ pgd = pgd_offset(current->mm, va); /* what is tsk->mm */ ++ if (pgd_none(*pgd) || pgd_bad(*pgd)) { ++ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR, va=0x%x, pgd invalid! \n", va); ++ return 0; ++ } ++ ++ pmd = pmd_offset((pud_t *)pgd, va); ++ if (pmd_none(*pmd) || pmd_bad(*pmd)) { ++ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR, va=0x%x, pmd invalid! \n", va); ++ return 0; ++ } ++ ++ pte = pte_offset_map(pmd, va); ++ if (pte_present(*pte)) { ++ pa = (pte_val(*pte) & (PAGE_MASK)) | pageOffset; ++ return pa; ++ } ++ ++ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR va=0x%x, pte invalid! \n", va); ++ return 0; ++} ++EXPORT_SYMBOL(nand_virt_to_phys_add); ++ ++bool ++get_device_info(u16 id, u32 ext_id, flashdev_info * pdevinfo) ++{ ++ u32 index; ++ for (index = 0; gen_FlashTable[index].id != 0; index++) { ++ if (id == gen_FlashTable[index].id && ext_id == gen_FlashTable[index].ext_id) { ++ pdevinfo->id = gen_FlashTable[index].id; ++ pdevinfo->ext_id = gen_FlashTable[index].ext_id; ++ pdevinfo->blocksize = gen_FlashTable[index].blocksize; ++ pdevinfo->addr_cycle = gen_FlashTable[index].addr_cycle; ++ pdevinfo->iowidth = gen_FlashTable[index].iowidth; ++ pdevinfo->timmingsetting = gen_FlashTable[index].timmingsetting; ++ pdevinfo->advancedmode = gen_FlashTable[index].advancedmode; ++ pdevinfo->pagesize = gen_FlashTable[index].pagesize; ++ pdevinfo->sparesize = gen_FlashTable[index].sparesize; ++ pdevinfo->totalsize = gen_FlashTable[index].totalsize; ++ memcpy(pdevinfo->devciename, gen_FlashTable[index].devciename, sizeof(pdevinfo->devciename)); ++ printk(KERN_INFO "Device found in MTK table, ID: %x, EXT_ID: %x\n", id, ext_id); ++ ++ goto find; ++ } ++ } ++ ++find: ++ if (0 == pdevinfo->id) { ++ printk(KERN_INFO "Device not found, ID: %x\n", id); ++ return false; ++ } else { ++ return true; ++ } ++} ++ ++static void ++ECC_Config(struct mtk_nand_host_hw *hw,u32 ecc_bit) ++{ ++ u32 u4ENCODESize; ++ u32 u4DECODESize; ++ u32 ecc_bit_cfg = ECC_CNFG_ECC4; ++ ++ switch(ecc_bit){ ++ case 4: ++ ecc_bit_cfg = ECC_CNFG_ECC4; ++ break; ++ case 8: ++ ecc_bit_cfg = ECC_CNFG_ECC8; ++ break; ++ case 10: ++ ecc_bit_cfg = ECC_CNFG_ECC10; ++ break; ++ case 12: ++ ecc_bit_cfg = ECC_CNFG_ECC12; ++ break; ++ default: ++ break; ++ } ++ DRV_WriteReg16(ECC_DECCON_REG16, DEC_DE); ++ do { ++ } while (!DRV_Reg16(ECC_DECIDLE_REG16)); ++ ++ DRV_WriteReg16(ECC_ENCCON_REG16, ENC_DE); ++ do { ++ } while (!DRV_Reg32(ECC_ENCIDLE_REG32)); ++ ++ /* setup FDM register base */ ++ DRV_WriteReg32(ECC_FDMADDR_REG32, NFI_FDM0L_REG32); ++ ++ /* Sector + FDM */ ++ u4ENCODESize = (hw->nand_sec_size + 8) << 3; ++ /* Sector + FDM + YAFFS2 meta data bits */ ++ u4DECODESize = ((hw->nand_sec_size + 8) << 3) + ecc_bit * 13; ++ ++ /* configure ECC decoder && encoder */ ++ DRV_WriteReg32(ECC_DECCNFG_REG32, ecc_bit_cfg | DEC_CNFG_NFI | DEC_CNFG_EMPTY_EN | (u4DECODESize << DEC_CNFG_CODE_SHIFT)); ++ ++ DRV_WriteReg32(ECC_ENCCNFG_REG32, ecc_bit_cfg | ENC_CNFG_NFI | (u4ENCODESize << ENC_CNFG_MSG_SHIFT)); ++ NFI_SET_REG32(ECC_DECCNFG_REG32, DEC_CNFG_EL); ++} ++ ++static void ++ECC_Decode_Start(void) ++{ ++ while (!(DRV_Reg16(ECC_DECIDLE_REG16) & DEC_IDLE)) ++ ; ++ DRV_WriteReg16(ECC_DECCON_REG16, DEC_EN); ++} ++ ++static void ++ECC_Decode_End(void) ++{ ++ while (!(DRV_Reg16(ECC_DECIDLE_REG16) & DEC_IDLE)) ++ ; ++ DRV_WriteReg16(ECC_DECCON_REG16, DEC_DE); ++} ++ ++static void ++ECC_Encode_Start(void) ++{ ++ while (!(DRV_Reg32(ECC_ENCIDLE_REG32) & ENC_IDLE)) ++ ; ++ mb(); ++ DRV_WriteReg16(ECC_ENCCON_REG16, ENC_EN); ++} ++ ++static void ++ECC_Encode_End(void) ++{ ++ /* wait for device returning idle */ ++ while (!(DRV_Reg32(ECC_ENCIDLE_REG32) & ENC_IDLE)) ; ++ mb(); ++ DRV_WriteReg16(ECC_ENCCON_REG16, ENC_DE); ++} ++ ++static bool ++mtk_nand_check_bch_error(struct mtd_info *mtd, u8 * pDataBuf, u32 u4SecIndex, u32 u4PageAddr) ++{ ++ bool bRet = true; ++ u16 u2SectorDoneMask = 1 << u4SecIndex; ++ u32 u4ErrorNumDebug, i, u4ErrNum; ++ u32 timeout = 0xFFFF; ++ // int el; ++ u32 au4ErrBitLoc[6]; ++ u32 u4ErrByteLoc, u4BitOffset; ++ u32 u4ErrBitLoc1th, u4ErrBitLoc2nd; ++ ++ //4 // Wait for Decode Done ++ while (0 == (u2SectorDoneMask & DRV_Reg16(ECC_DECDONE_REG16))) { ++ timeout--; ++ if (0 == timeout) ++ return false; ++ } ++ /* We will manually correct the error bits in the last sector, not all the sectors of the page! */ ++ memset(au4ErrBitLoc, 0x0, sizeof(au4ErrBitLoc)); ++ u4ErrorNumDebug = DRV_Reg32(ECC_DECENUM_REG32); ++ u4ErrNum = DRV_Reg32(ECC_DECENUM_REG32) >> (u4SecIndex << 2); ++ u4ErrNum &= 0xF; ++ ++ if (u4ErrNum) { ++ if (0xF == u4ErrNum) { ++ mtd->ecc_stats.failed++; ++ bRet = false; ++ printk(KERN_ERR"mtk_nand: UnCorrectable at PageAddr=%d\n", u4PageAddr); ++ } else { ++ for (i = 0; i < ((u4ErrNum + 1) >> 1); ++i) { ++ au4ErrBitLoc[i] = DRV_Reg32(ECC_DECEL0_REG32 + i); ++ u4ErrBitLoc1th = au4ErrBitLoc[i] & 0x1FFF; ++ if (u4ErrBitLoc1th < 0x1000) { ++ u4ErrByteLoc = u4ErrBitLoc1th / 8; ++ u4BitOffset = u4ErrBitLoc1th % 8; ++ pDataBuf[u4ErrByteLoc] = pDataBuf[u4ErrByteLoc] ^ (1 << u4BitOffset); ++ mtd->ecc_stats.corrected++; ++ } else { ++ mtd->ecc_stats.failed++; ++ } ++ u4ErrBitLoc2nd = (au4ErrBitLoc[i] >> 16) & 0x1FFF; ++ if (0 != u4ErrBitLoc2nd) { ++ if (u4ErrBitLoc2nd < 0x1000) { ++ u4ErrByteLoc = u4ErrBitLoc2nd / 8; ++ u4BitOffset = u4ErrBitLoc2nd % 8; ++ pDataBuf[u4ErrByteLoc] = pDataBuf[u4ErrByteLoc] ^ (1 << u4BitOffset); ++ mtd->ecc_stats.corrected++; ++ } else { ++ mtd->ecc_stats.failed++; ++ //printk(KERN_ERR"UnCorrectable High ErrLoc=%d\n", au4ErrBitLoc[i]); ++ } ++ } ++ } ++ } ++ if (0 == (DRV_Reg16(ECC_DECFER_REG16) & (1 << u4SecIndex))) ++ bRet = false; ++ } ++ return bRet; ++} ++ ++static bool ++mtk_nand_RFIFOValidSize(u16 u2Size) ++{ ++ u32 timeout = 0xFFFF; ++ while (FIFO_RD_REMAIN(DRV_Reg16(NFI_FIFOSTA_REG16)) < u2Size) { ++ timeout--; ++ if (0 == timeout) ++ return false; ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_WFIFOValidSize(u16 u2Size) ++{ ++ u32 timeout = 0xFFFF; ++ ++ while (FIFO_WR_REMAIN(DRV_Reg16(NFI_FIFOSTA_REG16)) > u2Size) { ++ timeout--; ++ if (0 == timeout) ++ return false; ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_status_ready(u32 u4Status) ++{ ++ u32 timeout = 0xFFFF; ++ ++ while ((DRV_Reg32(NFI_STA_REG32) & u4Status) != 0) { ++ timeout--; ++ if (0 == timeout) ++ return false; ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_reset(void) ++{ ++ int timeout = 0xFFFF; ++ if (DRV_Reg16(NFI_MASTERSTA_REG16)) { ++ mb(); ++ DRV_WriteReg16(NFI_CON_REG16, CON_FIFO_FLUSH | CON_NFI_RST); ++ while (DRV_Reg16(NFI_MASTERSTA_REG16)) { ++ timeout--; ++ if (!timeout) ++ MSG(INIT, "Wait for NFI_MASTERSTA timeout\n"); ++ } ++ } ++ /* issue reset operation */ ++ mb(); ++ DRV_WriteReg16(NFI_CON_REG16, CON_FIFO_FLUSH | CON_NFI_RST); ++ ++ return mtk_nand_status_ready(STA_NFI_FSM_MASK | STA_NAND_BUSY) && mtk_nand_RFIFOValidSize(0) && mtk_nand_WFIFOValidSize(0); ++} ++ ++static void ++mtk_nand_set_mode(u16 u2OpMode) ++{ ++ u16 u2Mode = DRV_Reg16(NFI_CNFG_REG16); ++ u2Mode &= ~CNFG_OP_MODE_MASK; ++ u2Mode |= u2OpMode; ++ DRV_WriteReg16(NFI_CNFG_REG16, u2Mode); ++} ++ ++static void ++mtk_nand_set_autoformat(bool bEnable) ++{ ++ if (bEnable) ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_AUTO_FMT_EN); ++ else ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AUTO_FMT_EN); ++} ++ ++static void ++mtk_nand_configure_fdm(u16 u2FDMSize) ++{ ++ NFI_CLN_REG16(NFI_PAGEFMT_REG16, PAGEFMT_FDM_MASK | PAGEFMT_FDM_ECC_MASK); ++ NFI_SET_REG16(NFI_PAGEFMT_REG16, u2FDMSize << PAGEFMT_FDM_SHIFT); ++ NFI_SET_REG16(NFI_PAGEFMT_REG16, u2FDMSize << PAGEFMT_FDM_ECC_SHIFT); ++} ++ ++static void ++mtk_nand_configure_lock(void) ++{ ++ u32 u4WriteColNOB = 2; ++ u32 u4WriteRowNOB = 3; ++ u32 u4EraseColNOB = 0; ++ u32 u4EraseRowNOB = 3; ++ DRV_WriteReg16(NFI_LOCKANOB_REG16, ++ (u4WriteColNOB << PROG_CADD_NOB_SHIFT) | (u4WriteRowNOB << PROG_RADD_NOB_SHIFT) | (u4EraseColNOB << ERASE_CADD_NOB_SHIFT) | (u4EraseRowNOB << ERASE_RADD_NOB_SHIFT)); ++ ++ if (CHIPVER_ECO_1 == g_u4ChipVer) { ++ int i; ++ for (i = 0; i < 16; ++i) { ++ DRV_WriteReg32(NFI_LOCK00ADD_REG32 + (i << 1), 0xFFFFFFFF); ++ DRV_WriteReg32(NFI_LOCK00FMT_REG32 + (i << 1), 0xFFFFFFFF); ++ } ++ //DRV_WriteReg16(NFI_LOCKANOB_REG16, 0x0); ++ DRV_WriteReg32(NFI_LOCKCON_REG32, 0xFFFFFFFF); ++ DRV_WriteReg16(NFI_LOCK_REG16, NFI_LOCK_ON); ++ } ++} ++ ++static bool ++mtk_nand_pio_ready(void) ++{ ++ int count = 0; ++ while (!(DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1)) { ++ count++; ++ if (count > 0xffff) { ++ printk("PIO_DIRDY timeout\n"); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++static bool ++mtk_nand_set_command(u16 command) ++{ ++ mb(); ++ DRV_WriteReg16(NFI_CMD_REG16, command); ++ return mtk_nand_status_ready(STA_CMD_STATE); ++} ++ ++static bool ++mtk_nand_set_address(u32 u4ColAddr, u32 u4RowAddr, u16 u2ColNOB, u16 u2RowNOB) ++{ ++ mb(); ++ DRV_WriteReg32(NFI_COLADDR_REG32, u4ColAddr); ++ DRV_WriteReg32(NFI_ROWADDR_REG32, u4RowAddr); ++ DRV_WriteReg16(NFI_ADDRNOB_REG16, u2ColNOB | (u2RowNOB << ADDR_ROW_NOB_SHIFT)); ++ return mtk_nand_status_ready(STA_ADDR_STATE); ++} ++ ++static void mtk_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) ++{ ++ if (ctrl & NAND_ALE) { ++ mtk_nand_set_address(dat, 0, 1, 0); ++ } else if (ctrl & NAND_CLE) { ++ mtk_nand_reset(); ++ mtk_nand_set_mode(0x6000); ++ mtk_nand_set_command(dat); ++ } ++} ++ ++static bool ++mtk_nand_check_RW_count(u16 u2WriteSize) ++{ ++ u32 timeout = 0xFFFF; ++ u16 u2SecNum = u2WriteSize >> 9; ++ ++ while (ADDRCNTR_CNTR(DRV_Reg16(NFI_ADDRCNTR_REG16)) < u2SecNum) { ++ timeout--; ++ if (0 == timeout) { ++ printk(KERN_INFO "[%s] timeout\n", __FUNCTION__); ++ return false; ++ } ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_ready_for_read(struct nand_chip *nand, u32 u4RowAddr, u32 u4ColAddr, bool full, u8 * buf) ++{ ++ /* Reset NFI HW internal state machine and flush NFI in/out FIFO */ ++ bool bRet = false; ++ u16 sec_num = 1 << (nand->page_shift - 9); ++ u32 col_addr = u4ColAddr; ++ u32 colnob = 2, rownob = devinfo.addr_cycle - 2; ++ if (nand->options & NAND_BUSWIDTH_16) ++ col_addr /= 2; ++ ++ if (!mtk_nand_reset()) ++ goto cleanup; ++ if (g_bHwEcc) { ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } else { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } ++ ++ mtk_nand_set_mode(CNFG_OP_READ); ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_READ_EN); ++ DRV_WriteReg16(NFI_CON_REG16, sec_num << CON_NFI_SEC_SHIFT); ++ ++ if (full) { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ ++ if (g_bHwEcc) ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ else ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } else { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ } ++ ++ mtk_nand_set_autoformat(full); ++ if (full) ++ if (g_bHwEcc) ++ ECC_Decode_Start(); ++ if (!mtk_nand_set_command(NAND_CMD_READ0)) ++ goto cleanup; ++ if (!mtk_nand_set_address(col_addr, u4RowAddr, colnob, rownob)) ++ goto cleanup; ++ if (!mtk_nand_set_command(NAND_CMD_READSTART)) ++ goto cleanup; ++ if (!mtk_nand_status_ready(STA_NAND_BUSY)) ++ goto cleanup; ++ ++ bRet = true; ++ ++cleanup: ++ return bRet; ++} ++ ++static bool ++mtk_nand_ready_for_write(struct nand_chip *nand, u32 u4RowAddr, u32 col_addr, bool full, u8 * buf) ++{ ++ bool bRet = false; ++ u32 sec_num = 1 << (nand->page_shift - 9); ++ u32 colnob = 2, rownob = devinfo.addr_cycle - 2; ++ if (nand->options & NAND_BUSWIDTH_16) ++ col_addr /= 2; ++ ++ /* Reset NFI HW internal state machine and flush NFI in/out FIFO */ ++ if (!mtk_nand_reset()) ++ return false; ++ ++ mtk_nand_set_mode(CNFG_OP_PRGM); ++ ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_READ_EN); ++ ++ DRV_WriteReg16(NFI_CON_REG16, sec_num << CON_NFI_SEC_SHIFT); ++ ++ if (full) { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ if (g_bHwEcc) ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ else ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } else { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ } ++ ++ mtk_nand_set_autoformat(full); ++ ++ if (full) ++ if (g_bHwEcc) ++ ECC_Encode_Start(); ++ ++ if (!mtk_nand_set_command(NAND_CMD_SEQIN)) ++ goto cleanup; ++ //1 FIXED ME: For Any Kind of AddrCycle ++ if (!mtk_nand_set_address(col_addr, u4RowAddr, colnob, rownob)) ++ goto cleanup; ++ ++ if (!mtk_nand_status_ready(STA_NAND_BUSY)) ++ goto cleanup; ++ ++ bRet = true; ++ ++cleanup: ++ return bRet; ++} ++ ++static bool ++mtk_nand_check_dececc_done(u32 u4SecNum) ++{ ++ u32 timeout, dec_mask; ++ ++ timeout = 0xffff; ++ dec_mask = (1 << u4SecNum) - 1; ++ while ((dec_mask != DRV_Reg(ECC_DECDONE_REG16)) && timeout > 0) ++ timeout--; ++ if (timeout == 0) { ++ MSG(VERIFY, "ECC_DECDONE: timeout\n"); ++ return false; ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_mcu_read_data(u8 * buf, u32 length) ++{ ++ int timeout = 0xffff; ++ u32 i; ++ u32 *buf32 = (u32 *) buf; ++ if ((u32) buf % 4 || length % 4) ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ else ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ ++ //DRV_WriteReg32(NFI_STRADDR_REG32, 0); ++ mb(); ++ NFI_SET_REG16(NFI_CON_REG16, CON_NFI_BRD); ++ ++ if ((u32) buf % 4 || length % 4) { ++ for (i = 0; (i < (length)) && (timeout > 0);) { ++ if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) { ++ *buf++ = (u8) DRV_Reg32(NFI_DATAR_REG32); ++ i++; ++ } else { ++ timeout--; ++ } ++ if (0 == timeout) { ++ printk(KERN_ERR "[%s] timeout\n", __FUNCTION__); ++ dump_nfi(); ++ return false; ++ } ++ } ++ } else { ++ for (i = 0; (i < (length >> 2)) && (timeout > 0);) { ++ if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) { ++ *buf32++ = DRV_Reg32(NFI_DATAR_REG32); ++ i++; ++ } else { ++ timeout--; ++ } ++ if (0 == timeout) { ++ printk(KERN_ERR "[%s] timeout\n", __FUNCTION__); ++ dump_nfi(); ++ return false; ++ } ++ } ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_read_page_data(struct mtd_info *mtd, u8 * pDataBuf, u32 u4Size) ++{ ++ return mtk_nand_mcu_read_data(pDataBuf, u4Size); ++} ++ ++static bool ++mtk_nand_mcu_write_data(struct mtd_info *mtd, const u8 * buf, u32 length) ++{ ++ u32 timeout = 0xFFFF; ++ u32 i; ++ u32 *pBuf32; ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ mb(); ++ NFI_SET_REG16(NFI_CON_REG16, CON_NFI_BWR); ++ pBuf32 = (u32 *) buf; ++ ++ if ((u32) buf % 4 || length % 4) ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ else ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ ++ if ((u32) buf % 4 || length % 4) { ++ for (i = 0; (i < (length)) && (timeout > 0);) { ++ if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) { ++ DRV_WriteReg32(NFI_DATAW_REG32, *buf++); ++ i++; ++ } else { ++ timeout--; ++ } ++ if (0 == timeout) { ++ printk(KERN_ERR "[%s] timeout\n", __FUNCTION__); ++ dump_nfi(); ++ return false; ++ } ++ } ++ } else { ++ for (i = 0; (i < (length >> 2)) && (timeout > 0);) { ++ if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) { ++ DRV_WriteReg32(NFI_DATAW_REG32, *pBuf32++); ++ i++; ++ } else { ++ timeout--; ++ } ++ if (0 == timeout) { ++ printk(KERN_ERR "[%s] timeout\n", __FUNCTION__); ++ dump_nfi(); ++ return false; ++ } ++ } ++ } ++ ++ return true; ++} ++ ++static bool ++mtk_nand_write_page_data(struct mtd_info *mtd, u8 * buf, u32 size) ++{ ++ return mtk_nand_mcu_write_data(mtd, buf, size); ++} ++ ++static void ++mtk_nand_read_fdm_data(u8 * pDataBuf, u32 u4SecNum) ++{ ++ u32 i; ++ u32 *pBuf32 = (u32 *) pDataBuf; ++ ++ if (pBuf32) { ++ for (i = 0; i < u4SecNum; ++i) { ++ *pBuf32++ = DRV_Reg32(NFI_FDM0L_REG32 + (i << 1)); ++ *pBuf32++ = DRV_Reg32(NFI_FDM0M_REG32 + (i << 1)); ++ } ++ } ++} ++ ++static u8 fdm_buf[64]; ++static void ++mtk_nand_write_fdm_data(struct nand_chip *chip, u8 * pDataBuf, u32 u4SecNum) ++{ ++ u32 i, j; ++ u8 checksum = 0; ++ bool empty = true; ++ struct nand_oobfree *free_entry; ++ u32 *pBuf32; ++ ++ memcpy(fdm_buf, pDataBuf, u4SecNum * 8); ++ ++ free_entry = layout->oobfree; ++ for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free_entry[i].length; i++) { ++ for (j = 0; j < free_entry[i].length; j++) { ++ if (pDataBuf[free_entry[i].offset + j] != 0xFF) ++ empty = false; ++ checksum ^= pDataBuf[free_entry[i].offset + j]; ++ } ++ } ++ ++ if (!empty) { ++ fdm_buf[free_entry[i - 1].offset + free_entry[i - 1].length] = checksum; ++ } ++ ++ pBuf32 = (u32 *) fdm_buf; ++ for (i = 0; i < u4SecNum; ++i) { ++ DRV_WriteReg32(NFI_FDM0L_REG32 + (i << 1), *pBuf32++); ++ DRV_WriteReg32(NFI_FDM0M_REG32 + (i << 1), *pBuf32++); ++ } ++} ++ ++static void ++mtk_nand_stop_read(void) ++{ ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BRD); ++ mtk_nand_reset(); ++ if (g_bHwEcc) ++ ECC_Decode_End(); ++ DRV_WriteReg16(NFI_INTR_EN_REG16, 0); ++} ++ ++static void ++mtk_nand_stop_write(void) ++{ ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BWR); ++ if (g_bHwEcc) ++ ECC_Encode_End(); ++ DRV_WriteReg16(NFI_INTR_EN_REG16, 0); ++} ++ ++bool ++mtk_nand_exec_read_page(struct mtd_info *mtd, u32 u4RowAddr, u32 u4PageSize, u8 * pPageBuf, u8 * pFDMBuf) ++{ ++ u8 *buf; ++ bool bRet = true; ++ struct nand_chip *nand = mtd->priv; ++ u32 u4SecNum = u4PageSize >> 9; ++ ++ if (((u32) pPageBuf % 16) && local_buffer_16_align) ++ buf = local_buffer_16_align; ++ else ++ buf = pPageBuf; ++ if (mtk_nand_ready_for_read(nand, u4RowAddr, 0, true, buf)) { ++ int j; ++ for (j = 0 ; j < u4SecNum; j++) { ++ if (!mtk_nand_read_page_data(mtd, buf+j*512, 512)) ++ bRet = false; ++ if(g_bHwEcc && !mtk_nand_check_dececc_done(j+1)) ++ bRet = false; ++ if(g_bHwEcc && !mtk_nand_check_bch_error(mtd, buf+j*512, j, u4RowAddr)) ++ bRet = false; ++ } ++ if (!mtk_nand_status_ready(STA_NAND_BUSY)) ++ bRet = false; ++ ++ mtk_nand_read_fdm_data(pFDMBuf, u4SecNum); ++ mtk_nand_stop_read(); ++ } ++ ++ if (buf == local_buffer_16_align) ++ memcpy(pPageBuf, buf, u4PageSize); ++ ++ return bRet; ++} ++ ++int ++mtk_nand_exec_write_page(struct mtd_info *mtd, u32 u4RowAddr, u32 u4PageSize, u8 * pPageBuf, u8 * pFDMBuf) ++{ ++ struct nand_chip *chip = mtd->priv; ++ u32 u4SecNum = u4PageSize >> 9; ++ u8 *buf; ++ u8 status; ++ ++ MSG(WRITE, "mtk_nand_exec_write_page, page: 0x%x\n", u4RowAddr); ++ ++ if (((u32) pPageBuf % 16) && local_buffer_16_align) { ++ printk(KERN_INFO "Data buffer not 16 bytes aligned: %p\n", pPageBuf); ++ memcpy(local_buffer_16_align, pPageBuf, mtd->writesize); ++ buf = local_buffer_16_align; ++ } else ++ buf = pPageBuf; ++ ++ if (mtk_nand_ready_for_write(chip, u4RowAddr, 0, true, buf)) { ++ mtk_nand_write_fdm_data(chip, pFDMBuf, u4SecNum); ++ (void)mtk_nand_write_page_data(mtd, buf, u4PageSize); ++ (void)mtk_nand_check_RW_count(u4PageSize); ++ mtk_nand_stop_write(); ++ (void)mtk_nand_set_command(NAND_CMD_PAGEPROG); ++ while (DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY) ; ++ } ++ ++ status = chip->waitfunc(mtd, chip); ++ if (status & NAND_STATUS_FAIL) ++ return -EIO; ++ return 0; ++} ++ ++static int ++get_start_end_block(struct mtd_info *mtd, int block, int *start_blk, int *end_blk) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int i; ++ ++ *start_blk = 0; ++ for (i = 0; i <= part_num; i++) ++ { ++ if (i == part_num) ++ { ++ // try the last reset partition ++ *end_blk = (chip->chipsize >> chip->phys_erase_shift) - 1; ++ if (*start_blk <= *end_blk) ++ { ++ if ((block >= *start_blk) && (block <= *end_blk)) ++ break; ++ } ++ } ++ // skip All partition entry ++ else if (g_pasStatic_Partition[i].size == MTDPART_SIZ_FULL) ++ { ++ continue; ++ } ++ *end_blk = *start_blk + (g_pasStatic_Partition[i].size >> chip->phys_erase_shift) - 1; ++ if ((block >= *start_blk) && (block <= *end_blk)) ++ break; ++ *start_blk = *end_blk + 1; ++ } ++ if (*start_blk > *end_blk) ++ { ++ return -1; ++ } ++ return 0; ++} ++ ++static int ++block_remap(struct mtd_info *mtd, int block) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int start_blk, end_blk; ++ int j, block_offset; ++ int bad_block = 0; ++ ++ if (chip->bbt == NULL) { ++ printk("ERROR!! no bbt table for block_remap\n"); ++ return -1; ++ } ++ ++ if (get_start_end_block(mtd, block, &start_blk, &end_blk) < 0) { ++ printk("ERROR!! can not find start_blk and end_blk\n"); ++ return -1; ++ } ++ ++ block_offset = block - start_blk; ++ for (j = start_blk; j <= end_blk;j++) { ++ if (((chip->bbt[j >> 2] >> ((j<<1) & 0x6)) & 0x3) == 0x0) { ++ if (!block_offset) ++ break; ++ block_offset--; ++ } else { ++ bad_block++; ++ } ++ } ++ if (j <= end_blk) { ++ return j; ++ } else { ++ // remap to the bad block ++ for (j = end_blk; bad_block > 0; j--) ++ { ++ if (((chip->bbt[j >> 2] >> ((j<<1) & 0x6)) & 0x3) != 0x0) ++ { ++ bad_block--; ++ if (bad_block <= block_offset) ++ return j; ++ } ++ } ++ } ++ ++ printk("Error!! block_remap error\n"); ++ return -1; ++} ++ ++int ++check_block_remap(struct mtd_info *mtd, int block) ++{ ++ if (shift_on_bbt) ++ return block_remap(mtd, block); ++ else ++ return block; ++} ++EXPORT_SYMBOL(check_block_remap); ++ ++ ++static int ++write_next_on_fail(struct mtd_info *mtd, char *write_buf, int page, int * to_blk) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int i, j, to_page = 0, first_page; ++ char *buf, *oob; ++ int start_blk = 0, end_blk; ++ int mapped_block; ++ int page_per_block_bit = chip->phys_erase_shift - chip->page_shift; ++ int block = page >> page_per_block_bit; ++ ++ // find next available block in the same MTD partition ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ ++ get_start_end_block(mtd, block, &start_blk, &end_blk); ++ ++ buf = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL | GFP_DMA); ++ if (buf == NULL) ++ return -1; ++ ++ oob = buf + mtd->writesize; ++ for ((*to_blk) = block + 1; (*to_blk) <= end_blk ; (*to_blk)++) { ++ if (nand_bbt_get(mtd, (*to_blk) << page_per_block_bit) == 0) { ++ int status; ++ status = mtk_nand_erase_hw(mtd, (*to_blk) << page_per_block_bit); ++ if (status & NAND_STATUS_FAIL) { ++ mtk_nand_block_markbad_hw(mtd, (*to_blk) << chip->phys_erase_shift); ++ nand_bbt_set(mtd, (*to_blk) << page_per_block_bit, 0x3); ++ } else { ++ /* good block */ ++ to_page = (*to_blk) << page_per_block_bit; ++ break; ++ } ++ } ++ } ++ ++ if (!to_page) { ++ kfree(buf); ++ return -1; ++ } ++ ++ first_page = (page >> page_per_block_bit) << page_per_block_bit; ++ for (i = 0; i < (1 << page_per_block_bit); i++) { ++ if ((first_page + i) != page) { ++ mtk_nand_read_oob_hw(mtd, chip, (first_page+i)); ++ for (j = 0; j < mtd->oobsize; j++) ++ if (chip->oob_poi[j] != (unsigned char)0xff) ++ break; ++ if (j < mtd->oobsize) { ++ mtk_nand_exec_read_page(mtd, (first_page+i), mtd->writesize, buf, oob); ++ memset(oob, 0xff, mtd->oobsize); ++ if (mtk_nand_exec_write_page(mtd, to_page + i, mtd->writesize, (u8 *)buf, oob) != 0) { ++ int ret, new_blk = 0; ++ nand_bbt_set(mtd, to_page, 0x3); ++ ret = write_next_on_fail(mtd, buf, to_page + i, &new_blk); ++ if (ret) { ++ kfree(buf); ++ mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift); ++ return ret; ++ } ++ mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift); ++ *to_blk = new_blk; ++ to_page = ((*to_blk) << page_per_block_bit); ++ } ++ } ++ } else { ++ memset(chip->oob_poi, 0xff, mtd->oobsize); ++ if (mtk_nand_exec_write_page(mtd, to_page + i, mtd->writesize, (u8 *)write_buf, chip->oob_poi) != 0) { ++ int ret, new_blk = 0; ++ nand_bbt_set(mtd, to_page, 0x3); ++ ret = write_next_on_fail(mtd, write_buf, to_page + i, &new_blk); ++ if (ret) { ++ kfree(buf); ++ mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift); ++ return ret; ++ } ++ mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift); ++ *to_blk = new_blk; ++ to_page = ((*to_blk) << page_per_block_bit); ++ } ++ } ++ } ++ ++ kfree(buf); ++ ++ return 0; ++} ++ ++static int ++mtk_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, uint32_t offset, ++ int data_len, const u8 * buf, int oob_required, int page, int raw) ++{ ++ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ int block = page / page_per_block; ++ u16 page_in_block = page % page_per_block; ++ int mapped_block = block; ++ ++#if defined(MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++ // write bad index into oob ++ if (mapped_block != block) ++ set_bad_index_to_oob(chip->oob_poi, block); ++ else ++ set_bad_index_to_oob(chip->oob_poi, FAKE_INDEX); ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } ++#endif ++ do { ++ if (mtk_nand_exec_write_page(mtd, page_in_block + mapped_block * page_per_block, mtd->writesize, (u8 *)buf, chip->oob_poi)) { ++ MSG(INIT, "write fail at block: 0x%x, page: 0x%x\n", mapped_block, page_in_block); ++#if defined(MTK_NAND_BMT) ++ if (update_bmt((page_in_block + mapped_block * page_per_block) << chip->page_shift, UPDATE_WRITE_FAIL, (u8 *) buf, chip->oob_poi)) { ++ MSG(INIT, "Update BMT success\n"); ++ return 0; ++ } else { ++ MSG(INIT, "Update BMT fail\n"); ++ return -EIO; ++ } ++#else ++ { ++ int new_blk; ++ nand_bbt_set(mtd, page_in_block + mapped_block * page_per_block, 0x3); ++ if (write_next_on_fail(mtd, (char *)buf, page_in_block + mapped_block * page_per_block, &new_blk) != 0) ++ { ++ mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift); ++ return NAND_STATUS_FAIL; ++ } ++ mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift); ++ break; ++ } ++#endif ++ } else ++ break; ++ } while(1); ++ ++ return 0; ++} ++ ++static void ++mtk_nand_command_bp(struct mtd_info *mtd, unsigned int command, int column, int page_addr) ++{ ++ struct nand_chip *nand = mtd->priv; ++ ++ switch (command) { ++ case NAND_CMD_SEQIN: ++ memset(g_kCMD.au1OOB, 0xFF, sizeof(g_kCMD.au1OOB)); ++ g_kCMD.pDataBuf = NULL; ++ g_kCMD.u4RowAddr = page_addr; ++ g_kCMD.u4ColAddr = column; ++ break; ++ ++ case NAND_CMD_PAGEPROG: ++ if (g_kCMD.pDataBuf || (0xFF != g_kCMD.au1OOB[nand_badblock_offset])) { ++ u8 *pDataBuf = g_kCMD.pDataBuf ? g_kCMD.pDataBuf : nand->buffers->databuf; ++ mtk_nand_exec_write_page(mtd, g_kCMD.u4RowAddr, mtd->writesize, pDataBuf, g_kCMD.au1OOB); ++ g_kCMD.u4RowAddr = (u32) - 1; ++ g_kCMD.u4OOBRowAddr = (u32) - 1; ++ } ++ break; ++ ++ case NAND_CMD_READOOB: ++ g_kCMD.u4RowAddr = page_addr; ++ g_kCMD.u4ColAddr = column + mtd->writesize; ++ break; ++ ++ case NAND_CMD_READ0: ++ g_kCMD.u4RowAddr = page_addr; ++ g_kCMD.u4ColAddr = column; ++ break; ++ ++ case NAND_CMD_ERASE1: ++ nand->state=FL_ERASING; ++ (void)mtk_nand_reset(); ++ mtk_nand_set_mode(CNFG_OP_ERASE); ++ (void)mtk_nand_set_command(NAND_CMD_ERASE1); ++ (void)mtk_nand_set_address(0, page_addr, 0, devinfo.addr_cycle - 2); ++ break; ++ ++ case NAND_CMD_ERASE2: ++ (void)mtk_nand_set_command(NAND_CMD_ERASE2); ++ while (DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY) ++ ; ++ break; ++ ++ case NAND_CMD_STATUS: ++ (void)mtk_nand_reset(); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ mtk_nand_set_mode(CNFG_OP_SRD); ++ mtk_nand_set_mode(CNFG_READ_EN); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ (void)mtk_nand_set_command(NAND_CMD_STATUS); ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_NOB_MASK); ++ mb(); ++ DRV_WriteReg16(NFI_CON_REG16, CON_NFI_SRD | (1 << CON_NFI_NOB_SHIFT)); ++ g_bcmdstatus = true; ++ break; ++ ++ case NAND_CMD_RESET: ++ (void)mtk_nand_reset(); ++ DRV_WriteReg16(NFI_INTR_EN_REG16, INTR_RST_DONE_EN); ++ (void)mtk_nand_set_command(NAND_CMD_RESET); ++ DRV_WriteReg16(NFI_BASE+0x44, 0xF1); ++ while(!(DRV_Reg16(NFI_INTR_REG16)&INTR_RST_DONE_EN)) ++ ; ++ break; ++ ++ case NAND_CMD_READID: ++ mtk_nand_reset(); ++ /* Disable HW ECC */ ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_READ_EN | CNFG_BYTE_RW); ++ (void)mtk_nand_reset(); ++ mb(); ++ mtk_nand_set_mode(CNFG_OP_SRD); ++ (void)mtk_nand_set_command(NAND_CMD_READID); ++ (void)mtk_nand_set_address(0, 0, 1, 0); ++ DRV_WriteReg16(NFI_CON_REG16, CON_NFI_SRD); ++ while (DRV_Reg32(NFI_STA_REG32) & STA_DATAR_STATE) ++ ; ++ break; ++ ++ default: ++ BUG(); ++ break; ++ } ++} ++ ++static void ++mtk_nand_select_chip(struct mtd_info *mtd, int chip) ++{ ++ if ((chip == -1) && (false == g_bInitDone)) { ++ struct nand_chip *nand = mtd->priv; ++ struct mtk_nand_host *host = nand->priv; ++ struct mtk_nand_host_hw *hw = host->hw; ++ u32 spare_per_sector = mtd->oobsize / (mtd->writesize / 512); ++ u32 ecc_bit = 4; ++ u32 spare_bit = PAGEFMT_SPARE_16; ++ ++ if (spare_per_sector >= 28) { ++ spare_bit = PAGEFMT_SPARE_28; ++ ecc_bit = 12; ++ spare_per_sector = 28; ++ } else if (spare_per_sector >= 27) { ++ spare_bit = PAGEFMT_SPARE_27; ++ ecc_bit = 8; ++ spare_per_sector = 27; ++ } else if (spare_per_sector >= 26) { ++ spare_bit = PAGEFMT_SPARE_26; ++ ecc_bit = 8; ++ spare_per_sector = 26; ++ } else if (spare_per_sector >= 16) { ++ spare_bit = PAGEFMT_SPARE_16; ++ ecc_bit = 4; ++ spare_per_sector = 16; ++ } else { ++ MSG(INIT, "[NAND]: NFI not support oobsize: %x\n", spare_per_sector); ++ ASSERT(0); ++ } ++ mtd->oobsize = spare_per_sector*(mtd->writesize/512); ++ MSG(INIT, "[NAND]select ecc bit:%d, sparesize :%d spare_per_sector=%d\n",ecc_bit,mtd->oobsize,spare_per_sector); ++ /* Setup PageFormat */ ++ if (4096 == mtd->writesize) { ++ NFI_SET_REG16(NFI_PAGEFMT_REG16, (spare_bit << PAGEFMT_SPARE_SHIFT) | PAGEFMT_4K); ++ nand->cmdfunc = mtk_nand_command_bp; ++ } else if (2048 == mtd->writesize) { ++ NFI_SET_REG16(NFI_PAGEFMT_REG16, (spare_bit << PAGEFMT_SPARE_SHIFT) | PAGEFMT_2K); ++ nand->cmdfunc = mtk_nand_command_bp; ++ } ++ ECC_Config(hw,ecc_bit); ++ g_bInitDone = true; ++ } ++ switch (chip) { ++ case -1: ++ break; ++ case 0: ++ case 1: ++ /* Jun Shen, 2011.04.13 */ ++ /* Note: MT6577 EVB NAND is mounted on CS0, but FPGA is CS1 */ ++ DRV_WriteReg16(NFI_CSEL_REG16, chip); ++ /* Jun Shen, 2011.04.13 */ ++ break; ++ } ++} ++ ++static uint8_t ++mtk_nand_read_byte(struct mtd_info *mtd) ++{ ++ uint8_t retval = 0; ++ ++ if (!mtk_nand_pio_ready()) { ++ printk("pio ready timeout\n"); ++ retval = false; ++ } ++ ++ if (g_bcmdstatus) { ++ retval = DRV_Reg8(NFI_DATAR_REG32); ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_NOB_MASK); ++ mtk_nand_reset(); ++ if (g_bHwEcc) { ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } else { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } ++ g_bcmdstatus = false; ++ } else ++ retval = DRV_Reg8(NFI_DATAR_REG32); ++ ++ return retval; ++} ++ ++static void ++mtk_nand_read_buf(struct mtd_info *mtd, uint8_t * buf, int len) ++{ ++ struct nand_chip *nand = (struct nand_chip *)mtd->priv; ++ struct NAND_CMD *pkCMD = &g_kCMD; ++ u32 u4ColAddr = pkCMD->u4ColAddr; ++ u32 u4PageSize = mtd->writesize; ++ ++ if (u4ColAddr < u4PageSize) { ++ if ((u4ColAddr == 0) && (len >= u4PageSize)) { ++ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, buf, pkCMD->au1OOB); ++ if (len > u4PageSize) { ++ u32 u4Size = min(len - u4PageSize, sizeof(pkCMD->au1OOB)); ++ memcpy(buf + u4PageSize, pkCMD->au1OOB, u4Size); ++ } ++ } else { ++ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, nand->buffers->databuf, pkCMD->au1OOB); ++ memcpy(buf, nand->buffers->databuf + u4ColAddr, len); ++ } ++ pkCMD->u4OOBRowAddr = pkCMD->u4RowAddr; ++ } else { ++ u32 u4Offset = u4ColAddr - u4PageSize; ++ u32 u4Size = min(len - u4Offset, sizeof(pkCMD->au1OOB)); ++ if (pkCMD->u4OOBRowAddr != pkCMD->u4RowAddr) { ++ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, nand->buffers->databuf, pkCMD->au1OOB); ++ pkCMD->u4OOBRowAddr = pkCMD->u4RowAddr; ++ } ++ memcpy(buf, pkCMD->au1OOB + u4Offset, u4Size); ++ } ++ pkCMD->u4ColAddr += len; ++} ++ ++static void ++mtk_nand_write_buf(struct mtd_info *mtd, const uint8_t * buf, int len) ++{ ++ struct NAND_CMD *pkCMD = &g_kCMD; ++ u32 u4ColAddr = pkCMD->u4ColAddr; ++ u32 u4PageSize = mtd->writesize; ++ int i4Size, i; ++ ++ if (u4ColAddr >= u4PageSize) { ++ u32 u4Offset = u4ColAddr - u4PageSize; ++ u8 *pOOB = pkCMD->au1OOB + u4Offset; ++ i4Size = min(len, (int)(sizeof(pkCMD->au1OOB) - u4Offset)); ++ for (i = 0; i < i4Size; i++) { ++ pOOB[i] &= buf[i]; ++ } ++ } else { ++ pkCMD->pDataBuf = (u8 *) buf; ++ } ++ ++ pkCMD->u4ColAddr += len; ++} ++ ++static int ++mtk_nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t * buf, int oob_required, int page) ++{ ++ mtk_nand_write_buf(mtd, buf, mtd->writesize); ++ mtk_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize); ++ return 0; ++} ++ ++static int ++mtk_nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf, int oob_required, int page) ++{ ++ struct NAND_CMD *pkCMD = &g_kCMD; ++ u32 u4ColAddr = pkCMD->u4ColAddr; ++ u32 u4PageSize = mtd->writesize; ++ ++ if (u4ColAddr == 0) { ++ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, buf, chip->oob_poi); ++ pkCMD->u4ColAddr += u4PageSize + mtd->oobsize; ++ } ++ ++ return 0; ++} ++ ++static int ++mtk_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, u8 * buf, int page) ++{ ++ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ int block = page / page_per_block; ++ u16 page_in_block = page % page_per_block; ++ int mapped_block = block; ++ ++#if defined (MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++ if (mtk_nand_exec_read_page(mtd, page_in_block + mapped_block * page_per_block, ++ mtd->writesize, buf, chip->oob_poi)) ++ return 0; ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } ++ ++ if (mtk_nand_exec_read_page(mtd, page_in_block + mapped_block * page_per_block, mtd->writesize, buf, chip->oob_poi)) ++ return 0; ++ else ++ return -EIO; ++#endif ++} ++ ++int ++mtk_nand_erase_hw(struct mtd_info *mtd, int page) ++{ ++ struct nand_chip *chip = (struct nand_chip *)mtd->priv; ++ ++ chip->erase(mtd, page); ++ ++ return chip->waitfunc(mtd, chip); ++} ++ ++static int ++mtk_nand_erase(struct mtd_info *mtd, int page) ++{ ++ // get mapping ++ struct nand_chip *chip = mtd->priv; ++ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ int page_in_block = page % page_per_block; ++ int block = page / page_per_block; ++ int mapped_block = block; ++ ++#if defined(MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } ++#endif ++ ++ do { ++ int status = mtk_nand_erase_hw(mtd, page_in_block + page_per_block * mapped_block); ++ ++ if (status & NAND_STATUS_FAIL) { ++#if defined (MTK_NAND_BMT) ++ if (update_bmt( (page_in_block + mapped_block * page_per_block) << chip->page_shift, ++ UPDATE_ERASE_FAIL, NULL, NULL)) ++ { ++ MSG(INIT, "Erase fail at block: 0x%x, update BMT success\n", mapped_block); ++ return 0; ++ } else { ++ MSG(INIT, "Erase fail at block: 0x%x, update BMT fail\n", mapped_block); ++ return NAND_STATUS_FAIL; ++ } ++#else ++ mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift); ++ nand_bbt_set(mtd, page_in_block + mapped_block * page_per_block, 0x3); ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } else ++ return NAND_STATUS_FAIL; ++#endif ++ } else ++ break; ++ } while(1); ++ ++ return 0; ++} ++ ++static int ++mtk_nand_read_oob_raw(struct mtd_info *mtd, uint8_t * buf, int page_addr, int len) ++{ ++ struct nand_chip *chip = (struct nand_chip *)mtd->priv; ++ u32 col_addr = 0; ++ u32 sector = 0; ++ int res = 0; ++ u32 colnob = 2, rawnob = devinfo.addr_cycle - 2; ++ int randomread = 0; ++ int read_len = 0; ++ int sec_num = 1<<(chip->page_shift-9); ++ int spare_per_sector = mtd->oobsize/sec_num; ++ ++ if (len > NAND_MAX_OOBSIZE || len % OOB_AVAI_PER_SECTOR || !buf) { ++ printk(KERN_WARNING "[%s] invalid parameter, len: %d, buf: %p\n", __FUNCTION__, len, buf); ++ return -EINVAL; ++ } ++ if (len > spare_per_sector) ++ randomread = 1; ++ if (!randomread || !(devinfo.advancedmode & RAMDOM_READ)) { ++ while (len > 0) { ++ read_len = min(len, spare_per_sector); ++ col_addr = NAND_SECTOR_SIZE + sector * (NAND_SECTOR_SIZE + spare_per_sector); // TODO: Fix this hard-code 16 ++ if (!mtk_nand_ready_for_read(chip, page_addr, col_addr, false, NULL)) { ++ printk(KERN_WARNING "mtk_nand_ready_for_read return failed\n"); ++ res = -EIO; ++ goto error; ++ } ++ if (!mtk_nand_mcu_read_data(buf + spare_per_sector * sector, read_len)) { ++ printk(KERN_WARNING "mtk_nand_mcu_read_data return failed\n"); ++ res = -EIO; ++ goto error; ++ } ++ mtk_nand_check_RW_count(read_len); ++ mtk_nand_stop_read(); ++ sector++; ++ len -= read_len; ++ } ++ } else { ++ col_addr = NAND_SECTOR_SIZE; ++ if (chip->options & NAND_BUSWIDTH_16) ++ col_addr /= 2; ++ if (!mtk_nand_reset()) ++ goto error; ++ mtk_nand_set_mode(0x6000); ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_READ_EN); ++ DRV_WriteReg16(NFI_CON_REG16, 4 << CON_NFI_SEC_SHIFT); ++ ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ ++ mtk_nand_set_autoformat(false); ++ ++ if (!mtk_nand_set_command(NAND_CMD_READ0)) ++ goto error; ++ //1 FIXED ME: For Any Kind of AddrCycle ++ if (!mtk_nand_set_address(col_addr, page_addr, colnob, rawnob)) ++ goto error; ++ if (!mtk_nand_set_command(NAND_CMD_READSTART)) ++ goto error; ++ if (!mtk_nand_status_ready(STA_NAND_BUSY)) ++ goto error; ++ read_len = min(len, spare_per_sector); ++ if (!mtk_nand_mcu_read_data(buf + spare_per_sector * sector, read_len)) { ++ printk(KERN_WARNING "mtk_nand_mcu_read_data return failed first 16\n"); ++ res = -EIO; ++ goto error; ++ } ++ sector++; ++ len -= read_len; ++ mtk_nand_stop_read(); ++ while (len > 0) { ++ read_len = min(len, spare_per_sector); ++ if (!mtk_nand_set_command(0x05)) ++ goto error; ++ col_addr = NAND_SECTOR_SIZE + sector * (NAND_SECTOR_SIZE + spare_per_sector); ++ if (chip->options & NAND_BUSWIDTH_16) ++ col_addr /= 2; ++ DRV_WriteReg32(NFI_COLADDR_REG32, col_addr); ++ DRV_WriteReg16(NFI_ADDRNOB_REG16, 2); ++ DRV_WriteReg16(NFI_CON_REG16, 4 << CON_NFI_SEC_SHIFT); ++ if (!mtk_nand_status_ready(STA_ADDR_STATE)) ++ goto error; ++ if (!mtk_nand_set_command(0xE0)) ++ goto error; ++ if (!mtk_nand_status_ready(STA_NAND_BUSY)) ++ goto error; ++ if (!mtk_nand_mcu_read_data(buf + spare_per_sector * sector, read_len)) { ++ printk(KERN_WARNING "mtk_nand_mcu_read_data return failed first 16\n"); ++ res = -EIO; ++ goto error; ++ } ++ mtk_nand_stop_read(); ++ sector++; ++ len -= read_len; ++ } ++ } ++error: ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BRD); ++ return res; ++} ++ ++static int ++mtk_nand_write_oob_raw(struct mtd_info *mtd, const uint8_t * buf, int page_addr, int len) ++{ ++ struct nand_chip *chip = mtd->priv; ++ u32 col_addr = 0; ++ u32 sector = 0; ++ int write_len = 0; ++ int status; ++ int sec_num = 1<<(chip->page_shift-9); ++ int spare_per_sector = mtd->oobsize/sec_num; ++ ++ if (len > NAND_MAX_OOBSIZE || len % OOB_AVAI_PER_SECTOR || !buf) { ++ printk(KERN_WARNING "[%s] invalid parameter, len: %d, buf: %p\n", __FUNCTION__, len, buf); ++ return -EINVAL; ++ } ++ ++ while (len > 0) { ++ write_len = min(len, spare_per_sector); ++ col_addr = sector * (NAND_SECTOR_SIZE + spare_per_sector) + NAND_SECTOR_SIZE; ++ if (!mtk_nand_ready_for_write(chip, page_addr, col_addr, false, NULL)) ++ return -EIO; ++ if (!mtk_nand_mcu_write_data(mtd, buf + sector * spare_per_sector, write_len)) ++ return -EIO; ++ (void)mtk_nand_check_RW_count(write_len); ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BWR); ++ (void)mtk_nand_set_command(NAND_CMD_PAGEPROG); ++ while (DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY) ++ ; ++ status = chip->waitfunc(mtd, chip); ++ if (status & NAND_STATUS_FAIL) { ++ printk(KERN_INFO "status: %d\n", status); ++ return -EIO; ++ } ++ len -= write_len; ++ sector++; ++ } ++ ++ return 0; ++} ++ ++static int ++mtk_nand_write_oob_hw(struct mtd_info *mtd, struct nand_chip *chip, int page) ++{ ++ int i, iter; ++ int sec_num = 1<<(chip->page_shift-9); ++ int spare_per_sector = mtd->oobsize/sec_num; ++ ++ memcpy(local_oob_buf, chip->oob_poi, mtd->oobsize); ++ ++ // copy ecc data ++ for (i = 0; i < layout->eccbytes; i++) { ++ iter = (i / (spare_per_sector-OOB_AVAI_PER_SECTOR)) * spare_per_sector + OOB_AVAI_PER_SECTOR + i % (spare_per_sector-OOB_AVAI_PER_SECTOR); ++ local_oob_buf[iter] = chip->oob_poi[layout->eccpos[i]]; ++ } ++ ++ // copy FDM data ++ for (i = 0; i < sec_num; i++) ++ memcpy(&local_oob_buf[i * spare_per_sector], &chip->oob_poi[i * OOB_AVAI_PER_SECTOR], OOB_AVAI_PER_SECTOR); ++ ++ return mtk_nand_write_oob_raw(mtd, local_oob_buf, page, mtd->oobsize); ++} ++ ++static int mtk_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) ++{ ++ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ int block = page / page_per_block; ++ u16 page_in_block = page % page_per_block; ++ int mapped_block = block; ++ ++#if defined(MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++ // write bad index into oob ++ if (mapped_block != block) ++ set_bad_index_to_oob(chip->oob_poi, block); ++ else ++ set_bad_index_to_oob(chip->oob_poi, FAKE_INDEX); ++#else ++ if (shift_on_bbt) ++ { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } ++#endif ++ do { ++ if (mtk_nand_write_oob_hw(mtd, chip, page_in_block + mapped_block * page_per_block /* page */)) { ++ MSG(INIT, "write oob fail at block: 0x%x, page: 0x%x\n", mapped_block, page_in_block); ++#if defined(MTK_NAND_BMT) ++ if (update_bmt((page_in_block + mapped_block * page_per_block) << chip->page_shift, ++ UPDATE_WRITE_FAIL, NULL, chip->oob_poi)) ++ { ++ MSG(INIT, "Update BMT success\n"); ++ return 0; ++ } else { ++ MSG(INIT, "Update BMT fail\n"); ++ return -EIO; ++ } ++#else ++ mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift); ++ nand_bbt_set(mtd, page_in_block + mapped_block * page_per_block, 0x3); ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, mapped_block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } else { ++ return NAND_STATUS_FAIL; ++ } ++#endif ++ } else ++ break; ++ } while (1); ++ ++ return 0; ++} ++ ++int ++mtk_nand_block_markbad_hw(struct mtd_info *mtd, loff_t offset) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int block = (int)offset >> chip->phys_erase_shift; ++ int page = block * (1 << (chip->phys_erase_shift - chip->page_shift)); ++ u8 buf[8]; ++ ++ memset(buf, 0xFF, 8); ++ buf[0] = 0; ++ return mtk_nand_write_oob_raw(mtd, buf, page, 8); ++} ++ ++static int ++mtk_nand_block_markbad(struct mtd_info *mtd, loff_t offset) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int block = (int)offset >> chip->phys_erase_shift; ++ int ret; ++ int mapped_block = block; ++ ++ nand_get_device(chip, mtd, FL_WRITING); ++ ++#if defined(MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++ ret = mtk_nand_block_markbad_hw(mtd, mapped_block << chip->phys_erase_shift); ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) { ++ printk("NAND mark bad failed\n"); ++ nand_release_device(mtd); ++ return NAND_STATUS_FAIL; ++ } ++ } ++ ret = mtk_nand_block_markbad_hw(mtd, mapped_block << chip->phys_erase_shift); ++#endif ++ nand_release_device(mtd); ++ ++ return ret; ++} ++ ++int ++mtk_nand_read_oob_hw(struct mtd_info *mtd, struct nand_chip *chip, int page) ++{ ++ int i; ++ u8 iter = 0; ++ ++ int sec_num = 1<<(chip->page_shift-9); ++ int spare_per_sector = mtd->oobsize/sec_num; ++ ++ if (mtk_nand_read_oob_raw(mtd, chip->oob_poi, page, mtd->oobsize)) { ++ printk(KERN_ERR "[%s]mtk_nand_read_oob_raw return failed\n", __FUNCTION__); ++ return -EIO; ++ } ++ ++ // adjust to ecc physical layout to memory layout ++ /*********************************************************/ ++ /* FDM0 | ECC0 | FDM1 | ECC1 | FDM2 | ECC2 | FDM3 | ECC3 */ ++ /* 8B | 8B | 8B | 8B | 8B | 8B | 8B | 8B */ ++ /*********************************************************/ ++ ++ memcpy(local_oob_buf, chip->oob_poi, mtd->oobsize); ++ // copy ecc data ++ for (i = 0; i < layout->eccbytes; i++) { ++ iter = (i / (spare_per_sector-OOB_AVAI_PER_SECTOR)) * spare_per_sector + OOB_AVAI_PER_SECTOR + i % (spare_per_sector-OOB_AVAI_PER_SECTOR); ++ chip->oob_poi[layout->eccpos[i]] = local_oob_buf[iter]; ++ } ++ ++ // copy FDM data ++ for (i = 0; i < sec_num; i++) { ++ memcpy(&chip->oob_poi[i * OOB_AVAI_PER_SECTOR], &local_oob_buf[i * spare_per_sector], OOB_AVAI_PER_SECTOR); ++ } ++ ++ return 0; ++} ++ ++static int ++mtk_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) ++{ ++ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ int block = page / page_per_block; ++ u16 page_in_block = page % page_per_block; ++ int mapped_block = block; ++ ++#if defined (MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++ mtk_nand_read_oob_hw(mtd, chip, page_in_block + mapped_block * page_per_block); ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ // allow to read oob even if the block is bad ++ } ++ if (mtk_nand_read_oob_hw(mtd, chip, page_in_block + mapped_block * page_per_block)!=0) ++ return -1; ++#endif ++ return 0; ++} ++ ++int ++mtk_nand_block_bad_hw(struct mtd_info *mtd, loff_t ofs) ++{ ++ struct nand_chip *chip = (struct nand_chip *)mtd->priv; ++ int page_addr = (int)(ofs >> chip->page_shift); ++ unsigned int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ unsigned char oob_buf[8]; ++ ++ page_addr &= ~(page_per_block - 1); ++ if (mtk_nand_read_oob_raw(mtd, oob_buf, page_addr, sizeof(oob_buf))) { ++ printk(KERN_WARNING "mtk_nand_read_oob_raw return error\n"); ++ return 1; ++ } ++ ++ if (oob_buf[0] != 0xff) { ++ printk(KERN_WARNING "Bad block detected at 0x%x, oob_buf[0] is 0x%x\n", page_addr, oob_buf[0]); ++ // dump_nfi(); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int ++mtk_nand_block_bad(struct mtd_info *mtd, loff_t ofs) ++{ ++ struct nand_chip *chip = (struct nand_chip *)mtd->priv; ++ int block = (int)ofs >> chip->phys_erase_shift; ++ int mapped_block = block; ++ int ret; ++ ++#if defined(MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ } ++#endif ++ ++ ret = mtk_nand_block_bad_hw(mtd, mapped_block << chip->phys_erase_shift); ++#if defined (MTK_NAND_BMT) ++ if (ret) { ++ MSG(INIT, "Unmapped bad block: 0x%x\n", mapped_block); ++ if (update_bmt(mapped_block << chip->phys_erase_shift, UPDATE_UNMAPPED_BLOCK, NULL, NULL)) { ++ MSG(INIT, "Update BMT success\n"); ++ ret = 0; ++ } else { ++ MSG(INIT, "Update BMT fail\n"); ++ ret = 1; ++ } ++ } ++#endif ++ ++ return ret; ++} ++ ++#ifdef CONFIG_MTD_NAND_VERIFY_WRITE ++char gacBuf[4096 + 288]; ++ ++static int ++mtk_nand_verify_buf(struct mtd_info *mtd, const uint8_t * buf, int len) ++{ ++ struct nand_chip *chip = (struct nand_chip *)mtd->priv; ++ struct NAND_CMD *pkCMD = &g_kCMD; ++ u32 u4PageSize = mtd->writesize; ++ u32 *pSrc, *pDst; ++ int i; ++ ++ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, gacBuf, gacBuf + u4PageSize); ++ ++ pSrc = (u32 *) buf; ++ pDst = (u32 *) gacBuf; ++ len = len / sizeof(u32); ++ for (i = 0; i < len; ++i) { ++ if (*pSrc != *pDst) { ++ MSG(VERIFY, "mtk_nand_verify_buf page fail at page %d\n", pkCMD->u4RowAddr); ++ return -1; ++ } ++ pSrc++; ++ pDst++; ++ } ++ ++ pSrc = (u32 *) chip->oob_poi; ++ pDst = (u32 *) (gacBuf + u4PageSize); ++ ++ if ((pSrc[0] != pDst[0]) || (pSrc[1] != pDst[1]) || (pSrc[2] != pDst[2]) || (pSrc[3] != pDst[3]) || (pSrc[4] != pDst[4]) || (pSrc[5] != pDst[5])) { ++ // TODO: Ask Designer Why? ++ //(pSrc[6] != pDst[6]) || (pSrc[7] != pDst[7])) ++ MSG(VERIFY, "mtk_nand_verify_buf oob fail at page %d\n", pkCMD->u4RowAddr); ++ MSG(VERIFY, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", pSrc[0], pSrc[1], pSrc[2], pSrc[3], pSrc[4], pSrc[5], pSrc[6], pSrc[7]); ++ MSG(VERIFY, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", pDst[0], pDst[1], pDst[2], pDst[3], pDst[4], pDst[5], pDst[6], pDst[7]); ++ return -1; ++ } ++ return 0; ++} ++#endif ++ ++static void ++mtk_nand_init_hw(struct mtk_nand_host *host) { ++ struct mtk_nand_host_hw *hw = host->hw; ++ u32 data; ++ ++ data = DRV_Reg32(RALINK_SYSCTL_BASE+0x60); ++ data &= ~((0x3<<18)|(0x3<<16)); ++ data |= ((0x2<<18) |(0x2<<16)); ++ DRV_WriteReg32(RALINK_SYSCTL_BASE+0x60, data); ++ ++ MSG(INIT, "Enable NFI Clock\n"); ++ nand_enable_clock(); ++ ++ g_bInitDone = false; ++ g_kCMD.u4OOBRowAddr = (u32) - 1; ++ ++ /* Set default NFI access timing control */ ++ DRV_WriteReg32(NFI_ACCCON_REG32, hw->nfi_access_timing); ++ DRV_WriteReg16(NFI_CNFG_REG16, 0); ++ DRV_WriteReg16(NFI_PAGEFMT_REG16, 0); ++ ++ /* Reset the state machine and data FIFO, because flushing FIFO */ ++ (void)mtk_nand_reset(); ++ ++ /* Set the ECC engine */ ++ if (hw->nand_ecc_mode == NAND_ECC_HW) { ++ MSG(INIT, "%s : Use HW ECC\n", MODULE_NAME); ++ if (g_bHwEcc) ++ NFI_SET_REG32(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ ECC_Config(host->hw,4); ++ mtk_nand_configure_fdm(8); ++ mtk_nand_configure_lock(); ++ } ++ ++ NFI_SET_REG16(NFI_IOCON_REG16, 0x47); ++} ++ ++static int mtk_nand_dev_ready(struct mtd_info *mtd) ++{ ++ return !(DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY); ++} ++ ++#define FACT_BBT_BLOCK_NUM 32 // use the latest 32 BLOCK for factory bbt table ++#define FACT_BBT_OOB_SIGNATURE 1 ++#define FACT_BBT_SIGNATURE_LEN 7 ++const u8 oob_signature[] = "mtknand"; ++static u8 *fact_bbt = 0; ++static u32 bbt_size = 0; ++ ++static int ++read_fact_bbt(struct mtd_info *mtd, unsigned int page) ++{ ++ struct nand_chip *chip = mtd->priv; ++ ++ // read oob ++ if (mtk_nand_read_oob_hw(mtd, chip, page)==0) ++ { ++ if (chip->oob_poi[nand_badblock_offset] != 0xFF) ++ { ++ printk("Bad Block on Page %x\n", page); ++ return -1; ++ } ++ if (memcmp(&chip->oob_poi[FACT_BBT_OOB_SIGNATURE], oob_signature, FACT_BBT_SIGNATURE_LEN) != 0) ++ { ++ printk("compare signature failed %x\n", page); ++ return -1; ++ } ++ if (mtk_nand_exec_read_page(mtd, page, mtd->writesize, chip->buffers->databuf, chip->oob_poi)) ++ { ++ printk("Signature matched and data read!\n"); ++ memcpy(fact_bbt, chip->buffers->databuf, (bbt_size <= mtd->writesize)? bbt_size:mtd->writesize); ++ return 0; ++ } ++ ++ } ++ printk("failed at page %x\n", page); ++ return -1; ++} ++ ++static int ++load_fact_bbt(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int i; ++ u32 total_block; ++ ++ total_block = 1 << (chip->chip_shift - chip->phys_erase_shift); ++ bbt_size = total_block >> 2; ++ ++ if ((!fact_bbt) && (bbt_size)) ++ fact_bbt = (u8 *)kmalloc(bbt_size, GFP_KERNEL); ++ if (!fact_bbt) ++ return -1; ++ ++ for (i = total_block - 1; i >= (total_block - FACT_BBT_BLOCK_NUM); i--) ++ { ++ if (read_fact_bbt(mtd, i << (chip->phys_erase_shift - chip->page_shift)) == 0) ++ { ++ printk("load_fact_bbt success %d\n", i); ++ return 0; ++ } ++ ++ } ++ printk("load_fact_bbt failed\n"); ++ return -1; ++} ++ ++static int oob_mtk_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ oobregion->length = 8; ++ oobregion->offset = layout->eccpos[section * 8]; ++ ++ return 0; ++} ++ ++static int oob_mtk_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section >= (layout->eccbytes / 8)) { ++ return -ERANGE; ++ } ++ oobregion->offset = layout->oobfree[section].offset; ++ oobregion->length = layout->oobfree[section].length; ++ ++ return 0; ++} ++ ++ ++static const struct mtd_ooblayout_ops oob_mtk_ops = { ++ .ecc = oob_mtk_ooblayout_ecc, ++ .free = oob_mtk_ooblayout_free, ++}; ++ ++static int ++mtk_nand_probe(struct platform_device *pdev) ++{ ++ struct mtd_part_parser_data ppdata; ++ struct mtk_nand_host_hw *hw; ++ struct nand_chip *nand_chip; ++ struct mtd_info *mtd; ++ u8 ext_id1, ext_id2, ext_id3; ++ int err = 0; ++ int id; ++ u32 ext_id; ++ int i; ++ u32 data; ++ ++ data = DRV_Reg32(RALINK_SYSCTL_BASE+0x60); ++ data &= ~((0x3<<18)|(0x3<<16)); ++ data |= ((0x2<<18) |(0x2<<16)); ++ DRV_WriteReg32(RALINK_SYSCTL_BASE+0x60, data); ++ ++ hw = &mt7621_nand_hw; ++ BUG_ON(!hw); ++ /* Allocate memory for the device structure (and zero it) */ ++ host = kzalloc(sizeof(struct mtk_nand_host), GFP_KERNEL); ++ if (!host) { ++ MSG(INIT, "mtk_nand: failed to allocate device structure.\n"); ++ return -ENOMEM; ++ } ++ ++ /* Allocate memory for 16 byte aligned buffer */ ++ local_buffer_16_align = local_buffer + 16 - ((u32) local_buffer % 16); ++ printk(KERN_INFO "Allocate 16 byte aligned buffer: %p\n", local_buffer_16_align); ++ host->hw = hw; ++ ++ /* init mtd data structure */ ++ nand_chip = &host->nand_chip; ++ nand_chip->priv = host; /* link the private data structures */ ++ ++ mtd = host->mtd = &nand_chip->mtd; ++ mtd->priv = nand_chip; ++ mtd->owner = THIS_MODULE; ++ mtd->name = "MT7621-NAND"; ++ ++ hw->nand_ecc_mode = NAND_ECC_HW; ++ ++ /* Set address of NAND IO lines */ ++ nand_chip->IO_ADDR_R = (void __iomem *)NFI_DATAR_REG32; ++ nand_chip->IO_ADDR_W = (void __iomem *)NFI_DATAW_REG32; ++ nand_chip->chip_delay = 20; /* 20us command delay time */ ++ nand_chip->ecc.mode = hw->nand_ecc_mode; /* enable ECC */ ++ nand_chip->ecc.strength = 1; ++ nand_chip->read_byte = mtk_nand_read_byte; ++ nand_chip->read_buf = mtk_nand_read_buf; ++ nand_chip->write_buf = mtk_nand_write_buf; ++#ifdef CONFIG_MTD_NAND_VERIFY_WRITE ++ nand_chip->verify_buf = mtk_nand_verify_buf; ++#endif ++ nand_chip->select_chip = mtk_nand_select_chip; ++ nand_chip->dev_ready = mtk_nand_dev_ready; ++ nand_chip->cmdfunc = mtk_nand_command_bp; ++ nand_chip->ecc.read_page = mtk_nand_read_page_hwecc; ++ nand_chip->ecc.write_page = mtk_nand_write_page_hwecc; ++ ++ mtd_set_ooblayout(mtd, &oob_mtk_ops); ++ nand_chip->ecc.size = hw->nand_ecc_size; //2048 ++ nand_chip->ecc.bytes = hw->nand_ecc_bytes; //32 ++ ++ // For BMT, we need to revise driver architecture ++ nand_chip->write_page = mtk_nand_write_page; ++ nand_chip->ecc.write_oob = mtk_nand_write_oob; ++ nand_chip->block_markbad = mtk_nand_block_markbad; // need to add nand_get_device()/nand_release_device(). ++ nand_chip->erase_mtk = mtk_nand_erase; ++ nand_chip->read_page = mtk_nand_read_page; ++ nand_chip->ecc.read_oob = mtk_nand_read_oob; ++ nand_chip->block_bad = mtk_nand_block_bad; ++ nand_chip->cmd_ctrl = mtk_nfc_cmd_ctrl; ++ ++ //Qwert:Add for Uboot ++ mtk_nand_init_hw(host); ++ /* Select the device */ ++ nand_chip->select_chip(mtd, NFI_DEFAULT_CS); ++ ++ /* ++ * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx) ++ * after power-up ++ */ ++ nand_chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); ++ ++ memset(&devinfo, 0 , sizeof(flashdev_info)); ++ ++ /* Send the command for reading device ID */ ++ ++ nand_chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); ++ ++ /* Read manufacturer and device IDs */ ++ manu_id = nand_chip->read_byte(mtd); ++ dev_id = nand_chip->read_byte(mtd); ++ id = dev_id | (manu_id << 8); ++ ext_id1 = nand_chip->read_byte(mtd); ++ ext_id2 = nand_chip->read_byte(mtd); ++ ext_id3 = nand_chip->read_byte(mtd); ++ ext_id = ext_id1 << 16 | ext_id2 << 8 | ext_id3; ++ if (!get_device_info(id, ext_id, &devinfo)) { ++ u32 chip_mode = RALINK_REG(RALINK_SYSCTL_BASE+0x010)&0x0F; ++ MSG(INIT, "Not Support this Device! \r\n"); ++ memset(&devinfo, 0 , sizeof(flashdev_info)); ++ MSG(INIT, "chip_mode=%08X\n",chip_mode); ++ ++ /* apply bootstrap first */ ++ devinfo.addr_cycle = 5; ++ devinfo.iowidth = 8; ++ ++ switch (chip_mode) { ++ case 10: ++ devinfo.pagesize = 2048; ++ devinfo.sparesize = 128; ++ devinfo.totalsize = 128; ++ devinfo.blocksize = 128; ++ break; ++ case 11: ++ devinfo.pagesize = 4096; ++ devinfo.sparesize = 128; ++ devinfo.totalsize = 1024; ++ devinfo.blocksize = 256; ++ break; ++ case 12: ++ devinfo.pagesize = 4096; ++ devinfo.sparesize = 224; ++ devinfo.totalsize = 2048; ++ devinfo.blocksize = 512; ++ break; ++ default: ++ case 1: ++ devinfo.pagesize = 2048; ++ devinfo.sparesize = 64; ++ devinfo.totalsize = 128; ++ devinfo.blocksize = 128; ++ break; ++ } ++ ++ devinfo.timmingsetting = NFI_DEFAULT_ACCESS_TIMING; ++ devinfo.devciename[0] = 'U'; ++ devinfo.advancedmode = 0; ++ } ++ mtd->writesize = devinfo.pagesize; ++ mtd->erasesize = (devinfo.blocksize<<10); ++ mtd->oobsize = devinfo.sparesize; ++ ++ nand_chip->chipsize = (devinfo.totalsize<<20); ++ nand_chip->page_shift = ffs(mtd->writesize) - 1; ++ nand_chip->pagemask = (nand_chip->chipsize >> nand_chip->page_shift) - 1; ++ nand_chip->phys_erase_shift = ffs(mtd->erasesize) - 1; ++ nand_chip->chip_shift = ffs(nand_chip->chipsize) - 1;//0x1C;//ffs(nand_chip->chipsize) - 1; ++ nand_chip->cmd_ctrl = mtk_nfc_cmd_ctrl; ++ ++ /* allocate buffers or call select_chip here or a bit earlier*/ ++ { ++ struct nand_buffers *nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize + mtd->oobsize * 3, GFP_KERNEL); ++ if (!nbuf) { ++ return -ENOMEM; ++ } ++ nbuf->ecccalc = (uint8_t *)(nbuf + 1); ++ nbuf->ecccode = nbuf->ecccalc + mtd->oobsize; ++ nbuf->databuf = nbuf->ecccode + mtd->oobsize; ++ ++ nand_chip->buffers = nbuf; ++ nand_chip->options |= NAND_OWN_BUFFERS; ++ } ++ ++ nand_chip->oob_poi = nand_chip->buffers->databuf + mtd->writesize; ++ nand_chip->badblockpos = 0; ++ ++ if (devinfo.pagesize == 4096) ++ layout = &nand_oob_128; ++ else if (devinfo.pagesize == 2048) ++ layout = &nand_oob_64; ++ else if (devinfo.pagesize == 512) ++ layout = &nand_oob_16; ++ ++ layout->eccbytes = devinfo.sparesize-OOB_AVAI_PER_SECTOR*(devinfo.pagesize/NAND_SECTOR_SIZE); ++ for (i = 0; i < layout->eccbytes; i++) ++ layout->eccpos[i]=OOB_AVAI_PER_SECTOR*(devinfo.pagesize/NAND_SECTOR_SIZE)+i; ++ ++ MSG(INIT, "Support this Device in MTK table! %x \r\n", id); ++ hw->nfi_bus_width = devinfo.iowidth; ++ DRV_WriteReg32(NFI_ACCCON_REG32, devinfo.timmingsetting); ++ ++ /* 16-bit bus width */ ++ if (hw->nfi_bus_width == 16) { ++ MSG(INIT, "%s : Set the 16-bit I/O settings!\n", MODULE_NAME); ++ nand_chip->options |= NAND_BUSWIDTH_16; ++ } ++ mtd->oobsize = devinfo.sparesize; ++ hw->nfi_cs_num = 1; ++ ++ /* Scan to find existance of the device */ ++ if (nand_scan(mtd, hw->nfi_cs_num)) { ++ MSG(INIT, "%s : nand_scan fail.\n", MODULE_NAME); ++ err = -ENXIO; ++ goto out; ++ } ++ ++ g_page_size = mtd->writesize; ++ platform_set_drvdata(pdev, host); ++ if (hw->nfi_bus_width == 16) { ++ NFI_SET_REG16(NFI_PAGEFMT_REG16, PAGEFMT_DBYTE_EN); ++ } ++ ++ nand_chip->select_chip(mtd, 0); ++#if defined(MTK_NAND_BMT) ++ nand_chip->chipsize -= (BMT_POOL_SIZE) << nand_chip->phys_erase_shift; ++#endif ++ mtd->size = nand_chip->chipsize; ++ ++ CFG_BLOCKSIZE = mtd->erasesize; ++ ++#if defined(MTK_NAND_BMT) ++ if (!g_bmt) { ++ if (!(g_bmt = init_bmt(nand_chip, BMT_POOL_SIZE))) { ++ MSG(INIT, "Error: init bmt failed\n"); ++ return 0; ++ } ++ } ++#endif ++ ++ nand_set_flash_node(nand_chip, pdev->dev.of_node); ++ err = mtd_device_parse_register(mtd, probe_types, &ppdata, ++ NULL, 0); ++ if (!err) { ++ MSG(INIT, "[mtk_nand] probe successfully!\n"); ++ nand_disable_clock(); ++ shift_on_bbt = 1; ++ if (load_fact_bbt(mtd) == 0) { ++ int i; ++ for (i = 0; i < 0x100; i++) ++ nand_chip->bbt[i] |= fact_bbt[i]; ++ } ++ ++ return err; ++ } ++ ++out: ++ MSG(INIT, "[NFI] mtk_nand_probe fail, err = %d!\n", err); ++ nand_release(mtd); ++ platform_set_drvdata(pdev, NULL); ++ if ( NULL != nand_chip->buffers) { ++ kfree(nand_chip->buffers); ++ } ++ kfree(host); ++ nand_disable_clock(); ++ return err; ++} ++ ++static int ++mtk_nand_remove(struct platform_device *pdev) ++{ ++ struct mtk_nand_host *host = platform_get_drvdata(pdev); ++ struct mtd_info *mtd = host->mtd; ++ struct nand_chip *nand_chip = &host->nand_chip; ++ ++ nand_release(mtd); ++ if ( NULL != nand_chip->buffers) { ++ kfree(nand_chip->buffers); ++ } ++ kfree(host); ++ nand_disable_clock(); ++ ++ return 0; ++} ++ ++static const struct of_device_id mt7621_nand_match[] = { ++ { .compatible = "mtk,mt7621-nand" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mt7621_nand_match); ++ ++static struct platform_driver mtk_nand_driver = { ++ .probe = mtk_nand_probe, ++ .remove = mtk_nand_remove, ++ .driver = { ++ .name = "MT7621-NAND", ++ .owner = THIS_MODULE, ++ .of_match_table = mt7621_nand_match, ++ }, ++}; ++ ++static int __init ++mtk_nand_init(void) ++{ ++ printk("MediaTek Nand driver init, version %s\n", VERSION); ++ ++ return platform_driver_register(&mtk_nand_driver); ++} ++ ++static void __exit ++mtk_nand_exit(void) ++{ ++ platform_driver_unregister(&mtk_nand_driver); ++} ++ ++module_init(mtk_nand_init); ++module_exit(mtk_nand_exit); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/mtd/nand/mtk_nand2.h +@@ -0,0 +1,452 @@ ++#ifndef __MTK_NAND_H ++#define __MTK_NAND_H ++ ++#define RALINK_NAND_CTRL_BASE 0xBE003000 ++#define RALINK_SYSCTL_BASE 0xBE000000 ++#define RALINK_NANDECC_CTRL_BASE 0xBE003800 ++/******************************************************************************* ++ * NFI Register Definition ++ *******************************************************************************/ ++ ++#define NFI_CNFG_REG16 ((volatile P_U16)(NFI_BASE+0x0000)) ++#define NFI_PAGEFMT_REG16 ((volatile P_U16)(NFI_BASE+0x0004)) ++#define NFI_CON_REG16 ((volatile P_U16)(NFI_BASE+0x0008)) ++#define NFI_ACCCON_REG32 ((volatile P_U32)(NFI_BASE+0x000C)) ++#define NFI_INTR_EN_REG16 ((volatile P_U16)(NFI_BASE+0x0010)) ++#define NFI_INTR_REG16 ((volatile P_U16)(NFI_BASE+0x0014)) ++ ++#define NFI_CMD_REG16 ((volatile P_U16)(NFI_BASE+0x0020)) ++ ++#define NFI_ADDRNOB_REG16 ((volatile P_U16)(NFI_BASE+0x0030)) ++#define NFI_COLADDR_REG32 ((volatile P_U32)(NFI_BASE+0x0034)) ++#define NFI_ROWADDR_REG32 ((volatile P_U32)(NFI_BASE+0x0038)) ++ ++#define NFI_STRDATA_REG16 ((volatile P_U16)(NFI_BASE+0x0040)) ++ ++#define NFI_DATAW_REG32 ((volatile P_U32)(NFI_BASE+0x0050)) ++#define NFI_DATAR_REG32 ((volatile P_U32)(NFI_BASE+0x0054)) ++#define NFI_PIO_DIRDY_REG16 ((volatile P_U16)(NFI_BASE+0x0058)) ++ ++#define NFI_STA_REG32 ((volatile P_U32)(NFI_BASE+0x0060)) ++#define NFI_FIFOSTA_REG16 ((volatile P_U16)(NFI_BASE+0x0064)) ++#define NFI_LOCKSTA_REG16 ((volatile P_U16)(NFI_BASE+0x0068)) ++ ++#define NFI_ADDRCNTR_REG16 ((volatile P_U16)(NFI_BASE+0x0070)) ++ ++#define NFI_STRADDR_REG32 ((volatile P_U32)(NFI_BASE+0x0080)) ++#define NFI_BYTELEN_REG16 ((volatile P_U16)(NFI_BASE+0x0084)) ++ ++#define NFI_CSEL_REG16 ((volatile P_U16)(NFI_BASE+0x0090)) ++#define NFI_IOCON_REG16 ((volatile P_U16)(NFI_BASE+0x0094)) ++ ++#define NFI_FDM0L_REG32 ((volatile P_U32)(NFI_BASE+0x00A0)) ++#define NFI_FDM0M_REG32 ((volatile P_U32)(NFI_BASE+0x00A4)) ++ ++#define NFI_LOCK_REG16 ((volatile P_U16)(NFI_BASE+0x0100)) ++#define NFI_LOCKCON_REG32 ((volatile P_U32)(NFI_BASE+0x0104)) ++#define NFI_LOCKANOB_REG16 ((volatile P_U16)(NFI_BASE+0x0108)) ++#define NFI_LOCK00ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0110)) ++#define NFI_LOCK00FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0114)) ++#define NFI_LOCK01ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0118)) ++#define NFI_LOCK01FMT_REG32 ((volatile P_U32)(NFI_BASE+0x011C)) ++#define NFI_LOCK02ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0120)) ++#define NFI_LOCK02FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0124)) ++#define NFI_LOCK03ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0128)) ++#define NFI_LOCK03FMT_REG32 ((volatile P_U32)(NFI_BASE+0x012C)) ++#define NFI_LOCK04ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0130)) ++#define NFI_LOCK04FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0134)) ++#define NFI_LOCK05ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0138)) ++#define NFI_LOCK05FMT_REG32 ((volatile P_U32)(NFI_BASE+0x013C)) ++#define NFI_LOCK06ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0140)) ++#define NFI_LOCK06FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0144)) ++#define NFI_LOCK07ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0148)) ++#define NFI_LOCK07FMT_REG32 ((volatile P_U32)(NFI_BASE+0x014C)) ++#define NFI_LOCK08ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0150)) ++#define NFI_LOCK08FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0154)) ++#define NFI_LOCK09ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0158)) ++#define NFI_LOCK09FMT_REG32 ((volatile P_U32)(NFI_BASE+0x015C)) ++#define NFI_LOCK10ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0160)) ++#define NFI_LOCK10FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0164)) ++#define NFI_LOCK11ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0168)) ++#define NFI_LOCK11FMT_REG32 ((volatile P_U32)(NFI_BASE+0x016C)) ++#define NFI_LOCK12ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0170)) ++#define NFI_LOCK12FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0174)) ++#define NFI_LOCK13ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0178)) ++#define NFI_LOCK13FMT_REG32 ((volatile P_U32)(NFI_BASE+0x017C)) ++#define NFI_LOCK14ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0180)) ++#define NFI_LOCK14FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0184)) ++#define NFI_LOCK15ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0188)) ++#define NFI_LOCK15FMT_REG32 ((volatile P_U32)(NFI_BASE+0x018C)) ++ ++#define NFI_FIFODATA0_REG32 ((volatile P_U32)(NFI_BASE+0x0190)) ++#define NFI_FIFODATA1_REG32 ((volatile P_U32)(NFI_BASE+0x0194)) ++#define NFI_FIFODATA2_REG32 ((volatile P_U32)(NFI_BASE+0x0198)) ++#define NFI_FIFODATA3_REG32 ((volatile P_U32)(NFI_BASE+0x019C)) ++#define NFI_MASTERSTA_REG16 ((volatile P_U16)(NFI_BASE+0x0210)) ++ ++ ++/******************************************************************************* ++ * NFI Register Field Definition ++ *******************************************************************************/ ++ ++/* NFI_CNFG */ ++#define CNFG_AHB (0x0001) ++#define CNFG_READ_EN (0x0002) ++#define CNFG_DMA_BURST_EN (0x0004) ++#define CNFG_BYTE_RW (0x0040) ++#define CNFG_HW_ECC_EN (0x0100) ++#define CNFG_AUTO_FMT_EN (0x0200) ++#define CNFG_OP_IDLE (0x0000) ++#define CNFG_OP_READ (0x1000) ++#define CNFG_OP_SRD (0x2000) ++#define CNFG_OP_PRGM (0x3000) ++#define CNFG_OP_ERASE (0x4000) ++#define CNFG_OP_RESET (0x5000) ++#define CNFG_OP_CUST (0x6000) ++#define CNFG_OP_MODE_MASK (0x7000) ++#define CNFG_OP_MODE_SHIFT (12) ++ ++/* NFI_PAGEFMT */ ++#define PAGEFMT_512 (0x0000) ++#define PAGEFMT_2K (0x0001) ++#define PAGEFMT_4K (0x0002) ++ ++#define PAGEFMT_PAGE_MASK (0x0003) ++ ++#define PAGEFMT_DBYTE_EN (0x0008) ++ ++#define PAGEFMT_SPARE_16 (0x0000) ++#define PAGEFMT_SPARE_26 (0x0001) ++#define PAGEFMT_SPARE_27 (0x0002) ++#define PAGEFMT_SPARE_28 (0x0003) ++#define PAGEFMT_SPARE_MASK (0x0030) ++#define PAGEFMT_SPARE_SHIFT (4) ++ ++#define PAGEFMT_FDM_MASK (0x0F00) ++#define PAGEFMT_FDM_SHIFT (8) ++ ++#define PAGEFMT_FDM_ECC_MASK (0xF000) ++#define PAGEFMT_FDM_ECC_SHIFT (12) ++ ++/* NFI_CON */ ++#define CON_FIFO_FLUSH (0x0001) ++#define CON_NFI_RST (0x0002) ++#define CON_NFI_SRD (0x0010) ++ ++#define CON_NFI_NOB_MASK (0x0060) ++#define CON_NFI_NOB_SHIFT (5) ++ ++#define CON_NFI_BRD (0x0100) ++#define CON_NFI_BWR (0x0200) ++ ++#define CON_NFI_SEC_MASK (0xF000) ++#define CON_NFI_SEC_SHIFT (12) ++ ++/* NFI_ACCCON */ ++#define ACCCON_SETTING () ++ ++/* NFI_INTR_EN */ ++#define INTR_RD_DONE_EN (0x0001) ++#define INTR_WR_DONE_EN (0x0002) ++#define INTR_RST_DONE_EN (0x0004) ++#define INTR_ERASE_DONE_EN (0x0008) ++#define INTR_BSY_RTN_EN (0x0010) ++#define INTR_ACC_LOCK_EN (0x0020) ++#define INTR_AHB_DONE_EN (0x0040) ++#define INTR_ALL_INTR_DE (0x0000) ++#define INTR_ALL_INTR_EN (0x007F) ++ ++/* NFI_INTR */ ++#define INTR_RD_DONE (0x0001) ++#define INTR_WR_DONE (0x0002) ++#define INTR_RST_DONE (0x0004) ++#define INTR_ERASE_DONE (0x0008) ++#define INTR_BSY_RTN (0x0010) ++#define INTR_ACC_LOCK (0x0020) ++#define INTR_AHB_DONE (0x0040) ++ ++/* NFI_ADDRNOB */ ++#define ADDR_COL_NOB_MASK (0x0003) ++#define ADDR_COL_NOB_SHIFT (0) ++#define ADDR_ROW_NOB_MASK (0x0030) ++#define ADDR_ROW_NOB_SHIFT (4) ++ ++/* NFI_STA */ ++#define STA_READ_EMPTY (0x00001000) ++#define STA_ACC_LOCK (0x00000010) ++#define STA_CMD_STATE (0x00000001) ++#define STA_ADDR_STATE (0x00000002) ++#define STA_DATAR_STATE (0x00000004) ++#define STA_DATAW_STATE (0x00000008) ++ ++#define STA_NAND_FSM_MASK (0x1F000000) ++#define STA_NAND_BUSY (0x00000100) ++#define STA_NAND_BUSY_RETURN (0x00000200) ++#define STA_NFI_FSM_MASK (0x000F0000) ++#define STA_NFI_OP_MASK (0x0000000F) ++ ++/* NFI_FIFOSTA */ ++#define FIFO_RD_EMPTY (0x0040) ++#define FIFO_RD_FULL (0x0080) ++#define FIFO_WR_FULL (0x8000) ++#define FIFO_WR_EMPTY (0x4000) ++#define FIFO_RD_REMAIN(x) (0x1F&(x)) ++#define FIFO_WR_REMAIN(x) ((0x1F00&(x))>>8) ++ ++/* NFI_ADDRCNTR */ ++#define ADDRCNTR_CNTR(x) ((0xF000&(x))>>12) ++#define ADDRCNTR_OFFSET(x) (0x03FF&(x)) ++ ++/* NFI_LOCK */ ++#define NFI_LOCK_ON (0x0001) ++ ++/* NFI_LOCKANOB */ ++#define PROG_RADD_NOB_MASK (0x7000) ++#define PROG_RADD_NOB_SHIFT (12) ++#define PROG_CADD_NOB_MASK (0x0300) ++#define PROG_CADD_NOB_SHIFT (8) ++#define ERASE_RADD_NOB_MASK (0x0070) ++#define ERASE_RADD_NOB_SHIFT (4) ++#define ERASE_CADD_NOB_MASK (0x0007) ++#define ERASE_CADD_NOB_SHIFT (0) ++ ++/******************************************************************************* ++ * ECC Register Definition ++ *******************************************************************************/ ++ ++#define ECC_ENCCON_REG16 ((volatile P_U16)(NFIECC_BASE+0x0000)) ++#define ECC_ENCCNFG_REG32 ((volatile P_U32)(NFIECC_BASE+0x0004)) ++#define ECC_ENCDIADDR_REG32 ((volatile P_U32)(NFIECC_BASE+0x0008)) ++#define ECC_ENCIDLE_REG32 ((volatile P_U32)(NFIECC_BASE+0x000C)) ++#define ECC_ENCPAR0_REG32 ((volatile P_U32)(NFIECC_BASE+0x0010)) ++#define ECC_ENCPAR1_REG32 ((volatile P_U32)(NFIECC_BASE+0x0014)) ++#define ECC_ENCPAR2_REG32 ((volatile P_U32)(NFIECC_BASE+0x0018)) ++#define ECC_ENCPAR3_REG32 ((volatile P_U32)(NFIECC_BASE+0x001C)) ++#define ECC_ENCPAR4_REG32 ((volatile P_U32)(NFIECC_BASE+0x0020)) ++#define ECC_ENCSTA_REG32 ((volatile P_U32)(NFIECC_BASE+0x0024)) ++#define ECC_ENCIRQEN_REG16 ((volatile P_U16)(NFIECC_BASE+0x0028)) ++#define ECC_ENCIRQSTA_REG16 ((volatile P_U16)(NFIECC_BASE+0x002C)) ++ ++#define ECC_DECCON_REG16 ((volatile P_U16)(NFIECC_BASE+0x0100)) ++#define ECC_DECCNFG_REG32 ((volatile P_U32)(NFIECC_BASE+0x0104)) ++#define ECC_DECDIADDR_REG32 ((volatile P_U32)(NFIECC_BASE+0x0108)) ++#define ECC_DECIDLE_REG16 ((volatile P_U16)(NFIECC_BASE+0x010C)) ++#define ECC_DECFER_REG16 ((volatile P_U16)(NFIECC_BASE+0x0110)) ++#define ECC_DECENUM_REG32 ((volatile P_U32)(NFIECC_BASE+0x0114)) ++#define ECC_DECDONE_REG16 ((volatile P_U16)(NFIECC_BASE+0x0118)) ++#define ECC_DECEL0_REG32 ((volatile P_U32)(NFIECC_BASE+0x011C)) ++#define ECC_DECEL1_REG32 ((volatile P_U32)(NFIECC_BASE+0x0120)) ++#define ECC_DECEL2_REG32 ((volatile P_U32)(NFIECC_BASE+0x0124)) ++#define ECC_DECEL3_REG32 ((volatile P_U32)(NFIECC_BASE+0x0128)) ++#define ECC_DECEL4_REG32 ((volatile P_U32)(NFIECC_BASE+0x012C)) ++#define ECC_DECEL5_REG32 ((volatile P_U32)(NFIECC_BASE+0x0130)) ++#define ECC_DECIRQEN_REG16 ((volatile P_U16)(NFIECC_BASE+0x0134)) ++#define ECC_DECIRQSTA_REG16 ((volatile P_U16)(NFIECC_BASE+0x0138)) ++#define ECC_FDMADDR_REG32 ((volatile P_U32)(NFIECC_BASE+0x013C)) ++#define ECC_DECFSM_REG32 ((volatile P_U32)(NFIECC_BASE+0x0140)) ++#define ECC_SYNSTA_REG32 ((volatile P_U32)(NFIECC_BASE+0x0144)) ++#define ECC_DECNFIDI_REG32 ((volatile P_U32)(NFIECC_BASE+0x0148)) ++#define ECC_SYN0_REG32 ((volatile P_U32)(NFIECC_BASE+0x014C)) ++ ++/******************************************************************************* ++ * ECC register definition ++ *******************************************************************************/ ++/* ECC_ENCON */ ++#define ENC_EN (0x0001) ++#define ENC_DE (0x0000) ++ ++/* ECC_ENCCNFG */ ++#define ECC_CNFG_ECC4 (0x0000) ++#define ECC_CNFG_ECC6 (0x0001) ++#define ECC_CNFG_ECC8 (0x0002) ++#define ECC_CNFG_ECC10 (0x0003) ++#define ECC_CNFG_ECC12 (0x0004) ++#define ECC_CNFG_ECC_MASK (0x00000007) ++ ++#define ENC_CNFG_NFI (0x0010) ++#define ENC_CNFG_MODE_MASK (0x0010) ++ ++#define ENC_CNFG_META6 (0x10300000) ++#define ENC_CNFG_META8 (0x10400000) ++ ++#define ENC_CNFG_MSG_MASK (0x1FFF0000) ++#define ENC_CNFG_MSG_SHIFT (0x10) ++ ++/* ECC_ENCIDLE */ ++#define ENC_IDLE (0x0001) ++ ++/* ECC_ENCSTA */ ++#define STA_FSM (0x001F) ++#define STA_COUNT_PS (0xFF10) ++#define STA_COUNT_MS (0x3FFF0000) ++ ++/* ECC_ENCIRQEN */ ++#define ENC_IRQEN (0x0001) ++ ++/* ECC_ENCIRQSTA */ ++#define ENC_IRQSTA (0x0001) ++ ++/* ECC_DECCON */ ++#define DEC_EN (0x0001) ++#define DEC_DE (0x0000) ++ ++/* ECC_ENCCNFG */ ++#define DEC_CNFG_ECC4 (0x0000) ++//#define DEC_CNFG_ECC6 (0x0001) ++//#define DEC_CNFG_ECC12 (0x0002) ++#define DEC_CNFG_NFI (0x0010) ++//#define DEC_CNFG_META6 (0x10300000) ++//#define DEC_CNFG_META8 (0x10400000) ++ ++#define DEC_CNFG_FER (0x01000) ++#define DEC_CNFG_EL (0x02000) ++#define DEC_CNFG_CORRECT (0x03000) ++#define DEC_CNFG_TYPE_MASK (0x03000) ++ ++#define DEC_CNFG_EMPTY_EN (0x80000000) ++ ++#define DEC_CNFG_CODE_MASK (0x1FFF0000) ++#define DEC_CNFG_CODE_SHIFT (0x10) ++ ++/* ECC_DECIDLE */ ++#define DEC_IDLE (0x0001) ++ ++/* ECC_DECFER */ ++#define DEC_FER0 (0x0001) ++#define DEC_FER1 (0x0002) ++#define DEC_FER2 (0x0004) ++#define DEC_FER3 (0x0008) ++#define DEC_FER4 (0x0010) ++#define DEC_FER5 (0x0020) ++#define DEC_FER6 (0x0040) ++#define DEC_FER7 (0x0080) ++ ++/* ECC_DECENUM */ ++#define ERR_NUM0 (0x0000000F) ++#define ERR_NUM1 (0x000000F0) ++#define ERR_NUM2 (0x00000F00) ++#define ERR_NUM3 (0x0000F000) ++#define ERR_NUM4 (0x000F0000) ++#define ERR_NUM5 (0x00F00000) ++#define ERR_NUM6 (0x0F000000) ++#define ERR_NUM7 (0xF0000000) ++ ++/* ECC_DECDONE */ ++#define DEC_DONE0 (0x0001) ++#define DEC_DONE1 (0x0002) ++#define DEC_DONE2 (0x0004) ++#define DEC_DONE3 (0x0008) ++#define DEC_DONE4 (0x0010) ++#define DEC_DONE5 (0x0020) ++#define DEC_DONE6 (0x0040) ++#define DEC_DONE7 (0x0080) ++ ++/* ECC_DECIRQEN */ ++#define DEC_IRQEN (0x0001) ++ ++/* ECC_DECIRQSTA */ ++#define DEC_IRQSTA (0x0001) ++ ++#define CHIPVER_ECO_1 (0x8a00) ++#define CHIPVER_ECO_2 (0x8a01) ++ ++//#define NAND_PFM ++ ++/******************************************************************************* ++ * Data Structure Definition ++ *******************************************************************************/ ++struct mtk_nand_host ++{ ++ struct nand_chip nand_chip; ++ struct mtd_info *mtd; ++ struct mtk_nand_host_hw *hw; ++}; ++ ++struct NAND_CMD ++{ ++ u32 u4ColAddr; ++ u32 u4RowAddr; ++ u32 u4OOBRowAddr; ++ u8 au1OOB[288]; ++ u8* pDataBuf; ++#ifdef NAND_PFM ++ u32 pureReadOOB; ++ u32 pureReadOOBNum; ++#endif ++}; ++ ++/* ++ * ECC layout control structure. Exported to userspace for ++ * diagnosis and to allow creation of raw images ++struct nand_ecclayout { ++ uint32_t eccbytes; ++ uint32_t eccpos[64]; ++ uint32_t oobavail; ++ struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; ++}; ++*/ ++#define __DEBUG_NAND 1 /* Debug information on/off */ ++ ++/* Debug message event */ ++#define DBG_EVT_NONE 0x00000000 /* No event */ ++#define DBG_EVT_INIT 0x00000001 /* Initial related event */ ++#define DBG_EVT_VERIFY 0x00000002 /* Verify buffer related event */ ++#define DBG_EVT_PERFORMANCE 0x00000004 /* Performance related event */ ++#define DBG_EVT_READ 0x00000008 /* Read related event */ ++#define DBG_EVT_WRITE 0x00000010 /* Write related event */ ++#define DBG_EVT_ERASE 0x00000020 /* Erase related event */ ++#define DBG_EVT_BADBLOCK 0x00000040 /* Badblock related event */ ++#define DBG_EVT_POWERCTL 0x00000080 /* Suspend/Resume related event */ ++ ++#define DBG_EVT_ALL 0xffffffff ++ ++#define DBG_EVT_MASK (DBG_EVT_INIT) ++ ++#if __DEBUG_NAND ++#define MSG(evt, fmt, args...) \ ++do { \ ++ if ((DBG_EVT_##evt) & DBG_EVT_MASK) { \ ++ printk(fmt, ##args); \ ++ } \ ++} while(0) ++ ++#define MSG_FUNC_ENTRY(f) MSG(FUC, ": %s\n", __FUNCTION__) ++#else ++#define MSG(evt, fmt, args...) do{}while(0) ++#define MSG_FUNC_ENTRY(f) do{}while(0) ++#endif ++ ++#define RAMDOM_READ 1<<0 ++#define CACHE_READ 1<<1 ++ ++typedef struct ++{ ++ u16 id; //deviceid+menuid ++ u32 ext_id; ++ u8 addr_cycle; ++ u8 iowidth; ++ u16 totalsize; ++ u16 blocksize; ++ u16 pagesize; ++ u16 sparesize; ++ u32 timmingsetting; ++ char devciename[14]; ++ u32 advancedmode; // ++}flashdev_info,*pflashdev_info; ++ ++/* NAND driver */ ++#if 0 ++struct mtk_nand_host_hw { ++ unsigned int nfi_bus_width; /* NFI_BUS_WIDTH */ ++ unsigned int nfi_access_timing; /* NFI_ACCESS_TIMING */ ++ unsigned int nfi_cs_num; /* NFI_CS_NUM */ ++ unsigned int nand_sec_size; /* NAND_SECTOR_SIZE */ ++ unsigned int nand_sec_shift; /* NAND_SECTOR_SHIFT */ ++ unsigned int nand_ecc_size; ++ unsigned int nand_ecc_bytes; ++ unsigned int nand_ecc_mode; ++}; ++extern struct mtk_nand_host_hw mt7621_nand_hw; ++extern u32 CFG_BLOCKSIZE; ++#endif ++#endif +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -48,7 +48,7 @@ + #include + #include + +-static int nand_get_device(struct mtd_info *mtd, int new_state); ++int nand_get_device(struct mtd_info *mtd, int new_state); + + static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops); +@@ -240,7 +240,7 @@ static int check_offs_len(struct mtd_inf + * + * Release chip lock and wake up anyone waiting on the device. + */ +-static void nand_release_device(struct mtd_info *mtd) ++void nand_release_device(struct mtd_info *mtd) + { + struct nand_chip *chip = mtd_to_nand(mtd); + +@@ -968,7 +968,7 @@ static void panic_nand_get_device(struct + * + * Get the device and lock it for exclusive access + */ +-static int ++int + nand_get_device(struct mtd_info *mtd, int new_state) + { + struct nand_chip *chip = mtd_to_nand(mtd); +--- a/drivers/mtd/nand/nand_bbt.c ++++ b/drivers/mtd/nand/nand_bbt.c +@@ -1215,6 +1215,25 @@ err: + return res; + } + ++void nand_bbt_set(struct mtd_info *mtd, int page, int flag) ++{ ++ struct nand_chip *this = mtd->priv; ++ int block; ++ ++ block = (int)(page >> (this->bbt_erase_shift - this->page_shift - 1)); ++ this->bbt[block >> 3] &= ~(0x03 << (block & 0x6)); ++ this->bbt[block >> 3] |= (flag & 0x3) << (block & 0x6); ++} ++ ++int nand_bbt_get(struct mtd_info *mtd, int page) ++{ ++ struct nand_chip *this = mtd->priv; ++ int block; ++ ++ block = (int)(page >> (this->bbt_erase_shift - this->page_shift - 1)); ++ return (this->bbt[block >> 3] >> (block & 0x06)) & 0x03; ++} ++ + /** + * nand_update_bbt - update bad block table(s) + * @mtd: MTD device structure +--- /dev/null ++++ b/drivers/mtd/nand/nand_def.h +@@ -0,0 +1,123 @@ ++#ifndef __NAND_DEF_H__ ++#define __NAND_DEF_H__ ++ ++#define VERSION "v2.1 Fix AHB virt2phys error" ++#define MODULE_NAME "# MTK NAND #" ++#define PROCNAME "driver/nand" ++ ++#undef TESTTIME ++//#define __UBOOT_NAND__ 1 ++#define __KERNEL_NAND__ 1 ++//#define __PRELOADER_NAND__ 1 ++//#define PMT 1 ++//#define _MTK_NAND_DUMMY_DRIVER ++//#define CONFIG_BADBLOCK_CHECK 1 ++//#ifdef CONFIG_BADBLOCK_CHECK ++//#define MTK_NAND_BMT 1 ++//#endif ++#define ECC_ENABLE 1 ++#define MANUAL_CORRECT 1 ++//#define __INTERNAL_USE_AHB_MODE__ (0) ++#define SKIP_BAD_BLOCK ++#define FACT_BBT ++ ++#ifndef NAND_OTP_SUPPORT ++#define NAND_OTP_SUPPORT 0 ++#endif ++ ++/******************************************************************************* ++ * Macro definition ++ *******************************************************************************/ ++//#define NFI_SET_REG32(reg, value) (DRV_WriteReg32(reg, DRV_Reg32(reg) | (value))) ++//#define NFI_SET_REG16(reg, value) (DRV_WriteReg16(reg, DRV_Reg16(reg) | (value))) ++//#define NFI_CLN_REG32(reg, value) (DRV_WriteReg32(reg, DRV_Reg32(reg) & (~(value)))) ++//#define NFI_CLN_REG16(reg, value) (DRV_WriteReg16(reg, DRV_Reg16(reg) & (~(value)))) ++ ++#if defined (__KERNEL_NAND__) ++#define NFI_SET_REG32(reg, value) \ ++do { \ ++ g_value = (DRV_Reg32(reg) | (value));\ ++ DRV_WriteReg32(reg, g_value); \ ++} while(0) ++ ++#define NFI_SET_REG16(reg, value) \ ++do { \ ++ g_value = (DRV_Reg16(reg) | (value));\ ++ DRV_WriteReg16(reg, g_value); \ ++} while(0) ++ ++#define NFI_CLN_REG32(reg, value) \ ++do { \ ++ g_value = (DRV_Reg32(reg) & (~(value)));\ ++ DRV_WriteReg32(reg, g_value); \ ++} while(0) ++ ++#define NFI_CLN_REG16(reg, value) \ ++do { \ ++ g_value = (DRV_Reg16(reg) & (~(value)));\ ++ DRV_WriteReg16(reg, g_value); \ ++} while(0) ++#endif ++ ++#define NFI_WAIT_STATE_DONE(state) do{;}while (__raw_readl(NFI_STA_REG32) & state) ++#define NFI_WAIT_TO_READY() do{;}while (!(__raw_readl(NFI_STA_REG32) & STA_BUSY2READY)) ++ ++ ++#define NAND_SECTOR_SIZE (512) ++#define OOB_PER_SECTOR (16) ++#define OOB_AVAI_PER_SECTOR (8) ++ ++#ifndef PART_SIZE_BMTPOOL ++#define BMT_POOL_SIZE (80) ++#else ++#define BMT_POOL_SIZE (PART_SIZE_BMTPOOL) ++#endif ++ ++#define PMT_POOL_SIZE (2) ++ ++#define TIMEOUT_1 0x1fff ++#define TIMEOUT_2 0x8ff ++#define TIMEOUT_3 0xffff ++#define TIMEOUT_4 0xffff//5000 //PIO ++ ++ ++/* temporarity definiation */ ++#if !defined (__KERNEL_NAND__) ++#define KERN_INFO ++#define KERN_WARNING ++#define KERN_ERR ++#define PAGE_SIZE (4096) ++#endif ++#define AddStorageTrace //AddStorageTrace ++#define STORAGE_LOGGER_MSG_NAND 0 ++#define NFI_BASE RALINK_NAND_CTRL_BASE ++#define NFIECC_BASE RALINK_NANDECC_CTRL_BASE ++ ++#ifdef __INTERNAL_USE_AHB_MODE__ ++#define MT65xx_POLARITY_LOW 0 ++#define MT65XX_PDN_PERI_NFI 0 ++#define MT65xx_EDGE_SENSITIVE 0 ++#define MT6575_NFI_IRQ_ID (58) ++#endif ++ ++#if defined (__KERNEL_NAND__) ++#define RALINK_REG(x) (*((volatile u32 *)(x))) ++#define __virt_to_phys(x) virt_to_phys((volatile void*)x) ++#else ++#define CONFIG_MTD_NAND_VERIFY_WRITE (1) ++#define printk printf ++#define ra_dbg printf ++#define BUG() //BUG() ++#define BUG_ON(x) //BUG_ON() ++#define NUM_PARTITIONS 1 ++#endif ++ ++#define NFI_DEFAULT_ACCESS_TIMING (0x30C77fff) //(0x44333) ++ ++//uboot only support 1 cs ++#define NFI_CS_NUM (1) ++#define NFI_DEFAULT_CS (0) ++ ++#include "mt6575_typedefs.h" ++ ++#endif /* __NAND_DEF_H__ */ +--- /dev/null ++++ b/drivers/mtd/nand/nand_device_list.h +@@ -0,0 +1,56 @@ ++/* Copyright Statement: ++ * ++ * This software/firmware and related documentation ("MediaTek Software") are ++ * protected under relevant copyright laws. The information contained herein ++ * is confidential and proprietary to MediaTek Inc. and/or its licensors. ++ * Without the prior written permission of MediaTek inc. and/or its licensors, ++ * any reproduction, modification, use or disclosure of MediaTek Software, ++ * and information contained herein, in whole or in part, shall be strictly prohibited. ++ */ ++/* MediaTek Inc. (C) 2010. All rights reserved. ++ * ++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON ++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH ++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES ++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES ++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK ++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR ++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND ++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO ++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++ * ++ * The following software/firmware and/or related documentation ("MediaTek Software") ++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's ++ * applicable license agreements with MediaTek Inc. ++ */ ++ ++#ifndef __NAND_DEVICE_LIST_H__ ++#define __NAND_DEVICE_LIST_H__ ++ ++static const flashdev_info gen_FlashTable[]={ ++ {0x20BC, 0x105554, 5, 16, 512, 128, 2048, 64, 0x1123, "EHD013151MA_5", 0}, ++ {0xECBC, 0x005554, 5, 16, 512, 128, 2048, 64, 0x1123, "K524G2GACB_A0", 0}, ++ {0x2CBC, 0x905556, 5, 16, 512, 128, 2048, 64, 0x21044333, "MT29C4G96MAZA", 0}, ++ {0x2CDA, 0x909506, 5, 8, 256, 128, 2048, 64, 0x30C77fff, "MT29F2G08ABAE", 0}, ++ {0xADBC, 0x905554, 5, 16, 512, 128, 2048, 64, 0x10801011, "H9DA4GH4JJAMC", 0}, ++ {0x01F1, 0x801D01, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "S34ML01G100TF", 0}, ++ {0x92F1, 0x8095FF, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "F59L1G81A", 0}, ++ {0xECD3, 0x519558, 5, 8, 1024, 128, 2048, 64, 0x44333, "K9K8G8000", 0}, ++ {0xC2F1, 0x801DC2, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "MX30LF1G08AA", 0}, ++ {0x98D3, 0x902676, 5, 8, 1024, 256, 4096, 224, 0x00C25332, "TC58NVG3S0F", 0}, ++ {0x01DA, 0x909546, 5, 8, 256, 128, 2048, 128, 0x30C77fff, "S34ML02G200TF", 0}, ++ {0x01DC, 0x909556, 5, 8, 512, 128, 2048, 128, 0x30C77fff, "S34ML04G200TF", 0}, ++ {0x0000, 0x000000, 0, 0, 0, 0, 0, 0, 0, "xxxxxxxxxx", 0}, ++}; ++ ++ ++#endif +--- /dev/null ++++ b/drivers/mtd/nand/partition.h +@@ -0,0 +1,115 @@ ++/* Copyright Statement: ++ * ++ * This software/firmware and related documentation ("MediaTek Software") are ++ * protected under relevant copyright laws. The information contained herein ++ * is confidential and proprietary to MediaTek Inc. and/or its licensors. ++ * Without the prior written permission of MediaTek inc. and/or its licensors, ++ * any reproduction, modification, use or disclosure of MediaTek Software, ++ * and information contained herein, in whole or in part, shall be strictly prohibited. ++ */ ++/* MediaTek Inc. (C) 2010. All rights reserved. ++ * ++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON ++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH ++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES ++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES ++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK ++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR ++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND ++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO ++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++ * ++ * The following software/firmware and/or related documentation ("MediaTek Software") ++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's ++ * applicable license agreements with MediaTek Inc. ++ */ ++ ++#include ++#include ++#include ++ ++#define RECONFIG_PARTITION_SIZE 1 ++ ++#define MTD_BOOT_PART_SIZE 0x80000 ++#define MTD_CONFIG_PART_SIZE 0x20000 ++#define MTD_FACTORY_PART_SIZE 0x20000 ++ ++extern unsigned int CFG_BLOCKSIZE; ++#define LARGE_MTD_BOOT_PART_SIZE (CFG_BLOCKSIZE<<2) ++#define LARGE_MTD_CONFIG_PART_SIZE (CFG_BLOCKSIZE<<2) ++#define LARGE_MTD_FACTORY_PART_SIZE (CFG_BLOCKSIZE<<1) ++ ++/*=======================================================================*/ ++/* NAND PARTITION Mapping */ ++/*=======================================================================*/ ++//#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition g_pasStatic_Partition[] = { ++ { ++ name: "ALL", ++ size: MTDPART_SIZ_FULL, ++ offset: 0, ++ }, ++ /* Put your own partition definitions here */ ++ { ++ name: "Bootloader", ++ size: MTD_BOOT_PART_SIZE, ++ offset: 0, ++ }, { ++ name: "Config", ++ size: MTD_CONFIG_PART_SIZE, ++ offset: MTDPART_OFS_APPEND ++ }, { ++ name: "Factory", ++ size: MTD_FACTORY_PART_SIZE, ++ offset: MTDPART_OFS_APPEND ++#ifdef CONFIG_RT2880_ROOTFS_IN_FLASH ++ }, { ++ name: "Kernel", ++ size: MTD_KERN_PART_SIZE, ++ offset: MTDPART_OFS_APPEND, ++ }, { ++ name: "RootFS", ++ size: MTD_ROOTFS_PART_SIZE, ++ offset: MTDPART_OFS_APPEND, ++#ifdef CONFIG_ROOTFS_IN_FLASH_NO_PADDING ++ }, { ++ name: "Kernel_RootFS", ++ size: MTD_KERN_PART_SIZE + MTD_ROOTFS_PART_SIZE, ++ offset: MTD_BOOT_PART_SIZE + MTD_CONFIG_PART_SIZE + MTD_FACTORY_PART_SIZE, ++#endif ++#else //CONFIG_RT2880_ROOTFS_IN_RAM ++ }, { ++ name: "Kernel", ++ size: 0x10000, ++ offset: MTDPART_OFS_APPEND, ++#endif ++#ifdef CONFIG_DUAL_IMAGE ++ }, { ++ name: "Kernel2", ++ size: MTD_KERN2_PART_SIZE, ++ offset: MTD_KERN2_PART_OFFSET, ++#ifdef CONFIG_RT2880_ROOTFS_IN_FLASH ++ }, { ++ name: "RootFS2", ++ size: MTD_ROOTFS2_PART_SIZE, ++ offset: MTD_ROOTFS2_PART_OFFSET, ++#endif ++#endif ++ } ++ ++}; ++ ++#define NUM_PARTITIONS ARRAY_SIZE(g_pasStatic_Partition) ++extern int part_num; // = NUM_PARTITIONS; ++//#endif ++#undef RECONFIG_PARTITION_SIZE ++ diff --git a/target/linux/ramips/patches-4.14/0040-nand-hack-restore-write_page.patch b/target/linux/ramips/patches-4.14/0040-nand-hack-restore-write_page.patch new file mode 100644 index 000000000..ec2afeaf0 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0040-nand-hack-restore-write_page.patch @@ -0,0 +1,42 @@ +--- a/include/linux/mtd/rawnand.h ++++ b/include/linux/mtd/rawnand.h +@@ -885,6 +885,9 @@ struct nand_chip { + int(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this); + int (*erase)(struct mtd_info *mtd, int page); + int (*scan_bbt)(struct mtd_info *mtd); ++ int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, ++ uint32_t offset, int data_len, const uint8_t *buf, ++ int oob_required, int page, int raw); + int (*onfi_set_features)(struct mtd_info *mtd, struct nand_chip *chip, + int feature_addr, uint8_t *subfeature_para); + int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip, +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -2761,9 +2761,14 @@ static int nand_do_write_ops(struct mtd_ + memset(chip->oob_poi, 0xff, mtd->oobsize); + } + +- ret = nand_write_page(mtd, chip, column, bytes, wbuf, +- oob_required, page, +- (ops->mode == MTD_OPS_RAW)); ++// if (chip->write_page) ++ ret = chip->write_page(mtd, chip, column, bytes, wbuf, ++ oob_required, page, ++ (ops->mode == MTD_OPS_RAW)); ++// else ++// ret = nand_write_page(mtd, chip, column, bytes, wbuf, ++// oob_required, page, ++// (ops->mode == MTD_OPS_RAW)); + if (ret) + break; + +@@ -4719,6 +4724,9 @@ int nand_scan_tail(struct mtd_info *mtd) + } + } + ++// if (!chip->write_page) ++// chip->write_page = nand_write_page; ++ + /* + * Check ECC mode, default to software if 3byte/512byte hardware ECC is + * selected and we have 256 byte pagesize fallback to software ECC diff --git a/target/linux/ramips/patches-4.14/0040-nand-hack.patch b/target/linux/ramips/patches-4.14/0040-nand-hack.patch new file mode 100644 index 000000000..ae6eed933 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0040-nand-hack.patch @@ -0,0 +1,65 @@ +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -1908,6 +1908,9 @@ static int nand_do_read_ops(struct mtd_i + __func__, buf); + + read_retry: ++#ifdef CONFIG_MTK_MTD_NAND ++ ret = chip->read_page(mtd, chip, bufpoi, page); ++#else + if (nand_standard_page_accessors(&chip->ecc)) + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); + +@@ -1927,6 +1930,7 @@ read_retry: + else + ret = chip->ecc.read_page(mtd, chip, bufpoi, + oob_required, page); ++#endif + if (ret < 0) { + if (use_bufpoi) + /* Invalidate page cache */ +@@ -3084,8 +3088,11 @@ int nand_erase_nand(struct mtd_info *mtd + (page + pages_per_block)) + chip->pagebuf = -1; + ++#ifdef CONFIG_MTK_MTD_NAND ++ status = chip->erase_mtk(mtd, page & chip->pagemask); ++#else + status = chip->erase(mtd, page & chip->pagemask); +- ++#endif + /* See if block erase succeeded */ + if (status & NAND_STATUS_FAIL) { + pr_debug("%s: failed erase, page 0x%08x\n", +@@ -4215,6 +4222,7 @@ int nand_scan_ident(struct mtd_info *mtd + * cmdfunc() both expect cmd_ctrl() to be populated, + * so we need to check that that's the case + */ ++ printk("%s:%s[%d]%p %p %p\n", __FILE__, __func__, __LINE__, chip->cmdfunc, chip->select_chip, chip->cmd_ctrl); + pr_err("chip.cmd_ctrl() callback is not provided"); + return -EINVAL; + } +--- a/drivers/mtd/nand/nand_device_list.h ++++ b/drivers/mtd/nand/nand_device_list.h +@@ -44,6 +44,8 @@ static const flashdev_info gen_FlashTabl + {0xADBC, 0x905554, 5, 16, 512, 128, 2048, 64, 0x10801011, "H9DA4GH4JJAMC", 0}, + {0x01F1, 0x801D01, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "S34ML01G100TF", 0}, + {0x92F1, 0x8095FF, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "F59L1G81A", 0}, ++ {0xC8DA, 0x909544, 5, 8, 256, 128, 2048, 64, 0x30C77fff, "F59L2G81A", 0}, ++ {0xC8DC, 0x909554, 5, 8, 512, 128, 2048, 64, 0x30C77fff, "F59L4G81A", 0}, + {0xECD3, 0x519558, 5, 8, 1024, 128, 2048, 64, 0x44333, "K9K8G8000", 0}, + {0xC2F1, 0x801DC2, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "MX30LF1G08AA", 0}, + {0x98D3, 0x902676, 5, 8, 1024, 256, 4096, 224, 0x00C25332, "TC58NVG3S0F", 0}, +--- a/include/linux/mtd/rawnand.h ++++ b/include/linux/mtd/rawnand.h +@@ -896,6 +896,10 @@ struct nand_chip { + int (*setup_data_interface)(struct mtd_info *mtd, int chipnr, + const struct nand_data_interface *conf); + ++#ifdef CONFIG_MTK_MTD_NAND ++ int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, u8 *buf, int page); ++ int (*erase_mtk)(struct mtd_info *mtd, int page); ++#endif /* CONFIG_MTK_MTD_NAND */ + + int chip_delay; + unsigned int options; diff --git a/target/linux/ramips/patches-4.14/0041-DT-Add-documentation-for-spi-rt2880.patch b/target/linux/ramips/patches-4.14/0041-DT-Add-documentation-for-spi-rt2880.patch new file mode 100644 index 000000000..e2643e3f2 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0041-DT-Add-documentation-for-spi-rt2880.patch @@ -0,0 +1,44 @@ +From da6015e7f19d749f135f7ac55c4ec47b06faa868 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 9 Aug 2013 20:12:59 +0200 +Subject: [PATCH 41/53] DT: Add documentation for spi-rt2880 + +Describe the SPI master found on the MIPS based Ralink RT2880 SoC. + +Signed-off-by: John Crispin +--- + .../devicetree/bindings/spi/spi-rt2880.txt | 28 ++++++++++++++++++++ + 1 file changed, 28 insertions(+) + create mode 100644 Documentation/devicetree/bindings/spi/spi-rt2880.txt + +--- /dev/null ++++ b/Documentation/devicetree/bindings/spi/spi-rt2880.txt +@@ -0,0 +1,28 @@ ++Ralink SoC RT2880 SPI master controller. ++ ++This SPI controller is found on most wireless SoCs made by ralink. ++ ++Required properties: ++- compatible : "ralink,rt2880-spi" ++- reg : The register base for the controller. ++- #address-cells : <1>, as required by generic SPI binding. ++- #size-cells : <0>, also as required by generic SPI binding. ++ ++Child nodes as per the generic SPI binding. ++ ++Example: ++ ++ spi@b00 { ++ compatible = "ralink,rt2880-spi"; ++ reg = <0xb00 0x100>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ m25p80@0 { ++ compatible = "m25p80"; ++ reg = <0>; ++ spi-max-frequency = <10000000>; ++ }; ++ }; ++ diff --git a/target/linux/ramips/patches-4.14/0042-SPI-ralink-add-Ralink-SoC-spi-driver.patch b/target/linux/ramips/patches-4.14/0042-SPI-ralink-add-Ralink-SoC-spi-driver.patch new file mode 100644 index 000000000..1dd9f40c3 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0042-SPI-ralink-add-Ralink-SoC-spi-driver.patch @@ -0,0 +1,574 @@ +From 683af4ebb91a1600df1946ac4769d916b8a1be65 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 11:15:12 +0100 +Subject: [PATCH 42/53] SPI: ralink: add Ralink SoC spi driver + +Add the driver needed to make SPI work on Ralink SoC. + +Signed-off-by: Gabor Juhos +Acked-by: John Crispin +--- + drivers/spi/Kconfig | 6 + + drivers/spi/Makefile | 1 + + drivers/spi/spi-rt2880.c | 530 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 537 insertions(+) + create mode 100644 drivers/spi/spi-rt2880.c + +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -563,6 +563,12 @@ config SPI_QUP + This driver can also be built as a module. If so, the module + will be called spi_qup. + ++config SPI_RT2880 ++ tristate "Ralink RT288x SPI Controller" ++ depends on RALINK ++ help ++ This selects a driver for the Ralink RT288x/RT305x SPI Controller. ++ + config SPI_S3C24XX + tristate "Samsung S3C24XX series SPI" + depends on ARCH_S3C24XX +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -81,6 +81,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o + obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o + obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o + obj-$(CONFIG_SPI_RSPI) += spi-rspi.o ++obj-$(CONFIG_SPI_RT2880) += spi-rt2880.o + obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o + spi-s3c24xx-hw-y := spi-s3c24xx.o + spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o +--- /dev/null ++++ b/drivers/spi/spi-rt2880.c +@@ -0,0 +1,530 @@ ++/* ++ * spi-rt2880.c -- Ralink RT288x/RT305x SPI controller driver ++ * ++ * Copyright (C) 2011 Sergiy ++ * Copyright (C) 2011-2013 Gabor Juhos ++ * ++ * Some parts are based on spi-orion.c: ++ * Author: Shadi Ammouri ++ * Copyright (C) 2007-2008 Marvell Ltd. ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "spi-rt2880" ++ ++#define RAMIPS_SPI_STAT 0x00 ++#define RAMIPS_SPI_CFG 0x10 ++#define RAMIPS_SPI_CTL 0x14 ++#define RAMIPS_SPI_DATA 0x20 ++#define RAMIPS_SPI_ADDR 0x24 ++#define RAMIPS_SPI_BS 0x28 ++#define RAMIPS_SPI_USER 0x2C ++#define RAMIPS_SPI_TXFIFO 0x30 ++#define RAMIPS_SPI_RXFIFO 0x34 ++#define RAMIPS_SPI_FIFO_STAT 0x38 ++#define RAMIPS_SPI_MODE 0x3C ++#define RAMIPS_SPI_DEV_OFFSET 0x40 ++#define RAMIPS_SPI_DMA 0x80 ++#define RAMIPS_SPI_DMASTAT 0x84 ++#define RAMIPS_SPI_ARBITER 0xF0 ++ ++/* SPISTAT register bit field */ ++#define SPISTAT_BUSY BIT(0) ++ ++/* SPICFG register bit field */ ++#define SPICFG_ADDRMODE BIT(12) ++#define SPICFG_RXENVDIS BIT(11) ++#define SPICFG_RXCAP BIT(10) ++#define SPICFG_SPIENMODE BIT(9) ++#define SPICFG_MSBFIRST BIT(8) ++#define SPICFG_SPICLKPOL BIT(6) ++#define SPICFG_RXCLKEDGE_FALLING BIT(5) ++#define SPICFG_TXCLKEDGE_FALLING BIT(4) ++#define SPICFG_HIZSPI BIT(3) ++#define SPICFG_SPICLK_PRESCALE_MASK 0x7 ++#define SPICFG_SPICLK_DIV2 0 ++#define SPICFG_SPICLK_DIV4 1 ++#define SPICFG_SPICLK_DIV8 2 ++#define SPICFG_SPICLK_DIV16 3 ++#define SPICFG_SPICLK_DIV32 4 ++#define SPICFG_SPICLK_DIV64 5 ++#define SPICFG_SPICLK_DIV128 6 ++#define SPICFG_SPICLK_DISABLE 7 ++ ++/* SPICTL register bit field */ ++#define SPICTL_START BIT(4) ++#define SPICTL_HIZSDO BIT(3) ++#define SPICTL_STARTWR BIT(2) ++#define SPICTL_STARTRD BIT(1) ++#define SPICTL_SPIENA BIT(0) ++ ++/* SPIUSER register bit field */ ++#define SPIUSER_USERMODE BIT(21) ++#define SPIUSER_INSTR_PHASE BIT(20) ++#define SPIUSER_ADDR_PHASE_MASK 0x7 ++#define SPIUSER_ADDR_PHASE_OFFSET 17 ++#define SPIUSER_MODE_PHASE BIT(16) ++#define SPIUSER_DUMMY_PHASE_MASK 0x3 ++#define SPIUSER_DUMMY_PHASE_OFFSET 14 ++#define SPIUSER_DATA_PHASE_MASK 0x3 ++#define SPIUSER_DATA_PHASE_OFFSET 12 ++#define SPIUSER_DATA_READ (BIT(0) << SPIUSER_DATA_PHASE_OFFSET) ++#define SPIUSER_DATA_WRITE (BIT(1) << SPIUSER_DATA_PHASE_OFFSET) ++#define SPIUSER_ADDR_TYPE_OFFSET 9 ++#define SPIUSER_MODE_TYPE_OFFSET 6 ++#define SPIUSER_DUMMY_TYPE_OFFSET 3 ++#define SPIUSER_DATA_TYPE_OFFSET 0 ++#define SPIUSER_TRANSFER_MASK 0x7 ++#define SPIUSER_TRANSFER_SINGLE BIT(0) ++#define SPIUSER_TRANSFER_DUAL BIT(1) ++#define SPIUSER_TRANSFER_QUAD BIT(2) ++ ++#define SPIUSER_TRANSFER_TYPE(type) ( \ ++ (type << SPIUSER_ADDR_TYPE_OFFSET) | \ ++ (type << SPIUSER_MODE_TYPE_OFFSET) | \ ++ (type << SPIUSER_DUMMY_TYPE_OFFSET) | \ ++ (type << SPIUSER_DATA_TYPE_OFFSET) \ ++) ++ ++/* SPIFIFOSTAT register bit field */ ++#define SPIFIFOSTAT_TXEMPTY BIT(19) ++#define SPIFIFOSTAT_RXEMPTY BIT(18) ++#define SPIFIFOSTAT_TXFULL BIT(17) ++#define SPIFIFOSTAT_RXFULL BIT(16) ++#define SPIFIFOSTAT_FIFO_MASK 0xff ++#define SPIFIFOSTAT_TX_OFFSET 8 ++#define SPIFIFOSTAT_RX_OFFSET 0 ++ ++#define SPI_FIFO_DEPTH 16 ++ ++/* SPIMODE register bit field */ ++#define SPIMODE_MODE_OFFSET 24 ++#define SPIMODE_DUMMY_OFFSET 0 ++ ++/* SPIARB register bit field */ ++#define SPICTL_ARB_EN BIT(31) ++#define SPICTL_CSCTL1 BIT(16) ++#define SPI1_POR BIT(1) ++#define SPI0_POR BIT(0) ++ ++#define RT2880_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | \ ++ SPI_CS_HIGH) ++ ++static atomic_t hw_reset_count = ATOMIC_INIT(0); ++ ++struct rt2880_spi { ++ struct spi_master *master; ++ void __iomem *base; ++ u32 speed; ++ u16 wait_loops; ++ u16 mode; ++ struct clk *clk; ++}; ++ ++static inline struct rt2880_spi *spidev_to_rt2880_spi(struct spi_device *spi) ++{ ++ return spi_master_get_devdata(spi->master); ++} ++ ++static inline u32 rt2880_spi_read(struct rt2880_spi *rs, u32 reg) ++{ ++ return ioread32(rs->base + reg); ++} ++ ++static inline void rt2880_spi_write(struct rt2880_spi *rs, u32 reg, ++ const u32 val) ++{ ++ iowrite32(val, rs->base + reg); ++} ++ ++static inline void rt2880_spi_setbits(struct rt2880_spi *rs, u32 reg, u32 mask) ++{ ++ void __iomem *addr = rs->base + reg; ++ ++ iowrite32((ioread32(addr) | mask), addr); ++} ++ ++static inline void rt2880_spi_clrbits(struct rt2880_spi *rs, u32 reg, u32 mask) ++{ ++ void __iomem *addr = rs->base + reg; ++ ++ iowrite32((ioread32(addr) & ~mask), addr); ++} ++ ++static u32 rt2880_spi_baudrate_get(struct spi_device *spi, unsigned int speed) ++{ ++ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); ++ u32 rate; ++ u32 prescale; ++ ++ /* ++ * the supported rates are: 2, 4, 8, ... 128 ++ * round up as we look for equal or less speed ++ */ ++ rate = DIV_ROUND_UP(clk_get_rate(rs->clk), speed); ++ rate = roundup_pow_of_two(rate); ++ ++ /* Convert the rate to SPI clock divisor value. */ ++ prescale = ilog2(rate / 2); ++ ++ /* some tolerance. double and add 100 */ ++ rs->wait_loops = (8 * HZ * loops_per_jiffy) / ++ (clk_get_rate(rs->clk) / rate); ++ rs->wait_loops = (rs->wait_loops << 1) + 100; ++ rs->speed = speed; ++ ++ dev_dbg(&spi->dev, "speed: %lu/%u, rate: %u, prescal: %u, loops: %hu\n", ++ clk_get_rate(rs->clk) / rate, speed, rate, prescale, ++ rs->wait_loops); ++ ++ return prescale; ++} ++ ++static u32 get_arbiter_offset(struct spi_master *master) ++{ ++ u32 offset; ++ ++ offset = RAMIPS_SPI_ARBITER; ++ if (master->bus_num == 1) ++ offset -= RAMIPS_SPI_DEV_OFFSET; ++ ++ return offset; ++} ++ ++static void rt2880_spi_set_cs(struct spi_device *spi, bool enable) ++{ ++ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); ++ ++ if (enable) ++ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA); ++ else ++ rt2880_spi_clrbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA); ++} ++ ++static int rt2880_spi_wait_ready(struct rt2880_spi *rs, int len) ++{ ++ int loop = rs->wait_loops * len; ++ ++ while ((rt2880_spi_read(rs, RAMIPS_SPI_STAT) & SPISTAT_BUSY) && --loop) ++ cpu_relax(); ++ ++ if (loop) ++ return 0; ++ ++ return -ETIMEDOUT; ++} ++ ++static void rt2880_dump_reg(struct spi_master *master) ++{ ++ struct rt2880_spi *rs = spi_master_get_devdata(master); ++ ++ dev_dbg(&master->dev, "stat: %08x, cfg: %08x, ctl: %08x, " \ ++ "data: %08x, arb: %08x\n", ++ rt2880_spi_read(rs, RAMIPS_SPI_STAT), ++ rt2880_spi_read(rs, RAMIPS_SPI_CFG), ++ rt2880_spi_read(rs, RAMIPS_SPI_CTL), ++ rt2880_spi_read(rs, RAMIPS_SPI_DATA), ++ rt2880_spi_read(rs, get_arbiter_offset(master))); ++} ++ ++static int rt2880_spi_transfer_one(struct spi_master *master, ++ struct spi_device *spi, struct spi_transfer *xfer) ++{ ++ struct rt2880_spi *rs = spi_master_get_devdata(master); ++ unsigned len; ++ const u8 *tx = xfer->tx_buf; ++ u8 *rx = xfer->rx_buf; ++ int err = 0; ++ ++ /* change clock speed */ ++ if (unlikely(rs->speed != xfer->speed_hz)) { ++ u32 reg; ++ reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG); ++ reg &= ~SPICFG_SPICLK_PRESCALE_MASK; ++ reg |= rt2880_spi_baudrate_get(spi, xfer->speed_hz); ++ rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg); ++ } ++ ++ if (tx) { ++ len = xfer->len; ++ while (len-- > 0) { ++ rt2880_spi_write(rs, RAMIPS_SPI_DATA, *tx++); ++ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTWR); ++ err = rt2880_spi_wait_ready(rs, 1); ++ if (err) { ++ dev_err(&spi->dev, "TX failed, err=%d\n", err); ++ goto out; ++ } ++ } ++ } ++ ++ if (rx) { ++ len = xfer->len; ++ while (len-- > 0) { ++ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTRD); ++ err = rt2880_spi_wait_ready(rs, 1); ++ if (err) { ++ dev_err(&spi->dev, "RX failed, err=%d\n", err); ++ goto out; ++ } ++ *rx++ = (u8) rt2880_spi_read(rs, RAMIPS_SPI_DATA); ++ } ++ } ++ ++out: ++ return err; ++} ++ ++/* copy from spi.c */ ++static void spi_set_cs(struct spi_device *spi, bool enable) ++{ ++ if (spi->mode & SPI_CS_HIGH) ++ enable = !enable; ++ ++ if (spi->cs_gpio >= 0) ++ gpio_set_value(spi->cs_gpio, !enable); ++ else if (spi->master->set_cs) ++ spi->master->set_cs(spi, !enable); ++} ++ ++static int rt2880_spi_setup(struct spi_device *spi) ++{ ++ struct spi_master *master = spi->master; ++ struct rt2880_spi *rs = spi_master_get_devdata(master); ++ u32 reg, old_reg, arbit_off; ++ ++ if ((spi->max_speed_hz > master->max_speed_hz) || ++ (spi->max_speed_hz < master->min_speed_hz)) { ++ dev_err(&spi->dev, "invalide requested speed %d Hz\n", ++ spi->max_speed_hz); ++ return -EINVAL; ++ } ++ ++ if (!(master->bits_per_word_mask & ++ BIT(spi->bits_per_word - 1))) { ++ dev_err(&spi->dev, "invalide bits_per_word %d\n", ++ spi->bits_per_word); ++ return -EINVAL; ++ } ++ ++ /* the hardware seems can't work on mode0 force it to mode3 */ ++ if ((spi->mode & (SPI_CPOL | SPI_CPHA)) == SPI_MODE_0) { ++ dev_warn(&spi->dev, "force spi mode3\n"); ++ spi->mode |= SPI_MODE_3; ++ } ++ ++ /* chip polarity */ ++ arbit_off = get_arbiter_offset(master); ++ reg = old_reg = rt2880_spi_read(rs, arbit_off); ++ if (spi->mode & SPI_CS_HIGH) { ++ switch (master->bus_num) { ++ case 1: ++ reg |= SPI1_POR; ++ break; ++ default: ++ reg |= SPI0_POR; ++ break; ++ } ++ } else { ++ switch (master->bus_num) { ++ case 1: ++ reg &= ~SPI1_POR; ++ break; ++ default: ++ reg &= ~SPI0_POR; ++ break; ++ } ++ } ++ ++ /* enable spi1 */ ++ if (master->bus_num == 1) ++ reg |= SPICTL_ARB_EN; ++ ++ if (reg != old_reg) ++ rt2880_spi_write(rs, arbit_off, reg); ++ ++ /* deselected the spi device */ ++ spi_set_cs(spi, false); ++ ++ rt2880_dump_reg(master); ++ ++ return 0; ++} ++ ++static int rt2880_spi_prepare_message(struct spi_master *master, ++ struct spi_message *msg) ++{ ++ struct rt2880_spi *rs = spi_master_get_devdata(master); ++ struct spi_device *spi = msg->spi; ++ u32 reg; ++ ++ if ((rs->mode == spi->mode) && (rs->speed == spi->max_speed_hz)) ++ return 0; ++ ++#if 0 ++ /* set spido to tri-state */ ++ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_HIZSDO); ++#endif ++ ++ reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG); ++ ++ reg &= ~(SPICFG_MSBFIRST | SPICFG_SPICLKPOL | ++ SPICFG_RXCLKEDGE_FALLING | ++ SPICFG_TXCLKEDGE_FALLING | ++ SPICFG_SPICLK_PRESCALE_MASK); ++ ++ /* MSB */ ++ if (!(spi->mode & SPI_LSB_FIRST)) ++ reg |= SPICFG_MSBFIRST; ++ ++ /* spi mode */ ++ switch (spi->mode & (SPI_CPOL | SPI_CPHA)) { ++ case SPI_MODE_0: ++ reg |= SPICFG_TXCLKEDGE_FALLING; ++ break; ++ case SPI_MODE_1: ++ reg |= SPICFG_RXCLKEDGE_FALLING; ++ break; ++ case SPI_MODE_2: ++ reg |= SPICFG_SPICLKPOL | SPICFG_RXCLKEDGE_FALLING; ++ break; ++ case SPI_MODE_3: ++ reg |= SPICFG_SPICLKPOL | SPICFG_TXCLKEDGE_FALLING; ++ break; ++ } ++ rs->mode = spi->mode; ++ ++#if 0 ++ /* set spiclk and spiena to tri-state */ ++ reg |= SPICFG_HIZSPI; ++#endif ++ ++ /* clock divide */ ++ reg |= rt2880_spi_baudrate_get(spi, spi->max_speed_hz); ++ ++ rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg); ++ ++ return 0; ++} ++ ++static int rt2880_spi_probe(struct platform_device *pdev) ++{ ++ struct spi_master *master; ++ struct rt2880_spi *rs; ++ void __iomem *base; ++ struct resource *r; ++ struct clk *clk; ++ int ret; ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(&pdev->dev, r); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(clk)) { ++ dev_err(&pdev->dev, "unable to get SYS clock\n"); ++ return PTR_ERR(clk); ++ } ++ ++ ret = clk_prepare_enable(clk); ++ if (ret) ++ goto err_clk; ++ ++ master = spi_alloc_master(&pdev->dev, sizeof(*rs)); ++ if (master == NULL) { ++ dev_dbg(&pdev->dev, "master allocation failed\n"); ++ ret = -ENOMEM; ++ goto err_clk; ++ } ++ ++ master->dev.of_node = pdev->dev.of_node; ++ master->mode_bits = RT2880_SPI_MODE_BITS; ++ master->bits_per_word_mask = SPI_BPW_MASK(8); ++ master->min_speed_hz = clk_get_rate(clk) / 128; ++ master->max_speed_hz = clk_get_rate(clk) / 2; ++ master->flags = SPI_MASTER_HALF_DUPLEX; ++ master->setup = rt2880_spi_setup; ++ master->prepare_message = rt2880_spi_prepare_message; ++ master->set_cs = rt2880_spi_set_cs; ++ master->transfer_one = rt2880_spi_transfer_one, ++ ++ dev_set_drvdata(&pdev->dev, master); ++ ++ rs = spi_master_get_devdata(master); ++ rs->master = master; ++ rs->base = base; ++ rs->clk = clk; ++ ++ if (atomic_inc_return(&hw_reset_count) == 1) ++ device_reset(&pdev->dev); ++ ++ ret = devm_spi_register_master(&pdev->dev, master); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "devm_spi_register_master error.\n"); ++ goto err_master; ++ } ++ ++ return ret; ++ ++err_master: ++ spi_master_put(master); ++ kfree(master); ++err_clk: ++ clk_disable_unprepare(clk); ++ ++ return ret; ++} ++ ++static int rt2880_spi_remove(struct platform_device *pdev) ++{ ++ struct spi_master *master; ++ struct rt2880_spi *rs; ++ ++ master = dev_get_drvdata(&pdev->dev); ++ rs = spi_master_get_devdata(master); ++ ++ clk_disable_unprepare(rs->clk); ++ atomic_dec(&hw_reset_count); ++ ++ return 0; ++} ++ ++MODULE_ALIAS("platform:" DRIVER_NAME); ++ ++static const struct of_device_id rt2880_spi_match[] = { ++ { .compatible = "ralink,rt2880-spi" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt2880_spi_match); ++ ++static struct platform_driver rt2880_spi_driver = { ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = rt2880_spi_match, ++ }, ++ .probe = rt2880_spi_probe, ++ .remove = rt2880_spi_remove, ++}; ++ ++module_platform_driver(rt2880_spi_driver); ++ ++MODULE_DESCRIPTION("Ralink SPI driver"); ++MODULE_AUTHOR("Sergiy "); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/ramips/patches-4.14/0043-spi-add-mt7621-support.patch b/target/linux/ramips/patches-4.14/0043-spi-add-mt7621-support.patch new file mode 100644 index 000000000..5f939e3e4 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0043-spi-add-mt7621-support.patch @@ -0,0 +1,532 @@ +From 87a5fcd57c577cd94b5b080deb98885077c13a42 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 09:49:07 +0100 +Subject: [PATCH 43/53] spi: add mt7621 support + +Signed-off-by: John Crispin +--- + drivers/spi/Kconfig | 6 + + drivers/spi/Makefile | 1 + + drivers/spi/spi-mt7621.c | 480 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 487 insertions(+) + create mode 100644 drivers/spi/spi-mt7621.c + +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -569,6 +569,12 @@ config SPI_RT2880 + help + This selects a driver for the Ralink RT288x/RT305x SPI Controller. + ++config SPI_MT7621 ++ tristate "MediaTek MT7621 SPI Controller" ++ depends on RALINK ++ help ++ This selects a driver for the MediaTek MT7621 SPI Controller. ++ + config SPI_S3C24XX + tristate "Samsung S3C24XX series SPI" + depends on ARCH_S3C24XX +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -60,6 +60,7 @@ obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mp + obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o + obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o + obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o ++obj-$(CONFIG_SPI_MT7621) += spi-mt7621.o + obj-$(CONFIG_SPI_MXS) += spi-mxs.o + obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o + obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o +--- /dev/null ++++ b/drivers/spi/spi-mt7621.c +@@ -0,0 +1,491 @@ ++/* ++ * spi-mt7621.c -- MediaTek MT7621 SPI controller driver ++ * ++ * Copyright (C) 2011 Sergiy ++ * Copyright (C) 2011-2013 Gabor Juhos ++ * Copyright (C) 2014-2015 Felix Fietkau ++ * ++ * Some parts are based on spi-orion.c: ++ * Author: Shadi Ammouri ++ * Copyright (C) 2007-2008 Marvell Ltd. ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define SPI_BPW_MASK(bits) BIT((bits) - 1) ++ ++#define DRIVER_NAME "spi-mt7621" ++/* in usec */ ++#define RALINK_SPI_WAIT_MAX_LOOP 2000 ++ ++/* SPISTAT register bit field */ ++#define SPISTAT_BUSY BIT(0) ++ ++#define MT7621_SPI_TRANS 0x00 ++#define SPITRANS_BUSY BIT(16) ++ ++#define MT7621_SPI_OPCODE 0x04 ++#define MT7621_SPI_DATA0 0x08 ++#define MT7621_SPI_DATA4 0x18 ++#define SPI_CTL_TX_RX_CNT_MASK 0xff ++#define SPI_CTL_START BIT(8) ++ ++#define MT7621_SPI_POLAR 0x38 ++#define MT7621_SPI_MASTER 0x28 ++#define MT7621_SPI_MOREBUF 0x2c ++#define MT7621_SPI_SPACE 0x3c ++ ++#define MT7621_CPHA BIT(5) ++#define MT7621_CPOL BIT(4) ++#define MT7621_LSB_FIRST BIT(3) ++ ++#define RT2880_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH) ++ ++struct mt7621_spi; ++ ++struct mt7621_spi { ++ struct spi_master *master; ++ void __iomem *base; ++ unsigned int sys_freq; ++ unsigned int speed; ++ struct clk *clk; ++ spinlock_t lock; ++ ++ struct mt7621_spi_ops *ops; ++}; ++ ++static inline struct mt7621_spi *spidev_to_mt7621_spi(struct spi_device *spi) ++{ ++ return spi_master_get_devdata(spi->master); ++} ++ ++static inline u32 mt7621_spi_read(struct mt7621_spi *rs, u32 reg) ++{ ++ return ioread32(rs->base + reg); ++} ++ ++static inline void mt7621_spi_write(struct mt7621_spi *rs, u32 reg, u32 val) ++{ ++ iowrite32(val, rs->base + reg); ++} ++ ++static void mt7621_spi_reset(struct mt7621_spi *rs, int duplex) ++{ ++ u32 master = mt7621_spi_read(rs, MT7621_SPI_MASTER); ++ ++ master |= 7 << 29; ++ master |= 1 << 2; ++ if (duplex) ++ master |= 1 << 10; ++ else ++ master &= ~(1 << 10); ++ ++ mt7621_spi_write(rs, MT7621_SPI_MASTER, master); ++} ++ ++static void mt7621_spi_set_cs(struct spi_device *spi, int enable) ++{ ++ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); ++ int cs = spi->chip_select; ++ u32 polar = 0; ++ ++ mt7621_spi_reset(rs, cs); ++ if (enable) ++ polar = BIT(cs); ++ mt7621_spi_write(rs, MT7621_SPI_POLAR, polar); ++} ++ ++static int mt7621_spi_prepare(struct spi_device *spi, unsigned int speed) ++{ ++ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); ++ u32 rate; ++ u32 reg; ++ ++ dev_dbg(&spi->dev, "speed:%u\n", speed); ++ ++ rate = DIV_ROUND_UP(rs->sys_freq, speed); ++ dev_dbg(&spi->dev, "rate-1:%u\n", rate); ++ ++ if (rate > 4097) ++ return -EINVAL; ++ ++ if (rate < 2) ++ rate = 2; ++ ++ reg = mt7621_spi_read(rs, MT7621_SPI_MASTER); ++ reg &= ~(0xfff << 16); ++ reg |= (rate - 2) << 16; ++ rs->speed = speed; ++ ++ reg &= ~MT7621_LSB_FIRST; ++ if (spi->mode & SPI_LSB_FIRST) ++ reg |= MT7621_LSB_FIRST; ++ ++ reg &= ~(MT7621_CPHA | MT7621_CPOL); ++ switch(spi->mode & (SPI_CPOL | SPI_CPHA)) { ++ case SPI_MODE_0: ++ break; ++ case SPI_MODE_1: ++ reg |= MT7621_CPHA; ++ break; ++ case SPI_MODE_2: ++ reg |= MT7621_CPOL; ++ break; ++ case SPI_MODE_3: ++ reg |= MT7621_CPOL | MT7621_CPHA; ++ break; ++ } ++ mt7621_spi_write(rs, MT7621_SPI_MASTER, reg); ++ ++ return 0; ++} ++ ++static inline int mt7621_spi_wait_till_ready(struct spi_device *spi) ++{ ++ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); ++ int i; ++ ++ for (i = 0; i < RALINK_SPI_WAIT_MAX_LOOP; i++) { ++ u32 status; ++ ++ status = mt7621_spi_read(rs, MT7621_SPI_TRANS); ++ if ((status & SPITRANS_BUSY) == 0) { ++ return 0; ++ } ++ cpu_relax(); ++ udelay(1); ++ } ++ ++ return -ETIMEDOUT; ++} ++ ++static int mt7621_spi_transfer_half_duplex(struct spi_master *master, ++ struct spi_message *m) ++{ ++ struct mt7621_spi *rs = spi_master_get_devdata(master); ++ struct spi_device *spi = m->spi; ++ unsigned int speed = spi->max_speed_hz; ++ struct spi_transfer *t = NULL; ++ int status = 0; ++ int i, len = 0; ++ int rx_len = 0; ++ u32 data[9] = { 0 }; ++ u32 val; ++ ++ mt7621_spi_wait_till_ready(spi); ++ ++ list_for_each_entry(t, &m->transfers, transfer_list) { ++ const u8 *buf = t->tx_buf; ++ ++ if (t->rx_buf) ++ rx_len += t->len; ++ ++ if (!buf) ++ continue; ++ ++ if (t->speed_hz < speed) ++ speed = t->speed_hz; ++ ++ /* ++ * m25p80 might attempt to write more data than we can handle. ++ * truncate the message to what we can fit into the registers ++ */ ++ if (len + t->len > 36) ++ t->len = 36 - len; ++ ++ for (i = 0; i < t->len; i++, len++) ++ data[len / 4] |= buf[i] << (8 * (len & 3)); ++ } ++ ++ if (WARN_ON(rx_len > 32)) { ++ status = -EIO; ++ goto msg_done; ++ } ++ ++ if (mt7621_spi_prepare(spi, speed)) { ++ status = -EIO; ++ goto msg_done; ++ } ++ data[0] = swab32(data[0]); ++ if (len < 4) ++ data[0] >>= (4 - len) * 8; ++ ++ for (i = 0; i < len; i += 4) ++ mt7621_spi_write(rs, MT7621_SPI_OPCODE + i, data[i / 4]); ++ ++ val = (min_t(int, len, 4) * 8) << 24; ++ if (len > 4) ++ val |= (len - 4) * 8; ++ val |= (rx_len * 8) << 12; ++ mt7621_spi_write(rs, MT7621_SPI_MOREBUF, val); ++ ++ mt7621_spi_set_cs(spi, 1); ++ ++ val = mt7621_spi_read(rs, MT7621_SPI_TRANS); ++ val |= SPI_CTL_START; ++ mt7621_spi_write(rs, MT7621_SPI_TRANS, val); ++ ++ mt7621_spi_wait_till_ready(spi); ++ ++ mt7621_spi_set_cs(spi, 0); ++ ++ for (i = 0; i < rx_len; i += 4) ++ data[i / 4] = mt7621_spi_read(rs, MT7621_SPI_DATA0 + i); ++ ++ m->actual_length = len + rx_len; ++ ++ len = 0; ++ list_for_each_entry(t, &m->transfers, transfer_list) { ++ u8 *buf = t->rx_buf; ++ ++ if (!buf) ++ continue; ++ ++ for (i = 0; i < t->len; i++, len++) ++ buf[i] = data[len / 4] >> (8 * (len & 3)); ++ } ++ ++msg_done: ++ m->status = status; ++ spi_finalize_current_message(master); ++ ++ return 0; ++} ++ ++static int mt7621_spi_transfer_full_duplex(struct spi_master *master, ++ struct spi_message *m) ++{ ++ struct mt7621_spi *rs = spi_master_get_devdata(master); ++ struct spi_device *spi = m->spi; ++ unsigned int speed = spi->max_speed_hz; ++ struct spi_transfer *t = NULL; ++ int status = 0; ++ int i, len = 0; ++ int rx_len = 0; ++ u32 data[9] = { 0 }; ++ u32 val = 0; ++ ++ mt7621_spi_wait_till_ready(spi); ++ ++ list_for_each_entry(t, &m->transfers, transfer_list) { ++ const u8 *buf = t->tx_buf; ++ ++ if (t->rx_buf) ++ rx_len += t->len; ++ ++ if (!buf) ++ continue; ++ ++ if (WARN_ON(len + t->len > 16)) { ++ status = -EIO; ++ goto msg_done; ++ } ++ ++ for (i = 0; i < t->len; i++, len++) ++ data[len / 4] |= buf[i] << (8 * (len & 3)); ++ if (speed > t->speed_hz) ++ speed = t->speed_hz; ++ } ++ ++ if (WARN_ON(rx_len > 16)) { ++ status = -EIO; ++ goto msg_done; ++ } ++ ++ if (mt7621_spi_prepare(spi, speed)) { ++ status = -EIO; ++ goto msg_done; ++ } ++ ++ for (i = 0; i < len; i += 4) ++ mt7621_spi_write(rs, MT7621_SPI_DATA0 + i, data[i / 4]); ++ ++ val |= len * 8; ++ val |= (rx_len * 8) << 12; ++ mt7621_spi_write(rs, MT7621_SPI_MOREBUF, val); ++ ++ mt7621_spi_set_cs(spi, 1); ++ ++ val = mt7621_spi_read(rs, MT7621_SPI_TRANS); ++ val |= SPI_CTL_START; ++ mt7621_spi_write(rs, MT7621_SPI_TRANS, val); ++ ++ mt7621_spi_wait_till_ready(spi); ++ ++ mt7621_spi_set_cs(spi, 0); ++ ++ for (i = 0; i < rx_len; i += 4) ++ data[i / 4] = mt7621_spi_read(rs, MT7621_SPI_DATA4 + i); ++ ++ m->actual_length = rx_len; ++ ++ len = 0; ++ list_for_each_entry(t, &m->transfers, transfer_list) { ++ u8 *buf = t->rx_buf; ++ ++ if (!buf) ++ continue; ++ ++ for (i = 0; i < t->len; i++, len++) ++ buf[i] = data[len / 4] >> (8 * (len & 3)); ++ } ++ ++msg_done: ++ m->status = status; ++ spi_finalize_current_message(master); ++ ++ return 0; ++} ++ ++static int mt7621_spi_transfer_one_message(struct spi_master *master, ++ struct spi_message *m) ++{ ++ struct spi_device *spi = m->spi; ++ int cs = spi->chip_select; ++ ++ if (cs) ++ return mt7621_spi_transfer_full_duplex(master, m); ++ return mt7621_spi_transfer_half_duplex(master, m); ++} ++ ++static int mt7621_spi_setup(struct spi_device *spi) ++{ ++ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); ++ ++ if ((spi->max_speed_hz == 0) || ++ (spi->max_speed_hz > (rs->sys_freq / 2))) ++ spi->max_speed_hz = (rs->sys_freq / 2); ++ ++ if (spi->max_speed_hz < (rs->sys_freq / 4097)) { ++ dev_err(&spi->dev, "setup: requested speed is too low %d Hz\n", ++ spi->max_speed_hz); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id mt7621_spi_match[] = { ++ { .compatible = "ralink,mt7621-spi" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mt7621_spi_match); ++ ++static size_t mt7621_max_transfer_size(struct spi_device *spi) ++{ ++ return 32; ++} ++ ++static int mt7621_spi_probe(struct platform_device *pdev) ++{ ++ const struct of_device_id *match; ++ struct spi_master *master; ++ struct mt7621_spi *rs; ++ unsigned long flags; ++ void __iomem *base; ++ struct resource *r; ++ int status = 0; ++ struct clk *clk; ++ struct mt7621_spi_ops *ops; ++ ++ match = of_match_device(mt7621_spi_match, &pdev->dev); ++ if (!match) ++ return -EINVAL; ++ ops = (struct mt7621_spi_ops *)match->data; ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(&pdev->dev, r); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(clk)) { ++ dev_err(&pdev->dev, "unable to get SYS clock, err=%d\n", ++ status); ++ return PTR_ERR(clk); ++ } ++ ++ status = clk_prepare_enable(clk); ++ if (status) ++ return status; ++ ++ master = spi_alloc_master(&pdev->dev, sizeof(*rs)); ++ if (master == NULL) { ++ dev_info(&pdev->dev, "master allocation failed\n"); ++ return -ENOMEM; ++ } ++ ++ master->mode_bits = RT2880_SPI_MODE_BITS; ++ ++ master->setup = mt7621_spi_setup; ++ master->transfer_one_message = mt7621_spi_transfer_one_message; ++ master->bits_per_word_mask = SPI_BPW_MASK(8); ++ master->dev.of_node = pdev->dev.of_node; ++ master->num_chipselect = 2; ++ master->max_transfer_size = mt7621_max_transfer_size; ++ ++ dev_set_drvdata(&pdev->dev, master); ++ ++ rs = spi_master_get_devdata(master); ++ rs->base = base; ++ rs->clk = clk; ++ rs->master = master; ++ rs->sys_freq = clk_get_rate(rs->clk); ++ rs->ops = ops; ++ dev_info(&pdev->dev, "sys_freq: %u\n", rs->sys_freq); ++ spin_lock_irqsave(&rs->lock, flags); ++ ++ device_reset(&pdev->dev); ++ ++ mt7621_spi_reset(rs, 0); ++ ++ return spi_register_master(master); ++} ++ ++static int mt7621_spi_remove(struct platform_device *pdev) ++{ ++ struct spi_master *master; ++ struct mt7621_spi *rs; ++ ++ master = dev_get_drvdata(&pdev->dev); ++ rs = spi_master_get_devdata(master); ++ ++ clk_disable(rs->clk); ++ spi_unregister_master(master); ++ ++ return 0; ++} ++ ++MODULE_ALIAS("platform:" DRIVER_NAME); ++ ++static struct platform_driver mt7621_spi_driver = { ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = mt7621_spi_match, ++ }, ++ .probe = mt7621_spi_probe, ++ .remove = mt7621_spi_remove, ++}; ++ ++module_platform_driver(mt7621_spi_driver); ++ ++MODULE_DESCRIPTION("MT7621 SPI driver"); ++MODULE_AUTHOR("Felix Fietkau "); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/ramips/patches-4.14/0044-i2c-MIPS-adds-ralink-I2C-driver.patch b/target/linux/ramips/patches-4.14/0044-i2c-MIPS-adds-ralink-I2C-driver.patch new file mode 100644 index 000000000..471c8f40e --- /dev/null +++ b/target/linux/ramips/patches-4.14/0044-i2c-MIPS-adds-ralink-I2C-driver.patch @@ -0,0 +1,507 @@ +From 723b8beaabf3c3c4b1ce69480141f1e926f3f3b2 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 09:52:56 +0100 +Subject: [PATCH 44/53] i2c: MIPS: adds ralink I2C driver + +Signed-off-by: John Crispin +--- + .../devicetree/bindings/i2c/i2c-ralink.txt | 27 ++ + drivers/i2c/busses/Kconfig | 4 + + drivers/i2c/busses/Makefile | 1 + + drivers/i2c/busses/i2c-ralink.c | 327 ++++++++++++++++++++ + 4 files changed, 359 insertions(+) + create mode 100644 Documentation/devicetree/bindings/i2c/i2c-ralink.txt + create mode 100644 drivers/i2c/busses/i2c-ralink.c + +--- /dev/null ++++ b/Documentation/devicetree/bindings/i2c/i2c-ralink.txt +@@ -0,0 +1,27 @@ ++I2C for Ralink platforms ++ ++Required properties : ++- compatible : Must be "link,rt3052-i2c" ++- reg: physical base address of the controller and length of memory mapped ++ region. ++- #address-cells = <1>; ++- #size-cells = <0>; ++ ++Optional properties: ++- Child nodes conforming to i2c bus binding ++ ++Example : ++ ++palmbus@10000000 { ++ i2c@900 { ++ compatible = "link,rt3052-i2c"; ++ reg = <0x900 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hwmon@4b { ++ compatible = "national,lm92"; ++ reg = <0x4b>; ++ }; ++ }; ++}; +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -863,6 +863,11 @@ config I2C_RK3X + This driver can also be built as a module. If so, the module will + be called i2c-rk3x. + ++config I2C_RALINK ++ tristate "Ralink I2C Controller" ++ depends on RALINK && !SOC_MT7621 ++ select OF_I2C ++ + config HAVE_S3C2410_I2C + bool + help +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -84,6 +84,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o + obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o + obj-$(CONFIG_I2C_PXA) += i2c-pxa.o + obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o ++obj-$(CONFIG_I2C_RALINK) += i2c-ralink.o + obj-$(CONFIG_I2C_QUP) += i2c-qup.o + obj-$(CONFIG_I2C_RIIC) += i2c-riic.o + obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o +--- /dev/null ++++ b/drivers/i2c/busses/i2c-ralink.c +@@ -0,0 +1,435 @@ ++/* ++ * drivers/i2c/busses/i2c-ralink.c ++ * ++ * Copyright (C) 2013 Steven Liu ++ * Copyright (C) 2016 Michael Lee ++ * ++ * Improve driver for i2cdetect from i2c-tools to detect i2c devices on the bus. ++ * (C) 2014 Sittisak ++ * ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define REG_CONFIG_REG 0x00 ++#define REG_CLKDIV_REG 0x04 ++#define REG_DEVADDR_REG 0x08 ++#define REG_ADDR_REG 0x0C ++#define REG_DATAOUT_REG 0x10 ++#define REG_DATAIN_REG 0x14 ++#define REG_STATUS_REG 0x18 ++#define REG_STARTXFR_REG 0x1C ++#define REG_BYTECNT_REG 0x20 ++ ++/* REG_CONFIG_REG */ ++#define I2C_ADDRLEN_OFFSET 5 ++#define I2C_DEVADLEN_OFFSET 2 ++#define I2C_ADDRLEN_MASK 0x3 ++#define I2C_ADDR_DIS BIT(1) ++#define I2C_DEVADDR_DIS BIT(0) ++#define I2C_ADDRLEN_8 (7 << I2C_ADDRLEN_OFFSET) ++#define I2C_DEVADLEN_7 (6 << I2C_DEVADLEN_OFFSET) ++#define I2C_CONF_DEFAULT (I2C_ADDRLEN_8 | I2C_DEVADLEN_7) ++ ++/* REG_CLKDIV_REG */ ++#define I2C_CLKDIV_MASK 0xffff ++ ++/* REG_DEVADDR_REG */ ++#define I2C_DEVADDR_MASK 0x7f ++ ++/* REG_ADDR_REG */ ++#define I2C_ADDR_MASK 0xff ++ ++/* REG_STATUS_REG */ ++#define I2C_STARTERR BIT(4) ++#define I2C_ACKERR BIT(3) ++#define I2C_DATARDY BIT(2) ++#define I2C_SDOEMPTY BIT(1) ++#define I2C_BUSY BIT(0) ++ ++/* REG_STARTXFR_REG */ ++#define NOSTOP_CMD BIT(2) ++#define NODATA_CMD BIT(1) ++#define READ_CMD BIT(0) ++ ++/* REG_BYTECNT_REG */ ++#define BYTECNT_MAX 64 ++#define SET_BYTECNT(x) (x - 1) ++ ++/* timeout waiting for I2C devices to respond (clock streching) */ ++#define TIMEOUT_MS 1000 ++#define DELAY_INTERVAL_US 100 ++ ++struct rt_i2c { ++ void __iomem *base; ++ struct clk *clk; ++ struct device *dev; ++ struct i2c_adapter adap; ++ u32 cur_clk; ++ u32 clk_div; ++ u32 flags; ++}; ++ ++static void rt_i2c_w32(struct rt_i2c *i2c, u32 val, unsigned reg) ++{ ++ iowrite32(val, i2c->base + reg); ++} ++ ++static u32 rt_i2c_r32(struct rt_i2c *i2c, unsigned reg) ++{ ++ return ioread32(i2c->base + reg); ++} ++ ++static int poll_down_timeout(void __iomem *addr, u32 mask) ++{ ++ unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); ++ ++ do { ++ if (!(readl_relaxed(addr) & mask)) ++ return 0; ++ ++ usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); ++ } while (time_before(jiffies, timeout)); ++ ++ return (readl_relaxed(addr) & mask) ? -EAGAIN : 0; ++} ++ ++static int rt_i2c_wait_idle(struct rt_i2c *i2c) ++{ ++ int ret; ++ ++ ret = poll_down_timeout(i2c->base + REG_STATUS_REG, I2C_BUSY); ++ if (ret < 0) ++ dev_dbg(i2c->dev, "idle err(%d)\n", ret); ++ ++ return ret; ++} ++ ++static int poll_up_timeout(void __iomem *addr, u32 mask) ++{ ++ unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); ++ u32 status; ++ ++ do { ++ status = readl_relaxed(addr); ++ ++ /* check error status */ ++ if (status & I2C_STARTERR) ++ return -EAGAIN; ++ else if (status & I2C_ACKERR) ++ return -ENXIO; ++ else if (status & mask) ++ return 0; ++ ++ usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); ++ } while (time_before(jiffies, timeout)); ++ ++ return -ETIMEDOUT; ++} ++ ++static int rt_i2c_wait_rx_done(struct rt_i2c *i2c) ++{ ++ int ret; ++ ++ ret = poll_up_timeout(i2c->base + REG_STATUS_REG, I2C_DATARDY); ++ if (ret < 0) ++ dev_dbg(i2c->dev, "rx err(%d)\n", ret); ++ ++ return ret; ++} ++ ++static int rt_i2c_wait_tx_done(struct rt_i2c *i2c) ++{ ++ int ret; ++ ++ ret = poll_up_timeout(i2c->base + REG_STATUS_REG, I2C_SDOEMPTY); ++ if (ret < 0) ++ dev_dbg(i2c->dev, "tx err(%d)\n", ret); ++ ++ return ret; ++} ++ ++static void rt_i2c_reset(struct rt_i2c *i2c) ++{ ++ device_reset(i2c->adap.dev.parent); ++ barrier(); ++ rt_i2c_w32(i2c, i2c->clk_div, REG_CLKDIV_REG); ++} ++ ++static void rt_i2c_dump_reg(struct rt_i2c *i2c) ++{ ++ dev_dbg(i2c->dev, "conf %08x, clkdiv %08x, devaddr %08x, " \ ++ "addr %08x, dataout %08x, datain %08x, " \ ++ "status %08x, startxfr %08x, bytecnt %08x\n", ++ rt_i2c_r32(i2c, REG_CONFIG_REG), ++ rt_i2c_r32(i2c, REG_CLKDIV_REG), ++ rt_i2c_r32(i2c, REG_DEVADDR_REG), ++ rt_i2c_r32(i2c, REG_ADDR_REG), ++ rt_i2c_r32(i2c, REG_DATAOUT_REG), ++ rt_i2c_r32(i2c, REG_DATAIN_REG), ++ rt_i2c_r32(i2c, REG_STATUS_REG), ++ rt_i2c_r32(i2c, REG_STARTXFR_REG), ++ rt_i2c_r32(i2c, REG_BYTECNT_REG)); ++} ++ ++static int rt_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ++ int num) ++{ ++ struct rt_i2c *i2c; ++ struct i2c_msg *pmsg; ++ unsigned char addr; ++ int i, j, ret; ++ u32 cmd; ++ ++ i2c = i2c_get_adapdata(adap); ++ ++ for (i = 0; i < num; i++) { ++ pmsg = &msgs[i]; ++ if (i == (num - 1)) ++ cmd = 0; ++ else ++ cmd = NOSTOP_CMD; ++ ++ dev_dbg(i2c->dev, "addr: 0x%x, len: %d, flags: 0x%x, stop: %d\n", ++ pmsg->addr, pmsg->len, pmsg->flags, ++ (cmd == 0)? 1 : 0); ++ ++ /* wait hardware idle */ ++ if ((ret = rt_i2c_wait_idle(i2c))) ++ goto err_timeout; ++ ++ if (pmsg->flags & I2C_M_TEN) { ++ rt_i2c_w32(i2c, I2C_CONF_DEFAULT, REG_CONFIG_REG); ++ /* 10 bits address */ ++ addr = 0x78 | ((pmsg->addr >> 8) & 0x03); ++ rt_i2c_w32(i2c, addr & I2C_DEVADDR_MASK, ++ REG_DEVADDR_REG); ++ rt_i2c_w32(i2c, pmsg->addr & I2C_ADDR_MASK, ++ REG_ADDR_REG); ++ } else { ++ rt_i2c_w32(i2c, I2C_CONF_DEFAULT | I2C_ADDR_DIS, ++ REG_CONFIG_REG); ++ /* 7 bits address */ ++ rt_i2c_w32(i2c, pmsg->addr & I2C_DEVADDR_MASK, ++ REG_DEVADDR_REG); ++ } ++ ++ /* buffer length */ ++ if (pmsg->len == 0) ++ cmd |= NODATA_CMD; ++ else ++ rt_i2c_w32(i2c, SET_BYTECNT(pmsg->len), ++ REG_BYTECNT_REG); ++ ++ j = 0; ++ if (pmsg->flags & I2C_M_RD) { ++ cmd |= READ_CMD; ++ /* start transfer */ ++ barrier(); ++ rt_i2c_w32(i2c, cmd, REG_STARTXFR_REG); ++ do { ++ /* wait */ ++ if ((ret = rt_i2c_wait_rx_done(i2c))) ++ goto err_timeout; ++ /* read data */ ++ if (pmsg->len) ++ pmsg->buf[j] = rt_i2c_r32(i2c, ++ REG_DATAIN_REG); ++ j++; ++ } while (j < pmsg->len); ++ } else { ++ do { ++ /* write data */ ++ if (pmsg->len) ++ rt_i2c_w32(i2c, pmsg->buf[j], ++ REG_DATAOUT_REG); ++ /* start transfer */ ++ if (j == 0) { ++ barrier(); ++ rt_i2c_w32(i2c, cmd, REG_STARTXFR_REG); ++ } ++ /* wait */ ++ if ((ret = rt_i2c_wait_tx_done(i2c))) ++ goto err_timeout; ++ j++; ++ } while (j < pmsg->len); ++ } ++ } ++ /* the return value is number of executed messages */ ++ ret = i; ++ ++ return ret; ++ ++err_timeout: ++ rt_i2c_dump_reg(i2c); ++ rt_i2c_reset(i2c); ++ return ret; ++} ++ ++static u32 rt_i2c_func(struct i2c_adapter *a) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; ++} ++ ++static const struct i2c_algorithm rt_i2c_algo = { ++ .master_xfer = rt_i2c_master_xfer, ++ .functionality = rt_i2c_func, ++}; ++ ++static const struct of_device_id i2c_rt_dt_ids[] = { ++ { .compatible = "ralink,rt2880-i2c" }, ++ { /* sentinel */ } ++}; ++ ++MODULE_DEVICE_TABLE(of, i2c_rt_dt_ids); ++ ++static struct i2c_adapter_quirks rt_i2c_quirks = { ++ .max_write_len = BYTECNT_MAX, ++ .max_read_len = BYTECNT_MAX, ++}; ++ ++static int rt_i2c_init(struct rt_i2c *i2c) ++{ ++ u32 reg; ++ ++ /* i2c_sclk = periph_clk / ((2 * clk_div) + 5) */ ++ i2c->clk_div = (clk_get_rate(i2c->clk) - (5 * i2c->cur_clk)) / ++ (2 * i2c->cur_clk); ++ if (i2c->clk_div < 8) ++ i2c->clk_div = 8; ++ if (i2c->clk_div > I2C_CLKDIV_MASK) ++ i2c->clk_div = I2C_CLKDIV_MASK; ++ ++ /* check support combinde/repeated start message */ ++ rt_i2c_w32(i2c, NOSTOP_CMD, REG_STARTXFR_REG); ++ reg = rt_i2c_r32(i2c, REG_STARTXFR_REG) & NOSTOP_CMD; ++ ++ rt_i2c_reset(i2c); ++ ++ return reg; ++} ++ ++static int rt_i2c_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ struct rt_i2c *i2c; ++ struct i2c_adapter *adap; ++ const struct of_device_id *match; ++ int ret, restart; ++ ++ match = of_match_device(i2c_rt_dt_ids, &pdev->dev); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "no memory resource found\n"); ++ return -ENODEV; ++ } ++ ++ i2c = devm_kzalloc(&pdev->dev, sizeof(struct rt_i2c), GFP_KERNEL); ++ if (!i2c) { ++ dev_err(&pdev->dev, "failed to allocate i2c_adapter\n"); ++ return -ENOMEM; ++ } ++ ++ i2c->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(i2c->base)) ++ return PTR_ERR(i2c->base); ++ ++ i2c->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(i2c->clk)) { ++ dev_err(&pdev->dev, "no clock defined\n"); ++ return -ENODEV; ++ } ++ clk_prepare_enable(i2c->clk); ++ i2c->dev = &pdev->dev; ++ ++ if (of_property_read_u32(pdev->dev.of_node, ++ "clock-frequency", &i2c->cur_clk)) ++ i2c->cur_clk = 100000; ++ ++ adap = &i2c->adap; ++ adap->owner = THIS_MODULE; ++ adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; ++ adap->algo = &rt_i2c_algo; ++ adap->retries = 3; ++ adap->dev.parent = &pdev->dev; ++ i2c_set_adapdata(adap, i2c); ++ adap->dev.of_node = pdev->dev.of_node; ++ strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); ++ adap->quirks = &rt_i2c_quirks; ++ ++ platform_set_drvdata(pdev, i2c); ++ ++ restart = rt_i2c_init(i2c); ++ ++ ret = i2c_add_adapter(adap); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "failed to add adapter\n"); ++ clk_disable_unprepare(i2c->clk); ++ return ret; ++ } ++ ++ dev_info(&pdev->dev, "clock %uKHz, re-start %ssupport\n", ++ i2c->cur_clk/1000, restart ? "" : "not "); ++ ++ return ret; ++} ++ ++static int rt_i2c_remove(struct platform_device *pdev) ++{ ++ struct rt_i2c *i2c = platform_get_drvdata(pdev); ++ ++ i2c_del_adapter(&i2c->adap); ++ clk_disable_unprepare(i2c->clk); ++ ++ return 0; ++} ++ ++static struct platform_driver rt_i2c_driver = { ++ .probe = rt_i2c_probe, ++ .remove = rt_i2c_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "i2c-ralink", ++ .of_match_table = i2c_rt_dt_ids, ++ }, ++}; ++ ++static int __init i2c_rt_init (void) ++{ ++ return platform_driver_register(&rt_i2c_driver); ++} ++subsys_initcall(i2c_rt_init); ++ ++static void __exit i2c_rt_exit (void) ++{ ++ platform_driver_unregister(&rt_i2c_driver); ++} ++module_exit(i2c_rt_exit); ++ ++MODULE_AUTHOR("Steven Liu "); ++MODULE_DESCRIPTION("Ralink I2c host driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:Ralink-I2C"); diff --git a/target/linux/ramips/patches-4.14/0045-i2c-add-mt7621-driver.patch b/target/linux/ramips/patches-4.14/0045-i2c-add-mt7621-driver.patch new file mode 100644 index 000000000..9cd8c4b5c --- /dev/null +++ b/target/linux/ramips/patches-4.14/0045-i2c-add-mt7621-driver.patch @@ -0,0 +1,473 @@ +From d5c54ff3d1db0a4348fa04d8e78f3bf6063e3afc Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 7 Dec 2015 17:21:27 +0100 +Subject: [PATCH 45/53] i2c: add mt7621 driver + +Signed-off-by: John Crispin +--- + drivers/i2c/busses/Kconfig | 4 + + drivers/i2c/busses/Makefile | 1 + + drivers/i2c/busses/i2c-mt7621.c | 303 +++++++++++++++++++++++++++++++++++++++ + 3 files changed, 308 insertions(+) + create mode 100644 drivers/i2c/busses/i2c-mt7621.c + +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -868,6 +868,11 @@ config I2C_RALINK + depends on RALINK && !SOC_MT7621 + select OF_I2C + ++config I2C_MT7621 ++ tristate "MT7621/MT7628 I2C Controller" ++ depends on RALINK && (SOC_MT7620 || SOC_MT7621) ++ select OF_I2C ++ + config HAVE_S3C2410_I2C + bool + help +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -85,6 +85,7 @@ obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o + obj-$(CONFIG_I2C_PXA) += i2c-pxa.o + obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o + obj-$(CONFIG_I2C_RALINK) += i2c-ralink.o ++obj-$(CONFIG_I2C_MT7621) += i2c-mt7621.o + obj-$(CONFIG_I2C_QUP) += i2c-qup.o + obj-$(CONFIG_I2C_RIIC) += i2c-riic.o + obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o +--- /dev/null ++++ b/drivers/i2c/busses/i2c-mt7621.c +@@ -0,0 +1,433 @@ ++/* ++ * drivers/i2c/busses/i2c-mt7621.c ++ * ++ * Copyright (C) 2013 Steven Liu ++ * Copyright (C) 2016 Michael Lee ++ * ++ * Improve driver for i2cdetect from i2c-tools to detect i2c devices on the bus. ++ * (C) 2014 Sittisak ++ * ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define REG_SM0CFG0 0x08 ++#define REG_SM0DOUT 0x10 ++#define REG_SM0DIN 0x14 ++#define REG_SM0ST 0x18 ++#define REG_SM0AUTO 0x1C ++#define REG_SM0CFG1 0x20 ++#define REG_SM0CFG2 0x28 ++#define REG_SM0CTL0 0x40 ++#define REG_SM0CTL1 0x44 ++#define REG_SM0D0 0x50 ++#define REG_SM0D1 0x54 ++#define REG_PINTEN 0x5C ++#define REG_PINTST 0x60 ++#define REG_PINTCL 0x64 ++ ++/* REG_SM0CFG0 */ ++#define I2C_DEVADDR_MASK 0x7f ++ ++/* REG_SM0ST */ ++#define I2C_DATARDY BIT(2) ++#define I2C_SDOEMPTY BIT(1) ++#define I2C_BUSY BIT(0) ++ ++/* REG_SM0AUTO */ ++#define READ_CMD BIT(0) ++ ++/* REG_SM0CFG1 */ ++#define BYTECNT_MAX 64 ++#define SET_BYTECNT(x) (x - 1) ++ ++/* REG_SM0CFG2 */ ++#define AUTOMODE_EN BIT(0) ++ ++/* REG_SM0CTL0 */ ++#define ODRAIN_HIGH_SM0 BIT(31) ++#define VSYNC_SHIFT 28 ++#define VSYNC_MASK 0x3 ++#define VSYNC_PULSE (0x1 << VSYNC_SHIFT) ++#define VSYNC_RISING (0x2 << VSYNC_SHIFT) ++#define CLK_DIV_SHIFT 16 ++#define CLK_DIV_MASK 0xfff ++#define DEG_CNT_SHIFT 8 ++#define DEG_CNT_MASK 0xff ++#define WAIT_HIGH BIT(6) ++#define DEG_EN BIT(5) ++#define CS_STATUA BIT(4) ++#define SCL_STATUS BIT(3) ++#define SDA_STATUS BIT(2) ++#define SM0_EN BIT(1) ++#define SCL_STRECH BIT(0) ++ ++/* REG_SM0CTL1 */ ++#define ACK_SHIFT 16 ++#define ACK_MASK 0xff ++#define PGLEN_SHIFT 8 ++#define PGLEN_MASK 0x7 ++#define SM0_MODE_SHIFT 4 ++#define SM0_MODE_MASK 0x7 ++#define SM0_MODE_START 0x1 ++#define SM0_MODE_WRITE 0x2 ++#define SM0_MODE_STOP 0x3 ++#define SM0_MODE_READ_NACK 0x4 ++#define SM0_MODE_READ_ACK 0x5 ++#define SM0_TRI_BUSY BIT(0) ++ ++/* timeout waiting for I2C devices to respond (clock streching) */ ++#define TIMEOUT_MS 1000 ++#define DELAY_INTERVAL_US 100 ++ ++struct mtk_i2c { ++ void __iomem *base; ++ struct clk *clk; ++ struct device *dev; ++ struct i2c_adapter adap; ++ u32 cur_clk; ++ u32 clk_div; ++ u32 flags; ++}; ++ ++static void mtk_i2c_w32(struct mtk_i2c *i2c, u32 val, unsigned reg) ++{ ++ iowrite32(val, i2c->base + reg); ++} ++ ++static u32 mtk_i2c_r32(struct mtk_i2c *i2c, unsigned reg) ++{ ++ return ioread32(i2c->base + reg); ++} ++ ++static int poll_down_timeout(void __iomem *addr, u32 mask) ++{ ++ unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); ++ ++ do { ++ if (!(readl_relaxed(addr) & mask)) ++ return 0; ++ ++ usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); ++ } while (time_before(jiffies, timeout)); ++ ++ return (readl_relaxed(addr) & mask) ? -EAGAIN : 0; ++} ++ ++static int mtk_i2c_wait_idle(struct mtk_i2c *i2c) ++{ ++ int ret; ++ ++ ret = poll_down_timeout(i2c->base + REG_SM0ST, I2C_BUSY); ++ if (ret < 0) ++ dev_dbg(i2c->dev, "idle err(%d)\n", ret); ++ ++ return ret; ++} ++ ++static int poll_up_timeout(void __iomem *addr, u32 mask) ++{ ++ unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); ++ u32 status; ++ ++ do { ++ status = readl_relaxed(addr); ++ if (status & mask) ++ return 0; ++ usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); ++ } while (time_before(jiffies, timeout)); ++ ++ return -ETIMEDOUT; ++} ++ ++static int mtk_i2c_wait_rx_done(struct mtk_i2c *i2c) ++{ ++ int ret; ++ ++ ret = poll_up_timeout(i2c->base + REG_SM0ST, I2C_DATARDY); ++ if (ret < 0) ++ dev_dbg(i2c->dev, "rx err(%d)\n", ret); ++ ++ return ret; ++} ++ ++static int mtk_i2c_wait_tx_done(struct mtk_i2c *i2c) ++{ ++ int ret; ++ ++ ret = poll_up_timeout(i2c->base + REG_SM0ST, I2C_SDOEMPTY); ++ if (ret < 0) ++ dev_dbg(i2c->dev, "tx err(%d)\n", ret); ++ ++ return ret; ++} ++ ++static void mtk_i2c_reset(struct mtk_i2c *i2c) ++{ ++ u32 reg; ++ device_reset(i2c->adap.dev.parent); ++ barrier(); ++ ++ /* ctrl0 */ ++ reg = ODRAIN_HIGH_SM0 | VSYNC_PULSE | (i2c->clk_div << CLK_DIV_SHIFT) | ++ WAIT_HIGH | SM0_EN; ++ mtk_i2c_w32(i2c, reg, REG_SM0CTL0); ++ ++ /* auto mode */ ++ mtk_i2c_w32(i2c, AUTOMODE_EN, REG_SM0CFG2); ++} ++ ++static void mtk_i2c_dump_reg(struct mtk_i2c *i2c) ++{ ++ dev_dbg(i2c->dev, "cfg0 %08x, dout %08x, din %08x, " \ ++ "status %08x, auto %08x, cfg1 %08x, " \ ++ "cfg2 %08x, ctl0 %08x, ctl1 %08x\n", ++ mtk_i2c_r32(i2c, REG_SM0CFG0), ++ mtk_i2c_r32(i2c, REG_SM0DOUT), ++ mtk_i2c_r32(i2c, REG_SM0DIN), ++ mtk_i2c_r32(i2c, REG_SM0ST), ++ mtk_i2c_r32(i2c, REG_SM0AUTO), ++ mtk_i2c_r32(i2c, REG_SM0CFG1), ++ mtk_i2c_r32(i2c, REG_SM0CFG2), ++ mtk_i2c_r32(i2c, REG_SM0CTL0), ++ mtk_i2c_r32(i2c, REG_SM0CTL1)); ++} ++ ++static int mtk_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ++ int num) ++{ ++ struct mtk_i2c *i2c; ++ struct i2c_msg *pmsg; ++ int i, j, ret; ++ u32 cmd; ++ ++ i2c = i2c_get_adapdata(adap); ++ ++ for (i = 0; i < num; i++) { ++ pmsg = &msgs[i]; ++ cmd = 0; ++ ++ dev_dbg(i2c->dev, "addr: 0x%x, len: %d, flags: 0x%x\n", ++ pmsg->addr, pmsg->len, pmsg->flags); ++ ++ /* wait hardware idle */ ++ if ((ret = mtk_i2c_wait_idle(i2c))) ++ goto err_timeout; ++ ++ if (pmsg->flags & I2C_M_TEN) { ++ dev_dbg(i2c->dev, "10 bits addr not supported\n"); ++ return -EINVAL; ++ } else { ++ /* 7 bits address */ ++ mtk_i2c_w32(i2c, pmsg->addr & I2C_DEVADDR_MASK, ++ REG_SM0CFG0); ++ } ++ ++ /* buffer length */ ++ if (pmsg->len == 0) { ++ dev_dbg(i2c->dev, "length is 0\n"); ++ return -EINVAL; ++ } else ++ mtk_i2c_w32(i2c, SET_BYTECNT(pmsg->len), ++ REG_SM0CFG1); ++ ++ j = 0; ++ if (pmsg->flags & I2C_M_RD) { ++ cmd |= READ_CMD; ++ /* start transfer */ ++ barrier(); ++ mtk_i2c_w32(i2c, cmd, REG_SM0AUTO); ++ do { ++ /* wait */ ++ if ((ret = mtk_i2c_wait_rx_done(i2c))) ++ goto err_timeout; ++ /* read data */ ++ if (pmsg->len) ++ pmsg->buf[j] = mtk_i2c_r32(i2c, ++ REG_SM0DIN); ++ j++; ++ } while (j < pmsg->len); ++ } else { ++ do { ++ /* write data */ ++ if (pmsg->len) ++ mtk_i2c_w32(i2c, pmsg->buf[j], ++ REG_SM0DOUT); ++ /* start transfer */ ++ if (j == 0) { ++ barrier(); ++ mtk_i2c_w32(i2c, cmd, REG_SM0AUTO); ++ } ++ /* wait */ ++ if ((ret = mtk_i2c_wait_tx_done(i2c))) ++ goto err_timeout; ++ j++; ++ } while (j < pmsg->len); ++ } ++ } ++ /* the return value is number of executed messages */ ++ ret = i; ++ ++ return ret; ++ ++err_timeout: ++ mtk_i2c_dump_reg(i2c); ++ mtk_i2c_reset(i2c); ++ return ret; ++} ++ ++static u32 mtk_i2c_func(struct i2c_adapter *a) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; ++} ++ ++static const struct i2c_algorithm mtk_i2c_algo = { ++ .master_xfer = mtk_i2c_master_xfer, ++ .functionality = mtk_i2c_func, ++}; ++ ++static const struct of_device_id i2c_mtk_dt_ids[] = { ++ { .compatible = "mediatek,mt7621-i2c" }, ++ { /* sentinel */ } ++}; ++ ++MODULE_DEVICE_TABLE(of, i2c_mtk_dt_ids); ++ ++static struct i2c_adapter_quirks mtk_i2c_quirks = { ++ .max_write_len = BYTECNT_MAX, ++ .max_read_len = BYTECNT_MAX, ++}; ++ ++static void mtk_i2c_init(struct mtk_i2c *i2c) ++{ ++ i2c->clk_div = clk_get_rate(i2c->clk) / i2c->cur_clk; ++ if (i2c->clk_div > CLK_DIV_MASK) ++ i2c->clk_div = CLK_DIV_MASK; ++ ++ mtk_i2c_reset(i2c); ++} ++ ++static int mtk_i2c_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ struct mtk_i2c *i2c; ++ struct i2c_adapter *adap; ++ const struct of_device_id *match; ++ int ret; ++ ++ match = of_match_device(i2c_mtk_dt_ids, &pdev->dev); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "no memory resource found\n"); ++ return -ENODEV; ++ } ++ ++ i2c = devm_kzalloc(&pdev->dev, sizeof(struct mtk_i2c), GFP_KERNEL); ++ if (!i2c) { ++ dev_err(&pdev->dev, "failed to allocate i2c_adapter\n"); ++ return -ENOMEM; ++ } ++ ++ i2c->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(i2c->base)) ++ return PTR_ERR(i2c->base); ++ ++ i2c->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(i2c->clk)) { ++ dev_err(&pdev->dev, "no clock defined\n"); ++ return -ENODEV; ++ } ++ clk_prepare_enable(i2c->clk); ++ i2c->dev = &pdev->dev; ++ ++ if (of_property_read_u32(pdev->dev.of_node, ++ "clock-frequency", &i2c->cur_clk)) ++ i2c->cur_clk = 100000; ++ ++ adap = &i2c->adap; ++ adap->owner = THIS_MODULE; ++ adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; ++ adap->algo = &mtk_i2c_algo; ++ adap->retries = 3; ++ adap->dev.parent = &pdev->dev; ++ i2c_set_adapdata(adap, i2c); ++ adap->dev.of_node = pdev->dev.of_node; ++ strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); ++ adap->quirks = &mtk_i2c_quirks; ++ ++ platform_set_drvdata(pdev, i2c); ++ ++ mtk_i2c_init(i2c); ++ ++ ret = i2c_add_adapter(adap); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "failed to add adapter\n"); ++ clk_disable_unprepare(i2c->clk); ++ return ret; ++ } ++ ++ dev_info(&pdev->dev, "clock %uKHz, re-start not support\n", ++ i2c->cur_clk/1000); ++ ++ return ret; ++} ++ ++static int mtk_i2c_remove(struct platform_device *pdev) ++{ ++ struct mtk_i2c *i2c = platform_get_drvdata(pdev); ++ ++ i2c_del_adapter(&i2c->adap); ++ clk_disable_unprepare(i2c->clk); ++ ++ return 0; ++} ++ ++static struct platform_driver mtk_i2c_driver = { ++ .probe = mtk_i2c_probe, ++ .remove = mtk_i2c_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "i2c-mt7621", ++ .of_match_table = i2c_mtk_dt_ids, ++ }, ++}; ++ ++static int __init i2c_mtk_init (void) ++{ ++ return platform_driver_register(&mtk_i2c_driver); ++} ++subsys_initcall(i2c_mtk_init); ++ ++static void __exit i2c_mtk_exit (void) ++{ ++ platform_driver_unregister(&mtk_i2c_driver); ++} ++module_exit(i2c_mtk_exit); ++ ++MODULE_AUTHOR("Steven Liu "); ++MODULE_DESCRIPTION("MT7621 I2c host driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:MT7621-I2C"); diff --git a/target/linux/ramips/patches-4.14/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch b/target/linux/ramips/patches-4.14/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch new file mode 100644 index 000000000..353b6836a --- /dev/null +++ b/target/linux/ramips/patches-4.14/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch @@ -0,0 +1,43 @@ +From 23147af14531cbdada194b94120ef8774f46292d Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 13 Nov 2014 19:08:40 +0100 +Subject: [PATCH 46/53] mmc: MIPS: ralink: add sdhci for mt7620a SoC + +Signed-off-by: John Crispin +--- + drivers/mmc/host/Kconfig | 2 + + drivers/mmc/host/Makefile | 1 + + drivers/mmc/host/mtk-mmc/Kconfig | 16 + + drivers/mmc/host/mtk-mmc/Makefile | 42 + + drivers/mmc/host/mtk-mmc/board.h | 137 ++ + drivers/mmc/host/mtk-mmc/dbg.c | 347 ++++ + drivers/mmc/host/mtk-mmc/dbg.h | 156 ++ + drivers/mmc/host/mtk-mmc/mt6575_sd.h | 1001 +++++++++++ + drivers/mmc/host/mtk-mmc/sd.c | 3060 ++++++++++++++++++++++++++++++++++ + 9 files changed, 4762 insertions(+) + create mode 100644 drivers/mmc/host/mtk-mmc/Kconfig + create mode 100644 drivers/mmc/host/mtk-mmc/Makefile + create mode 100644 drivers/mmc/host/mtk-mmc/board.h + create mode 100644 drivers/mmc/host/mtk-mmc/dbg.c + create mode 100644 drivers/mmc/host/mtk-mmc/dbg.h + create mode 100644 drivers/mmc/host/mtk-mmc/mt6575_sd.h + create mode 100644 drivers/mmc/host/mtk-mmc/sd.c + +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -899,3 +899,5 @@ config MMC_SDHCI_XENON + This selects Marvell Xenon eMMC/SD/SDIO SDHCI. + If you have a controller with this interface, say Y or M here. + If unsure, say N. ++ ++source "drivers/mmc/host/mtk-mmc/Kconfig" +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -3,6 +3,7 @@ + # Makefile for MMC/SD host controller drivers + # + ++obj-$(CONFIG_MTK_MMC) += mtk-mmc/ + obj-$(CONFIG_MMC_ARMMMCI) += armmmci.o + armmmci-y := mmci.o + armmmci-$(CONFIG_MMC_QCOM_DML) += mmci_qcom_dml.o diff --git a/target/linux/ramips/patches-4.14/0047-DMA-ralink-add-rt2880-dma-engine.patch b/target/linux/ramips/patches-4.14/0047-DMA-ralink-add-rt2880-dma-engine.patch new file mode 100644 index 000000000..b74a48a22 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0047-DMA-ralink-add-rt2880-dma-engine.patch @@ -0,0 +1,1757 @@ +From f1c4d9e622c800e1f38b3818f933ec7597d1ccfb Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 09:29:51 +0100 +Subject: [PATCH 47/53] DMA: ralink: add rt2880 dma engine + +Signed-off-by: John Crispin +--- + drivers/dma/Kconfig | 6 + + drivers/dma/Makefile | 1 + + drivers/dma/ralink-gdma.c | 577 +++++++++++++++++++++++++++++++++++++++++++++ + include/linux/dmaengine.h | 1 + + 4 files changed, 585 insertions(+) + create mode 100644 drivers/dma/ralink-gdma.c + +--- a/drivers/dma/Kconfig ++++ b/drivers/dma/Kconfig +@@ -40,6 +40,18 @@ config ASYNC_TX_ENABLE_CHANNEL_SWITCH + config ARCH_HAS_ASYNC_TX_FIND_CHANNEL + bool + ++config DMA_RALINK ++ tristate "RALINK DMA support" ++ depends on RALINK && !SOC_RT288X ++ select DMA_ENGINE ++ select DMA_VIRTUAL_CHANNELS ++ ++config MTK_HSDMA ++ tristate "MTK HSDMA support" ++ depends on RALINK && SOC_MT7621 ++ select DMA_ENGINE ++ select DMA_VIRTUAL_CHANNELS ++ + config DMA_ENGINE + bool + +--- a/drivers/dma/Makefile ++++ b/drivers/dma/Makefile +@@ -71,6 +71,8 @@ obj-$(CONFIG_TI_EDMA) += edma.o + obj-$(CONFIG_XGENE_DMA) += xgene-dma.o + obj-$(CONFIG_ZX_DMA) += zx_dma.o + obj-$(CONFIG_ST_FDMA) += st_fdma.o ++obj-$(CONFIG_DMA_RALINK) += ralink-gdma.o ++obj-$(CONFIG_MTK_HSDMA) += mtk-hsdma.o + + obj-y += qcom/ + obj-y += xilinx/ +--- /dev/null ++++ b/drivers/dma/ralink-gdma.c +@@ -0,0 +1,928 @@ ++/* ++ * Copyright (C) 2013, Lars-Peter Clausen ++ * GDMA4740 DMAC support ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "virt-dma.h" ++ ++#define GDMA_REG_SRC_ADDR(x) (0x00 + (x) * 0x10) ++#define GDMA_REG_DST_ADDR(x) (0x04 + (x) * 0x10) ++ ++#define GDMA_REG_CTRL0(x) (0x08 + (x) * 0x10) ++#define GDMA_REG_CTRL0_TX_MASK 0xffff ++#define GDMA_REG_CTRL0_TX_SHIFT 16 ++#define GDMA_REG_CTRL0_CURR_MASK 0xff ++#define GDMA_REG_CTRL0_CURR_SHIFT 8 ++#define GDMA_REG_CTRL0_SRC_ADDR_FIXED BIT(7) ++#define GDMA_REG_CTRL0_DST_ADDR_FIXED BIT(6) ++#define GDMA_REG_CTRL0_BURST_MASK 0x7 ++#define GDMA_REG_CTRL0_BURST_SHIFT 3 ++#define GDMA_REG_CTRL0_DONE_INT BIT(2) ++#define GDMA_REG_CTRL0_ENABLE BIT(1) ++#define GDMA_REG_CTRL0_SW_MODE BIT(0) ++ ++#define GDMA_REG_CTRL1(x) (0x0c + (x) * 0x10) ++#define GDMA_REG_CTRL1_SEG_MASK 0xf ++#define GDMA_REG_CTRL1_SEG_SHIFT 22 ++#define GDMA_REG_CTRL1_REQ_MASK 0x3f ++#define GDMA_REG_CTRL1_SRC_REQ_SHIFT 16 ++#define GDMA_REG_CTRL1_DST_REQ_SHIFT 8 ++#define GDMA_REG_CTRL1_CONTINOUS BIT(14) ++#define GDMA_REG_CTRL1_NEXT_MASK 0x1f ++#define GDMA_REG_CTRL1_NEXT_SHIFT 3 ++#define GDMA_REG_CTRL1_COHERENT BIT(2) ++#define GDMA_REG_CTRL1_FAIL BIT(1) ++#define GDMA_REG_CTRL1_MASK BIT(0) ++ ++#define GDMA_REG_UNMASK_INT 0x200 ++#define GDMA_REG_DONE_INT 0x204 ++ ++#define GDMA_REG_GCT 0x220 ++#define GDMA_REG_GCT_CHAN_MASK 0x3 ++#define GDMA_REG_GCT_CHAN_SHIFT 3 ++#define GDMA_REG_GCT_VER_MASK 0x3 ++#define GDMA_REG_GCT_VER_SHIFT 1 ++#define GDMA_REG_GCT_ARBIT_RR BIT(0) ++ ++#define GDMA_REG_REQSTS 0x2a0 ++#define GDMA_REG_ACKSTS 0x2a4 ++#define GDMA_REG_FINSTS 0x2a8 ++ ++/* for RT305X gdma registers */ ++#define GDMA_RT305X_CTRL0_REQ_MASK 0xf ++#define GDMA_RT305X_CTRL0_SRC_REQ_SHIFT 12 ++#define GDMA_RT305X_CTRL0_DST_REQ_SHIFT 8 ++ ++#define GDMA_RT305X_CTRL1_FAIL BIT(4) ++#define GDMA_RT305X_CTRL1_NEXT_MASK 0x7 ++#define GDMA_RT305X_CTRL1_NEXT_SHIFT 1 ++ ++#define GDMA_RT305X_STATUS_INT 0x80 ++#define GDMA_RT305X_STATUS_SIGNAL 0x84 ++#define GDMA_RT305X_GCT 0x88 ++ ++/* for MT7621 gdma registers */ ++#define GDMA_REG_PERF_START(x) (0x230 + (x) * 0x8) ++#define GDMA_REG_PERF_END(x) (0x234 + (x) * 0x8) ++ ++enum gdma_dma_transfer_size { ++ GDMA_TRANSFER_SIZE_4BYTE = 0, ++ GDMA_TRANSFER_SIZE_8BYTE = 1, ++ GDMA_TRANSFER_SIZE_16BYTE = 2, ++ GDMA_TRANSFER_SIZE_32BYTE = 3, ++ GDMA_TRANSFER_SIZE_64BYTE = 4, ++}; ++ ++struct gdma_dma_sg { ++ dma_addr_t src_addr; ++ dma_addr_t dst_addr; ++ u32 len; ++}; ++ ++struct gdma_dma_desc { ++ struct virt_dma_desc vdesc; ++ ++ enum dma_transfer_direction direction; ++ bool cyclic; ++ ++ u32 residue; ++ unsigned int num_sgs; ++ struct gdma_dma_sg sg[]; ++}; ++ ++struct gdma_dmaengine_chan { ++ struct virt_dma_chan vchan; ++ unsigned int id; ++ unsigned int slave_id; ++ ++ dma_addr_t fifo_addr; ++ enum gdma_dma_transfer_size burst_size; ++ ++ struct gdma_dma_desc *desc; ++ unsigned int next_sg; ++}; ++ ++struct gdma_dma_dev { ++ struct dma_device ddev; ++ struct device_dma_parameters dma_parms; ++ struct gdma_data *data; ++ void __iomem *base; ++ struct tasklet_struct task; ++ volatile unsigned long chan_issued; ++ atomic_t cnt; ++ ++ struct gdma_dmaengine_chan chan[]; ++}; ++ ++struct gdma_data ++{ ++ int chancnt; ++ u32 done_int_reg; ++ void (*init)(struct gdma_dma_dev *dma_dev); ++ int (*start_transfer)(struct gdma_dmaengine_chan *chan); ++}; ++ ++static struct gdma_dma_dev *gdma_dma_chan_get_dev( ++ struct gdma_dmaengine_chan *chan) ++{ ++ return container_of(chan->vchan.chan.device, struct gdma_dma_dev, ++ ddev); ++} ++ ++static struct gdma_dmaengine_chan *to_gdma_dma_chan(struct dma_chan *c) ++{ ++ return container_of(c, struct gdma_dmaengine_chan, vchan.chan); ++} ++ ++static struct gdma_dma_desc *to_gdma_dma_desc(struct virt_dma_desc *vdesc) ++{ ++ return container_of(vdesc, struct gdma_dma_desc, vdesc); ++} ++ ++static inline uint32_t gdma_dma_read(struct gdma_dma_dev *dma_dev, ++ unsigned int reg) ++{ ++ return readl(dma_dev->base + reg); ++} ++ ++static inline void gdma_dma_write(struct gdma_dma_dev *dma_dev, ++ unsigned reg, uint32_t val) ++{ ++ writel(val, dma_dev->base + reg); ++} ++ ++static struct gdma_dma_desc *gdma_dma_alloc_desc(unsigned int num_sgs) ++{ ++ return kzalloc(sizeof(struct gdma_dma_desc) + ++ sizeof(struct gdma_dma_sg) * num_sgs, GFP_ATOMIC); ++} ++ ++static enum gdma_dma_transfer_size gdma_dma_maxburst(u32 maxburst) ++{ ++ if (maxburst < 2) ++ return GDMA_TRANSFER_SIZE_4BYTE; ++ else if (maxburst < 4) ++ return GDMA_TRANSFER_SIZE_8BYTE; ++ else if (maxburst < 8) ++ return GDMA_TRANSFER_SIZE_16BYTE; ++ else if (maxburst < 16) ++ return GDMA_TRANSFER_SIZE_32BYTE; ++ else ++ return GDMA_TRANSFER_SIZE_64BYTE; ++} ++ ++static int gdma_dma_config(struct dma_chan *c, ++ struct dma_slave_config *config) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); ++ ++ if (config->device_fc) { ++ dev_err(dma_dev->ddev.dev, "not support flow controller\n"); ++ return -EINVAL; ++ } ++ ++ switch (config->direction) { ++ case DMA_MEM_TO_DEV: ++ if (config->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) { ++ dev_err(dma_dev->ddev.dev, "only support 4 byte buswidth\n"); ++ return -EINVAL; ++ } ++ chan->slave_id = config->slave_id; ++ chan->fifo_addr = config->dst_addr; ++ chan->burst_size = gdma_dma_maxburst(config->dst_maxburst); ++ break; ++ case DMA_DEV_TO_MEM: ++ if (config->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) { ++ dev_err(dma_dev->ddev.dev, "only support 4 byte buswidth\n"); ++ return -EINVAL; ++ } ++ chan->slave_id = config->slave_id; ++ chan->fifo_addr = config->src_addr; ++ chan->burst_size = gdma_dma_maxburst(config->src_maxburst); ++ break; ++ default: ++ dev_err(dma_dev->ddev.dev, "direction type %d error\n", ++ config->direction); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int gdma_dma_terminate_all(struct dma_chan *c) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); ++ unsigned long flags, timeout; ++ LIST_HEAD(head); ++ int i = 0; ++ ++ spin_lock_irqsave(&chan->vchan.lock, flags); ++ chan->desc = NULL; ++ clear_bit(chan->id, &dma_dev->chan_issued); ++ vchan_get_all_descriptors(&chan->vchan, &head); ++ spin_unlock_irqrestore(&chan->vchan.lock, flags); ++ ++ vchan_dma_desc_free_list(&chan->vchan, &head); ++ ++ /* wait dma transfer complete */ ++ timeout = jiffies + msecs_to_jiffies(5000); ++ while (gdma_dma_read(dma_dev, GDMA_REG_CTRL0(chan->id)) & ++ GDMA_REG_CTRL0_ENABLE) { ++ if (time_after_eq(jiffies, timeout)) { ++ dev_err(dma_dev->ddev.dev, "chan %d wait timeout\n", ++ chan->id); ++ /* restore to init value */ ++ gdma_dma_write(dma_dev, GDMA_REG_CTRL0(chan->id), 0); ++ break; ++ } ++ cpu_relax(); ++ i++; ++ } ++ ++ if (i) ++ dev_dbg(dma_dev->ddev.dev, "terminate chan %d loops %d\n", ++ chan->id, i); ++ ++ return 0; ++} ++ ++static void rt305x_dump_reg(struct gdma_dma_dev *dma_dev, int id) ++{ ++ dev_dbg(dma_dev->ddev.dev, "chan %d, src %08x, dst %08x, ctr0 %08x, " \ ++ "ctr1 %08x, intr %08x, signal %08x\n", id, ++ gdma_dma_read(dma_dev, GDMA_REG_SRC_ADDR(id)), ++ gdma_dma_read(dma_dev, GDMA_REG_DST_ADDR(id)), ++ gdma_dma_read(dma_dev, GDMA_REG_CTRL0(id)), ++ gdma_dma_read(dma_dev, GDMA_REG_CTRL1(id)), ++ gdma_dma_read(dma_dev, GDMA_RT305X_STATUS_INT), ++ gdma_dma_read(dma_dev, GDMA_RT305X_STATUS_SIGNAL)); ++} ++ ++static int rt305x_gdma_start_transfer(struct gdma_dmaengine_chan *chan) ++{ ++ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); ++ dma_addr_t src_addr, dst_addr; ++ struct gdma_dma_sg *sg; ++ uint32_t ctrl0, ctrl1; ++ ++ /* verify chan is already stopped */ ++ ctrl0 = gdma_dma_read(dma_dev, GDMA_REG_CTRL0(chan->id)); ++ if (unlikely(ctrl0 & GDMA_REG_CTRL0_ENABLE)) { ++ dev_err(dma_dev->ddev.dev, "chan %d is start(%08x).\n", ++ chan->id, ctrl0); ++ rt305x_dump_reg(dma_dev, chan->id); ++ return -EINVAL; ++ } ++ ++ sg = &chan->desc->sg[chan->next_sg]; ++ if (chan->desc->direction == DMA_MEM_TO_DEV) { ++ src_addr = sg->src_addr; ++ dst_addr = chan->fifo_addr; ++ ctrl0 = GDMA_REG_CTRL0_DST_ADDR_FIXED | \ ++ (8 << GDMA_RT305X_CTRL0_SRC_REQ_SHIFT) | \ ++ (chan->slave_id << GDMA_RT305X_CTRL0_DST_REQ_SHIFT); ++ } else if (chan->desc->direction == DMA_DEV_TO_MEM) { ++ src_addr = chan->fifo_addr; ++ dst_addr = sg->dst_addr; ++ ctrl0 = GDMA_REG_CTRL0_SRC_ADDR_FIXED | \ ++ (chan->slave_id << GDMA_RT305X_CTRL0_SRC_REQ_SHIFT) | \ ++ (8 << GDMA_RT305X_CTRL0_DST_REQ_SHIFT); ++ } else if (chan->desc->direction == DMA_MEM_TO_MEM) { ++ /* ++ * TODO: memcpy function have bugs. sometime it will copy ++ * more 8 bytes data when using dmatest verify. ++ */ ++ src_addr = sg->src_addr; ++ dst_addr = sg->dst_addr; ++ ctrl0 = GDMA_REG_CTRL0_SW_MODE | \ ++ (8 << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ ++ (8 << GDMA_REG_CTRL1_DST_REQ_SHIFT); ++ } else { ++ dev_err(dma_dev->ddev.dev, "direction type %d error\n", ++ chan->desc->direction); ++ return -EINVAL; ++ } ++ ++ ctrl0 |= (sg->len << GDMA_REG_CTRL0_TX_SHIFT) | \ ++ (chan->burst_size << GDMA_REG_CTRL0_BURST_SHIFT) | \ ++ GDMA_REG_CTRL0_DONE_INT | GDMA_REG_CTRL0_ENABLE; ++ ctrl1 = chan->id << GDMA_REG_CTRL1_NEXT_SHIFT; ++ ++ chan->next_sg++; ++ gdma_dma_write(dma_dev, GDMA_REG_SRC_ADDR(chan->id), src_addr); ++ gdma_dma_write(dma_dev, GDMA_REG_DST_ADDR(chan->id), dst_addr); ++ gdma_dma_write(dma_dev, GDMA_REG_CTRL1(chan->id), ctrl1); ++ ++ /* make sure next_sg is update */ ++ wmb(); ++ gdma_dma_write(dma_dev, GDMA_REG_CTRL0(chan->id), ctrl0); ++ ++ return 0; ++} ++ ++static void rt3883_dump_reg(struct gdma_dma_dev *dma_dev, int id) ++{ ++ dev_dbg(dma_dev->ddev.dev, "chan %d, src %08x, dst %08x, ctr0 %08x, " \ ++ "ctr1 %08x, unmask %08x, done %08x, " \ ++ "req %08x, ack %08x, fin %08x\n", id, ++ gdma_dma_read(dma_dev, GDMA_REG_SRC_ADDR(id)), ++ gdma_dma_read(dma_dev, GDMA_REG_DST_ADDR(id)), ++ gdma_dma_read(dma_dev, GDMA_REG_CTRL0(id)), ++ gdma_dma_read(dma_dev, GDMA_REG_CTRL1(id)), ++ gdma_dma_read(dma_dev, GDMA_REG_UNMASK_INT), ++ gdma_dma_read(dma_dev, GDMA_REG_DONE_INT), ++ gdma_dma_read(dma_dev, GDMA_REG_REQSTS), ++ gdma_dma_read(dma_dev, GDMA_REG_ACKSTS), ++ gdma_dma_read(dma_dev, GDMA_REG_FINSTS)); ++} ++ ++static int rt3883_gdma_start_transfer(struct gdma_dmaengine_chan *chan) ++{ ++ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); ++ dma_addr_t src_addr, dst_addr; ++ struct gdma_dma_sg *sg; ++ uint32_t ctrl0, ctrl1; ++ ++ /* verify chan is already stopped */ ++ ctrl0 = gdma_dma_read(dma_dev, GDMA_REG_CTRL0(chan->id)); ++ if (unlikely(ctrl0 & GDMA_REG_CTRL0_ENABLE)) { ++ dev_err(dma_dev->ddev.dev, "chan %d is start(%08x).\n", ++ chan->id, ctrl0); ++ rt3883_dump_reg(dma_dev, chan->id); ++ return -EINVAL; ++ } ++ ++ sg = &chan->desc->sg[chan->next_sg]; ++ if (chan->desc->direction == DMA_MEM_TO_DEV) { ++ src_addr = sg->src_addr; ++ dst_addr = chan->fifo_addr; ++ ctrl0 = GDMA_REG_CTRL0_DST_ADDR_FIXED; ++ ctrl1 = (32 << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ ++ (chan->slave_id << GDMA_REG_CTRL1_DST_REQ_SHIFT); ++ } else if (chan->desc->direction == DMA_DEV_TO_MEM) { ++ src_addr = chan->fifo_addr; ++ dst_addr = sg->dst_addr; ++ ctrl0 = GDMA_REG_CTRL0_SRC_ADDR_FIXED; ++ ctrl1 = (chan->slave_id << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ ++ (32 << GDMA_REG_CTRL1_DST_REQ_SHIFT) | \ ++ GDMA_REG_CTRL1_COHERENT; ++ } else if (chan->desc->direction == DMA_MEM_TO_MEM) { ++ src_addr = sg->src_addr; ++ dst_addr = sg->dst_addr; ++ ctrl0 = GDMA_REG_CTRL0_SW_MODE; ++ ctrl1 = (32 << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ ++ (32 << GDMA_REG_CTRL1_DST_REQ_SHIFT) | \ ++ GDMA_REG_CTRL1_COHERENT; ++ } else { ++ dev_err(dma_dev->ddev.dev, "direction type %d error\n", ++ chan->desc->direction); ++ return -EINVAL; ++ } ++ ++ ctrl0 |= (sg->len << GDMA_REG_CTRL0_TX_SHIFT) | \ ++ (chan->burst_size << GDMA_REG_CTRL0_BURST_SHIFT) | \ ++ GDMA_REG_CTRL0_DONE_INT | GDMA_REG_CTRL0_ENABLE; ++ ctrl1 |= chan->id << GDMA_REG_CTRL1_NEXT_SHIFT; ++ ++ chan->next_sg++; ++ gdma_dma_write(dma_dev, GDMA_REG_SRC_ADDR(chan->id), src_addr); ++ gdma_dma_write(dma_dev, GDMA_REG_DST_ADDR(chan->id), dst_addr); ++ gdma_dma_write(dma_dev, GDMA_REG_CTRL1(chan->id), ctrl1); ++ ++ /* make sure next_sg is update */ ++ wmb(); ++ gdma_dma_write(dma_dev, GDMA_REG_CTRL0(chan->id), ctrl0); ++ ++ return 0; ++} ++ ++static inline int gdma_start_transfer(struct gdma_dma_dev *dma_dev, ++ struct gdma_dmaengine_chan *chan) ++{ ++ return dma_dev->data->start_transfer(chan); ++} ++ ++static int gdma_next_desc(struct gdma_dmaengine_chan *chan) ++{ ++ struct virt_dma_desc *vdesc; ++ ++ vdesc = vchan_next_desc(&chan->vchan); ++ if (!vdesc) { ++ chan->desc = NULL; ++ return 0; ++ } ++ chan->desc = to_gdma_dma_desc(vdesc); ++ chan->next_sg = 0; ++ ++ return 1; ++} ++ ++static void gdma_dma_chan_irq(struct gdma_dma_dev *dma_dev, ++ struct gdma_dmaengine_chan *chan) ++{ ++ struct gdma_dma_desc *desc; ++ unsigned long flags; ++ int chan_issued; ++ ++ chan_issued = 0; ++ spin_lock_irqsave(&chan->vchan.lock, flags); ++ desc = chan->desc; ++ if (desc) { ++ if (desc->cyclic) { ++ vchan_cyclic_callback(&desc->vdesc); ++ if (chan->next_sg == desc->num_sgs) ++ chan->next_sg = 0; ++ chan_issued = 1; ++ } else { ++ desc->residue -= desc->sg[chan->next_sg - 1].len; ++ if (chan->next_sg == desc->num_sgs) { ++ list_del(&desc->vdesc.node); ++ vchan_cookie_complete(&desc->vdesc); ++ chan_issued = gdma_next_desc(chan); ++ } else ++ chan_issued = 1; ++ } ++ } else ++ dev_dbg(dma_dev->ddev.dev, "chan %d no desc to complete\n", ++ chan->id); ++ if (chan_issued) ++ set_bit(chan->id, &dma_dev->chan_issued); ++ spin_unlock_irqrestore(&chan->vchan.lock, flags); ++} ++ ++static irqreturn_t gdma_dma_irq(int irq, void *devid) ++{ ++ struct gdma_dma_dev *dma_dev = devid; ++ u32 done, done_reg; ++ unsigned int i; ++ ++ done_reg = dma_dev->data->done_int_reg; ++ done = gdma_dma_read(dma_dev, done_reg); ++ if (unlikely(!done)) ++ return IRQ_NONE; ++ ++ /* clean done bits */ ++ gdma_dma_write(dma_dev, done_reg, done); ++ ++ i = 0; ++ while (done) { ++ if (done & 0x1) { ++ gdma_dma_chan_irq(dma_dev, &dma_dev->chan[i]); ++ atomic_dec(&dma_dev->cnt); ++ } ++ done >>= 1; ++ i++; ++ } ++ ++ /* start only have work to do */ ++ if (dma_dev->chan_issued) ++ tasklet_schedule(&dma_dev->task); ++ ++ return IRQ_HANDLED; ++} ++ ++static void gdma_dma_issue_pending(struct dma_chan *c) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&chan->vchan.lock, flags); ++ if (vchan_issue_pending(&chan->vchan) && !chan->desc) { ++ if (gdma_next_desc(chan)) { ++ set_bit(chan->id, &dma_dev->chan_issued); ++ tasklet_schedule(&dma_dev->task); ++ } else ++ dev_dbg(dma_dev->ddev.dev, "chan %d no desc to issue\n", ++ chan->id); ++ } ++ spin_unlock_irqrestore(&chan->vchan.lock, flags); ++} ++ ++static struct dma_async_tx_descriptor *gdma_dma_prep_slave_sg( ++ struct dma_chan *c, struct scatterlist *sgl, ++ unsigned int sg_len, enum dma_transfer_direction direction, ++ unsigned long flags, void *context) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct gdma_dma_desc *desc; ++ struct scatterlist *sg; ++ unsigned int i; ++ ++ desc = gdma_dma_alloc_desc(sg_len); ++ if (!desc) { ++ dev_err(c->device->dev, "alloc sg decs error\n"); ++ return NULL; ++ } ++ desc->residue = 0; ++ ++ for_each_sg(sgl, sg, sg_len, i) { ++ if (direction == DMA_MEM_TO_DEV) ++ desc->sg[i].src_addr = sg_dma_address(sg); ++ else if (direction == DMA_DEV_TO_MEM) ++ desc->sg[i].dst_addr = sg_dma_address(sg); ++ else { ++ dev_err(c->device->dev, "direction type %d error\n", ++ direction); ++ goto free_desc; ++ } ++ ++ if (unlikely(sg_dma_len(sg) > GDMA_REG_CTRL0_TX_MASK)) { ++ dev_err(c->device->dev, "sg len too large %d\n", ++ sg_dma_len(sg)); ++ goto free_desc; ++ } ++ desc->sg[i].len = sg_dma_len(sg); ++ desc->residue += sg_dma_len(sg); ++ } ++ ++ desc->num_sgs = sg_len; ++ desc->direction = direction; ++ desc->cyclic = false; ++ ++ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); ++ ++free_desc: ++ kfree(desc); ++ return NULL; ++} ++ ++static struct dma_async_tx_descriptor * gdma_dma_prep_dma_memcpy( ++ struct dma_chan *c, dma_addr_t dest, dma_addr_t src, ++ size_t len, unsigned long flags) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct gdma_dma_desc *desc; ++ unsigned int num_periods, i; ++ size_t xfer_count; ++ ++ if (len <= 0) ++ return NULL; ++ ++ chan->burst_size = gdma_dma_maxburst(len >> 2); ++ ++ xfer_count = GDMA_REG_CTRL0_TX_MASK; ++ num_periods = DIV_ROUND_UP(len, xfer_count); ++ ++ desc = gdma_dma_alloc_desc(num_periods); ++ if (!desc) { ++ dev_err(c->device->dev, "alloc memcpy decs error\n"); ++ return NULL; ++ } ++ desc->residue = len; ++ ++ for (i = 0; i < num_periods; i++) { ++ desc->sg[i].src_addr = src; ++ desc->sg[i].dst_addr = dest; ++ if (len > xfer_count) { ++ desc->sg[i].len = xfer_count; ++ } else { ++ desc->sg[i].len = len; ++ } ++ src += desc->sg[i].len; ++ dest += desc->sg[i].len; ++ len -= desc->sg[i].len; ++ } ++ ++ desc->num_sgs = num_periods; ++ desc->direction = DMA_MEM_TO_MEM; ++ desc->cyclic = false; ++ ++ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); ++} ++ ++static struct dma_async_tx_descriptor *gdma_dma_prep_dma_cyclic( ++ struct dma_chan *c, dma_addr_t buf_addr, size_t buf_len, ++ size_t period_len, enum dma_transfer_direction direction, ++ unsigned long flags) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct gdma_dma_desc *desc; ++ unsigned int num_periods, i; ++ ++ if (buf_len % period_len) ++ return NULL; ++ ++ if (period_len > GDMA_REG_CTRL0_TX_MASK) { ++ dev_err(c->device->dev, "cyclic len too large %d\n", ++ period_len); ++ return NULL; ++ } ++ ++ num_periods = buf_len / period_len; ++ desc = gdma_dma_alloc_desc(num_periods); ++ if (!desc) { ++ dev_err(c->device->dev, "alloc cyclic decs error\n"); ++ return NULL; ++ } ++ desc->residue = buf_len; ++ ++ for (i = 0; i < num_periods; i++) { ++ if (direction == DMA_MEM_TO_DEV) ++ desc->sg[i].src_addr = buf_addr; ++ else if (direction == DMA_DEV_TO_MEM) ++ desc->sg[i].dst_addr = buf_addr; ++ else { ++ dev_err(c->device->dev, "direction type %d error\n", ++ direction); ++ goto free_desc; ++ } ++ desc->sg[i].len = period_len; ++ buf_addr += period_len; ++ } ++ ++ desc->num_sgs = num_periods; ++ desc->direction = direction; ++ desc->cyclic = true; ++ ++ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); ++ ++free_desc: ++ kfree(desc); ++ return NULL; ++} ++ ++static enum dma_status gdma_dma_tx_status(struct dma_chan *c, ++ dma_cookie_t cookie, struct dma_tx_state *state) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct virt_dma_desc *vdesc; ++ enum dma_status status; ++ unsigned long flags; ++ struct gdma_dma_desc *desc; ++ ++ status = dma_cookie_status(c, cookie, state); ++ if (status == DMA_COMPLETE || !state) ++ return status; ++ ++ spin_lock_irqsave(&chan->vchan.lock, flags); ++ desc = chan->desc; ++ if (desc && (cookie == desc->vdesc.tx.cookie)) { ++ /* ++ * We never update edesc->residue in the cyclic case, so we ++ * can tell the remaining room to the end of the circular ++ * buffer. ++ */ ++ if (desc->cyclic) ++ state->residue = desc->residue - ++ ((chan->next_sg - 1) * desc->sg[0].len); ++ else ++ state->residue = desc->residue; ++ } else if ((vdesc = vchan_find_desc(&chan->vchan, cookie))) ++ state->residue = to_gdma_dma_desc(vdesc)->residue; ++ spin_unlock_irqrestore(&chan->vchan.lock, flags); ++ ++ dev_dbg(c->device->dev, "tx residue %d bytes\n", state->residue); ++ ++ return status; ++} ++ ++static void gdma_dma_free_chan_resources(struct dma_chan *c) ++{ ++ vchan_free_chan_resources(to_virt_chan(c)); ++} ++ ++static void gdma_dma_desc_free(struct virt_dma_desc *vdesc) ++{ ++ kfree(container_of(vdesc, struct gdma_dma_desc, vdesc)); ++} ++ ++static void gdma_dma_tasklet(unsigned long arg) ++{ ++ struct gdma_dma_dev *dma_dev = (struct gdma_dma_dev *)arg; ++ struct gdma_dmaengine_chan *chan; ++ static unsigned int last_chan; ++ unsigned int i, chan_mask; ++ ++ /* record last chan to round robin all chans */ ++ i = last_chan; ++ chan_mask = dma_dev->data->chancnt - 1; ++ do { ++ /* ++ * on mt7621. when verify with dmatest with all ++ * channel is enable. we need to limit only two ++ * channel is working at the same time. otherwise the ++ * data will have problem. ++ */ ++ if (atomic_read(&dma_dev->cnt) >= 2) { ++ last_chan = i; ++ break; ++ } ++ ++ if (test_and_clear_bit(i, &dma_dev->chan_issued)) { ++ chan = &dma_dev->chan[i]; ++ if (chan->desc) { ++ atomic_inc(&dma_dev->cnt); ++ gdma_start_transfer(dma_dev, chan); ++ } else ++ dev_dbg(dma_dev->ddev.dev, "chan %d no desc to issue\n", chan->id); ++ ++ if (!dma_dev->chan_issued) ++ break; ++ } ++ ++ i = (i + 1) & chan_mask; ++ } while (i != last_chan); ++} ++ ++static void rt305x_gdma_init(struct gdma_dma_dev *dma_dev) ++{ ++ uint32_t gct; ++ ++ /* all chans round robin */ ++ gdma_dma_write(dma_dev, GDMA_RT305X_GCT, GDMA_REG_GCT_ARBIT_RR); ++ ++ gct = gdma_dma_read(dma_dev, GDMA_RT305X_GCT); ++ dev_info(dma_dev->ddev.dev, "revision: %d, channels: %d\n", ++ (gct >> GDMA_REG_GCT_VER_SHIFT) & GDMA_REG_GCT_VER_MASK, ++ 8 << ((gct >> GDMA_REG_GCT_CHAN_SHIFT) & ++ GDMA_REG_GCT_CHAN_MASK)); ++} ++ ++static void rt3883_gdma_init(struct gdma_dma_dev *dma_dev) ++{ ++ uint32_t gct; ++ ++ /* all chans round robin */ ++ gdma_dma_write(dma_dev, GDMA_REG_GCT, GDMA_REG_GCT_ARBIT_RR); ++ ++ gct = gdma_dma_read(dma_dev, GDMA_REG_GCT); ++ dev_info(dma_dev->ddev.dev, "revision: %d, channels: %d\n", ++ (gct >> GDMA_REG_GCT_VER_SHIFT) & GDMA_REG_GCT_VER_MASK, ++ 8 << ((gct >> GDMA_REG_GCT_CHAN_SHIFT) & ++ GDMA_REG_GCT_CHAN_MASK)); ++} ++ ++static struct gdma_data rt305x_gdma_data = { ++ .chancnt = 8, ++ .done_int_reg = GDMA_RT305X_STATUS_INT, ++ .init = rt305x_gdma_init, ++ .start_transfer = rt305x_gdma_start_transfer, ++}; ++ ++static struct gdma_data rt3883_gdma_data = { ++ .chancnt = 16, ++ .done_int_reg = GDMA_REG_DONE_INT, ++ .init = rt3883_gdma_init, ++ .start_transfer = rt3883_gdma_start_transfer, ++}; ++ ++static const struct of_device_id gdma_of_match_table[] = { ++ { .compatible = "ralink,rt305x-gdma", .data = &rt305x_gdma_data }, ++ { .compatible = "ralink,rt3883-gdma", .data = &rt3883_gdma_data }, ++ { }, ++}; ++ ++static int gdma_dma_probe(struct platform_device *pdev) ++{ ++ const struct of_device_id *match; ++ struct gdma_dmaengine_chan *chan; ++ struct gdma_dma_dev *dma_dev; ++ struct dma_device *dd; ++ unsigned int i; ++ struct resource *res; ++ int ret; ++ int irq; ++ void __iomem *base; ++ struct gdma_data *data; ++ ++ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); ++ if (ret) ++ return ret; ++ ++ match = of_match_device(gdma_of_match_table, &pdev->dev); ++ if (!match) ++ return -EINVAL; ++ data = (struct gdma_data *) match->data; ++ ++ dma_dev = devm_kzalloc(&pdev->dev, sizeof(*dma_dev) + ++ (sizeof(struct gdma_dmaengine_chan) * data->chancnt), ++ GFP_KERNEL); ++ if (!dma_dev) { ++ dev_err(&pdev->dev, "alloc dma device failed\n"); ++ return -EINVAL; ++ } ++ dma_dev->data = data; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ dma_dev->base = base; ++ tasklet_init(&dma_dev->task, gdma_dma_tasklet, (unsigned long)dma_dev); ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, "failed to get irq\n"); ++ return -EINVAL; ++ } ++ ret = devm_request_irq(&pdev->dev, irq, gdma_dma_irq, ++ 0, dev_name(&pdev->dev), dma_dev); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to request irq\n"); ++ return ret; ++ } ++ ++ device_reset(&pdev->dev); ++ ++ dd = &dma_dev->ddev; ++ dma_cap_set(DMA_MEMCPY, dd->cap_mask); ++ dma_cap_set(DMA_SLAVE, dd->cap_mask); ++ dma_cap_set(DMA_CYCLIC, dd->cap_mask); ++ dd->device_free_chan_resources = gdma_dma_free_chan_resources; ++ dd->device_prep_dma_memcpy = gdma_dma_prep_dma_memcpy; ++ dd->device_prep_slave_sg = gdma_dma_prep_slave_sg; ++ dd->device_prep_dma_cyclic = gdma_dma_prep_dma_cyclic; ++ dd->device_config = gdma_dma_config; ++ dd->device_terminate_all = gdma_dma_terminate_all; ++ dd->device_tx_status = gdma_dma_tx_status; ++ dd->device_issue_pending = gdma_dma_issue_pending; ++ ++ dd->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); ++ dd->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); ++ dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); ++ dd->residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; ++ ++ dd->dev = &pdev->dev; ++ dd->dev->dma_parms = &dma_dev->dma_parms; ++ dma_set_max_seg_size(dd->dev, GDMA_REG_CTRL0_TX_MASK); ++ INIT_LIST_HEAD(&dd->channels); ++ ++ for (i = 0; i < data->chancnt; i++) { ++ chan = &dma_dev->chan[i]; ++ chan->id = i; ++ chan->vchan.desc_free = gdma_dma_desc_free; ++ vchan_init(&chan->vchan, dd); ++ } ++ ++ /* init hardware */ ++ data->init(dma_dev); ++ ++ ret = dma_async_device_register(dd); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to register dma device\n"); ++ return ret; ++ } ++ ++ ret = of_dma_controller_register(pdev->dev.of_node, ++ of_dma_xlate_by_chan_id, dma_dev); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to register of dma controller\n"); ++ goto err_unregister; ++ } ++ ++ platform_set_drvdata(pdev, dma_dev); ++ ++ return 0; ++ ++err_unregister: ++ dma_async_device_unregister(dd); ++ return ret; ++} ++ ++static int gdma_dma_remove(struct platform_device *pdev) ++{ ++ struct gdma_dma_dev *dma_dev = platform_get_drvdata(pdev); ++ ++ tasklet_kill(&dma_dev->task); ++ of_dma_controller_free(pdev->dev.of_node); ++ dma_async_device_unregister(&dma_dev->ddev); ++ ++ return 0; ++} ++ ++static struct platform_driver gdma_dma_driver = { ++ .probe = gdma_dma_probe, ++ .remove = gdma_dma_remove, ++ .driver = { ++ .name = "gdma-rt2880", ++ .of_match_table = gdma_of_match_table, ++ }, ++}; ++module_platform_driver(gdma_dma_driver); ++ ++MODULE_AUTHOR("Lars-Peter Clausen "); ++MODULE_DESCRIPTION("Ralink/MTK DMA driver"); ++MODULE_LICENSE("GPL v2"); +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -525,6 +525,7 @@ static inline void dma_set_unmap(struct + struct dmaengine_unmap_data * + dmaengine_get_unmap_data(struct device *dev, int nr, gfp_t flags); + void dmaengine_unmap_put(struct dmaengine_unmap_data *unmap); ++struct dma_chan *dma_get_slave_channel(struct dma_chan *chan); + #else + static inline void dma_set_unmap(struct dma_async_tx_descriptor *tx, + struct dmaengine_unmap_data *unmap) +--- /dev/null ++++ b/drivers/dma/mtk-hsdma.c +@@ -0,0 +1,767 @@ ++/* ++ * Copyright (C) 2015, Michael Lee ++ * MTK HSDMA support ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "virt-dma.h" ++ ++#define HSDMA_BASE_OFFSET 0x800 ++ ++#define HSDMA_REG_TX_BASE 0x00 ++#define HSDMA_REG_TX_CNT 0x04 ++#define HSDMA_REG_TX_CTX 0x08 ++#define HSDMA_REG_TX_DTX 0x0c ++#define HSDMA_REG_RX_BASE 0x100 ++#define HSDMA_REG_RX_CNT 0x104 ++#define HSDMA_REG_RX_CRX 0x108 ++#define HSDMA_REG_RX_DRX 0x10c ++#define HSDMA_REG_INFO 0x200 ++#define HSDMA_REG_GLO_CFG 0x204 ++#define HSDMA_REG_RST_CFG 0x208 ++#define HSDMA_REG_DELAY_INT 0x20c ++#define HSDMA_REG_FREEQ_THRES 0x210 ++#define HSDMA_REG_INT_STATUS 0x220 ++#define HSDMA_REG_INT_MASK 0x228 ++#define HSDMA_REG_SCH_Q01 0x280 ++#define HSDMA_REG_SCH_Q23 0x284 ++ ++#define HSDMA_DESCS_MAX 0xfff ++#define HSDMA_DESCS_NUM 8 ++#define HSDMA_DESCS_MASK (HSDMA_DESCS_NUM - 1) ++#define HSDMA_NEXT_DESC(x) (((x) + 1) & HSDMA_DESCS_MASK) ++ ++/* HSDMA_REG_INFO */ ++#define HSDMA_INFO_INDEX_MASK 0xf ++#define HSDMA_INFO_INDEX_SHIFT 24 ++#define HSDMA_INFO_BASE_MASK 0xff ++#define HSDMA_INFO_BASE_SHIFT 16 ++#define HSDMA_INFO_RX_MASK 0xff ++#define HSDMA_INFO_RX_SHIFT 8 ++#define HSDMA_INFO_TX_MASK 0xff ++#define HSDMA_INFO_TX_SHIFT 0 ++ ++/* HSDMA_REG_GLO_CFG */ ++#define HSDMA_GLO_TX_2B_OFFSET BIT(31) ++#define HSDMA_GLO_CLK_GATE BIT(30) ++#define HSDMA_GLO_BYTE_SWAP BIT(29) ++#define HSDMA_GLO_MULTI_DMA BIT(10) ++#define HSDMA_GLO_TWO_BUF BIT(9) ++#define HSDMA_GLO_32B_DESC BIT(8) ++#define HSDMA_GLO_BIG_ENDIAN BIT(7) ++#define HSDMA_GLO_TX_DONE BIT(6) ++#define HSDMA_GLO_BT_MASK 0x3 ++#define HSDMA_GLO_BT_SHIFT 4 ++#define HSDMA_GLO_RX_BUSY BIT(3) ++#define HSDMA_GLO_RX_DMA BIT(2) ++#define HSDMA_GLO_TX_BUSY BIT(1) ++#define HSDMA_GLO_TX_DMA BIT(0) ++ ++#define HSDMA_BT_SIZE_16BYTES (0 << HSDMA_GLO_BT_SHIFT) ++#define HSDMA_BT_SIZE_32BYTES (1 << HSDMA_GLO_BT_SHIFT) ++#define HSDMA_BT_SIZE_64BYTES (2 << HSDMA_GLO_BT_SHIFT) ++#define HSDMA_BT_SIZE_128BYTES (3 << HSDMA_GLO_BT_SHIFT) ++ ++#define HSDMA_GLO_DEFAULT (HSDMA_GLO_MULTI_DMA | \ ++ HSDMA_GLO_RX_DMA | HSDMA_GLO_TX_DMA | HSDMA_BT_SIZE_32BYTES) ++ ++/* HSDMA_REG_RST_CFG */ ++#define HSDMA_RST_RX_SHIFT 16 ++#define HSDMA_RST_TX_SHIFT 0 ++ ++/* HSDMA_REG_DELAY_INT */ ++#define HSDMA_DELAY_INT_EN BIT(15) ++#define HSDMA_DELAY_PEND_OFFSET 8 ++#define HSDMA_DELAY_TIME_OFFSET 0 ++#define HSDMA_DELAY_TX_OFFSET 16 ++#define HSDMA_DELAY_RX_OFFSET 0 ++ ++#define HSDMA_DELAY_INIT(x) (HSDMA_DELAY_INT_EN | \ ++ ((x) << HSDMA_DELAY_PEND_OFFSET)) ++#define HSDMA_DELAY(x) ((HSDMA_DELAY_INIT(x) << \ ++ HSDMA_DELAY_TX_OFFSET) | HSDMA_DELAY_INIT(x)) ++ ++/* HSDMA_REG_INT_STATUS */ ++#define HSDMA_INT_DELAY_RX_COH BIT(31) ++#define HSDMA_INT_DELAY_RX_INT BIT(30) ++#define HSDMA_INT_DELAY_TX_COH BIT(29) ++#define HSDMA_INT_DELAY_TX_INT BIT(28) ++#define HSDMA_INT_RX_MASK 0x3 ++#define HSDMA_INT_RX_SHIFT 16 ++#define HSDMA_INT_RX_Q0 BIT(16) ++#define HSDMA_INT_TX_MASK 0xf ++#define HSDMA_INT_TX_SHIFT 0 ++#define HSDMA_INT_TX_Q0 BIT(0) ++ ++/* tx/rx dma desc flags */ ++#define HSDMA_PLEN_MASK 0x3fff ++#define HSDMA_DESC_DONE BIT(31) ++#define HSDMA_DESC_LS0 BIT(30) ++#define HSDMA_DESC_PLEN0(_x) (((_x) & HSDMA_PLEN_MASK) << 16) ++#define HSDMA_DESC_TAG BIT(15) ++#define HSDMA_DESC_LS1 BIT(14) ++#define HSDMA_DESC_PLEN1(_x) ((_x) & HSDMA_PLEN_MASK) ++ ++/* align 4 bytes */ ++#define HSDMA_ALIGN_SIZE 3 ++/* align size 128bytes */ ++#define HSDMA_MAX_PLEN 0x3f80 ++ ++struct hsdma_desc { ++ u32 addr0; ++ u32 flags; ++ u32 addr1; ++ u32 unused; ++}; ++ ++struct mtk_hsdma_sg { ++ dma_addr_t src_addr; ++ dma_addr_t dst_addr; ++ u32 len; ++}; ++ ++struct mtk_hsdma_desc { ++ struct virt_dma_desc vdesc; ++ unsigned int num_sgs; ++ struct mtk_hsdma_sg sg[1]; ++}; ++ ++struct mtk_hsdma_chan { ++ struct virt_dma_chan vchan; ++ unsigned int id; ++ dma_addr_t desc_addr; ++ int tx_idx; ++ int rx_idx; ++ struct hsdma_desc *tx_ring; ++ struct hsdma_desc *rx_ring; ++ struct mtk_hsdma_desc *desc; ++ unsigned int next_sg; ++}; ++ ++struct mtk_hsdam_engine { ++ struct dma_device ddev; ++ struct device_dma_parameters dma_parms; ++ void __iomem *base; ++ struct tasklet_struct task; ++ volatile unsigned long chan_issued; ++ ++ struct mtk_hsdma_chan chan[1]; ++}; ++ ++static inline struct mtk_hsdam_engine *mtk_hsdma_chan_get_dev( ++ struct mtk_hsdma_chan *chan) ++{ ++ return container_of(chan->vchan.chan.device, struct mtk_hsdam_engine, ++ ddev); ++} ++ ++static inline struct mtk_hsdma_chan *to_mtk_hsdma_chan(struct dma_chan *c) ++{ ++ return container_of(c, struct mtk_hsdma_chan, vchan.chan); ++} ++ ++static inline struct mtk_hsdma_desc *to_mtk_hsdma_desc( ++ struct virt_dma_desc *vdesc) ++{ ++ return container_of(vdesc, struct mtk_hsdma_desc, vdesc); ++} ++ ++static inline u32 mtk_hsdma_read(struct mtk_hsdam_engine *hsdma, u32 reg) ++{ ++ return readl(hsdma->base + reg); ++} ++ ++static inline void mtk_hsdma_write(struct mtk_hsdam_engine *hsdma, ++ unsigned reg, u32 val) ++{ ++ writel(val, hsdma->base + reg); ++} ++ ++static void mtk_hsdma_reset_chan(struct mtk_hsdam_engine *hsdma, ++ struct mtk_hsdma_chan *chan) ++{ ++ chan->tx_idx = 0; ++ chan->rx_idx = HSDMA_DESCS_NUM - 1; ++ ++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_CTX, chan->tx_idx); ++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_CRX, chan->rx_idx); ++ ++ mtk_hsdma_write(hsdma, HSDMA_REG_RST_CFG, ++ 0x1 << (chan->id + HSDMA_RST_TX_SHIFT)); ++ mtk_hsdma_write(hsdma, HSDMA_REG_RST_CFG, ++ 0x1 << (chan->id + HSDMA_RST_RX_SHIFT)); ++} ++ ++static void hsdma_dump_reg(struct mtk_hsdam_engine *hsdma) ++{ ++ dev_dbg(hsdma->ddev.dev, "tbase %08x, tcnt %08x, " \ ++ "tctx %08x, tdtx: %08x, rbase %08x, " \ ++ "rcnt %08x, rctx %08x, rdtx %08x\n", ++ mtk_hsdma_read(hsdma, HSDMA_REG_TX_BASE), ++ mtk_hsdma_read(hsdma, HSDMA_REG_TX_CNT), ++ mtk_hsdma_read(hsdma, HSDMA_REG_TX_CTX), ++ mtk_hsdma_read(hsdma, HSDMA_REG_TX_DTX), ++ mtk_hsdma_read(hsdma, HSDMA_REG_RX_BASE), ++ mtk_hsdma_read(hsdma, HSDMA_REG_RX_CNT), ++ mtk_hsdma_read(hsdma, HSDMA_REG_RX_CRX), ++ mtk_hsdma_read(hsdma, HSDMA_REG_RX_DRX)); ++ ++ dev_dbg(hsdma->ddev.dev, "info %08x, glo %08x, delay %08x, " \ ++ "intr_stat %08x, intr_mask %08x\n", ++ mtk_hsdma_read(hsdma, HSDMA_REG_INFO), ++ mtk_hsdma_read(hsdma, HSDMA_REG_GLO_CFG), ++ mtk_hsdma_read(hsdma, HSDMA_REG_DELAY_INT), ++ mtk_hsdma_read(hsdma, HSDMA_REG_INT_STATUS), ++ mtk_hsdma_read(hsdma, HSDMA_REG_INT_MASK)); ++} ++ ++static void hsdma_dump_desc(struct mtk_hsdam_engine *hsdma, ++ struct mtk_hsdma_chan *chan) ++{ ++ struct hsdma_desc *tx_desc; ++ struct hsdma_desc *rx_desc; ++ int i; ++ ++ dev_dbg(hsdma->ddev.dev, "tx idx: %d, rx idx: %d\n", ++ chan->tx_idx, chan->rx_idx); ++ ++ for (i = 0; i < HSDMA_DESCS_NUM; i++) { ++ tx_desc = &chan->tx_ring[i]; ++ rx_desc = &chan->rx_ring[i]; ++ ++ dev_dbg(hsdma->ddev.dev, "%d tx addr0: %08x, flags %08x, " \ ++ "tx addr1: %08x, rx addr0 %08x, flags %08x\n", ++ i, tx_desc->addr0, tx_desc->flags, \ ++ tx_desc->addr1, rx_desc->addr0, rx_desc->flags); ++ } ++} ++ ++static void mtk_hsdma_reset(struct mtk_hsdam_engine *hsdma, ++ struct mtk_hsdma_chan *chan) ++{ ++ int i; ++ ++ /* disable dma */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, 0); ++ ++ /* disable intr */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, 0); ++ ++ /* init desc value */ ++ for (i = 0; i < HSDMA_DESCS_NUM; i++) { ++ chan->tx_ring[i].addr0 = 0; ++ chan->tx_ring[i].flags = HSDMA_DESC_LS0 | ++ HSDMA_DESC_DONE; ++ } ++ for (i = 0; i < HSDMA_DESCS_NUM; i++) { ++ chan->rx_ring[i].addr0 = 0; ++ chan->rx_ring[i].flags = 0; ++ } ++ ++ /* reset */ ++ mtk_hsdma_reset_chan(hsdma, chan); ++ ++ /* enable intr */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, HSDMA_INT_RX_Q0); ++ ++ /* enable dma */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, HSDMA_GLO_DEFAULT); ++} ++ ++static int mtk_hsdma_terminate_all(struct dma_chan *c) ++{ ++ struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c); ++ struct mtk_hsdam_engine *hsdma = mtk_hsdma_chan_get_dev(chan); ++ unsigned long timeout; ++ LIST_HEAD(head); ++ ++ spin_lock_bh(&chan->vchan.lock); ++ chan->desc = NULL; ++ clear_bit(chan->id, &hsdma->chan_issued); ++ vchan_get_all_descriptors(&chan->vchan, &head); ++ spin_unlock_bh(&chan->vchan.lock); ++ ++ vchan_dma_desc_free_list(&chan->vchan, &head); ++ ++ /* wait dma transfer complete */ ++ timeout = jiffies + msecs_to_jiffies(2000); ++ while (mtk_hsdma_read(hsdma, HSDMA_REG_GLO_CFG) & ++ (HSDMA_GLO_RX_BUSY | HSDMA_GLO_TX_BUSY)) { ++ if (time_after_eq(jiffies, timeout)) { ++ hsdma_dump_desc(hsdma, chan); ++ mtk_hsdma_reset(hsdma, chan); ++ dev_err(hsdma->ddev.dev, "timeout, reset it\n"); ++ break; ++ } ++ cpu_relax(); ++ } ++ ++ return 0; ++} ++ ++static int mtk_hsdma_start_transfer(struct mtk_hsdam_engine *hsdma, ++ struct mtk_hsdma_chan *chan) ++{ ++ dma_addr_t src, dst; ++ size_t len, tlen; ++ struct hsdma_desc *tx_desc, *rx_desc; ++ struct mtk_hsdma_sg *sg; ++ unsigned int i; ++ int rx_idx; ++ ++ sg = &chan->desc->sg[0]; ++ len = sg->len; ++ chan->desc->num_sgs = DIV_ROUND_UP(len, HSDMA_MAX_PLEN); ++ ++ /* tx desc */ ++ src = sg->src_addr; ++ for (i = 0; i < chan->desc->num_sgs; i++) { ++ if (len > HSDMA_MAX_PLEN) ++ tlen = HSDMA_MAX_PLEN; ++ else ++ tlen = len; ++ ++ if (i & 0x1) { ++ tx_desc->addr1 = src; ++ tx_desc->flags |= HSDMA_DESC_PLEN1(tlen); ++ } else { ++ tx_desc = &chan->tx_ring[chan->tx_idx]; ++ tx_desc->addr0 = src; ++ tx_desc->flags = HSDMA_DESC_PLEN0(tlen); ++ ++ /* update index */ ++ chan->tx_idx = HSDMA_NEXT_DESC(chan->tx_idx); ++ } ++ ++ src += tlen; ++ len -= tlen; ++ } ++ if (i & 0x1) ++ tx_desc->flags |= HSDMA_DESC_LS0; ++ else ++ tx_desc->flags |= HSDMA_DESC_LS1; ++ ++ /* rx desc */ ++ rx_idx = HSDMA_NEXT_DESC(chan->rx_idx); ++ len = sg->len; ++ dst = sg->dst_addr; ++ for (i = 0; i < chan->desc->num_sgs; i++) { ++ rx_desc = &chan->rx_ring[rx_idx]; ++ if (len > HSDMA_MAX_PLEN) ++ tlen = HSDMA_MAX_PLEN; ++ else ++ tlen = len; ++ ++ rx_desc->addr0 = dst; ++ rx_desc->flags = HSDMA_DESC_PLEN0(tlen); ++ ++ dst += tlen; ++ len -= tlen; ++ ++ /* update index */ ++ rx_idx = HSDMA_NEXT_DESC(rx_idx); ++ } ++ ++ /* make sure desc and index all up to date */ ++ wmb(); ++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_CTX, chan->tx_idx); ++ ++ return 0; ++} ++ ++static int gdma_next_desc(struct mtk_hsdma_chan *chan) ++{ ++ struct virt_dma_desc *vdesc; ++ ++ vdesc = vchan_next_desc(&chan->vchan); ++ if (!vdesc) { ++ chan->desc = NULL; ++ return 0; ++ } ++ chan->desc = to_mtk_hsdma_desc(vdesc); ++ chan->next_sg = 0; ++ ++ return 1; ++} ++ ++static void mtk_hsdma_chan_done(struct mtk_hsdam_engine *hsdma, ++ struct mtk_hsdma_chan *chan) ++{ ++ struct mtk_hsdma_desc *desc; ++ int chan_issued; ++ ++ chan_issued = 0; ++ spin_lock_bh(&chan->vchan.lock); ++ desc = chan->desc; ++ if (likely(desc)) { ++ if (chan->next_sg == desc->num_sgs) { ++ list_del(&desc->vdesc.node); ++ vchan_cookie_complete(&desc->vdesc); ++ chan_issued = gdma_next_desc(chan); ++ } ++ } else ++ dev_dbg(hsdma->ddev.dev, "no desc to complete\n"); ++ ++ if (chan_issued) ++ set_bit(chan->id, &hsdma->chan_issued); ++ spin_unlock_bh(&chan->vchan.lock); ++} ++ ++static irqreturn_t mtk_hsdma_irq(int irq, void *devid) ++{ ++ struct mtk_hsdam_engine *hsdma = devid; ++ u32 status; ++ ++ status = mtk_hsdma_read(hsdma, HSDMA_REG_INT_STATUS); ++ if (unlikely(!status)) ++ return IRQ_NONE; ++ ++ if (likely(status & HSDMA_INT_RX_Q0)) ++ tasklet_schedule(&hsdma->task); ++ else ++ dev_dbg(hsdma->ddev.dev, "unhandle irq status %08x\n", ++ status); ++ /* clean intr bits */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_INT_STATUS, status); ++ ++ return IRQ_HANDLED; ++} ++ ++static void mtk_hsdma_issue_pending(struct dma_chan *c) ++{ ++ struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c); ++ struct mtk_hsdam_engine *hsdma = mtk_hsdma_chan_get_dev(chan); ++ ++ spin_lock_bh(&chan->vchan.lock); ++ if (vchan_issue_pending(&chan->vchan) && !chan->desc) { ++ if (gdma_next_desc(chan)) { ++ set_bit(chan->id, &hsdma->chan_issued); ++ tasklet_schedule(&hsdma->task); ++ } else ++ dev_dbg(hsdma->ddev.dev, "no desc to issue\n"); ++ } ++ spin_unlock_bh(&chan->vchan.lock); ++} ++ ++static struct dma_async_tx_descriptor * mtk_hsdma_prep_dma_memcpy( ++ struct dma_chan *c, dma_addr_t dest, dma_addr_t src, ++ size_t len, unsigned long flags) ++{ ++ struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c); ++ struct mtk_hsdma_desc *desc; ++ ++ if (len <= 0) ++ return NULL; ++ ++ desc = kzalloc(sizeof(struct mtk_hsdma_desc), GFP_ATOMIC); ++ if (!desc) { ++ dev_err(c->device->dev, "alloc memcpy decs error\n"); ++ return NULL; ++ } ++ ++ desc->sg[0].src_addr = src; ++ desc->sg[0].dst_addr = dest; ++ desc->sg[0].len = len; ++ ++ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); ++} ++ ++static enum dma_status mtk_hsdma_tx_status(struct dma_chan *c, ++ dma_cookie_t cookie, struct dma_tx_state *state) ++{ ++ return dma_cookie_status(c, cookie, state); ++} ++ ++static void mtk_hsdma_free_chan_resources(struct dma_chan *c) ++{ ++ vchan_free_chan_resources(to_virt_chan(c)); ++} ++ ++static void mtk_hsdma_desc_free(struct virt_dma_desc *vdesc) ++{ ++ kfree(container_of(vdesc, struct mtk_hsdma_desc, vdesc)); ++} ++ ++static void mtk_hsdma_tx(struct mtk_hsdam_engine *hsdma) ++{ ++ struct mtk_hsdma_chan *chan; ++ ++ if (test_and_clear_bit(0, &hsdma->chan_issued)) { ++ chan = &hsdma->chan[0]; ++ if (chan->desc) { ++ mtk_hsdma_start_transfer(hsdma, chan); ++ } else ++ dev_dbg(hsdma->ddev.dev,"chan 0 no desc to issue\n"); ++ } ++} ++ ++static void mtk_hsdma_rx(struct mtk_hsdam_engine *hsdma) ++{ ++ struct mtk_hsdma_chan *chan; ++ int next_idx, drx_idx, cnt; ++ ++ chan = &hsdma->chan[0]; ++ next_idx = HSDMA_NEXT_DESC(chan->rx_idx); ++ drx_idx = mtk_hsdma_read(hsdma, HSDMA_REG_RX_DRX); ++ ++ cnt = (drx_idx - next_idx) & HSDMA_DESCS_MASK; ++ if (!cnt) ++ return; ++ ++ chan->next_sg += cnt; ++ chan->rx_idx = (chan->rx_idx + cnt) & HSDMA_DESCS_MASK; ++ ++ /* update rx crx */ ++ wmb(); ++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_CRX, chan->rx_idx); ++ ++ mtk_hsdma_chan_done(hsdma, chan); ++} ++ ++static void mtk_hsdma_tasklet(unsigned long arg) ++{ ++ struct mtk_hsdam_engine *hsdma = (struct mtk_hsdam_engine *)arg; ++ ++ mtk_hsdma_rx(hsdma); ++ mtk_hsdma_tx(hsdma); ++} ++ ++static int mtk_hsdam_alloc_desc(struct mtk_hsdam_engine *hsdma, ++ struct mtk_hsdma_chan *chan) ++{ ++ int i; ++ ++ chan->tx_ring = dma_alloc_coherent(hsdma->ddev.dev, ++ 2 * HSDMA_DESCS_NUM * sizeof(*chan->tx_ring), ++ &chan->desc_addr, GFP_ATOMIC | __GFP_ZERO); ++ if (!chan->tx_ring) ++ goto no_mem; ++ ++ chan->rx_ring = &chan->tx_ring[HSDMA_DESCS_NUM]; ++ ++ /* init tx ring value */ ++ for (i = 0; i < HSDMA_DESCS_NUM; i++) ++ chan->tx_ring[i].flags = HSDMA_DESC_LS0 | HSDMA_DESC_DONE; ++ ++ return 0; ++no_mem: ++ return -ENOMEM; ++} ++ ++static void mtk_hsdam_free_desc(struct mtk_hsdam_engine *hsdma, ++ struct mtk_hsdma_chan *chan) ++{ ++ if (chan->tx_ring) { ++ dma_free_coherent(hsdma->ddev.dev, ++ 2 * HSDMA_DESCS_NUM * sizeof(*chan->tx_ring), ++ chan->tx_ring, chan->desc_addr); ++ chan->tx_ring = NULL; ++ chan->rx_ring = NULL; ++ } ++} ++ ++static int mtk_hsdma_init(struct mtk_hsdam_engine *hsdma) ++{ ++ struct mtk_hsdma_chan *chan; ++ int ret; ++ u32 reg; ++ ++ /* init desc */ ++ chan = &hsdma->chan[0]; ++ ret = mtk_hsdam_alloc_desc(hsdma, chan); ++ if (ret) ++ return ret; ++ ++ /* tx */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_BASE, chan->desc_addr); ++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_CNT, HSDMA_DESCS_NUM); ++ /* rx */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_BASE, chan->desc_addr + ++ (sizeof(struct hsdma_desc) * HSDMA_DESCS_NUM)); ++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_CNT, HSDMA_DESCS_NUM); ++ /* reset */ ++ mtk_hsdma_reset_chan(hsdma, chan); ++ ++ /* enable rx intr */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, HSDMA_INT_RX_Q0); ++ ++ /* enable dma */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, HSDMA_GLO_DEFAULT); ++ ++ /* hardware info */ ++ reg = mtk_hsdma_read(hsdma, HSDMA_REG_INFO); ++ dev_info(hsdma->ddev.dev, "rx: %d, tx: %d\n", ++ (reg >> HSDMA_INFO_RX_SHIFT) & HSDMA_INFO_RX_MASK, ++ (reg >> HSDMA_INFO_TX_SHIFT) & HSDMA_INFO_TX_MASK); ++ ++ hsdma_dump_reg(hsdma); ++ ++ return ret; ++} ++ ++static void mtk_hsdma_uninit(struct mtk_hsdam_engine *hsdma) ++{ ++ struct mtk_hsdma_chan *chan; ++ ++ /* disable dma */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, 0); ++ ++ /* disable intr */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, 0); ++ ++ /* free desc */ ++ chan = &hsdma->chan[0]; ++ mtk_hsdam_free_desc(hsdma, chan); ++ ++ /* tx */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_BASE, 0); ++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_CNT, 0); ++ /* rx */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_BASE, 0); ++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_CNT, 0); ++ /* reset */ ++ mtk_hsdma_reset_chan(hsdma, chan); ++} ++ ++static const struct of_device_id mtk_hsdma_of_match[] = { ++ { .compatible = "mediatek,mt7621-hsdma" }, ++ { }, ++}; ++ ++static int mtk_hsdma_probe(struct platform_device *pdev) ++{ ++ const struct of_device_id *match; ++ struct mtk_hsdma_chan *chan; ++ struct mtk_hsdam_engine *hsdma; ++ struct dma_device *dd; ++ struct resource *res; ++ int ret; ++ int irq; ++ void __iomem *base; ++ ++ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); ++ if (ret) ++ return ret; ++ ++ match = of_match_device(mtk_hsdma_of_match, &pdev->dev); ++ if (!match) ++ return -EINVAL; ++ ++ hsdma = devm_kzalloc(&pdev->dev, sizeof(*hsdma), GFP_KERNEL); ++ if (!hsdma) { ++ dev_err(&pdev->dev, "alloc dma device failed\n"); ++ return -EINVAL; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ hsdma->base = base + HSDMA_BASE_OFFSET; ++ tasklet_init(&hsdma->task, mtk_hsdma_tasklet, (unsigned long)hsdma); ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, "failed to get irq\n"); ++ return -EINVAL; ++ } ++ ret = devm_request_irq(&pdev->dev, irq, mtk_hsdma_irq, ++ 0, dev_name(&pdev->dev), hsdma); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to request irq\n"); ++ return ret; ++ } ++ ++ device_reset(&pdev->dev); ++ ++ dd = &hsdma->ddev; ++ dma_cap_set(DMA_MEMCPY, dd->cap_mask); ++ dd->copy_align = HSDMA_ALIGN_SIZE; ++ dd->device_free_chan_resources = mtk_hsdma_free_chan_resources; ++ dd->device_prep_dma_memcpy = mtk_hsdma_prep_dma_memcpy; ++ dd->device_terminate_all = mtk_hsdma_terminate_all; ++ dd->device_tx_status = mtk_hsdma_tx_status; ++ dd->device_issue_pending = mtk_hsdma_issue_pending; ++ dd->dev = &pdev->dev; ++ dd->dev->dma_parms = &hsdma->dma_parms; ++ dma_set_max_seg_size(dd->dev, HSDMA_MAX_PLEN); ++ INIT_LIST_HEAD(&dd->channels); ++ ++ chan = &hsdma->chan[0]; ++ chan->id = 0; ++ chan->vchan.desc_free = mtk_hsdma_desc_free; ++ vchan_init(&chan->vchan, dd); ++ ++ /* init hardware */ ++ ret = mtk_hsdma_init(hsdma); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to alloc ring descs\n"); ++ return ret; ++ } ++ ++ ret = dma_async_device_register(dd); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to register dma device\n"); ++ return ret; ++ } ++ ++ ret = of_dma_controller_register(pdev->dev.of_node, ++ of_dma_xlate_by_chan_id, hsdma); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to register of dma controller\n"); ++ goto err_unregister; ++ } ++ ++ platform_set_drvdata(pdev, hsdma); ++ ++ return 0; ++ ++err_unregister: ++ dma_async_device_unregister(dd); ++ return ret; ++} ++ ++static int mtk_hsdma_remove(struct platform_device *pdev) ++{ ++ struct mtk_hsdam_engine *hsdma = platform_get_drvdata(pdev); ++ ++ mtk_hsdma_uninit(hsdma); ++ ++ of_dma_controller_free(pdev->dev.of_node); ++ dma_async_device_unregister(&hsdma->ddev); ++ ++ return 0; ++} ++ ++static struct platform_driver mtk_hsdma_driver = { ++ .probe = mtk_hsdma_probe, ++ .remove = mtk_hsdma_remove, ++ .driver = { ++ .name = "hsdma-mt7621", ++ .of_match_table = mtk_hsdma_of_match, ++ }, ++}; ++module_platform_driver(mtk_hsdma_driver); ++ ++MODULE_AUTHOR("Michael Lee "); ++MODULE_DESCRIPTION("MTK HSDMA driver"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ramips/patches-4.14/0048-asoc-add-mt7620-support.patch b/target/linux/ramips/patches-4.14/0048-asoc-add-mt7620-support.patch new file mode 100644 index 000000000..5f105c69e --- /dev/null +++ b/target/linux/ramips/patches-4.14/0048-asoc-add-mt7620-support.patch @@ -0,0 +1,1046 @@ +From 7f29222b1731e8182ba94a331531dec18865a1e4 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 09:31:47 +0100 +Subject: [PATCH 48/53] asoc: add mt7620 support + +Signed-off-by: John Crispin +--- + arch/mips/ralink/of.c | 2 + + sound/soc/Kconfig | 1 + + sound/soc/Makefile | 1 + + sound/soc/ralink/Kconfig | 15 ++ + sound/soc/ralink/Makefile | 11 + + sound/soc/ralink/mt7620-i2s.c | 436 ++++++++++++++++++++++++++++++++++++++ + sound/soc/ralink/mt7620-wm8960.c | 233 ++++++++++++++++++++ + 7 files changed, 699 insertions(+) + create mode 100644 sound/soc/ralink/Kconfig + create mode 100644 sound/soc/ralink/Makefile + create mode 100644 sound/soc/ralink/mt7620-i2s.c + create mode 100644 sound/soc/ralink/mt7620-wm8960.c + +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -26,6 +27,7 @@ + #include "common.h" + + __iomem void *rt_sysc_membase; ++EXPORT_SYMBOL(rt_sysc_membase); + __iomem void *rt_memc_membase; + + __iomem void *plat_of_remap_node(const char *node) +--- a/sound/soc/Kconfig ++++ b/sound/soc/Kconfig +@@ -59,6 +59,7 @@ source "sound/soc/mxs/Kconfig" + source "sound/soc/pxa/Kconfig" + source "sound/soc/qcom/Kconfig" + source "sound/soc/rockchip/Kconfig" ++source "sound/soc/ralink/Kconfig" + source "sound/soc/samsung/Kconfig" + source "sound/soc/sh/Kconfig" + source "sound/soc/sirf/Kconfig" +--- a/sound/soc/Makefile ++++ b/sound/soc/Makefile +@@ -40,6 +40,7 @@ obj-$(CONFIG_SND_SOC) += kirkwood/ + obj-$(CONFIG_SND_SOC) += pxa/ + obj-$(CONFIG_SND_SOC) += qcom/ + obj-$(CONFIG_SND_SOC) += rockchip/ ++obj-$(CONFIG_SND_SOC) += ralink/ + obj-$(CONFIG_SND_SOC) += samsung/ + obj-$(CONFIG_SND_SOC) += sh/ + obj-$(CONFIG_SND_SOC) += sirf/ +--- /dev/null ++++ b/sound/soc/ralink/Kconfig +@@ -0,0 +1,8 @@ ++config SND_RALINK_SOC_I2S ++ depends on RALINK && SND_SOC && !SOC_RT288X ++ select SND_SOC_GENERIC_DMAENGINE_PCM ++ select REGMAP_MMIO ++ tristate "SoC Audio (I2S protocol) for Ralink SoC" ++ help ++ Say Y if you want to use I2S protocol and I2S codec on Ralink/MediaTek ++ based boards. +--- /dev/null ++++ b/sound/soc/ralink/Makefile +@@ -0,0 +1,6 @@ ++# ++# Ralink/MediaTek Platform Support ++# ++snd-soc-ralink-i2s-objs := ralink-i2s.o ++ ++obj-$(CONFIG_SND_RALINK_SOC_I2S) += snd-soc-ralink-i2s.o +--- /dev/null ++++ b/sound/soc/ralink/ralink-i2s.c +@@ -0,0 +1,965 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen ++ * Copyright (C) 2016 Michael Lee ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define DRV_NAME "ralink-i2s" ++ ++#define I2S_REG_CFG0 0x00 ++#define I2S_REG_INT_STATUS 0x04 ++#define I2S_REG_INT_EN 0x08 ++#define I2S_REG_FF_STATUS 0x0c ++#define I2S_REG_WREG 0x10 ++#define I2S_REG_RREG 0x14 ++#define I2S_REG_CFG1 0x18 ++#define I2S_REG_DIVCMP 0x20 ++#define I2S_REG_DIVINT 0x24 ++ ++/* I2S_REG_CFG0 */ ++#define I2S_REG_CFG0_EN BIT(31) ++#define I2S_REG_CFG0_DMA_EN BIT(30) ++#define I2S_REG_CFG0_BYTE_SWAP BIT(28) ++#define I2S_REG_CFG0_TX_EN BIT(24) ++#define I2S_REG_CFG0_RX_EN BIT(20) ++#define I2S_REG_CFG0_SLAVE BIT(16) ++#define I2S_REG_CFG0_RX_THRES 12 ++#define I2S_REG_CFG0_TX_THRES 4 ++#define I2S_REG_CFG0_THRES_MASK (0xf << I2S_REG_CFG0_RX_THRES) | \ ++ (4 << I2S_REG_CFG0_TX_THRES) ++#define I2S_REG_CFG0_DFT_THRES (4 << I2S_REG_CFG0_RX_THRES) | \ ++ (4 << I2S_REG_CFG0_TX_THRES) ++/* RT305x */ ++#define I2S_REG_CFG0_CLK_DIS BIT(8) ++#define I2S_REG_CFG0_TXCH_SWAP BIT(3) ++#define I2S_REG_CFG0_TXCH1_OFF BIT(2) ++#define I2S_REG_CFG0_TXCH0_OFF BIT(1) ++#define I2S_REG_CFG0_SLAVE_EN BIT(0) ++/* RT3883 */ ++#define I2S_REG_CFG0_RXCH_SWAP BIT(11) ++#define I2S_REG_CFG0_RXCH1_OFF BIT(10) ++#define I2S_REG_CFG0_RXCH0_OFF BIT(9) ++#define I2S_REG_CFG0_WS_INV BIT(0) ++/* MT7628 */ ++#define I2S_REG_CFG0_FMT_LE BIT(29) ++#define I2S_REG_CFG0_SYS_BE BIT(28) ++#define I2S_REG_CFG0_NORM_24 BIT(18) ++#define I2S_REG_CFG0_DATA_24 BIT(17) ++ ++/* I2S_REG_INT_STATUS */ ++#define I2S_REG_INT_RX_FAULT BIT(7) ++#define I2S_REG_INT_RX_OVRUN BIT(6) ++#define I2S_REG_INT_RX_UNRUN BIT(5) ++#define I2S_REG_INT_RX_THRES BIT(4) ++#define I2S_REG_INT_TX_FAULT BIT(3) ++#define I2S_REG_INT_TX_OVRUN BIT(2) ++#define I2S_REG_INT_TX_UNRUN BIT(1) ++#define I2S_REG_INT_TX_THRES BIT(0) ++#define I2S_REG_INT_TX_MASK 0xf ++#define I2S_REG_INT_RX_MASK 0xf0 ++ ++/* I2S_REG_INT_STATUS */ ++#define I2S_RX_AVCNT(x) ((x >> 4) & 0xf) ++#define I2S_TX_AVCNT(x) (x & 0xf) ++/* MT7628 */ ++#define MT7628_I2S_RX_AVCNT(x) ((x >> 8) & 0x1f) ++#define MT7628_I2S_TX_AVCNT(x) (x & 0x1f) ++ ++/* I2S_REG_CFG1 */ ++#define I2S_REG_CFG1_LBK BIT(31) ++#define I2S_REG_CFG1_EXTLBK BIT(30) ++/* RT3883 */ ++#define I2S_REG_CFG1_LEFT_J BIT(0) ++#define I2S_REG_CFG1_RIGHT_J BIT(1) ++#define I2S_REG_CFG1_FMT_MASK 0x3 ++ ++/* I2S_REG_DIVCMP */ ++#define I2S_REG_DIVCMP_CLKEN BIT(31) ++#define I2S_REG_DIVCMP_DIVCOMP_MASK 0x1ff ++ ++/* I2S_REG_DIVINT */ ++#define I2S_REG_DIVINT_MASK 0x3ff ++ ++/* BCLK dividers */ ++#define RALINK_I2S_DIVCMP 0 ++#define RALINK_I2S_DIVINT 1 ++ ++/* FIFO */ ++#define RALINK_I2S_FIFO_SIZE 32 ++ ++/* feature flags */ ++#define RALINK_FLAGS_TXONLY BIT(0) ++#define RALINK_FLAGS_LEFT_J BIT(1) ++#define RALINK_FLAGS_RIGHT_J BIT(2) ++#define RALINK_FLAGS_ENDIAN BIT(3) ++#define RALINK_FLAGS_24BIT BIT(4) ++ ++#define RALINK_I2S_INT_EN 0 ++ ++struct ralink_i2s_stats { ++ u32 dmafault; ++ u32 overrun; ++ u32 underrun; ++ u32 belowthres; ++}; ++ ++struct ralink_i2s { ++ struct device *dev; ++ void __iomem *regs; ++ struct clk *clk; ++ struct regmap *regmap; ++ u32 flags; ++ unsigned int fmt; ++ u16 txdma_req; ++ u16 rxdma_req; ++ ++ struct snd_dmaengine_dai_dma_data playback_dma_data; ++ struct snd_dmaengine_dai_dma_data capture_dma_data; ++ ++ struct dentry *dbg_dir; ++ struct dentry *dbg_stats; ++ struct ralink_i2s_stats txstats; ++ struct ralink_i2s_stats rxstats; ++}; ++ ++static void ralink_i2s_dump_regs(struct ralink_i2s *i2s) ++{ ++ u32 buf[10]; ++ int ret; ++ ++ ret = regmap_bulk_read(i2s->regmap, I2S_REG_CFG0, ++ buf, ARRAY_SIZE(buf)); ++ ++ dev_dbg(i2s->dev, "CFG0: %08x, INTSTAT: %08x, INTEN: %08x, " \ ++ "FFSTAT: %08x, WREG: %08x, RREG: %08x, " \ ++ "CFG1: %08x, DIVCMP: %08x, DIVINT: %08x\n", ++ buf[0], buf[1], buf[2], buf[3], buf[4], ++ buf[5], buf[6], buf[8], buf[9]); ++} ++ ++static int ralink_i2s_set_sysclk(struct snd_soc_dai *dai, ++ int clk_id, unsigned int freq, int dir) ++{ ++ return 0; ++} ++ ++static int ralink_i2s_set_sys_bclk(struct snd_soc_dai *dai, int width, int rate) ++{ ++ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ unsigned long clk = clk_get_rate(i2s->clk); ++ int div; ++ uint32_t data; ++ ++ /* disable clock at slave mode */ ++ if ((i2s->fmt & SND_SOC_DAIFMT_MASTER_MASK) == ++ SND_SOC_DAIFMT_CBM_CFM) { ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_CLK_DIS, ++ I2S_REG_CFG0_CLK_DIS); ++ return 0; ++ } ++ ++ /* FREQOUT = FREQIN / (I2S_CLK_DIV + 1) */ ++ div = (clk / rate ) - 1; ++ ++ data = rt_sysc_r32(0x30); ++ data &= (0xff << 8); ++ data |= (0x1 << 15) | (div << 8); ++ rt_sysc_w32(data, 0x30); ++ ++ /* enable clock */ ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, I2S_REG_CFG0_CLK_DIS, 0); ++ ++ dev_dbg(i2s->dev, "clk: %lu, rate: %u, div: %d\n", ++ clk, rate, div); ++ ++ return 0; ++} ++ ++static int ralink_i2s_set_bclk(struct snd_soc_dai *dai, int width, int rate) ++{ ++ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ unsigned long clk = clk_get_rate(i2s->clk); ++ int divint, divcomp; ++ ++ /* disable clock at slave mode */ ++ if ((i2s->fmt & SND_SOC_DAIFMT_MASTER_MASK) == ++ SND_SOC_DAIFMT_CBM_CFM) { ++ regmap_update_bits(i2s->regmap, I2S_REG_DIVCMP, ++ I2S_REG_DIVCMP_CLKEN, 0); ++ return 0; ++ } ++ ++ /* FREQOUT = FREQIN * (1/2) * (1/(DIVINT + DIVCOMP/512)) */ ++ clk = clk / (2 * 2 * width); ++ divint = clk / rate; ++ divcomp = ((clk % rate) * 512) / rate; ++ ++ if ((divint > I2S_REG_DIVINT_MASK) || ++ (divcomp > I2S_REG_DIVCMP_DIVCOMP_MASK)) ++ return -EINVAL; ++ ++ regmap_update_bits(i2s->regmap, I2S_REG_DIVINT, ++ I2S_REG_DIVINT_MASK, divint); ++ regmap_update_bits(i2s->regmap, I2S_REG_DIVCMP, ++ I2S_REG_DIVCMP_DIVCOMP_MASK, divcomp); ++ ++ /* enable clock */ ++ regmap_update_bits(i2s->regmap, I2S_REG_DIVCMP, I2S_REG_DIVCMP_CLKEN, ++ I2S_REG_DIVCMP_CLKEN); ++ ++ dev_dbg(i2s->dev, "clk: %lu, rate: %u, int: %d, comp: %d\n", ++ clk_get_rate(i2s->clk), rate, divint, divcomp); ++ ++ return 0; ++} ++ ++static int ralink_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) ++{ ++ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ unsigned int cfg0 = 0, cfg1 = 0; ++ ++ /* set master/slave audio interface */ ++ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { ++ case SND_SOC_DAIFMT_CBM_CFM: ++ if (i2s->flags & RALINK_FLAGS_TXONLY) ++ cfg0 |= I2S_REG_CFG0_SLAVE_EN; ++ else ++ cfg0 |= I2S_REG_CFG0_SLAVE; ++ break; ++ case SND_SOC_DAIFMT_CBS_CFS: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* interface format */ ++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { ++ case SND_SOC_DAIFMT_I2S: ++ break; ++ case SND_SOC_DAIFMT_RIGHT_J: ++ if (i2s->flags & RALINK_FLAGS_RIGHT_J) { ++ cfg1 |= I2S_REG_CFG1_RIGHT_J; ++ break; ++ } ++ return -EINVAL; ++ case SND_SOC_DAIFMT_LEFT_J: ++ if (i2s->flags & RALINK_FLAGS_LEFT_J) { ++ cfg1 |= I2S_REG_CFG1_LEFT_J; ++ break; ++ } ++ return -EINVAL; ++ default: ++ return -EINVAL; ++ } ++ ++ /* clock inversion */ ++ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { ++ case SND_SOC_DAIFMT_NB_NF: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (i2s->flags & RALINK_FLAGS_TXONLY) { ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_SLAVE_EN, cfg0); ++ } else { ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_SLAVE, cfg0); ++ } ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG1, ++ I2S_REG_CFG1_FMT_MASK, cfg1); ++ i2s->fmt = fmt; ++ ++ return 0; ++} ++ ++static int ralink_i2s_startup(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ ++ if (dai->active) ++ return 0; ++ ++ /* setup status interrupt */ ++#if (RALINK_I2S_INT_EN) ++ regmap_write(i2s->regmap, I2S_REG_INT_EN, 0xff); ++#else ++ regmap_write(i2s->regmap, I2S_REG_INT_EN, 0x0); ++#endif ++ ++ /* enable */ ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_EN | I2S_REG_CFG0_DMA_EN | ++ I2S_REG_CFG0_THRES_MASK, ++ I2S_REG_CFG0_EN | I2S_REG_CFG0_DMA_EN | ++ I2S_REG_CFG0_DFT_THRES); ++ ++ return 0; ++} ++ ++static void ralink_i2s_shutdown(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ ++ /* If both streams are stopped, disable module and clock */ ++ if (dai->active) ++ return; ++ ++ /* ++ * datasheet mention when disable all control regs are cleared ++ * to initial values. need reinit at startup. ++ */ ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, I2S_REG_CFG0_EN, 0); ++} ++ ++static int ralink_i2s_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) ++{ ++ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ int width; ++ int ret; ++ ++ width = params_width(params); ++ switch (width) { ++ case 16: ++ if (i2s->flags & RALINK_FLAGS_24BIT) ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_DATA_24, 0); ++ break; ++ case 24: ++ if (i2s->flags & RALINK_FLAGS_24BIT) { ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_DATA_24, ++ I2S_REG_CFG0_DATA_24); ++ break; ++ } ++ return -EINVAL; ++ default: ++ return -EINVAL; ++ } ++ ++ switch (params_channels(params)) { ++ case 2: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (i2s->flags & RALINK_FLAGS_ENDIAN) { ++ /* system endian */ ++#ifdef SNDRV_LITTLE_ENDIAN ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_SYS_BE, 0); ++#else ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_SYS_BE, ++ I2S_REG_CFG0_SYS_BE); ++#endif ++ ++ /* data endian */ ++ switch (params_format(params)) { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ case SNDRV_PCM_FORMAT_S24_LE: ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_FMT_LE, ++ I2S_REG_CFG0_FMT_LE); ++ break; ++ case SNDRV_PCM_FORMAT_S16_BE: ++ case SNDRV_PCM_FORMAT_S24_BE: ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_FMT_LE, 0); ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ /* setup bclk rate */ ++ if (i2s->flags & RALINK_FLAGS_TXONLY) ++ ret = ralink_i2s_set_sys_bclk(dai, width, params_rate(params)); ++ else ++ ret = ralink_i2s_set_bclk(dai, width, params_rate(params)); ++ ++ return ret; ++} ++ ++static int ralink_i2s_trigger(struct snd_pcm_substream *substream, int cmd, ++ struct snd_soc_dai *dai) ++{ ++ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ unsigned int mask, val; ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ mask = I2S_REG_CFG0_TX_EN; ++ else ++ mask = I2S_REG_CFG0_RX_EN; ++ ++ switch (cmd) { ++ case SNDRV_PCM_TRIGGER_START: ++ case SNDRV_PCM_TRIGGER_RESUME: ++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ val = mask; ++ break; ++ case SNDRV_PCM_TRIGGER_STOP: ++ case SNDRV_PCM_TRIGGER_SUSPEND: ++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ++ val = 0; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, mask, val); ++ ++ return 0; ++} ++ ++static void ralink_i2s_init_dma_data(struct ralink_i2s *i2s, ++ struct resource *res) ++{ ++ struct snd_dmaengine_dai_dma_data *dma_data; ++ ++ /* Playback */ ++ dma_data = &i2s->playback_dma_data; ++ dma_data->addr = res->start + I2S_REG_WREG; ++ dma_data->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ dma_data->maxburst = 1; ++ dma_data->slave_id = i2s->txdma_req; ++ ++ if (i2s->flags & RALINK_FLAGS_TXONLY) ++ return; ++ ++ /* Capture */ ++ dma_data = &i2s->capture_dma_data; ++ dma_data->addr = res->start + I2S_REG_RREG; ++ dma_data->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ dma_data->maxburst = 1; ++ dma_data->slave_id = i2s->rxdma_req; ++} ++ ++static int ralink_i2s_dai_probe(struct snd_soc_dai *dai) ++{ ++ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ ++ snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, ++ &i2s->capture_dma_data); ++ ++ return 0; ++} ++ ++static int ralink_i2s_dai_remove(struct snd_soc_dai *dai) ++{ ++ return 0; ++} ++ ++static const struct snd_soc_dai_ops ralink_i2s_dai_ops = { ++ .set_sysclk = ralink_i2s_set_sysclk, ++ .set_fmt = ralink_i2s_set_fmt, ++ .startup = ralink_i2s_startup, ++ .shutdown = ralink_i2s_shutdown, ++ .hw_params = ralink_i2s_hw_params, ++ .trigger = ralink_i2s_trigger, ++}; ++ ++static struct snd_soc_dai_driver ralink_i2s_dai = { ++ .name = DRV_NAME, ++ .probe = ralink_i2s_dai_probe, ++ .remove = ralink_i2s_dai_remove, ++ .ops = &ralink_i2s_dai_ops, ++ .capture = { ++ .stream_name = "I2S Capture", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rate_min = 5512, ++ .rate_max = 192000, ++ .rates = SNDRV_PCM_RATE_CONTINUOUS, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ }, ++ .playback = { ++ .stream_name = "I2S Playback", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rate_min = 5512, ++ .rate_max = 192000, ++ .rates = SNDRV_PCM_RATE_CONTINUOUS, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ }, ++ .symmetric_rates = 1, ++}; ++ ++static struct snd_pcm_hardware ralink_pcm_hardware = { ++ .info = SNDRV_PCM_INFO_MMAP | ++ SNDRV_PCM_INFO_MMAP_VALID | ++ SNDRV_PCM_INFO_INTERLEAVED | ++ SNDRV_PCM_INFO_BLOCK_TRANSFER, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ .channels_min = 2, ++ .channels_max = 2, ++ .period_bytes_min = PAGE_SIZE, ++ .period_bytes_max = PAGE_SIZE * 2, ++ .periods_min = 2, ++ .periods_max = 128, ++ .buffer_bytes_max = 128 * 1024, ++ .fifo_size = RALINK_I2S_FIFO_SIZE, ++}; ++ ++static const struct snd_dmaengine_pcm_config ralink_dmaengine_pcm_config = { ++ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, ++ .pcm_hardware = &ralink_pcm_hardware, ++ .prealloc_buffer_size = 256 * PAGE_SIZE, ++}; ++ ++static const struct snd_soc_component_driver ralink_i2s_component = { ++ .name = DRV_NAME, ++}; ++ ++static bool ralink_i2s_readable_reg(struct device *dev, unsigned int reg) ++{ ++ return true; ++} ++ ++static bool ralink_i2s_volatile_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case I2S_REG_INT_STATUS: ++ case I2S_REG_FF_STATUS: ++ return true; ++ } ++ return false; ++} ++ ++static bool ralink_i2s_writeable_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case I2S_REG_FF_STATUS: ++ case I2S_REG_RREG: ++ return false; ++ } ++ return true; ++} ++ ++static const struct regmap_config ralink_i2s_regmap_config = { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .writeable_reg = ralink_i2s_writeable_reg, ++ .readable_reg = ralink_i2s_readable_reg, ++ .volatile_reg = ralink_i2s_volatile_reg, ++ .max_register = I2S_REG_DIVINT, ++}; ++ ++#if (RALINK_I2S_INT_EN) ++static irqreturn_t ralink_i2s_irq(int irq, void *devid) ++{ ++ struct ralink_i2s *i2s = devid; ++ u32 status; ++ ++ regmap_read(i2s->regmap, I2S_REG_INT_STATUS, &status); ++ if (unlikely(!status)) ++ return IRQ_NONE; ++ ++ /* tx stats */ ++ if (status & I2S_REG_INT_TX_MASK) { ++ if (status & I2S_REG_INT_TX_THRES) ++ i2s->txstats.belowthres++; ++ if (status & I2S_REG_INT_TX_UNRUN) ++ i2s->txstats.underrun++; ++ if (status & I2S_REG_INT_TX_OVRUN) ++ i2s->txstats.overrun++; ++ if (status & I2S_REG_INT_TX_FAULT) ++ i2s->txstats.dmafault++; ++ } ++ ++ /* rx stats */ ++ if (status & I2S_REG_INT_RX_MASK) { ++ if (status & I2S_REG_INT_RX_THRES) ++ i2s->rxstats.belowthres++; ++ if (status & I2S_REG_INT_RX_UNRUN) ++ i2s->rxstats.underrun++; ++ if (status & I2S_REG_INT_RX_OVRUN) ++ i2s->rxstats.overrun++; ++ if (status & I2S_REG_INT_RX_FAULT) ++ i2s->rxstats.dmafault++; ++ } ++ ++ /* clean status bits */ ++ regmap_write(i2s->regmap, I2S_REG_INT_STATUS, status); ++ ++ return IRQ_HANDLED; ++} ++#endif ++ ++#if IS_ENABLED(CONFIG_DEBUG_FS) ++static int ralink_i2s_stats_show(struct seq_file *s, void *unused) ++{ ++ struct ralink_i2s *i2s = s->private; ++ ++ seq_printf(s, "tx stats\n"); ++ seq_printf(s, "\tbelow threshold\t%u\n", i2s->txstats.belowthres); ++ seq_printf(s, "\tunder run\t%u\n", i2s->txstats.underrun); ++ seq_printf(s, "\tover run\t%u\n", i2s->txstats.overrun); ++ seq_printf(s, "\tdma fault\t%u\n", i2s->txstats.dmafault); ++ ++ seq_printf(s, "rx stats\n"); ++ seq_printf(s, "\tbelow threshold\t%u\n", i2s->rxstats.belowthres); ++ seq_printf(s, "\tunder run\t%u\n", i2s->rxstats.underrun); ++ seq_printf(s, "\tover run\t%u\n", i2s->rxstats.overrun); ++ seq_printf(s, "\tdma fault\t%u\n", i2s->rxstats.dmafault); ++ ++ ralink_i2s_dump_regs(i2s); ++ ++ return 0; ++} ++ ++static int ralink_i2s_stats_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, ralink_i2s_stats_show, inode->i_private); ++} ++ ++static const struct file_operations ralink_i2s_stats_ops = { ++ .open = ralink_i2s_stats_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static inline int ralink_i2s_debugfs_create(struct ralink_i2s *i2s) ++{ ++ i2s->dbg_dir = debugfs_create_dir(dev_name(i2s->dev), NULL); ++ if (!i2s->dbg_dir) ++ return -ENOMEM; ++ ++ i2s->dbg_stats = debugfs_create_file("stats", S_IRUGO, ++ i2s->dbg_dir, i2s, &ralink_i2s_stats_ops); ++ if (!i2s->dbg_stats) { ++ debugfs_remove(i2s->dbg_dir); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++static inline void ralink_i2s_debugfs_remove(struct ralink_i2s *i2s) ++{ ++ debugfs_remove(i2s->dbg_stats); ++ debugfs_remove(i2s->dbg_dir); ++} ++#else ++static inline int ralink_i2s_debugfs_create(struct ralink_i2s *i2s) ++{ ++ return 0; ++} ++ ++static inline void ralink_i2s_debugfs_remove(struct fsl_ssi_dbg *ssi_dbg) ++{ ++} ++#endif ++ ++/* ++ * TODO: these refclk setup functions should use ++ * clock framework instead. hardcode it now. ++ */ ++static void rt3350_refclk_setup(void) ++{ ++ uint32_t data; ++ ++ /* set refclk output 12Mhz clock */ ++ data = rt_sysc_r32(0x2c); ++ data |= (0x1 << 8); ++ rt_sysc_w32(data, 0x2c); ++} ++ ++static void rt3883_refclk_setup(void) ++{ ++ uint32_t data; ++ ++ /* set refclk output 12Mhz clock */ ++ data = rt_sysc_r32(0x2c); ++ data &= ~(0x3 << 13); ++ data |= (0x1 << 13); ++ rt_sysc_w32(data, 0x2c); ++} ++ ++static void rt3552_refclk_setup(void) ++{ ++ uint32_t data; ++ ++ /* set refclk output 12Mhz clock */ ++ data = rt_sysc_r32(0x2c); ++ data &= ~(0xf << 8); ++ data |= (0x3 << 8); ++ rt_sysc_w32(data, 0x2c); ++} ++ ++static void mt7620_refclk_setup(void) ++{ ++ uint32_t data; ++ ++ /* set refclk output 12Mhz clock */ ++ data = rt_sysc_r32(0x2c); ++ data &= ~(0x7 << 9); ++ data |= 0x1 << 9; ++ rt_sysc_w32(data, 0x2c); ++} ++ ++static void mt7621_refclk_setup(void) ++{ ++ uint32_t data; ++ ++ /* set refclk output 12Mhz clock */ ++ data = rt_sysc_r32(0x2c); ++ data &= ~(0x1f << 18); ++ data |= (0x19 << 18); ++ data &= ~(0x1f << 12); ++ data |= (0x1 << 12); ++ data &= ~(0x7 << 9); ++ data |= (0x5 << 9); ++ rt_sysc_w32(data, 0x2c); ++} ++ ++static void mt7628_refclk_setup(void) ++{ ++ uint32_t data; ++ ++ /* set i2s and refclk digital pad */ ++ data = rt_sysc_r32(0x3c); ++ data |= 0x1f; ++ rt_sysc_w32(data, 0x3c); ++ ++ /* Adjust REFCLK0's driving strength */ ++ data = rt_sysc_r32(0x1354); ++ data &= ~(0x1 << 5); ++ rt_sysc_w32(data, 0x1354); ++ data = rt_sysc_r32(0x1364); ++ data |= ~(0x1 << 5); ++ rt_sysc_w32(data, 0x1364); ++ ++ /* set refclk output 12Mhz clock */ ++ data = rt_sysc_r32(0x2c); ++ data &= ~(0x7 << 9); ++ data |= 0x1 << 9; ++ rt_sysc_w32(data, 0x2c); ++} ++ ++struct rt_i2s_data { ++ u32 flags; ++ void (*refclk_setup)(void); ++}; ++ ++struct rt_i2s_data rt3050_i2s_data = { .flags = RALINK_FLAGS_TXONLY }; ++struct rt_i2s_data rt3350_i2s_data = { .flags = RALINK_FLAGS_TXONLY, ++ .refclk_setup = rt3350_refclk_setup }; ++struct rt_i2s_data rt3883_i2s_data = { ++ .flags = (RALINK_FLAGS_LEFT_J | RALINK_FLAGS_RIGHT_J), ++ .refclk_setup = rt3883_refclk_setup }; ++struct rt_i2s_data rt3352_i2s_data = { .refclk_setup = rt3552_refclk_setup}; ++struct rt_i2s_data mt7620_i2s_data = { .refclk_setup = mt7620_refclk_setup}; ++struct rt_i2s_data mt7621_i2s_data = { .refclk_setup = mt7621_refclk_setup}; ++struct rt_i2s_data mt7628_i2s_data = { ++ .flags = (RALINK_FLAGS_ENDIAN | RALINK_FLAGS_24BIT | ++ RALINK_FLAGS_LEFT_J), ++ .refclk_setup = mt7628_refclk_setup}; ++ ++static const struct of_device_id ralink_i2s_match_table[] = { ++ { .compatible = "ralink,rt3050-i2s", ++ .data = (void *)&rt3050_i2s_data }, ++ { .compatible = "ralink,rt3350-i2s", ++ .data = (void *)&rt3350_i2s_data }, ++ { .compatible = "ralink,rt3883-i2s", ++ .data = (void *)&rt3883_i2s_data }, ++ { .compatible = "ralink,rt3352-i2s", ++ .data = (void *)&rt3352_i2s_data }, ++ { .compatible = "mediatek,mt7620-i2s", ++ .data = (void *)&mt7620_i2s_data }, ++ { .compatible = "mediatek,mt7621-i2s", ++ .data = (void *)&mt7621_i2s_data }, ++ { .compatible = "mediatek,mt7628-i2s", ++ .data = (void *)&mt7628_i2s_data }, ++}; ++MODULE_DEVICE_TABLE(of, ralink_i2s_match_table); ++ ++static int ralink_i2s_probe(struct platform_device *pdev) ++{ ++ const struct of_device_id *match; ++ struct device_node *np = pdev->dev.of_node; ++ struct ralink_i2s *i2s; ++ struct resource *res; ++ int irq, ret; ++ u32 dma_req; ++ struct rt_i2s_data *data; ++ ++ i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); ++ if (!i2s) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, i2s); ++ i2s->dev = &pdev->dev; ++ ++ match = of_match_device(ralink_i2s_match_table, &pdev->dev); ++ if (!match) ++ return -EINVAL; ++ data = (struct rt_i2s_data *)match->data; ++ i2s->flags = data->flags; ++ /* setup out 12Mhz refclk to codec as mclk */ ++ if (data->refclk_setup) ++ data->refclk_setup(); ++ ++ if (of_property_read_u32(np, "txdma-req", &dma_req)) { ++ dev_err(&pdev->dev, "no txdma-req define\n"); ++ return -EINVAL; ++ } ++ i2s->txdma_req = (u16)dma_req; ++ if (!(i2s->flags & RALINK_FLAGS_TXONLY)) { ++ if (of_property_read_u32(np, "rxdma-req", &dma_req)) { ++ dev_err(&pdev->dev, "no rxdma-req define\n"); ++ return -EINVAL; ++ } ++ i2s->rxdma_req = (u16)dma_req; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ i2s->regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(i2s->regs)) ++ return PTR_ERR(i2s->regs); ++ ++ i2s->regmap = devm_regmap_init_mmio(&pdev->dev, i2s->regs, ++ &ralink_i2s_regmap_config); ++ if (IS_ERR(i2s->regmap)) { ++ dev_err(&pdev->dev, "regmap init failed\n"); ++ return PTR_ERR(i2s->regmap); ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, "failed to get irq\n"); ++ return -EINVAL; ++ } ++ ++#if (RALINK_I2S_INT_EN) ++ ret = devm_request_irq(&pdev->dev, irq, ralink_i2s_irq, ++ 0, dev_name(&pdev->dev), i2s); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to request irq\n"); ++ return ret; ++ } ++#endif ++ ++ i2s->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(i2s->clk)) { ++ dev_err(&pdev->dev, "no clock defined\n"); ++ return PTR_ERR(i2s->clk); ++ } ++ ++ ret = clk_prepare_enable(i2s->clk); ++ if (ret) ++ return ret; ++ ++ ralink_i2s_init_dma_data(i2s, res); ++ ++ device_reset(&pdev->dev); ++ ++ ret = ralink_i2s_debugfs_create(i2s); ++ if (ret) { ++ dev_err(&pdev->dev, "create debugfs failed\n"); ++ goto err_clk_disable; ++ } ++ ++ /* enable 24bits support */ ++ if (i2s->flags & RALINK_FLAGS_24BIT) { ++ ralink_i2s_dai.capture.formats |= SNDRV_PCM_FMTBIT_S24_LE; ++ ralink_i2s_dai.playback.formats |= SNDRV_PCM_FMTBIT_S24_LE; ++ } ++ ++ /* enable big endian support */ ++ if (i2s->flags & RALINK_FLAGS_ENDIAN) { ++ ralink_i2s_dai.capture.formats |= SNDRV_PCM_FMTBIT_S16_BE; ++ ralink_i2s_dai.playback.formats |= SNDRV_PCM_FMTBIT_S16_BE; ++ ralink_pcm_hardware.formats |= SNDRV_PCM_FMTBIT_S16_BE; ++ if (i2s->flags & RALINK_FLAGS_24BIT) { ++ ralink_i2s_dai.capture.formats |= ++ SNDRV_PCM_FMTBIT_S24_BE; ++ ralink_i2s_dai.playback.formats |= ++ SNDRV_PCM_FMTBIT_S24_BE; ++ ralink_pcm_hardware.formats |= ++ SNDRV_PCM_FMTBIT_S24_BE; ++ } ++ } ++ ++ /* disable capture support */ ++ if (i2s->flags & RALINK_FLAGS_TXONLY) ++ memset(&ralink_i2s_dai.capture, sizeof(ralink_i2s_dai.capture), ++ 0); ++ ++ ret = devm_snd_soc_register_component(&pdev->dev, &ralink_i2s_component, ++ &ralink_i2s_dai, 1); ++ if (ret) ++ goto err_debugfs; ++ ++ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, ++ &ralink_dmaengine_pcm_config, ++ SND_DMAENGINE_PCM_FLAG_COMPAT); ++ if (ret) ++ goto err_debugfs; ++ ++ dev_info(i2s->dev, "mclk %luKHz\n", clk_get_rate(i2s->clk) / 1000000); ++ ++ return 0; ++ ++err_debugfs: ++ ralink_i2s_debugfs_remove(i2s); ++ ++err_clk_disable: ++ clk_disable_unprepare(i2s->clk); ++ ++ return ret; ++} ++ ++static int ralink_i2s_remove(struct platform_device *pdev) ++{ ++ struct ralink_i2s *i2s = platform_get_drvdata(pdev); ++ ++ ralink_i2s_debugfs_remove(i2s); ++ clk_disable_unprepare(i2s->clk); ++ ++ return 0; ++} ++ ++static struct platform_driver ralink_i2s_driver = { ++ .probe = ralink_i2s_probe, ++ .remove = ralink_i2s_remove, ++ .driver = { ++ .name = DRV_NAME, ++ .of_match_table = ralink_i2s_match_table, ++ }, ++}; ++module_platform_driver(ralink_i2s_driver); ++ ++MODULE_AUTHOR("Lars-Peter Clausen, "); ++MODULE_DESCRIPTION("Ralink/MediaTek I2S driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:" DRV_NAME); diff --git a/target/linux/ramips/patches-4.14/0051-serial-add-ugly-custom-baud-rate-hack.patch b/target/linux/ramips/patches-4.14/0051-serial-add-ugly-custom-baud-rate-hack.patch new file mode 100644 index 000000000..b71d8f38e --- /dev/null +++ b/target/linux/ramips/patches-4.14/0051-serial-add-ugly-custom-baud-rate-hack.patch @@ -0,0 +1,22 @@ +From a7eb46e0ea4a11e4dfb56ab129bf816d1059a6c5 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 7 Dec 2015 17:31:08 +0100 +Subject: [PATCH 51/53] serial: add ugly custom baud rate hack + +Signed-off-by: John Crispin +--- + drivers/tty/serial/serial_core.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/tty/serial/serial_core.c ++++ b/drivers/tty/serial/serial_core.c +@@ -411,6 +411,9 @@ uart_get_baud_rate(struct uart_port *por + break; + } + ++ if (tty_termios_baud_rate(termios) == 2500000) ++ return 250000; ++ + for (try = 0; try < 2; try++) { + baud = tty_termios_baud_rate(termios); + diff --git a/target/linux/ramips/patches-4.14/0052-pwm-add-mediatek-support.patch b/target/linux/ramips/patches-4.14/0052-pwm-add-mediatek-support.patch new file mode 100644 index 000000000..6eb7f16b9 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0052-pwm-add-mediatek-support.patch @@ -0,0 +1,217 @@ +From fc8f96309c21c1bc3276427309cd7d361347d66e Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 7 Dec 2015 17:16:50 +0100 +Subject: [PATCH 52/53] pwm: add mediatek support + +Signed-off-by: John Crispin +--- + drivers/pwm/Kconfig | 9 +++ + drivers/pwm/Makefile | 1 + + drivers/pwm/pwm-mediatek.c | 173 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 183 insertions(+) + create mode 100644 drivers/pwm/pwm-mediatek.c + +--- a/drivers/pwm/Kconfig ++++ b/drivers/pwm/Kconfig +@@ -302,6 +302,15 @@ config PWM_MEDIATEK + To compile this driver as a module, choose M here: the module + will be called pwm-mediatek. + ++config PWM_MEDIATEK_RAMIPS ++ tristate "Mediatek PWM support" ++ depends on RALINK && OF ++ help ++ Generic PWM framework driver for Mediatek ARM SoC. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called pwm-mxs. ++ + config PWM_MXS + tristate "Freescale MXS PWM support" + depends on ARCH_MXS && OF +--- a/drivers/pwm/Makefile ++++ b/drivers/pwm/Makefile +@@ -28,6 +28,7 @@ obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-p + obj-$(CONFIG_PWM_LPSS_PLATFORM) += pwm-lpss-platform.o + obj-$(CONFIG_PWM_MESON) += pwm-meson.o + obj-$(CONFIG_PWM_MEDIATEK) += pwm-mediatek.o ++obj-$(CONFIG_PWM_MEDIATEK_RAMIPS) += pwm-mediatek-ramips.o + obj-$(CONFIG_PWM_MTK_DISP) += pwm-mtk-disp.o + obj-$(CONFIG_PWM_MXS) += pwm-mxs.o + obj-$(CONFIG_PWM_OMAP_DMTIMER) += pwm-omap-dmtimer.o +--- /dev/null ++++ b/drivers/pwm/pwm-mediatek-ramips.c +@@ -0,0 +1,173 @@ ++/* ++ * Mediatek Pulse Width Modulator driver ++ * ++ * Copyright (C) 2015 John Crispin ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define NUM_PWM 4 ++ ++/* PWM registers and bits definitions */ ++#define PWMCON 0x00 ++#define PWMHDUR 0x04 ++#define PWMLDUR 0x08 ++#define PWMGDUR 0x0c ++#define PWMWAVENUM 0x28 ++#define PWMDWIDTH 0x2c ++#define PWMTHRES 0x30 ++ ++/** ++ * struct mtk_pwm_chip - struct representing pwm chip ++ * ++ * @mmio_base: base address of pwm chip ++ * @chip: linux pwm chip representation ++ */ ++struct mtk_pwm_chip { ++ void __iomem *mmio_base; ++ struct pwm_chip chip; ++}; ++ ++static inline struct mtk_pwm_chip *to_mtk_pwm_chip(struct pwm_chip *chip) ++{ ++ return container_of(chip, struct mtk_pwm_chip, chip); ++} ++ ++static inline u32 mtk_pwm_readl(struct mtk_pwm_chip *chip, unsigned int num, ++ unsigned long offset) ++{ ++ return ioread32(chip->mmio_base + 0x10 + (num * 0x40) + offset); ++} ++ ++static inline void mtk_pwm_writel(struct mtk_pwm_chip *chip, ++ unsigned int num, unsigned long offset, ++ unsigned long val) ++{ ++ iowrite32(val, chip->mmio_base + 0x10 + (num * 0x40) + offset); ++} ++ ++static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ++ int duty_ns, int period_ns) ++{ ++ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); ++ u32 resolution = 100 / 4; ++ u32 clkdiv = 0; ++ ++ while (period_ns / resolution > 8191) { ++ clkdiv++; ++ resolution *= 2; ++ } ++ ++ if (clkdiv > 7) ++ return -1; ++ ++ mtk_pwm_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | BIT(3) | clkdiv); ++ mtk_pwm_writel(pc, pwm->hwpwm, PWMDWIDTH, period_ns / resolution); ++ mtk_pwm_writel(pc, pwm->hwpwm, PWMTHRES, duty_ns / resolution); ++ return 0; ++} ++ ++static int mtk_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); ++ u32 val; ++ ++ val = ioread32(pc->mmio_base); ++ val |= BIT(pwm->hwpwm); ++ iowrite32(val, pc->mmio_base); ++ ++ return 0; ++} ++ ++static void mtk_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); ++ u32 val; ++ ++ val = ioread32(pc->mmio_base); ++ val &= ~BIT(pwm->hwpwm); ++ iowrite32(val, pc->mmio_base); ++} ++ ++static const struct pwm_ops mtk_pwm_ops = { ++ .config = mtk_pwm_config, ++ .enable = mtk_pwm_enable, ++ .disable = mtk_pwm_disable, ++ .owner = THIS_MODULE, ++}; ++ ++static int mtk_pwm_probe(struct platform_device *pdev) ++{ ++ struct mtk_pwm_chip *pc; ++ struct resource *r; ++ int ret; ++ ++ pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); ++ if (!pc) ++ return -ENOMEM; ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ pc->mmio_base = devm_ioremap_resource(&pdev->dev, r); ++ if (IS_ERR(pc->mmio_base)) ++ return PTR_ERR(pc->mmio_base); ++ ++ platform_set_drvdata(pdev, pc); ++ ++ pc->chip.dev = &pdev->dev; ++ pc->chip.ops = &mtk_pwm_ops; ++ pc->chip.base = -1; ++ pc->chip.npwm = NUM_PWM; ++ ++ ret = pwmchip_add(&pc->chip); ++ if (ret < 0) ++ dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int mtk_pwm_remove(struct platform_device *pdev) ++{ ++ struct mtk_pwm_chip *pc = platform_get_drvdata(pdev); ++ int i; ++ ++ for (i = 0; i < NUM_PWM; i++) ++ pwm_disable(&pc->chip.pwms[i]); ++ ++ return pwmchip_remove(&pc->chip); ++} ++ ++static const struct of_device_id mtk_pwm_of_match[] = { ++ { .compatible = "mediatek,mt7628-pwm" }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(of, mtk_pwm_of_match); ++ ++static struct platform_driver mtk_pwm_driver = { ++ .driver = { ++ .name = "mtk-pwm", ++ .owner = THIS_MODULE, ++ .of_match_table = mtk_pwm_of_match, ++ }, ++ .probe = mtk_pwm_probe, ++ .remove = mtk_pwm_remove, ++}; ++ ++module_platform_driver(mtk_pwm_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("John Crispin "); ++MODULE_ALIAS("platform:mtk-pwm"); diff --git a/target/linux/ramips/patches-4.14/0053-mtd-spi-nor-add-w25q256-3b-mode-switch.patch b/target/linux/ramips/patches-4.14/0053-mtd-spi-nor-add-w25q256-3b-mode-switch.patch new file mode 100644 index 000000000..b8819e53e --- /dev/null +++ b/target/linux/ramips/patches-4.14/0053-mtd-spi-nor-add-w25q256-3b-mode-switch.patch @@ -0,0 +1,214 @@ +mtd: spi-nor: add support for switching between 3-byte and 4-byte addressing on w25q256 flash + +On some devices the flash chip needs to be in 3-byte addressing mode during +reboot, otherwise the boot loader will fail to start. +This mode however does not allow regular reads/writes onto the upper 16M +half. W25Q256 has separate read commands for reading from >16M, however +it does not have any separate write commands. +This patch changes the code to leave the chip in 3-byte mode most of the +time and only switch during erase/write cycles that go to >16M +addresses. + +Signed-off-by: Felix Fietkau +--- +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -89,6 +89,10 @@ struct flash_info { + #define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ + #define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ + #define USE_CLSR BIT(14) /* use CLSR command */ ++#define SPI_NOR_4B_READ_OP BIT(15) /* ++ * Like SPI_NOR_4B_OPCODES, but for read ++ * op code only. ++ */ + }; + + #define JEDEC_MFR(info) ((info)->id[0]) +@@ -240,6 +244,15 @@ static inline u8 spi_nor_convert_3to4_er + ARRAY_SIZE(spi_nor_3to4_erase)); + } + ++static void spi_nor_set_4byte_read(struct spi_nor *nor, ++ const struct flash_info *info) ++{ ++ nor->addr_width = 3; ++ nor->ext_addr = 0; ++ nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode); ++ nor->flags |= SNOR_F_4B_EXT_ADDR; ++} ++ + static void spi_nor_set_4byte_opcodes(struct spi_nor *nor, + const struct flash_info *info) + { +@@ -467,6 +480,36 @@ static int spi_nor_erase_sector(struct s + return nor->write_reg(nor, nor->erase_opcode, buf, nor->addr_width); + } + ++static int spi_nor_check_ext_addr(struct spi_nor *nor, u32 addr) ++{ ++ bool ext_addr; ++ int ret; ++ u8 cmd; ++ ++ if (!(nor->flags & SNOR_F_4B_EXT_ADDR)) ++ return 0; ++ ++ ext_addr = !!(addr & 0xff000000); ++ if (nor->ext_addr == ext_addr) ++ return 0; ++ ++ cmd = ext_addr ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; ++ write_enable(nor); ++ ret = nor->write_reg(nor, cmd, NULL, 0); ++ if (ret) ++ return ret; ++ ++ cmd = 0; ++ ret = nor->write_reg(nor, SPINOR_OP_WREAR, &cmd, 1); ++ if (ret) ++ return ret; ++ ++ nor->addr_width = 3 + ext_addr; ++ nor->ext_addr = ext_addr; ++ write_disable(nor); ++ return 0; ++} ++ + /* + * Erase an address range on the nor chip. The address range may extend + * one or more erase sectors. Return an error is there is a problem erasing. +@@ -492,6 +535,10 @@ static int spi_nor_erase(struct mtd_info + if (ret) + return ret; + ++ ret = spi_nor_check_ext_addr(nor, addr + len); ++ if (ret) ++ return ret; ++ + /* whole-chip erase? */ + if (len == mtd->size && !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) { + unsigned long timeout; +@@ -542,6 +589,7 @@ static int spi_nor_erase(struct mtd_info + write_disable(nor); + + erase_err: ++ spi_nor_check_ext_addr(nor, 0); + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); + + instr->state = ret ? MTD_ERASE_FAILED : MTD_ERASE_DONE; +@@ -834,7 +882,9 @@ static int spi_nor_lock(struct mtd_info + if (ret) + return ret; + ++ spi_nor_check_ext_addr(nor, ofs + len); + ret = nor->flash_lock(nor, ofs, len); ++ spi_nor_check_ext_addr(nor, 0); + + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); + return ret; +@@ -849,7 +899,9 @@ static int spi_nor_unlock(struct mtd_inf + if (ret) + return ret; + ++ spi_nor_check_ext_addr(nor, ofs + len); + ret = nor->flash_unlock(nor, ofs, len); ++ spi_nor_check_ext_addr(nor, 0); + + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); + return ret; +@@ -1164,7 +1216,7 @@ static const struct flash_info spi_nor_i + { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, + { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, + { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, +- { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_READ_OP) }, + { "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024, + SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) }, + +@@ -1220,6 +1272,9 @@ static int spi_nor_read(struct mtd_info + if (ret) + return ret; + ++ if (nor->flags & SNOR_F_4B_EXT_ADDR) ++ nor->addr_width = 4; ++ + while (len) { + loff_t addr = from; + +@@ -1244,6 +1299,18 @@ static int spi_nor_read(struct mtd_info + ret = 0; + + read_err: ++ if (nor->flags & SNOR_F_4B_EXT_ADDR) { ++ u8 val = 0; ++ ++ if ((from + len) & 0xff000000) { ++ write_enable(nor); ++ nor->write_reg(nor, SPINOR_OP_WREAR, &val, 1); ++ write_disable(nor); ++ } ++ ++ nor->addr_width = 3; ++ } ++ + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ); + return ret; + } +@@ -1345,6 +1412,10 @@ static int spi_nor_write(struct mtd_info + if (ret) + return ret; + ++ ret = spi_nor_check_ext_addr(nor, to + len); ++ if (ret < 0) ++ return ret; ++ + for (i = 0; i < len; ) { + ssize_t written; + loff_t addr = to + i; +@@ -1385,6 +1456,7 @@ static int spi_nor_write(struct mtd_info + } + + write_err: ++ spi_nor_check_ext_addr(nor, 0); + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); + return ret; + } +@@ -2801,8 +2873,10 @@ int spi_nor_scan(struct spi_nor *nor, co + } else if (mtd->size > 0x1000000) { + /* enable 4-byte addressing if the device exceeds 16MiB */ + nor->addr_width = 4; +- if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || +- info->flags & SPI_NOR_4B_OPCODES) ++ if (info->flags & SPI_NOR_4B_READ_OP) ++ spi_nor_set_4byte_read(nor, info); ++ else if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || ++ info->flags & SPI_NOR_4B_OPCODES) + spi_nor_set_4byte_opcodes(nor, info); + else + set_4byte(nor, info, 1); +--- a/include/linux/mtd/spi-nor.h ++++ b/include/linux/mtd/spi-nor.h +@@ -102,6 +102,7 @@ + /* Used for Macronix and Winbond flashes. */ + #define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */ + #define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */ ++#define SPINOR_OP_WREAR 0xc5 /* Write extended address register */ + + /* Used for Spansion flashes only. */ + #define SPINOR_OP_BRWR 0x17 /* Bank register write */ +@@ -229,6 +230,7 @@ enum spi_nor_option_flags { + SNOR_F_S3AN_ADDR_DEFAULT = BIT(3), + SNOR_F_READY_XSR_RDY = BIT(4), + SNOR_F_USE_CLSR = BIT(5), ++ SNOR_F_4B_EXT_ADDR = BIT(6), + }; + + /** +@@ -280,6 +282,7 @@ struct spi_nor { + enum spi_nor_protocol reg_proto; + bool sst_write_second; + u32 flags; ++ u8 ext_addr; + u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE]; + + int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops); diff --git a/target/linux/ramips/patches-4.14/0069-awake-rt305x-dwc2-controller.patch b/target/linux/ramips/patches-4.14/0069-awake-rt305x-dwc2-controller.patch new file mode 100644 index 000000000..0e09e1d4e --- /dev/null +++ b/target/linux/ramips/patches-4.14/0069-awake-rt305x-dwc2-controller.patch @@ -0,0 +1,15 @@ +--- a/drivers/usb/dwc2/platform.c ++++ b/drivers/usb/dwc2/platform.c +@@ -406,6 +406,12 @@ static int dwc2_driver_probe(struct plat + if (retval) + return retval; + ++ /* Enable USB port before any regs access */ ++ if (dwc2_readl(hsotg->regs + PCGCTL) & 0x0f) { ++ dwc2_writel(0x00, hsotg->regs + PCGCTL); ++ /* TODO: mdelay(25) here? vendor driver don't use it */ ++ } ++ + retval = dwc2_get_dr_mode(hsotg); + if (retval) + goto error; diff --git a/target/linux/ramips/patches-4.14/0070-weak_reordering.patch b/target/linux/ramips/patches-4.14/0070-weak_reordering.patch new file mode 100644 index 000000000..8f8c42c47 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0070-weak_reordering.patch @@ -0,0 +1,10 @@ +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -57,6 +57,7 @@ choice + select COMMON_CLK + select CLKSRC_MIPS_GIC + select HW_HAS_PCI ++ select WEAK_REORDERING_BEYOND_LLSC + endchoice + + choice diff --git a/target/linux/ramips/patches-4.14/0090-ethernet.patch b/target/linux/ramips/patches-4.14/0090-ethernet.patch new file mode 100644 index 000000000..20f69fcc0 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0090-ethernet.patch @@ -0,0 +1,41 @@ +From b6f779ea9c329451b89404583b45b9eb00155b32 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Wed, 18 Nov 2015 03:58:26 +0100 +Subject: [PATCH 510/513] net-next: mediatek: add Kconfig and Makefile + +This patch adds the Makefile and Kconfig required to make the driver build. + +Signed-off-by: John Crispin +Signed-off-by: Felix Fietkau +Signed-off-by: Michael Lee +--- + drivers/net/ethernet/Kconfig | 1 + + drivers/net/ethernet/Makefile | 1 + + drivers/net/ethernet/mtk/Kconfig | 62 ++++++++++++++++++++++++++++++++ + drivers/net/ethernet/mtk/Makefile | 20 +++++++++++ + 4 files changed, 84 insertions(+) + create mode 100644 drivers/net/ethernet/mtk/Kconfig + create mode 100644 drivers/net/ethernet/mtk/Makefile + +--- a/drivers/net/ethernet/Kconfig ++++ b/drivers/net/ethernet/Kconfig +@@ -110,7 +110,7 @@ config LANTIQ_ETOP + Support for the MII0 inside the Lantiq SoC + + source "drivers/net/ethernet/marvell/Kconfig" +-source "drivers/net/ethernet/mediatek/Kconfig" ++source "drivers/net/ethernet/mtk/Kconfig" + source "drivers/net/ethernet/mellanox/Kconfig" + source "drivers/net/ethernet/micrel/Kconfig" + source "drivers/net/ethernet/microchip/Kconfig" +--- a/drivers/net/ethernet/Makefile ++++ b/drivers/net/ethernet/Makefile +@@ -51,7 +51,7 @@ obj-$(CONFIG_JME) += jme.o + obj-$(CONFIG_KORINA) += korina.o + obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o + obj-$(CONFIG_NET_VENDOR_MARVELL) += marvell/ +-obj-$(CONFIG_NET_VENDOR_MEDIATEK) += mediatek/ ++obj-$(CONFIG_NET_VENDOR_MEDIATEK) += mtk/ + obj-$(CONFIG_NET_VENDOR_MELLANOX) += mellanox/ + obj-$(CONFIG_NET_VENDOR_MICREL) += micrel/ + obj-$(CONFIG_NET_VENDOR_MICROCHIP) += microchip/ diff --git a/target/linux/ramips/patches-4.14/0098-disable_cm.patch b/target/linux/ramips/patches-4.14/0098-disable_cm.patch new file mode 100644 index 000000000..bc00619df --- /dev/null +++ b/target/linux/ramips/patches-4.14/0098-disable_cm.patch @@ -0,0 +1,19 @@ +--- a/arch/mips/kernel/mips-cm.c ++++ b/arch/mips/kernel/mips-cm.c +@@ -237,6 +237,7 @@ int mips_cm_probe(void) + + /* disable CM regions */ + write_gcr_reg0_base(CM_GCR_REGn_BASE_BASEADDR); ++ /* + write_gcr_reg0_mask(CM_GCR_REGn_MASK_ADDRMASK); + write_gcr_reg1_base(CM_GCR_REGn_BASE_BASEADDR); + write_gcr_reg1_mask(CM_GCR_REGn_MASK_ADDRMASK); +@@ -244,7 +245,7 @@ int mips_cm_probe(void) + write_gcr_reg2_mask(CM_GCR_REGn_MASK_ADDRMASK); + write_gcr_reg3_base(CM_GCR_REGn_BASE_BASEADDR); + write_gcr_reg3_mask(CM_GCR_REGn_MASK_ADDRMASK); +- ++*/ + /* probe for an L2-only sync region */ + mips_cm_probe_l2sync(); + diff --git a/target/linux/ramips/patches-4.14/0099-pci-mt7620.patch b/target/linux/ramips/patches-4.14/0099-pci-mt7620.patch new file mode 100644 index 000000000..997fb6a2b --- /dev/null +++ b/target/linux/ramips/patches-4.14/0099-pci-mt7620.patch @@ -0,0 +1,10 @@ +--- a/arch/mips/pci/pci-mt7620.c ++++ b/arch/mips/pci/pci-mt7620.c +@@ -33,7 +33,6 @@ + #define RALINK_GPIOMODE 0x60 + + #define PPLL_CFG1 0x9c +-#define PDRV_SW_SET BIT(23) + + #define PPLL_DRV 0xa0 + #define PDRV_SW_SET (1<<31) diff --git a/target/linux/ramips/patches-4.14/0100-prom_fixes.patch b/target/linux/ramips/patches-4.14/0100-prom_fixes.patch new file mode 100644 index 000000000..91ac3b22c --- /dev/null +++ b/target/linux/ramips/patches-4.14/0100-prom_fixes.patch @@ -0,0 +1,66 @@ +From 67b7bff0fd364c194e653f69baa623ba2141bd4c Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 4 Aug 2014 18:46:02 +0200 +Subject: [PATCH 07/53] MIPS: ralink: copy the commandline from the devicetree + +Signed-off-by: John Crispin +--- + arch/mips/ralink/of.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -3,7 +3,7 @@ + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * +- * Copyright (C) 2008 Imre Kaloz ++ * Copyright (C) 2008-2014 Imre Kaloz + * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2013 John Crispin + */ +@@ -66,6 +66,19 @@ static int __init early_init_dt_find_mem + return 0; + } + ++static int chosen_dtb; ++ ++static int __init early_init_dt_find_chosen(unsigned long node, const char *uname, ++ int depth, void *data) ++{ ++ if (depth == 1 && !strcmp(uname, "chosen")) ++ chosen_dtb = 1; ++ ++ return 0; ++} ++ ++extern struct boot_param_header __image_dtb; ++ + void __init plat_mem_setup(void) + { + void *dtb = NULL; +@@ -82,7 +95,11 @@ void __init plat_mem_setup(void) + else if (__dtb_start != __dtb_end) + dtb = (void *)__dtb_start; + +- __dt_setup_arch(dtb); ++ __dt_setup_arch(&__image_dtb); ++ ++ of_scan_flat_dt(early_init_dt_find_chosen, NULL); ++ if (chosen_dtb) ++ strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); + + strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); + +--- a/arch/mips/kernel/head.S ++++ b/arch/mips/kernel/head.S +@@ -85,6 +85,9 @@ EXPORT(__image_cmdline) + .fill 0x400 + #endif /* CONFIG_IMAGE_CMDLINE_HACK */ + ++ .ascii "OWRTDTB:" ++ EXPORT(__image_dtb) ++ .fill 0x4000 + __REF + + NESTED(kernel_entry, 16, sp) # kernel entry point diff --git a/target/linux/ramips/patches-4.14/0200-linkit_bootstrap.patch b/target/linux/ramips/patches-4.14/0200-linkit_bootstrap.patch new file mode 100644 index 000000000..865ae79f4 --- /dev/null +++ b/target/linux/ramips/patches-4.14/0200-linkit_bootstrap.patch @@ -0,0 +1,97 @@ +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -57,6 +57,7 @@ obj-$(CONFIG_CXL_BASE) += cxl/ + obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o + obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o + obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o ++obj-$(CONFIG_SOC_MT7620) += linkit.o + + lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o + lkdtm-$(CONFIG_LKDTM) += lkdtm_bugs.o +--- /dev/null ++++ b/drivers/misc/linkit.c +@@ -0,0 +1,84 @@ ++/* ++ * 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 ++ * publishhed by the Free Software Foundation. ++ * ++ * Copyright (C) 2015 John Crispin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define LINKIT_LATCH_GPIO 11 ++ ++struct linkit_hw_data { ++ char board[16]; ++ char rev[16]; ++}; ++ ++static void sanify_string(char *s) ++{ ++ int i; ++ ++ for (i = 0; i < 15; i++) ++ if (s[i] <= 0x20) ++ s[i] = '\0'; ++ s[15] = '\0'; ++} ++ ++static int linkit_probe(struct platform_device *pdev) ++{ ++ struct linkit_hw_data hw; ++ struct mtd_info *mtd; ++ size_t retlen; ++ int ret; ++ ++ mtd = get_mtd_device_nm("factory"); ++ if (IS_ERR(mtd)) ++ return PTR_ERR(mtd); ++ ++ ret = mtd_read(mtd, 0x400, sizeof(hw), &retlen, (u_char *) &hw); ++ put_mtd_device(mtd); ++ ++ sanify_string(hw.board); ++ sanify_string(hw.rev); ++ ++ dev_info(&pdev->dev, "Version : %s\n", hw.board); ++ dev_info(&pdev->dev, "Revision : %s\n", hw.rev); ++ ++ if (!strcmp(hw.board, "LINKITS7688")) { ++ dev_info(&pdev->dev, "setting up bootstrap latch\n"); ++ ++ if (devm_gpio_request(&pdev->dev, LINKIT_LATCH_GPIO, "bootstrap")) { ++ dev_err(&pdev->dev, "failed to setup bootstrap gpio\n"); ++ return -1; ++ } ++ gpio_direction_output(LINKIT_LATCH_GPIO, 0); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id linkit_match[] = { ++ { .compatible = "mediatek,linkit" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, linkit_match); ++ ++static struct platform_driver linkit_driver = { ++ .probe = linkit_probe, ++ .driver = { ++ .name = "mtk-linkit", ++ .owner = THIS_MODULE, ++ .of_match_table = linkit_match, ++ }, ++}; ++ ++int __init linkit_init(void) ++{ ++ return platform_driver_register(&linkit_driver); ++} ++late_initcall_sync(linkit_init); diff --git a/target/linux/ramips/patches-4.14/100-mt7621-core-detect-hack.patch b/target/linux/ramips/patches-4.14/100-mt7621-core-detect-hack.patch new file mode 100644 index 000000000..991e19b6d --- /dev/null +++ b/target/linux/ramips/patches-4.14/100-mt7621-core-detect-hack.patch @@ -0,0 +1,61 @@ +There is a variant of MT7621 which contains only one CPU core instead of 2. +This is not reflected in the config register, so the kernel detects more +physical cores, which leads to a hang on SMP bringup. +Add a hack to detect missing cores. + +Signed-off-by: Felix Fietkau + +--- a/arch/mips/kernel/smp-cps.c ++++ b/arch/mips/kernel/smp-cps.c +@@ -47,6 +47,11 @@ static unsigned core_vpe_count(unsigned + return mips_cps_numvps(cluster, core); + } + ++bool __weak plat_cpu_core_present(int core) ++{ ++ return true; ++} ++ + static void __init cps_smp_setup(void) + { + unsigned int nclusters, ncores, nvpes, core_vpes; +@@ -64,6 +69,8 @@ static void __init cps_smp_setup(void) + + ncores = mips_cps_numcores(cl); + for (c = 0; c < ncores; c++) { ++ if (!plat_cpu_core_present(c)) ++ continue; + core_vpes = core_vpe_count(cl, c); + + if (c > 0) +--- a/arch/mips/ralink/mt7621.c ++++ b/arch/mips/ralink/mt7621.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include + +@@ -162,6 +163,20 @@ void __init ralink_of_remap(void) + panic("Failed to remap core resources"); + } + ++bool plat_cpu_core_present(int core) ++{ ++ struct cpulaunch *launch = (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH); ++ ++ if (!core) ++ return true; ++ launch += core * 2; /* 2 VPEs per core */ ++ if (!(launch->flags & LAUNCH_FREADY)) ++ return false; ++ if (launch->flags & (LAUNCH_FGO | LAUNCH_FGONE)) ++ return false; ++ return true; ++} ++ + void prom_soc_init(struct ralink_soc_info *soc_info) + { + void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7621_SYSC_BASE); diff --git a/target/linux/ramips/patches-4.14/101-mt7621-timer.patch b/target/linux/ramips/patches-4.14/101-mt7621-timer.patch new file mode 100644 index 000000000..ea8be5694 --- /dev/null +++ b/target/linux/ramips/patches-4.14/101-mt7621-timer.patch @@ -0,0 +1,98 @@ +--- a/arch/mips/ralink/mt7621.c ++++ b/arch/mips/ralink/mt7621.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + + #include + +@@ -177,6 +178,58 @@ bool plat_cpu_core_present(int core) + return true; + } + ++#define LPS_PREC 8 ++/* ++* Re-calibration lpj(loop-per-jiffy). ++* (derived from kernel/calibrate.c) ++*/ ++static int udelay_recal(void) ++{ ++ unsigned int i, lpj = 0; ++ unsigned long ticks, loopbit; ++ int lps_precision = LPS_PREC; ++ ++ lpj = (1<<12); ++ ++ while ((lpj <<= 1) != 0) { ++ /* wait for "start of" clock tick */ ++ ticks = jiffies; ++ while (ticks == jiffies) ++ /* nothing */; ++ ++ /* Go .. */ ++ ticks = jiffies; ++ __delay(lpj); ++ ticks = jiffies - ticks; ++ if (ticks) ++ break; ++ } ++ ++ /* ++ * Do a binary approximation to get lpj set to ++ * equal one clock (up to lps_precision bits) ++ */ ++ lpj >>= 1; ++ loopbit = lpj; ++ while (lps_precision-- && (loopbit >>= 1)) { ++ lpj |= loopbit; ++ ticks = jiffies; ++ while (ticks == jiffies) ++ /* nothing */; ++ ticks = jiffies; ++ __delay(lpj); ++ if (jiffies != ticks) /* longer than 1 tick */ ++ lpj &= ~loopbit; ++ } ++ printk(KERN_INFO "%d CPUs re-calibrate udelay(lpj = %d)\n", NR_CPUS, lpj); ++ ++ for(i=0; i< NR_CPUS; i++) ++ cpu_data[i].udelay_val = lpj; ++ ++ return 0; ++} ++device_initcall(udelay_recal); ++ + void prom_soc_init(struct ralink_soc_info *soc_info) + { + void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7621_SYSC_BASE); +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -58,6 +58,7 @@ choice + select CLKSRC_MIPS_GIC + select HW_HAS_PCI + select WEAK_REORDERING_BEYOND_LLSC ++ select GENERIC_CLOCKEVENTS_BROADCAST + endchoice + + choice +--- a/arch/mips/ralink/timer-gic.c ++++ b/arch/mips/ralink/timer-gic.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + + #include "common.h" + +@@ -19,6 +20,8 @@ void __init plat_time_init(void) + { + ralink_of_remap(); + ++ mips_hpt_frequency = 880000000 / 2; ++ + of_clk_init(NULL); + timer_probe(); + } diff --git a/target/linux/ramips/patches-4.14/110-mt7621-perfctr-fix.patch b/target/linux/ramips/patches-4.14/110-mt7621-perfctr-fix.patch new file mode 100644 index 000000000..4c40e65ab --- /dev/null +++ b/target/linux/ramips/patches-4.14/110-mt7621-perfctr-fix.patch @@ -0,0 +1,15 @@ +--- a/arch/mips/ralink/irq-gic.c ++++ b/arch/mips/ralink/irq-gic.c +@@ -15,6 +15,12 @@ + + int get_c0_perfcount_int(void) + { ++ /* ++ * Performance counter events are routed through GIC. ++ * Prevent them from firing on CPU IRQ7 as well ++ */ ++ clear_c0_status(IE_SW0 << 7); ++ + return gic_get_c0_perfcount_int(); + } + EXPORT_SYMBOL_GPL(get_c0_perfcount_int); diff --git a/target/linux/ramips/patches-4.14/302-spi-nor-add-gd25q512.patch b/target/linux/ramips/patches-4.14/302-spi-nor-add-gd25q512.patch new file mode 100644 index 000000000..408fc13e7 --- /dev/null +++ b/target/linux/ramips/patches-4.14/302-spi-nor-add-gd25q512.patch @@ -0,0 +1,14 @@ +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -1050,6 +1050,11 @@ static const struct flash_info spi_nor_i + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, ++ { ++ "gd25q512", INFO(0xc84020, 0, 64 * 1024, 1024, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4B_OPCODES) ++ }, + + /* Intel/Numonyx -- xxxs33b */ + { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, diff --git a/target/linux/ramips/patches-4.14/303-spi-nor-enable-4B-opcodes-for-mx66l51235l.patch b/target/linux/ramips/patches-4.14/303-spi-nor-enable-4B-opcodes-for-mx66l51235l.patch new file mode 100644 index 000000000..ea8d83d98 --- /dev/null +++ b/target/linux/ramips/patches-4.14/303-spi-nor-enable-4B-opcodes-for-mx66l51235l.patch @@ -0,0 +1,11 @@ +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -1083,7 +1083,7 @@ static const struct flash_info spi_nor_i + { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) }, + { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, +- { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { "mx66l1g45g", INFO(0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, diff --git a/target/linux/ramips/patches-4.14/998-mt7621-needs-jiffies.patch b/target/linux/ramips/patches-4.14/998-mt7621-needs-jiffies.patch new file mode 100644 index 000000000..906f68adb --- /dev/null +++ b/target/linux/ramips/patches-4.14/998-mt7621-needs-jiffies.patch @@ -0,0 +1,10 @@ +--- a/arch/mips/ralink/mt7621.c ++++ b/arch/mips/ralink/mt7621.c +@@ -9,6 +9,7 @@ + + #include + #include ++#include + + #include + #include diff --git a/target/linux/ramips/patches-4.14/999-fix-pci-init-mt7620.patch b/target/linux/ramips/patches-4.14/999-fix-pci-init-mt7620.patch new file mode 100644 index 000000000..3310a6bdb --- /dev/null +++ b/target/linux/ramips/patches-4.14/999-fix-pci-init-mt7620.patch @@ -0,0 +1,21 @@ +--- a/arch/mips/pci/pci-mt7620.c ++++ b/arch/mips/pci/pci-mt7620.c +@@ -35,6 +35,7 @@ + #define PPLL_CFG1 0x9c + + #define PPLL_DRV 0xa0 ++#define PPLL_LD (1<<23) + #define PDRV_SW_SET (1<<31) + #define LC_CKDRVPD (1<<19) + #define LC_CKDRVOHZ (1<<18) +@@ -242,8 +243,8 @@ static int mt7620_pci_hw_init(struct pla + rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1); + mdelay(100); + +- if (!(rt_sysc_r32(PPLL_CFG1) & PDRV_SW_SET)) { +- dev_err(&pdev->dev, "MT7620 PPLL unlock\n"); ++ if (!(rt_sysc_r32(PPLL_CFG1) & PPLL_LD)) { ++ dev_err(&pdev->dev, "MT7620 PPLL is unlocked, aborting init\n"); + reset_control_assert(rstpcie0); + rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1); + return -1; diff --git a/target/linux/ramips/patches-4.9/0053-mtd-spi-nor-add-w25q256-3b-mode-switch.patch b/target/linux/ramips/patches-4.9/0053-mtd-spi-nor-add-w25q256-3b-mode-switch.patch index 9d45ad010..c43dd03ee 100644 --- a/target/linux/ramips/patches-4.9/0053-mtd-spi-nor-add-w25q256-3b-mode-switch.patch +++ b/target/linux/ramips/patches-4.9/0053-mtd-spi-nor-add-w25q256-3b-mode-switch.patch @@ -173,7 +173,7 @@ Signed-off-by: Felix Fietkau spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); return ret; } -@@ -1717,8 +1789,10 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -1719,8 +1791,10 @@ int spi_nor_scan(struct spi_nor *nor, co else if (mtd->size > 0x1000000) { /* enable 4-byte addressing if the device exceeds 16MiB */ nor->addr_width = 4; diff --git a/target/linux/ramips/patches-4.9/0054-mtd-add-chunked-read-io-to-m25p80.patch b/target/linux/ramips/patches-4.9/0054-mtd-add-chunked-read-io-to-m25p80.patch index 0a429d2bc..d6133e159 100644 --- a/target/linux/ramips/patches-4.9/0054-mtd-add-chunked-read-io-to-m25p80.patch +++ b/target/linux/ramips/patches-4.9/0054-mtd-add-chunked-read-io-to-m25p80.patch @@ -68,7 +68,7 @@ static int macronix_quad_enable(struct spi_nor *nor) { int ret, val; -@@ -1702,10 +1763,12 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -1704,10 +1765,12 @@ int spi_nor_scan(struct spi_nor *nor, co } /* sst nor chips use AAI word program */ @@ -83,7 +83,7 @@ if (info->flags & USE_FSR) nor->flags |= SNOR_F_USE_FSR; -@@ -1737,11 +1800,20 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -1739,11 +1802,20 @@ int spi_nor_scan(struct spi_nor *nor, co mtd->writebufsize = nor->page_size; if (np) { diff --git a/target/linux/ramips/rt288x/config-4.9 b/target/linux/ramips/rt288x/config-4.14 similarity index 86% rename from target/linux/ramips/rt288x/config-4.9 rename to target/linux/ramips/rt288x/config-4.14 index 92f1881ff..dba539766 100644 --- a/target/linux/ramips/rt288x/config-4.9 +++ b/target/linux/ramips/rt288x/config-4.14 @@ -5,14 +5,25 @@ CONFIG_ARCH_HAS_ELF_RANDOMIZE=y # CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set CONFIG_ARCH_HAS_RESET_CONTROLLER=y # CONFIG_ARCH_HAS_SG_CHAIN is not set +# CONFIG_ARCH_HAS_STRICT_KERNEL_RWX is not set +# CONFIG_ARCH_HAS_STRICT_MODULE_RWX is not set CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y +CONFIG_ARCH_MMAP_RND_BITS_MAX=15 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 +# CONFIG_ARCH_OPTIONAL_KERNEL_RWX is not set +# CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT is not set CONFIG_ARCH_SUPPORTS_UPROBES=y CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_ARCH_USE_QUEUED_RWLOCKS=y +CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y +# CONFIG_ARCH_WANTS_THP_SWAP is not set CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y CONFIG_BLK_MQ_PCI=y +# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_CEVT_R4K=y # CONFIG_CEVT_SYSTICK_QUIRK is not set CONFIG_CLKDEV_LOOKUP=y @@ -39,16 +50,23 @@ CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_WORKQUEUE=y CONFIG_CSRC_R4K=y CONFIG_DMA_NONCOHERENT=y +# CONFIG_DMA_NOOP_OPS is not set +# CONFIG_DMA_VIRT_OPS is not set +# CONFIG_DRM_LIB_RANDOM is not set # CONFIG_DTB_RT2880_EVAL is not set CONFIG_DTB_RT_NONE=y CONFIG_DTC=y CONFIG_EARLY_PRINTK=y +CONFIG_EXPORTFS=y CONFIG_FIXED_PHY=y +CONFIG_FUTEX_PI=y CONFIG_GENERIC_ATOMIC64=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_CPU_AUTOPROBE=y CONFIG_GENERIC_IO=y CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y CONFIG_GENERIC_IRQ_SHOW=y CONFIG_GENERIC_PCI_IOMAP=y CONFIG_GENERIC_SCHED_CLOCK=y @@ -57,6 +75,7 @@ CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_GPIOLIB=y CONFIG_GPIO_RALINK=y CONFIG_GPIO_SYSFS=y +# CONFIG_GRO_CELLS is not set CONFIG_HANDLE_DOMAIN_IRQ=y CONFIG_HARDWARE_WATCHPOINTS=y CONFIG_HAS_DMA=y @@ -73,6 +92,7 @@ CONFIG_HAVE_CBPF_JIT=y CONFIG_HAVE_CC_STACKPROTECTOR=y CONFIG_HAVE_CLK=y CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_COPY_THREAD_TLS=y CONFIG_HAVE_C_RECORDMCOUNT=y CONFIG_HAVE_DEBUG_KMEMLEAK=y CONFIG_HAVE_DEBUG_STACKOVERFLOW=y @@ -108,7 +128,8 @@ CONFIG_IRQ_INTC=y CONFIG_IRQ_MIPS_CPU=y CONFIG_IRQ_WORK=y CONFIG_LIBFDT=y -CONFIG_MDIO_BOARDINFO=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y CONFIG_MIPS=y CONFIG_MIPS_ASID_BITS=8 CONFIG_MIPS_ASID_SHIFT=0 @@ -134,6 +155,7 @@ CONFIG_MTD_SPI_NOR=y CONFIG_MTD_SPLIT_FIRMWARE=y CONFIG_MTD_SPLIT_LZMA_FW=y CONFIG_MTD_SPLIT_UIMAGE_FW=y +CONFIG_MTD_SPLIT_WRGG_FW=y CONFIG_NEED_DMA_MAP_STATE=y CONFIG_NEED_PER_CPU_KM=y CONFIG_NET_MEDIATEK_MDIO=y @@ -167,6 +189,7 @@ CONFIG_PINCTRL_RT2880=y # CONFIG_PINCTRL_SINGLE is not set CONFIG_RALINK=y CONFIG_RALINK_WDT=y +# CONFIG_RCU_NEED_SEGCBLIST is not set # CONFIG_RCU_STALL_COMMON is not set CONFIG_RESET_CONTROLLER=y # CONFIG_SCHED_INFO is not set @@ -194,16 +217,15 @@ CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y CONFIG_SYS_SUPPORTS_ARBIT_HZ=y CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_THIN_ARCHIVES=y CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TINY_SRCU=y CONFIG_USB=m CONFIG_USB_COMMON=m CONFIG_USB_EHCI_HCD=m CONFIG_USB_EHCI_HCD_PLATFORM=m -CONFIG_USB_EHCI_PCI=m CONFIG_USB_OHCI_HCD=m -CONFIG_USB_OHCI_HCD_PCI=m CONFIG_USB_OHCI_HCD_PLATFORM=m CONFIG_USB_SUPPORT=y -# CONFIG_USB_UHCI_HCD is not set CONFIG_USE_OF=y CONFIG_WATCHDOG_CORE=y diff --git a/target/linux/ramips/rt305x/config-4.9 b/target/linux/ramips/rt305x/config-4.14 similarity index 98% rename from target/linux/ramips/rt305x/config-4.9 rename to target/linux/ramips/rt305x/config-4.14 index ae843f372..33be3910a 100644 --- a/target/linux/ramips/rt305x/config-4.9 +++ b/target/linux/ramips/rt305x/config-4.14 @@ -12,6 +12,8 @@ CONFIG_ARCH_SUPPORTS_UPROBES=y CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ARCH_USE_BUILTIN_BSWAP=y CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_CEVT_R4K=y CONFIG_CEVT_SYSTICK_QUIRK=y CONFIG_CLKDEV_LOOKUP=y diff --git a/target/linux/ramips/rt3883/config-4.9 b/target/linux/ramips/rt3883/config-4.14 similarity index 86% rename from target/linux/ramips/rt3883/config-4.9 rename to target/linux/ramips/rt3883/config-4.14 index 3b116e560..6a0386fa4 100644 --- a/target/linux/ramips/rt3883/config-4.9 +++ b/target/linux/ramips/rt3883/config-4.14 @@ -6,14 +6,25 @@ CONFIG_ARCH_HAS_ELF_RANDOMIZE=y # CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set CONFIG_ARCH_HAS_RESET_CONTROLLER=y # CONFIG_ARCH_HAS_SG_CHAIN is not set +# CONFIG_ARCH_HAS_STRICT_KERNEL_RWX is not set +# CONFIG_ARCH_HAS_STRICT_MODULE_RWX is not set CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y +CONFIG_ARCH_MMAP_RND_BITS_MAX=15 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 +# CONFIG_ARCH_OPTIONAL_KERNEL_RWX is not set +# CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT is not set CONFIG_ARCH_SUPPORTS_UPROBES=y CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_ARCH_USE_QUEUED_RWLOCKS=y +CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y +# CONFIG_ARCH_WANTS_THP_SWAP is not set CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y CONFIG_BLK_MQ_PCI=y +# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_CEVT_R4K=y # CONFIG_CEVT_SYSTICK_QUIRK is not set CONFIG_CLKDEV_LOOKUP=y @@ -41,17 +52,24 @@ CONFIG_CRYPTO_WORKQUEUE=y CONFIG_CSRC_R4K=y CONFIG_DEBUG_PINCTRL=y CONFIG_DMA_NONCOHERENT=y +# CONFIG_DMA_NOOP_OPS is not set +# CONFIG_DMA_VIRT_OPS is not set +# CONFIG_DRM_LIB_RANDOM is not set # CONFIG_DTB_RT3883_EVAL is not set CONFIG_DTB_RT_NONE=y CONFIG_DTC=y CONFIG_EARLY_PRINTK=y CONFIG_ETHERNET_PACKET_MANGLE=y +CONFIG_EXPORTFS=y CONFIG_FIXED_PHY=y +CONFIG_FUTEX_PI=y CONFIG_GENERIC_ATOMIC64=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_CPU_AUTOPROBE=y CONFIG_GENERIC_IO=y CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y CONFIG_GENERIC_IRQ_SHOW=y CONFIG_GENERIC_PCI_IOMAP=y CONFIG_GENERIC_PHY=y @@ -61,6 +79,7 @@ CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_GPIOLIB=y CONFIG_GPIO_RALINK=y CONFIG_GPIO_SYSFS=y +# CONFIG_GRO_CELLS is not set CONFIG_HANDLE_DOMAIN_IRQ=y CONFIG_HARDWARE_WATCHPOINTS=y CONFIG_HAS_DMA=y @@ -77,6 +96,7 @@ CONFIG_HAVE_CBPF_JIT=y CONFIG_HAVE_CC_STACKPROTECTOR=y CONFIG_HAVE_CLK=y CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_COPY_THREAD_TLS=y CONFIG_HAVE_C_RECORDMCOUNT=y CONFIG_HAVE_DEBUG_KMEMLEAK=y CONFIG_HAVE_DEBUG_STACKOVERFLOW=y @@ -111,7 +131,9 @@ CONFIG_IRQ_INTC=y CONFIG_IRQ_MIPS_CPU=y CONFIG_IRQ_WORK=y CONFIG_LIBFDT=y -CONFIG_MDIO_BOARDINFO=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MFD_SYSCON=y CONFIG_MIPS=y CONFIG_MIPS_ASID_BITS=8 CONFIG_MIPS_ASID_SHIFT=0 @@ -170,7 +192,10 @@ CONFIG_PINCTRL_RT2880=y # CONFIG_PINCTRL_SINGLE is not set CONFIG_RALINK=y CONFIG_RALINK_WDT=y +# CONFIG_RCU_NEED_SEGCBLIST is not set # CONFIG_RCU_STALL_COMMON is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y CONFIG_RESET_CONTROLLER=y CONFIG_RTL8366_SMI=y CONFIG_RTL8367B_PHY=y @@ -200,7 +225,9 @@ CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y CONFIG_SYS_SUPPORTS_ARBIT_HZ=y CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_THIN_ARCHIVES=y CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TINY_SRCU=y CONFIG_USB_SUPPORT=y CONFIG_USE_OF=y CONFIG_WATCHDOG_CORE=y diff --git a/target/linux/sunxi/patches-4.9/0050-stmmac-form-4-10.patch b/target/linux/sunxi/patches-4.9/0050-stmmac-form-4-10.patch index ca2eb3ac8..69bbb411d 100644 --- a/target/linux/sunxi/patches-4.9/0050-stmmac-form-4-10.patch +++ b/target/linux/sunxi/patches-4.9/0050-stmmac-form-4-10.patch @@ -2131,9 +2131,9 @@ { + struct net_device *ndev = priv->dev; unsigned long flags; + int interface = priv->plat->interface; bool ret = false; - -@@ -295,7 +297,7 @@ bool stmmac_eee_init(struct stmmac_priv +@@ -301,7 +303,7 @@ bool stmmac_eee_init(struct stmmac_priv int tx_lpi_timer = priv->tx_lpi_timer; /* Check if the PHY supports EEE */ @@ -2142,7 +2142,7 @@ /* To manage at run-time if the EEE cannot be supported * anymore (for example because the lp caps have been * changed). -@@ -303,7 +305,7 @@ bool stmmac_eee_init(struct stmmac_priv +@@ -309,7 +311,7 @@ bool stmmac_eee_init(struct stmmac_priv */ spin_lock_irqsave(&priv->lock, flags); if (priv->eee_active) { @@ -2151,7 +2151,7 @@ del_timer_sync(&priv->eee_ctrl_timer); priv->hw->mac->set_eee_timer(priv->hw, 0, tx_lpi_timer); -@@ -327,12 +329,12 @@ bool stmmac_eee_init(struct stmmac_priv +@@ -333,12 +335,12 @@ bool stmmac_eee_init(struct stmmac_priv tx_lpi_timer); } /* Set HW EEE according to the speed */ @@ -2166,7 +2166,7 @@ } out: return ret; -@@ -450,8 +452,8 @@ static int stmmac_hwtstamp_ioctl(struct +@@ -456,8 +458,8 @@ static int stmmac_hwtstamp_ioctl(struct sizeof(struct hwtstamp_config))) return -EFAULT; @@ -2177,7 +2177,7 @@ /* reserved for future extensions */ if (config.flags) -@@ -697,7 +699,7 @@ static void stmmac_release_ptp(struct st +@@ -703,7 +705,7 @@ static void stmmac_release_ptp(struct st static void stmmac_adjust_link(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); @@ -2186,7 +2186,7 @@ unsigned long flags; int new_state = 0; unsigned int fc = priv->flow_ctrl, pause_time = priv->pause; -@@ -750,9 +752,9 @@ static void stmmac_adjust_link(struct ne +@@ -756,9 +758,9 @@ static void stmmac_adjust_link(struct ne stmmac_hw_fix_mac_speed(priv); break; default: @@ -2199,7 +2199,7 @@ break; } -@@ -805,10 +807,10 @@ static void stmmac_check_pcs_mode(struct +@@ -811,10 +813,10 @@ static void stmmac_check_pcs_mode(struct (interface == PHY_INTERFACE_MODE_RGMII_ID) || (interface == PHY_INTERFACE_MODE_RGMII_RXID) || (interface == PHY_INTERFACE_MODE_RGMII_TXID)) { @@ -2212,7 +2212,7 @@ priv->hw->pcs = STMMAC_PCS_SGMII; } } -@@ -843,15 +845,15 @@ static int stmmac_init_phy(struct net_de +@@ -849,15 +851,15 @@ static int stmmac_init_phy(struct net_de snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, priv->plat->phy_addr); @@ -2231,7 +2231,7 @@ if (!phydev) return -ENODEV; -@@ -884,10 +886,8 @@ static int stmmac_init_phy(struct net_de +@@ -890,10 +892,8 @@ static int stmmac_init_phy(struct net_de if (phydev->is_pseudo_fixed_link) phydev->irq = PHY_POLL; @@ -2244,7 +2244,7 @@ return 0; } -@@ -973,7 +973,8 @@ static int stmmac_init_rx_buffers(struct +@@ -979,7 +979,8 @@ static int stmmac_init_rx_buffers(struct skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags); if (!skb) { @@ -2254,7 +2254,7 @@ return -ENOMEM; } priv->rx_skbuff[i] = skb; -@@ -981,15 +982,15 @@ static int stmmac_init_rx_buffers(struct +@@ -987,15 +988,15 @@ static int stmmac_init_rx_buffers(struct priv->dma_buf_sz, DMA_FROM_DEVICE); if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[i])) { @@ -2273,7 +2273,7 @@ if ((priv->hw->mode->init_desc3) && (priv->dma_buf_sz == BUF_SIZE_16KiB)) -@@ -1031,13 +1032,14 @@ static int init_dma_desc_rings(struct ne +@@ -1037,13 +1038,14 @@ static int init_dma_desc_rings(struct ne priv->dma_buf_sz = bfsize; @@ -2294,7 +2294,7 @@ for (i = 0; i < DMA_RX_SIZE; i++) { struct dma_desc *p; if (priv->extend_desc) -@@ -1049,10 +1051,9 @@ static int init_dma_desc_rings(struct ne +@@ -1055,10 +1057,9 @@ static int init_dma_desc_rings(struct ne if (ret) goto err_init_rx_buffers; @@ -2308,7 +2308,7 @@ } priv->cur_rx = 0; priv->dirty_rx = (unsigned int)(i - DMA_RX_SIZE); -@@ -1307,7 +1308,7 @@ static void stmmac_tx_clean(struct stmma +@@ -1313,7 +1314,7 @@ static void stmmac_tx_clean(struct stmma unsigned int bytes_compl = 0, pkts_compl = 0; unsigned int entry = priv->dirty_tx; @@ -2317,7 +2317,7 @@ priv->xstats.tx_clean++; -@@ -1378,22 +1379,17 @@ static void stmmac_tx_clean(struct stmma +@@ -1384,22 +1385,17 @@ static void stmmac_tx_clean(struct stmma netdev_completed_queue(priv->dev, pkts_compl, bytes_compl); if (unlikely(netif_queue_stopped(priv->dev) && @@ -2345,7 +2345,7 @@ } static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv) -@@ -1497,7 +1493,7 @@ static void stmmac_mmc_setup(struct stmm +@@ -1503,7 +1499,7 @@ static void stmmac_mmc_setup(struct stmm dwmac_mmc_ctrl(priv->mmcaddr, mode); memset(&priv->mmc, 0, sizeof(struct stmmac_counters)); } else @@ -2354,7 +2354,7 @@ } /** -@@ -1510,18 +1506,18 @@ static void stmmac_mmc_setup(struct stmm +@@ -1516,18 +1512,18 @@ static void stmmac_mmc_setup(struct stmm static void stmmac_selec_desc_mode(struct stmmac_priv *priv) { if (priv->plat->enh_desc) { @@ -2377,7 +2377,7 @@ priv->hw->desc = &ndesc_ops; } } -@@ -1562,8 +1558,8 @@ static void stmmac_check_ether_addr(stru +@@ -1568,8 +1564,8 @@ static void stmmac_check_ether_addr(stru priv->dev->dev_addr, 0); if (!is_valid_ether_addr(priv->dev->dev_addr)) eth_hw_addr_random(priv->dev); @@ -2388,7 +2388,7 @@ } } -@@ -1577,16 +1573,12 @@ static void stmmac_check_ether_addr(stru +@@ -1583,16 +1579,12 @@ static void stmmac_check_ether_addr(stru */ static int stmmac_init_dma_engine(struct stmmac_priv *priv) { @@ -2408,7 +2408,7 @@ } if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE)) -@@ -1598,8 +1590,8 @@ static int stmmac_init_dma_engine(struct +@@ -1604,8 +1596,8 @@ static int stmmac_init_dma_engine(struct return ret; } @@ -2419,7 +2419,7 @@ if (priv->synopsys_id >= DWMAC_CORE_4_00) { priv->rx_tail_addr = priv->dma_rx_phy + -@@ -1671,7 +1663,8 @@ static int stmmac_hw_setup(struct net_de +@@ -1677,7 +1669,8 @@ static int stmmac_hw_setup(struct net_de /* DMA initialization and SW reset */ ret = stmmac_init_dma_engine(priv); if (ret < 0) { @@ -2429,7 +2429,7 @@ return ret; } -@@ -1700,7 +1693,7 @@ static int stmmac_hw_setup(struct net_de +@@ -1706,7 +1699,7 @@ static int stmmac_hw_setup(struct net_de ret = priv->hw->mac->rx_ipc(priv->hw); if (!ret) { @@ -2438,7 +2438,7 @@ priv->plat->rx_coe = STMMAC_RX_COE_NONE; priv->hw->rx_csum = 0; } -@@ -1725,10 +1718,11 @@ static int stmmac_hw_setup(struct net_de +@@ -1731,10 +1724,11 @@ static int stmmac_hw_setup(struct net_de #ifdef CONFIG_DEBUG_FS ret = stmmac_init_fs(dev); if (ret < 0) @@ -2452,7 +2452,7 @@ priv->hw->dma->start_tx(priv->ioaddr); priv->hw->dma->start_rx(priv->ioaddr); -@@ -1783,8 +1777,9 @@ static int stmmac_open(struct net_device +@@ -1789,8 +1783,9 @@ static int stmmac_open(struct net_device priv->hw->pcs != STMMAC_PCS_RTBI) { ret = stmmac_init_phy(dev); if (ret) { @@ -2464,7 +2464,7 @@ return ret; } } -@@ -1799,33 +1794,36 @@ static int stmmac_open(struct net_device +@@ -1805,33 +1800,36 @@ static int stmmac_open(struct net_device ret = alloc_dma_desc_resources(priv); if (ret < 0) { @@ -2508,7 +2508,7 @@ goto init_error; } -@@ -1834,8 +1832,9 @@ static int stmmac_open(struct net_device +@@ -1840,8 +1838,9 @@ static int stmmac_open(struct net_device ret = request_irq(priv->wol_irq, stmmac_interrupt, IRQF_SHARED, dev->name, dev); if (unlikely(ret < 0)) { @@ -2520,7 +2520,7 @@ goto wolirq_error; } } -@@ -1845,8 +1844,9 @@ static int stmmac_open(struct net_device +@@ -1851,8 +1850,9 @@ static int stmmac_open(struct net_device ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED, dev->name, dev); if (unlikely(ret < 0)) { @@ -2532,7 +2532,7 @@ goto lpiirq_error; } } -@@ -1865,8 +1865,8 @@ wolirq_error: +@@ -1871,8 +1871,8 @@ wolirq_error: init_error: free_dma_desc_resources(priv); dma_desc_error: @@ -2543,7 +2543,7 @@ return ret; } -@@ -1885,10 +1885,9 @@ static int stmmac_release(struct net_dev +@@ -1891,10 +1891,9 @@ static int stmmac_release(struct net_dev del_timer_sync(&priv->eee_ctrl_timer); /* Stop and disconnect the PHY */ @@ -2557,7 +2557,7 @@ } netif_stop_queue(dev); -@@ -1948,13 +1947,13 @@ static void stmmac_tso_allocator(struct +@@ -1954,13 +1953,13 @@ static void stmmac_tso_allocator(struct priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE); desc = priv->dma_tx + priv->cur_tx; @@ -2573,7 +2573,7 @@ 0, 0); tmp_len -= TSO_MAX_BUFF_SIZE; -@@ -1999,8 +1998,6 @@ static netdev_tx_t stmmac_tso_xmit(struc +@@ -2005,8 +2004,6 @@ static netdev_tx_t stmmac_tso_xmit(struc u8 proto_hdr_len; int i; @@ -2582,7 +2582,7 @@ /* Compute header lengths */ proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); -@@ -2010,9 +2007,10 @@ static netdev_tx_t stmmac_tso_xmit(struc +@@ -2016,9 +2013,10 @@ static netdev_tx_t stmmac_tso_xmit(struc if (!netif_queue_stopped(dev)) { netif_stop_queue(dev); /* This is a hard error, log it. */ @@ -2595,7 +2595,7 @@ return NETDEV_TX_BUSY; } -@@ -2050,11 +2048,11 @@ static netdev_tx_t stmmac_tso_xmit(struc +@@ -2056,11 +2054,11 @@ static netdev_tx_t stmmac_tso_xmit(struc priv->tx_skbuff_dma[first_entry].len = skb_headlen(skb); priv->tx_skbuff[first_entry] = skb; @@ -2609,7 +2609,7 @@ /* If needed take extra descriptors to fill the remaining payload */ tmp_pay_len = pay_len - TSO_MAX_BUFF_SIZE; -@@ -2083,8 +2081,8 @@ static netdev_tx_t stmmac_tso_xmit(struc +@@ -2089,8 +2087,8 @@ static netdev_tx_t stmmac_tso_xmit(struc priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE); if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) { @@ -2620,7 +2620,7 @@ netif_stop_queue(dev); } -@@ -2128,7 +2126,7 @@ static netdev_tx_t stmmac_tso_xmit(struc +@@ -2134,7 +2132,7 @@ static netdev_tx_t stmmac_tso_xmit(struc * descriptor and then barrier is needed to make sure that * all is coherent before granting the DMA engine. */ @@ -2629,7 +2629,7 @@ if (netif_msg_pktdata(priv)) { pr_info("%s: curr=%d dirty=%d f=%d, e=%d, f_p=%p, nfrags %d\n", -@@ -2147,11 +2145,9 @@ static netdev_tx_t stmmac_tso_xmit(struc +@@ -2153,11 +2151,9 @@ static netdev_tx_t stmmac_tso_xmit(struc priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr, STMMAC_CHAN0); @@ -2641,7 +2641,7 @@ dev_err(priv->device, "Tx dma map failed\n"); dev_kfree_skb(skb); priv->dev->stats.tx_dropped++; -@@ -2183,14 +2179,13 @@ static netdev_tx_t stmmac_xmit(struct sk +@@ -2189,14 +2185,13 @@ static netdev_tx_t stmmac_xmit(struct sk return stmmac_tso_xmit(skb, dev); } @@ -2659,7 +2659,7 @@ } return NETDEV_TX_BUSY; } -@@ -2243,13 +2238,11 @@ static netdev_tx_t stmmac_xmit(struct sk +@@ -2249,13 +2244,11 @@ static netdev_tx_t stmmac_xmit(struct sk priv->tx_skbuff[entry] = NULL; @@ -2678,7 +2678,7 @@ priv->tx_skbuff_dma[entry].map_as_page = true; priv->tx_skbuff_dma[entry].len = len; -@@ -2267,9 +2260,10 @@ static netdev_tx_t stmmac_xmit(struct sk +@@ -2273,9 +2266,10 @@ static netdev_tx_t stmmac_xmit(struct sk if (netif_msg_pktdata(priv)) { void *tx_head; @@ -2692,7 +2692,7 @@ if (priv->extend_desc) tx_head = (void *)priv->dma_etx; -@@ -2278,13 +2272,13 @@ static netdev_tx_t stmmac_xmit(struct sk +@@ -2284,13 +2278,13 @@ static netdev_tx_t stmmac_xmit(struct sk priv->hw->desc->display_ring(tx_head, DMA_TX_SIZE, false); @@ -2709,7 +2709,7 @@ netif_stop_queue(dev); } -@@ -2320,13 +2314,11 @@ static netdev_tx_t stmmac_xmit(struct sk +@@ -2326,13 +2320,11 @@ static netdev_tx_t stmmac_xmit(struct sk if (dma_mapping_error(priv->device, des)) goto dma_map_err; @@ -2728,7 +2728,7 @@ priv->tx_skbuff_dma[first_entry].len = nopaged_len; priv->tx_skbuff_dma[first_entry].last_segment = last_segment; -@@ -2347,7 +2339,7 @@ static netdev_tx_t stmmac_xmit(struct sk +@@ -2353,7 +2345,7 @@ static netdev_tx_t stmmac_xmit(struct sk * descriptor and then barrier is needed to make sure that * all is coherent before granting the DMA engine. */ @@ -2737,7 +2737,7 @@ } netdev_sent_queue(dev, skb->len); -@@ -2358,12 +2350,10 @@ static netdev_tx_t stmmac_xmit(struct sk +@@ -2364,12 +2356,10 @@ static netdev_tx_t stmmac_xmit(struct sk priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr, STMMAC_CHAN0); @@ -2751,7 +2751,7 @@ dev_kfree_skb(skb); priv->dev->stats.tx_dropped++; return NETDEV_TX_OK; -@@ -2434,16 +2424,16 @@ static inline void stmmac_rx_refill(stru +@@ -2440,16 +2430,16 @@ static inline void stmmac_rx_refill(stru DMA_FROM_DEVICE); if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[entry])) { @@ -2771,7 +2771,7 @@ } if (priv->hw->mode->refill_desc3) priv->hw->mode->refill_desc3(priv, p); -@@ -2451,17 +2441,17 @@ static inline void stmmac_rx_refill(stru +@@ -2457,17 +2447,17 @@ static inline void stmmac_rx_refill(stru if (priv->rx_zeroc_thresh > 0) priv->rx_zeroc_thresh--; @@ -2793,7 +2793,7 @@ entry = STMMAC_GET_ENTRY(entry, DMA_RX_SIZE); } -@@ -2485,7 +2475,7 @@ static int stmmac_rx(struct stmmac_priv +@@ -2491,7 +2481,7 @@ static int stmmac_rx(struct stmmac_priv if (netif_msg_rx_status(priv)) { void *rx_head; @@ -2802,7 +2802,7 @@ if (priv->extend_desc) rx_head = (void *)priv->dma_erx; else -@@ -2547,9 +2537,9 @@ static int stmmac_rx(struct stmmac_priv +@@ -2553,9 +2543,9 @@ static int stmmac_rx(struct stmmac_priv unsigned int des; if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) @@ -2814,7 +2814,7 @@ frame_len = priv->hw->desc->get_rx_frame_len(p, coe); -@@ -2558,9 +2548,9 @@ static int stmmac_rx(struct stmmac_priv +@@ -2564,9 +2554,9 @@ static int stmmac_rx(struct stmmac_priv * ignored */ if (frame_len > priv->dma_buf_sz) { @@ -2827,7 +2827,7 @@ priv->dev->stats.rx_length_errors++; break; } -@@ -2572,11 +2562,11 @@ static int stmmac_rx(struct stmmac_priv +@@ -2578,11 +2568,11 @@ static int stmmac_rx(struct stmmac_priv frame_len -= ETH_FCS_LEN; if (netif_msg_rx_status(priv)) { @@ -2843,7 +2843,7 @@ } /* The zero-copy is always used for all the sizes -@@ -2613,8 +2603,9 @@ static int stmmac_rx(struct stmmac_priv +@@ -2619,8 +2609,9 @@ static int stmmac_rx(struct stmmac_priv } else { skb = priv->rx_skbuff[entry]; if (unlikely(!skb)) { @@ -2855,7 +2855,7 @@ priv->dev->stats.rx_dropped++; break; } -@@ -2630,7 +2621,8 @@ static int stmmac_rx(struct stmmac_priv +@@ -2636,7 +2627,8 @@ static int stmmac_rx(struct stmmac_priv } if (netif_msg_pktdata(priv)) { @@ -2865,7 +2865,7 @@ print_pkt(skb->data, frame_len); } -@@ -2733,7 +2725,7 @@ static int stmmac_change_mtu(struct net_ +@@ -2739,7 +2731,7 @@ static int stmmac_change_mtu(struct net_ int max_mtu; if (netif_running(dev)) { @@ -2874,7 +2874,7 @@ return -EBUSY; } -@@ -2825,7 +2817,7 @@ static irqreturn_t stmmac_interrupt(int +@@ -2831,7 +2823,7 @@ static irqreturn_t stmmac_interrupt(int pm_wakeup_event(priv->device, 0); if (unlikely(!dev)) { @@ -2883,7 +2883,7 @@ return IRQ_NONE; } -@@ -2883,7 +2875,6 @@ static void stmmac_poll_controller(struc +@@ -2889,7 +2881,6 @@ static void stmmac_poll_controller(struc */ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { @@ -2891,7 +2891,7 @@ int ret = -EOPNOTSUPP; if (!netif_running(dev)) -@@ -2893,9 +2884,9 @@ static int stmmac_ioctl(struct net_devic +@@ -2899,9 +2890,9 @@ static int stmmac_ioctl(struct net_devic case SIOCGMIIPHY: case SIOCGMIIREG: case SIOCSMIIREG: @@ -2903,7 +2903,7 @@ break; case SIOCSHWTSTAMP: ret = stmmac_hwtstamp_ioctl(dev, rq); -@@ -2923,14 +2914,17 @@ static void sysfs_display_ring(void *hea +@@ -2929,14 +2920,17 @@ static void sysfs_display_ring(void *hea x = *(u64 *) ep; seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", i, (unsigned int)virt_to_phys(ep), @@ -2924,7 +2924,7 @@ p++; } seq_printf(seq, "\n"); -@@ -2962,6 +2956,8 @@ static int stmmac_sysfs_ring_open(struct +@@ -2968,6 +2962,8 @@ static int stmmac_sysfs_ring_open(struct return single_open(file, stmmac_sysfs_ring_read, inode->i_private); } @@ -2933,7 +2933,7 @@ static const struct file_operations stmmac_rings_status_fops = { .owner = THIS_MODULE, .open = stmmac_sysfs_ring_open, -@@ -2984,11 +2980,11 @@ static int stmmac_sysfs_dma_cap_read(str +@@ -2990,11 +2986,11 @@ static int stmmac_sysfs_dma_cap_read(str seq_printf(seq, "\tDMA HW features\n"); seq_printf(seq, "==============================\n"); @@ -2948,7 +2948,7 @@ (priv->dma_cap.half_duplex) ? "Y" : "N"); seq_printf(seq, "\tHash Filter: %s\n", (priv->dma_cap.hash_filter) ? "Y" : "N"); -@@ -3006,9 +3002,9 @@ static int stmmac_sysfs_dma_cap_read(str +@@ -3012,9 +3008,9 @@ static int stmmac_sysfs_dma_cap_read(str (priv->dma_cap.rmon) ? "Y" : "N"); seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n", (priv->dma_cap.time_stamp) ? "Y" : "N"); @@ -2960,7 +2960,7 @@ (priv->dma_cap.eee) ? "Y" : "N"); seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N"); seq_printf(seq, "\tChecksum Offload in TX: %s\n", -@@ -3055,8 +3051,7 @@ static int stmmac_init_fs(struct net_dev +@@ -3061,8 +3057,7 @@ static int stmmac_init_fs(struct net_dev priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir); if (!priv->dbgfs_dir || IS_ERR(priv->dbgfs_dir)) { @@ -2970,7 +2970,7 @@ return -ENOMEM; } -@@ -3068,7 +3063,7 @@ static int stmmac_init_fs(struct net_dev +@@ -3074,7 +3069,7 @@ static int stmmac_init_fs(struct net_dev &stmmac_rings_status_fops); if (!priv->dbgfs_rings_status || IS_ERR(priv->dbgfs_rings_status)) { @@ -2979,7 +2979,7 @@ debugfs_remove_recursive(priv->dbgfs_dir); return -ENOMEM; -@@ -3080,7 +3075,7 @@ static int stmmac_init_fs(struct net_dev +@@ -3086,7 +3081,7 @@ static int stmmac_init_fs(struct net_dev dev, &stmmac_dma_cap_fops); if (!priv->dbgfs_dma_cap || IS_ERR(priv->dbgfs_dma_cap)) { @@ -2988,7 +2988,7 @@ debugfs_remove_recursive(priv->dbgfs_dir); return -ENOMEM; -@@ -3152,11 +3147,11 @@ static int stmmac_hw_init(struct stmmac_ +@@ -3158,11 +3153,11 @@ static int stmmac_hw_init(struct stmmac_ } else { if (chain_mode) { priv->hw->mode = &chain_mode_ops; @@ -3002,7 +3002,7 @@ priv->mode = STMMAC_RING_MODE; } } -@@ -3164,7 +3159,7 @@ static int stmmac_hw_init(struct stmmac_ +@@ -3170,7 +3165,7 @@ static int stmmac_hw_init(struct stmmac_ /* Get the HW capability (new GMAC newer than 3.50a) */ priv->hw_cap_support = stmmac_get_hw_features(priv); if (priv->hw_cap_support) { @@ -3011,7 +3011,7 @@ /* We can override some gmac/dma configuration fields: e.g. * enh_desc, tx_coe (e.g. that are passed through the -@@ -3189,8 +3184,9 @@ static int stmmac_hw_init(struct stmmac_ +@@ -3195,8 +3190,9 @@ static int stmmac_hw_init(struct stmmac_ else if (priv->dma_cap.rx_coe_type1) priv->plat->rx_coe = STMMAC_RX_COE_TYPE1; @@ -3023,7 +3023,7 @@ /* To use alternate (extended), normal or GMAC4 descriptor structures */ if (priv->synopsys_id >= DWMAC_CORE_4_00) -@@ -3200,20 +3196,20 @@ static int stmmac_hw_init(struct stmmac_ +@@ -3206,20 +3202,20 @@ static int stmmac_hw_init(struct stmmac_ if (priv->plat->rx_coe) { priv->hw->rx_csum = priv->plat->rx_coe; @@ -3049,7 +3049,7 @@ return 0; } -@@ -3272,8 +3268,8 @@ int stmmac_dvr_probe(struct device *devi +@@ -3278,8 +3274,8 @@ int stmmac_dvr_probe(struct device *devi priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME); if (IS_ERR(priv->stmmac_clk)) { @@ -3060,7 +3060,7 @@ /* If failed to obtain stmmac_clk and specific clk_csr value * is NOT passed from the platform, probe fail. */ -@@ -3322,7 +3318,7 @@ int stmmac_dvr_probe(struct device *devi +@@ -3328,7 +3324,7 @@ int stmmac_dvr_probe(struct device *devi if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) { ndev->hw_features |= NETIF_F_TSO; priv->tso = true; @@ -3069,7 +3069,7 @@ } ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA; ndev->watchdog_timeo = msecs_to_jiffies(watchdog); -@@ -3342,13 +3338,13 @@ int stmmac_dvr_probe(struct device *devi +@@ -3348,13 +3344,13 @@ int stmmac_dvr_probe(struct device *devi */ if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) { priv->use_riwt = 1; @@ -3085,7 +3085,7 @@ /* If a specific clk_csr value is passed from the platform * this means that the CSR Clock Range selection cannot be -@@ -3369,15 +3365,17 @@ int stmmac_dvr_probe(struct device *devi +@@ -3375,15 +3371,17 @@ int stmmac_dvr_probe(struct device *devi /* MDIO bus Registration */ ret = stmmac_mdio_register(ndev); if (ret < 0) { @@ -3107,7 +3107,7 @@ goto error_netdev_register; } -@@ -3388,7 +3386,7 @@ error_netdev_register: +@@ -3394,7 +3392,7 @@ error_netdev_register: priv->hw->pcs != STMMAC_PCS_TBI && priv->hw->pcs != STMMAC_PCS_RTBI) stmmac_mdio_unregister(ndev); @@ -3116,7 +3116,7 @@ netif_napi_del(&priv->napi); error_hw_init: clk_disable_unprepare(priv->pclk); -@@ -3412,7 +3410,7 @@ int stmmac_dvr_remove(struct device *dev +@@ -3418,7 +3416,7 @@ int stmmac_dvr_remove(struct device *dev struct net_device *ndev = dev_get_drvdata(dev); struct stmmac_priv *priv = netdev_priv(ndev); @@ -3125,7 +3125,7 @@ priv->hw->dma->stop_rx(priv->ioaddr); priv->hw->dma->stop_tx(priv->ioaddr); -@@ -3450,8 +3448,8 @@ int stmmac_suspend(struct device *dev) +@@ -3456,8 +3454,8 @@ int stmmac_suspend(struct device *dev) if (!ndev || !netif_running(ndev)) return 0; @@ -3136,7 +3136,7 @@ spin_lock_irqsave(&priv->lock, flags); -@@ -3545,8 +3543,8 @@ int stmmac_resume(struct device *dev) +@@ -3551,8 +3549,8 @@ int stmmac_resume(struct device *dev) spin_unlock_irqrestore(&priv->lock, flags); diff --git a/target/linux/sunxi/patches-4.9/0051-stmmac-form-4-11.patch b/target/linux/sunxi/patches-4.9/0051-stmmac-form-4-11.patch index fc626cbb9..31d045670 100644 --- a/target/linux/sunxi/patches-4.9/0051-stmmac-form-4-11.patch +++ b/target/linux/sunxi/patches-4.9/0051-stmmac-form-4-11.patch @@ -1460,7 +1460,7 @@ } /** -@@ -415,7 +412,7 @@ static void stmmac_get_rx_hwtstamp(struc +@@ -421,7 +418,7 @@ static void stmmac_get_rx_hwtstamp(struc /** * stmmac_hwtstamp_ioctl - control hardware timestamping. * @dev: device pointer. @@ -1469,7 +1469,7 @@ * a proprietary structure used to pass information to the driver. * Description: * This function configures the MAC to enable/disable both outgoing(TX) -@@ -606,7 +603,7 @@ static int stmmac_hwtstamp_ioctl(struct +@@ -612,7 +609,7 @@ static int stmmac_hwtstamp_ioctl(struct /* program Sub Second Increment reg */ sec_inc = priv->hw->ptp->config_sub_second_increment( @@ -1478,7 +1478,7 @@ priv->plat->has_gmac4); temp = div_u64(1000000000ULL, sec_inc); -@@ -616,7 +613,7 @@ static int stmmac_hwtstamp_ioctl(struct +@@ -622,7 +619,7 @@ static int stmmac_hwtstamp_ioctl(struct * where, freq_div_ratio = 1e9ns/sec_inc */ temp = (u64)(temp << 32); @@ -1487,7 +1487,7 @@ priv->hw->ptp->config_addend(priv->ptpaddr, priv->default_addend); -@@ -644,18 +641,6 @@ static int stmmac_init_ptp(struct stmmac +@@ -650,18 +647,6 @@ static int stmmac_init_ptp(struct stmmac if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) return -EOPNOTSUPP; @@ -1506,7 +1506,7 @@ priv->adv_ts = 0; /* Check if adv_ts can be enabled for dwmac 4.x core */ if (priv->plat->has_gmac4 && priv->dma_cap.atime_stamp) -@@ -682,8 +667,8 @@ static int stmmac_init_ptp(struct stmmac +@@ -688,8 +673,8 @@ static int stmmac_init_ptp(struct stmmac static void stmmac_release_ptp(struct stmmac_priv *priv) { @@ -1517,7 +1517,7 @@ stmmac_ptp_unregister(priv); } -@@ -704,7 +689,7 @@ static void stmmac_adjust_link(struct ne +@@ -710,7 +695,7 @@ static void stmmac_adjust_link(struct ne int new_state = 0; unsigned int fc = priv->flow_ctrl, pause_time = priv->pause; @@ -1526,7 +1526,7 @@ return; spin_lock_irqsave(&priv->lock, flags); -@@ -731,33 +716,36 @@ static void stmmac_adjust_link(struct ne +@@ -737,33 +722,36 @@ static void stmmac_adjust_link(struct ne new_state = 1; switch (phydev->speed) { case 1000: @@ -1577,7 +1577,7 @@ priv->speed = phydev->speed; } -@@ -770,8 +758,8 @@ static void stmmac_adjust_link(struct ne +@@ -776,8 +764,8 @@ static void stmmac_adjust_link(struct ne } else if (priv->oldlink) { new_state = 1; priv->oldlink = 0; @@ -1588,7 +1588,7 @@ } if (new_state && netif_msg_link(priv)) -@@ -833,8 +821,8 @@ static int stmmac_init_phy(struct net_de +@@ -839,8 +827,8 @@ static int stmmac_init_phy(struct net_de int interface = priv->plat->interface; int max_speed = priv->plat->max_speed; priv->oldlink = 0; @@ -1599,7 +1599,7 @@ if (priv->plat->phy_node) { phydev = of_phy_connect(dev, priv->plat->phy_node, -@@ -886,9 +874,7 @@ static int stmmac_init_phy(struct net_de +@@ -892,9 +880,7 @@ static int stmmac_init_phy(struct net_de if (phydev->is_pseudo_fixed_link) phydev->irq = PHY_POLL; @@ -1610,7 +1610,7 @@ return 0; } -@@ -1014,7 +1000,7 @@ static void stmmac_free_rx_buffers(struc +@@ -1020,7 +1006,7 @@ static void stmmac_free_rx_buffers(struc * @dev: net device structure * @flags: gfp flag. * Description: this function initializes the DMA RX/TX descriptors @@ -1619,7 +1619,7 @@ * modes. */ static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) -@@ -1127,13 +1113,6 @@ static void dma_free_tx_skbufs(struct st +@@ -1133,13 +1119,6 @@ static void dma_free_tx_skbufs(struct st int i; for (i = 0; i < DMA_TX_SIZE; i++) { @@ -1633,7 +1633,7 @@ if (priv->tx_skbuff_dma[i].buf) { if (priv->tx_skbuff_dma[i].map_as_page) dma_unmap_page(priv->device, -@@ -1147,7 +1126,7 @@ static void dma_free_tx_skbufs(struct st +@@ -1153,7 +1132,7 @@ static void dma_free_tx_skbufs(struct st DMA_TO_DEVICE); } @@ -1642,7 +1642,7 @@ dev_kfree_skb_any(priv->tx_skbuff[i]); priv->tx_skbuff[i] = NULL; priv->tx_skbuff_dma[i].buf = 0; -@@ -1271,6 +1250,28 @@ static void free_dma_desc_resources(stru +@@ -1277,6 +1256,28 @@ static void free_dma_desc_resources(stru } /** @@ -1671,7 +1671,7 @@ * stmmac_dma_operation_mode - HW DMA operation mode * @priv: driver private structure * Description: it is used for configuring the DMA operation mode register in -@@ -1671,10 +1672,6 @@ static int stmmac_hw_setup(struct net_de +@@ -1677,10 +1678,6 @@ static int stmmac_hw_setup(struct net_de /* Copy the MAC addr into the HW */ priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0); @@ -1682,7 +1682,7 @@ /* PS and related bits will be programmed according to the speed */ if (priv->hw->pcs) { int speed = priv->plat->mac_port_sel_speed; -@@ -1691,6 +1688,10 @@ static int stmmac_hw_setup(struct net_de +@@ -1697,6 +1694,10 @@ static int stmmac_hw_setup(struct net_de /* Initialize the MAC Core */ priv->hw->mac->core_init(priv->hw, dev->mtu); @@ -1693,7 +1693,7 @@ ret = priv->hw->mac->rx_ipc(priv->hw); if (!ret) { netdev_warn(priv->dev, "RX IPC Checksum Offload disabled\n"); -@@ -1711,8 +1712,10 @@ static int stmmac_hw_setup(struct net_de +@@ -1717,8 +1718,10 @@ static int stmmac_hw_setup(struct net_de if (init_ptp) { ret = stmmac_init_ptp(priv); @@ -1706,7 +1706,7 @@ } #ifdef CONFIG_DEBUG_FS -@@ -1726,11 +1729,6 @@ static int stmmac_hw_setup(struct net_de +@@ -1732,11 +1735,6 @@ static int stmmac_hw_setup(struct net_de priv->hw->dma->start_tx(priv->ioaddr); priv->hw->dma->start_rx(priv->ioaddr); @@ -1718,7 +1718,7 @@ priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS; if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) { -@@ -2520,7 +2518,7 @@ static int stmmac_rx(struct stmmac_priv +@@ -2526,7 +2524,7 @@ static int stmmac_rx(struct stmmac_priv if (unlikely(status == discard_frame)) { priv->dev->stats.rx_errors++; if (priv->hwts_rx_en && !priv->extend_desc) { @@ -1727,7 +1727,7 @@ * with timestamp value, hence reinitialize * them in stmmac_rx_refill() function so that * device can reuse it. -@@ -2543,7 +2541,7 @@ static int stmmac_rx(struct stmmac_priv +@@ -2549,7 +2547,7 @@ static int stmmac_rx(struct stmmac_priv frame_len = priv->hw->desc->get_rx_frame_len(p, coe); @@ -1736,7 +1736,7 @@ * (preallocated during init) then the packet is * ignored */ -@@ -2763,7 +2761,7 @@ static netdev_features_t stmmac_fix_feat +@@ -2769,7 +2767,7 @@ static netdev_features_t stmmac_fix_feat /* Some GMAC devices have a bugged Jumbo frame support that * needs to have the Tx COE disabled for oversized frames * (due to limited buffer sizes). In this case we disable @@ -1745,7 +1745,7 @@ */ if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN)) features &= ~NETIF_F_CSUM_MASK; -@@ -2909,9 +2907,7 @@ static void sysfs_display_ring(void *hea +@@ -2915,9 +2913,7 @@ static void sysfs_display_ring(void *hea struct dma_desc *p = (struct dma_desc *)head; for (i = 0; i < size; i++) { @@ -1755,7 +1755,7 @@ seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", i, (unsigned int)virt_to_phys(ep), le32_to_cpu(ep->basic.des0), -@@ -2920,7 +2916,6 @@ static void sysfs_display_ring(void *hea +@@ -2926,7 +2922,6 @@ static void sysfs_display_ring(void *hea le32_to_cpu(ep->basic.des3)); ep++; } else { @@ -1763,7 +1763,7 @@ seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", i, (unsigned int)virt_to_phys(ep), le32_to_cpu(p->des0), le32_to_cpu(p->des1), -@@ -2990,7 +2985,7 @@ static int stmmac_sysfs_dma_cap_read(str +@@ -2996,7 +2991,7 @@ static int stmmac_sysfs_dma_cap_read(str (priv->dma_cap.hash_filter) ? "Y" : "N"); seq_printf(seq, "\tMultiple MAC address registers: %s\n", (priv->dma_cap.multi_addr) ? "Y" : "N"); @@ -1772,7 +1772,7 @@ (priv->dma_cap.pcs) ? "Y" : "N"); seq_printf(seq, "\tSMA (MDIO) Interface: %s\n", (priv->dma_cap.sma_mdio) ? "Y" : "N"); -@@ -3266,44 +3261,8 @@ int stmmac_dvr_probe(struct device *devi +@@ -3272,44 +3267,8 @@ int stmmac_dvr_probe(struct device *devi if ((phyaddr >= 0) && (phyaddr <= 31)) priv->plat->phy_addr = phyaddr; @@ -1819,7 +1819,7 @@ /* Init MAC and get the capabilities */ ret = stmmac_hw_init(priv); -@@ -3389,10 +3348,6 @@ error_netdev_register: +@@ -3395,10 +3354,6 @@ error_netdev_register: error_mdio_register: netif_napi_del(&priv->napi); error_hw_init: @@ -1830,7 +1830,7 @@ free_netdev(ndev); return ret; -@@ -3418,10 +3373,10 @@ int stmmac_dvr_remove(struct device *dev +@@ -3424,10 +3379,10 @@ int stmmac_dvr_remove(struct device *dev stmmac_set_mac(priv->ioaddr, false); netif_carrier_off(ndev); unregister_netdev(ndev); @@ -1845,7 +1845,7 @@ if (priv->hw->pcs != STMMAC_PCS_RGMII && priv->hw->pcs != STMMAC_PCS_TBI && priv->hw->pcs != STMMAC_PCS_RTBI) -@@ -3470,14 +3425,14 @@ int stmmac_suspend(struct device *dev) +@@ -3476,14 +3431,14 @@ int stmmac_suspend(struct device *dev) stmmac_set_mac(priv->ioaddr, false); pinctrl_pm_select_sleep_state(priv->device); /* Disable clock in case of PWM is off */ @@ -1864,7 +1864,7 @@ return 0; } EXPORT_SYMBOL_GPL(stmmac_suspend); -@@ -3510,9 +3465,9 @@ int stmmac_resume(struct device *dev) +@@ -3516,9 +3471,9 @@ int stmmac_resume(struct device *dev) priv->irq_wake = 0; } else { pinctrl_pm_select_default_state(priv->device); diff --git a/target/linux/sunxi/patches-4.9/0052-stmmac-form-4-12.patch b/target/linux/sunxi/patches-4.9/0052-stmmac-form-4-12.patch index 18f58e947..1356a4b9e 100644 --- a/target/linux/sunxi/patches-4.9/0052-stmmac-form-4-12.patch +++ b/target/linux/sunxi/patches-4.9/0052-stmmac-form-4-12.patch @@ -2742,7 +2742,7 @@ priv->hw->mac->set_eee_mode(priv->hw, priv->plat->en_tx_lpi_clockgating); } -@@ -359,14 +434,14 @@ static void stmmac_get_tx_hwtstamp(struc +@@ -365,14 +440,14 @@ static void stmmac_get_tx_hwtstamp(struc return; /* check tx tstamp status */ @@ -2759,7 +2759,7 @@ /* pass tstamp to stack */ skb_tstamp_tx(skb, &shhwtstamp); } -@@ -393,19 +468,19 @@ static void stmmac_get_rx_hwtstamp(struc +@@ -399,19 +474,19 @@ static void stmmac_get_rx_hwtstamp(struc return; /* Check if timestamp is available */ @@ -2782,7 +2782,7 @@ } } -@@ -471,7 +546,10 @@ static int stmmac_hwtstamp_ioctl(struct +@@ -477,7 +552,10 @@ static int stmmac_hwtstamp_ioctl(struct /* PTP v1, UDP, any kind of event packet */ config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; /* take time stamp for all event messages */ @@ -2794,7 +2794,7 @@ ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; -@@ -503,7 +581,10 @@ static int stmmac_hwtstamp_ioctl(struct +@@ -509,7 +587,10 @@ static int stmmac_hwtstamp_ioctl(struct config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; ptp_v2 = PTP_TCR_TSVER2ENA; /* take time stamp for all event messages */ @@ -2806,7 +2806,7 @@ ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; -@@ -537,7 +618,10 @@ static int stmmac_hwtstamp_ioctl(struct +@@ -543,7 +624,10 @@ static int stmmac_hwtstamp_ioctl(struct config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; ptp_v2 = PTP_TCR_TSVER2ENA; /* take time stamp for all event messages */ @@ -2818,7 +2818,7 @@ ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; -@@ -673,6 +757,19 @@ static void stmmac_release_ptp(struct st +@@ -679,6 +763,19 @@ static void stmmac_release_ptp(struct st } /** @@ -2838,7 +2838,7 @@ * stmmac_adjust_link - adjusts the link parameters * @dev: net device structure * Description: this is the helper called by the physical abstraction layer -@@ -687,7 +784,6 @@ static void stmmac_adjust_link(struct ne +@@ -693,7 +790,6 @@ static void stmmac_adjust_link(struct ne struct phy_device *phydev = dev->phydev; unsigned long flags; int new_state = 0; @@ -2846,7 +2846,7 @@ if (!phydev) return; -@@ -709,8 +805,7 @@ static void stmmac_adjust_link(struct ne +@@ -715,8 +811,7 @@ static void stmmac_adjust_link(struct ne } /* Flow Control operation */ if (phydev->pause) @@ -2856,7 +2856,7 @@ if (phydev->speed != priv->speed) { new_state = 1; -@@ -878,22 +973,56 @@ static int stmmac_init_phy(struct net_de +@@ -884,22 +979,56 @@ static int stmmac_init_phy(struct net_de return 0; } @@ -2925,7 +2925,7 @@ } static int stmmac_set_bfsize(int mtu, int bufsize) -@@ -913,48 +1042,88 @@ static int stmmac_set_bfsize(int mtu, in +@@ -919,48 +1048,88 @@ static int stmmac_set_bfsize(int mtu, in } /** @@ -3024,7 +3024,7 @@ struct sk_buff *skb; skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags); -@@ -963,20 +1132,20 @@ static int stmmac_init_rx_buffers(struct +@@ -969,20 +1138,20 @@ static int stmmac_init_rx_buffers(struct "%s: Rx init fails; skb is NULL\n", __func__); return -ENOMEM; } @@ -3050,7 +3050,7 @@ if ((priv->hw->mode->init_desc3) && (priv->dma_buf_sz == BUF_SIZE_16KiB)) -@@ -985,30 +1154,71 @@ static int stmmac_init_rx_buffers(struct +@@ -991,30 +1160,71 @@ static int stmmac_init_rx_buffers(struct return 0; } @@ -3131,7 +3131,7 @@ if (priv->hw->mode->set_16kib_bfsize) bfsize = priv->hw->mode->set_16kib_bfsize(dev->mtu); -@@ -1018,235 +1228,409 @@ static int init_dma_desc_rings(struct ne +@@ -1024,235 +1234,409 @@ static int init_dma_desc_rings(struct ne priv->dma_buf_sz = bfsize; @@ -3706,7 +3706,7 @@ } /** -@@ -1256,19 +1640,104 @@ static void free_dma_desc_resources(stru +@@ -1262,19 +1646,104 @@ static void free_dma_desc_resources(stru */ static void stmmac_mac_enable_rx_queues(struct stmmac_priv *priv) { @@ -3822,7 +3822,7 @@ } /** -@@ -1279,11 +1748,20 @@ static void stmmac_mac_enable_rx_queues( +@@ -1285,11 +1754,20 @@ static void stmmac_mac_enable_rx_queues( */ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) { @@ -3847,7 +3847,7 @@ /* * In case of GMAC, SF mode can be enabled * to perform the TX COE in HW. This depends on: -@@ -1291,37 +1769,53 @@ static void stmmac_dma_operation_mode(st +@@ -1297,37 +1775,53 @@ static void stmmac_dma_operation_mode(st * 2) There is no bugged Jumbo frame support * that needs to not insert csum in the TDES. */ @@ -3911,7 +3911,7 @@ status = priv->hw->desc->tx_status(&priv->dev->stats, &priv->xstats, p, -@@ -1342,48 +1836,51 @@ static void stmmac_tx_clean(struct stmma +@@ -1348,48 +1842,51 @@ static void stmmac_tx_clean(struct stmma stmmac_get_tx_hwtstamp(priv, p, skb); } @@ -3981,7 +3981,7 @@ } if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) { -@@ -1393,45 +1890,76 @@ static void stmmac_tx_clean(struct stmma +@@ -1399,45 +1896,76 @@ static void stmmac_tx_clean(struct stmma netif_tx_unlock(priv->dev); } @@ -4073,7 +4073,7 @@ } /** -@@ -1443,31 +1971,43 @@ static void stmmac_tx_err(struct stmmac_ +@@ -1449,31 +1977,43 @@ static void stmmac_tx_err(struct stmmac_ */ static void stmmac_dma_interrupt(struct stmmac_priv *priv) { @@ -4138,7 +4138,7 @@ } /** -@@ -1574,6 +2114,13 @@ static void stmmac_check_ether_addr(stru +@@ -1580,6 +2120,13 @@ static void stmmac_check_ether_addr(stru */ static int stmmac_init_dma_engine(struct stmmac_priv *priv) { @@ -4152,7 +4152,7 @@ int atds = 0; int ret = 0; -@@ -1591,19 +2138,49 @@ static int stmmac_init_dma_engine(struct +@@ -1597,19 +2144,49 @@ static int stmmac_init_dma_engine(struct return ret; } @@ -4214,7 +4214,7 @@ } if (priv->plat->axi && priv->hw->dma->axi) -@@ -1621,8 +2198,12 @@ static int stmmac_init_dma_engine(struct +@@ -1627,8 +2204,12 @@ static int stmmac_init_dma_engine(struct static void stmmac_tx_timer(unsigned long data) { struct stmmac_priv *priv = (struct stmmac_priv *)data; @@ -4228,7 +4228,7 @@ } /** -@@ -1644,6 +2225,196 @@ static void stmmac_init_tx_coalesce(stru +@@ -1650,6 +2231,196 @@ static void stmmac_init_tx_coalesce(stru add_timer(&priv->txtimer); } @@ -4425,7 +4425,7 @@ /** * stmmac_hw_setup - setup mac in a usable state. * @dev : pointer to the device structure. -@@ -1659,6 +2430,9 @@ static void stmmac_init_tx_coalesce(stru +@@ -1665,6 +2436,9 @@ static void stmmac_init_tx_coalesce(stru static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) { struct stmmac_priv *priv = netdev_priv(dev); @@ -4435,7 +4435,7 @@ int ret; /* DMA initialization and SW reset */ -@@ -1688,9 +2462,9 @@ static int stmmac_hw_setup(struct net_de +@@ -1694,9 +2468,9 @@ static int stmmac_hw_setup(struct net_de /* Initialize the MAC Core */ priv->hw->mac->core_init(priv->hw, dev->mtu); @@ -4448,7 +4448,7 @@ ret = priv->hw->mac->rx_ipc(priv->hw); if (!ret) { -@@ -1700,10 +2474,7 @@ static int stmmac_hw_setup(struct net_de +@@ -1706,10 +2480,7 @@ static int stmmac_hw_setup(struct net_de } /* Enable the MAC Rx/Tx */ @@ -4460,7 +4460,7 @@ /* Set the HW DMA mode and the COE */ stmmac_dma_operation_mode(priv); -@@ -1711,6 +2482,10 @@ static int stmmac_hw_setup(struct net_de +@@ -1717,6 +2488,10 @@ static int stmmac_hw_setup(struct net_de stmmac_mmc_setup(priv); if (init_ptp) { @@ -4471,7 +4471,7 @@ ret = stmmac_init_ptp(priv); if (ret == -EOPNOTSUPP) netdev_warn(priv->dev, "PTP not supported by HW\n"); -@@ -1725,35 +2500,37 @@ static int stmmac_hw_setup(struct net_de +@@ -1731,35 +2506,37 @@ static int stmmac_hw_setup(struct net_de __func__); #endif /* Start the ball rolling... */ @@ -4523,7 +4523,7 @@ /** * stmmac_open - open entry point of the driver * @dev : pointer to the device structure. -@@ -1822,7 +2599,7 @@ static int stmmac_open(struct net_device +@@ -1828,7 +2605,7 @@ static int stmmac_open(struct net_device netdev_err(priv->dev, "%s: ERROR: allocating the IRQ %d (error: %d)\n", __func__, dev->irq, ret); @@ -4532,7 +4532,7 @@ } /* Request the Wake IRQ in case of another line is used for WoL */ -@@ -1849,8 +2626,8 @@ static int stmmac_open(struct net_device +@@ -1855,8 +2632,8 @@ static int stmmac_open(struct net_device } } @@ -4543,7 +4543,7 @@ return 0; -@@ -1859,7 +2636,12 @@ lpiirq_error: +@@ -1865,7 +2642,12 @@ lpiirq_error: free_irq(priv->wol_irq, dev); wolirq_error: free_irq(dev->irq, dev); @@ -4556,7 +4556,7 @@ init_error: free_dma_desc_resources(priv); dma_desc_error: -@@ -1888,9 +2670,9 @@ static int stmmac_release(struct net_dev +@@ -1894,9 +2676,9 @@ static int stmmac_release(struct net_dev phy_disconnect(dev->phydev); } @@ -4568,7 +4568,7 @@ del_timer_sync(&priv->txtimer); -@@ -1902,14 +2684,13 @@ static int stmmac_release(struct net_dev +@@ -1908,14 +2690,13 @@ static int stmmac_release(struct net_dev free_irq(priv->lpi_irq, dev); /* Stop TX/RX DMA and clear the descriptors */ @@ -4585,7 +4585,7 @@ netif_carrier_off(dev); -@@ -1928,22 +2709,24 @@ static int stmmac_release(struct net_dev +@@ -1934,22 +2715,24 @@ static int stmmac_release(struct net_dev * @des: buffer start address * @total_len: total length to fill in descriptors * @last_segmant: condition for the last descriptor @@ -4614,7 +4614,7 @@ desc->des0 = cpu_to_le32(des + (total_len - tmp_len)); buff_size = tmp_len >= TSO_MAX_BUFF_SIZE ? -@@ -1951,7 +2734,7 @@ static void stmmac_tso_allocator(struct +@@ -1957,7 +2740,7 @@ static void stmmac_tso_allocator(struct priv->hw->desc->prepare_tso_tx_desc(desc, 0, buff_size, 0, 1, @@ -4623,7 +4623,7 @@ 0, 0); tmp_len -= TSO_MAX_BUFF_SIZE; -@@ -1987,23 +2770,28 @@ static void stmmac_tso_allocator(struct +@@ -1993,23 +2776,28 @@ static void stmmac_tso_allocator(struct */ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -4658,7 +4658,7 @@ /* This is a hard error, log it. */ netdev_err(priv->dev, "%s: Tx Ring full when queue awake\n", -@@ -2018,10 +2806,10 @@ static netdev_tx_t stmmac_tso_xmit(struc +@@ -2024,10 +2812,10 @@ static netdev_tx_t stmmac_tso_xmit(struc /* set new MSS value if needed */ if (mss != priv->mss) { @@ -4671,7 +4671,7 @@ } if (netif_msg_tx_queued(priv)) { -@@ -2031,9 +2819,9 @@ static netdev_tx_t stmmac_tso_xmit(struc +@@ -2037,9 +2825,9 @@ static netdev_tx_t stmmac_tso_xmit(struc skb->data_len); } @@ -4683,7 +4683,7 @@ first = desc; /* first descriptor: fill Headers on Buf1 */ -@@ -2042,9 +2830,8 @@ static netdev_tx_t stmmac_tso_xmit(struc +@@ -2048,9 +2836,8 @@ static netdev_tx_t stmmac_tso_xmit(struc if (dma_mapping_error(priv->device, des)) goto dma_map_err; @@ -4695,7 +4695,7 @@ first->des0 = cpu_to_le32(des); -@@ -2055,7 +2842,7 @@ static netdev_tx_t stmmac_tso_xmit(struc +@@ -2061,7 +2848,7 @@ static netdev_tx_t stmmac_tso_xmit(struc /* If needed take extra descriptors to fill the remaining payload */ tmp_pay_len = pay_len - TSO_MAX_BUFF_SIZE; @@ -4704,7 +4704,7 @@ /* Prepare fragments */ for (i = 0; i < nfrags; i++) { -@@ -2064,24 +2851,34 @@ static netdev_tx_t stmmac_tso_xmit(struc +@@ -2070,24 +2857,34 @@ static netdev_tx_t stmmac_tso_xmit(struc des = skb_frag_dma_map(priv->device, frag, 0, skb_frag_size(frag), DMA_TO_DEVICE); @@ -4748,7 +4748,7 @@ } dev->stats.tx_bytes += skb->len; -@@ -2113,7 +2910,7 @@ static netdev_tx_t stmmac_tso_xmit(struc +@@ -2119,7 +2916,7 @@ static netdev_tx_t stmmac_tso_xmit(struc priv->hw->desc->prepare_tso_tx_desc(first, 1, proto_hdr_len, pay_len, @@ -4757,7 +4757,7 @@ tcp_hdrlen(skb) / 4, (skb->len - proto_hdr_len)); /* If context desc is used to change MSS */ -@@ -2128,20 +2925,20 @@ static netdev_tx_t stmmac_tso_xmit(struc +@@ -2134,20 +2931,20 @@ static netdev_tx_t stmmac_tso_xmit(struc if (netif_msg_pktdata(priv)) { pr_info("%s: curr=%d dirty=%d f=%d, e=%d, f_p=%p, nfrags %d\n", @@ -4784,7 +4784,7 @@ return NETDEV_TX_OK; -@@ -2165,21 +2962,27 @@ static netdev_tx_t stmmac_xmit(struct sk +@@ -2171,21 +2968,27 @@ static netdev_tx_t stmmac_xmit(struct sk struct stmmac_priv *priv = netdev_priv(dev); unsigned int nopaged_len = skb_headlen(skb); int i, csum_insertion = 0, is_jumbo = 0; @@ -4816,7 +4816,7 @@ /* This is a hard error, log it. */ netdev_err(priv->dev, "%s: Tx Ring full when queue awake\n", -@@ -2191,20 +2994,18 @@ static netdev_tx_t stmmac_xmit(struct sk +@@ -2197,20 +3000,18 @@ static netdev_tx_t stmmac_xmit(struct sk if (priv->tx_path_in_lpi_mode) stmmac_disable_eee_mode(priv); @@ -4840,7 +4840,7 @@ enh_desc = priv->plat->enh_desc; /* To program the descriptors according to the size of the frame */ if (enh_desc) -@@ -2212,7 +3013,7 @@ static netdev_tx_t stmmac_xmit(struct sk +@@ -2218,7 +3019,7 @@ static netdev_tx_t stmmac_xmit(struct sk if (unlikely(is_jumbo) && likely(priv->synopsys_id < DWMAC_CORE_4_00)) { @@ -4849,7 +4849,7 @@ if (unlikely(entry < 0)) goto dma_map_err; } -@@ -2225,48 +3026,56 @@ static netdev_tx_t stmmac_xmit(struct sk +@@ -2231,48 +3032,56 @@ static netdev_tx_t stmmac_xmit(struct sk entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); if (likely(priv->extend_desc)) @@ -4919,7 +4919,7 @@ priv->hw->desc->display_ring(tx_head, DMA_TX_SIZE, false); -@@ -2274,10 +3083,10 @@ static netdev_tx_t stmmac_xmit(struct sk +@@ -2280,10 +3089,10 @@ static netdev_tx_t stmmac_xmit(struct sk print_pkt(skb->data, skb->len); } @@ -4932,7 +4932,7 @@ } dev->stats.tx_bytes += skb->len; -@@ -2312,14 +3121,14 @@ static netdev_tx_t stmmac_xmit(struct sk +@@ -2318,14 +3127,14 @@ static netdev_tx_t stmmac_xmit(struct sk if (dma_mapping_error(priv->device, des)) goto dma_map_err; @@ -4950,7 +4950,7 @@ if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && priv->hwts_tx_en)) { -@@ -2331,7 +3140,7 @@ static netdev_tx_t stmmac_xmit(struct sk +@@ -2337,7 +3146,7 @@ static netdev_tx_t stmmac_xmit(struct sk /* Prepare the first descriptor setting the OWN bit too */ priv->hw->desc->prepare_tx_desc(first, 1, nopaged_len, csum_insertion, priv->mode, 1, @@ -4959,7 +4959,7 @@ /* The own bit must be the latest setting done when prepare the * descriptor and then barrier is needed to make sure that -@@ -2340,13 +3149,13 @@ static netdev_tx_t stmmac_xmit(struct sk +@@ -2346,13 +3155,13 @@ static netdev_tx_t stmmac_xmit(struct sk dma_wmb(); } @@ -4976,7 +4976,7 @@ return NETDEV_TX_OK; -@@ -2374,9 +3183,9 @@ static void stmmac_rx_vlan(struct net_de +@@ -2380,9 +3189,9 @@ static void stmmac_rx_vlan(struct net_de } @@ -4988,7 +4988,7 @@ return 0; return 1; -@@ -2385,30 +3194,33 @@ static inline int stmmac_rx_threshold_co +@@ -2391,30 +3200,33 @@ static inline int stmmac_rx_threshold_co /** * stmmac_rx_refill - refill used skb preallocated buffers * @priv: driver private structure @@ -5029,7 +5029,7 @@ if (unlikely(net_ratelimit())) dev_err(priv->device, "fail to alloc skb entry %d\n", -@@ -2416,28 +3228,28 @@ static inline void stmmac_rx_refill(stru +@@ -2422,28 +3234,28 @@ static inline void stmmac_rx_refill(stru break; } @@ -5066,7 +5066,7 @@ netif_dbg(priv, rx_status, priv->dev, "refill entry #%d\n", entry); -@@ -2453,31 +3265,33 @@ static inline void stmmac_rx_refill(stru +@@ -2459,31 +3271,33 @@ static inline void stmmac_rx_refill(stru entry = STMMAC_GET_ENTRY(entry, DMA_RX_SIZE); } @@ -5107,7 +5107,7 @@ priv->hw->desc->display_ring(rx_head, DMA_RX_SIZE, true); } -@@ -2487,9 +3301,9 @@ static int stmmac_rx(struct stmmac_priv +@@ -2493,9 +3307,9 @@ static int stmmac_rx(struct stmmac_priv struct dma_desc *np; if (priv->extend_desc) @@ -5119,7 +5119,7 @@ /* read the status of the incoming frame */ status = priv->hw->desc->rx_status(&priv->dev->stats, -@@ -2500,20 +3314,20 @@ static int stmmac_rx(struct stmmac_priv +@@ -2506,20 +3320,20 @@ static int stmmac_rx(struct stmmac_priv count++; @@ -5145,7 +5145,7 @@ entry); if (unlikely(status == discard_frame)) { priv->dev->stats.rx_errors++; -@@ -2523,9 +3337,9 @@ static int stmmac_rx(struct stmmac_priv +@@ -2529,9 +3343,9 @@ static int stmmac_rx(struct stmmac_priv * them in stmmac_rx_refill() function so that * device can reuse it. */ @@ -5157,7 +5157,7 @@ priv->dma_buf_sz, DMA_FROM_DEVICE); } -@@ -2573,7 +3387,7 @@ static int stmmac_rx(struct stmmac_priv +@@ -2579,7 +3393,7 @@ static int stmmac_rx(struct stmmac_priv */ if (unlikely(!priv->plat->has_gmac4 && ((frame_len < priv->rx_copybreak) || @@ -5166,7 +5166,7 @@ skb = netdev_alloc_skb_ip_align(priv->dev, frame_len); if (unlikely(!skb)) { -@@ -2585,21 +3399,21 @@ static int stmmac_rx(struct stmmac_priv +@@ -2591,21 +3405,21 @@ static int stmmac_rx(struct stmmac_priv } dma_sync_single_for_cpu(priv->device, @@ -5192,7 +5192,7 @@ if (unlikely(!skb)) { netdev_err(priv->dev, "%s: Inconsistent Rx chain\n", -@@ -2608,12 +3422,12 @@ static int stmmac_rx(struct stmmac_priv +@@ -2614,12 +3428,12 @@ static int stmmac_rx(struct stmmac_priv break; } prefetch(skb->data - NET_IP_ALIGN); @@ -5208,7 +5208,7 @@ priv->dma_buf_sz, DMA_FROM_DEVICE); } -@@ -2635,7 +3449,7 @@ static int stmmac_rx(struct stmmac_priv +@@ -2641,7 +3455,7 @@ static int stmmac_rx(struct stmmac_priv else skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -5217,7 +5217,7 @@ priv->dev->stats.rx_packets++; priv->dev->stats.rx_bytes += frame_len; -@@ -2643,7 +3457,7 @@ static int stmmac_rx(struct stmmac_priv +@@ -2649,7 +3463,7 @@ static int stmmac_rx(struct stmmac_priv entry = next_entry; } @@ -5226,7 +5226,7 @@ priv->xstats.rx_pkt_n += count; -@@ -2660,16 +3474,24 @@ static int stmmac_rx(struct stmmac_priv +@@ -2666,16 +3480,24 @@ static int stmmac_rx(struct stmmac_priv */ static int stmmac_poll(struct napi_struct *napi, int budget) { @@ -5255,7 +5255,7 @@ } return work_done; } -@@ -2685,9 +3507,12 @@ static int stmmac_poll(struct napi_struc +@@ -2691,9 +3513,12 @@ static int stmmac_poll(struct napi_struc static void stmmac_tx_timeout(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); @@ -5269,7 +5269,7 @@ } /** -@@ -2810,6 +3635,12 @@ static irqreturn_t stmmac_interrupt(int +@@ -2816,6 +3641,12 @@ static irqreturn_t stmmac_interrupt(int { struct net_device *dev = (struct net_device *)dev_id; struct stmmac_priv *priv = netdev_priv(dev); @@ -5282,7 +5282,7 @@ if (priv->irq_wake) pm_wakeup_event(priv->device, 0); -@@ -2823,16 +3654,30 @@ static irqreturn_t stmmac_interrupt(int +@@ -2829,16 +3660,30 @@ static irqreturn_t stmmac_interrupt(int if ((priv->plat->has_gmac) || (priv->plat->has_gmac4)) { int status = priv->hw->mac->host_irq_status(priv->hw, &priv->xstats); @@ -5317,7 +5317,7 @@ } /* PCS link status */ -@@ -2917,7 +3762,7 @@ static void sysfs_display_ring(void *hea +@@ -2923,7 +3768,7 @@ static void sysfs_display_ring(void *hea ep++; } else { seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", @@ -5326,7 +5326,7 @@ le32_to_cpu(p->des0), le32_to_cpu(p->des1), le32_to_cpu(p->des2), le32_to_cpu(p->des3)); p++; -@@ -2930,17 +3775,40 @@ static int stmmac_sysfs_ring_read(struct +@@ -2936,17 +3781,40 @@ static int stmmac_sysfs_ring_read(struct { struct net_device *dev = seq->private; struct stmmac_priv *priv = netdev_priv(dev); @@ -5377,7 +5377,7 @@ } return 0; -@@ -3223,11 +4091,14 @@ int stmmac_dvr_probe(struct device *devi +@@ -3229,11 +4097,14 @@ int stmmac_dvr_probe(struct device *devi struct plat_stmmacenet_data *plat_dat, struct stmmac_resources *res) { @@ -5394,7 +5394,7 @@ if (!ndev) return -ENOMEM; -@@ -3269,6 +4140,10 @@ int stmmac_dvr_probe(struct device *devi +@@ -3275,6 +4146,10 @@ int stmmac_dvr_probe(struct device *devi if (ret) goto error_hw_init; @@ -5405,7 +5405,7 @@ ndev->netdev_ops = &stmmac_netdev_ops; ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | -@@ -3301,7 +4176,12 @@ int stmmac_dvr_probe(struct device *devi +@@ -3307,7 +4182,12 @@ int stmmac_dvr_probe(struct device *devi "Enable RX Mitigation via HW Watchdog Timer\n"); } @@ -5419,7 +5419,7 @@ spin_lock_init(&priv->lock); -@@ -3346,7 +4226,11 @@ error_netdev_register: +@@ -3352,7 +4232,11 @@ error_netdev_register: priv->hw->pcs != STMMAC_PCS_RTBI) stmmac_mdio_unregister(ndev); error_mdio_register: @@ -5432,7 +5432,7 @@ error_hw_init: free_netdev(ndev); -@@ -3367,10 +4251,9 @@ int stmmac_dvr_remove(struct device *dev +@@ -3373,10 +4257,9 @@ int stmmac_dvr_remove(struct device *dev netdev_info(priv->dev, "%s: removing driver", __func__); @@ -5445,7 +5445,7 @@ netif_carrier_off(ndev); unregister_netdev(ndev); if (priv->plat->stmmac_rst) -@@ -3409,20 +4292,19 @@ int stmmac_suspend(struct device *dev) +@@ -3415,20 +4298,19 @@ int stmmac_suspend(struct device *dev) spin_lock_irqsave(&priv->lock, flags); netif_device_detach(ndev); @@ -5470,7 +5470,7 @@ pinctrl_pm_select_sleep_state(priv->device); /* Disable clock in case of PWM is off */ clk_disable(priv->plat->pclk); -@@ -3438,6 +4320,31 @@ int stmmac_suspend(struct device *dev) +@@ -3444,6 +4326,31 @@ int stmmac_suspend(struct device *dev) EXPORT_SYMBOL_GPL(stmmac_suspend); /** @@ -5502,7 +5502,7 @@ * stmmac_resume - resume callback * @dev: device pointer * Description: when resume this function is invoked to setup the DMA and CORE -@@ -3477,10 +4384,8 @@ int stmmac_resume(struct device *dev) +@@ -3483,10 +4390,8 @@ int stmmac_resume(struct device *dev) spin_lock_irqsave(&priv->lock, flags); @@ -5515,7 +5515,7 @@ /* reset private mss value to force mss context settings at * next tso xmit (only used for gmac4). */ -@@ -3492,9 +4397,9 @@ int stmmac_resume(struct device *dev) +@@ -3498,9 +4403,9 @@ int stmmac_resume(struct device *dev) stmmac_init_tx_coalesce(priv); stmmac_set_rx_mode(ndev); diff --git a/target/linux/sunxi/patches-4.9/0053-stmmac-form-4-13.patch b/target/linux/sunxi/patches-4.9/0053-stmmac-form-4-13.patch index 161e9f0e6..a5d860ddc 100644 --- a/target/linux/sunxi/patches-4.9/0053-stmmac-form-4-13.patch +++ b/target/linux/sunxi/patches-4.9/0053-stmmac-form-4-13.patch @@ -1347,7 +1347,7 @@ } static void print_pkt(unsigned char *buf, int len) -@@ -783,7 +794,7 @@ static void stmmac_adjust_link(struct ne +@@ -789,7 +800,7 @@ static void stmmac_adjust_link(struct ne struct stmmac_priv *priv = netdev_priv(dev); struct phy_device *phydev = dev->phydev; unsigned long flags; @@ -1356,7 +1356,7 @@ if (!phydev) return; -@@ -796,8 +807,8 @@ static void stmmac_adjust_link(struct ne +@@ -802,8 +813,8 @@ static void stmmac_adjust_link(struct ne /* Now we make sure that we can be in full duplex mode. * If not, we operate in half-duplex mode. */ if (phydev->duplex != priv->oldduplex) { @@ -1367,7 +1367,7 @@ ctrl &= ~priv->hw->link.duplex; else ctrl |= priv->hw->link.duplex; -@@ -808,30 +819,17 @@ static void stmmac_adjust_link(struct ne +@@ -814,30 +825,17 @@ static void stmmac_adjust_link(struct ne stmmac_mac_flow_ctrl(priv, phydev->duplex); if (phydev->speed != priv->speed) { @@ -1406,7 +1406,7 @@ break; default: netif_warn(priv, link, priv->dev, -@@ -847,12 +845,12 @@ static void stmmac_adjust_link(struct ne +@@ -853,12 +851,12 @@ static void stmmac_adjust_link(struct ne writel(ctrl, priv->ioaddr + MAC_CTRL_REG); if (!priv->oldlink) { @@ -1423,7 +1423,7 @@ priv->speed = SPEED_UNKNOWN; priv->oldduplex = DUPLEX_UNKNOWN; } -@@ -915,7 +913,7 @@ static int stmmac_init_phy(struct net_de +@@ -921,7 +919,7 @@ static int stmmac_init_phy(struct net_de char bus_id[MII_BUS_ID_SIZE]; int interface = priv->plat->interface; int max_speed = priv->plat->max_speed; @@ -1432,7 +1432,7 @@ priv->speed = SPEED_UNKNOWN; priv->oldduplex = DUPLEX_UNKNOWN; -@@ -1450,7 +1448,7 @@ static void free_dma_rx_desc_resources(s +@@ -1456,7 +1454,7 @@ static void free_dma_rx_desc_resources(s static void free_dma_tx_desc_resources(struct stmmac_priv *priv) { u32 tx_count = priv->plat->tx_queues_to_use; @@ -1441,7 +1441,7 @@ /* Free TX queue resources */ for (queue = 0; queue < tx_count; queue++) { -@@ -1499,7 +1497,7 @@ static int alloc_dma_rx_desc_resources(s +@@ -1505,7 +1503,7 @@ static int alloc_dma_rx_desc_resources(s sizeof(dma_addr_t), GFP_KERNEL); if (!rx_q->rx_skbuff_dma) @@ -1450,7 +1450,7 @@ rx_q->rx_skbuff = kmalloc_array(DMA_RX_SIZE, sizeof(struct sk_buff *), -@@ -1562,13 +1560,13 @@ static int alloc_dma_tx_desc_resources(s +@@ -1568,13 +1566,13 @@ static int alloc_dma_tx_desc_resources(s sizeof(*tx_q->tx_skbuff_dma), GFP_KERNEL); if (!tx_q->tx_skbuff_dma) @@ -1466,7 +1466,7 @@ if (priv->extend_desc) { tx_q->dma_etx = dma_zalloc_coherent(priv->device, -@@ -1578,7 +1576,7 @@ static int alloc_dma_tx_desc_resources(s +@@ -1584,7 +1582,7 @@ static int alloc_dma_tx_desc_resources(s &tx_q->dma_tx_phy, GFP_KERNEL); if (!tx_q->dma_etx) @@ -1475,7 +1475,7 @@ } else { tx_q->dma_tx = dma_zalloc_coherent(priv->device, DMA_TX_SIZE * -@@ -1587,13 +1585,13 @@ static int alloc_dma_tx_desc_resources(s +@@ -1593,13 +1591,13 @@ static int alloc_dma_tx_desc_resources(s &tx_q->dma_tx_phy, GFP_KERNEL); if (!tx_q->dma_tx) @@ -1491,7 +1491,7 @@ free_dma_tx_desc_resources(priv); return ret; -@@ -2896,8 +2894,7 @@ static netdev_tx_t stmmac_tso_xmit(struc +@@ -2902,8 +2900,7 @@ static netdev_tx_t stmmac_tso_xmit(struc priv->xstats.tx_set_ic_bit++; } @@ -1501,7 +1501,7 @@ if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && priv->hwts_tx_en)) { -@@ -2975,7 +2972,7 @@ static netdev_tx_t stmmac_xmit(struct sk +@@ -2981,7 +2978,7 @@ static netdev_tx_t stmmac_xmit(struct sk /* Manage oversized TCP frames for GMAC4 device */ if (skb_is_gso(skb) && priv->tso) { @@ -1510,7 +1510,7 @@ return stmmac_tso_xmit(skb, dev); } -@@ -3106,8 +3103,7 @@ static netdev_tx_t stmmac_xmit(struct sk +@@ -3112,8 +3109,7 @@ static netdev_tx_t stmmac_xmit(struct sk priv->xstats.tx_set_ic_bit++; } @@ -1520,7 +1520,7 @@ /* Ready to fill the first descriptor and set the OWN bit w/o any * problems because all the descriptors are actually ready to be -@@ -3984,7 +3980,9 @@ static int stmmac_hw_init(struct stmmac_ +@@ -3990,7 +3986,9 @@ static int stmmac_hw_init(struct stmmac_ struct mac_device_info *mac; /* Identify the MAC HW device */ @@ -1531,7 +1531,7 @@ priv->dev->priv_flags |= IFF_UNICAST_FLT; mac = dwmac1000_setup(priv->ioaddr, priv->plat->multicast_filter_bins, -@@ -4004,6 +4002,10 @@ static int stmmac_hw_init(struct stmmac_ +@@ -4010,6 +4008,10 @@ static int stmmac_hw_init(struct stmmac_ priv->hw = mac; @@ -1542,7 +1542,7 @@ /* To use the chained or ring mode */ if (priv->synopsys_id >= DWMAC_CORE_4_00) { priv->hw->mode = &dwmac4_ring_mode_ops; -@@ -4132,8 +4134,15 @@ int stmmac_dvr_probe(struct device *devi +@@ -4138,8 +4140,15 @@ int stmmac_dvr_probe(struct device *devi if ((phyaddr >= 0) && (phyaddr <= 31)) priv->plat->phy_addr = phyaddr; @@ -1559,7 +1559,7 @@ /* Init MAC and get the capabilities */ ret = stmmac_hw_init(priv); -@@ -4150,7 +4159,7 @@ int stmmac_dvr_probe(struct device *devi +@@ -4156,7 +4165,7 @@ int stmmac_dvr_probe(struct device *devi NETIF_F_RXCSUM; if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) { @@ -1568,7 +1568,7 @@ priv->tso = true; dev_info(priv->device, "TSO feature enabled\n"); } -@@ -4312,7 +4321,7 @@ int stmmac_suspend(struct device *dev) +@@ -4318,7 +4327,7 @@ int stmmac_suspend(struct device *dev) } spin_unlock_irqrestore(&priv->lock, flags); diff --git a/target/linux/x86/64/config-default b/target/linux/x86/64/config-default index faaba8064..f2ed18797 100644 --- a/target/linux/x86/64/config-default +++ b/target/linux/x86/64/config-default @@ -6,7 +6,6 @@ CONFIG_ACPI_BATTERY=y CONFIG_ACPI_BUTTON=y # CONFIG_ACPI_CMPC is not set CONFIG_ACPI_CONTAINER=y -CONFIG_ACPI_CPPC_LIB=y CONFIG_ACPI_CPU_FREQ_PSS=y # CONFIG_ACPI_CUSTOM_DSDT is not set # CONFIG_ACPI_DEBUG is not set @@ -16,48 +15,45 @@ CONFIG_ACPI_CPU_FREQ_PSS=y CONFIG_ACPI_FAN=y CONFIG_ACPI_HOTPLUG_CPU=y CONFIG_ACPI_HOTPLUG_IOAPIC=y -# CONFIG_ACPI_I2C_OPREGION is not set +# CONFIG_ACPI_INITRD_TABLE_OVERRIDE is not set CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y +# CONFIG_ACPI_NFIT is not set # CONFIG_ACPI_PCI_SLOT is not set CONFIG_ACPI_PROCESSOR=y # CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set -CONFIG_ACPI_PROCESSOR_CSTATE=y CONFIG_ACPI_PROCESSOR_IDLE=y # CONFIG_ACPI_PROCFS_POWER is not set CONFIG_ACPI_REV_OVERRIDE_POSSIBLE=y # CONFIG_ACPI_SBS is not set CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y CONFIG_ACPI_THERMAL=y +# CONFIG_ACPI_VIDEO is not set # CONFIG_ACPI_WMI is not set CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig" -CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y -CONFIG_ARCH_HAS_ADD_PAGES=y -CONFIG_ARCH_HAS_KCOV=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y CONFIG_ARCH_HAS_PMEM_API=y -CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE=y -CONFIG_ARCH_HAS_ZONE_DEVICE=y +CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y -CONFIG_ARCH_MMAP_RND_BITS=28 -CONFIG_ARCH_MMAP_RND_BITS_MAX=32 -CONFIG_ARCH_MMAP_RND_BITS_MIN=28 +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_ARCH_SUPPORTS_INT128=y CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y -CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y CONFIG_AUDIT_ARCH=y +# CONFIG_BACKLIGHT_APPLE is not set CONFIG_BACKLIGHT_CLASS_DEVICE=y CONFIG_BACKLIGHT_GENERIC=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_BLK_DEV_INTEGRITY=y -CONFIG_BLK_MQ_VIRTIO=y # CONFIG_BOOTPARAM_HOTPLUG_CPU0 is not set CONFIG_CALGARY_IOMMU=y CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y CONFIG_CONNECTOR=y -# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set CONFIG_CPU_RMAP=y CONFIG_CRC_T10DIF=y +CONFIG_CRYPTO_ABLK_HELPER=y CONFIG_CRYPTO_AEAD=y CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_AES_NI_INTEL=y @@ -73,7 +69,6 @@ CONFIG_CRYPTO_CRCT10DIF=y # CONFIG_CRYPTO_CRCT10DIF_PCLMUL is not set CONFIG_CRYPTO_CRYPTD=y # CONFIG_CRYPTO_DES3_EDE_X86_64 is not set -CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_GF128MUL=y CONFIG_CRYPTO_GLUE_HELPER_X86=y CONFIG_CRYPTO_LRW=y @@ -87,24 +82,17 @@ CONFIG_CRYPTO_NULL2=y # CONFIG_CRYPTO_SERPENT_SSE2_X86_64 is not set # CONFIG_CRYPTO_SHA1_MB is not set # CONFIG_CRYPTO_SHA1_SSSE3 is not set -# CONFIG_CRYPTO_SHA256_MB is not set # CONFIG_CRYPTO_SHA256_SSSE3 is not set -# CONFIG_CRYPTO_SHA512_MB is not set # CONFIG_CRYPTO_SHA512_SSSE3 is not set -CONFIG_CRYPTO_SIMD=y # CONFIG_CRYPTO_SKEIN is not set # CONFIG_CRYPTO_TWOFISH_AVX_X86_64 is not set # CONFIG_CRYPTO_TWOFISH_X86_64 is not set # CONFIG_CRYPTO_TWOFISH_X86_64_3WAY is not set CONFIG_CRYPTO_XTS=y # CONFIG_DEBUG_HOTPLUG_CPU0 is not set -# CONFIG_DPTF_POWER is not set # CONFIG_EARLY_PRINTK_EFI is not set CONFIG_EFI=y CONFIG_EFIVAR_FS=m -# CONFIG_EFI_BOOTLOADER_CONTROL is not set -# CONFIG_EFI_CAPSULE_LOADER is not set -# CONFIG_EFI_DEV_PATH_PARSER is not set CONFIG_EFI_ESRT=y # CONFIG_EFI_FAKE_MEMMAP is not set # CONFIG_EFI_MIXED is not set @@ -112,7 +100,6 @@ CONFIG_EFI_ESRT=y CONFIG_EFI_RUNTIME_MAP=y CONFIG_EFI_RUNTIME_WRAPPERS=y CONFIG_EFI_STUB=y -# CONFIG_EFI_TEST is not set CONFIG_EFI_VARS=y CONFIG_FB=y CONFIG_FB_CFB_COPYAREA=y @@ -142,34 +129,32 @@ CONFIG_FREEZER=y CONFIG_GART_IOMMU=y CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y CONFIG_GENERIC_CPU=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_MIGRATION=y CONFIG_GENERIC_PENDING_IRQ=y CONFIG_GPIOLIB=y -CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_GPIO_104_IDIO_16 is not set CONFIG_GPIO_ACPI=y -CONFIG_GPIO_ICH=y -CONFIG_GPIO_IT87=y -CONFIG_GPIO_LYNXPOINT=y -CONFIG_GPIO_SCH=y +# CONFIG_GPIO_AMDPT is not set +CONFIG_GPIO_DEVRES=y +# CONFIG_GPIO_F7188X is not set +# CONFIG_GPIO_INTEL_MID is not set +# CONFIG_GPIO_IT87 is not set +# CONFIG_GPIO_LYNXPOINT is not set CONFIG_GPIO_SYSFS=y -CONFIG_HARDLOCKUP_CHECK_TIMESTAMP=y CONFIG_HAVE_ACPI_APEI=y CONFIG_HAVE_ACPI_APEI_NMI=y # CONFIG_HAVE_AOUT is not set +CONFIG_HAVE_ARCH_HUGE_VMAP=y CONFIG_HAVE_ARCH_SOFT_DIRTY=y -CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD=y -CONFIG_HAVE_ARCH_VMAP_STACK=y +CONFIG_HAVE_BPF_JIT=y CONFIG_HAVE_CONTEXT_TRACKING=y -CONFIG_HAVE_EBPF_JIT=y CONFIG_HAVE_FENTRY=y # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y CONFIG_HAVE_LIVEPATCH=y CONFIG_HAVE_MEMORY_PRESENT=y -CONFIG_HAVE_STACK_VALIDATION=y CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_HIBERNATE_CALLBACKS=y +CONFIG_HID=y CONFIG_HID_BATTERY_STRENGTH=y CONFIG_HID_GENERIC=y CONFIG_HID_HYPERV_MOUSE=y @@ -187,8 +172,6 @@ CONFIG_HVC_DRIVER=y CONFIG_HVC_IRQ=y CONFIG_HVC_XEN=y CONFIG_HVC_XEN_FRONTEND=y -CONFIG_HWMON=y -CONFIG_HWMON_VID=y CONFIG_HW_RANDOM_AMD=y CONFIG_HW_RANDOM_INTEL=y CONFIG_HW_RANDOM_VIRTIO=y @@ -198,30 +181,20 @@ CONFIG_HYPERV_BALLOON=y CONFIG_HYPERV_KEYBOARD=y CONFIG_HYPERV_NET=y CONFIG_HYPERV_STORAGE=y -CONFIG_HYPERV_TSCPAGE=y CONFIG_HYPERV_UTILS=y -# CONFIG_HYPERV_VSOCKETS is not set -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y # CONFIG_I7300_IDLE is not set # CONFIG_IA32_EMULATION is not set CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 CONFIG_INPUT_XEN_KBDDEV_FRONTEND=y -CONFIG_INTEL_IDLE=y -# CONFIG_INTEL_INT0002_VGPIO is not set # CONFIG_INTEL_IPS is not set # CONFIG_INTEL_MENLOW is not set # CONFIG_INTEL_MIC_BUS is not set -CONFIG_INTEL_PCH_THERMAL=y # CONFIG_INTEL_PMC_IPC is not set -CONFIG_INTEL_SOC_DTS_IOSF_CORE=y -CONFIG_INTEL_SOC_DTS_THERMAL=y -# CONFIG_INTEL_TURBO_MAX_3 is not set # CONFIG_IOMMU_DEBUG is not set -CONFIG_IOSF_MBI=y -# CONFIG_IOSF_MBI_DEBUG is not set +CONFIG_IOMMU_HELPER=y # CONFIG_ISCSI_IBFT_FIND is not set -CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y +# CONFIG_ITCO_VENDOR_SUPPORT is not set +CONFIG_ITCO_WDT=y # CONFIG_KVM_DEBUG_FS is not set CONFIG_KVM_GUEST=y # CONFIG_LCD_CLASS_DEVICE is not set @@ -229,10 +202,9 @@ CONFIG_LEDS_GPIO=y # CONFIG_LEGACY_VSYSCALL_EMULATE is not set # CONFIG_LEGACY_VSYSCALL_NATIVE is not set CONFIG_LEGACY_VSYSCALL_NONE=y +# CONFIG_LIQUIDIO is not set CONFIG_LOCK_SPIN_ON_OWNER=y CONFIG_LPC_ICH=y -CONFIG_LPC_SCH=y -CONFIG_MAILBOX=y # CONFIG_MAXSMP is not set CONFIG_MEMORY_BALLOON=y # CONFIG_MEMORY_HOTPLUG is not set @@ -250,34 +222,34 @@ CONFIG_MMU_NOTIFIER=y CONFIG_MODULES_USE_ELF_RELA=y # CONFIG_MPSC is not set CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_NET_FLOW_LIMIT=y CONFIG_NR_CPUS=8 # CONFIG_NUMA is not set CONFIG_OUTPUT_FORMAT="elf64-x86-64" CONFIG_PADATA=y -CONFIG_PAGE_TABLE_ISOLATION=y CONFIG_PARAVIRT=y CONFIG_PARAVIRT_CLOCK=y # CONFIG_PARAVIRT_DEBUG is not set CONFIG_PARAVIRT_SPINLOCKS=y +# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set CONFIG_PATA_AMD=y CONFIG_PATA_ATIIXP=y CONFIG_PATA_MPIIX=y CONFIG_PATA_OLDPIIX=y CONFIG_PATA_PLATFORM=y CONFIG_PATA_VIA=y -CONFIG_PCC=y CONFIG_PCIEAER=y CONFIG_PCIEPORTBUS=y CONFIG_PCIE_PME=y -CONFIG_PCI_HYPERV=y +CONFIG_PCI_BUS_ADDR_T_64BIT=y # CONFIG_PCI_MMCONFIG is not set CONFIG_PCI_XEN=y CONFIG_PGTABLE_LEVELS=4 CONFIG_PHYSICAL_ALIGN=0x1000000 +CONFIG_PHYS_ADDR_T_64BIT=y CONFIG_PM=y # CONFIG_PMIC_OPREGION is not set -CONFIG_PM_CLK=y # CONFIG_PM_DEBUG is not set CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y @@ -290,29 +262,17 @@ CONFIG_QUEUED_RWLOCKS=y CONFIG_QUEUED_SPINLOCKS=y # CONFIG_RANDOMIZE_BASE is not set CONFIG_RAS=y -CONFIG_RCU_NEED_SEGCBLIST=y CONFIG_RCU_STALL_COMMON=y -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y CONFIG_RELOCATABLE=y -CONFIG_RESET_ATTACK_MITIGATION=y CONFIG_RFS_ACCEL=y CONFIG_RPS=y -CONFIG_RTC_I2C_AND_SPI=y CONFIG_RWSEM_SPIN_ON_OWNER=y # CONFIG_SAMSUNG_Q10 is not set CONFIG_SATA_AHCI=y CONFIG_SCHED_MC=y -CONFIG_SCHED_MC_PRIO=y CONFIG_SCHED_SMT=y # CONFIG_SCIF_BUS is not set CONFIG_SCSI_VIRTIO=y -CONFIG_SENSORS_CORETEMP=y -CONFIG_SENSORS_FAM15H_POWER=y -CONFIG_SENSORS_I5500=y -CONFIG_SENSORS_K10TEMP=y -CONFIG_SENSORS_K8TEMP=y -CONFIG_SENSORS_VIA_CPUTEMP=y CONFIG_SERIAL_8250_PNP=y CONFIG_SMP=y CONFIG_SPARSEMEM=y @@ -322,24 +282,30 @@ CONFIG_SPARSEMEM_MANUAL=y # CONFIG_SPARSEMEM_VMEMMAP is not set CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y # CONFIG_SURFACE_PRO3_BUTTON is not set +CONFIG_SWIOTLB=y CONFIG_SWIOTLB_XEN=y CONFIG_SYS_HYPERVISOR=y -CONFIG_THERMAL_GOV_USER_SPACE=y -CONFIG_THERMAL_HWMON=y -CONFIG_THERMAL_WRITABLE_TRIPS=y +# CONFIG_THUNDER_NIC_BGX is not set +# CONFIG_THUNDER_NIC_PF is not set +# CONFIG_THUNDER_NIC_VF is not set # CONFIG_TOSHIBA_BT_RFKILL is not set CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -# CONFIG_UNWINDER_ORC is not set CONFIG_UCS2_STRING=y # CONFIG_UNISYSSPAR is not set +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set +CONFIG_USB_EHCI_PCI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_HCD_PCI=y +# CONFIG_USB_OHCI_HCD_PLATFORM is not set CONFIG_USB_STORAGE=y +CONFIG_USB_UHCI_HCD=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_PCI=y # CONFIG_USB_XHCI_PLATFORM is not set CONFIG_VGACON_SOFT_SCROLLBACK=y -# CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT is not set CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 CONFIG_VIRTIO=y CONFIG_VIRTIO_BALLOON=y @@ -350,10 +316,7 @@ CONFIG_VIRTIO_MMIO=y CONFIG_VIRTIO_NET=y CONFIG_VIRTIO_PCI=y CONFIG_VIRTIO_PCI_LEGACY=y -# CONFIG_VIRTIO_VSOCKETS is not set CONFIG_VIRT_DRIVERS=y -CONFIG_VMAP_STACK=y -# CONFIG_VMD is not set CONFIG_VMWARE_BALLOON=y CONFIG_VMWARE_PVSCSI=y CONFIG_VMWARE_VMCI=y @@ -362,7 +325,6 @@ CONFIG_VMXNET3=y CONFIG_VSOCKETS=y CONFIG_VT_CONSOLE_SLEEP=y CONFIG_WATCHDOG_CORE=y -# CONFIG_X86_5LEVEL is not set CONFIG_X86_64=y CONFIG_X86_64_SMP=y CONFIG_X86_ACPI_CPUFREQ=y @@ -370,20 +332,18 @@ CONFIG_X86_ACPI_CPUFREQ=y CONFIG_X86_AMD_FREQ_SENSITIVITY=y # CONFIG_X86_AMD_PLATFORM_DEVICE is not set CONFIG_X86_CMOV=y -CONFIG_X86_CPUID=y +CONFIG_X86_CMPXCHG64=y CONFIG_X86_DEBUGCTLMSR=y CONFIG_X86_DEV_DMA_OPS=y CONFIG_X86_DIRECT_GBPAGES=y # CONFIG_X86_INTEL_LPSS is not set -# CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS is not set -# CONFIG_X86_INTEL_MPX is not set -CONFIG_X86_INTEL_PSTATE=y CONFIG_X86_MINIMUM_CPU_FAMILY=64 +# CONFIG_X86_MSR is not set # CONFIG_X86_PCC_CPUFREQ is not set -CONFIG_X86_PKG_TEMP_THERMAL=y # CONFIG_X86_PMEM_LEGACY is not set CONFIG_X86_PM_TIMER=y # CONFIG_X86_POWERNOW_K8 is not set +CONFIG_X86_TSC=y # CONFIG_X86_VSYSCALL_EMULATION is not set CONFIG_X86_X2APIC=y # CONFIG_X86_X32 is not set @@ -410,11 +370,8 @@ CONFIG_XEN_HAVE_VPMU=y CONFIG_XEN_NETDEV_FRONTEND=y CONFIG_XEN_PCIDEV_FRONTEND=y CONFIG_XEN_PRIVCMD=y -CONFIG_XEN_PV=y CONFIG_XEN_PVH=y CONFIG_XEN_PVHVM=y -CONFIG_XEN_PVHVM_SMP=y -CONFIG_XEN_PV_SMP=y CONFIG_XEN_SAVE_RESTORE=y CONFIG_XEN_SCRUB_PAGES=y CONFIG_XEN_SCSI_FRONTEND=y @@ -424,3 +381,30 @@ CONFIG_XEN_WDT=y CONFIG_XEN_XENBUS_FRONTEND=y CONFIG_XPS=y CONFIG_ZONE_DMA32=y +CONFIG_ARCH_MMAP_RND_BITS=28 +CONFIG_ARCH_MMAP_RND_BITS_MAX=32 +CONFIG_ARCH_MMAP_RND_BITS_MIN=28 +CONFIG_VMAP_STACK=y +CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS=y +# CONFIG_PCI_HYPERV is not set +CONFIG_VMD=n +CONFIG_VIRTIO_VSOCKETS=n +CONFIG_SATA_ZPODD=n +# CONFIG_EFI_BOOTLOADER_CONTROL is not set +# CONFIG_EFI_CAPSULE_LOADER is not set +# CONFIG_EFI_DEV_PATH_PARSER is not set +# CONFIG_EFI_TEST is not set +CONFIG_CPU_HOTPLUG_STATE_CONTROL=n +CONFIG_PAGE_TABLE_ISOLATION=y +CONFIG_CRYPTO_SHA256_MB=n +CONFIG_CRYPTO_SHA512_MB=n +CONFIG_XEN_PV=y +CONFIG_SCHED_MC_PRIO=y +# CONFIG_X86_5LEVEL is not set +# CONFIG_X86_INTEL_MPX is not set +# CONFIG_HYPERV_VSOCKETS is not set +# CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT is not set +# CONFIG_INTEL_INT0002_VGPIO is not set +# CONFIG_INTEL_TURBO_MAX_3 is not set +CONFIG_RESET_ATTACK_MITIGATION=y +# CONFIG_UNWINDER_ORC is not set diff --git a/target/linux/x86/Makefile b/target/linux/x86/Makefile index 058edd1a3..9e3a8556b 100644 --- a/target/linux/x86/Makefile +++ b/target/linux/x86/Makefile @@ -13,16 +13,16 @@ FEATURES:=squashfs ext4 vdi vmdk pcmcia targz fpu SUBTARGETS:=generic legacy geode 64 MAINTAINER:=Felix Fietkau -KERNEL_PATCHVER:=4.9 +KERNEL_PATCHVER:=4.14 KERNELNAME:=bzImage include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += partx-utils mkf2fs fdisk e2fsprogs wpad kmod-usb-hid \ -kmod-ath5k kmod-ath9k kmod-ath10k kmod-rt2800-usb kmod-e1000e kmod-igb kmod-igbvf kmod-ixgbe kmod-vmxnet3 htop lm-sensors \ +kmod-ath5k kmod-ath9k kmod-ath9k-htc kmod-ath10k kmod-rt2800-usb kmod-e1000e kmod-igb kmod-igbvf kmod-ixgbe kmod-pcnet32 kmod-tulip kmod-vmxnet3 htop lm-sensors \ autocore automount autosamba ath10k-firmware-qca988x brcmfmac-firmware-43602a1-pcie \ -alsa-utils kmod-ac97 kmod-sound-hda-core kmod-sound-hda-codec-realtek kmod-sound-hda-intel kmod-sound-hda-codec-via kmod-sound-via82xx kmod-usb-audio \ +alsa-utils kmod-ac97 kmod-sound-hda-core kmod-sound-hda-codec-realtek kmod-sound-hda-codec-via kmod-sound-via82xx kmod-usb-audio \ kmod-usb-net kmod-usb-net-asix kmod-usb-net-asix-ax88179 kmod-usb-net-rtl8150 kmod-usb-net-rtl8152 $(eval $(call BuildTarget)) diff --git a/target/linux/x86/config-4.14 b/target/linux/x86/config-4.14 index c742b75d1..bfc60e033 100644 --- a/target/linux/x86/config-4.14 +++ b/target/linux/x86/config-4.14 @@ -1,6 +1,30 @@ # CONFIG_60XX_WDT is not set # CONFIG_64BIT is not set -# CONFIG_ACPI is not set +CONFIG_ACPI=y +CONFIG_ACPI_AC=y +CONFIG_ACPI_BATTERY=y +# CONFIG_ACPI_CMPC is not set +# CONFIG_ACPI_CONTAINER is not set +CONFIG_ACPI_CPU_FREQ_PSS=y +# CONFIG_ACPI_CUSTOM_DSDT is not set +# CONFIG_ACPI_DEBUG is not set +# CONFIG_ACPI_DEBUGGER is not set +# CONFIG_ACPI_DOCK is not set +# CONFIG_ACPI_EC_DEBUGFS is not set +CONFIG_ACPI_FAN=y +CONFIG_ACPI_HOTPLUG_IOAPIC=y +CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y +# CONFIG_ACPI_PCI_SLOT is not set +CONFIG_ACPI_PROCESSOR=y +# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set +CONFIG_ACPI_PROCESSOR_CSTATE=y +CONFIG_ACPI_PROCESSOR_IDLE=y +# CONFIG_ACPI_PROCFS_POWER is not set +CONFIG_ACPI_REV_OVERRIDE_POSSIBLE=y +# CONFIG_ACPI_SBS is not set +CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y +CONFIG_ACPI_THERMAL=y +# CONFIG_ACPI_WMI is not set # CONFIG_ACQUIRE_WDT is not set # CONFIG_ADVANTECH_WDT is not set # CONFIG_ALIM1535_WDT is not set @@ -12,6 +36,7 @@ CONFIG_ARCH_DISCARD_MEMBLOCK=y CONFIG_ARCH_DMA_ADDR_T_64BIT=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y +CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CPU_RELAX=y CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y @@ -20,6 +45,7 @@ CONFIG_ARCH_HAS_FAST_MULTIPLIER=y CONFIG_ARCH_HAS_FORTIFY_SOURCE=y CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y CONFIG_ARCH_HAS_MEM_ENCRYPT=y +CONFIG_ARCH_HAS_REFCOUNT=y CONFIG_ARCH_HAS_SET_MEMORY=y CONFIG_ARCH_HAS_SG_CHAIN=y CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y @@ -27,6 +53,7 @@ CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y # CONFIG_ARCH_OPTIONAL_KERNEL_RWX is not set @@ -87,6 +114,7 @@ CONFIG_CPU_FREQ_GOV_PERFORMANCE=y CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_IDLE=y CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_RMAP=y CONFIG_CPU_SUP_AMD=y CONFIG_CPU_SUP_CENTAUR=y CONFIG_CPU_SUP_CYRIX_32=y @@ -96,12 +124,17 @@ CONFIG_CPU_SUP_UMC_32=y # CONFIG_CRASHLOG is not set CONFIG_CRASH_CORE=y CONFIG_CRC16=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_AES_586=y CONFIG_CRYPTO_CRC32=y CONFIG_CRYPTO_CRC32C=y # CONFIG_CRYPTO_CRC32_PCLMUL is not set CONFIG_CRYPTO_HASH=y CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_NULL2=y CONFIG_CRYPTO_RNG2=y # CONFIG_CRYPTO_SERPENT_SSE2_586 is not set CONFIG_CRYPTO_WORKQUEUE=y @@ -113,7 +146,6 @@ CONFIG_DCACHE_WORD_ACCESS=y CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_DEBUG_NMI_SELFTEST is not set # CONFIG_DEBUG_TLBFLUSH is not set -# CONFIG_DEBUG_VIRTUAL is not set CONFIG_DECOMPRESS_BZIP2=y CONFIG_DECOMPRESS_GZIP=y CONFIG_DEFAULT_IO_DELAY_TYPE=0 @@ -125,6 +157,7 @@ CONFIG_DMIID=y CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y CONFIG_DMI_SYSFS=y CONFIG_DNOTIFY=y +# CONFIG_DPTF_POWER is not set # CONFIG_DRM_LIB_RANDOM is not set CONFIG_DUMMY_CONSOLE=y CONFIG_EARLY_PRINTK=y @@ -132,14 +165,10 @@ CONFIG_EARLY_PRINTK=y CONFIG_EDAC_ATOMIC_SCRUB=y CONFIG_EDAC_SUPPORT=y # CONFIG_EDD is not set +# CONFIG_EFI_DEV_PATH_PARSER is not set # CONFIG_EUROTECH_WDT is not set CONFIG_EXPORTFS=y CONFIG_EXT4_FS=y -# CONFIG_F2FS_CHECK_FS is not set -CONFIG_F2FS_FS=y -# CONFIG_F2FS_FS_SECURITY is not set -CONFIG_F2FS_FS_XATTR=y -CONFIG_F2FS_STAT_FS=y # CONFIG_F71808E_WDT is not set CONFIG_FIRMWARE_IN_KERNEL=y CONFIG_FIRMWARE_MEMMAP=y @@ -159,15 +188,19 @@ CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y CONFIG_GENERIC_EARLY_IOREMAP=y CONFIG_GENERIC_FIND_FIRST_BIT=y CONFIG_GENERIC_IO=y CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_MIGRATION=y CONFIG_GENERIC_IRQ_SHOW=y CONFIG_GENERIC_ISA_DMA=y CONFIG_GENERIC_MSI_IRQ=y CONFIG_GENERIC_MSI_IRQ_DOMAIN=y CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PENDING_IRQ=y CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_GENERIC_STRNCPY_FROM_USER=y CONFIG_GENERIC_STRNLEN_USER=y @@ -180,6 +213,8 @@ CONFIG_HAS_DMA=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT_MAP=y # CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_ACPI_APEI=y +CONFIG_HAVE_ACPI_APEI_NMI=y CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y CONFIG_HAVE_AOUT=y CONFIG_HAVE_ARCH_AUDITSYSCALL=y @@ -244,11 +279,14 @@ CONFIG_HIGHMEM=y # CONFIG_HIGHMEM4G is not set CONFIG_HIGHMEM64G=y # CONFIG_HIGHPTE is not set +# CONFIG_HPET is not set CONFIG_HPET_EMULATE_RTC=y CONFIG_HPET_TIMER=y +# CONFIG_HP_ACCEL is not set # CONFIG_HP_WATCHDOG is not set CONFIG_HT_IRQ=y # CONFIG_HUGETLBFS is not set +CONFIG_HWMON=y CONFIG_HW_CONSOLE=y CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_GEODE=y @@ -266,7 +304,10 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_INPUT=y CONFIG_INPUT_KEYBOARD=y CONFIG_INSTRUCTION_DECODER=y +# CONFIG_INTEL_IPS is not set +# CONFIG_INTEL_MENLOW is not set # CONFIG_INTEL_PCH_THERMAL is not set +# CONFIG_INTEL_PMC_IPC is not set # CONFIG_INTEL_POWERCLAMP is not set # CONFIG_INTEL_RDT is not set # CONFIG_INTEL_SOC_DTS_THERMAL is not set @@ -287,6 +328,7 @@ CONFIG_IRQ_FORCED_THREADING=y CONFIG_IRQ_WORK=y # CONFIG_ISA is not set CONFIG_ISA_DMA_API=y +# CONFIG_ISCSI_IBFT_FIND is not set # CONFIG_IT8712F_WDT is not set # CONFIG_IT87_WDT is not set # CONFIG_ITCO_WDT is not set @@ -297,6 +339,7 @@ CONFIG_KEXEC_CORE=y CONFIG_KEYBOARD_ATKBD=y # CONFIG_LEDS_CLEVO_MAIL is not set CONFIG_LIBNVDIMM=y +CONFIG_LOCK_SPIN_ON_OWNER=y # CONFIG_M486 is not set # CONFIG_M586 is not set CONFIG_M586MMX=y @@ -310,6 +353,7 @@ CONFIG_M586MMX=y # CONFIG_MDIO_BUS is not set # CONFIG_MEFFICEON is not set # CONFIG_MELAN is not set +# CONFIG_MFD_INTEL_LPSS_ACPI is not set # CONFIG_MFD_INTEL_LPSS_PCI is not set # CONFIG_MGEODEGX1 is not set # CONFIG_MGEODE_LX is not set @@ -327,6 +371,7 @@ CONFIG_MODULES_USE_ELF_REL=y # CONFIG_MTD is not set CONFIG_MTRR=y # CONFIG_MTRR_SANITIZER is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y # CONFIG_MVIAC3_2 is not set # CONFIG_MVIAC7 is not set # CONFIG_MWINCHIP3D is not set @@ -337,15 +382,15 @@ CONFIG_ND_BTT=y CONFIG_ND_CLAIM=y CONFIG_NEED_DMA_MAP_STATE=y CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y -CONFIG_NEED_PER_CPU_KM=y CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y CONFIG_NEED_SG_DMA_LENGTH=y # CONFIG_NET5501 is not set +CONFIG_NET_FLOW_LIMIT=y # CONFIG_NET_NS is not set CONFIG_NLS=y # CONFIG_NOHIGHMEM is not set CONFIG_NO_BOOTMEM=y -CONFIG_NR_CPUS=1 +CONFIG_NR_CPUS=8 # CONFIG_NSC_GPIO is not set CONFIG_NVRAM=y # CONFIG_OF is not set @@ -354,6 +399,7 @@ CONFIG_OLD_SIGSUSPEND3=y CONFIG_OPROFILE_NMI_TIMER=y # CONFIG_OPTIMIZE_INLINING is not set CONFIG_OUTPUT_FORMAT="elf32-i386" +CONFIG_PADATA=y CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_PC104=y # CONFIG_PC8736x_GPIO is not set @@ -369,6 +415,7 @@ CONFIG_PCI_GOANY=y # CONFIG_PCI_GOMMCONFIG is not set CONFIG_PCI_LABEL=y CONFIG_PCI_LOCKLESS_CONFIG=y +CONFIG_PCI_MMCONFIG=y CONFIG_PCI_MSI=y CONFIG_PCI_MSI_IRQ_DOMAIN=y CONFIG_PCSPKR_PLATFORM=y @@ -381,20 +428,32 @@ CONFIG_PHYSICAL_ALIGN=0x100000 CONFIG_PHYSICAL_START=0x1000000 CONFIG_PHYS_ADDR_T_64BIT=y CONFIG_PMC_ATOM=y +# CONFIG_PMIC_OPREGION is not set +CONFIG_PNP=y +CONFIG_PNPACPI=y +CONFIG_PNP_DEBUG_MESSAGES=y CONFIG_POWER_SUPPLY=y -CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 # CONFIG_PROCESSOR_SELECT is not set CONFIG_PROC_PAGE_MONITOR=y # CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set # CONFIG_PUNIT_ATOM_DEBUG is not set +# CONFIG_PVPANIC is not set +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y CONFIG_RATIONAL=y -# CONFIG_RCU_NEED_SEGCBLIST is not set -# CONFIG_RCU_STALL_COMMON is not set +CONFIG_RCU_NEED_SEGCBLIST=y +CONFIG_RCU_STALL_COMMON=y CONFIG_RD_BZIP2=y CONFIG_RD_GZIP=y +# CONFIG_RETPOLINE is not set +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y CONFIG_RTC_CLASS=y CONFIG_RTC_MC146818_LIB=y +CONFIG_RWSEM_SPIN_ON_OWNER=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y +# CONFIG_SAMSUNG_Q10 is not set +CONFIG_SATA_AHCI=y # CONFIG_SBC7240_WDT is not set # CONFIG_SBC8360_WDT is not set # CONFIG_SBC_EPX_C3_WATCHDOG is not set @@ -406,20 +465,26 @@ CONFIG_SCx200=y CONFIG_SCx200HR_TIMER=y # CONFIG_SCx200_GPIO is not set # CONFIG_SCx200_WDT is not set +CONFIG_SENSORS_CORETEMP=y +CONFIG_SENSORS_FAM15H_POWER=y +CONFIG_SENSORS_K10TEMP=y +CONFIG_SENSORS_K8TEMP=y +CONFIG_SENSORS_VIA686A=y # CONFIG_SERIAL_8250_FSL is not set CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PNP=y CONFIG_SERIO=y CONFIG_SERIO_I8042=y CONFIG_SERIO_LIBPS2=y CONFIG_SERIO_SERPORT=y CONFIG_SG_POOL=y +CONFIG_SMP=y # CONFIG_SMSC37B787_WDT is not set # CONFIG_SMSC_SCH311X_WDT is not set CONFIG_SPARSEMEM_STATIC=y CONFIG_SPARSE_IRQ=y CONFIG_SRCU=y -CONFIG_STRICT_KERNEL_RWX=y -CONFIG_STRICT_MODULE_RWX=y +# CONFIG_SURFACE_PRO3_BUTTON is not set CONFIG_SWIOTLB=y CONFIG_SYSCTL_EXCEPTION_TRACE=y # CONFIG_TELCLOCK is not set @@ -430,11 +495,12 @@ CONFIG_THERMAL_GOV_STEP_WISE=y CONFIG_THIN_ARCHIVES=y CONFIG_THREAD_INFO_IN_TASK=y CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TINY_SRCU=y # CONFIG_TOSHIBA is not set -# CONFIG_UNWINDER_GUESS is not set +# CONFIG_TOSHIBA_BT_RFKILL is not set +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y CONFIG_UNWINDER_FRAME_POINTER=y -CONFIG_UP_LATE_INIT=y +# CONFIG_UNWINDER_GUESS is not set CONFIG_USB=y CONFIG_USB_COMMON=y CONFIG_USB_EHCI_HCD=y @@ -445,6 +511,7 @@ CONFIG_USB_HIDDEV=y CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_HCD_PLATFORM is not set CONFIG_USB_PCI=y +CONFIG_USB_STORAGE=y CONFIG_USB_SUPPORT=y # CONFIG_USB_UHCI_HCD is not set # CONFIG_USERIO is not set @@ -464,19 +531,27 @@ CONFIG_X86=y CONFIG_X86_32=y # CONFIG_X86_32_IRIS is not set CONFIG_X86_32_LAZY_GS=y +CONFIG_X86_32_SMP=y +CONFIG_X86_ACPI_CPUFREQ=y +CONFIG_X86_ACPI_CPUFREQ_CPB=y CONFIG_X86_ALIGNMENT_16=y +# CONFIG_X86_AMD_FREQ_SENSITIVITY is not set +# CONFIG_X86_AMD_PLATFORM_DEVICE is not set # CONFIG_X86_ANCIENT_MCE is not set +# CONFIG_X86_BIGSMP is not set # CONFIG_X86_CHECK_BIOS_CORRUPTION is not set CONFIG_X86_CMPXCHG64=y # CONFIG_X86_CPUFREQ_NFORCE2 is not set # CONFIG_X86_CPUID is not set # CONFIG_X86_DEBUG_FPU is not set # CONFIG_X86_EXTENDED_PLATFORM is not set +# CONFIG_X86_E_POWERSAVER is not set CONFIG_X86_F00F_BUG=y CONFIG_X86_FAST_FEATURE_TESTS=y CONFIG_X86_FEATURE_NAMES=y CONFIG_X86_GENERIC=y # CONFIG_X86_GX_SUSPMOD is not set +# CONFIG_X86_INTEL_LPSS is not set # CONFIG_X86_INTEL_PSTATE is not set CONFIG_X86_INTEL_USERCOPY=y CONFIG_X86_INTERNODE_CACHE_SHIFT=6 @@ -484,6 +559,7 @@ CONFIG_X86_IO_APIC=y CONFIG_X86_L1_CACHE_SHIFT=6 # CONFIG_X86_LEGACY_VM86 is not set CONFIG_X86_LOCAL_APIC=y +# CONFIG_X86_LONGHAUL is not set # CONFIG_X86_LONGRUN is not set CONFIG_X86_MCE=y # CONFIG_X86_MCELOG_LEGACY is not set @@ -497,11 +573,14 @@ CONFIG_X86_MSR=y # CONFIG_X86_P4_CLOCKMOD is not set CONFIG_X86_PAE=y CONFIG_X86_PAT=y +# CONFIG_X86_PCC_CPUFREQ is not set CONFIG_X86_PLATFORM_DEVICES=y CONFIG_X86_PMEM_LEGACY=y CONFIG_X86_PMEM_LEGACY_DEVICE=y +CONFIG_X86_PM_TIMER=y # CONFIG_X86_POWERNOW_K6 is not set # CONFIG_X86_POWERNOW_K7 is not set +# CONFIG_X86_POWERNOW_K8 is not set CONFIG_X86_PPRO_FENCE=y # CONFIG_X86_PTDUMP is not set # CONFIG_X86_PTDUMP_CORE is not set @@ -516,10 +595,8 @@ CONFIG_X86_RESERVE_LOW=64 CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y CONFIG_X86_THERMAL_VECTOR=y CONFIG_X86_TSC=y -CONFIG_X86_UP_APIC=y -CONFIG_X86_UP_IOAPIC=y CONFIG_X86_VERBOSE_BOOTUP=y +CONFIG_XPS=y CONFIG_XZ_DEC_BCJ=y CONFIG_XZ_DEC_X86=y CONFIG_ZLIB_INFLATE=y -CONFIG_SATA_AHCI=y \ No newline at end of file diff --git a/target/linux/x86/config-4.4 b/target/linux/x86/config-4.4 new file mode 100644 index 000000000..26bb124b8 --- /dev/null +++ b/target/linux/x86/config-4.4 @@ -0,0 +1,459 @@ +# CONFIG_60XX_WDT is not set +# CONFIG_64BIT is not set +# CONFIG_ACPI is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_ALIM1535_WDT is not set +# CONFIG_ALIX is not set +CONFIG_AMD_NB=y +CONFIG_ARCH_CLOCKSOURCE_DATA=y +CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig" +CONFIG_ARCH_DISCARD_MEMBLOCK=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_ARCH_HAS_CPU_RELAX=y +CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_ARCH_HAS_FAST_MULTIPLIER=y +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +CONFIG_ARCH_HAS_MMIO_FLUSH=y +CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-ecx -fcall-saved-edx" +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y +# CONFIG_ARCH_RANDOM is not set +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT=y +CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y +CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_USES_PG_UNCACHED=y +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_ARCH_USE_QUEUED_RWLOCKS=y +CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y +CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_ATA=y +CONFIG_ATA_GENERIC=y +CONFIG_ATA_PIIX=y +CONFIG_BINFMT_MISC=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_SD=y +CONFIG_BOUNCE=y +CONFIG_CLKBLD_I8253=y +CONFIG_CLKEVT_I8253=y +CONFIG_CLKSRC_I8253=y +CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y +CONFIG_CLOCKSOURCE_WATCHDOG=y +CONFIG_CLONE_BACKWARDS=y +# CONFIG_COMPAT_VDSO is not set +CONFIG_CONSOLE_TRANSLATIONS=y +# CONFIG_CPU5_WDT is not set +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_GOV_COMMON=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_SUP_AMD=y +CONFIG_CPU_SUP_CENTAUR=y +CONFIG_CPU_SUP_CYRIX_32=y +CONFIG_CPU_SUP_INTEL=y +CONFIG_CPU_SUP_TRANSMETA_32=y +CONFIG_CPU_SUP_UMC_32=y +# CONFIG_CRASHLOG is not set +CONFIG_CRC16=y +CONFIG_CRYPTO_AES_586=y +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32_PCLMUL is not set +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +# CONFIG_CRYPTO_SERPENT_SSE2_586 is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CX_ECAT is not set +CONFIG_DCACHE_WORD_ACCESS=y +# CONFIG_DCDBAS is not set +# CONFIG_DEBUG_BOOT_PARAMS is not set +# CONFIG_DEBUG_ENTRY is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_NMI_SELFTEST is not set +# CONFIG_DEBUG_TLBFLUSH is not set +# CONFIG_DEBUG_VIRTUAL is not set +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DEFAULT_IO_DELAY_TYPE=0 +# CONFIG_DELL_RBU is not set +CONFIG_DMI=y +CONFIG_DMIID=y +CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y +CONFIG_DMI_SYSFS=y +CONFIG_DNOTIFY=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_EARLY_PRINTK=y +# CONFIG_EARLY_PRINTK_DBGP is not set +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +# CONFIG_EDD is not set +# CONFIG_EUROTECH_WDT is not set +CONFIG_EXT4_FS=y +# CONFIG_F2FS_CHECK_FS is not set +CONFIG_F2FS_FS=y +# CONFIG_F2FS_FS_SECURITY is not set +CONFIG_F2FS_FS_XATTR=y +CONFIG_F2FS_STAT_FS=y +# CONFIG_F71808E_WDT is not set +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_FIRMWARE_MEMMAP=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FS_MBCACHE=y +CONFIG_FUSION=y +# CONFIG_FUSION_CTL is not set +# CONFIG_FUSION_LOGGING is not set +CONFIG_FUSION_MAX_SGE=128 +CONFIG_FUSION_SPI=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_FIND_FIRST_BIT=y +CONFIG_GENERIC_IO=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +# CONFIG_GEOS is not set +CONFIG_GLOB=y +# CONFIG_GOOGLE_FIRMWARE is not set +# CONFIG_HANGCHECK_TIMER is not set +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y +CONFIG_HAVE_AOUT=y +CONFIG_HAVE_ARCH_AUDITSYSCALL=y +# CONFIG_HAVE_ARCH_BITREVERSE is not set +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_HAVE_ARCH_KMEMCHECK=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_HAVE_ATOMIC_IOMAP=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_HAVE_CMPXCHG_LOCAL=y +CONFIG_HAVE_COPY_THREAD_TLS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_DEBUG_KMEMLEAK=y +CONFIG_HAVE_DEBUG_STACKOVERFLOW=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_KPROBES_ON_FTRACE=y +CONFIG_HAVE_KVM=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y +CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y +CONFIG_HAVE_MMIOTRACE_SUPPORT=y +CONFIG_HAVE_NET_DSA=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_OPTPROBES=y +CONFIG_HAVE_PCSPKR_PLATFORM=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_PERF_EVENTS_NMI=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_SETUP_PER_CPU_AREA=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_UID16=y +CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y +CONFIG_HAVE_USER_RETURN_NOTIFIER=y +CONFIG_HIGHMEM=y +CONFIG_HIGHMEM4G=y +# CONFIG_HIGHPTE is not set +CONFIG_HPET_EMULATE_RTC=y +CONFIG_HPET_TIMER=y +# CONFIG_HP_WATCHDOG is not set +CONFIG_HT_IRQ=y +# CONFIG_HUGETLBFS is not set +CONFIG_HW_CONSOLE=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_GEODE=y +CONFIG_HW_RANDOM_VIA=y +# CONFIG_HYPERVISOR_GUEST is not set +CONFIG_HZ_PERIODIC=y +CONFIG_I8253_LOCK=y +# CONFIG_I8K is not set +# CONFIG_IB700_WDT is not set +# CONFIG_IBMASR is not set +# CONFIG_IBM_RTL is not set +# CONFIG_IE6XX_WDT is not set +CONFIG_ILLEGAL_POINTER_VALUE=0 +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INPUT=y +CONFIG_INPUT_KEYBOARD=y +CONFIG_INSTRUCTION_DECODER=y +# CONFIG_INTEL_PCH_THERMAL is not set +# CONFIG_INTEL_POWERCLAMP is not set +# CONFIG_INTEL_SOC_DTS_THERMAL is not set +# CONFIG_IOMMU_STRESS is not set +# CONFIG_IOSF_MBI is not set +CONFIG_IO_DELAY_0X80=y +# CONFIG_IO_DELAY_0XED is not set +# CONFIG_IO_DELAY_NONE is not set +CONFIG_IO_DELAY_TYPE_0X80=0 +CONFIG_IO_DELAY_TYPE_0XED=1 +CONFIG_IO_DELAY_TYPE_NONE=3 +CONFIG_IO_DELAY_TYPE_UDELAY=2 +# CONFIG_IO_DELAY_UDELAY is not set +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_WORK=y +# CONFIG_ISA is not set +CONFIG_ISA_DMA_API=y +# CONFIG_IT8712F_WDT is not set +# CONFIG_IT87_WDT is not set +# CONFIG_ITCO_WDT is not set +CONFIG_JBD2=y +CONFIG_KALLSYMS=y +CONFIG_KEXEC=y +CONFIG_KEXEC_CORE=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_LEDS_CLEVO_MAIL is not set +CONFIG_M486=y +# CONFIG_M586 is not set +# CONFIG_M586MMX is not set +# CONFIG_M586TSC is not set +# CONFIG_M686 is not set +# CONFIG_MACHZ_WDT is not set +# CONFIG_MATOM is not set +# CONFIG_MCORE2 is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MCYRIXIII is not set +# CONFIG_MEFFICEON is not set +# CONFIG_MELAN is not set +# CONFIG_MFD_INTEL_LPSS_PCI is not set +# CONFIG_MGEODEGX1 is not set +# CONFIG_MGEODE_LX is not set +# CONFIG_MICROCODE is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +# CONFIG_MODIFY_LDT_SYSCALL is not set +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_MODULES_USE_ELF_REL=y +# CONFIG_MPENTIUM4 is not set +# CONFIG_MPENTIUMII is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set +# CONFIG_MTD is not set +CONFIG_MTRR=y +# CONFIG_MTRR_SANITIZER is not set +# CONFIG_MVIAC3_2 is not set +# CONFIG_MVIAC7 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MWINCHIPC6 is not set +CONFIG_NAMESPACES=y +CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y +CONFIG_NEED_PER_CPU_KM=y +CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y +CONFIG_NEED_SG_DMA_LENGTH=y +# CONFIG_NET5501 is not set +# CONFIG_NET_NS is not set +CONFIG_NLS=y +# CONFIG_NOHIGHMEM is not set +CONFIG_NO_BOOTMEM=y +CONFIG_NR_CPUS=1 +# CONFIG_NSC_GPIO is not set +CONFIG_NVRAM=y +# CONFIG_OF is not set +CONFIG_OLD_SIGACTION=y +CONFIG_OLD_SIGSUSPEND3=y +# CONFIG_OLPC is not set +CONFIG_OPROFILE_NMI_TIMER=y +# CONFIG_OPTIMIZE_INLINING is not set +CONFIG_OUTPUT_FORMAT="elf32-i386" +CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PC8736x_GPIO is not set +# CONFIG_PC87413_WDT is not set +CONFIG_PCI=y +CONFIG_PCI_BIOS=y +CONFIG_PCI_DIRECT=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_GOANY=y +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOMMCONFIG is not set +CONFIG_PCI_LABEL=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PCSPKR_PLATFORM=y +CONFIG_PERF_EVENTS=y +CONFIG_PERF_EVENTS_INTEL_UNCORE=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYSICAL_ALIGN=0x100000 +CONFIG_PHYSICAL_START=0x1000000 +CONFIG_PMC_ATOM=y +CONFIG_POWER_SUPPLY=y +# CONFIG_PROCESSOR_SELECT is not set +CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set +# CONFIG_PUNIT_ATOM_DEBUG is not set +CONFIG_RATIONAL=y +# CONFIG_RCU_STALL_COMMON is not set +CONFIG_RD_BZIP2=y +CONFIG_RD_GZIP=y +# CONFIG_RELOCATABLE is not set +CONFIG_RTC_CLASS=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +# CONFIG_SBC7240_WDT is not set +# CONFIG_SBC8360_WDT is not set +# CONFIG_SBC_EPX_C3_WATCHDOG is not set +# CONFIG_SC1200_WDT is not set +CONFIG_SCHED_HRTICK=y +# CONFIG_SCHED_INFO is not set +CONFIG_SCSI=y +CONFIG_SCSI_SPI_ATTRS=y +CONFIG_SCx200=y +CONFIG_SCx200HR_TIMER=y +# CONFIG_SCx200_GPIO is not set +# CONFIG_SCx200_WDT is not set +# CONFIG_SERIAL_8250_FSL is not set +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIO=y +# CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_I8042=y +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SMSC37B787_WDT is not set +# CONFIG_SMSC_SCH311X_WDT is not set +CONFIG_SPARSEMEM_STATIC=y +CONFIG_SPARSE_IRQ=y +CONFIG_SRCU=y +CONFIG_STRICT_DEVMEM=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +# CONFIG_TELCLOCK is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_TOSHIBA is not set +CONFIG_UP_LATE_INIT=y +CONFIG_USB_SUPPORT=y +# CONFIG_USERIO is not set +# CONFIG_USER_NS is not set +CONFIG_USER_STACKTRACE_SUPPORT=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set +CONFIG_VGA_CONSOLE=y +# CONFIG_VIA_WDT is not set +# CONFIG_VM86 is not set +# CONFIG_VMWARE_VMCI is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_WAFER_WDT is not set +CONFIG_X86=y +CONFIG_X86_32=y +# CONFIG_X86_32_IRIS is not set +CONFIG_X86_32_LAZY_GS=y +CONFIG_X86_ALIGNMENT_16=y +# CONFIG_X86_ANCIENT_MCE is not set +# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set +# CONFIG_X86_CPUFREQ_NFORCE2 is not set +# CONFIG_X86_CPUID is not set +# CONFIG_X86_DEBUG_FPU is not set +# CONFIG_X86_EXTENDED_PLATFORM is not set +CONFIG_X86_F00F_BUG=y +CONFIG_X86_FEATURE_NAMES=y +CONFIG_X86_GENERIC=y +# CONFIG_X86_GX_SUSPMOD is not set +# CONFIG_X86_INTEL_MPX is not set +# CONFIG_X86_INTEL_PSTATE is not set +CONFIG_X86_INTEL_USERCOPY=y +CONFIG_X86_INTERNODE_CACHE_SHIFT=6 +CONFIG_X86_INVD_BUG=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_L1_CACHE_SHIFT=6 +# CONFIG_X86_LEGACY_VM86 is not set +CONFIG_X86_LOCAL_APIC=y +# CONFIG_X86_LONGRUN is not set +CONFIG_X86_MCE=y +CONFIG_X86_MCE_AMD=y +# CONFIG_X86_MCE_INJECT is not set +CONFIG_X86_MCE_INTEL=y +CONFIG_X86_MCE_THRESHOLD=y +CONFIG_X86_MINIMUM_CPU_FAMILY=4 +CONFIG_X86_MPPARSE=y +CONFIG_X86_MSR=y +# CONFIG_X86_P4_CLOCKMOD is not set +CONFIG_X86_PAT=y +CONFIG_X86_PLATFORM_DEVICES=y +# CONFIG_X86_POWERNOW_K6 is not set +# CONFIG_X86_POWERNOW_K7 is not set +CONFIG_X86_PPRO_FENCE=y +# CONFIG_X86_PTDUMP is not set +# CONFIG_X86_PTDUMP_CORE is not set +# CONFIG_X86_REBOOTFIXUPS is not set +CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y +CONFIG_X86_RESERVE_LOW=64 +# CONFIG_X86_SMAP is not set +# CONFIG_X86_SPEEDSTEP_CENTRINO is not set +# CONFIG_X86_SPEEDSTEP_ICH is not set +# CONFIG_X86_SPEEDSTEP_LIB is not set +# CONFIG_X86_SPEEDSTEP_SMI is not set +CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y +CONFIG_X86_THERMAL_VECTOR=y +CONFIG_X86_UP_APIC=y +CONFIG_X86_UP_IOAPIC=y +CONFIG_X86_VERBOSE_BOOTUP=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_XZ_DEC_X86=y +CONFIG_ZLIB_INFLATE=y diff --git a/target/linux/x86/config-4.9 b/target/linux/x86/config-4.9 index e70aec6b7..723b58093 100644 --- a/target/linux/x86/config-4.9 +++ b/target/linux/x86/config-4.9 @@ -1,6 +1,30 @@ # CONFIG_60XX_WDT is not set # CONFIG_64BIT is not set -# CONFIG_ACPI is not set +CONFIG_ACPI=y +CONFIG_ACPI_AC=y +CONFIG_ACPI_BATTERY=y +# CONFIG_ACPI_CMPC is not set +# CONFIG_ACPI_CONTAINER is not set +CONFIG_ACPI_CPU_FREQ_PSS=y +# CONFIG_ACPI_CUSTOM_DSDT is not set +# CONFIG_ACPI_DEBUG is not set +# CONFIG_ACPI_DEBUGGER is not set +# CONFIG_ACPI_DOCK is not set +# CONFIG_ACPI_EC_DEBUGFS is not set +CONFIG_ACPI_FAN=y +CONFIG_ACPI_HOTPLUG_IOAPIC=y +CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y +# CONFIG_ACPI_PCI_SLOT is not set +CONFIG_ACPI_PROCESSOR=y +# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set +CONFIG_ACPI_PROCESSOR_CSTATE=y +CONFIG_ACPI_PROCESSOR_IDLE=y +# CONFIG_ACPI_PROCFS_POWER is not set +CONFIG_ACPI_REV_OVERRIDE_POSSIBLE=y +# CONFIG_ACPI_SBS is not set +CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y +CONFIG_ACPI_THERMAL=y +# CONFIG_ACPI_WMI is not set # CONFIG_ACQUIRE_WDT is not set # CONFIG_ADVANTECH_WDT is not set # CONFIG_ALIM1535_WDT is not set @@ -12,6 +36,7 @@ CONFIG_ARCH_DISCARD_MEMBLOCK=y CONFIG_ARCH_DMA_ADDR_T_64BIT=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y +CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CPU_RELAX=y CONFIG_ARCH_HAS_ELF_RANDOMIZE=y @@ -22,6 +47,7 @@ CONFIG_ARCH_HAS_SG_CHAIN=y CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y CONFIG_ARCH_PHYS_ADDR_T_64BIT=y @@ -46,6 +72,7 @@ CONFIG_ARCH_WANT_GENERAL_HUGETLB=y CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y CONFIG_ATA=y +CONFIG_ATA_ACPI=y CONFIG_ATA_GENERIC=y CONFIG_ATA_PIIX=y CONFIG_BINFMT_MISC=y @@ -79,6 +106,7 @@ CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y CONFIG_CPU_IDLE=y CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_RMAP=y CONFIG_CPU_SUP_AMD=y CONFIG_CPU_SUP_CENTAUR=y CONFIG_CPU_SUP_CYRIX_32=y @@ -87,12 +115,17 @@ CONFIG_CPU_SUP_TRANSMETA_32=y CONFIG_CPU_SUP_UMC_32=y # CONFIG_CRASHLOG is not set CONFIG_CRC16=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_AES_586=y CONFIG_CRYPTO_CRC32=y CONFIG_CRYPTO_CRC32C=y # CONFIG_CRYPTO_CRC32_PCLMUL is not set CONFIG_CRYPTO_HASH=y CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_NULL2=y CONFIG_CRYPTO_RNG2=y # CONFIG_CRYPTO_SERPENT_SSE2_586 is not set CONFIG_CRYPTO_WORKQUEUE=y @@ -115,6 +148,7 @@ CONFIG_DMIID=y CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y CONFIG_DMI_SYSFS=y CONFIG_DNOTIFY=y +# CONFIG_DPTF_POWER is not set CONFIG_DUMMY_CONSOLE=y CONFIG_EARLY_PRINTK=y # CONFIG_EARLY_PRINTK_DBGP is not set @@ -123,11 +157,6 @@ CONFIG_EDAC_SUPPORT=y # CONFIG_EDD is not set # CONFIG_EUROTECH_WDT is not set CONFIG_EXT4_FS=y -# CONFIG_F2FS_CHECK_FS is not set -CONFIG_F2FS_FS=y -# CONFIG_F2FS_FS_SECURITY is not set -CONFIG_F2FS_FS_XATTR=y -CONFIG_F2FS_STAT_FS=y # CONFIG_F71808E_WDT is not set CONFIG_FIRMWARE_IN_KERNEL=y CONFIG_FIRMWARE_MEMMAP=y @@ -145,6 +174,7 @@ CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y CONFIG_GENERIC_EARLY_IOREMAP=y CONFIG_GENERIC_FIND_FIRST_BIT=y CONFIG_GENERIC_IO=y @@ -154,6 +184,8 @@ CONFIG_GENERIC_ISA_DMA=y CONFIG_GENERIC_MSI_IRQ=y CONFIG_GENERIC_MSI_IRQ_DOMAIN=y CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_GENERIC_PHY=y CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_GENERIC_STRNCPY_FROM_USER=y CONFIG_GENERIC_STRNLEN_USER=y @@ -166,6 +198,8 @@ CONFIG_HAS_DMA=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT_MAP=y # CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_ACPI_APEI=y +CONFIG_HAVE_ACPI_APEI_NMI=y CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y CONFIG_HAVE_AOUT=y CONFIG_HAVE_ARCH_AUDITSYSCALL=y @@ -224,11 +258,15 @@ CONFIG_HIGHMEM=y # CONFIG_HIGHMEM4G is not set CONFIG_HIGHMEM64G=y # CONFIG_HIGHPTE is not set +# CONFIG_HPET is not set CONFIG_HPET_EMULATE_RTC=y CONFIG_HPET_TIMER=y +# CONFIG_HP_ACCEL is not set # CONFIG_HP_WATCHDOG is not set CONFIG_HT_IRQ=y # CONFIG_HUGETLBFS is not set +CONFIG_HWMON=y +CONFIG_HWMON_VID=y CONFIG_HW_CONSOLE=y CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_GEODE=y @@ -246,7 +284,10 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_INPUT=y CONFIG_INPUT_KEYBOARD=y CONFIG_INSTRUCTION_DECODER=y +# CONFIG_INTEL_IPS is not set +# CONFIG_INTEL_MENLOW is not set # CONFIG_INTEL_PCH_THERMAL is not set +# CONFIG_INTEL_PMC_IPC is not set # CONFIG_INTEL_POWERCLAMP is not set # CONFIG_INTEL_SOC_DTS_THERMAL is not set CONFIG_IOMMU_HELPER=y @@ -266,6 +307,7 @@ CONFIG_IRQ_FORCED_THREADING=y CONFIG_IRQ_WORK=y # CONFIG_ISA is not set CONFIG_ISA_DMA_API=y +# CONFIG_ISCSI_IBFT_FIND is not set # CONFIG_IT8712F_WDT is not set # CONFIG_IT87_WDT is not set # CONFIG_ITCO_WDT is not set @@ -276,6 +318,7 @@ CONFIG_KEXEC_CORE=y CONFIG_KEYBOARD_ATKBD=y # CONFIG_LEDS_CLEVO_MAIL is not set CONFIG_LIBNVDIMM=y +CONFIG_LOCK_SPIN_ON_OWNER=y # CONFIG_M486 is not set # CONFIG_M586 is not set CONFIG_M586MMX=y @@ -288,6 +331,7 @@ CONFIG_M586MMX=y # CONFIG_MCYRIXIII is not set # CONFIG_MEFFICEON is not set # CONFIG_MELAN is not set +# CONFIG_MFD_INTEL_LPSS_ACPI is not set # CONFIG_MFD_INTEL_LPSS_PCI is not set # CONFIG_MGEODEGX1 is not set # CONFIG_MGEODE_LX is not set @@ -295,6 +339,14 @@ CONFIG_M586MMX=y # CONFIG_MK6 is not set # CONFIG_MK7 is not set # CONFIG_MK8 is not set +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_SDHCI=y +# CONFIG_MMC_SDHCI_PCI is not set +# CONFIG_MMC_SDHCI_PLTFM is not set +# CONFIG_MMC_TIFM_SD is not set +CONFIG_MMC_USHC=y +# CONFIG_MMC_WBSD is not set # CONFIG_MODIFY_LDT_SYSCALL is not set CONFIG_MODULES_TREE_LOOKUP=y CONFIG_MODULES_USE_ELF_REL=y @@ -305,6 +357,7 @@ CONFIG_MODULES_USE_ELF_REL=y # CONFIG_MTD is not set CONFIG_MTRR=y # CONFIG_MTRR_SANITIZER is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y # CONFIG_MVIAC3_2 is not set # CONFIG_MVIAC7 is not set # CONFIG_MWINCHIP3D is not set @@ -315,15 +368,15 @@ CONFIG_ND_BTT=y CONFIG_ND_CLAIM=y CONFIG_NEED_DMA_MAP_STATE=y CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y -CONFIG_NEED_PER_CPU_KM=y CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y CONFIG_NEED_SG_DMA_LENGTH=y # CONFIG_NET5501 is not set +CONFIG_NET_FLOW_LIMIT=y # CONFIG_NET_NS is not set CONFIG_NLS=y # CONFIG_NOHIGHMEM is not set CONFIG_NO_BOOTMEM=y -CONFIG_NR_CPUS=1 +CONFIG_NR_CPUS=8 # CONFIG_NSC_GPIO is not set CONFIG_NVME_CORE=y CONFIG_NVRAM=y @@ -333,7 +386,13 @@ CONFIG_OLD_SIGSUSPEND3=y CONFIG_OPROFILE_NMI_TIMER=y # CONFIG_OPTIMIZE_INLINING is not set CONFIG_OUTPUT_FORMAT="elf32-i386" +CONFIG_PADATA=y CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PATA_ACPI=y +CONFIG_PATA_ALI=y +CONFIG_PATA_AMD=y +CONFIG_PATA_MPIIX=y +CONFIG_PATA_SCH=y # CONFIG_PC8736x_GPIO is not set # CONFIG_PC87413_WDT is not set CONFIG_PCI=y @@ -346,6 +405,7 @@ CONFIG_PCI_GOANY=y # CONFIG_PCI_GODIRECT is not set # CONFIG_PCI_GOMMCONFIG is not set CONFIG_PCI_LABEL=y +CONFIG_PCI_MMCONFIG=y CONFIG_PCI_MSI=y CONFIG_PCI_MSI_IRQ_DOMAIN=y CONFIG_PCSPKR_PLATFORM=y @@ -358,18 +418,34 @@ CONFIG_PHYSICAL_ALIGN=0x100000 CONFIG_PHYSICAL_START=0x1000000 CONFIG_PHYS_ADDR_T_64BIT=y CONFIG_PMC_ATOM=y +# CONFIG_PMIC_OPREGION is not set +CONFIG_PNP=y +CONFIG_PNPACPI=y +CONFIG_PNP_DEBUG_MESSAGES=y CONFIG_POWER_SUPPLY=y # CONFIG_PROCESSOR_SELECT is not set CONFIG_PROC_PAGE_MONITOR=y # CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set # CONFIG_PUNIT_ATOM_DEBUG is not set -# CONFIG_RCU_STALL_COMMON is not set +# CONFIG_PVPANIC is not set +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RCU_STALL_COMMON=y CONFIG_RD_BZIP2=y CONFIG_RD_GZIP=y +# CONFIG_RETPOLINE is not set +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y CONFIG_RTC_CLASS=y CONFIG_RTC_MC146818_LIB=y +CONFIG_RWSEM_SPIN_ON_OWNER=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y +# CONFIG_SAMSUNG_Q10 is not set CONFIG_SATA_AHCI=y +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_SATA_MV=y +CONFIG_SATA_NV=y +CONFIG_SATA_VIA=y # CONFIG_SBC7240_WDT is not set # CONFIG_SBC8360_WDT is not set # CONFIG_SBC_EPX_C3_WATCHDOG is not set @@ -381,8 +457,15 @@ CONFIG_SCx200=y CONFIG_SCx200HR_TIMER=y # CONFIG_SCx200_GPIO is not set # CONFIG_SCx200_WDT is not set +CONFIG_SENSORS_CORETEMP=y +CONFIG_SENSORS_FAM15H_POWER=y +CONFIG_SENSORS_I5500=y +CONFIG_SENSORS_K10TEMP=y +CONFIG_SENSORS_K8TEMP=y +CONFIG_SENSORS_VIA_CPUTEMP=y # CONFIG_SERIAL_8250_FSL is not set CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PNP=y CONFIG_SERIO=y # CONFIG_SERIO_CT82C710 is not set CONFIG_SERIO_I8042=y @@ -390,12 +473,14 @@ CONFIG_SERIO_LIBPS2=y CONFIG_SERIO_SERPORT=y CONFIG_SG_POOL=y # CONFIG_SHORTCUT_FE is not set +CONFIG_SMP=y # CONFIG_SMSC37B787_WDT is not set # CONFIG_SMSC_SCH311X_WDT is not set CONFIG_SPARSEMEM_STATIC=y CONFIG_SPARSE_IRQ=y CONFIG_SRCU=y CONFIG_STRICT_DEVMEM=y +# CONFIG_SURFACE_PRO3_BUTTON is not set CONFIG_SWIOTLB=y CONFIG_SYSCTL_EXCEPTION_TRACE=y # CONFIG_TELCLOCK is not set @@ -405,7 +490,8 @@ CONFIG_THERMAL_GOV_STEP_WISE=y CONFIG_THREAD_INFO_IN_TASK=y CONFIG_TICK_CPU_ACCOUNTING=y # CONFIG_TOSHIBA is not set -CONFIG_UP_LATE_INIT=y +# CONFIG_TOSHIBA_BT_RFKILL is not set +CONFIG_TREE_RCU=y CONFIG_USB=y CONFIG_USB_COMMON=y CONFIG_USB_EHCI_HCD=y @@ -415,6 +501,7 @@ CONFIG_USB_HID=y CONFIG_USB_HIDDEV=y CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_HCD_PLATFORM is not set +CONFIG_USB_STORAGE=y CONFIG_USB_SUPPORT=y CONFIG_USB_UHCI_HCD=y # CONFIG_USERIO is not set @@ -434,19 +521,27 @@ CONFIG_X86=y CONFIG_X86_32=y # CONFIG_X86_32_IRIS is not set CONFIG_X86_32_LAZY_GS=y +CONFIG_X86_32_SMP=y +CONFIG_X86_ACPI_CPUFREQ=y +CONFIG_X86_ACPI_CPUFREQ_CPB=y CONFIG_X86_ALIGNMENT_16=y +# CONFIG_X86_AMD_FREQ_SENSITIVITY is not set +# CONFIG_X86_AMD_PLATFORM_DEVICE is not set # CONFIG_X86_ANCIENT_MCE is not set +# CONFIG_X86_BIGSMP is not set # CONFIG_X86_CHECK_BIOS_CORRUPTION is not set CONFIG_X86_CMPXCHG64=y # CONFIG_X86_CPUFREQ_NFORCE2 is not set # CONFIG_X86_CPUID is not set # CONFIG_X86_DEBUG_FPU is not set # CONFIG_X86_EXTENDED_PLATFORM is not set +# CONFIG_X86_E_POWERSAVER is not set CONFIG_X86_F00F_BUG=y CONFIG_X86_FAST_FEATURE_TESTS=y CONFIG_X86_FEATURE_NAMES=y CONFIG_X86_GENERIC=y # CONFIG_X86_GX_SUSPMOD is not set +# CONFIG_X86_INTEL_LPSS is not set # CONFIG_X86_INTEL_MPX is not set # CONFIG_X86_INTEL_PSTATE is not set CONFIG_X86_INTEL_USERCOPY=y @@ -455,6 +550,7 @@ CONFIG_X86_IO_APIC=y CONFIG_X86_L1_CACHE_SHIFT=6 # CONFIG_X86_LEGACY_VM86 is not set CONFIG_X86_LOCAL_APIC=y +# CONFIG_X86_LONGHAUL is not set # CONFIG_X86_LONGRUN is not set CONFIG_X86_MCE=y CONFIG_X86_MCE_AMD=y @@ -467,11 +563,14 @@ CONFIG_X86_MSR=y # CONFIG_X86_P4_CLOCKMOD is not set CONFIG_X86_PAE=y CONFIG_X86_PAT=y +# CONFIG_X86_PCC_CPUFREQ is not set CONFIG_X86_PLATFORM_DEVICES=y CONFIG_X86_PMEM_LEGACY=y CONFIG_X86_PMEM_LEGACY_DEVICE=y +CONFIG_X86_PM_TIMER=y # CONFIG_X86_POWERNOW_K6 is not set # CONFIG_X86_POWERNOW_K7 is not set +# CONFIG_X86_POWERNOW_K8 is not set CONFIG_X86_PPRO_FENCE=y # CONFIG_X86_PTDUMP is not set # CONFIG_X86_PTDUMP_CORE is not set @@ -486,9 +585,8 @@ CONFIG_X86_RESERVE_LOW=64 CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y CONFIG_X86_THERMAL_VECTOR=y CONFIG_X86_TSC=y -CONFIG_X86_UP_APIC=y -CONFIG_X86_UP_IOAPIC=y CONFIG_X86_VERBOSE_BOOTUP=y +CONFIG_XPS=y CONFIG_XZ_DEC_BCJ=y CONFIG_XZ_DEC_X86=y CONFIG_ZLIB_INFLATE=y diff --git a/target/linux/x86/generic/config-default b/target/linux/x86/generic/config-default index 327e7c647..39398f151 100644 --- a/target/linux/x86/generic/config-default +++ b/target/linux/x86/generic/config-default @@ -1,4 +1,3 @@ -# CONFIG_104_QUAD_8 is not set # CONFIG_3C515 is not set CONFIG_ACPI=y CONFIG_ACPI_AC=y @@ -17,11 +16,12 @@ CONFIG_ACPI_CPU_FREQ_PSS=y CONFIG_ACPI_HOTPLUG_CPU=y CONFIG_ACPI_HOTPLUG_IOAPIC=y # CONFIG_ACPI_I2C_OPREGION is not set +# CONFIG_ACPI_INITRD_TABLE_OVERRIDE is not set CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y +# CONFIG_ACPI_NFIT is not set # CONFIG_ACPI_PCI_SLOT is not set CONFIG_ACPI_PROCESSOR=y # CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set -CONFIG_ACPI_PROCESSOR_CSTATE=y CONFIG_ACPI_PROCESSOR_IDLE=y # CONFIG_ACPI_PROCFS_POWER is not set CONFIG_ACPI_REV_OVERRIDE_POSSIBLE=y @@ -42,17 +42,21 @@ CONFIG_AGP_INTEL=y # CONFIG_AGP_SWORKS is not set # CONFIG_AGP_VIA is not set # CONFIG_APM is not set -CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_ARCH_RANDOM=y +CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y +# CONFIG_BACKLIGHT_APPLE is not set CONFIG_BACKLIGHT_CLASS_DEVICE=y CONFIG_BACKLIGHT_GENERIC=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_BLK_DEV_SR=y # CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_BLK_MQ_VIRTIO=y # CONFIG_BOOTPARAM_HOTPLUG_CPU0 is not set -CONFIG_CONNECTOR=y -# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_COMMON_CLK=y CONFIG_CPU_IDLE_GOV_MENU=y CONFIG_CPU_RMAP=y CONFIG_CRYPTO_AEAD=y @@ -62,58 +66,54 @@ CONFIG_CRYPTO_MANAGER2=y CONFIG_CRYPTO_NULL2=y # CONFIG_DEBUG_HOTPLUG_CPU0 is not set CONFIG_DMA_SHARED_BUFFER=y -# CONFIG_DPTF_POWER is not set CONFIG_DRM=y CONFIG_DRM_AMDGPU=y # CONFIG_DRM_AMDGPU_CIK is not set -# CONFIG_DRM_AMDGPU_GART_DEBUGFS is not set -# CONFIG_DRM_AMDGPU_SI is not set # CONFIG_DRM_AMDGPU_USERPTR is not set -# CONFIG_DRM_AMD_ACP is not set +# CONFIG_DRM_AST is not set CONFIG_DRM_BOCHS=y CONFIG_DRM_BRIDGE=y +# CONFIG_DRM_CIRRUS_QEMU is not set CONFIG_DRM_FBDEV_EMULATION=y -CONFIG_DRM_FBDEV_OVERALLOC=100 # CONFIG_DRM_GMA500 is not set +# CONFIG_DRM_I2C_ADV7511 is not set +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_I2C_SIL164 is not set +# CONFIG_DRM_I810 is not set CONFIG_DRM_I915=y -# CONFIG_DRM_I915_ALPHA_SUPPORT is not set -CONFIG_DRM_I915_CAPTURE_ERROR=y -CONFIG_DRM_I915_COMPRESS_ERROR=y -# CONFIG_DRM_I915_DEBUG is not set -# CONFIG_DRM_I915_DEBUG_VBLANK_EVADE is not set -# CONFIG_DRM_I915_GVT is not set -# CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS is not set # CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT is not set -# CONFIG_DRM_I915_SELFTEST is not set -# CONFIG_DRM_I915_SW_FENCE_CHECK_DAG is not set -# CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS is not set -CONFIG_DRM_I915_USERPTR=y -# CONFIG_DRM_I915_WERROR is not set CONFIG_DRM_KMS_FB_HELPER=y CONFIG_DRM_KMS_HELPER=y +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +# CONFIG_DRM_MGA is not set +# CONFIG_DRM_MGAG200 is not set CONFIG_DRM_MIPI_DSI=y +# CONFIG_DRM_NOUVEAU is not set CONFIG_DRM_PANEL=y -CONFIG_DRM_PANEL_BRIDGE=y +# CONFIG_DRM_QXL is not set +# CONFIG_DRM_R128 is not set CONFIG_DRM_RADEON=y +# CONFIG_DRM_RADEON_UMS is not set # CONFIG_DRM_RADEON_USERPTR is not set +# CONFIG_DRM_SAVAGE is not set +# CONFIG_DRM_SIS is not set +# CONFIG_DRM_TDFX is not set CONFIG_DRM_TTM=y +# CONFIG_DRM_UDL is not set +# CONFIG_DRM_VGEM is not set +# CONFIG_DRM_VIA is not set CONFIG_DRM_VIRTIO_GPU=y # CONFIG_DRM_VMWGFX is not set CONFIG_EARLY_PRINTK_EFI=y -# CONFIG_EBC_C384_WDT is not set CONFIG_EFI=y CONFIG_EFIVAR_FS=m -# CONFIG_EFI_BOOTLOADER_CONTROL is not set -# CONFIG_EFI_CAPSULE_LOADER is not set -# CONFIG_EFI_CAPSULE_QUIRK_QUARK_CSH is not set -# CONFIG_EFI_DEV_PATH_PARSER is not set CONFIG_EFI_ESRT=y # CONFIG_EFI_FAKE_MEMMAP is not set # CONFIG_EFI_PGT_DUMP is not set CONFIG_EFI_RUNTIME_MAP=y CONFIG_EFI_RUNTIME_WRAPPERS=y CONFIG_EFI_STUB=y -# CONFIG_EFI_TEST is not set CONFIG_EFI_VARS=y # CONFIG_EISA is not set # CONFIG_EL3 is not set @@ -124,9 +124,7 @@ CONFIG_FB_CFB_IMAGEBLIT=y CONFIG_FB_CMDLINE=y CONFIG_FB_DEFERRED_IO=y CONFIG_FB_EFI=y -CONFIG_FB_HYPERV=y # CONFIG_FB_I810 is not set -# CONFIG_FB_PROVIDE_GET_FB_UNMAPPED_AREA is not set CONFIG_FB_SYS_COPYAREA=y CONFIG_FB_SYS_FILLRECT=y CONFIG_FB_SYS_FOPS=y @@ -140,18 +138,23 @@ CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set CONFIG_FREEZER=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_MIGRATION=y CONFIG_GENERIC_PENDING_IRQ=y CONFIG_GENERIC_PINCONF=y CONFIG_GPIOLIB=y CONFIG_GPIOLIB_IRQCHIP=y -# CONFIG_GPIO_104_DIO_48E is not set # CONFIG_GPIO_104_IDIO_16 is not set -# CONFIG_GPIO_104_IDI_48 is not set CONFIG_GPIO_ACPI=y +# CONFIG_GPIO_AMDPT is not set +CONFIG_GPIO_DEVRES=y +# CONFIG_GPIO_F7188X is not set +# CONFIG_GPIO_INTEL_MID is not set +# CONFIG_GPIO_IT87 is not set +# CONFIG_GPIO_LYNXPOINT is not set CONFIG_HAVE_ACPI_APEI=y CONFIG_HAVE_ACPI_APEI_NMI=y +CONFIG_HAVE_ARCH_HUGE_VMAP=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CLK_PREPARE=y CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y CONFIG_HAVE_KVM_EVENTFD=y CONFIG_HAVE_KVM_IRQCHIP=y @@ -161,18 +164,11 @@ CONFIG_HAVE_KVM_IRQ_ROUTING=y CONFIG_HAVE_KVM_MSI=y CONFIG_HDMI=y CONFIG_HIBERNATE_CALLBACKS=y +CONFIG_HID=y CONFIG_HID_BATTERY_STRENGTH=y -CONFIG_HID_GENERIC=y -CONFIG_HID_HYPERV_MOUSE=y +# CONFIG_HIGHMEM4G is not set +CONFIG_HIGHMEM64G=y CONFIG_HOTPLUG_CPU=y -CONFIG_HOTPLUG_PCI=y -CONFIG_HOTPLUG_PCI_ACPI=y -# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set -# CONFIG_HOTPLUG_PCI_COMPAQ is not set -# CONFIG_HOTPLUG_PCI_CPCI is not set -# CONFIG_HOTPLUG_PCI_IBM is not set -CONFIG_HOTPLUG_PCI_PCIE=y -# CONFIG_HOTPLUG_PCI_SHPC is not set CONFIG_HPET=y CONFIG_HPET_MMAP=y # CONFIG_HP_ACCEL is not set @@ -181,15 +177,8 @@ CONFIG_HVC_IRQ=y CONFIG_HVC_XEN=y CONFIG_HVC_XEN_FRONTEND=y CONFIG_HWMON=y -CONFIG_HWMON_VID=y CONFIG_HW_RANDOM_VIRTIO=y -CONFIG_HYPERV=y CONFIG_HYPERVISOR_GUEST=y -CONFIG_HYPERV_BALLOON=y -CONFIG_HYPERV_KEYBOARD=y -CONFIG_HYPERV_NET=y -CONFIG_HYPERV_STORAGE=y -CONFIG_HYPERV_UTILS=y CONFIG_I2C=y CONFIG_I2C_ALGOBIT=y CONFIG_I2C_BOARDINFO=y @@ -201,26 +190,20 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 CONFIG_INPUT_XEN_KBDDEV_FRONTEND=y CONFIG_INTEL_GTT=y CONFIG_INTEL_IDLE=y -# CONFIG_INTEL_INT0002_VGPIO is not set # CONFIG_INTEL_IPS is not set # CONFIG_INTEL_MENLOW is not set -CONFIG_INTEL_PCH_THERMAL=y # CONFIG_INTEL_PMC_IPC is not set -CONFIG_INTEL_SOC_DTS_IOSF_CORE=y -CONFIG_INTEL_SOC_DTS_THERMAL=y -# CONFIG_INTEL_SOC_PMIC_CHTWC is not set CONFIG_INTERVAL_TREE=y -CONFIG_IOSF_MBI=y -# CONFIG_IOSF_MBI_DEBUG is not set +CONFIG_IOMMU_HELPER=y CONFIG_IRQ_BYPASS_MANAGER=y CONFIG_ISA=y CONFIG_ISAPNP=y -CONFIG_ISA_BUS_API=y # CONFIG_ISCSI_IBFT_FIND is not set CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set CONFIG_KVM=y CONFIG_KVM_AMD=y +CONFIG_KVM_APIC_ARCHITECTURE=y CONFIG_KVM_ASYNC_PF=y # CONFIG_KVM_DEBUG_FS is not set CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y @@ -232,7 +215,7 @@ CONFIG_KVM_VFIO=y # CONFIG_LCD_CLASS_DEVICE is not set # CONFIG_LGUEST_GUEST is not set CONFIG_LOCK_SPIN_ON_OWNER=y -# CONFIG_M586MMX is not set +# CONFIG_M486 is not set # CONFIG_MDA_CONSOLE is not set CONFIG_MEMORY_BALLOON=y CONFIG_MFD_CORE=y @@ -253,14 +236,11 @@ CONFIG_MMU_NOTIFIER=y # CONFIG_MOUSE_CYAPA is not set CONFIG_MOUSE_PS2=y CONFIG_MOUSE_PS2_ALPS=y -# CONFIG_MOUSE_PS2_BYD is not set # CONFIG_MOUSE_PS2_CYPRESS is not set # CONFIG_MOUSE_PS2_ELANTECH is not set CONFIG_MOUSE_PS2_LIFEBOOK=y CONFIG_MOUSE_PS2_LOGIPS2PP=y -CONFIG_MOUSE_PS2_SMBUS=y CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y # CONFIG_MOUSE_PS2_TOUCHKIT is not set CONFIG_MOUSE_PS2_TRACKPOINT=y # CONFIG_MOUSE_PS2_VMMOUSE is not set @@ -268,6 +248,7 @@ CONFIG_MOUSE_PS2_TRACKPOINT=y # CONFIG_MOUSE_VSXXXAA is not set CONFIG_MPENTIUM4=y CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_NET_FLOW_LIMIT=y CONFIG_NO_HZ=y CONFIG_NR_CPUS=4 @@ -276,6 +257,7 @@ CONFIG_PARAVIRT=y CONFIG_PARAVIRT_CLOCK=y # CONFIG_PARAVIRT_DEBUG is not set CONFIG_PARAVIRT_SPINLOCKS=y +# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set CONFIG_PATA_AMD=y CONFIG_PATA_ATIIXP=y CONFIG_PATA_MPIIX=y @@ -286,18 +268,17 @@ CONFIG_PATA_VIA=y CONFIG_PCIEAER=y CONFIG_PCIEPORTBUS=y CONFIG_PCIE_PME=y +CONFIG_PCI_BUS_ADDR_T_64BIT=y CONFIG_PCI_MMCONFIG=y CONFIG_PCI_XEN=y # CONFIG_PCWATCHDOG is not set +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYS_ADDR_T_64BIT=y CONFIG_PINCTRL=y CONFIG_PINCTRL_BAYTRAIL=y CONFIG_PINCTRL_BROXTON=y -CONFIG_PINCTRL_CANNONLAKE=y CONFIG_PINCTRL_CHERRYVIEW=y -CONFIG_PINCTRL_DENVERTON=y -CONFIG_PINCTRL_GEMINILAKE=y CONFIG_PINCTRL_INTEL=y -# CONFIG_PINCTRL_LEWISBURG is not set CONFIG_PINCTRL_SUNRISEPOINT=y CONFIG_PM=y # CONFIG_PMIC_OPREGION is not set @@ -310,57 +291,47 @@ CONFIG_PNPACPI=y # CONFIG_PNPBIOS is not set CONFIG_PNP_DEBUG_MESSAGES=y CONFIG_PREEMPT_NOTIFIERS=y -CONFIG_PROC_EVENTS=y # CONFIG_PVPANIC is not set CONFIG_QUEUED_RWLOCKS=y CONFIG_QUEUED_SPINLOCKS=y # CONFIG_RANDOMIZE_BASE is not set CONFIG_RAS=y -CONFIG_RCU_NEED_SEGCBLIST=y CONFIG_RCU_STALL_COMMON=y -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y -# CONFIG_RELAY is not set CONFIG_RELOCATABLE=y -CONFIG_RESET_ATTACK_MITIGATION=y CONFIG_RFS_ACCEL=y CONFIG_RPS=y -CONFIG_RTC_I2C_AND_SPI=y CONFIG_RWSEM_SPIN_ON_OWNER=y # CONFIG_SAMSUNG_Q10 is not set CONFIG_SATA_AHCI=y CONFIG_SATA_VIA=y CONFIG_SCHED_INFO=y CONFIG_SCSI_VIRTIO=y -CONFIG_SENSORS_CORETEMP=y -CONFIG_SENSORS_FAM15H_POWER=y -CONFIG_SENSORS_I5500=y -CONFIG_SENSORS_K10TEMP=y -CONFIG_SENSORS_K8TEMP=y -CONFIG_SENSORS_VIA_CPUTEMP=y CONFIG_SERIAL_8250_PNP=y CONFIG_SMP=y # CONFIG_SURFACE_PRO3_BUTTON is not set +CONFIG_SWIOTLB=y CONFIG_SWIOTLB_XEN=y -# CONFIG_SW_SYNC is not set -# CONFIG_SYNC_FILE is not set CONFIG_SYS_HYPERVISOR=y CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y -CONFIG_THERMAL_GOV_USER_SPACE=y -CONFIG_THERMAL_HWMON=y -CONFIG_THERMAL_WRITABLE_TRIPS=y # CONFIG_TOSHIBA_BT_RFKILL is not set CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y CONFIG_UCS2_STRING=y +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set +CONFIG_USB_EHCI_PCI=y +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_HCD_PLATFORM is not set CONFIG_USB_STORAGE=y +CONFIG_USB_UHCI_HCD=y CONFIG_USER_RETURN_NOTIFIER=y CONFIG_VGACON_SOFT_SCROLLBACK=y -# CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT is not set CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 CONFIG_VHOST=y CONFIG_VHOST_NET=y +CONFIG_VHOST_RING=y CONFIG_VIRTIO=y CONFIG_VIRTIO_BALLOON=y CONFIG_VIRTIO_BLK=y @@ -381,7 +352,7 @@ CONFIG_X86_AMD_FREQ_SENSITIVITY=y # CONFIG_X86_AMD_PLATFORM_DEVICE is not set # CONFIG_X86_BIGSMP is not set CONFIG_X86_CMOV=y -CONFIG_X86_CPUID=y +CONFIG_X86_CMPXCHG64=y CONFIG_X86_DEBUGCTLMSR=y # CONFIG_X86_E_POWERSAVER is not set CONFIG_X86_INTEL_LPSS=y @@ -389,12 +360,14 @@ CONFIG_X86_INTEL_PSTATE=y CONFIG_X86_INTERNODE_CACHE_SHIFT=7 CONFIG_X86_L1_CACHE_SHIFT=7 # CONFIG_X86_LONGHAUL is not set +CONFIG_X86_MINIMUM_CPU_FAMILY=5 CONFIG_X86_NEED_RELOCS=y +CONFIG_X86_PAE=y # CONFIG_X86_PCC_CPUFREQ is not set -CONFIG_X86_PKG_TEMP_THERMAL=y # CONFIG_X86_PMEM_LEGACY is not set CONFIG_X86_PM_TIMER=y # CONFIG_X86_POWERNOW_K8 is not set +CONFIG_X86_TSC=y CONFIG_X86_USE_PPRO_CHECKSUM=y CONFIG_XEN=y CONFIG_XENFS=y @@ -416,11 +389,7 @@ CONFIG_XEN_HAVE_VPMU=y CONFIG_XEN_NETDEV_FRONTEND=y CONFIG_XEN_PCIDEV_FRONTEND=y CONFIG_XEN_PRIVCMD=y -CONFIG_XEN_PV=y -CONFIG_XEN_PVH=y CONFIG_XEN_PVHVM=y -CONFIG_XEN_PVHVM_SMP=y -CONFIG_XEN_PV_SMP=y CONFIG_XEN_SAVE_RESTORE=y CONFIG_XEN_SCRUB_PAGES=y CONFIG_XEN_SCSI_FRONTEND=y @@ -429,4 +398,19 @@ CONFIG_XEN_SYS_HYPERVISOR=y CONFIG_XEN_WDT=y CONFIG_XEN_XENBUS_FRONTEND=y CONFIG_XPS=y -CONFIG_ZLIB_DEFLATE=y +CONFIG_ARCH_MMAP_RND_BITS=28 +CONFIG_ARCH_MMAP_RND_BITS_MAX=32 +CONFIG_ARCH_MMAP_RND_BITS_MIN=28 +CONFIG_VMAP_STACK=y +CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS=y +CONFIG_PCI_HYPERV=y +CONFIG_VMD=n +CONFIG_VIRTIO_VSOCKETS=n +CONFIG_SATA_ZPODD=n +CONFIG_EFI_BOOTLOADER_CONTROL=y +CONFIG_EFI_CAPSULE_LOADER=y +CONFIG_EFI_TEST=n +CONFIG_CPU_HOTPLUG_STATE_CONTROL=n +CONFIG_PAGE_TABLE_ISOLATION=y +CONFIG_CRYPTO_SHA256_MB=n +CONFIG_CRYPTO_SHA512_MB=n \ No newline at end of file diff --git a/target/linux/x86/geode/config-default b/target/linux/x86/geode/config-default index b564b940e..d1c8f5a97 100644 --- a/target/linux/x86/geode/config-default +++ b/target/linux/x86/geode/config-default @@ -1,4 +1,3 @@ -# CONFIG_104_QUAD_8 is not set # CONFIG_3C515 is not set CONFIG_8139CP=y CONFIG_8139TOO=y @@ -8,7 +7,7 @@ CONFIG_8139TOO_PIO=y # CONFIG_8139_OLD_RX_RESET is not set CONFIG_ACPI=y CONFIG_ACPI_AC=y -# CONFIG_ACPI_BATTERY is not set +CONFIG_ACPI_BATTERY=y # CONFIG_ACPI_CMPC is not set # CONFIG_ACPI_CONTAINER is not set CONFIG_ACPI_CPU_FREQ_PSS=y @@ -20,11 +19,11 @@ CONFIG_ACPI_CPU_FREQ_PSS=y CONFIG_ACPI_FAN=y CONFIG_ACPI_HOTPLUG_IOAPIC=y CONFIG_ACPI_I2C_OPREGION=y +# CONFIG_ACPI_INITRD_TABLE_OVERRIDE is not set CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y # CONFIG_ACPI_PCI_SLOT is not set CONFIG_ACPI_PROCESSOR=y # CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set -CONFIG_ACPI_PROCESSOR_CSTATE=y CONFIG_ACPI_PROCESSOR_IDLE=y # CONFIG_ACPI_PROCFS_POWER is not set CONFIG_ACPI_REV_OVERRIDE_POSSIBLE=y @@ -33,29 +32,29 @@ CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y CONFIG_ACPI_THERMAL=y # CONFIG_ACPI_WMI is not set CONFIG_ALIX=y -CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y # CONFIG_ATA_PIIX is not set CONFIG_CS5535_CLOCK_EVENT_SRC=y CONFIG_CS5535_MFGPT=y CONFIG_CS5535_MFGPT_DEFAULT_IRQ=7 -# CONFIG_DPTF_POWER is not set -# CONFIG_EBC_C384_WDT is not set -# CONFIG_EFI_DEV_PATH_PARSER is not set +# CONFIG_EFI is not set # CONFIG_EISA is not set # CONFIG_EL3 is not set CONFIG_GEODE_WDT=y CONFIG_GEOS=y CONFIG_GPIOLIB=y -# CONFIG_GPIO_104_DIO_48E is not set # CONFIG_GPIO_104_IDIO_16 is not set -# CONFIG_GPIO_104_IDI_48 is not set CONFIG_GPIO_ACPI=y +# CONFIG_GPIO_AMDPT is not set CONFIG_GPIO_CS5535=y +CONFIG_GPIO_DEVRES=y +# CONFIG_GPIO_F7188X is not set +# CONFIG_GPIO_INTEL_MID is not set +# CONFIG_GPIO_IT87 is not set +# CONFIG_GPIO_LYNXPOINT is not set CONFIG_GPIO_SYSFS=y CONFIG_HAVE_ACPI_APEI=y CONFIG_HAVE_ACPI_APEI_NMI=y -CONFIG_HIGHMEM4G=y # CONFIG_HIGHMEM64G is not set # CONFIG_HPET is not set # CONFIG_HP_ACCEL is not set @@ -65,18 +64,15 @@ CONFIG_I2C_ALGOBIT=y CONFIG_I2C_ALGOPCA=y CONFIG_I2C_ALGOPCF=y CONFIG_I2C_BOARDINFO=y -# CONFIG_INTEL_INT0002_VGPIO is not set # CONFIG_INTEL_IPS is not set # CONFIG_INTEL_MENLOW is not set # CONFIG_INTEL_PMC_IPC is not set -# CONFIG_INTEL_SOC_PMIC_CHTWC is not set CONFIG_ISA=y # CONFIG_ISAPNP is not set -CONFIG_ISA_BUS_API=y # CONFIG_ISCSI_IBFT_FIND is not set # CONFIG_LANCE is not set CONFIG_LEDS_GPIO=y -# CONFIG_M586MMX is not set +# CONFIG_M486 is not set # CONFIG_MDA_CONSOLE is not set CONFIG_MFD_CORE=y CONFIG_MFD_CS5535=y @@ -86,7 +82,6 @@ CONFIG_MGEODEGX1=y CONFIG_NATSEMI=y CONFIG_NET5501=y CONFIG_NSC_GPIO=y -# CONFIG_OLPC is not set CONFIG_PATA_CS5520=y CONFIG_PATA_CS5530=y CONFIG_PATA_CS5535=y @@ -95,17 +90,12 @@ CONFIG_PATA_SC1200=y CONFIG_PC8736x_GPIO=y CONFIG_PCI_MMCONFIG=y # CONFIG_PCWATCHDOG is not set -CONFIG_PGTABLE_LEVELS=2 -# CONFIG_PHYS_ADDR_T_64BIT is not set # CONFIG_PMIC_OPREGION is not set CONFIG_PNP=y CONFIG_PNPACPI=y # CONFIG_PNPBIOS is not set CONFIG_PNP_DEBUG_MESSAGES=y # CONFIG_PVPANIC is not set -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y -CONFIG_RTC_I2C_AND_SPI=y # CONFIG_SAMSUNG_Q10 is not set CONFIG_SC1200_WDT=y CONFIG_SCx200_ACB=y @@ -114,10 +104,16 @@ CONFIG_SENSORS_LM90=y CONFIG_SERIAL_8250_PNP=y # CONFIG_SURFACE_PRO3_BUTTON is not set # CONFIG_TOSHIBA_BT_RFKILL is not set -# CONFIG_USB_UHCI_HCD is not set +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set +CONFIG_USB_EHCI_PCI=y +CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_HCD_PCI=y +# CONFIG_USB_OHCI_HCD_PLATFORM is not set +# CONFIG_USB_UHCI_HCD is not set CONFIG_VGACON_SOFT_SCROLLBACK=y -# CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT is not set CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 CONFIG_VIA_RHINE=y CONFIG_VIA_RHINE_MMIO=y @@ -130,7 +126,8 @@ CONFIG_X86_DEBUGCTLMSR=y # CONFIG_X86_INTEL_LPSS is not set # CONFIG_X86_LONGHAUL is not set # CONFIG_X86_MCE is not set -CONFIG_X86_MINIMUM_CPU_FAMILY=4 # CONFIG_X86_PCC_CPUFREQ is not set CONFIG_X86_PM_TIMER=y +# CONFIG_X86_PPRO_FENCE is not set CONFIG_X86_REBOOTFIXUPS=y +CONFIG_X86_TSC=y diff --git a/target/linux/x86/image/Makefile b/target/linux/x86/image/Makefile index 8a3cb327e..830bca6e4 100644 --- a/target/linux/x86/image/Makefile +++ b/target/linux/x86/image/Makefile @@ -10,6 +10,9 @@ include $(INCLUDE_DIR)/image.mk export PATH=$(TARGET_PATH):/sbin GRUB2_MODULES = biosdisk boot chain configfile ext2 linux ls part_msdos reboot serial vga +GRUB2_MODULES_LEGACY = $(GRUB2_MODULES) +GRUB2_MODULES_LEGACY += part_gpt search fat exfat +GRUB2_MODULES_EFI = boot chain configfile ext2 linux ls part_msdos reboot serial part_gpt part_msdos search fat exfat ext2 efi_gop efi_uga gfxterm GRUB2_MODULES_ISO = biosdisk boot chain configfile iso9660 linux ls part_msdos reboot serial vga GRUB_TERMINALS = GRUB_SERIAL_CONFIG = @@ -42,6 +45,8 @@ ifneq ($(GRUB_TERMINALS),) endif SIGNATURE:=$(shell perl -e 'printf("%08x", rand(0xFFFFFFFF))') +EFI_SIGNATURE:=$(shell perl -e 'printf("%08x-%04x-%04x-%04x-%06x%06x", rand(0xFFFFFFFF), rand(0xFFFF), rand(0xFFFF), rand(0xFFFF), rand(0xFFFFFF), rand(0xFFFFFF))') + ROOTPART:=$(call qstrip,$(CONFIG_TARGET_ROOTFS_PARTNAME)) ROOTPART:=$(if $(ROOTPART),$(ROOTPART),PARTUUID=$(SIGNATURE)-02) @@ -51,7 +56,7 @@ ifneq ($(CONFIG_TARGET_x86_xen_domu),) GRUB_ROOT = xen/xvda,msdos1 endif -ifneq ($(CONFIG_GRUB_IMAGES),) +ifneq ($(CONFIG_GRUB_IMAGES)$(CONFIG_EFI_IMAGES),) BOOTOPTS:=$(call qstrip,$(CONFIG_GRUB_BOOTOPTS)) @@ -63,6 +68,90 @@ ifneq ($(CONFIG_GRUB_IMAGES),) root=$(ROOTPART) rootfstype=squashfs rootwait endef + ifneq ($(CONFIG_EFI_IMAGES),) + + define Image/cmdline/efi + $(subst $(SIGNATURE)-02,$2,$(call Image/cmdline/$(1))) + endef + + define Image/Build/efi + # left here because the image builder doesnt need these + rm -rf $(KDIR)/root.grub/ || true + $(INSTALL_DIR) $(KDIR)/root.grub/boot/grub $(KDIR)/grub2 + $(CP) $(KDIR)/bzImage $(KDIR)/root.grub/boot/vmlinuz + echo '(hd0) $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img' > $(KDIR)/grub2/device.map + sed \ + -e 's#@SERIAL_CONFIG@#$(strip $(GRUB_SERIAL_CONFIG))#g' \ + -e 's#@TERMINAL_CONFIG@#$(strip $(GRUB_TERMINAL_CONFIG))#g' \ + -e 's#@CMDLINE@#$(strip $(call Image/cmdline/efi,$(1),$(EFI_SIGNATURE)) $(BOOTOPTS) $(GRUB_CONSOLE_CMDLINE))#g' \ + -e 's#@TIMEOUT@#$(GRUB_TIMEOUT)#g' \ + -e 's#set root.*#search --file /boot/grub/$(SIGNATURE).cfg --set=root#g' \ + ./grub.cfg > $(KDIR)/root.grub/boot/grub/grub.cfg + $(CP) $(KDIR)/root.grub/boot/grub/grub.cfg $(KDIR)/root.grub/boot/grub/$(SIGNATURE).cfg + grub-mkimage \ + -d $(STAGING_DIR_HOST)/lib/grub/i386-pc \ + -o $(KDIR)/grub2/core.img \ + -O i386-pc \ + -p '(hd0,gpt1)/boot/grub' \ + -c $(KDIR)/root.grub/boot/grub/grub.cfg \ + $(GRUB2_MODULES_LEGACY) + $(CP) $(STAGING_DIR_HOST)/lib/grub/i386-pc/*.img $(KDIR)/grub2/ + + # Build the efi grub version + rm -rf $(KDIR)/grub2.efi/ || true + $(INSTALL_DIR) $(KDIR)/grub2.efi/efi/boot/ + + # Generate the grub search root config (grub will search for the $(SIGNATURE).cfg file placed on the boot partition as grub does not support search of GPT UUID yet) + echo "search --file /boot/grub/$(SIGNATURE).cfg --set=root" > $(KDIR)/grub2.efi/efi/boot/grub.cfg + echo "configfile /boot/grub/grub.cfg" >> $(KDIR)/grub2.efi/efi/boot/grub.cfg + + # Create the EFI grub binary + grub-mkimage-efi \ + -d $(STAGING_DIR_HOST)/lib/grub/x86_64-efi \ + -o $(KDIR)/grub2.efi/efi/boot/bootx64.efi \ + -O x86_64-efi \ + -p /efi/boot \ + -c $(KDIR)/grub2.efi/efi/boot/grub.cfg \ + $(GRUB2_MODULES_EFI) + + # Generate the EFI VFAT bootfs + rm $(KDIR)/kernel.efi || true + mkfs.fat -C $(KDIR)/kernel.efi -S 512 1024 + mcopy -s -i "$(KDIR)/kernel.efi" $(KDIR)/grub2.efi/* ::/ + + SIGNATURE="$(SIGNATURE)" PATH="$(TARGET_PATH)" ./gen_image_efi.sh \ + $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img \ + $(CONFIG_TARGET_KERNEL_PARTSIZE) $(KDIR)/root.grub \ + 1 $(KDIR)/kernel.efi \ + 1 \ + $(CONFIG_TARGET_ROOTFS_PARTSIZE) $(KDIR)/root.$(1) \ + 256 + + # Setup legacy bios for hybrid MBR (optional) + grub-bios-setup \ + --device-map="$(KDIR)/grub2/device.map" \ + -d "$(KDIR)/grub2" \ + -r "hd0,msdos1" \ + "$(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img" + + # Convert the MBR partition to GPT and set EFI ROOTFS signature + dd if=/dev/zero of="$(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img" bs=512 count=33 conv=notrunc oflag=append + sgdisk -g "$(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img" + sgdisk -t 2:EF00 "$(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img" + sgdisk -t 3:EF02 "$(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img" + sgdisk -u 4:$(EFI_SIGNATURE) "$(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img" + sgdisk -h "$(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img" + + # Setup EFI grub + grub-bios-setup-efi \ + --device-map="$(KDIR)/grub2/device.map" \ + -d "$(KDIR)/grub2" \ + -r "hd0,gpt1" \ + "$(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img" + endef + endif + + ifneq ($(CONFIG_GRUB_IMAGES),) define Image/Build/grub2 # left here because the image builder doesnt need these $(INSTALL_DIR) $(KDIR)/root.grub/boot/grub $(KDIR)/grub2 @@ -94,6 +183,8 @@ ifneq ($(CONFIG_GRUB_IMAGES),) -r "hd0,msdos1" \ "$(BIN_DIR)/$(IMG_PREFIX)-combined-$(1).img" endef + endif + endif define Image/Build/squashfs @@ -133,6 +224,14 @@ ifneq ($(CONFIG_VDI_IMAGES),) # XXX: VBoxManage insists on setting perms to 0600 chmod 0644 $(BIN_DIR)/$(IMG_PREFIX)-combined-$(1).vdi endef + define Image/Build/vdi_efi + rm $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).vdi || true + qemu-img convert -f raw -O vdi \ + $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img \ + $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).vdi + # XXX: VBoxManage insists on setting perms to 0600 + chmod 0644 $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).vdi + endef endif ifneq ($(CONFIG_VMDK_IMAGES),) @@ -142,11 +241,37 @@ ifneq ($(CONFIG_VMDK_IMAGES),) $(BIN_DIR)/$(IMG_PREFIX)-combined-$(1).img \ $(BIN_DIR)/$(IMG_PREFIX)-combined-$(1).vmdk endef + define Image/Build/vmdk_efi + rm $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).vmdk || true + qemu-img convert -f raw -O vmdk \ + $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img \ + $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).vmdk + endef +endif + +ifneq ($(CONFIG_VHD_IMAGES),) + define Image/Build/vhd + rm $(BIN_DIR)/$(IMG_PREFIX)-combined-$(1).vhd || true + qemu-img convert -f raw -O vpc \ + $(BIN_DIR)/$(IMG_PREFIX)-combined-$(1).img \ + $(BIN_DIR)/$(IMG_PREFIX)-combined-$(1).vhd + endef + define Image/Build/vhd_efi + rm $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).vmdk || true + qemu-img convert -f raw -O vpc \ + $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img \ + $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).vhd + endef endif define Image/Build/gzip - gzip -f9n $(BIN_DIR)/$(IMG_PREFIX)-combined-$(1).img gzip -f9n $(BIN_DIR)/$(IMG_PREFIX)-rootfs-$(1).img +ifneq ($(CONFIG_GRUB_IMAGES),) + gzip -f9n $(BIN_DIR)/$(IMG_PREFIX)-combined-$(1).img +endif +ifneq ($(CONFIG_EFI_IMAGES),) + gzip -f9n $(BIN_DIR)/$(IMG_PREFIX)-uefi-gpt-$(1).img +endif endef ifneq ($(CONFIG_TARGET_IMAGES_GZIP),) @@ -174,8 +299,17 @@ define Image/Build $(call Image/Build/$(1)) ifneq ($(1),iso) $(call Image/Build/grub2,$(1)) + $(call Image/Build/efi,$(1)) +ifneq ($(CONFIG_GRUB_IMAGES),) $(call Image/Build/vdi,$(1)) $(call Image/Build/vmdk,$(1)) + $(call Image/Build/vhd,$(1)) +endif +ifneq ($(CONFIG_EFI_IMAGES),) + $(call Image/Build/vdi_efi,$(1)) + $(call Image/Build/vmdk_efi,$(1)) + $(call Image/Build/vhd_efi,$(1)) +endif $(CP) $(KDIR)/root.$(1) $(BIN_DIR)/$(IMG_PREFIX)-rootfs-$(1).img else $(CP) $(KDIR)/root.iso $(BIN_DIR)/$(IMG_PREFIX).iso diff --git a/target/linux/x86/image/gen_image_efi.sh b/target/linux/x86/image/gen_image_efi.sh new file mode 100755 index 000000000..3ecb25fed --- /dev/null +++ b/target/linux/x86/image/gen_image_efi.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +set -x +[ $# == 8 -o $# == 9 ] || { + echo "SYNTAX: $0 []" + exit 1 +} + +OUTPUT="$1" +KERNELSIZE="$2" +KERNELDIR="$3" +EFISIZE="$4" +EFIIMAGE="$5" +EFIGRUBSIZE="$6" +ROOTFSSIZE="$7" +ROOTFSIMAGE="$8" +ALIGN="$9" + +rm -f "$OUTPUT" + +head=16 +sect=63 +cyl=$(( ($KERNELSIZE + $EFISIZE + $EFIGRUBSIZE + $ROOTFSSIZE) * 1024 * 1024 / ($head * $sect * 512) )) + +# create partition table +set `ptgen -o "$OUTPUT" -h $head -s $sect -p ${KERNELSIZE}m -p ${EFISIZE}m -p ${EFIGRUBSIZE}m -p ${ROOTFSSIZE}m ${ALIGN:+-l $ALIGN} ${SIGNATURE:+-S 0x$SIGNATURE}` + +KERNELOFFSET="$(($1 / 512))" +KERNELSIZE="$2" +EFIOFFSET="$(($3 / 512))" +EFISIZE="$(($4 / 512))" +EFIGRUBOFFSET="$(($5 / 512))" +EFIGRUBSIZE="$(($6 / 512))" +ROOTFSOFFSET="$(($7 / 512))" +ROOTFSSIZE="$(($8 / 512))" + +dd if=/dev/zero of="$OUTPUT" bs=512 seek="$ROOTFSOFFSET" conv=notrunc count="$ROOTFSSIZE" +dd if="$ROOTFSIMAGE" of="$OUTPUT" bs=512 seek="$ROOTFSOFFSET" conv=notrunc +dd if="$EFIIMAGE" of="$OUTPUT" bs=512 seek="$EFIOFFSET" conv=notrunc + +[ -n "$NOGRUB" ] && exit 0 + +make_ext4fs -J -l "$KERNELSIZE" "$OUTPUT.kernel" "$KERNELDIR" +dd if="$OUTPUT.kernel" of="$OUTPUT" bs=512 seek="$KERNELOFFSET" conv=notrunc +rm -f "$OUTPUT.kernel" diff --git a/target/linux/x86/legacy/config-default b/target/linux/x86/legacy/config-default index d1a4e8103..02cd851de 100644 --- a/target/linux/x86/legacy/config-default +++ b/target/linux/x86/legacy/config-default @@ -1,4 +1,3 @@ -# CONFIG_104_QUAD_8 is not set # CONFIG_3C515 is not set CONFIG_ACPI=y CONFIG_ACPI_AC=y @@ -15,11 +14,11 @@ CONFIG_ACPI_CPU_FREQ_PSS=y # CONFIG_ACPI_FAN is not set CONFIG_ACPI_HOTPLUG_IOAPIC=y # CONFIG_ACPI_I2C_OPREGION is not set +# CONFIG_ACPI_INITRD_TABLE_OVERRIDE is not set CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y # CONFIG_ACPI_PCI_SLOT is not set CONFIG_ACPI_PROCESSOR=y # CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set -CONFIG_ACPI_PROCESSOR_CSTATE=y CONFIG_ACPI_PROCESSOR_IDLE=y # CONFIG_ACPI_PROCFS_POWER is not set CONFIG_ACPI_REV_OVERRIDE_POSSIBLE=y @@ -39,53 +38,56 @@ CONFIG_AGP_INTEL=y # CONFIG_AGP_SIS is not set # CONFIG_AGP_SWORKS is not set # CONFIG_AGP_VIA is not set -CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y +# CONFIG_BACKLIGHT_APPLE is not set CONFIG_BACKLIGHT_CLASS_DEVICE=y CONFIG_BACKLIGHT_GENERIC=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_BLK_DEV_SR=y # CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_COMMON_CLK=y CONFIG_CPU_IDLE_GOV_MENU=y CONFIG_DMA_SHARED_BUFFER=y -# CONFIG_DPTF_POWER is not set CONFIG_DRM=y CONFIG_DRM_AMDGPU=y # CONFIG_DRM_AMDGPU_CIK is not set -# CONFIG_DRM_AMDGPU_GART_DEBUGFS is not set -# CONFIG_DRM_AMDGPU_SI is not set # CONFIG_DRM_AMDGPU_USERPTR is not set -# CONFIG_DRM_AMD_ACP is not set +# CONFIG_DRM_AST is not set CONFIG_DRM_BOCHS=y CONFIG_DRM_BRIDGE=y +# CONFIG_DRM_CIRRUS_QEMU is not set CONFIG_DRM_FBDEV_EMULATION=y -CONFIG_DRM_FBDEV_OVERALLOC=100 # CONFIG_DRM_GMA500 is not set +# CONFIG_DRM_I2C_ADV7511 is not set +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_I2C_SIL164 is not set +# CONFIG_DRM_I810 is not set CONFIG_DRM_I915=y -# CONFIG_DRM_I915_ALPHA_SUPPORT is not set -CONFIG_DRM_I915_CAPTURE_ERROR=y -CONFIG_DRM_I915_COMPRESS_ERROR=y -# CONFIG_DRM_I915_DEBUG is not set -# CONFIG_DRM_I915_DEBUG_VBLANK_EVADE is not set -# CONFIG_DRM_I915_GVT is not set -# CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS is not set -# CONFIG_DRM_I915_SELFTEST is not set # CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT is not set -# CONFIG_DRM_I915_SW_FENCE_CHECK_DAG is not set -# CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS is not set -CONFIG_DRM_I915_USERPTR=y -# CONFIG_DRM_I915_WERROR is not set CONFIG_DRM_KMS_FB_HELPER=y CONFIG_DRM_KMS_HELPER=y +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +# CONFIG_DRM_MGA is not set +# CONFIG_DRM_MGAG200 is not set CONFIG_DRM_MIPI_DSI=y +# CONFIG_DRM_NOUVEAU is not set CONFIG_DRM_PANEL=y -CONFIG_DRM_PANEL_BRIDGE=y +# CONFIG_DRM_QXL is not set +# CONFIG_DRM_R128 is not set CONFIG_DRM_RADEON=y +# CONFIG_DRM_RADEON_UMS is not set # CONFIG_DRM_RADEON_USERPTR is not set +# CONFIG_DRM_SAVAGE is not set +# CONFIG_DRM_SIS is not set +# CONFIG_DRM_TDFX is not set CONFIG_DRM_TTM=y +# CONFIG_DRM_UDL is not set +# CONFIG_DRM_VGEM is not set +# CONFIG_DRM_VIA is not set # CONFIG_DRM_VMWGFX is not set -# CONFIG_EBC_C384_WDT is not set -# CONFIG_EFI_DEV_PATH_PARSER is not set +# CONFIG_EFI is not set # CONFIG_EISA is not set # CONFIG_EL3 is not set CONFIG_FB=y @@ -93,9 +95,7 @@ CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_IMAGEBLIT=y CONFIG_FB_CMDLINE=y -CONFIG_FB_DEFERRED_IO=y # CONFIG_FB_I810 is not set -# CONFIG_FB_PROVIDE_GET_FB_UNMAPPED_AREA is not set CONFIG_FB_SYS_COPYAREA=y CONFIG_FB_SYS_FILLRECT=y CONFIG_FB_SYS_FOPS=y @@ -110,9 +110,12 @@ CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set CONFIG_HAVE_ACPI_APEI=y CONFIG_HAVE_ACPI_APEI_NMI=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CLK_PREPARE=y CONFIG_HDMI=y +CONFIG_HID=y CONFIG_HID_BATTERY_STRENGTH=y -# CONFIG_HIGHMEM64G is not set +# CONFIG_HIGHMEM4G is not set CONFIG_HPET=y CONFIG_HPET_MMAP=y # CONFIG_HP_ACCEL is not set @@ -130,13 +133,9 @@ CONFIG_INTEL_IDLE=y # CONFIG_INTEL_IPS is not set # CONFIG_INTEL_MENLOW is not set # CONFIG_INTEL_PMC_IPC is not set -# CONFIG_INTEL_SOC_PMIC_CHTWC is not set CONFIG_INTERVAL_TREE=y -CONFIG_IOSF_MBI=y -# CONFIG_IOSF_MBI_DEBUG is not set CONFIG_ISA=y CONFIG_ISAPNP=y -CONFIG_ISA_BUS_API=y # CONFIG_ISCSI_IBFT_FIND is not set CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set @@ -148,26 +147,21 @@ CONFIG_MFD_INTEL_LPSS=y CONFIG_MFD_INTEL_LPSS_ACPI=y # CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set # CONFIG_MIXCOMWD is not set -CONFIG_MMU_NOTIFIER=y # CONFIG_MOUSE_BCM5974 is not set # CONFIG_MOUSE_CYAPA is not set CONFIG_MOUSE_PS2=y CONFIG_MOUSE_PS2_ALPS=y -# CONFIG_MOUSE_PS2_BYD is not set # CONFIG_MOUSE_PS2_CYPRESS is not set # CONFIG_MOUSE_PS2_ELANTECH is not set CONFIG_MOUSE_PS2_LIFEBOOK=y CONFIG_MOUSE_PS2_LOGIPS2PP=y -CONFIG_MOUSE_PS2_SMBUS=y CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y # CONFIG_MOUSE_PS2_TOUCHKIT is not set CONFIG_MOUSE_PS2_TRACKPOINT=y # CONFIG_MOUSE_SERIAL is not set # CONFIG_MOUSE_VSXXXAA is not set CONFIG_NOHIGHMEM=y CONFIG_NO_HZ=y -# CONFIG_OLPC is not set CONFIG_PATA_AMD=y CONFIG_PATA_ATIIXP=y CONFIG_PATA_LEGACY=y @@ -180,8 +174,6 @@ CONFIG_PCIEAER=y CONFIG_PCIEPORTBUS=y CONFIG_PCI_MMCONFIG=y # CONFIG_PCWATCHDOG is not set -CONFIG_PGTABLE_LEVELS=2 -# CONFIG_PHYS_ADDR_T_64BIT is not set # CONFIG_PMIC_OPREGION is not set CONFIG_PNP=y CONFIG_PNPACPI=y @@ -189,20 +181,21 @@ CONFIG_PNPACPI=y CONFIG_PNP_DEBUG_MESSAGES=y # CONFIG_PVPANIC is not set CONFIG_RAS=y -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y -CONFIG_RELAY=y -CONFIG_RTC_I2C_AND_SPI=y # CONFIG_SAMSUNG_Q10 is not set CONFIG_SATA_AHCI=y CONFIG_SERIAL_8250_PNP=y # CONFIG_SURFACE_PRO3_BUTTON is not set -# CONFIG_SW_SYNC is not set -CONFIG_SYNC_FILE=y # CONFIG_TOSHIBA_BT_RFKILL is not set +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set +CONFIG_USB_EHCI_PCI=y +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_HCD_PLATFORM is not set CONFIG_USB_STORAGE=y +CONFIG_USB_UHCI_HCD=y CONFIG_VGACON_SOFT_SCROLLBACK=y -# CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT is not set CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 # CONFIG_WDT is not set CONFIG_X86_ACPI_CPUFREQ=y @@ -212,9 +205,7 @@ CONFIG_X86_ACPI_CPUFREQ=y # CONFIG_X86_E_POWERSAVER is not set # CONFIG_X86_INTEL_LPSS is not set # CONFIG_X86_LONGHAUL is not set -CONFIG_X86_MINIMUM_CPU_FAMILY=4 # CONFIG_X86_PAE is not set # CONFIG_X86_PCC_CPUFREQ is not set CONFIG_X86_PM_TIMER=y # CONFIG_X86_POWERNOW_K8 is not set -CONFIG_ZLIB_DEFLATE=y diff --git a/target/linux/x86/patches-4.4/011-tune_lzma_options.patch b/target/linux/x86/patches-4.4/011-tune_lzma_options.patch new file mode 100644 index 000000000..5f8f5d821 --- /dev/null +++ b/target/linux/x86/patches-4.4/011-tune_lzma_options.patch @@ -0,0 +1,22 @@ +--- a/scripts/Makefile.lib ++++ b/scripts/Makefile.lib +@@ -324,7 +324,7 @@ cmd_bzip2 = (cat $(filter-out FORCE,$^) + + quiet_cmd_lzma = LZMA $@ + cmd_lzma = (cat $(filter-out FORCE,$^) | \ +- lzma e -d20 -lc1 -lp2 -pb2 -eos -si -so && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ ++ lzma e -lc8 -eos -si -so && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ + (rm -f $@ ; false) + + quiet_cmd_lzo = LZO $@ +--- a/arch/x86/include/asm/boot.h ++++ b/arch/x86/include/asm/boot.h +@@ -23,7 +23,7 @@ + #error "Invalid value for CONFIG_PHYSICAL_ALIGN" + #endif + +-#ifdef CONFIG_KERNEL_BZIP2 ++#if defined(CONFIG_KERNEL_BZIP2) || defined(CONFIG_KERNEL_LZMA) + #define BOOT_HEAP_SIZE 0x400000 + #else /* !CONFIG_KERNEL_BZIP2 */ + diff --git a/target/linux/x86/patches-4.4/097-0001-sp5100_tco-Add-AMD-Mullins-platform-support.patch b/target/linux/x86/patches-4.4/097-0001-sp5100_tco-Add-AMD-Mullins-platform-support.patch new file mode 100644 index 000000000..70169abbe --- /dev/null +++ b/target/linux/x86/patches-4.4/097-0001-sp5100_tco-Add-AMD-Mullins-platform-support.patch @@ -0,0 +1,26 @@ +From 190aa4304de6fe2185d96392ddf56580fa133e99 Mon Sep 17 00:00:00 2001 +From: Denis Turischev +Date: Tue, 24 Nov 2015 10:46:12 +0200 +Subject: [PATCH] sp5100_tco: Add AMD Mullins platform support + +AMD Mullins watchdog is fully compatible to the previous Hudson chipset, +reuse the existent sp5100_tco driver. + +Signed-off-by: Denis Turischev +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +--- + drivers/watchdog/sp5100_tco.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/watchdog/sp5100_tco.c ++++ b/drivers/watchdog/sp5100_tco.c +@@ -306,6 +306,8 @@ static struct miscdevice sp5100_tco_misc + static const struct pci_device_id sp5100_tco_pci_tbl[] = { + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_ANY_ID, + PCI_ANY_ID, }, ++ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, PCI_ANY_ID, ++ PCI_ANY_ID, }, + { 0, }, /* End of list */ + }; + MODULE_DEVICE_TABLE(pci, sp5100_tco_pci_tbl); diff --git a/target/linux/x86/patches-4.4/097-0002-sp5100_tco-Add-AMD-Carrizo-platform-support.patch b/target/linux/x86/patches-4.4/097-0002-sp5100_tco-Add-AMD-Carrizo-platform-support.patch new file mode 100644 index 000000000..33862a25d --- /dev/null +++ b/target/linux/x86/patches-4.4/097-0002-sp5100_tco-Add-AMD-Carrizo-platform-support.patch @@ -0,0 +1,27 @@ +From cca118fa2a0a94e0f0b3c8dd1dda922cdee45089 Mon Sep 17 00:00:00 2001 +From: Huang Rui +Date: Mon, 23 Nov 2015 18:07:36 +0800 +Subject: [PATCH] sp5100_tco: Add AMD Carrizo platform support + +sp5100_tco watchdog is also supported on AMD KernCZ chipset of Carrizo +platform. + +Signed-off-by: Huang Rui +Cc: Denis Turischev +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +--- + drivers/watchdog/sp5100_tco.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/watchdog/sp5100_tco.c ++++ b/drivers/watchdog/sp5100_tco.c +@@ -308,6 +308,8 @@ static const struct pci_device_id sp5100 + PCI_ANY_ID, }, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, PCI_ANY_ID, + PCI_ANY_ID, }, ++ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_KERNCZ_SMBUS, PCI_ANY_ID, ++ PCI_ANY_ID, }, + { 0, }, /* End of list */ + }; + MODULE_DEVICE_TABLE(pci, sp5100_tco_pci_tbl); diff --git a/target/linux/x86/patches-4.4/097-0003-sp5100_tco-fix-the-device-check-for-SB800-and-later-chipsets.patch b/target/linux/x86/patches-4.4/097-0003-sp5100_tco-fix-the-device-check-for-SB800-and-later-chipsets.patch new file mode 100644 index 000000000..8f16fa990 --- /dev/null +++ b/target/linux/x86/patches-4.4/097-0003-sp5100_tco-fix-the-device-check-for-SB800-and-later-chipsets.patch @@ -0,0 +1,76 @@ +From bdecfcdb5461834aab24002bb18d3cbdd907b7fb Mon Sep 17 00:00:00 2001 +From: Huang Rui +Date: Mon, 23 Nov 2015 18:07:35 +0800 +Subject: [PATCH] sp5100_tco: fix the device check for SB800 and later chipsets + +For SB800 and later chipsets, the register definitions are the same +with SB800. And for SB700 and older chipsets, the definitions should +be same with SP5100/SB7x0. + +Signed-off-by: Huang Rui +Cc: Denis Turischev +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +--- + drivers/watchdog/sp5100_tco.c | 28 ++++++++++++++++------------ + 1 file changed, 16 insertions(+), 12 deletions(-) + +--- a/drivers/watchdog/sp5100_tco.c ++++ b/drivers/watchdog/sp5100_tco.c +@@ -335,21 +335,24 @@ static unsigned char sp5100_tco_setupdev + if (!sp5100_tco_pci) + return 0; + +- pr_info("PCI Revision ID: 0x%x\n", sp5100_tco_pci->revision); ++ pr_info("PCI Vendor ID: 0x%x, Device ID: 0x%x, Revision ID: 0x%x\n", ++ sp5100_tco_pci->vendor, sp5100_tco_pci->device, ++ sp5100_tco_pci->revision); + + /* + * Determine type of southbridge chipset. + */ +- if (sp5100_tco_pci->revision >= 0x40) { +- dev_name = SB800_DEVNAME; +- index_reg = SB800_IO_PM_INDEX_REG; +- data_reg = SB800_IO_PM_DATA_REG; +- base_addr = SB800_PM_WATCHDOG_BASE; +- } else { ++ if (sp5100_tco_pci->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && ++ sp5100_tco_pci->revision < 0x40) { + dev_name = SP5100_DEVNAME; + index_reg = SP5100_IO_PM_INDEX_REG; + data_reg = SP5100_IO_PM_DATA_REG; + base_addr = SP5100_PM_WATCHDOG_BASE; ++ } else { ++ dev_name = SB800_DEVNAME; ++ index_reg = SB800_IO_PM_INDEX_REG; ++ data_reg = SB800_IO_PM_DATA_REG; ++ base_addr = SB800_PM_WATCHDOG_BASE; + } + + /* Request the IO ports used by this driver */ +@@ -385,7 +388,12 @@ static unsigned char sp5100_tco_setupdev + * Secondly, Find the watchdog timer MMIO address + * from SBResource_MMIO register. + */ +- if (sp5100_tco_pci->revision >= 0x40) { ++ if (sp5100_tco_pci->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && ++ sp5100_tco_pci->revision < 0x40) { ++ /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */ ++ pci_read_config_dword(sp5100_tco_pci, ++ SP5100_SB_RESOURCE_MMIO_BASE, &val); ++ } else { + /* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */ + outb(SB800_PM_ACPI_MMIO_EN+3, SB800_IO_PM_INDEX_REG); + val = inb(SB800_IO_PM_DATA_REG); +@@ -395,10 +403,6 @@ static unsigned char sp5100_tco_setupdev + val = val << 8 | inb(SB800_IO_PM_DATA_REG); + outb(SB800_PM_ACPI_MMIO_EN+0, SB800_IO_PM_INDEX_REG); + val = val << 8 | inb(SB800_IO_PM_DATA_REG); +- } else { +- /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */ +- pci_read_config_dword(sp5100_tco_pci, +- SP5100_SB_RESOURCE_MMIO_BASE, &val); + } + + /* The SBResource_MMIO is enabled and mapped memory space? */ diff --git a/target/linux/x86/patches-4.4/097-0004-watchdog-sp5100_tco-properly-check-for-new-register-.patch b/target/linux/x86/patches-4.4/097-0004-watchdog-sp5100_tco-properly-check-for-new-register-.patch new file mode 100644 index 000000000..103aa4853 --- /dev/null +++ b/target/linux/x86/patches-4.4/097-0004-watchdog-sp5100_tco-properly-check-for-new-register-.patch @@ -0,0 +1,72 @@ +From 46856fabe40cc80f92134683cdec7dc0fc8f4000 Mon Sep 17 00:00:00 2001 +From: Lucas Stach +Date: Tue, 3 May 2016 19:15:58 +0200 +Subject: [PATCH] watchdog: sp5100_tco: properly check for new register layouts + +Commits 190aa4304de6 (Add AMD Mullins platform support) and +cca118fa2a0a94 (Add AMD Carrizo platform support) enabled the +driver on a lot more devices, but the following commit missed +a single location in the code when checking if the SB800 register +offsets should be used. This leads to the wrong register being +written which in turn causes ACPI to go haywire. + +Fix this by introducing a helper function to check for the new +register layout and use this consistently. + +https://bugzilla.kernel.org/show_bug.cgi?id=114201 +https://bugzilla.redhat.com/show_bug.cgi?id=1329910 +Fixes: bdecfcdb5461 (sp5100_tco: fix the device check for SB800 +and later chipsets) +Cc: stable@vger.kernel.org (4.5+) +Signed-off-by: Lucas Stach +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +--- + drivers/watchdog/sp5100_tco.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +--- a/drivers/watchdog/sp5100_tco.c ++++ b/drivers/watchdog/sp5100_tco.c +@@ -73,6 +73,13 @@ MODULE_PARM_DESC(nowayout, "Watchdog can + /* + * Some TCO specific functions + */ ++ ++static bool tco_has_sp5100_reg_layout(struct pci_dev *dev) ++{ ++ return dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && ++ dev->revision < 0x40; ++} ++ + static void tco_timer_start(void) + { + u32 val; +@@ -129,7 +136,7 @@ static void tco_timer_enable(void) + { + int val; + +- if (sp5100_tco_pci->revision >= 0x40) { ++ if (!tco_has_sp5100_reg_layout(sp5100_tco_pci)) { + /* For SB800 or later */ + /* Set the Watchdog timer resolution to 1 sec */ + outb(SB800_PM_WATCHDOG_CONFIG, SB800_IO_PM_INDEX_REG); +@@ -342,8 +349,7 @@ static unsigned char sp5100_tco_setupdev + /* + * Determine type of southbridge chipset. + */ +- if (sp5100_tco_pci->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && +- sp5100_tco_pci->revision < 0x40) { ++ if (tco_has_sp5100_reg_layout(sp5100_tco_pci)) { + dev_name = SP5100_DEVNAME; + index_reg = SP5100_IO_PM_INDEX_REG; + data_reg = SP5100_IO_PM_DATA_REG; +@@ -388,8 +394,7 @@ static unsigned char sp5100_tco_setupdev + * Secondly, Find the watchdog timer MMIO address + * from SBResource_MMIO register. + */ +- if (sp5100_tco_pci->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && +- sp5100_tco_pci->revision < 0x40) { ++ if (tco_has_sp5100_reg_layout(sp5100_tco_pci)) { + /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */ + pci_read_config_dword(sp5100_tco_pci, + SP5100_SB_RESOURCE_MMIO_BASE, &val); diff --git a/target/linux/x86/patches-4.4/100-fix_cs5535_clockevt.patch b/target/linux/x86/patches-4.4/100-fix_cs5535_clockevt.patch new file mode 100644 index 000000000..c3a7fce9c --- /dev/null +++ b/target/linux/x86/patches-4.4/100-fix_cs5535_clockevt.patch @@ -0,0 +1,12 @@ +--- a/drivers/clocksource/cs5535-clockevt.c ++++ b/drivers/clocksource/cs5535-clockevt.c +@@ -130,7 +130,8 @@ static irqreturn_t mfgpt_tick(int irq, v + cs5535_mfgpt_write(cs5535_event_clock, MFGPT_REG_SETUP, + MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2); + +- cs5535_clockevent.event_handler(&cs5535_clockevent); ++ if (cs5535_clockevent.event_handler) ++ cs5535_clockevent.event_handler(&cs5535_clockevent); + return IRQ_HANDLED; + } + diff --git a/toolchain/Config.in b/toolchain/Config.in index bf7b9c33d..3de2b108b 100644 --- a/toolchain/Config.in +++ b/toolchain/Config.in @@ -286,6 +286,10 @@ config USE_MUSL default y if !TOOLCHAINOPTS && !EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN && !(arc || powerpc64) bool +config SSP_SUPPORT + default y if USE_MUSL || GCC_LIBSSP + bool + config USE_EXTERNAL_LIBC bool default y if EXTERNAL_TOOLCHAIN || NATIVE_TOOLCHAIN diff --git a/toolchain/binutils/Config.in b/toolchain/binutils/Config.in index 25f721a6b..56bcd162a 100644 --- a/toolchain/binutils/Config.in +++ b/toolchain/binutils/Config.in @@ -3,7 +3,7 @@ choice prompt "Binutils Version" if TOOLCHAINOPTS default BINUTILS_USE_VERSION_2_28 if !arc - default BINUTILS_USE_VERSION_2_28_ARC if arc + default BINUTILS_USE_VERSION_2_29_ARC if arc help Select the version of binutils you wish to use. @@ -17,10 +17,10 @@ choice bool "Binutils 2.28" select BINUTILS_VERSION_2_28 - config BINUTILS_USE_VERSION_2_28_ARC + config BINUTILS_USE_VERSION_2_29_ARC depends on arc - bool "ARC binutils 2.28" - select BINUTILS_VERSION_2_28_ARC + bool "ARC binutils 2.29" + select BINUTILS_VERSION_2_29_ARC config BINUTILS_USE_VERSION_2_29_1 depends on !arc diff --git a/toolchain/binutils/Config.version b/toolchain/binutils/Config.version index 54df1730c..159a25f10 100644 --- a/toolchain/binutils/Config.version +++ b/toolchain/binutils/Config.version @@ -5,7 +5,7 @@ config BINUTILS_VERSION_2_28 default y if (!TOOLCHAINOPTS && !arc) bool -config BINUTILS_VERSION_2_28_ARC +config BINUTILS_VERSION_2_29_ARC default y if (!TOOLCHAINOPTS && arc) bool @@ -17,4 +17,4 @@ config BINUTILS_VERSION default "2.27" if BINUTILS_VERSION_2_27 default "2.28" if BINUTILS_VERSION_2_28 default "2.29.1" if BINUTILS_VERSION_2_29_1 - default "arc-2017.03" if BINUTILS_VERSION_2_28_ARC + default "arc-2017.09" if BINUTILS_VERSION_2_29_ARC diff --git a/toolchain/binutils/Makefile b/toolchain/binutils/Makefile index fd4af5c25..c46d29933 100644 --- a/toolchain/binutils/Makefile +++ b/toolchain/binutils/Makefile @@ -25,11 +25,11 @@ ifeq ($(PKG_VERSION),2.29.1) PKG_HASH:=1509dff41369fb70aed23682351b663b56db894034773e6dbf7d5d6071fc55cc endif -ifneq ($(CONFIG_BINUTILS_VERSION_2_28_ARC),) - PKG_REV:=arc-2017.03-release +ifneq ($(CONFIG_BINUTILS_VERSION_2_29_ARC),) + PKG_REV:=arc-2017.09-release PKG_SOURCE_URL:=https://github.com/foss-for-synopsys-dwc-arc-processors/binutils-gdb/archive/$(PKG_REV)/ PKG_SOURCE:=$(PKG_NAME)-$(PKG_REV).tar.gz - PKG_HASH:=f9c1e09ef10aaf9619181f49587f464ba0a70d29b7f6f879047140acac852409 + PKG_HASH:=2ea086fd5521e942926dd6ff6922ce31c29ee7ffc754fca3d06385e0f27600f8 BINUTILS_DIR:=$(PKG_NAME)-gdb-$(PKG_REV) HOST_BUILD_DIR:=$(BUILD_DIR_TOOLCHAIN)/$(BINUTILS_DIR) endif diff --git a/toolchain/binutils/patches/2.28/001-ELF-BFD-Limit-_bfd_elf_link_renumber_dynsyms-call-in.patch b/toolchain/binutils/patches/2.28/001-ELF-BFD-Limit-_bfd_elf_link_renumber_dynsyms-call-in.patch new file mode 100644 index 000000000..e2587b81e --- /dev/null +++ b/toolchain/binutils/patches/2.28/001-ELF-BFD-Limit-_bfd_elf_link_renumber_dynsyms-call-in.patch @@ -0,0 +1,52 @@ +From 2424aef3a744bc6ca4099a655065c70a63f0fb49 Mon Sep 17 00:00:00 2001 +From: "Maciej W. Rozycki" +Date: Wed, 26 Apr 2017 22:18:13 +0100 +Subject: ELF/BFD: Limit `_bfd_elf_link_renumber_dynsyms' call in section GC + +Consistently call `_bfd_elf_link_renumber_dynsyms' only if linking a +dynamic binary, complementing code in `bfd_elf_size_dynsym_hash_dynstr' +and commit ccabcbe51e85 ("New attempt at fixing MIPS --gc-sections et +al."), . + + bfd/ + * elflink.c (elf_gc_sweep): Only call + `_bfd_elf_link_renumber_dynsyms' if dynamic sections have been + created. + +(backported from commit c46cec3a8cfe02fbe0f6c67ba53abc5369c5c659) +--- + bfd/ChangeLog | 6 ++++++ + bfd/elflink.c | 3 ++- + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/bfd/ChangeLog b/bfd/ChangeLog +index 85c6a817e5..537ebb5e2c 100644 +--- a/bfd/ChangeLog ++++ b/bfd/ChangeLog +@@ -1,3 +1,9 @@ ++2017-04-26 Maciej W. Rozycki ++ ++ * elflink.c (elf_gc_sweep): Only call ++ `_bfd_elf_link_renumber_dynsyms' if dynamic sections have been ++ created. ++ + 2017-03-02 Tristan Gingold + + * version.m4: Bump version to 2.28 +diff --git a/bfd/elflink.c b/bfd/elflink.c +index 69b66f2831..75d6543dcc 100644 +--- a/bfd/elflink.c ++++ b/bfd/elflink.c +@@ -12986,7 +12986,8 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info) + elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol, + &sweep_info); + +- _bfd_elf_link_renumber_dynsyms (abfd, info, §ion_sym_count); ++ if (elf_hash_table (info)->dynamic_sections_created) ++ _bfd_elf_link_renumber_dynsyms (abfd, info, §ion_sym_count); + return TRUE; + } + +-- +2.11.0 + diff --git a/toolchain/binutils/patches/2.28/002-PR-ld-21334-Always-call-_bfd_elf_link_renumber_dynsy.patch b/toolchain/binutils/patches/2.28/002-PR-ld-21334-Always-call-_bfd_elf_link_renumber_dynsy.patch new file mode 100644 index 000000000..7cfbaa615 --- /dev/null +++ b/toolchain/binutils/patches/2.28/002-PR-ld-21334-Always-call-_bfd_elf_link_renumber_dynsy.patch @@ -0,0 +1,184 @@ +From 51ffcfc2c67b4c4aa1620fb4c9834c38d150e1c5 Mon Sep 17 00:00:00 2001 +From: "Maciej W. Rozycki" +Date: Wed, 26 Apr 2017 22:23:44 +0100 +Subject: PR ld/21334: Always call `_bfd_elf_link_renumber_dynsyms' if required + +Complement commit e17b0c351f0b ("MIPS/BFD: Respect the ELF gABI dynamic +symbol table sort requirement") and correct an inconsistency in dynamic +symbol accounting data causing an assertion failure in the MIPS backend: + +ld: BFD (GNU Binutils) 2.28.51.20170330 assertion fail +../../binutils-gdb/bfd/elfxx-mips.c:3860 + +in the course of making a GOT entry in a static binary to satisfy a GOT +relocation present in input, due to the local dynamic symbol count not +having been established. + +To do so let backends request `_bfd_elf_link_renumber_dynsyms' to be +always called, rather than where a dynamic binary is linked only, and +then make this request in the MIPS backend. + + bfd/ + PR ld/21334 + * elf-bfd.h (elf_backend_data): Add `always_renumber_dynsyms' + member. + * elfxx-target.h [!elf_backend_always_renumber_dynsyms] + (elf_backend_always_renumber_dynsyms): Define. + (elfNN_bed): Initialize `always_renumber_dynsyms' member. + * elfxx-mips.h (elf_backend_always_renumber_dynsyms): Define. + * elflink.c (bfd_elf_size_dynsym_hash_dynstr): Also call + `_bfd_elf_link_renumber_dynsyms' if the backend has requested + it. + (elf_gc_sweep): Likewise. + +(backported from commit 23ec1e32b1ab714649a7c25e49b5d721fe3bd3db) +--- + bfd/ChangeLog | 14 ++++++++++++++ + bfd/elf-bfd.h | 4 ++++ + bfd/elflink.c | 34 +++++++++++++++++++++++----------- + bfd/elfxx-mips.h | 1 + + bfd/elfxx-target.h | 6 +++++- + 5 files changed, 47 insertions(+), 12 deletions(-) + +diff --git a/bfd/ChangeLog b/bfd/ChangeLog +index 537ebb5e2c..3f10bc55f2 100644 +--- a/bfd/ChangeLog ++++ b/bfd/ChangeLog +@@ -1,5 +1,19 @@ + 2017-04-26 Maciej W. Rozycki + ++ PR ld/21334 ++ * elf-bfd.h (elf_backend_data): Add `always_renumber_dynsyms' ++ member. ++ * elfxx-target.h [!elf_backend_always_renumber_dynsyms] ++ (elf_backend_always_renumber_dynsyms): Define. ++ (elfNN_bed): Initialize `always_renumber_dynsyms' member. ++ * elfxx-mips.h (elf_backend_always_renumber_dynsyms): Define. ++ * elflink.c (bfd_elf_size_dynsym_hash_dynstr): Also call ++ `_bfd_elf_link_renumber_dynsyms' if the backend has requested ++ it. ++ (elf_gc_sweep): Likewise. ++ ++2017-04-26 Maciej W. Rozycki ++ + * elflink.c (elf_gc_sweep): Only call + `_bfd_elf_link_renumber_dynsyms' if dynamic sections have been + created. +diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h +index 5de9ab6ca6..dc4bd87f89 100644 +--- a/bfd/elf-bfd.h ++++ b/bfd/elf-bfd.h +@@ -1478,6 +1478,10 @@ struct elf_backend_data + /* Address of protected data defined in the shared library may be + external, i.e., due to copy relocation. */ + unsigned extern_protected_data : 1; ++ ++ /* True if `_bfd_elf_link_renumber_dynsyms' must be called even for ++ static binaries. */ ++ unsigned always_renumber_dynsyms : 1; + }; + + /* Information about reloc sections associated with a bfd_elf_section_data +diff --git a/bfd/elflink.c b/bfd/elflink.c +index 75d6543dcc..507f2b6259 100644 +--- a/bfd/elflink.c ++++ b/bfd/elflink.c +@@ -6710,6 +6710,8 @@ bfd_boolean + bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) + { + const struct elf_backend_data *bed; ++ unsigned long section_sym_count; ++ bfd_size_type dynsymcount; + + if (!is_elf_hash_table (info->hash)) + return TRUE; +@@ -6717,24 +6719,30 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) + bed = get_elf_backend_data (output_bfd); + (*bed->elf_backend_init_index_section) (output_bfd, info); + ++ /* Assign dynsym indices. In a shared library we generate a section ++ symbol for each output section, which come first. Next come all ++ of the back-end allocated local dynamic syms, followed by the rest ++ of the global symbols. ++ ++ This is usually not needed for static binaries, however backends ++ can request to always do it, e.g. the MIPS backend uses dynamic ++ symbol counts to lay out GOT, which will be produced in the ++ presence of GOT relocations even in static binaries (holding fixed ++ data in that case, to satisfy those relocations). */ ++ ++ if (elf_hash_table (info)->dynamic_sections_created ++ || bed->always_renumber_dynsyms) ++ dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info, ++ §ion_sym_count); ++ + if (elf_hash_table (info)->dynamic_sections_created) + { + bfd *dynobj; + asection *s; +- bfd_size_type dynsymcount; +- unsigned long section_sym_count; + unsigned int dtagcount; + + dynobj = elf_hash_table (info)->dynobj; + +- /* Assign dynsym indicies. In a shared library we generate a +- section symbol for each output section, which come first. +- Next come all of the back-end allocated local dynamic syms, +- followed by the rest of the global symbols. */ +- +- dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info, +- §ion_sym_count); +- + /* Work out the size of the symbol version section. */ + s = bfd_get_linker_section (dynobj, ".gnu.version"); + BFD_ASSERT (s != NULL); +@@ -12986,7 +12994,11 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info) + elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol, + &sweep_info); + +- if (elf_hash_table (info)->dynamic_sections_created) ++ /* We need to reassign dynsym indices now that symbols may have ++ been removed. See the call in `bfd_elf_size_dynsym_hash_dynstr' ++ for the details of the conditions used here. */ ++ if (elf_hash_table (info)->dynamic_sections_created ++ || bed->always_renumber_dynsyms) + _bfd_elf_link_renumber_dynsyms (abfd, info, §ion_sym_count); + return TRUE; + } +diff --git a/bfd/elfxx-mips.h b/bfd/elfxx-mips.h +index fa5b5d2de9..274129b2e5 100644 +--- a/bfd/elfxx-mips.h ++++ b/bfd/elfxx-mips.h +@@ -196,3 +196,4 @@ literal_reloc_p (int r_type) + #define elf_backend_post_process_headers _bfd_mips_post_process_headers + #define elf_backend_compact_eh_encoding _bfd_mips_elf_compact_eh_encoding + #define elf_backend_cant_unwind_opcode _bfd_mips_elf_cant_unwind_opcode ++#define elf_backend_always_renumber_dynsyms TRUE +diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h +index d063fb7f1b..d07600c15d 100644 +--- a/bfd/elfxx-target.h ++++ b/bfd/elfxx-target.h +@@ -126,6 +126,9 @@ + #ifndef elf_backend_extern_protected_data + #define elf_backend_extern_protected_data 0 + #endif ++#ifndef elf_backend_always_renumber_dynsyms ++#define elf_backend_always_renumber_dynsyms FALSE ++#endif + #ifndef elf_backend_stack_align + #define elf_backend_stack_align 16 + #endif +@@ -866,7 +869,8 @@ static struct elf_backend_data elfNN_bed = + elf_backend_no_page_alias, + elf_backend_default_execstack, + elf_backend_caches_rawsize, +- elf_backend_extern_protected_data ++ elf_backend_extern_protected_data, ++ elf_backend_always_renumber_dynsyms + }; + + /* Forward declaration for use when initialising alternative_target field. */ +-- +2.11.0 + diff --git a/toolchain/gcc/Config.in b/toolchain/gcc/Config.in index a54c8d12d..30ac13787 100644 --- a/toolchain/gcc/Config.in +++ b/toolchain/gcc/Config.in @@ -2,14 +2,14 @@ choice prompt "GCC compiler Version" if TOOLCHAINOPTS - default GCC_USE_VERSION_6_3_ARC if arc + default GCC_USE_VERSION_7_1_ARC if arc default GCC_USE_VERSION_5 help Select the version of gcc you wish to use. - config GCC_USE_VERSION_6_3_ARC - select GCC_VERSION_6_3_ARC - bool "gcc 6.3.x with support of ARC cores" + config GCC_USE_VERSION_7_1_ARC + select GCC_VERSION_7_1_ARC + bool "gcc 7.1.x with support of ARC cores" depends on arc config GCC_USE_VERSION_5 @@ -37,9 +37,24 @@ config EXTRA_GCC_CONFIG_OPTIONS help Any additional gcc options you may want to include.... -config SSP_SUPPORT +config GCC_DEFAULT_PIE bool - prompt "Enable Stack-Smashing Protection support" if TOOLCHAINOPTS + prompt "Build executable with PIE enabled by default" if TOOLCHAINOPTS + depends on !GCC_USE_VERSION_5 + default n + help + Use gcc configure option --enable-default-pie to turn on -fPIE and -pie by default. + +config GCC_DEFAULT_SSP + bool + prompt "Build executable with Stack-Smashing Protection enabled by default" if TOOLCHAINOPTS + default n + help + Use gcc configure option --enable-default-ssp to turn on -fstack-protector-strong by default. + +config GCC_LIBSSP + bool + prompt "Build gcc libssp" if TOOLCHAINOPTS depends on !USE_MUSL default y if !USE_MUSL help diff --git a/toolchain/gcc/Config.version b/toolchain/gcc/Config.version index 4edf8a87a..307a3657a 100644 --- a/toolchain/gcc/Config.version +++ b/toolchain/gcc/Config.version @@ -1,14 +1,14 @@ -config GCC_VERSION_6_3_ARC +config GCC_VERSION_7_1_ARC default y if (!TOOLCHAINOPTS && arc) bool config GCC_VERSION string - default "arc-2017.03-release" if GCC_VERSION_6_3_ARC + default "arc-2017.09-release" if GCC_VERSION_7_1_ARC default "6.3.0" if GCC_USE_VERSION_6 - default "7.2.0" if GCC_USE_VERSION_7 + default "7.3.0" if GCC_USE_VERSION_7 default "5.5.0" -config GCC_VERSION_6_3 +config GCC_VERSION_7_1 bool - default y if GCC_VERSION_6_3_ARC + default y if GCC_VERSION_7_1_ARC diff --git a/toolchain/gcc/common.mk b/toolchain/gcc/common.mk index 69214aca0..fb60e57c7 100644 --- a/toolchain/gcc/common.mk +++ b/toolchain/gcc/common.mk @@ -37,16 +37,16 @@ ifeq ($(PKG_VERSION),6.3.0) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 endif -ifeq ($(PKG_VERSION),7.2.0) - PKG_HASH:=1cf7adf8ff4b5aa49041c8734bbcf1ad18cc4c94d0029aae0f4e48841088479a +ifeq ($(PKG_VERSION),7.3.0) + PKG_HASH:=832ca6ae04636adbb430e865a1451adf6979ab44ca1c8374f61fba65645ce15c endif -ifneq ($(CONFIG_GCC_VERSION_6_3_ARC),) - PKG_VERSION:=6.3.0 +ifneq ($(CONFIG_GCC_VERSION_7_1_ARC),) + PKG_VERSION:=7.1.1 PKG_SOURCE_URL:=https://github.com/foss-for-synopsys-dwc-arc-processors/gcc/archive/$(GCC_VERSION) PKG_SOURCE:=$(PKG_NAME)-$(GCC_VERSION).tar.gz - PKG_HASH:=b7223e134199b1a6f71de629da6aa845790e55d28e9892143dde09b1bc878110 - PKG_REV:=2017.03-release + PKG_HASH:=90596af8b9c26a434cec0a3b3d37d0c7c755ab6a65496af6ca32529fab5a6cfe + PKG_REV:=2017.09-release GCC_DIR:=gcc-arc-$(PKG_REV) HOST_BUILD_DIR = $(BUILD_DIR_HOST)/$(PKG_NAME)-$(GCC_VERSION) endif @@ -133,7 +133,17 @@ ifndef GCC_VERSION_4_8 GCC_CONFIGURE += --with-diagnostics-color=auto-if-env endif -ifneq ($(CONFIG_SSP_SUPPORT),) +ifneq ($(CONFIG_GCC_DEFAULT_PIE),) + GCC_CONFIGURE+= \ + --enable-default-pie +endif + +ifneq ($(CONFIG_GCC_DEFAULT_SSP),) + GCC_CONFIGURE+= \ + --enable-default-ssp +endif + +ifneq ($(CONFIG_GCC_LIBSSP),) GCC_CONFIGURE+= \ --enable-libssp else diff --git a/toolchain/gcc/patches/7.2.0/001-revert_register_mode_search.patch b/toolchain/gcc/patches/7.3.0/001-revert_register_mode_search.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/001-revert_register_mode_search.patch rename to toolchain/gcc/patches/7.3.0/001-revert_register_mode_search.patch diff --git a/toolchain/gcc/patches/7.2.0/002-case_insensitive.patch b/toolchain/gcc/patches/7.3.0/002-case_insensitive.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/002-case_insensitive.patch rename to toolchain/gcc/patches/7.3.0/002-case_insensitive.patch diff --git a/toolchain/gcc/patches/7.2.0/010-documentation.patch b/toolchain/gcc/patches/7.3.0/010-documentation.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/010-documentation.patch rename to toolchain/gcc/patches/7.3.0/010-documentation.patch diff --git a/toolchain/gcc/patches/7.2.0/230-musl_libssp.patch b/toolchain/gcc/patches/7.3.0/230-musl_libssp.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/230-musl_libssp.patch rename to toolchain/gcc/patches/7.3.0/230-musl_libssp.patch diff --git a/toolchain/gcc/patches/7.2.0/300-mips_Os_cpu_rtx_cost_model.patch b/toolchain/gcc/patches/7.3.0/300-mips_Os_cpu_rtx_cost_model.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/300-mips_Os_cpu_rtx_cost_model.patch rename to toolchain/gcc/patches/7.3.0/300-mips_Os_cpu_rtx_cost_model.patch diff --git a/toolchain/gcc/patches/7.2.0/800-arm_v5te_no_ldrd_strd.patch b/toolchain/gcc/patches/7.3.0/800-arm_v5te_no_ldrd_strd.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/800-arm_v5te_no_ldrd_strd.patch rename to toolchain/gcc/patches/7.3.0/800-arm_v5te_no_ldrd_strd.patch diff --git a/toolchain/gcc/patches/7.2.0/810-arm-softfloat-libgcc.patch b/toolchain/gcc/patches/7.3.0/810-arm-softfloat-libgcc.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/810-arm-softfloat-libgcc.patch rename to toolchain/gcc/patches/7.3.0/810-arm-softfloat-libgcc.patch diff --git a/toolchain/gcc/patches/7.2.0/820-libgcc_pic.patch b/toolchain/gcc/patches/7.3.0/820-libgcc_pic.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/820-libgcc_pic.patch rename to toolchain/gcc/patches/7.3.0/820-libgcc_pic.patch diff --git a/toolchain/gcc/patches/7.2.0/840-armv4_pass_fix-v4bx_to_ld.patch b/toolchain/gcc/patches/7.3.0/840-armv4_pass_fix-v4bx_to_ld.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/840-armv4_pass_fix-v4bx_to_ld.patch rename to toolchain/gcc/patches/7.3.0/840-armv4_pass_fix-v4bx_to_ld.patch diff --git a/toolchain/gcc/patches/7.2.0/850-use_shared_libgcc.patch b/toolchain/gcc/patches/7.3.0/850-use_shared_libgcc.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/850-use_shared_libgcc.patch rename to toolchain/gcc/patches/7.3.0/850-use_shared_libgcc.patch diff --git a/toolchain/gcc/patches/7.2.0/851-libgcc_no_compat.patch b/toolchain/gcc/patches/7.3.0/851-libgcc_no_compat.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/851-libgcc_no_compat.patch rename to toolchain/gcc/patches/7.3.0/851-libgcc_no_compat.patch diff --git a/toolchain/gcc/patches/7.2.0/870-ppc_no_crtsavres.patch b/toolchain/gcc/patches/7.3.0/870-ppc_no_crtsavres.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/870-ppc_no_crtsavres.patch rename to toolchain/gcc/patches/7.3.0/870-ppc_no_crtsavres.patch diff --git a/toolchain/gcc/patches/7.2.0/881-no_tm_section.patch b/toolchain/gcc/patches/7.3.0/881-no_tm_section.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/881-no_tm_section.patch rename to toolchain/gcc/patches/7.3.0/881-no_tm_section.patch diff --git a/toolchain/gcc/patches/7.2.0/900-bad-mips16-crt.patch b/toolchain/gcc/patches/7.3.0/900-bad-mips16-crt.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/900-bad-mips16-crt.patch rename to toolchain/gcc/patches/7.3.0/900-bad-mips16-crt.patch diff --git a/toolchain/gcc/patches/7.2.0/910-mbsd_multi.patch b/toolchain/gcc/patches/7.3.0/910-mbsd_multi.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/910-mbsd_multi.patch rename to toolchain/gcc/patches/7.3.0/910-mbsd_multi.patch diff --git a/toolchain/gcc/patches/7.2.0/920-specs_nonfatal_getenv.patch b/toolchain/gcc/patches/7.3.0/920-specs_nonfatal_getenv.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/920-specs_nonfatal_getenv.patch rename to toolchain/gcc/patches/7.3.0/920-specs_nonfatal_getenv.patch diff --git a/toolchain/gcc/patches/7.2.0/930-fix-mips-noexecstack.patch b/toolchain/gcc/patches/7.3.0/930-fix-mips-noexecstack.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/930-fix-mips-noexecstack.patch rename to toolchain/gcc/patches/7.3.0/930-fix-mips-noexecstack.patch diff --git a/toolchain/gcc/patches/7.2.0/940-no-clobber-stamp-bits.patch b/toolchain/gcc/patches/7.3.0/940-no-clobber-stamp-bits.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/940-no-clobber-stamp-bits.patch rename to toolchain/gcc/patches/7.3.0/940-no-clobber-stamp-bits.patch diff --git a/toolchain/gcc/patches/7.2.0/950-cpp_file_path_translation.patch b/toolchain/gcc/patches/7.3.0/950-cpp_file_path_translation.patch similarity index 100% rename from toolchain/gcc/patches/7.2.0/950-cpp_file_path_translation.patch rename to toolchain/gcc/patches/7.3.0/950-cpp_file_path_translation.patch diff --git a/toolchain/gcc/patches/arc-2017.03-release/230-musl_libssp.patch b/toolchain/gcc/patches/arc-2017.03-release/230-musl_libssp.patch deleted file mode 100644 index 8dfd1fc28..000000000 --- a/toolchain/gcc/patches/arc-2017.03-release/230-musl_libssp.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- a/gcc/gcc.c -+++ b/gcc/gcc.c -@@ -858,7 +858,9 @@ proper position among the other output f - #endif - - #ifndef LINK_SSP_SPEC --#ifdef TARGET_LIBC_PROVIDES_SSP -+#if DEFAULT_LIBC == LIBC_MUSL -+#define LINK_SSP_SPEC "-lssp_nonshared" -+#elif defined(TARGET_LIBC_PROVIDES_SSP) - #define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \ - "|fstack-protector-strong|fstack-protector-explicit:}" - #else diff --git a/toolchain/gcc/patches/arc-2017.03-release/280-musl-disable-ifunc-by-default.patch b/toolchain/gcc/patches/arc-2017.03-release/280-musl-disable-ifunc-by-default.patch deleted file mode 100644 index df09e4f63..000000000 --- a/toolchain/gcc/patches/arc-2017.03-release/280-musl-disable-ifunc-by-default.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 450fb05e2a7510d37744f044009f8237d902f65c Mon Sep 17 00:00:00 2001 -From: nsz -Date: Tue, 30 Aug 2016 10:26:22 +0000 -Subject: [PATCH] disable ifunc on *-musl by default - -gcc/ - * config.gcc (*-*-*musl*): Disable gnu-indirect-function. - - - -git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@239859 138bc75d-0d04-0410-961f-82ee72b054a4 ---- - gcc/ChangeLog | 4 ++++ - gcc/config.gcc | 4 ++-- - 2 files changed, 6 insertions(+), 2 deletions(-) - ---- a/gcc/config.gcc -+++ b/gcc/config.gcc -@@ -1495,7 +1495,7 @@ i[34567]86-*-linux* | i[34567]86-*-kfree - extra_options="${extra_options} linux-android.opt" - # Assume modern glibc if not targeting Android nor uclibc. - case ${target} in -- *-*-*android*|*-*-*uclibc*) -+ *-*-*android*|*-*-*uclibc*|*-*-*musl*) - ;; - *) - default_gnu_indirect_function=yes -@@ -1564,7 +1564,7 @@ x86_64-*-linux* | x86_64-*-kfreebsd*-gnu - extra_options="${extra_options} linux-android.opt" - # Assume modern glibc if not targeting Android nor uclibc. - case ${target} in -- *-*-*android*|*-*-*uclibc*) -+ *-*-*android*|*-*-*uclibc*|*-*-*musl*) - ;; - *) - default_gnu_indirect_function=yes diff --git a/toolchain/gcc/patches/arc-2017.03-release/300-mips_Os_cpu_rtx_cost_model.patch b/toolchain/gcc/patches/arc-2017.03-release/300-mips_Os_cpu_rtx_cost_model.patch deleted file mode 100644 index d76bd8cb1..000000000 --- a/toolchain/gcc/patches/arc-2017.03-release/300-mips_Os_cpu_rtx_cost_model.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/gcc/config/mips/mips.c -+++ b/gcc/config/mips/mips.c -@@ -17928,7 +17928,7 @@ mips_option_override (void) - flag_pcc_struct_return = 0; - - /* Decide which rtx_costs structure to use. */ -- if (optimize_size) -+ if (0 && optimize_size) - mips_cost = &mips_rtx_cost_optimize_size; - else - mips_cost = &mips_rtx_cost_data[mips_tune]; diff --git a/toolchain/gcc/patches/arc-2017.03-release/800-arm_v5te_no_ldrd_strd.patch b/toolchain/gcc/patches/arc-2017.03-release/800-arm_v5te_no_ldrd_strd.patch deleted file mode 100644 index 2e7c23f85..000000000 --- a/toolchain/gcc/patches/arc-2017.03-release/800-arm_v5te_no_ldrd_strd.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/gcc/config/arm/arm.h -+++ b/gcc/config/arm/arm.h -@@ -166,7 +166,7 @@ extern void (*arm_lang_output_object_att - /* Thumb-1 only. */ - #define TARGET_THUMB1_ONLY (TARGET_THUMB1 && !arm_arch_notm) - --#define TARGET_LDRD (arm_arch5e && ARM_DOUBLEWORD_ALIGN \ -+#define TARGET_LDRD (arm_arch6 && ARM_DOUBLEWORD_ALIGN \ - && !TARGET_THUMB1) - - #define TARGET_CRC32 (arm_arch_crc) diff --git a/toolchain/gcc/patches/arc-2017.03-release/830-arm_unbreak_armv4t.patch b/toolchain/gcc/patches/arc-2017.03-release/830-arm_unbreak_armv4t.patch deleted file mode 100644 index 37f8f2a54..000000000 --- a/toolchain/gcc/patches/arc-2017.03-release/830-arm_unbreak_armv4t.patch +++ /dev/null @@ -1,13 +0,0 @@ -http://sourceware.org/ml/crossgcc/2008-05/msg00009.html - ---- a/gcc/config/arm/linux-eabi.h -+++ b/gcc/config/arm/linux-eabi.h -@@ -45,7 +45,7 @@ - The ARM10TDMI core is the default for armv5t, so set - SUBTARGET_CPU_DEFAULT to achieve this. */ - #undef SUBTARGET_CPU_DEFAULT --#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm10tdmi -+#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm9tdmi - - /* TARGET_BIG_ENDIAN_DEFAULT is set in - config.gcc for big endian configurations. */ diff --git a/toolchain/gcc/patches/arc-2017.03-release/870-ppc_no_crtsavres.patch b/toolchain/gcc/patches/arc-2017.03-release/870-ppc_no_crtsavres.patch deleted file mode 100644 index 9e543a0fc..000000000 --- a/toolchain/gcc/patches/arc-2017.03-release/870-ppc_no_crtsavres.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/gcc/config/rs6000/rs6000.c -+++ b/gcc/config/rs6000/rs6000.c -@@ -24171,7 +24171,7 @@ rs6000_savres_strategy (rs6000_stack_t * - /* Define cutoff for using out-of-line functions to save registers. */ - if (DEFAULT_ABI == ABI_V4 || TARGET_ELF) - { -- if (!optimize_size) -+ if (1) - { - strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS; - strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS; diff --git a/toolchain/gcc/patches/arc-2017.03-release/880-no_java_section.patch b/toolchain/gcc/patches/arc-2017.03-release/880-no_java_section.patch deleted file mode 100644 index 0fa9e627c..000000000 --- a/toolchain/gcc/patches/arc-2017.03-release/880-no_java_section.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/gcc/defaults.h -+++ b/gcc/defaults.h -@@ -395,7 +395,7 @@ see the files COPYING3 and COPYING.RUNTI - /* If we have named section and we support weak symbols, then use the - .jcr section for recording java classes which need to be registered - at program start-up time. */ --#if defined (TARGET_ASM_NAMED_SECTION) && SUPPORTS_WEAK -+#if 0 && defined (TARGET_ASM_NAMED_SECTION) && SUPPORTS_WEAK - #ifndef JCR_SECTION_NAME - #define JCR_SECTION_NAME ".jcr" - #endif diff --git a/toolchain/gcc/patches/arc-2017.03-release/881-no_tm_section.patch b/toolchain/gcc/patches/arc-2017.03-release/881-no_tm_section.patch deleted file mode 100644 index fab5db3be..000000000 --- a/toolchain/gcc/patches/arc-2017.03-release/881-no_tm_section.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/libgcc/crtstuff.c -+++ b/libgcc/crtstuff.c -@@ -152,7 +152,7 @@ call_ ## FUNC (void) \ - #endif - - #if !defined(USE_TM_CLONE_REGISTRY) && defined(OBJECT_FORMAT_ELF) --# define USE_TM_CLONE_REGISTRY 1 -+# define USE_TM_CLONE_REGISTRY 0 - #endif - - /* We do not want to add the weak attribute to the declarations of these diff --git a/toolchain/gcc/patches/arc-2017.03-release/900-bad-mips16-crt.patch b/toolchain/gcc/patches/arc-2017.03-release/900-bad-mips16-crt.patch deleted file mode 100644 index dd6e9dc88..000000000 --- a/toolchain/gcc/patches/arc-2017.03-release/900-bad-mips16-crt.patch +++ /dev/null @@ -1,9 +0,0 @@ ---- a/libgcc/config/mips/t-mips16 -+++ b/libgcc/config/mips/t-mips16 -@@ -43,3 +43,6 @@ SYNC_CFLAGS = -mno-mips16 - - # Version these symbols if building libgcc.so. - SHLIB_MAPFILES += $(srcdir)/config/mips/libgcc-mips16.ver -+ -+CRTSTUFF_T_CFLAGS += -mno-mips16 -+CRTSTUFF_T_CFLAGS_S += -mno-mips16 diff --git a/toolchain/gcc/patches/arc-2017.03-release/940-no-clobber-stamp-bits.patch b/toolchain/gcc/patches/arc-2017.03-release/940-no-clobber-stamp-bits.patch deleted file mode 100644 index 68e62865b..000000000 --- a/toolchain/gcc/patches/arc-2017.03-release/940-no-clobber-stamp-bits.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/libstdc++-v3/include/Makefile.in -+++ b/libstdc++-v3/include/Makefile.in -@@ -1459,7 +1459,7 @@ stamp-bits: ${bits_headers} - @$(STAMP) stamp-bits - - stamp-bits-sup: stamp-bits ${bits_sup_headers} -- @-cd ${bits_builddir} && $(LN_S) $? . 2>/dev/null -+ @-cd ${bits_builddir} && $(LN_S) $(filter-out stamp-bits,$?) . 2>/dev/null - @$(STAMP) stamp-bits-sup - - stamp-c_base: ${c_base_headers} diff --git a/toolchain/gcc/patches/arc-2017.03-release/001-revert_register_mode_search.patch b/toolchain/gcc/patches/arc-2017.09-release/001-revert_register_mode_search.patch similarity index 84% rename from toolchain/gcc/patches/arc-2017.03-release/001-revert_register_mode_search.patch rename to toolchain/gcc/patches/arc-2017.09-release/001-revert_register_mode_search.patch index bd6fbdb4a..63e3fee00 100644 --- a/toolchain/gcc/patches/arc-2017.03-release/001-revert_register_mode_search.patch +++ b/toolchain/gcc/patches/arc-2017.09-release/001-revert_register_mode_search.patch @@ -1,3 +1,15 @@ +commit 31285a20390a5e53a74a2a71d1b5c82f366ddd5a +Author: Felix Fietkau +Date: Tue May 6 11:49:05 2014 +0000 + + gcc: revert an upstream patch that is causing a regression on powerpc + + https://forum.openwrt.org/viewtopic.php?pid=232494#p232494 + + Signed-off-by: Felix Fietkau + + SVN-Revision: 40709 + Revert of: commit 275035b56823b26d5fb7e90fad945b998648edf2 @@ -14,7 +26,7 @@ Date: Thu Sep 5 14:09:07 2013 +0000 --- a/gcc/reginfo.c +++ b/gcc/reginfo.c -@@ -625,35 +625,40 @@ choose_hard_reg_mode (unsigned int regno +@@ -637,35 +637,40 @@ choose_hard_reg_mode (unsigned int regno mode = GET_MODE_WIDER_MODE (mode)) if ((unsigned) hard_regno_nregs[regno][mode] == nregs && HARD_REGNO_MODE_OK (regno, mode) diff --git a/toolchain/gcc/patches/arc-2017.03-release/002-case_insensitive.patch b/toolchain/gcc/patches/arc-2017.09-release/002-case_insensitive.patch similarity index 64% rename from toolchain/gcc/patches/arc-2017.03-release/002-case_insensitive.patch rename to toolchain/gcc/patches/arc-2017.09-release/002-case_insensitive.patch index b3d2dbe29..3442076d7 100644 --- a/toolchain/gcc/patches/arc-2017.03-release/002-case_insensitive.patch +++ b/toolchain/gcc/patches/arc-2017.09-release/002-case_insensitive.patch @@ -1,3 +1,13 @@ +commit 81cc26c706b2bc8c8c1eb1a322e5c5157900836e +Author: Felix Fietkau +Date: Sun Oct 19 21:45:51 2014 +0000 + + gcc: do not assume that the Mac OS X filesystem is case insensitive + + Signed-off-by: Felix Fietkau + + SVN-Revision: 42973 + --- a/include/filenames.h +++ b/include/filenames.h @@ -43,11 +43,6 @@ extern "C" { diff --git a/toolchain/gcc/patches/arc-2017.03-release/010-documentation.patch b/toolchain/gcc/patches/arc-2017.09-release/010-documentation.patch similarity index 65% rename from toolchain/gcc/patches/arc-2017.03-release/010-documentation.patch rename to toolchain/gcc/patches/arc-2017.09-release/010-documentation.patch index 2adb28c83..0106814f4 100644 --- a/toolchain/gcc/patches/arc-2017.03-release/010-documentation.patch +++ b/toolchain/gcc/patches/arc-2017.09-release/010-documentation.patch @@ -1,6 +1,18 @@ +commit 098bd91f5eae625c7d2ee621e10930fc4434e5e2 +Author: Luka Perkov +Date: Tue Feb 26 16:16:33 2013 +0000 + + gcc: don't build documentation + + This closes #13039. + + Signed-off-by: Luka Perkov + + SVN-Revision: 35807 + --- a/gcc/Makefile.in +++ b/gcc/Makefile.in -@@ -3021,18 +3021,10 @@ doc/gcc.info: $(TEXI_GCC_FILES) +@@ -3121,18 +3121,10 @@ doc/gcc.info: $(TEXI_GCC_FILES) doc/gccint.info: $(TEXI_GCCINT_FILES) doc/cppinternals.info: $(TEXI_CPPINT_FILES) diff --git a/toolchain/gcc/patches/arc-2017.09-release/230-musl_libssp.patch b/toolchain/gcc/patches/arc-2017.09-release/230-musl_libssp.patch new file mode 100644 index 000000000..eebee9175 --- /dev/null +++ b/toolchain/gcc/patches/arc-2017.09-release/230-musl_libssp.patch @@ -0,0 +1,28 @@ +commit 1877bc9d8f2be143fbe530347a945850d0ecd234 +Author: Steven Barth +Date: Mon Jun 22 10:31:07 2015 +0000 + + gcc/musl: rework SSP-support + + Make musl provide libssp_nonshared.a and make GCC link it unconditionally + if musl is used. This should be a no-op if SSP is disabled and seems to be + the only reliable way of dealing with SSP over all packages due to the mess + that is linkerflags handling in packages. + + Signed-off-by: Steven Barth + + SVN-Revision: 46108 + +--- a/gcc/gcc.c ++++ b/gcc/gcc.c +@@ -861,7 +861,9 @@ proper position among the other output f + #endif + + #ifndef LINK_SSP_SPEC +-#ifdef TARGET_LIBC_PROVIDES_SSP ++#if DEFAULT_LIBC == LIBC_MUSL ++#define LINK_SSP_SPEC "-lssp_nonshared" ++#elif defined(TARGET_LIBC_PROVIDES_SSP) + #define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \ + "|fstack-protector-strong|fstack-protector-explicit:}" + #else diff --git a/toolchain/gcc/patches/arc-2017.09-release/300-mips_Os_cpu_rtx_cost_model.patch b/toolchain/gcc/patches/arc-2017.09-release/300-mips_Os_cpu_rtx_cost_model.patch new file mode 100644 index 000000000..84c0fdab6 --- /dev/null +++ b/toolchain/gcc/patches/arc-2017.09-release/300-mips_Os_cpu_rtx_cost_model.patch @@ -0,0 +1,21 @@ +commit ecf7671b769fe96f7b5134be442089f8bdba55d2 +Author: Felix Fietkau +Date: Thu Aug 4 20:29:45 2016 +0200 + +gcc: add a patch to generate better code with Os on mips + +Also happens to reduce compressed code size a bit + +Signed-off-by: Felix Fietkau + +--- a/gcc/config/mips/mips.c ++++ b/gcc/config/mips/mips.c +@@ -19784,7 +19784,7 @@ mips_option_override (void) + flag_pcc_struct_return = 0; + + /* Decide which rtx_costs structure to use. */ +- if (optimize_size) ++ if (0 && optimize_size) + mips_cost = &mips_rtx_cost_optimize_size; + else + mips_cost = &mips_rtx_cost_data[mips_tune]; diff --git a/toolchain/gcc/patches/arc-2017.09-release/800-arm_v5te_no_ldrd_strd.patch b/toolchain/gcc/patches/arc-2017.09-release/800-arm_v5te_no_ldrd_strd.patch new file mode 100644 index 000000000..76200a166 --- /dev/null +++ b/toolchain/gcc/patches/arc-2017.09-release/800-arm_v5te_no_ldrd_strd.patch @@ -0,0 +1,32 @@ +commit b050f87d13b5dc7ed82feb9a90f4529de58bdf25 +Author: Felix Fietkau +Date: Wed Feb 19 19:20:10 2014 +0000 + + gcc: prevent the use of LDRD/STRD on ARMv5TE + + These instructions are for 64-bit load/store. On ARMv5TE, the CPU + requires addresses to be aligned to 64-bit. When misaligned, behavior is + undefined (effectively either loads the same word twice on LDRD, or + corrupts surrounding memory on STRD). + + On ARMv6 and newer, unaligned access is safe. + + Removing these instructions for ARMv5TE is necessary, because GCC + ignores alignment information in pointers and does unsafe optimizations + that have shown up as bugs in various places. + + Signed-off-by: Felix Fietkau + + SVN-Revision: 39638 + +--- a/gcc/config/arm/arm.h ++++ b/gcc/config/arm/arm.h +@@ -150,7 +150,7 @@ extern tree arm_fp16_type_node; + /* Thumb-1 only. */ + #define TARGET_THUMB1_ONLY (TARGET_THUMB1 && !arm_arch_notm) + +-#define TARGET_LDRD (arm_arch5e && ARM_DOUBLEWORD_ALIGN \ ++#define TARGET_LDRD (arm_arch6 && ARM_DOUBLEWORD_ALIGN \ + && !TARGET_THUMB1) + + #define TARGET_CRC32 (arm_arch_crc) diff --git a/toolchain/gcc/patches/arc-2017.03-release/810-arm-softfloat-libgcc.patch b/toolchain/gcc/patches/arc-2017.09-release/810-arm-softfloat-libgcc.patch similarity index 80% rename from toolchain/gcc/patches/arc-2017.03-release/810-arm-softfloat-libgcc.patch rename to toolchain/gcc/patches/arc-2017.09-release/810-arm-softfloat-libgcc.patch index 1d06f5b2e..5c9d86aea 100644 --- a/toolchain/gcc/patches/arc-2017.03-release/810-arm-softfloat-libgcc.patch +++ b/toolchain/gcc/patches/arc-2017.09-release/810-arm-softfloat-libgcc.patch @@ -1,3 +1,11 @@ +commit 8570c4be394cff7282f332f97da2ff569a927ddb +Author: Imre Kaloz +Date: Wed Feb 2 20:06:12 2011 +0000 + + fixup arm soft-float symbols + + SVN-Revision: 25325 + --- a/libgcc/config/arm/t-linux +++ b/libgcc/config/arm/t-linux @@ -1,6 +1,10 @@ @@ -14,7 +22,7 @@ # difference. --- a/gcc/config/arm/linux-elf.h +++ b/gcc/config/arm/linux-elf.h -@@ -60,8 +60,6 @@ +@@ -58,8 +58,6 @@ %{shared:-lc} \ %{!shared:%{profile:-lc_p}%{!profile:-lc}}" diff --git a/toolchain/gcc/patches/arc-2017.03-release/820-libgcc_pic.patch b/toolchain/gcc/patches/arc-2017.09-release/820-libgcc_pic.patch similarity index 71% rename from toolchain/gcc/patches/arc-2017.03-release/820-libgcc_pic.patch rename to toolchain/gcc/patches/arc-2017.09-release/820-libgcc_pic.patch index f925d96f6..0cc1e07e2 100644 --- a/toolchain/gcc/patches/arc-2017.03-release/820-libgcc_pic.patch +++ b/toolchain/gcc/patches/arc-2017.09-release/820-libgcc_pic.patch @@ -1,6 +1,14 @@ +commit c96312958c0621e72c9b32da5bc224ffe2161384 +Author: Felix Fietkau +Date: Mon Oct 19 23:26:09 2009 +0000 + + gcc: create a proper libgcc_pic.a static library for relinking (4.3.3+ for now, backport will follow) + + SVN-Revision: 18086 + --- a/libgcc/Makefile.in +++ b/libgcc/Makefile.in -@@ -888,11 +888,12 @@ $(libgcov-driver-objects): %$(objext): $ +@@ -920,11 +920,12 @@ $(libgcov-driver-objects): %$(objext): $ # Static libraries. libgcc.a: $(libgcc-objects) @@ -14,7 +22,7 @@ -rm -f $@ objects="$(objects)"; \ -@@ -913,7 +914,7 @@ all: libunwind.a +@@ -945,7 +946,7 @@ all: libunwind.a endif ifeq ($(enable_shared),yes) @@ -23,7 +31,7 @@ ifneq ($(LIBUNWIND),) all: libunwind$(SHLIB_EXT) libgcc_s$(SHLIB_EXT): libunwind$(SHLIB_EXT) -@@ -1115,6 +1116,10 @@ install-shared: +@@ -1151,6 +1152,10 @@ install-shared: chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_eh.a $(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_eh.a diff --git a/toolchain/gcc/patches/arc-2017.03-release/840-armv4_pass_fix-v4bx_to_ld.patch b/toolchain/gcc/patches/arc-2017.09-release/840-armv4_pass_fix-v4bx_to_ld.patch similarity index 78% rename from toolchain/gcc/patches/arc-2017.03-release/840-armv4_pass_fix-v4bx_to_ld.patch rename to toolchain/gcc/patches/arc-2017.09-release/840-armv4_pass_fix-v4bx_to_ld.patch index cb1fb9823..b9c9b161a 100644 --- a/toolchain/gcc/patches/arc-2017.03-release/840-armv4_pass_fix-v4bx_to_ld.patch +++ b/toolchain/gcc/patches/arc-2017.09-release/840-armv4_pass_fix-v4bx_to_ld.patch @@ -1,6 +1,15 @@ +commit 7edc8ca5456d9743dd0075eb3cc5b04f4f24c8cc +Author: Imre Kaloz +Date: Wed Feb 2 19:34:36 2011 +0000 + + add armv4 fixup patches + + SVN-Revision: 25322 + + --- a/gcc/config/arm/linux-eabi.h +++ b/gcc/config/arm/linux-eabi.h -@@ -94,10 +94,15 @@ +@@ -88,10 +88,15 @@ #define MUSL_DYNAMIC_LINKER \ "/lib/ld-musl-arm" MUSL_DYNAMIC_LINKER_E "%{mfloat-abi=hard:hf}.so.1" diff --git a/toolchain/gcc/patches/arc-2017.03-release/850-use_shared_libgcc.patch b/toolchain/gcc/patches/arc-2017.09-release/850-use_shared_libgcc.patch similarity index 81% rename from toolchain/gcc/patches/arc-2017.03-release/850-use_shared_libgcc.patch rename to toolchain/gcc/patches/arc-2017.09-release/850-use_shared_libgcc.patch index cd20244c6..1d07efed8 100644 --- a/toolchain/gcc/patches/arc-2017.03-release/850-use_shared_libgcc.patch +++ b/toolchain/gcc/patches/arc-2017.09-release/850-use_shared_libgcc.patch @@ -1,6 +1,13 @@ +commit dcfc40358b5a3cae7320c17f8d1cebd5ad5540cd +Author: Felix Fietkau +Date: Sun Feb 12 20:25:47 2012 +0000 + + gcc 4.6: port over the missing patch 850-use_shared_libgcc.patch to prevent libgcc crap from leaking into every single binary + + SVN-Revision: 30486 --- a/gcc/config/arm/linux-eabi.h +++ b/gcc/config/arm/linux-eabi.h -@@ -132,10 +132,6 @@ +@@ -126,10 +126,6 @@ "%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s} " \ LINUX_OR_ANDROID_LD (GNU_USER_TARGET_ENDFILE_SPEC, ANDROID_ENDFILE_SPEC) @@ -26,7 +33,7 @@ -muclibc or -mglibc or -mbionic or -mmusl has been passed to change --- a/libgcc/mkmap-symver.awk +++ b/libgcc/mkmap-symver.awk -@@ -132,5 +132,5 @@ function output(lib) { +@@ -136,5 +136,5 @@ function output(lib) { else if (inherit[lib]) printf("} %s;\n", inherit[lib]); else diff --git a/toolchain/gcc/patches/arc-2017.03-release/851-libgcc_no_compat.patch b/toolchain/gcc/patches/arc-2017.09-release/851-libgcc_no_compat.patch similarity index 63% rename from toolchain/gcc/patches/arc-2017.03-release/851-libgcc_no_compat.patch rename to toolchain/gcc/patches/arc-2017.09-release/851-libgcc_no_compat.patch index 80c347684..d710e4071 100644 --- a/toolchain/gcc/patches/arc-2017.03-release/851-libgcc_no_compat.patch +++ b/toolchain/gcc/patches/arc-2017.09-release/851-libgcc_no_compat.patch @@ -1,3 +1,13 @@ +commit 64661de100da1ec1061ef3e5e400285dce115e6b +Author: Felix Fietkau +Date: Sun May 10 13:16:35 2015 +0000 + + gcc: add some size optimization patches + + Signed-off-by: Felix Fietkau + + SVN-Revision: 45664 + --- a/libgcc/config/t-libunwind +++ b/libgcc/config/t-libunwind @@ -2,8 +2,7 @@ diff --git a/toolchain/gcc/patches/arc-2017.09-release/870-ppc_no_crtsavres.patch b/toolchain/gcc/patches/arc-2017.09-release/870-ppc_no_crtsavres.patch new file mode 100644 index 000000000..156468b45 --- /dev/null +++ b/toolchain/gcc/patches/arc-2017.09-release/870-ppc_no_crtsavres.patch @@ -0,0 +1,18 @@ +commit d8c570a1531035c3e26bcd94741e5f5b9c36b5d9 +Author: Felix Fietkau +Date: Mon Mar 5 00:51:01 2012 +0000 + + gcc: do not emit references to _savegpr_* and _restgpr_* on powerpc, as they are tricky to deal with wrt. libgcc. they cannot be linked dynamically + + SVN-Revision: 30814 +--- a/gcc/config/rs6000/rs6000.c ++++ b/gcc/config/rs6000/rs6000.c +@@ -26936,7 +26936,7 @@ rs6000_savres_strategy (rs6000_stack_t * + /* Define cutoff for using out-of-line functions to save registers. */ + if (DEFAULT_ABI == ABI_V4 || TARGET_ELF) + { +- if (!optimize_size) ++ if (1) + { + strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS; + strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS; diff --git a/toolchain/gcc/patches/arc-2017.09-release/881-no_tm_section.patch b/toolchain/gcc/patches/arc-2017.09-release/881-no_tm_section.patch new file mode 100644 index 000000000..a58dc27e6 --- /dev/null +++ b/toolchain/gcc/patches/arc-2017.09-release/881-no_tm_section.patch @@ -0,0 +1,22 @@ +commit 565988ab47bd9b96b50608564aee2104aeb4b7ae +Author: Felix Fietkau +Date: Tue Dec 13 14:20:49 2016 +0100 + + gcc: rip out transactional memory related bloat from crtbegin + + Slightly improves compression for each executable, saving about 4k from + the default ar71xx rootfs + + Signed-off-by: Felix Fietkau + +--- a/libgcc/crtstuff.c ++++ b/libgcc/crtstuff.c +@@ -152,7 +152,7 @@ call_ ## FUNC (void) \ + #endif + + #if !defined(USE_TM_CLONE_REGISTRY) && defined(OBJECT_FORMAT_ELF) +-# define USE_TM_CLONE_REGISTRY 1 ++# define USE_TM_CLONE_REGISTRY 0 + #endif + + /* We do not want to add the weak attribute to the declarations of these diff --git a/toolchain/gcc/patches/arc-2017.09-release/900-bad-mips16-crt.patch b/toolchain/gcc/patches/arc-2017.09-release/900-bad-mips16-crt.patch new file mode 100644 index 000000000..f5cc0a74e --- /dev/null +++ b/toolchain/gcc/patches/arc-2017.09-release/900-bad-mips16-crt.patch @@ -0,0 +1,30 @@ +commit 9dc38e48f7a6f88b7ac7bfaced91f53660204e46 +Author: Florian Fainelli +Date: Fri Apr 5 12:36:06 2013 +0000 + + toolchain/gcc: .init and .fini need to pick one ISA + + The .init and .fini sections are built by concatenating code + fragments. Putting mips16 code in the middle of a mips32 code block + doesn't work. Make gcc built the magic crt stuff in no-mips16 mode. + + This is specific to 4.6-linaro but is probably portable to other gcc + flavors. Adding this to the t-libgcc-mips16 makefile fragment is a + hack not suitable for pushing upstream, but there is no mips/t-linux + or mips/t-uclibc and I am not going to touch gcc/configure for two + lines. + + Signed-off-by: Jay Carlson + Signed-off-by: Florian Fainelli + + SVN-Revision: 36200 + +--- a/libgcc/config/mips/t-mips16 ++++ b/libgcc/config/mips/t-mips16 +@@ -43,3 +43,6 @@ SYNC_CFLAGS = -mno-mips16 + + # Version these symbols if building libgcc.so. + SHLIB_MAPFILES += $(srcdir)/config/mips/libgcc-mips16.ver ++ ++CRTSTUFF_T_CFLAGS += -mno-mips16 ++CRTSTUFF_T_CFLAGS_S += -mno-mips16 diff --git a/toolchain/gcc/patches/arc-2017.03-release/910-mbsd_multi.patch b/toolchain/gcc/patches/arc-2017.09-release/910-mbsd_multi.patch similarity index 50% rename from toolchain/gcc/patches/arc-2017.03-release/910-mbsd_multi.patch rename to toolchain/gcc/patches/arc-2017.09-release/910-mbsd_multi.patch index 62203dfcf..286cfadae 100644 --- a/toolchain/gcc/patches/arc-2017.03-release/910-mbsd_multi.patch +++ b/toolchain/gcc/patches/arc-2017.09-release/910-mbsd_multi.patch @@ -1,22 +1,23 @@ +commit 99368862e44740ff4fd33760893f04e14f9dbdf1 +Author: Felix Fietkau +Date: Tue Jul 31 00:52:27 2007 +0000 - This patch brings over a few features from MirBSD: + Port the mbsd_multi patch from freewrt, which adds -fhonour-copts. This will emit warnings in packages that don't use our target cflags properly + + SVN-Revision: 8256 + + This patch brings over a feature from MirBSD: * -fhonour-copts If this option is not given, it's warned (depending on environment variables). This is to catch errors of misbuilt packages which override CFLAGS themselves. - * -Werror-maybe-reset - Has the effect of -Wno-error if GCC_NO_WERROR is - set and not '0', a no-operation otherwise. This is - to be able to use -Werror in "make" but prevent - GNU autoconf generated configure scripts from - freaking out. This patch was authored by Thorsten Glaser with copyright assignment to the FSF in effect. --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c -@@ -107,6 +107,9 @@ static int class_dump_flags; +@@ -108,6 +108,9 @@ static int class_dump_flags; /* Whether any standard preincluded header has been preincluded. */ static bool done_preinclude; @@ -26,7 +27,7 @@ static void handle_OPT_d (const char *); static void set_std_cxx98 (int); static void set_std_cxx11 (int); -@@ -442,6 +445,12 @@ c_common_handle_option (size_t scode, co +@@ -456,6 +459,12 @@ c_common_handle_option (size_t scode, co flag_no_builtin = !value; break; @@ -39,7 +40,7 @@ case OPT_fconstant_string_class_: constant_string_class_name = arg; break; -@@ -1041,6 +1050,47 @@ c_common_init (void) +@@ -1084,6 +1093,47 @@ c_common_init (void) return false; } @@ -89,18 +90,7 @@ --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt -@@ -438,6 +438,10 @@ Wfloat-conversion - C ObjC C++ ObjC++ Var(warn_float_conversion) Warning LangEnabledBy(C ObjC C++ ObjC++,Wconversion) - Warn for implicit type conversions that cause loss of floating point precision. - -+Werror-maybe-reset -+C ObjC C++ ObjC++ -+; Documented in common.opt -+ - Wfloat-equal - C ObjC C++ ObjC++ Var(warn_float_equal) Warning - Warn if testing floating point numbers for equality. -@@ -1252,6 +1256,9 @@ C++ ObjC++ Optimization Alias(fexception +@@ -1412,6 +1412,9 @@ C++ ObjC++ Optimization Alias(fexception fhonor-std C++ ObjC++ Ignore Warn(switch %qs is no longer supported) @@ -112,18 +102,7 @@ Assume normal C execution environment. --- a/gcc/common.opt +++ b/gcc/common.opt -@@ -581,6 +581,10 @@ Werror= - Common Joined - Treat specified warning as error. - -+Werror-maybe-reset -+Common -+If environment variable GCC_NO_WERROR is set, act as -Wno-error -+ - Wextra - Common Var(extra_warnings) Warning - Print extra (possibly unwanted) warnings. -@@ -1432,6 +1436,9 @@ fguess-branch-probability +@@ -1510,6 +1510,9 @@ fguess-branch-probability Common Report Var(flag_guess_branch_prob) Optimization Enable guessing of branch probabilities. @@ -135,60 +114,24 @@ ; On SVR4 targets, it also controls whether or not to emit a --- a/gcc/opts.c +++ b/gcc/opts.c -@@ -1783,6 +1783,17 @@ common_handle_option (struct gcc_options +@@ -1928,6 +1928,9 @@ common_handle_option (struct gcc_options opts, opts_set, loc, dc); break; -+ case OPT_Werror_maybe_reset: -+ { -+ char *ev = getenv ("GCC_NO_WERROR"); -+ if ((ev != NULL) && (*ev != '0')) -+ warnings_are_errors = 0; -+ } -+ break; -+ + case OPT_fhonour_copts: + break; + case OPT_Wlarger_than_: opts->x_larger_than_size = value; opts->x_warn_larger_than = value != -1; ---- a/gcc/doc/cppopts.texi -+++ b/gcc/doc/cppopts.texi -@@ -163,6 +163,11 @@ in older programs. This warning is on b - Make all warnings into hard errors. Source code which triggers warnings - will be rejected. - -+ at item -Werror-maybe-reset -+ at opindex Werror-maybe-reset -+Act like @samp{-Wno-error} if the @env{GCC_NO_WERROR} environment -+variable is set to anything other than 0 or empty. -+ - @item -Wsystem-headers - @opindex Wsystem-headers - Issue warnings for code in system headers. These are normally unhelpful --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi -@@ -263,7 +263,7 @@ Objective-C and Objective-C++ Dialects}. - -Wno-discarded-qualifiers -Wno-discarded-array-qualifiers @gol - -Wno-div-by-zero -Wdouble-promotion -Wduplicated-cond @gol - -Wempty-body -Wenum-compare -Wno-endif-labels @gol ---Werror -Werror=* -Wfatal-errors -Wfloat-equal -Wformat -Wformat=2 @gol -+-Werror -Werror=* -Werror-maybe-reset -Wfatal-errors -Wfloat-equal -Wformat -Wformat=2 @gol - -Wno-format-contains-nul -Wno-format-extra-args -Wformat-nonliteral @gol - -Wformat-security -Wformat-signedness -Wformat-y2k -Wframe-address @gol - -Wframe-larger-than=@var{len} -Wno-free-nonheap-object -Wjump-misses-init @gol -@@ -5737,6 +5737,22 @@ This option is only supported for C and +@@ -6567,6 +6567,17 @@ This option is only supported for C and @option{-Wall} and by @option{-Wpedantic}, which can be disabled with @option{-Wno-pointer-sign}. -+ at item -Werror-maybe-reset -+ at opindex Werror-maybe-reset -+Act like @samp{-Wno-error} if the @env{GCC_NO_WERROR} environment -+variable is set to anything other than 0 or empty. -+ -+ at item -fhonour-copts -+ at opindex fhonour-copts ++@item -fhonour-copts ++@opindex fhonour-copts +If @env{GCC_HONOUR_COPTS} is set to 1, abort if this option is not +given at least once, and warn if it is given more than once. +If @env{GCC_HONOUR_COPTS} is set to 2, abort if this option is not @@ -201,22 +144,3 @@ @item -Wstack-protector @opindex Wstack-protector @opindex Wno-stack-protector -@@ -6605,7 +6621,7 @@ so, the first branch is redirected to ei - second branch or a point immediately following it, depending on whether - the condition is known to be true or false. - --Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}. -+Enabled at levels @option{-O3}. - - @item -fsplit-wide-types - @opindex fsplit-wide-types ---- a/gcc/java/jvspec.c -+++ b/gcc/java/jvspec.c -@@ -629,6 +629,7 @@ lang_specific_pre_link (void) - class name. Append dummy `.c' that can be stripped by set_input so %b - is correct. */ - set_input (concat (main_class_name, "main.c", NULL)); -+ putenv ("GCC_HONOUR_COPTS=s"); /* XXX hack! */ - err = do_spec (jvgenmain_spec); - if (err == 0) - { diff --git a/toolchain/gcc/patches/arc-2017.03-release/920-specs_nonfatal_getenv.patch b/toolchain/gcc/patches/arc-2017.09-release/920-specs_nonfatal_getenv.patch similarity index 59% rename from toolchain/gcc/patches/arc-2017.03-release/920-specs_nonfatal_getenv.patch rename to toolchain/gcc/patches/arc-2017.09-release/920-specs_nonfatal_getenv.patch index dc0acb95a..69b40621d 100644 --- a/toolchain/gcc/patches/arc-2017.03-release/920-specs_nonfatal_getenv.patch +++ b/toolchain/gcc/patches/arc-2017.09-release/920-specs_nonfatal_getenv.patch @@ -1,6 +1,13 @@ +Author: Jo-Philipp Wich +Date: Sat Apr 21 03:02:39 2012 +0000 + + gcc: add patch to make the getenv() spec function nonfatal if requested environment variable is unset + + SVN-Revision: 31390 + --- a/gcc/gcc.c +++ b/gcc/gcc.c -@@ -9198,8 +9198,10 @@ getenv_spec_function (int argc, const ch +@@ -9280,8 +9280,10 @@ getenv_spec_function (int argc, const ch value = varname; if (!value) diff --git a/toolchain/gcc/patches/arc-2017.03-release/930-fix-mips-noexecstack.patch b/toolchain/gcc/patches/arc-2017.09-release/930-fix-mips-noexecstack.patch similarity index 95% rename from toolchain/gcc/patches/arc-2017.03-release/930-fix-mips-noexecstack.patch rename to toolchain/gcc/patches/arc-2017.09-release/930-fix-mips-noexecstack.patch index 2a99840b6..90d10f11e 100644 --- a/toolchain/gcc/patches/arc-2017.03-release/930-fix-mips-noexecstack.patch +++ b/toolchain/gcc/patches/arc-2017.09-release/930-fix-mips-noexecstack.patch @@ -48,9 +48,9 @@ sellcey@mips.com --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c -@@ -20228,6 +20228,9 @@ mips_promote_function_mode (const_tree t - #undef TARGET_HARD_REGNO_SCRATCH_OK - #define TARGET_HARD_REGNO_SCRATCH_OK mips_hard_regno_scratch_ok +@@ -22561,6 +22561,9 @@ mips_promote_function_mode (const_tree t + #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS + #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 2 +#undef TARGET_ASM_FILE_END +#define TARGET_ASM_FILE_END file_end_indicate_exec_stack diff --git a/toolchain/gcc/patches/arc-2017.09-release/940-no-clobber-stamp-bits.patch b/toolchain/gcc/patches/arc-2017.09-release/940-no-clobber-stamp-bits.patch new file mode 100644 index 000000000..8b88b4066 --- /dev/null +++ b/toolchain/gcc/patches/arc-2017.09-release/940-no-clobber-stamp-bits.patch @@ -0,0 +1,33 @@ +commit 548d9a008ff265e9eaa3c7e0e6e301c6bd5645e6 +Author: Felix Fietkau +Date: Fri Dec 12 17:01:57 2014 +0000 + + gcc: don't clobber stamp-bits with a symlink to itself + + Several versions of gcc have an issue in libstdc++v3 where the build may + clobber stamp-bits with a link to itself. This doesn't manifest itself + on all systems. On several Ubuntu systems, this doesn't appear to be a + problem, but it is an issue on Fedora 16 systems. + + To fix the issue, we'll simply filter out stamp-bits from the symlinks + to be generated. + + Note: gcc 4.4.7 is unaffected by this issue, so no fix is necessary + there. + + Signed-off-by: John Szakmeister + + SVN-Revision: 43669 + + +--- a/libstdc++-v3/include/Makefile.in ++++ b/libstdc++-v3/include/Makefile.in +@@ -1476,7 +1476,7 @@ stamp-bits: ${bits_headers} + @$(STAMP) stamp-bits + + stamp-bits-sup: stamp-bits ${bits_sup_headers} +- @-cd ${bits_builddir} && $(LN_S) $? . 2>/dev/null ++ @-cd ${bits_builddir} && $(LN_S) $(filter-out stamp-bits,$?) . 2>/dev/null + @$(STAMP) stamp-bits-sup + + stamp-c_base: ${c_base_headers} diff --git a/toolchain/gcc/patches/arc-2017.03-release/950-cpp_file_path_translation.patch b/toolchain/gcc/patches/arc-2017.09-release/950-cpp_file_path_translation.patch similarity index 80% rename from toolchain/gcc/patches/arc-2017.03-release/950-cpp_file_path_translation.patch rename to toolchain/gcc/patches/arc-2017.09-release/950-cpp_file_path_translation.patch index d467eb7c9..60729dd7f 100644 --- a/toolchain/gcc/patches/arc-2017.03-release/950-cpp_file_path_translation.patch +++ b/toolchain/gcc/patches/arc-2017.09-release/950-cpp_file_path_translation.patch @@ -1,8 +1,18 @@ +commit 331735a357a73c7b8adc205241ac3cc6543d985e +Author: Felix Fietkau +Date: Tue Nov 17 12:38:22 2015 +0000 + + gcc: add a patch to 5.x that supports translation of __FILE__ paths + + Signed-off-by: Felix Fietkau + + SVN-Revision: 47490 + Forward ported from attachment to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47047 --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c -@@ -574,6 +574,10 @@ c_common_handle_option (size_t scode, co +@@ -588,6 +588,10 @@ c_common_handle_option (size_t scode, co add_path (xstrdup (arg), SYSTEM, 0, true); break; @@ -15,7 +25,7 @@ Forward ported from attachment to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=4 break; --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt -@@ -1632,6 +1632,10 @@ iquote +@@ -1825,6 +1825,10 @@ iquote C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs) -iquote Add to the end of the quote include path. @@ -28,19 +38,19 @@ Forward ported from attachment to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=4 -iwithprefix Add to the end of the system include path. --- a/gcc/doc/cpp.texi +++ b/gcc/doc/cpp.texi -@@ -4444,6 +4444,7 @@ without notice. +@@ -4272,6 +4272,7 @@ Refer to the GCC manual for full documen @c man begin SYNOPSIS cpp [@option{-D}@var{macro}[=@var{defn}]@dots{}] [@option{-U}@var{macro}] [@option{-I}@var{dir}@dots{}] [@option{-iquote}@var{dir}@dots{}] + [@option{-iremap}@var{src}:@var{dst}] - [@option{-W}@var{warn}@dots{}] [@option{-M}|@option{-MM}] [@option{-MG}] [@option{-MF} @var{filename}] [@option{-MP}] [@option{-MQ} @var{target}@dots{}] + [@option{-MT} @var{target}@dots{}] --- a/gcc/doc/cppopts.texi +++ b/gcc/doc/cppopts.texi -@@ -532,6 +532,12 @@ Search @var{dir} only for header files r - If @var{dir} begins with @code{=}, then the @code{=} will be replaced - by the sysroot prefix; see @option{--sysroot} and @option{-isysroot}. +@@ -220,6 +220,12 @@ extensions @samp{.i}, @samp{.ii} or @sam + extensions that GCC uses for preprocessed files created by + @option{-save-temps}. +@item -iremap @var{src}:@var{dst} +@opindex iremap @@ -53,20 +63,9 @@ Forward ported from attachment to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=4 When preprocessing, handle directives, but do not expand macros. --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi -@@ -476,8 +476,8 @@ Objective-C and Objective-C++ Dialects}. - @item Directory Options - @xref{Directory Options,,Options for Directory Search}. - @gccoptlist{-B@var{prefix} -I@var{dir} -iplugindir=@var{dir} @gol ---iquote@var{dir} -L@var{dir} -no-canonical-prefixes -I- @gol ----sysroot=@var{dir} --no-sysroot-suffix} -+-iquote@var{dir} -iremap@var{src}:@var{dst} -L@var{dir} -no-canonical-prefixes @gol -+-I- --sysroot=@var{dir} --no-sysroot-suffix} - - @item Code Generation Options - @xref{Code Gen Options,,Options for Code Generation Conventions}. -@@ -10861,6 +10861,12 @@ be searched for header files only for th - "@var{file}"}; they are not searched for @code{#include <@var{file}>}, - otherwise just like @option{-I}. +@@ -11863,6 +11863,12 @@ by @option{-fplugin=@var{name}} instead + @option{-fplugin=@var{path}/@var{name}.so}. This option is not meant + to be used by the user, but only passed by the driver. +@item -iremap @var{src}:@var{dst} +@opindex iremap @@ -79,7 +78,7 @@ Forward ported from attachment to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=4 Add directory @var{dir} to the list of directories to be searched --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h -@@ -760,6 +760,9 @@ extern void cpp_set_lang (cpp_reader *, +@@ -820,6 +820,9 @@ extern void cpp_set_lang (cpp_reader *, /* Set the include paths. */ extern void cpp_set_include_chains (cpp_reader *, cpp_dir *, cpp_dir *, int); diff --git a/toolchain/gdb/Makefile b/toolchain/gdb/Makefile index abd6d033c..5c80eef9a 100644 --- a/toolchain/gdb/Makefile +++ b/toolchain/gdb/Makefile @@ -9,11 +9,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gdb ifeq ($(CONFIG_arc),y) -PKG_VERSION:=arc-2017.03-gdb +PKG_VERSION:=arc-2017.09-gdb PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://github.com/foss-for-synopsys-dwc-arc-processors/binutils-gdb/archive/arc-2017.03-gdb -PKG_HASH:=f47930161e9e99c46ab018dabbf56024739dda29c51f92495eaa0d4d7e3511f6 +PKG_SOURCE_URL:=https://github.com/foss-for-synopsys-dwc-arc-processors/binutils-gdb/archive/arc-2017.09-gdb +PKG_HASH:=7e3c2a763bf500a40c5c4591a7e22c591dafc1f214b1d514895c1096e85c883a GDB_DIR:=binutils-$(PKG_NAME)-$(PKG_VERSION) PATCH_DIR:=./patches-arc else diff --git a/toolchain/kernel-headers/Makefile b/toolchain/kernel-headers/Makefile index e374e706e..f7842cb9b 100644 --- a/toolchain/kernel-headers/Makefile +++ b/toolchain/kernel-headers/Makefile @@ -17,7 +17,13 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=linux PKG_VERSION:=$(LINUX_VERSION) PKG_SOURCE:=$(LINUX_SOURCE) -PKG_SOURCE_URL:=$(LINUX_SITE) +ifneq ($(strip $(CONFIG_KERNEL_GIT_CLONE_URI)),"") + PKG_SOURCE_PROTO:=git + PKG_SOURCE_URL:=$(call qstrip,$(CONFIG_KERNEL_GIT_CLONE_URI)) + PKG_SOURCE_VERSION:=$(CONFIG_KERNEL_GIT_REF) +else + PKG_SOURCE_URL:=$(LINUX_SITE) +endif HOST_BUILD_DIR:=$(KERNEL_BUILD_DIR)/linux-$(LINUX_VERSION) PKG_HASH:=$(LINUX_KERNEL_HASH) LINUX_DIR := $(HOST_BUILD_DIR) diff --git a/toolchain/musl/common.mk b/toolchain/musl/common.mk index a94a47557..497aa8df0 100644 --- a/toolchain/musl/common.mk +++ b/toolchain/musl/common.mk @@ -9,7 +9,7 @@ include $(INCLUDE_DIR)/target.mk PKG_NAME:=musl PKG_VERSION:=1.1.18 -PKG_RELEASE=1 +PKG_RELEASE=2 PKG_SOURCE_PROTO:=git PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) @@ -21,9 +21,11 @@ PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.xz LIBC_SO_VERSION:=$(PKG_VERSION) PATCH_DIR:=$(PATH_PREFIX)/patches +BUILD_DIR_HOST:=$(BUILD_DIR_TOOLCHAIN) +HOST_BUILD_PREFIX:=$(TOOLCHAIN_DIR) HOST_BUILD_DIR:=$(BUILD_DIR_TOOLCHAIN)/$(PKG_NAME)-$(PKG_VERSION) -include $(INCLUDE_DIR)/toolchain-build.mk +include $(INCLUDE_DIR)/host-build.mk include $(INCLUDE_DIR)/hardening.mk MUSL_CONFIGURE:= \ @@ -37,18 +39,8 @@ MUSL_CONFIGURE:= \ --disable-gcc-wrapper \ --enable-debug -define Host/Prepare - $(call Host/Prepare/Default) - $(if $(strip $(QUILT)), \ - cd $(HOST_BUILD_DIR); \ - if $(QUILT_CMD) next >/dev/null 2>&1; then \ - $(QUILT_CMD) push -a; \ - fi - ) - ln -snf $(PKG_NAME)-$(PKG_VERSION) $(BUILD_DIR_TOOLCHAIN)/$(PKG_NAME) -endef - define Host/Configure + ln -snf $(PKG_NAME)-$(PKG_VERSION) $(BUILD_DIR_TOOLCHAIN)/$(PKG_NAME) ( cd $(HOST_BUILD_DIR); rm -f config.cache; \ $(MUSL_CONFIGURE) \ ); diff --git a/toolchain/musl/patches/010-kernel-suppress-some-more-Linux-uapi-definitions.patch b/toolchain/musl/patches/010-kernel-suppress-some-more-Linux-uapi-definitions.patch new file mode 100644 index 000000000..78b487fae --- /dev/null +++ b/toolchain/musl/patches/010-kernel-suppress-some-more-Linux-uapi-definitions.patch @@ -0,0 +1,59 @@ +From 8e85d2c268000b51cc690f3a55a820d8f8a6c0bc Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Thu, 22 Jun 2017 22:04:28 +0200 +Subject: [PATCH] Add additional uapi guards for Linux kernel header files + +With Linux kernel 4.15 it will be possible to guard more parts of the +Linux header files from a libc. Make use of this in musl to guard all +the structures and other definitions from the Linux header files which +are also defined by the header files provided by musl. This will make +musl compile with the unmodified Linux kernel user space headers. + +This extends the definitions done in commit 04983f227238 ("make +netinet/in.h suppress clashing definitions from kernel headers") + +The needed patches were recently accepted for Linux 4.15: +https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c0bace798436bca0fdc221ff61143f1376a9c3de +https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6926e041a8920c8ec27e4e155efa760aa01551fd +--- + include/net/if.h | 7 +++++++ + include/netinet/if_ether.h | 1 + + include/sys/xattr.h | 2 ++ + 3 files changed, 10 insertions(+) + +--- a/include/net/if.h ++++ b/include/net/if.h +@@ -125,6 +125,13 @@ struct ifconf { + #define ifc_req ifc_ifcu.ifcu_req + #define _IOT_ifconf _IOT(_IOTS(struct ifconf),1,0,0,0,0) + ++#define __UAPI_DEF_IF_IFCONF 0 ++#define __UAPI_DEF_IF_IFMAP 0 ++#define __UAPI_DEF_IF_IFNAMSIZ 0 ++#define __UAPI_DEF_IF_IFREQ 0 ++#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 0 ++#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 0 ++ + #endif + + #ifdef __cplusplus +--- a/include/netinet/if_ether.h ++++ b/include/netinet/if_ether.h +@@ -133,5 +133,6 @@ do { \ + (enaddr)[5] = ((uint8_t *)ipaddr)[3]; \ + } while(0) + ++#define __UAPI_DEF_ETHHDR 0 + + #endif +--- a/include/sys/xattr.h ++++ b/include/sys/xattr.h +@@ -24,6 +24,8 @@ int removexattr(const char *, const char + int lremovexattr(const char *, const char *); + int fremovexattr(int, const char *); + ++#define __UAPI_DEF_XATTR 0 ++ + #ifdef __cplusplus + } + #endif diff --git a/toolchain/musl/patches/400-Add-format-attribute-to-some-function-declarations.patch b/toolchain/musl/patches/400-Add-format-attribute-to-some-function-declarations.patch index c495d67e0..67fedae30 100644 --- a/toolchain/musl/patches/400-Add-format-attribute-to-some-function-declarations.patch +++ b/toolchain/musl/patches/400-Add-format-attribute-to-some-function-declarations.patch @@ -45,11 +45,7 @@ Signed-off-by: Hauke Mehrtens +#else +#define __fp(x, y) +#endif - --_Noreturn void err(int, const char *, ...); --_Noreturn void verr(int, const char *, va_list); --_Noreturn void errx(int, const char *, ...); --_Noreturn void verrx(int, const char *, va_list); ++ +void warn(const char *, ...) __fp(1, 2); +void vwarn(const char *, va_list) __fp(1, 0); +void warnx(const char *, ...) __fp(1, 2); @@ -59,7 +55,11 @@ Signed-off-by: Hauke Mehrtens +_Noreturn void verr(int, const char *, va_list) __fp(2, 0); +_Noreturn void errx(int, const char *, ...) __fp(2, 3); +_Noreturn void verrx(int, const char *, va_list) __fp(2, 0); -+ + +-_Noreturn void err(int, const char *, ...); +-_Noreturn void verr(int, const char *, va_list); +-_Noreturn void errx(int, const char *, ...); +-_Noreturn void verrx(int, const char *, va_list); +#undef __fp #ifdef __cplusplus diff --git a/toolchain/uClibc/common.mk b/toolchain/uClibc/common.mk index 384d73233..1600b790c 100644 --- a/toolchain/uClibc/common.mk +++ b/toolchain/uClibc/common.mk @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/target.mk -PKG_VERSION:=1.0.22 +PKG_VERSION:=1.0.28 PKG_NAME:=uClibc-ng PKG_SOURCE_URL = http://downloads.uclibc-ng.org/releases/$(PKG_VERSION)/ @@ -16,7 +16,7 @@ CONFIG_DIR:=$(PATH_PREFIX)/config PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz LIBC_SO_VERSION:=$(PKG_VERSION) -PKG_HASH:=f2004c85db8e07e9f1c2e8b7c513fa7c237bc9f9685d8e1bfc89535b8a85449b +PKG_HASH:=a1504ddc34a29cc9bfd1f5a7419c4b63bb510d9e2faed81618d1b596ceb0a5a9 HOST_BUILD_DIR:=$(BUILD_DIR_TOOLCHAIN)/$(PKG_NAME)-$(PKG_VERSION) diff --git a/tools/Makefile b/tools/Makefile index 50bd552d7..a95342f50 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -29,6 +29,7 @@ tools-y += mm-macros missing-macros cmake scons bc findutils gengetopt patchelf tools-y += mtools dosfstools libressl tools-$(CONFIG_TARGET_orion_generic) += wrt350nv2-builder upslug2 tools-$(CONFIG_TARGET_x86) += qemu +tools-$(CONFIG_EFI_IMAGES) += popt gptfdisk tools-$(CONFIG_TARGET_mxs) += elftosb sdimage tools-$(CONFIG_TARGET_ar71xx) += lzma-old squashfs tools-$(CONFIG_USES_MINOR) += kernel2minor @@ -71,6 +72,7 @@ $(curdir)/libressl/compile := $(curdir)/pkg-config/compile $(curdir)/mkimage/compile += $(curdir)/libressl/compile $(curdir)/firmware-utils/compile += $(curdir)/libressl/compile $(curdir)/cmake/compile += $(curdir)/libressl/compile +$(curdir)/gptfdisk/compile += $(curdir)/popt/compile $(curdir)/e2fsprogs/compile ifneq ($(HOST_OS),Linux) tools-y += coreutils diff --git a/tools/gptfdisk/Makefile b/tools/gptfdisk/Makefile new file mode 100644 index 000000000..dc5a5eb0d --- /dev/null +++ b/tools/gptfdisk/Makefile @@ -0,0 +1,37 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gptfdisk +PKG_VERSION:=1.0.1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://www.rodsbooks.com/gdisk/ +PKG_HASH:=864c8aee2efdda50346804d7e6230407d5f42a8ae754df70404dd8b2fdfaeac7 + +HOST_BUILD_PARALLEL := 1 + +include $(INCLUDE_DIR)/host-build.mk + +HOST_CONFIGURE_VARS += \ + MAKEFLAGS="$(HOST_JOBS)" \ + CXXFLAGS="$(HOST_CFLAGS)" + +HOST_CONFIGURE_ARGS := \ + $(if $(MAKE_JOBSERVER),--parallel="$(MAKE_JOBSERVER)") \ + --prefix=$(STAGING_DIR_HOST) + +define Host/Compile + $(MAKE) LDFLAGS="$(HOST_LDFLAGS)" CXXFLAGS="$(HOST_CFLAGS) -I$(STAGING_DIR_HOST)/include/e2fsprogs" -C $(HOST_BUILD_DIR) sgdisk +endef + +define Host/Install + $(INSTALL_BIN) $(HOST_BUILD_DIR)/sgdisk $(STAGING_DIR_HOST)/bin/ +endef + +define Host/Clean + rm -f $(STAGING_DIR_HOST)/bin/sgdisk +endef + +HOSTCC := $(HOSTCC_NOCACHE) +HOSTCXX := $(HOSTCXX_NOCACHE) + +$(eval $(call HostBuild)) diff --git a/tools/popt/Makefile b/tools/popt/Makefile new file mode 100644 index 000000000..7d1a1f8ef --- /dev/null +++ b/tools/popt/Makefile @@ -0,0 +1,20 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=popt +PKG_VERSION:=1.16 +PKG_HASH:=e728ed296fe9f069a0e005003c3d6b2dde3d9cad453422a10d6558616d304cc8 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://rpm5.org/files/popt/ +PKG_LICENSE:=MIT + +HOST_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/host-build.mk + +HOST_CONFIGURE_ARGS += --disable-shared --disable-nls +HOST_CFLAGS += $(FPIC) + +$(eval $(call HostBuild)) +
    Edit Stream Relay Config
    Mode (requires OSCam restart) ++ ++
    Source Stream Host:
    Source Stream Port:
    Source Stream User:
    Source Stream Password:
    Relay Port:
    ECM fix delay:
    Process EMM from stream: ++ ++
    AU providers:
    [BISS] Enable date-coded keys:
    [Drecrypt] Path to ee36.bin:
    [Drecrypt] Path to ee56.bin:
    [Drecrypt] Center force group:
    [Drecrypt] Siberia force group: