mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-27 21:03:31 -04:00
Merge branch 'for-linus' into for-next
Pull 7.2 devel branch for put_device auto-clean fixes. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
13
.mailmap
13
.mailmap
@@ -66,6 +66,11 @@ Alex Hung <alexhung@gmail.com> <alex.hung@canonical.com>
|
||||
Alex Shi <alexs@kernel.org> <alex.shi@intel.com>
|
||||
Alex Shi <alexs@kernel.org> <alex.shi@linaro.org>
|
||||
Alex Shi <alexs@kernel.org> <alex.shi@linux.alibaba.com>
|
||||
Alice Mikityanska <alice.kernel@fastmail.im> <maxtram95@gmail.com>
|
||||
Alice Mikityanska <alice.kernel@fastmail.im> <maximmi@mellanox.com>
|
||||
Alice Mikityanska <alice.kernel@fastmail.im> <maximmi@nvidia.com>
|
||||
Alice Mikityanska <alice.kernel@fastmail.im> <maxim@isovalent.com>
|
||||
Alice Mikityanska <alice.kernel@fastmail.im> <alice@isovalent.com>
|
||||
Aloka Dixit <quic_alokad@quicinc.com> <alokad@codeaurora.org>
|
||||
Al Viro <viro@ftp.linux.org.uk>
|
||||
Al Viro <viro@zenIV.linux.org.uk>
|
||||
@@ -540,6 +545,7 @@ Maciej W. Rozycki <macro@mips.com> <macro@imgtec.com>
|
||||
Maciej W. Rozycki <macro@orcam.me.uk> <macro@linux-mips.org>
|
||||
Maharaja Kennadyrajan <quic_mkenna@quicinc.com> <mkenna@codeaurora.org>
|
||||
Maheshwar Ajja <quic_majja@quicinc.com> <majja@codeaurora.org>
|
||||
Maíra Canal <mairacanal@riseup.net> <maira.canal@usp.br>
|
||||
Malathi Gottam <quic_mgottam@quicinc.com> <mgottam@codeaurora.org>
|
||||
Manikanta Pubbisetty <quic_mpubbise@quicinc.com> <mpubbise@codeaurora.org>
|
||||
Manivannan Sadhasivam <mani@kernel.org> <manivannanece23@gmail.com>
|
||||
@@ -585,8 +591,6 @@ Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@osg.samsung.com>
|
||||
Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@redhat.com>
|
||||
Mauro Carvalho Chehab <mchehab@kernel.org> <m.chehab@samsung.com>
|
||||
Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@s-opensource.com>
|
||||
Maxim Mikityanskiy <maxtram95@gmail.com> <maximmi@mellanox.com>
|
||||
Maxim Mikityanskiy <maxtram95@gmail.com> <maximmi@nvidia.com>
|
||||
Maxime Ripard <mripard@kernel.org> <maxime@cerno.tech>
|
||||
Maxime Ripard <mripard@kernel.org> <maxime.ripard@bootlin.com>
|
||||
Maxime Ripard <mripard@kernel.org> <maxime.ripard@free-electrons.com>
|
||||
@@ -595,8 +599,8 @@ Mayuresh Janorkar <mayur@ti.com>
|
||||
Md Sadre Alam <quic_mdalam@quicinc.com> <mdalam@codeaurora.org>
|
||||
Miaoqing Pan <quic_miaoqing@quicinc.com> <miaoqing@codeaurora.org>
|
||||
Michael Buesch <m@bues.ch>
|
||||
Michal Grzeschik <mgr@kernel.org> <m.grzeschik@pengutronix.de>
|
||||
Michal Grzeschik <mgr@kernel.org> <mgr@pengutronix.de>
|
||||
Michael Grzeschik <mgr@kernel.org> <m.grzeschik@pengutronix.de>
|
||||
Michael Grzeschik <mgr@kernel.org> <mgr@pengutronix.de>
|
||||
Michael Riesch <michael.riesch@collabora.com> <michael.riesch@wolfvision.net>
|
||||
Michal Simek <michal.simek@amd.com> <michal.simek@xilinx.com>
|
||||
Michel Dänzer <michel@tungstengraphics.com>
|
||||
@@ -817,6 +821,7 @@ Simon Wunderlich <sw@simonwunderlich.de> <simon.wunderlich@s2003.tu-chemnitz.de>
|
||||
Simon Wunderlich <sw@simonwunderlich.de> <simon.wunderlich@saxnet.de>
|
||||
Simon Wunderlich <sw@simonwunderlich.de> <simon@open-mesh.com>
|
||||
Simon Wunderlich <sw@simonwunderlich.de> <siwu@hrz.tu-chemnitz.de>
|
||||
SJ Park <sj@kernel.org>
|
||||
Sricharan Ramabadhran <quic_srichara@quicinc.com> <sricharan@codeaurora.org>
|
||||
Srinivas Kandagatla <srini@kernel.org> <srinivas.kandagatla@st.com>
|
||||
Srinivas Kandagatla <srini@kernel.org> <srinivas.kandagatla@linaro.org>
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
what: /sys/kernel/mm/damon/
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Interface for Data Access MONitoring (DAMON). Contains files
|
||||
for controlling DAMON. For more details on DAMON itself,
|
||||
please refer to Documentation/admin-guide/mm/damon/index.rst.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Interface for privileged users of DAMON. Contains files for
|
||||
controlling DAMON that aimed to be used by privileged users.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/nr_kdamonds
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a number 'N' to this file creates the number of
|
||||
directories for controlling each DAMON worker thread (kdamond)
|
||||
named '0' to 'N-1' under the kdamonds/ directory.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/state
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing 'on' or 'off' to this file makes the kdamond starts or
|
||||
stops, respectively. Reading the file returns the keywords
|
||||
based on the current status. Writing 'commit' to this file
|
||||
@@ -40,33 +40,33 @@ Description: Writing 'on' or 'off' to this file makes the kdamond starts or
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/pid
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Reading this file returns the pid of the kdamond if it is
|
||||
running.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/refresh_ms
|
||||
Date: Jul 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a value to this file sets the time interval for
|
||||
automatic DAMON status file contents update. Writing '0'
|
||||
disables the update. Reading this file returns the value.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/nr_contexts
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a number 'N' to this file creates the number of
|
||||
directories for controlling each DAMON context named '0' to
|
||||
'N-1' under the contexts/ directory.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/avail_operations
|
||||
Date: Apr 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Reading this file returns the available monitoring operations
|
||||
sets on the currently running kernel.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/operations
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a keyword for a monitoring operations set ('vaddr' for
|
||||
virtual address spaces monitoring, 'fvaddr' for fixed virtual
|
||||
address ranges monitoring, and 'paddr' for the physical address
|
||||
@@ -79,42 +79,42 @@ Description: Writing a keyword for a monitoring operations set ('vaddr' for
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/addr_unit
|
||||
Date: Aug 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing an integer to this file sets the 'address unit'
|
||||
parameter of the given operations set of the context. Reading
|
||||
the file returns the last-written 'address unit' value.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/pause
|
||||
Date: Mar 2026
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a boolean keyword to this file sets the 'pause' request
|
||||
parameter for the context. Reading the file returns the
|
||||
last-written 'pause' value.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/monitoring_attrs/intervals/sample_us
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a value to this file sets the sampling interval of the
|
||||
DAMON context in microseconds as the value. Reading this file
|
||||
returns the value.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/monitoring_attrs/intervals/aggr_us
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a value to this file sets the aggregation interval of
|
||||
the DAMON context in microseconds as the value. Reading this
|
||||
file returns the value.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/monitoring_attrs/intervals/update_us
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a value to this file sets the update interval of the
|
||||
DAMON context in microseconds as the value. Reading this file
|
||||
returns the value.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/monitoring_attrs/intervals/intrvals_goal/access_bp
|
||||
Date: Feb 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a value to this file sets the monitoring intervals
|
||||
auto-tuning target DAMON-observed access events ratio within
|
||||
the given time interval (aggrs in same directory), in bp
|
||||
@@ -122,7 +122,7 @@ Description: Writing a value to this file sets the monitoring intervals
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/monitoring_attrs/intervals/intrvals_goal/aggrs
|
||||
Date: Feb 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a value to this file sets the time interval to achieve
|
||||
the monitoring intervals auto-tuning target DAMON-observed
|
||||
access events ratio (access_bp in same directory) within.
|
||||
@@ -130,14 +130,14 @@ Description: Writing a value to this file sets the time interval to achieve
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/monitoring_attrs/intervals/intrvals_goal/min_sample_us
|
||||
Date: Feb 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a value to this file sets the minimum value of
|
||||
auto-tuned sampling interval in microseconds. Reading this
|
||||
file returns the value.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/monitoring_attrs/intervals/intrvals_goal/max_sample_us
|
||||
Date: Feb 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a value to this file sets the maximum value of
|
||||
auto-tuned sampling interval in microseconds. Reading this
|
||||
file returns the value.
|
||||
@@ -145,42 +145,42 @@ Description: Writing a value to this file sets the maximum value of
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/monitoring_attrs/nr_regions/min
|
||||
|
||||
WDate: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a value to this file sets the minimum number of
|
||||
monitoring regions of the DAMON context as the value. Reading
|
||||
this file returns the value.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/monitoring_attrs/nr_regions/max
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a value to this file sets the maximum number of
|
||||
monitoring regions of the DAMON context as the value. Reading
|
||||
this file returns the value.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/targets/nr_targets
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a number 'N' to this file creates the number of
|
||||
directories for controlling each DAMON target of the context
|
||||
named '0' to 'N-1' under the contexts/ directory.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/targets/<T>/pid_target
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the pid of
|
||||
the target process if the context is for virtual address spaces
|
||||
monitoring, respectively.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/targets/<T>/obsolete_target
|
||||
Date: Oct 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the
|
||||
obsoleteness of the matching parameters commit destination
|
||||
target.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/targets/<T>/regions/nr_regions
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a number 'N' to this file creates the number of
|
||||
directories for setting each DAMON target memory region of the
|
||||
context named '0' to 'N-1' under the regions/ directory. In
|
||||
@@ -190,181 +190,181 @@ Description: Writing a number 'N' to this file creates the number of
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/targets/<T>/regions/<R>/start
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the start
|
||||
address of the monitoring region.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/targets/<T>/regions/<R>/end
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the end
|
||||
address of the monitoring region.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/nr_schemes
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a number 'N' to this file creates the number of
|
||||
directories for controlling each DAMON-based operation scheme
|
||||
of the context named '0' to 'N-1' under the schemes/ directory.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/action
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the action
|
||||
of the scheme.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/target_nid
|
||||
Date: Jun 2024
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Action's target NUMA node id. Supported by only relevant
|
||||
actions.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/apply_interval_us
|
||||
Date: Sep 2023
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a value to this file sets the action apply interval of
|
||||
the scheme in microseconds. Reading this file returns the
|
||||
value.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/access_pattern/sz/min
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the minimum
|
||||
size of the scheme's target regions in bytes.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/access_pattern/sz/max
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the maximum
|
||||
size of the scheme's target regions in bytes.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/access_pattern/nr_accesses/min
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the manimum
|
||||
'nr_accesses' of the scheme's target regions.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/access_pattern/nr_accesses/max
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the maximum
|
||||
'nr_accesses' of the scheme's target regions.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/access_pattern/age/min
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the minimum
|
||||
'age' of the scheme's target regions.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/access_pattern/age/max
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the maximum
|
||||
'age' of the scheme's target regions.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/quotas/ms
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the time
|
||||
quota of the scheme in milliseconds.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/quotas/bytes
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the size
|
||||
quota of the scheme in bytes.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/quotas/effective_bytes
|
||||
Date: Feb 2024
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Reading from this file gets the effective size quota of the
|
||||
scheme in bytes, which adjusted for the time quota and goals.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/quotas/reset_interval_ms
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the quotas
|
||||
charge reset interval of the scheme in milliseconds.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/quotas/goals/nr_goals
|
||||
Date: Nov 2023
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a number 'N' to this file creates the number of
|
||||
directories for setting automatic tuning of the scheme's
|
||||
aggressiveness named '0' to 'N-1' under the goals/ directory.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/quotas/goals/<G>/target_metric
|
||||
Date: Feb 2024
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the quota
|
||||
auto-tuning goal metric.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/quotas/goals/<G>/target_value
|
||||
Date: Nov 2023
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the target
|
||||
value of the goal metric.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/quotas/goals/<G>/current_value
|
||||
Date: Nov 2023
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the current
|
||||
value of the goal metric.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/quotas/goals/<G>/nid
|
||||
Date: Apr 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the nid
|
||||
parameter of the goal.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/quotas/goals/<G>/path
|
||||
Date: Oct 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the path
|
||||
parameter of the goal.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/quotas/goal_tuner
|
||||
Date: Mar 2026
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the
|
||||
goal-based effective quota auto-tuning algorithm to use.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/quotas/fail_charge_num
|
||||
Date: Mar 2026
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the
|
||||
action-failed memory quota charging ratio numerator.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/quotas/fail_charge_denom
|
||||
Date: Mar 2026
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the
|
||||
action-failed memory quota charging ratio denominator.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/quotas/weights/sz_permil
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the
|
||||
under-quota limit regions prioritization weight for 'size' in
|
||||
permil.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/quotas/weights/nr_accesses_permil
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the
|
||||
under-quota limit regions prioritization weight for
|
||||
'nr_accesses' in permil.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/quotas/weights/age_permil
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the
|
||||
under-quota limit regions prioritization weight for 'age' in
|
||||
permil.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/watermarks/metric
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the metric
|
||||
of the watermarks for the scheme. The writable/readable
|
||||
keywords for this file are 'none' for disabling the watermarks
|
||||
@@ -373,44 +373,44 @@ Description: Writing to and reading from this file sets and gets the metric
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/watermarks/interval_us
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the metric
|
||||
check interval of the watermarks for the scheme in
|
||||
microseconds.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/watermarks/high
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the high
|
||||
watermark of the scheme in permil.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/watermarks/mid
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the mid
|
||||
watermark of the scheme in permil.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/watermarks/low
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the low
|
||||
watermark of the scheme in permil.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/core_filters
|
||||
Date: Feb 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Directory for DAMON core layer-handled DAMOS filters.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/core_filters/nr_filters
|
||||
Date: Feb 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a number 'N' to this file creates the number of
|
||||
directories for setting filters of the scheme named '0' to
|
||||
'N-1' under the core_filters/ directory.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/core_filters/<F>/type
|
||||
Date: Feb 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the type of
|
||||
the memory of the interest. 'anon' for anonymous pages,
|
||||
'memcg' for specific memory cgroup, 'young' for young pages,
|
||||
@@ -419,62 +419,62 @@ Description: Writing to and reading from this file sets and gets the type of
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/core_filters/<F>/memcg_path
|
||||
Date: Feb 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: If 'memcg' is written to the 'type' file, writing to and
|
||||
reading from this file sets and gets the path to the memory
|
||||
cgroup of the interest.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/core_filters/<F>/addr_start
|
||||
Date: Feb 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: If 'addr' is written to the 'type' file, writing to or reading
|
||||
from this file sets or gets the start address of the address
|
||||
range for the filter.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/core_filters/<F>/addr_end
|
||||
Date: Feb 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: If 'addr' is written to the 'type' file, writing to or reading
|
||||
from this file sets or gets the end address of the address
|
||||
range for the filter.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/core_filters/<F>/min
|
||||
Date: Feb 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: If 'hugepage_size' is written to the 'type' file, writing to
|
||||
or reading from this file sets or gets the minimum size of the
|
||||
hugepage for the filter.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/core_filters/<F>/max
|
||||
Date: Feb 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: If 'hugepage_size' is written to the 'type' file, writing to
|
||||
or reading from this file sets or gets the maximum size of the
|
||||
hugepage for the filter.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/core_filters/<F>/damon_target_idx
|
||||
Date: Feb 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: If 'target' is written to the 'type' file, writing to or
|
||||
reading from this file sets or gets the index of the DAMON
|
||||
monitoring target of the interest.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/core_filters/<F>/matching
|
||||
Date: Feb 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing 'Y' or 'N' to this file sets whether the filter is for
|
||||
the memory of the 'type', or all except the 'type'.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/core_filters/<F>/allow
|
||||
Date: Feb 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing 'Y' or 'N' to this file sets whether to allow or reject
|
||||
applying the scheme's action to the memory that satisfies the
|
||||
'type' and the 'matching' of the directory.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/ops_filters
|
||||
Date: Feb 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Directory for DAMON operations set layer-handled DAMOS filters.
|
||||
Files under this directory works same to those of
|
||||
/sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/core_filters
|
||||
@@ -482,7 +482,7 @@ Description: Directory for DAMON operations set layer-handled DAMOS filters.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/filters
|
||||
Date: Dec 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Directory for DAMOS filters. Files under this directory works
|
||||
same to those of
|
||||
/sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/{core,ops}_filters
|
||||
@@ -491,14 +491,14 @@ Description: Directory for DAMOS filters. Files under this directory works
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/dests/nr_dests
|
||||
Date: Jul 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a number 'N' to this file creates the number of
|
||||
directories for setting action destinations of the scheme named
|
||||
'0' to 'N-1' under the dests/ directory.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/dests/<D>/id
|
||||
Date: Jul 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the id of
|
||||
the DAMOS action destination. For DAMOS_MIGRATE_{HOT,COLD}
|
||||
actions, the destination node's node id can be written and
|
||||
@@ -506,98 +506,98 @@ Description: Writing to and reading from this file sets and gets the id of
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/dests/<D>/weight
|
||||
Date: Jul 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing to and reading from this file sets and gets the weight
|
||||
of the DAMOS action destination to select as the destination of
|
||||
each action among the destinations.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/stats/nr_tried
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Reading this file returns the number of regions that the action
|
||||
of the scheme has tried to be applied.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/stats/sz_tried
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Reading this file returns the total size of regions that the
|
||||
action of the scheme has tried to be applied in bytes.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/stats/nr_applied
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Reading this file returns the number of regions that the action
|
||||
of the scheme has successfully applied.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/stats/sz_applied
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Reading this file returns the total size of regions that the
|
||||
action of the scheme has successfully applied in bytes.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/stats/sz_ops_filter_passed
|
||||
Date: Dec 2024
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Reading this file returns the total size of memory that passed
|
||||
DAMON operations layer-handled filters of the scheme in bytes.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/stats/qt_exceeds
|
||||
Date: Mar 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Reading this file returns the number of the exceed events of
|
||||
the scheme's quotas.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/stats/nr_snapshots
|
||||
Date: Dec 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Reading this file returns the total number of DAMON snapshots
|
||||
that the scheme has tried to be applied.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/stats/max_nr_snapshots
|
||||
Date: Dec 2025
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Writing a number to this file sets the upper limit of
|
||||
nr_snapshots that deactivates the scheme when the limit is
|
||||
reached or exceeded.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/tried_regions/total_bytes
|
||||
Date: Jul 2023
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Reading this file returns the total amount of memory that
|
||||
corresponding DAMON-based Operation Scheme's action has tried
|
||||
to be applied.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/tried_regions/<R>/start
|
||||
Date: Oct 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Reading this file returns the start address of a memory region
|
||||
that corresponding DAMON-based Operation Scheme's action has
|
||||
tried to be applied.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/tried_regions/<R>/end
|
||||
Date: Oct 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Reading this file returns the end address of a memory region
|
||||
that corresponding DAMON-based Operation Scheme's action has
|
||||
tried to be applied.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/tried_regions/<R>/nr_accesses
|
||||
Date: Oct 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Reading this file returns the 'nr_accesses' of a memory region
|
||||
that corresponding DAMON-based Operation Scheme's action has
|
||||
tried to be applied.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/tried_regions/<R>/age
|
||||
Date: Oct 2022
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Reading this file returns the 'age' of a memory region that
|
||||
corresponding DAMON-based Operation Scheme's action has tried
|
||||
to be applied.
|
||||
|
||||
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/tried_regions/<R>/sz_filter_passed
|
||||
Date: Dec 2024
|
||||
Contact: SeongJae Park <sj@kernel.org>
|
||||
Contact: SJ Park <sj@kernel.org>
|
||||
Description: Reading this file returns the size of the memory in the region
|
||||
that passed DAMON operations layer-handled filters of the
|
||||
scheme in bytes.
|
||||
|
||||
@@ -135,7 +135,6 @@ properties:
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
||||
@@ -24,7 +24,11 @@ allOf:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: spacemit,k1-spi
|
||||
oneOf:
|
||||
- const: spacemit,k1-spi
|
||||
- items:
|
||||
- const: spacemit,k3-spi
|
||||
- const: spacemit,k1-spi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -1585,31 +1585,31 @@ attribute-sets:
|
||||
type: u32
|
||||
-
|
||||
name: mode
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: guard
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: protect
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: fast-leave
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: learning
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: unicast-flood
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: proxyarp
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: learning-sync
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: proxyarp-wifi
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: root-id
|
||||
type: binary
|
||||
@@ -1656,34 +1656,34 @@ attribute-sets:
|
||||
type: pad
|
||||
-
|
||||
name: mcast-flood
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: mcast-to-ucast
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: vlan-tunnel
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: bcast-flood
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: group-fwd-mask
|
||||
type: u16
|
||||
-
|
||||
name: neigh-suppress
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: isolated
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: backup-port
|
||||
type: u32
|
||||
-
|
||||
name: mrp-ring-open
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: mrp-in-open
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: mcast-eht-hosts-limit
|
||||
type: u32
|
||||
@@ -1692,10 +1692,10 @@ attribute-sets:
|
||||
type: u32
|
||||
-
|
||||
name: locked
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: mab
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: mcast-n-groups
|
||||
type: u32
|
||||
@@ -1704,7 +1704,7 @@ attribute-sets:
|
||||
type: u32
|
||||
-
|
||||
name: neigh-vlan-suppress
|
||||
type: flag
|
||||
type: u8
|
||||
-
|
||||
name: backup-nhid
|
||||
type: u32
|
||||
|
||||
@@ -59,7 +59,7 @@ advantechwdt:
|
||||
|
||||
alim1535_wdt:
|
||||
timeout:
|
||||
Watchdog timeout in seconds. (0 < timeout < 18000, default=60
|
||||
Watchdog timeout in seconds. (0 < timeout < 18000, default=60)
|
||||
nowayout:
|
||||
Watchdog cannot be stopped once started
|
||||
(default=kernel config parameter)
|
||||
@@ -68,7 +68,7 @@ alim1535_wdt:
|
||||
|
||||
alim7101_wdt:
|
||||
timeout:
|
||||
Watchdog timeout in seconds. (1<=timeout<=3600, default=30
|
||||
Watchdog timeout in seconds. (1<=timeout<=3600, default=30)
|
||||
use_gpio:
|
||||
Use the gpio watchdog (required by old cobalt boards).
|
||||
default=0/off/no
|
||||
|
||||
17
MAINTAINERS
17
MAINTAINERS
@@ -6478,7 +6478,7 @@ L: linux-cifs@vger.kernel.org
|
||||
L: samba-technical@lists.samba.org (moderated for non-subscribers)
|
||||
S: Supported
|
||||
W: https://wiki.samba.org/index.php/LinuxCIFS
|
||||
T: git https://git.samba.org/sfrench/cifs-2.6.git
|
||||
T: git https://git.samba.org/sfrench/cifs-2.6.git for-next
|
||||
F: Documentation/admin-guide/cifs/
|
||||
F: fs/smb/client/
|
||||
F: fs/smb/common/
|
||||
@@ -7125,7 +7125,7 @@ W: https://docs.dasharo.com/
|
||||
F: drivers/platform/x86/dasharo-acpi.c
|
||||
|
||||
DAMON
|
||||
M: SeongJae Park <sj@kernel.org>
|
||||
M: SJ Park <sj@kernel.org>
|
||||
L: damon@lists.linux.dev
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
@@ -11108,6 +11108,7 @@ F: drivers/platform/x86/gpd-pocket-fan.c
|
||||
|
||||
GPIB DRIVERS
|
||||
M: Dave Penkler <dpenkler@gmail.com>
|
||||
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
S: Maintained
|
||||
F: drivers/gpib/
|
||||
F: include/uapi/linux/gpib.h
|
||||
@@ -14142,7 +14143,7 @@ R: Sergey Senozhatsky <senozhatsky@chromium.org>
|
||||
R: Tom Talpey <tom@talpey.com>
|
||||
L: linux-cifs@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git https://git.samba.org/ksmbd.git
|
||||
T: git https://git.samba.org/ksmbd.git ksmbd-for-next
|
||||
F: Documentation/filesystems/smb/ksmbd.rst
|
||||
F: fs/smb/common/
|
||||
F: fs/smb/server/
|
||||
@@ -17257,6 +17258,7 @@ R: Ryan Roberts <ryan.roberts@arm.com>
|
||||
R: Dev Jain <dev.jain@arm.com>
|
||||
R: Barry Song <baohua@kernel.org>
|
||||
R: Lance Yang <lance.yang@linux.dev>
|
||||
R: Usama Arif <usama.arif@linux.dev>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
W: http://www.linux-mm.org
|
||||
@@ -19108,6 +19110,7 @@ F: drivers/nfc/
|
||||
F: include/net/nfc/
|
||||
F: include/uapi/linux/nfc.h
|
||||
F: net/nfc/
|
||||
F: tools/testing/selftests/nci/
|
||||
|
||||
NFC VIRTUAL NCI DEVICE DRIVER
|
||||
M: Bongsu Jeon <bongsu.jeon@samsung.com>
|
||||
@@ -19299,7 +19302,7 @@ F: fs/ntfs3/
|
||||
|
||||
NTSYNC SYNCHRONIZATION PRIMITIVE DRIVER
|
||||
M: Elizabeth Figura <zfigura@codeweavers.com>
|
||||
L: wine-devel@winehq.org
|
||||
L: wine-devel@list.winehq.org
|
||||
S: Supported
|
||||
F: Documentation/userspace-api/ntsync.rst
|
||||
F: drivers/misc/ntsync.c
|
||||
@@ -25972,8 +25975,9 @@ F: Documentation/devicetree/bindings/phy/st,stm32mp25-combophy.yaml
|
||||
F: drivers/phy/st/phy-stm32-combophy.c
|
||||
|
||||
STMMAC ETHERNET DRIVER
|
||||
M: Maxime Chevallier <maxime.chevallier@bootlin.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Orphan
|
||||
S: Maintained
|
||||
F: Documentation/networking/device_drivers/ethernet/stmicro/
|
||||
F: drivers/net/ethernet/stmicro/stmmac/
|
||||
|
||||
@@ -27929,7 +27933,6 @@ F: drivers/usb/isp1760/*
|
||||
|
||||
USB LAN78XX ETHERNET DRIVER
|
||||
M: Thangaraj Samynathan <Thangaraj.S@microchip.com>
|
||||
M: Rengarajan Sundararajan <Rengarajan.S@microchip.com>
|
||||
M: UNGLinuxDriver@microchip.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
@@ -29398,7 +29401,7 @@ F: net/xdp/
|
||||
F: tools/testing/selftests/bpf/*xsk*
|
||||
|
||||
XEN BLOCK SUBSYSTEM
|
||||
M: Roger Pau Monné <roger.pau@citrix.com>
|
||||
M: Roger Pau Monné <roger@xenproject.org>
|
||||
L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
|
||||
S: Supported
|
||||
F: drivers/block/xen*
|
||||
|
||||
7
Makefile
7
Makefile
@@ -2,7 +2,7 @@
|
||||
VERSION = 7
|
||||
PATCHLEVEL = 2
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc4
|
||||
EXTRAVERSION = -rc5
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
@@ -475,6 +475,10 @@ KBUILD_USERLDFLAGS := $(USERLDFLAGS)
|
||||
|
||||
# These flags apply to all Rust code in the tree, including the kernel and
|
||||
# host programs.
|
||||
#
|
||||
# `-Aclippy::unwrap_or_default`: the lint is buggy [1] and ignores our
|
||||
# MSRV. It can trigger depending on the optimization level.
|
||||
# [1] https://github.com/rust-lang/rust-clippy/issues/17379
|
||||
export rust_common_flags := --edition=2021 \
|
||||
-Zbinary_dep_depinfo=y \
|
||||
-Astable_features \
|
||||
@@ -503,6 +507,7 @@ export rust_common_flags := --edition=2021 \
|
||||
-Aclippy::uninlined_format_args \
|
||||
-Wclippy::unnecessary_safety_comment \
|
||||
-Wclippy::unnecessary_safety_doc \
|
||||
-Aclippy::unwrap_or_default \
|
||||
-Wrustdoc::missing_crate_level_docs \
|
||||
-Wrustdoc::unescaped_backticks
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
* Annoyingly, the negative levels for Address size faults aren't laid out
|
||||
* contiguously (or in the desired order)
|
||||
*/
|
||||
#define ESR_ELx_FSC_ADDRSZ_nL(n) ((n) == -1 ? 0x25 : 0x2C)
|
||||
#define ESR_ELx_FSC_ADDRSZ_nL(n) ((n) == -1 ? 0x29 : 0x2C)
|
||||
#define ESR_ELx_FSC_ADDRSZ_L(n) ((n) < 0 ? ESR_ELx_FSC_ADDRSZ_nL(n) : \
|
||||
(ESR_ELx_FSC_ADDRSZ + (n)))
|
||||
|
||||
|
||||
@@ -78,8 +78,12 @@ enum fixed_addresses {
|
||||
/*
|
||||
* Temporary boot-time mappings, used by early_ioremap(),
|
||||
* before ioremap() is functional.
|
||||
*
|
||||
* Reserve one extra page so a 256K mapping may start at any
|
||||
* offset within a page. early_ioremap() maps the page-aligned
|
||||
* physical range, so the initial offset can consume an extra page.
|
||||
*/
|
||||
#define NR_FIX_BTMAPS (SZ_256K / PAGE_SIZE)
|
||||
#define NR_FIX_BTMAPS ((SZ_256K / PAGE_SIZE) + 1)
|
||||
#define FIX_BTMAPS_SLOTS 7
|
||||
#define TOTAL_FIX_BTMAPS (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
|
||||
|
||||
|
||||
@@ -26,6 +26,12 @@
|
||||
struct prev_kprobe {
|
||||
struct kprobe *kp;
|
||||
unsigned int status;
|
||||
|
||||
/*
|
||||
* The original DAIF state of the outer kprobe, saved here before
|
||||
* a nested kprobe overwrites kcb->saved_irqflag during reentry.
|
||||
*/
|
||||
unsigned long saved_irqflag;
|
||||
};
|
||||
|
||||
/* per-cpu kprobe control block */
|
||||
|
||||
@@ -174,12 +174,27 @@ static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
|
||||
{
|
||||
kcb->prev_kprobe.kp = kprobe_running();
|
||||
kcb->prev_kprobe.status = kcb->kprobe_status;
|
||||
|
||||
/*
|
||||
* Save the outer kprobe's original DAIF flags before the nested
|
||||
* kprobe calls kprobes_save_local_irqflag() and overwrites
|
||||
* kcb->saved_irqflag. Without this, the outer kprobe will restore
|
||||
* the wrong DAIF state and leave interrupts permanently masked.
|
||||
*/
|
||||
kcb->prev_kprobe.saved_irqflag = kcb->saved_irqflag;
|
||||
}
|
||||
|
||||
static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
|
||||
{
|
||||
__this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
|
||||
kcb->kprobe_status = kcb->prev_kprobe.status;
|
||||
|
||||
/*
|
||||
* Restore the outer kprobe's saved_irqflag so that when its
|
||||
* single-step completes, kprobes_restore_local_irqflag() uses
|
||||
* the correct original DAIF value.
|
||||
*/
|
||||
kcb->saved_irqflag = kcb->prev_kprobe.saved_irqflag;
|
||||
}
|
||||
|
||||
static void __kprobes set_current_kprobe(struct kprobe *p)
|
||||
@@ -240,10 +255,16 @@ static int __kprobes reenter_kprobe(struct kprobe *p,
|
||||
switch (kcb->kprobe_status) {
|
||||
case KPROBE_HIT_SSDONE:
|
||||
case KPROBE_HIT_ACTIVE:
|
||||
case KPROBE_HIT_SS:
|
||||
/*
|
||||
* A probe can be hit while another kprobe is preparing or
|
||||
* executing its XOL single-step instruction. This is still a
|
||||
* recoverable one-level reentry, so handle it in the same way as
|
||||
* reentry from KPROBE_HIT_ACTIVE or KPROBE_HIT_SSDONE.
|
||||
*/
|
||||
kprobes_inc_nmissed_count(p);
|
||||
setup_singlestep(p, regs, kcb, 1);
|
||||
break;
|
||||
case KPROBE_HIT_SS:
|
||||
case KPROBE_REENTER:
|
||||
pr_warn("Failed to recover from reentered kprobes.\n");
|
||||
dump_kprobe(p);
|
||||
@@ -282,9 +303,31 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
|
||||
struct kprobe *cur = kprobe_running();
|
||||
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
||||
|
||||
/*
|
||||
* Simulated kprobes execute in the debug trap context and have no
|
||||
* XOL slot. Any page fault taken while a simulated kprobe is in
|
||||
* progress cannot have been caused by kprobe single-stepping and
|
||||
* must be left alone for the normal page fault handler, including
|
||||
* fixup_exception.
|
||||
*/
|
||||
if (cur && !cur->ainsn.xol_insn)
|
||||
return 0;
|
||||
|
||||
switch (kcb->kprobe_status) {
|
||||
case KPROBE_HIT_SS:
|
||||
case KPROBE_REENTER:
|
||||
/*
|
||||
* A page fault taken while in KPROBE_HIT_SS or
|
||||
* KPROBE_REENTER state is only attributable to kprobe
|
||||
* single-stepping if the faulting PC points to the
|
||||
* current kprobe's XOL instruction. If the fault occurred
|
||||
* elsewhere (e.g. in perf or tracing code invoked from the
|
||||
* debug exception path), leave it for the normal page fault
|
||||
* handler to process.
|
||||
*/
|
||||
if (instruction_pointer(regs) != (unsigned long)cur->ainsn.xol_insn)
|
||||
break;
|
||||
|
||||
/*
|
||||
* We are here because the instruction being single
|
||||
* stepped caused a page fault. We reset the current
|
||||
|
||||
@@ -76,6 +76,8 @@ static void data_abort_decode(unsigned long esr)
|
||||
pr_alert(" SF = %lu, AR = %lu\n",
|
||||
(esr & ESR_ELx_SF) >> ESR_ELx_SF_SHIFT,
|
||||
(esr & ESR_ELx_AR) >> ESR_ELx_AR_SHIFT);
|
||||
pr_alert(" Xs = %llu\n",
|
||||
(iss2 & ESR_ELx_Xs_MASK) >> ESR_ELx_Xs_SHIFT);
|
||||
} else {
|
||||
pr_alert(" ISV = 0, ISS = 0x%08lx, ISS2 = 0x%08lx\n",
|
||||
esr & ESR_ELx_ISS_MASK, iss2);
|
||||
@@ -87,11 +89,10 @@ static void data_abort_decode(unsigned long esr)
|
||||
(iss2 & ESR_ELx_TnD) >> ESR_ELx_TnD_SHIFT,
|
||||
(iss2 & ESR_ELx_TagAccess) >> ESR_ELx_TagAccess_SHIFT);
|
||||
|
||||
pr_alert(" GCS = %ld, Overlay = %lu, DirtyBit = %lu, Xs = %llu\n",
|
||||
pr_alert(" GCS = %ld, Overlay = %lu, DirtyBit = %lu\n",
|
||||
(iss2 & ESR_ELx_GCS) >> ESR_ELx_GCS_SHIFT,
|
||||
(iss2 & ESR_ELx_Overlay) >> ESR_ELx_Overlay_SHIFT,
|
||||
(iss2 & ESR_ELx_DirtyBit) >> ESR_ELx_DirtyBit_SHIFT,
|
||||
(iss2 & ESR_ELx_Xs_MASK) >> ESR_ELx_Xs_SHIFT);
|
||||
(iss2 & ESR_ELx_DirtyBit) >> ESR_ELx_DirtyBit_SHIFT);
|
||||
}
|
||||
|
||||
static void mem_abort_decode(unsigned long esr)
|
||||
|
||||
@@ -87,7 +87,7 @@ static int find_num_contig(struct mm_struct *mm, unsigned long addr,
|
||||
p4dp = p4d_offset(pgdp, addr);
|
||||
pudp = pud_offset(p4dp, addr);
|
||||
pmdp = pmd_offset(pudp, addr);
|
||||
if ((pte_t *)pmdp == ptep) {
|
||||
if ((pte_t *)PTR_ALIGN_DOWN(pmdp, sizeof(*pmdp) * CONT_PMDS) == ptep) {
|
||||
*pgsize = PMD_SIZE;
|
||||
return CONT_PMDS;
|
||||
}
|
||||
|
||||
@@ -2194,7 +2194,7 @@ static int prevent_memory_remove_notifier(struct notifier_block *nb,
|
||||
}
|
||||
}
|
||||
|
||||
if (!can_unmap_without_split(pfn, arg->nr_pages))
|
||||
if (!can_unmap_without_split(arg->start_pfn, arg->nr_pages))
|
||||
return NOTIFY_BAD;
|
||||
|
||||
return NOTIFY_OK;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#ifdef CONFIG_64BIT
|
||||
#define TASK_STRUCT_OFFSET 0
|
||||
#else
|
||||
#define TASK_STRUCT_OFFSET 2000
|
||||
#define TASK_STRUCT_OFFSET 2040
|
||||
#endif
|
||||
|
||||
.macro cpu_save_nonscratch thread
|
||||
|
||||
@@ -201,10 +201,12 @@ static void __init acpi_process_madt(void)
|
||||
}
|
||||
|
||||
int pptt_enabled;
|
||||
static int acpi_nr_packages;
|
||||
static int acpi_package_ids[MAX_PACKAGES];
|
||||
|
||||
int __init parse_acpi_topology(void)
|
||||
{
|
||||
int cpu, topology_id;
|
||||
int i, cpu, topology_id;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
topology_id = find_acpi_cpu_topology(cpu, 0);
|
||||
@@ -222,6 +224,29 @@ int __init parse_acpi_topology(void)
|
||||
|
||||
cpu_data[cpu].core = topology_id;
|
||||
}
|
||||
|
||||
topology_id = find_acpi_cpu_topology_package(cpu);
|
||||
if (topology_id < 0) {
|
||||
pr_warn("Invalid BIOS PPTT\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
for (i = 0; i < acpi_nr_packages; i++)
|
||||
if (acpi_package_ids[i] == topology_id)
|
||||
break;
|
||||
|
||||
if (i == acpi_nr_packages)
|
||||
acpi_package_ids[acpi_nr_packages++] = topology_id;
|
||||
|
||||
cpu_data[cpu].package = topology_id;
|
||||
}
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
for (i = 0; i < acpi_nr_packages; i++)
|
||||
if (cpu_data[cpu].package == acpi_package_ids[i]) {
|
||||
cpu_data[cpu].package = i; /* Canonicalize */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pptt_enabled = 1;
|
||||
|
||||
@@ -252,7 +252,8 @@ static int kgdb_loongarch_notify(struct notifier_block *self, unsigned long cmd,
|
||||
if (atomic_read(&kgdb_active) != -1)
|
||||
kgdb_nmicallback(smp_processor_id(), regs);
|
||||
|
||||
if (kgdb_handle_exception(args->trapnr, args->signr, cmd, regs))
|
||||
if (kgdb_handle_exception(regs->csr_era == stepped_address ? 0 : args->trapnr,
|
||||
args->signr, cmd, regs))
|
||||
return NOTIFY_DONE;
|
||||
|
||||
if (atomic_read(&kgdb_setting_breakpoint))
|
||||
|
||||
@@ -42,6 +42,7 @@ static unsigned long first_ind_entry;
|
||||
int machine_kexec_prepare(struct kimage *kimage)
|
||||
{
|
||||
int i;
|
||||
char head[8];
|
||||
char *bootloader = "kexec";
|
||||
void *cmdline_ptr = (void *)KEXEC_CMDLINE_ADDR;
|
||||
|
||||
@@ -59,7 +60,9 @@ int machine_kexec_prepare(struct kimage *kimage)
|
||||
} else {
|
||||
/* Find the command line */
|
||||
for (i = 0; i < kimage->nr_segments; i++) {
|
||||
if (!strncmp(bootloader, (char __user *)kimage->segment[i].buf, strlen(bootloader))) {
|
||||
if (copy_from_user(head, kimage->segment[i].buf, strlen(bootloader)))
|
||||
continue;
|
||||
if (!strncmp(bootloader, head, strlen(bootloader))) {
|
||||
if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_SIZE))
|
||||
kimage->arch.cmdline_ptr = (unsigned long)cmdline_ptr;
|
||||
break;
|
||||
|
||||
@@ -71,27 +71,27 @@
|
||||
cfi_ld s7, PT_R30
|
||||
cfi_ld s8, PT_R31
|
||||
LONG_L t0, sp, PT_CRMD
|
||||
li.d t1, 0x7 /* mask bit[1:0] PLV, bit[2] IE */
|
||||
LONG_LI t1, 0x7 /* mask bit[1:0] PLV, bit[2] IE */
|
||||
csrxchg t0, t1, LOONGARCH_CSR_CRMD
|
||||
.endm
|
||||
|
||||
SYM_CODE_START(arch_rethook_trampoline)
|
||||
UNWIND_HINT_UNDEFINED
|
||||
addi.d sp, sp, -PT_SIZE
|
||||
PTR_ADDI sp, sp, -PT_SIZE
|
||||
save_all_base_regs
|
||||
|
||||
addi.d t0, sp, PT_SIZE
|
||||
LONG_S t0, sp, PT_R3
|
||||
PTR_ADDI t0, sp, PT_SIZE
|
||||
LONG_S t0, sp, PT_R3
|
||||
|
||||
move a0, sp /* pt_regs */
|
||||
move a0, sp /* pt_regs */
|
||||
|
||||
bl arch_rethook_trampoline_callback
|
||||
bl arch_rethook_trampoline_callback
|
||||
|
||||
/* use the result as the return-address */
|
||||
move ra, a0
|
||||
move ra, a0
|
||||
|
||||
restore_all_base_regs
|
||||
addi.d sp, sp, PT_SIZE
|
||||
PTR_ADDI sp, sp, PT_SIZE
|
||||
|
||||
jr ra
|
||||
jr ra
|
||||
SYM_CODE_END(arch_rethook_trampoline)
|
||||
|
||||
@@ -603,6 +603,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
memblock_init();
|
||||
pagetable_init();
|
||||
bootcmdline_init(cmdline_p);
|
||||
jump_label_init(); /* Initialise the static keys for early params */
|
||||
parse_early_param();
|
||||
reserve_initrd_mem();
|
||||
|
||||
@@ -610,8 +611,6 @@ void __init setup_arch(char **cmdline_p)
|
||||
arch_mem_init(cmdline_p);
|
||||
|
||||
resource_init();
|
||||
jump_label_init(); /* Initialise the static keys for paravirtualization */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
plat_smp_setup();
|
||||
prefill_possible_map();
|
||||
|
||||
@@ -426,10 +426,10 @@ void loongson_init_secondary(void)
|
||||
numa_add_cpu(cpu);
|
||||
#endif
|
||||
per_cpu(cpu_state, cpu) = CPU_ONLINE;
|
||||
cpu_data[cpu].package =
|
||||
cpu_logical_map(cpu) / loongson_sysconf.cores_per_package;
|
||||
cpu_data[cpu].core = pptt_enabled ? cpu_data[cpu].core :
|
||||
cpu_logical_map(cpu) % loongson_sysconf.cores_per_package;
|
||||
cpu_data[cpu].package = pptt_enabled ? cpu_data[cpu].package :
|
||||
cpu_logical_map(cpu) / loongson_sysconf.cores_per_package;
|
||||
cpu_data[cpu].global_id = cpu_logical_map(cpu);
|
||||
}
|
||||
|
||||
|
||||
@@ -835,7 +835,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
|
||||
move_reg(ctx, t1, src);
|
||||
emit_sext_32(ctx, t1, is32);
|
||||
emit_insn(ctx, divd, dst, dst, t1);
|
||||
emit_sext_32(ctx, dst, is32);
|
||||
emit_zext_32(ctx, dst, is32);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -852,7 +852,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
|
||||
emit_sext_32(ctx, t1, is32);
|
||||
emit_sext_32(ctx, dst, is32);
|
||||
emit_insn(ctx, divd, dst, dst, t1);
|
||||
emit_sext_32(ctx, dst, is32);
|
||||
emit_zext_32(ctx, dst, is32);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -870,7 +870,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
|
||||
move_reg(ctx, t1, src);
|
||||
emit_sext_32(ctx, t1, is32);
|
||||
emit_insn(ctx, modd, dst, dst, t1);
|
||||
emit_sext_32(ctx, dst, is32);
|
||||
emit_zext_32(ctx, dst, is32);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -887,7 +887,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
|
||||
emit_sext_32(ctx, t1, is32);
|
||||
emit_sext_32(ctx, dst, is32);
|
||||
emit_insn(ctx, modd, dst, dst, t1);
|
||||
emit_sext_32(ctx, dst, is32);
|
||||
emit_zext_32(ctx, dst, is32);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2361,6 +2361,7 @@ void bpf_jit_free(struct bpf_prog *prog)
|
||||
*/
|
||||
if (jit_data) {
|
||||
bpf_jit_binary_pack_finalize(jit_data->ro_header, jit_data->header);
|
||||
kvfree(jit_data->ctx.offset);
|
||||
kfree(jit_data);
|
||||
}
|
||||
hdr = bpf_jit_binary_pack_hdr(prog);
|
||||
|
||||
@@ -110,7 +110,7 @@ void wildfiremod_halt(void)
|
||||
printk(KERN_INFO "WildFireMod hibernating...\n");
|
||||
|
||||
/* Set portE.5 to Digital IO */
|
||||
mcf_write16(read16(MCFGPIO_PEPAR) & ~(1 << (5 * 2)), MCFGPIO_PEPAR);
|
||||
mcf_write16(mcf_read16(MCFGPIO_PEPAR) & ~(1 << (5 * 2)), MCFGPIO_PEPAR);
|
||||
|
||||
/* Make portE.5 an output */
|
||||
mcf_write8(mcf_read8(MCFGPIO_PDDR_E) | (1 << 5), MCFGPIO_PDDR_E);
|
||||
|
||||
@@ -55,10 +55,12 @@ static inline void clear_page(void *page)
|
||||
#define clear_user_page(addr, vaddr, page) \
|
||||
do { clear_page(addr); \
|
||||
flush_dcache_page(page); \
|
||||
(void)(vaddr); \
|
||||
} while (0)
|
||||
#define copy_user_page(to, from, vaddr, page) \
|
||||
do { copy_page(to, from); \
|
||||
flush_dcache_page(page); \
|
||||
(void)(vaddr); \
|
||||
} while (0)
|
||||
|
||||
extern unsigned long m68k_memoffset;
|
||||
|
||||
@@ -209,13 +209,13 @@ struct kvm_vcpu_arch {
|
||||
/*
|
||||
* VCPU interrupts
|
||||
*
|
||||
* We have a lockless approach for tracking pending VCPU interrupts
|
||||
* implemented using atomic bitops. The irqs_pending bitmap represent
|
||||
* pending interrupts whereas irqs_pending_mask represent bits changed
|
||||
* in irqs_pending. Our approach is modeled around multiple producer
|
||||
* and single consumer problem where the consumer is the VCPU itself.
|
||||
* The irqs_pending bitmap represents pending interrupts whereas
|
||||
* irqs_pending_mask represents bits changed in irqs_pending. Updates
|
||||
* to these bitmaps are serialized so vcpu interrupt sync/flush cannot
|
||||
* drop a newly injected interrupt while syncing guest-visible HVIP.
|
||||
*/
|
||||
#define KVM_RISCV_VCPU_NR_IRQS 64
|
||||
raw_spinlock_t irqs_pending_lock;
|
||||
DECLARE_BITMAP(irqs_pending, KVM_RISCV_VCPU_NR_IRQS);
|
||||
DECLARE_BITMAP(irqs_pending_mask, KVM_RISCV_VCPU_NR_IRQS);
|
||||
|
||||
|
||||
@@ -53,12 +53,15 @@ void kvm_riscv_vcpu_aia_flush_interrupts(struct kvm_vcpu *vcpu)
|
||||
struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
|
||||
unsigned long mask, val;
|
||||
|
||||
lockdep_assert_held(&vcpu->arch.irqs_pending_lock);
|
||||
|
||||
if (!kvm_riscv_aia_available())
|
||||
return;
|
||||
|
||||
if (READ_ONCE(vcpu->arch.irqs_pending_mask[1])) {
|
||||
mask = xchg_acquire(&vcpu->arch.irqs_pending_mask[1], 0);
|
||||
val = READ_ONCE(vcpu->arch.irqs_pending[1]) & mask;
|
||||
mask = vcpu->arch.irqs_pending_mask[1];
|
||||
if (mask) {
|
||||
vcpu->arch.irqs_pending_mask[1] = 0;
|
||||
val = vcpu->arch.irqs_pending[1] & mask;
|
||||
|
||||
csr->hviph &= ~mask;
|
||||
csr->hviph |= val;
|
||||
@@ -69,6 +72,8 @@ void kvm_riscv_vcpu_aia_sync_interrupts(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
|
||||
|
||||
lockdep_assert_held(&vcpu->arch.irqs_pending_lock);
|
||||
|
||||
if (kvm_riscv_aia_available())
|
||||
csr->vsieh = ncsr_read(CSR_VSIEH);
|
||||
}
|
||||
@@ -77,13 +82,22 @@ void kvm_riscv_vcpu_aia_sync_interrupts(struct kvm_vcpu *vcpu)
|
||||
bool kvm_riscv_vcpu_aia_has_interrupts(struct kvm_vcpu *vcpu, u64 mask)
|
||||
{
|
||||
unsigned long seip;
|
||||
#ifdef CONFIG_32BIT
|
||||
unsigned long flags;
|
||||
bool pending;
|
||||
#endif
|
||||
|
||||
if (!kvm_riscv_aia_available())
|
||||
return false;
|
||||
|
||||
#ifdef CONFIG_32BIT
|
||||
if (READ_ONCE(vcpu->arch.irqs_pending[1]) &
|
||||
(vcpu->arch.aia_context.guest_csr.vsieh & upper_32_bits(mask)))
|
||||
raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
|
||||
pending = vcpu->arch.irqs_pending[1] &
|
||||
(vcpu->arch.aia_context.guest_csr.vsieh &
|
||||
upper_32_bits(mask));
|
||||
raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
|
||||
|
||||
if (pending)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
@@ -207,6 +221,9 @@ int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu,
|
||||
{
|
||||
struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
|
||||
unsigned long regs_max = sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long);
|
||||
#ifdef CONFIG_32BIT
|
||||
unsigned long flags;
|
||||
#endif
|
||||
|
||||
if (!riscv_isa_extension_available(vcpu->arch.isa, SSAIA))
|
||||
return -ENOENT;
|
||||
@@ -219,8 +236,12 @@ int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu,
|
||||
((unsigned long *)csr)[reg_num] = val;
|
||||
|
||||
#ifdef CONFIG_32BIT
|
||||
if (reg_num == KVM_REG_RISCV_CSR_AIA_REG(siph))
|
||||
WRITE_ONCE(vcpu->arch.irqs_pending_mask[1], 0);
|
||||
if (reg_num == KVM_REG_RISCV_CSR_AIA_REG(siph)) {
|
||||
raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
|
||||
vcpu->arch.irqs_pending_mask[1] = 0;
|
||||
raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock,
|
||||
flags);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/cpufeature.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pgtable.h>
|
||||
#include <asm/kvm_gstage.h>
|
||||
#include <asm/hwcap.h>
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
unsigned long kvm_riscv_gstage_max_pgd_levels __ro_after_init = 3;
|
||||
@@ -171,8 +173,10 @@ int kvm_riscv_gstage_set_pte(struct kvm_gstage *gstage,
|
||||
}
|
||||
|
||||
if (pte_val(*ptep) != pte_val(map->pte)) {
|
||||
bool was_invalid = !pte_val(*ptep);
|
||||
set_pte(ptep, map->pte);
|
||||
if (gstage_pte_leaf(ptep))
|
||||
if (gstage_pte_leaf(ptep) &&
|
||||
!(was_invalid && riscv_has_extension_unlikely(RISCV_ISA_EXT_SVVPTC)))
|
||||
gstage_tlb_flush(gstage, current_level, map->addr);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ int kvm_riscv_mmu_ioremap(struct kvm *kvm, gpa_t gpa, phys_addr_t hpa,
|
||||
pgprot_t prot;
|
||||
unsigned long pfn;
|
||||
phys_addr_t addr, end;
|
||||
unsigned long pgd_levels = kvm->arch.pgd_levels;
|
||||
struct kvm_mmu_memory_cache pcache = {
|
||||
.gfp_custom = (in_atomic) ? GFP_ATOMIC | __GFP_ACCOUNT : 0,
|
||||
.gfp_zero = __GFP_ZERO,
|
||||
@@ -63,7 +64,7 @@ int kvm_riscv_mmu_ioremap(struct kvm *kvm, gpa_t gpa, phys_addr_t hpa,
|
||||
if (!writable)
|
||||
map.pte = pte_wrprotect(map.pte);
|
||||
|
||||
ret = kvm_mmu_topup_memory_cache(&pcache, kvm->arch.pgd_levels);
|
||||
ret = __kvm_mmu_topup_memory_cache(&pcache, pgd_levels, pgd_levels);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ static void kvm_riscv_vcpu_context_reset(struct kvm_vcpu *vcpu,
|
||||
|
||||
static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu, bool kvm_sbi_reset)
|
||||
{
|
||||
unsigned long flags;
|
||||
bool loaded;
|
||||
|
||||
/**
|
||||
@@ -104,8 +105,10 @@ static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu, bool kvm_sbi_reset)
|
||||
|
||||
kvm_riscv_vcpu_aia_reset(vcpu);
|
||||
|
||||
raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
|
||||
bitmap_zero(vcpu->arch.irqs_pending, KVM_RISCV_VCPU_NR_IRQS);
|
||||
bitmap_zero(vcpu->arch.irqs_pending_mask, KVM_RISCV_VCPU_NR_IRQS);
|
||||
raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
|
||||
|
||||
kvm_riscv_vcpu_pmu_reset(vcpu);
|
||||
|
||||
@@ -151,6 +154,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
|
||||
|
||||
/* Setup VCPU hfence queue */
|
||||
spin_lock_init(&vcpu->arch.hfence_lock);
|
||||
raw_spin_lock_init(&vcpu->arch.irqs_pending_lock);
|
||||
|
||||
spin_lock_init(&vcpu->arch.reset_state.lock);
|
||||
|
||||
@@ -352,10 +356,14 @@ void kvm_riscv_vcpu_flush_interrupts(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
|
||||
unsigned long mask, val;
|
||||
unsigned long flags;
|
||||
|
||||
if (READ_ONCE(vcpu->arch.irqs_pending_mask[0])) {
|
||||
mask = xchg_acquire(&vcpu->arch.irqs_pending_mask[0], 0);
|
||||
val = READ_ONCE(vcpu->arch.irqs_pending[0]) & mask;
|
||||
raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
|
||||
|
||||
mask = vcpu->arch.irqs_pending_mask[0];
|
||||
if (mask) {
|
||||
vcpu->arch.irqs_pending_mask[0] = 0;
|
||||
val = vcpu->arch.irqs_pending[0] & mask;
|
||||
|
||||
csr->hvip &= ~mask;
|
||||
csr->hvip |= val;
|
||||
@@ -363,11 +371,14 @@ void kvm_riscv_vcpu_flush_interrupts(struct kvm_vcpu *vcpu)
|
||||
|
||||
/* Flush AIA high interrupts */
|
||||
kvm_riscv_vcpu_aia_flush_interrupts(vcpu);
|
||||
|
||||
raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
|
||||
}
|
||||
|
||||
void kvm_riscv_vcpu_sync_interrupts(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
unsigned long hvip;
|
||||
unsigned long flags;
|
||||
struct kvm_vcpu_arch *v = &vcpu->arch;
|
||||
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
|
||||
|
||||
@@ -376,34 +387,41 @@ void kvm_riscv_vcpu_sync_interrupts(struct kvm_vcpu *vcpu)
|
||||
|
||||
/* Sync-up HVIP.VSSIP bit changes does by Guest */
|
||||
hvip = ncsr_read(CSR_HVIP);
|
||||
|
||||
raw_spin_lock_irqsave(&v->irqs_pending_lock, flags);
|
||||
|
||||
if ((csr->hvip ^ hvip) & (1UL << IRQ_VS_SOFT)) {
|
||||
if (hvip & (1UL << IRQ_VS_SOFT)) {
|
||||
if (!test_and_set_bit(IRQ_VS_SOFT,
|
||||
v->irqs_pending_mask))
|
||||
set_bit(IRQ_VS_SOFT, v->irqs_pending);
|
||||
if (!__test_and_set_bit(IRQ_VS_SOFT,
|
||||
v->irqs_pending_mask))
|
||||
__set_bit(IRQ_VS_SOFT, v->irqs_pending);
|
||||
} else {
|
||||
if (!test_and_set_bit(IRQ_VS_SOFT,
|
||||
v->irqs_pending_mask))
|
||||
clear_bit(IRQ_VS_SOFT, v->irqs_pending);
|
||||
if (!__test_and_set_bit(IRQ_VS_SOFT,
|
||||
v->irqs_pending_mask))
|
||||
__clear_bit(IRQ_VS_SOFT, v->irqs_pending);
|
||||
}
|
||||
}
|
||||
|
||||
/* Sync up the HVIP.LCOFIP bit changes (only clear) by the guest */
|
||||
if ((csr->hvip ^ hvip) & (1UL << IRQ_PMU_OVF)) {
|
||||
if (!(hvip & (1UL << IRQ_PMU_OVF)) &&
|
||||
!test_and_set_bit(IRQ_PMU_OVF, v->irqs_pending_mask))
|
||||
clear_bit(IRQ_PMU_OVF, v->irqs_pending);
|
||||
!__test_and_set_bit(IRQ_PMU_OVF, v->irqs_pending_mask))
|
||||
__clear_bit(IRQ_PMU_OVF, v->irqs_pending);
|
||||
}
|
||||
|
||||
/* Sync-up AIA high interrupts */
|
||||
kvm_riscv_vcpu_aia_sync_interrupts(vcpu);
|
||||
|
||||
raw_spin_unlock_irqrestore(&v->irqs_pending_lock, flags);
|
||||
|
||||
/* Sync-up timer CSRs */
|
||||
kvm_riscv_vcpu_timer_sync(vcpu);
|
||||
}
|
||||
|
||||
int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* We only allow VS-mode software, timer, and external
|
||||
* interrupts when irq is one of the local interrupts
|
||||
@@ -416,9 +434,10 @@ int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
|
||||
irq != IRQ_PMU_OVF)
|
||||
return -EINVAL;
|
||||
|
||||
set_bit(irq, vcpu->arch.irqs_pending);
|
||||
smp_mb__before_atomic();
|
||||
set_bit(irq, vcpu->arch.irqs_pending_mask);
|
||||
raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
|
||||
__set_bit(irq, vcpu->arch.irqs_pending);
|
||||
__set_bit(irq, vcpu->arch.irqs_pending_mask);
|
||||
raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
|
||||
|
||||
kvm_vcpu_kick(vcpu);
|
||||
|
||||
@@ -427,6 +446,8 @@ int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
|
||||
|
||||
int kvm_riscv_vcpu_unset_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* We only allow VS-mode software, timer, counter overflow and external
|
||||
* interrupts when irq is one of the local interrupts
|
||||
@@ -439,26 +460,33 @@ int kvm_riscv_vcpu_unset_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
|
||||
irq != IRQ_PMU_OVF)
|
||||
return -EINVAL;
|
||||
|
||||
clear_bit(irq, vcpu->arch.irqs_pending);
|
||||
smp_mb__before_atomic();
|
||||
set_bit(irq, vcpu->arch.irqs_pending_mask);
|
||||
raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
|
||||
__clear_bit(irq, vcpu->arch.irqs_pending);
|
||||
__set_bit(irq, vcpu->arch.irqs_pending_mask);
|
||||
raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool kvm_riscv_vcpu_has_interrupts(struct kvm_vcpu *vcpu, u64 mask)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long ie;
|
||||
bool ret;
|
||||
|
||||
raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
|
||||
ie = ((vcpu->arch.guest_csr.vsie & VSIP_VALID_MASK)
|
||||
<< VSIP_TO_HVIP_SHIFT) & (unsigned long)mask;
|
||||
ie |= vcpu->arch.guest_csr.vsie & ~IRQ_LOCAL_MASK &
|
||||
(unsigned long)mask;
|
||||
if (READ_ONCE(vcpu->arch.irqs_pending[0]) & ie)
|
||||
return true;
|
||||
ret = vcpu->arch.irqs_pending[0] & ie;
|
||||
raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
|
||||
|
||||
/* Check AIA high interrupts */
|
||||
return kvm_riscv_vcpu_aia_has_interrupts(vcpu, mask);
|
||||
if (!ret)
|
||||
ret = kvm_riscv_vcpu_aia_has_interrupts(vcpu, mask);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __kvm_riscv_vcpu_power_off(struct kvm_vcpu *vcpu)
|
||||
|
||||
@@ -38,6 +38,25 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
|
||||
return kvm_riscv_vcpu_mmio_store(vcpu, run,
|
||||
fault_addr,
|
||||
trap->htinst);
|
||||
case EXC_INST_GUEST_PAGE_FAULT: {
|
||||
/*
|
||||
* No memslot backs this GPA and an instruction fetch
|
||||
* cannot be emulated as MMIO. On bare metal a fetch
|
||||
* from an unbacked physical address raises an
|
||||
* instruction access fault, so reflect that back to
|
||||
* the guest.
|
||||
*/
|
||||
struct kvm_cpu_trap inst_trap = {
|
||||
.sepc = trap->sepc,
|
||||
.scause = EXC_INST_ACCESS,
|
||||
.stval = trap->stval,
|
||||
.htval = 0,
|
||||
.htinst = 0,
|
||||
};
|
||||
|
||||
kvm_riscv_vcpu_trap_redirect(vcpu, &inst_trap);
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
};
|
||||
|
||||
@@ -50,19 +50,13 @@ static int kvm_riscv_vcpu_get_reg_config(struct kvm_vcpu *vcpu,
|
||||
reg_val = vcpu->arch.isa[0] & KVM_RISCV_BASE_ISA_MASK;
|
||||
break;
|
||||
case KVM_REG_RISCV_CONFIG_REG(zicbom_block_size):
|
||||
if (kvm_riscv_isa_check_host(ZICBOM))
|
||||
return -ENOENT;
|
||||
reg_val = riscv_cbom_block_size;
|
||||
reg_val = (kvm_riscv_isa_check_host(ZICBOM)) ? 0 : riscv_cbom_block_size;
|
||||
break;
|
||||
case KVM_REG_RISCV_CONFIG_REG(zicboz_block_size):
|
||||
if (kvm_riscv_isa_check_host(ZICBOZ))
|
||||
return -ENOENT;
|
||||
reg_val = riscv_cboz_block_size;
|
||||
reg_val = (kvm_riscv_isa_check_host(ZICBOZ)) ? 0 : riscv_cboz_block_size;
|
||||
break;
|
||||
case KVM_REG_RISCV_CONFIG_REG(zicbop_block_size):
|
||||
if (kvm_riscv_isa_check_host(ZICBOP))
|
||||
return -ENOENT;
|
||||
reg_val = riscv_cbop_block_size;
|
||||
reg_val = (kvm_riscv_isa_check_host(ZICBOP)) ? 0 : riscv_cbop_block_size;
|
||||
break;
|
||||
case KVM_REG_RISCV_CONFIG_REG(mvendorid):
|
||||
reg_val = vcpu->arch.mvendorid;
|
||||
@@ -144,21 +138,15 @@ static int kvm_riscv_vcpu_set_reg_config(struct kvm_vcpu *vcpu,
|
||||
}
|
||||
break;
|
||||
case KVM_REG_RISCV_CONFIG_REG(zicbom_block_size):
|
||||
if (kvm_riscv_isa_check_host(ZICBOM))
|
||||
return -ENOENT;
|
||||
if (reg_val != riscv_cbom_block_size)
|
||||
if (reg_val && reg_val != riscv_cbom_block_size)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case KVM_REG_RISCV_CONFIG_REG(zicboz_block_size):
|
||||
if (kvm_riscv_isa_check_host(ZICBOZ))
|
||||
return -ENOENT;
|
||||
if (reg_val != riscv_cboz_block_size)
|
||||
if (reg_val && reg_val != riscv_cboz_block_size)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case KVM_REG_RISCV_CONFIG_REG(zicbop_block_size):
|
||||
if (kvm_riscv_isa_check_host(ZICBOP))
|
||||
return -ENOENT;
|
||||
if (reg_val != riscv_cbop_block_size)
|
||||
if (reg_val && reg_val != riscv_cbop_block_size)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case KVM_REG_RISCV_CONFIG_REG(mvendorid):
|
||||
@@ -298,6 +286,7 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
|
||||
{
|
||||
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
|
||||
unsigned long regs_max = sizeof(struct kvm_riscv_csr) / sizeof(unsigned long);
|
||||
unsigned long flags;
|
||||
|
||||
if (reg_num >= regs_max)
|
||||
return -ENOENT;
|
||||
@@ -311,8 +300,11 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
|
||||
|
||||
((unsigned long *)csr)[reg_num] = reg_val;
|
||||
|
||||
if (reg_num == KVM_REG_RISCV_CSR_REG(sip))
|
||||
WRITE_ONCE(vcpu->arch.irqs_pending_mask[0], 0);
|
||||
if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) {
|
||||
raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
|
||||
vcpu->arch.irqs_pending_mask[0] = 0;
|
||||
raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -614,20 +606,6 @@ static int copy_config_reg_indices(const struct kvm_vcpu *vcpu,
|
||||
u64 size;
|
||||
u64 reg;
|
||||
|
||||
/*
|
||||
* Avoid reporting config reg if the corresponding extension
|
||||
* was not available.
|
||||
*/
|
||||
if (i == KVM_REG_RISCV_CONFIG_REG(zicbom_block_size) &&
|
||||
kvm_riscv_isa_check_host(ZICBOM))
|
||||
continue;
|
||||
else if (i == KVM_REG_RISCV_CONFIG_REG(zicboz_block_size) &&
|
||||
kvm_riscv_isa_check_host(ZICBOZ))
|
||||
continue;
|
||||
else if (i == KVM_REG_RISCV_CONFIG_REG(zicbop_block_size) &&
|
||||
kvm_riscv_isa_check_host(ZICBOP))
|
||||
continue;
|
||||
|
||||
size = IS_ENABLED(CONFIG_32BIT) ? KVM_REG_SIZE_U32 : KVM_REG_SIZE_U64;
|
||||
reg = KVM_REG_RISCV | size | KVM_REG_RISCV_CONFIG | i;
|
||||
|
||||
|
||||
@@ -586,7 +586,7 @@ int kvm_riscv_vcpu_pmu_ctr_start(struct kvm_vcpu *vcpu, unsigned long ctr_base,
|
||||
}
|
||||
}
|
||||
/* Start the counters that have been configured and requested by the guest */
|
||||
for_each_set_bit(i, &ctr_mask, RISCV_MAX_COUNTERS) {
|
||||
for_each_set_bit(i, &ctr_mask, BITS_PER_LONG) {
|
||||
pmc_index = array_index_nospec(i + ctr_base,
|
||||
RISCV_KVM_MAX_COUNTERS);
|
||||
if (!test_bit(pmc_index, kvpmu->pmc_in_use))
|
||||
@@ -658,7 +658,7 @@ int kvm_riscv_vcpu_pmu_ctr_stop(struct kvm_vcpu *vcpu, unsigned long ctr_base,
|
||||
}
|
||||
|
||||
/* Stop the counters that have been configured and requested by the guest */
|
||||
for_each_set_bit(i, &ctr_mask, RISCV_MAX_COUNTERS) {
|
||||
for_each_set_bit(i, &ctr_mask, BITS_PER_LONG) {
|
||||
pmc_index = array_index_nospec(i + ctr_base,
|
||||
RISCV_KVM_MAX_COUNTERS);
|
||||
if (!test_bit(pmc_index, kvpmu->pmc_in_use))
|
||||
|
||||
@@ -327,9 +327,11 @@ static int kvm_sbi_fwft_set(struct kvm_vcpu *vcpu, u32 feature,
|
||||
if (conf->flags & SBI_FWFT_SET_FLAG_LOCK)
|
||||
return SBI_ERR_DENIED_LOCKED;
|
||||
|
||||
conf->flags = flags;
|
||||
ret = conf->feature->set(vcpu, conf, false, value);
|
||||
if (ret == SBI_SUCCESS)
|
||||
conf->flags = flags;
|
||||
|
||||
return conf->feature->set(vcpu, conf, false, value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kvm_sbi_fwft_get(struct kvm_vcpu *vcpu, unsigned long feature,
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/kvm_isa.h>
|
||||
@@ -129,11 +130,20 @@ static int kvm_riscv_vcpu_vreg_addr(struct kvm_vcpu *vcpu,
|
||||
return -ENOENT;
|
||||
}
|
||||
} else if (reg_num <= KVM_REG_RISCV_VECTOR_REG(31)) {
|
||||
unsigned long reg_offset;
|
||||
|
||||
if (reg_size != vlenb)
|
||||
return -EINVAL;
|
||||
WARN_ON(!cntx->vector.datap);
|
||||
*reg_addr = cntx->vector.datap +
|
||||
(reg_num - KVM_REG_RISCV_VECTOR_REG(0)) * vlenb;
|
||||
/*
|
||||
* The reg_num is derived from the userspace-provided ONE_REG
|
||||
* id. Sanitize it with array_index_nospec() to prevent
|
||||
* speculative out-of-bounds access to the vector register
|
||||
* buffer (32 vector registers: v0..v31).
|
||||
*/
|
||||
reg_offset = array_index_nospec(
|
||||
reg_num - KVM_REG_RISCV_VECTOR_REG(0), 32);
|
||||
*reg_addr = cntx->vector.datap + reg_offset * vlenb;
|
||||
} else {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ ATOMIC_NOTIFIER_HEAD(s390_epoch_delta_notifier);
|
||||
EXPORT_SYMBOL(s390_epoch_delta_notifier);
|
||||
|
||||
unsigned char ptff_function_mask[16];
|
||||
EXPORT_SYMBOL(ptff_function_mask);
|
||||
|
||||
static unsigned long lpar_offset;
|
||||
static unsigned long initial_leap_seconds;
|
||||
|
||||
@@ -27,6 +27,7 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma \
|
||||
KBUILD_CFLAGS := -m$(BITS) -O2 $(CLANG_FLAGS)
|
||||
KBUILD_CFLAGS += $(CC_FLAGS_DIALECT)
|
||||
KBUILD_CFLAGS += -fno-strict-aliasing -fPIE
|
||||
KBUILD_CFLAGS += -fno-jump-tables
|
||||
KBUILD_CFLAGS += -Wundef
|
||||
KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
|
||||
cflags-$(CONFIG_X86_32) := -march=i386
|
||||
|
||||
@@ -2052,7 +2052,7 @@ static void apic_timer_expired(struct kvm_lapic *apic, bool from_timer_fn)
|
||||
if (apic_lvtt_tscdeadline(apic) || ktimer->hv_timer_in_use)
|
||||
ktimer->expired_tscdeadline = ktimer->tscdeadline;
|
||||
|
||||
if (!from_timer_fn && apic->apicv_active) {
|
||||
if (!from_timer_fn && apic->apicv_active && vcpu->wants_to_run) {
|
||||
WARN_ON(kvm_get_running_vcpu() != vcpu);
|
||||
kvm_apic_inject_pending_timer_irqs(apic);
|
||||
return;
|
||||
|
||||
@@ -2642,6 +2642,7 @@ static int mmu_page_zap_pte(struct kvm *kvm, struct kvm_mmu_page *sp,
|
||||
*/
|
||||
if (tdp_enabled && invalid_list &&
|
||||
child->role.guest_mode &&
|
||||
!child->root_count &&
|
||||
!atomic_long_read(&child->parent_ptes.val))
|
||||
return kvm_mmu_prepare_zap_page(kvm, child,
|
||||
invalid_list);
|
||||
@@ -4852,16 +4853,17 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
|
||||
if (r != RET_PF_CONTINUE)
|
||||
return r;
|
||||
|
||||
r = RET_PF_RETRY;
|
||||
write_lock(&vcpu->kvm->mmu_lock);
|
||||
|
||||
if (is_page_fault_stale(vcpu, fault))
|
||||
goto out_unlock;
|
||||
|
||||
r = make_mmu_pages_available(vcpu);
|
||||
if (r)
|
||||
goto out_unlock;
|
||||
|
||||
if (is_page_fault_stale(vcpu, fault)) {
|
||||
r = RET_PF_RETRY;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
r = direct_map(vcpu, fault);
|
||||
|
||||
out_unlock:
|
||||
@@ -7574,7 +7576,9 @@ void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm, u64 gen)
|
||||
static void mmu_destroy_caches(void)
|
||||
{
|
||||
kmem_cache_destroy(pte_list_desc_cache);
|
||||
pte_list_desc_cache = NULL;
|
||||
kmem_cache_destroy(mmu_page_header_cache);
|
||||
mmu_page_header_cache = NULL;
|
||||
}
|
||||
|
||||
static void kvm_wake_nx_recovery_thread(struct kvm *kvm)
|
||||
|
||||
@@ -864,15 +864,17 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
|
||||
}
|
||||
#endif
|
||||
|
||||
r = RET_PF_RETRY;
|
||||
write_lock(&vcpu->kvm->mmu_lock);
|
||||
|
||||
if (is_page_fault_stale(vcpu, fault))
|
||||
goto out_unlock;
|
||||
|
||||
r = make_mmu_pages_available(vcpu);
|
||||
if (r)
|
||||
goto out_unlock;
|
||||
|
||||
if (is_page_fault_stale(vcpu, fault)) {
|
||||
r = RET_PF_RETRY;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
r = FNAME(fetch)(vcpu, fault, &walker);
|
||||
|
||||
out_unlock:
|
||||
|
||||
@@ -336,6 +336,7 @@ static void nested_put_vmcs12_pages(struct kvm_vcpu *vcpu)
|
||||
static void free_nested(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
struct vmcs *shadow_vmcs;
|
||||
|
||||
if (WARN_ON_ONCE(vmx->loaded_vmcs != &vmx->vmcs01))
|
||||
vmx_switch_vmcs(vcpu, &vmx->vmcs01);
|
||||
@@ -353,9 +354,15 @@ static void free_nested(struct kvm_vcpu *vcpu)
|
||||
vmx->nested.current_vmptr = INVALID_GPA;
|
||||
if (enable_shadow_vmcs) {
|
||||
vmx_disable_shadow_vmcs(vmx);
|
||||
vmcs_clear(vmx->vmcs01.shadow_vmcs);
|
||||
free_vmcs(vmx->vmcs01.shadow_vmcs);
|
||||
|
||||
/*
|
||||
* Keep the pointer visible until after VMCLEAR, so migration
|
||||
* can clear an active shadow VMCS on the old CPU.
|
||||
*/
|
||||
shadow_vmcs = vmx->vmcs01.shadow_vmcs;
|
||||
vmcs_clear(shadow_vmcs);
|
||||
vmx->vmcs01.shadow_vmcs = NULL;
|
||||
free_vmcs(shadow_vmcs);
|
||||
}
|
||||
kfree(vmx->nested.cached_vmcs12);
|
||||
vmx->nested.cached_vmcs12 = NULL;
|
||||
|
||||
@@ -43,20 +43,22 @@ struct aie2_ctx_health {
|
||||
|
||||
static inline void aie2_tdr_signal(struct amdxdna_dev *xdna)
|
||||
{
|
||||
WRITE_ONCE(xdna->dev_handle->tdr_status, AIE2_TDR_SIGNALED);
|
||||
WRITE_ONCE(xdna->dev_handle->last_signal_ts, jiffies);
|
||||
}
|
||||
|
||||
static bool aie2_tdr_detect(struct amdxdna_dev *xdna)
|
||||
{
|
||||
struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
|
||||
unsigned long last = READ_ONCE(ndev->last_signal_ts);
|
||||
|
||||
if (READ_ONCE(ndev->tdr_status) == AIE2_TDR_WAIT) {
|
||||
XDNA_ERR(xdna, "TDR timeout detected");
|
||||
return true;
|
||||
}
|
||||
if (!tdr_timeout_ms)
|
||||
return false;
|
||||
|
||||
WRITE_ONCE(ndev->tdr_status, AIE2_TDR_WAIT);
|
||||
return false;
|
||||
if (!time_after(jiffies, last + msecs_to_jiffies(tdr_timeout_ms)))
|
||||
return false;
|
||||
|
||||
XDNA_ERR(xdna, "TDR timeout detected");
|
||||
return true;
|
||||
}
|
||||
|
||||
static void aie2_cmd_release(struct kref *ref)
|
||||
@@ -434,6 +436,12 @@ aie2_sched_job_run(struct drm_sched_job *sched_job)
|
||||
mmput(job->mm);
|
||||
fence = ERR_PTR(ret);
|
||||
} else {
|
||||
/*
|
||||
* Command is successfully posted to hardware, update the
|
||||
* tdr timestamp. The total pending commands are limited.
|
||||
* So there will not be a case that driver keeps posting
|
||||
* commands without getting any hardware respond.
|
||||
*/
|
||||
aie2_tdr_signal(hwctx->client->xdna);
|
||||
}
|
||||
trace_xdna_job(sched_job, hwctx->name, "sent to device",
|
||||
@@ -658,7 +666,9 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
|
||||
const struct drm_sched_init_args args = {
|
||||
.ops = &sched_ops,
|
||||
.credit_limit = HWCTX_MAX_CMDS,
|
||||
.timeout = msecs_to_jiffies(tdr_timeout_ms),
|
||||
.timeout = tdr_timeout_ms ?
|
||||
msecs_to_jiffies(tdr_timeout_ms) :
|
||||
MAX_SCHEDULE_TIMEOUT,
|
||||
.name = "amdxdna_js",
|
||||
.dev = xdna->ddev.dev,
|
||||
};
|
||||
|
||||
@@ -420,6 +420,7 @@ static int aie2_hw_start(struct amdxdna_dev *xdna)
|
||||
goto stop_fw;
|
||||
}
|
||||
|
||||
WRITE_ONCE(ndev->last_signal_ts, jiffies);
|
||||
ndev->dev_status = AIE2_DEV_START;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -143,11 +143,6 @@ struct aie2_exec_msg_ops {
|
||||
u32 (*get_chain_msg_op)(u32 cmd_op);
|
||||
};
|
||||
|
||||
enum aie2_tdr_status {
|
||||
AIE2_TDR_WAIT,
|
||||
AIE2_TDR_SIGNALED,
|
||||
};
|
||||
|
||||
struct amdxdna_dev_hdl {
|
||||
struct aie_device aie;
|
||||
const struct amdxdna_dev_priv *priv;
|
||||
@@ -179,7 +174,7 @@ struct amdxdna_dev_hdl {
|
||||
u32 hwctx_num;
|
||||
|
||||
struct amdxdna_async_error last_async_err;
|
||||
enum aie2_tdr_status tdr_status;
|
||||
unsigned long last_signal_ts;
|
||||
};
|
||||
|
||||
struct aie2_hw_ops {
|
||||
|
||||
@@ -192,9 +192,17 @@ static u64 dma_length(struct ethosu_validated_cmdstream_info *info,
|
||||
return len;
|
||||
}
|
||||
|
||||
static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info,
|
||||
static bool feat_matrix_chained(struct ethosu_device *edev, struct feat_matrix *fm)
|
||||
{
|
||||
u32 storage = fm->precision >> 14;
|
||||
|
||||
return !ethosu_is_u65(edev) && storage == 2;
|
||||
}
|
||||
|
||||
static u64 feat_matrix_length(struct ethosu_device *edev,
|
||||
struct ethosu_validated_cmdstream_info *info,
|
||||
struct feat_matrix *fm,
|
||||
u32 x, u32 y, u32 c)
|
||||
u32 x, u32 y, u32 c, bool ofm)
|
||||
{
|
||||
u32 element_size, storage = fm->precision >> 14;
|
||||
int tile = 0;
|
||||
@@ -203,6 +211,9 @@ static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info,
|
||||
if (fm->region < 0)
|
||||
return U64_MAX;
|
||||
|
||||
if (feat_matrix_chained(edev, fm))
|
||||
return 0;
|
||||
|
||||
switch (storage) {
|
||||
case 0:
|
||||
if (x >= fm->width0 + 1) {
|
||||
@@ -223,6 +234,8 @@ static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info,
|
||||
tile = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return U64_MAX;
|
||||
}
|
||||
if (fm->base[tile] == U64_MAX)
|
||||
return U64_MAX;
|
||||
@@ -231,10 +244,11 @@ static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info,
|
||||
|
||||
switch ((fm->precision >> 6) & 0x3) { // format
|
||||
case 0: //nhwc:
|
||||
addr += x * fm->stride_x + c;
|
||||
element_size = BIT((fm->precision >> (ofm ? 1 : 2)) & 0x3);
|
||||
addr += x * fm->stride_x + c * element_size;
|
||||
break;
|
||||
case 1: //nhcwb16:
|
||||
element_size = BIT((fm->precision >> 1) & 0x3);
|
||||
element_size = BIT((fm->precision >> (ofm ? 1 : 2)) & 0x3);
|
||||
|
||||
addr += (c / 16) * fm->stride_c + (16 * x + (c & 0xf)) * element_size;
|
||||
break;
|
||||
@@ -250,6 +264,7 @@ static int calc_sizes(struct drm_device *ddev,
|
||||
u16 op, struct cmd_state *st,
|
||||
bool ifm, bool ifm2, bool weight, bool scale)
|
||||
{
|
||||
struct ethosu_device *edev = to_ethosu_device(ddev);
|
||||
u64 len;
|
||||
|
||||
if (ifm) {
|
||||
@@ -267,8 +282,8 @@ static int calc_sizes(struct drm_device *ddev,
|
||||
if (ifm_height < 0 || ifm_width < 0)
|
||||
return -EINVAL;
|
||||
|
||||
len = feat_matrix_length(info, &st->ifm, ifm_width,
|
||||
ifm_height, st->ifm.depth);
|
||||
len = feat_matrix_length(edev, info, &st->ifm, ifm_width,
|
||||
ifm_height, st->ifm.depth, false);
|
||||
dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n",
|
||||
op, st->ifm.region, st->ifm.base[0], len);
|
||||
if (len == U64_MAX)
|
||||
@@ -276,8 +291,8 @@ static int calc_sizes(struct drm_device *ddev,
|
||||
}
|
||||
|
||||
if (ifm2) {
|
||||
len = feat_matrix_length(info, &st->ifm2, st->ifm.depth,
|
||||
0, st->ofm.depth);
|
||||
len = feat_matrix_length(edev, info, &st->ifm2, st->ifm.depth,
|
||||
0, st->ofm.depth, false);
|
||||
dev_dbg(ddev->dev, "op %d: IFM2:%d:0x%llx-0x%llx\n",
|
||||
op, st->ifm2.region, st->ifm2.base[0], len);
|
||||
if (len == U64_MAX)
|
||||
@@ -308,13 +323,14 @@ static int calc_sizes(struct drm_device *ddev,
|
||||
st->scale[0].base + st->scale[0].length);
|
||||
}
|
||||
|
||||
len = feat_matrix_length(info, &st->ofm, st->ofm.width,
|
||||
st->ofm.height[2], st->ofm.depth);
|
||||
len = feat_matrix_length(edev, info, &st->ofm, st->ofm.width,
|
||||
st->ofm.height[2], st->ofm.depth, true);
|
||||
dev_dbg(ddev->dev, "op %d: OFM:%d:0x%llx-0x%llx\n",
|
||||
op, st->ofm.region, st->ofm.base[0], len);
|
||||
if (len == U64_MAX)
|
||||
return -EINVAL;
|
||||
info->output_region[st->ofm.region] = true;
|
||||
if (!feat_matrix_chained(edev, &st->ofm))
|
||||
info->output_region[st->ofm.region] = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -324,6 +340,7 @@ static int calc_sizes_elemwise(struct drm_device *ddev,
|
||||
u16 op, struct cmd_state *st,
|
||||
bool ifm, bool ifm2)
|
||||
{
|
||||
struct ethosu_device *edev = to_ethosu_device(ddev);
|
||||
u32 height, width, depth;
|
||||
u64 len;
|
||||
|
||||
@@ -332,8 +349,8 @@ static int calc_sizes_elemwise(struct drm_device *ddev,
|
||||
width = st->ifm.broadcast & 0x2 ? 0 : st->ofm.width;
|
||||
depth = st->ifm.broadcast & 0x4 ? 0 : st->ofm.depth;
|
||||
|
||||
len = feat_matrix_length(info, &st->ifm, width,
|
||||
height, depth);
|
||||
len = feat_matrix_length(edev, info, &st->ifm, width,
|
||||
height, depth, false);
|
||||
dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n",
|
||||
op, st->ifm.region, st->ifm.base[0], len);
|
||||
if (len == U64_MAX)
|
||||
@@ -345,21 +362,22 @@ static int calc_sizes_elemwise(struct drm_device *ddev,
|
||||
width = st->ifm2.broadcast & 0x2 ? 0 : st->ofm.width;
|
||||
depth = st->ifm2.broadcast & 0x4 ? 0 : st->ofm.depth;
|
||||
|
||||
len = feat_matrix_length(info, &st->ifm2, width,
|
||||
height, depth);
|
||||
len = feat_matrix_length(edev, info, &st->ifm2, width,
|
||||
height, depth, false);
|
||||
dev_dbg(ddev->dev, "op %d: IFM2:%d:0x%llx-0x%llx\n",
|
||||
op, st->ifm2.region, st->ifm2.base[0], len);
|
||||
if (len == U64_MAX)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
len = feat_matrix_length(info, &st->ofm, st->ofm.width,
|
||||
st->ofm.height[2], st->ofm.depth);
|
||||
len = feat_matrix_length(edev, info, &st->ofm, st->ofm.width,
|
||||
st->ofm.height[2], st->ofm.depth, true);
|
||||
dev_dbg(ddev->dev, "op %d: OFM:%d:0x%llx-0x%llx\n",
|
||||
op, st->ofm.region, st->ofm.base[0], len);
|
||||
if (len == U64_MAX)
|
||||
return -EINVAL;
|
||||
info->output_region[st->ofm.region] = true;
|
||||
if (!feat_matrix_chained(edev, &st->ofm))
|
||||
info->output_region[st->ofm.region] = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1273,14 +1273,14 @@ fn transaction(self: &Arc<Self>, cmd: u32, reader: &mut UserSliceReader) -> Resu
|
||||
inner.extended_error =
|
||||
ExtendedError::new(info.debug_id as u32, err.reply, source.to_errno());
|
||||
}
|
||||
}
|
||||
|
||||
pr_warn!(
|
||||
"{}:{} transaction to {} failed: {err:?}",
|
||||
info.from_pid,
|
||||
info.from_tid,
|
||||
info.to_pid
|
||||
);
|
||||
pr_warn!(
|
||||
"{}:{} transaction to {} failed: {err:?}",
|
||||
info.from_pid,
|
||||
info.from_tid,
|
||||
info.to_pid
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1950,9 +1950,14 @@ static int rbd_object_map_update_finish(struct rbd_obj_request *obj_req,
|
||||
bool has_current_state;
|
||||
void *p;
|
||||
|
||||
if (osd_req->r_result)
|
||||
if (osd_req->r_result < 0)
|
||||
return osd_req->r_result;
|
||||
|
||||
/*
|
||||
* Writes aren't allowed to return a data payload.
|
||||
*/
|
||||
WARN_ON_ONCE(osd_req->r_result > 0);
|
||||
|
||||
/*
|
||||
* Nothing to do for a snapshot object map.
|
||||
*/
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/wait_bit.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/swap.h>
|
||||
@@ -26,7 +27,6 @@
|
||||
#include <linux/compat.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/miscdevice.h>
|
||||
@@ -327,7 +327,6 @@ struct ublk_device {
|
||||
|
||||
struct ublk_params params;
|
||||
|
||||
struct completion completion;
|
||||
u32 nr_queue_ready;
|
||||
bool unprivileged_daemons;
|
||||
struct mutex cancel_mutex;
|
||||
@@ -3054,12 +3053,12 @@ static void ublk_mark_io_ready(struct ublk_device *ub, u16 q_id,
|
||||
if (ublk_dev_ready(ub)) {
|
||||
/*
|
||||
* All queues ready - clear device-level canceling flag
|
||||
* and complete the recovery/initialization.
|
||||
* and wake ublk_dev_ready() waiters.
|
||||
*/
|
||||
mutex_lock(&ub->cancel_mutex);
|
||||
ub->canceling = false;
|
||||
mutex_unlock(&ub->cancel_mutex);
|
||||
complete_all(&ub->completion);
|
||||
wake_up_var(&ub->nr_queue_ready);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4273,7 +4272,6 @@ static int ublk_init_queues(struct ublk_device *ub)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
init_completion(&ub->completion);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -4417,6 +4415,26 @@ static bool ublk_validate_user_pid(struct ublk_device *ub, pid_t ublksrv_pid)
|
||||
return ub->ublksrv_tgid == ublksrv_pid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait until all queues have fetched their I/O commands, and return with
|
||||
* ub->mutex held and readiness guaranteed: then every queue's ->canceling
|
||||
* is cleared. Ready may regress between wakeup and mutex_lock() (F_BATCH
|
||||
* UNPREP, daemon death), so re-check it under the mutex and wait again.
|
||||
*/
|
||||
static int ublk_wait_dev_ready_and_lock(struct ublk_device *ub)
|
||||
{
|
||||
while (true) {
|
||||
if (wait_var_event_interruptible(&ub->nr_queue_ready,
|
||||
ublk_dev_ready(ub)))
|
||||
return -EINTR;
|
||||
|
||||
mutex_lock(&ub->mutex);
|
||||
if (ublk_dev_ready(ub))
|
||||
return 0;
|
||||
mutex_unlock(&ub->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static int ublk_ctrl_start_dev(struct ublk_device *ub,
|
||||
const struct ublksrv_ctrl_cmd *header)
|
||||
{
|
||||
@@ -4499,15 +4517,10 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub,
|
||||
};
|
||||
}
|
||||
|
||||
if (wait_for_completion_interruptible(&ub->completion) != 0)
|
||||
if (ublk_wait_dev_ready_and_lock(ub))
|
||||
return -EINTR;
|
||||
|
||||
if (!ublk_validate_user_pid(ub, ublksrv_pid))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&ub->mutex);
|
||||
/* device may become not ready in case of F_BATCH */
|
||||
if (!ublk_dev_ready(ub)) {
|
||||
if (!ublk_validate_user_pid(ub, ublksrv_pid)) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
@@ -5071,7 +5084,6 @@ static int ublk_ctrl_start_recovery(struct ublk_device *ub)
|
||||
goto out_unlock;
|
||||
}
|
||||
pr_devel("%s: start recovery for dev id %d\n", __func__, ub->ub_number);
|
||||
init_completion(&ub->completion);
|
||||
ret = 0;
|
||||
out_unlock:
|
||||
mutex_unlock(&ub->mutex);
|
||||
@@ -5087,16 +5099,17 @@ static int ublk_ctrl_end_recovery(struct ublk_device *ub,
|
||||
pr_devel("%s: Waiting for all FETCH_REQs, dev id %d...\n", __func__,
|
||||
header->dev_id);
|
||||
|
||||
if (wait_for_completion_interruptible(&ub->completion))
|
||||
if (ublk_wait_dev_ready_and_lock(ub))
|
||||
return -EINTR;
|
||||
|
||||
pr_devel("%s: All FETCH_REQs received, dev id %d\n", __func__,
|
||||
header->dev_id);
|
||||
|
||||
if (!ublk_validate_user_pid(ub, ublksrv_pid))
|
||||
return -EINVAL;
|
||||
if (!ublk_validate_user_pid(ub, ublksrv_pid)) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
mutex_lock(&ub->mutex);
|
||||
if (ublk_nosrv_should_stop_dev(ub))
|
||||
goto out_unlock;
|
||||
|
||||
|
||||
@@ -2782,7 +2782,9 @@ static int btusb_setup_realtek(struct hci_dev *hdev)
|
||||
|
||||
static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
if (skb->data[0] == HCI_VENDOR_PKT && skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) {
|
||||
if (skb->len >= HCI_EVENT_HDR_SIZE + 1 &&
|
||||
skb->data[0] == HCI_VENDOR_PKT &&
|
||||
skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) {
|
||||
struct rtk_dev_coredump_hdr hdr = {
|
||||
.code = RTK_DEVCOREDUMP_CODE_MEMDUMP,
|
||||
};
|
||||
|
||||
@@ -3187,6 +3187,7 @@ static noinline int mmc_ioctl_cdrom_volume(struct cdrom_device_info *cdi,
|
||||
|
||||
/* set volume */
|
||||
cgc->buffer = buffer + offset - 8;
|
||||
cgc->buflen -= offset - 8;
|
||||
memset(cgc->buffer, 0, 8);
|
||||
return cdrom_mode_select(cdi, cgc);
|
||||
}
|
||||
|
||||
@@ -211,6 +211,13 @@ static irqreturn_t parport_interrupt(int irq, void *d)
|
||||
unsigned int ctrl;
|
||||
unsigned short val = 0;
|
||||
|
||||
/*
|
||||
* Check device is fully attached. Device interrupts should have
|
||||
* been disabled, but do this in case of bad hardware.
|
||||
*/
|
||||
if (!dev->attached)
|
||||
return IRQ_NONE;
|
||||
|
||||
ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
|
||||
if (!(ctrl & PARPORT_CTRL_IRQ_ENA))
|
||||
return IRQ_NONE;
|
||||
@@ -233,6 +240,9 @@ static int parport_attach(struct comedi_device *dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
outb(0, dev->iobase + PARPORT_DATA_REG);
|
||||
outb(0, dev->iobase + PARPORT_CTRL_REG);
|
||||
|
||||
if (it->options[1]) {
|
||||
ret = request_irq(it->options[1], parport_interrupt, 0,
|
||||
dev->board_name, dev);
|
||||
@@ -288,9 +298,6 @@ static int parport_attach(struct comedi_device *dev,
|
||||
s->cancel = parport_intr_cancel;
|
||||
}
|
||||
|
||||
outb(0, dev->iobase + PARPORT_DATA_REG);
|
||||
outb(0, dev->iobase + PARPORT_CTRL_REG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -297,31 +297,34 @@ static struct fwnet_fragment_info *fwnet_frag_new(
|
||||
if (fi->offset + fi->len == offset) {
|
||||
/* The new fragment can be tacked on to the end */
|
||||
/* Did the new fragment plug a hole? */
|
||||
fi2 = list_entry(fi->fi_link.next,
|
||||
struct fwnet_fragment_info, fi_link);
|
||||
if (fi->offset + fi->len == fi2->offset) {
|
||||
/* glue fragments together */
|
||||
fi->len += len + fi2->len;
|
||||
list_del(&fi2->fi_link);
|
||||
kfree(fi2);
|
||||
} else {
|
||||
fi->len += len;
|
||||
if (!list_is_last(&fi->fi_link, &pd->fi_list)) {
|
||||
fi2 = list_next_entry(fi, fi_link);
|
||||
if (offset + len == fi2->offset) {
|
||||
/* glue fragments together */
|
||||
fi->len += len + fi2->len;
|
||||
list_del(&fi2->fi_link);
|
||||
kfree(fi2);
|
||||
|
||||
return fi;
|
||||
}
|
||||
}
|
||||
fi->len += len;
|
||||
|
||||
return fi;
|
||||
}
|
||||
if (offset + len == fi->offset) {
|
||||
/* The new fragment can be tacked on to the beginning */
|
||||
/* Did the new fragment plug a hole? */
|
||||
fi2 = list_entry(fi->fi_link.prev,
|
||||
struct fwnet_fragment_info, fi_link);
|
||||
if (fi2->offset + fi2->len == fi->offset) {
|
||||
/* glue fragments together */
|
||||
fi2->len += fi->len + len;
|
||||
list_del(&fi->fi_link);
|
||||
kfree(fi);
|
||||
if (!list_is_first(&fi->fi_link, &pd->fi_list)) {
|
||||
fi2 = list_prev_entry(fi, fi_link);
|
||||
if (fi2->offset + fi2->len == offset) {
|
||||
/* glue fragments together */
|
||||
fi2->len += fi->len + len;
|
||||
list_del(&fi->fi_link);
|
||||
kfree(fi);
|
||||
|
||||
return fi2;
|
||||
return fi2;
|
||||
}
|
||||
}
|
||||
fi->offset = offset;
|
||||
fi->len += len;
|
||||
|
||||
@@ -1499,8 +1499,9 @@ int stratix10_svc_async_poll(struct stratix10_svc_chan *chan,
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
return 0;
|
||||
} else if (handle->res.a0 == INTEL_SIP_SMC_STATUS_BUSY) {
|
||||
dev_dbg(ctrl->dev, "async message is still in progress\n");
|
||||
} else if (handle->res.a0 == INTEL_SIP_SMC_STATUS_BUSY ||
|
||||
handle->res.a0 == INTEL_SIP_SMC_STATUS_NO_RESPONSE) {
|
||||
dev_dbg(ctrl->dev, "async message is not ready yet\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
@@ -1857,14 +1858,16 @@ void *stratix10_svc_allocate_memory(struct stratix10_svc_chan *chan,
|
||||
struct gen_pool *genpool = chan->ctrl->genpool;
|
||||
size_t s = roundup(size, 1 << genpool->min_alloc_order);
|
||||
|
||||
pmem = devm_kzalloc(chan->ctrl->dev, sizeof(*pmem), GFP_KERNEL);
|
||||
pmem = kzalloc_obj(*pmem);
|
||||
if (!pmem)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
guard(mutex)(&svc_mem_lock);
|
||||
va = gen_pool_alloc(genpool, s);
|
||||
if (!va)
|
||||
if (!va) {
|
||||
kfree(pmem);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
memset((void *)va, 0, s);
|
||||
pa = gen_pool_virt_to_phys(genpool, va);
|
||||
@@ -1890,6 +1893,7 @@ EXPORT_SYMBOL_GPL(stratix10_svc_allocate_memory);
|
||||
void stratix10_svc_free_memory(struct stratix10_svc_chan *chan, void *kaddr)
|
||||
{
|
||||
struct stratix10_svc_data_mem *pmem;
|
||||
|
||||
guard(mutex)(&svc_mem_lock);
|
||||
|
||||
list_for_each_entry(pmem, &svc_data_mem, node)
|
||||
@@ -1898,10 +1902,9 @@ void stratix10_svc_free_memory(struct stratix10_svc_chan *chan, void *kaddr)
|
||||
(unsigned long)kaddr, pmem->size);
|
||||
pmem->vaddr = NULL;
|
||||
list_del(&pmem->node);
|
||||
kfree(pmem);
|
||||
return;
|
||||
}
|
||||
|
||||
list_del(&svc_data_mem);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(stratix10_svc_free_memory);
|
||||
|
||||
@@ -2046,12 +2049,12 @@ static void stratix10_svc_drv_remove(struct platform_device *pdev)
|
||||
struct stratix10_svc_controller *ctrl = platform_get_drvdata(pdev);
|
||||
struct stratix10_svc *svc = ctrl->svc;
|
||||
|
||||
platform_device_unregister(svc->stratix10_svc_rsu);
|
||||
|
||||
stratix10_svc_async_exit(ctrl);
|
||||
|
||||
of_platform_depopulate(ctrl->dev);
|
||||
|
||||
platform_device_unregister(svc->stratix10_svc_rsu);
|
||||
|
||||
for (i = 0; i < SVC_NUM_CHANNEL; i++) {
|
||||
if (ctrl->chans[i].task) {
|
||||
kthread_stop(ctrl->chans[i].task);
|
||||
|
||||
@@ -3324,7 +3324,8 @@ static void dm_gpureset_toggle_interrupts(struct amdgpu_device *adev,
|
||||
acrtc = get_crtc_by_otg_inst(
|
||||
adev, state->stream_status[i].primary_otg_inst);
|
||||
|
||||
if (acrtc && state->stream_status[i].plane_count != 0) {
|
||||
if (acrtc && state->stream_status[i].plane_count != 0 &&
|
||||
amdgpu_ip_version(adev, DCE_HWIP, 0) == 0) {
|
||||
irq_source = IRQ_TYPE_PFLIP + acrtc->otg_inst;
|
||||
rc = dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY;
|
||||
if (rc)
|
||||
|
||||
@@ -280,10 +280,19 @@ static inline int amdgpu_dm_crtc_set_vblank(struct drm_crtc *crtc, bool enable)
|
||||
* is enabled. On DCE, vupdate is only needed in VRR mode.
|
||||
*/
|
||||
if (amdgpu_ip_version(adev, DCE_HWIP, 0) != 0) {
|
||||
rc = amdgpu_dm_crtc_set_vupdate_irq(crtc, enable);
|
||||
if (enable) {
|
||||
rc = amdgpu_irq_get(adev, &adev->vupdate_irq, irq_type);
|
||||
drm_dbg_vbl(crtc->dev, "Get vupdate_irq ret=%d\n", rc);
|
||||
} else {
|
||||
rc = amdgpu_irq_put(adev, &adev->vupdate_irq, irq_type);
|
||||
drm_dbg_vbl(crtc->dev, "Put vupdate_irq ret=%d\n", rc);
|
||||
}
|
||||
} else if (dc_supports_vrr(dm->dc->ctx->dce_version)) {
|
||||
if (enable) {
|
||||
/* vblank irq on -> Only need vupdate irq in vrr mode */
|
||||
/* vblank irq on -> Only need vupdate irq in vrr mode
|
||||
* Not ref-counted since we need explicit enable/disable
|
||||
* for DCE VRR handling
|
||||
*/
|
||||
if (amdgpu_dm_crtc_vrr_active(acrtc_state))
|
||||
rc = amdgpu_dm_crtc_set_vupdate_irq(crtc, true);
|
||||
} else {
|
||||
|
||||
@@ -781,7 +781,7 @@ enum drm_gpusvm_scan_result drm_gpusvm_scan_mm(struct drm_gpusvm_range *range,
|
||||
const struct dev_pagemap *other = NULL;
|
||||
int err, i;
|
||||
|
||||
pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
|
||||
pfns = kvcalloc(npages, sizeof(*pfns), GFP_KERNEL);
|
||||
if (!pfns)
|
||||
return DRM_GPUSVM_SCAN_UNPOPULATED;
|
||||
|
||||
@@ -1753,8 +1753,10 @@ int drm_gpusvm_range_evict(struct drm_gpusvm *gpusvm,
|
||||
return -EFAULT;
|
||||
|
||||
pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
|
||||
if (!pfns)
|
||||
if (!pfns) {
|
||||
mmput(mm);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hmm_range.hmm_pfns = pfns;
|
||||
while (!time_after(jiffies, timeout)) {
|
||||
|
||||
@@ -727,8 +727,10 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
|
||||
}
|
||||
|
||||
err = ops->populate_devmem_pfn(devmem_allocation, npages, migrate.dst);
|
||||
if (err)
|
||||
goto err_aborted_migration;
|
||||
if (err) {
|
||||
npages = 0;
|
||||
goto err_finalize;
|
||||
}
|
||||
|
||||
own_pages = 0;
|
||||
|
||||
@@ -807,8 +809,11 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
|
||||
msecs_to_jiffies(mdetails->timeslice_ms);
|
||||
|
||||
err_finalize:
|
||||
if (err)
|
||||
if (err) {
|
||||
drm_pagemap_migration_unlock_put_pages(npages, migrate.dst);
|
||||
for (i = npages; i < npages_in_range(start, end); ++i)
|
||||
migrate.dst[i] = 0;
|
||||
}
|
||||
err_aborted_migration:
|
||||
migrate_vma_pages(&migrate);
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg)
|
||||
struct oaktrail_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
|
||||
struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
|
||||
u32 temp;
|
||||
int ret;
|
||||
|
||||
i2c_dev->status = I2C_STAT_INIT;
|
||||
i2c_dev->msg = pmsg;
|
||||
@@ -109,9 +110,14 @@ static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg)
|
||||
HDMI_WRITE(HDMI_HI2CHCR, temp);
|
||||
HDMI_READ(HDMI_HI2CHCR);
|
||||
|
||||
while (i2c_dev->status != I2C_TRANSACTION_DONE)
|
||||
wait_for_completion_interruptible_timeout(&i2c_dev->complete,
|
||||
while (i2c_dev->status != I2C_TRANSACTION_DONE) {
|
||||
ret = wait_for_completion_interruptible_timeout(&i2c_dev->complete,
|
||||
10 * HZ);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (!ret)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -130,7 +136,7 @@ static int oaktrail_hdmi_i2c_access(struct i2c_adapter *adap,
|
||||
{
|
||||
struct oaktrail_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
|
||||
struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
|
||||
int i;
|
||||
int i, ret = 0;
|
||||
|
||||
mutex_lock(&i2c_dev->i2c_lock);
|
||||
|
||||
@@ -142,9 +148,11 @@ static int oaktrail_hdmi_i2c_access(struct i2c_adapter *adap,
|
||||
for (i = 0; i < num; i++) {
|
||||
if (pmsg->len && pmsg->buf) {
|
||||
if (pmsg->flags & I2C_M_RD)
|
||||
xfer_read(adap, pmsg);
|
||||
ret = xfer_read(adap, pmsg);
|
||||
else
|
||||
xfer_write(adap, pmsg);
|
||||
ret = xfer_write(adap, pmsg);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
pmsg++; /* next message */
|
||||
}
|
||||
@@ -154,6 +162,9 @@ static int oaktrail_hdmi_i2c_access(struct i2c_adapter *adap,
|
||||
|
||||
mutex_unlock(&i2c_dev->i2c_lock);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
@@ -615,12 +615,7 @@ check_if_vesa_backlight_possible(struct intel_dp *intel_dp)
|
||||
int ret;
|
||||
u8 bit_min, bit_max;
|
||||
|
||||
/*
|
||||
* Since we only support Fully AUX Based VESA Backlight interface make sure
|
||||
* backlight enable is possible via AUX along with backlight adjustment
|
||||
*/
|
||||
if (!(intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP &&
|
||||
intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP))
|
||||
if (!(intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP))
|
||||
return false;
|
||||
|
||||
ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &bit_min);
|
||||
|
||||
@@ -747,6 +747,7 @@ pvr_vm_map(struct pvr_vm_context *vm_ctx, struct pvr_gem_object *pvr_obj,
|
||||
|
||||
pvr_gem_object_get(pvr_obj);
|
||||
|
||||
mutex_lock(&vm_ctx->lock);
|
||||
err = drm_gpuvm_exec_lock(&vm_exec);
|
||||
if (err)
|
||||
goto err_cleanup;
|
||||
@@ -756,6 +757,7 @@ pvr_vm_map(struct pvr_vm_context *vm_ctx, struct pvr_gem_object *pvr_obj,
|
||||
drm_gpuvm_exec_unlock(&vm_exec);
|
||||
|
||||
err_cleanup:
|
||||
mutex_unlock(&vm_ctx->lock);
|
||||
pvr_vm_bind_op_fini(&bind_op);
|
||||
|
||||
return err;
|
||||
|
||||
@@ -232,6 +232,7 @@ config DRM_PANEL_HIMAX_HX83121A
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select DRM_DISPLAY_HELPER
|
||||
select DRM_DISPLAY_DSC_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
help
|
||||
@@ -332,6 +333,7 @@ config DRM_PANEL_ILITEK_ILI9882T
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select DRM_DISPLAY_HELPER
|
||||
select DRM_DISPLAY_DSC_HELPER
|
||||
help
|
||||
Say Y if you want to enable support for panels based on the
|
||||
@@ -954,6 +956,7 @@ config DRM_PANEL_SAMSUNG_S6E3HA8
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select DRM_DISPLAY_HELPER
|
||||
select DRM_DISPLAY_DSC_HELPER
|
||||
help
|
||||
Say Y or M here if you want to enable support for the
|
||||
|
||||
@@ -2562,9 +2562,12 @@ static int ili9881c_dsi_probe(struct mipi_dsi_device *dsi)
|
||||
"Couldn't get our power regulator\n");
|
||||
|
||||
ctx->iovcc = devm_regulator_get_optional(&dsi->dev, "iovcc");
|
||||
if (IS_ERR(ctx->iovcc))
|
||||
return dev_err_probe(&dsi->dev, PTR_ERR(ctx->iovcc),
|
||||
if (IS_ERR(ctx->iovcc)) {
|
||||
if (PTR_ERR(ctx->iovcc) != -ENODEV)
|
||||
return dev_err_probe(&dsi->dev, PTR_ERR(ctx->iovcc),
|
||||
"Couldn't get our iovcc regulator\n");
|
||||
ctx->iovcc = NULL;
|
||||
}
|
||||
|
||||
ctx->reset = devm_gpiod_get_optional(&dsi->dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(ctx->reset))
|
||||
|
||||
@@ -95,13 +95,9 @@ static void drm_gem_shmem_test_obj_create_private(struct kunit *test)
|
||||
sg_init_one(sgt->sgl, buf, TEST_SIZE);
|
||||
|
||||
/*
|
||||
* Set the DMA mask to 64-bits and map the sgtables
|
||||
* otherwise drm_gem_shmem_free will cause a warning
|
||||
* on debug kernels.
|
||||
* Map the sgtables otherwise drm_gem_shmem_free will cause a warning on
|
||||
* debug kernels.
|
||||
*/
|
||||
ret = dma_set_mask(drm_dev->dev, DMA_BIT_MASK(64));
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
ret = dma_map_sgtable(drm_dev->dev, sgt, DMA_BIDIRECTIONAL, 0);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
@@ -352,11 +348,19 @@ static int drm_gem_shmem_test_init(struct kunit *test)
|
||||
{
|
||||
struct device *dev;
|
||||
struct drm_device *drm_dev;
|
||||
int ret;
|
||||
|
||||
/* Allocate a parent device */
|
||||
dev = drm_kunit_helper_alloc_device(test);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
|
||||
|
||||
/*
|
||||
* Set the DMA mask to 64-bits to avoid intermittent failures calling
|
||||
* drm_gem_shmem_get_pages_sgt().
|
||||
*/
|
||||
ret = dma_set_mask(dev, DMA_BIT_MASK(64));
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
/*
|
||||
* The DRM core will automatically initialize the GEM core and create
|
||||
* a DRM Memory Manager object which provides an address space pool
|
||||
|
||||
@@ -315,33 +315,16 @@ static const u32 appletbdrm_primary_plane_formats[] = {
|
||||
DRM_FORMAT_XRGB8888, /* emulated */
|
||||
};
|
||||
|
||||
static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
|
||||
struct drm_atomic_commit *state)
|
||||
static int appletbdrm_primary_plane_helper_begin_fb_access(struct drm_plane *plane,
|
||||
struct drm_plane_state *new_plane_state)
|
||||
{
|
||||
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
|
||||
struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
|
||||
struct drm_crtc *new_crtc = new_plane_state->crtc;
|
||||
struct drm_crtc_state *new_crtc_state = NULL;
|
||||
struct appletbdrm_plane_state *appletbdrm_state = to_appletbdrm_plane_state(new_plane_state);
|
||||
size_t frames_size = 0;
|
||||
struct drm_atomic_helper_damage_iter iter;
|
||||
struct drm_rect damage;
|
||||
size_t frames_size = 0;
|
||||
size_t request_size;
|
||||
int ret;
|
||||
|
||||
if (new_crtc)
|
||||
new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
false, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
else if (!new_plane_state->visible)
|
||||
return 0;
|
||||
|
||||
drm_atomic_helper_damage_iter_init(&iter, old_plane_state, new_plane_state);
|
||||
drm_atomic_helper_damage_iter_init(&iter, plane->state, new_plane_state);
|
||||
drm_atomic_for_each_plane_damage(&iter, &damage) {
|
||||
frames_size += struct_size((struct appletbdrm_frame *)0, buf, rect_size(&damage));
|
||||
}
|
||||
@@ -366,6 +349,29 @@ static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
|
||||
appletbdrm_state->request_size = request_size;
|
||||
appletbdrm_state->frames_size = frames_size;
|
||||
|
||||
return drm_gem_begin_shadow_fb_access(plane, new_plane_state);
|
||||
}
|
||||
|
||||
static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
|
||||
struct drm_atomic_commit *state)
|
||||
{
|
||||
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
|
||||
struct drm_crtc *new_crtc = new_plane_state->crtc;
|
||||
struct drm_crtc_state *new_crtc_state = NULL;
|
||||
int ret;
|
||||
|
||||
if (new_crtc)
|
||||
new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
false, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
else if (!new_plane_state->visible)
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -468,7 +474,7 @@ static int appletbdrm_flush_damage(struct appletbdrm_device *adev,
|
||||
}
|
||||
|
||||
static void appletbdrm_primary_plane_helper_atomic_update(struct drm_plane *plane,
|
||||
struct drm_atomic_commit *old_state)
|
||||
struct drm_atomic_commit *old_state)
|
||||
{
|
||||
struct appletbdrm_device *adev = drm_to_adev(plane->dev);
|
||||
struct drm_device *drm = plane->dev;
|
||||
@@ -552,7 +558,8 @@ static void appletbdrm_primary_plane_destroy_state(struct drm_plane *plane,
|
||||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs appletbdrm_primary_plane_helper_funcs = {
|
||||
DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
|
||||
.begin_fb_access = appletbdrm_primary_plane_helper_begin_fb_access,
|
||||
.end_fb_access = drm_gem_end_shadow_fb_access,
|
||||
.atomic_check = appletbdrm_primary_plane_helper_atomic_check,
|
||||
.atomic_update = appletbdrm_primary_plane_helper_atomic_update,
|
||||
.atomic_disable = appletbdrm_primary_plane_helper_atomic_disable,
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
#include <drm/ttm/ttm_backup.h>
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/page-flags.h>
|
||||
#include <linux/swap.h>
|
||||
|
||||
#include "ttm_pool_internal.h"
|
||||
|
||||
/*
|
||||
* Need to map shmem indices to handle since a handle value
|
||||
* of 0 means error, following the swp_entry_t convention.
|
||||
@@ -68,17 +69,23 @@ int ttm_backup_copy_page(struct file *backup, struct page *dst,
|
||||
}
|
||||
|
||||
/**
|
||||
* ttm_backup_backup_page() - Backup a page
|
||||
* ttm_backup_backup_folio() - Backup a folio
|
||||
* @backup: The struct backup pointer to use.
|
||||
* @page: The page to back up.
|
||||
* @writeback: Whether to perform immediate writeback of the page.
|
||||
* @folio: The folio to back up.
|
||||
* @order: The allocation order of @folio. Since TTM allocates higher-order
|
||||
* pages without __GFP_COMP, folio_nr_pages(@folio) would always
|
||||
* return 1; the caller must pass the true order explicitly.
|
||||
* @writeback: Whether to perform immediate writeback of the folio's pages.
|
||||
* This may have performance implications.
|
||||
* @idx: A unique integer for each page and each struct backup.
|
||||
* @idx: A unique integer for the first page of the folio and each struct backup.
|
||||
* This allows the backup implementation to avoid managing
|
||||
* its address space separately.
|
||||
* @page_gfp: The gfp value used when the page was allocated.
|
||||
* This is used for accounting purposes.
|
||||
* @folio_gfp: The gfp value used when the folio was allocated.
|
||||
* Currently unused.
|
||||
* @alloc_gfp: The gfp to be used when allocating memory.
|
||||
* @nr_pages_backed: Output. On a successful return, set to the number of
|
||||
* pages actually backed up, which may be less than (1 << @order)
|
||||
* if an -ENOMEM was encountered mid-folio.
|
||||
*
|
||||
* Context: If called from reclaim context, the caller needs to
|
||||
* assert that the shrinker gfp has __GFP_FS set, to avoid
|
||||
@@ -87,53 +94,87 @@ int ttm_backup_copy_page(struct file *backup, struct page *dst,
|
||||
* that the shrinker gfp has __GFP_IO set, since without it,
|
||||
* we're not allowed to start backup IO.
|
||||
*
|
||||
* Return: A handle on success. Negative error code on failure.
|
||||
*
|
||||
* Note: This function could be extended to back up a folio and
|
||||
* implementations would then split the folio internally if needed.
|
||||
* Drawback is that the caller would then have to keep track of
|
||||
* the folio size- and usage.
|
||||
* Return: A handle for the first backed-up page on success (handles for
|
||||
* subsequent pages follow sequentially). -ENOMEM if no pages could be backed
|
||||
* up. Any other negative error code if a non-ENOMEM failure occurred; in that
|
||||
* case any pages backed up so far are truncated before returning.
|
||||
*/
|
||||
s64
|
||||
ttm_backup_backup_page(struct file *backup, struct page *page,
|
||||
bool writeback, pgoff_t idx, gfp_t page_gfp,
|
||||
gfp_t alloc_gfp)
|
||||
ttm_backup_backup_folio(struct file *backup, struct folio *folio,
|
||||
unsigned int order, bool writeback, pgoff_t idx,
|
||||
gfp_t folio_gfp, gfp_t alloc_gfp,
|
||||
pgoff_t *nr_pages_backed)
|
||||
{
|
||||
struct address_space *mapping = backup->f_mapping;
|
||||
unsigned long handle = 0;
|
||||
int nr_pages = 1 << order;
|
||||
struct folio *to_folio;
|
||||
int ret;
|
||||
int ret, i;
|
||||
|
||||
to_folio = shmem_read_folio_gfp(mapping, idx, alloc_gfp);
|
||||
if (IS_ERR(to_folio))
|
||||
return PTR_ERR(to_folio);
|
||||
*nr_pages_backed = 0;
|
||||
|
||||
folio_mark_accessed(to_folio);
|
||||
folio_lock(to_folio);
|
||||
folio_mark_dirty(to_folio);
|
||||
copy_highpage(folio_file_page(to_folio, idx), page);
|
||||
handle = ttm_backup_shmem_idx_to_handle(idx);
|
||||
for (i = 0; i < nr_pages; ) {
|
||||
int to_nr, j;
|
||||
|
||||
if (writeback && !folio_mapped(to_folio) &&
|
||||
folio_clear_dirty_for_io(to_folio)) {
|
||||
folio_set_reclaim(to_folio);
|
||||
ret = shmem_writeout(to_folio, NULL, NULL);
|
||||
if (!folio_test_writeback(to_folio))
|
||||
folio_clear_reclaim(to_folio);
|
||||
/*
|
||||
* If writeout succeeds, it unlocks the folio. errors
|
||||
* are otherwise dropped, since writeout is only best
|
||||
* effort here.
|
||||
* Only inject past the first subpage so *nr_pages_backed is
|
||||
* always > 0 here, matching a genuine mid-compound -ENOMEM
|
||||
* and driving the caller's reactive split fallback instead
|
||||
* of an early, no-progress failure.
|
||||
*/
|
||||
if (ret)
|
||||
if (IS_ENABLED(CONFIG_FAULT_INJECTION) && i &&
|
||||
ttm_backup_fault_inject_folio())
|
||||
to_folio = ERR_PTR(-ENOMEM);
|
||||
else
|
||||
to_folio = shmem_read_folio_gfp(mapping, idx + i, alloc_gfp);
|
||||
if (IS_ERR(to_folio)) {
|
||||
int err = PTR_ERR(to_folio);
|
||||
|
||||
if (err == -ENOMEM && *nr_pages_backed)
|
||||
return ttm_backup_shmem_idx_to_handle(idx);
|
||||
|
||||
if (*nr_pages_backed) {
|
||||
shmem_truncate_range(file_inode(backup),
|
||||
(loff_t)idx << PAGE_SHIFT,
|
||||
((loff_t)(idx + i) << PAGE_SHIFT) - 1);
|
||||
/*
|
||||
* The pages just truncated are no longer
|
||||
* backed up; don't let the caller mistake
|
||||
* them for valid handles.
|
||||
*/
|
||||
*nr_pages_backed = 0;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
to_nr = min_t(int, nr_pages - i,
|
||||
folio_next_index(to_folio) - (idx + i));
|
||||
|
||||
folio_mark_accessed(to_folio);
|
||||
folio_lock(to_folio);
|
||||
folio_mark_dirty(to_folio);
|
||||
|
||||
for (j = 0; j < to_nr; j++)
|
||||
copy_highpage(folio_file_page(to_folio, idx + i + j),
|
||||
folio_page(folio, i + j));
|
||||
|
||||
if (writeback && !folio_mapped(to_folio) &&
|
||||
folio_clear_dirty_for_io(to_folio)) {
|
||||
folio_set_reclaim(to_folio);
|
||||
ret = shmem_writeout(to_folio, NULL, NULL);
|
||||
if (!folio_test_writeback(to_folio))
|
||||
folio_clear_reclaim(to_folio);
|
||||
if (ret == AOP_WRITEPAGE_ACTIVATE)
|
||||
folio_unlock(to_folio);
|
||||
} else {
|
||||
folio_unlock(to_folio);
|
||||
} else {
|
||||
folio_unlock(to_folio);
|
||||
}
|
||||
|
||||
folio_put(to_folio);
|
||||
i += to_nr;
|
||||
*nr_pages_backed = i;
|
||||
}
|
||||
|
||||
folio_put(to_folio);
|
||||
|
||||
return handle;
|
||||
return ttm_backup_shmem_idx_to_handle(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -53,8 +53,23 @@
|
||||
#ifdef CONFIG_FAULT_INJECTION
|
||||
#include <linux/fault-inject.h>
|
||||
static DECLARE_FAULT_ATTR(backup_fault_inject);
|
||||
|
||||
/*
|
||||
* Exposed to ttm_backup.c so a mid-compound subpage can be made to fail
|
||||
* with -ENOMEM, exercising the reactive split-and-retry fallback in
|
||||
* ttm_pool_backup() for high-order backups.
|
||||
*/
|
||||
bool ttm_backup_fault_inject_folio(void)
|
||||
{
|
||||
return should_fail(&backup_fault_inject, 1);
|
||||
}
|
||||
#else
|
||||
#define should_fail(...) false
|
||||
|
||||
bool ttm_backup_fault_inject_folio(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -487,7 +502,7 @@ static void ttm_pool_split_for_swap(struct ttm_pool *pool, struct page *p)
|
||||
/**
|
||||
* DOC: Partial backup and restoration of a struct ttm_tt.
|
||||
*
|
||||
* Swapout using ttm_backup_backup_page() and swapin using
|
||||
* Swapout using ttm_backup_backup_folio() and swapin using
|
||||
* ttm_backup_copy_page() may fail.
|
||||
* The former most likely due to lack of swap-space or memory, the latter due
|
||||
* to lack of memory or because of signal interruption during waits.
|
||||
@@ -1036,12 +1051,12 @@ long ttm_pool_backup(struct ttm_pool *pool, struct ttm_tt *tt,
|
||||
{
|
||||
struct file *backup = tt->backup;
|
||||
struct page *page;
|
||||
unsigned long handle;
|
||||
gfp_t alloc_gfp;
|
||||
gfp_t gfp;
|
||||
int ret = 0;
|
||||
pgoff_t shrunken = 0;
|
||||
pgoff_t i, num_pages;
|
||||
pgoff_t i, j, num_pages, npages;
|
||||
pgoff_t nr_backed;
|
||||
|
||||
if (WARN_ON(ttm_tt_is_backed_up(tt)))
|
||||
return -EINVAL;
|
||||
@@ -1119,9 +1134,11 @@ long ttm_pool_backup(struct ttm_pool *pool, struct ttm_tt *tt,
|
||||
if (IS_ENABLED(CONFIG_FAULT_INJECTION) && should_fail(&backup_fault_inject, 1))
|
||||
num_pages = DIV_ROUND_UP(num_pages, 2);
|
||||
|
||||
for (i = 0; i < num_pages; ++i) {
|
||||
s64 shandle;
|
||||
for (i = 0; i < num_pages; i += npages) {
|
||||
unsigned int order;
|
||||
s64 handle;
|
||||
|
||||
npages = 1;
|
||||
page = tt->pages[i];
|
||||
if (unlikely(!page))
|
||||
continue;
|
||||
@@ -1130,19 +1147,61 @@ long ttm_pool_backup(struct ttm_pool *pool, struct ttm_tt *tt,
|
||||
if (unlikely(ttm_backup_page_ptr_is_handle(page)))
|
||||
continue;
|
||||
|
||||
ttm_pool_split_for_swap(pool, page);
|
||||
order = ttm_pool_page_order(pool, page);
|
||||
npages = 1UL << order;
|
||||
|
||||
shandle = ttm_backup_backup_page(backup, page, flags->writeback, i,
|
||||
gfp, alloc_gfp);
|
||||
if (shandle < 0) {
|
||||
/* We allow partially shrunken tts */
|
||||
ret = shandle;
|
||||
/*
|
||||
* We don't allow dipping kernel reserves for high order backup
|
||||
*/
|
||||
if (order)
|
||||
alloc_gfp |= __GFP_NOMEMALLOC;
|
||||
else
|
||||
alloc_gfp &= ~__GFP_NOMEMALLOC;
|
||||
|
||||
/*
|
||||
* Back up the compound atomically at its native order. If
|
||||
* fault injection truncated num_pages mid-compound, skip
|
||||
* the partial tail rather than splitting.
|
||||
*/
|
||||
if (unlikely(i + npages > num_pages))
|
||||
break;
|
||||
|
||||
handle = ttm_backup_backup_folio(backup, page_folio(page),
|
||||
order, flags->writeback, i,
|
||||
gfp, alloc_gfp,
|
||||
&nr_backed);
|
||||
/*
|
||||
* Zero progress on this compound (whether order 0 or a
|
||||
* high-order compound that failed before backing up even
|
||||
* its first subpage) is unrecoverable: bail out rather than
|
||||
* looping forever with npages == nr_backed == 0 below.
|
||||
*/
|
||||
if (unlikely(handle < 0 && !nr_backed)) {
|
||||
ret = handle;
|
||||
break;
|
||||
}
|
||||
handle = shandle;
|
||||
tt->pages[i] = ttm_backup_handle_to_page_ptr(handle);
|
||||
__free_pages_gpu_account(page, 0, false);
|
||||
shrunken++;
|
||||
|
||||
for (j = 0; j < nr_backed; j++)
|
||||
tt->pages[i + j] = ttm_backup_handle_to_page_ptr(handle + j);
|
||||
|
||||
shrunken += nr_backed;
|
||||
|
||||
if (unlikely(nr_backed < npages)) {
|
||||
/*
|
||||
* Partial OOM backup: split the compound and free the
|
||||
* subpages whose content is now in shmem. Continue the
|
||||
* loop from the first un-backed order-0 page.
|
||||
*/
|
||||
ttm_pool_split_for_swap(pool, page);
|
||||
for (j = 0; j < nr_backed; j++)
|
||||
__free_pages_gpu_account(page + j, 0, false);
|
||||
npages = nr_backed;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Fully backed up: free at native order. */
|
||||
page->private = 0;
|
||||
__free_pages_gpu_account(page, order, false);
|
||||
}
|
||||
|
||||
return shrunken ? shrunken : ret;
|
||||
|
||||
@@ -22,4 +22,12 @@ static inline unsigned int ttm_pool_beneficial_order(struct ttm_pool *pool)
|
||||
return pool->alloc_flags & 0xff;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implemented in ttm_pool.c, used by ttm_backup.c. Returns true if a fault
|
||||
* should be injected mid-compound to test the reactive split-and-retry
|
||||
* fallback in ttm_pool_backup(). Always returns false when
|
||||
* CONFIG_FAULT_INJECTION is disabled.
|
||||
*/
|
||||
bool ttm_backup_fault_inject_folio(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -571,6 +571,8 @@ extern bool super_pages;
|
||||
void v3d_init_hw_state(struct v3d_dev *v3d);
|
||||
int v3d_gem_init(struct drm_device *dev);
|
||||
void v3d_gem_destroy(struct drm_device *dev);
|
||||
void v3d_idle_axi(struct v3d_dev *v3d, int core);
|
||||
void v3d_idle_gca(struct v3d_dev *v3d);
|
||||
void v3d_reset_sms(struct v3d_dev *v3d);
|
||||
void v3d_reset(struct v3d_dev *v3d);
|
||||
void v3d_invalidate_caches(struct v3d_dev *v3d);
|
||||
|
||||
@@ -36,9 +36,21 @@ v3d_init_core(struct v3d_dev *v3d, int core)
|
||||
V3D_CORE_WRITE(core, V3D_CTL_L2TFLEND, ~0);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
v3d_idle_axi(struct v3d_dev *v3d, int core)
|
||||
{
|
||||
if (v3d->ver >= V3D_GEN_71) {
|
||||
V3D_WRITE(V3D_GMP_CFG(v3d->ver), V3D_GMP_CFG_STOP_REQ);
|
||||
|
||||
if (wait_for((V3D_READ(V3D_GMP_STATUS(v3d->ver)) &
|
||||
(V3D_GMP_STATUS_RD_COUNT_MASK |
|
||||
V3D_GMP_STATUS_WR_COUNT_MASK |
|
||||
V3D_GMP_STATUS_CFG_BUSY)) == 0, 100)) {
|
||||
drm_err(&v3d->drm, "Failed to wait for safe GMP shutdown\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
V3D_CORE_WRITE(core, V3D_GMP_CFG(v3d->ver), V3D_GMP_CFG_STOP_REQ);
|
||||
|
||||
if (wait_for((V3D_CORE_READ(core, V3D_GMP_STATUS(v3d->ver)) &
|
||||
@@ -49,7 +61,7 @@ v3d_idle_axi(struct v3d_dev *v3d, int core)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
v3d_idle_gca(struct v3d_dev *v3d)
|
||||
{
|
||||
if (v3d->ver >= V3D_GEN_41)
|
||||
|
||||
@@ -54,8 +54,15 @@ int v3d_power_suspend(struct device *dev)
|
||||
|
||||
v3d_clean_caches(v3d);
|
||||
|
||||
/* Wait until V3D has no active or pending AXI transactions. */
|
||||
v3d_idle_axi(v3d, 0);
|
||||
v3d_idle_gca(v3d);
|
||||
|
||||
ret = v3d_suspend_sms(v3d);
|
||||
if (ret) {
|
||||
/* Staying active: undo the GMP STOP_REQ from v3d_idle_axi(). */
|
||||
V3D_WRITE(V3D_GMP_CFG(v3d->ver),
|
||||
V3D_READ(V3D_GMP_CFG(v3d->ver)) & ~V3D_GMP_CFG_STOP_REQ);
|
||||
v3d_irq_enable(v3d);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -732,9 +732,13 @@ static int vc4_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct
|
||||
{
|
||||
struct vc4_bo *bo = to_vc4_bo(obj);
|
||||
|
||||
if (bo->validated_shader && (vma->vm_flags & VM_WRITE)) {
|
||||
DRM_DEBUG("mmapping of shader BOs for writing not allowed.\n");
|
||||
return -EINVAL;
|
||||
if (bo->validated_shader) {
|
||||
if (vma->vm_flags & VM_WRITE) {
|
||||
DRM_DEBUG("mmapping of shader BOs for writing not allowed.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vm_flags_clear(vma, VM_MAYWRITE);
|
||||
}
|
||||
|
||||
mutex_lock(&bo->madv_lock);
|
||||
@@ -1044,7 +1048,7 @@ static void vc4_bo_cache_destroy(struct drm_device *dev, void *unused)
|
||||
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
||||
int i;
|
||||
|
||||
timer_delete(&vc4->bo_cache.time_timer);
|
||||
timer_shutdown_sync(&vc4->bo_cache.time_timer);
|
||||
cancel_work_sync(&vc4->bo_cache.time_work);
|
||||
|
||||
vc4_bo_cache_purge(dev);
|
||||
|
||||
@@ -1752,7 +1752,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
|
||||
static void vc4_hvs_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
struct drm_device *drm = dev_get_drvdata(master);
|
||||
struct drm_device *drm = data;
|
||||
struct vc4_dev *vc4 = to_vc4_dev(drm);
|
||||
struct vc4_hvs *hvs = vc4->hvs;
|
||||
struct drm_mm_node *node, *next;
|
||||
|
||||
@@ -494,7 +494,7 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
|
||||
static void vc4_v3d_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
struct drm_device *drm = dev_get_drvdata(master);
|
||||
struct drm_device *drm = data;
|
||||
struct vc4_dev *vc4 = to_vc4_dev(drm);
|
||||
|
||||
vc4_irq_uninstall(drm);
|
||||
|
||||
@@ -78,7 +78,7 @@ static int vmw_gb_surface_unbind(struct vmw_resource *res,
|
||||
static int vmw_gb_surface_destroy(struct vmw_resource *res);
|
||||
static int
|
||||
vmw_gb_surface_define_internal(struct drm_device *dev,
|
||||
struct drm_vmw_gb_surface_create_ext_req *req,
|
||||
const struct drm_vmw_gb_surface_create_ext_req *req,
|
||||
struct drm_vmw_gb_surface_create_rep *rep,
|
||||
struct drm_file *file_priv);
|
||||
static int
|
||||
@@ -1503,7 +1503,7 @@ int vmw_gb_surface_reference_ext_ioctl(struct drm_device *dev, void *data,
|
||||
*/
|
||||
static int
|
||||
vmw_gb_surface_define_internal(struct drm_device *dev,
|
||||
struct drm_vmw_gb_surface_create_ext_req *req,
|
||||
const struct drm_vmw_gb_surface_create_ext_req *req,
|
||||
struct drm_vmw_gb_surface_create_rep *rep,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
@@ -1521,9 +1521,21 @@ vmw_gb_surface_define_internal(struct drm_device *dev,
|
||||
req->base.svga3d_flags);
|
||||
|
||||
/* array_size must be null for non-GL3 host. */
|
||||
if (req->base.array_size > 0 && !has_sm4_context(dev_priv)) {
|
||||
VMW_DEBUG_USER("SM4 surface not supported.\n");
|
||||
return -EINVAL;
|
||||
if (req->base.array_size > 0) {
|
||||
if (has_sm5_context(dev_priv)) {
|
||||
if (req->base.array_size > SVGA3D_SM5_MAX_SURFACE_ARRAYSIZE) {
|
||||
VMW_DEBUG_USER("Invalid Surface Array Size.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (has_sm4_context(dev_priv)) {
|
||||
if (req->base.array_size > SVGA3D_SM4_MAX_SURFACE_ARRAYSIZE) {
|
||||
VMW_DEBUG_USER("Invalid Surface Array Size.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
VMW_DEBUG_USER("SM4+ surface not supported.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_sm4_1_context(dev_priv)) {
|
||||
|
||||
@@ -95,18 +95,21 @@ static int xe_i2c_register_adapter(struct xe_i2c *i2c)
|
||||
struct platform_device *pdev;
|
||||
struct fwnode_handle *fwnode;
|
||||
int ret;
|
||||
u32 id;
|
||||
|
||||
fwnode = fwnode_create_software_node(xe_i2c_adapter_properties, NULL);
|
||||
if (IS_ERR(fwnode))
|
||||
return PTR_ERR(fwnode);
|
||||
|
||||
id = (pci_domain_nr(pci->bus) << 16) | pci_dev_id(pci);
|
||||
|
||||
/*
|
||||
* Not using platform_device_register_full() here because we don't have
|
||||
* a handle to the platform_device before it returns. xe_i2c_notifier()
|
||||
* uses that handle, but it may be called before
|
||||
* platform_device_register_full() is done.
|
||||
*/
|
||||
pdev = platform_device_alloc(adapter_name, pci_dev_id(pci));
|
||||
pdev = platform_device_alloc(adapter_name, id);
|
||||
if (!pdev) {
|
||||
ret = -ENOMEM;
|
||||
goto err_fwnode_remove;
|
||||
|
||||
@@ -1313,6 +1313,7 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q,
|
||||
* content.
|
||||
* @src_bo: The buffer object @src is currently bound to.
|
||||
* @read_write : Creates BB commands for CCS read/write.
|
||||
* @bound: Device is bound
|
||||
*
|
||||
* Directly clearing the BB lacks atomicity and can lead to undefined
|
||||
* behavior if the vCPU is halted mid-operation during the clearing
|
||||
@@ -1325,7 +1326,8 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q,
|
||||
* Returns: None.
|
||||
*/
|
||||
void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo,
|
||||
enum xe_sriov_vf_ccs_rw_ctxs read_write)
|
||||
enum xe_sriov_vf_ccs_rw_ctxs read_write,
|
||||
bool bound)
|
||||
{
|
||||
struct xe_mem_pool_node *bb = src_bo->bb_ccs[read_write];
|
||||
struct xe_device *xe = xe_bo_device(src_bo);
|
||||
@@ -1339,13 +1341,15 @@ void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo,
|
||||
bb_pool = ctx->mem.ccs_bb_pool;
|
||||
|
||||
scoped_guard(mutex, xe_mem_pool_bo_swap_guard(bb_pool)) {
|
||||
xe_mem_pool_swap_shadow_locked(bb_pool);
|
||||
if (bound) {
|
||||
xe_mem_pool_swap_shadow_locked(bb_pool);
|
||||
|
||||
cs = xe_mem_pool_node_cpu_addr(bb);
|
||||
memset(cs, MI_NOOP, bb->sa_node.size);
|
||||
xe_sriov_vf_ccs_rw_update_bb_addr(ctx);
|
||||
cs = xe_mem_pool_node_cpu_addr(bb);
|
||||
memset(cs, MI_NOOP, bb->sa_node.size);
|
||||
xe_sriov_vf_ccs_rw_update_bb_addr(ctx);
|
||||
|
||||
xe_mem_pool_sync_shadow_locked(bb);
|
||||
xe_mem_pool_sync_shadow_locked(bb);
|
||||
}
|
||||
xe_mem_pool_free_node(bb);
|
||||
src_bo->bb_ccs[read_write] = NULL;
|
||||
}
|
||||
|
||||
@@ -142,7 +142,8 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q,
|
||||
enum xe_sriov_vf_ccs_rw_ctxs read_write);
|
||||
|
||||
void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo,
|
||||
enum xe_sriov_vf_ccs_rw_ctxs read_write);
|
||||
enum xe_sriov_vf_ccs_rw_ctxs read_write,
|
||||
bool bound);
|
||||
|
||||
struct xe_lrc *xe_migrate_lrc(struct xe_migrate *migrate);
|
||||
struct xe_exec_queue *xe_migrate_exec_queue(struct xe_migrate *migrate);
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
* Copyright © 2025 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
|
||||
#include "instructions/xe_mi_commands.h"
|
||||
#include "instructions/xe_gpu_commands.h"
|
||||
#include "xe_bb.h"
|
||||
@@ -446,7 +448,7 @@ int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo, struct ttm_resource *new_mem)
|
||||
*/
|
||||
for_each_ccs_rw_ctx(ctx_id) {
|
||||
if (bo->bb_ccs[ctx_id])
|
||||
xe_migrate_ccs_rw_copy_clear(bo, ctx_id);
|
||||
xe_migrate_ccs_rw_copy_clear(bo, ctx_id, true);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
@@ -466,19 +468,27 @@ int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo)
|
||||
struct xe_device *xe = xe_bo_device(bo);
|
||||
enum xe_sriov_vf_ccs_rw_ctxs ctx_id;
|
||||
struct xe_mem_pool_node *bb;
|
||||
bool bound;
|
||||
int idx;
|
||||
|
||||
xe_assert(xe, IS_VF_CCS_READY(xe));
|
||||
|
||||
if (!xe_bo_has_valid_ccs_bb(bo))
|
||||
return 0;
|
||||
|
||||
bound = drm_dev_enter(&xe->drm, &idx);
|
||||
|
||||
for_each_ccs_rw_ctx(ctx_id) {
|
||||
bb = bo->bb_ccs[ctx_id];
|
||||
if (!bb)
|
||||
continue;
|
||||
|
||||
xe_migrate_ccs_rw_copy_clear(bo, ctx_id);
|
||||
xe_migrate_ccs_rw_copy_clear(bo, ctx_id, bound);
|
||||
}
|
||||
|
||||
if (bound)
|
||||
drm_dev_exit(idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1809,10 +1809,10 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef)
|
||||
return ERR_PTR(err);
|
||||
|
||||
err_svm_fini:
|
||||
if (flags & XE_VM_FLAG_FAULT_MODE) {
|
||||
vm->size = 0; /* close the vm */
|
||||
xe_svm_fini(vm);
|
||||
}
|
||||
vm->size = 0; /* close the vm */
|
||||
if (flags & XE_VM_FLAG_FAULT_MODE)
|
||||
xe_svm_close(vm);
|
||||
xe_svm_fini(vm);
|
||||
err_no_resv:
|
||||
mutex_destroy(&vm->snap_mutex);
|
||||
for_each_tile(tile, xe, id)
|
||||
|
||||
@@ -332,6 +332,20 @@ static int xe_vm_invalidate_madvise_range(struct xe_vm *vm, u64 start, u64 end)
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* madvise_range_needs_invalidation() - Check whether madvise needs invalidation
|
||||
* @args: madvise ioctl arguments
|
||||
*
|
||||
* Purgeable state updates only touch VMA/BO metadata. PTEs stay valid and are
|
||||
* zapped only if the BO is later purged.
|
||||
*
|
||||
* Return: true when the update needs PTE invalidation.
|
||||
*/
|
||||
static bool madvise_range_needs_invalidation(const struct drm_xe_madvise *args)
|
||||
{
|
||||
return args->type != DRM_XE_VMA_ATTR_PURGEABLE_STATE;
|
||||
}
|
||||
|
||||
static bool madvise_args_are_sane(struct xe_device *xe, const struct drm_xe_madvise *args)
|
||||
{
|
||||
if (XE_IOCTL_DBG(xe, !args))
|
||||
@@ -708,8 +722,9 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
|
||||
madvise_funcs[attr_type](xe, vm, madvise_range.vmas, madvise_range.num_vmas, args,
|
||||
&details);
|
||||
|
||||
err = xe_vm_invalidate_madvise_range(vm, madvise_range.addr,
|
||||
madvise_range.addr + args->range);
|
||||
if (madvise_range_needs_invalidation(args))
|
||||
err = xe_vm_invalidate_madvise_range(vm, madvise_range.addr,
|
||||
madvise_range.addr + args->range);
|
||||
|
||||
if (madvise_range.has_svm_userptr_vmas)
|
||||
xe_svm_notifier_unlock(vm);
|
||||
|
||||
@@ -1009,7 +1009,7 @@ struct ec_sensors_data {
|
||||
/* sorted list of unique register banks */
|
||||
u8 banks[ASUS_EC_MAX_BANK + 1];
|
||||
/* in jiffies */
|
||||
unsigned long last_updated;
|
||||
u64 next_update;
|
||||
struct lock_data lock_data;
|
||||
/* number of board EC sensors */
|
||||
u8 nr_sensors;
|
||||
@@ -1189,7 +1189,7 @@ static int asus_ec_block_read(const struct device *dev,
|
||||
}
|
||||
for (ireg = 0; ireg < ec->nr_registers; ireg++) {
|
||||
reg_bank = register_bank(ec->registers[ireg]);
|
||||
if (reg_bank < bank) {
|
||||
if (reg_bank != bank) {
|
||||
continue;
|
||||
}
|
||||
ec_read(register_index(ec->registers[ireg]),
|
||||
@@ -1278,13 +1278,12 @@ static int get_cached_value_or_update(const struct device *dev,
|
||||
int sensor_index,
|
||||
struct ec_sensors_data *state, s32 *value)
|
||||
{
|
||||
if (time_after(jiffies, state->last_updated + HZ)) {
|
||||
if (time_after64(get_jiffies_64(), state->next_update)) {
|
||||
if (update_ec_sensors(dev, state)) {
|
||||
dev_err(dev, "update_ec_sensors() failure\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
state->last_updated = jiffies;
|
||||
state->next_update = get_jiffies_64() + HZ;
|
||||
}
|
||||
|
||||
*value = state->sensors[sensor_index].cached_value;
|
||||
@@ -1402,6 +1401,7 @@ static int asus_ec_probe(struct platform_device *pdev)
|
||||
if (!ec_data)
|
||||
return -ENOMEM;
|
||||
|
||||
ec_data->next_update = INITIAL_JIFFIES;
|
||||
dev_set_drvdata(dev, ec_data);
|
||||
ec_data->board_info = pboard_info;
|
||||
|
||||
@@ -1495,9 +1495,11 @@ static int asus_ec_probe(struct platform_device *pdev)
|
||||
if (!nr_count[type])
|
||||
continue;
|
||||
|
||||
asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev,
|
||||
nr_count[type], type,
|
||||
hwmon_attributes[type]);
|
||||
status = asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev,
|
||||
nr_count[type], type,
|
||||
hwmon_attributes[type]);
|
||||
if (status)
|
||||
return status;
|
||||
*ptr_asus_ec_ci++ = asus_ec_hwmon_chan++;
|
||||
}
|
||||
|
||||
|
||||
@@ -645,6 +645,7 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
|
||||
out_hw_close:
|
||||
hid_hw_close(hdev);
|
||||
hid_device_io_stop(hdev);
|
||||
out_hw_stop:
|
||||
hid_hw_stop(hdev);
|
||||
return ret;
|
||||
|
||||
@@ -822,6 +822,7 @@ static int corsairpsu_probe(struct hid_device *hdev, const struct hid_device_id
|
||||
|
||||
fail_and_close:
|
||||
hid_hw_close(hdev);
|
||||
hid_device_io_stop(hdev);
|
||||
fail_and_stop:
|
||||
hid_hw_stop(hdev);
|
||||
return ret;
|
||||
|
||||
@@ -371,13 +371,15 @@ static int waterforce_probe(struct hid_device *hdev, const struct hid_device_id
|
||||
if (IS_ERR(priv->hwmon_dev)) {
|
||||
ret = PTR_ERR(priv->hwmon_dev);
|
||||
hid_err(hdev, "hwmon registration failed with %d\n", ret);
|
||||
goto fail_and_close;
|
||||
goto fail_and_io_stop;
|
||||
}
|
||||
|
||||
waterforce_debugfs_init(priv);
|
||||
|
||||
return 0;
|
||||
|
||||
fail_and_io_stop:
|
||||
hid_device_io_stop(hdev);
|
||||
fail_and_close:
|
||||
hid_hw_close(hdev);
|
||||
fail_and_stop:
|
||||
|
||||
@@ -948,7 +948,7 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id
|
||||
ret = kraken3_init_device(hdev);
|
||||
if (ret < 0) {
|
||||
hid_err(hdev, "device init failed with %d\n", ret);
|
||||
goto fail_and_close;
|
||||
goto fail_and_stop_io;
|
||||
}
|
||||
|
||||
ret = kraken3_get_fw_ver(hdev);
|
||||
@@ -960,13 +960,15 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id
|
||||
if (IS_ERR(priv->hwmon_dev)) {
|
||||
ret = PTR_ERR(priv->hwmon_dev);
|
||||
hid_err(hdev, "hwmon registration failed with %d\n", ret);
|
||||
goto fail_and_close;
|
||||
goto fail_and_stop_io;
|
||||
}
|
||||
|
||||
kraken3_debugfs_init(priv, device_name);
|
||||
|
||||
return 0;
|
||||
|
||||
fail_and_stop_io:
|
||||
hid_device_io_stop(hdev);
|
||||
fail_and_close:
|
||||
hid_hw_close(hdev);
|
||||
fail_and_stop:
|
||||
|
||||
@@ -768,7 +768,7 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev,
|
||||
|
||||
out_hw_close:
|
||||
hid_hw_close(hdev);
|
||||
|
||||
hid_device_io_stop(hdev);
|
||||
out_hw_stop:
|
||||
hid_hw_stop(hdev);
|
||||
return ret;
|
||||
|
||||
@@ -1052,32 +1052,49 @@ static int occ_setup_sensor_attrs(struct occ *occ)
|
||||
}
|
||||
|
||||
/* only need to do this once at startup, as OCC won't change sensors on us */
|
||||
static void occ_parse_poll_response(struct occ *occ)
|
||||
static int occ_parse_poll_response(struct occ *occ)
|
||||
{
|
||||
unsigned int i, old_offset, offset = 0, size = 0;
|
||||
u16 data_length;
|
||||
struct occ_sensor *sensor;
|
||||
struct occ_sensors *sensors = &occ->sensors;
|
||||
struct occ_sensors parsed = {};
|
||||
struct occ_sensors *sensors = &parsed;
|
||||
struct occ_response *resp = &occ->resp;
|
||||
struct occ_poll_response *poll =
|
||||
(struct occ_poll_response *)&resp->data[0];
|
||||
struct occ_poll_response_header *header = &poll->header;
|
||||
struct occ_sensor_data_block *block = &poll->block;
|
||||
|
||||
data_length = get_unaligned_be16(&resp->data_length);
|
||||
if (data_length < sizeof(*header) || data_length > OCC_RESP_DATA_BYTES) {
|
||||
dev_err(occ->bus_dev, "invalid OCC poll response length %u\n",
|
||||
data_length);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
dev_info(occ->bus_dev, "OCC found, code level: %.16s\n",
|
||||
header->occ_code_level);
|
||||
|
||||
for (i = 0; i < header->num_sensor_data_blocks; ++i) {
|
||||
block = (struct occ_sensor_data_block *)((u8 *)block + offset);
|
||||
if (size + sizeof(*header) + sizeof(block->header) >
|
||||
data_length) {
|
||||
dev_err(occ->bus_dev,
|
||||
"truncated OCC sensor block header\n");
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
old_offset = offset;
|
||||
offset = (block->header.num_sensors *
|
||||
block->header.sensor_length) + sizeof(block->header);
|
||||
size += offset;
|
||||
|
||||
/* validate all the length/size fields */
|
||||
if ((size + sizeof(*header)) >= OCC_RESP_DATA_BYTES) {
|
||||
dev_warn(occ->bus_dev, "exceeded response buffer\n");
|
||||
return;
|
||||
if (size + sizeof(*header) + offset > data_length) {
|
||||
dev_err(occ->bus_dev,
|
||||
"exceeded OCC poll response length\n");
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
size += offset;
|
||||
|
||||
dev_dbg(occ->bus_dev, " %04x..%04x: %.4s (%d sensors)\n",
|
||||
old_offset, offset - 1, block->header.eye_catcher,
|
||||
@@ -1107,6 +1124,9 @@ static void occ_parse_poll_response(struct occ *occ)
|
||||
|
||||
dev_dbg(occ->bus_dev, "Max resp size: %u+%zd=%zd\n", size,
|
||||
sizeof(*header), size + sizeof(*header));
|
||||
occ->sensors = parsed;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int occ_active(struct occ *occ, bool active)
|
||||
@@ -1138,10 +1158,12 @@ int occ_active(struct occ *occ, bool active)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
occ->active = true;
|
||||
occ->next_update = jiffies + OCC_UPDATE_FREQUENCY;
|
||||
occ_parse_poll_response(occ);
|
||||
rc = occ_parse_poll_response(occ);
|
||||
if (rc)
|
||||
goto unlock;
|
||||
|
||||
occ->active = true;
|
||||
rc = occ_setup_sensor_attrs(occ);
|
||||
if (rc) {
|
||||
dev_err(occ->bus_dev,
|
||||
|
||||
@@ -88,6 +88,33 @@ static int max34440_read_word_data(struct i2c_client *client, int page,
|
||||
ret = pmbus_read_word_data(client, page, phase,
|
||||
data->iout_oc_warn_limit);
|
||||
break;
|
||||
case PMBUS_VIN_OV_FAULT_LIMIT:
|
||||
case PMBUS_VIN_OV_WARN_LIMIT:
|
||||
case PMBUS_VIN_UV_WARN_LIMIT:
|
||||
case PMBUS_VIN_UV_FAULT_LIMIT:
|
||||
case PMBUS_MFR_VIN_MIN:
|
||||
case PMBUS_MFR_VIN_MAX:
|
||||
case PMBUS_IIN_OC_WARN_LIMIT:
|
||||
case PMBUS_IIN_OC_FAULT_LIMIT:
|
||||
case PMBUS_MFR_IIN_MAX:
|
||||
case PMBUS_MFR_VOUT_MIN:
|
||||
case PMBUS_MFR_VOUT_MAX:
|
||||
case PMBUS_IOUT_UC_FAULT_LIMIT:
|
||||
case PMBUS_MFR_IOUT_MAX:
|
||||
case PMBUS_UT_WARN_LIMIT:
|
||||
case PMBUS_UT_FAULT_LIMIT:
|
||||
case PMBUS_MFR_MAX_TEMP_1:
|
||||
/*
|
||||
* MAX34451/ADPM family do not support VIN/IIN limit registers,
|
||||
* manufacturer-specific min/max registers, or undercurrent/
|
||||
* undertemperature fault limits. Accessing these triggers CML
|
||||
* error and asserts ALERT.
|
||||
*/
|
||||
if (data->id == max34451 || data->id == adpm12160 ||
|
||||
data->id == adpm12200 || data->id == adpm12250)
|
||||
return -ENXIO;
|
||||
ret = -ENODATA;
|
||||
break;
|
||||
case PMBUS_VIRT_READ_VOUT_MIN:
|
||||
ret = pmbus_read_word_data(client, page, phase,
|
||||
MAX34440_MFR_VOUT_MIN);
|
||||
@@ -244,6 +271,51 @@ static int max34440_read_byte_data(struct i2c_client *client, int page, int reg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max34451_read_byte_data(struct i2c_client *client, int page, int reg)
|
||||
{
|
||||
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||||
const struct max34440_data *data = to_max34440_data(info);
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_STATUS_BYTE:
|
||||
case PMBUS_STATUS_OTHER:
|
||||
/*
|
||||
* MAX34451/ADPM family do not support STATUS_BYTE or
|
||||
* STATUS_OTHER registers. Accessing them triggers CML
|
||||
* error and asserts ALERT.
|
||||
*/
|
||||
if (data->id == max34451 || data->id == adpm12160 ||
|
||||
data->id == adpm12200 || data->id == adpm12250)
|
||||
return -ENXIO;
|
||||
return -ENODATA;
|
||||
default:
|
||||
return -ENODATA;
|
||||
}
|
||||
}
|
||||
|
||||
static int max34451_write_byte_data(struct i2c_client *client, int page,
|
||||
int reg, u8 byte)
|
||||
{
|
||||
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||||
const struct max34440_data *data = to_max34440_data(info);
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_STATUS_BYTE:
|
||||
case PMBUS_STATUS_OTHER:
|
||||
/*
|
||||
* MAX34451/ADPM family do not support STATUS_BYTE or
|
||||
* STATUS_OTHER registers. Writing to them triggers CML
|
||||
* error and asserts ALERT.
|
||||
*/
|
||||
if (data->id == max34451 || data->id == adpm12160 ||
|
||||
data->id == adpm12200 || data->id == adpm12250)
|
||||
return -ENXIO;
|
||||
return -ENODATA;
|
||||
default:
|
||||
return -ENODATA;
|
||||
}
|
||||
}
|
||||
|
||||
static int max34451_set_supported_funcs(struct i2c_client *client,
|
||||
struct max34440_data *data)
|
||||
{
|
||||
@@ -363,7 +435,9 @@ static struct pmbus_driver_info max34440_info[] = {
|
||||
.func[9] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT,
|
||||
.func[10] = PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT,
|
||||
.func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
|
||||
.read_byte_data = max34451_read_byte_data,
|
||||
.read_word_data = max34440_read_word_data,
|
||||
.write_byte_data = max34451_write_byte_data,
|
||||
.write_word_data = max34440_write_word_data,
|
||||
},
|
||||
[adpm12200] = {
|
||||
@@ -399,7 +473,9 @@ static struct pmbus_driver_info max34440_info[] = {
|
||||
.func[10] = PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT,
|
||||
.func[14] = PMBUS_HAVE_IOUT,
|
||||
.func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
|
||||
.read_byte_data = max34451_read_byte_data,
|
||||
.read_word_data = max34440_read_word_data,
|
||||
.write_byte_data = max34451_write_byte_data,
|
||||
.write_word_data = max34440_write_word_data,
|
||||
},
|
||||
[adpm12250] = {
|
||||
@@ -433,7 +509,9 @@ static struct pmbus_driver_info max34440_info[] = {
|
||||
.func[10] = PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT,
|
||||
.func[14] = PMBUS_HAVE_IOUT,
|
||||
.func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
|
||||
.read_byte_data = max34451_read_byte_data,
|
||||
.read_word_data = max34440_read_word_data,
|
||||
.write_byte_data = max34451_write_byte_data,
|
||||
.write_word_data = max34440_write_word_data,
|
||||
},
|
||||
[max34440] = {
|
||||
@@ -581,7 +659,9 @@ static struct pmbus_driver_info max34440_info[] = {
|
||||
.func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
|
||||
.func[19] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
|
||||
.func[20] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
|
||||
.read_byte_data = max34451_read_byte_data,
|
||||
.read_word_data = max34440_read_word_data,
|
||||
.write_byte_data = max34451_write_byte_data,
|
||||
.write_word_data = max34440_write_word_data,
|
||||
.page_change_delay = MAX34440_PAGE_CHANGE_DELAY,
|
||||
},
|
||||
|
||||
@@ -843,18 +843,8 @@ static int intel_th_output_open(struct inode *inode, struct file *file)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int intel_th_output_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct intel_th_device *thdev = file->private_data;
|
||||
|
||||
put_device(&thdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations intel_th_output_fops = {
|
||||
.open = intel_th_output_open,
|
||||
.release = intel_th_output_release,
|
||||
.llseek = noop_llseek,
|
||||
};
|
||||
|
||||
|
||||
@@ -1490,8 +1490,10 @@ static int intel_th_msc_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct msc_iter *iter = file->private_data;
|
||||
struct msc *msc = iter->msc;
|
||||
struct intel_th_device *thdev = msc->thdev;
|
||||
|
||||
msc_iter_remove(iter, msc);
|
||||
put_device(&thdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ static void bng_re_fill_fw_msg(struct bnge_fw_msg *fw_msg, void *msg,
|
||||
}
|
||||
|
||||
static int bng_re_net_ring_free(struct bng_re_dev *rdev,
|
||||
u16 fw_ring_id, int type)
|
||||
u32 fw_ring_id, int type)
|
||||
{
|
||||
struct bnge_auxr_dev *aux_dev = rdev->aux_dev;
|
||||
struct hwrm_ring_free_input req = {};
|
||||
@@ -123,7 +123,7 @@ static int bng_re_net_ring_free(struct bng_re_dev *rdev,
|
||||
|
||||
bng_re_init_hwrm_hdr((void *)&req, HWRM_RING_FREE);
|
||||
req.ring_type = type;
|
||||
req.ring_id = cpu_to_le16(fw_ring_id);
|
||||
req.ring_id = cpu_to_le32(fw_ring_id);
|
||||
bng_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp,
|
||||
sizeof(resp), BNGE_DFLT_HWRM_CMD_TIMEOUT);
|
||||
rc = bnge_send_msg(aux_dev, &fw_msg);
|
||||
@@ -161,7 +161,7 @@ static int bng_re_net_ring_alloc(struct bng_re_dev *rdev,
|
||||
sizeof(resp), BNGE_DFLT_HWRM_CMD_TIMEOUT);
|
||||
rc = bnge_send_msg(aux_dev, &fw_msg);
|
||||
if (!rc)
|
||||
*fw_ring_id = le16_to_cpu(resp.ring_id);
|
||||
*fw_ring_id = (u16)le32_to_cpu(resp.ring_id);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3864,6 +3864,12 @@ static int __init parse_ivrs_acpihid(char *str)
|
||||
return 1;
|
||||
|
||||
found:
|
||||
if (early_acpihid_map_size == EARLY_MAP_SIZE) {
|
||||
pr_err("Early ACPI HID map overflow - ignoring ivrs_acpihid%s\n",
|
||||
str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
p = acpiid;
|
||||
hid = strsep(&p, ":");
|
||||
uid = p;
|
||||
|
||||
@@ -1450,11 +1450,23 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
|
||||
int ret;
|
||||
u64 data;
|
||||
|
||||
if (!iommu->need_sync)
|
||||
return 0;
|
||||
|
||||
raw_spin_lock_irqsave(&iommu->lock, flags);
|
||||
|
||||
if (!iommu->need_sync) {
|
||||
/*
|
||||
* No command has been queued since the last completion-wait.
|
||||
* A concurrent CPU may have already queued that CWAIT and
|
||||
* cleared need_sync; need_sync == false only means a covering
|
||||
* CWAIT is queued, not that all prior commands have completed.
|
||||
* Wait for the last allocated sequence number so that any
|
||||
* command queued before this call (possibly on another CPU)
|
||||
* is guaranteed to have completed before returning.
|
||||
*/
|
||||
data = iommu->cmd_sem_val;
|
||||
raw_spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
return wait_on_sem(iommu, data);
|
||||
}
|
||||
|
||||
data = get_cmdsem_val(iommu);
|
||||
build_completion_wait(&cmd, iommu, data);
|
||||
|
||||
@@ -1464,9 +1476,7 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = wait_on_sem(iommu, data);
|
||||
|
||||
return ret;
|
||||
return wait_on_sem(iommu, data);
|
||||
}
|
||||
|
||||
static void domain_flush_complete(struct protection_domain *domain)
|
||||
|
||||
@@ -59,7 +59,9 @@ static int validate_gdte_nested(struct iommu_hwpt_amd_guest *gdte)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *gdom_info_load_or_alloc_locked(struct xarray *xa, unsigned long index)
|
||||
static void *gdom_info_load_or_alloc_locked(struct xarray *xa,
|
||||
unsigned long index,
|
||||
unsigned long *flags)
|
||||
{
|
||||
struct guest_domain_mapping_info *elm, *res;
|
||||
|
||||
@@ -67,13 +69,13 @@ static void *gdom_info_load_or_alloc_locked(struct xarray *xa, unsigned long ind
|
||||
if (elm)
|
||||
return elm;
|
||||
|
||||
xa_unlock(xa);
|
||||
xa_unlock_irqrestore(xa, *flags);
|
||||
elm = kzalloc_obj(struct guest_domain_mapping_info);
|
||||
xa_lock(xa);
|
||||
xa_lock_irqsave(xa, *flags);
|
||||
if (!elm)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
res = __xa_cmpxchg(xa, index, NULL, elm, GFP_KERNEL);
|
||||
res = __xa_cmpxchg(xa, index, NULL, elm, GFP_ATOMIC);
|
||||
if (xa_is_err(res))
|
||||
res = ERR_PTR(xa_err(res));
|
||||
|
||||
@@ -95,6 +97,7 @@ amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags,
|
||||
const struct iommu_user_data *user_data)
|
||||
{
|
||||
int ret;
|
||||
unsigned long irqflags;
|
||||
struct nested_domain *ndom;
|
||||
struct guest_domain_mapping_info *gdom_info;
|
||||
struct amd_iommu_viommu *aviommu = container_of(viommu, struct amd_iommu_viommu, core);
|
||||
@@ -136,11 +139,12 @@ amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags,
|
||||
* keep track of the gDomID mapping. When the S2 is changed, the INVALIDATE_IOMMU_PAGES
|
||||
* command must be issued for each hDomID in the xarray.
|
||||
*/
|
||||
xa_lock(&aviommu->gdomid_array);
|
||||
xa_lock_irqsave(&aviommu->gdomid_array, irqflags);
|
||||
|
||||
gdom_info = gdom_info_load_or_alloc_locked(&aviommu->gdomid_array, ndom->gdom_id);
|
||||
gdom_info = gdom_info_load_or_alloc_locked(&aviommu->gdomid_array,
|
||||
ndom->gdom_id, &irqflags);
|
||||
if (IS_ERR(gdom_info)) {
|
||||
xa_unlock(&aviommu->gdomid_array);
|
||||
xa_unlock_irqrestore(&aviommu->gdomid_array, irqflags);
|
||||
ret = PTR_ERR(gdom_info);
|
||||
goto out_err;
|
||||
}
|
||||
@@ -148,7 +152,7 @@ amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags,
|
||||
/* Check if gDomID exist */
|
||||
if (refcount_inc_not_zero(&gdom_info->users)) {
|
||||
ndom->gdom_info = gdom_info;
|
||||
xa_unlock(&aviommu->gdomid_array);
|
||||
xa_unlock_irqrestore(&aviommu->gdomid_array, irqflags);
|
||||
|
||||
pr_debug("%s: Found gdom_id=%#x, hdom_id=%#x\n",
|
||||
__func__, ndom->gdom_id, gdom_info->hdom_id);
|
||||
@@ -161,7 +165,7 @@ amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags,
|
||||
if (gdom_info->hdom_id <= 0) {
|
||||
__xa_cmpxchg(&aviommu->gdomid_array,
|
||||
ndom->gdom_id, gdom_info, NULL, GFP_ATOMIC);
|
||||
xa_unlock(&aviommu->gdomid_array);
|
||||
xa_unlock_irqrestore(&aviommu->gdomid_array, irqflags);
|
||||
ret = -ENOSPC;
|
||||
goto out_err_gdom_info;
|
||||
}
|
||||
@@ -169,7 +173,7 @@ amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags,
|
||||
ndom->gdom_info = gdom_info;
|
||||
refcount_set(&gdom_info->users, 1);
|
||||
|
||||
xa_unlock(&aviommu->gdomid_array);
|
||||
xa_unlock_irqrestore(&aviommu->gdomid_array, irqflags);
|
||||
|
||||
pr_debug("%s: Allocate gdom_id=%#x, hdom_id=%#x\n",
|
||||
__func__, ndom->gdom_id, gdom_info->hdom_id);
|
||||
@@ -257,14 +261,15 @@ static int nested_attach_device(struct iommu_domain *dom, struct device *dev,
|
||||
|
||||
static void nested_domain_free(struct iommu_domain *dom)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
struct guest_domain_mapping_info *curr;
|
||||
struct nested_domain *ndom = to_ndomain(dom);
|
||||
struct nested_domain *ndom __free(kfree) = to_ndomain(dom);
|
||||
struct amd_iommu_viommu *aviommu = ndom->viommu;
|
||||
|
||||
xa_lock(&aviommu->gdomid_array);
|
||||
xa_lock_irqsave(&aviommu->gdomid_array, irqflags);
|
||||
|
||||
if (!refcount_dec_and_test(&ndom->gdom_info->users)) {
|
||||
xa_unlock(&aviommu->gdomid_array);
|
||||
xa_unlock_irqrestore(&aviommu->gdomid_array, irqflags);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -275,7 +280,7 @@ static void nested_domain_free(struct iommu_domain *dom)
|
||||
curr = __xa_cmpxchg(&aviommu->gdomid_array, ndom->gdom_id,
|
||||
ndom->gdom_info, NULL, GFP_ATOMIC);
|
||||
|
||||
xa_unlock(&aviommu->gdomid_array);
|
||||
xa_unlock_irqrestore(&aviommu->gdomid_array, irqflags);
|
||||
if (WARN_ON(!curr || xa_err(curr)))
|
||||
return;
|
||||
|
||||
@@ -285,7 +290,6 @@ static void nested_domain_free(struct iommu_domain *dom)
|
||||
|
||||
amd_iommu_pdom_id_free(ndom->gdom_info->hdom_id);
|
||||
kfree(curr);
|
||||
kfree(ndom);
|
||||
}
|
||||
|
||||
static const struct iommu_domain_ops nested_domain_ops = {
|
||||
|
||||
@@ -63,7 +63,7 @@ void dmar_latency_disable(struct intel_iommu *iommu, enum latency_type type)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&latency_lock, flags);
|
||||
memset(&lstat[type], 0, sizeof(*lstat) * DMAR_LATENCY_NUM);
|
||||
memset(&lstat[type], 0, sizeof(*lstat));
|
||||
spin_unlock_irqrestore(&latency_lock, flags);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
void intel_svm_check(struct intel_iommu *iommu)
|
||||
{
|
||||
if (!pasid_supported(iommu))
|
||||
if (!pasid_supported(iommu) || !ecap_smpwc(iommu->ecap))
|
||||
return;
|
||||
|
||||
if (cpu_feature_enabled(X86_FEATURE_GBPAGES) &&
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* Intel Management Engine Interface (Intel MEI) Linux driver
|
||||
*/
|
||||
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
@@ -1330,15 +1331,16 @@ static void mei_dev_bus_put(struct mei_device *bus)
|
||||
static void mei_cl_bus_dev_release(struct device *dev)
|
||||
{
|
||||
struct mei_cl_device *cldev = to_mei_cl_device(dev);
|
||||
struct mei_device *mdev = cldev->cl->dev;
|
||||
struct mei_device *bus = cldev->bus;
|
||||
struct mei_cl *cl;
|
||||
|
||||
mei_cl_flush_queues(cldev->cl, NULL);
|
||||
mei_me_cl_put(cldev->me_cl);
|
||||
mei_dev_bus_put(cldev->bus);
|
||||
|
||||
list_for_each_entry(cl, &mdev->file_list, link)
|
||||
WARN_ON(cl == cldev->cl);
|
||||
scoped_guard(mutex, &bus->device_lock) {
|
||||
mei_cl_flush_queues(cldev->cl, NULL);
|
||||
mei_me_cl_put(cldev->me_cl);
|
||||
list_for_each_entry(cl, &bus->file_list, link)
|
||||
WARN_ON(cl == cldev->cl);
|
||||
}
|
||||
mei_dev_bus_put(bus);
|
||||
|
||||
kfree(cldev->cl);
|
||||
kfree(cldev);
|
||||
|
||||
@@ -367,7 +367,7 @@ static long nsm_dev_ioctl(struct file *file, unsigned int cmd,
|
||||
/* Copy user argument struct to kernel argument struct */
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(&raw, argp, _IOC_SIZE(cmd)))
|
||||
goto out;
|
||||
return r;
|
||||
|
||||
mutex_lock(&nsm->lock);
|
||||
|
||||
@@ -413,6 +413,7 @@ static int nsm_device_init_vq(struct virtio_device *vdev)
|
||||
}
|
||||
|
||||
static const struct file_operations nsm_dev_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.unlocked_ioctl = nsm_dev_ioctl,
|
||||
.compat_ioctl = compat_ptr_ioctl,
|
||||
};
|
||||
|
||||
@@ -1211,7 +1211,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
data = true;
|
||||
}
|
||||
v6 = false;
|
||||
group.ip4 = iph->daddr;
|
||||
group.ip4 = ip_hdr(skb)->daddr;
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
} else if (iph->version == 6) {
|
||||
ip6h = ipv6_hdr(skb);
|
||||
@@ -1235,7 +1235,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
data = true;
|
||||
}
|
||||
v6 = true;
|
||||
group.ip6 = ip6h->daddr;
|
||||
group.ip6 = ipv6_hdr(skb)->daddr;
|
||||
#endif
|
||||
} else {
|
||||
dev->stats.tx_errors++;
|
||||
@@ -1278,12 +1278,12 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
hlist_for_each_entry_rcu(gnode, &tunnel->groups[hash],
|
||||
node) {
|
||||
if (!v6) {
|
||||
if (gnode->group_addr.ip4 == iph->daddr)
|
||||
if (gnode->group_addr.ip4 == group.ip4)
|
||||
goto found;
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
} else {
|
||||
if (ipv6_addr_equal(&gnode->group_addr.ip6,
|
||||
&ip6h->daddr))
|
||||
&group.ip6))
|
||||
goto found;
|
||||
#endif
|
||||
}
|
||||
@@ -2000,14 +2000,18 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb,
|
||||
struct igmpv3_report *ihrv3 = igmpv3_report_hdr(skb);
|
||||
int len = skb_transport_offset(skb) + sizeof(*ihrv3);
|
||||
void *zero_grec = (void *)&igmpv3_zero_grec;
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
struct amt_group_node *gnode;
|
||||
union amt_addr group, host;
|
||||
struct igmpv3_grec *grec;
|
||||
__be32 saddr;
|
||||
u16 nsrcs;
|
||||
u16 ngrec;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ntohs(ihrv3->ngrec); i++) {
|
||||
saddr = ip_hdr(skb)->saddr;
|
||||
ngrec = ntohs(ihrv3->ngrec);
|
||||
|
||||
for (i = 0; i < ngrec; i++) {
|
||||
len += sizeof(*grec);
|
||||
if (!ip_mc_may_pull(skb, len))
|
||||
break;
|
||||
@@ -2019,10 +2023,13 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb,
|
||||
if (!ip_mc_may_pull(skb, len))
|
||||
break;
|
||||
|
||||
grec = (void *)(skb->data + len - sizeof(*grec) -
|
||||
nsrcs * sizeof(__be32));
|
||||
|
||||
memset(&group, 0, sizeof(union amt_addr));
|
||||
group.ip4 = grec->grec_mca;
|
||||
memset(&host, 0, sizeof(union amt_addr));
|
||||
host.ip4 = iph->saddr;
|
||||
host.ip4 = saddr;
|
||||
gnode = amt_lookup_group(tunnel, &group, &host, false);
|
||||
if (!gnode) {
|
||||
gnode = amt_add_group(amt, tunnel, &group, &host,
|
||||
@@ -2162,14 +2169,18 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb,
|
||||
struct mld2_report *mld2r = (struct mld2_report *)icmp6_hdr(skb);
|
||||
int len = skb_transport_offset(skb) + sizeof(*mld2r);
|
||||
void *zero_grec = (void *)&mldv2_zero_grec;
|
||||
struct ipv6hdr *ip6h = ipv6_hdr(skb);
|
||||
struct amt_group_node *gnode;
|
||||
union amt_addr group, host;
|
||||
struct mld2_grec *grec;
|
||||
struct in6_addr saddr;
|
||||
u16 nsrcs;
|
||||
u16 ngrec;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ntohs(mld2r->mld2r_ngrec); i++) {
|
||||
saddr = ipv6_hdr(skb)->saddr;
|
||||
ngrec = ntohs(mld2r->mld2r_ngrec);
|
||||
|
||||
for (i = 0; i < ngrec; i++) {
|
||||
len += sizeof(*grec);
|
||||
if (!ipv6_mc_may_pull(skb, len))
|
||||
break;
|
||||
@@ -2181,10 +2192,13 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb,
|
||||
if (!ipv6_mc_may_pull(skb, len))
|
||||
break;
|
||||
|
||||
grec = (void *)(skb->data + len - sizeof(*grec) -
|
||||
nsrcs * sizeof(struct in6_addr));
|
||||
|
||||
memset(&group, 0, sizeof(union amt_addr));
|
||||
group.ip6 = grec->grec_mca;
|
||||
memset(&host, 0, sizeof(union amt_addr));
|
||||
host.ip6 = ip6h->saddr;
|
||||
host.ip6 = saddr;
|
||||
gnode = amt_lookup_group(tunnel, &group, &host, true);
|
||||
if (!gnode) {
|
||||
gnode = amt_add_group(amt, tunnel, &group, &host,
|
||||
@@ -2305,7 +2319,9 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)
|
||||
skb_push(skb, sizeof(*eth));
|
||||
skb_reset_mac_header(skb);
|
||||
skb_pull(skb, sizeof(*eth));
|
||||
eth = eth_hdr(skb);
|
||||
|
||||
if (skb_cow_head(skb, 0))
|
||||
return true;
|
||||
|
||||
if (!pskb_may_pull(skb, sizeof(*iph)))
|
||||
return true;
|
||||
@@ -2315,6 +2331,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)
|
||||
if (!ipv4_is_multicast(iph->daddr))
|
||||
return true;
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
eth = eth_hdr(skb);
|
||||
eth->h_proto = htons(ETH_P_IP);
|
||||
ip_eth_mc_map(iph->daddr, eth->h_dest);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
@@ -2328,6 +2345,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)
|
||||
if (!ipv6_addr_is_multicast(&ip6h->daddr))
|
||||
return true;
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
eth = eth_hdr(skb);
|
||||
eth->h_proto = htons(ETH_P_IPV6);
|
||||
ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
|
||||
#endif
|
||||
@@ -2351,10 +2369,12 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct amt_header_membership_query *amtmq;
|
||||
struct igmpv3_query *ihv3;
|
||||
struct ethhdr *eth, *oeth;
|
||||
struct igmpv3_query *ihv3;
|
||||
u8 h_source[ETH_ALEN];
|
||||
struct iphdr *iph;
|
||||
int hdr_size, len;
|
||||
u64 response_mac;
|
||||
|
||||
hdr_size = sizeof(*amtmq) + sizeof(struct udphdr);
|
||||
if (!pskb_may_pull(skb, hdr_size))
|
||||
@@ -2367,6 +2387,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
|
||||
if (amtmq->nonce != amt->nonce)
|
||||
return true;
|
||||
|
||||
response_mac = amtmq->response_mac;
|
||||
|
||||
hdr_size -= sizeof(*eth);
|
||||
if (iptunnel_pull_header(skb, hdr_size, htons(ETH_P_TEB), false))
|
||||
return true;
|
||||
@@ -2376,6 +2398,9 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
|
||||
skb_pull(skb, sizeof(*eth));
|
||||
skb_reset_network_header(skb);
|
||||
eth = eth_hdr(skb);
|
||||
ether_addr_copy(h_source, oeth->h_source);
|
||||
if (skb_cow_head(skb, 0))
|
||||
return true;
|
||||
if (!pskb_may_pull(skb, sizeof(*iph)))
|
||||
return true;
|
||||
|
||||
@@ -2388,6 +2413,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
|
||||
sizeof(*ihv3)))
|
||||
return true;
|
||||
|
||||
iph = ip_hdr(skb);
|
||||
if (!ipv4_is_multicast(iph->daddr))
|
||||
return true;
|
||||
|
||||
@@ -2395,10 +2421,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
|
||||
skb_reset_transport_header(skb);
|
||||
skb_push(skb, sizeof(*iph) + AMT_IPHDR_OPTS);
|
||||
WRITE_ONCE(amt->ready4, true);
|
||||
amt->mac = amtmq->response_mac;
|
||||
amt->mac = response_mac;
|
||||
amt->req_cnt = 0;
|
||||
amt->qi = ihv3->qqic;
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
eth = eth_hdr(skb);
|
||||
eth->h_proto = htons(ETH_P_IP);
|
||||
ip_eth_mc_map(iph->daddr, eth->h_dest);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
@@ -2421,10 +2448,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
|
||||
skb_reset_transport_header(skb);
|
||||
skb_push(skb, sizeof(*ip6h) + AMT_IP6HDR_OPTS);
|
||||
WRITE_ONCE(amt->ready6, true);
|
||||
amt->mac = amtmq->response_mac;
|
||||
amt->mac = response_mac;
|
||||
amt->req_cnt = 0;
|
||||
amt->qi = mld2q->mld2q_qqic;
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
eth = eth_hdr(skb);
|
||||
eth->h_proto = htons(ETH_P_IPV6);
|
||||
ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
|
||||
#endif
|
||||
@@ -2432,7 +2460,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
|
||||
return true;
|
||||
}
|
||||
|
||||
ether_addr_copy(eth->h_source, oeth->h_source);
|
||||
ether_addr_copy(eth->h_source, h_source);
|
||||
skb->pkt_type = PACKET_MULTICAST;
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
len = skb->len;
|
||||
@@ -2455,8 +2483,11 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
|
||||
struct ethhdr *eth;
|
||||
struct iphdr *iph;
|
||||
int len, hdr_size;
|
||||
u64 response_mac;
|
||||
__be32 saddr;
|
||||
__be32 nonce;
|
||||
|
||||
iph = ip_hdr(skb);
|
||||
saddr = ip_hdr(skb)->saddr;
|
||||
|
||||
hdr_size = sizeof(*amtmu) + sizeof(struct udphdr);
|
||||
if (!pskb_may_pull(skb, hdr_size))
|
||||
@@ -2466,15 +2497,18 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
|
||||
if (amtmu->reserved || amtmu->version)
|
||||
return true;
|
||||
|
||||
nonce = amtmu->nonce;
|
||||
response_mac = amtmu->response_mac;
|
||||
|
||||
if (iptunnel_pull_header(skb, hdr_size, skb->protocol, false))
|
||||
return true;
|
||||
|
||||
skb_reset_network_header(skb);
|
||||
|
||||
list_for_each_entry_rcu(tunnel, &amt->tunnel_list, list) {
|
||||
if (tunnel->ip4 == iph->saddr) {
|
||||
if ((amtmu->nonce == tunnel->nonce &&
|
||||
amtmu->response_mac == tunnel->mac)) {
|
||||
if (tunnel->ip4 == saddr) {
|
||||
if ((nonce == tunnel->nonce &&
|
||||
response_mac == tunnel->mac)) {
|
||||
mod_delayed_work(amt_wq, &tunnel->gc_wq,
|
||||
msecs_to_jiffies(amt_gmi(amt))
|
||||
* 3);
|
||||
@@ -2492,6 +2526,9 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
|
||||
if (!pskb_may_pull(skb, sizeof(*iph)))
|
||||
return true;
|
||||
|
||||
if (skb_cow_head(skb, 0))
|
||||
return true;
|
||||
|
||||
iph = ip_hdr(skb);
|
||||
if (iph->version == 4) {
|
||||
if (ip_mc_check_igmp(skb)) {
|
||||
@@ -2508,6 +2545,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
|
||||
eth = eth_hdr(skb);
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
eth->h_proto = htons(ETH_P_IP);
|
||||
iph = ip_hdr(skb);
|
||||
ip_eth_mc_map(iph->daddr, eth->h_dest);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
} else if (iph->version == 6) {
|
||||
@@ -2527,6 +2565,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
|
||||
eth = eth_hdr(skb);
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
eth->h_proto = htons(ETH_P_IPV6);
|
||||
ip6h = ipv6_hdr(skb);
|
||||
ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
|
||||
#endif
|
||||
} else {
|
||||
@@ -2772,7 +2811,7 @@ static void amt_gw_rcv(struct amt_dev *amt, struct sk_buff *skb)
|
||||
static int amt_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct amt_dev *amt;
|
||||
struct iphdr *iph;
|
||||
__be32 saddr;
|
||||
int type;
|
||||
bool err;
|
||||
|
||||
@@ -2785,7 +2824,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
skb->dev = amt->dev;
|
||||
iph = ip_hdr(skb);
|
||||
saddr = ip_hdr(skb)->saddr;
|
||||
type = amt_parse_type(skb);
|
||||
if (type == -1) {
|
||||
err = true;
|
||||
@@ -2795,7 +2834,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
if (amt->mode == AMT_MODE_GATEWAY) {
|
||||
switch (type) {
|
||||
case AMT_MSG_ADVERTISEMENT:
|
||||
if (iph->saddr != amt->discovery_ip) {
|
||||
if (saddr != amt->discovery_ip) {
|
||||
netdev_dbg(amt->dev, "Invalid Relay IP\n");
|
||||
err = true;
|
||||
goto drop;
|
||||
@@ -2807,7 +2846,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
}
|
||||
goto out;
|
||||
case AMT_MSG_MULTICAST_DATA:
|
||||
if (iph->saddr != amt->remote_ip) {
|
||||
if (saddr != amt->remote_ip) {
|
||||
netdev_dbg(amt->dev, "Invalid Relay IP\n");
|
||||
err = true;
|
||||
goto drop;
|
||||
@@ -2818,7 +2857,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
else
|
||||
goto out;
|
||||
case AMT_MSG_MEMBERSHIP_QUERY:
|
||||
if (iph->saddr != amt->remote_ip) {
|
||||
if (saddr != amt->remote_ip) {
|
||||
netdev_dbg(amt->dev, "Invalid Relay IP\n");
|
||||
err = true;
|
||||
goto drop;
|
||||
@@ -2995,9 +3034,15 @@ static int amt_dev_open(struct net_device *dev)
|
||||
amt->event_idx = 0;
|
||||
amt->nr_events = 0;
|
||||
|
||||
enable_delayed_work(&amt->discovery_wq);
|
||||
enable_delayed_work(&amt->req_wq);
|
||||
|
||||
err = amt_socket_create(amt);
|
||||
if (err)
|
||||
if (err) {
|
||||
disable_delayed_work(&amt->req_wq);
|
||||
disable_delayed_work(&amt->discovery_wq);
|
||||
return err;
|
||||
}
|
||||
|
||||
amt->req_cnt = 0;
|
||||
amt->remote_ip = 0;
|
||||
@@ -3023,8 +3068,8 @@ static int amt_dev_stop(struct net_device *dev)
|
||||
struct sock *sk;
|
||||
int i;
|
||||
|
||||
cancel_delayed_work_sync(&amt->req_wq);
|
||||
cancel_delayed_work_sync(&amt->discovery_wq);
|
||||
disable_delayed_work_sync(&amt->req_wq);
|
||||
disable_delayed_work_sync(&amt->discovery_wq);
|
||||
cancel_delayed_work_sync(&amt->secret_wq);
|
||||
|
||||
/* shutdown */
|
||||
@@ -3278,6 +3323,8 @@ static int amt_newlink(struct net_device *dev,
|
||||
INIT_DELAYED_WORK(&amt->req_wq, amt_req_work);
|
||||
INIT_DELAYED_WORK(&amt->secret_wq, amt_secret_work);
|
||||
INIT_WORK(&amt->event_wq, amt_event_work);
|
||||
disable_delayed_work(&amt->req_wq);
|
||||
disable_delayed_work(&amt->discovery_wq);
|
||||
INIT_LIST_HEAD(&amt->tunnel_list);
|
||||
return 0;
|
||||
err:
|
||||
|
||||
@@ -3455,7 +3455,8 @@ static void bond_send_validate(struct bonding *bond, struct slave *slave)
|
||||
{
|
||||
bond_arp_send_all(bond, slave);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
bond_ns_send_all(bond, slave);
|
||||
if (likely(ipv6_mod_enabled()))
|
||||
bond_ns_send_all(bond, slave);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user