diff options
79 files changed, 8271 insertions, 3160 deletions
diff --git a/meta-openbmc-mods/conf/layer.conf b/meta-openbmc-mods/conf/layer.conf index 8fcab4a0a..9cc62fc6a 100644 --- a/meta-openbmc-mods/conf/layer.conf +++ b/meta-openbmc-mods/conf/layer.conf @@ -8,7 +8,7 @@ BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ BBFILE_COLLECTIONS += "intel" BBFILE_PATTERN_intel = "^${LAYERDIR}/" BBFILE_PRIORITY_intel = "5" -LAYERSERIES_COMPAT_intel = "sumo" +LAYERSERIES_COMPAT_intel = "thud" IMAGE_FEATURES[validitems] += "tools-sdk tools-debug" diff --git a/meta-openbmc-mods/conf/machine/include/intel.inc b/meta-openbmc-mods/conf/machine/include/intel.inc index 7fe8bf50f..20ca34a66 100644 --- a/meta-openbmc-mods/conf/machine/include/intel.inc +++ b/meta-openbmc-mods/conf/machine/include/intel.inc @@ -10,6 +10,8 @@ OBMC_MACHINE_FEATURES += "\ VIRTUAL-RUNTIME_skeleton_workbook = "${MACHINE}-config" +VIRTUAL-RUNTIME_obmc-led-monitor = "" + PREFERRED_PROVIDER_virtual/obmc-host-ipmi-hw = "phosphor-ipmi-kcs" PREFERRED_PROVIDER_virtual/obmc-chassis-mgmt = "packagegroup-intel-apps" PREFERRED_PROVIDER_virtual/obmc-fan-mgmt = "packagegroup-intel-apps" diff --git a/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass b/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass index 7deca9c05..fad660450 100644 --- a/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass +++ b/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass @@ -29,6 +29,7 @@ IMAGE_INSTALL_append = " \ frb2-watchdog \ srvcfg-manager \ callback-manager \ + post-code-manager \ " # this package was flagged as a security risk diff --git a/meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/at-scale-debug.bb b/meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/at-scale-debug.bb index 8d4a67ec5..de30d52b7 100644 --- a/meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/at-scale-debug.bb +++ b/meta-openbmc-mods/meta-common/recipes-core/at-scale-debug/at-scale-debug.bb @@ -13,7 +13,7 @@ do_configure[depends] += "virtual/kernel:do_shared_workdir" SRC_URI = "git://git@github.com/Intel-BMC/at-scale-debug;protocol=ssh" -SRCREV = "de77d02aefa3c9df62365e7f07224c5cf9b0eb96" +SRCREV = "c4c223bdbe5b58a7acad12dc9700365330f2df1c" S = "${WORKDIR}/git" SYSTEMD_SERVICE_${PN} += "com.intel.AtScaleDebug.service" diff --git a/meta-openbmc-mods/meta-common/recipes-core/bmcweb/bmcweb/0001-Refine-KVM-websock-proxy.patch b/meta-openbmc-mods/meta-common/recipes-core/bmcweb/bmcweb/0001-Refine-KVM-websock-proxy.patch deleted file mode 100644 index acbfebdee..000000000 --- a/meta-openbmc-mods/meta-common/recipes-core/bmcweb/bmcweb/0001-Refine-KVM-websock-proxy.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 430bfc33ee396e4aced0514b66703e5c58a7503d Mon Sep 17 00:00:00 2001 -From: Jae Hyun Yoo <jae.hyun.yoo@intel.com> -Date: Tue, 26 Feb 2019 15:46:07 -0800 -Subject: [PATCH] Refine KVM websock proxy - -This commit simplifies input buffer delivering logic by removing -a doWrite() call from readDone(). Input events can be delivered -through websocket's onmessage handler only and it's enough. - -Also, it fixes a suspicious weak point of commit/consume pair on -outputBuffer. - -Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com> ---- - include/kvm_websocket.hpp | 57 +++++++++++++++++++++-------------------------- - 1 file changed, 26 insertions(+), 31 deletions(-) - -diff --git a/include/kvm_websocket.hpp b/include/kvm_websocket.hpp -index aa2eaecc3205..447171b9981a 100644 ---- a/include/kvm_websocket.hpp -+++ b/include/kvm_websocket.hpp -@@ -20,53 +20,48 @@ static boost::beast::flat_static_buffer<1024U> inputBuffer; - - static crow::websocket::Connection* session = nullptr; - --static bool doingWrite = false; -+inline void doWrite(); - --inline void doWrite() -+inline void WriteDone(const boost::system::error_code& ec, -+ std::size_t bytesWritten) - { -- if (doingWrite) -+ BMCWEB_LOG_DEBUG << "Wrote " << bytesWritten << "bytes"; -+ inputBuffer.consume(bytesWritten); -+ -+ if (session == nullptr) -+ { -+ return; -+ } -+ if (ec == boost::asio::error::eof) -+ { -+ session->close("KVM socket port closed"); -+ return; -+ } -+ if (ec) - { -- BMCWEB_LOG_DEBUG << "Already writing. Bailing out"; -+ session->close("Error in reading to host port"); -+ BMCWEB_LOG_ERROR << "Error in KVM socket write " << ec; - return; - } -+ -+ doWrite(); -+} -+ -+inline void doWrite() -+{ - if (inputBuffer.size() == 0) - { - BMCWEB_LOG_DEBUG << "inputBuffer empty. Bailing out"; - return; - } - -- doingWrite = true; -- hostSocket->async_write_some( -- inputBuffer.data(), -- [](boost::beast::error_code ec, std::size_t bytes_written) { -- BMCWEB_LOG_DEBUG << "Wrote " << bytes_written << "bytes"; -- doingWrite = false; -- inputBuffer.consume(bytes_written); -- -- if (session == nullptr) -- { -- return; -- } -- if (ec == boost::asio::error::eof) -- { -- session->close("KVM socket port closed"); -- return; -- } -- if (ec) -- { -- session->close("Error in reading to host port"); -- BMCWEB_LOG_ERROR << "Error in KVM socket write " << ec; -- return; -- } -- doWrite(); -- }); -+ hostSocket->async_write_some(inputBuffer.data(), WriteDone); - } - - inline void doRead(); - - inline void readDone(const boost::system::error_code& ec, std::size_t bytesRead) - { -- outputBuffer.commit(bytesRead); - BMCWEB_LOG_DEBUG << "read done. Read " << bytesRead << " bytes"; - if (ec) - { -@@ -82,6 +77,7 @@ inline void readDone(const boost::system::error_code& ec, std::size_t bytesRead) - return; - } - -+ outputBuffer.commit(bytesRead); - boost::beast::string_view payload( - static_cast<const char*>(outputBuffer.data().data()), bytesRead); - BMCWEB_LOG_DEBUG << "Sending payload size " << payload.size(); -@@ -112,7 +108,6 @@ inline void connectHandler(const boost::system::error_code& ec) - return; - } - -- doWrite(); - doRead(); - } - --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-core/bmcweb/bmcweb_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/bmcweb/bmcweb_%.bbappend index 8d5a43c51..7f07e48ea 100644 --- a/meta-openbmc-mods/meta-common/recipes-core/bmcweb/bmcweb_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-core/bmcweb/bmcweb_%.bbappend @@ -6,8 +6,6 @@ GROUPADD_PARAM_${PN} = "web; redfish " FILESEXTRAPATHS_append := ":${THISDIR}/${PN}" -SRC_URI += "file://0001-Refine-KVM-websock-proxy.patch" - # Enable CPU Log and Raw PECI support EXTRA_OECMAKE += "-DBMCWEB_ENABLE_REDFISH_CPU_LOG=ON" EXTRA_OECMAKE += "-DBMCWEB_ENABLE_REDFISH_RAW_PECI=ON" diff --git a/meta-openbmc-mods/meta-common/recipes-core/cpu-log-util/cpu-log-util_git.bb b/meta-openbmc-mods/meta-common/recipes-core/cpu-log-util/cpu-log-util_git.bb index 10793689b..8419fb483 100644 --- a/meta-openbmc-mods/meta-common/recipes-core/cpu-log-util/cpu-log-util_git.bb +++ b/meta-openbmc-mods/meta-common/recipes-core/cpu-log-util/cpu-log-util_git.bb @@ -11,7 +11,7 @@ LICENSE = "CLOSED" LIC_FILES_CHKSUM = "" SRC_URI = "git://git@github.com/Intel-BMC/at-scale-debug;protocol=ssh" -SRCREV = "de77d02aefa3c9df62365e7f07224c5cf9b0eb96" +SRCREV = "c4c223bdbe5b58a7acad12dc9700365330f2df1c" S = "${WORKDIR}/git/cpu-log-util" PACKAGES += "libpeci" diff --git a/meta-openbmc-mods/meta-common/recipes-core/fw-update/files/usb-ctrl b/meta-openbmc-mods/meta-common/recipes-core/fw-update/files/usb-ctrl new file mode 100644 index 000000000..ae9f54263 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/fw-update/files/usb-ctrl @@ -0,0 +1,136 @@ +#!/bin/sh + +setup_image() +{ + set -x + local storage="$1" + local sz_mb="$2" + # create the backing store + dd if=/dev/zero of=$storage bs=1M seek=$sz_mb count=0 2>/dev/null + # this shows up as 23FC-F676 in /dev/disk/by-uuid + local diskid=0x23FCF676 + mkdosfs -n 'OPENBMC-FW' -i $diskid -I $storage >/dev/null 2>&1 +} + +mount_image() +{ + set -x + local storage="$1" + local stormnt="$2" + mkdir -p $stormnt || exit 1 + mount -o loop -t vfat $storage $stormnt +} + +cleanup_image() +{ + set -x + local storage="$1" + local stormnt="$2" + umount -f "$stormnt" + rm -f "$storage" + rmdir "$stormnt" +} + +GADGET_BASE=/sys/kernel/config/usb_gadget + +which_dev() +{ + local in_use=$(cat $GADGET_BASE/*/UDC) + cd /sys/class/udc + for D in *; do + case "$in_use" in + *"$D"*) ;; + *) echo "$D"; return 0;; + esac + done + return 1 +} + +usb_ms_insert() +{ + local name="$1" + local storage="$2" + + if [ -d $GADGET_BASE/$name ]; then + echo "device $name already exists" >&2 + return 1 + fi + mkdir $GADGET_BASE/$name + cd $GADGET_BASE/$name + + echo 0x1d6b > idVendor # Linux Foundation + echo 0x0105 > idProduct # FunctionFS Gadget + mkdir strings/0x409 + local machineid=$(cat /etc/machine-id) + local data="OpenBMC USB mass storage gadget device serial number" + local serial=$( echo -n "${machineid}${data}${machineid}" | \ + sha256sum | cut -b 0-12 ) + echo $serial > strings/0x409/serialnumber + echo OpenBMC > strings/0x409/manufacturer + echo "OpenBMC Mass Storage" > strings/0x409/product + + mkdir configs/c.1 + mkdir functions/mass_storage.$name + echo $storage > functions/mass_storage.$name/lun.0/file + echo 0 > functions/mass_storage.$name/lun.0/removable + mkdir configs/c.1/strings/0x409 + + echo "Conf 1" > configs/c.1/strings/0x409/configuration + echo 120 > configs/c.1/MaxPower + ln -s functions/mass_storage.$name configs/c.1 + local dev=$(which_dev) + echo $dev > UDC +} + +usb_ms_eject() +{ + local name="$1" + + echo '' > $GADGET_BASE/$name/UDC + + rm -f $GADGET_BASE/$name/configs/c.1/mass_storage.$name + rmdir $GADGET_BASE/$name/configs/c.1/strings/0x409 + rmdir $GADGET_BASE/$name/configs/c.1 + rmdir $GADGET_BASE/$name/functions/mass_storage.$name + rmdir $GADGET_BASE/$name/strings/0x409 + rmdir $GADGET_BASE/$name +} + +usage() +{ + echo "Usage: $0 <action> ..." + echo " $0 setup <file> <sizeMB>" + echo " $0 insert <name> <file>" + echo " $0 eject <name>" + echo " $0 mount <file> <mnt>" + echo " $0 cleanup <file> <mnt>" + exit 1 +} + +echo "$#: $0 $@" +case "$1" in + insert) + shift + usb_ms_insert "$@" + ;; + eject) + shift + usb_ms_eject "$@" + ;; + setup) + shift + setup_image "$@" + ;; + mount) + shift + mount_image "$@" + ;; + cleanup) + shift + cleanup_image "$@" + ;; + *) + usage + ;; +esac +exit $? diff --git a/meta-openbmc-mods/meta-common/recipes-core/fw-update/intel-fw-update.bb b/meta-openbmc-mods/meta-common/recipes-core/fw-update/intel-fw-update.bb index ea39e62be..ac8e58c03 100644 --- a/meta-openbmc-mods/meta-common/recipes-core/fw-update/intel-fw-update.bb +++ b/meta-openbmc-mods/meta-common/recipes-core/fw-update/intel-fw-update.bb @@ -6,13 +6,17 @@ PR = "r1" RDEPENDS_intel-fw-update += "mtd-utils" # wget tftp scp RDEPENDS_intel-fw-update += "busybox dropbear" +# mkfs.vfat, parted +RDEPENDS_intel-fw-update += "dosfstools parted" LICENSE = "Apache-2.0" LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658" SRC_URI += "file://fwupd.sh" +SRC_URI += "file://usb-ctrl" do_install() { install -d ${D}${bindir} install -m 0755 ${WORKDIR}/fwupd.sh ${D}${bindir} + install -m 0755 ${WORKDIR}/usb-ctrl ${D}${bindir} } diff --git a/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem_%.bbappend index a7c19f708..5526d9c6b 100644 --- a/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-core/ipmi/intel-ipmi-oem_%.bbappend @@ -1,2 +1,2 @@ SRC_URI = "git://github.com/openbmc/intel-ipmi-oem.git" -SRCREV = "fcce83df799d9580f48b7f793989c9c96bc882e0" +SRCREV = "7086a88cfe94db15233bae450b3a03d3566bca68" diff --git a/meta-openbmc-mods/meta-common/recipes-core/ipmi/ipmi-providers.bb b/meta-openbmc-mods/meta-common/recipes-core/ipmi/ipmi-providers.bb index 9e620a19c..c23da6df2 100644 --- a/meta-openbmc-mods/meta-common/recipes-core/ipmi/ipmi-providers.bb +++ b/meta-openbmc-mods/meta-common/recipes-core/ipmi/ipmi-providers.bb @@ -2,7 +2,7 @@ SUMMARY = "Intel IPMI Providers" DESCRIPTION = "IPMI Provider Libraries" SRC_URI = "git://git@github.com/Intel-BMC/intel-ipmi-providers;protocol=ssh" -SRCREV = "3573b25576d14b3334f93bd988c6e2003fab8f90" +SRCREV = "bbb45687fc2993980ac95117d8503ee6c2358965" S = "${WORKDIR}/git" PV = "0.1+git${SRCPV}" diff --git a/meta-openbmc-mods/meta-common/recipes-core/peci-pcie/peci-pcie_git.bb b/meta-openbmc-mods/meta-common/recipes-core/peci-pcie/peci-pcie_git.bb index 91eed5a82..2e89c27c1 100644 --- a/meta-openbmc-mods/meta-common/recipes-core/peci-pcie/peci-pcie_git.bb +++ b/meta-openbmc-mods/meta-common/recipes-core/peci-pcie/peci-pcie_git.bb @@ -10,7 +10,7 @@ SRC_URI = "git://git@github.com/Intel-BMC/provingground;protocol=ssh" DEPENDS = "boost sdbusplus cpu-log-util" PV = "0.1+git${SRCPV}" -SRCREV = "3cc86d6c536b4c5ee7afb5447837b83ce8b3d149" +SRCREV = "c927781ad3ca1408cd7fb0b7cc2538ea10ded76b" S = "${WORKDIR}/git/peci_pcie" diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/.clang-format b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/.clang-format deleted file mode 100644 index 8c5278e6f..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/.clang-format +++ /dev/null @@ -1,98 +0,0 @@ ---- -Language: Cpp -# BasedOnStyle: LLVM -AccessModifierOffset: -2 -AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: false -AlignConsecutiveDeclarations: false -AlignEscapedNewlinesLeft: false -AlignOperands: true -AlignTrailingComments: true -AllowAllParametersOfDeclarationOnNextLine: true -AllowShortBlocksOnASingleLine: false -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: None -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: true -BinPackArguments: true -BinPackParameters: true -BraceWrapping: - AfterClass: true - AfterControlStatement: true - AfterEnum: true - AfterFunction: true - AfterNamespace: true - AfterObjCDeclaration: true - AfterStruct: true - AfterUnion: true - BeforeCatch: true - BeforeElse: true - IndentBraces: false -BreakBeforeBinaryOperators: None -BreakBeforeBraces: Custom -BreakBeforeTernaryOperators: true -BreakConstructorInitializers: AfterColon -ColumnLimit: 80 -CommentPragmas: '^ IWYU pragma:' -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 4 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -DerivePointerAlignment: false -DisableFormat: false -ExperimentalAutoDetectBinPacking: false -FixNamespaceComments: true -ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] -IncludeBlocks: Regroup -IncludeCategories: - - Regex: '^[<"](gtest|gmock)' - Priority: 5 - - Regex: '^"config.h"' - Priority: -1 - - Regex: '^".*\.hpp"' - Priority: 1 - - Regex: '^<.*\.h>' - Priority: 2 - - Regex: '^<.*' - Priority: 3 - - Regex: '.*' - Priority: 4 -IndentCaseLabels: true -IndentWidth: 4 -IndentWrappedFunctionNames: true -KeepEmptyLinesAtTheStartOfBlocks: true -MacroBlockBegin: '' -MacroBlockEnd: '' -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -ObjCBlockIndentWidth: 2 -ObjCSpaceAfterProperty: false -ObjCSpaceBeforeProtocolList: true -PenaltyBreakBeforeFirstCallParameter: 19 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakString: 1000 -PenaltyExcessCharacter: 1000000 -PenaltyReturnTypeOnItsOwnLine: 60 -PointerAlignment: Left -ReflowComments: true -SortIncludes: true -SortUsingDeclarations: true -SpaceAfterCStyleCast: false -SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: ControlStatements -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: false -SpacesInContainerLiterals: true -SpacesInCStyleCastParentheses: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: Cpp11 -TabWidth: 4 -UseTab: Never -... diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0001-Fix-video-restarting-sync-issue.patch b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0001-Fix-video-restarting-sync-issue.patch new file mode 100644 index 000000000..0c9267796 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0001-Fix-video-restarting-sync-issue.patch @@ -0,0 +1,57 @@ +From 561e73cf200fa25a2c2f1ede4e4c899e192a95a4 Mon Sep 17 00:00:00 2001 +From: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com> +Date: Wed, 6 Mar 2019 15:39:58 -0800 +Subject: [PATCH] Fix video restarting sync issue + +There is a video start/stop sync issue inbetween ikvm server and +ikvm manager because newClient and clientGone callback called +by a different thread from libvncserver. To fix this issue, this +commit moves the video.start() call from server to manager to +unify video control thread. + +Tested: + Open KVM web page and reload the web page by pressing F5. + KVM page should be reloaded correctly. + +Change-Id: Ic0d14ea712510318e9e8f45615a95e82aeaaddf1 +Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com> +--- + ikvm_manager.cpp | 1 + + ikvm_server.cpp | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ikvm_manager.cpp b/ikvm_manager.cpp +index 5e014d057410..d56110dd977f 100644 +--- a/ikvm_manager.cpp ++++ b/ikvm_manager.cpp +@@ -21,6 +21,7 @@ void Manager::run() + { + if (server.wantsFrame()) + { ++ video.start(); + video.getFrame(); + server.sendFrame(); + } +diff --git a/ikvm_server.cpp b/ikvm_server.cpp +index 37a927b9d418..35310da292be 100644 +--- a/ikvm_server.cpp ++++ b/ikvm_server.cpp +@@ -154,6 +154,7 @@ void Server::clientGone(rfbClientPtr cl) + Server* server = (Server*)cl->screen->screenData; + + delete (ClientData*)cl->clientData; ++ cl->clientData = nullptr; + + if (server->numClients-- == 1) + { +@@ -173,7 +174,6 @@ enum rfbNewClientAction Server::newClient(rfbClientPtr cl) + { + server->pendingResize = false; + server->frameCounter = 0; +- server->video.start(); + } + + return RFB_CLIENT_ACCEPT; +-- +2.7.4 + diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0002-Restart-video-when-mode-detection-is-failed.patch b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0002-Restart-video-when-mode-detection-is-failed.patch new file mode 100644 index 000000000..9219b7dd0 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/0002-Restart-video-when-mode-detection-is-failed.patch @@ -0,0 +1,82 @@ +From 474addee4ed8da523bdc1cfe609099f9ebfb6f07 Mon Sep 17 00:00:00 2001 +From: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com> +Date: Fri, 15 Mar 2019 15:21:51 -0700 +Subject: [PATCH] Restart video when mode detection is failed + +KVM sometimes stops when video mode is changed. This commit adds +video restarting logic for the case. + +Tested: + 1. Open BMCWeb -> Server control -> KVM + 2. Checked KVM screen update while restarting the host. It + updates all frames even when video mode changes happen. + +Change-Id: If986394110986e49a6eaac1ae2859208fa7681f5 +Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com> +--- + ikvm_video.cpp | 23 +++++++++++++---------- + ikvm_video.hpp | 6 ++++++ + 2 files changed, 19 insertions(+), 10 deletions(-) + +diff --git a/ikvm_video.cpp b/ikvm_video.cpp +index ed5ed92ef131..a34cdf2c083f 100644 +--- a/ikvm_video.cpp ++++ b/ikvm_video.cpp +@@ -155,6 +155,7 @@ bool Video::needsResize() + { + log<level::ERR>("Failed to query timings", + entry("ERROR=%s", strerror(errno))); ++ restart(); + return false; + } + +@@ -265,17 +266,19 @@ void Video::resize() + xyz::openbmc_project::Common::Device::ReadFailure:: + CALLOUT_DEVICE_PATH(path.c_str())); + } +- +- rc = ioctl(fd, VIDIOC_S_DV_TIMINGS, &timings); +- if (rc < 0) ++ else + { +- log<level::ERR>("Failed to set timings", +- entry("ERROR=%s", strerror(errno))); +- elog<ReadFailure>( +- xyz::openbmc_project::Common::Device::ReadFailure:: +- CALLOUT_ERRNO(errno), +- xyz::openbmc_project::Common::Device::ReadFailure:: +- CALLOUT_DEVICE_PATH(path.c_str())); ++ rc = ioctl(fd, VIDIOC_S_DV_TIMINGS, &timings); ++ if (rc < 0) ++ { ++ log<level::ERR>("Failed to set timings", ++ entry("ERROR=%s", strerror(errno))); ++ elog<ReadFailure>( ++ xyz::openbmc_project::Common::Device::ReadFailure:: ++ CALLOUT_ERRNO(errno), ++ xyz::openbmc_project::Common::Device::ReadFailure:: ++ CALLOUT_DEVICE_PATH(path.c_str())); ++ } + } + + buffers.clear(); +diff --git a/ikvm_video.hpp b/ikvm_video.hpp +index 0e5f3afb27b4..faaa57d36f1a 100644 +--- a/ikvm_video.hpp ++++ b/ikvm_video.hpp +@@ -50,6 +50,12 @@ class Video + void start(); + /* @brief Stops streaming from the video device */ + void stop(); ++ /* @brief Restarts streaming from the video device */ ++ void restart() ++ { ++ stop(); ++ start(); ++ } + + /* + * @brief Gets the desired video frame rate in frames per second +-- +2.7.4 + diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/LICENSE b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/LICENSE deleted file mode 100644 index 8dada3eda..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/MAINTAINERS b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/MAINTAINERS deleted file mode 100644 index a5ab97e02..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/MAINTAINERS +++ /dev/null @@ -1,45 +0,0 @@ -How to use this list: - Find the most specific section entry (described below) that matches where - your change lives and add the reviewers (R) and maintainers (M) as - reviewers. You can use the same method to track down who knows a particular - code base best. - - Your change/query may span multiple entries; that is okay. - - If you do not find an entry that describes your request at all, someone - forgot to update this list; please at least file an issue or send an email - to a maintainer, but preferably you should just update this document. - -Description of section entries: - - Section entries are structured according to the following scheme: - - X: NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!> - X: ... - . - . - . - - Where REPO_NAME is the name of the repository within the OpenBMC GitHub - organization; FILE_PATH is a file path within the repository, possibly with - wildcards; X is a tag of one of the following types: - - M: Denotes maintainer; has fields NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!>; - if omitted from an entry, assume one of the maintainers from the - MAINTAINERS entry. - R: Denotes reviewer; has fields NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!>; - these people are to be added as reviewers for a change matching the repo - path. - F: Denotes forked from an external repository; has fields URL. - - Line comments are to be denoted "# SOME COMMENT" (typical shell style - comment); it is important to follow the correct syntax and semantics as we - may want to use automated tools with this file in the future. - - A change cannot be added to an OpenBMC repository without a MAINTAINER's - approval; thus, a MAINTAINER should always be listed as a reviewer. - -START OF MAINTAINERS LIST -------------------------- - -M: Eddie James <eajames@linux.ibm.com> <eajames!> diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/Makefile.am b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/Makefile.am deleted file mode 100644 index 1022b2e59..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/Makefile.am +++ /dev/null @@ -1,31 +0,0 @@ -bin_PROGRAMS = obmc-ikvm -dist_bin_SCRIPTS = create_usbhid.sh - -noinst_HEADERS = \ - ikvm_args.hpp \ - ikvm_input.hpp \ - ikvm_manager.hpp \ - ikvm_server.hpp \ - ikvm_video.hpp - -obmc_ikvm_SOURCES = \ - ikvm_args.cpp \ - ikvm_input.cpp \ - ikvm_manager.cpp \ - ikvm_server.cpp \ - ikvm_video.cpp \ - obmc-ikvm.cpp - -obmc_ikvm_CXXFLAGS = \ - $(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \ - $(PHOSPHOR_LOGGING_CFLAGS) \ - $(PTHREAD_CFLAGS) \ - $(SDBUSPLUS_CFLAGS) \ - $(LIBVNCSERVER_CFLAGS) - -obmc_ikvm_LDFLAGS = \ - $(PHOSPHOR_DBUS_INTERFACES_LIBS) \ - $(PHOSPHOR_LOGGING_LIBS) \ - $(PTHREAD_LIBS) \ - $(SDBUSPLUS_LIBS) \ - $(LIBVNCSERVER_LIBS) diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/README.md b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/README.md deleted file mode 100644 index 70d6e1373..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# OpenBMC IpKVM Server - -The obmc-ikvm application is a VNC server that provides access to the host -graphics output. The application interfaces with the video device on the BMC -that captures the host graphics, and then serves that video data on the RFB -(remote framebuffer, also known as VNC) protocol. The application also -interfaces with the BMC USB gadget device to pass HID events from the BMC to -the host, allowing the user to interact with the host system. - -## Usage - -Once the host is running and an appropriate HID gadget device is instantiated -on the BMC, the application can be started with the following command: -``` obmc-ikvm -v <video device path> -i <HID gadget device path> ``` - -For example: - -``` obmc-ikvm -v /dev/video0 -i /dev/hidg0 ``` diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/bootstrap.sh b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/bootstrap.sh deleted file mode 100644 index 50b75b7ee..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/bootstrap.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -AUTOCONF_FILES="Makefile.in aclocal.m4 ar-lib autom4te.cache compile \ - config.guess config.h.in config.sub configure depcomp install-sh \ - ltmain.sh missing *libtool test-driver" - -case $1 in - clean) - test -f Makefile && make maintainer-clean - for file in ${AUTOCONF_FILES}; do - find -name "$file" | xargs -r rm -rf - done - exit 0 - ;; -esac - -autoreconf -i -echo 'Run "./configure ${CONFIGURE_FLAGS} && make"' diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/configure.ac b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/configure.ac deleted file mode 100644 index 671316022..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/configure.ac +++ /dev/null @@ -1,29 +0,0 @@ -# Initialization -AC_PREREQ([2.69]) -AC_INIT([obmc-ikvm], [1.0], [https://github.com/openbmc/obmc-ikvm/issues]) -AC_LANG([C++]) -AC_CONFIG_HEADERS([config.h]) -AM_INIT_AUTOMAKE([subdir-objects -Wall -Werror foreign dist-xz]) -AM_SILENT_RULES([yes]) - -# Checks for programs. -AC_PROG_CXX -AM_PROG_AR -AC_PROG_INSTALL -AC_PROG_MAKE_SET - -# Checks for typedefs, structures, and compiler characteristics. -AX_CXX_COMPILE_STDCXX_17([noext]) -AX_APPEND_COMPILE_FLAGS([-Wall -Werror], [CXXFLAGS]) - -# Checks for libraries. -AC_CHECK_LIB([pthread], [pthread_create]) -PKG_CHECK_MODULES([LIBVNCSERVER], [libvncserver], , AC_MSG_ERROR(["Requires libvncserver package."])) -PKG_CHECK_MODULES([SDBUSPLUS], [sdbusplus], , AC_MSG_ERROR(["Requires sdbusplus package."])) -PKG_CHECK_MODULES([PHOSPHOR_LOGGING], [phosphor-logging], , AC_MSG_ERROR(["Requires phosphor-logging package."])) -PKG_CHECK_MODULES([PHOSPHOR_DBUS_INTERFACES], [phosphor-dbus-interfaces], , AC_MSG_ERROR(["Requires phosphor-dbus-interfaces package."])) - -LT_INIT - -AC_CONFIG_FILES([Makefile]) -AC_OUTPUT diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/create_usbhid.sh b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/create_usbhid.sh deleted file mode 100644 index 955f18b61..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/create_usbhid.sh +++ /dev/null @@ -1,135 +0,0 @@ -#!/bin/sh - -new_directory="/sys/kernel/config/usb_gadget/obmc_input" - -if [ -e "${new_directory}" ]; then - exit 0 -fi - -# create gadget -original_directory="$(pwd)" -mkdir "${new_directory}" -cd "${new_directory}" - -# add basic information -echo 0x0100 > bcdDevice -echo 0x0200 > bcdUSB -echo 0x0104 > idProduct # Multifunction Composite Gadget -echo 0x1d6b > idVendor # Linux Foundation - -# create English locale -mkdir strings/0x409 - -echo "OpenBMC" > strings/0x409/manufacturer -echo "virtual_input" > strings/0x409/product -echo "OBMC0001" > strings/0x409/serialnumber - -# Create HID keyboard function -mkdir functions/hid.0 - -echo 1 > functions/hid.0/protocol # 1: keyboard -echo 8 > functions/hid.0/report_length -echo 1 > functions/hid.0/subclass - -# Binary HID keyboard descriptor -# 0x05, 0x01, // USAGE_PAGE (Generic Desktop) -# 0x09, 0x06, // USAGE (Keyboard) -# 0xa1, 0x01, // COLLECTION (Application) -# 0x05, 0x07, // USAGE_PAGE (Keyboard) -# 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) -# 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) -# 0x15, 0x00, // LOGICAL_MINIMUM (0) -# 0x25, 0x01, // LOGICAL_MAXIMUM (1) -# 0x75, 0x01, // REPORT_SIZE (1) -# 0x95, 0x08, // REPORT_COUNT (8) -# 0x81, 0x02, // INPUT (Data,Var,Abs) -# 0x95, 0x01, // REPORT_COUNT (1) -# 0x75, 0x08, // REPORT_SIZE (8) -# 0x81, 0x03, // INPUT (Data,Var,Abs) -# 0x95, 0x05, // REPORT_COUNT (5) -# 0x75, 0x01, // REPORT_SIZE (1) -# 0x05, 0x08, // USAGE_PAGE (LEDs) -# 0x19, 0x01, // USAGE_MINIMUM (Num Lock) -# 0x29, 0x05, // USAGE_MAXIMUM (Kana) -# 0x91, 0x02, // OUTPUT (Data,Var,Abs) -# 0x95, 0x01, // REPORT_COUNT (1) -# 0x75, 0x03, // REPORT_SIZE (3) -# 0x91, 0x03, // OUTPUT (Cnst,Var,Abs) -# 0x95, 0x06, // REPORT_COUNT (6) -# 0x75, 0x08, // REPORT_SIZE (8) -# 0x15, 0x00, // LOGICAL_MINIMUM (0) -# 0x25, 0x65, // LOGICAL_MAXIMUM (101) -# 0x05, 0x07, // USAGE_PAGE (Keyboard) -# 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) -# 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) -# 0x81, 0x00, // INPUT (Data,Ary,Abs) -# 0xc0 // END_COLLECTION -echo -ne '\x05\x01\x09\x06\xa1\x01\x05\x07\x19\xe0\x29\xe7\x15\x00\x25\x01\x75\x01\x95\x08\x81\x02\x95\x01\x75\x08\x81\x03\x95\x05\x75\x01\x05\x08\x19\x01\x29\x05\x91\x02\x95\x01\x75\x03\x91\x03\x95\x06\x75\x08\x15\x00\x25\x65\x05\x07\x19\x00\x29\x65\x81\x00\xc0' > functions/hid.0/report_desc - -# Create HID mouse function -mkdir functions/hid.1 - -echo 2 > functions/hid.1/protocol # 2: mouse -echo 5 > functions/hid.1/report_length -echo 1 > functions/hid.1/subclass - -# Binary HID mouse descriptor (absolute coordinate) -# 0x05, 0x01, // USAGE_PAGE (Generic Desktop) -# 0x09, 0x02, // USAGE (Mouse) -# 0xa1, 0x01, // COLLECTION (Application) -# 0x09, 0x01, // USAGE (Pointer) -# 0xa1, 0x00, // COLLECTION (Physical) -# 0x05, 0x09, // USAGE_PAGE (Button) -# 0x19, 0x01, // USAGE_MINIMUM (Button 1) -# 0x29, 0x03, // USAGE_MAXIMUM (Button 3) -# 0x15, 0x00, // LOGICAL_MINIMUM (0) -# 0x25, 0x01, // LOGICAL_MAXIMUM (1) -# 0x95, 0x03, // REPORT_COUNT (3) -# 0x75, 0x01, // REPORT_SIZE (1) -# 0x81, 0x02, // INPUT (Data,Var,Abs) -# 0x95, 0x01, // REPORT_COUNT (1) -# 0x75, 0x05, // REPORT_SIZE (5) -# 0x81, 0x03, // INPUT (Cnst,Var,Abs) -# 0x05, 0x01, // USAGE_PAGE (Generic Desktop) -# 0x09, 0x30, // USAGE (X) -# 0x09, 0x31, // USAGE (Y) -# 0x35, 0x00, // PHYSICAL_MINIMUM (0) -# 0x46, 0xff, 0x7f, // PHYSICAL_MAXIMUM (32767) -# 0x15, 0x00, // LOGICAL_MINIMUM (0) -# 0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767) -# 0x65, 0x11, // UNIT (SI Lin:Distance) -# 0x55, 0x00, // UNIT_EXPONENT (0) -# 0x75, 0x10, // REPORT_SIZE (16) -# 0x95, 0x02, // REPORT_COUNT (2) -# 0x81, 0x02, // INPUT (Data,Var,Abs) -# 0xc0, // END_COLLECTION -# 0xc0 // END_COLLECTION -echo -ne '\x05\x01\x09\x02\xa1\x01\x09\x01\xa1\x00\x05\x09\x19\x01\x29\x03\x15\x00\x25\x01\x95\x03\x75\x01\x81\x02\x95\x01\x75\x05\x81\x03\x05\x01\x09\x30\x09\x31\x35\x00\x46\xff\x7f\x15\x00\x26\xff\x7f\x65\x11\x55\x00\x75\x10\x95\x02\x81\x02\xc0\xc0' > functions/hid.1/report_desc - -# Create configuration -mkdir configs/c.1 -mkdir configs/c.1/strings/0x409 - -echo 0x80 > configs/c.1/bmAttributes -echo 200 > configs/c.1/MaxPower -echo "" > configs/c.1/strings/0x409/configuration - -# Link HID functions to configuration -ln -s functions/hid.0 configs/c.1 -ln -s functions/hid.1 configs/c.1 - -# Enable gadget -dev_name="1e6a0000.usb-vhub" -i=0 -num_ports=5 -base_usb_dir="/sys/bus/platform/devices/${dev_name}/${dev_name}:p" -while [ $i -lt $num_ports ]; do - port=$(($i + 1)) - i=$port - if [ ! -e "${base_usb_dir}${port}/gadget/suspended" ]; then - break - fi -done -echo "${dev_name}:p${port}" > UDC - -cd "${original_directory}" diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_args.cpp b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_args.cpp deleted file mode 100644 index 2723187dd..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_args.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "ikvm_args.hpp" - -#include <getopt.h> -#include <rfb/rfb.h> -#include <stdio.h> -#include <stdlib.h> - -namespace ikvm -{ - -Args::Args(int argc, char* argv[]) : frameRate(30), commandLine(argc, argv) -{ - int option; - const char* opts = "f:h:k:p:v:"; - struct option lopts[] = {{"frameRate", 1, 0, 'f'}, {"help", 0, 0, 'h'}, - {"keyboard", 1, 0, 'k'}, {"mouse", 1, 0, 'p'}, - {"videoDevice", 1, 0, 'v'}, {0, 0, 0, 0}}; - - while ((option = getopt_long(argc, argv, opts, lopts, NULL)) != -1) - { - switch (option) - { - case 'f': - frameRate = (int)strtol(optarg, NULL, 0); - if (frameRate < 0 || frameRate > 60) - frameRate = 30; - break; - case 'h': - printUsage(); - exit(0); - case 'k': - keyboardPath = std::string(optarg); - break; - case 'p': - pointerPath = std::string(optarg); - break; - case 'v': - videoPath = std::string(optarg); - break; - } - } -} - -void Args::printUsage() -{ - // use fprintf(stderr to match rfbUsage() - fprintf(stderr, "OpenBMC IKVM daemon\n"); - fprintf(stderr, "Usage: obmc-ikvm [options]\n"); - fprintf(stderr, "-f frame rate try this frame rate\n"); - fprintf(stderr, "-h, --help show this message and exit\n"); - fprintf(stderr, "-k device HID keyboard gadget device\n"); - fprintf(stderr, "-p device HID mouse gadget device\n"); - fprintf(stderr, "-v device V4L2 device\n"); - rfbUsage(); -} - -} // namespace ikvm diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_args.hpp b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_args.hpp deleted file mode 100644 index f877d32e9..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_args.hpp +++ /dev/null @@ -1,123 +0,0 @@ -#pragma once - -#include <string> - -namespace ikvm -{ - -/* - * @class Args - * @brief Command line argument parser and storage - */ -class Args -{ - public: - /* - * @struct CommandLine - * @brief Stores the original command line arguments for later use - */ - struct CommandLine - { - /* - * @brief Constructs CommandLine object - * - * @param[in] c - Number of arguments - * @param[in] v - Array of arguments - */ - CommandLine(int c, char** v) : argc(c), argv(v) - { - } - ~CommandLine() = default; - CommandLine(const CommandLine&) = default; - CommandLine& operator=(const CommandLine&) = default; - CommandLine(CommandLine&&) = default; - CommandLine& operator=(CommandLine&&) = default; - - int argc; - char** argv; - }; - - /* - * @brief Constructs Args object - * - * @param[in] argc - The number of arguments in the command line call - * @param[in] argv - The array of arguments from the command line - */ - Args(int argc, char* argv[]); - ~Args() = default; - Args(const Args&) = default; - Args& operator=(const Args&) = default; - Args(Args&&) = default; - Args& operator=(Args&&) = default; - - /* - * @brief Get the original command line arguments - * - * @return Reference to the CommandLine structure storing the original - * command line arguments - */ - inline const CommandLine& getCommandLine() const - { - return commandLine; - } - - /* - * @brief Get the desired video frame rate - * - * @return Value of the desired frame rate in frames per second - */ - inline int getFrameRate() const - { - return frameRate; - } - - /* - * @brief Get the path to the USB keyboard device - * - * @return Reference to the string storing the path to the keyboard device - */ - inline const std::string& getKeyboardPath() const - { - return keyboardPath; - } - - /* - * @brief Get the path to the USB mouse device - * - * @return Reference to the string storing the path to the mouse device - */ - inline const std::string& getPointerPath() const - { - return pointerPath; - } - - /* - * @brief Get the path to the V4L2 video device - * - * @return Reference to the string storing the path to the video device - */ - inline const std::string& getVideoPath() const - { - return videoPath; - } - - private: - /* @brief Prints the application usage to stderr */ - void printUsage(); - - /* - * @brief Desired frame rate (in frames per second) of the video - * stream - */ - int frameRate; - /* @brief Path to the USB keyboard device */ - std::string keyboardPath; - /* @brief Path to the USB mouse device */ - std::string pointerPath; - /* @brief Path to the V4L2 video device */ - std::string videoPath; - /* @brief Original command line arguments passed to the application */ - CommandLine commandLine; -}; - -} // namespace ikvm diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_input.cpp b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_input.cpp deleted file mode 100644 index f161f7327..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_input.cpp +++ /dev/null @@ -1,380 +0,0 @@ -#include "ikvm_input.hpp" - -#include "ikvm_server.hpp" -#include "scancodes.hpp" - -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <rfb/keysym.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include <phosphor-logging/elog-errors.hpp> -#include <phosphor-logging/elog.hpp> -#include <phosphor-logging/log.hpp> -#include <xyz/openbmc_project/Common/File/error.hpp> - -namespace ikvm -{ - -using namespace phosphor::logging; -using namespace sdbusplus::xyz::openbmc_project::Common::File::Error; - -Input::Input(const std::string& kbdPath, const std::string& ptrPath) : - keyboardFd(-1), pointerFd(-1), keyboardReport{0}, pointerReport{0}, - keyboardPath(kbdPath), pointerPath(ptrPath) -{ - if (!keyboardPath.empty()) - { - keyboardFd = open(keyboardPath.c_str(), O_RDWR | O_CLOEXEC); - if (keyboardFd < 0) - { - log<level::ERR>("Failed to open input device", - entry("PATH=%s", keyboardPath.c_str()), - entry("ERROR=%s", strerror(errno))); - elog<Open>(xyz::openbmc_project::Common::File::Open::ERRNO(errno), - xyz::openbmc_project::Common::File::Open::PATH( - keyboardPath.c_str())); - } - } - - if (!pointerPath.empty()) - { - pointerFd = open(pointerPath.c_str(), O_RDWR | O_CLOEXEC); - if (pointerFd < 0) - { - log<level::ERR>("Failed to open input device", - entry("PATH=%s", pointerPath.c_str()), - entry("ERROR=%s", strerror(errno))); - elog<Open>(xyz::openbmc_project::Common::File::Open::ERRNO(errno), - xyz::openbmc_project::Common::File::Open::PATH( - pointerPath.c_str())); - } - } -} - -Input::~Input() -{ - if (keyboardFd >= 0) - { - close(keyboardFd); - } - - if (pointerFd >= 0) - { - close(pointerFd); - } -} - -void Input::keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl) -{ - Server::ClientData* cd = (Server::ClientData*)cl->clientData; - Input* input = cd->input; - - if (down) - { - uint8_t sc = keyToScancode(key); - - if (sc) - { - if (input->keysDown.find(key) == input->keysDown.end()) - { - for (unsigned int i = 2; i < KEY_REPORT_LENGTH; ++i) - { - if (!input->keyboardReport[i]) - { - input->keyboardReport[i] = sc; - input->keysDown.insert(std::make_pair(key, i)); - input->sendKeyboard = true; - break; - } - } - } - } - else - { - uint8_t mod = keyToMod(key); - - if (mod) - { - input->keyboardReport[0] |= mod; - input->sendKeyboard = true; - } - } - } - else - { - auto it = input->keysDown.find(key); - - if (it != input->keysDown.end()) - { - input->keyboardReport[it->second] = 0; - input->keysDown.erase(it); - input->sendKeyboard = true; - } - else - { - uint8_t mod = keyToMod(key); - - if (mod) - { - input->keyboardReport[0] &= ~mod; - input->sendKeyboard = true; - } - } - } -} - -void Input::pointerEvent(int buttonMask, int x, int y, rfbClientPtr cl) -{ - Server::ClientData* cd = (Server::ClientData*)cl->clientData; - Input* input = cd->input; - Server* server = (Server*)cl->screen->screenData; - const Video& video = server->getVideo(); - - input->pointerReport[0] = buttonMask & 0xFF; - - if (x >= 0 && (unsigned int)x < video.getWidth()) - { - uint16_t xx = x * ((SHRT_MAX + 1) / video.getWidth()); - - memcpy(&input->pointerReport[1], &xx, 2); - } - - if (y >= 0 && (unsigned int)y < video.getHeight()) - { - uint16_t yy = y * ((SHRT_MAX + 1) / video.getHeight()); - - memcpy(&input->pointerReport[3], &yy, 2); - } - - input->sendPointer = true; - rfbDefaultPtrAddEvent(buttonMask, x, y, cl); -} - -void Input::sendWakeupPacket() -{ - uint8_t wakeupReport[PTR_REPORT_LENGTH] = {0}; - uint16_t xy = SHRT_MAX / 2; - - if (pointerFd < 0) - { - return; - } - - memcpy(&wakeupReport[1], &xy, 2); - memcpy(&wakeupReport[3], &xy, 2); - - if (write(pointerFd, wakeupReport, PTR_REPORT_LENGTH) != PTR_REPORT_LENGTH) - { - log<level::ERR>("Failed to write report", - entry("ERROR=%s", strerror(errno))); - } -} - -void Input::sendReport() -{ - if (sendKeyboard && keyboardFd >= 0) - { - if (write(keyboardFd, keyboardReport, KEY_REPORT_LENGTH) != - KEY_REPORT_LENGTH) - { - log<level::ERR>("Failed to write keyboard report", - entry("ERROR=%s", strerror(errno))); - } - - sendKeyboard = false; - } - - if (sendPointer && pointerFd >= 0) - { - if (write(pointerFd, pointerReport, PTR_REPORT_LENGTH) != - PTR_REPORT_LENGTH) - { - log<level::ERR>("Failed to write pointer report", - entry("ERROR=%s", strerror(errno))); - } - - sendPointer = false; - } -} - -uint8_t Input::keyToMod(rfbKeySym key) -{ - uint8_t mod = 0; - - if (key >= XK_Shift_L && key <= XK_Control_R) - { - mod = shiftCtrlMap[key - XK_Shift_L]; - } - else if (key >= XK_Meta_L && key <= XK_Alt_R) - { - mod = metaAltMap[key - XK_Meta_L]; - } - - return mod; -} - -uint8_t Input::keyToScancode(rfbKeySym key) -{ - uint8_t scancode = 0; - - if ((key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z')) - { - scancode = USBHID_KEY_A + ((key & 0x5F) - 'A'); - } - else if (key >= '1' && key <= '9') - { - scancode = USBHID_KEY_1 + (key - '1'); - } - else if (key >= XK_F1 && key <= XK_F12) - { - scancode = USBHID_KEY_F1 + (key - XK_F1); - } - else - { - switch (key) - { - case XK_exclam: - scancode = USBHID_KEY_1; - break; - case XK_at: - scancode = USBHID_KEY_2; - break; - case XK_numbersign: - scancode = USBHID_KEY_3; - break; - case XK_dollar: - scancode = USBHID_KEY_4; - break; - case XK_percent: - scancode = USBHID_KEY_5; - break; - case XK_asciicircum: - scancode = USBHID_KEY_6; - break; - case XK_ampersand: - scancode = USBHID_KEY_7; - break; - case XK_asterisk: - scancode = USBHID_KEY_8; - break; - case XK_parenleft: - scancode = USBHID_KEY_9; - break; - case XK_0: - case XK_parenright: - scancode = USBHID_KEY_0; - break; - case XK_Return: - scancode = USBHID_KEY_RETURN; - break; - case XK_Escape: - scancode = USBHID_KEY_ESC; - break; - case XK_BackSpace: - scancode = USBHID_KEY_BACKSPACE; - break; - case XK_Tab: - scancode = USBHID_KEY_TAB; - break; - case XK_space: - scancode = USBHID_KEY_SPACE; - break; - case XK_minus: - case XK_underscore: - scancode = USBHID_KEY_MINUS; - break; - case XK_plus: - case XK_equal: - scancode = USBHID_KEY_EQUAL; - break; - case XK_bracketleft: - case XK_braceleft: - scancode = USBHID_KEY_LEFTBRACE; - break; - case XK_bracketright: - case XK_braceright: - scancode = USBHID_KEY_RIGHTBRACE; - break; - case XK_backslash: - case XK_bar: - scancode = USBHID_KEY_BACKSLASH; - break; - case XK_colon: - case XK_semicolon: - scancode = USBHID_KEY_SEMICOLON; - break; - case XK_quotedbl: - case XK_apostrophe: - scancode = USBHID_KEY_APOSTROPHE; - break; - case XK_grave: - case XK_asciitilde: - scancode = USBHID_KEY_GRAVE; - break; - case XK_comma: - case XK_less: - scancode = USBHID_KEY_COMMA; - break; - case XK_period: - case XK_greater: - scancode = USBHID_KEY_DOT; - break; - case XK_slash: - case XK_question: - scancode = USBHID_KEY_SLASH; - break; - case XK_Caps_Lock: - scancode = USBHID_KEY_CAPSLOCK; - break; - case XK_Print: - scancode = USBHID_KEY_PRINT; - break; - case XK_Scroll_Lock: - scancode = USBHID_KEY_SCROLLLOCK; - break; - case XK_Pause: - scancode = USBHID_KEY_PAUSE; - break; - case XK_Insert: - scancode = USBHID_KEY_INSERT; - break; - case XK_Home: - scancode = USBHID_KEY_HOME; - break; - case XK_Page_Up: - scancode = USBHID_KEY_PAGEUP; - break; - case XK_Delete: - scancode = USBHID_KEY_DELETE; - break; - case XK_End: - scancode = USBHID_KEY_END; - break; - case XK_Page_Down: - scancode = USBHID_KEY_PAGEDOWN; - break; - case XK_Right: - scancode = USBHID_KEY_RIGHT; - break; - case XK_Left: - scancode = USBHID_KEY_LEFT; - break; - case XK_Down: - scancode = USBHID_KEY_DOWN; - break; - case XK_Up: - scancode = USBHID_KEY_UP; - break; - case XK_Num_Lock: - scancode = USBHID_KEY_NUMLOCK; - break; - } - } - - return scancode; -} - -} // namespace ikvm diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_input.hpp b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_input.hpp deleted file mode 100644 index f7413a4cd..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_input.hpp +++ /dev/null @@ -1,111 +0,0 @@ -#pragma once - -#include <rfb/rfb.h> - -#include <map> -#include <string> - -namespace ikvm -{ - -/* - * @class Input - * @brief Receives events from RFB clients and sends reports to the USB input - * device - */ -class Input -{ - public: - /* - * @brief Constructs Input object - * - * @param[in] kbdPath - Path to the USB keyboard device - * @param[in] ptrPath - Path to the USB mouse device - */ - Input(const std::string& kbdPath, const std::string& ptrPath); - ~Input(); - Input(const Input&) = default; - Input& operator=(const Input&) = default; - Input(Input&&) = default; - Input& operator=(Input&&) = default; - - /* - * @brief RFB client key event handler - * - * @param[in] down - Boolean indicating whether key is pressed or not - * @param[in] key - Key code - * @param[in] cl - Handle to the RFB client - */ - static void keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl); - /* - * @brief RFB client pointer event handler - * - * @param[in] buttonMask - Bitmask indicating which buttons have been - * pressed - * @param[in] x - Pointer x-coordinate - * @param[in] y - Pointer y-coordinate - * @param[in] cl - Handle to the RFB client - */ - static void pointerEvent(int buttonMask, int x, int y, rfbClientPtr cl); - - /* @brief Sends a wakeup data packet to the USB input device */ - void sendWakeupPacket(); - /* @brief Sends an HID report to the USB input device */ - void sendReport(); - - private: - static constexpr int NUM_MODIFIER_BITS = 4; - static constexpr int KEY_REPORT_LENGTH = 8; - static constexpr int PTR_REPORT_LENGTH = 5; - - /* @brief HID modifier bits mapped to shift and control key codes */ - static constexpr uint8_t shiftCtrlMap[NUM_MODIFIER_BITS] = { - 0x02, // left shift - 0x20, // right shift - 0x01, // left control - 0x10 // right control - }; - /* @brief HID modifier bits mapped to meta and alt key codes */ - static constexpr uint8_t metaAltMap[NUM_MODIFIER_BITS] = { - 0x08, // left meta - 0x80, // right meta - 0x04, // left alt - 0x40 // right alt - }; - /* - * @brief Translates a RFB-specific key code to HID modifier bit - * - * @param[in] key - key code - */ - static uint8_t keyToMod(rfbKeySym key); - /* - * @brief Translates a RFB-specific key code to HID scancode - * - * @param[in] key - key code - */ - static uint8_t keyToScancode(rfbKeySym key); - - /* @brief Indicates whether or not to send a keyboard report */ - bool sendKeyboard; - /* @brief Indicates whether or not to send a pointer report */ - bool sendPointer; - /* @brief File descriptor for the USB keyboard device */ - int keyboardFd; - /* @brief File descriptor for the USB mouse device */ - int pointerFd; - /* @brief Data for keyboard report */ - uint8_t keyboardReport[KEY_REPORT_LENGTH]; - /* @brief Data for pointer report */ - uint8_t pointerReport[PTR_REPORT_LENGTH]; - /* @brief Path to the USB keyboard device */ - std::string keyboardPath; - /* @brief Path to the USB mouse device */ - std::string pointerPath; - /* - * @brief Mapping of RFB key code to report data index to keep track - * of which keys are down - */ - std::map<int, int> keysDown; -}; - -} // namespace ikvm diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_manager.cpp b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_manager.cpp deleted file mode 100644 index 5e014d057..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_manager.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "ikvm_manager.hpp" - -#include <thread> - -namespace ikvm -{ - -Manager::Manager(const Args& args) : - continueExecuting(true), serverDone(false), videoDone(true), - input(args.getKeyboardPath(), args.getPointerPath()), - video(args.getVideoPath(), input, args.getFrameRate()), - server(args, input, video) -{ -} - -void Manager::run() -{ - std::thread run(serverThread, this); - - while (continueExecuting) - { - if (server.wantsFrame()) - { - video.getFrame(); - server.sendFrame(); - } - else - { - video.stop(); - } - - if (video.needsResize()) - { - videoDone = false; - waitServer(); - video.resize(); - server.resize(); - setVideoDone(); - } - else - { - setVideoDone(); - waitServer(); - } - } - - run.join(); -} - -void Manager::serverThread(Manager* manager) -{ - while (manager->continueExecuting) - { - manager->server.run(); - manager->setServerDone(); - manager->waitVideo(); - } -} - -void Manager::setServerDone() -{ - std::unique_lock<std::mutex> ulock(lock); - - serverDone = true; - sync.notify_all(); -} - -void Manager::setVideoDone() -{ - std::unique_lock<std::mutex> ulock(lock); - - videoDone = true; - sync.notify_all(); -} - -void Manager::waitServer() -{ - std::unique_lock<std::mutex> ulock(lock); - - while (!serverDone) - { - sync.wait(ulock); - } - - serverDone = false; -} - -void Manager::waitVideo() -{ - std::unique_lock<std::mutex> ulock(lock); - - while (!videoDone) - { - sync.wait(ulock); - } - - // don't reset videoDone -} - -} // namespace ikvm diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_manager.hpp b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_manager.hpp deleted file mode 100644 index 67d5a681e..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_manager.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once - -#include "ikvm_args.hpp" -#include "ikvm_input.hpp" -#include "ikvm_server.hpp" -#include "ikvm_video.hpp" - -#include <condition_variable> -#include <mutex> - -namespace ikvm -{ - -/* - * @class Manager - * @brief Manages the VNC server by executing threaded loops of RFB operations - * and video device operations. - */ -class Manager -{ - public: - /* - * @brief Constructs the Manager object - * - * @param[in] args - Reference to Args object - */ - Manager(const Args& args); - ~Manager() = default; - Manager(const Manager&) = default; - Manager& operator=(const Manager&) = default; - Manager(Manager&&) = default; - Manager& operator=(Manager&&) = default; - - /* @brief Begins operation of the VNC server */ - void run(); - - private: - /* - * @brief Thread function to loop the RFB update operations - * - * @param[in] manager - Pointer to the Manager object - */ - static void serverThread(Manager* manager); - - /* @brief Notifies thread waiters that RFB operations are complete */ - void setServerDone(); - /* @brief Notifies thread waiters that video operations are complete */ - void setVideoDone(); - /* @brief Blocks until RFB operations complete */ - void waitServer(); - /* @brief Blocks until video operations are complete */ - void waitVideo(); - - /* - * @brief Boolean to indicate whether the application should continue - * running - */ - bool continueExecuting; - /* @brief Boolean to indicate that RFB operations are complete */ - bool serverDone; - /* @brief Boolean to indicate that video operations are complete */ - bool videoDone; - /* @brief Input object */ - Input input; - /* @brief Video object */ - Video video; - /* @brief RFB server object */ - Server server; - /* @brief Condition variable to enable waiting for thread completion */ - std::condition_variable sync; - /* @brief Mutex for waiting on condition variable safely */ - std::mutex lock; -}; - -} // namespace ikvm diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_server.cpp b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_server.cpp deleted file mode 100644 index 47737587e..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_server.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include "ikvm_server.hpp" - -#include <rfb/rfbproto.h> - -#include <phosphor-logging/elog-errors.hpp> -#include <phosphor-logging/elog.hpp> -#include <phosphor-logging/log.hpp> -#include <xyz/openbmc_project/Common/error.hpp> - -namespace ikvm -{ - -using namespace phosphor::logging; -using namespace sdbusplus::xyz::openbmc_project::Common::Error; - -Server::Server(const Args& args, Input& i, Video& v) : - pendingResize(false), frameCounter(0), numClients(0), input(i), video(v) -{ - std::string ip("localhost"); - const Args::CommandLine& commandLine = args.getCommandLine(); - int argc = commandLine.argc; - - server = rfbGetScreen(&argc, commandLine.argv, video.getWidth(), - video.getHeight(), Video::bitsPerSample, - Video::samplesPerPixel, Video::bytesPerPixel); - - if (!server) - { - log<level::ERR>("Failed to get VNC screen due to invalid arguments"); - elog<InvalidArgument>( - xyz::openbmc_project::Common::InvalidArgument::ARGUMENT_NAME(""), - xyz::openbmc_project::Common::InvalidArgument::ARGUMENT_VALUE("")); - } - - framebuffer.resize( - video.getHeight() * video.getWidth() * Video::bytesPerPixel, 0); - - server->screenData = this; - server->desktopName = "OpenBMC IKVM"; - server->alwaysShared = true; - server->frameBuffer = framebuffer.data(); - server->newClientHook = newClient; - server->cursor = rfbMakeXCursor(cursorWidth, cursorHeight, (char*)cursor, - (char*)cursorMask); - server->cursor->xhot = 1; - server->cursor->yhot = 1; - // char httpDir[] = "../webclients"; - // server->httpDir = httpDir; - // server->httpEnableProxyConnect = true; - - // commented it out to allow OOB connection - // rfbStringToAddr(&ip[0], &server->listenInterface); - - rfbInitServer(server); - - rfbMarkRectAsModified(server, 0, 0, video.getWidth(), video.getHeight()); - - server->kbdAddEvent = Input::keyEvent; - server->ptrAddEvent = Input::pointerEvent; - - processTime = (1000000 / video.getFrameRate()) - 100; -} - -Server::~Server() -{ - rfbScreenCleanup(server); -} - -void Server::resize() -{ - if (frameCounter > video.getFrameRate()) - { - doResize(); - } - else - { - pendingResize = true; - } -} - -void Server::run() -{ - rfbProcessEvents(server, processTime); - - if (server->clientHead) - { - input.sendReport(); - - frameCounter++; - if (pendingResize && frameCounter > video.getFrameRate()) - { - doResize(); - pendingResize = false; - } - } -} - -void Server::sendFrame() -{ - char* data = video.getData(); - rfbClientIteratorPtr it; - rfbClientPtr cl; - - if (!data || pendingResize) - { - return; - } - - it = rfbGetClientIterator(server); - - while ((cl = rfbClientIteratorNext(it))) - { - ClientData* cd = (ClientData*)cl->clientData; - rfbFramebufferUpdateMsg* fu = (rfbFramebufferUpdateMsg*)cl->updateBuf; - - if (!cd) - { - continue; - } - - if (cd->skipFrame) - { - cd->skipFrame--; - continue; - } - - if (cl->enableLastRectEncoding) - { - fu->nRects = 0xFFFF; - } - else - { - fu->nRects = Swap16IfLE(1); - } - - fu->type = rfbFramebufferUpdate; - cl->ublen = sz_rfbFramebufferUpdateMsg; - rfbSendUpdateBuf(cl); - - cl->tightEncoding = rfbEncodingTight; - rfbSendTightHeader(cl, 0, 0, video.getWidth(), video.getHeight()); - - cl->updateBuf[cl->ublen++] = (char)(rfbTightJpeg << 4); - rfbSendCompressedDataTight(cl, data, video.getFrameSize()); - - if (cl->enableLastRectEncoding) - { - rfbSendLastRectMarker(cl); - } - - rfbSendUpdateBuf(cl); - } - - rfbReleaseClientIterator(it); -} - -void Server::clientGone(rfbClientPtr cl) -{ - Server* server = (Server*)cl->screen->screenData; - - delete (ClientData*)cl->clientData; - - if (server->numClients-- == 1) - { - rfbMarkRectAsModified(server->server, 0, 0, server->video.getWidth(), - server->video.getHeight()); - } -} - -enum rfbNewClientAction Server::newClient(rfbClientPtr cl) -{ - Server* server = (Server*)cl->screen->screenData; - - cl->clientData = - new ClientData(server->video.getFrameRate(), &server->input); - cl->clientGoneHook = clientGone; - if (!server->numClients++) - { - server->pendingResize = false; - server->frameCounter = 0; - server->video.start(); - } - - return RFB_CLIENT_ACCEPT; -} - -void Server::doResize() -{ - rfbClientIteratorPtr it; - rfbClientPtr cl; - - framebuffer.resize( - video.getHeight() * video.getWidth() * Video::bytesPerPixel, 0); - - rfbNewFramebuffer(server, framebuffer.data(), video.getWidth(), - video.getHeight(), Video::bitsPerSample, - Video::samplesPerPixel, Video::bytesPerPixel); - rfbMarkRectAsModified(server, 0, 0, video.getWidth(), video.getHeight()); - - it = rfbGetClientIterator(server); - - while ((cl = rfbClientIteratorNext(it))) - { - ClientData* cd = (ClientData*)cl->clientData; - - if (!cd) - { - continue; - } - - // delay video updates to give the client time to resize - cd->skipFrame = video.getFrameRate(); - } - - rfbReleaseClientIterator(it); -} - -} // namespace ikvm diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_server.hpp b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_server.hpp deleted file mode 100644 index b8062017b..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_server.hpp +++ /dev/null @@ -1,167 +0,0 @@ -#pragma once - -#include "ikvm_args.hpp" -#include "ikvm_input.hpp" -#include "ikvm_video.hpp" - -#include <rfb/rfb.h> - -#include <vector> - -namespace ikvm -{ - -/* - * @class Server - * @brief Manages the RFB server connection and updates - */ -class Server -{ - public: - /* - * @struct ClientData - * @brief Store necessary data for each connected RFB client - */ - struct ClientData - { - /* - * @brief Constructs ClientData object - * - * @param[in] s - Number of frames to skip when client connects - * @param[in] i - Pointer to Input object - */ - ClientData(int s, Input* i) : skipFrame(s), input(i) - { - } - ~ClientData() = default; - ClientData(const ClientData&) = default; - ClientData& operator=(const ClientData&) = default; - ClientData(ClientData&&) = default; - ClientData& operator=(ClientData&&) = default; - - int skipFrame; - Input* input; - }; - - /* - * @brief Constructs Server object - * - * @param[in] args - Reference to Args object - * @param[in] i - Reference to Input object - * @param[in] v - Reference to Video object - */ - Server(const Args& args, Input& i, Video& v); - ~Server(); - Server(const Server&) = default; - Server& operator=(const Server&) = default; - Server(Server&&) = default; - Server& operator=(Server&&) = default; - - /* @brief Resizes the RFB framebuffer */ - void resize(); - /* @brief Executes any pending RFB updates and client input */ - void run(); - /* @brief Sends pending video frame to clients */ - void sendFrame(); - - /* - * @brief Indicates whether or not video data is desired - * - * @return Boolean to indicate whether any clients need a video frame - */ - inline bool wantsFrame() const - { - return server->clientHead; - } - /* - * @brief Get the Video object - * - * @return Reference to the Video object - */ - inline const Video& getVideo() const - { - return video; - } - - private: - /* - * @brief Handler for a client disconnecting - * - * @param[in] cl - Handle to the client object - */ - static void clientGone(rfbClientPtr cl); - /* - * @brief Handler for client connecting - * - * @param[in] cl - Handle to the client object - */ - static enum rfbNewClientAction newClient(rfbClientPtr cl); - - /* @brief Performs the resize operation on the framebuffer */ - void doResize(); - - /* @brief Boolean to indicate if a resize operation is on-going */ - bool pendingResize; - /* @brief Number of frames handled since a client connected */ - int frameCounter; - /* @brief Number of connected clients */ - unsigned int numClients; - /* @brief Microseconds to process RFB events every frame */ - long int processTime; - /* @brief Handle to the RFB server object */ - rfbScreenInfoPtr server; - /* @brief Reference to the Input object */ - Input& input; - /* @brief Reference to the Video object */ - Video& video; - /* @brief Default framebuffer storage */ - std::vector<char> framebuffer; - /* @brief Cursor bitmap width */ - static constexpr int cursorWidth = 20; - /* @brief Cursor bitmap height */ - static constexpr int cursorHeight = 20; - /* @brief Cursor bitmap */ - static constexpr char cursor[] = " " - " x " - " xx " - " xxx " - " xxxx " - " xxxxx " - " xxxxxx " - " xxxxxxx " - " xxxxxxxx " - " xxxxxxxxx " - " xxxxxxxxxx " - " xxxxxxxxxxx " - " xxxxxxx " - " xxxxxxx " - " xxx xxx " - " xx xxx " - " x xxx " - " xxx " - " x " - " "; - /* @brief Cursor bitmap mask */ - static constexpr char cursorMask[] = " o " - "oxo " - "oxxo " - "oxxxo " - "oxxxxo " - "oxxxxxo " - "oxxxxxxo " - "oxxxxxxxo " - "oxxxxxxxxo " - "oxxxxxxxxxo " - "oxxxxxxxxxxo " - "oxxxxxxxxxxxo " - "oxxxxxxxoooo " - "oxxxxxxxo " - "oxxxooxxxo " - "oxxo oxxxo " - "oxo oxxxo " - " o oxxxo " - " oxo " - " o "; -}; - -} // namespace ikvm diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_video.cpp b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_video.cpp deleted file mode 100644 index 13de54da1..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_video.cpp +++ /dev/null @@ -1,478 +0,0 @@ -#include "ikvm_video.hpp" - -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <linux/videodev2.h> -#include <poll.h> -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include <phosphor-logging/elog-errors.hpp> -#include <phosphor-logging/elog.hpp> -#include <phosphor-logging/log.hpp> -#include <xyz/openbmc_project/Common/Device/error.hpp> -#include <xyz/openbmc_project/Common/File/error.hpp> - -namespace ikvm -{ - -const int Video::bitsPerSample(8); -const int Video::bytesPerPixel(4); -const int Video::samplesPerPixel(3); - -using namespace phosphor::logging; -using namespace sdbusplus::xyz::openbmc_project::Common::File::Error; -using namespace sdbusplus::xyz::openbmc_project::Common::Device::Error; - -Video::Video(const std::string& p, Input& input, int fr) : - resizeAfterOpen(false), fd(-1), frameRate(fr), lastFrameIndex(-1), - height(600), width(800), input(input), path(p) -{ -} - -Video::~Video() -{ - stop(); -} - -char* Video::getData() -{ - if (lastFrameIndex >= 0) - { - return (char*)buffers[lastFrameIndex].data; - } - - return nullptr; -} - -void Video::getFrame() -{ - bool queue(false); - int rc(0); - v4l2_buffer buf; - - if (fd < 0) - { - return; - } - - memset(&buf, 0, sizeof(v4l2_buffer)); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - - while (rc >= 0) - { - rc = ioctl(fd, VIDIOC_DQBUF, &buf); - if (rc >= 0) - { - buffers[buf.index].queued = false; - - if (!(buf.flags & V4L2_BUF_FLAG_ERROR)) - { - lastFrameIndex = buf.index; - buffers[lastFrameIndex].payload = buf.bytesused; - queue = true; - break; - } - else - { - buffers[buf.index].payload = 0; - } - } - else - { - restart(); - return; - } - } - - if (queue) - { - for (unsigned int i = 0; i < buffers.size(); ++i) - { - if (i == (unsigned int)lastFrameIndex) - { - continue; - } - - if (!buffers[i].queued) - { - memset(&buf, 0, sizeof(v4l2_buffer)); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = i; - - rc = ioctl(fd, VIDIOC_QBUF, &buf); - if (rc) - { - log<level::ERR>("Failed to queue buffer", - entry("ERROR=%s", strerror(errno))); - elog<ReadFailure>( - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_ERRNO(errno), - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_DEVICE_PATH(path.c_str())); - } - - buffers[i].queued = true; - } - } - } -} - -bool Video::needsResize() -{ - int rc; - v4l2_dv_timings timings; - - if (fd < 0) - { - return false; - } - - if (resizeAfterOpen) - { - return true; - } - - memset(&timings, 0, sizeof(v4l2_dv_timings)); - rc = ioctl(fd, VIDIOC_QUERY_DV_TIMINGS, &timings); - if (rc < 0) - { - log<level::ERR>("Failed to query timings", - entry("ERROR=%s", strerror(errno))); - return false; - } - - if (timings.bt.width != width || timings.bt.height != height) - { - width = timings.bt.width; - height = timings.bt.height; - - if (!width || !height) - { - log<level::ERR>("Failed to get new resolution", - entry("WIDTH=%d", width), - entry("HEIGHT=%d", height)); - elog<Open>( - xyz::openbmc_project::Common::File::Open::ERRNO(-EPROTO), - xyz::openbmc_project::Common::File::Open::PATH(path.c_str())); - } - - lastFrameIndex = -1; - return true; - } - - return false; -} - -void Video::resize() -{ - int rc; - unsigned int i; - bool needsResizeCall(false); - v4l2_buf_type type(V4L2_BUF_TYPE_VIDEO_CAPTURE); - v4l2_requestbuffers req; - - if (fd < 0) - { - return; - } - - if (resizeAfterOpen) - { - resizeAfterOpen = false; - return; - } - - for (i = 0; i < buffers.size(); ++i) - { - if (buffers[i].data) - { - needsResizeCall = true; - break; - } - } - - if (needsResizeCall) - { - rc = ioctl(fd, VIDIOC_STREAMOFF, &type); - if (rc) - { - log<level::ERR>("Failed to stop streaming", - entry("ERROR=%s", strerror(errno))); - elog<ReadFailure>( - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_ERRNO(errno), - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_DEVICE_PATH(path.c_str())); - } - } - - for (i = 0; i < buffers.size(); ++i) - { - if (buffers[i].data) - { - munmap(buffers[i].data, buffers[i].size); - buffers[i].data = nullptr; - buffers[i].queued = false; - } - } - - if (needsResizeCall) - { - v4l2_dv_timings timings; - - memset(&req, 0, sizeof(v4l2_requestbuffers)); - req.count = 0; - req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - req.memory = V4L2_MEMORY_MMAP; - rc = ioctl(fd, VIDIOC_REQBUFS, &req); - if (rc < 0) - { - log<level::ERR>("Failed to zero streaming buffers", - entry("ERROR=%s", strerror(errno))); - elog<ReadFailure>( - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_ERRNO(errno), - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_DEVICE_PATH(path.c_str())); - } - - memset(&timings, 0, sizeof(v4l2_dv_timings)); - rc = ioctl(fd, VIDIOC_QUERY_DV_TIMINGS, &timings); - if (rc < 0) - { - log<level::ERR>("Failed to query timings", - entry("ERROR=%s", strerror(errno))); - elog<ReadFailure>( - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_ERRNO(errno), - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_DEVICE_PATH(path.c_str())); - } - - rc = ioctl(fd, VIDIOC_S_DV_TIMINGS, &timings); - if (rc < 0) - { - log<level::ERR>("Failed to set timings", - entry("ERROR=%s", strerror(errno))); - elog<ReadFailure>( - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_ERRNO(errno), - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_DEVICE_PATH(path.c_str())); - } - - buffers.clear(); - } - - memset(&req, 0, sizeof(v4l2_requestbuffers)); - req.count = 3; - req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - req.memory = V4L2_MEMORY_MMAP; - rc = ioctl(fd, VIDIOC_REQBUFS, &req); - if (rc < 0 || req.count < 2) - { - log<level::ERR>("Failed to request streaming buffers", - entry("ERROR=%s", strerror(errno))); - elog<ReadFailure>( - xyz::openbmc_project::Common::Device::ReadFailure::CALLOUT_ERRNO( - errno), - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_DEVICE_PATH(path.c_str())); - } - - buffers.resize(req.count); - - for (i = 0; i < buffers.size(); ++i) - { - v4l2_buffer buf; - - memset(&buf, 0, sizeof(v4l2_buffer)); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = i; - - rc = ioctl(fd, VIDIOC_QUERYBUF, &buf); - if (rc < 0) - { - log<level::ERR>("Failed to query buffer", - entry("ERROR=%s", strerror(errno))); - elog<ReadFailure>( - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_ERRNO(errno), - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_DEVICE_PATH(path.c_str())); - } - - buffers[i].data = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, buf.m.offset); - if (buffers[i].data == MAP_FAILED) - { - log<level::ERR>("Failed to mmap buffer", - entry("ERROR=%s", strerror(errno))); - elog<ReadFailure>( - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_ERRNO(errno), - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_DEVICE_PATH(path.c_str())); - } - - buffers[i].size = buf.length; - - rc = ioctl(fd, VIDIOC_QBUF, &buf); - if (rc < 0) - { - log<level::ERR>("Failed to queue buffer", - entry("ERROR=%s", strerror(errno))); - elog<ReadFailure>( - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_ERRNO(errno), - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_DEVICE_PATH(path.c_str())); - } - - buffers[i].queued = true; - } - - rc = ioctl(fd, VIDIOC_STREAMON, &type); - if (rc) - { - log<level::ERR>("Failed to start streaming", - entry("ERROR=%s", strerror(errno))); - elog<ReadFailure>( - xyz::openbmc_project::Common::Device::ReadFailure::CALLOUT_ERRNO( - errno), - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_DEVICE_PATH(path.c_str())); - } -} - -void Video::start() -{ - int rc; - size_t oldHeight = height; - size_t oldWidth = width; - v4l2_capability cap; - v4l2_format fmt; - v4l2_streamparm sparm; - - if (fd >= 0) - { - return; - } - - fd = open(path.c_str(), O_RDWR); - if (fd < 0) - { - input.sendWakeupPacket(); - - fd = open(path.c_str(), O_RDWR); - if (fd < 0) - { - log<level::ERR>("Failed to open video device", - entry("PATH=%s", path.c_str()), - entry("ERROR=%s", strerror(errno))); - elog<Open>( - xyz::openbmc_project::Common::File::Open::ERRNO(errno), - xyz::openbmc_project::Common::File::Open::PATH(path.c_str())); - } - } - - memset(&cap, 0, sizeof(v4l2_capability)); - rc = ioctl(fd, VIDIOC_QUERYCAP, &cap); - if (rc < 0) - { - log<level::ERR>("Failed to query video device capabilities", - entry("ERROR=%s", strerror(errno))); - elog<ReadFailure>( - xyz::openbmc_project::Common::Device::ReadFailure::CALLOUT_ERRNO( - errno), - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_DEVICE_PATH(path.c_str())); - } - - if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) || - !(cap.capabilities & V4L2_CAP_STREAMING)) - { - log<level::ERR>("Video device doesn't support this application"); - elog<Open>( - xyz::openbmc_project::Common::File::Open::ERRNO(errno), - xyz::openbmc_project::Common::File::Open::PATH(path.c_str())); - } - - memset(&fmt, 0, sizeof(v4l2_format)); - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - rc = ioctl(fd, VIDIOC_G_FMT, &fmt); - if (rc < 0) - { - log<level::ERR>("Failed to query video device format", - entry("ERROR=%s", strerror(errno))); - elog<ReadFailure>( - xyz::openbmc_project::Common::Device::ReadFailure::CALLOUT_ERRNO( - errno), - xyz::openbmc_project::Common::Device::ReadFailure:: - CALLOUT_DEVICE_PATH(path.c_str())); - } - - memset(&sparm, 0, sizeof(v4l2_streamparm)); - sparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - sparm.parm.capture.timeperframe.numerator = 1; - sparm.parm.capture.timeperframe.denominator = frameRate; - rc = ioctl(fd, VIDIOC_S_PARM, &sparm); - if (rc < 0) - { - log<level::WARNING>("Failed to set video device frame rate", - entry("ERROR=%s", strerror(errno))); - } - - height = fmt.fmt.pix.height; - width = fmt.fmt.pix.width; - - resize(); - - if (oldHeight != height || oldWidth != width) - { - resizeAfterOpen = true; - } -} - -void Video::stop() -{ - int rc; - unsigned int i; - v4l2_buf_type type(V4L2_BUF_TYPE_VIDEO_CAPTURE); - - if (fd < 0) - { - return; - } - - lastFrameIndex = -1; - - rc = ioctl(fd, VIDIOC_STREAMOFF, &type); - if (rc) - { - log<level::ERR>("Failed to stop streaming", - entry("ERROR=%s", strerror(errno))); - } - - for (i = 0; i < buffers.size(); ++i) - { - if (buffers[i].data) - { - munmap(buffers[i].data, buffers[i].size); - buffers[i].data = nullptr; - buffers[i].queued = false; - } - } - - close(fd); - fd = -1; -} - -} // namespace ikvm diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_video.hpp b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_video.hpp deleted file mode 100644 index 8ce5319f5..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/ikvm_video.hpp +++ /dev/null @@ -1,150 +0,0 @@ -#pragma once - -#include "ikvm_input.hpp" - -#include <mutex> -#include <string> -#include <vector> - -namespace ikvm -{ - -/* - * @class Video - * @brief Sets up the V4L2 video device and performs read operations - */ -class Video -{ - public: - /* - * @brief Constructs Video object - * - * @param[in] p - Path to the V4L2 video device - * @param[in] input - Reference to the Input object - * @param[in] fr - desired frame rate of the video - */ - Video(const std::string& p, Input& input, int fr = 30); - ~Video(); - Video(const Video&) = default; - Video& operator=(const Video&) = default; - Video(Video&&) = default; - Video& operator=(Video&&) = default; - - /* - * @brief Gets the video frame data - * - * @return Pointer to the video frame data - */ - char* getData(); - /* @brief Performs read to grab latest video frame */ - void getFrame(); - /* - * @brief Gets whether or not the video frame needs to be resized - * - * @return Boolean indicating if the frame needs to be resized - */ - bool needsResize(); - /* @brief Performs the resize and re-allocates framebuffer */ - void resize(); - /* @brief Starts streaming from the video device */ - void start(); - /* @brief Stops streaming from the video device */ - void stop(); - - /* @brief Restart streaming from the video device */ - inline void restart() - { - stop(); - start(); - } - /* - * @brief Gets the desired video frame rate in frames per second - * - * @return Value of the desired frame rate - */ - inline int getFrameRate() const - { - return frameRate; - } - /* - * @brief Gets the size of the video frame data - * - * @return Value of the size of the video frame data in bytes - */ - inline size_t getFrameSize() const - { - return buffers[lastFrameIndex].payload; - } - /* - * @brief Gets the height of the video frame - * - * @return Value of the height of video frame in pixels - */ - inline size_t getHeight() const - { - return height; - } - /* - * @brief Gets the width of the video frame - * - * @return Value of the width of video frame in pixels - */ - inline size_t getWidth() const - { - return width; - } - - /* @brief Number of bits per component of a pixel */ - static const int bitsPerSample; - /* @brief Number of bytes of storage for a pixel */ - static const int bytesPerPixel; - /* @brief Number of components in a pixel (i.e. 3 for RGB pixel) */ - static const int samplesPerPixel; - - private: - /* - * @struct Buffer - * @brief Store the address and size of frame data from streaming - * operations - */ - struct Buffer - { - Buffer() : data(nullptr), queued(false), payload(0), size(0) - { - } - ~Buffer() = default; - Buffer(const Buffer&) = default; - Buffer& operator=(const Buffer&) = default; - Buffer(Buffer&&) = default; - Buffer& operator=(Buffer&&) = default; - - void* data; - bool queued; - size_t payload; - size_t size; - }; - - /* - * @brief Boolean to indicate whether the resize was triggered during - * the open operation - */ - bool resizeAfterOpen; - /* @brief File descriptor for the V4L2 video device */ - int fd; - /* @brief Desired frame rate of video stream in frames per second */ - int frameRate; - /* @brief Buffer index for the last video frame */ - int lastFrameIndex; - /* @brief Height in pixels of the video frame */ - size_t height; - /* @brief Width in pixels of the video frame */ - size_t width; - /* @brief Reference to the Input object */ - Input& input; - /* @brief Path to the V4L2 video device */ - const std::string path; - /* @brief Streaming buffer storage */ - std::vector<Buffer> buffers; -}; - -} // namespace ikvm diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/obmc-ikvm.cpp b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/obmc-ikvm.cpp deleted file mode 100644 index 271857b72..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/obmc-ikvm.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "ikvm_args.hpp" -#include "ikvm_manager.hpp" - -int main(int argc, char* argv[]) -{ - ikvm::Args args(argc, argv); - ikvm::Manager manager(args); - - manager.run(); - - return 0; -} diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/scancodes.hpp b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/scancodes.hpp deleted file mode 100644 index db79231a2..000000000 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm/scancodes.hpp +++ /dev/null @@ -1,82 +0,0 @@ -#pragma once - -#define USBHID_KEY_A 0x04 -#define USBHID_KEY_B 0x05 -#define USBHID_KEY_C 0x06 -#define USBHID_KEY_D 0x07 -#define USBHID_KEY_E 0x08 -#define USBHID_KEY_F 0x09 -#define USBHID_KEY_G 0x0a -#define USBHID_KEY_H 0x0b -#define USBHID_KEY_I 0x0c -#define USBHID_KEY_J 0x0d -#define USBHID_KEY_K 0x0e -#define USBHID_KEY_L 0x0f -#define USBHID_KEY_M 0x10 -#define USBHID_KEY_N 0x11 -#define USBHID_KEY_O 0x12 -#define USBHID_KEY_P 0x13 -#define USBHID_KEY_Q 0x14 -#define USBHID_KEY_R 0x15 -#define USBHID_KEY_S 0x16 -#define USBHID_KEY_T 0x17 -#define USBHID_KEY_U 0x18 -#define USBHID_KEY_V 0x19 -#define USBHID_KEY_W 0x1a -#define USBHID_KEY_X 0x1b -#define USBHID_KEY_Y 0x1c -#define USBHID_KEY_Z 0x1d -#define USBHID_KEY_1 0x1e -#define USBHID_KEY_2 0x1f -#define USBHID_KEY_3 0x20 -#define USBHID_KEY_4 0x21 -#define USBHID_KEY_5 0x22 -#define USBHID_KEY_6 0x23 -#define USBHID_KEY_7 0x24 -#define USBHID_KEY_8 0x25 -#define USBHID_KEY_9 0x26 -#define USBHID_KEY_0 0x27 -#define USBHID_KEY_RETURN 0x28 -#define USBHID_KEY_ESC 0x29 -#define USBHID_KEY_BACKSPACE 0x2a -#define USBHID_KEY_TAB 0x2b -#define USBHID_KEY_SPACE 0x2c -#define USBHID_KEY_MINUS 0x2d -#define USBHID_KEY_EQUAL 0x2e -#define USBHID_KEY_LEFTBRACE 0x2f -#define USBHID_KEY_RIGHTBRACE 0x30 -#define USBHID_KEY_BACKSLASH 0x31 -#define USBHID_KEY_HASH 0x32 -#define USBHID_KEY_SEMICOLON 0x33 -#define USBHID_KEY_APOSTROPHE 0x34 -#define USBHID_KEY_GRAVE 0x35 -#define USBHID_KEY_COMMA 0x36 -#define USBHID_KEY_DOT 0x37 -#define USBHID_KEY_SLASH 0x38 -#define USBHID_KEY_CAPSLOCK 0x39 -#define USBHID_KEY_F1 0x3a -#define USBHID_KEY_F2 0x3b -#define USBHID_KEY_F3 0x3c -#define USBHID_KEY_F4 0x3d -#define USBHID_KEY_F5 0x3e -#define USBHID_KEY_F6 0x3f -#define USBHID_KEY_F7 0x40 -#define USBHID_KEY_F8 0x41 -#define USBHID_KEY_F9 0x42 -#define USBHID_KEY_F10 0x43 -#define USBHID_KEY_F11 0x44 -#define USBHID_KEY_F12 0x45 -#define USBHID_KEY_PRINT 0x46 -#define USBHID_KEY_SCROLLLOCK 0x47 -#define USBHID_KEY_PAUSE 0x48 -#define USBHID_KEY_INSERT 0x49 -#define USBHID_KEY_HOME 0x4a -#define USBHID_KEY_PAGEUP 0x4b -#define USBHID_KEY_DELETE 0x4c -#define USBHID_KEY_END 0x4d -#define USBHID_KEY_PAGEDOWN 0x4e -#define USBHID_KEY_RIGHT 0x4f -#define USBHID_KEY_LEFT 0x50 -#define USBHID_KEY_DOWN 0x51 -#define USBHID_KEY_UP 0x52 -#define USBHID_KEY_NUMLOCK 0x53 diff --git a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm_git.bb b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm_git.bb index f08b29ce7..7002134db 100644 --- a/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm_git.bb +++ b/meta-openbmc-mods/meta-common/recipes-graphics/obmc-ikvm/obmc-ikvm_git.bb @@ -7,6 +7,9 @@ DEPENDS = " libvncserver sdbusplus sdbusplus-native phosphor-logging phosphor-db SRC_URI = "git://github.com/openbmc/obmc-ikvm" SRCREV = "2bc661d34abd1fda92a9d2b256ed88ca0e90d09a" +SRC_URI += "file://0001-Fix-video-restarting-sync-issue.patch \ + file://0002-Restart-video-when-mode-detection-is-failed.patch \ + " PR = "r1" PR_append = "+gitr${SRCPV}" diff --git a/meta-openbmc-mods/meta-common/recipes-intel/chassis/intel-chassis-control.bb b/meta-openbmc-mods/meta-common/recipes-intel/chassis/intel-chassis-control.bb index c34578b7f..1635b41a1 100644 --- a/meta-openbmc-mods/meta-common/recipes-intel/chassis/intel-chassis-control.bb +++ b/meta-openbmc-mods/meta-common/recipes-intel/chassis/intel-chassis-control.bb @@ -2,7 +2,7 @@ SUMMARY = "Chassis Power Control service for Intel based platform" DESCRIPTION = "Chassis Power Control service for Intel based platfrom" SRC_URI = "git://git@github.com/Intel-BMC/intel-chassis-control.git;protocol=ssh" -SRCREV = "371617ab2dbdf003e373876fa7d5a9ca83b1529d" +SRCREV = "d49efd0b5e1c81fd530dbd9fa0a7545f071bc823" S = "${WORKDIR}/git/services/chassis/" diff --git a/meta-openbmc-mods/meta-common/recipes-intel/packagegroups/packagegroup-intel-apps.bb b/meta-openbmc-mods/meta-common/recipes-intel/packagegroups/packagegroup-intel-apps.bb index 923133be7..fdaf60b41 100644 --- a/meta-openbmc-mods/meta-common/recipes-intel/packagegroups/packagegroup-intel-apps.bb +++ b/meta-openbmc-mods/meta-common/recipes-intel/packagegroups/packagegroup-intel-apps.bb @@ -27,6 +27,7 @@ RPROVIDES_${PN}-system += "virtual-obmc-system-mgmt" SUMMARY_${PN}-chassis = "Intel Chassis" RDEPENDS_${PN}-chassis = " \ intel-chassis-control \ + libgpiod \ obmc-host-failure-reboots \ " diff --git a/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv1.bb b/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv1.bb index 21299e5b6..b5a55810c 100644 --- a/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv1.bb +++ b/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv1.bb @@ -2,7 +2,7 @@ SUMMARY = "SMBIOS MDR version 1 service for Intel based platform" DESCRIPTION = "SMBIOS MDR version 1 service for Intel based platfrom" SRC_URI = "git://git@github.com/Intel-BMC/provingground.git;protocol=ssh" -SRCREV = "3cc86d6c536b4c5ee7afb5447837b83ce8b3d149" +SRCREV = "c927781ad3ca1408cd7fb0b7cc2538ea10ded76b" S = "${WORKDIR}/git/services/smbios/" diff --git a/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2.bb b/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2.bb index 074f580e9..de192388f 100644 --- a/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2.bb +++ b/meta-openbmc-mods/meta-common/recipes-intel/smbios/smbios-mdrv2.bb @@ -2,7 +2,7 @@ SUMMARY = "SMBIOS MDR version 2 service for Intel based platform" DESCRIPTION = "SMBIOS MDR version 2 service for Intel based platfrom" SRC_URI = "git://git@github.com/Intel-BMC/provingground.git;protocol=ssh" -SRCREV = "3cc86d6c536b4c5ee7afb5447837b83ce8b3d149" +SRCREV = "c927781ad3ca1408cd7fb0b7cc2538ea10ded76b" S = "${WORKDIR}/git/services/smbios-mdrv2/" diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch index 232903f2c..31faf9608 100644 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch @@ -1,25 +1,117 @@ -From 3b9ab062d0eb781fc767bd15ce58dc7b7990e65b Mon Sep 17 00:00:00 2001 +From 23f9b7808eab57957fa3bcb37974a1fdb22e7b64 Mon Sep 17 00:00:00 2001 From: Jae Hyun Yoo <jae.hyun.yoo@intel.com> Date: Mon, 7 Jan 2019 09:56:10 -0800 Subject: [PATCH] Update PECI drivers to sync with linux upstreaming version -This commit updates PECI drivers to with linux community -upstreaming version. +Upstreaming is in holding. It's for adding DTS sensor with PECI +subsystem code update. Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com> --- - drivers/hwmon/peci-cputemp.c | 2 +- - drivers/hwmon/peci-dimmtemp.c | 2 +- - drivers/hwmon/peci-hwmon.h | 2 +- - drivers/mfd/intel-peci-client.c | 43 +++++++++++++++-------------------- - drivers/peci/peci-aspeed.c | 2 +- - drivers/peci/peci-core.c | 10 ++++---- - include/linux/mfd/intel-peci-client.h | 4 +--- - include/linux/peci.h | 2 +- - 8 files changed, 29 insertions(+), 38 deletions(-) + Documentation/hwmon/peci-cputemp | 34 +- + drivers/hwmon/Kconfig | 4 +- + drivers/hwmon/peci-cputemp.c | 156 ++++-- + drivers/hwmon/peci-dimmtemp.c | 69 +-- + drivers/hwmon/peci-hwmon.h | 9 +- + drivers/mfd/Kconfig | 5 +- + drivers/mfd/intel-peci-client.c | 43 +- + drivers/peci/Kconfig | 35 +- + drivers/peci/Makefile | 6 +- + drivers/peci/busses/Kconfig | 19 + + drivers/peci/busses/Makefile | 6 + + drivers/peci/busses/peci-aspeed.c | 494 +++++++++++++++++++ + drivers/peci/peci-aspeed.c | 505 ------------------- + drivers/peci/peci-core.c | 889 ++++++++++++++++++---------------- + drivers/peci/peci-dev.c | 340 +++++++++++++ + include/linux/mfd/intel-peci-client.h | 6 +- + include/linux/peci.h | 30 +- + include/uapi/linux/peci-ioctl.h | 394 ++++++++------- + 18 files changed, 1805 insertions(+), 1239 deletions(-) + create mode 100644 drivers/peci/busses/Kconfig + create mode 100644 drivers/peci/busses/Makefile + create mode 100644 drivers/peci/busses/peci-aspeed.c + delete mode 100644 drivers/peci/peci-aspeed.c + create mode 100644 drivers/peci/peci-dev.c +diff --git a/Documentation/hwmon/peci-cputemp b/Documentation/hwmon/peci-cputemp +index 821a9258f2e6..a3a3e465c888 100644 +--- a/Documentation/hwmon/peci-cputemp ++++ b/Documentation/hwmon/peci-cputemp +@@ -51,28 +51,38 @@ temp1_crit Provides shutdown temperature of the CPU package which + temp1_crit_hyst Provides the hysteresis value from Tcontrol to Tjmax of + the CPU package. + +-temp2_label "Tcontrol" +-temp2_input Provides current Tcontrol temperature of the CPU ++temp2_label "DTS" ++temp2_input Provides current DTS temperature of the CPU package. ++temp2_max Provides thermal control temperature of the CPU package ++ which is also known as Tcontrol. ++temp2_crit Provides shutdown temperature of the CPU package which ++ is also known as the maximum processor junction ++ temperature, Tjmax or Tprochot. ++temp2_crit_hyst Provides the hysteresis value from Tcontrol to Tjmax of ++ the CPU package. ++ ++temp3_label "Tcontrol" ++temp3_input Provides current Tcontrol temperature of the CPU + package which is also known as Fan Temperature target. + Indicates the relative value from thermal monitor trip + temperature at which fans should be engaged. +-temp2_crit Provides Tcontrol critical value of the CPU package ++temp3_crit Provides Tcontrol critical value of the CPU package + which is same to Tjmax. + +-temp3_label "Tthrottle" +-temp3_input Provides current Tthrottle temperature of the CPU ++temp4_label "Tthrottle" ++temp4_input Provides current Tthrottle temperature of the CPU + package. Used for throttling temperature. If this value + is allowed and lower than Tjmax - the throttle will + occur and reported at lower than Tjmax. + +-temp4_label "Tjmax" +-temp4_input Provides the maximum junction temperature, Tjmax of the ++temp5_label "Tjmax" ++temp5_input Provides the maximum junction temperature, Tjmax of the + CPU package. + +-temp[5-*]_label Provides string "Core X", where X is resolved core ++temp[6-*]_label Provides string "Core X", where X is resolved core + number. +-temp[5-*]_input Provides current temperature of each core. +-temp[5-*]_max Provides thermal control temperature of the core. +-temp[5-*]_crit Provides shutdown temperature of the core. +-temp[5-*]_crit_hyst Provides the hysteresis value from Tcontrol to Tjmax of ++temp[6-*]_input Provides current temperature of each core. ++temp[6-*]_max Provides thermal control temperature of the core. ++temp[6-*]_crit Provides shutdown temperature of the core. ++temp[6-*]_crit_hyst Provides the hysteresis value from Tcontrol to Tjmax of + the core. +diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +index 9e118d700b48..efe67f7faed3 100644 +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -1319,7 +1319,7 @@ config SENSORS_PECI_CPUTEMP + the PECI Client Command Suite via the processor PECI client. + Check Documentation/hwmon/peci-cputemp for details. + +- This driver can also be built as a module. If so, the module ++ This driver can also be built as a module. If so, the module + will be called peci-cputemp. + + config SENSORS_PECI_DIMMTEMP +@@ -1333,7 +1333,7 @@ config SENSORS_PECI_DIMMTEMP + Suite via the processor PECI client. + Check Documentation/hwmon/peci-dimmtemp for details. + +- This driver can also be built as a module. If so, the module ++ This driver can also be built as a module. If so, the module + will be called peci-dimmtemp. + + source drivers/hwmon/pmbus/Kconfig diff --git a/drivers/hwmon/peci-cputemp.c b/drivers/hwmon/peci-cputemp.c -index 11880c86a854..63796d883c82 100644 +index 11880c86a854..30ba1638e358 100644 --- a/drivers/hwmon/peci-cputemp.c +++ b/drivers/hwmon/peci-cputemp.c @@ -1,5 +1,5 @@ @@ -29,8 +121,341 @@ index 11880c86a854..63796d883c82 100644 #include <linux/hwmon.h> #include <linux/jiffies.h> +@@ -9,7 +9,7 @@ + #include <linux/platform_device.h> + #include "peci-hwmon.h" + +-#define DEFAULT_CHANNEL_NUMS 4 ++#define DEFAULT_CHANNEL_NUMS 5 + #define CORETEMP_CHANNEL_NUMS CORE_NUMS_MAX + #define CPUTEMP_CHANNEL_NUMS (DEFAULT_CHANNEL_NUMS + CORETEMP_CHANNEL_NUMS) + +@@ -21,6 +21,7 @@ + + struct temp_group { + struct temp_data die; ++ struct temp_data dts; + struct temp_data tcontrol; + struct temp_data tthrottle; + struct temp_data tjmax; +@@ -43,6 +44,7 @@ struct peci_cputemp { + + enum cputemp_channels { + channel_die, ++ channel_dts, + channel_tcontrol, + channel_tthrottle, + channel_tjmax, +@@ -54,6 +56,10 @@ static const u32 config_table[DEFAULT_CHANNEL_NUMS + 1] = { + HWMON_T_LABEL | HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | + HWMON_T_CRIT_HYST, + ++ /* DTS margin */ ++ HWMON_T_LABEL | HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | ++ HWMON_T_CRIT_HYST, ++ + /* Tcontrol temperature */ + HWMON_T_LABEL | HWMON_T_INPUT | HWMON_T_CRIT, + +@@ -70,6 +76,7 @@ static const u32 config_table[DEFAULT_CHANNEL_NUMS + 1] = { + + static const char *cputemp_label[CPUTEMP_CHANNEL_NUMS] = { + "Die", ++ "DTS", + "Tcontrol", + "Tthrottle", + "Tjmax", +@@ -92,19 +99,20 @@ static int get_temp_targets(struct peci_cputemp *priv) + s32 tthrottle_offset; + s32 tcontrol_margin; + u8 pkg_cfg[4]; +- int rc; ++ int ret; + +- /** ++ /* + * Just use only the tcontrol marker to determine if target values need + * update. + */ + if (!peci_temp_need_update(&priv->temp.tcontrol)) + return 0; + +- rc = peci_client_read_package_config(priv->mgr, +- MBX_INDEX_TEMP_TARGET, 0, pkg_cfg); +- if (rc) +- return rc; ++ ret = peci_client_read_package_config(priv->mgr, ++ PECI_MBX_INDEX_TEMP_TARGET, 0, ++ pkg_cfg); ++ if (ret) ++ return ret; + + priv->temp.tjmax.value = pkg_cfg[2] * 1000; + +@@ -123,17 +131,16 @@ static int get_temp_targets(struct peci_cputemp *priv) + static int get_die_temp(struct peci_cputemp *priv) + { + struct peci_get_temp_msg msg; +- int rc; ++ int ret; + + if (!peci_temp_need_update(&priv->temp.die)) + return 0; + + msg.addr = priv->mgr->client->addr; + +- rc = peci_command(priv->mgr->client->adapter, PECI_CMD_GET_TEMP, +- &msg); +- if (rc) +- return rc; ++ ret = peci_command(priv->mgr->client->adapter, PECI_CMD_GET_TEMP, &msg); ++ if (ret) ++ return ret; + + /* Note that the tjmax should be available before calling it */ + priv->temp.die.value = priv->temp.tjmax.value + +@@ -144,24 +151,67 @@ static int get_die_temp(struct peci_cputemp *priv) + return 0; + } + ++static int get_dts(struct peci_cputemp *priv) ++{ ++ struct peci_rd_pkg_cfg_msg msg; ++ s32 dts_margin; ++ int ret; ++ ++ if (!peci_temp_need_update(&priv->temp.dts)) ++ return 0; ++ ++ msg.addr = priv->mgr->client->addr; ++ msg.index = PECI_MBX_INDEX_DTS_MARGIN; ++ msg.param = 0; ++ msg.rx_len = 4; ++ ++ ret = peci_command(priv->mgr->client->adapter, PECI_CMD_RD_PKG_CFG, ++ &msg); ++ if (ret) ++ return ret; ++ ++ dts_margin = (msg.pkg_config[1] << 8) | msg.pkg_config[0]; ++ ++ /** ++ * Processors return a value of DTS reading in 10.6 format ++ * (10 bits signed decimal, 6 bits fractional). ++ * Error codes: ++ * 0x8000: General sensor error ++ * 0x8001: Reserved ++ * 0x8002: Underflow on reading value ++ * 0x8003-0x81ff: Reserved ++ */ ++ if (dts_margin >= 0x8000 && dts_margin <= 0x81ff) ++ return -EIO; ++ ++ dts_margin = ten_dot_six_to_millidegree(dts_margin); ++ ++ /* Note that the tcontrol should be available before calling it */ ++ priv->temp.dts.value = priv->temp.tcontrol.value - dts_margin; ++ ++ peci_temp_mark_updated(&priv->temp.dts); ++ ++ return 0; ++} ++ + static int get_core_temp(struct peci_cputemp *priv, int core_index) + { + s32 core_dts_margin; + u8 pkg_cfg[4]; +- int rc; ++ int ret; + + if (!peci_temp_need_update(&priv->temp.core[core_index])) + return 0; + +- rc = peci_client_read_package_config(priv->mgr, +- MBX_INDEX_PER_CORE_DTS_TEMP, +- core_index, pkg_cfg); +- if (rc) +- return rc; ++ ret = peci_client_read_package_config(priv->mgr, ++ PECI_MBX_INDEX_PER_CORE_DTS_TEMP, ++ core_index, pkg_cfg); ++ if (ret) ++ return ret; + + core_dts_margin = le16_to_cpup((__le16 *)pkg_cfg); + +- /** ++ /* + * Processors return a value of the core DTS reading in 10.6 format + * (10 bits signed decimal, 6 bits fractional). + * Error codes: +@@ -192,6 +242,7 @@ static int cputemp_read_string(struct device *dev, + return -EOPNOTSUPP; + + *str = cputemp_label[channel]; ++ + return 0; + } + +@@ -200,26 +251,33 @@ static int cputemp_read(struct device *dev, + u32 attr, int channel, long *val) + { + struct peci_cputemp *priv = dev_get_drvdata(dev); +- int rc, core_index; ++ int ret, core_index; + + if (channel >= CPUTEMP_CHANNEL_NUMS || + !(priv->temp_config[channel] & BIT(attr))) + return -EOPNOTSUPP; + +- rc = get_temp_targets(priv); +- if (rc) +- return rc; ++ ret = get_temp_targets(priv); ++ if (ret) ++ return ret; + + switch (attr) { + case hwmon_temp_input: + switch (channel) { + case channel_die: +- rc = get_die_temp(priv); +- if (rc) ++ ret = get_die_temp(priv); ++ if (ret) + break; + + *val = priv->temp.die.value; + break; ++ case channel_dts: ++ ret = get_dts(priv); ++ if (ret) ++ break; ++ ++ *val = priv->temp.dts.value; ++ break; + case channel_tcontrol: + *val = priv->temp.tcontrol.value; + break; +@@ -231,8 +289,8 @@ static int cputemp_read(struct device *dev, + break; + default: + core_index = channel - DEFAULT_CHANNEL_NUMS; +- rc = get_core_temp(priv, core_index); +- if (rc) ++ ret = get_core_temp(priv, core_index); ++ if (ret) + break; + + *val = priv->temp.core[core_index].value; +@@ -249,11 +307,11 @@ static int cputemp_read(struct device *dev, + *val = priv->temp.tjmax.value - priv->temp.tcontrol.value; + break; + default: +- rc = -EOPNOTSUPP; ++ ret = -EOPNOTSUPP; + break; + } + +- return rc; ++ return ret; + } + + static umode_t cputemp_is_visible(const void *data, +@@ -262,11 +320,11 @@ static umode_t cputemp_is_visible(const void *data, + { + const struct peci_cputemp *priv = data; + +- if (priv->temp_config[channel] & BIT(attr)) +- if (channel < DEFAULT_CHANNEL_NUMS || +- (channel >= DEFAULT_CHANNEL_NUMS && +- (priv->core_mask & BIT(channel - DEFAULT_CHANNEL_NUMS)))) +- return 0444; ++ if ((priv->temp_config[channel] & BIT(attr)) && ++ (channel < DEFAULT_CHANNEL_NUMS || ++ (channel >= DEFAULT_CHANNEL_NUMS && ++ (priv->core_mask & BIT(channel - DEFAULT_CHANNEL_NUMS))))) ++ return 0444; + + return 0; + } +@@ -280,7 +338,7 @@ static const struct hwmon_ops cputemp_ops = { + static int check_resolved_cores(struct peci_cputemp *priv) + { + struct peci_rd_pci_cfg_local_msg msg; +- int rc; ++ int ret; + + /* Get the RESOLVED_CORES register value */ + msg.addr = priv->mgr->client->addr; +@@ -290,30 +348,31 @@ static int check_resolved_cores(struct peci_cputemp *priv) + msg.reg = REG_RESOLVED_CORES_OFFSET; + msg.rx_len = 4; + +- rc = peci_command(priv->mgr->client->adapter, +- PECI_CMD_RD_PCI_CFG_LOCAL, &msg); +- if (rc) +- return rc; ++ ret = peci_command(priv->mgr->client->adapter, ++ PECI_CMD_RD_PCI_CFG_LOCAL, &msg); ++ if (ret) ++ return ret; + + priv->core_mask = le32_to_cpup((__le32 *)msg.pci_config); + if (!priv->core_mask) + return -EAGAIN; + + dev_dbg(priv->dev, "Scanned resolved cores: 0x%x\n", priv->core_mask); ++ + return 0; + } + + static int create_core_temp_info(struct peci_cputemp *priv) + { +- int rc, i; ++ int ret, i; + +- rc = check_resolved_cores(priv); +- if (rc) +- return rc; ++ ret = check_resolved_cores(priv); ++ if (ret) ++ return ret; + + for (i = 0; i < priv->gen_info->core_max; i++) + if (priv->core_mask & BIT(i)) +- while (i + DEFAULT_CHANNEL_NUMS >= priv->config_idx) ++ while (priv->config_idx <= i + DEFAULT_CHANNEL_NUMS) + priv->temp_config[priv->config_idx++] = + config_table[channel_core]; + +@@ -326,7 +385,7 @@ static int peci_cputemp_probe(struct platform_device *pdev) + struct device *dev = &pdev->dev; + struct peci_cputemp *priv; + struct device *hwmon_dev; +- int rc; ++ int ret; + + if ((mgr->client->adapter->cmd_mask & + (BIT(PECI_CMD_GET_TEMP) | BIT(PECI_CMD_RD_PKG_CFG))) != +@@ -346,12 +405,13 @@ static int peci_cputemp_probe(struct platform_device *pdev) + mgr->client->addr - PECI_BASE_ADDR); + + priv->temp_config[priv->config_idx++] = config_table[channel_die]; ++ priv->temp_config[priv->config_idx++] = config_table[channel_dts]; + priv->temp_config[priv->config_idx++] = config_table[channel_tcontrol]; + priv->temp_config[priv->config_idx++] = config_table[channel_tthrottle]; + priv->temp_config[priv->config_idx++] = config_table[channel_tjmax]; + +- rc = create_core_temp_info(priv); +- if (rc) ++ ret = create_core_temp_info(priv); ++ if (ret) + dev_dbg(dev, "Skipped creating core temp info\n"); + + priv->chip.ops = &cputemp_ops; diff --git a/drivers/hwmon/peci-dimmtemp.c b/drivers/hwmon/peci-dimmtemp.c -index 86a45a90805b..6e90d9bfeb45 100644 +index 86a45a90805b..e088366fd138 100644 --- a/drivers/hwmon/peci-dimmtemp.c +++ b/drivers/hwmon/peci-dimmtemp.c @@ -1,5 +1,5 @@ @@ -40,8 +465,180 @@ index 86a45a90805b..6e90d9bfeb45 100644 #include <linux/hwmon.h> #include <linux/jiffies.h> +@@ -45,16 +45,16 @@ static int get_dimm_temp(struct peci_dimmtemp *priv, int dimm_no) + int dimm_order = dimm_no % priv->gen_info->dimm_idx_max; + int chan_rank = dimm_no / priv->gen_info->dimm_idx_max; + u8 cfg_data[4]; +- int rc; ++ int ret; + + if (!peci_temp_need_update(&priv->temp[dimm_no])) + return 0; + +- rc = peci_client_read_package_config(priv->mgr, +- MBX_INDEX_DDR_DIMM_TEMP, +- chan_rank, cfg_data); +- if (rc) +- return rc; ++ ret = peci_client_read_package_config(priv->mgr, ++ PECI_MBX_INDEX_DDR_DIMM_TEMP, ++ chan_rank, cfg_data); ++ if (ret) ++ return ret; + + priv->temp[dimm_no].value = cfg_data[dimm_order] * 1000; + +@@ -77,6 +77,7 @@ static int dimmtemp_read_string(struct device *dev, + chan_rank = channel / dimm_idx_max; + dimm_idx = channel % dimm_idx_max; + *str = dimmtemp_label[chan_rank][dimm_idx]; ++ + return 0; + } + +@@ -84,16 +85,17 @@ static int dimmtemp_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) + { + struct peci_dimmtemp *priv = dev_get_drvdata(dev); +- int rc; ++ int ret; + + if (attr != hwmon_temp_input) + return -EOPNOTSUPP; + +- rc = get_dimm_temp(priv, channel); +- if (rc) +- return rc; ++ ret = get_dimm_temp(priv, channel); ++ if (ret) ++ return ret; + + *val = priv->temp[channel].value; ++ + return 0; + } + +@@ -120,16 +122,16 @@ static int check_populated_dimms(struct peci_dimmtemp *priv) + { + u32 chan_rank_max = priv->gen_info->chan_rank_max; + u32 dimm_idx_max = priv->gen_info->dimm_idx_max; +- int chan_rank, dimm_idx, rc; ++ int chan_rank, dimm_idx, ret; + u8 cfg_data[4]; + + for (chan_rank = 0; chan_rank < chan_rank_max; chan_rank++) { +- rc = peci_client_read_package_config(priv->mgr, +- MBX_INDEX_DDR_DIMM_TEMP, +- chan_rank, cfg_data); +- if (rc) { ++ ret = peci_client_read_package_config(priv->mgr, ++ PECI_MBX_INDEX_DDR_DIMM_TEMP, ++ chan_rank, cfg_data); ++ if (ret) { + priv->dimm_mask = 0; +- return rc; ++ return ret; + } + + for (dimm_idx = 0; dimm_idx < dimm_idx_max; dimm_idx++) +@@ -143,17 +145,18 @@ static int check_populated_dimms(struct peci_dimmtemp *priv) + return -EAGAIN; + + dev_dbg(priv->dev, "Scanned populated DIMMs: 0x%x\n", priv->dimm_mask); ++ + return 0; + } + + static int create_dimm_temp_info(struct peci_dimmtemp *priv) + { +- int rc, i, config_idx, channels; ++ int ret, i, config_idx, channels; + struct device *hwmon_dev; + +- rc = check_populated_dimms(priv); +- if (rc) { +- if (rc == -EAGAIN) { ++ ret = check_populated_dimms(priv); ++ if (ret) { ++ if (ret == -EAGAIN) { + if (priv->retry_count < DIMM_MASK_CHECK_RETRY_MAX) { + queue_delayed_work(priv->work_queue, + &priv->work_handler, +@@ -164,11 +167,11 @@ static int create_dimm_temp_info(struct peci_dimmtemp *priv) + } else { + dev_err(priv->dev, + "Timeout DIMM temp info creation\n"); +- rc = -ETIMEDOUT; ++ ret = -ETIMEDOUT; + } + } + +- return rc; ++ return ret; + } + + channels = priv->gen_info->chan_rank_max * +@@ -192,12 +195,12 @@ static int create_dimm_temp_info(struct peci_dimmtemp *priv) + priv, + &priv->chip, + NULL); +- rc = PTR_ERR_OR_ZERO(hwmon_dev); +- if (!rc) ++ ret = PTR_ERR_OR_ZERO(hwmon_dev); ++ if (!ret) + dev_dbg(priv->dev, "%s: sensor '%s'\n", + dev_name(hwmon_dev), priv->name); + +- return rc; ++ return ret; + } + + static void create_dimm_temp_info_delayed(struct work_struct *work) +@@ -205,10 +208,10 @@ static void create_dimm_temp_info_delayed(struct work_struct *work) + struct delayed_work *dwork = to_delayed_work(work); + struct peci_dimmtemp *priv = container_of(dwork, struct peci_dimmtemp, + work_handler); +- int rc; ++ int ret; + +- rc = create_dimm_temp_info(priv); +- if (rc && rc != -EAGAIN) ++ ret = create_dimm_temp_info(priv); ++ if (ret && ret != -EAGAIN) + dev_dbg(priv->dev, "Failed to create DIMM temp info\n"); + } + +@@ -217,7 +220,7 @@ static int peci_dimmtemp_probe(struct platform_device *pdev) + struct peci_client_manager *mgr = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + struct peci_dimmtemp *priv; +- int rc; ++ int ret; + + if ((mgr->client->adapter->cmd_mask & + (BIT(PECI_CMD_GET_TEMP) | BIT(PECI_CMD_RD_PKG_CFG))) != +@@ -242,8 +245,8 @@ static int peci_dimmtemp_probe(struct platform_device *pdev) + + INIT_DELAYED_WORK(&priv->work_handler, create_dimm_temp_info_delayed); + +- rc = create_dimm_temp_info(priv); +- if (rc && rc != -EAGAIN) { ++ ret = create_dimm_temp_info(priv); ++ if (ret && ret != -EAGAIN) { + dev_err(dev, "Failed to create DIMM temp info\n"); + goto err_free_wq; + } +@@ -252,7 +255,7 @@ static int peci_dimmtemp_probe(struct platform_device *pdev) + + err_free_wq: + destroy_workqueue(priv->work_queue); +- return rc; ++ return ret; + } + + static int peci_dimmtemp_remove(struct platform_device *pdev) diff --git a/drivers/hwmon/peci-hwmon.h b/drivers/hwmon/peci-hwmon.h -index 6ca1855a86bb..16e3c195094c 100644 +index 6ca1855a86bb..ce6b470eae63 100644 --- a/drivers/hwmon/peci-hwmon.h +++ b/drivers/hwmon/peci-hwmon.h @@ -1,5 +1,5 @@ @@ -51,6 +648,43 @@ index 6ca1855a86bb..16e3c195094c 100644 #ifndef __PECI_HWMON_H #define __PECI_HWMON_H +@@ -29,11 +29,8 @@ struct temp_data { + */ + static inline bool peci_temp_need_update(struct temp_data *temp) + { +- if (temp->valid && +- time_before(jiffies, temp->last_updated + UPDATE_INTERVAL)) +- return false; +- +- return true; ++ return !temp->valid || ++ time_after(jiffies, temp->last_updated + UPDATE_INTERVAL); + } + + /** +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index 66b71a6122d6..28a83b354ea8 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -596,7 +596,7 @@ config MFD_INTEL_MSIC + devices used in Intel Medfield platforms. + + config MFD_INTEL_PECI_CLIENT +- bool "Intel PECI client" ++ tristate "Intel PECI client" + depends on (PECI || COMPILE_TEST) + select MFD_CORE + help +@@ -609,6 +609,9 @@ config MFD_INTEL_PECI_CLIENT + Additional drivers must be enabled in order to use the functionality + of the device. + ++ This driver can also be built as a module. If so, the module ++ will be called intel-peci-client. ++ + config MFD_IPAQ_MICRO + bool "Atmel Micro ASIC (iPAQ h3100/h3600/h3700) Support" + depends on SA1100_H3100 || SA1100_H3600 diff --git a/drivers/mfd/intel-peci-client.c b/drivers/mfd/intel-peci-client.c index d53e4f1078ac..d62442438512 100644 --- a/drivers/mfd/intel-peci-client.c @@ -180,30 +814,2094 @@ index d53e4f1078ac..d62442438512 100644 static const struct peci_device_id peci_client_ids[] = { { .name = "peci-client" }, +diff --git a/drivers/peci/Kconfig b/drivers/peci/Kconfig +index 9e9845ebcff4..9752feee2454 100644 +--- a/drivers/peci/Kconfig ++++ b/drivers/peci/Kconfig +@@ -2,10 +2,12 @@ + # Platform Environment Control Interface (PECI) subsystem configuration + # + ++menu "PECI support" ++ + config PECI +- bool "PECI support" +- select RT_MUTEXES ++ tristate "PECI support" + select CRC8 ++ default n + help + The Platform Environment Control Interface (PECI) is a one-wire bus + interface that provides a communication channel from Intel processors +@@ -14,26 +16,23 @@ config PECI + If you want PECI support, you should say Y here and also to the + specific driver for your bus adapter(s) below. + +-if PECI +- +-# +-# PECI hardware bus configuration +-# ++ This support is also available as a module. If so, the module ++ will be called peci-core. + +-menu "PECI Hardware Bus support" ++if PECI + +-config PECI_ASPEED +- tristate "ASPEED PECI support" +- select REGMAP_MMIO +- depends on OF +- depends on ARCH_ASPEED || COMPILE_TEST ++config PECI_CHARDEV ++ tristate "PECI device interface" + help +- Say Y here if you want support for the Platform Environment Control +- Interface (PECI) bus adapter driver on the ASPEED SoCs. ++ Say Y here to use peci-* device files, usually found in the /dev ++ directory on your system. They make it possible to have user-space ++ programs use the PECI bus. + +- This support is also available as a module. If so, the module +- will be called peci-aspeed. ++ This support is also available as a module. If so, the module ++ will be called peci-dev. + +-endmenu ++source "drivers/peci/busses/Kconfig" + + endif # PECI ++ ++endmenu +diff --git a/drivers/peci/Makefile b/drivers/peci/Makefile +index 886285e69765..da8b0a33fa42 100644 +--- a/drivers/peci/Makefile ++++ b/drivers/peci/Makefile +@@ -1,9 +1,11 @@ ++# SPDX-License-Identifier: GPL-2.0 + # +-# Makefile for the PECI core and bus drivers. ++# Makefile for the PECI core drivers. + # + + # Core functionality + obj-$(CONFIG_PECI) += peci-core.o ++obj-$(CONFIG_PECI_CHARDEV) += peci-dev.o + + # Hardware specific bus drivers +-obj-$(CONFIG_PECI_ASPEED) += peci-aspeed.o ++obj-y += busses/ +diff --git a/drivers/peci/busses/Kconfig b/drivers/peci/busses/Kconfig +new file mode 100644 +index 000000000000..a20d470b4250 +--- /dev/null ++++ b/drivers/peci/busses/Kconfig +@@ -0,0 +1,19 @@ ++# ++# PECI hardware bus configuration ++# ++ ++menu "PECI Hardware Bus support" ++ ++config PECI_ASPEED ++ tristate "ASPEED PECI support" ++ depends on ARCH_ASPEED || COMPILE_TEST ++ depends on OF ++ depends on PECI ++ help ++ Say Y here if you want support for the Platform Environment Control ++ Interface (PECI) bus adapter driver on the ASPEED SoCs. ++ ++ This support is also available as a module. If so, the module ++ will be called peci-aspeed. ++ ++endmenu +diff --git a/drivers/peci/busses/Makefile b/drivers/peci/busses/Makefile +new file mode 100644 +index 000000000000..69e31dfaca19 +--- /dev/null ++++ b/drivers/peci/busses/Makefile +@@ -0,0 +1,6 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Makefile for the PECI hardware bus drivers. ++# ++ ++obj-$(CONFIG_PECI_ASPEED) += peci-aspeed.o +diff --git a/drivers/peci/busses/peci-aspeed.c b/drivers/peci/busses/peci-aspeed.c +new file mode 100644 +index 000000000000..8a0dd40730cc +--- /dev/null ++++ b/drivers/peci/busses/peci-aspeed.c +@@ -0,0 +1,494 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// Copyright (C) 2012-2017 ASPEED Technology Inc. ++// Copyright (c) 2018-2019 Intel Corporation ++ ++#include <linux/bitfield.h> ++#include <linux/clk.h> ++#include <linux/delay.h> ++#include <linux/interrupt.h> ++#include <linux/io.h> ++#include <linux/jiffies.h> ++#include <linux/module.h> ++#include <linux/of.h> ++#include <linux/peci.h> ++#include <linux/platform_device.h> ++#include <linux/reset.h> ++ ++/* ASPEED PECI Registers */ ++/* Control Register */ ++#define ASPEED_PECI_CTRL 0x00 ++#define ASPEED_PECI_CTRL_SAMPLING_MASK GENMASK(19, 16) ++#define ASPEED_PECI_CTRL_READ_MODE_MASK GENMASK(13, 12) ++#define ASPEED_PECI_CTRL_READ_MODE_COUNT BIT(12) ++#define ASPEED_PECI_CTRL_READ_MODE_DBG BIT(13) ++#define ASPEED_PECI_CTRL_CLK_SOURCE_MASK BIT(11) ++#define ASPEED_PECI_CTRL_CLK_DIV_MASK GENMASK(10, 8) ++#define ASPEED_PECI_CTRL_INVERT_OUT BIT(7) ++#define ASPEED_PECI_CTRL_INVERT_IN BIT(6) ++#define ASPEED_PECI_CTRL_BUS_CONTENT_EN BIT(5) ++#define ASPEED_PECI_CTRL_PECI_EN BIT(4) ++#define ASPEED_PECI_CTRL_PECI_CLK_EN BIT(0) ++ ++/* Timing Negotiation Register */ ++#define ASPEED_PECI_TIMING_NEGOTIATION 0x04 ++#define ASPEED_PECI_TIMING_MESSAGE_MASK GENMASK(15, 8) ++#define ASPEED_PECI_TIMING_ADDRESS_MASK GENMASK(7, 0) ++ ++/* Command Register */ ++#define ASPEED_PECI_CMD 0x08 ++#define ASPEED_PECI_CMD_PIN_MON BIT(31) ++#define ASPEED_PECI_CMD_STS_MASK GENMASK(27, 24) ++#define ASPEED_PECI_CMD_IDLE_MASK (ASPEED_PECI_CMD_STS_MASK | \ ++ ASPEED_PECI_CMD_PIN_MON) ++#define ASPEED_PECI_CMD_FIRE BIT(0) ++ ++/* Read/Write Length Register */ ++#define ASPEED_PECI_RW_LENGTH 0x0c ++#define ASPEED_PECI_AW_FCS_EN BIT(31) ++#define ASPEED_PECI_READ_LEN_MASK GENMASK(23, 16) ++#define ASPEED_PECI_WRITE_LEN_MASK GENMASK(15, 8) ++#define ASPEED_PECI_TAGET_ADDR_MASK GENMASK(7, 0) ++ ++/* Expected FCS Data Register */ ++#define ASPEED_PECI_EXP_FCS 0x10 ++#define ASPEED_PECI_EXP_READ_FCS_MASK GENMASK(23, 16) ++#define ASPEED_PECI_EXP_AW_FCS_AUTO_MASK GENMASK(15, 8) ++#define ASPEED_PECI_EXP_WRITE_FCS_MASK GENMASK(7, 0) ++ ++/* Captured FCS Data Register */ ++#define ASPEED_PECI_CAP_FCS 0x14 ++#define ASPEED_PECI_CAP_READ_FCS_MASK GENMASK(23, 16) ++#define ASPEED_PECI_CAP_WRITE_FCS_MASK GENMASK(7, 0) ++ ++/* Interrupt Register */ ++#define ASPEED_PECI_INT_CTRL 0x18 ++#define ASPEED_PECI_TIMING_NEGO_SEL_MASK GENMASK(31, 30) ++#define ASPEED_PECI_1ST_BIT_OF_ADDR_NEGO 0 ++#define ASPEED_PECI_2ND_BIT_OF_ADDR_NEGO 1 ++#define ASPEED_PECI_MESSAGE_NEGO 2 ++#define ASPEED_PECI_INT_MASK GENMASK(4, 0) ++#define ASPEED_PECI_INT_BUS_TIMEOUT BIT(4) ++#define ASPEED_PECI_INT_BUS_CONNECT BIT(3) ++#define ASPEED_PECI_INT_W_FCS_BAD BIT(2) ++#define ASPEED_PECI_INT_W_FCS_ABORT BIT(1) ++#define ASPEED_PECI_INT_CMD_DONE BIT(0) ++ ++/* Interrupt Status Register */ ++#define ASPEED_PECI_INT_STS 0x1c ++#define ASPEED_PECI_INT_TIMING_RESULT_MASK GENMASK(29, 16) ++ /* bits[4..0]: Same bit fields in the 'Interrupt Register' */ ++ ++/* Rx/Tx Data Buffer Registers */ ++#define ASPEED_PECI_W_DATA0 0x20 ++#define ASPEED_PECI_W_DATA1 0x24 ++#define ASPEED_PECI_W_DATA2 0x28 ++#define ASPEED_PECI_W_DATA3 0x2c ++#define ASPEED_PECI_R_DATA0 0x30 ++#define ASPEED_PECI_R_DATA1 0x34 ++#define ASPEED_PECI_R_DATA2 0x38 ++#define ASPEED_PECI_R_DATA3 0x3c ++#define ASPEED_PECI_W_DATA4 0x40 ++#define ASPEED_PECI_W_DATA5 0x44 ++#define ASPEED_PECI_W_DATA6 0x48 ++#define ASPEED_PECI_W_DATA7 0x4c ++#define ASPEED_PECI_R_DATA4 0x50 ++#define ASPEED_PECI_R_DATA5 0x54 ++#define ASPEED_PECI_R_DATA6 0x58 ++#define ASPEED_PECI_R_DATA7 0x5c ++#define ASPEED_PECI_DATA_BUF_SIZE_MAX 32 ++ ++/* Timing Negotiation */ ++#define ASPEED_PECI_RD_SAMPLING_POINT_DEFAULT 8 ++#define ASPEED_PECI_RD_SAMPLING_POINT_MAX 15 ++#define ASPEED_PECI_CLK_DIV_DEFAULT 0 ++#define ASPEED_PECI_CLK_DIV_MAX 7 ++#define ASPEED_PECI_MSG_TIMING_DEFAULT 1 ++#define ASPEED_PECI_MSG_TIMING_MAX 255 ++#define ASPEED_PECI_ADDR_TIMING_DEFAULT 1 ++#define ASPEED_PECI_ADDR_TIMING_MAX 255 ++ ++/* Timeout */ ++#define ASPEED_PECI_IDLE_CHECK_TIMEOUT_USEC 50000 ++#define ASPEED_PECI_IDLE_CHECK_INTERVAL_USEC 10000 ++#define ASPEED_PECI_CMD_TIMEOUT_MS_DEFAULT 1000 ++#define ASPEED_PECI_CMD_TIMEOUT_MS_MAX 60000 ++ ++struct aspeed_peci { ++ struct peci_adapter *adapter; ++ struct device *dev; ++ void __iomem *base; ++ struct clk *clk; ++ struct reset_control *rst; ++ int irq; ++ spinlock_t lock; /* to sync completion status handling */ ++ struct completion xfer_complete; ++ u32 status; ++ u32 cmd_timeout_ms; ++}; ++ ++static int aspeed_peci_check_idle(struct aspeed_peci *priv) ++{ ++ ulong timeout = jiffies + usecs_to_jiffies(ASPEED_PECI_IDLE_CHECK_TIMEOUT_USEC); ++ u32 cmd_sts; ++ ++ for (;;) { ++ cmd_sts = readl(priv->base + ASPEED_PECI_CMD); ++ if (!(cmd_sts & ASPEED_PECI_CMD_IDLE_MASK)) ++ break; ++ if (time_after(jiffies, timeout)) { ++ cmd_sts = readl(priv->base + ASPEED_PECI_CMD); ++ break; ++ } ++ usleep_range((ASPEED_PECI_IDLE_CHECK_INTERVAL_USEC >> 2) + 1, ++ ASPEED_PECI_IDLE_CHECK_INTERVAL_USEC); ++ } ++ ++ return !(cmd_sts & ASPEED_PECI_CMD_IDLE_MASK) ? 0 : -ETIMEDOUT; ++} ++ ++static int aspeed_peci_xfer(struct peci_adapter *adapter, ++ struct peci_xfer_msg *msg) ++{ ++ struct aspeed_peci *priv = peci_get_adapdata(adapter); ++ long err, timeout = msecs_to_jiffies(priv->cmd_timeout_ms); ++ u32 peci_head, peci_state, rx_data = 0; ++ ulong flags; ++ int i, ret; ++ uint reg; ++ ++ if (msg->tx_len > ASPEED_PECI_DATA_BUF_SIZE_MAX || ++ msg->rx_len > ASPEED_PECI_DATA_BUF_SIZE_MAX) ++ return -EINVAL; ++ ++ /* Check command sts and bus idle state */ ++ ret = aspeed_peci_check_idle(priv); ++ if (ret) ++ return ret; /* -ETIMEDOUT */ ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ reinit_completion(&priv->xfer_complete); ++ ++ peci_head = FIELD_PREP(ASPEED_PECI_TAGET_ADDR_MASK, msg->addr) | ++ FIELD_PREP(ASPEED_PECI_WRITE_LEN_MASK, msg->tx_len) | ++ FIELD_PREP(ASPEED_PECI_READ_LEN_MASK, msg->rx_len); ++ ++ writel(peci_head, priv->base + ASPEED_PECI_RW_LENGTH); ++ ++ for (i = 0; i < msg->tx_len; i += 4) { ++ reg = i < 16 ? ASPEED_PECI_W_DATA0 + i % 16 : ++ ASPEED_PECI_W_DATA4 + i % 16; ++ writel(le32_to_cpup((__le32 *)&msg->tx_buf[i]), ++ priv->base + reg); ++ } ++ ++ dev_dbg(priv->dev, "HEAD : 0x%08x\n", peci_head); ++ print_hex_dump_debug("TX : ", DUMP_PREFIX_NONE, 16, 1, ++ msg->tx_buf, msg->tx_len, true); ++ ++ priv->status = 0; ++ writel(ASPEED_PECI_CMD_FIRE, priv->base + ASPEED_PECI_CMD); ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ err = wait_for_completion_interruptible_timeout(&priv->xfer_complete, ++ timeout); ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ dev_dbg(priv->dev, "INT_STS : 0x%08x\n", priv->status); ++ peci_state = readl(priv->base + ASPEED_PECI_CMD); ++ dev_dbg(priv->dev, "PECI_STATE : 0x%lx\n", ++ FIELD_GET(ASPEED_PECI_CMD_STS_MASK, peci_state)); ++ ++ writel(0, priv->base + ASPEED_PECI_CMD); ++ ++ if (err <= 0 || priv->status != ASPEED_PECI_INT_CMD_DONE) { ++ if (err < 0) { /* -ERESTARTSYS */ ++ ret = (int)err; ++ goto err_irqrestore; ++ } else if (err == 0) { ++ dev_dbg(priv->dev, "Timeout waiting for a response!\n"); ++ ret = -ETIMEDOUT; ++ goto err_irqrestore; ++ } ++ ++ dev_dbg(priv->dev, "No valid response!\n"); ++ ret = -EIO; ++ goto err_irqrestore; ++ } ++ ++ /* ++ * Note that rx_len and rx_buf size can be an odd number. ++ * Byte handling is more efficient. ++ */ ++ for (i = 0; i < msg->rx_len; i++) { ++ u8 byte_offset = i % 4; ++ ++ if (byte_offset == 0) { ++ reg = i < 16 ? ASPEED_PECI_R_DATA0 + i % 16 : ++ ASPEED_PECI_R_DATA4 + i % 16; ++ rx_data = readl(priv->base + reg); ++ } ++ ++ msg->rx_buf[i] = (u8)(rx_data >> (byte_offset << 3)); ++ } ++ ++ print_hex_dump_debug("RX : ", DUMP_PREFIX_NONE, 16, 1, ++ msg->rx_buf, msg->rx_len, true); ++ ++ peci_state = readl(priv->base + ASPEED_PECI_CMD); ++ dev_dbg(priv->dev, "PECI_STATE : 0x%lx\n", ++ FIELD_GET(ASPEED_PECI_CMD_STS_MASK, peci_state)); ++ dev_dbg(priv->dev, "------------------------\n"); ++ ++err_irqrestore: ++ spin_unlock_irqrestore(&priv->lock, flags); ++ return ret; ++} ++ ++static irqreturn_t aspeed_peci_irq_handler(int irq, void *arg) ++{ ++ struct aspeed_peci *priv = arg; ++ u32 status; ++ ++ spin_lock(&priv->lock); ++ status = readl(priv->base + ASPEED_PECI_INT_STS); ++ writel(status, priv->base + ASPEED_PECI_INT_STS); ++ priv->status |= (status & ASPEED_PECI_INT_MASK); ++ ++ /* ++ * In most cases, interrupt bits will be set one by one but also note ++ * that multiple interrupt bits could be set at the same time. ++ */ ++ if (status & ASPEED_PECI_INT_BUS_TIMEOUT) { ++ dev_dbg(priv->dev, "ASPEED_PECI_INT_BUS_TIMEOUT\n"); ++ } ++ ++ if (status & ASPEED_PECI_INT_BUS_CONNECT) { ++ dev_dbg(priv->dev, "ASPEED_PECI_INT_BUS_CONNECT\n"); ++ } ++ ++ if (status & ASPEED_PECI_INT_W_FCS_BAD) { ++ dev_dbg(priv->dev, "ASPEED_PECI_INT_W_FCS_BAD\n"); ++ } ++ ++ if (status & ASPEED_PECI_INT_W_FCS_ABORT) { ++ dev_dbg(priv->dev, "ASPEED_PECI_INT_W_FCS_ABORT\n"); ++ } ++ ++ /* ++ * All commands should be ended up with a ASPEED_PECI_INT_CMD_DONE bit ++ * set even in an error case. ++ */ ++ if (status & ASPEED_PECI_INT_CMD_DONE) { ++ dev_dbg(priv->dev, "ASPEED_PECI_INT_CMD_DONE\n"); ++ complete(&priv->xfer_complete); ++ } ++ ++ spin_unlock(&priv->lock); ++ return IRQ_HANDLED; ++} ++ ++static int aspeed_peci_init_ctrl(struct aspeed_peci *priv) ++{ ++ u32 msg_timing, addr_timing, rd_sampling_point; ++ u32 clk_freq, clk_divisor, clk_div_val = 0; ++ int ret; ++ ++ priv->clk = devm_clk_get(priv->dev, NULL); ++ if (IS_ERR(priv->clk)) { ++ dev_err(priv->dev, "Failed to get clk source.\n"); ++ return PTR_ERR(priv->clk); ++ } ++ ++ ret = clk_prepare_enable(priv->clk); ++ if (ret) { ++ dev_err(priv->dev, "Failed to enable clock.\n"); ++ return ret; ++ } ++ ++ ret = device_property_read_u32(priv->dev, "clock-frequency", &clk_freq); ++ if (ret) { ++ dev_err(priv->dev, ++ "Could not read clock-frequency property.\n"); ++ clk_disable_unprepare(priv->clk); ++ return ret; ++ } ++ ++ clk_divisor = clk_get_rate(priv->clk) / clk_freq; ++ ++ while ((clk_divisor >> 1) && (clk_div_val < ASPEED_PECI_CLK_DIV_MAX)) ++ clk_div_val++; ++ ++ ret = device_property_read_u32(priv->dev, "msg-timing", &msg_timing); ++ if (ret || msg_timing > ASPEED_PECI_MSG_TIMING_MAX) { ++ if (!ret) ++ dev_warn(priv->dev, ++ "Invalid msg-timing : %u, Use default : %u\n", ++ msg_timing, ASPEED_PECI_MSG_TIMING_DEFAULT); ++ msg_timing = ASPEED_PECI_MSG_TIMING_DEFAULT; ++ } ++ ++ ret = device_property_read_u32(priv->dev, "addr-timing", &addr_timing); ++ if (ret || addr_timing > ASPEED_PECI_ADDR_TIMING_MAX) { ++ if (!ret) ++ dev_warn(priv->dev, ++ "Invalid addr-timing : %u, Use default : %u\n", ++ addr_timing, ASPEED_PECI_ADDR_TIMING_DEFAULT); ++ addr_timing = ASPEED_PECI_ADDR_TIMING_DEFAULT; ++ } ++ ++ ret = device_property_read_u32(priv->dev, "rd-sampling-point", ++ &rd_sampling_point); ++ if (ret || rd_sampling_point > ASPEED_PECI_RD_SAMPLING_POINT_MAX) { ++ if (!ret) ++ dev_warn(priv->dev, ++ "Invalid rd-sampling-point : %u. Use default : %u\n", ++ rd_sampling_point, ++ ASPEED_PECI_RD_SAMPLING_POINT_DEFAULT); ++ rd_sampling_point = ASPEED_PECI_RD_SAMPLING_POINT_DEFAULT; ++ } ++ ++ ret = device_property_read_u32(priv->dev, "cmd-timeout-ms", ++ &priv->cmd_timeout_ms); ++ if (ret || priv->cmd_timeout_ms > ASPEED_PECI_CMD_TIMEOUT_MS_MAX || ++ priv->cmd_timeout_ms == 0) { ++ if (!ret) ++ dev_warn(priv->dev, ++ "Invalid cmd-timeout-ms : %u. Use default : %u\n", ++ priv->cmd_timeout_ms, ++ ASPEED_PECI_CMD_TIMEOUT_MS_DEFAULT); ++ priv->cmd_timeout_ms = ASPEED_PECI_CMD_TIMEOUT_MS_DEFAULT; ++ } ++ ++ writel(FIELD_PREP(ASPEED_PECI_CTRL_CLK_DIV_MASK, ++ ASPEED_PECI_CLK_DIV_DEFAULT) | ++ ASPEED_PECI_CTRL_PECI_CLK_EN, priv->base + ASPEED_PECI_CTRL); ++ ++ /* ++ * Timing negotiation period setting. ++ * The unit of the programmed value is 4 times of PECI clock period. ++ */ ++ writel(FIELD_PREP(ASPEED_PECI_TIMING_MESSAGE_MASK, msg_timing) | ++ FIELD_PREP(ASPEED_PECI_TIMING_ADDRESS_MASK, addr_timing), ++ priv->base + ASPEED_PECI_TIMING_NEGOTIATION); ++ ++ /* Clear interrupts */ ++ writel(readl(priv->base + ASPEED_PECI_INT_STS) | ASPEED_PECI_INT_MASK, ++ priv->base + ASPEED_PECI_INT_STS); ++ ++ /* Set timing negotiation mode and enable interrupts */ ++ writel(FIELD_PREP(ASPEED_PECI_TIMING_NEGO_SEL_MASK, ++ ASPEED_PECI_1ST_BIT_OF_ADDR_NEGO) | ++ ASPEED_PECI_INT_MASK, priv->base + ASPEED_PECI_INT_CTRL); ++ ++ /* Read sampling point and clock speed setting */ ++ writel(FIELD_PREP(ASPEED_PECI_CTRL_SAMPLING_MASK, rd_sampling_point) | ++ FIELD_PREP(ASPEED_PECI_CTRL_CLK_DIV_MASK, clk_div_val) | ++ ASPEED_PECI_CTRL_PECI_EN | ASPEED_PECI_CTRL_PECI_CLK_EN, ++ priv->base + ASPEED_PECI_CTRL); ++ ++ return 0; ++} ++ ++static int aspeed_peci_probe(struct platform_device *pdev) ++{ ++ struct peci_adapter *adapter; ++ struct aspeed_peci *priv; ++ struct resource *res; ++ int ret; ++ ++ adapter = peci_alloc_adapter(&pdev->dev, sizeof(*priv)); ++ if (!adapter) ++ return -ENOMEM; ++ ++ priv = peci_get_adapdata(adapter); ++ priv->adapter = adapter; ++ priv->dev = &pdev->dev; ++ dev_set_drvdata(&pdev->dev, priv); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ priv->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(priv->base)) { ++ ret = PTR_ERR(priv->base); ++ goto err_put_adapter_dev; ++ } ++ ++ priv->irq = platform_get_irq(pdev, 0); ++ if (!priv->irq) { ++ ret = -ENODEV; ++ goto err_put_adapter_dev; ++ } ++ ++ ret = devm_request_irq(&pdev->dev, priv->irq, aspeed_peci_irq_handler, ++ 0, "peci-aspeed-irq", priv); ++ if (ret) ++ goto err_put_adapter_dev; ++ ++ init_completion(&priv->xfer_complete); ++ spin_lock_init(&priv->lock); ++ ++ priv->adapter->owner = THIS_MODULE; ++ priv->adapter->dev.of_node = of_node_get(dev_of_node(priv->dev)); ++ strlcpy(priv->adapter->name, pdev->name, sizeof(priv->adapter->name)); ++ priv->adapter->xfer = aspeed_peci_xfer; ++ priv->adapter->use_dma = false; ++ ++ priv->rst = devm_reset_control_get(&pdev->dev, NULL); ++ if (IS_ERR(priv->rst)) { ++ dev_err(&pdev->dev, ++ "missing or invalid reset controller entry"); ++ ret = PTR_ERR(priv->rst); ++ goto err_put_adapter_dev; ++ } ++ reset_control_deassert(priv->rst); ++ ++ ret = aspeed_peci_init_ctrl(priv); ++ if (ret) ++ goto err_put_adapter_dev; ++ ++ ret = peci_add_adapter(priv->adapter); ++ if (ret) ++ goto err_put_adapter_dev; ++ ++ dev_info(&pdev->dev, "peci bus %d registered, irq %d\n", ++ priv->adapter->nr, priv->irq); ++ ++ return 0; ++ ++err_put_adapter_dev: ++ put_device(&adapter->dev); ++ return ret; ++} ++ ++static int aspeed_peci_remove(struct platform_device *pdev) ++{ ++ struct aspeed_peci *priv = dev_get_drvdata(&pdev->dev); ++ ++ clk_disable_unprepare(priv->clk); ++ reset_control_assert(priv->rst); ++ peci_del_adapter(priv->adapter); ++ of_node_put(priv->adapter->dev.of_node); ++ ++ return 0; ++} ++ ++static const struct of_device_id aspeed_peci_of_table[] = { ++ { .compatible = "aspeed,ast2400-peci", }, ++ { .compatible = "aspeed,ast2500-peci", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, aspeed_peci_of_table); ++ ++static struct platform_driver aspeed_peci_driver = { ++ .probe = aspeed_peci_probe, ++ .remove = aspeed_peci_remove, ++ .driver = { ++ .name = "peci-aspeed", ++ .of_match_table = of_match_ptr(aspeed_peci_of_table), ++ }, ++}; ++module_platform_driver(aspeed_peci_driver); ++ ++MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>"); ++MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>"); ++MODULE_DESCRIPTION("ASPEED PECI driver"); ++MODULE_LICENSE("GPL v2"); diff --git a/drivers/peci/peci-aspeed.c b/drivers/peci/peci-aspeed.c -index 51cb2563ceb6..2293d4e56e63 100644 +deleted file mode 100644 +index 51cb2563ceb6..000000000000 --- a/drivers/peci/peci-aspeed.c -+++ b/drivers/peci/peci-aspeed.c -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0 - // Copyright (C) 2012-2017 ASPEED Technology Inc. ++++ /dev/null +@@ -1,505 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-// Copyright (C) 2012-2017 ASPEED Technology Inc. -// Copyright (c) 2018 Intel Corporation -+// Copyright (c) 2018-2019 Intel Corporation - - #include <linux/bitfield.h> - #include <linux/clk.h> +- +-#include <linux/bitfield.h> +-#include <linux/clk.h> +-#include <linux/interrupt.h> +-#include <linux/jiffies.h> +-#include <linux/module.h> +-#include <linux/of.h> +-#include <linux/peci.h> +-#include <linux/platform_device.h> +-#include <linux/regmap.h> +-#include <linux/reset.h> +- +-/* ASPEED PECI Registers */ +-#define ASPEED_PECI_CTRL 0x00 +-#define ASPEED_PECI_TIMING 0x04 +-#define ASPEED_PECI_CMD 0x08 +-#define ASPEED_PECI_CMD_CTRL 0x0c +-#define ASPEED_PECI_EXP_FCS 0x10 +-#define ASPEED_PECI_CAP_FCS 0x14 +-#define ASPEED_PECI_INT_CTRL 0x18 +-#define ASPEED_PECI_INT_STS 0x1c +-#define ASPEED_PECI_W_DATA0 0x20 +-#define ASPEED_PECI_W_DATA1 0x24 +-#define ASPEED_PECI_W_DATA2 0x28 +-#define ASPEED_PECI_W_DATA3 0x2c +-#define ASPEED_PECI_R_DATA0 0x30 +-#define ASPEED_PECI_R_DATA1 0x34 +-#define ASPEED_PECI_R_DATA2 0x38 +-#define ASPEED_PECI_R_DATA3 0x3c +-#define ASPEED_PECI_W_DATA4 0x40 +-#define ASPEED_PECI_W_DATA5 0x44 +-#define ASPEED_PECI_W_DATA6 0x48 +-#define ASPEED_PECI_W_DATA7 0x4c +-#define ASPEED_PECI_R_DATA4 0x50 +-#define ASPEED_PECI_R_DATA5 0x54 +-#define ASPEED_PECI_R_DATA6 0x58 +-#define ASPEED_PECI_R_DATA7 0x5c +- +-/* ASPEED_PECI_CTRL - 0x00 : Control Register */ +-#define PECI_CTRL_SAMPLING_MASK GENMASK(19, 16) +-#define PECI_CTRL_READ_MODE_MASK GENMASK(13, 12) +-#define PECI_CTRL_READ_MODE_COUNT BIT(12) +-#define PECI_CTRL_READ_MODE_DBG BIT(13) +-#define PECI_CTRL_CLK_SOURCE_MASK BIT(11) +-#define PECI_CTRL_CLK_DIV_MASK GENMASK(10, 8) +-#define PECI_CTRL_INVERT_OUT BIT(7) +-#define PECI_CTRL_INVERT_IN BIT(6) +-#define PECI_CTRL_BUS_CONTENT_EN BIT(5) +-#define PECI_CTRL_PECI_EN BIT(4) +-#define PECI_CTRL_PECI_CLK_EN BIT(0) +- +-/* ASPEED_PECI_TIMING - 0x04 : Timing Negotiation Register */ +-#define PECI_TIMING_MESSAGE_MASK GENMASK(15, 8) +-#define PECI_TIMING_ADDRESS_MASK GENMASK(7, 0) +- +-/* ASPEED_PECI_CMD - 0x08 : Command Register */ +-#define PECI_CMD_PIN_MON BIT(31) +-#define PECI_CMD_STS_MASK GENMASK(27, 24) +-#define PECI_CMD_IDLE_MASK (PECI_CMD_STS_MASK | PECI_CMD_PIN_MON) +-#define PECI_CMD_FIRE BIT(0) +- +-/* ASPEED_PECI_LEN - 0x0C : Read/Write Length Register */ +-#define PECI_AW_FCS_EN BIT(31) +-#define PECI_READ_LEN_MASK GENMASK(23, 16) +-#define PECI_WRITE_LEN_MASK GENMASK(15, 8) +-#define PECI_TAGET_ADDR_MASK GENMASK(7, 0) +- +-/* ASPEED_PECI_EXP_FCS - 0x10 : Expected FCS Data Register */ +-#define PECI_EXPECT_READ_FCS_MASK GENMASK(23, 16) +-#define PECI_EXPECT_AW_FCS_AUTO_MASK GENMASK(15, 8) +-#define PECI_EXPECT_WRITE_FCS_MASK GENMASK(7, 0) +- +-/* ASPEED_PECI_CAP_FCS - 0x14 : Captured FCS Data Register */ +-#define PECI_CAPTURE_READ_FCS_MASK GENMASK(23, 16) +-#define PECI_CAPTURE_WRITE_FCS_MASK GENMASK(7, 0) +- +-/* ASPEED_PECI_INT_CTRL/STS - 0x18/0x1c : Interrupt Register */ +-#define PECI_INT_TIMING_RESULT_MASK GENMASK(31, 30) +-#define PECI_INT_TIMEOUT BIT(4) +-#define PECI_INT_CONNECT BIT(3) +-#define PECI_INT_W_FCS_BAD BIT(2) +-#define PECI_INT_W_FCS_ABORT BIT(1) +-#define PECI_INT_CMD_DONE BIT(0) +- +-#define PECI_INT_MASK (PECI_INT_TIMEOUT | PECI_INT_CONNECT | \ +- PECI_INT_W_FCS_BAD | PECI_INT_W_FCS_ABORT | \ +- PECI_INT_CMD_DONE) +- +-#define PECI_IDLE_CHECK_TIMEOUT_USEC 50000 +-#define PECI_IDLE_CHECK_INTERVAL_USEC 10000 +- +-#define PECI_RD_SAMPLING_POINT_DEFAULT 8 +-#define PECI_RD_SAMPLING_POINT_MAX 15 +-#define PECI_CLK_DIV_DEFAULT 0 +-#define PECI_CLK_DIV_MAX 7 +-#define PECI_MSG_TIMING_DEFAULT 1 +-#define PECI_MSG_TIMING_MAX 255 +-#define PECI_ADDR_TIMING_DEFAULT 1 +-#define PECI_ADDR_TIMING_MAX 255 +-#define PECI_CMD_TIMEOUT_MS_DEFAULT 1000 +-#define PECI_CMD_TIMEOUT_MS_MAX 60000 +- +-struct aspeed_peci { +- struct peci_adapter *adapter; +- struct device *dev; +- struct regmap *regmap; +- struct clk *clk; +- struct reset_control *rst; +- int irq; +- spinlock_t lock; /* to sync completion status handling */ +- struct completion xfer_complete; +- u32 status; +- u32 cmd_timeout_ms; +-}; +- +-static int aspeed_peci_xfer_native(struct aspeed_peci *priv, +- struct peci_xfer_msg *msg) +-{ +- long err, timeout = msecs_to_jiffies(priv->cmd_timeout_ms); +- u32 peci_head, peci_state, rx_data, cmd_sts; +- unsigned long flags; +- int i, rc; +- uint reg; +- +- /* Check command sts and bus idle state */ +- rc = regmap_read_poll_timeout(priv->regmap, ASPEED_PECI_CMD, cmd_sts, +- !(cmd_sts & PECI_CMD_IDLE_MASK), +- PECI_IDLE_CHECK_INTERVAL_USEC, +- PECI_IDLE_CHECK_TIMEOUT_USEC); +- if (rc) +- return rc; /* -ETIMEDOUT */ +- +- spin_lock_irqsave(&priv->lock, flags); +- reinit_completion(&priv->xfer_complete); +- +- peci_head = FIELD_PREP(PECI_TAGET_ADDR_MASK, msg->addr) | +- FIELD_PREP(PECI_WRITE_LEN_MASK, msg->tx_len) | +- FIELD_PREP(PECI_READ_LEN_MASK, msg->rx_len); +- +- regmap_write(priv->regmap, ASPEED_PECI_CMD_CTRL, peci_head); +- +- for (i = 0; i < msg->tx_len; i += 4) { +- reg = i < 16 ? ASPEED_PECI_W_DATA0 + i % 16 : +- ASPEED_PECI_W_DATA4 + i % 16; +- regmap_write(priv->regmap, reg, +- le32_to_cpup((__le32 *)&msg->tx_buf[i])); +- } +- +- dev_dbg(priv->dev, "HEAD : 0x%08x\n", peci_head); +- print_hex_dump_debug("TX : ", DUMP_PREFIX_NONE, 16, 1, +- msg->tx_buf, msg->tx_len, true); +- +- priv->status = 0; +- regmap_write(priv->regmap, ASPEED_PECI_CMD, PECI_CMD_FIRE); +- spin_unlock_irqrestore(&priv->lock, flags); +- +- err = wait_for_completion_interruptible_timeout(&priv->xfer_complete, +- timeout); +- +- spin_lock_irqsave(&priv->lock, flags); +- dev_dbg(priv->dev, "INT_STS : 0x%08x\n", priv->status); +- regmap_read(priv->regmap, ASPEED_PECI_CMD, &peci_state); +- dev_dbg(priv->dev, "PECI_STATE : 0x%lx\n", +- FIELD_GET(PECI_CMD_STS_MASK, peci_state)); +- +- regmap_write(priv->regmap, ASPEED_PECI_CMD, 0); +- +- if (err <= 0 || priv->status != PECI_INT_CMD_DONE) { +- if (err < 0) { /* -ERESTARTSYS */ +- rc = (int)err; +- goto err_irqrestore; +- } else if (err == 0) { +- dev_dbg(priv->dev, "Timeout waiting for a response!\n"); +- rc = -ETIMEDOUT; +- goto err_irqrestore; +- } +- +- dev_dbg(priv->dev, "No valid response!\n"); +- rc = -EIO; +- goto err_irqrestore; +- } +- +- /** +- * Note that rx_len and rx_buf size can be an odd number. +- * Byte handling is more efficient. +- */ +- for (i = 0; i < msg->rx_len; i++) { +- u8 byte_offset = i % 4; +- +- if (byte_offset == 0) { +- reg = i < 16 ? ASPEED_PECI_R_DATA0 + i % 16 : +- ASPEED_PECI_R_DATA4 + i % 16; +- regmap_read(priv->regmap, reg, &rx_data); +- } +- +- msg->rx_buf[i] = (u8)(rx_data >> (byte_offset << 3)); +- } +- +- print_hex_dump_debug("RX : ", DUMP_PREFIX_NONE, 16, 1, +- msg->rx_buf, msg->rx_len, true); +- +- regmap_read(priv->regmap, ASPEED_PECI_CMD, &peci_state); +- dev_dbg(priv->dev, "PECI_STATE : 0x%lx\n", +- FIELD_GET(PECI_CMD_STS_MASK, peci_state)); +- dev_dbg(priv->dev, "------------------------\n"); +- +-err_irqrestore: +- spin_unlock_irqrestore(&priv->lock, flags); +- return rc; +-} +- +-static irqreturn_t aspeed_peci_irq_handler(int irq, void *arg) +-{ +- struct aspeed_peci *priv = arg; +- u32 status_ack = 0; +- u32 status; +- +- spin_lock(&priv->lock); +- regmap_read(priv->regmap, ASPEED_PECI_INT_STS, &status); +- priv->status |= (status & PECI_INT_MASK); +- +- /** +- * In most cases, interrupt bits will be set one by one but also note +- * that multiple interrupt bits could be set at the same time. +- */ +- if (status & PECI_INT_TIMEOUT) { +- dev_dbg(priv->dev, "PECI_INT_TIMEOUT\n"); +- status_ack |= PECI_INT_TIMEOUT; +- } +- +- if (status & PECI_INT_CONNECT) { +- dev_dbg(priv->dev, "PECI_INT_CONNECT\n"); +- status_ack |= PECI_INT_CONNECT; +- } +- +- if (status & PECI_INT_W_FCS_BAD) { +- dev_dbg(priv->dev, "PECI_INT_W_FCS_BAD\n"); +- status_ack |= PECI_INT_W_FCS_BAD; +- } +- +- if (status & PECI_INT_W_FCS_ABORT) { +- dev_dbg(priv->dev, "PECI_INT_W_FCS_ABORT\n"); +- status_ack |= PECI_INT_W_FCS_ABORT; +- } +- +- /** +- * All commands should be ended up with a PECI_INT_CMD_DONE bit set +- * even in an error case. +- */ +- if (status & PECI_INT_CMD_DONE) { +- dev_dbg(priv->dev, "PECI_INT_CMD_DONE\n"); +- status_ack |= PECI_INT_CMD_DONE; +- complete(&priv->xfer_complete); +- } +- +- regmap_write(priv->regmap, ASPEED_PECI_INT_STS, status_ack); +- spin_unlock(&priv->lock); +- return IRQ_HANDLED; +-} +- +-static int aspeed_peci_init_ctrl(struct aspeed_peci *priv) +-{ +- u32 msg_timing, addr_timing, rd_sampling_point; +- u32 clk_freq, clk_divisor, clk_div_val = 0; +- int ret; +- +- priv->clk = devm_clk_get(priv->dev, NULL); +- if (IS_ERR(priv->clk)) { +- dev_err(priv->dev, "Failed to get clk source.\n"); +- return PTR_ERR(priv->clk); +- } +- +- ret = clk_prepare_enable(priv->clk); +- if (ret) { +- dev_err(priv->dev, "Failed to enable clock.\n"); +- return ret; +- } +- +- ret = of_property_read_u32(priv->dev->of_node, "clock-frequency", +- &clk_freq); +- if (ret) { +- dev_err(priv->dev, +- "Could not read clock-frequency property.\n"); +- clk_disable_unprepare(priv->clk); +- return ret; +- } +- +- clk_divisor = clk_get_rate(priv->clk) / clk_freq; +- +- while ((clk_divisor >> 1) && (clk_div_val < PECI_CLK_DIV_MAX)) +- clk_div_val++; +- +- ret = of_property_read_u32(priv->dev->of_node, "msg-timing", +- &msg_timing); +- if (ret || msg_timing > PECI_MSG_TIMING_MAX) { +- if (!ret) +- dev_warn(priv->dev, +- "Invalid msg-timing : %u, Use default : %u\n", +- msg_timing, PECI_MSG_TIMING_DEFAULT); +- msg_timing = PECI_MSG_TIMING_DEFAULT; +- } +- +- ret = of_property_read_u32(priv->dev->of_node, "addr-timing", +- &addr_timing); +- if (ret || addr_timing > PECI_ADDR_TIMING_MAX) { +- if (!ret) +- dev_warn(priv->dev, +- "Invalid addr-timing : %u, Use default : %u\n", +- addr_timing, PECI_ADDR_TIMING_DEFAULT); +- addr_timing = PECI_ADDR_TIMING_DEFAULT; +- } +- +- ret = of_property_read_u32(priv->dev->of_node, "rd-sampling-point", +- &rd_sampling_point); +- if (ret || rd_sampling_point > PECI_RD_SAMPLING_POINT_MAX) { +- if (!ret) +- dev_warn(priv->dev, +- "Invalid rd-sampling-point : %u. Use default : %u\n", +- rd_sampling_point, +- PECI_RD_SAMPLING_POINT_DEFAULT); +- rd_sampling_point = PECI_RD_SAMPLING_POINT_DEFAULT; +- } +- +- ret = of_property_read_u32(priv->dev->of_node, "cmd-timeout-ms", +- &priv->cmd_timeout_ms); +- if (ret || priv->cmd_timeout_ms > PECI_CMD_TIMEOUT_MS_MAX || +- priv->cmd_timeout_ms == 0) { +- if (!ret) +- dev_warn(priv->dev, +- "Invalid cmd-timeout-ms : %u. Use default : %u\n", +- priv->cmd_timeout_ms, +- PECI_CMD_TIMEOUT_MS_DEFAULT); +- priv->cmd_timeout_ms = PECI_CMD_TIMEOUT_MS_DEFAULT; +- } +- +- regmap_write(priv->regmap, ASPEED_PECI_CTRL, +- FIELD_PREP(PECI_CTRL_CLK_DIV_MASK, PECI_CLK_DIV_DEFAULT) | +- PECI_CTRL_PECI_CLK_EN); +- +- /** +- * Timing negotiation period setting. +- * The unit of the programmed value is 4 times of PECI clock period. +- */ +- regmap_write(priv->regmap, ASPEED_PECI_TIMING, +- FIELD_PREP(PECI_TIMING_MESSAGE_MASK, msg_timing) | +- FIELD_PREP(PECI_TIMING_ADDRESS_MASK, addr_timing)); +- +- /* Clear interrupts */ +- regmap_write(priv->regmap, ASPEED_PECI_INT_STS, PECI_INT_MASK); +- +- /* Enable interrupts */ +- regmap_write(priv->regmap, ASPEED_PECI_INT_CTRL, PECI_INT_MASK); +- +- /* Read sampling point and clock speed setting */ +- regmap_write(priv->regmap, ASPEED_PECI_CTRL, +- FIELD_PREP(PECI_CTRL_SAMPLING_MASK, rd_sampling_point) | +- FIELD_PREP(PECI_CTRL_CLK_DIV_MASK, clk_div_val) | +- PECI_CTRL_PECI_EN | PECI_CTRL_PECI_CLK_EN); +- +- return 0; +-} +- +-static const struct regmap_config aspeed_peci_regmap_config = { +- .reg_bits = 32, +- .val_bits = 32, +- .reg_stride = 4, +- .max_register = ASPEED_PECI_R_DATA7, +- .val_format_endian = REGMAP_ENDIAN_LITTLE, +- .fast_io = true, +-}; +- +-static int aspeed_peci_xfer(struct peci_adapter *adapter, +- struct peci_xfer_msg *msg) +-{ +- struct aspeed_peci *priv = peci_get_adapdata(adapter); +- +- return aspeed_peci_xfer_native(priv, msg); +-} +- +-static int aspeed_peci_probe(struct platform_device *pdev) +-{ +- struct peci_adapter *adapter; +- struct aspeed_peci *priv; +- struct resource *res; +- void __iomem *base; +- u32 cmd_sts; +- int ret; +- +- adapter = peci_alloc_adapter(&pdev->dev, sizeof(*priv)); +- if (!adapter) +- return -ENOMEM; +- +- priv = peci_get_adapdata(adapter); +- priv->adapter = adapter; +- priv->dev = &pdev->dev; +- dev_set_drvdata(&pdev->dev, priv); +- +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- base = devm_ioremap_resource(&pdev->dev, res); +- if (IS_ERR(base)) { +- ret = PTR_ERR(base); +- goto err_put_adapter_dev; +- } +- +- priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, +- &aspeed_peci_regmap_config); +- if (IS_ERR(priv->regmap)) { +- ret = PTR_ERR(priv->regmap); +- goto err_put_adapter_dev; +- } +- +- /** +- * We check that the regmap works on this very first access, +- * but as this is an MMIO-backed regmap, subsequent regmap +- * access is not going to fail and we skip error checks from +- * this point. +- */ +- ret = regmap_read(priv->regmap, ASPEED_PECI_CMD, &cmd_sts); +- if (ret) { +- ret = -EIO; +- goto err_put_adapter_dev; +- } +- +- priv->irq = platform_get_irq(pdev, 0); +- if (!priv->irq) { +- ret = -ENODEV; +- goto err_put_adapter_dev; +- } +- +- ret = devm_request_irq(&pdev->dev, priv->irq, aspeed_peci_irq_handler, +- 0, "peci-aspeed-irq", priv); +- if (ret) +- goto err_put_adapter_dev; +- +- init_completion(&priv->xfer_complete); +- spin_lock_init(&priv->lock); +- +- priv->adapter->owner = THIS_MODULE; +- priv->adapter->dev.of_node = of_node_get(dev_of_node(priv->dev)); +- strlcpy(priv->adapter->name, pdev->name, sizeof(priv->adapter->name)); +- priv->adapter->xfer = aspeed_peci_xfer; +- +- priv->rst = devm_reset_control_get(&pdev->dev, NULL); +- if (IS_ERR(priv->rst)) { +- dev_err(&pdev->dev, +- "missing or invalid reset controller entry"); +- ret = PTR_ERR(priv->rst); +- goto err_put_adapter_dev; +- } +- reset_control_deassert(priv->rst); +- +- ret = aspeed_peci_init_ctrl(priv); +- if (ret) +- goto err_put_adapter_dev; +- +- ret = peci_add_adapter(priv->adapter); +- if (ret) +- goto err_put_adapter_dev; +- +- dev_info(&pdev->dev, "peci bus %d registered, irq %d\n", +- priv->adapter->nr, priv->irq); +- +- return 0; +- +-err_put_adapter_dev: +- put_device(&adapter->dev); +- return ret; +-} +- +-static int aspeed_peci_remove(struct platform_device *pdev) +-{ +- struct aspeed_peci *priv = dev_get_drvdata(&pdev->dev); +- +- clk_disable_unprepare(priv->clk); +- reset_control_assert(priv->rst); +- peci_del_adapter(priv->adapter); +- of_node_put(priv->adapter->dev.of_node); +- +- return 0; +-} +- +-static const struct of_device_id aspeed_peci_of_table[] = { +- { .compatible = "aspeed,ast2400-peci", }, +- { .compatible = "aspeed,ast2500-peci", }, +- { } +-}; +-MODULE_DEVICE_TABLE(of, aspeed_peci_of_table); +- +-static struct platform_driver aspeed_peci_driver = { +- .probe = aspeed_peci_probe, +- .remove = aspeed_peci_remove, +- .driver = { +- .name = "peci-aspeed", +- .of_match_table = of_match_ptr(aspeed_peci_of_table), +- }, +-}; +-module_platform_driver(aspeed_peci_driver); +- +-MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>"); +-MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>"); +-MODULE_DESCRIPTION("ASPEED PECI driver"); +-MODULE_LICENSE("GPL v2"); diff --git a/drivers/peci/peci-core.c b/drivers/peci/peci-core.c -index fac8c72dcda8..7ae05ded94bf 100644 +index fac8c72dcda8..3ebdb46613b9 100644 --- a/drivers/peci/peci-core.c +++ b/drivers/peci/peci-core.c -@@ -1,5 +1,5 @@ +@@ -1,38 +1,31 @@ // SPDX-License-Identifier: GPL-2.0 -// Copyright (c) 2018 Intel Corporation +// Copyright (c) 2018-2019 Intel Corporation #include <linux/bitfield.h> #include <linux/crc8.h> -@@ -666,9 +666,9 @@ peci_of_match_device(const struct of_device_id *matches, + #include <linux/delay.h> +-#include <linux/fs.h> ++#include <linux/mm.h> + #include <linux/module.h> + #include <linux/of_device.h> + #include <linux/peci.h> + #include <linux/pm_domain.h> + #include <linux/pm_runtime.h> ++#include <linux/sched/task_stack.h> + #include <linux/slab.h> +-#include <linux/uaccess.h> + + /* Mask for getting minor revision number from DIB */ + #define REVISION_NUM_MASK GENMASK(15, 8) + +-/* CRC8 table for Assure Write Frame Check */ ++/* CRC8 table for Assured Write Frame Check */ + #define PECI_CRC8_POLYNOMIAL 0x07 + DECLARE_CRC8_TABLE(peci_crc8_table); + +-static struct device_type peci_adapter_type; +-static struct device_type peci_client_type; +- +-/* Max number of peci cdev */ +-#define PECI_CDEV_MAX 16 +- +-static dev_t peci_devt; + static bool is_registered; + + static DEFINE_MUTEX(core_lock); + static DEFINE_IDR(peci_adapter_idr); + +-static struct peci_adapter *peci_get_adapter(int nr) ++struct peci_adapter *peci_get_adapter(int nr) + { + struct peci_adapter *adapter; + +@@ -48,10 +41,12 @@ static struct peci_adapter *peci_get_adapter(int nr) + + out_unlock: + mutex_unlock(&core_lock); ++ + return adapter; + } ++EXPORT_SYMBOL_GPL(peci_get_adapter); + +-static void peci_put_adapter(struct peci_adapter *adapter) ++void peci_put_adapter(struct peci_adapter *adapter) + { + if (!adapter) + return; +@@ -59,6 +54,7 @@ static void peci_put_adapter(struct peci_adapter *adapter) + put_device(&adapter->dev); + module_put(adapter->owner); + } ++EXPORT_SYMBOL_GPL(peci_put_adapter); + + static ssize_t name_show(struct device *dev, + struct device_attribute *attr, +@@ -84,10 +80,11 @@ static struct attribute *peci_device_attrs[] = { + }; + ATTRIBUTE_GROUPS(peci_device); + +-static struct device_type peci_client_type = { ++struct device_type peci_client_type = { + .groups = peci_device_groups, + .release = peci_client_dev_release, + }; ++EXPORT_SYMBOL_GPL(peci_client_type); + + /** + * peci_verify_client - return parameter as peci_client, or NULL +@@ -103,19 +100,120 @@ struct peci_client *peci_verify_client(struct device *dev) + } + EXPORT_SYMBOL_GPL(peci_verify_client); + +-static u8 peci_aw_fcs(u8 *data, int len) ++/** ++ * peci_get_xfer_msg() - get a DMA safe peci_xfer_msg for the given tx and rx ++ * length ++ * @tx_len: the length of tx_buf. May be 0 if tx_buf isn't needed. ++ * @rx_len: the length of rx_buf. May be 0 if rx_buf isn't needed. ++ * ++ * Return: NULL if a DMA safe buffer was not obtained. ++ * Or a valid pointer to be used with DMA. After use, release it by ++ * calling peci_put_xfer_msg(). ++ * ++ * This function must only be called from process context! ++ */ ++struct peci_xfer_msg *peci_get_xfer_msg(u8 tx_len, u8 rx_len) ++{ ++ struct peci_xfer_msg *msg; ++ u8 *tx_buf, *rx_buf; ++ ++ if (tx_len) { ++ tx_buf = kzalloc(tx_len, GFP_KERNEL); ++ if (!tx_buf) ++ return NULL; ++ } else { ++ tx_buf = NULL; ++ } ++ ++ if (rx_len) { ++ rx_buf = kzalloc(rx_len, GFP_KERNEL); ++ if (!rx_buf) ++ goto err_free_tx_buf; ++ } else { ++ rx_buf = NULL; ++ } ++ ++ msg = kzalloc(sizeof(struct peci_xfer_msg), GFP_KERNEL); ++ if (!msg) ++ goto err_free_tx_rx_buf; ++ ++ msg->tx_len = tx_len; ++ msg->tx_buf = tx_buf; ++ msg->rx_len = rx_len; ++ msg->rx_buf = rx_buf; ++ ++ return msg; ++ ++err_free_tx_rx_buf: ++ kfree(rx_buf); ++err_free_tx_buf: ++ kfree(tx_buf); ++ ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(peci_get_xfer_msg); ++ ++/** ++ * peci_put_xfer_msg - release a DMA safe peci_xfer_msg ++ * @msg: the message obtained from peci_get_xfer_msg(). May be NULL. ++ */ ++void peci_put_xfer_msg(struct peci_xfer_msg *msg) ++{ ++ if (!msg) ++ return; ++ ++ kfree(msg->rx_buf); ++ kfree(msg->tx_buf); ++ kfree(msg); ++} ++EXPORT_SYMBOL_GPL(peci_put_xfer_msg); ++ ++/* Calculate an Assured Write Frame Check Sequence byte */ ++static int peci_aw_fcs(struct peci_xfer_msg *msg, int len, u8 *aw_fcs) + { +- return crc8(peci_crc8_table, data, (size_t)len, 0); ++ u8 *tmp_buf; ++ ++ /* Allocate a temporary buffer to use a contiguous byte array */ ++ tmp_buf = kmalloc(len, GFP_KERNEL); ++ if (!tmp_buf) ++ return -ENOMEM; ++ ++ tmp_buf[0] = msg->addr; ++ tmp_buf[1] = msg->tx_len; ++ tmp_buf[2] = msg->rx_len; ++ memcpy(&tmp_buf[2], &msg->tx_buf[0], len - 3); ++ ++ *aw_fcs = crc8(peci_crc8_table, tmp_buf, (size_t)len, 0); ++ ++ kfree(tmp_buf); ++ ++ return 0; + } + + static int __peci_xfer(struct peci_adapter *adapter, struct peci_xfer_msg *msg, + bool do_retry, bool has_aw_fcs) + { +- ktime_t start, end; +- s64 elapsed_ms; +- int rc = 0; ++ ulong timeout = jiffies; ++ u8 aw_fcs; ++ int ret; + +- /** ++ /* ++ * In case if adapter uses DMA, check at here whether tx and rx buffers ++ * are DMA capable or not. ++ */ ++ if (IS_ENABLED(CONFIG_HAS_DMA) && adapter->use_dma) { ++ if (is_vmalloc_addr(msg->tx_buf) || ++ is_vmalloc_addr(msg->rx_buf)) { ++ WARN_ONCE(1, "xfer msg is not dma capable\n"); ++ return -EAGAIN; ++ } else if (object_is_on_stack(msg->tx_buf) || ++ object_is_on_stack(msg->rx_buf)) { ++ WARN_ONCE(1, "xfer msg is on stack\n"); ++ return -EAGAIN; ++ } ++ } ++ ++ /* + * For some commands, the PECI originator may need to retry a command if + * the processor PECI client responds with a 0x8x completion code. In + * each instance, the processor PECI client may have started the +@@ -125,55 +223,56 @@ static int __peci_xfer(struct peci_adapter *adapter, struct peci_xfer_msg *msg, + */ + + if (do_retry) +- start = ktime_get(); ++ timeout += msecs_to_jiffies(PECI_DEV_RETRY_TIME_MS); + +- do { +- rc = adapter->xfer(adapter, msg); ++ for (;;) { ++ ret = adapter->xfer(adapter, msg); + +- if (!do_retry || rc) ++ if (!do_retry || ret) + break; + +- if (msg->rx_buf[0] == DEV_PECI_CC_SUCCESS) ++ if (msg->rx_buf[0] == PECI_DEV_CC_SUCCESS) + break; + + /* Retry is needed when completion code is 0x8x */ +- if ((msg->rx_buf[0] & DEV_PECI_CC_RETRY_CHECK_MASK) != +- DEV_PECI_CC_NEED_RETRY) { +- rc = -EIO; ++ if ((msg->rx_buf[0] & PECI_DEV_CC_RETRY_CHECK_MASK) != ++ PECI_DEV_CC_NEED_RETRY) { ++ ret = -EIO; + break; + } + + /* Set the retry bit to indicate a retry attempt */ +- msg->tx_buf[1] |= DEV_PECI_RETRY_BIT; ++ msg->tx_buf[1] |= PECI_DEV_RETRY_BIT; + + /* Recalculate the AW FCS if it has one */ +- if (has_aw_fcs) +- msg->tx_buf[msg->tx_len - 1] = 0x80 ^ +- peci_aw_fcs((u8 *)msg, +- 2 + msg->tx_len); ++ if (has_aw_fcs) { ++ ret = peci_aw_fcs(msg, 2 + msg->tx_len, &aw_fcs); ++ if (ret) ++ break; + +- /** ++ msg->tx_buf[msg->tx_len - 1] = 0x80 ^ aw_fcs; ++ } ++ ++ /* + * Retry for at least 250ms before returning an error. + * Retry interval guideline: + * No minimum < Retry Interval < No maximum + * (recommend 10ms) + */ +- end = ktime_get(); +- elapsed_ms = ktime_to_ms(ktime_sub(end, start)); +- if (elapsed_ms >= DEV_PECI_RETRY_TIME_MS) { ++ if (time_after(jiffies, timeout)) { + dev_dbg(&adapter->dev, "Timeout retrying xfer!\n"); +- rc = -ETIMEDOUT; ++ ret = -ETIMEDOUT; + break; + } + +- usleep_range((DEV_PECI_RETRY_INTERVAL_USEC >> 2) + 1, +- DEV_PECI_RETRY_INTERVAL_USEC); +- } while (true); ++ usleep_range((PECI_DEV_RETRY_INTERVAL_USEC >> 2) + 1, ++ PECI_DEV_RETRY_INTERVAL_USEC); ++ } + +- if (rc) +- dev_dbg(&adapter->dev, "xfer error, rc: %d\n", rc); ++ if (ret) ++ dev_dbg(&adapter->dev, "xfer error: %d\n", ret); + +- return rc; ++ return ret; + } + + static int peci_xfer(struct peci_adapter *adapter, struct peci_xfer_msg *msg) +@@ -190,34 +289,37 @@ static int peci_xfer_with_retries(struct peci_adapter *adapter, + + static int peci_scan_cmd_mask(struct peci_adapter *adapter) + { +- struct peci_xfer_msg msg; ++ struct peci_xfer_msg *msg; + u8 revision; +- int rc = 0; ++ int ret; + u64 dib; + + /* Update command mask just once */ + if (adapter->cmd_mask & BIT(PECI_CMD_XFER)) + return 0; + +- msg.addr = PECI_BASE_ADDR; +- msg.tx_len = GET_DIB_WR_LEN; +- msg.rx_len = GET_DIB_RD_LEN; +- msg.tx_buf[0] = GET_DIB_PECI_CMD; ++ msg = peci_get_xfer_msg(PECI_GET_DIB_WR_LEN, PECI_GET_DIB_RD_LEN); ++ if (!msg) ++ return -ENOMEM; ++ ++ msg->addr = PECI_BASE_ADDR; ++ msg->tx_buf[0] = PECI_GET_DIB_CMD; + +- rc = peci_xfer(adapter, &msg); +- if (rc) +- return rc; ++ ret = peci_xfer(adapter, msg); ++ if (ret) ++ return ret; + +- dib = le64_to_cpup((__le64 *)msg.rx_buf); ++ dib = le64_to_cpup((__le64 *)msg->rx_buf); + + /* Check special case for Get DIB command */ + if (dib == 0) { + dev_dbg(&adapter->dev, "DIB read as 0\n"); +- return -EIO; ++ ret = -EIO; ++ goto out; + } + + /** +- * Setting up the supporting commands based on minor revision number. ++ * Setting up the supporting commands based on revision number. + * See PECI Spec Table 3-1. + */ + revision = FIELD_GET(REVISION_NUM_MASK, dib); +@@ -243,10 +345,14 @@ static int peci_scan_cmd_mask(struct peci_adapter *adapter) + adapter->cmd_mask |= BIT(PECI_CMD_GET_DIB); + adapter->cmd_mask |= BIT(PECI_CMD_PING); + +- return rc; ++out: ++ peci_put_xfer_msg(msg); ++ ++ return ret; + } + +-static int peci_cmd_support(struct peci_adapter *adapter, enum peci_cmd cmd) ++static int peci_check_cmd_support(struct peci_adapter *adapter, ++ enum peci_cmd cmd) + { + if (!(adapter->cmd_mask & BIT(PECI_CMD_PING)) && + peci_scan_cmd_mask(adapter) < 0) { +@@ -262,70 +368,87 @@ static int peci_cmd_support(struct peci_adapter *adapter, enum peci_cmd cmd) + return 0; + } + +-static int peci_ioctl_xfer(struct peci_adapter *adapter, void *vmsg) ++static int peci_cmd_xfer(struct peci_adapter *adapter, void *vmsg) + { + struct peci_xfer_msg *msg = vmsg; + + return peci_xfer(adapter, msg); + } + +-static int peci_ioctl_ping(struct peci_adapter *adapter, void *vmsg) ++static int peci_cmd_ping(struct peci_adapter *adapter, void *vmsg) + { + struct peci_ping_msg *umsg = vmsg; +- struct peci_xfer_msg msg; ++ struct peci_xfer_msg *msg; ++ int ret; + +- msg.addr = umsg->addr; +- msg.tx_len = 0; +- msg.rx_len = 0; ++ msg = peci_get_xfer_msg(0, 0); ++ if (!msg) ++ return -ENOMEM; + +- return peci_xfer(adapter, &msg); ++ msg->addr = umsg->addr; ++ ++ ret = peci_xfer(adapter, msg); ++ ++ peci_put_xfer_msg(msg); ++ ++ return ret; + } + +-static int peci_ioctl_get_dib(struct peci_adapter *adapter, void *vmsg) ++static int peci_cmd_get_dib(struct peci_adapter *adapter, void *vmsg) + { + struct peci_get_dib_msg *umsg = vmsg; +- struct peci_xfer_msg msg; +- int rc; ++ struct peci_xfer_msg *msg; ++ int ret; + +- msg.addr = umsg->addr; +- msg.tx_len = GET_DIB_WR_LEN; +- msg.rx_len = GET_DIB_RD_LEN; +- msg.tx_buf[0] = GET_DIB_PECI_CMD; ++ msg = peci_get_xfer_msg(PECI_GET_DIB_WR_LEN, PECI_GET_DIB_RD_LEN); ++ if (!msg) ++ return -ENOMEM; + +- rc = peci_xfer(adapter, &msg); +- if (rc) +- return rc; ++ msg->addr = umsg->addr; ++ msg->tx_buf[0] = PECI_GET_DIB_CMD; + +- umsg->dib = le64_to_cpup((__le64 *)msg.rx_buf); ++ ret = peci_xfer(adapter, msg); ++ if (ret) ++ goto out; + +- return 0; ++ umsg->dib = le64_to_cpup((__le64 *)msg->rx_buf); ++ ++out: ++ peci_put_xfer_msg(msg); ++ ++ return ret; + } + +-static int peci_ioctl_get_temp(struct peci_adapter *adapter, void *vmsg) ++static int peci_cmd_get_temp(struct peci_adapter *adapter, void *vmsg) + { + struct peci_get_temp_msg *umsg = vmsg; +- struct peci_xfer_msg msg; +- int rc; ++ struct peci_xfer_msg *msg; ++ int ret; + +- msg.addr = umsg->addr; +- msg.tx_len = GET_TEMP_WR_LEN; +- msg.rx_len = GET_TEMP_RD_LEN; +- msg.tx_buf[0] = GET_TEMP_PECI_CMD; ++ msg = peci_get_xfer_msg(PECI_GET_TEMP_WR_LEN, PECI_GET_TEMP_RD_LEN); ++ if (!msg) ++ return -ENOMEM; + +- rc = peci_xfer(adapter, &msg); +- if (rc) +- return rc; ++ msg->addr = umsg->addr; ++ msg->tx_buf[0] = PECI_GET_TEMP_CMD; + +- umsg->temp_raw = le16_to_cpup((__le16 *)msg.rx_buf); ++ ret = peci_xfer(adapter, msg); ++ if (ret) ++ goto out; + +- return 0; ++ umsg->temp_raw = le16_to_cpup((__le16 *)msg->rx_buf); ++ ++out: ++ peci_put_xfer_msg(msg); ++ ++ return ret; + } + +-static int peci_ioctl_rd_pkg_cfg(struct peci_adapter *adapter, void *vmsg) ++static int peci_cmd_rd_pkg_cfg(struct peci_adapter *adapter, void *vmsg) + { + struct peci_rd_pkg_cfg_msg *umsg = vmsg; +- struct peci_xfer_msg msg; +- int rc = 0; ++ struct peci_xfer_msg *msg; ++ int ret; + + /* Per the PECI spec, the read length must be a byte, word, or dword */ + if (umsg->rx_len != 1 && umsg->rx_len != 2 && umsg->rx_len != 4) { +@@ -334,29 +457,34 @@ static int peci_ioctl_rd_pkg_cfg(struct peci_adapter *adapter, void *vmsg) + return -EINVAL; + } + +- msg.addr = umsg->addr; +- msg.tx_len = RDPKGCFG_WRITE_LEN; +- /* read lengths of 1 and 2 result in an error, so only use 4 for now */ +- msg.rx_len = RDPKGCFG_READ_LEN_BASE + umsg->rx_len; +- msg.tx_buf[0] = RDPKGCFG_PECI_CMD; +- msg.tx_buf[1] = 0; /* request byte for Host ID | Retry bit */ +- /* Host ID is 0 for PECI 3.0 */ +- msg.tx_buf[2] = umsg->index; /* RdPkgConfig index */ +- msg.tx_buf[3] = (u8)umsg->param; /* LSB - Config parameter */ +- msg.tx_buf[4] = (u8)(umsg->param >> 8); /* MSB - Config parameter */ ++ msg = peci_get_xfer_msg(PECI_RDPKGCFG_WRITE_LEN, ++ PECI_RDPKGCFG_READ_LEN_BASE + umsg->rx_len); ++ if (!msg) ++ return -ENOMEM; ++ ++ msg->addr = umsg->addr; ++ msg->tx_buf[0] = PECI_RDPKGCFG_CMD; ++ msg->tx_buf[1] = 0; /* request byte for Host ID | Retry bit */ ++ /* Host ID is 0 for PECI 3.0 */ ++ msg->tx_buf[2] = umsg->index; /* RdPkgConfig index */ ++ msg->tx_buf[3] = (u8)umsg->param; /* LSB - Config parameter */ ++ msg->tx_buf[4] = (u8)(umsg->param >> 8); /* MSB - Config parameter */ ++ ++ ret = peci_xfer_with_retries(adapter, msg, false); ++ if (!ret) ++ memcpy(umsg->pkg_config, &msg->rx_buf[1], umsg->rx_len); + +- rc = peci_xfer_with_retries(adapter, &msg, false); +- if (!rc) +- memcpy(umsg->pkg_config, &msg.rx_buf[1], umsg->rx_len); ++ peci_put_xfer_msg(msg); + +- return rc; ++ return ret; + } + +-static int peci_ioctl_wr_pkg_cfg(struct peci_adapter *adapter, void *vmsg) ++static int peci_cmd_wr_pkg_cfg(struct peci_adapter *adapter, void *vmsg) + { + struct peci_wr_pkg_cfg_msg *umsg = vmsg; +- struct peci_xfer_msg msg; +- int rc = 0, i; ++ struct peci_xfer_msg *msg; ++ int ret, i; ++ u8 aw_fcs; + + /* Per the PECI spec, the write length must be a dword */ + if (umsg->tx_len != 4) { +@@ -365,86 +493,113 @@ static int peci_ioctl_wr_pkg_cfg(struct peci_adapter *adapter, void *vmsg) + return -EINVAL; + } + +- msg.addr = umsg->addr; +- msg.tx_len = WRPKGCFG_WRITE_LEN_BASE + umsg->tx_len; +- /* read lengths of 1 and 2 result in an error, so only use 4 for now */ +- msg.rx_len = WRPKGCFG_READ_LEN; +- msg.tx_buf[0] = WRPKGCFG_PECI_CMD; +- msg.tx_buf[1] = 0; /* request byte for Host ID | Retry bit */ ++ msg = peci_get_xfer_msg(PECI_WRPKGCFG_WRITE_LEN_BASE + umsg->tx_len, ++ PECI_WRPKGCFG_READ_LEN); ++ if (!msg) ++ return -ENOMEM; ++ ++ msg->addr = umsg->addr; ++ msg->tx_buf[0] = PECI_WRPKGCFG_CMD; ++ msg->tx_buf[1] = 0; /* request byte for Host ID | Retry bit */ + /* Host ID is 0 for PECI 3.0 */ +- msg.tx_buf[2] = umsg->index; /* RdPkgConfig index */ +- msg.tx_buf[3] = (u8)umsg->param; /* LSB - Config parameter */ +- msg.tx_buf[4] = (u8)(umsg->param >> 8); /* MSB - Config parameter */ ++ msg->tx_buf[2] = umsg->index; /* RdPkgConfig index */ ++ msg->tx_buf[3] = (u8)umsg->param; /* LSB - Config parameter */ ++ msg->tx_buf[4] = (u8)(umsg->param >> 8); /* MSB - Config parameter */ + for (i = 0; i < umsg->tx_len; i++) +- msg.tx_buf[5 + i] = (u8)(umsg->value >> (i << 3)); ++ msg->tx_buf[5 + i] = (u8)(umsg->value >> (i << 3)); ++ ++ /* Add an Assured Write Frame Check Sequence byte */ ++ ret = peci_aw_fcs(msg, 8 + umsg->tx_len, &aw_fcs); ++ if (ret) ++ goto out; ++ ++ msg->tx_buf[5 + i] = 0x80 ^ aw_fcs; + +- /* Add an Assure Write Frame Check Sequence byte */ +- msg.tx_buf[5 + i] = 0x80 ^ +- peci_aw_fcs((u8 *)&msg, 8 + umsg->tx_len); ++ ret = peci_xfer_with_retries(adapter, msg, true); + +- rc = peci_xfer_with_retries(adapter, &msg, true); ++out: ++ peci_put_xfer_msg(msg); + +- return rc; ++ return ret; + } + +-static int peci_ioctl_rd_ia_msr(struct peci_adapter *adapter, void *vmsg) ++static int peci_cmd_rd_ia_msr(struct peci_adapter *adapter, void *vmsg) + { + struct peci_rd_ia_msr_msg *umsg = vmsg; +- struct peci_xfer_msg msg; +- int rc = 0; +- +- msg.addr = umsg->addr; +- msg.tx_len = RDIAMSR_WRITE_LEN; +- msg.rx_len = RDIAMSR_READ_LEN; +- msg.tx_buf[0] = RDIAMSR_PECI_CMD; +- msg.tx_buf[1] = 0; +- msg.tx_buf[2] = umsg->thread_id; +- msg.tx_buf[3] = (u8)umsg->address; +- msg.tx_buf[4] = (u8)(umsg->address >> 8); +- +- rc = peci_xfer_with_retries(adapter, &msg, false); +- if (!rc) +- memcpy(&umsg->value, &msg.rx_buf[1], sizeof(uint64_t)); +- +- return rc; ++ struct peci_xfer_msg *msg; ++ int ret; ++ ++ msg = peci_get_xfer_msg(PECI_RDIAMSR_WRITE_LEN, PECI_RDIAMSR_READ_LEN); ++ if (!msg) ++ return -ENOMEM; ++ ++ msg->addr = umsg->addr; ++ msg->tx_buf[0] = PECI_RDIAMSR_CMD; ++ msg->tx_buf[1] = 0; ++ msg->tx_buf[2] = umsg->thread_id; ++ msg->tx_buf[3] = (u8)umsg->address; ++ msg->tx_buf[4] = (u8)(umsg->address >> 8); ++ ++ ret = peci_xfer_with_retries(adapter, msg, false); ++ if (!ret) ++ memcpy(&umsg->value, &msg->rx_buf[1], sizeof(uint64_t)); ++ ++ peci_put_xfer_msg(msg); ++ ++ return ret; ++} ++ ++static int peci_cmd_wr_ia_msr(struct peci_adapter *adapter, void *vmsg) ++{ ++ return -ENOSYS; /* Not implemented yet */ + } + +-static int peci_ioctl_rd_pci_cfg(struct peci_adapter *adapter, void *vmsg) ++static int peci_cmd_rd_pci_cfg(struct peci_adapter *adapter, void *vmsg) + { + struct peci_rd_pci_cfg_msg *umsg = vmsg; +- struct peci_xfer_msg msg; ++ struct peci_xfer_msg *msg; + u32 address; +- int rc = 0; ++ int ret; ++ ++ msg = peci_get_xfer_msg(PECI_RDPCICFG_WRITE_LEN, ++ PECI_RDPCICFG_READ_LEN); ++ if (!msg) ++ return -ENOMEM; + + address = umsg->reg; /* [11:0] - Register */ + address |= (u32)umsg->function << 12; /* [14:12] - Function */ + address |= (u32)umsg->device << 15; /* [19:15] - Device */ + address |= (u32)umsg->bus << 20; /* [27:20] - Bus */ + /* [31:28] - Reserved */ +- msg.addr = umsg->addr; +- msg.tx_len = RDPCICFG_WRITE_LEN; +- msg.rx_len = RDPCICFG_READ_LEN; +- msg.tx_buf[0] = RDPCICFG_PECI_CMD; +- msg.tx_buf[1] = 0; /* request byte for Host ID | Retry bit */ ++ msg->addr = umsg->addr; ++ msg->tx_buf[0] = PECI_RDPCICFG_CMD; ++ msg->tx_buf[1] = 0; /* request byte for Host ID | Retry bit */ + /* Host ID is 0 for PECI 3.0 */ +- msg.tx_buf[2] = (u8)address; /* LSB - PCI Config Address */ +- msg.tx_buf[3] = (u8)(address >> 8); /* PCI Config Address */ +- msg.tx_buf[4] = (u8)(address >> 16); /* PCI Config Address */ +- msg.tx_buf[5] = (u8)(address >> 24); /* MSB - PCI Config Address */ ++ msg->tx_buf[2] = (u8)address; /* LSB - PCI Config Address */ ++ msg->tx_buf[3] = (u8)(address >> 8); /* PCI Config Address */ ++ msg->tx_buf[4] = (u8)(address >> 16); /* PCI Config Address */ ++ msg->tx_buf[5] = (u8)(address >> 24); /* MSB - PCI Config Address */ ++ ++ ret = peci_xfer_with_retries(adapter, msg, false); ++ if (!ret) ++ memcpy(umsg->pci_config, &msg->rx_buf[1], 4); + +- rc = peci_xfer_with_retries(adapter, &msg, false); +- if (!rc) +- memcpy(umsg->pci_config, &msg.rx_buf[1], 4); ++ peci_put_xfer_msg(msg); + +- return rc; ++ return ret; + } + +-static int peci_ioctl_rd_pci_cfg_local(struct peci_adapter *adapter, void *vmsg) ++static int peci_cmd_wr_pci_cfg(struct peci_adapter *adapter, void *vmsg) ++{ ++ return -ENOSYS; /* Not implemented yet */ ++} ++ ++static int peci_cmd_rd_pci_cfg_local(struct peci_adapter *adapter, void *vmsg) + { + struct peci_rd_pci_cfg_local_msg *umsg = vmsg; +- struct peci_xfer_msg msg; ++ struct peci_xfer_msg *msg; + u32 address; +- int rc = 0; ++ int ret; + + /* Per the PECI spec, the read length must be a byte, word, or dword */ + if (umsg->rx_len != 1 && umsg->rx_len != 2 && umsg->rx_len != 4) { +@@ -453,34 +608,41 @@ static int peci_ioctl_rd_pci_cfg_local(struct peci_adapter *adapter, void *vmsg) + return -EINVAL; + } + ++ msg = peci_get_xfer_msg(PECI_RDPCICFGLOCAL_WRITE_LEN, ++ PECI_RDPCICFGLOCAL_READ_LEN_BASE + ++ umsg->rx_len); ++ if (!msg) ++ return -ENOMEM; ++ + address = umsg->reg; /* [11:0] - Register */ + address |= (u32)umsg->function << 12; /* [14:12] - Function */ + address |= (u32)umsg->device << 15; /* [19:15] - Device */ + address |= (u32)umsg->bus << 20; /* [23:20] - Bus */ + +- msg.addr = umsg->addr; +- msg.tx_len = RDPCICFGLOCAL_WRITE_LEN; +- msg.rx_len = RDPCICFGLOCAL_READ_LEN_BASE + umsg->rx_len; +- msg.tx_buf[0] = RDPCICFGLOCAL_PECI_CMD; +- msg.tx_buf[1] = 0; /* request byte for Host ID | Retry bit */ +- /* Host ID is 0 for PECI 3.0 */ +- msg.tx_buf[2] = (u8)address; /* LSB - PCI Configuration Address */ +- msg.tx_buf[3] = (u8)(address >> 8); /* PCI Configuration Address */ +- msg.tx_buf[4] = (u8)(address >> 16); /* PCI Configuration Address */ ++ msg->addr = umsg->addr; ++ msg->tx_buf[0] = PECI_RDPCICFGLOCAL_CMD; ++ msg->tx_buf[1] = 0; /* request byte for Host ID | Retry bit */ ++ /* Host ID is 0 for PECI 3.0 */ ++ msg->tx_buf[2] = (u8)address; /* LSB - PCI Configuration Address */ ++ msg->tx_buf[3] = (u8)(address >> 8); /* PCI Configuration Address */ ++ msg->tx_buf[4] = (u8)(address >> 16); /* PCI Configuration Address */ ++ ++ ret = peci_xfer_with_retries(adapter, msg, false); ++ if (!ret) ++ memcpy(umsg->pci_config, &msg->rx_buf[1], umsg->rx_len); + +- rc = peci_xfer_with_retries(adapter, &msg, false); +- if (!rc) +- memcpy(umsg->pci_config, &msg.rx_buf[1], umsg->rx_len); ++ peci_put_xfer_msg(msg); + +- return rc; ++ return ret; + } + +-static int peci_ioctl_wr_pci_cfg_local(struct peci_adapter *adapter, void *vmsg) ++static int peci_cmd_wr_pci_cfg_local(struct peci_adapter *adapter, void *vmsg) + { + struct peci_wr_pci_cfg_local_msg *umsg = vmsg; +- struct peci_xfer_msg msg; +- int rc = 0, i; ++ struct peci_xfer_msg *msg; + u32 address; ++ int ret, i; ++ u8 aw_fcs; + + /* Per the PECI spec, the write length must be a byte, word, or dword */ + if (umsg->tx_len != 1 && umsg->tx_len != 2 && umsg->tx_len != 4) { +@@ -489,47 +651,56 @@ static int peci_ioctl_wr_pci_cfg_local(struct peci_adapter *adapter, void *vmsg) + return -EINVAL; + } + ++ msg = peci_get_xfer_msg(PECI_WRPCICFGLOCAL_WRITE_LEN_BASE + ++ umsg->tx_len, PECI_WRPCICFGLOCAL_READ_LEN); ++ if (!msg) ++ return -ENOMEM; ++ + address = umsg->reg; /* [11:0] - Register */ + address |= (u32)umsg->function << 12; /* [14:12] - Function */ + address |= (u32)umsg->device << 15; /* [19:15] - Device */ + address |= (u32)umsg->bus << 20; /* [23:20] - Bus */ + +- msg.addr = umsg->addr; +- msg.tx_len = WRPCICFGLOCAL_WRITE_LEN_BASE + umsg->tx_len; +- msg.rx_len = WRPCICFGLOCAL_READ_LEN; +- msg.tx_buf[0] = WRPCICFGLOCAL_PECI_CMD; +- msg.tx_buf[1] = 0; /* request byte for Host ID | Retry bit */ +- /* Host ID is 0 for PECI 3.0 */ +- msg.tx_buf[2] = (u8)address; /* LSB - PCI Configuration Address */ +- msg.tx_buf[3] = (u8)(address >> 8); /* PCI Configuration Address */ +- msg.tx_buf[4] = (u8)(address >> 16); /* PCI Configuration Address */ ++ msg->addr = umsg->addr; ++ msg->tx_buf[0] = PECI_WRPCICFGLOCAL_CMD; ++ msg->tx_buf[1] = 0; /* request byte for Host ID | Retry bit */ ++ /* Host ID is 0 for PECI 3.0 */ ++ msg->tx_buf[2] = (u8)address; /* LSB - PCI Configuration Address */ ++ msg->tx_buf[3] = (u8)(address >> 8); /* PCI Configuration Address */ ++ msg->tx_buf[4] = (u8)(address >> 16); /* PCI Configuration Address */ + for (i = 0; i < umsg->tx_len; i++) +- msg.tx_buf[5 + i] = (u8)(umsg->value >> (i << 3)); ++ msg->tx_buf[5 + i] = (u8)(umsg->value >> (i << 3)); ++ ++ /* Add an Assured Write Frame Check Sequence byte */ ++ ret = peci_aw_fcs(msg, 8 + umsg->tx_len, &aw_fcs); ++ if (ret) ++ goto out; ++ ++ msg->tx_buf[5 + i] = 0x80 ^ aw_fcs; + +- /* Add an Assure Write Frame Check Sequence byte */ +- msg.tx_buf[5 + i] = 0x80 ^ +- peci_aw_fcs((u8 *)&msg, 8 + umsg->tx_len); ++ ret = peci_xfer_with_retries(adapter, msg, true); + +- rc = peci_xfer_with_retries(adapter, &msg, true); ++out: ++ peci_put_xfer_msg(msg); + +- return rc; ++ return ret; + } + +-typedef int (*peci_ioctl_fn_type)(struct peci_adapter *, void *); +- +-static const peci_ioctl_fn_type peci_ioctl_fn[PECI_CMD_MAX] = { +- peci_ioctl_xfer, +- peci_ioctl_ping, +- peci_ioctl_get_dib, +- peci_ioctl_get_temp, +- peci_ioctl_rd_pkg_cfg, +- peci_ioctl_wr_pkg_cfg, +- peci_ioctl_rd_ia_msr, +- NULL, /* Reserved */ +- peci_ioctl_rd_pci_cfg, +- NULL, /* Reserved */ +- peci_ioctl_rd_pci_cfg_local, +- peci_ioctl_wr_pci_cfg_local, ++typedef int (*peci_cmd_fn_type)(struct peci_adapter *, void *); ++ ++static const peci_cmd_fn_type peci_cmd_fn[PECI_CMD_MAX] = { ++ peci_cmd_xfer, ++ peci_cmd_ping, ++ peci_cmd_get_dib, ++ peci_cmd_get_temp, ++ peci_cmd_rd_pkg_cfg, ++ peci_cmd_wr_pkg_cfg, ++ peci_cmd_rd_ia_msr, ++ peci_cmd_wr_ia_msr, ++ peci_cmd_rd_pci_cfg, ++ peci_cmd_wr_pci_cfg, ++ peci_cmd_rd_pci_cfg_local, ++ peci_cmd_wr_pci_cfg_local, + }; + + /** +@@ -545,109 +716,28 @@ static const peci_ioctl_fn_type peci_ioctl_fn[PECI_CMD_MAX] = { + */ + int peci_command(struct peci_adapter *adapter, enum peci_cmd cmd, void *vmsg) + { +- int rc = 0; ++ int ret; + + if (cmd >= PECI_CMD_MAX || cmd < PECI_CMD_XFER) +- return -EINVAL; ++ return -ENOTTY; + + dev_dbg(&adapter->dev, "%s, cmd=0x%02x\n", __func__, cmd); + +- if (!peci_ioctl_fn[cmd]) ++ if (!peci_cmd_fn[cmd]) + return -EINVAL; + +- rt_mutex_lock(&adapter->bus_lock); ++ mutex_lock(&adapter->bus_lock); + +- rc = peci_cmd_support(adapter, cmd); +- if (!rc) +- rc = peci_ioctl_fn[cmd](adapter, vmsg); ++ ret = peci_check_cmd_support(adapter, cmd); ++ if (!ret) ++ ret = peci_cmd_fn[cmd](adapter, vmsg); + +- rt_mutex_unlock(&adapter->bus_lock); ++ mutex_unlock(&adapter->bus_lock); + +- return rc; ++ return ret; + } + EXPORT_SYMBOL_GPL(peci_command); + +-static long peci_ioctl(struct file *file, unsigned int iocmd, unsigned long arg) +-{ +- struct peci_adapter *adapter = file->private_data; +- void __user *argp = (void __user *)arg; +- unsigned int msg_len; +- enum peci_cmd cmd; +- int rc = 0; +- u8 *msg; +- +- if (!capable(CAP_SYS_ADMIN)) +- return -EPERM; +- +- dev_dbg(&adapter->dev, "ioctl, cmd=0x%x, arg=0x%lx\n", iocmd, arg); +- +- switch (iocmd) { +- case PECI_IOC_XFER: +- case PECI_IOC_PING: +- case PECI_IOC_GET_DIB: +- case PECI_IOC_GET_TEMP: +- case PECI_IOC_RD_PKG_CFG: +- case PECI_IOC_WR_PKG_CFG: +- case PECI_IOC_RD_IA_MSR: +- case PECI_IOC_RD_PCI_CFG: +- case PECI_IOC_RD_PCI_CFG_LOCAL: +- case PECI_IOC_WR_PCI_CFG_LOCAL: +- cmd = _IOC_NR(iocmd); +- msg_len = _IOC_SIZE(iocmd); +- break; +- +- default: +- dev_dbg(&adapter->dev, "Invalid ioctl cmd : 0x%x\n", iocmd); +- return -ENOTTY; +- } +- +- if (!access_ok(VERIFY_WRITE, argp, msg_len)) +- return -EFAULT; +- +- msg = memdup_user(argp, msg_len); +- if (IS_ERR(msg)) +- return PTR_ERR(msg); +- +- rc = peci_command(adapter, cmd, msg); +- +- if (!rc && copy_to_user(argp, msg, msg_len)) +- rc = -EFAULT; +- +- kfree(msg); +- return (long)rc; +-} +- +-static int peci_open(struct inode *inode, struct file *file) +-{ +- unsigned int minor = iminor(inode); +- struct peci_adapter *adapter; +- +- adapter = peci_get_adapter(minor); +- if (!adapter) +- return -ENODEV; +- +- file->private_data = adapter; +- +- return 0; +-} +- +-static int peci_release(struct inode *inode, struct file *file) +-{ +- struct peci_adapter *adapter = file->private_data; +- +- peci_put_adapter(adapter); +- file->private_data = NULL; +- +- return 0; +-} +- +-static const struct file_operations peci_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = peci_ioctl, +- .open = peci_open, +- .release = peci_release, +-}; +- + static int peci_detect(struct peci_adapter *adapter, u8 addr) + { + struct peci_ping_msg msg; +@@ -666,9 +756,9 @@ peci_of_match_device(const struct of_device_id *matches, return NULL; return of_match_device(matches, &client->dev); @@ -215,7 +2913,314 @@ index fac8c72dcda8..7ae05ded94bf 100644 } static const struct peci_device_id * -@@ -1119,7 +1119,7 @@ static void peci_of_register_devices(struct peci_adapter *adapter) +@@ -737,6 +827,7 @@ static int peci_device_probe(struct device *dev) + + err_detach_pm_domain: + dev_pm_domain_detach(&client->dev, true); ++ + return status; + } + +@@ -775,13 +866,14 @@ static void peci_device_shutdown(struct device *dev) + driver->shutdown(client); + } + +-static struct bus_type peci_bus_type = { ++struct bus_type peci_bus_type = { + .name = "peci", + .match = peci_device_match, + .probe = peci_device_probe, + .remove = peci_device_remove, + .shutdown = peci_device_shutdown, + }; ++EXPORT_SYMBOL_GPL(peci_bus_type); + + static int peci_check_addr_validity(u8 addr) + { +@@ -814,18 +906,18 @@ static int peci_check_client_busy(struct device *dev, void *client_new_p) + int peci_get_cpu_id(struct peci_adapter *adapter, u8 addr, u32 *cpu_id) + { + struct peci_rd_pkg_cfg_msg msg; +- int rc; ++ int ret; + + msg.addr = addr; +- msg.index = MBX_INDEX_CPU_ID; +- msg.param = PKG_ID_CPU_ID; ++ msg.index = PECI_MBX_INDEX_CPU_ID; ++ msg.param = PECI_PKG_ID_CPU_ID; + msg.rx_len = 4; + +- rc = peci_command(adapter, PECI_CMD_RD_PKG_CFG, &msg); +- if (!rc) ++ ret = peci_command(adapter, PECI_CMD_RD_PKG_CFG, &msg); ++ if (!ret) + *cpu_id = le32_to_cpup((__le32 *)msg.pkg_config); + +- return rc; ++ return ret; + } + EXPORT_SYMBOL_GPL(peci_get_cpu_id); + +@@ -833,7 +925,7 @@ static struct peci_client *peci_new_device(struct peci_adapter *adapter, + struct peci_board_info const *info) + { + struct peci_client *client; +- int rc; ++ int ret; + + /* Increase reference count for the adapter assigned */ + if (!peci_get_adapter(adapter->nr)) +@@ -847,46 +939,49 @@ static struct peci_client *peci_new_device(struct peci_adapter *adapter, + client->addr = info->addr; + strlcpy(client->name, info->type, sizeof(client->name)); + +- rc = peci_check_addr_validity(client->addr); +- if (rc) { ++ ret = peci_check_addr_validity(client->addr); ++ if (ret) { + dev_err(&adapter->dev, "Invalid PECI CPU address 0x%02hx\n", + client->addr); + goto err_free_client_silent; + } + + /* Check online status of client */ +- rc = peci_detect(adapter, client->addr); +- if (rc) ++ ret = peci_detect(adapter, client->addr); ++ if (ret) + goto err_free_client; + +- rc = device_for_each_child(&adapter->dev, client, +- peci_check_client_busy); +- if (rc) ++ ret = device_for_each_child(&adapter->dev, client, ++ peci_check_client_busy); ++ if (ret) + goto err_free_client; + + client->dev.parent = &client->adapter->dev; + client->dev.bus = &peci_bus_type; + client->dev.type = &peci_client_type; +- client->dev.of_node = info->of_node; ++ client->dev.of_node = of_node_get(info->of_node); + dev_set_name(&client->dev, "%d-%02x", adapter->nr, client->addr); + +- rc = device_register(&client->dev); +- if (rc) +- goto err_free_client; ++ ret = device_register(&client->dev); ++ if (ret) ++ goto err_put_of_node; + + dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n", + client->name, dev_name(&client->dev)); + + return client; + ++err_put_of_node: ++ of_node_put(info->of_node); + err_free_client: + dev_err(&adapter->dev, + "Failed to register peci client %s at 0x%02x (%d)\n", +- client->name, client->addr, rc); ++ client->name, client->addr, ret); + err_free_client_silent: + kfree(client); + err_put_adapter: + peci_put_adapter(adapter); ++ + return NULL; + } + +@@ -895,8 +990,10 @@ static void peci_unregister_device(struct peci_client *client) + if (!client) + return; + +- if (client->dev.of_node) ++ if (client->dev.of_node) { + of_node_clear_flag(client->dev.of_node, OF_POPULATED); ++ of_node_put(client->dev.of_node); ++ } + + device_unregister(&client->dev); + } +@@ -916,7 +1013,7 @@ static void peci_adapter_dev_release(struct device *dev) + + dev_dbg(dev, "%s: %s\n", __func__, adapter->name); + mutex_destroy(&adapter->userspace_clients_lock); +- rt_mutex_destroy(&adapter->bus_lock); ++ mutex_destroy(&adapter->bus_lock); + kfree(adapter); + } + +@@ -928,7 +1025,8 @@ static ssize_t peci_sysfs_new_device(struct device *dev, + struct peci_board_info info = {}; + struct peci_client *client; + char *blank, end; +- int rc; ++ short addr; ++ int ret; + + /* Parse device type */ + blank = strchr(buf, ' '); +@@ -943,16 +1041,17 @@ static ssize_t peci_sysfs_new_device(struct device *dev, + memcpy(info.type, buf, blank - buf); + + /* Parse remaining parameters, reject extra parameters */ +- rc = sscanf(++blank, "%hi%c", &info.addr, &end); +- if (rc < 1) { ++ ret = sscanf(++blank, "%hi%c", &addr, &end); ++ if (ret < 1) { + dev_err(dev, "%s: Can't parse client address\n", "new_device"); + return -EINVAL; + } +- if (rc > 1 && end != '\n') { ++ if (ret > 1 && end != '\n') { + dev_err(dev, "%s: Extra parameters\n", "new_device"); + return -EINVAL; + } + ++ info.addr = (u8)addr; + client = peci_new_device(adapter, &info); + if (!client) + return -EINVAL; +@@ -961,8 +1060,8 @@ static ssize_t peci_sysfs_new_device(struct device *dev, + mutex_lock(&adapter->userspace_clients_lock); + list_add_tail(&client->detected, &adapter->userspace_clients); + mutex_unlock(&adapter->userspace_clients_lock); +- dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device", +- info.type, info.addr); ++ dev_dbg(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device", ++ info.type, info.addr); + + return count; + } +@@ -975,9 +1074,9 @@ static ssize_t peci_sysfs_delete_device(struct device *dev, + struct peci_adapter *adapter = to_peci_adapter(dev); + struct peci_client *client, *next; + struct peci_board_info info = {}; +- struct peci_driver *driver; + char *blank, end; +- int rc; ++ short addr; ++ int ret; + + /* Parse device type */ + blank = strchr(buf, ' '); +@@ -992,41 +1091,41 @@ static ssize_t peci_sysfs_delete_device(struct device *dev, + memcpy(info.type, buf, blank - buf); + + /* Parse remaining parameters, reject extra parameters */ +- rc = sscanf(++blank, "%hi%c", &info.addr, &end); +- if (rc < 1) { ++ ret = sscanf(++blank, "%hi%c", &addr, &end); ++ if (ret < 1) { + dev_err(dev, "%s: Can't parse client address\n", + "delete_device"); + return -EINVAL; + } +- if (rc > 1 && end != '\n') { ++ if (ret > 1 && end != '\n') { + dev_err(dev, "%s: Extra parameters\n", "delete_device"); + return -EINVAL; + } + ++ info.addr = (u8)addr; ++ + /* Make sure the device was added through sysfs */ +- rc = -ENOENT; ++ ret = -ENOENT; + mutex_lock(&adapter->userspace_clients_lock); + list_for_each_entry_safe(client, next, &adapter->userspace_clients, + detected) { +- driver = to_peci_driver(client->dev.driver); +- + if (client->addr == info.addr && + !strncmp(client->name, info.type, PECI_NAME_SIZE)) { +- dev_info(dev, "%s: Deleting device %s at 0x%02hx\n", +- "delete_device", client->name, client->addr); ++ dev_dbg(dev, "%s: Deleting device %s at 0x%02hx\n", ++ "delete_device", client->name, client->addr); + list_del(&client->detected); + peci_unregister_device(client); +- rc = count; ++ ret = count; + break; + } + } + mutex_unlock(&adapter->userspace_clients_lock); + +- if (rc < 0) +- dev_err(dev, "%s: Can't find device in list\n", ++ if (ret < 0) ++ dev_dbg(dev, "%s: Can't find device in list\n", + "delete_device"); + +- return rc; ++ return ret; + } + static DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, 0200, NULL, + peci_sysfs_delete_device); +@@ -1039,10 +1138,11 @@ static struct attribute *peci_adapter_attrs[] = { + }; + ATTRIBUTE_GROUPS(peci_adapter); + +-static struct device_type peci_adapter_type = { ++struct device_type peci_adapter_type = { + .groups = peci_adapter_groups, + .release = peci_adapter_dev_release, + }; ++EXPORT_SYMBOL_GPL(peci_adapter_type); + + /** + * peci_verify_adapter - return parameter as peci_adapter, or NULL +@@ -1063,32 +1163,26 @@ static struct peci_client *peci_of_register_device(struct peci_adapter *adapter, + struct device_node *node) + { + struct peci_board_info info = {}; +- struct peci_client *result; +- const __be32 *addr_be; +- int len; ++ struct peci_client *client; ++ u32 addr; ++ int ret; + + dev_dbg(&adapter->dev, "register %pOF\n", node); + +- if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) { +- dev_err(&adapter->dev, "modalias failure on %pOF\n", node); +- return ERR_PTR(-EINVAL); +- } +- +- addr_be = of_get_property(node, "reg", &len); +- if (!addr_be || len < sizeof(*addr_be)) { ++ ret = of_property_read_u32(node, "reg", &addr); ++ if (ret) { + dev_err(&adapter->dev, "invalid reg on %pOF\n", node); +- return ERR_PTR(-EINVAL); ++ return ERR_PTR(ret); + } + +- info.addr = be32_to_cpup(addr_be); +- info.of_node = of_node_get(node); ++ info.addr = addr; ++ info.of_node = node; + +- result = peci_new_device(adapter, &info); +- if (!result) +- result = ERR_PTR(-EINVAL); ++ client = peci_new_device(adapter, &info); ++ if (!client) ++ client = ERR_PTR(-EINVAL); + +- of_node_put(node); +- return result; ++ return client; + } + + static void peci_of_register_devices(struct peci_adapter *adapter) +@@ -1119,7 +1213,7 @@ static void peci_of_register_devices(struct peci_adapter *adapter) of_node_put(bus); } @@ -224,7 +3229,18 @@ index fac8c72dcda8..7ae05ded94bf 100644 static void peci_of_register_devices(struct peci_adapter *adapter) { } #endif /* CONFIG_OF */ -@@ -1216,7 +1216,7 @@ static int peci_of_notify(struct notifier_block *nb, +@@ -1163,9 +1257,7 @@ static struct peci_adapter *peci_of_find_adapter(struct device_node *node) + return adapter; + } + +-static int peci_of_notify(struct notifier_block *nb, +- unsigned long action, +- void *arg) ++static int peci_of_notify(struct notifier_block *nb, ulong action, void *arg) + { + struct of_reconfig_data *rd = arg; + struct peci_adapter *adapter; +@@ -1216,7 +1308,7 @@ static int peci_of_notify(struct notifier_block *nb, static struct notifier_block peci_of_notifier = { .notifier_call = peci_of_notify, }; @@ -233,8 +3249,516 @@ index fac8c72dcda8..7ae05ded94bf 100644 extern struct notifier_block peci_of_notifier; #endif /* CONFIG_OF_DYNAMIC */ +@@ -1240,7 +1332,7 @@ extern struct notifier_block peci_of_notifier; + * + * Return: the peci_adapter structure on success, else NULL. + */ +-struct peci_adapter *peci_alloc_adapter(struct device *dev, unsigned int size) ++struct peci_adapter *peci_alloc_adapter(struct device *dev, uint size) + { + struct peci_adapter *adapter; + +@@ -1263,7 +1355,7 @@ EXPORT_SYMBOL_GPL(peci_alloc_adapter); + + static int peci_register_adapter(struct peci_adapter *adapter) + { +- int rc = -EINVAL; ++ int ret = -EINVAL; + + /* Can't register until after driver model init */ + if (WARN_ON(!is_registered)) +@@ -1275,27 +1367,17 @@ static int peci_register_adapter(struct peci_adapter *adapter) + if (WARN(!adapter->xfer, "peci adapter has no xfer function\n")) + goto err_free_idr; + +- rt_mutex_init(&adapter->bus_lock); ++ mutex_init(&adapter->bus_lock); + mutex_init(&adapter->userspace_clients_lock); + INIT_LIST_HEAD(&adapter->userspace_clients); + + dev_set_name(&adapter->dev, "peci-%d", adapter->nr); + +- /* cdev */ +- cdev_init(&adapter->cdev, &peci_fops); +- adapter->cdev.owner = THIS_MODULE; +- adapter->dev.devt = MKDEV(MAJOR(peci_devt), adapter->nr); +- rc = cdev_add(&adapter->cdev, adapter->dev.devt, 1); +- if (rc) { +- pr_err("adapter '%s': can't add cdev (%d)\n", +- adapter->name, rc); +- goto err_free_idr; +- } +- rc = device_add(&adapter->dev); +- if (rc) { ++ ret = device_add(&adapter->dev); ++ if (ret) { + pr_err("adapter '%s': can't add device (%d)\n", +- adapter->name, rc); +- goto err_del_cdev; ++ adapter->name, ret); ++ goto err_free_idr; + } + + dev_dbg(&adapter->dev, "adapter [%s] registered\n", adapter->name); +@@ -1309,13 +1391,11 @@ static int peci_register_adapter(struct peci_adapter *adapter) + + return 0; + +-err_del_cdev: +- cdev_del(&adapter->cdev); + err_free_idr: + mutex_lock(&core_lock); + idr_remove(&peci_adapter_idr, adapter->nr); + mutex_unlock(&core_lock); +- return rc; ++ return ret; + } + + static int peci_add_numbered_adapter(struct peci_adapter *adapter) +@@ -1411,7 +1491,7 @@ void peci_del_adapter(struct peci_adapter *adapter) + } + mutex_unlock(&adapter->userspace_clients_lock); + +- /** ++ /* + * Detach any active clients. This can't fail, thus we do not + * check the returned value. + */ +@@ -1420,13 +1500,8 @@ void peci_del_adapter(struct peci_adapter *adapter) + /* device name is gone after device_unregister */ + dev_dbg(&adapter->dev, "adapter [%s] unregistered\n", adapter->name); + +- /* free cdev */ +- cdev_del(&adapter->cdev); +- + pm_runtime_disable(&adapter->dev); +- + nr = adapter->nr; +- + device_unregister(&adapter->dev); + + /* free bus id */ +@@ -1436,6 +1511,18 @@ void peci_del_adapter(struct peci_adapter *adapter) + } + EXPORT_SYMBOL_GPL(peci_del_adapter); + ++int peci_for_each_dev(void *data, int (*fn)(struct device *, void *)) ++{ ++ int ret; ++ ++ mutex_lock(&core_lock); ++ ret = bus_for_each_dev(&peci_bus_type, NULL, data, fn); ++ mutex_unlock(&core_lock); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(peci_for_each_dev); ++ + /** + * peci_register_driver - register a PECI driver + * @owner: owner module of the driver being registered +@@ -1446,7 +1533,7 @@ EXPORT_SYMBOL_GPL(peci_del_adapter); + */ + int peci_register_driver(struct module *owner, struct peci_driver *driver) + { +- int rc; ++ int ret; + + /* Can't register until after driver model init */ + if (WARN_ON(!is_registered)) +@@ -1456,13 +1543,13 @@ int peci_register_driver(struct module *owner, struct peci_driver *driver) + driver->driver.owner = owner; + driver->driver.bus = &peci_bus_type; + +- /** ++ /* + * When registration returns, the driver core + * will have called probe() for all matching-but-unbound devices. + */ +- rc = driver_register(&driver->driver); +- if (rc) +- return rc; ++ ret = driver_register(&driver->driver); ++ if (ret) ++ return ret; + + pr_debug("driver [%s] registered\n", driver->driver.name); + +@@ -1492,13 +1579,6 @@ static int __init peci_init(void) + return ret; + } + +- ret = alloc_chrdev_region(&peci_devt, 0, PECI_CDEV_MAX, "peci"); +- if (ret < 0) { +- pr_err("peci: Failed to allocate chr dev region!\n"); +- bus_unregister(&peci_bus_type); +- return ret; +- } +- + crc8_populate_msb(peci_crc8_table, PECI_CRC8_POLYNOMIAL); + + if (IS_ENABLED(CONFIG_OF_DYNAMIC)) +@@ -1514,11 +1594,10 @@ static void __exit peci_exit(void) + if (IS_ENABLED(CONFIG_OF_DYNAMIC)) + WARN_ON(of_reconfig_notifier_unregister(&peci_of_notifier)); + +- unregister_chrdev_region(peci_devt, PECI_CDEV_MAX); + bus_unregister(&peci_bus_type); + } + +-postcore_initcall(peci_init); ++subsys_initcall(peci_init); + module_exit(peci_exit); + + MODULE_AUTHOR("Jason M Biils <jason.m.bills@linux.intel.com>"); +diff --git a/drivers/peci/peci-dev.c b/drivers/peci/peci-dev.c +new file mode 100644 +index 000000000000..5de0683206bc +--- /dev/null ++++ b/drivers/peci/peci-dev.c +@@ -0,0 +1,340 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// Copyright (c) 2018-2019 Intel Corporation ++ ++#include <linux/cdev.h> ++#include <linux/fs.h> ++#include <linux/list.h> ++#include <linux/module.h> ++#include <linux/notifier.h> ++#include <linux/peci.h> ++#include <linux/slab.h> ++#include <linux/uaccess.h> ++ ++/* ++ * A peci_dev represents an peci_adapter ... an PECI or SMBus master, not a ++ * slave (peci_client) with which messages will be exchanged. It's coupled ++ * with a character special file which is accessed by user mode drivers. ++ * ++ * The list of peci_dev structures is parallel to the peci_adapter lists ++ * maintained by the driver model, and is updated using bus notifications. ++ */ ++struct peci_dev { ++ struct list_head list; ++ struct peci_adapter *adapter; ++ struct device *dev; ++ struct cdev cdev; ++}; ++ ++#define PECI_MINORS MINORMASK ++ ++static dev_t peci_devt; ++static LIST_HEAD(peci_dev_list); ++static DEFINE_SPINLOCK(peci_dev_list_lock); ++ ++static struct peci_dev *peci_dev_get_by_minor(uint index) ++{ ++ struct peci_dev *peci_dev; ++ ++ spin_lock(&peci_dev_list_lock); ++ list_for_each_entry(peci_dev, &peci_dev_list, list) { ++ if (peci_dev->adapter->nr == index) ++ goto found; ++ } ++ peci_dev = NULL; ++found: ++ spin_unlock(&peci_dev_list_lock); ++ ++ return peci_dev; ++} ++ ++static struct peci_dev *peci_dev_alloc(struct peci_adapter *adapter) ++{ ++ struct peci_dev *peci_dev; ++ ++ if (adapter->nr >= PECI_MINORS) { ++ printk(KERN_ERR "peci-dev: Out of device minors (%d)\n", ++ adapter->nr); ++ return ERR_PTR(-ENODEV); ++ } ++ ++ peci_dev = kzalloc(sizeof(*peci_dev), GFP_KERNEL); ++ if (!peci_dev) ++ return ERR_PTR(-ENOMEM); ++ peci_dev->adapter = adapter; ++ ++ spin_lock(&peci_dev_list_lock); ++ list_add_tail(&peci_dev->list, &peci_dev_list); ++ spin_unlock(&peci_dev_list_lock); ++ ++ return peci_dev; ++} ++ ++static void peci_dev_put(struct peci_dev *peci_dev) ++{ ++ spin_lock(&peci_dev_list_lock); ++ list_del(&peci_dev->list); ++ spin_unlock(&peci_dev_list_lock); ++ kfree(peci_dev); ++} ++ ++static ssize_t name_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct peci_dev *peci_dev = peci_dev_get_by_minor(MINOR(dev->devt)); ++ ++ if (!peci_dev) ++ return -ENODEV; ++ ++ return sprintf(buf, "%s\n", peci_dev->adapter->name); ++} ++static DEVICE_ATTR_RO(name); ++ ++static struct attribute *peci_dev_attrs[] = { ++ &dev_attr_name.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(peci_dev); ++ ++static long peci_dev_ioctl(struct file *file, uint iocmd, ulong arg) ++{ ++ struct peci_dev *peci_dev = file->private_data; ++ struct peci_xfer_msg __user *uxmsg; ++ struct peci_xfer_msg *xmsg = NULL; ++ void __user *umsg; ++ enum peci_cmd cmd; ++ u8 *msg = NULL; ++ uint msg_len; ++ int ret; ++ ++ cmd = _IOC_NR(iocmd); ++ msg_len = _IOC_SIZE(iocmd); ++ ++ switch (cmd) { ++ case PECI_CMD_XFER: ++ if (msg_len != sizeof(struct peci_xfer_msg)) { ++ ret = -EFAULT; ++ break; ++ } ++ ++ uxmsg = (struct peci_xfer_msg __user *)arg; ++ xmsg = peci_get_xfer_msg(uxmsg->tx_len, uxmsg->rx_len); ++ if (IS_ERR(xmsg)) { ++ ret = PTR_ERR(xmsg); ++ break; ++ } ++ ++ if (uxmsg->tx_len && ++ copy_from_user(uxmsg->tx_buf, xmsg->tx_buf, ++ uxmsg->tx_len)) { ++ ret = -EFAULT; ++ break; ++ } ++ ++ ret = peci_command(peci_dev->adapter, cmd, xmsg); ++ if (!ret && uxmsg->rx_len && ++ copy_to_user(xmsg->rx_buf, uxmsg->rx_buf, ++ uxmsg->rx_len)) ++ ret = -EFAULT; ++ ++ break; ++ ++ default: ++ umsg = (void __user *)arg; ++ msg = memdup_user(umsg, msg_len); ++ if (IS_ERR(msg)) { ++ ret = PTR_ERR(msg); ++ break; ++ } ++ ++ ret = peci_command(peci_dev->adapter, cmd, msg); ++ if (!ret && copy_to_user(umsg, msg, msg_len)) ++ ret = -EFAULT; ++ ++ break; ++ } ++ ++ peci_put_xfer_msg(xmsg); ++ kfree(msg); ++ ++ return (long)ret; ++} ++ ++static int peci_dev_open(struct inode *inode, struct file *file) ++{ ++ struct peci_adapter *adapter; ++ struct peci_dev *peci_dev; ++ ++ peci_dev = peci_dev_get_by_minor(iminor(inode)); ++ if (!peci_dev) ++ return -ENODEV; ++ ++ adapter = peci_get_adapter(peci_dev->adapter->nr); ++ if (!adapter) ++ return -ENODEV; ++ ++ file->private_data = peci_dev; ++ ++ return 0; ++} ++ ++static int peci_dev_release(struct inode *inode, struct file *file) ++{ ++ struct peci_dev *peci_dev = file->private_data; ++ ++ peci_put_adapter(peci_dev->adapter); ++ file->private_data = NULL; ++ ++ return 0; ++} ++ ++static const struct file_operations peci_dev_fops = { ++ .owner = THIS_MODULE, ++ .unlocked_ioctl = peci_dev_ioctl, ++ .open = peci_dev_open, ++ .release = peci_dev_release, ++ .llseek = no_llseek, ++}; ++ ++static struct class *peci_dev_class; ++ ++static int peci_dev_attach_adapter(struct device *dev, void *dummy) ++{ ++ struct peci_adapter *adapter; ++ struct peci_dev *peci_dev; ++ dev_t devt; ++ int ret; ++ ++ if (dev->type != &peci_adapter_type) ++ return 0; ++ ++ adapter = to_peci_adapter(dev); ++ peci_dev = peci_dev_alloc(adapter); ++ if (IS_ERR(peci_dev)) ++ return PTR_ERR(peci_dev); ++ ++ cdev_init(&peci_dev->cdev, &peci_dev_fops); ++ peci_dev->cdev.owner = THIS_MODULE; ++ devt = MKDEV(MAJOR(peci_devt), adapter->nr); ++ ++ ret = cdev_add(&peci_dev->cdev, devt, 1); ++ if (ret) ++ goto err_put_dev; ++ ++ /* register this peci device with the driver core */ ++ peci_dev->dev = device_create(peci_dev_class, &adapter->dev, devt, NULL, ++ "peci-%d", adapter->nr); ++ if (IS_ERR(peci_dev->dev)) { ++ ret = PTR_ERR(peci_dev->dev); ++ goto err_del_cdev; ++ } ++ ++ pr_info("peci-dev: adapter [%s] registered as minor %d\n", ++ adapter->name, adapter->nr); ++ ++ return 0; ++ ++err_del_cdev: ++ cdev_del(&peci_dev->cdev); ++err_put_dev: ++ peci_dev_put(peci_dev); ++ ++ return ret; ++} ++ ++static int peci_dev_detach_adapter(struct device *dev, void *dummy) ++{ ++ struct peci_adapter *adapter; ++ struct peci_dev *peci_dev; ++ dev_t devt; ++ ++ if (dev->type != &peci_adapter_type) ++ return 0; ++ ++ adapter = to_peci_adapter(dev); ++ peci_dev = peci_dev_get_by_minor(adapter->nr); ++ if (!peci_dev) ++ return 0; ++ ++ cdev_del(&peci_dev->cdev); ++ devt = peci_dev->dev->devt; ++ peci_dev_put(peci_dev); ++ device_destroy(peci_dev_class, devt); ++ ++ pr_info("peci-dev: adapter [%s] unregistered\n", adapter->name); ++ ++ return 0; ++} ++ ++static int peci_dev_notifier_call(struct notifier_block *nb, ulong action, ++ void *data) ++{ ++ struct device *dev = data; ++ ++ switch (action) { ++ case BUS_NOTIFY_ADD_DEVICE: ++ return peci_dev_attach_adapter(dev, NULL); ++ case BUS_NOTIFY_DEL_DEVICE: ++ return peci_dev_detach_adapter(dev, NULL); ++ } ++ ++ return 0; ++} ++ ++static struct notifier_block peci_dev_notifier = { ++ .notifier_call = peci_dev_notifier_call, ++}; ++ ++static int __init peci_dev_init(void) ++{ ++ int ret; ++ ++ printk(KERN_INFO "peci /dev entries driver\n"); ++ ++ ret = alloc_chrdev_region(&peci_devt, 0, PECI_MINORS, "peci"); ++ if (ret < 0) { ++ pr_err("peci: Failed to allocate chr dev region!\n"); ++ bus_unregister(&peci_bus_type); ++ goto err; ++ } ++ ++ peci_dev_class = class_create(THIS_MODULE, "peci-dev"); ++ if (IS_ERR(peci_dev_class)) { ++ ret = PTR_ERR(peci_dev_class); ++ goto err_unreg_chrdev; ++ } ++ peci_dev_class->dev_groups = peci_dev_groups; ++ ++ /* Keep track of adapters which will be added or removed later */ ++ ret = bus_register_notifier(&peci_bus_type, &peci_dev_notifier); ++ if (ret) ++ goto err_destroy_class; ++ ++ /* Bind to already existing adapters right away */ ++ peci_for_each_dev(NULL, peci_dev_attach_adapter); ++ ++ return 0; ++ ++err_destroy_class: ++ class_destroy(peci_dev_class); ++err_unreg_chrdev: ++ unregister_chrdev_region(peci_devt, PECI_MINORS); ++err: ++ printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__); ++ ++ return ret; ++} ++ ++static void __exit peci_dev_exit(void) ++{ ++ bus_unregister_notifier(&peci_bus_type, &peci_dev_notifier); ++ peci_for_each_dev(NULL, peci_dev_detach_adapter); ++ class_destroy(peci_dev_class); ++ unregister_chrdev_region(peci_devt, PECI_MINORS); ++} ++ ++module_init(peci_dev_init); ++module_exit(peci_dev_exit); ++ ++MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>"); ++MODULE_DESCRIPTION("PECI /dev entries driver"); ++MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mfd/intel-peci-client.h b/include/linux/mfd/intel-peci-client.h -index 8f6d823a59cd..dd5eb36cca75 100644 +index 8f6d823a59cd..1f1b07a9aeab 100644 --- a/include/linux/mfd/intel-peci-client.h +++ b/include/linux/mfd/intel-peci-client.h @@ -1,5 +1,5 @@ @@ -244,6 +3768,15 @@ index 8f6d823a59cd..dd5eb36cca75 100644 #ifndef __LINUX_MFD_INTEL_PECI_CLIENT_H #define __LINUX_MFD_INTEL_PECI_CLIENT_H +@@ -9,7 +9,7 @@ + #if IS_ENABLED(CONFIG_X86) + #include <asm/intel-family.h> + #else +-/** ++/* + * Architectures other than x86 cannot include the header file so define these + * at here. These are needed for detecting type of client x86 CPUs behind a PECI + * connection. @@ -58,7 +58,6 @@ struct cpu_gen_info { /** * struct peci_client_manager - PECI client manager information @@ -261,16 +3794,599 @@ index 8f6d823a59cd..dd5eb36cca75 100644 const struct cpu_gen_info *gen_info; }; diff --git a/include/linux/peci.h b/include/linux/peci.h -index d0e47d45d1d0..4b8be939585c 100644 +index d0e47d45d1d0..6fc424dc2a73 100644 --- a/include/linux/peci.h +++ b/include/linux/peci.h -@@ -1,5 +1,5 @@ +@@ -1,19 +1,18 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (c) 2018 Intel Corporation */ +/* Copyright (c) 2018-2019 Intel Corporation */ #ifndef __LINUX_PECI_H #define __LINUX_PECI_H + +-#include <linux/cdev.h> + #include <linux/device.h> ++#include <linux/mutex.h> + #include <linux/peci-ioctl.h> +-#include <linux/rtmutex.h> + + #define PECI_NAME_SIZE 32 + + struct peci_board_info { + char type[PECI_NAME_SIZE]; +- unsigned short addr; /* CPU client address */ ++ u8 addr; /* CPU client address */ + struct device_node *of_node; + }; + +@@ -22,29 +21,29 @@ struct peci_board_info { + * @owner: owner module of the PECI adpater + * @bus_lock: mutex for exclusion of multiple callers + * @dev: device interface to this driver +- * @cdev: character device object to create character device + * @nr: the bus number to map + * @name: name of the adapter + * @userspace_clients_lock: mutex for exclusion of clients handling + * @userspace_clients: list of registered clients + * @xfer: low-level transfer function pointer of the adapter + * @cmd_mask: mask for supportable PECI commands ++ * @use_dma: flag for indicating that adapter uses DMA + * + * Each PECI adapter can communicate with one or more PECI client children. + * These make a small bus, sharing a single wired PECI connection. + */ + struct peci_adapter { + struct module *owner; +- struct rt_mutex bus_lock; ++ struct mutex bus_lock; + struct device dev; +- struct cdev cdev; + int nr; + char name[PECI_NAME_SIZE]; + struct mutex userspace_clients_lock; /* clients list mutex */ + struct list_head userspace_clients; + int (*xfer)(struct peci_adapter *adapter, + struct peci_xfer_msg *msg); +- uint cmd_mask; ++ u32 cmd_mask; ++ bool use_dma; + }; + + static inline struct peci_adapter *to_peci_adapter(void *d) +@@ -87,8 +86,8 @@ static inline struct peci_client *to_peci_client(void *d) + } + + struct peci_device_id { +- char name[PECI_NAME_SIZE]; +- unsigned long driver_data; /* Data private to the driver */ ++ char name[PECI_NAME_SIZE]; ++ ulong driver_data; /* Data private to the driver */ + }; + + /** +@@ -129,13 +128,22 @@ static inline struct peci_driver *to_peci_driver(void *d) + /* use a define to avoid include chaining to get THIS_MODULE */ + #define peci_add_driver(driver) peci_register_driver(THIS_MODULE, driver) + ++extern struct bus_type peci_bus_type; ++extern struct device_type peci_adapter_type; ++extern struct device_type peci_client_type; ++ + int peci_register_driver(struct module *owner, struct peci_driver *drv); + void peci_del_driver(struct peci_driver *driver); + struct peci_client *peci_verify_client(struct device *dev); +-struct peci_adapter *peci_alloc_adapter(struct device *dev, unsigned int size); ++struct peci_adapter *peci_alloc_adapter(struct device *dev, uint size); ++struct peci_adapter *peci_get_adapter(int nr); ++void peci_put_adapter(struct peci_adapter *adapter); + int peci_add_adapter(struct peci_adapter *adapter); + void peci_del_adapter(struct peci_adapter *adapter); + struct peci_adapter *peci_verify_adapter(struct device *dev); ++int peci_for_each_dev(void *data, int (*fn)(struct device *, void *)); ++struct peci_xfer_msg *peci_get_xfer_msg(u8 tx_len, u8 rx_len); ++void peci_put_xfer_msg(struct peci_xfer_msg *msg); + int peci_command(struct peci_adapter *adpater, enum peci_cmd cmd, void *vmsg); + int peci_get_cpu_id(struct peci_adapter *adapter, u8 addr, u32 *cpu_id); + +diff --git a/include/uapi/linux/peci-ioctl.h b/include/uapi/linux/peci-ioctl.h +index a6dae71cbff5..8467b2fbee1f 100644 +--- a/include/uapi/linux/peci-ioctl.h ++++ b/include/uapi/linux/peci-ioctl.h +@@ -1,5 +1,5 @@ + /* SPDX-License-Identifier: GPL-2.0 */ +-/* Copyright (c) 2018 Intel Corporation */ ++/* Copyright (c) 2018-2019 Intel Corporation */ + + #ifndef __PECI_IOCTL_H + #define __PECI_IOCTL_H +@@ -7,136 +7,34 @@ + #include <linux/ioctl.h> + #include <linux/types.h> + +-/* Base Address of 48d */ +-#define PECI_BASE_ADDR 0x30 /* The PECI client's default address of 0x30 */ +-#define PECI_OFFSET_MAX 8 /* Max numver of CPU clients */ +- +-/* PCI Access */ +-#define MAX_PCI_READ_LEN 24 /* Number of bytes of the PCI Space read */ +- +-#define PCI_BUS0_CPU0 0x00 +-#define PCI_BUS0_CPU1 0x80 +-#define PCI_CPUBUSNO_BUS 0x00 +-#define PCI_CPUBUSNO_DEV 0x08 +-#define PCI_CPUBUSNO_FUNC 0x02 +-#define PCI_CPUBUSNO 0xcc +-#define PCI_CPUBUSNO_1 0xd0 +-#define PCI_CPUBUSNO_VALID 0xd4 +- +-/* Package Identifier Read Parameter Value */ +-#define PKG_ID_CPU_ID 0x0000 /* CPUID Info */ +-#define PKG_ID_PLATFORM_ID 0x0001 /* Platform ID */ +-#define PKG_ID_UNCORE_ID 0x0002 /* Uncore Device ID */ +-#define PKG_ID_MAX_THREAD_ID 0x0003 /* Max Thread ID */ +-#define PKG_ID_MICROCODE_REV 0x0004 /* CPU Microcode Update Revision */ +-#define PKG_ID_MACHINE_CHECK_STATUS 0x0005 /* Machine Check Status */ +- +-/* RdPkgConfig Index */ +-#define MBX_INDEX_CPU_ID 0 /* Package Identifier Read */ +-#define MBX_INDEX_VR_DEBUG 1 /* VR Debug */ +-#define MBX_INDEX_PKG_TEMP_READ 2 /* Package Temperature Read */ +-#define MBX_INDEX_ENERGY_COUNTER 3 /* Energy counter */ +-#define MBX_INDEX_ENERGY_STATUS 4 /* DDR Energy Status */ +-#define MBX_INDEX_WAKE_MODE_BIT 5 /* "Wake on PECI" Mode bit */ +-#define MBX_INDEX_EPI 6 /* Efficient Performance Indication */ +-#define MBX_INDEX_PKG_RAPL_PERF 8 /* Pkg RAPL Performance Status Read */ +-#define MBX_INDEX_PER_CORE_DTS_TEMP 9 /* Per Core DTS Temperature Read */ +-#define MBX_INDEX_DTS_MARGIN 10 /* DTS thermal margin */ +-#define MBX_INDEX_SKT_PWR_THRTL_DUR 11 /* Socket Power Throttled Duration */ +-#define MBX_INDEX_CFG_TDP_CONTROL 12 /* TDP Config Control */ +-#define MBX_INDEX_CFG_TDP_LEVELS 13 /* TDP Config Levels */ +-#define MBX_INDEX_DDR_DIMM_TEMP 14 /* DDR DIMM Temperature */ +-#define MBX_INDEX_CFG_ICCMAX 15 /* Configurable ICCMAX */ +-#define MBX_INDEX_TEMP_TARGET 16 /* Temperature Target Read */ +-#define MBX_INDEX_CURR_CFG_LIMIT 17 /* Current Config Limit */ +-#define MBX_INDEX_DIMM_TEMP_READ 20 /* Package Thermal Status Read */ +-#define MBX_INDEX_DRAM_IMC_TMP_READ 22 /* DRAM IMC Temperature Read */ +-#define MBX_INDEX_DDR_CH_THERM_STAT 23 /* DDR Channel Thermal Status */ +-#define MBX_INDEX_PKG_POWER_LIMIT1 26 /* Package Power Limit1 */ +-#define MBX_INDEX_PKG_POWER_LIMIT2 27 /* Package Power Limit2 */ +-#define MBX_INDEX_TDP 28 /* Thermal design power minimum */ +-#define MBX_INDEX_TDP_HIGH 29 /* Thermal design power maximum */ +-#define MBX_INDEX_TDP_UNITS 30 /* Units for power/energy registers */ +-#define MBX_INDEX_RUN_TIME 31 /* Accumulated Run Time */ +-#define MBX_INDEX_CONSTRAINED_TIME 32 /* Thermally Constrained Time Read */ +-#define MBX_INDEX_TURBO_RATIO 33 /* Turbo Activation Ratio */ +-#define MBX_INDEX_DDR_RAPL_PL1 34 /* DDR RAPL PL1 */ +-#define MBX_INDEX_DDR_PWR_INFO_HIGH 35 /* DRAM Power Info Read (high) */ +-#define MBX_INDEX_DDR_PWR_INFO_LOW 36 /* DRAM Power Info Read (low) */ +-#define MBX_INDEX_DDR_RAPL_PL2 37 /* DDR RAPL PL2 */ +-#define MBX_INDEX_DDR_RAPL_STATUS 38 /* DDR RAPL Performance Status */ +-#define MBX_INDEX_DDR_HOT_ABSOLUTE 43 /* DDR Hottest Dimm Absolute Temp */ +-#define MBX_INDEX_DDR_HOT_RELATIVE 44 /* DDR Hottest Dimm Relative Temp */ +-#define MBX_INDEX_DDR_THROTTLE_TIME 45 /* DDR Throttle Time */ +-#define MBX_INDEX_DDR_THERM_STATUS 46 /* DDR Thermal Status */ +-#define MBX_INDEX_TIME_AVG_TEMP 47 /* Package time-averaged temperature */ +-#define MBX_INDEX_TURBO_RATIO_LIMIT 49 /* Turbo Ratio Limit Read */ +-#define MBX_INDEX_HWP_AUTO_OOB 53 /* HWP Autonomous Out-of-band */ +-#define MBX_INDEX_DDR_WARM_BUDGET 55 /* DDR Warm Power Budget */ +-#define MBX_INDEX_DDR_HOT_BUDGET 56 /* DDR Hot Power Budget */ +-#define MBX_INDEX_PKG_PSYS_PWR_LIM3 57 /* Package/Psys Power Limit3 */ +-#define MBX_INDEX_PKG_PSYS_PWR_LIM1 58 /* Package/Psys Power Limit1 */ +-#define MBX_INDEX_PKG_PSYS_PWR_LIM2 59 /* Package/Psys Power Limit2 */ +-#define MBX_INDEX_PKG_PSYS_PWR_LIM4 60 /* Package/Psys Power Limit4 */ +-#define MBX_INDEX_PERF_LIMIT_REASON 65 /* Performance Limit Reasons */ +- +-/* WrPkgConfig Index */ +-#define MBX_INDEX_DIMM_AMBIENT 19 +-#define MBX_INDEX_DIMM_TEMP 24 ++/* The PECI client's default address of 0x30 */ ++#define PECI_BASE_ADDR 0x30 ++ ++/* Max number of CPU clients */ ++#define PECI_OFFSET_MAX 8 ++ ++/* PECI read/write data buffer size max */ ++#define PECI_BUFFER_SIZE 255 + + /* Device Specific Completion Code (CC) Definition */ +-#define DEV_PECI_CC_SUCCESS 0x40 +-#define DEV_PECI_CC_TIMEOUT 0x80 +-#define DEV_PECI_CC_OUT_OF_RESOURCE 0x81 +-#define DEV_PECI_CC_UNAVAIL_RESOURCE 0x82 +-#define DEV_PECI_CC_INVALID_REQ 0x90 ++#define PECI_DEV_CC_SUCCESS 0x40 ++#define PECI_DEV_CC_TIMEOUT 0x80 ++#define PECI_DEV_CC_OUT_OF_RESOURCE 0x81 ++#define PECI_DEV_CC_UNAVAIL_RESOURCE 0x82 ++#define PECI_DEV_CC_INVALID_REQ 0x90 + + /* Completion Code mask to check retry needs */ +-#define DEV_PECI_CC_RETRY_CHECK_MASK 0xf0 +-#define DEV_PECI_CC_NEED_RETRY 0x80 ++#define PECI_DEV_CC_RETRY_CHECK_MASK 0xf0 ++#define PECI_DEV_CC_NEED_RETRY 0x80 + + /* Skylake EDS says to retry for 250ms */ +-#define DEV_PECI_RETRY_TIME_MS 250 +-#define DEV_PECI_RETRY_INTERVAL_USEC 10000 +-#define DEV_PECI_RETRY_BIT 0x01 +- +-#define GET_TEMP_WR_LEN 1 +-#define GET_TEMP_RD_LEN 2 +-#define GET_TEMP_PECI_CMD 0x01 +- +-#define GET_DIB_WR_LEN 1 +-#define GET_DIB_RD_LEN 8 +-#define GET_DIB_PECI_CMD 0xf7 +- +-#define RDPKGCFG_WRITE_LEN 5 +-#define RDPKGCFG_READ_LEN_BASE 1 +-#define RDPKGCFG_PECI_CMD 0xa1 +- +-#define WRPKGCFG_WRITE_LEN_BASE 6 +-#define WRPKGCFG_READ_LEN 1 +-#define WRPKGCFG_PECI_CMD 0xa5 +- +-#define RDIAMSR_WRITE_LEN 5 +-#define RDIAMSR_READ_LEN 9 +-#define RDIAMSR_PECI_CMD 0xb1 +- +-#define WRIAMSR_PECI_CMD 0xb5 +- +-#define RDPCICFG_WRITE_LEN 6 +-#define RDPCICFG_READ_LEN 5 +-#define RDPCICFG_PECI_CMD 0x61 ++#define PECI_DEV_RETRY_TIME_MS 250 ++#define PECI_DEV_RETRY_INTERVAL_USEC 10000 ++#define PECI_DEV_RETRY_BIT 0x01 + +-#define WRPCICFG_PECI_CMD 0x65 ++#define PECI_WRIAMSR_CMD 0xb5 + +-#define RDPCICFGLOCAL_WRITE_LEN 5 +-#define RDPCICFGLOCAL_READ_LEN_BASE 1 +-#define RDPCICFGLOCAL_PECI_CMD 0xe1 +- +-#define WRPCICFGLOCAL_WRITE_LEN_BASE 6 +-#define WRPCICFGLOCAL_READ_LEN 1 +-#define WRPCICFGLOCAL_PECI_CMD 0xe5 +- +-#define PECI_BUFFER_SIZE 32 ++#define PECI_WRPCICFG_CMD 0x65 + + /** + * enum peci_cmd - PECI client commands +@@ -186,11 +84,12 @@ enum peci_cmd { + * raw PECI transfer + */ + struct peci_xfer_msg { +- __u8 addr; +- __u8 tx_len; +- __u8 rx_len; +- __u8 tx_buf[PECI_BUFFER_SIZE]; +- __u8 rx_buf[PECI_BUFFER_SIZE]; ++ __u8 addr; ++ __u8 tx_len; ++ __u8 rx_len; ++ __u8 padding; ++ __u8 *tx_buf; ++ __u8 *rx_buf; + } __attribute__((__packed__)); + + /** +@@ -202,7 +101,8 @@ struct peci_xfer_msg { + * powered-off, etc. + */ + struct peci_ping_msg { +- __u8 addr; ++ __u8 addr; ++ __u8 padding[3]; + } __attribute__((__packed__)); + + /** +@@ -216,8 +116,13 @@ struct peci_ping_msg { + * command. + */ + struct peci_get_dib_msg { +- __u8 addr; +- __u64 dib; ++#define PECI_GET_DIB_WR_LEN 1 ++#define PECI_GET_DIB_RD_LEN 8 ++#define PECI_GET_DIB_CMD 0xf7 ++ ++ __u8 addr; ++ __u8 padding[3]; ++ __u64 dib; + } __attribute__((__packed__)); + + /** +@@ -232,8 +137,14 @@ struct peci_get_dib_msg { + * below the maximum processor junction temperature. + */ + struct peci_get_temp_msg { +- __u8 addr; +- __s16 temp_raw; ++#define PECI_GET_TEMP_WR_LEN 1 ++#define PECI_GET_TEMP_RD_LEN 2 ++#define PECI_GET_TEMP_CMD 0x01 ++ ++ __u8 addr; ++ __u8 padding0[3]; ++ __s16 temp_raw; ++ __u8 padding1[2]; + } __attribute__((__packed__)); + + /** +@@ -251,11 +162,72 @@ struct peci_get_temp_msg { + * DIMM temperatures and so on. + */ + struct peci_rd_pkg_cfg_msg { +- __u8 addr; +- __u8 index; +- __u16 param; +- __u8 rx_len; +- __u8 pkg_config[4]; ++#define PECI_RDPKGCFG_WRITE_LEN 5 ++#define PECI_RDPKGCFG_READ_LEN_BASE 1 ++#define PECI_RDPKGCFG_CMD 0xa1 ++ ++ __u8 addr; ++ __u8 index; ++#define PECI_MBX_INDEX_CPU_ID 0 /* Package Identifier Read */ ++#define PECI_MBX_INDEX_VR_DEBUG 1 /* VR Debug */ ++#define PECI_MBX_INDEX_PKG_TEMP_READ 2 /* Package Temperature Read */ ++#define PECI_MBX_INDEX_ENERGY_COUNTER 3 /* Energy counter */ ++#define PECI_MBX_INDEX_ENERGY_STATUS 4 /* DDR Energy Status */ ++#define PECI_MBX_INDEX_WAKE_MODE_BIT 5 /* "Wake on PECI" Mode bit */ ++#define PECI_MBX_INDEX_EPI 6 /* Efficient Performance Indication */ ++#define PECI_MBX_INDEX_PKG_RAPL_PERF 8 /* Pkg RAPL Performance Status Read */ ++#define PECI_MBX_INDEX_PER_CORE_DTS_TEMP 9 /* Per Core DTS Temperature Read */ ++#define PECI_MBX_INDEX_DTS_MARGIN 10 /* DTS thermal margin */ ++#define PECI_MBX_INDEX_SKT_PWR_THRTL_DUR 11 /* Socket Power Throttled Duration */ ++#define PECI_MBX_INDEX_CFG_TDP_CONTROL 12 /* TDP Config Control */ ++#define PECI_MBX_INDEX_CFG_TDP_LEVELS 13 /* TDP Config Levels */ ++#define PECI_MBX_INDEX_DDR_DIMM_TEMP 14 /* DDR DIMM Temperature */ ++#define PECI_MBX_INDEX_CFG_ICCMAX 15 /* Configurable ICCMAX */ ++#define PECI_MBX_INDEX_TEMP_TARGET 16 /* Temperature Target Read */ ++#define PECI_MBX_INDEX_CURR_CFG_LIMIT 17 /* Current Config Limit */ ++#define PECI_MBX_INDEX_DIMM_TEMP_READ 20 /* Package Thermal Status Read */ ++#define PECI_MBX_INDEX_DRAM_IMC_TMP_READ 22 /* DRAM IMC Temperature Read */ ++#define PECI_MBX_INDEX_DDR_CH_THERM_STAT 23 /* DDR Channel Thermal Status */ ++#define PECI_MBX_INDEX_PKG_POWER_LIMIT1 26 /* Package Power Limit1 */ ++#define PECI_MBX_INDEX_PKG_POWER_LIMIT2 27 /* Package Power Limit2 */ ++#define PECI_MBX_INDEX_TDP 28 /* Thermal design power minimum */ ++#define PECI_MBX_INDEX_TDP_HIGH 29 /* Thermal design power maximum */ ++#define PECI_MBX_INDEX_TDP_UNITS 30 /* Units for power/energy registers */ ++#define PECI_MBX_INDEX_RUN_TIME 31 /* Accumulated Run Time */ ++#define PECI_MBX_INDEX_CONSTRAINED_TIME 32 /* Thermally Constrained Time Read */ ++#define PECI_MBX_INDEX_TURBO_RATIO 33 /* Turbo Activation Ratio */ ++#define PECI_MBX_INDEX_DDR_RAPL_PL1 34 /* DDR RAPL PL1 */ ++#define PECI_MBX_INDEX_DDR_PWR_INFO_HIGH 35 /* DRAM Power Info Read (high) */ ++#define PECI_MBX_INDEX_DDR_PWR_INFO_LOW 36 /* DRAM Power Info Read (low) */ ++#define PECI_MBX_INDEX_DDR_RAPL_PL2 37 /* DDR RAPL PL2 */ ++#define PECI_MBX_INDEX_DDR_RAPL_STATUS 38 /* DDR RAPL Performance Status */ ++#define PECI_MBX_INDEX_DDR_HOT_ABSOLUTE 43 /* DDR Hottest Dimm Absolute Temp */ ++#define PECI_MBX_INDEX_DDR_HOT_RELATIVE 44 /* DDR Hottest Dimm Relative Temp */ ++#define PECI_MBX_INDEX_DDR_THROTTLE_TIME 45 /* DDR Throttle Time */ ++#define PECI_MBX_INDEX_DDR_THERM_STATUS 46 /* DDR Thermal Status */ ++#define PECI_MBX_INDEX_TIME_AVG_TEMP 47 /* Package time-averaged temperature */ ++#define PECI_MBX_INDEX_TURBO_RATIO_LIMIT 49 /* Turbo Ratio Limit Read */ ++#define PECI_MBX_INDEX_HWP_AUTO_OOB 53 /* HWP Autonomous Out-of-band */ ++#define PECI_MBX_INDEX_DDR_WARM_BUDGET 55 /* DDR Warm Power Budget */ ++#define PECI_MBX_INDEX_DDR_HOT_BUDGET 56 /* DDR Hot Power Budget */ ++#define PECI_MBX_INDEX_PKG_PSYS_PWR_LIM3 57 /* Package/Psys Power Limit3 */ ++#define PECI_MBX_INDEX_PKG_PSYS_PWR_LIM1 58 /* Package/Psys Power Limit1 */ ++#define PECI_MBX_INDEX_PKG_PSYS_PWR_LIM2 59 /* Package/Psys Power Limit2 */ ++#define PECI_MBX_INDEX_PKG_PSYS_PWR_LIM4 60 /* Package/Psys Power Limit4 */ ++#define PECI_MBX_INDEX_PERF_LIMIT_REASON 65 /* Performance Limit Reasons */ ++ ++ __u16 param; ++/* When index is PECI_MBX_INDEX_CPU_ID */ ++#define PECI_PKG_ID_CPU_ID 0x0000 /* CPUID Info */ ++#define PECI_PKG_ID_PLATFORM_ID 0x0001 /* Platform ID */ ++#define PECI_PKG_ID_UNCORE_ID 0x0002 /* Uncore Device ID */ ++#define PECI_PKG_ID_MAX_THREAD_ID 0x0003 /* Max Thread ID */ ++#define PECI_PKG_ID_MICROCODE_REV 0x0004 /* CPU Microcode Update Revision */ ++#define PECI_PKG_ID_MACHINE_CHECK_STATUS 0x0005 /* Machine Check Status */ ++ ++ __u8 rx_len; ++ __u8 padding[3]; ++ __u8 pkg_config[4]; + } __attribute__((__packed__)); + + /** +@@ -272,11 +244,19 @@ struct peci_rd_pkg_cfg_msg { + * may include power limiting, thermal averaging constant programming and so on. + */ + struct peci_wr_pkg_cfg_msg { +- __u8 addr; +- __u8 index; +- __u16 param; +- __u8 tx_len; +- __u32 value; ++#define PECI_WRPKGCFG_WRITE_LEN_BASE 6 ++#define PECI_WRPKGCFG_READ_LEN 1 ++#define PECI_WRPKGCFG_CMD 0xa5 ++ ++ __u8 addr; ++ __u8 index; ++#define PECI_MBX_INDEX_DIMM_AMBIENT 19 ++#define PECI_MBX_INDEX_DIMM_TEMP 24 ++ ++ __u16 param; ++ __u8 tx_len; ++ __u8 padding[3]; ++ __u32 value; + } __attribute__((__packed__)); + + /** +@@ -290,10 +270,34 @@ struct peci_wr_pkg_cfg_msg { + * (MSRs) defined in the processor's Intel Architecture (IA). + */ + struct peci_rd_ia_msr_msg { +- __u8 addr; +- __u8 thread_id; +- __u16 address; +- __u64 value; ++#define PECI_RDIAMSR_WRITE_LEN 5 ++#define PECI_RDIAMSR_READ_LEN 9 ++#define PECI_RDIAMSR_CMD 0xb1 ++ ++ __u8 addr; ++ __u8 thread_id; ++ __u16 address; ++ __u64 value; ++} __attribute__((__packed__)); ++ ++/** ++ * struct peci_wr_ia_msr_msg - WrIAMSR command ++ * @addr: address of the client ++ * @thread_id: ID of the specific logical processor ++ * @address: address of MSR to write to ++ * @tx_len: number of data to be written in bytes ++ * @value: data to be written ++ * ++ * The WrIAMSR() PECI command provides write access to Model Specific Registers ++ * (MSRs) defined in the processor's Intel Architecture (IA). ++ */ ++struct peci_wr_ia_msr_msg { ++ __u8 addr; ++ __u8 thread_id; ++ __u16 address; ++ __u8 tx_len; ++ __u8 padding[3]; ++ __u64 value; + } __attribute__((__packed__)); + + /** +@@ -310,12 +314,52 @@ struct peci_rd_ia_msr_msg { + * processor. + */ + struct peci_rd_pci_cfg_msg { +- __u8 addr; +- __u8 bus; +- __u8 device; +- __u8 function; +- __u16 reg; +- __u8 pci_config[4]; ++#define PECI_RDPCICFG_WRITE_LEN 6 ++#define PECI_RDPCICFG_READ_LEN 5 ++#define PECI_RDPCICFG_READ_LEN_MAX 24 ++#define PECI_RDPCICFG_CMD 0x61 ++ ++ __u8 addr; ++ __u8 bus; ++#define PECI_PCI_BUS0_CPU0 0x00 ++#define PECI_PCI_BUS0_CPU1 0x80 ++#define PECI_PCI_CPUBUSNO_BUS 0x00 ++#define PECI_PCI_CPUBUSNO_DEV 0x08 ++#define PECI_PCI_CPUBUSNO_FUNC 0x02 ++#define PECI_PCI_CPUBUSNO 0xcc ++#define PECI_PCI_CPUBUSNO_1 0xd0 ++#define PECI_PCI_CPUBUSNO_VALID 0xd4 ++ ++ __u8 device; ++ __u8 function; ++ __u16 reg; ++ __u8 padding[2]; ++ __u8 pci_config[4]; ++} __attribute__((__packed__)); ++ ++/** ++ * struct peci_wr_pci_cfg_msg - WrPCIConfig command ++ * @addr: address of the client ++ * @bus: PCI bus number ++ * @device: PCI device number ++ * @function: specific function to write to ++ * @reg: specific register to write to ++ * @tx_len: number of data to be written in bytes ++ * @pci_config: config data to be written ++ * ++ * The RdPCIConfig() command provides sideband write access to the PCI ++ * configuration space maintained in downstream devices external to the ++ * processor. ++ */ ++struct peci_wr_pci_cfg_msg { ++ __u8 addr; ++ __u8 bus; ++ __u8 device; ++ __u8 function; ++ __u16 reg; ++ __u8 tx_len; ++ __u8 padding; ++ __u8 pci_config[4]; + } __attribute__((__packed__)); + + /** +@@ -333,13 +377,18 @@ struct peci_rd_pci_cfg_msg { + * processor IIO and uncore registers within the PCI configuration space. + */ + struct peci_rd_pci_cfg_local_msg { +- __u8 addr; +- __u8 bus; +- __u8 device; +- __u8 function; +- __u16 reg; +- __u8 rx_len; +- __u8 pci_config[4]; ++#define PECI_RDPCICFGLOCAL_WRITE_LEN 5 ++#define PECI_RDPCICFGLOCAL_READ_LEN_BASE 1 ++#define PECI_RDPCICFGLOCAL_CMD 0xe1 ++ ++ __u8 addr; ++ __u8 bus; ++ __u8 device; ++ __u8 function; ++ __u16 reg; ++ __u8 rx_len; ++ __u8 padding[3]; ++ __u8 pci_config[4]; + } __attribute__((__packed__)); + + /** +@@ -357,13 +406,18 @@ struct peci_rd_pci_cfg_local_msg { + * access this space even before BIOS enumeration of the system buses. + */ + struct peci_wr_pci_cfg_local_msg { +- __u8 addr; +- __u8 bus; +- __u8 device; +- __u8 function; +- __u16 reg; +- __u8 tx_len; +- __u32 value; ++#define PECI_WRPCICFGLOCAL_WRITE_LEN_BASE 6 ++#define PECI_WRPCICFGLOCAL_READ_LEN 1 ++#define PECI_WRPCICFGLOCAL_CMD 0xe5 ++ ++ __u8 addr; ++ __u8 bus; ++ __u8 device; ++ __u8 function; ++ __u16 reg; ++ __u8 tx_len; ++ __u8 padding[3]; ++ __u32 value; + } __attribute__((__packed__)); + + #define PECI_IOC_BASE 0xb7 +@@ -389,9 +443,15 @@ struct peci_wr_pci_cfg_local_msg { + #define PECI_IOC_RD_IA_MSR \ + _IOWR(PECI_IOC_BASE, PECI_CMD_RD_IA_MSR, struct peci_rd_ia_msr_msg) + ++#define PECI_IOC_WR_IA_MSR \ ++ _IOWR(PECI_IOC_BASE, PECI_CMD_WR_IA_MSR, struct peci_wr_ia_msr_msg) ++ + #define PECI_IOC_RD_PCI_CFG \ + _IOWR(PECI_IOC_BASE, PECI_CMD_RD_PCI_CFG, struct peci_rd_pci_cfg_msg) + ++#define PECI_IOC_WR_PCI_CFG \ ++ _IOWR(PECI_IOC_BASE, PECI_CMD_WR_PCI_CFG, struct peci_wr_pci_cfg_msg) ++ + #define PECI_IOC_RD_PCI_CFG_LOCAL \ + _IOWR(PECI_IOC_BASE, PECI_CMD_RD_PCI_CFG_LOCAL, \ + struct peci_rd_pci_cfg_local_msg) -- 2.7.4 diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0026-Add-support-for-new-PECI-commands.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0026-Add-support-for-new-PECI-commands.patch index 3ba6fd56e..922a45787 100644 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0026-Add-support-for-new-PECI-commands.patch +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0026-Add-support-for-new-PECI-commands.patch @@ -1,19 +1,19 @@ -From e734cd91f288838a491a75e16f3a09d353079139 Mon Sep 17 00:00:00 2001 +From 23a7407c3f1bab7c01b93eeced4e137601ac1c94 Mon Sep 17 00:00:00 2001 From: "Jason M. Bills" <jason.m.bills@intel.com> Date: Wed, 4 Apr 2018 13:52:39 -0700 Subject: [PATCH] Add support for new PECI commands Signed-off-by: Jason M. Bills <jason.m.bills@intel.com> --- - drivers/peci/peci-core.c | 200 ++++++++++++++++++++++++++++++++++++++++ - include/uapi/linux/peci-ioctl.h | 109 ++++++++++++++++++++++ - 2 files changed, 309 insertions(+) + drivers/peci/peci-core.c | 223 ++++++++++++++++++++++++++++++++++++++++ + include/uapi/linux/peci-ioctl.h | 102 ++++++++++++++++++ + 2 files changed, 325 insertions(+) diff --git a/drivers/peci/peci-core.c b/drivers/peci/peci-core.c -index fac8c72dcda8..62dada99afee 100644 +index 14048a13ef8a..2f7e795158ce 100644 --- a/drivers/peci/peci-core.c +++ b/drivers/peci/peci-core.c -@@ -242,6 +242,9 @@ static int peci_scan_cmd_mask(struct peci_adapter *adapter) +@@ -344,6 +344,9 @@ static int peci_scan_cmd_mask(struct peci_adapter *adapter) adapter->cmd_mask |= BIT(PECI_CMD_GET_TEMP); adapter->cmd_mask |= BIT(PECI_CMD_GET_DIB); adapter->cmd_mask |= BIT(PECI_CMD_PING); @@ -21,23 +21,23 @@ index fac8c72dcda8..62dada99afee 100644 + adapter->cmd_mask |= BIT(PECI_CMD_CRASHDUMP_DISC); + adapter->cmd_mask |= BIT(PECI_CMD_CRASHDUMP_GET_FRAME); - return rc; - } -@@ -515,6 +518,197 @@ static int peci_ioctl_wr_pci_cfg_local(struct peci_adapter *adapter, void *vmsg) - return rc; + out: + peci_put_xfer_msg(msg); +@@ -686,6 +689,223 @@ static int peci_cmd_wr_pci_cfg_local(struct peci_adapter *adapter, void *vmsg) + return ret; } -+static int peci_ioctl_rd_end_pt_cfg(struct peci_adapter *adapter, void *vmsg) ++static int peci_cmd_rd_end_pt_cfg(struct peci_adapter *adapter, void *vmsg) +{ + struct peci_rd_end_pt_cfg_msg *umsg = vmsg; -+ struct peci_xfer_msg msg; ++ struct peci_xfer_msg *msg = NULL; + u32 address; -+ int rc = 0; ++ int ret; + + switch (umsg->msg_type) { -+ case RDENDPTCFG_TYPE_LOCAL_PCI: -+ case RDENDPTCFG_TYPE_PCI: -+ /** ++ case PECI_RDENDPTCFG_TYPE_LOCAL_PCI: ++ case PECI_RDENDPTCFG_TYPE_PCI: ++ /* + * Per the PECI spec, the read length must be a byte, word, + * or dword + */ @@ -49,6 +49,12 @@ index fac8c72dcda8..62dada99afee 100644 + return -EINVAL; + } + ++ msg = peci_get_xfer_msg(PECI_RDENDPTCFG_PCI_WRITE_LEN, ++ PECI_RDENDPTCFG_READ_LEN_BASE + ++ umsg->rx_len); ++ if (!msg) ++ return -ENOMEM; ++ + address = umsg->params.pci_cfg.reg; /* [11:0] - Register */ + address |= (u32)umsg->params.pci_cfg.function + << 12; /* [14:12] - Function */ @@ -57,25 +63,24 @@ index fac8c72dcda8..62dada99afee 100644 + address |= (u32)umsg->params.pci_cfg.bus + << 20; /* [27:20] - Bus */ + /* [31:28] - Reserved */ -+ msg.addr = umsg->addr; -+ msg.tx_len = RDENDPTCFG_PCI_WRITE_LEN; -+ msg.rx_len = RDENDPTCFG_READ_LEN_BASE + umsg->rx_len; -+ msg.tx_buf[0] = RDENDPTCFG_PECI_CMD; -+ msg.tx_buf[1] = 0x00; /* request byte for Host ID | Retry bit */ -+ msg.tx_buf[2] = umsg->msg_type; /* Message Type */ -+ msg.tx_buf[3] = 0x00; /* Endpoint ID */ -+ msg.tx_buf[4] = 0x00; /* Reserved */ -+ msg.tx_buf[5] = 0x00; /* Reserved */ -+ msg.tx_buf[6] = RDENDPTCFG_ADDR_TYPE_PCI; /* Address Type */ -+ msg.tx_buf[7] = umsg->params.pci_cfg.seg; /* PCI Segment */ -+ msg.tx_buf[8] = (u8)address; /* LSB - PCI Config Address */ -+ msg.tx_buf[9] = (u8)(address >> 8); /* PCI Config Address */ -+ msg.tx_buf[10] = (u8)(address >> 16); /* PCI Config Address */ -+ msg.tx_buf[11] = ++ msg->addr = umsg->addr; ++ msg->tx_buf[0] = PECI_RDENDPTCFG_CMD; ++ msg->tx_buf[1] = 0x00; /* request byte for Host ID|Retry bit */ ++ msg->tx_buf[2] = umsg->msg_type; /* Message Type */ ++ msg->tx_buf[3] = 0x00; /* Endpoint ID */ ++ msg->tx_buf[4] = 0x00; /* Reserved */ ++ msg->tx_buf[5] = 0x00; /* Reserved */ ++ msg->tx_buf[6] = PECI_RDENDPTCFG_ADDR_TYPE_PCI; /* Addr Type */ ++ msg->tx_buf[7] = umsg->params.pci_cfg.seg; /* PCI Segment */ ++ msg->tx_buf[8] = (u8)address; /* LSB - PCI Config Address */ ++ msg->tx_buf[9] = (u8)(address >> 8); /* PCI Config Address */ ++ msg->tx_buf[10] = (u8)(address >> 16); /* PCI Config Address */ ++ msg->tx_buf[11] = + (u8)(address >> 24); /* MSB - PCI Config Address */ + break; -+ case RDENDPTCFG_TYPE_MMIO: -+ /** ++ ++ case PECI_RDENDPTCFG_TYPE_MMIO: ++ /* + * Per the PECI spec, the read length must be a byte, word, + * dword, or qword + */ @@ -86,73 +91,82 @@ index fac8c72dcda8..62dada99afee 100644 + umsg->rx_len); + return -EINVAL; + } -+ /** ++ /* + * Per the PECI spec, the address type must specify either DWORD + * or QWORD + */ + if (umsg->params.mmio.addr_type != -+ RDENDPTCFG_ADDR_TYPE_MMIO_D && -+ umsg->params.mmio.addr_type != -+ RDENDPTCFG_ADDR_TYPE_MMIO_Q) { ++ PECI_RDENDPTCFG_ADDR_TYPE_MMIO_D && ++ umsg->params.mmio.addr_type != ++ PECI_RDENDPTCFG_ADDR_TYPE_MMIO_Q) { + dev_dbg(&adapter->dev, + "Invalid address type, addr_type: %d\n", + umsg->params.mmio.addr_type); + return -EINVAL; + } + ++ msg = peci_get_xfer_msg(PECI_RDENDPTCFG_MMIO_D_WRITE_LEN, ++ PECI_RDENDPTCFG_READ_LEN_BASE + ++ umsg->rx_len); ++ if (!msg) ++ return -ENOMEM; ++ + address = umsg->params.mmio.function; /* [2:0] - Function */ + address |= (u32)umsg->params.mmio.device + << 3; /* [7:3] - Device */ + -+ msg.addr = umsg->addr; -+ msg.tx_len = RDENDPTCFG_MMIO_D_WRITE_LEN; -+ msg.rx_len = RDENDPTCFG_READ_LEN_BASE + umsg->rx_len; -+ msg.tx_buf[0] = RDENDPTCFG_PECI_CMD; -+ msg.tx_buf[1] = 0x00; /* request byte for Host ID | Retry bit */ -+ msg.tx_buf[2] = umsg->msg_type; /* Message Type */ -+ msg.tx_buf[3] = 0x00; /* Endpoint ID */ -+ msg.tx_buf[4] = 0x00; /* Reserved */ -+ msg.tx_buf[5] = umsg->params.mmio.bar; /* BAR # */ -+ msg.tx_buf[6] = umsg->params.mmio.addr_type; /* Address Type */ -+ msg.tx_buf[7] = umsg->params.mmio.seg; /* PCI Segment */ -+ msg.tx_buf[8] = (u8)address; /* Function/Device */ -+ msg.tx_buf[9] = umsg->params.mmio.bus; /* PCI Bus */ -+ msg.tx_buf[10] = (u8)umsg->params.mmio ++ msg->addr = umsg->addr; ++ msg->tx_buf[0] = PECI_RDENDPTCFG_CMD; ++ msg->tx_buf[1] = 0x00; /* request byte for Host ID|Retry bit */ ++ msg->tx_buf[2] = umsg->msg_type; /* Message Type */ ++ msg->tx_buf[3] = 0x00; /* Endpoint ID */ ++ msg->tx_buf[4] = 0x00; /* Reserved */ ++ msg->tx_buf[5] = umsg->params.mmio.bar; /* BAR # */ ++ msg->tx_buf[6] = umsg->params.mmio.addr_type; /* Address Type */ ++ msg->tx_buf[7] = umsg->params.mmio.seg; /* PCI Segment */ ++ msg->tx_buf[8] = (u8)address; /* Function/Device */ ++ msg->tx_buf[9] = umsg->params.mmio.bus; /* PCI Bus */ ++ msg->tx_buf[10] = (u8)umsg->params.mmio + .offset; /* LSB - Register Offset */ -+ msg.tx_buf[11] = (u8)(umsg->params.mmio.offset -+ >> 8); /* Register Offset */ -+ msg.tx_buf[12] = (u8)(umsg->params.mmio.offset -+ >> 16); /* Register Offset */ -+ msg.tx_buf[13] = (u8)(umsg->params.mmio.offset -+ >> 24); /* MSB - DWORD Register Offset */ -+ if (umsg->params.mmio.addr_type -+ == RDENDPTCFG_ADDR_TYPE_MMIO_Q) { -+ msg.tx_len = RDENDPTCFG_MMIO_Q_WRITE_LEN; -+ msg.tx_buf[14] = (u8)(umsg->params.mmio.offset -+ >> 32); /* Register Offset */ -+ msg.tx_buf[15] = (u8)(umsg->params.mmio.offset -+ >> 40); /* Register Offset */ -+ msg.tx_buf[16] = (u8)(umsg->params.mmio.offset -+ >> 48); /* Register Offset */ -+ msg.tx_buf[17] = ++ msg->tx_buf[11] = (u8)(umsg->params.mmio.offset ++ >> 8); /* Register Offset */ ++ msg->tx_buf[12] = (u8)(umsg->params.mmio.offset ++ >> 16); /* Register Offset */ ++ msg->tx_buf[13] = (u8)(umsg->params.mmio.offset ++ >> 24); /* MSB - DWORD Register Offset */ ++ if (umsg->params.mmio.addr_type == ++ PECI_RDENDPTCFG_ADDR_TYPE_MMIO_Q) { ++ msg->tx_len = PECI_RDENDPTCFG_MMIO_Q_WRITE_LEN; ++ msg->tx_buf[14] = (u8)(umsg->params.mmio.offset ++ >> 32); /* Register Offset */ ++ msg->tx_buf[15] = (u8)(umsg->params.mmio.offset ++ >> 40); /* Register Offset */ ++ msg->tx_buf[16] = (u8)(umsg->params.mmio.offset ++ >> 48); /* Register Offset */ ++ msg->tx_buf[17] = + (u8)(umsg->params.mmio.offset + >> 56); /* MSB - QWORD Register Offset */ + } + break; ++ ++ default: ++ return -EINVAL; + } + -+ rc = peci_xfer_with_retries(adapter, &msg, false); -+ if (!rc) -+ memcpy(umsg->data, &msg.rx_buf[1], umsg->rx_len); ++ ret = peci_xfer_with_retries(adapter, msg, false); ++ if (!ret) ++ memcpy(umsg->data, &msg->rx_buf[1], umsg->rx_len); + -+ return rc; ++ peci_put_xfer_msg(msg); ++ ++ return ret; +} + -+static int peci_ioctl_crashdump_disc(struct peci_adapter *adapter, void *vmsg) ++static int peci_cmd_crashdump_disc(struct peci_adapter *adapter, void *vmsg) +{ + struct peci_crashdump_disc_msg *umsg = vmsg; -+ struct peci_xfer_msg msg; -+ int rc = 0; ++ struct peci_xfer_msg *msg; ++ int ret; + + /* Per the EDS, the read length must be a byte, word, or qword */ + if (umsg->rx_len != 1 && umsg->rx_len != 2 && umsg->rx_len != 8) { @@ -161,33 +175,39 @@ index fac8c72dcda8..62dada99afee 100644 + return -EINVAL; + } + -+ msg.addr = umsg->addr; -+ msg.tx_len = CRASHDUMP_DISC_WRITE_LEN; -+ msg.rx_len = CRASHDUMP_DISC_READ_LEN_BASE + umsg->rx_len; -+ msg.tx_buf[0] = CRASHDUMP_CMD; -+ msg.tx_buf[1] = 0x00; /* request byte for Host ID | Retry bit */ ++ msg = peci_get_xfer_msg(PECI_CRASHDUMP_DISC_WRITE_LEN, ++ PECI_CRASHDUMP_DISC_READ_LEN_BASE + ++ umsg->rx_len); ++ if (!msg) ++ return -ENOMEM; ++ ++ msg->addr = umsg->addr; ++ msg->tx_buf[0] = PECI_CRASHDUMP_CMD; ++ msg->tx_buf[1] = 0x00; /* request byte for Host ID | Retry bit */ + /* Host ID is 0 for PECI 3.0 */ -+ msg.tx_buf[2] = CRASHDUMP_DISC_VERSION; -+ msg.tx_buf[3] = CRASHDUMP_DISC_OPCODE; -+ msg.tx_buf[4] = umsg->subopcode; -+ msg.tx_buf[5] = umsg->param0; -+ msg.tx_buf[6] = (u8)umsg->param1; -+ msg.tx_buf[7] = (u8)(umsg->param1 >> 8); -+ msg.tx_buf[8] = umsg->param2; -+ -+ rc = peci_xfer_with_retries(adapter, &msg, false); -+ if (!rc) -+ memcpy(umsg->data, &msg.rx_buf[1], umsg->rx_len); -+ -+ return rc; ++ msg->tx_buf[2] = PECI_CRASHDUMP_DISC_VERSION; ++ msg->tx_buf[3] = PECI_CRASHDUMP_DISC_OPCODE; ++ msg->tx_buf[4] = umsg->subopcode; ++ msg->tx_buf[5] = umsg->param0; ++ msg->tx_buf[6] = (u8)umsg->param1; ++ msg->tx_buf[7] = (u8)(umsg->param1 >> 8); ++ msg->tx_buf[8] = umsg->param2; ++ ++ ret = peci_xfer_with_retries(adapter, msg, false); ++ if (!ret) ++ memcpy(umsg->data, &msg->rx_buf[1], umsg->rx_len); ++ ++ peci_put_xfer_msg(msg); ++ ++ return ret; +} + -+static int peci_ioctl_crashdump_get_frame(struct peci_adapter *adapter, -+ void *vmsg) ++static int peci_cmd_crashdump_get_frame(struct peci_adapter *adapter, ++ void *vmsg) +{ + struct peci_crashdump_get_frame_msg *umsg = vmsg; -+ struct peci_xfer_msg msg; -+ int rc = 0; ++ struct peci_xfer_msg *msg; ++ int ret; + + /* Per the EDS, the read length must be a qword or dqword */ + if (umsg->rx_len != 8 && umsg->rx_len != 16) { @@ -196,120 +216,52 @@ index fac8c72dcda8..62dada99afee 100644 + return -EINVAL; + } + -+ msg.addr = umsg->addr; -+ msg.tx_len = CRASHDUMP_GET_FRAME_WRITE_LEN; -+ msg.rx_len = CRASHDUMP_GET_FRAME_READ_LEN_BASE + umsg->rx_len; -+ msg.tx_buf[0] = CRASHDUMP_CMD; -+ msg.tx_buf[1] = 0x00; /* request byte for Host ID | Retry bit */ ++ msg = peci_get_xfer_msg(PECI_CRASHDUMP_GET_FRAME_WRITE_LEN, ++ PECI_CRASHDUMP_GET_FRAME_READ_LEN_BASE + ++ umsg->rx_len); ++ if (!msg) ++ return -ENOMEM; ++ ++ msg->addr = umsg->addr; ++ msg->tx_buf[0] = PECI_CRASHDUMP_CMD; ++ msg->tx_buf[1] = 0x00; /* request byte for Host ID | Retry bit */ + /* Host ID is 0 for PECI 3.0 */ -+ msg.tx_buf[2] = CRASHDUMP_GET_FRAME_VERSION; -+ msg.tx_buf[3] = CRASHDUMP_GET_FRAME_OPCODE; -+ msg.tx_buf[4] = (u8)umsg->param0; -+ msg.tx_buf[5] = (u8)(umsg->param0 >> 8); -+ msg.tx_buf[6] = (u8)umsg->param1; -+ msg.tx_buf[7] = (u8)(umsg->param1 >> 8); -+ msg.tx_buf[8] = (u8)umsg->param2; -+ msg.tx_buf[8] = (u8)(umsg->param2 >> 8); -+ -+ rc = peci_xfer_with_retries(adapter, &msg, false); -+ if (!rc) -+ memcpy(umsg->data, &msg.rx_buf[1], umsg->rx_len); -+ -+ return rc; ++ msg->tx_buf[2] = PECI_CRASHDUMP_GET_FRAME_VERSION; ++ msg->tx_buf[3] = PECI_CRASHDUMP_GET_FRAME_OPCODE; ++ msg->tx_buf[4] = (u8)umsg->param0; ++ msg->tx_buf[5] = (u8)(umsg->param0 >> 8); ++ msg->tx_buf[6] = (u8)umsg->param1; ++ msg->tx_buf[7] = (u8)(umsg->param1 >> 8); ++ msg->tx_buf[8] = (u8)umsg->param2; ++ msg->tx_buf[8] = (u8)(umsg->param2 >> 8); ++ ++ ret = peci_xfer_with_retries(adapter, msg, false); ++ if (!ret) ++ memcpy(umsg->data, &msg->rx_buf[1], umsg->rx_len); ++ ++ peci_put_xfer_msg(msg); ++ ++ return ret; +} + - typedef int (*peci_ioctl_fn_type)(struct peci_adapter *, void *); + typedef int (*peci_cmd_fn_type)(struct peci_adapter *, void *); - static const peci_ioctl_fn_type peci_ioctl_fn[PECI_CMD_MAX] = { -@@ -530,6 +724,9 @@ static const peci_ioctl_fn_type peci_ioctl_fn[PECI_CMD_MAX] = { - NULL, /* Reserved */ - peci_ioctl_rd_pci_cfg_local, - peci_ioctl_wr_pci_cfg_local, -+ peci_ioctl_rd_end_pt_cfg, -+ peci_ioctl_crashdump_disc, -+ peci_ioctl_crashdump_get_frame, + static const peci_cmd_fn_type peci_cmd_fn[PECI_CMD_MAX] = { +@@ -701,6 +921,9 @@ static const peci_cmd_fn_type peci_cmd_fn[PECI_CMD_MAX] = { + peci_cmd_wr_pci_cfg, + peci_cmd_rd_pci_cfg_local, + peci_cmd_wr_pci_cfg_local, ++ peci_cmd_rd_end_pt_cfg, ++ peci_cmd_crashdump_disc, ++ peci_cmd_crashdump_get_frame, }; /** -@@ -592,6 +789,9 @@ static long peci_ioctl(struct file *file, unsigned int iocmd, unsigned long arg) - case PECI_IOC_RD_PCI_CFG: - case PECI_IOC_RD_PCI_CFG_LOCAL: - case PECI_IOC_WR_PCI_CFG_LOCAL: -+ case PECI_IOC_RD_END_PT_CFG: -+ case PECI_IOC_CRASHDUMP_DISC: -+ case PECI_IOC_CRASHDUMP_GET_FRAME: - cmd = _IOC_NR(iocmd); - msg_len = _IOC_SIZE(iocmd); - break; diff --git a/include/uapi/linux/peci-ioctl.h b/include/uapi/linux/peci-ioctl.h -index a6dae71cbff5..5040d1cb4a3d 100644 +index 8467b2fbee1f..090b02c4de49 100644 --- a/include/uapi/linux/peci-ioctl.h +++ b/include/uapi/linux/peci-ioctl.h -@@ -31,6 +31,40 @@ - #define PKG_ID_MICROCODE_REV 0x0004 /* CPU Microcode Update Revision */ - #define PKG_ID_MACHINE_CHECK_STATUS 0x0005 /* Machine Check Status */ - -+/* RdEndPointCfg Parameters */ -+enum rdendptcfg_msg_type { -+ RDENDPTCFG_TYPE_LOCAL_PCI = 0x03, -+ RDENDPTCFG_TYPE_PCI = 0x04, -+ RDENDPTCFG_TYPE_MMIO = 0x05, -+}; -+ -+enum rdendptcfg_addr_type { -+ RDENDPTCFG_ADDR_TYPE_PCI = 0x04, -+ RDENDPTCFG_ADDR_TYPE_MMIO_D = 0x05, -+ RDENDPTCFG_ADDR_TYPE_MMIO_Q = 0x06, -+}; -+ -+/* Crashdump Parameters */ -+enum crashdump_agent { -+ CRASHDUMP_CORE = 0x00, -+ CRASHDUMP_TOR = 0x01, -+}; -+ -+enum crashdump_discovery_sub_opcode { -+ CRASHDUMP_ENABLED = 0x00, -+ CRASHDUMP_NUM_AGENTS = 0x01, -+ CRASHDUMP_AGENT_DATA = 0x02, -+}; -+ -+enum crashdump_agent_data_param { -+ CRASHDUMP_AGENT_ID = 0x00, -+ CRASHDUMP_AGENT_PARAM = 0x01, -+}; -+ -+enum crashdump_agent_param { -+ CRASHDUMP_PAYLOAD_SIZE = 0x00, -+}; -+ - /* RdPkgConfig Index */ - #define MBX_INDEX_CPU_ID 0 /* Package Identifier Read */ - #define MBX_INDEX_VR_DEBUG 1 /* VR Debug */ -@@ -136,6 +170,22 @@ - #define WRPCICFGLOCAL_READ_LEN 1 - #define WRPCICFGLOCAL_PECI_CMD 0xe5 - -+#define RDENDPTCFG_PCI_WRITE_LEN 0x0C -+#define RDENDPTCFG_MMIO_D_WRITE_LEN 0x0E -+#define RDENDPTCFG_MMIO_Q_WRITE_LEN 0x12 -+#define RDENDPTCFG_READ_LEN_BASE 1 -+#define RDENDPTCFG_PECI_CMD 0xC1 -+ -+#define CRASHDUMP_DISC_WRITE_LEN 9 -+#define CRASHDUMP_DISC_READ_LEN_BASE 1 -+#define CRASHDUMP_DISC_VERSION 1 -+#define CRASHDUMP_DISC_OPCODE 1 -+#define CRASHDUMP_GET_FRAME_WRITE_LEN 10 -+#define CRASHDUMP_GET_FRAME_READ_LEN_BASE 1 -+#define CRASHDUMP_GET_FRAME_VERSION 3 -+#define CRASHDUMP_GET_FRAME_OPCODE 3 -+#define CRASHDUMP_CMD 0x71 -+ - #define PECI_BUFFER_SIZE 32 - - /** -@@ -172,6 +222,9 @@ enum peci_cmd { +@@ -70,6 +70,9 @@ enum peci_cmd { PECI_CMD_WR_PCI_CFG, PECI_CMD_RD_PCI_CFG_LOCAL, PECI_CMD_WR_PCI_CFG_LOCAL, @@ -319,58 +271,101 @@ index a6dae71cbff5..5040d1cb4a3d 100644 PECI_CMD_MAX }; -@@ -366,6 +419,50 @@ struct peci_wr_pci_cfg_local_msg { - __u32 value; +@@ -420,6 +423,93 @@ struct peci_wr_pci_cfg_local_msg { + __u32 value; } __attribute__((__packed__)); +struct peci_rd_end_pt_cfg_msg { -+ __u8 addr; -+ __u8 msg_type; ++#define PECI_RDENDPTCFG_PCI_WRITE_LEN 0x0C ++#define PECI_RDENDPTCFG_MMIO_D_WRITE_LEN 0x0E ++#define PECI_RDENDPTCFG_MMIO_Q_WRITE_LEN 0x12 ++#define PECI_RDENDPTCFG_READ_LEN_BASE 1 ++#define PECI_RDENDPTCFG_CMD 0xC1 ++ ++ __u8 addr; ++ __u8 msg_type; ++#define PECI_RDENDPTCFG_TYPE_LOCAL_PCI 0x03 ++#define PECI_RDENDPTCFG_TYPE_PCI 0x04 ++#define PECI_RDENDPTCFG_TYPE_MMIO 0x05 ++ + union { + struct { -+ __u8 seg; -+ __u8 bus; -+ __u8 device; -+ __u8 function; -+ __u16 reg; ++ __u8 seg; ++ __u8 bus; ++ __u8 device; ++ __u8 function; ++ __u16 reg; + } pci_cfg; + struct { -+ __u8 seg; -+ __u8 bus; -+ __u8 device; -+ __u8 function; -+ __u8 bar; -+ __u8 addr_type; -+ __u64 offset; ++ __u8 seg; ++ __u8 bus; ++ __u8 device; ++ __u8 function; ++ __u8 bar; ++ __u8 addr_type; ++#define PECI_RDENDPTCFG_ADDR_TYPE_PCI 0x04 ++#define PECI_RDENDPTCFG_ADDR_TYPE_MMIO_D 0x05 ++#define PECI_RDENDPTCFG_ADDR_TYPE_MMIO_Q 0x06 ++ ++ __u64 offset; + } mmio; + } params; -+ __u8 rx_len; -+ __u8 data[8]; ++ __u8 rx_len; ++ __u8 padding[3]; ++ __u8 data[8]; +} __attribute__((__packed__)); + ++/* Crashdump Agent */ ++#define PECI_CRASHDUMP_CORE 0x00 ++#define PECI_CRASHDUMP_TOR 0x01 ++ ++/* Crashdump Agent Param */ ++#define PECI_CRASHDUMP_PAYLOAD_SIZE 0x00 ++ ++/* Crashdump Agent Data Param */ ++#define PECI_CRASHDUMP_AGENT_ID 0x00 ++#define PECI_CRASHDUMP_AGENT_PARAM 0x01 ++ +struct peci_crashdump_disc_msg { -+ __u8 addr; -+ __u8 subopcode; -+ __u8 param0; -+ __u16 param1; -+ __u8 param2; -+ __u8 rx_len; -+ __u8 data[8]; ++ __u8 addr; ++ __u8 subopcode; ++#define PECI_CRASHDUMP_ENABLED 0x00 ++#define PECI_CRASHDUMP_NUM_AGENTS 0x01 ++#define PECI_CRASHDUMP_AGENT_DATA 0x02 ++ ++ __u8 param0; ++ __u8 padding; ++ __u16 param1; ++ __u8 param2; ++ __u8 rx_len; ++ __u8 data[8]; +} __attribute__((__packed__)); + +struct peci_crashdump_get_frame_msg { -+ __u8 addr; -+ __u16 param0; -+ __u16 param1; -+ __u16 param2; -+ __u8 rx_len; -+ __u8 data[16]; ++#define PECI_CRASHDUMP_DISC_WRITE_LEN 9 ++#define PECI_CRASHDUMP_DISC_READ_LEN_BASE 1 ++#define PECI_CRASHDUMP_DISC_VERSION 1 ++#define PECI_CRASHDUMP_DISC_OPCODE 1 ++#define PECI_CRASHDUMP_GET_FRAME_WRITE_LEN 10 ++#define PECI_CRASHDUMP_GET_FRAME_READ_LEN_BASE 1 ++#define PECI_CRASHDUMP_GET_FRAME_VERSION 3 ++#define PECI_CRASHDUMP_GET_FRAME_OPCODE 3 ++#define PECI_CRASHDUMP_CMD 0x71 ++ ++ __u8 addr; ++ __u8 padding0; ++ __u16 param0; ++ __u16 param1; ++ __u16 param2; ++ __u8 rx_len; ++ __u8 padding1[3]; ++ __u8 data[16]; +} __attribute__((__packed__)); + #define PECI_IOC_BASE 0xb7 #define PECI_IOC_XFER \ -@@ -400,4 +497,16 @@ struct peci_wr_pci_cfg_local_msg { +@@ -460,4 +550,16 @@ struct peci_wr_pci_cfg_local_msg { _IOWR(PECI_IOC_BASE, PECI_CMD_WR_PCI_CFG_LOCAL, \ struct peci_wr_pci_cfg_local_msg) diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0041-Enable-passthrough-based-gpio-character-device.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0041-Enable-passthrough-based-gpio-character-device.patch new file mode 100644 index 000000000..9e7757011 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0041-Enable-passthrough-based-gpio-character-device.patch @@ -0,0 +1,287 @@ +From d34efc982a9206db87da49be3d9b1e20f59be56f Mon Sep 17 00:00:00 2001 +From: Kuiying Wang <kuiying.wang@intel.com> +Date: Thu, 31 Jan 2019 17:47:39 +0800 +Subject: [PATCH] Enable passthrough based gpio character device. + +Signed-off-by: Kuiying Wang <kuiying.wang@intel.com> +--- + drivers/gpio/gpio-aspeed.c | 47 ++++++++++++++++++++++- + drivers/gpio/gpiolib.c | 51 +++++++++++++++++++++++-- + drivers/gpio/gpiolib.h | 1 + + include/linux/gpio/consumer.h | 9 +++++ + include/linux/pinctrl/pinconf-generic.h | 2 + + include/uapi/linux/gpio.h | 1 + + 6 files changed, 106 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c +index 2342e154029b..06fd95197684 100644 +--- a/drivers/gpio/gpio-aspeed.c ++++ b/drivers/gpio/gpio-aspeed.c +@@ -17,9 +17,11 @@ + #include <linux/init.h> + #include <linux/io.h> + #include <linux/kernel.h> ++#include <linux/mfd/syscon.h> + #include <linux/module.h> + #include <linux/pinctrl/consumer.h> + #include <linux/platform_device.h> ++#include <linux/regmap.h> + #include <linux/spinlock.h> + #include <linux/string.h> + +@@ -58,6 +60,7 @@ struct aspeed_gpio { + struct gpio_chip chip; + spinlock_t lock; + void __iomem *base; ++ struct regmap *scu; + int irq; + const struct aspeed_gpio_config *config; + +@@ -91,6 +94,13 @@ struct aspeed_gpio_bank { + * and thus can be used to read back what was last written + * reliably. + */ ++#define SCU8C 0x8C /* Multi-function Pin Control #4 */ ++#define PASS_THROUGH1 32 ++#define PASS_THROUGH2 34 ++#define PASS_THROUGH2_MASK 0x2000 ++#define PASS_THROUGH1_MASK 0x1000 ++#define PASS_THROUGH2_ON 0x2000 ++#define PASS_THROUGH1_ON 0x1000 + + static const int debounce_timers[4] = { 0x00, 0x50, 0x54, 0x58 }; + +@@ -988,12 +998,38 @@ static int set_debounce(struct gpio_chip *chip, unsigned int offset, + return disable_debounce(chip, offset); + } + ++static int aspeed_gpio_pass_through(struct gpio_chip *chip, unsigned int offset, ++ unsigned long param) ++{ ++ struct aspeed_gpio *gpio = gpiochip_get_data(chip); ++ u32 value; ++ ++ if (!gpio->scu) ++ return -ENOTSUPP; ++ if (param == PIN_CONFIG_PASS_THROUGH_ENABLE){ ++ if (offset == PASS_THROUGH2){ ++ regmap_update_bits(gpio->scu, SCU8C, PASS_THROUGH2_MASK, PASS_THROUGH2_ON); ++ } else if (offset == PASS_THROUGH1){ ++ regmap_update_bits(gpio->scu, SCU8C, PASS_THROUGH1_MASK, PASS_THROUGH1_ON); ++ } ++ } else if (param == PIN_CONFIG_PASS_THROUGH_DISABLE){ ++ if (offset == PASS_THROUGH2){ ++ regmap_update_bits(gpio->scu, SCU8C, PASS_THROUGH2_MASK, ~(PASS_THROUGH2_ON)); ++ } else if (offset == PASS_THROUGH1){ ++ regmap_update_bits(gpio->scu, SCU8C, PASS_THROUGH1_MASK, ~(PASS_THROUGH1_ON)); ++ } ++ } else { ++ return -ENOTSUPP; ++ } ++ ++ return 0; ++} ++ + static int aspeed_gpio_set_config(struct gpio_chip *chip, unsigned int offset, + unsigned long config) + { + unsigned long param = pinconf_to_config_param(config); + u32 arg = pinconf_to_config_argument(config); +- + if (param == PIN_CONFIG_INPUT_DEBOUNCE) + return set_debounce(chip, offset, arg); + else if (param == PIN_CONFIG_BIAS_DISABLE || +@@ -1006,6 +1042,9 @@ static int aspeed_gpio_set_config(struct gpio_chip *chip, unsigned int offset, + return -ENOTSUPP; + else if (param == PIN_CONFIG_PERSIST_STATE) + return aspeed_gpio_reset_tolerance(chip, offset, arg); ++ else if (param == PIN_CONFIG_PASS_THROUGH_ENABLE || ++ param == PIN_CONFIG_PASS_THROUGH_DISABLE) ++ return aspeed_gpio_pass_through(chip, offset, param); + + return -ENOTSUPP; + } +@@ -1167,7 +1206,11 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) + gpio->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(gpio->base)) + return PTR_ERR(gpio->base); +- ++ gpio->scu = syscon_regmap_lookup_by_compatible("aspeed,ast2500-scu"); ++ if (IS_ERR(gpio->scu)) { ++ dev_err(&pdev->dev, "Failed to find SCU regmap\n"); ++ gpio->scu = NULL; ++ } + spin_lock_init(&gpio->lock); + + gpio_id = of_match_node(aspeed_gpio_of_table, pdev->dev.of_node); +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index a8e01d99919c..21eeca17583d 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -419,6 +419,7 @@ struct linehandle_state { + GPIOHANDLE_REQUEST_OUTPUT | \ + GPIOHANDLE_REQUEST_ACTIVE_LOW | \ + GPIOHANDLE_REQUEST_OPEN_DRAIN | \ ++ GPIOHANDLE_REQUEST_PASS_THROUGH | \ + GPIOHANDLE_REQUEST_OPEN_SOURCE) + + static long linehandle_ioctl(struct file *filep, unsigned int cmd, +@@ -519,7 +520,6 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) + return -EINVAL; + + lflags = handlereq.flags; +- + /* Return an error if an unknown flag is set */ + if (lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) + return -EINVAL; +@@ -579,6 +579,8 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) + set_bit(FLAG_OPEN_DRAIN, &desc->flags); + if (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE) + set_bit(FLAG_OPEN_SOURCE, &desc->flags); ++ if (lflags & GPIOHANDLE_REQUEST_PASS_THROUGH) ++ set_bit(FLAG_PASS_THROUGH, &desc->flags); + + ret = gpiod_set_transitory(desc, false); + if (ret < 0) +@@ -598,6 +600,11 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) + ret = gpiod_direction_input(desc); + if (ret) + goto out_free_descs; ++ } else if (lflags & GPIOHANDLE_REQUEST_PASS_THROUGH) { ++ int val = !!handlereq.default_values[i]; ++ ret = gpiod_direction_pass_through(desc, val); ++ if (ret) ++ goto out_free_descs; + } + dev_dbg(&gdev->dev, "registered chardev handle for line %d\n", + offset); +@@ -1010,7 +1017,6 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + struct gpio_device *gdev = filp->private_data; + struct gpio_chip *chip = gdev->chip; + void __user *ip = (void __user *)arg; +- + /* We fail any subsequent ioctl():s when the chip is gone */ + if (!chip) + return -ENODEV; +@@ -1018,7 +1024,6 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + /* Fill in the struct and pass to userspace */ + if (cmd == GPIO_GET_CHIPINFO_IOCTL) { + struct gpiochip_info chipinfo; +- + memset(&chipinfo, 0, sizeof(chipinfo)); + + strncpy(chipinfo.name, dev_name(&gdev->dev), +@@ -2643,6 +2648,46 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) + } + EXPORT_SYMBOL_GPL(gpiod_direction_output); + ++/** ++ * gpiod_direction_pass_through - set the GPIO direction to pass-through ++ * @desc: GPIO to set to pass-through ++ * ++ * Set the direction of the passed GPIO to passthrough. ++ * ++ * Return 0 in case of success, else an error code. ++ */ ++int gpiod_direction_pass_through(struct gpio_desc *desc, int val) ++{ ++ struct gpio_chip *gc; ++ ++ VALIDATE_DESC(desc); ++ /* GPIOs used for IRQs shall not be set as pass-through */ ++ if (test_bit(FLAG_USED_AS_IRQ, &desc->flags)) { ++ gpiod_err(desc, ++ "%s: tried to set a GPIO tied to an IRQ as pass-through\n", ++ __func__); ++ return -EIO; ++ } ++ gc = desc->gdev->chip; ++ val = !!val; ++ if (test_bit(FLAG_PASS_THROUGH, &desc->flags)) { ++ if (val) ++ gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc), ++ PIN_CONFIG_PASS_THROUGH_ENABLE); ++ else ++ gpio_set_drive_single_ended(gc, gpio_chip_hwgpio(desc), ++ PIN_CONFIG_PASS_THROUGH_DISABLE); ++ } else { ++ gpiod_err(desc, ++ "%s: desc->flags is not set to FLAG_PASS_THROUGH\n", ++ __func__); ++ return -EIO; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(gpiod_direction_pass_through); ++ + /** + * gpiod_set_debounce - sets @debounce time for a GPIO + * @desc: descriptor of the GPIO for which to set debounce time +diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h +index a7e49fef73d4..b143ee47870a 100644 +--- a/drivers/gpio/gpiolib.h ++++ b/drivers/gpio/gpiolib.h +@@ -210,6 +210,7 @@ struct gpio_desc { + #define FLAG_IS_OUT 1 + #define FLAG_EXPORT 2 /* protected by sysfs_lock */ + #define FLAG_SYSFS 3 /* exported via /sys/class/gpio/control */ ++#define FLAG_PASS_THROUGH 4 /*Gpio is passthrough type*/ + #define FLAG_ACTIVE_LOW 6 /* value has active low */ + #define FLAG_OPEN_DRAIN 7 /* Gpio is open drain type */ + #define FLAG_OPEN_SOURCE 8 /* Gpio is open source type */ +diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h +index 21ddbe440030..96551839c191 100644 +--- a/include/linux/gpio/consumer.h ++++ b/include/linux/gpio/consumer.h +@@ -99,6 +99,7 @@ void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs); + int gpiod_get_direction(struct gpio_desc *desc); + int gpiod_direction_input(struct gpio_desc *desc); + int gpiod_direction_output(struct gpio_desc *desc, int value); ++int gpiod_direction_pass_through(struct gpio_desc *desc, int val); + int gpiod_direction_output_raw(struct gpio_desc *desc, int value); + + /* Value get/set from non-sleeping context */ +@@ -314,6 +315,14 @@ static inline int gpiod_direction_output(struct gpio_desc *desc, int value) + WARN_ON(1); + return -ENOSYS; + } ++ ++static inline int gpiod_direction_pass_through(struct gpio_desc *desc, int val) ++{ ++ /* GPIO can never have been requested */ ++ WARN_ON(1); ++ return -ENOSYS; ++} ++ + static inline int gpiod_direction_output_raw(struct gpio_desc *desc, int value) + { + /* GPIO can never have been requested */ +diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h +index 6c0680641108..59f0cbabb685 100644 +--- a/include/linux/pinctrl/pinconf-generic.h ++++ b/include/linux/pinctrl/pinconf-generic.h +@@ -124,6 +124,8 @@ enum pin_config_param { + PIN_CONFIG_SLEW_RATE, + PIN_CONFIG_SKEW_DELAY, + PIN_CONFIG_PERSIST_STATE, ++ PIN_CONFIG_PASS_THROUGH_ENABLE, ++ PIN_CONFIG_PASS_THROUGH_DISABLE, + PIN_CONFIG_END = 0x7F, + PIN_CONFIG_MAX = 0xFF, + }; +diff --git a/include/uapi/linux/gpio.h b/include/uapi/linux/gpio.h +index 1bf6e6df084b..384ced158412 100644 +--- a/include/uapi/linux/gpio.h ++++ b/include/uapi/linux/gpio.h +@@ -62,6 +62,7 @@ struct gpioline_info { + #define GPIOHANDLE_REQUEST_ACTIVE_LOW (1UL << 2) + #define GPIOHANDLE_REQUEST_OPEN_DRAIN (1UL << 3) + #define GPIOHANDLE_REQUEST_OPEN_SOURCE (1UL << 4) ++#define GPIOHANDLE_REQUEST_PASS_THROUGH (1UL << 5) + + /** + * struct gpiohandle_request - Information about a GPIO handle request +-- +2.19.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch new file mode 100644 index 000000000..901d63645 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch @@ -0,0 +1,105 @@ +From ca4f6555620212ffccd943ea4c58e7ee7b1b0571 Mon Sep 17 00:00:00 2001 +From: Jae Hyun Yoo <jae.hyun.yoo@intel.com> +Date: Thu, 7 Mar 2019 15:17:40 -0800 +Subject: [PATCH] Add bus-timeout-ms and #retries device tree properties + +BMC uses I2C bus 7 as a PMBus channel to communicate with PSUs, +also ME uses this bus as SMLink to control PSUs so this bus is +managed by multi-masters. In this use case, some arbitration errors +are expected so we need to add retry logic. And PMBus subsystem +uses I2C bus in kernel internally so retry logic should be +supported in kernel level. + +To support the use case, this commit adds 'bus-timeout-ms' and +'#retries' device tree properties to set the bus specific +parameters at kernel boot time without using any additional ioctls +from user space. + +This patch would not be accepted by I2C maintainer in linux +upstream because he doesn't like adding these legacy properties +into device tree, so keep it only in downstream. + +Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com> +--- + Documentation/devicetree/bindings/i2c/i2c-aspeed.txt | 3 +++ + Documentation/devicetree/bindings/i2c/i2c.txt | 6 ++++++ + drivers/i2c/busses/i2c-aspeed.c | 1 - + drivers/i2c/i2c-core-base.c | 12 ++++++++++-- + 4 files changed, 19 insertions(+), 3 deletions(-) + +diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt +index 8fbd8633a387..7da7e813b2b0 100644 +--- a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt ++++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt +@@ -16,6 +16,9 @@ Optional Properties: + - bus-frequency : frequency of the bus clock in Hz defaults to 100 kHz when not + specified + - multi-master : states that there is another master active on this bus. ++- bus-timeout-ms: bus timeout in milliseconds defaults to 1 second when not ++ specified. ++- #retries : Number of retries for master transfer. + + Example: + +diff --git a/Documentation/devicetree/bindings/i2c/i2c.txt b/Documentation/devicetree/bindings/i2c/i2c.txt +index 11263982470e..bdead91f82a4 100644 +--- a/Documentation/devicetree/bindings/i2c/i2c.txt ++++ b/Documentation/devicetree/bindings/i2c/i2c.txt +@@ -80,6 +80,12 @@ wants to support one of the below features, it should adapt the bindings below. + Names of map programmable addresses. + It can contain any map needing another address than default one. + ++- bus-timeout-ms ++ Bus timeout in milliseconds. ++ ++- #retries ++ Number of retries for master transfer. ++ + Binding may contain optional "interrupts" property, describing interrupts + used by the device. I2C core will assign "irq" interrupt (or the very first + interrupt if not using interrupt names) as primary interrupt for the slave. +diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c +index 506d867b43d9..84237c5d0aca 100644 +--- a/drivers/i2c/busses/i2c-aspeed.c ++++ b/drivers/i2c/busses/i2c-aspeed.c +@@ -1012,7 +1012,6 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) + spin_lock_init(&bus->lock); + init_completion(&bus->cmd_complete); + bus->adap.owner = THIS_MODULE; +- bus->adap.retries = 0; + bus->adap.algo = &aspeed_i2c_algo; + bus->adap.dev.parent = &pdev->dev; + bus->adap.dev.of_node = pdev->dev.of_node; +diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c +index 728b818501b1..17cf0fb037ac 100644 +--- a/drivers/i2c/i2c-core-base.c ++++ b/drivers/i2c/i2c-core-base.c +@@ -1232,6 +1232,7 @@ static void i2c_adapter_hold_timer_callback(struct timer_list *t) + + static int i2c_register_adapter(struct i2c_adapter *adap) + { ++ u32 bus_timeout_ms = 0; + int res = -EINVAL; + + /* Can't register until after driver model init */ +@@ -1258,8 +1259,15 @@ static int i2c_register_adapter(struct i2c_adapter *adap) + INIT_LIST_HEAD(&adap->userspace_clients); + + /* Set default timeout to 1 second if not already set */ +- if (adap->timeout == 0) +- adap->timeout = HZ; ++ if (adap->timeout == 0) { ++ device_property_read_u32(&adap->dev, "bus-timeout-ms", ++ &bus_timeout_ms); ++ adap->timeout = bus_timeout_ms ? ++ msecs_to_jiffies(bus_timeout_ms) : HZ; ++ } ++ ++ /* Set retries count if it has the property setting */ ++ device_property_read_u32(&adap->dev, "#retries", &adap->retries); + + /* register soft irqs for Host Notify */ + res = i2c_setup_host_notify_irq_domain(adap); +-- +2.7.4 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend index cdf4325d9..e08672d2d 100644 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend @@ -11,7 +11,7 @@ SRC_URI += " \ file://0007-New-flash-map-for-intel.patch \ file://0008-Add-ASPEED-SGPIO-driver.patch \ file://0009-SGPIO-DT-and-pinctrl-fixup.patch \ - file://0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch \ + file://0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch \ file://0019-Add-I2C-IPMB-support.patch \ file://0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch \ file://0022-Add-AST2500-eSPI-driver.patch \ @@ -28,4 +28,6 @@ SRC_URI += " \ file://0038-media-aspeed-backport-ikvm-patches.patch \ file://0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch \ file://0040-i2c-Add-mux-hold-unhold-msg-types.patch \ + file://0041-Enable-passthrough-based-gpio-character-device.patch \ + file://0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch \ " diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend index 2ae5eeb64..c4d5ba9ae 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend @@ -1,6 +1,6 @@ # this is here just to bump faster than upstream SRC_URI = "git://github.com/openbmc/entity-manager.git" -SRCREV = "9945ddffc67a9e564a92a3c0bddf2a2d7dc70b97" +SRCREV = "623de6cbb49070085bb97b98ba379206bac98a7a" FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0019-Creating-the-Session-interface-for-Host-and-LAN.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0019-Creating-the-Session-interface-for-Host-and-LAN.patch new file mode 100644 index 000000000..e1208cf5b --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0019-Creating-the-Session-interface-for-Host-and-LAN.patch @@ -0,0 +1,126 @@ +From f805522921d69eb4ea70248fe7e54557363aacea Mon Sep 17 00:00:00 2001 +From: Suryakanth Sekar <suryakanth.sekar@linux.intel.com> +Date: Sat, 2 Mar 2019 03:31:09 +0530 +Subject: [PATCH] Creating the Session interface- for Host and LAN + +Defined all needed session properites to manage the session in +host and also in LAN + +Change-Id: Ic7cccfc3333a602ee07fcd60077ec58fd8f06304 +Signed-off-by: Suryakanth Sekar <suryakanth.sekar@linux.intel.com> +--- + xyz/openbmc_project/Session/Info.interface.yaml | 56 +++++++++++++++++++++++++ + xyz/openbmc_project/Session/README.md | 38 +++++++++++++++++ + 2 files changed, 94 insertions(+) + create mode 100644 xyz/openbmc_project/Session/Info.interface.yaml + create mode 100644 xyz/openbmc_project/Session/README.md + +diff --git a/xyz/openbmc_project/Session/Info.interface.yaml b/xyz/openbmc_project/Session/Info.interface.yaml +new file mode 100644 +index 0000000..fbb5a45 +--- /dev/null ++++ b/xyz/openbmc_project/Session/Info.interface.yaml +@@ -0,0 +1,56 @@ ++description: > ++ Provides properties for session objects. ++ As communication to this service is done through authenticated ++ & authorized session, there won't be any validation for the both. ++ ++properties: ++ - name: SessionHandle ++ type: byte ++ description: > ++ Session Handle,unique number to locate the session. ++ errors: ++ - xyz.openbmc_project.Common.Error.InternalFailure ++ - name: ChannelNum ++ type: byte ++ description: > ++ channelnumber which session is created. ++ errors: ++ - xyz.openbmc_project.Common.Error.InternalFailure ++ - name: CurrentPrivilege ++ type: byte ++ description: > ++ Privilege of the session. ++ errors: ++ - xyz.openbmc_project.Common.Error.InternalFailure ++ - name: RemoteIPAddr ++ type: uint32 ++ description: > ++ Remote IP address. ++ errors: ++ - xyz.openbmc_project.Common.Error.InternalFailure ++ - name: RemotePort ++ type: uint16 ++ description: > ++ Remote IP Port. ++ errors: ++ - xyz.openbmc_project.Common.Error.InternalFailure ++ - name: RemoteMACAddress ++ type: array[byte] ++ description: > ++ Remote MAC address. ++ errors: ++ - xyz.openbmc_project.Common.Error.InternalFailure ++ - name: UserID ++ type: byte ++ description: > ++ Session created by given user ID. ++ errors: ++ - xyz.openbmc_project.Common.Error.InternalFailure ++ - name: State ++ type: byte ++ description: > ++ Session state. ++ errors: ++ - xyz.openbmc_project.Common.Error.InternalFailure ++ ++# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 +diff --git a/xyz/openbmc_project/Session/README.md b/xyz/openbmc_project/Session/README.md +new file mode 100644 +index 0000000..f220885 +--- /dev/null ++++ b/xyz/openbmc_project/Session/README.md +@@ -0,0 +1,38 @@ ++# Session Management ++ ++## Overview ++Session Manager service exposes D-Bus methods for session management operations. ++ ++### Session Manager Interface ++Session manager interface `xyz.openbmc_project.Session.Manager` provides following ++methods, properties and signals. ++ ++#### xyz.openbmc_project.Session.Manager interface ++##### methods ++* CreateSession - To create new session object to the system. ++ ++##### properties ++* MaxSessionSupported - To list all the groups supported in the system. ++* ActiveSessionCount - To hold the no of active sessions. ++ ++Session manager service will create session objects for every session ++in the system under object path `/xyz/openbmc_project/session/<SessionIndex>`. ++Each session object can be handled through 'org.freedesktop.DBus.ObjectManager'. ++session object will expose following properties and methods. ++ ++#### xyz.openbmc_project.Session.Info interface ++##### properties ++* SessionID - Session ID,random unique number to locate the session. ++* Channel - Session created Channel. ++* SessionPrivilege - Privilege of the session. ++* RemoteIPAddr – Remote IP address. ++* RemotePort - Remote Port address. ++* RemoteMACAddress -Remote MAC Address. ++* UserID - Session created by given user id. ++ ++ ++ ++#### xyz.openbmc_project.Object.Delete ++#### methods ++* Delete - To delete the session object in the system. ++ +-- +2.7.4 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0020-Create-dbus-interface-for-SOL-commands.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0020-Create-dbus-interface-for-SOL-commands.patch new file mode 100644 index 000000000..68d2c92b7 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces/0020-Create-dbus-interface-for-SOL-commands.patch @@ -0,0 +1,76 @@ +From 2820ca36ab21c52341cdbde477756f960eaeb68b Mon Sep 17 00:00:00 2001 +From: Cheng C Yang <cheng.c.yang@intel.com> +Date: Wed, 13 Mar 2019 11:19:07 +0800 +Subject: [PATCH] Create dbus interface for SOL commands + +Create dbus properties for Set/Get SOL config parameter command. +Some platforms need to call Set/Get SOL config parameter command +through KCS, and since sol manager in net-ipmid cannot be accessed +by commands in host-ipmid, need to create a dbus interface in +phospher-settings to transfer properties from host-ipmid to +net-ipmid. + +TestedBy: +With the related code change in net-ipmid, busctl introspect +xyz.openbmc_project.Ipmi.SOL /xyz/openbmc_project/SOL +can show all the properties needed. + +Signed-off-by: Cheng C Yang <cheng.c.yang@intel.com> +--- + xyz/openbmc_project/Ipmi/SOL.interface.yaml | 44 ++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + create mode 100644 xyz/openbmc_project/Ipmi/SOL.interface.yaml + +diff --git a/xyz/openbmc_project/Ipmi/SOL.interface.yaml b/xyz/openbmc_project/Ipmi/SOL.interface.yaml +new file mode 100644 +index 0000000..94db59f +--- /dev/null ++++ b/xyz/openbmc_project/Ipmi/SOL.interface.yaml +@@ -0,0 +1,44 @@ ++description: > ++ SOL properties use for Get/Set SOL config parameter command in host-ipmid ++ sending config to SOL process in net-ipmid. ++ Since some platforms need to access Get/Set SOL config parameter command ++ through KCS, and current sol manager is implemented in net-ipmid and ++ cannot be accessed by host-ipmid, add a dbus interface for host-ipmid ++ command to transfer properties to net-ipmid. ++ This interface will be implemented in phosphor-settings. ++properties: ++ - name: Progress ++ type: byte ++ description: > ++ Set In Progress property, indicate when any parameters are being ++ updated. ++ - name: Enable ++ type: boolean ++ description: > ++ SOL Enable property, this controls whether the SOL payload type ++ can be activated. ++ - name: Authentication ++ type: byte ++ description: > ++ If SOL enable Force Payload Encryption and Authenticaton. ++ And the minimun operating privilege level SOL required. ++ - name: AccumulateIntervalMS ++ type: byte ++ description: > ++ Character Accumulate Interval in 5ms increments. ++ BMC will wait this time before transmitting a packet. ++ - name: Threshold ++ type: byte ++ description: > ++ BMC will automatically send an SOL character data packet containing ++ this number of characters as soon as this number of characters ++ (or greater) has been accepted from the baseboard serial controller. ++ - name: RetryCount ++ type: byte ++ description: > ++ Packet will be dropped if no ACK/NACK received by time retries ++ expire. ++ - name: RetryIntervalMS ++ type: byte ++ description: > ++ Retry Interval in 10ms increments. +-- +2.16.2 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces_%.bbappend index 2449d9225..d32650a3a 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-dbus-interfaces_%.bbappend @@ -13,4 +13,6 @@ SRC_URI += "file://0002-Modify-Dbus-for-IPv6.patch \ file://0016-Add-DBUS-interface-of-SMBIOS-MDR-V2.patch \ file://0017-Add-shutdown-policy-interface-for-get-set-shutdown-p.patch \ file://0018-Define-post-code-interfaces-for-post-code-manager.patch \ + file://0019-Creating-the-Session-interface-for-Host-and-LAN.patch \ + file://0020-Create-dbus-interface-for-SOL-commands.patch \ " diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend index 3ea7b96b1..e085d244e 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend @@ -5,4 +5,4 @@ SYSTEMD_SERVICE_${PN} = "phosphor-pid-control.service" EXTRA_OECONF = "--enable-configure-dbus=yes" SRC_URI = "git://github.com/openbmc/phosphor-pid-control.git" -SRCREV = "f42741197ec807e0436a5e519ccff18519c67248" +SRCREV = "e6e6f62680cf77c0a742ca806609d10103273b07" diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0001-image_verify-Add-support-for-OpenSSL-1.1.0.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0001-image_verify-Add-support-for-OpenSSL-1.1.0.patch deleted file mode 100644 index c5850473c..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager/0001-image_verify-Add-support-for-OpenSSL-1.1.0.patch +++ /dev/null @@ -1,130 +0,0 @@ -From fa124c7944088624d40d6b265bac0651bd8235bb Mon Sep 17 00:00:00 2001 -From: Adriana Kobylak <anoo@us.ibm.com> -Date: Thu, 6 Sep 2018 13:15:34 -0500 -Subject: [PATCH] image_verify: Add support for OpenSSL 1.1.0 - -With OpenSSL 1.1.0, some of the functions were renamed, for -example EVP_MD_CTX_create() and EVP_MD_CTX_destroy() were -renamed to EVP_MD_CTX_new() and EVP_MD_CTX_free(). -Reference: https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes -Abstract them to support old and new APIs. - -Resolves openbmc/openbmc#3136 - -Tested: Verified the signature verification was successful. - -Change-Id: I2297243fdd652055fe9ea88f26eb2dcf473d24e6 -Signed-off-by: Adriana Kobylak <anoo@us.ibm.com> - -%% original patch: 0001-image_verify-Add-support-for-OpenSSL-1.1.0.patch ---- - Makefile.am | 8 ++++++-- - image_verify.cpp | 2 +- - image_verify.hpp | 1 + - utils.cpp | 29 +++++++++++++++++++++++++++++ - utils.hpp | 15 +++++++++++++++ - 5 files changed, 52 insertions(+), 3 deletions(-) - create mode 100644 utils.cpp - create mode 100644 utils.hpp - -diff --git a/Makefile.am b/Makefile.am -index adba0e4..21b556f 100755 ---- a/Makefile.am -+++ b/Makefile.am -@@ -42,8 +42,12 @@ phosphor_image_updater_SOURCES = \ - include ubi/Makefile.am.include - - if WANT_SIGNATURE_VERIFY_BUILD --noinst_HEADERS += image_verify.hpp --phosphor_image_updater_SOURCES += image_verify.cpp -+noinst_HEADERS += \ -+ image_verify.hpp \ -+ utils.hpp -+phosphor_image_updater_SOURCES += \ -+ image_verify.cpp \ -+ utils.cpp - endif - - if WANT_SYNC -diff --git a/image_verify.cpp b/image_verify.cpp -index 7d59910..ba6b24d 100644 ---- a/image_verify.cpp -+++ b/image_verify.cpp -@@ -216,7 +216,7 @@ bool Signature::verifyFile(const fs::path& file, const fs::path& sigFile, - EVP_PKEY_assign_RSA(pKeyPtr.get(), publicRSA); - - // Initializes a digest context. -- EVP_MD_CTX_Ptr rsaVerifyCtx(EVP_MD_CTX_create(), ::EVP_MD_CTX_destroy); -+ EVP_MD_CTX_Ptr rsaVerifyCtx(EVP_MD_CTX_new(), ::EVP_MD_CTX_free); - - // Adds all digest algorithms to the internal table - OpenSSL_add_all_digests(); -diff --git a/image_verify.hpp b/image_verify.hpp -index cbd0e39..22ee5f9 100644 ---- a/image_verify.hpp -+++ b/image_verify.hpp -@@ -1,4 +1,5 @@ - #pragma once -+#include "utils.hpp" - #include <openssl/rsa.h> - #include <openssl/evp.h> - #include <openssl/pem.h> -diff --git a/utils.cpp b/utils.cpp -new file mode 100644 -index 0000000..95fc2e0 ---- /dev/null -+++ b/utils.cpp -@@ -0,0 +1,29 @@ -+#include "utils.hpp" -+ -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+ -+#include <string.h> -+ -+static void* OPENSSL_zalloc(size_t num) -+{ -+ void* ret = OPENSSL_malloc(num); -+ -+ if (ret != NULL) -+ { -+ memset(ret, 0, num); -+ } -+ return ret; -+} -+ -+EVP_MD_CTX* EVP_MD_CTX_new(void) -+{ -+ return (EVP_MD_CTX*)OPENSSL_zalloc(sizeof(EVP_MD_CTX)); -+} -+ -+void EVP_MD_CTX_free(EVP_MD_CTX* ctx) -+{ -+ EVP_MD_CTX_cleanup(ctx); -+ OPENSSL_free(ctx); -+} -+ -+#endif // OPENSSL_VERSION_NUMBER < 0x10100000L -diff --git a/utils.hpp b/utils.hpp -new file mode 100644 -index 0000000..90569bf ---- /dev/null -+++ b/utils.hpp -@@ -0,0 +1,15 @@ -+#pragma once -+ -+// With OpenSSL 1.1.0, some functions were deprecated. Need to abstract them -+// to make the code backward compatible with older OpenSSL veresions. -+// Reference: https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+ -+#include <openssl/evp.h> -+ -+extern "C" { -+EVP_MD_CTX* EVP_MD_CTX_new(void); -+void EVP_MD_CTX_free(EVP_MD_CTX* ctx); -+} -+ -+#endif // OPENSSL_VERSION_NUMBER < 0x10100000L --- -2.7.4 - diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend index d19da526e..80c5ea9d3 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/flash/phosphor-software-manager_%.bbappend @@ -4,7 +4,7 @@ EXTRA_OECONF += "--enable-fwupd_script" SYSTEMD_SERVICE_${PN}-updater += "fwupd@.service" SRC_URI_remove = "git://github.com/openbmc/phosphor-bmc-code-mgmt" -SRC_URI += "git://git@github.com/Intel-BMC/phosphor-bmc-code-mgmt.git;protocol=ssh" +SRC_URI += "git://git@github.com/Intel-BMC/phosphor-bmc-code-mgmt;protocol=ssh" SRCREV = "f8f76c29dbe2806a6eacd15847563cdf7f7567f4" #Currently enforcing image signature validation only for PFR images diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/gpiodaemon/gpiodaemon.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/gpiodaemon/gpiodaemon.bb index 6d6762fc9..0ff44cf73 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/gpiodaemon/gpiodaemon.bb +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/gpiodaemon/gpiodaemon.bb @@ -10,7 +10,7 @@ LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e" SRC_URI = "git://git@github.com/Intel-BMC/provingground.git;protocol=ssh" -SRCREV = "3cc86d6c536b4c5ee7afb5447837b83ce8b3d149" +SRCREV = "c927781ad3ca1408cd7fb0b7cc2538ea10ded76b" inherit cmake systemd SYSTEMD_SERVICE_${PN} = "gpiodaemon.service" diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-channel-inventory%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-channel-inventory%.bbappend deleted file mode 100644 index d79704ec6..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-channel-inventory%.bbappend +++ /dev/null @@ -1,4 +0,0 @@ -FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" - -SRC_URI += " file://channel.yaml \ - " diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-channel-inventory%/channel.yaml b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-channel-inventory%/channel.yaml deleted file mode 100644 index 032e05127..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-channel-inventory%/channel.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# Channel Number (must be unique) is the key -1: - # ifName the ethernet device name (used in the dbus path) - ifName: eth0 -2: - ifName: eth1 -3: - ifName: eth1 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0054-Fix-User-commands-require-channel-layer-lib.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0054-Fix-User-commands-require-channel-layer-lib.patch new file mode 100644 index 000000000..bf6f672cf --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0054-Fix-User-commands-require-channel-layer-lib.patch @@ -0,0 +1,37 @@ +From 5d0c9d2217dbe369daffb8a92d7b5e7d7d34d566 Mon Sep 17 00:00:00 2001 +From: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com> +Date: Sat, 2 Mar 2019 20:08:32 +0530 +Subject: [PATCH] Fix: User commands require channel layer lib + +As channel layer is separated out from user layer lib, it +has to be manually included in libusercommands, as user +command handlers use channel layer API's + +Tested-by: +1. Made sure that libusercommands are loaded on it's own +without any undefined symbol error. +2. ipmitool user list 1 works on host interface + +Change-Id: I6652ad248e01afc1349e3a9612754dbdb84b96ad +Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com> +--- + Makefile.am | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/Makefile.am b/Makefile.am +index bb7bdbf..4e9101e 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -120,7 +120,8 @@ libipmi20_la_CXXFLAGS = $(COMMON_CXX) + providers_LTLIBRARIES += libusercmds.la + libusercmds_la_LIBADD = \ + libipmid/libipmid.la \ +- user_channel/libuserlayer.la ++ user_channel/libuserlayer.la \ ++ user_channel/libchannellayer.la + libusercmds_la_SOURCES = \ + user_channel/usercommands.cpp + libusercmds_la_LDFLAGS = \ +-- +2.7.4 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0055-Implement-set-front-panel-button-enables-command.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0055-Implement-set-front-panel-button-enables-command.patch new file mode 100644 index 000000000..170e530f9 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0055-Implement-set-front-panel-button-enables-command.patch @@ -0,0 +1,185 @@ +From b8b88a5c0f9e9cb6023cb8d5453e5cfadaa1a375 Mon Sep 17 00:00:00 2001 +From: Kuiying Wang <kuiying.wang@intel.com> +Date: Fri, 4 Jan 2019 10:50:21 +0800 +Subject: [PATCH] Implement set front panel button enables command + +Through modify buttons' property "Enabled" to disable/enable +corresponding button. +Currently support power and reset button. + +Test-By: ipmitool raw 0x0 0xa 0x2 //disable reset button + ipmitool raw 0x0 0xa 0x1 //disable power button + ipmitool raw 0x0 0xa 0x0 //enable all buttons + +Change-Id: Ice6f58edb898689f7a7fa08ad078d25fccaab27e +Signed-off-by: Kuiying Wang <kuiying.wang@intel.com> +--- + chassishandler.cpp | 98 +++++++++++++++++++++++++++++++++++++++ + chassishandler.hpp | 1 + + host-ipmid-whitelist.conf | 1 + + 3 files changed, 100 insertions(+) + +diff --git a/chassishandler.cpp b/chassishandler.cpp +index 4b42b3c..1a5b805 100644 +--- a/chassishandler.cpp ++++ b/chassishandler.cpp +@@ -112,6 +112,8 @@ const static constexpr char chassisSMDevAddrProp[] = "SMDeviceAddress"; + const static constexpr char chassisBridgeDevAddrProp[] = "BridgeDeviceAddress"; + static constexpr uint8_t chassisCapFlagMask = 0x0f; + static constexpr uint8_t chassisCapAddrMask = 0xfe; ++static constexpr uint8_t disableResetButton = 0x2; ++static constexpr uint8_t disablePowerButton = 0x1; + + typedef struct + { +@@ -140,6 +142,19 @@ struct GetPOHCountResponse + uint8_t counterReading[4]; ///< Counter reading + } __attribute__((packed)); + ++typedef struct ++{ ++ uint8_t disables; // Front Panel Button Enables ++ //[7:4] - reserved ++ //[3] - 1b = disable Standby (sleep) button for entering standby (sleep) ++ //(control can still be used to wake the system) ++ //[2] - 1b = disable Diagnostic Interrupt button ++ //[1] - 1b = disable Reset button ++ //[0] - 1b = disable Power off button for power off only (in the case there ++ // is a single combined power/standby (sleep) button, then this also ++ // disables sleep requests via that button) ++} __attribute__((packed)) IPMISetFrontPanelButtonEnablesReq; ++ + // Phosphor Host State manager + namespace State = sdbusplus::xyz::openbmc_project::State::server; + +@@ -948,6 +963,8 @@ ipmi_ret_t ipmi_get_chassis_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd, + + // Front Panel Button Capabilities and disable/enable status(Optional) + // set to 0, for we don't support them. ++ // TODO, it is tracked by an issue: ++ // https://github.com/openbmc/phosphor-host-ipmid/issues/122 + chassis_status.front_panel_button_cap_status = 0; + + // Pack the actual response +@@ -1721,6 +1738,82 @@ ipmi_ret_t ipmi_chassis_set_power_restore_policy( + return IPMI_CC_OK; + } + ++ipmi_ret_t ipmiSetFrontPanelButtonEnables(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ++ ipmi_request_t request, ++ ipmi_response_t response, ++ ipmi_data_len_t data_len, ++ ipmi_context_t context) ++{ ++ bool enable = false; ++ constexpr const char* powerButtonIntf = ++ "xyz.openbmc_project.Chassis.Buttons.Power"; ++ constexpr const char* powerButtonPath = ++ "/xyz/openbmc_project/Chassis/Buttons/Power0"; ++ constexpr const char* resetButtonIntf = ++ "xyz.openbmc_project.Chassis.Buttons.Reset"; ++ constexpr const char* resetButtonPath = ++ "/xyz/openbmc_project/Chassis/Buttons/Reset0"; ++ using namespace chassis::internal; ++ ++ IPMISetFrontPanelButtonEnablesReq* req = ++ static_cast<IPMISetFrontPanelButtonEnablesReq*>(request); ++ if (*data_len != 1) ++ { ++ *data_len = 0; ++ log<level::ERR>("IPMI request len is invalid"); ++ return IPMI_CC_REQ_DATA_LEN_INVALID; ++ } ++ *data_len = 0; ++ if (req->disables & disablePowerButton) ++ { ++ // Disable power button ++ enable = false; ++ } ++ else ++ { ++ // Enable power button ++ enable = true; ++ } ++ // set power button Enabled property ++ try ++ { ++ auto service = ipmi::getService(dbus, powerButtonIntf, powerButtonPath); ++ ipmi::setDbusProperty(dbus, service, powerButtonPath, powerButtonIntf, ++ "Enabled", enable); ++ } ++ catch (sdbusplus::exception::SdBusError& e) ++ { ++ log<level::ERR>(e.what()); ++ log<level::ERR>("Fail to set power button Enabled property"); ++ return IPMI_CC_UNSPECIFIED_ERROR; ++ } ++ ++ if (req->disables & disableResetButton) ++ { ++ // disable reset button ++ enable = false; ++ } ++ else ++ { ++ // enable reset button ++ enable = true; ++ } ++ // set reset button Enabled property ++ try ++ { ++ auto service = ipmi::getService(dbus, resetButtonIntf, resetButtonPath); ++ ipmi::setDbusProperty(dbus, service, resetButtonPath, resetButtonIntf, ++ "Enabled", enable); ++ } ++ catch (sdbusplus::exception::SdBusError& e) ++ { ++ log<level::ERR>(e.what()); ++ log<level::ERR>("Fail to set reset button Enabled property"); ++ return IPMI_CC_UNSPECIFIED_ERROR; ++ } ++ return IPMI_CC_OK; ++} ++ + void register_netfn_chassis_functions() + { + createIdentifyTimer(); +@@ -1733,6 +1826,11 @@ void register_netfn_chassis_functions() + ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP, NULL, + ipmi_get_chassis_cap, PRIVILEGE_USER); + ++ // Set Front Panel Button Enables ++ ipmi_register_callback(NETFUN_CHASSIS, ++ IPMI_CMD_SET_FRONT_PANEL_BUTTON_ENABLES, NULL, ++ ipmiSetFrontPanelButtonEnables, PRIVILEGE_ADMIN); ++ + // Set Chassis Capabilities + ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_CHASSIS_CAP, NULL, + ipmi_set_chassis_cap, PRIVILEGE_USER); +diff --git a/chassishandler.hpp b/chassishandler.hpp +index 49b5ef8..f4a6bff 100644 +--- a/chassishandler.hpp ++++ b/chassishandler.hpp +@@ -19,6 +19,7 @@ enum ipmi_netfn_chassis_cmds + // Get capability bits + IPMI_CMD_SET_SYS_BOOT_OPTIONS = 0x08, + IPMI_CMD_GET_SYS_BOOT_OPTIONS = 0x09, ++ IPMI_CMD_SET_FRONT_PANEL_BUTTON_ENABLES = 0x0A, + IPMI_CMD_GET_POH_COUNTER = 0x0F, + }; + +diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf +index e5cd0b5..d96d9ed 100644 +--- a/host-ipmid-whitelist.conf ++++ b/host-ipmid-whitelist.conf +@@ -6,6 +6,7 @@ + 0x00:0x06 //<Chassis>:<Set Power Restore Policy> + 0x00:0x08 //<Chassis>:<Set System Boot Options> + 0x00:0x09 //<Chassis>:<Get System Boot Options> ++0x00:0x0A //<Chassis>:<Set Front Panel Button Enables> + 0x00:0x0F //<Chassis>:<Get POH Counter Command> + 0x04:0x2D //<Sensor/Event>:<Get Sensor Reading> + 0x04:0x2F //<Sensor/Event>:<Get Sensor Type> +-- +2.19.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend index a92fc833b..56f90ec24 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend @@ -17,6 +17,8 @@ SRC_URI += "file://phosphor-ipmi-host.service \ file://0050-enable-6-oem-commands.patch \ file://0051-Fix-Set-LAN-Config-to-work-without-SetInProgress.patch \ file://0053-Fix-keep-looping-issue-when-entering-OS.patch \ + file://0054-Fix-User-commands-require-channel-layer-lib.patch \ + file://0055-Implement-set-front-panel-button-enables-command.patch \ " do_install_append(){ diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-node-manager-proxy_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-node-manager-proxy_git.bb deleted file mode 100644 index 24b1dd2a0..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-node-manager-proxy_git.bb +++ /dev/null @@ -1,19 +0,0 @@ -SUMMARY = "Node Manager Proxy" -DESCRIPTION = "The Node Manager Proxy provides a simple interface for communicating \ -with Management Engine via IPMB" - -SRC_URI = "git://git@github.com/openbmc-intel/node-manager;protocol=ssh" -SRCREV = "596cd421d4749c8b6d672fb410eccf9f2da08b3a" -PV = "0.1+git${SRCPV}" - -LICENSE = "Apache-2.0" -LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e" - -SYSTEMD_SERVICE_${PN} = "node-manager-proxy.service" - -DEPENDS = "sdbusplus \ - phosphor-logging \ - boost" - -S = "${WORKDIR}/git/" -inherit cmake systemd diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-node-manager-proxy_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-node-manager-proxy_git.bb index ead7a92aa..09d2f9c41 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-node-manager-proxy_git.bb +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-node-manager-proxy_git.bb @@ -2,8 +2,8 @@ SUMMARY = "Node Manager Proxy" DESCRIPTION = "The Node Manager Proxy provides a simple interface for communicating \ with Management Engine via IPMB" -SRC_URI = "git://git@github.com/Intel-BMC/node-manager.git;protocol=ssh" -SRCREV = "e5a5f6189ce357438f40116717b995bab82c50ae" +SRC_URI = "git://git@github.com/Intel-BMC/node-manager;protocol=ssh" +SRCREV = "81133dd32bd0337aec9e026d1c9c2788028c7bdd" PV = "0.1+git${SRCPV}" LICENSE = "Apache-2.0" diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config/led.yaml b/meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config/led.yaml index 813ffbfd4..7b193f85b 100755 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config/led.yaml +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/leds/intel-led-manager-config/led.yaml @@ -34,3 +34,11 @@ enclosure_identify: identify: Action: 'On' +cpu0_fault: + cpu0fault: + Action: 'On' + +cpu1_fault: + cpu1fault: + Action: 'On' + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend index 56fb8531d..dff1647e8 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend @@ -1,8 +1,4 @@ -SRCREV = "46342ec359c8e0ed543ebb352cfba8f26ce85afe" +SRCREV = "209ec56cca898725213140fd0d1205a4d2f1c6a4" SRC_URI = "git://github.com/openbmc/dbus-sensors.git" DEPENDS_append = " i2c-tools" - -# turn this back on when we have a need, but disable it now -# as no shipping platforms use it and it will take cpu cycles -EXTRA_OECMAKE_append = " -DDISABLE_INTRUSION=ON" diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/srvcfg-manager/srvcfg-manager_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/srvcfg-manager/srvcfg-manager_git.bb index 184b539a9..de2c0a106 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/srvcfg-manager/srvcfg-manager_git.bb +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/srvcfg-manager/srvcfg-manager_git.bb @@ -9,7 +9,7 @@ LICENSE = "Apache-2.0" LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e" SRC_URI = "git://git@github.com/Intel-BMC/provingground.git;protocol=ssh" -SRCREV = "3cc86d6c536b4c5ee7afb5447837b83ce8b3d149" +SRCREV = "c927781ad3ca1408cd7fb0b7cc2538ea10ded76b" inherit cmake systemd SYSTEMD_SERVICE_${PN} = "srvcfg-manager.service" diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0002-Capture-host-restart-cause.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0002-Capture-host-restart-cause.patch index 7c6f684ca..7d70b29fa 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0002-Capture-host-restart-cause.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0002-Capture-host-restart-cause.patch @@ -1,24 +1,27 @@ -From 8dea573181c4455e144335e14cac9f54ebbf7208 Mon Sep 17 00:00:00 2001 +From c0f01261572cb527cf9dc62fa732b28c658ff013 Mon Sep 17 00:00:00 2001 From: Kuiying Wang <kuiying.wang@intel.com> Date: Tue, 7 Aug 2018 16:43:00 +0800 Subject: [PATCH] Capture host restart cause -Capture host restart cause on power/reset button pressed. +Capture host restart cause on power/reset button pressed, +and power restore policy settings. Save the restart cause into file system. And restort it when BMC boot up. Signed-off-by: Kuiying Wang <kuiying.wang@intel.com> +Signed-off-by: Yong Li <yong.b.li@linux.intel.com> --- - configure.ac | 4 +-- - host_state_manager.cpp | 16 ++++++++++++ - host_state_manager.hpp | 56 +++++++++++++++++++++++++++++++++++++++--- - 3 files changed, 71 insertions(+), 5 deletions(-) + configure.ac | 4 ++-- + discover_system_state.cpp | 14 ++++++++++++ + host_state_manager.cpp | 16 ++++++++++++++ + host_state_manager.hpp | 56 ++++++++++++++++++++++++++++++++++++++++++++--- + 4 files changed, 85 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac -index 838aaf2..5879e2f 100644 +index e985a95..b9e64c8 100644 --- a/configure.ac +++ b/configure.ac -@@ -54,9 +54,9 @@ AC_ARG_VAR(HOST_RUNNING_FILE, [File to create if host is running]) +@@ -56,9 +56,9 @@ AC_ARG_VAR(HOST_RUNNING_FILE, [File to create if host is running]) AS_IF([test "x$HOST_RUNNING_FILE" == "x"], [HOST_RUNNING_FILE="/run/openbmc/host@%u-on"]) AC_DEFINE_UNQUOTED([HOST_RUNNING_FILE], ["$HOST_RUNNING_FILE"], [File to create if host is running]) @@ -30,11 +33,50 @@ index 838aaf2..5879e2f 100644 AC_DEFINE_UNQUOTED([HOST_STATE_PERSIST_PATH], ["$HOST_STATE_PERSIST_PATH"], \ [Path of file for storing requested host state.]) +diff --git a/discover_system_state.cpp b/discover_system_state.cpp +index 3a38152..0b5798a 100644 +--- a/discover_system_state.cpp ++++ b/discover_system_state.cpp +@@ -12,6 +12,7 @@ + #include "settings.hpp" + #include "xyz/openbmc_project/Common/error.hpp" + #include "xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp" ++#include <xyz/openbmc_project/State/Host/server.hpp> + + namespace phosphor + { +@@ -181,6 +182,10 @@ int main(int argc, char** argv) + log<level::INFO>("power_policy=ALWAYS_POWER_ON, powering host on"); + setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition", + convertForMessage(server::Host::Transition::On)); ++ ++ setProperty( ++ bus, hostPath, HOST_BUSNAME, "HostRestartCause", ++ convertForMessage(server::Host::RestartCause::PowerPolicyAlwaysOn)); + } + else if (RestorePolicy::Policy::Restore == + RestorePolicy::convertPolicyFromString(powerPolicy)) +@@ -192,6 +197,15 @@ int main(int argc, char** argv) + getProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition"); + setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition", + hostReqState); ++ ++ if (server::Host::convertTransitionFromString(hostReqState) == ++ server::Host::Transition::On) ++ { ++ setProperty( ++ bus, hostPath, HOST_BUSNAME, "HostRestartCause", ++ convertForMessage( ++ server::Host::RestartCause::PowerPolicyPreviousState)); ++ } + } + + return 0; diff --git a/host_state_manager.cpp b/host_state_manager.cpp -index ec1f95f..8573d00 100644 +index 7d661dd..03d210d 100644 --- a/host_state_manager.cpp +++ b/host_state_manager.cpp -@@ -304,6 +304,15 @@ bool Host::deserialize(const fs::path& path) +@@ -308,6 +308,15 @@ bool Host::deserialize(const fs::path& path) } } @@ -50,7 +92,7 @@ index ec1f95f..8573d00 100644 Host::Transition Host::requestedHostTransition(Transition value) { log<level::INFO>("Host State transaction request", -@@ -349,6 +358,13 @@ Host::HostState Host::currentHostState(HostState value) +@@ -353,6 +362,13 @@ Host::HostState Host::currentHostState(HostState value) return server::Host::currentHostState(value); } @@ -63,7 +105,7 @@ index ec1f95f..8573d00 100644 + } // namespace manager } // namespace state - } // namepsace phosphor + } // namespace phosphor diff --git a/host_state_manager.hpp b/host_state_manager.hpp index 2b00777..e74fab7 100644 --- a/host_state_manager.hpp @@ -188,5 +230,5 @@ index 2b00777..e74fab7 100644 } // namespace manager -- -2.17.0 +2.7.4 diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0003-Use-warm-reboot-for-the-Reboot-host-state-transition.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0003-Use-warm-reboot-for-the-Reboot-host-state-transition.patch new file mode 100644 index 000000000..40722c3c9 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0003-Use-warm-reboot-for-the-Reboot-host-state-transition.patch @@ -0,0 +1,71 @@ +From 8a7f73a0688524c71023da89e8cb5578dac16f5d Mon Sep 17 00:00:00 2001 +From: Yong Li <yong.b.li@linux.intel.com> +Date: Fri, 8 Mar 2019 17:21:49 +0800 +Subject: [PATCH] Use warm-reboot for the Reboot host state transition + +The same as reset button pressing, the pgood signal will keep on during the reboot + +Tested By: +ipmitool chassis power reset +The pgood(gpio219) will be keep high during the reset process + +Signed-off-by: Yong Li <yong.b.li@linux.intel.com> +--- + host_state_manager.cpp | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +diff --git a/host_state_manager.cpp b/host_state_manager.cpp +index 03d210d..8fac348 100644 +--- a/host_state_manager.cpp ++++ b/host_state_manager.cpp +@@ -44,8 +44,9 @@ constexpr auto HOST_STATE_SOFT_POWEROFF_TGT = "obmc-host-shutdown@0.target"; + constexpr auto HOST_STATE_POWEROFF_TGT = "obmc-host-stop@0.target"; + constexpr auto HOST_STATE_POWERON_TGT = "obmc-host-start@0.target"; + constexpr auto HOST_STATE_POWERON_MIN_TGT = "obmc-host-startmin@0.target"; +-constexpr auto HOST_STATE_REBOOT_TGT = "obmc-host-reboot@0.target"; ++constexpr auto HOST_STATE_REBOOT_TGT = "obmc-host-warm-reset@0.target"; + constexpr auto HOST_STATE_QUIESCE_TGT = "obmc-host-quiesce@0.target"; ++constexpr auto hostStateRebootService = "intel-power-warm-reset@0.service"; + + constexpr auto ACTIVE_STATE = "active"; + constexpr auto ACTIVATING_STATE = "activating"; +@@ -168,6 +169,7 @@ bool Host::stateActive(const std::string& target) + + const auto& currentStateStr = + sdbusplus::message::variant_ns::get<std::string>(currentState); ++ + return currentStateStr == ACTIVE_STATE || + currentStateStr == ACTIVATING_STATE; + } +@@ -236,18 +238,22 @@ void Host::sysStateChange(sdbusplus::message::message& msg) + // Read the msg and populate each variable + msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult); + +- if ((newStateUnit == HOST_STATE_POWEROFF_TGT) && +- (newStateResult == "done") && +- (!stateActive(HOST_STATE_POWERON_MIN_TGT))) ++ if (((newStateUnit == HOST_STATE_POWEROFF_TGT) && ++ (newStateResult == "done") && ++ (!stateActive(HOST_STATE_POWERON_MIN_TGT))) || ++ ((newStateUnit == hostStateRebootService) && ++ (newStateResult == "done"))) + { + log<level::INFO>("Received signal that host is off"); + this->currentHostState(server::Host::HostState::Off); + this->bootProgress(bootprogress::Progress::ProgressStages::Unspecified); + this->operatingSystemState(osstatus::Status::OSStatus::Inactive); + } +- else if ((newStateUnit == HOST_STATE_POWERON_MIN_TGT) && +- (newStateResult == "done") && +- (stateActive(HOST_STATE_POWERON_MIN_TGT))) ++ else if (((newStateUnit == HOST_STATE_POWERON_MIN_TGT) && ++ (newStateResult == "done") && ++ (stateActive(HOST_STATE_POWERON_MIN_TGT))) || ++ ((newStateUnit == HOST_STATE_REBOOT_TGT) && ++ (newStateResult == "done"))) + { + log<level::INFO>("Received signal that host is running"); + this->currentHostState(server::Host::HostState::Running); +-- +2.7.4 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend index 92f5e530c..4c50ecf5e 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend @@ -5,4 +5,5 @@ SRC_URI += "file://0001-Modify-dbus-interface-for-power-control.patch \ file://phosphor-reset-host-reboot-attempts@.service \ file://phosphor-reset-host-check@.service \ file://0002-Capture-host-restart-cause.patch \ + file://0003-Use-warm-reboot-for-the-Reboot-host-state-transition.patch \ " diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager/0001-Implement-post-code-manager.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager/0001-Implement-post-code-manager.patch new file mode 100644 index 000000000..8915484cd --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager/0001-Implement-post-code-manager.patch @@ -0,0 +1,499 @@ +From 7d78e70735e1bce51ef34cfe128be68758de3447 Mon Sep 17 00:00:00 2001 +From: Kuiying Wang <kuiying.wang@intel.com> +Date: Tue, 19 Feb 2019 15:00:11 +0800 +Subject: [PATCH] Implement post code manager + +Implement method and properties defined in PostCode.interface.yaml +under phosphor-dbus-interfaces/xyz/openbmc_project/State/Boot +1. Method: std::vector<uint64_t> PostCode::getPostCodes(uint16_t index) +2. Properties: CurrentBootCycleIndex/MaxBootCycleNum + +Test-By: + Every cycle post codes is saved in "/var/lib/phosphor-post-code-manager" + "1" file is saved all post codes for cycle 1 + "2" file is saved all post codes for cycle 2 + "CurrentBootCycleIndex" file is saved the current boot cycle number. + root@wolfpass:/var/lib/phosphor-post-code-manager# ls + 1 2 CurrentBootCycleIndex + +Change-Id: Ia89b9121983261fef5573092d890beb84626ceeb +Signed-off-by: Kuiying Wang <kuiying.wang@intel.com> +--- + CMakeLists.txt | 45 ++++++ + MAINTAINERS | 45 ++++++ + inc/post_code.hpp | 152 ++++++++++++++++++ + ...penbmc_project.State.Boot.PostCode.service | 11 ++ + src/main.cpp | 61 +++++++ + src/post_code.cpp | 109 +++++++++++++ + 6 files changed, 423 insertions(+) + create mode 100644 CMakeLists.txt + create mode 100644 MAINTAINERS + create mode 100644 inc/post_code.hpp + create mode 100644 service_files/xyz.openbmc_project.State.Boot.PostCode.service + create mode 100644 src/main.cpp + create mode 100644 src/post_code.cpp + +diff --git a/CMakeLists.txt b/CMakeLists.txt +new file mode 100644 +index 0000000..594d839 +--- /dev/null ++++ b/CMakeLists.txt +@@ -0,0 +1,45 @@ ++cmake_minimum_required(VERSION 2.8.10 FATAL_ERROR) ++project(post-code-manager CXX) ++set(CMAKE_CXX_STANDARD 17) ++set(CMAKE_CXX_STANDARD_REQUIRED ON) ++ ++set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) ++include(GNUInstallDirs) ++include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc) ++include_directories(${CMAKE_CURRENT_BINARY_DIR}) ++ ++set(DBUS_OBJECT_NAME "xyz/openbmc_project/State/Boot/PostCode") ++set(DBUS_INTF_NAME "xyz.openbmc_project.State.Boot.PostCode") ++ ++add_definitions(-DDBUS_OBJECT_NAME="/${DBUS_OBJECT_NAME}") ++add_definitions(-DDBUS_INTF_NAME="${DBUS_INTF_NAME}") ++set(SRC_FILES src/post_code.cpp ++ src/main.cpp ) ++set ( SERVICE_FILES ++ service_files/xyz.openbmc_project.State.Boot.PostCode.service ) ++ ++# import sdbusplus ++find_package(PkgConfig REQUIRED) ++pkg_check_modules(SDBUSPLUSPLUS sdbusplus REQUIRED) ++include_directories(${SDBUSPLUSPLUS_INCLUDE_DIRS}) ++link_directories(${SDBUSPLUSPLUS_LIBRARY_DIRS}) ++find_program(SDBUSPLUSPLUS sdbus++) ++ ++# import phosphor-logging ++find_package(PkgConfig REQUIRED) ++pkg_check_modules(LOGGING phosphor-logging REQUIRED) ++include_directories(${LOGGING_INCLUDE_DIRS}) ++link_directories(${LOGGING_LIBRARY_DIRS}) ++ ++# phosphor-dbus-interfaces ++find_package(PkgConfig REQUIRED) ++pkg_check_modules(DBUSINTERFACE phosphor-dbus-interfaces REQUIRED) ++include_directories(${DBUSINTERFACE_INCLUDE_DIRS}) ++link_directories(${DBUSINTERFACE_LIBRARY_DIRS}) ++ ++add_executable(${PROJECT_NAME} ${SRC_FILES}) ++target_link_libraries(${PROJECT_NAME} ${DBUSINTERFACE_LIBRARIES} ) ++target_link_libraries(${PROJECT_NAME} "${SDBUSPLUSPLUS_LIBRARIES} -lstdc++fs -lphosphor_dbus") ++ ++install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) ++install (FILES ${SERVICE_FILES} DESTINATION /lib/systemd/system/) +\ No newline at end of file +diff --git a/MAINTAINERS b/MAINTAINERS +new file mode 100644 +index 0000000..de6cc54 +--- /dev/null ++++ b/MAINTAINERS +@@ -0,0 +1,45 @@ ++How to use this list: ++ Find the most specific section entry (described below) that matches where ++ your change lives and add the reviewers (R) and maintainers (M) as ++ reviewers. You can use the same method to track down who knows a particular ++ code base best. ++ ++ Your change/query may span multiple entries; that is okay. ++ ++ If you do not find an entry that describes your request at all, someone ++ forgot to update this list; please at least file an issue or send an email ++ to a maintainer, but preferably you should just update this document. ++ ++Description of section entries: ++ ++ Section entries are structured according to the following scheme: ++ ++ X: NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!> ++ X: ... ++ . ++ . ++ . ++ ++ Where REPO_NAME is the name of the repository within the OpenBMC GitHub ++ organization; FILE_PATH is a file path within the repository, possibly with ++ wildcards; X is a tag of one of the following types: ++ ++ M: Denotes maintainer; has fields NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!>; ++ if omitted from an entry, assume one of the maintainers from the ++ MAINTAINERS entry. ++ R: Denotes reviewer; has fields NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!>; ++ these people are to be added as reviewers for a change matching the repo ++ path. ++ F: Denotes forked from an external repository; has fields URL. ++ ++ Line comments are to be denoted "# SOME COMMENT" (typical shell style ++ comment); it is important to follow the correct syntax and semantics as we ++ may want to use automated tools with this file in the future. ++ ++ A change cannot be added to an OpenBMC repository without a MAINTAINER's ++ approval; thus, a MAINTAINER should always be listed as a reviewer. ++ ++START OF MAINTAINERS LIST ++------------------------- ++ ++M: Kuiying Wang <kuiying.wang@intel.com> <kuiyingw> +\ No newline at end of file +diff --git a/inc/post_code.hpp b/inc/post_code.hpp +new file mode 100644 +index 0000000..84c8b3e +--- /dev/null ++++ b/inc/post_code.hpp +@@ -0,0 +1,152 @@ ++/* ++// Copyright (c) 2019 Intel Corporation ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++*/ ++#pragma once ++#include <fcntl.h> ++#include <unistd.h> ++#include <cereal/cereal.hpp> ++#include <experimental/filesystem> ++#include <cereal/access.hpp> ++#include <cereal/archives/json.hpp> ++#include <iostream> ++#include <fstream> ++#include <cereal/types/vector.hpp> ++ ++#include <xyz/openbmc_project/State/Boot/PostCode/server.hpp> ++#include <xyz/openbmc_project/Common/error.hpp> ++#include <phosphor-logging/elog-errors.hpp> ++#include <xyz/openbmc_project/State/Host/server.hpp> ++ ++#define MaxPostCodeCycles 100 ++ ++const static constexpr char *PostCodePath = ++ "/xyz/openbmc_project/state/boot/raw"; ++const static constexpr char *PropertiesIntf = ++ "org.freedesktop.DBus.Properties"; ++const static constexpr char *PostCodeListPath = ++ "/var/lib/phosphor-post-code-manager/"; ++const static constexpr char *CurrentBootCycleIndexName = ++ "CurrentBootCycleIndex"; ++const static constexpr char *HostStatePath = ++ "/xyz/openbmc_project/state/host0"; ++ ++ ++struct EventDeleter ++{ ++ void operator()(sd_event *event) const ++ { ++ event = sd_event_unref(event); ++ } ++}; ++using EventPtr = std::unique_ptr<sd_event, EventDeleter>; ++namespace fs = std::experimental::filesystem; ++namespace StateServer = sdbusplus::xyz::openbmc_project::State::server; ++ ++using post_code = ++ sdbusplus::xyz::openbmc_project::State::Boot::server::PostCode; ++ ++struct PostCode : sdbusplus::server::object_t<post_code> ++{ ++ PostCode(sdbusplus::bus::bus& bus, const char* path, ++ EventPtr &event) : ++ sdbusplus::server::object_t<post_code>(bus, path), ++ bus(bus), ++ propertiesChangedSignalRaw( ++ bus, ++ sdbusplus::bus::match::rules::type::signal() + ++ sdbusplus::bus::match::rules::member("PropertiesChanged") + ++ sdbusplus::bus::match::rules::path(PostCodePath) + ++ sdbusplus::bus::match::rules::interface(PropertiesIntf), ++ [this](sdbusplus::message::message &msg) { ++ std::string objectName; ++ std::map<std::string, sdbusplus::message::variant<uint64_t>> msgData; ++ msg.read(objectName, msgData); ++ // Check if it was the Value property that changed. ++ auto valPropMap = msgData.find("Value"); ++ { ++ if (valPropMap != msgData.end()) ++ { ++ this->savePostCodes(sdbusplus::message::variant_ns::get<uint64_t>(valPropMap->second)); ++ } ++ } ++ }), ++ propertiesChangedSignalCurrentHostState( ++ bus, ++ sdbusplus::bus::match::rules::type::signal() + ++ sdbusplus::bus::match::rules::member("PropertiesChanged") + ++ sdbusplus::bus::match::rules::path(HostStatePath) + ++ sdbusplus::bus::match::rules::interface(PropertiesIntf), ++ [this](sdbusplus::message::message &msg) { ++ std::string objectName; ++ std::map<std::string, sdbusplus::message::variant<std::string>> msgData; ++ msg.read(objectName, msgData); ++ // Check if it was the Value property that changed. ++ auto valPropMap = msgData.find("CurrentHostState"); ++ { ++ if (valPropMap != msgData.end()) ++ { ++ StateServer::Host::HostState currentHostState = ++ StateServer::Host::convertHostStateFromString( ++ sdbusplus::message::variant_ns::get<std::string>(valPropMap->second)); ++ if (currentHostState == StateServer::Host::HostState::Off) ++ { ++ if (this->currentBootCycleIndex() >= this->maxBootCycleNum()) ++ { ++ this->currentBootCycleIndex(1); ++ } else{ ++ this->currentBootCycleIndex(this->currentBootCycleIndex() + 1); ++ } ++ this->postCodes.clear(); ++ } ++ } ++ } ++ }) ++ { ++ phosphor::logging::log<phosphor::logging::level::INFO>( ++ "PostCode is created"); ++ auto dir = fs::path(PostCodeListPath); ++ fs::create_directories(dir); ++ strPostCodeListPath = PostCodeListPath; ++ strCurrentBootCycleIndexName = CurrentBootCycleIndexName; ++ uint16_t index = 0; ++ deserialize(fs::path(strPostCodeListPath + strCurrentBootCycleIndexName), index); ++ currentBootCycleIndex(index); ++ maxBootCycleNum(MaxPostCodeCycles); ++ if (currentBootCycleIndex() >= maxBootCycleNum()) ++ { ++ currentBootCycleIndex(1); ++ } else{ ++ currentBootCycleIndex(currentBootCycleIndex() + 1); ++ } ++ } ++ ~PostCode() ++ { ++ ++ } ++ ++ std::vector<uint64_t> getPostCodes(uint16_t index) override; ++ ++ private: ++ sdbusplus::bus::bus& bus; ++ std::vector<uint64_t> postCodes; ++ std::string strPostCodeListPath; ++ std::string strCurrentBootCycleIndexName; ++ void savePostCodes(uint64_t code); ++ sdbusplus::bus::match_t propertiesChangedSignalRaw; ++ sdbusplus::bus::match_t propertiesChangedSignalCurrentHostState; ++ fs::path serialize(const std::string& path); ++ bool deserialize(const fs::path& path, uint16_t& index); ++ bool deserializePostCodes(const fs::path& path, std::vector<uint64_t> &codes); ++}; +diff --git a/service_files/xyz.openbmc_project.State.Boot.PostCode.service b/service_files/xyz.openbmc_project.State.Boot.PostCode.service +new file mode 100644 +index 0000000..67bc43f +--- /dev/null ++++ b/service_files/xyz.openbmc_project.State.Boot.PostCode.service +@@ -0,0 +1,11 @@ ++[Unit] ++Description=Post code manager ++ ++[Service] ++ExecStart=/usr/bin/env post-code-manager ++SyslogIdentifier=post-code-manager ++Type=dbus ++BusName=xyz.openbmc_project.State.Boot.PostCode ++ ++[Install] ++WantedBy=obmc-standby.target +diff --git a/src/main.cpp b/src/main.cpp +new file mode 100644 +index 0000000..4a74b29 +--- /dev/null ++++ b/src/main.cpp +@@ -0,0 +1,61 @@ ++/* ++// Copyright (c) 2019 Intel Corporation ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++*/ ++#include "post_code.hpp" ++ ++int main(int argc, char* argv[]) ++{ ++ int ret = 0; ++ ++ phosphor::logging::log<phosphor::logging::level::INFO>( ++ "Start post code manager service..."); ++ ++ sd_event* event = nullptr; ++ ret = sd_event_default(&event); ++ if (ret < 0) ++ { ++ phosphor::logging::log<phosphor::logging::level::ERR>( ++ "Error creating a default sd_event handler"); ++ return ret; ++ } ++ EventPtr eventP{event}; ++ event = nullptr; ++ ++ sdbusplus::bus::bus bus = sdbusplus::bus::new_default(); ++ sdbusplus::server::manager_t m{bus, DBUS_OBJECT_NAME}; ++ ++ bus.request_name(DBUS_INTF_NAME); ++ ++ PostCode postCode{bus, DBUS_OBJECT_NAME, eventP}; ++ ++ try ++ { ++ bus.attach_event(eventP.get(), SD_EVENT_PRIORITY_NORMAL); ++ ret = sd_event_loop(eventP.get()); ++ if (ret < 0) ++ { ++ phosphor::logging::log<phosphor::logging::level::ERR>( ++ "Error occurred during the sd_event_loop", ++ phosphor::logging::entry("RET=%d", ret)); ++ } ++ } ++ catch (std::exception& e) ++ { ++ phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); ++ return -1; ++ } ++ return 0; ++ ++} +diff --git a/src/post_code.cpp b/src/post_code.cpp +new file mode 100644 +index 0000000..983eeee +--- /dev/null ++++ b/src/post_code.cpp +@@ -0,0 +1,109 @@ ++/* ++// Copyright (c) 2019 Intel Corporation ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++*/ ++#include "post_code.hpp" ++std::vector<uint64_t> PostCode::getPostCodes(uint16_t index) ++{ ++ std::vector<uint64_t> codes; ++ ++ if (currentBootCycleIndex() == index) ++ return postCodes; ++ deserializePostCodes(fs::path(strPostCodeListPath + std::to_string(index)), codes); ++ return codes; ++} ++void PostCode::savePostCodes(uint64_t code) ++{ ++ postCodes.push_back(code); ++ serialize(fs::path(PostCodeListPath)); ++ return; ++} ++ ++fs::path PostCode::serialize(const std::string& path) ++{ ++ try ++ { ++ uint16_t index = currentBootCycleIndex(); ++ fs::path fullPath(path + strCurrentBootCycleIndexName); ++ std::ofstream os(fullPath.c_str(), std::ios::binary); ++ cereal::JSONOutputArchive oarchive(os); ++ oarchive(index); ++ ++ std::ofstream osPostCodes((path + std::to_string(currentBootCycleIndex())).c_str(), std::ios::binary); ++ cereal::JSONOutputArchive oarchivePostCodes(osPostCodes); ++ oarchivePostCodes(postCodes); ++ ++ return path; ++ } ++ catch (cereal::Exception& e) ++ { ++ phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); ++ } ++ catch (const fs::filesystem_error& e) ++ { ++ phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); ++ } ++} ++ ++bool PostCode::deserialize(const fs::path& path, uint16_t& index) ++{ ++ try ++ { ++ if (fs::exists(path)) ++ { ++ std::ifstream is(path.c_str(), std::ios::in | std::ios::binary); ++ cereal::JSONInputArchive iarchive(is); ++ iarchive(index); ++ return true; ++ } ++ return false; ++ } ++ catch (cereal::Exception& e) ++ { ++ phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); ++ return false; ++ } ++ catch (const fs::filesystem_error& e) ++ { ++ return false; ++ } ++ ++ return false; ++} ++ ++bool PostCode::deserializePostCodes(const fs::path& path, std::vector<uint64_t> &codes) ++{ ++ try ++ { ++ if (fs::exists(path)) ++ { ++ std::ifstream is(path.c_str(), std::ios::in | std::ios::binary); ++ cereal::JSONInputArchive iarchive(is); ++ iarchive(codes); ++ return true; ++ } ++ return false; ++ } ++ catch (cereal::Exception& e) ++ { ++ phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); ++ return false; ++ } ++ catch (const fs::filesystem_error& e) ++ { ++ return false; ++ } ++ ++ return false; ++} +-- +2.19.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager_git.bb new file mode 100644 index 000000000..8f2ead18a --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager_git.bb @@ -0,0 +1,34 @@ +SUMMARY = "Phosphor post code manager" +DESCRIPTION = "Post Code Manager" + +SRC_URI = "git://github.com/openbmc/phosphor-post-code-manager.git" +SRCREV = "7f50dcaa6feb66cf5307b8a0e4742a36a50eed29" + +S = "${WORKDIR}/git" + +PV = "1.0+git${SRCPV}" + +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327" + +inherit cmake pkgconfig systemd + +SYSTEMD_SERVICE_${PN} += "xyz.openbmc_project.State.Boot.PostCode.service" + +DEPENDS += " \ + autoconf-archive-native \ + systemd \ + sdbusplus \ + sdbusplus-native \ + phosphor-dbus-interfaces \ + phosphor-dbus-interfaces-native \ + phosphor-logging \ + " +RDEPENDS_${PN} += " \ + libsystemd \ + sdbusplus \ + phosphor-dbus-interfaces \ + phosphor-logging \ + " +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" +SRC_URI += "file://0001-Implement-post-code-manager.patch" diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/system/callback-manager.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/system/callback-manager.bb index 3fb68201e..74f87e019 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/system/callback-manager.bb +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/system/callback-manager.bb @@ -1,13 +1,13 @@ SUMMARY = "Callback Manager" DESCRIPTION = "D-Bus daemon that registers matches that trigger method calls" -SRC_URI = "git://git@github.com/Intel-BMC/provingground.git;protocol=ssh" +SRC_URI = "git://git@github.com/Intel-BMC/provingground;protocol=ssh" inherit cmake systemd DEPENDS = "boost sdbusplus" PV = "0.1+git${SRCPV}" -SRCREV = "3cc86d6c536b4c5ee7afb5447837b83ce8b3d149" +SRCREV = "c927781ad3ca1408cd7fb0b7cc2538ea10ded76b" S = "${WORKDIR}/git/callback-manager" diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/system/obmc-mgr-system%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/system/obmc-mgr-system%.bbappend deleted file mode 100644 index 37bb8f961..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/system/obmc-mgr-system%.bbappend +++ /dev/null @@ -1,2 +0,0 @@ -SYSTEMD_AUTO_ENABLE = "enable" - diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0005-Added-suport-for-multiple-user-manager-services.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0005-Added-suport-for-multiple-user-manager-services.patch index 332933a28..01be1501a 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0005-Added-suport-for-multiple-user-manager-services.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0005-Added-suport-for-multiple-user-manager-services.patch @@ -1,4 +1,4 @@ -From 4762913cfbd45234ddb363a5ec130eb56a8c7af0 Mon Sep 17 00:00:00 2001 +From 6e13c881be7df3cd1e19c69355ef87b91dbc197b Mon Sep 17 00:00:00 2001 From: Radivoje Jovanovic <radivoje.jovanovic@intel.com> Date: Mon, 2 Jul 2018 19:23:25 -0700 Subject: [PATCH] Added suport for multiple user manager services @@ -11,16 +11,16 @@ Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.co --- Makefile.am | 5 +- mainapp.cpp | 89 ++++++- - user_mgr.cpp | 295 +++------------------ + user_mgr.cpp | 293 +++------------------ user_mgr.hpp | 9 +- user_service.cpp | 781 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ user_service.hpp | 233 +++++++++++++++++ - 6 files changed, 1141 insertions(+), 271 deletions(-) + 6 files changed, 1141 insertions(+), 269 deletions(-) create mode 100644 user_service.cpp create mode 100644 user_service.hpp diff --git a/Makefile.am b/Makefile.am -index 4413b84..e4310d4 100644 +index 9da26ef..5556619 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,12 +1,13 @@ @@ -151,10 +151,10 @@ index c9da030..03c406a 100644 // Claim the bus now bus.request_name(USER_MANAGER_BUSNAME); diff --git a/user_mgr.cpp b/user_mgr.cpp -index 786a8fd..51193cc 100644 +index 47edf7d..32f3f4c 100644 --- a/user_mgr.cpp +++ b/user_mgr.cpp -@@ -14,26 +14,18 @@ +@@ -14,26 +14,20 @@ // limitations under the License. */ @@ -165,8 +165,8 @@ index 786a8fd..51193cc 100644 +#include <cstdio> + #include <fstream> --#include <grp.h> --#include <pwd.h> + #include <grp.h> + #include <pwd.h> #include <regex> -#include <algorithm> -#include <numeric> @@ -184,7 +184,7 @@ index 786a8fd..51193cc 100644 #include "user_mgr.hpp" #include "users.hpp" #include "config.h" -@@ -43,12 +35,10 @@ namespace phosphor +@@ -43,12 +37,10 @@ namespace phosphor namespace user { @@ -197,7 +197,7 @@ index 786a8fd..51193cc 100644 static constexpr uint8_t minPasswdLength = 8; static constexpr int success = 0; static constexpr int failure = -1; -@@ -83,79 +73,6 @@ using NoResource = +@@ -94,79 +86,6 @@ using NoResource = using Argument = xyz::openbmc_project::Common::InvalidArgument; @@ -277,7 +277,7 @@ index 786a8fd..51193cc 100644 bool UserMgr::isUserExist(const std::string &userName) { if (userName.empty()) -@@ -282,39 +199,14 @@ void UserMgr::createUser(std::string userName, +@@ -293,39 +212,14 @@ void UserMgr::createUser(std::string userName, { throwForInvalidPrivilege(priv); throwForInvalidGroups(groupNames); @@ -289,9 +289,7 @@ index 786a8fd..51193cc 100644 - std::string groups = getCSVFromVector(groupNames); - bool sshRequested = removeStringFromCSV(groups, grpSsh); -+ // Tell the User Service to create a new user with the info provided. -+ userSrvc->createUser(userName, groupNames, priv, enabled); - +- - // treat privilege as a group - This is to avoid using different file to - // store the same. - if (!priv.empty()) @@ -314,13 +312,15 @@ index 786a8fd..51193cc 100644 - log<level::ERR>("Unable to create new user"); - elog<InternalFailure>(); - } -- ++ // Tell the User Service to create a new user with the info provided. ++ userSrvc->createUser(userName, groupNames, priv, enabled); + - // Add the users object before sending out the signal + // Add the users to the local list before sending out the signal std::string userObj = std::string(usersObjPath) + "/" + userName; std::sort(groupNames.begin(), groupNames.end()); usersList.emplace( -@@ -328,19 +220,11 @@ void UserMgr::createUser(std::string userName, +@@ -339,19 +233,11 @@ void UserMgr::createUser(std::string userName, void UserMgr::deleteUser(std::string userName) { @@ -344,7 +344,7 @@ index 786a8fd..51193cc 100644 usersList.erase(userName); -@@ -351,24 +235,13 @@ void UserMgr::deleteUser(std::string userName) +@@ -362,24 +248,13 @@ void UserMgr::deleteUser(std::string userName) void UserMgr::renameUser(std::string userName, std::string newUserName) { @@ -372,7 +372,7 @@ index 786a8fd..51193cc 100644 const auto &user = usersList[userName]; std::string priv = user.get()->userPrivilege(); std::vector<std::string> groupNames = user.get()->userGroups(); -@@ -392,8 +265,6 @@ void UserMgr::updateGroupsAndPriv(const std::string &userName, +@@ -403,8 +278,6 @@ void UserMgr::updateGroupsAndPriv(const std::string &userName, { throwForInvalidPrivilege(priv); throwForInvalidGroups(groupNames); @@ -381,7 +381,7 @@ index 786a8fd..51193cc 100644 throwForUserDoesNotExist(userName); const std::vector<std::string> &oldGroupNames = usersList[userName].get()->userGroups(); -@@ -409,29 +280,8 @@ void UserMgr::updateGroupsAndPriv(const std::string &userName, +@@ -420,29 +293,8 @@ void UserMgr::updateGroupsAndPriv(const std::string &userName, throwForMaxGrpUserCount(groupNames); } @@ -413,7 +413,7 @@ index 786a8fd..51193cc 100644 log<level::INFO>("User groups / privilege updated successfully", entry("USER_NAME=%s", userName.c_str())); -@@ -627,19 +477,9 @@ int UserMgr::setPamModuleArgValue(const std::string &moduleName, +@@ -638,19 +490,9 @@ int UserMgr::setPamModuleArgValue(const std::string &moduleName, void UserMgr::userEnable(const std::string &userName, bool enabled) { @@ -435,7 +435,7 @@ index 786a8fd..51193cc 100644 log<level::INFO>("User enabled/disabled state updated successfully", entry("USER_NAME=%s", userName.c_str()), -@@ -730,49 +570,8 @@ bool UserMgr::userLockedForFailedAttempt(const std::string &userName, +@@ -728,49 +570,8 @@ bool UserMgr::userLockedForFailedAttempt(const std::string &userName, UserSSHLists UserMgr::getUserAndSshGrpList() { @@ -487,7 +487,7 @@ index 786a8fd..51193cc 100644 } size_t UserMgr::getIpmiUsersCount() -@@ -783,60 +582,23 @@ size_t UserMgr::getIpmiUsersCount() +@@ -781,49 +582,14 @@ size_t UserMgr::getIpmiUsersCount() bool UserMgr::isUserEnabled(const std::string &userName) { @@ -540,7 +540,8 @@ index 786a8fd..51193cc 100644 + return std::move(userSrvc->getUsersInGroup(groupName)); } - void UserMgr::initUserObjects(void) + DbusUserObj UserMgr::getPrivilegeMapperObject(void) +@@ -1018,11 +784,9 @@ void UserMgr::initUserObjects(void) { // All user management lock has to be based on /etc/shadow phosphor::user::shadow::Lock lock(); @@ -554,7 +555,7 @@ index 786a8fd..51193cc 100644 if (!userNameList.empty()) { -@@ -891,8 +653,10 @@ void UserMgr::initUserObjects(void) +@@ -1077,8 +841,10 @@ void UserMgr::initUserObjects(void) } } @@ -567,7 +568,7 @@ index 786a8fd..51193cc 100644 { UserMgrIface::allPrivileges(privMgr); std::sort(groupsMgr.begin(), groupsMgr.end()); -@@ -1000,6 +764,7 @@ UserMgr::UserMgr(sdbusplus::bus::bus &bus, const char *path) : +@@ -1186,6 +952,7 @@ UserMgr::UserMgr(sdbusplus::bus::bus &bus, const char *path) : } AccountPolicyIface::accountUnlockTimeout(value32); } @@ -576,18 +577,18 @@ index 786a8fd..51193cc 100644 } diff --git a/user_mgr.hpp b/user_mgr.hpp -index c1673f1..169f121 100644 +index c78174d..9d9c842 100644 --- a/user_mgr.hpp +++ b/user_mgr.hpp -@@ -20,6 +20,7 @@ - #include <xyz/openbmc_project/User/AccountPolicy/server.hpp> +@@ -21,6 +21,7 @@ #include <unordered_map> + #include <variant> #include "users.hpp" +#include "user_service.hpp" namespace phosphor { -@@ -27,8 +28,6 @@ namespace user +@@ -28,8 +29,6 @@ namespace user { using UserMgrIface = sdbusplus::xyz::openbmc_project::User::server::Manager; @@ -596,7 +597,7 @@ index c1673f1..169f121 100644 using AccountPolicyIface = sdbusplus::xyz::openbmc_project::User::server::AccountPolicy; -@@ -49,8 +48,10 @@ class UserMgr : public UserMgrIface, AccountPolicyIface +@@ -71,8 +70,10 @@ class UserMgr : public UserMgrIface, AccountPolicyIface * * @param[in] bus - sdbusplus handler * @param[in] path - D-Bus path @@ -608,7 +609,7 @@ index c1673f1..169f121 100644 /** @brief create user method. * This method creates a new user as requested -@@ -148,6 +149,8 @@ class UserMgr : public UserMgrIface, AccountPolicyIface +@@ -181,6 +182,8 @@ class UserMgr : public UserMgrIface, AccountPolicyIface /** @brief object path */ const std::string path; diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui/0007-Fix-some-page-keeps-loading-on-IE11.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui/0007-Fix-some-page-keeps-loading-on-IE11.patch new file mode 100644 index 000000000..31d810cb6 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui/0007-Fix-some-page-keeps-loading-on-IE11.patch @@ -0,0 +1,68 @@ +From 5a3750377629725890f949d68e7e0ba7d4752825 Mon Sep 17 00:00:00 2001 +From: Mirage Su <mirage.su@mic.com.tw> +Date: Fri, 8 Mar 2019 17:12:46 +0800 +Subject: [PATCH] Fix some page keeps loading on IE11 + +--- + app/index.js | 1 + + package-lock.json | 19 +++++++++++++++++++ + package.json | 1 + + 3 files changed, 21 insertions(+) + mode change 100644 => 100755 package-lock.json + +diff --git a/app/index.js b/app/index.js +index c9fed83..c51203e 100644 +--- a/app/index.js ++++ b/app/index.js +@@ -8,6 +8,7 @@ + */ + import 'angular/angular-csp.css'; + import 'bootstrap/dist/css/bootstrap.css'; ++import 'babel-polyfill'; + + import angular from 'angular'; + import angular_animate from 'angular-animate'; +diff --git a/package-lock.json b/package-lock.json +old mode 100644 +new mode 100755 +index 2d9d31b..61e9787 +--- a/package-lock.json ++++ b/package-lock.json +@@ -1500,6 +1500,25 @@ + "babel-runtime": "6.26.0" + } + }, ++ "babel-polyfill": { ++ "version": "6.26.0", ++ "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", ++ "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", ++ "dev": true, ++ "requires": { ++ "babel-runtime": "^6.26.0", ++ "core-js": "^2.5.0", ++ "regenerator-runtime": "^0.10.5" ++ }, ++ "dependencies": { ++ "regenerator-runtime": { ++ "version": "0.10.5", ++ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", ++ "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", ++ "dev": true ++ } ++ } ++ }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", +diff --git a/package.json b/package.json +index 35c6b78..1bdf934 100644 +--- a/package.json ++++ b/package.json +@@ -50,6 +50,7 @@ + "autoprefixer": "9.1.5", + "babel-core": "6.26.3", + "babel-loader": "8.0.2", ++ "babel-polyfill": "^6.26.0", + "compression-webpack-plugin": "2.0.0", + "copy-webpack-plugin": "4.5.2", + "csp-html-webpack-plugin": "^2.5.0", diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui/config.json b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui/config.json new file mode 100644 index 000000000..1543a6249 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui/config.json @@ -0,0 +1,8 @@ +{ + "customKeyEnable": true, + "keyType" : "VT100+", + "customConsoleDisplaySize": { + "width": 100, + "height": 32 + } +} diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend index e40b5ed8e..dd1ed6613 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/phosphor-webui_%.bbappend @@ -1,3 +1,10 @@ FILESEXTRAPATHS_append := ":${THISDIR}/${PN}" -SRC_URI += "file://0001-Implement-KVM-in-webui.patch" +SRC_URI += "file://0001-Implement-KVM-in-webui.patch \ + file://config.json \ + file://0007-Fix-some-page-keeps-loading-on-IE11.patch \ + " + +do_compile_prepend() { + cp -r ${WORKDIR}/config.json ${S}/ +} diff --git a/meta-openbmc-mods/meta-wolfpass/recipes-kernel/linux/linux-aspeed/0001-Create-intel-purley-dts.patch b/meta-openbmc-mods/meta-wolfpass/recipes-kernel/linux/linux-aspeed/0001-Create-intel-purley-dts.patch index dc3f9846d..518b0067e 100644 --- a/meta-openbmc-mods/meta-wolfpass/recipes-kernel/linux/linux-aspeed/0001-Create-intel-purley-dts.patch +++ b/meta-openbmc-mods/meta-wolfpass/recipes-kernel/linux/linux-aspeed/0001-Create-intel-purley-dts.patch @@ -1,4 +1,4 @@ -From 939070905b0d6d70b2e39d424e0797451efdedf8 Mon Sep 17 00:00:00 2001 +From fb77288a4cb922bea97003a6ece97c527df8a0f2 Mon Sep 17 00:00:00 2001 From: Yuan Li <yuan.li@linux.intel.com> Date: Tue, 19 Sep 2017 15:55:39 +0800 Subject: [PATCH] ARM: dts: purley: Merge all dts node in the unified patch. @@ -21,22 +21,23 @@ The below changes to the dts file are merged together: * uart4/serail3 * enable high speed uart clock * timer pwm +* cpu0/1fault LEDs Signed-off-by: Yuan Li <yuan.li@linux.intel.com> Signed-off-by: Yong Li <yong.b.li@linux.intel.com> Signed-off-by: James Feist <james.feist@linux.intel.com> Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com> --- - arch/arm/boot/dts/aspeed-bmc-intel-purley.dts | 347 ++++++++++++++++++++++++++ - 1 file changed, 347 insertions(+) + arch/arm/boot/dts/aspeed-bmc-intel-purley.dts | 357 ++++++++++++++++++++++++++ + 1 file changed, 357 insertions(+) create mode 100644 arch/arm/boot/dts/aspeed-bmc-intel-purley.dts diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts b/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts new file mode 100644 -index 000000000000..8a18645e6316 +index 000000000000..4d70d776e330 --- /dev/null +++ b/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts -@@ -0,0 +1,347 @@ +@@ -0,0 +1,357 @@ +/dts-v1/; + +#include "aspeed-g5.dtsi" @@ -100,16 +101,27 @@ index 000000000000..8a18645e6316 + compatible = "gpio-leds"; + + identify { ++ default-state = "off"; + gpios = <&gpio ASPEED_GPIO(S, 6) GPIO_ACTIVE_LOW>; + }; + + status_amber { ++ default-state = "off"; + gpios = <&gpio ASPEED_GPIO(S, 5) GPIO_ACTIVE_LOW>; + }; + + status_green { ++ default-state = "keep"; + gpios = <&gpio ASPEED_GPIO(S, 4) GPIO_ACTIVE_LOW>; + }; ++ ++ cpu0fault { ++ gpios = <&gpio ASPEED_GPIO(F, 4) GPIO_ACTIVE_HIGH>; ++ }; ++ ++ cpu1fault { ++ gpios = <&gpio ASPEED_GPIO(F, 5) GPIO_ACTIVE_HIGH>; ++ }; + }; + + beeper { @@ -263,10 +275,12 @@ index 000000000000..8a18645e6316 +}; + +&i2c1 { ++ multi-master; + status = "okay"; +}; + +&i2c2 { ++ multi-master; + status = "okay"; +}; + @@ -297,17 +311,14 @@ index 000000000000..8a18645e6316 +}; + +&i2c6 { ++ multi-master; + status = "okay"; +}; + +&i2c7 { + multi-master; ++ #retries = <3>; + status = "okay"; -+ -+ smlink1-pmbus1@10 { -+ compatible = "slave-mqueue"; -+ reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>; -+ }; +}; + +&gfx { diff --git a/meta-openbmc-mods/meta-wolfpass/recipes-kernel/linux/linux-aspeed/wolfpass.cfg b/meta-openbmc-mods/meta-wolfpass/recipes-kernel/linux/linux-aspeed/wolfpass.cfg index 9549d4d7b..480d4cc18 100644 --- a/meta-openbmc-mods/meta-wolfpass/recipes-kernel/linux/linux-aspeed/wolfpass.cfg +++ b/meta-openbmc-mods/meta-wolfpass/recipes-kernel/linux/linux-aspeed/wolfpass.cfg @@ -8,6 +8,7 @@ CONFIG_ASPEED_ADC=y CONFIG_SGPIO_ASPEED=y CONFIG_CRC8=y CONFIG_PECI=y +CONFIG_PECI_CHARDEV=y CONFIG_PECI_ASPEED=y CONFIG_SENSORS_PECI_CPUTEMP=y CONFIG_SENSORS_PECI_DIMMTEMP=y @@ -58,3 +59,11 @@ CONFIG_PWM=y CONFIG_PWM_FTTMR010=y CONFIG_INPUT_MISC=y CONFIG_INPUT_PWM_BEEPER=y +CONFIG_VFAT_FS=y +CONFIG_NLS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_15=y +CONFIG_NLS_UTF8=y + diff --git a/meta-openbmc-mods/meta-wolfpass/recipes-phosphor/configuration/entity-manager/TNP-baseboard.json b/meta-openbmc-mods/meta-wolfpass/recipes-phosphor/configuration/entity-manager/TNP-baseboard.json new file mode 100644 index 000000000..01b899061 --- /dev/null +++ b/meta-openbmc-mods/meta-wolfpass/recipes-phosphor/configuration/entity-manager/TNP-baseboard.json @@ -0,0 +1,1945 @@ +{
+ "Exposes": [
+ {
+ "Address": "0x4A",
+ "Bus": 6,
+ "Name": "BMC Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Index": 0,
+ "Name": "Baseboard 12 Volt",
+ "PowerState": "On",
+ "ScaleFactor": 0.1124,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 13.494
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 13.101
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 10.945
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 10.616
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Name": "CPU 1 Fan Connector",
+ "Pwm": 7,
+ "Status": "disabled",
+ "Tachs": [
+ 13
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Name": "CPU 2 Fan Connector",
+ "Pwm": 8,
+ "Status": "disabled",
+ "Tachs": [
+ 14
+ ],
+ "Type": "IntelFanConnector"
+ },
+ {
+ "Address": "0x49",
+ "Bus": 6,
+ "Name": "Left Rear Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Index": 4,
+ "Name": "P0V83_LAN_AUX",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 0.901
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 0.875
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.786
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.763
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 3,
+ "Name": "P105_PCH_AUX",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.139
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.106
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.995
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.966
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 5,
+ "Name": "P12V_AUX",
+ "ScaleFactor": 0.1124,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 13.494
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 13.101
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 10.945
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 10.616
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 6,
+ "Name": "P1V8_PCH",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.961
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.904
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.699
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.648
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 1,
+ "Name": "P3V3",
+ "PowerState": "On",
+ "ScaleFactor": 0.4107,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 3.647
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 3.541
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 3.066
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 2.974
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 7,
+ "Name": "P3VBAT",
+ "ScaleFactor": 0.3333,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 3.296
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 3.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 2.457
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 2.138
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 8,
+ "Name": "PVCCIN_CPU0",
+ "PowerState": "On",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 2.151
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 2.088
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.418
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.376
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 9,
+ "Name": "PVCCIN_CPU1",
+ "PowerState": "On",
+ "ScaleFactor": 0.7505,
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 2.151
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 2.088
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.418
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.376
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 14,
+ "Name": "PVCCIO_CPU0",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.19
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.155
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.752
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.729
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 15,
+ "Name": "PVCCIO_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.19
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.155
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.752
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.729
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 10,
+ "Name": "PVDQ_ABCD_CPU0",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 12,
+ "Name": "PVDQ_ABCD_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 11,
+ "Name": "PVDQ_EFGH_CPU0",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 13,
+ "Name": "PVDQ_EFGH_CPU1",
+ "PowerState": "On",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.301
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.263
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 1.138
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 1.104
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Index": 2,
+ "Name": "PVNN_PCH_AUX",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 1.081
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 1.049
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 0.807
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0.783
+ }
+ ],
+ "Type": "ADC"
+ },
+ {
+ "Address": "0x4D",
+ "Bus": 6,
+ "Name": "Right Rear Board Temp",
+ "Name1": "Right Rear TMP421 Internal Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP421"
+ },
+ {
+ "Address": "0x48",
+ "Bus": 6,
+ "Name": "Voltage Regulator 1 Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x4B",
+ "Bus": 6,
+ "Name": "Voltage Regulator 2 Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "TMP75"
+ },
+ {
+ "Address": "0x30",
+ "Bus": 0,
+ "CpuID": 0,
+ "Name": "Skylake CPU 0",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Label": "DIMM",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 99
+ },
+ {
+ "Direction": "greater than",
+ "Label": "DIMM",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 89
+ }
+ ],
+ "Type": "SkylakeCPU"
+ },
+ {
+ "Address": "0x31",
+ "Bus": 0,
+ "CpuID": 1,
+ "Name": "Skylake CPU 1",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Label": "DIMM",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 99
+ },
+ {
+ "Direction": "greater than",
+ "Label": "DIMM",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 89
+ }
+ ],
+ "Type": "SkylakeCPU"
+ },
+ {
+ "Direction": "In",
+ "Index": 32,
+ "Name": "Reset Button",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 33,
+ "Name": "Reset Out",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Both",
+ "Index": 34,
+ "Name": "Power Button",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Both",
+ "Index": 35,
+ "Name": "Power Up",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 40,
+ "Name": "NMI Out",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 50,
+ "Name": "PCH Thermaltrip",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 51,
+ "Name": "Lcp Enter Button",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 52,
+ "Name": "Lcp Left Button",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 53,
+ "Name": "Lcp Right Button",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 49,
+ "Name": "Cpu Caterr",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 48,
+ "Name": "Cpu Err2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 63,
+ "Name": "PU 240VA Status",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 208,
+ "Name": "P3v3bat BridgeEn",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 214,
+ "Name": "Nmi Button",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 215,
+ "Name": "Post complete",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 217,
+ "Name": "Nmi Button",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 218,
+ "Name": "ID Button",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 219,
+ "Name": "Power Good",
+ "Polarity": "High",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 232,
+ "Name": "Post Complete led0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 233,
+ "Name": "Post Complete led1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 233,
+ "Name": "CPU1 Thermaltrip",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 234,
+ "Name": "Post Complete led2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 234,
+ "Name": "CPU1 VR Hot",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 235,
+ "Name": "Post Complete led3",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 236,
+ "Name": "Post Complete led4",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 236,
+ "Name": "CPU1 Mem VR Hot1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 237,
+ "Name": "Post Complete led5",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 237,
+ "Name": "CPU1 Mem VR Hot2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 238,
+ "Name": "Post Complete led6",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 239,
+ "Name": "Post Complete led7",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 232,
+ "Name": "CPU1 Present",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 235,
+ "Name": "CPU1 FIVR Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 238,
+ "Name": "CPU1 ID0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 240,
+ "Name": "CPU1 CH1 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 240,
+ "Name": "CPU1 Mismatch",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 241,
+ "Name": "CPU1 CH1 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 241,
+ "Name": "CPU1 DIMM Thermaltrip",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 242,
+ "Name": "CPU1 CH2 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 242,
+ "Name": "CPU2 Present",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 243,
+ "Name": "CPU1 CH2 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 243,
+ "Name": "CPU2 Thermaltrip",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 244,
+ "Name": "CPU1 CH3 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 244,
+ "Name": "CPU2 VR Hot",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 245,
+ "Name": "CPU1 CH3 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 245,
+ "Name": "CPU2 FIVR Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 246,
+ "Name": "CPU1 CH4 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 246,
+ "Name": "CPU2 Mem VR Hot1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 247,
+ "Name": "CPU1 CH4 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 247,
+ "Name": "CPU1 Mem VR Hot2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 248,
+ "Name": "CPU1 CH5 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 248,
+ "Name": "CPU2 ID0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 249,
+ "Name": "CPU1 CH5 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 250,
+ "Name": "CPU1 CH6 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 250,
+ "Name": "CPU2 Mismatch",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 251,
+ "Name": "CPU1 CH6 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 251,
+ "Name": "CPU2 DIMM Thermaltrip",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 252,
+ "Name": "Fan1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 253,
+ "Name": "Fan2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 254,
+ "Name": "Fan3 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 255,
+ "Name": "Fan4 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 256,
+ "Name": "Fan5 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 257,
+ "Name": "Fan6 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 258,
+ "Name": "Fan7 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 259,
+ "Name": "Fan8 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 260,
+ "Name": "CPU2 CH1 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 261,
+ "Name": "CPU1 CH1 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 262,
+ "Name": "CPU2 CH2 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 263,
+ "Name": "CPU2 CH2 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 264,
+ "Name": "CPU2 CH3 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 265,
+ "Name": "CPU2 CH3 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 266,
+ "Name": "CPU2 CH4 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 267,
+ "Name": "CPU2 CH4 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 268,
+ "Name": "CPU2 CH5 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 269,
+ "Name": "CPU2 CH5 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 270,
+ "Name": "CPU2 CH6 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 271,
+ "Name": "CPU2 CH6 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 272,
+ "Name": "CPU3 CH1 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 272,
+ "Name": "PLD Minor Revison Bit 0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 273,
+ "Name": "CPU3 CH1 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 273,
+ "Name": "PLD Minor Revison Bit 1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 274,
+ "Name": "CPU3 CH2 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 274,
+ "Name": "PLD Minor Revison Bit 2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 275,
+ "Name": "CPU3 CH2 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 275,
+ "Name": "PLD Minor Revison Bit 3",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 276,
+ "Name": "CPU3 CH3 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 276,
+ "Name": "PLD Major Revison Bit 0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 277,
+ "Name": "CPU3 CH3 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 277,
+ "Name": "PLD Major Revison Bit 1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 278,
+ "Name": "CPU3 CH4 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 278,
+ "Name": "PLD Major Revison Bit 2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 279,
+ "Name": "CPU3 CH4 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 279,
+ "Name": "PLD Major Revison Bit 2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 280,
+ "Name": "CPU3 CH5 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 280,
+ "Name": "Main PLD Minor Revison Bit 0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 281,
+ "Name": "CPU3 CH5 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 281,
+ "Name": "Main PLD Minor Revison Bit 1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 282,
+ "Name": "CPU3 CH6 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 282,
+ "Name": "Main PLD Minor Revison Bit 2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 283,
+ "Name": "CPU3 CH6 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 283,
+ "Name": "Main PLD Minor Revison Bit 3",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 284,
+ "Name": "CPU4 CH1 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 284,
+ "Name": "Main PLD Major Revison Bit 0",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 285,
+ "Name": "CPU4 CH1 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 285,
+ "Name": "Main PLD Major Revison Bit 1",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 286,
+ "Name": "CPU4 CH2 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 286,
+ "Name": "Main PLD Major Revison Bit 2",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 287,
+ "Name": "CPU4 CH2 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 287,
+ "Name": "Main PLD Major Revison Bit 3",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 288,
+ "Name": "CPU4 CH3 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 289,
+ "Name": "CPU4 CH3 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 289,
+ "Name": "Memory Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 290,
+ "Name": "CPU4 CH4 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 290,
+ "Name": "CPU Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 291,
+ "Name": "CPU4 CH4 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 291,
+ "Name": "P5V P3V3 Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 292,
+ "Name": "CPU4 CH5 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 292,
+ "Name": "PSU Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 293,
+ "Name": "CPU4 CH5 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 293,
+ "Name": "SAS Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 294,
+ "Name": "CPU4 CH6 DIMM1 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 294,
+ "Name": "Lan Aux Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Out",
+ "Index": 295,
+ "Name": "CPU4 CH6 DIMM2 FAULT",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Direction": "Input",
+ "Index": 295,
+ "Name": "PCH Pwr Fault",
+ "Polarity": "Low",
+ "Type": "Gpio"
+ },
+ {
+ "Address": "0x8",
+ "Class": "METemp",
+ "Name": "SSB Temp",
+ "PowerState": "BiosPost",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 103
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 98
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x7c",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 P12V PVCCIO VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x70",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 P12V PVCCIN VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x74",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 VR Mem ABC Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x78",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU1 VR Mem DEF Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x9c",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU2 P12V PVCCIO VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x50",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU2 P12V PVCCIN VR Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x94",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU2 VR Mem ABC Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x98",
+ "Class": "PxeBridgeTemp",
+ "Name": "CPU2 VR Mem DEF Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0xAC",
+ "Class": "PxeBridgeTemp",
+ "Name": "VR P1V05 Temp",
+ "Thresholds": [
+ {
+ "Direction": "greater than",
+ "Name": "upper critical",
+ "Severity": 1,
+ "Value": 115
+ },
+ {
+ "Direction": "greater than",
+ "Name": "upper non critical",
+ "Severity": 0,
+ "Value": 110
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower non critical",
+ "Severity": 0,
+ "Value": 5
+ },
+ {
+ "Direction": "less than",
+ "Name": "lower critical",
+ "Severity": 1,
+ "Value": 0
+ }
+ ],
+ "Type": "IpmbSensor"
+ },
+ {
+ "Address": "0x71",
+ "Bus": 2,
+ "ChannelNames": [
+ "M2_Slot1",
+ "M2_Slot2",
+ "",
+ ""
+ ],
+ "Name": "M.2 Mux",
+ "Type": "PCA9543Mux"
+ }
+ ],
+ "Name": "TNP Baseboard",
+ "Probe": "xyz.openbmc_project.FruDevice({'PRODUCT_PRODUCT_NAME': '.*TNP'})",
+ "Type": "Board",
+ "xyz.openbmc_project.Inventory.Decorator.Asset": {
+ "Manufacturer": "$PRODUCT_MANUFACTURER",
+ "Model": "$PRODUCT_PRODUCT_NAME",
+ "PartNumber": "$PRODUCT_PART_NUMBER",
+ "SerialNumber": "$PRODUCT_SERIAL_NUMBER"
+ }
+}
diff --git a/meta-openbmc-mods/meta-wolfpass/recipes-phosphor/configuration/entity-manager_%.bbappend b/meta-openbmc-mods/meta-wolfpass/recipes-phosphor/configuration/entity-manager_%.bbappend index d9fe8e10f..51c47c35e 100644 --- a/meta-openbmc-mods/meta-wolfpass/recipes-phosphor/configuration/entity-manager_%.bbappend +++ b/meta-openbmc-mods/meta-wolfpass/recipes-phosphor/configuration/entity-manager_%.bbappend @@ -1,6 +1,7 @@ FILESEXTRAPATHS_append := ":${THISDIR}/${PN}" SRC_URI_append = " file://WC-Baseboard.json \ - file://WP-Baseboard.json" + file://WP-Baseboard.json \ + file://TNP-baseboard.json" RDEPENDS_${PN} += " default-fru" diff --git a/meta-openbmc-mods/meta-wolfpass/recipes-phosphor/fru/default-fru/S2600TNP.fru.bin b/meta-openbmc-mods/meta-wolfpass/recipes-phosphor/fru/default-fru/S2600TNP.fru.bin Binary files differnew file mode 100644 index 000000000..afd58e6b9 --- /dev/null +++ b/meta-openbmc-mods/meta-wolfpass/recipes-phosphor/fru/default-fru/S2600TNP.fru.bin diff --git a/meta-openbmc-mods/meta-wolfpass/recipes-phosphor/fru/default-fru/checkFru.sh b/meta-openbmc-mods/meta-wolfpass/recipes-phosphor/fru/default-fru/checkFru.sh index b619dac8b..1eb79b299 100755 --- a/meta-openbmc-mods/meta-wolfpass/recipes-phosphor/fru/default-fru/checkFru.sh +++ b/meta-openbmc-mods/meta-wolfpass/recipes-phosphor/fru/default-fru/checkFru.sh @@ -2,7 +2,7 @@ # this script checks the gpio id and loads the correct baseboard fru fruFile="/etc/fru/baseboard.fru.bin" -idGpio=( 8 9 10 11 12) +idGpio=( 8 9 10 11 12 53) result=0 idx=0 @@ -21,14 +21,17 @@ do done # wp -if (($result == 30)); then +if (($result == 62)); then cat S2600WP.fru.bin > $fruFile # wc -elif (($result == 13)); then +elif (($result == 45)); then cat S2600WC.fru.bin > $fruFile # cyp -elif (($result == 28)); then +elif (($result == 60)); then cat S2600CYP.fru.bin > $fruFile +# tnp +elif (($result == 12)); then + cat S2600TNP.fru.bin > $fruFile # default to wft else cat S2600WFT.fru.bin > $fruFile |