Import of kernel-4.18.0-553.156.1.el8_10
This commit is contained in:
parent
72e7bf404b
commit
49821798bc
@ -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:
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
/*
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
472
net/can/bcm.c
472
net/can/bcm.c
@ -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 */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user