Import of kernel-4.18.0-553.156.1.el8_10

This commit is contained in:
almalinux-bot-kernel 2026-08-19 04:18:30 +00:00
parent 72e7bf404b
commit 49821798bc
16 changed files with 425 additions and 253 deletions

View File

@ -203,12 +203,15 @@ CONTENTS
- Total bandwidth (this_bw): this is the sum of all tasks "belonging" to the
runqueue, including the tasks in Inactive state.
- Maximum usable bandwidth (max_bw): This is the maximum bandwidth usable by
deadline tasks and is currently set to the RT capacity.
The algorithm reclaims the bandwidth of the tasks in Inactive state.
It does so by decrementing the runtime of the executing task Ti at a pace equal
to
dq = -max{ Ui / Umax, (1 - Uinact - Uextra) } dt
dq = -(max{ Ui, (Umax - Uinact - Uextra) } / Umax) dt
where:

View File

@ -12,7 +12,7 @@ RHEL_MINOR = 10
#
# Use this spot to avoid future merge conflicts.
# Do not trim this comment.
RHEL_RELEASE = 553.155.1
RHEL_RELEASE = 553.156.1
#
# ZSTREAM

View File

@ -28,8 +28,11 @@ static int ccp_aes_complete(struct crypto_async_request *async_req, int ret)
if (ret)
return ret;
if (ctx->u.aes.mode != CCP_AES_MODE_ECB)
memcpy(req->iv, rctx->iv, AES_BLOCK_SIZE);
if (ctx->u.aes.mode != CCP_AES_MODE_ECB) {
size_t ivsize = crypto_skcipher_ivsize(crypto_skcipher_reqtfm(req));
memcpy(req->iv, rctx->iv, ivsize);
}
return 0;
}

View File

