diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4d9a40c0..e4cc5db1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,6 +6,37 @@ stages: - test - doc - deploy + - release + +variables: + PACKAGE_REGISTRY_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/ethercat/${CI_COMMIT_TAG}" + +rtai: + stage: build + image: registry.gitlab.com/etherlab.org/build-container-factory/ethercat-kernels:rtai + + script: + - ./bootstrap + - ./configure --enable-8139too --enable-igb --enable-e100 --with-linux-dir=/usr/src/linux-obj/x86_64/0404rtai --enable-rtdm --with-rtai-dir=/usr + - make -j8 all modules + +xenomai2: + stage: build + image: registry.gitlab.com/etherlab.org/build-container-factory/ethercat-kernels:xenomai2 + + script: + - ./bootstrap + - ./configure --disable-8139too --with-linux-dir=/usr/src/linux-obj/x86_64/0318xenomai2 --enable-rtdm --with-xenomai-dir=/usr + - make -j8 all modules + +xenomai3: + stage: build + image: registry.gitlab.com/etherlab.org/build-container-factory/ethercat-kernels:xenomai3 + + script: + - ./bootstrap + - ./configure --enable-8139too --enable-igb --enable-e100 --with-linux-dir=/usr/src/linux-obj/x86_64/0510xenomai3 --enable-rtdm --with-xenomai-dir=/usr + - make -j8 all modules build: stage: build @@ -14,6 +45,7 @@ build: - ./bootstrap - ./configure --with-linux-dir=/usr/src/linux-obj/$(uname -i)/default --enable-tty --with-devices=2 --enable-ccat - make -j8 all modules + - make -C lib symbol-version-check - make DISTCHECK_CONFIGURE_FLAGS="--with-linux-dir=/usr/src/linux-obj/$(uname -i)/default" distcheck - make dist - mkdir test_dist && cd test_dist && tar xzf ../ethercat-*.tar.gz && cd ethercat-*/ @@ -21,6 +53,10 @@ build: - ../configure --with-linux-dir=/usr/src/linux-obj/$(uname -i)/default --disable-8139too --enable-tty --with-devices=2 --enable-ccat - make -j8 all modules + artifacts: + paths: + - ethercat-*.tar.gz + - ethercat-*.tar.bz2 # Build ethercat tool subcommand help output for documentation commands: @@ -89,12 +125,45 @@ pdf: update docs server: stage: deploy rules: - - if: $CI_COMMIT_BRANCH == "stable-1.5" && $CI_PROJECT_NAMESPACE == "etherlab.org" + - if: $CI_COMMIT_BRANCH == "stable-1.6" && $CI_PROJECT_NAMESPACE == "etherlab.org" trigger: etherlab.org/docs +upload: + stage: deploy + image: curlimages/curl:latest + rules: + - if: $CI_COMMIT_TAG && $CI_COMMIT_REF_PROTECTED == "true" + dependencies: + - "build" + script: + - echo "$CI_COMMIT_TAG" | grep -qE '^[0-9]+(\.[0-9]+){2}$' + - | + curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" \ + --header "Content-Type: application/gzip" \ + --fail-with-body \ + --upload-file "ethercat-${CI_COMMIT_TAG}.tar.gz" \ + "${PACKAGE_REGISTRY_URL}/ethercat-${CI_COMMIT_TAG}.tar.gz" + curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" \ + --header "Content-Type: application/x-bzip2" \ + --fail-with-body \ + --upload-file "ethercat-${CI_COMMIT_TAG}.tar.bz2" \ + "${PACKAGE_REGISTRY_URL}/ethercat-${CI_COMMIT_TAG}.tar.bz2" + + +release: + stage: release + image: registry.gitlab.com/gitlab-org/release-cli:latest + rules: + - if: $CI_COMMIT_TAG && $CI_COMMIT_REF_PROTECTED == "true" + script: + - | + release-cli create --name "Release $CI_COMMIT_TAG" --tag-name $CI_COMMIT_TAG \ + --assets-link "{\"name\":\"ethercat.tar.bz2\",\"url\":\"${PACKAGE_REGISTRY_URL}/ethercat-${CI_COMMIT_TAG}.tar.bz2\",\"link_type\":\"package\",\"filepath\":\"/dist-tarballs/ethercat.tar.bz2\"}" \ + --assets-link "{\"name\":\"ethercat.tar.gz\",\"url\":\"${PACKAGE_REGISTRY_URL}/ethercat-${CI_COMMIT_TAG}.tar.gz\",\"link_type\":\"package\",\"filepath\":\"/dist-tarballs/ethercat.tar.gz\"}" + # from 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml', but on all branches workflow: rules: - if: $CI_MERGE_REQUEST_IID - if: $CI_COMMIT_TAG - - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH == "stable-1.5" + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH == "stable-1.6" diff --git a/Kbuild.in b/Kbuild.in index 546430bc..4cc9eb9f 100644 --- a/Kbuild.in +++ b/Kbuild.in @@ -27,4 +27,9 @@ ifeq (@ENABLE_TTY@,1) obj-m += tty/ endif +ifeq (@ENABLE_RTAI@, 1) +KBUILD_EXTRA_SYMBOLS := \ + @RTAI_MODULE_DIR@/Module.symvers +endif + #----------------------------------------------------------------------------- diff --git a/NEWS b/NEWS index fba9edc5..d4bb398d 100644 --- a/NEWS +++ b/NEWS @@ -4,8 +4,16 @@ vim: spelllang=en spell tw=78 ------------------------------------------------------------------------------- +Changes in 1.6.0: + +* Added all native Ethernet drivers for kernels 5.14 and 6.1. +* Dropped support for kernels < 3.0. +* Allow to query the scanning progress via API. +* Added EoE set IP command via command-line-tool. + Changes since 1.5.2: +* Added feature flag API. * Fixed FoE timeout calculation bug. Changes in 1.5.2: diff --git a/configure.ac b/configure.ac index e3ca699e..7a9d22d1 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # -# Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH +# Copyright (C) 2006-2024 Florian Pose, Ingenieurgemeinschaft IgH # # This file is part of the IgH EtherCAT Master. # @@ -17,7 +17,7 @@ # with the IgH EtherCAT Master; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_PREREQ(2.59) @@ -31,7 +31,7 @@ AC_PREREQ(2.59) # - Update version number below # - make dist-bzip2 # -AC_INIT([ethercat],[1.5.2],[fp@igh.de]) +AC_INIT([ethercat],[1.6.0],[fp@igh.de]) AC_CONFIG_AUX_DIR([autoconf]) AM_INIT_AUTOMAKE([-Wall -Wno-override -Werror dist-bzip2 subdir-objects foreign]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) @@ -42,18 +42,18 @@ AC_PROG_SED PKG_PROG_PKG_CONFIG PKG_INSTALLDIR() -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # Global -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AM_PROG_CC_C_O m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) AC_PROG_CXX AC_PROG_LIBTOOL -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # Kernel modules -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_MSG_CHECKING([whether to build kernel modules]) @@ -82,9 +82,9 @@ fi AM_CONDITIONAL(ENABLE_KERNEL, test "x$enablekernel" = "x1") AC_SUBST(ENABLE_KERNEL,[$enablekernel]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # Linux sources -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- if test "x$enablekernel" = "x1"; then @@ -146,9 +146,9 @@ AC_MSG_RESULT([$LINUX_SOURCE_DIR (Kernel $linuxversion)]) fi -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # Linux module installation subdirectory -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_ARG_WITH([module-dir], AC_HELP_STRING( @@ -163,9 +163,9 @@ AC_SUBST(INSTALL_MOD_DIR,[$moddir]) AC_MSG_CHECKING([for Linux modules installation directory]) AC_MSG_RESULT([$INSTALL_MOD_DIR]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # Generic Ethernet driver -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_ARG_ENABLE([generic], AS_HELP_STRING([--enable-generic], @@ -186,9 +186,9 @@ AC_ARG_ENABLE([generic], AM_CONDITIONAL(ENABLE_GENERIC, test "x$enablegeneric" = "x1") AC_SUBST(ENABLE_GENERIC,[$enablegeneric]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # 8139too driver -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_ARG_ENABLE([8139too], AS_HELP_STRING([--enable-8139too], @@ -241,9 +241,9 @@ fi AC_SUBST(KERNEL_8139TOO,[$kernel8139too]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # e100 driver -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_ARG_ENABLE([e100], AS_HELP_STRING([--enable-e100], @@ -296,9 +296,9 @@ fi AC_SUBST(KERNEL_E100,[$kernele100]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # e1000 driver -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_ARG_ENABLE([e1000], AS_HELP_STRING([--enable-e1000], @@ -351,9 +351,9 @@ fi AC_SUBST(KERNEL_E1000,[$kernele1000]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # e1000e driver -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_ARG_ENABLE([e1000e], AS_HELP_STRING([--enable-e1000e], @@ -426,9 +426,9 @@ fi AC_SUBST(KERNEL_E1000E,[$kernele1000e]) AC_SUBST(E1000E_LAYOUT, [$e1000elayout]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # genet driver -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_ARG_ENABLE([genet], AS_HELP_STRING([--enable-genet], @@ -474,9 +474,9 @@ fi AC_SUBST(KERNEL_GENET,[$kernelgenet]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # igb driver -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_ARG_ENABLE([igb], AS_HELP_STRING([--enable-igb], @@ -521,9 +521,10 @@ if test "x${enableigb}" = "x1"; then fi AC_SUBST(KERNEL_IGB,[$kerneligb]) -#------------------------------------------------------------------------------ + +#----------------------------------------------------------------------------- # igc driver -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_ARG_ENABLE([igc], AS_HELP_STRING([--enable-igc], @@ -568,9 +569,9 @@ fi AC_SUBST(KERNEL_IGC,[$kerneligc]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # r8169 driver -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_ARG_ENABLE([r8169], AS_HELP_STRING([--enable-r8169], @@ -632,9 +633,9 @@ fi AC_SUBST(KERNEL_R8169,[$kernel_r8169]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # CCAT driver -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_MSG_CHECKING([whether to build the CCAT driver]) @@ -663,9 +664,9 @@ fi AM_CONDITIONAL(ENABLE_CCAT, test "x$enableccat" = "x1") AC_SUBST(ENABLE_CCAT,[$enableccat]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # RTAI path (optional) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_ARG_WITH([rtai-dir], AC_HELP_STRING( @@ -694,6 +695,7 @@ else rtai_lxrt_cflags=`$rtaidir/bin/rtai-config --lxrt-cflags` rtai_lxrt_ldflags=`$rtaidir/bin/rtai-config --lxrt-ldflags` + rtai_module_dir=`$rtaidir/bin/rtai-config --module-dir` fi AC_SUBST(RTAI_DIR,[$rtaidir]) @@ -702,10 +704,11 @@ AC_SUBST(ENABLE_RTAI,[$rtai]) AC_SUBST(RTAI_LXRT_CFLAGS,[$rtai_lxrt_cflags]) AC_SUBST(RTAI_LXRT_LDFLAGS,[$rtai_lxrt_ldflags]) +AC_SUBST(RTAI_MODULE_DIR,[$rtai_module_dir]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # Xenomai path (optional) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_ARG_WITH([xenomai-dir], AC_HELP_STRING( @@ -722,28 +725,61 @@ AC_ARG_WITH([xenomai-dir], ] ) +AC_ARG_WITH([xenomai-config], + AC_HELP_STRING( + [--with-xenomai-config=], + [Xenomai config invokation, default to xenomai-dir/bin/xeno-config] + ), + [ + xenomaiconfig=[$withval] + ], + [ + xenomaiconfig="$xenomaidir/bin/xeno-config" + ] +) + AC_MSG_CHECKING([for Xenomai path]) if test -z "${xenomaidir}"; then AC_MSG_RESULT([not specified.]) else - if test \! -r ${xenomaidir}/include/xeno_config.h; then + if test \! -x ${xenomaiconfig}; then AC_MSG_ERROR([no Xenomai installation found in ${xenomaidir}!]) fi AC_MSG_RESULT([$xenomaidir]) - xeno_native_cflags=`$xenomaidir/bin/xeno-config --skin native --cflags` - xeno_native_ldflags=`$xenomaidir/bin/xeno-config --skin native --ldflags` - xeno_posix_cflags=`$xenomaidir/bin/xeno-config --skin posix --cflags` - xeno_posix_ldflags=`$xenomaidir/bin/xeno-config --skin posix --ldflags` - xeno_rtdm_cflags=`$xenomaidir/bin/xeno-config --skin rtdm --cflags` - xeno_rtdm_ldflags=`$xenomaidir/bin/xeno-config --skin rtdm --ldflags` + xenomai_ver=`$xenomaiconfig --version` + xenomai_ver=${xenomai_ver##\"} + xenomai_ver=${xenomai_ver%%\"} + echo "xenomai version: " $xenomai_ver + + if test ${xenomai_ver%%.*} -gt 2; then + xeno_alchemy_cflags=`$xenomaiconfig --skin alchemy --cflags` + xeno_alchemy_ldflags=`$xenomaiconfig --skin alchemy --auto-init-solib --ldflags` + xeno_posix_ldflags=`$xenomaiconfig --skin posix --auto-init-solib --ldflags` + xeno_rtdm_ldflags=`$xenomaiconfig --skin rtdm --auto-init-solib --ldflags` + xeno_v3=1 + xeno=0 + AC_DEFINE([EC_RTDM_XENOMAI_V3], [1], [Use Xenomai3 RTDM flavour]) + else + xeno_native_cflags=`$xenomaiconfig --skin native --cflags` + xeno_native_ldflags=`$xenomaiconfig --skin native --ldflags` + xeno_posix_ldflags=`$xenomaiconfig --skin posix --ldflags` + xeno_rtdm_ldflags=`$xenomaiconfig --skin rtdm --ldflags` + fi + + xeno_posix_cflags=`$xenomaiconfig --skin posix --cflags` + xeno_rtdm_cflags=`$xenomaiconfig --skin rtdm --cflags` fi AC_SUBST(XENOMAI_DIR,[$xenomaidir]) AM_CONDITIONAL(ENABLE_XENOMAI, test "x$xeno" = "x1") AC_SUBST(ENABLE_XENOMAI,[$xeno]) +AM_CONDITIONAL(ENABLE_XENOMAI_V3, test "x$xeno_v3" = "x1") +AC_SUBST(ENABLE_XENOMAI_V3,[$xeno_v3]) +AC_SUBST(XENOMAI_ALCHEMY_CFLAGS,[$xeno_alchemy_cflags]) +AC_SUBST(XENOMAI_ALCHEMY_LDFLAGS,[$xeno_alchemy_ldflags]) AC_SUBST(XENOMAI_NATIVE_CFLAGS,[$xeno_native_cflags]) AC_SUBST(XENOMAI_NATIVE_LDFLAGS,[$xeno_native_ldflags]) AC_SUBST(XENOMAI_POSIX_CFLAGS,[$xeno_posix_cflags]) @@ -751,9 +787,9 @@ AC_SUBST(XENOMAI_POSIX_LDFLAGS,[$xeno_posix_ldflags]) AC_SUBST(XENOMAI_RTDM_CFLAGS,[$xeno_rtdm_cflags]) AC_SUBST(XENOMAI_RTDM_LDFLAGS,[$xeno_rtdm_ldflags]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # RTDM interface (optional) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_ARG_ENABLE([rtdm], AC_HELP_STRING( @@ -785,9 +821,9 @@ fi AM_CONDITIONAL(ENABLE_RTDM, test "x$rtdm" = "x1") AC_SUBST(ENABLE_RTDM,[$rtdm]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # Debug interface -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_MSG_CHECKING([whether to build the debug interface]) @@ -817,9 +853,9 @@ fi AM_CONDITIONAL(ENABLE_DEBUG_IF, test "x$dbg" = "x1") AC_SUBST(ENABLE_DEBUG_IF,[$dbg]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # Debug ring -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_MSG_CHECKING([whether to build the debug ring]) @@ -846,9 +882,9 @@ else AC_MSG_RESULT([no]) fi -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # Ethernet over EtherCAT support -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_MSG_CHECKING([whether to build with EoE support]) @@ -878,9 +914,9 @@ fi AM_CONDITIONAL(ENABLE_EOE, test "x$eoe" = "x1") AC_SUBST(ENABLE_EOE,[$eoe]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # CPU timestamp counter support -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_MSG_CHECKING([whether to use the CPU timestamp counter]) @@ -907,9 +943,9 @@ else AC_MSG_RESULT([no]) fi -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # High-resolution timer support -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_MSG_CHECKING([whether to use high-resolution timers for scheduling]) @@ -936,9 +972,9 @@ else AC_MSG_RESULT([no]) fi -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # Read alias address from register -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_MSG_CHECKING([whether to read alias addresses from registers]) @@ -965,7 +1001,7 @@ else AC_MSG_RESULT([no]) fi -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # Command-line tool #----------------------------------------------------------------------------- @@ -995,9 +1031,9 @@ fi AM_CONDITIONAL(BUILD_TOOL, test "x$tool" = "x1") -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # Userspace library generation -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_MSG_CHECKING([whether to build the userspace library]) @@ -1025,9 +1061,9 @@ fi AM_CONDITIONAL(ENABLE_USERLIB, test "x$userlib" = "x1") -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # TTY driver -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_MSG_CHECKING([whether to build the tty driver]) @@ -1056,9 +1092,9 @@ fi AM_CONDITIONAL(ENABLE_TTY, test "x$tty" = "x1") AC_SUBST(ENABLE_TTY,[$tty]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # Slave identification wildcards -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_MSG_CHECKING([whether to allow identification wildcards]) @@ -1086,9 +1122,9 @@ else AC_MSG_RESULT([no]) fi -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # Redundancy (number of devices) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_ARG_WITH([devices], AC_HELP_STRING( @@ -1118,9 +1154,9 @@ fi AC_DEFINE_UNQUOTED([EC_MAX_NUM_DEVICES], $devices, [Max. number of Ethernet devices per master]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # SII assignment -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_MSG_CHECKING([whether to assign the SII to PDI]) @@ -1147,9 +1183,9 @@ else AC_MSG_RESULT([no]) fi -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # syslog output in realtime context -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_MSG_CHECKING([whether to syslog in realtime context]) @@ -1176,9 +1212,9 @@ else AC_MSG_RESULT([no]) fi -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- # systemd service support -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_ARG_WITH([systemdsystemunitdir], AS_HELP_STRING([--with-systemdsystemunitdir=DIR], @@ -1205,7 +1241,7 @@ esac AM_CONDITIONAL(HAVE_SYSTEMD, test "x$with_systemdsystemunitdir" != "x") AC_SUBST(systemdsystemunitdir,[$with_systemdsystemunitdir]) -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- AC_CONFIG_FILES([ Doxyfile @@ -1257,6 +1293,7 @@ AC_CONFIG_FILES([ tty/Kbuild tty/Makefile ]) + AC_OUTPUT -#------------------------------------------------------------------------------ +#----------------------------------------------------------------------------- diff --git a/devices/e1000/e1000-4.4-ethercat.h b/devices/e1000/e1000-4.4-ethercat.h index 8abbe43b..1b047b23 100644 --- a/devices/e1000/e1000-4.4-ethercat.h +++ b/devices/e1000/e1000-4.4-ethercat.h @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -331,6 +332,7 @@ struct e1000_adapter { ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; enum e1000_state_t { diff --git a/devices/e1000/e1000-5.10-ethercat.h b/devices/e1000/e1000-5.10-ethercat.h index 87301858..e8281f68 100644 --- a/devices/e1000/e1000-5.10-ethercat.h +++ b/devices/e1000/e1000-5.10-ethercat.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -304,6 +305,7 @@ struct e1000_adapter { ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; enum e1000_state_t { diff --git a/devices/e1000/e1000-5.14-ethercat.h b/devices/e1000/e1000-5.14-ethercat.h index 023fee7b..71aa37ad 100644 --- a/devices/e1000/e1000-5.14-ethercat.h +++ b/devices/e1000/e1000-5.14-ethercat.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -304,6 +305,7 @@ struct e1000_adapter { ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; enum e1000_state_t { diff --git a/devices/e1000/e1000-5.15-ethercat.h b/devices/e1000/e1000-5.15-ethercat.h index b94866b7..17589120 100644 --- a/devices/e1000/e1000-5.15-ethercat.h +++ b/devices/e1000/e1000-5.15-ethercat.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -304,6 +305,7 @@ struct e1000_adapter { ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; enum e1000_state_t { diff --git a/devices/e1000/e1000-6.1-ethercat.h b/devices/e1000/e1000-6.1-ethercat.h index 30546b83..0769b47c 100644 --- a/devices/e1000/e1000-6.1-ethercat.h +++ b/devices/e1000/e1000-6.1-ethercat.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -304,6 +305,7 @@ struct e1000_adapter { ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; enum e1000_state_t { diff --git a/devices/e1000/e1000_main-4.4-ethercat.c b/devices/e1000/e1000_main-4.4-ethercat.c index b3649eb6..18042c1f 100644 --- a/devices/e1000/e1000_main-4.4-ethercat.c +++ b/devices/e1000/e1000_main-4.4-ethercat.c @@ -1253,6 +1253,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) // offer device to EtherCAT master module adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE); if (adapter->ecdev) { + init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog); err = ecdev_open(adapter->ecdev); if (err) { ecdev_withdraw(adapter->ecdev); @@ -1332,6 +1333,7 @@ static void e1000_remove(struct pci_dev *pdev) if (adapter->ecdev) { ecdev_close(adapter->ecdev); + irq_work_sync(&adapter->ec_watchdog_kicker); ecdev_withdraw(adapter->ecdev); } else { unregister_netdev(netdev); @@ -3857,12 +3859,20 @@ void e1000_update_stats(struct e1000_adapter *adapter) } } +static void ec_kick_watchdog(struct irq_work *work) +{ + struct e1000_adapter *adapter = + container_of(work, struct e1000_adapter, ec_watchdog_kicker); + + schedule_work(&adapter->watchdog_task); +} + void ec_poll(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); if (jiffies - adapter->ec_watchdog_jiffies >= 2 * HZ) { - e1000_watchdog(&adapter->watchdog_task.work); adapter->ec_watchdog_jiffies = jiffies; + irq_work_queue(&adapter->ec_watchdog_kicker); } e1000_intr(0, netdev); diff --git a/devices/e1000/e1000_main-5.10-ethercat.c b/devices/e1000/e1000_main-5.10-ethercat.c index 03c4bc6a..018f1168 100644 --- a/devices/e1000/e1000_main-5.10-ethercat.c +++ b/devices/e1000/e1000_main-5.10-ethercat.c @@ -1234,6 +1234,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) // offer device to EtherCAT master module adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE); if (adapter->ecdev) { + init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog); err = ecdev_open(adapter->ecdev); if (err) { ecdev_withdraw(adapter->ecdev); @@ -1313,6 +1314,7 @@ static void e1000_remove(struct pci_dev *pdev) if (adapter->ecdev) { ecdev_close(adapter->ecdev); + irq_work_sync(&adapter->ec_watchdog_kicker); ecdev_withdraw(adapter->ecdev); } else { unregister_netdev(netdev); @@ -3835,12 +3837,20 @@ void e1000_update_stats(struct e1000_adapter *adapter) } } +static void ec_kick_watchdog(struct irq_work *work) +{ + struct e1000_adapter *adapter = + container_of(work, struct e1000_adapter, ec_watchdog_kicker); + + schedule_work(&adapter->watchdog_task); +} + void ec_poll(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); if (jiffies - adapter->ec_watchdog_jiffies >= 2 * HZ) { - e1000_watchdog(&adapter->watchdog_task.work); adapter->ec_watchdog_jiffies = jiffies; + irq_work_queue(&adapter->ec_watchdog_kicker); } e1000_intr(0, netdev); diff --git a/devices/e1000/e1000_main-5.14-ethercat.c b/devices/e1000/e1000_main-5.14-ethercat.c index 20f154c6..ad3e681b 100644 --- a/devices/e1000/e1000_main-5.14-ethercat.c +++ b/devices/e1000/e1000_main-5.14-ethercat.c @@ -1234,6 +1234,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) // offer device to EtherCAT master module adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE); if (adapter->ecdev) { + init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog); err = ecdev_open(adapter->ecdev); if (err) { ecdev_withdraw(adapter->ecdev); @@ -1313,6 +1314,7 @@ static void e1000_remove(struct pci_dev *pdev) if (adapter->ecdev) { ecdev_close(adapter->ecdev); + irq_work_sync(&adapter->ec_watchdog_kicker); ecdev_withdraw(adapter->ecdev); } else { unregister_netdev(netdev); @@ -3834,12 +3836,20 @@ void e1000_update_stats(struct e1000_adapter *adapter) } } +static void ec_kick_watchdog(struct irq_work *work) +{ + struct e1000_adapter *adapter = + container_of(work, struct e1000_adapter, ec_watchdog_kicker); + + schedule_work(&adapter->watchdog_task); +} + void ec_poll(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); if (jiffies - adapter->ec_watchdog_jiffies >= 2 * HZ) { - e1000_watchdog(&adapter->watchdog_task.work); adapter->ec_watchdog_jiffies = jiffies; + irq_work_queue(&adapter->ec_watchdog_kicker); } e1000_intr(0, netdev); diff --git a/devices/e1000/e1000_main-5.15-ethercat.c b/devices/e1000/e1000_main-5.15-ethercat.c index 5f94a2c3..082150e9 100644 --- a/devices/e1000/e1000_main-5.15-ethercat.c +++ b/devices/e1000/e1000_main-5.15-ethercat.c @@ -1234,6 +1234,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) // offer device to EtherCAT master module adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE); if (adapter->ecdev) { + init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog); err = ecdev_open(adapter->ecdev); if (err) { ecdev_withdraw(adapter->ecdev); @@ -1313,6 +1314,7 @@ static void e1000_remove(struct pci_dev *pdev) if (adapter->ecdev) { ecdev_close(adapter->ecdev); + irq_work_sync(&adapter->ec_watchdog_kicker); ecdev_withdraw(adapter->ecdev); } else { unregister_netdev(netdev); @@ -3834,12 +3836,20 @@ void e1000_update_stats(struct e1000_adapter *adapter) } } +static void ec_kick_watchdog(struct irq_work *work) +{ + struct e1000_adapter *adapter = + container_of(work, struct e1000_adapter, ec_watchdog_kicker); + + schedule_work(&adapter->watchdog_task); +} + void ec_poll(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); if (jiffies - adapter->ec_watchdog_jiffies >= 2 * HZ) { - e1000_watchdog(&adapter->watchdog_task.work); adapter->ec_watchdog_jiffies = jiffies; + irq_work_queue(&adapter->ec_watchdog_kicker); } e1000_intr(0, netdev); diff --git a/devices/e1000/e1000_main-6.1-ethercat.c b/devices/e1000/e1000_main-6.1-ethercat.c index ce79ffa8..1898e511 100644 --- a/devices/e1000/e1000_main-6.1-ethercat.c +++ b/devices/e1000/e1000_main-6.1-ethercat.c @@ -1234,6 +1234,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) // offer device to EtherCAT master module adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE); if (adapter->ecdev) { + init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog); err = ecdev_open(adapter->ecdev); if (err) { ecdev_withdraw(adapter->ecdev); @@ -1313,6 +1314,7 @@ static void e1000_remove(struct pci_dev *pdev) if (adapter->ecdev) { ecdev_close(adapter->ecdev); + irq_work_sync(&adapter->ec_watchdog_kicker); ecdev_withdraw(adapter->ecdev); } else { unregister_netdev(netdev); @@ -3835,12 +3837,20 @@ void e1000_update_stats(struct e1000_adapter *adapter) } } +static void ec_kick_watchdog(struct irq_work *work) +{ + struct e1000_adapter *adapter = + container_of(work, struct e1000_adapter, ec_watchdog_kicker); + + schedule_work(&adapter->watchdog_task); +} + void ec_poll(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); if (jiffies - adapter->ec_watchdog_jiffies >= 2 * HZ) { - e1000_watchdog(&adapter->watchdog_task.work); adapter->ec_watchdog_jiffies = jiffies; + irq_work_queue(&adapter->ec_watchdog_kicker); } e1000_intr(0, netdev); diff --git a/devices/igb/igb-4.4-ethercat.h b/devices/igb/igb-4.4-ethercat.h index 05f41ddd..846e2c81 100644 --- a/devices/igb/igb-4.4-ethercat.h +++ b/devices/igb/igb-4.4-ethercat.h @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -474,6 +475,7 @@ struct igb_adapter { /* EtherCAT device variables */ ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; #define IGB_FLAG_HAS_MSI (1 << 0) diff --git a/devices/igb/igb-5.10-ethercat.h b/devices/igb/igb-5.10-ethercat.h index 3fbfcad0..6bfdc364 100644 --- a/devices/igb/igb-5.10-ethercat.h +++ b/devices/igb/igb-5.10-ethercat.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -671,6 +672,7 @@ struct igb_adapter { /* EtherCAT device variables */ ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; /* flags controlling PTP/1588 function */ diff --git a/devices/igb/igb-5.14-ethercat.h b/devices/igb/igb-5.14-ethercat.h index 8c634215..59392816 100644 --- a/devices/igb/igb-5.14-ethercat.h +++ b/devices/igb/igb-5.14-ethercat.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -671,6 +672,7 @@ struct igb_adapter { /* EtherCAT device variables */ ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; /* flags controlling PTP/1588 function */ diff --git a/devices/igb/igb-5.15-ethercat.h b/devices/igb/igb-5.15-ethercat.h index 2e82cc6f..02c798fe 100644 --- a/devices/igb/igb-5.15-ethercat.h +++ b/devices/igb/igb-5.15-ethercat.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -671,6 +672,7 @@ struct igb_adapter { /* EtherCAT device variables */ ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; /* flags controlling PTP/1588 function */ diff --git a/devices/igb/igb-6.1-ethercat.h b/devices/igb/igb-6.1-ethercat.h index 78b9125a..dbdf917d 100644 --- a/devices/igb/igb-6.1-ethercat.h +++ b/devices/igb/igb-6.1-ethercat.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -673,6 +674,7 @@ struct igb_adapter { /* EtherCAT device variables */ ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; /* flags controlling PTP/1588 function */ diff --git a/devices/igb/igb_main-4.4-ethercat.c b/devices/igb/igb_main-4.4-ethercat.c index 22c22b6f..0d89fde9 100644 --- a/devices/igb/igb_main-4.4-ethercat.c +++ b/devices/igb/igb_main-4.4-ethercat.c @@ -2126,6 +2126,14 @@ static const struct net_device_ops igb_netdev_ops = { .ndo_features_check = passthru_features_check, }; +static void ec_kick_watchdog(struct irq_work *work) +{ + struct igb_adapter *adapter = + container_of(work, struct igb_adapter, ec_watchdog_kicker); + + schedule_work(&adapter->watchdog_task); +} + /** * ec_poll - EtherCAT poll routine * @netdev: net device structure @@ -2140,12 +2148,8 @@ void ec_poll(struct net_device *netdev) int budget = 64; if (jiffies - adapter->ec_watchdog_jiffies >= 2 * HZ) { - struct e1000_hw *hw = &adapter->hw; - bool link; - hw->mac.get_link_status = true; - link = igb_has_link(adapter); - ecdev_set_link(adapter->ecdev, link); adapter->ec_watchdog_jiffies = jiffies; + irq_work_queue(&adapter->ec_watchdog_kicker); } for (i = 0; i < adapter->num_q_vectors; i++) { @@ -2605,6 +2609,7 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE); if (adapter->ecdev) { + init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog); err = ecdev_open(adapter->ecdev); if (err) { ecdev_withdraw(adapter->ecdev); @@ -2868,6 +2873,7 @@ static void igb_remove(struct pci_dev *pdev) if (adapter->ecdev) { ecdev_close(adapter->ecdev); + irq_work_sync(&adapter->ec_watchdog_kicker); ecdev_withdraw(adapter->ecdev); } @@ -4336,8 +4342,16 @@ static void igb_watchdog_task(struct work_struct *work) int i; u32 connsw; + if (adapter->ecdev) + hw->mac.get_link_status = true; + link = igb_has_link(adapter); + if (adapter->ecdev) { + ecdev_set_link(adapter->ecdev, link); + return; + } + if (adapter->flags & IGB_FLAG_NEED_LINK_UPDATE) { if (time_after(jiffies, (adapter->link_check_timeout + HZ))) adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; diff --git a/devices/igb/igb_main-5.10-ethercat.c b/devices/igb/igb_main-5.10-ethercat.c index 0b5dab47..719a03d4 100644 --- a/devices/igb/igb_main-5.10-ethercat.c +++ b/devices/igb/igb_main-5.10-ethercat.c @@ -3045,6 +3045,14 @@ static const struct net_device_ops igb_netdev_ops = { .ndo_xdp_xmit = igb_xdp_xmit, }; +static void ec_kick_watchdog(struct irq_work *work) +{ + struct igb_adapter *adapter = + container_of(work, struct igb_adapter, ec_watchdog_kicker); + + schedule_work(&adapter->watchdog_task); +} + /** * ec_poll - EtherCAT poll routine * @netdev: net device structure @@ -3059,12 +3067,8 @@ void ec_poll(struct net_device *netdev) int budget = 64; if (jiffies - adapter->ec_watchdog_jiffies >= 2 * HZ) { - struct e1000_hw *hw = &adapter->hw; - bool link; - hw->mac.get_link_status = true; - link = igb_has_link(adapter); - ecdev_set_link(adapter->ecdev, link); adapter->ec_watchdog_jiffies = jiffies; + irq_work_queue(&adapter->ec_watchdog_kicker); } for (i = 0; i < adapter->num_q_vectors; i++) { @@ -3560,6 +3564,7 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE); if (adapter->ecdev) { + init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog); err = ecdev_open(adapter->ecdev); if (err) { ecdev_withdraw(adapter->ecdev); @@ -3864,6 +3869,7 @@ static void igb_remove(struct pci_dev *pdev) if (adapter->ecdev) { ecdev_close(adapter->ecdev); + irq_work_sync(&adapter->ec_watchdog_kicker); ecdev_withdraw(adapter->ecdev); } @@ -5525,8 +5531,16 @@ static void igb_watchdog_task(struct work_struct *work) u32 connsw; u16 phy_data, retry_count = 20; + if (adapter->ecdev) + hw->mac.get_link_status = true; + link = igb_has_link(adapter); + if (adapter->ecdev) { + ecdev_set_link(adapter->ecdev, link); + return; + } + if (adapter->flags & IGB_FLAG_NEED_LINK_UPDATE) { if (time_after(jiffies, (adapter->link_check_timeout + HZ))) adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; diff --git a/devices/igb/igb_main-5.14-ethercat.c b/devices/igb/igb_main-5.14-ethercat.c index 29c5656c..483642c6 100644 --- a/devices/igb/igb_main-5.14-ethercat.c +++ b/devices/igb/igb_main-5.14-ethercat.c @@ -3055,6 +3055,14 @@ static const struct net_device_ops igb_netdev_ops = { .ndo_xdp_xmit = igb_xdp_xmit, }; +static void ec_kick_watchdog(struct irq_work *work) +{ + struct igb_adapter *adapter = + container_of(work, struct igb_adapter, ec_watchdog_kicker); + + schedule_work(&adapter->watchdog_task); +} + /** * ec_poll - EtherCAT poll routine * @netdev: net device structure @@ -3069,12 +3077,8 @@ void ec_poll(struct net_device *netdev) int budget = 64; if (jiffies - adapter->ec_watchdog_jiffies >= 2 * HZ) { - struct e1000_hw *hw = &adapter->hw; - bool link; - hw->mac.get_link_status = true; - link = igb_has_link(adapter); - ecdev_set_link(adapter->ecdev, link); adapter->ec_watchdog_jiffies = jiffies; + irq_work_queue(&adapter->ec_watchdog_kicker); } for (i = 0; i < adapter->num_q_vectors; i++) { @@ -3570,6 +3574,7 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE); if (adapter->ecdev) { + init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog); err = ecdev_open(adapter->ecdev); if (err) { ecdev_withdraw(adapter->ecdev); @@ -3874,6 +3879,7 @@ static void igb_remove(struct pci_dev *pdev) if (adapter->ecdev) { ecdev_close(adapter->ecdev); + irq_work_sync(&adapter->ec_watchdog_kicker); ecdev_withdraw(adapter->ecdev); } @@ -5535,8 +5541,16 @@ static void igb_watchdog_task(struct work_struct *work) u32 connsw; u16 phy_data, retry_count = 20; + if (adapter->ecdev) + hw->mac.get_link_status = true; + link = igb_has_link(adapter); + if (adapter->ecdev) { + ecdev_set_link(adapter->ecdev, link); + return; + } + if (adapter->flags & IGB_FLAG_NEED_LINK_UPDATE) { if (time_after(jiffies, (adapter->link_check_timeout + HZ))) adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; diff --git a/devices/igb/igb_main-5.15-ethercat.c b/devices/igb/igb_main-5.15-ethercat.c index 2e93f4be..4d3703a5 100644 --- a/devices/igb/igb_main-5.15-ethercat.c +++ b/devices/igb/igb_main-5.15-ethercat.c @@ -3044,6 +3044,14 @@ static const struct net_device_ops igb_netdev_ops = { .ndo_xdp_xmit = igb_xdp_xmit, }; +static void ec_kick_watchdog(struct irq_work *work) +{ + struct igb_adapter *adapter = + container_of(work, struct igb_adapter, ec_watchdog_kicker); + + schedule_work(&adapter->watchdog_task); +} + /** * ec_poll - EtherCAT poll routine * @netdev: net device structure @@ -3058,12 +3066,8 @@ void ec_poll(struct net_device *netdev) int budget = 64; if (jiffies - adapter->ec_watchdog_jiffies >= 2 * HZ) { - struct e1000_hw *hw = &adapter->hw; - bool link; - hw->mac.get_link_status = true; - link = igb_has_link(adapter); - ecdev_set_link(adapter->ecdev, link); adapter->ec_watchdog_jiffies = jiffies; + irq_work_queue(&adapter->ec_watchdog_kicker); } for (i = 0; i < adapter->num_q_vectors; i++) { @@ -3559,6 +3563,7 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE); if (adapter->ecdev) { + init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog); err = ecdev_open(adapter->ecdev); if (err) { ecdev_withdraw(adapter->ecdev); @@ -3863,6 +3868,7 @@ static void igb_remove(struct pci_dev *pdev) if (adapter->ecdev) { ecdev_close(adapter->ecdev); + irq_work_sync(&adapter->ec_watchdog_kicker); ecdev_withdraw(adapter->ecdev); } @@ -5533,8 +5539,16 @@ static void igb_watchdog_task(struct work_struct *work) u32 connsw; u16 phy_data, retry_count = 20; + if (adapter->ecdev) + hw->mac.get_link_status = true; + link = igb_has_link(adapter); + if (adapter->ecdev) { + ecdev_set_link(adapter->ecdev, link); + return; + } + if (adapter->flags & IGB_FLAG_NEED_LINK_UPDATE) { if (time_after(jiffies, (adapter->link_check_timeout + HZ))) adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; diff --git a/devices/igb/igb_main-6.1-ethercat.c b/devices/igb/igb_main-6.1-ethercat.c index 13b860ce..8c1c1165 100644 --- a/devices/igb/igb_main-6.1-ethercat.c +++ b/devices/igb/igb_main-6.1-ethercat.c @@ -3070,6 +3070,14 @@ static const struct net_device_ops igb_netdev_ops = { .ndo_xdp_xmit = igb_xdp_xmit, }; +static void ec_kick_watchdog(struct irq_work *work) +{ + struct igb_adapter *adapter = + container_of(work, struct igb_adapter, ec_watchdog_kicker); + + schedule_work(&adapter->watchdog_task); +} + /** * ec_poll - EtherCAT poll routine * @netdev: net device structure @@ -3084,12 +3092,8 @@ void ec_poll(struct net_device *netdev) int budget = 64; if (jiffies - adapter->ec_watchdog_jiffies >= 2 * HZ) { - struct e1000_hw *hw = &adapter->hw; - bool link; - hw->mac.get_link_status = true; - link = igb_has_link(adapter); - ecdev_set_link(adapter->ecdev, link); adapter->ec_watchdog_jiffies = jiffies; + irq_work_queue(&adapter->ec_watchdog_kicker); } for (i = 0; i < adapter->num_q_vectors; i++) { @@ -3578,6 +3582,7 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE); if (adapter->ecdev) { + init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog); err = ecdev_open(adapter->ecdev); if (err) { ecdev_withdraw(adapter->ecdev); @@ -3890,6 +3895,7 @@ static void igb_remove(struct pci_dev *pdev) if (adapter->ecdev) { ecdev_close(adapter->ecdev); + irq_work_sync(&adapter->ec_watchdog_kicker); ecdev_withdraw(adapter->ecdev); } @@ -5566,8 +5572,16 @@ static void igb_watchdog_task(struct work_struct *work) u32 connsw; u16 phy_data, retry_count = 20; + if (adapter->ecdev) + hw->mac.get_link_status = true; + link = igb_has_link(adapter); + if (adapter->ecdev) { + ecdev_set_link(adapter->ecdev, link); + return; + } + if (adapter->flags & IGB_FLAG_NEED_LINK_UPDATE) { if (time_after(jiffies, (adapter->link_check_timeout + HZ))) adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; diff --git a/devices/igc/igc-6.4-ethercat.h b/devices/igc/igc-6.4-ethercat.h index 52ad0a95..5f01efdf 100644 --- a/devices/igc/igc-6.4-ethercat.h +++ b/devices/igc/igc-6.4-ethercat.h @@ -5,6 +5,7 @@ #define _IGC_H_ #include "../ecdev.h" +#include #include #include #include @@ -268,6 +269,7 @@ struct igc_adapter { /* EtherCAT device variables */ ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; void igc_up(struct igc_adapter *adapter); diff --git a/devices/igc/igc-6.6-ethercat.h b/devices/igc/igc-6.6-ethercat.h index 18efb14e..dc1b5813 100644 --- a/devices/igc/igc-6.6-ethercat.h +++ b/devices/igc/igc-6.6-ethercat.h @@ -5,6 +5,7 @@ #define _IGC_H_ #include "../ecdev.h" +#include #include #include #include @@ -283,6 +284,7 @@ struct igc_adapter { /* EtherCAT device variables */ ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; void igc_up(struct igc_adapter *adapter); diff --git a/devices/igc/igc_main-6.4-ethercat.c b/devices/igc/igc_main-6.4-ethercat.c index 7c6b5dc8..ef1e34fe 100644 --- a/devices/igc/igc_main-6.4-ethercat.c +++ b/devices/igc/igc_main-6.4-ethercat.c @@ -5576,8 +5576,16 @@ static void igc_watchdog_task(struct work_struct *work) u32 link; int i; + if (adapter->ecdev) + hw->mac.get_link_status = true; + link = igc_has_link(adapter); + if (adapter->ecdev) { + ecdev_set_link(adapter->ecdev, link); + return; + } + if (adapter->flags & IGC_FLAG_NEED_LINK_UPDATE) { if (time_after(jiffies, (adapter->link_check_timeout + HZ))) adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE; @@ -6537,6 +6545,14 @@ static const struct net_device_ops igc_netdev_ops = { .ndo_xsk_wakeup = igc_xsk_wakeup, }; +static void ec_kick_watchdog(struct irq_work *work) +{ + struct igc_adapter *adapter = + container_of(work, struct igc_adapter, ec_watchdog_kicker); + + schedule_work(&adapter->watchdog_task); +} + /** * ec_poll - EtherCAT poll routine * @netdev: net device structure @@ -6551,13 +6567,8 @@ void ec_poll(struct net_device *netdev) int budget = 64; if (jiffies - adapter->ec_watchdog_jiffies >= 2 * HZ) { - struct igc_hw *hw = &adapter->hw; - - bool link; - hw->mac.get_link_status = true; - link = igc_has_link(adapter); - ecdev_set_link(adapter->ecdev, link); adapter->ec_watchdog_jiffies = jiffies; + irq_work_queue(&adapter->ec_watchdog_kicker); } for (i = 0; i < adapter->num_q_vectors; i++) { @@ -6910,6 +6921,7 @@ static int igc_probe(struct pci_dev *pdev, adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE); if (adapter->ecdev) { + init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog); err = ecdev_open(adapter->ecdev); if (err) { ecdev_withdraw(adapter->ecdev); @@ -6976,6 +6988,7 @@ static void igc_remove(struct pci_dev *pdev) if (adapter->ecdev) { ecdev_close(adapter->ecdev); + irq_work_sync(&adapter->irq_work); ecdev_withdraw(adapter->ecdev); } diff --git a/devices/igc/igc_main-6.6-ethercat.c b/devices/igc/igc_main-6.6-ethercat.c index 7faa0df1..81e911ad 100644 --- a/devices/igc/igc_main-6.6-ethercat.c +++ b/devices/igc/igc_main-6.6-ethercat.c @@ -5641,8 +5641,16 @@ static void igc_watchdog_task(struct work_struct *work) u32 link; int i; + if (adapter->ecdev) + hw->mac.get_link_status = true; + link = igc_has_link(adapter); + if (adapter->ecdev) { + ecdev_set_link(adapter->ecdev, link); + return; + } + if (adapter->flags & IGC_FLAG_NEED_LINK_UPDATE) { if (time_after(jiffies, (adapter->link_check_timeout + HZ))) adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE; @@ -6657,6 +6665,14 @@ static const struct net_device_ops igc_netdev_ops = { .ndo_xsk_wakeup = igc_xsk_wakeup, }; +static void ec_kick_watchdog(struct irq_work *work) +{ + struct igc_adapter *adapter = + container_of(work, struct igc_adapter, ec_watchdog_kicker); + + schedule_work(&adapter->watchdog_task); +} + /** * ec_poll - EtherCAT poll routine * @netdev: net device structure @@ -6671,13 +6687,8 @@ void ec_poll(struct net_device *netdev) int budget = 64; if (jiffies - adapter->ec_watchdog_jiffies >= 2 * HZ) { - struct igc_hw *hw = &adapter->hw; - - bool link; - hw->mac.get_link_status = true; - link = igc_has_link(adapter); - ecdev_set_link(adapter->ecdev, link); adapter->ec_watchdog_jiffies = jiffies; + irq_work_queue(&adapter->ec_watchdog_kicker); } for (i = 0; i < adapter->num_q_vectors; i++) { @@ -7050,6 +7061,7 @@ static int igc_probe(struct pci_dev *pdev, adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE); if (adapter->ecdev) { + init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog); err = ecdev_open(adapter->ecdev); if (err) { ecdev_withdraw(adapter->ecdev); @@ -7116,6 +7128,7 @@ static void igc_remove(struct pci_dev *pdev) if (adapter->ecdev) { ecdev_close(adapter->ecdev); + irq_work_sync(&adapter->irq_work); ecdev_withdraw(adapter->ecdev); } diff --git a/devices/r8169/r8169_main-5.10-ethercat.c b/devices/r8169/r8169_main-5.10-ethercat.c index 91595421..b00c04af 100644 --- a/devices/r8169/r8169_main-5.10-ethercat.c +++ b/devices/r8169/r8169_main-5.10-ethercat.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -35,7 +36,7 @@ #include "../ecdev.h" -#define MODULENAME "r8169" +#define MODULENAME "ec_r8169" #define FIRMWARE_8168D_1 "rtl_nic/rtl8168d-1.fw" #define FIRMWARE_8168D_2 "rtl_nic/rtl8168d-2.fw" @@ -633,6 +634,7 @@ struct rtl8169_private { ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; typedef void (*rtl_generic_fct)(struct rtl8169_private *tp); @@ -5079,6 +5081,7 @@ static void rtl_remove_one(struct pci_dev *pdev) if (tp->ecdev) { ecdev_close(tp->ecdev); + irq_work_sync(&tp->ec_watchdog_kicker); ecdev_withdraw(tp->ecdev); } else { unregister_netdev(tp->dev); @@ -5369,6 +5372,14 @@ done: rtl_rar_set(tp, mac_addr); } +static void ec_kick_watchdog(struct irq_work *work) +{ + struct rtl8169_private *tp = + container_of(work, struct rtl8169_private, ec_watchdog_kicker); + + phy_mac_interrupt(tp->phydev); +} + static void ec_poll(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -5387,8 +5398,7 @@ static void ec_poll(struct net_device *dev) rtl_rx(dev, tp, 100); if (status & LinkChg) - phy_mac_interrupt(tp->phydev); - + irq_work_queue(&tp->ec_watchdog_kicker); rtl_ack_events(tp, status); } @@ -5588,6 +5598,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pm_runtime_put_sync(&pdev->dev); if (tp->ecdev) { + init_irq_work(&tp->ec_watchdog_kicker, ec_kick_watchdog); rc = ecdev_open(tp->ecdev); if (rc) { ecdev_withdraw(tp->ecdev); diff --git a/devices/r8169/r8169_main-5.14-ethercat.c b/devices/r8169/r8169_main-5.14-ethercat.c index 58ed3d95..51c54f47 100644 --- a/devices/r8169/r8169_main-5.14-ethercat.c +++ b/devices/r8169/r8169_main-5.14-ethercat.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -653,6 +654,7 @@ struct rtl8169_private { ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; typedef void (*rtl_generic_fct)(struct rtl8169_private *tp); @@ -5048,6 +5050,7 @@ static void rtl_remove_one(struct pci_dev *pdev) if (tp->ecdev) { ecdev_close(tp->ecdev); + irq_work_sync(&tp->ec_watchdog_kicker); ecdev_withdraw(tp->ecdev); } else { unregister_netdev(tp->dev); @@ -5338,6 +5341,14 @@ done: rtl_rar_set(tp, mac_addr); } +static void ec_kick_watchdog(struct irq_work *work) +{ + struct rtl8169_private *tp = + container_of(work, struct rtl8169_private, ec_watchdog_kicker); + + phy_mac_interrupt(tp->phydev); +} + static void ec_poll(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -5356,7 +5367,7 @@ static void ec_poll(struct net_device *dev) rtl_rx(dev, tp, 100); if (status & LinkChg) - phy_mac_interrupt(tp->phydev); + irq_work_queue(&tp->ec_watchdog_kicker); rtl_ack_events(tp, status); } @@ -5560,6 +5571,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pm_runtime_put_sync(&pdev->dev); if (tp->ecdev) { + init_irq_work(&tp->ec_watchdog_kicker, ec_kick_watchdog); rc = ecdev_open(tp->ecdev); if (rc) { ecdev_withdraw(tp->ecdev); diff --git a/devices/r8169/r8169_main-5.15-ethercat.c b/devices/r8169/r8169_main-5.15-ethercat.c index f2bc5230..df956257 100644 --- a/devices/r8169/r8169_main-5.15-ethercat.c +++ b/devices/r8169/r8169_main-5.15-ethercat.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -641,6 +642,7 @@ struct rtl8169_private { ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; typedef void (*rtl_generic_fct)(struct rtl8169_private *tp); @@ -5041,6 +5043,7 @@ static void rtl_remove_one(struct pci_dev *pdev) if (tp->ecdev) { ecdev_close(tp->ecdev); + irq_work_sync(&tp->ec_watchdog_kicker); ecdev_withdraw(tp->ecdev); } else { unregister_netdev(tp->dev); @@ -5331,6 +5334,14 @@ done: rtl_rar_set(tp, mac_addr); } +static void ec_kick_watchdog(struct irq_work *work) +{ + struct rtl8169_private *tp = + container_of(work, struct rtl8169_private, ec_watchdog_kicker); + + phy_mac_interrupt(tp->phydev); +} + static void ec_poll(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -5349,7 +5360,7 @@ static void ec_poll(struct net_device *dev) rtl_rx(dev, tp, 100); if (status & LinkChg) - phy_mac_interrupt(tp->phydev); + irq_work_queue(&tp->ec_watchdog_kicker); rtl_ack_events(tp, status); } @@ -5552,6 +5563,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pm_runtime_put_sync(&pdev->dev); if (tp->ecdev) { + init_irq_work(&tp->ec_watchdog_kicker, ec_kick_watchdog); rc = ecdev_open(tp->ecdev); if (rc) { ecdev_withdraw(tp->ecdev); diff --git a/devices/r8169/r8169_main-6.1-ethercat.c b/devices/r8169/r8169_main-6.1-ethercat.c index 82405979..06e02bc6 100644 --- a/devices/r8169/r8169_main-6.1-ethercat.c +++ b/devices/r8169/r8169_main-6.1-ethercat.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -630,6 +631,7 @@ struct rtl8169_private { ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; typedef void (*rtl_generic_fct)(struct rtl8169_private *tp); @@ -4919,6 +4921,7 @@ static void rtl_remove_one(struct pci_dev *pdev) if (tp->ecdev) { ecdev_close(tp->ecdev); + irq_work_sync(&tp->ec_watchdog_kicker); ecdev_withdraw(tp->ecdev); } else { unregister_netdev(tp->dev); @@ -5189,6 +5192,14 @@ static bool rtl_aspm_is_safe(struct rtl8169_private *tp) return false; } +static void ec_kick_watchdog(struct irq_work *work) +{ + struct rtl8169_private *tp = + container_of(work, struct rtl8169_private, ec_watchdog_kicker); + + phy_mac_interrupt(tp->phydev); +} + static void ec_poll(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -5207,7 +5218,7 @@ static void ec_poll(struct net_device *dev) rtl_rx(dev, tp, 100); if (status & LinkChg) - phy_mac_interrupt(tp->phydev); + irq_work_queue(&tp->ec_watchdog_kicker); rtl_ack_events(tp, status); } @@ -5416,6 +5427,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pm_runtime_put_sync(&pdev->dev); if (tp->ecdev) { + init_irq_work(&tp->ec_watchdog_kicker, ec_kick_watchdog); rc = ecdev_open(tp->ecdev); if (rc) { ecdev_withdraw(tp->ecdev); diff --git a/examples/Makefile.am b/examples/Makefile.am index 7ac06ecd..d73d0977 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -40,6 +40,11 @@ SUBDIRS += \ xenomai \ xenomai_posix endif +if ENABLE_XENOMAI_V3 +SUBDIRS += \ + xenomai \ + xenomai_posix +endif if ENABLE_RTAI SUBDIRS += \ diff --git a/examples/rtai_rtdm/main.c b/examples/rtai_rtdm/main.c index 577310f7..d7570efc 100644 --- a/examples/rtai_rtdm/main.c +++ b/examples/rtai_rtdm/main.c @@ -38,7 +38,7 @@ RT_TASK *task; const static unsigned int cycle_us = 1000; /* 1 ms */ -static int run = 1; +static volatile sig_atomic_t run = 1; /****************************************************************************/ diff --git a/examples/rtai_rtdm_dc/main.c b/examples/rtai_rtdm_dc/main.c index 61fa4ae4..1676cae4 100644 --- a/examples/rtai_rtdm_dc/main.c +++ b/examples/rtai_rtdm_dc/main.c @@ -38,7 +38,7 @@ RT_TASK *task; static unsigned int cycle_ns = 1000000; /* 1 ms */ -static int run = 1; +static volatile sig_atomic_t run = 1; /****************************************************************************/ diff --git a/examples/user/main.c b/examples/user/main.c index 7feffc74..8c7083a3 100644 --- a/examples/user/main.c +++ b/examples/user/main.c @@ -100,7 +100,7 @@ static unsigned int blink = 0; // Analog in -------------------------- -static ec_pdo_entry_info_t el3102_pdo_entries[] = { +static const ec_pdo_entry_info_t el3102_pdo_entries[] = { {0x3101, 1, 8}, // channel 1 status {0x3101, 2, 16}, // channel 1 value {0x3102, 1, 8}, // channel 2 status @@ -109,12 +109,12 @@ static ec_pdo_entry_info_t el3102_pdo_entries[] = { {0x6401, 2, 16} // channel 2 value (alt.) }; -static ec_pdo_info_t el3102_pdos[] = { +static const ec_pdo_info_t el3102_pdos[] = { {0x1A00, 2, el3102_pdo_entries}, {0x1A01, 2, el3102_pdo_entries + 2} }; -static ec_sync_info_t el3102_syncs[] = { +static const ec_sync_info_t el3102_syncs[] = { {2, EC_DIR_OUTPUT}, {3, EC_DIR_INPUT, 2, el3102_pdos}, {0xff} @@ -122,17 +122,17 @@ static ec_sync_info_t el3102_syncs[] = { // Analog out ------------------------- -static ec_pdo_entry_info_t el4102_pdo_entries[] = { +static const ec_pdo_entry_info_t el4102_pdo_entries[] = { {0x3001, 1, 16}, // channel 1 value {0x3002, 1, 16}, // channel 2 value }; -static ec_pdo_info_t el4102_pdos[] = { +static const ec_pdo_info_t el4102_pdos[] = { {0x1600, 1, el4102_pdo_entries}, {0x1601, 1, el4102_pdo_entries + 1} }; -static ec_sync_info_t el4102_syncs[] = { +static const ec_sync_info_t el4102_syncs[] = { {2, EC_DIR_OUTPUT, 2, el4102_pdos}, {3, EC_DIR_INPUT}, {0xff} @@ -140,21 +140,21 @@ static ec_sync_info_t el4102_syncs[] = { // Digital out ------------------------ -static ec_pdo_entry_info_t el2004_channels[] = { +static const ec_pdo_entry_info_t el2004_channels[] = { {0x3001, 1, 1}, // Value 1 {0x3001, 2, 1}, // Value 2 {0x3001, 3, 1}, // Value 3 {0x3001, 4, 1} // Value 4 }; -static ec_pdo_info_t el2004_pdos[] = { +static const ec_pdo_info_t el2004_pdos[] = { {0x1600, 1, &el2004_channels[0]}, {0x1601, 1, &el2004_channels[1]}, {0x1602, 1, &el2004_channels[2]}, {0x1603, 1, &el2004_channels[3]} }; -static ec_sync_info_t el2004_syncs[] = { +static const ec_sync_info_t el2004_syncs[] = { {0, EC_DIR_OUTPUT, 4, el2004_pdos}, {1, EC_DIR_INPUT}, {0xff} diff --git a/examples/xenomai/Makefile.am b/examples/xenomai/Makefile.am index 5792e1ef..ef20fb2d 100644 --- a/examples/xenomai/Makefile.am +++ b/examples/xenomai/Makefile.am @@ -25,13 +25,26 @@ ec_xenomai_example_SOURCES = main.c ec_xenomai_example_CFLAGS = \ -Wall \ - -I$(top_srcdir)/include \ + -I$(top_srcdir)/include + +ec_xenomai_example_LDFLAGS = \ + -L$(top_builddir)/lib/.libs -lethercat_rtdm + +if ENABLE_XENOMAI_V3 +ec_xenomai_example_CFLAGS += \ + -DXENOMAI_API_V3 \ + $(XENOMAI_ALCHEMY_CFLAGS) + +ec_xenomai_example_LDFLAGS += \ + $(XENOMAI_ALCHEMY_LDFLAGS) +else +ec_xenomai_example_CFLAGS += \ $(XENOMAI_NATIVE_CFLAGS) \ $(XENOMAI_RTDM_CFLAGS) -ec_xenomai_example_LDFLAGS = \ - -L$(top_builddir)/lib/.libs -lethercat_rtdm \ +ec_xenomai_example_LDFLAGS += \ $(XENOMAI_NATIVE_LDFLAGS) \ $(XENOMAI_RTDM_LDFLAGS) +endif #------------------------------------------------------------------------------ diff --git a/examples/xenomai/main.c b/examples/xenomai/main.c index e76dff20..c322e2ca 100644 --- a/examples/xenomai/main.c +++ b/examples/xenomai/main.c @@ -29,19 +29,25 @@ #include #include #include +#ifdef XENOMAI_API_V3 +#include +#include +enum {T_FPU = 0}; +#else #include #include #include #include #include #include +#endif #include #include "ecrt.h" RT_TASK my_task; -static int run = 1; +static volatile sig_atomic_t run = 1; /****************************************************************************/ @@ -84,14 +90,14 @@ const static ec_pdo_entry_reg_t domain1_regs[] = { * Revision number: 0x00100000 */ -ec_pdo_entry_info_t slave_1_pdo_entries[] = { +const ec_pdo_entry_info_t slave_1_pdo_entries[] = { {0x7000, 0x01, 1}, /* Output */ {0x7010, 0x01, 1}, /* Output */ {0x7020, 0x01, 1}, /* Output */ {0x7030, 0x01, 1}, /* Output */ }; -ec_pdo_info_t slave_1_pdos[] = { +const ec_pdo_info_t slave_1_pdos[] = { {0x1600, 1, slave_1_pdo_entries + 0}, /* Channel 1 */ {0x1601, 1, slave_1_pdo_entries + 1}, /* Channel 2 */ {0x1602, 1, slave_1_pdo_entries + 2}, /* Channel 3 */ @@ -201,8 +207,10 @@ int main(int argc, char *argv[]) ec_slave_config_t *sc; int ret; +#ifndef XENOMAI_API_V3 /* Perform auto-init of rt_print buffers if the task doesn't do so */ rt_print_auto_init(1); +#endif signal(SIGTERM, signal_handler); signal(SIGINT, signal_handler); diff --git a/examples/xenomai_posix/Makefile.am b/examples/xenomai_posix/Makefile.am index 5d3962de..994750ee 100644 --- a/examples/xenomai_posix/Makefile.am +++ b/examples/xenomai_posix/Makefile.am @@ -29,6 +29,11 @@ ec_xenomai_posix_example_CFLAGS = \ $(XENOMAI_POSIX_CFLAGS) \ $(XENOMAI_RTDM_CFLAGS) +if ENABLE_XENOMAI_V3 +ec_xenomai_posix_example_CFLAGS += \ + -DXENOMAI_API_V3 +endif + ec_xenomai_posix_example_LDFLAGS = \ -L$(top_builddir)/lib/.libs -lethercat_rtdm \ $(XENOMAI_POSIX_LDFLAGS) \ diff --git a/examples/xenomai_posix/main.c b/examples/xenomai_posix/main.c index 28f9254f..9e18008b 100644 --- a/examples/xenomai_posix/main.c +++ b/examples/xenomai_posix/main.c @@ -32,8 +32,10 @@ #include #include +#ifndef XENOMAI_API_V3 #include #include +#endif #include "ecrt.h" @@ -43,7 +45,7 @@ static unsigned int cycle_us = 1000; /* 1 ms */ static pthread_t cyclic_thread; -static int run = 1; +static volatile sig_atomic_t run = 1; /****************************************************************************/ @@ -86,21 +88,21 @@ const static ec_pdo_entry_reg_t domain1_regs[] = { * Revision number: 0x00100000 */ -ec_pdo_entry_info_t slave_1_pdo_entries[] = { +const ec_pdo_entry_info_t slave_1_pdo_entries[] = { {0x7000, 0x01, 1}, /* Output */ {0x7010, 0x01, 1}, /* Output */ {0x7020, 0x01, 1}, /* Output */ {0x7030, 0x01, 1}, /* Output */ }; -ec_pdo_info_t slave_1_pdos[] = { +const ec_pdo_info_t slave_1_pdos[] = { {0x1600, 1, slave_1_pdo_entries + 0}, /* Channel 1 */ {0x1601, 1, slave_1_pdo_entries + 1}, /* Channel 2 */ {0x1602, 1, slave_1_pdo_entries + 2}, /* Channel 3 */ {0x1603, 1, slave_1_pdo_entries + 3}, /* Channel 4 */ }; -ec_sync_info_t slave_1_syncs[] = { +const ec_sync_info_t slave_1_syncs[] = { {0, EC_DIR_OUTPUT, 4, slave_1_pdos + 0, EC_WD_ENABLE}, {0xff} }; @@ -271,7 +273,7 @@ int main(int argc, char *argv[]) pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE); pthread_attr_setinheritsched(&thattr, PTHREAD_EXPLICIT_SCHED); pthread_attr_setschedpolicy(&thattr, SCHED_FIFO); - pthread_setschedparam(cyclic_thread, SCHED_FIFO, ¶m); + pthread_attr_setschedparam(&thattr, ¶m); ret = pthread_create(&cyclic_thread, &thattr, &my_thread, NULL); if (ret) { diff --git a/include/ecrt.h b/include/ecrt.h index 7bc60acc..bb3591e3 100644 --- a/include/ecrt.h +++ b/include/ecrt.h @@ -180,7 +180,7 @@ /** EtherCAT realtime interface minor version number. */ -#define ECRT_VER_MINOR 5 +#define ECRT_VER_MINOR 6 /** EtherCAT realtime interface version word generator. */ @@ -409,10 +409,10 @@ typedef struct { * \see ecrt_master(). */ typedef struct { - unsigned int slave_count; /**< Number of slaves in the bus. */ - unsigned int link_up : 1; /**< \a true, if the network link is up. */ - uint8_t scan_busy; /**< \a true, while the master is scanning the bus */ - uint64_t app_time; /**< Application time. */ + unsigned int slave_count; /**< Number of slaves in the bus. */ + unsigned int link_up : 1; /**< \a true, if the network link is up. */ + uint8_t scan_busy; /**< \a true, while the master is scanning the bus */ + uint64_t app_time; /**< Application time. */ } ec_master_info_t; /****************************************************************************/ @@ -424,10 +424,11 @@ typedef struct { * \see ecrt_master_scan_progress(). */ typedef struct { - unsigned int slave_count; /**< Number of slaves detected. */ - unsigned int scan_index; /**< Index of the slave that is currently scanned. - If it is less than the \a slave_count, the - network scan is in progress. */ + unsigned int slave_count; /**< Number of slaves detected. */ + unsigned int scan_index; /**< Index of the slave that is currently + scanned. If it is less than the \a + slave_count, the network scan is in progress. + */ } ec_master_scan_progress_t; /****************************************************************************/ @@ -559,9 +560,9 @@ typedef struct { Zero means, that the default mapping shall be used (this can only be done if the slave is present at bus configuration time). */ - ec_pdo_entry_info_t *entries; /**< Array of PDO entries to map. Can either - be \a NULL, or must contain at - least \a n_entries values. */ + ec_pdo_entry_info_t const *entries; /**< Array of PDO entries to map. Can + either be \a NULL, or must contain + at least \a n_entries values. */ } ec_pdo_info_t; /****************************************************************************/ @@ -578,8 +579,8 @@ typedef struct { but can also be \a 0xff to mark the end of the list. */ ec_direction_t dir; /**< Sync manager direction. */ unsigned int n_pdos; /**< Number of PDOs in \a pdos. */ - ec_pdo_info_t *pdos; /**< Array with PDOs to assign. This must contain - at least \a n_pdos PDOs. */ + ec_pdo_info_t const *pdos; /**< Array with PDOs to assign. This must + contain at least \a n_pdos PDOs. */ ec_watchdog_mode_t watchdog_mode; /**< Watchdog mode. */ } ec_sync_info_t; @@ -601,8 +602,8 @@ typedef struct { (byte-)offset in the process data. */ unsigned int *bit_position; /**< Pointer to a variable to store a bit position (0-7) within the \a offset. Can be - NULL, in which case an error is raised if the - PDO entry does not byte-align. */ + NULL, in which case an error is raised if + the PDO entry does not byte-align. */ } ec_pdo_entry_reg_t; /****************************************************************************/ @@ -835,7 +836,7 @@ EC_PUBLIC_API int ecrt_master( * * \return 0 in case of success, else < 0 */ -int ecrt_master_scan_progress( +EC_PUBLIC_API int ecrt_master_scan_progress( ec_master_t *master, /**< EtherCAT master */ ec_master_scan_progress_t *progress /**< Structure that will output the progress information. */ @@ -927,7 +928,7 @@ EC_PUBLIC_API int ecrt_master_sdo_download( uint16_t slave_position, /**< Slave position. */ uint16_t index, /**< Index of the SDO. */ uint8_t subindex, /**< Subindex of the SDO. */ - uint8_t *data, /**< Data buffer to download. */ + const uint8_t *data, /**< Data buffer to download. */ size_t data_size, /**< Size of the data buffer. */ uint32_t *abort_code /**< Abort code of the SDO download. */ ); @@ -946,7 +947,7 @@ EC_PUBLIC_API int ecrt_master_sdo_download_complete( ec_master_t *master, /**< EtherCAT master. */ uint16_t slave_position, /**< Slave position. */ uint16_t index, /**< Index of the SDO. */ - uint8_t *data, /**< Data buffer to download. */ + const uint8_t *data, /**< Data buffer to download. */ size_t data_size, /**< Size of the data buffer. */ uint32_t *abort_code /**< Abort code of the SDO download. */ ); @@ -984,7 +985,7 @@ EC_PUBLIC_API int ecrt_master_write_idn( uint16_t slave_position, /**< Slave position. */ uint8_t drive_no, /**< Drive number. */ uint16_t idn, /**< SoE IDN (see ecrt_slave_config_idn()). */ - uint8_t *data, /**< Pointer to data to write. */ + const uint8_t *data, /**< Pointer to data to write. */ size_t data_size, /**< Size of data to write. */ uint16_t *error_code /**< Pointer to variable, where an SoE error code can be stored. */ @@ -1169,6 +1170,9 @@ EC_PUBLIC_API void ecrt_master_sync_reference_clock( * The reference clock will by synchronized to the time passed in the * sync_time parameter. * + * Has to be called by the application after ecrt_master_activate() + * has returned. + * * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_master_sync_reference_clock_to( @@ -1180,6 +1184,9 @@ EC_PUBLIC_API void ecrt_master_sync_reference_clock_to( * * All slave clocks synchronized to the reference clock. * + * Has to be called by the application after ecrt_master_activate() + * has returned. + * * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_master_sync_slave_clocks( @@ -1203,7 +1210,7 @@ EC_PUBLIC_API void ecrt_master_sync_slave_clocks( * \retval -EIO Slave synchronization datagram was not received. */ EC_PUBLIC_API int ecrt_master_reference_clock_time( - ec_master_t *master, /**< EtherCAT master. */ + const ec_master_t *master, /**< EtherCAT master. */ uint32_t *time /**< Pointer to store the queried system time. */ ); @@ -1230,7 +1237,7 @@ EC_PUBLIC_API void ecrt_master_sync_monitor_queue( * \return Upper estimation of the maximum time difference in ns. */ EC_PUBLIC_API uint32_t ecrt_master_sync_monitor_process( - ec_master_t *master /**< EtherCAT master. */ + const ec_master_t *master /**< EtherCAT master. */ ); /** Retry configuring slaves. @@ -1239,6 +1246,8 @@ EC_PUBLIC_API uint32_t ecrt_master_sync_monitor_process( * OP state. In general, this is not necessary, because it is automatically * done by the master. But with special slaves, that can be reconfigured by * the vendor during runtime, it can be useful. + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_master_reset( ec_master_t *master /**< EtherCAT master. */ @@ -1654,7 +1663,7 @@ EC_PUBLIC_API int ecrt_slave_config_emerg_clear( * \return Number of overruns since last clear, or negative error code. */ EC_PUBLIC_API int ecrt_slave_config_emerg_overruns( - ec_slave_config_t *sc /**< Slave configuration. */ + const ec_slave_config_t *sc /**< Slave configuration. */ ); /** Create an SDO request to exchange SDOs during realtime operation. @@ -1684,7 +1693,7 @@ EC_PUBLIC_API ec_sdo_request_t *ecrt_slave_config_create_sdo_request( * * \return New SoE request, or NULL on error. */ -ec_soe_request_t *ecrt_slave_config_create_soe_request( +EC_PUBLIC_API ec_soe_request_t *ecrt_slave_config_create_soe_request( ec_slave_config_t *sc, /**< Slave configuration. */ uint8_t drive_no, /**< Drive number. */ uint16_t idn, /**< Sercos ID-Number. */ @@ -2022,8 +2031,8 @@ EC_PUBLIC_API void ecrt_sdo_request_timeout( * * This function returns a pointer to the request's internal SDO data memory. * - * - After a read operation was successful, integer data can be evaluated using - * the EC_READ_*() macros as usual. Example: + * - After a read operation was successful, integer data can be evaluated + * using the EC_READ_*() macros as usual. Example: * \code * uint16_t value = EC_READ_U16(ecrt_sdo_request_data(sdo))); * \endcode @@ -2042,7 +2051,7 @@ EC_PUBLIC_API void ecrt_sdo_request_timeout( * \return Pointer to the internal SDO data memory. */ EC_PUBLIC_API uint8_t *ecrt_sdo_request_data( - ec_sdo_request_t *req /**< SDO request. */ + const ec_sdo_request_t *req /**< SDO request. */ ); /** Returns the current SDO data size. @@ -2103,7 +2112,7 @@ EC_PUBLIC_API void ecrt_sdo_request_read( * ecrt_soe_request_state() returns EC_REQUEST_BUSY, this may lead to * unexpected results. */ -void ecrt_soe_request_idn( +EC_PUBLIC_API void ecrt_soe_request_idn( ec_soe_request_t *req, /**< IDN request. */ uint8_t drive_no, /**< SDO index. */ uint16_t idn /**< SoE IDN. */ @@ -2117,7 +2126,7 @@ void ecrt_soe_request_idn( * The timeout is permanently stored in the request object and is valid until * the next call of this method. */ -void ecrt_soe_request_timeout( +EC_PUBLIC_API void ecrt_soe_request_timeout( ec_soe_request_t *req, /**< SoE request. */ uint32_t timeout /**< Timeout in milliseconds. Zero means no timeout. */ @@ -2146,8 +2155,8 @@ void ecrt_soe_request_timeout( * * \return Pointer to the internal IDN data memory. */ -uint8_t *ecrt_soe_request_data( - ec_soe_request_t *req /**< SoE request. */ +EC_PUBLIC_API uint8_t *ecrt_soe_request_data( + const ec_soe_request_t *req /**< SoE request. */ ); /** Returns the current IDN data size. @@ -2158,7 +2167,7 @@ uint8_t *ecrt_soe_request_data( * * \return IDN data size in bytes. */ -size_t ecrt_soe_request_data_size( +EC_PUBLIC_API size_t ecrt_soe_request_data_size( const ec_soe_request_t *req /**< SoE request. */ ); @@ -2166,8 +2175,9 @@ size_t ecrt_soe_request_data_size( * * \return Request state. */ -ec_request_state_t ecrt_soe_request_state( - ec_soe_request_t *req /**< SoE request. */ +EC_PUBLIC_API ec_request_state_t ecrt_soe_request_state( + ec_soe_request_t *req /**< SoE request. Not const, because the + internal data size may be updated. */ ); /** Schedule an SoE IDN write operation. @@ -2175,7 +2185,7 @@ ec_request_state_t ecrt_soe_request_state( * \attention This method may not be called while ecrt_soe_request_state() * returns EC_REQUEST_BUSY. */ -void ecrt_soe_request_write( +EC_PUBLIC_API void ecrt_soe_request_write( ec_soe_request_t *req /**< SoE request. */ ); @@ -2188,7 +2198,7 @@ void ecrt_soe_request_write( * ecrt_soe_request_data() must be considered as invalid while * ecrt_soe_request_state() returns EC_REQUEST_BUSY. */ -void ecrt_soe_request_read( +EC_PUBLIC_API void ecrt_soe_request_read( ec_soe_request_t *req /**< SoE request. */ ); @@ -2244,7 +2254,7 @@ EC_PUBLIC_API void ecrt_voe_handler_received_header( * \return Pointer to the internal memory. */ EC_PUBLIC_API uint8_t *ecrt_voe_handler_data( - ec_voe_handler_t *voe /**< VoE handler. */ + const ec_voe_handler_t *voe /**< VoE handler. */ ); /** Returns the current data size. @@ -2346,22 +2356,16 @@ EC_PUBLIC_API ec_request_state_t ecrt_voe_handler_execute( * \return Pointer to the internal memory. */ EC_PUBLIC_API uint8_t *ecrt_reg_request_data( - ec_reg_request_t *req /**< Register request. */ + const ec_reg_request_t *req /**< Register request. */ ); /** Get the current state of the register request. * * \return Request state. */ -#ifdef __KERNEL__ ec_request_state_t ecrt_reg_request_state( const ec_reg_request_t *req /**< Register request. */ ); -#else -EC_PUBLIC_API ec_request_state_t ecrt_reg_request_state( - ec_reg_request_t *req /**< Register request. */ - ); -#endif /** Schedule an register write operation. * diff --git a/lib/Makefile.am b/lib/Makefile.am index aa7ad970..e64c7c30 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -70,15 +70,18 @@ libethercat_la_CFLAGS = -fno-strict-aliasing -Wall -I$(top_srcdir) \ # 3:0:2 # libethercat_la_LDFLAGS = -version-info 3:0:2 \ + -Wl,--version-script=$(srcdir)/libethercat.map \ -fvisibility=hidden +libethercat_la_DEPENDENCIES = libethercat.map + pkgconfig_DATA = libethercat.pc cmakedir = $(libdir)/cmake/ethercat cmake_DATA = ethercat-config.cmake -EXTRA_DIST = ethercat-config.cmake.in +EXTRA_DIST = ethercat-config.cmake.in libethercat.map CLEANFILES = $(cmake_DATA) @@ -90,7 +93,7 @@ if ENABLE_RTDM lib_LTLIBRARIES += libethercat_rtdm.la libethercat_rtdm_la_SOURCES = $(libethercat_la_SOURCES) -libethercat_rtdm_la_CFLAGS = $(libethercat_la_CFLAGS) -DUSE_RTDM +libethercat_rtdm_la_CFLAGS = $(libethercat_la_CFLAGS) libethercat_rtdm_la_LDFLAGS = $(libethercat_la_LDFLAGS) if ENABLE_XENOMAI @@ -98,6 +101,14 @@ libethercat_rtdm_la_CFLAGS += $(XENOMAI_RTDM_CFLAGS) libethercat_rtdm_la_LDFLAGS += $(XENOMAI_RTDM_LDFLAGS) endif +if ENABLE_XENOMAI_V3 +libethercat_rtdm_la_CFLAGS += $(XENOMAI_RTDM_CFLAGS) +libethercat_rtdm_la_LDFLAGS += $(XENOMAI_RTDM_LDFLAGS) +libethercat_rtdm_la_CFLAGS += -DUSE_RTDM_XENOMAI_V3 +else +libethercat_rtdm_la_CFLAGS += -DUSE_RTDM +endif + if ENABLE_RTAI libethercat_rtdm_la_CFLAGS += $(RTAI_LXRT_CFLAGS) libethercat_rtdm_la_LDFLAGS += $(RTAI_LXRT_LDFLAGS) @@ -111,3 +122,17 @@ endif ethercat-config.cmake: $(srcdir)/ethercat-config.cmake.in Makefile $(SED) -e 's,%libdir%,$(libdir),' -e 's,%includedir%,$(includedir),' $< > $@ + + +#----------------------------------------------------------------------------- + +.PHONY: symbol-version-check + +# check whether all symbols marked with EC_PUBLIC_API are listed in +# libethercat.map + +symbol-version-check: libethercat.la + readelf --dyn-syms --wide $(builddir)/.libs/libethercat.so | \ + awk '$$4 == "FUNC" && $$7 != "UND" && $$8 !~ /@LIBETHERCAT/ { print "Unversioned symbol: " $$8; err = 1; } END { exit err; }' + +#----------------------------------------------------------------------------- diff --git a/lib/common.c b/lib/common.c index 041a6019..4dbdee72 100644 --- a/lib/common.c +++ b/lib/common.c @@ -79,8 +79,10 @@ ec_master_t *ecrt_open_master(unsigned int master_index) master->first_config = NULL; snprintf(path, MAX_PATH_LEN - 1, -#ifdef USE_RTDM +#if defined(USE_RTDM) "EtherCAT%u", +#elif defined(USE_RTDM_XENOMAI_V3) + "/dev/rtdm/EtherCAT%u", #else "/dev/EtherCAT%u", #endif diff --git a/lib/libethercat.map b/lib/libethercat.map new file mode 100644 index 00000000..fb1693f0 --- /dev/null +++ b/lib/libethercat.map @@ -0,0 +1,107 @@ +LIBETHERCAT_1.5.2 { + global: + ecrt_domain_data; + ecrt_domain_process; + ecrt_domain_queue; + ecrt_domain_reg_pdo_entry_list; + ecrt_domain_size; + ecrt_domain_state; + ecrt_master; + ecrt_master_activate; + ecrt_master_application_time; + ecrt_master_create_domain; + ecrt_master_deactivate; + ecrt_master_get_pdo; + ecrt_master_get_pdo_entry; + ecrt_master_get_slave; + ecrt_master_get_sync_manager; + ecrt_master_link_state; + ecrt_master_read_idn; + ecrt_master_receive; + ecrt_master_reference_clock_time; + ecrt_master_reserve; + ecrt_master_reset; + ecrt_master_sdo_download; + ecrt_master_sdo_download_complete; + ecrt_master_sdo_upload; + ecrt_master_select_reference_clock; + ecrt_master_send; + ecrt_master_set_send_interval; + ecrt_master_slave_config; + ecrt_master_state; + ecrt_master_sync_monitor_process; + ecrt_master_sync_monitor_queue; + ecrt_master_sync_reference_clock; + ecrt_master_sync_slave_clocks; + ecrt_master_write_idn; + ecrt_open_master; + ecrt_reg_request_data; + ecrt_reg_request_read; + ecrt_reg_request_state; + ecrt_reg_request_write; + ecrt_release_master; + ecrt_request_master; + ecrt_sdo_request_data; + ecrt_sdo_request_data_size; + ecrt_sdo_request_index; + ecrt_sdo_request_read; + ecrt_sdo_request_state; + ecrt_sdo_request_timeout; + ecrt_sdo_request_write; + ecrt_slave_config_complete_sdo; + ecrt_slave_config_create_reg_request; + ecrt_slave_config_create_sdo_request; + ecrt_slave_config_create_soe_request; + ecrt_slave_config_create_voe_handler; + ecrt_slave_config_dc; + ecrt_slave_config_emerg_clear; + ecrt_slave_config_emerg_overruns; + ecrt_slave_config_emerg_pop; + ecrt_slave_config_emerg_size; + ecrt_slave_config_idn; + ecrt_slave_config_pdo_assign_add; + ecrt_slave_config_pdo_assign_clear; + ecrt_slave_config_pdo_mapping_add; + ecrt_slave_config_pdo_mapping_clear; + ecrt_slave_config_pdos; + ecrt_slave_config_reg_pdo_entry; + ecrt_slave_config_reg_pdo_entry_pos; + ecrt_slave_config_sdo; + ecrt_slave_config_sdo16; + ecrt_slave_config_sdo32; + ecrt_slave_config_sdo8; + ecrt_slave_config_state; + ecrt_slave_config_sync_manager; + ecrt_slave_config_watchdog; + ecrt_version_magic; + ecrt_voe_handler_data; + ecrt_voe_handler_data_size; + ecrt_voe_handler_execute; + ecrt_voe_handler_read; + ecrt_voe_handler_read_nosync; + ecrt_voe_handler_received_header; + ecrt_voe_handler_send_header; + ecrt_voe_handler_write; +}; + +LIBETHERCAT_1.5.3 { + global: + ecrt_master_sync_reference_clock_to; + ecrt_read_lreal; + ecrt_read_real; + ecrt_slave_config_flag; + ecrt_soe_request_data; + ecrt_soe_request_data_size; + ecrt_soe_request_idn; + ecrt_soe_request_read; + ecrt_soe_request_state; + ecrt_soe_request_timeout; + ecrt_soe_request_write; + ecrt_write_lreal; + ecrt_write_real; +} LIBETHERCAT_1.5.2; + +LIBETHERCAT_1.6 { + global: + ecrt_master_scan_progress; +} LIBETHERCAT_1.5.3; diff --git a/lib/master.c b/lib/master.c index b02cdd86..f2d846e1 100644 --- a/lib/master.c +++ b/lib/master.c @@ -405,9 +405,9 @@ int ecrt_master_get_pdo_entry(ec_master_t *master, uint16_t slave_position, /****************************************************************************/ -int ecrt_master_sdo_download(ec_master_t *master, uint16_t slave_position, - uint16_t index, uint8_t subindex, uint8_t *data, - size_t data_size, uint32_t *abort_code) +int ecrt_master_sdo_download(ec_master_t *master, + uint16_t slave_position, uint16_t index, uint8_t subindex, + const uint8_t *data, size_t data_size, uint32_t *abort_code) { ec_ioctl_slave_sdo_download_t download; int ret; @@ -417,7 +417,7 @@ int ecrt_master_sdo_download(ec_master_t *master, uint16_t slave_position, download.sdo_entry_subindex = subindex; download.complete_access = 0; download.data_size = data_size; - download.data = data; + download.data = (uint8_t *) data; // will only be read in ioctl() ret = ioctl(master->fd, EC_IOCTL_SLAVE_SDO_DOWNLOAD, &download); if (EC_IOCTL_IS_ERROR(ret)) { @@ -435,7 +435,7 @@ int ecrt_master_sdo_download(ec_master_t *master, uint16_t slave_position, /****************************************************************************/ int ecrt_master_sdo_download_complete(ec_master_t *master, - uint16_t slave_position, uint16_t index, uint8_t *data, + uint16_t slave_position, uint16_t index, const uint8_t *data, size_t data_size, uint32_t *abort_code) { ec_ioctl_slave_sdo_download_t download; @@ -446,7 +446,7 @@ int ecrt_master_sdo_download_complete(ec_master_t *master, download.sdo_entry_subindex = 0; download.complete_access = 1; download.data_size = data_size; - download.data = data; + download.data = (uint8_t *) data; // will only be read in ioctl() ret = ioctl(master->fd, EC_IOCTL_SLAVE_SDO_DOWNLOAD, &download); if (EC_IOCTL_IS_ERROR(ret)) { @@ -493,7 +493,7 @@ int ecrt_master_sdo_upload(ec_master_t *master, uint16_t slave_position, /****************************************************************************/ int ecrt_master_write_idn(ec_master_t *master, uint16_t slave_position, - uint8_t drive_no, uint16_t idn, uint8_t *data, size_t data_size, + uint8_t drive_no, uint16_t idn, const uint8_t *data, size_t data_size, uint16_t *error_code) { ec_ioctl_slave_soe_write_t io; @@ -503,7 +503,7 @@ int ecrt_master_write_idn(ec_master_t *master, uint16_t slave_position, io.drive_no = drive_no; io.idn = idn; io.data_size = data_size; - io.data = data; + io.data = (uint8_t *) data; // will only be read in ioctl() ret = ioctl(master->fd, EC_IOCTL_SLAVE_SOE_WRITE, &io); if (EC_IOCTL_IS_ERROR(ret)) { @@ -742,7 +742,8 @@ void ecrt_master_sync_slave_clocks(ec_master_t *master) /****************************************************************************/ -int ecrt_master_reference_clock_time(ec_master_t *master, uint32_t *time) +int ecrt_master_reference_clock_time(const ec_master_t *master, + uint32_t *time) { int ret; @@ -770,7 +771,7 @@ void ecrt_master_sync_monitor_queue(ec_master_t *master) /****************************************************************************/ -uint32_t ecrt_master_sync_monitor_process(ec_master_t *master) +uint32_t ecrt_master_sync_monitor_process(const ec_master_t *master) { uint32_t time_diff; int ret; diff --git a/lib/reg_request.c b/lib/reg_request.c index db824f92..6fb04c98 100644 --- a/lib/reg_request.c +++ b/lib/reg_request.c @@ -48,14 +48,14 @@ void ec_reg_request_clear(ec_reg_request_t *reg) * Application interface. ****************************************************************************/ -uint8_t *ecrt_reg_request_data(ec_reg_request_t *reg) +uint8_t *ecrt_reg_request_data(const ec_reg_request_t *reg) { return reg->data; } /****************************************************************************/ -ec_request_state_t ecrt_reg_request_state(ec_reg_request_t *reg) +ec_request_state_t ecrt_reg_request_state(const ec_reg_request_t *reg) { ec_ioctl_reg_request_t io; int ret; diff --git a/lib/sdo_request.c b/lib/sdo_request.c index 4f9df6de..6271f642 100644 --- a/lib/sdo_request.c +++ b/lib/sdo_request.c @@ -86,7 +86,7 @@ void ecrt_sdo_request_timeout(ec_sdo_request_t *req, uint32_t timeout) /****************************************************************************/ -uint8_t *ecrt_sdo_request_data(ec_sdo_request_t *req) +uint8_t *ecrt_sdo_request_data(const ec_sdo_request_t *req) { return req->data; } diff --git a/lib/slave_config.c b/lib/slave_config.c index 6b3b2e44..4ac132a9 100644 --- a/lib/slave_config.c +++ b/lib/slave_config.c @@ -523,7 +523,7 @@ int ecrt_slave_config_emerg_clear(ec_slave_config_t *sc) /****************************************************************************/ -int ecrt_slave_config_emerg_overruns(ec_slave_config_t *sc) +int ecrt_slave_config_emerg_overruns(const ec_slave_config_t *sc) { ec_ioctl_sc_emerg_t io; int ret; diff --git a/lib/soe_request.c b/lib/soe_request.c index 1516ec93..d95a4ef1 100644 --- a/lib/soe_request.c +++ b/lib/soe_request.c @@ -86,7 +86,7 @@ void ecrt_soe_request_timeout(ec_soe_request_t *req, uint32_t timeout) /****************************************************************************/ -uint8_t *ecrt_soe_request_data(ec_soe_request_t *req) +uint8_t *ecrt_soe_request_data(const ec_soe_request_t *req) { return req->data; } diff --git a/lib/voe_handler.c b/lib/voe_handler.c index a743ff26..f0ae45c9 100644 --- a/lib/voe_handler.c +++ b/lib/voe_handler.c @@ -86,7 +86,7 @@ void ecrt_voe_handler_received_header(const ec_voe_handler_t *voe, /****************************************************************************/ -uint8_t *ecrt_voe_handler_data(ec_voe_handler_t *voe) +uint8_t *ecrt_voe_handler_data(const ec_voe_handler_t *voe) { return voe->data; } diff --git a/master/Kbuild.in b/master/Kbuild.in index 393e68d5..75eff6ff 100644 --- a/master/Kbuild.in +++ b/master/Kbuild.in @@ -78,18 +78,24 @@ endif ifeq (@ENABLE_RTDM@,1) +ifeq (@ENABLE_XENOMAI_V3@, 1) +ec_master-objs += rtdm_xenomai_v3.o +else ec_master-objs += rtdm.o +endif ifeq (@ENABLE_XENOMAI@, 1) -CFLAGS_rtdm.o := -I@XENOMAI_DIR@/include +CFLAGS_rtdm.o := @XENOMAI_RTDM_CFLAGS@ +CFLAGS_rtdm-ioctl.o := @XENOMAI_RTDM_CFLAGS@ endif ifeq (@ENABLE_RTAI@, 1) CFLAGS_rtdm.o := -I@RTAI_DIR@/include +CFLAGS_rtdm-ioctl.o := -I@RTAI_DIR@/include endif ec_master-objs += rtdm-ioctl.o -CFLAGS_rtdm-ioctl.o := -DEC_IOCTL_RTDM +CFLAGS_rtdm-ioctl.o += -DEC_IOCTL_RTDM endif # ENABLE_RTDM diff --git a/master/Makefile.am b/master/Makefile.am index c1f768ef..1a0ef30a 100644 --- a/master/Makefile.am +++ b/master/Makefile.am @@ -60,6 +60,8 @@ noinst_HEADERS = \ reg_request.c reg_request.h \ rtdm-ioctl.c \ rtdm.c rtdm.h \ + rtdm_details.h \ + rtdm_xenomai_v3.c \ sdo.c sdo.h \ sdo_entry.c sdo_entry.h \ sdo_request.c sdo_request.h \ diff --git a/master/coe_emerg_ring.c b/master/coe_emerg_ring.c index 6e19b982..b0026c3b 100644 --- a/master/coe_emerg_ring.c +++ b/master/coe_emerg_ring.c @@ -160,7 +160,7 @@ int ec_coe_emerg_ring_clear_ring( * \return Number of overruns. */ int ec_coe_emerg_ring_overruns( - ec_coe_emerg_ring_t *ring /**< Emergency ring. */ + const ec_coe_emerg_ring_t *ring /**< Emergency ring. */ ) { return ring->overruns; diff --git a/master/coe_emerg_ring.h b/master/coe_emerg_ring.h index 2f00c01d..36ab2c41 100644 --- a/master/coe_emerg_ring.h +++ b/master/coe_emerg_ring.h @@ -63,7 +63,7 @@ int ec_coe_emerg_ring_size(ec_coe_emerg_ring_t *, size_t); void ec_coe_emerg_ring_push(ec_coe_emerg_ring_t *, const u8 *); int ec_coe_emerg_ring_pop(ec_coe_emerg_ring_t *, u8 *); int ec_coe_emerg_ring_clear_ring(ec_coe_emerg_ring_t *); -int ec_coe_emerg_ring_overruns(ec_coe_emerg_ring_t *); +int ec_coe_emerg_ring_overruns(const ec_coe_emerg_ring_t *); /****************************************************************************/ diff --git a/master/ioctl.c b/master/ioctl.c index 042e9d2a..394dee15 100644 --- a/master/ioctl.c +++ b/master/ioctl.c @@ -49,16 +49,23 @@ #endif #ifdef EC_IOCTL_RTDM +# include "rtdm_details.h" /* RTDM does not support locking yet, * therefore no send/receive callbacks are set too. */ # define ec_ioctl_lock(lock) do {} while(0) # define ec_ioctl_unlock(lock) do {} while(0) # define ec_ioctl_lock_interruptible(lock) (0) +# define ec_copy_to_user(to, from, n, ctx) \ + rtdm_safe_copy_to_user(ec_ioctl_to_rtdm(ctx), to, from, n) +# define ec_copy_from_user(to, from, n, ctx) \ + rtdm_safe_copy_from_user(ec_ioctl_to_rtdm(ctx), to, from, n) #else # define ec_ioctl_lock(lock) rt_mutex_lock(lock) # define ec_ioctl_unlock(lock) rt_mutex_unlock(lock) # define ec_ioctl_lock_interruptible(lock) \ rt_mutex_lock_interruptible(lock) +# define ec_copy_to_user(to, from, n, ctx) copy_to_user(to, from, n) +# define ec_copy_from_user(to, from, n, ctx) copy_from_user(to, from, n) #endif // EC_IOCTL_RTDM /****************************************************************************/ @@ -85,7 +92,8 @@ static void ec_ioctl_strcpy( * \return Zero on success, otherwise a negative error code. */ static ATTRIBUTES int ec_ioctl_module( - void *arg /**< Userspace address to store the results. */ + void *arg, /**< ioctl() argument. */ + ec_ioctl_context_t *ctx /**< Private data structure of file handle. */ ) { ec_ioctl_module_t data; @@ -93,7 +101,7 @@ static ATTRIBUTES int ec_ioctl_module( data.ioctl_version_magic = EC_IOCTL_VERSION_MAGIC; data.master_count = ec_master_count(); - if (copy_to_user((void __user *) arg, &data, sizeof(data))) + if (ec_copy_to_user((void __user *) arg, &data, sizeof(data), ctx)) return -EFAULT; return 0; @@ -1893,7 +1901,7 @@ static ATTRIBUTES int ec_ioctl_activate( offset += ecrt_domain_size(domain); } -#ifdef EC_IOCTL_RTDM +#if defined(EC_IOCTL_RTDM) && !defined(EC_RTDM_XENOMAI_V3) /* RTDM uses a different approach for memory-mapping, which has to be * initiated by the kernel. */ @@ -2038,7 +2046,7 @@ static ATTRIBUTES int ec_ioctl_master_state( ecrt_master_state(master, &data); - if (copy_to_user((void __user *) arg, &data, sizeof(data))) + if (ec_copy_to_user((void __user *) arg, &data, sizeof(data), ctx)) return -EFAULT; return 0; @@ -2060,7 +2068,7 @@ static ATTRIBUTES int ec_ioctl_master_link_state( ec_master_link_state_t state; int ret; - if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) { + if (ec_copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl), ctx)) { return -EFAULT; } @@ -2069,7 +2077,8 @@ static ATTRIBUTES int ec_ioctl_master_link_state( return ret; } - if (copy_to_user((void __user *) ioctl.state, &state, sizeof(state))) { + if (ec_copy_to_user((void __user *) ioctl.state, + &state, sizeof(state), ctx)) { return -EFAULT; } @@ -2093,7 +2102,7 @@ static ATTRIBUTES int ec_ioctl_app_time( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&time, (void __user *) arg, sizeof(time))) { + if (ec_copy_from_user(&time, (void __user *) arg, sizeof(time), ctx)) { return -EFAULT; } @@ -2141,7 +2150,7 @@ static ATTRIBUTES int ec_ioctl_sync_ref_to( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&time, (void __user *) arg, sizeof(time))) { + if (ec_copy_from_user(&time, (void __user *) arg, sizeof(time), ctx)) { return -EFAULT; } @@ -2199,7 +2208,7 @@ static ATTRIBUTES int ec_ioctl_ref_clock_time( return ret; } - if (copy_to_user((void __user *) arg, &time, sizeof(time))) { + if (ec_copy_to_user((void __user *) arg, &time, sizeof(time), ctx)) { return -EFAULT; } @@ -2248,7 +2257,8 @@ static ATTRIBUTES int ec_ioctl_sync_mon_process( time_diff = ecrt_master_sync_monitor_process(master); - if (copy_to_user((void __user *) arg, &time_diff, sizeof(time_diff))) + if (ec_copy_to_user((void __user *) arg, &time_diff, + sizeof(time_diff), ctx)) return -EFAULT; return 0; @@ -2764,7 +2774,7 @@ static ATTRIBUTES int ec_ioctl_sc_emerg_pop( return -EPERM; } - if (copy_from_user(&io, (void __user *) arg, sizeof(io))) { + if (ec_copy_from_user(&io, (void __user *) arg, sizeof(io), ctx)) { return -EFAULT; } @@ -2780,7 +2790,7 @@ static ATTRIBUTES int ec_ioctl_sc_emerg_pop( return ret; } - if (copy_to_user((void __user *) io.target, msg, sizeof(msg))) { + if (ec_copy_to_user((void __user *) io.target, msg, sizeof(msg), ctx)) { return -EFAULT; } @@ -2806,7 +2816,7 @@ static ATTRIBUTES int ec_ioctl_sc_emerg_clear( return -EPERM; } - if (copy_from_user(&io, (void __user *) arg, sizeof(io))) { + if (ec_copy_from_user(&io, (void __user *) arg, sizeof(io), ctx)) { return -EFAULT; } @@ -2840,7 +2850,7 @@ static ATTRIBUTES int ec_ioctl_sc_emerg_overruns( return -EPERM; } - if (copy_from_user(&io, (void __user *) arg, sizeof(io))) { + if (ec_copy_from_user(&io, (void __user *) arg, sizeof(io), ctx)) { return -EFAULT; } @@ -2858,7 +2868,7 @@ static ATTRIBUTES int ec_ioctl_sc_emerg_overruns( io.overruns = ret; - if (copy_to_user((void __user *) arg, &io, sizeof(io))) { + if (ec_copy_to_user((void __user *) arg, &io, sizeof(io), ctx)) { return -EFAULT; } @@ -3092,7 +3102,7 @@ static ATTRIBUTES int ec_ioctl_sc_state( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) { return -EFAULT; } @@ -3105,7 +3115,8 @@ static ATTRIBUTES int ec_ioctl_sc_state( ecrt_slave_config_state(sc, &state); - if (copy_to_user((void __user *) data.state, &state, sizeof(state))) + if (ec_copy_to_user((void __user *) data.state, + &state, sizeof(state), ctx)) return -EFAULT; return 0; @@ -3368,7 +3379,7 @@ static ATTRIBUTES int ec_ioctl_domain_state( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) { return -EFAULT; } @@ -3381,7 +3392,7 @@ static ATTRIBUTES int ec_ioctl_domain_state( ecrt_domain_state(domain, &state); - if (copy_to_user((void __user *) data.state, &state, sizeof(state))) + if (ec_copy_to_user((void __user *) data.state, &state, sizeof(state), ctx)) return -EFAULT; return 0; @@ -3406,7 +3417,7 @@ static ATTRIBUTES int ec_ioctl_sdo_request_index( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; /* no locking of master_sem needed, because neither sc nor req will not be @@ -3443,7 +3454,7 @@ static ATTRIBUTES int ec_ioctl_sdo_request_timeout( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; /* no locking of master_sem needed, because neither sc nor req will not be @@ -3480,7 +3491,7 @@ static ATTRIBUTES int ec_ioctl_sdo_request_state( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; /* no locking of master_sem needed, because neither sc nor req will not be @@ -3500,7 +3511,7 @@ static ATTRIBUTES int ec_ioctl_sdo_request_state( else data.size = 0; - if (copy_to_user((void __user *) arg, &data, sizeof(data))) + if (ec_copy_to_user((void __user *) arg, &data, sizeof(data), ctx)) return -EFAULT; return 0; @@ -3525,7 +3536,7 @@ static ATTRIBUTES int ec_ioctl_sdo_request_read( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; /* no locking of master_sem needed, because neither sc nor req will not be @@ -3563,7 +3574,7 @@ static ATTRIBUTES int ec_ioctl_sdo_request_write( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; if (!data.size) { @@ -3586,7 +3597,8 @@ static ATTRIBUTES int ec_ioctl_sdo_request_write( if (ret) return ret; - if (copy_from_user(req->data, (void __user *) data.data, data.size)) + if (ec_copy_from_user(req->data, (void __user *) data.data, + data.size, ctx)) return -EFAULT; req->data_size = data.size; @@ -3613,7 +3625,7 @@ static ATTRIBUTES int ec_ioctl_sdo_request_data( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; /* no locking of master_sem needed, because neither sc nor req will not be @@ -3627,8 +3639,8 @@ static ATTRIBUTES int ec_ioctl_sdo_request_data( return -ENOENT; } - if (copy_to_user((void __user *) data.data, ecrt_sdo_request_data(req), - ecrt_sdo_request_data_size(req))) + if (ec_copy_to_user((void __user *) data.data, ecrt_sdo_request_data(req), + ecrt_sdo_request_data_size(req), ctx)) return -EFAULT; return 0; @@ -3653,7 +3665,7 @@ static ATTRIBUTES int ec_ioctl_soe_request_index( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; /* no locking of master_sem needed, because neither sc nor req will not be @@ -3690,7 +3702,7 @@ static ATTRIBUTES int ec_ioctl_soe_request_timeout( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; /* no locking of master_sem needed, because neither sc nor req will not be @@ -3727,7 +3739,7 @@ static ATTRIBUTES int ec_ioctl_soe_request_state( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; /* no locking of master_sem needed, because neither sc nor req will not be @@ -3749,7 +3761,7 @@ static ATTRIBUTES int ec_ioctl_soe_request_state( data.size = 0; } - if (copy_to_user((void __user *) arg, &data, sizeof(data))) + if (ec_copy_to_user((void __user *) arg, &data, sizeof(data), ctx)) return -EFAULT; return 0; @@ -3774,7 +3786,7 @@ static ATTRIBUTES int ec_ioctl_soe_request_read( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; /* no locking of master_sem needed, because neither sc nor req will not be @@ -3812,7 +3824,7 @@ static ATTRIBUTES int ec_ioctl_soe_request_write( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; if (!data.size) { @@ -3835,7 +3847,8 @@ static ATTRIBUTES int ec_ioctl_soe_request_write( if (ret) return ret; - if (copy_from_user(req->data, (void __user *) data.data, data.size)) + if (ec_copy_from_user(req->data, (void __user *) data.data, + data.size, ctx)) return -EFAULT; req->data_size = data.size; @@ -3862,7 +3875,7 @@ static ATTRIBUTES int ec_ioctl_soe_request_data( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; /* no locking of master_sem needed, because neither sc nor req will not be @@ -3876,8 +3889,8 @@ static ATTRIBUTES int ec_ioctl_soe_request_data( return -ENOENT; } - if (copy_to_user((void __user *) data.data, ecrt_soe_request_data(req), - ecrt_soe_request_data_size(req))) + if (ec_copy_to_user((void __user *) data.data, ecrt_soe_request_data(req), + ecrt_soe_request_data_size(req), ctx)) return -EFAULT; return 0; @@ -3903,7 +3916,7 @@ static ATTRIBUTES int ec_ioctl_reg_request_data( return -EPERM; } - if (copy_from_user(&io, (void __user *) arg, sizeof(io))) { + if (ec_copy_from_user(&io, (void __user *) arg, sizeof(io), ctx)) { return -EFAULT; } @@ -3922,8 +3935,8 @@ static ATTRIBUTES int ec_ioctl_reg_request_data( return -ENOENT; } - if (copy_to_user((void __user *) io.data, ecrt_reg_request_data(reg), - min(reg->mem_size, io.mem_size))) { + if (ec_copy_to_user((void __user *) io.data, ecrt_reg_request_data(reg), + min(reg->mem_size, io.mem_size), ctx)) { return -EFAULT; } @@ -3950,7 +3963,7 @@ static ATTRIBUTES int ec_ioctl_reg_request_state( return -EPERM; } - if (copy_from_user(&io, (void __user *) arg, sizeof(io))) { + if (ec_copy_from_user(&io, (void __user *) arg, sizeof(io), ctx)) { return -EFAULT; } @@ -3968,7 +3981,7 @@ static ATTRIBUTES int ec_ioctl_reg_request_state( io.state = ecrt_reg_request_state(reg); io.new_data = io.state == EC_REQUEST_SUCCESS && reg->dir == EC_DIR_INPUT; - if (copy_to_user((void __user *) arg, &io, sizeof(io))) { + if (ec_copy_to_user((void __user *) arg, &io, sizeof(io), ctx)) { return -EFAULT; } @@ -3995,7 +4008,7 @@ static ATTRIBUTES int ec_ioctl_reg_request_write( return -EPERM; } - if (copy_from_user(&io, (void __user *) arg, sizeof(io))) { + if (ec_copy_from_user(&io, (void __user *) arg, sizeof(io), ctx)) { return -EFAULT; } @@ -4014,8 +4027,8 @@ static ATTRIBUTES int ec_ioctl_reg_request_write( return -EOVERFLOW; } - if (copy_from_user(reg->data, (void __user *) io.data, - io.transfer_size)) { + if (ec_copy_from_user(reg->data, (void __user *) io.data, + io.transfer_size, ctx)) { return -EFAULT; } @@ -4043,7 +4056,7 @@ static ATTRIBUTES int ec_ioctl_reg_request_read( return -EPERM; } - if (copy_from_user(&io, (void __user *) arg, sizeof(io))) { + if (ec_copy_from_user(&io, (void __user *) arg, sizeof(io), ctx)) { return -EFAULT; } @@ -4087,13 +4100,14 @@ static ATTRIBUTES int ec_ioctl_voe_send_header( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; - if (get_user(vendor_id, data.vendor_id)) + if (ec_copy_from_user(&vendor_id, data.vendor_id, sizeof(vendor_id), ctx)) return -EFAULT; - if (get_user(vendor_type, data.vendor_type)) + if (ec_copy_from_user(&vendor_type, data.vendor_type, + sizeof(vendor_type), ctx)) return -EFAULT; /* no locking of master_sem needed, because neither sc nor voe will not be @@ -4132,7 +4146,7 @@ static ATTRIBUTES int ec_ioctl_voe_rec_header( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; /* no locking of master_sem needed, because neither sc nor voe will not be @@ -4149,11 +4163,13 @@ static ATTRIBUTES int ec_ioctl_voe_rec_header( ecrt_voe_handler_received_header(voe, &vendor_id, &vendor_type); if (likely(data.vendor_id)) - if (put_user(vendor_id, data.vendor_id)) + if (ec_copy_to_user(data.vendor_id, &vendor_id, + sizeof(vendor_id), ctx)) return -EFAULT; if (likely(data.vendor_type)) - if (put_user(vendor_type, data.vendor_type)) + if (ec_copy_to_user(data.vendor_type, &vendor_type, + sizeof(vendor_type), ctx)) return -EFAULT; return 0; @@ -4178,7 +4194,7 @@ static ATTRIBUTES int ec_ioctl_voe_read( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; /* no locking of master_sem needed, because neither sc nor voe will not be @@ -4215,7 +4231,7 @@ static ATTRIBUTES int ec_ioctl_voe_read_nosync( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; /* no locking of master_sem needed, because neither sc nor voe will not be @@ -4252,7 +4268,7 @@ static ATTRIBUTES int ec_ioctl_voe_write( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; /* no locking of master_sem needed, because neither sc nor voe will not be @@ -4270,8 +4286,8 @@ static ATTRIBUTES int ec_ioctl_voe_write( if (data.size > ec_voe_handler_mem_size(voe)) return -EOVERFLOW; - if (copy_from_user(ecrt_voe_handler_data(voe), - (void __user *) data.data, data.size)) + if (ec_copy_from_user(ecrt_voe_handler_data(voe), + (void __user *) data.data, data.size, ctx)) return -EFAULT; } @@ -4298,7 +4314,7 @@ static ATTRIBUTES int ec_ioctl_voe_exec( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; /* no locking of master_sem needed, because neither sc nor voe will not be @@ -4321,7 +4337,7 @@ static ATTRIBUTES int ec_ioctl_voe_exec( else data.size = 0; - if (copy_to_user((void __user *) arg, &data, sizeof(data))) + if (ec_copy_to_user((void __user *) arg, &data, sizeof(data), ctx)) return -EFAULT; return 0; @@ -4346,7 +4362,7 @@ static ATTRIBUTES int ec_ioctl_voe_data( if (unlikely(!ctx->requested)) return -EPERM; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (ec_copy_from_user(&data, (void __user *) arg, sizeof(data), ctx)) return -EFAULT; /* no locking of master_sem needed, because neither sc nor voe will not be @@ -4360,8 +4376,8 @@ static ATTRIBUTES int ec_ioctl_voe_data( return -ENOENT; } - if (copy_to_user((void __user *) data.data, ecrt_voe_handler_data(voe), - ecrt_voe_handler_data_size(voe))) + if (ec_copy_to_user((void __user *) data.data, ecrt_voe_handler_data(voe), + ecrt_voe_handler_data_size(voe), ctx)) return -EFAULT; return 0; @@ -4649,18 +4665,239 @@ static ATTRIBUTES int ec_ioctl_slave_soe_write( /****************************************************************************/ /** ioctl() function to use. + * + * For RTDM, there will be ec_ioctl_rtdm_rt and ec_ioctl_rtdm_nrt. + * For "normal" cdev, there will be ec_ioctl_rt only. */ -#ifdef EC_IOCTL_RTDM -#define EC_IOCTL ec_ioctl_rtdm -#else -#define EC_IOCTL ec_ioctl +#ifndef EC_IOCTL_RTDM +static long ec_ioctl_nrt( + ec_master_t *master, /**< EtherCAT master. */ + ec_ioctl_context_t *ctx, /**< Device context. */ + unsigned int cmd, /**< ioctl() command identifier. */ + void *arg /**< ioctl() argument. */); #endif /** Called when an ioctl() command is issued. + * Both RT and nRT context. * * \return ioctl() return code. */ -long EC_IOCTL( +static long ec_ioctl_both( + ec_master_t *master, /**< EtherCAT master. */ + ec_ioctl_context_t *ctx, /**< Device context. */ + unsigned int cmd, /**< ioctl() command identifier. */ + void *arg /**< ioctl() argument. */ + ) +{ + int ret; + + switch (cmd) { + case EC_IOCTL_MODULE: + ret = ec_ioctl_module(arg, ctx); + break; + case EC_IOCTL_MASTER_DEBUG: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_master_debug(master, arg); + break; + case EC_IOCTL_MASTER_RESCAN: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_master_rescan(master, arg); + break; + case EC_IOCTL_MASTER_STATE: + ret = ec_ioctl_master_state(master, arg, ctx); + break; + case EC_IOCTL_MASTER_LINK_STATE: + ret = ec_ioctl_master_link_state(master, arg, ctx); + break; + case EC_IOCTL_APP_TIME: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_app_time(master, arg, ctx); + break; + case EC_IOCTL_REF_CLOCK_TIME: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_ref_clock_time(master, arg, ctx); + break; + case EC_IOCTL_SC_EMERG_POP: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sc_emerg_pop(master, arg, ctx); + break; + case EC_IOCTL_SC_EMERG_CLEAR: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sc_emerg_clear(master, arg, ctx); + break; + case EC_IOCTL_SC_EMERG_OVERRUNS: + ret = ec_ioctl_sc_emerg_overruns(master, arg, ctx); + break; + case EC_IOCTL_SC_STATE: + ret = ec_ioctl_sc_state(master, arg, ctx); + break; + case EC_IOCTL_DOMAIN_STATE: + ret = ec_ioctl_domain_state(master, arg, ctx); + break; + case EC_IOCTL_SDO_REQUEST_INDEX: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sdo_request_index(master, arg, ctx); + break; + case EC_IOCTL_SDO_REQUEST_TIMEOUT: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sdo_request_timeout(master, arg, ctx); + break; + case EC_IOCTL_SDO_REQUEST_STATE: + ret = ec_ioctl_sdo_request_state(master, arg, ctx); + break; + case EC_IOCTL_SDO_REQUEST_READ: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sdo_request_read(master, arg, ctx); + break; + case EC_IOCTL_SDO_REQUEST_WRITE: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sdo_request_write(master, arg, ctx); + break; + case EC_IOCTL_SDO_REQUEST_DATA: + ret = ec_ioctl_sdo_request_data(master, arg, ctx); + break; + case EC_IOCTL_SOE_REQUEST_IDN: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_soe_request_index(master, arg, ctx); + break; + case EC_IOCTL_SOE_REQUEST_TIMEOUT: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_soe_request_timeout(master, arg, ctx); + break; + case EC_IOCTL_SOE_REQUEST_STATE: + ret = ec_ioctl_soe_request_state(master, arg, ctx); + break; + case EC_IOCTL_SOE_REQUEST_READ: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_soe_request_read(master, arg, ctx); + break; + case EC_IOCTL_SOE_REQUEST_WRITE: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_soe_request_write(master, arg, ctx); + break; + case EC_IOCTL_SOE_REQUEST_DATA: + ret = ec_ioctl_soe_request_data(master, arg, ctx); + break; + case EC_IOCTL_REG_REQUEST_DATA: + ret = ec_ioctl_reg_request_data(master, arg, ctx); + break; + case EC_IOCTL_REG_REQUEST_STATE: + ret = ec_ioctl_reg_request_state(master, arg, ctx); + break; + case EC_IOCTL_REG_REQUEST_WRITE: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_reg_request_write(master, arg, ctx); + break; + case EC_IOCTL_REG_REQUEST_READ: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_reg_request_read(master, arg, ctx); + break; + case EC_IOCTL_VOE_SEND_HEADER: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_voe_send_header(master, arg, ctx); + break; + case EC_IOCTL_VOE_REC_HEADER: + ret = ec_ioctl_voe_rec_header(master, arg, ctx); + break; + case EC_IOCTL_VOE_READ: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_voe_read(master, arg, ctx); + break; + case EC_IOCTL_VOE_READ_NOSYNC: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_voe_read_nosync(master, arg, ctx); + break; + case EC_IOCTL_VOE_WRITE: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_voe_write(master, arg, ctx); + break; + case EC_IOCTL_VOE_DATA: + ret = ec_ioctl_voe_data(master, arg, ctx); + break; + default: +#ifdef EC_IOCTL_RTDM + ret = -ENOTTY; +#else + /* chain non-rt commands for normal cdev */ + ret = ec_ioctl_nrt(master, ctx, cmd, arg); +#endif + break; + } + + return ret; +} + +/** Called when an ioctl() command is issued. + * RTDM: RT only. + * + * \return ioctl() return code. + */ +#ifdef EC_IOCTL_RTDM +long ec_ioctl_rtdm_rt +#else +long ec_ioctl +#endif + ( ec_master_t *master, /**< EtherCAT master. */ ec_ioctl_context_t *ctx, /**< Device context. */ unsigned int cmd, /**< ioctl() command identifier. */ @@ -4670,13 +4907,121 @@ long EC_IOCTL( #if DEBUG_LATENCY cycles_t a = get_cycles(), b; unsigned int t; +#endif + long ret; + + switch (cmd) { + case EC_IOCTL_SEND: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_send(master, arg, ctx); + break; + case EC_IOCTL_RECEIVE: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_receive(master, arg, ctx); + break; + case EC_IOCTL_SYNC_REF: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sync_ref(master, arg, ctx); + break; + case EC_IOCTL_SYNC_REF_TO: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sync_ref_to(master, arg, ctx); + break; + case EC_IOCTL_SYNC_SLAVES: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sync_slaves(master, arg, ctx); + break; + case EC_IOCTL_SYNC_MON_QUEUE: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sync_mon_queue(master, arg, ctx); + break; + case EC_IOCTL_SYNC_MON_PROCESS: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sync_mon_process(master, arg, ctx); + break; + case EC_IOCTL_DOMAIN_PROCESS: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_domain_process(master, arg, ctx); + break; + case EC_IOCTL_DOMAIN_QUEUE: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_domain_queue(master, arg, ctx); + break; + case EC_IOCTL_VOE_EXEC: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_voe_exec(master, arg, ctx); + break; + default: + ret = ec_ioctl_both(master, ctx, cmd, arg); + break; + } + +#if DEBUG_LATENCY + b = get_cycles(); + t = (unsigned int) ((b - a) * 1000LL) / cpu_khz; + if (t > 50) { + EC_MASTER_WARN(master, "ioctl(0x%02x) took %u us.\n", + _IOC_NR(cmd), t); + } +#endif + + return ret; +} + +/** Called when an ioctl() command is issued. + * nRT context only. + * + * \return ioctl() return code. + */ +#ifdef EC_IOCTL_RTDM +long ec_ioctl_rtdm_nrt +#else +static long ec_ioctl_nrt +#endif + ( + ec_master_t *master, /**< EtherCAT master. */ + ec_ioctl_context_t *ctx, /**< Device context. */ + unsigned int cmd, /**< ioctl() command identifier. */ + void *arg /**< ioctl() argument. */ + ) +{ +#if DEBUG_LATENCY && !defined(EC_IOCTL_RTDM) + cycles_t a = get_cycles(), b; + unsigned int t; #endif int ret; switch (cmd) { - case EC_IOCTL_MODULE: - ret = ec_ioctl_module(arg); - break; case EC_IOCTL_MASTER: ret = ec_ioctl_master(master, arg); break; @@ -4701,20 +5046,6 @@ long EC_IOCTL( case EC_IOCTL_DOMAIN_DATA: ret = ec_ioctl_domain_data(master, arg); break; - case EC_IOCTL_MASTER_DEBUG: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_master_debug(master, arg); - break; - case EC_IOCTL_MASTER_RESCAN: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_master_rescan(master, arg); - break; case EC_IOCTL_SLAVE_STATE: if (!ctx->writable) { ret = -EPERM; @@ -4852,75 +5183,6 @@ long EC_IOCTL( } ret = ec_ioctl_deactivate(master, arg, ctx); break; - case EC_IOCTL_SEND: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_send(master, arg, ctx); - break; - case EC_IOCTL_RECEIVE: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_receive(master, arg, ctx); - break; - case EC_IOCTL_MASTER_STATE: - ret = ec_ioctl_master_state(master, arg, ctx); - break; - case EC_IOCTL_MASTER_LINK_STATE: - ret = ec_ioctl_master_link_state(master, arg, ctx); - break; - case EC_IOCTL_APP_TIME: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_app_time(master, arg, ctx); - break; - case EC_IOCTL_SYNC_REF: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_sync_ref(master, arg, ctx); - break; - case EC_IOCTL_SYNC_REF_TO: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_sync_ref_to(master, arg, ctx); - break; - case EC_IOCTL_SYNC_SLAVES: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_sync_slaves(master, arg, ctx); - break; - case EC_IOCTL_REF_CLOCK_TIME: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_ref_clock_time(master, arg, ctx); - break; - case EC_IOCTL_SYNC_MON_QUEUE: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_sync_mon_queue(master, arg, ctx); - break; - case EC_IOCTL_SYNC_MON_PROCESS: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_sync_mon_process(master, arg, ctx); - break; case EC_IOCTL_RESET: if (!ctx->writable) { ret = -EPERM; @@ -5005,23 +5267,6 @@ long EC_IOCTL( } ret = ec_ioctl_sc_emerg_size(master, arg, ctx); break; - case EC_IOCTL_SC_EMERG_POP: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_sc_emerg_pop(master, arg, ctx); - break; - case EC_IOCTL_SC_EMERG_CLEAR: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_sc_emerg_clear(master, arg, ctx); - break; - case EC_IOCTL_SC_EMERG_OVERRUNS: - ret = ec_ioctl_sc_emerg_overruns(master, arg, ctx); - break; case EC_IOCTL_SC_SDO_REQUEST: if (!ctx->writable) { ret = -EPERM; @@ -5050,9 +5295,6 @@ long EC_IOCTL( } ret = ec_ioctl_sc_create_voe_handler(master, arg, ctx); break; - case EC_IOCTL_SC_STATE: - ret = ec_ioctl_sc_state(master, arg, ctx); - break; case EC_IOCTL_SC_IDN: if (!ctx->writable) { ret = -EPERM; @@ -5073,152 +5315,6 @@ long EC_IOCTL( case EC_IOCTL_DOMAIN_OFFSET: ret = ec_ioctl_domain_offset(master, arg, ctx); break; - case EC_IOCTL_DOMAIN_PROCESS: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_domain_process(master, arg, ctx); - break; - case EC_IOCTL_DOMAIN_QUEUE: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_domain_queue(master, arg, ctx); - break; - case EC_IOCTL_DOMAIN_STATE: - ret = ec_ioctl_domain_state(master, arg, ctx); - break; - case EC_IOCTL_SDO_REQUEST_INDEX: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_sdo_request_index(master, arg, ctx); - break; - case EC_IOCTL_SDO_REQUEST_TIMEOUT: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_sdo_request_timeout(master, arg, ctx); - break; - case EC_IOCTL_SDO_REQUEST_STATE: - ret = ec_ioctl_sdo_request_state(master, arg, ctx); - break; - case EC_IOCTL_SDO_REQUEST_READ: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_sdo_request_read(master, arg, ctx); - break; - case EC_IOCTL_SDO_REQUEST_WRITE: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_sdo_request_write(master, arg, ctx); - break; - case EC_IOCTL_SDO_REQUEST_DATA: - ret = ec_ioctl_sdo_request_data(master, arg, ctx); - break; - case EC_IOCTL_SOE_REQUEST_IDN: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_soe_request_index(master, arg, ctx); - break; - case EC_IOCTL_SOE_REQUEST_TIMEOUT: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_soe_request_timeout(master, arg, ctx); - break; - case EC_IOCTL_SOE_REQUEST_STATE: - ret = ec_ioctl_soe_request_state(master, arg, ctx); - break; - case EC_IOCTL_SOE_REQUEST_READ: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_soe_request_read(master, arg, ctx); - break; - case EC_IOCTL_SOE_REQUEST_WRITE: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_soe_request_write(master, arg, ctx); - break; - case EC_IOCTL_SOE_REQUEST_DATA: - ret = ec_ioctl_soe_request_data(master, arg, ctx); - break; - case EC_IOCTL_REG_REQUEST_DATA: - ret = ec_ioctl_reg_request_data(master, arg, ctx); - break; - case EC_IOCTL_REG_REQUEST_STATE: - ret = ec_ioctl_reg_request_state(master, arg, ctx); - break; - case EC_IOCTL_REG_REQUEST_WRITE: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_reg_request_write(master, arg, ctx); - break; - case EC_IOCTL_REG_REQUEST_READ: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_reg_request_read(master, arg, ctx); - break; - case EC_IOCTL_VOE_SEND_HEADER: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_voe_send_header(master, arg, ctx); - break; - case EC_IOCTL_VOE_REC_HEADER: - ret = ec_ioctl_voe_rec_header(master, arg, ctx); - break; - case EC_IOCTL_VOE_READ: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_voe_read(master, arg, ctx); - break; - case EC_IOCTL_VOE_READ_NOSYNC: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_voe_read_nosync(master, arg, ctx); - break; - case EC_IOCTL_VOE_WRITE: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_voe_write(master, arg, ctx); - break; - case EC_IOCTL_VOE_EXEC: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_voe_exec(master, arg, ctx); - break; - case EC_IOCTL_VOE_DATA: - ret = ec_ioctl_voe_data(master, arg, ctx); - break; case EC_IOCTL_SET_SEND_INTERVAL: if (!ctx->writable) { ret = -EPERM; @@ -5227,11 +5323,15 @@ long EC_IOCTL( ret = ec_ioctl_set_send_interval(master, arg, ctx); break; default: +#ifdef EC_IOCTL_RTDM + ret = ec_ioctl_both(master, ctx, cmd, arg); +#else ret = -ENOTTY; +#endif break; } -#if DEBUG_LATENCY +#if DEBUG_LATENCY && !defined(EC_IOCTL_RTDM) b = get_cycles(); t = (unsigned int) ((b - a) * 1000LL) / cpu_khz; if (t > 50) { diff --git a/master/ioctl.h b/master/ioctl.h index 61c8354f..afaf62c6 100644 --- a/master/ioctl.h +++ b/master/ioctl.h @@ -843,9 +843,14 @@ long ec_ioctl(ec_master_t *, ec_ioctl_context_t *, unsigned int, #ifdef EC_RTDM -long ec_ioctl_rtdm(ec_master_t *, ec_ioctl_context_t *, unsigned int, +long ec_ioctl_rtdm_rt(ec_master_t *, ec_ioctl_context_t *, unsigned int, void __user *); +long ec_ioctl_rtdm_nrt(ec_master_t *, ec_ioctl_context_t *, unsigned int, + void __user *); + +#ifndef EC_RTDM_XENOMAI_V3 int ec_rtdm_mmap(ec_ioctl_context_t *, void **); +#endif #endif diff --git a/master/master.c b/master/master.c index 0e06367a..8a8c7744 100644 --- a/master/master.c +++ b/master/master.c @@ -2769,7 +2769,8 @@ void ecrt_master_application_time(ec_master_t *master, uint64_t app_time) /****************************************************************************/ -int ecrt_master_reference_clock_time(ec_master_t *master, uint32_t *time) +int ecrt_master_reference_clock_time(const ec_master_t *master, + uint32_t *time) { if (!master->dc_ref_clock) { return -ENXIO; @@ -2829,7 +2830,7 @@ void ecrt_master_sync_monitor_queue(ec_master_t *master) /****************************************************************************/ -uint32_t ecrt_master_sync_monitor_process(ec_master_t *master) +uint32_t ecrt_master_sync_monitor_process(const ec_master_t *master) { if (master->sync_mon_datagram.state == EC_DATAGRAM_RECEIVED) { return EC_READ_U32(master->sync_mon_datagram.data) & 0x7fffffff; @@ -2841,7 +2842,7 @@ uint32_t ecrt_master_sync_monitor_process(ec_master_t *master) /****************************************************************************/ int ecrt_master_sdo_download(ec_master_t *master, uint16_t slave_position, - uint16_t index, uint8_t subindex, uint8_t *data, + uint16_t index, uint8_t subindex, const uint8_t *data, size_t data_size, uint32_t *abort_code) { ec_sdo_request_t request; @@ -2920,7 +2921,7 @@ int ecrt_master_sdo_download(ec_master_t *master, uint16_t slave_position, /****************************************************************************/ int ecrt_master_sdo_download_complete(ec_master_t *master, - uint16_t slave_position, uint16_t index, uint8_t *data, + uint16_t slave_position, uint16_t index, const uint8_t *data, size_t data_size, uint32_t *abort_code) { ec_sdo_request_t request; @@ -3084,7 +3085,7 @@ int ecrt_master_sdo_upload(ec_master_t *master, uint16_t slave_position, /****************************************************************************/ int ecrt_master_write_idn(ec_master_t *master, uint16_t slave_position, - uint8_t drive_no, uint16_t idn, uint8_t *data, size_t data_size, + uint8_t drive_no, uint16_t idn, const uint8_t *data, size_t data_size, uint16_t *error_code) { ec_soe_request_t request; diff --git a/master/reg_request.c b/master/reg_request.c index 627061be..29f7d4e2 100644 --- a/master/reg_request.c +++ b/master/reg_request.c @@ -75,7 +75,7 @@ void ec_reg_request_clear( * Application interface. ****************************************************************************/ -uint8_t *ecrt_reg_request_data(ec_reg_request_t *reg) +uint8_t *ecrt_reg_request_data(const ec_reg_request_t *reg) { return reg->data; } diff --git a/master/rtdm.c b/master/rtdm.c index e28c26de..f9a15b1c 100644 --- a/master/rtdm.c +++ b/master/rtdm.c @@ -33,6 +33,7 @@ #include "master.h" #include "ioctl.h" #include "rtdm.h" +#include "rtdm_details.h" /** Set to 1 to enable device operations debugging. */ @@ -40,20 +41,12 @@ /****************************************************************************/ -/** Context structure for an open RTDM file handle. - */ -typedef struct { - rtdm_user_info_t *user_info; /**< RTDM user data. */ - ec_ioctl_context_t ioctl_ctx; /**< Context structure. */ -} ec_rtdm_context_t; - -/****************************************************************************/ - -int ec_rtdm_open(struct rtdm_dev_context *, rtdm_user_info_t *, int); -int ec_rtdm_close(struct rtdm_dev_context *, rtdm_user_info_t *); -int ec_rtdm_ioctl(struct rtdm_dev_context *, rtdm_user_info_t *, +static int ec_rtdm_open(struct rtdm_dev_context *, rtdm_user_info_t *, int); +static int ec_rtdm_close(struct rtdm_dev_context *, rtdm_user_info_t *); +static int ec_rtdm_ioctl_nrt_handler(struct rtdm_dev_context *, rtdm_user_info_t *, + unsigned int, void __user *); +static int ec_rtdm_ioctl_rt_handler(struct rtdm_dev_context *, rtdm_user_info_t *, unsigned int, void __user *); - /****************************************************************************/ /** Initialize an RTDM device. @@ -82,8 +75,8 @@ int ec_rtdm_dev_init( "EtherCAT%u", master->index); rtdm_dev->dev->open_nrt = ec_rtdm_open; rtdm_dev->dev->ops.close_nrt = ec_rtdm_close; - rtdm_dev->dev->ops.ioctl_rt = ec_rtdm_ioctl; - rtdm_dev->dev->ops.ioctl_nrt = ec_rtdm_ioctl; + rtdm_dev->dev->ops.ioctl_rt = ec_rtdm_ioctl_rt_handler; + rtdm_dev->dev->ops.ioctl_nrt = ec_rtdm_ioctl_nrt_handler; rtdm_dev->dev->device_class = RTDM_CLASS_EXPERIMENTAL; rtdm_dev->dev->device_sub_class = 222; rtdm_dev->dev->driver_name = "EtherCAT"; @@ -132,7 +125,7 @@ void ec_rtdm_dev_clear( * * \return Always zero (success). */ -int ec_rtdm_open( +static int ec_rtdm_open( struct rtdm_dev_context *context, /**< Context. */ rtdm_user_info_t *user_info, /**< User data. */ int oflags /**< Open flags. */ @@ -143,7 +136,7 @@ int ec_rtdm_open( ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) context->device->device_data; #endif - ctx->user_info = user_info; + ctx->user_fd = user_info; ctx->ioctl_ctx.writable = oflags & O_WRONLY || oflags & O_RDWR; ctx->ioctl_ctx.requested = 0; ctx->ioctl_ctx.process_data = NULL; @@ -162,7 +155,7 @@ int ec_rtdm_open( * * \return Always zero (success). */ -int ec_rtdm_close( +static int ec_rtdm_close( struct rtdm_dev_context *context, /**< Context. */ rtdm_user_info_t *user_info /**< User data. */ ) @@ -187,7 +180,7 @@ int ec_rtdm_close( * * \return ioctl() return code. */ -int ec_rtdm_ioctl( +static int ec_rtdm_ioctl_nrt_handler( struct rtdm_dev_context *context, /**< Context. */ rtdm_user_info_t *user_info, /**< User data. */ unsigned int request, /**< Request. */ @@ -202,7 +195,32 @@ int ec_rtdm_ioctl( " on RTDM device %s.\n", request, _IOC_NR(request), context->device->device_name); #endif - return ec_ioctl_rtdm(rtdm_dev->master, &ctx->ioctl_ctx, request, arg); + return ec_ioctl_rtdm_nrt(rtdm_dev->master, &ctx->ioctl_ctx, request, arg); +} + +static int ec_rtdm_ioctl_rt_handler( + struct rtdm_dev_context *context, /**< Context. */ + rtdm_user_info_t *user_info, /**< User data. */ + unsigned int request, /**< Request. */ + void __user *arg /**< Argument. */ + ) +{ + int result; + ec_rtdm_context_t *ctx = (ec_rtdm_context_t *) context->dev_private; + ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) context->device->device_data; + +#if DEBUG + EC_MASTER_INFO(rtdm_dev->master, "ioctl(request = %u, ctl = %02x)" + " on RTDM device %s.\n", request, _IOC_NR(request), + context->device->device_name); +#endif + result = ec_ioctl_rtdm_rt(rtdm_dev->master, &ctx->ioctl_ctx, request, arg); + + if (result == -ENOTTY) { + /* Try again with nrt ioctl handler above in secondary mode. */ + return -ENOSYS; + } + return result; } /****************************************************************************/ @@ -220,7 +238,7 @@ int ec_rtdm_mmap( container_of(ioctl_ctx, ec_rtdm_context_t, ioctl_ctx); int ret; - ret = rtdm_mmap_to_user(ctx->user_info, + ret = rtdm_mmap_to_user(ctx->user_fd, ioctl_ctx->process_data, ioctl_ctx->process_data_size, PROT_READ | PROT_WRITE, user_address, diff --git a/master/rtdm_details.h b/master/rtdm_details.h new file mode 100644 index 00000000..9bea0636 --- /dev/null +++ b/master/rtdm_details.h @@ -0,0 +1,64 @@ +/***************************************************************************** + * + * Copyright (C) 2024 Bjarne von Horn + * + * This file is part of the IgH EtherCAT master. + * + * The IgH EtherCAT master is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * The IgH EtherCAT master 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 the IgH EtherCAT master. If not, see . + * + * The license mentioned above concerns the source code only. Using the + * EtherCAT technology and brand is only permitted in compliance with the + * industrial property and similar rights of Beckhoff Automation GmbH. + * + ****************************************************************************/ + + +#ifndef __EC_RTDM_DETAILS_H__ +#define __EC_RTDM_DETAILS_H__ + +#include "../config.h" +#include "ioctl.h" + +#include + +#ifdef EC_RTDM_XENOMAI_V3 + +#include +#define EC_RTDM_USERFD_T struct rtdm_fd + +#else // EC_RTDM_XENOMAI_V3 + +#include + +#define EC_RTDM_USERFD_T rtdm_user_info_t + +#endif // EC_RTDM_XENOMAI_V3 + +/****************************************************************************/ + +/** Context structure for an open RTDM file handle. + */ +typedef struct ec_rtdm_context { + EC_RTDM_USERFD_T *user_fd; /**< RTDM user data. */ + ec_ioctl_context_t ioctl_ctx; /**< Context structure. */ +} ec_rtdm_context_t; + +/****************************************************************************/ + +static inline EC_RTDM_USERFD_T *ec_ioctl_to_rtdm(ec_ioctl_context_t *ctx) +{ + return container_of(ctx, ec_rtdm_context_t, ioctl_ctx)->user_fd; +} + + +#endif // __EC_RTDM_DETAILS_H__ diff --git a/master/rtdm_xenomai_v3.c b/master/rtdm_xenomai_v3.c new file mode 100644 index 00000000..09a969c1 --- /dev/null +++ b/master/rtdm_xenomai_v3.c @@ -0,0 +1,178 @@ +/***************************************************************************** + * + * $Id$ + * + * Copyright (C) 2009-2010 Moehwald GmbH B. Benner + * 2011 IgH Andreas Stewering-Bone + * 2012 Florian Pose + * + * This file is part of the IgH EtherCAT master. + * + * The IgH EtherCAT master is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * The IgH EtherCAT master 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 the IgH EtherCAT master. If not, see . + * + * The license mentioned above concerns the source code only. Using the + * EtherCAT technology and brand is only permitted in compliance with the + * industrial property and similar rights of Beckhoff Automation GmbH. + * + ****************************************************************************/ + +/** \file + * RTDM interface. + */ + +#include +#include +#include + +#include "master.h" +#include "ioctl.h" +#include "rtdm.h" +#include "rtdm_details.h" + +/** Set to 1 to enable device operations debugging. + */ +#define DEBUG_RTDM 0 + +static int ec_rtdm_open(struct rtdm_fd *fd, int oflags) +{ + struct ec_rtdm_context *ctx = rtdm_fd_to_private(fd); +#if DEBUG_RTDM + struct rtdm_device *dev = rtdm_fd_device(fd); + ec_rtdm_dev_t *rtdm_dev = dev->device_data; +#endif + + ctx->user_fd = fd; + + ctx->ioctl_ctx.writable = oflags & O_WRONLY || oflags & O_RDWR; + ctx->ioctl_ctx.requested = 0; + ctx->ioctl_ctx.process_data = NULL; + ctx->ioctl_ctx.process_data_size = 0; + +#if DEBUG_RTDM + EC_MASTER_INFO(rtdm_dev->master, "RTDM device %s opened.\n", + dev->name); +#endif + + return 0; +} + +static void ec_rtdm_close(struct rtdm_fd *fd) +{ + struct ec_rtdm_context *ctx = rtdm_fd_to_private(fd); + struct rtdm_device *dev = rtdm_fd_device(fd); + ec_rtdm_dev_t *rtdm_dev = dev->device_data; + + if (ctx->ioctl_ctx.requested) + ecrt_release_master(rtdm_dev->master); + + if (ctx->ioctl_ctx.process_data) + vfree(ctx->ioctl_ctx.process_data); + +#if DEBUG_RTDM + EC_MASTER_INFO(rtdm_dev->master, "RTDM device %s closed.\n", + dev->name); +#endif +} + +static int ec_rtdm_ioctl_rt_handler(struct rtdm_fd *fd, unsigned int request, + void __user *arg) +{ + int result; + struct ec_rtdm_context *ctx = rtdm_fd_to_private(fd); + struct rtdm_device *dev = rtdm_fd_device(fd); + ec_rtdm_dev_t *rtdm_dev = dev->device_data; + + result = ec_ioctl_rtdm_rt(rtdm_dev->master, &ctx->ioctl_ctx, request, arg); + + if (result == -ENOTTY) + /* Try again with nrt ioctl handler below in secondary mode. */ + return -ENOSYS; + + return result; +} + +static int ec_rtdm_ioctl_nrt_handler(struct rtdm_fd *fd, unsigned int request, + void __user *arg) +{ + struct ec_rtdm_context *ctx = rtdm_fd_to_private(fd); + struct rtdm_device *dev = rtdm_fd_device(fd); + ec_rtdm_dev_t *rtdm_dev = dev->device_data; + + return ec_ioctl_rtdm_nrt(rtdm_dev->master, &ctx->ioctl_ctx, request, arg); +} + +static int ec_rtdm_mmap(struct rtdm_fd *fd, struct vm_area_struct *vma) +{ + struct ec_rtdm_context *ctx = (struct ec_rtdm_context *) rtdm_fd_to_private(fd); + return rtdm_mmap_kmem(vma, (void *)ctx->ioctl_ctx.process_data); +} + +static struct rtdm_driver ec_rtdm_driver = { + .profile_info = RTDM_PROFILE_INFO(ec_rtdm, + RTDM_CLASS_EXPERIMENTAL, + 222, + 0), + .device_flags = RTDM_NAMED_DEVICE, + .device_count = 1, + .context_size = sizeof(struct ec_rtdm_context), + .ops = { + .open = ec_rtdm_open, + .close = ec_rtdm_close, + .ioctl_rt = ec_rtdm_ioctl_rt_handler, + .ioctl_nrt = ec_rtdm_ioctl_nrt_handler, + .mmap = ec_rtdm_mmap, + }, +}; + +int ec_rtdm_dev_init(ec_rtdm_dev_t *rtdm_dev, ec_master_t *master) +{ + struct rtdm_device *dev; + int ret; + + rtdm_dev->master = master; + + rtdm_dev->dev = kzalloc(sizeof(struct rtdm_device), GFP_KERNEL); + if (!rtdm_dev->dev) { + EC_MASTER_ERR(master, + "Failed to reserve memory for RTDM device.\n"); + return -ENOMEM; + } + + dev = rtdm_dev->dev; + + dev->driver = &ec_rtdm_driver; + dev->device_data = rtdm_dev; + dev->label = "EtherCAT%u"; + + ret = rtdm_dev_register(dev); + if (ret) { + EC_MASTER_ERR(master, "Initialization of RTDM interface failed" + " (return value %i).\n", ret); + kfree(dev); + return ret; + } + + EC_MASTER_INFO(master, "Registered RTDM device %s.\n", dev->name); + + return 0; +} + +void ec_rtdm_dev_clear(ec_rtdm_dev_t *rtdm_dev) +{ + rtdm_dev_unregister(rtdm_dev->dev); + + EC_MASTER_INFO(rtdm_dev->master, "Unregistered RTDM device %s.\n", + rtdm_dev->dev->name); + + kfree(rtdm_dev->dev); +} diff --git a/master/sdo_request.c b/master/sdo_request.c index 3a4c66c6..d0de57db 100644 --- a/master/sdo_request.c +++ b/master/sdo_request.c @@ -194,7 +194,7 @@ void ecrt_sdo_request_timeout(ec_sdo_request_t *req, uint32_t timeout) /****************************************************************************/ -uint8_t *ecrt_sdo_request_data(ec_sdo_request_t *req) +uint8_t *ecrt_sdo_request_data(const ec_sdo_request_t *req) { return req->data; } diff --git a/master/slave_config.c b/master/slave_config.c index b68cfd14..d09d4055 100644 --- a/master/slave_config.c +++ b/master/slave_config.c @@ -1121,7 +1121,7 @@ int ecrt_slave_config_emerg_clear(ec_slave_config_t *sc) /****************************************************************************/ -int ecrt_slave_config_emerg_overruns(ec_slave_config_t *sc) +int ecrt_slave_config_emerg_overruns(const ec_slave_config_t *sc) { return ec_coe_emerg_ring_overruns(&sc->emerg_ring); } diff --git a/master/soe_request.c b/master/soe_request.c index 7acd50bf..20aa231a 100644 --- a/master/soe_request.c +++ b/master/soe_request.c @@ -279,7 +279,7 @@ void ecrt_soe_request_timeout(ec_soe_request_t *req, uint32_t timeout) /****************************************************************************/ -uint8_t *ecrt_soe_request_data(ec_soe_request_t *req) +uint8_t *ecrt_soe_request_data(const ec_soe_request_t *req) { return req->data; } diff --git a/master/voe_handler.c b/master/voe_handler.c index 68df5397..bc09069e 100644 --- a/master/voe_handler.c +++ b/master/voe_handler.c @@ -134,7 +134,7 @@ void ecrt_voe_handler_received_header(const ec_voe_handler_t *voe, /****************************************************************************/ -uint8_t *ecrt_voe_handler_data(ec_voe_handler_t *voe) +uint8_t *ecrt_voe_handler_data(const ec_voe_handler_t *voe) { return voe->datagram.data + EC_MBOX_HEADER_SIZE + EC_VOE_HEADER_SIZE; }