diff --git a/platform/broadcom/docker-syncd-brcm/Dockerfile.j2 b/platform/broadcom/docker-syncd-brcm/Dockerfile.j2 index b20e353f84..1ef1c58877 100755 --- a/platform/broadcom/docker-syncd-brcm/Dockerfile.j2 +++ b/platform/broadcom/docker-syncd-brcm/Dockerfile.j2 @@ -1,3 +1,4 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages %} FROM docker-config-engine-stretch ARG docker_container_name @@ -14,10 +15,8 @@ debs/{{ deb }}{{' '}} {%- endfor -%} debs/ -RUN dpkg -i \ -{% for deb in docker_syncd_brcm_debs.split(' ') -%} -debs/{{ deb }}{{' '}} -{%- endfor %} +# Install locally-built Debian packages and implicitly install their dependencies +{{ install_debian_packages(docker_syncd_brcm_debs.split(' ')) }} ## TODO: add kmod into Depends RUN apt-get install -yf kmod diff --git a/platform/broadcom/sai-modules.mk b/platform/broadcom/sai-modules.mk index dc77c4b5cb..1d559d0ad3 100644 --- a/platform/broadcom/sai-modules.mk +++ b/platform/broadcom/sai-modules.mk @@ -1,7 +1,7 @@ # Broadcom SAI modules KVERSION = 4.9.0-9-2-amd64 -BRCM_OPENNSL_KERNEL_VERSION = 3.4.1.11-1 +BRCM_OPENNSL_KERNEL_VERSION = 3.7.3.3-1 BRCM_OPENNSL_KERNEL = opennsl-modules_$(BRCM_OPENNSL_KERNEL_VERSION)_amd64.deb $(BRCM_OPENNSL_KERNEL)_SRC_PATH = $(PLATFORM_PATH)/saibcm-modules diff --git a/platform/broadcom/sai.mk b/platform/broadcom/sai.mk index 833c22f6bb..63c1e21ec7 100644 --- a/platform/broadcom/sai.mk +++ b/platform/broadcom/sai.mk @@ -1,9 +1,9 @@ -BRCM_SAI = libsaibcm_3.5.3.1m-25_amd64.deb -$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.5/libsaibcm_3.5.3.1m-26_amd64.deb?sv=2015-04-05&sr=b&sig=zo83IKnlT7goymXwynW8%2Fx6rR2eIh0AiIS%2BSrSMUhRE%3D&se=2033-07-21T18%3A50%3A27Z&sp=r" +BRCM_SAI = libsaibcm_3.7.3.3_amd64.deb +$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.7/libsaibcm_3.7.3.3_amd64.deb?sv=2015-04-05&sr=b&sig=Y66VSRUEl4PDf5kHRo%2FS3DBBE9tONSyCzNJvi8IP9n8%3D&se=2033-08-25T01%3A22%3A08Z&sp=r" -BRCM_SAI_DEV = libsaibcm-dev_3.5.3.1m-25_amd64.deb +BRCM_SAI_DEV = libsaibcm-dev_3.7.3.3_amd64.deb $(eval $(call add_derived_package,$(BRCM_SAI),$(BRCM_SAI_DEV))) -$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.5/libsaibcm-dev_3.5.3.1m-26_amd64.deb?sv=2015-04-05&sr=b&sig=tQmkCIy2mnb9rH7B9oXFUZDwijMGXWnVtta2CNTMbFM%3D&se=2033-07-21T18%3A50%3A47Z&sp=r" +$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.7/libsaibcm-dev_3.7.3.3_amd64.deb?sv=2015-04-05&sr=b&sig=6%2BWzgFL845H9lKE0COsN53P4MO4UWfSo0z%2FmUMFbYVk%3D&se=2033-08-25T01%3A21%3A50Z&sp=r" SONIC_ONLINE_DEBS += $(BRCM_SAI) -$(BRCM_SAI_DEV)_DEPENDS += $(BRCM_SAI) +$(BRCM_SAI_DEV)_DEPENDS += $(BRCM_SAI) \ No newline at end of file diff --git a/platform/broadcom/saibcm-modules/debian/changelog b/platform/broadcom/saibcm-modules/debian/changelog index 5ea7b289ee..2be513ed04 100644 --- a/platform/broadcom/saibcm-modules/debian/changelog +++ b/platform/broadcom/saibcm-modules/debian/changelog @@ -1,3 +1,24 @@ +opennsl (3.7.3.3-1) unstable; urgency=medium + + * Port Broadcom SAI 3.7.3.3 + * Cherry-pick change from master branch, 3.7.3.3-1 + + -- Judy Joseph Fri, 2 Dec 2019 15:32:47 +0000 + +opennsl (3.7.3.2-1) unstable; urgency=medium + + * Port Broadcom SAI 3.7.3.2 + * Cherry-pick change from master branch, 3.7.3.2-1 + + -- Judy Joseph Fri, 12 Nov 2019 15:22:47 +0000 + +opennsl (3.7.3.1-1) unstable; urgency=medium + + * Port Broadcom SAI 3.7.3.1 + * Cherry-pick change from master branch, 3.7.3.1-1 + + -- Judy Joseph Fri, 19 Sep 2019 13:11:47 +0000 + opennsl (3.4.1.11-1) unstable; urgency=medium * Port Broadcom SAI 3.4.1.11 diff --git a/platform/broadcom/saibcm-modules/debian/opennsl-modules.init b/platform/broadcom/saibcm-modules/debian/opennsl-modules.init index 1aaa91bb2d..7def10cbff 100755 --- a/platform/broadcom/saibcm-modules/debian/opennsl-modules.init +++ b/platform/broadcom/saibcm-modules/debian/opennsl-modules.init @@ -32,14 +32,38 @@ function create_devices() # level logs function load_kernel_modules() { - modprobe linux-kernel-bde dmasize=32M maxpayload=128 debug=4 dma_debug=1 + . /host/machine.conf + + if [ -n "$aboot_platform" ]; then + platform=$aboot_platform + elif [ -n "$onie_platform" ]; then + platform=$onie_platform + else + platform="unknown" + fi + + # Set the default configuration for dmasize and usemsi parameters + dmasize=32M + usemsi=0 + + # Source the platform env file + env_file="/usr/share/sonic/device/$platform/platform_env.conf" + source $env_file + + modprobe linux-kernel-bde dmasize=$dmasize maxpayload=128 debug=4 dma_debug=1 usemsi=$usemsi modprobe linux-user-bde + + # Using insmod with absolute path for psample to make sure bcm psample is loaded. + # There is a different psample.ko module getting created at net/psample/psample.ko + insmod /lib/modules/$(uname -r)/extra/psample.ko + modprobe linux-bcm-knet use_rx_skb=1 rx_buffer_size=9238 debug=0x5020 modprobe linux-knet-cb } function remove_kernel_modules() { + rmmod psample.ko rmmod linux-knet-cb rmmod linux-bcm-knet rmmod linux-user-bde diff --git a/platform/broadcom/saibcm-modules/debian/opennsl-modules.install b/platform/broadcom/saibcm-modules/debian/opennsl-modules.install index 11b100d37f..e16980dc2c 100644 --- a/platform/broadcom/saibcm-modules/debian/opennsl-modules.install +++ b/platform/broadcom/saibcm-modules/debian/opennsl-modules.install @@ -2,4 +2,5 @@ systems/linux/user/x86-smp_generic_64-2_6/linux-bcm-knet.ko lib/modules/4.9.0-9- systems/linux/user/x86-smp_generic_64-2_6/linux-kernel-bde.ko lib/modules/4.9.0-9-2-amd64/extra systems/linux/user/x86-smp_generic_64-2_6/linux-user-bde.ko lib/modules/4.9.0-9-2-amd64/extra systems/linux/user/x86-smp_generic_64-2_6/linux-knet-cb.ko lib/modules/4.9.0-9-2-amd64/extra +systems/linux/user/x86-smp_generic_64-2_6/psample.ko lib/modules/4.9.0-9-2-amd64/extra systemd/opennsl-modules.service lib/systemd/system diff --git a/platform/broadcom/saibcm-modules/debian/rules b/platform/broadcom/saibcm-modules/debian/rules index 33abe645d4..0092cc1a10 100755 --- a/platform/broadcom/saibcm-modules/debian/rules +++ b/platform/broadcom/saibcm-modules/debian/rules @@ -60,7 +60,7 @@ kdist_config: prep-deb-files kdist_clean: clean dh_testdir dh_clean - SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 KERNDIR=/usr/src/linux-headers-4.9.0-9-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-9-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean + SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 BUILD_PSAMPLE=1 KERNDIR=/usr/src/linux-headers-4.9.0-9-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-9-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean # rm -f driver/*.o driver/*.ko # ### end KERNEL SETUP @@ -78,7 +78,7 @@ build-arch-stamp: dh_testdir # Add here command to compile/build the package. - SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 KERNDIR=/usr/src/linux-headers-4.9.0-9-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-9-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 + SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 BUILD_PSAMPLE=1 KERNDIR=/usr/src/linux-headers-4.9.0-9-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-9-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 touch $@ @@ -103,7 +103,7 @@ clean: rm -f build-arch-stamp build-indep-stamp configure-stamp # Add here commands to clean up after the build process. - SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 KERNDIR=/usr/src/linux-headers-4.9.0-9-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-9-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean + SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 BUILD_PSAMPLE=1 KERNDIR=/usr/src/linux-headers-4.9.0-9-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-9-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean dh_clean diff --git a/platform/broadcom/saibcm-modules/include/ibde.h b/platform/broadcom/saibcm-modules/include/ibde.h index 9c8956f5e3..45112eadcb 100644 --- a/platform/broadcom/saibcm-modules/include/ibde.h +++ b/platform/broadcom/saibcm-modules/include/ibde.h @@ -148,14 +148,6 @@ typedef struct ibde_s { */ int (*get_cmic_ver)(int d, uint32 *ver); - /* - * Probe available devices. - * Return value : - * 0: success to probe available devices - * -1: error happens during probe - */ - int (*probe)(void); - /* * I2C operations on the Device, assuming it is connected by I2C to the CPU. */ diff --git a/platform/broadcom/saibcm-modules/include/kcom.h b/platform/broadcom/saibcm-modules/include/kcom.h index 76f3e47a8d..1e3cad0753 100644 --- a/platform/broadcom/saibcm-modules/include/kcom.h +++ b/platform/broadcom/saibcm-modules/include/kcom.h @@ -121,6 +121,13 @@ typedef struct kcom_msg_hdr_s { #define KCOM_NETIF_NAME_MAX 16 +/* + * Max size of Sand System Headers + * For DNX, Module Header(20B) + PTCH(2B) + ITMH(5B) + * For DPP, PTCH(2B) + ITMH(4B) + */ +#define KCOM_NETIF_SYSTEM_HEADERS_SIZE_MAX 27 + typedef struct kcom_netif_s { uint16 id; uint8 type; @@ -133,6 +140,8 @@ typedef struct kcom_netif_s { uint8 macaddr[6]; uint8 ptch[2]; uint8 itmh[4]; + uint8 system_headers[KCOM_NETIF_SYSTEM_HEADERS_SIZE_MAX]; + uint8 system_headers_size; char name[KCOM_NETIF_NAME_MAX]; } kcom_netif_t; @@ -216,6 +225,13 @@ typedef struct kcom_filter_s { uint8 b[KCOM_FILTER_BYTES_MAX]; uint32 w[KCOM_FILTER_WORDS_MAX]; } mask; + /** Information to parse Dune system headers */ + uint32 ftmh_lb_key_ext_size; + uint32 ftmh_stacking_ext_size; + uint32 pph_base_size; + uint32 pph_lif_ext_size[8]; + uint8 udh_enable; + uint32 udh_length_type[4]; } kcom_filter_t; /* @@ -470,8 +486,7 @@ typedef struct kcom_msg_filter_destroy_s { * Get list of currently defined packet filters. */ #ifndef KCOM_FILTER_MAX -/* SAI_FIXUP - Increased the filters to 1024 from 128 */ -#define KCOM_FILTER_MAX 1024 +#define KCOM_FILTER_MAX 128 #endif typedef struct kcom_msg_filter_list_s { diff --git a/platform/broadcom/saibcm-modules/include/soc/devids.h b/platform/broadcom/saibcm-modules/include/soc/devids.h index cb072a78cb..7546ef3922 100644 --- a/platform/broadcom/saibcm-modules/include/soc/devids.h +++ b/platform/broadcom/saibcm-modules/include/soc/devids.h @@ -14,7 +14,7 @@ * version 2 (GPLv2) along with this source code. */ /* - * Copyright: (c) 2018 Broadcom. + * Copyright: (c) 2019 Broadcom. * All Rights Reserved. */ @@ -835,31 +835,6 @@ #define BCM56746_A0_REV_ID 1 #define BCM56746_A1_REV_ID 2 -#define BCM88230_DEVICE_ID 0x0230 -#define BCM88230_A0_REV_ID 1 -#define BCM88230_B0_REV_ID 0x11 -#define BCM88230_C0_REV_ID 0x21 -#define BCM88231_DEVICE_ID 0x0231 -#define BCM88231_A0_REV_ID 1 -#define BCM88231_B0_REV_ID 0x11 -#define BCM88231_C0_REV_ID 0x21 -#define BCM88235_DEVICE_ID 0x0235 -#define BCM88235_A0_REV_ID 1 -#define BCM88235_B0_REV_ID 0x11 -#define BCM88235_C0_REV_ID 0x21 -#define BCM88236_DEVICE_ID 0x0236 -#define BCM88236_A0_REV_ID 1 -#define BCM88236_B0_REV_ID 0x11 -#define BCM88236_C0_REV_ID 0x21 -#define BCM88239_DEVICE_ID 0x0239 -#define BCM88239_A0_REV_ID 1 -#define BCM88239_B0_REV_ID 0x11 -#define BCM88239_C0_REV_ID 0x21 -#define BCM56613_DEVICE_ID 0xb613 -#define BCM56613_A0_REV_ID 1 -#define BCM56613_B0_REV_ID 0x11 -#define BCM56613_C0_REV_ID 0x21 - #define BCM88732_DEVICE_ID 0x0732 #define BCM88732_A0_REV_ID 1 #define BCM88732_A1_REV_ID 2 @@ -1243,10 +1218,13 @@ #define BCM56981_A0_REV_ID 1 #define BCM56982_DEVICE_ID 0xb982 #define BCM56982_A0_REV_ID 1 +#define BCM56982_B0_REV_ID 0x11 #define BCM56983_DEVICE_ID 0xb983 #define BCM56983_A0_REV_ID 1 +#define BCM56983_B0_REV_ID 0x11 #define BCM56984_DEVICE_ID 0xb984 #define BCM56984_A0_REV_ID 1 +#define BCM56984_B0_REV_ID 0x11 #define BCM56968_DEVICE_ID 0xb968 #define BCM56968_A0_REV_ID 1 @@ -1428,33 +1406,43 @@ #define BCM56370_DEVICE_ID 0xb370 #define BCM56370_A0_REV_ID 1 +#define BCM56370_A1_REV_ID 0x02 #define BCM56371_DEVICE_ID 0xb371 #define BCM56371_A0_REV_ID 1 +#define BCM56371_A1_REV_ID 0x02 #define BCM56372_DEVICE_ID 0xb372 #define BCM56372_A0_REV_ID 1 +#define BCM56372_A1_REV_ID 0x02 #define BCM56374_DEVICE_ID 0xb374 #define BCM56374_A0_REV_ID 1 +#define BCM56374_A1_REV_ID 0x02 #define BCM56375_DEVICE_ID 0xb375 #define BCM56375_A0_REV_ID 1 +#define BCM56375_A1_REV_ID 0x02 #define BCM56376_DEVICE_ID 0xb376 #define BCM56376_A0_REV_ID 1 +#define BCM56376_A1_REV_ID 0x02 #define BCM56377_DEVICE_ID 0xb377 #define BCM56377_A0_REV_ID 1 +#define BCM56377_A1_REV_ID 0x02 #define BCM56577_DEVICE_ID 0xb577 #define BCM56577_A0_REV_ID 1 +#define BCM56577_A1_REV_ID 0x02 #define BCM56578_DEVICE_ID 0xb578 #define BCM56578_A0_REV_ID 1 +#define BCM56578_A1_REV_ID 0x02 #define BCM56579_DEVICE_ID 0xb579 #define BCM56579_A0_REV_ID 1 +#define BCM56579_A1_REV_ID 0x02 #define BCM56770_DEVICE_ID 0xb770 #define BCM56770_A0_REV_ID 1 @@ -1488,247 +1476,6 @@ #define BROADCOM_PHYID_HIGH 0x0040 -#define BCM5338_PHYID_LOW 0x62b0 -#define BCM5338_A0_REV_ID 0 -#define BCM5338_A1_REV_ID 1 -#define BCM5338_B0_REV_ID 3 - -#define BCM5324_PHYID_LOW 0xbc20 -#define BCM5324_PHYID_HIGH 0x143 -#define BCM5324_A1_PHYID_HIGH 0x153 -#define BCM5324_DEVICE_ID 0xbc20 -#define BCM5324_A0_REV_ID 0 -#define BCM5324_A1_REV_ID 1 -#define BCM5324_A2_REV_ID 2 - -#define BCM5380_PHYID_LOW 0x6250 -#define BCM5380_A0_REV_ID 0 - -#define BCM5388_PHYID_LOW 0x6288 -#define BCM5388_A0_REV_ID 0 - -#define BCM5396_PHYID_LOW 0xbd70 -#define BCM5396_PHYID_HIGH 0x143 -#define BCM5396_DEVICE_ID 0x96 -#define BCM5396_A0_REV_ID 0 - -#define BCM5389_PHYID_LOW 0xbd70 -#define BCM5389_PHYID_HIGH 0x143 -#define BCM5389_DEVICE_ID 0x89 -#define BCM5389_A0_REV_ID 0 -#define BCM5389_A1_DEVICE_ID 0x86 -#define BCM5389_A1_REV_ID 1 - -#define BCM5398_PHYID_LOW 0xbcd0 -#define BCM5398_PHYID_HIGH 0x0143 -#define BCM5398_DEVICE_ID 0x98 -#define BCM5398_A0_REV_ID 0 - -#define BCM5325_PHYID_LOW 0xbc30 -#define BCM5325_PHYID_HIGH 0x143 -#define BCM5325_DEVICE_ID 0xbc30 -#define BCM5325_A0_REV_ID 0 -#define BCM5325_A1_REV_ID 1 - -#define BCM5348_PHYID_LOW 0xbe40 -#define BCM5348_PHYID_HIGH 0x0143 -#define BCM5348_DEVICE_ID 0x48 -#define BCM5348_A0_REV_ID 0 -#define BCM5348_A1_REV_ID 1 - -#define BCM5397_PHYID_LOW 0xbcd0 -#define BCM5397_PHYID_HIGH 0x0143 -#define BCM5397_DEVICE_ID 0x97 -#define BCM5397_A0_REV_ID 0 - -#define BCM5347_PHYID_LOW 0xbe40 -#define BCM5347_PHYID_HIGH 0x0143 -#define BCM5347_DEVICE_ID 0x47 -#define BCM5347_A0_REV_ID 0 - -#define BCM5395_PHYID_LOW 0xbcf0 -#define BCM5395_PHYID_HIGH 0x0143 -#define BCM5395_DEVICE_ID 0xbcf0 -#define BCM5395_A0_REV_ID 0 - -#define BCM53242_PHYID_LOW 0xbf10 -#define BCM53242_PHYID_HIGH 0x0143 -#define BCM53242_DEVICE_ID 0xbf10 -#define BCM53242_A0_REV_ID 0 -#define BCM53242_B0_REV_ID 4 -#define BCM53242_B1_REV_ID 5 - -#define BCM53262_PHYID_LOW 0xbf20 -#define BCM53262_PHYID_HIGH 0x0143 -#define BCM53262_DEVICE_ID 0xbf20 -#define BCM53262_A0_REV_ID 0 -#define BCM53262_B0_REV_ID 4 -#define BCM53262_B1_REV_ID 5 - -#define BCM53115_PHYID_LOW 0xbf80 -#define BCM53115_PHYID_HIGH 0x0143 -#define BCM53115_DEVICE_ID 0xbf80 -#define BCM53115_A0_REV_ID 0 -#define BCM53115_A1_REV_ID 1 -#define BCM53115_B0_REV_ID 2 -#define BCM53115_B1_REV_ID 3 -#define BCM53115_C0_REV_ID 8 - -#define BCM53118_PHYID_LOW 0xbfe0 -#define BCM53118_PHYID_HIGH 0x0143 -#define BCM53118_DEVICE_ID 0xbfe0 -#define BCM53118_A0_REV_ID 0 - -#define BCM53118_B0_REV_ID 4 -#define BCM53118_B1_REV_ID 5 - -#define BCM53280_PHYID_LOW 0x5e90 -#define BCM53280_PHYID_HIGH 0x0362 -#define BCM53280_DEVICE_ID (0x4 | BCM53280_PHYID_LOW) -#define BCM53280_A0_REV_ID 0 -#define BCM53280_B0_REV_ID 0x4 -#define BCM53280_B1_REV_ID 0x5 -#define BCM53280_B2_REV_ID 0x6 -#define BCM53286_DEVICE_ID (0x4 | BCM53280_PHYID_LOW) -#define BCM53288_DEVICE_ID (0xc | BCM53280_PHYID_LOW) -#define BCM53284_DEVICE_ID (0x7 | BCM53280_PHYID_LOW) -#define BCM53283_DEVICE_ID (0x6 | BCM53280_PHYID_LOW) -#define BCM53282_DEVICE_ID (0x5 | BCM53280_PHYID_LOW) -#define BCM53101_PHYID_LOW 0x5ed0 -#define BCM53101_PHYID_HIGH 0x0362 -#define BCM53101_DEVICE_ID 0x5ed0 -#define BCM53101_A0_REV_ID 0 -#define BCM53101_B0_REV_ID 4 - -#define BCM53125_PHYID_LOW 0x5f20 -#define BCM53125_PHYID_HIGH 0x0362 -#define BCM53125_DEVICE_ID 0x5f20 -#define BCM53125_A0_REV_ID 0 -#define BCM53125_B0_REV_ID 0x4 -#define BCM53125_MODEL_ID 0x53125 - -#define BCM53134_PHYID_LOW 0x5350 -#define BCM53134_PHYID_HIGH 0xAE02 -#define BCM53134_DEVICE_ID 0x5350 -#define BCM53134_A0_REV_ID 0x0 -#define BCM53134_B0_REV_ID 0x1 -#define BCM53134_B1_REV_ID 0x2 -#define BCM53134_A0_MODEL_ID 0x5035 -#define BCM53134_B0_MODEL_ID 0x5075 - -#define BCM53128_PHYID_LOW 0x5e10 -#define BCM53128_PHYID_HIGH 0x0362 -#define BCM53128_DEVICE_ID 0x5e10 -#define BCM53128_A0_REV_ID 0 -#define BCM53128_B0_REV_ID 0x4 -#define BCM53128_MODEL_ID 0x53128 - -#define BCM53600_PHYID_LOW 0x5f40 -#define BCM53600_PHYID_HIGH 0x0362 -#define BCM53600_DEVICE_ID (0x3 | BCM53600_PHYID_LOW) -#define BCM53600_A0_REV_ID 0 -#define BCM53602_DEVICE_ID (0x1 | BCM53600_PHYID_LOW) -#define BCM53603_DEVICE_ID (0x2 | BCM53600_PHYID_LOW) -#define BCM53604_DEVICE_ID (0x3 | BCM53600_PHYID_LOW) -#define BCM53606_DEVICE_ID (0x7 | BCM53600_PHYID_LOW) - -#define BCM89500_PHYID_LOW 0x5d30 -#define BCM89500_PHYID_HIGH 0x0362 -#define BCM89500_DEVICE_ID 0x9500 -#define BCM89501_DEVICE_ID 0x9501 -#define BCM89200_DEVICE_ID 0x9200 -#define BCM89500_A0_REV_ID 0 -#define BCM89500_B0_REV_ID 0x4 -#define BCM89500_MODEL_ID 0x89500 - -#define BCM53010_PHYID_LOW 0x8760 -#define BCM53010_PHYID_HIGH 0x600d -#define BCM53010_DEVICE_ID 0x3010 -#define BCM53011_DEVICE_ID 0x3011 -#define BCM53012_DEVICE_ID 0x3012 -#define BCM53010_A0_REV_ID 0 -#define BCM53010_A2_REV_ID 0x2 -#define BCM53010_MODEL_ID 0x53010 - -#define BCM53018_PHYID_LOW 0x87c0 -#define BCM53018_PHYID_HIGH 0x600d -#define BCM53017_DEVICE_ID 0x3016 -#define BCM53018_DEVICE_ID 0x3018 -#define BCM53019_DEVICE_ID 0x3019 -#define BCM53018_A0_REV_ID 0 -#define BCM53018_MODEL_ID 0x53016 - -#define BCM53020_PHYID_LOW 0x87f0 -#define BCM53020_PHYID_HIGH 0x600d -#define BCM53020_DEVICE_ID 0x8022 -#define BCM53022_DEVICE_ID 0x8022 -#define BCM53023_DEVICE_ID 0x8023 -#define BCM53025_DEVICE_ID 0x8025 -#define BCM58625_DEVICE_ID 0x8625 -#define BCM58622_DEVICE_ID 0x8622 -#define BCM58623_DEVICE_ID 0x8623 -#define BCM58525_DEVICE_ID 0x8525 -#define BCM58522_DEVICE_ID 0x8522 -#define BCM53020_A0_REV_ID 0 -#define BCM53020_MODEL_ID 0x3025 - -#define BCM4713_DEVICE_ID 0x4713 -#define BCM4713_A0_REV_ID 0 -#define BCM4713_A9_REV_ID 9 - -#define BCM53000_GMAC_DEVICE_ID 0x4715 -#define BCM53000_A0_REV_ID 0 - -#define BCM53010_GMAC_DEVICE_ID 0x4715 - -#define BCM53000PCIE_DEVICE_ID 0x5300 - -#define SANDBURST_VENDOR_ID 0x17ba -#define BME3200_DEVICE_ID 0x0280 -#define BME3200_A0_REV_ID 0x0000 -#define BME3200_B0_REV_ID 0x0001 -#define BM9600_DEVICE_ID 0x0480 -#define BM9600_A0_REV_ID 0x0000 -#define BM9600_B0_REV_ID 0x0010 -#define QE2000_DEVICE_ID 0x0300 -#define QE2000_A1_REV_ID 0x0001 -#define QE2000_A2_REV_ID 0x0002 -#define QE2000_A3_REV_ID 0x0003 -#define QE2000_A4_REV_ID 0x0004 -#define BCM88020_DEVICE_ID 0x0380 -#define BCM88020_A0_REV_ID 0x0000 -#define BCM88020_A1_REV_ID 0x0001 -#define BCM88020_A2_REV_ID 0x0002 -#define BCM88025_DEVICE_ID 0x0580 -#define BCM88025_A0_REV_ID 0x0000 -#define BCM88030_DEVICE_ID 0x0038 -#define BCM88030_A0_REV_ID 0x0001 -#define BCM88030_A1_REV_ID 0x0002 -#define BCM88030_B0_REV_ID 0x0011 -#define BCM88030_B1_REV_ID 0x0012 -#define BCM88034_DEVICE_ID 0x0034 -#define BCM88034_A0_REV_ID (BCM88030_A0_REV_ID) -#define BCM88034_A1_REV_ID (BCM88030_A1_REV_ID) -#define BCM88034_B0_REV_ID (BCM88030_B0_REV_ID) -#define BCM88034_B1_REV_ID (BCM88030_B1_REV_ID) -#define BCM88039_DEVICE_ID 0x0039 -#define BCM88039_A0_REV_ID (BCM88030_A0_REV_ID) -#define BCM88039_A1_REV_ID (BCM88030_A1_REV_ID) -#define BCM88039_B0_REV_ID (BCM88030_B0_REV_ID) -#define BCM88039_B1_REV_ID (BCM88030_B1_REV_ID) -#define BCM88130_DEVICE_ID 0x0480 -#define BCM88130_A0_REV_ID 0x0000 -#define BCM88130_A1_REV_ID 0x0001 -#define BCM88130_B0_REV_ID 0x0010 -#define PLX_VENDOR_ID 0x10b5 -#define PLX9656_DEVICE_ID 0x9656 -#define PLX9656_REV_ID 0x0000 -#define PLX9056_DEVICE_ID 0x9056 -#define PLX9056_REV_ID 0x0000 - -#define TK371X_DEVICE_ID 0x8600 -#define TK371X_A0_REV_ID 0x0 - #define GEDI_DEVICE_ID 0xa100 #define GEDI_REV_ID 0x0001 #define ARAD_DEVICE_ID 0x8650 @@ -1778,6 +1525,7 @@ #define DNXC_A0_REV_ID 0x0001 #define DNXC_A1_REV_ID 0x0002 #define DNXC_B0_REV_ID 0x0011 +#define DNXC_B1_REV_ID 0x0012 #define BCM88790_DEVICE_ID 0x8790 #define BCM88790_A0_REV_ID DNXC_A0_REV_ID #define BCM88790_B0_REV_ID DNXC_B0_REV_ID @@ -1933,9 +1681,34 @@ #define BCM88381_A0_REV_ID JERICHO_PLUS_A0_REV_ID #define JERICHO_2_DEVICE_ID 0x8690 -#define JERICHO_2_A0_REV_ID 0x0001 +#define JERICHO_2_A0_REV_ID DNXC_A0_REV_ID +#define JERICHO_2_B0_REV_ID DNXC_B0_REV_ID +#define JERICHO_2_B1_REV_ID DNXC_B1_REV_ID #define BCM88690_DEVICE_ID JERICHO_2_DEVICE_ID #define BCM88690_A0_REV_ID JERICHO_2_A0_REV_ID +#define BCM88690_B0_REV_ID JERICHO_2_B0_REV_ID +#define BCM88690_B1_REV_ID JERICHO_2_B1_REV_ID +#define BCM88691_DEVICE_ID 0x8691 +#define BCM88692_DEVICE_ID 0x8692 +#define BCM88693_DEVICE_ID 0x8693 +#define BCM88694_DEVICE_ID 0x8694 +#define BCM88695_DEVICE_ID 0x8695 +#define BCM88696_DEVICE_ID 0x8696 +#define BCM88697_DEVICE_ID 0x8697 +#define BCM88698_DEVICE_ID 0x8698 +#define BCM88699_DEVICE_ID 0x8699 +#define BCM8869A_DEVICE_ID 0x869A +#define BCM8869B_DEVICE_ID 0x869B +#define BCM8869C_DEVICE_ID 0x869C +#define BCM8869D_DEVICE_ID 0x869D +#define BCM8869E_DEVICE_ID 0x869E +#define BCM8869F_DEVICE_ID 0x869F +#define BCM_JR2_DEVID_MASK 0xFFF0 + +#define J2C_DEVICE_ID 0x8800 +#define J2C_A0_REV_ID DNXC_A0_REV_ID +#define BCM88800_DEVICE_ID J2C_DEVICE_ID +#define BCM88800_A0_REV_ID J2C_A0_REV_ID #define QAX_DEVICE_ID 0x8470 #define QAX_A0_REV_ID 0x0001 @@ -1964,6 +1737,7 @@ #define BCM88270_A1_REV_ID QUX_A1_REV_ID #define BCM88272_DEVICE_ID 0x8272 #define BCM88273_DEVICE_ID 0x8273 +#define BCM88274_DEVICE_ID 0x8274 #define BCM88278_DEVICE_ID 0x8278 #define BCM88279_DEVICE_ID 0x8279 @@ -2045,5 +1819,8 @@ #define ACP_PCI_VENDOR_ID 0x10ee #define ACP_PCI_DEVICE_ID 0x7011 #define ACP_PCI_REV_ID 0x0001 + +#define PLX9056_DEVICE_ID 0x9056 + #endif diff --git a/platform/broadcom/saibcm-modules/make/Make.config b/platform/broadcom/saibcm-modules/make/Make.config index b8fa17bda1..409a6a49b3 100644 --- a/platform/broadcom/saibcm-modules/make/Make.config +++ b/platform/broadcom/saibcm-modules/make/Make.config @@ -54,12 +54,7 @@ endif -include ${SDK}/make/Make.local ifdef ALL_CHIPS - ROBO_CHIPS = 1 ESW_CHIPS = 1 -else - ifndef ROBO_CHIPS - ESW_CHIPS = 1 - endif endif # ALL_CHIPS # @@ -166,7 +161,7 @@ CFLAGS += ${INCFLAGS} CXXFLAGS += ${INCFLAGS} CPPFLAGS += ${INCFLAGS} -CFLAGS += -DSAI_FIXUP -DBCM_PORT_DEFAULT_DISABLE -DBCM_VLAN_NO_DEFAULT_ETHER -DBCM_VLAN_NO_DEFAULT_CPU -DBCM_WARM_BOOT_SUPPORT -DSAL_CONFIG_FILE_DISABLE -DSAL_THREAD_NAME_PRINT_DISABLE -UKCOM_FILTER_MAX -DKCOM_FILTER_MAX=256 -DALPM_ENABLE -DOPENNSL_PHY_ROUTINES -DTH2_CPU_POOL_SETUP -DINCLUDE_L3 -DSAI_ONLY -DPRINT_TO_SYSLOG -D_SHR_PBMP_WIDTH=256 -DINCLUDE_DIAG_SHELL -DSTATIC=static -DLOG_TEST -DLOG_SAI -D_GNU_SOURCE +CFLAGS += -DSAI_FIXUP -UKCOM_FILTER_MAX -DKCOM_FILTER_MAX=1024 # # Debug #ifdef control diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-gto b/platform/broadcom/saibcm-modules/make/Makefile.linux-gto index 947c20e74f..786b4cc26b 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-gto +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-gto @@ -74,12 +74,6 @@ modname_flags = $(if $(filter 1,$(words $(modname))),\ KFLAG_INCLD = $(TOOLCHAIN_BIN_DIR)/../lib/gcc/$(TARGET_ARCHITECTURE)/4.6.4/include ifdef BROADCOM_SVK -ifdef BCM_BME3200_B0 -PLX_PCI2LBUS=1 -endif -ifdef BCM_BM9600_B0 -PLX_PCI2LBUS=1 -endif ifeq ($PLX_PCI2LBUS, 1) CFLAGS += -DBCM_PLX9656_LOCAL_BUS -DBDE_LINUX_NON_INTERRUPTIBLE endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-gto-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-gto-2_6 index 4caa490242..56085c7a3c 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-gto-2_6 +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-gto-2_6 @@ -224,12 +224,6 @@ endif endif ifdef BROADCOM_SVK -ifdef BCM_BME3200_B0 -PLX_PCI2LBUS=1 -endif -ifdef BCM_BM9600_B0 -PLX_PCI2LBUS=1 -endif ifeq ($PLX_PCI2LBUS, 1) CFLAGS += -DBCM_PLX9656_LOCAL_BUS -DBDE_LINUX_NON_INTERRUPTIBLE endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc index 7c0f9411f5..092e474e25 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc @@ -27,11 +27,11 @@ endif # TARGET_ARCHITECTURE Compiler for target architecture # KERNDIR Kernel directory for iPROC-CMICd devices ifeq (BE,$(ENDIAN_MODE)) -TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/iproc-be/XLDK +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/xldk50-be/XLDK32 TARGET_ARCHITECTURE:=armeb-broadcom-linux-uclibcgnueabi KERNDIR ?= $(TOOLCHAIN_BASE_DIR)/kernel/linux else -TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/iproc/XLDK +TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/xldk50/XLDK32 TARGET_ARCHITECTURE:= arm-broadcom-linux-uclibcgnueabi KERNDIR ?= $(TOOLCHAIN_BASE_DIR)/kernel/linux endif @@ -60,6 +60,8 @@ CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=0 ENDIAN = LE_HOST=1 endif +CFLAGS += -fno-aggressive-loop-optimizations + CFGFLAGS += -D$(ENDIAN) -DIPROC_CMICD CFGFLAGS += -DBCM_PLATFORM_STRING=\"IPROC_CMICD\" @@ -80,7 +82,7 @@ basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" modname_flags = $(if $(filter 1,$(words $(modname))),\ -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") -KFLAG_INCLD ?= $(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/lib/gcc/$(TARGET_ARCHITECTURE)/4.9.3/include +KFLAG_INCLD ?= $(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/lib/gcc/$(TARGET_ARCHITECTURE)/4.9.4/include ifeq (,$(KFLAGS)) KFLAGS := -D__LINUX_ARM_ARCH__=7 -D__KERNEL__ -nostdinc -isystem $(KFLAG_INCLD) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/generated/autoconf.h -I$(KERNDIR)/arch/arm/include -I$(KERNDIR)/arch/arm/include/generated -I$(KERNDIR)/arch/arm/mach-iproc/include -Wall -Wstrict-prototypes -Wno-trigraphs -Os -fno-strict-aliasing -fno-common -marm -mabi=aapcs-linux -fno-pic -pipe -msoft-float -ffreestanding -march=armv7-a -mfpu=vfp -mfloat-abi=softfp -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -mlong-calls diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-kmodule b/platform/broadcom/saibcm-modules/make/Makefile.linux-kmodule index 3ad11d169c..540c497ea2 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-kmodule +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-kmodule @@ -71,7 +71,7 @@ $(KMODULE): rm -f *.o *.ko .*.cmd rm -fr .tmp_versions ln -s $(LIBDIR)/$(MODULE) $(PRE_COMPILED_OBJ)_shipped - echo "suppress warning" > .$(PRE_COMPILED_OBJ).cmd + if [ ! -f $(KERNBLDDIR)/NO_SUPRESS ]; then echo "# suppress warning" > .$(PRE_COMPILED_OBJ).cmd; fi $(MAKE) -C $(KERNBLDDIR) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) modules if [ ! -f Module.symvers ]; then echo "old kernel (pre-2.6.17)" > Module.symvers; fi cp -f $(KMODULE) $(LIBDIR) diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-common-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-common-2_6 index 07af2afcc9..25e953136b 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-common-2_6 +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-common-2_6 @@ -22,7 +22,7 @@ ENDIAN = LE_HOST=1 CFGFLAGS += -D$(ENDIAN) CFGFLAGS += -DBCM_PLATFORM_STRING=\"X86\" ifeq (,$(findstring -DSAL_BDE_DMA_MEM_DEFAULT,$(CFGFLAGS))) -CFGFLAGS += -DSAL_BDE_DMA_MEM_DEFAULT=32 +CFGFLAGS += -DSAL_BDE_DMA_MEM_DEFAULT=16 endif # Extra variables. diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-generic-common-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-generic-common-2_6 index ab342c12d2..bf0ea85d57 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-generic-common-2_6 +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-generic-common-2_6 @@ -48,4 +48,4 @@ AUTOCONF = $(KERNDIR)/include/linux/autoconf.h endif # gcc system include path -SYSINC = $(shell gcc -print-search-dirs | grep install | cut -c 10-)include +SYSINC = $(shell $(CC) -print-search-dirs | grep install | cut -c 10-)include diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-smp_generic_64-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-smp_generic_64-2_6 index bb0bbea536..bc0230ec82 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-smp_generic_64-2_6 +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-smp_generic_64-2_6 @@ -43,4 +43,3 @@ KFLAGS += -I$(KERNDIR_COMMON)/include -I$(KERNDIR_COMMON)/include/uapi -I$(KERND endif include ${SDK}/make/Makefile.linux-x86-common-2_6 - diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux-bde.h b/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux-bde.h index 927201bc1f..bdf7a56dca 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux-bde.h +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux-bde.h @@ -222,7 +222,7 @@ extern int lkbde_dev_instid_set(int d, uint32 instid); extern int lkbde_irq_mask_set(int d, uint32 addr, uint32 mask, uint32 fmask); extern int lkbde_irq_mask_get(int d, uint32 *mask, uint32 *fmask); -#if (defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT)) +#ifdef BCM_SAND_SUPPORT extern int lkbde_cpu_write(int d, uint32 addr, uint32 *buf); extern int lkbde_cpu_read(int d, uint32 addr, uint32 *buf); extern int lkbde_cpu_pci_register(int d); @@ -241,15 +241,12 @@ extern int lkbde_cpu_pci_register(int d); */ #define LKBDE_IPROC_REG 0x4000 -#if defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) +#ifdef BCM_SAND_SUPPORT #include #if defined(__DUNE_LINUX_BCM_CPU_PCIE__) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) #ifndef _SIMPLE_MEMORY_ALLOCATION_ #define _SIMPLE_MEMORY_ALLOCATION_ 1 #endif -#ifndef USE_LINUX_BDE_MMAP -#define USE_LINUX_BDE_MMAP 1 -#endif #endif #endif @@ -271,13 +268,9 @@ extern int lkbde_cpu_pci_register(int d); #define _SIMPLE_MEMORY_ALLOCATION_ 9 /* compile in the allocation method, but do not use it by default */ #endif -/* By default we use our private mmap only if /dev/mem mmap has restrictions */ +/* By default we use our private mmap for DMA pool */ #ifndef USE_LINUX_BDE_MMAP -#ifdef CONFIG_STRICT_DEVMEM #define USE_LINUX_BDE_MMAP 1 -#else -#define USE_LINUX_BDE_MMAP 0 -#endif #endif #endif /* __KERNEL__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux_dma.h b/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux_dma.h index bfbbceb2d8..3bf7488abc 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux_dma.h +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux_dma.h @@ -58,7 +58,7 @@ #define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) #endif -extern void _dma_init(int robo_switch, int dev_index); +extern void _dma_init(int dev_index); extern int _dma_cleanup(void); extern void _dma_pprint(void); extern uint32_t *_salloc(int d, int size, const char *name); @@ -68,7 +68,7 @@ extern int _sflush(int d, void *ptr, int length); extern sal_paddr_t _l2p(int d, void *vaddr); extern void *_p2l(int d, sal_paddr_t paddr); extern int _dma_pool_allocated(void); -extern int _dma_range_valid(unsigned long phys_addr, unsigned long size); +extern int _dma_mmap(struct file *filp, struct vm_area_struct *vma); #endif /* __KERNEL__ */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/Makefile b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/Makefile index 3d504a5665..aedd487b1f 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/Makefile +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/Makefile @@ -33,33 +33,11 @@ LIBS = $(LIBDIR)/libkern.a BDE = linux-kernel-bde.o -ifdef ROBO_CHIPS -CFLAGS += -I$(ET_ROBO) -I${SDK}/include/shared/et -ET_ROBO = ${SDK}/systems/drv/et -endif - # need to add vpath sources -VPATH = ../shared $(ET_ROBO) +VPATH = ../shared # Add the srcs to be found by vpath LSRCS += mpool.c -ifdef ROBO_CHIPS -platformsplt = $(subst -, , ${platform}) # change hyphens to spaces -platformbase = $(word 1,${platformsplt}) - -ifeq ($(platformbase), keystone) - LSRCS += etc_robo_spi.c aiutils.c -else - ifeq ($(platformbase), keystone_le) - LSRCS += etc_robo_spi.c aiutils.c - else - ifeq ($(platformbase), iproc) - LSRCS += robo_srab.c robo_spi.c aiutils.c - endif - endif -endif # platformbase - -endif # ROBO_CHIPS # Add shared BDE sources VPATH += ../../shared diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux-kernel-bde.c b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux-kernel-bde.c index 1a04b2b52e..464a72bd3e 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux-kernel-bde.c +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux-kernel-bde.c @@ -35,30 +35,22 @@ #include "linux_shbde.h" -#ifdef BCM_ROBO_SUPPORT -/* robo/et related header files */ -#include -#include - -#if defined(KEYSTONE) -#include -#include -#include -#include -#elif defined(IPROC_CMICD) -#include -#include -#ifdef BCM_STARFIGHTER3_SUPPORT -#include -#endif -#include -#include -#else /* BCM4704 */ -#include -#include -#endif -#endif /* BCM_ROBO_SUPPORT */ +#ifdef __GNUC__ +#if __GNUC__ == 8 +/* + * Prevent gcc 8.1.10 using a compiler inline memcpy even if using -fno-builtin or + * -fno-builtin-memcpy . + * __inline_memcpy and __memcpy are kernel functions that may be used instead, + * for either an inline or non-inline implementations of the function + */ +#define MEMCPY __inline_memcpy +#else +#define MEMCPY memcpy +#endif /* __GNUC__ == 8 */ +#else /* ifdef __GNUC__ */ +#define MEMCPY memcpy +#endif /* ifdef __GNUC__ */ #define PCI_USE_INT_NONE (-1) #define PCI_USE_INT_INTX (0) @@ -108,26 +100,6 @@ int msixcnt = 1; #define PCI_DEVICE_ID_PLX_9056 0x9056 #endif -/* local defined device IDs, refer to bcmdevs.h */ -#ifndef BCM53000_GMAC_ID -#define BCM53000_GMAC_ID 0x4715 /* 53003 gmac id */ -#endif -#ifndef BCM53010_GMAC_ID -#define BCM53010_GMAC_ID 0x4715 /* 5301x gmac id */ -#endif -#ifndef BCM47XX_ENET_ID -#define BCM47XX_ENET_ID 0x4713 /* 4710 enet */ -#endif -#ifndef BCM53010_CHIP_ID -#define BCM53010_CHIP_ID 0xcf12 /* 53010 chipcommon chipid */ -#endif -#ifndef BCM53018_CHIP_ID -#define BCM53018_CHIP_ID 0xcf1a /* 53018 chipcommon chipid */ -#endif -#ifndef BCM53020_CHIP_ID -#define BCM53020_CHIP_ID 0xcf1e /* 53020 chipcommon chipid */ -#endif - /* For 2.4.x kernel support */ #ifndef IRQF_SHARED #define IRQF_SHARED SA_SHIRQ @@ -186,14 +158,6 @@ MODULE_PARM_DESC(spifreq, "Force SPI Frequency for Keystone CPU (0 for default frequency)"); #endif -#if defined(BCM_EA_SUPPORT) -#if defined(BCM_TK371X_SUPPORT) -static int eadevices; -LKM_MOD_PARAM(eadevices, "i", int, 0); -MODULE_PARM_DESC(eadevices, -"Number of TK371X devices"); -#endif /* */ -#endif /* BCM_EA_SUPPORT */ /* Compatibility */ #ifdef LKM_2_4 @@ -203,7 +167,7 @@ MODULE_PARM_DESC(eadevices, #define IRQ_HANDLED #define SYNC_IRQ(_i) synchronize_irq() #else /* LKM_2_6 */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) #define _ISR_RET irqreturn_t #else #define _ISR_RET int @@ -212,6 +176,7 @@ MODULE_PARM_DESC(eadevices, #define _ISR_PARAMS(_i,_d,_r) int _i, void *_d #else #define _ISR_PARAMS(_i,_d,_r) int _i, void *_d, struct pt_regs *_r +typedef irqreturn_t (*irq_handler_t)(int _i, void *_d, struct pt_regs *_r); #endif #define SYNC_IRQ(_i) synchronize_irq(_i) char * ___strtok; @@ -364,7 +329,6 @@ static int _ndevices = 0; static int _switch_ndevices = 0; static int _ether_ndevices = 0; static int _cpu_ndevices = 0; -static int robo_switch = 0; #define VALID_DEVICE(_n) ((_n >= 0) && (_n < _ndevices)) @@ -375,48 +339,10 @@ static uint32 iproc_cmicx_irqs[IHOST_CMICX_MAX_INTRS]; #endif /* CPU MMIO area used with CPU cards provided on demo boards */ -#if (defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT)) && (defined(__DUNE_WRX_BCM_CPU__) || defined(__DUNE_GTO_BCM_CPU__)) +#if defined(BCM_SAND_SUPPORT) && (defined(__DUNE_WRX_BCM_CPU__) || defined(__DUNE_GTO_BCM_CPU__)) static void *cpu_address = NULL; #endif -#ifdef BCM_ROBO_SUPPORT - -/* for SPI access via bcm4710 core */ -static void *robo = NULL; -static void *sbh = NULL; - -#ifdef ALTA_ROBO_SPI - -extern void *alta_eth_spi_ctrl; - -extern int -robo_spi_read(void *cookie, uint16_t reg, uint8_t *buf, int len); - -extern int -robo_spi_write(void *cookie, uint16_t reg, uint8_t *buf, int len); - -#define ROBO_RREG(_robo, _dev, _page, _reg, _buf, _len) \ - robo_spi_read(_dev ? NULL : alta_eth_spi_ctrl, \ - (_page << 8) | (_reg), _buf, _len) -#define ROBO_WREG(_robo, _dev, _page, _reg, _buf, _len) \ - robo_spi_write(_dev ? NULL : alta_eth_spi_ctrl, \ - (_page << 8) | (_reg), _buf, _len) - -#else /* !ALTA_ROBO_SPI */ - -#if defined(KEYSTONE) || defined(IPROC_CMICD) -#define ROBO_RREG(_robo, _dev, _page, _reg, _buf, _len) \ - robo_rreg(_robo, _dev, _page, _reg, _buf, _len) -#define ROBO_WREG(_robo, _dev, _page, _reg, _buf, _len) \ - robo_wreg(_robo, _dev, _page, _reg, _buf, _len) -#else -#define ROBO_RREG(_robo, _dev, _page, _reg, _buf, _len) -#define ROBO_WREG(_robo, _dev, _page, _reg, _buf, _len) -#endif - -#endif /* ALTA_ROBO_SPI */ - -#endif /* BCM_ROBO_SUPPORT */ /* Broadcom BCM4704 */ #define BCM4704_VENDOR_ID 0x14E4 @@ -500,6 +426,17 @@ robo_spi_write(void *cookie, uint16_t reg, uint8_t *buf, int len); #define BCM58712_PCI_VENDOR_ID 0x14E4 #define BCM58712_PCI_DEVICE_ID 0x168E +/* Default gicd address if not available in DTB */ +#define IHOST_GICD_REG_ADDR 0x10781100 +#define IHOST_GICD_REG_REMAP_LEN 0x100 + +#define IHOST_GICD_REG_ADDR_VALID(d, addr) \ + (_devices[d].bde_dev.base_address1 && \ + (addr & 0xFFFFFF00) == _devices[d].phys_address1) + +#define IHOST_GICD_REG_ADDR_REMAP(d, addr) \ + (void *)(_devices[d].bde_dev.base_address1 + (addr - _devices[d].phys_address1)) + static uint32_t _read(int d, uint32_t addr); #ifdef BCM_ICS @@ -551,6 +488,19 @@ _parse_eb_args(char *str, char * format, ...) static void _bde_add_device(void) { + int add_switch_device = 0; + if (_devices[_ndevices].dev_type & BDE_SWITCH_DEV_TYPE) { + _switch_ndevices++; + add_switch_device = 1; + } else if (_devices[_ndevices].dev_type & BDE_ETHER_DEV_TYPE) { + _ether_ndevices++; + } else if (_devices[_ndevices].dev_type & BDE_CPU_DEV_TYPE) { + _cpu_ndevices++; + } else { + return; + } + _ndevices++; + /* * In order to be backward compatible with the user mode BDE * (specifically the interrupt IOCTLs) and the CM, switch devices @@ -558,7 +508,7 @@ _bde_add_device(void) * order), we let the non-switch device(s) drop down to the end of * the device array. */ - if (_switch_ndevices > 0) { + if (add_switch_device) { bde_ctrl_t tmp_dev; int i, s = 0; @@ -573,13 +523,12 @@ _bde_add_device(void) } _devices[i] = tmp_dev; } + + _dma_init(_switch_ndevices-1); } - /* Initialize device locks and dma */ - if (_ndevices > 0) { - spin_lock_init(&_devices[_ndevices-1].lock); - _dma_init(robo_switch, _ndevices-1); - } + /* Initialize device locks */ + spin_lock_init(&_devices[_ndevices-1].lock); } static int @@ -590,8 +539,7 @@ _eb_device_create(resource_size_t paddr, int irq, int rd_hw, int wr_hw) dev_id = _ndevices; - ctrl = _devices + _ndevices++; - _switch_ndevices++; + ctrl = _devices + _ndevices; ctrl->dev_type |= BDE_EB_DEV_TYPE | BDE_SWITCH_DEV_TYPE; ctrl->pci_device = NULL; /* No PCI bus */ @@ -617,15 +565,15 @@ _eb_device_create(resource_size_t paddr, int irq, int rd_hw, int wr_hw) ctrl->isr = NULL; ctrl->isr_data = NULL; - _bde_add_device(); - gprintk("Created EB device at BA=%x IRQ=%d RD16=%d WR16=%d device=0x%x\n", (unsigned int)paddr, irq, rd_hw, wr_hw, ctrl->bde_dev.device); + _bde_add_device(); + return 0; } -#if defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT) +#ifdef BCM_SAND_SUPPORT #include @@ -637,9 +585,6 @@ sand_device_create(void) ctrl = _devices; /* FIX_ME: on petra, take first device */ #ifndef __DUNE_LINUX_BCM_CPU_PCIE__ - _switch_ndevices++; - _ndevices++; - ctrl->dev_type |= BDE_PCI_DEV_TYPE | BDE_SWITCH_DEV_TYPE; ctrl->pci_device = NULL; /* No PCI bus */ @@ -677,7 +622,7 @@ sand_device_create(void) return 0; } -#endif +#endif /* BCM_SAND_SUPPORT */ #ifdef IPROC_CMICD static void @@ -739,8 +684,7 @@ iproc_cmicd_probe(struct platform_device *pldev) } size = memres->end - memres->start + 1; - ctrl = _devices + _ndevices++; - _switch_ndevices++; + ctrl = _devices + _ndevices; ctrl->dev_type = BDE_AXI_DEV_TYPE | BDE_SWITCH_DEV_TYPE | BDE_256K_REG_SPACE; ctrl->pci_device = NULL; /* No PCI bus */ @@ -764,6 +708,24 @@ iproc_cmicd_probe(struct platform_device *pldev) ctrl->bde_dev.device = readl(icfg_chip_id) & 0xffff; ctrl->bde_dev.rev = readl(icfg_chip_id+1) & 0xff; iounmap(icfg_chip_id); + /* Map GICD block in the AXI memory space into CPU address space */ + memres = iproc_platform_get_resource(pldev, IORESOURCE_MEM, 1); + if (memres) { + ctrl->bde_dev.base_address1 = (sal_vaddr_t)IOREMAP(memres->start, memres->end - memres->start + 1); + ctrl->phys_address1 = memres->start; + } else { + /* Use default address if not available in DTB */ + ctrl->bde_dev.base_address1 = (sal_vaddr_t)IOREMAP(IHOST_GICD_REG_ADDR, IHOST_GICD_REG_REMAP_LEN); + ctrl->phys_address1 = IHOST_GICD_REG_ADDR; + } + if (ctrl->bde_dev.base_address1) { + if (debug >= 1) { + gprintk("base_address1:0x%lx phys_address1:0x%lx\n", + (unsigned long)ctrl->bde_dev.base_address1, (unsigned long)ctrl->phys_address1); + } + } else { + gprintk("Error mapping ihost GICD registers\n"); + } } else #endif { @@ -777,6 +739,7 @@ iproc_cmicd_probe(struct platform_device *pldev) ctrl->bde_dev.device = dev_rev_id & 0xffff; ctrl->bde_dev.rev = (dev_rev_id >> 16) & 0xff; #endif + ctrl->bde_dev.base_address1 = 0; } #ifdef CONFIG_OF @@ -901,10 +864,6 @@ iproc_has_cmicd(void) /* Only allowed accessing CMICD module if the SOC has it */ switch (cca_cid) { - case BCM53010_CHIP_ID: - case BCM53018_CHIP_ID: - case BCM53020_CHIP_ID: - return 0; default: break; } @@ -1052,8 +1011,7 @@ _ics_bde_create(void) resource_size_t paddr; if (_ndevices == 0) { - ctrl = _devices + _ndevices++; - _switch_ndevices++; + ctrl = _devices + _ndevices; ctrl->dev_type |= BDE_ICS_DEV_TYPE | BDE_SWITCH_DEV_TYPE; ctrl->pci_device = NULL; /* No PCI bus */ @@ -1072,8 +1030,8 @@ _ics_bde_create(void) ctrl->isr = NULL; ctrl->isr_data = NULL; - _bde_add_device(); printk("Created ICS device ..%x\n", ctrl->bde_dev.base_address); + _bde_add_device(); } return 0; @@ -1248,7 +1206,6 @@ static const struct pci_device_id _id_table[] = { { BROADCOM_VENDOR_ID, BCM56150_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56151_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56152_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { BROADCOM_VENDOR_ID, BCM56613_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56930_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56931_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56935_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, @@ -1301,14 +1258,6 @@ static const struct pci_device_id _id_table[] = { { BROADCOM_VENDOR_ID, BCM56044_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56045_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56046_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { BROADCOM_VENDOR_ID, BCM88230_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { BROADCOM_VENDOR_ID, BCM88030_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { BROADCOM_VENDOR_ID, BCM88034_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { BROADCOM_VENDOR_ID, BCM88039_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { BROADCOM_VENDOR_ID, BCM88231_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { BROADCOM_VENDOR_ID, BCM88235_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { BROADCOM_VENDOR_ID, BCM88236_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { BROADCOM_VENDOR_ID, BCM88239_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM55440_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56440_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56441_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, @@ -1450,15 +1399,6 @@ static const struct pci_device_id _id_table[] = { { BROADCOM_VENDOR_ID, BCM56174_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM53570_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM53575_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, -#ifdef BCM_ROBO_SUPPORT - { BROADCOM_VENDOR_ID, BCM47XX_ENET_ID, PCI_ANY_ID, PCI_ANY_ID }, -#ifdef KEYSTONE - { BROADCOM_VENDOR_ID, BCM53000_GMAC_ID, PCI_ANY_ID, PCI_ANY_ID }, -#endif -#endif - { SANDBURST_VENDOR_ID, QE2000_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { SANDBURST_VENDOR_ID, BCM88020_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { SANDBURST_VENDOR_ID, BCM88025_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9656, PCI_ANY_ID, PCI_ANY_ID }, { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9056, PCI_ANY_ID, PCI_ANY_ID }, { BCM53000_VENDOR_ID, BCM53000PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, @@ -1506,6 +1446,7 @@ static const struct pci_device_id _id_table[] = { { BROADCOM_VENDOR_ID, BCM88270_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88272_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88273_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88274_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88278_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88279_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, @@ -1524,7 +1465,6 @@ static const struct pci_device_id _id_table[] = { { BROADCOM_VENDOR_ID, BCM88685_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88380_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88381_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { BROADCOM_VENDOR_ID, BCM88690_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88202_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88360_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88361_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, @@ -1537,6 +1477,25 @@ static const struct pci_device_id _id_table[] = { { BROADCOM_VENDOR_ID, BCM88661_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88664_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, #endif +#ifdef BCM_DNX_SUPPORT + { BROADCOM_VENDOR_ID, BCM88690_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88690_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88691_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88692_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88693_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88694_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88695_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88696_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88697_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88698_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88699_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8869A_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8869B_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8869C_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8869D_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8869F_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88800_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, +#endif /* BCM_DNX_SUPPORT */ #ifdef BCM_DFE_SUPPORT { BROADCOM_VENDOR_ID, BCM88750_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88753_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, @@ -2083,24 +2042,20 @@ _msi_connect(bde_ctrl_t *ctrl) #else ret = pci_enable_msix(ctrl->pci_device, ctrl->entries, ctrl->msix_cnt); -#endif if (ret > 0) { /* Not enough vectors available , Retry MSI-X */ gprintk("Retrying with MSI-X interrupts = %d\n", ret); ctrl->msix_cnt = ret; msixcnt = ret; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0) - ret = pci_enable_msix_range(ctrl->pci_device, - ctrl->entries, ctrl->msix_cnt, ctrl->msix_cnt); -#else ret = pci_enable_msix(ctrl->pci_device, ctrl->entries, ctrl->msix_cnt); -#endif if (ret != 0) goto er_intx_free; - } else if (ret < 0) { - /* Error */ - goto er_intx_free; + } +#endif + if (ret < 0) { + /* Error */ + goto er_intx_free; } else { gprintk("Enabled MSI-X interrupts = %d\n", ctrl->msix_cnt); return 0; @@ -2228,13 +2183,12 @@ _pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) int cmic_bar; int baroff = 0; int iproc = 0; - uint32 gmac_base = 0; int plx_dev = 0; int eth_dev = 0; int cpu_dev = 0; int update_devid = 0; int paxb_core = 0; - int rescan = 0, rescan_idx = -1; + int add_dev = 0, rescan = 0, rescan_idx = -1; shbde_hal_t shared_bde, *shbde = &shared_bde; if (debug >= 4) {gprintk("probing: vendor_id=0x%x, device_id=0x%x\n", dev->vendor, dev->device);} @@ -2280,17 +2234,6 @@ _pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) case PCI_DEVICE_ID_PLX_9656: plx_dev = 1; break; -#if defined (BCM_ROBO_SUPPORT) && defined(KEYSTONE) - case BCM53000_GMAC_ID: - eth_dev = 1; - gmac_base = SB_ENUM_BASE; - break; -#endif -#if defined (BCM_ROBO_SUPPORT) - case BCM47XX_ENET_ID: - eth_dev = 1; - break; -#endif case BCM53000PCIE_DEVICE_ID: cpu_dev = 1; break; @@ -2332,10 +2275,10 @@ _pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) if (_ether_ndevices >= LINUX_BDE_MAX_ETHER_DEVICES) { return 0;; } - ctrl = _devices + _ndevices++; - _ether_ndevices++; + ctrl = _devices + _ndevices; ctrl->dev_type |= BDE_ETHER_DEV_TYPE; ctrl->iLine = dev->irq; + add_dev = 1; if (debug >= 1) gprintk("Found PCI device %04x:%04x as Ethernet device\n", dev->vendor, dev->device); @@ -2343,9 +2286,9 @@ _pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) if (_cpu_ndevices >= LINUX_BDE_MAX_CPU_DEVICES) { return 0;; } - ctrl = _devices + _ndevices++; - _cpu_ndevices++; + ctrl = _devices + _ndevices; ctrl->dev_type |= BDE_CPU_DEV_TYPE; + add_dev = 1; if (debug >= 1) gprintk("Found PCI device %04x:%04x as CPU device\n", dev->vendor, dev->device); @@ -2365,16 +2308,16 @@ _pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) ctrl = _devices + rescan_idx; ctrl->dev_state = BDE_DEV_STATE_CHANGED; } else { - ctrl = _devices + _ndevices++; - _switch_ndevices++; + ctrl = _devices + _ndevices; ctrl->dev_type |= BDE_SWITCH_DEV_TYPE; ctrl->domain_no = pci_domain_nr(dev->bus); ctrl->bus_no = dev->bus->number; ctrl->dev_state = BDE_DEV_STATE_NORMAL; + add_dev = 1; } /* Save shared BDE HAL in device structure */ - memcpy(&ctrl->shbde, shbde, sizeof(ctrl->shbde)); + MEMCPY(&ctrl->shbde, shbde, sizeof(ctrl->shbde)); if (update_devid) { /* Re-read the device ID */ @@ -2675,43 +2618,9 @@ _pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) } /* Save shared BDE HAL in device structure */ - memcpy(&ctrl->shbde, shbde, sizeof(ctrl->shbde)); + MEMCPY(&ctrl->shbde, shbde, sizeof(ctrl->shbde)); - /* - * Since the GMAC driver of Robo chips needs access to the - * ChipCommon and Wrapper registers, we set the base address - * as the enumeration base address and its size as 3MB to - * cover all Wrapper register regions. - */ - if (gmac_base) { - uint32_t offset; - - ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(gmac_base, 0x300000); - - /* Record the base address of GMAC core */ - offset = ctrl->phys_address - gmac_base; - ctrl->alt_base_addr = ctrl->bde_dev.base_address + offset; - ctrl->phys_address = gmac_base; - } - - /* - * Workaround bug in FE2K A1 part; shows as A0 part in PCI config space, - * read the FE's regs directly to get the true revision - */ - if (ctrl->bde_dev.device == BCM88020_DEVICE_ID && ctrl->bde_dev.rev == 0) { -#define FE2000_REVISION_OFFSET (0x0) - uint32_t fe_rev; - - fe_rev = *((uint32_t*)(ctrl->bde_dev.base_address + FE2000_REVISION_OFFSET)); - if ((fe_rev >> 16) == BCM88020_DEVICE_ID) { - fe_rev &= 0xff; - } else { - fe_rev = (fe_rev >> 24) & 0xff; - } - ctrl->bde_dev.rev = fe_rev; - } - ctrl->isr = NULL; ctrl->isr_data = NULL; @@ -2732,28 +2641,21 @@ _pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) if (debug >= 1) gprintk("PCI resource len 8MB\n"); } -#if defined (BCM_ROBO_SUPPORT) && !defined(ALTA_ROBO_SPI) - /* MDC/MDIO path for pseudo PHY access to ROBO register on BCM5836/4704 */ - if (dev->device == BCM47XX_ENET_ID) { - ((uint32 *)ctrl->bde_dev.base_address)[0x410 / 4] = 0; - } -#endif #ifdef LINUX_BDE_DMA_DEVICE_SUPPORT ctrl->dma_dev = &dev->dev; #endif - if (!rescan) { - _bde_add_device(); - } - if (debug >= 2) { gprintk("_pci_probe: configured dev:0x%x rev:0x%x with base_addresses: 0x%lx 0x%lx\n", (unsigned)ctrl->bde_dev.device, (unsigned)ctrl->bde_dev.rev, (unsigned long)ctrl->bde_dev.base_address, (unsigned long)ctrl->bde_dev.base_address1); } - /* Let's boogie */ + if (add_dev) { + _bde_add_device(); + } + /* Let's boogie */ return 0; } @@ -2833,8 +2735,7 @@ static struct pci_driver _device_driver = { static void _spi_device_setup(void) { bde_ctrl_t *ctrl; - ctrl = _devices + _ndevices++; - _switch_ndevices++; + ctrl = _devices + _ndevices; ctrl->dev_type |= BDE_SWITCH_DEV_TYPE; ctrl->iLine = 0xa3; ctrl->be_pio = 0; @@ -2846,483 +2747,12 @@ _spi_device_setup(void) { gprintk("SPI Slave Mode: force ctrl->bde_dev.rev=0x%x\n",ctrl->bde_dev.rev); gprintk("SPI Slave Mode: force ctrl->dev_type=0x%x\n",ctrl->dev_type); } + _bde_add_device(); } #endif /* BCM_ICS */ -#ifdef BCM_ROBO_SUPPORT -#ifdef KEYSTONE -#define DEFAULT_FREQ (SPI_FREQ_DEFAULT) -#define FREQ_20MHZ (SPI_FREQ_20MHZ) -#else /* IPROC_CMICD */ -#define DEFAULT_FREQ (0) -#define FREQ_20MHZ (0) -#endif - - -/* -* The model_info /rev_info for Robo devices is defined like this: -* -* 31 28 27 24 23 20 19 16 15 8 7 0 -* +----+---------+------+-----+---------+--------+ -* | op | reserved| mask |len | page |offset | -* +----+---------+------+-----+---------+--------+ -* -* op: 1:OR phyidl, 2: use PCIE device ID -* mlen: mask len (in bytes) 1:means 0xf,2 means 0xff -* len: Size of model/rev ID register (in bytes) -* page: Page containing model ID and revision registers -* offset: Model/rev ID register offset -*/ -static struct bde_spi_device_id _spi_id_table[] = { - { BCM53242_PHYID_HIGH, BCM53242_PHYID_LOW , 0, 0, DEFAULT_FREQ}, - { BCM53262_PHYID_HIGH, BCM53262_PHYID_LOW , 0, 0, DEFAULT_FREQ}, - { BCM53115_PHYID_HIGH, BCM53115_PHYID_LOW , 0, 0, DEFAULT_FREQ}, - { BCM53118_PHYID_HIGH, BCM53118_PHYID_LOW , 0, 0, DEFAULT_FREQ}, - { BCM53280_PHYID_HIGH, BCM53280_PHYID_LOW , 0x101800e8, 0, FREQ_20MHZ}, - { BCM53101_PHYID_HIGH, BCM53101_PHYID_LOW , 0, 0x110240, FREQ_20MHZ}, - { BCM53125_PHYID_HIGH, BCM53125_PHYID_LOW , 0, 0x110240, FREQ_20MHZ}, - { BCM53128_PHYID_HIGH, BCM53128_PHYID_LOW , 0, 0x110240, FREQ_20MHZ}, - { BCM53600_PHYID_HIGH, BCM53600_PHYID_LOW , 0x101800e8, 0, FREQ_20MHZ}, - { BCM89500_PHYID_HIGH, BCM89500_PHYID_LOW ,0x240230, 0x110240, FREQ_20MHZ}, - { BCM53010_PHYID_HIGH, BCM53010_PHYID_LOW ,0x240230, 0x110240, 0}, - { BCM53018_PHYID_HIGH, BCM53018_PHYID_LOW ,0x240230, 0x110240, 0}, - { BCM5389_PHYID_HIGH, BCM5389_PHYID_LOW, 0x110230, 0x110240, DEFAULT_FREQ}, - { BCM53020_PHYID_HIGH, BCM53020_PHYID_LOW ,0x20240230, 0x110240, 0}, - { BCM5396_PHYID_HIGH , BCM5396_PHYID_LOW, 0x110230, 0x110240, DEFAULT_FREQ}, - { BCM53134_PHYID_HIGH, BCM53134_PHYID_LOW , 0, 0x110240, DEFAULT_FREQ}, - { 0, 0, 0, 0, 0 }, -}; -#endif - -#ifdef BCM_ROBO_SUPPORT - -static int -_spi_device_valid_check(unsigned short phyidh,unsigned short phyidl, uint8 check_flag) -{ - struct bde_spi_device_id *_ids; - int idx, match_idx; - - match_idx = -1; - idx = 0; - - if (check_flag == 0){ - /* check_flag == 0 check phyidh only*/ - for (_ids = _spi_id_table; - _ids->phyid_high && _ids->phyid_low; _ids++){ - if (_ids->phyid_high == phyidh) { - return 0; - } - } - /* No valid SPI devices found */ - return 1; - } else { - while(_spi_id_table[idx].phyid_high){ - if (phyidh == _spi_id_table[idx].phyid_high && - phyidl == _spi_id_table[idx].phyid_low) { - /* Found a match */ - match_idx = idx; - break; - } - idx++; - } - return match_idx; - } -} - -#if defined(IPROC_CMICD) || defined(KEYSTONE) -#define ROBO_ATTACH_AVAIL -#endif - -#ifdef ROBO_ATTACH_AVAIL - -#define SOC_ATTACH(_sc)\ - ai_soc_kattach(_sc) - -#if defined(IPROC_CMICD) -#ifdef BCM_STARFIGHTER3_SUPPORT -#define ROBO_ATTACH_SPI(_sih, _ss)\ - robo_attach_spi(_sih) -#define ROBO_DETACH_SPI(robo)\ - robo_detach_spi(robo) -#define ROBO_SPI_RREG(_robo, _dev, _page, _reg, _buf, _len) \ - robo_spi_rreg(_robo, _dev, _page, _reg, _buf, _len) -#define ROBO_SPI_WREG(_robo, _dev, _page, _reg, _buf, _len) \ - robo_spi_wreg(_robo, _dev, _page, _reg, _buf, _len) -#endif -#define ROBO_ATTACH(_sih, _ss)\ - robo_attach(_sih) -#define MAX_BUSTYPE 1 -#define ROBO_SWITCH_BUS(_robo, _bustype) -#define ROBO_SELECT_DEVICE(_robo, _phyidh, _phyidl) -#else /* KEYSTONE */ -#define ROBO_ATTACH(_sih, _ss)\ - robo_attach(_sih, _ss) -/* bustype 2: ROBO_MDCMDIO_BUS, 1: ROBO_SPI_BUS */ -#define MAX_BUSTYPE 2 -#define ROBO_SWITCH_BUS(_robo, _bustype)\ - robo_switch_bus(_robo, _bustype) - -#define ROBO_SELECT_DEVICE(_robo, _phyidh, _phyidl) \ - robo_select_device(_robo, _phyidh, _phyidl) -#endif - -#else - -#define SOC_ATTACH(_sc) (NULL) -#define ROBO_ATTACH(_sih, _ss) (NULL) -#define MAX_BUSTYPE (0) -#define ROBO_SWITCH_BUS(_robo, _bustype) -#define ROBO_SELECT_DEVICE(_robo, _phyidh, _phyidl) -#endif - - -#if defined(IPROC_CMICD) && defined(BCM_STARFIGHTER3_SUPPORT) -static int -probe_robo_switch_iproc_spi(void) -{ - int dev; - int max_devices, max_bustype; - uint8 buf[8]; - unsigned short phyidh = 0, phyidl = 0; - - - /* Get Robo device handle */ - if (robo == NULL) { - robo = (void *)ROBO_ATTACH_SPI(sbh, 0); - } - if (robo == NULL) { - return -ENODEV; - } - - max_bustype = MAX_BUSTYPE + 1; - - while(_spi_device_valid_check(phyidh, 0, 0)) { - max_bustype --; - if(!max_bustype) - return -ENODEV; - buf[0] = buf[1] = 0; - ROBO_SPI_RREG(robo, 0, 0x10, 0x04, buf, (uint)2); - phyidh = buf[0] | (buf[1] << 8); - /* re-try */ - if ((phyidh == 0x0) || (phyidh == 0xffff)) { - ROBO_SPI_RREG(robo, 0, 0x10, 0x04, buf, (uint)2); - phyidh = buf[0] | (buf[1] << 8); - } - } - - /* For psedo_phy access, only support one robo switch*/ - /* For Northstar, only one switch on SRAB interface */ - max_devices = (max_bustype == MAX_BUSTYPE) ? 1 : LINUX_BDE_MAX_SWITCH_DEVICES; - - for (dev = 0; dev < max_devices; dev++) { - bde_ctrl_t *ctrl; - int match_idx, i; - unsigned short phyidl_nr; /* phyidl with revision stripped */ - uint16 model_id; - uint8 rev_id; - uint32 addr, len; - uint32 mlen; - - if (_switch_ndevices >= LINUX_BDE_MAX_SWITCH_DEVICES) { - break; - } - buf[0] = buf[1] = 0; - ROBO_SPI_RREG(robo, dev, 0x10, 0x04, buf, (uint)2); - phyidh = buf[0] | (buf[1] << 8); - - buf[0] = buf[1] = 0; - ROBO_SPI_RREG(robo, dev, 0x10, 0x06, buf, (uint)2); - phyidl = buf[0] | (buf[1] << 8); - - /* Strip revision */ - phyidl_nr = phyidl & 0xfff0; - - match_idx = _spi_device_valid_check(phyidh, phyidl_nr, 1); - if (match_idx == -1) { - if (debug >= 1) gprintk("found %d robo device(s).\n", robo_switch); - break; - } - - model_id = phyidl_nr; - - if(_spi_id_table[match_idx].rev_info){ - addr = _spi_id_table[match_idx].rev_info & 0xffff; - len = (_spi_id_table[match_idx].rev_info >> 16) & 0xf; - ROBO_SPI_RREG(robo, dev, (addr >> 8), (addr & 0xff), buf, (uint)len); - mlen = (_spi_id_table[match_idx].rev_info >> 20) & 0xf; - rev_id = 0; - for (i = 0; i < mlen; i++) - rev_id |= buf[i] << (i << 3); - } else { - rev_id = phyidl & 0xf; - } - - gprintk("found robo device with %d:%04x:%04x:%04x:%02x\n", - dev, phyidh, phyidl, model_id, rev_id); - - ROBO_SELECT_DEVICE(robo, phyidh, phyidl); - - /* Match supported chips */ - ctrl = _devices + _ndevices++; - _switch_ndevices++; - - if (NULL == (ctrl->spi_device = (struct spi_dev *) - KMALLOC(sizeof(struct spi_dev), GFP_KERNEL))) { - gprintk("no memory available"); - return -ENOMEM; - } - ctrl->dev_type = (BDE_SPI_DEV_TYPE | BDE_SWITCH_DEV_TYPE); - ctrl->spi_device->cid = dev; - ctrl->spi_device->part = model_id; - ctrl->spi_device->rev = rev_id; - ctrl->spi_device->robo = robo; - ctrl->spi_device->phyid_high = phyidh; - ctrl->spi_device->phyid_low = phyidl; - ctrl->bde_dev.device = model_id; - ctrl->bde_dev.rev = rev_id; - ctrl->bde_dev.base_address = (sal_vaddr_t)NULL; - ctrl->isr = NULL; - ctrl->isr_data = NULL; - robo_switch++; - _bde_add_device(); - - } - - return robo_switch; - -} - -int spi_device_found = 0; - -#endif /* IPROC_CMICD || SF3 */ - - -static int -probe_robo_switch(void) -{ - int dev; - int max_devices, max_bustype; - uint8 buf[8]; - unsigned short phyidh = 0, phyidl = 0; -#if defined(KEYSTONE) - uint32 spi_freq = 0; -#endif -#if defined(IPROC_CMICD) - sal_vaddr_t addr_base; - uint32 data_reg; -#endif /* IPROC_CMICD */ - - - spin_lock_init(&bus_lock); - - if (_switch_ndevices) { - /* - * Currently skip probe robo if esw chips were found - * FIX this while combined plateform support. - */ - return robo_switch; - } - - /* Get Robo device handle */ - if (robo == NULL) { - sbh = (void *)SOC_ATTACH(NULL); - if (sbh == NULL) { - return -ENODEV; - } - } - -#if defined(IPROC_CMICD) && defined(BCM_STARFIGHTER3_SUPPORT) - robo_switch = probe_robo_switch_iproc_spi(); - - if (robo_switch > 0) { - /* Robo switch found by SPI probe */ - spi_device_found = 1; - gprintk("SPI device found, Skipping SRAB probe\n"); - return robo_switch; - } else { - gprintk("SPI device NOT found, Probe SRAB probe\n"); - ROBO_DETACH_SPI(robo); - } -#endif - - if (robo == NULL) { - robo = (void *)ROBO_ATTACH(sbh, 0); - } - if (robo == NULL) { - return -ENODEV; - } - - max_bustype = MAX_BUSTYPE + 1; - - while(_spi_device_valid_check(phyidh, 0, 0)) { - max_bustype --; - if(!max_bustype) - return -ENODEV; - ROBO_SWITCH_BUS(robo, max_bustype); - buf[0] = buf[1] = 0; - ROBO_RREG(robo, 0, 0x10, 0x04, buf, (uint)2); - phyidh = buf[0] | (buf[1] << 8); - /* re-try */ - if ((phyidh == 0x0) || (phyidh == 0xffff)) { - ROBO_RREG(robo, 0, 0x10, 0x04, buf, (uint)2); - phyidh = buf[0] | (buf[1] << 8); - } - } - - /* For psedo_phy access, only support one robo switch*/ - /* For Northstar, only one switch on SRAB interface */ - max_devices = (max_bustype == MAX_BUSTYPE) ? 1 : LINUX_BDE_MAX_SWITCH_DEVICES; - - for (dev = 0; dev < max_devices; dev++) { - bde_ctrl_t *ctrl; - int match_idx, i; - unsigned short phyidl_nr; /* phyidl with revision stripped */ - uint16 model_id; - uint8 rev_id; -#if defined(KEYSTONE) || defined(IPROC_CMICD) - uint32 addr, len; -#endif - uint32 mlen, op; - - if (_switch_ndevices >= LINUX_BDE_MAX_SWITCH_DEVICES) { - break; - } - buf[0] = buf[1] = 0; - ROBO_RREG(robo, dev, 0x10, 0x04, buf, (uint)2); - phyidh = buf[0] | (buf[1] << 8); - - buf[0] = buf[1] = 0; - ROBO_RREG(robo, dev, 0x10, 0x06, buf, (uint)2); - phyidl = buf[0] | (buf[1] << 8); - - /* Strip revision */ - phyidl_nr = phyidl & 0xfff0; - - match_idx = _spi_device_valid_check(phyidh, phyidl_nr, 1); - if (match_idx == -1) { - if (debug >= 1) gprintk("found %d robo device(s).\n", robo_switch); - break; - } - - if(_spi_id_table[match_idx].model_info){ -#if defined(KEYSTONE) || defined(IPROC_CMICD) - addr = _spi_id_table[match_idx].model_info & 0xffff; - len = (_spi_id_table[match_idx].model_info >> 16) & 0xf; -#endif - ROBO_RREG(robo, dev, (addr >> 8), (addr & 0xff), buf, (uint)len); - mlen = (_spi_id_table[match_idx].model_info >> 20) & 0xf; - model_id = 0; - for (i = 0; i < mlen; i++) - model_id |= buf[i] << (i << 3); - op = (_spi_id_table[match_idx].model_info >> 28) & 0xf; - if(op == 1) { - model_id |= phyidl_nr; -#if defined(IPROC_CMICD) - } else if (op == 2) { - /* The package id of NS+ is determined by : - * Write 0 to 0x18012120 (PAXB_0_CONFIG_IND_ADDR) - * Read 0x18012124 (PAX_B_CONFIG_IND_DATA), - * bits 31:16 will be the device id from OTP space - */ -#define PAXB_ENUM_BASE (0x18012000) -#define PAXB_CONFIG_IND_ADDR_OFFSET (0x120) -#define PAXB_CONFIG_IND_DATA_OFFSET (0x124) - - addr_base = (sal_vaddr_t)IOREMAP(PAXB_ENUM_BASE, 0x1000); - if (!addr_base) { - gprintk("ioremap of PAXB registers failed\n"); - } else { - writel(0x0, (uint32 *)(addr_base + - PAXB_CONFIG_IND_ADDR_OFFSET)); - data_reg = readl((uint32 *)(addr_base + - PAXB_CONFIG_IND_DATA_OFFSET)); - model_id = (data_reg >> 16); - iounmap((void *)addr_base); - - /* - * Some model ID can't be determined by PCIE device ID - * It needs to refer some OTP values. - */ - robo_model_id_adjust_from_otp(robo, &model_id); - } - -#undef PAXB_ENUM_BASE -#undef PAXB_CONFIG_IND_ADDR_OFFSET -#undef PAXB_CONFIG_IND_DATA_OFFSET -#endif /* IPROC_CMICD */ - } - } else { - model_id = phyidl_nr; - } - if(_spi_id_table[match_idx].rev_info){ -#if defined(KEYSTONE) || defined(IPROC_CMICD) - addr = _spi_id_table[match_idx].rev_info & 0xffff; - len = (_spi_id_table[match_idx].rev_info >> 16) & 0xf; -#endif - ROBO_RREG(robo, dev, (addr >> 8), (addr & 0xff), buf, (uint)len); - mlen = (_spi_id_table[match_idx].rev_info >> 20) & 0xf; - rev_id = 0; - for (i = 0; i < mlen; i++) - rev_id |= buf[i] << (i << 3); - } else { - rev_id = phyidl & 0xf; - } - gprintk("found robo device with %d:%04x:%04x:%04x:%02x\n", - dev, phyidh, phyidl, model_id, rev_id); - - ROBO_SELECT_DEVICE(robo, phyidh, phyidl); - - /* Match supported chips */ - ctrl = _devices + _ndevices++; - _switch_ndevices++; - - if (NULL == (ctrl->spi_device = (struct spi_dev *) - KMALLOC(sizeof(struct spi_dev), GFP_KERNEL))) { - gprintk("no memory available"); - return -ENOMEM; - } - ctrl->dev_type = (BDE_SPI_DEV_TYPE | BDE_SWITCH_DEV_TYPE); - ctrl->spi_device->cid = dev; - ctrl->spi_device->part = model_id; - ctrl->spi_device->rev = rev_id; - ctrl->spi_device->robo = robo; - ctrl->spi_device->phyid_high = phyidh; - ctrl->spi_device->phyid_low = phyidl; - ctrl->bde_dev.device = model_id; - ctrl->bde_dev.rev = rev_id; - ctrl->bde_dev.base_address = (sal_vaddr_t)NULL; - ctrl->isr = NULL; - ctrl->isr_data = NULL; - robo_switch++; - -#if defined(KEYSTONE) - spi_freq = _spi_id_table[match_idx].spifreq; -#endif - _bde_add_device(); - } - -#if defined(KEYSTONE) - /* Override the SPI frequency from user configuration */ - if (spifreq != 0) { - spi_freq = spifreq; - } - if (spi_freq != 0) { - /* - * The underlying chip can support the SPI frequency - * higher than default (2MHz). - */ - if (spi_freq != SPI_FREQ_DEFAULT) { - chipc_spi_set_freq(robo, 0, spi_freq); - } - } -#endif - return robo_switch; - -} - -#endif #if defined(BCM_METROCORE_LOCAL_BUS) static bde_ctrl_t* @@ -3330,8 +2760,7 @@ map_local_bus(uint64_t addr, uint32_t size) { bde_ctrl_t *ctrl; - ctrl = _devices + _ndevices++; - _switch_ndevices++; + ctrl = _devices + _ndevices; /* * For now: use EB type as `local bus' @@ -3347,7 +2776,6 @@ map_local_bus(uint64_t addr, uint32_t size) ctrl->phys_address = addr; _bde_add_device(); - return(ctrl); } @@ -3355,106 +2783,6 @@ map_local_bus(uint64_t addr, uint32_t size) #endif - -#ifdef BCM_METROCORE_LOCAL_BUS - /* - * SBX platform has both PCI- and local bus-attached devices - * The local bus devices have fixed address ranges (and don't - * support or require DMA), but are otherwise the same as PCI devices - */ -#define FPGA_IRQ 37 -#define FPGA_PHYS 0x100E0000 -#define BME_PHYS 0x100C0000 -#define SE_PHYS 0x100D0000 -#define FPGA_SIZE 0x00004000 -#define BME_SIZE 0x00004000 -#define MAC0_PHYS 0x100B0000 -#define MAC1_PHYS 0x100B8000 -#define MAC_SIZE 0x800 - - -/* - * Please refer to "Supervisor Fabric Module (SFM) Specification" - * page 23 for the following registers. - */ -#define FPGA_LC_POWER_DISABLE_OFFSET 0x4 -#define FPGA_LC_POWER_DISABLE_ENABLE_ALL_MASK 0x1e - -#define FPGA_LC_POWER_RESET_OFFSET 0x5 -#define FPGA_LC_POWER_RESET_ENABLE_ALL_MASK 0x1e - -#define FPGA_SW_SFM_MASTER_MODE_OFFSET 0x14 -#define FPGA_SW_SFM_MASTER_MODE_ENABLE_MASK 0x10 - - -static int -probe_metrocore_local_bus(void) { - bde_ctrl_t *ctrl; - uint32_t dev_rev_id; - VOL uint8_t *fpga; - - /* - * Write the FPGA on the fabric card, to let metrocore - * line cards out of reset. We actually don't bother to determine whether - * the card is a line card or a fabric card because when we do - * this on the line cards, it has no effect. - */ - fpga = (uint8_t *) IOREMAP(FPGA_PHYS, FPGA_SIZE); - fpga[FPGA_SW_SFM_MASTER_MODE_OFFSET] - |= FPGA_SW_SFM_MASTER_MODE_ENABLE_MASK; - fpga[FPGA_LC_POWER_DISABLE_OFFSET] - |= FPGA_LC_POWER_DISABLE_ENABLE_ALL_MASK; - fpga[FPGA_LC_POWER_RESET_OFFSET] - |= FPGA_LC_POWER_RESET_ENABLE_ALL_MASK; - - ctrl = map_local_bus(BME_PHYS, BME_SIZE); - - dev_rev_id = - *((uint32_t *) - (((uint8_t *) ctrl->bde_dev.base_address) + BME_REVISION_OFFSET)); - ctrl->bde_dev.device = dev_rev_id >> 16; - ctrl->bde_dev.rev = (dev_rev_id & 0xFF); - - if ((ctrl->bde_dev.device != BME3200_DEVICE_ID) && - (ctrl->bde_dev.device != BCM88130_DEVICE_ID)) { - gprintk("probe_metrocore_local_bus: wrong BME type: " - "0x%x (vs 0x%x or 0x%x)\n", - ctrl->bde_dev.device, BME3200_DEVICE_ID, BCM88130_DEVICE_ID); - return -1; - } - - ctrl->iLine = FPGA_IRQ; - ctrl->isr = NULL; - ctrl->isr_data = NULL; - - /* - * - * We start from SE & include the FPGA, which is 128k - */ - ctrl = map_local_bus(SE_PHYS, 128 * 1024); - - dev_rev_id = - *((uint32_t *) - (((uint8_t *) ctrl->bde_dev.base_address) + BME_REVISION_OFFSET)); - ctrl->bde_dev.device = dev_rev_id >> 16; - ctrl->bde_dev.rev = (dev_rev_id & 0xFF); - - if ((ctrl->bde_dev.device != BME3200_DEVICE_ID) && - (ctrl->bde_dev.device != BCM88130_DEVICE_ID)) { - gprintk("probe_metrocore_local_bus: wrong SE (BME) type: " - "0x%x (vs 0x%x)\n", - ctrl->bde_dev.device, BME3200_DEVICE_ID); - return -1; - } - - ctrl->iLine = FPGA_IRQ; - ctrl->isr = NULL; - ctrl->isr_data = NULL; - - return 0; -} -#endif - #ifdef BCM_PLX9656_LOCAL_BUS #if 1 @@ -3476,8 +2804,7 @@ map_local_bus2(bde_ctrl_t *plx_ctrl, uint32_t dev_base, uint32_t size) uint8_t *addr; bde_ctrl_t *ctrl; - ctrl = _devices + _ndevices++; - _switch_ndevices++; + ctrl = _devices + _ndevices; /* * For now: use EB type as `local bus' @@ -3499,15 +2826,11 @@ map_local_bus2(bde_ctrl_t *plx_ctrl, uint32_t dev_base, uint32_t size) ctrl->bde_dev.device = dev_rev_id >> 16; ctrl->bde_dev.rev = (dev_rev_id & 0xFF); + _bde_add_device(); switch (ctrl->bde_dev.device) { - case BCM88130_DEVICE_ID: - case BME3200_DEVICE_ID: - break; default: - gprintk("wrong BME type: 0x%x (vs 0x%x or 0x%x)\n", - ctrl->bde_dev.device, BME3200_DEVICE_ID, BCM88130_DEVICE_ID); return 0; } return(ctrl); @@ -3557,143 +2880,8 @@ probe_plx_local_bus(void) #endif /* BCM_PLX9656_LOCAL_BUS */ -#if defined(BCM_EA_SUPPORT) -#if defined(BCM_TK371X_SUPPORT) -static void -probe_tk371x_dev(void) -{ - bde_ctrl_t *ctrl; - int ea_uid=0; - - /* eadevices is from the argument of insmod */ - for (ea_uid = 0; ea_uid < eadevices; ea_uid++) { - ctrl = _devices + _ndevices++; - _switch_ndevices++; - ctrl->dev_type = (BDE_MII_DEV_TYPE | BDE_SWITCH_DEV_TYPE); - ctrl->bde_dev.device = TK371X_DEVICE_ID; - ctrl->bde_dev.rev = 0x0; - ctrl->bde_dev.base_address = (sal_vaddr_t)NULL; - ctrl->iLine = 0; - } -} -#endif /* BCM_TK371X_SUPPORT*/ -#endif /* BCM_EA_SUPPORT */ -#if defined(BCM_ROBO_SUPPORT) -#if defined(IPROC_CMICD) -struct chip_device_info { - uint32 cc_base; /* Chip-common register base */ - uint32 cc_size; /* Chip-common register limit */ - uint32 cid_reg_off; /* Chip id register offset */ -}; - -static struct chip_device_info _chip_table = { -#if defined(IPROC_CMICD) - 0x18000000, 0x00000300, 0x00000000 -#else - 0,0,0 -#endif -}; - -struct gmac_device_info { - uint32 cid; /* chip id */ - uint32 rid; /* revision id */ - uint32 pid; /* package id */ - - uint32 gmac_dev_id; /* gmac core device id */ - uint32 gmac_base_addr; /* gmac core base address */ - int gmac_irq; /* gmac irq number */ -}; - -static struct gmac_device_info _gmac_table[] = { -#if defined(IPROC_CMICD) - {BCM53010_CHIP_ID, 0, 0, BCM53010_GMAC_ID, 0x18026000, 181}, /* BCM53012 */ - {BCM53010_CHIP_ID, 0, 2, BCM53010_GMAC_ID, 0x18026000, 181}, /* BCM53011 */ - {BCM53010_CHIP_ID, 0, 1, BCM53010_GMAC_ID, 0x18026000, 181}, /* BCM53010 */ - {BCM53018_CHIP_ID, 0, 0, BCM53010_GMAC_ID, 0x18026000, 181}, /* BCM53018 */ - {BCM53018_CHIP_ID, 0, 2, BCM53010_GMAC_ID, 0x18026000, 181}, /* BCM53017 */ - {BCM53018_CHIP_ID, 0, 1, BCM53010_GMAC_ID, 0x18026000, 181}, /* BCM53019 */ - {BCM53020_CHIP_ID, 0, 0, BCM53010_GMAC_ID, 0x18024000, 181}, /* BCM53022 */ - {BCM53020_CHIP_ID, 4, 0, BCM53010_GMAC_ID, 0x18023000, 180}, /* BCM53022 */ -#endif - {0,0,0,0,0,0} -}; - -static sal_vaddr_t _cca_base = 0; - -static int -_gmac_dev_create(void) -{ - bde_ctrl_t *ctrl; - uint32 gmac_base = 0; - uint32 offset = 0; - uint32 cca_cid; - uint32 cid, rid, pid; - int i = 0, found; - - if (_chip_table.cc_base == 0) { - gprintk("Create GMAC device failed. Unable to identify CPU.\n"); - return -1; - } - - /* 1. Determine which CPU/GMAC configuration is now */ - _cca_base = (sal_vaddr_t)IOREMAP(_chip_table.cc_base, _chip_table.cc_size); - cca_cid = readl((uint32 *)(_cca_base + _chip_table.cid_reg_off)); - - cid = cca_cid & CID_ID_MASK; - rid = (cca_cid & CID_REV_MASK) >> CID_REV_SHIFT; - pid = (cca_cid & CID_PKG_MASK) >> CID_PKG_SHIFT; - - found = 0; - for (i = 0; ; i++) { - if (_gmac_table[i].cid == 0) { - /* End of table */ - break; - } - if ((_gmac_table[i].cid == cid) && - (_gmac_table[i].rid == rid) && - (_gmac_table[i].pid == pid)) { - /* found */ - found = 1; - break; - } - } - if (!found) { - gprintk("Create GMAC device failed. Unable to identify GMAC device.\n"); - } - - /* 2. Create GMAC device */ - /* fill-in necessary information depends on the CPU/GMAC configuration */ - if ((cid == BCM53010_CHIP_ID) || (cid == BCM53018_CHIP_ID) || - (cid == BCM53020_CHIP_ID)) { - ctrl = _devices + _ndevices++; - _ether_ndevices++; - - ctrl->dev_type |= BDE_ETHER_DEV_TYPE; - ctrl->dev_type |= BDE_PCI_DEV_TYPE; - - ctrl->iLine = _gmac_table[i].gmac_irq; - - ctrl->be_pio = 0; - - ctrl->bde_dev.rev = _gmac_table[i].rid; - ctrl->bde_dev.device = _gmac_table[i].gmac_dev_id; - - gmac_base = 0x18000000; - offset = _gmac_table[i].gmac_base_addr - gmac_base; - ctrl->bde_dev.base_address = (sal_vaddr_t)IOREMAP(gmac_base, 0x300000); - ctrl->alt_base_addr = ctrl->bde_dev.base_address + offset; - ctrl->phys_address = gmac_base; - - ctrl->isr = NULL; - ctrl->isr_data = NULL; - } - - return 0; -} -#endif -#endif /* * Generic module functions @@ -3738,13 +2926,6 @@ _init(void) /* Register our goodies */ _device_driver.name = LINUX_KERNEL_BDE_NAME; -#if defined(BCM_ROBO_SUPPORT) -#if defined(IPROC_CMICD) - if (_gmac_dev_create()) { - return -ENODEV; - } -#endif -#endif /* defined (BCM_ROBO_SUPPORT) */ /* Configure MSI interrupt support */ use_msi = usemsi; @@ -3797,17 +2978,11 @@ _init(void) #endif #endif /* BCM_ICS */ -#ifdef BCM_ROBO_SUPPORT - probe_robo_switch(); -#endif -#if defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT) +#ifdef BCM_SAND_SUPPORT sand_device_create(); #endif -#if defined(BCM_TK371X_SUPPORT) - probe_tk371x_dev(); -#endif /* * Probe for EB Bus devices. */ @@ -3863,24 +3038,6 @@ _cleanup(void) } #endif -#if defined(BCM_ROBO_SUPPORT) -#if defined(IPROC_CMICD) - if (_cca_base) { - iounmap((void *)_cca_base); - } -#endif - - if (robo) { -#if defined(KEYSTONE) || defined(IPROC_CMICD) - robo_detach(robo); -#endif /* KEYSTONE || IPROC_CMICD */ - } - if (sbh) { -#if defined(KEYSTONE) || defined(IPROC_CMICD) - ai_soc_detach(sbh); -#endif /* KEYSTONE || IPROC_CMICD */ - } -#endif for (i = 0; i < _ndevices; i++) { bde_ctrl_t *ctrl = _devices + i; @@ -3891,7 +3048,7 @@ _cleanup(void) } } } -#if (defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT)) && (defined(__DUNE_WRX_BCM_CPU__) || defined(__DUNE_GTO_BCM_CPU__)) +#if defined(BCM_SAND_SUPPORT) && (defined(__DUNE_WRX_BCM_CPU__) || defined(__DUNE_GTO_BCM_CPU__)) if (cpu_address) { /* unmap CPU card MMIO */ iounmap(cpu_address); cpu_address = NULL; @@ -3950,7 +3107,10 @@ _pprint(void) continue; } if (ctrl->dev_type & BDE_PCI_DEV_TYPE) { - pprintf("PCI device 0x%x:0x%x:%d:0x%.8lx:0x%.8lx:%d%s\n", + pprintf("PCI device %02x:%02x.%x 0x%x:0x%x:%d:0x%.8lx:0x%.8lx:%d%s\n", + (unsigned int)ctrl->pci_device->bus->number, + PCI_SLOT(ctrl->pci_device->devfn), + PCI_FUNC(ctrl->pci_device->devfn), ctrl->pci_device->vendor, ctrl->pci_device->device, ctrl->bde_dev.rev, @@ -3991,40 +3151,6 @@ _pprint(void) return 0; } -#if USE_LINUX_BDE_MMAP -/* - * Some kernels (mainly x86) prevent mapping of kernel RAM memory to - * user space via the /dev/mem device. The function below provides a - * backdoor to mapping the DMA pool to user space via the - * /dev/linux-kernel-bde device. - */ -static int _mmap(struct file *filp, struct vm_area_struct *vma) -{ - unsigned long phys_addr = vma->vm_pgoff << PAGE_SHIFT; - unsigned long size = vma->vm_end - vma->vm_start; - - if(!_dma_range_valid(phys_addr, size)) { - return -EINVAL; - } - -#ifdef REMAP_DMA_NONCACHED - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -#endif - - if (remap_pfn_range(vma, - vma->vm_start, - vma->vm_pgoff, - size, - vma->vm_page_prot)) { - gprintk("Failed to mmap phys range 0x%lx-0x%lx to 0x%lx-0x%lx\n", - phys_addr, phys_addr + size, vma->vm_start,vma->vm_end); - return -EAGAIN; - } - - return 0; -} -#endif /* USE_LINUX_BDE_MMAP */ - /* Workaround for broken Busybox/PPC insmod */ static char _modname[] = LINUX_KERNEL_BDE_NAME; @@ -4034,9 +3160,7 @@ static gmodule_t _gmodule = { init: _init, cleanup: _cleanup, pprint: _pprint, -#if USE_LINUX_BDE_MMAP - mmap: _mmap, -#endif + mmap: _dma_mmap, }; gmodule_t * @@ -4336,7 +3460,7 @@ _interrupt_connect(int d, gprintk("%s(%d):device# = %d, irq = %d\n", __func__, __LINE__, d, ctrl->entries[i].vector); } - ret = request_irq(ctrl->entries[i].vector, _isr, 0, + ret = request_irq(ctrl->entries[i].vector, (irq_handler_t)_isr, 0, LINUX_KERNEL_BDE_NAME, ctrl); if (ret < 0) break; @@ -4358,7 +3482,7 @@ _interrupt_connect(int d, if (unlikely(debug >= 1)) gprintk("%s(%d):device# = %d, request_irq(%d)\n", __func__, __LINE__, d, iproc_cmicx_irqs[i]); - ret = request_irq(iproc_cmicx_irqs[i], _isr, + ret = request_irq(iproc_cmicx_irqs[i], (irq_handler_t)_isr, irq_flags, LINUX_KERNEL_BDE_NAME, ctrl); if (ret < 0) { gprintk("request_irq(%d) failed(%d)\n", iproc_cmicx_irqs[i], ret); @@ -4536,6 +3660,9 @@ _iproc_read(int d, uint32_t addr) } if (_devices[d].dev_type & BDE_AXI_DEV_TYPE) { + if (IHOST_GICD_REG_ADDR_VALID(d, addr)) { + return readl(IHOST_GICD_REG_ADDR_REMAP(d, addr)); + } return _iproc_ihost_read(d, addr); } @@ -4556,6 +3683,10 @@ _iproc_write(int d, uint32_t addr, uint32_t data) } if (_devices[d].dev_type & BDE_AXI_DEV_TYPE) { + if (IHOST_GICD_REG_ADDR_VALID(d, addr)) { + writel(data, IHOST_GICD_REG_ADDR_REMAP(d, addr)); + return 0; + } return _iproc_ihost_write(d, addr, data); } @@ -4626,126 +3757,7 @@ _get_cmic_ver(int d , uint32_t *ver) return -1; } -#ifdef BCM_ROBO_SUPPORT -#define SOC_ROBO_PAGE_BP 8 /* for Robo Chip only */ - -#if defined(IPROC_CMICD) -extern int ccb_mii_read(int dev_type, int phy_addr, int reg_off, uint16 *data); -extern int ccb_mii_write(int dev_type, int phy_addr, int reg_off, uint16 data); - -/* device type */ -#define MII_DEV_LOCAL 0 -#define MII_DEV_EXT 1 -#endif - -static int -_spi_read(int d, uint32 addr, uint8 *buf, int len) -{ -#if defined(KEYSTONE) || defined(IPROC_CMICD) - bde_ctrl_t *ctrl; - uint8 page, offset; -#endif -#if defined(IPROC_CMICD) - int rv = 0; - uint16 value = 0; -#endif - - if (!VALID_DEVICE(d)) { - return -1; - } - - if (!(_devices[d].dev_type & BDE_SPI_DEV_TYPE)) { - gprintk("_spi_read: Not SPI device %d, type %x\n", - d, _devices[d].dev_type); - return -1; - } - -#if defined(KEYSTONE) || defined(IPROC_CMICD) - ctrl = _devices + d; -#endif - -#if defined(IPROC_CMICD) - if (addr & SOC_EXTERNAL_PHY_BUS_CPUMDIO) { - rv = ccb_mii_read(MII_DEV_EXT, (addr >> 8) & 0xff, addr & 0xff, &value); - memcpy(buf, &value, 2); - return rv; - } -#endif - -#if defined(KEYSTONE) || defined(IPROC_CMICD) - page = (addr >> SOC_ROBO_PAGE_BP) & 0xFF; - offset = addr & 0xFF; -#endif - -#if defined(IPROC_CMICD) && defined(BCM_STARFIGHTER3_SUPPORT) - if (spi_device_found) { - ROBO_SPI_RREG(ctrl->spi_device->robo, ctrl->spi_device->cid, - page, offset, buf, (uint)len); - } else -#endif - { - ROBO_RREG(ctrl->spi_device->robo, ctrl->spi_device->cid, - page, offset, buf, (uint)len); - } - - return 0; -} - -static int -_spi_write(int d, uint32 addr, uint8 *buf, int len) -{ -#if defined(KEYSTONE) || defined(IPROC_CMICD) - bde_ctrl_t *ctrl; - uint8 page, offset; -#endif -#if defined(IPROC_CMICD) - int rv = 0; - uint16 value = 0; -#endif - if (!VALID_DEVICE(d)) { - return -1; - } - - if (!(_devices[d].dev_type & BDE_SPI_DEV_TYPE)) { - gprintk("_spi_write: Not SPI device %d, type %x\n", - d, _devices[d].dev_type); - return -1; - } - -#if defined(KEYSTONE) || defined(IPROC_CMICD) - ctrl = _devices + d; -#endif - -#if defined(IPROC_CMICD) - if (addr & SOC_EXTERNAL_PHY_BUS_CPUMDIO) { - memcpy(&value, buf, 2); - rv = ccb_mii_write(MII_DEV_EXT, (addr >> 8) & 0xff, addr & 0xff, value); - return rv; - } -#endif - -#if defined(KEYSTONE) || defined(IPROC_CMICD) - page = (addr >> SOC_ROBO_PAGE_BP) & 0xFF; - offset = addr & 0xFF; -#endif - -#if defined(IPROC_CMICD) && defined(BCM_STARFIGHTER3_SUPPORT) - if (spi_device_found) { - ROBO_SPI_WREG(ctrl->spi_device->robo, ctrl->spi_device->cid, - page, offset, buf, (uint)len); - } else -#endif - { - ROBO_WREG(ctrl->spi_device->robo, ctrl->spi_device->cid, - page, offset, buf, (uint)len); - } - - return 0; -} - -#endif - -#if defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT) +#ifdef BCM_SAND_SUPPORT int lkbde_cpu_write(int d, uint32 addr, uint32 *buf) { @@ -4853,7 +3865,7 @@ lkbde_cpu_pci_register(int d) case BCM88380_DEVICE_ID: case BCM88381_DEVICE_ID: case BCM88680_DEVICE_ID: - case BCM88690_DEVICE_ID: + case BCM88800_DEVICE_ID: case BCM88470_DEVICE_ID: case BCM88470P_DEVICE_ID: case BCM88471_DEVICE_ID: @@ -4865,6 +3877,7 @@ lkbde_cpu_pci_register(int d) case BCM88270_DEVICE_ID: case BCM88272_DEVICE_ID: case BCM88273_DEVICE_ID: + case BCM88274_DEVICE_ID: case BCM88278_DEVICE_ID: case BCM8206_DEVICE_ID: case BCM88350_DEVICE_ID: @@ -4902,6 +3915,22 @@ lkbde_cpu_pci_register(int d) break; } +#ifdef BCM_DNX_SUPPORT + /*All Jericho 2 devices from 0x8690 to 0x869F*/ + if (SOC_IS_JERICHO_2_TYPE(ctrl->bde_dev.device)) { + /* Fix bar 0 address */ /* FIXME: write full phy address */ + pci_write_config_byte(ctrl->pci_device, 0x12, 0x10); + pci_write_config_byte(ctrl->pci_device, 0x13, 0x60); + + /* + * For DMA transactions - set Max_Payload_Size and + * Max_Read_Request_Size to 128 bytes. + */ + pci_write_config_byte(ctrl->pci_device, 0xb5, 0x0c); + pci_write_config_byte(ctrl->pci_device, 0xb4, 0x0); + } +#endif + /* Redo ioremap */ if (ctrl->bde_dev.base_address) { iounmap((void *)ctrl->bde_dev.base_address); @@ -4955,7 +3984,7 @@ lkbde_mem_read(int d, uint32 addr, uint32 *buf) return 0; } LKM_EXPORT_SYM(lkbde_mem_read); -#endif /* defined(BCM_PETRA_SUPPORT) */ +#endif /* BCM_SAND_SUPPORT */ static ibde_t _ibde = { name: _name, @@ -4975,13 +4004,9 @@ static ibde_t _ibde = { interrupt_disconnect: _interrupt_disconnect, l2p: _l2p, p2l: _p2l, -#if defined(BCM_ROBO_SUPPORT) - spi_read: _spi_read, - spi_write: _spi_write, -#else + NULL, NULL, -#endif /* defined(BCM_ROBO_SUPPORT) */ iproc_read: _iproc_read, iproc_write: _iproc_write, get_cmic_ver: _get_cmic_ver, @@ -5328,7 +4353,7 @@ LKM_EXPORT_SYM(lkbde_dev_state_set); LKM_EXPORT_SYM(lkbde_dev_state_get); LKM_EXPORT_SYM(lkbde_dev_instid_set); LKM_EXPORT_SYM(lkbde_dev_instid_get); -#if (defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT)) +#ifdef BCM_SAND_SUPPORT LKM_EXPORT_SYM(lkbde_cpu_write); LKM_EXPORT_SYM(lkbde_cpu_read); LKM_EXPORT_SYM(lkbde_cpu_pci_register); diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_dma.c b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_dma.c index 32b769784c..eb3dc04951 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_dma.c +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_dma.c @@ -85,10 +85,25 @@ #if _SIMPLE_MEMORY_ALLOCATION_ == 1 #define ALLOC_METHOD_DEFAULT ALLOC_TYPE_API +#if defined(__arm__) +#define USE_DMA_MMAP_COHERENT +#define _PGPROT_NONCACHED(x) x = pgprot_noncached((x)) +#elif defined(__aarch64__ ) +#define USE_DMA_MMAP_COHERENT +#define _PGPROT_NONCACHED(x) x = pgprot_writecombine((x)) +#endif #else #define ALLOC_METHOD_DEFAULT ALLOC_TYPE_CHUNK #endif +#ifndef _PGPROT_NONCACHED +#ifdef REMAP_DMA_NONCACHED +#define _PGPROT_NONCACHED(x) x = pgprot_noncached((x)) +#else +#define _PGPROT_NONCACHED(x) +#endif +#endif + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) #include #define virt_to_bus virt_to_phys @@ -101,6 +116,12 @@ #define VIRT_TO_PAGE(p) virt_to_page((p)) #endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)) +#define DMA_MAPPING_ERROR(d, p) dma_mapping_error((d),(p)) +#else +#define DMA_MAPPING_ERROR(d, p) dma_mapping_error((p)) +#endif + #ifndef KMALLOC_MAX_SIZE #define KMALLOC_MAX_SIZE (1UL << (MAX_ORDER - 1 + PAGE_SHIFT)) #endif @@ -170,7 +191,6 @@ MODULE_PARM_DESC(himemaddr, #else #define DMA_MEM_DEFAULT (8 * ONE_MB) #endif -#define DMA_MEM_DEFAULT_ROBO (4 * ONE_MB) /* We try to assemble a contiguous segment from chunks of this size */ #define DMA_BLOCK_SIZE (512 * ONE_KB) @@ -203,6 +223,7 @@ static unsigned long _himemaddr = 0; static int _use_dma_mapping = 0; static LIST_HEAD(_dma_seg); +#define DMA_DEV_INDEX 0 /* Device index to allocate memory pool */ #define DMA_DEV(n) lkbde_get_dma_dev(n) #define BDE_NUM_DEVICES(t) lkbde_get_num_devices(t) @@ -545,7 +566,7 @@ _pgcleanup(void) case ALLOC_TYPE_API: if (_dma_vbase) { if (dma_debug >= 1) gprintk("freeing v=%p p=0x%lx size=0x%lx\n", _dma_vbase,(unsigned long) _dma_pbase, (unsigned long)_dma_mem_size); - dma_free_coherent(DMA_DEV(0), _dma_mem_size, _dma_vbase, _dma_pbase); + dma_free_coherent(DMA_DEV(DMA_DEV_INDEX), _dma_mem_size, _dma_vbase, _dma_pbase); } break; #endif /* _SIMPLE_MEMORY_ALLOCATION_ */ @@ -554,7 +575,7 @@ _pgcleanup(void) struct list_head *pos, *tmp; int i, ndevices; if (_use_dma_mapping) { - ndevices = BDE_NUM_DEVICES(BDE_ALL_DEVICES); + ndevices = BDE_NUM_DEVICES(BDE_SWITCH_DEVICES); for (i = 0; i < ndevices && DMA_DEV(i); i ++) { dma_unmap_single(DMA_DEV(i), (dma_addr_t)_dma_pbase, _dma_mem_size, DMA_BIDIRECTIONAL); } @@ -591,7 +612,6 @@ static void _alloc_mpool(size_t size) { unsigned long pbase = 0; - #if defined(__arm__) && !defined(CONFIG_HIGHMEM) if (_use_himem) { gprintk("DMA in high memory requires CONFIG_HIGHMEM on ARM CPUs.\n"); @@ -614,6 +634,9 @@ _alloc_mpool(size_t size) _dma_vbase = IOREMAP(_dma_pbase, size); } else { /* Get DMA memory from kernel */ + if (dma_debug >= 1) { + gprintk("Allocating DMA memory using method dmaalloc=%d\n", dmaalloc); + } switch (dmaalloc) { #if _SIMPLE_MEMORY_ALLOCATION_ case ALLOC_TYPE_API: { @@ -624,8 +647,9 @@ _alloc_mpool(size_t size) /* get a memory allocation from the kernel */ { dma_addr_t dma_handle; - if (!(_dma_vbase = dma_alloc_coherent(DMA_DEV(0), alloc_size, &dma_handle, GFP_KERNEL)) || !dma_handle) { - gprintk("failed to allocate the memory pool of size 0x%lx\n", (unsigned long)alloc_size); + if (!(_dma_vbase = dma_alloc_coherent(DMA_DEV(DMA_DEV_INDEX), + alloc_size, &dma_handle, GFP_KERNEL)) || !dma_handle) { + gprintk("Failed to allocate coherent memory pool of size 0x%lx\n", (unsigned long)alloc_size); return; } _cpu_pbase = pbase = dma_handle; @@ -643,14 +667,14 @@ _alloc_mpool(size_t size) case ALLOC_TYPE_CHUNK: _dma_vbase = _pgalloc(size); if (!_dma_vbase) { - gprintk("failed to allocate the memory pool of size 0x%lx\n", (unsigned long)size); + gprintk("Failed to allocate memory pool of size 0x%lx\n", (unsigned long)size); return; } _cpu_pbase = virt_to_bus(_dma_vbase); /* Use dma_map_single to obtain DMA bus address or IOVA if iommu is present. */ - if (DMA_DEV(0)) { - pbase = dma_map_single(DMA_DEV(0), _dma_vbase, size, DMA_BIDIRECTIONAL); - if (dma_mapping_error(DMA_DEV(0), pbase)) { + if (DMA_DEV(DMA_DEV_INDEX)) { + pbase = dma_map_single(DMA_DEV(DMA_DEV_INDEX), _dma_vbase, size, DMA_BIDIRECTIONAL); + if (DMA_MAPPING_ERROR(DMA_DEV(DMA_DEV_INDEX), pbase)) { gprintk("Failed to map memory at %p\n", _dma_vbase); _pgcleanup(); _dma_vbase = NULL; @@ -659,7 +683,6 @@ _alloc_mpool(size_t size) } _use_dma_mapping = 1; } else { - /* Device has not been probed. */ pbase = _cpu_pbase; } break; @@ -719,15 +742,21 @@ _dma_cleanup(void) return 0; } -void _dma_init(int robo_switch, int dev_index) +void _dma_init(int dev_index) { unsigned long pbase; - if (dev_index > 0) { - if ((_use_dma_mapping == 1) && DMA_DEV(dev_index) && _dma_vbase) { + if (dev_index > DMA_DEV_INDEX) { + if (_use_dma_mapping && DMA_DEV(dev_index) && _dma_vbase) { pbase = dma_map_single(DMA_DEV(dev_index), _dma_vbase, _dma_mem_size, DMA_BIDIRECTIONAL); - if (dma_mapping_error(DMA_DEV(dev_index), pbase)) { + if (DMA_MAPPING_ERROR(DMA_DEV(dev_index), pbase)) { gprintk("Failed to map memory for device %d at %p\n", dev_index, _dma_vbase); + return; + } + if (pbase != (unsigned long)_dma_pbase) { + /* Bus address/IOVA must be identical for all devices. */ + gprintk("Device %d has different pbase: %lx (should be %lx)\n", + dev_index, pbase, (unsigned long)_dma_pbase); } } return; @@ -745,10 +774,6 @@ void _dma_init(int robo_switch, int dev_index) gprintk("dmasize must be a power of 2 (1M, 2M, 4M, 8M etc.)\n"); _dma_mem_size = 0; } - } else { - if(robo_switch){ - _dma_mem_size = DMA_MEM_DEFAULT_ROBO; - } } if (himem) { @@ -775,42 +800,54 @@ void _dma_init(int robo_switch, int dev_index) _alloc_mpool(_dma_mem_size); if (_dma_vbase == NULL) { gprintk("no DMA memory available\n"); - } - else { + } else { mpool_init(); _dma_pool = mpool_create(_dma_vbase, _dma_mem_size); } } } -#if USE_LINUX_BDE_MMAP /* - * Function: _dma_range_valid + * Some kernels are configured to prevent mapping of kernel RAM memory + * into user space via the /dev/mem device. * - * Purpose: - * Check if DMA address range is valid. - * Parameters: - * phys_addr - start physical address - * size - range size - * Returns: - * 0 : not valid - * 1 : valid + * The function below provides a backdoor to mapping the DMA pool to + * user space via the BDE device file. */ -int -_dma_range_valid(unsigned long phys_addr, unsigned long size) +int _dma_mmap(struct file *filp, struct vm_area_struct *vma) { - unsigned long pool_start = _cpu_pbase; - unsigned long pool_end = pool_start + _dma_mem_size; + unsigned long phys_addr = vma->vm_pgoff << PAGE_SHIFT; + unsigned long size = vma->vm_end - vma->vm_start; - if (phys_addr < pool_start || (phys_addr + size) > pool_end) { + if (phys_addr < (unsigned long )_cpu_pbase || + (phys_addr + size) > ((unsigned long )_cpu_pbase + _dma_mem_size)) { gprintk("range 0x%lx-0x%lx outside DMA pool 0x%lx-0x%lx\n", - phys_addr, phys_addr + size, pool_start, pool_end); - return 0; + phys_addr, phys_addr + size, (unsigned long )_cpu_pbase, + (unsigned long )_cpu_pbase + _dma_mem_size); + return -EINVAL; + } + +#ifdef USE_DMA_MMAP_COHERENT + if (dmaalloc == ALLOC_TYPE_API) { + vma->vm_pgoff = 0; + return dma_mmap_coherent(DMA_DEV(DMA_DEV_INDEX), vma, (void *)_dma_vbase, phys_addr, size); } - return 1; -} #endif + _PGPROT_NONCACHED(vma->vm_page_prot); + + if (remap_pfn_range(vma, + vma->vm_start, + vma->vm_pgoff, + size, + vma->vm_page_prot)) { + gprintk("Failed to mmap phys range 0x%lx-0x%lx to 0x%lx-0x%lx\n", + phys_addr, phys_addr + size, vma->vm_start,vma->vm_end); + return -EAGAIN; + } + return 0; +} + /* * Function: _dma_pool_allocated * diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/shared/mpool.c b/platform/broadcom/saibcm-modules/systems/bde/linux/shared/mpool.c index 7a377cd007..13206596ee 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/shared/mpool.c +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/shared/mpool.c @@ -70,12 +70,31 @@ static sal_sem_t _mpool_lock; #endif #endif +#define MPOOL_BUF_SIZE 1024 +#define MPOOL_BUF_ALLOC_COUNT_MAX 16 + typedef struct mpool_mem_s { unsigned char *address; int size; + struct mpool_mem_s *prev; struct mpool_mem_s *next; } mpool_mem_t; +static int _buf_alloc_count; +static mpool_mem_t *mpool_buf[MPOOL_BUF_ALLOC_COUNT_MAX]; +static mpool_mem_t *free_list; + +#define ALLOC_INIT_MPOOL_BUF(ptr) \ + ptr = MALLOC((sizeof(mpool_mem_t) * MPOOL_BUF_SIZE)); \ + if (ptr) { \ + int i; \ + for (i = 0; i < MPOOL_BUF_SIZE - 1; i++) { \ + ptr[i].next = &ptr[i+1]; \ + } \ + ptr[MPOOL_BUF_SIZE - 1].next = NULL; \ + free_list = &ptr[0]; \ + } + /* * Function: mpool_init * @@ -116,6 +135,10 @@ mpool_alloc(mpool_handle_t pool, int size) MPOOL_LOCK(); + if (size < BCM_CACHE_LINE_BYTES) { + size = BCM_CACHE_LINE_BYTES; + } + mod = size & (BCM_CACHE_LINE_BYTES - 1); if (mod != 0 ) { size += (BCM_CACHE_LINE_BYTES - mod); @@ -131,21 +154,37 @@ mpool_alloc(mpool_handle_t pool, int size) MPOOL_UNLOCK(); return NULL; } - newptr = MALLOC(sizeof(mpool_mem_t)); - if (!newptr) { - MPOOL_UNLOCK(); - return NULL; + + if (!free_list) { + if (_buf_alloc_count == MPOOL_BUF_ALLOC_COUNT_MAX) { + MPOOL_UNLOCK(); + return NULL; + } + + ALLOC_INIT_MPOOL_BUF(mpool_buf[_buf_alloc_count]); + + if (mpool_buf[_buf_alloc_count] == NULL) { + MPOOL_UNLOCK(); + return NULL; + } + + _buf_alloc_count++; } + + newptr = free_list; + free_list = free_list->next; newptr->address = ptr->address + ptr->size; newptr->size = size; newptr->next = ptr->next; + newptr->prev = ptr; + ptr->next->prev = newptr; ptr->next = newptr; #ifdef TRACK_DMA_USAGE _dma_mem_used += size; #endif - MPOOL_UNLOCK(); + MPOOL_UNLOCK(); return newptr->address; } @@ -165,25 +204,29 @@ void mpool_free(mpool_handle_t pool, void *addr) { unsigned char *address = (unsigned char *)addr; - mpool_mem_t *ptr = pool, *prev = NULL; + mpool_mem_t *head = pool, *ptr = NULL; MPOOL_LOCK(); - - while (ptr && ptr->next) { - if (ptr->next->address == address) { + + if (!(head && head->prev)) { + MPOOL_UNLOCK(); + return; + } + + ptr = head->prev->prev; + + while (ptr && (ptr != head)) { + if (ptr->address == address) { #ifdef TRACK_DMA_USAGE - _dma_mem_used -= ptr->next->size; + _dma_mem_used -= ptr->size; #endif + ptr->prev->next = ptr->next; + ptr->next->prev = ptr->prev; + ptr->next = free_list; + free_list = ptr; break; } - ptr = ptr->next; - } - - if (ptr && ptr->next) { - prev = ptr; - ptr = ptr->next; - prev->next = ptr->next; - FREE(ptr); + ptr = ptr->prev; } MPOOL_UNLOCK(); @@ -208,34 +251,45 @@ mpool_create(void *base_ptr, int size) { mpool_mem_t *head, *tail; int mod = (int)(((unsigned long)base_ptr) & (BCM_CACHE_LINE_BYTES - 1)); + int i; MPOOL_LOCK(); + for (i = 0; i < MPOOL_BUF_ALLOC_COUNT_MAX; i++) { + mpool_buf[i] = NULL; + } + + _buf_alloc_count = 0; + + ALLOC_INIT_MPOOL_BUF(mpool_buf[_buf_alloc_count]); + + if (mpool_buf[_buf_alloc_count] == NULL) { + MPOOL_UNLOCK(); + return NULL; + } + + _buf_alloc_count++; + if (mod) { base_ptr = (char*)base_ptr + (BCM_CACHE_LINE_BYTES - mod); size -= (BCM_CACHE_LINE_BYTES - mod); } size &= ~(BCM_CACHE_LINE_BYTES - 1); - - head = (mpool_mem_t *)MALLOC(sizeof(mpool_mem_t)); - if (head == NULL) { - return NULL; - } - tail = (mpool_mem_t *)MALLOC(sizeof(mpool_mem_t)); - if (tail == NULL) { - FREE(head); - return NULL; - } - + head = free_list; + free_list = free_list->next; + tail = free_list; + free_list = free_list->next; + head->size = tail->size = 0; head->address = base_ptr; tail->address = head->address + size; + head->prev = tail; head->next = tail; + tail->prev = head; tail->next = NULL; MPOOL_UNLOCK(); - return head; } @@ -252,13 +306,20 @@ mpool_create(void *base_ptr, int size) int mpool_destroy(mpool_handle_t pool) { - mpool_mem_t *ptr, *next; - + int i; + MPOOL_LOCK(); - for (ptr = pool; ptr; ptr = next) { - next = ptr->next; - FREE(ptr); + if ((mpool_mem_t *)pool != mpool_buf[0]) { + MPOOL_UNLOCK(); + return 0; + } + + for (i = 0; i < MPOOL_BUF_ALLOC_COUNT_MAX; i++) { + if (mpool_buf[i]) { + FREE(mpool_buf[i]); + mpool_buf[i] = NULL; + } } MPOOL_UNLOCK(); @@ -285,7 +346,7 @@ mpool_usage(mpool_handle_t pool) MPOOL_LOCK(); for (ptr = pool; ptr; ptr = ptr->next) { - usage += ptr->size; + usage += ptr->size; } MPOOL_UNLOCK(); diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.c b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.c index 6c7c9bb950..370f89e022 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.c +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.c @@ -33,9 +33,6 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0) #include #endif -#ifdef KEYSTONE -#include -#endif MODULE_AUTHOR("Broadcom Corporation"); @@ -676,124 +673,10 @@ _bcm88750_interrupt(bde_ctrl_t *ctrl) #endif } -static void -_qe2k_interrupt(bde_ctrl_t *ctrl) -{ - bde_inst_resource_t *res; - - res = &_bde_inst_resource[ctrl->inst]; - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x20/sizeof(uint32)); - - atomic_set(&res->intr, 1); -#ifdef BDE_LINUX_NON_INTERRUPTIBLE - wake_up(&res->intr_wq); -#else - wake_up_interruptible(&res->intr_wq); -#endif -} - -static void -_fe2k_interrupt(bde_ctrl_t *ctrl) -{ - bde_inst_resource_t *res; - - res = &_bde_inst_resource[ctrl->inst]; - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x18/sizeof(uint32)); /* PC_INTERRUPT_MASK */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x24/sizeof(uint32)); /* PC_ERROR0_MASK */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x2c/sizeof(uint32)); /* PC_ERROR1_MASK */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x34/sizeof(uint32)); /* PC_UNIT_MASK */ - - atomic_set(&res->intr, 1); -#ifdef BDE_LINUX_NON_INTERRUPTIBLE - wake_up(&res->intr_wq); -#else - wake_up_interruptible(&res->intr_wq); -#endif -} - -static void -_fe2kxt_interrupt(bde_ctrl_t *ctrl) -{ - bde_inst_resource_t *res; - - res = &_bde_inst_resource[ctrl->inst]; - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x2c/sizeof(uint32)); /* PC_INTERRUPT_MASK */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x38/sizeof(uint32)); /* PC_ERROR0_MASK */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x40/sizeof(uint32)); /* PC_ERROR1_MASK */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x50/sizeof(uint32)); /* PC_UNIT_MASK */ - - atomic_set(&res->intr, 1); -#ifdef BDE_LINUX_NON_INTERRUPTIBLE - wake_up(&res->intr_wq); -#else - wake_up_interruptible(&res->intr_wq); -#endif -} - -static void -_bme3200_interrupt(bde_ctrl_t *ctrl) -{ - bde_inst_resource_t *res; - - res = &_bde_inst_resource[ctrl->inst]; - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x54/sizeof(uint32)); /* PI_PT_ERROR0 */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x5c/sizeof(uint32)); /* PI_PT_ERROR1 */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x64/sizeof(uint32)); /* PI_PT_ERROR2 */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x6c/sizeof(uint32)); /* PI_PT_ERROR3 */ - - atomic_set(&res->intr, 1); -#ifdef BDE_LINUX_NON_INTERRUPTIBLE - wake_up(&res->intr_wq); -#else - wake_up_interruptible(&res->intr_wq); -#endif -} - - -static void -_bm9600_interrupt(bde_ctrl_t *ctrl) -{ - bde_inst_resource_t *res; - - res = &_bde_inst_resource[ctrl->inst]; - - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x5c/sizeof(uint32)); /* PI_INTERRUPT_MASK */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0xc/sizeof(uint32)); /* PI_UNIT_INTERRUPT0_MASK */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x14/sizeof(uint32)); /* PI_UNIT_INTERRUPT1_MASK */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x1c/sizeof(uint32)); /* PI_UNIT_INTERRUPT2_MASK */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x24/sizeof(uint32)); /* PI_UNIT_INTERRUPT3_MASK */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x2c/sizeof(uint32)); /* PI_UNIT_INTERRUPT4_MASK */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x34/sizeof(uint32)); /* PI_UNIT_INTERRUPT5_MASK */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x3c/sizeof(uint32)); /* PI_UNIT_INTERRUPT6_MASK */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x44/sizeof(uint32)); /* PI_UNIT_INTERRUPT7_MASK */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x4c/sizeof(uint32)); /* PI_UNIT_INTERRUPT8_MASK */ - SSOC_WRITEL(0xffffffff, ctrl->ba + 0x54/sizeof(uint32)); /* PI_UNIT_INTERRUPT9_MASK */ - - atomic_set(&res->intr, 1); -#ifdef BDE_LINUX_NON_INTERRUPTIBLE - wake_up(&res->intr_wq); -#else - wake_up_interruptible(&res->intr_wq); -#endif -} - - - /* The actual interrupt handler of ethernet devices */ static void _ether_interrupt(bde_ctrl_t *ctrl) { -#ifdef KEYSTONE - /* - * Since the two GMAC cores are sharing the same IRQ. - * Add the checking to handle the interrupt events. - */ - if ((ctrl->devid == BCM53000_GMAC_ID)) { - if ((readl(ctrl->ba + 0x020/4) & readl(ctrl->ba + 0x024/4)) == 0) { - return; - } - } -#endif SSOC_WRITEL(0, ctrl->ba + 0x024/4); atomic_set(&_ether_interrupt_has_taken_place, 1); @@ -813,11 +696,6 @@ static struct _intr_mode_s { { (isr_f)_cmicm_interrupt, "CMICm" }, { (isr_f)_cmicd_interrupt, "CMICd" }, { (isr_f)_cmicd_cmc0_interrupt, "CMICd CMC0" }, - { (isr_f)_qe2k_interrupt, "QE2K" }, - { (isr_f)_fe2k_interrupt, "FE2K" }, - { (isr_f)_fe2kxt_interrupt, "FE2KXT" }, - { (isr_f)_bme3200_interrupt, "BME3200" }, - { (isr_f)_bm9600_interrupt, "BM9600" }, { (isr_f)_bcm88750_interrupt, "BCM88750" }, { (isr_f)_cmicx_interrupt, "CMICx" }, { NULL, NULL } @@ -845,7 +723,7 @@ _devices_init(int d) uint32 ver; uint16 device_id_mask = 0xFFF0; uint16 device_id; - int state = 0; + uint32 state = 0; (void)lkbde_dev_state_get(d, &state); if (state == BDE_DEV_STATE_REMOVED) { @@ -864,21 +742,6 @@ _devices_init(int d) } if (ctrl->dev_type & BDE_SWITCH_DEV_TYPE) { switch (user_bde->get_dev(d)->device) { - case QE2000_DEVICE_ID: - ctrl->isr = (isr_f)_qe2k_interrupt; - break; - case BCM88020_DEVICE_ID: - ctrl->isr = (isr_f)_fe2k_interrupt; - break; - case BCM88025_DEVICE_ID: - ctrl->isr = (isr_f)_fe2kxt_interrupt; - break; - case BME3200_DEVICE_ID: - ctrl->isr = (isr_f)_bme3200_interrupt; - break; - case BM9600_DEVICE_ID: - ctrl->isr = (isr_f)_bm9600_interrupt; - break; case BCM88750_DEVICE_ID: case BCM88753_DEVICE_ID: case BCM88754_DEVICE_ID: @@ -920,7 +783,7 @@ _devices_init(int d) case BCM88380_DEVICE_ID: case BCM88381_DEVICE_ID: case BCM88680_DEVICE_ID: - case BCM88690_DEVICE_ID: + case BCM88800_DEVICE_ID: case BCM88770_DEVICE_ID: case BCM88773_DEVICE_ID: case BCM88774_DEVICE_ID: @@ -938,6 +801,7 @@ _devices_init(int d) case BCM88270_DEVICE_ID: case BCM88272_DEVICE_ID: case BCM88273_DEVICE_ID: + case BCM88274_DEVICE_ID: case BCM88278_DEVICE_ID: case BCM88279_DEVICE_ID: case BCM8206_DEVICE_ID: @@ -1002,7 +866,15 @@ _devices_init(int d) } break; } - /* All Ramon devices from 0x8790 to 0x879F */ + +#ifdef BCM_DNX_SUPPORT + /*All Jericho 2 devices from 0x8690 to 0x869F*/ + if (SOC_IS_JERICHO_2_TYPE(user_bde->get_dev(d)->device)) { + ctrl->isr = (isr_f)_cmicx_interrupt; + } +#endif + + /*All Ramon devices from 0x8790 to 0x879F*/ if ((user_bde->get_dev(d)->device & BCM88790_DEVICE_ID) == BCM88790_DEVICE_ID) { ctrl->isr = (isr_f)_cmicx_interrupt; } @@ -1456,30 +1328,9 @@ _ioctl(unsigned int cmd, unsigned long arg) } break; case LUBDE_USLEEP: - sal_usleep(io.d0); - break; case LUBDE_UDELAY: - sal_udelay(io.d0); - break; case LUBDE_SEM_OP: - switch (io.d0) { - case LUBDE_SEM_OP_CREATE: - io.p0 = (bde_kernel_addr_t)sal_sem_create("", io.d1, io.d2); - break; - case LUBDE_SEM_OP_DESTROY: - sal_sem_destroy((sal_sem_t)io.p0); - break; - case LUBDE_SEM_OP_TAKE: - io.rc = sal_sem_take((sal_sem_t)io.p0, io.d2); - break; - case LUBDE_SEM_OP_GIVE: - io.rc = sal_sem_give((sal_sem_t)io.p0); - break; - default: - io.rc = LUBDE_FAIL; - break; - } - break; + return -EINVAL; case LUBDE_WRITE_IRQ_MASK: io.rc = lkbde_irq_mask_set(io.dev, io.d0, io.d1, 0); break; @@ -1499,7 +1350,7 @@ _ioctl(unsigned int cmd, unsigned long arg) case LUBDE_WRITE_REG_16BIT_BUS: io.rc = user_bde->write(io.dev, io.d0, io.d1); break; -#if (defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT)) +#ifdef BCM_SAND_SUPPORT case LUBDE_CPU_WRITE_REG: { if (lkbde_cpu_write(io.dev, io.d0, (uint32*)io.dx.buf) == -1) { diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_iproc.c b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_iproc.c index e1bdcc4db0..05253141b2 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_iproc.c +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_iproc.c @@ -30,6 +30,8 @@ #define BAR0_PAXB_CONFIG_IND_ADDR 0x2120 #define BAR0_PAXB_CONFIG_IND_DATA 0x2124 +#define PAXB_0_CMICD_TO_PCIE_INTR_EN 0x2380 + #define BAR0_PAXB_IMAP0_0 (0x2c00) #define BAR0_PAXB_IMAP0_1 (0x2c04) #define BAR0_PAXB_IMAP0_2 (0x2c08) @@ -287,7 +289,8 @@ shbde_iproc_paxb_init(shbde_hal_t *shbde, void *iproc_regs, iproc32_write(shbde, reg, data | 0x1); } } - /* Configure MSIX interrupt page, only need for iproc ver == 0x10 */ + + /* Configure MSIX interrupt page, only need for iproc ver == 0x10 */ if ((icfg->use_msi == 2) && (icfg->iproc_ver == 0x10)) { unsigned int mask = (0x1 << PAXB_0_FUNC0_IMAP1_3_ADDR_SHIFT) - 1; reg = ROFFS(iproc_regs, PAXB_0_FUNC0_IMAP1_3); @@ -296,6 +299,17 @@ shbde_iproc_paxb_init(shbde_hal_t *shbde, void *iproc_regs, data |= 0x410 << PAXB_0_FUNC0_IMAP1_3_ADDR_SHIFT; iproc32_write(shbde, reg, data); } + + /* Disable INTx interrupt if MSI/MSIX is selected */ + reg = ROFFS(iproc_regs, PAXB_0_CMICD_TO_PCIE_INTR_EN); + data = iproc32_read(shbde, reg); + if (icfg->use_msi) { + data &= ~0x1; + } else { + data |= 0x1; + } + iproc32_write(shbde, reg, data); + return pci_num; } diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/bcm-knet.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/bcm-knet.c index 6767090ec7..b8094f392d 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/bcm-knet.c +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/bcm-knet.c @@ -67,6 +67,7 @@ #include #include +#include #include #include #include @@ -405,6 +406,59 @@ static inline struct sk_buff *skb_padto(struct sk_buff *skb, unsigned int len) pci_dma_mapping_error(d, a) #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) +enum { + SKBTX_HW_TSTAMP = 1 << 0, + SKBTX_SW_TSTAMP = 1 << 1, + SKBTX_IN_PROGRESS = 1 << 2, +}; +struct skb_shared_hwtstamps { + ktime_t hwtstamp; + ktime_t syststamp; +}; +struct bkn_skb_shared_info { + uint8_t tx_flags; + struct skb_shared_hwtstamps hwtstamps; +}; +#define bkn_skb_shinfo(_skb) ((struct bkn_skb_shared_info *)(unsigned char *)_skb->end) +#define bkn_skb_tx_flags(_skb) bkn_skb_shinfo(_skb)->tx_flags +static inline struct skb_shared_hwtstamps *skb_hwtstamps(struct sk_buff *skb) +{ + return &bkn_skb_shinfo(skb)->hwtstamps; +} +void skb_tstamp_tx(struct sk_buff *orig_skb, struct skb_shared_hwtstamps *hwtstamps) +{ +} +static inline void bkn_skb_tx_timestamp(struct sk_buff *skb) +{ +} +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) +static inline ktime_t ns_to_ktime(u64 ns) +{ + static const ktime_t ktime; + return ktime; +} +#endif +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) +#include +enum { + SKBTX_HW_TSTAMP = 1 << 0, + SKBTX_SW_TSTAMP = 1 << 1, + SKBTX_IN_PROGRESS = 1 << 2, +}; +#define bkn_skb_tx_flags(_skb) skb_shinfo(_skb)->tx_flags.flags +static inline void bkn_skb_tx_timestamp(struct sk_buff *skb) +{ +} +#else +#include +#define bkn_skb_tx_flags(_skb) skb_shinfo(_skb)->tx_flags +static inline void bkn_skb_tx_timestamp(struct sk_buff *skb) +{ + return skb_tx_timestamp(skb); +} +#endif + #ifdef LINUX_BDE_DMA_DEVICE_SUPPORT #define DMA_DEV device #define DMA_FROMDEV DMA_FROM_DEVICE @@ -471,6 +525,9 @@ typedef struct bkn_dcb_chain_s { #define NUM_CMICX_RX_CHAN 7 #define NUM_CMICM_RX_CHAN 3 +#define FCS_SZ 4 +#define TAG_SZ 4 + /* Device control info */ typedef struct bkn_switch_info_s { struct list_head list; @@ -497,6 +554,12 @@ typedef struct bkn_switch_info_s { int dcb_type; /* DCB type */ int dcb_wsize; /* DCB size (in 32-bit words) */ int pkt_hdr_size; /* Packet header size */ + uint32_t ftmh_lb_key_ext_size; /* FTMH LB-Key Extension existence/size */ + uint32_t ftmh_stacking_ext_size; /* FTMH Stacking extension existence/size */ + uint32_t pph_base_size; /* Size of PPH base */ + uint32_t pph_lif_ext_size[8]; /* Size of PPH Lif extension header */ + uint8_t udh_enable; /* Indicates UDH existence */ + uint32_t udh_length_type[4]; /* Size of UDH header per type */ int rx_chans; /* Number of Rx channels */ uint32_t dma_hi; /* DMA higher address */ uint32_t cmic_type; /* CMIC type (CMICe or CMICm) */ @@ -516,6 +579,10 @@ typedef struct bkn_switch_info_s { uint32_t inst_id; /* Instance id of this device */ int evt_idx; /* Event queue index for this device*/ int basedev_suspended; /* Base device suspended */ + int tx_hwts; /* HW timestamp for Tx */ + int rx_hwts; /* HW timestamp for Rx */ + struct sk_buff_head tx_ptp_queue; /* Tx PTP skb queue */ + struct work_struct tx_ptp_work; /* Tx PTP work */ struct { bkn_desc_info_t desc[MAX_TX_DCBS+1]; int free; /* Number of free Tx DCBs */ @@ -574,71 +641,163 @@ typedef struct bkn_switch_info_s { } rx[NUM_RX_CHAN]; } bkn_switch_info_t; -#define BKN_DNX_HDR_MAX_SIZE 40 +/* PTCH_2 */ +#define BKN_DNX_PTCH_2_SIZE 2 +/* ITMH */ +#define BKN_DNX_ITMH_SIZE 5 +/* Modlue Header */ +#define BKN_DNX_MODULE_HEADER_SIZE 20 /* FTMH */ -#define BKN_DNX_FTMH_LB_EXT_EN 0x1 -#define BKN_DNX_FTMH_STACKING_EXT_EN 0x2 -#define BKN_DNX_FTMH_SIZE_BYTE 9 -#define BKN_DNX_FTMH_LB_EXT_SIZE_BYTE 1 -#define BKN_DNX_FTMH_STACKING_SIZE_BYTE 2 -#define BKN_DNX_FTMH_DEST_EXT_SIZE_BYTE 2 -#define BKN_DNX_FTMH_LB_EXT_SIZE_BYTE 1 -#define BKN_DNX_FTMH_PKT_SIZE_MSB 0 -#define BKN_DNX_FTMH_PKT_SIZE_NOF_BITS 14 -#define BKN_DNX_FTMH_TC_MSB 14 -#define BKN_DNX_FTMH_TC_NOF_BITS 3 -#define BKN_DNX_FTMH_SRC_SYS_PORT_MSB 17 -#define BKN_DNX_FTMH_SRC_SYS_PORT_NOF_BITS 16 -#define BKN_DNX_FTMH_EXT_DSP_EXIST_MSB 68 -#define BKN_DNX_FTMH_EXT_DSP_EXIST_NOF_BITS 1 -#define BKN_DNX_FTMH_EXT_MSB 45 -#define BKN_DNX_FTMH_EXT_NOF_BITS 2 -#define BKN_DNX_FTMH_FIRST_EXT_MSB 72 -#define BKN_DNX_FTMH_ACTION_TYPE_MSB 43 -#define BKN_DNX_FTMH_ACTION_TYPE_NOF_BITS 2 -#define BKN_DNX_FTMH_PPH_TYPE_MSB 45 -#define BKN_DNX_FTMH_PPH_TYPE_NOF_BITS 2 +#define BKN_DNX_FTMH_SRC_SYS_PORT_AGGREGATE_MSB 17 +#define BKN_DNX_FTMH_SRC_SYS_PORT_AGGREGATE_NOF_BITS 16 +#define BKN_DNX_FTMH_PP_DSP_MSB 33 +#define BKN_DNX_FTMH_PP_DSP_NOF_BITS 8 +#define BKN_DNX_FTMH_ACTION_TYPE_MSB 43 +#define BKN_DNX_FTMH_ACTION_TYPE_NOF_BITS 2 +#define BKN_DNX_FTMH_PPH_TYPE_IS_TSH_EN_MSB 73 +#define BKN_DNX_FTMH_PPH_TYPE_IS_TSH_EN_NOF_BITS 1 +#define BKN_DNX_FTMH_PPH_TYPE_IS_PPH_EN_MSB 74 +#define BKN_DNX_FTMH_PPH_TYPE_IS_PPH_EN_NOF_BITS 1 +#define BKN_DNX_FTMH_TM_DST_EXT_PRESENT_MSB 75 +#define BKN_DNX_FTMH_TM_DST_EXT_PRESENT_NOF_BITS 1 +#define BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE_MSB 76 +#define BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE_NOF_BITS 1 +#define BKN_DNX_FTMH_FLOW_ID_EXT_SIZE_MSB 77 +#define BKN_DNX_FTMH_FLOW_ID_EXT_SIZE_NOF_BITS 1 +#define BKN_DNX_FTMH_BIER_BFR_EXT_SIZE_MSB 78 +#define BKN_DNX_FTMH_BIER_BFR_EXT_SIZE_NOF_BITS 1 +/* Fix Length for FTMH and Extension headers */ +#define BKN_DNX_FTMH_BASE_SIZE 10 +#define BKN_DNX_FTMH_BIER_BFR_EXT_SIZE 2 +#define BKN_DNX_FTMH_TM_DST_EXT_SIZE 3 +#define BKN_DNX_FTMH_FLOW_ID_EXT_SIZE 3 +#define BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE 6 +/* TSH */ +#define BKN_DNX_TSH_SIZE 4 /* PPH */ -#define BKN_DNX_PPH_SIZE_BYTE 7 -#define BKN_DNX_PPH_EEI_EXTENSION_PRESENT_MSB 0 -#define BKN_DNX_PPH_EEI_EXTENSION_PRESENT_NOF_BITS 1 -#define BKN_DNX_PPH_LEARN_EXENSION_PRESENT_MSB 1 -#define BKN_DNX_PPH_LEARN_EXENSION_PRESENT_NOF_BITS 1 -#define BKN_DNX_PPH_FHEI_SIZE_MSB 2 -#define BKN_DNX_PPH_FHEI_SIZE_NOF_BITS 2 -#define BKN_DNX_PPH_FORWARD_CODE_MSB 4 -#define BKN_DNX_PPH_FORWARD_CODE_NOF_BITS 4 -#define BKN_DNX_PPH_VSI_MSB 22 -#define BKN_DNX_PPH_VSI_NOF_BITS 16 -/* FHEI TRAP/SNOOP 3B */ -#define BKN_DNX_PPH_FHEI_3B_SIZE_BYTE 3 -#define BKN_DNX_PPH_FHEI_5B_SIZE_BYTE 5 -#define BKN_DNX_PPH_FHEI_8B_SIZE_BYTE 8 -#define BKN_DNX_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_MSB 0 -#define BKN_DNX_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_NOF_BITS 16 -#define BKN_DNX_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_MSB 16 -#define BKN_DNX_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_NOF_BITS 8 -/* PPH extension */ -#define BKN_DNX_PPH_EXPLICIT_EDITING_INFOMATION_EXTENSION_SIZE_BYTE 3 -#define BKN_DNX_PPH_LEARN_EXTENSION_SIZE_BYTE 5 +#define BKN_DNX_PPH_BASE_TYPE_9 9 +#define BKN_DNX_PPH_BASE_TYPE_10 10 +#define BKN_DNX_PPH_BASE_TYPE_12 12 +#define BKN_DNX_PPH_9_FORWARD_DOMAIN_MSB 5 +#define BKN_DNX_PPH_9_FORWARD_DOMAIN_NOF_BITS 16 +#define BKN_DNX_PPH_9_LEARN_EXT_PRESENT_MSB 53 +#define BKN_DNX_PPH_9_LEARN_EXT_PRESENT_NOF_BITS 1 +#define BKN_DNX_PPH_9_FHEI_SIZE_MSB 54 +#define BKN_DNX_PPH_9_FHEI_SIZE_NOF_BITS 2 +#define BKN_DNX_PPH_9_LIF_EXT_TYPE_MSB 56 +#define BKN_DNX_PPH_9_LIF_EXT_TYPE_NOF_BITS 3 +#define BKN_DNX_PPH_10_FORWARD_DOMAIN_MSB 9 +#define BKN_DNX_PPH_10_FORWARD_DOMAIN_NOF_BITS 16 +#define BKN_DNX_PPH_10_LEARN_EXT_PRESENT_MSB 61 +#define BKN_DNX_PPH_10_LEARN_EXT_PRESENT_NOF_BITS 1 +#define BKN_DNX_PPH_10_FHEI_SIZE_MSB 62 +#define BKN_DNX_PPH_10_FHEI_SIZE_NOF_BITS 2 +#define BKN_DNX_PPH_10_LIF_EXT_TYPE_MSB 64 +#define BKN_DNX_PPH_10_LIF_EXT_TYPE_NOF_BITS 3 +#define BKN_DNX_PPH_12_FORWARD_DOMAIN_MSB 21 +#define BKN_DNX_PPH_12_FORWARD_DOMAIN_NOF_BITS 18 +#define BKN_DNX_PPH_12_LEARN_EXT_PRESENT_MSB 77 +#define BKN_DNX_PPH_12_LEARN_EXT_PRESENT_NOF_BITS 1 +#define BKN_DNX_PPH_12_FHEI_SIZE_MSB 78 +#define BKN_DNX_PPH_12_FHEI_SIZE_NOF_BITS 2 +#define BKN_DNX_PPH_12_LIF_EXT_TYPE_MSB 80 +#define BKN_DNX_PPH_12_LIF_EXT_TYPE_NOF_BITS 3 +/* PPH.FHEI_TYPE */ +#define BKN_DNX_PPH_FHEI_TYPE_SZ0 1 +#define BKN_DNX_PPH_FHEI_TYPE_SZ1 2 +#define BKN_DNX_PPH_FHEI_TYPE_SZ2 3 +/* FHEI */ +#define BKN_DNX_PPH_FHEI_SZ0_SIZE 3 +#define BKN_DNX_PPH_FHEI_SZ1_SIZE 5 +#define BKN_DNX_PPH_FHEI_SZ2_SIZE 8 +#define BKN_DNX_PPH_FHEI_TRAP_5B_QUALIFIER_MSB 0 +#define BKN_DNX_PPH_FHEI_TRAP_5B_QUALIFIER_NOF_BITS 27 +#define BKN_DNX_PPH_FHEI_TRAP_5B_CODE_MSB 27 +#define BKN_DNX_PPH_FHEI_TRAP_5B_CODE_NOF_BITS 9 +#define BKN_DNX_PPH_FHEI_TRAP_5B_TYPE_MSB 36 +#define BKN_DNX_PPH_FHEI_TRAP_5B_TYPE_NOF_BITS 4 +/* PPH Extension */ +#define BKN_DNX_PPH_LEARN_EXT_SIZE 19 +/* UDH */ +#define BKN_DNX_UDH_DATA_TYPE_0_MSB 0 +#define BKN_DNX_UDH_DATA_TYPE_0_NOF_BITS 2 +#define BKN_DNX_UDH_DATA_TYPE_1_MSB 2 +#define BKN_DNX_UDH_DATA_TYPE_1_NOF_BITS 2 +#define BKN_DNX_UDH_DATA_TYPE_2_MSB 4 +#define BKN_DNX_UDH_DATA_TYPE_2_NOF_BITS 2 +#define BKN_DNX_UDH_DATA_TYPE_3_MSB 6 +#define BKN_DNX_UDH_DATA_TYPE_3_NOF_BITS 2 +#define BKN_DNX_UDH_BASE_SIZE 1 +#define BKN_DPP_HDR_MAX_SIZE 40 +/* PTCH_2 */ +#define BKN_DPP_PTCH_2_SIZE 2 +/* ITMH */ +#define BKN_DPP_ITMH_SIZE 4 +/* FTMH */ +#define BKN_DPP_FTMH_LB_EXT_EN 0x1 +#define BKN_DPP_FTMH_STACKING_EXT_EN 0x2 +#define BKN_DPP_FTMH_SIZE_BYTE 9 +#define BKN_DPP_FTMH_LB_EXT_SIZE_BYTE 1 +#define BKN_DPP_FTMH_STACKING_SIZE_BYTE 2 +#define BKN_DPP_FTMH_DEST_EXT_SIZE_BYTE 2 +#define BKN_DPP_FTMH_LB_EXT_SIZE_BYTE 1 +#define BKN_DPP_FTMH_PKT_SIZE_MSB 0 +#define BKN_DPP_FTMH_PKT_SIZE_NOF_BITS 14 +#define BKN_DPP_FTMH_TC_MSB 14 +#define BKN_DPP_FTMH_TC_NOF_BITS 3 +#define BKN_DPP_FTMH_SRC_SYS_PORT_MSB 17 +#define BKN_DPP_FTMH_SRC_SYS_PORT_NOF_BITS 16 +#define BKN_DPP_FTMH_EXT_DSP_EXIST_MSB 68 +#define BKN_DPP_FTMH_EXT_DSP_EXIST_NOF_BITS 1 +#define BKN_DPP_FTMH_EXT_MSB 45 +#define BKN_DPP_FTMH_EXT_NOF_BITS 2 +#define BKN_DPP_FTMH_FIRST_EXT_MSB 72 +#define BKN_DPP_FTMH_ACTION_TYPE_MSB 43 +#define BKN_DPP_FTMH_ACTION_TYPE_NOF_BITS 2 +#define BKN_DPP_FTMH_PPH_TYPE_MSB 45 +#define BKN_DPP_FTMH_PPH_TYPE_NOF_BITS 2 + +/* PPH */ +#define BKN_DPP_PPH_SIZE_BYTE 7 +#define BKN_DPP_PPH_EEI_EXTENSION_PRESENT_MSB 0 +#define BKN_DPP_PPH_EEI_EXTENSION_PRESENT_NOF_BITS 1 +#define BKN_DPP_PPH_LEARN_EXENSION_PRESENT_MSB 1 +#define BKN_DPP_PPH_LEARN_EXENSION_PRESENT_NOF_BITS 1 +#define BKN_DPP_PPH_FHEI_SIZE_MSB 2 +#define BKN_DPP_PPH_FHEI_SIZE_NOF_BITS 2 +#define BKN_DPP_PPH_FORWARD_CODE_MSB 4 +#define BKN_DPP_PPH_FORWARD_CODE_NOF_BITS 4 +#define BKN_DPP_PPH_VSI_MSB 22 +#define BKN_DPP_PPH_VSI_NOF_BITS 16 +/* FHEI TRAP/SNOOP 3B */ +#define BKN_DPP_PPH_FHEI_3B_SIZE_BYTE 3 +#define BKN_DPP_PPH_FHEI_5B_SIZE_BYTE 5 +#define BKN_DPP_PPH_FHEI_8B_SIZE_BYTE 8 +#define BKN_DPP_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_MSB 0 +#define BKN_DPP_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_NOF_BITS 16 +#define BKN_DPP_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_MSB 16 +#define BKN_DPP_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_NOF_BITS 8 +/* PPH extension */ +#define BKN_DPP_PPH_EXPLICIT_EDITING_INFOMATION_EXTENSION_SIZE_BYTE 3 +#define BKN_DPP_PPH_LEARN_EXTENSION_SIZE_BYTE 5 /* ftmh action type. */ -typedef enum bkn_dnx_ftmh_action_type_e { - BKN_DNX_FTMH_ACTION_TYPE_FORWARD = 0, /* TM action is forward */ - BKN_DNX_FTMH_ACTION_TYPE_SNOOP = 1, /* TM action is snoop */ - BKN_DNX_FTMH_ACTION_TYPE_INBOUND_MIRROR = 2, /* TM action is inbound mirror. */ - BKN_DNX_FTMH_ACTION_TYPE_OUTBOUND_MIRROR = 3 /* TM action is outbound mirror. */ -}bkn_dnx_ftmh_action_type_t; +typedef enum bkn_dpp_ftmh_action_type_e { + BKN_DPP_FTMH_ACTION_TYPE_FORWARD = 0, /* TM action is forward */ + BKN_DPP_FTMH_ACTION_TYPE_SNOOP = 1, /* TM action is snoop */ + BKN_DPP_FTMH_ACTION_TYPE_INBOUND_MIRROR = 2, /* TM action is inbound mirror. */ + BKN_DPP_FTMH_ACTION_TYPE_OUTBOUND_MIRROR = 3 /* TM action is outbound mirror. */ +}bkn_dpp_ftmh_action_type_t; /* ftmh dest extension. */ -typedef struct bkn_dnx_ftmh_dest_extension_s { +typedef struct bkn_dpp_ftmh_dest_extension_s { uint8 valid; /* Set if the extension is present */ uint32_t dst_sys_port; /* Destination System Port */ -} bkn_dnx_ftmh_dest_extension_t; +} bkn_dpp_ftmh_dest_extension_t; /* dnx packet */ -typedef struct bkn_pkt_dnx_s { +typedef struct bkn_dune_system_header_info_s { uint32_t ntwrk_header_ptr; struct { uint32_t packet_size; /* Packet size in bytes */ @@ -652,8 +811,13 @@ typedef struct bkn_pkt_dnx_s { uint32_t trap_qualifier; /* RAW Data */ uint32_t trap_id; /* RAW Data */ } internal; -} bkn_dnx_packet_info; - + uint32_t system_header_size; + uint32_t ftmh_spa; /* FTMH: Source-System-Port-Aggregate*/ + uint32_t pph_forward_domain; /* PPH: Forward-Domain*/ + uint32_t fhei_qualifier; /* FHEI: Qualifier */ + uint32_t fhei_code; /* FHEI: Code */ + uint32_t fhei_type; /* FHEI: Type */ +} bkn_dune_system_header_info_t; #define PREV_IDX(_cur, _max) (((_cur) == 0) ? (_max) - 1 : (_cur) - 1) @@ -715,6 +879,8 @@ typedef struct bkn_priv_s { uint32_t vlan; uint32_t flags; uint32_t cb_user_data; + uint8_t system_headers[27]; + uint32_t system_headers_size; } bkn_priv_t; typedef struct bkn_filter_s { @@ -755,6 +921,14 @@ LIST_HEAD(_sinfo_list); static knet_skb_cb_f knet_rx_cb = NULL; static knet_skb_cb_f knet_tx_cb = NULL; static knet_filter_cb_f knet_filter_cb = NULL; +static knet_hw_tstamp_enable_cb_f knet_hw_tstamp_enable_cb = NULL; +static knet_hw_tstamp_enable_cb_f knet_hw_tstamp_disable_cb = NULL; +static knet_hw_tstamp_tx_time_get_cb_f knet_hw_tstamp_tx_time_get_cb = NULL; +static knet_hw_tstamp_tx_meta_get_cb_f knet_hw_tstamp_tx_meta_get_cb = NULL; +static knet_hw_tstamp_ptp_clock_index_cb_f knet_hw_tstamp_ptp_clock_index_cb = NULL; +static knet_hw_tstamp_rx_time_upscale_cb_f knet_hw_tstamp_rx_time_upscale_cb = NULL; +static knet_netif_cb_f knet_netif_create_cb = NULL; +static knet_netif_cb_f knet_netif_destroy_cb = NULL; /* * Thread management @@ -955,6 +1129,8 @@ static bkn_thread_ctrl_t bkn_evt_ctrl; #define CMICX_IRQ_STATr (CMICX_CMC_BASE + 0x0000106c) #define CMICX_IRQ_STAT_CLRr (CMICX_CMC_BASE + 0x00001074) #define CMICX_IRQ_ENABr 0x18013100 +#define IHOST_GIC_GIC400_GICD_ISENABLERN_5r 0x10781114 +#define IHOST_GIC_GIC400_GICD_ICENABLERN_5r 0x10781194 /* CMICx interrupts reserved for kernel handler */ #define CMICX_TXRX_IRQ_MASK 0xffffffff @@ -992,6 +1168,7 @@ static bkn_thread_ctrl_t bkn_evt_ctrl; #define CMICX_DS_CMC_DESC_DONE(ch) (0x00000001 << ((ch) * 4)) #define CMICX_DS_CMC_CHAIN_DONE(ch) (0x00000002 << ((ch) * 4)) #define CMICX_DS_CMC_CTRLD_INT(ch) (0x00000008 << ((ch) * 4)) +#define CMICX_DS_CMC_DMA_CHAIN_DONE (0x00000001) #define CMICX_DS_CMC_DMA_ACTIVE (0x00000002) #define DMA_TO_BUS_HI(dma) ((dma) | sinfo->dma_hi) @@ -1498,12 +1675,25 @@ xgsx_dma_chan_abort(bkn_switch_info_t *sinfo, int chan, int polls) static inline void xgsx_irq_mask_set(bkn_switch_info_t *sinfo, uint32_t mask) { + uint32_t irq_mask_reg = CMICX_IRQ_ENABr; + uint32_t irq_mask, irq_fmask, disable_mask; + if (sinfo->napi_poll_mode) { mask = 0; } + if (sinfo->cpu_no == 1) { + lkbde_irq_mask_get(sinfo->dev_no, &irq_mask, &irq_fmask); + disable_mask = ~mask & (irq_mask & irq_fmask); + if (disable_mask) { + lkbde_irq_mask_set(sinfo->dev_no | LKBDE_ISR2_DEV | LKBDE_IPROC_REG, + IHOST_GIC_GIC400_GICD_ICENABLERN_5r, disable_mask, CMICX_TXRX_IRQ_MASK); + } + irq_mask_reg = IHOST_GIC_GIC400_GICD_ISENABLERN_5r; + } + lkbde_irq_mask_set(sinfo->dev_no | LKBDE_ISR2_DEV | LKBDE_IPROC_REG, - CMICX_IRQ_ENABr, mask, CMICX_TXRX_IRQ_MASK); + irq_mask_reg, mask, CMICX_TXRX_IRQ_MASK); } static inline void @@ -2094,6 +2284,7 @@ bkn_rx_refill(bkn_switch_info_t *sinfo, int chan) bkn_desc_info_t *desc; uint32_t *dcb; uint32_t resv_size = sinfo->cmic_type == 'x' ? RCPU_HDR_SIZE : RCPU_RX_ENCAP_SIZE; + uint32_t meta_size = sinfo->cmic_type == 'x' ? RCPU_RX_META_SIZE : 0; int prev; if (sinfo->rx[chan].use_rx_skb == 0) { @@ -2121,7 +2312,7 @@ bkn_rx_refill(bkn_switch_info_t *sinfo, int chan) chan, sinfo->rx[chan].cur)); } skb = desc->skb; - desc->dma_size = rx_buffer_size; + desc->dma_size = rx_buffer_size + meta_size; #ifdef KNET_NO_AXI_DMA_INVAL /* * FIXME: Need to retain this code until iProc customers have been @@ -2166,7 +2357,7 @@ bkn_rx_refill(bkn_switch_info_t *sinfo, int chan) } if (sinfo->cmic_type == 'x') { dcb[1] = DMA_TO_BUS_HI(desc->skb_dma >> 32); - dcb[2] |= rx_buffer_size; + dcb[2] |= rx_buffer_size + meta_size; } else { dcb[1] |= rx_buffer_size; } @@ -2327,6 +2518,37 @@ bkn_dma_abort(bkn_switch_info_t *sinfo) return 0; } +static int +device_is_dpp(bkn_switch_info_t *sinfo) +{ + int is_dpp = 0; + + is_dpp = (sinfo->dcb_type == 28) ? 1 : 0; + return is_dpp; +} + +static int +device_is_dnx(bkn_switch_info_t *sinfo) +{ + int is_dnx = 0; + + /* No EP_TO_CPU header for DNX(JR2) */ + is_dnx = ((sinfo->cmic_type == 'x') && (sinfo->pkt_hdr_size ==0)) ? 1 : 0; + return is_dnx; +} + +/* is DPP or is DNX*/ +static int +device_is_sand(bkn_switch_info_t *sinfo) +{ + int is_sand = 0; + + if (device_is_dpp(sinfo) || device_is_dnx(sinfo)) { + is_sand = 1; + } + return is_sand; +} + static bkn_filter_t * bkn_match_rx_pkt(bkn_switch_info_t *sinfo, uint8_t *pkt, int pktlen, void *meta, int chan, bkn_filter_t *cbf) @@ -2349,12 +2571,38 @@ bkn_match_rx_pkt(bkn_switch_info_t *sinfo, uint8_t *pkt, int pktlen, wsize = BYTES2WORDS(size); DBG_VERB(("Filter: size = %d (%d), data = 0x%08x, mask = 0x%08x\n", size, wsize, kf->data.w[0], kf->mask.w[0])); + + if (device_is_dnx(sinfo)) { + DBG_DUNE(("Filter: size = %d (wsize %d)\n", size, wsize)); + for (idx = 0; idx < wsize; idx++) + { + DBG_DUNE(("OOB[%d]: 0x%08x [0x%08x]\n", idx, kf->data.w[idx], kf->mask.w[idx])); + } + DBG_DUNE(("Meta Data [+ Selected Raw packet data]\n")); + for (idx = 0; idx < wsize; idx++) + { + DBG_DUNE(("Scratch[%d]: 0x%08x\n", idx, scratch.data.w[idx])); + } + } + match = 1; if (match) { - if (kf->priority < (num_rx_prio * sinfo->rx_chans)) { - if (kf->priority < (num_rx_prio * chan) || - kf->priority >= (num_rx_prio * (chan + 1))) { - match = 0; + if (device_is_sand(sinfo)) + { + /** priority 0 means no priority check */ + if (kf->priority && (kf->priority < (num_rx_prio * sinfo->rx_chans))) { + if (kf->priority < (num_rx_prio * chan) || + kf->priority >= (num_rx_prio * (chan + 1))) { + match = 0; + } + } + } + else { + if (kf->priority < (num_rx_prio * sinfo->rx_chans)) { + if (kf->priority < (num_rx_prio * chan) || + kf->priority >= (num_rx_prio * (chan + 1))) { + match = 0; + } } } } @@ -2422,6 +2670,43 @@ bkn_netif_lookup(bkn_switch_info_t *sinfo, int id) return NULL; } +static int +bkn_hw_tstamp_rx_set(bkn_switch_info_t *sinfo, struct sk_buff *skb, uint32 *meta) +{ + struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); + uint32_t *md = meta; + uint64_t ts = 0; + + switch (sinfo->dcb_type) { + case 26: + case 32: + case 33: + ts = md[14]; + ts = ts << 32 | md[12]; + break; + case 36: + ts = md[10]; + break; + case 38: + ts = md[4] & 0xffff; + ts = ts << 32 | md[5]; + break; + default: + return -1; + } + + if (knet_hw_tstamp_rx_time_upscale_cb) { + if (knet_hw_tstamp_rx_time_upscale_cb(sinfo->dev_no, &ts) < 0) { + return -1; + } + } + + memset(shhwtstamps, 0, sizeof(*shhwtstamps)); + shhwtstamps->hwtstamp = ns_to_ktime(be64_to_cpu(ts)); + + return 0; +} + static int bkn_add_rcpu_encap(bkn_switch_info_t *sinfo, struct sk_buff *skb, void *meta) { @@ -2491,15 +2776,6 @@ bkn_eth_type_update(struct sk_buff *skb, int ethertype) #define BKN_DNX_BYTE_SWAP(x) ((((x) << 24)) | (((x) & 0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) >> 24))) #endif -static int -device_is_dune(bkn_switch_info_t *sinfo) -{ - int is_dune = 0; - - is_dune = (sinfo->dcb_type == 28) ? 1 : 0; - return is_dune; -} - static int packet_is_untagged(uint16_t tpid) { @@ -2513,7 +2789,7 @@ packet_is_untagged(uint16_t tpid) } static void -bkn_dnx_bitstream_set_field(uint32_t *input_buffer, uint32_t start_bit, uint32_t nof_bits, uint32_t field) +bkn_bitstream_set_field(uint32_t *input_buffer, uint32_t start_bit, uint32_t nof_bits, uint32_t field) { uint32_t place; uint32_t field_bit_i; @@ -2540,7 +2816,7 @@ bkn_dnx_bitstream_set_field(uint32_t *input_buffer, uint32_t start_bit, uint32_t } static void -bkn_dnx_bitstream_get_field(uint8_t *input_buffer, uint32_t start_bit, uint32_t nof_bits, uint32_t *output_value) +bkn_bitstream_get_field(uint8_t *input_buffer, uint32_t start_bit, uint32_t nof_bits, uint32_t *output_value) { uint32_t idx; uint32_t buf_sizes=0; @@ -2590,7 +2866,7 @@ bkn_dnx_bitstream_get_field(uint8_t *input_buffer, uint32_t start_bit, uint32_t } static void -bkn_dnx_packet_parse_ftmh(bkn_switch_info_t *sinfo, uint8_t hdr_buff[], bkn_dnx_packet_info *packet_info) +bkn_dpp_packet_parse_ftmh(bkn_switch_info_t *sinfo, uint8_t hdr_buff[], bkn_dune_system_header_info_t *packet_info) { uint32_t header_ptr = 0; uint32_t dsp_ext_exist=0; @@ -2599,76 +2875,76 @@ bkn_dnx_packet_parse_ftmh(bkn_switch_info_t *sinfo, uint8_t hdr_buff[], bkn_dnx_ header_ptr = packet_info->ntwrk_header_ptr; /* Packet-size */ - bkn_dnx_bitstream_get_field( + bkn_bitstream_get_field( &hdr_buff[header_ptr], - BKN_DNX_FTMH_PKT_SIZE_MSB, - BKN_DNX_FTMH_PKT_SIZE_NOF_BITS, + BKN_DPP_FTMH_PKT_SIZE_MSB, + BKN_DPP_FTMH_PKT_SIZE_NOF_BITS, &fld_val); packet_info->ftmh.packet_size = fld_val; /* Traffic-class */ - bkn_dnx_bitstream_get_field( + bkn_bitstream_get_field( &hdr_buff[header_ptr], - BKN_DNX_FTMH_TC_MSB, - BKN_DNX_FTMH_TC_NOF_BITS, + BKN_DPP_FTMH_TC_MSB, + BKN_DPP_FTMH_TC_NOF_BITS, &fld_val); packet_info->ftmh.prio = fld_val; /* Source-system-port-aggregate */ - bkn_dnx_bitstream_get_field( + bkn_bitstream_get_field( &hdr_buff[header_ptr], - BKN_DNX_FTMH_SRC_SYS_PORT_MSB, - BKN_DNX_FTMH_SRC_SYS_PORT_NOF_BITS, + BKN_DPP_FTMH_SRC_SYS_PORT_MSB, + BKN_DPP_FTMH_SRC_SYS_PORT_NOF_BITS, &fld_val); packet_info->ftmh.src_sys_port = fld_val; /* TM-action-type */ - bkn_dnx_bitstream_get_field( + bkn_bitstream_get_field( &hdr_buff[header_ptr], - BKN_DNX_FTMH_ACTION_TYPE_MSB, - BKN_DNX_FTMH_ACTION_TYPE_NOF_BITS, + BKN_DPP_FTMH_ACTION_TYPE_MSB, + BKN_DPP_FTMH_ACTION_TYPE_NOF_BITS, &fld_val); packet_info->ftmh.action_type = fld_val; /* PPH-type */ - bkn_dnx_bitstream_get_field( + bkn_bitstream_get_field( &hdr_buff[header_ptr], - BKN_DNX_FTMH_PPH_TYPE_MSB, - BKN_DNX_FTMH_PPH_TYPE_NOF_BITS, + BKN_DPP_FTMH_PPH_TYPE_MSB, + BKN_DPP_FTMH_PPH_TYPE_NOF_BITS, &fld_val); packet_info->ftmh.pph_type = fld_val; - packet_info->ntwrk_header_ptr += BKN_DNX_FTMH_SIZE_BYTE; + packet_info->ntwrk_header_ptr += BKN_DPP_FTMH_SIZE_BYTE; DBG_DUNE(("FTMH(%d) Packet-size %d Action-type %d PPH-type %d Source-system-port 0x%x Traffic-class %d\n", packet_info->ntwrk_header_ptr, packet_info->ftmh.packet_size, packet_info->ftmh.action_type, packet_info->ftmh.pph_type, packet_info->ftmh.src_sys_port, packet_info->ftmh.prio)); /* LB-Key ext */ - if ((sinfo->pkt_hdr_size & BKN_DNX_FTMH_LB_EXT_EN) == BKN_DNX_FTMH_LB_EXT_EN) + if ((sinfo->pkt_hdr_size & BKN_DPP_FTMH_LB_EXT_EN) == BKN_DPP_FTMH_LB_EXT_EN) { - packet_info->ntwrk_header_ptr += BKN_DNX_FTMH_LB_EXT_SIZE_BYTE; + packet_info->ntwrk_header_ptr += BKN_DPP_FTMH_LB_EXT_SIZE_BYTE; DBG_DUNE(("FTMH(%d) FTMH LB-Key Extension is present\n", packet_info->ntwrk_header_ptr)); } /* DSP ext*/ fld_val = 0; - bkn_dnx_bitstream_get_field( + bkn_bitstream_get_field( &hdr_buff[header_ptr], - BKN_DNX_FTMH_EXT_DSP_EXIST_MSB, - BKN_DNX_FTMH_EXT_DSP_EXIST_NOF_BITS, + BKN_DPP_FTMH_EXT_DSP_EXIST_MSB, + BKN_DPP_FTMH_EXT_DSP_EXIST_NOF_BITS, &dsp_ext_exist); if (dsp_ext_exist) { - packet_info->ntwrk_header_ptr += BKN_DNX_FTMH_DEST_EXT_SIZE_BYTE; + packet_info->ntwrk_header_ptr += BKN_DPP_FTMH_DEST_EXT_SIZE_BYTE; DBG_DUNE(("FTMH(%d) DSP-extension-present 1\n", packet_info->ntwrk_header_ptr)); } /* stacking ext */ - if ((sinfo->pkt_hdr_size & BKN_DNX_FTMH_STACKING_EXT_EN) == BKN_DNX_FTMH_STACKING_EXT_EN) + if ((sinfo->pkt_hdr_size & BKN_DPP_FTMH_STACKING_EXT_EN) == BKN_DPP_FTMH_STACKING_EXT_EN) { - packet_info->ntwrk_header_ptr += BKN_DNX_FTMH_STACKING_SIZE_BYTE; + packet_info->ntwrk_header_ptr += BKN_DPP_FTMH_STACKING_SIZE_BYTE; DBG_DUNE(("FTMH(%d) FTMH Stacking Extension is present\n", packet_info->ntwrk_header_ptr)); } return; } static void -bkn_dnx_packet_parse_internal(bkn_switch_info_t *sinfo, uint8_t hdr_buff[], bkn_dnx_packet_info *packet_info) +bkn_dpp_packet_parse_internal(bkn_switch_info_t *sinfo, uint8_t hdr_buff[], bkn_dune_system_header_info_t *packet_info) { uint32_t header_ptr = 0; uint32_t fld_val; @@ -2680,38 +2956,38 @@ bkn_dnx_packet_parse_internal(bkn_switch_info_t *sinfo, uint8_t hdr_buff[], bkn_ header_ptr = packet_info->ntwrk_header_ptr; - bkn_dnx_bitstream_get_field( + bkn_bitstream_get_field( &hdr_buff[header_ptr], - BKN_DNX_PPH_EEI_EXTENSION_PRESENT_MSB, - BKN_DNX_PPH_EEI_EXTENSION_PRESENT_NOF_BITS, + BKN_DPP_PPH_EEI_EXTENSION_PRESENT_MSB, + BKN_DPP_PPH_EEI_EXTENSION_PRESENT_NOF_BITS, &eei_extension_present); - bkn_dnx_bitstream_get_field( + bkn_bitstream_get_field( &hdr_buff[header_ptr], - BKN_DNX_PPH_LEARN_EXENSION_PRESENT_MSB, - BKN_DNX_PPH_LEARN_EXENSION_PRESENT_NOF_BITS, + BKN_DPP_PPH_LEARN_EXENSION_PRESENT_MSB, + BKN_DPP_PPH_LEARN_EXENSION_PRESENT_NOF_BITS, &learn_extension_present); - bkn_dnx_bitstream_get_field( + bkn_bitstream_get_field( &hdr_buff[header_ptr], - BKN_DNX_PPH_FHEI_SIZE_MSB, - BKN_DNX_PPH_FHEI_SIZE_NOF_BITS, + BKN_DPP_PPH_FHEI_SIZE_MSB, + BKN_DPP_PPH_FHEI_SIZE_NOF_BITS, &fhei_size); - bkn_dnx_bitstream_get_field( + bkn_bitstream_get_field( &hdr_buff[header_ptr], - BKN_DNX_PPH_FORWARD_CODE_MSB, - BKN_DNX_PPH_FORWARD_CODE_NOF_BITS, + BKN_DPP_PPH_FORWARD_CODE_MSB, + BKN_DPP_PPH_FORWARD_CODE_NOF_BITS, &forward_code); /* 7: CPU-Trap */ is_trapped = (uint8_t)(forward_code == 7); - bkn_dnx_bitstream_get_field( + bkn_bitstream_get_field( &hdr_buff[header_ptr], - BKN_DNX_PPH_VSI_MSB, - BKN_DNX_PPH_VSI_NOF_BITS, + BKN_DPP_PPH_VSI_MSB, + BKN_DPP_PPH_VSI_NOF_BITS, &fld_val); packet_info->internal.vsi = fld_val; /* size of PPH base is 7 */ - packet_info->ntwrk_header_ptr += BKN_DNX_PPH_SIZE_BYTE; + packet_info->ntwrk_header_ptr += BKN_DPP_PPH_SIZE_BYTE; header_ptr = packet_info->ntwrk_header_ptr; DBG_DUNE(("PPH(%d) Forward-Code %d EEI-Extension %d Learn-Extension %d VSI %d FHEI-size %d\n", packet_info->ntwrk_header_ptr, @@ -2721,38 +2997,38 @@ bkn_dnx_packet_parse_internal(bkn_switch_info_t *sinfo, uint8_t hdr_buff[], bkn_ if (is_trapped && (fhei_size == 1)) { /* CPU trap code qualifier */ - bkn_dnx_bitstream_get_field( + bkn_bitstream_get_field( &hdr_buff[header_ptr], - BKN_DNX_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_MSB, - BKN_DNX_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_NOF_BITS, + BKN_DPP_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_MSB, + BKN_DPP_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_NOF_BITS, &fld_val); packet_info->internal.trap_qualifier = fld_val; /* CPU trap code */ - bkn_dnx_bitstream_get_field( + bkn_bitstream_get_field( &hdr_buff[header_ptr], - BKN_DNX_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_MSB, - BKN_DNX_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_NOF_BITS, + BKN_DPP_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_MSB, + BKN_DPP_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_NOF_BITS, &fld_val); packet_info->internal.trap_id = fld_val; } switch(fhei_size) { case 1: - packet_info->ntwrk_header_ptr += BKN_DNX_PPH_FHEI_3B_SIZE_BYTE; + packet_info->ntwrk_header_ptr += BKN_DPP_PPH_FHEI_3B_SIZE_BYTE; break; case 2: - packet_info->ntwrk_header_ptr += BKN_DNX_PPH_FHEI_5B_SIZE_BYTE; + packet_info->ntwrk_header_ptr += BKN_DPP_PPH_FHEI_5B_SIZE_BYTE; break; case 3: - packet_info->ntwrk_header_ptr += BKN_DNX_PPH_FHEI_8B_SIZE_BYTE; + packet_info->ntwrk_header_ptr += BKN_DPP_PPH_FHEI_8B_SIZE_BYTE; break; default: break; } if (eei_extension_present) { - packet_info->ntwrk_header_ptr += BKN_DNX_PPH_EXPLICIT_EDITING_INFOMATION_EXTENSION_SIZE_BYTE; + packet_info->ntwrk_header_ptr += BKN_DPP_PPH_EXPLICIT_EDITING_INFOMATION_EXTENSION_SIZE_BYTE; } if (learn_extension_present) { - packet_info->ntwrk_header_ptr += BKN_DNX_PPH_LEARN_EXTENSION_SIZE_BYTE; + packet_info->ntwrk_header_ptr += BKN_DPP_PPH_LEARN_EXTENSION_SIZE_BYTE; } DBG_DUNE(("FHEI(%d) trap_qualifier 0x%x trap_id 0x%x\n", packet_info->ntwrk_header_ptr, packet_info->internal.trap_qualifier, packet_info->internal.trap_id)); @@ -2760,23 +3036,23 @@ bkn_dnx_packet_parse_internal(bkn_switch_info_t *sinfo, uint8_t hdr_buff[], bkn_ } static int -bkn_dnx_packet_header_parse(bkn_switch_info_t *sinfo, uint8 *buff, uint32_t buff_len, bkn_dnx_packet_info *packet_info) +bkn_dpp_packet_header_parse(bkn_switch_info_t *sinfo, uint8 *buff, uint32_t buff_len, bkn_dune_system_header_info_t *packet_info) { - uint8_t hdr_buff[BKN_DNX_HDR_MAX_SIZE]; + uint8_t hdr_buff[BKN_DPP_HDR_MAX_SIZE]; uint32_t hdr_size; uint8_t has_internal = 0; if ((buff == NULL) || (packet_info == NULL)) { return -1; } - hdr_size = buff_len < BKN_DNX_HDR_MAX_SIZE ? buff_len: BKN_DNX_HDR_MAX_SIZE; + hdr_size = buff_len < BKN_DPP_HDR_MAX_SIZE ? buff_len: BKN_DPP_HDR_MAX_SIZE; memcpy(hdr_buff, buff, hdr_size); /* FTMH */ - bkn_dnx_packet_parse_ftmh(sinfo, hdr_buff, packet_info); + bkn_dpp_packet_parse_ftmh(sinfo, hdr_buff, packet_info); if (packet_info->ftmh.packet_size != (buff_len + 2)) { DBG_DUNE(("FTMH packet size verfication failed, %d-%d\n", packet_info->ftmh.packet_size, buff_len)); - memset(packet_info, 0, sizeof(bkn_dnx_packet_info)); + memset(packet_info, 0, sizeof(bkn_dune_system_header_info_t)); return -1; } switch (packet_info->ftmh.pph_type) { @@ -2798,7 +3074,7 @@ bkn_dnx_packet_header_parse(bkn_switch_info_t *sinfo, uint8 *buff, uint32_t buff } if (has_internal) { - bkn_dnx_packet_parse_internal(sinfo, &hdr_buff[0], packet_info); + bkn_dpp_packet_parse_internal(sinfo, &hdr_buff[0], packet_info); } /* FIXME: */ @@ -2807,6 +3083,398 @@ bkn_dnx_packet_header_parse(bkn_switch_info_t *sinfo, uint8 *buff, uint32_t buff return 0; } +static int +bkn_dnx_packet_header_parse(bkn_switch_info_t *sinfo, uint8 *buf, uint32_t buf_len, bkn_dune_system_header_info_t *packet_info) +{ + uint32_t fld_val; + uint32_t hdr_size = 0; + uint32_t pkt_offset_ingress_untrapped =0; + uint8_t tm_dst_ext_present = 0; + uint8_t app_specific_ext_size = 0; + uint8_t flow_id_ext_size = 0; + uint8_t bier_bfr_ext_size = 0; + uint8_t is_pph_en = 0; + uint8_t is_tsh_en = 0; + + if ((buf == NULL) || (packet_info == NULL)) { + return -1; + } + + /* FTMH: Source-System-Port-Aggregate */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_FTMH_SRC_SYS_PORT_AGGREGATE_MSB, + BKN_DNX_FTMH_SRC_SYS_PORT_AGGREGATE_NOF_BITS, + &fld_val); + packet_info->ftmh_spa = fld_val; + /* FTMH: PPH-Type TSH */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_FTMH_PPH_TYPE_IS_TSH_EN_MSB, + BKN_DNX_FTMH_PPH_TYPE_IS_TSH_EN_NOF_BITS, + &fld_val); + is_tsh_en = fld_val; + /* FTMH: PPH-Type PPH base */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_FTMH_PPH_TYPE_IS_PPH_EN_MSB, + BKN_DNX_FTMH_PPH_TYPE_IS_PPH_EN_NOF_BITS, + &fld_val); + is_pph_en = fld_val; + /* FTMH: TM-Destination-Extension-Present */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_FTMH_TM_DST_EXT_PRESENT_MSB, + BKN_DNX_FTMH_TM_DST_EXT_PRESENT_NOF_BITS, + &fld_val); + tm_dst_ext_present = fld_val; + /* FTMH: Application-Specific-Extension-Size */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE_MSB, + BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE_NOF_BITS, + &fld_val); + app_specific_ext_size = fld_val; + /* FTMH: Flow-ID-Extension-Size */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_FTMH_FLOW_ID_EXT_SIZE_MSB, + BKN_DNX_FTMH_FLOW_ID_EXT_SIZE_NOF_BITS, + &fld_val); + flow_id_ext_size = fld_val; + /* FTMH: BIER-BFR-Extension-Size */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_FTMH_BIER_BFR_EXT_SIZE_MSB, + BKN_DNX_FTMH_BIER_BFR_EXT_SIZE_NOF_BITS, + &fld_val); + bier_bfr_ext_size = fld_val; + + hdr_size = BKN_DNX_FTMH_BASE_SIZE; + pkt_offset_ingress_untrapped = BKN_DNX_FTMH_BASE_SIZE; + + DBG_DUNE(("FTMH(%d) source-system-port 0x%x is_tsh_en %d is_pph_en %d\n", + hdr_size, packet_info->ftmh_spa, is_tsh_en, is_pph_en)); + + /* FTMH LB-Key Extension */ + if (sinfo->ftmh_lb_key_ext_size > 0) + { + hdr_size += sinfo->ftmh_lb_key_ext_size; + DBG_DUNE(("FTMH LB-Key Extension(%d) is present\n", sinfo->ftmh_lb_key_ext_size)); + } + /* FTMH Stacking Extension */ + if (sinfo->ftmh_stacking_ext_size > 0) + { + hdr_size += sinfo->ftmh_stacking_ext_size; + DBG_DUNE(("FTMH Stacking Extension(%d) is present\n", sinfo->ftmh_stacking_ext_size)); + } + /* FTMH BIER BFR Extension */ + if (bier_bfr_ext_size > 0) + { + hdr_size += BKN_DNX_FTMH_BIER_BFR_EXT_SIZE; + DBG_DUNE(("FTMH BIER BFR Extension(2) is present\n")); + } + /* FTMH TM Destination Extension */ + if (tm_dst_ext_present > 0) + { + hdr_size += BKN_DNX_FTMH_TM_DST_EXT_SIZE; + DBG_DUNE(("FTMH TM Destination Extension(3) is present\n")); + } + /* FTMH Application Specific Extension */ + if (app_specific_ext_size > 0) + { + hdr_size += BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE; + DBG_DUNE(("FTMH Application Specific Extension(6) is present\n")); + } + /* FTMH Flow-ID Extension */ + if (flow_id_ext_size > 0) + { + hdr_size += BKN_DNX_FTMH_FLOW_ID_EXT_SIZE; + DBG_DUNE(("FTMH Flow-ID Extension(3) is present\n")); + } + + /* Given the packet is trapped to CPU */ + + /* Time-Stamp Header */ + if (is_tsh_en == TRUE) + { + hdr_size += BKN_DNX_TSH_SIZE; + DBG_DUNE(("Time-Stamp Header(4) is present\n")); + } + + /* Packet Processing Header */ + if (is_pph_en) + { + uint8_t learn_ext_present; + uint8_t fhei_size; + uint8_t lif_ext_type; + + switch (sinfo->pph_base_size) + { + case BKN_DNX_PPH_BASE_TYPE_9: + /* FTMH: Forward-Domain */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_PPH_9_FORWARD_DOMAIN_MSB, + BKN_DNX_PPH_9_FORWARD_DOMAIN_NOF_BITS, + &fld_val); + packet_info->pph_forward_domain = fld_val; + /* FTMH: Learn-Extension-Present */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_PPH_9_LEARN_EXT_PRESENT_MSB, + BKN_DNX_PPH_9_LEARN_EXT_PRESENT_NOF_BITS, + &fld_val); + learn_ext_present = fld_val; + /* FTMH: FHEI-Size */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_PPH_9_FHEI_SIZE_MSB, + BKN_DNX_PPH_9_FHEI_SIZE_NOF_BITS, + &fld_val); + fhei_size = fld_val; + /* FTMH: LIF-Extension-Type */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_PPH_9_LIF_EXT_TYPE_MSB, + BKN_DNX_PPH_9_LIF_EXT_TYPE_NOF_BITS, + &fld_val); + lif_ext_type = fld_val; + + hdr_size += BKN_DNX_PPH_BASE_TYPE_9; + DBG_DUNE(("PPH(10) FWD_DOMAIN %d, LEARN_EXT %d, FHEI_SIZE %d, LIF_EXT %d \n", + packet_info->pph_forward_domain, learn_ext_present, fhei_size, lif_ext_type)); + break; + case BKN_DNX_PPH_BASE_TYPE_10: + /* FTMH: Forward-Domain */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_PPH_10_FORWARD_DOMAIN_MSB, + BKN_DNX_PPH_10_FORWARD_DOMAIN_NOF_BITS, + &fld_val); + packet_info->pph_forward_domain = fld_val; + /* FTMH: Learn-Extension-Present */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_PPH_10_LEARN_EXT_PRESENT_MSB, + BKN_DNX_PPH_10_LEARN_EXT_PRESENT_NOF_BITS, + &fld_val); + learn_ext_present = fld_val; + /* FTMH: FHEI-Size */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_PPH_10_FHEI_SIZE_MSB, + BKN_DNX_PPH_10_FHEI_SIZE_NOF_BITS, + &fld_val); + fhei_size = fld_val; + /* FTMH: LIF-Extension-Type */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_PPH_10_LIF_EXT_TYPE_MSB, + BKN_DNX_PPH_10_LIF_EXT_TYPE_NOF_BITS, + &fld_val); + lif_ext_type = fld_val; + + hdr_size += BKN_DNX_PPH_BASE_TYPE_10; + DBG_DUNE(("PPH(10) FWD_DOMAIN %d, LEARN_EXT %d, FHEI_SIZE %d, LIF_EXT %d \n", + packet_info->pph_forward_domain, learn_ext_present, fhei_size, lif_ext_type)); + break; + case BKN_DNX_PPH_BASE_TYPE_12: + /* FTMH: Forward-Domain */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_PPH_12_FORWARD_DOMAIN_MSB, + BKN_DNX_PPH_12_FORWARD_DOMAIN_NOF_BITS, + &fld_val); + packet_info->pph_forward_domain = fld_val; + /* FTMH: Learn-Extension-Present */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_PPH_12_LEARN_EXT_PRESENT_MSB, + BKN_DNX_PPH_12_LEARN_EXT_PRESENT_NOF_BITS, + &fld_val); + learn_ext_present = fld_val; + /* FTMH: FHEI-Size */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_PPH_12_FHEI_SIZE_MSB, + BKN_DNX_PPH_12_FHEI_SIZE_NOF_BITS, + &fld_val); + fhei_size = fld_val; + /* FTMH: LIF-Extension-Type */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_PPH_12_LIF_EXT_TYPE_MSB, + BKN_DNX_PPH_12_LIF_EXT_TYPE_NOF_BITS, + &fld_val); + lif_ext_type = fld_val; + + hdr_size += BKN_DNX_PPH_BASE_TYPE_12; + DBG_DUNE(("PPH(12) FWD_DOMAIN %d, LEARN_EXT %d, FHEI_SIZE %d, LIF_EXT %d \n", + packet_info->pph_forward_domain, learn_ext_present, fhei_size, lif_ext_type)); + break; + default: + fhei_size = 0; + lif_ext_type = 0; + learn_ext_present = 0; + break; + } + if (fhei_size) + { + switch (fhei_size) + { + case BKN_DNX_PPH_FHEI_TYPE_SZ0: + hdr_size += BKN_DNX_PPH_FHEI_SZ0_SIZE; + DBG_DUNE(("FHEI(3) is present\n")); + break; + case BKN_DNX_PPH_FHEI_TYPE_SZ1: + /* FHEI: Code */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_PPH_FHEI_TRAP_5B_TYPE_MSB, + BKN_DNX_PPH_FHEI_TRAP_5B_TYPE_NOF_BITS, + &fld_val); + packet_info->fhei_type = fld_val; + /* FHEI-Size == 5B, FHEI-Type == Trap/Sniff */ + if (packet_info->fhei_type == 0x5) + { + /* FHEI: Qualifier */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_PPH_FHEI_TRAP_5B_QUALIFIER_MSB, + BKN_DNX_PPH_FHEI_TRAP_5B_QUALIFIER_NOF_BITS, + &fld_val); + packet_info->fhei_qualifier = fld_val; + /* FHEI: Code */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_PPH_FHEI_TRAP_5B_CODE_MSB, + BKN_DNX_PPH_FHEI_TRAP_5B_CODE_NOF_BITS, + &fld_val); + packet_info->fhei_code = fld_val; + } + hdr_size += BKN_DNX_PPH_FHEI_SZ1_SIZE; + DBG_DUNE(("FHEI(5) is present code 0x%x qualifier 0x%x\n", packet_info->fhei_code, packet_info->fhei_qualifier)); + break; + case BKN_DNX_PPH_FHEI_TYPE_SZ2: + hdr_size += BKN_DNX_PPH_FHEI_SZ1_SIZE; + DBG_DUNE(("FHEI(8) is present\n")); + break; + } + } + + /* PPH LIF Extension */ + if (lif_ext_type) + { + hdr_size += sinfo->pph_lif_ext_size[lif_ext_type]; + DBG_DUNE(("PPH LIF Extension(%d) is present\n", sinfo->pph_lif_ext_size[lif_ext_type])); + } + + /* PPH Learn Extension */ + if (learn_ext_present) + { + hdr_size += BKN_DNX_PPH_LEARN_EXT_SIZE; + DBG_DUNE(("PPH Learn Extension(19) is present\n")); + } + } + + /* UDH Header */ + if (sinfo->udh_enable) + { + uint8 data_type_0; + uint8 data_type_1; + uint8 data_type_2; + uint8 data_type_3; + + DBG_DUNE(("UDH base(1) is present\n")); + + /* UDH: UDH-Data-Type[0] */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_UDH_DATA_TYPE_0_MSB, + BKN_DNX_UDH_DATA_TYPE_0_NOF_BITS, + &fld_val); + data_type_0 = fld_val; + hdr_size += sinfo->udh_length_type[data_type_0]; + /* UDH: UDH-Data-Type[1] */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_UDH_DATA_TYPE_1_MSB, + BKN_DNX_UDH_DATA_TYPE_1_NOF_BITS, + &fld_val); + data_type_1 = fld_val; + hdr_size += sinfo->udh_length_type[data_type_1]; + /* UDH: UDH-Data-Type[2] */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_UDH_DATA_TYPE_2_MSB, + BKN_DNX_UDH_DATA_TYPE_2_NOF_BITS, + &fld_val); + data_type_2 = fld_val; + hdr_size += sinfo->udh_length_type[data_type_2]; + /* UDH: UDH-Data-Type[3] */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_UDH_DATA_TYPE_3_MSB, + BKN_DNX_UDH_DATA_TYPE_3_NOF_BITS, + &fld_val); + data_type_3 = fld_val; + hdr_size += sinfo->udh_length_type[data_type_3]; + hdr_size += BKN_DNX_UDH_BASE_SIZE; + } + + /* + * Check if fhei_type if of type trap + * There is a RISK that raw packet data is parsed and fhei_type is 0x5 by chance + */ + if (packet_info->fhei_type == 0x5) + { + /* Done for ingress trapped packets */ + packet_info->system_header_size = hdr_size; + DBG_DUNE(("Total Size of Headers is %d\n", packet_info->system_header_size)); + return 0; + } + else + { + /* New generated header will be FTMH(80b), TSH(32b), PPH(96b), FHEI(40b) */ + + /* Revert packet_info except info from FTHM base header */ + packet_info->fhei_qualifier = 0; + packet_info->fhei_code = 0; + packet_info->fhei_type = 0; + hdr_size = pkt_offset_ingress_untrapped; + + /* Time-Stamp Header */ + hdr_size += BKN_DNX_TSH_SIZE; + DBG_DUNE(("Time-Stamp Header(4) is present\n")); + + /** Packet Processing Header */ + bkn_bitstream_get_field( + &buf[hdr_size], + BKN_DNX_PPH_12_FORWARD_DOMAIN_MSB, + BKN_DNX_PPH_12_FORWARD_DOMAIN_NOF_BITS, + &fld_val); + packet_info->pph_forward_domain = fld_val; + hdr_size += BKN_DNX_PPH_BASE_TYPE_12; + DBG_DUNE(("PPH(12) is present\n")); + + /* + * FHEI(Trap,40) + * 5B-FHEI format for sys_hdr_generation_profile:J2-OAM + * 8b' 0 + * 19b'oam_id + * 9b' cpu_trap_code: INGRESS_TRAP_ID is always 0 here + * 4b' type(0x5): J2-Configuration FHEI Type for CPU trap + */ + hdr_size += BKN_DNX_PPH_FHEI_SZ1_SIZE; + DBG_DUNE(("FHEI(5) is present\n")); + } + packet_info->system_header_size = hdr_size; + DBG_DUNE(("Total Size of Headers is %d\n", packet_info->system_header_size)); + return 0; +} + + static int bkn_do_api_rx(bkn_switch_info_t *sinfo, int chan, int budget) { @@ -2824,7 +3492,8 @@ bkn_do_api_rx(bkn_switch_info_t *sinfo, int chan, int budget) int pktlen; int idx; int dcbs_done = 0; - bkn_dnx_packet_info packet_info = {0}; + bkn_dune_system_header_info_t packet_info = {0}; + uint32_t dnx_meta_data[3] = {0}; dcb_chain = sinfo->rx[chan].api_dcb_chain; if (dcb_chain == NULL) { @@ -2868,9 +3537,16 @@ bkn_do_api_rx(bkn_switch_info_t *sinfo, int chan, int budget) } pkt = (uint8_t *)kernel_bde->p2l(sinfo->dev_no, (sal_paddr_t)pkt_dma); if (sinfo->cmic_type == 'x') { - meta = (uint32_t *)pkt; - err_woff = sinfo->pkt_hdr_size / sizeof(uint32_t) - 1; - meta[err_woff] = dcb[sinfo->dcb_wsize-1]; + if (device_is_dnx(sinfo)){ + meta = &dnx_meta_data[0]; + /* get error bit from last DCB words */ + err_woff = 2; + meta[err_woff] = dcb[sinfo->dcb_wsize-1]; + } else { + meta = (uint32_t *)pkt; + err_woff = sinfo->pkt_hdr_size / sizeof(uint32_t) - 1; + meta[err_woff] = dcb[sinfo->dcb_wsize-1]; + } } else { meta = dcb; err_woff = sinfo->dcb_wsize - 1; @@ -2878,22 +3554,22 @@ bkn_do_api_rx(bkn_switch_info_t *sinfo, int chan, int budget) pktlen = dcb[sinfo->dcb_wsize-1] & SOC_DCB_KNET_COUNT_MASK; bkn_dump_pkt(pkt, pktlen, XGS_DMA_RX_CHAN); - if (device_is_dune(sinfo)) { + if (device_is_dpp(sinfo)) { uint16_t tpid = 0; uint16_t vid = 0; int res = -1; - memset(&packet_info, 0, sizeof(bkn_dnx_packet_info)); - res = bkn_dnx_packet_header_parse(sinfo, pkt, (uint32_t)pktlen, &packet_info); + memset(&packet_info, 0, sizeof(bkn_dune_system_header_info_t)); + res = bkn_dpp_packet_header_parse(sinfo, pkt, (uint32_t)pktlen, &packet_info); if (res == 0) { if (packet_info.ftmh.action_type == 0x2) { - bkn_dnx_bitstream_set_field((uint32_t *)dcb, 192, 32, 0x8); + bkn_bitstream_set_field((uint32_t *)dcb, 192, 32, 0x8); } else if (packet_info.ftmh.action_type == 0x1) { - bkn_dnx_bitstream_set_field((uint32_t *)dcb, 231, 25, 0x20); + bkn_bitstream_set_field((uint32_t *)dcb, 231, 25, 0x20); } - bkn_dnx_bitstream_set_field((uint32_t *)dcb, 112, 16, packet_info.ftmh.src_sys_port); - bkn_dnx_bitstream_set_field((uint32_t *)dcb, 296, 12, packet_info.internal.vsi); - bkn_dnx_bitstream_set_field((uint32_t *)dcb, 64, 32, (packet_info.internal.trap_id << 16 | packet_info.internal.trap_qualifier)); + bkn_bitstream_set_field((uint32_t *)dcb, 112, 16, packet_info.ftmh.src_sys_port); + bkn_bitstream_set_field((uint32_t *)dcb, 296, 12, packet_info.internal.vsi); + bkn_bitstream_set_field((uint32_t *)dcb, 64, 32, (packet_info.internal.trap_id << 16 | packet_info.internal.trap_qualifier)); pkt += packet_info.ntwrk_header_ptr; pktlen -= packet_info.ntwrk_header_ptr; bkn_dump_pkt(pkt, 32, XGS_DMA_RX_CHAN); @@ -2919,10 +3595,25 @@ bkn_do_api_rx(bkn_switch_info_t *sinfo, int chan, int budget) } } } + else if (device_is_dnx(sinfo)) { + int res = -1; + res = bkn_dnx_packet_header_parse(sinfo, pkt, (uint32_t)pktlen, &packet_info); + if (res == 0) { + bkn_bitstream_set_field(meta, 0, 16, packet_info.fhei_code); + bkn_bitstream_set_field(meta, 16, 16, packet_info.fhei_qualifier); + bkn_bitstream_set_field(meta, 32, 16, packet_info.ftmh_spa); + bkn_bitstream_set_field(meta, 48, 16, (packet_info.pph_forward_domain & 0xffff)); - if (device_is_dune(sinfo)) { - filter = bkn_match_rx_pkt(sinfo, pkt, pktlen + packet_info.ntwrk_header_ptr, - dcb, chan, &cbf); + pkt += packet_info.system_header_size; + pktlen -= packet_info.system_header_size; + bkn_dump_pkt(pkt, 32, XGS_DMA_RX_CHAN); + } + } + + if (device_is_dpp(sinfo)) { + filter = bkn_match_rx_pkt(sinfo, pkt, pktlen, dcb, chan, &cbf); + } else if (device_is_dnx(sinfo)) { + filter = bkn_match_rx_pkt(sinfo, pkt, pktlen, meta, chan, &cbf); } else { filter = bkn_match_rx_pkt(sinfo, pkt + sinfo->pkt_hdr_size, pktlen - sinfo->pkt_hdr_size, meta, chan, &cbf); @@ -3001,7 +3692,7 @@ bkn_do_api_rx(bkn_switch_info_t *sinfo, int chan, int budget) } skb_copy_to_linear_data(skb, pkt, pktlen); - if (device_is_dune(sinfo)) { + if (device_is_sand(sinfo)) { /* CRC has been stripped */ skb_put(skb, pktlen); } else { @@ -3023,6 +3714,11 @@ bkn_do_api_rx(bkn_switch_info_t *sinfo, int chan, int budget) } } + /* Do Rx timestamping */ + if (sinfo->rx_hwts) { + bkn_hw_tstamp_rx_set(sinfo, skb, meta); + } + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { bkn_add_rcpu_encap(sinfo, skb, meta); DBG_PDMP(("After add RCPU ENCAP\n")); @@ -3095,7 +3791,8 @@ bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget) int pktlen; int idx; int dcbs_done = 0; - bkn_dnx_packet_info packet_info = {0}; + bkn_dune_system_header_info_t packet_info = {0}; + uint32_t dnx_meta_data[3] = {0}; if (!sinfo->rx[chan].running) { /* Rx not ready */ @@ -3122,9 +3819,16 @@ bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget) sinfo->rx[chan].pkts++; skb = desc->skb; if (sinfo->cmic_type == 'x') { - meta = (uint32_t *)skb->data; - err_woff = sinfo->pkt_hdr_size / sizeof(uint32_t) - 1; - meta[err_woff] = dcb[sinfo->dcb_wsize-1]; + if (device_is_dnx(sinfo)){ + meta = &dnx_meta_data[0]; + /* get error bit from last DCB words */ + err_woff = 2; + meta[err_woff] = dcb[sinfo->dcb_wsize-1]; + } else { + meta = (uint32_t *)skb->data; + err_woff = sinfo->pkt_hdr_size / sizeof(uint32_t) - 1; + meta[err_woff] = dcb[sinfo->dcb_wsize-1]; + } } else { meta = dcb; err_woff = sinfo->dcb_wsize - 1; @@ -3138,23 +3842,23 @@ bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget) desc->skb_dma = 0; bkn_dump_pkt(skb->data, pktlen, XGS_DMA_RX_CHAN); - if (device_is_dune(sinfo)) { + if (device_is_dpp(sinfo)) { uint16_t tpid = 0; uint16_t vid = 0; uint8_t *pkt = skb->data; int res = 0; - memset(&packet_info, 0, sizeof(bkn_dnx_packet_info)); - res = bkn_dnx_packet_header_parse(sinfo, pkt, (uint32_t)pktlen, &packet_info); + memset(&packet_info, 0, sizeof(bkn_dune_system_header_info_t)); + res = bkn_dpp_packet_header_parse(sinfo, pkt, (uint32_t)pktlen, &packet_info); if (res == 0) { if (packet_info.ftmh.action_type == 0x2) { - bkn_dnx_bitstream_set_field((uint32_t *)dcb, 192, 32, 0x8); + bkn_bitstream_set_field((uint32_t *)dcb, 192, 32, 0x8); } else if (packet_info.ftmh.action_type == 0x1) { - bkn_dnx_bitstream_set_field((uint32_t *)dcb, 231, 25, 0x20); + bkn_bitstream_set_field((uint32_t *)dcb, 231, 25, 0x20); } - bkn_dnx_bitstream_set_field((uint32_t *)dcb, 112, 16, packet_info.ftmh.src_sys_port); - bkn_dnx_bitstream_set_field((uint32_t *)dcb, 296, 12, packet_info.internal.vsi); - bkn_dnx_bitstream_set_field((uint32_t *)dcb, 64, 32, (packet_info.internal.trap_id << 16 | packet_info.internal.trap_qualifier)); + bkn_bitstream_set_field((uint32_t *)dcb, 112, 16, packet_info.ftmh.src_sys_port); + bkn_bitstream_set_field((uint32_t *)dcb, 296, 12, packet_info.internal.vsi); + bkn_bitstream_set_field((uint32_t *)dcb, 64, 32, (packet_info.internal.trap_id << 16 | packet_info.internal.trap_qualifier)); pkt = skb->data + packet_info.ntwrk_header_ptr; /* check if vlan tag exists */ tpid = (uint16_t)((pkt[12] << 8) | pkt[13]); @@ -3178,10 +3882,29 @@ bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget) } } } + else if (device_is_dnx(sinfo)) { + uint8_t *pkt = skb->data; + int res = -1; - if (device_is_dune(sinfo)) { - filter = bkn_match_rx_pkt(sinfo, skb->data + packet_info.ntwrk_header_ptr, + res = bkn_dnx_packet_header_parse(sinfo, pkt, (uint32_t)pktlen, &packet_info); + if (res == 0) { + bkn_bitstream_set_field(meta, 0, 16, packet_info.fhei_code); + bkn_bitstream_set_field(meta, 16, 16, packet_info.fhei_qualifier); + bkn_bitstream_set_field(meta, 32, 16, packet_info.ftmh_spa); + bkn_bitstream_set_field(meta, 48, 16, (packet_info.pph_forward_domain & 0xffff)); + + pkt += packet_info.system_header_size; + pktlen -= packet_info.ntwrk_header_ptr; + bkn_dump_pkt(pkt, 32, XGS_DMA_RX_CHAN); + } + } + + if (device_is_dpp(sinfo)) { + filter = bkn_match_rx_pkt(sinfo, skb->data + packet_info.ntwrk_header_ptr, pktlen, dcb, chan, &cbf); + } else if (device_is_dnx(sinfo)) { + filter = bkn_match_rx_pkt(sinfo, skb->data + packet_info.system_header_size, + pktlen, meta, chan, &cbf); } else { filter = bkn_match_rx_pkt(sinfo, skb->data + sinfo->pkt_hdr_size, pktlen - sinfo->pkt_hdr_size, meta, chan, &cbf); @@ -3216,12 +3939,12 @@ bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget) sinfo->rx[chan].pkts_f_netif++; if (((filter->kf.mirror_type == KCOM_DEST_T_API) && - (!device_is_dune(sinfo))) || dbg_pkt_enable) { + (!device_is_sand(sinfo))) || dbg_pkt_enable) { sinfo->rx[chan].pkts_m_api++; bkn_api_rx_copy_from_skb(sinfo, chan, desc); } - if (device_is_dune(sinfo)) { + if (device_is_dpp(sinfo)) { if (filter->kf.mirror_type == KCOM_DEST_T_API) { sinfo->rx[chan].pkts_m_api++; bkn_api_rx_copy_from_skb(sinfo, chan, desc); @@ -3232,11 +3955,22 @@ bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget) bkn_dump_pkt(skb->data, 32, XGS_DMA_RX_CHAN); /* CRC has been stripped on Dune*/ skb_put(skb, pktlen); + } else if (device_is_dnx(sinfo)) { + if (filter->kf.mirror_type == KCOM_DEST_T_API) { + sinfo->rx[chan].pkts_m_api++; + bkn_api_rx_copy_from_skb(sinfo, chan, desc); + } + /* Strip Dune headers */ + skb->data += packet_info.system_header_size; + pktlen -= packet_info.system_header_size; + bkn_dump_pkt(skb->data, 32, XGS_DMA_RX_CHAN); + /* CRC has been stripped on Dune*/ + skb_put(skb, pktlen); } else { skb_put(skb, pktlen - 4); /* Strip CRC */ } - if (sinfo->cmic_type == 'x') { + if (sinfo->cmic_type == 'x' && !device_is_dnx(sinfo)) { skb_pull(skb, sinfo->pkt_hdr_size); } @@ -3252,7 +3986,7 @@ bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget) ((u32*)skb->data)[2] = ((u32*)skb->data)[1]; ((u32*)skb->data)[1] = ((u32*)skb->data)[0]; skb_pull(skb, 4); - if (sinfo->cmic_type == 'x') { + if (sinfo->cmic_type == 'x' && !device_is_dnx(sinfo)) { for (idx = sinfo->pkt_hdr_size / sizeof(uint32_t); idx; idx--) { meta[idx] = meta[idx - 1]; } @@ -3292,6 +4026,11 @@ bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget) } } + /* Do Rx timestamping */ + if (sinfo->rx_hwts) { + bkn_hw_tstamp_rx_set(sinfo, skb, meta); + } + if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { bkn_add_rcpu_encap(sinfo, skb, meta); DBG_PDMP(("After add RCPU ENCAP\n")); @@ -3489,6 +4228,45 @@ bkn_resume_tx(bkn_switch_info_t *sinfo) } } +static int +bkn_hw_tstamp_tx_set(bkn_switch_info_t *sinfo, struct sk_buff *skb) +{ + struct skb_shared_hwtstamps shhwtstamps; + uint64_t ts = 0; + uint32_t hdrlen = sinfo->cmic_type == 'x' ? PKT_TX_HDR_SIZE : 0; + int port; + + if (!knet_hw_tstamp_tx_time_get_cb) { + return -1; + } + + port = KNET_SKB_CB(skb)->port; + if (knet_hw_tstamp_tx_time_get_cb(sinfo->dev_no, port, skb->data + hdrlen, &ts) < 0) { + return -1; + } + + memset(&shhwtstamps, 0, sizeof(shhwtstamps)); + shhwtstamps.hwtstamp = ns_to_ktime(be64_to_cpu(ts)); + skb_tstamp_tx(skb, &shhwtstamps); + + return 0; +} + +static void +bkn_hw_tstamp_tx_work(struct work_struct *work) +{ + bkn_switch_info_t *sinfo = container_of(work, bkn_switch_info_t, tx_ptp_work); + struct sk_buff *skb; + + while (skb_queue_len(&sinfo->tx_ptp_queue)) { + skb = skb_dequeue(&sinfo->tx_ptp_queue); + if (bkn_hw_tstamp_tx_set(sinfo, skb) < 0) { + gprintk("Timestamp has not been taken for the current skb.\n"); + } + dev_kfree_skb_any(skb); + } +} + static int bkn_do_tx(bkn_switch_info_t *sinfo) { @@ -3515,7 +4293,12 @@ bkn_do_tx(bkn_switch_info_t *sinfo) DMA_UNMAP_SINGLE(sinfo->dma_dev, desc->skb_dma, desc->dma_size, DMA_TODEV); - dev_kfree_skb_any(desc->skb); + if (bkn_skb_tx_flags(desc->skb) & SKBTX_IN_PROGRESS) { + skb_queue_tail(&sinfo->tx_ptp_queue, desc->skb); + schedule_work(&sinfo->tx_ptp_work); + } else { + dev_kfree_skb_any(desc->skb); + } desc->skb = NULL; desc->skb_dma = 0; } @@ -3926,10 +4709,16 @@ xgsx_do_dma(bkn_switch_info_t *sinfo, int budget) { int rx_dcbs_done = 0, tx_dcbs_done = 0; int chan_done, budget_chans = 0; - uint32_t irq_stat; + uint32_t irq_stat, tx_dma_stat, rx_dma_stat[NUM_CMICX_RX_CHAN]; int chan; DEV_READ32(sinfo, CMICX_IRQ_STATr, &irq_stat); + DEV_READ32(sinfo, CMICX_DMA_STATr + 0x80 * XGS_DMA_TX_CHAN, &tx_dma_stat); + for (chan = 0; chan < sinfo->rx_chans; chan++) { + DEV_READ32(sinfo, + CMICX_DMA_STATr + 0x80 * (XGS_DMA_RX_CHAN + chan), + &rx_dma_stat[chan]); + } for (chan = 0; chan < sinfo->rx_chans; chan++) { if ((irq_stat & CMICX_DS_CMC_CTRLD_INT(XGS_DMA_RX_CHAN + chan)) || @@ -3964,14 +4753,14 @@ xgsx_do_dma(bkn_switch_info_t *sinfo, int budget) continue; } - if (irq_stat & CMICX_DS_CMC_CHAIN_DONE(XGS_DMA_RX_CHAN + chan)) { + if (rx_dma_stat[chan] & CMICX_DS_CMC_DMA_CHAIN_DONE) { xgsx_dma_chain_clear(sinfo, XGS_DMA_RX_CHAN + chan); bkn_rx_chain_done(sinfo, chan); } } if ((irq_stat & CMICX_DS_CMC_CTRLD_INT(XGS_DMA_TX_CHAN)) || - (irq_stat & CMICX_DS_CMC_CHAIN_DONE(XGS_DMA_TX_CHAN))) { + (tx_dma_stat & CMICX_DS_CMC_DMA_CHAIN_DONE)) { if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) { xgsx_dma_desc_clear(sinfo, XGS_DMA_TX_CHAN); } else { @@ -4229,6 +5018,70 @@ bkn_set_mac_address(struct net_device *dev, void *addr) } #endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) +static int +bkn_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + bkn_priv_t *priv = netdev_priv(dev); + bkn_switch_info_t *sinfo = priv->sinfo; + struct hwtstamp_config config; + + if (cmd == SIOCSHWTSTAMP) { + if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) { + return -EFAULT; + } + + if (!knet_hw_tstamp_enable_cb || !knet_hw_tstamp_disable_cb || + priv->type != KCOM_NETIF_T_PORT) { + return -ERANGE; + } + + switch (config.tx_type) { + case HWTSTAMP_TX_OFF: + knet_hw_tstamp_disable_cb(sinfo->dev_no, priv->port); + sinfo->tx_hwts = 0; + break; + case HWTSTAMP_TX_ON: + knet_hw_tstamp_enable_cb(sinfo->dev_no, priv->port); + sinfo->tx_hwts = 1; + break; + default: + return -ERANGE; + } + + switch (config.rx_filter) { + case HWTSTAMP_FILTER_NONE: + if (sinfo->rx_hwts) { + knet_hw_tstamp_disable_cb(sinfo->dev_no, priv->port); + sinfo->rx_hwts = 0; + } + break; + default: + if (!sinfo->rx_hwts) { + knet_hw_tstamp_enable_cb(sinfo->dev_no, priv->port); + sinfo->rx_hwts = 1; + } + config.rx_filter = HWTSTAMP_FILTER_ALL; + break; + } + + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) + if (cmd == SIOCGHWTSTAMP) { + config.flags = 0; + config.tx_type = sinfo->tx_hwts ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; + config.rx_filter = sinfo->rx_hwts ? HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE; + + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0; + } +#endif + + return -EINVAL; +} +#endif + static int bkn_change_mtu(struct net_device *dev, int new_mtu) { @@ -4354,6 +5207,44 @@ bkn_set_multicast_list(struct net_device *dev) { } +static int +bkn_hw_tstamp_tx_config(bkn_switch_info_t *sinfo, struct sk_buff *skb, uint32_t *meta) +{ + uint32_t *md = NULL; + + if (!knet_hw_tstamp_tx_meta_get_cb) { + return -1; + } + + KNET_SKB_CB(skb)->dcb_type = sinfo->dcb_type & 0xFFFF; + knet_hw_tstamp_tx_meta_get_cb(sinfo->dev_no, skb, &md); + if (!md) { + return -1; + } + + switch (sinfo->dcb_type) { + case 26: + case 32: + case 33: + meta[2] |= md[0]; + meta[3] |= md[1]; + meta[4] |= md[2]; + meta[5] |= md[3]; + break; + case 36: + case 38: + meta[0] |= md[0]; + meta[1] |= md[1]; + meta[2] |= md[2]; + meta[3] |= md[3]; + break; + default: + return -1; + } + + return 0; +} + static int bkn_tx(struct sk_buff *skb, struct net_device *dev) { @@ -4391,8 +5282,8 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) uint32_t *dcb, *meta; pktdata = skb->data; - pktlen = skb->len + 4; - hdrlen = sinfo->cmic_type == 'x' ? PKT_TX_HDR_SIZE : 0; + pktlen = skb->len; + hdrlen = (sinfo->cmic_type == 'x' ) ? ((device_is_dnx(sinfo)) ? priv->system_headers_size: PKT_TX_HDR_SIZE) : 0; rcpulen = 0; sop = 0; @@ -4447,7 +5338,7 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) if (skb_header_cloned(skb)) { /* Current SKB cannot be modified */ DBG_SKB(("Realloc Tx SKB\n")); - new_skb = dev_alloc_skb(pktlen + 4); + new_skb = dev_alloc_skb(pktlen + TAG_SZ + FCS_SZ); if (new_skb == NULL) { DBG_WARN(("Tx drop: No SKB memory\n")); priv->stats.tx_dropped++; @@ -4458,7 +5349,7 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) } memcpy(new_skb->data, pktdata, 12); memcpy(&new_skb->data[16], &pktdata[12], pktlen - 12); - skb_put(new_skb, pktlen + 4); + skb_put(new_skb, pktlen + TAG_SZ); dev_kfree_skb_any(skb); skb = new_skb; pktdata = skb->data; @@ -4466,26 +5357,25 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) } else { /* Add tag to RCPU header space */ DBG_SKB(("Expand into unused RCPU header\n")); - rcpulen -= 4; + rcpulen -= TAG_SZ; pktdata = &skb->data[rcpulen]; for (idx = 0; idx < 12; idx++) { - pktdata[idx] = pktdata[idx + 4]; + pktdata[idx] = pktdata[idx + TAG_SZ]; } } pktdata[12] = 0x81; pktdata[13] = 0x00; pktdata[14] = (priv->vlan >> 8) & 0xf; pktdata[15] = priv->vlan & 0xff; - pktlen += 4; + pktlen += TAG_SZ; } } } else { if (sinfo->cmic_type == 'x' && priv->port >= 0) { - if (skb_header_cloned(skb) || skb_headroom(skb) < hdrlen + 4 || - (sinfo->dcb_type == 36 && (unsigned long)skb->data % 4)) { + if (skb_header_cloned(skb) || skb_headroom(skb) < hdrlen + 4) { /* Current SKB cannot be modified */ DBG_SKB(("Realloc Tx SKB\n")); - new_skb = dev_alloc_skb(pktlen + hdrlen + 4); + new_skb = dev_alloc_skb(pktlen + hdrlen + 4 + FCS_SZ); if (new_skb == NULL) { DBG_WARN(("Tx drop: No SKB memory\n")); priv->stats.tx_dropped++; @@ -4494,7 +5384,10 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&sinfo->lock, flags); return 0; } - skb_reserve(new_skb, 4); + if (!device_is_dnx(sinfo)) + { + skb_reserve(new_skb, 4); + } memcpy(new_skb->data + hdrlen, skb->data, pktlen); skb_put(new_skb, pktlen + hdrlen); dev_kfree_skb_any(skb); @@ -4511,13 +5404,14 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) } if (priv->port < 0 || (priv->flags & KCOM_NETIF_F_ADD_TAG)) { + DBG_DUNE(("ADD VLAN TAG\n")); /* Need to add VLAN tag if packet is untagged */ tpid = (skb->data[hdrlen + 12] << 8) | skb->data[hdrlen + 13]; if (tpid != 0x8100) { if (skb_header_cloned(skb) || skb_headroom(skb) < 4) { /* Current SKB cannot be modified */ DBG_SKB(("Realloc Tx SKB\n")); - new_skb = dev_alloc_skb(pktlen + 4); + new_skb = dev_alloc_skb(pktlen + TAG_SZ + FCS_SZ); if (new_skb == NULL) { DBG_WARN(("Tx drop: No SKB memory\n")); priv->stats.tx_dropped++; @@ -4529,15 +5423,15 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) memcpy(new_skb->data, skb->data, hdrlen + 12); memcpy(&new_skb->data[hdrlen + 16], &skb->data[hdrlen + 12], pktlen - hdrlen - 12); - skb_put(new_skb, pktlen + 4); + skb_put(new_skb, pktlen + TAG_SZ); dev_kfree_skb_any(skb); skb = new_skb; } else { /* Add tag to existing buffer */ DBG_SKB(("Expand Tx SKB\n")); - skb_push(skb, 4); + skb_push(skb, TAG_SZ); for (idx = 0; idx < hdrlen + 12; idx++) { - skb->data[idx] = skb->data[idx + 4]; + skb->data[idx] = skb->data[idx + TAG_SZ]; } } pktdata = skb->data; @@ -4545,7 +5439,7 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) pktdata[hdrlen + 13] = 0x00; pktdata[hdrlen + 14] = (priv->vlan >> 8) & 0xf; pktdata[hdrlen + 15] = priv->vlan & 0xff; - pktlen += 4; + pktlen += TAG_SZ; } } } @@ -4556,8 +5450,8 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) if (tpid == 0x8100) { taglen = 4; } - if (pktlen < (64 + taglen + hdrlen)) { - pktlen = (64 + taglen + hdrlen); + if (pktlen < (60 + taglen + hdrlen)) { + pktlen = (60 + taglen + hdrlen); if (SKB_PADTO(skb, pktlen) != 0) { DBG_WARN(("Tx drop: skb_padto failed\n")); priv->stats.tx_dropped++; @@ -4568,12 +5462,11 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) } /* skb_padto may update the skb->data pointer */ pktdata = &skb->data[rcpulen]; - DBG_SKB(("Packet padded to %d bytes\n", pktlen)); } - if (pktlen > SOC_DCB_KNET_COUNT_MASK) { + if ((pktlen + FCS_SZ) > SOC_DCB_KNET_COUNT_MASK) { DBG_WARN(("Tx drop: size of pkt (%d) is out of range(%d)\n", - pktlen, SOC_DCB_KNET_COUNT_MASK)); + (pktlen + FCS_SZ), SOC_DCB_KNET_COUNT_MASK)); sinfo->tx.pkts_d_over_limit++; priv->stats.tx_dropped++; dev_kfree_skb_any(skb); @@ -4582,7 +5475,7 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) } dcb = desc->dcb_mem; - meta = sinfo->cmic_type == 'x' ? (uint32_t *)pktdata : dcb; + meta = (sinfo->cmic_type == 'x') ? (uint32_t *)pktdata : dcb; memset(dcb, 0, sinfo->dcb_wsize * sizeof(uint32_t)); if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) { /* If module header SOP is non-zero, use RCPU meta data */ @@ -4634,7 +5527,7 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) if (skb_header_cloned(skb) || skb_headroom(skb) < 4) { /* Current SKB cannot be modified */ DBG_SKB(("Realloc Tx SKB for DNX ITMH header\n")); - new_skb = dev_alloc_skb(pktlen + 4 + 2); + new_skb = dev_alloc_skb(pktlen + 4 + 2 + FCS_SZ); if (new_skb == NULL) { DBG_WARN(("Tx drop: No SKB memory for DNX ITMH header\n")); priv->stats.tx_dropped++; @@ -4663,7 +5556,7 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) if (skb_header_cloned(skb) || skb_headroom(skb) < 4) { /* Current SKB cannot be modified */ DBG_SKB(("Realloc Tx SKB for DNX header\n")); - new_skb = dev_alloc_skb(pktlen + 2); + new_skb = dev_alloc_skb(pktlen + 2 + FCS_SZ); if (new_skb == NULL) { DBG_WARN(("Tx drop: No SKB memory for DNX header\n")); priv->stats.tx_dropped++; @@ -4737,6 +5630,16 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) dcb[4] |= (priv->qnum & 0x3f) << 8; } break; + case 39: + if (device_is_dnx(sinfo)) { + /* + * if KCOM_NETIF_T_PORT, add MH+PTCH+ITMH header + * if KCOM_NETIF_T_VLAN, add MH+PTCH+header + */ + pktdata = skb->data; + memcpy(&pktdata[0], priv->system_headers, priv->system_headers_size); + } + break; default: dcb[2] = 0xff000000; dcb[3] = 0x00000100; @@ -4761,10 +5664,10 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) /* Restore (possibly) altered packet variables * bit0 -bit15 of dcb[1] is used to save requested byte count */ - if ((skb->len + 4) <= SOC_DCB_KNET_COUNT_MASK) { - pktlen = skb->len + 4; - if (pktlen < (64 + taglen + hdrlen)) { - pktlen = (64 + taglen + hdrlen); + if ((skb->len + FCS_SZ) <= SOC_DCB_KNET_COUNT_MASK) { + pktlen = skb->len; + if (pktlen < (60 + taglen + hdrlen)) { + pktlen = (60 + taglen + hdrlen); if (SKB_PADTO(skb, pktlen) != 0) { DBG_WARN(("Tx drop: skb_padto failed\n")); priv->stats.tx_dropped++; @@ -4776,9 +5679,12 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) DBG_SKB(("Packet padded to %d bytes after tx callback\n", pktlen)); } pktdata = skb->data; + if (sinfo->cmic_type == 'x') { + meta = (uint32_t *)pktdata; + } } else { DBG_WARN(("Tx drop: size of pkt (%d) is out of range(%d)\n", - pktlen, SOC_DCB_KNET_COUNT_MASK)); + (pktlen + FCS_SZ), SOC_DCB_KNET_COUNT_MASK)); sinfo->tx.pkts_d_over_limit++; priv->stats.tx_dropped++; sinfo->tx.pkts_d_callback++; @@ -4788,8 +5694,20 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) } } + /* Do Tx timestamping */ + if (priv->port >= 0) { + if (bkn_skb_tx_flags(skb) & SKBTX_HW_TSTAMP && sinfo->tx_hwts) { + KNET_SKB_CB(skb)->port = priv->port; + bkn_hw_tstamp_tx_config(sinfo, skb, meta); + bkn_skb_tx_flags(skb) |= SKBTX_IN_PROGRESS; + } + bkn_skb_tx_timestamp(skb); + } + /* Prepare for DMA */ desc->skb = skb; + /* Add FCS bytes */ + pktlen = pktlen + FCS_SZ; desc->dma_size = pktlen; desc->skb_dma = DMA_MAP_SINGLE(sinfo->dma_dev, pktdata, desc->dma_size, @@ -4859,9 +5777,8 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) } static void -bkn_timer(unsigned long context) +bkn_timer_func(bkn_switch_info_t *sinfo) { - bkn_switch_info_t *sinfo = (bkn_switch_info_t *)context; unsigned long flags; int chan; int restart_timer; @@ -4892,6 +5809,22 @@ bkn_timer(unsigned long context) spin_unlock_irqrestore(&sinfo->lock, flags); } +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) +static void +bkn_timer(unsigned long context) +{ + bkn_switch_info_t *sinfo = (bkn_switch_info_t *)context; + return bkn_timer_func(sinfo); +} +#else +static void +bkn_timer(struct timer_list *t) +{ + bkn_switch_info_t *sinfo = from_timer(sinfo, t, timer); + return bkn_timer_func(sinfo); +} +#endif + static void bkn_rx_add_tokens(bkn_switch_info_t *sinfo, int chan) { @@ -4925,9 +5858,8 @@ bkn_rx_add_tokens(bkn_switch_info_t *sinfo, int chan) } static void -bkn_rxtick(unsigned long context) +bkn_rxtick_func(bkn_switch_info_t *sinfo) { - bkn_switch_info_t *sinfo = (bkn_switch_info_t *)context; unsigned long flags; unsigned long cur_jif, ticks; uint32_t pkt_diff; @@ -4962,6 +5894,22 @@ bkn_rxtick(unsigned long context) add_timer(&sinfo->rxtick); } +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) +static void +bkn_rxtick(unsigned long context) +{ + bkn_switch_info_t *sinfo = (bkn_switch_info_t *)context; + return bkn_rxtick_func(sinfo); +} +#else +static void +bkn_rxtick(struct timer_list *t) +{ + bkn_switch_info_t *sinfo = from_timer(sinfo, t, rxtick); + return bkn_rxtick_func(sinfo); +} +#endif + static void bkn_rx_rate_config(bkn_switch_info_t *sinfo) { @@ -5041,11 +5989,17 @@ bkn_create_sinfo(int dev_no) sinfo->evt_idx = -1; spin_lock_init(&sinfo->lock); + skb_queue_head_init(&sinfo->tx_ptp_queue); + INIT_WORK(&sinfo->tx_ptp_work, bkn_hw_tstamp_tx_work); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) init_timer(&sinfo->timer); - sinfo->timer.expires = jiffies + 1; sinfo->timer.data = (unsigned long)sinfo; sinfo->timer.function = bkn_timer; +#else + timer_setup(&sinfo->timer, bkn_timer, 0); +#endif + sinfo->timer.expires = jiffies + 1; INIT_LIST_HEAD(&sinfo->tx.api_dcb_list); @@ -5063,10 +6017,14 @@ bkn_create_sinfo(int dev_no) sinfo->rx[0].use_rx_skb = 0; } +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)) init_timer(&sinfo->rxtick); - sinfo->rxtick.expires = jiffies + 1; sinfo->rxtick.data = (unsigned long)sinfo; sinfo->rxtick.function = bkn_rxtick; +#else + timer_setup(&sinfo->rxtick, bkn_rxtick, 0); +#endif + sinfo->rxtick.expires = jiffies + 1; for (chan = 0; chan < NUM_RX_CHAN; chan++) { sinfo->rx[chan].rate_max = rx_rate[chan]; @@ -5081,7 +6039,6 @@ bkn_create_sinfo(int dev_no) return sinfo; } - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) static const struct net_device_ops bkn_netdev_ops = { .ndo_open = bkn_open, @@ -5091,7 +6048,7 @@ static const struct net_device_ops bkn_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_set_rx_mode = bkn_set_multicast_list, .ndo_set_mac_address = bkn_set_mac_address, - .ndo_do_ioctl = NULL, + .ndo_do_ioctl = bkn_ioctl, .ndo_tx_timeout = NULL, .ndo_change_mtu = bkn_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -5100,6 +6057,61 @@ static const struct net_device_ops bkn_netdev_ops = { }; #endif +static void +bkn_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) +{ + strlcpy(drvinfo->driver, "bcm-knet", sizeof(drvinfo->driver)); + snprintf(drvinfo->version, sizeof(drvinfo->version), "%d", KCOM_VERSION); + strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); + strlcpy(drvinfo->bus_info, "N/A", sizeof(drvinfo->bus_info)); +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)) +static int +bkn_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) +{ + bkn_priv_t *priv = netdev_priv(dev); + bkn_switch_info_t *sinfo = priv->sinfo; + + switch (sinfo->dcb_type) { + case 26: + case 32: + case 33: + case 36: + case 38: + info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + info->tx_types = 1 << HWTSTAMP_TX_OFF | 1 << HWTSTAMP_TX_ON; + info->rx_filters = 1 << HWTSTAMP_FILTER_NONE | 1 << HWTSTAMP_FILTER_ALL; + if (knet_hw_tstamp_ptp_clock_index_cb) { + info->phc_index = knet_hw_tstamp_ptp_clock_index_cb(sinfo->dev_no); + } else { + info->phc_index = -1; + } + break; + default: + info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE; + info->phc_index = -1; + break; + } + + return 0; +} +#endif + +static const struct ethtool_ops bkn_ethtool_ops = { + .get_drvinfo = bkn_get_drvinfo, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)) + .get_ts_info = bkn_get_ts_info, +#endif +}; + static struct net_device * bkn_init_ndev(u8 *mac, char *name) { @@ -5144,6 +6156,7 @@ bkn_init_ndev(u8 *mac, char *name) dev->poll_controller = bkn_poll_controller; #endif #endif + dev->ethtool_ops = &bkn_ethtool_ops; if (name && *name) { strncpy(dev->name, name, IFNAMSIZ-1); } @@ -6413,10 +7426,12 @@ bkn_knet_hw_reset(kcom_msg_hw_reset_t *kmsg, int len) /* Clean all if no channels specified */ bkn_dma_abort(sinfo); bkn_clean_dcbs(sinfo); + skb_queue_purge(&sinfo->tx_ptp_queue); } else { if (kmsg->channels & (1 << XGS_DMA_TX_CHAN)) { bkn_dma_abort_tx(sinfo); bkn_clean_tx_dcbs(sinfo); + skb_queue_purge(&sinfo->tx_ptp_queue); } for (chan = 0; chan < sinfo->rx_chans; chan++) { if (kmsg->channels & (1 << (XGS_DMA_RX_CHAN + chan))) { @@ -6460,6 +7475,10 @@ bkn_knet_hw_init(kcom_msg_hw_init_t *kmsg, int len) sinfo->rx_chans = NUM_RX_CHAN; } + DBG_DUNE(("CMIC:%c DCB:%d WSIZE:%d DMA HI: 0x%08x HDR size: %d\n", + sinfo->cmic_type, sinfo->dcb_type, sinfo->dcb_wsize, + sinfo->dma_hi, sinfo->pkt_hdr_size)); + /* Config Continuous DMA mode */ sinfo->cdma_channels = kmsg->cdma_channels & ~(~0 << (sinfo->rx_chans + 1)); @@ -6598,17 +7617,26 @@ bkn_knet_netif_create(kcom_msg_netif_create_t *kmsg, int len) priv->vlan = kmsg->netif.vlan; if (priv->type == KCOM_NETIF_T_PORT) { priv->port = kmsg->netif.port; - memcpy(priv->itmh, kmsg->netif.itmh, 4); + if (device_is_dpp(sinfo)) { + memcpy(priv->itmh, kmsg->netif.itmh, 4); + } else if (device_is_dnx(sinfo)) { + memcpy(priv->system_headers, kmsg->netif.system_headers, kmsg->netif.system_headers_size); + priv->system_headers_size = kmsg->netif.system_headers_size; + } priv->qnum = kmsg->netif.qnum; } else { - if ((device_is_dune(sinfo)) && (priv->type == KCOM_NETIF_T_VLAN)) { - /* set port as SSP to PTCH */ - priv->port = kmsg->netif.port; - priv->qnum = kmsg->netif.qnum; - } - else { - priv->port = -1; - } + if (device_is_sand(sinfo)) { + if (device_is_dpp(sinfo)) { + priv->port = kmsg->netif.port; + priv->qnum = kmsg->netif.qnum; + }else if (device_is_dnx(sinfo)) { + memcpy(priv->system_headers, kmsg->netif.system_headers, kmsg->netif.system_headers_size); + priv->system_headers_size = kmsg->netif.system_headers_size; + } + } + else { + priv->port = -1; + } } priv->flags = kmsg->netif.flags; priv->cb_user_data = kmsg->netif.cb_user_data; @@ -6669,14 +7697,28 @@ bkn_knet_netif_create(kcom_msg_netif_create_t *kmsg, int len) } } - spin_unlock_irqrestore(&sinfo->lock, flags); - DBG_VERB(("Assigned ID %d to Ethernet device %s\n", priv->id, dev->name)); kmsg->netif.id = priv->id; memcpy(kmsg->netif.macaddr, dev->dev_addr, 6); memcpy(kmsg->netif.name, dev->name, KCOM_NETIF_NAME_MAX - 1); + + if (knet_netif_create_cb != NULL) { + int retv = knet_netif_create_cb(kmsg->hdr.unit, &(kmsg->netif), dev); + if (retv) { + gprintk("Warning: knet_netif_create_cb() returned %d for netif '%s'\n", retv, dev->name); + } + } + + spin_unlock_irqrestore(&sinfo->lock, flags); + + if (device_is_dnx(sinfo)) { + int idx = 0; + for (idx = 0; idx < priv->system_headers_size; idx++) { + DBG_DUNE(("System Header[%d]: 0x%02x\n", idx, priv->system_headers[idx])); + } + } return sizeof(*kmsg); } @@ -6716,6 +7758,12 @@ bkn_knet_netif_destroy(kcom_msg_netif_destroy_t *kmsg, int len) return sizeof(kcom_msg_hdr_t); } + if (knet_netif_destroy_cb != NULL) { + kcom_netif_t netif; + memset(&netif, 0, sizeof(kcom_netif_t)); + netif.id = priv->id; + knet_netif_destroy_cb(kmsg->hdr.unit, &netif, priv->dev); + } list_del(&priv->list); if (priv->id < sinfo->ndev_max) { @@ -6871,6 +7919,17 @@ bkn_knet_filter_create(kcom_msg_filter_create_t *kmsg, int len) } memset(filter, 0, sizeof(*filter)); memcpy(&filter->kf, &kmsg->filter, sizeof(filter->kf)); + + if (device_is_dnx(sinfo)) { + /* Information to parser Dune system headers */ + sinfo->ftmh_lb_key_ext_size = kmsg->filter.ftmh_lb_key_ext_size; + sinfo->ftmh_stacking_ext_size = kmsg->filter.ftmh_stacking_ext_size; + sinfo->pph_base_size = kmsg->filter.pph_base_size; + memcpy(sinfo->pph_lif_ext_size, kmsg->filter.pph_lif_ext_size, sizeof(sinfo->pph_lif_ext_size)); + sinfo->udh_enable = kmsg->filter.udh_enable; + memcpy(sinfo->udh_length_type, kmsg->filter.udh_length_type, sizeof(sinfo->udh_length_type)); + } + filter->kf.id = id; /* Add according to priority */ @@ -6894,6 +7953,20 @@ bkn_knet_filter_create(kcom_msg_filter_create_t *kmsg, int len) DBG_VERB(("Created filter ID %d (%s).\n", filter->kf.id, filter->kf.desc)); + if (device_is_dnx(sinfo)) { + int idx, wsize; + wsize = BYTES2WORDS(filter->kf.oob_data_size + filter->kf.pkt_data_size); + DBG_DUNE(("Filter: oob_data_size = %d pkt_data_size=%d wsize %d\n", filter->kf.oob_data_size, filter->kf.pkt_data_size, wsize)); + for (idx = 0; idx < wsize; idx++) + { + DBG_DUNE(("OOB[%d]: 0x%08x [0x%08x]\n", idx, filter->kf.data.w[idx], filter->kf.mask.w[idx])); + } + DBG_DUNE(("DNX system headers parameters:LB_KEY_EXT %d, STK_EXT %d, PPH_BASE %d, LIF_EXT %d %d %d, UDH_ENA %d, %d %d %d %d\n", + sinfo->ftmh_lb_key_ext_size, sinfo->ftmh_stacking_ext_size, sinfo->pph_base_size, + sinfo->pph_lif_ext_size[1],sinfo->pph_lif_ext_size[2], sinfo->pph_lif_ext_size[3], + sinfo->udh_enable, sinfo->udh_length_type[0], sinfo->udh_length_type[1], sinfo->udh_length_type[2], sinfo->udh_length_type[3])); + } + return len; } @@ -7248,10 +8321,14 @@ bkn_get_next_dma_event(kcom_msg_dma_info_t *kmsg) if (sinfo && (sinfo->inst_id != 0) && ((sinfo->inst_id & (1 << dev_evt)) == 0)) { - DBG_INST((" %s skip dev(%d)\n",__FUNCTION__,dev_evt)); + DBG_INST((" %s skip dev(%d)\n",__FUNCTION__,dev_no)); continue; } + if (sinfo->evt_idx == -1) { + /* Event queue is not ready yet */ + continue; + } if (sinfo && sinfo->dma_events) { DBG_EVT(("Next DMA events (0x%08x)\n", sinfo->dma_events)); kmsg->hdr.unit = sinfo->dev_no; @@ -7265,9 +8342,11 @@ bkn_get_next_dma_event(kcom_msg_dma_info_t *kmsg) break; } - if (dev_no == last_dev_no) { + if ((dev_no == last_dev_no) || + (_bkn_multi_inst && (dev_no == dev_evt))) { evt = &_bkn_evt[sinfo->evt_idx]; - DBG_INST(("wait queue index %d\n",sinfo->evt_idx)); + DBG_INST(("dev_no %d dev_evt %d wait queue index %d\n", + dev_no, dev_evt, sinfo->evt_idx)); wait_event_interruptible(evt->evt_wq, evt->evt_wq_get != evt->evt_wq_put); DBG_VERB(("Event thread wakeup\n")); @@ -7363,6 +8442,7 @@ _cleanup(void) spin_lock_irqsave(&sinfo->lock, flags); bkn_clean_dcbs(sinfo); + skb_queue_purge(&sinfo->tx_ptp_queue); spin_unlock_irqrestore(&sinfo->lock, flags); } @@ -7667,6 +8747,68 @@ gmodule_get(void) return &_gmodule; } +/* + * Get DCB type and other HW info + */ +int +bkn_hw_info_get(int unit, knet_hw_info_t *hw_info) +{ + bkn_switch_info_t *sinfo; + sinfo = bkn_sinfo_from_unit(unit); + if (sinfo == NULL) { + gprintk("Warning: unknown unit: %d\n", unit); + return (-1); + } + + hw_info->cmic_type = sinfo->cmic_type; + hw_info->dcb_type = sinfo->dcb_type; + hw_info->dcb_size = WORDS2BYTES(sinfo->dcb_wsize); + hw_info->pkt_hdr_size = sinfo->pkt_hdr_size; + hw_info->cdma_channels = sinfo->cdma_channels; + + return (0); +} + +int +bkn_netif_create_cb_register(knet_netif_cb_f netif_cb) +{ + if (knet_netif_create_cb != NULL) { + return -1; + } + knet_netif_create_cb = netif_cb; + return 0; +} + +int +bkn_netif_create_cb_unregister(knet_netif_cb_f netif_cb) +{ + if (netif_cb != NULL && knet_netif_create_cb != netif_cb) { + return -1; + } + knet_netif_create_cb = NULL; + return 0; +} + +int +bkn_netif_destroy_cb_register(knet_netif_cb_f netif_cb) +{ + if (knet_netif_destroy_cb != NULL) { + return -1; + } + knet_netif_destroy_cb = netif_cb; + return 0; +} + +int +bkn_netif_destroy_cb_unregister(knet_netif_cb_f netif_cb) +{ + if (netif_cb != NULL && knet_netif_destroy_cb != netif_cb) { + return -1; + } + knet_netif_destroy_cb = NULL; + return 0; +} + /* * Call-back interfaces for other Linux kernel drivers. * @@ -7675,6 +8817,11 @@ gmodule_get(void) * * The Tx call-back allows an external module to modify SKB contents * before it is injected inot the switch. + * + * The HW timestamp callbacks invoke an external module to enable, disable + * HW timestamp on a specific port which is indicated while the netif is + * created through KNET API. KNET can also get device-specific SOBMH and + * timestamp for a Tx PTP packet through these callbacks. */ int @@ -7737,9 +8884,152 @@ bkn_filter_cb_unregister(knet_filter_cb_f filter_cb) return 0; } +int +bkn_hw_tstamp_enable_cb_register(knet_hw_tstamp_enable_cb_f hw_tstamp_enable_cb) +{ + if (knet_hw_tstamp_enable_cb != NULL) { + return -1; + } + knet_hw_tstamp_enable_cb = hw_tstamp_enable_cb; + return 0; +} + +int +bkn_hw_tstamp_enable_cb_unregister(knet_hw_tstamp_enable_cb_f hw_tstamp_enable_cb) +{ + if (hw_tstamp_enable_cb == NULL || + knet_hw_tstamp_enable_cb != hw_tstamp_enable_cb) { + return -1; + } + knet_hw_tstamp_enable_cb = NULL; + return 0; +} + +int +bkn_hw_tstamp_disable_cb_register(knet_hw_tstamp_enable_cb_f hw_tstamp_disable_cb) +{ + if (knet_hw_tstamp_disable_cb != NULL) { + return -1; + } + knet_hw_tstamp_disable_cb = hw_tstamp_disable_cb; + return 0; +} + +int +bkn_hw_tstamp_disable_cb_unregister(knet_hw_tstamp_enable_cb_f hw_tstamp_disable_cb) +{ + if (hw_tstamp_disable_cb == NULL || + knet_hw_tstamp_disable_cb != hw_tstamp_disable_cb) { + return -1; + } + knet_hw_tstamp_disable_cb = NULL; + return 0; +} + +int +bkn_hw_tstamp_tx_time_get_cb_register(knet_hw_tstamp_tx_time_get_cb_f hw_tstamp_tx_time_get_cb) +{ + if (knet_hw_tstamp_tx_time_get_cb != NULL) { + return -1; + } + knet_hw_tstamp_tx_time_get_cb = hw_tstamp_tx_time_get_cb; + return 0; +} + +int +bkn_hw_tstamp_tx_time_get_cb_unregister(knet_hw_tstamp_tx_time_get_cb_f hw_tstamp_tx_time_get_cb) +{ + if (hw_tstamp_tx_time_get_cb == NULL || + knet_hw_tstamp_tx_time_get_cb != hw_tstamp_tx_time_get_cb) { + return -1; + } + knet_hw_tstamp_tx_time_get_cb = NULL; + return 0; +} + +int +bkn_hw_tstamp_tx_meta_get_cb_register(knet_hw_tstamp_tx_meta_get_cb_f hw_tstamp_tx_meta_get_cb) +{ + if (knet_hw_tstamp_tx_meta_get_cb != NULL) { + return -1; + } + knet_hw_tstamp_tx_meta_get_cb = hw_tstamp_tx_meta_get_cb; + return 0; +} + +int +bkn_hw_tstamp_tx_meta_get_cb_unregister(knet_hw_tstamp_tx_meta_get_cb_f hw_tstamp_tx_meta_get_cb) +{ + if (hw_tstamp_tx_meta_get_cb == NULL || + knet_hw_tstamp_tx_meta_get_cb != hw_tstamp_tx_meta_get_cb) { + return -1; + } + knet_hw_tstamp_tx_meta_get_cb = NULL; + return 0; +} + +int +bkn_hw_tstamp_ptp_clock_index_cb_register(knet_hw_tstamp_ptp_clock_index_cb_f hw_tstamp_ptp_clock_index_cb) +{ + if (knet_hw_tstamp_ptp_clock_index_cb != NULL) { + return -1; + } + knet_hw_tstamp_ptp_clock_index_cb = hw_tstamp_ptp_clock_index_cb; + return 0; +} + +int +bkn_hw_tstamp_ptp_clock_index_cb_unregister(knet_hw_tstamp_ptp_clock_index_cb_f hw_tstamp_ptp_clock_index_cb) +{ + if (hw_tstamp_ptp_clock_index_cb == NULL || + knet_hw_tstamp_ptp_clock_index_cb != hw_tstamp_ptp_clock_index_cb) { + return -1; + } + knet_hw_tstamp_ptp_clock_index_cb = NULL; + return 0; +} + +int +bkn_hw_tstamp_rx_time_upscale_cb_register(knet_hw_tstamp_rx_time_upscale_cb_f hw_tstamp_rx_time_upscale_cb) +{ + if (knet_hw_tstamp_rx_time_upscale_cb != NULL) { + return -1; + } + knet_hw_tstamp_rx_time_upscale_cb = hw_tstamp_rx_time_upscale_cb; + return 0; +} + +int +bkn_hw_tstamp_rx_time_upscale_cb_unregister(knet_hw_tstamp_rx_time_upscale_cb_f hw_tstamp_rx_time_upscale_cb) +{ + if (hw_tstamp_rx_time_upscale_cb == NULL || + knet_hw_tstamp_rx_time_upscale_cb != hw_tstamp_rx_time_upscale_cb) { + return -1; + } + knet_hw_tstamp_rx_time_upscale_cb = NULL; + return 0; +} + LKM_EXPORT_SYM(bkn_rx_skb_cb_register); LKM_EXPORT_SYM(bkn_rx_skb_cb_unregister); LKM_EXPORT_SYM(bkn_tx_skb_cb_register); LKM_EXPORT_SYM(bkn_tx_skb_cb_unregister); LKM_EXPORT_SYM(bkn_filter_cb_register); LKM_EXPORT_SYM(bkn_filter_cb_unregister); +LKM_EXPORT_SYM(bkn_hw_tstamp_enable_cb_register); +LKM_EXPORT_SYM(bkn_hw_tstamp_enable_cb_unregister); +LKM_EXPORT_SYM(bkn_hw_tstamp_disable_cb_register); +LKM_EXPORT_SYM(bkn_hw_tstamp_disable_cb_unregister); +LKM_EXPORT_SYM(bkn_hw_tstamp_tx_time_get_cb_register); +LKM_EXPORT_SYM(bkn_hw_tstamp_tx_time_get_cb_unregister); +LKM_EXPORT_SYM(bkn_hw_tstamp_tx_meta_get_cb_register); +LKM_EXPORT_SYM(bkn_hw_tstamp_tx_meta_get_cb_unregister); +LKM_EXPORT_SYM(bkn_hw_tstamp_ptp_clock_index_cb_register); +LKM_EXPORT_SYM(bkn_hw_tstamp_ptp_clock_index_cb_unregister); +LKM_EXPORT_SYM(bkn_hw_tstamp_rx_time_upscale_cb_register); +LKM_EXPORT_SYM(bkn_hw_tstamp_rx_time_upscale_cb_unregister); +LKM_EXPORT_SYM(bkn_hw_info_get); +LKM_EXPORT_SYM(bkn_netif_create_cb_register); +LKM_EXPORT_SYM(bkn_netif_create_cb_unregister); +LKM_EXPORT_SYM(bkn_netif_destroy_cb_register); +LKM_EXPORT_SYM(bkn_netif_destroy_cb_unregister); diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/bcm-knet.h b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/bcm-knet.h index 760690b3fb..477c037a0c 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/bcm-knet.h +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/bcm-knet.h @@ -39,14 +39,17 @@ typedef struct { * Call-back interfaces for other Linux kernel drivers. */ #include +#include +#include typedef struct { uint32 netif_user_data; uint32 filter_user_data; uint16 dcb_type; + int port; } knet_skb_cb_t; -#define KNET_SKB_CB(__skb) ((knet_skb_cb_t *)&((__skb)->cb[0])) +#define KNET_SKB_CB(_skb) ((knet_skb_cb_t *)_skb->cb) typedef struct sk_buff * (*knet_skb_cb_f)(struct sk_buff *skb, int dev_no, void *meta); @@ -55,6 +58,21 @@ typedef int (*knet_filter_cb_f)(uint8_t *pkt, int size, int dev_no, void *meta, int chan, kcom_filter_t *filter); +typedef int +(*knet_hw_tstamp_enable_cb_f)(int dev_no, int port); + +typedef int +(*knet_hw_tstamp_tx_time_get_cb_f)(int dev_no, int port, uint8_t *pkt, uint64_t *ts); + +typedef int +(*knet_hw_tstamp_tx_meta_get_cb_f)(int dev_no, struct sk_buff *skb, uint32_t **md); + +typedef int +(*knet_hw_tstamp_ptp_clock_index_cb_f)(int dev_no); + +typedef int +(*knet_hw_tstamp_rx_time_upscale_cb_f)(int dev_no, uint64_t *ts); + extern int bkn_rx_skb_cb_register(knet_skb_cb_f rx_cb); @@ -73,6 +91,68 @@ bkn_filter_cb_register(knet_filter_cb_f filter_cb); extern int bkn_filter_cb_unregister(knet_filter_cb_f filter_cb); -#endif +extern int +bkn_hw_tstamp_enable_cb_register(knet_hw_tstamp_enable_cb_f hw_tstamp_enable_cb); + +extern int +bkn_hw_tstamp_enable_cb_unregister(knet_hw_tstamp_enable_cb_f hw_tstamp_enable_cb); + +extern int +bkn_hw_tstamp_disable_cb_register(knet_hw_tstamp_enable_cb_f hw_tstamp_disable_cb); + +extern int +bkn_hw_tstamp_disable_cb_unregister(knet_hw_tstamp_enable_cb_f hw_tstamp_disable_cb); + +extern int +bkn_hw_tstamp_tx_time_get_cb_register(knet_hw_tstamp_tx_time_get_cb_f hw_tstamp_tx_time_get_cb); + +extern int +bkn_hw_tstamp_tx_time_get_cb_unregister(knet_hw_tstamp_tx_time_get_cb_f hw_tstamp_tx_time_get_cb); + +extern int +bkn_hw_tstamp_tx_meta_get_cb_register(knet_hw_tstamp_tx_meta_get_cb_f hw_tstamp_tx_meta_get_cb); + +extern int +bkn_hw_tstamp_tx_meta_get_cb_unregister(knet_hw_tstamp_tx_meta_get_cb_f hw_tstamp_tx_meta_get_cb); + +extern int +bkn_hw_tstamp_ptp_clock_index_cb_register(knet_hw_tstamp_ptp_clock_index_cb_f hw_tstamp_ptp_clock_index_cb); + +extern int +bkn_hw_tstamp_ptp_clock_index_cb_unregister(knet_hw_tstamp_ptp_clock_index_cb_f hw_tstamp_ptp_clock_index_cb); + +extern int +bkn_hw_tstamp_rx_time_upscale_cb_register(knet_hw_tstamp_rx_time_upscale_cb_f hw_tstamp_rx_time_upscale_cb); + +extern int +bkn_hw_tstamp_rx_time_upscale_cb_unregister(knet_hw_tstamp_rx_time_upscale_cb_f hw_tstamp_rx_time_upscale_cb); + +typedef struct { + uint8 cmic_type; + uint8 dcb_type; + uint8 dcb_size; + uint8 pkt_hdr_size; + uint32 cdma_channels; +} knet_hw_info_t; + +extern int +bkn_hw_info_get(int unit, knet_hw_info_t *hw_info); + +typedef int +(*knet_netif_cb_f)(int unit, kcom_netif_t *netif, struct net_device *dev); + +extern int +bkn_netif_create_cb_register(knet_netif_cb_f netif_cb); + +extern int +bkn_netif_create_cb_unregister(knet_netif_cb_f netif_cb); + +extern int +bkn_netif_destroy_cb_register(knet_netif_cb_f netif_cb); + +extern int +bkn_netif_destroy_cb_unregister(knet_netif_cb_f netif_cb); + +#endif /* __KERNEL__ */ #endif /* __LINUX_BCM_KNET_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/net/psample.h b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/net/psample.h new file mode 100644 index 0000000000..57c000785e --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/net/psample.h @@ -0,0 +1,24 @@ +#ifndef __NET_PSAMPLE_H +#define __NET_PSAMPLE_H + +#include +#include +#include +#include + +struct psample_group { + struct list_head list; + struct net *net; + u32 group_num; + u32 refcount; + u32 seq; +}; + +extern struct psample_group *psample_group_get(struct net *net, u32 group_num); +extern void psample_group_put(struct psample_group *group); + +extern void psample_sample_packet(struct psample_group *group, struct sk_buff *skb, + u32 trunc_size, int in_ifindex, int out_ifindex, + u32 sample_rate); + +#endif /* __NET_PSAMPLE_H */ diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/uapi/linux/psample.h b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/uapi/linux/psample.h new file mode 100644 index 0000000000..ed48996ec0 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/uapi/linux/psample.h @@ -0,0 +1,35 @@ +#ifndef __UAPI_PSAMPLE_H +#define __UAPI_PSAMPLE_H + +enum { + /* sampled packet metadata */ + PSAMPLE_ATTR_IIFINDEX, + PSAMPLE_ATTR_OIFINDEX, + PSAMPLE_ATTR_ORIGSIZE, + PSAMPLE_ATTR_SAMPLE_GROUP, + PSAMPLE_ATTR_GROUP_SEQ, + PSAMPLE_ATTR_SAMPLE_RATE, + PSAMPLE_ATTR_DATA, + + /* commands attributes */ + PSAMPLE_ATTR_GROUP_REFCOUNT, + + __PSAMPLE_ATTR_MAX +}; + +enum psample_command { + PSAMPLE_CMD_SAMPLE, + PSAMPLE_CMD_GET_GROUP, + PSAMPLE_CMD_NEW_GROUP, + PSAMPLE_CMD_DEL_GROUP, +}; + +/* Can be overridden at runtime by module option */ +#define PSAMPLE_ATTR_MAX (__PSAMPLE_ATTR_MAX - 1) + +#define PSAMPLE_NL_MCGRP_CONFIG_NAME "config" +#define PSAMPLE_NL_MCGRP_SAMPLE_NAME "packets" +#define PSAMPLE_GENL_NAME "psample" +#define PSAMPLE_GENL_VERSION 1 + +#endif diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/Makefile b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/Makefile index d7ca56cd57..2a167bb9e8 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/Makefile +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/Makefile @@ -36,7 +36,9 @@ KMODULE = $(LIBDIR)/$(THIS_MOD_NAME).ko build: $(MODULE) $(KMODULE) endif -KBUILD_EXTRA_SYMBOLS := ${BLDDIR}/../bcm-knet/kernel_module/Module.symvers +ifeq ($(BUILD_PSAMPLE),1) +KBUILD_EXTRA_SYMBOLS += ${BLDDIR}/../psample/kernel_module/Module.symvers +endif # BCM Network Device diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/knet-cb.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/knet-cb.c index da221f9f45..89d1087212 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/knet-cb.c +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/knet-cb.c @@ -1,5 +1,5 @@ /* - * Copyright 2017 Broadcom + * Copyright 2017-2019 Broadcom * * 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 @@ -45,17 +45,20 @@ #include #include +/* Enable sflow sampling using psample */ +#ifdef PSAMPLE_SUPPORT +#include "psample-cb.h" +#endif + MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("Broadcom Linux KNET Call-Back Driver"); MODULE_LICENSE("GPL"); - -static int debug; +int debug; LKM_MOD_PARAM(debug, "i", int, 0); MODULE_PARM_DESC(debug, "Debug level (default 0)"); - /* Module Information */ #define MODULE_MAJOR 121 #define MODULE_NAME "linux-knet-cb" @@ -63,8 +66,10 @@ MODULE_PARM_DESC(debug, /* set KNET_CB_DEBUG for debug info */ #define KNET_CB_DEBUG -#define FILTER_TAG_STRIP 0 -#define FILTER_TAG_KEEP 1 +/* These below need to match incoming enum values */ +#define FILTER_TAG_STRIP 0 +#define FILTER_TAG_KEEP 1 +#define FILTER_TAG_ORIGINAL 2 /* Maintain tag strip statistics */ struct strip_stats_s { @@ -105,7 +110,7 @@ strip_vlan_tag(struct sk_buff *skb) * * DCB type 14: word 12, bits 10.11 * DCB type 19, 20, 21, 22, 30: word 12, bits 10..11 - * DCB type 23, 29: word 13, bits 0..1 + * DCB type 23, 29: word 13, bits 0..1 * DCB type 31, 34, 37: word 13, bits 0..1 * DCB type 26, 32, 33, 35: word 13, bits 0..1 * @@ -150,7 +155,7 @@ get_tag_status(int dcb_type, void *meta) { /* untested */ /* TH3 only parses outer tag. */ - const int tag_map[4] = { 0, 2, -1, -1 }; + const int tag_map[4] = { 0, 2, -1, -1 }; tag_status = tag_map[(dcb[9] >> 13) & 0x3]; } break; @@ -162,7 +167,7 @@ get_tag_status(int dcb_type, void *meta) if (debug & 0x1) { gprintk("%s; DCB Type: %d; tag status: %d\n", __func__, dcb_type, tag_status); } -#endif +#endif return tag_status; } @@ -183,12 +188,12 @@ strip_tag_rx_cb(struct sk_buff *skb, int dev_no, void *meta) if (debug & 0x1) { gprintk("%s Enter; netif Flags: %08X filter_flags %08X \n", __func__, netif_flags, filter_flags); - } + } #endif /* KNET implements this already */ if (filter_flags == FILTER_TAG_KEEP) - { +{ strip_stats.skipped++; return skb; } @@ -217,8 +222,17 @@ strip_tag_rx_cb(struct sk_buff *skb, int dev_no, void *meta) return skb; } + if (filter_flags == FILTER_TAG_ORIGINAL) + { + /* If untagged or single inner, strip the extra tag that knet + keep tag will add. */ + if (tag_status < 2) + { + strip_tag = 1; + } + } strip_stats.checked++; - + if (strip_tag) { #ifdef KNET_CB_DEBUG if (debug & 0x1) { @@ -235,7 +249,6 @@ strip_tag_rx_cb(struct sk_buff *skb, int dev_no, void *meta) } } #endif - return skb; } @@ -250,16 +263,50 @@ strip_tag_tx_cb(struct sk_buff *skb, int dev_no, void *meta) /* Filter callback not used */ static int strip_tag_filter_cb(uint8_t * pkt, int size, int dev_no, void *meta, - int chan, kcom_filter_t *kf) + int chan, kcom_filter_t *kf) { /* Pass through for now */ return 0; } +static int +knet_filter_cb(uint8_t * pkt, int size, int dev_no, void *meta, + int chan, kcom_filter_t *kf) +{ + /* check for filter callback handler */ +#ifdef PSAMPLE_SUPPORT + if (strncmp(kf->desc, PSAMPLE_CB_NAME, KCOM_FILTER_DESC_MAX) == 0) { + return psample_filter_cb (pkt, size, dev_no, meta, chan, kf); + } +#endif + return strip_tag_filter_cb (pkt, size, dev_no, meta, chan, kf); +} + +static int +knet_netif_create_cb(int unit, kcom_netif_t *netif, struct net_device *dev) +{ + int retv = 0; +#ifdef PSAMPLE_SUPPORT + retv = psample_netif_create_cb(unit, netif, dev); +#endif + return retv; +} + +static int +knet_netif_destroy_cb(int unit, kcom_netif_t *netif, struct net_device *dev) +{ + int retv = 0; +#ifdef PSAMPLE_SUPPORT + retv = psample_netif_destroy_cb(unit, netif, dev); +#endif + return retv; +} + /* * Get statistics. * % cat /proc/linux-knet-cb */ + static int _pprint(void) { @@ -275,19 +322,40 @@ static int _cleanup(void) { bkn_rx_skb_cb_unregister(strip_tag_rx_cb); - bkn_tx_skb_cb_unregister(strip_tag_tx_cb); - bkn_filter_cb_unregister(strip_tag_filter_cb); + /* strip_tag_tx_cb is currently a no-op, so no need to unregister */ + if (0) + { + bkn_tx_skb_cb_unregister(strip_tag_tx_cb); + } + bkn_filter_cb_unregister(knet_filter_cb); + bkn_netif_create_cb_unregister(knet_netif_create_cb); + bkn_netif_destroy_cb_unregister(knet_netif_destroy_cb); + +#ifdef PSAMPLE_SUPPORT + psample_cleanup(); +#endif return 0; } static int _init(void) { - bkn_rx_skb_cb_register(strip_tag_rx_cb); - bkn_tx_skb_cb_register(strip_tag_tx_cb); - bkn_filter_cb_register(strip_tag_filter_cb); + bkn_rx_skb_cb_register(strip_tag_rx_cb); + /* strip_tag_tx_cb is currently a no-op, so no need to register */ + if (0) + { + bkn_tx_skb_cb_register(strip_tag_tx_cb); + } + +#ifdef PSAMPLE_SUPPORT + psample_init(); +#endif + + bkn_filter_cb_register(knet_filter_cb); + bkn_netif_create_cb_register(knet_netif_create_cb); + bkn_netif_destroy_cb_register(knet_netif_destroy_cb); return 0; } diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.c new file mode 100644 index 0000000000..ef6fc102ce --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.c @@ -0,0 +1,875 @@ +/* + * Copyright 2017-2019 Broadcom + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: psample_cb.c $ + * $Copyright: (c) 2019 Broadcom Corp. + * All Rights Reserved.$ + */ + +/* + * Driver for call-back functions for Linux KNET driver. + * + * This code is used to integrate packet sampling KNET callback to + * the psample infra for sending sampled pkts to userspace sflow + * applications such as Host Sflow (https://github.com/sflow/host-sflow) + * using genetlink interfaces. + * + * The module can be built from the standard Linux user mode target + * directories using the following command (assuming bash), e.g. + * + * cd $SDK/systems/linux/user/ + * make BUILD_KNET_CB=1 + * + */ + +#include /* Must be included first */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "psample-cb.h" + +#define PSAMPLE_CB_DBG +#ifdef PSAMPLE_CB_DBG +extern int debug; +#define PSAMPLE_CB_DBG_PRINT(...) \ + if (debug & 0x1) { \ + gprintk(__VA_ARGS__); \ + } +#else +#define PSAMPLE_CB_DBG_PRINT(...) +#endif + +/* HIGIG2 header fields */ +#define SOC_HIGIG_SOP (0xfb) +#define SOC_HIGIG_START(x) ((x[0] >> 24) & 0xff) +#define SOC_HIGIG_DSTPORT(x) ((x[1] >> 11) & 0x1f) +#define SOC_HIGIG_SRCPORT(x) ((x[1] >> 16) & 0x1f) +#define SOC_HIGIG2_SOP (0xfb) //0xfc - TODO: how can we differentiate between Higig and higig2? +#define SOC_HIGIG2_START(x) ((x[0] >> 24) & 0xff) +#define SOC_HIGIG2_DSTPORT(x) ((x[0] >> 0) & 0xff) +#define SOC_HIGIG2_SRCPORT(x) ((x[1] >> 16) & 0xff) +#define SOC_DCB32_HG_OFFSET (6) + +#define FCS_SZ 4 +#define PSAMPLE_NLA_PADDING 4 + +#define PSAMPLE_RATE_DFLT 1 +#define PSAMPLE_SIZE_DFLT 128 +static int psample_size = PSAMPLE_SIZE_DFLT; +LKM_MOD_PARAM(psample_size, "i", int, 0); +MODULE_PARM_DESC(psample_size, +"psample pkt size (default 128 bytes)"); + +/* driver proc entry root */ +static struct proc_dir_entry *psample_proc_root = NULL; + +/* psample general info */ +typedef struct { + struct list_head netif_list; + knet_hw_info_t hw; + struct net *netns; + spinlock_t lock; +} psample_info_t; +static psample_info_t g_psample_info = {{0}}; + +/* Maintain sampled pkt statistics */ +typedef struct psample_stats_s { + unsigned long pkts_f_psample_cb; + unsigned long pkts_f_psample_mod; + unsigned long pkts_f_handled; + unsigned long pkts_f_pass_through; + unsigned long pkts_d_no_group; + unsigned long pkts_d_sampling_disabled; + unsigned long pkts_d_no_skb; + unsigned long pkts_d_not_ready; + unsigned long pkts_d_metadata; + unsigned long pkts_d_meta_srcport; + unsigned long pkts_d_meta_dstport; + unsigned long pkts_d_invalid_size; +} psample_stats_t; +static psample_stats_t g_psample_stats = {0}; + +typedef struct psample_meta_s { + int trunc_size; + int src_ifindex; + int dst_ifindex; + int sample_rate; +} psample_meta_t; + + +static psample_netif_t* +psample_netif_lookup_by_port(int unit, int port) +{ + struct list_head *list; + psample_netif_t *psample_netif = NULL; + unsigned long flags; + + /* look for port from list of available net_devices */ + spin_lock_irqsave(&g_psample_info.lock, flags); + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (psample_netif->port == port) { + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return psample_netif; + } + } + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return (NULL); +} + +static int +psample_info_get (int unit, psample_info_t *psample_info) +{ + int rv = 0; + if (!psample_info) { + gprintk("%s: psample_info is NULL\n", __func__); + return (-1); + } + + /* get hw info */ + rv = bkn_hw_info_get(unit, &psample_info->hw); + if (rv < 0) { + gprintk("%s: failed to get hw info\n", __func__); + return (-1); + } + + PSAMPLE_CB_DBG_PRINT("%s: DCB type %d\n", + __func__, psample_info->hw.dcb_type); + return (0); +} + +static int +psample_meta_srcport_get(uint8_t *pkt, void *pkt_meta) +{ + int srcport = 0; + uint32_t *metadata = (uint32_t*)pkt_meta; + + switch(g_psample_info.hw.dcb_type) { + case 36: /* TD3 */ + case 38: /* TH3 */ + break; + case 32: /* TH1/TH2 */ + case 26: /* TD2 */ + case 23: /* HX4 */ + metadata += SOC_DCB32_HG_OFFSET; + break; + default: + break; + } + + if (SOC_HIGIG2_START(metadata) == SOC_HIGIG2_SOP) + { + srcport = SOC_HIGIG2_SRCPORT(metadata); + } + else if (SOC_HIGIG_START(metadata) == SOC_HIGIG_SOP) + { + srcport = SOC_HIGIG_SRCPORT(metadata); + } + else + { + PSAMPLE_CB_DBG_PRINT("%s: Could not detect metadata sop type: 0x%02x (w[0]: 0x%04x)\n", __func__, + SOC_HIGIG_START(metadata), metadata[0]); + return -1; + } + return srcport; +} + +static int +psample_meta_dstport_get(uint8_t *pkt, void *pkt_meta) +{ + int dstport = 0; + uint32_t *metadata = (uint32_t*)pkt_meta; + + switch(g_psample_info.hw.dcb_type) { + case 36: /* TD3 */ + case 38: /* TH3 */ + break; + case 32: /* TH1/TH2 */ + case 26: /* TD2 */ + case 23: /* HX4 */ + metadata += SOC_DCB32_HG_OFFSET; + break; + default: + break; + } + + if (SOC_HIGIG2_START(metadata) == SOC_HIGIG2_SOP) + { + dstport = SOC_HIGIG2_DSTPORT(metadata); + } + else if (SOC_HIGIG_START(metadata) == SOC_HIGIG_SOP) + { + dstport = SOC_HIGIG_DSTPORT(metadata); + } + else + { + PSAMPLE_CB_DBG_PRINT("%s: Could not detect metadata sop type: 0x%02x (w[0]: 0x%04x)\n", __func__, + SOC_HIGIG_START(metadata), metadata[0]); + return (-1); + } + return dstport; +} + +static int +psample_meta_sample_reason(uint8_t *pkt, void *pkt_meta) +{ + uint32_t *metadata = (uint32_t*)pkt_meta; + uint32_t reason = 0; + uint32_t reason_hi = 0; + uint32_t sample_rx_reason_mask = 0; + + /* Sample Pkt reason code (bcmRxReasonSampleSource) */ + switch(g_psample_info.hw.dcb_type) { + case 36: /* TD3 */ + case 38: /* TH3 */ + reason_hi = *(metadata + 4); + reason = *(metadata + 5); + sample_rx_reason_mask = (1 << 3); + break; + case 32: /* TH1/TH2 */ + case 26: /* TD2 */ + case 23: /* HX4 */ + default: + reason_hi = *(metadata + 2); + reason = *(metadata + 3); + sample_rx_reason_mask = (1 << 5); + break; + } + + PSAMPLE_CB_DBG_PRINT("%s: DCB%d sample_rx_reason_mask: 0x%08x, reason: 0x%08x, reason_hi: 0x%08x\n", + __func__, g_psample_info.hw.dcb_type, sample_rx_reason_mask, reason, reason_hi); + + /* Check if only sample reason code is set. + * If only sample reason code, then consume pkt. + * If other reason codes exist, then pkt should be + * passed through to Linux network stack. + */ + if ((reason & ~sample_rx_reason_mask) || reason_hi) { + return 0; /* multiple reasons set, pass through */ + } + + /* only sample rx reason set, consume pkt */ + return (1); +} + +static int +psample_meta_get(int unit, uint8_t *pkt, void *pkt_meta, psample_meta_t *sflow_meta) +{ + int srcport, dstport; + int src_ifindex = 0; + int dst_ifindex = 0; + int sample_rate = PSAMPLE_RATE_DFLT; + int sample_size = PSAMPLE_SIZE_DFLT; + psample_netif_t *psample_netif = NULL; + +#ifdef PSAMPLE_CB_DBG + if (debug & 0x1) { + int i=0; + uint8_t *meta = (uint8_t*)pkt_meta; + PSAMPLE_CB_DBG_PRINT("%s: psample pkt metadata\n", __func__); + for (i=0; i<64; i+=16) { + PSAMPLE_CB_DBG_PRINT("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + meta[i+0], meta[i+1], meta[i+2], meta[i+3], meta[i+4], meta[i+5], meta[i+6], meta[i+7], + meta[i+8], meta[i+9], meta[i+10], meta[i+11], meta[i+12], meta[i+13], meta[i+14], meta[i+15]); + } + } +#endif + + /* parse pkt metadata for src and dst ports */ + srcport = psample_meta_srcport_get(pkt, pkt_meta); + dstport = psample_meta_dstport_get(pkt, pkt_meta); + if ((srcport == -1) || (dstport == -1)) { + gprintk("%s: invalid srcport %d or dstport %d\n", __func__, srcport, dstport); + return (-1); + } + + /* find src port netif (no need to lookup CPU port) */ + if (srcport != 0) { + if ((psample_netif = psample_netif_lookup_by_port(unit, srcport))) { + src_ifindex = psample_netif->dev->ifindex; + sample_rate = psample_netif->sample_rate; + sample_size = psample_netif->sample_size; + } else { + g_psample_stats.pkts_d_meta_srcport++; + PSAMPLE_CB_DBG_PRINT("%s: could not find srcport(%d)\n", __func__, srcport); + } + } + + /* find dst port netif (no need to lookup CPU port) */ + if (dstport != 0) { + if ((psample_netif = psample_netif_lookup_by_port(unit, dstport))) { + dst_ifindex = psample_netif->dev->ifindex; + } else { + g_psample_stats.pkts_d_meta_dstport++; + PSAMPLE_CB_DBG_PRINT("%s: could not find dstport(%d)\n", __func__, dstport); + } + } + + PSAMPLE_CB_DBG_PRINT("%s: srcport %d, dstport %d, src_ifindex %d, dst_ifindex %d, trunc_size %d, sample_rate %d\n", + __func__, srcport, dstport, src_ifindex, dst_ifindex, sample_size, sample_rate); + + sflow_meta->src_ifindex = src_ifindex; + sflow_meta->dst_ifindex = dst_ifindex; + sflow_meta->trunc_size = sample_size; + sflow_meta->sample_rate = sample_rate; + + return (0); +} + +int +psample_filter_cb(uint8_t * pkt, int size, int dev_no, void *pkt_meta, + int chan, kcom_filter_t *kf) +{ + struct psample_group *group; + psample_meta_t meta; + struct sk_buff skb; + int rv = 0; + static int info_get = 0; + + if (!info_get) { + rv = psample_info_get (dev_no, &g_psample_info); + if (rv < 0) { + gprintk("%s: failed to get psample info\n", __func__); + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + info_get = 1; + } + + PSAMPLE_CB_DBG_PRINT("%s: pkt size %d, kf->dest_id %d, kf->cb_user_data %d\n", + __func__, size, kf->dest_id, kf->cb_user_data); + g_psample_stats.pkts_f_psample_cb++; + + /* get psample group info. psample genetlink group ID passed in kf->dest_id */ + group = psample_group_get(g_psample_info.netns, kf->dest_id); + if (!group) { + gprintk("%s: Could not find psample genetlink group %d\n", __func__, kf->cb_user_data); + g_psample_stats.pkts_d_no_group++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + + /* get psample metadata */ + rv = psample_meta_get(dev_no, pkt, pkt_meta, &meta); + if (rv < 0) { + gprintk("%s: Could not parse pkt metadata\n", __func__); + g_psample_stats.pkts_d_metadata++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + + /* Adjust original pkt size to remove 4B FCS */ + if (size < FCS_SZ) { + g_psample_stats.pkts_d_invalid_size++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } else { + size -= FCS_SZ; + } + + /* Account for padding in libnl used by psample */ + if (meta.trunc_size >= size) { + meta.trunc_size = size - PSAMPLE_NLA_PADDING; + } + + PSAMPLE_CB_DBG_PRINT("%s: group 0x%x, trunc_size %d, src_ifdx %d, dst_ifdx %d, sample_rate %d\n", + __func__, group->group_num, meta.trunc_size, meta.src_ifindex, meta.dst_ifindex, meta.sample_rate); + + /* drop if configured sample rate is 0 */ + if (meta.sample_rate > 0) { + /* setup skb to point to pkt */ + memset(&skb, 0, sizeof(struct sk_buff)); + skb.len = size; + skb.data = pkt; + + psample_sample_packet(group, + &skb, + meta.trunc_size, + meta.src_ifindex, + meta.dst_ifindex, + meta.sample_rate); + + g_psample_stats.pkts_f_psample_mod++; + } else { + g_psample_stats.pkts_d_sampling_disabled++; + } + +PSAMPLE_FILTER_CB_PKT_HANDLED: + /* if sample reason only, consume pkt. else pass through */ + rv = psample_meta_sample_reason(pkt, pkt_meta); + if (rv) { + g_psample_stats.pkts_f_handled++; + } else { + g_psample_stats.pkts_f_pass_through++; + } + return rv; +} + +int +psample_netif_create_cb(int unit, kcom_netif_t *netif, struct net_device *dev) +{ + int found; + struct list_head *list; + psample_netif_t *psample_netif, *lpsample_netif; + unsigned long flags; + + if ((psample_netif = kmalloc(sizeof(psample_netif_t), GFP_KERNEL)) == NULL) { + gprintk("%s: failed to alloc psample mem for netif '%s'\n", + __func__, dev->name); + return (-1); + } + + spin_lock_irqsave(&g_psample_info.lock, flags); + + psample_netif->dev = dev; + psample_netif->id = netif->id; + psample_netif->port = netif->port; + psample_netif->vlan = netif->vlan; + psample_netif->qnum = netif->qnum; + psample_netif->sample_rate = PSAMPLE_RATE_DFLT; + psample_netif->sample_size = PSAMPLE_SIZE_DFLT; + + /* insert netif sorted by ID similar to bkn_knet_netif_create() */ + found = 0; + list_for_each(list, &g_psample_info.netif_list) { + lpsample_netif = (psample_netif_t*)list; + if (netif->id < lpsample_netif->id) { + found = 1; + break; + } + } + + if (found) { + /* Replace previously removed interface */ + list_add_tail(&psample_netif->list, &lpsample_netif->list); + } else { + /* No holes - add to end of list */ + list_add_tail(&psample_netif->list, &g_psample_info.netif_list); + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + PSAMPLE_CB_DBG_PRINT("%s: added psample netif '%s'\n", __func__, dev->name); + return (0); +} + +int +psample_netif_destroy_cb(int unit, kcom_netif_t *netif, struct net_device *dev) +{ + int found; + struct list_head *list; + psample_netif_t *psample_netif; + unsigned long flags; + + if (!netif || !dev) { + gprintk("%s: netif or net_device is NULL\n", __func__); + return (-1); + } + + spin_lock_irqsave(&g_psample_info.lock, flags); + + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (netif->id == psample_netif->id) { + found = 1; + list_del(&psample_netif->list); + PSAMPLE_CB_DBG_PRINT("%s: removing psample netif '%s'\n", __func__, dev->name); + kfree(psample_netif); + break; + } + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + if (!found) { + gprintk("%s: netif ID %d not found!\n", __func__, netif->id); + return (-1); + } + return (0); +} + +/* + * psample rate Proc Read Entry + */ +static int +psample_proc_rate_show(struct seq_file *m, void *v) +{ + struct list_head *list; + psample_netif_t *psample_netif; + unsigned long flags; + + spin_lock_irqsave(&g_psample_info.lock, flags); + + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + seq_printf(m, " %-14s %d\n", psample_netif->dev->name, psample_netif->sample_rate); + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + return 0; +} + +static int +psample_proc_rate_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_rate_show, NULL); +} + +/* + * psample rate Proc Write Entry + * + * Syntax: + * = + * + * Where is a virtual network interface name. + * + * Examples: + * eth4=1000 + */ +static ssize_t +psample_proc_rate_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + int found; + struct list_head *list; + psample_netif_t *psample_netif; + char sample_str[40], *ptr, *newline; + unsigned long flags; + + + if (count > sizeof(sample_str)) { + count = sizeof(sample_str) - 1; + sample_str[count] = '\0'; + } + if (copy_from_user(sample_str, buf, count)) { + return -EFAULT; + } + sample_str[count] = 0; + newline = strchr(sample_str, '\n'); + if (newline) { + /* Chop off the trailing newline */ + *newline = '\0'; + } + + if ((ptr = strchr(sample_str, '=')) == NULL && + (ptr = strchr(sample_str, ':')) == NULL) { + gprintk("Error: Pkt sample rate syntax not recognized: '%s'\n", sample_str); + return count; + } + *ptr++ = 0; + + spin_lock_irqsave(&g_psample_info.lock, flags); + + found = 0; + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (strcmp(psample_netif->dev->name, sample_str) == 0) { + psample_netif->sample_rate = simple_strtol(ptr, NULL, 10); + // TODO MLI@BRCM - check valid sample rate + found = 1; + break; + } + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + if (!found) { + gprintk("Warning: Failed setting psample rate on unknown network interface: '%s'\n", sample_str); + } + return count; +} + +struct file_operations psample_proc_rate_file_ops = { + owner: THIS_MODULE, + open: psample_proc_rate_open, + read: seq_read, + llseek: seq_lseek, + write: psample_proc_rate_write, + release: single_release, +}; + +/* + * psample size Proc Read Entry + */ +static int +psample_proc_size_show(struct seq_file *m, void *v) +{ + struct list_head *list; + psample_netif_t *psample_netif; + unsigned long flags; + + spin_lock_irqsave(&g_psample_info.lock, flags); + + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + seq_printf(m, " %-14s %d\n", psample_netif->dev->name, psample_netif->sample_size); + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return 0; +} + +static int +psample_proc_size_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_size_show, NULL); +} + +/* + * psample size Proc Write Entry + * + * Syntax: + * = + * + * Where is a virtual network interface name. + * + * Examples: + * eth4=128 + */ +static ssize_t +psample_proc_size_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + int found; + struct list_head *list; + psample_netif_t *psample_netif; + char sample_str[40], *ptr, *newline; + unsigned long flags; + + if (count > sizeof(sample_str)) { + count = sizeof(sample_str) - 1; + sample_str[count] = '\0'; + } + if (copy_from_user(sample_str, buf, count)) { + return -EFAULT; + } + sample_str[count] = 0; + newline = strchr(sample_str, '\n'); + if (newline) { + /* Chop off the trailing newline */ + *newline = '\0'; + } + + if ((ptr = strchr(sample_str, '=')) == NULL && + (ptr = strchr(sample_str, ':')) == NULL) { + gprintk("Error: Pkt sample size syntax not recognized: '%s'\n", sample_str); + return count; + } + *ptr++ = 0; + + spin_lock_irqsave(&g_psample_info.lock, flags); + + found = 0; + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (strcmp(psample_netif->dev->name, sample_str) == 0) { + psample_netif->sample_size = simple_strtol(ptr, NULL, 10); + // TODO MLI@BRCM - check valid sample size + found = 1; + break; + } + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + if (!found) { + gprintk("Warning: Failed setting psample size on unknown network interface: '%s'\n", sample_str); + } + return count; +} + +struct file_operations psample_proc_size_file_ops = { + owner: THIS_MODULE, + open: psample_proc_size_open, + read: seq_read, + llseek: seq_lseek, + write: psample_proc_size_write, + release: single_release, +}; + +/* + * psample debug Proc Read Entry + */ +static int +psample_proc_debug_show(struct seq_file *m, void *v) +{ + seq_printf(m, "BCM KNET %s Callback Config\n", PSAMPLE_CB_NAME); + seq_printf(m, " debug: 0x%x\n", debug); + seq_printf(m, " cmic_type: %d\n", g_psample_info.hw.cmic_type); + seq_printf(m, " dcb_type: %d\n", g_psample_info.hw.dcb_type); + seq_printf(m, " dcb_size: %d\n", g_psample_info.hw.dcb_size); + seq_printf(m, " pkt_hdr_size: %d\n", g_psample_info.hw.pkt_hdr_size); + seq_printf(m, " cdma_channels: %d\n", g_psample_info.hw.cdma_channels); + + return 0; +} + +static int +psample_proc_debug_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_debug_show, NULL); +} + +/* + * psample debug Proc Write Entry + * + * Syntax: + * debug= + * + * Where corresponds to the debug module parameter. + * + * Examples: + * debug=0x1 + */ +static ssize_t +psample_proc_debug_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + char debug_str[40]; + char *ptr; + + if (count > sizeof(debug_str)) { + count = sizeof(debug_str) - 1; + debug_str[count] = '\0'; + } + if (copy_from_user(debug_str, buf, count)) { + return -EFAULT; + } + + if ((ptr = strstr(debug_str, "debug=")) != NULL) { + ptr += 6; + debug = simple_strtol(ptr, NULL, 0); + } else { + gprintk("Warning: unknown configuration setting\n"); + } + + return count; +} + +struct file_operations psample_proc_debug_file_ops = { + owner: THIS_MODULE, + open: psample_proc_debug_open, + read: seq_read, + llseek: seq_lseek, + write: psample_proc_debug_write, + release: single_release, +}; + +static int +psample_proc_stats_show(struct seq_file *m, void *v) +{ + seq_printf(m, "BCM KNET %s Callback Stats\n", PSAMPLE_CB_NAME); + seq_printf(m, " DCB type %d\n", g_psample_info.hw.dcb_type); + seq_printf(m, " pkts filter psample cb %10lu\n", g_psample_stats.pkts_f_psample_cb); + seq_printf(m, " pkts sent to psample module %10lu\n", g_psample_stats.pkts_f_psample_mod); + seq_printf(m, " pkts handled by psample %10lu\n", g_psample_stats.pkts_f_handled); + seq_printf(m, " pkts pass through %10lu\n", g_psample_stats.pkts_f_pass_through); + seq_printf(m, " pkts drop no psample group %10lu\n", g_psample_stats.pkts_d_no_group); + seq_printf(m, " pkts drop sampling disabled %10lu\n", g_psample_stats.pkts_d_sampling_disabled); + seq_printf(m, " pkts drop no skb %10lu\n", g_psample_stats.pkts_d_no_skb); + seq_printf(m, " pkts drop psample not ready %10lu\n", g_psample_stats.pkts_d_not_ready); + seq_printf(m, " pkts drop metadata parse error %10lu\n", g_psample_stats.pkts_d_metadata); + seq_printf(m, " pkts with invalid src port %10lu\n", g_psample_stats.pkts_d_meta_srcport); + seq_printf(m, " pkts with invalid dst port %10lu\n", g_psample_stats.pkts_d_meta_dstport); + seq_printf(m, " pkts with invalid orig pkt sz %10lu\n", g_psample_stats.pkts_d_invalid_size); + return 0; +} + +static int +psample_proc_stats_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_stats_show, NULL); +} + +struct file_operations psample_proc_stats_file_ops = { + owner: THIS_MODULE, + open: psample_proc_stats_open, + read: seq_read, + llseek: seq_lseek, + write: NULL, + release: single_release, +}; + +int psample_cleanup(void) +{ + remove_proc_entry("stats", psample_proc_root); + remove_proc_entry("rate", psample_proc_root); + remove_proc_entry("size", psample_proc_root); + remove_proc_entry("debug", psample_proc_root); + return 0; +} + +int psample_init(void) +{ + #define PROCFS_MAX_PATH 1024 + char psample_procfs_path[PROCFS_MAX_PATH]; + struct proc_dir_entry *entry; + + /* create procfs for psample */ + snprintf(psample_procfs_path, PROCFS_MAX_PATH, "bcm/knet-cb"); + proc_mkdir(psample_procfs_path, NULL); + snprintf(psample_procfs_path, PROCFS_MAX_PATH, "%s/%s", psample_procfs_path, PSAMPLE_CB_NAME); + psample_proc_root = proc_mkdir(psample_procfs_path, NULL); + + /* create procfs for psample stats */ + PROC_CREATE(entry, "stats", 0666, psample_proc_root, &psample_proc_stats_file_ops); + if (entry == NULL) { + gprintk("%s: Unable to create procfs entry '/procfs/%s/stats'\n", __func__, psample_procfs_path); + return -1; + } + + /* create procfs for setting sample rates */ + PROC_CREATE(entry, "rate", 0666, psample_proc_root, &psample_proc_rate_file_ops); + if (entry == NULL) { + gprintk("%s: Unable to create procfs entry '/procfs/%s/rate'\n", __func__, psample_procfs_path); + return -1; + } + + /* create procfs for setting sample size */ + PROC_CREATE(entry, "size", 0666, psample_proc_root, &psample_proc_size_file_ops); + if (entry == NULL) { + gprintk("%s: Unable to create procfs entry '/procfs/%s/size'\n", __func__, psample_procfs_path); + return -1; + } + + /* create procfs for debug log */ + PROC_CREATE(entry, "debug", 0666, psample_proc_root, &psample_proc_debug_file_ops); + if (entry == NULL) { + gprintk("%s: Unable to create procfs entry '/procfs/%s/debug'\n", __func__, psample_procfs_path); + return -1; + } + + /* clear data structs */ + memset(&g_psample_stats, 0, sizeof(psample_stats_t)); + memset(&g_psample_info, 0, sizeof(psample_info_t)); + + /* setup psample_info struct */ + INIT_LIST_HEAD(&g_psample_info.netif_list); + spin_lock_init(&g_psample_info.lock); + + /* get net namespace */ + g_psample_info.netns = get_net_ns_by_pid(current->pid); + if (!g_psample_info.netns) { + gprintk("%s: Could not get network namespace for pid %d\n", __func__, current->pid); + return (-1); + } + PSAMPLE_CB_DBG_PRINT("%s: current->pid %d, netns 0x%p, sample_size %d\n", __func__, + current->pid, g_psample_info.netns, psample_size); + + return 0; +} diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.h b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.h new file mode 100644 index 0000000000..8f9398c516 --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.h @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Broadcom + * + * 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 (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: psample_cb.h $ + * $Copyright: (c) 2019 Broadcom Corp. + * All Rights Reserved.$ + */ +#ifndef __PSAMPLE_CB_H__ +#define __PSAMPLE_CB_H__ + +#include +#include +#include + +#define PSAMPLE_CB_NAME "psample" + +extern int +psample_init(void); + +extern int +psample_cleanup(void); + +extern int +psample_filter_cb(uint8_t * pkt, int size, int dev_no, void *pkt_meta, + int chan, kcom_filter_t *kf); + +/* psample data per interface */ +typedef struct { + struct list_head list; + struct net_device *dev; + uint16 id; + uint8 port; + uint16 vlan; + uint16 qnum; + uint32 sample_rate; + uint32 sample_size; +} psample_netif_t; + +extern int +psample_netif_create_cb(int unit, kcom_netif_t *netif, struct net_device *dev); + +extern int +psample_netif_destroy_cb(int unit, kcom_netif_t *netif, struct net_device *dev); + +#endif /* __PSAMPLE_CB_H__ */ diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/Makefile b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/Makefile new file mode 100644 index 0000000000..631590104c --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/Makefile @@ -0,0 +1,64 @@ +# +# Copyright 2017 Broadcom +# +# 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 (the "GPL"). +# +# 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 version 2 (GPLv2) for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 (GPLv2) along with this source code. +# +# -*- Makefile -*- +# $Id: Makefile,v 1.3 Broadcom SDK $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ +# +LOCALDIR = systems/linux/kernel/modules/psample + +include ${SDK}/make/Make.config + +LIBS = $(LIBDIR)/libkern.a + +ifeq ($(kernel_version),2_4) +MODULE = $(LIBDIR)/psample.o +else +KERNEL_MODULE_DIR = kernel_module + +THIS_MOD_NAME := psample +MODULE = $(LIBDIR)/$(THIS_MOD_NAME).o +KMODULE = $(LIBDIR)/$(THIS_MOD_NAME).ko + +build: $(MODULE) $(KMODULE) +endif + +KBUILD_EXTRA_SYMBOLS := ${BLDDIR}/../bcm-knet/kernel_module/Module.symvers + +# BCM Network Device + +$(MODULE): $(BLDDIR)/.tree $(BOBJS) $(LIBS) + $(LD) $(MODULE_LDFLAGS) -r -d $(BOBJS) $(LIBS) -o $@ +ifneq ($(kernel_version),2_4) +$(KMODULE): $(MODULE) + rm -fr $(BLDDIR)/$(KERNEL_MODULE_DIR) + mkdir $(BLDDIR)/$(KERNEL_MODULE_DIR) + cp ${SDK}/make/Makefile.linux-kmodule $(BLDDIR)/$(KERNEL_MODULE_DIR)/Makefile + cat ${KBUILD_EXTRA_SYMBOLS} > $(BLDDIR)/$(KERNEL_MODULE_DIR)/Module.symvers + MOD_NAME=$(THIS_MOD_NAME) $(MAKE) -C $(BLDDIR)/$(KERNEL_MODULE_DIR) $(THIS_MOD_NAME).ko +endif + +# Make.depend is before clean:: so that Make.depend's clean:: runs first. + +include ${SDK}/make/Make.depend + +clean:: + $(RM) $(BLDDIR)/version.c $(BLDDIR)/version.o + $(RM) $(BOBJS) $(MODULE) + +ifneq ($(kernel_version),2_4) +.PHONY: build +endif diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/psample.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/psample.c new file mode 100644 index 0000000000..e1d4e2353b --- /dev/null +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/psample.c @@ -0,0 +1,302 @@ +/* + * net/psample/psample.c - Netlink channel for packet sampling + * Copyright (c) 2017 Yotam Gigi + * + * 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 + +#define PSAMPLE_MAX_PACKET_SIZE 0xffff + +static LIST_HEAD(psample_groups_list); +static DEFINE_SPINLOCK(psample_groups_lock); + +/* multicast groups */ +enum psample_nl_multicast_groups { + PSAMPLE_NL_MCGRP_CONFIG, + PSAMPLE_NL_MCGRP_SAMPLE, +}; + +static const struct genl_multicast_group psample_nl_mcgrps[] = { + [PSAMPLE_NL_MCGRP_CONFIG] = { .name = PSAMPLE_NL_MCGRP_CONFIG_NAME }, + [PSAMPLE_NL_MCGRP_SAMPLE] = { .name = PSAMPLE_NL_MCGRP_SAMPLE_NAME }, +}; + +static struct genl_family psample_nl_family __ro_after_init; + +static int psample_group_nl_fill(struct sk_buff *msg, + struct psample_group *group, + enum psample_command cmd, u32 portid, u32 seq, + int flags) +{ + void *hdr; + int ret; + + hdr = genlmsg_put(msg, portid, seq, &psample_nl_family, flags, cmd); + if (!hdr) + return -EMSGSIZE; + + ret = nla_put_u32(msg, PSAMPLE_ATTR_SAMPLE_GROUP, group->group_num); + if (ret < 0) + goto error; + + ret = nla_put_u32(msg, PSAMPLE_ATTR_GROUP_REFCOUNT, group->refcount); + if (ret < 0) + goto error; + + ret = nla_put_u32(msg, PSAMPLE_ATTR_GROUP_SEQ, group->seq); + if (ret < 0) + goto error; + + genlmsg_end(msg, hdr); + return 0; + +error: + genlmsg_cancel(msg, hdr); + return -EMSGSIZE; +} + +static int psample_nl_cmd_get_group_dumpit(struct sk_buff *msg, + struct netlink_callback *cb) +{ + struct psample_group *group; + int start = cb->args[0]; + int idx = 0; + int err; + + spin_lock(&psample_groups_lock); + list_for_each_entry(group, &psample_groups_list, list) { + if (!net_eq(group->net, sock_net(msg->sk))) + continue; + if (idx < start) { + idx++; + continue; + } + err = psample_group_nl_fill(msg, group, PSAMPLE_CMD_NEW_GROUP, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, NLM_F_MULTI); + if (err) + break; + idx++; + } + + spin_unlock(&psample_groups_lock); + cb->args[0] = idx; + return msg->len; +} + +static const struct genl_ops psample_nl_ops[] = { + { + .cmd = PSAMPLE_CMD_GET_GROUP, + .dumpit = psample_nl_cmd_get_group_dumpit, + /* can be retrieved by unprivileged users */ + } +}; + +static struct genl_family psample_nl_family __ro_after_init = { + .name = PSAMPLE_GENL_NAME, + .version = PSAMPLE_GENL_VERSION, + .maxattr = PSAMPLE_ATTR_MAX, + .netnsok = true, + .module = THIS_MODULE, + .mcgrps = psample_nl_mcgrps, + .ops = psample_nl_ops, + .n_ops = ARRAY_SIZE(psample_nl_ops), + .n_mcgrps = ARRAY_SIZE(psample_nl_mcgrps), +}; + +static void psample_group_notify(struct psample_group *group, + enum psample_command cmd) +{ + struct sk_buff *msg; + int err; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); + if (!msg) + return; + + err = psample_group_nl_fill(msg, group, cmd, 0, 0, NLM_F_MULTI); + if (!err) + genlmsg_multicast_netns(&psample_nl_family, group->net, msg, 0, + PSAMPLE_NL_MCGRP_CONFIG, GFP_ATOMIC); + else + nlmsg_free(msg); +} + +static struct psample_group *psample_group_create(struct net *net, + u32 group_num) +{ + struct psample_group *group; + + group = kzalloc(sizeof(*group), GFP_ATOMIC); + if (!group) + return NULL; + + group->net = net; + group->group_num = group_num; + list_add_tail(&group->list, &psample_groups_list); + + psample_group_notify(group, PSAMPLE_CMD_NEW_GROUP); + return group; +} + +static void psample_group_destroy(struct psample_group *group) +{ + psample_group_notify(group, PSAMPLE_CMD_DEL_GROUP); + list_del(&group->list); + kfree(group); +} + +static struct psample_group * +psample_group_lookup(struct net *net, u32 group_num) +{ + struct psample_group *group; + + list_for_each_entry(group, &psample_groups_list, list) + if ((group->group_num == group_num) && (group->net == net)) + return group; + return NULL; +} + +struct psample_group *psample_group_get(struct net *net, u32 group_num) +{ + struct psample_group *group; + + spin_lock(&psample_groups_lock); + + group = psample_group_lookup(net, group_num); + if (!group) { + group = psample_group_create(net, group_num); + if (!group) + goto out; + } + group->refcount++; + +out: + spin_unlock(&psample_groups_lock); + return group; +} +EXPORT_SYMBOL_GPL(psample_group_get); + +void psample_group_put(struct psample_group *group) +{ + spin_lock(&psample_groups_lock); + + if (--group->refcount == 0) + psample_group_destroy(group); + + spin_unlock(&psample_groups_lock); +} +EXPORT_SYMBOL_GPL(psample_group_put); + +void psample_sample_packet(struct psample_group *group, struct sk_buff *skb, + u32 trunc_size, int in_ifindex, int out_ifindex, + u32 sample_rate) +{ + struct sk_buff *nl_skb; + int data_len; + int meta_len; + void *data; + int ret; + + meta_len = (in_ifindex ? nla_total_size(sizeof(u16)) : 0) + + (out_ifindex ? nla_total_size(sizeof(u16)) : 0) + + nla_total_size(sizeof(u32)) + /* sample_rate */ + nla_total_size(sizeof(u32)) + /* orig_size */ + nla_total_size(sizeof(u32)) + /* group_num */ + nla_total_size(sizeof(u32)); /* seq */ + + data_len = min(skb->len, trunc_size); + if (meta_len + nla_total_size(data_len) > PSAMPLE_MAX_PACKET_SIZE) + data_len = PSAMPLE_MAX_PACKET_SIZE - meta_len - NLA_HDRLEN + - NLA_ALIGNTO; + + nl_skb = genlmsg_new(meta_len + data_len, GFP_ATOMIC); + if (unlikely(!nl_skb)) + return; + + data = genlmsg_put(nl_skb, 0, 0, &psample_nl_family, 0, + PSAMPLE_CMD_SAMPLE); + if (unlikely(!data)) + goto error; + + if (in_ifindex) { + ret = nla_put_u16(nl_skb, PSAMPLE_ATTR_IIFINDEX, in_ifindex); + if (unlikely(ret < 0)) + goto error; + } + + if (out_ifindex) { + ret = nla_put_u16(nl_skb, PSAMPLE_ATTR_OIFINDEX, out_ifindex); + if (unlikely(ret < 0)) + goto error; + } + + ret = nla_put_u32(nl_skb, PSAMPLE_ATTR_SAMPLE_RATE, sample_rate); + if (unlikely(ret < 0)) + goto error; + + ret = nla_put_u32(nl_skb, PSAMPLE_ATTR_ORIGSIZE, skb->len); + if (unlikely(ret < 0)) + goto error; + + ret = nla_put_u32(nl_skb, PSAMPLE_ATTR_SAMPLE_GROUP, group->group_num); + if (unlikely(ret < 0)) + goto error; + + ret = nla_put_u32(nl_skb, PSAMPLE_ATTR_GROUP_SEQ, group->seq++); + if (unlikely(ret < 0)) + goto error; + + if (data_len) { + int nla_len = nla_total_size(data_len); + struct nlattr *nla; + + nla = (struct nlattr *)skb_put(nl_skb, nla_len); + nla->nla_type = PSAMPLE_ATTR_DATA; + nla->nla_len = nla_attr_size(data_len); + + if (skb_copy_bits(skb, 0, nla_data(nla), data_len)) + goto error; + } + + genlmsg_end(nl_skb, data); + genlmsg_multicast_netns(&psample_nl_family, group->net, nl_skb, 0, + PSAMPLE_NL_MCGRP_SAMPLE, GFP_ATOMIC); + + return; +error: + pr_err_ratelimited("Could not create psample log message\n"); + nlmsg_free(nl_skb); +} +EXPORT_SYMBOL_GPL(psample_sample_packet); + +static int __init psample_module_init(void) +{ + return genl_register_family(&psample_nl_family); +} + +static void __exit psample_module_exit(void) +{ + genl_unregister_family(&psample_nl_family); +} + +module_init(psample_module_init); +module_exit(psample_module_exit); + +MODULE_AUTHOR("Yotam Gigi "); +MODULE_DESCRIPTION("netlink channel for packet sampling"); +MODULE_LICENSE("GPL v2"); diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/common/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/common/Makefile index 0e62265443..20d83735fc 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/user/common/Makefile +++ b/platform/broadcom/saibcm-modules/systems/linux/user/common/Makefile @@ -91,6 +91,9 @@ KNET_CB := $(DEST_DIR)/$(KNET_CB_LOCAL) BCM_KNET_LOCAL :=linux-bcm-knet.$(KOBJ) BCM_KNET=$(DEST_DIR)/$(BCM_KNET_LOCAL) +PSAMPLE_LOCAL := psample.$(KOBJ) +PSAMPLE := $(DEST_DIR)/$(PSAMPLE_LOCAL) + ifeq (,$(findstring DELIVER,$(MAKECMDGOALS))) .DEFAULT_GOAL := all all_targets := kernel_modules $(KERNEL_BDE) $(USER_BDE) @@ -126,6 +129,15 @@ all_targets +=$(LOCAL_TARGETS) endif endif +ifdef BUILD_PSAMPLE +all_targets += $(PSAMPLE) +ADD_TO_CFLAGS += -DPSAMPLE_SUPPORT +ifeq ($(NO_LOCAL_TARGETS),) +LOCAL_TARGETS +=$(patsubst %,../$(platform)/%,$(PSAMPLE_LOCAL)) +all_targets +=$(LOCAL_TARGETS) +endif +endif + ADD_TO_CFLAGS += -I$(SDK)/systems/linux/kernel/modules/include COND_KNET_LIBS = libuser.$(libext) endif @@ -159,6 +171,10 @@ kernel_modules: ifeq ($(BUILD_KNET),1) $(MAKE) -j1 -C $(SDK)/systems/linux/kernel/modules kernel_version=$(kernel_version) \ subdirs="shared bcm-knet" override-target=linux-$(platform) CFLAGS="$(CFLAGS)" +ifdef BUILD_PSAMPLE + $(MAKE) -j1 -C $(SDK)/systems/linux/kernel/modules kernel_version=$(kernel_version) \ + subdirs="psample" override-target=linux-$(platform) CFLAGS="$(CFLAGS)" +endif ifdef BUILD_KNET_CB $(MAKE) -j1 -C $(SDK)/systems/linux/kernel/modules kernel_version=$(kernel_version) \ subdirs="knet-cb" override-target=linux-$(platform) CFLAGS="$(CFLAGS)" @@ -178,6 +194,10 @@ $(BCM_KNET): $(KERN_BLDROOT)/linux-bcm-knet.$(KOBJ) $(KNET_CB): $(KERN_BLDROOT)/linux-knet-cb.$(KOBJ) $(OBJCOPY) --strip-debug $< $@ +$(PSAMPLE): $(KERN_BLDROOT)/psample.$(KOBJ) + $(OBJCOPY) --strip-debug $< $@ + + ifeq ($(NO_LOCAL_TARGETS),) $(foreach targ,$(LOCAL_TARGETS),$(eval $(call LOCAL_TARGET_DEF,$(targ)))) endif @@ -194,6 +214,7 @@ clean:: $(RM) $(KERN_BLDROOT)/linux-user-bde.$(KOBJ) $(RM) $(KERN_BLDROOT)/linux-bcm-knet.$(KOBJ) $(RM) $(KERN_BLDROOT)/linux-knet-cb.$(KOBJ) + $(RM) $(KERN_BLDROOT)/psample.$(KOBJ) $(RM) $(LOCAL_TARGETS) distclean:: clean diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/iproc/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/iproc/Makefile index 7a8b4a8b0c..03300ff8a0 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/user/iproc/Makefile +++ b/platform/broadcom/saibcm-modules/systems/linux/user/iproc/Makefile @@ -44,7 +44,7 @@ endif export SDK -override kernel_version=4_4 +override kernel_version=4_14 platform=iproc IPROC_BUILD=1 diff --git a/sonic-slave-stretch/Dockerfile.j2 b/sonic-slave-stretch/Dockerfile.j2 index f52bd943b0..31be4f50d4 100644 --- a/sonic-slave-stretch/Dockerfile.j2 +++ b/sonic-slave-stretch/Dockerfile.j2 @@ -291,7 +291,9 @@ RUN apt-get update && apt-get install -y \ automake1.11 \ libselinux1-dev \ # For kdump-tools - liblzo2-dev + liblzo2-dev \ +# For SAI3.7 + libprotobuf-dev # For smartmontools 6.6-1 RUN apt-get -t stretch-backports install -y debhelper