@ -114,12 +114,19 @@ void amdgpu_gart_dummy_page_fini(struct amdgpu_device *adev)
*/
int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev)
{
int r;
if (adev->gart.bo != NULL)
return 0;
return amdgpu_bo_create_kernel(adev, adev->gart.table_size, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_VRAM, &adev->gart.bo,
NULL, (void *)&adev->gart.ptr);
r = amdgpu_bo_create_kernel(adev, adev->gart.table_size, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_VRAM, &adev->gart.bo,
NULL, (void *)&adev->gart.ptr);
if (r)
return r;
memset_io(adev->gart.ptr, adev->gart.gart_pte_flags, adev->gart.table_size);
return 0;
}
/**

View File

@ -51,8 +51,6 @@
#include "amdgpu_amdkfd.h"
#include "amdgpu_hmm.h"
#define MAX_WALK_BYTE (2UL << 30)
/**
* amdgpu_hmm_invalidate_gfx - callback to notify about mm change
*
@ -172,6 +170,7 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
{
struct hmm_range *hmm_range;
unsigned long end;
const u64 max_bytes = SZ_2G;
unsigned long timeout;
unsigned long i;
unsigned long *pfns;
@ -196,8 +195,9 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
end = start + npages * PAGE_SIZE;
hmm_range->dev_private_owner = owner;
hmm_range->notifier_seq = mmu_interval_read_begin(notifier);
do {
hmm_range->end = min(hmm_range->start + MAX_WALK_BYTE, end);
hmm_range->end = min(hmm_range->start + max_bytes, end);
pr_debug("hmm range: start = 0x%lx, end = 0x%lx",
hmm_range->start, hmm_range->end);
@ -208,7 +208,6 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
timeout = jiffies + msecs_to_jiffies(timeout);
retry:
hmm_range->notifier_seq = mmu_interval_read_begin(notifier);
r = hmm_range_fault(hmm_range);
if (unlikely(r)) {
/*
@ -222,7 +221,7 @@ retry:
if (hmm_range->end == end)
break;
hmm_range->hmm_pfns += MAX_WALK_BYTE >> PAGE_SHIFT;
hmm_range->hmm_pfns += max_bytes >> PAGE_SHIFT;
hmm_range->start = hmm_range->end;
schedule();
} while (hmm_range->end < end);

View File

@ -330,6 +330,12 @@ static int kfd_event_page_set(struct kfd_process *p, void *kernel_address,
if (p->signal_page)
return -EBUSY;
if (size < KFD_SIGNAL_EVENT_LIMIT * 8) {
pr_err("Event page size %llu is too small, need at least %lu bytes\n",
size, (unsigned long)(KFD_SIGNAL_EVENT_LIMIT * 8));
return -EINVAL;
}
page = kzalloc(sizeof(*page), GFP_KERNEL);
if (!page)
return -ENOMEM;

View File

@ -289,8 +289,8 @@ bool dal_vector_reserve(struct vector *vector, uint32_t capacity)
if (capacity <= vector->capacity)
return true;
new_container = krealloc(vector->container,
capacity * vector->struct_size, GFP_KERNEL);
new_container = krealloc_array(vector->container,
capacity, vector->struct_size, GFP_KERNEL);
if (new_container) {
vector->container = new_container;

View File

@ -2499,14 +2499,16 @@ static enum bp_result get_integrated_info_v11(
info_v11->extdispconninfo.checksum;
info->dp0_ext_hdmi_slv_addr = info_v11->dp0_retimer_set.HdmiSlvAddr;
info->dp0_ext_hdmi_reg_num = info_v11->dp0_retimer_set.HdmiRegNum;
info->dp0_ext_hdmi_reg_num = min_t(u8, info_v11->dp0_retimer_set.HdmiRegNum,
ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings));
for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
}
info->dp0_ext_hdmi_6g_reg_num = info_v11->dp0_retimer_set.Hdmi6GRegNum;
info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp0_retimer_set.Hdmi6GRegNum,
ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings));
for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
@ -2515,14 +2517,16 @@ static enum bp_result get_integrated_info_v11(
}
info->dp1_ext_hdmi_slv_addr = info_v11->dp1_retimer_set.HdmiSlvAddr;
info->dp1_ext_hdmi_reg_num = info_v11->dp1_retimer_set.HdmiRegNum;
info->dp1_ext_hdmi_reg_num = min_t(u8, info_v11->dp1_retimer_set.HdmiRegNum,
ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings));
for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
}
info->dp1_ext_hdmi_6g_reg_num = info_v11->dp1_retimer_set.Hdmi6GRegNum;
info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp1_retimer_set.Hdmi6GRegNum,
ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings));
for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
@ -2531,14 +2535,16 @@ static enum bp_result get_integrated_info_v11(
}
info->dp2_ext_hdmi_slv_addr = info_v11->dp2_retimer_set.HdmiSlvAddr;
info->dp2_ext_hdmi_reg_num = info_v11->dp2_retimer_set.HdmiRegNum;
info->dp2_ext_hdmi_reg_num = min_t(u8, info_v11->dp2_retimer_set.HdmiRegNum,
ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings));
for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
}
info->dp2_ext_hdmi_6g_reg_num = info_v11->dp2_retimer_set.Hdmi6GRegNum;
info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp2_retimer_set.Hdmi6GRegNum,
ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings));
for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
@ -2547,14 +2553,16 @@ static enum bp_result get_integrated_info_v11(
}
info->dp3_ext_hdmi_slv_addr = info_v11->dp3_retimer_set.HdmiSlvAddr;
info->dp3_ext_hdmi_reg_num = info_v11->dp3_retimer_set.HdmiRegNum;
info->dp3_ext_hdmi_reg_num = min_t(u8, info_v11->dp3_retimer_set.HdmiRegNum,
ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings));
for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
}
info->dp3_ext_hdmi_6g_reg_num = info_v11->dp3_retimer_set.Hdmi6GRegNum;
info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp3_retimer_set.Hdmi6GRegNum,
ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings));
for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
@ -2703,14 +2711,16 @@ static enum bp_result get_integrated_info_v2_1(
info->ext_disp_conn_info.checksum =
info_v2_1->extdispconninfo.checksum;
info->dp0_ext_hdmi_slv_addr = info_v2_1->dp0_retimer_set.HdmiSlvAddr;
info->dp0_ext_hdmi_reg_num = info_v2_1->dp0_retimer_set.HdmiRegNum;
info->dp0_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.HdmiRegNum,
ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings));
for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
}
info->dp0_ext_hdmi_6g_reg_num = info_v2_1->dp0_retimer_set.Hdmi6GRegNum;
info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.Hdmi6GRegNum,
ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings));
for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
@ -2718,14 +2728,16 @@ static enum bp_result get_integrated_info_v2_1(
info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
}
info->dp1_ext_hdmi_slv_addr = info_v2_1->dp1_retimer_set.HdmiSlvAddr;
info->dp1_ext_hdmi_reg_num = info_v2_1->dp1_retimer_set.HdmiRegNum;
info->dp1_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.HdmiRegNum,
ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings));
for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
}
info->dp1_ext_hdmi_6g_reg_num = info_v2_1->dp1_retimer_set.Hdmi6GRegNum;
info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.Hdmi6GRegNum,
ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings));
for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
@ -2733,14 +2745,16 @@ static enum bp_result get_integrated_info_v2_1(
info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
}
info->dp2_ext_hdmi_slv_addr = info_v2_1->dp2_retimer_set.HdmiSlvAddr;
info->dp2_ext_hdmi_reg_num = info_v2_1->dp2_retimer_set.HdmiRegNum;
info->dp2_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.HdmiRegNum,
ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings));
for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
}
info->dp2_ext_hdmi_6g_reg_num = info_v2_1->dp2_retimer_set.Hdmi6GRegNum;
info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.Hdmi6GRegNum,
ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings));
for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
@ -2748,14 +2762,16 @@ static enum bp_result get_integrated_info_v2_1(
info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
}
info->dp3_ext_hdmi_slv_addr = info_v2_1->dp3_retimer_set.HdmiSlvAddr;
info->dp3_ext_hdmi_reg_num = info_v2_1->dp3_retimer_set.HdmiRegNum;
info->dp3_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.HdmiRegNum,
ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings));
for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
}
info->dp3_ext_hdmi_6g_reg_num = info_v2_1->dp3_retimer_set.Hdmi6GRegNum;
info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.Hdmi6GRegNum,
ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings));
for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;

View File

@ -4693,7 +4693,11 @@ bool dc_process_dmub_aux_transfer_async(struct dc *dc,
union dmub_rb_cmd cmd = {0};
struct dc_dmub_srv *dmub_srv = dc->ctx->dmub_srv;
ASSERT(payload->length <= 16);
if (link_index >= dc->link_count || !dc->links[link_index])
return false;
if (payload->length > sizeof(cmd.dp_aux_access.aux_control.dpaux.data))
return false;
cmd.dp_aux_access.header.type = DMUB_CMD__DP_AUX_ACCESS;
cmd.dp_aux_access.header.payload_bytes = 0;

View File

@ -423,8 +423,6 @@ void i915_ttm_free_cached_io_rsgt(struct drm_i915_gem_object *obj)
int i915_ttm_purge(struct drm_i915_gem_object *obj)
{
struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
struct i915_ttm_tt *i915_tt =
container_of(bo->ttm, typeof(*i915_tt), ttm);
struct ttm_operation_ctx ctx = {
.interruptible = true,
.no_wait_gpu = false,
@ -439,16 +437,22 @@ int i915_ttm_purge(struct drm_i915_gem_object *obj)
if (ret)
return ret;
if (bo->ttm && i915_tt->filp) {
/*
* The below fput(which eventually calls shmem_truncate) might
* be delayed by worker, so when directly called to purge the
* pages(like by the shrinker) we should try to be more
* aggressive and release the pages immediately.
*/
shmem_truncate_range(file_inode(i915_tt->filp),
0, (loff_t)-1);
fput(fetch_and_zero(&i915_tt->filp));
if (bo->ttm) {
struct i915_ttm_tt *i915_tt =
container_of(bo->ttm, typeof(*i915_tt), ttm);
if (i915_tt->filp) {
/*
* The below fput(which eventually calls shmem_truncate)
* might be delayed by worker, so when directly called
* to purge the pages(like by the shrinker) we should
* try to be more aggressive and release the pages
* immediately.
*/
shmem_truncate_range(file_inode(i915_tt->filp),
0, (loff_t)-1);
fput(fetch_and_zero(&i915_tt->filp));
}
}
obj->write_domain = 0;

