* [PATCH AUTOSEL 4.19 102/252] Revert "tty/serial: atmel: fix out of range clock divider handling"
From: Sasha Levin @ 2020-02-14 16:09 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Greg Kroah-Hartman, Stephen Rothwell, David Engraf, Sasha Levin,
linux-serial, linux-arm-kernel
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[ Upstream commit 6dbd54e4154dfe386b3333687de15be239576617 ]
This reverts commit 751d0017334db9c4d68a8909c59f662a6ecbcec6.
The wrong commit got added to the tty-next tree, the correct one is in
the tty-linus branch.
Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
Cc: David Engraf <david.engraf@sysgo.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/tty/serial/atmel_serial.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index f34520e9ad6e5..19b926b44cc1e 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -2154,6 +2154,9 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
mode |= ATMEL_US_USMODE_NORMAL;
}
+ /* set the mode, clock divisor, parity, stop bits and data size */
+ atmel_uart_writel(port, ATMEL_US_MR, mode);
+
/*
* Set the baud rate:
* Fractional baudrate allows to setup output frequency more
--
2.20.1
^ permalink raw reply related
* [PATCH AUTOSEL 4.19 073/252] drm/radeon: remove set but not used variable 'blocks'
From: Sasha Levin @ 2020-02-14 16:08 UTC (permalink / raw)
To: linux-kernel, stable
Cc: zhengbin, Hulk Robot, Alex Deucher, Sasha Levin, amd-gfx,
dri-devel
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: zhengbin <zhengbin13@huawei.com>
[ Upstream commit 77441f77949807fda4a0aec0bdf3e86ae863fd56 ]
Fixes gcc '-Wunused-but-set-variable' warning:
drivers/gpu/drm/radeon/radeon_combios.c: In function radeon_combios_get_power_modes:
drivers/gpu/drm/radeon/radeon_combios.c:2638:10: warning: variable blocks set but not used [-Wunused-but-set-variable]
It is introduced by commit 56278a8edace ("drm/radeon/kms:
pull power mode info from bios tables (v3)"), but never used,
so remove it.
Reported-by: Hulk Robot <hulkci@huawei.com>
Signed-off-by: zhengbin <zhengbin13@huawei.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/radeon/radeon_combios.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index 60a61d33f6076..88afdc6bb93bd 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -2635,7 +2635,7 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev)
{
struct drm_device *dev = rdev->ddev;
u16 offset, misc, misc2 = 0;
- u8 rev, blocks, tmp;
+ u8 rev, tmp;
int state_index = 0;
struct radeon_i2c_bus_rec i2c_bus;
@@ -2728,7 +2728,6 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev)
offset = combios_get_table_offset(dev, COMBIOS_POWERPLAY_INFO_TABLE);
if (offset) {
rev = RBIOS8(offset);
- blocks = RBIOS8(offset + 0x2);
/* power mode 0 tends to be the only valid one */
rdev->pm.power_state[state_index].num_clock_modes = 1;
rdev->pm.power_state[state_index].clock_info[0].mclk = RBIOS32(offset + 0x5 + 0x2);
--
2.20.1
^ permalink raw reply related
* [PATCH AUTOSEL 4.19 103/252] b43legacy: Fix -Wcast-function-type
From: Sasha Levin @ 2020-02-14 16:09 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Phong Tran, Larry Finger, Kees Cook, Kalle Valo, Sasha Levin,
linux-wireless, b43-dev, netdev
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: Phong Tran <tranmanphong@gmail.com>
[ Upstream commit 475eec112e4267232d10f4afe2f939a241692b6c ]
correct usage prototype of callback in tasklet_init().
Report by https://github.com/KSPP/linux/issues/20
Tested-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: Phong Tran <tranmanphong@gmail.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/broadcom/b43legacy/main.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/broadcom/b43legacy/main.c b/drivers/net/wireless/broadcom/b43legacy/main.c
index 55f411925960e..770cc218ca4bd 100644
--- a/drivers/net/wireless/broadcom/b43legacy/main.c
+++ b/drivers/net/wireless/broadcom/b43legacy/main.c
@@ -1304,8 +1304,9 @@ static void handle_irq_ucode_debug(struct b43legacy_wldev *dev)
}
/* Interrupt handler bottom-half */
-static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev)
+static void b43legacy_interrupt_tasklet(unsigned long data)
{
+ struct b43legacy_wldev *dev = (struct b43legacy_wldev *)data;
u32 reason;
u32 dma_reason[ARRAY_SIZE(dev->dma_reason)];
u32 merged_dma_reason = 0;
@@ -3775,7 +3776,7 @@ static int b43legacy_one_core_attach(struct ssb_device *dev,
b43legacy_set_status(wldev, B43legacy_STAT_UNINIT);
wldev->bad_frames_preempt = modparam_bad_frames_preempt;
tasklet_init(&wldev->isr_tasklet,
- (void (*)(unsigned long))b43legacy_interrupt_tasklet,
+ b43legacy_interrupt_tasklet,
(unsigned long)wldev);
if (modparam_pio)
wldev->__using_pio = true;
--
2.20.1
^ permalink raw reply related
* Re: [PATCH 09/11] drm, cgroup: Introduce lgpu as DRM cgroup resource
From: Kenny Ho @ 2020-02-14 17:08 UTC (permalink / raw)
To: Jason Ekstrand
Cc: juan.zuniga-anaya, Kenny Ho, Kuehling, Felix, jsparks,
amd-gfx mailing list, lkaplan, Alex Deucher, nirmoy.das,
Maling list - DRI developers, Greathouse, Joseph, Tejun Heo,
cgroups, Christian König, damon.mcdougall
In-Reply-To: <CAOFGe96N5gG+08rQCRC+diHKDAfxPFYEnVxDS8_udvjcBYgsPg@mail.gmail.com>
Hi Jason,
Thanks for the review.
On Fri, Feb 14, 2020 at 11:44 AM Jason Ekstrand <jason@jlekstrand.net> wrote:
>
> Pardon my ignorance but I'm a bit confused by this. What is a "logical GPU"? What are we subdividing? Are we carving up memory? Compute power? Both?
The intention is compute but it is up to the individual drm driver to decide.
> If it's carving up compute power, what's actually being carved up? Time? Execution units/waves/threads? Even if that's the case, what advantage does it give to have it in terms of a fixed set of lgpus where each cgroup gets to pick a fixed set. Does affinity matter that much? Why not just say how many waves the GPU supports and that they have to be allocated in chunks of 16 waves (pulling a number out of thin air) and let the cgroup specify how many waves it wants.
>
> Don't get me wrong here. I'm all for the notion of being able to use cgroups to carve up GPU compute resources. However, this sounds to me like the most AMD-specific solution possible. We (Intel) could probably do some sort of carving up as well but we'd likely want to do it with preemption and time-slicing rather than handing out specific EUs.
This has been discussed in the RFC before
(https://www.spinics.net/lists/cgroups/msg23469.html.) As mentioned
before, the idea of a compute unit is hardly an AMD specific thing as
it is in the OpenCL standard and part of the architecture of many
different vendors. In addition, the interface presented here supports
Intel's use case. What you described is what I considered as the
"anonymous resources" view of the lgpu. What you/Intel can do, is to
register your device to drmcg to have 100 lgpu and users can specify
simply by count. So if they want to allocate 5% for a cgroup, they
would set count=5. Per the documentation in this patch: "Some DRM
devices may only support lgpu as anonymous resources. In such case,
the significance of the position of the set bits in list will be
ignored." What Intel does with the user expressed configuration of "5
out of 100" is entirely up to Intel (time slice if you like, change to
specific EUs later if you like, or make it driver configurable to
support both if you like.)
Regards,
Kenny
>
> On Fri, Feb 14, 2020 at 9:57 AM Kenny Ho <Kenny.Ho@amd.com> wrote:
>>
>> drm.lgpu
>> A read-write nested-keyed file which exists on all cgroups.
>> Each entry is keyed by the DRM device's major:minor.
>>
>> lgpu stands for logical GPU, it is an abstraction used to
>> subdivide a physical DRM device for the purpose of resource
>> management. This file stores user configuration while the
>> drm.lgpu.effective reflects the actual allocation after
>> considering the relationship between the cgroups and their
>> configurations.
>>
>> The lgpu is a discrete quantity that is device specific (i.e.
>> some DRM devices may have 64 lgpus while others may have 100
>> lgpus.) The lgpu is a single quantity that can be allocated
>> in three different ways denoted by the following nested keys.
>>
>> ===== ==============================================
>> weight Allocate by proportion in relationship with
>> active sibling cgroups
>> count Allocate by amount statically, treat lgpu as
>> anonymous resources
>> list Allocate statically, treat lgpu as named
>> resource
>> ===== ==============================================
>>
>> For example:
>> 226:0 weight=100 count=256 list=0-255
>> 226:1 weight=100 count=4 list=0,2,4,6
>> 226:2 weight=100 count=32 list=32-63
>> 226:3 weight=100 count=0 list=
>> 226:4 weight=500 count=0 list=
>>
>> lgpu is represented by a bitmap and uses the bitmap_parselist
>> kernel function so the list key input format is a
>> comma-separated list of decimal numbers and ranges.
>>
>> Consecutively set bits are shown as two hyphen-separated decimal
>> numbers, the smallest and largest bit numbers set in the range.
>> Optionally each range can be postfixed to denote that only parts
>> of it should be set. The range will divided to groups of
>> specific size.
>> Syntax: range:used_size/group_size
>> Example: 0-1023:2/256 ==> 0,1,256,257,512,513,768,769
>>
>> The count key is the hamming weight / hweight of the bitmap.
>>
>> Weight, count and list accept the max and default keywords.
>>
>> Some DRM devices may only support lgpu as anonymous resources.
>> In such case, the significance of the position of the set bits
>> in list will be ignored.
>>
>> The weight quantity is only in effect when static allocation
>> is not used (by setting count=0) for this cgroup. The weight
>> quantity distributes lgpus that are not statically allocated by
>> the siblings. For example, given siblings cgroupA, cgroupB and
>> cgroupC for a DRM device that has 64 lgpus, if cgroupA occupies
>> 0-63, no lgpu is available to be distributed by weight.
>> Similarly, if cgroupA has list=0-31 and cgroupB has list=16-63,
>> cgroupC will be starved if it tries to allocate by weight.
>>
>> On the other hand, if cgroupA has weight=100 count=0, cgroupB
>> has list=16-47, and cgroupC has weight=100 count=0, then 32
>> lgpus are available to be distributed evenly between cgroupA
>> and cgroupC. In drm.lgpu.effective, cgroupA will have
>> list=0-15 and cgroupC will have list=48-63.
>>
>> This lgpu resource supports the 'allocation' and 'weight'
>> resource distribution model.
>>
>> drm.lgpu.effective
>> A read-only nested-keyed file which exists on all cgroups.
>> Each entry is keyed by the DRM device's major:minor.
>>
>> lgpu stands for logical GPU, it is an abstraction used to
>> subdivide a physical DRM device for the purpose of resource
>> management. This file reflects the actual allocation after
>> considering the relationship between the cgroups and their
>> configurations in drm.lgpu.
>>
>> Change-Id: Idde0ef9a331fd67bb9c7eb8ef9978439e6452488
>> Signed-off-by: Kenny Ho <Kenny.Ho@amd.com>
>> ---
>> Documentation/admin-guide/cgroup-v2.rst | 80 ++++++
>> include/drm/drm_cgroup.h | 3 +
>> include/linux/cgroup_drm.h | 22 ++
>> kernel/cgroup/drm.c | 324 +++++++++++++++++++++++-
>> 4 files changed, 427 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
>> index ce5dc027366a..d8a41956e5c7 100644
>> --- a/Documentation/admin-guide/cgroup-v2.rst
>> +++ b/Documentation/admin-guide/cgroup-v2.rst
>> @@ -2120,6 +2120,86 @@ DRM Interface Files
>> Set largest allocation for /dev/dri/card1 to 4MB
>> echo "226:1 4m" > drm.buffer.peak.max
>>
>> + drm.lgpu
>> + A read-write nested-keyed file which exists on all cgroups.
>> + Each entry is keyed by the DRM device's major:minor.
>> +
>> + lgpu stands for logical GPU, it is an abstraction used to
>> + subdivide a physical DRM device for the purpose of resource
>> + management. This file stores user configuration while the
>> + drm.lgpu.effective reflects the actual allocation after
>> + considering the relationship between the cgroups and their
>> + configurations.
>> +
>> + The lgpu is a discrete quantity that is device specific (i.e.
>> + some DRM devices may have 64 lgpus while others may have 100
>> + lgpus.) The lgpu is a single quantity that can be allocated
>> + in three different ways denoted by the following nested keys.
>> +
>> + ===== ==============================================
>> + weight Allocate by proportion in relationship with
>> + active sibling cgroups
>> + count Allocate by amount statically, treat lgpu as
>> + anonymous resources
>> + list Allocate statically, treat lgpu as named
>> + resource
>> + ===== ==============================================
>> +
>> + For example:
>> + 226:0 weight=100 count=256 list=0-255
>> + 226:1 weight=100 count=4 list=0,2,4,6
>> + 226:2 weight=100 count=32 list=32-63
>> + 226:3 weight=100 count=0 list=
>> + 226:4 weight=500 count=0 list=
>> +
>> + lgpu is represented by a bitmap and uses the bitmap_parselist
>> + kernel function so the list key input format is a
>> + comma-separated list of decimal numbers and ranges.
>> +
>> + Consecutively set bits are shown as two hyphen-separated decimal
>> + numbers, the smallest and largest bit numbers set in the range.
>> + Optionally each range can be postfixed to denote that only parts
>> + of it should be set. The range will divided to groups of
>> + specific size.
>> + Syntax: range:used_size/group_size
>> + Example: 0-1023:2/256 ==> 0,1,256,257,512,513,768,769
>> +
>> + The count key is the hamming weight / hweight of the bitmap.
>> +
>> + Weight, count and list accept the max and default keywords.
>> +
>> + Some DRM devices may only support lgpu as anonymous resources.
>> + In such case, the significance of the position of the set bits
>> + in list will be ignored.
>> +
>> + The weight quantity is only in effect when static allocation
>> + is not used (by setting count=0) for this cgroup. The weight
>> + quantity distributes lgpus that are not statically allocated by
>> + the siblings. For example, given siblings cgroupA, cgroupB and
>> + cgroupC for a DRM device that has 64 lgpus, if cgroupA occupies
>> + 0-63, no lgpu is available to be distributed by weight.
>> + Similarly, if cgroupA has list=0-31 and cgroupB has list=16-63,
>> + cgroupC will be starved if it tries to allocate by weight.
>> +
>> + On the other hand, if cgroupA has weight=100 count=0, cgroupB
>> + has list=16-47, and cgroupC has weight=100 count=0, then 32
>> + lgpus are available to be distributed evenly between cgroupA
>> + and cgroupC. In drm.lgpu.effective, cgroupA will have
>> + list=0-15 and cgroupC will have list=48-63.
>> +
>> + This lgpu resource supports the 'allocation' and 'weight'
>> + resource distribution model.
>> +
>> + drm.lgpu.effective
>> + A read-only nested-keyed file which exists on all cgroups.
>> + Each entry is keyed by the DRM device's major:minor.
>> +
>> + lgpu stands for logical GPU, it is an abstraction used to
>> + subdivide a physical DRM device for the purpose of resource
>> + management. This file reflects the actual allocation after
>> + considering the relationship between the cgroups and their
>> + configurations in drm.lgpu.
>> +
>> GEM Buffer Ownership
>> ~~~~~~~~~~~~~~~~~~~~
>>
>> diff --git a/include/drm/drm_cgroup.h b/include/drm/drm_cgroup.h
>> index 2b41d4d22e33..619a110cc748 100644
>> --- a/include/drm/drm_cgroup.h
>> +++ b/include/drm/drm_cgroup.h
>> @@ -17,6 +17,9 @@ struct drmcg_props {
>>
>> s64 bo_limits_total_allocated_default;
>> s64 bo_limits_peak_allocated_default;
>> +
>> + int lgpu_capacity;
>> + DECLARE_BITMAP(lgpu_slots, MAX_DRMCG_LGPU_CAPACITY);
>> };
>>
>> void drmcg_bind(struct drm_minor (*(*acq_dm)(unsigned int minor_id)),
>> diff --git a/include/linux/cgroup_drm.h b/include/linux/cgroup_drm.h
>> index eae400f3d9b4..bb09704e7f71 100644
>> --- a/include/linux/cgroup_drm.h
>> +++ b/include/linux/cgroup_drm.h
>> @@ -11,10 +11,14 @@
>> /* limit defined per the way drm_minor_alloc operates */
>> #define MAX_DRM_DEV (64 * DRM_MINOR_RENDER)
>>
>> +#define MAX_DRMCG_LGPU_CAPACITY 256
>> +
>> enum drmcg_res_type {
>> DRMCG_TYPE_BO_TOTAL,
>> DRMCG_TYPE_BO_PEAK,
>> DRMCG_TYPE_BO_COUNT,
>> + DRMCG_TYPE_LGPU,
>> + DRMCG_TYPE_LGPU_EFF,
>> __DRMCG_TYPE_LAST,
>> };
>>
>> @@ -32,6 +36,24 @@ struct drmcg_device_resource {
>> s64 bo_limits_peak_allocated;
>>
>> s64 bo_stats_count_allocated;
>> +
>> + /**
>> + * Logical GPU
>> + *
>> + * *_cfg are properties configured by users
>> + * *_eff are the effective properties being applied to the hardware
>> + * *_stg is used to calculate _eff before applying to _eff
>> + * after considering the entire hierarchy
>> + */
>> + DECLARE_BITMAP(lgpu_stg, MAX_DRMCG_LGPU_CAPACITY);
>> + /* user configurations */
>> + s64 lgpu_weight_cfg;
>> + DECLARE_BITMAP(lgpu_cfg, MAX_DRMCG_LGPU_CAPACITY);
>> + /* effective lgpu for the cgroup after considering
>> + * relationship with other cgroup
>> + */
>> + s64 lgpu_count_eff;
>> + DECLARE_BITMAP(lgpu_eff, MAX_DRMCG_LGPU_CAPACITY);
>> };
>>
>> /**
>> diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c
>> index 5fcbbc13fa1c..a4e88a3704bb 100644
>> --- a/kernel/cgroup/drm.c
>> +++ b/kernel/cgroup/drm.c
>> @@ -9,6 +9,7 @@
>> #include <linux/seq_file.h>
>> #include <linux/mutex.h>
>> #include <linux/kernel.h>
>> +#include <linux/bitmap.h>
>> #include <linux/cgroup_drm.h>
>> #include <drm/drm_file.h>
>> #include <drm/drm_drv.h>
>> @@ -41,6 +42,10 @@ enum drmcg_file_type {
>> DRMCG_FTYPE_DEFAULT,
>> };
>>
>> +#define LGPU_LIMITS_NAME_LIST "list"
>> +#define LGPU_LIMITS_NAME_COUNT "count"
>> +#define LGPU_LIMITS_NAME_WEIGHT "weight"
>> +
>> /**
>> * drmcg_bind - Bind DRM subsystem to cgroup subsystem
>> * @acq_dm: function pointer to the drm_minor_acquire function
>> @@ -98,6 +103,13 @@ static inline int init_drmcg_single(struct drmcg *drmcg, struct drm_device *dev)
>> ddr->bo_limits_peak_allocated =
>> dev->drmcg_props.bo_limits_peak_allocated_default;
>>
>> + bitmap_copy(ddr->lgpu_cfg, dev->drmcg_props.lgpu_slots,
>> + MAX_DRMCG_LGPU_CAPACITY);
>> + bitmap_copy(ddr->lgpu_stg, dev->drmcg_props.lgpu_slots,
>> + MAX_DRMCG_LGPU_CAPACITY);
>> +
>> + ddr->lgpu_weight_cfg = CGROUP_WEIGHT_DFL;
>> +
>> return 0;
>> }
>>
>> @@ -121,6 +133,120 @@ static inline void drmcg_update_cg_tree(struct drm_device *dev)
>> mutex_unlock(&cgroup_mutex);
>> }
>>
>> +static void drmcg_calculate_effective_lgpu(struct drm_device *dev,
>> + const unsigned long *free_static,
>> + const unsigned long *free_weighted,
>> + struct drmcg *parent_drmcg)
>> +{
>> + int capacity = dev->drmcg_props.lgpu_capacity;
>> + DECLARE_BITMAP(lgpu_unused, MAX_DRMCG_LGPU_CAPACITY);
>> + DECLARE_BITMAP(lgpu_by_weight, MAX_DRMCG_LGPU_CAPACITY);
>> + struct drmcg_device_resource *parent_ddr;
>> + struct drmcg_device_resource *ddr;
>> + int minor = dev->primary->index;
>> + struct cgroup_subsys_state *pos;
>> + struct drmcg *child;
>> + s64 weight_sum = 0;
>> + s64 unused;
>> +
>> + parent_ddr = parent_drmcg->dev_resources[minor];
>> +
>> + if (bitmap_empty(parent_ddr->lgpu_cfg, capacity))
>> + /* no static cfg, use weight for calculating the effective */
>> + bitmap_copy(parent_ddr->lgpu_stg, free_weighted, capacity);
>> + else
>> + /* lgpu statically configured, use the overlap as effective */
>> + bitmap_and(parent_ddr->lgpu_stg, free_static,
>> + parent_ddr->lgpu_cfg, capacity);
>> +
>> + /* calculate lgpu available for distribution by weight for children */
>> + bitmap_copy(lgpu_unused, parent_ddr->lgpu_stg, capacity);
>> + css_for_each_child(pos, &parent_drmcg->css) {
>> + child = css_to_drmcg(pos);
>> + ddr = child->dev_resources[minor];
>> +
>> + if (bitmap_empty(ddr->lgpu_cfg, capacity))
>> + /* no static allocation, participate in weight dist */
>> + weight_sum += ddr->lgpu_weight_cfg;
>> + else
>> + /* take out statically allocated lgpu by siblings */
>> + bitmap_andnot(lgpu_unused, lgpu_unused, ddr->lgpu_cfg,
>> + capacity);
>> + }
>> +
>> + unused = bitmap_weight(lgpu_unused, capacity);
>> +
>> + css_for_each_child(pos, &parent_drmcg->css) {
>> + child = css_to_drmcg(pos);
>> + ddr = child->dev_resources[minor];
>> +
>> + bitmap_zero(lgpu_by_weight, capacity);
>> + /* no static allocation, participate in weight distribution */
>> + if (bitmap_empty(ddr->lgpu_cfg, capacity)) {
>> + int c;
>> + int p = 0;
>> +
>> + for (c = ddr->lgpu_weight_cfg * unused / weight_sum;
>> + c > 0; c--) {
>> + p = find_next_bit(lgpu_unused, capacity, p);
>> + if (p < capacity) {
>> + clear_bit(p, lgpu_unused);
>> + set_bit(p, lgpu_by_weight);
>> + }
>> + }
>> +
>> + }
>> +
>> + drmcg_calculate_effective_lgpu(dev, parent_ddr->lgpu_stg,
>> + lgpu_by_weight, child);
>> + }
>> +}
>> +
>> +static void drmcg_apply_effective_lgpu(struct drm_device *dev)
>> +{
>> + int capacity = dev->drmcg_props.lgpu_capacity;
>> + int minor = dev->primary->index;
>> + struct drmcg_device_resource *ddr;
>> + struct cgroup_subsys_state *pos;
>> + struct drmcg *drmcg;
>> +
>> + if (root_drmcg == NULL) {
>> + WARN_ON(root_drmcg == NULL);
>> + return;
>> + }
>> +
>> + rcu_read_lock();
>> +
>> + /* process the entire cgroup tree from root to simplify the algorithm */
>> + drmcg_calculate_effective_lgpu(dev, dev->drmcg_props.lgpu_slots,
>> + dev->drmcg_props.lgpu_slots, root_drmcg);
>> +
>> + /* apply changes to effective only if there is a change */
>> + css_for_each_descendant_pre(pos, &root_drmcg->css) {
>> + drmcg = css_to_drmcg(pos);
>> + ddr = drmcg->dev_resources[minor];
>> +
>> + if (!bitmap_equal(ddr->lgpu_stg, ddr->lgpu_eff, capacity)) {
>> + bitmap_copy(ddr->lgpu_eff, ddr->lgpu_stg, capacity);
>> + ddr->lgpu_count_eff =
>> + bitmap_weight(ddr->lgpu_eff, capacity);
>> + }
>> + }
>> + rcu_read_unlock();
>> +}
>> +
>> +static void drmcg_apply_effective(enum drmcg_res_type type,
>> + struct drm_device *dev, struct drmcg *changed_drmcg)
>> +{
>> + switch (type) {
>> + case DRMCG_TYPE_LGPU:
>> + drmcg_apply_effective_lgpu(dev);
>> + break;
>> + default:
>> + break;
>> + }
>> +}
>> +
>> /**
>> * drmcg_register_dev - register a DRM device for usage in drm cgroup
>> * @dev: DRM device
>> @@ -143,7 +269,13 @@ void drmcg_register_dev(struct drm_device *dev)
>> {
>> dev->driver->drmcg_custom_init(dev, &dev->drmcg_props);
>>
>> + WARN_ON(dev->drmcg_props.lgpu_capacity !=
>> + bitmap_weight(dev->drmcg_props.lgpu_slots,
>> + MAX_DRMCG_LGPU_CAPACITY));
>> +
>> drmcg_update_cg_tree(dev);
>> +
>> + drmcg_apply_effective(DRMCG_TYPE_LGPU, dev, root_drmcg);
>> }
>> mutex_unlock(&drmcg_mutex);
>> }
>> @@ -297,7 +429,8 @@ static void drmcg_print_stats(struct drmcg_device_resource *ddr,
>> }
>>
>> static void drmcg_print_limits(struct drmcg_device_resource *ddr,
>> - struct seq_file *sf, enum drmcg_res_type type)
>> + struct seq_file *sf, enum drmcg_res_type type,
>> + struct drm_device *dev)
>> {
>> if (ddr == NULL) {
>> seq_puts(sf, "\n");
>> @@ -311,6 +444,25 @@ static void drmcg_print_limits(struct drmcg_device_resource *ddr,
>> case DRMCG_TYPE_BO_PEAK:
>> seq_printf(sf, "%lld\n", ddr->bo_limits_peak_allocated);
>> break;
>> + case DRMCG_TYPE_LGPU:
>> + seq_printf(sf, "%s=%lld %s=%d %s=%*pbl\n",
>> + LGPU_LIMITS_NAME_WEIGHT,
>> + ddr->lgpu_weight_cfg,
>> + LGPU_LIMITS_NAME_COUNT,
>> + bitmap_weight(ddr->lgpu_cfg,
>> + dev->drmcg_props.lgpu_capacity),
>> + LGPU_LIMITS_NAME_LIST,
>> + dev->drmcg_props.lgpu_capacity,
>> + ddr->lgpu_cfg);
>> + break;
>> + case DRMCG_TYPE_LGPU_EFF:
>> + seq_printf(sf, "%s=%lld %s=%*pbl\n",
>> + LGPU_LIMITS_NAME_COUNT,
>> + ddr->lgpu_count_eff,
>> + LGPU_LIMITS_NAME_LIST,
>> + dev->drmcg_props.lgpu_capacity,
>> + ddr->lgpu_eff);
>> + break;
>> default:
>> seq_puts(sf, "\n");
>> break;
>> @@ -329,6 +481,17 @@ static void drmcg_print_default(struct drmcg_props *props,
>> seq_printf(sf, "%lld\n",
>> props->bo_limits_peak_allocated_default);
>> break;
>> + case DRMCG_TYPE_LGPU:
>> + seq_printf(sf, "%s=%d %s=%d %s=%*pbl\n",
>> + LGPU_LIMITS_NAME_WEIGHT,
>> + CGROUP_WEIGHT_DFL,
>> + LGPU_LIMITS_NAME_COUNT,
>> + bitmap_weight(props->lgpu_slots,
>> + props->lgpu_capacity),
>> + LGPU_LIMITS_NAME_LIST,
>> + props->lgpu_capacity,
>> + props->lgpu_slots);
>> + break;
>> default:
>> seq_puts(sf, "\n");
>> break;
>> @@ -358,7 +521,7 @@ static int drmcg_seq_show_fn(int id, void *ptr, void *data)
>> drmcg_print_stats(ddr, sf, type);
>> break;
>> case DRMCG_FTYPE_LIMIT:
>> - drmcg_print_limits(ddr, sf, type);
>> + drmcg_print_limits(ddr, sf, type, minor->dev);
>> break;
>> case DRMCG_FTYPE_DEFAULT:
>> drmcg_print_default(&minor->dev->drmcg_props, sf, type);
>> @@ -415,6 +578,115 @@ static int drmcg_process_limit_s64_val(char *sval, bool is_mem,
>> return rc;
>> }
>>
>> +static void drmcg_nested_limit_parse(struct kernfs_open_file *of,
>> + struct drm_device *dev, char *attrs)
>> +{
>> + DECLARE_BITMAP(tmp_bitmap, MAX_DRMCG_LGPU_CAPACITY);
>> + DECLARE_BITMAP(chk_bitmap, MAX_DRMCG_LGPU_CAPACITY);
>> + enum drmcg_res_type type =
>> + DRMCG_CTF_PRIV2RESTYPE(of_cft(of)->private);
>> + struct drmcg *drmcg = css_to_drmcg(of_css(of));
>> + struct drmcg_props *props = &dev->drmcg_props;
>> + char *cft_name = of_cft(of)->name;
>> + int minor = dev->primary->index;
>> + char *nested = strstrip(attrs);
>> + struct drmcg_device_resource *ddr =
>> + drmcg->dev_resources[minor];
>> + char *attr;
>> + char sname[256];
>> + char sval[256];
>> + s64 val;
>> + int rc;
>> +
>> + while (nested != NULL) {
>> + attr = strsep(&nested, " ");
>> +
>> + if (sscanf(attr, "%255[^=]=%255[^=]", sname, sval) != 2)
>> + continue;
>> +
>> + switch (type) {
>> + case DRMCG_TYPE_LGPU:
>> + if (strncmp(sname, LGPU_LIMITS_NAME_LIST, 256) &&
>> + strncmp(sname, LGPU_LIMITS_NAME_COUNT, 256) &&
>> + strncmp(sname, LGPU_LIMITS_NAME_WEIGHT, 256))
>> + continue;
>> +
>> + if (strncmp(sname, LGPU_LIMITS_NAME_WEIGHT, 256) &&
>> + (!strcmp("max", sval) ||
>> + !strcmp("default", sval))) {
>> + bitmap_copy(ddr->lgpu_cfg, props->lgpu_slots,
>> + props->lgpu_capacity);
>> +
>> + continue;
>> + }
>> +
>> + if (strncmp(sname, LGPU_LIMITS_NAME_WEIGHT, 256) == 0) {
>> + rc = drmcg_process_limit_s64_val(sval,
>> + false, CGROUP_WEIGHT_DFL,
>> + CGROUP_WEIGHT_MAX, &val);
>> +
>> + if (rc || val < CGROUP_WEIGHT_MIN ||
>> + val > CGROUP_WEIGHT_MAX) {
>> + drmcg_pr_cft_err(drmcg, rc, cft_name,
>> + minor);
>> + continue;
>> + }
>> +
>> + ddr->lgpu_weight_cfg = val;
>> + continue;
>> + }
>> +
>> + if (strncmp(sname, LGPU_LIMITS_NAME_COUNT, 256) == 0) {
>> + rc = drmcg_process_limit_s64_val(sval,
>> + false, props->lgpu_capacity,
>> + props->lgpu_capacity, &val);
>> +
>> + if (rc || val < 0) {
>> + drmcg_pr_cft_err(drmcg, rc, cft_name,
>> + minor);
>> + continue;
>> + }
>> +
>> + bitmap_zero(tmp_bitmap,
>> + MAX_DRMCG_LGPU_CAPACITY);
>> + bitmap_set(tmp_bitmap, 0, val);
>> + }
>> +
>> + if (strncmp(sname, LGPU_LIMITS_NAME_LIST, 256) == 0) {
>> + rc = bitmap_parselist(sval, tmp_bitmap,
>> + MAX_DRMCG_LGPU_CAPACITY);
>> +
>> + if (rc) {
>> + drmcg_pr_cft_err(drmcg, rc, cft_name,
>> + minor);
>> + continue;
>> + }
>> +
>> + bitmap_andnot(chk_bitmap, tmp_bitmap,
>> + props->lgpu_slots,
>> + MAX_DRMCG_LGPU_CAPACITY);
>> +
>> + /* user setting does not intersect with
>> + * available lgpu */
>> + if (!bitmap_empty(chk_bitmap,
>> + MAX_DRMCG_LGPU_CAPACITY)) {
>> + drmcg_pr_cft_err(drmcg, 0, cft_name,
>> + minor);
>> + continue;
>> + }
>> + }
>> +
>> + bitmap_copy(ddr->lgpu_cfg, tmp_bitmap,
>> + props->lgpu_capacity);
>> +
>> + break; /* DRMCG_TYPE_LGPU */
>> + default:
>> + break;
>> + } /* switch (type) */
>> + }
>> +}
>> +
>> +
>> /**
>> * drmcg_limit_write - parse cgroup interface files to obtain user config
>> *
>> @@ -499,9 +771,15 @@ static ssize_t drmcg_limit_write(struct kernfs_open_file *of, char *buf,
>>
>> ddr->bo_limits_peak_allocated = val;
>> break;
>> + case DRMCG_TYPE_LGPU:
>> + drmcg_nested_limit_parse(of, dm->dev, sattr);
>> + break;
>> default:
>> break;
>> }
>> +
>> + drmcg_apply_effective(type, dm->dev, drmcg);
>> +
>> mutex_unlock(&dm->dev->drmcg_mutex);
>>
>> mutex_lock(&drmcg_mutex);
>> @@ -560,12 +838,51 @@ struct cftype files[] = {
>> .private = DRMCG_CTF_PRIV(DRMCG_TYPE_BO_COUNT,
>> DRMCG_FTYPE_STATS),
>> },
>> + {
>> + .name = "lgpu",
>> + .seq_show = drmcg_seq_show,
>> + .write = drmcg_limit_write,
>> + .private = DRMCG_CTF_PRIV(DRMCG_TYPE_LGPU,
>> + DRMCG_FTYPE_LIMIT),
>> + },
>> + {
>> + .name = "lgpu.default",
>> + .seq_show = drmcg_seq_show,
>> + .flags = CFTYPE_ONLY_ON_ROOT,
>> + .private = DRMCG_CTF_PRIV(DRMCG_TYPE_LGPU,
>> + DRMCG_FTYPE_DEFAULT),
>> + },
>> + {
>> + .name = "lgpu.effective",
>> + .seq_show = drmcg_seq_show,
>> + .private = DRMCG_CTF_PRIV(DRMCG_TYPE_LGPU_EFF,
>> + DRMCG_FTYPE_LIMIT),
>> + },
>> { } /* terminate */
>> };
>>
>> +static int drmcg_online_fn(int id, void *ptr, void *data)
>> +{
>> + struct drm_minor *minor = ptr;
>> + struct drmcg *drmcg = data;
>> +
>> + if (minor->type != DRM_MINOR_PRIMARY)
>> + return 0;
>> +
>> + drmcg_apply_effective(DRMCG_TYPE_LGPU, minor->dev, drmcg);
>> +
>> + return 0;
>> +}
>> +
>> +static int drmcg_css_online(struct cgroup_subsys_state *css)
>> +{
>> + return drm_minor_for_each(&drmcg_online_fn, css_to_drmcg(css));
>> +}
>> +
>> struct cgroup_subsys drm_cgrp_subsys = {
>> .css_alloc = drmcg_css_alloc,
>> .css_free = drmcg_css_free,
>> + .css_online = drmcg_css_online,
>> .early_init = false,
>> .legacy_cftypes = files,
>> .dfl_cftypes = files,
>> @@ -585,6 +902,9 @@ void drmcg_device_early_init(struct drm_device *dev)
>> dev->drmcg_props.bo_limits_total_allocated_default = S64_MAX;
>> dev->drmcg_props.bo_limits_peak_allocated_default = S64_MAX;
>>
>> + dev->drmcg_props.lgpu_capacity = MAX_DRMCG_LGPU_CAPACITY;
>> + bitmap_fill(dev->drmcg_props.lgpu_slots, MAX_DRMCG_LGPU_CAPACITY);
>> +
>> drmcg_update_cg_tree(dev);
>> }
>> EXPORT_SYMBOL(drmcg_device_early_init);
>> --
>> 2.25.0
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* Re: [PATCH 09/11] drm, cgroup: Introduce lgpu as DRM cgroup resource
From: Kenny Ho @ 2020-02-14 17:08 UTC (permalink / raw)
To: Jason Ekstrand
Cc: juan.zuniga-anaya, Daniel Vetter, Kenny Ho, Kuehling, Felix,
jsparks, amd-gfx mailing list, lkaplan, Alex Deucher, nirmoy.das,
Maling list - DRI developers, Greathouse, Joseph, Tejun Heo,
cgroups, Christian König, damon.mcdougall
In-Reply-To: <CAOFGe96N5gG+08rQCRC+diHKDAfxPFYEnVxDS8_udvjcBYgsPg@mail.gmail.com>
Hi Jason,
Thanks for the review.
On Fri, Feb 14, 2020 at 11:44 AM Jason Ekstrand <jason@jlekstrand.net> wrote:
>
> Pardon my ignorance but I'm a bit confused by this. What is a "logical GPU"? What are we subdividing? Are we carving up memory? Compute power? Both?
The intention is compute but it is up to the individual drm driver to decide.
> If it's carving up compute power, what's actually being carved up? Time? Execution units/waves/threads? Even if that's the case, what advantage does it give to have it in terms of a fixed set of lgpus where each cgroup gets to pick a fixed set. Does affinity matter that much? Why not just say how many waves the GPU supports and that they have to be allocated in chunks of 16 waves (pulling a number out of thin air) and let the cgroup specify how many waves it wants.
>
> Don't get me wrong here. I'm all for the notion of being able to use cgroups to carve up GPU compute resources. However, this sounds to me like the most AMD-specific solution possible. We (Intel) could probably do some sort of carving up as well but we'd likely want to do it with preemption and time-slicing rather than handing out specific EUs.
This has been discussed in the RFC before
(https://www.spinics.net/lists/cgroups/msg23469.html.) As mentioned
before, the idea of a compute unit is hardly an AMD specific thing as
it is in the OpenCL standard and part of the architecture of many
different vendors. In addition, the interface presented here supports
Intel's use case. What you described is what I considered as the
"anonymous resources" view of the lgpu. What you/Intel can do, is to
register your device to drmcg to have 100 lgpu and users can specify
simply by count. So if they want to allocate 5% for a cgroup, they
would set count=5. Per the documentation in this patch: "Some DRM
devices may only support lgpu as anonymous resources. In such case,
the significance of the position of the set bits in list will be
ignored." What Intel does with the user expressed configuration of "5
out of 100" is entirely up to Intel (time slice if you like, change to
specific EUs later if you like, or make it driver configurable to
support both if you like.)
Regards,
Kenny
>
> On Fri, Feb 14, 2020 at 9:57 AM Kenny Ho <Kenny.Ho@amd.com> wrote:
>>
>> drm.lgpu
>> A read-write nested-keyed file which exists on all cgroups.
>> Each entry is keyed by the DRM device's major:minor.
>>
>> lgpu stands for logical GPU, it is an abstraction used to
>> subdivide a physical DRM device for the purpose of resource
>> management. This file stores user configuration while the
>> drm.lgpu.effective reflects the actual allocation after
>> considering the relationship between the cgroups and their
>> configurations.
>>
>> The lgpu is a discrete quantity that is device specific (i.e.
>> some DRM devices may have 64 lgpus while others may have 100
>> lgpus.) The lgpu is a single quantity that can be allocated
>> in three different ways denoted by the following nested keys.
>>
>> ===== ==============================================
>> weight Allocate by proportion in relationship with
>> active sibling cgroups
>> count Allocate by amount statically, treat lgpu as
>> anonymous resources
>> list Allocate statically, treat lgpu as named
>> resource
>> ===== ==============================================
>>
>> For example:
>> 226:0 weight=100 count=256 list=0-255
>> 226:1 weight=100 count=4 list=0,2,4,6
>> 226:2 weight=100 count=32 list=32-63
>> 226:3 weight=100 count=0 list=
>> 226:4 weight=500 count=0 list=
>>
>> lgpu is represented by a bitmap and uses the bitmap_parselist
>> kernel function so the list key input format is a
>> comma-separated list of decimal numbers and ranges.
>>
>> Consecutively set bits are shown as two hyphen-separated decimal
>> numbers, the smallest and largest bit numbers set in the range.
>> Optionally each range can be postfixed to denote that only parts
>> of it should be set. The range will divided to groups of
>> specific size.
>> Syntax: range:used_size/group_size
>> Example: 0-1023:2/256 ==> 0,1,256,257,512,513,768,769
>>
>> The count key is the hamming weight / hweight of the bitmap.
>>
>> Weight, count and list accept the max and default keywords.
>>
>> Some DRM devices may only support lgpu as anonymous resources.
>> In such case, the significance of the position of the set bits
>> in list will be ignored.
>>
>> The weight quantity is only in effect when static allocation
>> is not used (by setting count=0) for this cgroup. The weight
>> quantity distributes lgpus that are not statically allocated by
>> the siblings. For example, given siblings cgroupA, cgroupB and
>> cgroupC for a DRM device that has 64 lgpus, if cgroupA occupies
>> 0-63, no lgpu is available to be distributed by weight.
>> Similarly, if cgroupA has list=0-31 and cgroupB has list=16-63,
>> cgroupC will be starved if it tries to allocate by weight.
>>
>> On the other hand, if cgroupA has weight=100 count=0, cgroupB
>> has list=16-47, and cgroupC has weight=100 count=0, then 32
>> lgpus are available to be distributed evenly between cgroupA
>> and cgroupC. In drm.lgpu.effective, cgroupA will have
>> list=0-15 and cgroupC will have list=48-63.
>>
>> This lgpu resource supports the 'allocation' and 'weight'
>> resource distribution model.
>>
>> drm.lgpu.effective
>> A read-only nested-keyed file which exists on all cgroups.
>> Each entry is keyed by the DRM device's major:minor.
>>
>> lgpu stands for logical GPU, it is an abstraction used to
>> subdivide a physical DRM device for the purpose of resource
>> management. This file reflects the actual allocation after
>> considering the relationship between the cgroups and their
>> configurations in drm.lgpu.
>>
>> Change-Id: Idde0ef9a331fd67bb9c7eb8ef9978439e6452488
>> Signed-off-by: Kenny Ho <Kenny.Ho@amd.com>
>> ---
>> Documentation/admin-guide/cgroup-v2.rst | 80 ++++++
>> include/drm/drm_cgroup.h | 3 +
>> include/linux/cgroup_drm.h | 22 ++
>> kernel/cgroup/drm.c | 324 +++++++++++++++++++++++-
>> 4 files changed, 427 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
>> index ce5dc027366a..d8a41956e5c7 100644
>> --- a/Documentation/admin-guide/cgroup-v2.rst
>> +++ b/Documentation/admin-guide/cgroup-v2.rst
>> @@ -2120,6 +2120,86 @@ DRM Interface Files
>> Set largest allocation for /dev/dri/card1 to 4MB
>> echo "226:1 4m" > drm.buffer.peak.max
>>
>> + drm.lgpu
>> + A read-write nested-keyed file which exists on all cgroups.
>> + Each entry is keyed by the DRM device's major:minor.
>> +
>> + lgpu stands for logical GPU, it is an abstraction used to
>> + subdivide a physical DRM device for the purpose of resource
>> + management. This file stores user configuration while the
>> + drm.lgpu.effective reflects the actual allocation after
>> + considering the relationship between the cgroups and their
>> + configurations.
>> +
>> + The lgpu is a discrete quantity that is device specific (i.e.
>> + some DRM devices may have 64 lgpus while others may have 100
>> + lgpus.) The lgpu is a single quantity that can be allocated
>> + in three different ways denoted by the following nested keys.
>> +
>> + ===== ==============================================
>> + weight Allocate by proportion in relationship with
>> + active sibling cgroups
>> + count Allocate by amount statically, treat lgpu as
>> + anonymous resources
>> + list Allocate statically, treat lgpu as named
>> + resource
>> + ===== ==============================================
>> +
>> + For example:
>> + 226:0 weight=100 count=256 list=0-255
>> + 226:1 weight=100 count=4 list=0,2,4,6
>> + 226:2 weight=100 count=32 list=32-63
>> + 226:3 weight=100 count=0 list=
>> + 226:4 weight=500 count=0 list=
>> +
>> + lgpu is represented by a bitmap and uses the bitmap_parselist
>> + kernel function so the list key input format is a
>> + comma-separated list of decimal numbers and ranges.
>> +
>> + Consecutively set bits are shown as two hyphen-separated decimal
>> + numbers, the smallest and largest bit numbers set in the range.
>> + Optionally each range can be postfixed to denote that only parts
>> + of it should be set. The range will divided to groups of
>> + specific size.
>> + Syntax: range:used_size/group_size
>> + Example: 0-1023:2/256 ==> 0,1,256,257,512,513,768,769
>> +
>> + The count key is the hamming weight / hweight of the bitmap.
>> +
>> + Weight, count and list accept the max and default keywords.
>> +
>> + Some DRM devices may only support lgpu as anonymous resources.
>> + In such case, the significance of the position of the set bits
>> + in list will be ignored.
>> +
>> + The weight quantity is only in effect when static allocation
>> + is not used (by setting count=0) for this cgroup. The weight
>> + quantity distributes lgpus that are not statically allocated by
>> + the siblings. For example, given siblings cgroupA, cgroupB and
>> + cgroupC for a DRM device that has 64 lgpus, if cgroupA occupies
>> + 0-63, no lgpu is available to be distributed by weight.
>> + Similarly, if cgroupA has list=0-31 and cgroupB has list=16-63,
>> + cgroupC will be starved if it tries to allocate by weight.
>> +
>> + On the other hand, if cgroupA has weight=100 count=0, cgroupB
>> + has list=16-47, and cgroupC has weight=100 count=0, then 32
>> + lgpus are available to be distributed evenly between cgroupA
>> + and cgroupC. In drm.lgpu.effective, cgroupA will have
>> + list=0-15 and cgroupC will have list=48-63.
>> +
>> + This lgpu resource supports the 'allocation' and 'weight'
>> + resource distribution model.
>> +
>> + drm.lgpu.effective
>> + A read-only nested-keyed file which exists on all cgroups.
>> + Each entry is keyed by the DRM device's major:minor.
>> +
>> + lgpu stands for logical GPU, it is an abstraction used to
>> + subdivide a physical DRM device for the purpose of resource
>> + management. This file reflects the actual allocation after
>> + considering the relationship between the cgroups and their
>> + configurations in drm.lgpu.
>> +
>> GEM Buffer Ownership
>> ~~~~~~~~~~~~~~~~~~~~
>>
>> diff --git a/include/drm/drm_cgroup.h b/include/drm/drm_cgroup.h
>> index 2b41d4d22e33..619a110cc748 100644
>> --- a/include/drm/drm_cgroup.h
>> +++ b/include/drm/drm_cgroup.h
>> @@ -17,6 +17,9 @@ struct drmcg_props {
>>
>> s64 bo_limits_total_allocated_default;
>> s64 bo_limits_peak_allocated_default;
>> +
>> + int lgpu_capacity;
>> + DECLARE_BITMAP(lgpu_slots, MAX_DRMCG_LGPU_CAPACITY);
>> };
>>
>> void drmcg_bind(struct drm_minor (*(*acq_dm)(unsigned int minor_id)),
>> diff --git a/include/linux/cgroup_drm.h b/include/linux/cgroup_drm.h
>> index eae400f3d9b4..bb09704e7f71 100644
>> --- a/include/linux/cgroup_drm.h
>> +++ b/include/linux/cgroup_drm.h
>> @@ -11,10 +11,14 @@
>> /* limit defined per the way drm_minor_alloc operates */
>> #define MAX_DRM_DEV (64 * DRM_MINOR_RENDER)
>>
>> +#define MAX_DRMCG_LGPU_CAPACITY 256
>> +
>> enum drmcg_res_type {
>> DRMCG_TYPE_BO_TOTAL,
>> DRMCG_TYPE_BO_PEAK,
>> DRMCG_TYPE_BO_COUNT,
>> + DRMCG_TYPE_LGPU,
>> + DRMCG_TYPE_LGPU_EFF,
>> __DRMCG_TYPE_LAST,
>> };
>>
>> @@ -32,6 +36,24 @@ struct drmcg_device_resource {
>> s64 bo_limits_peak_allocated;
>>
>> s64 bo_stats_count_allocated;
>> +
>> + /**
>> + * Logical GPU
>> + *
>> + * *_cfg are properties configured by users
>> + * *_eff are the effective properties being applied to the hardware
>> + * *_stg is used to calculate _eff before applying to _eff
>> + * after considering the entire hierarchy
>> + */
>> + DECLARE_BITMAP(lgpu_stg, MAX_DRMCG_LGPU_CAPACITY);
>> + /* user configurations */
>> + s64 lgpu_weight_cfg;
>> + DECLARE_BITMAP(lgpu_cfg, MAX_DRMCG_LGPU_CAPACITY);
>> + /* effective lgpu for the cgroup after considering
>> + * relationship with other cgroup
>> + */
>> + s64 lgpu_count_eff;
>> + DECLARE_BITMAP(lgpu_eff, MAX_DRMCG_LGPU_CAPACITY);
>> };
>>
>> /**
>> diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c
>> index 5fcbbc13fa1c..a4e88a3704bb 100644
>> --- a/kernel/cgroup/drm.c
>> +++ b/kernel/cgroup/drm.c
>> @@ -9,6 +9,7 @@
>> #include <linux/seq_file.h>
>> #include <linux/mutex.h>
>> #include <linux/kernel.h>
>> +#include <linux/bitmap.h>
>> #include <linux/cgroup_drm.h>
>> #include <drm/drm_file.h>
>> #include <drm/drm_drv.h>
>> @@ -41,6 +42,10 @@ enum drmcg_file_type {
>> DRMCG_FTYPE_DEFAULT,
>> };
>>
>> +#define LGPU_LIMITS_NAME_LIST "list"
>> +#define LGPU_LIMITS_NAME_COUNT "count"
>> +#define LGPU_LIMITS_NAME_WEIGHT "weight"
>> +
>> /**
>> * drmcg_bind - Bind DRM subsystem to cgroup subsystem
>> * @acq_dm: function pointer to the drm_minor_acquire function
>> @@ -98,6 +103,13 @@ static inline int init_drmcg_single(struct drmcg *drmcg, struct drm_device *dev)
>> ddr->bo_limits_peak_allocated =
>> dev->drmcg_props.bo_limits_peak_allocated_default;
>>
>> + bitmap_copy(ddr->lgpu_cfg, dev->drmcg_props.lgpu_slots,
>> + MAX_DRMCG_LGPU_CAPACITY);
>> + bitmap_copy(ddr->lgpu_stg, dev->drmcg_props.lgpu_slots,
>> + MAX_DRMCG_LGPU_CAPACITY);
>> +
>> + ddr->lgpu_weight_cfg = CGROUP_WEIGHT_DFL;
>> +
>> return 0;
>> }
>>
>> @@ -121,6 +133,120 @@ static inline void drmcg_update_cg_tree(struct drm_device *dev)
>> mutex_unlock(&cgroup_mutex);
>> }
>>
>> +static void drmcg_calculate_effective_lgpu(struct drm_device *dev,
>> + const unsigned long *free_static,
>> + const unsigned long *free_weighted,
>> + struct drmcg *parent_drmcg)
>> +{
>> + int capacity = dev->drmcg_props.lgpu_capacity;
>> + DECLARE_BITMAP(lgpu_unused, MAX_DRMCG_LGPU_CAPACITY);
>> + DECLARE_BITMAP(lgpu_by_weight, MAX_DRMCG_LGPU_CAPACITY);
>> + struct drmcg_device_resource *parent_ddr;
>> + struct drmcg_device_resource *ddr;
>> + int minor = dev->primary->index;
>> + struct cgroup_subsys_state *pos;
>> + struct drmcg *child;
>> + s64 weight_sum = 0;
>> + s64 unused;
>> +
>> + parent_ddr = parent_drmcg->dev_resources[minor];
>> +
>> + if (bitmap_empty(parent_ddr->lgpu_cfg, capacity))
>> + /* no static cfg, use weight for calculating the effective */
>> + bitmap_copy(parent_ddr->lgpu_stg, free_weighted, capacity);
>> + else
>> + /* lgpu statically configured, use the overlap as effective */
>> + bitmap_and(parent_ddr->lgpu_stg, free_static,
>> + parent_ddr->lgpu_cfg, capacity);
>> +
>> + /* calculate lgpu available for distribution by weight for children */
>> + bitmap_copy(lgpu_unused, parent_ddr->lgpu_stg, capacity);
>> + css_for_each_child(pos, &parent_drmcg->css) {
>> + child = css_to_drmcg(pos);
>> + ddr = child->dev_resources[minor];
>> +
>> + if (bitmap_empty(ddr->lgpu_cfg, capacity))
>> + /* no static allocation, participate in weight dist */
>> + weight_sum += ddr->lgpu_weight_cfg;
>> + else
>> + /* take out statically allocated lgpu by siblings */
>> + bitmap_andnot(lgpu_unused, lgpu_unused, ddr->lgpu_cfg,
>> + capacity);
>> + }
>> +
>> + unused = bitmap_weight(lgpu_unused, capacity);
>> +
>> + css_for_each_child(pos, &parent_drmcg->css) {
>> + child = css_to_drmcg(pos);
>> + ddr = child->dev_resources[minor];
>> +
>> + bitmap_zero(lgpu_by_weight, capacity);
>> + /* no static allocation, participate in weight distribution */
>> + if (bitmap_empty(ddr->lgpu_cfg, capacity)) {
>> + int c;
>> + int p = 0;
>> +
>> + for (c = ddr->lgpu_weight_cfg * unused / weight_sum;
>> + c > 0; c--) {
>> + p = find_next_bit(lgpu_unused, capacity, p);
>> + if (p < capacity) {
>> + clear_bit(p, lgpu_unused);
>> + set_bit(p, lgpu_by_weight);
>> + }
>> + }
>> +
>> + }
>> +
>> + drmcg_calculate_effective_lgpu(dev, parent_ddr->lgpu_stg,
>> + lgpu_by_weight, child);
>> + }
>> +}
>> +
>> +static void drmcg_apply_effective_lgpu(struct drm_device *dev)
>> +{
>> + int capacity = dev->drmcg_props.lgpu_capacity;
>> + int minor = dev->primary->index;
>> + struct drmcg_device_resource *ddr;
>> + struct cgroup_subsys_state *pos;
>> + struct drmcg *drmcg;
>> +
>> + if (root_drmcg == NULL) {
>> + WARN_ON(root_drmcg == NULL);
>> + return;
>> + }
>> +
>> + rcu_read_lock();
>> +
>> + /* process the entire cgroup tree from root to simplify the algorithm */
>> + drmcg_calculate_effective_lgpu(dev, dev->drmcg_props.lgpu_slots,
>> + dev->drmcg_props.lgpu_slots, root_drmcg);
>> +
>> + /* apply changes to effective only if there is a change */
>> + css_for_each_descendant_pre(pos, &root_drmcg->css) {
>> + drmcg = css_to_drmcg(pos);
>> + ddr = drmcg->dev_resources[minor];
>> +
>> + if (!bitmap_equal(ddr->lgpu_stg, ddr->lgpu_eff, capacity)) {
>> + bitmap_copy(ddr->lgpu_eff, ddr->lgpu_stg, capacity);
>> + ddr->lgpu_count_eff =
>> + bitmap_weight(ddr->lgpu_eff, capacity);
>> + }
>> + }
>> + rcu_read_unlock();
>> +}
>> +
>> +static void drmcg_apply_effective(enum drmcg_res_type type,
>> + struct drm_device *dev, struct drmcg *changed_drmcg)
>> +{
>> + switch (type) {
>> + case DRMCG_TYPE_LGPU:
>> + drmcg_apply_effective_lgpu(dev);
>> + break;
>> + default:
>> + break;
>> + }
>> +}
>> +
>> /**
>> * drmcg_register_dev - register a DRM device for usage in drm cgroup
>> * @dev: DRM device
>> @@ -143,7 +269,13 @@ void drmcg_register_dev(struct drm_device *dev)
>> {
>> dev->driver->drmcg_custom_init(dev, &dev->drmcg_props);
>>
>> + WARN_ON(dev->drmcg_props.lgpu_capacity !=
>> + bitmap_weight(dev->drmcg_props.lgpu_slots,
>> + MAX_DRMCG_LGPU_CAPACITY));
>> +
>> drmcg_update_cg_tree(dev);
>> +
>> + drmcg_apply_effective(DRMCG_TYPE_LGPU, dev, root_drmcg);
>> }
>> mutex_unlock(&drmcg_mutex);
>> }
>> @@ -297,7 +429,8 @@ static void drmcg_print_stats(struct drmcg_device_resource *ddr,
>> }
>>
>> static void drmcg_print_limits(struct drmcg_device_resource *ddr,
>> - struct seq_file *sf, enum drmcg_res_type type)
>> + struct seq_file *sf, enum drmcg_res_type type,
>> + struct drm_device *dev)
>> {
>> if (ddr == NULL) {
>> seq_puts(sf, "\n");
>> @@ -311,6 +444,25 @@ static void drmcg_print_limits(struct drmcg_device_resource *ddr,
>> case DRMCG_TYPE_BO_PEAK:
>> seq_printf(sf, "%lld\n", ddr->bo_limits_peak_allocated);
>> break;
>> + case DRMCG_TYPE_LGPU:
>> + seq_printf(sf, "%s=%lld %s=%d %s=%*pbl\n",
>> + LGPU_LIMITS_NAME_WEIGHT,
>> + ddr->lgpu_weight_cfg,
>> + LGPU_LIMITS_NAME_COUNT,
>> + bitmap_weight(ddr->lgpu_cfg,
>> + dev->drmcg_props.lgpu_capacity),
>> + LGPU_LIMITS_NAME_LIST,
>> + dev->drmcg_props.lgpu_capacity,
>> + ddr->lgpu_cfg);
>> + break;
>> + case DRMCG_TYPE_LGPU_EFF:
>> + seq_printf(sf, "%s=%lld %s=%*pbl\n",
>> + LGPU_LIMITS_NAME_COUNT,
>> + ddr->lgpu_count_eff,
>> + LGPU_LIMITS_NAME_LIST,
>> + dev->drmcg_props.lgpu_capacity,
>> + ddr->lgpu_eff);
>> + break;
>> default:
>> seq_puts(sf, "\n");
>> break;
>> @@ -329,6 +481,17 @@ static void drmcg_print_default(struct drmcg_props *props,
>> seq_printf(sf, "%lld\n",
>> props->bo_limits_peak_allocated_default);
>> break;
>> + case DRMCG_TYPE_LGPU:
>> + seq_printf(sf, "%s=%d %s=%d %s=%*pbl\n",
>> + LGPU_LIMITS_NAME_WEIGHT,
>> + CGROUP_WEIGHT_DFL,
>> + LGPU_LIMITS_NAME_COUNT,
>> + bitmap_weight(props->lgpu_slots,
>> + props->lgpu_capacity),
>> + LGPU_LIMITS_NAME_LIST,
>> + props->lgpu_capacity,
>> + props->lgpu_slots);
>> + break;
>> default:
>> seq_puts(sf, "\n");
>> break;
>> @@ -358,7 +521,7 @@ static int drmcg_seq_show_fn(int id, void *ptr, void *data)
>> drmcg_print_stats(ddr, sf, type);
>> break;
>> case DRMCG_FTYPE_LIMIT:
>> - drmcg_print_limits(ddr, sf, type);
>> + drmcg_print_limits(ddr, sf, type, minor->dev);
>> break;
>> case DRMCG_FTYPE_DEFAULT:
>> drmcg_print_default(&minor->dev->drmcg_props, sf, type);
>> @@ -415,6 +578,115 @@ static int drmcg_process_limit_s64_val(char *sval, bool is_mem,
>> return rc;
>> }
>>
>> +static void drmcg_nested_limit_parse(struct kernfs_open_file *of,
>> + struct drm_device *dev, char *attrs)
>> +{
>> + DECLARE_BITMAP(tmp_bitmap, MAX_DRMCG_LGPU_CAPACITY);
>> + DECLARE_BITMAP(chk_bitmap, MAX_DRMCG_LGPU_CAPACITY);
>> + enum drmcg_res_type type =
>> + DRMCG_CTF_PRIV2RESTYPE(of_cft(of)->private);
>> + struct drmcg *drmcg = css_to_drmcg(of_css(of));
>> + struct drmcg_props *props = &dev->drmcg_props;
>> + char *cft_name = of_cft(of)->name;
>> + int minor = dev->primary->index;
>> + char *nested = strstrip(attrs);
>> + struct drmcg_device_resource *ddr =
>> + drmcg->dev_resources[minor];
>> + char *attr;
>> + char sname[256];
>> + char sval[256];
>> + s64 val;
>> + int rc;
>> +
>> + while (nested != NULL) {
>> + attr = strsep(&nested, " ");
>> +
>> + if (sscanf(attr, "%255[^=]=%255[^=]", sname, sval) != 2)
>> + continue;
>> +
>> + switch (type) {
>> + case DRMCG_TYPE_LGPU:
>> + if (strncmp(sname, LGPU_LIMITS_NAME_LIST, 256) &&
>> + strncmp(sname, LGPU_LIMITS_NAME_COUNT, 256) &&
>> + strncmp(sname, LGPU_LIMITS_NAME_WEIGHT, 256))
>> + continue;
>> +
>> + if (strncmp(sname, LGPU_LIMITS_NAME_WEIGHT, 256) &&
>> + (!strcmp("max", sval) ||
>> + !strcmp("default", sval))) {
>> + bitmap_copy(ddr->lgpu_cfg, props->lgpu_slots,
>> + props->lgpu_capacity);
>> +
>> + continue;
>> + }
>> +
>> + if (strncmp(sname, LGPU_LIMITS_NAME_WEIGHT, 256) == 0) {
>> + rc = drmcg_process_limit_s64_val(sval,
>> + false, CGROUP_WEIGHT_DFL,
>> + CGROUP_WEIGHT_MAX, &val);
>> +
>> + if (rc || val < CGROUP_WEIGHT_MIN ||
>> + val > CGROUP_WEIGHT_MAX) {
>> + drmcg_pr_cft_err(drmcg, rc, cft_name,
>> + minor);
>> + continue;
>> + }
>> +
>> + ddr->lgpu_weight_cfg = val;
>> + continue;
>> + }
>> +
>> + if (strncmp(sname, LGPU_LIMITS_NAME_COUNT, 256) == 0) {
>> + rc = drmcg_process_limit_s64_val(sval,
>> + false, props->lgpu_capacity,
>> + props->lgpu_capacity, &val);
>> +
>> + if (rc || val < 0) {
>> + drmcg_pr_cft_err(drmcg, rc, cft_name,
>> + minor);
>> + continue;
>> + }
>> +
>> + bitmap_zero(tmp_bitmap,
>> + MAX_DRMCG_LGPU_CAPACITY);
>> + bitmap_set(tmp_bitmap, 0, val);
>> + }
>> +
>> + if (strncmp(sname, LGPU_LIMITS_NAME_LIST, 256) == 0) {
>> + rc = bitmap_parselist(sval, tmp_bitmap,
>> + MAX_DRMCG_LGPU_CAPACITY);
>> +
>> + if (rc) {
>> + drmcg_pr_cft_err(drmcg, rc, cft_name,
>> + minor);
>> + continue;
>> + }
>> +
>> + bitmap_andnot(chk_bitmap, tmp_bitmap,
>> + props->lgpu_slots,
>> + MAX_DRMCG_LGPU_CAPACITY);
>> +
>> + /* user setting does not intersect with
>> + * available lgpu */
>> + if (!bitmap_empty(chk_bitmap,
>> + MAX_DRMCG_LGPU_CAPACITY)) {
>> + drmcg_pr_cft_err(drmcg, 0, cft_name,
>> + minor);
>> + continue;
>> + }
>> + }
>> +
>> + bitmap_copy(ddr->lgpu_cfg, tmp_bitmap,
>> + props->lgpu_capacity);
>> +
>> + break; /* DRMCG_TYPE_LGPU */
>> + default:
>> + break;
>> + } /* switch (type) */
>> + }
>> +}
>> +
>> +
>> /**
>> * drmcg_limit_write - parse cgroup interface files to obtain user config
>> *
>> @@ -499,9 +771,15 @@ static ssize_t drmcg_limit_write(struct kernfs_open_file *of, char *buf,
>>
>> ddr->bo_limits_peak_allocated = val;
>> break;
>> + case DRMCG_TYPE_LGPU:
>> + drmcg_nested_limit_parse(of, dm->dev, sattr);
>> + break;
>> default:
>> break;
>> }
>> +
>> + drmcg_apply_effective(type, dm->dev, drmcg);
>> +
>> mutex_unlock(&dm->dev->drmcg_mutex);
>>
>> mutex_lock(&drmcg_mutex);
>> @@ -560,12 +838,51 @@ struct cftype files[] = {
>> .private = DRMCG_CTF_PRIV(DRMCG_TYPE_BO_COUNT,
>> DRMCG_FTYPE_STATS),
>> },
>> + {
>> + .name = "lgpu",
>> + .seq_show = drmcg_seq_show,
>> + .write = drmcg_limit_write,
>> + .private = DRMCG_CTF_PRIV(DRMCG_TYPE_LGPU,
>> + DRMCG_FTYPE_LIMIT),
>> + },
>> + {
>> + .name = "lgpu.default",
>> + .seq_show = drmcg_seq_show,
>> + .flags = CFTYPE_ONLY_ON_ROOT,
>> + .private = DRMCG_CTF_PRIV(DRMCG_TYPE_LGPU,
>> + DRMCG_FTYPE_DEFAULT),
>> + },
>> + {
>> + .name = "lgpu.effective",
>> + .seq_show = drmcg_seq_show,
>> + .private = DRMCG_CTF_PRIV(DRMCG_TYPE_LGPU_EFF,
>> + DRMCG_FTYPE_LIMIT),
>> + },
>> { } /* terminate */
>> };
>>
>> +static int drmcg_online_fn(int id, void *ptr, void *data)
>> +{
>> + struct drm_minor *minor = ptr;
>> + struct drmcg *drmcg = data;
>> +
>> + if (minor->type != DRM_MINOR_PRIMARY)
>> + return 0;
>> +
>> + drmcg_apply_effective(DRMCG_TYPE_LGPU, minor->dev, drmcg);
>> +
>> + return 0;
>> +}
>> +
>> +static int drmcg_css_online(struct cgroup_subsys_state *css)
>> +{
>> + return drm_minor_for_each(&drmcg_online_fn, css_to_drmcg(css));
>> +}
>> +
>> struct cgroup_subsys drm_cgrp_subsys = {
>> .css_alloc = drmcg_css_alloc,
>> .css_free = drmcg_css_free,
>> + .css_online = drmcg_css_online,
>> .early_init = false,
>> .legacy_cftypes = files,
>> .dfl_cftypes = files,
>> @@ -585,6 +902,9 @@ void drmcg_device_early_init(struct drm_device *dev)
>> dev->drmcg_props.bo_limits_total_allocated_default = S64_MAX;
>> dev->drmcg_props.bo_limits_peak_allocated_default = S64_MAX;
>>
>> + dev->drmcg_props.lgpu_capacity = MAX_DRMCG_LGPU_CAPACITY;
>> + bitmap_fill(dev->drmcg_props.lgpu_slots, MAX_DRMCG_LGPU_CAPACITY);
>> +
>> drmcg_update_cg_tree(dev);
>> }
>> EXPORT_SYMBOL(drmcg_device_early_init);
>> --
>> 2.25.0
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
^ permalink raw reply
* Re: [PATCH] kvm/emulate: fix a -Werror=cast-function-type
From: Qian Cai @ 2020-02-14 17:08 UTC (permalink / raw)
To: Sean Christopherson
Cc: pbonzini, vkuznets, wanpengli, jmattson, joro, kvm, linux-kernel
In-Reply-To: <20200214165923.GA20690@linux.intel.com>
On Fri, 2020-02-14 at 08:59 -0800, Sean Christopherson wrote:
> On Fri, Feb 14, 2020 at 10:56:08AM -0500, Qian Cai wrote:
> > arch/x86/kvm/emulate.c: In function 'x86_emulate_insn':
> > arch/x86/kvm/emulate.c:5686:22: error: cast between incompatible
> > function types from 'int (*)(struct x86_emulate_ctxt *)' to 'void
> > (*)(struct fastop *)' [-Werror=cast-function-type]
> > rc = fastop(ctxt, (fastop_t)ctxt->execute);
> >
> > Fixes: 3009afc6e39e ("KVM: x86: Use a typedef for fastop functions")
> > Signed-off-by: Qian Cai <cai@lca.pw>
> > ---
> > arch/x86/kvm/emulate.c | 8 +++++---
> > 1 file changed, 5 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
> > index ddbc61984227..17ae820cf59d 100644
> > --- a/arch/x86/kvm/emulate.c
> > +++ b/arch/x86/kvm/emulate.c
> > @@ -5682,10 +5682,12 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
> > ctxt->eflags &= ~X86_EFLAGS_RF;
> >
> > if (ctxt->execute) {
> > - if (ctxt->d & Fastop)
> > - rc = fastop(ctxt, (fastop_t)ctxt->execute);
>
> Alternatively, can we do -Wno-cast-function-type? That's a silly warning
> IMO.
I am doing W=1 on linux-next where some of the warnings might be silly but the
recent commit changes all warnings to errors forces me having to silence those
somehow.
>
> If not, will either of these work?
>
> rc = fastop(ctxt, (void *)ctxt->execute);
>
> or
> rc = fastop(ctxt, (fastop_t)(void *)ctxt->execute);
I have no strong preference. I originally thought just to go back the previous
code style where might be more acceptable, but it is up to maintainers.
>
> > - else
> > + if (ctxt->d & Fastop) {
> > + fastop_t fop = (void *)ctxt->execute;
> > + rc = fastop(ctxt, fop);
> > + } else {
> > rc = ctxt->execute(ctxt);
> > + }
> > if (rc != X86EMUL_CONTINUE)
> > goto done;
> > goto writeback;
> > --
> > 1.8.3.1
> >
^ permalink raw reply
* [PATCH AUTOSEL 4.19 104/252] ipw2x00: Fix -Wcast-function-type
From: Sasha Levin @ 2020-02-14 16:09 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Phong Tran, Kees Cook, Kalle Valo, Sasha Levin, linux-wireless,
netdev
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: Phong Tran <tranmanphong@gmail.com>
[ Upstream commit ebd77feb27e91bb5fe35a7818b7c13ea7435fb98 ]
correct usage prototype of callback in tasklet_init().
Report by https://github.com/KSPP/linux/issues/20
Signed-off-by: Phong Tran <tranmanphong@gmail.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/intel/ipw2x00/ipw2100.c | 7 ++++---
drivers/net/wireless/intel/ipw2x00/ipw2200.c | 5 +++--
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
index 910db46db6a12..a3a470976a5c7 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
@@ -3220,8 +3220,9 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
}
}
-static void ipw2100_irq_tasklet(struct ipw2100_priv *priv)
+static void ipw2100_irq_tasklet(unsigned long data)
{
+ struct ipw2100_priv *priv = (struct ipw2100_priv *)data;
struct net_device *dev = priv->net_dev;
unsigned long flags;
u32 inta, tmp;
@@ -6025,7 +6026,7 @@ static void ipw2100_rf_kill(struct work_struct *work)
spin_unlock_irqrestore(&priv->low_lock, flags);
}
-static void ipw2100_irq_tasklet(struct ipw2100_priv *priv);
+static void ipw2100_irq_tasklet(unsigned long data);
static const struct net_device_ops ipw2100_netdev_ops = {
.ndo_open = ipw2100_open,
@@ -6155,7 +6156,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill);
INIT_DELAYED_WORK(&priv->scan_event, ipw2100_scan_event);
- tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
+ tasklet_init(&priv->irq_tasklet,
ipw2100_irq_tasklet, (unsigned long)priv);
/* NOTE: We do not start the deferred work for status checks yet */
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
index 9644e7b93645f..04aee2fdba375 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
@@ -1959,8 +1959,9 @@ static void notify_wx_assoc_event(struct ipw_priv *priv)
wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);
}
-static void ipw_irq_tasklet(struct ipw_priv *priv)
+static void ipw_irq_tasklet(unsigned long data)
{
+ struct ipw_priv *priv = (struct ipw_priv *)data;
u32 inta, inta_mask, handled = 0;
unsigned long flags;
int rc = 0;
@@ -10694,7 +10695,7 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv)
INIT_WORK(&priv->qos_activate, ipw_bg_qos_activate);
#endif /* CONFIG_IPW2200_QOS */
- tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
+ tasklet_init(&priv->irq_tasklet,
ipw_irq_tasklet, (unsigned long)priv);
return ret;
--
2.20.1
^ permalink raw reply related
* Re: [PATCH 1/4] drm/connector: Add data polarity flags
From: Sam Ravnborg @ 2020-02-14 16:13 UTC (permalink / raw)
To: Maxime Ripard
Cc: Chen-Yu Tsai, Maxime Ripard, dri-devel, Maarten Lankhorst,
Sean Paul, Daniel Vetter, David Airlie, devicetree, Mark Rutland,
Rob Herring, Frank Rowand, Thierry Reding, linux-arm-kernel
In-Reply-To: <b541006fa0a1c34ac5f668dc561aa1598f8fd86c.1581682983.git-series.maxime@cerno.tech>
Hi Maxime.
On Fri, Feb 14, 2020 at 01:24:38PM +0100, Maxime Ripard wrote:
> Some LVDS encoders can change the polarity of the data signals being
> sent. Add a DRM bus flag to reflect this.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
> include/drm/drm_connector.h | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 221910948b37..9a08fe6ab7c2 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -330,6 +330,8 @@ enum drm_panel_orientation {
> * edge of the pixel clock
> * @DRM_BUS_FLAG_SHARP_SIGNALS: Set if the Sharp-specific signals
> * (SPL, CLS, PS, REV) must be used
> + * @DRM_BUS_FLAG_DATA_LOW: The Data signals are active low
> + * @DRM_BUS_FLAG_DATA_HIGH: The Data signals are active high
Reading the description of these falgs always confuses me.
In this case if neither bit 9 nor bit 10 is set then the data signals
are netiher active low nor active high.
So what can I then expect?
We have the same logic loophole for DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE
and DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE.
So it is not new, but can we do better here?
Sam
> */
> enum drm_bus_flags {
> DRM_BUS_FLAG_DE_LOW = BIT(0),
> @@ -349,6 +351,8 @@ enum drm_bus_flags {
> DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE = DRM_BUS_FLAG_SYNC_NEGEDGE,
> DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE = DRM_BUS_FLAG_SYNC_POSEDGE,
> DRM_BUS_FLAG_SHARP_SIGNALS = BIT(8),
> + DRM_BUS_FLAG_DATA_LOW = BIT(9),
> + DRM_BUS_FLAG_DATA_HIGH = BIT(10),
> };
>
> /**
> --
> git-series 0.9.1
^ permalink raw reply
* [PATCH AUTOSEL 4.19 106/252] rtlwifi: rtl_pci: Fix -Wcast-function-type
From: Sasha Levin @ 2020-02-14 16:09 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Phong Tran, Kees Cook, Kalle Valo, Sasha Levin, linux-wireless,
netdev
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: Phong Tran <tranmanphong@gmail.com>
[ Upstream commit cb775c88da5d48a85d99d95219f637b6fad2e0e9 ]
correct usage prototype of callback in tasklet_init().
Report by https://github.com/KSPP/linux/issues/20
Signed-off-by: Phong Tran <tranmanphong@gmail.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/realtek/rtlwifi/pci.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index 5d1fda16fc8c4..83749578fa8b3 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -1082,13 +1082,15 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
return ret;
}
-static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw)
+static void _rtl_pci_irq_tasklet(unsigned long data)
{
+ struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
_rtl_pci_tx_chk_waitq(hw);
}
-static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
+static void _rtl_pci_prepare_bcn_tasklet(unsigned long data)
{
+ struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -1214,10 +1216,10 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw,
/*task */
tasklet_init(&rtlpriv->works.irq_tasklet,
- (void (*)(unsigned long))_rtl_pci_irq_tasklet,
+ _rtl_pci_irq_tasklet,
(unsigned long)hw);
tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet,
- (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet,
+ _rtl_pci_prepare_bcn_tasklet,
(unsigned long)hw);
INIT_WORK(&rtlpriv->works.lps_change_work,
rtl_lps_change_work_callback);
--
2.20.1
^ permalink raw reply related
* Re: [PATCH net] net: dsa: b53: Ensure the default VID is untagged
From: Florian Fainelli @ 2020-02-14 17:08 UTC (permalink / raw)
To: Vladimir Oltean
Cc: netdev, Andrew Lunn, Vivien Didelot, David S. Miller, open list
In-Reply-To: <CA+h21hqVWc6Tis12oJsfgXtsW2mJr0qUFu28G3qjMf-sOJWAwg@mail.gmail.com>
On 2/14/2020 2:36 AM, Vladimir Oltean wrote:
> Hi Florian,
>
> On Thu, 13 Feb 2020 at 21:10, Florian Fainelli <f.fainelli@gmail.com> wrote:
>>
>> We need to ensure that the default VID is untagged otherwise the switch
>> will be sending frames tagged frames and the results can be problematic.
>> This is especially true with b53 switches that use VID 0 as their
>> default VLAN since VID 0 has a special meaning.
>>
>> Fixes: fea83353177a ("net: dsa: b53: Fix default VLAN ID")
>> Fixes: 061f6a505ac3 ("net: dsa: Add ndo_vlan_rx_{add, kill}_vid implementation")
>> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
>> ---
>> drivers/net/dsa/b53/b53_common.c | 3 +++
>> 1 file changed, 3 insertions(+)
>>
>> diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
>> index 449a22172e07..f25c43b300d4 100644
>> --- a/drivers/net/dsa/b53/b53_common.c
>> +++ b/drivers/net/dsa/b53/b53_common.c
>> @@ -1366,6 +1366,9 @@ void b53_vlan_add(struct dsa_switch *ds, int port,
>>
>> b53_get_vlan_entry(dev, vid, vl);
>>
>> + if (vid == b53_default_pvid(dev))
>> + untagged = true;
>> +
>> vl->members |= BIT(port);
>> if (untagged && !dsa_is_cpu_port(ds, port))
>> vl->untag |= BIT(port);
>> --
>> 2.17.1
>>
>
> Don't you mean to force untagged egress only for the pvid value of 0?
The default VID (0 for most switches, 1 for 5325/65) is configured as
pvid during b53_configure_vlan() so when we get a call to port_vlan_add
with VID == 0 this is coming exclusively from
dsa_slave_vlan_rx_add_vid() since the bridge will never program a VID <
1. When dsa_slave_vlan_rx_add_vid() calls us, we do not have any VLAN
flags set in the object.
--
Florian
^ permalink raw reply
* Re: [PATCH 09/11] drm, cgroup: Introduce lgpu as DRM cgroup resource
From: Kenny Ho @ 2020-02-14 17:08 UTC (permalink / raw)
To: Jason Ekstrand
Cc: juan.zuniga-anaya-5C7GfCeVMHo, Daniel Vetter, Kenny Ho,
Kuehling, Felix, jsparks-WVYJKLFxKCc, amd-gfx mailing list,
lkaplan-WVYJKLFxKCc, Alex Deucher, nirmoy.das-5C7GfCeVMHo,
Maling list - DRI developers, Greathouse, Joseph, Tejun Heo,
cgroups-u79uwXL29TY76Z2rM5mHXA, Christian König,
damon.mcdougall-5C7GfCeVMHo
In-Reply-To: <CAOFGe96N5gG+08rQCRC+diHKDAfxPFYEnVxDS8_udvjcBYgsPg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
Hi Jason,
Thanks for the review.
On Fri, Feb 14, 2020 at 11:44 AM Jason Ekstrand <jason-fQELhIk9awXprZlt/sZkLg@public.gmane.org> wrote:
>
> Pardon my ignorance but I'm a bit confused by this. What is a "logical GPU"? What are we subdividing? Are we carving up memory? Compute power? Both?
The intention is compute but it is up to the individual drm driver to decide.
> If it's carving up compute power, what's actually being carved up? Time? Execution units/waves/threads? Even if that's the case, what advantage does it give to have it in terms of a fixed set of lgpus where each cgroup gets to pick a fixed set. Does affinity matter that much? Why not just say how many waves the GPU supports and that they have to be allocated in chunks of 16 waves (pulling a number out of thin air) and let the cgroup specify how many waves it wants.
>
> Don't get me wrong here. I'm all for the notion of being able to use cgroups to carve up GPU compute resources. However, this sounds to me like the most AMD-specific solution possible. We (Intel) could probably do some sort of carving up as well but we'd likely want to do it with preemption and time-slicing rather than handing out specific EUs.
This has been discussed in the RFC before
(https://www.spinics.net/lists/cgroups/msg23469.html.) As mentioned
before, the idea of a compute unit is hardly an AMD specific thing as
it is in the OpenCL standard and part of the architecture of many
different vendors. In addition, the interface presented here supports
Intel's use case. What you described is what I considered as the
"anonymous resources" view of the lgpu. What you/Intel can do, is to
register your device to drmcg to have 100 lgpu and users can specify
simply by count. So if they want to allocate 5% for a cgroup, they
would set count=5. Per the documentation in this patch: "Some DRM
devices may only support lgpu as anonymous resources. In such case,
the significance of the position of the set bits in list will be
ignored." What Intel does with the user expressed configuration of "5
out of 100" is entirely up to Intel (time slice if you like, change to
specific EUs later if you like, or make it driver configurable to
support both if you like.)
Regards,
Kenny
>
> On Fri, Feb 14, 2020 at 9:57 AM Kenny Ho <Kenny.Ho-5C7GfCeVMHo@public.gmane.org> wrote:
>>
>> drm.lgpu
>> A read-write nested-keyed file which exists on all cgroups.
>> Each entry is keyed by the DRM device's major:minor.
>>
>> lgpu stands for logical GPU, it is an abstraction used to
>> subdivide a physical DRM device for the purpose of resource
>> management. This file stores user configuration while the
>> drm.lgpu.effective reflects the actual allocation after
>> considering the relationship between the cgroups and their
>> configurations.
>>
>> The lgpu is a discrete quantity that is device specific (i.e.
>> some DRM devices may have 64 lgpus while others may have 100
>> lgpus.) The lgpu is a single quantity that can be allocated
>> in three different ways denoted by the following nested keys.
>>
>> ===== ==============================================
>> weight Allocate by proportion in relationship with
>> active sibling cgroups
>> count Allocate by amount statically, treat lgpu as
>> anonymous resources
>> list Allocate statically, treat lgpu as named
>> resource
>> ===== ==============================================
>>
>> For example:
>> 226:0 weight=100 count=256 list=0-255
>> 226:1 weight=100 count=4 list=0,2,4,6
>> 226:2 weight=100 count=32 list=32-63
>> 226:3 weight=100 count=0 list=
>> 226:4 weight=500 count=0 list=
>>
>> lgpu is represented by a bitmap and uses the bitmap_parselist
>> kernel function so the list key input format is a
>> comma-separated list of decimal numbers and ranges.
>>
>> Consecutively set bits are shown as two hyphen-separated decimal
>> numbers, the smallest and largest bit numbers set in the range.
>> Optionally each range can be postfixed to denote that only parts
>> of it should be set. The range will divided to groups of
>> specific size.
>> Syntax: range:used_size/group_size
>> Example: 0-1023:2/256 ==> 0,1,256,257,512,513,768,769
>>
>> The count key is the hamming weight / hweight of the bitmap.
>>
>> Weight, count and list accept the max and default keywords.
>>
>> Some DRM devices may only support lgpu as anonymous resources.
>> In such case, the significance of the position of the set bits
>> in list will be ignored.
>>
>> The weight quantity is only in effect when static allocation
>> is not used (by setting count=0) for this cgroup. The weight
>> quantity distributes lgpus that are not statically allocated by
>> the siblings. For example, given siblings cgroupA, cgroupB and
>> cgroupC for a DRM device that has 64 lgpus, if cgroupA occupies
>> 0-63, no lgpu is available to be distributed by weight.
>> Similarly, if cgroupA has list=0-31 and cgroupB has list=16-63,
>> cgroupC will be starved if it tries to allocate by weight.
>>
>> On the other hand, if cgroupA has weight=100 count=0, cgroupB
>> has list=16-47, and cgroupC has weight=100 count=0, then 32
>> lgpus are available to be distributed evenly between cgroupA
>> and cgroupC. In drm.lgpu.effective, cgroupA will have
>> list=0-15 and cgroupC will have list=48-63.
>>
>> This lgpu resource supports the 'allocation' and 'weight'
>> resource distribution model.
>>
>> drm.lgpu.effective
>> A read-only nested-keyed file which exists on all cgroups.
>> Each entry is keyed by the DRM device's major:minor.
>>
>> lgpu stands for logical GPU, it is an abstraction used to
>> subdivide a physical DRM device for the purpose of resource
>> management. This file reflects the actual allocation after
>> considering the relationship between the cgroups and their
>> configurations in drm.lgpu.
>>
>> Change-Id: Idde0ef9a331fd67bb9c7eb8ef9978439e6452488
>> Signed-off-by: Kenny Ho <Kenny.Ho-5C7GfCeVMHo@public.gmane.org>
>> ---
>> Documentation/admin-guide/cgroup-v2.rst | 80 ++++++
>> include/drm/drm_cgroup.h | 3 +
>> include/linux/cgroup_drm.h | 22 ++
>> kernel/cgroup/drm.c | 324 +++++++++++++++++++++++-
>> 4 files changed, 427 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
>> index ce5dc027366a..d8a41956e5c7 100644
>> --- a/Documentation/admin-guide/cgroup-v2.rst
>> +++ b/Documentation/admin-guide/cgroup-v2.rst
>> @@ -2120,6 +2120,86 @@ DRM Interface Files
>> Set largest allocation for /dev/dri/card1 to 4MB
>> echo "226:1 4m" > drm.buffer.peak.max
>>
>> + drm.lgpu
>> + A read-write nested-keyed file which exists on all cgroups.
>> + Each entry is keyed by the DRM device's major:minor.
>> +
>> + lgpu stands for logical GPU, it is an abstraction used to
>> + subdivide a physical DRM device for the purpose of resource
>> + management. This file stores user configuration while the
>> + drm.lgpu.effective reflects the actual allocation after
>> + considering the relationship between the cgroups and their
>> + configurations.
>> +
>> + The lgpu is a discrete quantity that is device specific (i.e.
>> + some DRM devices may have 64 lgpus while others may have 100
>> + lgpus.) The lgpu is a single quantity that can be allocated
>> + in three different ways denoted by the following nested keys.
>> +
>> + ===== ==============================================
>> + weight Allocate by proportion in relationship with
>> + active sibling cgroups
>> + count Allocate by amount statically, treat lgpu as
>> + anonymous resources
>> + list Allocate statically, treat lgpu as named
>> + resource
>> + ===== ==============================================
>> +
>> + For example:
>> + 226:0 weight=100 count=256 list=0-255
>> + 226:1 weight=100 count=4 list=0,2,4,6
>> + 226:2 weight=100 count=32 list=32-63
>> + 226:3 weight=100 count=0 list=
>> + 226:4 weight=500 count=0 list=
>> +
>> + lgpu is represented by a bitmap and uses the bitmap_parselist
>> + kernel function so the list key input format is a
>> + comma-separated list of decimal numbers and ranges.
>> +
>> + Consecutively set bits are shown as two hyphen-separated decimal
>> + numbers, the smallest and largest bit numbers set in the range.
>> + Optionally each range can be postfixed to denote that only parts
>> + of it should be set. The range will divided to groups of
>> + specific size.
>> + Syntax: range:used_size/group_size
>> + Example: 0-1023:2/256 ==> 0,1,256,257,512,513,768,769
>> +
>> + The count key is the hamming weight / hweight of the bitmap.
>> +
>> + Weight, count and list accept the max and default keywords.
>> +
>> + Some DRM devices may only support lgpu as anonymous resources.
>> + In such case, the significance of the position of the set bits
>> + in list will be ignored.
>> +
>> + The weight quantity is only in effect when static allocation
>> + is not used (by setting count=0) for this cgroup. The weight
>> + quantity distributes lgpus that are not statically allocated by
>> + the siblings. For example, given siblings cgroupA, cgroupB and
>> + cgroupC for a DRM device that has 64 lgpus, if cgroupA occupies
>> + 0-63, no lgpu is available to be distributed by weight.
>> + Similarly, if cgroupA has list=0-31 and cgroupB has list=16-63,
>> + cgroupC will be starved if it tries to allocate by weight.
>> +
>> + On the other hand, if cgroupA has weight=100 count=0, cgroupB
>> + has list=16-47, and cgroupC has weight=100 count=0, then 32
>> + lgpus are available to be distributed evenly between cgroupA
>> + and cgroupC. In drm.lgpu.effective, cgroupA will have
>> + list=0-15 and cgroupC will have list=48-63.
>> +
>> + This lgpu resource supports the 'allocation' and 'weight'
>> + resource distribution model.
>> +
>> + drm.lgpu.effective
>> + A read-only nested-keyed file which exists on all cgroups.
>> + Each entry is keyed by the DRM device's major:minor.
>> +
>> + lgpu stands for logical GPU, it is an abstraction used to
>> + subdivide a physical DRM device for the purpose of resource
>> + management. This file reflects the actual allocation after
>> + considering the relationship between the cgroups and their
>> + configurations in drm.lgpu.
>> +
>> GEM Buffer Ownership
>> ~~~~~~~~~~~~~~~~~~~~
>>
>> diff --git a/include/drm/drm_cgroup.h b/include/drm/drm_cgroup.h
>> index 2b41d4d22e33..619a110cc748 100644
>> --- a/include/drm/drm_cgroup.h
>> +++ b/include/drm/drm_cgroup.h
>> @@ -17,6 +17,9 @@ struct drmcg_props {
>>
>> s64 bo_limits_total_allocated_default;
>> s64 bo_limits_peak_allocated_default;
>> +
>> + int lgpu_capacity;
>> + DECLARE_BITMAP(lgpu_slots, MAX_DRMCG_LGPU_CAPACITY);
>> };
>>
>> void drmcg_bind(struct drm_minor (*(*acq_dm)(unsigned int minor_id)),
>> diff --git a/include/linux/cgroup_drm.h b/include/linux/cgroup_drm.h
>> index eae400f3d9b4..bb09704e7f71 100644
>> --- a/include/linux/cgroup_drm.h
>> +++ b/include/linux/cgroup_drm.h
>> @@ -11,10 +11,14 @@
>> /* limit defined per the way drm_minor_alloc operates */
>> #define MAX_DRM_DEV (64 * DRM_MINOR_RENDER)
>>
>> +#define MAX_DRMCG_LGPU_CAPACITY 256
>> +
>> enum drmcg_res_type {
>> DRMCG_TYPE_BO_TOTAL,
>> DRMCG_TYPE_BO_PEAK,
>> DRMCG_TYPE_BO_COUNT,
>> + DRMCG_TYPE_LGPU,
>> + DRMCG_TYPE_LGPU_EFF,
>> __DRMCG_TYPE_LAST,
>> };
>>
>> @@ -32,6 +36,24 @@ struct drmcg_device_resource {
>> s64 bo_limits_peak_allocated;
>>
>> s64 bo_stats_count_allocated;
>> +
>> + /**
>> + * Logical GPU
>> + *
>> + * *_cfg are properties configured by users
>> + * *_eff are the effective properties being applied to the hardware
>> + * *_stg is used to calculate _eff before applying to _eff
>> + * after considering the entire hierarchy
>> + */
>> + DECLARE_BITMAP(lgpu_stg, MAX_DRMCG_LGPU_CAPACITY);
>> + /* user configurations */
>> + s64 lgpu_weight_cfg;
>> + DECLARE_BITMAP(lgpu_cfg, MAX_DRMCG_LGPU_CAPACITY);
>> + /* effective lgpu for the cgroup after considering
>> + * relationship with other cgroup
>> + */
>> + s64 lgpu_count_eff;
>> + DECLARE_BITMAP(lgpu_eff, MAX_DRMCG_LGPU_CAPACITY);
>> };
>>
>> /**
>> diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c
>> index 5fcbbc13fa1c..a4e88a3704bb 100644
>> --- a/kernel/cgroup/drm.c
>> +++ b/kernel/cgroup/drm.c
>> @@ -9,6 +9,7 @@
>> #include <linux/seq_file.h>
>> #include <linux/mutex.h>
>> #include <linux/kernel.h>
>> +#include <linux/bitmap.h>
>> #include <linux/cgroup_drm.h>
>> #include <drm/drm_file.h>
>> #include <drm/drm_drv.h>
>> @@ -41,6 +42,10 @@ enum drmcg_file_type {
>> DRMCG_FTYPE_DEFAULT,
>> };
>>
>> +#define LGPU_LIMITS_NAME_LIST "list"
>> +#define LGPU_LIMITS_NAME_COUNT "count"
>> +#define LGPU_LIMITS_NAME_WEIGHT "weight"
>> +
>> /**
>> * drmcg_bind - Bind DRM subsystem to cgroup subsystem
>> * @acq_dm: function pointer to the drm_minor_acquire function
>> @@ -98,6 +103,13 @@ static inline int init_drmcg_single(struct drmcg *drmcg, struct drm_device *dev)
>> ddr->bo_limits_peak_allocated =
>> dev->drmcg_props.bo_limits_peak_allocated_default;
>>
>> + bitmap_copy(ddr->lgpu_cfg, dev->drmcg_props.lgpu_slots,
>> + MAX_DRMCG_LGPU_CAPACITY);
>> + bitmap_copy(ddr->lgpu_stg, dev->drmcg_props.lgpu_slots,
>> + MAX_DRMCG_LGPU_CAPACITY);
>> +
>> + ddr->lgpu_weight_cfg = CGROUP_WEIGHT_DFL;
>> +
>> return 0;
>> }
>>
>> @@ -121,6 +133,120 @@ static inline void drmcg_update_cg_tree(struct drm_device *dev)
>> mutex_unlock(&cgroup_mutex);
>> }
>>
>> +static void drmcg_calculate_effective_lgpu(struct drm_device *dev,
>> + const unsigned long *free_static,
>> + const unsigned long *free_weighted,
>> + struct drmcg *parent_drmcg)
>> +{
>> + int capacity = dev->drmcg_props.lgpu_capacity;
>> + DECLARE_BITMAP(lgpu_unused, MAX_DRMCG_LGPU_CAPACITY);
>> + DECLARE_BITMAP(lgpu_by_weight, MAX_DRMCG_LGPU_CAPACITY);
>> + struct drmcg_device_resource *parent_ddr;
>> + struct drmcg_device_resource *ddr;
>> + int minor = dev->primary->index;
>> + struct cgroup_subsys_state *pos;
>> + struct drmcg *child;
>> + s64 weight_sum = 0;
>> + s64 unused;
>> +
>> + parent_ddr = parent_drmcg->dev_resources[minor];
>> +
>> + if (bitmap_empty(parent_ddr->lgpu_cfg, capacity))
>> + /* no static cfg, use weight for calculating the effective */
>> + bitmap_copy(parent_ddr->lgpu_stg, free_weighted, capacity);
>> + else
>> + /* lgpu statically configured, use the overlap as effective */
>> + bitmap_and(parent_ddr->lgpu_stg, free_static,
>> + parent_ddr->lgpu_cfg, capacity);
>> +
>> + /* calculate lgpu available for distribution by weight for children */
>> + bitmap_copy(lgpu_unused, parent_ddr->lgpu_stg, capacity);
>> + css_for_each_child(pos, &parent_drmcg->css) {
>> + child = css_to_drmcg(pos);
>> + ddr = child->dev_resources[minor];
>> +
>> + if (bitmap_empty(ddr->lgpu_cfg, capacity))
>> + /* no static allocation, participate in weight dist */
>> + weight_sum += ddr->lgpu_weight_cfg;
>> + else
>> + /* take out statically allocated lgpu by siblings */
>> + bitmap_andnot(lgpu_unused, lgpu_unused, ddr->lgpu_cfg,
>> + capacity);
>> + }
>> +
>> + unused = bitmap_weight(lgpu_unused, capacity);
>> +
>> + css_for_each_child(pos, &parent_drmcg->css) {
>> + child = css_to_drmcg(pos);
>> + ddr = child->dev_resources[minor];
>> +
>> + bitmap_zero(lgpu_by_weight, capacity);
>> + /* no static allocation, participate in weight distribution */
>> + if (bitmap_empty(ddr->lgpu_cfg, capacity)) {
>> + int c;
>> + int p = 0;
>> +
>> + for (c = ddr->lgpu_weight_cfg * unused / weight_sum;
>> + c > 0; c--) {
>> + p = find_next_bit(lgpu_unused, capacity, p);
>> + if (p < capacity) {
>> + clear_bit(p, lgpu_unused);
>> + set_bit(p, lgpu_by_weight);
>> + }
>> + }
>> +
>> + }
>> +
>> + drmcg_calculate_effective_lgpu(dev, parent_ddr->lgpu_stg,
>> + lgpu_by_weight, child);
>> + }
>> +}
>> +
>> +static void drmcg_apply_effective_lgpu(struct drm_device *dev)
>> +{
>> + int capacity = dev->drmcg_props.lgpu_capacity;
>> + int minor = dev->primary->index;
>> + struct drmcg_device_resource *ddr;
>> + struct cgroup_subsys_state *pos;
>> + struct drmcg *drmcg;
>> +
>> + if (root_drmcg == NULL) {
>> + WARN_ON(root_drmcg == NULL);
>> + return;
>> + }
>> +
>> + rcu_read_lock();
>> +
>> + /* process the entire cgroup tree from root to simplify the algorithm */
>> + drmcg_calculate_effective_lgpu(dev, dev->drmcg_props.lgpu_slots,
>> + dev->drmcg_props.lgpu_slots, root_drmcg);
>> +
>> + /* apply changes to effective only if there is a change */
>> + css_for_each_descendant_pre(pos, &root_drmcg->css) {
>> + drmcg = css_to_drmcg(pos);
>> + ddr = drmcg->dev_resources[minor];
>> +
>> + if (!bitmap_equal(ddr->lgpu_stg, ddr->lgpu_eff, capacity)) {
>> + bitmap_copy(ddr->lgpu_eff, ddr->lgpu_stg, capacity);
>> + ddr->lgpu_count_eff =
>> + bitmap_weight(ddr->lgpu_eff, capacity);
>> + }
>> + }
>> + rcu_read_unlock();
>> +}
>> +
>> +static void drmcg_apply_effective(enum drmcg_res_type type,
>> + struct drm_device *dev, struct drmcg *changed_drmcg)
>> +{
>> + switch (type) {
>> + case DRMCG_TYPE_LGPU:
>> + drmcg_apply_effective_lgpu(dev);
>> + break;
>> + default:
>> + break;
>> + }
>> +}
>> +
>> /**
>> * drmcg_register_dev - register a DRM device for usage in drm cgroup
>> * @dev: DRM device
>> @@ -143,7 +269,13 @@ void drmcg_register_dev(struct drm_device *dev)
>> {
>> dev->driver->drmcg_custom_init(dev, &dev->drmcg_props);
>>
>> + WARN_ON(dev->drmcg_props.lgpu_capacity !=
>> + bitmap_weight(dev->drmcg_props.lgpu_slots,
>> + MAX_DRMCG_LGPU_CAPACITY));
>> +
>> drmcg_update_cg_tree(dev);
>> +
>> + drmcg_apply_effective(DRMCG_TYPE_LGPU, dev, root_drmcg);
>> }
>> mutex_unlock(&drmcg_mutex);
>> }
>> @@ -297,7 +429,8 @@ static void drmcg_print_stats(struct drmcg_device_resource *ddr,
>> }
>>
>> static void drmcg_print_limits(struct drmcg_device_resource *ddr,
>> - struct seq_file *sf, enum drmcg_res_type type)
>> + struct seq_file *sf, enum drmcg_res_type type,
>> + struct drm_device *dev)
>> {
>> if (ddr == NULL) {
>> seq_puts(sf, "\n");
>> @@ -311,6 +444,25 @@ static void drmcg_print_limits(struct drmcg_device_resource *ddr,
>> case DRMCG_TYPE_BO_PEAK:
>> seq_printf(sf, "%lld\n", ddr->bo_limits_peak_allocated);
>> break;
>> + case DRMCG_TYPE_LGPU:
>> + seq_printf(sf, "%s=%lld %s=%d %s=%*pbl\n",
>> + LGPU_LIMITS_NAME_WEIGHT,
>> + ddr->lgpu_weight_cfg,
>> + LGPU_LIMITS_NAME_COUNT,
>> + bitmap_weight(ddr->lgpu_cfg,
>> + dev->drmcg_props.lgpu_capacity),
>> + LGPU_LIMITS_NAME_LIST,
>> + dev->drmcg_props.lgpu_capacity,
>> + ddr->lgpu_cfg);
>> + break;
>> + case DRMCG_TYPE_LGPU_EFF:
>> + seq_printf(sf, "%s=%lld %s=%*pbl\n",
>> + LGPU_LIMITS_NAME_COUNT,
>> + ddr->lgpu_count_eff,
>> + LGPU_LIMITS_NAME_LIST,
>> + dev->drmcg_props.lgpu_capacity,
>> + ddr->lgpu_eff);
>> + break;
>> default:
>> seq_puts(sf, "\n");
>> break;
>> @@ -329,6 +481,17 @@ static void drmcg_print_default(struct drmcg_props *props,
>> seq_printf(sf, "%lld\n",
>> props->bo_limits_peak_allocated_default);
>> break;
>> + case DRMCG_TYPE_LGPU:
>> + seq_printf(sf, "%s=%d %s=%d %s=%*pbl\n",
>> + LGPU_LIMITS_NAME_WEIGHT,
>> + CGROUP_WEIGHT_DFL,
>> + LGPU_LIMITS_NAME_COUNT,
>> + bitmap_weight(props->lgpu_slots,
>> + props->lgpu_capacity),
>> + LGPU_LIMITS_NAME_LIST,
>> + props->lgpu_capacity,
>> + props->lgpu_slots);
>> + break;
>> default:
>> seq_puts(sf, "\n");
>> break;
>> @@ -358,7 +521,7 @@ static int drmcg_seq_show_fn(int id, void *ptr, void *data)
>> drmcg_print_stats(ddr, sf, type);
>> break;
>> case DRMCG_FTYPE_LIMIT:
>> - drmcg_print_limits(ddr, sf, type);
>> + drmcg_print_limits(ddr, sf, type, minor->dev);
>> break;
>> case DRMCG_FTYPE_DEFAULT:
>> drmcg_print_default(&minor->dev->drmcg_props, sf, type);
>> @@ -415,6 +578,115 @@ static int drmcg_process_limit_s64_val(char *sval, bool is_mem,
>> return rc;
>> }
>>
>> +static void drmcg_nested_limit_parse(struct kernfs_open_file *of,
>> + struct drm_device *dev, char *attrs)
>> +{
>> + DECLARE_BITMAP(tmp_bitmap, MAX_DRMCG_LGPU_CAPACITY);
>> + DECLARE_BITMAP(chk_bitmap, MAX_DRMCG_LGPU_CAPACITY);
>> + enum drmcg_res_type type =
>> + DRMCG_CTF_PRIV2RESTYPE(of_cft(of)->private);
>> + struct drmcg *drmcg = css_to_drmcg(of_css(of));
>> + struct drmcg_props *props = &dev->drmcg_props;
>> + char *cft_name = of_cft(of)->name;
>> + int minor = dev->primary->index;
>> + char *nested = strstrip(attrs);
>> + struct drmcg_device_resource *ddr =
>> + drmcg->dev_resources[minor];
>> + char *attr;
>> + char sname[256];
>> + char sval[256];
>> + s64 val;
>> + int rc;
>> +
>> + while (nested != NULL) {
>> + attr = strsep(&nested, " ");
>> +
>> + if (sscanf(attr, "%255[^=]=%255[^=]", sname, sval) != 2)
>> + continue;
>> +
>> + switch (type) {
>> + case DRMCG_TYPE_LGPU:
>> + if (strncmp(sname, LGPU_LIMITS_NAME_LIST, 256) &&
>> + strncmp(sname, LGPU_LIMITS_NAME_COUNT, 256) &&
>> + strncmp(sname, LGPU_LIMITS_NAME_WEIGHT, 256))
>> + continue;
>> +
>> + if (strncmp(sname, LGPU_LIMITS_NAME_WEIGHT, 256) &&
>> + (!strcmp("max", sval) ||
>> + !strcmp("default", sval))) {
>> + bitmap_copy(ddr->lgpu_cfg, props->lgpu_slots,
>> + props->lgpu_capacity);
>> +
>> + continue;
>> + }
>> +
>> + if (strncmp(sname, LGPU_LIMITS_NAME_WEIGHT, 256) == 0) {
>> + rc = drmcg_process_limit_s64_val(sval,
>> + false, CGROUP_WEIGHT_DFL,
>> + CGROUP_WEIGHT_MAX, &val);
>> +
>> + if (rc || val < CGROUP_WEIGHT_MIN ||
>> + val > CGROUP_WEIGHT_MAX) {
>> + drmcg_pr_cft_err(drmcg, rc, cft_name,
>> + minor);
>> + continue;
>> + }
>> +
>> + ddr->lgpu_weight_cfg = val;
>> + continue;
>> + }
>> +
>> + if (strncmp(sname, LGPU_LIMITS_NAME_COUNT, 256) == 0) {
>> + rc = drmcg_process_limit_s64_val(sval,
>> + false, props->lgpu_capacity,
>> + props->lgpu_capacity, &val);
>> +
>> + if (rc || val < 0) {
>> + drmcg_pr_cft_err(drmcg, rc, cft_name,
>> + minor);
>> + continue;
>> + }
>> +
>> + bitmap_zero(tmp_bitmap,
>> + MAX_DRMCG_LGPU_CAPACITY);
>> + bitmap_set(tmp_bitmap, 0, val);
>> + }
>> +
>> + if (strncmp(sname, LGPU_LIMITS_NAME_LIST, 256) == 0) {
>> + rc = bitmap_parselist(sval, tmp_bitmap,
>> + MAX_DRMCG_LGPU_CAPACITY);
>> +
>> + if (rc) {
>> + drmcg_pr_cft_err(drmcg, rc, cft_name,
>> + minor);
>> + continue;
>> + }
>> +
>> + bitmap_andnot(chk_bitmap, tmp_bitmap,
>> + props->lgpu_slots,
>> + MAX_DRMCG_LGPU_CAPACITY);
>> +
>> + /* user setting does not intersect with
>> + * available lgpu */
>> + if (!bitmap_empty(chk_bitmap,
>> + MAX_DRMCG_LGPU_CAPACITY)) {
>> + drmcg_pr_cft_err(drmcg, 0, cft_name,
>> + minor);
>> + continue;
>> + }
>> + }
>> +
>> + bitmap_copy(ddr->lgpu_cfg, tmp_bitmap,
>> + props->lgpu_capacity);
>> +
>> + break; /* DRMCG_TYPE_LGPU */
>> + default:
>> + break;
>> + } /* switch (type) */
>> + }
>> +}
>> +
>> +
>> /**
>> * drmcg_limit_write - parse cgroup interface files to obtain user config
>> *
>> @@ -499,9 +771,15 @@ static ssize_t drmcg_limit_write(struct kernfs_open_file *of, char *buf,
>>
>> ddr->bo_limits_peak_allocated = val;
>> break;
>> + case DRMCG_TYPE_LGPU:
>> + drmcg_nested_limit_parse(of, dm->dev, sattr);
>> + break;
>> default:
>> break;
>> }
>> +
>> + drmcg_apply_effective(type, dm->dev, drmcg);
>> +
>> mutex_unlock(&dm->dev->drmcg_mutex);
>>
>> mutex_lock(&drmcg_mutex);
>> @@ -560,12 +838,51 @@ struct cftype files[] = {
>> .private = DRMCG_CTF_PRIV(DRMCG_TYPE_BO_COUNT,
>> DRMCG_FTYPE_STATS),
>> },
>> + {
>> + .name = "lgpu",
>> + .seq_show = drmcg_seq_show,
>> + .write = drmcg_limit_write,
>> + .private = DRMCG_CTF_PRIV(DRMCG_TYPE_LGPU,
>> + DRMCG_FTYPE_LIMIT),
>> + },
>> + {
>> + .name = "lgpu.default",
>> + .seq_show = drmcg_seq_show,
>> + .flags = CFTYPE_ONLY_ON_ROOT,
>> + .private = DRMCG_CTF_PRIV(DRMCG_TYPE_LGPU,
>> + DRMCG_FTYPE_DEFAULT),
>> + },
>> + {
>> + .name = "lgpu.effective",
>> + .seq_show = drmcg_seq_show,
>> + .private = DRMCG_CTF_PRIV(DRMCG_TYPE_LGPU_EFF,
>> + DRMCG_FTYPE_LIMIT),
>> + },
>> { } /* terminate */
>> };
>>
>> +static int drmcg_online_fn(int id, void *ptr, void *data)
>> +{
>> + struct drm_minor *minor = ptr;
>> + struct drmcg *drmcg = data;
>> +
>> + if (minor->type != DRM_MINOR_PRIMARY)
>> + return 0;
>> +
>> + drmcg_apply_effective(DRMCG_TYPE_LGPU, minor->dev, drmcg);
>> +
>> + return 0;
>> +}
>> +
>> +static int drmcg_css_online(struct cgroup_subsys_state *css)
>> +{
>> + return drm_minor_for_each(&drmcg_online_fn, css_to_drmcg(css));
>> +}
>> +
>> struct cgroup_subsys drm_cgrp_subsys = {
>> .css_alloc = drmcg_css_alloc,
>> .css_free = drmcg_css_free,
>> + .css_online = drmcg_css_online,
>> .early_init = false,
>> .legacy_cftypes = files,
>> .dfl_cftypes = files,
>> @@ -585,6 +902,9 @@ void drmcg_device_early_init(struct drm_device *dev)
>> dev->drmcg_props.bo_limits_total_allocated_default = S64_MAX;
>> dev->drmcg_props.bo_limits_peak_allocated_default = S64_MAX;
>>
>> + dev->drmcg_props.lgpu_capacity = MAX_DRMCG_LGPU_CAPACITY;
>> + bitmap_fill(dev->drmcg_props.lgpu_slots, MAX_DRMCG_LGPU_CAPACITY);
>> +
>> drmcg_update_cg_tree(dev);
>> }
>> EXPORT_SYMBOL(drmcg_device_early_init);
>> --
>> 2.25.0
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* [PATCH AUTOSEL 4.19 105/252] iwlegacy: Fix -Wcast-function-type
From: Sasha Levin @ 2020-02-14 16:09 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Phong Tran, Kees Cook, Kalle Valo, Sasha Levin, linux-wireless,
netdev
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: Phong Tran <tranmanphong@gmail.com>
[ Upstream commit da5e57e8a6a3e69dac2937ba63fa86355628fbb2 ]
correct usage prototype of callback in tasklet_init().
Report by https://github.com/KSPP/linux/issues/20
Signed-off-by: Phong Tran <tranmanphong@gmail.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/intel/iwlegacy/3945-mac.c | 5 +++--
drivers/net/wireless/intel/iwlegacy/4965-mac.c | 5 +++--
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlegacy/3945-mac.c b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
index 57e3b6cca2341..b536ec20eaccb 100644
--- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c
+++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
@@ -1392,8 +1392,9 @@ il3945_dump_nic_error_log(struct il_priv *il)
}
static void
-il3945_irq_tasklet(struct il_priv *il)
+il3945_irq_tasklet(unsigned long data)
{
+ struct il_priv *il = (struct il_priv *)data;
u32 inta, handled = 0;
u32 inta_fh;
unsigned long flags;
@@ -3419,7 +3420,7 @@ il3945_setup_deferred_work(struct il_priv *il)
timer_setup(&il->watchdog, il_bg_watchdog, 0);
tasklet_init(&il->irq_tasklet,
- (void (*)(unsigned long))il3945_irq_tasklet,
+ il3945_irq_tasklet,
(unsigned long)il);
}
diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
index 280cd8ae1696d..6fc51c74cdb86 100644
--- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
@@ -4360,8 +4360,9 @@ il4965_synchronize_irq(struct il_priv *il)
}
static void
-il4965_irq_tasklet(struct il_priv *il)
+il4965_irq_tasklet(unsigned long data)
{
+ struct il_priv *il = (struct il_priv *)data;
u32 inta, handled = 0;
u32 inta_fh;
unsigned long flags;
@@ -6257,7 +6258,7 @@ il4965_setup_deferred_work(struct il_priv *il)
timer_setup(&il->watchdog, il_bg_watchdog, 0);
tasklet_init(&il->irq_tasklet,
- (void (*)(unsigned long))il4965_irq_tasklet,
+ il4965_irq_tasklet,
(unsigned long)il);
}
--
2.20.1
^ permalink raw reply related
* [PATCH AUTOSEL 4.19 107/252] bcma: remove set but not used variable 'sizel'
From: Sasha Levin @ 2020-02-14 16:09 UTC (permalink / raw)
To: linux-kernel, stable; +Cc: yu kuai, Kalle Valo, Sasha Levin, linux-wireless
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: yu kuai <yukuai3@huawei.com>
[ Upstream commit f427939391f290cbeabe0231eb8a116429d823f0 ]
Fixes gcc '-Wunused-but-set-variable' warning:
drivers/bcma/scan.c: In function ‘bcma_erom_get_addr_desc’:
drivers/bcma/scan.c:222:20: warning: variable ‘sizel’ set but
not used [-Wunused-but-set-variable]
It is never used, and so can be removed.
Fixes: 8369ae33b705 ("bcma: add Broadcom specific AMBA bus driver")
Signed-off-by: yu kuai <yukuai3@huawei.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/bcma/scan.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index 4a2d1b235fb5a..1f2de714b4017 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -219,7 +219,7 @@ static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 __iomem **eromptr)
static u32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr,
u32 type, u8 port)
{
- u32 addrl, addrh, sizel, sizeh = 0;
+ u32 addrl, addrh, sizeh = 0;
u32 size;
u32 ent = bcma_erom_get_ent(bus, eromptr);
@@ -239,12 +239,9 @@ static u32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr,
if ((ent & SCAN_ADDR_SZ) == SCAN_ADDR_SZ_SZD) {
size = bcma_erom_get_ent(bus, eromptr);
- sizel = size & SCAN_SIZE_SZ;
if (size & SCAN_SIZE_SG32)
sizeh = bcma_erom_get_ent(bus, eromptr);
- } else
- sizel = SCAN_ADDR_SZ_BASE <<
- ((ent & SCAN_ADDR_SZ) >> SCAN_ADDR_SZ_SHIFT);
+ }
return addrl;
}
--
2.20.1
^ permalink raw reply related
* [PATCH AUTOSEL 4.19 109/252] ACPICA: Disassembler: create buffer fields in ACPI_PARSE_LOAD_PASS1
From: Sasha Levin @ 2020-02-14 16:09 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Erik Kaneda, Elia Geretto, Bob Moore, Rafael J . Wysocki,
Sasha Levin, linux-acpi, devel
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: Erik Kaneda <erik.kaneda@intel.com>
[ Upstream commit 5ddbd77181dfca61b16d2e2222382ea65637f1b9 ]
ACPICA commit 29cc8dbc5463a93625bed87d7550a8bed8913bf4
create_buffer_field is a deferred op that is typically processed in
load pass 2. However, disassembly of control method contents walk the
parse tree with ACPI_PARSE_LOAD_PASS1 and AML_CREATE operators are
processed in a later walk. This is a problem when there is a control
method that has the same name as the AML_CREATE object. In this case,
any use of the name segment will be detected as a method call rather
than a reference to a buffer field. If this is detected as a method
call, it can result in a mal-formed parse tree if the control methods
have parameters.
This change in processing AML_CREATE ops earlier solves this issue by
inserting the named object in the ACPI namespace so that references
to this name would be detected as a name string rather than a method
call.
Link: https://github.com/acpica/acpica/commit/29cc8dbc
Reported-by: Elia Geretto <elia.f.geretto@gmail.com>
Tested-by: Elia Geretto <elia.f.geretto@gmail.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Erik Kaneda <erik.kaneda@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/acpi/acpica/dsfield.c | 2 +-
drivers/acpi/acpica/dswload.c | 21 +++++++++++++++++++++
2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c
index 30fe89545d6ab..bcc6a7acc5762 100644
--- a/drivers/acpi/acpica/dsfield.c
+++ b/drivers/acpi/acpica/dsfield.c
@@ -244,7 +244,7 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
* FUNCTION: acpi_ds_get_field_names
*
* PARAMETERS: info - create_field info structure
- * ` walk_state - Current method state
+ * walk_state - Current method state
* arg - First parser arg for the field name list
*
* RETURN: Status
diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c
index d06c414462822..ba53662f12179 100644
--- a/drivers/acpi/acpica/dswload.c
+++ b/drivers/acpi/acpica/dswload.c
@@ -412,6 +412,27 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
walk_state));
+ /*
+ * Disassembler: handle create field operators here.
+ *
+ * create_buffer_field is a deferred op that is typically processed in load
+ * pass 2. However, disassembly of control method contents walk the parse
+ * tree with ACPI_PARSE_LOAD_PASS1 and AML_CREATE operators are processed
+ * in a later walk. This is a problem when there is a control method that
+ * has the same name as the AML_CREATE object. In this case, any use of the
+ * name segment will be detected as a method call rather than a reference
+ * to a buffer field.
+ *
+ * This earlier creation during disassembly solves this issue by inserting
+ * the named object in the ACPI namespace so that references to this name
+ * would be a name string rather than a method call.
+ */
+ if ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) &&
+ (walk_state->op_info->flags & AML_CREATE)) {
+ status = acpi_ds_create_buffer_field(op, walk_state);
+ return_ACPI_STATUS(status);
+ }
+
/* We are only interested in opcodes that have an associated name */
if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) {
--
2.20.1
^ permalink raw reply related
* [PATCH AUTOSEL 4.19 108/252] orinoco: avoid assertion in case of NULL pointer
From: Sasha Levin @ 2020-02-14 16:09 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Aditya Pakki, Kalle Valo, Sasha Levin, linux-wireless, netdev
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: Aditya Pakki <pakki001@umn.edu>
[ Upstream commit c705f9fc6a1736dcf6ec01f8206707c108dca824 ]
In ezusb_init, if upriv is NULL, the code crashes. However, the caller
in ezusb_probe can handle the error and print the failure message.
The patch replaces the BUG_ON call to error return.
Signed-off-by: Aditya Pakki <pakki001@umn.edu>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/intersil/orinoco/orinoco_usb.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
index 2c7dd2a7350c1..b704e4bce171d 100644
--- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
@@ -1364,7 +1364,8 @@ static int ezusb_init(struct hermes *hw)
int retval;
BUG_ON(in_interrupt());
- BUG_ON(!upriv);
+ if (!upriv)
+ return -EINVAL;
upriv->reply_count = 0;
/* Write the MAGIC number on the simulated registers to keep
--
2.20.1
^ permalink raw reply related
* [PATCH AUTOSEL 4.19 110/252] scsi: ufs: Complete pending requests in host reset and restore path
From: Sasha Levin @ 2020-02-14 16:09 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Can Guo, Alim Akhtar, Bean Huo, Martin K . Petersen, Sasha Levin,
linux-scsi
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: Can Guo <cang@codeaurora.org>
[ Upstream commit 2df74b6985b51e77756e2e8faa16c45ca3ba53c5 ]
In UFS host reset and restore path, before probe, we stop and start the
host controller once. After host controller is stopped, the pending
requests, if any, are cleared from the doorbell, but no completion IRQ
would be raised due to the hba is stopped. These pending requests shall be
completed along with the first NOP_OUT command (as it is the first command
which can raise a transfer completion IRQ) sent during probe. Since the
OCSs of these pending requests are not SUCCESS (because they are not yet
literally finished), their UPIUs shall be dumped. When there are multiple
pending requests, the UPIU dump can be overwhelming and may lead to
stability issues because it is in atomic context. Therefore, before probe,
complete these pending requests right after host controller is stopped and
silence the UPIU dump from them.
Link: https://lore.kernel.org/r/1574751214-8321-5-git-send-email-cang@qti.qualcomm.com
Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
Reviewed-by: Bean Huo <beanhuo@micron.com>
Tested-by: Bean Huo <beanhuo@micron.com>
Signed-off-by: Can Guo <cang@codeaurora.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/scsi/ufs/ufshcd.c | 24 ++++++++++--------------
drivers/scsi/ufs/ufshcd.h | 2 ++
2 files changed, 12 insertions(+), 14 deletions(-)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index f4fcaee41dc26..b3dee24917a86 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -4809,7 +4809,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
break;
} /* end of switch */
- if (host_byte(result) != DID_OK)
+ if ((host_byte(result) != DID_OK) && !hba->silence_err_logs)
ufshcd_print_trs(hba, 1 << lrbp->task_tag, true);
return result;
}
@@ -5341,8 +5341,8 @@ static void ufshcd_err_handler(struct work_struct *work)
/*
* if host reset is required then skip clearing the pending
- * transfers forcefully because they will automatically get
- * cleared after link startup.
+ * transfers forcefully because they will get cleared during
+ * host reset and restore
*/
if (needs_reset)
goto skip_pending_xfer_clear;
@@ -5996,9 +5996,15 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba)
int err;
unsigned long flags;
- /* Reset the host controller */
+ /*
+ * Stop the host controller and complete the requests
+ * cleared by h/w
+ */
spin_lock_irqsave(hba->host->host_lock, flags);
ufshcd_hba_stop(hba, false);
+ hba->silence_err_logs = true;
+ ufshcd_complete_requests(hba);
+ hba->silence_err_logs = false;
spin_unlock_irqrestore(hba->host->host_lock, flags);
/* scale up clocks to max frequency before full reinitialization */
@@ -6032,22 +6038,12 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba)
static int ufshcd_reset_and_restore(struct ufs_hba *hba)
{
int err = 0;
- unsigned long flags;
int retries = MAX_HOST_RESET_RETRIES;
do {
err = ufshcd_host_reset_and_restore(hba);
} while (err && --retries);
- /*
- * After reset the door-bell might be cleared, complete
- * outstanding requests in s/w here.
- */
- spin_lock_irqsave(hba->host->host_lock, flags);
- ufshcd_transfer_req_compl(hba);
- ufshcd_tmc_handler(hba);
- spin_unlock_irqrestore(hba->host->host_lock, flags);
-
return err;
}
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 33fdd3f281ae8..4554a4b725b54 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -489,6 +489,7 @@ struct ufs_stats {
* @uic_error: UFS interconnect layer error status
* @saved_err: sticky error mask
* @saved_uic_err: sticky UIC error mask
+ * @silence_err_logs: flag to silence error logs
* @dev_cmd: ufs device management command information
* @last_dme_cmd_tstamp: time stamp of the last completed DME command
* @auto_bkops_enabled: to track whether bkops is enabled in device
@@ -645,6 +646,7 @@ struct ufs_hba {
u32 saved_err;
u32 saved_uic_err;
struct ufs_stats ufs_stats;
+ bool silence_err_logs;
/* Device management request data */
struct ufs_dev_cmd dev_cmd;
--
2.20.1
^ permalink raw reply related
* [PATCH AUTOSEL 4.19 112/252] scsi: aic7xxx: Adjust indentation in ahc_find_syncrate
From: Sasha Levin @ 2020-02-14 16:09 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Nathan Chancellor, Martin K . Petersen, Sasha Levin, linux-scsi,
clang-built-linux
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: Nathan Chancellor <natechancellor@gmail.com>
[ Upstream commit 4dbc96ad65c45cdd4e895ed7ae4c151b780790c5 ]
Clang warns:
../drivers/scsi/aic7xxx/aic7xxx_core.c:2317:5: warning: misleading
indentation; statement is not part of the previous 'if'
[-Wmisleading-indentation]
if ((syncrate->sxfr_u2 & ST_SXFR) != 0)
^
../drivers/scsi/aic7xxx/aic7xxx_core.c:2310:4: note: previous statement
is here
if (syncrate == &ahc_syncrates[maxsync])
^
1 warning generated.
This warning occurs because there is a space amongst the tabs on this
line. Remove it so that the indentation is consistent with the Linux kernel
coding style and clang no longer warns.
This has been a problem since the beginning of git history hence no fixes
tag.
Link: https://github.com/ClangBuiltLinux/linux/issues/817
Link: https://lore.kernel.org/r/20191218014220.52746-1-natechancellor@gmail.com
Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/scsi/aic7xxx/aic7xxx_core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c
index 915a34f141e4f..49e02e8745533 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -2321,7 +2321,7 @@ ahc_find_syncrate(struct ahc_softc *ahc, u_int *period,
* At some speeds, we only support
* ST transfers.
*/
- if ((syncrate->sxfr_u2 & ST_SXFR) != 0)
+ if ((syncrate->sxfr_u2 & ST_SXFR) != 0)
*ppr_options &= ~MSG_EXT_PPR_DT_REQ;
break;
}
--
2.20.1
^ permalink raw reply related
* [PATCH AUTOSEL 4.19 114/252] ARM: dts: r8a7779: Add device node for ARM global timer
From: Sasha Levin @ 2020-02-14 16:09 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Geert Uytterhoeven, Sasha Levin, linux-renesas-soc, devicetree
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: Geert Uytterhoeven <geert+renesas@glider.be>
[ Upstream commit 8443ffd1bbd5be74e9b12db234746d12e8ea93e2 ]
Add a device node for the global timer, which is part of the Cortex-A9
MPCore.
The global timer can serve as an accurate (4 ns) clock source for
scheduling and delay loops.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/20191211135222.26770-4-geert+renesas@glider.be
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/arm/boot/dts/r8a7779.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi
index 03919714645ae..f1c9b2bc542c5 100644
--- a/arch/arm/boot/dts/r8a7779.dtsi
+++ b/arch/arm/boot/dts/r8a7779.dtsi
@@ -68,6 +68,14 @@
<0xf0000100 0x100>;
};
+ timer@f0000200 {
+ compatible = "arm,cortex-a9-global-timer";
+ reg = <0xf0000200 0x100>;
+ interrupts = <GIC_PPI 11
+ (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
+ clocks = <&cpg_clocks R8A7779_CLK_ZS>;
+ };
+
timer@f0000600 {
compatible = "arm,cortex-a9-twd-timer";
reg = <0xf0000600 0x20>;
--
2.20.1
^ permalink raw reply related
* [PATCH AUTOSEL 4.19 116/252] rtc: hym8563: Return -EINVAL if the time is known to be invalid
From: Sasha Levin @ 2020-02-14 16:09 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Paul Kocialkowski, Alexandre Belloni, Sasha Levin, linux-rtc
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
[ Upstream commit f236a2a2ebabad0848ad0995af7ad1dc7029e895 ]
The current code returns -EPERM when the voltage loss bit is set.
Since the bit indicates that the time value is not valid, return
-EINVAL instead, which is the appropriate error code for this
situation.
Fixes: dcaf03849352 ("rtc: add hym8563 rtc-driver")
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
Link: https://lore.kernel.org/r/20191212153111.966923-1-paul.kocialkowski@bootlin.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/rtc/rtc-hym8563.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c
index e5ad527cb75e3..a8c2d38b24112 100644
--- a/drivers/rtc/rtc-hym8563.c
+++ b/drivers/rtc/rtc-hym8563.c
@@ -105,7 +105,7 @@ static int hym8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
if (!hym8563->valid) {
dev_warn(&client->dev, "no valid clock/calendar values available\n");
- return -EPERM;
+ return -EINVAL;
}
ret = i2c_smbus_read_i2c_block_data(client, HYM8563_SEC, 7, buf);
--
2.20.1
^ permalink raw reply related
* [PATCH AUTOSEL 4.19 115/252] selinux: ensure we cleanup the internal AVC counters on error in avc_update()
From: Sasha Levin @ 2020-02-14 16:09 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Jaihind Yadav, Ravi Kumar Siddojigari, Paul Moore, Sasha Levin,
selinux
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: Jaihind Yadav <jaihindyadav@codeaurora.org>
[ Upstream commit 030b995ad9ece9fa2d218af4429c1c78c2342096 ]
In AVC update we don't call avc_node_kill() when avc_xperms_populate()
fails, resulting in the avc->avc_cache.active_nodes counter having a
false value. In last patch this changes was missed , so correcting it.
Fixes: fa1aa143ac4a ("selinux: extended permissions for ioctls")
Signed-off-by: Jaihind Yadav <jaihindyadav@codeaurora.org>
Signed-off-by: Ravi Kumar Siddojigari <rsiddoji@codeaurora.org>
[PM: merge fuzz, minor description cleanup]
Signed-off-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
security/selinux/avc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 83eef39c8a799..d52be7b9f08c8 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -896,7 +896,7 @@ static int avc_update_node(struct selinux_avc *avc,
if (orig->ae.xp_node) {
rc = avc_xperms_populate(node, orig->ae.xp_node);
if (rc) {
- kmem_cache_free(avc_node_cachep, node);
+ avc_node_kill(avc, node);
goto out_unlock;
}
}
--
2.20.1
^ permalink raw reply related
* RE: [PATCH] ACPICA: Fix a typo in acuuid.h
From: Kaneda, Erik @ 2020-02-14 17:07 UTC (permalink / raw)
To: Rafael J. Wysocki, Christophe JAILLET
Cc: lenb@kernel.org, Moore, Robert, linux-acpi@vger.kernel.org,
devel@acpica.org, linux-kernel@vger.kernel.org,
kernel-janitors@vger.kernel.org
In-Reply-To: <2712088.SaWAGPlJqS@kreacher>
> -----Original Message-----
> From: linux-acpi-owner@vger.kernel.org <linux-acpi-
> owner@vger.kernel.org> On Behalf Of Rafael J. Wysocki
> Sent: Friday, February 14, 2020 2:02 AM
> To: Christophe JAILLET <christophe.jaillet@wanadoo.fr>; Kaneda, Erik
> <erik.kaneda@intel.com>
> Cc: lenb@kernel.org; Moore, Robert <robert.moore@intel.com>; linux-
> acpi@vger.kernel.org; devel@acpica.org; linux-kernel@vger.kernel.org;
> kernel-janitors@vger.kernel.org
> Subject: Re: [PATCH] ACPICA: Fix a typo in acuuid.h
>
> On Friday, February 14, 2020 7:30:03 AM CET Christophe JAILLET wrote:
> > The comment related to the ending of the include guard should be
> > related to __ACUUID_H__, not __AUUID_H__ (i.e. 'C' is missing).
> >
> > Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
>
> Erik, please route this through the upstream.
Thanks for your patch!
I'll add it to our next release (in March)
Erik
>
> Thanks!
>
> > ---
> > include/acpi/acuuid.h | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/include/acpi/acuuid.h b/include/acpi/acuuid.h index
> > 9dd4689a39cf..9e1367b19069 100644
> > --- a/include/acpi/acuuid.h
> > +++ b/include/acpi/acuuid.h
> > @@ -57,4 +57,4 @@
> > #define UUID_THERMAL_EXTENSIONS "14d399cd-7a27-4b18-8fb4-
> 7cb7b9f4e500"
> > #define UUID_DEVICE_PROPERTIES "daffd814-6eba-4d8c-8a91-
> bc9bbf4aa301"
> >
> > -#endif /* __AUUID_H__ */
> > +#endif /* __ACUUID_H__ */
> >
>
>
>
^ permalink raw reply
* [PATCH AUTOSEL 4.19 118/252] dmaengine: imx-sdma: Fix memory leak
From: Sasha Levin @ 2020-02-14 16:09 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Sascha Hauer, Robin Gong, Vinod Koul, Sasha Levin, dmaengine,
linux-arm-kernel
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: Sascha Hauer <s.hauer@pengutronix.de>
[ Upstream commit 02939cd167095f16328a1bd5cab5a90b550606df ]
The current descriptor is not on any list of the virtual DMA channel.
Once sdma_terminate_all() is called when a descriptor is currently
in flight then this one is forgotten to be freed. We have to call
vchan_terminate_vdesc() on this descriptor to re-add it to the lists.
Now that we also free the currently running descriptor we can (and
actually have to) remove the current descriptor from its list also
for the cyclic case.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Reviewed-by: Robin Gong <yibin.gong@nxp.com>
Tested-by: Robin Gong <yibin.gong@nxp.com>
Link: https://lore.kernel.org/r/20191216105328.15198-10-s.hauer@pengutronix.de
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/dma/imx-sdma.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index ceb82e74f5b4e..d66a7fdff898e 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -738,12 +738,8 @@ static void sdma_start_desc(struct sdma_channel *sdmac)
return;
}
sdmac->desc = desc = to_sdma_desc(&vd->tx);
- /*
- * Do not delete the node in desc_issued list in cyclic mode, otherwise
- * the desc allocated will never be freed in vchan_dma_desc_free_list
- */
- if (!(sdmac->flags & IMX_DMA_SG_LOOP))
- list_del(&vd->node);
+
+ list_del(&vd->node);
sdma->channel_control[channel].base_bd_ptr = desc->bd_phys;
sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
@@ -1044,7 +1040,6 @@ static void sdma_channel_terminate_work(struct work_struct *work)
spin_lock_irqsave(&sdmac->vc.lock, flags);
vchan_get_all_descriptors(&sdmac->vc, &head);
- sdmac->desc = NULL;
spin_unlock_irqrestore(&sdmac->vc.lock, flags);
vchan_dma_desc_free_list(&sdmac->vc, &head);
}
@@ -1052,11 +1047,19 @@ static void sdma_channel_terminate_work(struct work_struct *work)
static int sdma_disable_channel_async(struct dma_chan *chan)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
+ unsigned long flags;
+
+ spin_lock_irqsave(&sdmac->vc.lock, flags);
sdma_disable_channel(chan);
- if (sdmac->desc)
+ if (sdmac->desc) {
+ vchan_terminate_vdesc(&sdmac->desc->vd);
+ sdmac->desc = NULL;
schedule_work(&sdmac->terminate_worker);
+ }
+
+ spin_unlock_irqrestore(&sdmac->vc.lock, flags);
return 0;
}
--
2.20.1
^ permalink raw reply related
* [PATCH AUTOSEL 4.19 117/252] dmaengine: Store module owner in dma_device struct
From: Sasha Levin @ 2020-02-14 16:09 UTC (permalink / raw)
To: linux-kernel, stable; +Cc: Logan Gunthorpe, Vinod Koul, Sasha Levin, dmaengine
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: Logan Gunthorpe <logang@deltatee.com>
[ Upstream commit dae7a589c18a4d979d5f14b09374e871b995ceb1 ]
dma_chan_to_owner() dereferences the driver from the struct device to
obtain the owner and call module_[get|put](). However, if the backing
device is unbound before the dma_device is unregistered, the driver
will be cleared and this will cause a NULL pointer dereference.
Instead, store a pointer to the owner module in the dma_device struct
so the module reference can be properly put when the channel is put, even
if the backing device was destroyed first.
This change helps to support a safer unbind of DMA engines.
If the dma_device is unregistered in the driver's remove function,
there's no guarantee that there are no existing clients and a users
action may trigger the WARN_ONCE in dma_async_device_unregister()
which is unlikely to leave the system in a consistent state.
Instead, a better approach is to allow the backing driver to go away
and fail any subsequent requests to it.
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Link: https://lore.kernel.org/r/20191216190120.21374-2-logang@deltatee.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/dma/dmaengine.c | 4 +++-
include/linux/dmaengine.h | 2 ++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index f1a441ab395d7..8a52a5efee4f5 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -190,7 +190,7 @@ __dma_device_satisfies_mask(struct dma_device *device,
static struct module *dma_chan_to_owner(struct dma_chan *chan)
{
- return chan->device->dev->driver->owner;
+ return chan->device->owner;
}
/**
@@ -923,6 +923,8 @@ int dma_async_device_register(struct dma_device *device)
return -EIO;
}
+ device->owner = device->dev->driver->owner;
+
if (dma_has_cap(DMA_MEMCPY, device->cap_mask) && !device->device_prep_dma_memcpy) {
dev_err(device->dev,
"Device claims capability %s, but op is not defined\n",
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 0647f436f88c2..50128c36f0b48 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -686,6 +686,7 @@ struct dma_filter {
* @fill_align: alignment shift for memset operations
* @dev_id: unique device ID
* @dev: struct device reference for dma mapping api
+ * @owner: owner module (automatically set based on the provided dev)
* @src_addr_widths: bit mask of src addr widths the device supports
* Width is specified in bytes, e.g. for a device supporting
* a width of 4 the mask should have BIT(4) set.
@@ -749,6 +750,7 @@ struct dma_device {
int dev_id;
struct device *dev;
+ struct module *owner;
u32 src_addr_widths;
u32 dst_addr_widths;
--
2.20.1
^ permalink raw reply related
* [PATCH AUTOSEL 4.19 121/252] x86/vdso: Provide missing include file
From: Sasha Levin @ 2020-02-14 16:09 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Valdis Klētnieks, Borislav Petkov, H. Peter Anvin,
Andy Lutomirski, Ingo Molnar, Thomas Gleixner, x86-ml,
Sasha Levin
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: Valdis Klētnieks <valdis.kletnieks@vt.edu>
[ Upstream commit bff47c2302cc249bcd550b17067f8dddbd4b6f77 ]
When building with C=1, sparse issues a warning:
CHECK arch/x86/entry/vdso/vdso32-setup.c
arch/x86/entry/vdso/vdso32-setup.c:28:28: warning: symbol 'vdso32_enabled' was not declared. Should it be static?
Provide the missing header file.
Signed-off-by: Valdis Kletnieks <valdis.kletnieks@vt.edu>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: x86-ml <x86@kernel.org>
Link: https://lkml.kernel.org/r/36224.1575599767@turing-police
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/x86/entry/vdso/vdso32-setup.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/x86/entry/vdso/vdso32-setup.c b/arch/x86/entry/vdso/vdso32-setup.c
index 42d4c89f990ed..ddff0ca6f5098 100644
--- a/arch/x86/entry/vdso/vdso32-setup.c
+++ b/arch/x86/entry/vdso/vdso32-setup.c
@@ -11,6 +11,7 @@
#include <linux/smp.h>
#include <linux/kernel.h>
#include <linux/mm_types.h>
+#include <linux/elf.h>
#include <asm/processor.h>
#include <asm/vdso.h>
--
2.20.1
^ permalink raw reply related
* [PATCH AUTOSEL 4.19 122/252] PM / devfreq: rk3399_dmc: Add COMPILE_TEST and HAVE_ARM_SMCCC dependency
From: Sasha Levin @ 2020-02-14 16:09 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Chanwoo Choi, kbuild test robot, Sasha Levin, linux-pm
In-Reply-To: <20200214161147.15842-1-sashal@kernel.org>
From: Chanwoo Choi <cw00.choi@samsung.com>
[ Upstream commit eff5d31f7407fa9d31fb840106f1593399457298 ]
To build test, add COMPILE_TEST depedency to both ARM_RK3399_DMC_DEVFREQ
and DEVFREQ_EVENT_ROCKCHIP_DFI configuration. And ARM_RK3399_DMC_DEVFREQ
used the SMCCC interface so that add HAVE_ARM_SMCCC dependency to prevent
the build break.
Reported-by: kbuild test robot <lkp@intel.com>
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/devfreq/Kconfig | 3 ++-
drivers/devfreq/event/Kconfig | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index 6a172d338f6dc..4c4ec68b0566d 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -103,7 +103,8 @@ config ARM_TEGRA_DEVFREQ
config ARM_RK3399_DMC_DEVFREQ
tristate "ARM RK3399 DMC DEVFREQ Driver"
- depends on ARCH_ROCKCHIP
+ depends on (ARCH_ROCKCHIP && HAVE_ARM_SMCCC) || \
+ (COMPILE_TEST && HAVE_ARM_SMCCC)
select DEVFREQ_EVENT_ROCKCHIP_DFI
select DEVFREQ_GOV_SIMPLE_ONDEMAND
select PM_DEVFREQ_EVENT
diff --git a/drivers/devfreq/event/Kconfig b/drivers/devfreq/event/Kconfig
index cd949800eed96..8851bc4e8e3e1 100644
--- a/drivers/devfreq/event/Kconfig
+++ b/drivers/devfreq/event/Kconfig
@@ -33,7 +33,7 @@ config DEVFREQ_EVENT_EXYNOS_PPMU
config DEVFREQ_EVENT_ROCKCHIP_DFI
tristate "ROCKCHIP DFI DEVFREQ event Driver"
- depends on ARCH_ROCKCHIP
+ depends on ARCH_ROCKCHIP || COMPILE_TEST
help
This add the devfreq-event driver for Rockchip SoC. It provides DFI
(DDR Monitor Module) driver to count ddr load.
--
2.20.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.