mirror of
https://github.com/Telecominfraproject/OpenNetworkLinux.git
synced 2025-12-25 17:27:01 +00:00
Merge pull request #12 from opencomputeproject/master
merge from upstream
This commit is contained in:
12
.gitmodules
vendored
12
.gitmodules
vendored
@@ -1,21 +1,21 @@
|
||||
[submodule "packages/base/any/initrds/buildroot/builds/buildroot-mirror"]
|
||||
path = packages/base/any/initrds/buildroot/builds/buildroot-mirror
|
||||
url = git://github.com/opennetworklinux/buildroot-mirror
|
||||
url = http://github.com/opennetworklinux/buildroot-mirror
|
||||
[submodule "packages/base/any/kernels/legacy/linux-3.9.6"]
|
||||
path = packages/base/any/kernels/legacy/linux-3.9.6
|
||||
url = git://github.com/opennetworklinux/linux-3.9.6
|
||||
url = http://github.com/opennetworklinux/linux-3.9.6
|
||||
[submodule "sm/infra"]
|
||||
path = sm/infra
|
||||
url = git://github.com/floodlight/infra
|
||||
url = http://github.com/floodlight/infra
|
||||
[submodule "sm/bigcode"]
|
||||
path = sm/bigcode
|
||||
url = git://github.com/floodlight/bigcode
|
||||
url = http://github.com/floodlight/bigcode
|
||||
[submodule "packages/base/any/kernels/legacy/linux-3.8.13"]
|
||||
path = packages/base/any/kernels/legacy/linux-3.8.13
|
||||
url = git://github.com/opennetworklinux/linux-3.8.13
|
||||
url = http://github.com/opennetworklinux/linux-3.8.13
|
||||
[submodule "packages/platforms-closed"]
|
||||
path = packages/platforms-closed
|
||||
url = git@github.com:opennetworklinux/platforms-closed
|
||||
[submodule "sm/build-artifacts"]
|
||||
path = sm/build-artifacts
|
||||
url = git://github.com/opennetworklinux/build-artifacts
|
||||
url = http://github.com/opennetworklinux/build-artifacts
|
||||
|
||||
@@ -144,7 +144,19 @@ if test "$installer_debug"; then
|
||||
fi
|
||||
|
||||
# Pickup ONIE defines for this machine.
|
||||
if test -r /etc/machine.conf; then
|
||||
if test "$onie_platform"; then
|
||||
:
|
||||
else
|
||||
onie_platform=$(onie-sysinfo -p 2>/dev/null) || :
|
||||
fi
|
||||
if test "$onie_arch"; then
|
||||
:
|
||||
else
|
||||
onie_arch=$(onie-sysinfo -c 2>/dev/null) || :
|
||||
fi
|
||||
if test "$onie_platform"; then
|
||||
:
|
||||
elif test -r /etc/machine.conf; then
|
||||
. /etc/machine.conf
|
||||
fi
|
||||
|
||||
@@ -252,7 +264,7 @@ if test "${onie_platform}"; then
|
||||
}
|
||||
else
|
||||
if test "$ARCH_X86"; then
|
||||
echo "Missing onie_platform (invalid /etc/machine.conf)" 1>&2
|
||||
echo "Missing onie_platform (invalid or missing onie-sysinfo or /etc/machine.conf)" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
#
|
||||
@@ -472,6 +484,11 @@ mkdir -p "${rootdir}/etc/onl"
|
||||
cp /dev/null "${rootdir}/etc/onl/installer.conf"
|
||||
echo "onl_version=\"$onl_version\"" >> "${rootdir}/etc/onl/installer.conf"
|
||||
|
||||
# pass in the platform identifier, otherwise encoded in
|
||||
# machine-XXX.conf and onie-sysinfo
|
||||
echo "onie_platform=$onie_platform" >> "${rootdir}/etc/onl/installer.conf"
|
||||
echo "onie_arch=$onie_arch" >> "${rootdir}/etc/onl/installer.conf"
|
||||
|
||||
# Generate the MD5 signature for ourselves for future reference.
|
||||
installer_md5=$(md5sum "$0" | awk '{print $1}')
|
||||
echo "installer_md5=\"$installer_md5\"" >> "${rootdir}/etc/onl/installer.conf"
|
||||
@@ -561,7 +578,7 @@ if test -f "$postinst"; then
|
||||
fi
|
||||
|
||||
installer_unzip $installer_zip postinstall.sh || :
|
||||
if test -f preinstall.sh; then
|
||||
if test -f postinstall.sh; then
|
||||
chmod +x postinstall.sh
|
||||
./postinstall.sh $rootdir
|
||||
fi
|
||||
|
||||
@@ -78,3 +78,4 @@
|
||||
- tcpdump
|
||||
- strace
|
||||
- sysstat
|
||||
- ipmitool
|
||||
|
||||
@@ -11,5 +11,7 @@
|
||||
- hw-management
|
||||
- sx-kernel
|
||||
- onl-kernel-3.16-lts-x86-64-all-modules
|
||||
- onl-kernel-4.9-lts-x86-64-all-modules
|
||||
- onl-kernel-4.14-lts-x86-64-all-modules
|
||||
- efibootmgr
|
||||
- gdisk
|
||||
|
||||
@@ -23,7 +23,7 @@ Multistrap:
|
||||
noauth: true
|
||||
explicitsuite: false
|
||||
unpack: true
|
||||
debootstrap: Debian-Local Local-All Local-Arch ONL
|
||||
debootstrap: Debian-Local Local-All Local-Arch ONL-Local
|
||||
aptsources: Debian ONL
|
||||
|
||||
Debian:
|
||||
@@ -46,6 +46,12 @@ Multistrap:
|
||||
suite: unstable
|
||||
omitdebsrc: true
|
||||
|
||||
ONL-Local:
|
||||
packages: *Packages
|
||||
source: http://${APT_CACHE}apt.opennetlinux.org/debian
|
||||
suite: unstable
|
||||
omitdebsrc: true
|
||||
|
||||
Local-All:
|
||||
source: ${ONLPM_OPTION_REPO}/${ONL_DEBIAN_SUITE}/packages/binary-all
|
||||
omitdebsrc: true
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
- usbutils
|
||||
- mtd-utils
|
||||
- i2c-tools
|
||||
- kmod
|
||||
- isc-dhcp-client
|
||||
- ntp
|
||||
- wget
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
- grub2
|
||||
- onl-upgrade
|
||||
- hw-management
|
||||
- sx-kernel
|
||||
- onl-kernel-3.16-lts-x86-64-all-modules
|
||||
- onl-kernel-4.9-lts-x86-64-all-modules
|
||||
- onl-kernel-4.14-lts-x86-64-all-modules
|
||||
- efibootmgr
|
||||
- gdisk
|
||||
|
||||
@@ -23,7 +23,7 @@ Multistrap:
|
||||
noauth: true
|
||||
explicitsuite: false
|
||||
unpack: true
|
||||
debootstrap: Debian-Local Local-All Local-Arch ONL
|
||||
debootstrap: Debian-Local Local-All Local-Arch ONL-Local
|
||||
aptsources: Debian ONL
|
||||
|
||||
Debian:
|
||||
@@ -46,6 +46,12 @@ Multistrap:
|
||||
suite: unstable
|
||||
omitdebsrc: true
|
||||
|
||||
ONL-Local:
|
||||
packages: *Packages
|
||||
source: http://${APT_CACHE}apt.opennetlinux.org/debian
|
||||
suite: unstable
|
||||
omitdebsrc: true
|
||||
|
||||
Local-All:
|
||||
source: ${ONLPM_OPTION_REPO}/${ONL_DEBIAN_SUITE}/packages/binary-all
|
||||
omitdebsrc: true
|
||||
|
||||
@@ -42,7 +42,7 @@ Multistrap:
|
||||
|
||||
ONL:
|
||||
packages: *Packages
|
||||
source: http://apt.opennetlinux.org/debian
|
||||
source: http://${APT_CACHE}apt.opennetlinux.org/debian
|
||||
suite: unstable
|
||||
omitdebsrc: true
|
||||
|
||||
|
||||
24
docs/README-proxy.md
Normal file
24
docs/README-proxy.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# How to build ONL behind an HTTP Proxy
|
||||
|
||||
Many corporate environments don't provide native access to the Internet
|
||||
and instead all access must go through an HTTP proxy. Since the ONL
|
||||
build process dynamically pulls lots of things, this can be a pain.
|
||||
While everyone's setup is different, hopefully these directions help
|
||||
reduce that pain.
|
||||
|
||||
* Make sure you have apt-cacher-ng installed in your host (non-docker)
|
||||
environment and that docker starts it. Next, configure it to use
|
||||
your proxy:
|
||||
|
||||
$ grep Proxy /etc/apt-cacher-ng/acng.conf
|
||||
Proxy: http://myproxy.mycompany.com:8080
|
||||
$ sudo /etc/init.d/apt-cacher-ng restart
|
||||
|
||||
* Make sure your git config is configured correctly for
|
||||
proxies:
|
||||
|
||||
$ cat ~/.gitconfig
|
||||
[https]
|
||||
proxy = myproxy.mycompany.com:8080
|
||||
[https]
|
||||
proxy = myproxy.mycompany.com:8080
|
||||
@@ -1,107 +1,114 @@
|
||||
Hardware Support
|
||||
================
|
||||
Because of the HTML formatting, this page may be best viewed from
|
||||
<http://opennetlinux.org/hcl>
|
||||
|
||||
|
||||
Quanta
|
||||
------
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr class="info">
|
||||
<th> Device <th> Ports <th> CPU <th> Forwarding <th> ONL Certified <th> In Lab <th> OF-DPA <th> OpenNSL <th> SAI </tr>
|
||||
</thead>
|
||||
<tr> <td> QuantaMesh T1048-LB9 <td> 48x1G + 4x10G <td> FreeScale P2020 <td> Broadcom BCM56534 (Firebolt3) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
|
||||
<tr> <td> QuantaMesh T3048-LY2 <td> 48x10G + 4x40G <td> FreeScale P2020 <td> Broadcom BCM56846 (Trident+) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
|
||||
<tr> <td> QuantaMesh T3048-LY8 <td> 48x10G + 6x40G <td> Intel Rangeley C2758 x86 <td> Broadcom BCM56854 (Trident2) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
|
||||
<tr> <td> QuantaMesh T5032-LY6 <td> 32x40G <td> Intel Rangeley C2758 x86 <td> Broadcom BCM56850 (Trident2) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
|
||||
<tr> <td> QuantaMesh T3048-LY9 <td> 48x10GT + 6x40G <td> Intel Rangeley C2758 x86 <td> Broadcom BCM56850 (Trident2) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
|
||||
</table>
|
||||
|
||||
|
||||
Accton/Edge-Core
|
||||
------
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr class="info">
|
||||
<th> Device <th> Ports <th> CPU <th> Forwarding <th> ONL Certified <th> In Lab <th> OF-DPA <th> OpenNSL <th> SAI </tr>
|
||||
</thead>
|
||||
<tr> <td> Accton AS4600-54T <td> 48x1G + 4x10G <td> FreeScale P2020 <td> Broadcom BCM56540 (Apollo2) <td> Yes <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
|
||||
<tr> <td> Accton AS4610-54P <td> 48x1G + 4x10G + 2x20G <td> Dual-core ARM Cortex A9 1GHz <td> Broadcom BCM56340 (Helix4) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
|
||||
<tr> <td> Accton AS5610-52X <td> 48x10G + 4x40G <td> FreeScale P2020 <td> Broadcom BCM56846 (Trident+) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
|
||||
<tr> <td> Accton AS5710-54X <td> 48x10G + 6x40G <td> FreeScale P2041 <td> Broadcom BCM56854 (Trident2) <td> Yes <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
|
||||
<tr> <td> Accton AS6700-32X <td> 32x40G <td> FreeScale P2041 <td> Broadcom BCM56850 (Trident2) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
|
||||
<tr> <td> Accton AS5512-54X <td> 48x10G + 6x40G <td> Intel Rangeley C2538 x86 <td> MediaTek/Nephos MT3258 <td> Yes <td> Yes <td> No <td> No <td> No </tr>
|
||||
<tr> <td> Accton AS5712-54X <td> 48x10G + 6x40G <td> Intel Rangeley C2538 x86 <td> Broadcom BCM56854 (Trident2) <td> Yes <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
|
||||
<tr> <td> Accton AS6712-32X <td> 32x40G <td> Intel Rangeley C2538 x86 <td> Broadcom BCM56850 (Trident2) <td> Yes <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
|
||||
<tr> <td> Accton AS5812-54T <td> 48x10G + 6x40G <td> Intel Rangeley C2538 x86 <td> Broadcom BCM56864 (Trident2+) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
|
||||
<tr> <td> Accton AS5812-54X <td> 48x10G + 6x40G <td> Intel Rangeley C2538 x86 <td> Broadcom BCM56864 (Trident2+) <td> Yes <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
|
||||
<tr> <td> Accton AS6812-32X <td> 32x40G <td> Intel Rangeley C2538 x86 <td> Broadcom BCM56864 (Trident2+) <td> Yes <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
|
||||
<tr> <td> Accton AS7712-32X <td> 32x100G <td> Intel Rangeley C2538 x86 <td> Broadcom BCM56960 (Tomahawk) <td> Yes <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
|
||||
<tr> <td> Accton AS7716-32X <td> 32x100G <td> Intel Xeon D-1518 x86 <td> Broadcom BCM56960 (Tomahawk) <td> Yes <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
|
||||
<tr> <td> Accton Wedge-16X <td> 16x40G <td> Intel Rangeley C2550 x86 <td> Broadcom BCM56864 (Trident2+) <td> Work In Progress** <td> Yes <td> No <td> Yes <td> No </tr>
|
||||
<tr> <td> Accton (FB) Wedge 100 <td> 32x100G <td> Intel Bay Trail E3845 x86 <td> Broadcom BCM56960 (Tomahawk) <td> Work In Progress** <td> Yes <td> No <td> Yes <td> No </tr>
|
||||
</table>
|
||||
Device Ports CPU Forwarding In Lab
|
||||
Accton AS4600-54T 48x1G + 4x10G FreeScale P2020 Broadcom BCM56540 (Apollo2) Yes
|
||||
Accton AS4610-54P 48x1G + 4x10G + 2x20G Dual-core ARM Cortex A9 Broadcom BCM56340 (Helix4) Yes
|
||||
Accton AS5512-54X 48x10G + 6x40G Intel C2538 MediaTek/Nephos MT3258 Yes
|
||||
Accton AS5610-52X 48x10G + 4x40G FreeScale P2020 Broadcom BCM56846 (Trident+) Yes
|
||||
Accton AS5710-54X 48x10G + 6x40G FreeScale P2041 Broadcom BCM56854 (Trident2) Yes
|
||||
Accton AS5712-54X 48x10G + 6x40G Intel C2538 Broadcom BCM56854 (Trident2) Yes
|
||||
Accton AS5812-54T 48x10G + 6x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes
|
||||
Accton AS5812-54X 48x10G + 6x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes
|
||||
Accton AS5822-32X 48x10G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) Yes
|
||||
Accton AS5912-54X 48x10G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) Yes
|
||||
Accton AS5912-54XK 48x10G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) Yes
|
||||
Accton AS5916-54XM 48x10G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) No
|
||||
Accton AS5916-54X 48x10G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) No
|
||||
Accton AS6700-32X 32x40G FreeScale P2041 Broadcom BCM56850 (Trident2) Yes
|
||||
Accton AS6712-32X 32x40G Intel C2538 Broadcom BCM56850 (Trident2) Yes
|
||||
Accton AS6812-32X 32x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes
|
||||
Accton AS7312-54X 48x25G + 6x100G Intel C2558 Broadcom BCM88375 (Qumran) Yes
|
||||
Accton AS7712-32X 32x100G Intel C2538 Broadcom BCM56960 (Tomahawk) Yes
|
||||
Accton AS7716-32X 32x100G Intel Xeon D-1518 Broadcom BCM56960 (Tomahawk) Yes
|
||||
Accton AS7816-64X 64x100 Intel C2558 Broadcom BCM56970 (Tomahawk II) Yes
|
||||
Accton Wedge-16X 16x40G Intel C2550 Broadcom BCM56864 (Trident2+) Yes
|
||||
Accton Wedge 100-32X 32x100G Intel E3845 Broadcom BCM56960 (Tomahawk) Yes
|
||||
Accton Wedge 100S-32X 32x100G Intel D1508 Broadcom BCM56960 (Tomahawk) Yes
|
||||
|
||||
Alpha Networks
|
||||
---
|
||||
Device Ports CPU Forwarding In Lab
|
||||
SNX-60A0-486F 48x10G + 6x40G Intel C2558 Broadcom BCM56850 (Trident2) Yes
|
||||
|
||||
Celestica
|
||||
---
|
||||
Device Ports CPU Forwarding In Lab
|
||||
Redstone-XP 48x10G + 6x40G Intel C2558 Broadcom BCM56854 (Trident2) Yes
|
||||
Seastone 32x100G Intel C2558 Broadcom BCM56960 (Tomahawk) No
|
||||
|
||||
DNI/Agema
|
||||
---
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr class="info">
|
||||
<th> Device <th> Ports <th> CPU <th> Forwarding <th> ONL Certified <th> In Lab <th> OF-DPA <th> OpenNSL <th> SAI </tr>
|
||||
</thead>
|
||||
<tr> <td> AG-7448CU <td> 48x10G + 4x40G <td> FreeScale P2020 <td> Broadcom BCM56845 (Trident) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
|
||||
</table>
|
||||
Device Ports CPU Forwarding In Lab
|
||||
AG-7448CU 48x10G + 4x40G FreeScale P2020 Broadcom BCM56845 (Trident) Yes
|
||||
AG-5648 48x25G + 6x100G Intel D1548 Broadcom BCM56960 (Tomahawk) No
|
||||
AG-5648v1 48x25G + 6x100G Intel D1548 Broadcom BCM56963 (Tomahawk+) No
|
||||
AG-7648 48x10G + 6x40G Intel D1548 Broadcom BCM56854 (Trident2) Yes
|
||||
AG-9032v1 32x100G Intel D1548 Broadcom BCM56960 (Tomahawk) Yes
|
||||
AG-9032v2 32x100G Intel D1548 Broadcom BCM56963 (Tomahawk+) No
|
||||
AG-9064 64x100G Intel D1547 Broadcom BCM56970 (Tomahawk II) No
|
||||
AGC-5648S 48x25G + 6x100G Intel D1548 Broadcom BCM88680 (Jericho+) No
|
||||
AGC-7648A 48x10G + 6x100G Intel D1548 Broadcom BCM88370 (Qumran MX) No
|
||||
WB-2448 48x1GT + 4x10G Intel E3805 Broadcom BCM56150 (Hurricane2) No
|
||||
AG-6248C 48x1GT + 2x10G ARM A9 1GHz Broadcom BCM56340 (Helix4) Yes
|
||||
|
||||
Dell
|
||||
---
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr class="info">
|
||||
<th> Device <th> Ports <th> CPU <th> Forwarding <th> ONL Certified <th> In Lab <th> OF-DPA <th> OpenNSL <th> SAI </tr>
|
||||
</thead>
|
||||
<tr> <td> S4810-ON <td> 48x10G + 4x40G <td> FreeScale P2020 <td> Broadcom BCM56845 (Trident) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
|
||||
<tr> <td> S4048-ON <td> 48x10G + 6x40G <td> Intel Atom C2338 <td> Broadcom BCM56854 (Trident2) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
|
||||
<tr> <td> S6000-ON <td> 32x40G <td> Intel Atom S1220 <td> Broadcom BCM56850 (Trident2) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
|
||||
<tr> <td> Z9100-ON <td> 32x100G <td> Intel Atom C2538 <td> Broadcom BCM56960 (Tomahawk) <td> Yes <td> Yes <td> No <td> No <td> No </tr>
|
||||
</table>
|
||||
Device Ports CPU Forwarding In Lab
|
||||
S4000-ON 48x10G + 6x40G Intel C2338 Broadcom BCM56854 (Trident2) Yes
|
||||
S4810-ON 48x10G + 4x40G FreeScale P2020 Broadcom BCM56845 (Trident) Yes
|
||||
S4048-ON 48x10G + 6x40G Intel C2338 Broadcom BCM56854 (Trident2) Yes
|
||||
S6000-ON 32x40G Intel S1220 Broadcom BCM56850 (Trident2) Yes
|
||||
S6010-ON 32x40G Intel S1220 Broadcom BCM56850 (Trident2) Yes
|
||||
S6100-ON 64x50G/128x25G Intel C2538 Broadcom BCM56960 (Tomahawk) Yes
|
||||
Z9100-ON 32x100G Intel C2538 Broadcom BCM56960 (Tomahawk) Yes
|
||||
|
||||
Interface Masters Technologies, Inc.
|
||||
HPE
|
||||
---
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr class="info">
|
||||
<th> Device <th> Ports <th> CPU <th> Forwarding <th> ONL Certified <th> In Lab <th> OF-DPA <th> OpenNSL <th> SAI </tr>
|
||||
</thead>
|
||||
<tr> <td> Niagara 2948X12XLm <td> 48x10G + 12x40G <td> Intel/AMD x86 <td> Broadcom BCM56850 (Trident2) <td> Work In Progress** <td> No <td> Yes*** <td> Yes*** <td> No </tr>
|
||||
<tr> <td> Niagara 2960X6XLm <td> 60x10G + 6x40G <td> Intel/AMD x86 <td> Broadcom BCM56850 (Trident2) <td> Work In Progress** <td> No <td> Yes*** <td> Yes*** <td> No </tr>
|
||||
<tr> <td> Niagara 2972Xm <td> 72x10G <td> Intel/AMD x86 <td> Broadcom BCM56850 (Trident2) <td> Work In Progress** <td> Yes <td> Yes*** <td> Yes*** <td> No </tr>
|
||||
<tr> <td> Niagara 2932XL <td> 32x40G <td> Intel/AMD x86 <td> Broadcom BCM56850 (Trident2) <td> Work In Progress** <td> No <td> Yes*** <td> Yes*** <td> No </tr>
|
||||
<tr> <td> Niagara 2948X6XL <td> 48x10G + 6x40G <td> Intel/AMD x86 <td> Broadcom BCM56850 (Trident2) <td> Work In Progress** <td> No <td> Yes*** <td> Yes <td> No </tr>
|
||||
</table>
|
||||
Device Ports CPU Forwarding In Lab
|
||||
Altoline 6921 48x10G + 6x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes
|
||||
Altoline 6921T 48x10G + 6x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes
|
||||
Altoline 6941 32x40G Intel C2538 Broadcom BCM56864 (Trident2+) Yes
|
||||
Altoline 6960 32x100G Intel C2538 Broadcom BCM56960 (Tomahawk) Yes
|
||||
|
||||
Ingrasys
|
||||
---
|
||||
Device Ports CPU Forwarding In Lab
|
||||
S9100-32X 32x100G Intel Broadcom BCM56960 (Tomahawk) No
|
||||
|
||||
Inventec
|
||||
---
|
||||
Device Ports CPU Forwarding In Lab
|
||||
D7032Q28B 32x100G Intel No
|
||||
|
||||
Mellanox
|
||||
---
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr class="info">
|
||||
<th> Device <th> Ports <th> CPU <th> Forwarding <th> ONL Certified <th> In Lab <th> SAI </tr>
|
||||
</thead>
|
||||
<tr> <td> SN2100 <td> 16x100G <td> Intel Rangeley C2558 <td> Mellanox Spectrum <td> Yes <td> Yes <td> Yes </tr>
|
||||
<tr> <td> SN2100B <td> 16x40G <td> Intel Rangeley C2558 <td> Mellanox Spectrum <td> Yes <td> No <td> Yes </tr>
|
||||
<tr> <td> SN2410 <td> 48x25G + 8x100G <td> Intel Ivybridge 1047UE <td> Mellanox Spectrum <td> Yes <td> Yes <td> Yes </tr>
|
||||
<tr> <td> SN2410B <td> 48x10G + 8x100G <td> Intel Ivybridge 1047UE <td> Mellanox Spectrum <td> Yes <td> No <td> Yes </tr>
|
||||
<tr> <td> SN2700 <td> 32x100G <td> Intel Ivybridge 1047UE <td> Mellanox Spectrum <td> Yes <td> Yes <td> Yes </tr>
|
||||
<tr> <td> SN2700B <td> 32x40G <td> Intel Ivybridge 1047UE <td> Mellanox Spectrum <td> Yes <td> No <td> Yes </tr>
|
||||
</table>
|
||||
Device Ports CPU Forwarding In Lab
|
||||
SN2100 16x100G Intel C2558 Mellanox Spectrum Yes
|
||||
SN2100B 16x40G Intel C2558 Mellanox Spectrum No
|
||||
SN2410 48x25G + 8x100G Intel 1047UE Mellanox Spectrum Yes
|
||||
SN2410B 48x10G + 8x100G Intel 1047UE Mellanox Spectrum No
|
||||
SN2700 32x100G Intel 1047UE Mellanox Spectrum Yes
|
||||
SN2700B 32x40G Intel 1047UE Mellanox Spectrum No
|
||||
|
||||
Notes:
|
||||
Netberg
|
||||
---
|
||||
Device Ports CPU Forwarding In Lab
|
||||
Aurora 620 32x100G Intel C2558 Broadcom BCM56960 (Tomahawk) Yes
|
||||
Aurora 720 48x10/25G + 6x40/100G Intel C2558 Broadcom BCM56960 (Tomahawk) Yes
|
||||
|
||||
ONL Certified means that the system runs ONIE, is able to install a generic version of ONL and has the ONL Platform drivers necessary to manage the system.
|
||||
|
||||
\* Systems no longer in the lab cannot be certified post removal
|
||||
|
||||
\** Developing ONL Platform Drivers
|
||||
|
||||
\*** Vendor provided
|
||||
Quanta
|
||||
------
|
||||
Device Ports CPU Forwarding In Lab
|
||||
QuantaMesh T1048-LB9 48x1G + 4x10G FreeScale P2020 Broadcom BCM56534 (Firebolt3) Yes
|
||||
QuantaMesh T3048-LY2 48x10G + 4x40G FreeScale P2020 Broadcom BCM56846 (Trident+) Yes
|
||||
QuantaMesh T5032-LY6 32x40G Intel C2758 Broadcom BCM56850 (Trident2) Yes
|
||||
QuantaMesh T3048-LY7 48x10G + 4x100G Intel C2558 Broadcom BCM56768 (Maverick) Yes
|
||||
QuantaMesh T3048-LY8 48x10G + 6x40G Intel C2758 Broadcom BCM56854 (Trident2) Yes
|
||||
QuantaMesh T3048-LY9 48x10GT + 6x40G Intel C2758 Broadcom BCM56850 (Trident2) Yes
|
||||
QuantaMesh T7032-IX1 32x100G Intel C2758 Broadcom BCM56960 (Tomahawk) Yes
|
||||
QuantaMesh T7032-IX1B 32x100G Intel C2758 Broadcom BCM56960 (Tomahawk) Yes
|
||||
QuantaMesh T4048-IX2 48xSFP28 + 8xQSFP28 Intel C2758 Broadcom BCM56960 (Tomahawk) Yes
|
||||
QuantaMesh T4048-IX8 48x10G + 8x100G Intel Broadcom BCM56870 (Trident 3) Yes
|
||||
|
||||
@@ -176,7 +176,7 @@ MODSYNCLIST_DEFAULT := .config Module.symvers Makefile include scripts drivers \
|
||||
arch/powerpc/include arch/powerpc/Makefile arch/powerpc/lib arch/powerpc/boot/dts \
|
||||
arch/arm/include arch/arm/Makefile arch/arm/lib arch/arm/boot/dts
|
||||
|
||||
MODSYNCLIST := $(MODSYNCLIST_DEFAULT) $(MODSYNCLIST_EXTRA)
|
||||
MODSYNCLIST := $(MODSYNCLIST_DEFAULT) $(MODSYNCLIST_EXTRA) $(K_MODSYNCLIST)
|
||||
|
||||
# This file must be preserved for PPC module builds.
|
||||
MODSYNCKEEP := arch/powerpc/lib/crtsavres.o
|
||||
|
||||
@@ -33,7 +33,7 @@ RFS_MANIFEST := etc/onl/rootfs/manifest.json
|
||||
endif
|
||||
|
||||
RFS:
|
||||
$(ONL_V_at) rm -rf manifest.json
|
||||
$(ONL_V_at) sudo rm -rf manifest.json
|
||||
$(ONL_V_at) $(RFS_COMMAND)
|
||||
$(ONL_V_at) [ -f $(RFS_DIR)/$(RFS_MANIFEST) ] && cp $(RFS_DIR)/$(RFS_MANIFEST) .
|
||||
|
||||
@@ -44,3 +44,6 @@ clean:
|
||||
|
||||
show-packages:
|
||||
$(ONL_V_at) $(RFS_COMMAND) --show-packages
|
||||
|
||||
build-packages:
|
||||
$(ONL_V_at) $(RFS_COMMAND) --only-build-packages
|
||||
|
||||
@@ -21,6 +21,9 @@ if [ -f /etc/onl/abort ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -f /mnt/onl/boot/autoboot ]; then
|
||||
. /mnt/onl/boot/autoboot
|
||||
fi
|
||||
|
||||
#
|
||||
# The maximum number of times we will retry autobooting before
|
||||
@@ -118,4 +121,3 @@ else
|
||||
msg_error "BOOTMODE $BOOTMODE is not implemented. Autobooting cannot continue."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import zipfile
|
||||
import onl.install.InstallUtils
|
||||
MountContext = onl.install.InstallUtils.MountContext
|
||||
BlkidParser = onl.install.InstallUtils.BlkidParser
|
||||
UbinfoParser = onl.install.InstallUtils.UbinfoParser
|
||||
ProcMountsParser = onl.install.InstallUtils.ProcMountsParser
|
||||
|
||||
import onl.mounts
|
||||
@@ -221,7 +222,7 @@ class Runner(onl.install.InstallUtils.SubprocessMixin):
|
||||
|
||||
blkid = BlkidParser(log=self.log)
|
||||
|
||||
if ':' in SWI:
|
||||
if not SWI.startswith('/') and ':' in SWI:
|
||||
devspec, sep, r = SWI.partition(':')
|
||||
|
||||
p = "/dev/%s" % devspec
|
||||
@@ -247,6 +248,14 @@ class Runner(onl.install.InstallUtils.SubprocessMixin):
|
||||
part = blkid[label]
|
||||
except IndexError:
|
||||
part = None
|
||||
if part is None:
|
||||
ubinfo = UbinfoParser(log=self.log)
|
||||
part = {}
|
||||
part = ubinfo[label]
|
||||
device = "/dev/" + part['device'] + "_" + part['Volume ID']
|
||||
|
||||
return self.blockdevCopy(device, r, dir=mpt)
|
||||
|
||||
if part is not None:
|
||||
return self.blockdevCopy(part.device, r, dir=mpt)
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import logging
|
||||
|
||||
import onl.install.InstallUtils
|
||||
BlkidParser = onl.install.InstallUtils.BlkidParser
|
||||
UbinfoParser = onl.install.InstallUtils.UbinfoParser
|
||||
|
||||
import onl.mounts
|
||||
MountContext = onl.install.InstallUtils.MountContext
|
||||
@@ -26,6 +27,7 @@ class Runner(onl.install.InstallUtils.SubprocessMixin):
|
||||
self.log = log
|
||||
|
||||
self.blkid = BlkidParser(log=self.log)
|
||||
self.ubinfo = UbinfoParser(log=self.log)
|
||||
|
||||
def mount(self, SWI):
|
||||
|
||||
@@ -125,6 +127,13 @@ class Runner(onl.install.InstallUtils.SubprocessMixin):
|
||||
part = self.blkid[label]
|
||||
except IndexError:
|
||||
part = None
|
||||
if part is None:
|
||||
part = {}
|
||||
part = self.ubinfo[label]
|
||||
|
||||
device = "/dev/" + part['device'] + "_" + part['Volume ID']
|
||||
|
||||
return self.blockdevMount(device, path, dir=mpt)
|
||||
if part is not None:
|
||||
return self.blockdevMount(part.device, path, dir=mpt)
|
||||
|
||||
@@ -141,7 +150,12 @@ class Runner(onl.install.InstallUtils.SubprocessMixin):
|
||||
if not os.path.exists(dst):
|
||||
self.log.error("missing SWI: %s", dst)
|
||||
return None
|
||||
self.check_call(('mount', '-o', 'rw,remount', dst,))
|
||||
p = dev.find('ubi')
|
||||
if p < 0:
|
||||
self.check_call(('mount', '-o', 'rw,remount', dst,))
|
||||
else:
|
||||
self.check_call(('mount', '-t', 'ubifs', '-o', 'rw,remount', dst,))
|
||||
|
||||
return dst
|
||||
|
||||
with MountContext(device=dev, log=self.log) as ctx:
|
||||
@@ -154,7 +168,12 @@ class Runner(onl.install.InstallUtils.SubprocessMixin):
|
||||
# move to its proper location as per mtab
|
||||
# XXX perms may not be right here
|
||||
if dir is not None:
|
||||
self.check_call(('mount', '-o', 'rw,remount', ctx.dir,))
|
||||
p = dev.find('ubi')
|
||||
if p < 0:
|
||||
self.check_call(('mount', '-o', 'rw,remount', ctx.dir,))
|
||||
else:
|
||||
self.check_call(('mount', '-t', 'ubifs', '-o', 'rw,remount', ctx.dir,))
|
||||
|
||||
self.check_call(('mount', '--move', ctx.dir, dir,))
|
||||
ctx.mounted = False
|
||||
dst = dir
|
||||
|
||||
@@ -15,8 +15,8 @@ if [ ! -d /mnt/onl/data ]; then
|
||||
fi
|
||||
|
||||
# make sure it's mounted as per mtab.yml
|
||||
d1=$(stat -f -c '%d' /mnt/onl)
|
||||
d2=$(stat -f -c '%d' /mnt/onl/data)
|
||||
d1=$(stat -f -c '%b' /mnt/onl)
|
||||
d2=$(stat -f -c '%b' /mnt/onl/data)
|
||||
if [ "$d1" -eq "$d2" ]; then
|
||||
msg_error "Unmounted /mnt/onl/data, disk boot cannot continue"
|
||||
exit 200
|
||||
|
||||
7
packages/base/all/vendor-config-onl/src/bin/onie-sysinfo
Executable file
7
packages/base/all/vendor-config-onl/src/bin/onie-sysinfo
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
"""Run native onie-sysinfo
|
||||
"""
|
||||
|
||||
import onl.install.ShellApp
|
||||
onl.install.ShellApp.OnieSysinfoApp.main()
|
||||
9
packages/base/all/vendor-config-onl/src/bin/onldebni
Executable file
9
packages/base/all/vendor-config-onl/src/bin/onldebni
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
/bin/echo -e "#!/bin/sh\\nexit 101" >/usr/sbin/policy-rc.d
|
||||
chmod +x /usr/sbin/policy-rc.d
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
export DEBCONF_NONINTERACTIVE_SEEN=true
|
||||
$@
|
||||
rc=$?
|
||||
rm -f /usr/sbin/policy-rc.d
|
||||
exit $rc
|
||||
@@ -122,10 +122,8 @@ installer_mkchroot() {
|
||||
mkdir -p "${rootdir}${TMPDIR}"
|
||||
fi
|
||||
|
||||
# export ONIE defines to the installer
|
||||
if test -r /etc/machine.conf; then
|
||||
cp /etc/machine.conf "${rootdir}/etc/machine.conf"
|
||||
fi
|
||||
# export ONIE defines to the installer, if they exist
|
||||
cp /etc/machine*.conf "${rootdir}/etc/."
|
||||
|
||||
# export ONL defines to the installer
|
||||
mkdir -p "${rootdir}/etc/onl"
|
||||
|
||||
@@ -129,6 +129,13 @@ default:
|
||||
- ext2load mmc 0:1 $onl_loadaddr $onl_itb
|
||||
- "bootm $onl_loadaddr#$onl_platform"
|
||||
|
||||
#ubifs to boot onl
|
||||
flash_bootcmds: &flash_bootcmds
|
||||
- ubi part open
|
||||
- ubifsmount ONL-BOOT
|
||||
- ubifsload $loadaddr $onl_itb
|
||||
- "bootm $onl_loadaddr#$onl_platform"
|
||||
|
||||
nos_bootcmds: *ide_bootcmds
|
||||
|
||||
# Configure the fw_env.config file,
|
||||
|
||||
@@ -31,6 +31,11 @@ default:
|
||||
=: kernel-4.9-lts-x86_64-all
|
||||
package: onl-kernel-4.9-lts-x86-64-all:amd64
|
||||
|
||||
|
||||
kernel-4.14: &kernel-4-14
|
||||
=: kernel-4.14-lts-x86_64-all
|
||||
package: onl-kernel-4.14-lts-x86-64-all:amd64
|
||||
|
||||
# pick one of the above kernels
|
||||
kernel:
|
||||
<<: *kernel-3-16
|
||||
|
||||
@@ -111,6 +111,8 @@ class OnlBootConfigNet(OnlBootConfig):
|
||||
self.delete('NETIP')
|
||||
self.delete('NETMASK')
|
||||
self.delete('NETGW')
|
||||
self.delete('NETDNS')
|
||||
self.delete('NETDOMAIN')
|
||||
self.set('NETAUTO', 'dhcp')
|
||||
|
||||
def netauto_get(self):
|
||||
@@ -137,13 +139,27 @@ class OnlBootConfigNet(OnlBootConfig):
|
||||
def netgw_get(self):
|
||||
return self.keys.get('NETGW', None)
|
||||
|
||||
def netdns_set(self, dns):
|
||||
self.delete('NETAUTO')
|
||||
self.keys['NETDNS'] = dns
|
||||
|
||||
def netdns_get(self):
|
||||
return self.keys.get('NETDNS', None)
|
||||
|
||||
def netdomain_set(self, domain):
|
||||
self.delete('NETAUTO')
|
||||
self.keys['NETDOMAIN'] = domain
|
||||
|
||||
def netdomain_get(self):
|
||||
return self.keys.get('NETDOMAIN', None)
|
||||
|
||||
def __validate(self):
|
||||
if 'NETAUTO' not in self.keys:
|
||||
|
||||
netip = self.keys.get('NETIP', None)
|
||||
if netip:
|
||||
if not self.is_ip_address(netip):
|
||||
raise ValueError("NETIP=%s is not a valid ip-address" % (netup))
|
||||
raise ValueError("NETIP=%s is not a valid ip-address" % (netip))
|
||||
elif self.NET_REQUIRED:
|
||||
raise ValueError("No IP configuration set for the management interface.")
|
||||
|
||||
@@ -168,6 +184,11 @@ class OnlBootConfigNet(OnlBootConfig):
|
||||
elif netip or netmask or netgw:
|
||||
raise ValueError("Incomplete static network configuration. NETIP, NETMASK, and NETGW must all be set.")
|
||||
|
||||
netdns = self.keys.get('NETDNS', None)
|
||||
if netdns:
|
||||
if not self.is_ip_address(netdns):
|
||||
raise ValueError("NETDNS=%s is not a valid ip-address" % (netdns))
|
||||
|
||||
elif self.keys['NETAUTO'] not in ['dhcp', 'up']:
|
||||
raise ValueError("The NETAUTO value '%s' is invalid." % self.keys['NETAUTO'])
|
||||
elif self.keys['NETAUTO'] == 'up' and self.NET_REQUIRED:
|
||||
@@ -214,7 +235,8 @@ class OnlBootConfigNet(OnlBootConfig):
|
||||
ap.add_argument("--ip", help='Set static IP address for the management interface.', type=OnlBootConfigNet.argparse_type_is_ip_address)
|
||||
ap.add_argument("--netmask", help='Set the static netmask for the management interface.', type=OnlBootConfigNet.argparse_type_is_netmask)
|
||||
ap.add_argument("--gateway", help='Set the gateway address.', type=OnlBootConfigNet.argparse_type_is_ip_address)
|
||||
|
||||
ap.add_argument("--dns", help='Set the dns server.', type=OnlBootConfigNet.argparse_type_is_ip_address)
|
||||
ap.add_argument("--domain", help='Set the dns domain.')
|
||||
|
||||
def __argparse_process(self, ops):
|
||||
if ops.dhcp:
|
||||
@@ -229,6 +251,12 @@ class OnlBootConfigNet(OnlBootConfig):
|
||||
if ops.gateway:
|
||||
self.netgw_set(ops.gateway)
|
||||
|
||||
if ops.dns:
|
||||
self.netdns_set(ops.dns)
|
||||
|
||||
if ops.domain:
|
||||
self.netdomain_set(ops.domain)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
bc = OnlBootConfigNet()
|
||||
|
||||
@@ -17,7 +17,7 @@ import time
|
||||
from InstallUtils import InitrdContext
|
||||
from InstallUtils import SubprocessMixin
|
||||
from InstallUtils import ProcMountsParser
|
||||
from ShellApp import OnieBootContext
|
||||
from ShellApp import OnieBootContext, OnieSysinfo
|
||||
import ConfUtils, BaseInstall
|
||||
|
||||
class App(SubprocessMixin, object):
|
||||
@@ -129,7 +129,7 @@ class App(SubprocessMixin, object):
|
||||
def runLocalOrChroot(self):
|
||||
|
||||
if self.machineConf is None:
|
||||
self.log.error("missing machine.conf")
|
||||
self.log.error("missing onie-sysinfo or machine.conf")
|
||||
return 1
|
||||
if self.installerConf is None:
|
||||
self.log.error("missing installer.conf")
|
||||
@@ -230,10 +230,17 @@ class App(SubprocessMixin, object):
|
||||
def runLocal(self):
|
||||
|
||||
self.log.info("getting installer configuration")
|
||||
if os.path.exists(ConfUtils.MachineConf.PATH):
|
||||
osi = OnieSysinfo(log=self.log.getChild("onie-sysinfo"))
|
||||
try:
|
||||
halp = osi.help
|
||||
except AttributeError:
|
||||
halp = None
|
||||
if halp is not None:
|
||||
self.machineConf = osi
|
||||
elif os.path.exists(ConfUtils.MachineConf.PATH):
|
||||
self.machineConf = ConfUtils.MachineConf()
|
||||
else:
|
||||
self.log.warn("missing /etc/machine.conf from ONIE runtime")
|
||||
self.log.warn("missing onie-sysinfo or /etc/machine.conf from ONIE runtime")
|
||||
self.machineConf = ConfUtils.MachineConf(path='/dev/null')
|
||||
|
||||
self.installerConf = ConfUtils.InstallerConf()
|
||||
@@ -243,21 +250,38 @@ class App(SubprocessMixin, object):
|
||||
def findPlatform(self):
|
||||
|
||||
plat = arch = None
|
||||
if os.path.exists(ConfUtils.MachineConf.PATH):
|
||||
|
||||
def _p2a(plat):
|
||||
if plat.startswith('x86-64'):
|
||||
return 'x86_64'
|
||||
else:
|
||||
return plat.partition('-')[0]
|
||||
|
||||
# recover platform specifier from installer configuration
|
||||
if plat is None:
|
||||
plat = getattr(self.installerConf, 'onie_platform', None)
|
||||
if plat:
|
||||
self.log.info("ONL installer running chrooted.")
|
||||
plat = plat.replace('_', '-').replace('.', '-')
|
||||
arch = getattr(self.installerConf, 'onie_arch', None)
|
||||
|
||||
# recover platform specifier from legacy ONIE machine.conf
|
||||
if plat is None and self.machineConf is not None:
|
||||
plat = getattr(self.machineConf, 'onie_platform', None)
|
||||
arch = getattr(self.machineConf, 'onie_arch', None)
|
||||
if plat and arch:
|
||||
if plat:
|
||||
self.log.info("ONL installer running under ONIE.")
|
||||
plat = plat.replace('_', '-').replace('.', '-')
|
||||
elif os.path.exists("/etc/onl/platform"):
|
||||
|
||||
# recover platform specifier from ONL runtime
|
||||
if plat is None and os.path.exists("/etc/onl/platform"):
|
||||
with open("/etc/onl/platform") as fd:
|
||||
plat = fd.read().strip()
|
||||
if plat.startswith('x86-64'):
|
||||
arch = 'x86_64'
|
||||
else:
|
||||
arch = plat.partition('-')[0]
|
||||
self.log.info("ONL installer running under ONL or ONL loader.")
|
||||
|
||||
if plat is not None and arch is None:
|
||||
arch = _p2a(plat)
|
||||
|
||||
if plat and arch:
|
||||
self.installerConf.installer_platform = plat
|
||||
self.installerConf.installer_arch = arch
|
||||
|
||||
@@ -17,7 +17,7 @@ import imp
|
||||
import fnmatch, glob
|
||||
|
||||
from InstallUtils import SubprocessMixin
|
||||
from InstallUtils import MountContext, BlkidParser, PartedParser
|
||||
from InstallUtils import MountContext, BlkidParser, PartedParser, UbinfoParser
|
||||
from InstallUtils import ProcMountsParser
|
||||
from InstallUtils import GdiskParser
|
||||
from InstallUtils import OnieSubprocess
|
||||
@@ -83,6 +83,7 @@ class Base:
|
||||
# keep track of next partition/next block
|
||||
|
||||
self.blkidParts = []
|
||||
self.ubiParts = []
|
||||
# current scan of partitions and labels
|
||||
|
||||
self.partedDevice = None
|
||||
@@ -853,7 +854,203 @@ class GrubInstaller(SubprocessMixin, Base):
|
||||
def shutdown(self):
|
||||
Base.shutdown(self)
|
||||
|
||||
class UbootInstaller(SubprocessMixin, Base):
|
||||
class UBIfsCreater(SubprocessMixin, Base):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
Base.__init__(self, *args, **kwargs)
|
||||
self.log = logging.getLogger("ubinfo -a")
|
||||
self.device = self.im.getDevice()
|
||||
self.ubiParts = None
|
||||
"""Set up an UBI file system."""
|
||||
|
||||
def ubifsinit(self):
|
||||
UNITS = {
|
||||
'GiB' : 1024 * 1024 * 1024,
|
||||
'G' : 1000 * 1000 * 1000,
|
||||
'MiB' : 1024 * 1024,
|
||||
'M' : 1000 * 1000,
|
||||
'KiB' : 1024,
|
||||
'K' : 1000,
|
||||
}
|
||||
try:
|
||||
code = 0
|
||||
if not code:
|
||||
mtd_num = self.device[-1]
|
||||
cmd = ('ubiformat', '/dev/mtd' + mtd_num)
|
||||
self.check_call(cmd, vmode=self.V2)
|
||||
cmd = ('ubiattach', '-m', mtd_num, '-d', '0', '/dev/ubi_ctrl',)
|
||||
self.check_call(cmd, vmode=self.V2)
|
||||
for part in self.im.platformConf['installer']:
|
||||
label, partData = list(part.items())[0]
|
||||
if type(partData) == dict:
|
||||
sz, fmt = partData['='], partData.get('format', 'ubifs')
|
||||
else:
|
||||
sz, fmt = partData, 'ubifs'
|
||||
cnt = None
|
||||
for ul, ub in UNITS.items():
|
||||
if sz.endswith(ul):
|
||||
cnt = int(sz[:-len(ul)], 10) * ub
|
||||
break
|
||||
if cnt is None:
|
||||
self.log.error("invalid size (no units) for %s: %s",part, sz)
|
||||
return 1
|
||||
label = label.strip()
|
||||
cmd = ('ubimkvol', '/dev/ubi0', '-N', label, '-s', bytes(cnt),)
|
||||
self.check_call(cmd, vmode=self.V2)
|
||||
except Exception:
|
||||
self.log.exception("cannot create UBI file systemfrom %s",self.device)
|
||||
|
||||
return 0
|
||||
|
||||
def ubi_mount(self, dir, devpart):
|
||||
|
||||
if devpart is None:
|
||||
self.log.error("Mount failed.no given mount device part")
|
||||
return 1
|
||||
if dir is None:
|
||||
self.log.error("Mount failed.no given mount directory")
|
||||
return 1
|
||||
if self.ubiParts is None:
|
||||
try:
|
||||
self.ubiParts = UbinfoParser(log=self.log.getChild("ubinfo -a"))
|
||||
except Exception:
|
||||
self.log.exception("Mount failed.No UBIfs")
|
||||
return 1
|
||||
try:
|
||||
dev = self.ubiParts[devpart]
|
||||
except IndexError as ex:
|
||||
self.log.error("Mount failed.cannot find %s partition", str(devpart))
|
||||
return 1
|
||||
self.makedirs(dir)
|
||||
device = "/dev/" + dev['device'] + "_" + dev['Volume ID']
|
||||
if dev['fsType']:
|
||||
cmd = ('mount', '-t', dev['fsType'], device, dir,)
|
||||
else:
|
||||
cmd = ('mount', device, dir,)
|
||||
code = self.check_call(cmd, vmode=self.V2)
|
||||
if code:
|
||||
self.log.error("Mount failed.mount command exect failed")
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def ubi_unmount(self,dir=None):
|
||||
|
||||
if dir is None:
|
||||
self.log.error("Unmount failed.no given unmount directory")
|
||||
return 1
|
||||
cmd = ('umount', dir)
|
||||
code = self.check_call(cmd, vmode=self.V2)
|
||||
if code:
|
||||
self.log.error("Unmount failed.umount command exect failed")
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def ubi_getinfo(self):
|
||||
try:
|
||||
self.ubiParts = UbinfoParser(log=self.log.getChild("ubinfo -a"))
|
||||
except Exception:
|
||||
self.log.exception("UBI info get failed.No UBIfs")
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def ubi_installSwi(self):
|
||||
|
||||
files = os.listdir(self.im.installerConf.installer_dir) + self.zf.namelist()
|
||||
|
||||
swis = [x for x in files if x.endswith('.swi')]
|
||||
|
||||
if not swis:
|
||||
self.log.warn("No ONL Software Image available for ubi installation.")
|
||||
self.log.warn("Post-install ZTN installation will be required.")
|
||||
|
||||
if len(swis) > 1:
|
||||
self.log.error("Multiple SWIs found in ubi installer: %s", " ".join(swis))
|
||||
return 1
|
||||
|
||||
base = swis[0]
|
||||
|
||||
self.log.info("Installing ONL Software Image (%s)...", base)
|
||||
dev = "ONL-IMAGES"
|
||||
dstDir = "/tmp/ubifs"
|
||||
code = self.ubi_mount(dstDir,dev)
|
||||
if code :
|
||||
return 1
|
||||
dst = os.path.join(dstDir, base)
|
||||
self.installerCopy(base, dst)
|
||||
self.log.info("syncing block devices(%s)...",dev)
|
||||
self.check_call(('sync',))
|
||||
self.ubi_unmount(dstDir)
|
||||
return 0
|
||||
|
||||
def ubi_installLoader(self):
|
||||
|
||||
loaderBasename = None
|
||||
for c in sysconfig.installer.fit:
|
||||
if self.installerExists(c):
|
||||
loaderBasename = c
|
||||
break
|
||||
if not loaderBasename:
|
||||
self.log.error("The platform loader file is missing.")
|
||||
return 1
|
||||
|
||||
self.log.info("Installing the ONL loader from %s...", loaderBasename)
|
||||
dev = "ONL-BOOT"
|
||||
dstDir = "/tmp/ubiloader"
|
||||
code = self.ubi_mount(dstDir,dev)
|
||||
if code :
|
||||
return 1
|
||||
dst = os.path.join(dstDir, "%s.itb" % self.im.installerConf.installer_platform)
|
||||
self.installerCopy(loaderBasename, dst)
|
||||
self.log.info("syncing block devices(%s)...",dev)
|
||||
self.check_call(('sync',))
|
||||
self.ubi_unmount(dstDir)
|
||||
return 0
|
||||
|
||||
def ubi_installBootConfig(self):
|
||||
|
||||
basename = 'boot-config'
|
||||
|
||||
self.log.info("Installing boot-config to ONL-BOOT partion")
|
||||
dev = "ONL-BOOT"
|
||||
dstDir = "/tmp/ubibootcon"
|
||||
code = self.ubi_mount(dstDir,dev)
|
||||
if code :
|
||||
return 1
|
||||
dst = os.path.join(dstDir, basename)
|
||||
self.installerCopy(basename, dst, True)
|
||||
with open(dst) as fd:
|
||||
buf = fd.read()
|
||||
ecf = buf.encode('base64', 'strict').strip()
|
||||
if self.im.grub and self.im.grubEnv is not None:
|
||||
setattr(self.im.grubEnv, 'boot_config_default', ecf)
|
||||
if self.im.uboot and self.im.ubootEnv is not None:
|
||||
setattr(self.im.ubootEnv, 'boot-config-default', ecf)
|
||||
self.log.info("syncing block devices(%s)...",dev)
|
||||
self.check_call(('sync',))
|
||||
self.ubi_unmount(dstDir)
|
||||
return 0
|
||||
|
||||
def ubi_installOnlConfig(self):
|
||||
|
||||
self.log.info("Installing onl-config to ONL-CONFIG partion")
|
||||
dev = "ONL-CONFIG"
|
||||
dstDir = "/tmp/ubionlconfig"
|
||||
code = self.ubi_mount(dstDir,dev)
|
||||
if code :
|
||||
return 1
|
||||
for f in self.zf.namelist():
|
||||
d = 'config/'
|
||||
if f.startswith(d) and f != d:
|
||||
dst = os.path.join(dstDir, os.path.basename(f))
|
||||
if not os.path.exists(dst):
|
||||
self.installerCopy(f, dst)
|
||||
self.log.info("syncing block devices(%s)...",dev)
|
||||
self.check_call(('sync',))
|
||||
self.ubi_unmount(dstDir)
|
||||
return 0
|
||||
|
||||
|
||||
class UbootInstaller(SubprocessMixin, UBIfsCreater):
|
||||
|
||||
class installmeta(Base.installmeta):
|
||||
|
||||
@@ -874,13 +1071,16 @@ class UbootInstaller(SubprocessMixin, Base):
|
||||
cmds.append("setenv onl_itb %s" % itb)
|
||||
for item in self.platformConf['loader']['setenv']:
|
||||
k, v = list(item.items())[0]
|
||||
cmds.append("setenv %s %s" % (k, v,))
|
||||
device = self.getDevice()
|
||||
if "mtdblock" in device:
|
||||
cmds.append("setenv %s %s ${platformargs} ubi.mtd=%s root=/dev/ram ethaddr=$ethaddr" % (k, v, device[-1],))
|
||||
else:
|
||||
cmds.append("setenv %s %s" % (k, v,))
|
||||
cmds.extend(self.platformConf['loader']['nos_bootcmds'])
|
||||
return "; ".join(cmds)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
Base.__init__(self, *args, **kwargs)
|
||||
|
||||
UBIfsCreater.__init__(self, *args, **kwargs)
|
||||
self.device = self.im.getDevice()
|
||||
|
||||
self.rawLoaderDevice = None
|
||||
@@ -1014,6 +1214,24 @@ class UbootInstaller(SubprocessMixin, Base):
|
||||
|
||||
code = self.assertUnmounted()
|
||||
if code: return code
|
||||
|
||||
if "mtdblock" in self.device:
|
||||
code = self.ubifsinit()
|
||||
if code: return code
|
||||
code = self.ubi_getinfo()
|
||||
if code: return code
|
||||
code = self.ubi_installSwi()
|
||||
if code: return code
|
||||
code = self.ubi_installLoader()
|
||||
if code: return code
|
||||
code = self.ubi_installBootConfig()
|
||||
if code: return code
|
||||
code = self.ubi_installOnlConfig()
|
||||
if code: return code
|
||||
code = self.runPlugins(Plugin.PLUGIN_POSTINSTALL)
|
||||
if code: return code
|
||||
code = self.installUbootEnv()
|
||||
return code
|
||||
|
||||
code = self.maybeCreateLabel()
|
||||
if code: return code
|
||||
@@ -1035,6 +1253,7 @@ class UbootInstaller(SubprocessMixin, Base):
|
||||
self.log.info("found a disk with %d blocks",
|
||||
self.partedDevice.getLength())
|
||||
|
||||
self.blkidParts = BlkidParser(log=self.log.getChild("blkid"))
|
||||
code = self.findMsdos()
|
||||
if code: return code
|
||||
|
||||
|
||||
@@ -63,18 +63,30 @@ class ConfFileBase(ConfBase):
|
||||
PATH = None
|
||||
# Override me
|
||||
|
||||
def __init__(self, path=None):
|
||||
SHELL = False
|
||||
# override me
|
||||
|
||||
def __init__(self, path=None, shell=False):
|
||||
self.__dict__['path'] = path or self.PATH
|
||||
self.__dict__['shell'] = shell or self.SHELL
|
||||
ConfBase.__init__(self)
|
||||
|
||||
def _parse(self):
|
||||
self.__dict__['_data'] = {}
|
||||
with open(self.path) as fd:
|
||||
for line in fd.xreadlines():
|
||||
if self.SHELL:
|
||||
cmd = "IFS=; set -e; . '%s'; set +e; set | egrep ^[a-zA-Z][a-zA-Z0-9_]*=" % self.path
|
||||
buf = subprocess.check_output(cmd, shell=True)
|
||||
for line in buf.splitlines(False):
|
||||
self._feedLine(line)
|
||||
else:
|
||||
with open(self.path) as fd:
|
||||
for line in fd.xreadlines():
|
||||
self._feedLine(line)
|
||||
|
||||
class MachineConf(ConfFileBase):
|
||||
"""XXX roth -- deprecated, machine.conf is executable shell now."""
|
||||
PATH = "/etc/machine.conf"
|
||||
SHELL = True
|
||||
|
||||
class InstallerConf(ConfFileBase):
|
||||
PATH = "/etc/onl/installer.conf"
|
||||
|
||||
@@ -388,6 +388,63 @@ class BlkidParser(SubprocessMixin):
|
||||
def __len__(self):
|
||||
return len(self.parts)
|
||||
|
||||
class UbinfoParser(SubprocessMixin):
|
||||
|
||||
def __init__(self, log=None):
|
||||
self.log = log or logging.getLogger("ubinfo -a")
|
||||
self.parse()
|
||||
|
||||
def parse(self):
|
||||
self.parts = []
|
||||
lines = ''
|
||||
try:
|
||||
cmd = ('ubinfo', '-a',)
|
||||
lines = self.check_output(cmd).splitlines()
|
||||
except Exception as ex:
|
||||
return self
|
||||
|
||||
dev = None
|
||||
volId = None
|
||||
name = None
|
||||
attrs = {}
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
|
||||
p = line.find(':')
|
||||
if p < 0: continue
|
||||
name, value = line[:p], line[p+1:].strip()
|
||||
if 'Volume ID' in name:
|
||||
p = value.find('(')
|
||||
if p < 0: continue
|
||||
volumeId = value[:p].strip()
|
||||
attrs['Volume ID'] = volumeId
|
||||
p = value.find('on')
|
||||
if p < 0: continue
|
||||
dev = value[p+2:-1].strip()
|
||||
attrs['device'] = dev
|
||||
|
||||
if 'Name' in name:
|
||||
dev = "/dev/" + dev + "_" + volumeId
|
||||
p = line.find(':')
|
||||
if p < 0: continue
|
||||
attrs['Name'] = line[p+1:].strip()
|
||||
attrs['fsType'] = 'ubifs'
|
||||
self.parts.append(attrs)
|
||||
dev = None
|
||||
volId = None
|
||||
name = None
|
||||
attrs = {}
|
||||
|
||||
def __getitem__(self, idxOrName):
|
||||
if type(idxOrName) == int:
|
||||
return self.parts[idxOrName]
|
||||
for part in self.parts:
|
||||
if part['Name'] == idxOrName: return part
|
||||
raise IndexError("cannot find partition %s" % repr(idxOrName))
|
||||
|
||||
def __len__(self):
|
||||
return len(self.parts)
|
||||
|
||||
class ProcMtdEntry:
|
||||
|
||||
def __init__(self,
|
||||
|
||||
@@ -15,9 +15,6 @@ from InstallUtils import ProcMountsParser, ProcMtdParser
|
||||
from InstallUtils import BlkidParser
|
||||
from InstallUtils import UbootInitrdContext
|
||||
|
||||
import onl.platform.current
|
||||
from onl.sysconfig import sysconfig
|
||||
|
||||
class AppBase(SubprocessMixin, object):
|
||||
|
||||
@property
|
||||
@@ -228,6 +225,105 @@ class Onie(AppBase):
|
||||
with OnieBootContext(log=self.log) as ctx:
|
||||
return self._runInitrdShell(ctx.initrd)
|
||||
|
||||
class OnieSysinfoApp(SubprocessMixin, object):
|
||||
|
||||
PROG = "onie-sysinfo"
|
||||
|
||||
def __init__(self, args=[], log=None):
|
||||
|
||||
if log is not None:
|
||||
self.log = log
|
||||
else:
|
||||
self.log = logging.getLogger(self.__class__.__name__)
|
||||
self.args = args or ['-p',]
|
||||
self.output = None
|
||||
|
||||
def _runInitrdShell(self, initrd):
|
||||
with InitrdContext(initrd=initrd, log=self.log) as ctx:
|
||||
cmd = ['onie-sysinfo',]
|
||||
cmd.extend(self.args)
|
||||
cmd = ('chroot', ctx.dir,
|
||||
'/bin/sh', '-c', 'IFS=;' + " ".join(cmd))
|
||||
try:
|
||||
self.output = self.check_output(cmd)
|
||||
ret = 0
|
||||
except subprocess.CalledProcessError, what:
|
||||
self.log.error("failed command: %s", " ".join(what.cmd))
|
||||
for line in (what.output or "").splitlines():
|
||||
self.log.error(">>> %s", line)
|
||||
ret = what.returncode
|
||||
return ret
|
||||
|
||||
def run(self):
|
||||
with OnieBootContext(log=self.log) as ctx:
|
||||
ret = self._runInitrdShell(ctx.initrd)
|
||||
if self.output is not None:
|
||||
sys.stdout.write(self.output)
|
||||
return ret
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def main(cls):
|
||||
|
||||
logging.basicConfig()
|
||||
logger = logging.getLogger(cls.PROG)
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
args = list(sys.argv[1:])
|
||||
sysinfoArgs = []
|
||||
while args:
|
||||
|
||||
if args[0] in ('-v', '--verbose',):
|
||||
logger.setLevel(logging.DEBUG)
|
||||
args.pop(0)
|
||||
continue
|
||||
|
||||
if args[0] in ('-q', '--quiet',):
|
||||
logger.setLevel(logging.ERROR)
|
||||
args.pop(0)
|
||||
continue
|
||||
|
||||
sysinfoArgs.append(args.pop(0))
|
||||
|
||||
app = cls(args=sysinfoArgs, log=logger)
|
||||
try:
|
||||
code = app.run()
|
||||
except:
|
||||
logger.exception("runner failed")
|
||||
code = 1
|
||||
app.shutdown()
|
||||
sys.exit(code)
|
||||
|
||||
class OnieSysinfo(OnieSysinfoApp):
|
||||
|
||||
def _runArgs(self, *args):
|
||||
self.args = args
|
||||
with OnieBootContext(log=self.log) as ctx:
|
||||
ret = self._runInitrdShell(ctx.initrd)
|
||||
if self.output is not None:
|
||||
return self.output.rstrip()
|
||||
raise AttributeError("cannot retrieve onie-sysinfo attribute via %s" % str(args))
|
||||
|
||||
@property
|
||||
def help(self):
|
||||
return self._runArgs('-h')
|
||||
|
||||
@property
|
||||
def onie_platform(self):
|
||||
return self._runArgs('-p')
|
||||
|
||||
@property
|
||||
def onie_arch(self):
|
||||
return self._runArgs('-c')
|
||||
|
||||
@property
|
||||
def onie_version(self):
|
||||
return self._runArgs('-v')
|
||||
|
||||
# XXX roth other switches too
|
||||
|
||||
class Loader(AppBase):
|
||||
"""Application shell that uses the (installed) loader runtime."""
|
||||
|
||||
@@ -331,6 +427,7 @@ class Loader(AppBase):
|
||||
|
||||
def run(self):
|
||||
|
||||
import onl.platform.current
|
||||
self.platform = onl.platform.current.OnlPlatform()
|
||||
self.pc = self.platform.platform_config
|
||||
|
||||
@@ -353,6 +450,7 @@ class Upgrader(AppBase):
|
||||
|
||||
def runGrub(self):
|
||||
|
||||
from onl.sysconfig import sysconfig
|
||||
d = sysconfig.upgrade.loader.package.dir
|
||||
for b in sysconfig.upgrade.loader.package.grub:
|
||||
p = os.path.join(d, b)
|
||||
@@ -365,6 +463,7 @@ class Upgrader(AppBase):
|
||||
|
||||
def runUboot(self):
|
||||
|
||||
from onl.sysconfig import sysconfig
|
||||
d = sysconfig.upgrade.loader.package.dir
|
||||
for b in sysconfig.upgrade.loader.package.fit:
|
||||
p = os.path.join(d, b)
|
||||
@@ -377,6 +476,7 @@ class Upgrader(AppBase):
|
||||
|
||||
def run(self):
|
||||
|
||||
import onl.platform.current
|
||||
self.platform = onl.platform.current.OnlPlatform()
|
||||
self.pc = self.platform.platform_config
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import shutil
|
||||
import argparse
|
||||
import fnmatch
|
||||
import subprocess
|
||||
import glob
|
||||
|
||||
from onl.install.InstallUtils import InitrdContext
|
||||
from onl.install.InstallUtils import ProcMountsParser
|
||||
@@ -58,10 +59,11 @@ class App(SubprocessMixin):
|
||||
self.log.info("onie directory is %s", octx.onieDir)
|
||||
self.log.info("initrd directory is %s", octx.initrdDir)
|
||||
|
||||
src = os.path.join(octx.initrdDir, "etc/machine.conf")
|
||||
dst = os.path.join(ctx.dir, "etc/machine.conf")
|
||||
self.log.debug("+ /bin/cp %s %s", src, dst)
|
||||
shutil.copy2(src, dst)
|
||||
srcPat = os.path.join(octx.initrdDir, "etc/machine*.conf")
|
||||
for src in glob.glob(srcPat):
|
||||
dst = os.path.join(ctx.dir, "etc", os.path.split(src)[1])
|
||||
self.log.debug("+ /bin/cp %s %s", src, dst)
|
||||
shutil.copy2(src, dst)
|
||||
|
||||
src = "/etc/fw_env.config"
|
||||
if os.path.exists(src):
|
||||
@@ -98,6 +100,13 @@ class App(SubprocessMixin):
|
||||
pass
|
||||
installerConf.installer_zip = os.path.split(zipPath)[1]
|
||||
|
||||
import onl.platform.current
|
||||
plat = onl.platform.current.OnlPlatformName
|
||||
if plat.startswith('x86-64'):
|
||||
plat = 'x86_64' + plat[6:]
|
||||
installerConf.onie_platform = plat
|
||||
installerConf.onie_arch = plat.partition('-')[0]
|
||||
|
||||
# finalize the local installer.conf
|
||||
dst = os.path.join(ctx.dir, "etc/onl/installer.conf")
|
||||
with open(dst, "w") as fd:
|
||||
@@ -195,7 +204,7 @@ class App(SubprocessMixin):
|
||||
pdir,))
|
||||
|
||||
for m in pm.mounts:
|
||||
if m.dir.startswith('/mnt/onl'):
|
||||
if m.dir.startswith('/mnt/onl') or m.dir.startswith('/boot'):
|
||||
if not self.force:
|
||||
self.log.error("directory %s is still mounted (try --force)", m.dir)
|
||||
return 1
|
||||
|
||||
@@ -63,7 +63,12 @@ class MountManager(object):
|
||||
self.logger.debug("%s not mounted @ %s. It will be mounted %s" % (device, directory, mode))
|
||||
|
||||
try:
|
||||
cmd = "mount -o %s %s %s" % (','.join(mountargs), device, directory)
|
||||
p = device.find('ubi')
|
||||
if p < 0:
|
||||
cmd = "mount -o %s %s %s" % (','.join(mountargs), device, directory)
|
||||
else:
|
||||
cmd = "mount -o %s -t %s %s %s" % (','.join(mountargs), 'ubifs', device, directory)
|
||||
|
||||
self.logger.debug("+ %s" % cmd)
|
||||
subprocess.check_call(cmd, shell=True)
|
||||
except subprocess.CalledProcessError, e:
|
||||
@@ -148,11 +153,42 @@ class OnlMountManager(object):
|
||||
def _discover(k):
|
||||
v = md[k]
|
||||
lbl = v.get('label', k)
|
||||
|
||||
useUbiDev = False
|
||||
try:
|
||||
v['device'] = subprocess.check_output(('blkid', '-L', lbl,)).strip()
|
||||
except subprocess.CalledProcessError:
|
||||
return False
|
||||
useUbiDev = True
|
||||
if useUbiDev == True:
|
||||
if k == 'EFI-BOOT':
|
||||
return False
|
||||
try:
|
||||
output = subprocess.check_output("ubinfo -d 0 -N %s" % k, shell=True).splitlines()
|
||||
except subprocess.CalledProcessError:
|
||||
return False
|
||||
|
||||
volumeId = None
|
||||
device = None
|
||||
for line in output:
|
||||
line = line.strip()
|
||||
p = line.find(':')
|
||||
if p < 0:
|
||||
self.logger.debug("Invalid ubinfo output %s" % line)
|
||||
|
||||
name, value = line[:p], line[p+1:].strip()
|
||||
if 'Volume ID' in name:
|
||||
p = value.find('(')
|
||||
if p < 0:
|
||||
self.logger.debug("Invalid Volume ID %s" % value)
|
||||
|
||||
volumeId = value[:p].strip()
|
||||
p = value.find('on')
|
||||
if p < 0:
|
||||
self.logger.debug("Invalid ubi devicde %s" % value)
|
||||
|
||||
device = value[p+2:-1].strip()
|
||||
if 'Name' in name:
|
||||
v['device'] = "/dev/" + device + "_" + volumeId
|
||||
|
||||
|
||||
if not os.path.isdir(v['dir']):
|
||||
self.logger.debug("Make directory '%s'...", v['dir'])
|
||||
|
||||
@@ -17,6 +17,7 @@ import yaml
|
||||
import onl.YamlUtils
|
||||
import subprocess
|
||||
import platform
|
||||
import ast
|
||||
|
||||
class OnlInfoObject(object):
|
||||
DEFAULT_INDENT=" "
|
||||
@@ -164,6 +165,7 @@ class OnlPlatformBase(object):
|
||||
except ValueError, e:
|
||||
if required:
|
||||
raise e
|
||||
self.add_info_dict(name, {}, klass)
|
||||
elif required:
|
||||
raise RuntimeError("A required system file (%s) is missing." % f)
|
||||
|
||||
@@ -255,9 +257,11 @@ class OnlPlatformBase(object):
|
||||
mc = self.basedir_onl("etc/onie/machine.json")
|
||||
if not os.path.exists(mc):
|
||||
data = {}
|
||||
mcconf = subprocess.check_output("""onie-shell -c "cat /etc/machine.conf" """, shell=True)
|
||||
mcconf = subprocess.check_output("""onie-shell -c "IFS=; . /etc/machine.conf; set | egrep ^onie_.*=" """, shell=True)
|
||||
for entry in mcconf.split():
|
||||
(k,e,v) = entry.partition('=')
|
||||
if v and (v.startswith("'") or v.startswith('"')):
|
||||
v = ast.literal_eval(v)
|
||||
if e:
|
||||
data[k] = v
|
||||
|
||||
@@ -473,6 +477,10 @@ class OnlPlatformPortConfig_48x1_4x10(object):
|
||||
PORT_COUNT=52
|
||||
PORT_CONFIG="48x1 + 4x10"
|
||||
|
||||
class OnlPlatformPortConfig_48x1_2x10(object):
|
||||
PORT_COUNT=50
|
||||
PORT_CONFIG="48x1 + 2x10"
|
||||
|
||||
class OnlPlatformPortConfig_48x10_4x40(object):
|
||||
PORT_COUNT=52
|
||||
PORT_CONFIG="48x10 + 4x40"
|
||||
@@ -481,6 +489,10 @@ class OnlPlatformPortConfig_48x10_6x40(object):
|
||||
PORT_COUNT=54
|
||||
PORT_CONFIG="48x10 + 6x40"
|
||||
|
||||
class OnlPlatformPortConfig_48x10_4x100(object):
|
||||
PORT_COUNT=52
|
||||
PORT_CONFIG="48x10 + 4x100"
|
||||
|
||||
class OnlPlatformPortConfig_48x25_6x100(object):
|
||||
PORT_COUNT=54
|
||||
PORT_CONFIG="48x25 + 6x100"
|
||||
@@ -501,6 +513,10 @@ class OnlPlatformPortConfig_32x100(object):
|
||||
PORT_COUNT=32
|
||||
PORT_CONFIG="32x100"
|
||||
|
||||
class OnlPlatformPortConfig_64x100(object):
|
||||
PORT_COUNT=64
|
||||
PORT_CONFIG="64x100"
|
||||
|
||||
class OnlPlatformPortConfig_24x1_4x10(object):
|
||||
PORT_COUNT=28
|
||||
PORT_CONFIG="24x1 + 4x10"
|
||||
|
||||
@@ -61,6 +61,13 @@ def baseconfig():
|
||||
|
||||
ONLPDUMP = "%s/bin/onlpdump" % (platform.basedir_onl())
|
||||
|
||||
try:
|
||||
import dmidecode
|
||||
with open("%s/dmi-system-version" % platform.basedir_onl(), "w") as f:
|
||||
f.write(dmidecode.QuerySection('system')['0x0001']['data']['Version'])
|
||||
except:
|
||||
pass
|
||||
|
||||
if not platform.baseconfig():
|
||||
msg("*** platform class baseconfig failed.\n", fatal=True)
|
||||
|
||||
|
||||
@@ -14,21 +14,57 @@
|
||||
# platform-config packages.
|
||||
#
|
||||
############################################################
|
||||
import os
|
||||
import os, sys
|
||||
import importlib
|
||||
import subprocess
|
||||
import ast
|
||||
|
||||
def platform_name_get():
|
||||
# Determine the current platform name.
|
||||
platform = None
|
||||
if os.path.exists("/etc/onl/platform"):
|
||||
|
||||
# running ONL proper
|
||||
if platform is None and os.path.exists("/etc/onl/platform"):
|
||||
with open("/etc/onl/platform", 'r') as f:
|
||||
platform=f.read().strip()
|
||||
elif os.path.exists("/etc/machine.conf"):
|
||||
with open("/etc/machine.conf", 'r') as f:
|
||||
|
||||
# in the middle of an ONL install
|
||||
if platform is None and os.path.exists("/etc/onl/installer.conf"):
|
||||
with open("/etc/onl/installer.conf") as f:
|
||||
lines = f.readlines(False)
|
||||
lines = [x for x in lines if x.startswith('onie_platform=')]
|
||||
lines = [x for x in lines if x.startswith('onie_platform')]
|
||||
if lines:
|
||||
platform = lines[0].partition('=')[2].strip()
|
||||
|
||||
# running ONIE
|
||||
if platform is None and os.path.exists("/bin/onie-sysinfo"):
|
||||
try:
|
||||
platform = subprocess.check_output(('/bin/onie-sysinfo', '-p',)).strip()
|
||||
except subprocess.CalledProcessError as what:
|
||||
for line in (what.output or "").splitlines():
|
||||
sys.stderr.write(">>> %s\n" % line)
|
||||
sys.stderr.write("onie-sysinfo failed with code %d\n" % what.returncode)
|
||||
platform = None
|
||||
|
||||
# running ONL loader, with access to ONIE
|
||||
if platform is None and os.path.exists("/usr/bin/onie-shell"):
|
||||
try:
|
||||
platform = subprocess.check_output(('/usr/bin/onie-shell', '-c', "onie-sysinfo -p",)).strip()
|
||||
except subprocess.CalledProcessError as what:
|
||||
for line in (what.output or "").splitlines():
|
||||
sys.stderr.write(">>> %s\n" % line)
|
||||
sys.stderr.write("onie-sysinfo (onie-shell) failed with code %d\n" % what.returncode)
|
||||
platform = None
|
||||
|
||||
# legacy ONIE environment (including parsable shell in machine.conf)
|
||||
if platform is None and os.path.exists("/etc/machine.conf"):
|
||||
cmd = "IFS=; . /tmp/machine.conf; set | egrep ^onie_platform="
|
||||
buf = subprocess.check_output(cmd)
|
||||
if buf:
|
||||
platform = buf.partition('=')[2].strip()
|
||||
if platform.startswith('"') or platform.startswith("'"):
|
||||
platform = ast.literal_eval(platform)
|
||||
|
||||
if platform is None:
|
||||
raise RuntimeError("cannot find a platform declaration")
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ from onl.upgrade import ubase
|
||||
from onl.sysconfig import sysconfig
|
||||
from onl.mounts import OnlMountManager, OnlMountContextReadOnly, OnlMountContextReadWrite
|
||||
from onl.install import BaseInstall, ConfUtils, InstallUtils
|
||||
from onl.install.ShellApp import OnieBootContext
|
||||
from onl.install.ShellApp import OnieBootContext, OnieSysinfo
|
||||
import onl.platform.current
|
||||
import onl.versions
|
||||
|
||||
@@ -83,8 +83,12 @@ class LoaderUpgrade_Fit(LoaderUpgradeBase):
|
||||
onlPlatform = onl.platform.current.OnlPlatform()
|
||||
|
||||
with OnieBootContext(log=self.logger) as octx:
|
||||
path = os.path.join(octx.initrdDir, "etc/machine.conf")
|
||||
machineConf = ConfUtils.MachineConf(path=path)
|
||||
if os.path.exists("/usr/bin/onie-shell"):
|
||||
machineConf = OnieSysinfo(log=self.logger.getChild("onie-sysinfo"))
|
||||
else:
|
||||
path = os.path.join(octx.initrdDir, "etc/machine.conf")
|
||||
if os.path.exists(path):
|
||||
machineConf = ConfUtils.MachineConf(path=path)
|
||||
|
||||
installerConf = ConfUtils.InstallerConf(path="/dev/null")
|
||||
# start with an empty installerConf, fill it in piece by piece
|
||||
|
||||
@@ -15,7 +15,7 @@ include $(ONL)/make/config.mk
|
||||
kernel:
|
||||
rm -rf lib
|
||||
$(MAKE) -C $(ONL)/packages/base/any/kernels/3.16-lts/configs/x86_64-all K_TARGET_DIR=$(THIS_DIR) $(ONL_MAKE_PARALLEL)
|
||||
ARCH=x86_64 $(ONL)/tools/scripts/kmodbuild.sh linux-3.16.39-mbuild "$(wildcard $(ONL)/packages/base/any/kernels/modules/*)" onl/onl/common
|
||||
ARCH=x86_64 $(ONL)/tools/scripts/kmodbuild.sh linux-3.16.*-mbuild "$(wildcard $(ONL)/packages/base/any/kernels/modules/*)" onl/onl/common
|
||||
|
||||
clean:
|
||||
rm -rf linux-3.16* kernel-3.16*
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -0,0 +1,30 @@
|
||||
variables:
|
||||
basename: onl-kernel-4.14-lts-x86-64-all
|
||||
|
||||
common:
|
||||
arch: amd64
|
||||
version: 1.0.0
|
||||
copyright: Copyright 2013, 2014, 2015 Big Switch Networks
|
||||
maintainer: support@bigswitch.com
|
||||
support: opennetworklinux@googlegroups.com
|
||||
|
||||
packages:
|
||||
- name: $basename
|
||||
version: 1.0.0
|
||||
summary: Open Network Linux 4.14 LTS Kernel for X86_64 Platforms.
|
||||
symlinks: True
|
||||
|
||||
files:
|
||||
builds/kernel-4.14* : $$PKG_INSTALL/
|
||||
builds/linux-*mbuild : $$PKG_INSTALL/mbuilds
|
||||
|
||||
changelog: Change changes changes.,
|
||||
|
||||
- name: $basename-modules
|
||||
version: 1.0.0
|
||||
summary: Open Network Linux 4.14 LTS Kernel Modules for X86_64 Platforms
|
||||
|
||||
files:
|
||||
builds/lib: /lib
|
||||
|
||||
changelog: Change changes changes.,
|
||||
3
packages/base/amd64/kernels/kernel-4.14-lts-x86-64-all/builds/.gitignore
vendored
Normal file
3
packages/base/amd64/kernels/kernel-4.14-lts-x86-64-all/builds/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
linux-*
|
||||
kernel-*
|
||||
lib
|
||||
@@ -0,0 +1,22 @@
|
||||
# -*- Makefile -*-
|
||||
############################################################
|
||||
# <bsn.cl fy=2013 v=none>
|
||||
#
|
||||
# Copyright 2013, 2014 BigSwitch Networks, Inc.
|
||||
#
|
||||
#
|
||||
#
|
||||
# </bsn.cl>
|
||||
############################################################
|
||||
THIS_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
include $(ONL)/make/config.mk
|
||||
|
||||
kernel:
|
||||
rm -rf lib
|
||||
dpkg -l libelf-dev > /dev/null 2>&1 || sudo apt-get install libelf-dev
|
||||
$(MAKE) -C $(ONL)/packages/base/any/kernels/4.14-lts/configs/x86_64-all K_TARGET_DIR=$(THIS_DIR) $(ONL_MAKE_PARALLEL)
|
||||
ARCH=x86_64 $(ONL)/tools/scripts/kmodbuild.sh linux-4.14.*-mbuild "$(wildcard $(ONL)/packages/base/any/kernels/modules/*)" onl/onl/common
|
||||
|
||||
clean:
|
||||
rm -rf linux-4.14* kernel-4.14* lib
|
||||
@@ -15,7 +15,7 @@ include $(ONL)/make/config.mk
|
||||
kernel:
|
||||
rm -rf lib
|
||||
$(MAKE) -C $(ONL)/packages/base/any/kernels/4.9-lts/configs/x86_64-all K_TARGET_DIR=$(THIS_DIR) $(ONL_MAKE_PARALLEL)
|
||||
ARCH=x86_64 $(ONL)/tools/scripts/kmodbuild.sh linux-4.9.30-mbuild "$(wildcard $(ONL)/packages/base/any/kernels/modules/*)" onl/onl/common
|
||||
ARCH=x86_64 $(ONL)/tools/scripts/kmodbuild.sh linux-4.9.*-mbuild "$(wildcard $(ONL)/packages/base/any/kernels/modules/*)" onl/onl/common
|
||||
|
||||
clean:
|
||||
rm -rf linux-4.9* kernel-4.9*
|
||||
|
||||
@@ -2,7 +2,8 @@ include $(ONL)/make/config.amd64.mk
|
||||
|
||||
# All amd64 kernels
|
||||
KERNELS := $(shell $(ONLPM) --find-file onl-kernel-3.16-lts-x86-64-all:amd64 kernel-3.16-lts-x86_64-all) \
|
||||
$(shell $(ONLPM) --find-file onl-kernel-4.9-lts-x86-64-all:amd64 kernel-4.9-lts-x86_64-all)
|
||||
$(shell $(ONLPM) --find-file onl-kernel-4.9-lts-x86-64-all:amd64 kernel-4.9-lts-x86_64-all) \
|
||||
$(shell $(ONLPM) --find-file onl-kernel-4.14-lts-x86-64-all:amd64 kernel-4.14-lts-x86_64-all)
|
||||
|
||||
|
||||
# Loader initrd
|
||||
|
||||
@@ -16,7 +16,4 @@ packages:
|
||||
init: ${ONL}/packages/base/any/faultd/faultd.init
|
||||
|
||||
changelog: Change changes changes.,
|
||||
|
||||
|
||||
|
||||
|
||||
asr: True
|
||||
|
||||
@@ -110,7 +110,7 @@ faultd_config_lookup(const char* setting)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; faultd_config_settings[i].name; i++) {
|
||||
if(strcmp(faultd_config_settings[i].name, setting)) {
|
||||
if(!strcmp(faultd_config_settings[i].name, setting)) {
|
||||
return faultd_config_settings[i].value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Linux/powerpc 3.16.39 Kernel Configuration
|
||||
# Linux/powerpc 3.16.53 Kernel Configuration
|
||||
#
|
||||
# CONFIG_PPC64 is not set
|
||||
|
||||
@@ -732,7 +732,6 @@ CONFIG_VLAN_8021Q=y
|
||||
# CONFIG_BATMAN_ADV is not set
|
||||
# CONFIG_OPENVSWITCH is not set
|
||||
# CONFIG_VSOCKETS is not set
|
||||
# CONFIG_NETLINK_MMAP is not set
|
||||
# CONFIG_NETLINK_DIAG is not set
|
||||
# CONFIG_NET_MPLS_GSO is not set
|
||||
# CONFIG_HSR is not set
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Linux/x86_64 3.16.39 Kernel Configuration
|
||||
# Linux/x86_64 3.16.53 Kernel Configuration
|
||||
#
|
||||
CONFIG_64BIT=y
|
||||
CONFIG_X86_64=y
|
||||
@@ -1054,7 +1054,6 @@ CONFIG_DNS_RESOLVER=y
|
||||
# CONFIG_BATMAN_ADV is not set
|
||||
# CONFIG_OPENVSWITCH is not set
|
||||
# CONFIG_VSOCKETS is not set
|
||||
CONFIG_NETLINK_MMAP=y
|
||||
CONFIG_NETLINK_DIAG=y
|
||||
# CONFIG_NET_MPLS_GSO is not set
|
||||
# CONFIG_HSR is not set
|
||||
@@ -2004,7 +2003,7 @@ CONFIG_GPIO_GENERIC_PLATFORM=y
|
||||
# CONFIG_GPIO_F7188X is not set
|
||||
# CONFIG_GPIO_SCH311X is not set
|
||||
CONFIG_GPIO_SCH=y
|
||||
# CONFIG_GPIO_ICH is not set
|
||||
CONFIG_GPIO_ICH=m
|
||||
# CONFIG_GPIO_VX855 is not set
|
||||
# CONFIG_GPIO_LYNXPOINT is not set
|
||||
|
||||
@@ -2451,7 +2450,7 @@ CONFIG_HID_GENERIC=y
|
||||
# CONFIG_HID_BELKIN is not set
|
||||
# CONFIG_HID_CHERRY is not set
|
||||
# CONFIG_HID_CHICONY is not set
|
||||
# CONFIG_HID_CP2112 is not set
|
||||
CONFIG_HID_CP2112=y
|
||||
# CONFIG_HID_CYPRESS is not set
|
||||
# CONFIG_HID_DRAGONRISE is not set
|
||||
# CONFIG_HID_EMS_FF is not set
|
||||
@@ -2562,7 +2561,7 @@ CONFIG_USB_UHCI_HCD=y
|
||||
#
|
||||
# USB Device Class drivers
|
||||
#
|
||||
# CONFIG_USB_ACM is not set
|
||||
CONFIG_USB_ACM=y
|
||||
# CONFIG_USB_PRINTER is not set
|
||||
# CONFIG_USB_WDM is not set
|
||||
# CONFIG_USB_TMC is not set
|
||||
@@ -3412,6 +3411,7 @@ CONFIG_KEYS=y
|
||||
# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
|
||||
# CONFIG_SECURITY_DMESG_RESTRICT is not set
|
||||
# CONFIG_SECURITY is not set
|
||||
CONFIG_PAGE_TABLE_ISOLATION=y
|
||||
# CONFIG_SECURITYFS is not set
|
||||
CONFIG_DEFAULT_SECURITY_DAC=y
|
||||
CONFIG_DEFAULT_SECURITY=""
|
||||
@@ -3630,3 +3630,4 @@ CONFIG_AVERAGE=y
|
||||
CONFIG_CORDIC=y
|
||||
# CONFIG_DDR is not set
|
||||
CONFIG_OID_REGISTRY=y
|
||||
CONFIG_UCS2_STRING=y
|
||||
|
||||
@@ -25,6 +25,6 @@
|
||||
THIS_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
K_MAJOR_VERSION := 3
|
||||
K_PATCH_LEVEL := 16
|
||||
K_SUB_LEVEL := 39
|
||||
K_SUB_LEVEL := 53
|
||||
K_SUFFIX :=
|
||||
K_PATCH_DIR := $(THIS_DIR)/patches
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
|
||||
index bc37acd..fee4c66 100644
|
||||
--- a/drivers/hid/hid-cp2112.c
|
||||
+++ b/drivers/hid/hid-cp2112.c
|
||||
@@ -156,6 +156,7 @@ struct cp2112_device {
|
||||
wait_queue_head_t wait;
|
||||
u8 read_data[61];
|
||||
u8 read_length;
|
||||
+ u8 hwversion;
|
||||
int xfer_status;
|
||||
atomic_t read_avail;
|
||||
atomic_t xfer_avail;
|
||||
@@ -427,6 +428,156 @@ static int cp2112_write_req(void *buf, u8 slave_address, u8 command, u8 *data,
|
||||
return data_length + 4;
|
||||
}
|
||||
|
||||
+static int cp2112_i2c_write_req(void *buf, u8 slave_address, u8 *data,
|
||||
+ u8 data_length)
|
||||
+{
|
||||
+ struct cp2112_write_req_report *report = buf;
|
||||
+
|
||||
+ if (data_length > sizeof(report->data))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ report->report = CP2112_DATA_WRITE_REQUEST;
|
||||
+ report->slave_address = slave_address << 1;
|
||||
+ report->length = data_length;
|
||||
+ memcpy(report->data, data, data_length);
|
||||
+ return data_length + 3;
|
||||
+}
|
||||
+
|
||||
+static int cp2112_i2c_write_read_req(void *buf, u8 slave_address,
|
||||
+ u8 *addr, int addr_length,
|
||||
+ int read_length)
|
||||
+{
|
||||
+ struct cp2112_write_read_req_report *report = buf;
|
||||
+
|
||||
+ if (read_length < 1 || read_length > 512 ||
|
||||
+ addr_length > sizeof(report->target_address))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ report->report = CP2112_DATA_WRITE_READ_REQUEST;
|
||||
+ report->slave_address = slave_address << 1;
|
||||
+ report->length = cpu_to_be16(read_length);
|
||||
+ report->target_address_length = addr_length;
|
||||
+ memcpy(report->target_address, addr, addr_length);
|
||||
+ return addr_length + 5;
|
||||
+}
|
||||
+
|
||||
+static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
|
||||
+ int num)
|
||||
+{
|
||||
+ struct cp2112_device *dev = (struct cp2112_device *)adap->algo_data;
|
||||
+ struct hid_device *hdev = dev->hdev;
|
||||
+ u8 buf[64];
|
||||
+ ssize_t count;
|
||||
+ ssize_t read_length = 0;
|
||||
+ u8 *read_buf = NULL;
|
||||
+ unsigned int retries;
|
||||
+ int ret;
|
||||
+
|
||||
+ hid_dbg(hdev, "I2C %d messages\n", num);
|
||||
+
|
||||
+ if (num == 1) {
|
||||
+ if (msgs->flags & I2C_M_RD) {
|
||||
+ hid_dbg(hdev, "I2C read %#04x len %d\n",
|
||||
+ msgs->addr, msgs->len);
|
||||
+ read_length = msgs->len;
|
||||
+ read_buf = msgs->buf;
|
||||
+ count = cp2112_read_req(buf, msgs->addr, msgs->len);
|
||||
+ } else {
|
||||
+ hid_dbg(hdev, "I2C write %#04x len %d\n",
|
||||
+ msgs->addr, msgs->len);
|
||||
+ count = cp2112_i2c_write_req(buf, msgs->addr,
|
||||
+ msgs->buf, msgs->len);
|
||||
+ }
|
||||
+ if (count < 0)
|
||||
+ return count;
|
||||
+ } else if (dev->hwversion > 1 && /* no repeated start in rev 1 */
|
||||
+ num == 2 &&
|
||||
+ msgs[0].addr == msgs[1].addr &&
|
||||
+ !(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) {
|
||||
+ hid_dbg(hdev, "I2C write-read %#04x wlen %d rlen %d\n",
|
||||
+ msgs[0].addr, msgs[0].len, msgs[1].len);
|
||||
+ read_length = msgs[1].len;
|
||||
+ read_buf = msgs[1].buf;
|
||||
+ count = cp2112_i2c_write_read_req(buf, msgs[0].addr,
|
||||
+ msgs[0].buf, msgs[0].len, msgs[1].len);
|
||||
+ if (count < 0)
|
||||
+ return count;
|
||||
+ } else {
|
||||
+ hid_err(hdev,
|
||||
+ "Multi-message I2C transactions not supported\n");
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
+
|
||||
+ ret = hid_hw_power(hdev, PM_HINT_FULLON);
|
||||
+ if (ret < 0) {
|
||||
+ hid_err(hdev, "power management error: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = cp2112_hid_output(hdev, buf, count, HID_OUTPUT_REPORT);
|
||||
+ if (ret < 0) {
|
||||
+ hid_warn(hdev, "Error starting transaction: %d\n", ret);
|
||||
+ goto power_normal;
|
||||
+ }
|
||||
+
|
||||
+ for (retries = 0; retries < XFER_STATUS_RETRIES; ++retries) {
|
||||
+ ret = cp2112_xfer_status(dev);
|
||||
+ if (-EBUSY == ret)
|
||||
+ continue;
|
||||
+ if (ret < 0)
|
||||
+ goto power_normal;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (XFER_STATUS_RETRIES <= retries) {
|
||||
+ hid_warn(hdev, "Transfer timed out, cancelling.\n");
|
||||
+ buf[0] = CP2112_CANCEL_TRANSFER;
|
||||
+ buf[1] = 0x01;
|
||||
+
|
||||
+ ret = cp2112_hid_output(hdev, buf, 2, HID_OUTPUT_REPORT);
|
||||
+ if (ret < 0)
|
||||
+ hid_warn(hdev, "Error cancelling transaction: %d\n",
|
||||
+ ret);
|
||||
+
|
||||
+ ret = -ETIMEDOUT;
|
||||
+ goto power_normal;
|
||||
+ }
|
||||
+
|
||||
+ for (count = 0; count < read_length;) {
|
||||
+ ret = cp2112_read(dev, read_buf + count, read_length - count);
|
||||
+ if (ret < 0)
|
||||
+ goto power_normal;
|
||||
+ if (ret == 0) {
|
||||
+ hid_err(hdev, "read returned 0\n");
|
||||
+ ret = -EIO;
|
||||
+ goto power_normal;
|
||||
+ }
|
||||
+ count += ret;
|
||||
+ if (count > read_length) {
|
||||
+ /*
|
||||
+ * The hardware returned too much data.
|
||||
+ * This is mostly harmless because cp2112_read()
|
||||
+ * has a limit check so didn't overrun our
|
||||
+ * buffer. Nevertheless, we return an error
|
||||
+ * because something is seriously wrong and
|
||||
+ * it shouldn't go unnoticed.
|
||||
+ */
|
||||
+ hid_err(hdev, "long read: %d > %zd\n",
|
||||
+ ret, read_length - count + ret);
|
||||
+ ret = -EIO;
|
||||
+ goto power_normal;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* return the number of transferred messages */
|
||||
+ ret = num;
|
||||
+
|
||||
+power_normal:
|
||||
+ hid_hw_power(hdev, PM_HINT_NORMAL);
|
||||
+ hid_dbg(hdev, "I2C transfer finished: %d\n", ret);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
|
||||
unsigned short flags, char read_write, u8 command,
|
||||
int size, union i2c_smbus_data *data)
|
||||
@@ -593,7 +744,8 @@ power_normal:
|
||||
|
||||
static u32 cp2112_functionality(struct i2c_adapter *adap)
|
||||
{
|
||||
- return I2C_FUNC_SMBUS_BYTE |
|
||||
+ return I2C_FUNC_I2C |
|
||||
+ I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA |
|
||||
@@ -603,6 +755,7 @@ static u32 cp2112_functionality(struct i2c_adapter *adap)
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm smbus_algorithm = {
|
||||
+ .master_xfer = cp2112_i2c_xfer,
|
||||
.smbus_xfer = cp2112_xfer,
|
||||
.functionality = cp2112_functionality,
|
||||
};
|
||||
@@ -925,6 +1078,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
dev->adap.dev.parent = &hdev->dev;
|
||||
snprintf(dev->adap.name, sizeof(dev->adap.name),
|
||||
"CP2112 SMBus Bridge on hiddev%d", hdev->minor);
|
||||
+ dev->hwversion = buf[2];
|
||||
init_waitqueue_head(&dev->wait);
|
||||
|
||||
hid_device_io_start(hdev);
|
||||
|
||||
@@ -350,19 +350,6 @@ diff -urpN a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
|
||||
diff -urpN a/fs/ext4/namei.c b/fs/ext4/namei.c
|
||||
--- a/fs/ext4/namei.c 2016-11-20 01:17:41.000000000 +0000
|
||||
+++ b/fs/ext4/namei.c 2016-12-21 21:06:34.010677297 +0000
|
||||
@@ -1849,10 +1849,10 @@ static int make_indexed_dir(handle_t *ha
|
||||
|
||||
retval = ext4_handle_dirty_dx_node(handle, dir, frame->bh);
|
||||
if (retval)
|
||||
- goto out_frames;
|
||||
+ goto out_frames;
|
||||
retval = ext4_handle_dirty_dirent_node(handle, dir, bh);
|
||||
if (retval)
|
||||
- goto out_frames;
|
||||
+ goto out_frames;
|
||||
|
||||
de = do_split(handle,dir, &bh, frame, &hinfo);
|
||||
if (IS_ERR(de)) {
|
||||
@@ -2905,7 +2905,7 @@ retry:
|
||||
* for transaction commit if we are running out of space
|
||||
* and thus we deadlock. So we have to stop transaction now
|
||||
@@ -4075,20 +4062,6 @@ diff -urpN a/include/linux/fs.h b/include/linux/fs.h
|
||||
*
|
||||
* @AOP_TRUNCATED_PAGE: The AOP method that was handed a locked page has
|
||||
* unlocked it and the page might have been truncated.
|
||||
@@ -806,10 +826,10 @@ static inline struct file *get_file(stru
|
||||
|
||||
#define MAX_NON_LFS ((1UL<<31) - 1)
|
||||
|
||||
-/* Page cache limit. The filesystems should put that into their s_maxbytes
|
||||
- limits, otherwise bad things can happen in VM. */
|
||||
+/* Page cache limit. The filesystems should put that into their s_maxbytes
|
||||
+ limits, otherwise bad things can happen in VM. */
|
||||
#if BITS_PER_LONG==32
|
||||
-#define MAX_LFS_FILESIZE (((loff_t)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1)
|
||||
+#define MAX_LFS_FILESIZE (((loff_t)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1)
|
||||
#elif BITS_PER_LONG==64
|
||||
#define MAX_LFS_FILESIZE ((loff_t)0x7fffffffffffffffLL)
|
||||
#endif
|
||||
@@ -1401,6 +1421,7 @@ extern int vfs_link(struct dentry *, str
|
||||
extern int vfs_rmdir(struct inode *, struct dentry *);
|
||||
extern int vfs_unlink(struct inode *, struct dentry *, struct inode **);
|
||||
|
||||
@@ -26,4 +26,5 @@ platform-powerpc-dni-7448-r0.patch
|
||||
platform-powerpc-quanta-lb9-r0.patch
|
||||
driver-support-intel-igb-bcm50210-phy.patch
|
||||
driver-igb-netberg-aurora.patch
|
||||
driver-hid-cp2112-mods.patch
|
||||
gcc-no-pie.patch
|
||||
|
||||
@@ -38,6 +38,6 @@ K_COPY_DST := kernel-3.2-lts-arm-iproc-all.bin.gz
|
||||
endif
|
||||
|
||||
export ARCH=arm
|
||||
DTS_LIST := accton_as4610_54
|
||||
DTS_LIST := accton_as4610_54 delta_ag6248c
|
||||
|
||||
include $(ONL)/make/kbuild.mk
|
||||
|
||||
@@ -289,6 +289,7 @@ CONFIG_BCM_RAM_START_RESERVED_SIZE=0x200000
|
||||
# CONFIG_MACH_GH is not set
|
||||
# CONFIG_MACH_DNI_3448P is not set
|
||||
CONFIG_MACH_ACCTON_AS4610_54=y
|
||||
CONFIG_MACH_DELTA_AG6248C=y
|
||||
# CONFIG_MACH_IPROC_EMULATION is not set
|
||||
|
||||
#
|
||||
@@ -1938,7 +1939,8 @@ CONFIG_IPROC_QSPI_SINGLE_MODE=y
|
||||
# CONFIG_IPROC_QSPI_DUAL_MODE is not set
|
||||
# CONFIG_IPROC_QSPI_QUAD_MODE is not set
|
||||
CONFIG_IPROC_QSPI_MAX_HZ=62500000
|
||||
# CONFIG_IPROC_MTD_NAND is not set
|
||||
CONFIG_IPROC_MTD_NAND=y
|
||||
# CONFIG_IPROC_MTD_NAND_USE_JFFS2 is not set
|
||||
# CONFIG_IPROC_PWM is not set
|
||||
CONFIG_IPROC_USB2H=y
|
||||
CONFIG_USB_EHCI_BCM=y
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
diff --git a/arch/arm/boot/dts/delta_ag6248c.dts b/arch/arm/boot/dts/delta_ag6248c.dts
|
||||
new file mode 100755
|
||||
index 0000000..f86c35b
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/dts/delta_ag6248c.dts
|
||||
@@ -0,0 +1,78 @@
|
||||
+/*
|
||||
+ * Delta Networks, Inc. AG6248C Device Tree Source
|
||||
+ *
|
||||
+ * Copyright 2015, Cumulus Networks, Inc.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms of the GNU General Public License as published by the
|
||||
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||||
+ * option) any later version.
|
||||
+ *
|
||||
+ */
|
||||
+/dts-v1/;
|
||||
+/include/ "helix4.dtsi"
|
||||
+
|
||||
+/ {
|
||||
+ model = "delta,ag6248c";
|
||||
+ compatible = "delta,ag6248c";
|
||||
+
|
||||
+ aliases {
|
||||
+ serial0 = &uart0;
|
||||
+ i2c-controller0 = &i2c0;
|
||||
+ i2c-controller1 = &i2c1;
|
||||
+ };
|
||||
+
|
||||
+ memory {
|
||||
+ reg = <0x61000000 0x7f000000>;
|
||||
+ };
|
||||
+
|
||||
+ cpus {
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+
|
||||
+ cpu@0 {
|
||||
+ device_type = "cpu";
|
||||
+ compatible = "arm,cortex-a9";
|
||||
+ next-level-cache = <&L2>;
|
||||
+ reg = <0x00>;
|
||||
+ };
|
||||
+ cpu@1 {
|
||||
+ device_type = "cpu";
|
||||
+ compatible = "arm,cortex-a9";
|
||||
+ next-level-cache = <&L2>;
|
||||
+ reg = <0x01>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ localbus@1e000000{
|
||||
+ address-cells = <0x2>;
|
||||
+ #size-cells = <0x1>;
|
||||
+ compatible = "simple-bus";
|
||||
+ ranges = <0x0 0x0 0x1e000000 0x02000000>;
|
||||
+
|
||||
+ };
|
||||
+
|
||||
+ i2c0: i2c@18038000 {
|
||||
+ compatible = "iproc-smb";
|
||||
+ reg = <0x18038000 0x1000>;
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ interrupts = < 127 >;
|
||||
+ clock-frequency = <400000>;
|
||||
+ rtc@68 {
|
||||
+ compatible = "m41st85";
|
||||
+ reg = <0x68>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+
|
||||
+ i2c1: i2c@1803b000 {
|
||||
+ compatible = "iproc-smb";
|
||||
+ reg = <0x1803b000 0x1000>;
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ interrupts = < 128 >;
|
||||
+ clock-frequency = <100000>;
|
||||
+
|
||||
+ };
|
||||
+};
|
||||
diff --git a/arch/arm/mach-iproc/Kconfig b/arch/arm/mach-iproc/Kconfig
|
||||
index c77208d..c6a87fc 100644
|
||||
--- a/arch/arm/mach-iproc/Kconfig
|
||||
+++ b/arch/arm/mach-iproc/Kconfig
|
||||
@@ -49,6 +49,12 @@ config MACH_ACCTON_AS4610_54
|
||||
help
|
||||
Support for Accton AS4610-54 POE and non -POE board.
|
||||
|
||||
+config MACH_DELTA_AG6248C
|
||||
+ select ARM_L1_CACHE_SHIFT_6
|
||||
+ bool "Support Delta AG6248C board"
|
||||
+ help
|
||||
+ Support for Delta AG6248C board.
|
||||
+
|
||||
config MACH_IPROC_P7
|
||||
bool "Support iProc Profile 7 architecture"
|
||||
depends on MACH_GH
|
||||
diff --git a/arch/arm/mach-iproc/board_bu.c b/arch/arm/mach-iproc/board_bu.c
|
||||
index 7e07ed1..5479020 100644
|
||||
--- a/arch/arm/mach-iproc/board_bu.c
|
||||
+++ b/arch/arm/mach-iproc/board_bu.c
|
||||
@@ -1083,6 +1083,7 @@ MACHINE_END
|
||||
static const char * helix4_dt_board_compat[] = {
|
||||
"dni,dni_3448p",
|
||||
"accton,as4610_54",
|
||||
+ "delta,ag6248c",
|
||||
NULL
|
||||
};
|
||||
|
||||
diff --git a/arch/arm/mach-iproc/common.c b/arch/arm/mach-iproc/common.c
|
||||
index b116ffc..e911a2b 100644
|
||||
--- a/arch/arm/mach-iproc/common.c
|
||||
+++ b/arch/arm/mach-iproc/common.c
|
||||
@@ -187,7 +187,8 @@ static struct platform_device wdt_device =
|
||||
enum {
|
||||
HX4_NONE = 0,
|
||||
HX4_DNI_3448P,
|
||||
- HX4_ACCTON_AS4610_54
|
||||
+ HX4_ACCTON_AS4610_54,
|
||||
+ HX4_DELTA_AG6248C,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -212,6 +213,8 @@ int brcm_get_hx4_model(void)
|
||||
return HX4_DNI_3448P;
|
||||
else if (!strcmp(model, "accton,as4610_54"))
|
||||
return HX4_ACCTON_AS4610_54;
|
||||
+ else if (!strcmp(model, "delta,ag6248c"))
|
||||
+ return HX4_DELTA_AG6248C;
|
||||
|
||||
printk( KERN_ERR "Unknown Model %s\n", model );
|
||||
return HX4_NONE;
|
||||
diff --git a/arch/arm/mach-iproc/include/mach/iproc_regs.h b/arch/arm/mach-iproc/include/mach/iproc_regs.h
|
||||
index 460c436..50ea557 100644
|
||||
--- a/arch/arm/mach-iproc/include/mach/iproc_regs.h
|
||||
+++ b/arch/arm/mach-iproc/include/mach/iproc_regs.h
|
||||
@@ -364,7 +364,11 @@
|
||||
#define IPROC_GMAC3_INT 182
|
||||
#elif (defined(CONFIG_MACH_HX4) || defined(CONFIG_MACH_KT2) || defined(CONFIG_MACH_DNI_3448P) || \
|
||||
defined(CONFIG_MACH_ACCTON_AS4610_54))
|
||||
+#if defined(CONFIG_MACH_DELTA_AG6248C)
|
||||
+#define IPROC_NUM_GMACS 1
|
||||
+#else
|
||||
#define IPROC_NUM_GMACS 2
|
||||
+#endif
|
||||
#define IPROC_GMAC0_REG_BASE (GMAC0_DEVCONTROL) //(0x18022000)
|
||||
#define IPROC_GMAC1_REG_BASE (GMAC1_DEVCONTROL) //(0x18023000)
|
||||
#define IPROC_GMAC2_REG_BASE (0) // n/a
|
||||
diff --git a/drivers/bcmdrivers/gmac/src/shared/nvramstubs.c b/drivers/bcmdrivers/gmac/src/shared/nvramstubs.c
|
||||
index d5b400d..a823697 100644
|
||||
--- a/drivers/bcmdrivers/gmac/src/shared/nvramstubs.c
|
||||
+++ b/drivers/bcmdrivers/gmac/src/shared/nvramstubs.c
|
||||
@@ -143,7 +143,8 @@ __setup("envaddr=", envaddr_setup);
|
||||
enum {
|
||||
HX4_NONE = 0,
|
||||
HX4_DNI_3448P,
|
||||
- HX4_ACCTON_AS4610_54
|
||||
+ HX4_ACCTON_AS4610_54,
|
||||
+ HX4_DELTA_AG6248C
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -158,7 +159,10 @@ setup_uboot_vars(void) {
|
||||
} else if (modelnum == HX4_ACCTON_AS4610_54) {
|
||||
env_offset = 0x000f0000;
|
||||
uboot_vars_start = CONFIG_SPI_BASE + env_offset;
|
||||
- }
|
||||
+ }else if (modelnum == HX4_DELTA_AG6248C) {
|
||||
+ env_offset = 0x00300000;
|
||||
+ uboot_vars_start = CONFIG_NAND_BASE + env_offset;
|
||||
+ }
|
||||
}
|
||||
|
||||
/*
|
||||
--
|
||||
2.1.4
|
||||
|
||||
@@ -506,3 +506,4 @@ scripts_package_Makefile.patch
|
||||
tools_include_tools_be_byteshift.h.patch
|
||||
tools_include_tools_le_byteshift.h.patch
|
||||
platform-accton-as4610-device-drivers.patch
|
||||
platform-delta-ag6248c-device-drivers.patch
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
kernel-3.2*
|
||||
linux-*
|
||||
lib
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
THIS_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
K_MAJOR_VERSION := 3
|
||||
K_PATCH_LEVEL := 2
|
||||
K_SUB_LEVEL := 84
|
||||
K_SUB_LEVEL := 98
|
||||
K_SUFFIX :=
|
||||
ifndef K_PATCH_DIR
|
||||
K_PATCH_DIR := $(THIS_DIR)/patches
|
||||
|
||||
3
packages/base/any/kernels/4.14-lts/configs/x86_64-all/.gitignore
vendored
Normal file
3
packages/base/any/kernels/4.14-lts/configs/x86_64-all/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
kernel-*
|
||||
linux-*
|
||||
lib
|
||||
@@ -0,0 +1,37 @@
|
||||
############################################################
|
||||
# <bsn.cl fy=2015 v=onl>
|
||||
#
|
||||
# Copyright 2015 Big Switch Networks, Inc.
|
||||
#
|
||||
# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# </bsn.cl>
|
||||
############################################################
|
||||
THIS_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
include $(ONL)/make/config.mk
|
||||
|
||||
export ARCH := x86_64
|
||||
ifndef K_TARGET_DIR
|
||||
K_TARGET_DIR := $(THIS_DIR)
|
||||
endif
|
||||
|
||||
include ../../kconfig.mk
|
||||
K_CONFIG := x86_64-all.config
|
||||
K_BUILD_TARGET := bzImage
|
||||
K_COPY_SRC := arch/x86/boot/bzImage
|
||||
ifndef K_COPY_DST
|
||||
K_COPY_DST := kernel-4.14-lts-x86_64-all
|
||||
endif
|
||||
|
||||
include $(ONL)/make/kbuild.mk
|
||||
File diff suppressed because it is too large
Load Diff
27
packages/base/any/kernels/4.14-lts/kconfig.mk
Normal file
27
packages/base/any/kernels/4.14-lts/kconfig.mk
Normal file
@@ -0,0 +1,27 @@
|
||||
############################################################
|
||||
# <bsn.cl fy=2015 v=onl>
|
||||
#
|
||||
# Copyright 2015 Big Switch Networks, Inc.
|
||||
#
|
||||
# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# </bsn.cl>
|
||||
############################################################
|
||||
THIS_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
K_MAJOR_VERSION := 4
|
||||
K_PATCH_LEVEL := 14
|
||||
K_SUB_LEVEL := 34
|
||||
K_SUFFIX :=
|
||||
K_PATCH_DIR := $(THIS_DIR)/patches
|
||||
K_MODSYNCLIST := tools/objtool
|
||||
1
packages/base/any/kernels/4.14-lts/patches/series
Normal file
1
packages/base/any/kernels/4.14-lts/patches/series
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,6 @@
|
||||
THIS_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
K_MAJOR_VERSION := 4
|
||||
K_PATCH_LEVEL := 9
|
||||
K_SUB_LEVEL := 30
|
||||
K_SUB_LEVEL := 75
|
||||
K_SUFFIX :=
|
||||
K_PATCH_DIR := $(THIS_DIR)/patches
|
||||
|
||||
@@ -0,0 +1,544 @@
|
||||
Linux backport patch. Includes following commits:
|
||||
899e11216e1c215b97f2f8f92c7b010a4e88f38e
|
||||
|
||||
|
||||
diff -Nur a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
|
||||
--- a/drivers/i2c/busses/Kconfig 2017-11-12 08:08:32.136039784 +0000
|
||||
+++ b/drivers/i2c/busses/Kconfig 2017-11-12 08:08:40.776039899 +0000
|
||||
@@ -1150,6 +1150,17 @@
|
||||
This support is also available as a module. If so, the module
|
||||
will be called i2c-elektor.
|
||||
|
||||
+config I2C_MLXCPLD
|
||||
+ tristate "Mellanox I2C driver"
|
||||
+ depends on X86_64
|
||||
+ help
|
||||
+ This exposes the Mellanox platform I2C busses to the linux I2C layer
|
||||
+ for X86 based systems.
|
||||
+ Controller is implemented as CPLD logic.
|
||||
+
|
||||
+ This driver can also be built as a module. If so, the module will be
|
||||
+ called as i2c-mlxcpld.
|
||||
+
|
||||
config I2C_PCA_ISA
|
||||
tristate "PCA9564/PCA9665 on an ISA bus"
|
||||
depends on ISA
|
||||
diff -Nur a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
|
||||
--- a/drivers/i2c/busses/Makefile 2017-11-12 08:08:32.140039784 +0000
|
||||
+++ b/drivers/i2c/busses/Makefile 2017-11-12 08:08:40.780039899 +0000
|
||||
@@ -116,6 +116,7 @@
|
||||
obj-$(CONFIG_I2C_BRCMSTB) += i2c-brcmstb.o
|
||||
obj-$(CONFIG_I2C_CROS_EC_TUNNEL) += i2c-cros-ec-tunnel.o
|
||||
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
|
||||
+obj-$(CONFIG_I2C_MLXCPLD) += i2c-mlxcpld.o
|
||||
obj-$(CONFIG_I2C_OPAL) += i2c-opal.o
|
||||
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
|
||||
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
|
||||
diff -Nur a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c
|
||||
--- a/drivers/i2c/busses/i2c-mlxcpld.c 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/drivers/i2c/busses/i2c-mlxcpld.c 2017-11-12 08:08:40.780039899 +0000
|
||||
@@ -0,0 +1,504 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
|
||||
+ * Copyright (c) 2016 Michael Shych <michaels@mellanox.com>
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions are met:
|
||||
+ *
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ * 3. Neither the names of the copyright holders nor the names of its
|
||||
+ * contributors may be used to endorse or promote products derived from
|
||||
+ * this software without specific prior written permission.
|
||||
+ *
|
||||
+ * Alternatively, this software may be distributed under the terms of the
|
||||
+ * GNU General Public License ("GPL") version 2 as published by the Free
|
||||
+ * Software Foundation.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
+ * POSSIBILITY OF SUCH DAMAGE.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+/* General defines */
|
||||
+#define MLXPLAT_CPLD_LPC_I2C_BASE_ADDR 0x2000
|
||||
+#define MLXCPLD_I2C_DEVICE_NAME "i2c_mlxcpld"
|
||||
+#define MLXCPLD_I2C_VALID_FLAG (I2C_M_RECV_LEN | I2C_M_RD)
|
||||
+#define MLXCPLD_I2C_BUS_NUM 1
|
||||
+#define MLXCPLD_I2C_DATA_REG_SZ 36
|
||||
+#define MLXCPLD_I2C_MAX_ADDR_LEN 4
|
||||
+#define MLXCPLD_I2C_RETR_NUM 2
|
||||
+#define MLXCPLD_I2C_XFER_TO 500000 /* usec */
|
||||
+#define MLXCPLD_I2C_POLL_TIME 2000 /* usec */
|
||||
+
|
||||
+/* LPC I2C registers */
|
||||
+#define MLXCPLD_LPCI2C_LPF_REG 0x0
|
||||
+#define MLXCPLD_LPCI2C_CTRL_REG 0x1
|
||||
+#define MLXCPLD_LPCI2C_HALF_CYC_REG 0x4
|
||||
+#define MLXCPLD_LPCI2C_I2C_HOLD_REG 0x5
|
||||
+#define MLXCPLD_LPCI2C_CMD_REG 0x6
|
||||
+#define MLXCPLD_LPCI2C_NUM_DAT_REG 0x7
|
||||
+#define MLXCPLD_LPCI2C_NUM_ADDR_REG 0x8
|
||||
+#define MLXCPLD_LPCI2C_STATUS_REG 0x9
|
||||
+#define MLXCPLD_LPCI2C_DATA_REG 0xa
|
||||
+
|
||||
+/* LPC I2C masks and parametres */
|
||||
+#define MLXCPLD_LPCI2C_RST_SEL_MASK 0x1
|
||||
+#define MLXCPLD_LPCI2C_TRANS_END 0x1
|
||||
+#define MLXCPLD_LPCI2C_STATUS_NACK 0x10
|
||||
+#define MLXCPLD_LPCI2C_NO_IND 0
|
||||
+#define MLXCPLD_LPCI2C_ACK_IND 1
|
||||
+#define MLXCPLD_LPCI2C_NACK_IND 2
|
||||
+
|
||||
+struct mlxcpld_i2c_curr_xfer {
|
||||
+ u8 cmd;
|
||||
+ u8 addr_width;
|
||||
+ u8 data_len;
|
||||
+ u8 msg_num;
|
||||
+ struct i2c_msg *msg;
|
||||
+};
|
||||
+
|
||||
+struct mlxcpld_i2c_priv {
|
||||
+ struct i2c_adapter adap;
|
||||
+ u32 base_addr;
|
||||
+ struct mutex lock;
|
||||
+ struct mlxcpld_i2c_curr_xfer xfer;
|
||||
+ struct device *dev;
|
||||
+};
|
||||
+
|
||||
+static void mlxcpld_i2c_lpc_write_buf(u8 *data, u8 len, u32 addr)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < len - len % 4; i += 4)
|
||||
+ outl(*(u32 *)(data + i), addr + i);
|
||||
+ for (; i < len; ++i)
|
||||
+ outb(*(data + i), addr + i);
|
||||
+}
|
||||
+
|
||||
+static void mlxcpld_i2c_lpc_read_buf(u8 *data, u8 len, u32 addr)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < len - len % 4; i += 4)
|
||||
+ *(u32 *)(data + i) = inl(addr + i);
|
||||
+ for (; i < len; ++i)
|
||||
+ *(data + i) = inb(addr + i);
|
||||
+}
|
||||
+
|
||||
+static void mlxcpld_i2c_read_comm(struct mlxcpld_i2c_priv *priv, u8 offs,
|
||||
+ u8 *data, u8 datalen)
|
||||
+{
|
||||
+ u32 addr = priv->base_addr + offs;
|
||||
+
|
||||
+ switch (datalen) {
|
||||
+ case 1:
|
||||
+ *(data) = inb(addr);
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ *((u16 *)data) = inw(addr);
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ *((u16 *)data) = inw(addr);
|
||||
+ *(data + 2) = inb(addr + 2);
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ *((u32 *)data) = inl(addr);
|
||||
+ break;
|
||||
+ default:
|
||||
+ mlxcpld_i2c_lpc_read_buf(data, datalen, addr);
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void mlxcpld_i2c_write_comm(struct mlxcpld_i2c_priv *priv, u8 offs,
|
||||
+ u8 *data, u8 datalen)
|
||||
+{
|
||||
+ u32 addr = priv->base_addr + offs;
|
||||
+
|
||||
+ switch (datalen) {
|
||||
+ case 1:
|
||||
+ outb(*(data), addr);
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ outw(*((u16 *)data), addr);
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ outw(*((u16 *)data), addr);
|
||||
+ outb(*(data + 2), addr + 2);
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ outl(*((u32 *)data), addr);
|
||||
+ break;
|
||||
+ default:
|
||||
+ mlxcpld_i2c_lpc_write_buf(data, datalen, addr);
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Check validity of received i2c messages parameters.
|
||||
+ * Returns 0 if OK, other - in case of invalid parameters.
|
||||
+ */
|
||||
+static int mlxcpld_i2c_check_msg_params(struct mlxcpld_i2c_priv *priv,
|
||||
+ struct i2c_msg *msgs, int num)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ if (!num) {
|
||||
+ dev_err(priv->dev, "Incorrect 0 num of messages\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (unlikely(msgs[0].addr > 0x7f)) {
|
||||
+ dev_err(priv->dev, "Invalid address 0x%03x\n",
|
||||
+ msgs[0].addr);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < num; ++i) {
|
||||
+ if (unlikely(!msgs[i].buf)) {
|
||||
+ dev_err(priv->dev, "Invalid buf in msg[%d]\n",
|
||||
+ i);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ if (unlikely(msgs[0].addr != msgs[i].addr)) {
|
||||
+ dev_err(priv->dev, "Invalid addr in msg[%d]\n",
|
||||
+ i);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Check if transfer is completed and status of operation.
|
||||
+ * Returns 0 - transfer completed (both ACK or NACK),
|
||||
+ * negative - transfer isn't finished.
|
||||
+ */
|
||||
+static int mlxcpld_i2c_check_status(struct mlxcpld_i2c_priv *priv, int *status)
|
||||
+{
|
||||
+ u8 val;
|
||||
+
|
||||
+ mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_STATUS_REG, &val, 1);
|
||||
+
|
||||
+ if (val & MLXCPLD_LPCI2C_TRANS_END) {
|
||||
+ if (val & MLXCPLD_LPCI2C_STATUS_NACK)
|
||||
+ /*
|
||||
+ * The slave is unable to accept the data. No such
|
||||
+ * slave, command not understood, or unable to accept
|
||||
+ * any more data.
|
||||
+ */
|
||||
+ *status = MLXCPLD_LPCI2C_NACK_IND;
|
||||
+ else
|
||||
+ *status = MLXCPLD_LPCI2C_ACK_IND;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ *status = MLXCPLD_LPCI2C_NO_IND;
|
||||
+
|
||||
+ return -EIO;
|
||||
+}
|
||||
+
|
||||
+static void mlxcpld_i2c_set_transf_data(struct mlxcpld_i2c_priv *priv,
|
||||
+ struct i2c_msg *msgs, int num,
|
||||
+ u8 comm_len)
|
||||
+{
|
||||
+ priv->xfer.msg = msgs;
|
||||
+ priv->xfer.msg_num = num;
|
||||
+
|
||||
+ /*
|
||||
+ * All upper layers currently are never use transfer with more than
|
||||
+ * 2 messages. Actually, it's also not so relevant in Mellanox systems
|
||||
+ * because of HW limitation. Max size of transfer is not more than 32
|
||||
+ * bytes in the current x86 LPCI2C bridge.
|
||||
+ */
|
||||
+ priv->xfer.cmd = msgs[num - 1].flags & I2C_M_RD;
|
||||
+
|
||||
+ if (priv->xfer.cmd == I2C_M_RD && comm_len != msgs[0].len) {
|
||||
+ priv->xfer.addr_width = msgs[0].len;
|
||||
+ priv->xfer.data_len = comm_len - priv->xfer.addr_width;
|
||||
+ } else {
|
||||
+ priv->xfer.addr_width = 0;
|
||||
+ priv->xfer.data_len = comm_len;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Reset CPLD LPCI2C block */
|
||||
+static void mlxcpld_i2c_reset(struct mlxcpld_i2c_priv *priv)
|
||||
+{
|
||||
+ u8 val;
|
||||
+
|
||||
+ mutex_lock(&priv->lock);
|
||||
+
|
||||
+ mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_CTRL_REG, &val, 1);
|
||||
+ val &= ~MLXCPLD_LPCI2C_RST_SEL_MASK;
|
||||
+ mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_CTRL_REG, &val, 1);
|
||||
+
|
||||
+ mutex_unlock(&priv->lock);
|
||||
+}
|
||||
+
|
||||
+/* Make sure the CPLD is ready to start transmitting. */
|
||||
+static int mlxcpld_i2c_check_busy(struct mlxcpld_i2c_priv *priv)
|
||||
+{
|
||||
+ u8 val;
|
||||
+
|
||||
+ mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_STATUS_REG, &val, 1);
|
||||
+
|
||||
+ if (val & MLXCPLD_LPCI2C_TRANS_END)
|
||||
+ return 0;
|
||||
+
|
||||
+ return -EIO;
|
||||
+}
|
||||
+
|
||||
+static int mlxcpld_i2c_wait_for_free(struct mlxcpld_i2c_priv *priv)
|
||||
+{
|
||||
+ int timeout = 0;
|
||||
+
|
||||
+ do {
|
||||
+ if (!mlxcpld_i2c_check_busy(priv))
|
||||
+ break;
|
||||
+ usleep_range(MLXCPLD_I2C_POLL_TIME / 2, MLXCPLD_I2C_POLL_TIME);
|
||||
+ timeout += MLXCPLD_I2C_POLL_TIME;
|
||||
+ } while (timeout <= MLXCPLD_I2C_XFER_TO);
|
||||
+
|
||||
+ if (timeout > MLXCPLD_I2C_XFER_TO)
|
||||
+ return -ETIMEDOUT;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Wait for master transfer to complete.
|
||||
+ * It puts current process to sleep until we get interrupt or timeout expires.
|
||||
+ * Returns the number of transferred or read bytes or error (<0).
|
||||
+ */
|
||||
+static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv)
|
||||
+{
|
||||
+ int status, i, timeout = 0;
|
||||
+ u8 datalen;
|
||||
+
|
||||
+ do {
|
||||
+ usleep_range(MLXCPLD_I2C_POLL_TIME / 2, MLXCPLD_I2C_POLL_TIME);
|
||||
+ if (!mlxcpld_i2c_check_status(priv, &status))
|
||||
+ break;
|
||||
+ timeout += MLXCPLD_I2C_POLL_TIME;
|
||||
+ } while (status == 0 && timeout < MLXCPLD_I2C_XFER_TO);
|
||||
+
|
||||
+ switch (status) {
|
||||
+ case MLXCPLD_LPCI2C_NO_IND:
|
||||
+ return -ETIMEDOUT;
|
||||
+
|
||||
+ case MLXCPLD_LPCI2C_ACK_IND:
|
||||
+ if (priv->xfer.cmd != I2C_M_RD)
|
||||
+ return (priv->xfer.addr_width + priv->xfer.data_len);
|
||||
+
|
||||
+ if (priv->xfer.msg_num == 1)
|
||||
+ i = 0;
|
||||
+ else
|
||||
+ i = 1;
|
||||
+
|
||||
+ if (!priv->xfer.msg[i].buf)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /*
|
||||
+ * Actual read data len will be always the same as
|
||||
+ * requested len. 0xff (line pull-up) will be returned
|
||||
+ * if slave has no data to return. Thus don't read
|
||||
+ * MLXCPLD_LPCI2C_NUM_DAT_REG reg from CPLD.
|
||||
+ */
|
||||
+ datalen = priv->xfer.data_len;
|
||||
+
|
||||
+ mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_DATA_REG,
|
||||
+ priv->xfer.msg[i].buf, datalen);
|
||||
+
|
||||
+ return datalen;
|
||||
+
|
||||
+ case MLXCPLD_LPCI2C_NACK_IND:
|
||||
+ return -ENXIO;
|
||||
+
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void mlxcpld_i2c_xfer_msg(struct mlxcpld_i2c_priv *priv)
|
||||
+{
|
||||
+ int i, len = 0;
|
||||
+ u8 cmd;
|
||||
+
|
||||
+ mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_DAT_REG,
|
||||
+ &priv->xfer.data_len, 1);
|
||||
+ mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG,
|
||||
+ &priv->xfer.addr_width, 1);
|
||||
+
|
||||
+ for (i = 0; i < priv->xfer.msg_num; i++) {
|
||||
+ if ((priv->xfer.msg[i].flags & I2C_M_RD) != I2C_M_RD) {
|
||||
+ /* Don't write to CPLD buffer in read transaction */
|
||||
+ mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_DATA_REG +
|
||||
+ len, priv->xfer.msg[i].buf,
|
||||
+ priv->xfer.msg[i].len);
|
||||
+ len += priv->xfer.msg[i].len;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Set target slave address with command for master transfer.
|
||||
+ * It should be latest executed function before CPLD transaction.
|
||||
+ */
|
||||
+ cmd = (priv->xfer.msg[0].addr << 1) | priv->xfer.cmd;
|
||||
+ mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_CMD_REG, &cmd, 1);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Generic lpc-i2c transfer.
|
||||
+ * Returns the number of processed messages or error (<0).
|
||||
+ */
|
||||
+static int mlxcpld_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
|
||||
+ int num)
|
||||
+{
|
||||
+ struct mlxcpld_i2c_priv *priv = i2c_get_adapdata(adap);
|
||||
+ u8 comm_len = 0;
|
||||
+ int i, err;
|
||||
+
|
||||
+ err = mlxcpld_i2c_check_msg_params(priv, msgs, num);
|
||||
+ if (err) {
|
||||
+ dev_err(priv->dev, "Incorrect message\n");
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < num; ++i)
|
||||
+ comm_len += msgs[i].len;
|
||||
+
|
||||
+ /* Check bus state */
|
||||
+ if (mlxcpld_i2c_wait_for_free(priv)) {
|
||||
+ dev_err(priv->dev, "LPCI2C bridge is busy\n");
|
||||
+
|
||||
+ /*
|
||||
+ * Usually it means something serious has happened.
|
||||
+ * We can not have unfinished previous transfer
|
||||
+ * so it doesn't make any sense to try to stop it.
|
||||
+ * Probably we were not able to recover from the
|
||||
+ * previous error.
|
||||
+ * The only reasonable thing - is soft reset.
|
||||
+ */
|
||||
+ mlxcpld_i2c_reset(priv);
|
||||
+ if (mlxcpld_i2c_check_busy(priv)) {
|
||||
+ dev_err(priv->dev, "LPCI2C bridge is busy after reset\n");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ mlxcpld_i2c_set_transf_data(priv, msgs, num, comm_len);
|
||||
+
|
||||
+ mutex_lock(&priv->lock);
|
||||
+
|
||||
+ /* Do real transfer. Can't fail */
|
||||
+ mlxcpld_i2c_xfer_msg(priv);
|
||||
+
|
||||
+ /* Wait for transaction complete */
|
||||
+ err = mlxcpld_i2c_wait_for_tc(priv);
|
||||
+
|
||||
+ mutex_unlock(&priv->lock);
|
||||
+
|
||||
+ return err < 0 ? err : num;
|
||||
+}
|
||||
+
|
||||
+static u32 mlxcpld_i2c_func(struct i2c_adapter *adap)
|
||||
+{
|
||||
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||
+}
|
||||
+
|
||||
+static const struct i2c_algorithm mlxcpld_i2c_algo = {
|
||||
+ .master_xfer = mlxcpld_i2c_xfer,
|
||||
+ .functionality = mlxcpld_i2c_func
|
||||
+};
|
||||
+
|
||||
+static struct i2c_adapter_quirks mlxcpld_i2c_quirks = {
|
||||
+ .flags = I2C_AQ_COMB_WRITE_THEN_READ,
|
||||
+ .max_read_len = MLXCPLD_I2C_DATA_REG_SZ - MLXCPLD_I2C_MAX_ADDR_LEN,
|
||||
+ .max_write_len = MLXCPLD_I2C_DATA_REG_SZ,
|
||||
+ .max_comb_1st_msg_len = 4,
|
||||
+};
|
||||
+
|
||||
+static struct i2c_adapter mlxcpld_i2c_adapter = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .name = "i2c-mlxcpld",
|
||||
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
+ .algo = &mlxcpld_i2c_algo,
|
||||
+ .quirks = &mlxcpld_i2c_quirks,
|
||||
+ .retries = MLXCPLD_I2C_RETR_NUM,
|
||||
+ .nr = MLXCPLD_I2C_BUS_NUM,
|
||||
+};
|
||||
+
|
||||
+static int mlxcpld_i2c_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mlxcpld_i2c_priv *priv;
|
||||
+ int err;
|
||||
+
|
||||
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
+ if (!priv)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ mutex_init(&priv->lock);
|
||||
+ platform_set_drvdata(pdev, priv);
|
||||
+
|
||||
+ priv->dev = &pdev->dev;
|
||||
+
|
||||
+ /* Register with i2c layer */
|
||||
+ mlxcpld_i2c_adapter.timeout = usecs_to_jiffies(MLXCPLD_I2C_XFER_TO);
|
||||
+ priv->adap = mlxcpld_i2c_adapter;
|
||||
+ priv->adap.dev.parent = &pdev->dev;
|
||||
+ priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR;
|
||||
+ i2c_set_adapdata(&priv->adap, priv);
|
||||
+
|
||||
+ err = i2c_add_numbered_adapter(&priv->adap);
|
||||
+ if (err)
|
||||
+ mutex_destroy(&priv->lock);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int mlxcpld_i2c_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mlxcpld_i2c_priv *priv = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ i2c_del_adapter(&priv->adap);
|
||||
+ mutex_destroy(&priv->lock);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver mlxcpld_i2c_driver = {
|
||||
+ .probe = mlxcpld_i2c_probe,
|
||||
+ .remove = mlxcpld_i2c_remove,
|
||||
+ .driver = {
|
||||
+ .name = MLXCPLD_I2C_DEVICE_NAME,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(mlxcpld_i2c_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Michael Shych <michaels@mellanox.com>");
|
||||
+MODULE_DESCRIPTION("Mellanox I2C-CPLD controller driver");
|
||||
+MODULE_LICENSE("Dual BSD/GPL");
|
||||
+MODULE_ALIAS("platform:i2c-mlxcpld");
|
||||
@@ -0,0 +1,317 @@
|
||||
Linux backport patch. Includes following commits:
|
||||
e3448e71adb1fdd7f403c568ef5c2ed5adf2b197
|
||||
c3bb77620da428884807fb2f6f3485644e146f84
|
||||
db5f807ee3dcc779b78f59982cc3e89863069e9c
|
||||
|
||||
|
||||
diff -Nur a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
|
||||
--- a/drivers/i2c/muxes/Kconfig 2017-11-12 08:13:59.176044126 +0000
|
||||
+++ b/drivers/i2c/muxes/Kconfig 2017-11-12 08:14:27.992044509 +0000
|
||||
@@ -82,4 +82,15 @@
|
||||
demultiplexer that uses the pinctrl subsystem. This is useful if you
|
||||
want to change the I2C master at run-time depending on features.
|
||||
|
||||
+config I2C_MUX_MLXCPLD
|
||||
+ tristate "Mellanox CPLD based I2C multiplexer"
|
||||
+ help
|
||||
+ If you say yes to this option, support will be included for a
|
||||
+ CPLD based I2C multiplexer. This driver provides access to
|
||||
+ I2C busses connected through a MUX, which is controlled
|
||||
+ by a CPLD register.
|
||||
+
|
||||
+ This driver can also be built as a module. If so, the module
|
||||
+ will be called i2c-mux-mlxcpld.
|
||||
+
|
||||
endmenu
|
||||
diff -Nur a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile
|
||||
--- a/drivers/i2c/muxes/Makefile 2017-11-12 08:13:59.176044126 +0000
|
||||
+++ b/drivers/i2c/muxes/Makefile 2017-11-12 08:14:27.992044509 +0000
|
||||
@@ -6,6 +6,7 @@
|
||||
obj-$(CONFIG_I2C_DEMUX_PINCTRL) += i2c-demux-pinctrl.o
|
||||
|
||||
obj-$(CONFIG_I2C_MUX_GPIO) += i2c-mux-gpio.o
|
||||
+obj-$(CONFIG_I2C_MUX_MLXCPLD) += i2c-mux-mlxcpld.o
|
||||
obj-$(CONFIG_I2C_MUX_PCA9541) += i2c-mux-pca9541.o
|
||||
obj-$(CONFIG_I2C_MUX_PCA954x) += i2c-mux-pca954x.o
|
||||
obj-$(CONFIG_I2C_MUX_PINCTRL) += i2c-mux-pinctrl.o
|
||||
diff -Nur a/drivers/i2c/muxes/i2c-mux-mlxcpld.c b/drivers/i2c/muxes/i2c-mux-mlxcpld.c
|
||||
--- a/drivers/i2c/muxes/i2c-mux-mlxcpld.c 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/drivers/i2c/muxes/i2c-mux-mlxcpld.c 2017-11-12 08:14:27.992044509 +0000
|
||||
@@ -0,0 +1,221 @@
|
||||
+/*
|
||||
+ * drivers/i2c/muxes/i2c-mux-mlxcpld.c
|
||||
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
|
||||
+ * Copyright (c) 2016 Michael Shych <michaels@mellanox.com>
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions are met:
|
||||
+ *
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ * 3. Neither the names of the copyright holders nor the names of its
|
||||
+ * contributors may be used to endorse or promote products derived from
|
||||
+ * this software without specific prior written permission.
|
||||
+ *
|
||||
+ * Alternatively, this software may be distributed under the terms of the
|
||||
+ * GNU General Public License ("GPL") version 2 as published by the Free
|
||||
+ * Software Foundation.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
+ * POSSIBILITY OF SUCH DAMAGE.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/i2c-mux.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/i2c/mlxcpld.h>
|
||||
+
|
||||
+#define CPLD_MUX_MAX_NCHANS 8
|
||||
+
|
||||
+/* mlxcpld_mux - mux control structure:
|
||||
+ * @last_chan - last register value
|
||||
+ * @client - I2C device client
|
||||
+ */
|
||||
+struct mlxcpld_mux {
|
||||
+ u8 last_chan;
|
||||
+ struct i2c_client *client;
|
||||
+};
|
||||
+
|
||||
+/* MUX logic description.
|
||||
+ * Driver can support different mux control logic, according to CPLD
|
||||
+ * implementation.
|
||||
+ *
|
||||
+ * Connectivity schema.
|
||||
+ *
|
||||
+ * i2c-mlxcpld Digital Analog
|
||||
+ * driver
|
||||
+ * *--------* * -> mux1 (virt bus2) -> mux -> |
|
||||
+ * | I2CLPC | i2c physical * -> mux2 (virt bus3) -> mux -> |
|
||||
+ * | bridge | bus 1 *---------* |
|
||||
+ * | logic |---------------------> * mux reg * |
|
||||
+ * | in CPLD| *---------* |
|
||||
+ * *--------* i2c-mux-mlxpcld ^ * -> muxn (virt busn) -> mux -> |
|
||||
+ * | driver | |
|
||||
+ * | *---------------* | Devices
|
||||
+ * | * CPLD (i2c bus)* select |
|
||||
+ * | * registers for *--------*
|
||||
+ * | * mux selection * deselect
|
||||
+ * | *---------------*
|
||||
+ * | |
|
||||
+ * <--------> <----------->
|
||||
+ * i2c cntrl Board cntrl reg
|
||||
+ * reg space space (mux select,
|
||||
+ * IO, LED, WD, info)
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+static const struct i2c_device_id mlxcpld_mux_id[] = {
|
||||
+ { "mlxcpld_mux_module", 0 },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(i2c, mlxcpld_mux_id);
|
||||
+
|
||||
+/* Write to mux register. Don't use i2c_transfer() and i2c_smbus_xfer()
|
||||
+ * for this as they will try to lock adapter a second time.
|
||||
+ */
|
||||
+static int mlxcpld_mux_reg_write(struct i2c_adapter *adap,
|
||||
+ struct i2c_client *client, u8 val)
|
||||
+{
|
||||
+ struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&client->dev);
|
||||
+ int ret = -ENODEV;
|
||||
+
|
||||
+ if (adap->algo->master_xfer) {
|
||||
+ struct i2c_msg msg;
|
||||
+ u8 msgbuf[] = {pdata->sel_reg_addr, val};
|
||||
+
|
||||
+ msg.addr = client->addr;
|
||||
+ msg.flags = 0;
|
||||
+ msg.len = 2;
|
||||
+ msg.buf = msgbuf;
|
||||
+ ret = __i2c_transfer(adap, &msg, 1);
|
||||
+
|
||||
+ if (ret >= 0 && ret != 1)
|
||||
+ ret = -EREMOTEIO;
|
||||
+ } else if (adap->algo->smbus_xfer) {
|
||||
+ union i2c_smbus_data data;
|
||||
+
|
||||
+ data.byte = val;
|
||||
+ ret = adap->algo->smbus_xfer(adap, client->addr,
|
||||
+ client->flags, I2C_SMBUS_WRITE,
|
||||
+ pdata->sel_reg_addr,
|
||||
+ I2C_SMBUS_BYTE_DATA, &data);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mlxcpld_mux_select_chan(struct i2c_mux_core *muxc, u32 chan)
|
||||
+{
|
||||
+ struct mlxcpld_mux *data = i2c_mux_priv(muxc);
|
||||
+ struct i2c_client *client = data->client;
|
||||
+ u8 regval = chan + 1;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ /* Only select the channel if its different from the last channel */
|
||||
+ if (data->last_chan != regval) {
|
||||
+ err = mlxcpld_mux_reg_write(muxc->parent, client, regval);
|
||||
+ data->last_chan = err < 0 ? 0 : regval;
|
||||
+ }
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int mlxcpld_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
|
||||
+{
|
||||
+ struct mlxcpld_mux *data = i2c_mux_priv(muxc);
|
||||
+ struct i2c_client *client = data->client;
|
||||
+
|
||||
+ /* Deselect active channel */
|
||||
+ data->last_chan = 0;
|
||||
+
|
||||
+ return mlxcpld_mux_reg_write(muxc->parent, client, data->last_chan);
|
||||
+}
|
||||
+
|
||||
+/* Probe/reomove functions */
|
||||
+static int mlxcpld_mux_probe(struct i2c_client *client,
|
||||
+ const struct i2c_device_id *id)
|
||||
+{
|
||||
+ struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
|
||||
+ struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&client->dev);
|
||||
+ struct i2c_mux_core *muxc;
|
||||
+ int num, force;
|
||||
+ struct mlxcpld_mux *data;
|
||||
+ int err;
|
||||
+
|
||||
+ if (!pdata)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ muxc = i2c_mux_alloc(adap, &client->dev, CPLD_MUX_MAX_NCHANS,
|
||||
+ sizeof(*data), 0, mlxcpld_mux_select_chan,
|
||||
+ mlxcpld_mux_deselect);
|
||||
+ if (!muxc)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ data = i2c_mux_priv(muxc);
|
||||
+ i2c_set_clientdata(client, muxc);
|
||||
+ data->client = client;
|
||||
+ data->last_chan = 0; /* force the first selection */
|
||||
+
|
||||
+ /* Create an adapter for each channel. */
|
||||
+ for (num = 0; num < CPLD_MUX_MAX_NCHANS; num++) {
|
||||
+ if (num >= pdata->num_adaps)
|
||||
+ /* discard unconfigured channels */
|
||||
+ break;
|
||||
+
|
||||
+ force = pdata->adap_ids[num];
|
||||
+
|
||||
+ err = i2c_mux_add_adapter(muxc, force, num, 0);
|
||||
+ if (err)
|
||||
+ goto virt_reg_failed;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+virt_reg_failed:
|
||||
+ i2c_mux_del_adapters(muxc);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int mlxcpld_mux_remove(struct i2c_client *client)
|
||||
+{
|
||||
+ struct i2c_mux_core *muxc = i2c_get_clientdata(client);
|
||||
+
|
||||
+ i2c_mux_del_adapters(muxc);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct i2c_driver mlxcpld_mux_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "mlxcpld-mux",
|
||||
+ },
|
||||
+ .probe = mlxcpld_mux_probe,
|
||||
+ .remove = mlxcpld_mux_remove,
|
||||
+ .id_table = mlxcpld_mux_id,
|
||||
+};
|
||||
+
|
||||
+module_i2c_driver(mlxcpld_mux_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Michael Shych (michaels@mellanox.com)");
|
||||
+MODULE_DESCRIPTION("Mellanox I2C-CPLD-MUX driver");
|
||||
+MODULE_LICENSE("Dual BSD/GPL");
|
||||
+MODULE_ALIAS("platform:i2c-mux-mlxcpld");
|
||||
diff -Nur a/include/linux/i2c/mlxcpld.h b/include/linux/i2c/mlxcpld.h
|
||||
--- a/include/linux/i2c/mlxcpld.h 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/include/linux/i2c/mlxcpld.h 2017-11-12 08:17:03.032046568 +0000
|
||||
@@ -0,0 +1,52 @@
|
||||
+/*
|
||||
+ * mlxcpld.h - Mellanox I2C multiplexer support in CPLD
|
||||
+ *
|
||||
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
|
||||
+ * Copyright (c) 2016 Michael Shych <michaels@mellanox.com>
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions are met:
|
||||
+ *
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ * 3. Neither the names of the copyright holders nor the names of its
|
||||
+ * contributors may be used to endorse or promote products derived from
|
||||
+ * this software without specific prior written permission.
|
||||
+ *
|
||||
+ * Alternatively, this software may be distributed under the terms of the
|
||||
+ * GNU General Public License ("GPL") version 2 as published by the Free
|
||||
+ * Software Foundation.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
+ * POSSIBILITY OF SUCH DAMAGE.
|
||||
+ */
|
||||
+
|
||||
+#ifndef _LINUX_I2C_MLXCPLD_H
|
||||
+#define _LINUX_I2C_MLXCPLD_H
|
||||
+
|
||||
+/* Platform data for the CPLD I2C multiplexers */
|
||||
+
|
||||
+/* mlxcpld_mux_plat_data - per mux data, used with i2c_register_board_info
|
||||
+ * @adap_ids - adapter array
|
||||
+ * @num_adaps - number of adapters
|
||||
+ * @sel_reg_addr - mux select register offset in CPLD space
|
||||
+ */
|
||||
+struct mlxcpld_mux_plat_data {
|
||||
+ int *adap_ids;
|
||||
+ int num_adaps;
|
||||
+ int sel_reg_addr;
|
||||
+};
|
||||
+
|
||||
+#endif /* _LINUX_I2C_MLXCPLD_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,905 @@
|
||||
Linux backport patch. Includes following commits:
|
||||
2926024b5081fc8d4b086677bafa1ac55ea0b911
|
||||
6124fdf76488681713f278f3fdf2ba2dfe760211
|
||||
c84002d15210ca130263e23911cc399202124eb4
|
||||
07b89c2b2a5e8ce30166b96f87b324c6b419f108
|
||||
91973760712f350048a0fa8e0363e260bf874313
|
||||
c2e714e56360e34f88e0a75ee74e467d8b82de75
|
||||
af4779be0f2cec63f4cb15d3db78c5de3523756a
|
||||
d53bc5dc941653f0ed93b11a647bd6ff40f40ef2
|
||||
|
||||
|
||||
diff -Nur a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig
|
||||
--- a/drivers/platform/mellanox/Kconfig 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/drivers/platform/mellanox/Kconfig 2017-11-12 08:54:58.200076777 +0000
|
||||
@@ -0,0 +1,25 @@
|
||||
+#
|
||||
+# Platform support for Mellanox hardware
|
||||
+#
|
||||
+
|
||||
+menuconfig MELLANOX_PLATFORM
|
||||
+ bool "Platform support for Mellanox hardware"
|
||||
+ depends on X86 || ARM || COMPILE_TEST
|
||||
+ ---help---
|
||||
+ Say Y here to get to see options for platform support for
|
||||
+ Mellanox systems. This option alone does not add any kernel code.
|
||||
+
|
||||
+ If you say N, all options in this submenu will be skipped and disabled.
|
||||
+
|
||||
+if MELLANOX_PLATFORM
|
||||
+
|
||||
+config MLXREG_HOTPLUG
|
||||
+ tristate "Mellanox platform hotplug driver support"
|
||||
+ depends on REGMAP
|
||||
+ depends on HWMON
|
||||
+ depends on I2C
|
||||
+ ---help---
|
||||
+ This driver handles hot-plug events for the power suppliers, power
|
||||
+ cables and fans on the wide range Mellanox IB and Ethernet systems.
|
||||
+
|
||||
+endif # MELLANOX_PLATFORM
|
||||
diff -Nur a/drivers/platform/mellanox/Makefile b/drivers/platform/mellanox/Makefile
|
||||
--- a/drivers/platform/mellanox/Makefile 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/drivers/platform/mellanox/Makefile 2017-11-12 08:54:58.200076777 +0000
|
||||
@@ -0,0 +1 @@
|
||||
+obj-$(CONFIG_MLXREG_HOTPLUG) += mlxreg-hotplug.o
|
||||
diff -Nur a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c
|
||||
--- a/drivers/platform/mellanox/mlxreg-hotplug.c 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c 2017-11-12 08:54:58.200076777 +0000
|
||||
@@ -0,0 +1,710 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
|
||||
+ * Copyright (c) 2017 Vadim Pasternak <vadimp@mellanox.com>
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions are met:
|
||||
+ *
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ * 3. Neither the names of the copyright holders nor the names of its
|
||||
+ * contributors may be used to endorse or promote products derived from
|
||||
+ * this software without specific prior written permission.
|
||||
+ *
|
||||
+ * Alternatively, this software may be distributed under the terms of the
|
||||
+ * GNU General Public License ("GPL") version 2 as published by the Free
|
||||
+ * Software Foundation.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
+ * POSSIBILITY OF SUCH DAMAGE.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/hwmon.h>
|
||||
+#include <linux/hwmon-sysfs.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/platform_data/mlxreg.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/workqueue.h>
|
||||
+
|
||||
+/* Offset of event and mask registers from status register. */
|
||||
+#define MLXREG_HOTPLUG_EVENT_OFF 1
|
||||
+#define MLXREG_HOTPLUG_MASK_OFF 2
|
||||
+#define MLXREG_HOTPLUG_AGGR_MASK_OFF 1
|
||||
+
|
||||
+/* ASIC health parameters. */
|
||||
+#define MLXREG_HOTPLUG_HEALTH_MASK 0x02
|
||||
+#define MLXREG_HOTPLUG_RST_CNTR 3
|
||||
+
|
||||
+#define MLXREG_HOTPLUG_PROP_OKAY "okay"
|
||||
+#define MLXREG_HOTPLUG_PROP_DISABLED "disabled"
|
||||
+#define MLXREG_HOTPLUG_PROP_STATUS "status"
|
||||
+
|
||||
+#define MLXREG_HOTPLUG_ATTRS_MAX 24
|
||||
+
|
||||
+/**
|
||||
+ * struct mlxreg_hotplug_priv_data - platform private data:
|
||||
+ * @irq: platform device interrupt number;
|
||||
+ * @pdev: platform device;
|
||||
+ * @plat: platform data;
|
||||
+ * @dwork: delayed work template;
|
||||
+ * @lock: spin lock;
|
||||
+ * @hwmon: hwmon device;
|
||||
+ * @mlxreg_hotplug_attr: sysfs attributes array;
|
||||
+ * @mlxreg_hotplug_dev_attr: sysfs sensor device attribute array;
|
||||
+ * @group: sysfs attribute group;
|
||||
+ * @groups: list of sysfs attribute group for hwmon registration;
|
||||
+ * @cell: location of top aggregation interrupt register;
|
||||
+ * @mask: top aggregation interrupt common mask;
|
||||
+ * @aggr_cache: last value of aggregation register status;
|
||||
+ */
|
||||
+struct mlxreg_hotplug_priv_data {
|
||||
+ int irq;
|
||||
+ struct device *dev;
|
||||
+ struct platform_device *pdev;
|
||||
+ struct mlxreg_hotplug_platform_data *plat;
|
||||
+ struct regmap *regmap;
|
||||
+ struct delayed_work dwork_irq;
|
||||
+ struct delayed_work dwork;
|
||||
+ spinlock_t lock; /* sync with interrupt */
|
||||
+ struct device *hwmon;
|
||||
+ struct attribute *mlxreg_hotplug_attr[MLXREG_HOTPLUG_ATTRS_MAX + 1];
|
||||
+ struct sensor_device_attribute_2
|
||||
+ mlxreg_hotplug_dev_attr[MLXREG_HOTPLUG_ATTRS_MAX];
|
||||
+ struct attribute_group group;
|
||||
+ const struct attribute_group *groups[2];
|
||||
+ u32 cell;
|
||||
+ u32 mask;
|
||||
+ u32 aggr_cache;
|
||||
+ bool after_probe;
|
||||
+};
|
||||
+
|
||||
+#if defined(CONFIG_OF_DYNAMIC)
|
||||
+/**
|
||||
+ * struct mlxreg_hotplug_device_en - Open Firmware property for enabling device
|
||||
+ *
|
||||
+ * @name - property name;
|
||||
+ * @value - property value string;
|
||||
+ * @length - length of proprty value string;
|
||||
+ *
|
||||
+ * The structure is used for the devices, which require some dynamic
|
||||
+ * selection operation allowing access to them.
|
||||
+ */
|
||||
+static struct property mlxreg_hotplug_device_en = {
|
||||
+ .name = MLXREG_HOTPLUG_PROP_STATUS,
|
||||
+ .value = MLXREG_HOTPLUG_PROP_OKAY,
|
||||
+ .length = sizeof(MLXREG_HOTPLUG_PROP_OKAY),
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct mlxreg_hotplug_device_dis - Open Firmware property for disabling
|
||||
+ * device
|
||||
+ *
|
||||
+ * @name - property name;
|
||||
+ * @value - property value string;
|
||||
+ * @length - length of proprty value string;
|
||||
+ *
|
||||
+ * The structure is used for the devices, which require some dynamic
|
||||
+ * selection operation disallowing access to them.
|
||||
+ */
|
||||
+static struct property mlxreg_hotplug_device_dis = {
|
||||
+ .name = MLXREG_HOTPLUG_PROP_STATUS,
|
||||
+ .value = MLXREG_HOTPLUG_PROP_DISABLED,
|
||||
+ .length = sizeof(MLXREG_HOTPLUG_PROP_DISABLED),
|
||||
+};
|
||||
+
|
||||
+static int mlxreg_hotplug_of_device_create(struct mlxreg_core_data *data)
|
||||
+{
|
||||
+ return of_update_property(data->np, &mlxreg_hotplug_device_en);
|
||||
+}
|
||||
+
|
||||
+static void mlxreg_hotplug_of_device_destroy(struct mlxreg_core_data *data)
|
||||
+{
|
||||
+ of_update_property(data->np, &mlxreg_hotplug_device_dis);
|
||||
+ of_node_clear_flag(data->np, OF_POPULATED);
|
||||
+}
|
||||
+#else
|
||||
+static int mlxreg_hotplug_of_device_create(struct mlxreg_core_data *data)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void mlxreg_hotplug_of_device_destroy(struct mlxreg_core_data *data)
|
||||
+{
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static int mlxreg_hotplug_device_create(struct mlxreg_core_data *data)
|
||||
+{
|
||||
+ data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr);
|
||||
+ if (!data->hpdev.adapter)
|
||||
+ return -EFAULT;
|
||||
+
|
||||
+ data->hpdev.client = i2c_new_device(data->hpdev.adapter,
|
||||
+ data->hpdev.brdinfo);
|
||||
+ if (!data->hpdev.client) {
|
||||
+ i2c_put_adapter(data->hpdev.adapter);
|
||||
+ data->hpdev.adapter = NULL;
|
||||
+ return -EFAULT;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void mlxreg_hotplug_device_destroy(struct mlxreg_core_data *data)
|
||||
+{
|
||||
+ if (data->hpdev.client) {
|
||||
+ i2c_unregister_device(data->hpdev.client);
|
||||
+ data->hpdev.client = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (data->hpdev.adapter) {
|
||||
+ i2c_put_adapter(data->hpdev.adapter);
|
||||
+ data->hpdev.adapter = NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_hotplug_dev_enable(struct mlxreg_core_data *data)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ /* Enable and create device. */
|
||||
+ if (data->np)
|
||||
+ err = mlxreg_hotplug_of_device_create(data);
|
||||
+ else
|
||||
+ err = mlxreg_hotplug_device_create(data);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static void mlxreg_hotplug_dev_disable(struct mlxreg_core_data *data)
|
||||
+{
|
||||
+ /* Disable and unregister platform device. */
|
||||
+ if (data->np)
|
||||
+ mlxreg_hotplug_of_device_destroy(data);
|
||||
+ else
|
||||
+ mlxreg_hotplug_device_destroy(data);
|
||||
+}
|
||||
+
|
||||
+static ssize_t mlxreg_hotplug_attr_show(struct device *dev,
|
||||
+ struct device_attribute *attr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ struct mlxreg_hotplug_priv_data *priv = dev_get_drvdata(dev);
|
||||
+ struct mlxreg_core_hotplug_platform_data *pdata;
|
||||
+ int index = to_sensor_dev_attr_2(attr)->index;
|
||||
+ int nr = to_sensor_dev_attr_2(attr)->nr;
|
||||
+ struct mlxreg_core_item *item;
|
||||
+ struct mlxreg_core_data *data;
|
||||
+ u32 regval;
|
||||
+ int ret;
|
||||
+
|
||||
+ pdata = dev_get_platdata(&priv->pdev->dev);
|
||||
+ item = pdata->items + nr;
|
||||
+ data = item->data + index;
|
||||
+
|
||||
+ ret = regmap_read(priv->regmap, data->reg, ®val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (item->health) {
|
||||
+ regval &= data->mask;
|
||||
+ } else {
|
||||
+ /* Bit = 0 : functional if item->inversed is true. */
|
||||
+ if (item->inversed)
|
||||
+ regval = !(regval & data->mask);
|
||||
+ else
|
||||
+ regval = !!(regval & data->mask);
|
||||
+ }
|
||||
+
|
||||
+ return sprintf(buf, "%u\n", regval);
|
||||
+}
|
||||
+
|
||||
+#define PRIV_ATTR(i) priv->mlxreg_hotplug_attr[i]
|
||||
+#define PRIV_DEV_ATTR(i) priv->mlxreg_hotplug_dev_attr[i]
|
||||
+
|
||||
+static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv)
|
||||
+{
|
||||
+ struct mlxreg_core_hotplug_platform_data *pdata;
|
||||
+ struct mlxreg_core_item *item;
|
||||
+ struct mlxreg_core_data *data;
|
||||
+ int num_attrs = 0, id = 0, i, j;
|
||||
+
|
||||
+ pdata = dev_get_platdata(&priv->pdev->dev);
|
||||
+ item = pdata->items;
|
||||
+
|
||||
+ /* Go over all kinds of items - psu, pwr, fan. */
|
||||
+ for (i = 0; i < pdata->counter; i++, item++) {
|
||||
+ num_attrs += item->count;
|
||||
+ data = item->data;
|
||||
+ /* Go over all units within the item. */
|
||||
+ for (j = 0; j < item->count; j++, data++, id++) {
|
||||
+ PRIV_ATTR(id) = &PRIV_DEV_ATTR(id).dev_attr.attr;
|
||||
+ PRIV_ATTR(id)->name = devm_kasprintf(&priv->pdev->dev,
|
||||
+ GFP_KERNEL,
|
||||
+ data->label);
|
||||
+
|
||||
+ if (!PRIV_ATTR(id)->name) {
|
||||
+ dev_err(priv->dev, "Memory allocation failed for attr %d.\n",
|
||||
+ id);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ PRIV_DEV_ATTR(id).dev_attr.attr.name =
|
||||
+ PRIV_ATTR(id)->name;
|
||||
+ PRIV_DEV_ATTR(id).dev_attr.attr.mode = 0444;
|
||||
+ PRIV_DEV_ATTR(id).dev_attr.show =
|
||||
+ mlxreg_hotplug_attr_show;
|
||||
+ PRIV_DEV_ATTR(id).nr = i;
|
||||
+ PRIV_DEV_ATTR(id).index = j;
|
||||
+ sysfs_attr_init(&PRIV_DEV_ATTR(id).dev_attr.attr);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ priv->group.attrs = devm_kzalloc(&priv->pdev->dev, num_attrs *
|
||||
+ sizeof(struct attribute *),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!priv->group.attrs)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ priv->group.attrs = priv->mlxreg_hotplug_attr;
|
||||
+ priv->groups[0] = &priv->group;
|
||||
+ priv->groups[1] = NULL;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv,
|
||||
+ struct mlxreg_core_item *item)
|
||||
+{
|
||||
+ struct mlxreg_core_data *data;
|
||||
+ u32 asserted, regval, bit;
|
||||
+ int ret;
|
||||
+
|
||||
+ /*
|
||||
+ * Validate if item related to received signal type is valid.
|
||||
+ * It should never happen, excepted the situation when some
|
||||
+ * piece of hardware is broken. In such situation just produce
|
||||
+ * error message and return. Caller must continue to handle the
|
||||
+ * signals from other devices if any.
|
||||
+ */
|
||||
+ if (unlikely(!item)) {
|
||||
+ dev_err(priv->dev, "False signal: at offset:mask 0x%02x:0x%02x.\n",
|
||||
+ item->reg, item->mask);
|
||||
+
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Mask event. */
|
||||
+ ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_MASK_OFF,
|
||||
+ 0);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+
|
||||
+ /* Read status. */
|
||||
+ ret = regmap_read(priv->regmap, item->reg, ®val);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+
|
||||
+ /* Set asserted bits and save last status. */
|
||||
+ regval &= item->mask;
|
||||
+ asserted = item->cache ^ regval;
|
||||
+ item->cache = regval;
|
||||
+
|
||||
+ for_each_set_bit(bit, (unsigned long *)&asserted, 8) {
|
||||
+ data = item->data + bit;
|
||||
+ if (regval & BIT(bit)) {
|
||||
+ if (item->inversed)
|
||||
+ mlxreg_hotplug_dev_disable(data);
|
||||
+ else
|
||||
+ mlxreg_hotplug_dev_enable(data);
|
||||
+ } else {
|
||||
+ if (item->inversed)
|
||||
+ mlxreg_hotplug_dev_enable(data);
|
||||
+ else
|
||||
+ mlxreg_hotplug_dev_disable(data);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Acknowledge event. */
|
||||
+ ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_EVENT_OFF,
|
||||
+ 0);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+
|
||||
+ /* Unmask event. */
|
||||
+ ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_MASK_OFF,
|
||||
+ item->mask);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+
|
||||
+ return;
|
||||
+
|
||||
+access_error:
|
||||
+ dev_err(priv->dev, "Failed to complete workqueue.\n");
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv,
|
||||
+ struct mlxreg_core_item *item)
|
||||
+{
|
||||
+ struct mlxreg_core_data *data = item->data;
|
||||
+ u32 regval;
|
||||
+ int i, ret;
|
||||
+
|
||||
+ for (i = 0; i < item->count; i++, data++) {
|
||||
+ /* Mask event. */
|
||||
+ ret = regmap_write(priv->regmap, data->reg +
|
||||
+ MLXREG_HOTPLUG_MASK_OFF, 0);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+
|
||||
+ /* Read status. */
|
||||
+ ret = regmap_read(priv->regmap, data->reg, ®val);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+
|
||||
+ regval &= data->mask;
|
||||
+ item->cache = regval;
|
||||
+ if (regval == MLXREG_HOTPLUG_HEALTH_MASK) {
|
||||
+ if ((data->health_cntr++ == MLXREG_HOTPLUG_RST_CNTR) ||
|
||||
+ !priv->after_probe) {
|
||||
+ mlxreg_hotplug_dev_enable(data);
|
||||
+ data->attached = true;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (data->attached) {
|
||||
+ mlxreg_hotplug_dev_disable(data);
|
||||
+ data->attached = false;
|
||||
+ data->health_cntr = 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Acknowledge event. */
|
||||
+ ret = regmap_write(priv->regmap, data->reg +
|
||||
+ MLXREG_HOTPLUG_EVENT_OFF, 0);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+
|
||||
+ /* Unmask event. */
|
||||
+ ret = regmap_write(priv->regmap, data->reg +
|
||||
+ MLXREG_HOTPLUG_MASK_OFF, data->mask);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+ }
|
||||
+
|
||||
+ return;
|
||||
+
|
||||
+access_error:
|
||||
+ dev_err(priv->dev, "Failed to complete workqueue.\n");
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * mlxreg_hotplug_work_handler - performs traversing of device interrupt
|
||||
+ * registers according to the below hierarchy schema:
|
||||
+ *
|
||||
+ * Aggregation registers (status/mask)
|
||||
+ * PSU registers: *---*
|
||||
+ * *-----------------* | |
|
||||
+ * |status/event/mask|-----> | * |
|
||||
+ * *-----------------* | |
|
||||
+ * Power registers: | |
|
||||
+ * *-----------------* | |
|
||||
+ * |status/event/mask|-----> | * |
|
||||
+ * *-----------------* | |
|
||||
+ * FAN registers: | |--> CPU
|
||||
+ * *-----------------* | |
|
||||
+ * |status/event/mask|-----> | * |
|
||||
+ * *-----------------* | |
|
||||
+ * ASIC registers: | |
|
||||
+ * *-----------------* | |
|
||||
+ * |status/event/mask|-----> | * |
|
||||
+ * *-----------------* | |
|
||||
+ * *---*
|
||||
+ *
|
||||
+ * In case some system changed are detected: FAN in/out, PSU in/out, power
|
||||
+ * cable attached/detached, ASIC helath good/bad, relevant device is created
|
||||
+ * or destroyed.
|
||||
+ */
|
||||
+static void mlxreg_hotplug_work_handler(struct work_struct *work)
|
||||
+{
|
||||
+ struct mlxreg_hotplug_priv_data *priv = container_of(work,
|
||||
+ struct mlxreg_hotplug_priv_data, dwork_irq.work);
|
||||
+ struct mlxreg_core_hotplug_platform_data *pdata;
|
||||
+ struct mlxreg_core_item *item;
|
||||
+ unsigned long flags;
|
||||
+ u32 regval, aggr_asserted;
|
||||
+ int i;
|
||||
+ int ret;
|
||||
+
|
||||
+ pdata = dev_get_platdata(&priv->pdev->dev);
|
||||
+ item = pdata->items;
|
||||
+ /* Mask aggregation event. */
|
||||
+ ret = regmap_write(priv->regmap, pdata->cell +
|
||||
+ MLXREG_HOTPLUG_AGGR_MASK_OFF, 0);
|
||||
+ if (ret < 0)
|
||||
+ goto access_error;
|
||||
+
|
||||
+ /* Read aggregation status. */
|
||||
+ ret = regmap_read(priv->regmap, pdata->cell, ®val);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+
|
||||
+ regval &= pdata->mask;
|
||||
+ aggr_asserted = priv->aggr_cache ^ regval;
|
||||
+ priv->aggr_cache = regval;
|
||||
+
|
||||
+ /* Handle topology and health configuration changes. */
|
||||
+ for (i = 0; i < pdata->counter; i++, item++) {
|
||||
+ if (aggr_asserted & item->aggr_mask) {
|
||||
+ if (item->health)
|
||||
+ mlxreg_hotplug_health_work_helper(priv, item);
|
||||
+ else
|
||||
+ mlxreg_hotplug_work_helper(priv, item);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (aggr_asserted) {
|
||||
+ spin_lock_irqsave(&priv->lock, flags);
|
||||
+
|
||||
+ /*
|
||||
+ * It is possible, that some signals have been inserted, while
|
||||
+ * interrupt has been masked by mlxreg_hotplug_work_handler.
|
||||
+ * In this case such signals will be missed. In order to handle
|
||||
+ * these signals delayed work is canceled and work task
|
||||
+ * re-scheduled for immediate execution. It allows to handle
|
||||
+ * missed signals, if any. In other case work handler just
|
||||
+ * validates that no new signals have been received during
|
||||
+ * masking.
|
||||
+ */
|
||||
+ cancel_delayed_work(&priv->dwork_irq);
|
||||
+ schedule_delayed_work(&priv->dwork_irq, 0);
|
||||
+
|
||||
+ spin_unlock_irqrestore(&priv->lock, flags);
|
||||
+
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Unmask aggregation event (no need acknowledge). */
|
||||
+ ret = regmap_write(priv->regmap, pdata->cell +
|
||||
+ MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+
|
||||
+ return;
|
||||
+
|
||||
+access_error:
|
||||
+ dev_err(priv->dev, "Failed to complete workqueue.\n");
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv)
|
||||
+{
|
||||
+ struct mlxreg_core_hotplug_platform_data *pdata;
|
||||
+ struct mlxreg_core_item *item;
|
||||
+ int i;
|
||||
+ int ret;
|
||||
+
|
||||
+ pdata = dev_get_platdata(&priv->pdev->dev);
|
||||
+ item = pdata->items;
|
||||
+
|
||||
+ for (i = 0; i < pdata->counter; i++, item++) {
|
||||
+ /* Clear group presense event. */
|
||||
+ ret = regmap_write(priv->regmap, item->reg +
|
||||
+ MLXREG_HOTPLUG_EVENT_OFF, 0);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+
|
||||
+ /* Set group initial status as mask and unmask group event. */
|
||||
+ if (item->inversed) {
|
||||
+ item->cache = item->mask;
|
||||
+ ret = regmap_write(priv->regmap, item->reg +
|
||||
+ MLXREG_HOTPLUG_MASK_OFF,
|
||||
+ item->mask);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Keep aggregation initial status as zero and unmask events. */
|
||||
+ ret = regmap_write(priv->regmap, pdata->cell +
|
||||
+ MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+
|
||||
+ /* Keep low aggregation initial status as zero and unmask events. */
|
||||
+ ret = regmap_write(priv->regmap, pdata->cell_low +
|
||||
+ MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask_low);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+
|
||||
+ /* Invoke work handler for initializing hot plug devices setting. */
|
||||
+ mlxreg_hotplug_work_handler(&priv->dwork_irq.work);
|
||||
+
|
||||
+ enable_irq(priv->irq);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+access_error:
|
||||
+ dev_err(priv->dev, "Failed to set interrupts.\n");
|
||||
+
|
||||
+ enable_irq(priv->irq);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void mlxreg_hotplug_unset_irq(struct mlxreg_hotplug_priv_data *priv)
|
||||
+{
|
||||
+ struct mlxreg_core_hotplug_platform_data *pdata;
|
||||
+ struct mlxreg_core_item *item;
|
||||
+ struct mlxreg_core_data *data;
|
||||
+ int count, i, j;
|
||||
+
|
||||
+ pdata = dev_get_platdata(&priv->pdev->dev);
|
||||
+ item = pdata->items;
|
||||
+ disable_irq(priv->irq);
|
||||
+ cancel_delayed_work_sync(&priv->dwork_irq);
|
||||
+
|
||||
+ /* Mask low aggregation event. */
|
||||
+ regmap_write(priv->regmap, pdata->cell_low +
|
||||
+ MLXREG_HOTPLUG_AGGR_MASK_OFF, 0);
|
||||
+
|
||||
+ /* Mask aggregation event. */
|
||||
+ regmap_write(priv->regmap, pdata->cell + MLXREG_HOTPLUG_AGGR_MASK_OFF,
|
||||
+ 0);
|
||||
+
|
||||
+ /* Clear topology configurations. */
|
||||
+ for (i = 0; i < pdata->counter; i++, item++) {
|
||||
+ data = item->data;
|
||||
+ /* Mask group presense event. */
|
||||
+ regmap_write(priv->regmap, data->reg + MLXREG_HOTPLUG_MASK_OFF,
|
||||
+ 0);
|
||||
+ /* Clear group presense event. */
|
||||
+ regmap_write(priv->regmap, data->reg +
|
||||
+ MLXREG_HOTPLUG_EVENT_OFF, 0);
|
||||
+
|
||||
+ /* Remove all the attached devices in group. */
|
||||
+ count = item->count;
|
||||
+ for (j = 0; j < count; j++, data++)
|
||||
+ mlxreg_hotplug_dev_disable(data);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t mlxreg_hotplug_irq_handler(int irq, void *dev)
|
||||
+{
|
||||
+ struct mlxreg_hotplug_priv_data *priv =
|
||||
+ (struct mlxreg_hotplug_priv_data *)dev;
|
||||
+
|
||||
+ /* Schedule work task for immediate execution.*/
|
||||
+ schedule_delayed_work(&priv->dwork_irq, 0);
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_hotplug_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mlxreg_core_hotplug_platform_data *pdata;
|
||||
+ struct mlxreg_hotplug_priv_data *priv;
|
||||
+ int err;
|
||||
+
|
||||
+ pdata = dev_get_platdata(&pdev->dev);
|
||||
+ if (!pdata) {
|
||||
+ dev_err(&pdev->dev, "Failed to get platform data.\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
+ if (!priv)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ if (pdata->irq) {
|
||||
+ priv->irq = pdata->irq;
|
||||
+ } else {
|
||||
+ priv->irq = platform_get_irq(pdev, 0);
|
||||
+ if (priv->irq < 0) {
|
||||
+ dev_err(&pdev->dev, "Failed to get platform irq: %d\n",
|
||||
+ priv->irq);
|
||||
+ return priv->irq;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ priv->regmap = pdata->regmap;
|
||||
+ priv->dev = pdev->dev.parent;
|
||||
+ priv->pdev = pdev;
|
||||
+
|
||||
+ err = devm_request_irq(&pdev->dev, priv->irq,
|
||||
+ mlxreg_hotplug_irq_handler, IRQF_TRIGGER_FALLING
|
||||
+ | IRQF_SHARED, "mlxreg-hotplug", priv);
|
||||
+ if (err) {
|
||||
+ dev_err(&pdev->dev, "Failed to request irq: %d\n", err);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ disable_irq(priv->irq);
|
||||
+ spin_lock_init(&priv->lock);
|
||||
+ INIT_DELAYED_WORK(&priv->dwork_irq, mlxreg_hotplug_work_handler);
|
||||
+ /* Perform initial interrupts setup. */
|
||||
+ mlxreg_hotplug_set_irq(priv);
|
||||
+
|
||||
+ priv->after_probe = true;
|
||||
+ dev_set_drvdata(&pdev->dev, priv);
|
||||
+
|
||||
+ err = mlxreg_hotplug_attr_init(priv);
|
||||
+ if (err) {
|
||||
+ dev_err(&pdev->dev, "Failed to allocate attributes: %d\n",
|
||||
+ err);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ priv->hwmon = devm_hwmon_device_register_with_groups(&pdev->dev,
|
||||
+ "mlxreg_hotplug", priv, priv->groups);
|
||||
+ if (IS_ERR(priv->hwmon)) {
|
||||
+ dev_err(&pdev->dev, "Failed to register hwmon device %ld\n",
|
||||
+ PTR_ERR(priv->hwmon));
|
||||
+ return PTR_ERR(priv->hwmon);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_hotplug_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mlxreg_hotplug_priv_data *priv = dev_get_drvdata(&pdev->dev);
|
||||
+
|
||||
+ /* Clean interrupts setup. */
|
||||
+ mlxreg_hotplug_unset_irq(priv);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver mlxreg_hotplug_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "mlxreg-hotplug",
|
||||
+ },
|
||||
+ .probe = mlxreg_hotplug_probe,
|
||||
+ .remove = mlxreg_hotplug_remove,
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(mlxreg_hotplug_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
|
||||
+MODULE_DESCRIPTION("Mellanox regmap hotplug platform driver");
|
||||
+MODULE_LICENSE("Dual BSD/GPL");
|
||||
+MODULE_ALIAS("platform:mlxreg-hotplug");
|
||||
diff -Nur a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h
|
||||
--- a/include/linux/platform_data/mlxreg.h 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/include/linux/platform_data/mlxreg.h 2017-11-12 09:04:09.796084101 +0000
|
||||
@@ -0,0 +1,142 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
|
||||
+ * Copyright (c) 2017 Vadim Pasternak <vadimp@mellanox.com>
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions are met:
|
||||
+ *
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ * 3. Neither the names of the copyright holders nor the names of its
|
||||
+ * contributors may be used to endorse or promote products derived from
|
||||
+ * this software without specific prior written permission.
|
||||
+ *
|
||||
+ * Alternatively, this software may be distributed under the terms of the
|
||||
+ * GNU General Public License ("GPL") version 2 as published by the Free
|
||||
+ * Software Foundation.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
+ * POSSIBILITY OF SUCH DAMAGE.
|
||||
+ */
|
||||
+
|
||||
+#ifndef __LINUX_PLATFORM_DATA_MLXREG_H
|
||||
+#define __LINUX_PLATFORM_DATA_MLXREG_H
|
||||
+
|
||||
+#define MLXREG_CORE_LABEL_MAX_SIZE 32
|
||||
+
|
||||
+/**
|
||||
+ * struct mlxreg_hotplug_device - I2C device data:
|
||||
+ *
|
||||
+ * @adapter: I2C device adapter;
|
||||
+ * @client: I2C device client;
|
||||
+ * @brdinfo: device board information;
|
||||
+ * @nr: I2C device adapter number, to which device is to be attached;
|
||||
+ *
|
||||
+ * Structure represents I2C hotplug device static data (board topology) and
|
||||
+ * dynamic data (related kernel objects handles).
|
||||
+ */
|
||||
+struct mlxreg_hotplug_device {
|
||||
+ struct i2c_adapter *adapter;
|
||||
+ struct i2c_client *client;
|
||||
+ struct i2c_board_info *brdinfo;
|
||||
+ int nr;
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct mlxreg_core_data - attributes control data:
|
||||
+ *
|
||||
+ * @label: attribute label;
|
||||
+ * @label: attribute register offset;
|
||||
+ * @reg: attribute register;
|
||||
+ * @mask: attribute access mask;
|
||||
+ * @bit: attribute effective bit;
|
||||
+ * @np - pointer to node platform associated with attribute;
|
||||
+ * @hpdev - hotplug device data;
|
||||
+ * @health_cntr: dynamic device health indication counter;
|
||||
+ * @attached: true if device has been attached after good helath indication;
|
||||
+ */
|
||||
+struct mlxreg_core_data {
|
||||
+ char label[MLXREG_CORE_LABEL_MAX_SIZE];
|
||||
+ u32 reg;
|
||||
+ u32 mask;
|
||||
+ u32 bit;
|
||||
+ struct device_node *np;
|
||||
+ struct mlxreg_hotplug_device hpdev;
|
||||
+ u8 health_cntr;
|
||||
+ bool attached;
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct mlxreg_core_item - same type components controlled by the driver:
|
||||
+ *
|
||||
+ * @data: component data;
|
||||
+ * @aggr_mask: group aggregation mask;
|
||||
+ * @reg: group interrupt status register;
|
||||
+ * @mask: group interrupt mask;
|
||||
+ * @cache: last status value for elements fro the same group;
|
||||
+ * @count: number of available elements in the group;
|
||||
+ * @ind: element's index inside the group;
|
||||
+ * @inversed: if 0: 0 for signal status is OK, if 1 - 1 is OK;
|
||||
+ * @health: true if device has health indication, false in other case;
|
||||
+ */
|
||||
+struct mlxreg_core_item {
|
||||
+ struct mlxreg_core_data *data;
|
||||
+ u32 aggr_mask;
|
||||
+ u32 reg;
|
||||
+ u32 mask;
|
||||
+ u32 cache;
|
||||
+ u8 count;
|
||||
+ u8 ind;
|
||||
+ u8 inversed;
|
||||
+ u8 health;
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct mlxreg_core_led_platform_data - led platform data:
|
||||
+ *
|
||||
+ * @led_data: led private data;
|
||||
+ * @regmap: register map of parent device;
|
||||
+ * @counter: number of led instances;
|
||||
+ */
|
||||
+struct mlxreg_core_led_platform_data {
|
||||
+ struct mlxreg_core_data *data;
|
||||
+ void *regmap;
|
||||
+ int counter;
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct mlxreg_core_hotplug_platform_data - hotplug platform data:
|
||||
+ *
|
||||
+ * @items: same type components with the hotplug capability;
|
||||
+ * @irq: platform interrupt number;
|
||||
+ * @regmap: register map of parent device;
|
||||
+ * @counter: number of the components with the hotplug capability;
|
||||
+ * @cell: location of top aggregation interrupt register;
|
||||
+ * @mask: top aggregation interrupt common mask;
|
||||
+ * @cell_low: location of low aggregation interrupt register;
|
||||
+ * @mask_low: low aggregation interrupt common mask;
|
||||
+ */
|
||||
+struct mlxreg_core_hotplug_platform_data {
|
||||
+ struct mlxreg_core_item *items;
|
||||
+ int irq;
|
||||
+ void *regmap;
|
||||
+ int counter;
|
||||
+ u32 cell;
|
||||
+ u32 mask;
|
||||
+ u32 cell_low;
|
||||
+ u32 mask_low;
|
||||
+};
|
||||
+
|
||||
+#endif /* __LINUX_PLATFORM_DATA_MLXREG_H */
|
||||
@@ -0,0 +1,398 @@
|
||||
Linux backport patch. Includes following commits:
|
||||
7dc37aeb560416771cbdc286357157c7565dc1fe
|
||||
9244ef4cb79a8411656cb8fc2366f32f2294a0c9
|
||||
daf155fe70c9d69c28bba632b6a758ac8feab6e7
|
||||
|
||||
|
||||
diff -Nur a/drivers/leds/Kconfig b/drivers/leds/Kconfig
|
||||
--- a/drivers/leds/Kconfig 2017-11-12 09:08:40.740087699 +0000
|
||||
+++ b/drivers/leds/Kconfig 2017-11-12 09:06:54.580086289 +0000
|
||||
@@ -659,6 +659,35 @@
|
||||
This option enabled support for the LEDs on the Mellanox
|
||||
boards. Say Y to enabled these.
|
||||
|
||||
+config LEDS_MLXREG
|
||||
+ tristate "LED support for the Mellanox BMC cards"
|
||||
+ depends on LEDS_CLASS
|
||||
+ help
|
||||
+ This option enabled support for the LEDs on the Mellanox BMC cards.
|
||||
+ The driver can be activated from the device tree or by the direct
|
||||
+ platform device add call. Say Y to enabled these. To compile this
|
||||
+ driver as a module, choose 'M' here: the module will be called
|
||||
+ leds-mlxreg.
|
||||
+
|
||||
+config LEDS_USER
|
||||
+ tristate "Userspace LED support"
|
||||
+ depends on LEDS_CLASS
|
||||
+ help
|
||||
+ This option enables support for userspace LEDs. Say 'y' to enable this
|
||||
+ support in kernel. To compile this driver as a module, choose 'm' here:
|
||||
+ the module will be called uleds.
|
||||
+
|
||||
+config LEDS_NIC78BX
|
||||
+ tristate "LED support for NI PXI NIC78bx devices"
|
||||
+ depends on LEDS_CLASS
|
||||
+ depends on X86 && ACPI
|
||||
+ help
|
||||
+ This option enables support for the User1 and User2 LEDs on NI
|
||||
+ PXI NIC78bx devices.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the module
|
||||
+ will be called leds-nic78bx.
|
||||
+
|
||||
comment "LED Triggers"
|
||||
source "drivers/leds/trigger/Kconfig"
|
||||
|
||||
diff -Nur a/drivers/leds/Makefile b/drivers/leds/Makefile
|
||||
--- a/drivers/leds/Makefile 2017-11-12 09:08:40.740087699 +0000
|
||||
+++ b/drivers/leds/Makefile 2017-11-12 09:06:54.580086289 +0000
|
||||
@@ -71,6 +71,7 @@
|
||||
obj-$(CONFIG_LEDS_IS31FL32XX) += leds-is31fl32xx.o
|
||||
obj-$(CONFIG_LEDS_PM8058) += leds-pm8058.o
|
||||
obj-$(CONFIG_LEDS_MLXCPLD) += leds-mlxcpld.o
|
||||
+obj-$(CONFIG_LEDS_MLXREG) += leds-mlxreg.o
|
||||
|
||||
# LED SPI Drivers
|
||||
obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
|
||||
diff -Nur a/drivers/leds/leds-mlxcpld.c b/drivers/leds/leds-mlxcpld.c
|
||||
--- a/drivers/leds/leds-mlxcpld.c 2017-11-12 09:08:40.740087699 +0000
|
||||
+++ b/drivers/leds/leds-mlxcpld.c 2017-11-12 09:08:05.620087233 +0000
|
||||
@@ -400,6 +400,9 @@
|
||||
struct platform_device *pdev;
|
||||
int err;
|
||||
|
||||
+ if (!dmi_match(DMI_CHASSIS_VENDOR, "Mellanox Technologies Ltd."))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
|
||||
if (IS_ERR(pdev)) {
|
||||
pr_err("Device allocation failed\n");
|
||||
@@ -426,5 +429,5 @@
|
||||
|
||||
MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
|
||||
MODULE_DESCRIPTION("Mellanox board LED driver");
|
||||
-MODULE_LICENSE("GPL v2");
|
||||
+MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_ALIAS("platform:leds_mlxcpld");
|
||||
diff -Nur a/drivers/leds/leds-mlxreg.c b/drivers/leds/leds-mlxreg.c
|
||||
--- a/drivers/leds/leds-mlxreg.c 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/drivers/leds/leds-mlxreg.c 2017-11-12 09:06:54.580086289 +0000
|
||||
@@ -0,0 +1,318 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
|
||||
+ * Copyright (c) 2017 Vadim Pasternak <vadimp@mellanox.com>
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions are met:
|
||||
+ *
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ * 3. Neither the names of the copyright holders nor the names of its
|
||||
+ * contributors may be used to endorse or promote products derived from
|
||||
+ * this software without specific prior written permission.
|
||||
+ *
|
||||
+ * Alternatively, this software may be distributed under the terms of the
|
||||
+ * GNU General Public License ("GPL") version 2 as published by the Free
|
||||
+ * Software Foundation.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
+ * POSSIBILITY OF SUCH DAMAGE.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/leds.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/platform_data/mlxreg.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+
|
||||
+/* Codes for LEDs. */
|
||||
+#define MLXREG_LED_OFFSET_BLINK_3HZ 0x01 /* Offset from solid: 3Hz blink */
|
||||
+#define MLXREG_LED_OFFSET_BLINK_6HZ 0x02 /* Offset from solid: 6Hz blink */
|
||||
+#define MLXREG_LED_IS_OFF 0x00 /* Off */
|
||||
+#define MLXREG_LED_RED_SOLID 0x05 /* Solid red */
|
||||
+#define MLXREG_LED_GREEN_SOLID 0x0D /* Solid green */
|
||||
+#define MLXREG_LED_AMBER_SOLID 0x09 /* Solid amber */
|
||||
+#define MLXREG_LED_BLINK_3HZ 167 /* ~167 msec off/on - HW support */
|
||||
+#define MLXREG_LED_BLINK_6HZ 83 /* ~83 msec off/on - HW support */
|
||||
+
|
||||
+/**
|
||||
+ * struct mlxreg_led_data - led control data:
|
||||
+ *
|
||||
+ * @data: led configuration data;
|
||||
+ * @led_classdev: led class data;
|
||||
+ * @base_color: base led color (other colors have constant offset from base);
|
||||
+ * @led_data: led data;
|
||||
+ * @data_parent: pointer to private device control data of parent;
|
||||
+ */
|
||||
+struct mlxreg_led_data {
|
||||
+ struct mlxreg_core_data *data;
|
||||
+ struct led_classdev led_cdev;
|
||||
+ u8 base_color;
|
||||
+ void *data_parent;
|
||||
+ char led_cdev_name[MLXREG_CORE_LABEL_MAX_SIZE];
|
||||
+};
|
||||
+
|
||||
+#define cdev_to_priv(c) container_of(c, struct mlxreg_led_data, led_cdev)
|
||||
+
|
||||
+/**
|
||||
+ * struct mlxreg_led_priv_data - platform private data:
|
||||
+ *
|
||||
+ * @pdev: platform device;
|
||||
+ * @pdata: platform data;
|
||||
+ * @access_lock: mutex for attribute IO access;
|
||||
+ */
|
||||
+struct mlxreg_led_priv_data {
|
||||
+ struct platform_device *pdev;
|
||||
+ struct mlxreg_core_led_platform_data *pdata;
|
||||
+ struct mutex access_lock; /* protect IO operations */
|
||||
+};
|
||||
+
|
||||
+static int
|
||||
+mlxreg_led_store_hw(struct mlxreg_led_data *led_data, u8 vset)
|
||||
+{
|
||||
+ struct mlxreg_led_priv_data *priv = led_data->data_parent;
|
||||
+ struct mlxreg_core_led_platform_data *led_pdata = priv->pdata;
|
||||
+ struct mlxreg_core_data *data = led_data->data;
|
||||
+ u32 regval;
|
||||
+ u32 nib;
|
||||
+ int ret;
|
||||
+
|
||||
+ /*
|
||||
+ * Each LED is controlled through low or high nibble of the relevant
|
||||
+ * register byte. Register offset is specified by off parameter.
|
||||
+ * Parameter vset provides color code: 0x0 for off, 0x5 for solid red,
|
||||
+ * 0x6 for 3Hz blink red, 0xd for solid green, 0xe for 3Hz blink
|
||||
+ * green.
|
||||
+ * Parameter mask specifies which nibble is used for specific LED: mask
|
||||
+ * 0xf0 - lower nibble is to be used (bits from 0 to 3), mask 0x0f -
|
||||
+ * higher nibble (bits from 4 to 7).
|
||||
+ */
|
||||
+ mutex_lock(&priv->access_lock);
|
||||
+
|
||||
+ ret = regmap_read(led_pdata->regmap, data->reg, ®val);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+
|
||||
+ nib = (ror32(data->mask, data->bit) == 0xf0) ? rol32(vset, data->bit) :
|
||||
+ rol32(vset, data->bit + 4);
|
||||
+ regval = (regval & data->mask) | nib;
|
||||
+
|
||||
+ ret = regmap_write(led_pdata->regmap, data->reg, regval);
|
||||
+
|
||||
+access_error:
|
||||
+ mutex_unlock(&priv->access_lock);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static enum led_brightness
|
||||
+mlxreg_led_get_hw(struct mlxreg_led_data *led_data)
|
||||
+{
|
||||
+ struct mlxreg_led_priv_data *priv = led_data->data_parent;
|
||||
+ struct mlxreg_core_led_platform_data *led_pdata = priv->pdata;
|
||||
+ struct mlxreg_core_data *data = led_data->data;
|
||||
+ u32 regval;
|
||||
+ int ret;
|
||||
+
|
||||
+ /*
|
||||
+ * Each LED is controlled through low or high nibble of the relevant
|
||||
+ * register byte. Register offset is specified by off parameter.
|
||||
+ * Parameter vset provides color code: 0x0 for off, 0x5 for solid red,
|
||||
+ * 0x6 for 3Hz blink red, 0xd for solid green, 0xe for 3Hz blink
|
||||
+ * green.
|
||||
+ * Parameter mask specifies which nibble is used for specific LED: mask
|
||||
+ * 0xf0 - lower nibble is to be used (bits from 0 to 3), mask 0x0f -
|
||||
+ * higher nibble (bits from 4 to 7).
|
||||
+ */
|
||||
+ ret = regmap_read(led_pdata->regmap, data->reg, ®val);
|
||||
+ if (ret < 0) {
|
||||
+ dev_warn(led_data->led_cdev.dev, "Failed to get current brightness, error: %d\n",
|
||||
+ ret);
|
||||
+ /* Assume the LED is OFF */
|
||||
+ return LED_OFF;
|
||||
+ }
|
||||
+
|
||||
+ regval = regval & ~data->mask;
|
||||
+ regval = (ror32(data->mask, data->bit) == 0xf0) ? ror32(regval,
|
||||
+ data->bit) : ror32(regval, data->bit + 4);
|
||||
+ if (regval >= led_data->base_color &&
|
||||
+ regval <= (led_data->base_color + MLXREG_LED_OFFSET_BLINK_6HZ))
|
||||
+ ret = LED_FULL;
|
||||
+ else
|
||||
+ ret = LED_OFF;
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mlxreg_led_brightness_set(struct led_classdev *cled, enum led_brightness value)
|
||||
+{
|
||||
+ struct mlxreg_led_data *led_data = cdev_to_priv(cled);
|
||||
+
|
||||
+ if (value)
|
||||
+ return mlxreg_led_store_hw(led_data, led_data->base_color);
|
||||
+ else
|
||||
+ return mlxreg_led_store_hw(led_data, MLXREG_LED_IS_OFF);
|
||||
+}
|
||||
+
|
||||
+static enum led_brightness
|
||||
+mlxreg_led_brightness_get(struct led_classdev *cled)
|
||||
+{
|
||||
+ struct mlxreg_led_data *led_data = cdev_to_priv(cled);
|
||||
+
|
||||
+ return mlxreg_led_get_hw(led_data);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mlxreg_led_blink_set(struct led_classdev *cled, unsigned long *delay_on,
|
||||
+ unsigned long *delay_off)
|
||||
+{
|
||||
+ struct mlxreg_led_data *led_data = cdev_to_priv(cled);
|
||||
+ int err;
|
||||
+
|
||||
+ /*
|
||||
+ * HW supports two types of blinking: full (6Hz) and half (3Hz).
|
||||
+ * For delay on/off zero LED is setting to solid color. For others
|
||||
+ * combination blinking is to be controlled by the software timer.
|
||||
+ */
|
||||
+ if (!(*delay_on == 0 && *delay_off == 0) &&
|
||||
+ !(*delay_on == MLXREG_LED_BLINK_3HZ &&
|
||||
+ *delay_off == MLXREG_LED_BLINK_3HZ) &&
|
||||
+ !(*delay_on == MLXREG_LED_BLINK_6HZ &&
|
||||
+ *delay_off == MLXREG_LED_BLINK_6HZ))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (*delay_on == MLXREG_LED_BLINK_6HZ)
|
||||
+ err = mlxreg_led_store_hw(led_data, led_data->base_color +
|
||||
+ MLXREG_LED_OFFSET_BLINK_6HZ);
|
||||
+ else if (*delay_on == MLXREG_LED_BLINK_3HZ)
|
||||
+ err = mlxreg_led_store_hw(led_data, led_data->base_color +
|
||||
+ MLXREG_LED_OFFSET_BLINK_3HZ);
|
||||
+ else
|
||||
+ err = mlxreg_led_store_hw(led_data, led_data->base_color);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_led_config(struct mlxreg_led_priv_data *priv)
|
||||
+{
|
||||
+ struct mlxreg_core_led_platform_data *led_pdata = priv->pdata;
|
||||
+ struct mlxreg_core_data *data = led_pdata->data;
|
||||
+ struct mlxreg_led_data *led_data;
|
||||
+ struct led_classdev *led_cdev;
|
||||
+ int brightness;
|
||||
+ int i;
|
||||
+ int err;
|
||||
+
|
||||
+ for (i = 0; i < led_pdata->counter; i++, data++) {
|
||||
+ led_data = devm_kzalloc(&priv->pdev->dev, sizeof(*led_data),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!led_data)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ led_cdev = &led_data->led_cdev;
|
||||
+ led_data->data_parent = priv;
|
||||
+ if (strstr(data->label, "red") ||
|
||||
+ strstr(data->label, "orange")) {
|
||||
+ brightness = LED_OFF;
|
||||
+ led_data->base_color = MLXREG_LED_RED_SOLID;
|
||||
+ } else if (strstr(data->label, "amber")) {
|
||||
+ brightness = LED_OFF;
|
||||
+ led_data->base_color = MLXREG_LED_AMBER_SOLID;
|
||||
+ } else {
|
||||
+ brightness = LED_OFF;
|
||||
+ led_data->base_color = MLXREG_LED_GREEN_SOLID;
|
||||
+ }
|
||||
+ sprintf(led_data->led_cdev_name, "%s:%s", "mlxreg",
|
||||
+ data->label);
|
||||
+ led_cdev->name = led_data->led_cdev_name;
|
||||
+ led_cdev->brightness = brightness;
|
||||
+ led_cdev->max_brightness = 1;
|
||||
+ led_cdev->brightness_set_blocking =
|
||||
+ mlxreg_led_brightness_set;
|
||||
+ led_cdev->brightness_get = mlxreg_led_brightness_get;
|
||||
+ led_cdev->blink_set = mlxreg_led_blink_set;
|
||||
+ led_cdev->flags = LED_CORE_SUSPENDRESUME;
|
||||
+ led_data->data = data;
|
||||
+ err = devm_led_classdev_register(&priv->pdev->dev, led_cdev);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ if (led_cdev->brightness)
|
||||
+ mlxreg_led_brightness_set(led_cdev,
|
||||
+ led_cdev->brightness);
|
||||
+ dev_info(led_cdev->dev, "label: %s, mask: 0x%02x, offset:0x%02x\n",
|
||||
+ data->label, data->mask, data->reg);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_led_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mlxreg_core_led_platform_data *led_pdata;
|
||||
+ struct mlxreg_led_priv_data *priv;
|
||||
+
|
||||
+ led_pdata = dev_get_platdata(&pdev->dev);
|
||||
+ if (!led_pdata) {
|
||||
+ dev_err(&pdev->dev, "Failed to get platform data.\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
+ if (!priv)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ mutex_init(&priv->access_lock);
|
||||
+ priv->pdev = pdev;
|
||||
+ priv->pdata = led_pdata;
|
||||
+
|
||||
+ return mlxreg_led_config(priv);
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_led_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mlxreg_led_priv_data *priv = dev_get_drvdata(&pdev->dev);
|
||||
+
|
||||
+ mutex_destroy(&priv->access_lock);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id mlxreg_led_dt_match[] = {
|
||||
+ { .compatible = "mellanox,leds-mlxreg" },
|
||||
+ { },
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, mlxreg_led_dt_match);
|
||||
+
|
||||
+static struct platform_driver mlxreg_led_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "leds-mlxreg",
|
||||
+ .of_match_table = of_match_ptr(mlxreg_led_dt_match),
|
||||
+ },
|
||||
+ .probe = mlxreg_led_probe,
|
||||
+ .remove = mlxreg_led_remove,
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(mlxreg_led_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
|
||||
+MODULE_DESCRIPTION("Mellanox LED regmap driver");
|
||||
+MODULE_LICENSE("Dual BSD/GPL");
|
||||
+MODULE_ALIAS("platform:leds-mlxreg");
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
||||
Linux backport patch. Includes following commits:
|
||||
a4dffccb72a7fa46bb0d7f29e607375387e09956
|
||||
|
||||
|
||||
diff -Nur a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h
|
||||
--- a/drivers/hwmon/pmbus/pmbus.h 2017-11-09 16:25:22.760993964 +0000
|
||||
+++ b/drivers/hwmon/pmbus/pmbus.h 2017-11-09 16:26:02.568994492 +0000
|
||||
@@ -341,7 +341,7 @@
|
||||
#define PMBUS_HAVE_STATUS_VMON BIT(19)
|
||||
|
||||
enum pmbus_data_format { linear = 0, direct, vid };
|
||||
-enum vrm_version { vr11 = 0, vr12 };
|
||||
+enum vrm_version { vr11 = 0, vr12, vr13 };
|
||||
|
||||
struct pmbus_driver_info {
|
||||
int pages; /* Total number of pages */
|
||||
diff -Nur a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
|
||||
--- a/drivers/hwmon/pmbus/pmbus_core.c 2017-11-09 16:25:22.760993964 +0000
|
||||
+++ b/drivers/hwmon/pmbus/pmbus_core.c 2017-11-09 16:26:02.568994492 +0000
|
||||
@@ -531,6 +531,10 @@
|
||||
if (val >= 0x01)
|
||||
rv = 250 + (val - 1) * 5;
|
||||
break;
|
||||
+ case vr13:
|
||||
+ if (val >= 0x01)
|
||||
+ rv = 500 + (val - 1) * 10;
|
||||
+ break;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
Linux backport patch. Includes following commits:
|
||||
f7caf758e26ab84b2b9def9ec68235c85d645597
|
||||
|
||||
|
||||
diff -Nur a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
|
||||
--- a/drivers/hwmon/pmbus/Kconfig 2017-11-09 16:34:05.269000902 +0000
|
||||
+++ b/drivers/hwmon/pmbus/Kconfig 2017-11-09 16:35:49.701002288 +0000
|
||||
@@ -125,6 +125,15 @@
|
||||
This driver can also be built as a module. If so, the module will
|
||||
be called tps40422.
|
||||
|
||||
+config SENSORS_TPS53679
|
||||
+ tristate "TI TPS53679"
|
||||
+ help
|
||||
+ If you say yes here you get hardware monitoring support for TI
|
||||
+ TPS53679.
|
||||
+
|
||||
+ This driver can also be built as a module. If so, the module will
|
||||
+ be called tps53679.
|
||||
+
|
||||
config SENSORS_UCD9000
|
||||
tristate "TI UCD90120, UCD90124, UCD90160, UCD9090, UCD90910"
|
||||
default n
|
||||
diff -Nur a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
|
||||
--- a/drivers/hwmon/pmbus/Makefile 2017-11-09 16:34:05.269000902 +0000
|
||||
+++ b/drivers/hwmon/pmbus/Makefile 2017-11-09 16:35:49.701002288 +0000
|
||||
@@ -13,6 +13,7 @@
|
||||
obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
|
||||
obj-$(CONFIG_SENSORS_MAX8688) += max8688.o
|
||||
obj-$(CONFIG_SENSORS_TPS40422) += tps40422.o
|
||||
+obj-$(CONFIG_SENSORS_TPS53679) += tps53679.o
|
||||
obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o
|
||||
obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o
|
||||
obj-$(CONFIG_SENSORS_ZL6100) += zl6100.o
|
||||
diff -Nur a/drivers/hwmon/pmbus/tps53679.c b/drivers/hwmon/pmbus/tps53679.c
|
||||
--- a/drivers/hwmon/pmbus/tps53679.c 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/drivers/hwmon/pmbus/tps53679.c 2017-11-09 16:35:49.701002288 +0000
|
||||
@@ -0,0 +1,113 @@
|
||||
+/*
|
||||
+ * Hardware monitoring driver for Texas Instruments TPS53679
|
||||
+ *
|
||||
+ * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
|
||||
+ * Copyright (c) 2017 Vadim Pasternak <vadimp@mellanox.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation; either version 2 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include "pmbus.h"
|
||||
+
|
||||
+#define TPS53679_PROT_VR12_5MV 0x01 /* VR12.0 mode, 5-mV DAC */
|
||||
+#define TPS53679_PROT_VR12_5_10MV 0x02 /* VR12.5 mode, 10-mV DAC */
|
||||
+#define TPS53679_PROT_VR13_10MV 0x04 /* VR13.0 mode, 10-mV DAC */
|
||||
+#define TPS53679_PROT_IMVP8_5MV 0x05 /* IMVP8 mode, 5-mV DAC */
|
||||
+#define TPS53679_PROT_VR13_5MV 0x07 /* VR13.0 mode, 5-mV DAC */
|
||||
+#define TPS53679_PAGE_NUM 2
|
||||
+
|
||||
+static int tps53679_identify(struct i2c_client *client,
|
||||
+ struct pmbus_driver_info *info)
|
||||
+{
|
||||
+ u8 vout_params;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Read the register with VOUT scaling value.*/
|
||||
+ ret = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ vout_params = ret & GENMASK(4, 0);
|
||||
+
|
||||
+ switch (vout_params) {
|
||||
+ case TPS53679_PROT_VR13_10MV:
|
||||
+ case TPS53679_PROT_VR12_5_10MV:
|
||||
+ info->vrm_version = vr13;
|
||||
+ break;
|
||||
+ case TPS53679_PROT_VR13_5MV:
|
||||
+ case TPS53679_PROT_VR12_5MV:
|
||||
+ case TPS53679_PROT_IMVP8_5MV:
|
||||
+ info->vrm_version = vr12;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct pmbus_driver_info tps53679_info = {
|
||||
+ .pages = TPS53679_PAGE_NUM,
|
||||
+ .format[PSC_VOLTAGE_IN] = linear,
|
||||
+ .format[PSC_VOLTAGE_OUT] = vid,
|
||||
+ .format[PSC_TEMPERATURE] = linear,
|
||||
+ .format[PSC_CURRENT_OUT] = linear,
|
||||
+ .format[PSC_POWER] = linear,
|
||||
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
|
||||
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
|
||||
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
|
||||
+ PMBUS_HAVE_POUT,
|
||||
+ .func[1] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
|
||||
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
|
||||
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
|
||||
+ PMBUS_HAVE_POUT,
|
||||
+ .identify = tps53679_identify,
|
||||
+};
|
||||
+
|
||||
+static int tps53679_probe(struct i2c_client *client,
|
||||
+ const struct i2c_device_id *id)
|
||||
+{
|
||||
+ return pmbus_do_probe(client, id, &tps53679_info);
|
||||
+}
|
||||
+
|
||||
+static const struct i2c_device_id tps53679_id[] = {
|
||||
+ {"tps53679", 0},
|
||||
+ {}
|
||||
+};
|
||||
+
|
||||
+MODULE_DEVICE_TABLE(i2c, tps53679_id);
|
||||
+
|
||||
+static const struct of_device_id tps53679_of_match[] = {
|
||||
+ {.compatible = "ti,tps53679"},
|
||||
+ {}
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, tps53679_of_match);
|
||||
+
|
||||
+static struct i2c_driver tps53679_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "tps53679",
|
||||
+ .of_match_table = of_match_ptr(tps53679_of_match),
|
||||
+ },
|
||||
+ .probe = tps53679_probe,
|
||||
+ .remove = pmbus_do_remove,
|
||||
+ .id_table = tps53679_id,
|
||||
+};
|
||||
+
|
||||
+module_i2c_driver(tps53679_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
|
||||
+MODULE_DESCRIPTION("PMBus driver for Texas Instruments TPS53679");
|
||||
+MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,685 @@
|
||||
From 2c7476ab57dd42d8cba6c417ff32a77252964858 Mon Sep 17 00:00:00 2001
|
||||
From: Vadim Pasternak <vadimp@mellanox.com>
|
||||
Date: Thu, 16 Nov 2017 17:22:56 +0000
|
||||
Subject: [v4.9 backport 38/38] platform: mellonox: introduce mlxreg-io driver
|
||||
and add driver activation to mlx-platform
|
||||
|
||||
Patch introduces new module mlxreg-io, which exposes the registers of the
|
||||
programmable devices, equipped on Melanox systems to sysfs. These are the
|
||||
registers, which are used for system resets operation, system reset causes
|
||||
monitoring, select operation and version info.
|
||||
|
||||
Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
|
||||
---
|
||||
drivers/leds/leds-mlxreg.c | 10 +-
|
||||
drivers/platform/mellanox/Kconfig | 11 ++
|
||||
drivers/platform/mellanox/Makefile | 1 +
|
||||
drivers/platform/mellanox/mlxreg-io.c | 211 ++++++++++++++++++++++++++++++++++
|
||||
drivers/platform/x86/mlx-platform.c | 193 +++++++++++++++++++++++++++++--
|
||||
include/linux/platform_data/mlxreg.h | 6 +-
|
||||
6 files changed, 418 insertions(+), 14 deletions(-)
|
||||
create mode 100644 drivers/platform/mellanox/mlxreg-io.c
|
||||
|
||||
diff --git a/drivers/leds/leds-mlxreg.c b/drivers/leds/leds-mlxreg.c
|
||||
index a932f20..036c214 100644
|
||||
--- a/drivers/leds/leds-mlxreg.c
|
||||
+++ b/drivers/leds/leds-mlxreg.c
|
||||
@@ -79,7 +79,7 @@ struct mlxreg_led_data {
|
||||
*/
|
||||
struct mlxreg_led_priv_data {
|
||||
struct platform_device *pdev;
|
||||
- struct mlxreg_core_led_platform_data *pdata;
|
||||
+ struct mlxreg_core_platform_data *pdata;
|
||||
struct mutex access_lock; /* protect IO operations */
|
||||
};
|
||||
|
||||
@@ -87,7 +87,7 @@ static int
|
||||
mlxreg_led_store_hw(struct mlxreg_led_data *led_data, u8 vset)
|
||||
{
|
||||
struct mlxreg_led_priv_data *priv = led_data->data_parent;
|
||||
- struct mlxreg_core_led_platform_data *led_pdata = priv->pdata;
|
||||
+ struct mlxreg_core_platform_data *led_pdata = priv->pdata;
|
||||
struct mlxreg_core_data *data = led_data->data;
|
||||
u32 regval;
|
||||
u32 nib;
|
||||
@@ -125,7 +125,7 @@ static enum led_brightness
|
||||
mlxreg_led_get_hw(struct mlxreg_led_data *led_data)
|
||||
{
|
||||
struct mlxreg_led_priv_data *priv = led_data->data_parent;
|
||||
- struct mlxreg_core_led_platform_data *led_pdata = priv->pdata;
|
||||
+ struct mlxreg_core_platform_data *led_pdata = priv->pdata;
|
||||
struct mlxreg_core_data *data = led_data->data;
|
||||
u32 regval;
|
||||
int ret;
|
||||
@@ -212,7 +212,7 @@ mlxreg_led_blink_set(struct led_classdev *cled, unsigned long *delay_on,
|
||||
|
||||
static int mlxreg_led_config(struct mlxreg_led_priv_data *priv)
|
||||
{
|
||||
- struct mlxreg_core_led_platform_data *led_pdata = priv->pdata;
|
||||
+ struct mlxreg_core_platform_data *led_pdata = priv->pdata;
|
||||
struct mlxreg_core_data *data = led_pdata->data;
|
||||
struct mlxreg_led_data *led_data;
|
||||
struct led_classdev *led_cdev;
|
||||
@@ -266,7 +266,7 @@ static int mlxreg_led_config(struct mlxreg_led_priv_data *priv)
|
||||
|
||||
static int mlxreg_led_probe(struct platform_device *pdev)
|
||||
{
|
||||
- struct mlxreg_core_led_platform_data *led_pdata;
|
||||
+ struct mlxreg_core_platform_data *led_pdata;
|
||||
struct mlxreg_led_priv_data *priv;
|
||||
|
||||
led_pdata = dev_get_platdata(&pdev->dev);
|
||||
diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig
|
||||
index b197cc1..5c6dc29 100644
|
||||
--- a/drivers/platform/mellanox/Kconfig
|
||||
+++ b/drivers/platform/mellanox/Kconfig
|
||||
@@ -22,4 +22,15 @@ config MLXREG_HOTPLUG
|
||||
This driver handles hot-plug events for the power suppliers, power
|
||||
cables and fans on the wide range Mellanox IB and Ethernet systems.
|
||||
|
||||
+config MLXREG_IO
|
||||
+ tristate "Mellanox platform register driver support"
|
||||
+ depends on REGMAP
|
||||
+ depends on HWMON
|
||||
+ ---help---
|
||||
+ This driver allows access to Mellanox programmable device register
|
||||
+ space trough sysfs interface. The set of registers for sysfs access
|
||||
+ are defined per system type bases and includes the registers related
|
||||
+ to system resets operation, system reset causes monitoring and some
|
||||
+ kinds of mux selection.
|
||||
+
|
||||
endif # MELLANOX_PLATFORM
|
||||
diff --git a/drivers/platform/mellanox/Makefile b/drivers/platform/mellanox/Makefile
|
||||
index f58d089..b9a2692 100644
|
||||
--- a/drivers/platform/mellanox/Makefile
|
||||
+++ b/drivers/platform/mellanox/Makefile
|
||||
@@ -1 +1,2 @@
|
||||
obj-$(CONFIG_MLXREG_HOTPLUG) += mlxreg-hotplug.o
|
||||
+obj-$(CONFIG_MLXREG_IO) += mlxreg-io.o
|
||||
diff --git a/drivers/platform/mellanox/mlxreg-io.c b/drivers/platform/mellanox/mlxreg-io.c
|
||||
new file mode 100644
|
||||
index 0000000..f7434ca
|
||||
--- /dev/null
|
||||
+++ b/drivers/platform/mellanox/mlxreg-io.c
|
||||
@@ -0,0 +1,211 @@
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/hwmon.h>
|
||||
+#include <linux/hwmon-sysfs.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/platform_data/mlxreg.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+
|
||||
+/* Attribute parameters. */
|
||||
+#define MLXREG_IO_ATT_SIZE 10
|
||||
+#define MLXREG_IO_ATT_NUM 48
|
||||
+
|
||||
+/**
|
||||
+ * struct mlxreg_io_priv_data - driver's private data:
|
||||
+ *
|
||||
+ * @pdev: platform device;
|
||||
+ * @pdata: platform data;
|
||||
+ * @hwmon: hwmon device;
|
||||
+ * @mlxreg_io_attr: sysfs attributes array;
|
||||
+ * @mlxreg_io_dev_attr: sysfs sensor device attribute array;
|
||||
+ * @group: sysfs attribute group;
|
||||
+ * @groups: list of sysfs attribute group for hwmon registration;
|
||||
+ */
|
||||
+struct mlxreg_io_priv_data {
|
||||
+ struct platform_device *pdev;
|
||||
+ struct mlxreg_core_platform_data *pdata;
|
||||
+ struct device *hwmon;
|
||||
+ struct attribute *mlxreg_io_attr[MLXREG_IO_ATT_NUM + 1];
|
||||
+ struct sensor_device_attribute mlxreg_io_dev_attr[MLXREG_IO_ATT_NUM];
|
||||
+ struct attribute_group group;
|
||||
+ const struct attribute_group *groups[2];
|
||||
+};
|
||||
+
|
||||
+static ssize_t
|
||||
+mlxreg_io_attr_show(struct device *dev, struct device_attribute *attr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ struct mlxreg_io_priv_data *priv = dev_get_drvdata(dev);
|
||||
+ int index = to_sensor_dev_attr(attr)->index;
|
||||
+ struct mlxreg_core_data *data = priv->pdata->data + index;
|
||||
+ u32 regval = 0;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = regmap_read(priv->pdata->regmap, data->reg, ®val);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+
|
||||
+ if (!data->bit)
|
||||
+ regval = !!(regval & ~data->mask);
|
||||
+
|
||||
+ return sprintf(buf, "%u\n", regval);
|
||||
+
|
||||
+access_error:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static ssize_t
|
||||
+mlxreg_io_attr_store(struct device *dev, struct device_attribute *attr,
|
||||
+ const char *buf, size_t len)
|
||||
+{
|
||||
+ struct mlxreg_io_priv_data *priv = dev_get_drvdata(dev);
|
||||
+ int index = to_sensor_dev_attr(attr)->index;
|
||||
+ struct mlxreg_core_data *data = priv->pdata->data + index;
|
||||
+ u32 val, regval;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = kstrtou32(buf, MLXREG_IO_ATT_SIZE, &val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = regmap_read(priv->pdata->regmap, data->reg, ®val);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+
|
||||
+ regval &= data->mask;
|
||||
+
|
||||
+ val = !!val;
|
||||
+ if (val)
|
||||
+ regval |= ~data->mask;
|
||||
+ else
|
||||
+ regval &= data->mask;
|
||||
+
|
||||
+ ret = regmap_write(priv->pdata->regmap, data->reg, regval);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+
|
||||
+ return len;
|
||||
+
|
||||
+access_error:
|
||||
+ dev_err(&priv->pdev->dev, "Bus access error\n");
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_io_attr_init(struct mlxreg_io_priv_data *priv)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ priv->group.attrs = devm_kzalloc(&priv->pdev->dev,
|
||||
+ priv->pdata->counter *
|
||||
+ sizeof(struct attribute *),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!priv->group.attrs)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ for (i = 0; i < priv->pdata->counter; i++) {
|
||||
+ priv->mlxreg_io_attr[i] =
|
||||
+ &priv->mlxreg_io_dev_attr[i].dev_attr.attr;
|
||||
+
|
||||
+ /* Set attribute name as a label. */
|
||||
+ priv->mlxreg_io_attr[i]->name =
|
||||
+ devm_kasprintf(&priv->pdev->dev, GFP_KERNEL,
|
||||
+ priv->pdata->data[i].label);
|
||||
+
|
||||
+ if (!priv->mlxreg_io_attr[i]->name) {
|
||||
+ dev_err(&priv->pdev->dev, "Memory allocation failed for sysfs attribute %d.\n",
|
||||
+ i + 1);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ priv->mlxreg_io_dev_attr[i].dev_attr.attr.mode =
|
||||
+ priv->pdata->data[i].mode;
|
||||
+ switch (priv->pdata->data[i].mode) {
|
||||
+ case 0200:
|
||||
+ priv->mlxreg_io_dev_attr[i].dev_attr.store =
|
||||
+ mlxreg_io_attr_store;
|
||||
+ break;
|
||||
+
|
||||
+ case 0444:
|
||||
+ priv->mlxreg_io_dev_attr[i].dev_attr.show =
|
||||
+ mlxreg_io_attr_show;
|
||||
+ break;
|
||||
+
|
||||
+ case 0644:
|
||||
+ priv->mlxreg_io_dev_attr[i].dev_attr.show =
|
||||
+ mlxreg_io_attr_show;
|
||||
+ priv->mlxreg_io_dev_attr[i].dev_attr.store =
|
||||
+ mlxreg_io_attr_store;
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ dev_err(&priv->pdev->dev, "Bad access mode %u for attribute %s.\n",
|
||||
+ priv->pdata->data[i].mode,
|
||||
+ priv->mlxreg_io_attr[i]->name);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ priv->mlxreg_io_dev_attr[i].dev_attr.attr.name =
|
||||
+ priv->mlxreg_io_attr[i]->name;
|
||||
+ priv->mlxreg_io_dev_attr[i].index = i;
|
||||
+ sysfs_attr_init(&priv->mlxreg_io_dev_attr[i].dev_attr.attr);
|
||||
+ }
|
||||
+
|
||||
+ priv->group.attrs = priv->mlxreg_io_attr;
|
||||
+ priv->groups[0] = &priv->group;
|
||||
+ priv->groups[1] = NULL;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_io_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mlxreg_io_priv_data *priv;
|
||||
+ int err;
|
||||
+
|
||||
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
+ if (!priv)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ priv->pdata = dev_get_platdata(&pdev->dev);
|
||||
+ if (!priv->pdata) {
|
||||
+ dev_err(&pdev->dev, "Failed to get platform data.\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ priv->pdev = pdev;
|
||||
+
|
||||
+ err = mlxreg_io_attr_init(priv);
|
||||
+ if (err) {
|
||||
+ dev_err(&priv->pdev->dev, "Failed to allocate attributes: %d\n",
|
||||
+ err);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ priv->hwmon = devm_hwmon_device_register_with_groups(&pdev->dev,
|
||||
+ "mlxreg_io", priv, priv->groups);
|
||||
+ if (IS_ERR(priv->hwmon)) {
|
||||
+ dev_err(&pdev->dev, "Failed to register hwmon device %ld\n",
|
||||
+ PTR_ERR(priv->hwmon));
|
||||
+ return PTR_ERR(priv->hwmon);
|
||||
+ }
|
||||
+
|
||||
+ dev_set_drvdata(&pdev->dev, priv);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver mlxreg_io_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "mlxreg-io",
|
||||
+ },
|
||||
+ .probe = mlxreg_io_probe,
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(mlxreg_io_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
|
||||
+MODULE_DESCRIPTION("Mellanox regmap I/O access driver");
|
||||
+MODULE_LICENSE("Dual BSD/GPL");
|
||||
+MODULE_ALIAS("platform:mlxreg-io");
|
||||
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
|
||||
index 49721c2..61cbe35 100644
|
||||
--- a/drivers/platform/x86/mlx-platform.c
|
||||
+++ b/drivers/platform/x86/mlx-platform.c
|
||||
@@ -47,16 +47,31 @@
|
||||
/* LPC bus IO offsets */
|
||||
#define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000
|
||||
#define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500
|
||||
+#define MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFF 0x00
|
||||
+#define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFF 0x01
|
||||
+#define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF 0x1d
|
||||
#define MLXPLAT_CPLD_LPC_REG_LED1_OFF 0x20
|
||||
#define MLXPLAT_CPLD_LPC_REG_LED2_OFF 0x21
|
||||
#define MLXPLAT_CPLD_LPC_REG_LED3_OFF 0x22
|
||||
#define MLXPLAT_CPLD_LPC_REG_LED4_OFF 0x23
|
||||
#define MLXPLAT_CPLD_LPC_REG_LED5_OFF 0x24
|
||||
+#define MLXPLAT_CPLD_LPC_REG_GP1_OFF 0x30
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WP1_OFF 0x31
|
||||
+#define MLXPLAT_CPLD_LPC_REG_GP2_OFF 0x32
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WP2_OFF 0x33
|
||||
#define MLXPLAT_CPLD_LPC_REG_AGGR_OFF 0x3a
|
||||
+#define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFF 0x3b
|
||||
#define MLXPLAT_CPLD_LPC_REG_AGGR_LOW_OFF 0x40
|
||||
+#define MLXPLAT_CPLD_LPC_REG_AGGR_LOW_MASK_OFF 0x41
|
||||
#define MLXPLAT_CPLD_LPC_REG_PSU_OFF 0x58
|
||||
+#define MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFF 0x59
|
||||
+#define MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFF 0x5a
|
||||
#define MLXPLAT_CPLD_LPC_REG_PWR_OFF 0x64
|
||||
+#define MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFF 0x65
|
||||
+#define MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFF 0x66
|
||||
#define MLXPLAT_CPLD_LPC_REG_FAN_OFF 0x88
|
||||
+#define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFF 0x89
|
||||
+#define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFF 0x8a
|
||||
#define MLXPLAT_CPLD_LPC_IO_RANGE 0x100
|
||||
#define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb
|
||||
#define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda
|
||||
@@ -100,12 +115,14 @@
|
||||
* @pdev_mux - array of mux platform devices
|
||||
* @pdev_hotplug - hotplug platform devices
|
||||
* @pdev_led - led platform devices
|
||||
+ * @pdev_io_regs - register access platform devices
|
||||
*/
|
||||
struct mlxplat_priv {
|
||||
struct platform_device *pdev_i2c;
|
||||
struct platform_device *pdev_mux[MLXPLAT_CPLD_LPC_MUX_DEVS];
|
||||
struct platform_device *pdev_hotplug;
|
||||
struct platform_device *pdev_led;
|
||||
+ struct platform_device *pdev_io_regs;
|
||||
};
|
||||
|
||||
/* Regions for LPC I2C controller and LPC base register space */
|
||||
@@ -643,7 +660,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_led_data[] = {
|
||||
},
|
||||
};
|
||||
|
||||
-static struct mlxreg_core_led_platform_data mlxplat_default_led_data = {
|
||||
+static struct mlxreg_core_platform_data mlxplat_default_led_data = {
|
||||
.data = mlxplat_mlxcpld_default_led_data,
|
||||
.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_led_data),
|
||||
};
|
||||
@@ -697,7 +714,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_led_data[] = {
|
||||
},
|
||||
};
|
||||
|
||||
-static struct mlxreg_core_led_platform_data mlxplat_msn21xx_led_data = {
|
||||
+static struct mlxreg_core_platform_data mlxplat_msn21xx_led_data = {
|
||||
.data = mlxplat_mlxcpld_msn21xx_led_data,
|
||||
.counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_led_data),
|
||||
};
|
||||
@@ -786,11 +803,105 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_led_data[] = {
|
||||
},
|
||||
};
|
||||
|
||||
-static struct mlxreg_core_led_platform_data mlxplat_default_ng_led_data = {
|
||||
+static struct mlxreg_core_platform_data mlxplat_default_ng_led_data = {
|
||||
.data = mlxplat_mlxcpld_default_ng_led_data,
|
||||
.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_led_data),
|
||||
};
|
||||
|
||||
+static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
|
||||
+{
|
||||
+ switch (reg) {
|
||||
+ case MLXPLAT_CPLD_LPC_REG_LED1_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_LED2_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_LED3_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_LED4_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_LED5_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_GP1_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WP1_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_GP2_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WP2_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_AGGR_LOW_MASK_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFF:
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
|
||||
+{
|
||||
+ switch (reg) {
|
||||
+ case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_LED1_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_LED2_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_LED3_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_LED4_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_LED5_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_GP1_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WP1_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_GP2_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WP2_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_AGGR_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_AGGR_LOW_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_AGGR_LOW_MASK_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_PSU_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_PWR_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_FAN_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFF:
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
|
||||
+{
|
||||
+ switch (reg) {
|
||||
+ case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_LED1_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_LED2_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_LED3_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_LED4_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_LED5_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_GP1_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_GP2_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_AGGR_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_AGGR_LOW_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_AGGR_LOW_MASK_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_PSU_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_PWR_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_FAN_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFF:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFF:
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static const struct reg_default mlxplat_mlxcpld_regmap_default[] = {
|
||||
+ { MLXPLAT_CPLD_LPC_REG_WP1_OFF, 0x00 },
|
||||
+ { MLXPLAT_CPLD_LPC_REG_WP2_OFF, 0x00 },
|
||||
+};
|
||||
+
|
||||
static int
|
||||
mlxplat_mlxcpld_reg_read(void *context, unsigned int reg, unsigned int *val)
|
||||
{
|
||||
@@ -809,6 +920,12 @@ const struct regmap_config mlxplat_mlxcpld_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 255,
|
||||
+ .cache_type = REGCACHE_FLAT,
|
||||
+ .writeable_reg = mlxplat_mlxcpld_writeable_reg,
|
||||
+ .readable_reg = mlxplat_mlxcpld_readable_reg,
|
||||
+ .volatile_reg = mlxplat_mlxcpld_volatile_reg,
|
||||
+ .reg_defaults = mlxplat_mlxcpld_regmap_default,
|
||||
+ .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_default),
|
||||
.reg_read = mlxplat_mlxcpld_reg_read,
|
||||
.reg_write = mlxplat_mlxcpld_reg_write,
|
||||
};
|
||||
@@ -817,9 +934,38 @@ static struct resource mlxplat_mlxcpld_resources[] = {
|
||||
[0] = DEFINE_RES_IRQ_NAMED(17, "mlxreg-hotplug"),
|
||||
};
|
||||
|
||||
-struct platform_device *mlxplat_dev;
|
||||
-struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug;
|
||||
-struct mlxreg_core_led_platform_data *mlxplat_led;
|
||||
+static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = {
|
||||
+ { "cpld1_version", MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFF, 0x00,
|
||||
+ GENMASK(7, 0), 0444 },
|
||||
+ { "cpld2_version", MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFF, 0x00,
|
||||
+ GENMASK(7, 0), 0444 },
|
||||
+ { "cause_long_pb", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF,
|
||||
+ GENMASK(7, 0) & ~BIT(0), 0x00, 0444 },
|
||||
+ { "cause_short_pb", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF,
|
||||
+ GENMASK(7, 0) & ~BIT(1), 0x00, 0444 },
|
||||
+ { "cause_pwr_aux", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF,
|
||||
+ GENMASK(7, 0) & ~BIT(2), 0x00, 0444 },
|
||||
+ { "cause_pwr_fail", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF,
|
||||
+ GENMASK(7, 0) & ~BIT(3), 0x00, 0444 },
|
||||
+ { "psu1_on", MLXPLAT_CPLD_LPC_REG_GP1_OFF, GENMASK(7, 0) & ~BIT(0),
|
||||
+ 0x00, 0200 },
|
||||
+ { "psu2_on", MLXPLAT_CPLD_LPC_REG_GP1_OFF, GENMASK(7, 0) & ~BIT(1),
|
||||
+ 0x00, 0200 },
|
||||
+ { "pwr_cycle", MLXPLAT_CPLD_LPC_REG_GP1_OFF, GENMASK(7, 0) & ~BIT(2),
|
||||
+ 0x00, 0200 },
|
||||
+ { "select_iio", MLXPLAT_CPLD_LPC_REG_GP2_OFF, GENMASK(7, 0) & ~BIT(6),
|
||||
+ 0x00, 0644 },
|
||||
+};
|
||||
+
|
||||
+static struct mlxreg_core_platform_data mlxplat_default_regs_io_data = {
|
||||
+ .data = mlxplat_mlxcpld_default_regs_io_data,
|
||||
+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_regs_io_data),
|
||||
+};
|
||||
+
|
||||
+static struct platform_device *mlxplat_dev;
|
||||
+static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug;
|
||||
+static struct mlxreg_core_platform_data *mlxplat_led;
|
||||
+static struct mlxreg_core_platform_data *mlxplat_regs_io;
|
||||
|
||||
static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
|
||||
{
|
||||
@@ -832,6 +978,7 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
|
||||
}
|
||||
mlxplat_hotplug = &mlxplat_mlxcpld_default_data;
|
||||
mlxplat_led = &mlxplat_default_led_data;
|
||||
+ mlxplat_regs_io = &mlxplat_default_regs_io_data;
|
||||
|
||||
return 1;
|
||||
};
|
||||
@@ -847,6 +994,7 @@ static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
|
||||
}
|
||||
mlxplat_hotplug = &mlxplat_mlxcpld_msn21xx_data;
|
||||
mlxplat_led = &mlxplat_msn21xx_led_data;
|
||||
+ mlxplat_regs_io = &mlxplat_default_regs_io_data;
|
||||
|
||||
return 1;
|
||||
};
|
||||
@@ -862,6 +1010,7 @@ static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi)
|
||||
}
|
||||
mlxplat_hotplug = &mlxplat_mlxcpld_msn274x_data;
|
||||
mlxplat_led = &mlxplat_default_led_data;
|
||||
+ mlxplat_regs_io = &mlxplat_default_regs_io_data;
|
||||
|
||||
return 1;
|
||||
};
|
||||
@@ -877,6 +1026,7 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
|
||||
}
|
||||
mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data;
|
||||
mlxplat_led = &mlxplat_default_ng_led_data;
|
||||
+ mlxplat_regs_io = &mlxplat_default_regs_io_data;
|
||||
|
||||
return 1;
|
||||
};
|
||||
@@ -892,6 +1042,7 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi)
|
||||
}
|
||||
mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data;
|
||||
mlxplat_led = &mlxplat_msn21xx_led_data;
|
||||
+ mlxplat_regs_io = &mlxplat_default_regs_io_data;
|
||||
|
||||
return 1;
|
||||
};
|
||||
@@ -974,7 +1125,7 @@ static int __init mlxplat_init(void)
|
||||
{
|
||||
struct mlxplat_priv *priv;
|
||||
void __iomem *base;
|
||||
- int i, err = 0;
|
||||
+ int i, j, err = 0;
|
||||
|
||||
if (!dmi_check_system(mlxplat_dmi_table))
|
||||
return -ENODEV;
|
||||
@@ -1023,6 +1174,15 @@ static int __init mlxplat_init(void)
|
||||
if (IS_ERR(mlxplat_hotplug->regmap))
|
||||
goto fail_platform_mux_register;
|
||||
|
||||
+ /* Set default registers. */
|
||||
+ for (j = 0; j < mlxplat_mlxcpld_regmap_config.num_reg_defaults; j++) {
|
||||
+ err = regmap_write(mlxplat_hotplug->regmap,
|
||||
+ mlxplat_mlxcpld_regmap_default[j].reg,
|
||||
+ mlxplat_mlxcpld_regmap_default[j].def);
|
||||
+ if (err)
|
||||
+ goto fail_platform_mux_register;
|
||||
+ }
|
||||
+
|
||||
priv->pdev_hotplug = platform_device_register_resndata(
|
||||
&mlxplat_dev->dev, "mlxreg-hotplug",
|
||||
PLATFORM_DEVID_NONE,
|
||||
@@ -1044,8 +1204,26 @@ static int __init mlxplat_init(void)
|
||||
goto fail_platform_hotplug_register;
|
||||
}
|
||||
|
||||
+ mlxplat_regs_io->regmap = mlxplat_hotplug->regmap;
|
||||
+ priv->pdev_io_regs = platform_device_register_resndata(
|
||||
+ &mlxplat_dev->dev, "mlxreg-io",
|
||||
+ PLATFORM_DEVID_NONE, NULL, 0,
|
||||
+ mlxplat_regs_io, sizeof(*mlxplat_regs_io));
|
||||
+ if (IS_ERR(priv->pdev_io_regs)) {
|
||||
+ err = PTR_ERR(priv->pdev_io_regs);
|
||||
+ goto fail_platform_led_register;
|
||||
+ }
|
||||
+
|
||||
+ /* Sync registers with hardware. */
|
||||
+ regcache_mark_dirty(mlxplat_hotplug->regmap);
|
||||
+ err = regcache_sync(mlxplat_hotplug->regmap);
|
||||
+ if (err)
|
||||
+ goto fail_platform_led_register;
|
||||
+
|
||||
return 0;
|
||||
|
||||
+fail_platform_led_register:
|
||||
+ platform_device_unregister(priv->pdev_led);
|
||||
fail_platform_hotplug_register:
|
||||
platform_device_unregister(priv->pdev_hotplug);
|
||||
fail_platform_mux_register:
|
||||
@@ -1064,6 +1242,7 @@ static void __exit mlxplat_exit(void)
|
||||
struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
|
||||
int i;
|
||||
|
||||
+ platform_device_unregister(priv->pdev_io_regs);
|
||||
platform_device_unregister(priv->pdev_led);
|
||||
platform_device_unregister(priv->pdev_hotplug);
|
||||
|
||||
diff --git a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h
|
||||
index dd471c5..c25623b 100644
|
||||
--- a/include/linux/platform_data/mlxreg.h
|
||||
+++ b/include/linux/platform_data/mlxreg.h
|
||||
@@ -61,6 +61,7 @@ struct mlxreg_hotplug_device {
|
||||
* @label: attribute register offset;
|
||||
* @reg: attribute register;
|
||||
* @mask: attribute access mask;
|
||||
+ * @mode: access mode;
|
||||
* @bit: attribute effective bit;
|
||||
* @np - pointer to node platform associated with attribute;
|
||||
* @hpdev - hotplug device data;
|
||||
@@ -72,6 +73,7 @@ struct mlxreg_core_data {
|
||||
u32 reg;
|
||||
u32 mask;
|
||||
u32 bit;
|
||||
+ umode_t mode;
|
||||
struct device_node *np;
|
||||
struct mlxreg_hotplug_device hpdev;
|
||||
u8 health_cntr;
|
||||
@@ -104,13 +106,13 @@ struct mlxreg_core_item {
|
||||
};
|
||||
|
||||
/**
|
||||
- * struct mlxreg_core_led_platform_data - led platform data:
|
||||
+ * struct mlxreg_core_platform_data - platform data:
|
||||
*
|
||||
* @led_data: led private data;
|
||||
* @regmap: register map of parent device;
|
||||
* @counter: number of led instances;
|
||||
*/
|
||||
-struct mlxreg_core_led_platform_data {
|
||||
+struct mlxreg_core_platform_data {
|
||||
struct mlxreg_core_data *data;
|
||||
void *regmap;
|
||||
int counter;
|
||||
--
|
||||
2.1.4
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
From c794f8ffa6521c47bfbff813e7f713561d7da7bd Mon Sep 17 00:00:00 2001
|
||||
From: Vadim Pasternak <vadimp@mellanox.com>
|
||||
Date: Mon, 11 Dec 2017 19:02:19 +0000
|
||||
Subject: [v4.9 backport 09/29] platform/mellanox: mlxreg-hotplug driver add
|
||||
check for low aggregation register mask
|
||||
|
||||
It adds verification for low aggregation register mask offset. Only
|
||||
non-zero offset is considered as valid.
|
||||
|
||||
Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
|
||||
---
|
||||
drivers/platform/mellanox/mlxreg-hotplug.c | 18 +++++++++++-------
|
||||
1 file changed, 11 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c
|
||||
index 94fdb6b..ba9241e 100644
|
||||
--- a/drivers/platform/mellanox/mlxreg-hotplug.c
|
||||
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
|
||||
@@ -550,10 +550,13 @@ static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv)
|
||||
goto access_error;
|
||||
|
||||
/* Keep low aggregation initial status as zero and unmask events. */
|
||||
- ret = regmap_write(priv->regmap, pdata->cell_low +
|
||||
- MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask_low);
|
||||
- if (ret)
|
||||
- goto access_error;
|
||||
+ if (pdata->cell_low) {
|
||||
+ ret = regmap_write(priv->regmap, pdata->cell_low +
|
||||
+ MLXREG_HOTPLUG_AGGR_MASK_OFF,
|
||||
+ pdata->mask_low);
|
||||
+ if (ret)
|
||||
+ goto access_error;
|
||||
+ }
|
||||
|
||||
/* Invoke work handler for initializing hot plug devices setting. */
|
||||
mlxreg_hotplug_work_handler(&priv->dwork_irq.work);
|
||||
@@ -582,9 +585,10 @@ static void mlxreg_hotplug_unset_irq(struct mlxreg_hotplug_priv_data *priv)
|
||||
disable_irq(priv->irq);
|
||||
cancel_delayed_work_sync(&priv->dwork_irq);
|
||||
|
||||
- /* Mask low aggregation event. */
|
||||
- regmap_write(priv->regmap, pdata->cell_low +
|
||||
- MLXREG_HOTPLUG_AGGR_MASK_OFF, 0);
|
||||
+ /* Mask low aggregation event, if defined. */
|
||||
+ if (pdata->cell_low)
|
||||
+ regmap_write(priv->regmap, pdata->cell_low +
|
||||
+ MLXREG_HOTPLUG_AGGR_MASK_OFF, 0);
|
||||
|
||||
/* Mask aggregation event. */
|
||||
regmap_write(priv->regmap, pdata->cell + MLXREG_HOTPLUG_AGGR_MASK_OFF,
|
||||
--
|
||||
2.1.4
|
||||
|
||||
@@ -0,0 +1,472 @@
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/qsfp_sysfs.c b/drivers/net/ethernet/mellanox/mlxsw/qsfp_sysfs.c
|
||||
index 3bc6cf8..07cc7ea 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/qsfp_sysfs.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/qsfp_sysfs.c
|
||||
@@ -33,6 +33,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
+#include <linux/dmi.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sysfs.h>
|
||||
@@ -49,7 +50,8 @@
|
||||
#define MLXSW_QSFP_MAX_NUM 64
|
||||
#define MLXSW_QSFP_MIN_REQ_LEN 4
|
||||
#define MLXSW_QSFP_STATUS_VALID_TIME (120 * HZ)
|
||||
-#define MLXSW_QSFP_MAX_CPLD_NUM 1
|
||||
+#define MLXSW_QSFP_MAX_CPLD_NUM 3
|
||||
+#define MLXSW_QSFP_MIN_CPLD_NUM 1
|
||||
|
||||
static const u8 mlxsw_qsfp_page_number[] = { 0xa0, 0x00, 0x01, 0x02, 0x03 };
|
||||
static const u16 mlxsw_qsfp_page_shift[] = { 0x00, 0x80, 0x80, 0x80, 0x80 };
|
||||
@@ -85,6 +87,8 @@ struct mlxsw_qsfp {
|
||||
struct device_attribute *cpld_dev_attrs;
|
||||
};
|
||||
|
||||
+static int mlxsw_qsfp_cpld_num = MLXSW_QSFP_MIN_CPLD_NUM;
|
||||
+
|
||||
static int
|
||||
mlxsw_qsfp_query_module_eeprom(struct mlxsw_qsfp *mlxsw_qsfp, u8 index,
|
||||
loff_t off, size_t count, int page, char *buf)
|
||||
@@ -210,11 +214,11 @@ mlxsw_qsfp_cpld_show(struct device *dev, struct device_attribute *attr,
|
||||
u32 version, i;
|
||||
int err;
|
||||
|
||||
- for (i = 0; i < MLXSW_QSFP_MAX_CPLD_NUM; i++) {
|
||||
+ for (i = 0; i < mlxsw_qsfp_cpld_num; i++) {
|
||||
if ((mlxsw_qsfp->cpld_dev_attrs + i) == attr)
|
||||
break;
|
||||
}
|
||||
- if (i == MLXSW_QSFP_MAX_CPLD_NUM)
|
||||
+ if (i == mlxsw_qsfp_cpld_num)
|
||||
return -EINVAL;
|
||||
|
||||
mlxsw_reg_msci_pack(msci_pl, i);
|
||||
@@ -227,6 +231,32 @@ mlxsw_qsfp_cpld_show(struct device *dev, struct device_attribute *attr,
|
||||
return sprintf(buf, "%u\n", version);
|
||||
}
|
||||
|
||||
+static int __init mlxsw_qsfp_dmi_set_cpld_num(const struct dmi_system_id *dmi)
|
||||
+{
|
||||
+ mlxsw_qsfp_cpld_num = MLXSW_QSFP_MAX_CPLD_NUM;
|
||||
+
|
||||
+ return 1;
|
||||
+};
|
||||
+
|
||||
+static struct dmi_system_id mlxsw_qsfp_dmi_table[] __initdata = {
|
||||
+ {
|
||||
+ .callback = mlxsw_qsfp_dmi_set_cpld_num,
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "MSN24"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .callback = mlxsw_qsfp_dmi_set_cpld_num,
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "MSN27"),
|
||||
+ },
|
||||
+ },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(dmi, mlxsw_qsfp_dmi_table);
|
||||
+
|
||||
int mlxsw_qsfp_init(struct mlxsw_core *mlxsw_core,
|
||||
const struct mlxsw_bus_info *mlxsw_bus_info,
|
||||
struct mlxsw_qsfp **p_qsfp)
|
||||
@@ -242,6 +272,8 @@ int mlxsw_qsfp_init(struct mlxsw_core *mlxsw_core,
|
||||
if (!strcmp(mlxsw_bus_info->device_kind, "i2c"))
|
||||
return 0;
|
||||
|
||||
+ dmi_check_system(mlxsw_qsfp_dmi_table);
|
||||
+
|
||||
mlxsw_qsfp = devm_kzalloc(mlxsw_bus_info->dev, sizeof(*mlxsw_qsfp),
|
||||
GFP_KERNEL);
|
||||
if (!mlxsw_qsfp)
|
||||
@@ -285,7 +317,7 @@ int mlxsw_qsfp_init(struct mlxsw_core *mlxsw_core,
|
||||
return -ENOMEM;
|
||||
|
||||
mlxsw_qsfp->cpld_dev_attrs = devm_kzalloc(mlxsw_bus_info->dev,
|
||||
- MLXSW_QSFP_MAX_CPLD_NUM *
|
||||
+ mlxsw_qsfp_cpld_num *
|
||||
sizeof(*mlxsw_qsfp->cpld_dev_attrs),
|
||||
GFP_KERNEL);
|
||||
if (!mlxsw_qsfp->cpld_dev_attrs)
|
||||
@@ -323,7 +355,7 @@ int mlxsw_qsfp_init(struct mlxsw_core *mlxsw_core,
|
||||
}
|
||||
|
||||
cpld_dev_attr = mlxsw_qsfp->cpld_dev_attrs;
|
||||
- for (i = 0; i < MLXSW_QSFP_MAX_CPLD_NUM; i++, cpld_dev_attr++) {
|
||||
+ for (i = 0; i < mlxsw_qsfp_cpld_num; i++, cpld_dev_attr++) {
|
||||
cpld_dev_attr->show = mlxsw_qsfp_cpld_show;
|
||||
cpld_dev_attr->attr.mode = 0444;
|
||||
cpld_dev_attr->attr.name = devm_kasprintf(mlxsw_bus_info->dev,
|
||||
diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c
|
||||
index ba9241e..5c13591 100644
|
||||
--- a/drivers/platform/mellanox/mlxreg-hotplug.c
|
||||
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
|
||||
@@ -58,6 +58,7 @@
|
||||
#define MLXREG_HOTPLUG_PROP_STATUS "status"
|
||||
|
||||
#define MLXREG_HOTPLUG_ATTRS_MAX 24
|
||||
+#define MLXREG_HOTPLUG_NOT_ASSERT 3
|
||||
|
||||
/**
|
||||
* struct mlxreg_hotplug_priv_data - platform private data:
|
||||
@@ -74,6 +75,7 @@
|
||||
* @cell: location of top aggregation interrupt register;
|
||||
* @mask: top aggregation interrupt common mask;
|
||||
* @aggr_cache: last value of aggregation register status;
|
||||
+ * @not_asserted: number of entries in workqueue with no signal assertion;
|
||||
*/
|
||||
struct mlxreg_hotplug_priv_data {
|
||||
int irq;
|
||||
@@ -94,6 +96,7 @@ struct mlxreg_hotplug_priv_data {
|
||||
u32 mask;
|
||||
u32 aggr_cache;
|
||||
bool after_probe;
|
||||
+ u8 not_asserted;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_OF_DYNAMIC)
|
||||
@@ -441,7 +444,7 @@ mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv,
|
||||
* *---*
|
||||
*
|
||||
* In case some system changed are detected: FAN in/out, PSU in/out, power
|
||||
- * cable attached/detached, ASIC helath good/bad, relevant device is created
|
||||
+ * cable attached/detached, ASIC health good/bad, relevant device is created
|
||||
* or destroyed.
|
||||
*/
|
||||
static void mlxreg_hotplug_work_handler(struct work_struct *work)
|
||||
@@ -472,6 +475,13 @@ static void mlxreg_hotplug_work_handler(struct work_struct *work)
|
||||
aggr_asserted = priv->aggr_cache ^ regval;
|
||||
priv->aggr_cache = regval;
|
||||
|
||||
+ if (priv->not_asserted == MLXREG_HOTPLUG_NOT_ASSERT) {
|
||||
+ priv->not_asserted = 0;
|
||||
+ aggr_asserted = pdata->mask;
|
||||
+ }
|
||||
+ if (!aggr_asserted)
|
||||
+ goto unmask_event;
|
||||
+
|
||||
/* Handle topology and health configuration changes. */
|
||||
for (i = 0; i < pdata->counter; i++, item++) {
|
||||
if (aggr_asserted & item->aggr_mask) {
|
||||
@@ -503,6 +513,8 @@ static void mlxreg_hotplug_work_handler(struct work_struct *work)
|
||||
return;
|
||||
}
|
||||
|
||||
+unmask_event:
|
||||
+ priv->not_asserted++;
|
||||
/* Unmask aggregation event (no need acknowledge). */
|
||||
ret = regmap_write(priv->regmap, pdata->cell +
|
||||
MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask);
|
||||
@@ -626,6 +638,7 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct mlxreg_core_hotplug_platform_data *pdata;
|
||||
struct mlxreg_hotplug_priv_data *priv;
|
||||
+ struct i2c_adapter *deferred_adap;
|
||||
int err;
|
||||
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
@@ -634,6 +647,12 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ /* Defer probing if the necessary adapter is not configured yet. */
|
||||
+ deferred_adap = i2c_get_adapter(pdata->deferred_nr);
|
||||
+ if (!deferred_adap)
|
||||
+ return -EPROBE_DEFER;
|
||||
+ i2c_put_adapter(deferred_adap);
|
||||
+
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
|
||||
index 61cbe35..e03f03f 100644
|
||||
--- a/drivers/platform/x86/mlx-platform.c
|
||||
+++ b/drivers/platform/x86/mlx-platform.c
|
||||
@@ -99,6 +99,15 @@
|
||||
#define MLXPLAT_CPLD_LED_LO_NIBBLE_MASK GENMASK(7, 4)
|
||||
#define MLXPLAT_CPLD_LED_HI_NIBBLE_MASK GENMASK(3, 0)
|
||||
|
||||
+/* Default I2C parent bus number */
|
||||
+#define MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR 1
|
||||
+
|
||||
+/* Maximum number of possible physical buses equipped on system */
|
||||
+#define MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM 16
|
||||
+
|
||||
+/* Number of channels in group */
|
||||
+#define MLXPLAT_CPLD_GRP_CHNL_NUM 8
|
||||
+
|
||||
/* Start channel numbers */
|
||||
#define MLXPLAT_CPLD_CH1 2
|
||||
#define MLXPLAT_CPLD_CH2 10
|
||||
@@ -106,7 +115,8 @@
|
||||
/* Number of LPC attached MUX platform devices */
|
||||
#define MLXPLAT_CPLD_LPC_MUX_DEVS 2
|
||||
|
||||
-/* PSU adapter numbers */
|
||||
+/* Hotplug devices adapter numbers */
|
||||
+#define MLXPLAT_CPLD_NR_NONE -1
|
||||
#define MLXPLAT_CPLD_PSU_DEFAULT_NR 10
|
||||
#define MLXPLAT_CPLD_PSU_MSNXXXX_NR 4
|
||||
|
||||
@@ -137,7 +147,7 @@ static const struct resource mlxplat_lpc_resources[] = {
|
||||
};
|
||||
|
||||
/* Platform default channels */
|
||||
-static const int mlxplat_default_channels[][8] = {
|
||||
+static const int mlxplat_default_channels[][MLXPLAT_CPLD_GRP_CHNL_NUM] = {
|
||||
{
|
||||
MLXPLAT_CPLD_CH1, MLXPLAT_CPLD_CH1 + 1, MLXPLAT_CPLD_CH1 + 2,
|
||||
MLXPLAT_CPLD_CH1 + 3, MLXPLAT_CPLD_CH1 + 4, MLXPLAT_CPLD_CH1 +
|
||||
@@ -472,14 +482,14 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_fan_items_data[] = {
|
||||
{
|
||||
.label = "fan5",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF,
|
||||
- .mask = BIT(3),
|
||||
+ .mask = BIT(4),
|
||||
.hpdev.brdinfo = &mlxplat_mlxcpld_ng_fan,
|
||||
.hpdev.nr = 15,
|
||||
},
|
||||
{
|
||||
.label = "fan6",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF,
|
||||
- .mask = BIT(3),
|
||||
+ .mask = BIT(5),
|
||||
.hpdev.brdinfo = &mlxplat_mlxcpld_ng_fan,
|
||||
.hpdev.nr = 16,
|
||||
},
|
||||
@@ -943,10 +953,18 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = {
|
||||
GENMASK(7, 0) & ~BIT(0), 0x00, 0444 },
|
||||
{ "cause_short_pb", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF,
|
||||
GENMASK(7, 0) & ~BIT(1), 0x00, 0444 },
|
||||
- { "cause_pwr_aux", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF,
|
||||
+ { "cause_aux_pwr_or_refresh", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF,
|
||||
GENMASK(7, 0) & ~BIT(2), 0x00, 0444 },
|
||||
- { "cause_pwr_fail", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF,
|
||||
+ { "cause_main_pwr_fail", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF,
|
||||
GENMASK(7, 0) & ~BIT(3), 0x00, 0444 },
|
||||
+ { "cause_sw_reset", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF,
|
||||
+ GENMASK(7, 0) & ~BIT(4), 0x00, 0444 },
|
||||
+ { "cause_fw_reset", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF,
|
||||
+ GENMASK(7, 0) & ~BIT(5), 0x00, 0444 },
|
||||
+ { "cause_hotswap_or_wd", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF,
|
||||
+ GENMASK(7, 0) & ~BIT(6), 0x00, 0444 },
|
||||
+ { "cause_asic_thermal", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF,
|
||||
+ GENMASK(7, 0) & ~BIT(7), 0x00, 0444 },
|
||||
{ "psu1_on", MLXPLAT_CPLD_LPC_REG_GP1_OFF, GENMASK(7, 0) & ~BIT(0),
|
||||
0x00, 0200 },
|
||||
{ "psu2_on", MLXPLAT_CPLD_LPC_REG_GP1_OFF, GENMASK(7, 0) & ~BIT(1),
|
||||
@@ -977,6 +995,8 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
|
||||
ARRAY_SIZE(mlxplat_default_channels[i]);
|
||||
}
|
||||
mlxplat_hotplug = &mlxplat_mlxcpld_default_data;
|
||||
+ mlxplat_hotplug->deferred_nr =
|
||||
+ mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
|
||||
mlxplat_led = &mlxplat_default_led_data;
|
||||
mlxplat_regs_io = &mlxplat_default_regs_io_data;
|
||||
|
||||
@@ -993,6 +1013,8 @@ static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
|
||||
ARRAY_SIZE(mlxplat_msn21xx_channels);
|
||||
}
|
||||
mlxplat_hotplug = &mlxplat_mlxcpld_msn21xx_data;
|
||||
+ mlxplat_hotplug->deferred_nr =
|
||||
+ mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
|
||||
mlxplat_led = &mlxplat_msn21xx_led_data;
|
||||
mlxplat_regs_io = &mlxplat_default_regs_io_data;
|
||||
|
||||
@@ -1009,6 +1031,8 @@ static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi)
|
||||
ARRAY_SIZE(mlxplat_msn21xx_channels);
|
||||
}
|
||||
mlxplat_hotplug = &mlxplat_mlxcpld_msn274x_data;
|
||||
+ mlxplat_hotplug->deferred_nr =
|
||||
+ mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
|
||||
mlxplat_led = &mlxplat_default_led_data;
|
||||
mlxplat_regs_io = &mlxplat_default_regs_io_data;
|
||||
|
||||
@@ -1025,6 +1049,8 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
|
||||
ARRAY_SIZE(mlxplat_msn21xx_channels);
|
||||
}
|
||||
mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data;
|
||||
+ mlxplat_hotplug->deferred_nr =
|
||||
+ mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
|
||||
mlxplat_led = &mlxplat_default_ng_led_data;
|
||||
mlxplat_regs_io = &mlxplat_default_regs_io_data;
|
||||
|
||||
@@ -1041,13 +1067,15 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi)
|
||||
ARRAY_SIZE(mlxplat_msn21xx_channels);
|
||||
}
|
||||
mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data;
|
||||
+ mlxplat_hotplug->deferred_nr =
|
||||
+ mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
|
||||
mlxplat_led = &mlxplat_msn21xx_led_data;
|
||||
mlxplat_regs_io = &mlxplat_default_regs_io_data;
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
-static struct dmi_system_id mlxplat_dmi_table[] __initdata = {
|
||||
+static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
|
||||
{
|
||||
.callback = mlxplat_dmi_msn274x_matched,
|
||||
.matches = {
|
||||
@@ -1118,14 +1146,84 @@ static struct dmi_system_id mlxplat_dmi_table[] __initdata = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "SN34"),
|
||||
},
|
||||
},
|
||||
+ {
|
||||
+ .callback = mlxplat_dmi_default_matched,
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BOARD_NAME, "VMOD0001"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .callback = mlxplat_dmi_msn21xx_matched,
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BOARD_NAME, "VMOD0002"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .callback = mlxplat_dmi_msn274x_matched,
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BOARD_NAME, "VMOD0003"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .callback = mlxplat_dmi_msn201x_matched,
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BOARD_NAME, "VMOD0004"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .callback = mlxplat_dmi_qmb7xx_matched,
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BOARD_NAME, "VMOD0005"),
|
||||
+ },
|
||||
+ },
|
||||
{ }
|
||||
};
|
||||
|
||||
+MODULE_DEVICE_TABLE(dmi, mlxplat_dmi_table);
|
||||
+
|
||||
+static int mlxplat_mlxcpld_verify_bus_topology(int *nr)
|
||||
+{
|
||||
+ struct i2c_adapter *search_adap;
|
||||
+ int shift, i;
|
||||
+
|
||||
+ /* Scan adapters from expected id to verify it is free. */
|
||||
+ *nr = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR;
|
||||
+ for (i = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR; i <
|
||||
+ MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; i++) {
|
||||
+ search_adap = i2c_get_adapter(i);
|
||||
+ if (search_adap) {
|
||||
+ i2c_put_adapter(search_adap);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* Return if expected parent adapter is free. */
|
||||
+ if (i == MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR)
|
||||
+ return 0;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* Return with error if free id for adapter is not found. */
|
||||
+ if (i == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ /* Shift adapter ids, since expected parent adapter is not free. */
|
||||
+ *nr = i;
|
||||
+ for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
|
||||
+ shift = *nr - mlxplat_mux_data[i].parent;
|
||||
+ mlxplat_mux_data[i].parent = *nr;
|
||||
+ mlxplat_mux_data[i].base_nr += shift;
|
||||
+ if (shift > 0)
|
||||
+ mlxplat_hotplug->shift_nr = shift;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int __init mlxplat_init(void)
|
||||
{
|
||||
struct mlxplat_priv *priv;
|
||||
void __iomem *base;
|
||||
- int i, j, err = 0;
|
||||
+ int i, j, nr, err = 0;
|
||||
|
||||
if (!dmi_check_system(mlxplat_dmi_table))
|
||||
return -ENODEV;
|
||||
@@ -1145,7 +1243,12 @@ static int __init mlxplat_init(void)
|
||||
}
|
||||
platform_set_drvdata(mlxplat_dev, priv);
|
||||
|
||||
- priv->pdev_i2c = platform_device_register_simple("i2c_mlxcpld", -1,
|
||||
+ err = mlxplat_mlxcpld_verify_bus_topology(&nr);
|
||||
+ if (nr < 0)
|
||||
+ goto fail_alloc;
|
||||
+
|
||||
+ nr = (nr == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM) ? -1 : nr;
|
||||
+ priv->pdev_i2c = platform_device_register_simple("i2c_mlxcpld", nr,
|
||||
NULL, 0);
|
||||
if (IS_ERR(priv->pdev_i2c)) {
|
||||
err = PTR_ERR(priv->pdev_i2c);
|
||||
@@ -1166,13 +1269,17 @@ static int __init mlxplat_init(void)
|
||||
|
||||
base = devm_ioport_map(&mlxplat_dev->dev,
|
||||
mlxplat_lpc_resources[1].start, 1);
|
||||
- if (IS_ERR(base))
|
||||
+ if (!base) {
|
||||
+ err = -ENOMEM;
|
||||
goto fail_platform_mux_register;
|
||||
+ }
|
||||
|
||||
mlxplat_hotplug->regmap = devm_regmap_init(&mlxplat_dev->dev, NULL,
|
||||
base, &mlxplat_mlxcpld_regmap_config);
|
||||
- if (IS_ERR(mlxplat_hotplug->regmap))
|
||||
+ if (IS_ERR(mlxplat_hotplug->regmap)) {
|
||||
+ err = PTR_ERR(mlxplat_hotplug->regmap);
|
||||
goto fail_platform_mux_register;
|
||||
+ }
|
||||
|
||||
/* Set default registers. */
|
||||
for (j = 0; j < mlxplat_mlxcpld_regmap_config.num_reg_defaults; j++) {
|
||||
@@ -1257,13 +1364,3 @@ module_exit(mlxplat_exit);
|
||||
MODULE_AUTHOR("Vadim Pasternak (vadimp@mellanox.com)");
|
||||
MODULE_DESCRIPTION("Mellanox platform driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
-MODULE_ALIAS("dmi:*:*Mellanox*:MSN24*:");
|
||||
-MODULE_ALIAS("dmi:*:*Mellanox*:MSN27*:");
|
||||
-MODULE_ALIAS("dmi:*:*Mellanox*:MSB*:");
|
||||
-MODULE_ALIAS("dmi:*:*Mellanox*:MSX*:");
|
||||
-MODULE_ALIAS("dmi:*:*Mellanox*:MSN21*:");
|
||||
-MODULE_ALIAS("dmi:*:*Mellanox*MSN274*:");
|
||||
-MODULE_ALIAS("dmi:*:*Mellanox*MSN201*:");
|
||||
-MODULE_ALIAS("dmi:*:*Mellanox*QMB7*:");
|
||||
-MODULE_ALIAS("dmi:*:*Mellanox*SN37*:");
|
||||
-MODULE_ALIAS("dmi:*:*Mellanox*QM34*:");
|
||||
diff --git a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h
|
||||
index c25623b..b77c7a5 100644
|
||||
--- a/include/linux/platform_data/mlxreg.h
|
||||
+++ b/include/linux/platform_data/mlxreg.h
|
||||
@@ -129,6 +129,8 @@ struct mlxreg_core_platform_data {
|
||||
* @mask: top aggregation interrupt common mask;
|
||||
* @cell_low: location of low aggregation interrupt register;
|
||||
* @mask_low: low aggregation interrupt common mask;
|
||||
+ * @deferred_nr: I2C adapter number must be exist prior probing execution;
|
||||
+ * @shift_nr: I2C adapter numbers must be incremented by this value;
|
||||
*/
|
||||
struct mlxreg_core_hotplug_platform_data {
|
||||
struct mlxreg_core_item *items;
|
||||
@@ -139,6 +141,8 @@ struct mlxreg_core_hotplug_platform_data {
|
||||
u32 mask;
|
||||
u32 cell_low;
|
||||
u32 mask_low;
|
||||
+ int deferred_nr;
|
||||
+ int shift_nr;
|
||||
};
|
||||
|
||||
#endif /* __LINUX_PLATFORM_DATA_MLXREG_H */
|
||||
@@ -0,0 +1,199 @@
|
||||
From 23c8535af1dd9dcaecb5aaf4097129bfb7e24570 Mon Sep 17 00:00:00 2001
|
||||
From: Vadim Pasternak <vadimp@mellanox.com>
|
||||
Date: Thu, 15 Mar 2018 18:38:18 +0000
|
||||
Subject: [backport 4.9 7/7] i2c: busses: Add capabilities to i2c-mlxcpld
|
||||
|
||||
It adds support for extended length of read and write transactions.
|
||||
New CPLD logic allows double size of the read and write transactions
|
||||
length. This feature is verified through capability register, which is
|
||||
renamed from unclear LPF_REG to CPBLTY_REG. Two bits 5 and 6 of these
|
||||
register are used for length capability detection, while only 01
|
||||
combination indicates support of extended transaction length. Others mean
|
||||
lack of such support.
|
||||
|
||||
It adds support for smbus block read transaction. CPLD smbus block read
|
||||
bit of capability register is verified during driver initialization, and
|
||||
driver data is updated if such capability is available. In case an upper
|
||||
layer requests a read transaction of length one and expects that length
|
||||
will be the first received byte, driver will notify CPLD about SMBus block
|
||||
read transaction flavor, so CPLD will know to execute such kind of
|
||||
transaction.
|
||||
|
||||
It fixes report about supported functionality.
|
||||
Functionality can be different up to CPLD capability.
|
||||
|
||||
It allows mlxcpld driver to be connected to pre-defined adapter number
|
||||
equal or greater than one, in order to avoid current limitation, assuming
|
||||
usage of id number one only.
|
||||
|
||||
Author: Michael Shych <michaelsh@mellanox.com>
|
||||
Patches are sent to i2c-next.
|
||||
|
||||
Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
|
||||
---
|
||||
drivers/i2c/busses/i2c-mlxcpld.c | 70 ++++++++++++++++++++++++++++++++++------
|
||||
1 file changed, 60 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c
|
||||
index d271e6a..745ed43 100644
|
||||
--- a/drivers/i2c/busses/i2c-mlxcpld.c
|
||||
+++ b/drivers/i2c/busses/i2c-mlxcpld.c
|
||||
@@ -45,13 +45,16 @@
|
||||
#define MLXCPLD_I2C_VALID_FLAG (I2C_M_RECV_LEN | I2C_M_RD)
|
||||
#define MLXCPLD_I2C_BUS_NUM 1
|
||||
#define MLXCPLD_I2C_DATA_REG_SZ 36
|
||||
+#define MLXCPLD_I2C_DATA_SZ_BIT BIT(5)
|
||||
+#define MLXCPLD_I2C_DATA_SZ_MASK GENMASK(6, 5)
|
||||
+#define MLXCPLD_I2C_SMBUS_BLK_BIT BIT(7)
|
||||
#define MLXCPLD_I2C_MAX_ADDR_LEN 4
|
||||
#define MLXCPLD_I2C_RETR_NUM 2
|
||||
#define MLXCPLD_I2C_XFER_TO 500000 /* usec */
|
||||
#define MLXCPLD_I2C_POLL_TIME 2000 /* usec */
|
||||
|
||||
/* LPC I2C registers */
|
||||
-#define MLXCPLD_LPCI2C_LPF_REG 0x0
|
||||
+#define MLXCPLD_LPCI2C_CPBLTY_REG 0x0
|
||||
#define MLXCPLD_LPCI2C_CTRL_REG 0x1
|
||||
#define MLXCPLD_LPCI2C_HALF_CYC_REG 0x4
|
||||
#define MLXCPLD_LPCI2C_I2C_HOLD_REG 0x5
|
||||
@@ -83,6 +86,7 @@ struct mlxcpld_i2c_priv {
|
||||
struct mutex lock;
|
||||
struct mlxcpld_i2c_curr_xfer xfer;
|
||||
struct device *dev;
|
||||
+ bool smbus_block;
|
||||
};
|
||||
|
||||
static void mlxcpld_i2c_lpc_write_buf(u8 *data, u8 len, u32 addr)
|
||||
@@ -230,7 +234,7 @@ static void mlxcpld_i2c_set_transf_data(struct mlxcpld_i2c_priv *priv,
|
||||
* All upper layers currently are never use transfer with more than
|
||||
* 2 messages. Actually, it's also not so relevant in Mellanox systems
|
||||
* because of HW limitation. Max size of transfer is not more than 32
|
||||
- * bytes in the current x86 LPCI2C bridge.
|
||||
+ * or 68 bytes in the current x86 LPCI2C bridge.
|
||||
*/
|
||||
priv->xfer.cmd = msgs[num - 1].flags & I2C_M_RD;
|
||||
|
||||
@@ -295,7 +299,7 @@ static int mlxcpld_i2c_wait_for_free(struct mlxcpld_i2c_priv *priv)
|
||||
static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv)
|
||||
{
|
||||
int status, i, timeout = 0;
|
||||
- u8 datalen;
|
||||
+ u8 datalen, val;
|
||||
|
||||
do {
|
||||
usleep_range(MLXCPLD_I2C_POLL_TIME / 2, MLXCPLD_I2C_POLL_TIME);
|
||||
@@ -324,9 +328,22 @@ static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv)
|
||||
* Actual read data len will be always the same as
|
||||
* requested len. 0xff (line pull-up) will be returned
|
||||
* if slave has no data to return. Thus don't read
|
||||
- * MLXCPLD_LPCI2C_NUM_DAT_REG reg from CPLD.
|
||||
+ * MLXCPLD_LPCI2C_NUM_DAT_REG reg from CPLD. Only in case of
|
||||
+ * SMBus block read transaction data len can be different,
|
||||
+ * check this case.
|
||||
*/
|
||||
- datalen = priv->xfer.data_len;
|
||||
+ mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG, &val,
|
||||
+ 1);
|
||||
+ if (priv->smbus_block && (val & MLXCPLD_I2C_SMBUS_BLK_BIT)) {
|
||||
+ mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_NUM_DAT_REG,
|
||||
+ &datalen, 1);
|
||||
+ if (unlikely(datalen > (I2C_SMBUS_BLOCK_MAX + 1))) {
|
||||
+ dev_err(priv->dev, "Incorrect smbus block read message len\n");
|
||||
+ return -E2BIG;
|
||||
+ }
|
||||
+ } else {
|
||||
+ datalen = priv->xfer.data_len;
|
||||
+ }
|
||||
|
||||
mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_DATA_REG,
|
||||
priv->xfer.msg[i].buf, datalen);
|
||||
@@ -344,12 +361,20 @@ static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv)
|
||||
static void mlxcpld_i2c_xfer_msg(struct mlxcpld_i2c_priv *priv)
|
||||
{
|
||||
int i, len = 0;
|
||||
- u8 cmd;
|
||||
+ u8 cmd, val;
|
||||
|
||||
mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_DAT_REG,
|
||||
&priv->xfer.data_len, 1);
|
||||
- mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG,
|
||||
- &priv->xfer.addr_width, 1);
|
||||
+
|
||||
+ val = priv->xfer.addr_width;
|
||||
+ /* Notify HW about SMBus block read transaction */
|
||||
+ if (priv->smbus_block && priv->xfer.msg_num >= 2 &&
|
||||
+ priv->xfer.msg[1].len == 1 &&
|
||||
+ (priv->xfer.msg[1].flags & I2C_M_RECV_LEN) &&
|
||||
+ (priv->xfer.msg[1].flags & I2C_M_RD))
|
||||
+ val |= MLXCPLD_I2C_SMBUS_BLK_BIT;
|
||||
+
|
||||
+ mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG, &val, 1);
|
||||
|
||||
for (i = 0; i < priv->xfer.msg_num; i++) {
|
||||
if ((priv->xfer.msg[i].flags & I2C_M_RD) != I2C_M_RD) {
|
||||
@@ -425,7 +450,14 @@ static int mlxcpld_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
|
||||
|
||||
static u32 mlxcpld_i2c_func(struct i2c_adapter *adap)
|
||||
{
|
||||
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||
+ struct mlxcpld_i2c_priv *priv = i2c_get_adapdata(adap);
|
||||
+
|
||||
+ if (priv->smbus_block)
|
||||
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
|
||||
+ I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||
+ else
|
||||
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
|
||||
+ I2C_FUNC_SMBUS_I2C_BLOCK;
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm mlxcpld_i2c_algo = {
|
||||
@@ -433,13 +465,20 @@ static const struct i2c_algorithm mlxcpld_i2c_algo = {
|
||||
.functionality = mlxcpld_i2c_func
|
||||
};
|
||||
|
||||
-static struct i2c_adapter_quirks mlxcpld_i2c_quirks = {
|
||||
+static const struct i2c_adapter_quirks mlxcpld_i2c_quirks = {
|
||||
.flags = I2C_AQ_COMB_WRITE_THEN_READ,
|
||||
.max_read_len = MLXCPLD_I2C_DATA_REG_SZ - MLXCPLD_I2C_MAX_ADDR_LEN,
|
||||
.max_write_len = MLXCPLD_I2C_DATA_REG_SZ,
|
||||
.max_comb_1st_msg_len = 4,
|
||||
};
|
||||
|
||||
+static const struct i2c_adapter_quirks mlxcpld_i2c_quirks_ext = {
|
||||
+ .flags = I2C_AQ_COMB_WRITE_THEN_READ,
|
||||
+ .max_read_len = MLXCPLD_I2C_DATA_REG_SZ * 2 - MLXCPLD_I2C_MAX_ADDR_LEN,
|
||||
+ .max_write_len = MLXCPLD_I2C_DATA_REG_SZ * 2,
|
||||
+ .max_comb_1st_msg_len = 4,
|
||||
+};
|
||||
+
|
||||
static struct i2c_adapter mlxcpld_i2c_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "i2c-mlxcpld",
|
||||
@@ -454,6 +493,7 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct mlxcpld_i2c_priv *priv;
|
||||
int err;
|
||||
+ u8 val;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
@@ -466,6 +506,16 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev)
|
||||
|
||||
/* Register with i2c layer */
|
||||
mlxcpld_i2c_adapter.timeout = usecs_to_jiffies(MLXCPLD_I2C_XFER_TO);
|
||||
+ /* Read capability register */
|
||||
+ mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_CPBLTY_REG, &val, 1);
|
||||
+ /* Check support for extended transaction length */
|
||||
+ if ((val & MLXCPLD_I2C_DATA_SZ_MASK) == MLXCPLD_I2C_DATA_SZ_BIT)
|
||||
+ mlxcpld_i2c_adapter.quirks = &mlxcpld_i2c_quirks_ext;
|
||||
+ /* Check support for smbus block transaction */
|
||||
+ if (val & MLXCPLD_I2C_SMBUS_BLK_BIT)
|
||||
+ priv->smbus_block = true;
|
||||
+ if (pdev->id >= -1)
|
||||
+ mlxcpld_i2c_adapter.nr = pdev->id;
|
||||
priv->adap = mlxcpld_i2c_adapter;
|
||||
priv->adap.dev.parent = &pdev->dev;
|
||||
priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR;
|
||||
--
|
||||
2.1.4
|
||||
|
||||
@@ -1 +1,13 @@
|
||||
driver-support-intel-igb-bcm5461-phy.patch
|
||||
0001-i2c-mlxcpld-add-master-driver-for-Mellanox-systems.patch
|
||||
0002-i2c-mux-mlxcpld-add-driver-for-Mellanox-systems.patch
|
||||
0003-platform-mellanox-Introduce-Mellanox-hardware-platfo.patch
|
||||
0004-platform-x86-Introduce-support-for-Mellanox-hotplug-.patch
|
||||
0005-leds-add-driver-for-support-Mellanox-regmap-LEDs-for.patch
|
||||
0006-Mellanox-switch-drivers-changes.patch
|
||||
0007-hwmon-pmbus-Add-support-for-Intel-VID-protocol-VR13.patch
|
||||
0008-hwmon-pmbus-Add-support-for-Texas-Instruments-tps536.patch
|
||||
0009-platform-mellonox-introduce-mlxreg-io-driver-and-add.patch
|
||||
0010-platform-mellanox-mlxreg-hotplug-driver-add-check-fo.patch
|
||||
0011-platform-x86-mlx-platform-new-features.patch
|
||||
0012-i2c-busses-Add-capabilities-to-i2c-mlxcpld.patch
|
||||
|
||||
@@ -31,8 +31,11 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define MAX_FAN_DUTY_CYCLE 100
|
||||
#define MAX_FAN_DUTY_CYCLE 100
|
||||
#define I2C_RW_RETRY_COUNT 10
|
||||
#define I2C_RW_RETRY_INTERVAL 60 /* ms */
|
||||
|
||||
/* Addresses scanned
|
||||
*/
|
||||
@@ -41,6 +44,7 @@ static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
|
||||
enum chips {
|
||||
YM2651,
|
||||
YM2401,
|
||||
YM2851,
|
||||
};
|
||||
|
||||
/* Each client has this additional data
|
||||
@@ -67,6 +71,7 @@ struct ym2651y_data {
|
||||
u8 mfr_id[10]; /* Register value */
|
||||
u8 mfr_model[16]; /* Register value */
|
||||
u8 mfr_revsion[3]; /* Register value */
|
||||
u8 mfr_serial[20]; /* Register value */
|
||||
u16 mfr_vin_min; /* Register value */
|
||||
u16 mfr_vin_max; /* Register value */
|
||||
u16 mfr_iin_max; /* Register value */
|
||||
@@ -112,6 +117,7 @@ enum ym2651y_sysfs_attributes {
|
||||
PSU_MFR_ID,
|
||||
PSU_MFR_MODEL,
|
||||
PSU_MFR_REVISION,
|
||||
PSU_MFR_SERIAL,
|
||||
PSU_MFR_VIN_MIN,
|
||||
PSU_MFR_VIN_MAX,
|
||||
PSU_MFR_VOUT_MIN,
|
||||
@@ -140,6 +146,7 @@ static SENSOR_DEVICE_ATTR(psu_pmbus_revision,S_IRUGO, show_byte, NULL, PSU_PMB
|
||||
static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID);
|
||||
static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL);
|
||||
static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION);
|
||||
static SENSOR_DEVICE_ATTR(psu_mfr_serial, S_IRUGO, show_ascii, NULL, PSU_MFR_SERIAL);
|
||||
static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN);
|
||||
static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX);
|
||||
static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN);
|
||||
@@ -166,6 +173,7 @@ static struct attribute *ym2651y_attributes[] = {
|
||||
&sensor_dev_attr_psu_mfr_id.dev_attr.attr,
|
||||
&sensor_dev_attr_psu_mfr_model.dev_attr.attr,
|
||||
&sensor_dev_attr_psu_mfr_revision.dev_attr.attr,
|
||||
&sensor_dev_attr_psu_mfr_serial.dev_attr.attr,
|
||||
&sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr,
|
||||
&sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr,
|
||||
&sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr,
|
||||
@@ -370,6 +378,9 @@ static ssize_t show_ascii(struct device *dev, struct device_attribute *da,
|
||||
case PSU_MFR_REVISION: /* psu_mfr_revision */
|
||||
ptr = data->mfr_revsion + 1; /* The first byte is the count byte of string. */
|
||||
break;
|
||||
case PSU_MFR_SERIAL: /* psu_mfr_serial */
|
||||
ptr = data->mfr_serial + 1; /* The first byte is the count byte of string. */
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -477,6 +488,7 @@ static int ym2651y_remove(struct i2c_client *client)
|
||||
static const struct i2c_device_id ym2651y_id[] = {
|
||||
{ "ym2651", YM2651 },
|
||||
{ "ym2401", YM2401 },
|
||||
{ "ym2851", YM2851 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ym2651y_id);
|
||||
@@ -494,35 +506,75 @@ static struct i2c_driver ym2651y_driver = {
|
||||
|
||||
static int ym2651y_read_byte(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
return i2c_smbus_read_byte_data(client, reg);
|
||||
int status = 0, retry = I2C_RW_RETRY_COUNT;
|
||||
|
||||
while (retry) {
|
||||
status = i2c_smbus_read_byte_data(client, reg);
|
||||
if (unlikely(status < 0)) {
|
||||
msleep(I2C_RW_RETRY_INTERVAL);
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int ym2651y_read_word(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
return i2c_smbus_read_word_data(client, reg);
|
||||
int status = 0, retry = I2C_RW_RETRY_COUNT;
|
||||
|
||||
while (retry) {
|
||||
status = i2c_smbus_read_word_data(client, reg);
|
||||
if (unlikely(status < 0)) {
|
||||
msleep(I2C_RW_RETRY_INTERVAL);
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value)
|
||||
{
|
||||
return i2c_smbus_write_word_data(client, reg, value);
|
||||
int status = 0, retry = I2C_RW_RETRY_COUNT;
|
||||
|
||||
while (retry) {
|
||||
status = i2c_smbus_write_word_data(client, reg, value);
|
||||
if (unlikely(status < 0)) {
|
||||
msleep(I2C_RW_RETRY_INTERVAL);
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data,
|
||||
int data_len)
|
||||
{
|
||||
int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data);
|
||||
int status = 0, retry = I2C_RW_RETRY_COUNT;
|
||||
|
||||
if (unlikely(result < 0))
|
||||
goto abort;
|
||||
if (unlikely(result != data_len)) {
|
||||
result = -EIO;
|
||||
goto abort;
|
||||
while (retry) {
|
||||
status = i2c_smbus_read_i2c_block_data(client, command, data_len, data);
|
||||
if (unlikely(status < 0)) {
|
||||
msleep(I2C_RW_RETRY_INTERVAL);
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
result = 0;
|
||||
|
||||
abort:
|
||||
return result;
|
||||
return status;
|
||||
}
|
||||
|
||||
struct reg_data_byte {
|
||||
@@ -651,6 +703,17 @@ static struct ym2651y_data *ym2651y_update_device(struct device *dev)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Read mfr_serial */
|
||||
command = 0x9e;
|
||||
status = ym2651y_read_block(client, command, data->mfr_serial,
|
||||
ARRAY_SIZE(data->mfr_serial)-1);
|
||||
data->mfr_serial[ARRAY_SIZE(data->mfr_serial)-1] = '\0';
|
||||
|
||||
if (status < 0) {
|
||||
dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
|
||||
@@ -21,5 +21,4 @@ packages:
|
||||
init: ${ONL}/packages/base/any/onlp-snmpd/onlp-snmpd.init
|
||||
|
||||
changelog: Change changes changes.,
|
||||
|
||||
|
||||
asr: True
|
||||
|
||||
@@ -110,7 +110,7 @@ onlp_snmp_config_lookup(const char* setting)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; onlp_snmp_config_settings[i].name; i++) {
|
||||
if(strcmp(onlp_snmp_config_settings[i].name, setting)) {
|
||||
if(!strcmp(onlp_snmp_config_settings[i].name, setting)) {
|
||||
return onlp_snmp_config_settings[i].value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,9 +259,29 @@ us_to_next_update(void)
|
||||
return MIN(period - deltat, period);
|
||||
}
|
||||
|
||||
#include <onlplib/file_uds.h>
|
||||
|
||||
static int
|
||||
cpu_utilization_handler__(int fd, void* cookie)
|
||||
{
|
||||
char svalue[64];
|
||||
resources_t *curr = get_curr_resources();
|
||||
sprintf(svalue, "%d", curr->utilization_percent);
|
||||
write(fd, svalue, strlen(svalue));
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *
|
||||
do_update(void *arg)
|
||||
{
|
||||
onlp_file_uds_t* uds;
|
||||
if(ONLP_SUCCESS(onlp_file_uds_create(&uds))) {
|
||||
onlp_file_uds_add(uds,
|
||||
"/var/run/onl/cpu-utilization",
|
||||
cpu_utilization_handler__, NULL);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
resource_update();
|
||||
usleep(us_to_next_update());
|
||||
|
||||
@@ -26,11 +26,14 @@ packages:
|
||||
builds/onlp-platform/$BUILD_DIR/${TOOLCHAIN}/bin/libonlp-platform.so : $libdir/
|
||||
builds/onlp-platform-defaults/$BUILD_DIR/${TOOLCHAIN}/bin/libonlp-platform-defaults.so : $libdir/
|
||||
builds/onlpd/$BUILD_DIR/${TOOLCHAIN}/bin/onlpd : $bindir/
|
||||
${ONL}/packages/base/any/onlp/src/onlpdump.py: $bindir/
|
||||
${ONL}/packages/base/any/onlp/src/onlp/module/python/onlp/__init__.py: ${PY_INSTALL}/onlp/
|
||||
${ONL}/packages/base/any/onlp/src/onlp/module/python/onlp/onlp: ${PY_INSTALL}/onlp/onlp
|
||||
${ONL}/packages/base/any/onlp/src/onlp/module/python/onlp/test: ${PY_INSTALL}/onlp/test
|
||||
${ONL}/packages/base/any/onlp/src/onlplib/module/python/onlp/onlplib: ${PY_INSTALL}/onlp/onlplib
|
||||
${ONL}/packages/base/any/onlp/src/sff/module/python/onlp/sff: ${PY_INSTALL}/onlp/sff
|
||||
|
||||
init: $ONL/packages/base/any/onlp/src/onlpd.init
|
||||
|
||||
changelog: Change changes changes.,
|
||||
|
||||
|
||||
|
||||
|
||||
asr: True
|
||||
|
||||
1
packages/base/any/onlp/src/onlp/.gitignore
vendored
Normal file
1
packages/base/any/onlp/src/onlp/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.mk
|
||||
@@ -24,5 +24,5 @@
|
||||
############################################################
|
||||
|
||||
onlp_AUTO_DEFS := module/auto/onlp.yml
|
||||
onlp_AUTO_DIRS := module/inc/onlp module/src module/py
|
||||
onlp_AUTO_DIRS := module/inc/onlp module/src module/python/onlp/onlp
|
||||
include $(BUILDER)/auto.mk
|
||||
|
||||
@@ -109,6 +109,17 @@ oid_types: &oid_types
|
||||
- MODULE : 6
|
||||
- RTC : 7
|
||||
|
||||
# OID dump options
|
||||
oid_dump: &oid_dump
|
||||
- RECURSE
|
||||
- EVEN_IF_ABSENT
|
||||
|
||||
# OID show options
|
||||
oid_show: &oid_show
|
||||
- RECURSE
|
||||
- EXTENDED
|
||||
- YAML
|
||||
|
||||
# SFP Control
|
||||
sfp_control: &sfp_control
|
||||
- RESET
|
||||
@@ -255,6 +266,14 @@ definitions:
|
||||
onlp_oid_type:
|
||||
tag: oid
|
||||
members: *oid_types
|
||||
onlp_oid_show:
|
||||
tag: oid
|
||||
members: *oid_show
|
||||
flags: True
|
||||
onlp_oid_dump:
|
||||
tag: oid
|
||||
members: *oid_dump
|
||||
flags: True
|
||||
onlp_thermal_status:
|
||||
tag: thermal
|
||||
members: *thermal_status
|
||||
|
||||
@@ -47,6 +47,19 @@
|
||||
typedef uint32_t onlp_oid_t;
|
||||
|
||||
/* <auto.start.enum(tag:oid).define> */
|
||||
/** onlp_oid_dump */
|
||||
typedef enum onlp_oid_dump_e {
|
||||
ONLP_OID_DUMP_RECURSE = (1 << 0),
|
||||
ONLP_OID_DUMP_EVEN_IF_ABSENT = (1 << 1),
|
||||
} onlp_oid_dump_t;
|
||||
|
||||
/** onlp_oid_show */
|
||||
typedef enum onlp_oid_show_e {
|
||||
ONLP_OID_SHOW_RECURSE = (1 << 0),
|
||||
ONLP_OID_SHOW_EXTENDED = (1 << 1),
|
||||
ONLP_OID_SHOW_YAML = (1 << 2),
|
||||
} onlp_oid_show_t;
|
||||
|
||||
/** onlp_oid_type */
|
||||
typedef enum onlp_oid_type_e {
|
||||
ONLP_OID_TYPE_SYS = 1,
|
||||
@@ -121,13 +134,6 @@ typedef struct onlp_oid_hdr_s {
|
||||
} onlp_oid_hdr_t;
|
||||
|
||||
|
||||
#define ONLP_OID_DUMP_F_RECURSE 0x1
|
||||
#define ONLP_OID_DUMP_F_EVEN_IF_ABSENT 0x2
|
||||
|
||||
#define ONLP_OID_SHOW_F_RECURSE 0x1
|
||||
#define ONLP_OID_SHOW_F_EXTENDED 0x2
|
||||
#define ONLP_OID_SHOW_F_YAML 0x4
|
||||
|
||||
void onlp_oid_dump(onlp_oid_t oid, aim_pvs_t* pvs, uint32_t flags);
|
||||
void onlp_oid_table_dump(onlp_oid_table_t table, aim_pvs_t* pvs,
|
||||
uint32_t flags);
|
||||
@@ -199,6 +205,48 @@ int onlp_oid_hdr_get(onlp_oid_t oid, onlp_oid_hdr_t* hdr);
|
||||
*
|
||||
*****************************************************************************/
|
||||
/* <auto.start.enum(tag:oid).supportheader> */
|
||||
/** Enum names. */
|
||||
const char* onlp_oid_dump_name(onlp_oid_dump_t e);
|
||||
|
||||
/** Enum values. */
|
||||
int onlp_oid_dump_value(const char* str, onlp_oid_dump_t* e, int substr);
|
||||
|
||||
/** Enum descriptions. */
|
||||
const char* onlp_oid_dump_desc(onlp_oid_dump_t e);
|
||||
|
||||
/** Enum validator. */
|
||||
int onlp_oid_dump_valid(onlp_oid_dump_t e);
|
||||
|
||||
/** validator */
|
||||
#define ONLP_OID_DUMP_VALID(_e) \
|
||||
(onlp_oid_dump_valid((_e)))
|
||||
|
||||
/** onlp_oid_dump_map table. */
|
||||
extern aim_map_si_t onlp_oid_dump_map[];
|
||||
/** onlp_oid_dump_desc_map table. */
|
||||
extern aim_map_si_t onlp_oid_dump_desc_map[];
|
||||
|
||||
/** Enum names. */
|
||||
const char* onlp_oid_show_name(onlp_oid_show_t e);
|
||||
|
||||
/** Enum values. */
|
||||
int onlp_oid_show_value(const char* str, onlp_oid_show_t* e, int substr);
|
||||
|
||||
/** Enum descriptions. */
|
||||
const char* onlp_oid_show_desc(onlp_oid_show_t e);
|
||||
|
||||
/** Enum validator. */
|
||||
int onlp_oid_show_valid(onlp_oid_show_t e);
|
||||
|
||||
/** validator */
|
||||
#define ONLP_OID_SHOW_VALID(_e) \
|
||||
(onlp_oid_show_valid((_e)))
|
||||
|
||||
/** onlp_oid_show_map table. */
|
||||
extern aim_map_si_t onlp_oid_show_map[];
|
||||
/** onlp_oid_show_desc_map table. */
|
||||
extern aim_map_si_t onlp_oid_show_desc_map[];
|
||||
|
||||
/** Enum names. */
|
||||
const char* onlp_oid_type_name(onlp_oid_type_t e);
|
||||
|
||||
|
||||
@@ -48,6 +48,8 @@ ONLP_ENUMERATION_ENTRY(onlp_fan_status, "")
|
||||
ONLP_ENUMERATION_ENTRY(onlp_led_caps, "")
|
||||
ONLP_ENUMERATION_ENTRY(onlp_led_mode, "")
|
||||
ONLP_ENUMERATION_ENTRY(onlp_led_status, "")
|
||||
ONLP_ENUMERATION_ENTRY(onlp_oid_dump, "")
|
||||
ONLP_ENUMERATION_ENTRY(onlp_oid_show, "")
|
||||
ONLP_ENUMERATION_ENTRY(onlp_oid_type, "")
|
||||
ONLP_ENUMERATION_ENTRY(onlp_psu_caps, "")
|
||||
ONLP_ENUMERATION_ENTRY(onlp_psu_status, "")
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
"""__init__.py
|
||||
|
||||
Module init for onlp.
|
||||
"""
|
||||
@@ -0,0 +1,662 @@
|
||||
"""__init__.py
|
||||
|
||||
Module init for onlp.onlp
|
||||
"""
|
||||
|
||||
import ctypes
|
||||
|
||||
libonlp = ctypes.cdll.LoadLibrary("libonlp.so")
|
||||
libonlp.onlp_init()
|
||||
|
||||
import ctypes.util
|
||||
libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("c"))
|
||||
|
||||
import onlp.onlplib
|
||||
import onlp.sff
|
||||
from onlp.onlp import aim_weakref
|
||||
|
||||
from onlp.onlp.enums import *
|
||||
|
||||
# AIM/aim_memory.h
|
||||
|
||||
class aim_void_p(aim_weakref.AimPointer):
|
||||
|
||||
@classmethod
|
||||
def deletePointer(cls, aimPtr):
|
||||
libonlp.aim_free(aimPtr)
|
||||
|
||||
class aim_char_p(aim_void_p):
|
||||
"""AIM data that is a printable string."""
|
||||
|
||||
def __init__(self, stringOrAddress):
|
||||
|
||||
if stringOrAddress is None:
|
||||
aim_void_p.__init__(self, stringOrAddress)
|
||||
return
|
||||
|
||||
if isinstance(stringOrAddress, aim_void_p):
|
||||
aim_void_p.__init__(self, stringOrAddress)
|
||||
return
|
||||
|
||||
if isinstance(stringOrAddress, basestring):
|
||||
cs = ctypes.c_char_p(stringOrAddress)
|
||||
ptr = libonlp.aim_malloc(len(stringOrAddress)+1)
|
||||
libc.strcpy(ptr, ctypes.addressof(cs))
|
||||
aim_void_p.__init__(self, ptr)
|
||||
return
|
||||
|
||||
if type(stringOrAddress) == int:
|
||||
aim_void_p.__init__(self, stringOrAddress)
|
||||
return
|
||||
|
||||
raise ValueError("invalid initializer for aim_char_p: %s"
|
||||
% repr(stringOrAddress))
|
||||
|
||||
def string_at(self):
|
||||
if self.value:
|
||||
return ctypes.string_at(self.value)
|
||||
else:
|
||||
return None
|
||||
|
||||
def __eq__(self, other):
|
||||
return (isinstance(other, aim_char_p)
|
||||
and (self.string_at()==other.string_at()))
|
||||
|
||||
def __neq__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.string_at())
|
||||
|
||||
def aim_memory_init_prototypes():
|
||||
|
||||
libonlp.aim_malloc.restype = aim_void_p
|
||||
libonlp.aim_malloc.argtypes = (ctypes.c_size_t,)
|
||||
|
||||
libonlp.aim_free.restype = None
|
||||
libonlp.aim_free.argtypes = (aim_void_p,)
|
||||
|
||||
# AIM/aim_object.h
|
||||
|
||||
aim_object_dtor = ctypes.CFUNCTYPE(None, ctypes.c_void_p)
|
||||
|
||||
class aim_object(ctypes.Structure):
|
||||
_fields_ = [("_id", ctypes.c_char_p,),
|
||||
("subtype", ctypes.c_int,),
|
||||
("cookie", ctypes.c_void_p,),
|
||||
("destructor", aim_object_dtor,),]
|
||||
|
||||
# AIM/aim_pvs.h
|
||||
# AIM/aim_pvs_*.h
|
||||
|
||||
aim_vprintf_f = ctypes.CFUNCTYPE(ctypes.c_int)
|
||||
|
||||
class aim_pvs(ctypes.Structure):
|
||||
_fields_ = [("object", aim_object,),
|
||||
("description", ctypes.c_char_p,),
|
||||
("vprintf", aim_vprintf_f,),
|
||||
("enabled", ctypes.c_int,),
|
||||
("counter", ctypes.c_uint32,),
|
||||
("isatty", aim_vprintf_f,),]
|
||||
|
||||
def aim_pvs_init_prototypes():
|
||||
|
||||
libonlp.aim_pvs_buffer_create.restype = ctypes.POINTER(aim_pvs)
|
||||
|
||||
libonlp.aim_pvs_destroy.restype = None
|
||||
libonlp.aim_pvs_destroy.argtypes = (ctypes.POINTER(aim_pvs),)
|
||||
|
||||
libonlp.aim_pvs_buffer_size.restype = ctypes.c_int
|
||||
libonlp.aim_pvs_buffer_size.argtypes = (ctypes.POINTER(aim_pvs),)
|
||||
|
||||
libonlp.aim_pvs_buffer_get.restype = aim_char_p
|
||||
libonlp.aim_pvs_buffer_get.argtypes = (ctypes.POINTER(aim_pvs),)
|
||||
|
||||
libonlp.aim_pvs_buffer_reset.restype = None
|
||||
libonlp.aim_pvs_buffer_reset.argtypes = (ctypes.POINTER(aim_pvs),)
|
||||
|
||||
# AIM/aim_bitmap.h
|
||||
|
||||
aim_bitmap_word = ctypes.c_uint32
|
||||
AIM_BITMAP_BITS_PER_WORD = 32
|
||||
|
||||
def AIM_BITMAP_WORD_COUNT(bitcount):
|
||||
return ((bitcount // AIM_BITMAP_BITS_PER_WORD)
|
||||
+ (1 if (bitcount % AIM_BITMAP_BITS_PER_WORD) else 0))
|
||||
|
||||
# ugh, most of aim_bitmap.h is inline C
|
||||
|
||||
def AIM_BITMAP_HDR_WORD_GET(hdr, word):
|
||||
"""Return a specific ctypes word."""
|
||||
return hdr.words[word]
|
||||
|
||||
def AIM_BITMAP_HDR_BIT_WORD_GET(hdr, bit):
|
||||
"""Return the ctypes word holding this bit."""
|
||||
return hdr.words[bit/AIM_BITMAP_BITS_PER_WORD]
|
||||
|
||||
def AIM_BITMAP_HDR_BIT_WORD_SET(hdr, bit, word):
|
||||
"""Return the ctypes word holding this bit."""
|
||||
hdr.words[bit/AIM_BITMAP_BITS_PER_WORD] = word
|
||||
|
||||
def AIM_BITMAP_BIT_POS(bit):
|
||||
return (1<<(bit % AIM_BITMAP_BITS_PER_WORD))
|
||||
|
||||
def AIM_BITMAP_INIT(bitmap, count):
|
||||
"""Initialize a static bitmap."""
|
||||
libc.memset(ctypes.byref(bitmap), 0, ctypes.sizeof(bitmap))
|
||||
bitmap.hdr.maxbit = count
|
||||
bitmap.hdr.words = ctypes.cast(ctypes.byref(bitmap.words), ctypes.POINTER(ctypes.c_uint))
|
||||
bitmap.hdr.wordcount = AIM_BITMAP_WORD_COUNT(count)
|
||||
|
||||
class aim_bitmap_hdr(ctypes.Structure):
|
||||
_fields_ = [("wordcount", ctypes.c_int,),
|
||||
("words", ctypes.POINTER(aim_bitmap_word),),
|
||||
("maxbit", ctypes.c_int,),
|
||||
("allocated", ctypes.c_int,),]
|
||||
|
||||
class aim_bitmap(ctypes.Structure):
|
||||
_fields_ = [("hdr", aim_bitmap_hdr,),]
|
||||
|
||||
class aim_bitmap_ref(aim_weakref.AimReference):
|
||||
"""Dynamically allocated aim_bitmap."""
|
||||
|
||||
_fields_ = aim_bitmap._fields_
|
||||
|
||||
def __init__(self, bitcount):
|
||||
ptr = libonlp.aim_bitmap_alloc(None, bitcount)
|
||||
super(aim_bitmap_ref, self).__init__(ptr)
|
||||
|
||||
@classmethod
|
||||
def deleteReference(self, aimPtr):
|
||||
libonlp.aim_free(aimPtr)
|
||||
|
||||
class aim_bitmap256(aim_bitmap):
|
||||
"""Statically-allocated AIM bitmap."""
|
||||
_fields_ = [("words", aim_bitmap_word * AIM_BITMAP_WORD_COUNT(256),),]
|
||||
|
||||
def __init__(self):
|
||||
super(aim_bitmap256, self).__init__()
|
||||
AIM_BITMAP_INIT(self, 255)
|
||||
|
||||
def aim_bitmap_set(hdr, bit):
|
||||
word = AIM_BITMAP_HDR_BIT_WORD_GET(hdr, bit)
|
||||
word |= AIM_BITMAP_BIT_POS(bit)
|
||||
AIM_BITMAP_HDR_BIT_WORD_SET(hdr, bit, word)
|
||||
|
||||
def aim_bitmap_clr(hdr, bit):
|
||||
word = AIM_BITMAP_HDR_BIT_WORD_GET(hdr, bit)
|
||||
word &= ~(AIM_BITMAP_BIT_POS(bit))
|
||||
AIM_BITMAP_HDR_BIT_WORD_SET(hdr, bit, word)
|
||||
|
||||
def aim_bitmap_mod(hdr, bit, value):
|
||||
if value:
|
||||
aim_bitmap_set(hdr, bit)
|
||||
else:
|
||||
aim_bitmap_clr(hdr, bit)
|
||||
|
||||
def aim_bitmap_get(hdr, bit):
|
||||
val = AIM_BITMAP_HDR_BIT_WORD_GET(hdr,bit) & AIM_BITMAP_BIT_POS(bit)
|
||||
return 1 if val else 0
|
||||
|
||||
# Huh, these is inline too, but calls into glibc memset
|
||||
|
||||
def aim_bitmap_set_all(hdr):
|
||||
libc.memset(ctypes.byref(hdr.words), 0xFF, hdr.wordcount*ctypes.sizeof(aim_bitmap_word))
|
||||
|
||||
def aim_bitmap_clr_all(hdr):
|
||||
libc.memset(ctypes.byref(hdr.words), 0x00, hdr.wordcount*ctypes.sizeof(aim_bitmap_word))
|
||||
|
||||
# XXX aim_bitmap_count is left out
|
||||
|
||||
def aim_bitmap_init_prototypes():
|
||||
|
||||
libonlp.aim_bitmap_alloc.restype = ctypes.POINTER(aim_bitmap)
|
||||
libonlp.aim_bitmap_alloc.argtypes = (ctypes.POINTER(aim_bitmap), ctypes.c_int,)
|
||||
|
||||
libonlp.aim_bitmap_free.restype = None
|
||||
libonlp.aim_bitmap_free.argtypes = (ctypes.POINTER(aim_bitmap),)
|
||||
|
||||
# onlp.yml
|
||||
|
||||
##ONLP_CONFIG_INFO_STR_MAX = int(libonlp.onlp_config_lookup("ONLP_CONFIG_INFO_STR_MAX"))
|
||||
ONLP_CONFIG_INFO_STR_MAX = 64
|
||||
# prototype for onlp_config_lookup is not defined yet, see below
|
||||
|
||||
# onlp/oids.h
|
||||
|
||||
onlp_oid = ctypes.c_uint32
|
||||
|
||||
ONLP_OID_SYS = (ONLP_OID_TYPE.SYS<<24) | 1
|
||||
# XXX not a config option
|
||||
|
||||
ONLP_OID_DESC_SIZE = 128
|
||||
ONLP_OID_TABLE_SIZE = 32
|
||||
# XXX not a config option
|
||||
|
||||
class OidTableIterator(object):
|
||||
|
||||
def __init__(self, hdr):
|
||||
self.hdr = hdr
|
||||
self.idx = 0
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def next(self):
|
||||
if self.idx >= ONLP_OID_TABLE_SIZE:
|
||||
raise StopIteration
|
||||
oid = self.hdr.coids[self.idx]
|
||||
self.idx += 1
|
||||
if oid == 0:
|
||||
raise StopIteration
|
||||
oidHdr = onlp_oid_hdr()
|
||||
libonlp.onlp_oid_hdr_get(oid, ctypes.byref(oidHdr))
|
||||
return oidHdr
|
||||
|
||||
class onlp_oid_hdr(ctypes.Structure):
|
||||
|
||||
_fields_ = [("_id", onlp_oid,),
|
||||
("description", ctypes.c_char * ONLP_OID_DESC_SIZE,),
|
||||
("poid", onlp_oid,),
|
||||
("coids", onlp_oid * ONLP_OID_TABLE_SIZE,),]
|
||||
|
||||
def getType(self):
|
||||
return self._id >> 24
|
||||
|
||||
def isSystem(self):
|
||||
return self.getType() == ONLP_OID_TYPE.SYS
|
||||
def isThermal(self):
|
||||
return self.getType() == ONLP_OID_TYPE.THERMAL
|
||||
def isFan(self):
|
||||
return self.getType() == ONLP_OID_TYPE.FAN
|
||||
def isPsu(self):
|
||||
return self.getType() == ONLP_OID_TYPE.PSU
|
||||
def isLed(self):
|
||||
return self.getType() == ONLP_OID_TYPE.LED
|
||||
def isModule(self):
|
||||
return self.getType() == ONLP_OID_TYPE.MODULE
|
||||
def isRtc(self):
|
||||
return self.getType() == ONLP_OID_TYPE.RTC
|
||||
|
||||
def children(self):
|
||||
return OidTableIterator(self)
|
||||
|
||||
onlp_oid_iterate_f = ctypes.CFUNCTYPE(ctypes.c_int, onlp_oid, ctypes.c_void_p)
|
||||
|
||||
def onlp_oid_init_prototypes():
|
||||
|
||||
libonlp.onlp_oid_dump.restype = None
|
||||
libonlp.onlp_oid_dump.argtypes = (onlp_oid, ctypes.POINTER(aim_pvs), ctypes.c_uint32,)
|
||||
|
||||
libonlp.onlp_oid_table_dump.restype = None
|
||||
libonlp.onlp_oid_table_dump.argtypes = (ctypes.POINTER(onlp_oid), ctypes.POINTER(aim_pvs), ctypes.c_uint32,)
|
||||
|
||||
libonlp.onlp_oid_show.restype = None
|
||||
libonlp.onlp_oid_show.argtypes = (onlp_oid, ctypes.POINTER(aim_pvs), ctypes.c_uint32,)
|
||||
|
||||
libonlp.onlp_oid_table_show.restype = None
|
||||
libonlp.onlp_oid_table_show.argtypes = (ctypes.POINTER(onlp_oid), ctypes.POINTER(aim_pvs), ctypes.c_uint32,)
|
||||
|
||||
libonlp.onlp_oid_iterate.restype = ctypes.c_int
|
||||
libonlp.onlp_oid_iterate.argtypes = (onlp_oid, ctypes.c_int,
|
||||
onlp_oid_iterate_f, ctypes.c_void_p,)
|
||||
|
||||
libonlp.onlp_oid_hdr_get.restype = ctypes.c_int
|
||||
libonlp.onlp_oid_hdr_get.argtypes = (onlp_oid, ctypes.POINTER(onlp_oid_hdr,))
|
||||
|
||||
# onlp/sys.h
|
||||
|
||||
class onlp_sys_info(aim_weakref.AimStruct):
|
||||
|
||||
_fields_ = [("hdr", onlp_oid_hdr,),
|
||||
("onie_info", onlp.onlplib.onlp_onie_info,),
|
||||
("platform_info", onlp.onlplib.onlp_platform_info,),]
|
||||
|
||||
def __init__(self):
|
||||
self.initialized = False
|
||||
super(onlp_sys_info, self).__init__()
|
||||
|
||||
def deleteStruct(self):
|
||||
initialized, self.initialized = self.initialized, False
|
||||
if initialized:
|
||||
libonlp.onlp_sys_info_free(ctypes.byref(self))
|
||||
|
||||
def onlp_sys_init_prototypes():
|
||||
|
||||
libonlp.onlp_sys_init.restype = ctypes.c_int
|
||||
|
||||
libonlp.onlp_sys_info_get.restype = ctypes.c_int
|
||||
libonlp.onlp_sys_info_get.argtypes = (ctypes.POINTER(onlp_sys_info),)
|
||||
|
||||
libonlp.onlp_sys_info_free.restype = None
|
||||
libonlp.onlp_sys_info_get.argtypes = (ctypes.POINTER(onlp_sys_info),)
|
||||
|
||||
libonlp.onlp_sys_hdr_get.restype = ctypes.c_int
|
||||
libonlp.onlp_sys_hdr_get.argtypes = (ctypes.POINTER(onlp_oid_hdr),)
|
||||
|
||||
libonlp.onlp_sys_dump.restype = None
|
||||
libonlp.onlp_sys_dump.argtypes = (onlp_oid, ctypes.POINTER(aim_pvs), ctypes.c_uint32,)
|
||||
|
||||
libonlp.onlp_sys_show.restype = None
|
||||
libonlp.onlp_sys_show.argtypes = (onlp_oid, ctypes.POINTER(aim_pvs), ctypes.c_uint32,)
|
||||
|
||||
libonlp.onlp_sys_ioctl.restype = ctypes.c_int
|
||||
# leave the parameters empty (varargs)
|
||||
|
||||
##libonlp.onlp_sys_vioctl.restype = ctypes.c_int
|
||||
# NOTE that ctypes cannot automatically handle va_list
|
||||
|
||||
libonlp.onlp_sys_platform_manage_start.restype = ctypes.c_int
|
||||
libonlp.onlp_sys_platform_manage_start.argtypes = (ctypes.c_int,)
|
||||
|
||||
libonlp.onlp_sys_platform_manage_stop.restype = ctypes.c_int
|
||||
libonlp.onlp_sys_platform_manage_stop.argtypes = (ctypes.c_int,)
|
||||
|
||||
libonlp.onlp_sys_platform_manage_join.restype = ctypes.c_int
|
||||
|
||||
libonlp.onlp_sys_platform_manage_now.restype = None
|
||||
|
||||
libonlp.onlp_sys_debug.restype = ctypes.c_int
|
||||
libonlp.onlp_sys_debug.argtypes = (ctypes.POINTER(aim_pvs), ctypes.c_int,
|
||||
ctypes.POINTER(ctypes.POINTER(ctypes.c_char)),)
|
||||
|
||||
# onlp/fan.h
|
||||
|
||||
class onlp_fan_info(ctypes.Structure):
|
||||
_fields_ = [("hdr", onlp_oid_hdr,),
|
||||
("status", ctypes.c_uint32,),
|
||||
("caps", ctypes.c_uint32,),
|
||||
("rpm", ctypes.c_int,),
|
||||
("percentage", ctypes.c_int,),
|
||||
("mode", ctypes.c_uint32,),
|
||||
("model", ctypes.c_char * ONLP_CONFIG_INFO_STR_MAX,),
|
||||
("serial", ctypes.c_char * ONLP_CONFIG_INFO_STR_MAX,),]
|
||||
|
||||
def isPresent(self):
|
||||
return self.status & ONLP_FAN_STATUS.PRESENT
|
||||
|
||||
def isMissing(self):
|
||||
return not self.PRESENT()
|
||||
|
||||
def isFailed(self):
|
||||
return self.status & ONLP_FAN_STATUS.FAILED
|
||||
|
||||
def isNormal(self):
|
||||
return self.isPresent() and not self.isFailed()
|
||||
|
||||
def onlp_fan_init_prototypes():
|
||||
|
||||
libonlp.onlp_fan_init.restype = None
|
||||
|
||||
libonlp.onlp_fan_info_get.restype = ctypes.c_int
|
||||
libonlp.onlp_fan_info_get.argtypes = (onlp_oid, ctypes.POINTER(onlp_fan_info),)
|
||||
|
||||
libonlp.onlp_fan_status_get.restype = ctypes.c_int
|
||||
libonlp.onlp_fan_status_get.argtypes = (onlp_oid, ctypes.POINTER(ctypes.c_uint32),)
|
||||
|
||||
libonlp.onlp_fan_hdr_get.restype = ctypes.c_int
|
||||
libonlp.onlp_fan_hdr_get.argtypes = (onlp_oid, ctypes.POINTER(onlp_oid_hdr),)
|
||||
|
||||
libonlp.onlp_fan_rpm_set.restype = ctypes.c_int
|
||||
libonlp.onlp_fan_rpm_set.argtypes = (onlp_oid, ctypes.c_int,)
|
||||
|
||||
libonlp.onlp_fan_percentage_set.restype = ctypes.c_int
|
||||
libonlp.onlp_fan_percentage_set.argtypes = (onlp_oid, ctypes.c_int,)
|
||||
|
||||
libonlp.onlp_fan_mode_set.restype = ctypes.c_int
|
||||
libonlp.onlp_fan_mode_set.argtypes = (onlp_oid, ctypes.c_uint32,)
|
||||
|
||||
libonlp.onlp_fan_dir_set.restype = ctypes.c_int
|
||||
libonlp.onlp_fan_dir_set.argtypes = (onlp_oid, ctypes.c_uint32,)
|
||||
|
||||
libonlp.onlp_fan_dump.restype = None
|
||||
libonlp.onlp_fan_dump.argtypes = (onlp_oid, ctypes.POINTER(aim_pvs), ctypes.c_uint32,)
|
||||
|
||||
libonlp.onlp_fan_show.restype = None
|
||||
libonlp.onlp_fan_show.argtypes = (onlp_oid, ctypes.POINTER(aim_pvs), ctypes.c_uint32,)
|
||||
|
||||
# onlp/led.h
|
||||
|
||||
class onlp_led_info(ctypes.Structure):
|
||||
_fields_ = [("hdr", onlp_oid_hdr,),
|
||||
("status", ctypes.c_uint32,),
|
||||
("caps", ctypes.c_uint32,),
|
||||
("mode", ctypes.c_uint32,),
|
||||
("character", ctypes.c_char,),]
|
||||
|
||||
def onlp_led_init_prototypes():
|
||||
|
||||
libonlp.onlp_led_init.restype = None
|
||||
|
||||
libonlp.onlp_led_info_get.restype = ctypes.c_int
|
||||
libonlp.onlp_led_info_get.argtypes = (onlp_oid, ctypes.POINTER(onlp_led_info),)
|
||||
|
||||
libonlp.onlp_led_status_get.restype = ctypes.c_int
|
||||
libonlp.onlp_led_status_get.argtypes = (onlp_oid, ctypes.POINTER(ctypes.c_uint32),)
|
||||
|
||||
libonlp.onlp_led_hdr_get.restype = ctypes.c_int
|
||||
libonlp.onlp_led_hdr_get.argtypes = (onlp_oid, ctypes.POINTER(onlp_oid_hdr),)
|
||||
|
||||
libonlp.onlp_led_set.restype = ctypes.c_int
|
||||
libonlp.onlp_led_set.argtypes = (onlp_oid, ctypes.c_int,)
|
||||
|
||||
libonlp.onlp_led_mode_set.restype = ctypes.c_int
|
||||
libonlp.onlp_led_mode_set.argtypes = (onlp_oid, ctypes.c_uint32,)
|
||||
|
||||
libonlp.onlp_led_char_set.restype = ctypes.c_int
|
||||
libonlp.onlp_led_char_set.argtypes = (onlp_oid, ctypes.c_char,)
|
||||
|
||||
libonlp.onlp_led_dump.restype = None
|
||||
libonlp.onlp_led_dump.argtypes = (onlp_oid, ctypes.POINTER(aim_pvs), ctypes.c_uint32,)
|
||||
|
||||
libonlp.onlp_led_show.restype = None
|
||||
libonlp.onlp_led_show.argtypes = (onlp_oid, ctypes.POINTER(aim_pvs), ctypes.c_uint32,)
|
||||
|
||||
# onlp/onlp_config.h
|
||||
|
||||
# don't need the actual config structure, since we'll be using lookups
|
||||
|
||||
def onlp_config_init_prototypes():
|
||||
|
||||
libonlp.onlp_config_lookup.restype = ctypes.c_char_p
|
||||
libonlp.onlp_config_lookup.argtypes = (ctypes.c_char_p,)
|
||||
|
||||
libonlp.onlp_config_show.restype = ctypes.c_int
|
||||
libonlp.onlp_config_show.argtypes = (ctypes.POINTER(aim_pvs),)
|
||||
|
||||
# onlp/thermal.h
|
||||
|
||||
class onlp_thermal_info_thresholds(ctypes.Structure):
|
||||
_fields_ = [('warning', ctypes.c_int,),
|
||||
('error', ctypes.c_int,),
|
||||
('shutdown', ctypes.c_int,),]
|
||||
|
||||
class onlp_thermal_info(ctypes.Structure):
|
||||
_fields_ = [('hdr', onlp_oid_hdr,),
|
||||
('status', ctypes.c_uint32,),
|
||||
('caps', ctypes.c_uint32,),
|
||||
('mcelcius', ctypes.c_int,),
|
||||
('thresholds', onlp_thermal_info_thresholds,),]
|
||||
|
||||
def onlp_thermal_init_prototypes():
|
||||
|
||||
libonlp.onlp_thermal_init.restype = ctypes.c_int
|
||||
|
||||
libonlp.onlp_thermal_info_get.restype = ctypes.c_int
|
||||
libonlp.onlp_thermal_info_get.argtypes = (onlp_oid, ctypes.POINTER(onlp_thermal_info),)
|
||||
|
||||
libonlp.onlp_thermal_status_get.restype = ctypes.c_int
|
||||
libonlp.onlp_thermal_status_get.argtypes = (onlp_oid, ctypes.POINTER(ctypes.c_uint32),)
|
||||
|
||||
libonlp.onlp_thermal_hdr_get.restype = ctypes.c_int
|
||||
libonlp.onlp_thermal_hdr_get.argtypes = (onlp_oid, ctypes.POINTER(onlp_oid_hdr),)
|
||||
|
||||
libonlp.onlp_thermal_ioctl.restype = ctypes.c_int
|
||||
|
||||
libonlp.onlp_thermal_dump.restype = None
|
||||
libonlp.onlp_thermal_dump.argtypes = (onlp_oid, ctypes.POINTER(aim_pvs),)
|
||||
|
||||
libonlp.onlp_thermal_show.restype = None
|
||||
libonlp.onlp_thermal_show.argtypes = (onlp_oid, ctypes.POINTER(aim_pvs),)
|
||||
|
||||
# onlp/psu.h
|
||||
|
||||
class onlp_psu_info(ctypes.Structure):
|
||||
_fields_ = [("hdr", onlp_oid_hdr,),
|
||||
("model", ctypes.c_char * ONLP_CONFIG_INFO_STR_MAX,),
|
||||
("serial", ctypes.c_char * ONLP_CONFIG_INFO_STR_MAX,),
|
||||
("status", ctypes.c_uint32,),
|
||||
("caps", ctypes.c_uint32,),
|
||||
("mvin", ctypes.c_int,),
|
||||
("mvout", ctypes.c_int,),
|
||||
("miin", ctypes.c_int,),
|
||||
("miout", ctypes.c_int,),
|
||||
("mpin", ctypes.c_int,),
|
||||
("mpout", ctypes.c_int,),]
|
||||
|
||||
def onlp_psu_init_prototypes():
|
||||
|
||||
libonlp.onlp_psu_init.restype = ctypes.c_int
|
||||
|
||||
libonlp.onlp_psu_info_get.restype = ctypes.c_int
|
||||
libonlp.onlp_psu_info_get.argtypes = (onlp_oid, ctypes.POINTER(onlp_psu_info),)
|
||||
|
||||
libonlp.onlp_psu_status_get.restype = ctypes.c_int
|
||||
libonlp.onlp_psu_status_get.argtypes = (onlp_oid, ctypes.POINTER(ctypes.c_uint32),)
|
||||
|
||||
libonlp.onlp_psu_hdr_get.restype = ctypes.c_int
|
||||
libonlp.onlp_psu_hdr_get.argtypes = (onlp_oid, ctypes.POINTER(onlp_oid_hdr),)
|
||||
|
||||
libonlp.onlp_psu_ioctl.restype = ctypes.c_int
|
||||
|
||||
libonlp.onlp_psu_dump.restype = None
|
||||
libonlp.onlp_psu_dump.argtypes = (onlp_oid, ctypes.POINTER(aim_pvs),)
|
||||
|
||||
libonlp.onlp_psu_show.restype = None
|
||||
libonlp.onlp_psu_show.argtypes = (onlp_oid, ctypes.POINTER(aim_pvs),)
|
||||
|
||||
# sff/sff.h
|
||||
|
||||
def sff_init_prototypes():
|
||||
|
||||
libonlp.sff_sfp_type_get.restype = onlp.sff.sff_sfp_type
|
||||
libonlp.sff_sfp_type_get.argtypes = (ctypes.POINTER(ctypes.c_ubyte),)
|
||||
|
||||
libonlp.sff_module_type_get.restype = onlp.sff.sff_module_type
|
||||
libonlp.sff_module_type_get.argtypes = (ctypes.POINTER(ctypes.c_ubyte),)
|
||||
|
||||
libonlp.sff_media_type_get.restype = onlp.sff.sff_media_type
|
||||
libonlp.sff_media_type_get.argtypes = (onlp.sff.sff_module_type,)
|
||||
|
||||
libonlp.sff_module_caps_get.restype = ctypes.c_int
|
||||
libonlp.sff_module_caps_get.argtypes = (onlp.sff.sff_module_type, ctypes.POINTER(ctypes.c_uint32),)
|
||||
|
||||
libonlp.sff_eeprom_parse.restype = ctypes.c_int
|
||||
libonlp.sff_eeprom_parse.argtypes = (ctypes.POINTER(onlp.sff.sff_eeprom), ctypes.POINTER(ctypes.c_ubyte),)
|
||||
|
||||
libonlp.sff_eeprom_parse_file.restype = ctypes.c_int
|
||||
libonlp.sff_eeprom_parse_file.argtypes = (ctypes.POINTER(onlp.sff.sff_eeprom), ctypes.c_char_p,)
|
||||
|
||||
libonlp.sff_eeprom_invalidate.restype = None
|
||||
libonlp.sff_eeprom_invalidate.argtypes = (ctypes.POINTER(onlp.sff.sff_eeprom),)
|
||||
|
||||
libonlp.sff_eeprom_validate.restype = ctypes.c_int
|
||||
libonlp.sff_eeprom_validate.argtypes = (ctypes.POINTER(onlp.sff.sff_eeprom), ctypes.c_int,)
|
||||
|
||||
libonlp.sff_info_show.restype = None
|
||||
libonlp.sff_info_show.argtypes = (ctypes.POINTER(onlp.sff.sff_info), ctypes.POINTER(aim_pvs),)
|
||||
|
||||
libonlp.sff_info_init.restype = ctypes.c_int
|
||||
libonlp.sff_info_init.argtypes = (ctypes.POINTER(onlp.sff.sff_info), onlp.sff.sff_module_type,
|
||||
ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p,
|
||||
ctypes.c_int,)
|
||||
|
||||
# onlp/sff.h
|
||||
|
||||
onlp_sfp_bitmap = aim_bitmap256
|
||||
|
||||
onlp_sfp_control = ctypes.c_int
|
||||
|
||||
def onlp_sfp_init_prototypes():
|
||||
|
||||
libonlp.onlp_sfp_init.restype = ctypes.c_int
|
||||
|
||||
libonlp.onlp_sfp_bitmap_t_init.restype = None
|
||||
libonlp.onlp_sfp_bitmap_t_init.argtypes = (ctypes.POINTER(onlp_sfp_bitmap),)
|
||||
|
||||
libonlp.onlp_sfp_bitmap_get.restype = ctypes.c_int
|
||||
libonlp.onlp_sfp_bitmap_get.argtypes = (ctypes.POINTER(onlp_sfp_bitmap),)
|
||||
|
||||
libonlp.onlp_sfp_port_valid.restype = ctypes.c_int
|
||||
libonlp.onlp_sfp_port_valid.argtypes = (ctypes.c_int,)
|
||||
|
||||
libonlp.onlp_sfp_is_present.restype = ctypes.c_int
|
||||
libonlp.onlp_sfp_is_present.argtypes = (ctypes.c_int,)
|
||||
|
||||
libonlp.onlp_sfp_presence_bitmap_get.restype = ctypes.c_int
|
||||
libonlp.onlp_sfp_presence_bitmap_get.argtypes = (ctypes.POINTER(onlp_sfp_bitmap),)
|
||||
|
||||
libonlp.onlp_sfp_eeprom_read.restype = ctypes.c_int
|
||||
libonlp.onlp_sfp_eeprom_read.argtypes = (ctypes.c_int, ctypes.POINTER(ctypes.POINTER(ctypes.c_ubyte,)),)
|
||||
|
||||
libonlp.onlp_sfp_dom_read.restype = ctypes.c_int
|
||||
libonlp.onlp_sfp_dom_read.argtypes = (ctypes.c_int, ctypes.POINTER(ctypes.POINTER(ctypes.c_ubyte)),)
|
||||
|
||||
libonlp.onlp_sfp_denit.restype = ctypes.c_int
|
||||
|
||||
libonlp.onlp_sfp_rx_los_bitmap_get.restype = ctypes.c_int
|
||||
libonlp.onlp_sfp_rx_los_bitmap_get.argtypes = (ctypes.POINTER(onlp_sfp_bitmap),)
|
||||
|
||||
libonlp.onlp_sfp_dev_readb.restype = ctypes.c_int
|
||||
libonlp.onlp_sfp_dev_readb.argtypes = (ctypes.c_int, ctypes.c_ubyte, ctypes.c_ubyte,)
|
||||
|
||||
libonlp.onlp_sfp_dev_writeb.restype = ctypes.c_int
|
||||
libonlp.onlp_sfp_dev_writeb.argtypes = (ctypes.c_int, ctypes.c_ubyte, ctypes.c_ubyte, ctypes.c_ubyte)
|
||||
|
||||
libonlp.onlp_sfp_dev_readw.restype = ctypes.c_int
|
||||
libonlp.onlp_sfp_dev_readw.argtypes = (ctypes.c_int, ctypes.c_ubyte, ctypes.c_ubyte,)
|
||||
|
||||
libonlp.onlp_sfp_dev_writew.restype = ctypes.c_int
|
||||
libonlp.onlp_sfp_dev_writew.argtypes = (ctypes.c_int, ctypes.c_ubyte, ctypes.c_ubyte, ctypes.c_ushort)
|
||||
|
||||
libonlp.onlp_sfp_dump.restype = None
|
||||
libonlp.onlp_sfp_dump.argtypes = (ctypes.POINTER(aim_pvs),)
|
||||
|
||||
libonlp.onlp_sfp_ioctl.restype = ctypes.c_int
|
||||
|
||||
libonlp.onlp_sfp_post_insert.restype = ctypes.c_int
|
||||
libonlp.onlp_sfp_post_insert.argtypes = (ctypes.c_int, ctypes.POINTER(onlp.sff.sff_info),)
|
||||
|
||||
libonlp.onlp_sfp_control_set.restype = ctypes.c_int
|
||||
libonlp.onlp_sfp_control_set.argtypes = (ctypes.c_int, onlp_sfp_control, ctypes.c_int,)
|
||||
|
||||
libonlp.onlp_sfp_control_get.restype = ctypes.c_int
|
||||
libonlp.onlp_sfp_control_get.argtypes = (ctypes.c_int, onlp_sfp_control, ctypes.POINTER(ctypes.c_int))
|
||||
|
||||
libonlp.onlp_sfp_control_flags_get.restype = ctypes.c_int
|
||||
libonlp.onlp_sfp_control_flags_get.argtyeps = (ctypes.c_int, ctypes.POINTER(ctypes.c_uint32),)
|
||||
|
||||
# onlp/onlp.h
|
||||
|
||||
def init_prototypes():
|
||||
aim_memory_init_prototypes()
|
||||
aim_pvs_init_prototypes()
|
||||
aim_bitmap_init_prototypes()
|
||||
onlp_oid_init_prototypes()
|
||||
onlp_sys_init_prototypes()
|
||||
onlp_fan_init_prototypes()
|
||||
onlp_led_init_prototypes()
|
||||
|
||||
onlp_config_init_prototypes()
|
||||
|
||||
strMax = int(libonlp.onlp_config_lookup("ONLP_CONFIG_INFO_STR_MAX"))
|
||||
if ONLP_CONFIG_INFO_STR_MAX != strMax:
|
||||
raise AssertionError("ONLP_CONFIG_INFO_STR_MAX changed from %d to %d"
|
||||
% (ONLP_CONFIG_INFO_STR_MAX, strMax,))
|
||||
|
||||
onlp_thermal_init_prototypes()
|
||||
onlp_psu_init_prototypes()
|
||||
sff_init_prototypes()
|
||||
onlp_sfp_init_prototypes()
|
||||
|
||||
init_prototypes()
|
||||
@@ -0,0 +1,94 @@
|
||||
"""aim_weakref.py
|
||||
|
||||
Use weakref to implement smart AIM pointers.
|
||||
|
||||
See e.g.
|
||||
http://code.activestate.com/recipes/577242-calling-c-level-finalizers-without-__del__/
|
||||
"""
|
||||
|
||||
import ctypes
|
||||
import logging
|
||||
import weakref
|
||||
|
||||
logger = logging.getLogger("weakref")
|
||||
|
||||
def getLogger():
|
||||
global logger
|
||||
return logger
|
||||
|
||||
class AimOwnerRef(weakref.ref):
|
||||
pass
|
||||
|
||||
def _run_finalizer(ref):
|
||||
"""Internal weakref callback to run finalizers"""
|
||||
del _finalize_refs[id(ref)]
|
||||
finalizer = ref.finalizer
|
||||
item = ref.item
|
||||
try:
|
||||
finalizer(item)
|
||||
except Exception:
|
||||
getLogger().exception("finalizer failed")
|
||||
|
||||
_finalize_refs = {}
|
||||
|
||||
def track_for_finalization(owner, item, finalizer):
|
||||
"""Register an object for finalization.
|
||||
|
||||
``owner`` is the the object which is responsible for ``item``.
|
||||
``finalizer`` will be called with ``item`` as its only argument when
|
||||
``owner`` is destroyed by the garbage collector.
|
||||
"""
|
||||
ref = AimOwnerRef(owner, _run_finalizer)
|
||||
ref.item = item
|
||||
ref.finalizer = finalizer
|
||||
_finalize_refs[id(ref)] = ref
|
||||
|
||||
class AimReference(object):
|
||||
"""Manage an AIM pointer using reference semantics."""
|
||||
|
||||
@classmethod
|
||||
def deleteReference(cls, aimPtr):
|
||||
"""Override this with the proper delete semantics."""
|
||||
raise NotImplementedError
|
||||
|
||||
def __init__(self, aimPtr):
|
||||
self.ptr = aimPtr
|
||||
track_for_finalization(self, self.ptr, self.deleteReference)
|
||||
|
||||
def __getattr__(self, attr, dfl='__none__'):
|
||||
if dfl == '__none__':
|
||||
return getattr(self.ptr.contents, attr)
|
||||
else:
|
||||
return getattr(self.ptr.contents, attr, dfl)
|
||||
|
||||
def __setattr___(self, attr, val):
|
||||
setattr(self.ptr.contents, attr, val)
|
||||
|
||||
class AimPointer(ctypes.c_void_p):
|
||||
"""Manage an AIM pointer using pointer semantics."""
|
||||
|
||||
@classmethod
|
||||
def deletePointer(cls, aimPtr):
|
||||
"""Override this with the proper delete semantics."""
|
||||
raise NotImplementedError
|
||||
|
||||
def __init__(self, aimPtr):
|
||||
|
||||
super(ctypes.c_void_p, self).__init__(aimPtr)
|
||||
# XXX roth -- casting may be necessary
|
||||
|
||||
track_for_finalization(self, aimPtr, self.deletePointer)
|
||||
|
||||
class AimStruct(ctypes.Structure):
|
||||
"""Manage an AIM struct with internally-allocated data."""
|
||||
|
||||
@classmethod
|
||||
def deleteStruct(cls, aimPtr):
|
||||
"""Override this with the proper delete semantics."""
|
||||
raise NotImplementedError
|
||||
|
||||
def __init__(self):
|
||||
|
||||
super(ctypes.Structure, self).__init__()
|
||||
|
||||
track_for_finalization(self, self, self.deleteStruct)
|
||||
@@ -88,6 +88,17 @@ class ONLP_LED_STATUS(Enumeration):
|
||||
ON = (1 << 2)
|
||||
|
||||
|
||||
class ONLP_OID_DUMP(Enumeration):
|
||||
RECURSE = (1 << 0)
|
||||
EVEN_IF_ABSENT = (1 << 1)
|
||||
|
||||
|
||||
class ONLP_OID_SHOW(Enumeration):
|
||||
RECURSE = (1 << 0)
|
||||
EXTENDED = (1 << 1)
|
||||
YAML = (1 << 2)
|
||||
|
||||
|
||||
class ONLP_OID_TYPE(Enumeration):
|
||||
SYS = 1
|
||||
THERMAL = 2
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
"""__init__.py
|
||||
|
||||
Test code for the onlp Python bindings.
|
||||
"""
|
||||
@@ -281,7 +281,7 @@ onlp_fan_show(onlp_oid_t oid, aim_pvs_t* pvs, uint32_t flags)
|
||||
|
||||
rv = onlp_fan_info_get(oid, &fi);
|
||||
|
||||
yaml = flags & ONLP_OID_SHOW_F_YAML;
|
||||
yaml = flags & ONLP_OID_SHOW_YAML;
|
||||
|
||||
if(yaml) {
|
||||
iof_push(&iof, "- ");
|
||||
|
||||
@@ -215,7 +215,7 @@ onlp_led_show(onlp_oid_t id, aim_pvs_t* pvs, uint32_t flags)
|
||||
VALIDATENR(id);
|
||||
onlp_oid_show_iof_init_default(&iof, pvs, flags);
|
||||
|
||||
yaml = flags & ONLP_OID_SHOW_F_YAML;
|
||||
yaml = flags & ONLP_OID_SHOW_YAML;
|
||||
|
||||
if(yaml) {
|
||||
iof_push(&iof, " -");
|
||||
|
||||
@@ -216,7 +216,7 @@ onlp_oid_iterate(onlp_oid_t oid, onlp_oid_type_t type,
|
||||
}
|
||||
|
||||
ONLP_OID_TABLE_ITER(hdr.coids, oidp) {
|
||||
if(type == 0 || ONLP_OID_IS_TYPE(*oidp, type)) {
|
||||
if(type == 0 || ONLP_OID_IS_TYPE(type, *oidp)) {
|
||||
int rv = itf(*oidp, cookie);
|
||||
if(rv < 0) {
|
||||
return rv;
|
||||
|
||||
@@ -145,7 +145,7 @@ onlp_config_lookup(const char* setting)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; onlp_config_settings[i].name; i++) {
|
||||
if(strcmp(onlp_config_settings[i].name, setting)) {
|
||||
if(!strcmp(onlp_config_settings[i].name, setting)) {
|
||||
return onlp_config_settings[i].value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,6 +519,128 @@ onlp_led_status_valid(onlp_led_status_t e)
|
||||
}
|
||||
|
||||
|
||||
aim_map_si_t onlp_oid_dump_map[] =
|
||||
{
|
||||
{ "RECURSE", ONLP_OID_DUMP_RECURSE },
|
||||
{ "EVEN_IF_ABSENT", ONLP_OID_DUMP_EVEN_IF_ABSENT },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
aim_map_si_t onlp_oid_dump_desc_map[] =
|
||||
{
|
||||
{ "None", ONLP_OID_DUMP_RECURSE },
|
||||
{ "None", ONLP_OID_DUMP_EVEN_IF_ABSENT },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
const char*
|
||||
onlp_oid_dump_name(onlp_oid_dump_t e)
|
||||
{
|
||||
const char* name;
|
||||
if(aim_map_si_i(&name, e, onlp_oid_dump_map, 0)) {
|
||||
return name;
|
||||
}
|
||||
else {
|
||||
return "-invalid value for enum type 'onlp_oid_dump'";
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
onlp_oid_dump_value(const char* str, onlp_oid_dump_t* e, int substr)
|
||||
{
|
||||
int i;
|
||||
AIM_REFERENCE(substr);
|
||||
if(aim_map_si_s(&i, str, onlp_oid_dump_map, 0)) {
|
||||
/* Enum Found */
|
||||
*e = i;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
onlp_oid_dump_desc(onlp_oid_dump_t e)
|
||||
{
|
||||
const char* name;
|
||||
if(aim_map_si_i(&name, e, onlp_oid_dump_desc_map, 0)) {
|
||||
return name;
|
||||
}
|
||||
else {
|
||||
return "-invalid value for enum type 'onlp_oid_dump'";
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
onlp_oid_dump_valid(onlp_oid_dump_t e)
|
||||
{
|
||||
return aim_map_si_i(NULL, e, onlp_oid_dump_map, 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
aim_map_si_t onlp_oid_show_map[] =
|
||||
{
|
||||
{ "RECURSE", ONLP_OID_SHOW_RECURSE },
|
||||
{ "EXTENDED", ONLP_OID_SHOW_EXTENDED },
|
||||
{ "YAML", ONLP_OID_SHOW_YAML },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
aim_map_si_t onlp_oid_show_desc_map[] =
|
||||
{
|
||||
{ "None", ONLP_OID_SHOW_RECURSE },
|
||||
{ "None", ONLP_OID_SHOW_EXTENDED },
|
||||
{ "None", ONLP_OID_SHOW_YAML },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
const char*
|
||||
onlp_oid_show_name(onlp_oid_show_t e)
|
||||
{
|
||||
const char* name;
|
||||
if(aim_map_si_i(&name, e, onlp_oid_show_map, 0)) {
|
||||
return name;
|
||||
}
|
||||
else {
|
||||
return "-invalid value for enum type 'onlp_oid_show'";
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
onlp_oid_show_value(const char* str, onlp_oid_show_t* e, int substr)
|
||||
{
|
||||
int i;
|
||||
AIM_REFERENCE(substr);
|
||||
if(aim_map_si_s(&i, str, onlp_oid_show_map, 0)) {
|
||||
/* Enum Found */
|
||||
*e = i;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
onlp_oid_show_desc(onlp_oid_show_t e)
|
||||
{
|
||||
const char* name;
|
||||
if(aim_map_si_i(&name, e, onlp_oid_show_desc_map, 0)) {
|
||||
return name;
|
||||
}
|
||||
else {
|
||||
return "-invalid value for enum type 'onlp_oid_show'";
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
onlp_oid_show_valid(onlp_oid_show_t e)
|
||||
{
|
||||
return aim_map_si_i(NULL, e, onlp_oid_show_map, 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
aim_map_si_t onlp_oid_type_map[] =
|
||||
{
|
||||
{ "SYS", ONLP_OID_TYPE_SYS },
|
||||
|
||||
@@ -203,8 +203,8 @@ onlpdump_main(int argc, char* argv[])
|
||||
switch(c)
|
||||
{
|
||||
case 's': show=1; break;
|
||||
case 'r': show=1; showflags |= ONLP_OID_SHOW_F_RECURSE; break;
|
||||
case 'e': show=1; showflags |= ONLP_OID_SHOW_F_EXTENDED; break;
|
||||
case 'r': show=1; showflags |= ONLP_OID_SHOW_RECURSE; break;
|
||||
case 'e': show=1; showflags |= ONLP_OID_SHOW_EXTENDED; break;
|
||||
case 'd': show=0; break;
|
||||
case 'h': help=1; rv = 0; break;
|
||||
case 'j': j=1; break;
|
||||
@@ -220,7 +220,7 @@ onlpdump_main(int argc, char* argv[])
|
||||
case 'l': l=1; break;
|
||||
case 'b': b=1; break;
|
||||
case 'J': J = optarg; break;
|
||||
case 'y': show=1; showflags |= ONLP_OID_SHOW_F_YAML; break;
|
||||
case 'y': show=1; showflags |= ONLP_OID_SHOW_YAML; break;
|
||||
default: help=1; rv = 1; break;
|
||||
}
|
||||
}
|
||||
@@ -305,8 +305,8 @@ onlpdump_main(int argc, char* argv[])
|
||||
int oid;
|
||||
if(sscanf(O, "0x%x", &oid) == 1) {
|
||||
onlp_oid_dump(oid, &aim_pvs_stdout,
|
||||
ONLP_OID_DUMP_F_RECURSE |
|
||||
ONLP_OID_DUMP_F_EVEN_IF_ABSENT);
|
||||
ONLP_OID_DUMP_RECURSE |
|
||||
ONLP_OID_DUMP_EVEN_IF_ABSENT);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -349,7 +349,7 @@ onlpdump_main(int argc, char* argv[])
|
||||
if(show == 0) {
|
||||
/* Default to full dump */
|
||||
onlp_platform_dump(&aim_pvs_stdout,
|
||||
ONLP_OID_DUMP_F_RECURSE | ONLP_OID_DUMP_F_EVEN_IF_ABSENT);
|
||||
ONLP_OID_DUMP_RECURSE | ONLP_OID_DUMP_EVEN_IF_ABSENT);
|
||||
}
|
||||
else {
|
||||
onlp_platform_show(&aim_pvs_stdout,
|
||||
|
||||
@@ -69,7 +69,7 @@ onlp_psu_status_get_locked__(onlp_oid_t id, uint32_t* status)
|
||||
}
|
||||
if(ONLP_UNSUPPORTED(rv)) {
|
||||
onlp_psu_info_t pi;
|
||||
rv = onlp_psu_info_get(id, &pi);
|
||||
rv = onlp_psui_info_get(id, &pi);
|
||||
*status = pi.status;
|
||||
}
|
||||
return rv;
|
||||
@@ -143,7 +143,7 @@ onlp_psu_dump(onlp_oid_t id, aim_pvs_t* pvs, uint32_t flags)
|
||||
iof_iprintf(&iof, "Iout: %d", info.miout);
|
||||
iof_iprintf(&iof, "Pin: %d", info.mpin);
|
||||
iof_iprintf(&iof, "Pout: %d", info.mpout);
|
||||
if(flags & ONLP_OID_DUMP_F_RECURSE) {
|
||||
if(flags & ONLP_OID_DUMP_RECURSE) {
|
||||
onlp_oid_table_dump(info.hdr.coids, &iof.inherit, flags);
|
||||
}
|
||||
}
|
||||
@@ -165,7 +165,7 @@ onlp_psu_show(onlp_oid_t id, aim_pvs_t* pvs, uint32_t flags)
|
||||
onlp_oid_show_iof_init_default(&iof, pvs, flags);
|
||||
rv = onlp_psu_info_get(id, &pi);
|
||||
|
||||
yaml = flags & ONLP_OID_SHOW_F_YAML;
|
||||
yaml = flags & ONLP_OID_SHOW_YAML;
|
||||
|
||||
if(yaml) {
|
||||
iof_push(&iof, "- ");
|
||||
@@ -235,7 +235,7 @@ onlp_psu_show(onlp_oid_t id, aim_pvs_t* pvs, uint32_t flags)
|
||||
ONLP_MILLI_NORMAL_INTEGER_TENTHS(pi.mpout));
|
||||
}
|
||||
|
||||
if(flags & ONLP_OID_SHOW_F_RECURSE) {
|
||||
if(flags & ONLP_OID_SHOW_RECURSE) {
|
||||
/*
|
||||
* Display sub oids.
|
||||
*
|
||||
@@ -264,7 +264,7 @@ onlp_psu_show(onlp_oid_t id, aim_pvs_t* pvs, uint32_t flags)
|
||||
iof_pop(&iof);
|
||||
}
|
||||
|
||||
if(flags & ONLP_OID_SHOW_F_EXTENDED) {
|
||||
if(flags & ONLP_OID_SHOW_EXTENDED) {
|
||||
/* Include all other types as well. */
|
||||
ONLP_OID_TABLE_ITER_TYPE(pi.hdr.coids, oidp, LED) {
|
||||
onlp_oid_show(*oidp, &iof.inherit, flags);
|
||||
|
||||
@@ -143,7 +143,8 @@ onlp_sys_info_get_locked__(onlp_sys_info_t* rv)
|
||||
}
|
||||
else {
|
||||
if(onlp_sysi_onie_info_get(&rv->onie_info) != 0) {
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
memset(&rv->onie_info, 0, sizeof(rv->onie_info));
|
||||
list_init(&rv->onie_info.vx_list);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +215,7 @@ onlp_sys_show(onlp_oid_t id, aim_pvs_t* pvs, uint32_t flags)
|
||||
int yaml;
|
||||
|
||||
onlp_oid_show_iof_init_default(&iof, pvs, flags);
|
||||
yaml = (flags & ONLP_OID_SHOW_F_YAML);
|
||||
yaml = (flags & ONLP_OID_SHOW_YAML);
|
||||
|
||||
if(id && ONLP_OID_TYPE_GET(id) != ONLP_OID_TYPE_SYS) {
|
||||
return;
|
||||
@@ -234,14 +235,14 @@ onlp_sys_show(onlp_oid_t id, aim_pvs_t* pvs, uint32_t flags)
|
||||
* unless you specify EXTENDED or !RECURSIVE
|
||||
*/
|
||||
if(yaml ||
|
||||
flags & ONLP_OID_SHOW_F_EXTENDED ||
|
||||
(flags & ONLP_OID_SHOW_F_RECURSE) == 0) {
|
||||
flags & ONLP_OID_SHOW_EXTENDED ||
|
||||
(flags & ONLP_OID_SHOW_RECURSE) == 0) {
|
||||
iof_push(&iof, "System Information:");
|
||||
onlp_onie_show(&si.onie_info, &iof.inherit);
|
||||
iof_pop(&iof);
|
||||
}
|
||||
|
||||
if(flags & ONLP_OID_SHOW_F_RECURSE) {
|
||||
if(flags & ONLP_OID_SHOW_RECURSE) {
|
||||
|
||||
onlp_oid_t* oidp;
|
||||
|
||||
@@ -266,7 +267,7 @@ onlp_sys_show(onlp_oid_t id, aim_pvs_t* pvs, uint32_t flags)
|
||||
}
|
||||
YPOP();
|
||||
|
||||
if(flags & ONLP_OID_SHOW_F_EXTENDED) {
|
||||
if(flags & ONLP_OID_SHOW_EXTENDED) {
|
||||
/** Show all LEDs */
|
||||
YPUSH("LEDs:");
|
||||
ONLP_OID_TABLE_ITER_TYPE(si.hdr.coids, oidp, LED) {
|
||||
|
||||
@@ -202,7 +202,7 @@ onlp_thermal_show(onlp_oid_t id, aim_pvs_t* pvs, uint32_t flags)
|
||||
|
||||
rv = onlp_thermal_info_get(id, &ti);
|
||||
|
||||
yaml = flags & ONLP_OID_SHOW_F_YAML;
|
||||
yaml = flags & ONLP_OID_SHOW_YAML;
|
||||
|
||||
if(yaml) {
|
||||
iof_push(&iof, "- ");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user