View File

@ -1554,6 +1554,14 @@ static long vhost_vring_set_num_addr(struct vhost_dev *d,
BUG();
}
/*
* The metadata cache holds the IOTLB mapping that backed the previous
* desc/avail/used addresses and vring size, both of which are being
* replaced here. iotlb_access_ok() takes a cache hit as proof that the
* region was validated, so the stale entries have to go.
*/
__vhost_vq_meta_reset(vq);
mutex_unlock(&vq->mutex);
return r;

View File

@ -1,2 +1,2 @@
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
kernel.centos,1,Red Hat,kernel-core,4.18.0-553.155.1.el8.x86_64,mailto:secalert@redhat.com
kernel.centos,1,Red Hat,kernel-core,4.18.0-553.156.1.el8.x86_64,mailto:secalert@redhat.com

View File

@ -1197,43 +1197,39 @@ int dl_runtime_exceeded(struct sched_dl_entity *dl_se)
extern bool sched_rt_bandwidth_account(struct rt_rq *rt_rq);
/*
* This function implements the GRUB accounting rule:
* according to the GRUB reclaiming algorithm, the runtime is
* not decreased as "dq = -dt", but as
* "dq = -max{u / Umax, (1 - Uinact - Uextra)} dt",
* This function implements the GRUB accounting rule. According to the
* GRUB reclaiming algorithm, the runtime is not decreased as "dq = -dt",
* but as "dq = -(max{u, (Umax - Uinact - Uextra)} / Umax) dt",
* where u is the utilization of the task, Umax is the maximum reclaimable
* utilization, Uinact is the (per-runqueue) inactive utilization, computed
* as the difference between the "total runqueue utilization" and the
* runqueue active utilization, and Uextra is the (per runqueue) extra
* "runqueue active utilization", and Uextra is the (per runqueue) extra
* reclaimable utilization.
* Since rq->dl.running_bw and rq->dl.this_bw contain utilizations
* multiplied by 2^BW_SHIFT, the result has to be shifted right by
* BW_SHIFT.
* Since rq->dl.bw_ratio contains 1 / Umax multiplied by 2^RATIO_SHIFT,
* dl_bw is multiped by rq->dl.bw_ratio and shifted right by RATIO_SHIFT.
* Since delta is a 64 bit variable, to have an overflow its value
* should be larger than 2^(64 - 20 - 8), which is more than 64 seconds.
* So, overflow is not an issue here.
* Since rq->dl.running_bw and rq->dl.this_bw contain utilizations multiplied
* by 2^BW_SHIFT, the result has to be shifted right by BW_SHIFT.
* Since rq->dl.bw_ratio contains 1 / Umax multiplied by 2^RATIO_SHIFT, dl_bw
* is multiped by rq->dl.bw_ratio and shifted right by RATIO_SHIFT.
* Since delta is a 64 bit variable, to have an overflow its value should be
* larger than 2^(64 - 20 - 8), which is more than 64 seconds. So, overflow is
* not an issue here.
*/
static u64 grub_reclaim(u64 delta, struct rq *rq, struct sched_dl_entity *dl_se)
{
u64 u_inact = rq->dl.this_bw - rq->dl.running_bw; /* Utot - Uact */
u64 u_act;
u64 u_act_min = (dl_se->dl_bw * rq->dl.bw_ratio) >> RATIO_SHIFT;
u64 u_inact = rq->dl.this_bw - rq->dl.running_bw; /* Utot - Uact */
/*
* Instead of computing max{u * bw_ratio, (1 - u_inact - u_extra)},
* we compare u_inact + rq->dl.extra_bw with
* 1 - (u * rq->dl.bw_ratio >> RATIO_SHIFT), because
* u_inact + rq->dl.extra_bw can be larger than
* 1 * (so, 1 - u_inact - rq->dl.extra_bw would be negative
* leading to wrong results)
* Instead of computing max{u, (u_max - u_inact - u_extra)}, we
* compare u_inact + u_extra with u_max - u, because u_inact + u_extra
* can be larger than u_max. So, u_max - u_inact - u_extra would be
* negative leading to wrong results.
*/
if (u_inact + rq->dl.extra_bw > BW_UNIT - u_act_min)
u_act = u_act_min;
if (u_inact + rq->dl.extra_bw > rq->dl.max_bw - dl_se->dl_bw)
u_act = dl_se->dl_bw;
else
u_act = BW_UNIT - u_inact - rq->dl.extra_bw;
u_act = rq->dl.max_bw - u_inact - rq->dl.extra_bw;
u_act = (u_act * rq->dl.bw_ratio) >> RATIO_SHIFT;
return (delta * u_act) >> BW_SHIFT;
}
@ -2631,12 +2627,12 @@ static void init_dl_rq_bw_ratio(struct dl_rq *dl_rq)
{
if (global_rt_runtime() == RUNTIME_INF) {
dl_rq->bw_ratio = 1 << RATIO_SHIFT;
dl_rq->extra_bw = 1 << BW_SHIFT;
dl_rq->max_bw = dl_rq->extra_bw = 1 << BW_SHIFT;
} else {
dl_rq->bw_ratio = to_ratio(global_rt_runtime(),
global_rt_period()) >> (BW_SHIFT - RATIO_SHIFT);
dl_rq->extra_bw = to_ratio(global_rt_period(),
global_rt_runtime());
dl_rq->max_bw = dl_rq->extra_bw =
to_ratio(global_rt_period(), global_rt_runtime());
}
}

