diff --git a/.gitignore b/.gitignore index 7394541687..1f921971d8 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,9 @@ src/lldpd/* !src/lldpd/patch/ src/lm-sensors/* !src/lm-sensors/Makefile +src/monit/* +!src/monit/Makefile +!src/monit/patch/ src/mpdecimal/* !src/mpdecimal/Makefile src/python-click/* diff --git a/build_debian.sh b/build_debian.sh index ffa67b0653..cf545ff2fe 100755 --- a/build_debian.sh +++ b/build_debian.sh @@ -240,7 +240,6 @@ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y in openssh-server \ python \ python-setuptools \ - monit \ python-apt \ traceroute \ iputils-ping \ @@ -348,10 +347,6 @@ EOF sudo sed -i 's/^ListenAddress ::/#ListenAddress ::/' $FILESYSTEM_ROOT/etc/ssh/sshd_config sudo sed -i 's/^#ListenAddress 0.0.0.0/ListenAddress 0.0.0.0/' $FILESYSTEM_ROOT/etc/ssh/sshd_config -## Config monit -sudo cp files/image_config/monit/monitrc $FILESYSTEM_ROOT/etc/monit/ -sudo chmod 600 $FILESYSTEM_ROOT/etc/monit/monitrc - ## Config sysctl sudo mkdir -p $FILESYSTEM_ROOT/var/core sudo augtool --autosave " diff --git a/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/sai.profile b/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/sai.profile old mode 100644 new mode 100755 index 0e465ce12e..47e3107477 --- a/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/sai.profile +++ b/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/sai.profile @@ -1 +1 @@ -SAI_INIT_CONFIG_FILE=/etc/bcm/td3-as7326-48x25G+8x100G.config.bcm +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-as7326-48x25G+8x100G.config.bcm diff --git a/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/td3-as7326-48x25G+8x100G.config.bcm b/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/td3-as7326-48x25G+8x100G.config.bcm index 2b7b6fb080..1a4b7da32d 100755 --- a/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/td3-as7326-48x25G+8x100G.config.bcm +++ b/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/td3-as7326-48x25G+8x100G.config.bcm @@ -17,6 +17,7 @@ l2xmsg_mode=1 bcm_num_cos=8 bcm_stat_interval=2000000 cdma_timeout_usec=3000000 +ifp_inports_support_enable=1 ipv6_lpm_128b_enable=0x1 l3_max_ecmp_mode=1 l3_alpm_enable=2 @@ -24,11 +25,13 @@ lpm_scaling_enable=0 max_vp_lags=0 miim_intr_enable=0 module_64ports=1 +port_flex_enable=1 schan_intr_enable=0 stable_size=0x5500000 tdma_timeout_usec=3000000 skip_L2_USER_ENTRY=0 bcm_tunnel_term_compatible_mode=1 +l3_alpm_ipv6_128b_bkt_rsvd=1 dport_map_port_1=6 dport_map_port_2=2 diff --git a/device/accton/x86_64-accton_as7326_56x-r0/custom_led.bin b/device/accton/x86_64-accton_as7326_56x-r0/custom_led.bin new file mode 100755 index 0000000000..8495c82168 Binary files /dev/null and b/device/accton/x86_64-accton_as7326_56x-r0/custom_led.bin differ diff --git a/device/accton/x86_64-accton_as7326_56x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7326_56x-r0/led_proc_init.soc new file mode 100755 index 0000000000..01b49772c0 --- /dev/null +++ b/device/accton/x86_64-accton_as7326_56x-r0/led_proc_init.soc @@ -0,0 +1,6 @@ +#led auto off +#led stop +m0 load 0 0x0 /usr/share/sonic/platform/linkscan_led_fw.bin +m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin +led auto on +led start diff --git a/device/accton/x86_64-accton_as7326_56x-r0/linkscan_led_fw.bin b/device/accton/x86_64-accton_as7326_56x-r0/linkscan_led_fw.bin new file mode 100755 index 0000000000..a6a4794ecc Binary files /dev/null and b/device/accton/x86_64-accton_as7326_56x-r0/linkscan_led_fw.bin differ diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/platform_wait b/device/mellanox/x86_64-mlnx_msn2700-r0/platform_wait index 44321184dc..a233eb41de 100755 --- a/device/mellanox/x86_64-mlnx_msn2700-r0/platform_wait +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/platform_wait @@ -1,12 +1,37 @@ #!/bin/bash +declare -r SYSLOG_LOGGER="/usr/bin/logger" +declare -r SYSLOG_IDENTIFIER="platform_wait" +declare -r SYSLOG_ERROR="error" +declare -r SYSLOG_NOTICE="notice" +declare -r SYSLOG_INFO="info" + +declare -r HW_MGMT_CONFIG="/var/run/hw-management/config" + +declare -r MODULE_COUNTER="${HW_MGMT_CONFIG}/module_counter" +declare -r SFP_COUNTER="${HW_MGMT_CONFIG}/sfp_counter" + declare -r EXIT_SUCCESS="0" declare -r EXIT_TIMEOUT="1" -declare -r QSFP_PATH="/var/run/hw-management/qsfp" +function log_error() { + eval "${SYSLOG_LOGGER} -t ${SYSLOG_IDENTIFIER} -p ${SYSLOG_ERROR} $@" +} -function WaitForQsfpReady() { - local -r _QSFP_PATH="${1}" +function log_notice() { + eval "${SYSLOG_LOGGER} -t ${SYSLOG_IDENTIFIER} -p ${SYSLOG_NOTICE} $@" +} + +function log_info() { + eval "${SYSLOG_LOGGER} -t ${SYSLOG_IDENTIFIER} -p ${SYSLOG_INFO} $@" +} + +function wait_for_sfp() { + local -r _NUM_MATCH="^[0-9]+$" + local -r _NUM_ZERO="0" + + local _MODULE_CNT="0" + local _SFP_CNT="0" local -i _WDOG_CNT="1" local -ir _WDOG_MAX="300" @@ -14,11 +39,14 @@ function WaitForQsfpReady() { local -r _TIMEOUT="1s" while [[ "${_WDOG_CNT}" -le "${_WDOG_MAX}" ]]; do - for _QSFP in ${_QSFP_PATH}/qsfp*; do - if [[ -e "${_QSFP}" ]]; then + _MODULE_CNT="$(cat ${MODULE_COUNTER} 2>&1)" + _SFP_CNT="$(cat ${SFP_COUNTER} 2>&1)" + + if [[ "${_MODULE_CNT}" =~ ${_NUM_MATCH} && "${_SFP_CNT}" =~ ${_NUM_MATCH} ]]; then + if [[ "${_SFP_CNT}" -gt "${_NUM_ZERO}" && "${_MODULE_CNT}" -eq "${_SFP_CNT}" ]]; then return "${EXIT_SUCCESS}" fi - done + fi let "_WDOG_CNT++" sleep "${_TIMEOUT}" @@ -27,14 +55,15 @@ function WaitForQsfpReady() { return "${EXIT_TIMEOUT}" } -echo "Wait for QSFP I2C interface is ready" +log_info "Wait for SFP interfaces to be ready" -WaitForQsfpReady "${QSFP_PATH}" +wait_for_sfp EXIT_CODE="$?" if [[ "${EXIT_CODE}" != "${EXIT_SUCCESS}" ]]; then - echo "QSFP I2C interface is not ready: timeout" + log_error "SFP interfaces are not ready: timeout" exit "${EXIT_CODE}" fi -echo "QSFP I2C interface is ready: mlxsw_minimal has finished initialization" +log_info "SFP interfaces are ready" + exit "${EXIT_SUCCESS}" diff --git a/dockers/docker-base-stretch/Dockerfile.j2 b/dockers/docker-base-stretch/Dockerfile.j2 index e1d48cfa05..d8188a06af 100644 --- a/dockers/docker-base-stretch/Dockerfile.j2 +++ b/dockers/docker-base-stretch/Dockerfile.j2 @@ -48,7 +48,13 @@ RUN apt-get update && \ vim-tiny \ # Install dependencies of supervisor python-pkg-resources \ - python-meld3 + python-meld3 \ +# dependencies of redis-tools + libatomic1 \ + libjemalloc1 \ + liblua5.1-0 \ + lua-bitop \ + lua-cjson {% if CONFIGURED_ARCH == "armhf" %} # ip and ifconfig utility missing in docker for armhf diff --git a/dockers/docker-dhcp-relay/start.sh b/dockers/docker-dhcp-relay/start.sh index 54e58dd42a..0ac5ea1a10 100755 --- a/dockers/docker-dhcp-relay/start.sh +++ b/dockers/docker-dhcp-relay/start.sh @@ -16,12 +16,6 @@ if [ $(supervisorctl status | grep -c "^isc-dhcp-relay:") -gt 0 ]; then # lifetime of the process. /usr/bin/wait_for_intf.sh - # Allow a bit more time for interfaces to settle before starting the - # relay agent processes. - # FIXME: Remove/decrease this once we determine how to prevent future race - # conditions here. - sleep 180 - # Start all DHCP relay agent(s) supervisorctl start isc-dhcp-relay:* fi diff --git a/dockers/docker-fpm-frr/bgpcfgd b/dockers/docker-fpm-frr/bgpcfgd index 120e07fcdb..4211f49d22 100755 --- a/dockers/docker-fpm-frr/bgpcfgd +++ b/dockers/docker-fpm-frr/bgpcfgd @@ -120,29 +120,23 @@ class Directory(object): self.data = defaultdict(dict) self.notify = defaultdict(lambda: defaultdict(list)) - def path_exist(self, slot, path): + def path_traverse(self, slot, path): if slot not in self.data: - return False + return False, None elif path == '': - return True + return True, self.data[slot] d = self.data[slot] for p in path.split("/"): if p not in d: - return False + return False, None d = d[p] - return True + return True, d + + def path_exist(self, slot, path): + return self.path_traverse(slot, path)[0] def get_path(self, slot, path): - if slot not in self.data: - return None - elif path == '': - return self.data[slot] - d = self.data[slot] - for p in path.split("/"): - if p not in d: - return None - d = d[p] - return d + return self.path_traverse(slot, path)[1] def put(self, slot, key, value): self.data[slot][key] = value @@ -289,6 +283,8 @@ class BGPPeerMgr(Manager): } def set_handler(self, key, data): + key = self.normalize_key(key) + vrf, nbr = key.split('|', 1) if key not in self.peers: cmd = None neigmeta = self.directory.get_slot("neigmeta") @@ -298,14 +294,14 @@ class BGPPeerMgr(Manager): cmd = self.templates["add"].render( DEVICE_METADATA=self.directory.get_slot("meta"), DEVICE_NEIGHBOR_METADATA=neigmeta, - neighbor_addr=key, + neighbor_addr=nbr, bgp_session=data ) except: syslog.syslog(syslog.LOG_ERR, 'Peer {}. Error in rendering the template for "SET" command {}'.format(key, data)) return True if cmd is not None: - rc = self.apply_op(cmd) + rc = self.apply_op(cmd, vrf) if rc: self.peers.add(key) syslog.syslog(syslog.LOG_INFO, 'Peer {} added with attributes {}'.format(key, data)) @@ -316,13 +312,13 @@ class BGPPeerMgr(Manager): # commands for the peers only if "admin_status" in data: if data['admin_status'] == 'up': - rc = self.apply_op(self.templates["no shutdown"].render(neighbor_addr=key)) + rc = self.apply_op(self.templates["no shutdown"].render(neighbor_addr=nbr), vrf) if rc: syslog.syslog(syslog.LOG_INFO, 'Peer {} admin state is set to "up"'.format(key)) else: syslog.syslog(syslog.LOG_ERR, "Peer {} admin state wasn't set to 'up'.".format(key)) elif data['admin_status'] == 'down': - rc = self.apply_op(self.templates["shutdown"].render(neighbor_addr=key)) + rc = self.apply_op(self.templates["shutdown"].render(neighbor_addr=nbr), vrf) if rc: syslog.syslog(syslog.LOG_INFO, 'Peer {} admin state is set to "down"'.format(key)) else: @@ -334,23 +330,28 @@ class BGPPeerMgr(Manager): return True def del_handler(self, key): + key = self.normalize_key(key) + vrf, nbr = key.split('|', 1) if key not in self.peers: syslog.syslog(syslog.LOG_WARNING, 'Peer {} has not been found'.format(key)) return - cmd = self.templates["delete"].render(neighbor_addr=key) - rc = self.apply_op(cmd) + cmd = self.templates["delete"].render(neighbor_addr=nbr) + rc = self.apply_op(cmd, vrf) if rc: syslog.syslog(syslog.LOG_INFO, 'Peer {} has been removed'.format(key)) self.peers.remove(key) else: syslog.syslog(syslog.LOG_ERR, "Peer {} hasn't been removed".format(key)) - def apply_op(self, cmd): + def apply_op(self, cmd, vrf): bgp_asn = self.directory.get_slot("meta")["localhost"]["bgp_asn"] fd, tmp_filename = tempfile.mkstemp(dir='/tmp') os.close(fd) with open(tmp_filename, 'w') as fp: - fp.write('router bgp %s\n' % bgp_asn) + if vrf == 'default': + fp.write('router bgp %s\n' % bgp_asn) + else: + fp.write('router bgp %s vrf %s\n' % (bgp_asn, vrf)) fp.write("%s\n" % cmd) command = ["vtysh", "-f", tmp_filename] @@ -358,14 +359,31 @@ class BGPPeerMgr(Manager): os.remove(tmp_filename) return rc == 0 + @staticmethod + def normalize_key(key): + if '|' not in key: + return 'default|' + key + else: + return key + @staticmethod def load_peers(): - peers = set() - command = ["vtysh", "-c", "show bgp neighbors json"] + vrfs = [] + command = ["vtysh", "-c", "show bgp vrfs json"] rc, out, err = run_command(command) if rc == 0: - js_bgp = json.loads(out) - peers = set(js_bgp.keys()) + js_vrf = json.loads(out) + vrfs = js_vrf['vrfs'].keys() + + peers = set() + for vrf in vrfs: + command = ["vtysh", "-c", 'show bgp vrf {} neighbors json'.format(vrf)] + rc, out, err = run_command(command) + if rc == 0: + js_bgp = json.loads(out) + for nbr in js_bgp.keys(): + peers.add((vrf, nbr)) + return peers diff --git a/dockers/docker-orchagent/Dockerfile.j2 b/dockers/docker-orchagent/Dockerfile.j2 index f01bca7240..8a66e2adbe 100755 --- a/dockers/docker-orchagent/Dockerfile.j2 +++ b/dockers/docker-orchagent/Dockerfile.j2 @@ -18,13 +18,6 @@ RUN apt-get update && \ iproute2 \ ndisc6 \ tcpdump \ - # Install redis-tools dependencies - # TODO: implicitly install dependencies - libatomic1 \ - libjemalloc1 \ - liblua5.1-0 \ - lua-bitop \ - lua-cjson \ libelf1 \ libmnl0 \ bridge-utils diff --git a/dockers/docker-sonic-telemetry/Dockerfile.j2 b/dockers/docker-sonic-telemetry/Dockerfile.j2 index 3a5716001c..e94441b4f0 100644 --- a/dockers/docker-sonic-telemetry/Dockerfile.j2 +++ b/dockers/docker-sonic-telemetry/Dockerfile.j2 @@ -11,14 +11,7 @@ RUN apt-get update && \ apt-get install -f -y \ libdbus-1-3 \ libdaemon0 \ - libjansson4 \ - # Install redis-tools dependencies - # TODO: implicitly install dependencies - libatomic1 \ - libjemalloc1 \ - liblua5.1-0 \ - lua-bitop \ - lua-cjson + libjansson4 {% if docker_sonic_telemetry_debs.strip() -%} # Copy locally-built Debian package dependencies diff --git a/dockers/docker-teamd/Dockerfile.j2 b/dockers/docker-teamd/Dockerfile.j2 index fc8626e772..4282a10d0c 100644 --- a/dockers/docker-teamd/Dockerfile.j2 +++ b/dockers/docker-teamd/Dockerfile.j2 @@ -12,14 +12,7 @@ RUN apt-get update && \ libdbus-1-3 \ libdaemon0 \ libjansson4 \ - libpython2.7 \ - # Install redis-tools dependencies - # TODO: implicitly install dependencies - libatomic1 \ - libjemalloc1 \ - liblua5.1-0 \ - lua-bitop \ - lua-cjson + libpython2.7 {% if docker_teamd_debs.strip() -%} # Copy locally-built Debian package dependencies diff --git a/files/build_templates/docker_image_ctl.j2 b/files/build_templates/docker_image_ctl.j2 index c485254647..167a392730 100644 --- a/files/build_templates/docker_image_ctl.j2 +++ b/files/build_templates/docker_image_ctl.j2 @@ -149,6 +149,11 @@ function postStartAction() sonic-cfggen -j /etc/sonic/config_db.json --write-to-db fi + if [[ "$BOOT_TYPE" == "fast" ]]; then + # set the key to expire in 3 minutes + redis-cli -n 6 SET "FAST_REBOOT|system" "1" "EX" "180" + fi + redis-cli -n 4 SET "CONFIG_DB_INITIALIZED" "1" fi diff --git a/files/build_templates/sflow.service.j2 b/files/build_templates/sflow.service.j2 index de08f027ad..643bf64696 100644 --- a/files/build_templates/sflow.service.j2 +++ b/files/build_templates/sflow.service.j2 @@ -1,6 +1,6 @@ [Unit] Description=sFlow container -Requires=swss.service +Requisite=swss.service After=swss.service syncd.service Before=ntp-config.service StartLimitIntervalSec=1200 diff --git a/files/build_templates/snmp.service.j2 b/files/build_templates/snmp.service.j2 index 310048e68b..4997ab737e 100644 --- a/files/build_templates/snmp.service.j2 +++ b/files/build_templates/snmp.service.j2 @@ -4,6 +4,7 @@ Requires=updategraph.service Requisite=swss.service After=updategraph.service swss.service syncd.service Before=ntp-config.service +Conflicts=snmp.timer StartLimitIntervalSec=1200 StartLimitBurst=3 @@ -14,5 +15,3 @@ ExecStop=/usr/bin/{{docker_container_name}}.sh stop Restart=always RestartSec=30 -[Install] -WantedBy=multi-user.target swss.service diff --git a/files/build_templates/snmp.timer b/files/build_templates/snmp.timer index 464cf01459..6d1838554d 100644 --- a/files/build_templates/snmp.timer +++ b/files/build_templates/snmp.timer @@ -1,9 +1,11 @@ [Unit] Description=Delays snmp container until SONiC has started +Conflicts=snmp.service [Timer] +OnUnitActiveSec=0 sec OnBootSec=3min 30 sec Unit=snmp.service [Install] -WantedBy=timers.target +WantedBy=timers.target swss.service diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2 index f62ef44f0f..0e6d07fb00 100644 --- a/files/build_templates/sonic_debian_extension.j2 +++ b/files/build_templates/sonic_debian_extension.j2 @@ -36,6 +36,8 @@ FILESYSTEM_ROOT_USR="$FILESYSTEM_ROOT/usr" FILESYSTEM_ROOT_USR_SHARE="$FILESYSTEM_ROOT_USR/share" FILESYSTEM_ROOT_USR_SHARE_SONIC="$FILESYSTEM_ROOT_USR_SHARE/sonic" FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES="$FILESYSTEM_ROOT_USR_SHARE_SONIC/templates" +FILESYSTEM_ROOT_ETC="$FILESYSTEM_ROOT/etc" +FILESYSTEM_ROOT_ETC_SONIC="$FILESYSTEM_ROOT_ETC/sonic" GENERATED_SERVICE_FILE="$FILESYSTEM_ROOT/etc/sonic/generated_services.conf" @@ -164,6 +166,14 @@ sudo sed -i -e '/^passwd/s/ tacplus//' $FILESYSTEM_ROOT/etc/nsswitch.conf sudo DEBIAN_FRONTEND=noninteractive dpkg --root=$FILESYSTEM_ROOT -i $debs_path/kdump-tools_*.deb || \ sudo LANG=C DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=truechroot $FILESYSTEM_ROOT apt-get -q --no-install-suggests --no-install-recommends --force-no install +# Install custom-built monit package and SONiC configuration files +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/monit_*.deb || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f +sudo cp $IMAGE_CONFIGS/monit/monitrc $FILESYSTEM_ROOT/etc/monit/ +sudo chmod 600 $FILESYSTEM_ROOT/etc/monit/monitrc +sudo cp $IMAGE_CONFIGS/monit/conf.d/* $FILESYSTEM_ROOT/etc/monit/conf.d/ +sudo chmod 600 $FILESYSTEM_ROOT/etc/monit/conf.d/* + # Copy crontabs sudo cp -f $IMAGE_CONFIGS/cron.d/* $FILESYSTEM_ROOT/etc/cron.d/ @@ -207,6 +217,16 @@ echo "hostcfgd.service" | sudo tee -a $GENERATED_SERVICE_FILE sudo cp $IMAGE_CONFIGS/hostcfgd/hostcfgd $FILESYSTEM_ROOT/usr/bin/ sudo cp $IMAGE_CONFIGS/hostcfgd/*.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ +# copy core file uploader files +sudo cp $IMAGE_CONFIGS/corefile_uploader/core_uploader.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo LANG=C chroot $FILESYSTEM_ROOT systemctl disable core_uploader.service +sudo cp $IMAGE_CONFIGS/corefile_uploader/core_uploader.py $FILESYSTEM_ROOT/usr/bin/ +sudo cp $IMAGE_CONFIGS/corefile_uploader/core_analyzer.rc.json $FILESYSTEM_ROOT_ETC_SONIC/ +sudo chmod og-rw $FILESYSTEM_ROOT_ETC_SONIC/core_analyzer.rc.json +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install azure-storage +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install watchdog +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install futures + # Copy the buffer configuration template sudo cp $BUILD_TEMPLATES/buffers_config.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ @@ -329,7 +349,7 @@ EOF ## Bind docker path if [[ $CONFIGURED_ARCH == armhf || $CONFIGURED_ARCH == arm64 ]]; then sudo mkdir -p $FILESYSTEM_ROOT/dockerfs - sudo mount --bind dockerfs $FILESYSTEM_ROOT/dockerfs + sudo mount --bind dockerfs $FILESYSTEM_ROOT/dockerfs fi {% if installer_images.strip() -%} @@ -346,7 +366,7 @@ sudo LANG=C chroot $FILESYSTEM_ROOT docker $SONIC_NATIVE_DOCKERD_FOR_DOCKERFS ta {% endif %} {% endfor %} if [[ $CONFIGURED_ARCH == armhf || $CONFIGURED_ARCH == arm64 ]]; then - sudo umount $FILESYSTEM_ROOT/dockerfs + sudo umount $FILESYSTEM_ROOT/dockerfs sudo rm -fr $FILESYSTEM_ROOT/dockerfs sudo kill -9 `sudo $SONIC_NATIVE_DOCKERD_FOR_DOCKERFS_PID` || true else @@ -374,6 +394,10 @@ sudo LANG=C cp $SCRIPTS_DIR/syncd.sh $FILESYSTEM_ROOT/usr/local/bin/syncd.sh # It implements delayed start of services sudo cp $BUILD_TEMPLATES/snmp.timer $FILESYSTEM_ROOT/etc/systemd/system/ sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable snmp.timer +{% if enable_system_telemetry == 'y' %} +sudo cp $BUILD_TEMPLATES/telemetry.timer $FILESYSTEM_ROOT/etc/systemd/system/ +sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable telemetry.timer +{% endif %} sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get purge -y python-dev sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get clean -y diff --git a/files/build_templates/telemetry.service.j2 b/files/build_templates/telemetry.service.j2 index 98ae2871bf..43fa039156 100644 --- a/files/build_templates/telemetry.service.j2 +++ b/files/build_templates/telemetry.service.j2 @@ -14,5 +14,3 @@ ExecStop=/usr/bin/{{docker_container_name}}.sh stop Restart=always RestartSec=30 -[Install] -WantedBy=multi-user.target diff --git a/files/build_templates/telemetry.timer b/files/build_templates/telemetry.timer new file mode 100644 index 0000000000..e08f1c09ea --- /dev/null +++ b/files/build_templates/telemetry.timer @@ -0,0 +1,9 @@ +[Unit] +Description=Delays telemetry container until SONiC has started + +[Timer] +OnBootSec=3min 30 sec +Unit=telemetry.service + +[Install] +WantedBy=timers.target diff --git a/files/image_config/caclmgrd/caclmgrd b/files/image_config/caclmgrd/caclmgrd index 5e8d83074d..6226bb1676 100755 --- a/files/image_config/caclmgrd/caclmgrd +++ b/files/image_config/caclmgrd/caclmgrd @@ -194,13 +194,14 @@ class ControlPlaneAclManager(object): continue # If we haven't determined the IP version for this ACL table yet, - # try to do it now. We determine heuristically based on whether the - # src IP is an IPv4 or IPv6 address. - if not table_ip_version and "SRC_IP" in rule_props and rule_props["SRC_IP"]: - ip_addr = ipaddress.IPAddress(rule_props["SRC_IP"].split("/")[0]) - if isinstance(ip_addr, ipaddress.IPv6Address): + # try to do it now. We attempt to determine heuristically based on + # whether the src or dst IP of this rule is an IPv4 or IPv6 address. + if not table_ip_version: + if (("SRC_IPV6" in rule_props and rule_props["SRC_IPV6"]) or + ("DST_IPV6" in rule_props and rule_props["DST_IPV6"])): table_ip_version = 6 - elif isinstance(ip_addr, ipaddress.IPv4Address): + elif (("SRC_IP" in rule_props and rule_props["SRC_IP"]) or + ("DST_IP" in rule_props and rule_props["DST_IP"])): table_ip_version = 4 # If we were unable to determine whether this ACL table contains diff --git a/files/image_config/corefile_uploader/core_analyzer.rc.json b/files/image_config/corefile_uploader/core_analyzer.rc.json new file mode 100644 index 0000000000..3ffa33fd1e --- /dev/null +++ b/files/image_config/corefile_uploader/core_analyzer.rc.json @@ -0,0 +1,17 @@ +{ + "local_work": { + "core_upload": "/tmp/core_upload/" + }, + "azure_sonic_core_storage": { + "account_name": "corefilecollection", + "account_key": "", + "share_name": "corefiles-root" + }, + "metadata_files_in_archive": { + "version": "/etc/sonic/sonic_version.yml", + "core_info": "core_info.json" + }, + "env": { + "https_proxy": "" + } +} diff --git a/files/image_config/corefile_uploader/core_uploader.py b/files/image_config/corefile_uploader/core_uploader.py new file mode 100755 index 0000000000..2ae91ce089 --- /dev/null +++ b/files/image_config/corefile_uploader/core_uploader.py @@ -0,0 +1,285 @@ +#!/usr/bin/env python + +import os +import time +import tarfile +import socket +import yaml +import json +import syslog +from watchdog.observers import Observer +from watchdog.events import FileSystemEventHandler +from azure.storage.file import FileService + +global CORE_FILE_PATH, RC_FILE +global hostname, sonicversion, asicname, acctname, acctkey, sharename, cwd +global INIT_CWD +global log_level +global this_file + +this_file = os.path.basename(__file__) + +global cfg +cfg = "" + +CORE_FILE_PATH = "/var/core/" +RC_FILE = "/etc/sonic/core_analyzer.rc.json" +INIT_CWD = "/tmp" + +hostname = "" +sonicversion = "" +asicname = "" +acctname = "" +acctkey = "" +sharename = "" +cwd = [] + +HOURS_4 = (4 * 60 * 60) +PAUSE_ON_FAIL = (60 * 60) +WAIT_FILE_WRITE1 = (10 * 60) +WAIT_FILE_WRITE2= (5 * 60) +POLL_SLEEP = (60 * 60) +MAX_RETRIES = 5 +UPLOAD_PREFIX = "UPLOADED_" + +log_level = syslog.LOG_DEBUG + +def log_msg(lvl, fname, m): + if (lvl <= log_level): + syslog.syslog(lvl, "{}: {}".format(fname, m)) + + if log_level == syslog.LOG_DEBUG: + print("{}: {}".format(fname, m)) + +def log_err(m): + log_msg(syslog.LOG_ERR, this_file, m) + +def log_info(m): + log_msg(syslog.LOG_INFO, this_file, m) + +def log_warn(m): + log_msg(syslog.LOG_WARNING, this_file, m) + +def log_debug(m): + log_msg(syslog.LOG_DEBUG, this_file, m) + + +def make_new_dir(p): + os.system("rm -rf " + p) + os.system("mkdir -p " + p) + +def parse_a_json(data, prefix, val): + for i in data: + if type(data[i]) == dict: + parse_a_json(data[i], prefix + (i,), val) + else: + val[prefix + (i,)] = data[i] + +class config: + parsed_data = {} + cfg_data = {} + + def __init__(self): + while not os.path.exists(RC_FILE): + # Wait here until service restart + log_err("Unable to retrieve Azure storage credentials") + time.sleep (HOURS_4) + + with open(RC_FILE, 'r') as f: + self.parsed_data = json.load(f) + parse_a_json(self.parsed_data, (), self.cfg_data) + + def get_data(self, k): + return self.cfg_data[k] if self.cfg_data.has_key(k) else "" + + def get_dict(self): + return self.parsed_data + + def get_core_info(self, corepath, devicename): + info = {} + info["corefname"] = os.path.basename(corepath) + info["tstamp"] = str(os.stat(corepath).st_ctime) + info["devicename"] = devicename + + lpath = self.get_data(("metadata_files_in_archive", "core_info")) + f = open(lpath, "w+") + f.write(json.dumps(info, indent=4)) + f.close() + + return lpath + + +class Watcher: + + def __init__(self): + self.observer = Observer() + + def run(self): + event_handler = Handler() + self.observer.schedule(event_handler, CORE_FILE_PATH) + self.observer.start() + try: + while True: + time.sleep(POLL_SLEEP) + except: + self.observer.stop() + log_err("Error in watcher") + + self.observer.join() + +def set_env(lst): + for k in lst: + if lst[k]: + os.environ[k] = lst[k] + log_debug("set env {} = {}".format(k, lst[k])) + +class Handler(FileSystemEventHandler): + + @staticmethod + def init(): + global hostname, sonicversion, asicname, acctname, acctkey, sharename + global cwd, cfg + + cfg = config() + + set_env(cfg.get_dict()["env"]) + + hostname = socket.gethostname() + if not hostname: + raise Exception("Failed to read hostname") + + acctname = cfg.get_data(("azure_sonic_core_storage", "account_name")) + acctkey = cfg.get_data(("azure_sonic_core_storage", "account_key")) + sharename = cfg.get_data(("azure_sonic_core_storage", "share_name")) + + if not acctname or not acctkey or not sharename: + while True: + # Wait here until service restart + log_err("Unable to retrieve Azure storage credentials") + time.sleep (HOURS_4) + + with open("/etc/sonic/sonic_version.yml", 'r') as stream: + l = yaml.safe_load(stream) + sonicversion = l['build_version'] + asicname = l['asic_type'] + + if not sonicversion: + raise Exception("Failed to read build_version from /etc/sonic/sonic_version.yml") + + if not asicname: + raise Exception("Failed to read asic_type from /etc/sonic/sonic_version.yml") + + cwd = cfg.get_data(("local_work", "core_upload")).split("/") + if not len(cwd) > 2: + raise Exception("Invalid path for core_upload. Expect a min of two elements in path") + + os.chdir(INIT_CWD) + + @staticmethod + def on_any_event(event): + if event.is_directory: + return None + + elif event.event_type == 'created': + # Take any action here when a file is first created. + log_debug("Received create event - " + event.src_path) + Handler.wait_for_file_write_complete(event.src_path) + Handler.handle_file(event.src_path) + + + @staticmethod + def wait_for_file_write_complete(path): + mtime = 0 + + # Sleep for ample time enough for file dump to complete. + time.sleep(WAIT_FILE_WRITE1) + + # Give another chance & poll until mtime stabilizes + while mtime != os.stat(path).st_mtime: + mtime = os.stat(path).st_mtime + time.sleep(10) + + # A safety pause for double confirmation + time.sleep(WAIT_FILE_WRITE2) + if mtime != os.stat(path).st_mtime: + raise Exception("Dump file creation is too slow: " + path) + # Give up as something is terribly wrong with this file. + + log_debug("File write complete - " + path) + + + @staticmethod + def handle_file(path): + lpath = "/".join(cwd) + make_new_dir(lpath) + os.chdir(lpath) + + # Create a new archive with core & more. + metafiles = cfg.get_dict()["metadata_files_in_archive"] + + fname = os.path.basename(path) + tarf_name = fname + ".tar.gz" + + cfg.get_core_info(path, hostname) + + tar = tarfile.open(tarf_name, "w:gz") + for e in metafiles: + tar.add(metafiles[e]) + tar.add(path) + tar.close() + log_debug("Tar file for upload created: " + tarf_name) + + Handler.upload_file(tarf_name, tarf_name, path) + + log_debug("File uploaded - " + path) + os.chdir(INIT_CWD) + + @staticmethod + def upload_file(fname, fpath, coref): + daemonname = fname.split(".")[0] + i = 0 + fail_msg = "" + + while True: + try: + svc = FileService(account_name=acctname, account_key=acctkey) + + l = [sonicversion, asicname, daemonname, hostname] + e = [] + while len(e) != len(l): + e.append(l[len(e)]) + svc.create_directory(sharename, "/".join(e)) + + log_debug("Remote dir created: " + "/".join(e)) + + svc.create_file_from_path(sharename, "/".join(l), fname, fpath) + log_debug("Remote file created: name{} path{}".format(fname, fpath)) + newcoref = os.path.dirname(coref) + "/" + UPLOAD_PREFIX + os.path.basename(coref) + os.rename(coref, newcoref) + break + + except Exception as ex: + log_err("core uploader failed: Failed during upload (" + coref + ") err: ("+ str(ex) +") retry:" + str(i)) + if not os.path.exists(fpath): + break + i += 1 + time.sleep(PAUSE_ON_FAIL) + + + @staticmethod + def scan(): + for e in os.listdir(CORE_FILE_PATH): + fl = CORE_FILE_PATH + e + if os.path.isfile(fl) and not e.startswith(UPLOAD_PREFIX): + Handler.handle_file(fl) + + +if __name__ == '__main__': + try: + Handler.init() + w = Watcher() + Handler.scan() + w.run() + except Exception as e: + log_err("core uploader failed: " + str(e) + " Exiting ...") + diff --git a/files/image_config/corefile_uploader/core_uploader.service b/files/image_config/corefile_uploader/core_uploader.service new file mode 100644 index 0000000000..09ac1bd519 --- /dev/null +++ b/files/image_config/corefile_uploader/core_uploader.service @@ -0,0 +1,13 @@ +[Unit] +Description=Host core file uploader daemon +Requires=syslog.service +After=syslog.service + +[Service] +Type=simple +ExecStart=/usr/bin/core_uploader.py +StandardOutput=null +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/hostcfgd/hostcfgd b/files/image_config/hostcfgd/hostcfgd index 7fa8ed2ba2..e10288c0dd 100755 --- a/files/image_config/hostcfgd/hostcfgd +++ b/files/image_config/hostcfgd/hostcfgd @@ -176,6 +176,11 @@ class AaaCfg(object): if modify_conf: self.modify_conf_file() + def modify_single_file(self, filename, operations=None): + if operations: + cmd = "sed -e {0} {1} > {1}.new; mv -f {1} {1}.old; mv -f {1}.new {1}".format(' -e '.join(operations), filename) + os.system(cmd) + def modify_conf_file(self): auth = self.auth_default.copy() auth.update(self.auth) @@ -201,19 +206,19 @@ class AaaCfg(object): # Modify common-auth include file in /etc/pam.d/login and sshd if os.path.isfile(PAM_AUTH_CONF): - os.system("sed -i -e '/^@include/s/common-auth$/common-auth-sonic/' /etc/pam.d/sshd") - os.system("sed -i -e '/^@include/s/common-auth$/common-auth-sonic/' /etc/pam.d/login") + self.modify_single_file('/etc/pam.d/sshd', [ "'/^@include/s/common-auth$/common-auth-sonic/'" ]) + self.modify_single_file('/etc/pam.d/login', [ "'/^@include/s/common-auth$/common-auth-sonic/'" ]) else: - os.system("sed -i -e '/^@include/s/common-auth-sonic$/common-auth/' /etc/pam.d/sshd") - os.system("sed -i -e '/^@include/s/common-auth-sonic$/common-auth/' /etc/pam.d/login") + self.modify_single_file('/etc/pam.d/sshd', [ "'/^@include/s/common-auth-sonic$/common-auth/'" ]) + self.modify_single_file('/etc/pam.d/login', [ "'/^@include/s/common-auth-sonic$/common-auth/'" ]) # Add tacplus in nsswitch.conf if TACACS+ enable if 'tacacs+' in auth['login']: if os.path.isfile(NSS_CONF): - os.system("sed -i -e '/tacplus/b' -e '/^passwd/s/compat/tacplus &/' /etc/nsswitch.conf") + self.modify_single_file(NSS_CONF, [ "'/tacplus/b'", "'/^passwd/s/compat/tacplus &/'"]) else: if os.path.isfile(NSS_CONF): - os.system("sed -i -e '/^passwd/s/tacplus //' /etc/nsswitch.conf") + self.modify_single_file(NSS_CONF, [ "'/^passwd/s/tacplus //'" ]) # Set tacacs+ server in nss-tacplus conf template_file = os.path.abspath(NSS_TACPLUS_CONF_TEMPLATE) diff --git a/files/image_config/monit/conf.d/sonic-host b/files/image_config/monit/conf.d/sonic-host new file mode 100644 index 0000000000..8eaa1671d8 --- /dev/null +++ b/files/image_config/monit/conf.d/sonic-host @@ -0,0 +1,22 @@ +############################################################################### +## Monit configuration for SONiC host OS +## +## This includes system-level monitoring as well as processes which +## run in the host OS (i.e., not inside a Docker container) +############################################################################### + +check filesystem root-overlay with path / + if space usage > 90% for 5 times within 10 cycles then alert + +check filesystem var-log with path /var/log + if space usage > 90% for 5 times within 10 cycles then alert + +check system $HOST + if memory usage > 90% for 5 times within 10 cycles then alert + if cpu usage (user) > 90% for 5 times within 10 cycles then alert + if cpu usage (system) > 90% for 5 times within 10 cycles then alert + +check process rsyslog with pidfile /var/run/rsyslogd.pid + start program = "/bin/systemctl start rsyslog.service" + stop program = "/bin/systemctl stop rsyslog.service" + if totalmem > 800 MB for 5 times within 10 cycles then restart diff --git a/files/image_config/monit/monitrc b/files/image_config/monit/monitrc index f9350733fa..7864069e3a 100644 --- a/files/image_config/monit/monitrc +++ b/files/image_config/monit/monitrc @@ -24,8 +24,7 @@ ## Set syslog logging. If you want to log to a standalone log file instead, ## specify the full path to the log file # -# set logfile /var/log/monit.log -set logfile syslog + set logfile syslog # # ## Set the location of the Monit lock file which stores the process id of the @@ -153,8 +152,8 @@ set logfile syslog ## commands to a running Monit daemon. See the Monit Wiki if you want to ## enable SSL for the HTTP interface. # -set httpd unixsocket /var/run/monit.sock and - allow localhost # allow localhost to connect to the server and + set httpd unixsocket /var/run/monit.sock and + allow localhost # allow localhost to connect to the server # ############################################################################### ## Services @@ -294,15 +293,3 @@ set httpd unixsocket /var/run/monit.sock and include /etc/monit/conf.d/* include /etc/monit/conf-enabled/* # -check filesystem root-overlay with path / - if space usage > 90% for 5 times within 10 cycles then alert -check filesystem var-log with path /var/log - if space usage > 90% for 5 times within 10 cycles then alert -check system $HOST - if memory usage > 90% for 5 times within 10 cycles then alert - if cpu usage (user) > 90% for 5 times within 10 cycles then alert - if cpu usage (system) > 90% for 5 times within 10 cycles then alert -check process rsyslog with pidfile /var/run/rsyslogd.pid - start program = "/bin/systemctl start rsyslog.service" - stop program = "/bin/systemctl stop rsyslog.service" - if totalmem > 800 MB for 5 times within 10 cycles then restart diff --git a/files/image_config/process-reboot-cause/process-reboot-cause b/files/image_config/process-reboot-cause/process-reboot-cause index 49cfa75264..e5d228b4c6 100755 --- a/files/image_config/process-reboot-cause/process-reboot-cause +++ b/files/image_config/process-reboot-cause/process-reboot-cause @@ -11,6 +11,7 @@ try: import pwd import sys import syslog + import re except ImportError as err: raise ImportError("%s - required module not found" % str(err)) @@ -22,6 +23,16 @@ REBOOT_CAUSE_DIR = "/host/reboot-cause/" REBOOT_CAUSE_FILE = REBOOT_CAUSE_DIR + "reboot-cause.txt" PREVIOUS_REBOOT_CAUSE_FILE = REBOOT_CAUSE_DIR + "previous-reboot-cause.txt" FIRST_BOOT_PLATFORM_FILE = "/tmp/notify_firstboot_to_platform" +REBOOT_TYPE_KEXEC_FILE = "/proc/cmdline" +# The following SONIC_BOOT_TYPEs come from the warm/fast reboot script which is in sonic-utilities +# Because the system can be rebooted from some old versions, we have to take all possible BOOT options into consideration. +# On 201803, 201807 we have +# BOOT_OPTIONS="$(echo $KERNEL_OPTIONS | sed -e 's/\s*linux\s*/BOOT_IMAGE=/') fast-reboot" +# On 201811 and later we have +# BOOT_OPTIONS="$(echo $KERNEL_OPTIONS | sed -e 's/\s*linux\s*/BOOT_IMAGE=/') SONIC_BOOT_TYPE=${BOOT_TYPE_ARG}" where BOOT_TYPE_ARG can be warm, fastfast or fast +# To extract the commom part of them, we should have the following PATTERN +REBOOT_TYPE_KEXEC_PATTERN_WARM = ".*SONIC_BOOT_TYPE=(warm|fastfast).*" +REBOOT_TYPE_KEXEC_PATTERN_FAST = ".*SONIC_BOOT_TYPE=(fast|fast-reboot).*" UNKNOWN_REBOOT_CAUSE = "Unknown" @@ -47,7 +58,32 @@ def log_error(msg): # ============================= Functions ============================= +def parse_warmfast_reboot_from_proc_cmdline(): + if os.path.isfile(REBOOT_TYPE_KEXEC_FILE): + with open(REBOOT_TYPE_KEXEC_FILE, "r") as cause_file: + cause_file_kexec = cause_file.readline() + m = re.match(REBOOT_TYPE_KEXEC_PATTERN_WARM, cause_file_kexec) + if m and m.group(1): + return 'warm-reboot' + m = re.match(REBOOT_TYPE_KEXEC_PATTERN_FAST, cause_file_kexec) + if m and m.group(1): + return 'fast-reboot' + return None + +def find_software_reboot_cause(): + software_reboot_cause = UNKNOWN_REBOOT_CAUSE + + if os.path.isfile(REBOOT_CAUSE_FILE): + with open(REBOOT_CAUSE_FILE, "r") as cause_file: + software_reboot_cause = cause_file.readline().rstrip('\n') + + if os.path.isfile(FIRST_BOOT_PLATFORM_FILE): + os.remove(FIRST_BOOT_PLATFORM_FILE) + + return software_reboot_cause + + def main(): log_info("Starting up...") @@ -73,51 +109,48 @@ def main(): try: import sonic_platform - # Check if the previous reboot was caused by hardware - platform = sonic_platform.platform.Platform() - - chassis = platform.get_chassis() - - hardware_reboot_cause, optional_details = chassis.get_reboot_cause() - - if hardware_reboot_cause == chassis.REBOOT_CAUSE_NON_HARDWARE: - # The reboot was not caused by hardware. If there is a REBOOT_CAUSE_FILE, it will - # contain any software-related reboot info. We will use it as the previous cause. + # 1. Check if the previous reboot was warm/fast reboot by testing whether there is "fast|fastfast|warm" in /proc/cmdline + # If yes, the content of /hosts/reboot-cause/reboot-cause.txt will be treated as the reboot cause + proc_cmdline_reboot_cause = parse_warmfast_reboot_from_proc_cmdline() + if proc_cmdline_reboot_cause: + log_info("/proc/cmdline indicates reboot type: {}".format(proc_cmdline_reboot_cause)) if os.path.isfile(REBOOT_CAUSE_FILE): - cause_file = open(REBOOT_CAUSE_FILE, "r") - previous_reboot_cause = cause_file.readline().rstrip('\n') - cause_file.close() - # If it is FirstTime Boot and previous_reboot_cause is unknown - # and hardware_reboot cause is non_hardware then - # Update the reboot cause as required - if os.path.isfile(FIRST_BOOT_PLATFORM_FILE): - if (previous_reboot_cause == UNKNOWN_REBOOT_CAUSE): - previous_reboot_cause = UNKNOWN_REBOOT_CAUSE - os.remove(FIRST_BOOT_PLATFORM_FILE) - elif hardware_reboot_cause == chassis.REBOOT_CAUSE_HARDWARE_OTHER: - previous_reboot_cause = "{} ({})".format(hardware_reboot_cause, optional_details) + with open(REBOOT_CAUSE_FILE, "r") as cause_file: + proc_cmdline_reboot_cause = cause_file.readline().rstrip('\n') + else: + # /proc/cmdline says it's a warm/fast reboot but /host/reboot-cause.txt doesn't exist. + # This could happen when upgrading from a version doesn't support reboot cause. + log_info("Reboot cause file {} doesn't exist".format(REBOOT_CAUSE_DIR)) + + if proc_cmdline_reboot_cause is not None: + previous_reboot_cause = proc_cmdline_reboot_cause else: - previous_reboot_cause = hardware_reboot_cause + # 2. Check if the previous reboot was caused by hardware + # If yes, the hardware reboot cause will be treated as the reboot cause + platform = sonic_platform.platform.Platform() + + chassis = platform.get_chassis() + + hardware_reboot_cause, optional_details = chassis.get_reboot_cause() + + if hardware_reboot_cause == chassis.REBOOT_CAUSE_NON_HARDWARE: + # The reboot was not caused by hardware. If there is a REBOOT_CAUSE_FILE, it will + # contain any software-related reboot info. We will use it as the previous cause. + previous_reboot_cause = find_software_reboot_cause() + elif hardware_reboot_cause == chassis.REBOOT_CAUSE_HARDWARE_OTHER: + previous_reboot_cause = "{} ({})".format(hardware_reboot_cause, optional_details) + else: + previous_reboot_cause = hardware_reboot_cause except ImportError as err: log_warning("sonic_platform package not installed. Unable to detect hardware reboot causes.") # If there is a REBOOT_CAUSE_FILE, it will contain any software-related # reboot info. We will use it as the previous cause. - if os.path.isfile(REBOOT_CAUSE_FILE): - cause_file = open(REBOOT_CAUSE_FILE, "r") - previous_reboot_cause = cause_file.readline().rstrip('\n') - cause_file.close() + previous_reboot_cause = find_software_reboot_cause() - # If it is FirstTime Boot and previous_reboot_cause is unknown - # Update the reboot cause as required - if os.path.isfile(FIRST_BOOT_PLATFORM_FILE): - if (previous_reboot_cause == UNKNOWN_REBOOT_CAUSE): - previous_reboot_cause = UNKNOWN_REBOOT_CAUSE - os.remove(FIRST_BOOT_PLATFORM_FILE) # Write the previous reboot cause to PREVIOUS_REBOOT_CAUSE_FILE - prev_cause_file = open(PREVIOUS_REBOOT_CAUSE_FILE, "w") - prev_cause_file.write(previous_reboot_cause) - prev_cause_file.close() + with open(PREVIOUS_REBOOT_CAUSE_FILE, "w") as prev_cause_file: + prev_cause_file.write(previous_reboot_cause) # Also log the previous reboot cause to the syslog log_info("Previous reboot cause: {}".format(previous_reboot_cause)) @@ -127,9 +160,8 @@ def main(): os.remove(REBOOT_CAUSE_FILE) # Write a new default reboot cause file for the next reboot - cause_file = open(REBOOT_CAUSE_FILE, "w") - cause_file.write(UNKNOWN_REBOOT_CAUSE) - cause_file.close() + with open(REBOOT_CAUSE_FILE, "w") as cause_file: + cause_file.write(UNKNOWN_REBOOT_CAUSE) if __name__ == "__main__": diff --git a/files/scripts/swss.sh b/files/scripts/swss.sh index 416075d8b3..93f311019d 100755 --- a/files/scripts/swss.sh +++ b/files/scripts/swss.sh @@ -85,9 +85,7 @@ start_peer_and_dependent_services() { if [[ x"$WARM_BOOT" != x"true" ]]; then /bin/systemctl start ${PEER} for dep in ${DEPENDENT}; do - # Here we call `systemctl restart` on each dependent service instead of `systemctl start` to - # ensure the services actually get stopped and started in case they were not previously stopped. - /bin/systemctl restart ${dep} + /bin/systemctl start ${dep} done fi } @@ -163,6 +161,13 @@ stop() { /usr/bin/${SERVICE}.sh stop debug "Stopped ${SERVICE} service..." + # Flush FAST_REBOOT table when swss needs to stop. The only + # time when this would take effect is when fast-reboot + # encountered error, e.g. syncd crashed. And swss needs to + # be restarted. + debug "Clearing FAST_REBOOT flag..." + clean_up_tables 6 "'FAST_REBOOT*'" + # Unlock has to happen before reaching out to peer service unlock_service_state_change diff --git a/files/scripts/syncd.sh b/files/scripts/syncd.sh index 2b7c76263d..05e5552a64 100755 --- a/files/scripts/syncd.sh +++ b/files/scripts/syncd.sh @@ -64,7 +64,12 @@ function getBootType() TYPE='fastfast' ;; *SONIC_BOOT_TYPE=fast*|*fast-reboot*) - TYPE=$(awk '{ if ($1 <= 180) print "fast"; else print "cold" }' /proc/uptime) + # check that the key exists + if [[ $(redis-cli -n 6 GET "FAST_REBOOT|system") == "1" ]]; then + TYPE='fast' + else + TYPE='cold' + fi ;; *) TYPE='cold' @@ -106,7 +111,6 @@ start() { /bin/systemctl stop pmon debug "pmon is active while syncd starting, stop it first" fi - /usr/bin/hw-management.sh chipdown fi if [[ x"$BOOT_TYPE" == x"fast" ]]; then 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/platform/mellanox/fw.mk b/platform/mellanox/fw.mk index 9d506c1f5b..eb1a58cfda 100644 --- a/platform/mellanox/fw.mk +++ b/platform/mellanox/fw.mk @@ -11,12 +11,12 @@ else FW_FROM_URL = n endif -MLNX_SPC_FW_VERSION = 13.2000.2602 +MLNX_SPC_FW_VERSION = 13.2000.2696 MLNX_SPC_FW_FILE = fw-SPC-rel-$(subst .,_,$(MLNX_SPC_FW_VERSION))-EVB.mfa $(MLNX_SPC_FW_FILE)_PATH = $(MLNX_FW_BASE_PATH) $(MLNX_SPC_FW_FILE)_URL = $(MLNX_FW_BASE_URL)/$(MLNX_SPC_FW_FILE) -MLNX_SPC2_FW_VERSION = 29.2000.2602 +MLNX_SPC2_FW_VERSION = 29.2000.2696 MLNX_SPC2_FW_FILE = fw-SPC2-rel-$(subst .,_,$(MLNX_SPC2_FW_VERSION))-EVB.mfa $(MLNX_SPC2_FW_FILE)_PATH = $(MLNX_FW_BASE_PATH) $(MLNX_SPC2_FW_FILE)_URL = $(MLNX_FW_BASE_URL)/$(MLNX_SPC2_FW_FILE) diff --git a/platform/mellanox/hw-management.mk b/platform/mellanox/hw-management.mk index f41c2b9a25..ff1ea20757 100644 --- a/platform/mellanox/hw-management.mk +++ b/platform/mellanox/hw-management.mk @@ -1,6 +1,6 @@ # Mellanox HW Management -MLNX_HW_MANAGEMENT_VERSION = 7.0000.2303 +MLNX_HW_MANAGEMENT_VERSION = 7.0000.2308 export MLNX_HW_MANAGEMENT_VERSION diff --git a/platform/mellanox/hw-management/hw-mgmt b/platform/mellanox/hw-management/hw-mgmt index 7c26a8f6a5..28d83cdb35 160000 --- a/platform/mellanox/hw-management/hw-mgmt +++ b/platform/mellanox/hw-management/hw-mgmt @@ -1 +1 @@ -Subproject commit 7c26a8f6a520b06663992afe874bc56b1fcd9311 +Subproject commit 28d83cdb3565d3b0352cc718fe82a14cacd1d4a5 diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py index 845f355e28..254d9c2e3e 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py @@ -136,6 +136,26 @@ SFP_CHANNL_MON_WIDTH = 6 SFP_CHANNL_STATUS_OFFSET = 110 SFP_CHANNL_STATUS_WIDTH = 1 +# identifier value of xSFP module which is in the first byte of the EEPROM +# if the identifier value falls into SFP_TYPE_CODE_LIST the module is treated as a SFP module and parsed according to 8472 +# for QSFP_TYPE_CODE_LIST the module is treated as a QSFP module and parsed according to 8436/8636 +# Originally the type (SFP/QSFP) of each module is determined according to the SKU dictionary +# where the type of each FP port is defined. The content of EEPROM is parsed according to its type. +# However, sometimes the SFP module can be fit in an adapter and then pluged into a QSFP port. +# In this case the EEPROM content is in format of SFP but parsed as QSFP, causing failure. +# To resolve that issue the type field of the xSFP module is also fetched so that we can know exectly what type the +# module is. Currently only the following types are recognized as SFP/QSFP module. +# Meanwhile, if the a module's identifier value can't be recognized, it will be parsed according to the SKU dictionary. +# This is because in the future it's possible that some new identifier value which is not regonized but backward compatible +# with the current format and by doing so it can be parsed as much as possible. +SFP_TYPE_CODE_LIST = [ + '03' # SFP/SFP+/SFP28 +] +QSFP_TYPE_CODE_LIST = [ + '0d', # QSFP+ or later + '11' # QSFP28 or later +] + qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', 'Length OM2(m)', 'Length OM1(m)', 'Length Cable Assembly(m)') @@ -206,7 +226,7 @@ class SFP(SfpBase): self.index = sfp_index + 1 self.sfp_eeprom_path = "qsfp{}".format(self.index) self.sfp_status_path = "qsfp{}_status".format(self.index) - self.sfp_type = sfp_type + self._detect_sfp_type(sfp_type) self.dom_tx_disable_supported = False self._dom_capability_detect() self.sdk_handle = None @@ -293,6 +313,26 @@ class SFP(SfpBase): return eeprom_raw + def _detect_sfp_type(self, sfp_type): + eeprom_raw = [] + eeprom_raw = self._read_eeprom_specific_bytes(XCVR_TYPE_OFFSET, XCVR_TYPE_WIDTH) + if eeprom_raw: + if eeprom_raw[0] in SFP_TYPE_CODE_LIST: + self.sfp_type = SFP_TYPE + elif eeprom_raw[0] in QSFP_TYPE_CODE_LIST: + self.sfp_type = QSFP_TYPE + else: + # we don't regonize this identifier value, treat the xSFP module as the default type + self.sfp_type = sfp_type + logger.log_info("Identifier value of {} module {} is {} which isn't regonized and will be treated as default type ({})".format( + sfp_type, self.index, eeprom_raw[0], sfp_type + )) + else: + # eeprom_raw being None indicates the module is not present. + # in this case we treat it as the default type according to the SKU + self.sfp_type = sfp_type + + def _dom_capability_detect(self): if not self.get_presence(): self.dom_supported = False @@ -303,7 +343,7 @@ class SFP(SfpBase): self.calibration = 0 return - if self.sfp_type == "QSFP": + if self.sfp_type == QSFP_TYPE: self.calibration = 1 sfpi_obj = sff8436InterfaceId() if sfpi_obj is None: @@ -348,7 +388,7 @@ class SFP(SfpBase): self.dom_tx_power_supported = False self.calibration = 0 self.qsfp_page3_available = False - elif self.sfp_type == "SFP": + elif self.sfp_type == SFP_TYPE: sfpi_obj = sff8472InterfaceId() if sfpi_obj is None: return None diff --git a/platform/mellanox/mlnx-sai/SAI-Implementation b/platform/mellanox/mlnx-sai/SAI-Implementation index 925116eb63..d878245e36 160000 --- a/platform/mellanox/mlnx-sai/SAI-Implementation +++ b/platform/mellanox/mlnx-sai/SAI-Implementation @@ -1 +1 @@ -Subproject commit 925116eb63a5a9012dcc22a7a0682ada6e976380 +Subproject commit d878245e364ce8d5edd08bbd7120c44c92362235 diff --git a/platform/mellanox/sdk-src/sx-kernel/Makefile b/platform/mellanox/sdk-src/sx-kernel/Makefile index 9e979879fe..422f2ae95a 100644 --- a/platform/mellanox/sdk-src/sx-kernel/Makefile +++ b/platform/mellanox/sdk-src/sx-kernel/Makefile @@ -19,7 +19,6 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : fi # build - patch -p1 < ../sx_kernel_makefile_sonic_build.patch debuild -e KVERSION=$(KVERSION) -e KSRC_EXT=/lib/modules/$(KVERSION)/source/ -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) diff --git a/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers b/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers index 87f7a79112..c08b5bb381 160000 --- a/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers +++ b/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers @@ -1 +1 @@ -Subproject commit 87f7a7911275285abc63c24ba39aa4af4c4b4678 +Subproject commit c08b5bb3810fe7da2811622aa7003ac9cc95344b diff --git a/platform/mellanox/sdk-src/sx-kernel/sx_kernel_makefile_sonic_build.patch b/platform/mellanox/sdk-src/sx-kernel/sx_kernel_makefile_sonic_build.patch deleted file mode 100644 index e7c87d0799..0000000000 --- a/platform/mellanox/sdk-src/sx-kernel/sx_kernel_makefile_sonic_build.patch +++ /dev/null @@ -1,18 +0,0 @@ -diff --git a/makefile b/makefile -index f23f0ac..a16b2ce 100644 ---- a/makefile -+++ b/makefile -@@ -93,10 +93,10 @@ V ?= 1 - - ifneq ($(findstring 3.10,$(KVERSION))$(findstring 3.13,$(KVERSION))$(findstring 3.14,$(KVERSION))$(findstring 3.16,$(KVERSION)),) - MLNX_LINUX_AUTOCONF_FILE = include/generated/autoconf.h --MLNX_LINUX_EXTRA_INCLUDE_FILES = -include include/linux/kconfig.h -+MLNX_LINUX_EXTRA_INCLUDE_FILES = -include $(KSRC_EXT)/include/linux/kconfig.h - MLNX_LINUX_EXTRA_INCLUDE_FOLDERS = \ -- -Iarch/$$(SRCARCH)/include/uapi \ -- -Iinclude/uapi \ -+ -I$(KSRC_EXT)/arch/$$(SRCARCH)/include/uapi \ -+ -I$(KSRC_EXT)/include/uapi \ - -Iarch/$$(SRCARCH)/include/generated/uapi \ - -Iarch/$$(SRCARCH)/include/generated \ - -Iinclude/generated/uapi diff --git a/platform/mellanox/sdk.mk b/platform/mellanox/sdk.mk index 73568ce845..55a5b08bba 100644 --- a/platform/mellanox/sdk.mk +++ b/platform/mellanox/sdk.mk @@ -1,5 +1,5 @@ MLNX_SDK_BASE_PATH = $(PLATFORM_PATH)/sdk-src/sx-kernel/Switch-SDK-drivers/bin/ -MLNX_SDK_VERSION = 4.3.2602 +MLNX_SDK_VERSION = 4.3.2904 MLNX_SDK_ISSU_VERSION = 101 MLNX_SDK_DEB_VERSION = $(subst _,.,$(MLNX_SDK_VERSION)) diff --git a/rules/docker-base-stretch.mk b/rules/docker-base-stretch.mk index 55b7fd9f86..a54f4ec092 100644 --- a/rules/docker-base-stretch.mk +++ b/rules/docker-base-stretch.mk @@ -2,7 +2,7 @@ DOCKER_BASE_STRETCH = docker-base-stretch.gz $(DOCKER_BASE_STRETCH)_PATH = $(DOCKERS_PATH)/docker-base-stretch -$(DOCKER_BASE_STRETCH)_DEPENDS += $(SUPERVISOR) +$(DOCKER_BASE_STRETCH)_DEPENDS += $(SUPERVISOR) $(REDIS_TOOLS) $(DOCKER_BASE_STRETCH)_DEPENDS += $(SOCAT) GDB = gdb diff --git a/rules/monit.mk b/rules/monit.mk new file mode 100644 index 0000000000..d4c73453e4 --- /dev/null +++ b/rules/monit.mk @@ -0,0 +1,14 @@ +# monit package + +MONIT_VERSION = 5.20.0-6 + +export MONIT_VERSION + +MONIT = monit_$(MONIT_VERSION)_$(CONFIGURED_ARCH).deb +$(MONIT)_SRC_PATH = $(SRC_PATH)/monit +SONIC_MAKE_DEBS += $(MONIT) + +SONIC_STRETCH_DEBS += $(MONIT) + +MONIT_DBG = monit-dbgsym_$(MONIT_VERSION)_$(CONFIGURED_ARCH).deb +$(eval $(call add_derived_package,$(MONIT),$(MONIT_DBG))) diff --git a/slave.mk b/slave.mk index f81895f74d..147b2a95a7 100644 --- a/slave.mk +++ b/slave.mk @@ -616,7 +616,8 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \ $(IFUPDOWN2) \ $(KDUMP_TOOLS) \ $(LIBPAM_TACPLUS) \ - $(LIBNSS_TACPLUS)) \ + $(LIBNSS_TACPLUS) \ + $(MONIT)) \ $$(addprefix $(TARGET_PATH)/,$$($$*_DOCKERS)) \ $$(addprefix $(FILES_PATH)/,$$($$*_FILES)) \ $(addprefix $(STRETCH_FILES_PATH)/, $(if $(filter $(CONFIGURED_ARCH),amd64), $(IXGBE_DRIVER))) \ @@ -639,6 +640,7 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \ export sonic_asic_platform="$(patsubst %-$(CONFIGURED_ARCH),%,$(CONFIGURED_PLATFORM))" export enable_organization_extensions="$(ENABLE_ORGANIZATION_EXTENSIONS)" export enable_dhcp_graph_service="$(ENABLE_DHCP_GRAPH_SERVICE)" + export enable_system_telemetry="$(ENABLE_SYSTEM_TELEMETRY)" export shutdown_bgp_on_start="$(SHUTDOWN_BGP_ON_START)" export enable_pfcwd_on_start="$(ENABLE_PFCWD_ON_START)" export installer_debs="$(addprefix $(STRETCH_DEBS_PATH)/,$($*_INSTALLS))" 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 diff --git a/src/isc-dhcp/patch/0012-Don-t-skip-down-interfaces-when-discovering-interfac.patch b/src/isc-dhcp/patch/0012-Don-t-skip-down-interfaces-when-discovering-interfac.patch new file mode 100644 index 0000000000..f088b035ed --- /dev/null +++ b/src/isc-dhcp/patch/0012-Don-t-skip-down-interfaces-when-discovering-interfac.patch @@ -0,0 +1,32 @@ +From 06850e9beb2c50b5cc23fc94168acd9ae58d8ef8 Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Fri, 6 Dec 2019 05:53:09 +0000 +Subject: [PATCH] Don't skip down interfaces when discovering interfaces in + relay mode + +When discovering interfaces in relay mode, don't skip interfaces just +because they're down. If we fail to discover the interfaces because they +are down when the relay starts, but then are brought up at a later point +in time, the relay will discard any packets received on them because it +didn't discover the interface(s) when it started up. +--- + common/discover.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/common/discover.c b/common/discover.c +index 8d5b958..5efff49 100644 +--- a/common/discover.c ++++ b/common/discover.c +@@ -1016,7 +1016,8 @@ discover_interfaces(int state) { + info.flags & IFF_LOOPBACK || + info.flags & IFF_POINTOPOINT) && !tmp) || + (!(info.flags & IFF_UP) && +- state != DISCOVER_UNCONFIGURED)) ++ state != DISCOVER_UNCONFIGURED && ++ state != DISCOVER_RELAY)) + continue; + + /* If there isn't already an interface by this name, +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/series b/src/isc-dhcp/patch/series index 1b83f2166b..ec68967e28 100644 --- a/src/isc-dhcp/patch/series +++ b/src/isc-dhcp/patch/series @@ -10,3 +10,4 @@ 0009-CVE-2018-5733.patch 0010-CVE-2018-5732.patch 0008-interface-name-maxlen-crash.patch +0012-Don-t-skip-down-interfaces-when-discovering-interfac.patch diff --git a/src/lldpd/patch/0004-lldpctl-put-a-lock-around-some-commands-to-avoid-rac.patch b/src/lldpd/patch/0004-lldpctl-put-a-lock-around-some-commands-to-avoid-rac.patch new file mode 100644 index 0000000000..df7f26131d --- /dev/null +++ b/src/lldpd/patch/0004-lldpctl-put-a-lock-around-some-commands-to-avoid-rac.patch @@ -0,0 +1,169 @@ +From 46aa45d0fa3e8879ecdca1c156cb2d91194c45e9 Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Thu, 12 Dec 2019 13:47:17 -0800 +Subject: [PATCH 1/1] lldpctl: put a lock around some commands to avoid race + conditions + +--- + src/client/client.h | 3 +++ + src/client/commands.c | 58 ++++++++++++++++++++++++++++++++++++++++--- + src/client/conf.c | 4 +-- + 3 files changed, 60 insertions(+), 5 deletions(-) + +diff --git a/src/client/client.h b/src/client/client.h +index e3ee352..6c3e30d 100644 +--- a/src/client/client.h ++++ b/src/client/client.h +@@ -62,6 +62,8 @@ extern void add_history (); + #endif + #undef NEWLINE + ++extern const char *ctlname; ++ + /* commands.c */ + #define NEWLINE "" + struct cmd_node; +@@ -76,6 +78,7 @@ struct cmd_node *commands_new( + struct cmd_env*, void *), + void *); + struct cmd_node* commands_privileged(struct cmd_node *); ++struct cmd_node* commands_lock(struct cmd_node *); + struct cmd_node* commands_hidden(struct cmd_node *); + void commands_free(struct cmd_node *); + const char *cmdenv_arg(struct cmd_env*); +diff --git a/src/client/commands.c b/src/client/commands.c +index beedbf1..58df4a7 100644 +--- a/src/client/commands.c ++++ b/src/client/commands.c +@@ -18,6 +18,9 @@ + #include "client.h" + #include + #include ++#include ++#include ++#include + + /** + * An element of the environment (a key and a value). +@@ -68,6 +71,7 @@ struct cmd_node { + const char *token; /**< Token to enter this cnode */ + const char *doc; /**< Documentation string */ + int privileged; /**< Privileged command? */ ++ int lock; /**< Lock required for execution? */ + int hidden; /**< Hidden command? */ + + /** +@@ -113,6 +117,21 @@ commands_privileged(struct cmd_node *node) + return node; + } + ++/** ++ * Make a node accessible only with a lock. ++ * ++ * @param node node to use lock to execute ++ * @return the modified node ++ * ++ * The node is modified. It is returned to ease chaining. ++ */ ++struct cmd_node* ++commands_lock(struct cmd_node *node) ++{ ++ if (node) node->lock = 1; ++ return node; ++} ++ + /** + * Hide a node from help or completion. + * +@@ -344,6 +363,7 @@ _commands_execute(struct lldpctl_conn_t *conn, struct writer *w, + int n, rc = 0, completion = (word != NULL); + int help = 0; /* Are we asking for help? */ + int complete = 0; /* Are we asking for possible completions? */ ++ int needlock = 0; /* Do we need a lock? */ + struct cmd_env env = { + .elements = TAILQ_HEAD_INITIALIZER(env.elements), + .stack = TAILQ_HEAD_INITIALIZER(env.stack), +@@ -351,6 +371,7 @@ _commands_execute(struct lldpctl_conn_t *conn, struct writer *w, + .argv = argv, + .argp = 0 + }; ++ static int lockfd = -1; + cmdenv_push(&env, root); + if (!completion) + for (n = 0; n < argc; n++) +@@ -388,6 +409,7 @@ _commands_execute(struct lldpctl_conn_t *conn, struct writer *w, + !strcmp(candidate->token, token)) { + /* Exact match */ + best = candidate; ++ needlock = needlock || candidate->lock; + break; + } + if (!best) best = candidate; +@@ -406,6 +428,7 @@ _commands_execute(struct lldpctl_conn_t *conn, struct writer *w, + if (!candidate->token && + CAN_EXECUTE(candidate)) { + best = candidate; ++ needlock = needlock || candidate->lock; + break; + } + } +@@ -421,9 +444,38 @@ _commands_execute(struct lldpctl_conn_t *conn, struct writer *w, + + /* Push and execute */ + cmdenv_push(&env, best); +- if (best->execute && best->execute(conn, w, &env, best->arg) != 1) { +- rc = -1; +- goto end; ++ if (best->execute) { ++ struct sockaddr_un su; ++ if (needlock) { ++ if (lockfd == -1) { ++ log_debug("lldpctl", "reopen %s for locking", ctlname); ++ if ((lockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) { ++ log_warn("lldpctl", "cannot open for lock %s", ctlname); ++ rc = -1; ++ goto end; ++ } ++ su.sun_family = AF_UNIX; ++ strlcpy(su.sun_path, ctlname, sizeof(su.sun_path)); ++ if (connect(lockfd, (struct sockaddr *)&su, sizeof(struct sockaddr_un)) == -1) { ++ log_warn("lldpctl", "cannot connect to socket %s", ctlname); ++ rc = -1; ++ close(lockfd); lockfd = -1; ++ goto end; ++ } ++ } ++ if (lockf(lockfd, F_LOCK, 0) == -1) { ++ log_warn("lldpctl", "cannot get lock on %s", ctlname); ++ rc = -1; ++ close(lockfd); lockfd = -1; ++ goto end; ++ } ++ } ++ rc = best->execute(conn, w, &env, best->arg) != 1 ? -1 : rc; ++ if (needlock && lockf(lockfd, F_ULOCK, 0) == -1) { ++ log_warn("lldpctl", "cannot unlock %s", ctlname); ++ close(lockfd); lockfd = -1; ++ } ++ if (rc == -1) goto end; + } + env.argp++; + } +diff --git a/src/client/conf.c b/src/client/conf.c +index 1a14981..ba5743f 100644 +--- a/src/client/conf.c ++++ b/src/client/conf.c +@@ -37,8 +37,8 @@ register_commands_configure(struct cmd_node *root) + "unconfigure", + "Unconfigure system settings", + NULL, NULL, NULL); +- commands_privileged(configure); +- commands_privileged(unconfigure); ++ commands_privileged(commands_lock(configure)); ++ commands_privileged(commands_lock(unconfigure)); + cmd_restrict_ports(configure); + cmd_restrict_ports(unconfigure); + +-- +2.17.1.windows.2 + diff --git a/src/lldpd/patch/0005-Read-all-notifications-in-lldpctl_recv.patch b/src/lldpd/patch/0005-Read-all-notifications-in-lldpctl_recv.patch new file mode 100644 index 0000000000..1c3781da67 --- /dev/null +++ b/src/lldpd/patch/0005-Read-all-notifications-in-lldpctl_recv.patch @@ -0,0 +1,27 @@ +From b8e66b52f40103fd3abea77031c4634742c31860 Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Thu, 12 Dec 2019 12:47:42 -0800 +Subject: [PATCH 1/1] Read all notifications in lldpctl_recv + +--- + src/lib/connection.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/lib/connection.c b/src/lib/connection.c +index 591d9e9..88bbc99 100644 +--- a/src/lib/connection.c ++++ b/src/lib/connection.c +@@ -253,8 +253,8 @@ lldpctl_recv(lldpctl_conn_t *conn, const uint8_t *data, size_t length) + memcpy(conn->input_buffer + conn->input_buffer_len, data, length); + conn->input_buffer_len += length; + +- /* Is it a notification? */ +- check_for_notification(conn); ++ /* Read all notifications */ ++ while(!check_for_notification(conn)); + + RESET_ERROR(conn); + +-- +2.17.1.windows.2 + diff --git a/src/lldpd/patch/0006-lib-fix-memory-leak.patch b/src/lldpd/patch/0006-lib-fix-memory-leak.patch new file mode 100644 index 0000000000..765b5fb751 --- /dev/null +++ b/src/lldpd/patch/0006-lib-fix-memory-leak.patch @@ -0,0 +1,24 @@ +From 833653dffb9be40110142af2a7cb4076a0dd24f5 Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Thu, 12 Dec 2019 12:48:47 -0800 +Subject: [PATCH 1/1] lib: fix memory leak + +--- + src/lib/connection.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/lib/connection.c b/src/lib/connection.c +index 88bbc99..aa88dad 100644 +--- a/src/lib/connection.c ++++ b/src/lib/connection.c +@@ -114,6 +114,7 @@ lldpctl_new_name(const char *ctlname, lldpctl_send_callback send, lldpctl_recv_c + } + if (!send && !recv) { + if ((data = malloc(sizeof(struct lldpctl_conn_sync_t))) == NULL) { ++ free(conn->ctlname); + free(conn); + return NULL; + } +-- +2.17.1.windows.2 + diff --git a/src/lldpd/patch/0007-lib-fix-memory-leak-when-handling-I-O.patch b/src/lldpd/patch/0007-lib-fix-memory-leak-when-handling-I-O.patch new file mode 100644 index 0000000000..cad8bf2fd4 --- /dev/null +++ b/src/lldpd/patch/0007-lib-fix-memory-leak-when-handling-I-O.patch @@ -0,0 +1,85 @@ +From f6086575e63b5e089814ca116aa637d7588bfcd3 Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Thu, 12 Dec 2019 13:52:42 -0800 +Subject: [PATCH 1/1] lib: fix memory leak when handling I/O. + +--- + src/lib/atom.c | 11 ++++++----- + src/lib/atom.h | 9 ++++----- + src/lib/atoms/port.c | 2 +- + 3 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/src/lib/atom.c b/src/lib/atom.c +index 955f434..f81d3bb 100644 +--- a/src/lib/atom.c ++++ b/src/lib/atom.c +@@ -322,10 +322,12 @@ _lldpctl_do_something(lldpctl_conn_t *conn, + return SET_ERROR(conn, LLDPCTL_ERR_SERIALIZATION); + conn->state = state_send; + if (state_data) +- conn->state_data = strdup(state_data); ++ strlcpy(conn->state_data, state_data, sizeof(conn->state_data)); ++ else ++ conn->state_data[0] = 0; + } + if (conn->state == state_send && +- (state_data == NULL || !strcmp(conn->state_data, state_data))) { ++ (state_data == NULL || !strncmp(conn->state_data, state_data, sizeof(conn->state_data)))) { + /* We need to send the currently built message */ + rc = lldpctl_send(conn); + if (rc < 0) +@@ -333,7 +335,7 @@ _lldpctl_do_something(lldpctl_conn_t *conn, + conn->state = state_recv; + } + if (conn->state == state_recv && +- (state_data == NULL || !strcmp(conn->state_data, state_data))) { ++ (state_data == NULL || !strncmp(conn->state_data, state_data, sizeof(conn->state_data)))) { + /* We need to receive the answer */ + while ((rc = ctl_msg_recv_unserialized(&conn->input_buffer, + &conn->input_buffer_len, +@@ -347,8 +349,7 @@ _lldpctl_do_something(lldpctl_conn_t *conn, + return SET_ERROR(conn, LLDPCTL_ERR_SERIALIZATION); + /* rc == 0 */ + conn->state = CONN_STATE_IDLE; +- free(conn->state_data); +- conn->state_data = NULL; ++ conn->state_data[0] = 0; + return 0; + } else + return SET_ERROR(conn, LLDPCTL_ERR_INVALID_STATE); +diff --git a/src/lib/atom.h b/src/lib/atom.h +index 265c0a7..ab7037d 100644 +--- a/src/lib/atom.h ++++ b/src/lib/atom.h +@@ -55,11 +55,10 @@ struct lldpctl_conn_t { + #define CONN_STATE_GET_DEFAULT_PORT_SEND 14 + #define CONN_STATE_GET_DEFAULT_PORT_RECV 15 + int state; /* Current state */ +- char *state_data; /* Data attached to the state. It is used to +- * check that we are using the same data as a +- * previous call until the state machine goes to +- * CONN_STATE_IDLE. */ +- ++ /* Data attached to the state. It is used to check that we are using the ++ * same data as a previous call until the state machine goes to ++ * CONN_STATE_IDLE. */ ++ char state_data[IFNAMSIZ + 64]; + /* Error handling */ + lldpctl_error_t error; /* Last error */ + +diff --git a/src/lib/atoms/port.c b/src/lib/atoms/port.c +index 545155c..d902188 100644 +--- a/src/lib/atoms/port.c ++++ b/src/lib/atoms/port.c +@@ -329,7 +329,7 @@ _lldpctl_atom_set_atom_port(lldpctl_atom_t *atom, lldpctl_key_t key, lldpctl_ato + struct lldpd_hardware *hardware = p->hardware; + struct lldpd_port_set set = {}; + int rc; +- char *canary; ++ char *canary = NULL; + + #ifdef ENABLE_DOT3 + struct _lldpctl_atom_dot3_power_t *dpow; +-- +2.17.1.windows.2 + diff --git a/src/lldpd/patch/series b/src/lldpd/patch/series index 5e5e8bc997..626c5d5975 100644 --- a/src/lldpd/patch/series +++ b/src/lldpd/patch/series @@ -2,3 +2,7 @@ 0001-return-error-when-port-does-not-exist.patch 0002-Let-linux-kernel-to-find-appropriate-nl_pid-automa.patch 0003-update-tx-interval-immediately.patch +0004-lldpctl-put-a-lock-around-some-commands-to-avoid-rac.patch +0005-Read-all-notifications-in-lldpctl_recv.patch +0006-lib-fix-memory-leak.patch +0007-lib-fix-memory-leak-when-handling-I-O.patch diff --git a/src/monit/Makefile b/src/monit/Makefile new file mode 100644 index 0000000000..4ad9edd791 --- /dev/null +++ b/src/monit/Makefile @@ -0,0 +1,33 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = monit_$(MONIT_VERSION)_$(CONFIGURED_ARCH).deb +DERIVED_TARGETS = monit-dbgsym_$(MONIT_VERSION)_$(CONFIGURED_ARCH).deb + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + # Remove any stale files + rm -rf ./monit + + # Clone monit repo + git clone https://salsa.debian.org/sk-guest/monit.git + pushd ./monit + + # Reset HEAD to the commit of the proper tag + # NOTE: Using "git checkout " here detaches our HEAD, + # which stg doesn't like, so we use this method instead + # NOTE: For some reason, tags in the Debian monit repo are prefixed with "1%" + git reset --hard debian/1\%$(MONIT_VERSION) + + # Apply patches + stg init + stg import -s ../patch/series + + # Build source and Debian packages + dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) + popd + + # Move the newly-built .deb packages to the destination directory + mv $(DERIVED_TARGETS) $* $(DEST)/ + +$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) diff --git a/src/monit/patch/0001-used_system_memory_sysdep-Use-MemAvailable-value-if-.patch b/src/monit/patch/0001-used_system_memory_sysdep-Use-MemAvailable-value-if-.patch new file mode 100644 index 0000000000..9c67d153cb --- /dev/null +++ b/src/monit/patch/0001-used_system_memory_sysdep-Use-MemAvailable-value-if-.patch @@ -0,0 +1,70 @@ +From c392362c9c1d57256b7e8ab7c77926824677fd73 Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Tue, 19 Nov 2019 01:51:13 +0000 +Subject: [PATCH] [used_system_memory_sysdep] Use 'MemAvailable' value if + available + +--- + src/process/sysdep_LINUX.c | 35 +++++++++++++++++++++++------------ + 1 file changed, 23 insertions(+), 12 deletions(-) + +diff --git a/src/process/sysdep_LINUX.c b/src/process/sysdep_LINUX.c +index 0d18f85..221e785 100644 +--- a/src/process/sysdep_LINUX.c ++++ b/src/process/sysdep_LINUX.c +@@ -335,6 +335,7 @@ int getloadavg_sysdep(double *loadv, int nelem) { + boolean_t used_system_memory_sysdep(SystemInfo_T *si) { + char *ptr; + char buf[2048]; ++ unsigned long mem_available = 0UL; + unsigned long mem_free = 0UL; + unsigned long buffers = 0UL; + unsigned long cached = 0UL; +@@ -343,22 +344,32 @@ boolean_t used_system_memory_sysdep(SystemInfo_T *si) { + unsigned long swap_free = 0UL; + + if (! file_readProc(buf, sizeof(buf), "meminfo", -1, NULL)) { +- LogError("system statistic error -- cannot get real memory free amount\n"); ++ LogError("system statistic error -- cannot read /proc/meminfo\n"); + goto error; + } + +- /* Memory */ +- if (! (ptr = strstr(buf, "MemFree:")) || sscanf(ptr + 8, "%ld", &mem_free) != 1) { +- LogError("system statistic error -- cannot get real memory free amount\n"); +- goto error; ++ /* ++ * Memory ++ * ++ * First, check if the "MemAvailable" value is available on this system. If it is, we will ++ * use it. Otherwise we will attempt to calculate the amount of available memory ourself. ++ */ ++ if ((ptr = strstr(buf, "MemAvailable:")) && sscanf(ptr + 13, "%ld", &mem_available) == 1) { ++ si->total_mem = systeminfo.mem_max - (uint64_t)mem_available * 1024; ++ } else { ++ DEBUG("'MemAvailable' value not available on this system. Attempting to calculate available memory manually...\n"); ++ if (! (ptr = strstr(buf, "MemFree:")) || sscanf(ptr + 8, "%ld", &mem_free) != 1) { ++ LogError("system statistic error -- cannot get real memory free amount\n"); ++ goto error; ++ } ++ if (! (ptr = strstr(buf, "Buffers:")) || sscanf(ptr + 8, "%ld", &buffers) != 1) ++ DEBUG("system statistic error -- cannot get real memory buffers amount\n"); ++ if (! (ptr = strstr(buf, "Cached:")) || sscanf(ptr + 7, "%ld", &cached) != 1) ++ DEBUG("system statistic error -- cannot get real memory cache amount\n"); ++ if (! (ptr = strstr(buf, "SReclaimable:")) || sscanf(ptr + 13, "%ld", &slabreclaimable) != 1) ++ DEBUG("system statistic error -- cannot get slab reclaimable memory amount\n"); ++ si->total_mem = systeminfo.mem_max - (uint64_t)(mem_free + buffers + cached + slabreclaimable) * 1024; + } +- if (! (ptr = strstr(buf, "Buffers:")) || sscanf(ptr + 8, "%ld", &buffers) != 1) +- DEBUG("system statistic error -- cannot get real memory buffers amount\n"); +- if (! (ptr = strstr(buf, "Cached:")) || sscanf(ptr + 7, "%ld", &cached) != 1) +- DEBUG("system statistic error -- cannot get real memory cache amount\n"); +- if (! (ptr = strstr(buf, "SReclaimable:")) || sscanf(ptr + 13, "%ld", &slabreclaimable) != 1) +- DEBUG("system statistic error -- cannot get slab reclaimable memory amount\n"); +- si->total_mem = systeminfo.mem_max - (uint64_t)(mem_free + buffers + cached + slabreclaimable) * 1024; + + /* Swap */ + if (! (ptr = strstr(buf, "SwapTotal:")) || sscanf(ptr + 10, "%ld", &swap_total) != 1) { +-- +2.17.1 + diff --git a/src/monit/patch/series b/src/monit/patch/series new file mode 100644 index 0000000000..15fcdd50c8 --- /dev/null +++ b/src/monit/patch/series @@ -0,0 +1,2 @@ +# This series applies on GIT commit dc9bc1c949125140d967edfc598dfad47eedc552 +0001-used_system_memory_sysdep-Use-MemAvailable-value-if-.patch diff --git a/src/sonic-linux-kernel b/src/sonic-linux-kernel index feb42b05eb..d5bc436a61 160000 --- a/src/sonic-linux-kernel +++ b/src/sonic-linux-kernel @@ -1 +1 @@ -Subproject commit feb42b05eb912ea64f0b4ce17f4bc890929eb57e +Subproject commit d5bc436a6179ec5ba985f66e96d2fb7864f0002d diff --git a/src/sonic-platform-common b/src/sonic-platform-common index d22f0a0e64..6ddd012d9a 160000 --- a/src/sonic-platform-common +++ b/src/sonic-platform-common @@ -1 +1 @@ -Subproject commit d22f0a0e64f30e9e26064824fb11f27b2d636850 +Subproject commit 6ddd012d9ab362254bd6a54372ee0ab679a7130e diff --git a/src/sonic-platform-daemons b/src/sonic-platform-daemons index a34ba131f6..e97f2ab26c 160000 --- a/src/sonic-platform-daemons +++ b/src/sonic-platform-daemons @@ -1 +1 @@ -Subproject commit a34ba131f618a8df6beec1f548aa08f9cedc48db +Subproject commit e97f2ab26c6cfc8e620cceddf94fe47646afe64c diff --git a/src/sonic-py-swsssdk b/src/sonic-py-swsssdk index 4cee385349..dd21b345d7 160000 --- a/src/sonic-py-swsssdk +++ b/src/sonic-py-swsssdk @@ -1 +1 @@ -Subproject commit 4cee38534919e34f407363ac3ab5f31b4d09be6d +Subproject commit dd21b345d71dae02c6309c8faca911b1e25bc7b7 diff --git a/src/sonic-quagga b/src/sonic-quagga index 904a350107..0fa66a0210 160000 --- a/src/sonic-quagga +++ b/src/sonic-quagga @@ -1 +1 @@ -Subproject commit 904a350107793d44be7167500fcec9087ca3243b +Subproject commit 0fa66a0210c081a1e6f3778f1ea59f1853a94e04 diff --git a/src/sonic-sairedis b/src/sonic-sairedis index 533749062f..792800607c 160000 --- a/src/sonic-sairedis +++ b/src/sonic-sairedis @@ -1 +1 @@ -Subproject commit 533749062f638f74ebc09c4bd0a5162b2c575564 +Subproject commit 792800607c0a987097d430d9f7fa9dce34361cfd diff --git a/src/sonic-swss b/src/sonic-swss index c3b8fe10b1..7b9661b2ae 160000 --- a/src/sonic-swss +++ b/src/sonic-swss @@ -1 +1 @@ -Subproject commit c3b8fe10b1568022fa025ef4be9cb063bfe49df4 +Subproject commit 7b9661b2aea0d9c3c770c421ca9963e2d742197f diff --git a/src/sonic-swss-common b/src/sonic-swss-common index a4a1e108af..8d6844984b 160000 --- a/src/sonic-swss-common +++ b/src/sonic-swss-common @@ -1 +1 @@ -Subproject commit a4a1e108afb3e75717e204da49a975681d964e8c +Subproject commit 8d6844984b6f02d389eb5f8d92e14f3e12e3f19c diff --git a/src/sonic-utilities b/src/sonic-utilities index 1898102cf2..72f0e77aa1 160000 --- a/src/sonic-utilities +++ b/src/sonic-utilities @@ -1 +1 @@ -Subproject commit 1898102cf2c399ebf2360c461297b0ac9fae98e4 +Subproject commit 72f0e77aa172a7096b49b661e84512785efee4e0