mirror of
https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10.git
synced 2026-09-09 00:07:04 +08:00
Merge: CNB103: devlink: update devlink to the v7.1
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/2822 JIRA: https://redhat.atlassian.net/browse/RHEL-179081 Depends: !2273 Devlink update to version v7.1 Signed-off-by: Petr Oros <poros@redhat.com> Approved-by: Tony Camuso <tcamuso@redhat.com> Approved-by: Eric Chanudet <echanude@redhat.com> Approved-by: Ivan Vecera <ivecera@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
This commit is contained in:
@@ -157,6 +157,14 @@ definitions:
|
||||
entries:
|
||||
-
|
||||
name: entry
|
||||
-
|
||||
type: enum
|
||||
name: resource-scope
|
||||
entries:
|
||||
-
|
||||
name: dev
|
||||
-
|
||||
name: port
|
||||
-
|
||||
type: enum
|
||||
name: reload-action
|
||||
@@ -226,6 +234,10 @@ definitions:
|
||||
value: 10
|
||||
-
|
||||
name: binary
|
||||
-
|
||||
name: u64-array
|
||||
value: 129
|
||||
|
||||
-
|
||||
name: rate-tc-index-max
|
||||
type: const
|
||||
@@ -859,6 +871,30 @@ attribute-sets:
|
||||
name: health-reporter-burst-period
|
||||
type: u64
|
||||
doc: Time (in msec) for recoveries before starting the grace period.
|
||||
|
||||
# TODO: fill in the attributes in between
|
||||
|
||||
-
|
||||
name: param-reset-default
|
||||
type: flag
|
||||
doc: Request restoring parameter to its default value.
|
||||
value: 183
|
||||
-
|
||||
name: index
|
||||
type: uint
|
||||
doc: Unique devlink instance index.
|
||||
checks:
|
||||
max: u32-max
|
||||
-
|
||||
name: resource-scope-mask
|
||||
type: u32
|
||||
enum: resource-scope
|
||||
enum-as-flags: true
|
||||
doc: |
|
||||
Bitmask selecting which resource classes to include in a
|
||||
resource-dump response. Bit 0 (dev) selects device-level
|
||||
resources; bit 1 (port) selects port-level resources.
|
||||
When absent all classes are returned.
|
||||
-
|
||||
name: dl-dev-stats
|
||||
subset-of: devlink
|
||||
@@ -1298,11 +1334,13 @@ operations:
|
||||
attributes: &dev-id-attrs
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
reply: &get-reply
|
||||
value: 3
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- reload-failed
|
||||
- dev-stats
|
||||
dump:
|
||||
@@ -1321,6 +1359,7 @@ operations:
|
||||
attributes: &port-id-attrs
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- port-index
|
||||
reply:
|
||||
value: 7
|
||||
@@ -1345,6 +1384,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- port-index
|
||||
- port-type
|
||||
- port-function
|
||||
@@ -1362,6 +1402,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- port-index
|
||||
- port-flavour
|
||||
- port-pci-pf-number
|
||||
@@ -1396,6 +1437,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- port-index
|
||||
- port-split-count
|
||||
|
||||
@@ -1424,6 +1466,7 @@ operations:
|
||||
attributes: &sb-id-attrs
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- sb-index
|
||||
reply: &sb-get-reply
|
||||
value: 13
|
||||
@@ -1446,6 +1489,7 @@ operations:
|
||||
attributes: &sb-pool-id-attrs
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- sb-index
|
||||
- sb-pool-index
|
||||
reply: &sb-pool-get-reply
|
||||
@@ -1469,6 +1513,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- sb-index
|
||||
- sb-pool-index
|
||||
- sb-pool-threshold-type
|
||||
@@ -1487,6 +1532,7 @@ operations:
|
||||
attributes: &sb-port-pool-id-attrs
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- port-index
|
||||
- sb-index
|
||||
- sb-pool-index
|
||||
@@ -1511,6 +1557,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- port-index
|
||||
- sb-index
|
||||
- sb-pool-index
|
||||
@@ -1529,6 +1576,7 @@ operations:
|
||||
attributes: &sb-tc-pool-bind-id-attrs
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- port-index
|
||||
- sb-index
|
||||
- sb-pool-type
|
||||
@@ -1554,6 +1602,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- port-index
|
||||
- sb-index
|
||||
- sb-pool-index
|
||||
@@ -1575,6 +1624,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- sb-index
|
||||
|
||||
-
|
||||
@@ -1590,6 +1640,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- sb-index
|
||||
|
||||
-
|
||||
@@ -1608,6 +1659,7 @@ operations:
|
||||
attributes: &eswitch-attrs
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- eswitch-mode
|
||||
- eswitch-inline-mode
|
||||
- eswitch-encap-mode
|
||||
@@ -1636,12 +1688,14 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- dpipe-table-name
|
||||
reply:
|
||||
value: 31
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- dpipe-tables
|
||||
|
||||
-
|
||||
@@ -1656,11 +1710,13 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- dpipe-table-name
|
||||
reply:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- dpipe-entries
|
||||
|
||||
-
|
||||
@@ -1675,10 +1731,12 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
reply:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- dpipe-headers
|
||||
|
||||
-
|
||||
@@ -1694,6 +1752,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- dpipe-table-name
|
||||
- dpipe-table-counters-enabled
|
||||
|
||||
@@ -1710,6 +1769,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- resource-id
|
||||
- resource-size
|
||||
|
||||
@@ -1719,18 +1779,30 @@ operations:
|
||||
attribute-set: devlink
|
||||
dont-validate: [strict]
|
||||
do:
|
||||
pre: devlink-nl-pre-doit
|
||||
pre: devlink-nl-pre-doit-port-optional
|
||||
post: devlink-nl-post-doit
|
||||
request:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
reply:
|
||||
- index
|
||||
- port-index
|
||||
reply: &resource-dump-reply
|
||||
value: 36
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- port-index
|
||||
- resource-list
|
||||
dump:
|
||||
request:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- resource-scope-mask
|
||||
reply: *resource-dump-reply
|
||||
|
||||
-
|
||||
name: reload
|
||||
@@ -1745,6 +1817,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- reload-action
|
||||
- reload-limits
|
||||
- netns-pid
|
||||
@@ -1754,6 +1827,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- reload-actions-performed
|
||||
|
||||
-
|
||||
@@ -1768,6 +1842,7 @@ operations:
|
||||
attributes: ¶m-id-attrs
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- param-name
|
||||
reply: ¶m-get-reply
|
||||
attributes: *param-id-attrs
|
||||
@@ -1789,10 +1864,12 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- param-name
|
||||
- param-type
|
||||
# param-value-data is missing here as the type is variable
|
||||
- param-value-cmode
|
||||
- param-reset-default
|
||||
|
||||
-
|
||||
name: region-get
|
||||
@@ -1807,6 +1884,7 @@ operations:
|
||||
attributes: ®ion-id-attrs
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- port-index
|
||||
- region-name
|
||||
reply: ®ion-get-reply
|
||||
@@ -1831,6 +1909,7 @@ operations:
|
||||
attributes: ®ion-snapshot-id-attrs
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- port-index
|
||||
- region-name
|
||||
- region-snapshot-id
|
||||
@@ -1861,6 +1940,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- port-index
|
||||
- region-name
|
||||
- region-snapshot-id
|
||||
@@ -1872,6 +1952,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- port-index
|
||||
- region-name
|
||||
|
||||
@@ -1921,6 +2002,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- info-driver-name
|
||||
- info-serial-number
|
||||
- info-version-fixed
|
||||
@@ -1942,6 +2024,7 @@ operations:
|
||||
attributes: &health-reporter-id-attrs
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- port-index
|
||||
- health-reporter-name
|
||||
reply: &health-reporter-get-reply
|
||||
@@ -1964,6 +2047,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- port-index
|
||||
- health-reporter-name
|
||||
- health-reporter-graceful-period
|
||||
@@ -2034,6 +2118,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- flash-update-file-name
|
||||
- flash-update-component
|
||||
- flash-update-overwrite-mask
|
||||
@@ -2051,6 +2136,7 @@ operations:
|
||||
attributes: &trap-id-attrs
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- trap-name
|
||||
reply: &trap-get-reply
|
||||
value: 63
|
||||
@@ -2073,6 +2159,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- trap-name
|
||||
- trap-action
|
||||
|
||||
@@ -2089,6 +2176,7 @@ operations:
|
||||
attributes: &trap-group-id-attrs
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- trap-group-name
|
||||
reply: &trap-group-get-reply
|
||||
value: 67
|
||||
@@ -2111,6 +2199,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- trap-group-name
|
||||
- trap-action
|
||||
- trap-policer-id
|
||||
@@ -2128,6 +2217,7 @@ operations:
|
||||
attributes: &trap-policer-id-attrs
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- trap-policer-id
|
||||
reply: &trap-policer-get-reply
|
||||
value: 71
|
||||
@@ -2150,6 +2240,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- trap-policer-id
|
||||
- trap-policer-rate
|
||||
- trap-policer-burst
|
||||
@@ -2180,6 +2271,7 @@ operations:
|
||||
attributes: &rate-id-attrs
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- port-index
|
||||
- rate-node-name
|
||||
reply: &rate-get-reply
|
||||
@@ -2203,6 +2295,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- rate-node-name
|
||||
- rate-tx-share
|
||||
- rate-tx-max
|
||||
@@ -2224,6 +2317,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- rate-node-name
|
||||
- rate-tx-share
|
||||
- rate-tx-max
|
||||
@@ -2245,6 +2339,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- rate-node-name
|
||||
|
||||
-
|
||||
@@ -2260,6 +2355,7 @@ operations:
|
||||
attributes: &linecard-id-attrs
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- linecard-index
|
||||
reply: &linecard-get-reply
|
||||
value: 80
|
||||
@@ -2282,6 +2378,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- linecard-index
|
||||
- linecard-type
|
||||
|
||||
@@ -2315,6 +2412,7 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- selftests
|
||||
|
||||
-
|
||||
@@ -2326,4 +2424,5 @@ operations:
|
||||
attributes:
|
||||
- bus-name
|
||||
- dev-name
|
||||
- index
|
||||
- port-index
|
||||
|
||||
@@ -33,7 +33,9 @@ Device driver can provide specific callbacks for each "health reporter", e.g.:
|
||||
* Recovery procedures
|
||||
* Diagnostics procedures
|
||||
* Object dump procedures
|
||||
* Out Of Box initial parameters
|
||||
|
||||
Drivers also provide default values for generic reporter parameters when
|
||||
creating a health reporter.
|
||||
|
||||
Different parts of the driver can register different types of health reporters
|
||||
with different handlers.
|
||||
@@ -45,8 +47,9 @@ Once an error is reported, devlink health will perform the following actions:
|
||||
|
||||
* A log is being send to the kernel trace events buffer
|
||||
* Health status and statistics are being updated for the reporter instance
|
||||
* Object dump is being taken and saved at the reporter instance (as long as
|
||||
auto-dump is set and there is no other dump which is already stored)
|
||||
* Object dump is being taken and saved at the reporter instance. This is
|
||||
best effort and skipped when recovery is aborted, auto-dump is disabled,
|
||||
no dump callback is registered, or a dump is already stored.
|
||||
* Auto recovery attempt is being done. Depends on:
|
||||
|
||||
- Auto-recovery configuration
|
||||
@@ -75,7 +78,8 @@ User Interface
|
||||
==============
|
||||
|
||||
User can access/change each reporter's parameters and driver specific callbacks
|
||||
via ``devlink``, e.g per error type (per health reporter):
|
||||
via ``devlink``, e.g. per error type (per health reporter). Reporters may be
|
||||
registered for the whole devlink instance or for a specific devlink port.
|
||||
|
||||
* Configure reporter's generic parameters (like: disable/enable auto recovery)
|
||||
* Invoke recovery procedure
|
||||
|
||||
@@ -41,6 +41,16 @@ In order for ``driverinit`` parameters to take effect, the driver must
|
||||
support reloading via the ``devlink-reload`` command. This command will
|
||||
request a reload of the device driver.
|
||||
|
||||
Default parameter values
|
||||
=========================
|
||||
|
||||
Drivers may optionally export default values for parameters of cmode
|
||||
``runtime`` and ``permanent``. For ``driverinit`` parameters, the last
|
||||
value set by the driver will be used as the default value. Drivers can
|
||||
also support resetting params with cmode ``runtime`` and ``permanent``
|
||||
to their default values. Resetting ``driverinit`` params is supported
|
||||
by devlink core without additional driver support needed.
|
||||
|
||||
.. _devlink_params_generic:
|
||||
|
||||
Generic configuration parameters
|
||||
@@ -112,7 +122,7 @@ own name.
|
||||
* - ``enable_iwarp``
|
||||
- Boolean
|
||||
- Enable handling of iWARP traffic in the device.
|
||||
* - ``internal_err_reset``
|
||||
* - ``internal_error_reset``
|
||||
- Boolean
|
||||
- When enabled, the device driver will reset the device on internal
|
||||
errors.
|
||||
|
||||
@@ -38,7 +38,7 @@ Devlink port flavours are described below.
|
||||
- This indicates an eswitch port representing a port of PCI
|
||||
subfunction (SF).
|
||||
* - ``DEVLINK_PORT_FLAVOUR_VIRTUAL``
|
||||
- This indicates a virtual port for the PCI virtual function.
|
||||
- Any virtual port facing the user.
|
||||
|
||||
Devlink port can have a different type based on the link layer described below.
|
||||
|
||||
@@ -134,6 +134,9 @@ Users may also set the IPsec crypto capability of the function using
|
||||
Users may also set the IPsec packet capability of the function using
|
||||
`devlink port function set ipsec_packet` command.
|
||||
|
||||
The ``migratable`` attribute may be set only on ports with
|
||||
``DEVLINK_PORT_FLAVOUR_PCI_VF``.
|
||||
|
||||
Users may also set the maximum IO event queues of the function
|
||||
using `devlink port function set max_io_eqs` command.
|
||||
|
||||
|
||||
@@ -74,3 +74,73 @@ attribute, which represents the pending change in size. For example:
|
||||
|
||||
Note that changes in resource size may require a device reload to properly
|
||||
take effect.
|
||||
|
||||
Port-level Resources and Full Dump
|
||||
==================================
|
||||
|
||||
In addition to device-level resources, ``devlink`` also supports port-level
|
||||
resources. These resources are associated with a specific devlink port rather
|
||||
than the device as a whole.
|
||||
|
||||
To list resources for all devlink devices and ports:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$ devlink resource show
|
||||
pci/0000:03:00.0:
|
||||
name max_local_SFs size 128 unit entry dpipe_tables none
|
||||
name max_external_SFs size 128 unit entry dpipe_tables none
|
||||
pci/0000:03:00.0/196608:
|
||||
name max_SFs size 128 unit entry dpipe_tables none
|
||||
pci/0000:03:00.0/196609:
|
||||
name max_SFs size 128 unit entry dpipe_tables none
|
||||
pci/0000:03:00.1:
|
||||
name max_local_SFs size 128 unit entry dpipe_tables none
|
||||
name max_external_SFs size 128 unit entry dpipe_tables none
|
||||
pci/0000:03:00.1/196708:
|
||||
name max_SFs size 128 unit entry dpipe_tables none
|
||||
pci/0000:03:00.1/196709:
|
||||
name max_SFs size 128 unit entry dpipe_tables none
|
||||
|
||||
To show resources for a specific port:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$ devlink resource show pci/0000:03:00.0/196608
|
||||
pci/0000:03:00.0/196608:
|
||||
name max_SFs size 128 unit entry dpipe_tables none
|
||||
|
||||
Resource Scope Filtering
|
||||
========================
|
||||
|
||||
When dumping resources for all devices, ``devlink resource show`` accepts
|
||||
an optional ``scope`` parameter to restrict the response to device-level
|
||||
resources, port-level resources, or both (the default).
|
||||
|
||||
To dump only device-level resources across all devices:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$ devlink resource show scope dev
|
||||
pci/0000:03:00.0:
|
||||
name max_local_SFs size 128 unit entry dpipe_tables none
|
||||
name max_external_SFs size 128 unit entry dpipe_tables none
|
||||
pci/0000:03:00.1:
|
||||
name max_local_SFs size 128 unit entry dpipe_tables none
|
||||
name max_external_SFs size 128 unit entry dpipe_tables none
|
||||
|
||||
To dump only port-level resources across all devices:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$ devlink resource show scope port
|
||||
pci/0000:03:00.0/196608:
|
||||
name max_SFs size 128 unit entry dpipe_tables none
|
||||
pci/0000:03:00.0/196609:
|
||||
name max_SFs size 128 unit entry dpipe_tables none
|
||||
pci/0000:03:00.1/196708:
|
||||
name max_SFs size 128 unit entry dpipe_tables none
|
||||
pci/0000:03:00.1/196709:
|
||||
name max_SFs size 128 unit entry dpipe_tables none
|
||||
|
||||
Note that port-level resources are read-only.
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
========================
|
||||
Devlink Shared Instances
|
||||
========================
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
Shared devlink instances allow multiple physical functions (PFs) on the same
|
||||
chip to share a devlink instance for chip-wide operations.
|
||||
|
||||
Multiple PFs may reside on the same physical chip, running a single firmware.
|
||||
Some of the resources and configurations may be shared among these PFs. The
|
||||
shared devlink instance provides an object to pin configuration knobs on.
|
||||
|
||||
There are two possible usage models:
|
||||
|
||||
1. The shared devlink instance is used alongside individual PF devlink
|
||||
instances, providing chip-wide configuration in addition to per-PF
|
||||
configuration.
|
||||
2. The shared devlink instance is the only devlink instance, without
|
||||
per-PF instances.
|
||||
|
||||
It is up to the driver to decide which usage model to use.
|
||||
|
||||
The shared devlink instance is not backed by any struct *device*.
|
||||
|
||||
Implementation
|
||||
==============
|
||||
|
||||
Architecture
|
||||
------------
|
||||
|
||||
The implementation uses:
|
||||
|
||||
* **Chip identification**: PFs are grouped by chip using a driver-specific identifier
|
||||
* **Shared instance management**: Global list of shared instances with reference counting
|
||||
|
||||
API Functions
|
||||
-------------
|
||||
|
||||
The following functions are provided for managing shared devlink instances:
|
||||
|
||||
* ``devlink_shd_get()``: Get or create a shared devlink instance identified by a string ID
|
||||
* ``devlink_shd_put()``: Release a reference on a shared devlink instance
|
||||
* ``devlink_shd_get_priv()``: Get private data from shared devlink instance
|
||||
|
||||
Initialization Flow
|
||||
-------------------
|
||||
|
||||
1. **PF calls shared devlink init** during driver probe
|
||||
2. **Chip identification** using driver-specific method to determine device identity
|
||||
3. **Get or create shared instance** using ``devlink_shd_get()``:
|
||||
|
||||
* The function looks up existing instance by identifier
|
||||
* If none exists, creates new instance:
|
||||
- Allocates and registers devlink instance
|
||||
- Adds to global shared instances list
|
||||
- Increments reference count
|
||||
|
||||
4. **Set nested devlink instance** for the PF devlink instance using
|
||||
``devl_nested_devlink_set()`` before registering the PF devlink instance
|
||||
|
||||
Cleanup Flow
|
||||
------------
|
||||
|
||||
1. **Cleanup** when PF is removed
|
||||
2. **Call** ``devlink_shd_put()`` to release reference (decrements reference count)
|
||||
3. **Shared instance is automatically destroyed** when the last PF removes (reference count reaches zero)
|
||||
|
||||
Chip Identification
|
||||
-------------------
|
||||
|
||||
PFs belonging to the same chip are identified using a driver-specific method.
|
||||
The driver is free to choose any identifier that is suitable for determining
|
||||
whether two PFs are part of the same device. Examples include:
|
||||
|
||||
* **PCI VPD serial numbers**: Extract from PCI VPD
|
||||
* **Device tree properties**: Read chip identifier from device tree
|
||||
* **Other hardware-specific identifiers**: Any unique identifier that groups PFs by chip
|
||||
|
||||
Locking
|
||||
-------
|
||||
|
||||
A global mutex (``shd_mutex``) protects the shared instances list during registration/deregistration.
|
||||
|
||||
Similarly to other nested devlink instance relationships, devlink lock of
|
||||
the shared instance should be always taken after the devlink lock of PF.
|
||||
|
||||
Reference Counting
|
||||
------------------
|
||||
|
||||
Each shared devlink instance maintains a reference count (``refcount_t refcount``).
|
||||
The reference count is incremented when ``devlink_shd_get()`` is called and decremented
|
||||
when ``devlink_shd_put()`` is called. When the reference count reaches zero, the shared
|
||||
instance is automatically destroyed.
|
||||
@@ -516,9 +516,11 @@ Generic Packet Trap Groups
|
||||
|
||||
Generic packet trap groups are used to aggregate logically related packet
|
||||
traps. These groups allow the user to batch operations such as setting the trap
|
||||
action of all member traps. In addition, ``devlink-trap`` can report aggregated
|
||||
per-group packets and bytes statistics, in case per-trap statistics are too
|
||||
narrow. The description of these groups must be added to the following table:
|
||||
action of all member drop traps whose action may legally change. Exception and
|
||||
control traps remain unchanged. In addition, ``devlink-trap`` can report
|
||||
aggregated per-group packets and bytes statistics, in case per-trap statistics
|
||||
are too narrow. The description of these groups must be added to the following
|
||||
table:
|
||||
|
||||
.. list-table:: List of Generic Packet Trap Groups
|
||||
:widths: 10 90
|
||||
|
||||
@@ -13,8 +13,8 @@ new APIs prefixed by ``devl_*``. The older APIs handle all the locking
|
||||
in devlink core, but don't allow registration of most sub-objects once
|
||||
the main devlink object is itself registered. The newer ``devl_*`` APIs assume
|
||||
the devlink instance lock is already held. Drivers can take the instance
|
||||
lock by calling ``devl_lock()``. It is also held all callbacks of devlink
|
||||
netlink commands.
|
||||
lock by calling ``devl_lock()``. It is also held across all callbacks of
|
||||
devlink netlink commands.
|
||||
|
||||
Drivers are encouraged to use the devlink instance lock for their own needs.
|
||||
|
||||
@@ -33,11 +33,11 @@ sure to respect following rules:
|
||||
lock of both nested and parent instances at the same time, devlink
|
||||
instance lock of the parent instance should be taken first, only then
|
||||
instance lock of the nested instance could be taken.
|
||||
- Driver should use object-specific helpers to setup the
|
||||
nested relationship:
|
||||
- Driver should use object-specific helpers to setup the nested relationship
|
||||
before registering the nested devlink instance:
|
||||
|
||||
- ``devl_nested_devlink_set()`` - called to setup devlink -> nested
|
||||
devlink relationship (could be user for multiple nested instances.
|
||||
devlink relationship (could be used for multiple nested instances).
|
||||
- ``devl_port_fn_devlink_set()`` - called to setup port function ->
|
||||
nested devlink relationship.
|
||||
- ``devlink_linecard_nested_dl_set()`` - called to setup linecard ->
|
||||
@@ -68,6 +68,7 @@ general.
|
||||
devlink-resource
|
||||
devlink-selftests
|
||||
devlink-trap
|
||||
devlink-shared
|
||||
|
||||
Driver-specific documentation
|
||||
-----------------------------
|
||||
@@ -87,6 +88,8 @@ parameters, info versions, and other features it supports.
|
||||
ionic
|
||||
iosm
|
||||
ixgbe
|
||||
kvaser_pciefd
|
||||
kvaser_usb
|
||||
mlx4
|
||||
mlx5
|
||||
mlxsw
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=============================
|
||||
kvaser_pciefd devlink support
|
||||
=============================
|
||||
|
||||
This document describes the devlink features implemented by the
|
||||
``kvaser_pciefd`` device driver.
|
||||
|
||||
Info versions
|
||||
=============
|
||||
|
||||
The ``kvaser_pciefd`` driver reports the following versions
|
||||
|
||||
.. list-table:: devlink info versions implemented
|
||||
:widths: 5 5 90
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Description
|
||||
* - ``fw``
|
||||
- running
|
||||
- Version of the firmware running on the device. Also available
|
||||
through ``ethtool -i`` as ``firmware-version``.
|
||||
@@ -0,0 +1,33 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==========================
|
||||
kvaser_usb devlink support
|
||||
==========================
|
||||
|
||||
This document describes the devlink features implemented by the
|
||||
``kvaser_usb`` device driver.
|
||||
|
||||
Info versions
|
||||
=============
|
||||
|
||||
The ``kvaser_usb`` driver reports the following versions
|
||||
|
||||
.. list-table:: devlink info versions implemented
|
||||
:widths: 5 5 90
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Description
|
||||
* - ``fw``
|
||||
- running
|
||||
- Version of the firmware running on the device. Also available
|
||||
through ``ethtool -i`` as ``firmware-version``.
|
||||
* - ``board.rev``
|
||||
- fixed
|
||||
- The device hardware revision.
|
||||
* - ``board.id``
|
||||
- fixed
|
||||
- The device EAN (product number).
|
||||
* - ``serial_number``
|
||||
- fixed
|
||||
- The device serial number.
|
||||
@@ -24,7 +24,8 @@ static int otx2_cpt_dl_egrp_delete(struct devlink *dl, u32 id,
|
||||
}
|
||||
|
||||
static int otx2_cpt_dl_uc_info(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
ctx->val.vstr[0] = '\0';
|
||||
|
||||
@@ -32,7 +33,8 @@ static int otx2_cpt_dl_uc_info(struct devlink *dl, u32 id,
|
||||
}
|
||||
|
||||
static int otx2_cpt_dl_t106_mode_get(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct otx2_cpt_devlink *cpt_dl = devlink_priv(dl);
|
||||
struct otx2_cptpf_dev *cptpf = cpt_dl->cptpf;
|
||||
|
||||
@@ -315,10 +315,10 @@ EXPORT_SYMBOL_NS_GPL(zl3073x_devm_alloc, "ZL3073X");
|
||||
|
||||
static int
|
||||
zl3073x_devlink_param_clock_id_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (!val.vu64) {
|
||||
if (!val->vu64) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "'clock_id' must be non-zero");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -377,7 +377,7 @@ int zl3073x_devlink_register(struct zl3073x_dev *zldev)
|
||||
value.vu64 = zldev->clock_id;
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_CLOCK_ID,
|
||||
value);
|
||||
&value);
|
||||
|
||||
/* Register devlink instance */
|
||||
devl_register(devlink);
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
#include "ena_phc.h"
|
||||
|
||||
static int ena_devlink_enable_phc_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink);
|
||||
|
||||
if (!val.vbool)
|
||||
if (!val->vbool)
|
||||
return 0;
|
||||
|
||||
if (!ena_com_phc_supported(adapter->ena_dev)) {
|
||||
@@ -57,7 +57,7 @@ void ena_devlink_disable_phc_param(struct devlink *devlink)
|
||||
value.vbool = false;
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC,
|
||||
value);
|
||||
&value);
|
||||
devl_unlock(devlink);
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ static int ena_devlink_configure_params(struct devlink *devlink)
|
||||
value.vbool = ena_phc_is_enabled(adapter);
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC,
|
||||
value);
|
||||
&value);
|
||||
devl_unlock(devlink);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -254,12 +254,13 @@ int pdsc_dl_flash_update(struct devlink *dl,
|
||||
struct devlink_flash_update_params *params,
|
||||
struct netlink_ext_ack *extack);
|
||||
int pdsc_dl_enable_get(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx);
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack);
|
||||
int pdsc_dl_enable_set(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack);
|
||||
int pdsc_dl_enable_validate(struct devlink *dl, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
void __iomem *pdsc_map_dbpage(struct pdsc *pdsc, int page_num);
|
||||
|
||||
@@ -22,7 +22,8 @@ pdsc_viftype *pdsc_dl_find_viftype_by_id(struct pdsc *pdsc,
|
||||
}
|
||||
|
||||
int pdsc_dl_enable_get(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct pdsc *pdsc = devlink_priv(dl);
|
||||
struct pdsc_viftype *vt_entry;
|
||||
@@ -64,7 +65,7 @@ int pdsc_dl_enable_set(struct devlink *dl, u32 id,
|
||||
}
|
||||
|
||||
int pdsc_dl_enable_validate(struct devlink *dl, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct pdsc *pdsc = devlink_priv(dl);
|
||||
|
||||
@@ -1086,7 +1086,8 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
|
||||
}
|
||||
|
||||
static int bnxt_dl_nvm_param_get(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct bnxt *bp = bnxt_get_bp_from_dl(dl);
|
||||
struct hwrm_nvm_get_variable_input *req;
|
||||
@@ -1122,7 +1123,7 @@ static int bnxt_dl_nvm_param_set(struct devlink *dl, u32 id,
|
||||
}
|
||||
|
||||
static int bnxt_dl_roce_validate(struct devlink *dl, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
const struct bnxt_dl_nvm_param nvm_roce_cap = {0, NVM_OFF_RDMA_CAPABLE,
|
||||
@@ -1148,7 +1149,7 @@ static int bnxt_dl_roce_validate(struct devlink *dl, u32 id,
|
||||
}
|
||||
|
||||
static int bnxt_dl_msix_validate(struct devlink *dl, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
int max_val = -1;
|
||||
@@ -1159,7 +1160,7 @@ static int bnxt_dl_msix_validate(struct devlink *dl, u32 id,
|
||||
if (id == DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN)
|
||||
max_val = BNXT_MSIX_VEC_MIN_MAX;
|
||||
|
||||
if (val.vu32 > max_val) {
|
||||
if (val->vu32 > max_val) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "MSIX value is exceeding the range");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1168,7 +1169,8 @@ static int bnxt_dl_msix_validate(struct devlink *dl, u32 id,
|
||||
}
|
||||
|
||||
static int bnxt_remote_dev_reset_get(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct bnxt *bp = bnxt_get_bp_from_dl(dl);
|
||||
|
||||
|
||||
@@ -24,7 +24,8 @@ static int i40e_max_mac_per_vf_set(struct devlink *devlink,
|
||||
|
||||
static int i40e_max_mac_per_vf_get(struct devlink *devlink,
|
||||
u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct i40e_pf *pf = devlink_priv(devlink);
|
||||
|
||||
|
||||
@@ -611,11 +611,13 @@ exit_release_res:
|
||||
* @devlink: pointer to the devlink instance
|
||||
* @id: the parameter ID to set
|
||||
* @ctx: context to store the parameter value
|
||||
* @extack: netlink extended ACK structure
|
||||
*
|
||||
* Return: zero on success and negative value on failure.
|
||||
*/
|
||||
static int ice_devlink_tx_sched_layers_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ice_pf *pf = devlink_priv(devlink);
|
||||
int err;
|
||||
@@ -669,10 +671,10 @@ static int ice_devlink_tx_sched_layers_set(struct devlink *devlink, u32 id,
|
||||
* error.
|
||||
*/
|
||||
static int ice_devlink_tx_sched_layers_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (val.vu8 != ICE_SCHED_5_LAYERS && val.vu8 != ICE_SCHED_9_LAYERS) {
|
||||
if (val->vu8 != ICE_SCHED_5_LAYERS && val->vu8 != ICE_SCHED_9_LAYERS) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Wrong number of tx scheduler layers provided.");
|
||||
return -EINVAL;
|
||||
@@ -1352,7 +1354,8 @@ static const struct devlink_ops ice_sf_devlink_ops;
|
||||
|
||||
static int
|
||||
ice_devlink_enable_roce_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ice_pf *pf = devlink_priv(devlink);
|
||||
struct iidc_rdma_core_dev_info *cdev;
|
||||
@@ -1395,7 +1398,7 @@ static int ice_devlink_enable_roce_set(struct devlink *devlink, u32 id,
|
||||
|
||||
static int
|
||||
ice_devlink_enable_roce_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ice_pf *pf = devlink_priv(devlink);
|
||||
@@ -1418,7 +1421,8 @@ ice_devlink_enable_roce_validate(struct devlink *devlink, u32 id,
|
||||
|
||||
static int
|
||||
ice_devlink_enable_iw_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ice_pf *pf = devlink_priv(devlink);
|
||||
struct iidc_rdma_core_dev_info *cdev;
|
||||
@@ -1461,7 +1465,7 @@ static int ice_devlink_enable_iw_set(struct devlink *devlink, u32 id,
|
||||
|
||||
static int
|
||||
ice_devlink_enable_iw_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ice_pf *pf = devlink_priv(devlink);
|
||||
@@ -1525,11 +1529,13 @@ static int ice_devlink_local_fwd_str_to_mode(const char *mode_str)
|
||||
* @devlink: Pointer to the devlink instance.
|
||||
* @id: The parameter ID to set.
|
||||
* @ctx: Context to store the parameter value.
|
||||
* @extack: netlink extended ACK structure
|
||||
*
|
||||
* Return: Zero.
|
||||
*/
|
||||
static int ice_devlink_local_fwd_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ice_pf *pf = devlink_priv(devlink);
|
||||
struct ice_port_info *pi;
|
||||
@@ -1585,10 +1591,10 @@ static int ice_devlink_local_fwd_set(struct devlink *devlink, u32 id,
|
||||
* error.
|
||||
*/
|
||||
static int ice_devlink_local_fwd_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (ice_devlink_local_fwd_str_to_mode(val.vstr) < 0) {
|
||||
if (ice_devlink_local_fwd_str_to_mode(val->vstr) < 0) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Error: Requested value is not supported.");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1598,12 +1604,12 @@ static int ice_devlink_local_fwd_validate(struct devlink *devlink, u32 id,
|
||||
|
||||
static int
|
||||
ice_devlink_msix_max_pf_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ice_pf *pf = devlink_priv(devlink);
|
||||
|
||||
if (val.vu32 > pf->hw.func_caps.common_cap.num_msix_vectors)
|
||||
if (val->vu32 > pf->hw.func_caps.common_cap.num_msix_vectors)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@@ -1611,21 +1617,21 @@ ice_devlink_msix_max_pf_validate(struct devlink *devlink, u32 id,
|
||||
|
||||
static int
|
||||
ice_devlink_msix_min_pf_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (val.vu32 < ICE_MIN_MSIX)
|
||||
if (val->vu32 < ICE_MIN_MSIX)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ice_devlink_enable_rdma_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ice_pf *pf = devlink_priv(devlink);
|
||||
bool new_state = val.vbool;
|
||||
bool new_state = val->vbool;
|
||||
|
||||
if (new_state && !test_bit(ICE_FLAG_RDMA_ENA, pf->flags))
|
||||
return -EOPNOTSUPP;
|
||||
@@ -1785,16 +1791,16 @@ int ice_devlink_register_params(struct ice_pf *pf)
|
||||
value.vu32 = pf->msix.max;
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
|
||||
value);
|
||||
&value);
|
||||
value.vu32 = pf->msix.min;
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
|
||||
value);
|
||||
&value);
|
||||
|
||||
value.vbool = test_bit(ICE_FLAG_RDMA_ENA, pf->flags);
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA,
|
||||
value);
|
||||
&value);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -1179,12 +1179,12 @@ static void rvu_health_reporters_destroy(struct rvu *rvu)
|
||||
|
||||
/* Devlink Params APIs */
|
||||
static int rvu_af_dl_dwrr_mtu_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
|
||||
struct rvu *rvu = rvu_dl->rvu;
|
||||
int dwrr_mtu = val.vu32;
|
||||
int dwrr_mtu = val->vu32;
|
||||
struct nix_txsch *txsch;
|
||||
struct nix_hw *nix_hw;
|
||||
|
||||
@@ -1233,7 +1233,8 @@ static int rvu_af_dl_dwrr_mtu_set(struct devlink *devlink, u32 id,
|
||||
}
|
||||
|
||||
static int rvu_af_dl_dwrr_mtu_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
|
||||
struct rvu *rvu = rvu_dl->rvu;
|
||||
@@ -1259,7 +1260,8 @@ enum rvu_af_dl_param_id {
|
||||
};
|
||||
|
||||
static int rvu_af_npc_exact_feature_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
|
||||
struct rvu *rvu = rvu_dl->rvu;
|
||||
@@ -1286,14 +1288,14 @@ static int rvu_af_npc_exact_feature_disable(struct devlink *devlink, u32 id,
|
||||
}
|
||||
|
||||
static int rvu_af_npc_exact_feature_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
|
||||
struct rvu *rvu = rvu_dl->rvu;
|
||||
u64 enable;
|
||||
|
||||
if (kstrtoull(val.vstr, 10, &enable)) {
|
||||
if (kstrtoull(val->vstr, 10, &enable)) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Only 1 value is supported");
|
||||
return -EINVAL;
|
||||
@@ -1314,7 +1316,8 @@ static int rvu_af_npc_exact_feature_validate(struct devlink *devlink, u32 id,
|
||||
}
|
||||
|
||||
static int rvu_af_dl_npc_mcam_high_zone_percent_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
|
||||
struct rvu *rvu = rvu_dl->rvu;
|
||||
@@ -1348,7 +1351,7 @@ static int rvu_af_dl_npc_mcam_high_zone_percent_set(struct devlink *devlink, u32
|
||||
}
|
||||
|
||||
static int rvu_af_dl_npc_mcam_high_zone_percent_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
|
||||
@@ -1356,7 +1359,7 @@ static int rvu_af_dl_npc_mcam_high_zone_percent_validate(struct devlink *devlink
|
||||
struct npc_mcam *mcam;
|
||||
|
||||
/* The percent of high prio zone must range from 12% to 100% of unreserved mcam space */
|
||||
if (val.vu8 < 12 || val.vu8 > 100) {
|
||||
if (val->vu8 < 12 || val->vu8 > 100) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"mcam high zone percent must be between 12% to 100%");
|
||||
return -EINVAL;
|
||||
@@ -1376,7 +1379,8 @@ static int rvu_af_dl_npc_mcam_high_zone_percent_validate(struct devlink *devlink
|
||||
}
|
||||
|
||||
static int rvu_af_dl_npc_def_rule_cntr_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
|
||||
struct rvu *rvu = rvu_dl->rvu;
|
||||
@@ -1402,7 +1406,8 @@ static int rvu_af_dl_npc_def_rule_cntr_set(struct devlink *devlink, u32 id,
|
||||
}
|
||||
|
||||
static int rvu_af_dl_nix_maxlf_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
|
||||
struct rvu *rvu = rvu_dl->rvu;
|
||||
@@ -1436,7 +1441,7 @@ static int rvu_af_dl_nix_maxlf_set(struct devlink *devlink, u32 id,
|
||||
}
|
||||
|
||||
static int rvu_af_dl_nix_maxlf_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
|
||||
@@ -1460,13 +1465,13 @@ static int rvu_af_dl_nix_maxlf_validate(struct devlink *devlink, u32 id,
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (max_nix0_lf && val.vu16 > max_nix0_lf) {
|
||||
if (max_nix0_lf && val->vu16 > max_nix0_lf) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"requested nixlf is greater than the max supported nix0_lf");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (max_nix1_lf && val.vu16 > max_nix1_lf) {
|
||||
if (max_nix1_lf && val->vu16 > max_nix1_lf) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"requested nixlf is greater than the max supported nix1_lf");
|
||||
return -EINVAL;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
/* Devlink Params APIs */
|
||||
static int otx2_dl_mcam_count_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct otx2_devlink *otx2_dl = devlink_priv(devlink);
|
||||
@@ -48,7 +48,8 @@ static int otx2_dl_mcam_count_set(struct devlink *devlink, u32 id,
|
||||
}
|
||||
|
||||
static int otx2_dl_mcam_count_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct otx2_devlink *otx2_dl = devlink_priv(devlink);
|
||||
struct otx2_nic *pfvf = otx2_dl->pfvf;
|
||||
@@ -84,7 +85,8 @@ static int otx2_dl_ucast_flt_cnt_set(struct devlink *devlink, u32 id,
|
||||
}
|
||||
|
||||
static int otx2_dl_ucast_flt_cnt_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct otx2_devlink *otx2_dl = devlink_priv(devlink);
|
||||
struct otx2_nic *pfvf = otx2_dl->pfvf;
|
||||
@@ -95,7 +97,7 @@ static int otx2_dl_ucast_flt_cnt_get(struct devlink *devlink, u32 id,
|
||||
}
|
||||
|
||||
static int otx2_dl_ucast_flt_cnt_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct otx2_devlink *otx2_dl = devlink_priv(devlink);
|
||||
|
||||
@@ -172,7 +172,8 @@ MODULE_PARM_DESC(port_type_array, "Array of port types: HW_DEFAULT (0) is defaul
|
||||
static atomic_t pf_loading = ATOMIC_INIT(0);
|
||||
|
||||
static int mlx4_devlink_ierr_reset_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
ctx->val.vbool = !!mlx4_internal_err_reset;
|
||||
return 0;
|
||||
@@ -187,7 +188,8 @@ static int mlx4_devlink_ierr_reset_set(struct devlink *devlink, u32 id,
|
||||
}
|
||||
|
||||
static int mlx4_devlink_crdump_snapshot_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx4_priv *priv = devlink_priv(devlink);
|
||||
struct mlx4_dev *dev = &priv->dev;
|
||||
@@ -209,10 +211,10 @@ static int mlx4_devlink_crdump_snapshot_set(struct devlink *devlink, u32 id,
|
||||
|
||||
static int
|
||||
mlx4_devlink_max_macs_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
u32 value = val.vu32;
|
||||
u32 value = val->vu32;
|
||||
|
||||
if (value < 1 || value > 128)
|
||||
return -ERANGE;
|
||||
@@ -262,27 +264,27 @@ static void mlx4_devlink_set_params_init_values(struct devlink *devlink)
|
||||
value.vbool = !!mlx4_internal_err_reset;
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET,
|
||||
value);
|
||||
&value);
|
||||
|
||||
value.vu32 = 1UL << log_num_mac;
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
|
||||
value);
|
||||
&value);
|
||||
|
||||
value.vbool = enable_64b_cqe_eqe;
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
MLX4_DEVLINK_PARAM_ID_ENABLE_64B_CQE_EQE,
|
||||
value);
|
||||
&value);
|
||||
|
||||
value.vbool = enable_4k_uar;
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
MLX4_DEVLINK_PARAM_ID_ENABLE_4K_UAR,
|
||||
value);
|
||||
&value);
|
||||
|
||||
value.vbool = false;
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT,
|
||||
value);
|
||||
&value);
|
||||
}
|
||||
|
||||
static inline void mlx4_set_num_reserved_uars(struct mlx4_dev *dev,
|
||||
|
||||
@@ -461,11 +461,11 @@ void mlx5_devlink_free(struct devlink *devlink)
|
||||
}
|
||||
|
||||
static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
bool new_state = val.vbool;
|
||||
bool new_state = val->vbool;
|
||||
|
||||
if (new_state && !MLX5_CAP_GEN(dev, roce) &&
|
||||
!(MLX5_CAP_GEN(dev, roce_rw_supported) && MLX5_CAP_GEN_MAX(dev, roce))) {
|
||||
@@ -482,10 +482,10 @@ static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id,
|
||||
|
||||
#ifdef CONFIG_MLX5_ESWITCH
|
||||
static int mlx5_devlink_large_group_num_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
int group_num = val.vu32;
|
||||
int group_num = val->vu32;
|
||||
|
||||
if (group_num < 1 || group_num > 1024) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
@@ -498,27 +498,27 @@ static int mlx5_devlink_large_group_num_validate(struct devlink *devlink, u32 id
|
||||
#endif
|
||||
|
||||
static int mlx5_devlink_eq_depth_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
return (val.vu32 >= 64 && val.vu32 <= 4096) ? 0 : -EINVAL;
|
||||
return (val->vu32 >= 64 && val->vu32 <= 4096) ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
mlx5_devlink_hairpin_num_queues_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
return val.vu32 ? 0 : -EINVAL;
|
||||
return val->vu32 ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
mlx5_devlink_hairpin_queue_size_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
u32 val32 = val.vu32;
|
||||
u32 val32 = val->vu32;
|
||||
|
||||
if (!is_power_of_2(val32)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Value is not power of two");
|
||||
@@ -550,13 +550,13 @@ static void mlx5_devlink_hairpin_params_init_values(struct devlink *devlink)
|
||||
|
||||
value.vu32 = link_speed64;
|
||||
devl_param_driverinit_value_set(
|
||||
devlink, MLX5_DEVLINK_PARAM_ID_HAIRPIN_NUM_QUEUES, value);
|
||||
devlink, MLX5_DEVLINK_PARAM_ID_HAIRPIN_NUM_QUEUES, &value);
|
||||
|
||||
value.vu32 =
|
||||
BIT(min_t(u32, 16 - MLX5_MPWRQ_MIN_LOG_STRIDE_SZ(dev),
|
||||
MLX5_CAP_GEN(dev, log_max_hairpin_num_packets)));
|
||||
devl_param_driverinit_value_set(
|
||||
devlink, MLX5_DEVLINK_PARAM_ID_HAIRPIN_QUEUE_SIZE, value);
|
||||
devlink, MLX5_DEVLINK_PARAM_ID_HAIRPIN_QUEUE_SIZE, &value);
|
||||
}
|
||||
|
||||
static const struct devlink_param mlx5_devlink_params[] = {
|
||||
@@ -583,24 +583,24 @@ static void mlx5_devlink_set_params_init_values(struct devlink *devlink)
|
||||
value.vbool = MLX5_CAP_GEN(dev, roce) && !mlx5_dev_is_lightweight(dev);
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
|
||||
value);
|
||||
&value);
|
||||
|
||||
#ifdef CONFIG_MLX5_ESWITCH
|
||||
value.vu32 = ESW_OFFLOADS_DEFAULT_NUM_GROUPS;
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
|
||||
value);
|
||||
&value);
|
||||
#endif
|
||||
|
||||
value.vu32 = MLX5_COMP_EQ_SIZE;
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_IO_EQ_SIZE,
|
||||
value);
|
||||
&value);
|
||||
|
||||
value.vu32 = MLX5_NUM_ASYNC_EQE;
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_EVENT_EQ_SIZE,
|
||||
value);
|
||||
&value);
|
||||
}
|
||||
|
||||
static const struct devlink_param mlx5_devlink_eth_params[] = {
|
||||
@@ -633,7 +633,7 @@ static int mlx5_devlink_eth_params_register(struct devlink *devlink)
|
||||
value.vbool = !mlx5_dev_is_lightweight(dev);
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH,
|
||||
value);
|
||||
&value);
|
||||
|
||||
mlx5_devlink_hairpin_params_init_values(devlink);
|
||||
|
||||
@@ -657,12 +657,12 @@ static void mlx5_devlink_eth_params_unregister(struct devlink *devlink)
|
||||
|
||||
static int
|
||||
mlx5_devlink_pcie_cong_thresh_validate(struct devlink *devl, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (val.vu16 > MLX5_PCIE_CONG_THRESH_MAX) {
|
||||
if (val->vu16 > MLX5_PCIE_CONG_THRESH_MAX) {
|
||||
NL_SET_ERR_MSG_FMT_MOD(extack, "Value %u > max supported (%u)",
|
||||
val.vu16, MLX5_PCIE_CONG_THRESH_MAX);
|
||||
val->vu16, MLX5_PCIE_CONG_THRESH_MAX);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -687,19 +687,19 @@ static void mlx5_devlink_pcie_cong_init_values(struct devlink *devlink)
|
||||
|
||||
value.vu16 = MLX5_PCIE_CONG_THRESH_DEF_LOW;
|
||||
id = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_LOW;
|
||||
devl_param_driverinit_value_set(devlink, id, value);
|
||||
devl_param_driverinit_value_set(devlink, id, &value);
|
||||
|
||||
value.vu16 = MLX5_PCIE_CONG_THRESH_DEF_HIGH;
|
||||
id = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_HIGH;
|
||||
devl_param_driverinit_value_set(devlink, id, value);
|
||||
devl_param_driverinit_value_set(devlink, id, &value);
|
||||
|
||||
value.vu16 = MLX5_PCIE_CONG_THRESH_DEF_LOW;
|
||||
id = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_LOW;
|
||||
devl_param_driverinit_value_set(devlink, id, value);
|
||||
devl_param_driverinit_value_set(devlink, id, &value);
|
||||
|
||||
value.vu16 = MLX5_PCIE_CONG_THRESH_DEF_HIGH;
|
||||
id = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_HIGH;
|
||||
devl_param_driverinit_value_set(devlink, id, value);
|
||||
devl_param_driverinit_value_set(devlink, id, &value);
|
||||
}
|
||||
|
||||
static const struct devlink_param mlx5_devlink_pcie_cong_params[] = {
|
||||
@@ -751,11 +751,11 @@ static void mlx5_devlink_pcie_cong_params_unregister(struct devlink *devlink)
|
||||
}
|
||||
|
||||
static int mlx5_devlink_enable_rdma_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
bool new_state = val.vbool;
|
||||
bool new_state = val->vbool;
|
||||
|
||||
if (new_state && !mlx5_rdma_supported(dev))
|
||||
return -EOPNOTSUPP;
|
||||
@@ -784,7 +784,7 @@ static int mlx5_devlink_rdma_params_register(struct devlink *devlink)
|
||||
value.vbool = !mlx5_dev_is_lightweight(dev);
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA,
|
||||
value);
|
||||
&value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -819,7 +819,7 @@ static int mlx5_devlink_vnet_params_register(struct devlink *devlink)
|
||||
value.vbool = !mlx5_dev_is_lightweight(dev);
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET,
|
||||
value);
|
||||
&value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -866,22 +866,22 @@ static void mlx5_devlink_auxdev_params_unregister(struct devlink *devlink)
|
||||
}
|
||||
|
||||
static int mlx5_devlink_max_uc_list_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
|
||||
if (val.vu32 == 0) {
|
||||
if (val->vu32 == 0) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "max_macs value must be greater than 0");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!is_power_of_2(val.vu32)) {
|
||||
if (!is_power_of_2(val->vu32)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Only power of 2 values are supported for max_macs");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ilog2(val.vu32) >
|
||||
if (ilog2(val->vu32) >
|
||||
MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "max_macs value is out of the supported range");
|
||||
return -EINVAL;
|
||||
@@ -912,7 +912,7 @@ static int mlx5_devlink_max_uc_list_params_register(struct devlink *devlink)
|
||||
value.vu32 = 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list);
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
|
||||
value);
|
||||
&value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1962,7 +1962,8 @@ static int mlx5_devlink_esw_multiport_set(struct devlink *devlink, u32 id,
|
||||
}
|
||||
|
||||
static int mlx5_devlink_esw_multiport_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
|
||||
|
||||
@@ -2619,7 +2619,8 @@ done:
|
||||
}
|
||||
|
||||
static int esw_port_metadata_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
|
||||
@@ -2628,7 +2629,7 @@ static int esw_port_metadata_get(struct devlink *devlink, u32 id,
|
||||
}
|
||||
|
||||
static int esw_port_metadata_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
|
||||
@@ -3772,11 +3772,11 @@ cleanup:
|
||||
}
|
||||
|
||||
static int mlx5_fs_mode_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
char *value = val.vstr;
|
||||
char *value = val->vstr;
|
||||
u8 eswitch_mode;
|
||||
|
||||
eswitch_mode = mlx5_eswitch_mode(dev);
|
||||
@@ -3833,7 +3833,8 @@ static int mlx5_fs_mode_set(struct devlink *devlink, u32 id,
|
||||
}
|
||||
|
||||
static int mlx5_fs_mode_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
|
||||
|
||||
@@ -74,7 +74,8 @@ static int mlx5_fw_reset_enable_remote_dev_reset_set(struct devlink *devlink, u3
|
||||
}
|
||||
|
||||
static int mlx5_fw_reset_enable_remote_dev_reset_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
struct mlx5_fw_reset *fw_reset;
|
||||
|
||||
@@ -200,7 +200,8 @@ static const char *const
|
||||
|
||||
static int
|
||||
mlx5_nv_param_devlink_cqe_compress_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
|
||||
@@ -224,13 +225,13 @@ mlx5_nv_param_devlink_cqe_compress_get(struct devlink *devlink, u32 id,
|
||||
|
||||
static int
|
||||
mlx5_nv_param_devlink_cqe_compress_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cqe_compress_str); i++) {
|
||||
if (!strcmp(val.vstr, cqe_compress_str[i]))
|
||||
if (!strcmp(val->vstr, cqe_compress_str[i]))
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -302,7 +303,8 @@ static int mlx5_nv_param_read_per_host_pf_conf(struct mlx5_core_dev *dev,
|
||||
}
|
||||
|
||||
static int mlx5_devlink_enable_sriov_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
|
||||
@@ -413,7 +415,8 @@ static int mlx5_devlink_enable_sriov_set(struct devlink *devlink, u32 id,
|
||||
}
|
||||
|
||||
static int mlx5_devlink_total_vfs_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
|
||||
@@ -503,7 +506,7 @@ static int mlx5_devlink_total_vfs_set(struct devlink *devlink, u32 id,
|
||||
}
|
||||
|
||||
static int mlx5_devlink_total_vfs_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
@@ -522,7 +525,7 @@ static int mlx5_devlink_total_vfs_validate(struct devlink *devlink, u32 id,
|
||||
return 0; /* optimistic, but set might fail later */
|
||||
|
||||
max = MLX5_GET(nv_global_pci_cap, data, max_vfs_per_pf);
|
||||
if (val.vu16 > max) {
|
||||
if (val->vu16 > max) {
|
||||
NL_SET_ERR_MSG_FMT_MOD(extack,
|
||||
"Max allowed by device is %u", max);
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1306,11 +1306,11 @@ static int mlxsw_core_fw_flash_update(struct mlxsw_core *mlxsw_core,
|
||||
}
|
||||
|
||||
static int mlxsw_core_devlink_param_fw_load_policy_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (val.vu8 != DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER &&
|
||||
val.vu8 != DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH) {
|
||||
if (val->vu8 != DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER &&
|
||||
val->vu8 != DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "'fw_load_policy' must be 'driver' or 'flash'");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1337,7 +1337,7 @@ static int mlxsw_core_fw_params_register(struct mlxsw_core *mlxsw_core)
|
||||
value.vu8 = DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER;
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY,
|
||||
value);
|
||||
&value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1489,7 +1489,8 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
|
||||
|
||||
static int
|
||||
mlxsw_sp_acl_tcam_region_rehash_intrvl_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
|
||||
struct mlxsw_sp_acl_tcam *tcam;
|
||||
|
||||
@@ -81,7 +81,8 @@ static const struct nfp_devlink_param_u8_arg nfp_devlink_u8_args[] = {
|
||||
|
||||
static int
|
||||
nfp_devlink_param_u8_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
const struct nfp_devlink_param_u8_arg *arg;
|
||||
struct nfp_pf *pf = devlink_priv(devlink);
|
||||
@@ -169,7 +170,7 @@ exit_close_nsp:
|
||||
|
||||
static int
|
||||
nfp_devlink_param_u8_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
const struct nfp_devlink_param_u8_arg *arg;
|
||||
@@ -179,12 +180,12 @@ nfp_devlink_param_u8_validate(struct devlink *devlink, u32 id,
|
||||
|
||||
arg = &nfp_devlink_u8_args[id];
|
||||
|
||||
if (val.vu8 > arg->max_dl_val) {
|
||||
if (val->vu8 > arg->max_dl_val) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "parameter out of range");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (val.vu8 == arg->invalid_dl_val) {
|
||||
if (val->vu8 == arg->invalid_dl_val) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "unknown/invalid value specified");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -121,7 +121,8 @@ void qed_fw_reporters_destroy(struct devlink *devlink)
|
||||
}
|
||||
|
||||
static int qed_dl_param_get(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct qed_devlink *qed_dl = devlink_priv(dl);
|
||||
struct qed_dev *cdev;
|
||||
|
||||
@@ -3042,7 +3042,8 @@ static void am65_cpsw_init_host_port_emac(struct am65_cpsw_common *common)
|
||||
}
|
||||
|
||||
static int am65_cpsw_dl_switch_mode_get(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct am65_cpsw_devlink *dl_priv = devlink_priv(dl);
|
||||
struct am65_cpsw_common *common = dl_priv->common;
|
||||
|
||||
@@ -1610,7 +1610,8 @@ static const struct devlink_ops cpsw_devlink_ops = {
|
||||
};
|
||||
|
||||
static int cpsw_dl_switch_mode_get(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct cpsw_devlink *dl_priv = devlink_priv(dl);
|
||||
struct cpsw_common *cpsw = dl_priv->cpsw;
|
||||
@@ -1745,7 +1746,8 @@ exit:
|
||||
}
|
||||
|
||||
static int cpsw_dl_ale_ctrl_get(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct cpsw_devlink *dl_priv = devlink_priv(dl);
|
||||
struct cpsw_common *cpsw = dl_priv->cpsw;
|
||||
|
||||
@@ -320,6 +320,8 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev)
|
||||
&nsim_dev->max_macs);
|
||||
debugfs_create_bool("test1", 0600, nsim_dev->ddir,
|
||||
&nsim_dev->test1);
|
||||
debugfs_create_u32("test2", 0600, nsim_dev->ddir,
|
||||
&nsim_dev->test2);
|
||||
nsim_dev->take_snapshot = debugfs_create_file("take_snapshot",
|
||||
0200,
|
||||
nsim_dev->ddir,
|
||||
@@ -521,8 +523,53 @@ err_out:
|
||||
enum nsim_devlink_param_id {
|
||||
NSIM_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
|
||||
NSIM_DEVLINK_PARAM_ID_TEST1,
|
||||
NSIM_DEVLINK_PARAM_ID_TEST2,
|
||||
};
|
||||
|
||||
static int
|
||||
nsim_devlink_param_test2_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct nsim_dev *nsim_dev = devlink_priv(devlink);
|
||||
|
||||
ctx->val.vu32 = nsim_dev->test2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nsim_devlink_param_test2_set(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct nsim_dev *nsim_dev = devlink_priv(devlink);
|
||||
|
||||
nsim_dev->test2 = ctx->val.vu32;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define NSIM_DEV_TEST2_DEFAULT 1234
|
||||
|
||||
static int
|
||||
nsim_devlink_param_test2_get_default(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
ctx->val.vu32 = NSIM_DEV_TEST2_DEFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nsim_devlink_param_test2_reset_default(struct devlink *devlink, u32 id,
|
||||
enum devlink_param_cmode cmode,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct nsim_dev *nsim_dev = devlink_priv(devlink);
|
||||
|
||||
nsim_dev->test2 = NSIM_DEV_TEST2_DEFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct devlink_param nsim_devlink_params[] = {
|
||||
DEVLINK_PARAM_GENERIC(MAX_MACS,
|
||||
BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
|
||||
@@ -531,6 +578,14 @@ static const struct devlink_param nsim_devlink_params[] = {
|
||||
"test1", DEVLINK_PARAM_TYPE_BOOL,
|
||||
BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
|
||||
NULL, NULL, NULL),
|
||||
DEVLINK_PARAM_DRIVER_WITH_DEFAULTS(NSIM_DEVLINK_PARAM_ID_TEST2,
|
||||
"test2", DEVLINK_PARAM_TYPE_U32,
|
||||
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
|
||||
nsim_devlink_param_test2_get,
|
||||
nsim_devlink_param_test2_set,
|
||||
NULL,
|
||||
nsim_devlink_param_test2_get_default,
|
||||
nsim_devlink_param_test2_reset_default),
|
||||
};
|
||||
|
||||
static void nsim_devlink_set_params_init_values(struct nsim_dev *nsim_dev,
|
||||
@@ -541,11 +596,11 @@ static void nsim_devlink_set_params_init_values(struct nsim_dev *nsim_dev,
|
||||
value.vu32 = nsim_dev->max_macs;
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
|
||||
value);
|
||||
&value);
|
||||
value.vbool = nsim_dev->test1;
|
||||
devl_param_driverinit_value_set(devlink,
|
||||
NSIM_DEVLINK_PARAM_ID_TEST1,
|
||||
value);
|
||||
&value);
|
||||
}
|
||||
|
||||
static void nsim_devlink_param_load_driverinit_values(struct devlink *devlink)
|
||||
@@ -1431,9 +1486,25 @@ static int __nsim_dev_port_add(struct nsim_dev *nsim_dev, enum nsim_dev_port_typ
|
||||
if (err)
|
||||
goto err_port_free;
|
||||
|
||||
if (nsim_dev_port_is_pf(nsim_dev_port)) {
|
||||
u64 parent_id = DEVLINK_RESOURCE_ID_PARENT_TOP;
|
||||
struct devlink_resource_size_params params = {
|
||||
.size_max = 100,
|
||||
.size_granularity = 1,
|
||||
.unit = DEVLINK_RESOURCE_UNIT_ENTRY
|
||||
};
|
||||
|
||||
err = devl_port_resource_register(devlink_port,
|
||||
"test_resource", 20,
|
||||
NSIM_PORT_RESOURCE_TEST,
|
||||
parent_id, ¶ms);
|
||||
if (err)
|
||||
goto err_dl_port_unregister;
|
||||
}
|
||||
|
||||
err = nsim_dev_port_debugfs_init(nsim_dev, nsim_dev_port);
|
||||
if (err)
|
||||
goto err_dl_port_unregister;
|
||||
goto err_port_resource_unregister;
|
||||
|
||||
nsim_dev_port->ns = nsim_create(nsim_dev, nsim_dev_port);
|
||||
if (IS_ERR(nsim_dev_port->ns)) {
|
||||
@@ -1456,6 +1527,9 @@ err_nsim_destroy:
|
||||
nsim_destroy(nsim_dev_port->ns);
|
||||
err_port_debugfs_exit:
|
||||
nsim_dev_port_debugfs_exit(nsim_dev_port);
|
||||
err_port_resource_unregister:
|
||||
if (nsim_dev_port_is_pf(nsim_dev_port))
|
||||
devl_port_resources_unregister(devlink_port);
|
||||
err_dl_port_unregister:
|
||||
devl_port_unregister(devlink_port);
|
||||
err_port_free:
|
||||
@@ -1472,6 +1546,8 @@ static void __nsim_dev_port_del(struct nsim_dev_port *nsim_dev_port)
|
||||
devl_rate_leaf_destroy(&nsim_dev_port->devlink_port);
|
||||
nsim_destroy(nsim_dev_port->ns);
|
||||
nsim_dev_port_debugfs_exit(nsim_dev_port);
|
||||
if (nsim_dev_port_is_pf(nsim_dev_port))
|
||||
devl_port_resources_unregister(devlink_port);
|
||||
devl_port_unregister(devlink_port);
|
||||
kfree(nsim_dev_port);
|
||||
}
|
||||
@@ -1590,6 +1666,7 @@ int nsim_drv_probe(struct nsim_bus_dev *nsim_bus_dev)
|
||||
nsim_dev->fw_update_flash_chunk_time_ms = NSIM_DEV_FLASH_CHUNK_TIME_MS_DEFAULT;
|
||||
nsim_dev->max_macs = NSIM_DEV_MAX_MACS_DEFAULT;
|
||||
nsim_dev->test1 = NSIM_DEV_TEST1_DEFAULT;
|
||||
nsim_dev->test2 = NSIM_DEV_TEST2_DEFAULT;
|
||||
spin_lock_init(&nsim_dev->fa_cookie_lock);
|
||||
|
||||
dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev);
|
||||
|
||||
@@ -213,6 +213,10 @@ enum nsim_resource_id {
|
||||
NSIM_RESOURCE_NEXTHOPS,
|
||||
};
|
||||
|
||||
enum nsim_port_resource_id {
|
||||
NSIM_PORT_RESOURCE_TEST = 1,
|
||||
};
|
||||
|
||||
struct nsim_dev_health {
|
||||
struct devlink_health_reporter *empty_reporter;
|
||||
struct devlink_health_reporter *dummy_reporter;
|
||||
@@ -320,6 +324,7 @@ struct nsim_dev {
|
||||
u32 fw_update_flash_chunk_time_ms;
|
||||
u32 max_macs;
|
||||
bool test1;
|
||||
u32 test2;
|
||||
bool dont_allow_reload;
|
||||
bool fail_reload;
|
||||
struct devlink_region *dummy_region;
|
||||
|
||||
@@ -21,7 +21,8 @@ static struct iosm_coredump_file_info list[IOSM_NOF_CD_REGION] = {
|
||||
|
||||
/* Get the param values for the specific param ID's */
|
||||
static int ipc_devlink_get_param(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct iosm_devlink *ipc_devlink = devlink_priv(dl);
|
||||
|
||||
|
||||
+73
-4
@@ -131,6 +131,7 @@ struct devlink_rate {
|
||||
struct devlink_port {
|
||||
struct list_head list;
|
||||
struct list_head region_list;
|
||||
struct list_head resource_list;
|
||||
struct devlink *devlink;
|
||||
const struct devlink_port_ops *ops;
|
||||
unsigned int index;
|
||||
@@ -457,6 +458,13 @@ enum devlink_param_type {
|
||||
DEVLINK_PARAM_TYPE_U64 = DEVLINK_VAR_ATTR_TYPE_U64,
|
||||
DEVLINK_PARAM_TYPE_STRING = DEVLINK_VAR_ATTR_TYPE_STRING,
|
||||
DEVLINK_PARAM_TYPE_BOOL = DEVLINK_VAR_ATTR_TYPE_FLAG,
|
||||
DEVLINK_PARAM_TYPE_U64_ARRAY = DEVLINK_VAR_ATTR_TYPE_U64_ARRAY,
|
||||
};
|
||||
|
||||
#define __DEVLINK_PARAM_MAX_ARRAY_SIZE 32
|
||||
struct devlink_param_u64_array {
|
||||
u64 size;
|
||||
u64 val[__DEVLINK_PARAM_MAX_ARRAY_SIZE];
|
||||
};
|
||||
|
||||
union devlink_param_value {
|
||||
@@ -466,6 +474,7 @@ union devlink_param_value {
|
||||
u64 vu64;
|
||||
char vstr[__DEVLINK_PARAM_MAX_STRING_VALUE];
|
||||
bool vbool;
|
||||
struct devlink_param_u64_array u64arr;
|
||||
};
|
||||
|
||||
struct devlink_param_gset_ctx {
|
||||
@@ -504,6 +513,10 @@ struct devlink_flash_notify {
|
||||
* @set: set parameter value, used for runtime and permanent
|
||||
* configuration modes
|
||||
* @validate: validate input value is applicable (within value range, etc.)
|
||||
* @get_default: get parameter default value, used for runtime and permanent
|
||||
* configuration modes
|
||||
* @reset_default: reset parameter to default value, used for runtime and permanent
|
||||
* configuration modes
|
||||
*
|
||||
* This struct should be used by the driver to fill the data for
|
||||
* a parameter it registers.
|
||||
@@ -515,13 +528,20 @@ struct devlink_param {
|
||||
enum devlink_param_type type;
|
||||
unsigned long supported_cmodes;
|
||||
int (*get)(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx);
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack);
|
||||
int (*set)(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack);
|
||||
int (*validate)(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
union devlink_param_value *val,
|
||||
struct netlink_ext_ack *extack);
|
||||
int (*get_default)(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack);
|
||||
int (*reset_default)(struct devlink *devlink, u32 id,
|
||||
enum devlink_param_cmode cmode,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
RH_KABI_RESERVE(1)
|
||||
RH_KABI_RESERVE(2)
|
||||
@@ -536,6 +556,7 @@ struct devlink_param_item {
|
||||
* until reload.
|
||||
*/
|
||||
bool driverinit_value_new_valid;
|
||||
union devlink_param_value driverinit_default;
|
||||
};
|
||||
|
||||
enum devlink_param_generic_id {
|
||||
@@ -657,6 +678,37 @@ enum devlink_param_generic_id {
|
||||
.validate = _validate, \
|
||||
}
|
||||
|
||||
#define DEVLINK_PARAM_GENERIC_WITH_DEFAULTS(_id, _cmodes, _get, _set, \
|
||||
_validate, _get_default, \
|
||||
_reset_default) \
|
||||
{ \
|
||||
.id = DEVLINK_PARAM_GENERIC_ID_##_id, \
|
||||
.name = DEVLINK_PARAM_GENERIC_##_id##_NAME, \
|
||||
.type = DEVLINK_PARAM_GENERIC_##_id##_TYPE, \
|
||||
.generic = true, \
|
||||
.supported_cmodes = _cmodes, \
|
||||
.get = _get, \
|
||||
.set = _set, \
|
||||
.validate = _validate, \
|
||||
.get_default = _get_default, \
|
||||
.reset_default = _reset_default, \
|
||||
}
|
||||
|
||||
#define DEVLINK_PARAM_DRIVER_WITH_DEFAULTS(_id, _name, _type, _cmodes, \
|
||||
_get, _set, _validate, \
|
||||
_get_default, _reset_default) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.type = _type, \
|
||||
.supported_cmodes = _cmodes, \
|
||||
.get = _get, \
|
||||
.set = _set, \
|
||||
.validate = _validate, \
|
||||
.get_default = _get_default, \
|
||||
.reset_default = _reset_default, \
|
||||
}
|
||||
|
||||
/* Identifier of board design */
|
||||
#define DEVLINK_INFO_VERSION_GENERIC_BOARD_ID "board.id"
|
||||
/* Revision of board design */
|
||||
@@ -1614,6 +1666,9 @@ struct devlink_ops {
|
||||
void *devlink_priv(struct devlink *devlink);
|
||||
struct devlink *priv_to_devlink(void *priv);
|
||||
struct device *devlink_to_dev(const struct devlink *devlink);
|
||||
const char *devlink_bus_name(const struct devlink *devlink);
|
||||
const char *devlink_dev_name(const struct devlink *devlink);
|
||||
const char *devlink_dev_driver_name(const struct devlink *devlink);
|
||||
|
||||
/* Devlink instance explicit locking */
|
||||
void devl_lock(struct devlink *devlink);
|
||||
@@ -1647,6 +1702,13 @@ void devlink_register(struct devlink *devlink);
|
||||
void devlink_unregister(struct devlink *devlink);
|
||||
void devlink_free(struct devlink *devlink);
|
||||
|
||||
struct devlink *devlink_shd_get(const char *id,
|
||||
const struct devlink_ops *ops,
|
||||
size_t priv_size,
|
||||
const struct device_driver *driver);
|
||||
void devlink_shd_put(struct devlink *devlink);
|
||||
void *devlink_shd_get_priv(struct devlink *devlink);
|
||||
|
||||
/**
|
||||
* struct devlink_port_ops - Port operations
|
||||
* @port_split: Callback used to split the port into multiple ones.
|
||||
@@ -1887,12 +1949,19 @@ int devl_resource_register(struct devlink *devlink,
|
||||
u64 resource_size,
|
||||
u64 resource_id,
|
||||
u64 parent_resource_id,
|
||||
const struct devlink_resource_size_params *size_params);
|
||||
const struct devlink_resource_size_params *params);
|
||||
void devl_resources_unregister(struct devlink *devlink);
|
||||
void devlink_resources_unregister(struct devlink *devlink);
|
||||
int devl_resource_size_get(struct devlink *devlink,
|
||||
u64 resource_id,
|
||||
u64 *p_resource_size);
|
||||
int
|
||||
devl_port_resource_register(struct devlink_port *devlink_port,
|
||||
const char *resource_name,
|
||||
u64 resource_size, u64 resource_id,
|
||||
u64 parent_resource_id,
|
||||
const struct devlink_resource_size_params *params);
|
||||
void devl_port_resources_unregister(struct devlink_port *devlink_port);
|
||||
int devl_dpipe_table_resource_set(struct devlink *devlink,
|
||||
const char *table_name, u64 resource_id,
|
||||
u64 resource_units);
|
||||
@@ -1917,7 +1986,7 @@ void devlink_params_unregister(struct devlink *devlink,
|
||||
int devl_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
|
||||
union devlink_param_value *val);
|
||||
void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
|
||||
union devlink_param_value init_val);
|
||||
union devlink_param_value *init_val);
|
||||
void devl_param_value_changed(struct devlink *devlink, u32 param_id);
|
||||
struct devlink_region *devl_region_create(struct devlink *devlink,
|
||||
const struct devlink_region_ops *ops,
|
||||
|
||||
+2
-1
@@ -1258,7 +1258,8 @@ struct dsa_switch_ops {
|
||||
dsa_devlink_param_get, dsa_devlink_param_set, NULL)
|
||||
|
||||
int dsa_devlink_param_get(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx);
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack);
|
||||
int dsa_devlink_param_set(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
@@ -21,9 +21,9 @@ TRACE_EVENT(devlink_hwmsg,
|
||||
TP_ARGS(devlink, incoming, type, buf, len),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(bus_name, devlink_to_dev(devlink)->bus->name)
|
||||
__string(dev_name, dev_name(devlink_to_dev(devlink)))
|
||||
__string(driver_name, devlink_to_dev(devlink)->driver->name)
|
||||
__string(bus_name, devlink_bus_name(devlink))
|
||||
__string(dev_name, devlink_dev_name(devlink))
|
||||
__string(driver_name, devlink_dev_driver_name(devlink))
|
||||
__field(bool, incoming)
|
||||
__field(unsigned long, type)
|
||||
__dynamic_array(u8, buf, len)
|
||||
@@ -55,9 +55,9 @@ TRACE_EVENT(devlink_hwerr,
|
||||
TP_ARGS(devlink, err, msg),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(bus_name, devlink_to_dev(devlink)->bus->name)
|
||||
__string(dev_name, dev_name(devlink_to_dev(devlink)))
|
||||
__string(driver_name, devlink_to_dev(devlink)->driver->name)
|
||||
__string(bus_name, devlink_bus_name(devlink))
|
||||
__string(dev_name, devlink_dev_name(devlink))
|
||||
__string(driver_name, devlink_dev_driver_name(devlink))
|
||||
__field(int, err)
|
||||
__string(msg, msg)
|
||||
),
|
||||
@@ -85,9 +85,9 @@ TRACE_EVENT(devlink_health_report,
|
||||
TP_ARGS(devlink, reporter_name, msg),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(bus_name, devlink_to_dev(devlink)->bus->name)
|
||||
__string(dev_name, dev_name(devlink_to_dev(devlink)))
|
||||
__string(driver_name, devlink_to_dev(devlink)->driver->name)
|
||||
__string(bus_name, devlink_bus_name(devlink))
|
||||
__string(dev_name, devlink_dev_name(devlink))
|
||||
__string(driver_name, devlink_dev_driver_name(devlink))
|
||||
__string(reporter_name, reporter_name)
|
||||
__string(msg, msg)
|
||||
),
|
||||
@@ -116,9 +116,9 @@ TRACE_EVENT(devlink_health_recover_aborted,
|
||||
TP_ARGS(devlink, reporter_name, health_state, time_since_last_recover),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(bus_name, devlink_to_dev(devlink)->bus->name)
|
||||
__string(dev_name, dev_name(devlink_to_dev(devlink)))
|
||||
__string(driver_name, devlink_to_dev(devlink)->driver->name)
|
||||
__string(bus_name, devlink_bus_name(devlink))
|
||||
__string(dev_name, devlink_dev_name(devlink))
|
||||
__string(driver_name, devlink_dev_driver_name(devlink))
|
||||
__string(reporter_name, reporter_name)
|
||||
__field(bool, health_state)
|
||||
__field(u64, time_since_last_recover)
|
||||
@@ -150,9 +150,9 @@ TRACE_EVENT(devlink_health_reporter_state_update,
|
||||
TP_ARGS(devlink, reporter_name, new_state),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(bus_name, devlink_to_dev(devlink)->bus->name)
|
||||
__string(dev_name, dev_name(devlink_to_dev(devlink)))
|
||||
__string(driver_name, devlink_to_dev(devlink)->driver->name)
|
||||
__string(bus_name, devlink_bus_name(devlink))
|
||||
__string(dev_name, devlink_dev_name(devlink))
|
||||
__string(driver_name, devlink_dev_driver_name(devlink))
|
||||
__string(reporter_name, reporter_name)
|
||||
__field(u8, new_state)
|
||||
),
|
||||
@@ -181,9 +181,9 @@ TRACE_EVENT(devlink_trap_report,
|
||||
TP_ARGS(devlink, skb, metadata),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(bus_name, devlink_to_dev(devlink)->bus->name)
|
||||
__string(dev_name, dev_name(devlink_to_dev(devlink)))
|
||||
__string(driver_name, devlink_to_dev(devlink)->driver->name)
|
||||
__string(bus_name, devlink_bus_name(devlink))
|
||||
__string(dev_name, devlink_dev_name(devlink))
|
||||
__string(driver_name, devlink_dev_driver_name(devlink))
|
||||
__string(trap_name, metadata->trap_name)
|
||||
__string(trap_group_name, metadata->trap_group_name)
|
||||
__array(char, input_dev_name, IFNAMSIZ)
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#define DEVLINK_GENL_VERSION 0x1
|
||||
#define DEVLINK_GENL_MCGRP_CONFIG_NAME "config"
|
||||
|
||||
#define DEVLINK_INDEX_BUS_NAME "devlink_index"
|
||||
|
||||
enum devlink_command {
|
||||
/* don't change the order or add anything between, this is ABI! */
|
||||
DEVLINK_CMD_UNSPEC,
|
||||
@@ -404,6 +406,7 @@ enum devlink_var_attr_type {
|
||||
DEVLINK_VAR_ATTR_TYPE_BINARY,
|
||||
__DEVLINK_VAR_ATTR_TYPE_CUSTOM_BASE = 0x80,
|
||||
/* Any possible custom types, unrelated to NLA_* values go below */
|
||||
DEVLINK_VAR_ATTR_TYPE_U64_ARRAY,
|
||||
};
|
||||
|
||||
enum devlink_attr {
|
||||
@@ -639,6 +642,12 @@ enum devlink_attr {
|
||||
|
||||
DEVLINK_ATTR_HEALTH_REPORTER_BURST_PERIOD, /* u64 */
|
||||
|
||||
DEVLINK_ATTR_PARAM_VALUE_DEFAULT, /* dynamic */
|
||||
DEVLINK_ATTR_PARAM_RESET_DEFAULT, /* flag */
|
||||
|
||||
DEVLINK_ATTR_INDEX, /* uint */
|
||||
DEVLINK_ATTR_RESOURCE_SCOPE_MASK, /* u32 */
|
||||
|
||||
/* Add new attributes above here, update the spec in
|
||||
* Documentation/netlink/specs/devlink.yaml and re-generate
|
||||
* net/devlink/netlink_gen.c.
|
||||
@@ -697,6 +706,16 @@ enum devlink_resource_unit {
|
||||
DEVLINK_RESOURCE_UNIT_ENTRY,
|
||||
};
|
||||
|
||||
enum devlink_resource_scope {
|
||||
DEVLINK_RESOURCE_SCOPE_DEV_BIT,
|
||||
DEVLINK_RESOURCE_SCOPE_PORT_BIT,
|
||||
};
|
||||
|
||||
#define DEVLINK_RESOURCE_SCOPE_DEV \
|
||||
_BITUL(DEVLINK_RESOURCE_SCOPE_DEV_BIT)
|
||||
#define DEVLINK_RESOURCE_SCOPE_PORT \
|
||||
_BITUL(DEVLINK_RESOURCE_SCOPE_PORT_BIT)
|
||||
|
||||
enum devlink_port_fn_attr_cap {
|
||||
DEVLINK_PORT_FN_ATTR_CAP_ROCE_BIT,
|
||||
DEVLINK_PORT_FN_ATTR_CAP_MIGRATABLE_BIT,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
obj-y := core.o netlink.o netlink_gen.o dev.o port.o sb.o dpipe.o \
|
||||
resource.o param.o region.o health.o trap.o rate.o linecard.o
|
||||
resource.o param.o region.o health.o trap.o rate.o linecard.o sh_dev.o
|
||||
|
||||
+75
-24
@@ -178,9 +178,7 @@ int devlink_rel_nested_in_add(u32 *rel_index, u32 devlink_index,
|
||||
* a notification of a change of this object should be sent
|
||||
* over netlink. The parent devlink instance lock needs to be
|
||||
* taken during the notification preparation.
|
||||
* However, since the devlink lock of nested instance is held here,
|
||||
* we would end with wrong devlink instance lock ordering and
|
||||
* deadlock. Therefore the work is utilized to avoid that.
|
||||
* Since the parent may or may not be locked, 'work' is utilized.
|
||||
*/
|
||||
void devlink_rel_nested_in_notify(struct devlink *devlink)
|
||||
{
|
||||
@@ -250,6 +248,24 @@ struct device *devlink_to_dev(const struct devlink *devlink)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_to_dev);
|
||||
|
||||
const char *devlink_bus_name(const struct devlink *devlink)
|
||||
{
|
||||
return devlink->dev ? devlink->dev->bus->name : DEVLINK_INDEX_BUS_NAME;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_bus_name);
|
||||
|
||||
const char *devlink_dev_name(const struct devlink *devlink)
|
||||
{
|
||||
return devlink->dev ? dev_name(devlink->dev) : devlink->dev_name_index;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_dev_name);
|
||||
|
||||
const char *devlink_dev_driver_name(const struct devlink *devlink)
|
||||
{
|
||||
return devlink->dev_driver->name;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_dev_driver_name);
|
||||
|
||||
struct net *devlink_net(const struct devlink *devlink)
|
||||
{
|
||||
return read_pnet(&devlink->_net);
|
||||
@@ -313,7 +329,10 @@ static void devlink_release(struct work_struct *work)
|
||||
|
||||
mutex_destroy(&devlink->lock);
|
||||
lockdep_unregister_key(&devlink->lock_key);
|
||||
put_device(devlink->dev);
|
||||
if (devlink->dev)
|
||||
put_device(devlink->dev);
|
||||
else
|
||||
kfree(devlink->dev_name_index);
|
||||
kvfree(devlink);
|
||||
}
|
||||
|
||||
@@ -323,13 +342,15 @@ void devlink_put(struct devlink *devlink)
|
||||
queue_rcu_work(system_percpu_wq, &devlink->rwork);
|
||||
}
|
||||
|
||||
struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp)
|
||||
static struct devlink *__devlinks_xa_find_get(struct net *net,
|
||||
unsigned long *indexp,
|
||||
unsigned long end)
|
||||
{
|
||||
struct devlink *devlink = NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
retry:
|
||||
devlink = xa_find(&devlinks, indexp, ULONG_MAX, DEVLINK_REGISTERED);
|
||||
devlink = xa_find(&devlinks, indexp, end, DEVLINK_REGISTERED);
|
||||
if (!devlink)
|
||||
goto unlock;
|
||||
|
||||
@@ -348,6 +369,16 @@ next:
|
||||
goto retry;
|
||||
}
|
||||
|
||||
struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp)
|
||||
{
|
||||
return __devlinks_xa_find_get(net, indexp, ULONG_MAX);
|
||||
}
|
||||
|
||||
struct devlink *devlinks_xa_lookup_get(struct net *net, unsigned long index)
|
||||
{
|
||||
return __devlinks_xa_find_get(net, &index, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* devl_register - Register devlink instance
|
||||
* @devlink: devlink
|
||||
@@ -396,27 +427,15 @@ void devlink_unregister(struct devlink *devlink)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_unregister);
|
||||
|
||||
/**
|
||||
* devlink_alloc_ns - Allocate new devlink instance resources
|
||||
* in specific namespace
|
||||
*
|
||||
* @ops: ops
|
||||
* @priv_size: size of user private data
|
||||
* @net: net namespace
|
||||
* @dev: parent device
|
||||
*
|
||||
* Allocate new devlink instance resources, including devlink index
|
||||
* and name.
|
||||
*/
|
||||
struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
|
||||
size_t priv_size, struct net *net,
|
||||
struct device *dev)
|
||||
struct devlink *__devlink_alloc(const struct devlink_ops *ops, size_t priv_size,
|
||||
struct net *net, struct device *dev,
|
||||
const struct device_driver *dev_driver)
|
||||
{
|
||||
struct devlink *devlink;
|
||||
static u32 last_id;
|
||||
int ret;
|
||||
|
||||
WARN_ON(!ops || !dev);
|
||||
WARN_ON(!ops || !dev_driver);
|
||||
if (!devlink_reload_actions_valid(ops))
|
||||
return NULL;
|
||||
|
||||
@@ -429,8 +448,16 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
|
||||
if (ret < 0)
|
||||
goto err_xa_alloc;
|
||||
|
||||
devlink->dev = get_device(dev);
|
||||
if (dev) {
|
||||
devlink->dev = get_device(dev);
|
||||
} else {
|
||||
devlink->dev_name_index = kasprintf(GFP_KERNEL, "%u", devlink->index);
|
||||
if (!devlink->dev_name_index)
|
||||
goto err_kasprintf;
|
||||
}
|
||||
|
||||
devlink->ops = ops;
|
||||
devlink->dev_driver = dev_driver;
|
||||
xa_init_flags(&devlink->ports, XA_FLAGS_ALLOC);
|
||||
xa_init_flags(&devlink->params, XA_FLAGS_ALLOC);
|
||||
xa_init_flags(&devlink->snapshot_ids, XA_FLAGS_ALLOC);
|
||||
@@ -454,10 +481,32 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
|
||||
|
||||
return devlink;
|
||||
|
||||
err_kasprintf:
|
||||
xa_erase(&devlinks, devlink->index);
|
||||
err_xa_alloc:
|
||||
kvfree(devlink);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* devlink_alloc_ns - Allocate new devlink instance resources
|
||||
* in specific namespace
|
||||
*
|
||||
* @ops: ops
|
||||
* @priv_size: size of user private data
|
||||
* @net: net namespace
|
||||
* @dev: parent device
|
||||
*
|
||||
* Allocate new devlink instance resources, including devlink index
|
||||
* and name.
|
||||
*/
|
||||
struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
|
||||
size_t priv_size, struct net *net,
|
||||
struct device *dev)
|
||||
{
|
||||
WARN_ON(!dev);
|
||||
return __devlink_alloc(ops, priv_size, net, dev, dev->driver);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_alloc_ns);
|
||||
|
||||
/**
|
||||
@@ -469,6 +518,8 @@ void devlink_free(struct devlink *devlink)
|
||||
{
|
||||
ASSERT_DEVLINK_NOT_REGISTERED(devlink);
|
||||
|
||||
devlink_rel_put(devlink);
|
||||
|
||||
WARN_ON(!list_empty(&devlink->trap_policer_list));
|
||||
WARN_ON(!list_empty(&devlink->trap_group_list));
|
||||
WARN_ON(!list_empty(&devlink->trap_list));
|
||||
@@ -477,7 +528,7 @@ void devlink_free(struct devlink *devlink)
|
||||
WARN_ON(!list_empty(&devlink->resource_list));
|
||||
WARN_ON(!list_empty(&devlink->dpipe_table_list));
|
||||
WARN_ON(!list_empty(&devlink->sb_list));
|
||||
WARN_ON(!list_empty(&devlink->rate_list));
|
||||
WARN_ON(devlink_rates_check(devlink, NULL, NULL));
|
||||
WARN_ON(!list_empty(&devlink->linecard_list));
|
||||
WARN_ON(!xa_empty(&devlink->ports));
|
||||
|
||||
|
||||
+8
-7
@@ -434,7 +434,7 @@ static void devlink_reload_reinit_sanity_check(struct devlink *devlink)
|
||||
WARN_ON(!list_empty(&devlink->trap_list));
|
||||
WARN_ON(!list_empty(&devlink->dpipe_table_list));
|
||||
WARN_ON(!list_empty(&devlink->sb_list));
|
||||
WARN_ON(!list_empty(&devlink->rate_list));
|
||||
WARN_ON(devlink_rates_check(devlink, NULL, NULL));
|
||||
WARN_ON(!list_empty(&devlink->linecard_list));
|
||||
WARN_ON(!xa_empty(&devlink->ports));
|
||||
}
|
||||
@@ -453,7 +453,8 @@ int devlink_reload(struct devlink *devlink, struct net *dest_net,
|
||||
* (e.g., PCI reset) and to close possible races between these
|
||||
* operations and probe/remove.
|
||||
*/
|
||||
device_lock_assert(devlink->dev);
|
||||
if (devlink->dev)
|
||||
device_lock_assert(devlink->dev);
|
||||
|
||||
memcpy(remote_reload_stats, devlink->stats.remote_reload_stats,
|
||||
sizeof(remote_reload_stats));
|
||||
@@ -715,10 +716,11 @@ int devlink_nl_eswitch_set_doit(struct sk_buff *skb, struct genl_info *info)
|
||||
if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) {
|
||||
if (!ops->eswitch_mode_set)
|
||||
return -EOPNOTSUPP;
|
||||
mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]);
|
||||
err = devlink_rate_nodes_check(devlink, mode, info->extack);
|
||||
err = devlink_rates_check(devlink, devlink_rate_is_node,
|
||||
info->extack);
|
||||
if (err)
|
||||
return err;
|
||||
mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]);
|
||||
err = ops->eswitch_mode_set(devlink, mode, info->extack);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -855,7 +857,7 @@ int devlink_info_version_running_put_ext(struct devlink_info_req *req,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_info_version_running_put_ext);
|
||||
|
||||
static int devlink_nl_driver_info_get(struct device_driver *drv,
|
||||
static int devlink_nl_driver_info_get(const struct device_driver *drv,
|
||||
struct devlink_info_req *req)
|
||||
{
|
||||
if (!drv)
|
||||
@@ -873,7 +875,6 @@ devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
|
||||
enum devlink_command cmd, u32 portid,
|
||||
u32 seq, int flags, struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct device *dev = devlink_to_dev(devlink);
|
||||
struct devlink_info_req req = {};
|
||||
void *hdr;
|
||||
int err;
|
||||
@@ -893,7 +894,7 @@ devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
|
||||
goto err_cancel_msg;
|
||||
}
|
||||
|
||||
err = devlink_nl_driver_info_get(dev->driver, &req);
|
||||
err = devlink_nl_driver_info_get(devlink->dev_driver, &req);
|
||||
if (err)
|
||||
goto err_cancel_msg;
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@ struct devlink {
|
||||
struct xarray snapshot_ids;
|
||||
struct devlink_dev_stats stats;
|
||||
struct device *dev;
|
||||
const char *dev_name_index;
|
||||
const struct device_driver *dev_driver;
|
||||
possible_net_t _net;
|
||||
/* Serializes access to devlink instance specific objects such as
|
||||
* port, sb, dpipe, resource, params, region, traps and more.
|
||||
@@ -66,6 +68,19 @@ struct devlink {
|
||||
extern struct xarray devlinks;
|
||||
extern struct genl_family devlink_nl_family;
|
||||
|
||||
struct devlink *__devlink_alloc(const struct devlink_ops *ops, size_t priv_size,
|
||||
struct net *net, struct device *dev,
|
||||
const struct device_driver *dev_driver);
|
||||
|
||||
#define devl_warn(devlink, format, args...) \
|
||||
do { \
|
||||
if ((devlink)->dev) \
|
||||
dev_warn((devlink)->dev, format, ##args); \
|
||||
else \
|
||||
pr_warn("devlink (%s): " format, \
|
||||
devlink_dev_name(devlink), ##args); \
|
||||
} while (0)
|
||||
|
||||
/* devlink instances are open to the access from the user space after
|
||||
* devlink_register() call. Such logical barrier allows us to have certain
|
||||
* expectations related to locking.
|
||||
@@ -90,6 +105,7 @@ extern struct genl_family devlink_nl_family;
|
||||
for (index = 0; (devlink = devlinks_xa_find_get(net, &index)); index++)
|
||||
|
||||
struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp);
|
||||
struct devlink *devlinks_xa_lookup_get(struct net *net, unsigned long index);
|
||||
|
||||
static inline bool __devl_is_registered(struct devlink *devlink)
|
||||
{
|
||||
@@ -104,7 +120,7 @@ static inline bool devl_is_registered(struct devlink *devlink)
|
||||
|
||||
static inline void devl_dev_lock(struct devlink *devlink, bool dev_lock)
|
||||
{
|
||||
if (dev_lock)
|
||||
if (dev_lock && devlink->dev)
|
||||
device_lock(devlink->dev);
|
||||
devl_lock(devlink);
|
||||
}
|
||||
@@ -112,7 +128,7 @@ static inline void devl_dev_lock(struct devlink *devlink, bool dev_lock)
|
||||
static inline void devl_dev_unlock(struct devlink *devlink, bool dev_lock)
|
||||
{
|
||||
devl_unlock(devlink);
|
||||
if (dev_lock)
|
||||
if (dev_lock && devlink->dev)
|
||||
device_unlock(devlink->dev);
|
||||
}
|
||||
|
||||
@@ -148,6 +164,11 @@ struct devlink_nl_dump_state {
|
||||
struct {
|
||||
u64 dump_ts;
|
||||
};
|
||||
/* DEVLINK_CMD_RESOURCE_DUMP */
|
||||
struct {
|
||||
u32 index;
|
||||
bool index_valid;
|
||||
} port_ctx;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -174,9 +195,11 @@ devlink_dump_state(struct netlink_callback *cb)
|
||||
static inline int
|
||||
devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
|
||||
{
|
||||
if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
|
||||
if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink_bus_name(devlink)))
|
||||
return -EMSGSIZE;
|
||||
if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
|
||||
if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, devlink_dev_name(devlink)))
|
||||
return -EMSGSIZE;
|
||||
if (nla_put_uint(msg, DEVLINK_ATTR_INDEX, devlink->index))
|
||||
return -EMSGSIZE;
|
||||
return 0;
|
||||
}
|
||||
@@ -202,6 +225,8 @@ struct devlink_obj_desc {
|
||||
const char *dev_name;
|
||||
unsigned int port_index;
|
||||
bool port_index_valid;
|
||||
unsigned int devlink_index;
|
||||
bool devlink_index_valid;
|
||||
long data[];
|
||||
};
|
||||
|
||||
@@ -209,8 +234,10 @@ static inline void devlink_nl_obj_desc_init(struct devlink_obj_desc *desc,
|
||||
struct devlink *devlink)
|
||||
{
|
||||
memset(desc, 0, sizeof(*desc));
|
||||
desc->bus_name = devlink->dev->bus->name;
|
||||
desc->dev_name = dev_name(devlink->dev);
|
||||
desc->bus_name = devlink_bus_name(devlink);
|
||||
desc->dev_name = devlink_dev_name(devlink);
|
||||
desc->devlink_index = devlink->index;
|
||||
desc->devlink_index_valid = true;
|
||||
}
|
||||
|
||||
static inline void devlink_nl_obj_desc_port_set(struct devlink_obj_desc *desc,
|
||||
@@ -297,8 +324,10 @@ int devlink_resources_validate(struct devlink *devlink,
|
||||
struct genl_info *info);
|
||||
|
||||
/* Rates */
|
||||
int devlink_rate_nodes_check(struct devlink *devlink, u16 mode,
|
||||
struct netlink_ext_ack *extack);
|
||||
bool devlink_rate_is_node(const struct devlink_rate *devlink_rate);
|
||||
int devlink_rates_check(struct devlink *devlink,
|
||||
bool (*rate_filter)(const struct devlink_rate *),
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
/* Linecards */
|
||||
unsigned int devlink_linecard_index(struct devlink_linecard *linecard);
|
||||
|
||||
@@ -1327,7 +1327,7 @@ void devlink_fmsg_dump_skb(struct devlink_fmsg *fmsg, const struct sk_buff *skb)
|
||||
if (sk) {
|
||||
devlink_fmsg_pair_nest_start(fmsg, "sk");
|
||||
devlink_fmsg_obj_nest_start(fmsg);
|
||||
devlink_fmsg_put(fmsg, "family", sk->sk_type);
|
||||
devlink_fmsg_put(fmsg, "family", sk->sk_family);
|
||||
devlink_fmsg_put(fmsg, "type", sk->sk_type);
|
||||
devlink_fmsg_put(fmsg, "proto", sk->sk_protocol);
|
||||
devlink_fmsg_obj_nest_end(fmsg);
|
||||
|
||||
+45
-9
@@ -73,13 +73,19 @@ int devlink_nl_notify_filter_set_doit(struct sk_buff *skb,
|
||||
flt->dev_name = pos;
|
||||
}
|
||||
|
||||
if (attrs[DEVLINK_ATTR_INDEX]) {
|
||||
flt->devlink_index = nla_get_uint(attrs[DEVLINK_ATTR_INDEX]);
|
||||
flt->devlink_index_valid = true;
|
||||
}
|
||||
|
||||
if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
|
||||
flt->port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
|
||||
flt->port_index_valid = true;
|
||||
}
|
||||
|
||||
/* Don't attach empty filter. */
|
||||
if (!flt->bus_name && !flt->dev_name && !flt->port_index_valid) {
|
||||
if (!flt->bus_name && !flt->dev_name &&
|
||||
!flt->devlink_index_valid && !flt->port_index_valid) {
|
||||
kfree(flt);
|
||||
flt = NULL;
|
||||
}
|
||||
@@ -100,6 +106,9 @@ int devlink_nl_notify_filter_set_doit(struct sk_buff *skb,
|
||||
static bool devlink_obj_desc_match(const struct devlink_obj_desc *desc,
|
||||
const struct devlink_obj_desc *flt)
|
||||
{
|
||||
if (desc->devlink_index_valid && flt->devlink_index_valid &&
|
||||
desc->devlink_index != flt->devlink_index)
|
||||
return false;
|
||||
if (desc->bus_name && flt->bus_name &&
|
||||
strcmp(desc->bus_name, flt->bus_name))
|
||||
return false;
|
||||
@@ -186,24 +195,48 @@ devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs,
|
||||
char *busname;
|
||||
char *devname;
|
||||
|
||||
if (attrs[DEVLINK_ATTR_INDEX]) {
|
||||
if (attrs[DEVLINK_ATTR_BUS_NAME] ||
|
||||
attrs[DEVLINK_ATTR_DEV_NAME])
|
||||
return ERR_PTR(-EINVAL);
|
||||
index = nla_get_u32(attrs[DEVLINK_ATTR_INDEX]);
|
||||
devlink = devlinks_xa_lookup_get(net, index);
|
||||
if (!devlink)
|
||||
return ERR_PTR(-ENODEV);
|
||||
goto found;
|
||||
}
|
||||
|
||||
if (!attrs[DEVLINK_ATTR_BUS_NAME] || !attrs[DEVLINK_ATTR_DEV_NAME])
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]);
|
||||
devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
|
||||
|
||||
if (!strcmp(busname, DEVLINK_INDEX_BUS_NAME)) {
|
||||
if (kstrtoul(devname, 10, &index))
|
||||
return ERR_PTR(-ENODEV);
|
||||
devlink = devlinks_xa_lookup_get(net, index);
|
||||
if (!devlink)
|
||||
return ERR_PTR(-ENODEV);
|
||||
goto found;
|
||||
}
|
||||
|
||||
devlinks_xa_for_each_registered_get(net, index, devlink) {
|
||||
if (strcmp(devlink->dev->bus->name, busname) == 0 &&
|
||||
strcmp(dev_name(devlink->dev), devname) == 0) {
|
||||
devl_dev_lock(devlink, dev_lock);
|
||||
if (devl_is_registered(devlink))
|
||||
return devlink;
|
||||
devl_dev_unlock(devlink, dev_lock);
|
||||
}
|
||||
if (strcmp(devlink_bus_name(devlink), busname) == 0 &&
|
||||
strcmp(devlink_dev_name(devlink), devname) == 0)
|
||||
goto found;
|
||||
devlink_put(devlink);
|
||||
}
|
||||
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
found:
|
||||
devl_dev_lock(devlink, dev_lock);
|
||||
if (devl_is_registered(devlink))
|
||||
return devlink;
|
||||
devl_dev_unlock(devlink, dev_lock);
|
||||
devlink_put(devlink);
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static int __devlink_nl_pre_doit(struct sk_buff *skb, struct genl_info *info,
|
||||
@@ -337,6 +370,8 @@ static int devlink_nl_inst_iter_dumpit(struct sk_buff *msg,
|
||||
|
||||
/* restart sub-object walk for the next instance */
|
||||
state->idx = 0;
|
||||
state->port_ctx.index = 0;
|
||||
state->port_ctx.index_valid = false;
|
||||
}
|
||||
|
||||
if (err != -EMSGSIZE)
|
||||
@@ -352,7 +387,8 @@ int devlink_nl_dumpit(struct sk_buff *msg, struct netlink_callback *cb,
|
||||
int flags = NLM_F_MULTI;
|
||||
|
||||
if (attrs &&
|
||||
(attrs[DEVLINK_ATTR_BUS_NAME] || attrs[DEVLINK_ATTR_DEV_NAME]))
|
||||
(attrs[DEVLINK_ATTR_BUS_NAME] || attrs[DEVLINK_ATTR_DEV_NAME] ||
|
||||
attrs[DEVLINK_ATTR_INDEX]))
|
||||
return devlink_nl_inst_single_dumpit(msg, cb, flags, dump_one,
|
||||
attrs);
|
||||
else
|
||||
|
||||
+237
-143
File diff suppressed because it is too large
Load Diff
@@ -17,17 +17,17 @@ extern const struct nla_policy devlink_dl_rate_tc_bws_nl_policy[DEVLINK_RATE_TC_
|
||||
extern const struct nla_policy devlink_dl_selftest_id_nl_policy[DEVLINK_ATTR_SELFTEST_ID_FLASH + 1];
|
||||
|
||||
/* Ops table for devlink */
|
||||
extern const struct genl_split_ops devlink_nl_ops[74];
|
||||
extern const struct genl_split_ops devlink_nl_ops[75];
|
||||
|
||||
int devlink_nl_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
|
||||
struct genl_info *info);
|
||||
int devlink_nl_pre_doit_port(const struct genl_split_ops *ops,
|
||||
struct sk_buff *skb, struct genl_info *info);
|
||||
int devlink_nl_pre_doit_dev_lock(const struct genl_split_ops *ops,
|
||||
struct sk_buff *skb, struct genl_info *info);
|
||||
int devlink_nl_pre_doit_port_optional(const struct genl_split_ops *ops,
|
||||
struct sk_buff *skb,
|
||||
struct genl_info *info);
|
||||
int devlink_nl_pre_doit_dev_lock(const struct genl_split_ops *ops,
|
||||
struct sk_buff *skb, struct genl_info *info);
|
||||
void
|
||||
devlink_nl_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
|
||||
struct genl_info *info);
|
||||
@@ -79,6 +79,8 @@ int devlink_nl_dpipe_table_counters_set_doit(struct sk_buff *skb,
|
||||
struct genl_info *info);
|
||||
int devlink_nl_resource_set_doit(struct sk_buff *skb, struct genl_info *info);
|
||||
int devlink_nl_resource_dump_doit(struct sk_buff *skb, struct genl_info *info);
|
||||
int devlink_nl_resource_dump_dumpit(struct sk_buff *skb,
|
||||
struct netlink_callback *cb);
|
||||
int devlink_nl_reload_doit(struct sk_buff *skb, struct genl_info *info);
|
||||
int devlink_nl_param_get_doit(struct sk_buff *skb, struct genl_info *info);
|
||||
int devlink_nl_param_get_dumpit(struct sk_buff *skb,
|
||||
|
||||
+213
-60
@@ -174,11 +174,12 @@ devlink_param_cmode_is_supported(const struct devlink_param *param,
|
||||
|
||||
static int devlink_param_get(struct devlink *devlink,
|
||||
const struct devlink_param *param,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (!param->get)
|
||||
return -EOPNOTSUPP;
|
||||
return param->get(devlink, param->id, ctx);
|
||||
return param->get(devlink, param->id, ctx, extack);
|
||||
}
|
||||
|
||||
static int devlink_param_set(struct devlink *devlink,
|
||||
@@ -191,50 +192,110 @@ static int devlink_param_set(struct devlink *devlink,
|
||||
return param->set(devlink, param->id, ctx, extack);
|
||||
}
|
||||
|
||||
static int devlink_param_get_default(struct devlink *devlink,
|
||||
const struct devlink_param *param,
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (!param->get_default)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return param->get_default(devlink, param->id, ctx, extack);
|
||||
}
|
||||
|
||||
static int devlink_param_reset_default(struct devlink *devlink,
|
||||
const struct devlink_param *param,
|
||||
enum devlink_param_cmode cmode,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
if (!param->reset_default)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return param->reset_default(devlink, param->id, cmode, extack);
|
||||
}
|
||||
|
||||
static int
|
||||
devlink_nl_param_value_put(struct sk_buff *msg, enum devlink_param_type type,
|
||||
int nla_type, union devlink_param_value *val,
|
||||
bool flag_as_u8)
|
||||
{
|
||||
switch (type) {
|
||||
case DEVLINK_PARAM_TYPE_U8:
|
||||
if (nla_put_u8(msg, nla_type, val->vu8))
|
||||
return -EMSGSIZE;
|
||||
break;
|
||||
case DEVLINK_PARAM_TYPE_U16:
|
||||
if (nla_put_u16(msg, nla_type, val->vu16))
|
||||
return -EMSGSIZE;
|
||||
break;
|
||||
case DEVLINK_PARAM_TYPE_U32:
|
||||
if (nla_put_u32(msg, nla_type, val->vu32))
|
||||
return -EMSGSIZE;
|
||||
break;
|
||||
case DEVLINK_PARAM_TYPE_U64:
|
||||
if (devlink_nl_put_u64(msg, nla_type, val->vu64))
|
||||
return -EMSGSIZE;
|
||||
break;
|
||||
case DEVLINK_PARAM_TYPE_STRING:
|
||||
if (nla_put_string(msg, nla_type, val->vstr))
|
||||
return -EMSGSIZE;
|
||||
break;
|
||||
case DEVLINK_PARAM_TYPE_BOOL:
|
||||
/* default values of type bool are encoded with u8, so that
|
||||
* false can be distinguished from not present
|
||||
*/
|
||||
if (flag_as_u8) {
|
||||
if (nla_put_u8(msg, nla_type, val->vbool))
|
||||
return -EMSGSIZE;
|
||||
} else {
|
||||
if (val->vbool && nla_put_flag(msg, nla_type))
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
break;
|
||||
case DEVLINK_PARAM_TYPE_U64_ARRAY:
|
||||
if (val->u64arr.size > __DEVLINK_PARAM_MAX_ARRAY_SIZE)
|
||||
return -EMSGSIZE;
|
||||
|
||||
for (int i = 0; i < val->u64arr.size; i++) {
|
||||
if (nla_put_uint(msg, nla_type, val->u64arr.val[i]))
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
devlink_nl_param_value_fill_one(struct sk_buff *msg,
|
||||
enum devlink_param_type type,
|
||||
enum devlink_param_cmode cmode,
|
||||
union devlink_param_value val)
|
||||
union devlink_param_value *val,
|
||||
union devlink_param_value *default_val,
|
||||
bool has_default)
|
||||
{
|
||||
struct nlattr *param_value_attr;
|
||||
int err = -EMSGSIZE;
|
||||
|
||||
param_value_attr = nla_nest_start_noflag(msg,
|
||||
DEVLINK_ATTR_PARAM_VALUE);
|
||||
if (!param_value_attr)
|
||||
goto nla_put_failure;
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
|
||||
goto value_nest_cancel;
|
||||
|
||||
switch (type) {
|
||||
case DEVLINK_PARAM_TYPE_U8:
|
||||
if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8))
|
||||
err = devlink_nl_param_value_put(msg, type,
|
||||
DEVLINK_ATTR_PARAM_VALUE_DATA,
|
||||
val, false);
|
||||
if (err)
|
||||
goto value_nest_cancel;
|
||||
|
||||
if (has_default) {
|
||||
err = devlink_nl_param_value_put(msg, type,
|
||||
DEVLINK_ATTR_PARAM_VALUE_DEFAULT,
|
||||
default_val, true);
|
||||
if (err)
|
||||
goto value_nest_cancel;
|
||||
break;
|
||||
case DEVLINK_PARAM_TYPE_U16:
|
||||
if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16))
|
||||
goto value_nest_cancel;
|
||||
break;
|
||||
case DEVLINK_PARAM_TYPE_U32:
|
||||
if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32))
|
||||
goto value_nest_cancel;
|
||||
break;
|
||||
case DEVLINK_PARAM_TYPE_U64:
|
||||
if (devlink_nl_put_u64(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
|
||||
val.vu64))
|
||||
goto value_nest_cancel;
|
||||
break;
|
||||
case DEVLINK_PARAM_TYPE_STRING:
|
||||
if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
|
||||
val.vstr))
|
||||
goto value_nest_cancel;
|
||||
break;
|
||||
case DEVLINK_PARAM_TYPE_BOOL:
|
||||
if (val.vbool &&
|
||||
nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA))
|
||||
goto value_nest_cancel;
|
||||
break;
|
||||
}
|
||||
|
||||
nla_nest_end(msg, param_value_attr);
|
||||
@@ -242,50 +303,89 @@ devlink_nl_param_value_fill_one(struct sk_buff *msg,
|
||||
|
||||
value_nest_cancel:
|
||||
nla_nest_cancel(msg, param_value_attr);
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
|
||||
unsigned int port_index,
|
||||
struct devlink_param_item *param_item,
|
||||
enum devlink_command cmd,
|
||||
u32 portid, u32 seq, int flags)
|
||||
u32 portid, u32 seq, int flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
|
||||
bool default_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
|
||||
bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
|
||||
const struct devlink_param *param = param_item->param;
|
||||
struct devlink_param_gset_ctx ctx;
|
||||
union devlink_param_value *default_value;
|
||||
union devlink_param_value *param_value;
|
||||
struct devlink_param_gset_ctx *ctx;
|
||||
struct nlattr *param_values_list;
|
||||
struct nlattr *param_attr;
|
||||
void *hdr;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
default_value = kcalloc(DEVLINK_PARAM_CMODE_MAX + 1,
|
||||
sizeof(*default_value), GFP_KERNEL);
|
||||
if (!default_value)
|
||||
return -ENOMEM;
|
||||
|
||||
param_value = kcalloc(DEVLINK_PARAM_CMODE_MAX + 1,
|
||||
sizeof(*param_value), GFP_KERNEL);
|
||||
if (!param_value) {
|
||||
kfree(default_value);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ctx = kzalloc_obj(*ctx);
|
||||
if (!ctx) {
|
||||
kfree(param_value);
|
||||
kfree(default_value);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Get value from driver part to driverinit configuration mode */
|
||||
for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
|
||||
if (!devlink_param_cmode_is_supported(param, i))
|
||||
continue;
|
||||
if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
|
||||
if (param_item->driverinit_value_new_valid)
|
||||
if (param_item->driverinit_value_new_valid) {
|
||||
param_value[i] = param_item->driverinit_value_new;
|
||||
else if (param_item->driverinit_value_valid)
|
||||
} else if (param_item->driverinit_value_valid) {
|
||||
param_value[i] = param_item->driverinit_value;
|
||||
else
|
||||
return -EOPNOTSUPP;
|
||||
} else {
|
||||
err = -EOPNOTSUPP;
|
||||
goto get_put_fail;
|
||||
}
|
||||
|
||||
if (param_item->driverinit_value_valid) {
|
||||
default_value[i] = param_item->driverinit_default;
|
||||
default_value_set[i] = true;
|
||||
}
|
||||
} else {
|
||||
ctx.cmode = i;
|
||||
err = devlink_param_get(devlink, param, &ctx);
|
||||
ctx->cmode = i;
|
||||
err = devlink_param_get(devlink, param, ctx, extack);
|
||||
if (err)
|
||||
return err;
|
||||
param_value[i] = ctx.val;
|
||||
goto get_put_fail;
|
||||
|
||||
param_value[i] = ctx->val;
|
||||
|
||||
err = devlink_param_get_default(devlink, param, ctx,
|
||||
extack);
|
||||
if (!err) {
|
||||
default_value[i] = ctx->val;
|
||||
default_value_set[i] = true;
|
||||
} else if (err != -EOPNOTSUPP) {
|
||||
goto get_put_fail;
|
||||
}
|
||||
}
|
||||
param_value_set[i] = true;
|
||||
}
|
||||
|
||||
err = -EMSGSIZE;
|
||||
hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
|
||||
if (!hdr)
|
||||
return -EMSGSIZE;
|
||||
goto get_put_fail;
|
||||
|
||||
if (devlink_nl_put_handle(msg, devlink))
|
||||
goto genlmsg_cancel;
|
||||
@@ -315,7 +415,9 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
|
||||
if (!param_value_set[i])
|
||||
continue;
|
||||
err = devlink_nl_param_value_fill_one(msg, param->type,
|
||||
i, param_value[i]);
|
||||
i, ¶m_value[i],
|
||||
&default_value[i],
|
||||
default_value_set[i]);
|
||||
if (err)
|
||||
goto values_list_nest_cancel;
|
||||
}
|
||||
@@ -323,6 +425,9 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
|
||||
nla_nest_end(msg, param_values_list);
|
||||
nla_nest_end(msg, param_attr);
|
||||
genlmsg_end(msg, hdr);
|
||||
kfree(default_value);
|
||||
kfree(param_value);
|
||||
kfree(ctx);
|
||||
return 0;
|
||||
|
||||
values_list_nest_cancel:
|
||||
@@ -331,7 +436,11 @@ param_nest_cancel:
|
||||
nla_nest_cancel(msg, param_attr);
|
||||
genlmsg_cancel:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
return -EMSGSIZE;
|
||||
get_put_fail:
|
||||
kfree(default_value);
|
||||
kfree(param_value);
|
||||
kfree(ctx);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void devlink_param_notify(struct devlink *devlink,
|
||||
@@ -357,7 +466,7 @@ static void devlink_param_notify(struct devlink *devlink,
|
||||
if (!msg)
|
||||
return;
|
||||
err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd,
|
||||
0, 0, 0);
|
||||
0, 0, 0, NULL);
|
||||
if (err) {
|
||||
nlmsg_free(msg);
|
||||
return;
|
||||
@@ -400,7 +509,8 @@ static int devlink_nl_param_get_dump_one(struct sk_buff *msg,
|
||||
err = devlink_nl_param_fill(msg, devlink, 0, param_item,
|
||||
DEVLINK_CMD_PARAM_GET,
|
||||
NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq, flags);
|
||||
cb->nlh->nlmsg_seq, flags,
|
||||
cb->extack);
|
||||
if (err == -EOPNOTSUPP) {
|
||||
err = 0;
|
||||
} else if (err) {
|
||||
@@ -436,7 +546,7 @@ devlink_param_value_get_from_info(const struct devlink_param *param,
|
||||
union devlink_param_value *value)
|
||||
{
|
||||
struct nlattr *param_data;
|
||||
int len;
|
||||
int len, cnt, rem;
|
||||
|
||||
param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA];
|
||||
|
||||
@@ -476,6 +586,28 @@ devlink_param_value_get_from_info(const struct devlink_param *param,
|
||||
return -EINVAL;
|
||||
value->vbool = nla_get_flag(param_data);
|
||||
break;
|
||||
|
||||
case DEVLINK_PARAM_TYPE_U64_ARRAY:
|
||||
cnt = 0;
|
||||
nla_for_each_attr_type(param_data,
|
||||
DEVLINK_ATTR_PARAM_VALUE_DATA,
|
||||
genlmsg_data(info->genlhdr),
|
||||
genlmsg_len(info->genlhdr), rem) {
|
||||
if (cnt >= __DEVLINK_PARAM_MAX_ARRAY_SIZE)
|
||||
return -EMSGSIZE;
|
||||
|
||||
if ((nla_len(param_data) != sizeof(u64)) &&
|
||||
(nla_len(param_data) != sizeof(u32))) {
|
||||
NL_SET_BAD_ATTR(info->extack, param_data);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
value->u64arr.val[cnt] = nla_get_uint(param_data);
|
||||
cnt++;
|
||||
}
|
||||
|
||||
value->u64arr.size = cnt;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -509,8 +641,8 @@ int devlink_nl_param_get_doit(struct sk_buff *skb,
|
||||
return -ENOMEM;
|
||||
|
||||
err = devlink_nl_param_fill(msg, devlink, 0, param_item,
|
||||
DEVLINK_CMD_PARAM_GET,
|
||||
info->snd_portid, info->snd_seq, 0);
|
||||
DEVLINK_CMD_PARAM_GET, info->snd_portid,
|
||||
info->snd_seq, 0, info->extack);
|
||||
if (err) {
|
||||
nlmsg_free(msg);
|
||||
return err;
|
||||
@@ -531,6 +663,7 @@ static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
|
||||
struct devlink_param_item *param_item;
|
||||
const struct devlink_param *param;
|
||||
union devlink_param_value value;
|
||||
bool reset_default;
|
||||
int err = 0;
|
||||
|
||||
param_item = devlink_param_get_from_info(params, info);
|
||||
@@ -542,13 +675,18 @@ static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
|
||||
return err;
|
||||
if (param_type != param->type)
|
||||
return -EINVAL;
|
||||
err = devlink_param_value_get_from_info(param, info, &value);
|
||||
if (err)
|
||||
return err;
|
||||
if (param->validate) {
|
||||
err = param->validate(devlink, param->id, value, info->extack);
|
||||
|
||||
reset_default = info->attrs[DEVLINK_ATTR_PARAM_RESET_DEFAULT];
|
||||
if (!reset_default) {
|
||||
err = devlink_param_value_get_from_info(param, info, &value);
|
||||
if (err)
|
||||
return err;
|
||||
if (param->validate) {
|
||||
err = param->validate(devlink, param->id, &value,
|
||||
info->extack);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_VALUE_CMODE))
|
||||
@@ -558,6 +696,15 @@ static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
|
||||
if (reset_default) {
|
||||
if (!param_item->driverinit_value_valid) {
|
||||
NL_SET_ERR_MSG(info->extack,
|
||||
"Default value not available");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
value = param_item->driverinit_default;
|
||||
}
|
||||
|
||||
param_item->driverinit_value_new = value;
|
||||
param_item->driverinit_value_new_valid = true;
|
||||
} else {
|
||||
@@ -565,7 +712,12 @@ static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
|
||||
return -EOPNOTSUPP;
|
||||
ctx.val = value;
|
||||
ctx.cmode = cmode;
|
||||
err = devlink_param_set(devlink, param, &ctx, info->extack);
|
||||
if (reset_default)
|
||||
err = devlink_param_reset_default(devlink, param, cmode,
|
||||
info->extack);
|
||||
else
|
||||
err = devlink_param_set(devlink, param, &ctx,
|
||||
info->extack);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -797,7 +949,7 @@ EXPORT_SYMBOL_GPL(devl_param_driverinit_value_get);
|
||||
* configuration mode default value.
|
||||
*/
|
||||
void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
|
||||
union devlink_param_value init_val)
|
||||
union devlink_param_value *init_val)
|
||||
{
|
||||
struct devlink_param_item *param_item;
|
||||
|
||||
@@ -811,8 +963,9 @@ void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
|
||||
DEVLINK_PARAM_CMODE_DRIVERINIT)))
|
||||
return;
|
||||
|
||||
param_item->driverinit_value = init_val;
|
||||
param_item->driverinit_value = *init_val;
|
||||
param_item->driverinit_value_valid = true;
|
||||
param_item->driverinit_default = *init_val;
|
||||
|
||||
devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
|
||||
}
|
||||
|
||||
+12
-9
@@ -220,8 +220,9 @@ size_t devlink_nl_port_handle_size(struct devlink_port *devlink_port)
|
||||
{
|
||||
struct devlink *devlink = devlink_port->devlink;
|
||||
|
||||
return nla_total_size(strlen(devlink->dev->bus->name) + 1) /* DEVLINK_ATTR_BUS_NAME */
|
||||
+ nla_total_size(strlen(dev_name(devlink->dev)) + 1) /* DEVLINK_ATTR_DEV_NAME */
|
||||
return nla_total_size(strlen(devlink_bus_name(devlink)) + 1) /* DEVLINK_ATTR_BUS_NAME */
|
||||
+ nla_total_size(strlen(devlink_dev_name(devlink)) + 1) /* DEVLINK_ATTR_DEV_NAME */
|
||||
+ nla_total_size(8) /* DEVLINK_ATTR_INDEX */
|
||||
+ nla_total_size(4); /* DEVLINK_ATTR_PORT_INDEX */
|
||||
}
|
||||
|
||||
@@ -975,7 +976,7 @@ static void devlink_port_type_warn(struct work_struct *work)
|
||||
struct devlink_port *port = container_of(to_delayed_work(work),
|
||||
struct devlink_port,
|
||||
type_warn_dw);
|
||||
dev_warn(port->devlink->dev, "Type was not set for devlink port.");
|
||||
devl_warn(port->devlink, "Type was not set for devlink port.");
|
||||
}
|
||||
|
||||
static bool devlink_port_type_should_warn(struct devlink_port *devlink_port)
|
||||
@@ -1024,6 +1025,7 @@ void devlink_port_init(struct devlink *devlink,
|
||||
return;
|
||||
devlink_port->devlink = devlink;
|
||||
INIT_LIST_HEAD(&devlink_port->region_list);
|
||||
INIT_LIST_HEAD(&devlink_port->resource_list);
|
||||
devlink_port->initialized = true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_port_init);
|
||||
@@ -1041,6 +1043,7 @@ EXPORT_SYMBOL_GPL(devlink_port_init);
|
||||
void devlink_port_fini(struct devlink_port *devlink_port)
|
||||
{
|
||||
WARN_ON(!list_empty(&devlink_port->region_list));
|
||||
WARN_ON(!list_empty(&devlink_port->resource_list));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_port_fini);
|
||||
|
||||
@@ -1241,9 +1244,9 @@ static void __devlink_port_type_set(struct devlink_port *devlink_port,
|
||||
*/
|
||||
void devlink_port_type_eth_set(struct devlink_port *devlink_port)
|
||||
{
|
||||
dev_warn(devlink_port->devlink->dev,
|
||||
"devlink port type for port %d set to Ethernet without a software interface reference, device type not supported by the kernel?\n",
|
||||
devlink_port->index);
|
||||
devl_warn(devlink_port->devlink,
|
||||
"devlink port type for port %d set to Ethernet without a software interface reference, device type not supported by the kernel?\n",
|
||||
devlink_port->index);
|
||||
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
|
||||
@@ -1272,9 +1275,9 @@ EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
|
||||
void devlink_port_type_clear(struct devlink_port *devlink_port)
|
||||
{
|
||||
if (devlink_port->type == DEVLINK_PORT_TYPE_ETH)
|
||||
dev_warn(devlink_port->devlink->dev,
|
||||
"devlink port type for port %d cleared without a software interface reference, device type not supported by the kernel?\n",
|
||||
devlink_port->index);
|
||||
devl_warn(devlink_port->devlink,
|
||||
"devlink port type for port %d cleared without a software interface reference, device type not supported by the kernel?\n",
|
||||
devlink_port->index);
|
||||
__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_port_type_clear);
|
||||
|
||||
+21
-17
@@ -12,8 +12,7 @@ devlink_rate_is_leaf(struct devlink_rate *devlink_rate)
|
||||
return devlink_rate->type == DEVLINK_RATE_TYPE_LEAF;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
devlink_rate_is_node(struct devlink_rate *devlink_rate)
|
||||
bool devlink_rate_is_node(const struct devlink_rate *devlink_rate)
|
||||
{
|
||||
return devlink_rate->type == DEVLINK_RATE_TYPE_NODE;
|
||||
}
|
||||
@@ -487,16 +486,19 @@ static int devlink_nl_rate_set(struct devlink_rate *devlink_rate,
|
||||
devlink_rate->tx_weight = weight;
|
||||
}
|
||||
|
||||
nla_parent = attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME];
|
||||
if (nla_parent) {
|
||||
err = devlink_nl_rate_parent_node_set(devlink_rate, info,
|
||||
nla_parent);
|
||||
if (attrs[DEVLINK_ATTR_RATE_TC_BWS]) {
|
||||
err = devlink_nl_rate_tc_bw_set(devlink_rate, info);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (attrs[DEVLINK_ATTR_RATE_TC_BWS]) {
|
||||
err = devlink_nl_rate_tc_bw_set(devlink_rate, info);
|
||||
/* Keep parent setting last because it takes a reference. This function
|
||||
* has no rollback, so failing after taking the ref would leak it.
|
||||
*/
|
||||
nla_parent = attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME];
|
||||
if (nla_parent) {
|
||||
err = devlink_nl_rate_parent_node_set(devlink_rate, info,
|
||||
nla_parent);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -688,14 +690,16 @@ int devlink_nl_rate_del_doit(struct sk_buff *skb, struct genl_info *info)
|
||||
return err;
|
||||
}
|
||||
|
||||
int devlink_rate_nodes_check(struct devlink *devlink, u16 mode,
|
||||
struct netlink_ext_ack *extack)
|
||||
int devlink_rates_check(struct devlink *devlink,
|
||||
bool (*rate_filter)(const struct devlink_rate *),
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct devlink_rate *devlink_rate;
|
||||
|
||||
list_for_each_entry(devlink_rate, &devlink->rate_list, list)
|
||||
if (devlink_rate_is_node(devlink_rate)) {
|
||||
NL_SET_ERR_MSG(extack, "Rate node(s) exists.");
|
||||
if (!rate_filter || rate_filter(devlink_rate)) {
|
||||
if (extack)
|
||||
NL_SET_ERR_MSG(extack, "Rate node(s) exists.");
|
||||
return -EBUSY;
|
||||
}
|
||||
return 0;
|
||||
@@ -724,11 +728,6 @@ devl_rate_node_create(struct devlink *devlink, void *priv, char *node_name,
|
||||
if (!rate_node)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
if (parent) {
|
||||
rate_node->parent = parent;
|
||||
refcount_inc(&rate_node->parent->refcnt);
|
||||
}
|
||||
|
||||
rate_node->type = DEVLINK_RATE_TYPE_NODE;
|
||||
rate_node->devlink = devlink;
|
||||
rate_node->priv = priv;
|
||||
@@ -739,6 +738,11 @@ devl_rate_node_create(struct devlink *devlink, void *priv, char *node_name,
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
rate_node->parent = parent;
|
||||
refcount_inc(&rate_node->parent->refcnt);
|
||||
}
|
||||
|
||||
refcount_set(&rate_node->refcnt, 1);
|
||||
list_add(&rate_node->list, &devlink->rate_list);
|
||||
devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW);
|
||||
|
||||
+273
-47
@@ -36,15 +36,16 @@ struct devlink_resource {
|
||||
};
|
||||
|
||||
static struct devlink_resource *
|
||||
devlink_resource_find(struct devlink *devlink,
|
||||
struct devlink_resource *resource, u64 resource_id)
|
||||
__devlink_resource_find(struct list_head *resource_list_head,
|
||||
struct devlink_resource *resource,
|
||||
u64 resource_id)
|
||||
{
|
||||
struct list_head *resource_list;
|
||||
|
||||
if (resource)
|
||||
resource_list = &resource->resource_list;
|
||||
else
|
||||
resource_list = &devlink->resource_list;
|
||||
resource_list = resource_list_head;
|
||||
|
||||
list_for_each_entry(resource, resource_list, list) {
|
||||
struct devlink_resource *child_resource;
|
||||
@@ -52,14 +53,23 @@ devlink_resource_find(struct devlink *devlink,
|
||||
if (resource->id == resource_id)
|
||||
return resource;
|
||||
|
||||
child_resource = devlink_resource_find(devlink, resource,
|
||||
resource_id);
|
||||
child_resource = __devlink_resource_find(resource_list_head,
|
||||
resource,
|
||||
resource_id);
|
||||
if (child_resource)
|
||||
return child_resource;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct devlink_resource *
|
||||
devlink_resource_find(struct devlink *devlink,
|
||||
struct devlink_resource *resource, u64 resource_id)
|
||||
{
|
||||
return __devlink_resource_find(&devlink->resource_list,
|
||||
resource, resource_id);
|
||||
}
|
||||
|
||||
static void
|
||||
devlink_resource_validate_children(struct devlink_resource *resource)
|
||||
{
|
||||
@@ -213,11 +223,38 @@ nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int devlink_resource_list_fill(struct sk_buff *skb,
|
||||
struct devlink *devlink,
|
||||
struct list_head *resource_list_head,
|
||||
int *idx)
|
||||
{
|
||||
struct devlink_resource *resource;
|
||||
int i = 0;
|
||||
int err;
|
||||
|
||||
list_for_each_entry(resource, resource_list_head, list) {
|
||||
if (i < *idx) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
err = devlink_resource_put(devlink, skb, resource);
|
||||
if (err) {
|
||||
*idx = i;
|
||||
return err;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
*idx = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int devlink_resource_fill(struct genl_info *info,
|
||||
enum devlink_command cmd, int flags)
|
||||
{
|
||||
struct devlink_port *devlink_port = info->user_ptr[1];
|
||||
struct devlink *devlink = info->user_ptr[0];
|
||||
struct devlink_resource *resource;
|
||||
struct list_head *resource_list;
|
||||
struct nlattr *resources_attr;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct nlmsghdr *nlh;
|
||||
@@ -226,7 +263,9 @@ static int devlink_resource_fill(struct genl_info *info,
|
||||
int i;
|
||||
int err;
|
||||
|
||||
resource = list_first_entry(&devlink->resource_list,
|
||||
resource_list = devlink_port ?
|
||||
&devlink_port->resource_list : &devlink->resource_list;
|
||||
resource = list_first_entry(resource_list,
|
||||
struct devlink_resource, list);
|
||||
start_again:
|
||||
err = devlink_nl_msg_reply_and_new(&skb, info);
|
||||
@@ -242,6 +281,9 @@ start_again:
|
||||
|
||||
if (devlink_nl_put_handle(skb, devlink))
|
||||
goto nla_put_failure;
|
||||
if (devlink_port &&
|
||||
nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
|
||||
goto nla_put_failure;
|
||||
|
||||
resources_attr = nla_nest_start_noflag(skb,
|
||||
DEVLINK_ATTR_RESOURCE_LIST);
|
||||
@@ -250,7 +292,7 @@ start_again:
|
||||
|
||||
incomplete = false;
|
||||
i = 0;
|
||||
list_for_each_entry_from(resource, &devlink->resource_list, list) {
|
||||
list_for_each_entry_from(resource, resource_list, list) {
|
||||
err = devlink_resource_put(devlink, skb, resource);
|
||||
if (err) {
|
||||
if (!i)
|
||||
@@ -284,14 +326,133 @@ err_resource_put:
|
||||
|
||||
int devlink_nl_resource_dump_doit(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct devlink_port *devlink_port = info->user_ptr[1];
|
||||
struct devlink *devlink = info->user_ptr[0];
|
||||
struct list_head *resource_list;
|
||||
|
||||
if (list_empty(&devlink->resource_list))
|
||||
if (info->attrs[DEVLINK_ATTR_PORT_INDEX] && !devlink_port)
|
||||
return -ENODEV;
|
||||
|
||||
resource_list = devlink_port ?
|
||||
&devlink_port->resource_list : &devlink->resource_list;
|
||||
if (list_empty(resource_list))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
devlink_resource_dump_fill_one(struct sk_buff *skb, struct devlink *devlink,
|
||||
struct devlink_port *devlink_port,
|
||||
struct netlink_callback *cb, int flags, int *idx)
|
||||
{
|
||||
struct list_head *resource_list;
|
||||
struct nlattr *resources_attr;
|
||||
int start_idx = *idx;
|
||||
void *hdr;
|
||||
int err;
|
||||
|
||||
resource_list = devlink_port ?
|
||||
&devlink_port->resource_list : &devlink->resource_list;
|
||||
|
||||
if (list_empty(resource_list))
|
||||
return 0;
|
||||
|
||||
err = -EMSGSIZE;
|
||||
hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
|
||||
&devlink_nl_family, flags, DEVLINK_CMD_RESOURCE_DUMP);
|
||||
if (!hdr)
|
||||
return err;
|
||||
|
||||
if (devlink_nl_put_handle(skb, devlink))
|
||||
goto nla_put_failure;
|
||||
if (devlink_port &&
|
||||
nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
|
||||
goto nla_put_failure;
|
||||
|
||||
resources_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_RESOURCE_LIST);
|
||||
if (!resources_attr)
|
||||
goto nla_put_failure;
|
||||
|
||||
err = devlink_resource_list_fill(skb, devlink, resource_list, idx);
|
||||
if (err) {
|
||||
if (*idx == start_idx)
|
||||
goto resource_list_cancel;
|
||||
nla_nest_end(skb, resources_attr);
|
||||
genlmsg_end(skb, hdr);
|
||||
return err;
|
||||
}
|
||||
nla_nest_end(skb, resources_attr);
|
||||
genlmsg_end(skb, hdr);
|
||||
return 0;
|
||||
|
||||
resource_list_cancel:
|
||||
nla_nest_cancel(skb, resources_attr);
|
||||
nla_put_failure:
|
||||
genlmsg_cancel(skb, hdr);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
devlink_nl_resource_dump_one(struct sk_buff *skb, struct devlink *devlink,
|
||||
struct netlink_callback *cb, int flags)
|
||||
{
|
||||
struct devlink_nl_dump_state *state = devlink_dump_state(cb);
|
||||
const struct genl_info *info = genl_info_dump(cb);
|
||||
struct devlink_port *devlink_port;
|
||||
struct nlattr *scope_attr = NULL;
|
||||
unsigned long port_idx;
|
||||
u32 scope = 0;
|
||||
int err;
|
||||
|
||||
if (info->attrs && info->attrs[DEVLINK_ATTR_RESOURCE_SCOPE_MASK]) {
|
||||
scope_attr = info->attrs[DEVLINK_ATTR_RESOURCE_SCOPE_MASK];
|
||||
scope = nla_get_u32(scope_attr);
|
||||
if (!scope) {
|
||||
NL_SET_ERR_MSG_ATTR(info->extack, scope_attr,
|
||||
"empty resource scope selection");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!state->port_ctx.index_valid &&
|
||||
(!scope || (scope & DEVLINK_RESOURCE_SCOPE_DEV))) {
|
||||
err = devlink_resource_dump_fill_one(skb, devlink, NULL,
|
||||
cb, flags, &state->idx);
|
||||
if (err)
|
||||
return err;
|
||||
state->idx = 0;
|
||||
}
|
||||
|
||||
if (scope && !(scope & DEVLINK_RESOURCE_SCOPE_PORT))
|
||||
goto out;
|
||||
/* Check in case port was removed between dump callbacks. */
|
||||
if (state->port_ctx.index_valid &&
|
||||
!xa_load(&devlink->ports, state->port_ctx.index))
|
||||
state->idx = 0;
|
||||
state->port_ctx.index_valid = true;
|
||||
xa_for_each_start(&devlink->ports, port_idx, devlink_port,
|
||||
state->port_ctx.index) {
|
||||
err = devlink_resource_dump_fill_one(skb, devlink, devlink_port,
|
||||
cb, flags, &state->idx);
|
||||
if (err) {
|
||||
state->port_ctx.index = port_idx;
|
||||
return err;
|
||||
}
|
||||
state->idx = 0;
|
||||
}
|
||||
out:
|
||||
state->port_ctx.index_valid = false;
|
||||
state->port_ctx.index = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int devlink_nl_resource_dump_dumpit(struct sk_buff *skb,
|
||||
struct netlink_callback *cb)
|
||||
{
|
||||
return devlink_nl_dumpit(skb, cb, devlink_nl_resource_dump_one);
|
||||
}
|
||||
|
||||
int devlink_resources_validate(struct devlink *devlink,
|
||||
struct devlink_resource *resource,
|
||||
struct genl_info *info)
|
||||
@@ -314,36 +475,25 @@ int devlink_resources_validate(struct devlink *devlink,
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* devl_resource_register - devlink resource register
|
||||
*
|
||||
* @devlink: devlink
|
||||
* @resource_name: resource's name
|
||||
* @resource_size: resource's size
|
||||
* @resource_id: resource's id
|
||||
* @parent_resource_id: resource's parent id
|
||||
* @size_params: size parameters
|
||||
*
|
||||
* Generic resources should reuse the same names across drivers.
|
||||
* Please see the generic resources list at:
|
||||
* Documentation/networking/devlink/devlink-resource.rst
|
||||
*/
|
||||
int devl_resource_register(struct devlink *devlink,
|
||||
const char *resource_name,
|
||||
u64 resource_size,
|
||||
u64 resource_id,
|
||||
u64 parent_resource_id,
|
||||
const struct devlink_resource_size_params *size_params)
|
||||
static int
|
||||
__devl_resource_register(struct devlink *devlink,
|
||||
struct list_head *resource_list_head,
|
||||
const char *resource_name, u64 resource_size,
|
||||
u64 resource_id, u64 parent_resource_id,
|
||||
const struct devlink_resource_size_params *params)
|
||||
{
|
||||
struct devlink_resource *resource;
|
||||
struct list_head *resource_list;
|
||||
bool top_hierarchy;
|
||||
|
||||
WARN_ON(resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP);
|
||||
|
||||
lockdep_assert_held(&devlink->lock);
|
||||
|
||||
top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP;
|
||||
|
||||
resource = devlink_resource_find(devlink, NULL, resource_id);
|
||||
resource = __devlink_resource_find(resource_list_head, NULL,
|
||||
resource_id);
|
||||
if (resource)
|
||||
return -EEXIST;
|
||||
|
||||
@@ -352,12 +502,13 @@ int devl_resource_register(struct devlink *devlink,
|
||||
return -ENOMEM;
|
||||
|
||||
if (top_hierarchy) {
|
||||
resource_list = &devlink->resource_list;
|
||||
resource_list = resource_list_head;
|
||||
} else {
|
||||
struct devlink_resource *parent_resource;
|
||||
|
||||
parent_resource = devlink_resource_find(devlink, NULL,
|
||||
parent_resource_id);
|
||||
parent_resource = __devlink_resource_find(resource_list_head,
|
||||
NULL,
|
||||
parent_resource_id);
|
||||
if (parent_resource) {
|
||||
resource_list = &parent_resource->resource_list;
|
||||
resource->parent = parent_resource;
|
||||
@@ -372,23 +523,64 @@ int devl_resource_register(struct devlink *devlink,
|
||||
resource->size_new = resource_size;
|
||||
resource->id = resource_id;
|
||||
resource->size_valid = true;
|
||||
memcpy(&resource->size_params, size_params,
|
||||
sizeof(resource->size_params));
|
||||
memcpy(&resource->size_params, params, sizeof(resource->size_params));
|
||||
INIT_LIST_HEAD(&resource->resource_list);
|
||||
list_add_tail(&resource->list, resource_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* devl_resource_register - devlink resource register
|
||||
*
|
||||
* @devlink: devlink
|
||||
* @resource_name: resource's name
|
||||
* @resource_size: resource's size
|
||||
* @resource_id: resource's id
|
||||
* @parent_resource_id: resource's parent id
|
||||
* @params: size parameters
|
||||
*
|
||||
* Generic resources should reuse the same names across drivers.
|
||||
* Please see the generic resources list at:
|
||||
* Documentation/networking/devlink/devlink-resource.rst
|
||||
*
|
||||
* Return: 0 on success, negative error code otherwise.
|
||||
*/
|
||||
int devl_resource_register(struct devlink *devlink, const char *resource_name,
|
||||
u64 resource_size, u64 resource_id,
|
||||
u64 parent_resource_id,
|
||||
const struct devlink_resource_size_params *params)
|
||||
{
|
||||
return __devl_resource_register(devlink, &devlink->resource_list,
|
||||
resource_name, resource_size,
|
||||
resource_id, parent_resource_id,
|
||||
params);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devl_resource_register);
|
||||
|
||||
static void devlink_resource_unregister(struct devlink *devlink,
|
||||
struct devlink_resource *resource)
|
||||
static void devlink_resource_unregister(struct devlink_resource *resource)
|
||||
{
|
||||
struct devlink_resource *tmp, *child_resource;
|
||||
|
||||
list_for_each_entry_safe(child_resource, tmp, &resource->resource_list,
|
||||
list) {
|
||||
devlink_resource_unregister(devlink, child_resource);
|
||||
devlink_resource_unregister(child_resource);
|
||||
list_del(&child_resource->list);
|
||||
kfree(child_resource);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
__devl_resources_unregister(struct devlink *devlink,
|
||||
struct list_head *resource_list_head)
|
||||
{
|
||||
struct devlink_resource *tmp, *child_resource;
|
||||
|
||||
lockdep_assert_held(&devlink->lock);
|
||||
|
||||
list_for_each_entry_safe(child_resource, tmp, resource_list_head,
|
||||
list) {
|
||||
devlink_resource_unregister(child_resource);
|
||||
list_del(&child_resource->list);
|
||||
kfree(child_resource);
|
||||
}
|
||||
@@ -401,16 +593,7 @@ static void devlink_resource_unregister(struct devlink *devlink,
|
||||
*/
|
||||
void devl_resources_unregister(struct devlink *devlink)
|
||||
{
|
||||
struct devlink_resource *tmp, *child_resource;
|
||||
|
||||
lockdep_assert_held(&devlink->lock);
|
||||
|
||||
list_for_each_entry_safe(child_resource, tmp, &devlink->resource_list,
|
||||
list) {
|
||||
devlink_resource_unregister(devlink, child_resource);
|
||||
list_del(&child_resource->list);
|
||||
kfree(child_resource);
|
||||
}
|
||||
__devl_resources_unregister(devlink, &devlink->resource_list);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devl_resources_unregister);
|
||||
|
||||
@@ -502,3 +685,46 @@ void devl_resource_occ_get_unregister(struct devlink *devlink,
|
||||
resource->occ_get_priv = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devl_resource_occ_get_unregister);
|
||||
|
||||
/**
|
||||
* devl_port_resource_register - devlink port resource register
|
||||
*
|
||||
* @devlink_port: devlink port
|
||||
* @resource_name: resource's name
|
||||
* @resource_size: resource's size
|
||||
* @resource_id: resource's id
|
||||
* @parent_resource_id: resource's parent id
|
||||
* @params: size parameters
|
||||
*
|
||||
* Generic resources should reuse the same names across drivers.
|
||||
* Please see the generic resources list at:
|
||||
* Documentation/networking/devlink/devlink-resource.rst
|
||||
*
|
||||
* Return: 0 on success, negative error code otherwise.
|
||||
*/
|
||||
int
|
||||
devl_port_resource_register(struct devlink_port *devlink_port,
|
||||
const char *resource_name,
|
||||
u64 resource_size, u64 resource_id,
|
||||
u64 parent_resource_id,
|
||||
const struct devlink_resource_size_params *params)
|
||||
{
|
||||
return __devl_resource_register(devlink_port->devlink,
|
||||
&devlink_port->resource_list,
|
||||
resource_name, resource_size,
|
||||
resource_id, parent_resource_id,
|
||||
params);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devl_port_resource_register);
|
||||
|
||||
/**
|
||||
* devl_port_resources_unregister - unregister all devlink port resources
|
||||
*
|
||||
* @devlink_port: devlink port
|
||||
*/
|
||||
void devl_port_resources_unregister(struct devlink_port *devlink_port)
|
||||
{
|
||||
__devl_resources_unregister(devlink_port->devlink,
|
||||
&devlink_port->resource_list);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devl_port_resources_unregister);
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/* Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
|
||||
|
||||
#include <net/devlink.h>
|
||||
|
||||
#include "devl_internal.h"
|
||||
|
||||
static LIST_HEAD(shd_list);
|
||||
static DEFINE_MUTEX(shd_mutex); /* Protects shd_list and shd->list */
|
||||
|
||||
/* This structure represents a shared devlink instance,
|
||||
* there is one created per identifier (e.g., serial number).
|
||||
*/
|
||||
struct devlink_shd {
|
||||
struct list_head list; /* Node in shd list */
|
||||
const char *id; /* Identifier string (e.g., serial number) */
|
||||
refcount_t refcount; /* Reference count */
|
||||
size_t priv_size; /* Size of driver private data */
|
||||
char priv[] __aligned(NETDEV_ALIGN) __counted_by(priv_size);
|
||||
};
|
||||
|
||||
static struct devlink_shd *devlink_shd_lookup(const char *id)
|
||||
{
|
||||
struct devlink_shd *shd;
|
||||
|
||||
list_for_each_entry(shd, &shd_list, list) {
|
||||
if (!strcmp(shd->id, id))
|
||||
return shd;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct devlink_shd *devlink_shd_create(const char *id,
|
||||
const struct devlink_ops *ops,
|
||||
size_t priv_size,
|
||||
const struct device_driver *driver)
|
||||
{
|
||||
struct devlink_shd *shd;
|
||||
struct devlink *devlink;
|
||||
|
||||
devlink = __devlink_alloc(ops, sizeof(struct devlink_shd) + priv_size,
|
||||
&init_net, NULL, driver);
|
||||
if (!devlink)
|
||||
return NULL;
|
||||
shd = devlink_priv(devlink);
|
||||
|
||||
shd->id = kstrdup(id, GFP_KERNEL);
|
||||
if (!shd->id)
|
||||
goto err_devlink_free;
|
||||
shd->priv_size = priv_size;
|
||||
refcount_set(&shd->refcount, 1);
|
||||
|
||||
devl_lock(devlink);
|
||||
devl_register(devlink);
|
||||
devl_unlock(devlink);
|
||||
|
||||
list_add_tail(&shd->list, &shd_list);
|
||||
|
||||
return shd;
|
||||
|
||||
err_devlink_free:
|
||||
devlink_free(devlink);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void devlink_shd_destroy(struct devlink_shd *shd)
|
||||
{
|
||||
struct devlink *devlink = priv_to_devlink(shd);
|
||||
|
||||
list_del(&shd->list);
|
||||
devl_lock(devlink);
|
||||
devl_unregister(devlink);
|
||||
devl_unlock(devlink);
|
||||
kfree(shd->id);
|
||||
devlink_free(devlink);
|
||||
}
|
||||
|
||||
/**
|
||||
* devlink_shd_get - Get or create a shared devlink instance
|
||||
* @id: Identifier string (e.g., serial number) for the shared instance
|
||||
* @ops: Devlink operations structure
|
||||
* @priv_size: Size of private data structure
|
||||
* @driver: Driver associated with the shared devlink instance
|
||||
*
|
||||
* Get an existing shared devlink instance identified by @id, or create
|
||||
* a new one if it doesn't exist. Return the devlink instance with a
|
||||
* reference held. The caller must call devlink_shd_put() when done.
|
||||
*
|
||||
* All callers sharing the same @id must pass identical @ops, @priv_size
|
||||
* and @driver. A mismatch triggers a warning and returns NULL.
|
||||
*
|
||||
* Return: Pointer to the shared devlink instance on success,
|
||||
* NULL on failure
|
||||
*/
|
||||
struct devlink *devlink_shd_get(const char *id,
|
||||
const struct devlink_ops *ops,
|
||||
size_t priv_size,
|
||||
const struct device_driver *driver)
|
||||
{
|
||||
struct devlink *devlink;
|
||||
struct devlink_shd *shd;
|
||||
|
||||
mutex_lock(&shd_mutex);
|
||||
|
||||
shd = devlink_shd_lookup(id);
|
||||
if (!shd) {
|
||||
shd = devlink_shd_create(id, ops, priv_size, driver);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
devlink = priv_to_devlink(shd);
|
||||
if (WARN_ON_ONCE(devlink->ops != ops ||
|
||||
shd->priv_size != priv_size ||
|
||||
devlink->dev_driver != driver)) {
|
||||
shd = NULL;
|
||||
goto unlock;
|
||||
}
|
||||
refcount_inc(&shd->refcount);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&shd_mutex);
|
||||
return shd ? priv_to_devlink(shd) : NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_shd_get);
|
||||
|
||||
/**
|
||||
* devlink_shd_put - Release a reference on a shared devlink instance
|
||||
* @devlink: Shared devlink instance
|
||||
*
|
||||
* Release a reference on a shared devlink instance obtained via
|
||||
* devlink_shd_get().
|
||||
*/
|
||||
void devlink_shd_put(struct devlink *devlink)
|
||||
{
|
||||
struct devlink_shd *shd;
|
||||
|
||||
mutex_lock(&shd_mutex);
|
||||
shd = devlink_priv(devlink);
|
||||
if (refcount_dec_and_test(&shd->refcount))
|
||||
devlink_shd_destroy(shd);
|
||||
mutex_unlock(&shd_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_shd_put);
|
||||
|
||||
/**
|
||||
* devlink_shd_get_priv - Get private data from shared devlink instance
|
||||
* @devlink: Devlink instance
|
||||
*
|
||||
* Returns a pointer to the driver's private data structure within
|
||||
* the shared devlink instance.
|
||||
*
|
||||
* Return: Pointer to private data
|
||||
*/
|
||||
void *devlink_shd_get_priv(struct devlink *devlink)
|
||||
{
|
||||
struct devlink_shd *shd = devlink_priv(devlink);
|
||||
|
||||
return shd->priv;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devlink_shd_get_priv);
|
||||
+2
-1
@@ -182,7 +182,8 @@ static const struct devlink_ops dsa_devlink_ops = {
|
||||
};
|
||||
|
||||
int dsa_devlink_param_get(struct devlink *dl, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
struct devlink_param_gset_ctx *ctx,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct dsa_switch *ds = dsa_devlink_to_ds(dl);
|
||||
|
||||
|
||||
@@ -21,21 +21,21 @@ Test Cases:
|
||||
----------
|
||||
1. test_no_tc_mapping_bandwidth:
|
||||
- Verifies that without TC mapping, bandwidth is NOT distributed according to
|
||||
the configured 80/20 split between TC4 and TC3
|
||||
- This test should fail if bandwidth matches the 80/20 split without TC
|
||||
the configured 20/80 split between TC3 and TC4
|
||||
- This test should fail if bandwidth matches the 20/80 split without TC
|
||||
mapping
|
||||
- Expected: Bandwidth should NOT be distributed as 80/20
|
||||
- Expected: Bandwidth should NOT be distributed as 20/80
|
||||
|
||||
2. test_tc_mapping_bandwidth:
|
||||
- Configures TC mapping using mqprio qdisc
|
||||
- Verifies that with TC mapping, bandwidth IS distributed according to the
|
||||
configured 80/20 split between TC3 and TC4
|
||||
- Expected: Bandwidth should be distributed as 80/20
|
||||
configured 20/80 split between TC3 and TC4
|
||||
- Expected: Bandwidth should be distributed as 20/80
|
||||
|
||||
Bandwidth Distribution:
|
||||
----------------------
|
||||
- TC3 (VLAN 101): Configured for 80% of total bandwidth
|
||||
- TC4 (VLAN 102): Configured for 20% of total bandwidth
|
||||
- TC3 (VLAN 101): Configured for 20% of total bandwidth
|
||||
- TC4 (VLAN 102): Configured for 80% of total bandwidth
|
||||
- Total bandwidth: 1Gbps
|
||||
- Tolerance: +-12%
|
||||
|
||||
@@ -64,43 +64,40 @@ from lib.py import KsftSkipEx, KsftFailEx, KsftXfailEx
|
||||
from lib.py import NetDrvEpEnv, DevlinkFamily
|
||||
from lib.py import NlError
|
||||
from lib.py import cmd, defer, ethtool, ip
|
||||
from lib.py import Iperf3Runner
|
||||
|
||||
|
||||
class BandwidthValidator:
|
||||
"""
|
||||
Validates bandwidth totals and per-TC shares against expected values
|
||||
with a tolerance.
|
||||
Validates total bandwidth and individual shares with tolerance
|
||||
relative to the overall total.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, shares):
|
||||
self.tolerance_percent = 12
|
||||
self.expected_total_gbps = 1.0
|
||||
self.total_min_expected = self.min_expected(self.expected_total_gbps)
|
||||
self.total_max_expected = self.max_expected(self.expected_total_gbps)
|
||||
self.tc_expected_percent = {
|
||||
3: 20.0,
|
||||
4: 80.0,
|
||||
}
|
||||
self.expected_total = sum(shares.values())
|
||||
self.bounds = {}
|
||||
|
||||
for name, exp in shares.items():
|
||||
self.bounds[name] = (self.min_expected(exp), self.max_expected(exp))
|
||||
|
||||
def min_expected(self, value):
|
||||
"""Calculates the minimum acceptable value based on tolerance."""
|
||||
return value - (value * self.tolerance_percent / 100)
|
||||
return value - (self.expected_total * self.tolerance_percent / 100)
|
||||
|
||||
def max_expected(self, value):
|
||||
"""Calculates the maximum acceptable value based on tolerance."""
|
||||
return value + (value * self.tolerance_percent / 100)
|
||||
return value + (self.expected_total * self.tolerance_percent / 100)
|
||||
|
||||
def bound(self, expected, value):
|
||||
"""Returns True if value is within expected tolerance."""
|
||||
return self.min_expected(expected) <= value <= self.max_expected(expected)
|
||||
|
||||
def tc_bandwidth_bound(self, value, tc_ix):
|
||||
def bound(self, values):
|
||||
"""
|
||||
Returns True if the given bandwidth value is within tolerance
|
||||
for the TC's expected bandwidth.
|
||||
Return True if all given values fall within tolerance.
|
||||
"""
|
||||
expected = self.tc_expected_percent[tc_ix]
|
||||
return self.bound(expected, value)
|
||||
for name, value in values.items():
|
||||
low, high = self.bounds[name]
|
||||
if not low <= value <= high:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def setup_vf(cfg, set_tc_mapping=True):
|
||||
@@ -116,8 +113,8 @@ def setup_vf(cfg, set_tc_mapping=True):
|
||||
except Exception as exc:
|
||||
raise KsftSkipEx(f"Failed to enable switchdev mode on {cfg.pci}") from exc
|
||||
try:
|
||||
cmd(f"echo 1 > /sys/class/net/{cfg.ifname}/device/sriov_numvfs")
|
||||
defer(cmd, f"echo 0 > /sys/class/net/{cfg.ifname}/device/sriov_numvfs")
|
||||
cmd(f"echo 1 > /sys/class/net/{cfg.ifname}/device/sriov_numvfs", shell=True)
|
||||
defer(cmd, f"echo 0 > /sys/class/net/{cfg.ifname}/device/sriov_numvfs", shell=True)
|
||||
except Exception as exc:
|
||||
raise KsftSkipEx(f"Failed to enable SR-IOV on {cfg.ifname}") from exc
|
||||
|
||||
@@ -139,8 +136,8 @@ def setup_vlans_on_vf(vf_ifc):
|
||||
Sets up two VLAN interfaces on the given VF, each mapped to a different TC.
|
||||
"""
|
||||
vlan_configs = [
|
||||
{"vlan_id": 101, "tc": 3, "ip": "198.51.100.2"},
|
||||
{"vlan_id": 102, "tc": 4, "ip": "198.51.100.10"},
|
||||
{"vlan_id": 101, "tc": 3, "ip": "198.51.100.1"},
|
||||
{"vlan_id": 102, "tc": 4, "ip": "198.51.100.9"},
|
||||
]
|
||||
|
||||
for config in vlan_configs:
|
||||
@@ -224,13 +221,13 @@ def setup_devlink_rate(cfg):
|
||||
raise KsftFailEx(f"rate_set failed on VF port {port_index}") from exc
|
||||
|
||||
|
||||
def setup_remote_server(cfg):
|
||||
def setup_remote_vlans(cfg):
|
||||
"""
|
||||
Sets up VLAN interfaces and starts iperf3 servers on the remote side.
|
||||
Sets up VLAN interfaces on the remote side.
|
||||
"""
|
||||
remote_dev = cfg.remote_ifname
|
||||
vlan_ids = [101, 102]
|
||||
remote_ips = ["198.51.100.1", "198.51.100.9"]
|
||||
remote_ips = ["198.51.100.2", "198.51.100.10"]
|
||||
|
||||
for vlan_id, ip_addr in zip(vlan_ids, remote_ips):
|
||||
vlan_dev = f"{remote_dev}.{vlan_id}"
|
||||
@@ -238,14 +235,13 @@ def setup_remote_server(cfg):
|
||||
f"type vlan id {vlan_id}", host=cfg.remote)
|
||||
cmd(f"ip addr add {ip_addr}/29 dev {vlan_dev}", host=cfg.remote)
|
||||
cmd(f"ip link set dev {vlan_dev} up", host=cfg.remote)
|
||||
cmd(f"iperf3 -s -1 -B {ip_addr}",background=True, host=cfg.remote)
|
||||
defer(cmd, f"ip link del {vlan_dev}", host=cfg.remote)
|
||||
|
||||
|
||||
def setup_test_environment(cfg, set_tc_mapping=True):
|
||||
"""
|
||||
Sets up the complete test environment including VF creation, VLANs,
|
||||
bridge configuration, devlink rate setup, and the remote server.
|
||||
bridge configuration and devlink rate setup.
|
||||
"""
|
||||
vf_ifc = setup_vf(cfg, set_tc_mapping)
|
||||
ksft_pr(f"Created VF interface: {vf_ifc}")
|
||||
@@ -256,51 +252,39 @@ def setup_test_environment(cfg, set_tc_mapping=True):
|
||||
setup_bridge(cfg)
|
||||
|
||||
setup_devlink_rate(cfg)
|
||||
setup_remote_server(cfg)
|
||||
time.sleep(2)
|
||||
setup_remote_vlans(cfg)
|
||||
|
||||
|
||||
def run_iperf_client(server_ip, local_ip, barrier, min_expected_gbps=0.1):
|
||||
def measure_bandwidth(cfg, server_ip, client_ip, barrier):
|
||||
"""
|
||||
Runs a single iperf3 client instance, binding to the given local IP.
|
||||
Waits on a barrier to synchronize with other threads.
|
||||
Synchronizes with peers and runs an iperf3-based bandwidth measurement
|
||||
between the given endpoints. Returns average Gbps.
|
||||
"""
|
||||
runner = Iperf3Runner(cfg, server_ip=server_ip, client_ip=client_ip)
|
||||
try:
|
||||
barrier.wait(timeout=10)
|
||||
except Exception as exc:
|
||||
raise KsftFailEx("iperf3 barrier wait timed") from exc
|
||||
|
||||
iperf_cmd = ["iperf3", "-c", server_ip, "-B", local_ip, "-J"]
|
||||
result = subprocess.run(iperf_cmd, capture_output=True, text=True,
|
||||
check=True)
|
||||
|
||||
try:
|
||||
output = json.loads(result.stdout)
|
||||
bits_per_second = output["end"]["sum_received"]["bits_per_second"]
|
||||
gbps = bits_per_second / 1e9
|
||||
if gbps < min_expected_gbps:
|
||||
ksft_pr(
|
||||
f"iperf3 bandwidth too low: {gbps:.2f} Gbps "
|
||||
f"(expected ≥ {min_expected_gbps} Gbps)"
|
||||
)
|
||||
return None
|
||||
return gbps
|
||||
except json.JSONDecodeError as exc:
|
||||
ksft_pr(f"Failed to parse iperf3 JSON output: {exc}")
|
||||
return None
|
||||
bw_gbps = runner.measure_bandwidth(reverse=True)
|
||||
except Exception as exc:
|
||||
raise KsftFailEx("iperf3 bandwidth measurement failed") from exc
|
||||
|
||||
return bw_gbps
|
||||
|
||||
|
||||
def run_bandwidth_test():
|
||||
def run_bandwidth_test(cfg):
|
||||
"""
|
||||
Launches iperf3 client threads for each VLAN/TC pair and collects results.
|
||||
Runs parallel bandwidth measurements for each VLAN/TC pair and collects results.
|
||||
"""
|
||||
def _run_iperf_client_thread(server_ip, local_ip, results, barrier, tc_ix):
|
||||
results[tc_ix] = run_iperf_client(server_ip, local_ip, barrier)
|
||||
def _run_measure_bandwidth_thread(local_ip, remote_ip, results, barrier, tc_ix):
|
||||
results[tc_ix] = measure_bandwidth(cfg, local_ip, remote_ip, barrier)
|
||||
|
||||
vf_vlan_data = [
|
||||
# (local_ip, remote_ip, TC)
|
||||
("198.51.100.2", "198.51.100.1", 3),
|
||||
("198.51.100.10", "198.51.100.9", 4),
|
||||
("198.51.100.1", "198.51.100.2", 3),
|
||||
("198.51.100.9", "198.51.100.10", 4),
|
||||
]
|
||||
|
||||
results = {}
|
||||
@@ -309,8 +293,8 @@ def run_bandwidth_test():
|
||||
|
||||
for local_ip, remote_ip, tc_ix in vf_vlan_data:
|
||||
thread = threading.Thread(
|
||||
target=_run_iperf_client_thread,
|
||||
args=(remote_ip, local_ip, results, start_barrier, tc_ix)
|
||||
target=_run_measure_bandwidth_thread,
|
||||
args=(local_ip, remote_ip, results, start_barrier, tc_ix)
|
||||
)
|
||||
thread.start()
|
||||
threads.append(thread)
|
||||
@@ -320,10 +304,11 @@ def run_bandwidth_test():
|
||||
|
||||
for tc_ix, tc_bw in results.items():
|
||||
if tc_bw is None:
|
||||
raise KsftFailEx("iperf3 client failed; cannot evaluate bandwidth")
|
||||
raise KsftFailEx("iperf3 failed; cannot evaluate bandwidth")
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def calculate_bandwidth_percentages(results):
|
||||
"""
|
||||
Calculates the percentage of total bandwidth received by TC3 and TC4.
|
||||
@@ -364,59 +349,48 @@ def verify_total_bandwidth(bw_data, validator):
|
||||
"""
|
||||
total = bw_data['total_bw']
|
||||
|
||||
if validator.bound(validator.expected_total_gbps, total):
|
||||
if validator.bound({"total": total}):
|
||||
return
|
||||
|
||||
if total < validator.total_min_expected:
|
||||
low, high = validator.bounds["total"]
|
||||
|
||||
if total < low:
|
||||
raise KsftSkipEx(
|
||||
f"Total bandwidth {total:.2f} Gbps < minimum "
|
||||
f"{validator.total_min_expected:.2f} Gbps; "
|
||||
f"parent tx_max ({validator.expected_total_gbps:.1f} G) "
|
||||
f"{low:.2f} Gbps; "
|
||||
f"parent tx_max ({validator.expected_total:.1f} G) "
|
||||
f"not reached, cannot validate share"
|
||||
)
|
||||
|
||||
raise KsftFailEx(
|
||||
f"Total bandwidth {total:.2f} Gbps exceeds allowed ceiling "
|
||||
f"{validator.total_max_expected:.2f} Gbps "
|
||||
f"(VF tx_max set to {validator.expected_total_gbps:.1f} G)"
|
||||
f"{high:.2f} Gbps "
|
||||
f"(VF tx_max set to {validator.expected_total:.1f} G)"
|
||||
)
|
||||
|
||||
|
||||
def check_bandwidth_distribution(bw_data, validator):
|
||||
"""
|
||||
Checks whether the measured TC3 and TC4 bandwidth percentages
|
||||
fall within their expected tolerance ranges.
|
||||
|
||||
Returns:
|
||||
bool: True if both TC3 and TC4 percentages are within bounds.
|
||||
"""
|
||||
tc3_valid = validator.tc_bandwidth_bound(bw_data['tc3_percentage'], 3)
|
||||
tc4_valid = validator.tc_bandwidth_bound(bw_data['tc4_percentage'], 4)
|
||||
|
||||
return tc3_valid and tc4_valid
|
||||
|
||||
|
||||
def run_bandwidth_distribution_test(cfg, set_tc_mapping):
|
||||
"""
|
||||
Runs parallel iperf3 tests for both TCs and collects results.
|
||||
Runs parallel bandwidth measurements for both TCs and collects results.
|
||||
"""
|
||||
setup_test_environment(cfg, set_tc_mapping)
|
||||
bandwidths = run_bandwidth_test()
|
||||
bandwidths = run_bandwidth_test(cfg)
|
||||
bw_data = calculate_bandwidth_percentages(bandwidths)
|
||||
test_name = "with TC mapping" if set_tc_mapping else "without TC mapping"
|
||||
print_bandwidth_results(bw_data, test_name)
|
||||
|
||||
verify_total_bandwidth(bw_data, cfg.bw_validator)
|
||||
verify_total_bandwidth(bw_data, cfg.traffic_bw_validator)
|
||||
|
||||
return check_bandwidth_distribution(bw_data, cfg.bw_validator)
|
||||
return cfg.tc_bw_validator.bound({"tc3": bw_data['tc3_percentage'],
|
||||
"tc4": bw_data['tc4_percentage']})
|
||||
|
||||
|
||||
def test_no_tc_mapping_bandwidth(cfg):
|
||||
"""
|
||||
Verifies that bandwidth is not split 80/20 without traffic class mapping.
|
||||
Verifies that bandwidth is not split 20/80 without traffic class mapping.
|
||||
"""
|
||||
pass_bw_msg = "Bandwidth is NOT distributed as 80/20 without TC mapping"
|
||||
fail_bw_msg = "Bandwidth matched 80/20 split without TC mapping"
|
||||
pass_bw_msg = "Bandwidth is NOT distributed as 20/80 without TC mapping"
|
||||
fail_bw_msg = "Bandwidth matched 20/80 split without TC mapping"
|
||||
is_mlx5 = "driver: mlx5" in ethtool(f"-i {cfg.ifname}").stdout
|
||||
|
||||
if run_bandwidth_distribution_test(cfg, set_tc_mapping=False):
|
||||
@@ -430,13 +404,13 @@ def test_no_tc_mapping_bandwidth(cfg):
|
||||
|
||||
def test_tc_mapping_bandwidth(cfg):
|
||||
"""
|
||||
Verifies that bandwidth is correctly split 80/20 between TC3 and TC4
|
||||
Verifies that bandwidth is correctly split 20/80 between TC3 and TC4
|
||||
when traffic class mapping is set.
|
||||
"""
|
||||
if run_bandwidth_distribution_test(cfg, set_tc_mapping=True):
|
||||
ksft_pr("Bandwidth is distributed as 80/20 with TC mapping")
|
||||
ksft_pr("Bandwidth is distributed as 20/80 with TC mapping")
|
||||
else:
|
||||
raise KsftFailEx("Bandwidth did not match 80/20 split with TC mapping")
|
||||
raise KsftFailEx("Bandwidth did not match 20/80 split with TC mapping")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
@@ -451,10 +425,9 @@ def main() -> None:
|
||||
)
|
||||
if not cfg.pci:
|
||||
raise KsftSkipEx("Could not get PCI address of the interface")
|
||||
cfg.require_cmd("iperf3")
|
||||
cfg.require_cmd("iperf3", remote=True)
|
||||
|
||||
cfg.bw_validator = BandwidthValidator()
|
||||
cfg.traffic_bw_validator = BandwidthValidator({"total": 1})
|
||||
cfg.tc_bw_validator = BandwidthValidator({"tc3": 20, "tc4": 80})
|
||||
|
||||
cases = [test_no_tc_mapping_bandwidth, test_tc_mapping_bandwidth]
|
||||
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
|
||||
lib_dir=$(dirname $0)/../../../net/forwarding
|
||||
|
||||
ALL_TESTS="fw_flash_test params_test regions_test reload_test \
|
||||
netns_reload_test resource_test dev_info_test \
|
||||
ALL_TESTS="fw_flash_test params_test \
|
||||
params_default_test regions_test reload_test \
|
||||
netns_reload_test resource_test resource_dump_test \
|
||||
port_resource_doit_test dev_info_test \
|
||||
empty_reporter_test dummy_reporter_test rate_test"
|
||||
NUM_NETIFS=0
|
||||
source $lib_dir/lib.sh
|
||||
@@ -78,17 +80,28 @@ fw_flash_test()
|
||||
param_get()
|
||||
{
|
||||
local name=$1
|
||||
local attr=${2:-value}
|
||||
local cmode=${3:-driverinit}
|
||||
|
||||
cmd_jq "devlink dev param show $DL_HANDLE name $name -j" \
|
||||
'.[][][].values[] | select(.cmode == "driverinit").value'
|
||||
'.[][][].values[] | select(.cmode == "'"$cmode"'").'"$attr"
|
||||
}
|
||||
|
||||
param_set()
|
||||
{
|
||||
local name=$1
|
||||
local value=$2
|
||||
local cmode=${3:-driverinit}
|
||||
|
||||
devlink dev param set $DL_HANDLE name $name cmode driverinit value $value
|
||||
devlink dev param set $DL_HANDLE name $name cmode $cmode value $value
|
||||
}
|
||||
|
||||
param_set_default()
|
||||
{
|
||||
local name=$1
|
||||
local cmode=${2:-driverinit}
|
||||
|
||||
devlink dev param set $DL_HANDLE name $name default cmode $cmode
|
||||
}
|
||||
|
||||
check_value()
|
||||
@@ -97,12 +110,18 @@ check_value()
|
||||
local phase_name=$2
|
||||
local expected_param_value=$3
|
||||
local expected_debugfs_value=$4
|
||||
local cmode=${5:-driverinit}
|
||||
local value
|
||||
local attr="value"
|
||||
|
||||
value=$(param_get $name)
|
||||
check_err $? "Failed to get $name param value"
|
||||
if [[ "$phase_name" == *"default"* ]]; then
|
||||
attr="default"
|
||||
fi
|
||||
|
||||
value=$(param_get $name $attr $cmode)
|
||||
check_err $? "Failed to get $name param $attr"
|
||||
[ "$value" == "$expected_param_value" ]
|
||||
check_err $? "Unexpected $phase_name $name param value"
|
||||
check_err $? "Unexpected $phase_name $name param $attr"
|
||||
value=$(<$DEBUGFS_DIR/$name)
|
||||
check_err $? "Failed to get $name debugfs value"
|
||||
[ "$value" == "$expected_debugfs_value" ]
|
||||
@@ -135,6 +154,92 @@ params_test()
|
||||
log_test "params test"
|
||||
}
|
||||
|
||||
value_to_debugfs()
|
||||
{
|
||||
local value=$1
|
||||
|
||||
case "$value" in
|
||||
true)
|
||||
echo "Y"
|
||||
;;
|
||||
false)
|
||||
echo "N"
|
||||
;;
|
||||
*)
|
||||
echo "$value"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
test_default()
|
||||
{
|
||||
local param_name=$1
|
||||
local new_value=$2
|
||||
local expected_default=$3
|
||||
local cmode=${4:-driverinit}
|
||||
local default_debugfs
|
||||
local new_debugfs
|
||||
local expected_debugfs
|
||||
|
||||
default_debugfs=$(value_to_debugfs $expected_default)
|
||||
new_debugfs=$(value_to_debugfs $new_value)
|
||||
|
||||
expected_debugfs=$default_debugfs
|
||||
check_value $param_name initial-default $expected_default $expected_debugfs $cmode
|
||||
|
||||
param_set $param_name $new_value $cmode
|
||||
check_err $? "Failed to set $param_name to $new_value"
|
||||
|
||||
expected_debugfs=$([ "$cmode" == "runtime" ] && echo "$new_debugfs" || echo "$default_debugfs")
|
||||
check_value $param_name post-set $new_value $expected_debugfs $cmode
|
||||
|
||||
devlink dev reload $DL_HANDLE
|
||||
check_err $? "Failed to reload device"
|
||||
|
||||
expected_debugfs=$new_debugfs
|
||||
check_value $param_name post-reload-new-value $new_value $expected_debugfs $cmode
|
||||
|
||||
param_set_default $param_name $cmode
|
||||
check_err $? "Failed to set $param_name to default"
|
||||
|
||||
expected_debugfs=$([ "$cmode" == "runtime" ] && echo "$default_debugfs" || echo "$new_debugfs")
|
||||
check_value $param_name post-set-default $expected_default $expected_debugfs $cmode
|
||||
|
||||
devlink dev reload $DL_HANDLE
|
||||
check_err $? "Failed to reload device"
|
||||
|
||||
expected_debugfs=$default_debugfs
|
||||
check_value $param_name post-reload-default $expected_default $expected_debugfs $cmode
|
||||
}
|
||||
|
||||
params_default_test()
|
||||
{
|
||||
RET=0
|
||||
|
||||
if ! devlink dev param help 2>&1 | grep -q "value VALUE | default"; then
|
||||
echo "SKIP: devlink cli missing default feature"
|
||||
return
|
||||
fi
|
||||
|
||||
# Remove side effects of previous tests. Use plain param_set, because
|
||||
# param_set_default is a feature under test here.
|
||||
param_set max_macs 32 driverinit
|
||||
check_err $? "Failed to reset max_macs to default value"
|
||||
param_set test1 true driverinit
|
||||
check_err $? "Failed to reset test1 to default value"
|
||||
param_set test2 1234 runtime
|
||||
check_err $? "Failed to reset test2 to default value"
|
||||
|
||||
devlink dev reload $DL_HANDLE
|
||||
check_err $? "Failed to reload device for clean state"
|
||||
|
||||
test_default max_macs 16 32 driverinit
|
||||
test_default test1 false true driverinit
|
||||
test_default test2 100 1234 runtime
|
||||
|
||||
log_test "params default test"
|
||||
}
|
||||
|
||||
check_region_size()
|
||||
{
|
||||
local name=$1
|
||||
@@ -378,6 +483,56 @@ resource_test()
|
||||
log_test "resource test"
|
||||
}
|
||||
|
||||
resource_dump_test()
|
||||
{
|
||||
RET=0
|
||||
|
||||
local port_jq
|
||||
local dev_jq
|
||||
local dl_jq
|
||||
local count
|
||||
|
||||
dl_jq="with_entries(select(.key | startswith(\"$DL_HANDLE\")))"
|
||||
port_jq="[.[] | $dl_jq | keys |"
|
||||
port_jq+=" map(select(test(\"/.+/\"))) | length] | add"
|
||||
dev_jq="[.[] | $dl_jq | keys |"
|
||||
dev_jq+=" map(select(test(\"/.+/\")|not)) | length] | add"
|
||||
|
||||
if ! devlink resource help 2>&1 | grep -q "scope"; then
|
||||
echo "SKIP: devlink resource show not supported"
|
||||
return
|
||||
fi
|
||||
|
||||
devlink resource show > /dev/null 2>&1
|
||||
check_err $? "Failed to dump all resources"
|
||||
|
||||
count=$(cmd_jq "devlink resource show -j" "$port_jq")
|
||||
[ "$count" -gt "0" ]
|
||||
check_err $? "missing port resources in resource dump"
|
||||
|
||||
count=$(cmd_jq "devlink resource show -j" "$dev_jq")
|
||||
[ "$count" -gt "0" ]
|
||||
check_err $? "missing device resources in resource dump"
|
||||
|
||||
count=$(cmd_jq "devlink resource show scope dev -j" "$dev_jq")
|
||||
[ "$count" -gt "0" ]
|
||||
check_err $? "dev scope missing device resources"
|
||||
|
||||
count=$(cmd_jq "devlink resource show scope dev -j" "$port_jq")
|
||||
[ "$count" -eq "0" ]
|
||||
check_err $? "dev scope returned port resources"
|
||||
|
||||
count=$(cmd_jq "devlink resource show scope port -j" "$port_jq")
|
||||
[ "$count" -gt "0" ]
|
||||
check_err $? "port scope missing port resources"
|
||||
|
||||
count=$(cmd_jq "devlink resource show scope port -j" "$dev_jq")
|
||||
[ "$count" -eq "0" ]
|
||||
check_err $? "port scope returned device resources"
|
||||
|
||||
log_test "resource dump test"
|
||||
}
|
||||
|
||||
info_get()
|
||||
{
|
||||
local name=$1
|
||||
@@ -664,6 +819,32 @@ rate_node_del()
|
||||
devlink port function rate del $handle
|
||||
}
|
||||
|
||||
port_resource_doit_test()
|
||||
{
|
||||
RET=0
|
||||
|
||||
local port_handle="${DL_HANDLE}/0"
|
||||
local name
|
||||
local size
|
||||
|
||||
if ! devlink resource help 2>&1 | grep -q "PORT_INDEX"; then
|
||||
echo "SKIP: devlink resource show with port not supported"
|
||||
return
|
||||
fi
|
||||
|
||||
name=$(cmd_jq "devlink resource show $port_handle -j" \
|
||||
'.[][][].name')
|
||||
[ "$name" == "test_resource" ]
|
||||
check_err $? "wrong port resource name (got $name)"
|
||||
|
||||
size=$(cmd_jq "devlink resource show $port_handle -j" \
|
||||
'.[][][].size')
|
||||
[ "$size" == "20" ]
|
||||
check_err $? "wrong port resource size (got $size)"
|
||||
|
||||
log_test "port resource doit test"
|
||||
}
|
||||
|
||||
rate_test()
|
||||
{
|
||||
RET=0
|
||||
|
||||
Reference in New Issue
Block a user