View File

@ -690,7 +690,9 @@ struct dl_rq {
/* runqueue is an rbtree, ordered by deadline */
struct rb_root_cached root;
unsigned long dl_nr_running;
RH_KABI_REPLACE_SPLIT(unsigned long dl_nr_running,
unsigned int dl_nr_running,
unsigned int dl_nr_migratory)
#ifdef CONFIG_SMP
/*
@ -704,7 +706,12 @@ struct dl_rq {
u64 next;
} earliest_dl;
unsigned long dl_nr_migratory;
/*
* Maximum available bandwidth for reclaiming by SCHED_FLAG_RECLAIM
* tasks of this rq. Used in calculation of reclaimable bandwidth(GRUB).
*/
RH_KABI_REPLACE(unsigned long dl_nr_migratory,
u64 max_bw)
int overloaded;
/*

View File

@ -820,7 +820,12 @@ void object_err(struct kmem_cache *s, struct page *page,
return;
slab_bug(s, "%s", reason);
print_trailer(s, page, object);
if (!object || !check_valid_pointer(s, page, object)) {
print_page_info(page);
pr_err("Invalid pointer 0x%p\n", object);
} else {
print_trailer(s, page, object);
}
add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
}

View File

@ -57,6 +57,7 @@
#include <linux/can/skb.h>
#include <linux/can/bcm.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <net/sock.h>
#include <net/net_namespace.h>
@ -102,7 +103,6 @@ struct bcm_op {
unsigned long frames_abs, frames_filtered;
struct bcm_timeval ival1, ival2;
struct hrtimer timer, thrtimer;
struct tasklet_struct tsklet, thrtsklet;
ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;
int rx_ifindex;
int cfsiz;
@ -116,6 +116,8 @@ struct bcm_op {
struct canfd_frame last_sframe;
struct sock *sk;
struct net_device *rx_reg_dev;
spinlock_t bcm_tx_lock; /* protect tx data and timer updates */
spinlock_t bcm_rx_update_lock; /* protect filter/timer data updates */
};
struct bcm_sock {
@ -245,16 +247,28 @@ static int bcm_proc_show(struct seq_file *m, void *v)
* bcm_can_tx - send the (next) CAN frame to the appropriate CAN interface
* of the given bcm tx op
*/
static void bcm_can_tx(struct bcm_op *op)
static void bcm_can_tx(struct bcm_op *op, struct canfd_frame *cf)
{
struct sk_buff *skb;
struct net_device *dev;
struct canfd_frame *cf = op->frames + op->cfsiz * op->currframe;
struct canfd_frame cframe;
bool cyclic = !cf;
unsigned int idx = 0;
int err;
/* no target device? => exit */
if (!op->ifindex)
return;
if (cyclic) {
/* read currframe under lock protection */
spin_lock_bh(&op->bcm_tx_lock);
idx = op->currframe;
memcpy(&cframe, op->frames + op->cfsiz * idx, op->cfsiz);
cf = &cframe;
spin_unlock_bh(&op->bcm_tx_lock);
}
dev = dev_get_by_index(sock_net(op->sk), op->ifindex);
if (!dev) {
/* RFC: should this bcm_op remove itself here? */
@ -274,15 +288,30 @@ static void bcm_can_tx(struct bcm_op *op)
/* send with loopback */
skb->dev = dev;
can_skb_set_owner(skb, op->sk);
can_send(skb, 1);
err = can_send(skb, 1);
/* update statistics */
op->currframe++;
op->frames_abs++;
/* update currframe and count under lock protection */
spin_lock_bh(&op->bcm_tx_lock);
/* reached last frame? */
if (op->currframe >= op->nframes)
op->currframe = 0;
if (!err)
op->frames_abs++;
/* only advance the cyclic sequence if nothing reset currframe while
* we were sending - a concurrent TX_RESET_MULTI_IDX means this
* frame's bookkeeping belongs to a sequence that no longer exists
*/
if (!cyclic || op->currframe == idx) {
op->currframe++;
/* reached last frame? */
if (op->currframe >= op->nframes)
op->currframe = 0;
if (op->count > 0)
op->count--;
}
spin_unlock_bh(&op->bcm_tx_lock);
out:
dev_put(dev);
}
@ -351,58 +380,84 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head,
}
}
static void bcm_tx_start_timer(struct bcm_op *op)
static bool bcm_tx_set_expiry(struct bcm_op *op, struct hrtimer *hrt)
{
ktime_t ival;
spin_lock_bh(&op->bcm_tx_lock);
if (op->kt_ival1 && op->count)
hrtimer_start(&op->timer,
ktime_add(ktime_get(), op->kt_ival1),
HRTIMER_MODE_ABS);
else if (op->kt_ival2)
hrtimer_start(&op->timer,
ktime_add(ktime_get(), op->kt_ival2),
HRTIMER_MODE_ABS);
ival = op->kt_ival1;
else if (op->kt_ival2) {
ival = op->kt_ival2;
} else {
spin_unlock_bh(&op->bcm_tx_lock);
return false;
}
spin_unlock_bh(&op->bcm_tx_lock);
hrtimer_set_expires(hrt, ktime_add(ktime_get(), ival));
return true;
}
static void bcm_tx_timeout_tsklet(unsigned long data)
static void bcm_tx_start_timer(struct bcm_op *op)
{
struct bcm_op *op = (struct bcm_op *)data;
if (bcm_tx_set_expiry(op, &op->timer))
hrtimer_start_expires(&op->timer, HRTIMER_MODE_ABS_SOFT);
}
/* bcm_tx_timeout_handler - performs cyclic CAN frame transmissions */
static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
{
struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
struct bcm_msg_head msg_head;
bool tx_ival1, tx_ival2;
if (op->kt_ival1 && (op->count > 0)) {
/* snapshot kt_ival1/kt_ival2/count under lock to avoid torn
* ktime_t reads racing with concurrent bcm_tx_setup() updates
*/
spin_lock_bh(&op->bcm_tx_lock);
tx_ival1 = op->kt_ival1 && (op->count > 0);
tx_ival2 = !!op->kt_ival2;
spin_unlock_bh(&op->bcm_tx_lock);
op->count--;
if (!op->count && (op->flags & TX_COUNTEVT)) {
if (tx_ival1) {
u32 flags, count;
struct bcm_timeval ival1, ival2;
bcm_can_tx(op, NULL);
/* snapshot variables under lock to avoid torn reads racing
* with concurrent bcm_tx_setup() updates
*/
spin_lock_bh(&op->bcm_tx_lock);
flags = op->flags;
count = op->count;
ival1 = op->ival1;
ival2 = op->ival2;
spin_unlock_bh(&op->bcm_tx_lock);
if (!count && (flags & TX_COUNTEVT)) {
/* create notification to user */
memset(&msg_head, 0, sizeof(msg_head));
msg_head.opcode = TX_EXPIRED;
msg_head.flags = op->flags;
msg_head.count = op->count;
msg_head.ival1 = op->ival1;
msg_head.ival2 = op->ival2;
msg_head.flags = flags;
msg_head.count = count;
msg_head.ival1 = ival1;
msg_head.ival2 = ival2;
msg_head.can_id = op->can_id;
msg_head.nframes = 0;
bcm_send_to_user(op, &msg_head, NULL, 0);
}
bcm_can_tx(op);
} else if (op->kt_ival2)
bcm_can_tx(op);
} else if (tx_ival2) {
bcm_can_tx(op, NULL);
}
bcm_tx_start_timer(op);
}
/*
* bcm_tx_timeout_handler - performs cyclic CAN frame transmissions
*/
static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
{
struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
tasklet_schedule(&op->tsklet);
return HRTIMER_NORESTART;
return bcm_tx_set_expiry(op, &op->timer) ?
HRTIMER_RESTART : HRTIMER_NORESTART;
}
/*
@ -469,7 +524,7 @@ static void bcm_rx_update_and_send(struct bcm_op *op,
/* do not send the saved data - only start throttle timer */
hrtimer_start(&op->thrtimer,
ktime_add(op->kt_lastmsg, op->kt_ival2),
HRTIMER_MODE_ABS);
HRTIMER_MODE_ABS_SOFT);
return;
}
@ -528,14 +583,23 @@ static void bcm_rx_starttimer(struct bcm_op *op)
return;
if (op->kt_ival1)
hrtimer_start(&op->timer, op->kt_ival1, HRTIMER_MODE_REL);
hrtimer_start(&op->timer, op->kt_ival1, HRTIMER_MODE_REL_SOFT);
}
static void bcm_rx_timeout_tsklet(unsigned long data)
/* bcm_rx_timeout_handler - when the (cyclic) CAN frame reception timed out */
static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
{
struct bcm_op *op = (struct bcm_op *)data;
struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
struct bcm_msg_head msg_head;
spin_lock_bh(&op->bcm_rx_update_lock);
/* if user wants to be informed, when cyclic CAN-Messages come back */
if ((op->flags & RX_ANNOUNCE_RESUME) && op->last_frames) {
/* clear received CAN frames to indicate 'nothing received' */
memset(op->last_frames, 0, op->nframes * op->cfsiz);
}
/* create notification to user */
memset(&msg_head, 0, sizeof(msg_head));
msg_head.opcode = RX_TIMEOUT;
@ -546,26 +610,9 @@ static void bcm_rx_timeout_tsklet(unsigned long data)
msg_head.can_id = op->can_id;
msg_head.nframes = 0;
spin_unlock_bh(&op->bcm_rx_update_lock);
bcm_send_to_user(op, &msg_head, NULL, 0);
}
/*
* bcm_rx_timeout_handler - when the (cyclic) CAN frame reception timed out
*/
static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
{
struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
/* schedule before NET_RX_SOFTIRQ */
tasklet_hi_schedule(&op->tsklet);
/* no restart of the timer is done here! */
/* if user wants to be informed, when cyclic CAN-Messages come back */
if ((op->flags & RX_ANNOUNCE_RESUME) && op->last_frames) {
/* clear received CAN frames to indicate 'nothing received' */
memset(op->last_frames, 0, op->nframes * op->cfsiz);
}
return HRTIMER_NORESTART;
}
@ -573,14 +620,12 @@ static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
/*
* bcm_rx_do_flush - helper for bcm_rx_thr_flush
*/
static inline int bcm_rx_do_flush(struct bcm_op *op, int update,
unsigned int index)
static inline int bcm_rx_do_flush(struct bcm_op *op, unsigned int index)
{
struct canfd_frame *lcf = op->last_frames + op->cfsiz * index;
if ((op->last_frames) && (lcf->flags & RX_THR)) {
if (update)
bcm_rx_changed(op, lcf);
bcm_rx_changed(op, lcf);
return 1;
}
return 0;
@ -588,11 +633,8 @@ static inline int bcm_rx_do_flush(struct bcm_op *op, int update,
/*
* bcm_rx_thr_flush - Check for throttled data and send it to the userspace
*
* update == 0 : just check if throttled data is available (any irq context)
* update == 1 : check and send throttled data to userspace (soft_irq context)
*/
static int bcm_rx_thr_flush(struct bcm_op *op, int update)
static int bcm_rx_thr_flush(struct bcm_op *op)
{
int updated = 0;
@ -601,24 +643,16 @@ static int bcm_rx_thr_flush(struct bcm_op *op, int update)
/* for MUX filter we start at index 1 */
for (i = 1; i < op->nframes; i++)
updated += bcm_rx_do_flush(op, update, i);
updated += bcm_rx_do_flush(op, i);
} else {
/* for RX_FILTER_ID and simple filter */
updated += bcm_rx_do_flush(op, update, 0);
updated += bcm_rx_do_flush(op, 0);
}
return updated;
}
static void bcm_rx_thr_tsklet(unsigned long data)
{
struct bcm_op *op = (struct bcm_op *)data;
/* push the changed data to the userspace */
bcm_rx_thr_flush(op, 1);
}
/*
* bcm_rx_thr_handler - the time for blocked content updates is over now:
* Check for throttled data and send it to the userspace
@ -626,17 +660,26 @@ static void bcm_rx_thr_tsklet(unsigned long data)
static enum hrtimer_restart bcm_rx_thr_handler(struct hrtimer *hrtimer)
{
struct bcm_op *op = container_of(hrtimer, struct bcm_op, thrtimer);
enum hrtimer_restart ret;
tasklet_schedule(&op->thrtsklet);
spin_lock_bh(&op->bcm_rx_update_lock);
if (bcm_rx_thr_flush(op, 0)) {
hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2);
return HRTIMER_RESTART;
/* kt_ival2 may have been concurrently cleared by bcm_rx_setup()
* before it cancels this timer - never forward with a zero
* interval in that case.
*/
if (bcm_rx_thr_flush(op) && op->kt_ival2) {
hrtimer_forward_now(hrtimer, op->kt_ival2);
ret = HRTIMER_RESTART;
} else {
/* rearm throttle handling */
op->kt_lastmsg = 0;
return HRTIMER_NORESTART;
ret = HRTIMER_NORESTART;
}
spin_unlock_bh(&op->bcm_rx_update_lock);
return ret;
}
/*
@ -646,7 +689,9 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
{
struct bcm_op *op = (struct bcm_op *)data;
const struct canfd_frame *rxframe = (struct canfd_frame *)skb->data;
struct canfd_frame rtrframe;
unsigned int i;
bool rtr_frame;
if (op->can_id != rxframe->can_id)
return;
@ -665,12 +710,23 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
/* update statistics */
op->frames_abs++;
if (op->flags & RX_RTR_FRAME) {
/* snapshot the flag under lock: op->flags/op->frames may be updated
* concurrently by bcm_rx_setup().
*/
spin_lock_bh(&op->bcm_rx_update_lock);
rtr_frame = op->flags & RX_RTR_FRAME;
if (rtr_frame)
memcpy(&rtrframe, op->frames, op->cfsiz);
spin_unlock_bh(&op->bcm_rx_update_lock);
if (rtr_frame) {
/* send reply for RTR-request (placed in op->frames[0]) */
bcm_can_tx(op);
bcm_can_tx(op, &rtrframe);
return;
}
spin_lock_bh(&op->bcm_rx_update_lock);
if (op->flags & RX_FILTER_ID) {
/* the easiest case */
bcm_rx_update_and_send(op, op->last_frames, rxframe);
@ -704,6 +760,8 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
rx_starttimer:
bcm_rx_starttimer(op);
spin_unlock_bh(&op->bcm_rx_update_lock);
}
/*
@ -725,23 +783,8 @@ static struct bcm_op *bcm_find_op(struct list_head *ops,
static void bcm_remove_op(struct bcm_op *op)
{
if (op->tsklet.func) {
while (test_bit(TASKLET_STATE_SCHED, &op->tsklet.state) ||
test_bit(TASKLET_STATE_RUN, &op->tsklet.state) ||
hrtimer_active(&op->timer)) {
hrtimer_cancel(&op->timer);
tasklet_kill(&op->tsklet);
}
}
if (op->thrtsklet.func) {
while (test_bit(TASKLET_STATE_SCHED, &op->thrtsklet.state) ||
test_bit(TASKLET_STATE_RUN, &op->thrtsklet.state) ||
hrtimer_active(&op->thrtimer)) {
hrtimer_cancel(&op->thrtimer);
tasklet_kill(&op->thrtsklet);
}
}
hrtimer_cancel(&op->timer);
hrtimer_cancel(&op->thrtimer);
if ((op->frames) && (op->frames != &op->sframe))
kfree(op->frames);
@ -880,6 +923,8 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
/* check the given can_id */
op = bcm_find_op(&bo->tx_ops, msg_head, ifindex);
if (op) {
void *new_frames;
/* update existing BCM operation */
/*
@ -890,11 +935,23 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
if (msg_head->nframes > op->nframes)
return -E2BIG;
/* update CAN frames content */
/* get new CAN frames content into a staging buffer before
* locking: validate and normalize the frames there so that
* bcm_can_tx() / bcm_tx_timeout_handler() never observe a
* partially updated or unvalidated frame in op->frames
*/
new_frames = kmalloc(msg_head->nframes * op->cfsiz, GFP_KERNEL);
if (!new_frames)
return -ENOMEM;
for (i = 0; i < msg_head->nframes; i++) {
cf = op->frames + op->cfsiz * i;
cf = new_frames + op->cfsiz * i;
err = memcpy_from_msg((u8 *)cf, msg, op->cfsiz);
if (err < 0) {
kfree(new_frames);
return err;
}
if (op->flags & CAN_FD_FRAME) {
if (cf->len > 64)
@ -904,16 +961,39 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
err = -EINVAL;
}
if (err < 0)
if (err < 0) {
kfree(new_frames);
return err;
}
if (msg_head->flags & TX_CP_CAN_ID) {
/* copy can_id into frame */
cf->can_id = msg_head->can_id;
}
}
spin_lock_bh(&op->bcm_tx_lock);
/* update CAN frames content */
memcpy(op->frames, new_frames, msg_head->nframes * op->cfsiz);
op->flags = msg_head->flags;
if (op->nframes != msg_head->nframes ||
op->flags & TX_RESET_MULTI_IDX) {
/* potentially update changed nframes */
op->nframes = msg_head->nframes;
/* restart multiple frame transmission */
op->currframe = 0;
}
if (op->flags & SETTIMER)
op->count = msg_head->count;
spin_unlock_bh(&op->bcm_tx_lock);
kfree(new_frames);
} else {
/* insert new BCM operation for the given can_id */
@ -921,9 +1001,14 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
if (!op)
return -ENOMEM;
spin_lock_init(&op->bcm_tx_lock);
op->can_id = msg_head->can_id;
op->cfsiz = CFSIZ(msg_head->flags);
op->flags = msg_head->flags;
op->nframes = msg_head->nframes;
if (op->flags & SETTIMER)
op->count = msg_head->count;
/* create array for CAN frames and copy the data */
if (msg_head->nframes > 1) {
@ -941,6 +1026,8 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
cf = op->frames + op->cfsiz * i;
err = memcpy_from_msg((u8 *)cf, msg, op->cfsiz);
if (err < 0)
goto free_op;
if (op->flags & CAN_FD_FRAME) {
if (cf->len > 64)
@ -950,12 +1037,8 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
err = -EINVAL;
}
if (err < 0) {
if (op->frames != &op->sframe)
kfree(op->frames);
kfree(op);
return err;
}
if (err < 0)
goto free_op;
if (msg_head->flags & TX_CP_CAN_ID) {
/* copy can_id into frame */
@ -971,41 +1054,27 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
op->ifindex = ifindex;
/* initialize uninitialized (kzalloc) structure */
hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hrtimer_init(&op->timer, CLOCK_MONOTONIC,
HRTIMER_MODE_REL_SOFT);
op->timer.function = bcm_tx_timeout_handler;
/* initialize tasklet for tx countevent notification */
tasklet_init(&op->tsklet, bcm_tx_timeout_tsklet,
(unsigned long) op);
/* currently unused in tx_ops */
hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC,
HRTIMER_MODE_REL_SOFT);
/* add this bcm_op to the list of the tx_ops */
list_add(&op->list, &bo->tx_ops);
} /* if ((op = bcm_find_op(&bo->tx_ops, msg_head->can_id, ifindex))) */
if (op->nframes != msg_head->nframes) {
op->nframes = msg_head->nframes;
/* start multiple frame transmission with index 0 */
op->currframe = 0;
}
/* check flags */
if (op->flags & TX_RESET_MULTI_IDX) {
/* start multiple frame transmission with index 0 */
op->currframe = 0;
}
if (op->flags & SETTIMER) {
/* set timer values */
op->count = msg_head->count;
spin_lock_bh(&op->bcm_tx_lock);
op->ival1 = msg_head->ival1;
op->ival2 = msg_head->ival2;
op->kt_ival1 = bcm_timeval_to_ktime(msg_head->ival1);
op->kt_ival2 = bcm_timeval_to_ktime(msg_head->ival2);
spin_unlock_bh(&op->bcm_tx_lock);
/* disable an active timer due to zero values? */
if (!op->kt_ival1 && !op->kt_ival2)
@ -1018,16 +1087,37 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
op->flags |= TX_ANNOUNCE;
}
if (op->flags & TX_ANNOUNCE) {
bcm_can_tx(op);
if (op->count)
op->count--;
}
if (op->flags & TX_ANNOUNCE)
bcm_can_tx(op, NULL);
if (op->flags & STARTTIMER)
bcm_tx_start_timer(op);
return msg_head->nframes * op->cfsiz + MHSIZ;
free_op:
if (op->frames != &op->sframe)
kfree(op->frames);
kfree(op);
return err;
}
static void bcm_rx_setup_rtr_check(struct bcm_msg_head *msg_head,
struct bcm_op *op, void *new_frames)
{
/* funny feature in RX(!)_SETUP only for RTR-mode:
* copy can_id into frame BUT without RTR-flag to
* prevent a full-load-loopback-test ... ;-]
* normalize this on the staged buffer, before it is
* ever installed into op->frames.
*/
if (msg_head->flags & RX_RTR_FRAME) {
struct canfd_frame *frame0 = new_frames;
if ((msg_head->flags & TX_CP_CAN_ID) ||
frame0->can_id == op->can_id)
frame0->can_id = op->can_id & ~CAN_RTR_FLAG;
}
}
/*
@ -1060,6 +1150,8 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
/* check the given can_id */
op = bcm_find_op(&bo->rx_ops, msg_head, ifindex);
if (op) {
void *new_frames = NULL;
/* update existing BCM operation */
/*
@ -1071,19 +1163,48 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
return -E2BIG;
if (msg_head->nframes) {
/* update CAN frames content */
err = memcpy_from_msg(op->frames, msg,
msg_head->nframes * op->cfsiz);
if (err < 0)
return err;
/* get new CAN frames content before locking */
new_frames = kmalloc(msg_head->nframes * op->cfsiz,
GFP_KERNEL);
if (!new_frames)
return -ENOMEM;
/* clear last_frames to indicate 'nothing received' */
memset(op->last_frames, 0, msg_head->nframes * op->cfsiz);
err = memcpy_from_msg(new_frames, msg,
msg_head->nframes * op->cfsiz);
if (err < 0) {
kfree(new_frames);
return err;
}
bcm_rx_setup_rtr_check(msg_head, op, new_frames);
}
spin_lock_bh(&op->bcm_rx_update_lock);
op->nframes = msg_head->nframes;
op->flags = msg_head->flags;
if (msg_head->nframes) {
/* update CAN frames content */
memcpy(op->frames, new_frames,
msg_head->nframes * op->cfsiz);
/* clear last_frames to indicate 'nothing received' */
memset(op->last_frames, 0,
msg_head->nframes * op->cfsiz);
}
if (msg_head->flags & SETTIMER) {
op->ival1 = msg_head->ival1;
op->ival2 = msg_head->ival2;
op->kt_ival1 = bcm_timeval_to_ktime(msg_head->ival1);
op->kt_ival2 = bcm_timeval_to_ktime(msg_head->ival2);
op->kt_lastmsg = 0;
}
spin_unlock_bh(&op->bcm_rx_update_lock);
/* free temporary frames / kfree(NULL) is safe */
kfree(new_frames);
/* Only an update -> do not call can_rx_register() */
do_rx_register = 0;
@ -1093,6 +1214,8 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
if (!op)
return -ENOMEM;
spin_lock_init(&op->bcm_tx_lock);
spin_lock_init(&op->bcm_rx_update_lock);
op->can_id = msg_head->can_id;
op->nframes = msg_head->nframes;
op->cfsiz = CFSIZ(msg_head->flags);
@ -1134,6 +1257,8 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
kfree(op);
return err;
}
bcm_rx_setup_rtr_check(msg_head, op, op->frames);
}
/* bcm_can_tx / bcm_tx_timeout_handler needs this */
@ -1144,20 +1269,14 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
op->rx_ifindex = ifindex;
/* initialize uninitialized (kzalloc) structure */
hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hrtimer_init(&op->timer, CLOCK_MONOTONIC,
HRTIMER_MODE_REL_SOFT);
op->timer.function = bcm_rx_timeout_handler;
/* initialize tasklet for rx timeout notification */
tasklet_init(&op->tsklet, bcm_rx_timeout_tsklet,
(unsigned long) op);
hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC,
HRTIMER_MODE_REL_SOFT);
op->thrtimer.function = bcm_rx_thr_handler;
/* initialize tasklet for rx throttle handling */
tasklet_init(&op->thrtsklet, bcm_rx_thr_tsklet,
(unsigned long) op);
/* add this bcm_op to the list of the rx_ops */
list_add(&op->list, &bo->rx_ops);
@ -1169,29 +1288,22 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
/* check flags */
if (op->flags & RX_RTR_FRAME) {
struct canfd_frame *frame0 = op->frames;
/* no timers in RTR-mode */
hrtimer_cancel(&op->thrtimer);
hrtimer_cancel(&op->timer);
/*
* funny feature in RX(!)_SETUP only for RTR-mode:
* copy can_id into frame BUT without RTR-flag to
* prevent a full-load-loopback-test ... ;-]
*/
if ((op->flags & TX_CP_CAN_ID) ||
(frame0->can_id == op->can_id))
frame0->can_id = op->can_id & ~CAN_RTR_FLAG;
} else {
if (op->flags & SETTIMER) {
/* set timer value */
op->ival1 = msg_head->ival1;
op->ival2 = msg_head->ival2;
op->kt_ival1 = bcm_timeval_to_ktime(msg_head->ival1);
op->kt_ival2 = bcm_timeval_to_ktime(msg_head->ival2);
/* set timers (locked) for newly created op */
if (do_rx_register) {
spin_lock_bh(&op->bcm_rx_update_lock);
op->ival1 = msg_head->ival1;
op->ival2 = msg_head->ival2;
op->kt_ival1 = bcm_timeval_to_ktime(msg_head->ival1);
op->kt_ival2 = bcm_timeval_to_ktime(msg_head->ival2);
op->kt_lastmsg = 0;
spin_unlock_bh(&op->bcm_rx_update_lock);
}
/* disable an active timer due to zero value? */
if (!op->kt_ival1)
@ -1201,14 +1313,16 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
* In any case cancel the throttle timer, flush
* potentially blocked msgs and reset throttle handling
*/
op->kt_lastmsg = 0;
hrtimer_cancel(&op->thrtimer);
bcm_rx_thr_flush(op, 1);
spin_lock_bh(&op->bcm_rx_update_lock);
bcm_rx_thr_flush(op);
spin_unlock_bh(&op->bcm_rx_update_lock);
}
if ((op->flags & STARTTIMER) && op->kt_ival1)
hrtimer_start(&op->timer, op->kt_ival1,
HRTIMER_MODE_REL);
HRTIMER_MODE_REL_SOFT);
}
/* now we can register for can_ids, if we added a new bcm_op */