From 93905d3d825a23fd055dd5fc490172e27965a87c Mon Sep 17 00:00:00 2001 From: Sagar Balani Date: Tue, 24 Jul 2018 10:23:12 -0700 Subject: [PATCH] [barefoot]: Support for platforms based on Barefoot Networks' device (#1796) * Initial commit * Add Ingrasys S9180-32X platform dirver. Signed-off-by: Wade He * Add bfn.service for init barefoot. Signed-off-by: Wade He * [Barefoot Beta] Add some functions and fixed some bugs. 1. Update sensors.conf. 2. Fixed IO expander init. 3. Fixed PSU EEPROM. 4. Fixed MB EEPROM. 5. Add fancontrol and fan init. 6. Add SYS LED control (sys, fan, fan tray). 7. 2.5V compute and setup max and min. 8. Fixed typo MB eeprom delete address. 9. Remove coretemp to BMC. 10. Add active CPLD. 11. Modify SFP+ GPIO slave address. 12. Modify tmp75 Near Port 32 slave address. Signed-off-by: Wade He * Add bfn script in /etc/init.d/ Signed-off-by: Wade He * Add bfn service in debian Signed-off-by: Wade He * Fixed CPLD switch LED behavior. Signed-off-by: Wade He * [Barefoot Beta] Fixed sensors and hwmon order. 1. Fixed ignore sensors Vbat. 2. Reorg hwmon order. Signed-off-by: Wade He * Fixed PSU1 and PSU2 EEPROM order. Signed-off-by: Wade He * initial barefoot checkin october 2017 * update refpoint * update refpoints * update refpoints to bf-master * update refpoint * update refpoint to tested version * change to platform from asic * update refpoint for swss * revert core creation setting * update refpoints * add telnet for debug shell * update refpoints 11/17/17 * missed change in file on previous merge * [CPLD] Fixed blink LED issue. * Fixed blink LED mask set error. Signed-off-by: Wade He * Update bf_kdrv.c for 6.0.2.39 * Update bf kernel driver * Add bf_fun kernel module. * Update bf_tun for fixed build error * merge with Azure master (12/12/17) * update swss refpoint * update refpoint of swss * library dependency for stack unroll * update refpoint to bf-master * [DHCP relay]: Fix circuit ID and remote ID bugs (#1248) * [DHCP relay]: Fix circuit ID and remote ID bugs * Set circuit_id_len after setting circuit_id_len to ip->name * [Platform] Add Psuutil and update sensors.conf for S9100-32X, S8810-32Q and S9200-64X (#1272) * Add I2C CPLD kernel module for psuutil. * Support psuutil script. * Add voltage min and max threshold. * Update sensors.conf for tmp75. Signed-off-by: Wade He * Allow multi platform support - infra (more changes to follow) * update relative path to include platform for clarity * [Platform] Add Ingrasys S9130-32X and S9230-64X with Nephos Switch ASIC for "branch 201712" (#1274) - What I did Add switch ASIC vendor: Nephos Add Nephos platforms: Ingrasys S9130-32X, Ingrasys S9230-64X - How I did it Add platform/nephos files Add platform/nephos/sonic-platform-modules-ingrasys submodule Add device/ingrasys/x86_64-ingrasys_s9130_32x-r0 files Add device/ingrasys/x86_64-ingrasys_s9230_64x-r0 files Add SONiC to support Nephos platform Update Head of submodule src/sonic-sairedis to "3b817bb" - How to verify it To build SONiC installer image and docker images, run the following commands: make configure PLATFORM=nephos make target/sonic-nephos.bin Check system and network feature is worked as well - Description for the changelog Add switch ASIC vendor and platforms for Nephos - A picture of a cute animal (not mandatory but encouraged) Signed-off-by: Sam Yang * change source of files to github (from dropbox), update sairedis refpoint * update refpoint of sairedis * [centec] support CENTEC SAI 1.0 on 201712 branch and update e582-48x6q board (#1269) * [marvel]: Marvell's updates for SONiC.201712 & SAI v1.0 (#1287) * update sairedis (fast-boot refpoint) * fix syncd rpc make files * update refpoint to handle Makefile change (no functional change) * [Marvell]: Add support for SLM5401-54x device (#1307) * Marvell's updates for SONiC.201712 & SAI v1.0 * [Platform] Add Marvell's SLM5401-54x for branch 201712 * [Broadcom]: Update Boradcom SAI package to 3.0.3.3-3 (#1312) (#1321) - update Arista 7050-QX32S config.bcm file - update Accton th-as771*-32x100G.config.bcm files * update refpoint for Makefile chnage in sairedis * update refpoint - sairedis * update sairedis to older refpoint till we debug clean build * export asic platform for build * update refpoint for makefiles * [PLATFORM] Centec update E582 driver fan/epprom/sensor (#1332) * Upload wnc-osw1800 * Modify for Barefoot suggest * Revert bfn-platform.mk * Update bfn-platform-wnc.mk Update parameter name * Update parameter name * initial support for WNC platform * change switch name to "switch" * Delete bf modules for rel_7_0 * Add Ingrasys S9180 platform Signed-off-by: Wade He * Modify bfnsdk for Ingrasys S9180 platform Signed-off-by: Wade He * Resolved the conflict. * Resolved the conflict. * Update submodule path and url. * Delete unused file. * Update PSU GPIO and EEPROM for psuutil. * Add psuutil in S9180-32X Signed-off-by: Wade He * update refpoint * update refpoint * change contact email, update refpoint * cleanup and update kernel modules * updates based on review * update refpoint * update refpoint * fix typo in config script to check for platforms * remove stale file * resolve conflicts * cleanup diffs with Azure repo and update SDK debs * update refpoints to Azure * address review comments * revert refpoint of swss-common * porting the build fix from master * porting build fix from master * Minor Fix * Minor fix * Temp to sde deb packages url * Update sonic - sairedis,swss & swss-common refpoints * Update git modules url path to bfn repo * updated paths for swss, swss-common & sairedis * Update refpoint for sonic-swss to local bfn repo * Update URL for downloading sde debian packages * porting fix links of debian git server from master * porting fix links of debian git server from master * [Ingrasys] Add platform support for S9280-64X with Barefoot ASIC * Update ref points for swss, swss-common and sairedis repos * Add sonic platform scripts for bfn montara/maverick * Call sh scripts instead of calling py scripts * Address upstream PR Comments (#10) * Update bf-master with azure/master * Undo changes to some files * Revert "Address upstream PR Comments (#10)" This reverts commit a7fddb83ca1073f90fbe46955ba57a9b43742c73. * Address upstream comments (#11) * Remove all non bfn specific changes from upstream PR * Revert "Address upstream comments (#11)" This reverts commit 559132103e5c73e43f4282d1559ede03f16abfea. * Undo non bfn changes * Little more cleanup * Add back code removed in merge * export CONFIGURED_PLATFORM * Update sairedis and swss refpoints * Address Upstream PR comment * change deb pkg dependency from 3.16.0-4-amd64 to 3.16.0-5-amd64 * Set default tx queue len for usb0 interface to 64 * Update sairedis refpoint * Update swss ref point * Add bfn buffer cfg files for montara/maverick as per new design * Update buffer cfg templates for bfn montara * add non zero size to buffer profile * add macro to generate port lists * Update buffer cfg templates for bfn mavericks * add non zero size for buffer profiles * add port generation macro * Add missing psmisc package * BGP docker seems to be missing killall utility being used by fast-reboot script. This is causing non graceful termination of BGP sessions. Adding psmisc to resolve this issue. * Update swss ref point * Update swss ref point * Update sairedis refpoint * Update sairedis refpoint * Update sairedis refpoint * Update sairedis refpoint * Update refpoint for sairedis and swss * sairedis to azure master * swss to latest bfn bf-master * Update gitmodules Update url for sairedis to azure master * Correct typo in bfn platform script * Update swss and sairedis ref points * Update swss ref point * Address Review comments * Update swws path in gitmodules to azure master * update swss refpoint * update base docker j2 file -remove psmisc package (could be a concern, would cause fast reboot to not work correctly will fix in another PR) * Fix sairedis refpoint broken in by previous merge * Remove psmisc from docker base image * This will break fast reboot as killall is required for killing bgp process and initiating graceful termination of BGP session. Will fix this in a seperate PR. Need this for SONIC upstreaming * Address upstream comments * Remove bmc interface from interface jinja template and sample output interfaces file * Add bmc interface at boot time to network interfaces for bfn bmc based platforms * Remove autogen ingrasys debian files * Revert "Remove autogen ingrasys debian files" * Buffer and qos config template fix for bfn platforms (#21) SWI-1509 Buffer and qos config template fix for bfn platforms * Fix qos config files for montara & mavericks (#22) * Reference only ppg 3,4 in qos files as no profiles are attached to 0,1 in buffer configs * Fix vs test (#23) --- .../installer.conf | 1 + .../minigraph.xml | 1079 ++++++++ .../montara/buffers.json.j2 | 2 + .../montara/buffers_defaults_t0.j2 | 83 + .../montara/buffers_defaults_t1.j2 | 83 + .../montara/pg_profile_lookup.ini | 17 + .../montara/port_config.ini | 33 + .../montara/qos.json.j2 | 161 ++ .../montara/switch-sai.conf | 34 + .../installer.conf | 1 + .../mavericks/buffers.json.j2 | 2 + .../mavericks/buffers_defaults_t0.j2 | 83 + .../mavericks/buffers_defaults_t1.j2 | 83 + .../mavericks/pg_profile_lookup.ini | 17 + .../mavericks/port_config.ini | 66 + .../mavericks/qos.json.j2 | 161 ++ .../mavericks/switch-sai.conf | 34 + .../minigraph.xml | 1079 ++++++++ .../INGRASYS-S9180-32X/port_config.ini | 33 + .../INGRASYS-S9180-32X/switch-sai.conf | 33 + .../x86_64-ingrasys_s9180_32x-r0/fancontrol | 12 + .../installer.conf | 3 + .../minigraph.xml | 151 ++ .../plugins/eeprom.py | 22 + .../plugins/psuutil.py | 90 + .../plugins/sfputil.py | 290 ++ .../x86_64-ingrasys_s9180_32x-r0/sensors.conf | 76 + .../OSW1800-48x6q/port_config.ini | 55 + .../OSW1800-48x6q/switch-sai.conf | 33 + device/wnc/x86_64-wnc_osw1800-r0/fancontrol | 11 + .../wnc/x86_64-wnc_osw1800-r0/installer.conf | 3 + .../wnc/x86_64-wnc_osw1800-r0/minigraph.xml | 1761 ++++++++++++ .../x86_64-wnc_osw1800-r0/plugins/eeprom.py | 22 + .../x86_64-wnc_osw1800-r0/plugins/psuutil.py | 64 + .../x86_64-wnc_osw1800-r0/plugins/sfputil.py | 205 ++ device/wnc/x86_64-wnc_osw1800-r0/sensors.conf | 33 + dockers/docker-orchagent-bfn | 1 + dockers/docker-orchagent/orchagent.sh | 2 + dockers/docker-saiserver-bfn/Dockerfile | 38 + dockers/docker-saiserver-bfn/portmap.ini | 33 + dockers/docker-saiserver-bfn/profile.ini | 1 + dockers/docker-saiserver-bfn/sai_tofino.xml | 2 + dockers/docker-saiserver-bfn/start.sh | 8 + dockers/docker-saiserver-bfn/supervisord.conf | 29 + files/build_templates/buffers_config.j2 | 2 +- .../interfaces/interfaces-config.sh | 11 + files/image_config/interfaces/interfaces.j2 | 1 + platform/barefoot/bfn-platform-ingrasys.mk | 5 + platform/barefoot/bfn-platform-wnc.mk | 5 + platform/barefoot/bfn-platform.mk | 5 + platform/barefoot/bfn-sai.mk | 5 + platform/barefoot/docker-orchagent-bfn.mk | 19 + platform/barefoot/docker-ptf-bfn.mk | 5 + platform/barefoot/docker-syncd-bfn-rpc.mk | 15 + .../docker-syncd-bfn-rpc/Dockerfile.j2 | 52 + .../docker-syncd-bfn-rpc/ptf_nn_agent.conf | 10 + platform/barefoot/docker-syncd-bfn.mk | 15 + .../barefoot/docker-syncd-bfn/Dockerfile.j2 | 29 + platform/barefoot/docker-syncd-bfn/start.sh | 9 + .../docker-syncd-bfn/supervisord.conf | 29 + platform/barefoot/libsaithrift-dev.mk | 7 + platform/barefoot/one-image.mk | 11 + .../barefoot/platform-modules-bfn-montara.mk | 11 + platform/barefoot/platform-modules-bfn.mk | 11 + .../barefoot/platform-modules-ingrasys.mk | 11 + .../barefoot/platform-modules-wnc-osw1800.mk | 11 + platform/barefoot/platform.conf | 0 platform/barefoot/python-saithrift.mk | 6 + platform/barefoot/rules.mk | 23 + .../LICENSE | 15 + .../MAINTAINERS | 3 + .../README.md | 2 + .../debian/changelog | 5 + .../debian/compat | 1 + .../debian/control | 12 + .../debian/copyright | 15 + .../debian/rules | 32 + .../modules/Makefile | 1 + .../modules/bf_kdrv.c | 1 + .../modules/bf_tun.c | 1 + .../scripts/eeprom | 10 + .../scripts/fancontrol | 11 + .../scripts/ps_info | 10 + .../scripts/sensors | 12 + .../scripts/sfputil | 10 + .../scripts/test | 1 + .../sonic-platform-modules-bfn/LICENSE | 15 + .../sonic-platform-modules-bfn/MAINTAINERS | 4 + .../sonic-platform-modules-bfn/README.md | 2 + .../debian/changelog | 5 + .../sonic-platform-modules-bfn/debian/compat | 1 + .../sonic-platform-modules-bfn/debian/control | 12 + .../debian/copyright | 15 + .../sonic-platform-modules-bfn/debian/files | 1 + .../sonic-platform-modules-bfn/debian/rules | 32 + .../modules/Makefile | 2 + .../modules/bf_kdrv.c | 1254 +++++++++ .../modules/bf_tun.c | 2396 +++++++++++++++++ .../sonic-platform-modules-bfn/scripts/eeprom | 10 + .../scripts/fancontrol | 11 + .../scripts/ps_info | 10 + .../scripts/sensors | 12 + .../scripts/sfputil | 10 + .../sonic-platform-modules-bfn/scripts/test | 1 + .../.gitignore | 52 + .../sonic-platform-modules-ingrasys/LICENSE | 674 +++++ .../debian/changelog | 17 + .../debian/compat | 1 + .../debian/control | 10 + .../debian/rules | 81 + .../sonic-platform-ingrasys-s9180-32x.dirs | 4 + .../sonic-platform-ingrasys-s9180-32x.install | 4 + ...sonic-platform-ingrasys-s9180-32x.postinst | 57 + .../sonic-platform-ingrasys-s9180-32x.postrm | 42 + .../sonic-platform-ingrasys-s9180-32x.prerm | 21 + .../sonic-platform-ingrasys-s9180-32x.upstart | 7 + .../s9180-32x/README.md | 185 ++ .../s9180-32x/modules/Makefile | 1 + .../s9180-32x/modules/eeprom_mb.c | 211 ++ .../s9180-32x/service/bfn.service | 13 + .../s9180-32x/service/qsfp-monitor.service | 15 + .../service/s9180-32x-monitor.service | 19 + .../s9180-32x/utils/bfn | 44 + .../s9180-32x/utils/i2c_utils.sh | 1423 ++++++++++ .../s9180-32x/utils/qsfp_monitor.sh | 104 + .../s9180-32x/utils/s9180_32x_monitor.sh | 41 + .../LICENSE | 15 + .../MAINTAINERS | 7 + .../README.md | 2 + .../debian/changelog | 5 + .../debian/compat | 1 + .../debian/control | 12 + .../debian/copyright | 15 + .../debian/rules | 38 + .../modules/Makefile | 6 + .../modules/bf_kdrv.c | 1254 +++++++++ .../modules/bf_tun.c | 2396 +++++++++++++++++ .../modules/i2c-mcp2221.c | 611 +++++ .../modules/wnc_cpld.c | 198 ++ .../modules/wnc_cpld3.c | 200 ++ .../modules/wnc_eeprom.c | 286 ++ .../scripts/device_node.sh | 91 + .../scripts/driver_load.sh | 50 + .../scripts/test | 1 + .../service/device_node.service | 11 + .../service/driver_load.service | 10 + platform/vs/tests/conftest.py | 17 +- slave.mk | 1 + sonic-slave/Dockerfile | 5 + .../tests/sample_output/interfaces | 1 + src/sonic-sairedis | 2 +- src/sonic-swss | 2 +- src/sonic-swss-common | 2 +- 153 files changed, 18532 insertions(+), 6 deletions(-) create mode 100644 device/barefoot/x86_64-accton_wedge100bf_32x-r0/installer.conf create mode 100644 device/barefoot/x86_64-accton_wedge100bf_32x-r0/minigraph.xml create mode 100644 device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers.json.j2 create mode 100644 device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers_defaults_t0.j2 create mode 100644 device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers_defaults_t1.j2 create mode 100644 device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/pg_profile_lookup.ini create mode 100644 device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/port_config.ini create mode 100644 device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/qos.json.j2 create mode 100644 device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/switch-sai.conf create mode 100644 device/barefoot/x86_64-accton_wedge100bf_65x-r0/installer.conf create mode 100644 device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers.json.j2 create mode 100644 device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers_defaults_t0.j2 create mode 100644 device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers_defaults_t1.j2 create mode 100644 device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/pg_profile_lookup.ini create mode 100644 device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/port_config.ini create mode 100644 device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/qos.json.j2 create mode 100644 device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/switch-sai.conf create mode 100644 device/barefoot/x86_64-accton_wedge100bf_65x-r0/minigraph.xml create mode 100644 device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/port_config.ini create mode 100644 device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/switch-sai.conf create mode 100644 device/ingrasys/x86_64-ingrasys_s9180_32x-r0/fancontrol create mode 100644 device/ingrasys/x86_64-ingrasys_s9180_32x-r0/installer.conf create mode 100644 device/ingrasys/x86_64-ingrasys_s9180_32x-r0/minigraph.xml create mode 100644 device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/eeprom.py create mode 100644 device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/psuutil.py create mode 100644 device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/sfputil.py create mode 100644 device/ingrasys/x86_64-ingrasys_s9180_32x-r0/sensors.conf create mode 100644 device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/port_config.ini create mode 100644 device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/switch-sai.conf create mode 100644 device/wnc/x86_64-wnc_osw1800-r0/fancontrol create mode 100644 device/wnc/x86_64-wnc_osw1800-r0/installer.conf create mode 100644 device/wnc/x86_64-wnc_osw1800-r0/minigraph.xml create mode 100644 device/wnc/x86_64-wnc_osw1800-r0/plugins/eeprom.py create mode 100644 device/wnc/x86_64-wnc_osw1800-r0/plugins/psuutil.py create mode 100644 device/wnc/x86_64-wnc_osw1800-r0/plugins/sfputil.py create mode 100644 device/wnc/x86_64-wnc_osw1800-r0/sensors.conf create mode 120000 dockers/docker-orchagent-bfn create mode 100755 dockers/docker-saiserver-bfn/Dockerfile create mode 100644 dockers/docker-saiserver-bfn/portmap.ini create mode 100644 dockers/docker-saiserver-bfn/profile.ini create mode 100644 dockers/docker-saiserver-bfn/sai_tofino.xml create mode 100755 dockers/docker-saiserver-bfn/start.sh create mode 100644 dockers/docker-saiserver-bfn/supervisord.conf create mode 100644 platform/barefoot/bfn-platform-ingrasys.mk create mode 100644 platform/barefoot/bfn-platform-wnc.mk create mode 100644 platform/barefoot/bfn-platform.mk create mode 100644 platform/barefoot/bfn-sai.mk create mode 100644 platform/barefoot/docker-orchagent-bfn.mk create mode 100644 platform/barefoot/docker-ptf-bfn.mk create mode 100644 platform/barefoot/docker-syncd-bfn-rpc.mk create mode 100644 platform/barefoot/docker-syncd-bfn-rpc/Dockerfile.j2 create mode 100644 platform/barefoot/docker-syncd-bfn-rpc/ptf_nn_agent.conf create mode 100644 platform/barefoot/docker-syncd-bfn.mk create mode 100755 platform/barefoot/docker-syncd-bfn/Dockerfile.j2 create mode 100755 platform/barefoot/docker-syncd-bfn/start.sh create mode 100644 platform/barefoot/docker-syncd-bfn/supervisord.conf create mode 100644 platform/barefoot/libsaithrift-dev.mk create mode 100644 platform/barefoot/one-image.mk create mode 100644 platform/barefoot/platform-modules-bfn-montara.mk create mode 100644 platform/barefoot/platform-modules-bfn.mk create mode 100644 platform/barefoot/platform-modules-ingrasys.mk create mode 100644 platform/barefoot/platform-modules-wnc-osw1800.mk create mode 100644 platform/barefoot/platform.conf create mode 100644 platform/barefoot/python-saithrift.mk create mode 100644 platform/barefoot/rules.mk create mode 100644 platform/barefoot/sonic-platform-modules-bfn-montara/LICENSE create mode 100644 platform/barefoot/sonic-platform-modules-bfn-montara/MAINTAINERS create mode 100644 platform/barefoot/sonic-platform-modules-bfn-montara/README.md create mode 100644 platform/barefoot/sonic-platform-modules-bfn-montara/debian/changelog create mode 100644 platform/barefoot/sonic-platform-modules-bfn-montara/debian/compat create mode 100644 platform/barefoot/sonic-platform-modules-bfn-montara/debian/control create mode 100644 platform/barefoot/sonic-platform-modules-bfn-montara/debian/copyright create mode 100755 platform/barefoot/sonic-platform-modules-bfn-montara/debian/rules create mode 120000 platform/barefoot/sonic-platform-modules-bfn-montara/modules/Makefile create mode 120000 platform/barefoot/sonic-platform-modules-bfn-montara/modules/bf_kdrv.c create mode 120000 platform/barefoot/sonic-platform-modules-bfn-montara/modules/bf_tun.c create mode 100755 platform/barefoot/sonic-platform-modules-bfn-montara/scripts/eeprom create mode 100755 platform/barefoot/sonic-platform-modules-bfn-montara/scripts/fancontrol create mode 100755 platform/barefoot/sonic-platform-modules-bfn-montara/scripts/ps_info create mode 100755 platform/barefoot/sonic-platform-modules-bfn-montara/scripts/sensors create mode 100755 platform/barefoot/sonic-platform-modules-bfn-montara/scripts/sfputil create mode 100755 platform/barefoot/sonic-platform-modules-bfn-montara/scripts/test create mode 100644 platform/barefoot/sonic-platform-modules-bfn/LICENSE create mode 100644 platform/barefoot/sonic-platform-modules-bfn/MAINTAINERS create mode 100644 platform/barefoot/sonic-platform-modules-bfn/README.md create mode 100644 platform/barefoot/sonic-platform-modules-bfn/debian/changelog create mode 100644 platform/barefoot/sonic-platform-modules-bfn/debian/compat create mode 100644 platform/barefoot/sonic-platform-modules-bfn/debian/control create mode 100644 platform/barefoot/sonic-platform-modules-bfn/debian/copyright create mode 100644 platform/barefoot/sonic-platform-modules-bfn/debian/files create mode 100755 platform/barefoot/sonic-platform-modules-bfn/debian/rules create mode 100644 platform/barefoot/sonic-platform-modules-bfn/modules/Makefile create mode 100644 platform/barefoot/sonic-platform-modules-bfn/modules/bf_kdrv.c create mode 100644 platform/barefoot/sonic-platform-modules-bfn/modules/bf_tun.c create mode 100755 platform/barefoot/sonic-platform-modules-bfn/scripts/eeprom create mode 100755 platform/barefoot/sonic-platform-modules-bfn/scripts/fancontrol create mode 100755 platform/barefoot/sonic-platform-modules-bfn/scripts/ps_info create mode 100755 platform/barefoot/sonic-platform-modules-bfn/scripts/sensors create mode 100755 platform/barefoot/sonic-platform-modules-bfn/scripts/sfputil create mode 100755 platform/barefoot/sonic-platform-modules-bfn/scripts/test create mode 100644 platform/barefoot/sonic-platform-modules-ingrasys/.gitignore create mode 100644 platform/barefoot/sonic-platform-modules-ingrasys/LICENSE create mode 100644 platform/barefoot/sonic-platform-modules-ingrasys/debian/changelog create mode 100644 platform/barefoot/sonic-platform-modules-ingrasys/debian/compat create mode 100644 platform/barefoot/sonic-platform-modules-ingrasys/debian/control create mode 100755 platform/barefoot/sonic-platform-modules-ingrasys/debian/rules create mode 100644 platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.dirs create mode 100644 platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.install create mode 100644 platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.postinst create mode 100644 platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.postrm create mode 100644 platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.prerm create mode 100644 platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.upstart create mode 100644 platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/README.md create mode 100644 platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/Makefile create mode 100644 platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/eeprom_mb.c create mode 100644 platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/bfn.service create mode 100644 platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/qsfp-monitor.service create mode 100644 platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/s9180-32x-monitor.service create mode 100755 platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/bfn create mode 100755 platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/i2c_utils.sh create mode 100755 platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/qsfp_monitor.sh create mode 100755 platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/s9180_32x_monitor.sh create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/LICENSE create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/MAINTAINERS create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/README.md create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/changelog create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/compat create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/control create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/copyright create mode 100755 platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/rules create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/Makefile create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/bf_kdrv.c create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/bf_tun.c create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/i2c-mcp2221.c create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld.c create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld3.c create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_eeprom.c create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/device_node.sh create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/driver_load.sh create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/test create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/service/device_node.service create mode 100644 platform/barefoot/sonic-platform-modules-wnc-osw1800/service/driver_load.service diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/installer.conf b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/installer.conf new file mode 100644 index 000000000000..3714ff053bb0 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/installer.conf @@ -0,0 +1 @@ +CONSOLE_SPEED=57600 diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/minigraph.xml b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/minigraph.xml new file mode 100644 index 000000000000..60d93ad69d66 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/minigraph.xml @@ -0,0 +1,1079 @@ + + + + + + ARISTA01T0 + 10.0.0.33 + switch + 10.0.0.32 + 1 + 180 + 60 + + + switch + 10.0.0.0 + ARISTA01T2 + 10.0.0.1 + 1 + 180 + 60 + + + ARISTA02T0 + 10.0.0.35 + switch + 10.0.0.34 + 1 + 180 + 60 + + + switch + 10.0.0.2 + ARISTA02T2 + 10.0.0.3 + 1 + 180 + 60 + + + ARISTA03T0 + 10.0.0.37 + switch + 10.0.0.36 + 1 + 180 + 60 + + + switch + 10.0.0.4 + ARISTA03T2 + 10.0.0.5 + 1 + 180 + 60 + + + ARISTA04T0 + 10.0.0.39 + switch + 10.0.0.38 + 1 + 180 + 60 + + + switch + 10.0.0.6 + ARISTA04T2 + 10.0.0.7 + 1 + 180 + 60 + + + ARISTA05T0 + 10.0.0.41 + switch + 10.0.0.40 + 1 + 180 + 60 + + + switch + 10.0.0.8 + ARISTA05T2 + 10.0.0.9 + 1 + 180 + 60 + + + ARISTA06T0 + 10.0.0.43 + switch + 10.0.0.42 + 1 + 180 + 60 + + + switch + 10.0.0.10 + ARISTA06T2 + 10.0.0.11 + 1 + 180 + 60 + + + ARISTA07T0 + 10.0.0.45 + switch + 10.0.0.44 + 1 + 180 + 60 + + + switch + 10.0.0.12 + ARISTA07T2 + 10.0.0.13 + 1 + 180 + 60 + + + ARISTA08T0 + 10.0.0.47 + switch + 10.0.0.46 + 1 + 180 + 60 + + + switch + 10.0.0.14 + ARISTA08T2 + 10.0.0.15 + 1 + 180 + 60 + + + ARISTA09T0 + 10.0.0.49 + switch + 10.0.0.48 + 1 + 180 + 60 + + + switch + 10.0.0.16 + ARISTA09T2 + 10.0.0.17 + 1 + 180 + 60 + + + ARISTA10T0 + 10.0.0.51 + switch + 10.0.0.50 + 1 + 180 + 60 + + + switch + 10.0.0.18 + ARISTA10T2 + 10.0.0.19 + 1 + 180 + 60 + + + ARISTA11T0 + 10.0.0.53 + switch + 10.0.0.52 + 1 + 180 + 60 + + + switch + 10.0.0.20 + ARISTA11T2 + 10.0.0.21 + 1 + 180 + 60 + + + ARISTA12T0 + 10.0.0.55 + switch + 10.0.0.54 + 1 + 180 + 60 + + + switch + 10.0.0.22 + ARISTA12T2 + 10.0.0.23 + 1 + 180 + 60 + + + ARISTA13T0 + 10.0.0.57 + switch + 10.0.0.56 + 1 + 180 + 60 + + + switch + 10.0.0.24 + ARISTA13T2 + 10.0.0.25 + 1 + 180 + 60 + + + ARISTA14T0 + 10.0.0.59 + switch + 10.0.0.58 + 1 + 180 + 60 + + + switch + 10.0.0.26 + ARISTA14T2 + 10.0.0.27 + 1 + 180 + 60 + + + ARISTA15T0 + 10.0.0.61 + switch + 10.0.0.60 + 1 + 180 + 60 + + + switch + 10.0.0.28 + ARISTA15T2 + 10.0.0.29 + 1 + 180 + 60 + + + ARISTA16T0 + 10.0.0.63 + switch + 10.0.0.62 + 1 + 180 + 60 + + + switch + 10.0.0.30 + ARISTA16T2 + 10.0.0.31 + 1 + 180 + 60 + + + + + 65100 + switch + + +
10.0.0.33
+ + +
+ +
10.0.0.1
+ + +
+ +
10.0.0.35
+ + +
+ +
10.0.0.3
+ + +
+ +
10.0.0.37
+ + +
+ +
10.0.0.5
+ + +
+ +
10.0.0.39
+ + +
+ +
10.0.0.7
+ + +
+ +
10.0.0.41
+ + +
+ +
10.0.0.9
+ + +
+ +
10.0.0.43
+ + +
+ +
10.0.0.11
+ + +
+ +
10.0.0.45
+ + +
+ +
10.0.0.13
+ + +
+ +
10.0.0.47
+ + +
+ +
10.0.0.15
+ + +
+ +
10.0.0.49
+ + +
+ +
10.0.0.17
+ + +
+ +
10.0.0.51
+ + +
+ +
10.0.0.19
+ + +
+ +
10.0.0.53
+ + +
+ +
10.0.0.21
+ + +
+ +
10.0.0.55
+ + +
+ +
10.0.0.23
+ + +
+ +
10.0.0.57
+ + +
+ +
10.0.0.25
+ + +
+ +
10.0.0.59
+ + +
+ +
10.0.0.27
+ + +
+ +
10.0.0.61
+ + +
+ +
10.0.0.29
+ + +
+ +
10.0.0.63
+ + +
+ +
10.0.0.31
+ + +
+
+ +
+ + 64001 + ARISTA01T0 + + + + 65200 + ARISTA01T2 + + + + 64002 + ARISTA02T0 + + + + 65200 + ARISTA02T2 + + + + 64003 + ARISTA03T0 + + + + 65200 + ARISTA03T2 + + + + 64004 + ARISTA04T0 + + + + 65200 + ARISTA04T2 + + + + 64005 + ARISTA05T0 + + + + 65200 + ARISTA05T2 + + + + 64006 + ARISTA06T0 + + + + 65200 + ARISTA06T2 + + + + 64007 + ARISTA07T0 + + + + 65200 + ARISTA07T2 + + + + 64008 + ARISTA08T0 + + + + 65200 + ARISTA08T2 + + + + 64009 + ARISTA09T0 + + + + 65200 + ARISTA09T2 + + + + 64010 + ARISTA10T0 + + + + 65200 + ARISTA10T2 + + + + 64011 + ARISTA11T0 + + + + 65200 + ARISTA11T2 + + + + 64012 + ARISTA12T0 + + + + 65200 + ARISTA12T2 + + + + 64013 + ARISTA13T0 + + + + 65200 + ARISTA13T2 + + + + 64014 + ARISTA14T0 + + + + 65200 + ARISTA14T2 + + + + 64015 + ARISTA15T0 + + + + 65200 + ARISTA15T2 + + + + 64016 + ARISTA16T0 + + + + 65200 + ARISTA16T2 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + + + + + + switch + + + + + + Ethernet0 + 10.0.0.0/31 + + + + Ethernet4 + 10.0.0.2/31 + + + + Ethernet8 + 10.0.0.4/31 + + + + Ethernet12 + 10.0.0.6/31 + + + + Ethernet16 + 10.0.0.8/31 + + + + Ethernet20 + 10.0.0.10/31 + + + + Ethernet24 + 10.0.0.12/31 + + + + Ethernet28 + 10.0.0.14/31 + + + + Ethernet32 + 10.0.0.16/31 + + + + Ethernet36 + 10.0.0.18/31 + + + + Ethernet40 + 10.0.0.20/31 + + + + Ethernet44 + 10.0.0.22/31 + + + + Ethernet48 + 10.0.0.24/31 + + + + Ethernet52 + 10.0.0.26/31 + + + + Ethernet56 + 10.0.0.28/31 + + + + Ethernet60 + 10.0.0.30/31 + + + + Ethernet64 + 10.0.0.32/31 + + + + Ethernet68 + 10.0.0.34/31 + + + + Ethernet72 + 10.0.0.36/31 + + + + Ethernet76 + 10.0.0.38/31 + + + + Ethernet80 + 10.0.0.40/31 + + + + Ethernet84 + 10.0.0.42/31 + + + + Ethernet88 + 10.0.0.44/31 + + + + Ethernet92 + 10.0.0.46/31 + + + + Ethernet96 + 10.0.0.48/31 + + + + Ethernet100 + 10.0.0.50/31 + + + + Ethernet104 + 10.0.0.52/31 + + + + Ethernet108 + 10.0.0.54/31 + + + + Ethernet112 + 10.0.0.56/31 + + + + Ethernet116 + 10.0.0.58/31 + + + + Ethernet120 + 10.0.0.60/31 + + + + Ethernet124 + 10.0.0.62/31 + + + + + + + + + + + + DeviceInterfaceLink + switch + Ethernet0 + ARISTA01T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet4 + ARISTA02T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet8 + ARISTA03T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet12 + ARISTA04T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet16 + ARISTA05T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet20 + ARISTA06T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet24 + ARISTA07T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet28 + ARISTA08T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet32 + ARISTA09T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet36 + ARISTA10T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet40 + ARISTA11T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet44 + ARISTA12T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet48 + ARISTA13T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet52 + ARISTA14T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet56 + ARISTA15T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet60 + ARISTA16T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet64 + ARISTA01T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet68 + ARISTA02T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet72 + ARISTA03T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet76 + ARISTA04T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet80 + ARISTA05T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet84 + ARISTA06T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet88 + ARISTA07T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet92 + ARISTA08T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet96 + ARISTA09T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet100 + ARISTA10T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet104 + ARISTA11T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet108 + ARISTA12T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet112 + ARISTA13T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet116 + ARISTA14T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet120 + ARISTA15T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet124 + ARISTA16T0 + Ethernet1 + + + + + switch + montara + + ` + + + + + switch + + + DhcpResources + + + + + NtpResources + + 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org + + + SyslogResources + + + + + ErspanDestinationIpv4 + + 2.2.2.2 + + + + + + + switch + montara +
diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers.json.j2 b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers.json.j2 new file mode 100644 index 000000000000..1083a6210fc9 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers_defaults_t0.j2 b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..73e95a457a2a --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers_defaults_t0.j2 @@ -0,0 +1,83 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '4194304' %} +{% set ingress_lossy_pool_size = '7340032' %} +{% set egress_lossless_pool_size = '16777152' %} +{% set egress_lossy_pool_size = '7340032' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,32) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + "size": "{{ ingress_lossy_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + "size": "{{ egress_lossy_pool_size }}", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"4096", + "dynamic_th":"0" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"4096", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + }, + "q_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + } + }, +{%- endmacro %} + +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +{%- endmacro %} diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers_defaults_t1.j2 b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..fce82ea2edf5 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/buffers_defaults_t1.j2 @@ -0,0 +1,83 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '2097152' %} +{% set ingress_lossy_pool_size = '5242880' %} +{% set egress_lossless_pool_size = '16777152' %} +{% set egress_lossy_pool_size = '5242880' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,32) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + "size": "{{ ingress_lossy_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + "size": "{{ egress_lossy_pool_size }}", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"4096", + "dynamic_th":"0" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"4096", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + }, + "q_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + } + }, +{%- endmacro %} + +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +{%- endmacro %} diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/pg_profile_lookup.ini b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/pg_profile_lookup.ini new file mode 100644 index 000000000000..b66b129fe43f --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/port_config.ini b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/port_config.ini new file mode 100644 index 000000000000..816bb0e94a70 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/port_config.ini @@ -0,0 +1,33 @@ +# name lanes +Ethernet0 0,1,2,3 +Ethernet4 4,5,6,7 +Ethernet8 8,9,10,11 +Ethernet12 12,13,14,15 +Ethernet16 16,17,18,19 +Ethernet20 20,21,22,23 +Ethernet24 24,25,26,27 +Ethernet28 28,29,30,31 +Ethernet32 32,33,34,35 +Ethernet36 36,37,38,39 +Ethernet40 40,41,42,43 +Ethernet44 44,45,46,47 +Ethernet48 48,49,50,51 +Ethernet52 52,53,54,55 +Ethernet56 56,57,58,59 +Ethernet60 60,61,62,63 +Ethernet64 64,65,66,67 +Ethernet68 68,69,70,71 +Ethernet72 72,73,74,75 +Ethernet76 76,77,78,79 +Ethernet80 80,81,82,83 +Ethernet84 84,85,86,87 +Ethernet88 88,89,90,91 +Ethernet92 92,93,94,95 +Ethernet96 96,97,98,99 +Ethernet100 100,101,102,103 +Ethernet104 104,105,106,107 +Ethernet108 108,109,110,111 +Ethernet112 112,113,114,115 +Ethernet116 116,117,118,119 +Ethernet120 120,121,122,123 +Ethernet124 124,125,126,127 diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/qos.json.j2 b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/qos.json.j2 new file mode 100644 index 000000000000..7b8732e2e125 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/qos.json.j2 @@ -0,0 +1,161 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "3": "3", + "4": "4" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1": { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2": { + "type":"DWRR", + "weight": "20" + } + }, + "PFC_PRIORITY_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "3": "3", + "4": "4" + } + }, + "PORT_QOS_MAP": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_to_pg_map" : "[PFC_PRIORITY_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_enable": "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSY": { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"516096", + "red_min_threshold":"516096", + "yellow_max_threshold":"516096", + "yellow_min_threshold":"516096", + "green_max_threshold": "184320", + "green_min_threshold": "184320" + }, + "AZURE_LOSSLESS": { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"516096", + "red_min_threshold":"516096", + "yellow_max_threshold":"516096", + "yellow_min_threshold":"516096", + "green_max_threshold": "184320", + "green_min_threshold": "184320" + } + }, + "QUEUE": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|0": { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|1": { + "scheduler" : "[SCHEDULER|scheduler.2]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|0-1": { + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSY]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|3-4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSLESS]" + } + } +} diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/switch-sai.conf b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/switch-sai.conf new file mode 100644 index 000000000000..089153b6a5ce --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/switch-sai.conf @@ -0,0 +1,34 @@ +{ + "chip_list": [ + { + "id": "asic-0", + "chip_family": "Tofino", + "instance": 0, + "pcie_sysfs_prefix": "/sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0", + "pcie_domain": 0, + "pcie_bus": 5, + "pcie_fn": 0, + "pcie_dev": 0, + "pcie_int_mode": 1, + "sds_fw_path": "share/tofino_sds_fw/avago/firmware" + } + ], + "instance": 0, + "p4_program_list": [ + { + "id": "pgm-0", + "instance": 0, + "path": "switch", + "program-name": "switch", + "pd": "lib/tofinopd/switch/libpd.so", + "pd-thrift": "lib/tofinopd/switch/libpdthrift.so", + "table-config": "share/tofinopd/switch/context.json", + "tofino-bin": "share/tofinopd/switch/tofino.bin", + "switchapi": "lib/libswitchapi.so", + "switchsai": "lib/libswitchsai.so", + "agent0": "lib/platform/x86_64-accton_wedge100bf_32x-r0/libpltfm_mgr.so", + "switchapi_port_add": false, + "non_default_port_ppgs": 5 + } + ] +} diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/installer.conf b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/installer.conf new file mode 100644 index 000000000000..3714ff053bb0 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/installer.conf @@ -0,0 +1 @@ +CONSOLE_SPEED=57600 diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers.json.j2 b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers.json.j2 new file mode 100644 index 000000000000..1083a6210fc9 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers_defaults_t0.j2 b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..e5b949faed00 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers_defaults_t0.j2 @@ -0,0 +1,83 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '4194304' %} +{% set ingress_lossy_pool_size = '7340032' %} +{% set egress_lossless_pool_size = '16777152' %} +{% set egress_lossy_pool_size = '7340032' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + "size": "{{ ingress_lossy_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + "size": "{{ egress_lossy_pool_size }}", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"4096", + "dynamic_th":"0" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"4096", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + }, + "q_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + } + }, +{%- endmacro %} + +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +{%- endmacro %} diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers_defaults_t1.j2 b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..1d8096c0d6cc --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/buffers_defaults_t1.j2 @@ -0,0 +1,83 @@ +{% set default_cable = '5m' %} +{% set ingress_lossless_pool_size = '2097152' %} +{% set ingress_lossy_pool_size = '5242880' %} +{% set egress_lossless_pool_size = '16777152' %} +{% set egress_lossy_pool_size = '5242880' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,64) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "{{ ingress_lossless_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "ingress_lossy_pool": { + "size": "{{ ingress_lossy_pool_size }}", + "type": "ingress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "{{ egress_lossless_pool_size }}", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossy_pool": { + "size": "{{ egress_lossy_pool_size }}", + "type": "egress", + "mode": "dynamic" + } + }, + "BUFFER_PROFILE": { + "ingress_lossless_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"4096", + "dynamic_th":"0" + }, + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"4096", + "dynamic_th":"7" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + }, + "q_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"4096", + "dynamic_th":"3" + } + }, +{%- endmacro %} + +{%- macro generate_pg_profils(port_names) %} + "BUFFER_PG": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]" + } + }, +{%- endmacro %} + +{%- macro generate_queue_buffers(port_names) %} + "BUFFER_QUEUE": { + "{{ port_names }}|3-4": { + "profile" : "[BUFFER_PROFILE|egress_lossless_profile]" + }, + "{{ port_names }}|0-1": { + "profile" : "[BUFFER_PROFILE|q_lossy_profile]" + } + } +{%- endmacro %} diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/pg_profile_lookup.ini b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/pg_profile_lookup.ini new file mode 100644 index 000000000000..b66b129fe43f --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/port_config.ini b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/port_config.ini new file mode 100644 index 000000000000..c1001741d28a --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/port_config.ini @@ -0,0 +1,66 @@ +# name lanes +Ethernet0 0,1,2,3 +Ethernet4 4,5,6,7 +Ethernet8 8,9,10,11 +Ethernet12 12,13,14,15 +Ethernet16 16,17,18,19 +Ethernet20 20,21,22,23 +Ethernet24 24,25,26,27 +Ethernet28 28,29,30,31 +Ethernet32 32,33,34,35 +Ethernet36 36,37,38,39 +Ethernet40 40,41,42,43 +Ethernet44 44,45,46,47 +Ethernet48 48,49,50,51 +Ethernet52 52,53,54,55 +Ethernet56 56,57,58,59 +Ethernet60 60,61,62,63 +Ethernet64 64,65,66,67 +Ethernet68 68,69,70,71 +Ethernet72 72,73,74,75 +Ethernet76 76,77,78,79 +Ethernet80 80,81,82,83 +Ethernet84 84,85,86,87 +Ethernet88 88,89,90,91 +Ethernet92 92,93,94,95 +Ethernet96 96,97,98,99 +Ethernet100 100,101,102,103 +Ethernet104 104,105,106,107 +Ethernet108 108,109,110,111 +Ethernet112 112,113,114,115 +Ethernet116 116,117,118,119 +Ethernet120 120,121,122,123 +Ethernet124 124,125,126,127 +Ethernet128 128,129,130,131 +Ethernet132 132,133,134,135 +Ethernet136 136,137,138,139 +Ethernet140 140,141,142,143 +Ethernet144 144,145,146,147 +Ethernet148 148,149,150,151 +Ethernet152 152,153,154,155 +Ethernet156 156,157,158,159 +Ethernet160 160,161,162,163 +Ethernet164 164,165,166,167 +Ethernet168 168,169,170,171 +Ethernet172 172,173,174,175 +Ethernet176 176,177,178,179 +Ethernet180 180,181,182,183 +Ethernet184 184,185,186,187 +Ethernet188 188,189,190,191 +Ethernet192 192,193,194,195 +Ethernet196 196,197,198,199 +Ethernet200 200,201,202,203 +Ethernet204 204,205,206,207 +Ethernet208 208,209,210,211 +Ethernet212 212,213,214,215 +Ethernet216 216,217,218,219 +Ethernet220 220,221,222,223 +Ethernet224 224,225,226,227 +Ethernet228 228,229,230,231 +Ethernet232 232,233,234,235 +Ethernet236 236,237,238,239 +Ethernet240 240,241,242,243 +Ethernet244 244,245,246,247 +Ethernet248 248,249,250,251 +Ethernet252 252,253,254,255 +Ethernet256 256,257,258,259 diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/qos.json.j2 b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/qos.json.j2 new file mode 100644 index 000000000000..7b8732e2e125 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/qos.json.j2 @@ -0,0 +1,161 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "3": "3", + "4": "4" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "3": "3", + "4": "4" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1": { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2": { + "type":"DWRR", + "weight": "20" + } + }, + "PFC_PRIORITY_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "3": "3", + "4": "4" + } + }, + "PORT_QOS_MAP": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_to_pg_map" : "[PFC_PRIORITY_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_enable": "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSY": { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"516096", + "red_min_threshold":"516096", + "yellow_max_threshold":"516096", + "yellow_min_threshold":"516096", + "green_max_threshold": "184320", + "green_min_threshold": "184320" + }, + "AZURE_LOSSLESS": { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"516096", + "red_min_threshold":"516096", + "yellow_max_threshold":"516096", + "yellow_min_threshold":"516096", + "green_max_threshold": "184320", + "green_min_threshold": "184320" + } + }, + "QUEUE": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|0": { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|1": { + "scheduler" : "[SCHEDULER|scheduler.2]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|0-1": { + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSY]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|3-4": { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSLESS]" + } + } +} diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/switch-sai.conf b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/switch-sai.conf new file mode 100644 index 000000000000..1f0ff8b32bb1 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/switch-sai.conf @@ -0,0 +1,34 @@ +{ + "chip_list": [ + { + "id": "asic-0", + "chip_family": "Tofino", + "instance": 0, + "pcie_sysfs_prefix": "/sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0", + "pcie_domain": 0, + "pcie_bus": 5, + "pcie_fn": 0, + "pcie_dev": 0, + "pcie_int_mode": 1, + "sds_fw_path": "share/tofino_sds_fw/avago/firmware" + } + ], + "instance": 0, + "p4_program_list": [ + { + "id": "pgm-0", + "instance": 0, + "path": "switch", + "program-name": "switch", + "pd": "lib/tofinopd/switch/libpd.so", + "pd-thrift": "lib/tofinopd/switch/libpdthrift.so", + "table-config": "share/tofinopd/switch/context.json", + "tofino-bin": "share/tofinopd/switch/tofino.bin", + "switchapi": "lib/libswitchapi.so", + "switchsai": "lib/libswitchsai.so", + "agent0": "lib/platform/x86_64-accton_wedge100bf_65x-r0/libpltfm_mgr.so", + "switchapi_port_add": false, + "non_default_port_ppgs": 5 + } + ] +} diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/minigraph.xml b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/minigraph.xml new file mode 100644 index 000000000000..18d614739737 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/minigraph.xml @@ -0,0 +1,1079 @@ + + + + + + ARISTA01T0 + 10.0.0.33 + switch + 10.0.0.32 + 1 + 180 + 60 + + + switch + 10.0.0.0 + ARISTA01T2 + 10.0.0.1 + 1 + 180 + 60 + + + ARISTA02T0 + 10.0.0.35 + switch + 10.0.0.34 + 1 + 180 + 60 + + + switch + 10.0.0.2 + ARISTA02T2 + 10.0.0.3 + 1 + 180 + 60 + + + ARISTA03T0 + 10.0.0.37 + switch + 10.0.0.36 + 1 + 180 + 60 + + + switch + 10.0.0.4 + ARISTA03T2 + 10.0.0.5 + 1 + 180 + 60 + + + ARISTA04T0 + 10.0.0.39 + switch + 10.0.0.38 + 1 + 180 + 60 + + + switch + 10.0.0.6 + ARISTA04T2 + 10.0.0.7 + 1 + 180 + 60 + + + ARISTA05T0 + 10.0.0.41 + switch + 10.0.0.40 + 1 + 180 + 60 + + + switch + 10.0.0.8 + ARISTA05T2 + 10.0.0.9 + 1 + 180 + 60 + + + ARISTA06T0 + 10.0.0.43 + switch + 10.0.0.42 + 1 + 180 + 60 + + + switch + 10.0.0.10 + ARISTA06T2 + 10.0.0.11 + 1 + 180 + 60 + + + ARISTA07T0 + 10.0.0.45 + switch + 10.0.0.44 + 1 + 180 + 60 + + + switch + 10.0.0.12 + ARISTA07T2 + 10.0.0.13 + 1 + 180 + 60 + + + ARISTA08T0 + 10.0.0.47 + switch + 10.0.0.46 + 1 + 180 + 60 + + + switch + 10.0.0.14 + ARISTA08T2 + 10.0.0.15 + 1 + 180 + 60 + + + ARISTA09T0 + 10.0.0.49 + switch + 10.0.0.48 + 1 + 180 + 60 + + + switch + 10.0.0.16 + ARISTA09T2 + 10.0.0.17 + 1 + 180 + 60 + + + ARISTA10T0 + 10.0.0.51 + switch + 10.0.0.50 + 1 + 180 + 60 + + + switch + 10.0.0.18 + ARISTA10T2 + 10.0.0.19 + 1 + 180 + 60 + + + ARISTA11T0 + 10.0.0.53 + switch + 10.0.0.52 + 1 + 180 + 60 + + + switch + 10.0.0.20 + ARISTA11T2 + 10.0.0.21 + 1 + 180 + 60 + + + ARISTA12T0 + 10.0.0.55 + switch + 10.0.0.54 + 1 + 180 + 60 + + + switch + 10.0.0.22 + ARISTA12T2 + 10.0.0.23 + 1 + 180 + 60 + + + ARISTA13T0 + 10.0.0.57 + switch + 10.0.0.56 + 1 + 180 + 60 + + + switch + 10.0.0.24 + ARISTA13T2 + 10.0.0.25 + 1 + 180 + 60 + + + ARISTA14T0 + 10.0.0.59 + switch + 10.0.0.58 + 1 + 180 + 60 + + + switch + 10.0.0.26 + ARISTA14T2 + 10.0.0.27 + 1 + 180 + 60 + + + ARISTA15T0 + 10.0.0.61 + switch + 10.0.0.60 + 1 + 180 + 60 + + + switch + 10.0.0.28 + ARISTA15T2 + 10.0.0.29 + 1 + 180 + 60 + + + ARISTA16T0 + 10.0.0.63 + switch + 10.0.0.62 + 1 + 180 + 60 + + + switch + 10.0.0.30 + ARISTA16T2 + 10.0.0.31 + 1 + 180 + 60 + + + + + 65100 + switch + + +
10.0.0.33
+ + +
+ +
10.0.0.1
+ + +
+ +
10.0.0.35
+ + +
+ +
10.0.0.3
+ + +
+ +
10.0.0.37
+ + +
+ +
10.0.0.5
+ + +
+ +
10.0.0.39
+ + +
+ +
10.0.0.7
+ + +
+ +
10.0.0.41
+ + +
+ +
10.0.0.9
+ + +
+ +
10.0.0.43
+ + +
+ +
10.0.0.11
+ + +
+ +
10.0.0.45
+ + +
+ +
10.0.0.13
+ + +
+ +
10.0.0.47
+ + +
+ +
10.0.0.15
+ + +
+ +
10.0.0.49
+ + +
+ +
10.0.0.17
+ + +
+ +
10.0.0.51
+ + +
+ +
10.0.0.19
+ + +
+ +
10.0.0.53
+ + +
+ +
10.0.0.21
+ + +
+ +
10.0.0.55
+ + +
+ +
10.0.0.23
+ + +
+ +
10.0.0.57
+ + +
+ +
10.0.0.25
+ + +
+ +
10.0.0.59
+ + +
+ +
10.0.0.27
+ + +
+ +
10.0.0.61
+ + +
+ +
10.0.0.29
+ + +
+ +
10.0.0.63
+ + +
+ +
10.0.0.31
+ + +
+
+ +
+ + 64001 + ARISTA01T0 + + + + 65200 + ARISTA01T2 + + + + 64002 + ARISTA02T0 + + + + 65200 + ARISTA02T2 + + + + 64003 + ARISTA03T0 + + + + 65200 + ARISTA03T2 + + + + 64004 + ARISTA04T0 + + + + 65200 + ARISTA04T2 + + + + 64005 + ARISTA05T0 + + + + 65200 + ARISTA05T2 + + + + 64006 + ARISTA06T0 + + + + 65200 + ARISTA06T2 + + + + 64007 + ARISTA07T0 + + + + 65200 + ARISTA07T2 + + + + 64008 + ARISTA08T0 + + + + 65200 + ARISTA08T2 + + + + 64009 + ARISTA09T0 + + + + 65200 + ARISTA09T2 + + + + 64010 + ARISTA10T0 + + + + 65200 + ARISTA10T2 + + + + 64011 + ARISTA11T0 + + + + 65200 + ARISTA11T2 + + + + 64012 + ARISTA12T0 + + + + 65200 + ARISTA12T2 + + + + 64013 + ARISTA13T0 + + + + 65200 + ARISTA13T2 + + + + 64014 + ARISTA14T0 + + + + 65200 + ARISTA14T2 + + + + 64015 + ARISTA15T0 + + + + 65200 + ARISTA15T2 + + + + 64016 + ARISTA16T0 + + + + 65200 + ARISTA16T2 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + + + + + + switch + + + + + + Ethernet0 + 10.0.0.0/31 + + + + Ethernet4 + 10.0.0.2/31 + + + + Ethernet8 + 10.0.0.4/31 + + + + Ethernet12 + 10.0.0.6/31 + + + + Ethernet16 + 10.0.0.8/31 + + + + Ethernet20 + 10.0.0.10/31 + + + + Ethernet24 + 10.0.0.12/31 + + + + Ethernet28 + 10.0.0.14/31 + + + + Ethernet32 + 10.0.0.16/31 + + + + Ethernet36 + 10.0.0.18/31 + + + + Ethernet40 + 10.0.0.20/31 + + + + Ethernet44 + 10.0.0.22/31 + + + + Ethernet48 + 10.0.0.24/31 + + + + Ethernet52 + 10.0.0.26/31 + + + + Ethernet56 + 10.0.0.28/31 + + + + Ethernet60 + 10.0.0.30/31 + + + + Ethernet64 + 10.0.0.32/31 + + + + Ethernet68 + 10.0.0.34/31 + + + + Ethernet72 + 10.0.0.36/31 + + + + Ethernet76 + 10.0.0.38/31 + + + + Ethernet80 + 10.0.0.40/31 + + + + Ethernet84 + 10.0.0.42/31 + + + + Ethernet88 + 10.0.0.44/31 + + + + Ethernet92 + 10.0.0.46/31 + + + + Ethernet96 + 10.0.0.48/31 + + + + Ethernet100 + 10.0.0.50/31 + + + + Ethernet104 + 10.0.0.52/31 + + + + Ethernet108 + 10.0.0.54/31 + + + + Ethernet112 + 10.0.0.56/31 + + + + Ethernet116 + 10.0.0.58/31 + + + + Ethernet120 + 10.0.0.60/31 + + + + Ethernet124 + 10.0.0.62/31 + + + + + + + + + + + + DeviceInterfaceLink + switch + Ethernet0 + ARISTA01T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet4 + ARISTA02T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet8 + ARISTA03T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet12 + ARISTA04T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet16 + ARISTA05T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet20 + ARISTA06T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet24 + ARISTA07T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet28 + ARISTA08T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet32 + ARISTA09T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet36 + ARISTA10T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet40 + ARISTA11T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet44 + ARISTA12T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet48 + ARISTA13T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet52 + ARISTA14T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet56 + ARISTA15T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet60 + ARISTA16T2 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet64 + ARISTA01T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet68 + ARISTA02T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet72 + ARISTA03T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet76 + ARISTA04T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet80 + ARISTA05T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet84 + ARISTA06T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet88 + ARISTA07T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet92 + ARISTA08T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet96 + ARISTA09T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet100 + ARISTA10T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet104 + ARISTA11T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet108 + ARISTA12T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet112 + ARISTA13T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet116 + ARISTA14T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet120 + ARISTA15T0 + Ethernet1 + + + DeviceInterfaceLink + switch + Ethernet124 + ARISTA16T0 + Ethernet1 + + + + + switch + mavericks + + ` + + + + + switch + + + DhcpResources + + + + + NtpResources + + 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org + + + SyslogResources + + + + + ErspanDestinationIpv4 + + 2.2.2.2 + + + + + + + switch + mavericks +
diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/port_config.ini b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/port_config.ini new file mode 100644 index 000000000000..8b25c1333a67 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/port_config.ini @@ -0,0 +1,33 @@ +# name lanes alias speed autoneg fec index +Ethernet0 0,1,2,3 Ethernet0 100000 0 none 0 +Ethernet4 4,5,6,7 Ethernet4 100000 0 none 1 +Ethernet8 8,9,10,11 Ethernet8 100000 0 none 2 +Ethernet12 12,13,14,15 Ethernet12 100000 0 none 3 +Ethernet16 16,17,18,19 Ethernet16 100000 0 none 4 +Ethernet20 20,21,22,23 Ethernet20 100000 0 none 5 +Ethernet24 24,25,26,27 Ethernet24 100000 0 none 6 +Ethernet28 28,29,30,31 Ethernet28 100000 0 none 7 +Ethernet32 32,33,34,35 Ethernet32 100000 0 none 8 +Ethernet36 36,37,38,39 Ethernet36 100000 0 none 9 +Ethernet40 40,41,42,43 Ethernet40 100000 0 none 10 +Ethernet44 44,45,46,47 Ethernet44 100000 0 none 11 +Ethernet48 48,49,50,51 Ethernet48 100000 0 none 12 +Ethernet52 52,53,54,55 Ethernet52 100000 0 none 13 +Ethernet56 56,57,58,59 Ethernet56 100000 0 none 14 +Ethernet60 60,61,62,63 Ethernet60 100000 0 none 15 +Ethernet64 64,65,66,67 Ethernet64 100000 0 none 16 +Ethernet68 68,69,70,71 Ethernet68 100000 0 none 17 +Ethernet72 72,73,74,75 Ethernet72 100000 0 none 18 +Ethernet76 76,77,78,79 Ethernet76 100000 0 none 19 +Ethernet80 80,81,82,83 Ethernet80 100000 0 none 20 +Ethernet84 84,85,86,87 Ethernet84 100000 0 none 21 +Ethernet88 88,89,90,91 Ethernet88 100000 0 none 22 +Ethernet92 92,93,94,95 Ethernet92 100000 0 none 23 +Ethernet96 96,97,98,99 Ethernet96 100000 0 none 24 +Ethernet100 100,101,102,103 Ethernet100 100000 0 none 25 +Ethernet104 104,105,106,107 Ethernet104 100000 0 none 26 +Ethernet108 108,109,110,111 Ethernet108 100000 0 none 27 +Ethernet112 112,113,114,115 Ethernet112 100000 0 none 28 +Ethernet116 116,117,118,119 Ethernet116 100000 0 none 29 +Ethernet120 120,121,122,123 Ethernet120 100000 0 none 30 +Ethernet124 124,125,126,127 Ethernet124 100000 0 none 31 diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/switch-sai.conf b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/switch-sai.conf new file mode 100644 index 000000000000..4f316bb9e5af --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/INGRASYS-S9180-32X/switch-sai.conf @@ -0,0 +1,33 @@ +{ + "chip_list": [ + { + "id": "asic-0", + "chip_family": "Tofino", + "instance": 0, + "pcie_sysfs_prefix": "/sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0", + "pcie_domain": 0, + "pcie_bus": 5, + "pcie_fn": 0, + "pcie_dev": 0, + "pcie_int_mode": 1, + "sds_fw_path": "share/tofino_sds_fw/avago/firmware" + } + ], + "instance": 0, + "p4_program_list": [ + { + "id": "pgm-0", + "instance": 0, + "path": "switch", + "program-name": "switch", + "pd": "lib/tofinopd/switch/libpd.so", + "pd-thrift": "lib/tofinopd/switch/libpdthrift.so", + "table-config": "share/tofinopd/switch/context.json", + "tofino-bin": "share/tofinopd/switch/tofino.bin", + "switchapi": "lib/libswitchapi.so", + "switchsai": "lib/libswitchsai.so", + "agent0": "lib/platform/x86_64-ingrasys_s9180_32x-r0/libpltfm_mgr.so", + "switchapi_port_add": false + } + ] +} diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/fancontrol b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/fancontrol new file mode 100644 index 000000000000..dc303afac034 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/fancontrol @@ -0,0 +1,12 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:1f.3/i2c-0/i2c-56/56-002f +DEVNAME=hwmon1=w83795adg +FCTEMPS=hwmon1/device/pwm2=hwmon2/temp2_input hwmon1/device/pwm1=hwmon2/temp2_input +FCFANS=hwmon1/device/pwm2=hwmon1/device/fan8_input hwmon1/device/pwm2=hwmon1/device/fan7_input hwmon1/device/pwm2=hwmon1/device/fan6_input hwmon1/device/pwm2=hwmon1/device/fan5_input hwmon1/device/pwm1=hwmon1/device/fan4_input hwmon1/device/pwm1=hwmon1/device/fan3_input hwmon1/device/pwm1=hwmon1/device/fan2_input hwmon1/device/pwm1=hwmon1/device/fan1_input +# TODO: check the temp value with HW after board ready +MINTEMP=hwmon1/device/pwm2=20 hwmon1/device/pwm1=20 +MAXTEMP=hwmon1/device/pwm2=60 hwmon1/device/pwm1=60 +MINSTART=hwmon1/device/pwm2=75 hwmon1/device/pwm1=75 +MINSTOP=hwmon1/device/pwm2=22 hwmon1/device/pwm1=22 + diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/installer.conf b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/installer.conf new file mode 100644 index 000000000000..925a32fc0c3a --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +CONSOLE_SPEED=115200 diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/minigraph.xml b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/minigraph.xml new file mode 100644 index 000000000000..e2d151e6ec47 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/minigraph.xml @@ -0,0 +1,151 @@ + + + + + + OCPSCH0104001MS + 10.10.1.26 + OCPSCH01040GGLF + 10.10.1.25 + 1 + 10 + 3 + + + OCPSCH0104002MS + 10.10.2.26 + OCPSCH01040GGLF + 10.10.2.25 + 1 + 10 + 3 + + + + + 64536 + OCPSCH01040GGLF + + +
10.10.1.26
+ + +
+ +
10.10.2.26
+ + +
+
+ +
+ + 64542 + OCPSCH0104001MS + + + + 64543 + OCPSCH0104002MS + + +
+
+ + + + + + HostIP + Loopback0 + + 100.0.0.9/32 + + 100.0.0.9/32 + + + + + + + + OCPSCH01040GGLF + + + + + + Ethernet0 + 10.10.1.25/30 + + + + Ethernet4 + 10.10.2.25/30 + + + + + + + + + + + + 40000 + DeviceInterfaceLink + OCPSCH0104001MS + Ethernet24 + OCPSCH01040GGLF + Ethernet0 + + + 40000 + DeviceInterfaceLink + OCPSCH0104002MS + Ethernet24 + OCPSCH01040GGLF + Ethernet4 + + + + + OCPSCH01040GGLF + INGRASYS-S9180-32X + + + + + + + OCPSCH01040GGLF + + + DhcpResources + + + + + NtpResources + + 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org + + + SyslogResources + + + + + ErspanDestinationIpv4 + + 2.2.2.2 + + + + + + + OCPSCH01040GGLF + INGRASYS-S9180-32X +
diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/eeprom.py b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/eeprom.py new file mode 100644 index 000000000000..d1270eeffbf6 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +############################################################################# +# Ingrasys S9180-32X +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0055/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/psuutil.py b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/psuutil.py new file mode 100644 index 000000000000..8a719388266a --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/psuutil.py @@ -0,0 +1,90 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + SYS_GPIO_DIR = "/sys/class/gpio/" + + def __init__(self): + PsuBase.__init__(self) + + + # Get sysfs attribute + def get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + MAX_PSUS = 2 + return MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + gpio_path = [ 'gpio99/value', 'gpio96/value' ] + attr_path = self.SYS_GPIO_DIR + gpio_path[index-1] + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 10) + # Check for PSU status + if (attr_value == 1): + status = 1 + + return status + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + gpio_path = [ 'gpio100/value', 'gpio97/value' ] + attr_path = self.SYS_GPIO_DIR + gpio_path[index-1] + + attr_value = self.get_attr_value(attr_path) + + if (attr_value != 'ERR'): + attr_value = int(attr_value, 10) + # Check for PSU status + if (attr_value == 1): + status = 1 + + return status + diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/sfputil.py b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/sfputil.py new file mode 100644 index 000000000000..e0f85a981182 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/plugins/sfputil.py @@ -0,0 +1,290 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 0 + PORT_END = 33 + SFP_PORT_START = 32 + PORTS_IN_BLOCK = 34 + + BASE_DIR_PATH = "/sys/class/gpio/gpio{0}/direction" + BASE_VAL_PATH = "/sys/class/gpio/gpio{0}/value" + + _port_to_eeprom_mapping = {} + port_to_i2c_mapping = { + 0: 10, + 1: 9, + 2: 12, + 3: 11, + 4: 14, + 5: 13, + 6: 16, + 7: 15, + 8: 18, + 9: 17, + 10: 20, + 11: 19, + 12: 22, + 13: 21, + 14: 24, + 15: 23, + 16: 26, + 17: 25, + 18: 28, + 19: 27, + 20: 30, + 21: 29, + 22: 32, + 23: 31, + 24: 34, + 25: 33, + 26: 36, + 27: 35, + 28: 38, + 29: 37, + 30: 40, + 31: 39, + 32: 45, + 33: 46 + } + + abs_to_gpio_mapping = { + 0: 241, + 1: 240, + 2: 243, + 3: 242, + 4: 245, + 5: 244, + 6: 247, + 7: 246, + 8: 249, + 9: 248, + 10: 251, + 11: 250, + 12: 253, + 13: 252, + 14: 255, + 15: 254, + 16: 225, + 17: 224, + 18: 227, + 19: 226, + 20: 229, + 21: 228, + 22: 231, + 23: 230, + 24: 233, + 25: 232, + 26: 235, + 27: 234, + 28: 237, + 29: 236, + 30: 239, + 31: 238, + 32: 177, + 33: 176 + } + + lpmode_to_gpio_mapping = { + 0: 161, + 1: 160, + 2: 163, + 3: 162, + 4: 165, + 5: 164, + 6: 167, + 7: 166, + 8: 169, + 9: 168, + 10: 171, + 11: 170, + 12: 173, + 13: 172, + 14: 175, + 15: 174, + 16: 145, + 17: 144, + 18: 147, + 19: 146, + 20: 149, + 21: 148, + 22: 151, + 23: 150, + 24: 153, + 25: 152, + 26: 155, + 27: 154, + 28: 157, + 29: 156, + 30: 159, + 31: 158 + } + + reset_to_gpio_mapping = { + 0: 129, + 1: 128, + 2: 131, + 3: 130, + 4: 133, + 5: 132, + 6: 135, + 7: 134, + 8: 137, + 9: 136, + 10: 139, + 11: 138, + 12: 141, + 13: 140, + 14: 143, + 15: 142, + 16: 113, + 17: 112, + 18: 115, + 19: 114, + 20: 117, + 21: 116, + 22: 119, + 23: 118, + 24: 121, + 25: 120, + 26: 123, + 27: 122, + 28: 125, + 29: 124, + 30: 127, + 31: 126 + } + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return range(0, self.PORTS_IN_BLOCK + 1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + @property + def sfp_port_start(self): + return self.SFP_PORT_START + + def __init__(self): + # Override port_to_eeprom_mapping for class initialization + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(self.port_start, self.port_end + 1): + port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x]) + self.port_to_eeprom_mapping[x] = port_eeprom_path + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + try: + abs_device_file = self.BASE_VAL_PATH.format( + self.abs_to_gpio_mapping[port_num]) + val_file = open(abs_device_file) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.sfp_port_start: # TBD + return False + + try: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + self.lpmode_to_gpio_mapping[port_num]) + val_file = open(lpmode_val_device_file) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + # content is a string, either "0" or "1" + if content == "1": + return True + + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.sfp_port_start: # TBD + return False + + try: + lpmode_val_device_file = self.BASE_VAL_PATH.format( + self.lpmode_to_gpio_mapping[port_num]) + val_file = open(lpmode_val_device_file, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + val_file.write("1" if lpmode is True else "0") + val_file.close() + + return True + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.sfp_port_start: # TBD + return False + + try: + reset_val_device_file = self.BASE_VAL_PATH.format( + self.reset_to_gpio_mapping[port_num]) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + val_file.write("1") + val_file.close() + + # Sleep 1 second to allow it to settle + time.sleep(1) + + try: + reset_val_device_file = self.BASE_VAL_PATH.format( + self.reset_to_gpio_mapping[port_num]) + val_file = open(reset_val_device_file, "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + val_file.write("0") + val_file.close() + + return True diff --git a/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/sensors.conf b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/sensors.conf new file mode 100644 index 000000000000..eb5a5b4b69f3 --- /dev/null +++ b/device/ingrasys/x86_64-ingrasys_s9180_32x-r0/sensors.conf @@ -0,0 +1,76 @@ +# libsensors configuration file +chip "i350bb-*" + ignore loc1 + +chip "jc42-*" + label temp1 "DIMM Temp" + set temp1_max 50 + set temp1_crit 85 + +bus "i2c-0" "I2C I801" +chip "tmp75-i2c-*-4f" + label temp1 "CPU Board Temp" + set temp1_max 50 + +bus "i2c-41" "i2c-7-switch (chan_id 0)" +chip "tmp75-i2c-*-48" + label temp1 "Near PSU1" + set temp1_max 50 +chip "tmp75-i2c-*-4a" + label temp1 "Rear MAC" + set temp1_max 50 +chip "tmp75-i2c-*-4b" + label temp1 "Near Port 32" + set temp1_max 50 +chip "tmp75-i2c-*-4d" + label temp1 "Near PSU2" + set temp1_max 50 +chip "lm86-i2c-*-4c" + label temp1 "Front MAC" + label temp2 "ASIC Core Temp" + set temp1_min 20 + set temp1_max 65 + set temp1_crit 70 + set temp2_min 20 + set temp2_max 70 + set temp2_crit 80 + +bus "i2c-56" "i2c-0-mux (chan_id 7)" +chip "w83795adg-*" + label in0 "0.9V" + set in0_max 0.927 + set in0_min 0.873 + label in1 "0.86V" + set in1_max 0.877 + set in1_min 0.843 + ignore in2 + ignore in3 + ignore in4 + ignore in5 + ignore in6 + ignore in7 + label in12 "2.5V" + #compute in12 (2*4*@)/10, @-(2*4*@/10) + compute in12 @/(1+(3/10)), @*(1+(3/10)) + set in12_max 2.625 + set in12_min 2.375 + # in12 and in13 are the same source + ignore in13 + ignore in14 + ignore in15 + ignore in16 + label fan1 "FANTRAY 1-A" + label fan2 "FANTRAY 1-B" + label fan3 "FANTRAY 2-A" + label fan4 "FANTRAY 2-B" + label fan5 "FANTRAY 3-A" + label fan6 "FANTRAY 3-B" + label fan7 "FANTRAY 4-A" + label fan8 "FANTRAY 4-B" + ignore temp1 + ignore temp2 + ignore temp3 + ignore temp4 + ignore temp5 + ignore temp6 + ignore intrusion0 diff --git a/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/port_config.ini b/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/port_config.ini new file mode 100644 index 000000000000..578f59203d30 --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias speed autoneg fec +Ethernet0 0 Ethernet0 25000 1 rs +Ethernet4 1 Ethernet4 25000 1 rs +Ethernet8 2 Ethernet8 25000 1 rs +Ethernet12 3 Ethernet12 25000 1 rs +Ethernet16 4 Ethernet16 25000 1 rs +Ethernet20 5 Ethernet20 25000 1 rs +Ethernet24 6 Ethernet24 25000 1 rs +Ethernet28 7 Ethernet28 25000 1 rs +Ethernet32 8 Ethernet32 25000 1 rs +Ethernet36 9 Ethernet36 25000 1 rs +Ethernet40 10 Ethernet40 25000 1 rs +Ethernet44 11 Ethernet44 25000 1 rs +Ethernet48 12 Ethernet48 25000 1 rs +Ethernet52 13 Ethernet52 25000 1 rs +Ethernet56 14 Ethernet56 25000 1 rs +Ethernet60 15 Ethernet60 25000 1 rs +Ethernet64 16 Ethernet64 25000 1 rs +Ethernet68 17 Ethernet68 25000 1 rs +Ethernet72 18 Ethernet72 25000 1 rs +Ethernet76 19 Ethernet76 25000 1 rs +Ethernet80 20 Ethernet80 25000 1 rs +Ethernet84 21 Ethernet84 25000 1 rs +Ethernet88 22 Ethernet88 25000 1 rs +Ethernet92 23 Ethernet92 25000 1 rs +Ethernet96 24 Ethernet96 25000 1 rs +Ethernet100 25 Ethernet100 25000 1 rs +Ethernet104 26 Ethernet104 25000 1 rs +Ethernet108 27 Ethernet108 25000 1 rs +Ethernet112 28 Ethernet112 25000 1 rs +Ethernet116 29 Ethernet116 25000 1 rs +Ethernet120 30 Ethernet120 25000 1 rs +Ethernet124 31 Ethernet124 25000 1 rs +Ethernet128 32 Ethernet128 25000 1 rs +Ethernet132 33 Ethernet132 25000 1 rs +Ethernet136 34 Ethernet136 25000 1 rs +Ethernet140 35 Ethernet140 25000 1 rs +Ethernet144 36 Ethernet144 25000 1 rs +Ethernet148 37 Ethernet148 25000 1 rs +Ethernet152 38 Ethernet152 25000 1 rs +Ethernet156 39 Ethernet156 25000 1 rs +Ethernet160 40 Ethernet160 25000 1 rs +Ethernet164 41 Ethernet164 25000 1 rs +Ethernet168 42 Ethernet168 25000 1 rs +Ethernet172 43 Ethernet172 25000 1 rs +Ethernet176 44 Ethernet176 25000 1 rs +Ethernet180 45 Ethernet180 25000 1 rs +Ethernet184 46 Ethernet184 25000 1 rs +Ethernet188 47 Ethernet188 25000 1 rs +Ethernet192 48,49,50,51 Ethernet192 100000 1 rs +Ethernet196 52,53,54,55 Ethernet196 100000 1 rs +Ethernet200 56,57,58,59 Ethernet200 100000 1 rs +Ethernet204 60,61,62,63 Ethernet204 100000 1 rs +Ethernet208 64,65,66,67 Ethernet208 100000 1 rs +Ethernet212 68,69,70,71 Ethernet212 100000 1 rs diff --git a/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/switch-sai.conf b/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/switch-sai.conf new file mode 100644 index 000000000000..65a02a621f03 --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/OSW1800-48x6q/switch-sai.conf @@ -0,0 +1,33 @@ +{ + "chip_list": [ + { + "id": "asic-0", + "chip_family": "Tofino", + "instance": 0, + "pcie_sysfs_prefix": "/sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0", + "pcie_domain": 0, + "pcie_bus": 5, + "pcie_fn": 0, + "pcie_dev": 0, + "pcie_int_mode": 1, + "sds_fw_path": "share/tofino_sds_fw/avago/firmware" + } + ], + "instance": 0, + "p4_program_list": [ + { + "id": "pgm-0", + "instance": 0, + "path": "switch", + "program-name": "switch", + "pd": "lib/tofinopd/switch/libpd.so", + "pd-thrift": "lib/tofinopd/switch/libpdthrift.so", + "table-config": "share/tofinopd/switch/context.json", + "tofino-bin": "share/tofinopd/switch/tofino.bin", + "switchapi": "lib/libswitchapi.so", + "switchsai": "lib/libswitchsai.so", + "agent0": "lib/platform/x86_64-wnc_osw1800-r0/libpltfm_mgr.so", + "switchapi_port_add": false + } + ] +} diff --git a/device/wnc/x86_64-wnc_osw1800-r0/fancontrol b/device/wnc/x86_64-wnc_osw1800-r0/fancontrol new file mode 100644 index 000000000000..d661bd11f1b2 --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/fancontrol @@ -0,0 +1,11 @@ +INTERVAL=10 +DEVPATH=hwmon1=devices/pci0000:00/0000:00:16.0/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.2/i2c-2/i2c-5/5-0033 hwmon2=devices/pci0000:00/0000:00:16.0/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.2/i2c-2/i2c-7/7-001e hwmon3=devices/pci0000:00/0000:00:16.0/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.2/i2c-2/i2c-7/7-004e hwmon4=devices/pci0000:00/0000:00:16.0/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.2/i2c-2/i2c-7/7-004f +DEVNAME=hwmon1=wnc_cpld3 hwmon2=tmp421 hwmon3=tmp75 hwmon4=tmp421 +FCTEMPS=hwmon1/pwm1=hwmon2/temp1_input hwmon1/pwm2=hwmon2/temp2_input hwmon1/pwm3=hwmon3/temp1_input hwmon1/pwm4=hwmon4/temp1_input hwmon1/pwm5=hwmon4/temp2_input +FCFANS=hwmon1/pwm1=hwmon1/fan1_input hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm3=hwmon1/fan3_input hwmon1/pwm4=hwmon1/fan4_input hwmon1/pwm5=hwmon1/fan5_input +MINTEMP=hwmon1/pwm1=20 hwmon1/pwm2=20 hwmon1/pwm3=20 hwmon1/pwm4=20 hwmon1/pwm5=20 +MAXTEMP=hwmon1/pwm1=50 hwmon1/pwm2=50 hwmon1/pwm3=50 hwmon1/pwm4=50 hwmon1/pwm5=50 +MINSTART=hwmon1/pwm1=32 hwmon1/pwm2=32 hwmon1/pwm3=32 hwmon1/pwm4=32 hwmon1/pwm5=32 +MINSTOP=hwmon1/pwm1=22 hwmon1/pwm2=22 hwmon1/pwm3=22 hwmon1/pwm4=22 hwmon1/pwm5=22 +MINPWM=hwmon1/pwm1=10 hwmon1/pwm2=10 hwmon1/pwm3=10 hwmon1/pwm4=10 hwmon1/pwm5=10 +MAXPWM=hwmon1/pwm1=100 hwmon1/pwm2=100 hwmon1/pwm3=100 hwmon1/pwm4=100 hwmon1/pwm5=100 diff --git a/device/wnc/x86_64-wnc_osw1800-r0/installer.conf b/device/wnc/x86_64-wnc_osw1800-r0/installer.conf new file mode 100644 index 000000000000..dfa6df22689b --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x2f8 +CONSOLE_DEV=1 +CONSOLE_SPEED=57600 diff --git a/device/wnc/x86_64-wnc_osw1800-r0/minigraph.xml b/device/wnc/x86_64-wnc_osw1800-r0/minigraph.xml new file mode 100644 index 000000000000..fc4dcee3058e --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/minigraph.xml @@ -0,0 +1,1761 @@ + + + + + + ARISTA01T0 + 10.0.0.55 + switch2 + 10.0.0.54 + 1 + 180 + 60 + + + switch2 + 10.0.0.0 + ARISTA01T2 + 10.0.0.1 + 1 + 180 + 60 + + + ARISTA02T0 + 10.0.0.57 + switch2 + 10.0.0.56 + 1 + 180 + 60 + + + switch2 + 10.0.0.2 + ARISTA02T2 + 10.0.0.3 + 1 + 180 + 60 + + + ARISTA03T0 + 10.0.0.59 + switch2 + 10.0.0.58 + 1 + 180 + 60 + + + switch2 + 10.0.0.4 + ARISTA03T2 + 10.0.0.5 + 1 + 180 + 60 + + + ARISTA04T0 + 10.0.0.61 + switch2 + 10.0.0.60 + 1 + 180 + 60 + + + switch2 + 10.0.0.6 + ARISTA04T2 + 10.0.0.7 + 1 + 180 + 60 + + + ARISTA05T0 + 10.0.0.63 + switch2 + 10.0.0.62 + 1 + 180 + 60 + + + switch2 + 10.0.0.8 + ARISTA05T2 + 10.0.0.9 + 1 + 180 + 60 + + + ARISTA06T0 + 10.0.0.65 + switch2 + 10.0.0.64 + 1 + 180 + 60 + + + switch2 + 10.0.0.10 + ARISTA06T2 + 10.0.0.11 + 1 + 180 + 60 + + + ARISTA07T0 + 10.0.0.67 + switch2 + 10.0.0.66 + 1 + 180 + 60 + + + switch2 + 10.0.0.12 + ARISTA07T2 + 10.0.0.13 + 1 + 180 + 60 + + + ARISTA08T0 + 10.0.0.69 + switch2 + 10.0.0.68 + 1 + 180 + 60 + + + switch2 + 10.0.0.14 + ARISTA08T2 + 10.0.0.15 + 1 + 180 + 60 + + + ARISTA09T0 + 10.0.0.71 + switch2 + 10.0.0.70 + 1 + 180 + 60 + + + switch2 + 10.0.0.16 + ARISTA09T2 + 10.0.0.17 + 1 + 180 + 60 + + + ARISTA10T0 + 10.0.0.73 + switch2 + 10.0.0.72 + 1 + 180 + 60 + + + switch2 + 10.0.0.18 + ARISTA10T2 + 10.0.0.19 + 1 + 180 + 60 + + + ARISTA11T0 + 10.0.0.75 + switch2 + 10.0.0.74 + 1 + 180 + 60 + + + switch2 + 10.0.0.20 + ARISTA11T2 + 10.0.0.21 + 1 + 180 + 60 + + + ARISTA12T0 + 10.0.0.77 + switch2 + 10.0.0.76 + 1 + 180 + 60 + + + switch2 + 10.0.0.22 + ARISTA12T2 + 10.0.0.23 + 1 + 180 + 60 + + + ARISTA13T0 + 10.0.0.79 + switch2 + 10.0.0.78 + 1 + 180 + 60 + + + switch2 + 10.0.0.24 + ARISTA13T2 + 10.0.0.25 + 1 + 180 + 60 + + + ARISTA14T0 + 10.0.0.81 + switch2 + 10.0.0.80 + 1 + 180 + 60 + + + switch2 + 10.0.0.26 + ARISTA14T2 + 10.0.0.27 + 1 + 180 + 60 + + + ARISTA15T0 + 10.0.0.83 + switch2 + 10.0.0.82 + 1 + 180 + 60 + + + switch2 + 10.0.0.28 + ARISTA15T2 + 10.0.0.29 + 1 + 180 + 60 + + + ARISTA16T0 + 10.0.0.85 + switch2 + 10.0.0.84 + 1 + 180 + 60 + + + switch2 + 10.0.0.30 + ARISTA16T2 + 10.0.0.31 + 1 + 180 + 60 + + + ARISTA17T0 + 10.0.0.87 + switch2 + 10.0.0.86 + 1 + 180 + 60 + + + switch2 + 10.0.0.32 + ARISTA17T2 + 10.0.0.33 + 1 + 180 + 60 + + + ARISTA18T0 + 10.0.0.89 + switch2 + 10.0.0.88 + 1 + 180 + 60 + + + switch2 + 10.0.0.34 + ARISTA18T2 + 10.0.0.35 + 1 + 180 + 60 + + + ARISTA19T0 + 10.0.0.91 + switch2 + 10.0.0.90 + 1 + 180 + 60 + + + switch2 + 10.0.0.36 + ARISTA19T2 + 10.0.0.37 + 1 + 180 + 60 + + + ARISTA20T0 + 10.0.0.93 + switch2 + 10.0.0.92 + 1 + 180 + 60 + + + switch2 + 10.0.0.38 + ARISTA20T2 + 10.0.0.39 + 1 + 180 + 60 + + + ARISTA21T0 + 10.0.0.95 + switch2 + 10.0.0.94 + 1 + 180 + 60 + + + switch2 + 10.0.0.40 + ARISTA21T2 + 10.0.0.41 + 1 + 180 + 60 + + + ARISTA22T0 + 10.0.0.97 + switch2 + 10.0.0.96 + 1 + 180 + 60 + + + switch2 + 10.0.0.42 + ARISTA22T2 + 10.0.0.43 + 1 + 180 + 60 + + + ARISTA23T0 + 10.0.0.99 + switch2 + 10.0.0.98 + 1 + 180 + 60 + + + switch2 + 10.0.0.44 + ARISTA23T2 + 10.0.0.45 + 1 + 180 + 60 + + + ARISTA24T0 + 10.0.0.101 + switch2 + 10.0.0.100 + 1 + 180 + 60 + + + switch2 + 10.0.0.46 + ARISTA24T2 + 10.0.0.47 + 1 + 180 + 60 + + + ARISTA25T0 + 10.0.0.103 + switch2 + 10.0.0.102 + 1 + 180 + 60 + + + switch2 + 10.0.0.48 + ARISTA25T2 + 10.0.0.49 + 1 + 180 + 60 + + + ARISTA26T0 + 10.0.0.105 + switch2 + 10.0.0.104 + 1 + 180 + 60 + + + switch2 + 10.0.0.50 + ARISTA26T2 + 10.0.0.51 + 1 + 180 + 60 + + + ARISTA27T0 + 10.0.0.107 + switch2 + 10.0.0.106 + 1 + 180 + 60 + + + switch2 + 10.0.0.52 + ARISTA27T2 + 10.0.0.53 + 1 + 180 + 60 + + + + + 65100 + switch2 + + +
10.0.0.55
+ + +
+ +
10.0.0.1
+ + +
+ +
10.0.0.57
+ + +
+ +
10.0.0.3
+ + +
+ +
10.0.0.59
+ + +
+ +
10.0.0.5
+ + +
+ +
10.0.0.61
+ + +
+ +
10.0.0.7
+ + +
+ +
10.0.0.63
+ + +
+ +
10.0.0.9
+ + +
+ +
10.0.0.65
+ + +
+ +
10.0.0.11
+ + +
+ +
10.0.0.67
+ + +
+ +
10.0.0.13
+ + +
+ +
10.0.0.69
+ + +
+ +
10.0.0.15
+ + +
+ +
10.0.0.71
+ + +
+ +
10.0.0.17
+ + +
+ +
10.0.0.73
+ + +
+ +
10.0.0.19
+ + +
+ +
10.0.0.75
+ + +
+ +
10.0.0.21
+ + +
+ +
10.0.0.77
+ + +
+ +
10.0.0.23
+ + +
+ +
10.0.0.79
+ + +
+ +
10.0.0.25
+ + +
+ +
10.0.0.81
+ + +
+ +
10.0.0.27
+ + +
+ +
10.0.0.83
+ + +
+ +
10.0.0.29
+ + +
+ +
10.0.0.85
+ + +
+ +
10.0.0.31
+ + +
+ +
10.0.0.87
+ + +
+ +
10.0.0.33
+ + +
+ +
10.0.0.89
+ + +
+ +
10.0.0.35
+ + +
+ +
10.0.0.91
+ + +
+ +
10.0.0.37
+ + +
+ +
10.0.0.93
+ + +
+ +
10.0.0.39
+ + +
+ +
10.0.0.95
+ + +
+ +
10.0.0.41
+ + +
+ +
10.0.0.97
+ + +
+ +
10.0.0.43
+ + +
+ +
10.0.0.99
+ + +
+ +
10.0.0.45
+ + +
+ +
10.0.0.101
+ + +
+ +
10.0.0.47
+ + +
+ +
10.0.0.103
+ + +
+ +
10.0.0.49
+ + +
+ +
10.0.0.105
+ + +
+ +
10.0.0.51
+ + +
+ +
10.0.0.107
+ + +
+ +
10.0.0.53
+ + +
+
+ +
+ + 64001 + ARISTA01T0 + + + + 65200 + ARISTA01T2 + + + + 64002 + ARISTA02T0 + + + + 65200 + ARISTA02T2 + + + + 64003 + ARISTA03T0 + + + + 65200 + ARISTA03T2 + + + + 64004 + ARISTA04T0 + + + + 65200 + ARISTA04T2 + + + + 64005 + ARISTA05T0 + + + + 65200 + ARISTA05T2 + + + + 64006 + ARISTA06T0 + + + + 65200 + ARISTA06T2 + + + + 64007 + ARISTA07T0 + + + + 65200 + ARISTA07T2 + + + + 64008 + ARISTA08T0 + + + + 65200 + ARISTA08T2 + + + + 64009 + ARISTA09T0 + + + + 65200 + ARISTA09T2 + + + + 64010 + ARISTA10T0 + + + + 65200 + ARISTA10T2 + + + + 64011 + ARISTA11T0 + + + + 65200 + ARISTA11T2 + + + + 64012 + ARISTA12T0 + + + + 65200 + ARISTA12T2 + + + + 64013 + ARISTA13T0 + + + + 65200 + ARISTA13T2 + + + + 64014 + ARISTA14T0 + + + + 65200 + ARISTA14T2 + + + + 64015 + ARISTA15T0 + + + + 65200 + ARISTA15T2 + + + + 64016 + ARISTA16T0 + + + + 65200 + ARISTA16T2 + + + + 64016 + ARISTA17T0 + + + + 65200 + ARISTA17T2 + + + + 64016 + ARISTA18T0 + + + + 65200 + ARISTA18T2 + + + + 64016 + ARISTA19T0 + + + + 65200 + ARISTA19T2 + + + + 64016 + ARISTA20T0 + + + + 65200 + ARISTA20T2 + + + + 64016 + ARISTA21T0 + + + + 65200 + ARISTA21T2 + + + + 64016 + ARISTA22T0 + + + + 65200 + ARISTA22T2 + + + + 64016 + ARISTA23T0 + + + + 65200 + ARISTA23T2 + + + + 64016 + ARISTA24T0 + + + + 65200 + ARISTA24T2 + + + + 64016 + ARISTA25T0 + + + + 65200 + ARISTA25T2 + + + + 64016 + ARISTA26T0 + + + + 65200 + ARISTA26T2 + + + + 64016 + ARISTA27T0 + + + + 65200 + ARISTA27T2 + + +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + + + + + + switch2 + + + + + + Ethernet0 + 10.0.0.0/31 + + + + Ethernet4 + 10.0.0.2/31 + + + + Ethernet8 + 10.0.0.4/31 + + + + Ethernet12 + 10.0.0.6/31 + + + + Ethernet16 + 10.0.0.8/31 + + + + Ethernet20 + 10.0.0.10/31 + + + + Ethernet24 + 10.0.0.12/31 + + + + Ethernet28 + 10.0.0.14/31 + + + + Ethernet32 + 10.0.0.16/31 + + + + Ethernet36 + 10.0.0.18/31 + + + + Ethernet40 + 10.0.0.20/31 + + + + Ethernet44 + 10.0.0.22/31 + + + + Ethernet48 + 10.0.0.24/31 + + + + Ethernet52 + 10.0.0.26/31 + + + + Ethernet56 + 10.0.0.28/31 + + + + Ethernet60 + 10.0.0.30/31 + + + + Ethernet64 + 10.0.0.32/31 + + + + Ethernet68 + 10.0.0.34/31 + + + + Ethernet72 + 10.0.0.36/31 + + + + Ethernet76 + 10.0.0.38/31 + + + + Ethernet80 + 10.0.0.40/31 + + + + Ethernet84 + 10.0.0.42/31 + + + + Ethernet88 + 10.0.0.44/31 + + + + Ethernet92 + 10.0.0.46/31 + + + + Ethernet96 + 10.0.0.48/31 + + + + Ethernet100 + 10.0.0.50/31 + + + + Ethernet104 + 10.0.0.52/31 + + + + Ethernet108 + 10.0.0.54/31 + + + + Ethernet112 + 10.0.0.56/31 + + + + Ethernet116 + 10.0.0.58/31 + + + + Ethernet120 + 10.0.0.60/31 + + + + Ethernet124 + 10.0.0.62/31 + + + + Ethernet128 + 10.0.0.64/31 + + + + Ethernet132 + 10.0.0.66/31 + + + + Ethernet136 + 10.0.0.68/31 + + + + Ethernet140 + 10.0.0.70/31 + + + + Ethernet144 + 10.0.0.72/31 + + + + Ethernet148 + 10.0.0.74/31 + + + + Ethernet152 + 10.0.0.76/31 + + + + Ethernet156 + 10.0.0.78/31 + + + + Ethernet160 + 10.0.0.80/31 + + + + Ethernet164 + 10.0.0.82/31 + + + + Ethernet168 + 10.0.0.84/31 + + + + Ethernet172 + 10.0.0.86/31 + + + + Ethernet176 + 10.0.0.88/31 + + + + Ethernet180 + 10.0.0.90/31 + + + + Ethernet184 + 10.0.0.92/31 + + + + Ethernet188 + 10.0.0.94/31 + + + + Ethernet192 + 10.0.0.96/31 + + + + Ethernet196 + 10.0.0.98/31 + + + + Ethernet200 + 10.0.0.100/31 + + + + Ethernet204 + 10.0.0.102/31 + + + + Ethernet208 + 10.0.0.104/31 + + + + Ethernet212 + 10.0.0.106/31 + + + + + + + + + + + + DeviceInterfaceLink + switch2 + Ethernet0 + ARISTA01T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet4 + ARISTA02T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet8 + ARISTA03T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet12 + ARISTA04T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet16 + ARISTA05T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet20 + ARISTA06T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet24 + ARISTA07T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet28 + ARISTA08T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet32 + ARISTA09T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet36 + ARISTA10T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet40 + ARISTA11T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet44 + ARISTA12T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet48 + ARISTA13T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet52 + ARISTA14T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet56 + ARISTA15T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet60 + ARISTA16T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet64 + ARISTA17T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet68 + ARISTA18T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet72 + ARISTA19T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet76 + ARISTA20T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet80 + ARISTA21T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet84 + ARISTA22T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet88 + ARISTA23T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet92 + ARISTA24T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet96 + ARISTA25T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet100 + ARISTA26T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet104 + ARISTA27T2 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet108 + ARISTA01T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet112 + ARISTA02T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet116 + ARISTA03T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet120 + ARISTA04T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet124 + ARISTA05T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet128 + ARISTA06T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet132 + ARISTA07T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet136 + ARISTA08T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet140 + ARISTA09T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet144 + ARISTA10T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet148 + ARISTA11T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet152 + ARISTA12T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet156 + ARISTA13T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet160 + ARISTA14T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet164 + ARISTA15T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet168 + ARISTA16T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet172 + ARISTA17T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet176 + ARISTA18T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet180 + ARISTA19T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet184 + ARISTA20T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet188 + ARISTA21T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet192 + ARISTA22T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet196 + ARISTA23T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet200 + ARISTA24T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet204 + ARISTA25T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet208 + ARISTA26T0 + Ethernet1 + + + DeviceInterfaceLink + switch2 + Ethernet212 + ARISTA27T0 + Ethernet1 + + + + + switch2 + OSW1800-48x6q + + + + + + + switch2 + + + DhcpResources + + 192.168.1.111 + + + NtpResources + + 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org + + + SyslogResources + + 192.0.0.1 + + + ErspanDestinationIpv4 + + 2.2.2.2 + + + + + + + switch2 + OSW1800-48x6q +
diff --git a/device/wnc/x86_64-wnc_osw1800-r0/plugins/eeprom.py b/device/wnc/x86_64-wnc_osw1800-r0/plugins/eeprom.py new file mode 100644 index 000000000000..a073374794fa --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-8/8-0052/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) + diff --git a/device/wnc/x86_64-wnc_osw1800-r0/plugins/psuutil.py b/device/wnc/x86_64-wnc_osw1800-r0/plugins/psuutil.py new file mode 100644 index 000000000000..e62159c8a8cc --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/plugins/psuutil.py @@ -0,0 +1,64 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + def get_num_psus(self): + return 2 + + def get_psu_status(self, index): + if index == 1: + psu_path = "/sys/bus/i2c/devices/6-0050/eeprom" + elif index == 2: + psu_path = "/sys/bus/i2c/devices/6-0051/eeprom" + else: + return False + + try: + data = open(psu_path, "rb") + except IOError: + return False + + result = int(data.read(1).encode("hex"), 16) + data.close() + + if result != 255 and result != 0: + return True + else: + return False + + def get_psu_presence(self, index): + if index == 1: + psu_path = "/sys/bus/i2c/devices/6-0050/eeprom" + elif index == 2: + psu_path = "/sys/bus/i2c/devices/6-0051/eeprom" + else: + return False + + try: + data = open(psu_path, "rb") + except IOError: + return False + + result = int(data.read(1).encode("hex"), 16) + data.close() + + if result != 255 and result != 0: + return True + else: + return False diff --git a/device/wnc/x86_64-wnc_osw1800-r0/plugins/sfputil.py b/device/wnc/x86_64-wnc_osw1800-r0/plugins/sfputil.py new file mode 100644 index 000000000000..1c1e86bc5d6e --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/plugins/sfputil.py @@ -0,0 +1,205 @@ +#! /usr/bin/python +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + from sonic_sfp.sfputilbase import SfpUtilBase + import sys + sys.path.append('/usr/lib/python2.7/dist-packages/sonic_sfp/') + from sff8472 import sff8472InterfaceId + from sff8472 import sff8472Dom + from sff8436 import sff8436InterfaceId + from sff8436 import sff8436Dom +except ImportError, e: + raise ImportError("%s - required module not found" % str(e)) + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 0 + PORT_END = 53 + PORTS_IN_BLOCK = 54 + + EEPROM_OFFSET = 11 + + _port_to_eeprom_mapping = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self): + return range(self.PORT_START + 48, self.PORTS_IN_BLOCK) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + def __init__(self): + eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(0, self.port_end + 1): + self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET) + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + bit_mask = port_num % 8 + + if port_num <= 7: + presence_path = "/sys/bus/i2c/devices/3-0031/sfp_mod_abs1" + elif 8 <= port_num and port_num <= 15: + presence_path = "/sys/bus/i2c/devices/3-0031/sfp_mod_abs2" + elif 16 <= port_num and port_num <= 23: + presence_path = "/sys/bus/i2c/devices/3-0031/sfp_mod_abs3" + elif 24 <= port_num and port_num <= 27: + presence_path = "/sys/bus/i2c/devices/3-0031/sfp_mod_abs4" + elif 28 <= port_num and port_num <= 31: + presence_path = "/sys/bus/i2c/devices/4-0032/sfp_mod_abs1" + bit_mask = bit_mask - 4 + elif 32 <= port_num and port_num <= 39: + presence_path = "/sys/bus/i2c/devices/4-0032/sfp_mod_abs2" + elif 40 <= port_num and port_num <= 47: + presence_path = "/sys/bus/i2c/devices/4-0032/sfp_mod_abs3" + elif 48 <= port_num and port_num <= 71: + presence_path = "/sys/bus/i2c/devices/4-0032/qsfp_modprs" + else: + return False + + try: + reg_file = open(presence_path, "rb") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + reg_file.close() + + if reg_value & (1 << bit_mask) == 0: + return True + else: + return False + + def get_low_power_mode(self, port_num): + if port_num in self.qsfp_ports: + bit_mask = port_num % 8 + else: + return False + + try: + reg_file = open("/sys/bus/i2c/devices/4-0032/qsfp_lpmode") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + reg_file.close() + + if reg_value & (1 << bit_mask) == 0: + return False + + return True + + def set_low_power_mode(self, port_num, lpmode): + if port_num in self.qsfp_ports: + bit_mask = port_num % 8 + else: + return False + + try: + reg_file = open("/sys/bus/i2c/devices/4-0032/qsfp_lpmode", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + + if lpmode is True: + reg_value = reg_value | (1 << bit_mask) + else: + reg_value = reg_value & ~(1 << bit_mask) + + reg_file.seek(0) + reg_file.write(str(reg_value)) + reg_file.close() + + return True + + def reset(self, port_num): + if port_num in self.qsfp_ports: + bit_mask = (port_num % 8) + 2 + else: + return False + + try: + reg_file = open("/sys/bus/i2c/devices/4-0032/reset_control", "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = reg_file.readline().rstrip() + reg_value = int(content, 16) + reg_value = reg_value & ~(1 << bit_mask) + + reg_file.seek(0) + reg_file.write(str(reg_value)) + reg_file.close() + + time.sleep(1) + + try: + reg_file = open("/sys/bus/i2c/devices/4-0032/reset_control", "w") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = reg_value | (1 << bit_mask) + reg_file.seek(0) + reg_file.write(str(reg_value)) + reg_file.close() + + return True + + def get_eeprom_dict(self, port_num): + if not self.get_presence(port_num): + return None + + sfp_data = {} + + eeprom_ifraw = self.get_eeprom_raw(port_num) + eeprom_domraw = self.get_eeprom_dom_raw(port_num) + + if eeprom_ifraw is None: + return None + + if port_num in self.qsfp_ports: + sfpi_obj = sff8436InterfaceId(eeprom_ifraw) + if sfpi_obj is not None: + sfp_data['interface'] = sfpi_obj.get_data_pretty() + + sfpd_obj = sff8436Dom(eeprom_ifraw) + if sfpd_obj is not None: + sfp_data['dom'] = sfpd_obj.get_data_pretty() + return sfp_data + + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + if sfpi_obj is not None: + sfp_data['interface'] = sfpi_obj.get_data_pretty() + cal_type = sfpi_obj.get_calibration_type() + + if eeprom_domraw is not None: + sfpd_obj = sff8472Dom(eeprom_domraw, cal_type) + if sfpd_obj is not None: + sfp_data['dom'] = sfpd_obj.get_data_pretty() + + return sfp_data diff --git a/device/wnc/x86_64-wnc_osw1800-r0/sensors.conf b/device/wnc/x86_64-wnc_osw1800-r0/sensors.conf new file mode 100644 index 000000000000..d91945ff722b --- /dev/null +++ b/device/wnc/x86_64-wnc_osw1800-r0/sensors.conf @@ -0,0 +1,33 @@ +# libsensors configuration filei +# -------------------------------------------------- +# + +bus "i2c-7" "i2c-2-mux" +chip "tmp421-i2c-7-1E" + label temp1 "ts1" + set temp1_max 50 + set temp1_max_hyst 25 + label temp2 "ts4" + set temp2_max 50 + set temp2_max_hyst 25 + +chip "tmp75-i2c-7-4E" + label temp1 "ts3" + set temp1_max 50 + set temp1_max_hyst 25 + +chip "tmp421-i2c-7-4F" + label temp1 "ts2" + set temp1_max 50 + set temp1_max_hyst 25 + label temp2 "ts5" + set temp2_max 50 + set temp2_max_hyst 25 + +bus "i2c-5" "i2c-2-mux" +chip "wnc_cpld3-i2c-5-33" + label fan1 "fan1" + label fan2 "fan2" + label fan3 "fan3" + label fan4 "fan4" + label fan5 "fan5" diff --git a/dockers/docker-orchagent-bfn b/dockers/docker-orchagent-bfn new file mode 120000 index 000000000000..8d52609c56e5 --- /dev/null +++ b/dockers/docker-orchagent-bfn @@ -0,0 +1 @@ +docker-orchagent \ No newline at end of file diff --git a/dockers/docker-orchagent/orchagent.sh b/dockers/docker-orchagent/orchagent.sh index 027c6d52a2fe..af9e5b0766ab 100755 --- a/dockers/docker-orchagent/orchagent.sh +++ b/dockers/docker-orchagent/orchagent.sh @@ -20,6 +20,8 @@ elif [ "$platform" == "cavium" ]; then ORCHAGENT_ARGS+="-m $MAC_ADDRESS" elif [ "$platform" == "nephos" ]; then ORCHAGENT_ARGS+="-m $MAC_ADDRESS" +elif [ "$platform" == "barefoot" ]; then + ORCHAGENT_ARGS+="-m $MAC_ADDRESS" fi exec /usr/bin/orchagent ${ORCHAGENT_ARGS} diff --git a/dockers/docker-saiserver-bfn/Dockerfile b/dockers/docker-saiserver-bfn/Dockerfile new file mode 100755 index 000000000000..427a551e0096 --- /dev/null +++ b/dockers/docker-saiserver-bfn/Dockerfile @@ -0,0 +1,38 @@ +FROM docker-base + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +COPY ["deps/applibs_*.deb", "/deps/applibs-dev_*.deb", "/deps/sx-complib_*.deb", "/deps/sxd-libs_*.deb", "/deps/sx-scew_*.deb", "/deps/sx-examples_*.deb", "/deps/sx-gen-utils_*.deb", "/deps/python-sdk-api_*.deb", "/deps/iproute2_*.deb", "/deps/mlnx-sai_*.deb", "/deps/libthrift-0.9.3_*.deb", "/deps/libnl-3-200_*.deb", "/deps/libnl-genl-3-200_*.deb", "/deps/libnl-route-3-200_*.deb", "/deps/"] + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; \ + dpkg_apt /deps/applibs_*.deb \ + && dpkg_apt /deps/applibs-dev_*.deb \ + && dpkg_apt /deps/sx-complib_*.deb \ + && dpkg_apt /deps/sxd-libs_*.deb \ + && dpkg_apt /deps/sx-scew_*.deb \ + && dpkg_apt /deps/sx-examples_*.deb \ + && dpkg_apt /deps/sx-gen-utils_*.deb \ + && dpkg_apt /deps/python-sdk-api_*.deb \ + && dpkg_apt /deps/iproute2_*.deb \ + && dpkg_apt /deps/mlnx-sai_*.deb \ + && dpkg_apt /deps/libthrift-0.9.3_*.deb \ + && dpkg_apt /deps/libnl-3-200_*.deb \ + && dpkg_apt /deps/libnl-genl-3-200_*.deb \ + && dpkg_apt /deps/libnl-route-3-200_*.deb + +COPY ["deps/saiserver", "start.sh", "/usr/bin/"] + +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +COPY ["profile.ini", "portmap.ini", "/etc/sai/"] + + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /deps + +ENTRYPOINT ["/usr/bin/supervisord"] + diff --git a/dockers/docker-saiserver-bfn/portmap.ini b/dockers/docker-saiserver-bfn/portmap.ini new file mode 100644 index 000000000000..4d3be08ce5f8 --- /dev/null +++ b/dockers/docker-saiserver-bfn/portmap.ini @@ -0,0 +1,33 @@ +# alias lanes +Ethernet1 0,1,2,3 +Ethernet2 4,5,6,7 +Ethernet3 8,9,10,11 +Ethernet4 12,13,14,15 +Ethernet5 16,17,18,19 +Ethernet6 20,21,22,23 +Ethernet7 24,25,26,27 +Ethernet8 28,29,30,31 +Ethernet9 32,33,34,35 +Ethernet10 36,37,38,39 +Ethernet11 40,41,42,43 +Ethernet12 44,45,46,47 +Ethernet13 48,49,50,51 +Ethernet14 52,53,54,55 +Ethernet15 56,57,58,59 +Ethernet16 60,61,62,63 +Ethernet17 64,65,66,67 +Ethernet18 68,69,70,71 +Ethernet19 72,73,74,75 +Ethernet20 76,77,78,79 +Ethernet21 80,81,82,83 +Ethernet22 84,85,86,87 +Ethernet23 88,89,90,91 +Ethernet24 92,93,94,95 +Ethernet25 96,97,98,99 +Ethernet26 100,101,102,103 +Ethernet27 104,105,106,107 +Ethernet28 108,109,110,111 +Ethernet29 112,113,114,115 +Ethernet30 116,117,118,119 +Ethernet31 120,121,122,123 +Ethernet32 124,125,126,127 \ No newline at end of file diff --git a/dockers/docker-saiserver-bfn/profile.ini b/dockers/docker-saiserver-bfn/profile.ini new file mode 100644 index 000000000000..b20b2c6f0e06 --- /dev/null +++ b/dockers/docker-saiserver-bfn/profile.ini @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sai_tofino.xml diff --git a/dockers/docker-saiserver-bfn/sai_tofino.xml b/dockers/docker-saiserver-bfn/sai_tofino.xml new file mode 100644 index 000000000000..139597f9cb07 --- /dev/null +++ b/dockers/docker-saiserver-bfn/sai_tofino.xml @@ -0,0 +1,2 @@ + + diff --git a/dockers/docker-saiserver-bfn/start.sh b/dockers/docker-saiserver-bfn/start.sh new file mode 100755 index 000000000000..16457d13e03a --- /dev/null +++ b/dockers/docker-saiserver-bfn/start.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +supervisorctl start saiserver + diff --git a/dockers/docker-saiserver-bfn/supervisord.conf b/dockers/docker-saiserver-bfn/supervisord.conf new file mode 100644 index 000000000000..e09ac3cbb449 --- /dev/null +++ b/dockers/docker-saiserver-bfn/supervisord.conf @@ -0,0 +1,29 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[program:start.sh] +command=/usr/bin/start.sh +priority=1 +autostart=true +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n +priority=2 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:saiserver] +command=/usr/bin/saiserver -p /etc/sai/profile.ini -f /etc/sai/portmap.ini +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + diff --git a/files/build_templates/buffers_config.j2 b/files/build_templates/buffers_config.j2 index 23503017f179..b4d260092c43 100644 --- a/files/build_templates/buffers_config.j2 +++ b/files/build_templates/buffers_config.j2 @@ -125,7 +125,7 @@ def {% endif %} {%- if defs.generate_pg_profils is defined %} -{{ defs.generate_pg_profils }}, +{{ defs.generate_pg_profils(port_names_active) }} {% else %} "BUFFER_PG": { "{{ port_names_active }}|0-1": { diff --git a/files/image_config/interfaces/interfaces-config.sh b/files/image_config/interfaces/interfaces-config.sh index a702917419ca..b5b06904c508 100755 --- a/files/image_config/interfaces/interfaces-config.sh +++ b/files/image_config/interfaces/interfaces-config.sh @@ -4,6 +4,17 @@ ifdown --force eth0 sonic-cfggen -d -t /usr/share/sonic/templates/interfaces.j2 > /etc/network/interfaces +# Add usb0 interface for bfn platforms +platform=$(sonic-cfggen -H -v 'DEVICE_METADATA["localhost"]["platform"]') +if [[ "$platform" == "x86_64-accton_wedge100bf_32x-r0" || "$platform" == "x86_64-accton_wedge100bf_65x-r0" ]]; then +cat <<'EOF' >> /etc/network/interfaces +# BMC interface +auto usb0 +iface usb0 inet6 auto +up ifconfig usb0 txqueuelen 64 +EOF +fi + [ -f /var/run/dhclient.eth0.pid ] && kill `cat /var/run/dhclient.eth0.pid` && rm -f /var/run/dhclient.eth0.pid systemctl restart networking diff --git a/files/image_config/interfaces/interfaces.j2 b/files/image_config/interfaces/interfaces.j2 index 71e2d2514fa2..924ff54af308 100644 --- a/files/image_config/interfaces/interfaces.j2 +++ b/files/image_config/interfaces/interfaces.j2 @@ -18,6 +18,7 @@ iface lo {{ 'inet' if prefix | ipv4 else 'inet6' }} static {% endfor %} {% endblock loopback %} {% block mgmt_interface %} + # The management network interface auto eth0 {% if MGMT_INTERFACE %} diff --git a/platform/barefoot/bfn-platform-ingrasys.mk b/platform/barefoot/bfn-platform-ingrasys.mk new file mode 100644 index 000000000000..a85d69baab79 --- /dev/null +++ b/platform/barefoot/bfn-platform-ingrasys.mk @@ -0,0 +1,5 @@ +BFN_INGRASYS_PLATFORM = bfnplatform-ingrasys_1.0.0_amd64.deb +$(BFN_INGRASYS_PLATFORM)_URL = "https://github.com/Ingrasys-sonic/packages/raw/master/lib/bfnplatform-ingrasys_1.0.0_amd64.deb" + +SONIC_ONLINE_DEBS += $(BFN_INGRASYS_PLATFORM) # $(BFN_SAI_DEV) +$(BFN_SAI_DEV)_DEPENDS += $(BFN_INGRASYS_PLATFORM) diff --git a/platform/barefoot/bfn-platform-wnc.mk b/platform/barefoot/bfn-platform-wnc.mk new file mode 100644 index 000000000000..e2f45d35b2b8 --- /dev/null +++ b/platform/barefoot/bfn-platform-wnc.mk @@ -0,0 +1,5 @@ +WNC_OSW1800_PLATFORM = bfnplatformwnc_1.0.0_amd64.deb +$(WNC_OSW1800_PLATFORM)_URL = "https://github.com/YaoTien/download/raw/master/sonic/sde/7_0_0_18/bfnplatformwnc_1.0.0_amd64.deb" + +SONIC_ONLINE_DEBS += $(WNC_OSW1800_PLATFORM) # $(BFN_SAI_DEV) +$(BFN_SAI_DEV)_DEPENDS += $(WNC_OSW1800_PLATFORM) diff --git a/platform/barefoot/bfn-platform.mk b/platform/barefoot/bfn-platform.mk new file mode 100644 index 000000000000..6f1e6e302961 --- /dev/null +++ b/platform/barefoot/bfn-platform.mk @@ -0,0 +1,5 @@ +BFN_PLATFORM = bfnplatform_1.0.0_amd64.deb +$(BFN_PLATFORM)_URL = "https://github.com/barefootnetworks/sonic-release-pkgs/raw/rel_8_2/bfnplatform_1.0.0_amd64.deb" + +SONIC_ONLINE_DEBS += $(BFN_PLATFORM) # $(BFN_SAI_DEV) +$(BFN_SAI_DEV)_DEPENDS += $(BFN_PLATFORM) diff --git a/platform/barefoot/bfn-sai.mk b/platform/barefoot/bfn-sai.mk new file mode 100644 index 000000000000..7e507d15a9fe --- /dev/null +++ b/platform/barefoot/bfn-sai.mk @@ -0,0 +1,5 @@ +BFN_SAI = bfnsdk_1.0.0_amd64.deb +$(BFN_SAI)_URL = "https://github.com/barefootnetworks/sonic-release-pkgs/raw/rel_8_2/bfnsdk_1.0.0_amd64.deb" + +SONIC_ONLINE_DEBS += $(BFN_SAI) # $(BFN_SAI_DEV) +$(BFN_SAI_DEV)_DEPENDS += $(BFN_SAI) diff --git a/platform/barefoot/docker-orchagent-bfn.mk b/platform/barefoot/docker-orchagent-bfn.mk new file mode 100644 index 000000000000..f13fa63d6f2a --- /dev/null +++ b/platform/barefoot/docker-orchagent-bfn.mk @@ -0,0 +1,19 @@ +# docker image for orchagent + +DOCKER_ORCHAGENT_BFN = docker-orchagent-bfn.gz +$(DOCKER_ORCHAGENT_BFN)_PATH = $(DOCKERS_PATH)/docker-orchagent +$(DOCKER_ORCHAGENT_BFN)_DEPENDS += $(SWSS) $(REDIS_TOOLS) +$(DOCKER_ORCHAGENT_BFN)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_BFN) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_ORCHAGENT_BFN) + +$(DOCKER_ORCHAGENT_BFN)_CONTAINER_NAME = swss +$(DOCKER_ORCHAGENT_BFN)_RUN_OPT += --net=host --privileged -t +$(DOCKER_ORCHAGENT_BFN)_RUN_OPT += -v /etc/network/interfaces:/etc/network/interfaces:ro +$(DOCKER_ORCHAGENT_BFN)_RUN_OPT += -v /etc/network/interfaces.d/:/etc/network/interfaces.d/:ro +$(DOCKER_ORCHAGENT_BFN)_RUN_OPT += -v /host/machine.conf:/host/machine.conf:ro +$(DOCKER_ORCHAGENT_BFN)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_ORCHAGENT_BFN)_RUN_OPT += -v /var/log/swss:/var/log/swss:rw + +$(DOCKER_ORCHAGENT_BFN)_BASE_IMAGE_FILES += swssloglevel:/usr/bin/swssloglevel +$(DOCKER_ORCHAGENT_BFN)_FILES += $(ARP_UPDATE_SCRIPT) diff --git a/platform/barefoot/docker-ptf-bfn.mk b/platform/barefoot/docker-ptf-bfn.mk new file mode 100644 index 000000000000..573e9cd9cffa --- /dev/null +++ b/platform/barefoot/docker-ptf-bfn.mk @@ -0,0 +1,5 @@ +# docker image for docker-ptf + +DOCKER_PTF_BFN = docker-ptf-bfn.gz +$(DOCKER_PTF_BFN)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift +$(DOCKER_PTF_BFN)_LOAD_DOCKERS += $(DOCKER_PTF) diff --git a/platform/barefoot/docker-syncd-bfn-rpc.mk b/platform/barefoot/docker-syncd-bfn-rpc.mk new file mode 100644 index 000000000000..61f5570c1612 --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn-rpc.mk @@ -0,0 +1,15 @@ +# docker image for syncd with rpc + +DOCKER_SYNCD_BFN_RPC = docker-syncd-bfn-rpc.gz +$(DOCKER_SYNCD_BFN_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-bfn-rpc +$(DOCKER_SYNCD_BFN_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) +$(DOCKER_SYNCD_BFN_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_BFN) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_BFN_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_BFN_RPC) +endif + +$(DOCKER_SYNCD_BFN_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_BFN_RPC)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_BFN_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_BFN_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/platform/barefoot/docker-syncd-bfn-rpc/Dockerfile.j2 b/platform/barefoot/docker-syncd-bfn-rpc/Dockerfile.j2 new file mode 100644 index 000000000000..9efeeb3f6b51 --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn-rpc/Dockerfile.j2 @@ -0,0 +1,52 @@ +FROM docker-syncd-bfn + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_bfn_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -P syncd + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_bfn_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + && wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install cffi==1.7.0 \ + && pip install --upgrade cffi==1.7.0 \ + && pip install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/bin/supervisord"] + diff --git a/platform/barefoot/docker-syncd-bfn-rpc/ptf_nn_agent.conf b/platform/barefoot/docker-syncd-bfn-rpc/ptf_nn_agent.conf new file mode 100644 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/barefoot/docker-syncd-bfn.mk b/platform/barefoot/docker-syncd-bfn.mk new file mode 100644 index 000000000000..22bb10763e75 --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn.mk @@ -0,0 +1,15 @@ +# docker image for syncd + +DOCKER_SYNCD_BFN = docker-syncd-bfn.gz +$(DOCKER_SYNCD_BFN)_PATH = $(PLATFORM_PATH)/docker-syncd-bfn +$(DOCKER_SYNCD_BFN)_DEPENDS += $(SYNCD) +$(DOCKER_SYNCD_BFN)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_BFN) +ifneq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_BFN) +endif + +$(DOCKER_SYNCD_BFN)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_BFN)_RUN_OPT += --net=host --privileged -t +$(DOCKER_SYNCD_BFN)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_BFN)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/platform/barefoot/docker-syncd-bfn/Dockerfile.j2 b/platform/barefoot/docker-syncd-bfn/Dockerfile.j2 new file mode 100755 index 000000000000..3e31e4b94417 --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn/Dockerfile.j2 @@ -0,0 +1,29 @@ +FROM docker-config-engine + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +COPY \ +{% for deb in docker_syncd_bfn_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get install -y libxml2 libpcap-dev libusb-1.0-0-dev libcurl3 libcurl4-gnutls-dev libunwind8-dev + +RUN dpkg -i \ +{% for deb in docker_syncd_bfn_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["start.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] + diff --git a/platform/barefoot/docker-syncd-bfn/start.sh b/platform/barefoot/docker-syncd-bfn/start.sh new file mode 100755 index 000000000000..1a39db4a9d83 --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn/start.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +. /opt/bfn/install/bin/dma_setup.sh +# . /opt/bfn/install/bin/bf_kdrv_mod_load /opt/bfn/install +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/bfn/install/lib supervisorctl start syncd diff --git a/platform/barefoot/docker-syncd-bfn/supervisord.conf b/platform/barefoot/docker-syncd-bfn/supervisord.conf new file mode 100644 index 000000000000..1e015fef931f --- /dev/null +++ b/platform/barefoot/docker-syncd-bfn/supervisord.conf @@ -0,0 +1,29 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[program:start.sh] +command=/usr/bin/start.sh +priority=1 +autostart=true +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n +priority=2 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:syncd] +command=/usr/bin/syncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + diff --git a/platform/barefoot/libsaithrift-dev.mk b/platform/barefoot/libsaithrift-dev.mk new file mode 100644 index 000000000000..c9c8cbb3adca --- /dev/null +++ b/platform/barefoot/libsaithrift-dev.mk @@ -0,0 +1,7 @@ +# libsaithrift-dev package + +LIBSAITHRIFT_DEV_BFN = libsaithrift-dev_0.9.4_amd64.deb +$(LIBSAITHRIFT_DEV_BFN)_SRC_PATH = $(SRC_PATH)/SAI +$(LIBSAITHRIFT_DEV_BFN)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(THRIFT_COMPILER) $(BFN_SAI) $(BFN_SAI_DEV) +$(LIBSAITHRIFT_DEV_BFN)_RDEPENDS += $(LIBTHRIFT) $(BFN_SAI) +#SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV_BFN) diff --git a/platform/barefoot/one-image.mk b/platform/barefoot/one-image.mk new file mode 100644 index 000000000000..a7b5d009516d --- /dev/null +++ b/platform/barefoot/one-image.mk @@ -0,0 +1,11 @@ +# sonic one image installer + +SONIC_ONE_IMAGE = sonic-barefoot.bin +$(SONIC_ONE_IMAGE)_MACHINE = barefoot +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie +$(SONIC_ONE_IMAGE)_INSTALLS += $(BFN_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(BFN_MONTARA_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(WNC_OSW1800_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(INGRASYS_S9180_32X_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES) +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/barefoot/platform-modules-bfn-montara.mk b/platform/barefoot/platform-modules-bfn-montara.mk new file mode 100644 index 000000000000..113faf201e41 --- /dev/null +++ b/platform/barefoot/platform-modules-bfn-montara.mk @@ -0,0 +1,11 @@ +# BFN Platform modules + +BFN_MONTARA_PLATFORM_MODULE_VERSION = 1.0 + +export BFN_MONTARA_PLATFORM_MODULE_VERSION + +BFN_MONTARA_PLATFORM_MODULE = platform-modules-bfn-montara_$(BFN_MONTARA_PLATFORM_MODULE_VERSION)_amd64.deb +$(BFN_MONTARA_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-bfn-montara +$(BFN_MONTARA_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(BFN_MONTARA_PLATFORM_MODULE)_PLATFORM = x86_64-accton_wedge100bf_32x-r0 +SONIC_DPKG_DEBS += $(BFN_MONTARA_PLATFORM_MODULE) diff --git a/platform/barefoot/platform-modules-bfn.mk b/platform/barefoot/platform-modules-bfn.mk new file mode 100644 index 000000000000..3f76e94aa0b2 --- /dev/null +++ b/platform/barefoot/platform-modules-bfn.mk @@ -0,0 +1,11 @@ +# BFN Platform modules + +BFN_PLATFORM_MODULE_VERSION = 1.0 + +export BFN_PLATFORM_MODULE_VERSION + +BFN_PLATFORM_MODULE = platform-modules-bfn_$(BFN_PLATFORM_MODULE_VERSION)_amd64.deb +$(BFN_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-bfn +$(BFN_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(BFN_PLATFORM_MODULE)_PLATFORM = x86_64-accton_wedge100bf_65x-r0 +SONIC_DPKG_DEBS += $(BFN_PLATFORM_MODULE) diff --git a/platform/barefoot/platform-modules-ingrasys.mk b/platform/barefoot/platform-modules-ingrasys.mk new file mode 100644 index 000000000000..7204adb7e02d --- /dev/null +++ b/platform/barefoot/platform-modules-ingrasys.mk @@ -0,0 +1,11 @@ +# Ingrasys S9180-32X Platform modules + +INGRASYS_S9180_32X_PLATFORM_MODULE_VERSION = 1.1.0 + +export INGRASYS_S9180_32X_PLATFORM_MODULE_VERSION + +INGRASYS_S9180_32X_PLATFORM_MODULE = sonic-platform-ingrasys-s9180-32x_$(INGRASYS_S9180_32X_PLATFORM_MODULE_VERSION)_amd64.deb +$(INGRASYS_S9180_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-ingrasys +$(INGRASYS_S9180_32X_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(INGRASYS_S9180_32X_PLATFORM_MODULE)_PLATFORM = x86_64-ingrasys_s9180_32x-r0 +SONIC_DPKG_DEBS += $(INGRASYS_S9180_32X_PLATFORM_MODULE) diff --git a/platform/barefoot/platform-modules-wnc-osw1800.mk b/platform/barefoot/platform-modules-wnc-osw1800.mk new file mode 100644 index 000000000000..a85ba6b19326 --- /dev/null +++ b/platform/barefoot/platform-modules-wnc-osw1800.mk @@ -0,0 +1,11 @@ +# BFN Platform modules + +WNC_OSW1800_PLATFORM_MODULE_VERSION = 1.0 + +export WNC_OSW1800_PLATFORM_MODULE_VERSION + +WNC_OSW1800_PLATFORM_MODULE = platform-modules-wnc-osw1800_$(WNC_OSW1800_PLATFORM_MODULE_VERSION)_amd64.deb +$(WNC_OSW1800_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-wnc-osw1800 +$(WNC_OSW1800_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +$(WNC_OSW1800_PLATFORM_MODULE)_PLATFORM = x86_64-wnc_osw1800-r0 +SONIC_DPKG_DEBS += $(WNC_OSW1800_PLATFORM_MODULE) diff --git a/platform/barefoot/platform.conf b/platform/barefoot/platform.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/barefoot/python-saithrift.mk b/platform/barefoot/python-saithrift.mk new file mode 100644 index 000000000000..ba4846402fb8 --- /dev/null +++ b/platform/barefoot/python-saithrift.mk @@ -0,0 +1,6 @@ +# python-saithrift package + +PYTHON_SAITHRIFT_BFN = python-saithrift_0.9.4_amd64.deb +$(PYTHON_SAITHRIFT_BFN)_SRC_PATH = $(SRC_PATH)/SAI +$(PYTHON_SAITHRIFT_BFN)_DEPENDS += $(BFN_SAI_DEV) $(BFN_SAI) $(THRIFT_COMPILER) $(PYTHON_THRIFT) $(LIBTHRIFT_DEV) +#SONIC_DPKG_DEBS += $(PYTHON_SAITHRIFT_BFN) diff --git a/platform/barefoot/rules.mk b/platform/barefoot/rules.mk new file mode 100644 index 000000000000..f10952dfadc2 --- /dev/null +++ b/platform/barefoot/rules.mk @@ -0,0 +1,23 @@ +include $(PLATFORM_PATH)/platform-modules-bfn.mk +include $(PLATFORM_PATH)/platform-modules-bfn-montara.mk +include $(PLATFORM_PATH)/platform-modules-wnc-osw1800.mk +include $(PLATFORM_PATH)/platform-modules-ingrasys.mk +include $(PLATFORM_PATH)/bfn-sai.mk +include $(PLATFORM_PATH)/docker-syncd-bfn.mk +include $(PLATFORM_PATH)/docker-syncd-bfn-rpc.mk +include $(PLATFORM_PATH)/docker-orchagent-bfn.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk +include $(PLATFORM_PATH)/python-saithrift.mk +include $(PLATFORM_PATH)/docker-ptf-bfn.mk +include $(PLATFORM_PATH)/bfn-platform.mk +include $(PLATFORM_PATH)/bfn-platform-wnc.mk +include $(PLATFORM_PATH)/bfn-platform-ingrasys.mk +SONIC_ALL += $(SONIC_ONE_IMAGE) \ + $(DOCKER_FPM) + +# Inject sai into sairedis +$(LIBSAIREDIS)_DEPENDS += $(BFN_SAI) $(WNC_OSW1800_PLATFORM) $(BFN_INGRASYS_PLATFORM) $(BFN_PLATFORM) #$(LIBSAITHRIFT_DEV_BFN) + +# Runtime dependency on sai is set only for syncd +$(SYNCD)_RDEPENDS += $(BFN_SAI) $(WNC_OSW1800_PLATFORM) $(BFN_INGRASYS_PLATFORM) $(BFN_PLATFORM) diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/LICENSE b/platform/barefoot/sonic-platform-modules-bfn-montara/LICENSE new file mode 100644 index 000000000000..676cdeec726b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2016 Microsoft, Inc + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/MAINTAINERS b/platform/barefoot/sonic-platform-modules-bfn-montara/MAINTAINERS new file mode 100644 index 000000000000..ed64c7824250 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/MAINTAINERS @@ -0,0 +1,3 @@ +# This file describes the maintainers for sonic-platform-modules-bfn +# See the SONiC project governance document for more information +Mailinglist = sonicproject@googlegroups.com diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/README.md b/platform/barefoot/sonic-platform-modules-bfn-montara/README.md new file mode 100644 index 000000000000..5dc055a1d9c3 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/README.md @@ -0,0 +1,2 @@ +# sonic-platform-modules-bfn +Device drivers for support of BFN platform for the SONiC project diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/changelog b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/changelog new file mode 100644 index 000000000000..80c1d96d3445 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/changelog @@ -0,0 +1,5 @@ +platform-modules-bfn-montara (1.0) unstable; urgency=low + + * Initial release + + -- Support Mon, 11 Nov 2015 11:11:11 -0800 diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/compat b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/compat new file mode 100644 index 000000000000..45a4fb75db86 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/compat @@ -0,0 +1 @@ +8 diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/control b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/control new file mode 100644 index 000000000000..2b1a9804baea --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/control @@ -0,0 +1,12 @@ +Source: platform-modules-bfn-montara +Section: main +Priority: extra +Maintainer: Support +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-bfn-montara +Architecture: amd64 +Depends: linux-image-3.16.0-5-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/copyright b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/copyright new file mode 100644 index 000000000000..ade42b7aa75a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/copyright @@ -0,0 +1,15 @@ +Provides linux kernel driver for BF PCIe devices + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/rules b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/rules new file mode 100755 index 000000000000..e48edc304904 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/rules @@ -0,0 +1,32 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_NAME := platform-modules-bfn-montara +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MODULE_SRC := $(shell pwd)/modules +SCRIPT_SRC := $(shell pwd)/scripts + +%: + dh $@ + +override_dh_auto_build: + make -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + +override_dh_auto_install: + dh_installdirs -p$(PACKAGE_NAME) $(KERNEL_SRC)/$(INSTALL_MOD_DIR) + cp $(MODULE_SRC)/*.ko debian/$(PACKAGE_NAME)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR) + dh_installdirs -p$(PACKAGE_NAME) usr/local/bin + cp -r $(SCRIPT_SRC)/* debian/$(PACKAGE_NAME)/usr/local/bin + +override_dh_usrlocal: + +override_dh_pysupport: + +override_dh_clean: + dh_clean + rm -f $(MODULE_SRC)/*.o $(MODULE_SRC)/*.ko $(MODULE_SRC)/*.mod.c $(MODULE_SRC)/.*.cmd + rm -f $(MODULE_SRC)/Module.markers $(MODULE_SRC)/Module.symvers $(MODULE_SRC)/modules.order + rm -rf $(MODULE_SRC)/.tmp_versions + diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/modules/Makefile b/platform/barefoot/sonic-platform-modules-bfn-montara/modules/Makefile new file mode 120000 index 000000000000..d394585dd286 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/modules/Makefile @@ -0,0 +1 @@ +../../sonic-platform-modules-bfn/modules/Makefile \ No newline at end of file diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/modules/bf_kdrv.c b/platform/barefoot/sonic-platform-modules-bfn-montara/modules/bf_kdrv.c new file mode 120000 index 000000000000..959d811823c0 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/modules/bf_kdrv.c @@ -0,0 +1 @@ +../../sonic-platform-modules-bfn/modules/bf_kdrv.c \ No newline at end of file diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/modules/bf_tun.c b/platform/barefoot/sonic-platform-modules-bfn-montara/modules/bf_tun.c new file mode 120000 index 000000000000..ea380c3075a7 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/modules/bf_tun.c @@ -0,0 +1 @@ +../../sonic-platform-modules-bfn/modules/bf_tun.c \ No newline at end of file diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/eeprom b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/eeprom new file mode 100755 index 000000000000..07d98556cbbf --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/eeprom @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd eeprom "$@" diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/fancontrol b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/fancontrol new file mode 100755 index 000000000000..515fcbdd69da --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/fancontrol @@ -0,0 +1,11 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd fancontrol "$@" + diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/ps_info b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/ps_info new file mode 100755 index 000000000000..38c9d3330414 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/ps_info @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd ps_info "$@" diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/sensors b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/sensors new file mode 100755 index 000000000000..07af6955321e --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/sensors @@ -0,0 +1,12 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd sensors "$@" + + diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/sfputil b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/sfputil new file mode 100755 index 000000000000..3df67614e499 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/sfputil @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd sfputil "$@" diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/test b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/test new file mode 100755 index 000000000000..38327722c91f --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/scripts/test @@ -0,0 +1 @@ +echo "test" diff --git a/platform/barefoot/sonic-platform-modules-bfn/LICENSE b/platform/barefoot/sonic-platform-modules-bfn/LICENSE new file mode 100644 index 000000000000..676cdeec726b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2016 Microsoft, Inc + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-bfn/MAINTAINERS b/platform/barefoot/sonic-platform-modules-bfn/MAINTAINERS new file mode 100644 index 000000000000..b9c62ce01546 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/MAINTAINERS @@ -0,0 +1,4 @@ +# This file describes the maintainers for sonic-platform-modules-bfn +# See the SONiC project governance document for more information + +Mailinglist = sonicproject@googlegroups.com diff --git a/platform/barefoot/sonic-platform-modules-bfn/README.md b/platform/barefoot/sonic-platform-modules-bfn/README.md new file mode 100644 index 000000000000..5dc055a1d9c3 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/README.md @@ -0,0 +1,2 @@ +# sonic-platform-modules-bfn +Device drivers for support of BFN platform for the SONiC project diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/changelog b/platform/barefoot/sonic-platform-modules-bfn/debian/changelog new file mode 100644 index 000000000000..d5df34112672 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/changelog @@ -0,0 +1,5 @@ +platform-modules-bfn (1.0) unstable; urgency=low + + * Initial release + + -- Support Mon, 11 Nov 2015 11:11:11 -0800 diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/compat b/platform/barefoot/sonic-platform-modules-bfn/debian/compat new file mode 100644 index 000000000000..45a4fb75db86 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/compat @@ -0,0 +1 @@ +8 diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/control b/platform/barefoot/sonic-platform-modules-bfn/debian/control new file mode 100644 index 000000000000..09d0cc82d2c3 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/control @@ -0,0 +1,12 @@ +Source: platform-modules-bfn +Section: main +Priority: extra +Maintainer: support +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-bfn +Architecture: amd64 +Depends: linux-image-3.16.0-5-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/copyright b/platform/barefoot/sonic-platform-modules-bfn/debian/copyright new file mode 100644 index 000000000000..ade42b7aa75a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/copyright @@ -0,0 +1,15 @@ +Provides linux kernel driver for BF PCIe devices + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/files b/platform/barefoot/sonic-platform-modules-bfn/debian/files new file mode 100644 index 000000000000..1cfb92c60ae1 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/files @@ -0,0 +1 @@ +platform-modules-bfn_1.0_amd64.deb main extra diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/rules b/platform/barefoot/sonic-platform-modules-bfn/debian/rules new file mode 100755 index 000000000000..73aa5d84da0b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/rules @@ -0,0 +1,32 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_NAME := platform-modules-bfn +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MODULE_SRC := $(shell pwd)/modules +SCRIPT_SRC := $(shell pwd)/scripts + +%: + dh $@ + +override_dh_auto_build: + make -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + +override_dh_auto_install: + dh_installdirs -p$(PACKAGE_NAME) $(KERNEL_SRC)/$(INSTALL_MOD_DIR) + cp $(MODULE_SRC)/*.ko debian/$(PACKAGE_NAME)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR) + dh_installdirs -p$(PACKAGE_NAME) usr/local/bin + cp -r $(SCRIPT_SRC)/* debian/$(PACKAGE_NAME)/usr/local/bin + +override_dh_usrlocal: + +override_dh_pysupport: + +override_dh_clean: + dh_clean + rm -f $(MODULE_SRC)/*.o $(MODULE_SRC)/*.ko $(MODULE_SRC)/*.mod.c $(MODULE_SRC)/.*.cmd + rm -f $(MODULE_SRC)/Module.markers $(MODULE_SRC)/Module.symvers $(MODULE_SRC)/modules.order + rm -rf $(MODULE_SRC)/.tmp_versions + diff --git a/platform/barefoot/sonic-platform-modules-bfn/modules/Makefile b/platform/barefoot/sonic-platform-modules-bfn/modules/Makefile new file mode 100644 index 000000000000..d180b29f6ae2 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := bf_kdrv.o +obj-m += bf_tun.o diff --git a/platform/barefoot/sonic-platform-modules-bfn/modules/bf_kdrv.c b/platform/barefoot/sonic-platform-modules-bfn/modules/bf_kdrv.c new file mode 100644 index 000000000000..fd66ad09493a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/modules/bf_kdrv.c @@ -0,0 +1,1254 @@ +/******************************************************************************* + * BAREFOOT NETWORKS CONFIDENTIAL & PROPRIETARY + * + * Copyright (c) 2015-2016 Barefoot Networks, Inc. + + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains the property of + * Barefoot Networks, Inc. and its suppliers, if any. The intellectual and + * technical concepts contained herein are proprietary to Barefoot Networks, + * Inc. + * and its suppliers and may be covered by U.S. and Foreign Patents, patents in + * process, and are protected by trade secret or copyright law. + * Dissemination of this information or reproduction of this material is + * strictly forbidden unless prior written permission is obtained from + * Barefoot Networks, Inc. + * + * No warranty, explicit or implicit is provided, unless granted under a + * written agreement with Barefoot Networks, Inc. + * + * $Id: $ + * + ******************************************************************************/ +/** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2015 Barefoot Networks. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the... + * + **/ + +/* bf_drv kernel module + * + * This is kernel mode driver for Tofino chip. + * Provides user space mmap service and user space "wait for interrupt" + * and "enable interrupt" services. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) + #include +#else + #include +#endif + +#include +#include +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) +//#error unsupported linux kernel version +#endif + +/* TBD: Need to build with CONFIG_PCI_MSI */ +extern int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec); +extern int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int minvec, int maxvec); + +#define PCI_VENDOR_ID_BF 0x1d1c +#define TOFINO_DEV_ID_A0 0x01 +#define TOFINO_DEV_ID_B0 0x10 + +#ifndef PCI_MSIX_ENTRY_SIZE +#define PCI_MSIX_ENTRY_SIZE 16 +#define PCI_MSIX_ENTRY_LOWER_ADDR 0 +#define PCI_MSIX_ENTRY_UPPER_ADDR 4 +#define PCI_MSIX_ENTRY_DATA 8 +#define PCI_MSIX_ENTRY_VECTOR_CTRL 12 +#define PCI_MSIX_ENTRY_CTRL_MASKBIT 1 +#endif + +#define BF_CLASS_NAME "bf" +#define BF_MAX_DEVICE_CNT 256 +#define BF_INTR_MODE_NONE_NAME "none" +#define BF_INTR_MODE_LEGACY_NAME "legacy" +#define BF_INTR_MODE_MSI_NAME "msi" +#define BF_INTR_MODE_MSIX_NAME "msix" +#define BF_MAX_BAR_MAPS 6 +#define BF_MSIX_ENTRY_CNT 128 /* TBD make it 512 */ +#define BF_MSI_ENTRY_CNT 2 + +/* interrupt mode */ +enum bf_intr_mode { + BF_INTR_MODE_NONE = 0, + BF_INTR_MODE_LEGACY, + BF_INTR_MODE_MSI, + BF_INTR_MODE_MSIX +}; + +/* device memory */ +struct bf_dev_mem { + const char *name; + phys_addr_t addr; + resource_size_t size; + void __iomem *internal_addr; +}; + +struct bf_listener { + struct bf_pci_dev *bfdev; + s32 event_count[BF_MSIX_ENTRY_CNT]; + int minor; + struct bf_listener *next; +}; + +/* device information */ +struct bf_dev_info { + struct module *owner; + struct device *dev; + int minor; + atomic_t event[BF_MSIX_ENTRY_CNT]; + wait_queue_head_t wait; + const char *version; + struct bf_dev_mem mem[BF_MAX_BAR_MAPS]; + struct msix_entry *msix_entries; + long irq; /* first irq vector */ + int num_irq; /* number of irq vectors */ + unsigned long irq_flags;/* sharable ?? */ + int pci_error_state; /* was there a pci bus error */ +}; + +/* cookie to be passed to IRQ handler, useful especially with MSIX */ +struct bf_int_vector { + struct bf_pci_dev *bf_dev; + int int_vec_offset; +}; + + +/** + * A structure describing the private information for a BF pcie device. + */ +struct bf_pci_dev { + struct bf_dev_info info; + struct pci_dev *pdev; + enum bf_intr_mode mode; + u8 instance; + char name[16]; + struct bf_int_vector bf_int_vec[BF_MSIX_ENTRY_CNT]; + struct bf_listener *listener_head; /* head of a singly linked list of + listeners */ +}; + +/* Keep any global information here that must survive even after the + * bf_pci_dev is free-ed up. + */ +struct bf_global { + struct bf_pci_dev *bfdev ; + struct cdev *bf_cdev; + struct fasync_struct *async_queue; +}; + +static int bf_major; +static int bf_minor[BF_MAX_DEVICE_CNT] = {0}; +static struct class *bf_class = NULL; +static char *intr_mode = NULL; +static enum bf_intr_mode bf_intr_mode_default = BF_INTR_MODE_MSI; +static spinlock_t bf_nonisr_lock; +/* dev->minor should index into this array */ +static struct bf_global bf_global[BF_MAX_DEVICE_CNT]; + +static void bf_add_listener(struct bf_pci_dev *bfdev, + struct bf_listener *listener) +{ + struct bf_listener **cur_listener = &bfdev->listener_head; + + if (!listener) { + return; + } + spin_lock(&bf_nonisr_lock); + + while (*cur_listener) { + cur_listener = &((*cur_listener)->next); + } + *cur_listener = listener; + listener->next = NULL; + + spin_unlock(&bf_nonisr_lock); +} + +static void bf_remove_listener(struct bf_pci_dev *bfdev, + struct bf_listener *listener) +{ + struct bf_listener **cur_listener = &bfdev->listener_head; + + /* in case of certain error conditions, this function might be called after bf_pci_remove() + */ + if (!bfdev || !listener) { + return; + } + spin_lock(&bf_nonisr_lock); + + if (*cur_listener == listener) { + *cur_listener = listener->next; + } else { + while (*cur_listener) { + if ((*cur_listener)->next == listener) { + (*cur_listener)->next = listener->next; + break; + } + cur_listener = &((*cur_listener)->next); + } + listener->next = NULL; + } + + spin_unlock(&bf_nonisr_lock); +} + +/* a pool of minor numbers is maintained */ +/* return the first available minor number */ +static int bf_get_next_minor_no(int *minor) +{ + int i; + + spin_lock(&bf_nonisr_lock); + for(i = 0; i < BF_MAX_DEVICE_CNT; i++) { + if (bf_minor[i] == 0) { + *minor = i; + bf_minor[i] = 1; /* mark it as taken */ + spin_unlock(&bf_nonisr_lock); + return 0; + } + } + *minor = -1; + spin_unlock(&bf_nonisr_lock); + return -1; +} + +/* return a minor number back to the pool for recycling */ +static int bf_return_minor_no(int minor) +{ + int err; + + spin_lock(&bf_nonisr_lock); + if (bf_minor[minor] == 0) { /* was already returned */ + err = -1; /* don't change anything, but return error */ + } else { + bf_minor[minor] = 0; /* mark it as available */ + err = 0; + } + spin_unlock(&bf_nonisr_lock); + return err; +} + +static inline struct bf_pci_dev *bf_get_pci_dev(struct bf_dev_info *info) +{ + return container_of(info, struct bf_pci_dev, info); +} + +/* + * It masks the msix on/off of generating MSI-X messages. + */ +static void +bf_msix_mask_irq(struct msi_desc *desc, int32_t state) +{ + u32 mask_bits = desc->masked; + unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_VECTOR_CTRL; + + if (state != 0) + mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT; + else + mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT; + + if (mask_bits != desc->masked) { + writel(mask_bits, desc->mask_base + offset); + readl(desc->mask_base); + desc->masked = mask_bits; + } +} + +/** + * irqcontrol can be used to disable/enable interrupt from user space processes. + * + * @param bf_dev + * pointer to bf_pci_dev + * @param irq_state + * state value. 1 to enable interrupt, 0 to disable interrupt. + * + * @return + * - On success, 0. + * - On failure, a negative value. + */ +static int +bf_pci_irqcontrol(struct bf_pci_dev *bfdev, s32 irq_state) +{ + struct pci_dev *pdev = bfdev->pdev; + + pci_cfg_access_lock(pdev); + if (bfdev->mode == BF_INTR_MODE_LEGACY) + pci_intx(pdev, !!irq_state); + + else if (bfdev->mode == BF_INTR_MODE_MSIX) { + struct msi_desc *desc; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0) + list_for_each_entry(desc, &pdev->msi_list, list) + bf_msix_mask_irq(desc, irq_state); +#else + for_each_pci_msi_entry(desc, pdev) + bf_msix_mask_irq(desc, irq_state); +#endif + } + pci_cfg_access_unlock(pdev); + + return 0; +} + +/** + * interrupt handler which will check if the interrupt is from the right + * device. If so, disable it here and will be enabled later. + */ +static irqreturn_t bf_pci_irqhandler(int irq, struct bf_pci_dev *bfdev) +{ + /* Legacy mode need to mask in hardware */ + if (bfdev->mode == BF_INTR_MODE_LEGACY && + !pci_check_and_mask_intx(bfdev->pdev)) + return IRQ_NONE; + + /* NOTE : if bfdev->info.pci_error_state == 1, then do not access the + * device and return IRQ_NOTHANDLED. + */ + /* Message signal mode, no share IRQ and automasked */ + return IRQ_HANDLED; +} + +/* Remap pci resources described by bar #pci_bar */ +static int +bf_pci_setup_iomem(struct pci_dev *dev, struct bf_dev_info *info, + int n, int pci_bar, const char *name) +{ + unsigned long addr, len; + void *internal_addr; + + if (sizeof(info->mem) / sizeof(info->mem[0]) <= n) + return -EINVAL; + + addr = pci_resource_start(dev, pci_bar); + len = pci_resource_len(dev, pci_bar); + if (addr == 0 || len == 0) + return -1; + internal_addr = pci_ioremap_bar(dev, pci_bar); + if (internal_addr == NULL) + return -1; + info->mem[n].name = name; + info->mem[n].addr = addr; + info->mem[n].internal_addr = internal_addr; + info->mem[n].size = len; + return 0; +} + +/* Unmap previously ioremap'd resources */ +static void +bf_pci_release_iomem(struct bf_dev_info *info) +{ + int i; + + for (i = 0; i < BF_MAX_BAR_MAPS; i++) { + if (info->mem[i].internal_addr) + iounmap(info->mem[i].internal_addr); + } +} + +static int +bf_setup_bars(struct pci_dev *dev, struct bf_dev_info *info) +{ + int i, iom, ret; + unsigned long flags; + static const char *bar_names[BF_MAX_BAR_MAPS] = { + "BAR0", "BAR1", "BAR2", "BAR3", "BAR4", "BAR5", + }; + + iom = 0; + + for (i = 0; i < BF_MAX_BAR_MAPS; i++) { + if (pci_resource_len(dev, i) != 0 && + pci_resource_start(dev, i) != 0) { + flags = pci_resource_flags(dev, i); + if (flags & IORESOURCE_MEM) { + ret = bf_pci_setup_iomem(dev, info, iom, i, bar_names[i]); + if (ret != 0) + return ret; + iom++; + } + } + } + return (iom != 0) ? ret : -ENOENT; +} + +static irqreturn_t bf_interrupt(int irq, void *bfdev_id) +{ + struct bf_pci_dev *bfdev = ((struct bf_int_vector *)bfdev_id)->bf_dev; + int vect_off = ((struct bf_int_vector *)bfdev_id)->int_vec_offset; + + irqreturn_t ret = bf_pci_irqhandler(irq, bfdev); + + if (ret == IRQ_HANDLED) + atomic_inc(&(bfdev->info.event[vect_off])); + + return ret; +} + +static unsigned int bf_poll(struct file *filep, poll_table *wait) +{ + struct bf_listener *listener = (struct bf_listener *)filep->private_data; + struct bf_pci_dev *bfdev = listener->bfdev; + int i; + + if (!bfdev) { + return -ENODEV; + } + if (!bfdev->info.irq) + return -EIO; + + poll_wait(filep, &bfdev->info.wait, wait); + + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) + if (listener->event_count[i] != atomic_read(&bfdev->info.event[i])) + return POLLIN | POLLRDNORM; + return 0; +} + +static int bf_find_mem_index(struct vm_area_struct *vma) +{ + struct bf_pci_dev *bfdev = vma->vm_private_data; + if (vma->vm_pgoff < BF_MAX_BAR_MAPS) { + if (bfdev->info.mem[vma->vm_pgoff].size == 0) + return -1; + return (int)vma->vm_pgoff; + } + return -1; +} + +static const struct vm_operations_struct bf_physical_vm_ops = { +#ifdef CONFIG_HAVE_IOREMAP_PROT + .access = generic_access_phys, +#endif +}; + +static int bf_mmap_physical(struct vm_area_struct *vma) +{ + struct bf_pci_dev *bfdev = vma->vm_private_data; + int bar = bf_find_mem_index(vma); + struct bf_dev_mem *mem; + if (bar < 0) + return -EINVAL; + + mem = bfdev->info.mem + bar; + + if (mem->addr & ~PAGE_MASK) + return -ENODEV; + if (vma->vm_end - vma->vm_start > mem->size) + return -EINVAL; + + vma->vm_ops = &bf_physical_vm_ops; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + /* + * We cannot use the vm_iomap_memory() helper here, + * because vma->vm_pgoff is the map index we looked + * up above in bf_find_mem_index(), rather than an + * actual page offset into the mmap. + * + * So we just do the physical mmap without a page + * offset. + */ + return remap_pfn_range(vma, vma->vm_start, mem->addr >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot); +} + +static int bf_mmap(struct file *filep, struct vm_area_struct *vma) +{ + struct bf_listener *listener = filep->private_data; + struct bf_pci_dev *bfdev = listener->bfdev; + int bar; + unsigned long requested_pages, actual_pages; + + if (!bfdev) { + return -ENODEV; + } + if (vma->vm_end < vma->vm_start) + return -EINVAL; + + vma->vm_private_data = bfdev; + + bar = bf_find_mem_index(vma); + if (bar < 0) + return -EINVAL; + + requested_pages = vma_pages(vma); + actual_pages = ((bfdev->info.mem[bar].addr & ~PAGE_MASK) + + bfdev->info.mem[bar].size + PAGE_SIZE -1) >> PAGE_SHIFT; + if (requested_pages > actual_pages) + return -EINVAL; + + return bf_mmap_physical(vma); +} + +static int bf_fasync(int fd, struct file *filep, int mode) +{ + int minor; + + if (!filep->private_data) { + return (-EINVAL); + } + minor = ((struct bf_listener *)filep->private_data)->minor; + if (minor >= BF_MAX_DEVICE_CNT) { + return (-EINVAL); + } + if (mode == 0 && &bf_global[minor].async_queue == NULL) { + return 0; /* nothing to do */ + } + return (fasync_helper(fd, filep, mode, &bf_global[minor].async_queue)); +} + +static int bf_open(struct inode *inode, struct file *filep) +{ + struct bf_pci_dev *bfdev; + struct bf_listener *listener; + int i; + + bfdev = bf_global[iminor(inode)].bfdev; + listener = kmalloc(sizeof(*listener), GFP_KERNEL); + if (listener) { + listener->bfdev = bfdev; + listener->minor = bfdev->info.minor; + listener->next = NULL; + bf_add_listener(bfdev, listener); + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) + listener->event_count[i] = atomic_read(&bfdev->info.event[i]); + filep->private_data = listener; + return 0; + } else { + return(-ENOMEM); + } +} + +static int bf_release(struct inode *inode, struct file *filep) +{ + struct bf_listener *listener = filep->private_data; + + bf_fasync(-1, filep, 0); /* empty any process id in the notification list */ + if (listener->bfdev) { + bf_remove_listener(listener->bfdev, listener); + } + kfree(listener); + return 0; +} + +/* user space support: make read() system call after poll() of select() */ +static ssize_t bf_read(struct file *filep, char __user *buf, + size_t count, loff_t *ppos) +{ + struct bf_listener *listener = filep->private_data; + struct bf_pci_dev *bfdev = listener->bfdev; + int retval, event_count[BF_MSIX_ENTRY_CNT]; + int i, mismatch_found = 0; /* OR of per vector mismatch */ + unsigned char cnt_match[BF_MSIX_ENTRY_CNT]; /* per vector mismatch */ + + if (!bfdev) { + return -ENODEV; + } + /* irq must be setup for read() to work */ + if (!bfdev->info.irq) + return -EIO; + + /* ensure that there is enough space on user buffer for the given interrupt + * mode */ + if (bfdev->mode == BF_INTR_MODE_MSIX) { + if (count < sizeof(s32)*BF_MSIX_ENTRY_CNT) + return -EINVAL; + count = sizeof(s32)*BF_MSIX_ENTRY_CNT; + } else if (bfdev->mode == BF_INTR_MODE_MSI) { + if (count < sizeof(s32)*BF_MSI_ENTRY_CNT) + return -EINVAL; + count = sizeof(s32)*BF_MSI_ENTRY_CNT; + } else { + if (count < sizeof(s32)) + return -EINVAL; + count = sizeof(s32); + } + + do { + set_current_state(TASK_INTERRUPTIBLE); + + for (i = 0; i < (count/sizeof(s32)); i++) { + event_count[i] = atomic_read(&(bfdev->info.event[i])); + if (event_count[i] != listener->event_count[i]) { + mismatch_found |= 1; + cnt_match[i] = 1; + } else { + event_count[i] = 0; + cnt_match[i] = 0; + } + } + if (mismatch_found) { + __set_current_state(TASK_RUNNING); + if (copy_to_user(buf, &event_count, count)) + retval = -EFAULT; + else { /* adjust the listener->event_count; */ + for (i = 0 ; i < (count/sizeof(s32)); i++) { + if (cnt_match[i]) { + listener->event_count[i] = event_count[i]; + } + } + retval = count; + } + break; + } + + if (filep->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + break; + } + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + schedule(); + } while (1); + + __set_current_state(TASK_RUNNING); + + return retval; +} + +/* user space is supposed to call this after it is done with interrupt + * processing + */ +static ssize_t bf_write(struct file *filep, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct bf_listener *listener = filep->private_data; + struct bf_pci_dev *bfdev = listener->bfdev; + ssize_t ret; + s32 int_en; + + if (!bfdev || !bfdev->info.irq) + return -EIO; + + if (count != sizeof(s32)) + return -EINVAL; + + if (copy_from_user(&int_en, buf, count)) + return -EFAULT; + + /* clear pci_error_state */ + bfdev->info.pci_error_state = 0; + + ret = bf_pci_irqcontrol(bfdev, int_en); + + return ret ? ret : sizeof(s32); +} + +static const struct file_operations bf_fops = { + .owner = THIS_MODULE, + .open = bf_open, + .release = bf_release, + .read = bf_read, + .write = bf_write, + .mmap = bf_mmap, + .poll = bf_poll, + .fasync = bf_fasync, +}; + +static int bf_major_init(struct bf_pci_dev *bfdev, int minor) +{ + struct cdev *cdev; + static const char name[] = "bf"; + dev_t bf_dev = 0; + int result; + + result = alloc_chrdev_region(&bf_dev, 0, BF_MAX_DEVICE_CNT, name); + if (result) + return result; + + result = -ENOMEM; + cdev = cdev_alloc(); + if (!cdev) { + goto fail_dev_add; + } + cdev->ops = &bf_fops; + cdev->owner = THIS_MODULE; + kobject_set_name(&cdev->kobj, "%s", name); + result = cdev_add(cdev, bf_dev, BF_MAX_DEVICE_CNT); + + if (result) + goto fail_dev_add; + + bf_major = MAJOR(bf_dev); + bf_global[minor].bf_cdev = cdev; + return 0; + +fail_dev_add: + unregister_chrdev_region(bf_dev, BF_MAX_DEVICE_CNT); + return result; +} + +static void bf_major_cleanup(struct bf_pci_dev *bfdev, int minor) +{ + unregister_chrdev_region(MKDEV(bf_major, 0), BF_MAX_DEVICE_CNT); + cdev_del(bf_global[minor].bf_cdev); +} + +static int bf_init_cdev(struct bf_pci_dev *bfdev, int minor) +{ + int ret; + ret = bf_major_init(bfdev, minor); + if (ret) + return ret; + + bf_class = class_create(THIS_MODULE, BF_CLASS_NAME); + if (!bf_class) { + printk(KERN_ERR "create_class failed for bf_dev\n"); + ret = -ENODEV; + goto err_class_register; + } + return 0; + +err_class_register: + bf_major_cleanup(bfdev, minor); + return ret; +} + +static void bf_remove_cdev(struct bf_pci_dev *bfdev) +{ + class_destroy(bf_class); + bf_major_cleanup(bfdev, bfdev->info.minor); +} + + +/** + * bf_register_device - register a new userspace mem device + * @parent: parent device + * @bfdev: bf pci device + * + * returns zero on success or a negative error code. + */ +int bf_register_device(struct device *parent, struct bf_pci_dev *bfdev) +{ + struct bf_dev_info *info = &bfdev->info; + int i, j, ret = 0; + int minor; + + if (!parent || !info || !info->version) + return -EINVAL; + + init_waitqueue_head(&info->wait); + + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) { + atomic_set(&info->event[i], 0); + } + + if (bf_get_next_minor_no(&minor)) { + return -EINVAL; + } + + ret = bf_init_cdev(bfdev, minor); + if (ret) { + printk(KERN_ERR "BF: device cdev creation failed\n"); + return ret; + } + + info->dev = device_create(bf_class, parent, + MKDEV(bf_major, minor), bfdev, + "bf%d", minor); + if (!info->dev) { + printk(KERN_ERR "BF: device creation failed\n"); + return -ENODEV; + } + + info->minor = minor; + + /* bind ISRs and request interrupts */ + if (info->irq && (bfdev->mode != BF_INTR_MODE_NONE)) { + /* + * Note that we deliberately don't use devm_request_irq + * here. The parent module can unregister the UIO device + * and call pci_disable_msi, which requires that this + * irq has been freed. However, the device may have open + * FDs at the time of unregister and therefore may not be + * freed until they are released. + */ + if (bfdev->mode == BF_INTR_MODE_LEGACY) { + ret = request_irq(info->irq, bf_interrupt, + info->irq_flags, bfdev->name, + (void *)&(bfdev->bf_int_vec[0])); + if (ret) { + printk(KERN_ERR "bf failed to request legacy irq %ld error %d\n", + info->irq, ret); + return ret; + } + printk(KERN_NOTICE "BF allocating legacy int vector %ld\n", info->irq); + } else if (bfdev->mode == BF_INTR_MODE_MSIX) { + for (i = 0; i < info->num_irq; i++) { + ret = request_irq(info->msix_entries[i].vector, bf_interrupt, + info->irq_flags, bfdev->name, + (void *)&(bfdev->bf_int_vec[i])); + if (ret) { + /* undo all other previous bindings */ + printk(KERN_ERR "bf failed to request MSIX ret %d itr %d\n", ret, i); + for (j = i - 1; j >= 0; j--) { + free_irq(info->msix_entries[j].vector, + (void *)&(bfdev->bf_int_vec[j])); + } + return ret; + } + } + printk(KERN_NOTICE "BF allocating %d MSIx vectors from %ld\n", + info->num_irq, info->irq); + } else if (bfdev->mode == BF_INTR_MODE_MSI) { + for (i = 0; i < info->num_irq; i++) { + ret = request_irq(info->irq + i, bf_interrupt, + info->irq_flags, bfdev->name, + (void *)&(bfdev->bf_int_vec[i])); + if (ret) { + /* undo all other previous bindings */ + printk(KERN_ERR "bf failed to request MSI ret %d itr %d\n", ret, i); + for (j = i - 1; j >= 0; j--) { + free_irq(info->irq + j, (void *)&(bfdev->bf_int_vec[j])); + } + return ret; + } + } + printk(KERN_NOTICE "BF allocating %d MSI vectors from %ld\n", + info->num_irq, info->irq); + } + } + return 0; +} + +/** + * bf_unregister_device - register a new userspace mem device + * @bfdev: bf pci device + * + * returns none + */ +void bf_unregister_device(struct bf_pci_dev *bfdev) +{ + struct bf_dev_info *info = &bfdev->info; + int i; + + if (info->irq) { + if (bfdev->mode == BF_INTR_MODE_LEGACY) { + free_irq(info->irq, (void *)&(bfdev->bf_int_vec[0])); + } else if (bfdev->mode == BF_INTR_MODE_MSIX) { + for (i = 0; i < info->num_irq; i++) { + free_irq(info->msix_entries[i].vector, (void *)&(bfdev->bf_int_vec[i])); + } + } else if (bfdev->mode == BF_INTR_MODE_MSI) { + for (i = 0; i < info->num_irq; i++) { + free_irq(info->irq + i, (void *)&(bfdev->bf_int_vec[i])); + } + } + } + device_destroy(bf_class, MKDEV(bf_major, info->minor)); + bf_remove_cdev(bfdev); + bf_return_minor_no(info->minor); + return; +} + +static inline struct device *pci_dev_to_dev(struct pci_dev *pdev) +{ + return &pdev->dev; +} + +static int +bf_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct bf_pci_dev *bfdev; + int err, pci_use_highmem; + int i, num_irq; + + memset(bf_global, 0, sizeof(bf_global)); + + bfdev = kzalloc(sizeof(struct bf_pci_dev), GFP_KERNEL); + if (!bfdev) + return -ENOMEM; + + /* init the cookies to be passed to ISRs */ + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) { + bfdev->bf_int_vec[i].int_vec_offset = i; + bfdev->bf_int_vec[i].bf_dev = bfdev; + } + + /* initialize intr_mode to none */ + bfdev->mode = BF_INTR_MODE_NONE; + + /* clear pci_error_state */ + bfdev->info.pci_error_state = 0; + + /* + * enable device + */ + err = pci_enable_device(pdev); + if (err != 0) { + dev_err(&pdev->dev, "Cannot enable PCI device\n"); + goto fail_free; + } + + /* + * reserve device's PCI memory regions for use by this + * module + */ + err = pci_request_regions(pdev, "bf_umem"); + if (err != 0) { + dev_err(&pdev->dev, "Cannot request regions\n"); + goto fail_pci_disable; + } + /* remap IO memory */ + err = bf_setup_bars(pdev, &bfdev->info); + if (err != 0) + goto fail_release_iomem; + + if (!dma_set_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(64)) && + !dma_set_coherent_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(64))) { + pci_use_highmem = 1; + } else { + err = dma_set_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(32)); + if (err) { + err = dma_set_coherent_mask(pci_dev_to_dev(pdev), + DMA_BIT_MASK(32)); + if (err) { + dev_err(pci_dev_to_dev(pdev), "No usable DMA " + "configuration, aborting\n"); + goto fail_release_iomem; + } + } + pci_use_highmem = 0; + } + + /* enable pci error reporting */ + /* for the current kernel version, kernel config must have set the followings: + * CONFIG_PCIEPORTBUS=y and CONFIG_PCIEAER = y + * we have pci_error_handlers defined that gets invoked by kernel AER module + * upon detecting the pcie error on this device's addresses. + * However, there seems no way that AER would pass the offending addresses + * to the callback functions. AER logs the error messages on the console. + * This driver's calback function send the SIGIO signal to the user space + * to indicate the error condition. + */ + pci_enable_pcie_error_reporting(pdev); + + /* enable bus mastering on the device */ + pci_set_master(pdev); + + /* fill in bfdev info */ + bfdev->info.version = "0.2"; + bfdev->info.owner = THIS_MODULE; + bfdev->pdev = pdev; + + switch (bf_intr_mode_default) { +#ifdef CONFIG_PCI_MSI + case BF_INTR_MODE_MSIX: + /* Only 1 msi-x vector needed */ + bfdev->info.msix_entries = kcalloc(BF_MSIX_ENTRY_CNT, + sizeof(struct msix_entry), GFP_KERNEL); + if (!bfdev->info.msix_entries) { + err = -ENOMEM; + goto fail_clear_pci_master; + } + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) { + bfdev->info.msix_entries[i].entry= i; + } + num_irq = pci_enable_msix_range(pdev, bfdev->info.msix_entries, + BF_MSIX_ENTRY_CNT, BF_MSIX_ENTRY_CNT); + if (num_irq == BF_MSIX_ENTRY_CNT) { + dev_dbg(&pdev->dev, "using MSI-X"); + bfdev->info.num_irq = num_irq; + bfdev->info.irq = bfdev->info.msix_entries[0].vector; + bfdev->mode = BF_INTR_MODE_MSIX; + printk(KERN_DEBUG "bf using %d MSIX irq from %ld\n", num_irq, + bfdev->info.irq); + break; + } else { + if (num_irq) + pci_disable_msix(pdev); + kfree(bfdev->info.msix_entries); + bfdev->info.msix_entries = NULL; + printk(KERN_ERR "bf error allocating MSIX vectors. Trying MSI...\n"); + /* and, fall back to MSI */ + } + /* ** intentional no-break */ + case BF_INTR_MODE_MSI: + num_irq = pci_enable_msi_range(pdev, BF_MSI_ENTRY_CNT, BF_MSI_ENTRY_CNT); + if (num_irq > 0) { + dev_dbg(&pdev->dev, "using MSI"); + bfdev->info.num_irq = num_irq; + bfdev->info.irq = pdev->irq; + bfdev->mode = BF_INTR_MODE_MSI; + printk(KERN_DEBUG "bf using %d MSI irq from %ld\n", bfdev->info.num_irq, + bfdev->info.irq); + break; + } +#endif /* CONFIG_PCI_MSI */ + /* fall back to Legacy Interrupt, intentional no-break */ + + case BF_INTR_MODE_LEGACY: + if (pci_intx_mask_supported(pdev)) { + dev_dbg(&pdev->dev, "using INTX"); + bfdev->info.irq_flags = IRQF_SHARED; + bfdev->info.irq = pdev->irq; + bfdev->mode = BF_INTR_MODE_LEGACY; + printk(KERN_DEBUG "bf using LEGACY irq %ld\n", bfdev->info.irq); + break; + } + dev_notice(&pdev->dev, "PCI INTx mask not supported\n"); + /* fall back to no Interrupt, intentional no-break */ + case BF_INTR_MODE_NONE: + bfdev->info.irq = 0; + bfdev->info.num_irq = 0; + bfdev->mode = BF_INTR_MODE_NONE; + break; + + default: + dev_err(&pdev->dev, "invalid IRQ mode %u", bf_intr_mode_default); + err = -EINVAL; + goto fail_clear_pci_master; + } + + pci_set_drvdata(pdev, bfdev); + sprintf(bfdev->name, "bf_%d", bfdev->info.minor); + /* register bf driver */ + err = bf_register_device(&pdev->dev, bfdev); + if (err != 0) + goto fail_release_irq; + + bf_global[bfdev->info.minor].async_queue = NULL; + bf_global[bfdev->info.minor].bfdev = bfdev; + + dev_info(&pdev->dev, "bf device %d registered with irq %ld\n", + bfdev->instance, bfdev->info.irq); + printk(KERN_ALERT "bf probe ok\n"); + return 0; + +fail_release_irq: + pci_set_drvdata(pdev, NULL); + if (bfdev->mode == BF_INTR_MODE_MSIX) { + pci_disable_msix(bfdev->pdev); + kfree(bfdev->info.msix_entries); + bfdev->info.msix_entries = NULL; + } + else if (bfdev->mode == BF_INTR_MODE_MSI) + pci_disable_msi(bfdev->pdev); +fail_clear_pci_master: + pci_clear_master(pdev); +fail_release_iomem: + bf_pci_release_iomem(&bfdev->info); + pci_release_regions(pdev); +fail_pci_disable: + pci_disable_device(pdev); +fail_free: + kfree(bfdev); + + printk(KERN_ERR "bf probe not ok\n"); + return err; +} + +static void +bf_pci_remove(struct pci_dev *pdev) +{ + struct bf_pci_dev *bfdev = pci_get_drvdata(pdev); + struct bf_listener *cur_listener; + + bf_unregister_device(bfdev); + if (bfdev->mode == BF_INTR_MODE_MSIX) { + pci_disable_msix(pdev); + kfree(bfdev->info.msix_entries); + bfdev->info.msix_entries = NULL; + } + else if (bfdev->mode == BF_INTR_MODE_MSI) + pci_disable_msi(pdev); + pci_clear_master(pdev); + bf_pci_release_iomem(&bfdev->info); + pci_release_regions(pdev); + pci_disable_pcie_error_reporting(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + bf_global[bfdev->info.minor].bfdev = NULL; + /* existing filep structures in open file(s) must be informed that + * bf_pci_dev is no longer valid */ + spin_lock(&bf_nonisr_lock); + cur_listener = bfdev->listener_head; + while (cur_listener) { + cur_listener->bfdev = NULL; + cur_listener = cur_listener->next; + } + spin_unlock(&bf_nonisr_lock); + kfree(bfdev); +} + +/** + * bf_pci_error_detected - called when PCI error is detected + * @pdev: Pointer to PCI device + * @state: The current pci connection state + * + * called when root complex detects pci error associated with the device + */ +static pci_ers_result_t bf_pci_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct bf_pci_dev *bfdev = pci_get_drvdata(pdev); + int minor; + + if (!bfdev) { + return PCI_ERS_RESULT_NONE; + } + printk(KERN_ERR "pci_err_detected state %d\n", state); + if (state == pci_channel_io_perm_failure || state == pci_channel_io_frozen) { + bfdev->info.pci_error_state = 1; + /* send a signal to the user space program of the error */ + minor = bfdev->info.minor; + if (minor < BF_MAX_DEVICE_CNT && bf_global[minor].async_queue) { + kill_fasync(&bf_global[minor].async_queue, SIGIO, POLL_ERR); + } + return PCI_ERS_RESULT_DISCONNECT; + } else { + return PCI_ERS_RESULT_NONE; + } +} + +/** + * bf_pci_slot_reset - called after the pci bus has been reset. + * @pdev: Pointer to PCI device + * + * Restart the card from scratch, as if from a cold-boot. + */ +static pci_ers_result_t bf_pci_slot_reset(struct pci_dev *pdev) +{ + /* nothing to do for now as we do not expect to get backto normal after + * a pcie link reset + * TBD: fill in this function if tofino can recover after an error + */ + return PCI_ERS_RESULT_DISCONNECT; +} + +/** + * bf_pci_resume - called when kernel thinks the device is up on PCIe. + * @pdev: Pointer to PCI device + * + * This callback is called when the error recovery driver tells us that + * its OK to resume normal operation. + */ +static void bf_pci_resume(struct pci_dev *pdev) +{ + /* this function should never be called for Tofinoi */ + struct bf_pci_dev *bfdev = pci_get_drvdata(pdev); + + printk(KERN_ERR "BF io_resume invoked after pci error\n"); + if (bfdev) { + bfdev->info.pci_error_state = 0; + } +} + +static int +bf_config_intr_mode(char *intr_str) +{ + if (!intr_str) { + pr_info("Use MSIX interrupt by default\n"); + return 0; + } + + if (!strcmp(intr_str, BF_INTR_MODE_MSIX_NAME)) { + bf_intr_mode_default = BF_INTR_MODE_MSIX; + pr_info("Use MSIX interrupt\n"); + } else if (!strcmp(intr_str, BF_INTR_MODE_MSI_NAME)) { + bf_intr_mode_default = BF_INTR_MODE_MSI; + pr_info("Use MSI interrupt\n"); + } else if (!strcmp(intr_str, BF_INTR_MODE_LEGACY_NAME)) { + bf_intr_mode_default = BF_INTR_MODE_LEGACY; + pr_info("Use legacy interrupt\n"); + } else { + pr_info("Error: bad parameter - %s\n", intr_str); + return -EINVAL; + } + + return 0; +} + +static const struct pci_device_id bf_pci_tbl[] = { + {PCI_VDEVICE(BF, TOFINO_DEV_ID_A0), 0}, + {PCI_VDEVICE(BF, TOFINO_DEV_ID_B0), 0}, + /* required last entry */ + { .device = 0 } +}; + +/* PCI bus error handlers */ +static struct pci_error_handlers bf_pci_err_handler = { + .error_detected = bf_pci_error_detected, + .slot_reset = bf_pci_slot_reset, + .resume = bf_pci_resume, +}; + +static struct pci_driver bf_pci_driver = { + .name = "bf", + .id_table = bf_pci_tbl, + .probe = bf_pci_probe, + .remove = bf_pci_remove, + .err_handler = &bf_pci_err_handler +}; + +static int __init +bfdrv_init(void) +{ + int ret; + + ret = bf_config_intr_mode(intr_mode); + if (ret < 0) + return ret; + + spin_lock_init(&bf_nonisr_lock); + return pci_register_driver(&bf_pci_driver); +} + +static void __exit +bfdrv_exit(void) +{ + pci_unregister_driver(&bf_pci_driver); +} + +module_init(bfdrv_init); +module_exit(bfdrv_exit); + +module_param(intr_mode, charp, S_IRUGO); +MODULE_PARM_DESC(intr_mode, +"bf interrupt mode (default=msix):\n" +" " BF_INTR_MODE_MSIX_NAME " Use MSIX interrupt\n" +" " BF_INTR_MODE_MSI_NAME " Use MSI interrupt\n" +" " BF_INTR_MODE_LEGACY_NAME " Use Legacy interrupt\n" +"\n"); + +MODULE_DEVICE_TABLE(pci, bf_pci_tbl); +MODULE_DESCRIPTION("Barefoot Tofino PCI device"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Barefoot Networks"); diff --git a/platform/barefoot/sonic-platform-modules-bfn/modules/bf_tun.c b/platform/barefoot/sonic-platform-modules-bfn/modules/bf_tun.c new file mode 100644 index 000000000000..a1ba7047baaa --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/modules/bf_tun.c @@ -0,0 +1,2396 @@ +/* + * TUN - Universal TUN/TAP device driver. + * Copyright (C) 1999-2002 Maxim Krasnyansky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * $Id: tun.c,v 1.15 2002/03/01 02:44:24 maxk Exp $ + */ + +/* + * Changes: + * + * Mike Kershaw 2005/08/14 + * Add TUNSETLINK ioctl to set the link encapsulation + * + * Mark Smith + * Use eth_random_addr() for tap MAC address. + * + * Harald Roelle 2004/04/20 + * Fixes in packet dropping, queue length setting and queue wakeup. + * Increased default tx queue length. + * Added ethtool API. + * Minor cleanups + * + * Daniel Podlejski + * Modifications for 2.3.99-pre5 kernel. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#define DRV_NAME "bf_tun" +#define DRV_VERSION "1.6" +#define DRV_DESCRIPTION "Universal TUN/TAP device driver" +#define DRV_COPYRIGHT "(C) 1999-2004 Max Krasnyansky " + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Uncomment to enable debugging */ +/* #define TUN_DEBUG 1 */ + +#define TUN_MINOR1 201 + +#ifdef TUN_DEBUG +static int debug; + +#define tun_debug(level, tun, fmt, args...) \ +do { \ + if (tun->debug) \ + netdev_printk(level, tun->dev, fmt, ##args); \ +} while (0) +#define DBG1(level, fmt, args...) \ +do { \ + if (debug == 2) \ + printk(level fmt, ##args); \ +} while (0) +#else +#define tun_debug(level, tun, fmt, args...) \ +do { \ + if (0) \ + netdev_printk(level, tun->dev, fmt, ##args); \ +} while (0) +#define DBG1(level, fmt, args...) \ +do { \ + if (0) \ + printk(level fmt, ##args); \ +} while (0) +#endif + +#define GOODCOPY_LEN 128 + +#define FLT_EXACT_COUNT 8 +struct tap_filter { + unsigned int count; /* Number of addrs. Zero means disabled */ + u32 mask[2]; /* Mask of the hashed addrs */ + unsigned char addr[FLT_EXACT_COUNT][ETH_ALEN]; +}; + +/* DEFAULT_MAX_NUM_RSS_QUEUES were chosen to let the rx/tx queues allocated for + * the netdevice to be fit in one page. So we can make sure the success of + * memory allocation. TODO: increase the limit. */ +#define MAX_TAP_QUEUES DEFAULT_MAX_NUM_RSS_QUEUES +#define MAX_TAP_FLOWS 4096 + +#define TUN_FLOW_EXPIRE (3 * HZ) + +/* A tun_file connects an open character device to a tuntap netdevice. It + * also contains all socket related structures (except sock_fprog and tap_filter) + * to serve as one transmit queue for tuntap device. The sock_fprog and + * tap_filter were kept in tun_struct since they were used for filtering for the + * netdevice not for a specific queue (at least I didn't see the requirement for + * this). + * + * RCU usage: + * The tun_file and tun_struct are loosely coupled, the pointer from one to the + * other can only be read while rcu_read_lock or rtnl_lock is held. + */ +struct tun_file { + struct sock sk; + struct socket socket; + struct socket_wq wq; + struct tun_struct __rcu *tun; + struct net *net; + struct fasync_struct *fasync; + /* only used for fasnyc */ + unsigned int flags; + union { + u16 queue_index; + unsigned int ifindex; + }; + struct list_head next; + struct tun_struct *detached; +}; + +struct tun_flow_entry { + struct hlist_node hash_link; + struct rcu_head rcu; + struct tun_struct *tun; + + u32 rxhash; + u32 rps_rxhash; + int queue_index; + unsigned long updated; +}; + +#define TUN_NUM_FLOW_ENTRIES 1024 + +/* Since the socket were moved to tun_file, to preserve the behavior of persist + * device, socket filter, sndbuf and vnet header size were restore when the + * file were attached to a persist device. + */ +struct tun_struct { + struct tun_file __rcu *tfiles[MAX_TAP_QUEUES]; + unsigned int numqueues; + unsigned int flags; + kuid_t owner; + kgid_t group; + + struct net_device *dev; + netdev_features_t set_features; +#define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ + NETIF_F_TSO6|NETIF_F_UFO) + + int vnet_hdr_sz; + int sndbuf; + struct tap_filter txflt; + struct sock_fprog fprog; + /* protected by rtnl lock */ + bool filter_attached; +#ifdef TUN_DEBUG + int debug; +#endif + spinlock_t lock; + struct hlist_head flows[TUN_NUM_FLOW_ENTRIES]; + struct timer_list flow_gc_timer; + unsigned long ageing_time; + unsigned int numdisabled; + struct list_head disabled; + void *security; + u32 flow_count; +}; + +static inline u32 tun_hashfn(u32 rxhash) +{ + return rxhash & 0x3ff; +} + +static struct tun_flow_entry *tun_flow_find(struct hlist_head *head, u32 rxhash) +{ + struct tun_flow_entry *e; + + hlist_for_each_entry_rcu(e, head, hash_link) { + if (e->rxhash == rxhash) + return e; + } + return NULL; +} + +static struct tun_flow_entry *tun_flow_create(struct tun_struct *tun, + struct hlist_head *head, + u32 rxhash, u16 queue_index) +{ + struct tun_flow_entry *e = kmalloc(sizeof(*e), GFP_ATOMIC); + + if (e) { + tun_debug(KERN_INFO, tun, "create flow: hash %u index %u\n", + rxhash, queue_index); + e->updated = jiffies; + e->rxhash = rxhash; + e->rps_rxhash = 0; + e->queue_index = queue_index; + e->tun = tun; + hlist_add_head_rcu(&e->hash_link, head); + ++tun->flow_count; + } + return e; +} + +static void tun_flow_delete(struct tun_struct *tun, struct tun_flow_entry *e) +{ + tun_debug(KERN_INFO, tun, "delete flow: hash %u index %u\n", + e->rxhash, e->queue_index); + sock_rps_reset_flow_hash(e->rps_rxhash); + hlist_del_rcu(&e->hash_link); + kfree_rcu(e, rcu); + --tun->flow_count; +} + +static void tun_flow_flush(struct tun_struct *tun) +{ + int i; + + spin_lock_bh(&tun->lock); + for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) { + struct tun_flow_entry *e; + struct hlist_node *n; + + hlist_for_each_entry_safe(e, n, &tun->flows[i], hash_link) + tun_flow_delete(tun, e); + } + spin_unlock_bh(&tun->lock); +} + +static void tun_flow_delete_by_queue(struct tun_struct *tun, u16 queue_index) +{ + int i; + + spin_lock_bh(&tun->lock); + for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) { + struct tun_flow_entry *e; + struct hlist_node *n; + + hlist_for_each_entry_safe(e, n, &tun->flows[i], hash_link) { + if (e->queue_index == queue_index) + tun_flow_delete(tun, e); + } + } + spin_unlock_bh(&tun->lock); +} + +static void tun_flow_cleanup(unsigned long data) +{ + struct tun_struct *tun = (struct tun_struct *)data; + unsigned long delay = tun->ageing_time; + unsigned long next_timer = jiffies + delay; + unsigned long count = 0; + int i; + + tun_debug(KERN_INFO, tun, "tun_flow_cleanup\n"); + + spin_lock_bh(&tun->lock); + for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) { + struct tun_flow_entry *e; + struct hlist_node *n; + + hlist_for_each_entry_safe(e, n, &tun->flows[i], hash_link) { + unsigned long this_timer; + count++; + this_timer = e->updated + delay; + if (time_before_eq(this_timer, jiffies)) + tun_flow_delete(tun, e); + else if (time_before(this_timer, next_timer)) + next_timer = this_timer; + } + } + + if (count) + mod_timer(&tun->flow_gc_timer, round_jiffies_up(next_timer)); + spin_unlock_bh(&tun->lock); +} + +static void tun_flow_update(struct tun_struct *tun, u32 rxhash, + struct tun_file *tfile) +{ + struct hlist_head *head; + struct tun_flow_entry *e; + unsigned long delay = tun->ageing_time; + u16 queue_index = tfile->queue_index; + + if (!rxhash) + return; + else + head = &tun->flows[tun_hashfn(rxhash)]; + + rcu_read_lock(); + + /* We may get a very small possibility of OOO during switching, not + * worth to optimize.*/ + if (tun->numqueues == 1 || tfile->detached) + goto unlock; + + e = tun_flow_find(head, rxhash); + if (likely(e)) { + /* TODO: keep queueing to old queue until it's empty? */ + e->queue_index = queue_index; + e->updated = jiffies; + sock_rps_record_flow_hash(e->rps_rxhash); + } else { + spin_lock_bh(&tun->lock); + if (!tun_flow_find(head, rxhash) && + tun->flow_count < MAX_TAP_FLOWS) + tun_flow_create(tun, head, rxhash, queue_index); + + if (!timer_pending(&tun->flow_gc_timer)) + mod_timer(&tun->flow_gc_timer, + round_jiffies_up(jiffies + delay)); + spin_unlock_bh(&tun->lock); + } + +unlock: + rcu_read_unlock(); +} + +/** + * Save the hash received in the stack receive path and update the + * flow_hash table accordingly. + */ +static inline void tun_flow_save_rps_rxhash(struct tun_flow_entry *e, u32 hash) +{ + if (unlikely(e->rps_rxhash != hash)) { + sock_rps_reset_flow_hash(e->rps_rxhash); + e->rps_rxhash = hash; + } +} + +/* We try to identify a flow through its rxhash first. The reason that + * we do not check rxq no. is because some cards(e.g 82599), chooses + * the rxq based on the txq where the last packet of the flow comes. As + * the userspace application move between processors, we may get a + * different rxq no. here. If we could not get rxhash, then we would + * hope the rxq no. may help here. + */ +static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback) +{ + struct tun_struct *tun = netdev_priv(dev); + struct tun_flow_entry *e; + u32 txq = 0; + u32 numqueues = 0; + + rcu_read_lock(); + numqueues = ACCESS_ONCE(tun->numqueues); + + txq = skb_get_hash(skb); + if (txq) { + e = tun_flow_find(&tun->flows[tun_hashfn(txq)], txq); + if (e) { + tun_flow_save_rps_rxhash(e, txq); + txq = e->queue_index; + } else + /* use multiply and shift instead of expensive divide */ + txq = ((u64)txq * numqueues) >> 32; + } else if (likely(skb_rx_queue_recorded(skb))) { + txq = skb_get_rx_queue(skb); + while (unlikely(txq >= numqueues)) + txq -= numqueues; + } + + rcu_read_unlock(); + return txq; +} + +static inline bool tun_not_capable(struct tun_struct *tun) +{ + const struct cred *cred = current_cred(); + struct net *net = dev_net(tun->dev); + + return ((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) || + (gid_valid(tun->group) && !in_egroup_p(tun->group))) && + !ns_capable(net->user_ns, CAP_NET_ADMIN); +} + +static void tun_set_real_num_queues(struct tun_struct *tun) +{ + netif_set_real_num_tx_queues(tun->dev, tun->numqueues); + netif_set_real_num_rx_queues(tun->dev, tun->numqueues); +} + +static void tun_disable_queue(struct tun_struct *tun, struct tun_file *tfile) +{ + tfile->detached = tun; + list_add_tail(&tfile->next, &tun->disabled); + ++tun->numdisabled; +} + +static struct tun_struct *tun_enable_queue(struct tun_file *tfile) +{ + struct tun_struct *tun = tfile->detached; + + tfile->detached = NULL; + list_del_init(&tfile->next); + --tun->numdisabled; + return tun; +} + +static void tun_queue_purge(struct tun_file *tfile) +{ + skb_queue_purge(&tfile->sk.sk_receive_queue); + skb_queue_purge(&tfile->sk.sk_error_queue); +} + +static void __tun_detach(struct tun_file *tfile, bool clean) +{ + struct tun_file *ntfile; + struct tun_struct *tun; + + tun = rtnl_dereference(tfile->tun); + + if (tun && !tfile->detached) { + u16 index = tfile->queue_index; + BUG_ON(index >= tun->numqueues); + + rcu_assign_pointer(tun->tfiles[index], + tun->tfiles[tun->numqueues - 1]); + ntfile = rtnl_dereference(tun->tfiles[index]); + ntfile->queue_index = index; + + --tun->numqueues; + if (clean) { + RCU_INIT_POINTER(tfile->tun, NULL); + sock_put(&tfile->sk); + } else + tun_disable_queue(tun, tfile); + + synchronize_net(); + tun_flow_delete_by_queue(tun, tun->numqueues + 1); + /* Drop read queue */ + tun_queue_purge(tfile); + tun_set_real_num_queues(tun); + } else if (tfile->detached && clean) { + tun = tun_enable_queue(tfile); + sock_put(&tfile->sk); + } + + if (clean) { + if (tun && tun->numqueues == 0 && tun->numdisabled == 0) { + netif_carrier_off(tun->dev); + + if (!(tun->flags & TUN_PERSIST) && + tun->dev->reg_state == NETREG_REGISTERED) + unregister_netdevice(tun->dev); + } + + BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED, + &tfile->socket.flags)); + sk_release_kernel(&tfile->sk); + } +} + +static void tun_detach(struct tun_file *tfile, bool clean) +{ + rtnl_lock(); + __tun_detach(tfile, clean); + rtnl_unlock(); +} + +static void tun_detach_all(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + struct tun_file *tfile, *tmp; + int i, n = tun->numqueues; + + for (i = 0; i < n; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + BUG_ON(!tfile); + tfile->socket.sk->sk_data_ready(tfile->socket.sk); + RCU_INIT_POINTER(tfile->tun, NULL); + --tun->numqueues; + } + list_for_each_entry(tfile, &tun->disabled, next) { + tfile->socket.sk->sk_data_ready(tfile->socket.sk); + RCU_INIT_POINTER(tfile->tun, NULL); + } + BUG_ON(tun->numqueues != 0); + + synchronize_net(); + for (i = 0; i < n; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + /* Drop read queue */ + tun_queue_purge(tfile); + sock_put(&tfile->sk); + } + list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) { + tun_enable_queue(tfile); + tun_queue_purge(tfile); + sock_put(&tfile->sk); + } + BUG_ON(tun->numdisabled != 0); + + if (tun->flags & TUN_PERSIST) + module_put(THIS_MODULE); +} + +static int tun_attach(struct tun_struct *tun, struct file *file, bool skip_filter) +{ + struct tun_file *tfile = file->private_data; + int err; + + err = security_tun_dev_attach(tfile->socket.sk, tun->security); + if (err < 0) + goto out; + + err = -EINVAL; + if (rtnl_dereference(tfile->tun) && !tfile->detached) + goto out; + + err = -EBUSY; + if (!(tun->flags & TUN_TAP_MQ) && tun->numqueues == 1) + goto out; + + err = -E2BIG; + if (!tfile->detached && + tun->numqueues + tun->numdisabled == MAX_TAP_QUEUES) + goto out; + + err = 0; + + /* Re-attach the filter to persist device */ + if (!skip_filter && (tun->filter_attached == true)) { + err = __sk_attach_filter(&tun->fprog, tfile->socket.sk, + lockdep_rtnl_is_held()); + if (!err) + goto out; + } + tfile->queue_index = tun->numqueues; + rcu_assign_pointer(tfile->tun, tun); + rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile); + tun->numqueues++; + + if (tfile->detached) + tun_enable_queue(tfile); + else + sock_hold(&tfile->sk); + + tun_set_real_num_queues(tun); + + /* device is allowed to go away first, so no need to hold extra + * refcnt. + */ + +out: + return err; +} + +static struct tun_struct *__tun_get(struct tun_file *tfile) +{ + struct tun_struct *tun; + + rcu_read_lock(); + tun = rcu_dereference(tfile->tun); + if (tun) + dev_hold(tun->dev); + rcu_read_unlock(); + + return tun; +} + +static struct tun_struct *tun_get(struct file *file) +{ + return __tun_get(file->private_data); +} + +static void tun_put(struct tun_struct *tun) +{ + dev_put(tun->dev); +} + +/* TAP filtering */ +static void addr_hash_set(u32 *mask, const u8 *addr) +{ + int n = ether_crc(ETH_ALEN, addr) >> 26; + mask[n >> 5] |= (1 << (n & 31)); +} + +static unsigned int addr_hash_test(const u32 *mask, const u8 *addr) +{ + int n = ether_crc(ETH_ALEN, addr) >> 26; + return mask[n >> 5] & (1 << (n & 31)); +} + +static int update_filter(struct tap_filter *filter, void __user *arg) +{ + struct { u8 u[ETH_ALEN]; } *addr; + struct tun_filter uf; + int err, alen, n, nexact; + + if (copy_from_user(&uf, arg, sizeof(uf))) + return -EFAULT; + + if (!uf.count) { + /* Disabled */ + filter->count = 0; + return 0; + } + + alen = ETH_ALEN * uf.count; + addr = kmalloc(alen, GFP_KERNEL); + if (!addr) + return -ENOMEM; + + if (copy_from_user(addr, arg + sizeof(uf), alen)) { + err = -EFAULT; + goto done; + } + + /* The filter is updated without holding any locks. Which is + * perfectly safe. We disable it first and in the worst + * case we'll accept a few undesired packets. */ + filter->count = 0; + wmb(); + + /* Use first set of addresses as an exact filter */ + for (n = 0; n < uf.count && n < FLT_EXACT_COUNT; n++) + memcpy(filter->addr[n], addr[n].u, ETH_ALEN); + + nexact = n; + + /* Remaining multicast addresses are hashed, + * unicast will leave the filter disabled. */ + memset(filter->mask, 0, sizeof(filter->mask)); + for (; n < uf.count; n++) { + if (!is_multicast_ether_addr(addr[n].u)) { + err = 0; /* no filter */ + goto done; + } + addr_hash_set(filter->mask, addr[n].u); + } + + /* For ALLMULTI just set the mask to all ones. + * This overrides the mask populated above. */ + if ((uf.flags & TUN_FLT_ALLMULTI)) + memset(filter->mask, ~0, sizeof(filter->mask)); + + /* Now enable the filter */ + wmb(); + filter->count = nexact; + + /* Return the number of exact filters */ + err = nexact; + +done: + kfree(addr); + return err; +} + +/* Returns: 0 - drop, !=0 - accept */ +static int run_filter(struct tap_filter *filter, const struct sk_buff *skb) +{ + /* Cannot use eth_hdr(skb) here because skb_mac_hdr() is incorrect + * at this point. */ + struct ethhdr *eh = (struct ethhdr *) skb->data; + int i; + + /* Exact match */ + for (i = 0; i < filter->count; i++) + if (ether_addr_equal(eh->h_dest, filter->addr[i])) + return 1; + + /* Inexact match (multicast only) */ + if (is_multicast_ether_addr(eh->h_dest)) + return addr_hash_test(filter->mask, eh->h_dest); + + return 0; +} + +/* + * Checks whether the packet is accepted or not. + * Returns: 0 - drop, !=0 - accept + */ +static int check_filter(struct tap_filter *filter, const struct sk_buff *skb) +{ + if (!filter->count) + return 1; + + return run_filter(filter, skb); +} + +/* Network device part of the driver */ + +static const struct ethtool_ops tun_ethtool_ops; + +/* Net device detach from fd. */ +static void tun_net_uninit(struct net_device *dev) +{ + tun_detach_all(dev); +} + +/* Net device open. */ +static int tun_net_open(struct net_device *dev) +{ + netif_tx_start_all_queues(dev); + return 0; +} + +/* Net device close. */ +static int tun_net_close(struct net_device *dev) +{ + netif_tx_stop_all_queues(dev); + return 0; +} + +/* Net device start xmit */ +static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + int txq = skb->queue_mapping; + struct tun_file *tfile; + u32 numqueues = 0; + + rcu_read_lock(); + tfile = rcu_dereference(tun->tfiles[txq]); + numqueues = ACCESS_ONCE(tun->numqueues); + + /* Drop packet if interface is not attached */ + if (txq >= numqueues) + goto drop; + + if (numqueues == 1) { + /* Select queue was not called for the skbuff, so we extract the + * RPS hash and save it into the flow_table here. + */ + __u32 rxhash; + + rxhash = skb_get_hash(skb); + if (rxhash) { + struct tun_flow_entry *e; + e = tun_flow_find(&tun->flows[tun_hashfn(rxhash)], + rxhash); + if (e) + tun_flow_save_rps_rxhash(e, rxhash); + } + } + + tun_debug(KERN_INFO, tun, "tun_net_xmit %d\n", skb->len); + + BUG_ON(!tfile); + + /* Drop if the filter does not like it. + * This is a noop if the filter is disabled. + * Filter can be enabled only for the TAP devices. */ + if (!check_filter(&tun->txflt, skb)) + goto drop; + + if (tfile->socket.sk->sk_filter && + sk_filter(tfile->socket.sk, skb)) + goto drop; + + /* Limit the number of packets queued by dividing txq length with the + * number of queues. + */ + if (skb_queue_len(&tfile->socket.sk->sk_receive_queue) * numqueues + >= dev->tx_queue_len) + goto drop; + + if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC))) + goto drop; + + if (skb->sk) { + sock_tx_timestamp(skb->sk, &skb_shinfo(skb)->tx_flags); + sw_tx_timestamp(skb); + } + + /* Orphan the skb - required as we might hang on to it + * for indefinite time. + */ + skb_orphan(skb); + + nf_reset(skb); + + /* Enqueue packet */ + skb_queue_tail(&tfile->socket.sk->sk_receive_queue, skb); + + /* Notify and wake up reader process */ + if (tfile->flags & TUN_FASYNC) + kill_fasync(&tfile->fasync, SIGIO, POLL_IN); + tfile->socket.sk->sk_data_ready(tfile->socket.sk); + + rcu_read_unlock(); + return NETDEV_TX_OK; + +drop: + dev->stats.tx_dropped++; + skb_tx_error(skb); + kfree_skb(skb); + rcu_read_unlock(); + return NETDEV_TX_OK; +} + +static void tun_net_mclist(struct net_device *dev) +{ + /* + * This callback is supposed to deal with mc filter in + * _rx_ path and has nothing to do with the _tx_ path. + * In rx path we always accept everything userspace gives us. + */ +} + +#define MIN_MTU 68 +#define MAX_MTU 65535 + +static int +tun_net_change_mtu(struct net_device *dev, int new_mtu) +{ + if (new_mtu < MIN_MTU || new_mtu + dev->hard_header_len > MAX_MTU) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + +static netdev_features_t tun_net_fix_features(struct net_device *dev, + netdev_features_t features) +{ + struct tun_struct *tun = netdev_priv(dev); + + return (features & tun->set_features) | (features & ~TUN_USER_FEATURES); +} + +static int +tun_change_carrier(struct net_device *dev, bool new_carrier) { + if (new_carrier) + netif_carrier_on(dev); + else + netif_carrier_off(dev); + return 0; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void tun_poll_controller(struct net_device *dev) +{ + /* + * Tun only receives frames when: + * 1) the char device endpoint gets data from user space + * 2) the tun socket gets a sendmsg call from user space + * Since both of those are synchronous operations, we are guaranteed + * never to have pending data when we poll for it + * so there is nothing to do here but return. + * We need this though so netpoll recognizes us as an interface that + * supports polling, which enables bridge devices in virt setups to + * still use netconsole + */ + return; +} +#endif +static const struct net_device_ops tun_netdev_ops = { + .ndo_uninit = tun_net_uninit, + .ndo_open = tun_net_open, + .ndo_stop = tun_net_close, + .ndo_start_xmit = tun_net_xmit, + .ndo_change_mtu = tun_net_change_mtu, + .ndo_fix_features = tun_net_fix_features, + .ndo_select_queue = tun_select_queue, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = tun_poll_controller, +#endif +}; + +static const struct net_device_ops tap_netdev_ops = { + .ndo_uninit = tun_net_uninit, + .ndo_open = tun_net_open, + .ndo_stop = tun_net_close, + .ndo_start_xmit = tun_net_xmit, + .ndo_change_mtu = tun_net_change_mtu, + .ndo_fix_features = tun_net_fix_features, + .ndo_set_rx_mode = tun_net_mclist, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_select_queue = tun_select_queue, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = tun_poll_controller, +#endif + .ndo_change_carrier = tun_change_carrier, +}; + +static void tun_flow_init(struct tun_struct *tun) +{ + int i; + + for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) + INIT_HLIST_HEAD(&tun->flows[i]); + + tun->ageing_time = TUN_FLOW_EXPIRE; + setup_timer(&tun->flow_gc_timer, tun_flow_cleanup, (unsigned long)tun); + mod_timer(&tun->flow_gc_timer, + round_jiffies_up(jiffies + tun->ageing_time)); +} + +static void tun_flow_uninit(struct tun_struct *tun) +{ + del_timer_sync(&tun->flow_gc_timer); + tun_flow_flush(tun); +} + +/* Initialize net device. */ +static void tun_net_init(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + + switch (tun->flags & TUN_TYPE_MASK) { + case TUN_TUN_DEV: + dev->netdev_ops = &tun_netdev_ops; + + /* Point-to-Point TUN Device */ + dev->hard_header_len = 0; + dev->addr_len = 0; + dev->mtu = 1500; + + /* Zero header length */ + dev->type = ARPHRD_NONE; + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + dev->tx_queue_len = TUN_READQ_SIZE*2; /* We prefer our own queue length */ + break; + + case TUN_TAP_DEV: + dev->netdev_ops = &tap_netdev_ops; + /* Ethernet TAP Device */ + ether_setup(dev); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + + eth_hw_addr_random(dev); + + dev->tx_queue_len = TUN_READQ_SIZE*2; /* We prefer our own queue length */ + break; + } +} + +/* Character device part */ + +/* Poll */ +static unsigned int tun_chr_poll(struct file *file, poll_table *wait) +{ + struct tun_file *tfile = file->private_data; + struct tun_struct *tun = __tun_get(tfile); + struct sock *sk; + unsigned int mask = 0; + + if (!tun) + return POLLERR; + + sk = tfile->socket.sk; + + tun_debug(KERN_INFO, tun, "tun_chr_poll\n"); + + poll_wait(file, sk_sleep(sk), wait); + + if (!skb_queue_empty(&sk->sk_receive_queue)) + mask |= POLLIN | POLLRDNORM; + + if (sock_writeable(sk) || + (!test_and_set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags) && + sock_writeable(sk))) + mask |= POLLOUT | POLLWRNORM; + + if (tun->dev->reg_state != NETREG_REGISTERED) + mask = POLLERR; + + tun_put(tun); + return mask; +} + +/* prepad is the amount to reserve at front. len is length after that. + * linear is a hint as to how much to copy (usually headers). */ +static struct sk_buff *tun_alloc_skb(struct tun_file *tfile, + size_t prepad, size_t len, + size_t linear, int noblock) +{ + struct sock *sk = tfile->socket.sk; + struct sk_buff *skb; + int err; + + /* Under a page? Don't bother with paged skb. */ + if (prepad + len < PAGE_SIZE || !linear) + linear = len; + + skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock, + &err, 0); + if (!skb) + return ERR_PTR(err); + + skb_reserve(skb, prepad); + skb_put(skb, linear); + skb->data_len = len - linear; + skb->len += len - linear; + + return skb; +} + +/* Get packet from user space buffer */ +static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, + void *msg_control, const struct iovec *iv, + size_t total_len, size_t count, int noblock) +{ + struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; + struct sk_buff *skb; + size_t len = total_len, align = NET_SKB_PAD, linear; + struct virtio_net_hdr gso = { 0 }; + int good_linear; + int offset = 0; + int copylen; + bool zerocopy = false; + int err; + u32 rxhash; + + if (!(tun->flags & TUN_NO_PI)) { + if (len < sizeof(pi)) + return -EINVAL; + len -= sizeof(pi); + + if (memcpy_fromiovecend((void *)&pi, iv, 0, sizeof(pi))) + return -EFAULT; + offset += sizeof(pi); + } + + if (tun->flags & TUN_VNET_HDR) { + if (len < tun->vnet_hdr_sz) + return -EINVAL; + len -= tun->vnet_hdr_sz; + + if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso))) + return -EFAULT; + + if ((gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && + gso.csum_start + gso.csum_offset + 2 > gso.hdr_len) + gso.hdr_len = gso.csum_start + gso.csum_offset + 2; + + if (gso.hdr_len > len) + return -EINVAL; + offset += tun->vnet_hdr_sz; + } + + if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { + align += NET_IP_ALIGN; + if (unlikely(len < ETH_HLEN || + (gso.hdr_len && gso.hdr_len < ETH_HLEN))) + return -EINVAL; + } + + good_linear = SKB_MAX_HEAD(align); + + if (msg_control) { + /* There are 256 bytes to be copied in skb, so there is + * enough room for skb expand head in case it is used. + * The rest of the buffer is mapped from userspace. + */ + copylen = gso.hdr_len ? gso.hdr_len : GOODCOPY_LEN; + if (copylen > good_linear) + copylen = good_linear; + linear = copylen; + if (iov_pages(iv, offset + copylen, count) <= MAX_SKB_FRAGS) + zerocopy = true; + } + + if (!zerocopy) { + copylen = len; + if (gso.hdr_len > good_linear) + linear = good_linear; + else + linear = gso.hdr_len; + } + + skb = tun_alloc_skb(tfile, align, copylen, linear, noblock); + if (IS_ERR(skb)) { + if (PTR_ERR(skb) != -EAGAIN) + tun->dev->stats.rx_dropped++; + return PTR_ERR(skb); + } + + if (zerocopy) + err = zerocopy_sg_from_iovec(skb, iv, offset, count); + else { + err = skb_copy_datagram_from_iovec(skb, 0, iv, offset, len); + if (!err && msg_control) { + struct ubuf_info *uarg = msg_control; + uarg->callback(uarg, false); + } + } + + if (err) { + tun->dev->stats.rx_dropped++; + kfree_skb(skb); + return -EFAULT; + } + + if (gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { + if (!skb_partial_csum_set(skb, gso.csum_start, + gso.csum_offset)) { + tun->dev->stats.rx_frame_errors++; + kfree_skb(skb); + return -EINVAL; + } + } + + switch (tun->flags & TUN_TYPE_MASK) { + case TUN_TUN_DEV: + if (tun->flags & TUN_NO_PI) { + switch (skb->data[0] & 0xf0) { + case 0x40: + pi.proto = htons(ETH_P_IP); + break; + case 0x60: + pi.proto = htons(ETH_P_IPV6); + break; + default: + tun->dev->stats.rx_dropped++; + kfree_skb(skb); + return -EINVAL; + } + } + + skb_reset_mac_header(skb); + skb->protocol = pi.proto; + skb->dev = tun->dev; + break; + case TUN_TAP_DEV: + skb->protocol = eth_type_trans(skb, tun->dev); + break; + } + + skb_reset_network_header(skb); + + if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) { + pr_debug("GSO!\n"); + switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { + case VIRTIO_NET_HDR_GSO_TCPV4: + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; + break; + case VIRTIO_NET_HDR_GSO_TCPV6: + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; + break; + case VIRTIO_NET_HDR_GSO_UDP: + skb_shinfo(skb)->gso_type = SKB_GSO_UDP; + if (skb->protocol == htons(ETH_P_IPV6)) + ipv6_proxy_select_ident(skb); + break; + default: + tun->dev->stats.rx_frame_errors++; + kfree_skb(skb); + return -EINVAL; + } + + if (gso.gso_type & VIRTIO_NET_HDR_GSO_ECN) + skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; + + skb_shinfo(skb)->gso_size = gso.gso_size; + if (skb_shinfo(skb)->gso_size == 0) { + tun->dev->stats.rx_frame_errors++; + kfree_skb(skb); + return -EINVAL; + } + + /* Header must be checked, and gso_segs computed. */ + skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; + skb_shinfo(skb)->gso_segs = 0; + } + + /* copy skb_ubuf_info for callback when skb has no error */ + if (zerocopy) { + skb_shinfo(skb)->destructor_arg = msg_control; + skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; + skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; + } + + skb_probe_transport_header(skb, 0); + + rxhash = skb_get_hash(skb); + netif_rx_ni(skb); + + tun->dev->stats.rx_packets++; + tun->dev->stats.rx_bytes += len; + + tun_flow_update(tun, rxhash, tfile); + return total_len; +} + +static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, + unsigned long count, loff_t pos) +{ + struct file *file = iocb->ki_filp; + struct tun_struct *tun = tun_get(file); + struct tun_file *tfile = file->private_data; + ssize_t result; + + if (!tun) + return -EBADFD; + + tun_debug(KERN_INFO, tun, "tun_chr_write %ld\n", count); + + result = tun_get_user(tun, tfile, NULL, iv, iov_length(iv, count), + count, file->f_flags & O_NONBLOCK); + + tun_put(tun); + return result; +} + +/* Put packet to the user space buffer */ +static ssize_t tun_put_user(struct tun_struct *tun, + struct tun_file *tfile, + struct sk_buff *skb, + const struct iovec *iv, int len) +{ + struct tun_pi pi = { 0, skb->protocol }; + ssize_t total = 0; + int vlan_offset = 0, copied; + int vlan_hlen = 0; + + if (vlan_tx_tag_present(skb)) + vlan_hlen = VLAN_HLEN; + + if (!(tun->flags & TUN_NO_PI)) { + if ((len -= sizeof(pi)) < 0) + return -EINVAL; + + if (len < skb->len) { + /* Packet will be striped */ + pi.flags |= TUN_PKT_STRIP; + } + + if (memcpy_toiovecend(iv, (void *) &pi, 0, sizeof(pi))) + return -EFAULT; + total += sizeof(pi); + } + + if (tun->flags & TUN_VNET_HDR) { + struct virtio_net_hdr gso = { 0 }; /* no info leak */ + if ((len -= tun->vnet_hdr_sz) < 0) + return -EINVAL; + + if (skb_is_gso(skb)) { + struct skb_shared_info *sinfo = skb_shinfo(skb); + + /* This is a hint as to how much should be linear. */ + gso.hdr_len = skb_headlen(skb); + gso.gso_size = sinfo->gso_size; + if (sinfo->gso_type & SKB_GSO_TCPV4) + gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; + else if (sinfo->gso_type & SKB_GSO_TCPV6) + gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; + else if (sinfo->gso_type & SKB_GSO_UDP) + gso.gso_type = VIRTIO_NET_HDR_GSO_UDP; + else { + pr_err("unexpected GSO type: " + "0x%x, gso_size %d, hdr_len %d\n", + sinfo->gso_type, gso.gso_size, + gso.hdr_len); + print_hex_dump(KERN_ERR, "tun: ", + DUMP_PREFIX_NONE, + 16, 1, skb->head, + min((int)gso.hdr_len, 64), true); + WARN_ON_ONCE(1); + return -EINVAL; + } + if (sinfo->gso_type & SKB_GSO_TCP_ECN) + gso.gso_type |= VIRTIO_NET_HDR_GSO_ECN; + } else + gso.gso_type = VIRTIO_NET_HDR_GSO_NONE; + + if (skb->ip_summed == CHECKSUM_PARTIAL) { + gso.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; + gso.csum_start = skb_checksum_start_offset(skb) + + vlan_hlen; + gso.csum_offset = skb->csum_offset; + } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + gso.flags = VIRTIO_NET_HDR_F_DATA_VALID; + } /* else everything is zero */ + + if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total, + sizeof(gso)))) + return -EFAULT; + total += tun->vnet_hdr_sz; + } + + copied = total; + len = min_t(int, skb->len + vlan_hlen, len); + total += skb->len + vlan_hlen; + if (vlan_hlen) { + int copy, ret; + struct { + __be16 h_vlan_proto; + __be16 h_vlan_TCI; + } veth; + + veth.h_vlan_proto = skb->vlan_proto; + veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb)); + + vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto); + + copy = min_t(int, vlan_offset, len); + ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy); + len -= copy; + copied += copy; + if (ret || !len) + goto done; + + copy = min_t(int, sizeof(veth), len); + ret = memcpy_toiovecend(iv, (void *)&veth, copied, copy); + len -= copy; + copied += copy; + if (ret || !len) + goto done; + } + + skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len); + +done: + tun->dev->stats.tx_packets++; + tun->dev->stats.tx_bytes += len; + + return total; +} + +static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile, + const struct iovec *iv, ssize_t len, int noblock) +{ + struct sk_buff *skb; + ssize_t ret = 0; + int peeked, err, off = 0; + + tun_debug(KERN_INFO, tun, "tun_do_read\n"); + + if (!len) + return ret; + + if (tun->dev->reg_state != NETREG_REGISTERED) + return -EIO; + + /* Read frames from queue */ + skb = __skb_recv_datagram(tfile->socket.sk, noblock ? MSG_DONTWAIT : 0, + &peeked, &off, &err); + if (skb) { + ret = tun_put_user(tun, tfile, skb, iv, len); + kfree_skb(skb); + } else + ret = err; + + return ret; +} + +static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, + unsigned long count, loff_t pos) +{ + struct file *file = iocb->ki_filp; + struct tun_file *tfile = file->private_data; + struct tun_struct *tun = __tun_get(tfile); + ssize_t len, ret; + + if (!tun) + return -EBADFD; + len = iov_length(iv, count); + if (len < 0) { + ret = -EINVAL; + goto out; + } + + ret = tun_do_read(tun, tfile, iv, len, + file->f_flags & O_NONBLOCK); + ret = min_t(ssize_t, ret, len); + if (ret > 0) + iocb->ki_pos = ret; +out: + tun_put(tun); + return ret; +} + +static void tun_free_netdev(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + + BUG_ON(!(list_empty(&tun->disabled))); + tun_flow_uninit(tun); + security_tun_dev_free_security(tun->security); + free_netdev(dev); +} + +static void tun_setup(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + + tun->owner = INVALID_UID; + tun->group = INVALID_GID; + + dev->ethtool_ops = &tun_ethtool_ops; + dev->destructor = tun_free_netdev; +} + +/* Trivial set of netlink ops to allow deleting tun or tap + * device with netlink. + */ +static int tun_validate(struct nlattr *tb[], struct nlattr *data[]) +{ + return -EINVAL; +} + +static struct rtnl_link_ops tun_link_ops __read_mostly = { + .kind = DRV_NAME, + .priv_size = sizeof(struct tun_struct), + .setup = tun_setup, + .validate = tun_validate, +}; + +static void tun_sock_write_space(struct sock *sk) +{ + struct tun_file *tfile; + wait_queue_head_t *wqueue; + + if (!sock_writeable(sk)) + return; + + if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags)) + return; + + wqueue = sk_sleep(sk); + if (wqueue && waitqueue_active(wqueue)) + wake_up_interruptible_sync_poll(wqueue, POLLOUT | + POLLWRNORM | POLLWRBAND); + + tfile = container_of(sk, struct tun_file, sk); + kill_fasync(&tfile->fasync, SIGIO, POLL_OUT); +} + +static int tun_sendmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len) +{ + int ret; + struct tun_file *tfile = container_of(sock, struct tun_file, socket); + struct tun_struct *tun = __tun_get(tfile); + + if (!tun) + return -EBADFD; + ret = tun_get_user(tun, tfile, m->msg_control, m->msg_iov, total_len, + m->msg_iovlen, m->msg_flags & MSG_DONTWAIT); + tun_put(tun); + return ret; +} + +static int tun_recvmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len, + int flags) +{ + struct tun_file *tfile = container_of(sock, struct tun_file, socket); + struct tun_struct *tun = __tun_get(tfile); + int ret; + + if (!tun) + return -EBADFD; + + if (flags & ~(MSG_DONTWAIT|MSG_TRUNC|MSG_ERRQUEUE)) { + ret = -EINVAL; + goto out; + } + if (flags & MSG_ERRQUEUE) { + ret = sock_recv_errqueue(sock->sk, m, total_len, + SOL_PACKET, TUN_TX_TIMESTAMP); + goto out; + } + ret = tun_do_read(tun, tfile, m->msg_iov, total_len, + flags & MSG_DONTWAIT); + if (ret > total_len) { + m->msg_flags |= MSG_TRUNC; + ret = flags & MSG_TRUNC ? ret : total_len; + } +out: + tun_put(tun); + return ret; +} + +static int tun_release(struct socket *sock) +{ + if (sock->sk) + sock_put(sock->sk); + return 0; +} + +/* Ops structure to mimic raw sockets with tun */ +static const struct proto_ops tun_socket_ops = { + .sendmsg = tun_sendmsg, + .recvmsg = tun_recvmsg, + .release = tun_release, +}; + +static struct proto tun_proto = { + .name = "bf_tun", + .owner = THIS_MODULE, + .obj_size = sizeof(struct tun_file), +}; + +static int tun_flags(struct tun_struct *tun) +{ + int flags = 0; + + if (tun->flags & TUN_TUN_DEV) + flags |= IFF_TUN; + else + flags |= IFF_TAP; + + if (tun->flags & TUN_NO_PI) + flags |= IFF_NO_PI; + + /* This flag has no real effect. We track the value for backwards + * compatibility. + */ + if (tun->flags & TUN_ONE_QUEUE) + flags |= IFF_ONE_QUEUE; + + if (tun->flags & TUN_VNET_HDR) + flags |= IFF_VNET_HDR; + + if (tun->flags & TUN_TAP_MQ) + flags |= IFF_MULTI_QUEUE; + + if (tun->flags & TUN_PERSIST) + flags |= IFF_PERSIST; + + return flags; +} + +static ssize_t tun_show_flags(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return sprintf(buf, "0x%x\n", tun_flags(tun)); +} + +static ssize_t tun_show_owner(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return uid_valid(tun->owner)? + sprintf(buf, "%u\n", + from_kuid_munged(current_user_ns(), tun->owner)): + sprintf(buf, "-1\n"); +} + +static ssize_t tun_show_group(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return gid_valid(tun->group) ? + sprintf(buf, "%u\n", + from_kgid_munged(current_user_ns(), tun->group)): + sprintf(buf, "-1\n"); +} + +static DEVICE_ATTR(tun_flags, 0444, tun_show_flags, NULL); +static DEVICE_ATTR(owner, 0444, tun_show_owner, NULL); +static DEVICE_ATTR(group, 0444, tun_show_group, NULL); + +static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) +{ + struct tun_struct *tun; + struct tun_file *tfile = file->private_data; + struct net_device *dev; + int err; + + if (tfile->detached) + return -EINVAL; + + dev = __dev_get_by_name(net, ifr->ifr_name); + if (dev) { + if (ifr->ifr_flags & IFF_TUN_EXCL) + return -EBUSY; + if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops) + tun = netdev_priv(dev); + else if ((ifr->ifr_flags & IFF_TAP) && dev->netdev_ops == &tap_netdev_ops) + tun = netdev_priv(dev); + else + return -EINVAL; + + if (!!(ifr->ifr_flags & IFF_MULTI_QUEUE) != + !!(tun->flags & TUN_TAP_MQ)) + return -EINVAL; + + if (tun_not_capable(tun)) + return -EPERM; + err = security_tun_dev_open(tun->security); + if (err < 0) + return err; + + err = tun_attach(tun, file, ifr->ifr_flags & IFF_NOFILTER); + if (err < 0) + return err; + + if (tun->flags & TUN_TAP_MQ && + (tun->numqueues + tun->numdisabled > 1)) { + /* One or more queue has already been attached, no need + * to initialize the device again. + */ + return 0; + } + } + else { + char *name; + unsigned long flags = 0; + int queues = ifr->ifr_flags & IFF_MULTI_QUEUE ? + MAX_TAP_QUEUES : 1; + + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + return -EPERM; + err = security_tun_dev_create(); + if (err < 0) + return err; + + /* Set dev type */ + if (ifr->ifr_flags & IFF_TUN) { + /* TUN device */ + flags |= TUN_TUN_DEV; + name = "tun%d"; + } else if (ifr->ifr_flags & IFF_TAP) { + /* TAP device */ + flags |= TUN_TAP_DEV; + name = "tap%d"; + } else + return -EINVAL; + + if (*ifr->ifr_name) + name = ifr->ifr_name; + + dev = alloc_netdev_mqs(sizeof(struct tun_struct), name, + tun_setup, queues, queues); + + if (!dev) + return -ENOMEM; + + dev_net_set(dev, net); + dev->rtnl_link_ops = &tun_link_ops; + dev->ifindex = tfile->ifindex; + + tun = netdev_priv(dev); + tun->dev = dev; + tun->flags = flags; + tun->txflt.count = 0; + tun->vnet_hdr_sz = sizeof(struct virtio_net_hdr); + + tun->filter_attached = false; + tun->sndbuf = tfile->socket.sk->sk_sndbuf; + + spin_lock_init(&tun->lock); + + err = security_tun_dev_alloc_security(&tun->security); + if (err < 0) + goto err_free_dev; + + tun_net_init(dev); + tun_flow_init(tun); + + dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | + TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_STAG_TX; + dev->features = dev->hw_features; + dev->vlan_features = dev->features & + ~(NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_STAG_TX); + + INIT_LIST_HEAD(&tun->disabled); + err = tun_attach(tun, file, false); + if (err < 0) + goto err_free_flow; + + err = register_netdevice(tun->dev); + if (err < 0) + goto err_detach; + + if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) || + device_create_file(&tun->dev->dev, &dev_attr_owner) || + device_create_file(&tun->dev->dev, &dev_attr_group)) + pr_err("Failed to create tun sysfs files\n"); + } + + netif_carrier_on(tun->dev); + + tun_debug(KERN_INFO, tun, "tun_set_iff\n"); + + if (ifr->ifr_flags & IFF_NO_PI) + tun->flags |= TUN_NO_PI; + else + tun->flags &= ~TUN_NO_PI; + + /* This flag has no real effect. We track the value for backwards + * compatibility. + */ + if (ifr->ifr_flags & IFF_ONE_QUEUE) + tun->flags |= TUN_ONE_QUEUE; + else + tun->flags &= ~TUN_ONE_QUEUE; + + if (ifr->ifr_flags & IFF_VNET_HDR) + tun->flags |= TUN_VNET_HDR; + else + tun->flags &= ~TUN_VNET_HDR; + + if (ifr->ifr_flags & IFF_MULTI_QUEUE) + tun->flags |= TUN_TAP_MQ; + else + tun->flags &= ~TUN_TAP_MQ; + + /* Make sure persistent devices do not get stuck in + * xoff state. + */ + if (netif_running(tun->dev)) + netif_tx_wake_all_queues(tun->dev); + + strcpy(ifr->ifr_name, tun->dev->name); + return 0; + +err_detach: + tun_detach_all(dev); +err_free_flow: + tun_flow_uninit(tun); + security_tun_dev_free_security(tun->security); +err_free_dev: + free_netdev(dev); + return err; +} + +static void tun_get_iff(struct net *net, struct tun_struct *tun, + struct ifreq *ifr) +{ + tun_debug(KERN_INFO, tun, "tun_get_iff\n"); + + strcpy(ifr->ifr_name, tun->dev->name); + + ifr->ifr_flags = tun_flags(tun); + +} + +/* This is like a cut-down ethtool ops, except done via tun fd so no + * privs required. */ +static int set_offload(struct tun_struct *tun, unsigned long arg) +{ + netdev_features_t features = 0; + + if (arg & TUN_F_CSUM) { + features |= NETIF_F_HW_CSUM; + arg &= ~TUN_F_CSUM; + + if (arg & (TUN_F_TSO4|TUN_F_TSO6)) { + if (arg & TUN_F_TSO_ECN) { + features |= NETIF_F_TSO_ECN; + arg &= ~TUN_F_TSO_ECN; + } + if (arg & TUN_F_TSO4) + features |= NETIF_F_TSO; + if (arg & TUN_F_TSO6) + features |= NETIF_F_TSO6; + arg &= ~(TUN_F_TSO4|TUN_F_TSO6); + } + + if (arg & TUN_F_UFO) { + features |= NETIF_F_UFO; + arg &= ~TUN_F_UFO; + } + } + + /* This gives the user a way to test for new features in future by + * trying to set them. */ + if (arg) + return -EINVAL; + + tun->set_features = features; + netdev_update_features(tun->dev); + + return 0; +} + +static void tun_detach_filter(struct tun_struct *tun, int n) +{ + int i; + struct tun_file *tfile; + + for (i = 0; i < n; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + __sk_detach_filter(tfile->socket.sk, lockdep_rtnl_is_held()); + } + + tun->filter_attached = false; +} + +static int tun_attach_filter(struct tun_struct *tun) +{ + int i, ret = 0; + struct tun_file *tfile; + + for (i = 0; i < tun->numqueues; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + ret = __sk_attach_filter(&tun->fprog, tfile->socket.sk, + lockdep_rtnl_is_held()); + if (ret) { + tun_detach_filter(tun, i); + return ret; + } + } + + tun->filter_attached = true; + return ret; +} + +static void tun_set_sndbuf(struct tun_struct *tun) +{ + struct tun_file *tfile; + int i; + + for (i = 0; i < tun->numqueues; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + tfile->socket.sk->sk_sndbuf = tun->sndbuf; + } +} + +static int tun_set_queue(struct file *file, struct ifreq *ifr) +{ + struct tun_file *tfile = file->private_data; + struct tun_struct *tun; + int ret = 0; + + rtnl_lock(); + + if (ifr->ifr_flags & IFF_ATTACH_QUEUE) { + tun = tfile->detached; + if (!tun) { + ret = -EINVAL; + goto unlock; + } + ret = security_tun_dev_attach_queue(tun->security); + if (ret < 0) + goto unlock; + ret = tun_attach(tun, file, false); + } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) { + tun = rtnl_dereference(tfile->tun); + if (!tun || !(tun->flags & TUN_TAP_MQ) || tfile->detached) + ret = -EINVAL; + else + __tun_detach(tfile, false); + } else + ret = -EINVAL; + +unlock: + rtnl_unlock(); + return ret; +} + +static long __tun_chr_ioctl(struct file *file, unsigned int cmd, + unsigned long arg, int ifreq_len) +{ + struct tun_file *tfile = file->private_data; + struct tun_struct *tun; + void __user* argp = (void __user*)arg; + struct ifreq ifr; + kuid_t owner; + kgid_t group; + int sndbuf; + int vnet_hdr_sz; + unsigned int ifindex; + int ret; + + if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == 0x89) { + if (copy_from_user(&ifr, argp, ifreq_len)) + return -EFAULT; + } else { + memset(&ifr, 0, sizeof(ifr)); + } + if (cmd == TUNGETFEATURES) { + /* Currently this just means: "what IFF flags are valid?". + * This is needed because we never checked for invalid flags on + * TUNSETIFF. */ + return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE | + IFF_VNET_HDR | IFF_MULTI_QUEUE, + (unsigned int __user*)argp); + } else if (cmd == TUNSETQUEUE) + return tun_set_queue(file, &ifr); + + ret = 0; + rtnl_lock(); + + tun = __tun_get(tfile); + if (cmd == TUNSETIFF && !tun) { + ifr.ifr_name[IFNAMSIZ-1] = '\0'; + + ret = tun_set_iff(tfile->net, file, &ifr); + + if (ret) + goto unlock; + + if (copy_to_user(argp, &ifr, ifreq_len)) + ret = -EFAULT; + goto unlock; + } + if (cmd == TUNSETIFINDEX) { + ret = -EPERM; + if (tun) + goto unlock; + + ret = -EFAULT; + if (copy_from_user(&ifindex, argp, sizeof(ifindex))) + goto unlock; + + ret = 0; + tfile->ifindex = ifindex; + goto unlock; + } + + ret = -EBADFD; + if (!tun) + goto unlock; + + tun_debug(KERN_INFO, tun, "tun_chr_ioctl cmd %u\n", cmd); + + ret = 0; + switch (cmd) { + case TUNGETIFF: + tun_get_iff(current->nsproxy->net_ns, tun, &ifr); + + if (tfile->detached) + ifr.ifr_flags |= IFF_DETACH_QUEUE; + if (!tfile->socket.sk->sk_filter) + ifr.ifr_flags |= IFF_NOFILTER; + + if (copy_to_user(argp, &ifr, ifreq_len)) + ret = -EFAULT; + break; + + case TUNSETNOCSUM: + /* Disable/Enable checksum */ + + /* [unimplemented] */ + tun_debug(KERN_INFO, tun, "ignored: set checksum %s\n", + arg ? "disabled" : "enabled"); + break; + + case TUNSETPERSIST: + /* Disable/Enable persist mode. Keep an extra reference to the + * module to prevent the module being unprobed. + */ + if (arg && !(tun->flags & TUN_PERSIST)) { + tun->flags |= TUN_PERSIST; + __module_get(THIS_MODULE); + } + if (!arg && (tun->flags & TUN_PERSIST)) { + tun->flags &= ~TUN_PERSIST; + module_put(THIS_MODULE); + } + + tun_debug(KERN_INFO, tun, "persist %s\n", + arg ? "enabled" : "disabled"); + break; + + case TUNSETOWNER: + /* Set owner of the device */ + owner = make_kuid(current_user_ns(), arg); + if (!uid_valid(owner)) { + ret = -EINVAL; + break; + } + tun->owner = owner; + tun_debug(KERN_INFO, tun, "owner set to %u\n", + from_kuid(&init_user_ns, tun->owner)); + break; + + case TUNSETGROUP: + /* Set group of the device */ + group = make_kgid(current_user_ns(), arg); + if (!gid_valid(group)) { + ret = -EINVAL; + break; + } + tun->group = group; + tun_debug(KERN_INFO, tun, "group set to %u\n", + from_kgid(&init_user_ns, tun->group)); + break; + + case TUNSETLINK: + /* Only allow setting the type when the interface is down */ + if (tun->dev->flags & IFF_UP) { + tun_debug(KERN_INFO, tun, + "Linktype set failed because interface is up\n"); + ret = -EBUSY; + } else { + tun->dev->type = (int) arg; + tun_debug(KERN_INFO, tun, "linktype set to %d\n", + tun->dev->type); + ret = 0; + } + break; + +#ifdef TUN_DEBUG + case TUNSETDEBUG: + tun->debug = arg; + break; +#endif + case TUNSETOFFLOAD: + ret = set_offload(tun, arg); + break; + + case TUNSETTXFILTER: + /* Can be set only for TAPs */ + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV) + break; + ret = update_filter(&tun->txflt, (void __user *)arg); + break; + + case SIOCGIFHWADDR: + /* Get hw address */ + memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN); + ifr.ifr_hwaddr.sa_family = tun->dev->type; + if (copy_to_user(argp, &ifr, ifreq_len)) + ret = -EFAULT; + break; + + case SIOCSIFHWADDR: + /* Set hw address */ + tun_debug(KERN_DEBUG, tun, "set hw address: %pM\n", + ifr.ifr_hwaddr.sa_data); + + ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr); + break; + + case TUNGETSNDBUF: + sndbuf = tfile->socket.sk->sk_sndbuf; + if (copy_to_user(argp, &sndbuf, sizeof(sndbuf))) + ret = -EFAULT; + break; + + case TUNSETSNDBUF: + if (copy_from_user(&sndbuf, argp, sizeof(sndbuf))) { + ret = -EFAULT; + break; + } + + tun->sndbuf = sndbuf; + tun_set_sndbuf(tun); + break; + + case TUNGETVNETHDRSZ: + vnet_hdr_sz = tun->vnet_hdr_sz; + if (copy_to_user(argp, &vnet_hdr_sz, sizeof(vnet_hdr_sz))) + ret = -EFAULT; + break; + + case TUNSETVNETHDRSZ: + if (copy_from_user(&vnet_hdr_sz, argp, sizeof(vnet_hdr_sz))) { + ret = -EFAULT; + break; + } + if (vnet_hdr_sz < (int)sizeof(struct virtio_net_hdr)) { + ret = -EINVAL; + break; + } + + tun->vnet_hdr_sz = vnet_hdr_sz; + break; + + case TUNATTACHFILTER: + /* Can be set only for TAPs */ + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV) + break; + ret = -EFAULT; + if (copy_from_user(&tun->fprog, argp, sizeof(tun->fprog))) + break; + + ret = tun_attach_filter(tun); + break; + + case TUNDETACHFILTER: + /* Can be set only for TAPs */ + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV) + break; + ret = 0; + tun_detach_filter(tun, tun->numqueues); + break; + + case TUNGETFILTER: + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV) + break; + ret = -EFAULT; + if (copy_to_user(argp, &tun->fprog, sizeof(tun->fprog))) + break; + ret = 0; + break; + + default: + ret = -EINVAL; + break; + } + +unlock: + rtnl_unlock(); + if (tun) + tun_put(tun); + return ret; +} + +static long tun_chr_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + return __tun_chr_ioctl(file, cmd, arg, sizeof (struct ifreq)); +} + +#ifdef CONFIG_COMPAT +static long tun_chr_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case TUNSETIFF: + case TUNGETIFF: + case TUNSETTXFILTER: + case TUNGETSNDBUF: + case TUNSETSNDBUF: + case SIOCGIFHWADDR: + case SIOCSIFHWADDR: + arg = (unsigned long)compat_ptr(arg); + break; + default: + arg = (compat_ulong_t)arg; + break; + } + + /* + * compat_ifreq is shorter than ifreq, so we must not access beyond + * the end of that structure. All fields that are used in this + * driver are compatible though, we don't need to convert the + * contents. + */ + return __tun_chr_ioctl(file, cmd, arg, sizeof(struct compat_ifreq)); +} +#endif /* CONFIG_COMPAT */ + +static int tun_chr_fasync(int fd, struct file *file, int on) +{ + struct tun_file *tfile = file->private_data; + int ret; + + if ((ret = fasync_helper(fd, file, on, &tfile->fasync)) < 0) + goto out; + + if (on) { + ret = __f_setown(file, task_pid(current), PIDTYPE_PID, 0); + if (ret) + goto out; + tfile->flags |= TUN_FASYNC; + } else + tfile->flags &= ~TUN_FASYNC; + ret = 0; +out: + return ret; +} + +static int tun_chr_open(struct inode *inode, struct file * file) +{ + struct tun_file *tfile; + + DBG1(KERN_INFO, "tunX: tun_chr_open\n"); + + tfile = (struct tun_file *)sk_alloc(&init_net, AF_UNSPEC, GFP_KERNEL, + &tun_proto); + if (!tfile) + return -ENOMEM; + RCU_INIT_POINTER(tfile->tun, NULL); + tfile->net = get_net(current->nsproxy->net_ns); + tfile->flags = 0; + tfile->ifindex = 0; + + init_waitqueue_head(&tfile->wq.wait); + RCU_INIT_POINTER(tfile->socket.wq, &tfile->wq); + + tfile->socket.file = file; + tfile->socket.ops = &tun_socket_ops; + + sock_init_data(&tfile->socket, &tfile->sk); + sk_change_net(&tfile->sk, tfile->net); + + tfile->sk.sk_write_space = tun_sock_write_space; + tfile->sk.sk_sndbuf = INT_MAX; + + file->private_data = tfile; + set_bit(SOCK_EXTERNALLY_ALLOCATED, &tfile->socket.flags); + INIT_LIST_HEAD(&tfile->next); + + sock_set_flag(&tfile->sk, SOCK_ZEROCOPY); + + return 0; +} + +static int tun_chr_close(struct inode *inode, struct file *file) +{ + struct tun_file *tfile = file->private_data; + struct net *net = tfile->net; + + tun_detach(tfile, true); + put_net(net); + + return 0; +} + +#ifdef CONFIG_PROC_FS +static int tun_chr_show_fdinfo(struct seq_file *m, struct file *f) +{ + struct tun_struct *tun; + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + + rtnl_lock(); + tun = tun_get(f); + if (tun) + tun_get_iff(current->nsproxy->net_ns, tun, &ifr); + rtnl_unlock(); + + if (tun) + tun_put(tun); + + return seq_printf(m, "iff:\t%s\n", ifr.ifr_name); +} +#endif + +static const struct file_operations tun_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = do_sync_read, + .aio_read = tun_chr_aio_read, + .write = do_sync_write, + .aio_write = tun_chr_aio_write, + .poll = tun_chr_poll, + .unlocked_ioctl = tun_chr_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = tun_chr_compat_ioctl, +#endif + .open = tun_chr_open, + .release = tun_chr_close, + .fasync = tun_chr_fasync, +#ifdef CONFIG_PROC_FS + .show_fdinfo = tun_chr_show_fdinfo, +#endif +}; + +static struct miscdevice tun_miscdev = { + .minor = (TUN_MINOR1), + .name = "bf_tun", + .nodename = "net/bf_tun", + .fops = &tun_fops, +}; + +/* ethtool interface */ + +static int tun_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + cmd->supported = 0; + cmd->advertising = 0; + ethtool_cmd_speed_set(cmd, SPEED_10); + cmd->duplex = DUPLEX_FULL; + cmd->port = PORT_TP; + cmd->phy_address = 0; + cmd->transceiver = XCVR_INTERNAL; + cmd->autoneg = AUTONEG_DISABLE; + cmd->maxtxpkt = 0; + cmd->maxrxpkt = 0; + return 0; +} + +static void tun_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct tun_struct *tun = netdev_priv(dev); + + strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); + strlcpy(info->version, DRV_VERSION, sizeof(info->version)); + + switch (tun->flags & TUN_TYPE_MASK) { + case TUN_TUN_DEV: + strlcpy(info->bus_info, "bf_tun", sizeof(info->bus_info)); + break; + case TUN_TAP_DEV: + strlcpy(info->bus_info, "tap", sizeof(info->bus_info)); + break; + } +} + +static u32 tun_get_msglevel(struct net_device *dev) +{ +#ifdef TUN_DEBUG + struct tun_struct *tun = netdev_priv(dev); + return tun->debug; +#else + return -EOPNOTSUPP; +#endif +} + +static void tun_set_msglevel(struct net_device *dev, u32 value) +{ +#ifdef TUN_DEBUG + struct tun_struct *tun = netdev_priv(dev); + tun->debug = value; +#endif +} + +static const struct ethtool_ops tun_ethtool_ops = { + .get_settings = tun_get_settings, + .get_drvinfo = tun_get_drvinfo, + .get_msglevel = tun_get_msglevel, + .set_msglevel = tun_set_msglevel, + .get_link = ethtool_op_get_link, + .get_ts_info = ethtool_op_get_ts_info, +}; + + +static int __init tun_init(void) +{ + int ret = 0; + + pr_info("%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); + pr_info("%s\n", DRV_COPYRIGHT); + + ret = rtnl_link_register(&tun_link_ops); + if (ret) { + pr_err("Can't register link_ops\n"); + goto err_linkops; + } + + ret = misc_register(&tun_miscdev); + if (ret) { + pr_err("Can't register misc device %d\n", (TUN_MINOR1)); + goto err_misc; + } + return 0; +err_misc: + rtnl_link_unregister(&tun_link_ops); +err_linkops: + return ret; +} + +static void tun_cleanup(void) +{ + misc_deregister(&tun_miscdev); + rtnl_link_unregister(&tun_link_ops); +} + +/* Get an underlying socket object from tun file. Returns error unless file is + * attached to a device. The returned object works like a packet socket, it + * can be used for sock_sendmsg/sock_recvmsg. The caller is responsible for + * holding a reference to the file for as long as the socket is in use. */ +struct socket *bf_tun_get_socket(struct file *file) +{ + struct tun_file *tfile; + if (file->f_op != &tun_fops) + return ERR_PTR(-EINVAL); + tfile = file->private_data; + if (!tfile) + return ERR_PTR(-EBADFD); + return &tfile->socket; +} +EXPORT_SYMBOL_GPL(bf_tun_get_socket); + +module_init(tun_init); +module_exit(tun_cleanup); +MODULE_DESCRIPTION(DRV_DESCRIPTION); +MODULE_AUTHOR(DRV_COPYRIGHT); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(TUN_MINOR1); +MODULE_ALIAS("devname:net/bf_tun"); diff --git a/platform/barefoot/sonic-platform-modules-bfn/scripts/eeprom b/platform/barefoot/sonic-platform-modules-bfn/scripts/eeprom new file mode 100755 index 000000000000..07d98556cbbf --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/scripts/eeprom @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd eeprom "$@" diff --git a/platform/barefoot/sonic-platform-modules-bfn/scripts/fancontrol b/platform/barefoot/sonic-platform-modules-bfn/scripts/fancontrol new file mode 100755 index 000000000000..515fcbdd69da --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/scripts/fancontrol @@ -0,0 +1,11 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd fancontrol "$@" + diff --git a/platform/barefoot/sonic-platform-modules-bfn/scripts/ps_info b/platform/barefoot/sonic-platform-modules-bfn/scripts/ps_info new file mode 100755 index 000000000000..38c9d3330414 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/scripts/ps_info @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd ps_info "$@" diff --git a/platform/barefoot/sonic-platform-modules-bfn/scripts/sensors b/platform/barefoot/sonic-platform-modules-bfn/scripts/sensors new file mode 100755 index 000000000000..07af6955321e --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/scripts/sensors @@ -0,0 +1,12 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd sensors "$@" + + diff --git a/platform/barefoot/sonic-platform-modules-bfn/scripts/sfputil b/platform/barefoot/sonic-platform-modules-bfn/scripts/sfputil new file mode 100755 index 000000000000..3df67614e499 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/scripts/sfputil @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS syncd sfputil "$@" diff --git a/platform/barefoot/sonic-platform-modules-bfn/scripts/test b/platform/barefoot/sonic-platform-modules-bfn/scripts/test new file mode 100755 index 000000000000..38327722c91f --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/scripts/test @@ -0,0 +1 @@ +echo "test" diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/.gitignore b/platform/barefoot/sonic-platform-modules-ingrasys/.gitignore new file mode 100644 index 000000000000..c6127b38c1aa --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/.gitignore @@ -0,0 +1,52 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/LICENSE b/platform/barefoot/sonic-platform-modules-ingrasys/LICENSE new file mode 100644 index 000000000000..9cecc1d4669e --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/changelog b/platform/barefoot/sonic-platform-modules-ingrasys/debian/changelog new file mode 100644 index 000000000000..f5c70c166031 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/changelog @@ -0,0 +1,17 @@ +platform-driver (1.1.0) unstable; urgency=low + + * Add support for s9180-32x + + -- developer Fri, 26 May 2017 11:00:00 +0800 + +platform-driver (1.1.0) unstable; urgency=low + + * Add support for s8900 series + + -- developer Wed, 29 Mar 2017 11:00:00 +0800 + +platform-driver (1.0.0) unstable; urgency=low + + * Initial release (Closes: #nnnn) + + -- developer Wed, 05 Oct 2016 16:30:45 +0800 diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/compat b/platform/barefoot/sonic-platform-modules-ingrasys/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/control b/platform/barefoot/sonic-platform-modules-ingrasys/debian/control new file mode 100644 index 000000000000..ec2c1f20c0f7 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/control @@ -0,0 +1,10 @@ +Source: platform-driver +Section: unknown +Priority: optional +Maintainer: Wade He +Build-Depends: debhelper (>= 9), dh-systemd +Standards-Version: 1.0.0 + +Package: sonic-platform-ingrasys-s9180-32x +Architecture: amd64 +Description: This package contains S9180-32X platform driver utility for SONiC project. diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/rules b/platform/barefoot/sonic-platform-modules-ingrasys/debian/rules new file mode 100755 index 000000000000..3ac0d3de6049 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/rules @@ -0,0 +1,81 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +PACKAGE_PRE_NAME := sonic-platform-ingrasys +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= s9180-32x +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CONF_DIR := conf + +%: + dh $@ --with systemd + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + #make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + done) + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +#install: build + #dh_testdir + #dh_testroot + #dh_clean -k + #dh_installdirs + +binary-indep: + dh_testdir + dh_installdirs + + # Custom package commands + (for mod in $(MODULE_DIRS); do \ + mkdir debian/tmp/usr/sbin -p; \ + mkdir debian/tmp/lib/systemd/system -p; \ + mkdir debian/tmp/etc/init.d -p; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/*.sh debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/sbin/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/bfn debian/$(PACKAGE_PRE_NAME)-$${mod}/etc/init\.d/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + done) + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.dirs b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.dirs new file mode 100644 index 000000000000..401d79eb79b8 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.dirs @@ -0,0 +1,4 @@ +usr/sbin +lib/systemd/system +etc/ +etc/init.d/ \ No newline at end of file diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.install b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.install new file mode 100644 index 000000000000..99bda5d123ae --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.install @@ -0,0 +1,4 @@ +lib/systemd/ +usr/sbin/ +etc/ +etc/init.d/ diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.postinst b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.postinst new file mode 100644 index 000000000000..38e5cac148c4 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.postinst @@ -0,0 +1,57 @@ +# Automatically added by dh_systemd_enable +# This will only remove masks created by d-s-h on package removal. +deb-systemd-helper unmask s9180-32x-monitor.service >/dev/null || true +deb-systemd-helper unmask bfn.service >/dev/null || true +deb-systemd-helper unmask qsfp-monitor.service >/dev/null || true +# Generate kernel modules.dep and map files for add eeprom_mb. +depmod -a || true +# was-enabled defaults to true, so new installations run enable. +if deb-systemd-helper --quiet was-enabled s9180-32x-monitor.service; then + # Enables the unit on first installation, creates new + # symlinks on upgrades if the unit file has changed. + deb-systemd-helper enable s9180-32x-monitor.service >/dev/null || true +else + # Update the statefile to add new symlinks (if any), which need to be + # cleaned up on purge. Also remove old symlinks. + deb-systemd-helper update-state s9180-32x-monitor.service >/dev/null || true +fi +if deb-systemd-helper --quiet was-enabled bfn.service; then + # Enables the unit on first installation, creates new + # symlinks on upgrades if the unit file has changed. + deb-systemd-helper enable bfn.service >/dev/null || true +else + # Update the statefile to add new symlinks (if any), which need to be + # cleaned up on purge. Also remove old symlinks. + deb-systemd-helper update-state bfn.service >/dev/null || true +fi +if deb-systemd-helper --quiet was-enabled qsfp-monitor.service; then + # Enables the unit on first installation, creates new + # symlinks on upgrades if the unit file has changed. + deb-systemd-helper enable qsfp-monitor.service >/dev/null || true +else + # Update the statefile to add new symlinks (if any), which need to be + # cleaned up on purge. Also remove old symlinks. + deb-systemd-helper update-state qsfp-monitor.service >/dev/null || true +fi +# End automatically added section +# Automatically added by dh_installinit +if [ -x "/etc/init.d/s9180-32x-monitor" ]; then + update-rc.d s9180-32x-monitor defaults >/dev/null + invoke-rc.d s9180-32x-monitor start || exit $? +fi +if [ -x "/etc/init.d/qsfp-monitor" ]; then + update-rc.d qsfp-monitor defaults >/dev/null + invoke-rc.d qsfp-monitor start || exit $? +fi +if [ -x "/etc/init.d/bfn" ]; then + invoke-rc.d bfn start || exit $? +fi +# End automatically added section +# Automatically added by dh_systemd_start +if [ -d /run/systemd/system ]; then + systemctl --system daemon-reload >/dev/null || true + deb-systemd-invoke start s9180-32x-monitor.service >/dev/null || true + deb-systemd-invoke start qsfp-monitor.service >/dev/null || true + deb-systemd-invoke start bfn.service >/dev/null || true +fi +# End automatically added section diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.postrm b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.postrm new file mode 100644 index 000000000000..19c6bcb2945f --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.postrm @@ -0,0 +1,42 @@ +# Automatically added by dh_systemd_start +if [ -d /run/systemd/system ]; then + systemctl --system daemon-reload >/dev/null || true + fi +# End automatically added section +# Automatically added by dh_installinit +if [ "$1" = "purge" ] ; then + update-rc.d s9180-32x-monitor remove >/dev/null + update-rc.d bfn remove >/dev/null + update-rc.d qsfp-monitor remove >/dev/null +fi + + +# In case this system is running systemd, we make systemd reload the unit files +# to pick up changes. +if [ -d /run/systemd/system ] ; then + systemctl --system daemon-reload >/dev/null || true +fi +# End automatically added section +# Automatically added by dh_systemd_enable +if [ "$1" = "remove" ]; then + if [ -x "/usr/bin/deb-systemd-helper" ]; then + deb-systemd-helper mask s9180-32x-monitor.service >/dev/null + deb-systemd-helper mask bfn.service >/dev/null + deb-systemd-helper mask qsfp-monitor.service >/dev/null + fi +fi + +if [ "$1" = "purge" ]; then + if [ -x "/usr/bin/deb-systemd-helper" ]; then + deb-systemd-helper purge s9180-32x-monitor.service >/dev/null + deb-systemd-helper unmask s9180-32x-monitor.service >/dev/null + deb-systemd-helper purge bfn.service >/dev/null + deb-systemd-helper unmask bfn.service >/dev/null + deb-systemd-helper purge qsfp-monitor.service >/dev/null + deb-systemd-helper unmask qsfp-monitor.service >/dev/null + fi +fi +# Generate kernel modules.dep and map files for remove eeprom_mb. +depmod -a || true +# End automatically added section + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.prerm b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.prerm new file mode 100644 index 000000000000..76533bfe6889 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.prerm @@ -0,0 +1,21 @@ +# Automatically added by dh_systemd_start +if [ -d /run/systemd/system ]; then + deb-systemd-invoke stop s9180-32x-monitor.service >/dev/null + deb-systemd-invoke stop bfn.service >/dev/null + deb-systemd-invoke stop qsfp-monitor.service >/dev/null +fi +# End automatically added section +# Automatically added by dh_installinit +if [ -x "/etc/init.d/s9180-32x-monitor" ]; then + invoke-rc.d s9180-32x-monitor stop || exit $? +fi +if [ -x "/etc/init.d/bfn" ]; then + invoke-rc.d bfn stop || exit $? +fi +if [ -x "/etc/init.d/qsfp-monitor" ]; then + invoke-rc.d qsfp-monitor stop || exit $? +fi +# Driver deinit +/usr/sbin/i2c_utils.sh i2c_deinit +# End automatically added section + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.upstart b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.upstart new file mode 100644 index 000000000000..2c8d2ebec6d7 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/debian/sonic-platform-ingrasys-s9180-32x.upstart @@ -0,0 +1,7 @@ +description "SONiC platform service" + +respawn + +exec /usr/sbin/s9180_32x_monitor.sh +exec /usr/sbin/qsfp_monitor.sh +exec /etc/init.d/bfn start diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/README.md b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/README.md new file mode 100644 index 000000000000..fa3760ab9ab7 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/README.md @@ -0,0 +1,185 @@ +# Ingrasys S9180-32X Platform Driver for SONiC + +Copyright (C) 2016 Ingrasys, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + + +## Licensing terms + +The Licensing terms of the files within this project is split 2 parts. +The Linux kernel is released under the GNU General Public License version 2. +All other code is released under the GNU General Public License version 3. +Please see the LICENSE file for copies of both licenses. + +## Contents of this package + + - service/ + > Service config files for platform initialization and monitoring + - utils/ + > Scripts useful during platform bringup and sysfs function + - conf/ + > Platform configure files. + +## Kernel modules and drivers + +The driver for interacting with Ingrasys S9180-32X is contained in the I2C +kernel module and initialization script. The initialization script loads +the modules in the correct order. It has been built and tested against +the Linux 3.16 kernel. + +The initialization script will modprobe the needed modules, navigate to the +module's device directory in sysfs, and write configuration data to +the kernel module. + +### IGB + +This is OOB Ports on front panel for management plane. + +The IGB module must be loaded first on Ingrasys S9180-32X platform. + +### I2C i801 + +The I2C i801 on Ingrasys S9180-32X can be found in +`/sys/bus/i2c/devices/i2c-0/` + +This is I2C bus for Clock Gen, DIMM channel and digital potentiometers. + +The i801 module must be loaded second on Ingrasys S9180-32X. + +### I2C iSMT + +The I2C iSMT module on S9180-32X can be found in +`/sys/bus/i2c/devices/i2c-1/` + +This is I2C bus for CPLD, HWM, power controller and I2C Switches. + +The i801 module must be loaded third on Ingrasys S9180-32X. + +### I2C PCA9548 +The PCA9548 module on S9180-32X can be found in +`/sys/bus/i2c/devices/i2c-2/` , `/sys/bus/i2c/devices/i2c-3/`, +`/sys/bus/i2c/devices/i2c-4/`, `/sys/bus/i2c/devices/i2c-5/`, +`/sys/bus/i2c/devices/i2c-6/`, `/sys/bus/i2c/devices/i2c-7/`, +`/sys/bus/i2c/devices/i2c-8/`, `/sys/bus/i2c/devices/i2c-9/`. + +The pca9548 module for zQSFP module get/set functions, PSU information, +fan status and EEPROM. + +## Hardware components + +The hardware components are initialized in the init script on S9180-32X. +The following describes manual initialization as well as interaction. +The examples below are just for Ingrasys S9180-32X platform. + +### Hardware initialization + +When the sonic-platform-ingrasys-s9180 package is installed on the S9180-32X, +it is automatically initialized. If you want to manual initialization, the +utility command usage as follows: +``` + i2c_utils.sh i2c_init +``` + +### EEPROM + +The EEPROM is including the board SKU, model name, vendor name, serial number, +and other information can be accessed with the specific eeprom kernel module. +After using `modprobe eeprom_mb` to detect the eeprom, it will show up in sysfs. + +The hexdump utility can be used to decode the raw output of the EEPROM. +For example, +``` + bash# echo "mb_eeprom 0x54" > /sys/bus/i2c/devices/i2c-9/new_device + bash# cat /sys/bus/i2c/drivers/mb_eeprom/9-0054/eeprom | hexdump -C +``` + +### Front panel LEDs + +LEDs can be setup on/off by using i2c utility `/usr/sbin/i2c_utils.sh`. +Utility function command usage as follows: + +``` +Status LED: + i2c_utils.sh i2c_sys_led green|amber on|off + +Fan status LED: + i2c_utils.sh i2c_fan_led green|amber on|off + +PSU1 status LED: + i2c_utils.sh i2c_psu1_led green|amber on|off + +PSU2 status LED: + i2c_utils.sh i2c_psu2_led green|amber on|off + +``` +QSFP Module Port LEDs control by ASIC library. + + +### Fan speed + +Fan speed are controlled by the w83795 kernel module. +It can be found in `/sys/class/hwmon/hwmon3/device/`. +If they were compiled as modules, you will need to modprobe w83795 for +their sysfs entries to show up. Each fan has an `fan_input` file +for reading the fan speed. And `pwm1` setting fan1 to fan4, +`pwm2` setting fan5 to fan8. + +There is docker-platform-monitor container installed fancontrol package that can +automatic control platform fan speed. + + +### Temperature sensors + +Temperature sensors are controlled by the w83795 kernel +module. It can be found in `/sys/class/hwmon/hwmon3/device/`. +If they were compiled as modules, then you will need to modprobe w83795 for +their sysfs entries to show up. +`temp1_input` is front MAC temperature sensor. `temp2_input` is rear MAC +temperature sensor. + +There is docker-platform-monitor container installed lm-sensors package that can +monitor platform temperature. And `sensors` command can show each +temperature sensors status. + +### Power supplies + +Power supplies status and its EEPROM info can be used i2c utility +`/usr/sbin/i2c_utils.sh` to get. +The usage as follows: +``` +PSU EEPROM: + i2c_utils.sh i2c_psu_eeprom_get + hexdump -C psu0.rom + hexdump -C psu1.rom + +PSU Status: + i2c_utils.sh i2c_psu_status +``` + +### QSFPs +QSFP modules are managed by the pca9548 kernel driver. +The i2c utility `/usr/sbin/i2c_utils.sh` can be used to get status and +module EEPROM informations. +The usage as follows: +``` +QSFP EEPROM: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + +QSFP Insert Event: + i2c_utils.sh i2c_qsfp_eeprom_get [1-32] + 0 => not insert + 1 => inserted +``` + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/Makefile b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/Makefile new file mode 100644 index 000000000000..3edb8690475e --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/Makefile @@ -0,0 +1 @@ +obj-m := eeprom_mb.o diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/eeprom_mb.c b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/eeprom_mb.c new file mode 100644 index 000000000000..61f0caf96130 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/modules/eeprom_mb.c @@ -0,0 +1,211 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 256 + +#define SLICE_BITS (6) +#define SLICE_SIZE (1 << SLICE_BITS) +#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE) + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +}; + + +static void mb_eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + int ret; + int addr; + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + addr = slice << SLICE_BITS; + + ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF); + /* select the eeprom address */ + if (ret < 0) { + dev_err(&client->dev, "address set failed\n"); + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) { + goto exit; + } + + for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) { + for (j = i; j < (i+SLICE_SIZE); j++) { + int res; + + res = i2c_smbus_read_byte(client); + if (res < 0) { + goto exit; + } + + data->data[j] = res & 0xFF; + } + } + + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t mb_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + if (off > EEPROM_SIZE) { + return 0; + } + if (off + count > EEPROM_SIZE) { + count = EEPROM_SIZE - off; + } + if (count == 0) { + return 0; + } + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) { + mb_eeprom_update_client(client, slice); + } + + memcpy(buf, &data->data[off], count); + + return count; +} + +static struct bin_attribute mb_eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IRUGO, + }, + .size = EEPROM_SIZE, + .read = mb_eeprom_read, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int mb_eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x50. So decline + attaching to addresses >= 0x51 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51) { + return -ENODEV; + } + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { + return -ENODEV; + } + + strlcpy(info->type, "eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int mb_eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &mb_eeprom_attr); + if (err) { + goto exit_kfree; + } + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int mb_eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &mb_eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id mb_eeprom_id[] = { + { "mb_eeprom", 0 }, + { } +}; + +static struct i2c_driver mb_eeprom_driver = { + .driver = { + .name = "mb_eeprom", + }, + .probe = mb_eeprom_probe, + .remove = mb_eeprom_remove, + .id_table = mb_eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = mb_eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(mb_eeprom_driver); + +MODULE_AUTHOR("Wade "); +MODULE_DESCRIPTION("Ingrasys Mother Borad EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/bfn.service b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/bfn.service new file mode 100644 index 000000000000..6c8c2fb71517 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/bfn.service @@ -0,0 +1,13 @@ +[Unit] +Description=Barefoot Kernel Module +After=local-fs.target +Before=docker.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/bfn start +ExecStop=-/etc/init.d/bfn stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/qsfp-monitor.service b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/qsfp-monitor.service new file mode 100644 index 000000000000..fde9dcf9f50a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/qsfp-monitor.service @@ -0,0 +1,15 @@ +[Unit] +Description= This QSFP Monitor service is to setup QSFP SI. +Requires=s9180-32x-monitor.service +After=s9180-32x-monitor.service + +[Service] +ExecStart=/usr/sbin/qsfp_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/s9180-32x-monitor.service b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/s9180-32x-monitor.service new file mode 100644 index 000000000000..884284b241ad --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/service/s9180-32x-monitor.service @@ -0,0 +1,19 @@ +[Unit] +Description= This Platform Monitor service is to initialize platform and monitor platform. +Before=platform-monitor.service +After=sysinit.target +Wants=fancontrol.service +Wants=qsfp-monitor.service +DefaultDependencies=no + +[Service] +ExecStartPre=/usr/sbin/i2c_utils.sh i2c_init +ExecStart=/usr/sbin/s9180_32x_monitor.sh +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/bfn b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/bfn new file mode 100755 index 000000000000..c52b1fab4ea1 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/bfn @@ -0,0 +1,44 @@ +#!/bin/bash +# This script load/unload Barefoot kernel modules + +### BEGIN INIT INFO +# Provides: +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Load Barefoot kernel modules +### END INIT INFO + +case "$1" in +start) + echo -n "Load Barefoot kernel modules... " + + modprobe bf_kdrv + modprobe bf_tun + + echo "done." + ;; + +stop) + echo -n "Unload Barefoot kernel modules... " + + rmmod bf_tun + rmmod bf_kdrv + + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/bfn {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/i2c_utils.sh b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/i2c_utils.sh new file mode 100755 index 000000000000..e765ed1da6a9 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/i2c_utils.sh @@ -0,0 +1,1423 @@ +#!/bin/bash + +# Copyright (C) 2017 Ingrasys, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +VERSION="1.0.0" +TRUE=200 +FALSE=404 + +EXEC_FUNC=${1} +QSFP_PORT=${2} +QSFP_ACTION=${2} +MB_EEPROM_ACTION=${2} +COLOR_PORT_LED=${3} +ONOFF_LED=${3} +COLOR_SYS_LED=${2} +BLINK_LED=${4} +FAN_TRAY=${4} + +############################################################ +# Distributor ID: Debian +# Description: Debian GNU/Linux 8.6 (jessie) +# Release: 8.6 +# Codename: jessie +# Linux debian 3.16.0-4-amd64 #1 +# SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux +############################################################ + +# Color Definition +COLOR_TITLE="\e[1;32m" ### Green ### +COLOR_WARNING="\e[1;33m" ### Yellow ### +COLOR_ERROR="\e[1;31m" ### Red ### +COLOR_END="\e[0m" ### END ### + +NUM_I801_DEVICE=0 # Main I2C +NUM_MUX1_CHAN0_DEVICE=$(( ${NUM_I801_DEVICE} + 1 )) # zQSFP I/O 0-7 +NUM_MUX1_CHAN1_DEVICE=$(( ${NUM_MUX1_CHAN0_DEVICE} + 1 )) # zQSFP I/O 8-15 +NUM_MUX1_CHAN2_DEVICE=$(( ${NUM_MUX1_CHAN1_DEVICE} + 1 )) # zQSFP I/O 16-23 +NUM_MUX1_CHAN3_DEVICE=$(( ${NUM_MUX1_CHAN2_DEVICE} + 1 )) # zQSFP I/O 24-31 +NUM_MUX1_CHAN4_DEVICE=$(( ${NUM_MUX1_CHAN3_DEVICE} + 1 )) # zQSFP I/O ABS#, INT +NUM_MUX1_CHAN5_DEVICE=$(( ${NUM_MUX1_CHAN4_DEVICE} + 1 )) # zQSFP I/O LPMODE, RST, MODSEL +NUM_MUX1_CHAN6_DEVICE=$(( ${NUM_MUX1_CHAN5_DEVICE} + 1 )) # MAC CLK CPLD +NUM_MUX1_CHAN7_DEVICE=$(( ${NUM_MUX1_CHAN6_DEVICE} + 1 )) # P1V0 PWR +NUM_MUX3_CHAN0_DEVICE=$(( ${NUM_MUX1_CHAN7_DEVICE} + 1 )) # zQSFP I/O 0-7 +NUM_MUX4_CHAN0_DEVICE=$(( ${NUM_MUX3_CHAN0_DEVICE} + 8 )) # zQSFP I/O 8-15 +NUM_MUX5_CHAN0_DEVICE=$(( ${NUM_MUX4_CHAN0_DEVICE} + 8 )) # zQSFP I/O 16-23 +NUM_MUX6_CHAN0_DEVICE=$(( ${NUM_MUX5_CHAN0_DEVICE} + 8 )) # zQSFP I/O 24-31 +NUM_MUX7_CHAN0_DEVICE=$(( ${NUM_MUX6_CHAN0_DEVICE} + 8 )) # Temp Sensor 0x48-0x4D +NUM_MAIN_MUX_CHAN0_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 8 )) # System LED HWMON +NUM_MAIN_MUX_CHAN1_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 1 )) # System LED +NUM_MAIN_MUX_CHAN2_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 2 )) # Board ID +NUM_MAIN_MUX_CHAN3_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 3 )) # MAX_Slave +NUM_MAIN_MUX_CHAN4_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 4 )) # TEMP Sensor +NUM_MAIN_MUX_CHAN5_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 5 )) # CLK GEN +NUM_MAIN_MUX_CHAN6_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 6 )) # VDD CORE +NUM_MAIN_MUX_CHAN7_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 7 )) # HWMON +NUM_FRU_MUX_CHAN0_DEVICE=$(( ${NUM_MAIN_MUX_CHAN0_DEVICE} + 8 )) # PSU2 +NUM_FRU_MUX_CHAN1_DEVICE=$(( ${NUM_FRU_MUX_CHAN0_DEVICE} + 1 )) # PSU1 +NUM_FRU_MUX_CHAN2_DEVICE=$(( ${NUM_FRU_MUX_CHAN0_DEVICE} + 2 )) # FAN +NUM_CPLD_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 3 )) # CPLD +NUM_SFP1_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 4 )) # CPLD +NUM_SFP2_DEVICE=$(( ${NUM_MUX7_CHAN0_DEVICE} + 5 )) # CPLD + +PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices" +PATH_HWMON_ROOT_DEVICES="/sys/class/hwmon" +PATH_HWMON_W83795_DEVICE="${PATH_HWMON_ROOT_DEVICES}/hwmon1" +PATH_I801_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I801_DEVICE}" +PATH_ISMT_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_ISMT_DEVICE}" +PATH_MUX_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" +PATH_MUX_CHAN1_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN1_DEVICE}" +PATH_MUX_CHAN2_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN2_DEVICE}" +PATH_MUX_CHAN3_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN3_DEVICE}" +PATH_MUX_CHAN4_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN4_DEVICE}" +PATH_MUX_CHAN5_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN5_DEVICE}" +PATH_MUX_CHAN6_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN6_DEVICE}" +PATH_MUX_CHAN7_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN7_DEVICE}" +PATH_MUX7_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX7_CHAN0_DEVICE}" +PATH_MAIN_MUX_CHAN0_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MAIN_MUX_CHAN0_DEVICE}" + +#Power Supply Status +PSU_DC_ON=1 +PSU_DC_OFF=0 +PSU_EXIST=1 +PSU_NOT_EXIST=0 + +# Help usage function +function _help { + echo "=========================================================" + echo "# Description: Help Function" + echo "=========================================================" + echo "----------------------------------------------------" + echo "EX : ${0} help" + echo " : ${0} i2c_init" + echo " : ${0} i2c_deinit" + echo " : ${0} i2c_temp_init" + echo " : ${0} i2c_fan_init" + echo " : ${0} i2c_volmon_init" + echo " : ${0} i2c_io_exp_init" + echo " : ${0} i2c_gpio_init" + echo " : ${0} i2c_gpio_deinit" + + echo " : ${0} i2c_psu_eeprom_get" + echo " : ${0} i2c_mb_eeprom_get" + echo " : ${0} i2c_cpu_eeprom_get" + echo " : ${0} i2c_qsfp_eeprom_get [1-34]" + echo " : ${0} i2c_qsfp_eeprom_init new|delete" + echo " : ${0} i2c_sfp_eeprom_init new|delete" + echo " : ${0} i2c_mb_eeprom_init new|delete" + echo " : ${0} i2c_psu_eeprom_init new|delete" + echo " : ${0} i2c_qsfp_status_get [1-34]" + echo " : ${0} i2c_qsfp_type_get [1-34]" + echo " : ${0} i2c_board_type_get" + echo " : ${0} i2c_psu_status" + echo " : ${0} i2c_led_fan_status_set" + echo " : ${0} i2c_led_fan_tray_status_set" + echo " : ${0} i2c_cpld_version" + echo " : ${0} i2c_port_led_set [1-34] green|yellow|off blink|noblink" + echo " : ${0} i2c_test_all" + echo " : ${0} i2c_sys_led green|amber" + echo " : ${0} i2c_fan_led green|amber on|off" + echo " : ${0} i2c_fan_tray_led green|amber on|off [1-4]" + echo "----------------------------------------------------" +} + +#Pause function +function _pause { + read -p "$*" +} + +#Retry command function +function _retry { + local i + for i in {1..5}; + do + eval "${*}" && break || echo "retry"; sleep 1; + done +} + +#I2C Init +function _i2c_init { + echo "=========================================================" + echo "# Description: I2C Init" + echo "=========================================================" + + rmmod eeprom + rmmod i2c_i801 + modprobe i2c_i801 + modprobe i2c_dev + modprobe i2c_mux_pca954x force_deselect_on_exit=1 + + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX1_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x70' > ${PATH_I801_DEVICE}/new_device" + else + echo "${PATH_I801_DEVICE} 0x70 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX3_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN0_DEVICE}/new_device" + else + echo "${PATH_MUX_CHAN0_DEVICE} 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX4_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN1_DEVICE}/new_device" + else + echo "${PATH_MUX_CHAN1_DEVICE} 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX5_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN2_DEVICE}/new_device" + else + echo "${PATH_MUX_CHAN2_DEVICE} 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX6_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN3_DEVICE}/new_device" + else + echo "${PATH_MUX_CHAN3_DEVICE} 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX7_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x71' > ${PATH_MUX_CHAN6_DEVICE}/new_device" + else + echo "${PATH_MUX_CHAN6_DEVICE} 0x71 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MAIN_MUX_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9548 0x76' > ${PATH_I801_DEVICE}/new_device" + else + echo "${PATH_MAIN_MUX_CHAN0_DEVICE} 0x76 already init." + fi + if [ ! -e "${PATH_SYS_I2C_DEVICES}/i2c-${NUM_FRU_MUX_CHAN0_DEVICE}" ]; then + _retry "echo 'pca9545 0x72' > ${PATH_I801_DEVICE}/new_device" + else + echo "${PATH_MAIN_MUX_CHAN0_DEVICE} 0x72 already init." + fi + + rmmod coretemp + rmmod jc42 + rmmod w83795 + rmmod lm75 + rmmod lm90 + rmmod eeprom + modprobe coretemp + modprobe w83795 + modprobe lm75 + modprobe lm90 + modprobe eeprom_mb + modprobe gpio-pca953x + _i2c_io_exp_init + _i2c_fan_init + _i2c_volmon_init + _i2c_fan_speed_init + _i2c_temp_init + modprobe jc42 + _i2c_gpio_init + _i2c_mb_eeprom_init "new" + _i2c_qsfp_eeprom_init "new" + _i2c_sfp_eeprom_init "new" + _i2c_psu_eeprom_init "new" + _i2c_led_fan_status_set + _i2c_led_fan_tray_status_set + + #SYS LED set green + COLOR_SYS_LED="green" + _i2c_sys_led +} + +#I2C Deinit +function _i2c_deinit { + _i2c_gpio_deinit + for mod in coretemp jc42 w83795 lm75 lm90 eeprom eeprom_mb gpio-pca953x i2c_mux_pca954x i2c_ismt i2c_i801; + do + [ "$(lsmod | grep "^$mod ")" != "" ] && rmmod $mod + done +} + +#FAN Init +function _i2c_fan_speed_init { + echo -n "FAN INIT..." + if [ -e "${PATH_HWMON_W83795_DEVICE}" ]; then + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm1 + echo 120 > ${PATH_HWMON_W83795_DEVICE}/device/pwm2 + echo "SUCCESS" + else + echo "FAIL" + fi + +} + +#VOLMON Init +function _i2c_volmon_init { + echo "VOLMON INIT..." + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x01 0x1C + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x02 0xFF + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x03 0x50 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x04 0x0A + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x00 0x80 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x01 0x1D + + # add w83795 to sysfs + dev_path="${PATH_SYS_I2C_DEVICES}/${NUM_MAIN_MUX_CHAN7_DEVICE}-0x2f" + if ! [ -L ${dev_path} ]; then + echo "w83795adg 0x2f" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MAIN_MUX_CHAN7_DEVICE}/new_device #hwmon + else + echo "${dev_path} already exist" + fi + echo "Done" +} + +#IO Expander Init +function _i2c_io_exp_init { + echo "=========================================================" + echo "# Description: I2C IO Expender Init" + echo "=========================================================" + + #Golden Finger to active CPLD + i2cget -y ${NUM_CPLD_DEVICE} 0x74 2 + #BMC dummy board reset + echo "BMC dummy board reset" + i2cset -y -r ${NUM_I801_DEVICE} 0x26 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x26 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x26 2 0x3F + i2cset -y -r ${NUM_I801_DEVICE} 0x26 3 0x1F + i2cset -y -r ${NUM_I801_DEVICE} 0x26 6 0xC0 + i2cset -y -r ${NUM_I801_DEVICE} 0x26 7 0x00 + + #CPU Baord + i2cset -y -r ${NUM_I801_DEVICE} 0x77 6 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x77 7 0xFF + + #SMBUS1 + #ABS + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x20 7 0xFF + + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x21 7 0xFF + + #Transcevior INT + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 6 0xFF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x22 7 0xFF + + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 2 0xCF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 3 0xF0 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 6 0xCF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x23 7 0xF0 + + #SFP+ PRES, TX FAULT, TX DIS, RX LOS, RS, TS + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 6 0xCF + i2cset -y -r ${NUM_MUX1_CHAN4_DEVICE} 0x27 7 0xF0 + + + echo "Init ZQSFP IO Expender" + echo "set ZQSFP LP_MODE = 0" + #set ZQSFP LP_MODE = 0 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x20 7 0x00 + + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 2 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 3 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x21 7 0x00 + + echo "set ZQSFP RST = 1" + #set ZQSFP RST = 1 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 2 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 3 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x22 7 0x00 + + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 4 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 5 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 2 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 3 0xFF + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 6 0x00 + i2cset -y -r ${NUM_MUX1_CHAN5_DEVICE} 0x23 7 0x00 + + #0.0: TH_RST_L - 0:Reset + #0.1: TH_PCIE_RST_L - 0:Reset + #0.2: LED_CLR - 0: Off, 1:On + #0.3: Host to BMC + #0.4: UART_SEL - 0:Host + #0.5: USB_SEL - 0: Host + #0.[7:6]: TH_CLK_FSEL (00) + #1.0: TH_INT_L + #1.1: QSFP0_INT_L - 0:Interrupt + #1.2: QSFP1_INT_L - 0:Interrupt + #1.3: QSFP2_INT_L - 0:Interrupt + #1.4: QSFP3_INT_L - 0:Interrupt + #1.5: TH_CLK_SEL (0) + #1.6: I210_RST_L - 0:Reset + #1.6: I210_PE_RST_L - 0:Reset + echo "Init HOST GPIO" + i2cset -y -r ${NUM_I801_DEVICE} 0x74 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x74 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x74 2 0x0F + i2cset -y -r ${NUM_I801_DEVICE} 0x74 3 0xDF + i2cset -y -r ${NUM_I801_DEVICE} 0x74 6 0x08 + i2cset -y -r ${NUM_I801_DEVICE} 0x74 7 0x1F + + + #LED board after PVT (BAREFOOT_IO_EXP_LED_ID) + echo "Init LED IO Expender" + echo "LED_CHANNEL=${NUM_MAIN_MUX_CHAN1_DEVICE}" + i2cset -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 4 0x00 + i2cset -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 5 0x00 + i2cset -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 6 0x00 + i2cset -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 7 0xFF + + #Board ID + echo "Init Board ID" + i2cset -y -r ${NUM_MAIN_MUX_CHAN2_DEVICE} 0x27 4 0x00 + i2cset -y -r ${NUM_MAIN_MUX_CHAN2_DEVICE} 0x27 5 0x00 + i2cset -y -r ${NUM_MAIN_MUX_CHAN2_DEVICE} 0x27 6 0xFF + i2cset -y -r ${NUM_MAIN_MUX_CHAN2_DEVICE} 0x27 7 0xFF + + #Board ID of dummy card + echo "Init Board ID of dummy card" + i2cset -y -r ${NUM_I801_DEVICE} 0x24 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x24 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x24 6 0xFF + i2cset -y -r ${NUM_I801_DEVICE} 0x24 7 0xFF + + #PSU I/O (BAREFOOT_IO_EXP_PSU_ID) + echo "Init PSU IO Expender" + i2cset -y -r ${NUM_I801_DEVICE} 0x25 4 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x25 5 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x25 2 0x00 + i2cset -y -r ${NUM_I801_DEVICE} 0x25 3 0x1D + i2cset -y -r ${NUM_I801_DEVICE} 0x25 6 0xDB + i2cset -y -r ${NUM_I801_DEVICE} 0x25 7 0x03 + + #FAN I/O (BAREFOOT_IO_EXP_FAN_ID) + echo "Init FAN IO Expender" + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 4 0x00 + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 5 0x00 + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 2 0x11 + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 3 0x11 + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 6 0xCC + i2cset -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 7 0xCC + +} + +#FANIN Init +function _i2c_fan_init { + echo "FANIN INIT..." + # enable fan monitor on w83795 + # 4 fantray with 8 FANIN + # select bank0 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x00 0x80 + # enable FANIN1~8 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x06 0xFF + # disable FANIN9~14 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x07 0x00 + + # select bank 2 + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x00 0x82 + # set PWM mode in FOMC + i2cset -y -r ${NUM_MAIN_MUX_CHAN7_DEVICE} 0x2F 0x0F 0x00 + + echo "Done" +} + +#GPIO Init +function _i2c_gpio_init { + local i=0 + #ABS Port 0-15 + echo "pca9535 0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + for i in {240..255}; + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #ABS Port 16-31 + echo "pca9535 0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + for i in {224..239}; + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #INT Port 0-15 + echo "pca9535 0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + for i in {208..223}; + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #INT Port 16-31 + echo "pca9535 0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + for i in {192..207}; + do + echo $i > /sys/class/gpio/export + echo 1 > /sys/class/gpio/gpio${i}/active_low + done + + #SFP+ + echo "pca9535 0x27" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/new_device + for i in {176..191}; + do + echo $i > /sys/class/gpio/export + case ${i} in + 176|177|178|179|182|183|188|189|190|191) + echo 1 > /sys/class/gpio/gpio${i}/active_low + ;; + 180|181|184|185|186|187) + echo out > /sys/class/gpio/gpio${i}/direction + ;; + esac + + done + #echo 176 > /sys/class/gpio/export + #echo 177 > /sys/class/gpio/export + #echo 178 > /sys/class/gpio/export + #echo 179 > /sys/class/gpio/export + #echo 180 > /sys/class/gpio/export + #echo 181 > /sys/class/gpio/export + #echo 182 > /sys/class/gpio/export + #echo 183 > /sys/class/gpio/export + #echo 184 > /sys/class/gpio/export + #echo 185 > /sys/class/gpio/export + #echo 186 > /sys/class/gpio/export + #echo 187 > /sys/class/gpio/export + #echo 188 > /sys/class/gpio/export + #echo 189 > /sys/class/gpio/export + #echo 190 > /sys/class/gpio/export + #echo 191 > /sys/class/gpio/export + #echo 1 > /sys/class/gpio/gpio176/active_low #SFP+0 ABS + #echo 1 > /sys/class/gpio/gpio177/active_low #SFP+1 ABS + #echo 1 > /sys/class/gpio/gpio178/active_low #SFP+0 TX_FAULT + #echo 1 > /sys/class/gpio/gpio179/active_low #SFP+1 TX_FAULT + #echo out > /sys/class/gpio/gpio180/direction #SFP+0 TX_DIS + #echo out > /sys/class/gpio/gpio181/direction #SFP+1 TX_DIS + #echo 1 > /sys/class/gpio/gpio182/active_low #SFP+0 RX_LOS + #echo 1 > /sys/class/gpio/gpio183/active_low #SFP+1 RX_LOS + #echo out > /sys/class/gpio/gpio184/direction #SFP+0 RS + #echo out > /sys/class/gpio/gpio185/direction #SFP+1 RS + #echo out > /sys/class/gpio/gpio186/direction #SFP+0 TS + #echo out > /sys/class/gpio/gpio187/direction #SFP+1 TS + #echo 1 > /sys/class/gpio/gpio188/active_low #N/A + #echo 1 > /sys/class/gpio/gpio189/active_low #N/A + #echo 1 > /sys/class/gpio/gpio190/active_low #N/A + #echo 1 > /sys/class/gpio/gpio191/active_low #N/A + + #LP Mode Port 0-15 + echo "pca9535 0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + for i in {160..175}; + do + echo $i > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio${i}/direction + done + + #LP Mode Port 16-31 + echo "pca9535 0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + for i in {144..159}; + do + echo $i > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio${i}/direction + done + + #RST Port 0-15 + echo "pca9535 0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + for i in {128..143}; + do + echo $i > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio${i}/direction + echo 1 > /sys/class/gpio/gpio${i}/active_low + echo 0 > /sys/class/gpio/gpio${i}/value + done + + #RST Port 16-31 + echo "pca9535 0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/new_device + for i in {112..127}; + do + echo $i > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio${i}/direction + echo 1 > /sys/class/gpio/gpio${i}/active_low + echo 0 > /sys/class/gpio/gpio${i}/value + done + + #PSU I/O on Dummy Board 0x25 + echo "pca9535 0x25" > /sys/bus/i2c/devices/i2c-${NUM_I801_DEVICE}/new_device + for i in {96..111}; + do + echo $i > /sys/class/gpio/export + case ${i} in + 97|98|100|101|102|105|106|108) + echo 1 > /sys/class/gpio/gpio${i}/active_low + ;; + 98|101|106|107|108) + echo out > /sys/class/gpio/gpio${i}/direction + ;; + esac + done +} + +#GPIO DeInit +function _i2c_gpio_deinit { + echo "0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x27" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN4_DEVICE}/delete_device + echo "0x20" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x21" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x22" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x23" > /sys/bus/i2c/devices/i2c-${NUM_MUX1_CHAN5_DEVICE}/delete_device + echo "0x25" > /sys/bus/i2c/devices/i2c-${NUM_I801_DEVICE}/delete_device +} + +#TMP75 Init +function _i2c_temp_init { + echo "lm86 0x4c" > ${PATH_MUX7_CHAN0_DEVICE}/new_device # ASIC Coretemp and Front MAC + echo "tmp75 0x4f" > ${PATH_I801_DEVICE}/new_device #CPU Board + echo "tmp75 0x48" > ${PATH_MUX7_CHAN0_DEVICE}/new_device # Near PSU1 + echo "tmp75 0x4a" > ${PATH_MUX7_CHAN0_DEVICE}/new_device # Rear MAC + echo "tmp75 0x4b" > ${PATH_MUX7_CHAN0_DEVICE}/new_device # Near Port 32 + echo "tmp75 0x4d" > ${PATH_MUX7_CHAN0_DEVICE}/new_device # Near PSU2 +} + +#Set FAN Tray LED +function _i2c_led_fan_tray_status_set { + echo "FAN Tray Status Setup" + #FAN Status get + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + # check if io expander for fan tray exist + #i2cset -m $mask -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} $i2cAddr $ioPort 0x33 + result=`i2cget -y ${NUM_FRU_MUX_CHAN2_DEVICE} 0x20 0 2>/dev/null` + err_code=$? + if [ "$err_code" != "0" ]; then + echo "fan tray not exist!" + return + fi + + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ]; then + FAN_TRAY=1 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=1 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ]; then + FAN_TRAY=2 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=2 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ]; then + FAN_TRAY=3 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=3 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi + + if [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + FAN_TRAY=4 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + else + FAN_TRAY=4 + echo "FAN_TRAY${FAN_TRAY}..." + COLOR_SYS_LED="green" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + COLOR_SYS_LED="amber" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_tray_led + fi +} + +#Set FAN LED +function _i2c_led_fan_status_set { + echo "FAN Status Setup" + #PSU Status set + FAN1_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan1_alarm` + FAN2_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan2_alarm` + FAN3_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan3_alarm` + FAN4_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan4_alarm` + FAN5_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan5_alarm` + FAN6_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan6_alarm` + FAN7_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan7_alarm` + FAN8_ALARM=`cat ${PATH_HWMON_W83795_DEVICE}/device/fan8_alarm` + + echo "led_fan setup..." + # all fan ok + if [ "${FAN1_ALARM}" == "0" ] && [ "${FAN2_ALARM}" == "0" ] \ + && [ "${FAN3_ALARM}" == "0" ] && [ "${FAN4_ALARM}" == "0" ] \ + && [ "${FAN5_ALARM}" == "0" ] && [ "${FAN6_ALARM}" == "0" ] \ + && [ "${FAN7_ALARM}" == "0" ] && [ "${FAN8_ALARM}" == "0" ]; then + COLOR_SYS_LED="green" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_led + # all fan fail + elif [ "${FAN1_ALARM}" == "1" ] && [ "${FAN2_ALARM}" == "1" ] \ + && [ "${FAN3_ALARM}" == "1" ] && [ "${FAN4_ALARM}" == "1" ] \ + && [ "${FAN5_ALARM}" == "1" ] && [ "${FAN6_ALARM}" == "1" ] \ + && [ "${FAN7_ALARM}" == "1" ] && [ "${FAN8_ALARM}" == "1" ]; then + COLOR_SYS_LED="green" + ONOFF_LED="off" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_led + # partial fan fail + else + COLOR_SYS_LED="amber" + ONOFF_LED="on" + echo "${COLOR_SYS_LED} ${ONOFF_LED}" + _i2c_fan_led + fi +} + +#Set QSFP Port variable +function _qsfp_port_i2c_var_set { + local port=$1 + case ${port} in + 1|2|3|4|5|6|7|8) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x20 + dataAddr=0 + eeprombusbase=${NUM_MUX3_CHAN0_DEVICE} + gpioBase=240 + ;; + 9|10|11|12|13|14|15|16) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x20 + dataAddr=1 + eeprombusbase=${NUM_MUX4_CHAN0_DEVICE} + gpioBase=240 + ;; + 17|18|19|20|21|22|23|24) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x21 + dataAddr=0 + eeprombusbase=${NUM_MUX5_CHAN0_DEVICE} + gpioBase=$((224 - 16)) + ;; + 25|26|27|28|29|30|31|32) + i2cbus=${NUM_MUX1_CHAN4_DEVICE} + regAddr=0x21 + dataAddr=1 + eeprombusbase=${NUM_MUX6_CHAN0_DEVICE} + gpioBase=$((224 - 16)) + ;; + 33) + i2cbus=${NUM_MUX1_CHAN7_DEVICE} + regAddr=0x27 + dataAddr=0 + gpioBase=145 + ;; + 34) + i2cbus=${NUM_MUX1_CHAN7_DEVICE} + regAddr=0x27 + dataAddr=1 + gpioBase=143 + ;; + *) + echo "Please input 1~34" + ;; + esac +} + +#Set QSFP Port variable +function _qsfp_eeprom_var_set { + local port=$1 + if [ ${port} -lt 33 ]; then + eeprombusidx=$(( ${port} % 8)) + case $eeprombusidx in + 1) + eeprombus=$(( $eeprombusbase + 1 )) + eepromAddr=0x50 + ;; + 2) + eeprombus=$(( $eeprombusbase + 0 )) + eepromAddr=0x50 + ;; + 3) + eeprombus=$(( $eeprombusbase + 3 )) + eepromAddr=0x50 + ;; + 4) + eeprombus=$(( $eeprombusbase + 2 )) + eepromAddr=0x50 + ;; + 5) + eeprombus=$(( $eeprombusbase + 5 )) + eepromAddr=0x50 + ;; + 6) + eeprombus=$(( $eeprombusbase + 4 )) + eepromAddr=0x50 + ;; + 7) + eeprombus=$(( $eeprombusbase + 7 )) + eepromAddr=0x50 + ;; + 0) + eeprombus=$(( $eeprombusbase + 6 )) + eepromAddr=0x50 + ;; + esac + else + case $port in + 33) + eeprombus=${NUM_SFP1_DEVICE} + eepromAddr=0x50 + ;; + 34) + eeprombus=${NUM_SFP2_DEVICE} + eepromAddr=0x50 + ;; + esac + fi +} + +#Get QSFP EEPROM Information +function _i2c_qsfp_eeprom_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + #status: 0 -> Down, 1 -> Up + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) ^ 1)) ))/value` + echo $status + + if [ $status = 0 ]; then + exit + fi + + _qsfp_eeprom_var_set ${QSFP_PORT} + + cat ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom | hexdump -C +} + +#Init QSFP EEPROM +function _i2c_qsfp_eeprom_init { + echo -n "QSFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-32 ports EEPROM + local i + for i in {1..32}; + do + _qsfp_port_i2c_var_set ${i} + + _qsfp_eeprom_var_set ${i} + + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "sff8436 $eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr) ]; then + echo "$eepromAddr" > ${PATH_SYS_I2C_DEVICES}/i2c-$eeprombus/delete_device + fi + done + echo "DONE" +} + +#Init Main Board EEPROM +function _i2c_mb_eeprom_init { + echo -n "Main Board EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init CPU EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0051 ]; then + echo "mb_eeprom 0x51" > ${PATH_I801_DEVICE}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0051 ]; then + echo "0x51" > ${PATH_I801_DEVICE}/delete_device + fi + #Init MB EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0055 ]; then + echo "mb_eeprom 0x55" > ${PATH_I801_DEVICE}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0055 ]; then + echo "0x55" > ${PATH_I801_DEVICE}/delete_device + fi + echo "DONE" +} + +#Init PSU EEPROM +function _i2c_psu_eeprom_init { + echo -n "PSU EEPROM INIT..." + + ## modprobe eeprom + modprobe eeprom + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init PSU EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN1_DEVICE}-0050 ] || \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN0_DEVICE}-0050 ]; then + ## PUS(0) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_FRU_MUX_CHAN1_DEVICE}/new_device + ## PUS(1) EEPROM + echo "eeprom 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_FRU_MUX_CHAN0_DEVICE}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN1_DEVICE}-0050 ] || \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN0_DEVICE}-0050 ]; then + ## PUS(0) EEPROM + echo "0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_FRU_MUX_CHAN1_DEVICE}/delete_device + ## PUS(1) EEPROM + echo "0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_FRU_MUX_CHAN0_DEVICE}/delete_device + fi + echo "DONE" +} + +#Init SFP EEPROM +function _i2c_sfp_eeprom_init { + echo -n "SFP EEPROM INIT..." + + #Action check + action=$1 + if [ -z "${action}" ]; then + echo "No action, skip" + return + elif [ "${action}" != "new" ] && [ "${action}" != "delete" ]; then + echo "Error action, skip" + return + fi + + #Init 1-32 ports EEPROM + if [ "${action}" == "new" ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_SFP1_DEVICE}-0050 ] && \ + ! [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_SFP2_DEVICE}-0050 ]; then + echo "sff8436 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_SFP1_DEVICE}/new_device + echo "sff8436 0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_SFP2_DEVICE}/new_device + elif [ "${action}" == "delete" ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_SFP1_DEVICE}-0050 ] && \ + [ -L ${PATH_SYS_I2C_DEVICES}/${NUM_SFP2_DEVICE}-0050 ]; then + echo "0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_SFP1_DEVICE}/delete_device + echo "0x50" > ${PATH_SYS_I2C_DEVICES}/i2c-${NUM_SFP2_DEVICE}/delete_device + fi + echo "DONE" +} + +#Get MotherBoard EEPROM Information +function _i2c_mb_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + + ## MB EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0055/eeprom | hexdump -C + echo "done..." +} + +#Get CPU EEPROM Information +function _i2c_cpu_eeprom_get { + echo "=========================================================" + echo "# Description: I2C MB EEPROM Get..." + echo "=========================================================" + + ## MB EEPROM + cat ${PATH_SYS_I2C_DEVICES}/${NUM_I801_DEVICE}-0051/eeprom | hexdump -C + echo "done..." +} + +#get QSFP Status +function _i2c_qsfp_status_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + #status: 0 -> Down, 1 -> Up + status=`cat /sys/class/gpio/gpio$(( $(($gpioBase + (${QSFP_PORT} - 1) ^ 1)) ))/value` + echo "status=$status" +} + +#get QSFP Type +function _i2c_qsfp_type_get { + + _qsfp_port_i2c_var_set ${QSFP_PORT} + + _qsfp_eeprom_var_set ${QSFP_PORT} + + #Get QSFP EEPROM info + qsfp_info=$(base64 ${PATH_SYS_I2C_DEVICES}/$eeprombus-$(printf "%04x" $eepromAddr)/eeprom) + + identifier=$(echo $qsfp_info | base64 -d -i | hexdump -s 128 -n 1 -e '"%x"') + connector=$(echo $qsfp_info | base64 -d -i | hexdump -s 130 -n 1 -e '"%x"') + transceiver=$(echo $qsfp_info | base64 -d -i | hexdump -s 131 -n 1 -e '"%x"') + + echo "identifier=$identifier" + echo "connector=$connector" + echo "transceiver=$transceiver" +} + +#Get Board Version and Type +function _i2c_board_type_get { + boardType=`i2cget -y ${NUM_CPLD_DEVICE} 0x33 0x00` + boardBuildRev=$((($boardType) & 0x03)) + boardHwRev=$((($boardType) >> 2 & 0x03)) + boardId=$((($boardType) >> 4)) + printf "BOARD_ID is 0x%02x, HW Rev %d, Build Rev %d\n" $boardId $boardHwRev $boardBuildRev + +} + +#Get CPLD Version +function _i2c_cpld_version { + cpldRev=`i2cget -y ${NUM_CPLD_DEVICE} 0x33 0x01` + cpldRelease=$((($cpldRev) >> 6 & 0x01)) + cpldVersion=$((($cpldRev) & 0x3F)) + printf "CPLD is %s version(0:RD 1:Release), Revision is 0x%02x\n" $cpldRelease $cpldVersion + +} + +#Set Port LED behavior +function _i2c_port_led_set { + local gy_offset=0x0 + local bl_offset=0x0 + local mask=0x0 + if [ "${QSFP_PORT}" == "" ]; then + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + case ${QSFP_PORT} in + 1|2|3|4) + gy_offset=0x80 + bl_offset=0x90 + ;; + 5|6|7|8) + gy_offset=0x81 + bl_offset=0x90 + ;; + 9|10|11|12) + gy_offset=0x82 + bl_offset=0x91 + ;; + 13|14|15|16) + gy_offset=0x83 + bl_offset=0x91 + ;; + 17|18|19|20) + gy_offset=0x84 + bl_offset=0x92 + ;; + 21|22|23|24) + gy_offset=0x85 + bl_offset=0x92 + ;; + 25|26|27|28) + gy_offset=0x86 + bl_offset=0x93 + ;; + 29|30|31|32) + gy_offset=0x87 + bl_offset=0x93 + ;; + 33) + gy_offset=0x88 + bl_offset=0x94 + mask=0x01 + ;; + 34) + gy_offset=0x88 + bl_offset=0x94 + mask=0x02 + ;; + *) + echo "Please input 1~34" + ;; + esac + + #Set green/yellow/off + if [ ${QSFP_PORT} -lt 33 ]; then + mask=$(( 0x3 << $(( $((${QSFP_PORT} - 0x1)) % 0x4 )) * 0x2 )) + elif [ ${QSFP_PORT} = 33 ]; then + value=1 + elif [ ${QSFP_PORT} = 34 ]; then + value=2 + fi + + if [ ${QSFP_PORT} -lt 33 ]; then + if [ "${COLOR_PORT_LED}" == "green" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${gy_offset} 0x55 + elif [ "${COLOR_PORT_LED}" == "yellow" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${gy_offset} 0xaa + elif [ "${COLOR_PORT_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${gy_offset} 0x00 + return + fi + elif [ ${QSFP_PORT} -ge 33 ]; then + if [ "${COLOR_PORT_LED}" == "green" ] || + [ "${COLOR_PORT_LED}" == "yellow" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${gy_offset} $value + elif [ "${COLOR_PORT_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${gy_offset} $((! ${value} )) + return + fi + fi + + #Set Blink/Unblink + if [ ${QSFP_PORT} -lt 33 ]; then + mask=$(( 0x1 << $(( $((${QSFP_PORT} - 0x1)) % 0x8 )) )) + elif [ ${QSFP_PORT} = 33 ]; then + value=1 + elif [ ${QSFP_PORT} = 34 ]; then + value=2 + fi + + if [ "${BLINK_LED}" == "blink" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${bl_offset} 0x00 + elif [ "${BLINK_LED}" == "noblink" ]; then + i2cset -m $mask -y -r ${NUM_CPLD_DEVICE} 0x33 ${bl_offset} 0xff + fi + +} + +#Get PSU EEPROM Information +function _i2c_psu_eeprom_get { + echo "=========================================================" + echo "# Description: I2C PSU EEPROM Get..." + echo "=========================================================" + + ## PUS(0) EEPROM + echo "========PSU1=========" + cat ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN1_DEVICE}-0050/eeprom | hexdump -C + + ## PUS(1) EEPROM + echo "========PSU2=========" + cat ${PATH_SYS_I2C_DEVICES}/${NUM_FRU_MUX_CHAN0_DEVICE}-0050/eeprom | hexdump -C + + echo "done..." +} + +#Set System Status LED +function _i2c_sys_led { + + if [ "${COLOR_SYS_LED}" == "green" ]; then + # set sys_led_g (0.7) = 1 + output_reg=2 + mask=0x01 + value=0x01 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + # set sys_led_g (0.7) = 0 + output_reg=2 + mask=0x01 + value=0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + #apply to io expander + i2cset -m ${mask} -y ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 ${value} + echo "Done" + +} + +#Set FAN Tray LED +function _i2c_fan_tray_led { + case ${FAN_TRAY} in + 1) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_SYS_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 2) + i2cAddr=0x20 + ioPort=2 + if [ "${COLOR_SYS_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + 3) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_SYS_LED}" == "green" ]; then + mask=0x01 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + mask=0x02 + fi + ;; + 4) + i2cAddr=0x20 + ioPort=3 + if [ "${COLOR_SYS_LED}" == "green" ]; then + mask=0x10 + elif [ "${COLOR_SYS_LED}" == "amber" ]; then + mask=0x20 + fi + ;; + *) + echo "Please input 1~4" + exit + ;; + esac + + if [ "${COLOR_SYS_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} $i2cAddr $ioPort 0x33 + elif [ "${COLOR_SYS_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} $i2cAddr $ioPort 0x00 + elif [ "${COLOR_SYS_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m $mask -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} $i2cAddr $ioPort 0x33 + elif [ "${COLOR_SYS_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m $mask -y -r ${NUM_FRU_MUX_CHAN2_DEVICE} $i2cAddr $ioPort 0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + +#Set FAN LED +function _i2c_fan_led { + if [ "${COLOR_SYS_LED}" == "green" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x06 -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 0x02 + elif [ "${COLOR_SYS_LED}" == "green" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x06 -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 0x00 + elif [ "${COLOR_SYS_LED}" == "amber" ] && [ "${ONOFF_LED}" == "on" ]; then + i2cset -m 0x06 -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 0x06 + elif [ "${COLOR_SYS_LED}" == "amber" ] && [ "${ONOFF_LED}" == "off" ]; then + i2cset -m 0x06 -y -r ${NUM_MAIN_MUX_CHAN1_DEVICE} 0x75 2 0x00 + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + echo "done..." +} + + +#Get PSU Status +function _i2c_psu_status { + psu2PwGood=`cat /sys/class/gpio/gpio96/value` # PSU0_PWROK (0.0) + psu2Exist=`cat /sys/class/gpio/gpio97/value` # PSU0_PRSNT_L (0.1) + + psu1PwGood=`cat /sys/class/gpio/gpio99/value` # PSU1_PWROK (0.3) + psu1Exist=`cat /sys/class/gpio/gpio100/value` # PSU1_PRSNT_L (0.4) + printf "PSU1 Exist:%d PSU1 PW Good:%d\n" $psu1Exist $psu1PwGood + printf "PSU2 Exist:%d PSU2 PW Good:%d\n" $psu2Exist $psu2PwGood +} + + +#Main Function +function _main { + start_time_str=`date` + start_time_sec=$(date +%s) + + if [ "${EXEC_FUNC}" == "help" ]; then + _help + elif [ "${EXEC_FUNC}" == "i2c_init" ]; then + _i2c_init + elif [ "${EXEC_FUNC}" == "i2c_deinit" ]; then + _i2c_deinit + elif [ "${EXEC_FUNC}" == "i2c_temp_init" ]; then + _i2c_temp_init + elif [ "${EXEC_FUNC}" == "i2c_fan_init" ]; then + _i2c_fan_init + elif [ "${EXEC_FUNC}" == "i2c_volmon_init" ]; then + _i2c_volmon_init + elif [ "${EXEC_FUNC}" == "i2c_io_exp_init" ]; then + _i2c_io_exp_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_init" ]; then + _i2c_gpio_init + elif [ "${EXEC_FUNC}" == "i2c_gpio_deinit" ]; then + _i2c_gpio_deinit + elif [ "${EXEC_FUNC}" == "i2c_temp_init" ]; then + _i2c_temp_init + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_get" ]; then + _i2c_mb_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_cpu_eeprom_get" ]; then + _i2c_cpu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_get" ]; then + _i2c_psu_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_get" ]; then + _i2c_qsfp_eeprom_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_eeprom_init" ]; then + _i2c_qsfp_eeprom_init ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_sfp_eeprom_init" ]; then + _i2c_sfp_eeprom_init ${QSFP_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_mb_eeprom_init" ]; then + _i2c_mb_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_psu_eeprom_init" ]; then + _i2c_psu_eeprom_init ${MB_EEPROM_ACTION} + elif [ "${EXEC_FUNC}" == "i2c_qsfp_status_get" ]; then + _i2c_qsfp_status_get + elif [ "${EXEC_FUNC}" == "i2c_qsfp_type_get" ]; then + _i2c_qsfp_type_get + elif [ "${EXEC_FUNC}" == "i2c_led_fan_status_set" ]; then + _i2c_led_fan_status_set + elif [ "${EXEC_FUNC}" == "i2c_led_fan_tray_status_set" ]; then + _i2c_led_fan_tray_status_set + elif [ "${EXEC_FUNC}" == "i2c_sys_led" ]; then + _i2c_sys_led + elif [ "${EXEC_FUNC}" == "i2c_fan_led" ]; then + _i2c_fan_led + elif [ "${EXEC_FUNC}" == "i2c_fan_tray_led" ]; then + _i2c_fan_tray_led + elif [ "${EXEC_FUNC}" == "i2c_board_type_get" ]; then + _i2c_board_type_get + elif [ "${EXEC_FUNC}" == "i2c_cpld_version" ]; then + _i2c_cpld_version + elif [ "${EXEC_FUNC}" == "i2c_psu_status" ]; then + _i2c_psu_status + elif [ "${EXEC_FUNC}" == "i2c_port_led_set" ]; then + _i2c_port_led_set + elif [ "${EXEC_FUNC}" == "i2c_test_all" ]; then + _i2c_init + _i2c_temp_init + _i2c_fan_init + _i2c_io_exp_init + _i2c_psu_eeprom_get + _i2c_mb_eeprom_get + _i2c_cpu_eeprom_get + _i2c_board_type_get + _i2c_cpld_version + _i2c_psu_status + else + echo "Invalid Parameters, Exit!!!" + _help + exit ${FALSE} + fi + + end_time_str=`date` + end_time_sec=$(date +%s) + diff_time=$[ ${end_time_sec} - ${start_time_sec} ] + echo "Start Time: ${start_time_str} (${start_time_sec})" + echo "End Time : ${end_time_str} (${end_time_sec})" + echo "Total Execution Time: ${diff_time} sec" + + echo "done!!!" +} + +_main diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/qsfp_monitor.sh b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/qsfp_monitor.sh new file mode 100755 index 000000000000..249f179216a6 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/qsfp_monitor.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# Copyright (C) 2017 Ingrasys, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=3 +I2C_UTILS="/usr/sbin/i2c_utils.sh" +QSFP_SI_SCRIPT="/usr/sbin/qsfp_si_cfg.sh" +QSFP_ARRAY=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + +#QSFP SI monitor +function _qsfp_si_monitor { + local i + local status + for i in {0..31}; + do + status=`${I2C_UTILS} i2c_qsfp_status_get $(expr $i + 1) | egrep '^status=.*$' | sed -e 's/status=//g'` + if [ "${status}" == "1" ]; then + _qsfp_type_check $i + fi + done +} + +#QSFP type +function _qsfp_type_check { + local port=$1 + local qsfp_type=`${I2C_UTILS} i2c_qsfp_type_get $(expr $port + 1)` + local identifier=`echo "$qsfp_type" | grep '^identifier=.*$' | sed -e 's/identifier=//g'` + if [ "${identifier}" == "11" ]; then + connector=`echo "$qsfp_type" | grep '^connector=.*$' | sed -e 's/connector=//g'` + case ${connector} in + 21|23) + #DAC + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to DAC" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} dac $port >/dev/null + fi + ;; + *) + #Optical + if [ "${QSFP_ARRAY[$port]}" != "${connector}" ]; then + echo "Change Port $(expr $port + 1) to Optical" + QSFP_ARRAY[$port]=${connector} + ${QSFP_SI_SCRIPT} optical $port >/dev/null + fi + ;; + esac + fi +} + +#Docker exist check +function _docker_swss_check { + while true + do + # Check if syncd starts + result=`docker exec -i swss bash -c "echo -en \"SELECT 1\\nHLEN HIDDEN\" | redis-cli | sed -n 2p"` #TBD FIX ME + if [ "$result" == "3" ]; then + return + fi + sleep $INTERVAL + done +} + +#Docker exist check +function _qsfp_si_cfg_script_check { + + if [ -f ${QSFP_SI_SCRIPT} ] && [ -x ${QSFP_SI_SCRIPT} ]; then + echo "SI Script exists. Start monitor." + return + else + echo "SI Script not exist. Exit monitor." + exit + fi +} + +# main function +function _main { + #Check SI Script + _qsfp_si_cfg_script_check + #Check docker swss is running + _docker_swss_check + while true + do + _qsfp_si_monitor + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main + diff --git a/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/s9180_32x_monitor.sh b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/s9180_32x_monitor.sh new file mode 100755 index 000000000000..c110bdeaaf04 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-ingrasys/s9180-32x/utils/s9180_32x_monitor.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# Copyright (C) 2016 Ingrasys, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +INTERVAL=5 +I2C_UTILS="/usr/sbin/i2c_utils.sh" + + +# TBD: LED status monitor +function _led_monitor { + ${I2C_UTILS} i2c_led_fan_status_set >/dev/null + ${I2C_UTILS} i2c_led_fan_tray_status_set >/dev/null +} + +# main function +function _main { + while true + do + #PSU controlled by dummy board, + #but fan LED and fan tray LED must controlled by this service + _led_monitor + + # Sleep while still handling signals + sleep $INTERVAL & + wait $! + done +} + +_main \ No newline at end of file diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/LICENSE b/platform/barefoot/sonic-platform-modules-wnc-osw1800/LICENSE new file mode 100644 index 000000000000..676cdeec726b --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2016 Microsoft, Inc + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/MAINTAINERS b/platform/barefoot/sonic-platform-modules-wnc-osw1800/MAINTAINERS new file mode 100644 index 000000000000..a578b60e24de --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/MAINTAINERS @@ -0,0 +1,7 @@ +# This file describes the maintainers for sonic-platform-modules-wnc-osw1800 +# See the SONiC project governance document for more information + +Name = "WNC" +Email = "wnc@wnc.com.tw" +Github = barefootnetworks +Mailinglist = wnc@wnc.com.tw diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/README.md b/platform/barefoot/sonic-platform-modules-wnc-osw1800/README.md new file mode 100644 index 000000000000..707c1068d6e6 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/README.md @@ -0,0 +1,2 @@ +# sonic-platform-modules-wnc-osw1800 +Device drivers for support of BFN platform for the SONiC project diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/changelog b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/changelog new file mode 100644 index 000000000000..466378b892d1 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/changelog @@ -0,0 +1,5 @@ +platform-modules-wnc-osw1800 (1.0) unstable; urgency=low + + * Initial release + + -- WNC Mon, 11 Nov 2015 11:11:11 -0800 diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/compat b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/compat new file mode 100644 index 000000000000..45a4fb75db86 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/compat @@ -0,0 +1 @@ +8 diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/control b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/control new file mode 100644 index 000000000000..6070cf9ad1fc --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/control @@ -0,0 +1,12 @@ +Source: platform-modules-wnc-osw1800 +Section: main +Priority: extra +Maintainer: WNC +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-wnc-osw1800 +Architecture: amd64 +Depends: linux-image-3.16.0-5-amd64 +Description: kernel modules for platform devices such as fan, led, sfp + diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/copyright b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/copyright new file mode 100644 index 000000000000..ade42b7aa75a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/copyright @@ -0,0 +1,15 @@ +Provides linux kernel driver for BF PCIe devices + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/rules b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/rules new file mode 100755 index 000000000000..644ab1ade433 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/rules @@ -0,0 +1,38 @@ +#!/usr/bin/make -f + +export INSTALL_MOD_DIR:=extra + +PACKAGE_NAME := platform-modules-wnc-osw1800 +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MODULE_SRC := $(shell pwd)/modules +SCRIPT_SRC := $(shell pwd)/scripts +SERVICE_SRC := $(shell pwd)/service + +%: + dh $@ + +override_dh_auto_build: + make -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + +override_dh_auto_install: + dh_installdirs -p$(PACKAGE_NAME) $(KERNEL_SRC)/$(INSTALL_MOD_DIR) + cp $(MODULE_SRC)/*.ko debian/$(PACKAGE_NAME)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR) + dh_installdirs -p$(PACKAGE_NAME) usr/local/bin + cp -r $(SCRIPT_SRC)/* debian/$(PACKAGE_NAME)/usr/local/bin + dh_installdirs -p$(PACKAGE_NAME) /etc/systemd/system + cp -r $(SERVICE_SRC)/* debian/$(PACKAGE_NAME)/etc/systemd/system + dh_installdirs -p$(PACKAGE_NAME) /etc/systemd/system/multi-user.target.wants + ln -s ../device_node.service debian/$(PACKAGE_NAME)/etc/systemd/system/multi-user.target.wants/device_node.service + ln -s ../driver_load.service debian/$(PACKAGE_NAME)/etc/systemd/system/multi-user.target.wants/driver_load.service + +override_dh_usrlocal: + +override_dh_pysupport: + +override_dh_clean: + dh_clean + rm -f $(MODULE_SRC)/*.o $(MODULE_SRC)/*.ko $(MODULE_SRC)/*.mod.c $(MODULE_SRC)/.*.cmd + rm -f $(MODULE_SRC)/Module.markers $(MODULE_SRC)/Module.symvers $(MODULE_SRC)/modules.order + rm -rf $(MODULE_SRC)/.tmp_versions + diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/Makefile b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/Makefile new file mode 100644 index 000000000000..29b904dd3232 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/Makefile @@ -0,0 +1,6 @@ +obj-m := bf_kdrv.o +obj-m += bf_tun.o +obj-m += i2c-mcp2221.o +obj-m += wnc_cpld.o +obj-m += wnc_cpld3.o +obj-m += wnc_eeprom.o diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/bf_kdrv.c b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/bf_kdrv.c new file mode 100644 index 000000000000..fd66ad09493a --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/bf_kdrv.c @@ -0,0 +1,1254 @@ +/******************************************************************************* + * BAREFOOT NETWORKS CONFIDENTIAL & PROPRIETARY + * + * Copyright (c) 2015-2016 Barefoot Networks, Inc. + + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains the property of + * Barefoot Networks, Inc. and its suppliers, if any. The intellectual and + * technical concepts contained herein are proprietary to Barefoot Networks, + * Inc. + * and its suppliers and may be covered by U.S. and Foreign Patents, patents in + * process, and are protected by trade secret or copyright law. + * Dissemination of this information or reproduction of this material is + * strictly forbidden unless prior written permission is obtained from + * Barefoot Networks, Inc. + * + * No warranty, explicit or implicit is provided, unless granted under a + * written agreement with Barefoot Networks, Inc. + * + * $Id: $ + * + ******************************************************************************/ +/** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2015 Barefoot Networks. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the... + * + **/ + +/* bf_drv kernel module + * + * This is kernel mode driver for Tofino chip. + * Provides user space mmap service and user space "wait for interrupt" + * and "enable interrupt" services. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) + #include +#else + #include +#endif + +#include +#include +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) +//#error unsupported linux kernel version +#endif + +/* TBD: Need to build with CONFIG_PCI_MSI */ +extern int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec); +extern int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int minvec, int maxvec); + +#define PCI_VENDOR_ID_BF 0x1d1c +#define TOFINO_DEV_ID_A0 0x01 +#define TOFINO_DEV_ID_B0 0x10 + +#ifndef PCI_MSIX_ENTRY_SIZE +#define PCI_MSIX_ENTRY_SIZE 16 +#define PCI_MSIX_ENTRY_LOWER_ADDR 0 +#define PCI_MSIX_ENTRY_UPPER_ADDR 4 +#define PCI_MSIX_ENTRY_DATA 8 +#define PCI_MSIX_ENTRY_VECTOR_CTRL 12 +#define PCI_MSIX_ENTRY_CTRL_MASKBIT 1 +#endif + +#define BF_CLASS_NAME "bf" +#define BF_MAX_DEVICE_CNT 256 +#define BF_INTR_MODE_NONE_NAME "none" +#define BF_INTR_MODE_LEGACY_NAME "legacy" +#define BF_INTR_MODE_MSI_NAME "msi" +#define BF_INTR_MODE_MSIX_NAME "msix" +#define BF_MAX_BAR_MAPS 6 +#define BF_MSIX_ENTRY_CNT 128 /* TBD make it 512 */ +#define BF_MSI_ENTRY_CNT 2 + +/* interrupt mode */ +enum bf_intr_mode { + BF_INTR_MODE_NONE = 0, + BF_INTR_MODE_LEGACY, + BF_INTR_MODE_MSI, + BF_INTR_MODE_MSIX +}; + +/* device memory */ +struct bf_dev_mem { + const char *name; + phys_addr_t addr; + resource_size_t size; + void __iomem *internal_addr; +}; + +struct bf_listener { + struct bf_pci_dev *bfdev; + s32 event_count[BF_MSIX_ENTRY_CNT]; + int minor; + struct bf_listener *next; +}; + +/* device information */ +struct bf_dev_info { + struct module *owner; + struct device *dev; + int minor; + atomic_t event[BF_MSIX_ENTRY_CNT]; + wait_queue_head_t wait; + const char *version; + struct bf_dev_mem mem[BF_MAX_BAR_MAPS]; + struct msix_entry *msix_entries; + long irq; /* first irq vector */ + int num_irq; /* number of irq vectors */ + unsigned long irq_flags;/* sharable ?? */ + int pci_error_state; /* was there a pci bus error */ +}; + +/* cookie to be passed to IRQ handler, useful especially with MSIX */ +struct bf_int_vector { + struct bf_pci_dev *bf_dev; + int int_vec_offset; +}; + + +/** + * A structure describing the private information for a BF pcie device. + */ +struct bf_pci_dev { + struct bf_dev_info info; + struct pci_dev *pdev; + enum bf_intr_mode mode; + u8 instance; + char name[16]; + struct bf_int_vector bf_int_vec[BF_MSIX_ENTRY_CNT]; + struct bf_listener *listener_head; /* head of a singly linked list of + listeners */ +}; + +/* Keep any global information here that must survive even after the + * bf_pci_dev is free-ed up. + */ +struct bf_global { + struct bf_pci_dev *bfdev ; + struct cdev *bf_cdev; + struct fasync_struct *async_queue; +}; + +static int bf_major; +static int bf_minor[BF_MAX_DEVICE_CNT] = {0}; +static struct class *bf_class = NULL; +static char *intr_mode = NULL; +static enum bf_intr_mode bf_intr_mode_default = BF_INTR_MODE_MSI; +static spinlock_t bf_nonisr_lock; +/* dev->minor should index into this array */ +static struct bf_global bf_global[BF_MAX_DEVICE_CNT]; + +static void bf_add_listener(struct bf_pci_dev *bfdev, + struct bf_listener *listener) +{ + struct bf_listener **cur_listener = &bfdev->listener_head; + + if (!listener) { + return; + } + spin_lock(&bf_nonisr_lock); + + while (*cur_listener) { + cur_listener = &((*cur_listener)->next); + } + *cur_listener = listener; + listener->next = NULL; + + spin_unlock(&bf_nonisr_lock); +} + +static void bf_remove_listener(struct bf_pci_dev *bfdev, + struct bf_listener *listener) +{ + struct bf_listener **cur_listener = &bfdev->listener_head; + + /* in case of certain error conditions, this function might be called after bf_pci_remove() + */ + if (!bfdev || !listener) { + return; + } + spin_lock(&bf_nonisr_lock); + + if (*cur_listener == listener) { + *cur_listener = listener->next; + } else { + while (*cur_listener) { + if ((*cur_listener)->next == listener) { + (*cur_listener)->next = listener->next; + break; + } + cur_listener = &((*cur_listener)->next); + } + listener->next = NULL; + } + + spin_unlock(&bf_nonisr_lock); +} + +/* a pool of minor numbers is maintained */ +/* return the first available minor number */ +static int bf_get_next_minor_no(int *minor) +{ + int i; + + spin_lock(&bf_nonisr_lock); + for(i = 0; i < BF_MAX_DEVICE_CNT; i++) { + if (bf_minor[i] == 0) { + *minor = i; + bf_minor[i] = 1; /* mark it as taken */ + spin_unlock(&bf_nonisr_lock); + return 0; + } + } + *minor = -1; + spin_unlock(&bf_nonisr_lock); + return -1; +} + +/* return a minor number back to the pool for recycling */ +static int bf_return_minor_no(int minor) +{ + int err; + + spin_lock(&bf_nonisr_lock); + if (bf_minor[minor] == 0) { /* was already returned */ + err = -1; /* don't change anything, but return error */ + } else { + bf_minor[minor] = 0; /* mark it as available */ + err = 0; + } + spin_unlock(&bf_nonisr_lock); + return err; +} + +static inline struct bf_pci_dev *bf_get_pci_dev(struct bf_dev_info *info) +{ + return container_of(info, struct bf_pci_dev, info); +} + +/* + * It masks the msix on/off of generating MSI-X messages. + */ +static void +bf_msix_mask_irq(struct msi_desc *desc, int32_t state) +{ + u32 mask_bits = desc->masked; + unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_VECTOR_CTRL; + + if (state != 0) + mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT; + else + mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT; + + if (mask_bits != desc->masked) { + writel(mask_bits, desc->mask_base + offset); + readl(desc->mask_base); + desc->masked = mask_bits; + } +} + +/** + * irqcontrol can be used to disable/enable interrupt from user space processes. + * + * @param bf_dev + * pointer to bf_pci_dev + * @param irq_state + * state value. 1 to enable interrupt, 0 to disable interrupt. + * + * @return + * - On success, 0. + * - On failure, a negative value. + */ +static int +bf_pci_irqcontrol(struct bf_pci_dev *bfdev, s32 irq_state) +{ + struct pci_dev *pdev = bfdev->pdev; + + pci_cfg_access_lock(pdev); + if (bfdev->mode == BF_INTR_MODE_LEGACY) + pci_intx(pdev, !!irq_state); + + else if (bfdev->mode == BF_INTR_MODE_MSIX) { + struct msi_desc *desc; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0) + list_for_each_entry(desc, &pdev->msi_list, list) + bf_msix_mask_irq(desc, irq_state); +#else + for_each_pci_msi_entry(desc, pdev) + bf_msix_mask_irq(desc, irq_state); +#endif + } + pci_cfg_access_unlock(pdev); + + return 0; +} + +/** + * interrupt handler which will check if the interrupt is from the right + * device. If so, disable it here and will be enabled later. + */ +static irqreturn_t bf_pci_irqhandler(int irq, struct bf_pci_dev *bfdev) +{ + /* Legacy mode need to mask in hardware */ + if (bfdev->mode == BF_INTR_MODE_LEGACY && + !pci_check_and_mask_intx(bfdev->pdev)) + return IRQ_NONE; + + /* NOTE : if bfdev->info.pci_error_state == 1, then do not access the + * device and return IRQ_NOTHANDLED. + */ + /* Message signal mode, no share IRQ and automasked */ + return IRQ_HANDLED; +} + +/* Remap pci resources described by bar #pci_bar */ +static int +bf_pci_setup_iomem(struct pci_dev *dev, struct bf_dev_info *info, + int n, int pci_bar, const char *name) +{ + unsigned long addr, len; + void *internal_addr; + + if (sizeof(info->mem) / sizeof(info->mem[0]) <= n) + return -EINVAL; + + addr = pci_resource_start(dev, pci_bar); + len = pci_resource_len(dev, pci_bar); + if (addr == 0 || len == 0) + return -1; + internal_addr = pci_ioremap_bar(dev, pci_bar); + if (internal_addr == NULL) + return -1; + info->mem[n].name = name; + info->mem[n].addr = addr; + info->mem[n].internal_addr = internal_addr; + info->mem[n].size = len; + return 0; +} + +/* Unmap previously ioremap'd resources */ +static void +bf_pci_release_iomem(struct bf_dev_info *info) +{ + int i; + + for (i = 0; i < BF_MAX_BAR_MAPS; i++) { + if (info->mem[i].internal_addr) + iounmap(info->mem[i].internal_addr); + } +} + +static int +bf_setup_bars(struct pci_dev *dev, struct bf_dev_info *info) +{ + int i, iom, ret; + unsigned long flags; + static const char *bar_names[BF_MAX_BAR_MAPS] = { + "BAR0", "BAR1", "BAR2", "BAR3", "BAR4", "BAR5", + }; + + iom = 0; + + for (i = 0; i < BF_MAX_BAR_MAPS; i++) { + if (pci_resource_len(dev, i) != 0 && + pci_resource_start(dev, i) != 0) { + flags = pci_resource_flags(dev, i); + if (flags & IORESOURCE_MEM) { + ret = bf_pci_setup_iomem(dev, info, iom, i, bar_names[i]); + if (ret != 0) + return ret; + iom++; + } + } + } + return (iom != 0) ? ret : -ENOENT; +} + +static irqreturn_t bf_interrupt(int irq, void *bfdev_id) +{ + struct bf_pci_dev *bfdev = ((struct bf_int_vector *)bfdev_id)->bf_dev; + int vect_off = ((struct bf_int_vector *)bfdev_id)->int_vec_offset; + + irqreturn_t ret = bf_pci_irqhandler(irq, bfdev); + + if (ret == IRQ_HANDLED) + atomic_inc(&(bfdev->info.event[vect_off])); + + return ret; +} + +static unsigned int bf_poll(struct file *filep, poll_table *wait) +{ + struct bf_listener *listener = (struct bf_listener *)filep->private_data; + struct bf_pci_dev *bfdev = listener->bfdev; + int i; + + if (!bfdev) { + return -ENODEV; + } + if (!bfdev->info.irq) + return -EIO; + + poll_wait(filep, &bfdev->info.wait, wait); + + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) + if (listener->event_count[i] != atomic_read(&bfdev->info.event[i])) + return POLLIN | POLLRDNORM; + return 0; +} + +static int bf_find_mem_index(struct vm_area_struct *vma) +{ + struct bf_pci_dev *bfdev = vma->vm_private_data; + if (vma->vm_pgoff < BF_MAX_BAR_MAPS) { + if (bfdev->info.mem[vma->vm_pgoff].size == 0) + return -1; + return (int)vma->vm_pgoff; + } + return -1; +} + +static const struct vm_operations_struct bf_physical_vm_ops = { +#ifdef CONFIG_HAVE_IOREMAP_PROT + .access = generic_access_phys, +#endif +}; + +static int bf_mmap_physical(struct vm_area_struct *vma) +{ + struct bf_pci_dev *bfdev = vma->vm_private_data; + int bar = bf_find_mem_index(vma); + struct bf_dev_mem *mem; + if (bar < 0) + return -EINVAL; + + mem = bfdev->info.mem + bar; + + if (mem->addr & ~PAGE_MASK) + return -ENODEV; + if (vma->vm_end - vma->vm_start > mem->size) + return -EINVAL; + + vma->vm_ops = &bf_physical_vm_ops; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + /* + * We cannot use the vm_iomap_memory() helper here, + * because vma->vm_pgoff is the map index we looked + * up above in bf_find_mem_index(), rather than an + * actual page offset into the mmap. + * + * So we just do the physical mmap without a page + * offset. + */ + return remap_pfn_range(vma, vma->vm_start, mem->addr >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot); +} + +static int bf_mmap(struct file *filep, struct vm_area_struct *vma) +{ + struct bf_listener *listener = filep->private_data; + struct bf_pci_dev *bfdev = listener->bfdev; + int bar; + unsigned long requested_pages, actual_pages; + + if (!bfdev) { + return -ENODEV; + } + if (vma->vm_end < vma->vm_start) + return -EINVAL; + + vma->vm_private_data = bfdev; + + bar = bf_find_mem_index(vma); + if (bar < 0) + return -EINVAL; + + requested_pages = vma_pages(vma); + actual_pages = ((bfdev->info.mem[bar].addr & ~PAGE_MASK) + + bfdev->info.mem[bar].size + PAGE_SIZE -1) >> PAGE_SHIFT; + if (requested_pages > actual_pages) + return -EINVAL; + + return bf_mmap_physical(vma); +} + +static int bf_fasync(int fd, struct file *filep, int mode) +{ + int minor; + + if (!filep->private_data) { + return (-EINVAL); + } + minor = ((struct bf_listener *)filep->private_data)->minor; + if (minor >= BF_MAX_DEVICE_CNT) { + return (-EINVAL); + } + if (mode == 0 && &bf_global[minor].async_queue == NULL) { + return 0; /* nothing to do */ + } + return (fasync_helper(fd, filep, mode, &bf_global[minor].async_queue)); +} + +static int bf_open(struct inode *inode, struct file *filep) +{ + struct bf_pci_dev *bfdev; + struct bf_listener *listener; + int i; + + bfdev = bf_global[iminor(inode)].bfdev; + listener = kmalloc(sizeof(*listener), GFP_KERNEL); + if (listener) { + listener->bfdev = bfdev; + listener->minor = bfdev->info.minor; + listener->next = NULL; + bf_add_listener(bfdev, listener); + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) + listener->event_count[i] = atomic_read(&bfdev->info.event[i]); + filep->private_data = listener; + return 0; + } else { + return(-ENOMEM); + } +} + +static int bf_release(struct inode *inode, struct file *filep) +{ + struct bf_listener *listener = filep->private_data; + + bf_fasync(-1, filep, 0); /* empty any process id in the notification list */ + if (listener->bfdev) { + bf_remove_listener(listener->bfdev, listener); + } + kfree(listener); + return 0; +} + +/* user space support: make read() system call after poll() of select() */ +static ssize_t bf_read(struct file *filep, char __user *buf, + size_t count, loff_t *ppos) +{ + struct bf_listener *listener = filep->private_data; + struct bf_pci_dev *bfdev = listener->bfdev; + int retval, event_count[BF_MSIX_ENTRY_CNT]; + int i, mismatch_found = 0; /* OR of per vector mismatch */ + unsigned char cnt_match[BF_MSIX_ENTRY_CNT]; /* per vector mismatch */ + + if (!bfdev) { + return -ENODEV; + } + /* irq must be setup for read() to work */ + if (!bfdev->info.irq) + return -EIO; + + /* ensure that there is enough space on user buffer for the given interrupt + * mode */ + if (bfdev->mode == BF_INTR_MODE_MSIX) { + if (count < sizeof(s32)*BF_MSIX_ENTRY_CNT) + return -EINVAL; + count = sizeof(s32)*BF_MSIX_ENTRY_CNT; + } else if (bfdev->mode == BF_INTR_MODE_MSI) { + if (count < sizeof(s32)*BF_MSI_ENTRY_CNT) + return -EINVAL; + count = sizeof(s32)*BF_MSI_ENTRY_CNT; + } else { + if (count < sizeof(s32)) + return -EINVAL; + count = sizeof(s32); + } + + do { + set_current_state(TASK_INTERRUPTIBLE); + + for (i = 0; i < (count/sizeof(s32)); i++) { + event_count[i] = atomic_read(&(bfdev->info.event[i])); + if (event_count[i] != listener->event_count[i]) { + mismatch_found |= 1; + cnt_match[i] = 1; + } else { + event_count[i] = 0; + cnt_match[i] = 0; + } + } + if (mismatch_found) { + __set_current_state(TASK_RUNNING); + if (copy_to_user(buf, &event_count, count)) + retval = -EFAULT; + else { /* adjust the listener->event_count; */ + for (i = 0 ; i < (count/sizeof(s32)); i++) { + if (cnt_match[i]) { + listener->event_count[i] = event_count[i]; + } + } + retval = count; + } + break; + } + + if (filep->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + break; + } + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + schedule(); + } while (1); + + __set_current_state(TASK_RUNNING); + + return retval; +} + +/* user space is supposed to call this after it is done with interrupt + * processing + */ +static ssize_t bf_write(struct file *filep, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct bf_listener *listener = filep->private_data; + struct bf_pci_dev *bfdev = listener->bfdev; + ssize_t ret; + s32 int_en; + + if (!bfdev || !bfdev->info.irq) + return -EIO; + + if (count != sizeof(s32)) + return -EINVAL; + + if (copy_from_user(&int_en, buf, count)) + return -EFAULT; + + /* clear pci_error_state */ + bfdev->info.pci_error_state = 0; + + ret = bf_pci_irqcontrol(bfdev, int_en); + + return ret ? ret : sizeof(s32); +} + +static const struct file_operations bf_fops = { + .owner = THIS_MODULE, + .open = bf_open, + .release = bf_release, + .read = bf_read, + .write = bf_write, + .mmap = bf_mmap, + .poll = bf_poll, + .fasync = bf_fasync, +}; + +static int bf_major_init(struct bf_pci_dev *bfdev, int minor) +{ + struct cdev *cdev; + static const char name[] = "bf"; + dev_t bf_dev = 0; + int result; + + result = alloc_chrdev_region(&bf_dev, 0, BF_MAX_DEVICE_CNT, name); + if (result) + return result; + + result = -ENOMEM; + cdev = cdev_alloc(); + if (!cdev) { + goto fail_dev_add; + } + cdev->ops = &bf_fops; + cdev->owner = THIS_MODULE; + kobject_set_name(&cdev->kobj, "%s", name); + result = cdev_add(cdev, bf_dev, BF_MAX_DEVICE_CNT); + + if (result) + goto fail_dev_add; + + bf_major = MAJOR(bf_dev); + bf_global[minor].bf_cdev = cdev; + return 0; + +fail_dev_add: + unregister_chrdev_region(bf_dev, BF_MAX_DEVICE_CNT); + return result; +} + +static void bf_major_cleanup(struct bf_pci_dev *bfdev, int minor) +{ + unregister_chrdev_region(MKDEV(bf_major, 0), BF_MAX_DEVICE_CNT); + cdev_del(bf_global[minor].bf_cdev); +} + +static int bf_init_cdev(struct bf_pci_dev *bfdev, int minor) +{ + int ret; + ret = bf_major_init(bfdev, minor); + if (ret) + return ret; + + bf_class = class_create(THIS_MODULE, BF_CLASS_NAME); + if (!bf_class) { + printk(KERN_ERR "create_class failed for bf_dev\n"); + ret = -ENODEV; + goto err_class_register; + } + return 0; + +err_class_register: + bf_major_cleanup(bfdev, minor); + return ret; +} + +static void bf_remove_cdev(struct bf_pci_dev *bfdev) +{ + class_destroy(bf_class); + bf_major_cleanup(bfdev, bfdev->info.minor); +} + + +/** + * bf_register_device - register a new userspace mem device + * @parent: parent device + * @bfdev: bf pci device + * + * returns zero on success or a negative error code. + */ +int bf_register_device(struct device *parent, struct bf_pci_dev *bfdev) +{ + struct bf_dev_info *info = &bfdev->info; + int i, j, ret = 0; + int minor; + + if (!parent || !info || !info->version) + return -EINVAL; + + init_waitqueue_head(&info->wait); + + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) { + atomic_set(&info->event[i], 0); + } + + if (bf_get_next_minor_no(&minor)) { + return -EINVAL; + } + + ret = bf_init_cdev(bfdev, minor); + if (ret) { + printk(KERN_ERR "BF: device cdev creation failed\n"); + return ret; + } + + info->dev = device_create(bf_class, parent, + MKDEV(bf_major, minor), bfdev, + "bf%d", minor); + if (!info->dev) { + printk(KERN_ERR "BF: device creation failed\n"); + return -ENODEV; + } + + info->minor = minor; + + /* bind ISRs and request interrupts */ + if (info->irq && (bfdev->mode != BF_INTR_MODE_NONE)) { + /* + * Note that we deliberately don't use devm_request_irq + * here. The parent module can unregister the UIO device + * and call pci_disable_msi, which requires that this + * irq has been freed. However, the device may have open + * FDs at the time of unregister and therefore may not be + * freed until they are released. + */ + if (bfdev->mode == BF_INTR_MODE_LEGACY) { + ret = request_irq(info->irq, bf_interrupt, + info->irq_flags, bfdev->name, + (void *)&(bfdev->bf_int_vec[0])); + if (ret) { + printk(KERN_ERR "bf failed to request legacy irq %ld error %d\n", + info->irq, ret); + return ret; + } + printk(KERN_NOTICE "BF allocating legacy int vector %ld\n", info->irq); + } else if (bfdev->mode == BF_INTR_MODE_MSIX) { + for (i = 0; i < info->num_irq; i++) { + ret = request_irq(info->msix_entries[i].vector, bf_interrupt, + info->irq_flags, bfdev->name, + (void *)&(bfdev->bf_int_vec[i])); + if (ret) { + /* undo all other previous bindings */ + printk(KERN_ERR "bf failed to request MSIX ret %d itr %d\n", ret, i); + for (j = i - 1; j >= 0; j--) { + free_irq(info->msix_entries[j].vector, + (void *)&(bfdev->bf_int_vec[j])); + } + return ret; + } + } + printk(KERN_NOTICE "BF allocating %d MSIx vectors from %ld\n", + info->num_irq, info->irq); + } else if (bfdev->mode == BF_INTR_MODE_MSI) { + for (i = 0; i < info->num_irq; i++) { + ret = request_irq(info->irq + i, bf_interrupt, + info->irq_flags, bfdev->name, + (void *)&(bfdev->bf_int_vec[i])); + if (ret) { + /* undo all other previous bindings */ + printk(KERN_ERR "bf failed to request MSI ret %d itr %d\n", ret, i); + for (j = i - 1; j >= 0; j--) { + free_irq(info->irq + j, (void *)&(bfdev->bf_int_vec[j])); + } + return ret; + } + } + printk(KERN_NOTICE "BF allocating %d MSI vectors from %ld\n", + info->num_irq, info->irq); + } + } + return 0; +} + +/** + * bf_unregister_device - register a new userspace mem device + * @bfdev: bf pci device + * + * returns none + */ +void bf_unregister_device(struct bf_pci_dev *bfdev) +{ + struct bf_dev_info *info = &bfdev->info; + int i; + + if (info->irq) { + if (bfdev->mode == BF_INTR_MODE_LEGACY) { + free_irq(info->irq, (void *)&(bfdev->bf_int_vec[0])); + } else if (bfdev->mode == BF_INTR_MODE_MSIX) { + for (i = 0; i < info->num_irq; i++) { + free_irq(info->msix_entries[i].vector, (void *)&(bfdev->bf_int_vec[i])); + } + } else if (bfdev->mode == BF_INTR_MODE_MSI) { + for (i = 0; i < info->num_irq; i++) { + free_irq(info->irq + i, (void *)&(bfdev->bf_int_vec[i])); + } + } + } + device_destroy(bf_class, MKDEV(bf_major, info->minor)); + bf_remove_cdev(bfdev); + bf_return_minor_no(info->minor); + return; +} + +static inline struct device *pci_dev_to_dev(struct pci_dev *pdev) +{ + return &pdev->dev; +} + +static int +bf_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct bf_pci_dev *bfdev; + int err, pci_use_highmem; + int i, num_irq; + + memset(bf_global, 0, sizeof(bf_global)); + + bfdev = kzalloc(sizeof(struct bf_pci_dev), GFP_KERNEL); + if (!bfdev) + return -ENOMEM; + + /* init the cookies to be passed to ISRs */ + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) { + bfdev->bf_int_vec[i].int_vec_offset = i; + bfdev->bf_int_vec[i].bf_dev = bfdev; + } + + /* initialize intr_mode to none */ + bfdev->mode = BF_INTR_MODE_NONE; + + /* clear pci_error_state */ + bfdev->info.pci_error_state = 0; + + /* + * enable device + */ + err = pci_enable_device(pdev); + if (err != 0) { + dev_err(&pdev->dev, "Cannot enable PCI device\n"); + goto fail_free; + } + + /* + * reserve device's PCI memory regions for use by this + * module + */ + err = pci_request_regions(pdev, "bf_umem"); + if (err != 0) { + dev_err(&pdev->dev, "Cannot request regions\n"); + goto fail_pci_disable; + } + /* remap IO memory */ + err = bf_setup_bars(pdev, &bfdev->info); + if (err != 0) + goto fail_release_iomem; + + if (!dma_set_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(64)) && + !dma_set_coherent_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(64))) { + pci_use_highmem = 1; + } else { + err = dma_set_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(32)); + if (err) { + err = dma_set_coherent_mask(pci_dev_to_dev(pdev), + DMA_BIT_MASK(32)); + if (err) { + dev_err(pci_dev_to_dev(pdev), "No usable DMA " + "configuration, aborting\n"); + goto fail_release_iomem; + } + } + pci_use_highmem = 0; + } + + /* enable pci error reporting */ + /* for the current kernel version, kernel config must have set the followings: + * CONFIG_PCIEPORTBUS=y and CONFIG_PCIEAER = y + * we have pci_error_handlers defined that gets invoked by kernel AER module + * upon detecting the pcie error on this device's addresses. + * However, there seems no way that AER would pass the offending addresses + * to the callback functions. AER logs the error messages on the console. + * This driver's calback function send the SIGIO signal to the user space + * to indicate the error condition. + */ + pci_enable_pcie_error_reporting(pdev); + + /* enable bus mastering on the device */ + pci_set_master(pdev); + + /* fill in bfdev info */ + bfdev->info.version = "0.2"; + bfdev->info.owner = THIS_MODULE; + bfdev->pdev = pdev; + + switch (bf_intr_mode_default) { +#ifdef CONFIG_PCI_MSI + case BF_INTR_MODE_MSIX: + /* Only 1 msi-x vector needed */ + bfdev->info.msix_entries = kcalloc(BF_MSIX_ENTRY_CNT, + sizeof(struct msix_entry), GFP_KERNEL); + if (!bfdev->info.msix_entries) { + err = -ENOMEM; + goto fail_clear_pci_master; + } + for (i = 0; i < BF_MSIX_ENTRY_CNT; i++) { + bfdev->info.msix_entries[i].entry= i; + } + num_irq = pci_enable_msix_range(pdev, bfdev->info.msix_entries, + BF_MSIX_ENTRY_CNT, BF_MSIX_ENTRY_CNT); + if (num_irq == BF_MSIX_ENTRY_CNT) { + dev_dbg(&pdev->dev, "using MSI-X"); + bfdev->info.num_irq = num_irq; + bfdev->info.irq = bfdev->info.msix_entries[0].vector; + bfdev->mode = BF_INTR_MODE_MSIX; + printk(KERN_DEBUG "bf using %d MSIX irq from %ld\n", num_irq, + bfdev->info.irq); + break; + } else { + if (num_irq) + pci_disable_msix(pdev); + kfree(bfdev->info.msix_entries); + bfdev->info.msix_entries = NULL; + printk(KERN_ERR "bf error allocating MSIX vectors. Trying MSI...\n"); + /* and, fall back to MSI */ + } + /* ** intentional no-break */ + case BF_INTR_MODE_MSI: + num_irq = pci_enable_msi_range(pdev, BF_MSI_ENTRY_CNT, BF_MSI_ENTRY_CNT); + if (num_irq > 0) { + dev_dbg(&pdev->dev, "using MSI"); + bfdev->info.num_irq = num_irq; + bfdev->info.irq = pdev->irq; + bfdev->mode = BF_INTR_MODE_MSI; + printk(KERN_DEBUG "bf using %d MSI irq from %ld\n", bfdev->info.num_irq, + bfdev->info.irq); + break; + } +#endif /* CONFIG_PCI_MSI */ + /* fall back to Legacy Interrupt, intentional no-break */ + + case BF_INTR_MODE_LEGACY: + if (pci_intx_mask_supported(pdev)) { + dev_dbg(&pdev->dev, "using INTX"); + bfdev->info.irq_flags = IRQF_SHARED; + bfdev->info.irq = pdev->irq; + bfdev->mode = BF_INTR_MODE_LEGACY; + printk(KERN_DEBUG "bf using LEGACY irq %ld\n", bfdev->info.irq); + break; + } + dev_notice(&pdev->dev, "PCI INTx mask not supported\n"); + /* fall back to no Interrupt, intentional no-break */ + case BF_INTR_MODE_NONE: + bfdev->info.irq = 0; + bfdev->info.num_irq = 0; + bfdev->mode = BF_INTR_MODE_NONE; + break; + + default: + dev_err(&pdev->dev, "invalid IRQ mode %u", bf_intr_mode_default); + err = -EINVAL; + goto fail_clear_pci_master; + } + + pci_set_drvdata(pdev, bfdev); + sprintf(bfdev->name, "bf_%d", bfdev->info.minor); + /* register bf driver */ + err = bf_register_device(&pdev->dev, bfdev); + if (err != 0) + goto fail_release_irq; + + bf_global[bfdev->info.minor].async_queue = NULL; + bf_global[bfdev->info.minor].bfdev = bfdev; + + dev_info(&pdev->dev, "bf device %d registered with irq %ld\n", + bfdev->instance, bfdev->info.irq); + printk(KERN_ALERT "bf probe ok\n"); + return 0; + +fail_release_irq: + pci_set_drvdata(pdev, NULL); + if (bfdev->mode == BF_INTR_MODE_MSIX) { + pci_disable_msix(bfdev->pdev); + kfree(bfdev->info.msix_entries); + bfdev->info.msix_entries = NULL; + } + else if (bfdev->mode == BF_INTR_MODE_MSI) + pci_disable_msi(bfdev->pdev); +fail_clear_pci_master: + pci_clear_master(pdev); +fail_release_iomem: + bf_pci_release_iomem(&bfdev->info); + pci_release_regions(pdev); +fail_pci_disable: + pci_disable_device(pdev); +fail_free: + kfree(bfdev); + + printk(KERN_ERR "bf probe not ok\n"); + return err; +} + +static void +bf_pci_remove(struct pci_dev *pdev) +{ + struct bf_pci_dev *bfdev = pci_get_drvdata(pdev); + struct bf_listener *cur_listener; + + bf_unregister_device(bfdev); + if (bfdev->mode == BF_INTR_MODE_MSIX) { + pci_disable_msix(pdev); + kfree(bfdev->info.msix_entries); + bfdev->info.msix_entries = NULL; + } + else if (bfdev->mode == BF_INTR_MODE_MSI) + pci_disable_msi(pdev); + pci_clear_master(pdev); + bf_pci_release_iomem(&bfdev->info); + pci_release_regions(pdev); + pci_disable_pcie_error_reporting(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + bf_global[bfdev->info.minor].bfdev = NULL; + /* existing filep structures in open file(s) must be informed that + * bf_pci_dev is no longer valid */ + spin_lock(&bf_nonisr_lock); + cur_listener = bfdev->listener_head; + while (cur_listener) { + cur_listener->bfdev = NULL; + cur_listener = cur_listener->next; + } + spin_unlock(&bf_nonisr_lock); + kfree(bfdev); +} + +/** + * bf_pci_error_detected - called when PCI error is detected + * @pdev: Pointer to PCI device + * @state: The current pci connection state + * + * called when root complex detects pci error associated with the device + */ +static pci_ers_result_t bf_pci_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct bf_pci_dev *bfdev = pci_get_drvdata(pdev); + int minor; + + if (!bfdev) { + return PCI_ERS_RESULT_NONE; + } + printk(KERN_ERR "pci_err_detected state %d\n", state); + if (state == pci_channel_io_perm_failure || state == pci_channel_io_frozen) { + bfdev->info.pci_error_state = 1; + /* send a signal to the user space program of the error */ + minor = bfdev->info.minor; + if (minor < BF_MAX_DEVICE_CNT && bf_global[minor].async_queue) { + kill_fasync(&bf_global[minor].async_queue, SIGIO, POLL_ERR); + } + return PCI_ERS_RESULT_DISCONNECT; + } else { + return PCI_ERS_RESULT_NONE; + } +} + +/** + * bf_pci_slot_reset - called after the pci bus has been reset. + * @pdev: Pointer to PCI device + * + * Restart the card from scratch, as if from a cold-boot. + */ +static pci_ers_result_t bf_pci_slot_reset(struct pci_dev *pdev) +{ + /* nothing to do for now as we do not expect to get backto normal after + * a pcie link reset + * TBD: fill in this function if tofino can recover after an error + */ + return PCI_ERS_RESULT_DISCONNECT; +} + +/** + * bf_pci_resume - called when kernel thinks the device is up on PCIe. + * @pdev: Pointer to PCI device + * + * This callback is called when the error recovery driver tells us that + * its OK to resume normal operation. + */ +static void bf_pci_resume(struct pci_dev *pdev) +{ + /* this function should never be called for Tofinoi */ + struct bf_pci_dev *bfdev = pci_get_drvdata(pdev); + + printk(KERN_ERR "BF io_resume invoked after pci error\n"); + if (bfdev) { + bfdev->info.pci_error_state = 0; + } +} + +static int +bf_config_intr_mode(char *intr_str) +{ + if (!intr_str) { + pr_info("Use MSIX interrupt by default\n"); + return 0; + } + + if (!strcmp(intr_str, BF_INTR_MODE_MSIX_NAME)) { + bf_intr_mode_default = BF_INTR_MODE_MSIX; + pr_info("Use MSIX interrupt\n"); + } else if (!strcmp(intr_str, BF_INTR_MODE_MSI_NAME)) { + bf_intr_mode_default = BF_INTR_MODE_MSI; + pr_info("Use MSI interrupt\n"); + } else if (!strcmp(intr_str, BF_INTR_MODE_LEGACY_NAME)) { + bf_intr_mode_default = BF_INTR_MODE_LEGACY; + pr_info("Use legacy interrupt\n"); + } else { + pr_info("Error: bad parameter - %s\n", intr_str); + return -EINVAL; + } + + return 0; +} + +static const struct pci_device_id bf_pci_tbl[] = { + {PCI_VDEVICE(BF, TOFINO_DEV_ID_A0), 0}, + {PCI_VDEVICE(BF, TOFINO_DEV_ID_B0), 0}, + /* required last entry */ + { .device = 0 } +}; + +/* PCI bus error handlers */ +static struct pci_error_handlers bf_pci_err_handler = { + .error_detected = bf_pci_error_detected, + .slot_reset = bf_pci_slot_reset, + .resume = bf_pci_resume, +}; + +static struct pci_driver bf_pci_driver = { + .name = "bf", + .id_table = bf_pci_tbl, + .probe = bf_pci_probe, + .remove = bf_pci_remove, + .err_handler = &bf_pci_err_handler +}; + +static int __init +bfdrv_init(void) +{ + int ret; + + ret = bf_config_intr_mode(intr_mode); + if (ret < 0) + return ret; + + spin_lock_init(&bf_nonisr_lock); + return pci_register_driver(&bf_pci_driver); +} + +static void __exit +bfdrv_exit(void) +{ + pci_unregister_driver(&bf_pci_driver); +} + +module_init(bfdrv_init); +module_exit(bfdrv_exit); + +module_param(intr_mode, charp, S_IRUGO); +MODULE_PARM_DESC(intr_mode, +"bf interrupt mode (default=msix):\n" +" " BF_INTR_MODE_MSIX_NAME " Use MSIX interrupt\n" +" " BF_INTR_MODE_MSI_NAME " Use MSI interrupt\n" +" " BF_INTR_MODE_LEGACY_NAME " Use Legacy interrupt\n" +"\n"); + +MODULE_DEVICE_TABLE(pci, bf_pci_tbl); +MODULE_DESCRIPTION("Barefoot Tofino PCI device"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Barefoot Networks"); diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/bf_tun.c b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/bf_tun.c new file mode 100644 index 000000000000..a1ba7047baaa --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/bf_tun.c @@ -0,0 +1,2396 @@ +/* + * TUN - Universal TUN/TAP device driver. + * Copyright (C) 1999-2002 Maxim Krasnyansky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * $Id: tun.c,v 1.15 2002/03/01 02:44:24 maxk Exp $ + */ + +/* + * Changes: + * + * Mike Kershaw 2005/08/14 + * Add TUNSETLINK ioctl to set the link encapsulation + * + * Mark Smith + * Use eth_random_addr() for tap MAC address. + * + * Harald Roelle 2004/04/20 + * Fixes in packet dropping, queue length setting and queue wakeup. + * Increased default tx queue length. + * Added ethtool API. + * Minor cleanups + * + * Daniel Podlejski + * Modifications for 2.3.99-pre5 kernel. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#define DRV_NAME "bf_tun" +#define DRV_VERSION "1.6" +#define DRV_DESCRIPTION "Universal TUN/TAP device driver" +#define DRV_COPYRIGHT "(C) 1999-2004 Max Krasnyansky " + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Uncomment to enable debugging */ +/* #define TUN_DEBUG 1 */ + +#define TUN_MINOR1 201 + +#ifdef TUN_DEBUG +static int debug; + +#define tun_debug(level, tun, fmt, args...) \ +do { \ + if (tun->debug) \ + netdev_printk(level, tun->dev, fmt, ##args); \ +} while (0) +#define DBG1(level, fmt, args...) \ +do { \ + if (debug == 2) \ + printk(level fmt, ##args); \ +} while (0) +#else +#define tun_debug(level, tun, fmt, args...) \ +do { \ + if (0) \ + netdev_printk(level, tun->dev, fmt, ##args); \ +} while (0) +#define DBG1(level, fmt, args...) \ +do { \ + if (0) \ + printk(level fmt, ##args); \ +} while (0) +#endif + +#define GOODCOPY_LEN 128 + +#define FLT_EXACT_COUNT 8 +struct tap_filter { + unsigned int count; /* Number of addrs. Zero means disabled */ + u32 mask[2]; /* Mask of the hashed addrs */ + unsigned char addr[FLT_EXACT_COUNT][ETH_ALEN]; +}; + +/* DEFAULT_MAX_NUM_RSS_QUEUES were chosen to let the rx/tx queues allocated for + * the netdevice to be fit in one page. So we can make sure the success of + * memory allocation. TODO: increase the limit. */ +#define MAX_TAP_QUEUES DEFAULT_MAX_NUM_RSS_QUEUES +#define MAX_TAP_FLOWS 4096 + +#define TUN_FLOW_EXPIRE (3 * HZ) + +/* A tun_file connects an open character device to a tuntap netdevice. It + * also contains all socket related structures (except sock_fprog and tap_filter) + * to serve as one transmit queue for tuntap device. The sock_fprog and + * tap_filter were kept in tun_struct since they were used for filtering for the + * netdevice not for a specific queue (at least I didn't see the requirement for + * this). + * + * RCU usage: + * The tun_file and tun_struct are loosely coupled, the pointer from one to the + * other can only be read while rcu_read_lock or rtnl_lock is held. + */ +struct tun_file { + struct sock sk; + struct socket socket; + struct socket_wq wq; + struct tun_struct __rcu *tun; + struct net *net; + struct fasync_struct *fasync; + /* only used for fasnyc */ + unsigned int flags; + union { + u16 queue_index; + unsigned int ifindex; + }; + struct list_head next; + struct tun_struct *detached; +}; + +struct tun_flow_entry { + struct hlist_node hash_link; + struct rcu_head rcu; + struct tun_struct *tun; + + u32 rxhash; + u32 rps_rxhash; + int queue_index; + unsigned long updated; +}; + +#define TUN_NUM_FLOW_ENTRIES 1024 + +/* Since the socket were moved to tun_file, to preserve the behavior of persist + * device, socket filter, sndbuf and vnet header size were restore when the + * file were attached to a persist device. + */ +struct tun_struct { + struct tun_file __rcu *tfiles[MAX_TAP_QUEUES]; + unsigned int numqueues; + unsigned int flags; + kuid_t owner; + kgid_t group; + + struct net_device *dev; + netdev_features_t set_features; +#define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ + NETIF_F_TSO6|NETIF_F_UFO) + + int vnet_hdr_sz; + int sndbuf; + struct tap_filter txflt; + struct sock_fprog fprog; + /* protected by rtnl lock */ + bool filter_attached; +#ifdef TUN_DEBUG + int debug; +#endif + spinlock_t lock; + struct hlist_head flows[TUN_NUM_FLOW_ENTRIES]; + struct timer_list flow_gc_timer; + unsigned long ageing_time; + unsigned int numdisabled; + struct list_head disabled; + void *security; + u32 flow_count; +}; + +static inline u32 tun_hashfn(u32 rxhash) +{ + return rxhash & 0x3ff; +} + +static struct tun_flow_entry *tun_flow_find(struct hlist_head *head, u32 rxhash) +{ + struct tun_flow_entry *e; + + hlist_for_each_entry_rcu(e, head, hash_link) { + if (e->rxhash == rxhash) + return e; + } + return NULL; +} + +static struct tun_flow_entry *tun_flow_create(struct tun_struct *tun, + struct hlist_head *head, + u32 rxhash, u16 queue_index) +{ + struct tun_flow_entry *e = kmalloc(sizeof(*e), GFP_ATOMIC); + + if (e) { + tun_debug(KERN_INFO, tun, "create flow: hash %u index %u\n", + rxhash, queue_index); + e->updated = jiffies; + e->rxhash = rxhash; + e->rps_rxhash = 0; + e->queue_index = queue_index; + e->tun = tun; + hlist_add_head_rcu(&e->hash_link, head); + ++tun->flow_count; + } + return e; +} + +static void tun_flow_delete(struct tun_struct *tun, struct tun_flow_entry *e) +{ + tun_debug(KERN_INFO, tun, "delete flow: hash %u index %u\n", + e->rxhash, e->queue_index); + sock_rps_reset_flow_hash(e->rps_rxhash); + hlist_del_rcu(&e->hash_link); + kfree_rcu(e, rcu); + --tun->flow_count; +} + +static void tun_flow_flush(struct tun_struct *tun) +{ + int i; + + spin_lock_bh(&tun->lock); + for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) { + struct tun_flow_entry *e; + struct hlist_node *n; + + hlist_for_each_entry_safe(e, n, &tun->flows[i], hash_link) + tun_flow_delete(tun, e); + } + spin_unlock_bh(&tun->lock); +} + +static void tun_flow_delete_by_queue(struct tun_struct *tun, u16 queue_index) +{ + int i; + + spin_lock_bh(&tun->lock); + for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) { + struct tun_flow_entry *e; + struct hlist_node *n; + + hlist_for_each_entry_safe(e, n, &tun->flows[i], hash_link) { + if (e->queue_index == queue_index) + tun_flow_delete(tun, e); + } + } + spin_unlock_bh(&tun->lock); +} + +static void tun_flow_cleanup(unsigned long data) +{ + struct tun_struct *tun = (struct tun_struct *)data; + unsigned long delay = tun->ageing_time; + unsigned long next_timer = jiffies + delay; + unsigned long count = 0; + int i; + + tun_debug(KERN_INFO, tun, "tun_flow_cleanup\n"); + + spin_lock_bh(&tun->lock); + for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) { + struct tun_flow_entry *e; + struct hlist_node *n; + + hlist_for_each_entry_safe(e, n, &tun->flows[i], hash_link) { + unsigned long this_timer; + count++; + this_timer = e->updated + delay; + if (time_before_eq(this_timer, jiffies)) + tun_flow_delete(tun, e); + else if (time_before(this_timer, next_timer)) + next_timer = this_timer; + } + } + + if (count) + mod_timer(&tun->flow_gc_timer, round_jiffies_up(next_timer)); + spin_unlock_bh(&tun->lock); +} + +static void tun_flow_update(struct tun_struct *tun, u32 rxhash, + struct tun_file *tfile) +{ + struct hlist_head *head; + struct tun_flow_entry *e; + unsigned long delay = tun->ageing_time; + u16 queue_index = tfile->queue_index; + + if (!rxhash) + return; + else + head = &tun->flows[tun_hashfn(rxhash)]; + + rcu_read_lock(); + + /* We may get a very small possibility of OOO during switching, not + * worth to optimize.*/ + if (tun->numqueues == 1 || tfile->detached) + goto unlock; + + e = tun_flow_find(head, rxhash); + if (likely(e)) { + /* TODO: keep queueing to old queue until it's empty? */ + e->queue_index = queue_index; + e->updated = jiffies; + sock_rps_record_flow_hash(e->rps_rxhash); + } else { + spin_lock_bh(&tun->lock); + if (!tun_flow_find(head, rxhash) && + tun->flow_count < MAX_TAP_FLOWS) + tun_flow_create(tun, head, rxhash, queue_index); + + if (!timer_pending(&tun->flow_gc_timer)) + mod_timer(&tun->flow_gc_timer, + round_jiffies_up(jiffies + delay)); + spin_unlock_bh(&tun->lock); + } + +unlock: + rcu_read_unlock(); +} + +/** + * Save the hash received in the stack receive path and update the + * flow_hash table accordingly. + */ +static inline void tun_flow_save_rps_rxhash(struct tun_flow_entry *e, u32 hash) +{ + if (unlikely(e->rps_rxhash != hash)) { + sock_rps_reset_flow_hash(e->rps_rxhash); + e->rps_rxhash = hash; + } +} + +/* We try to identify a flow through its rxhash first. The reason that + * we do not check rxq no. is because some cards(e.g 82599), chooses + * the rxq based on the txq where the last packet of the flow comes. As + * the userspace application move between processors, we may get a + * different rxq no. here. If we could not get rxhash, then we would + * hope the rxq no. may help here. + */ +static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback) +{ + struct tun_struct *tun = netdev_priv(dev); + struct tun_flow_entry *e; + u32 txq = 0; + u32 numqueues = 0; + + rcu_read_lock(); + numqueues = ACCESS_ONCE(tun->numqueues); + + txq = skb_get_hash(skb); + if (txq) { + e = tun_flow_find(&tun->flows[tun_hashfn(txq)], txq); + if (e) { + tun_flow_save_rps_rxhash(e, txq); + txq = e->queue_index; + } else + /* use multiply and shift instead of expensive divide */ + txq = ((u64)txq * numqueues) >> 32; + } else if (likely(skb_rx_queue_recorded(skb))) { + txq = skb_get_rx_queue(skb); + while (unlikely(txq >= numqueues)) + txq -= numqueues; + } + + rcu_read_unlock(); + return txq; +} + +static inline bool tun_not_capable(struct tun_struct *tun) +{ + const struct cred *cred = current_cred(); + struct net *net = dev_net(tun->dev); + + return ((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) || + (gid_valid(tun->group) && !in_egroup_p(tun->group))) && + !ns_capable(net->user_ns, CAP_NET_ADMIN); +} + +static void tun_set_real_num_queues(struct tun_struct *tun) +{ + netif_set_real_num_tx_queues(tun->dev, tun->numqueues); + netif_set_real_num_rx_queues(tun->dev, tun->numqueues); +} + +static void tun_disable_queue(struct tun_struct *tun, struct tun_file *tfile) +{ + tfile->detached = tun; + list_add_tail(&tfile->next, &tun->disabled); + ++tun->numdisabled; +} + +static struct tun_struct *tun_enable_queue(struct tun_file *tfile) +{ + struct tun_struct *tun = tfile->detached; + + tfile->detached = NULL; + list_del_init(&tfile->next); + --tun->numdisabled; + return tun; +} + +static void tun_queue_purge(struct tun_file *tfile) +{ + skb_queue_purge(&tfile->sk.sk_receive_queue); + skb_queue_purge(&tfile->sk.sk_error_queue); +} + +static void __tun_detach(struct tun_file *tfile, bool clean) +{ + struct tun_file *ntfile; + struct tun_struct *tun; + + tun = rtnl_dereference(tfile->tun); + + if (tun && !tfile->detached) { + u16 index = tfile->queue_index; + BUG_ON(index >= tun->numqueues); + + rcu_assign_pointer(tun->tfiles[index], + tun->tfiles[tun->numqueues - 1]); + ntfile = rtnl_dereference(tun->tfiles[index]); + ntfile->queue_index = index; + + --tun->numqueues; + if (clean) { + RCU_INIT_POINTER(tfile->tun, NULL); + sock_put(&tfile->sk); + } else + tun_disable_queue(tun, tfile); + + synchronize_net(); + tun_flow_delete_by_queue(tun, tun->numqueues + 1); + /* Drop read queue */ + tun_queue_purge(tfile); + tun_set_real_num_queues(tun); + } else if (tfile->detached && clean) { + tun = tun_enable_queue(tfile); + sock_put(&tfile->sk); + } + + if (clean) { + if (tun && tun->numqueues == 0 && tun->numdisabled == 0) { + netif_carrier_off(tun->dev); + + if (!(tun->flags & TUN_PERSIST) && + tun->dev->reg_state == NETREG_REGISTERED) + unregister_netdevice(tun->dev); + } + + BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED, + &tfile->socket.flags)); + sk_release_kernel(&tfile->sk); + } +} + +static void tun_detach(struct tun_file *tfile, bool clean) +{ + rtnl_lock(); + __tun_detach(tfile, clean); + rtnl_unlock(); +} + +static void tun_detach_all(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + struct tun_file *tfile, *tmp; + int i, n = tun->numqueues; + + for (i = 0; i < n; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + BUG_ON(!tfile); + tfile->socket.sk->sk_data_ready(tfile->socket.sk); + RCU_INIT_POINTER(tfile->tun, NULL); + --tun->numqueues; + } + list_for_each_entry(tfile, &tun->disabled, next) { + tfile->socket.sk->sk_data_ready(tfile->socket.sk); + RCU_INIT_POINTER(tfile->tun, NULL); + } + BUG_ON(tun->numqueues != 0); + + synchronize_net(); + for (i = 0; i < n; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + /* Drop read queue */ + tun_queue_purge(tfile); + sock_put(&tfile->sk); + } + list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) { + tun_enable_queue(tfile); + tun_queue_purge(tfile); + sock_put(&tfile->sk); + } + BUG_ON(tun->numdisabled != 0); + + if (tun->flags & TUN_PERSIST) + module_put(THIS_MODULE); +} + +static int tun_attach(struct tun_struct *tun, struct file *file, bool skip_filter) +{ + struct tun_file *tfile = file->private_data; + int err; + + err = security_tun_dev_attach(tfile->socket.sk, tun->security); + if (err < 0) + goto out; + + err = -EINVAL; + if (rtnl_dereference(tfile->tun) && !tfile->detached) + goto out; + + err = -EBUSY; + if (!(tun->flags & TUN_TAP_MQ) && tun->numqueues == 1) + goto out; + + err = -E2BIG; + if (!tfile->detached && + tun->numqueues + tun->numdisabled == MAX_TAP_QUEUES) + goto out; + + err = 0; + + /* Re-attach the filter to persist device */ + if (!skip_filter && (tun->filter_attached == true)) { + err = __sk_attach_filter(&tun->fprog, tfile->socket.sk, + lockdep_rtnl_is_held()); + if (!err) + goto out; + } + tfile->queue_index = tun->numqueues; + rcu_assign_pointer(tfile->tun, tun); + rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile); + tun->numqueues++; + + if (tfile->detached) + tun_enable_queue(tfile); + else + sock_hold(&tfile->sk); + + tun_set_real_num_queues(tun); + + /* device is allowed to go away first, so no need to hold extra + * refcnt. + */ + +out: + return err; +} + +static struct tun_struct *__tun_get(struct tun_file *tfile) +{ + struct tun_struct *tun; + + rcu_read_lock(); + tun = rcu_dereference(tfile->tun); + if (tun) + dev_hold(tun->dev); + rcu_read_unlock(); + + return tun; +} + +static struct tun_struct *tun_get(struct file *file) +{ + return __tun_get(file->private_data); +} + +static void tun_put(struct tun_struct *tun) +{ + dev_put(tun->dev); +} + +/* TAP filtering */ +static void addr_hash_set(u32 *mask, const u8 *addr) +{ + int n = ether_crc(ETH_ALEN, addr) >> 26; + mask[n >> 5] |= (1 << (n & 31)); +} + +static unsigned int addr_hash_test(const u32 *mask, const u8 *addr) +{ + int n = ether_crc(ETH_ALEN, addr) >> 26; + return mask[n >> 5] & (1 << (n & 31)); +} + +static int update_filter(struct tap_filter *filter, void __user *arg) +{ + struct { u8 u[ETH_ALEN]; } *addr; + struct tun_filter uf; + int err, alen, n, nexact; + + if (copy_from_user(&uf, arg, sizeof(uf))) + return -EFAULT; + + if (!uf.count) { + /* Disabled */ + filter->count = 0; + return 0; + } + + alen = ETH_ALEN * uf.count; + addr = kmalloc(alen, GFP_KERNEL); + if (!addr) + return -ENOMEM; + + if (copy_from_user(addr, arg + sizeof(uf), alen)) { + err = -EFAULT; + goto done; + } + + /* The filter is updated without holding any locks. Which is + * perfectly safe. We disable it first and in the worst + * case we'll accept a few undesired packets. */ + filter->count = 0; + wmb(); + + /* Use first set of addresses as an exact filter */ + for (n = 0; n < uf.count && n < FLT_EXACT_COUNT; n++) + memcpy(filter->addr[n], addr[n].u, ETH_ALEN); + + nexact = n; + + /* Remaining multicast addresses are hashed, + * unicast will leave the filter disabled. */ + memset(filter->mask, 0, sizeof(filter->mask)); + for (; n < uf.count; n++) { + if (!is_multicast_ether_addr(addr[n].u)) { + err = 0; /* no filter */ + goto done; + } + addr_hash_set(filter->mask, addr[n].u); + } + + /* For ALLMULTI just set the mask to all ones. + * This overrides the mask populated above. */ + if ((uf.flags & TUN_FLT_ALLMULTI)) + memset(filter->mask, ~0, sizeof(filter->mask)); + + /* Now enable the filter */ + wmb(); + filter->count = nexact; + + /* Return the number of exact filters */ + err = nexact; + +done: + kfree(addr); + return err; +} + +/* Returns: 0 - drop, !=0 - accept */ +static int run_filter(struct tap_filter *filter, const struct sk_buff *skb) +{ + /* Cannot use eth_hdr(skb) here because skb_mac_hdr() is incorrect + * at this point. */ + struct ethhdr *eh = (struct ethhdr *) skb->data; + int i; + + /* Exact match */ + for (i = 0; i < filter->count; i++) + if (ether_addr_equal(eh->h_dest, filter->addr[i])) + return 1; + + /* Inexact match (multicast only) */ + if (is_multicast_ether_addr(eh->h_dest)) + return addr_hash_test(filter->mask, eh->h_dest); + + return 0; +} + +/* + * Checks whether the packet is accepted or not. + * Returns: 0 - drop, !=0 - accept + */ +static int check_filter(struct tap_filter *filter, const struct sk_buff *skb) +{ + if (!filter->count) + return 1; + + return run_filter(filter, skb); +} + +/* Network device part of the driver */ + +static const struct ethtool_ops tun_ethtool_ops; + +/* Net device detach from fd. */ +static void tun_net_uninit(struct net_device *dev) +{ + tun_detach_all(dev); +} + +/* Net device open. */ +static int tun_net_open(struct net_device *dev) +{ + netif_tx_start_all_queues(dev); + return 0; +} + +/* Net device close. */ +static int tun_net_close(struct net_device *dev) +{ + netif_tx_stop_all_queues(dev); + return 0; +} + +/* Net device start xmit */ +static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + int txq = skb->queue_mapping; + struct tun_file *tfile; + u32 numqueues = 0; + + rcu_read_lock(); + tfile = rcu_dereference(tun->tfiles[txq]); + numqueues = ACCESS_ONCE(tun->numqueues); + + /* Drop packet if interface is not attached */ + if (txq >= numqueues) + goto drop; + + if (numqueues == 1) { + /* Select queue was not called for the skbuff, so we extract the + * RPS hash and save it into the flow_table here. + */ + __u32 rxhash; + + rxhash = skb_get_hash(skb); + if (rxhash) { + struct tun_flow_entry *e; + e = tun_flow_find(&tun->flows[tun_hashfn(rxhash)], + rxhash); + if (e) + tun_flow_save_rps_rxhash(e, rxhash); + } + } + + tun_debug(KERN_INFO, tun, "tun_net_xmit %d\n", skb->len); + + BUG_ON(!tfile); + + /* Drop if the filter does not like it. + * This is a noop if the filter is disabled. + * Filter can be enabled only for the TAP devices. */ + if (!check_filter(&tun->txflt, skb)) + goto drop; + + if (tfile->socket.sk->sk_filter && + sk_filter(tfile->socket.sk, skb)) + goto drop; + + /* Limit the number of packets queued by dividing txq length with the + * number of queues. + */ + if (skb_queue_len(&tfile->socket.sk->sk_receive_queue) * numqueues + >= dev->tx_queue_len) + goto drop; + + if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC))) + goto drop; + + if (skb->sk) { + sock_tx_timestamp(skb->sk, &skb_shinfo(skb)->tx_flags); + sw_tx_timestamp(skb); + } + + /* Orphan the skb - required as we might hang on to it + * for indefinite time. + */ + skb_orphan(skb); + + nf_reset(skb); + + /* Enqueue packet */ + skb_queue_tail(&tfile->socket.sk->sk_receive_queue, skb); + + /* Notify and wake up reader process */ + if (tfile->flags & TUN_FASYNC) + kill_fasync(&tfile->fasync, SIGIO, POLL_IN); + tfile->socket.sk->sk_data_ready(tfile->socket.sk); + + rcu_read_unlock(); + return NETDEV_TX_OK; + +drop: + dev->stats.tx_dropped++; + skb_tx_error(skb); + kfree_skb(skb); + rcu_read_unlock(); + return NETDEV_TX_OK; +} + +static void tun_net_mclist(struct net_device *dev) +{ + /* + * This callback is supposed to deal with mc filter in + * _rx_ path and has nothing to do with the _tx_ path. + * In rx path we always accept everything userspace gives us. + */ +} + +#define MIN_MTU 68 +#define MAX_MTU 65535 + +static int +tun_net_change_mtu(struct net_device *dev, int new_mtu) +{ + if (new_mtu < MIN_MTU || new_mtu + dev->hard_header_len > MAX_MTU) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + +static netdev_features_t tun_net_fix_features(struct net_device *dev, + netdev_features_t features) +{ + struct tun_struct *tun = netdev_priv(dev); + + return (features & tun->set_features) | (features & ~TUN_USER_FEATURES); +} + +static int +tun_change_carrier(struct net_device *dev, bool new_carrier) { + if (new_carrier) + netif_carrier_on(dev); + else + netif_carrier_off(dev); + return 0; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void tun_poll_controller(struct net_device *dev) +{ + /* + * Tun only receives frames when: + * 1) the char device endpoint gets data from user space + * 2) the tun socket gets a sendmsg call from user space + * Since both of those are synchronous operations, we are guaranteed + * never to have pending data when we poll for it + * so there is nothing to do here but return. + * We need this though so netpoll recognizes us as an interface that + * supports polling, which enables bridge devices in virt setups to + * still use netconsole + */ + return; +} +#endif +static const struct net_device_ops tun_netdev_ops = { + .ndo_uninit = tun_net_uninit, + .ndo_open = tun_net_open, + .ndo_stop = tun_net_close, + .ndo_start_xmit = tun_net_xmit, + .ndo_change_mtu = tun_net_change_mtu, + .ndo_fix_features = tun_net_fix_features, + .ndo_select_queue = tun_select_queue, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = tun_poll_controller, +#endif +}; + +static const struct net_device_ops tap_netdev_ops = { + .ndo_uninit = tun_net_uninit, + .ndo_open = tun_net_open, + .ndo_stop = tun_net_close, + .ndo_start_xmit = tun_net_xmit, + .ndo_change_mtu = tun_net_change_mtu, + .ndo_fix_features = tun_net_fix_features, + .ndo_set_rx_mode = tun_net_mclist, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_select_queue = tun_select_queue, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = tun_poll_controller, +#endif + .ndo_change_carrier = tun_change_carrier, +}; + +static void tun_flow_init(struct tun_struct *tun) +{ + int i; + + for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) + INIT_HLIST_HEAD(&tun->flows[i]); + + tun->ageing_time = TUN_FLOW_EXPIRE; + setup_timer(&tun->flow_gc_timer, tun_flow_cleanup, (unsigned long)tun); + mod_timer(&tun->flow_gc_timer, + round_jiffies_up(jiffies + tun->ageing_time)); +} + +static void tun_flow_uninit(struct tun_struct *tun) +{ + del_timer_sync(&tun->flow_gc_timer); + tun_flow_flush(tun); +} + +/* Initialize net device. */ +static void tun_net_init(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + + switch (tun->flags & TUN_TYPE_MASK) { + case TUN_TUN_DEV: + dev->netdev_ops = &tun_netdev_ops; + + /* Point-to-Point TUN Device */ + dev->hard_header_len = 0; + dev->addr_len = 0; + dev->mtu = 1500; + + /* Zero header length */ + dev->type = ARPHRD_NONE; + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + dev->tx_queue_len = TUN_READQ_SIZE*2; /* We prefer our own queue length */ + break; + + case TUN_TAP_DEV: + dev->netdev_ops = &tap_netdev_ops; + /* Ethernet TAP Device */ + ether_setup(dev); + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + + eth_hw_addr_random(dev); + + dev->tx_queue_len = TUN_READQ_SIZE*2; /* We prefer our own queue length */ + break; + } +} + +/* Character device part */ + +/* Poll */ +static unsigned int tun_chr_poll(struct file *file, poll_table *wait) +{ + struct tun_file *tfile = file->private_data; + struct tun_struct *tun = __tun_get(tfile); + struct sock *sk; + unsigned int mask = 0; + + if (!tun) + return POLLERR; + + sk = tfile->socket.sk; + + tun_debug(KERN_INFO, tun, "tun_chr_poll\n"); + + poll_wait(file, sk_sleep(sk), wait); + + if (!skb_queue_empty(&sk->sk_receive_queue)) + mask |= POLLIN | POLLRDNORM; + + if (sock_writeable(sk) || + (!test_and_set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags) && + sock_writeable(sk))) + mask |= POLLOUT | POLLWRNORM; + + if (tun->dev->reg_state != NETREG_REGISTERED) + mask = POLLERR; + + tun_put(tun); + return mask; +} + +/* prepad is the amount to reserve at front. len is length after that. + * linear is a hint as to how much to copy (usually headers). */ +static struct sk_buff *tun_alloc_skb(struct tun_file *tfile, + size_t prepad, size_t len, + size_t linear, int noblock) +{ + struct sock *sk = tfile->socket.sk; + struct sk_buff *skb; + int err; + + /* Under a page? Don't bother with paged skb. */ + if (prepad + len < PAGE_SIZE || !linear) + linear = len; + + skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock, + &err, 0); + if (!skb) + return ERR_PTR(err); + + skb_reserve(skb, prepad); + skb_put(skb, linear); + skb->data_len = len - linear; + skb->len += len - linear; + + return skb; +} + +/* Get packet from user space buffer */ +static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, + void *msg_control, const struct iovec *iv, + size_t total_len, size_t count, int noblock) +{ + struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; + struct sk_buff *skb; + size_t len = total_len, align = NET_SKB_PAD, linear; + struct virtio_net_hdr gso = { 0 }; + int good_linear; + int offset = 0; + int copylen; + bool zerocopy = false; + int err; + u32 rxhash; + + if (!(tun->flags & TUN_NO_PI)) { + if (len < sizeof(pi)) + return -EINVAL; + len -= sizeof(pi); + + if (memcpy_fromiovecend((void *)&pi, iv, 0, sizeof(pi))) + return -EFAULT; + offset += sizeof(pi); + } + + if (tun->flags & TUN_VNET_HDR) { + if (len < tun->vnet_hdr_sz) + return -EINVAL; + len -= tun->vnet_hdr_sz; + + if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso))) + return -EFAULT; + + if ((gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && + gso.csum_start + gso.csum_offset + 2 > gso.hdr_len) + gso.hdr_len = gso.csum_start + gso.csum_offset + 2; + + if (gso.hdr_len > len) + return -EINVAL; + offset += tun->vnet_hdr_sz; + } + + if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { + align += NET_IP_ALIGN; + if (unlikely(len < ETH_HLEN || + (gso.hdr_len && gso.hdr_len < ETH_HLEN))) + return -EINVAL; + } + + good_linear = SKB_MAX_HEAD(align); + + if (msg_control) { + /* There are 256 bytes to be copied in skb, so there is + * enough room for skb expand head in case it is used. + * The rest of the buffer is mapped from userspace. + */ + copylen = gso.hdr_len ? gso.hdr_len : GOODCOPY_LEN; + if (copylen > good_linear) + copylen = good_linear; + linear = copylen; + if (iov_pages(iv, offset + copylen, count) <= MAX_SKB_FRAGS) + zerocopy = true; + } + + if (!zerocopy) { + copylen = len; + if (gso.hdr_len > good_linear) + linear = good_linear; + else + linear = gso.hdr_len; + } + + skb = tun_alloc_skb(tfile, align, copylen, linear, noblock); + if (IS_ERR(skb)) { + if (PTR_ERR(skb) != -EAGAIN) + tun->dev->stats.rx_dropped++; + return PTR_ERR(skb); + } + + if (zerocopy) + err = zerocopy_sg_from_iovec(skb, iv, offset, count); + else { + err = skb_copy_datagram_from_iovec(skb, 0, iv, offset, len); + if (!err && msg_control) { + struct ubuf_info *uarg = msg_control; + uarg->callback(uarg, false); + } + } + + if (err) { + tun->dev->stats.rx_dropped++; + kfree_skb(skb); + return -EFAULT; + } + + if (gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { + if (!skb_partial_csum_set(skb, gso.csum_start, + gso.csum_offset)) { + tun->dev->stats.rx_frame_errors++; + kfree_skb(skb); + return -EINVAL; + } + } + + switch (tun->flags & TUN_TYPE_MASK) { + case TUN_TUN_DEV: + if (tun->flags & TUN_NO_PI) { + switch (skb->data[0] & 0xf0) { + case 0x40: + pi.proto = htons(ETH_P_IP); + break; + case 0x60: + pi.proto = htons(ETH_P_IPV6); + break; + default: + tun->dev->stats.rx_dropped++; + kfree_skb(skb); + return -EINVAL; + } + } + + skb_reset_mac_header(skb); + skb->protocol = pi.proto; + skb->dev = tun->dev; + break; + case TUN_TAP_DEV: + skb->protocol = eth_type_trans(skb, tun->dev); + break; + } + + skb_reset_network_header(skb); + + if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) { + pr_debug("GSO!\n"); + switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { + case VIRTIO_NET_HDR_GSO_TCPV4: + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; + break; + case VIRTIO_NET_HDR_GSO_TCPV6: + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; + break; + case VIRTIO_NET_HDR_GSO_UDP: + skb_shinfo(skb)->gso_type = SKB_GSO_UDP; + if (skb->protocol == htons(ETH_P_IPV6)) + ipv6_proxy_select_ident(skb); + break; + default: + tun->dev->stats.rx_frame_errors++; + kfree_skb(skb); + return -EINVAL; + } + + if (gso.gso_type & VIRTIO_NET_HDR_GSO_ECN) + skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; + + skb_shinfo(skb)->gso_size = gso.gso_size; + if (skb_shinfo(skb)->gso_size == 0) { + tun->dev->stats.rx_frame_errors++; + kfree_skb(skb); + return -EINVAL; + } + + /* Header must be checked, and gso_segs computed. */ + skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; + skb_shinfo(skb)->gso_segs = 0; + } + + /* copy skb_ubuf_info for callback when skb has no error */ + if (zerocopy) { + skb_shinfo(skb)->destructor_arg = msg_control; + skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; + skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; + } + + skb_probe_transport_header(skb, 0); + + rxhash = skb_get_hash(skb); + netif_rx_ni(skb); + + tun->dev->stats.rx_packets++; + tun->dev->stats.rx_bytes += len; + + tun_flow_update(tun, rxhash, tfile); + return total_len; +} + +static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, + unsigned long count, loff_t pos) +{ + struct file *file = iocb->ki_filp; + struct tun_struct *tun = tun_get(file); + struct tun_file *tfile = file->private_data; + ssize_t result; + + if (!tun) + return -EBADFD; + + tun_debug(KERN_INFO, tun, "tun_chr_write %ld\n", count); + + result = tun_get_user(tun, tfile, NULL, iv, iov_length(iv, count), + count, file->f_flags & O_NONBLOCK); + + tun_put(tun); + return result; +} + +/* Put packet to the user space buffer */ +static ssize_t tun_put_user(struct tun_struct *tun, + struct tun_file *tfile, + struct sk_buff *skb, + const struct iovec *iv, int len) +{ + struct tun_pi pi = { 0, skb->protocol }; + ssize_t total = 0; + int vlan_offset = 0, copied; + int vlan_hlen = 0; + + if (vlan_tx_tag_present(skb)) + vlan_hlen = VLAN_HLEN; + + if (!(tun->flags & TUN_NO_PI)) { + if ((len -= sizeof(pi)) < 0) + return -EINVAL; + + if (len < skb->len) { + /* Packet will be striped */ + pi.flags |= TUN_PKT_STRIP; + } + + if (memcpy_toiovecend(iv, (void *) &pi, 0, sizeof(pi))) + return -EFAULT; + total += sizeof(pi); + } + + if (tun->flags & TUN_VNET_HDR) { + struct virtio_net_hdr gso = { 0 }; /* no info leak */ + if ((len -= tun->vnet_hdr_sz) < 0) + return -EINVAL; + + if (skb_is_gso(skb)) { + struct skb_shared_info *sinfo = skb_shinfo(skb); + + /* This is a hint as to how much should be linear. */ + gso.hdr_len = skb_headlen(skb); + gso.gso_size = sinfo->gso_size; + if (sinfo->gso_type & SKB_GSO_TCPV4) + gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; + else if (sinfo->gso_type & SKB_GSO_TCPV6) + gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; + else if (sinfo->gso_type & SKB_GSO_UDP) + gso.gso_type = VIRTIO_NET_HDR_GSO_UDP; + else { + pr_err("unexpected GSO type: " + "0x%x, gso_size %d, hdr_len %d\n", + sinfo->gso_type, gso.gso_size, + gso.hdr_len); + print_hex_dump(KERN_ERR, "tun: ", + DUMP_PREFIX_NONE, + 16, 1, skb->head, + min((int)gso.hdr_len, 64), true); + WARN_ON_ONCE(1); + return -EINVAL; + } + if (sinfo->gso_type & SKB_GSO_TCP_ECN) + gso.gso_type |= VIRTIO_NET_HDR_GSO_ECN; + } else + gso.gso_type = VIRTIO_NET_HDR_GSO_NONE; + + if (skb->ip_summed == CHECKSUM_PARTIAL) { + gso.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; + gso.csum_start = skb_checksum_start_offset(skb) + + vlan_hlen; + gso.csum_offset = skb->csum_offset; + } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + gso.flags = VIRTIO_NET_HDR_F_DATA_VALID; + } /* else everything is zero */ + + if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total, + sizeof(gso)))) + return -EFAULT; + total += tun->vnet_hdr_sz; + } + + copied = total; + len = min_t(int, skb->len + vlan_hlen, len); + total += skb->len + vlan_hlen; + if (vlan_hlen) { + int copy, ret; + struct { + __be16 h_vlan_proto; + __be16 h_vlan_TCI; + } veth; + + veth.h_vlan_proto = skb->vlan_proto; + veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb)); + + vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto); + + copy = min_t(int, vlan_offset, len); + ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy); + len -= copy; + copied += copy; + if (ret || !len) + goto done; + + copy = min_t(int, sizeof(veth), len); + ret = memcpy_toiovecend(iv, (void *)&veth, copied, copy); + len -= copy; + copied += copy; + if (ret || !len) + goto done; + } + + skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len); + +done: + tun->dev->stats.tx_packets++; + tun->dev->stats.tx_bytes += len; + + return total; +} + +static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile, + const struct iovec *iv, ssize_t len, int noblock) +{ + struct sk_buff *skb; + ssize_t ret = 0; + int peeked, err, off = 0; + + tun_debug(KERN_INFO, tun, "tun_do_read\n"); + + if (!len) + return ret; + + if (tun->dev->reg_state != NETREG_REGISTERED) + return -EIO; + + /* Read frames from queue */ + skb = __skb_recv_datagram(tfile->socket.sk, noblock ? MSG_DONTWAIT : 0, + &peeked, &off, &err); + if (skb) { + ret = tun_put_user(tun, tfile, skb, iv, len); + kfree_skb(skb); + } else + ret = err; + + return ret; +} + +static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, + unsigned long count, loff_t pos) +{ + struct file *file = iocb->ki_filp; + struct tun_file *tfile = file->private_data; + struct tun_struct *tun = __tun_get(tfile); + ssize_t len, ret; + + if (!tun) + return -EBADFD; + len = iov_length(iv, count); + if (len < 0) { + ret = -EINVAL; + goto out; + } + + ret = tun_do_read(tun, tfile, iv, len, + file->f_flags & O_NONBLOCK); + ret = min_t(ssize_t, ret, len); + if (ret > 0) + iocb->ki_pos = ret; +out: + tun_put(tun); + return ret; +} + +static void tun_free_netdev(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + + BUG_ON(!(list_empty(&tun->disabled))); + tun_flow_uninit(tun); + security_tun_dev_free_security(tun->security); + free_netdev(dev); +} + +static void tun_setup(struct net_device *dev) +{ + struct tun_struct *tun = netdev_priv(dev); + + tun->owner = INVALID_UID; + tun->group = INVALID_GID; + + dev->ethtool_ops = &tun_ethtool_ops; + dev->destructor = tun_free_netdev; +} + +/* Trivial set of netlink ops to allow deleting tun or tap + * device with netlink. + */ +static int tun_validate(struct nlattr *tb[], struct nlattr *data[]) +{ + return -EINVAL; +} + +static struct rtnl_link_ops tun_link_ops __read_mostly = { + .kind = DRV_NAME, + .priv_size = sizeof(struct tun_struct), + .setup = tun_setup, + .validate = tun_validate, +}; + +static void tun_sock_write_space(struct sock *sk) +{ + struct tun_file *tfile; + wait_queue_head_t *wqueue; + + if (!sock_writeable(sk)) + return; + + if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags)) + return; + + wqueue = sk_sleep(sk); + if (wqueue && waitqueue_active(wqueue)) + wake_up_interruptible_sync_poll(wqueue, POLLOUT | + POLLWRNORM | POLLWRBAND); + + tfile = container_of(sk, struct tun_file, sk); + kill_fasync(&tfile->fasync, SIGIO, POLL_OUT); +} + +static int tun_sendmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len) +{ + int ret; + struct tun_file *tfile = container_of(sock, struct tun_file, socket); + struct tun_struct *tun = __tun_get(tfile); + + if (!tun) + return -EBADFD; + ret = tun_get_user(tun, tfile, m->msg_control, m->msg_iov, total_len, + m->msg_iovlen, m->msg_flags & MSG_DONTWAIT); + tun_put(tun); + return ret; +} + +static int tun_recvmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len, + int flags) +{ + struct tun_file *tfile = container_of(sock, struct tun_file, socket); + struct tun_struct *tun = __tun_get(tfile); + int ret; + + if (!tun) + return -EBADFD; + + if (flags & ~(MSG_DONTWAIT|MSG_TRUNC|MSG_ERRQUEUE)) { + ret = -EINVAL; + goto out; + } + if (flags & MSG_ERRQUEUE) { + ret = sock_recv_errqueue(sock->sk, m, total_len, + SOL_PACKET, TUN_TX_TIMESTAMP); + goto out; + } + ret = tun_do_read(tun, tfile, m->msg_iov, total_len, + flags & MSG_DONTWAIT); + if (ret > total_len) { + m->msg_flags |= MSG_TRUNC; + ret = flags & MSG_TRUNC ? ret : total_len; + } +out: + tun_put(tun); + return ret; +} + +static int tun_release(struct socket *sock) +{ + if (sock->sk) + sock_put(sock->sk); + return 0; +} + +/* Ops structure to mimic raw sockets with tun */ +static const struct proto_ops tun_socket_ops = { + .sendmsg = tun_sendmsg, + .recvmsg = tun_recvmsg, + .release = tun_release, +}; + +static struct proto tun_proto = { + .name = "bf_tun", + .owner = THIS_MODULE, + .obj_size = sizeof(struct tun_file), +}; + +static int tun_flags(struct tun_struct *tun) +{ + int flags = 0; + + if (tun->flags & TUN_TUN_DEV) + flags |= IFF_TUN; + else + flags |= IFF_TAP; + + if (tun->flags & TUN_NO_PI) + flags |= IFF_NO_PI; + + /* This flag has no real effect. We track the value for backwards + * compatibility. + */ + if (tun->flags & TUN_ONE_QUEUE) + flags |= IFF_ONE_QUEUE; + + if (tun->flags & TUN_VNET_HDR) + flags |= IFF_VNET_HDR; + + if (tun->flags & TUN_TAP_MQ) + flags |= IFF_MULTI_QUEUE; + + if (tun->flags & TUN_PERSIST) + flags |= IFF_PERSIST; + + return flags; +} + +static ssize_t tun_show_flags(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return sprintf(buf, "0x%x\n", tun_flags(tun)); +} + +static ssize_t tun_show_owner(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return uid_valid(tun->owner)? + sprintf(buf, "%u\n", + from_kuid_munged(current_user_ns(), tun->owner)): + sprintf(buf, "-1\n"); +} + +static ssize_t tun_show_group(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tun_struct *tun = netdev_priv(to_net_dev(dev)); + return gid_valid(tun->group) ? + sprintf(buf, "%u\n", + from_kgid_munged(current_user_ns(), tun->group)): + sprintf(buf, "-1\n"); +} + +static DEVICE_ATTR(tun_flags, 0444, tun_show_flags, NULL); +static DEVICE_ATTR(owner, 0444, tun_show_owner, NULL); +static DEVICE_ATTR(group, 0444, tun_show_group, NULL); + +static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) +{ + struct tun_struct *tun; + struct tun_file *tfile = file->private_data; + struct net_device *dev; + int err; + + if (tfile->detached) + return -EINVAL; + + dev = __dev_get_by_name(net, ifr->ifr_name); + if (dev) { + if (ifr->ifr_flags & IFF_TUN_EXCL) + return -EBUSY; + if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops) + tun = netdev_priv(dev); + else if ((ifr->ifr_flags & IFF_TAP) && dev->netdev_ops == &tap_netdev_ops) + tun = netdev_priv(dev); + else + return -EINVAL; + + if (!!(ifr->ifr_flags & IFF_MULTI_QUEUE) != + !!(tun->flags & TUN_TAP_MQ)) + return -EINVAL; + + if (tun_not_capable(tun)) + return -EPERM; + err = security_tun_dev_open(tun->security); + if (err < 0) + return err; + + err = tun_attach(tun, file, ifr->ifr_flags & IFF_NOFILTER); + if (err < 0) + return err; + + if (tun->flags & TUN_TAP_MQ && + (tun->numqueues + tun->numdisabled > 1)) { + /* One or more queue has already been attached, no need + * to initialize the device again. + */ + return 0; + } + } + else { + char *name; + unsigned long flags = 0; + int queues = ifr->ifr_flags & IFF_MULTI_QUEUE ? + MAX_TAP_QUEUES : 1; + + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + return -EPERM; + err = security_tun_dev_create(); + if (err < 0) + return err; + + /* Set dev type */ + if (ifr->ifr_flags & IFF_TUN) { + /* TUN device */ + flags |= TUN_TUN_DEV; + name = "tun%d"; + } else if (ifr->ifr_flags & IFF_TAP) { + /* TAP device */ + flags |= TUN_TAP_DEV; + name = "tap%d"; + } else + return -EINVAL; + + if (*ifr->ifr_name) + name = ifr->ifr_name; + + dev = alloc_netdev_mqs(sizeof(struct tun_struct), name, + tun_setup, queues, queues); + + if (!dev) + return -ENOMEM; + + dev_net_set(dev, net); + dev->rtnl_link_ops = &tun_link_ops; + dev->ifindex = tfile->ifindex; + + tun = netdev_priv(dev); + tun->dev = dev; + tun->flags = flags; + tun->txflt.count = 0; + tun->vnet_hdr_sz = sizeof(struct virtio_net_hdr); + + tun->filter_attached = false; + tun->sndbuf = tfile->socket.sk->sk_sndbuf; + + spin_lock_init(&tun->lock); + + err = security_tun_dev_alloc_security(&tun->security); + if (err < 0) + goto err_free_dev; + + tun_net_init(dev); + tun_flow_init(tun); + + dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | + TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_STAG_TX; + dev->features = dev->hw_features; + dev->vlan_features = dev->features & + ~(NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_STAG_TX); + + INIT_LIST_HEAD(&tun->disabled); + err = tun_attach(tun, file, false); + if (err < 0) + goto err_free_flow; + + err = register_netdevice(tun->dev); + if (err < 0) + goto err_detach; + + if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) || + device_create_file(&tun->dev->dev, &dev_attr_owner) || + device_create_file(&tun->dev->dev, &dev_attr_group)) + pr_err("Failed to create tun sysfs files\n"); + } + + netif_carrier_on(tun->dev); + + tun_debug(KERN_INFO, tun, "tun_set_iff\n"); + + if (ifr->ifr_flags & IFF_NO_PI) + tun->flags |= TUN_NO_PI; + else + tun->flags &= ~TUN_NO_PI; + + /* This flag has no real effect. We track the value for backwards + * compatibility. + */ + if (ifr->ifr_flags & IFF_ONE_QUEUE) + tun->flags |= TUN_ONE_QUEUE; + else + tun->flags &= ~TUN_ONE_QUEUE; + + if (ifr->ifr_flags & IFF_VNET_HDR) + tun->flags |= TUN_VNET_HDR; + else + tun->flags &= ~TUN_VNET_HDR; + + if (ifr->ifr_flags & IFF_MULTI_QUEUE) + tun->flags |= TUN_TAP_MQ; + else + tun->flags &= ~TUN_TAP_MQ; + + /* Make sure persistent devices do not get stuck in + * xoff state. + */ + if (netif_running(tun->dev)) + netif_tx_wake_all_queues(tun->dev); + + strcpy(ifr->ifr_name, tun->dev->name); + return 0; + +err_detach: + tun_detach_all(dev); +err_free_flow: + tun_flow_uninit(tun); + security_tun_dev_free_security(tun->security); +err_free_dev: + free_netdev(dev); + return err; +} + +static void tun_get_iff(struct net *net, struct tun_struct *tun, + struct ifreq *ifr) +{ + tun_debug(KERN_INFO, tun, "tun_get_iff\n"); + + strcpy(ifr->ifr_name, tun->dev->name); + + ifr->ifr_flags = tun_flags(tun); + +} + +/* This is like a cut-down ethtool ops, except done via tun fd so no + * privs required. */ +static int set_offload(struct tun_struct *tun, unsigned long arg) +{ + netdev_features_t features = 0; + + if (arg & TUN_F_CSUM) { + features |= NETIF_F_HW_CSUM; + arg &= ~TUN_F_CSUM; + + if (arg & (TUN_F_TSO4|TUN_F_TSO6)) { + if (arg & TUN_F_TSO_ECN) { + features |= NETIF_F_TSO_ECN; + arg &= ~TUN_F_TSO_ECN; + } + if (arg & TUN_F_TSO4) + features |= NETIF_F_TSO; + if (arg & TUN_F_TSO6) + features |= NETIF_F_TSO6; + arg &= ~(TUN_F_TSO4|TUN_F_TSO6); + } + + if (arg & TUN_F_UFO) { + features |= NETIF_F_UFO; + arg &= ~TUN_F_UFO; + } + } + + /* This gives the user a way to test for new features in future by + * trying to set them. */ + if (arg) + return -EINVAL; + + tun->set_features = features; + netdev_update_features(tun->dev); + + return 0; +} + +static void tun_detach_filter(struct tun_struct *tun, int n) +{ + int i; + struct tun_file *tfile; + + for (i = 0; i < n; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + __sk_detach_filter(tfile->socket.sk, lockdep_rtnl_is_held()); + } + + tun->filter_attached = false; +} + +static int tun_attach_filter(struct tun_struct *tun) +{ + int i, ret = 0; + struct tun_file *tfile; + + for (i = 0; i < tun->numqueues; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + ret = __sk_attach_filter(&tun->fprog, tfile->socket.sk, + lockdep_rtnl_is_held()); + if (ret) { + tun_detach_filter(tun, i); + return ret; + } + } + + tun->filter_attached = true; + return ret; +} + +static void tun_set_sndbuf(struct tun_struct *tun) +{ + struct tun_file *tfile; + int i; + + for (i = 0; i < tun->numqueues; i++) { + tfile = rtnl_dereference(tun->tfiles[i]); + tfile->socket.sk->sk_sndbuf = tun->sndbuf; + } +} + +static int tun_set_queue(struct file *file, struct ifreq *ifr) +{ + struct tun_file *tfile = file->private_data; + struct tun_struct *tun; + int ret = 0; + + rtnl_lock(); + + if (ifr->ifr_flags & IFF_ATTACH_QUEUE) { + tun = tfile->detached; + if (!tun) { + ret = -EINVAL; + goto unlock; + } + ret = security_tun_dev_attach_queue(tun->security); + if (ret < 0) + goto unlock; + ret = tun_attach(tun, file, false); + } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) { + tun = rtnl_dereference(tfile->tun); + if (!tun || !(tun->flags & TUN_TAP_MQ) || tfile->detached) + ret = -EINVAL; + else + __tun_detach(tfile, false); + } else + ret = -EINVAL; + +unlock: + rtnl_unlock(); + return ret; +} + +static long __tun_chr_ioctl(struct file *file, unsigned int cmd, + unsigned long arg, int ifreq_len) +{ + struct tun_file *tfile = file->private_data; + struct tun_struct *tun; + void __user* argp = (void __user*)arg; + struct ifreq ifr; + kuid_t owner; + kgid_t group; + int sndbuf; + int vnet_hdr_sz; + unsigned int ifindex; + int ret; + + if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == 0x89) { + if (copy_from_user(&ifr, argp, ifreq_len)) + return -EFAULT; + } else { + memset(&ifr, 0, sizeof(ifr)); + } + if (cmd == TUNGETFEATURES) { + /* Currently this just means: "what IFF flags are valid?". + * This is needed because we never checked for invalid flags on + * TUNSETIFF. */ + return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE | + IFF_VNET_HDR | IFF_MULTI_QUEUE, + (unsigned int __user*)argp); + } else if (cmd == TUNSETQUEUE) + return tun_set_queue(file, &ifr); + + ret = 0; + rtnl_lock(); + + tun = __tun_get(tfile); + if (cmd == TUNSETIFF && !tun) { + ifr.ifr_name[IFNAMSIZ-1] = '\0'; + + ret = tun_set_iff(tfile->net, file, &ifr); + + if (ret) + goto unlock; + + if (copy_to_user(argp, &ifr, ifreq_len)) + ret = -EFAULT; + goto unlock; + } + if (cmd == TUNSETIFINDEX) { + ret = -EPERM; + if (tun) + goto unlock; + + ret = -EFAULT; + if (copy_from_user(&ifindex, argp, sizeof(ifindex))) + goto unlock; + + ret = 0; + tfile->ifindex = ifindex; + goto unlock; + } + + ret = -EBADFD; + if (!tun) + goto unlock; + + tun_debug(KERN_INFO, tun, "tun_chr_ioctl cmd %u\n", cmd); + + ret = 0; + switch (cmd) { + case TUNGETIFF: + tun_get_iff(current->nsproxy->net_ns, tun, &ifr); + + if (tfile->detached) + ifr.ifr_flags |= IFF_DETACH_QUEUE; + if (!tfile->socket.sk->sk_filter) + ifr.ifr_flags |= IFF_NOFILTER; + + if (copy_to_user(argp, &ifr, ifreq_len)) + ret = -EFAULT; + break; + + case TUNSETNOCSUM: + /* Disable/Enable checksum */ + + /* [unimplemented] */ + tun_debug(KERN_INFO, tun, "ignored: set checksum %s\n", + arg ? "disabled" : "enabled"); + break; + + case TUNSETPERSIST: + /* Disable/Enable persist mode. Keep an extra reference to the + * module to prevent the module being unprobed. + */ + if (arg && !(tun->flags & TUN_PERSIST)) { + tun->flags |= TUN_PERSIST; + __module_get(THIS_MODULE); + } + if (!arg && (tun->flags & TUN_PERSIST)) { + tun->flags &= ~TUN_PERSIST; + module_put(THIS_MODULE); + } + + tun_debug(KERN_INFO, tun, "persist %s\n", + arg ? "enabled" : "disabled"); + break; + + case TUNSETOWNER: + /* Set owner of the device */ + owner = make_kuid(current_user_ns(), arg); + if (!uid_valid(owner)) { + ret = -EINVAL; + break; + } + tun->owner = owner; + tun_debug(KERN_INFO, tun, "owner set to %u\n", + from_kuid(&init_user_ns, tun->owner)); + break; + + case TUNSETGROUP: + /* Set group of the device */ + group = make_kgid(current_user_ns(), arg); + if (!gid_valid(group)) { + ret = -EINVAL; + break; + } + tun->group = group; + tun_debug(KERN_INFO, tun, "group set to %u\n", + from_kgid(&init_user_ns, tun->group)); + break; + + case TUNSETLINK: + /* Only allow setting the type when the interface is down */ + if (tun->dev->flags & IFF_UP) { + tun_debug(KERN_INFO, tun, + "Linktype set failed because interface is up\n"); + ret = -EBUSY; + } else { + tun->dev->type = (int) arg; + tun_debug(KERN_INFO, tun, "linktype set to %d\n", + tun->dev->type); + ret = 0; + } + break; + +#ifdef TUN_DEBUG + case TUNSETDEBUG: + tun->debug = arg; + break; +#endif + case TUNSETOFFLOAD: + ret = set_offload(tun, arg); + break; + + case TUNSETTXFILTER: + /* Can be set only for TAPs */ + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV) + break; + ret = update_filter(&tun->txflt, (void __user *)arg); + break; + + case SIOCGIFHWADDR: + /* Get hw address */ + memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN); + ifr.ifr_hwaddr.sa_family = tun->dev->type; + if (copy_to_user(argp, &ifr, ifreq_len)) + ret = -EFAULT; + break; + + case SIOCSIFHWADDR: + /* Set hw address */ + tun_debug(KERN_DEBUG, tun, "set hw address: %pM\n", + ifr.ifr_hwaddr.sa_data); + + ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr); + break; + + case TUNGETSNDBUF: + sndbuf = tfile->socket.sk->sk_sndbuf; + if (copy_to_user(argp, &sndbuf, sizeof(sndbuf))) + ret = -EFAULT; + break; + + case TUNSETSNDBUF: + if (copy_from_user(&sndbuf, argp, sizeof(sndbuf))) { + ret = -EFAULT; + break; + } + + tun->sndbuf = sndbuf; + tun_set_sndbuf(tun); + break; + + case TUNGETVNETHDRSZ: + vnet_hdr_sz = tun->vnet_hdr_sz; + if (copy_to_user(argp, &vnet_hdr_sz, sizeof(vnet_hdr_sz))) + ret = -EFAULT; + break; + + case TUNSETVNETHDRSZ: + if (copy_from_user(&vnet_hdr_sz, argp, sizeof(vnet_hdr_sz))) { + ret = -EFAULT; + break; + } + if (vnet_hdr_sz < (int)sizeof(struct virtio_net_hdr)) { + ret = -EINVAL; + break; + } + + tun->vnet_hdr_sz = vnet_hdr_sz; + break; + + case TUNATTACHFILTER: + /* Can be set only for TAPs */ + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV) + break; + ret = -EFAULT; + if (copy_from_user(&tun->fprog, argp, sizeof(tun->fprog))) + break; + + ret = tun_attach_filter(tun); + break; + + case TUNDETACHFILTER: + /* Can be set only for TAPs */ + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV) + break; + ret = 0; + tun_detach_filter(tun, tun->numqueues); + break; + + case TUNGETFILTER: + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV) + break; + ret = -EFAULT; + if (copy_to_user(argp, &tun->fprog, sizeof(tun->fprog))) + break; + ret = 0; + break; + + default: + ret = -EINVAL; + break; + } + +unlock: + rtnl_unlock(); + if (tun) + tun_put(tun); + return ret; +} + +static long tun_chr_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + return __tun_chr_ioctl(file, cmd, arg, sizeof (struct ifreq)); +} + +#ifdef CONFIG_COMPAT +static long tun_chr_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case TUNSETIFF: + case TUNGETIFF: + case TUNSETTXFILTER: + case TUNGETSNDBUF: + case TUNSETSNDBUF: + case SIOCGIFHWADDR: + case SIOCSIFHWADDR: + arg = (unsigned long)compat_ptr(arg); + break; + default: + arg = (compat_ulong_t)arg; + break; + } + + /* + * compat_ifreq is shorter than ifreq, so we must not access beyond + * the end of that structure. All fields that are used in this + * driver are compatible though, we don't need to convert the + * contents. + */ + return __tun_chr_ioctl(file, cmd, arg, sizeof(struct compat_ifreq)); +} +#endif /* CONFIG_COMPAT */ + +static int tun_chr_fasync(int fd, struct file *file, int on) +{ + struct tun_file *tfile = file->private_data; + int ret; + + if ((ret = fasync_helper(fd, file, on, &tfile->fasync)) < 0) + goto out; + + if (on) { + ret = __f_setown(file, task_pid(current), PIDTYPE_PID, 0); + if (ret) + goto out; + tfile->flags |= TUN_FASYNC; + } else + tfile->flags &= ~TUN_FASYNC; + ret = 0; +out: + return ret; +} + +static int tun_chr_open(struct inode *inode, struct file * file) +{ + struct tun_file *tfile; + + DBG1(KERN_INFO, "tunX: tun_chr_open\n"); + + tfile = (struct tun_file *)sk_alloc(&init_net, AF_UNSPEC, GFP_KERNEL, + &tun_proto); + if (!tfile) + return -ENOMEM; + RCU_INIT_POINTER(tfile->tun, NULL); + tfile->net = get_net(current->nsproxy->net_ns); + tfile->flags = 0; + tfile->ifindex = 0; + + init_waitqueue_head(&tfile->wq.wait); + RCU_INIT_POINTER(tfile->socket.wq, &tfile->wq); + + tfile->socket.file = file; + tfile->socket.ops = &tun_socket_ops; + + sock_init_data(&tfile->socket, &tfile->sk); + sk_change_net(&tfile->sk, tfile->net); + + tfile->sk.sk_write_space = tun_sock_write_space; + tfile->sk.sk_sndbuf = INT_MAX; + + file->private_data = tfile; + set_bit(SOCK_EXTERNALLY_ALLOCATED, &tfile->socket.flags); + INIT_LIST_HEAD(&tfile->next); + + sock_set_flag(&tfile->sk, SOCK_ZEROCOPY); + + return 0; +} + +static int tun_chr_close(struct inode *inode, struct file *file) +{ + struct tun_file *tfile = file->private_data; + struct net *net = tfile->net; + + tun_detach(tfile, true); + put_net(net); + + return 0; +} + +#ifdef CONFIG_PROC_FS +static int tun_chr_show_fdinfo(struct seq_file *m, struct file *f) +{ + struct tun_struct *tun; + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + + rtnl_lock(); + tun = tun_get(f); + if (tun) + tun_get_iff(current->nsproxy->net_ns, tun, &ifr); + rtnl_unlock(); + + if (tun) + tun_put(tun); + + return seq_printf(m, "iff:\t%s\n", ifr.ifr_name); +} +#endif + +static const struct file_operations tun_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = do_sync_read, + .aio_read = tun_chr_aio_read, + .write = do_sync_write, + .aio_write = tun_chr_aio_write, + .poll = tun_chr_poll, + .unlocked_ioctl = tun_chr_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = tun_chr_compat_ioctl, +#endif + .open = tun_chr_open, + .release = tun_chr_close, + .fasync = tun_chr_fasync, +#ifdef CONFIG_PROC_FS + .show_fdinfo = tun_chr_show_fdinfo, +#endif +}; + +static struct miscdevice tun_miscdev = { + .minor = (TUN_MINOR1), + .name = "bf_tun", + .nodename = "net/bf_tun", + .fops = &tun_fops, +}; + +/* ethtool interface */ + +static int tun_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + cmd->supported = 0; + cmd->advertising = 0; + ethtool_cmd_speed_set(cmd, SPEED_10); + cmd->duplex = DUPLEX_FULL; + cmd->port = PORT_TP; + cmd->phy_address = 0; + cmd->transceiver = XCVR_INTERNAL; + cmd->autoneg = AUTONEG_DISABLE; + cmd->maxtxpkt = 0; + cmd->maxrxpkt = 0; + return 0; +} + +static void tun_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct tun_struct *tun = netdev_priv(dev); + + strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); + strlcpy(info->version, DRV_VERSION, sizeof(info->version)); + + switch (tun->flags & TUN_TYPE_MASK) { + case TUN_TUN_DEV: + strlcpy(info->bus_info, "bf_tun", sizeof(info->bus_info)); + break; + case TUN_TAP_DEV: + strlcpy(info->bus_info, "tap", sizeof(info->bus_info)); + break; + } +} + +static u32 tun_get_msglevel(struct net_device *dev) +{ +#ifdef TUN_DEBUG + struct tun_struct *tun = netdev_priv(dev); + return tun->debug; +#else + return -EOPNOTSUPP; +#endif +} + +static void tun_set_msglevel(struct net_device *dev, u32 value) +{ +#ifdef TUN_DEBUG + struct tun_struct *tun = netdev_priv(dev); + tun->debug = value; +#endif +} + +static const struct ethtool_ops tun_ethtool_ops = { + .get_settings = tun_get_settings, + .get_drvinfo = tun_get_drvinfo, + .get_msglevel = tun_get_msglevel, + .set_msglevel = tun_set_msglevel, + .get_link = ethtool_op_get_link, + .get_ts_info = ethtool_op_get_ts_info, +}; + + +static int __init tun_init(void) +{ + int ret = 0; + + pr_info("%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); + pr_info("%s\n", DRV_COPYRIGHT); + + ret = rtnl_link_register(&tun_link_ops); + if (ret) { + pr_err("Can't register link_ops\n"); + goto err_linkops; + } + + ret = misc_register(&tun_miscdev); + if (ret) { + pr_err("Can't register misc device %d\n", (TUN_MINOR1)); + goto err_misc; + } + return 0; +err_misc: + rtnl_link_unregister(&tun_link_ops); +err_linkops: + return ret; +} + +static void tun_cleanup(void) +{ + misc_deregister(&tun_miscdev); + rtnl_link_unregister(&tun_link_ops); +} + +/* Get an underlying socket object from tun file. Returns error unless file is + * attached to a device. The returned object works like a packet socket, it + * can be used for sock_sendmsg/sock_recvmsg. The caller is responsible for + * holding a reference to the file for as long as the socket is in use. */ +struct socket *bf_tun_get_socket(struct file *file) +{ + struct tun_file *tfile; + if (file->f_op != &tun_fops) + return ERR_PTR(-EINVAL); + tfile = file->private_data; + if (!tfile) + return ERR_PTR(-EBADFD); + return &tfile->socket; +} +EXPORT_SYMBOL_GPL(bf_tun_get_socket); + +module_init(tun_init); +module_exit(tun_cleanup); +MODULE_DESCRIPTION(DRV_DESCRIPTION); +MODULE_AUTHOR(DRV_COPYRIGHT); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(TUN_MINOR1); +MODULE_ALIAS("devname:net/bf_tun"); diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/i2c-mcp2221.c b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/i2c-mcp2221.c new file mode 100644 index 000000000000..fcaa57fbafac --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/i2c-mcp2221.c @@ -0,0 +1,611 @@ +/* + * i2c bus driver for MCP2221 + * + * Derived from: + * i2c-tiny-usb.c + * i2c-diolan-u2c.c + * usb-serial.c + * onetouch.c + * usb-skeleton.c + * + * Copyright (C) 2014 Microchip Technology Inc. + * + * Author: Bogdan Bolocan http://www.microchip.com/support + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "i2c-mcp2221" + +#define USB_VENDOR_ID_MCP2221 0x04d8 +#define USB_DEVICE_ID_MCP2221 0x00dd + +#define MCP2221_OUTBUF_LEN 64 /* USB write packet length */ +#define MCP2221_INBUF_LEN 64 /* USB read packet length */ + +#define MCP2221_MAX_I2C_DATA_LEN 60 + +//#define MCP2221_FREQ_STD 100000 +#define MCP2221_FREQ_STD 400000 +//#define MCP2221_FREQ_STD 50000 +#define MCP2221_FREQ_MAX 500000 + +#define MCP2221_RETRY_MAX 50 +#define MCP2221_STD_DELAY_MS 1 +//#define MCP2221_STD_DELAY_MS 2 + +#define RESP_ERR_NOERR 0x00 +#define RESP_ADDR_NACK 0x25 +#define RESP_READ_ERR 0x7F +#define RESP_READ_COMPL 0x55 +#define RESP_I2C_IDLE 0x00 +#define RESP_I2C_START_TOUT 0x12 +#define RESP_I2C_RSTART_TOUT 0x17 +#define RESP_I2C_WRADDRL_TOUT 0x23 +#define RESP_I2C_WRADDRL_WSEND 0x21 +#define RESP_I2C_WRADDRL_NACK 0x25 +#define RESP_I2C_WRDATA_TOUT 0x44 +#define RESP_I2C_RDDATA_TOUT 0x52 +#define RESP_I2C_STOP_TOUT 0x62 + +#define CMD_MCP2221_STATUS 0x10 +#define SUBCMD_STATUS_CANCEL 0x10 +#define SUBCMD_STATUS_SPEED 0x20 +#define MASK_ADDR_NACK 0x40 + +#define CMD_MCP2221_RDDATA7 0x91 +#define CMD_MCP2221_GET_RDDATA 0x40 + +#define CMD_MCP2221_WRDATA7 0x90 + +/* Structure to hold all of our device specific stuff */ +struct i2c_mcp2221 { + u8 obuffer[MCP2221_OUTBUF_LEN]; /* USB write buffer */ + u8 ibuffer[MCP2221_INBUF_LEN]; /* USB read buffer */ + /* I2C/SMBus data buffer */ + u8 user_data_buffer[MCP2221_MAX_I2C_DATA_LEN]; + int ep_in, ep_out; /* Endpoints */ + struct usb_device *usb_dev; /* the usb device for this device */ + struct usb_interface *interface;/* the interface for this device */ + struct i2c_adapter adapter; /* i2c related things */ + uint frequency; /* I2C/SMBus communication frequency */ + /* Mutex for low-level USB transactions */ + struct mutex mcp2221_usb_op_lock; + /* wq to wait for an ongoing read/write */ + wait_queue_head_t usb_urb_completion_wait; + bool ongoing_usb_ll_op; /* a ll is in progress */ + + struct urb *interrupt_in_urb; + struct urb *interrupt_out_urb; +}; + +static uint frequency = MCP2221_FREQ_STD; /* I2C clock frequency in Hz */ + +module_param(frequency, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(frequency, "I2C clock frequency in hertz"); + +/* usb layer */ + + +/* + * Return list of supported functionality. + */ +static u32 mcp2221_usb_func(struct i2c_adapter *a) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | + I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL; +} + +static void mcp2221_usb_cmpl_cbk(struct urb *urb) +{ + struct i2c_mcp2221 *dev = urb->context; + int status = urb->status; + int retval; + + switch (status) { + case 0: /* success */ + break; + case -ECONNRESET: /* unlink */ + case -ENOENT: + case -ESHUTDOWN: + return; + /* -EPIPE: should clear the halt */ + default: /* error */ + goto resubmit; + } + + /* wake up the waitting function + modify the flag indicating the ll status */ + dev->ongoing_usb_ll_op = 0; + wake_up_interruptible(&dev->usb_urb_completion_wait); + return; + +resubmit: + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) { + dev_err(&dev->interface->dev, + "mcp2221(irq): can't resubmit intrerrupt urb, retval %d\n", + retval); + } +} + +static int mcp2221_ll_cmd(struct i2c_mcp2221 *dev) +{ + int rv; + + /* tell everybody to leave the URB alone */ + dev->ongoing_usb_ll_op = 1; + + /* submit the interrupt out ep packet */ + if (usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL)) { + dev_err(&dev->interface->dev, + "mcp2221(ll): usb_submit_urb intr out failed\n"); + dev->ongoing_usb_ll_op = 0; + return -EIO; + } + + /* wait for its completion */ + rv = wait_event_interruptible(dev->usb_urb_completion_wait, + (!dev->ongoing_usb_ll_op)); + if (rv < 0) { + dev_err(&dev->interface->dev, "mcp2221(ll): wait interrupted\n"); + goto ll_exit_clear_flag; + } + + /* tell everybody to leave the URB alone */ + dev->ongoing_usb_ll_op = 1; + + /* submit the interrupt in ep packet */ + if (usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL)) { + dev_err(&dev->interface->dev, "mcp2221(ll): usb_submit_urb intr in failed\n"); + dev->ongoing_usb_ll_op = 0; + return -EIO; + } + + /* wait for its completion */ + rv = wait_event_interruptible(dev->usb_urb_completion_wait, + (!dev->ongoing_usb_ll_op)); + if (rv < 0) { + dev_err(&dev->interface->dev, "mcp2221(ll): wait interrupted\n"); + goto ll_exit_clear_flag; + } + +ll_exit_clear_flag: + dev->ongoing_usb_ll_op = 0; + return rv; +} + +static int mcp2221_init(struct i2c_mcp2221 *dev) +{ + int ret; + + ret = 0; + if (frequency > MCP2221_FREQ_MAX) + frequency = MCP2221_FREQ_MAX; + + /* initialize the MCP2221 and bring it to "idle/ready" state */ + dev_info(&dev->interface->dev, + "MCP2221 at USB bus %03d address %03d Freq=%dKhz-- mcp2221_init()\n", + dev->usb_dev->bus->busnum, dev->usb_dev->devnum, frequency/1000); + + /* initialize unlocked mutex */ + mutex_init(&dev->mcp2221_usb_op_lock); + + dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->interrupt_out_urb) + goto init_error; + + usb_fill_int_urb(dev->interrupt_out_urb, dev->usb_dev, + usb_sndintpipe(dev->usb_dev, + dev->ep_out), + (void *)&dev->obuffer, MCP2221_OUTBUF_LEN, + mcp2221_usb_cmpl_cbk, dev, + 1); + + dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->interrupt_in_urb) + goto init_error; + + usb_fill_int_urb(dev->interrupt_in_urb, dev->usb_dev, + usb_rcvintpipe(dev->usb_dev, + dev->ep_in), + (void *)&dev->ibuffer, MCP2221_INBUF_LEN, + mcp2221_usb_cmpl_cbk, dev, + 1); + ret = 0; + goto init_no_error; + +init_error: + dev_err(&dev->interface->dev, "mcp2221_init: Error = %d\n", ret); + ret = -ENODEV; + +init_no_error: + dev_info(&dev->interface->dev, "mcp2221_init: Success\n"); + return ret; +} + +static int mcp2221_i2c_readwrite(struct i2c_mcp2221 *dev, + struct i2c_msg *pmsg) +{ + u8 ucI2cDiv, ucCancelXfer, ucXferLen; + int rv, retries; + unsigned int sleepCmd; + u8 *pSrc, *pDst, usbCmdStatus; + + retries = 0; + ucCancelXfer = 0; + /* clock divider for I2C operations */ + ucI2cDiv = (u8)((12000000/frequency) - 3); + + /* determine the best delay value here */ + /* (MCP2221_STD_DELAY_MS * MCP2221_FREQ_MAX)/frequency; */ + sleepCmd = MCP2221_STD_DELAY_MS; + + if (pmsg->len > MCP2221_MAX_I2C_DATA_LEN) + return -EINVAL; + +readwrite_reinit: + dev->obuffer[0] = CMD_MCP2221_STATUS; /* code for STATUS cmd */ + dev->obuffer[1] = 0x00; + dev->obuffer[2] = ucCancelXfer; /* cancel subcmd */ + dev->obuffer[3] = SUBCMD_STATUS_SPEED; /* set the xfer speed */ + dev->obuffer[4] = ucI2cDiv; + dev->obuffer[5] = 0x00; + dev->obuffer[6] = 0x00; + dev->obuffer[7] = 0x00; + + rv = mcp2221_ll_cmd(dev); + if (rv < 0) + return -EFAULT; + + if (dev->ibuffer[1] != RESP_ERR_NOERR) + return -EFAULT; + + if (dev->ibuffer[3] != SUBCMD_STATUS_SPEED) { + /* the speed could not be set - wait a while and retry */ + if (retries < MCP2221_RETRY_MAX) { + /* wait a while and retry the operation */ + retries++; + msleep(MCP2221_STD_DELAY_MS); + ucCancelXfer = SUBCMD_STATUS_CANCEL; + goto readwrite_reinit; + } else { + /* max number of retries was reached - return error */ + dev_err(&dev->interface->dev, + "mcp2221 CANCEL ERROR:retries = %d\n", retries); + return -EFAULT; + } + } + + if (pmsg->flags & I2C_M_RD) { + /* I2C read */ + ucXferLen = (u8)pmsg->len; + dev->obuffer[0] = CMD_MCP2221_RDDATA7; + dev->obuffer[1] = ucXferLen; /* LSB of the xfer length */ + dev->obuffer[2] = 0; /* no MSB for the xfer length */ + /* address in 8-bit format */ + dev->obuffer[3] = (u8)((pmsg->addr) << 1); + + rv = mcp2221_ll_cmd(dev); + if (rv < 0) + return -EFAULT; + + if (dev->ibuffer[1] != RESP_ERR_NOERR) + return -EFAULT; + + retries = 0; + dev->obuffer[0] = CMD_MCP2221_GET_RDDATA; + dev->obuffer[1] = 0x00; + dev->obuffer[2] = 0x00; + dev->obuffer[3] = 0x00; + + while (retries < MCP2221_RETRY_MAX) { + msleep(sleepCmd); + + rv = mcp2221_ll_cmd(dev); + if (rv < 0) + return -EFAULT; + + if (dev->ibuffer[1] != RESP_ERR_NOERR) + return -EFAULT; + + if (dev->ibuffer[2] == RESP_ADDR_NACK) + return -EFAULT; + + /* break the loop - cmd ended ok - used for bus scan */ + if ((dev->ibuffer[3] == 0x00) && + (dev->ibuffer[2] == 0x00)) + break; + + if (dev->ibuffer[3] == RESP_READ_ERR) { + retries++; + continue; + } + + if ((dev->ibuffer[2] == RESP_READ_COMPL) && + (dev->ibuffer[3] == ucXferLen)) { + /* we got the data - copy it */ + pSrc = (u8 *)&dev->ibuffer[4]; + pDst = (u8 *)&pmsg->buf[0]; + memcpy(pDst, pSrc, ucXferLen); + + if (pmsg->flags & I2C_M_RECV_LEN) + pmsg->len = ucXferLen; + + break; + } + + } + if (retries >= MCP2221_RETRY_MAX) + return -EFAULT; + } else { + /* I2C write */ + ucXferLen = (u8)pmsg->len; + dev->obuffer[0] = CMD_MCP2221_WRDATA7; + dev->obuffer[1] = ucXferLen; /* LSB of the xfer length */ + dev->obuffer[2] = 0; /* no MSB for the xfer length */ + /* address in 8-bit format */ + dev->obuffer[3] = (u8)((pmsg->addr) << 1); + /* copy the data we've read back */ + pSrc = (u8 *)&pmsg->buf[0]; + pDst = (u8 *)&dev->obuffer[4]; + memcpy(pDst, pSrc, ucXferLen); + + retries = 0; + + while (retries < MCP2221_RETRY_MAX) { + rv = mcp2221_ll_cmd(dev); + if (rv < 0) + return -EFAULT; + + if (dev->ibuffer[1] != RESP_ERR_NOERR) { + usbCmdStatus = dev->ibuffer[2]; + if (usbCmdStatus == RESP_I2C_START_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRADDRL_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRADDRL_NACK) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRDATA_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_STOP_TOUT) + return -EFAULT; + + msleep(sleepCmd); + retries++; + continue; + } else { /* command completed successfully */ + break; + } + } + if (retries >= MCP2221_RETRY_MAX) + return -EFAULT; + + /* now, prepare for the STATUS stage */ + retries = 0; + dev->obuffer[0] = CMD_MCP2221_STATUS; /* code for STATUS cmd */ + dev->obuffer[1] = 0x00; + dev->obuffer[2] = 0x00; + dev->obuffer[3] = 0x00; + dev->obuffer[4] = 0x00; + dev->obuffer[5] = 0x00; + dev->obuffer[6] = 0x00; + dev->obuffer[7] = 0x00; + + while (retries < MCP2221_RETRY_MAX) { + rv = mcp2221_ll_cmd(dev); + if (rv < 0) + return -EFAULT; + + if (dev->ibuffer[1] != RESP_ERR_NOERR) + return -EFAULT; + + /* i2c slave address was nack-ed */ + if (dev->ibuffer[20] & MASK_ADDR_NACK) + return -EFAULT; + + usbCmdStatus = dev->ibuffer[8]; + if (usbCmdStatus == RESP_I2C_IDLE) + break; + + if (usbCmdStatus == RESP_I2C_START_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRADDRL_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRADDRL_WSEND) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRADDRL_NACK) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_WRDATA_TOUT) + return -EFAULT; + + if (usbCmdStatus == RESP_I2C_STOP_TOUT) + return -EFAULT; + + msleep(sleepCmd); + retries++; + } + if (retries >= MCP2221_RETRY_MAX) + return -EFAULT; + } + + return 0; +} + +/* device layer */ +static int mcp2221_usb_i2c_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + struct i2c_mcp2221 *dev = i2c_get_adapdata(adap); + struct i2c_msg *pmsg; + int ret, count; + + for (count = 0; count < num; count++) { + pmsg = &msgs[count]; + /* no concurrent users of the mcp2221 i2c xfer */ + ret = mutex_lock_interruptible(&dev->mcp2221_usb_op_lock); + if (ret < 0) + goto abort; + + ret = mcp2221_i2c_readwrite(dev, pmsg); + mutex_unlock(&dev->mcp2221_usb_op_lock); + if (ret < 0) + goto abort; + } + + /* if all the messages were transferred ok, return "num" */ + ret = num; + +abort: + return ret; +} + +static const struct i2c_algorithm mcp2221_usb_algorithm = { + .master_xfer = mcp2221_usb_i2c_xfer, + .functionality = mcp2221_usb_func, +}; + +static const struct usb_device_id mcp2221_table[] = { + { USB_DEVICE(USB_VENDOR_ID_MCP2221, USB_DEVICE_ID_MCP2221) }, + { } +}; + +MODULE_DEVICE_TABLE(usb, mcp2221_table); + +static void mcp2221_free(struct i2c_mcp2221 *dev) +{ + usb_put_dev(dev->usb_dev); + kfree(dev); +} + +static int mcp2221_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_host_interface *hostif = interface->cur_altsetting; + struct i2c_mcp2221 *dev; + int ret; + + if ((hostif->desc.bInterfaceNumber != 2) + || (hostif->desc.bInterfaceClass != 3)) { + pr_info("i2c-mcp2221(probe): Interface doesn't match the MCP2221 HID\n"); + return -ENODEV; + } + + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + pr_info("i2c-mcp2221(probe): no memory for device state\n"); + ret = -ENOMEM; + goto error; + } + + dev->ep_in = hostif->endpoint[0].desc.bEndpointAddress; + dev->ep_out = hostif->endpoint[1].desc.bEndpointAddress; + + dev->usb_dev = usb_get_dev(interface_to_usbdev(interface)); + dev->interface = interface; + + init_waitqueue_head(&dev->usb_urb_completion_wait); + + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, dev); + + /* setup i2c adapter description */ + dev->adapter.owner = THIS_MODULE; + dev->adapter.class = I2C_CLASS_HWMON; + dev->adapter.algo = &mcp2221_usb_algorithm; + i2c_set_adapdata(&dev->adapter, dev); + + snprintf(dev->adapter.name, sizeof(dev->adapter.name), + DRIVER_NAME " at bus %03d device %03d", + dev->usb_dev->bus->busnum, dev->usb_dev->devnum); + + dev->adapter.dev.parent = &dev->interface->dev; + + /* initialize mcp2221 i2c interface */ + ret = mcp2221_init(dev); + if (ret < 0) { + dev_err(&interface->dev, "failed to initialize adapter\n"); + goto error_free; + } + + /* and finally attach to i2c layer */ + ret = i2c_add_adapter(&dev->adapter); + if (ret < 0) { + dev_err(&interface->dev, "failed to add I2C adapter\n"); + goto error_free; + } + + dev_info(&dev->interface->dev, + "mcp2221_probe() -> chip connected -> Success\n"); + return 0; + +error_free: + usb_set_intfdata(interface, NULL); + mcp2221_free(dev); +error: + return ret; +} + +static void mcp2221_disconnect(struct usb_interface *interface) +{ + struct i2c_mcp2221 *dev = usb_get_intfdata(interface); + + i2c_del_adapter(&dev->adapter); + + usb_kill_urb(dev->interrupt_in_urb); + usb_kill_urb(dev->interrupt_out_urb); + usb_free_urb(dev->interrupt_in_urb); + usb_free_urb(dev->interrupt_out_urb); + + usb_set_intfdata(interface, NULL); + mcp2221_free(dev); + + pr_info("i2c-mcp2221(disconnect) -> chip disconnected"); +} + +static struct usb_driver mcp2221_driver = { + .name = DRIVER_NAME, + .probe = mcp2221_probe, + .disconnect = mcp2221_disconnect, + .id_table = mcp2221_table, +}; + +module_usb_driver(mcp2221_driver); + +MODULE_AUTHOR("Bogdan Bolocan"); +MODULE_DESCRIPTION(DRIVER_NAME "I2C MCP2221"); +MODULE_LICENSE("GPL v2"); diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld.c b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld.c new file mode 100644 index 000000000000..3a7d40ba9177 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld.c @@ -0,0 +1,198 @@ +/* + * wnc_cpld.c - A driver for control wnc_cpld base on lm75.c + * + * Copyright (c) 1998, 1999 Frodo Looijaard + * Copyright (c) 2017 WNC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Addresses scanned */ +static const unsigned short normal_i2c[] = { 0x31, 0x32, I2C_CLIENT_END }; + +/* Size of EEPROM in bytes */ +#define CPLD_SIZE 3 + +/* Each client has this additional data */ +struct cpld_data { + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 data[CPLD_SIZE]; /* Register value */ +}; + +static ssize_t show_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + data->data[0] = i2c_smbus_read_byte_data(client, attr->index); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%02x\n", data->data[0]); +} + +static ssize_t set_value(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 temp; + int error; + + error = kstrtou8(buf, 10, &temp); + if (error) + return error; + + mutex_lock(&data->update_lock); + i2c_smbus_write_byte_data(client, attr->index, temp); + mutex_unlock(&data->update_lock); + + return count; +} + +static SENSOR_DEVICE_ATTR(reset_control, S_IWUSR | S_IRUGO, show_value, set_value, 2); +static SENSOR_DEVICE_ATTR(sfp_mod_abs1, S_IRUGO, show_value, NULL, 3); +static SENSOR_DEVICE_ATTR(sfp_mod_abs2, S_IRUGO, show_value, NULL, 4); +static SENSOR_DEVICE_ATTR(sfp_mod_abs3, S_IRUGO, show_value, NULL, 5); +static SENSOR_DEVICE_ATTR(sfp_mod_abs4, S_IRUGO, show_value, NULL, 6); +static SENSOR_DEVICE_ATTR(qsfp_modprs, S_IRUGO, show_value, NULL, 22); +static SENSOR_DEVICE_ATTR(qsfp_lpmode, S_IWUSR | S_IRUGO, show_value, set_value, 24); + +static struct attribute *cpld2_attributes[] = { + &sensor_dev_attr_reset_control.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs1.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs2.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs3.dev_attr.attr, + &sensor_dev_attr_qsfp_modprs.dev_attr.attr, + &sensor_dev_attr_qsfp_lpmode.dev_attr.attr, + NULL +}; + +static struct attribute *cpld1_attributes[] = { + &sensor_dev_attr_sfp_mod_abs1.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs2.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs3.dev_attr.attr, + &sensor_dev_attr_sfp_mod_abs4.dev_attr.attr, + NULL +}; + +static const struct attribute_group cpld2_group = { + .attrs = cpld2_attributes, +}; + +static const struct attribute_group cpld1_group = { + .attrs = cpld1_attributes, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int cpld_detect(struct i2c_client *new_client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = new_client->adapter; + int conf; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + + /* Unused bits */ + conf = i2c_smbus_read_byte_data(new_client, 0); + if (!conf) + return -ENODEV; + + return 0; +} + + +static int cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct cpld_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; +#if 1 + data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); +#endif + + if (client->addr == 49) /* 0x31 */ + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpld1_group); + else if (client->addr == 50) /* 0x32 */ + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &cpld2_group); + else + status = 1; + + if (status) + return status; + + dev_info(&client->dev, "cpld 0x%x found\n", client->addr); + + return 0; +} + +static int cpld_remove(struct i2c_client *client) +{ + if (client->addr == 49) /* 0x31 */ + sysfs_remove_group(&client->dev.kobj, &cpld1_group); + else if (client->addr == 50) /* 0x32 */ + sysfs_remove_group(&client->dev.kobj, &cpld2_group); + else + return 1; + + return 0; +} + +static const struct i2c_device_id cpld_id[] = { + { "wnc_cpld", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cpld_id); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "wnc_cpld", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_id, + .detect = cpld_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(cpld_driver); + +MODULE_AUTHOR("WNC "); +MODULE_DESCRIPTION("WNC CPLD driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld3.c b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld3.c new file mode 100644 index 000000000000..a24698aa9cef --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_cpld3.c @@ -0,0 +1,200 @@ +/* + * wnc_cpld.c - A driver for control wnc_cpld3 base on lm75.c + * + * Copyright (c) 1998, 1999 Frodo Looijaard + * Copyright (c) 2017 WNC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Addresses scanned */ +static const unsigned short normal_i2c[] = { 0x33, I2C_CLIENT_END }; + +/* Size of EEPROM in bytes */ +#define CPLD_SIZE 3 + +/* Each client has this additional data */ +struct cpld_data { + struct i2c_client *client; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 data[CPLD_SIZE]; /* Register value */ +}; + +static ssize_t show_hwmon_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int index = to_sensor_dev_attr_2(da)->index; + + mutex_lock(&data->update_lock); + data->data[0] = i2c_smbus_read_byte_data(client, index); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", data->data[0]); +} + +static ssize_t show_sysfs_value(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + data->data[0] = i2c_smbus_read_byte_data(client, attr->index); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%02x\n", data->data[0]); +} + +static ssize_t set_hwmon_value(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + struct cpld_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int index = to_sensor_dev_attr_2(da)->index; + u8 temp; + int error; + + error = kstrtou8(buf, 10, &temp); + if (error) + return error; + + mutex_lock(&data->update_lock); + i2c_smbus_write_byte_data(client, index, temp); + mutex_unlock(&data->update_lock); + + return count; +} + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_hwmon_value, NULL, 6); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_hwmon_value, NULL, 7); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_hwmon_value, NULL, 8); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_hwmon_value, NULL, 9); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_hwmon_value, NULL, 10); +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_hwmon_value, set_hwmon_value, 6); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_hwmon_value, set_hwmon_value, 7); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_hwmon_value, set_hwmon_value, 8); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_hwmon_value, set_hwmon_value, 9); +static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR | S_IRUGO, show_hwmon_value, set_hwmon_value, 10); + +static struct attribute *cpld3_hwmon_attrs[] = { + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, + &sensor_dev_attr_pwm5.dev_attr.attr, + NULL +}; + +ATTRIBUTE_GROUPS(cpld3_hwmon); + +static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO, show_sysfs_value, NULL, 1); +static SENSOR_DEVICE_ATTR(power_good, S_IRUGO, show_sysfs_value, NULL, 4); + +static struct attribute *cpld3_sysfs_attrs[] = { + &sensor_dev_attr_cpld_version.dev_attr.attr, + &sensor_dev_attr_power_good.dev_attr.attr, + NULL +}; + +static const struct attribute_group cpld3_sysfs_group = { + .attrs = cpld3_sysfs_attrs, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int cpld_detect(struct i2c_client *new_client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = new_client->adapter; + int conf; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + + /* Unused bits */ + conf = i2c_smbus_read_byte_data(new_client, 0); + if (!conf) + return -ENODEV; + + return 0; +} + + +static int cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct device *hwmon_dev; + struct cpld_data *data; + int status; + + data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->client = client; + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + status = sysfs_create_group(&client->dev.kobj, &cpld3_sysfs_group); + hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, client->name, data, cpld3_hwmon_groups); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static int cpld_remove(struct i2c_client *client) +{ + devm_hwmon_device_unregister(&client->dev); + sysfs_remove_group(&client->dev.kobj, &cpld3_sysfs_group); + return 0; +} + +static const struct i2c_device_id cpld_id[] = { + { "wnc_cpld3", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cpld_id); + +static struct i2c_driver cpld_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "wnc_cpld3", + }, + .probe = cpld_probe, + .remove = cpld_remove, + .id_table = cpld_id, + .detect = cpld_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(cpld_driver); + +MODULE_AUTHOR("WNC "); +MODULE_DESCRIPTION("WNC CPLD3 driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_eeprom.c b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_eeprom.c new file mode 100644 index 000000000000..8ddf1f2af279 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/modules/wnc_eeprom.c @@ -0,0 +1,286 @@ +/* + * Copyright (C) 1998, 1999 Frodo Looijaard and + * Philip Edelbrock + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2004 Jean Delvare + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, I2C_CLIENT_END }; + + +/* Size of EEPROM in bytes */ +#define EEPROM_SIZE 256 + +/* possible types of eeprom devices */ +enum eeprom_nature { + UNKNOWN, + VAIO, +}; + +/* Each client has this additional data */ +struct eeprom_data { + struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[8]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ + enum eeprom_nature nature; +}; + + +static void eeprom_update_client(struct i2c_client *client, u8 slice) +{ + struct eeprom_data *data = i2c_get_clientdata(client); + int i; + + mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { + dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); + + if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { + //for (i = slice << 5; i < (slice + 1) << 5; i += 32) + for (i = slice << 5; i < (slice + 1) << 5; i += 24) + if (i2c_smbus_read_i2c_block_data(client, i, + 24, data->data + i) + != 24) + goto exit; + } else { + for (i = slice << 5; i < (slice + 1) << 5; i += 2) { + int word = i2c_smbus_read_word_data(client, i); + if (word < 0) + goto exit; + data->data[i] = word & 0xff; + data->data[i + 1] = word >> 8; + } + } + data->last_updated[slice] = jiffies; + data->valid |= (1 << slice); + } +exit: + mutex_unlock(&data->update_lock); +} + +static ssize_t eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 slice; + + data->valid = 0; + + if (off > EEPROM_SIZE) + return 0; + if (off + count > EEPROM_SIZE) + count = EEPROM_SIZE - off; + + /* Only refresh slices which contain requested bytes */ + for (slice = off >> 5; slice <= (off + count - 1) >> 5; slice++) + eeprom_update_client(client, slice); + + /* Hide Vaio private settings to regular users: + - BIOS passwords: bytes 0x00 to 0x0f + - UUID: bytes 0x10 to 0x1f + - Serial number: 0xc0 to 0xdf */ + if (data->nature == VAIO && !capable(CAP_SYS_ADMIN)) { + int i; + + for (i = 0; i < count; i++) { + if ((off + i <= 0x1f) || + (off + i >= 0xc0 && off + i <= 0xdf)) + buf[i] = 0; + else + buf[i] = data->data[off + i]; + } + } else { + memcpy(buf, &data->data[off], count); + } + + return count; +} + +static ssize_t eeprom_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); + struct eeprom_data *data = i2c_get_clientdata(client); + u8 temp; + int error, reg; + + mutex_lock(&data->update_lock); + + error = kstrtou8(buf, 10, &temp); + if (error) + return error; + + if (client->addr == 0x51) { /* SFP AOC cable, page selection byte is 126 */ + reg = 126; + } + else if (client->addr == 0x50) { /* QSFP, page selection byte is 127 */ + data->data[0] = i2c_smbus_read_byte_data(client, 0); + + /* Base on SFF-8024, determine this module is SFP or QSFP by byte 0 (Identifier) */ + switch (data->data[0]){ + case 12: + case 13: + case 17: + case 24: + reg = 127; + break; + + default: + goto exit; + } + } + else + goto exit; + + i2c_smbus_write_byte_data(client, reg, temp); + +exit: + mutex_unlock(&data->update_lock); + + return count; +} + +static struct bin_attribute eeprom_attr = { + .attr = { + .name = "eeprom", + .mode = S_IWUSR | S_IRUGO | S_IWGRP | S_IWOTH, + }, + .size = EEPROM_SIZE, + .read = eeprom_read, + .write = eeprom_write, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int eeprom_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all + addresses 0x50-0x57, but we only care about 0x50. So decline + attaching to addresses >= 0x51 on DDC buses */ + if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51) + return -ENODEV; + + /* There are four ways we can read the EEPROM data: + (1) I2C block reads (faster, but unsupported by most adapters) + (2) Word reads (128% overhead) + (3) Consecutive byte reads (88% overhead, unsafe) + (4) Regular byte data reads (265% overhead) + The third and fourth methods are not implemented by this driver + because all known adapters support one of the first two. */ + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) + return -ENODEV; + + strlcpy(info->type, "wnc_eeprom", I2C_NAME_SIZE); + + return 0; +} + +static int eeprom_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = client->adapter; + struct eeprom_data *data; + int err; + + if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + memset(data->data, 0xff, EEPROM_SIZE); + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->nature = UNKNOWN; + + /* Detect the Vaio nature of EEPROMs. + We use the "PCG-" or "VGN-" prefix as the signature. */ + if (client->addr == 0x57 + && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + char name[4]; + + name[0] = i2c_smbus_read_byte_data(client, 0x80); + name[1] = i2c_smbus_read_byte_data(client, 0x81); + name[2] = i2c_smbus_read_byte_data(client, 0x82); + name[3] = i2c_smbus_read_byte_data(client, 0x83); + + if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) { + dev_info(&client->dev, "Vaio EEPROM detected, " + "enabling privacy protection\n"); + data->nature = VAIO; + } + } + + /* create the sysfs eeprom file */ + err = sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr); + if (err) + goto exit_kfree; + + return 0; + +exit_kfree: + kfree(data); +exit: + return err; +} + +static int eeprom_remove(struct i2c_client *client) +{ + sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static const struct i2c_device_id eeprom_id[] = { + { "wnc_eeprom", 0 }, + { } +}; + +static struct i2c_driver eeprom_driver = { + .driver = { + .name = "wnc_eeprom", + }, + .probe = eeprom_probe, + .remove = eeprom_remove, + .id_table = eeprom_id, + + .class = I2C_CLASS_DDC | I2C_CLASS_SPD, + .detect = eeprom_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(eeprom_driver); + +MODULE_AUTHOR("Frodo Looijaard and " + "Philip Edelbrock and " + "Greg Kroah-Hartman "); +MODULE_DESCRIPTION("I2C EEPROM driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/device_node.sh b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/device_node.sh new file mode 100644 index 000000000000..7e1c7c45a725 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/device_node.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +SEARCH_I2C_BUS=$(ls /sys/bus/i2c/devices) +I2C_BUS=-1 + +for i in $SEARCH_I2C_BUS +do + if [[ -n $(cat /sys/bus/i2c/devices/$i/name | grep i2c-mcp2221) ]]; then + I2C_BUS=$(echo $i | sed 's/i2c-//g') + break + fi +done + +if [[ $I2C_BUS == -1 ]]; then + echo "Can't find i2c-mcp2221" + exit +fi + +TOTAL_MUX=8 +START_NODE_NUM=$((I2C_BUS+1)) + +modprobe i2c_mux_pca954x force_deselect_on_exit=1 + +echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device +echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-$I2C_BUS/new_device + +sleep 5 + +/sbin/modprobe wnc_cpld +/sbin/modprobe wnc_cpld3 +/sbin/modprobe wnc_eeprom +/sbin/modprobe eeprom + +# MUX0: i2c-3~i2c-10 +# MUX1: i2c-11~i2c-18 +# MUX2: i2c-19~i2c-26 +# MUX3: i2c-27~i2c-34 +# MUX4: i2c-35~i2c-42 +# MUX5: i2c-43~i2c-50 +# MUX6: i2c-51~i2c-58 +# MUX7: i2c-59~i2c-66 + +# MUX0 channel0 +CHANNEL=0 +echo wnc_cpld 0x31 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel1 +CHANNEL=1 +echo wnc_cpld 0x32 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel2 +CHANNEL=2 +echo wnc_cpld3 0x33 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device +echo wnc_eeprom 0x53 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel3 +CHANNEL=3 +echo wnc_eeprom 0x50 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device +echo wnc_eeprom 0x51 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel4 +CHANNEL=4 +echo wnc_eeprom 0x54 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device +echo tmp421 0x1E > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device +sleep 1 +echo tmp75 0x4E > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device +sleep 1 +echo tmp421 0x4F > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel5 +CHANNEL=5 +echo wnc_eeprom 0x52 > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +# MUX0 channel7 +CHANNEL=7 +#echo wnc_eeprom 0x5B > /sys/bus/i2c/devices/i2c-$(($START_NODE_NUM+$CHANNEL))/new_device + +START_PORT_NUM=$((START_NODE_NUM+8)) +END_PORT_NUM=$((TOTAL_MUX*8+1)) + +for i in $(seq $START_PORT_NUM $END_PORT_NUM) +do + echo wnc_eeprom 0x50 > /sys/bus/i2c/devices/i2c-$i/new_device + echo wnc_eeprom 0x51 > /sys/bus/i2c/devices/i2c-$i/new_device +done diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/driver_load.sh b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/driver_load.sh new file mode 100644 index 000000000000..81cee0383ff2 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/driver_load.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +vid=04d8 +pid=00dd + +#check to see if sysfs is mounted +sysfs_path=`awk '/^sysfs/{ print $2 }' < /proc/mounts` +curr_path=`pwd` + +#if variable is empty, we should exit. No SYSFS found +if [[ -z $sysfs_path ]]; then + echo "No sysfs in this system! Exiting..." + exit 1 +fi + +function load_drivers +{ + modprobe i2c-dev + if [[ $? -ne 0 ]]; then + echo "Cannot load the \"i2c-dev\" driver! Exiting..." + exit 1 + fi + modprobe i2c-mcp2221 + if [[ $? -ne 0 ]]; then + echo "Cannot load the \"i2c-mcp2221\" driver! Exiting..." + exit 1 + fi + echo "I2C related drivers are loaded" +} + +usb_device_path=${sysfs_path}/bus/usb/devices + +cd $usb_device_path + +for usbdev in *; do + idvendor=${usb_device_path}/${usbdev}/idVendor + idproduct=${usb_device_path}/${usbdev}/idProduct + usb_driver=${usb_device_path}/${usbdev}/${usbdev}:1.2/driver + if [[ -f $idvendor ]]; then + dev_vid=`grep -i $vid < $idvendor` + dev_pid=`grep -i $pid < $idproduct` + if [[ -n $dev_vid ]] && [[ -n $dev_pid ]]; then + echo "I found the requested VID/PID: $dev_vid, $dev_pid" + load_drivers + echo -n "${usbdev}:1.2" > ${usb_driver}/unbind + echo -n "${usbdev}:1.2" > ${sysfs_path}/bus/usb/drivers/i2c-mcp2221/bind + fi + fi +done + diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/test b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/test new file mode 100644 index 000000000000..38327722c91f --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/scripts/test @@ -0,0 +1 @@ +echo "test" diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/device_node.service b/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/device_node.service new file mode 100644 index 000000000000..fd1bd9b15648 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/device_node.service @@ -0,0 +1,11 @@ +[Unit] +Description=Create device nodes for i2c devices. +Requires=driver_load.service +After=driver_load.service + +[Service] +Type=oneshot +ExecStart=/bin/bash /usr/local/bin/device_node.sh + +[Install] +WantedBy=multi-user.target diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/driver_load.service b/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/driver_load.service new file mode 100644 index 000000000000..52ce4d2f4442 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/service/driver_load.service @@ -0,0 +1,10 @@ +[Unit] +Description=Initialize i2c-mcp2221 driver. +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=/bin/bash /usr/local/bin/driver_load.sh + +[Install] +WantedBy=multi-user.target diff --git a/platform/vs/tests/conftest.py b/platform/vs/tests/conftest.py index 9256597f5e37..48ad7e15661a 100644 --- a/platform/vs/tests/conftest.py +++ b/platform/vs/tests/conftest.py @@ -54,8 +54,21 @@ def __init__(self, dvs): atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") keys = atbl.getKeys() - assert len(keys) == 1 - self.default_acl_table = keys[0] + assert len(keys) >= 1 + # Filter out DTel Acl tables + default_table_found = False + for k in keys: + if default_table_found: + break + (status, fvs) = atbl.get(k) + for item in fvs: + if item[0] == "SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST": + if 'SAI_ACL_BIND_POINT_TYPE_PORT' in item[1]: + self.default_acl_table = k + default_table_found = True + break + else: + break atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") keys = atbl.getKeys() diff --git a/slave.mk b/slave.mk index a4199bb1ebb6..a7cb518cb078 100644 --- a/slave.mk +++ b/slave.mk @@ -31,6 +31,7 @@ PROJECT_ROOT = $(shell pwd) CONFIGURED_PLATFORM := $(shell [ -f .platform ] && cat .platform || echo generic) PLATFORM_PATH = platform/$(CONFIGURED_PLATFORM) export BUILD_NUMBER +export CONFIGURED_PLATFORM ############################################################################### ## Utility rules diff --git a/sonic-slave/Dockerfile b/sonic-slave/Dockerfile index 8949db34a973..2737dab75f85 100644 --- a/sonic-slave/Dockerfile +++ b/sonic-slave/Dockerfile @@ -114,6 +114,11 @@ RUN apt-get update && apt-get install -y \ # For mellanox sai build libtool-bin \ libxml2-dev \ +# For BFN sdk build + libusb-1.0-0-dev \ + libcurl3-nss-dev \ + libunwind8-dev \ + telnet \ # For build image cpio \ squashfs-tools \ diff --git a/src/sonic-config-engine/tests/sample_output/interfaces b/src/sonic-config-engine/tests/sample_output/interfaces index 96dc577ffe8b..e3f09afd1a83 100644 --- a/src/sonic-config-engine/tests/sample_output/interfaces +++ b/src/sonic-config-engine/tests/sample_output/interfaces @@ -19,6 +19,7 @@ iface lo inet static address 10.10.0.99 netmask 255.255.255.255 # + # The management network interface auto eth0 iface eth0 inet static diff --git a/src/sonic-sairedis b/src/sonic-sairedis index 8585fc84d422..c2c5e7cf7fa4 160000 --- a/src/sonic-sairedis +++ b/src/sonic-sairedis @@ -1 +1 @@ -Subproject commit 8585fc84d422abf74d472702de7ad5ab20aa55e5 +Subproject commit c2c5e7cf7fa477691cda579405dde3d2573e066c diff --git a/src/sonic-swss b/src/sonic-swss index 762e7da80142..dcf6c905410f 160000 --- a/src/sonic-swss +++ b/src/sonic-swss @@ -1 +1 @@ -Subproject commit 762e7da80142358af0d348dea1143f38aa60a992 +Subproject commit dcf6c905410f08b004e880dbed56823d29e7bd5e diff --git a/src/sonic-swss-common b/src/sonic-swss-common index 8c5dab6b3417..dd470177f592 160000 --- a/src/sonic-swss-common +++ b/src/sonic-swss-common @@ -1 +1 @@ -Subproject commit 8c5dab6b341752b4bda3f63917a9c143df778322 +Subproject commit dd470177f5920ca546d1cc65dd206193c35d7e43