6.6.35-rc1 review
Subsystems (5)
Greg Kroah-Hartman
maintainerPATCH 131/267 iommu: Return right value in iommu_sva_bind_device()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lu Baolu <[email protected]>
[ Upstream commit 89e8a2366e3bce584b6c01549d5019c5cda1205e ]
iommu_sva_bind_device() should return either a sva bond handle or an ERR_PTR value in error cases. Existing drivers (idxd and uacce) only check the return value with IS_ERR(). This could potentially lead to a kernel NULL pointer dereference issue if the function returns NULL instead of an error pointer.
In reality, this doesn't cause any problems because iommu_sva_bind_device() only returns NULL when the kernel is not configured with CONFIG_IOMMU_SVA. In this case, iommu_dev_enable_feature(dev, IOMMU_DEV_FEAT_SVA) will return an error, and the device drivers won't call iommu_sva_bind_device() at all.
--- include/linux/iommu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/iommu.h +1 -1
@@ -1199,7 +1199,7 @@ u32 iommu_sva_get_pasid(struct iommu_sva *handle);static inline struct iommu_sva *iommu_sva_bind_device (struct device *dev,struct mm_struct *mm) { -return NULL ; +return ERR_PTR (-ENODEV ); }static inline void iommu_sva_unbind_device (struct iommu_sva *handle)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 132/267 io_uring/io-wq: Use set_bit() and test_bit() at worker->flags
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
[ Upstream commit 8a565304927fbd28c9f028c492b5c1714002cbab ]
Utilize set_bit() and test_bit() on worker->flags within io_uring/io-wq to address potential data races.
The structure io_worker->flags may be accessed through various data paths, leading to concurrency issues. When KCSAN is enabled, it reveals data races occurring in io_worker_handle_work and io_wq_activate_free_worker functions.
BUG: KCSAN: data-race in io_worker_handle_work / io_wq_activate_free_worker write to 0xffff8885c4246404 of 4 bytes by task 49071 on cpu 28: io_worker_handle_work (io_uring/io-wq.c:434 io_uring/io-wq.c:569) io_wq_worker (io_uring/io-wq.c:?)
<snip>
read to 0xffff8885c4246404 of 4 bytes by task 49024 on cpu 5: io_wq_activate_free_worker (io_uring/io-wq.c:? io_uring/io-wq.c:285) io_wq_enqueue (io_uring/io-wq.c:947) io_queue_iowq (io_uring/io_uring.c:524) io_req_task_submit (io_uring/io_uring.c:1511) io_handle_tw_list (io_uring/io_uring.c:1198)
<snip>
Line numbers against commit 18daea77cca6 ("Merge tag 'for-linus' ofgit://git.kernel.org/pub/scm/virt/kvm/kvm").
These races involve writes and reads to the same memory location by different tasks running on different CPUs. To mitigate this, refactor the code to use atomic operations such as set_bit(), test_bit(), and clear_bit() instead of basic "and" and "or" operations. This ensures thread-safe manipulation of worker flags.
Also, move create_index to avoid holes in the structure.
Stable-dep-of: 91215f70ea85 ("io_uring/io-wq: avoid garbage value of 'match' in io_wq_enqueue()")
--- io_uring/io-wq.c | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-)
io_uring/io-wq.c +24 -23
@@ -25,10 +25,10 @@#define WORKER_IDLE_TIMEOUT (5 * HZ)enum { -IO_WORKER_F_UP =1 ,/* up and active */ -IO_WORKER_F_RUNNING =2 ,/* account as running */ -IO_WORKER_F_FREE =4 ,/* worker on free list */ -IO_WORKER_F_BOUND =8 ,/* is doing bounded work */ +IO_WORKER_F_UP =0 ,/* up and active */ +IO_WORKER_F_RUNNING =1 ,/* account as running */ +IO_WORKER_F_FREE =2 ,/* worker on free list */ +IO_WORKER_F_BOUND =3 ,/* is doing bounded work */ };enum {
@@ -44,7 +44,8 @@ enum {*/ struct io_worker {refcount_t ref; -unsigned flags; +int create_index; +unsigned long flags;struct hlist_nulls_node nulls_node;struct list_head all_list;struct task_struct *task;
@@ -58,7 +59,6 @@ struct io_worker {unsigned long create_state;struct callback_head create_work; -int create_index;union {struct rcu_head rcu;
@@ -165,7 +165,7 @@ static inline struct io_wq_acct *io_work_get_acct(struct io_wq *wq,static inline struct io_wq_acct *io_wq_get_acct (struct io_worker *worker) { -return io_get_acct (worker->wq, worker->flags &IO_WORKER_F_BOUND ); +return io_get_acct (worker->wq,test_bit (IO_WORKER_F_BOUND , &worker->flags)); }static void io_worker_ref_put (struct io_wq *wq)
@@ -225,7 +225,7 @@ static void io_worker_exit(struct io_worker *worker)wait_for_completion (&worker->ref_done);raw_spin_lock (&wq->lock); -if (worker->flags &IO_WORKER_F_FREE ) +if (test_bit (IO_WORKER_F_FREE , &worker->flags))hlist_nulls_del_rcu (&worker->nulls_node);list_del_rcu (&worker->all_list);raw_spin_unlock (&wq->lock);
@@ -410,7 +410,7 @@ static void io_wq_dec_running(struct io_worker *worker)struct io_wq_acct *acct =io_wq_get_acct (worker);struct io_wq *wq = worker->wq; -if (!(worker->flags &IO_WORKER_F_UP )) +if (!test_bit (IO_WORKER_F_UP , &worker->flags))return ;if (!atomic_dec_and_test (&acct->nr_running))
@@ -430,8 +430,8 @@ static void io_wq_dec_running(struct io_worker *worker)*/ static void __io_worker_busy (struct io_wq *wq,struct io_worker *worker) { -if (worker->flags &IO_WORKER_F_FREE ) { - worker->flags &= ~IO_WORKER_F_FREE ; +if (test_bit (IO_WORKER_F_FREE , &worker->flags)) { +clear_bit (IO_WORKER_F_FREE , &worker->flags);raw_spin_lock (&wq->lock);hlist_nulls_del_init_rcu (&worker->nulls_node);raw_spin_unlock (&wq->lock);
@@ -444,8 +444,8 @@ static void __io_worker_busy(struct io_wq *wq, struct io_worker *worker)static void __io_worker_idle (struct io_wq *wq,struct io_worker *worker) __must_hold(wq->lock) { -if (!(worker->flags &IO_WORKER_F_FREE )) { - worker->flags |=IO_WORKER_F_FREE ; +if (!test_bit (IO_WORKER_F_FREE , &worker->flags)) { +set_bit (IO_WORKER_F_FREE , &worker->flags);hlist_nulls_add_head_rcu (&worker->nulls_node, &wq->free_list); } }
@@ -634,7 +634,8 @@ static int io_wq_worker(void *data)bool exit_mask = false, last_timeout = false;char buf[TASK_COMM_LEN ]; - worker->flags |= (IO_WORKER_F_UP |IO_WORKER_F_RUNNING ); +set_mask_bits (&worker->flags,0 , +BIT (IO_WORKER_F_UP ) |BIT (IO_WORKER_F_RUNNING ));snprintf (buf,sizeof (buf),"iou-wrk-%d" , wq->task->pid);set_task_comm (current, buf);
@@ -698,11 +699,11 @@ void io_wq_worker_running(struct task_struct *tsk)if (!worker)return ; -if (!(worker->flags &IO_WORKER_F_UP )) +if (!test_bit (IO_WORKER_F_UP , &worker->flags))return ; -if (worker->flags &IO_WORKER_F_RUNNING ) +if (test_bit (IO_WORKER_F_RUNNING , &worker->flags))return ; - worker->flags |=IO_WORKER_F_RUNNING ; +set_bit (IO_WORKER_F_RUNNING , &worker->flags);io_wq_inc_running (worker); }
@@ -716,12 +717,12 @@ void io_wq_worker_sleeping(struct task_struct *tsk)if (!worker)return ; -if (!(worker->flags &IO_WORKER_F_UP )) +if (!test_bit (IO_WORKER_F_UP , &worker->flags))return ; -if (!(worker->flags &IO_WORKER_F_RUNNING )) +if (!test_bit (IO_WORKER_F_RUNNING , &worker->flags))return ; - worker->flags &= ~IO_WORKER_F_RUNNING ; +clear_bit (IO_WORKER_F_RUNNING , &worker->flags);io_wq_dec_running (worker); }
@@ -735,7 +736,7 @@ static void io_init_new_worker(struct io_wq *wq, struct io_worker *worker,raw_spin_lock (&wq->lock);hlist_nulls_add_head_rcu (&worker->nulls_node, &wq->free_list);list_add_tail_rcu (&worker->all_list, &wq->all_list); - worker->flags |=IO_WORKER_F_FREE ; +set_bit (IO_WORKER_F_FREE , &worker->flags);raw_spin_unlock (&wq->lock);wake_up_new_task (tsk); }
@@ -841,7 +842,7 @@ static bool create_io_worker(struct io_wq *wq, int index)init_completion (&worker->ref_done);if (index ==IO_WQ_ACCT_BOUND ) - worker->flags |=IO_WORKER_F_BOUND ; +set_bit (IO_WORKER_F_BOUND , &worker->flags); tsk =create_io_thread (io_wq_worker, worker,NUMA_NO_NODE );if (!IS_ERR (tsk)) {
@@ -927,8 +928,8 @@ static bool io_wq_work_match_item(struct io_wq_work *work, void *data)void io_wq_enqueue (struct io_wq *wq,struct io_wq_work *work) {struct io_wq_acct *acct =io_work_get_acct (wq, work); +unsigned long work_flags = work->flags;struct io_cb_cancel_data match; -unsigned work_flags = work->flags;bool do_create;/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 133/267 io_uring/io-wq: avoid garbage value of match in io_wq_enqueue()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Su Hui <[email protected]>
[ Upstream commit 91215f70ea8541e9011c0b48f8b59b9e0ce6953b ]
Clang static checker (scan-build) warning:
o_uring/io-wq.c:line 1051, column 3
The expression is an uninitialized value. The computed value will also be garbage.
'match.nr_pending' is used in io_acct_cancel_pending_work(), but it is not fully initialized. Change the order of assignment for 'match' to fix this problem.
--- io_uring/io-wq.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
io_uring/io-wq.c +5 -5
@@ -929,7 +929,11 @@ void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work) {struct io_wq_acct *acct =io_work_get_acct (wq, work);unsigned long work_flags = work->flags; -struct io_cb_cancel_data match; +struct io_cb_cancel_data match = { + .fn = io_wq_work_match_item, + .data = work, + .cancel_all = false, + };bool do_create;/*
@@ -967,10 +971,6 @@ void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work)raw_spin_unlock (&wq->lock);/* fatal condition, failed to create the first worker */ - match.fn = io_wq_work_match_item, - match.data = work, - match.cancel_all = false, -io_acct_cancel_pending_work (wq, acct, &match); } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 134/267 HID: logitech-dj: Fix memory leak in logi_dj_recv_switch_to_dj_mode()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: José Expósito <[email protected]>
[ Upstream commit ce3af2ee95170b7d9e15fff6e500d67deab1e7b3 ]
Fix a memory leak on logi_dj_recv_send_report() error path.
--- drivers/hid/hid-logitech-dj.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/hid/hid-logitech-dj.c +3 -1
@@ -1284,8 +1284,10 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,*/ msleep (50 ); -if (retval) +if (retval) { +kfree (dj_report);return retval; + } }/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 135/267 drm/vmwgfx: Refactor drm connector probing for display modes
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Martin Krastev <[email protected]>
[ Upstream commit 935f795045a6f9b13d28d46ebdad04bfea8750dd ]
Implement drm_connector_helper_funcs.mode_valid and .get_modes, replacing custom drm_connector_funcs.fill_modes code with drm_helper_probe_single_connector_modes; for STDU, LDU & SOU display units.
Stable-dep-of: 426826933109 ("drm/vmwgfx: Filter modes which exceed graphics memory")
--- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 272 +++++++++------------------ drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 6 +- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 5 +- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 5 +- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 4 +- 5 files changed, 101 insertions(+), 191 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +89 -183
@@ -35,6 +35,7 @@#include <drm/drm_fourcc.h> #include <drm/drm_rect.h> #include <drm/drm_sysfs.h> +#include <drm/drm_edid.h> void vmw_du_cleanup (struct vmw_display_unit *du) {
@@ -2279,107 +2280,6 @@ vmw_du_connector_detect(struct drm_connector *connector, bool force) connector_status_connected : connector_status_disconnected); } -static struct drm_display_mode vmw_kms_connector_builtin[] = { -/* 640x480@60Hz */ - {DRM_MODE ("640x480" ,DRM_MODE_TYPE_DRIVER ,25175 ,640 ,656 , -752 ,800 ,0 ,480 ,489 ,492 ,525 ,0 , -DRM_MODE_FLAG_NHSYNC |DRM_MODE_FLAG_NVSYNC ) }, -/* 800x600@60Hz */ - {DRM_MODE ("800x600" ,DRM_MODE_TYPE_DRIVER ,40000 ,800 ,840 , -968 ,1056 ,0 ,600 ,601 ,605 ,628 ,0 , -DRM_MODE_FLAG_PHSYNC |DRM_MODE_FLAG_PVSYNC ) }, -/* 1024x768@60Hz */ - {DRM_MODE ("1024x768" ,DRM_MODE_TYPE_DRIVER ,65000 ,1024 ,1048 , -1184 ,1344 ,0 ,768 ,771 ,777 ,806 ,0 , -DRM_MODE_FLAG_NHSYNC |DRM_MODE_FLAG_NVSYNC ) }, -/* 1152x864@75Hz */ - {DRM_MODE ("1152x864" ,DRM_MODE_TYPE_DRIVER ,108000 ,1152 ,1216 , -1344 ,1600 ,0 ,864 ,865 ,868 ,900 ,0 , -DRM_MODE_FLAG_PHSYNC |DRM_MODE_FLAG_PVSYNC ) }, -/* 1280x720@60Hz */ - {DRM_MODE ("1280x720" ,DRM_MODE_TYPE_DRIVER ,74500 ,1280 ,1344 , -1472 ,1664 ,0 ,720 ,723 ,728 ,748 ,0 , -DRM_MODE_FLAG_NHSYNC |DRM_MODE_FLAG_PVSYNC ) }, -/* 1280x768@60Hz */ - {DRM_MODE ("1280x768" ,DRM_MODE_TYPE_DRIVER ,79500 ,1280 ,1344 , -1472 ,1664 ,0 ,768 ,771 ,778 ,798 ,0 , -DRM_MODE_FLAG_NHSYNC |DRM_MODE_FLAG_PVSYNC ) }, -/* 1280x800@60Hz */ - {DRM_MODE ("1280x800" ,DRM_MODE_TYPE_DRIVER ,83500 ,1280 ,1352 , -1480 ,1680 ,0 ,800 ,803 ,809 ,831 ,0 , -DRM_MODE_FLAG_PHSYNC |DRM_MODE_FLAG_NVSYNC ) }, -/* 1280x960@60Hz */ - {DRM_MODE ("1280x960" ,DRM_MODE_TYPE_DRIVER ,108000 ,1280 ,1376 , -1488 ,1800 ,0 ,960 ,961 ,964 ,1000 ,0 , -DRM_MODE_FLAG_PHSYNC |DRM_MODE_FLAG_PVSYNC ) }, -/* 1280x1024@60Hz */ - {DRM_MODE ("1280x1024" ,DRM_MODE_TYPE_DRIVER ,108000 ,1280 ,1328 , -1440 ,1688 ,0 ,1024 ,1025 ,1028 ,1066 ,0 , -DRM_MODE_FLAG_PHSYNC |DRM_MODE_FLAG_PVSYNC ) }, -/* 1360x768@60Hz */ - {DRM_MODE ("1360x768" ,DRM_MODE_TYPE_DRIVER ,85500 ,1360 ,1424 , -1536 ,1792 ,0 ,768 ,771 ,777 ,795 ,0 , -DRM_MODE_FLAG_PHSYNC |DRM_MODE_FLAG_PVSYNC ) }, -/* 1440x1050@60Hz */ - {DRM_MODE ("1400x1050" ,DRM_MODE_TYPE_DRIVER ,121750 ,1400 ,1488 , -1632 ,1864 ,0 ,1050 ,1053 ,1057 ,1089 ,0 , -DRM_MODE_FLAG_NHSYNC |DRM_MODE_FLAG_PVSYNC ) }, -/* 1440x900@60Hz */ - {DRM_MODE ("1440x900" ,DRM_MODE_TYPE_DRIVER ,106500 ,1440 ,1520 , -1672 ,1904 ,0 ,900 ,903 ,909 ,934 ,0 , -DRM_MODE_FLAG_NHSYNC |DRM_MODE_FLAG_PVSYNC ) }, -/* 1600x1200@60Hz */ - {DRM_MODE ("1600x1200" ,DRM_MODE_TYPE_DRIVER ,162000 ,1600 ,1664 , -1856 ,2160 ,0 ,1200 ,1201 ,1204 ,1250 ,0 , -DRM_MODE_FLAG_PHSYNC |DRM_MODE_FLAG_PVSYNC ) }, -/* 1680x1050@60Hz */ - {DRM_MODE ("1680x1050" ,DRM_MODE_TYPE_DRIVER ,146250 ,1680 ,1784 , -1960 ,2240 ,0 ,1050 ,1053 ,1059 ,1089 ,0 , -DRM_MODE_FLAG_NHSYNC |DRM_MODE_FLAG_PVSYNC ) }, -/* 1792x1344@60Hz */ - {DRM_MODE ("1792x1344" ,DRM_MODE_TYPE_DRIVER ,204750 ,1792 ,1920 , -2120 ,2448 ,0 ,1344 ,1345 ,1348 ,1394 ,0 , -DRM_MODE_FLAG_NHSYNC |DRM_MODE_FLAG_PVSYNC ) }, -/* 1853x1392@60Hz */ - {DRM_MODE ("1856x1392" ,DRM_MODE_TYPE_DRIVER ,218250 ,1856 ,1952 , -2176 ,2528 ,0 ,1392 ,1393 ,1396 ,1439 ,0 , -DRM_MODE_FLAG_NHSYNC |DRM_MODE_FLAG_PVSYNC ) }, -/* 1920x1080@60Hz */ - {DRM_MODE ("1920x1080" ,DRM_MODE_TYPE_DRIVER ,173000 ,1920 ,2048 , -2248 ,2576 ,0 ,1080 ,1083 ,1088 ,1120 ,0 , -DRM_MODE_FLAG_NHSYNC |DRM_MODE_FLAG_PVSYNC ) }, -/* 1920x1200@60Hz */ - {DRM_MODE ("1920x1200" ,DRM_MODE_TYPE_DRIVER ,193250 ,1920 ,2056 , -2256 ,2592 ,0 ,1200 ,1203 ,1209 ,1245 ,0 , -DRM_MODE_FLAG_NHSYNC |DRM_MODE_FLAG_PVSYNC ) }, -/* 1920x1440@60Hz */ - {DRM_MODE ("1920x1440" ,DRM_MODE_TYPE_DRIVER ,234000 ,1920 ,2048 , -2256 ,2600 ,0 ,1440 ,1441 ,1444 ,1500 ,0 , -DRM_MODE_FLAG_NHSYNC |DRM_MODE_FLAG_PVSYNC ) }, -/* 2560x1440@60Hz */ - {DRM_MODE ("2560x1440" ,DRM_MODE_TYPE_DRIVER ,241500 ,2560 ,2608 , -2640 ,2720 ,0 ,1440 ,1443 ,1448 ,1481 ,0 , -DRM_MODE_FLAG_PHSYNC |DRM_MODE_FLAG_NVSYNC ) }, -/* 2560x1600@60Hz */ - {DRM_MODE ("2560x1600" ,DRM_MODE_TYPE_DRIVER ,348500 ,2560 ,2752 , -3032 ,3504 ,0 ,1600 ,1603 ,1609 ,1658 ,0 , -DRM_MODE_FLAG_NHSYNC |DRM_MODE_FLAG_PVSYNC ) }, -/* 2880x1800@60Hz */ - {DRM_MODE ("2880x1800" ,DRM_MODE_TYPE_DRIVER ,337500 ,2880 ,2928 , -2960 ,3040 ,0 ,1800 ,1803 ,1809 ,1852 ,0 , -DRM_MODE_FLAG_PHSYNC |DRM_MODE_FLAG_NVSYNC ) }, -/* 3840x2160@60Hz */ - {DRM_MODE ("3840x2160" ,DRM_MODE_TYPE_DRIVER ,533000 ,3840 ,3888 , -3920 ,4000 ,0 ,2160 ,2163 ,2168 ,2222 ,0 , -DRM_MODE_FLAG_PHSYNC |DRM_MODE_FLAG_NVSYNC ) }, -/* 3840x2400@60Hz */ - {DRM_MODE ("3840x2400" ,DRM_MODE_TYPE_DRIVER ,592250 ,3840 ,3888 , -3920 ,4000 ,0 ,2400 ,2403 ,2409 ,2469 ,0 , -DRM_MODE_FLAG_PHSYNC |DRM_MODE_FLAG_NVSYNC ) }, -/* Terminate */ - {DRM_MODE ("" ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ) }, -}; -/** * vmw_guess_mode_timing - Provide fake timings for a * 60Hz vrefresh mode.
@@ -2401,88 +2301,6 @@ void vmw_guess_mode_timing(struct drm_display_mode *mode) } -int vmw_du_connector_fill_modes (struct drm_connector *connector, -uint32_t max_width,uint32_t max_height) -{ -struct vmw_display_unit *du =vmw_connector_to_du (connector); -struct drm_device *dev = connector->dev; -struct vmw_private *dev_priv =vmw_priv (dev); -struct drm_display_mode *mode =NULL ; -struct drm_display_mode *bmode; -struct drm_display_mode prefmode = {DRM_MODE ("preferred" , -DRM_MODE_TYPE_DRIVER |DRM_MODE_TYPE_PREFERRED , -0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , -DRM_MODE_FLAG_NHSYNC |DRM_MODE_FLAG_PVSYNC ) - }; -int i; -u32 assumed_bpp =4 ; - -if (dev_priv->assume_16bpp) - assumed_bpp =2 ; - - max_width =min (max_width, dev_priv->texture_max_width); - max_height =min (max_height, dev_priv->texture_max_height); - -/* -* For STDU extra limit for a mode on SVGA_REG_SCREENTARGET_MAX_WIDTH/ -* HEIGHT registers. -*/ -if (dev_priv->active_display_unit == vmw_du_screen_target) { - max_width =min (max_width, dev_priv->stdu_max_width); - max_height =min (max_height, dev_priv->stdu_max_height); - } - -/* Add preferred mode */ - mode =drm_mode_duplicate (dev, &prefmode); -if (!mode) -return 0 ; - mode->hdisplay = du->pref_width; - mode->vdisplay = du->pref_height; -vmw_guess_mode_timing (mode); -drm_mode_set_name (mode); - -if (vmw_kms_validate_mode_vram (dev_priv, - mode->hdisplay * assumed_bpp, - mode->vdisplay)) { -drm_mode_probed_add (connector, mode); - }else { -drm_mode_destroy (dev, mode); - mode =NULL ; - } - -if (du->pref_mode) { -list_del_init (&du->pref_mode->head); -drm_mode_destroy (dev, du->pref_mode); - } - -/* mode might be null here, this is intended */ - du->pref_mode = mode; - -for (i =0 ; vmw_kms_connector_builtin[i].type !=0 ; i++) { - bmode = &vmw_kms_connector_builtin[i]; -if (bmode->hdisplay > max_width || - bmode->vdisplay > max_height) -continue ; - -if (!vmw_kms_validate_mode_vram (dev_priv, - bmode->hdisplay * assumed_bpp, - bmode->vdisplay)) -continue ; - - mode =drm_mode_duplicate (dev, bmode); -if (!mode) -return 0 ; - -drm_mode_probed_add (connector, mode); - } - -drm_connector_list_update (connector); -/* Move the prefered mode first, help apps pick the right mode. */ -drm_mode_sort (&connector->modes); - -return 1 ; -} -/** * vmw_kms_update_layout_ioctl - Handler for DRM_VMW_UPDATE_LAYOUT ioctl * @dev: drm device for the ioctl
@@ -3023,3 +2841,91 @@ int vmw_du_helper_plane_update(struct vmw_du_update_plane *update)vmw_validation_unref_lists (&val_ctx);return ret; } + +/** +* vmw_connector_mode_valid - implements drm_connector_helper_funcs.mode_valid callback +* +* @connector: the drm connector, part of a DU container +* @mode: drm mode to check +* +* Returns MODE_OK on success, or a drm_mode_status error code. +*/ +enum drm_mode_status vmw_connector_mode_valid (struct drm_connector *connector, +struct drm_display_mode *mode) +{ +struct drm_device *dev = connector->dev; +struct vmw_private *dev_priv =vmw_priv (dev); +u32 max_width = dev_priv->texture_max_width; +u32 max_height = dev_priv->texture_max_height; +u32 assumed_cpp =4 ; + +if (dev_priv->assume_16bpp) + assumed_cpp =2 ; + +if (dev_priv->active_display_unit == vmw_du_screen_target) { + max_width =min (dev_priv->stdu_max_width, max_width); + max_height =min (dev_priv->stdu_max_height, max_height); + } + +if (max_width < mode->hdisplay) +return MODE_BAD_HVALUE ; + +if (max_height < mode->vdisplay) +return MODE_BAD_VVALUE ; + +if (!vmw_kms_validate_mode_vram (dev_priv, + mode->hdisplay * assumed_cpp, + mode->vdisplay)) +return MODE_MEM ; + +return MODE_OK ; +} + +/** +* vmw_connector_get_modes - implements drm_connector_helper_funcs.get_modes callback +* +* @connector: the drm connector, part of a DU container +* +* Returns the number of added modes. +*/ +int vmw_connector_get_modes (struct drm_connector *connector) +{ +struct vmw_display_unit *du =vmw_connector_to_du (connector); +struct drm_device *dev = connector->dev; +struct vmw_private *dev_priv =vmw_priv (dev); +struct drm_display_mode *mode =NULL ; +struct drm_display_mode prefmode = {DRM_MODE ("preferred" , +DRM_MODE_TYPE_DRIVER |DRM_MODE_TYPE_PREFERRED , +0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , +DRM_MODE_FLAG_NHSYNC |DRM_MODE_FLAG_PVSYNC ) + }; +u32 max_width; +u32 max_height; +u32 num_modes; + +/* Add preferred mode */ + mode =drm_mode_duplicate (dev, &prefmode); +if (!mode) +return 0 ; + + mode->hdisplay = du->pref_width; + mode->vdisplay = du->pref_height; +vmw_guess_mode_timing (mode); +drm_mode_set_name (mode); + +drm_mode_probed_add (connector, mode); +drm_dbg_kms (dev,"preferred mode " DRM_MODE_FMT "\n" ,DRM_MODE_ARG (mode)); + +/* Probe connector for all modes not exceeding our geom limits */ + max_width = dev_priv->texture_max_width; + max_height = dev_priv->texture_max_height; + +if (dev_priv->active_display_unit == vmw_du_screen_target) { + max_width =min (dev_priv->stdu_max_width, max_width); + max_height =min (dev_priv->stdu_max_height, max_height); + } + + num_modes =1 +drm_add_modes_noedid (connector, max_width, max_height); + +return num_modes; +}
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +3 -3
@@ -378,7 +378,6 @@ struct vmw_display_unit {unsigned pref_width;unsigned pref_height;bool pref_active; -struct drm_display_mode *pref_mode;/* * Gui positioning
@@ -428,8 +427,6 @@ void vmw_du_connector_save(struct drm_connector *connector);void vmw_du_connector_restore (struct drm_connector *connector);enum drm_connector_status vmw_du_connector_detect (struct drm_connector *connector,bool force); -int vmw_du_connector_fill_modes (struct drm_connector *connector, -uint32_t max_width,uint32_t max_height); int vmw_kms_helper_dirty(struct vmw_private *dev_priv, struct vmw_framebuffer *framebuffer, const struct drm_clip_rect *clips,
@@ -438,6 +435,9 @@ int vmw_kms_helper_dirty(struct vmw_private *dev_priv,int num_clips, int increment, struct vmw_kms_dirty *dirty); +enum drm_mode_status vmw_connector_mode_valid (struct drm_connector *connector, +struct drm_display_mode *mode); +int vmw_connector_get_modes (struct drm_connector *connector); void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv, struct drm_file *file_priv,
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +3 -2
@@ -304,7 +304,7 @@ static void vmw_ldu_connector_destroy(struct drm_connector *connector)static const struct drm_connector_funcs vmw_legacy_connector_funcs = { .dpms = vmw_du_connector_dpms, .detect = vmw_du_connector_detect, - .fill_modes = vmw_du_connector_fill_modes, + .fill_modes = drm_helper_probe_single_connector_modes, .destroy = vmw_ldu_connector_destroy, .reset = vmw_du_connector_reset, .atomic_duplicate_state = vmw_du_connector_duplicate_state,
@@ -313,6 +313,8 @@ static const struct drm_connector_funcs vmw_legacy_connector_funcs = {static const struct drm_connector_helper_funcs vmw_ldu_connector_helper_funcs = { + .get_modes = vmw_connector_get_modes, + .mode_valid = vmw_connector_mode_valid }; static int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv,
@@ -449,7 +451,6 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) ldu->base.pref_active = (unit ==0 ); ldu->base.pref_width = dev_priv->initial_width; ldu->base.pref_height = dev_priv->initial_height; - ldu->base.pref_mode =NULL ;/* * Remove this after enabling atomic because property values can
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +3 -2
@@ -347,7 +347,7 @@ static void vmw_sou_connector_destroy(struct drm_connector *connector)static const struct drm_connector_funcs vmw_sou_connector_funcs = { .dpms = vmw_du_connector_dpms, .detect = vmw_du_connector_detect, - .fill_modes = vmw_du_connector_fill_modes, + .fill_modes = drm_helper_probe_single_connector_modes, .destroy = vmw_sou_connector_destroy, .reset = vmw_du_connector_reset, .atomic_duplicate_state = vmw_du_connector_duplicate_state,
@@ -357,6 +357,8 @@ static const struct drm_connector_funcs vmw_sou_connector_funcs = {static const struct drm_connector_helper_funcs vmw_sou_connector_helper_funcs = { + .get_modes = vmw_connector_get_modes, + .mode_valid = vmw_connector_mode_valid };
@@ -826,7 +828,6 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) sou->base.pref_active = (unit ==0 ); sou->base.pref_width = dev_priv->initial_width; sou->base.pref_height = dev_priv->initial_height; - sou->base.pref_mode =NULL ;/* * Remove this after enabling atomic because property values can
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +3 -1
@@ -830,7 +830,7 @@ static void vmw_stdu_connector_destroy(struct drm_connector *connector)static const struct drm_connector_funcs vmw_stdu_connector_funcs = { .dpms = vmw_du_connector_dpms, .detect = vmw_du_connector_detect, - .fill_modes = vmw_du_connector_fill_modes, + .fill_modes = drm_helper_probe_single_connector_modes, .destroy = vmw_stdu_connector_destroy, .reset = vmw_du_connector_reset, .atomic_duplicate_state = vmw_du_connector_duplicate_state,
@@ -840,6 +840,8 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {static const struct drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = { + .get_modes = vmw_connector_get_modes, + .mode_valid = vmw_connector_mode_valid };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 136/267 drm/vmwgfx: Filter modes which exceed graphics memory
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Forbes <[email protected]>
[ Upstream commit 426826933109093503e7ef15d49348fc5ab505fe ]
SVGA requires individual surfaces to fit within graphics memory (max_mob_pages) which means that modes with a final buffer size that would exceed graphics memory must be pruned otherwise creation will fail.
Additionally llvmpipe requires its buffer height and width to be a multiple of its tile size which is 64. As a result we have to anticipate that llvmpipe will round up the mode size passed to it by the compositor when it creates buffers and filter modes where this rounding exceeds graphics memory.
This fixes an issue where VMs with low graphics memory (< 64MiB) configured with high resolution mode boot to a black screen because surface creation fails.
--- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 45 ++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +43 -2
@@ -41,7 +41,14 @@#define vmw_connector_to_stdu (x) \ container_of(x, struct vmw_screen_target_display_unit, base.connector) - +/* +* Some renderers such as llvmpipe will align the width and height of their +* buffers to match their tile size. We need to keep this in mind when exposing +* modes to userspace so that this possible over-allocation will not exceed +* graphics memory. 64x64 pixels seems to be a reasonable upper bound for the +* tile size of current renderers. +*/ +#define GPU_TILE_SIZE 64enum stdu_content_type {SAME_AS_DISPLAY =0 ,
@@ -825,7 +832,41 @@ static void vmw_stdu_connector_destroy(struct drm_connector *connector)vmw_stdu_destroy (vmw_connector_to_stdu (connector)); } +static enum drm_mode_status +vmw_stdu_connector_mode_valid (struct drm_connector *connector, +struct drm_display_mode *mode) +{ +enum drm_mode_status ret; +struct drm_device *dev = connector->dev; +struct vmw_private *dev_priv =vmw_priv (dev); +u64 assumed_cpp = dev_priv->assume_16bpp ?2 :4 ; +/* Align width and height to account for GPU tile over-alignment */ +u64 required_mem =ALIGN (mode->hdisplay,GPU_TILE_SIZE ) * +ALIGN (mode->vdisplay,GPU_TILE_SIZE ) * + assumed_cpp; + required_mem =ALIGN (required_mem,PAGE_SIZE ); + + ret =drm_mode_validate_size (mode, dev_priv->stdu_max_width, + dev_priv->stdu_max_height); +if (ret !=MODE_OK ) +return ret; + ret =drm_mode_validate_size (mode, dev_priv->texture_max_width, + dev_priv->texture_max_height); +if (ret !=MODE_OK ) +return ret; + +if (required_mem > dev_priv->max_primary_mem) +return MODE_MEM ; + +if (required_mem > dev_priv->max_mob_pages *PAGE_SIZE ) +return MODE_MEM ; + +if (required_mem > dev_priv->max_mob_size) +return MODE_MEM ; + +return MODE_OK ; +}static const struct drm_connector_funcs vmw_stdu_connector_funcs = { .dpms = vmw_du_connector_dpms,
@@ -841,7 +882,7 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {static const struct drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = { .get_modes = vmw_connector_get_modes, - .mode_valid = vmw_connector_mode_valid + .mode_valid = vmw_stdu_connector_mode_valid };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 137/267 drm/vmwgfx: 3D disabled should not effect STDU memory limits
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Forbes <[email protected]>
[ Upstream commit fb5e19d2dd03eb995ccd468d599b2337f7f66555 ]
This limit became a hard cap starting with the change referenced below. Surface creation on the device will fail if the requested size is larger than this limit so altering the value arbitrarily will expose modes that are too large for the device's hard limits.
--- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 7 ------- 1 file changed, 7 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +0 -7
@@ -956,13 +956,6 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)vmw_read (dev_priv,SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB ); -/* -* Workaround for low memory 2D VMs to compensate for the -* allocation taken by fbdev -*/ -if (!(dev_priv->capabilities &SVGA_CAP_3D )) - mem_size *=3 ; - dev_priv->max_mob_pages = mem_size *1024 /PAGE_SIZE ; dev_priv->max_primary_mem =vmw_read (dev_priv,SVGA_REG_MAX_PRIMARY_MEM );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 138/267 drm/vmwgfx: Remove STDU logic from generic mode_valid function
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Forbes <[email protected]>
[ Upstream commit dde1de06bd7248fd83c4ce5cf0dbe9e4e95bbb91 ]
STDU has its own mode_valid function now so this logic can be removed from the generic version.
--- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 3 --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 26 +++++++++----------------- 2 files changed, 9 insertions(+), 20 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +0 -3
@@ -1067,9 +1067,6 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,int vmw_kms_write_svga (struct vmw_private *vmw_priv,unsigned width,unsigned height,unsigned pitch,unsigned bpp,unsigned depth); -bool vmw_kms_validate_mode_vram (struct vmw_private *dev_priv, -uint32_t pitch, -uint32_t height); int vmw_kms_present(struct vmw_private *dev_priv, struct drm_file *file_priv, struct vmw_framebuffer *vfb,
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +9 -17
@@ -2151,13 +2151,12 @@ int vmw_kms_write_svga(struct vmw_private *vmw_priv,return 0 ; } +static bool vmw_kms_validate_mode_vram (struct vmw_private *dev_priv, -uint32_t pitch, -uint32_t height) +u64 pitch, +u64 height) { -return ((u64 ) pitch * (u64 ) height) < (u64) - ((dev_priv->active_display_unit == vmw_du_screen_target) ? - dev_priv->max_primary_mem : dev_priv->vram_size); +return (pitch * height) < (u64 )dev_priv->vram_size; }/**
@@ -2853,25 +2852,18 @@ int vmw_du_helper_plane_update(struct vmw_du_update_plane *update) enum drm_mode_status vmw_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { + enum drm_mode_status ret; struct drm_device *dev = connector->dev; struct vmw_private *dev_priv = vmw_priv(dev); - u32 max_width = dev_priv->texture_max_width; - u32 max_height = dev_priv->texture_max_height; u32 assumed_cpp = 4; if (dev_priv->assume_16bpp) assumed_cpp = 2; - if (dev_priv->active_display_unit == vmw_du_screen_target) { - max_width = min(dev_priv->stdu_max_width, max_width); - max_height = min(dev_priv->stdu_max_height, max_height); - } - - if (max_width < mode->hdisplay) - return MODE_BAD_HVALUE; - - if (max_height < mode->vdisplay) - return MODE_BAD_VVALUE; + ret = drm_mode_validate_size(mode, dev_priv->texture_max_width, + dev_priv->texture_max_height); + if (ret != MODE_OK) + return ret; if (!vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * assumed_cpp,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 139/267 drm/vmwgfx: Dont memcmp equivalent pointers
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Forbes <[email protected]>
[ Upstream commit 5703fc058efdafcdd6b70776ee562478f0753acb ]
These pointers are frequently the same and memcmp does not compare the pointers before comparing their contents so this was wasting cycles comparing 16 KiB of memory which will always be equal.
--- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +1 -1
@@ -216,7 +216,7 @@ static bool vmw_du_cursor_plane_has_changed(struct vmw_plane_state *old_vps, new_image =vmw_du_cursor_plane_acquire_image (new_vps); changed = false; -if (old_image && new_image) +if (old_image && new_image && old_image != new_image) changed =memcmp (old_image, new_image, size) !=0 ;return changed;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 140/267 af_unix: Annotate data-race of sk->sk_state in unix_accept().
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 1b536948e805aab61a48c5aa5db10c9afee880bd ]
Once sk->sk_state is changed to TCP_LISTEN, it never changes.
unix_accept() takes the advantage and reads sk->sk_state without holding unix_state_lock().
Let's use READ_ONCE() there.
--- net/unix/af_unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/unix/af_unix.c +1 -1
@@ -1710,7 +1710,7 @@ static int unix_accept(struct socket *so goto out; err = -EINVAL ; -if (sk->sk_state !=TCP_LISTEN ) +if (READ_ONCE (sk->sk_state) !=TCP_LISTEN ) goto out;/* If socket state is TCP_LISTEN it cannot change (for now...),
Greg Kroah-Hartman
maintainerPATCH 141/267 modpost: do not warn about missing MODULE_DESCRIPTION() for vmlinux.o
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masahiro Yamada <[email protected]>
[ Upstream commit 9185afeac2a3dcce8300a5684291a43c2838cfd6 ]
Building with W=1 incorrectly emits the following warning:
WARNING: modpost: missing MODULE_DESCRIPTION() in vmlinux.o
This check should apply only to modules.
--- scripts/mod/modpost.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
scripts/mod/modpost.c +3 -2
@@ -1684,10 +1684,11 @@ static void read_symbols(const char *modname) namespace =get_next_modinfo (&info,"import_ns" , namespace); } + +if (extra_warn && !get_modinfo (&info,"description" )) +warn ("missing MODULE_DESCRIPTION() in %s\n" , modname); } -if (extra_warn && !get_modinfo (&info,"description" )) -warn ("missing MODULE_DESCRIPTION() in %s\n" , modname);for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { symname =remove_dot (info.strtab + sym->st_name);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 142/267 net: sfp: Always call `sfp_sm_mod_remove()` on remove
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Csókás, Bence <[email protected]>
[ Upstream commit e96b2933152fd87b6a41765b2f58b158fde855b6 ]
If the module is in SFP_MOD_ERROR, sfp_sm_mod_remove() will not be run. As a consequence, sfp_hwmon_remove() is not getting run either, leaving a stale hwmon device behind. sfp_sm_mod_remove() itself checks sfp->sm_mod_state anyways, so this check was not really needed in the first place.
--- drivers/net/phy/sfp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/phy/sfp.c +1 -2
@@ -2394,8 +2394,7 @@ static void sfp_sm_module(struct sfp *sfp, unsigned int event)/* Handle remove event globally, it resets this state machine */ if (event ==SFP_E_REMOVE ) { -if (sfp->sm_mod_state >SFP_MOD_PROBE ) -sfp_sm_mod_remove (sfp); +sfp_sm_mod_remove (sfp);sfp_sm_mod_next (sfp,SFP_MOD_EMPTY ,0 );return ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 143/267 net: hns3: fix kernel crash problem in concurrent scenario
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yonglong Liu <[email protected]>
[ Upstream commit 12cda920212a49fa22d9e8b9492ac4ea013310a4 ]
When link status change, the nic driver need to notify the roce driver to handle this event, but at this time, the roce driver may uninit, then cause kernel crash.
To fix the problem, when link status change, need to check whether the roce registered, and when uninit, need to wait link update finish.
--- .../hisilicon/hns3/hns3pf/hclge_main.c | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +16 -5
@@ -3031,9 +3031,7 @@ static void hclge_push_link_status(struct hclge_dev *hdev)static void hclge_update_link_status (struct hclge_dev *hdev) { -struct hnae3_handle *rhandle = &hdev->vport[0 ].roce;struct hnae3_handle *handle = &hdev->vport[0 ].nic; -struct hnae3_client *rclient = hdev->roce_client;struct hnae3_client *client = hdev->nic_client;int state;int ret;
@@ -3057,8 +3055,15 @@ static void hclge_update_link_status(struct hclge_dev *hdev) client->ops->link_status_change (handle, state);hclge_config_mac_tnl_int (hdev, state); -if (rclient && rclient->ops->link_status_change) - rclient->ops->link_status_change (rhandle, state); + +if (test_bit (HCLGE_STATE_ROCE_REGISTERED , &hdev->state)) { +struct hnae3_handle *rhandle = &hdev->vport[0 ].roce; +struct hnae3_client *rclient = hdev->roce_client; + +if (rclient && rclient->ops->link_status_change) + rclient->ops->link_status_change (rhandle, + state); + }hclge_push_link_status (hdev); }
@@ -11233,6 +11238,12 @@ static int hclge_init_client_instance(struct hnae3_client *client,return ret; } +static bool hclge_uninit_need_wait (struct hclge_dev *hdev) +{ +return test_bit (HCLGE_STATE_RST_HANDLING , &hdev->state) || +test_bit (HCLGE_STATE_LINK_UPDATING , &hdev->state); +} +static void hclge_uninit_client_instance (struct hnae3_client *client,struct hnae3_ae_dev *ae_dev) {
@@ -11241,7 +11252,7 @@ static void hclge_uninit_client_instance(struct hnae3_client *client,if (hdev->roce_client) {clear_bit (HCLGE_STATE_ROCE_REGISTERED , &hdev->state); -while (test_bit (HCLGE_STATE_RST_HANDLING , &hdev->state)) +while (hclge_uninit_need_wait (hdev))msleep (HCLGE_WAIT_RESET_DONE ); hdev->roce_client->ops->uninit_instance (&vport->roce,0 );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 144/267 net: hns3: add cond_resched() to hns3 ring buffer init process
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jie Wang <[email protected]>
[ Upstream commit 968fde83841a8c23558dfbd0a0c69d636db52b55 ]
Currently hns3 ring buffer init process would hold cpu too long with big Tx/Rx ring depth. This could cause soft lockup.
So this patch adds cond_resched() to the process. Then cpu can break to run other tasks instead of busy looping.
--- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 4 ++++ drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 2 ++ 2 files changed, 6 insertions(+)
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +4 -0
@@ -3539,6 +3539,9 @@ static int hns3_alloc_ring_buffers(struct hns3_enet_ring *ring) ret =hns3_alloc_and_attach_buffer (ring, i);if (ret) goto out_buffer_fail; + +if (!(i %HNS3_RESCHED_BD_NUM )) +cond_resched (); }return 0 ;
@@ -5112,6 +5115,7 @@ int hns3_init_all_ring(struct hns3_nic_priv *priv) }u64_stats_init (&priv->ring[i].syncp); +cond_resched (); }return 0 ;
drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +2 -0
@@ -214,6 +214,8 @@ enum hns3_nic_state {#define HNS3_CQ_MODE_EQE 1U#define HNS3_CQ_MODE_CQE 0U +#define HNS3_RESCHED_BD_NUM 1024 +enum hns3_pkt_l2t_type {HNS3_L2_TYPE_UNICAST ,HNS3_L2_TYPE_MULTICAST ,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 145/267 liquidio: Adjust a NULL pointer handling path in lio_vf_rep_copy_packet
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksandr Mishin <[email protected]>
[ Upstream commit c44711b78608c98a3e6b49ce91678cd0917d5349 ]
In lio_vf_rep_copy_packet() pg_info->page is compared to a NULL value, but then it is unconditionally passed to skb_add_rx_frag() which looks strange and could lead to null pointer dereference.
lio_vf_rep_copy_packet() call trace looks like:
octeon_droq_process_packets
octeon_droq_fast_process_packets
octeon_droq_dispatch_pkt
octeon_create_recv_info
...search in the dispatch_list...
->disp_fn(rdisp->rinfo, ...)
lio_vf_rep_pkt_recv(struct octeon_recv_info *recv_info, ...)
In this path there is no code which sets pg_info->page to NULL. So this check looks unneeded and doesn't solve potential problem. But I guess the author had reason to add a check and I have no such card and can't do real test.
In addition, the code in the function liquidio_push_packet() in liquidio/lio_core.c does exactly the same.
Based on this, I consider the most acceptable compromise solution to adjust this issue by moving skb_add_rx_frag() into conditional scope.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c +5 -6
@@ -272,13 +272,12 @@ lio_vf_rep_copy_packet(struct octeon_device *oct, pg_info->page_offset;memcpy (skb->data, va,MIN_SKB_SIZE );skb_put (skb,MIN_SKB_SIZE ); +skb_add_rx_frag (skb,skb_shinfo (skb)->nr_frags, + pg_info->page, + pg_info->page_offset +MIN_SKB_SIZE , + len -MIN_SKB_SIZE , +LIO_RXBUFFER_SZ ); } - -skb_add_rx_frag (skb,skb_shinfo (skb)->nr_frags, - pg_info->page, - pg_info->page_offset +MIN_SKB_SIZE , - len -MIN_SKB_SIZE , -LIO_RXBUFFER_SZ ); }else {struct octeon_skb_page_info *pg_info = ((struct octeon_skb_page_info *)(skb->cb));
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 146/267 net: stmmac: dwmac-qcom-ethqos: Configure host DMA width
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sagar Cheluvegowda <[email protected]>
[ Upstream commit 0579f27249047006a818e463ee66a6c314d04cea ]
Commit 070246e4674b ("net: stmmac: Fix for mismatched host/device DMA address width") added support in the stmmac driver for platform drivers to indicate the host DMA width, but left it up to authors of the specific platforms to indicate if their width differed from the addr64 register read from the MAC itself.
Qualcomm's EMAC4 integration supports only up to 36 bit width (as opposed to the addr64 register indicating 40 bit width). Let's indicate that in the platform driver to avoid a scenario where the driver will allocate descriptors of size that is supported by the CPU which in our case is 36 bit, but as the addr64 register is still capable of 40 bits the device will use two descriptors as one address.
--- drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +4 -0
@@ -93,6 +93,7 @@ struct ethqos_emac_driver_data {bool has_emac_ge_3;const char *link_clk_name;bool has_integrated_pcs; +u32 dma_addr_width;struct dwmac4_addrs dwmac4_addrs; };
@@ -272,6 +273,7 @@ static const struct ethqos_emac_driver_data emac_v4_0_0_data = { .has_emac_ge_3 = true, .link_clk_name = "phyaux", .has_integrated_pcs = true, + .dma_addr_width = 36, .dwmac4_addrs = { .dma_chan = 0x00008100, .dma_chan_offset = 0x1000,
@@ -816,6 +818,8 @@ static int qcom_ethqos_probe(struct platform_device *pdev) plat_dat->flags |=STMMAC_FLAG_RX_CLK_RUNS_IN_LPI ;if (data->has_integrated_pcs) plat_dat->flags |=STMMAC_FLAG_HAS_INTEGRATED_PCS ; +if (data->dma_addr_width) + plat_dat->host_dma_width = data->dma_addr_width;if (ethqos->serdes_phy) { plat_dat->serdes_powerup = qcom_ethqos_serdes_powerup;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 147/267 drm/komeda: check for error-valued pointer
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amjad Ouled-Ameur <[email protected]>
[ Upstream commit b880018edd3a577e50366338194dee9b899947e0 ]
komeda_pipeline_get_state() may return an error-valued pointer, thus check the pointer for negative or null value before dereferencing.
--- drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c +1 -1
@@ -259,7 +259,7 @@ komeda_component_get_avail_scaler(struct komeda_component *c,u32 avail_scalers; pipe_st =komeda_pipeline_get_state (c->pipeline, state); -if (!pipe_st) +if (IS_ERR_OR_NULL (pipe_st))return NULL ; avail_scalers = (pipe_st->active_comps & KOMEDA_PIPELINE_SCALERS) ^
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 148/267 drm/bridge/panel: Fix runtime warning on panel bridge release
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adam Miotk <[email protected]>
[ Upstream commit ce62600c4dbee8d43b02277669dd91785a9b81d9 ]
Device managed panel bridge wrappers are created by calling to drm_panel_bridge_add_typed() and registering a release handler for clean-up when the device gets unbound.
Since the memory for this bridge is also managed and linked to the panel device, the release function should not try to free that memory. Moreover, the call to devm_kfree() inside drm_panel_bridge_remove() will fail in this case and emit a warning because the panel bridge resource is no longer on the device resources list (it has been removed from there before the call to release handlers).
--- drivers/gpu/drm/bridge/panel.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/gpu/drm/bridge/panel.c +5 -2
@@ -360,9 +360,12 @@ EXPORT_SYMBOL(drm_panel_bridge_set_orientation);static void devm_drm_panel_bridge_release (struct device *dev,void *res) { -struct drm_bridge **bridge = res; +struct drm_bridge *bridge = *(struct drm_bridge **)res; -drm_panel_bridge_remove (*bridge); +if (!bridge) +return ; + +drm_bridge_remove (bridge); }/**
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 149/267 tcp: fix race in tcp_v6_syn_recv_sock()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit d37fe4255abe8e7b419b90c5847e8ec2b8debb08 ]
tcp_v6_syn_recv_sock() calls ip6_dst_store() before inet_sk(newsk)->pinet6 has been set up.
This means ip6_dst_store() writes over the parent (listener) np->dst_cookie.
This is racy because multiple threads could share the same parent and their final np->dst_cookie could be wrong.
Move ip6_dst_store() call after inet_sk(newsk)->pinet6 has been changed and after the copy of parent ipv6_pinfo.
--- net/ipv6/tcp_ipv6.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/ipv6/tcp_ipv6.c +2 -1
@@ -1287,7 +1287,6 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff **/ newsk->sk_gso_type =SKB_GSO_TCPV6 ; -ip6_dst_store (newsk, dst,NULL ,NULL );inet6_sk_rx_dst_set (newsk, skb);inet_sk (newsk)->pinet6 =tcp_inet6_sk (newsk);
@@ -1298,6 +1297,8 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *memcpy (newnp, np,sizeof (struct ipv6_pinfo )); +ip6_dst_store (newsk, dst,NULL ,NULL ); + newsk->sk_v6_daddr = ireq->ir_v6_rmt_addr; newnp->saddr = ireq->ir_v6_loc_addr; newsk->sk_v6_rcv_saddr = ireq->ir_v6_loc_addr;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 150/267 net dsa: qca8k: fix usages of device_get_named_child_node()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
[ Upstream commit d029edefed39647c797c2710aedd9d31f84c069e ]
The documentation for device_get_named_child_node() mentions this important point:
"
The caller is responsible for calling fwnode_handle_put() on the returned fwnode pointer.
"
Add fwnode_handle_put() to avoid leaked references.
--- drivers/net/dsa/qca/qca8k-leds.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/net/dsa/qca/qca8k-leds.c +10 -2
@@ -431,8 +431,11 @@ qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int p init_data.devname_mandatory = true; init_data.devicename =kasprintf (GFP_KERNEL ,"%s:0%d" , ds->slave_mii_bus->id, port_num); -if (!init_data.devicename) +if (!init_data.devicename) { +fwnode_handle_put (led); +fwnode_handle_put (leds);return -ENOMEM ; + } ret =devm_led_classdev_register_ext (priv->dev, &port_led->cdev, &init_data);if (ret)
@@ -441,6 +444,7 @@ qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int pkfree (init_data.devicename); } +fwnode_handle_put (leds);return 0 ; }
@@ -471,9 +475,13 @@ qca8k_setup_led_ctrl(struct qca8k_priv *priv)* the correct port for LED setup. */ ret =qca8k_parse_port_leds (priv, port,qca8k_port_to_phy (port_num)); -if (ret) +if (ret) { +fwnode_handle_put (port); +fwnode_handle_put (ports);return ret; + } } +fwnode_handle_put (ports);return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 151/267 geneve: Fix incorrect inner network header offset when innerprotoinherit is set
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gal Pressman <[email protected]>
[ Upstream commit c6ae073f5903f6c6439d0ac855836a4da5c0a701 ]
When innerprotoinherit is set, the tunneled packets do not have an inner Ethernet header.
Change 'maclen' to not always assume the header length is ETH_HLEN, as there might not be a MAC header.
This resolves issues with drivers (e.g. mlx5, in mlx5e_tx_tunnel_accel()) who rely on the skb inner network header offset to be correct, and use it for TX offloads.
--- drivers/net/geneve.c | 10 ++++++---- include/net/ip_tunnels.h | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-)
drivers/net/geneve.c +6 -4
@@ -915,6 +915,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,struct geneve_dev *geneve, const struct ip_tunnel_info *info) { + bool inner_proto_inherit = geneve->cfg.inner_proto_inherit;bool xnet = !net_eq (geneve->net,dev_net (geneve->dev));struct geneve_sock *gs4 =rcu_dereference (geneve->sock4);const struct ip_tunnel_key *key = &info->key;
@@ -926,7 +927,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,__be16 sport;int err; -if (!skb_vlan_inet_prepare (skb)) +if (!skb_vlan_inet_prepare (skb, inner_proto_inherit))return -EINVAL ; sport =udp_flow_src_port (geneve->net, skb,1 ,USHRT_MAX , true);
@@ -999,7 +1000,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, } err =geneve_build_skb (&rt->dst, skb, info, xnet,sizeof (struct iphdr ), - geneve->cfg.inner_proto_inherit); + inner_proto_inherit);if (unlikely (err))return err;
@@ -1015,6 +1016,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,struct geneve_dev *geneve, const struct ip_tunnel_info *info) { + bool inner_proto_inherit = geneve->cfg.inner_proto_inherit;bool xnet = !net_eq (geneve->net,dev_net (geneve->dev));struct geneve_sock *gs6 =rcu_dereference (geneve->sock6);const struct ip_tunnel_key *key = &info->key;
@@ -1024,7 +1026,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,__be16 sport;int err; -if (!skb_vlan_inet_prepare (skb)) +if (!skb_vlan_inet_prepare (skb, inner_proto_inherit))return -EINVAL ; sport =udp_flow_src_port (geneve->net, skb,1 ,USHRT_MAX , true);
@@ -1079,7 +1081,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, ttl = ttl ? :ip6_dst_hoplimit (dst); } err =geneve_build_skb (dst, skb, info, xnet,sizeof (struct ipv6hdr ), - geneve->cfg.inner_proto_inherit); + inner_proto_inherit);if (unlikely (err))return err;
include/net/ip_tunnels.h +3 -2
@@ -362,9 +362,10 @@ static inline bool pskb_inet_may_pull(struct sk_buff *skb)/* Variant of pskb_inet_may_pull(). */ -static inline bool skb_vlan_inet_prepare (struct sk_buff *skb) +static inline bool skb_vlan_inet_prepare (struct sk_buff *skb, +bool inner_proto_inherit) { -int nhlen =0 , maclen =ETH_HLEN ; +int nhlen =0 , maclen = inner_proto_inherit ?0 :ETH_HLEN ;__be16 type = skb->protocol;/* Essentially this is skb_protocol(skb, true)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 152/267 net/mlx5e: Fix features validation check for tunneled UDP (non-VXLAN) packets
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gal Pressman <[email protected]>
[ Upstream commit 791b4089e326271424b78f2fae778b20e53d071b ]
Move the vxlan_features_check() call to after we verified the packet is a tunneled VXLAN packet.
Without this, tunneled UDP non-VXLAN packets (for ex. GENENVE) might wrongly not get offloaded.
In some cases, it worked by chance as GENEVE header is the same size as VXLAN, but it is obviously incorrect.
--- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_main.c +1 -2
@@ -4704,7 +4704,7 @@ static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,/* Verify if UDP port is being offloaded by HW */ if (mlx5_vxlan_lookup_port (priv->mdev->vxlan, port)) -return features; +return vxlan_features_check (skb, features);#if IS_ENABLED (CONFIG_GENEVE )/* Support Geneve offload for default UDP port */
@@ -4730,7 +4730,6 @@ netdev_features_t mlx5e_features_check(struct sk_buff *skb,struct mlx5e_priv *priv =netdev_priv (netdev); features =vlan_features_check (skb, features); - features =vxlan_features_check (skb, features);/* Validate if the tunneled packet is being offloaded by HW */ if (skb->encapsulation &&
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 153/267 Bluetooth: L2CAP: Fix rejecting L2CAP_CONN_PARAM_UPDATE_REQ
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit 806a5198c05987b748b50f3d0c0cfb3d417381a4 ]
This removes the bogus check for max > hcon->le_conn_max_interval since the later is just the initial maximum conn interval not the maximum the stack could support which is really 3200=4000ms.
In order to pass GAP/CONN/CPUP/BV-05-C one shall probably enter values of the following fields in IXIT that would cause hci_check_conn_params to fail:
TSPX_conn_update_int_minTSPX_conn_update_int_maxTSPX_conn_update_peripheral_latencyTSPX_conn_update_supervision_timeout
--- include/net/bluetooth/hci_core.h | 36 ++++++++++++++++++++++++++++---- net/bluetooth/l2cap_core.c | 8 +------ 2 files changed, 33 insertions(+), 11 deletions(-)
include/net/bluetooth/hci_core.h +32 -4
@@ -2071,18 +2071,46 @@ static inline int hci_check_conn_params(u16 min, u16 max, u16 latency, {u16 max_latency; -if (min > max || min <6 || max >3200 ) +if (min > max) { +BT_WARN ("min %d > max %d" , min, max);return -EINVAL ; + } + +if (min <6 ) { +BT_WARN ("min %d < 6" , min); +return -EINVAL ; + } + +if (max >3200 ) { +BT_WARN ("max %d > 3200" , max); +return -EINVAL ; + } + +if (to_multiplier <10 ) { +BT_WARN ("to_multiplier %d < 10" , to_multiplier); +return -EINVAL ; + } -if (to_multiplier <10 || to_multiplier >3200 ) +if (to_multiplier >3200 ) { +BT_WARN ("to_multiplier %d > 3200" , to_multiplier);return -EINVAL ; + } -if (max >= to_multiplier *8 ) +if (max >= to_multiplier *8 ) { +BT_WARN ("max %d >= to_multiplier %d * 8" , max, to_multiplier);return -EINVAL ; + } max_latency = (to_multiplier *4 / max) -1 ; -if (latency >499 || latency > max_latency) +if (latency >499 ) { +BT_WARN ("latency %d > 499" , latency);return -EINVAL ; + } + +if (latency > max_latency) { +BT_WARN ("latency %d > max_latency %d" , latency, max_latency); +return -EINVAL ; + }return 0 ; }
net/bluetooth/l2cap_core.c +1 -7
@@ -4645,13 +4645,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,memset (&rsp,0 ,sizeof (rsp)); -if (max > hcon->le_conn_max_interval) { -BT_DBG ("requested connection interval exceeds current bounds." ); - err = -EINVAL ; - }else { - err =hci_check_conn_params (min, max, latency, to_multiplier); - } - + err =hci_check_conn_params (min, max, latency, to_multiplier);if (err) rsp.result =cpu_to_le16 (L2CAP_CONN_PARAM_REJECTED );else
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 154/267 Bluetooth: fix connection setup in l2cap_connect
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit c695439d198d30e10553a3b98360c5efe77b6903 ]
The amp_id argument of l2cap_connect() was removed in commit 84a4bb6548a2 ("Bluetooth: HCI: Remove HCI_AMP support")
It was always called with amp_id == 0, i.e. AMP_ID_BREDR == 0x00 (ie. non-AMP controller). In the above commit, the code path for amp_id != 0 was preserved, although it should have used the amp_id == 0 one.
Restore the previous behavior of the non-AMP code path, to fix problems with L2CAP connections.
--- net/bluetooth/l2cap_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/bluetooth/l2cap_core.c +2 -2
@@ -4009,8 +4009,8 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, status =L2CAP_CS_AUTHOR_PEND ; chan->ops->defer (chan); }else { -l2cap_state_change (chan,BT_CONNECT2 ); - result =L2CAP_CR_PEND ; +l2cap_state_change (chan,BT_CONFIG ); + result =L2CAP_CR_SUCCESS ; status =L2CAP_CS_NO_INFO ; } }else {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 155/267 netfilter: nft_inner: validate mandatory meta and payload
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Davide Ornaghi <[email protected]>
[ Upstream commit c4ab9da85b9df3692f861512fe6c9812f38b7471 ]
Check for mandatory netlink attributes in payload and meta expression when used embedded from the inner expression, otherwise NULL pointer dereference is possible from userspace.
--- net/netfilter/nft_meta.c | 3 +++ net/netfilter/nft_payload.c | 4 ++++ 2 files changed, 7 insertions(+)
net/netfilter/nft_meta.c +3 -0
@@ -839,6 +839,9 @@ static int nft_meta_inner_init(const struct nft_ctx *ctx,struct nft_meta *priv =nft_expr_priv (expr);unsigned int len; +if (!tb[NFTA_META_KEY ] || !tb[NFTA_META_DREG ]) +return -EINVAL ; + priv->key =ntohl (nla_get_be32 (tb[NFTA_META_KEY ]));switch (priv->key) {case NFT_META_PROTOCOL :
net/netfilter/nft_payload.c +4 -0
@@ -650,6 +650,10 @@ static int nft_payload_inner_init(const struct nft_ctx *ctx,struct nft_payload *priv =nft_expr_priv (expr);u32 base; +if (!tb[NFTA_PAYLOAD_BASE ] || !tb[NFTA_PAYLOAD_OFFSET ] || + !tb[NFTA_PAYLOAD_LEN ] || !tb[NFTA_PAYLOAD_DREG ]) +return -EINVAL ; + base =ntohl (nla_get_be32 (tb[NFTA_PAYLOAD_BASE ]));switch (base) {case NFT_PAYLOAD_TUN_HEADER :
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 156/267 netfilter: ipset: Fix race between namespace cleanup and gc in the list:set type
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jozsef Kadlecsik <[email protected]>
[ Upstream commit 4e7aaa6b82d63e8ddcbfb56b4fd3d014ca586f10 ]
Lion Ackermann reported that there is a race condition between namespace cleanup in ipset and the garbage collection of the list:set type. The namespace cleanup can destroy the list:set type of sets while the gc of the set type is waiting to run in rcu cleanup. The latter uses data from the destroyed set which thus leads use after free. The patch contains the following parts:
- When destroying all sets, first remove the garbage collectors, then wait if needed and then destroy the sets.
- Fix the badly ordered "wait then remove gc" for the destroy a single set case.
- Fix the missing rcu locking in the list:set type in the userspace test case.
- Use proper RCU list handlings in the list:set type.
The patch depends on c1193d9bbbd3 (netfilter: ipset: Add list flush to cancel_gc).
--- net/netfilter/ipset/ip_set_core.c | 81 +++++++++++++++------------ net/netfilter/ipset/ip_set_list_set.c | 30 +++++----- 2 files changed, 60 insertions(+), 51 deletions(-)
net/netfilter/ipset/ip_set_core.c +46 -35
@@ -1172,23 +1172,50 @@ ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = { .len = IPSET_MAXNAMELEN - 1 }, }; +/* In order to return quickly when destroying a single set, it is split +* into two stages: +* - Cancel garbage collector +* - Destroy the set itself via call_rcu() +*/ +static void -ip_set_destroy_set (struct ip_set *set) +ip_set_destroy_set_rcu (struct rcu_head *head) { -pr_debug ("set: %s\n" , set->name); + struct ip_set *set = container_of(head, struct ip_set, rcu); -/* Must call it without holding any lock */ set->variant->destroy (set);module_put (set->type->me);kfree (set); }static void -ip_set_destroy_set_rcu (struct rcu_head *head) +_destroy_all_sets (struct ip_set_net *inst) { - struct ip_set *set = container_of(head, struct ip_set, rcu); +struct ip_set *set; +ip_set_id_t i; +bool need_wait = false; -ip_set_destroy_set (set); +/* First cancel gc's: set:list sets are flushed as well */ +for (i =0 ; i < inst->ip_set_max; i++) { + set =ip_set (inst, i); +if (set) { + set->variant->cancel_gc (set); +if (set->type->features &IPSET_TYPE_NAME ) + need_wait = true; + } + } +/* Must wait for flush to be really finished */ +if (need_wait) +rcu_barrier (); +for (i =0 ; i < inst->ip_set_max; i++) { + set =ip_set (inst, i); +if (set) { +ip_set (inst, i) =NULL ; + set->variant->destroy (set); +module_put (set->type->me); +kfree (set); + } + } } static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info,
@@ -1202,11 +1229,10 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info,if (unlikely (protocol_min_failed (attr)))return -IPSET_ERR_PROTOCOL ; -/* Commands are serialized and references are * protected by the ip_set_ref_lock. * External systems (i.e. xt_set) must call -* ip_set_put|get_nfnl_* functions, that way we +* ip_set_nfnl_get_* functions, that way we * can safely check references here. * * list:set timer can only decrement the reference
@@ -1214,8 +1240,6 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info,* without holding the lock. */ if (!attr[IPSET_ATTR_SETNAME ]) { -/* Must wait for flush to be really finished in list:set */ -rcu_barrier ();read_lock_bh (&ip_set_ref_lock);for (i =0 ; i < inst->ip_set_max; i++) { s =ip_set (inst, i);
@@ -1226,15 +1250,7 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info, } inst->is_destroyed = true;read_unlock_bh (&ip_set_ref_lock); -for (i =0 ; i < inst->ip_set_max; i++) { - s =ip_set (inst, i); -if (s) { -ip_set (inst, i) =NULL ; -/* Must cancel garbage collectors */ - s->variant->cancel_gc (s); -ip_set_destroy_set (s); - } - } +_destroy_all_sets (inst);/* Modified by ip_set_destroy() only, which is serialized */ inst->is_destroyed = false; }else {
@@ -1255,12 +1271,12 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info, features = s->type->features;ip_set (inst, i) =NULL ;read_unlock_bh (&ip_set_ref_lock); +/* Must cancel garbage collectors */ + s->variant->cancel_gc (s);if (features &IPSET_TYPE_NAME ) {/* Must wait for flush to be really finished */ rcu_barrier (); } -/* Must cancel garbage collectors */ - s->variant->cancel_gc (s);call_rcu (&s->rcu, ip_set_destroy_set_rcu); }return 0 ;
@@ -2365,30 +2381,25 @@ ip_set_net_init(struct net *net) } static void __net_exit -ip_set_net_exit (struct net *net) +ip_set_net_pre_exit (struct net *net) {struct ip_set_net *inst =ip_set_pernet (net); -struct ip_set *set =NULL ; -ip_set_id_t i; - inst->is_deleted = true;/* flag for ip_set_nfnl_put */ +} -nfnl_lock (NFNL_SUBSYS_IPSET ); -for (i =0 ; i < inst->ip_set_max; i++) { - set =ip_set (inst, i); -if (set) { -ip_set (inst, i) =NULL ; - set->variant->cancel_gc (set); -ip_set_destroy_set (set); - } - } -nfnl_unlock (NFNL_SUBSYS_IPSET ); +static void __net_exit +ip_set_net_exit (struct net *net) +{ +struct ip_set_net *inst =ip_set_pernet (net); + +_destroy_all_sets (inst);kvfree (rcu_dereference_protected (inst->ip_set_list,1 )); }static struct pernet_operations ip_set_net_ops = { .init = ip_set_net_init, + .pre_exit = ip_set_net_pre_exit, .exit = ip_set_net_exit, .id = &ip_set_net_id, .size =sizeof (struct ip_set_net ),
net/netfilter/ipset/ip_set_list_set.c +14 -16
@@ -79,7 +79,7 @@ list_set_kadd(struct ip_set *set, const struct sk_buff *skb,struct set_elem *e;int ret; -list_for_each_entry (e, &map->members, list) { +list_for_each_entry_rcu (e, &map->members, list) {if (SET_WITH_TIMEOUT (set) &&ip_set_timeout_expired (ext_timeout (e, set)))continue ;
@@ -99,7 +99,7 @@ list_set_kdel(struct ip_set *set, const struct sk_buff *skb,struct set_elem *e;int ret; -list_for_each_entry (e, &map->members, list) { +list_for_each_entry_rcu (e, &map->members, list) {if (SET_WITH_TIMEOUT (set) &&ip_set_timeout_expired (ext_timeout (e, set)))continue ;
@@ -188,9 +188,10 @@ list_set_utest(struct ip_set *set, void *value, const struct ip_set_ext *ext,struct list_set *map = set->data;struct set_adt_elem *d = value;struct set_elem *e, *next, *prev =NULL ; -int ret; +int ret =0 ; -list_for_each_entry (e, &map->members, list) { +rcu_read_lock (); +list_for_each_entry_rcu (e, &map->members, list) {if (SET_WITH_TIMEOUT (set) &&ip_set_timeout_expired (ext_timeout (e, set)))continue ;
@@ -201,6 +202,7 @@ list_set_utest(struct ip_set *set, void *value, const struct ip_set_ext *ext,if (d->before ==0 ) { ret =1 ; + goto out; }else if (d->before >0 ) { next =list_next_entry (e, list); ret = !list_is_last(&e->list, &map->members) &&
@@ -208,9 +210,11 @@ list_set_utest(struct ip_set *set, void *value, const struct ip_set_ext *ext, }else { ret = prev && prev->id == d->refid; } -return ret; + goto out; } -return 0 ; +out: +rcu_read_unlock (); +return ret; } static void
@@ -239,7 +243,7 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext,/* Find where to add the new entry */ n = prev = next =NULL ; -list_for_each_entry (e, &map->members, list) { +list_for_each_entry_rcu (e, &map->members, list) {if (SET_WITH_TIMEOUT (set) &&ip_set_timeout_expired (ext_timeout (e, set)))continue ;
@@ -316,9 +320,9 @@ list_set_udel(struct ip_set *set, void *value, const struct ip_set_ext *ext, {struct list_set *map = set->data;struct set_adt_elem *d = value; -struct set_elem *e, *next, *prev =NULL ; +struct set_elem *e, *n, *next, *prev =NULL ; -list_for_each_entry (e, &map->members, list) { +list_for_each_entry_safe (e, n, &map->members, list) {if (SET_WITH_TIMEOUT (set) &&ip_set_timeout_expired (ext_timeout (e, set)))continue ;
@@ -424,14 +428,8 @@ static void list_set_destroy(struct ip_set *set) {struct list_set *map = set->data; -struct set_elem *e, *n; -list_for_each_entry_safe (e, n, &map->members, list) { -list_del (&e->list); -ip_set_put_byindex (map->net, e->id); -ip_set_ext_destroy (set, e); -kfree (e); - } +WARN_ON_ONCE (!list_empty (&map->members));kfree (map); set->data =NULL ;
Signature · 1 line
2.43.0
Re: [PATCH 6.6 156/267] netfilter: ipset: Fix race between namespace cleanup and gc in the list:set type
Hi Greg,
Please, hold on with this one patch for ipset until an incremental fix hits upstream.
Quoted 289 lines · Greg Kroah-Hartman
6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jozsef Kadlecsik <[email protected]>
[ Upstream commit
4e7aaa6b82d63e8ddcbfb56b4fd3d014ca586f10]Lion Ackermann reported that there is a race condition between namespace cleanup in ipset and the garbage collection of the list:set type. The namespace cleanup can destroy the list:set type of sets while the gc of the set type is waiting to run in rcu cleanup. The latter uses data from the destroyed set which thus leads use after free. The patch contains the following parts:
- When destroying all sets, first remove the garbage collectors, then wait if needed and then destroy the sets.
- Fix the badly ordered "wait then remove gc" for the destroy a single set case.
- Fix the missing rcu locking in the list:set type in the userspace test case.
- Use proper RCU list handlings in the list:set type.The patch depends on
c1193d9bbbd3(netfilter: ipset: Add list flush tocancel_gc).Fixes 97f7cf1cd80e (netfilter: ipset: fix performance regression in swap operation)Reported-by Lion Ackermann <[email protected]>Tested-by Lion Ackermann <[email protected]>Signed-off-by Jozsef Kadlecsik <[email protected]>Signed-off-by Pablo Neira Ayuso <[email protected]>Signed-off-by Sasha Levin <[email protected]>--- net/netfilter/ipset/ip_set_core.c | 81 +++++++++++++++------------ net/netfilter/ipset/ip_set_list_set.c | 30 +++++----- 2 files changed, 60 insertions(+), 51 deletions(-)net/netfilter/ipset/ip_set_core.c +46
-35@@ -1172,23 +1172,50 @@ ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = { .len = IPSET_MAXNAMELEN - 1 }, }; +/* In order to return quickly when destroying a single set, it is split +* into two stages: +* - Cancel garbage collector +* - Destroy the set itself via call_rcu() +*/ +static void -ip_set_destroy_set (struct ip_set *set) +ip_set_destroy_set_rcu (struct rcu_head *head) { -pr_debug ("set: %s\n" , set->name); + struct ip_set *set = container_of(head, struct ip_set, rcu); -/* Must call it without holding any lock */ set->variant->destroy (set);module_put (set->type->me);kfree (set); }static void -ip_set_destroy_set_rcu (struct rcu_head *head) +_destroy_all_sets (struct ip_set_net *inst) { - struct ip_set *set = container_of(head, struct ip_set, rcu); +struct ip_set *set; +ip_set_id_t i; +bool need_wait = false; -ip_set_destroy_set (set); +/* First cancel gc's: set:list sets are flushed as well */ +for (i =0 ; i < inst->ip_set_max; i++) { + set =ip_set (inst, i); +if (set) { + set->variant->cancel_gc (set); +if (set->type->features &IPSET_TYPE_NAME ) + need_wait = true; + } + } +/* Must wait for flush to be really finished */ +if (need_wait) +rcu_barrier (); +for (i =0 ; i < inst->ip_set_max; i++) { + set =ip_set (inst, i); +if (set) { +ip_set (inst, i) =NULL ; + set->variant->destroy (set); +module_put (set->type->me); +kfree (set); + } + } } static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info,@@ -1202,11 +1229,10 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info,if (unlikely (protocol_min_failed (attr)))return -IPSET_ERR_PROTOCOL ; -/* Commands are serialized and references are * protected by the ip_set_ref_lock. * External systems (i.e. xt_set) must call -* ip_set_put|get_nfnl_* functions, that way we +* ip_set_nfnl_get_* functions, that way we * can safely check references here. * * list:set timer can only decrement the reference @@ -1214,8 +1240,6 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info,* without holding the lock. */ if (!attr[IPSET_ATTR_SETNAME ]) { -/* Must wait for flush to be really finished in list:set */ -rcu_barrier ();read_lock_bh (&ip_set_ref_lock);for (i =0 ; i < inst->ip_set_max; i++) { s =ip_set (inst, i);@@ -1226,15 +1250,7 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info, } inst->is_destroyed = true;read_unlock_bh (&ip_set_ref_lock); -for (i =0 ; i < inst->ip_set_max; i++) { - s =ip_set (inst, i); -if (s) { -ip_set (inst, i) =NULL ; -/* Must cancel garbage collectors */ - s->variant->cancel_gc (s); -ip_set_destroy_set (s); - } - } +_destroy_all_sets (inst);/* Modified by ip_set_destroy() only, which is serialized */ inst->is_destroyed = false; }else {@@ -1255,12 +1271,12 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info, features = s->type->features;ip_set (inst, i) =NULL ;read_unlock_bh (&ip_set_ref_lock); +/* Must cancel garbage collectors */ + s->variant->cancel_gc (s);if (features &IPSET_TYPE_NAME ) {/* Must wait for flush to be really finished */ rcu_barrier (); } -/* Must cancel garbage collectors */ - s->variant->cancel_gc (s);call_rcu (&s->rcu, ip_set_destroy_set_rcu); }return 0 ;@@ -2365,30 +2381,25 @@ ip_set_net_init(struct net *net) } static void __net_exit -ip_set_net_exit (struct net *net) +ip_set_net_pre_exit (struct net *net) {struct ip_set_net *inst =ip_set_pernet (net); -struct ip_set *set =NULL ; -ip_set_id_t i; - inst->is_deleted = true;/* flag for ip_set_nfnl_put */ +} -nfnl_lock (NFNL_SUBSYS_IPSET ); -for (i =0 ; i < inst->ip_set_max; i++) { - set =ip_set (inst, i); -if (set) { -ip_set (inst, i) =NULL ; - set->variant->cancel_gc (set); -ip_set_destroy_set (set); - } - } -nfnl_unlock (NFNL_SUBSYS_IPSET ); +static void __net_exit +ip_set_net_exit (struct net *net) +{ +struct ip_set_net *inst =ip_set_pernet (net); + +_destroy_all_sets (inst);kvfree (rcu_dereference_protected (inst->ip_set_list,1 )); }static struct pernet_operations ip_set_net_ops = { .init = ip_set_net_init, + .pre_exit = ip_set_net_pre_exit, .exit = ip_set_net_exit, .id = &ip_set_net_id, .size =sizeof (struct ip_set_net ),net/netfilter/ipset/ip_set_list_set.c +14
-16@@ -79,7 +79,7 @@ list_set_kadd(struct ip_set *set, const struct sk_buff *skb,struct set_elem *e;int ret; -list_for_each_entry (e, &map->members, list) { +list_for_each_entry_rcu (e, &map->members, list) {if (SET_WITH_TIMEOUT (set) &&ip_set_timeout_expired (ext_timeout (e, set)))continue ;@@ -99,7 +99,7 @@ list_set_kdel(struct ip_set *set, const struct sk_buff *skb,struct set_elem *e;int ret; -list_for_each_entry (e, &map->members, list) { +list_for_each_entry_rcu (e, &map->members, list) {if (SET_WITH_TIMEOUT (set) &&ip_set_timeout_expired (ext_timeout (e, set)))continue ;@@ -188,9 +188,10 @@ list_set_utest(struct ip_set *set, void *value, const struct ip_set_ext *ext,struct list_set *map = set->data;struct set_adt_elem *d = value;struct set_elem *e, *next, *prev =NULL ; -int ret; +int ret =0 ; -list_for_each_entry (e, &map->members, list) { +rcu_read_lock (); +list_for_each_entry_rcu (e, &map->members, list) {if (SET_WITH_TIMEOUT (set) &&ip_set_timeout_expired (ext_timeout (e, set)))continue ;@@ -201,6 +202,7 @@ list_set_utest(struct ip_set *set, void *value, const struct ip_set_ext *ext,if (d->before ==0 ) { ret =1 ; + goto out; }else if (d->before >0 ) { next =list_next_entry (e, list); ret = !list_is_last(&e->list, &map->members) &&@@ -208,9 +210,11 @@ list_set_utest(struct ip_set *set, void *value, const struct ip_set_ext *ext, }else { ret = prev && prev->id == d->refid; } -return ret; + goto out; } -return 0 ; +out: +rcu_read_unlock (); +return ret; } static void@@ -239,7 +243,7 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext,/* Find where to add the new entry */ n = prev = next =NULL ; -list_for_each_entry (e, &map->members, list) { +list_for_each_entry_rcu (e, &map->members, list) {if (SET_WITH_TIMEOUT (set) &&ip_set_timeout_expired (ext_timeout (e, set)))continue ;@@ -316,9 +320,9 @@ list_set_udel(struct ip_set *set, void *value, const struct ip_set_ext *ext, {struct list_set *map = set->data;struct set_adt_elem *d = value; -struct set_elem *e, *next, *prev =NULL ; +struct set_elem *e, *n, *next, *prev =NULL ; -list_for_each_entry (e, &map->members, list) { +list_for_each_entry_safe (e, n, &map->members, list) {if (SET_WITH_TIMEOUT (set) &&ip_set_timeout_expired (ext_timeout (e, set)))continue ;@@ -424,14 +428,8 @@ static void list_set_destroy(struct ip_set *set) {struct list_set *map = set->data; -struct set_elem *e, *n; -list_for_each_entry_safe (e, n, &map->members, list) { -list_del (&e->list); -ip_set_put_byindex (map->net, e->id); -ip_set_ext_destroy (set, e); -kfree (e); - } +WARN_ON_ONCE (!list_empty (&map->members));kfree (map); set->data =NULL ;Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 157/267 x86/asm: Use %c/%n instead of %P operand modifier in asm templates
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uros Bizjak <[email protected]>
[ Upstream commit 41cd2e1ee96e56401a18dbce6f42f0bdaebcbf3b ]
The "P" asm operand modifier is a x86 target-specific modifier.
When used with a constant, the "P" modifier emits "cst" instead of "$cst". This property is currently used to emit the bare constant without all syntax-specific prefixes.
The generic "c" resp. "n" operand modifier should be used instead.
No functional changes intended.
Stable-dep-of: 8c860ed825cb ("x86/uaccess: Fix missed zeroing of ia32 u64 get_user() range checking")
--- arch/x86/boot/main.c | 4 ++-- arch/x86/include/asm/alternative.h | 22 +++++++++++----------- arch/x86/include/asm/atomic64_32.h | 2 +- arch/x86/include/asm/cpufeature.h | 2 +- arch/x86/include/asm/irq_stack.h | 2 +- arch/x86/include/asm/uaccess.h | 4 ++-- 6 files changed, 18 insertions(+), 18 deletions(-)
arch/x86/boot/main.c +2 -2
@@ -119,8 +119,8 @@ static void init_heap(void)char *stack_end;if (boot_params.hdr.loadflags &CAN_USE_HEAP ) { - asm("leal %P1(%%esp),%0" - :"=r" (stack_end) :"i" (-STACK_SIZE )); + asm("leal %n1(%%esp),%0" + :"=r" (stack_end) :"i" (STACK_SIZE )); heap_end = (char *) ((size_t )boot_params.hdr.heap_end_ptr +0x200 );
arch/x86/include/asm/alternative.h +11 -11
@@ -288,10 +288,10 @@ static inline int alternatives_text_reserved(void *start, void *end)* Otherwise, if CPU has feature1, newinstr1 is used. * Otherwise, oldinstr is used. */ -#define alternative_input_2 (oldinstr, newinstr1, ft_flags1, newinstr2, \ - ft_flags2, input...) \ - asm_inline volatile(ALTERNATIVE_2(oldinstr, newinstr1, ft_flags1, \ - newinstr2, ft_flags2) \ +#define alternative_input_2 (oldinstr, newinstr1, ft_flags1, newinstr2, \ + ft_flags2, input...) \ + asm_inline volatile(ALTERNATIVE_2(oldinstr, newinstr1, ft_flags1, \ + newinstr2, ft_flags2) \ : : "i" (0), ## input)/* Like alternative_input, but with a single output argument */
@@ -301,7 +301,7 @@ static inline int alternatives_text_reserved(void *start, void *end)/* Like alternative_io, but for replacing a direct call with another one. */ #define alternative_call(oldfunc, newfunc, ft_flags, output, input...) \ - asm_inline volatile (ALTERNATIVE("call %P[old]", "call %P[new]", ft_flags) \ + asm_inline volatile (ALTERNATIVE("call %c[old]", "call %c[new]", ft_flags) \ : output : [old] "i" (oldfunc), [new] "i" (newfunc), ## input)/*
@@ -310,12 +310,12 @@ static inline int alternatives_text_reserved(void *start, void *end)* Otherwise, if CPU has feature1, function1 is used. * Otherwise, old function is used. */ -#define alternative_call_2 (oldfunc, newfunc1, ft_flags1, newfunc2, ft_flags2, \ - output, input...) \ - asm_inline volatile (ALTERNATIVE_2("call %P[old]", "call %P[new1]", ft_flags1,\ - "call %P[new2]", ft_flags2) \ - : output, ASM_CALL_CONSTRAINT \ - : [old] "i" (oldfunc), [new1] "i" (newfunc1), \ +#define alternative_call_2 (oldfunc, newfunc1, ft_flags1, newfunc2, ft_flags2, \ + output, input...) \ + asm_inline volatile (ALTERNATIVE_2("call %c[old]", "call %c[new1]", ft_flags1, \ + "call %c[new2]", ft_flags2) \ + : output, ASM_CALL_CONSTRAINT \ + : [old] "i" (oldfunc), [new1] "i" (newfunc1), \ [new2] "i" (newfunc2), ## input)/*
arch/x86/include/asm/atomic64_32.h +1 -1
@@ -24,7 +24,7 @@ typedef struct {#ifdef CONFIG_X86_CMPXCHG64 #define __alternative_atomic64(f, g, out, in...) \ - asm volatile("call %P[func]" \ + asm volatile("call %c[func]" \ : out : [func] "i" (atomic64_##g##_cx8), ## in)#define ATOMIC64_DECL (sym) ATOMIC64_DECL_ONE(sym##_cx8)
arch/x86/include/asm/cpufeature.h +1 -1
@@ -173,7 +173,7 @@ extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit); static __always_inline bool _static_cpu_has(u16 bit) { asm goto( - ALTERNATIVE_TERNARY("jmp 6f", %P[feature], "", "jmp %l[t_no]") + ALTERNATIVE_TERNARY("jmp 6f", %c[feature], "", "jmp %l[t_no]")".pushsection .altinstr_aux,\"ax\"\n" "6:\n" " testb %[bitnum]," _ASM_RIP(%P[cap_byte]) "\n"
arch/x86/include/asm/irq_stack.h +1 -1
@@ -100,7 +100,7 @@ }#define ASM_CALL_ARG0 \ - "call %P[__func] \n" \ + "call %c[__func] \n" \ ASM_REACHABLE#define ASM_CALL_ARG1 \
arch/x86/include/asm/uaccess.h +2 -2
@@ -78,7 +78,7 @@ extern int __get_user_bad(void);int __ret_gu; \ register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX); \__chk_user_ptr (ptr); \ - asm volatile("call __" #fn "_%P4" \ + asm volatile("call __" #fn "_%c4" \ : "=a" (__ret_gu), "=r" (__val_gu), \ ASM_CALL_CONSTRAINT \ : "0" (ptr), "i" (sizeof(*(ptr)))); \
@@ -177,7 +177,7 @@ extern void __put_user_nocheck_8(void);__chk_user_ptr (__ptr); \ __ptr_pu = __ptr; \ __val_pu = __x; \ - asm volatile("call __" #fn "_%P[size]" \ + asm volatile("call __" #fn "_%c[size]" \ : "=c" (__ret_pu), \ ASM_CALL_CONSTRAINT \ : "0" (__ptr_pu), \
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 158/267 x86/uaccess: Fix missed zeroing of ia32 u64 get_user() range checking
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kees Cook <[email protected]>
[ Upstream commit 8c860ed825cb85f6672cd7b10a8f33e3498a7c81 ]
When reworking the range checking for get_user(), the get_user_8() case on 32-bit wasn't zeroing the high register. (The jump to bad_get_user_8 was accidentally dropped.) Restore the correct error handling destination (and rename the jump to using the expected ".L" prefix).
While here, switch to using a named argument ("size") for the call template ("%c4" to "%c[size]") as already used in the other call templates in this file.
Found after moving the usercopy selftests to KUnit:
# usercopy_test_invalid: EXPECTATION FAILED at
lib/usercopy_kunit.c:278
Expected val_u64 == 0, but
val_u64 == -60129542144 (0xfffffff200000000)--- arch/x86/include/asm/uaccess.h | 4 ++-- arch/x86/lib/getuser.S | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-)
arch/x86/include/asm/uaccess.h +2 -2
@@ -78,10 +78,10 @@ extern int __get_user_bad(void);int __ret_gu; \ register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX); \__chk_user_ptr (ptr); \ - asm volatile("call __" #fn "_%c4" \ + asm volatile("call __" #fn "_%c[size]" \ : "=a" (__ret_gu), "=r" (__val_gu), \ ASM_CALL_CONSTRAINT \ - : "0" (ptr), "i" (sizeof(*(ptr)))); \ + : "0" (ptr), [size] "i" (sizeof(*(ptr)))); \ instrument_get_user(__val_gu); \ (x) = (__force __typeof__(*(ptr))) __val_gu; \ __builtin_expect(__ret_gu, 0); \
arch/x86/lib/getuser.S +5 -1
@@ -44,7 +44,11 @@ or %rdx, %rax .else cmp $TASK_SIZE_MAX-\size+1, %eax +.if \size != 8 jae .Lbad_get_user +.else + jae .Lbad_get_user_8 +.endif sbb %edx, %edx /* array_index_mask_nospec() */ and %edx, %eax .endif
@@ -154,7 +158,7 @@ SYM_CODE_END(__get_user_handle_exception) #ifdef CONFIG_X86_32 SYM_CODE_START_LOCAL(__get_user_8_handle_exception) ASM_CLAC -bad_get_user_8: +.Lbad_get_user_8: xor %edx,%edx xor %ecx,%ecx mov $(-EFAULT),%_ASM_AX
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 159/267 scsi: ufs: core: Quiesce request queues before checking pending cmds
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ziqi Chen <[email protected]>
[ Upstream commit 77691af484e28af7a692e511b9ed5ca63012ec6e ]
In ufshcd_clock_scaling_prepare(), after SCSI layer is blocked, ufshcd_pending_cmds() is called to check whether there are pending transactions or not. And only if there are no pending transactions can we proceed to kickstart the clock scaling sequence.
ufshcd_pending_cmds() traverses over all SCSI devices and calls sbitmap_weight() on their budget_map. sbitmap_weight() can be broken down to three steps:
1. Calculate the nr outstanding bits set in the 'word' bitmap.
2. Calculate the nr outstanding bits set in the 'cleared' bitmap.
3. Subtract the result from step 1 by the result from step 2.
This can lead to a race condition as outlined below:
Assume there is one pending transaction in the request queue of one SCSI device, say sda, and the budget token of this request is 0, the 'word' is 0x1 and the 'cleared' is 0x0.
1. When step 1 executes, it gets the result as 1.
2. Before step 2 executes, block layer tries to dispatch a new request to sda. Since the SCSI layer is blocked, the request cannot pass through SCSI but the block layer would do budget_get() and budget_put() to sda's budget map regardless, so the 'word' has become 0x3 and 'cleared' has become 0x2 (assume the new request got budget token 1).
3. When step 2 executes, it gets the result as 1.
4. When step 3 executes, it gets the result as 0, meaning there is no pending transactions, which is wrong.
Thread A Thread B
ufshcd_pending_cmds() __blk_mq_sched_dispatch_requests()
| |
sbitmap_weight(word) |
| scsi_mq_get_budget()
| |
| scsi_mq_put_budget()
| |
sbitmap_weight(cleared)
...
When this race condition happens, the clock scaling sequence is started with transactions still in flight, leading to subsequent hibernate enter failure, broken link, task abort and back to back error recovery.
Fix this race condition by quiescing the request queues before calling ufshcd_pending_cmds() so that block layer won't touch the budget map when ufshcd_pending_cmds() is working on it. In addition, remove the SCSI layer blocking/unblocking to reduce redundancies and latencies.
--- drivers/ufs/core/ufshcd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/ufs/core/ufshcd.c +3 -3
@@ -1267,7 +1267,7 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us)* make sure that there are no outstanding requests when * clock scaling is in progress */ -ufshcd_scsi_block_requests (hba); +blk_mq_quiesce_tagset (&hba->host->tag_set);mutex_lock (&hba->wb_mutex);down_write (&hba->clk_scaling_lock);
@@ -1276,7 +1276,7 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us) ret = -EBUSY ;up_write (&hba->clk_scaling_lock);mutex_unlock (&hba->wb_mutex); -ufshcd_scsi_unblock_requests (hba); +blk_mq_unquiesce_tagset (&hba->host->tag_set); goto out; }
@@ -1297,7 +1297,7 @@ static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, int err, bool scmutex_unlock (&hba->wb_mutex); -ufshcd_scsi_unblock_requests (hba); +blk_mq_unquiesce_tagset (&hba->host->tag_set);ufshcd_release (hba); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 160/267 net: pse-pd: Use EOPNOTSUPP error code instead of ENOTSUPP
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kory Maincent <[email protected]>
[ Upstream commit 144ba8580bcb82b2686c3d1a043299d844b9a682 ]
ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP as reported by checkpatch script.
--- include/linux/pse-pd/pse.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
include/linux/pse-pd/pse.h +2 -2
@@ -114,14 +114,14 @@ static inline int pse_ethtool_get_status(struct pse_control *psec,struct netlink_ext_ack *extack, struct pse_control_status *status) { - return -ENOTSUPP; + return -EOPNOTSUPP; }static inline int pse_ethtool_set_config (struct pse_control *psec,struct netlink_ext_ack *extack,const struct pse_control_config *config) { -return -ENOTSUPP ; +return -EOPNOTSUPP ; }#endif
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 161/267 gve: ignore nonrelevant GSO type bits when processing TSO headers
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joshua Washington <[email protected]>
[ Upstream commit 1b9f756344416e02b41439bf2324b26aa25e141c ]
TSO currently fails when the skb's gso_type field has more than one bit set.
TSO packets can be passed from userspace using PF_PACKET, TUNTAP and a few others, using virtio_net_hdr (e.g., PACKET_VNET_HDR). This includes virtualization, such as QEMU, a real use-case.
The gso_type and gso_size fields as passed from userspace in virtio_net_hdr are not trusted blindly by the kernel. It adds gso_type |= SKB_GSO_DODGY to force the packet to enter the software GSO stack for verification.
This issue might similarly come up when the CWR bit is set in the TCP header for congestion control, causing the SKB_GSO_TCP_ECN gso_type bit to be set.
v2 - Remove unnecessary comments, remove line break between fixes tag and signoffs.
v3 - Add back unrelated empty line removal.
--- drivers/net/ethernet/google/gve/gve_tx_dqo.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-)
drivers/net/ethernet/google/gve/gve_tx_dqo.c +5 -15
@@ -501,28 +501,18 @@ static int gve_prep_tso(struct sk_buff *skb)if (unlikely (skb_shinfo (skb)->gso_size <GVE_TX_MIN_TSO_MSS_DQO ))return -1 ; +if (!(skb_shinfo (skb)->gso_type & (SKB_GSO_TCPV4 |SKB_GSO_TCPV6 ))) +return -EINVAL ; +/* Needed because we will modify header. */ err =skb_cow_head (skb,0 );if (err <0 )return err; tcp =tcp_hdr (skb); - -/* Remove payload length from checksum. */ paylen = skb->len -skb_transport_offset (skb); - -switch (skb_shinfo (skb)->gso_type) { -case SKB_GSO_TCPV4 : -case SKB_GSO_TCPV6 : -csum_replace_by_diff (&tcp->check, - (__force __wsum )htonl (paylen)); - -/* Compute length of segmentation header. */ - header_len =skb_tcp_all_headers (skb); -break ; -default : -return -EINVAL ; - } +csum_replace_by_diff (&tcp->check, (__force __wsum )htonl (paylen)); + header_len =skb_tcp_all_headers (skb);if (unlikely (header_len >GVE_TX_MAX_HDR_SIZE_DQO ))return -EINVAL ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 162/267 net: stmmac: replace priv->speed with the portTransmitRate from the tc-cbs parameters
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiaolei Wang <[email protected]>
[ Upstream commit be27b896529787e23a35ae4befb6337ce73fcca0 ]
The current cbs parameter depends on speed after uplinking, which is not needed and will report a configuration error if the port is not initially connected. The UAPI exposed by tc-cbs requires userspace to recalculate the send slope anyway, because the formula depends on port_transmit_rate (see man tc-cbs), which is not an invariant from tc's perspective. Therefore, we use offload->sendslope and offload->idleslope to derive the original port_transmit_rate from the CBS formula.
--- .../net/ethernet/stmicro/stmmac/stmmac_tc.c | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +11 -14
@@ -343,10 +343,11 @@ static int tc_setup_cbs(struct stmmac_priv *priv, struct tc_cbs_qopt_offload *qopt) {u32 tx_queues_count = priv->plat->tx_queues_to_use; +s64 port_transmit_rate_kbps;u32 queue = qopt->queue; -u32 ptr, speed_div;u32 mode_to_use;u64 value; +u32 ptr;int ret;/* Queue 0 is not AVB capable */
@@ -355,30 +356,26 @@ static int tc_setup_cbs(struct stmmac_priv *priv,if (!priv->dma_cap.av)return -EOPNOTSUPP ; + port_transmit_rate_kbps = qopt->idleslope - qopt->sendslope; +/* Port Transmit Rate and Speed Divider */ -switch (priv->speed) { +switch (div_s64 (port_transmit_rate_kbps,1000 )) {case SPEED_10000 : - ptr =32 ; - speed_div =10000000 ; -break ;case SPEED_5000 : ptr =32 ; - speed_div =5000000 ;break ;case SPEED_2500 : - ptr =8 ; - speed_div =2500000 ; -break ;case SPEED_1000 : ptr =8 ; - speed_div =1000000 ;break ;case SPEED_100 : ptr =4 ; - speed_div =100000 ;break ;default : -return -EOPNOTSUPP ; +netdev_err (priv->dev, +"Invalid portTransmitRate %lld (idleSlope - sendSlope)\n" , + port_transmit_rate_kbps); +return -EINVAL ; } mode_to_use = priv->plat->tx_queues_cfg[queue].mode_to_use;
@@ -398,10 +395,10 @@ static int tc_setup_cbs(struct stmmac_priv *priv, }/* Final adjustments for HW */ - value =div_s64 (qopt->idleslope *1024ll * ptr, speed_div); + value =div_s64 (qopt->idleslope *1024ll * ptr, port_transmit_rate_kbps); priv->plat->tx_queues_cfg[queue].idle_slope = value &GENMASK (31 ,0 ); - value =div_s64 (-qopt->sendslope *1024ll * ptr, speed_div); + value =div_s64 (-qopt->sendslope *1024ll * ptr, port_transmit_rate_kbps); priv->plat->tx_queues_cfg[queue].send_slope = value &GENMASK (31 ,0 ); value = qopt->hicredit *1024ll *8 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 163/267 block: sed-opal: avoid possible wrong address reference in read_sed_opal_key()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Su Hui <[email protected]>
[ Upstream commit 9b1ebce6a1fded90d4a1c6c57dc6262dac4c4c14 ]
Clang static checker (scan-build) warning:
block/sed-opal.c:line 317, column 3
Value stored to 'ret' is never read.
Fix this problem by returning the error code when keyring_search() failed. Otherwise, 'key' will have a wrong value when 'kerf' stores the error code.
--- block/sed-opal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
block/sed-opal.c +1 -1
@@ -313,7 +313,7 @@ static int read_sed_opal_key(const char *key_name, u_char *buffer, int buflen) &key_type_user, key_name, true);if (IS_ERR (kref)) - ret =PTR_ERR (kref); +return PTR_ERR (kref); key =key_ref_to_ptr (kref);down_read (&key->sem);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 164/267 block: fix request.queuelist usage in flush
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chengming Zhou <[email protected]>
[ Upstream commit d0321c812d89c5910d8da8e4b10c891c6b96ff70 ]
Friedrich Weber reported a kernel crash problem and bisected to commit 81ada09cc25e ("blk-flush: reuse rq queuelist in flush state machine").
The root cause is that we use "list_move_tail(&rq->queuelist, pending)" in the PREFLUSH/POSTFLUSH sequences. But rq->queuelist.next == xxx since it's popped out from plug->cached_rq in __blk_mq_alloc_requests_batch(). We don't initialize its queuelist just for this first request, although the queuelist of all later popped requests will be initialized.
Fix it by changing to use "list_add_tail(&rq->queuelist, pending)" so rq->queuelist doesn't need to be initialized. It should be ok since rq can't be on any list when PREFLUSH or POSTFLUSH, has no move actually.
Please note the commit 81ada09cc25e ("blk-flush: reuse rq queuelist in flush state machine") also has another requirement that no drivers would touch rq->queuelist after blk_mq_end_request() since we will reuse it to add rq to the post-flush pending list in POSTFLUSH. If this is not true, we will have to revert that commit IMHO.
This updated version adds "list_del_init(&rq->queuelist)" in flush rq callback since the dm layer may submit request of a weird invalid format (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH), which causes double list_add if without this "list_del_init(&rq->queuelist)". The weird invalid format problem should be fixed in dm layer.
--- block/blk-flush.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
block/blk-flush.c +2 -1
@@ -183,7 +183,7 @@ static void blk_flush_complete_seq(struct request *rq,/* queue for flush */ if (list_empty (pending)) fq->flush_pending_since = jiffies; -list_move_tail (&rq->queuelist, pending); +list_add_tail (&rq->queuelist, pending);break ;case REQ_FSEQ_DATA :
@@ -261,6 +261,7 @@ static enum rq_end_io_ret flush_end_io(struct request *flush_rq,unsigned int seq =blk_flush_cur_seq (rq);BUG_ON (seq !=REQ_FSEQ_PREFLUSH && seq !=REQ_FSEQ_POSTFLUSH ); +list_del_init (&rq->queuelist);blk_flush_complete_seq (rq, fq, seq, error); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 165/267 nvmet-passthru: propagate status from id override functions
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Wagner <[email protected]>
[ Upstream commit d76584e53f4244dbc154bec447c3852600acc914 ]
The id override functions return a status which is not propagated to the caller.
--- drivers/nvme/target/passthru.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/nvme/target/passthru.c +3 -3
@@ -226,13 +226,13 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w) req->cmd->common.opcode == nvme_admin_identify) {switch (req->cmd->identify.cns) {case NVME_ID_CNS_CTRL : -nvmet_passthru_override_id_ctrl (req); + status =nvmet_passthru_override_id_ctrl (req);break ;case NVME_ID_CNS_NS : -nvmet_passthru_override_id_ns (req); + status =nvmet_passthru_override_id_ns (req);break ;case NVME_ID_CNS_NS_DESC_LIST : -nvmet_passthru_override_id_descs (req); + status =nvmet_passthru_override_id_descs (req);break ; } } else if (status < 0)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 166/267 net/ipv6: Fix the RT cache flush via sysctl using a previous delay
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Petr Pavlu <[email protected]>
[ Upstream commit 14a20e5b4ad998793c5f43b0330d9e1388446cf3 ]
The net.ipv6.route.flush system parameter takes a value which specifies a delay used during the flush operation for aging exception routes. The written value is however not used in the currently requested flush and instead utilized only in the next one.
A problem is that ipv6_sysctl_rtcache_flush() first reads the old value of net->ipv6.sysctl.flush_delay into a local delay variable and then calls proc_dointvec() which actually updates the sysctl based on the provided input.
Fix the problem by switching the order of the two operations.
--- net/ipv6/route.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/ipv6/route.c +2 -2
@@ -6332,12 +6332,12 @@ static int ipv6_sysctl_rtcache_flush(struct ctl_table *ctl, int write,if (!write)return -EINVAL ; - net = (struct net *)ctl->extra1; - delay = net->ipv6.sysctl.flush_delay; ret =proc_dointvec (ctl, write, buffer, lenp, ppos);if (ret)return ret; + net = (struct net *)ctl->extra1; + delay = net->ipv6.sysctl.flush_delay;fib6_run_gc (delay <=0 ?0 : (unsigned long )delay, net, delay >0 );return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 167/267 net: bridge: mst: pass vlan group directly to br_mst_vlan_set_state
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Aleksandrov <[email protected]>
[ Upstream commit 36c92936e868601fa1f43da6758cf55805043509 ]
Pass the already obtained vlan group pointer to br_mst_vlan_set_state() instead of dereferencing it again. Each caller has already correctly dereferenced it for their context. This change is required for the following suspicious RCU dereference fix. No functional changes intended.
--- net/bridge/br_mst.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
net/bridge/br_mst.c +5 -6
@@ -73,11 +73,10 @@ int br_mst_get_state(const struct net_device *dev, u16 msti, u8 *state) }EXPORT_SYMBOL_GPL (br_mst_get_state); -static void br_mst_vlan_set_state (struct net_bridge_port *p,struct net_bridge_vlan *v, +static void br_mst_vlan_set_state (struct net_bridge_vlan_group *vg, +struct net_bridge_vlan *v,u8 state) { -struct net_bridge_vlan_group *vg =nbp_vlan_group (p); -if (br_vlan_get_state (v) == state)return ;
@@ -121,7 +120,7 @@ int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state,if (v->brvlan->msti != msti)continue ; -br_mst_vlan_set_state (p, v, state); +br_mst_vlan_set_state (vg, v, state); } out:
@@ -140,13 +139,13 @@ static void br_mst_vlan_sync_state(struct net_bridge_vlan *pv, u16 msti)* it. */ if (v != pv && v->brvlan->msti == msti) { -br_mst_vlan_set_state (pv->port, pv, v->state); +br_mst_vlan_set_state (vg, pv, v->state);return ; } }/* Otherwise, start out in a new MSTI with all ports disabled. */ -return br_mst_vlan_set_state (pv->port, pv,BR_STATE_DISABLED ); +return br_mst_vlan_set_state (vg, pv,BR_STATE_DISABLED ); }int br_mst_vlan_set_msti (struct net_bridge_vlan *mv,u16 msti)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 168/267 net: bridge: mst: fix suspicious rcu usage in br_mst_set_state
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Aleksandrov <[email protected]>
[ Upstream commit 546ceb1dfdac866648ec959cbc71d9525bd73462 ]
I converted br_mst_set_state to RCU to avoid a vlan use-after-free but forgot to change the vlan group dereference helper. Switch to vlan group RCU deref helper to fix the suspicious rcu usage warning.
--- net/bridge/br_mst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/bridge/br_mst.c +1 -1
@@ -102,7 +102,7 @@ int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state,int err =0 ;rcu_read_lock (); - vg =nbp_vlan_group (p); + vg =nbp_vlan_group_rcu (p);if (!vg) goto out;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 169/267 ionic: fix use after netif_napi_del()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Taehee Yoo <[email protected]>
[ Upstream commit 79f18a41dd056115d685f3b0a419c7cd40055e13 ]
When queues are started, netif_napi_add() and napi_enable() are called. If there are 4 queues and only 3 queues are used for the current configuration, only 3 queues' napi should be registered and enabled. The ionic_qcq_enable() checks whether the .poll pointer is not NULL for enabling only the using queue' napi. Unused queues' napi will not be registered by netif_napi_add(), so the .poll pointer indicates NULL. But it couldn't distinguish whether the napi was unregistered or not because netif_napi_del() doesn't reset the .poll pointer to NULL. So, ionic_qcq_enable() calls napi_enable() for the queue, which was unregistered by netif_napi_del().
Reproducer:
ethtool -L <interface name> rx 1 tx 1 combined 0 ethtool -L <interface name> rx 0 tx 0 combined 1 ethtool -L <interface name> rx 0 tx 0 combined 4
Splat looks like:
kernel BUG at net/core/dev.c:6666!
Oops: invalid opcode: 0000 [#1] PREEMPT SMP NOPTI CPU: 3 PID: 1057 Comm: kworker/3:3 Not tainted 6.10.0-rc2+ #16 Workqueue: events ionic_lif_deferred_work [ionic] RIP: 0010:napi_enable+0x3b/0x40 Code: 48 89 c2 48 83 e2 f6 80 b9 61 09 00 00 00 74 0d 48 83 bf 60 01 00 00 00 74 03 80 ce 01 f0 4f RSP: 0018:ffffb6ed83227d48 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff97560cda0828 RCX: 0000000000000029 RDX: 0000000000000001 RSI: 0000000000000000 RDI: ffff97560cda0a28 RBP: ffffb6ed83227d50 R08: 0000000000000400 R09: 0000000000000001 R10: 0000000000000001 R11: 0000000000000001 R12: 0000000000000000 R13: ffff97560ce3c1a0 R14: 0000000000000000 R15: ffff975613ba0a20 FS: 0000000000000000(0000) GS:ffff975d5f780000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f8f734ee200 CR3: 0000000103e50000 CR4: 00000000007506f0 PKRU: 55555554 Call Trace: <TASK> ? die+0x33/0x90 ? do_trap+0xd9/0x100 ? napi_enable+0x3b/0x40 ? do_error_trap+0x83/0xb0 ? napi_enable+0x3b/0x40 ? napi_enable+0x3b/0x40 ? exc_invalid_op+0x4e/0x70 ? napi_enable+0x3b/0x40 ? asm_exc_invalid_op+0x16/0x20 ? napi_enable+0x3b/0x40 ionic_qcq_enable+0xb7/0x180 [ionic 59bdfc8a035436e1c4224ff7d10789e3f14643f8] ionic_start_queues+0xc4/0x290 [ionic 59bdfc8a035436e1c4224ff7d10789e3f14643f8] ionic_link_status_check+0x11c/0x170 [ionic 59bdfc8a035436e1c4224ff7d10789e3f14643f8] ionic_lif_deferred_work+0x129/0x280 [ionic 59bdfc8a035436e1c4224ff7d10789e3f14643f8] process_one_work+0x145/0x360 worker_thread+0x2bb/0x3d0 ? __pfx_worker_thread+0x10/0x10 kthread+0xcc/0x100 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x2d/0x50 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1a/0x30
--- drivers/net/ethernet/pensando/ionic/ionic_lif.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/net/ethernet/pensando/ionic/ionic_lif.c +1 -3
@@ -296,10 +296,8 @@ static int ionic_qcq_enable(struct ionic_qcq *qcq)if (ret)return ret; -if (qcq->napi.poll) -napi_enable (&qcq->napi); -if (qcq->flags &IONIC_QCQ_F_INTR ) { +napi_enable (&qcq->napi);irq_set_affinity_hint (qcq->intr.vector, &qcq->intr.affinity_mask); ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 170/267 af_unix: Read with MSG_PEEK loops if the first unread byte is OOB
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rao Shoaib <[email protected]>
[ Upstream commit a6736a0addd60fccc3a3508461d72314cc609772 ]
Read with MSG_PEEK flag loops if the first byte to read is an OOB byte. commit 22dd70eb2c3d ("af_unix: Don't peek OOB data without MSG_OOB.") addresses the loop issue but does not address the issue that no data beyond OOB byte can be read.
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
from socket import *
c1, c2 =socketpair(AF_UNIX, SOCK_STREAM)c1.send(b'a', MSG_OOB)
1
Quoted 1 line
Quoted 1 line
Quoted 1 line
c1.send(b'b')
1
Quoted 1 line
Quoted 1 line
Quoted 1 line
c2.recv(1, MSG_PEEK | MSG_DONTWAIT)
b'b'
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
from socket import *
c1, c2 =socketpair(AF_UNIX, SOCK_STREAM)c2.setsockopt(SOL_SOCKET, SO_OOBINLINE, 1)c1.send(b'a', MSG_OOB)
1
Quoted 1 line
Quoted 1 line
Quoted 1 line
c1.send(b'b')
1
Quoted 1 line
Quoted 1 line
Quoted 1 line
c2.recv(1, MSG_PEEK | MSG_DONTWAIT)
b'a'
Quoted 1 line
Quoted 1 line
Quoted 1 line
c2.recv(1, MSG_PEEK | MSG_DONTWAIT)
b'a'
Quoted 1 line
Quoted 1 line
Quoted 1 line
c2.recv(1, MSG_DONTWAIT)
b'a'
Quoted 1 line
Quoted 1 line
Quoted 1 line
c2.recv(1, MSG_PEEK | MSG_DONTWAIT)
b'b'
Quoted 1 line
Quoted 1 line
Quoted 1 line
--- net/unix/af_unix.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
net/unix/af_unix.c +9 -9
@@ -2596,18 +2596,18 @@ static struct sk_buff *manage_oob(structif (skb == u->oob_skb) {if (copied) { skb =NULL ; - }else if (sock_flag (sk,SOCK_URGINLINE )) { -if (!(flags &MSG_PEEK )) { + }else if (!(flags &MSG_PEEK )) { +if (sock_flag (sk,SOCK_URGINLINE )) {WRITE_ONCE (u->oob_skb,NULL );consume_skb (skb); + }else { +__skb_unlink (skb, &sk->sk_receive_queue); +WRITE_ONCE (u->oob_skb,NULL ); + unlinked_skb = skb; + skb =skb_peek (&sk->sk_receive_queue); } - }else if (flags &MSG_PEEK ) { - skb =NULL ; - }else { -__skb_unlink (skb, &sk->sk_receive_queue); -WRITE_ONCE (u->oob_skb,NULL ); - unlinked_skb = skb; - skb =skb_peek (&sk->sk_receive_queue); + }else if (!sock_flag (sk,SOCK_URGINLINE )) { + skb =skb_peek_next (skb, &sk->sk_receive_queue); } }
Greg Kroah-Hartman
maintainerPATCH 171/267 bnxt_en: Adjust logging of firmware messages in case of released token in __hwrm_send()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksandr Mishin <[email protected]>
[ Upstream commit a9b9741854a9fe9df948af49ca5514e0ed0429df ]
In case of token is released due to token->state == BNXT_HWRM_DEFERRED, released token (set to NULL) is used in log messages. This issue is expected to be prevented by HWRM_ERR_CODE_PF_UNAVAILABLE error code. But this error code is returned by recent firmware. So some firmware may not return it. This may lead to NULL pointer dereference.
Adjust this issue by adding token pointer check.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c +1 -1
@@ -678,7 +678,7 @@ static int __hwrm_send(struct bnxt *bp, struct bnxt_hwrm_ctx *ctx) req_type); else if (rc && rc != HWRM_ERR_CODE_PF_UNAVAILABLE) hwrm_err(bp, ctx, "hwrm req_type 0x%x seq id 0x%x error 0x%x\n", - req_type, token->seq_id, rc); + req_type, le16_to_cpu(ctx->req->seq_id), rc); rc =__hwrm_to_stderr (rc); exit:if (token)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 172/267 misc: microchip: pci1xxxx: fix double free in the error handling of gp_aux_bus_probe()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yongzhi Liu <[email protected]>
commit 086c6cbcc563c81d55257f9b27e14faf1d0963d3 upstream.
When auxiliary_device_add() returns error and then calls auxiliary_device_uninit(), callback function gp_auxiliary_device_release() calls ida_free() and kfree(aux_device_wrapper) to free memory. We should't call them again in the error handling path.
Fix this by skipping the redundant cleanup functions.
--- drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c +3 -0
@@ -111,6 +111,7 @@ static int gp_aux_bus_probe(struct pci_d err_aux_dev_add_1:auxiliary_device_uninit (&aux_bus->aux_device_wrapper[1 ]->aux_dev); + goto err_aux_dev_add_0; err_aux_dev_init_1:ida_free (&gp_client_ida, aux_bus->aux_device_wrapper[1 ]->aux_dev.id);
@@ -120,6 +121,7 @@ err_ida_alloc_1: err_aux_dev_add_0:auxiliary_device_uninit (&aux_bus->aux_device_wrapper[0 ]->aux_dev); + goto err_ret; err_aux_dev_init_0:ida_free (&gp_client_ida, aux_bus->aux_device_wrapper[0 ]->aux_dev.id);
@@ -127,6 +129,7 @@ err_aux_dev_init_0: err_ida_alloc_0:kfree (aux_bus->aux_device_wrapper[0 ]); +err_ret:return retval; }
Greg Kroah-Hartman
maintainerPATCH 173/267 ksmbd: move leading slash check to smb2_get_name()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
commit 1cdeca6a7264021e20157de0baf7880ff0ced822 upstream.
If the directory name in the root of the share starts with character like 镜(0x955c) or Ṝ(0x1e5c), it (and anything inside) cannot be accessed. The leading slash check must be checked after converting unicode to nls string.
--- fs/smb/server/smb2pdu.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-)
fs/smb/server/smb2pdu.c +6 -9
@@ -630,6 +630,12 @@ smb2_get_name(const char *src, const intreturn name; } +if (*name =='\\' ) { +pr_err ("not allow directory name included leading slash\n" ); +kfree (name); +return ERR_PTR (-EINVAL ); + } +ksmbd_conv_path_to_unix (name);ksmbd_strip_last_slash (name);return name;
@@ -2842,20 +2848,11 @@ int smb2_open(struct ksmbd_work *work) }if (req->NameLength) { -if ((req->CreateOptions &FILE_DIRECTORY_FILE_LE ) && - *(char *)req->Buffer =='\\' ) { -pr_err ("not allow directory name included leading slash\n" ); - rc = -EINVAL ; - goto err_out2; - } - name =smb2_get_name ((char *)req +le16_to_cpu (req->NameOffset),le16_to_cpu (req->NameLength), work->conn->local_nls);if (IS_ERR (name)) { rc =PTR_ERR (name); -if (rc != -ENOMEM ) - rc = -ENOENT ; name =NULL ; goto err_out2; }
Greg Kroah-Hartman
maintainerPATCH 174/267 ksmbd: fix missing use of get_write in in smb2_set_ea()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
commit 2bfc4214c69c62da13a9da8e3c3db5539da2ccd3 upstream.
Fix an issue where get_write is not used in smb2_set_ea().
--- fs/smb/server/smb2pdu.c | 7 ++++--- fs/smb/server/vfs.c | 17 +++++++++++------ fs/smb/server/vfs.h | 3 ++- fs/smb/server/vfs_cache.c | 3 ++- 4 files changed, 19 insertions(+), 11 deletions(-)
fs/smb/server/smb2pdu.c +4 -3
@@ -2367,7 +2367,8 @@ static int smb2_set_ea(struct smb2_ea_inif (rc >0 ) { rc =ksmbd_vfs_remove_xattr (idmap, path, - attr_name); + attr_name, + get_write);if (rc <0 ) { ksmbd_debug(SMB,
@@ -2382,7 +2383,7 @@ static int smb2_set_ea(struct smb2_ea_in }else { rc =ksmbd_vfs_setxattr (idmap, path, attr_name, value,le16_to_cpu (eabuf->EaValueLength), -0 , true); +0 , get_write);if (rc <0 ) { ksmbd_debug(SMB, "ksmbd_vfs_setxattr is failed(%d)\n",
@@ -2474,7 +2475,7 @@ static int smb2_remove_smb_xattrs(const !strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX, STREAM_PREFIX_LEN)) { err =ksmbd_vfs_remove_xattr (idmap, path, - name); + name, true);if (err)ksmbd_debug (SMB ,"remove xattr failed : %s\n" , name);
fs/smb/server/vfs.c +11 -6
@@ -1053,16 +1053,21 @@ int ksmbd_vfs_fqar_lseek(struct ksmbd_fi }int ksmbd_vfs_remove_xattr (struct mnt_idmap *idmap, -const struct path *path,char *attr_name) +const struct path *path,char *attr_name, +bool get_write) {int err; - err =mnt_want_write (path->mnt); -if (err) -return err; +if (get_write == true) { + err =mnt_want_write (path->mnt); +if (err) +return err; + } err =vfs_removexattr (idmap, path->dentry, attr_name); -mnt_drop_write (path->mnt); + +if (get_write == true) +mnt_drop_write (path->mnt);return err; }
@@ -1375,7 +1380,7 @@ int ksmbd_vfs_remove_sd_xattrs(struct mnksmbd_debug (SMB ,"%s, len %zd\n" , name,strlen (name));if (!strncmp (name,XATTR_NAME_SD ,XATTR_NAME_SD_LEN )) { - err =ksmbd_vfs_remove_xattr (idmap, path, name); + err =ksmbd_vfs_remove_xattr (idmap, path, name, true);if (err)ksmbd_debug (SMB ,"remove xattr failed : %s\n" , name); }
fs/smb/server/vfs.h +2 -1
@@ -114,7 +114,8 @@ int ksmbd_vfs_setxattr(struct mnt_idmapint ksmbd_vfs_xattr_stream_name (char *stream_name,char **xattr_stream_name,size_t *xattr_stream_name_size,int s_type);int ksmbd_vfs_remove_xattr (struct mnt_idmap *idmap, -const struct path *path,char *attr_name); +const struct path *path,char *attr_name, +bool get_write);int ksmbd_vfs_kern_path_locked (struct ksmbd_work *work,char *name,unsigned int flags,struct path *parent_path,struct path *path,bool caseless);
fs/smb/server/vfs_cache.c +2 -1
@@ -254,7 +254,8 @@ static void __ksmbd_inode_close(struct k ci->m_flags &= ~S_DEL_ON_CLS_STREAM ; err =ksmbd_vfs_remove_xattr (file_mnt_idmap (filp), &filp->f_path, - fp->stream.name); + fp->stream.name, + true);if (err)pr_err ("remove xattr failed : %s\n" , fp->stream.name);
Greg Kroah-Hartman
maintainerPATCH 175/267 x86/boot: Dont add the EFI stub to targets, again
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Segall <[email protected]>
commit b2747f108b8034271fd5289bd8f3a7003e0775a3 upstream.
This is a re-commit of
da05b143a308 ("x86/boot: Don't add the EFI stub to targets")
after the tagged patch incorrectly reverted it.
vmlinux-objs-y is added to targets, with an assumption that they are all relative to $(obj); adding a $(objtree)/drivers/... path causes the build to incorrectly create a useless arch/x86/boot/compressed/drivers/... directory tree.
Fix this just by using a different make variable for the EFI stub.
--- arch/x86/boot/compressed/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/boot/compressed/Makefile +2 -2
@@ -116,9 +116,9 @@ vmlinux-objs-$(CONFIG_UNACCEPTED_MEMORY) vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o -vmlinux-objs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a +vmlinux-libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a -$(obj)/vmlinux: $(vmlinux-objs-y) FORCE +$(obj)/vmlinux: $(vmlinux-objs-y) $(vmlinux-libs-y) FORCE $(call if_changed,ld) OBJCOPYFLAGS_vmlinux.bin := -R .comment -S
Greg Kroah-Hartman
maintainerPATCH 176/267 iio: adc: ad9467: fix scan type sign
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lechner <[email protected]>
commit 8a01ef749b0a632f0e1f4ead0f08b3310d99fcb1 upstream.
According to the IIO documentation, the sign in the scan type should be lower case. The ad9467 driver was incorrectly using upper case.
Fix by changing to lower case.
--- drivers/iio/adc/ad9467.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/iio/adc/ad9467.c +2 -2
@@ -225,11 +225,11 @@ static void __ad9467_get_scale(struct ad }static const struct iio_chan_spec ad9434_channels[] = { -AD9467_CHAN (0 ,0 ,12 ,'S' ), +AD9467_CHAN (0 ,0 ,12 ,'s' ), };static const struct iio_chan_spec ad9467_channels[] = { -AD9467_CHAN (0 ,0 ,16 ,'S' ), +AD9467_CHAN (0 ,0 ,16 ,'s' ), };static const struct ad9467_chip_info ad9467_chip_tbl = {
Greg Kroah-Hartman
maintainerPATCH 177/267 iio: dac: ad5592r: fix temperature channel scaling value
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marc Ferland <[email protected]>
commit 279428df888319bf68f2686934897301a250bb84 upstream.
The scale value for the temperature channel is (assuming Vref=2.5 and the datasheet):
376.7897513
When calculating both val and val2 for the temperature scale we use (3767897513/25) and multiply it by Vref (here I assume 2500mV) to obtain:
2500 * (3767897513/25) ==> 376789751300
Finally we divide with remainder by 10^9 to get:
val = 376
val2 = 789751300However, we return IIO_VAL_INT_PLUS_MICRO (should have been NANO) as the scale type. So when converting the raw temperature value to the 'processed' temperature value we will get (assuming raw=810, offset=-753):
processed = (raw + offset) * scale_val
= (810 + -753) * 376
= 21432
processed += div((raw + offset) * scale_val2, 10^6)
+= div((810 + -753) * 789751300, 10^6)
+= 45015
==> 66447
==> 66.4 Celciusinstead of the expected 21.5 Celsius.
Fix this issue by changing IIO_VAL_INT_PLUS_MICRO to IIO_VAL_INT_PLUS_NANO.
--- drivers/iio/dac/ad5592r-base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iio/dac/ad5592r-base.c +1 -1
@@ -415,7 +415,7 @@ static int ad5592r_read_raw(struct iio_ds64 tmp = *val * (3767897513LL /25LL ); *val =div_s64_rem (tmp,1000000000LL , val2); -return IIO_VAL_INT_PLUS_MICRO ; +return IIO_VAL_INT_PLUS_NANO ; }mutex_lock (&st->lock);
Greg Kroah-Hartman
maintainerPATCH 178/267 iio: invensense: fix odr switching to same value
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jean-Baptiste Maneyrol <[email protected]>
commit 95444b9eeb8c5c0330563931d70c61ca3b101548 upstream.
ODR switching happens in 2 steps, update to store the new value and then apply when the ODR change flag is received in the data. When switching to the same ODR value, the ODR change flag is never happening, and frequency switching is blocked waiting for the never coming apply.
Fix the issue by preventing update to happen when switching to same ODR value.
--- drivers/iio/common/inv_sensors/inv_sensors_timestamp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/iio/common/inv_sensors/inv_sensors_timestamp.c +5 -1
@@ -60,11 +60,15 @@ EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_init, IIO_INV_SENSORS_TIMESTAMP);int inv_sensors_timestamp_update_odr (struct inv_sensors_timestamp *ts,uint32_t period,bool fifo) { +uint32_t mult; +/* when FIFO is on, prevent odr change if one is already pending */ if (fifo && ts->new_mult !=0 )return -EAGAIN ; - ts->new_mult = period / ts->chip.clock_period; + mult = period / ts->chip.clock_period; +if (mult != ts->mult) + ts->new_mult = mult;return 0 ; }
Signature · 1 line
2.45.2
Greg Kroah-Hartman
maintainerPATCH 179/267 iio: imu: inv_icm42600: delete unneeded update watermark call
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jean-Baptiste Maneyrol <[email protected]>
commit 245f3b149e6cc3ac6ee612cdb7042263bfc9e73c upstream.
Update watermark will be done inside the hwfifo_set_watermark callback just after the update_scan_mode. It is useless to do it here.
--- drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c | 4 ---- drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c | 4 ---- 2 files changed, 8 deletions(-)
drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c +0 -4
@@ -129,10 +129,6 @@ static int inv_icm42600_accel_update_sca/* update data FIFO write */ inv_sensors_timestamp_apply_odr (ts,0 ,0 ,0 ); ret =inv_icm42600_buffer_set_fifo_en (st, fifo_en | st->fifo.en); -if (ret) - goto out_unlock; - - ret =inv_icm42600_buffer_update_watermark (st); out_unlock:mutex_unlock (&st->lock);
drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c +0 -4
@@ -129,10 +129,6 @@ static int inv_icm42600_gyro_update_scan/* update data FIFO write */ inv_sensors_timestamp_apply_odr (ts,0 ,0 ,0 ); ret =inv_icm42600_buffer_set_fifo_en (st, fifo_en | st->fifo.en); -if (ret) - goto out_unlock; - - ret =inv_icm42600_buffer_update_watermark (st); out_unlock:mutex_unlock (&st->lock);
Greg Kroah-Hartman
maintainerPATCH 180/267 drivers: core: synchronize really_probe() and dev_uevent()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dirk Behme <[email protected]>
commit c0a40097f0bc81deafc15f9195d1fb54595cd6d0 upstream.
Synchronize the dev->driver usage in really_probe() and dev_uevent(). These can run in different threads, what can result in the following race condition for dev->driver uninitialization:
Thread #1:
==========
really_probe() {
...probe_failed:
...
device_unbind_cleanup(dev) {
...
dev->driver = NULL; // <= Failed probe sets dev->driver to NULL
...
}...
}
Thread #2:
==========
dev_uevent() {
...
if (dev->driver)
// If dev->driver is NULLed from really_probe() from here on,
// after above check, the system crashes
add_uevent_var(env, "DRIVER=%s", dev->driver->name);...
}
really_probe() holds the lock, already. So nothing needs to be done there. dev_uevent() is called with lock held, often, too. But not always. What implies that we can't add any locking in dev_uevent() itself. So fix this race by adding the lock to the non-protected path. This is the path where above race is observed:
dev_uevent+0x235/0x380 uevent_show+0x10c/0x1f0 <= Add lock here dev_attr_show+0x3a/0xa0 sysfs_kf_seq_show+0x17c/0x250 kernfs_seq_show+0x7c/0x90 seq_read_iter+0x2d7/0x940 kernfs_fop_read_iter+0xc6/0x310 vfs_read+0x5bc/0x6b0 ksys_read+0xeb/0x1b0 __x64_sys_read+0x42/0x50 x64_sys_call+0x27ad/0x2d30 do_syscall_64+0xcd/0x1d0 entry_SYSCALL_64_after_hwframe+0x77/0x7f
Similar cases are reported by syzkaller in
https://syzkaller.appspot.com/bug?extid=ffa8143439596313a85a
But these are regarding the *initialization* of dev->driver
dev->driver = drv;
As this switches dev->driver to non-NULL these reports can be considered to be false-positives (which should be "fixed" by this commit, as well, though).
The same issue was reported and tried to be fixed back in 2015 in
https://lore.kernel.org/lkml/[email protected]/
already.
--- drivers/base/core.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/base/core.c +3 -0
@@ -2664,8 +2664,11 @@ static ssize_t uevent_show(struct deviceif (!env)return -ENOMEM ; +/* Synchronize with really_probe() */ +device_lock (dev);/* let the kset specific function add its keys */ retval = kset->uevent_ops->uevent (&dev->kobj, env); +device_unlock (dev);if (retval) goto out;
Greg Kroah-Hartman
maintainerPATCH 181/267 parisc: Try to fix random segmentation faults in package builds
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: John David Anglin <[email protected]>
commit 72d95924ee35c8cd16ef52f912483ee938a34d49 upstream.
PA-RISC systems with PA8800 and PA8900 processors have had problems with random segmentation faults for many years. Systems with earlier processors are much more stable.
Systems with PA8800 and PA8900 processors have a large L2 cache which needs per page flushing for decent performance when a large range is flushed. The combined cache in these systems is also more sensitive to non-equivalent aliases than the caches in earlier systems.
The majority of random segmentation faults that I have looked at appear to be memory corruption in memory allocated using mmap and malloc.
My first attempt at fixing the random faults didn't work. On reviewing the cache code, I realized that there were two issues which the existing code didn't handle correctly. Both relate to cache move-in. Another issue is that the present bit in PTEs is racy.
1) PA-RISC caches have a mind of their own and they can speculatively load data and instructions for a page as long as there is a entry in the TLB for the page which allows move-in. TLBs are local to each CPU. Thus, the TLB entry for a page must be purged before flushing the page. This is particularly important on SMP systems.
In some of the flush routines, the flush routine would be called and then the TLB entry would be purged. This was because the flush routine needed the TLB entry to do the flush.
2) My initial approach to trying the fix the random faults was to try and use flush_cache_page_if_present for all flush operations. This actually made things worse and led to a couple of hardware lockups. It finally dawned on me that some lines weren't being flushed because the pte check code was racy. This resulted in random inequivalent mappings to physical pages.
The __flush_cache_page tmpalias flush sets up its own TLB entry and it doesn't need the existing TLB entry. As long as we can find the pte pointer for the vm page, we can get the pfn and physical address of the page. We can also purge the TLB entry for the page before doing the flush. Further, __flush_cache_page uses a special TLB entry that inhibits cache move-in.
When switching page mappings, we need to ensure that lines are removed from the cache. It is not sufficient to just flush the lines to memory as they may come back.
This made it clear that we needed to implement all the required flush operations using tmpalias routines. This includes flushes for user and kernel pages.
After modifying the code to use tmpalias flushes, it became clear that the random segmentation faults were not fully resolved. The frequency of faults was worse on systems with a 64 MB L2 (PA8900) and systems with more CPUs (rp4440).
The warning that I added to flush_cache_page_if_present to detect pages that couldn't be flushed triggered frequently on some systems.
Helge and I looked at the pages that couldn't be flushed and found that the PTE was either cleared or for a swap page. Ignoring pages that were swapped out seemed okay but pages with cleared PTEs seemed problematic.
I looked at routines related to pte_clear and noticed ptep_clear_flush. The default implementation just flushes the TLB entry. However, it was obvious that on parisc we need to flush the cache page as well. If we don't flush the cache page, stale lines will be left in the cache and cause random corruption. Once a PTE is cleared, there is no way to find the physical address associated with the PTE and flush the associated page at a later time.
I implemented an updated change with a parisc specific version of ptep_clear_flush. It fixed the random data corruption on Helge's rp4440 and rp3440, as well as on my c8000.
At this point, I realized that I could restore the code where we only flush in flush_cache_page_if_present if the page has been accessed. However, for this, we also need to flush the cache when the accessed bit is cleared in ptep_clear_flush_young to keep things synchronized. The default implementation only flushes the TLB entry.
Other changes in this version are:
1) Implement parisc specific version of ptep_get. It's identical to default but needed in arch/parisc/include/asm/pgtable.h.
2) Revise parisc implementation of ptep_test_and_clear_young to use ptep_get (READ_ONCE).
3) Drop parisc implementation of ptep_get_and_clear. We can use default.
4) Revise flush_kernel_vmap_range and invalidate_kernel_vmap_range to use full data cache flush.
5) Move flush_cache_vmap and flush_cache_vunmap to cache.c. Handle VM_IOREMAP case in flush_cache_vmap.
At this time, I don't know whether it is better to always flush when the PTE present bit is set or when both the accessed and present bits are set. The later saves flushing pages that haven't been accessed, but we need to flush in ptep_clear_flush_young. It also needs a page table lookup to find the PTE pointer. The lpa instruction only needs a page table lookup when the PTE entry isn't in the TLB.
We don't atomically handle setting and clearing the _PAGE_ACCESSED bit. If we miss an update, we may miss a flush and the cache may get corrupted. Whether the current code is effectively atomic depends on process control.
When CONFIG_FLUSH_PAGE_ACCESSED is set to zero, the page will eventually be flushed when the PTE is cleared or in flush_cache_page_if_present. The _PAGE_ACCESSED bit is not used, so the problem is avoided.
The flush method can be selected using the CONFIG_FLUSH_PAGE_ACCESSED define in cache.c. The default is 0. I didn't see a large difference in performance.
--- arch/parisc/include/asm/cacheflush.h | 15 - arch/parisc/include/asm/pgtable.h | 27 +- arch/parisc/kernel/cache.c | 411 +++++++++++++++++++++-------------- 3 files changed, 274 insertions(+), 179 deletions(-)
arch/parisc/include/asm/cacheflush.h +4 -11
@@ -31,18 +31,17 @@ void flush_cache_all_local(void);void flush_cache_all (void );void flush_cache_mm (struct mm_struct *mm); -void flush_kernel_dcache_page_addr (const void *addr); -#define flush_kernel_dcache_range (start,size) \ flush_kernel_dcache_range_asm((start), (start)+(size)); +/* The only way to flush a vmap range is to flush whole cache */ #define ARCH_IMPLEMENTS_FLUSH_KERNEL_VMAP_RANGE 1void flush_kernel_vmap_range (void *vaddr,int size);void invalidate_kernel_vmap_range (void *vaddr,int size); -#define flush_cache_vmap (start, end) flush_cache_all() +void flush_cache_vmap (unsigned long start,unsigned long end);#define flush_cache_vmap_early (start, end) do { } while (0) -#define flush_cache_vunmap (start, end) flush_cache_all() +void flush_cache_vunmap (unsigned long start,unsigned long end);void flush_dcache_folio (struct folio *folio);#define flush_dcache_folio flush_dcache_folio
@@ -77,17 +76,11 @@ void flush_cache_page(struct vm_area_strvoid flush_cache_range (struct vm_area_struct *vma,unsigned long start,unsigned long end); -/* defined in pacache.S exported in cache.c used by flush_anon_page */ -void flush_dcache_page_asm (unsigned long phys_addr,unsigned long vaddr); -#define ARCH_HAS_FLUSH_ANON_PAGE void flush_anon_page (struct vm_area_struct *vma,struct page *page,unsigned long vmaddr);#define ARCH_HAS_FLUSH_ON_KUNMAP -static inline void kunmap_flush_on_unmap (const void *addr) -{ -flush_kernel_dcache_page_addr (addr); -} +void kunmap_flush_on_unmap (const void *addr);#endif /* _PARISC_CACHEFLUSH_H */
arch/parisc/include/asm/pgtable.h +12 -15
@@ -448,14 +448,17 @@ static inline pte_t pte_swp_clear_exclusreturn pte; } +static inline pte_t ptep_get (pte_t *ptep) +{ +return READ_ONCE (*ptep); +} +#define ptep_get ptep_get +static inline int ptep_test_and_clear_young (struct vm_area_struct *vma,unsigned long addr,pte_t *ptep) {pte_t pte; -if (!pte_young (*ptep)) -return 0 ; - - pte = *ptep; + pte =ptep_get (ptep);if (!pte_young (pte)) {return 0 ; }
@@ -463,17 +466,10 @@ static inline int ptep_test_and_clear_yoreturn 1 ; } -struct mm_struct ; -static inline pte_t ptep_get_and_clear (struct mm_struct *mm,unsigned long addr,pte_t *ptep) -{ -pte_t old_pte; - - old_pte = *ptep; -set_pte (ptep,__pte (0 )); - -return old_pte; -} +int ptep_clear_flush_young (struct vm_area_struct *vma,unsigned long addr,pte_t *ptep); +pte_t ptep_clear_flush (struct vm_area_struct *vma,unsigned long addr,pte_t *ptep); +struct mm_struct ;static inline void ptep_set_wrprotect (struct mm_struct *mm,unsigned long addr,pte_t *ptep) {set_pte (ptep,pte_wrprotect (*ptep));
@@ -511,7 +507,8 @@ static inline void ptep_set_wrprotect(st#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG -#define __HAVE_ARCH_PTEP_GET_AND_CLEAR +#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH +#define __HAVE_ARCH_PTEP_CLEAR_FLUSH#define __HAVE_ARCH_PTEP_SET_WRPROTECT#define __HAVE_ARCH_PTE_SAME
arch/parisc/kernel/cache.c +258 -153
565 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 182/267 ACPI: x86: Force StorageD3Enable on more products
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
commit e79a10652bbd320649da705ca1ea0c04351af403 upstream.
A Rembrandt-based HP thin client is reported to have problems where the NVME disk isn't present after resume from s2idle.
This is because the NVME disk wasn't put into D3 at suspend, and that happened because the StorageD3Enable _DSD was missing in the BIOS.
As AMD's architecture requires that the NVME is in D3 for s2idle, adjust the criteria for force_storage_d3 to match *all* Zen SoCs when the FADT advertises low power idle support.
This will ensure that any future products with this BIOS deficiency don't need to be added to the allow list of overrides.
--- drivers/acpi/x86/utils.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-)
drivers/acpi/x86/utils.c +10 -14
@@ -198,16 +198,16 @@ bool acpi_device_override_status(struct }/* -* AMD systems from Renoir and Lucienne *require* that the NVME controller +* AMD systems from Renoir onwards *require* that the NVME controller * is put into D3 over a Modern Standby / suspend-to-idle cycle. * * This is "typically" accomplished using the `StorageD3Enable` * property in the _DSD that is checked via the `acpi_storage_d3` function -* but this property was introduced after many of these systems launched -* and most OEM systems don't have it in their BIOS. +* but some OEM systems still don't have it in their BIOS. * * The Microsoft documentation for StorageD3Enable mentioned that Windows has -* a hardcoded allowlist for D3 support, which was used for these platforms. +* a hardcoded allowlist for D3 support as well as a registry key to override +* the BIOS, which has been used for these cases. * * This allows quirking on Linux in a similar fashion. *
@@ -220,19 +220,15 @@ bool acpi_device_override_status(struct* https://bugzilla.kernel.org/show_bug.cgi?id=216773 * https://bugzilla.kernel.org/show_bug.cgi?id=217003 * 2) On at least one HP system StorageD3Enable is missing on the second NVME -disk in the system. +* disk in the system. +* 3) On at least one HP Rembrandt system StorageD3Enable is missing on the only +* NVME device. */ -static const struct x86_cpu_id storage_d3_cpu_ids[] = { -X86_MATCH_VENDOR_FAM_MODEL (AMD ,23 ,24 ,NULL ),/* Picasso */ -X86_MATCH_VENDOR_FAM_MODEL (AMD ,23 ,96 ,NULL ),/* Renoir */ -X86_MATCH_VENDOR_FAM_MODEL (AMD ,23 ,104 ,NULL ),/* Lucienne */ -X86_MATCH_VENDOR_FAM_MODEL (AMD ,25 ,80 ,NULL ),/* Cezanne */ - {} -}; -bool force_storage_d3 (void ) { -return x86_match_cpu (storage_d3_cpu_ids); +if (!cpu_feature_enabled (X86_FEATURE_ZEN )) +return false; +return acpi_gbl_FADT.flags &ACPI_FADT_LOW_POWER_S0 ; }/*
Greg Kroah-Hartman
maintainerPATCH 183/267 drm/exynos/vidi: fix memory leak in .get_modes()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jani Nikula <[email protected]>
commit 38e3825631b1f314b21e3ade00b5a4d737eb054e upstream.
The duplicated EDID is never freed. Fix it.
--- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/gpu/drm/exynos/exynos_drm_vidi.c +6 -1
@@ -309,6 +309,7 @@ static int vidi_get_modes(struct drm_construct vidi_context *ctx =ctx_from_connector (connector);struct edid *edid;int edid_len; +int count;/* * the edid data comes from user side and it would be set
@@ -328,7 +329,11 @@ static int vidi_get_modes(struct drm_condrm_connector_update_edid_property (connector, edid); -return drm_add_edid_modes (connector, edid); + count =drm_add_edid_modes (connector, edid); + +kfree (edid); + +return count; }static const struct drm_connector_helper_funcs vidi_connector_helper_funcs = {
Greg Kroah-Hartman
maintainerPATCH 184/267 drm/exynos: hdmi: report safe 640x480 mode as a fallback when no EDID found
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marek Szyprowski <[email protected]>
commit 799d4b392417ed6889030a5b2335ccb6dcf030ab upstream.
When reading EDID fails and driver reports no modes available, the DRM core adds an artificial 1024x786 mode to the connector. Unfortunately some variants of the Exynos HDMI (like the one in Exynos4 SoCs) are not able to drive such mode, so report a safe 640x480 mode instead of nothing in case of the EDID reading failure.
This fixes the following issue observed on Trats2 board since commit 13d5b040363c ("drm/exynos: do not return negative values from .get_modes()"):
[drm] Exynos DRM: using 11c00000.fimd device for DMA mapping operations
exynos-drm exynos-drm: bound 11c00000.fimd (ops fimd_component_ops)
exynos-drm exynos-drm: bound 12c10000.mixer (ops mixer_component_ops)
exynos-dsi 11c80000.dsi: [drm:samsung_dsim_host_attach] Attached s6e8aa0 device (lanes:4 bpp:24 mode-flags:0x10b) exynos-drm exynos-drm: bound 11c80000.dsi (ops exynos_dsi_component_ops)
exynos-drm exynos-drm: bound 12d00000.hdmi (ops hdmi_component_ops)
[drm] Initialized exynos 1.1.0 20180330 for exynos-drm on minor 1
exynos-hdmi 12d00000.hdmi: [drm:hdmiphy_enable.part.0] *ERROR* PLL could not reach steady state panel-samsung-s6e8aa0 11c80000.dsi.0: ID: 0xa2, 0x20, 0x8c
exynos-mixer 12c10000.mixer: timeout waiting for VSYNC
------------[ cut here ]------------ WARNING: CPU: 1 PID: 11 at drivers/gpu/drm/drm_atomic_helper.c:1682 drm_atomic_helper_wait_for_vblanks.part.0+0x2b0/0x2b8 [CRTC:70:crtc-1] vblank wait timed out Modules linked in: CPU: 1 PID: 11 Comm: kworker/u16:0 Not tainted 6.9.0-rc5-next-20240424 #14913 Hardware name: Samsung Exynos (Flattened Device Tree) Workqueue: events_unbound deferred_probe_work_func Call trace: unwind_backtrace from show_stack+0x10/0x14 show_stack from dump_stack_lvl+0x68/0x88 dump_stack_lvl from __warn+0x7c/0x1c4 __warn from warn_slowpath_fmt+0x11c/0x1a8 warn_slowpath_fmt from drm_atomic_helper_wait_for_vblanks.part.0+0x2b0/0x2b8 drm_atomic_helper_wait_for_vblanks.part.0 from drm_atomic_helper_commit_tail_rpm+0x7c/0x8c drm_atomic_helper_commit_tail_rpm from commit_tail+0x9c/0x184 commit_tail from drm_atomic_helper_commit+0x168/0x190 drm_atomic_helper_commit from drm_atomic_commit+0xb4/0xe0 drm_atomic_commit from drm_client_modeset_commit_atomic+0x23c/0x27c drm_client_modeset_commit_atomic from drm_client_modeset_commit_locked+0x60/0x1cc drm_client_modeset_commit_locked from drm_client_modeset_commit+0x24/0x40 drm_client_modeset_commit from __drm_fb_helper_restore_fbdev_mode_unlocked+0x9c/0xc4 __drm_fb_helper_restore_fbdev_mode_unlocked from drm_fb_helper_set_par+0x2c/0x3c drm_fb_helper_set_par from fbcon_init+0x3d8/0x550 fbcon_init from visual_init+0xc0/0x108 visual_init from do_bind_con_driver+0x1b8/0x3a4 do_bind_con_driver from do_take_over_console+0x140/0x1ec do_take_over_console from do_fbcon_takeover+0x70/0xd0 do_fbcon_takeover from fbcon_fb_registered+0x19c/0x1ac fbcon_fb_registered from register_framebuffer+0x190/0x21c register_framebuffer from __drm_fb_helper_initial_config_and_unlock+0x350/0x574 __drm_fb_helper_initial_config_and_unlock from exynos_drm_fbdev_client_hotplug+0x6c/0xb0 exynos_drm_fbdev_client_hotplug from drm_client_register+0x58/0x94 drm_client_register from exynos_drm_bind+0x160/0x190 exynos_drm_bind from try_to_bring_up_aggregate_device+0x200/0x2d8 try_to_bring_up_aggregate_device from __component_add+0xb0/0x170 __component_add from mixer_probe+0x74/0xcc mixer_probe from platform_probe+0x5c/0xb8 platform_probe from really_probe+0xe0/0x3d8 really_probe from __driver_probe_device+0x9c/0x1e4 __driver_probe_device from driver_probe_device+0x30/0xc0 driver_probe_device from __device_attach_driver+0xa8/0x120 __device_attach_driver from bus_for_each_drv+0x80/0xcc bus_for_each_drv from __device_attach+0xac/0x1fc __device_attach from bus_probe_device+0x8c/0x90 bus_probe_device from deferred_probe_work_func+0x98/0xe0 deferred_probe_work_func from process_one_work+0x240/0x6d0 process_one_work from worker_thread+0x1a0/0x3f4 worker_thread from kthread+0x104/0x138 kthread from ret_from_fork+0x14/0x28 Exception stack(0xf0895fb0 to 0xf0895ff8) ... irq event stamp: 82357 hardirqs last enabled at (82363): [<c01a96e8>] vprintk_emit+0x308/0x33c hardirqs last disabled at (82368): [<c01a969c>] vprintk_emit+0x2bc/0x33c softirqs last enabled at (81614): [<c0101644>] __do_softirq+0x320/0x500 softirqs last disabled at (81609): [<c012dfe0>] __irq_exit_rcu+0x130/0x184 ---[ end trace 0000000000000000 ]---
exynos-drm exynos-drm: [drm] *ERROR* flip_done timed out
exynos-drm exynos-drm: [drm] *ERROR* [CRTC:70:crtc-1] commit wait timed out exynos-drm exynos-drm: [drm] *ERROR* flip_done timed out
exynos-drm exynos-drm: [drm] *ERROR* [CONNECTOR:74:HDMI-A-1] commit wait timed out exynos-drm exynos-drm: [drm] *ERROR* flip_done timed out
exynos-drm exynos-drm: [drm] *ERROR* [PLANE:56:plane-5] commit wait timed out exynos-mixer 12c10000.mixer: timeout waiting for VSYNC
--- drivers/gpu/drm/exynos/exynos_hdmi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/gpu/drm/exynos/exynos_hdmi.c +5 -2
@@ -887,11 +887,11 @@ static int hdmi_get_modes(struct drm_conint ret;if (!hdata->ddc_adpt) -return 0 ; + goto no_edid; edid =drm_get_edid (connector, hdata->ddc_adpt);if (!edid) -return 0 ; + goto no_edid; hdata->dvi_mode = !connector->display_info.is_hdmi; DRM_DEV_DEBUG_KMS(hdata->dev, "%s : width[%d] x height[%d]\n",
@@ -906,6 +906,9 @@ static int hdmi_get_modes(struct drm_conkfree (edid);return ret; + +no_edid: +return drm_add_modes_noedid (connector,640 ,480 ); }static int hdmi_find_phy_conf (struct hdmi_context *hdata,u32 pixel_clock)
Greg Kroah-Hartman
maintainerPATCH 185/267 mptcp: ensure snd_una is properly initialized on connect
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paolo Abeni <[email protected]>
commit 8031b58c3a9b1db3ef68b3bd749fbee2e1e1aaa3 upstream.
This is strictly related to commit fb7a0d334894 ("mptcp: ensure snd_nxt is properly initialized on connect"). It turns out that syzkaller can trigger the retransmit after fallback and before processing any other incoming packet - so that snd_una is still left uninitialized.
Address the issue explicitly initializing snd_una together with snd_nxt and write_seq.
--- net/mptcp/protocol.c | 1 + 1 file changed, 1 insertion(+)
net/mptcp/protocol.c +1 -0
@@ -3706,6 +3706,7 @@ static int mptcp_connect(struct sock *skWRITE_ONCE (msk->write_seq, subflow->idsn);WRITE_ONCE (msk->snd_nxt, subflow->idsn); +WRITE_ONCE (msk->snd_una, subflow->idsn);if (likely (!__mptcp_check_fallback (msk)))MPTCP_INC_STATS (sock_net (sk),MPTCP_MIB_MPCAPABLEACTIVE );
Greg Kroah-Hartman
maintainerPATCH 186/267 mptcp: pm: inc RmAddr MIB counter once per RM_ADDR ID
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: YonglongLi <[email protected]>
commit 6a09788c1a66e3d8b04b3b3e7618cc817bb60ae9 upstream.
The RmAddr MIB counter is supposed to be incremented once when a valid RM_ADDR has been received. Before this patch, it could have been incremented as many times as the number of subflows connected to the linked address ID, so it could have been 0, 1 or more than 1.
The "RmSubflow" is incremented after a local operation. In this case, it is normal to tied it with the number of subflows that have been actually removed.
The "remove invalid addresses" MP Join subtest has been modified to validate this case. A broadcast IP address is now used instead: the client will not be able to create a subflow to this address. The consequence is that when receiving the RM_ADDR with the ID attached to this broadcast IP address, no subflow linked to this ID will be found.
--- net/mptcp/pm_netlink.c | 5 ++++- tools/testing/selftests/net/mptcp/mptcp_join.sh | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-)
net/mptcp/pm_netlink.c +4 -1
@@ -822,10 +822,13 @@ static void mptcp_pm_nl_rm_addr_or_subflspin_lock_bh (&msk->pm.lock); removed = true; -__MPTCP_INC_STATS (sock_net (sk), rm_type); +if (rm_type ==MPTCP_MIB_RMSUBFLOW ) +__MPTCP_INC_STATS (sock_net (sk), rm_type); }if (rm_type ==MPTCP_MIB_RMSUBFLOW )__set_bit (rm_id ? rm_id : msk->mpc_endpoint_id, msk->pm.id_avail_bitmap); +else if (rm_type ==MPTCP_MIB_RMADDR ) +__MPTCP_INC_STATS (sock_net (sk), rm_type);if (!removed)continue ;
tools/testing/selftests/net/mptcp/mptcp_join.sh +2 -1
@@ -2394,7 +2394,8 @@ remove_tests() pm_nl_set_limits $ns1 3 3 pm_nl_add_endpoint $ns1 10.0.12.1 flags signal pm_nl_add_endpoint $ns1 10.0.3.1 flags signal - pm_nl_add_endpoint $ns1 10.0.14.1 flags signal + # broadcast IP: no packet for this address will be received on ns1 + pm_nl_add_endpoint $ns1 224.0.0.1 flags signal pm_nl_set_limits $ns2 3 3 addr_nr_ns1=-3 speed=10 \ run_tests $ns1 $ns2 10.0.1.1
Greg Kroah-Hartman
maintainerPATCH 187/267 mptcp: pm: update add_addr counters after connect
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: YonglongLi <[email protected]>
commit 40eec1795cc27b076d49236649a29507c7ed8c2d upstream.
The creation of new subflows can fail for different reasons. If no subflow have been created using the received ADD_ADDR, the related counters should not be updated, otherwise they will never be decremented for events related to this ID later on.
For the moment, the number of accepted ADD_ADDR is only decremented upon the reception of a related RM_ADDR, and only if the remote address ID is currently being used by at least one subflow. In other words, if no subflow can be created with the received address, the counter will not be decremented. In this case, it is then important not to increment pm.add_addr_accepted counter, and not to modify pm.accept_addr bit.
Note that this patch does not modify the behaviour in case of failures later on, e.g. if the MP Join is dropped or rejected.
The "remove invalid addresses" MP Join subtest has been modified to validate this case. The broadcast IP address is added before the "valid" address that will be used to successfully create a subflow, and the limit is decreased by one: without this patch, it was not possible to create the last subflow, because:
- the broadcast address would have been accepted even if it was not
usable: the creation of a subflow to this address results in an error,
- the limit of 2 accepted ADD_ADDR would have then been reached.
--- net/mptcp/pm_netlink.c | 16 ++++++++++------ tools/testing/selftests/net/mptcp/mptcp_join.sh | 4 ++-- 2 files changed, 12 insertions(+), 8 deletions(-)
net/mptcp/pm_netlink.c +10 -6
@@ -685,6 +685,7 @@ static void mptcp_pm_nl_add_addr_receiveunsigned int add_addr_accept_max;struct mptcp_addr_info remote;unsigned int subflows_max; +bool sf_created = false;int i, nr; add_addr_accept_max =mptcp_pm_get_add_addr_accept_max (msk);
@@ -712,15 +713,18 @@ static void mptcp_pm_nl_add_addr_receiveif (nr ==0 )return ; - msk->pm.add_addr_accepted++; -if (msk->pm.add_addr_accepted >= add_addr_accept_max || - msk->pm.subflows >= subflows_max) -WRITE_ONCE (msk->pm.accept_addr, false); -spin_unlock_bh (&msk->pm.lock);for (i =0 ; i < nr; i++) -__mptcp_subflow_connect (sk, &addrs[i], &remote); +if (__mptcp_subflow_connect (sk, &addrs[i], &remote) ==0 ) + sf_created = true;spin_lock_bh (&msk->pm.lock); + +if (sf_created) { + msk->pm.add_addr_accepted++; +if (msk->pm.add_addr_accepted >= add_addr_accept_max || + msk->pm.subflows >= subflows_max) +WRITE_ONCE (msk->pm.accept_addr, false); + } }void mptcp_pm_nl_addr_send_ack (struct mptcp_sock *msk)
tools/testing/selftests/net/mptcp/mptcp_join.sh +2 -2
@@ -2393,10 +2393,10 @@ remove_tests() if reset "remove invalid addresses"; then pm_nl_set_limits $ns1 3 3 pm_nl_add_endpoint $ns1 10.0.12.1 flags signal - pm_nl_add_endpoint $ns1 10.0.3.1 flags signal # broadcast IP: no packet for this address will be received on ns1 pm_nl_add_endpoint $ns1 224.0.0.1 flags signal - pm_nl_set_limits $ns2 3 3 + pm_nl_add_endpoint $ns1 10.0.3.1 flags signal + pm_nl_set_limits $ns2 2 2 addr_nr_ns1=-3 speed=10 \ run_tests $ns1 $ns2 10.0.1.1 chk_join_nr 1 1 1
Greg Kroah-Hartman
maintainerPATCH 188/267 clkdev: Update clkdev id usage to allow for longer names
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael J. Ruhl <[email protected]>
commit 99f4570cfba1e60daafde737cb7e395006d719e6 upstream.
clkdev DEV ID information is limited to an array of 20 bytes (MAX_DEV_ID). It is possible that the ID could be longer than that. If so, the lookup will fail because the "real ID" will not match the copied value.
For instance, generating a device name for the I2C Designware module using the PCI ID can result in a name of:
i2c_designware.39424
clkdev_create() will store:
i2c_designware.3942
The stored name is one off and will not match correctly during probe.
Increase the size of the ID to allow for a longer name.
--- drivers/clk/clkdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/clk/clkdev.c +1 -1
@@ -144,7 +144,7 @@ void clkdev_add_table(struct clk_lookupmutex_unlock (&clocks_mutex); } -#define MAX_DEV_ID 20 +#define MAX_DEV_ID 24#define MAX_CON_ID 16struct clk_lookup_alloc {
Greg Kroah-Hartman
maintainerPATCH 189/267 irqchip/gic-v3-its: Fix potential race condition in its_vlpi_prop_update()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hagar Hemdan <[email protected]>
commit b97e8a2f7130a4b30d1502003095833d16c028b3 upstream.
its_vlpi_prop_update() calls lpi_write_config() which obtains the mapping information for a VLPI without lock held. So it could race with its_vlpi_unmap().
Since all calls from its_irq_set_vcpu_affinity() require the same lock to be held, hoist the locking there instead of sprinkling the locking all over the place.
This bug was discovered using Coverity Static Analysis Security Testing (SAST) by Synopsys, Inc.
[ tglx: Use guard() instead of goto ]
--- drivers/irqchip/irq-gic-v3-its.c | 44 ++++++++++----------------------------- 1 file changed, 12 insertions(+), 32 deletions(-)
drivers/irqchip/irq-gic-v3-its.c +12 -32
@@ -1840,28 +1840,22 @@ static int its_vlpi_map(struct irq_data {struct its_device *its_dev =irq_data_get_irq_chip_data (d);u32 event =its_get_event_id (d); -int ret =0 ;if (!info->map)return -EINVAL ; -raw_spin_lock (&its_dev->event_map.vlpi_lock); -if (!its_dev->event_map.vm) {struct its_vlpi_map *maps; maps =kcalloc (its_dev->event_map.nr_lpis,sizeof (*maps),GFP_ATOMIC ); -if (!maps) { - ret = -ENOMEM ; - goto out; - } +if (!maps) +return -ENOMEM ; its_dev->event_map.vm = info->map->vm; its_dev->event_map.vlpi_maps = maps; }else if (its_dev->event_map.vm != info->map->vm) { - ret = -EINVAL ; - goto out; +return -EINVAL ; }/* Get our private copy of the mapping information */
@@ -1893,46 +1887,32 @@ static int its_vlpi_map(struct irq_data its_dev->event_map.nr_vlpis++; } -out: -raw_spin_unlock (&its_dev->event_map.vlpi_lock); -return ret; +return 0 ; }static int its_vlpi_get (struct irq_data *d,struct its_cmd_info *info) {struct its_device *its_dev =irq_data_get_irq_chip_data (d);struct its_vlpi_map *map; -int ret =0 ; - -raw_spin_lock (&its_dev->event_map.vlpi_lock); map =get_vlpi_map (d); -if (!its_dev->event_map.vm || !map) { - ret = -EINVAL ; - goto out; - } +if (!its_dev->event_map.vm || !map) +return -EINVAL ;/* Copy our mapping information to the incoming request */ *info->map = *map; -out: -raw_spin_unlock (&its_dev->event_map.vlpi_lock); -return ret; +return 0 ; }static int its_vlpi_unmap (struct irq_data *d) {struct its_device *its_dev =irq_data_get_irq_chip_data (d);u32 event =its_get_event_id (d); -int ret =0 ; -raw_spin_lock (&its_dev->event_map.vlpi_lock); - -if (!its_dev->event_map.vm || !irqd_is_forwarded_to_vcpu (d)) { - ret = -EINVAL ; - goto out; - } +if (!its_dev->event_map.vm || !irqd_is_forwarded_to_vcpu (d)) +return -EINVAL ;/* Drop the virtual mapping */ its_send_discard (its_dev, event);
@@ -1956,9 +1936,7 @@ static int its_vlpi_unmap(struct irq_datkfree (its_dev->event_map.vlpi_maps); } -out: -raw_spin_unlock (&its_dev->event_map.vlpi_lock); -return ret; +return 0 ; }static int its_vlpi_prop_update (struct irq_data *d,struct its_cmd_info *info)
@@ -1986,6 +1964,8 @@ static int its_irq_set_vcpu_affinity(strif (!is_v4 (its_dev->its))return -EINVAL ; +guard (raw_spinlock_irq)(&its_dev->event_map.vlpi_lock); +/* Unmap request? */ if (!info)return its_vlpi_unmap (d);
Greg Kroah-Hartman
maintainerPATCH 190/267 x86/kexec: Fix bug with call depth tracking
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Kaplan <[email protected]>
commit 93c1800b3799f17375989b0daf76497dd3e80922 upstream.
The call to cc_platform_has() triggers a fault and system crash if call depth tracking is active because the GS segment has been reset by load_segments() and GS_BASE is now 0 but call depth tracking uses per-CPU variables to operate.
Call cc_platform_has() earlier in the function when GS is still valid.
[ bp: Massage. ]
--- arch/x86/kernel/machine_kexec_64.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
arch/x86/kernel/machine_kexec_64.c +9 -2
@@ -298,8 +298,15 @@ void machine_kexec_cleanup(struct kimagevoid machine_kexec (struct kimage *image) {unsigned long page_list[PAGES_NR ]; -void *control_page; +unsigned int host_mem_enc_active;int save_ftrace_enabled; +void *control_page; + +/* +* This must be done before load_segments() since if call depth tracking +* is used then GS must be valid to make any function calls. +*/ + host_mem_enc_active =cc_platform_has (CC_ATTR_HOST_MEM_ENCRYPT );#ifdef CONFIG_KEXEC_JUMP if (image->preserve_context)
@@ -361,7 +368,7 @@ void machine_kexec(struct kimage *image) (unsigned long )page_list, image->start, image->preserve_context, - cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT)); + host_mem_enc_active);#ifdef CONFIG_KEXEC_JUMP if (image->preserve_context)
Greg Kroah-Hartman
maintainerPATCH 191/267 x86/amd_nb: Check for invalid SMN reads
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yazen Ghannam <[email protected]>
commit c625dabbf1c4a8e77e4734014f2fde7aa9071a1f upstream.
AMD Zen-based systems use a System Management Network (SMN) that provides access to implementation-specific registers.
SMN accesses are done indirectly through an index/data pair in PCI config space. The PCI config access may fail and return an error code. This would prevent the "read" value from being updated.
However, the PCI config access may succeed, but the return value may be invalid. This is in similar fashion to PCI bad reads, i.e. return all bits set.
Most systems will return 0 for SMN addresses that are not accessible. This is in line with AMD convention that unavailable registers are Read-as-Zero/Writes-Ignored.
However, some systems will return a "PCI Error Response" instead. This value, along with an error code of 0 from the PCI config access, will confuse callers of the amd_smn_read() function.
Check for this condition, clear the return value, and set a proper error code.
--- arch/x86/kernel/amd_nb.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
arch/x86/kernel/amd_nb.c +8 -1
@@ -209,7 +209,14 @@ out:int amd_smn_read (u16 node,u32 address,u32 *value) { -return __amd_smn_rw (node, address, value, false); +int err =__amd_smn_rw (node, address, value, false); + +if (PCI_POSSIBLE_ERROR (*value)) { + err = -ENODEV ; + *value =0 ; + } + +return err; }EXPORT_SYMBOL_GPL (amd_smn_read);
Greg Kroah-Hartman
maintainerPATCH 192/267 perf/core: Fix missing wakeup when waiting for context reference
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haifeng Xu <[email protected]>
commit 74751ef5c1912ebd3e65c3b65f45587e05ce5d36 upstream.
In our production environment, we found many hung tasks which are blocked for more than 18 hours. Their call traces are like this:
[346278.191038] __schedule+0x2d8/0x890 [346278.191046] schedule+0x4e/0xb0 [346278.191049] perf_event_free_task+0x220/0x270 [346278.191056] ? init_wait_var_entry+0x50/0x50 [346278.191060] copy_process+0x663/0x18d0 [346278.191068] kernel_clone+0x9d/0x3d0 [346278.191072] __do_sys_clone+0x5d/0x80 [346278.191076] __x64_sys_clone+0x25/0x30 [346278.191079] do_syscall_64+0x5c/0xc0 [346278.191083] ? syscall_exit_to_user_mode+0x27/0x50 [346278.191086] ? do_syscall_64+0x69/0xc0 [346278.191088] ? irqentry_exit_to_user_mode+0x9/0x20 [346278.191092] ? irqentry_exit+0x19/0x30 [346278.191095] ? exc_page_fault+0x89/0x160 [346278.191097] ? asm_exc_page_fault+0x8/0x30 [346278.191102] entry_SYSCALL_64_after_hwframe+0x44/0xae
The task was waiting for the refcount become to 1, but from the vmcore, we found the refcount has already been 1. It seems that the task didn't get woken up by perf_event_release_kernel() and got stuck forever. The below scenario may cause the problem.
Thread A Thread B
... ...perf_event_free_task perf_event_release_kernel
... acquire event->child_mutex ... get_ctx ... release event->child_mutex acquire ctx->mutex ... perf_free_event (acquire/release event->child_mutex) ... release ctx->mutex wait_var_event acquire ctx->mutex acquire event->child_mutex # move existing events to free_list release event->child_mutex release ctx->mutex put_ctx
... ...
In this case, all events of the ctx have been freed, so we couldn't find the ctx in free_list and Thread A will miss the wakeup. It's thus necessary to add a wakeup after dropping the reference.
--- kernel/events/core.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
kernel/events/core.c +13 -0
@@ -5353,6 +5353,7 @@ int perf_event_release_kernel(struct per again:mutex_lock (&event->child_mutex);list_for_each_entry (child, &event->child_list, child_list) { +void *var =NULL ;/* * Cannot change, child events are not migrated, see the
@@ -5393,11 +5394,23 @@ again:* this can't be the last reference. */ put_event (event); + }else { + var = &ctx->refcount; }mutex_unlock (&event->child_mutex);mutex_unlock (&ctx->mutex);put_ctx (ctx); + +if (var) { +/* +* If perf_event_free_task() has deleted all events from the +* ctx while the child_mutex got released above, make sure to +* notify about the preceding put_ctx(). +*/ +smp_mb ();/* pairs with wait_var_event() */ +wake_up_var (var); + } goto again; }mutex_unlock (&event->child_mutex);
Greg Kroah-Hartman
maintainerPATCH 193/267 perf auxtrace: Fix multiple use of --itrace option
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Hunter <[email protected]>
commit bb69c912c4e8005cf1ee6c63782d2fc28838dee2 upstream.
If the --itrace option is used more than once, the options are combined, but "i" and "y" (sub-)options can be corrupted because itrace_do_parse_synth_opts() incorrectly overwrites the period type and period with default values.
For example, with:
--itrace=i0ns --itrace=e
The processing of "--itrace=e", resets the "i" period from 0 nanoseconds to the default 100 microseconds.
Fix by performing the default setting of period type and period only if "i" or "y" are present in the currently processed --itrace value.
--- tools/perf/util/auxtrace.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
tools/perf/util/auxtrace.c +3 -1
@@ -1466,6 +1466,7 @@ int itrace_do_parse_synth_opts(struct itchar *endptr;bool period_type_set = false;bool period_set = false; +bool iy = false; synth_opts->set = true;
@@ -1484,6 +1485,7 @@ int itrace_do_parse_synth_opts(struct itswitch (*p++) {case 'i' :case 'y' : + iy = true;if (p[-1 ] =='y' ) synth_opts->cycles = true;else
@@ -1646,7 +1648,7 @@ int itrace_do_parse_synth_opts(struct it } } out: -if (synth_opts->instructions || synth_opts->cycles) { +if (iy) {if (!period_type_set) synth_opts->period_type =PERF_ITRACE_DEFAULT_PERIOD_TYPE ;
Greg Kroah-Hartman
maintainerPATCH 194/267 riscv: fix overlap of allocated page and PTR_ERR
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nam Cao <[email protected]>
commit 994af1825a2aa286f4903ff64a1c7378b52defe6 upstream.
On riscv32, it is possible for the last page in virtual address space (0xfffff000) to be allocated. This page overlaps with PTR_ERR, so that shouldn't happen.
There is already some code to ensure memblock won't allocate the last page. However, buddy allocator is left unchecked.
Fix this by reserving physical memory that would be mapped at virtual addresses greater than 0xfffff000.
--- arch/riscv/mm/init.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
arch/riscv/mm/init.c +11 -10
@@ -234,18 +234,19 @@ static void __init setup_bootmem(void) kernel_map.va_pa_offset =PAGE_OFFSET - phys_ram_base;/* -* memblock allocator is not aware of the fact that last 4K bytes of -* the addressable memory can not be mapped because of IS_ERR_VALUE -* macro. Make sure that last 4k bytes are not usable by memblock -* if end of dram is equal to maximum addressable memory. For 64-bit -* kernel, this problem can't happen here as the end of the virtual -* address space is occupied by the kernel mapping then this check must -* be done as soon as the kernel mapping base address is determined. +* Reserve physical address space that would be mapped to virtual +* addresses greater than (void *)(-PAGE_SIZE) because: +* - This memory would overlap with ERR_PTR +* - This memory belongs to high memory, which is not supported +* +* This is not applicable to 64-bit kernel, because virtual addresses +* after (void *)(-PAGE_SIZE) are not linearly mapped: they are +* occupied by kernel mapping. Also it is unrealistic for high memory +* to exist on 64-bit platforms. */ if (!IS_ENABLED (CONFIG_64BIT )) { - max_mapped_addr =__pa (~(ulong )0 ); -if (max_mapped_addr == (phys_ram_end -1 )) -memblock_set_current_limit (max_mapped_addr -4096 ); + max_mapped_addr =__va_to_pa_nodebug (-PAGE_SIZE ); +memblock_reserve (max_mapped_addr, (phys_addr_t)-max_mapped_addr); } min_low_pfn =PFN_UP (phys_ram_base);
Greg Kroah-Hartman
maintainerPATCH 195/267 tracing/selftests: Fix kprobe event name test for .isra. functions
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steven Rostedt (Google) <[email protected]>
commit 23a4b108accc29a6125ed14de4a044689ffeda78 upstream.
The kprobe_eventname.tc test checks if a function with .isra. can have a kprobe attached to it. It loops through the kallsyms file for all the functions that have the .isra. name, and checks if it exists in the available_filter_functions file, and if it does, it uses it to attach a kprobe to it.
The issue is that kprobes can not attach to functions that are listed more than once in available_filter_functions. With the latest kernel, the function that is found is: rapl_event_update.isra.0
# grep rapl_event_update.isra.0 /sys/kernel/tracing/available_filter_functions rapl_event_update.isra.0 rapl_event_update.isra.0
It is listed twice. This causes the attached kprobe to it to fail which in turn fails the test. Instead of just picking the function function that is found in available_filter_functions, pick the first one that is listed only once in available_filter_functions.
--- tools/testing/selftests/ftrace/test.d/kprobe/kprobe_eventname.tc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_eventname.tc +2 -1
@@ -30,7 +30,8 @@ find_dot_func() { fi grep " [tT] .*\.isra\..*" /proc/kallsyms | cut -f 3 -d " " | while read f; do - if grep -s $f available_filter_functions; then + cnt=`grep -s $f available_filter_functions | wc -l`; + if [ $cnt -eq 1 ]; then echo $f break fi
Greg Kroah-Hartman
maintainerPATCH 196/267 kheaders: explicitly define file modes for archived headers
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthias Maennich <[email protected]>
commit 3bd27a847a3a4827a948387cc8f0dbc9fa5931d5 upstream.
Build environments might be running with different umask settings resulting in indeterministic file modes for the files contained in kheaders.tar.xz. The file itself is served with 444, i.e. world readable. Archive the files explicitly with 744,a+X to improve reproducibility across build environments.
--mode=0444 is not suitable as directories need to be executable. Also, 444 makes it hard to delete all the readonly files after extraction.
--- kernel/gen_kheaders.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/gen_kheaders.sh +1 -1
@@ -89,7 +89,7 @@ find $cpio_dir -type f -print0 | # Create archive and try to normalize metadata for reproducibility. tar "${KBUILD_BUILD_TIMESTAMP:+--mtime=$KBUILD_BUILD_TIMESTAMP}" \ - --owner=0 --group=0 --sort=name --numeric-owner \ + --owner=0 --group=0 --sort=name --numeric-owner --mode=u=rw,go=r,a+X \ -I $XZ -cf $tarfile -C $cpio_dir/ . > /dev/null echo $headers_md5 > kernel/kheaders.md5
Greg Kroah-Hartman
maintainerPATCH 197/267 null_blk: Print correct max open zones limit in null_init_zoned_dev()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal <[email protected]>
commit 233e27b4d21c3e44eb863f03e566d3a22e81a7ae upstream.
When changing the maximum number of open zones, print that number instead of the total number of zones.
--- drivers/block/null_blk/zoned.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/block/null_blk/zoned.c +1 -1
@@ -112,7 +112,7 @@ int null_init_zoned_dev(struct nullb_devif (dev->zone_max_active && dev->zone_max_open > dev->zone_max_active) { dev->zone_max_open = dev->zone_max_active;pr_info ("changed the maximum number of open zones to %u\n" , - dev->nr_zones); + dev->zone_max_open); }else if (dev->zone_max_open >= dev->nr_zones - dev->zone_nr_conv) { dev->zone_max_open =0 ;pr_info ("zone_max_open limit disabled, limit >= zone count\n" );
Greg Kroah-Hartman
maintainerPATCH 198/267 sock_map: avoid race between sock_map_close and sk_psock_put
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thadeu Lima de Souza Cascardo <[email protected]>
commit 4b4647add7d3c8530493f7247d11e257ee425bf0 upstream.
sk_psock_get will return NULL if the refcount of psock has gone to 0, which will happen when the last call of sk_psock_put is done. However, sk_psock_drop may not have finished yet, so the close callback will still point to sock_map_close despite psock being NULL.
This can be reproduced with a thread deleting an element from the sock map, while the second one creates a socket, adds it to the map and closes it.
That will trigger the WARN_ON_ONCE:
------------[ cut here ]------------ WARNING: CPU: 1 PID: 7220 at net/core/sock_map.c:1701 sock_map_close+0x2a2/0x2d0 net/core/sock_map.c:1701 Modules linked in: CPU: 1 PID: 7220 Comm: syz-executor380 Not tainted 6.9.0-syzkaller-07726-g3c999d1ae3c7 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/02/2024 RIP: 0010:sock_map_close+0x2a2/0x2d0 net/core/sock_map.c:1701 Code: df e8 92 29 88 f8 48 8b 1b 48 89 d8 48 c1 e8 03 42 80 3c 20 00 74 08 48 89 df e8 79 29 88 f8 4c 8b 23 eb 89 e8 4f 15 23 f8 90 <0f> 0b 90 48 83 c4 08 5b 41 5c 41 5d 41 5e 41 5f 5d e9 13 26 3d 02 RSP: 0018:ffffc9000441fda8 EFLAGS: 00010293 RAX: ffffffff89731ae1 RBX: ffffffff94b87540 RCX: ffff888029470000 RDX: 0000000000000000 RSI: ffffffff8bcab5c0 RDI: ffffffff8c1faba0 RBP: 0000000000000000 R08: ffffffff92f9b61f R09: 1ffffffff25f36c3 R10: dffffc0000000000 R11: fffffbfff25f36c4 R12: ffffffff89731840 R13: ffff88804b587000 R14: ffff88804b587000 R15: ffffffff89731870 FS: 000055555e080380(0000) GS:ffff8880b9500000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 00000000207d4000 CR4: 0000000000350ef0 Call Trace: <TASK> unix_release+0x87/0xc0 net/unix/af_unix.c:1048 __sock_release net/socket.c:659 [inline] sock_close+0xbe/0x240 net/socket.c:1421 __fput+0x42b/0x8a0 fs/file_table.c:422 __do_sys_close fs/open.c:1556 [inline] __se_sys_close fs/open.c:1541 [inline] __x64_sys_close+0x7f/0x110 fs/open.c:1541 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf5/0x240 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7fb37d618070 Code: 00 00 48 c7 c2 b8 ff ff ff f7 d8 64 89 02 b8 ff ff ff ff eb d4 e8 10 2c 00 00 80 3d 31 f0 07 00 00 74 17 b8 03 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 48 c3 0f 1f 80 00 00 00 00 48 83 ec 18 89 7c RSP: 002b:00007ffcd4a525d8 EFLAGS: 00000202 ORIG_RAX: 0000000000000003 RAX: ffffffffffffffda RBX: 0000000000000005 RCX: 00007fb37d618070 RDX: 0000000000000010 RSI: 00000000200001c0 RDI: 0000000000000004 RBP: 0000000000000000 R08: 0000000100000000 R09: 0000000100000000 R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000000 R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 </TASK>
Use sk_psock, which will only check that the pointer is not been set to NULL yet, which should only happen after the callbacks are restored. If, then, a reference can still be gotten, we may call sk_psock_stop and cancel psock->work.
As suggested by Paolo Abeni, reorder the condition so the control flow is less convoluted.
After that change, the reproducer does not trigger the WARN_ON_ONCE anymore.
--- net/core/sock_map.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
net/core/sock_map.c +10 -6
@@ -1639,19 +1639,23 @@ void sock_map_close(struct sock *sk, lonlock_sock (sk);rcu_read_lock (); - psock =sk_psock_get (sk); -if (unlikely (!psock)) { -rcu_read_unlock (); -release_sock (sk); - saved_close =READ_ONCE (sk->sk_prot)->close; - }else { + psock =sk_psock (sk); +if (likely (psock)) { saved_close = psock->saved_close;sock_map_remove_links (sk, psock); + psock =sk_psock_get (sk); +if (unlikely (!psock)) + goto no_psock;rcu_read_unlock ();sk_psock_stop (psock);release_sock (sk);cancel_delayed_work_sync (&psock->work);sk_psock_put (sk, psock); + }else { + saved_close =READ_ONCE (sk->sk_prot)->close; +no_psock: +rcu_read_unlock (); +release_sock (sk); }/* Make sure we do not recurse. This is a bug.
Greg Kroah-Hartman
maintainerPATCH 199/267 dma-buf: handle testing kthreads creation failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fedor Pchelkin <[email protected]>
commit 6cb05d89fd62a76a9b74bd16211fb0930e89fea8 upstream.
kthread creation may possibly fail inside race_signal_callback(). In such a case stop the already started threads, put the already taken references to them and return with error code.
Found by Linux Verification Center (linuxtesting.org).
--- drivers/dma-buf/st-dma-fence.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/dma-buf/st-dma-fence.c +6 -0
@@ -540,6 +540,12 @@ static int race_signal_callback(void *ar t[i].before = pass; t[i].task =kthread_run (thread_signal_callback, &t[i],"dma-fence:%d" , i); +if (IS_ERR (t[i].task)) { + ret =PTR_ERR (t[i].task); +while (--i >=0 ) +kthread_stop_put (t[i].task); +return ret; + }get_task_struct (t[i].task); }
Greg Kroah-Hartman
maintainerPATCH 200/267 vmci: prevent speculation leaks by sanitizing event in event_deliver()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hagar Gamal Halim Hemdan <[email protected]>
commit 8003f00d895310d409b2bf9ef907c56b42a4e0f4 upstream.
Coverity spotted that event_msg is controlled by user-space, event_msg->event_data.event is passed to event_deliver() and used as an index without sanitization.
This change ensures that the event index is sanitized to mitigate any possibility of speculative information leaks.
This bug was discovered and resolved using Coverity Static Analysis Security Testing (SAST) by Synopsys, Inc.
Only compile tested, no access to HW.
--- drivers/misc/vmw_vmci/vmci_event.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/misc/vmw_vmci/vmci_event.c +5 -1
@@ -9,6 +9,7 @@#include <linux/vmw_vmci_api.h> #include <linux/list.h> #include <linux/module.h> +#include <linux/nospec.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/rculist.h>
@@ -86,9 +87,12 @@ static void event_deliver(struct vmci_ev {struct vmci_subscription *cur;struct list_head *subscriber_list; +u32 sanitized_event, max_vmci_event;rcu_read_lock (); - subscriber_list = &subscriber_array[event_msg->event_data.event]; + max_vmci_event =ARRAY_SIZE (subscriber_array); + sanitized_event =array_index_nospec (event_msg->event_data.event, max_vmci_event); + subscriber_list = &subscriber_array[sanitized_event];list_for_each_entry_rcu (cur, subscriber_list, node) { cur->callback (cur->id, &event_msg->event_data, cur->callback_data);
Greg Kroah-Hartman
maintainerPATCH 201/267 spmi: hisi-spmi-controller: Do not override device identifier
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vamshi Gajjela <[email protected]>
commit eda4923d78d634482227c0b189d9b7ca18824146 upstream.
'nr' member of struct spmi_controller, which serves as an identifier for the controller/bus. This value is a dynamic ID assigned in spmi_controller_alloc, and overriding it from the driver results in an ida_free error "ida_free called for id=xx which is not allocated".
--- drivers/spmi/hisi-spmi-controller.c | 1 - 1 file changed, 1 deletion(-)
drivers/spmi/hisi-spmi-controller.c +0 -1
@@ -303,7 +303,6 @@ static int spmi_controller_probe(structspin_lock_init (&spmi_controller->lock); - ctrl->nr = spmi_controller->channel; ctrl->dev.parent = pdev->dev.parent; ctrl->dev.of_node =of_node_get (pdev->dev.of_node);
Greg Kroah-Hartman
maintainerPATCH 202/267 knfsd: LOOKUP can return an illegal error value
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Trond Myklebust <[email protected]>
commit e221c45da3770962418fb30c27d941bbc70d595a upstream.
The 'NFS error' NFSERR_OPNOTSUPP is not described by any of the official NFS related RFCs, but appears to have snuck into some older .x files for NFSv2.
Either way, it is not in RFC1094, RFC1813 or any of the NFSv4 RFCs, so should not be returned by the knfsd server, and particularly not by the "LOOKUP" operation.
Instead, let's return NFSERR_STALE, which is more appropriate if the filesystem encodes the filehandle as FILEID_INVALID.
--- fs/nfsd/nfsfh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/nfsd/nfsfh.c +2 -2
@@ -572,7 +572,7 @@ fh_compose(struct svc_fh *fhp, struct sv_fh_update (fhp, exp, dentry);if (fhp->fh_handle.fh_fileid_type ==FILEID_INVALID ) {fh_put (fhp); -return nfserr_opnotsupp; +return nfserr_stale; }return 0 ;
@@ -598,7 +598,7 @@ fh_update(struct svc_fh *fhp)_fh_update (fhp, fhp->fh_export, dentry);if (fhp->fh_handle.fh_fileid_type ==FILEID_INVALID ) -return nfserr_opnotsupp; +return nfserr_stale;return 0 ; out_bad:printk (KERN_ERR "fh_update: fh not verified!\n" );
Greg Kroah-Hartman
maintainerPATCH 203/267 fs/proc: fix softlockup in __read_vmcore
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rik van Riel <[email protected]>
commit 5cbcb62dddf5346077feb82b7b0c9254222d3445 upstream.
While taking a kernel core dump with makedumpfile on a larger system, softlockup messages often appear.
While softlockup warnings can be harmless, they can also interfere with things like RCU freeing memory, which can be problematic when the kdump kexec image is configured with as little memory as possible.
Avoid the softlockup, and give things like work items and RCU a chance to do their thing during __read_vmcore by adding a cond_resched.
--- fs/proc/vmcore.c | 2 ++ 1 file changed, 2 insertions(+)
fs/proc/vmcore.c +2 -0
@@ -383,6 +383,8 @@ static ssize_t __read_vmcore(struct iov_/* leave now if filled buffer already */ if (!iov_iter_count (iter))return acc; + +cond_resched (); }list_for_each_entry (m, &vmcore_list, list) {
Greg Kroah-Hartman
maintainerPATCH 204/267 ocfs2: use coarse time for new created files
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Su Yue <[email protected]>
commit b8cb324277ee16f3eca3055b96fce4735a5a41c6 upstream.
The default atime related mount option is '-o realtime' which means file atime should be updated if atime <= ctime or atime <= mtime. atime should be updated in the following scenario, but it is not:
==========================================================
$ rm /mnt/testfile; $ echo test > /mnt/testfile $ stat -c "%X %Y %Z" /mnt/testfile 1711881646 1711881646 1711881646 $ sleep 5 $ cat /mnt/testfile > /dev/null $ stat -c "%X %Y %Z" /mnt/testfile 1711881646 1711881646 1711881646 ==========================================================
And the reason the atime in the test is not updated is that ocfs2 calls ktime_get_real_ts64() in __ocfs2_mknod_locked during file creation. Then inode_set_ctime_current() is called in inode_set_ctime_current() calls ktime_get_coarse_real_ts64() to get current time.
ktime_get_real_ts64() is more accurate than ktime_get_coarse_real_ts64(). In my test box, I saw ctime set by ktime_get_coarse_real_ts64() is less than ktime_get_real_ts64() even ctime is set later. The ctime of the new inode is smaller than atime.
The call trace is like:
ocfs2_create
ocfs2_mknod
__ocfs2_mknod_locked
....
ktime_get_real_ts64 <------- set atime,ctime,mtime, more accurate
ocfs2_populate_inode
...
ocfs2_init_acl
ocfs2_acl_set_mode
inode_set_ctime_current
current_time
ktime_get_coarse_real_ts64 <-------less accurateocfs2_file_read_iter
ocfs2_inode_lock_atime
ocfs2_should_update_atime
atime <= ctime ? <-------- false, ctime < atime due to accuracy
So here call ktime_get_coarse_real_ts64 to set inode time coarser while creating new files. It may lower the accuracy of file times. But it's not a big deal since we already use coarse time in other places like ocfs2_update_inode_atime and inode_set_ctime_current.
--- fs/ocfs2/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ocfs2/namei.c +1 -1
@@ -566,7 +566,7 @@ static int __ocfs2_mknod_locked(struct i fe->i_last_eb_blk =0 ;strcpy (fe->i_signature,OCFS2_INODE_SIGNATURE ); fe->i_flags |=cpu_to_le32 (OCFS2_VALID_FL ); -ktime_get_real_ts64 (&ts); +ktime_get_coarse_real_ts64 (&ts); fe->i_atime = fe->i_ctime = fe->i_mtime =cpu_to_le64 (ts.tv_sec); fe->i_mtime_nsec = fe->i_ctime_nsec = fe->i_atime_nsec =
Greg Kroah-Hartman
maintainerPATCH 205/267 ocfs2: fix races between hole punching and AIO+DIO
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Su Yue <[email protected]>
commit 952b023f06a24b2ad6ba67304c4c84d45bea2f18 upstream.
After commit "ocfs2: return real error code in ocfs2_dio_wr_get_block", fstests/generic/300 become from always failed to sometimes failed:
========================================================================
[ 473.293420 ] run fstests generic/300
[ 475.296983 ] JBD2: Ignoring recovery information on journal [ 475.302473 ] ocfs2: Mounting device (253,1) on (node local, slot 0) with ordered data mode. [ 494.290998 ] OCFS2: ERROR (device dm-1): ocfs2_change_extent_flag: Owner 5668 has an extent at cpos 78723 which can no longer be found [ 494.291609 ] On-disk corruption discovered. Please run fsck.ocfs2 once the filesystem is unmounted. [ 494.292018 ] OCFS2: File system is now read-only. [ 494.292224 ] (kworker/19:11,2628,19):ocfs2_mark_extent_written:5272 ERROR: status = -30 [ 494.292602 ] (kworker/19:11,2628,19):ocfs2_dio_end_io_write:2374 ERROR: status = -3
fio: io_u error on file /mnt/scratch/racer: Read-only file system: write offset=460849152, buflen=131072
=========================================================================
In __blockdev_direct_IO, ocfs2_dio_wr_get_block is called to add unwritten extents to a list. extents are also inserted into extent tree in ocfs2_write_begin_nolock. Then another thread call fallocate to puch a hole at one of the unwritten extent. The extent at cpos was removed by ocfs2_remove_extent(). At end io worker thread, ocfs2_search_extent_list found there is no such extent at the cpos.
T1 T2 T3
inode lock
...
insert extents
...
inode unlockocfs2_fallocate
__ocfs2_change_file_space
inode lock
lock ip_alloc_sem
ocfs2_remove_inode_range inode
ocfs2_remove_btree_range
ocfs2_remove_extent
^---remove the extent at cpos 78723 ...
unlock ip_alloc_sem
inode unlock
ocfs2_dio_end_io
ocfs2_dio_end_io_write
lock ip_alloc_sem ocfs2_mark_extent_written
ocfs2_change_extent_flag
ocfs2_search_extent_list ^---failed to find extent
...
unlock ip_alloc_sem
In most filesystems, fallocate is not compatible with racing with AIO+DIO, so fix it by adding to wait for all dio before fallocate/punch_hole like ext4.
--- fs/ocfs2/file.c | 2 ++ 1 file changed, 2 insertions(+)
fs/ocfs2/file.c +2 -0
@@ -1934,6 +1934,8 @@ static int __ocfs2_change_file_space(strinode_lock (inode); +/* Wait all existing dio workers, newcomers will block on i_rwsem */ +inode_dio_wait (inode);/* * This prevents concurrent writes on other nodes */
Greg Kroah-Hartman
maintainerPATCH 206/267 PCI: rockchip-ep: Remove wrong mask on subsys_vendor_id
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rick Wertenbroek <[email protected]>
commit 2dba285caba53f309d6060fca911b43d63f41697 upstream.
Remove wrong mask on subsys_vendor_id. Both the Vendor ID and Subsystem Vendor ID are u16 variables and are written to a u32 register of the controller. The Subsystem Vendor ID was always 0 because the u16 value was masked incorrectly with GENMASK(31,16) resulting in all lower 16 bits being set to 0 prior to the shift.
Remove both masks as they are unnecessary and set the register correctly i.e., the lower 16-bits are the Vendor ID and the upper 16-bits are the Subsystem Vendor ID.
This is documented in the RK3399 TRM section 17.6.7.1.17
--- drivers/pci/controller/pcie-rockchip-ep.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/pci/controller/pcie-rockchip-ep.c +2 -4
@@ -98,10 +98,8 @@ static int rockchip_pcie_ep_write_header/* All functions share the same vendor ID with function 0 */ if (fn ==0 ) { -u32 vid_regs = (hdr->vendorid &GENMASK (15 ,0 )) | - (hdr->subsys_vendor_id &GENMASK (31 ,16 )) <<16 ; - -rockchip_pcie_write (rockchip, vid_regs, +rockchip_pcie_write (rockchip, + hdr->vendorid | hdr->subsys_vendor_id <<16 ,PCIE_CORE_CONFIG_VENDOR ); }
Greg Kroah-Hartman
maintainerPATCH 207/267 dmaengine: axi-dmac: fix possible race in remove()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nuno Sa <[email protected]>
commit 1bc31444209c8efae98cb78818131950d9a6f4d6 upstream.
We need to first free the IRQ before calling of_dma_controller_free(). Otherwise we could get an interrupt and schedule a tasklet while removing the DMA controller.
--- drivers/dma/dma-axi-dmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma/dma-axi-dmac.c +1 -1
@@ -1033,8 +1033,8 @@ static int axi_dmac_remove(struct platfo {struct axi_dmac *dmac =platform_get_drvdata (pdev); -of_dma_controller_free (pdev->dev.of_node);free_irq (dmac->irq, dmac); +of_dma_controller_free (pdev->dev.of_node);tasklet_kill (&dmac->chan.vchan.task);dma_async_device_unregister (&dmac->dma_dev);clk_disable_unprepare (dmac->clk);
Greg Kroah-Hartman
maintainerPATCH 208/267 remoteproc: k3-r5: Wait for core0 power-up before powering up core1
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Apurva Nandan <[email protected]>
commit 61f6f68447aba08aeaa97593af3a7d85a114891f upstream.
PSC controller has a limitation that it can only power-up the second core when the first core is in ON state. Power-state for core0 should be equal to or higher than core1, else the kernel is seen hanging during rproc loading.
Make the powering up of cores sequential, by waiting for the current core to power-up before proceeding to the next core, with a timeout of 2sec. Add a wait queue event in k3_r5_cluster_rproc_init call, that will wait for the current core to be released from reset before proceeding with the next core.
--- drivers/remoteproc/ti_k3_r5_remoteproc.c | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
drivers/remoteproc/ti_k3_r5_remoteproc.c +33 -0
@@ -103,12 +103,14 @@ struct k3_r5_soc_data {* @dev: cached device pointer * @mode: Mode to configure the Cluster - Split or LockStep * @cores: list of R5 cores within the cluster +* @core_transition: wait queue to sync core state changes * @soc_data: SoC-specific feature data for a R5FSS */ struct k3_r5_cluster {struct device *dev;enum cluster_mode mode;struct list_head cores; +wait_queue_head_t core_transition;const struct k3_r5_soc_data *soc_data; };
@@ -128,6 +130,7 @@ struct k3_r5_cluster {* @atcm_enable: flag to control ATCM enablement * @btcm_enable: flag to control BTCM enablement * @loczrama: flag to dictate which TCM is at device address 0x0 +* @released_from_reset: flag to signal when core is out of reset */ struct k3_r5_core {struct list_head elem;
@@ -144,6 +147,7 @@ struct k3_r5_core {u32 atcm_enable;u32 btcm_enable;u32 loczrama; +bool released_from_reset; };/**
@@ -460,6 +464,8 @@ static int k3_r5_rproc_prepare(struct rp ret);return ret; } + core->released_from_reset = true; +wake_up_interruptible (&cluster->core_transition);/* * Newer IP revisions like on J7200 SoCs support h/w auto-initialization
@@ -1140,6 +1146,12 @@ static int k3_r5_rproc_configure_mode(streturn ret; } +/* +* Skip the waiting mechanism for sequential power-on of cores if the +* core has already been booted by another entity. +*/ + core->released_from_reset = c_state; + ret =ti_sci_proc_get_status (core->tsp, &boot_vec, &cfg, &ctrl, &stat);if (ret <0 ) {
@@ -1280,6 +1292,26 @@ init_rmem: cluster->mode ==CLUSTER_MODE_SINGLECPU || cluster->mode == CLUSTER_MODE_SINGLECORE) break; + +/* +* R5 cores require to be powered on sequentially, core0 +* should be in higher power state than core1 in a cluster +* So, wait for current core to power up before proceeding +* to next core and put timeout of 2sec for each core. +* +* This waiting mechanism is necessary because +* rproc_auto_boot_callback() for core1 can be called before +* core0 due to thread execution order. +*/ + ret =wait_event_interruptible_timeout (cluster->core_transition, + core->released_from_reset, +msecs_to_jiffies (2000 )); +if (ret <=0 ) { +dev_err (dev, +"Timed out waiting for %s core to power up!\n" , + rproc->name); +return ret; + } }return 0 ;
@@ -1709,6 +1741,7 @@ static int k3_r5_probe(struct platform_d cluster->dev = dev; cluster->soc_data = data;INIT_LIST_HEAD (&cluster->cores); +init_waitqueue_head (&cluster->core_transition); ret =of_property_read_u32 (np,"ti,cluster-mode" , &cluster->mode);if (ret <0 && ret != -EINVAL ) {
Greg Kroah-Hartman
maintainerPATCH 209/267 remoteproc: k3-r5: Do not allow core1 to power up before core0 via sysfs
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Beleswar Padhi <[email protected]>
commit 3c8a9066d584f5010b6f4ba03bf6b19d28973d52 upstream.
PSC controller has a limitation that it can only power-up the second core when the first core is in ON state. Power-state for core0 should be equal to or higher than core1.
Therefore, prevent core1 from powering up before core0 during the start process from sysfs. Similarly, prevent core0 from shutting down before core1 has been shut down from sysfs.
--- drivers/remoteproc/ti_k3_r5_remoteproc.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)
drivers/remoteproc/ti_k3_r5_remoteproc.c +21 -2
@@ -548,7 +548,7 @@ static int k3_r5_rproc_start(struct rprostruct k3_r5_rproc *kproc = rproc->priv;struct k3_r5_cluster *cluster = kproc->cluster;struct device *dev = kproc->dev; -struct k3_r5_core *core; +struct k3_r5_core *core0, *core;u32 boot_addr;int ret;
@@ -574,6 +574,15 @@ static int k3_r5_rproc_start(struct rpro goto unroll_core_run; } }else { +/* do not allow core 1 to start before core 0 */ + core0 = list_first_entry(&cluster->cores, struct k3_r5_core, + elem); +if (core != core0 && core0->rproc->state ==RPROC_OFFLINE ) { +dev_err (dev,"%s: can not start core 1 before core 0\n" , + __func__); +return -EPERM ; + } + ret =k3_r5_core_run (core);if (ret) goto put_mbox;
@@ -619,7 +628,8 @@ static int k3_r5_rproc_stop(struct rproc {struct k3_r5_rproc *kproc = rproc->priv;struct k3_r5_cluster *cluster = kproc->cluster; -struct k3_r5_core *core = kproc->core; +struct device *dev = kproc->dev; +struct k3_r5_core *core1, *core = kproc->core;int ret;/* halt all applicable cores */
@@ -632,6 +642,15 @@ static int k3_r5_rproc_stop(struct rproc } } }else { +/* do not allow core 0 to stop before core 1 */ + core1 = list_last_entry(&cluster->cores, struct k3_r5_core, + elem); +if (core != core1 && core1->rproc->state !=RPROC_OFFLINE ) { +dev_err (dev,"%s: can not stop core 0 before core 1\n" , + __func__); +return -EPERM ; + } + ret =k3_r5_core_halt (core);if (ret) goto out;
Greg Kroah-Hartman
maintainerPATCH 210/267 iio: adc: axi-adc: make sure AXI clock is enabled
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nuno Sa <[email protected]>
commit 80721776c5af6f6dce7d84ba8df063957aa425a2 upstream.
We can only access the IP core registers if the bus clock is enabled. As such we need to get and enable it and not rely on anyone else to do it.
Note this clock is a very fundamental one that is typically enabled pretty early during boot. Independently of that, we should really rely on it to be enabled.
--- drivers/iio/adc/adi-axi-adc.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/iio/adc/adi-axi-adc.c +5 -0
@@ -175,6 +175,7 @@ static int adi_axi_adc_probe(struct platstruct adi_axi_adc_state *st;void __iomem *base;unsigned int ver; +struct clk *clk;int ret; st =devm_kzalloc (&pdev->dev,sizeof (*st),GFP_KERNEL );
@@ -195,6 +196,10 @@ static int adi_axi_adc_probe(struct platif (!expected_ver)return -ENODEV ; + clk =devm_clk_get_enabled (&pdev->dev,NULL ); +if (IS_ERR (clk)) +return PTR_ERR (clk); +/* * Force disable the core. Up to the frontend to enable us. And we can * still read/write registers...
Greg Kroah-Hartman
maintainerPATCH 211/267 iio: invensense: fix interrupt timestamp alignment
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jean-Baptiste Maneyrol <[email protected]>
commit 0340dc4c82590d8735c58cf904a8aa1173273ab5 upstream.
Restrict interrupt timestamp alignment for not overflowing max/min period thresholds.
--- drivers/iio/common/inv_sensors/inv_sensors_timestamp.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/iio/common/inv_sensors/inv_sensors_timestamp.c +7 -2
@@ -105,6 +105,9 @@ static bool inv_update_chip_period(strucstatic void inv_align_timestamp_it (struct inv_sensors_timestamp *ts) { +const int64_t period_min = ts->min_period * ts->mult; +const int64_t period_max = ts->max_period * ts->mult; +int64_t add_max, sub_max;int64_t delta, jitter;int64_t adjust;
@@ -112,11 +115,13 @@ static void inv_align_timestamp_it(struc delta = ts->it.lo - ts->timestamp;/* adjust timestamp while respecting jitter */ + add_max = period_max - (int64_t )ts->period; + sub_max = period_min - (int64_t )ts->period; jitter =INV_SENSORS_TIMESTAMP_JITTER ((int64_t )ts->period, ts->chip.jitter);if (delta > jitter) - adjust = jitter; + adjust = add_max;else if (delta < -jitter) - adjust = -jitter; + adjust = sub_max;else adjust =0 ;
Greg Kroah-Hartman
maintainerPATCH 212/267 riscv: rewrite __kernel_map_pages() to fix sleeping in invalid context
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nam Cao <[email protected]>
commit fb1cf0878328fe75d47f0aed0a65b30126fcefc4 upstream.
__kernel_map_pages() is a debug function which clears the valid bit in page table entry for deallocated pages to detect illegal memory accesses to freed pages.
This function set/clear the valid bit using __set_memory(). __set_memory() acquires init_mm's semaphore, and this operation may sleep. This is problematic, because __kernel_map_pages() can be called in atomic context, and thus is illegal to sleep. An example warning that this causes:
BUG: sleeping function called from invalid context at kernel/locking/rwsem.c:1578 in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 2, name: kthreadd preempt_count: 2, expected: 0 CPU: 0 PID: 2 Comm: kthreadd Not tainted 6.9.0-g1d4c6d784ef6 #37 Hardware name: riscv-virtio,qemu (DT) Call Trace: [<ffffffff800060dc>] dump_backtrace+0x1c/0x24 [<ffffffff8091ef6e>] show_stack+0x2c/0x38 [<ffffffff8092baf8>] dump_stack_lvl+0x5a/0x72 [<ffffffff8092bb24>] dump_stack+0x14/0x1c [<ffffffff8003b7ac>] __might_resched+0x104/0x10e [<ffffffff8003b7f4>] __might_sleep+0x3e/0x62 [<ffffffff8093276a>] down_write+0x20/0x72 [<ffffffff8000cf00>] __set_memory+0x82/0x2fa [<ffffffff8000d324>] __kernel_map_pages+0x5a/0xd4 [<ffffffff80196cca>] __alloc_pages_bulk+0x3b2/0x43a [<ffffffff8018ee82>] __vmalloc_node_range+0x196/0x6ba [<ffffffff80011904>] copy_process+0x72c/0x17ec [<ffffffff80012ab4>] kernel_clone+0x60/0x2fe [<ffffffff80012f62>] kernel_thread+0x82/0xa0 [<ffffffff8003552c>] kthreadd+0x14a/0x1be [<ffffffff809357de>] ret_from_fork+0xe/0x1c
Rewrite this function with apply_to_existing_page_range(). It is fine to not have any locking, because __kernel_map_pages() works with pages being allocated/deallocated and those pages are not changed by anyone else in the meantime.
--- arch/riscv/mm/pageattr.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-)
arch/riscv/mm/pageattr.c +22 -6
@@ -387,17 +387,33 @@ int set_direct_map_default_noflush(struc }#ifdef CONFIG_DEBUG_PAGEALLOC +static int debug_pagealloc_set_page (pte_t *pte,unsigned long addr,void *data) +{ +int enable = *(int *)data; + +unsigned long val =pte_val (ptep_get (pte)); + +if (enable) + val |= _PAGE_PRESENT; +else + val &= ~_PAGE_PRESENT; + +set_pte (pte,__pte (val)); + +return 0 ; +} +void __kernel_map_pages (struct page *page,int numpages,int enable) {if (!debug_pagealloc_enabled ())return ; -if (enable) -__set_memory ((unsigned long )page_address (page), numpages, -__pgprot (_PAGE_PRESENT),__pgprot (0 )); -else -__set_memory ((unsigned long )page_address (page), numpages, -__pgprot (0 ),__pgprot (_PAGE_PRESENT)); +unsigned long start = (unsigned long )page_address (page); +unsigned long size =PAGE_SIZE * numpages; + +apply_to_existing_page_range (&init_mm, start, size, debug_pagealloc_set_page, &enable); + +flush_tlb_kernel_range (start, start + size); }#endif
Greg Kroah-Hartman
maintainerPATCH 213/267 rtla/timerlat: Simplify "no value" printing on top
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Bristot de Oliveira <[email protected]>
commit 5f0769331a965675cdfec97c09f3f6e875d7c246 upstream.
Instead of printing three times the same output, print it only once, reducing lines and being sure that all no values have the same length.
It also fixes an extra '\n' when running the with kernel threads, like here:
=============== %< ==============
Timer Latency0 00:00:01 | IRQ Timer Latency (us) | Thread Timer Latency (us) CPU COUNT | cur min avg max | cur min avg max 2 #0 | - - - - | 161 161 161 161 3 #0 | - - - - | 161 161 161 161 8 #1 | 54 54 54 54 | - - - -'\n'
---------------|----------------------------------------|---------------------------------------
ALL #1 e0 | 54 54 54 | 161 161 161
=============== %< ==============This '\n' should have been removed with the user-space support that added another '\n' if not running with kernel threads.
--- tools/tracing/rtla/src/timerlat_top.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-)
tools/tracing/rtla/src/timerlat_top.c +5 -12
@@ -211,6 +211,8 @@ static void timerlat_top_header(struct otrace_seq_printf (s,"\n" ); } +static const char *no_value =" -" ; +/* * timerlat_top_print - prints the output of a given CPU */
@@ -238,10 +240,7 @@ static void timerlat_top_print(struct ostrace_seq_printf (s,"%3d #%-9d |" , cpu, cpu_data->irq_count);if (!cpu_data->irq_count) { -trace_seq_printf (s," - " ); -trace_seq_printf (s," - " ); -trace_seq_printf (s," - " ); -trace_seq_printf (s," - |" ); +trace_seq_printf (s,"%s %s %s %s |" , no_value, no_value, no_value, no_value); }else {trace_seq_printf (s,"%9llu " , cpu_data->cur_irq / params->output_divisor);trace_seq_printf (s,"%9llu " , cpu_data->min_irq / params->output_divisor);
@@ -250,10 +249,7 @@ static void timerlat_top_print(struct os }if (!cpu_data->thread_count) { -trace_seq_printf (s," - " ); -trace_seq_printf (s," - " ); -trace_seq_printf (s," - " ); -trace_seq_printf (s," -\n" ); +trace_seq_printf (s,"%s %s %s %s" , no_value, no_value, no_value, no_value); }else {trace_seq_printf (s,"%9llu " , cpu_data->cur_thread / divisor);trace_seq_printf (s,"%9llu " , cpu_data->min_thread / divisor);
@@ -270,10 +266,7 @@ static void timerlat_top_print(struct ostrace_seq_printf (s," |" );if (!cpu_data->user_count) { -trace_seq_printf (s," - " ); -trace_seq_printf (s," - " ); -trace_seq_printf (s," - " ); -trace_seq_printf (s," -\n" ); +trace_seq_printf (s,"%s %s %s %s\n" , no_value, no_value, no_value, no_value); }else {trace_seq_printf (s,"%9llu " , cpu_data->cur_user / divisor);trace_seq_printf (s,"%9llu " , cpu_data->min_user / divisor);
Greg Kroah-Hartman
maintainerPATCH 214/267 rtla/auto-analysis: Replace \t with spaces
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Bristot de Oliveira <[email protected]>
commit a40e5e4dd0207485dee75e2b8e860d5853bcc5f7 upstream.
When copying timerlat auto-analysis from a terminal to some web pages or
chats, the \t are being replaced with a single ' ' or ' ', breaking
the output.
For example:
## CPU 3 hit stop tracing, analyzing it ##
IRQ handler delay: 1.30 us (0.11 %)
IRQ latency: 1.90 us
Timerlat IRQ duration: 3.00 us (0.24 %)
Blocking thread: 1223.16 us (99.00 %)
insync:4048 1223.16 us
IRQ interference 4.93 us (0.40 %)
local_timer:236 4.93 us
------------------------------------------------------------------------
Thread latency: 1235.47 us (100%)Replace \t with spaces to avoid this problem.
--- tools/tracing/rtla/src/timerlat_aa.c | 111 ++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 47 deletions(-)
tools/tracing/rtla/src/timerlat_aa.c +64 -47
@@ -16,6 +16,9 @@ enum timelat_state { TIMERLAT_WAITING_THREAD, }; +/* Used to fill spaces in the output */ +static const char *spaces =" " ; +#define MAX_COMM 24/*
@@ -274,14 +277,17 @@ static int timerlat_aa_nmi_handler(struc taa_data->prev_irq_timstamp = start;trace_seq_reset (taa_data->prev_irqs_seq); -trace_seq_printf (taa_data->prev_irqs_seq,"\t%24s \t\t\t%9.2f us\n" , -"nmi" ,ns_to_usf (duration)); +trace_seq_printf (taa_data->prev_irqs_seq," %24s %.*s %9.2f us\n" , +"nmi" , +24 , spaces, +ns_to_usf (duration));return 0 ; } taa_data->thread_nmi_sum += duration; -trace_seq_printf (taa_data->nmi_seq," %24s \t\t\t%9.2f us\n" , -"nmi" ,ns_to_usf (duration)); +trace_seq_printf (taa_data->nmi_seq," %24s %.*s %9.2f us\n" , +"nmi" , +24 , spaces,ns_to_usf (duration));return 0 ; }
@@ -323,8 +329,10 @@ static int timerlat_aa_irq_handler(struc taa_data->prev_irq_timstamp = start;trace_seq_reset (taa_data->prev_irqs_seq); -trace_seq_printf (taa_data->prev_irqs_seq,"\t%24s:%-3llu \t\t%9.2f us\n" , - desc, vector,ns_to_usf (duration)); +trace_seq_printf (taa_data->prev_irqs_seq," %24s:%-3llu %.*s %9.2f us\n" , + desc, vector, +15 , spaces, +ns_to_usf (duration));return 0 ; }
@@ -372,8 +380,10 @@ static int timerlat_aa_irq_handler(struc* IRQ interference. */ taa_data->thread_irq_sum += duration; -trace_seq_printf (taa_data->irqs_seq," %24s:%-3llu \t %9.2f us\n" , - desc, vector,ns_to_usf (duration)); +trace_seq_printf (taa_data->irqs_seq," %24s:%-3llu %.*s %9.2f us\n" , + desc, vector, +24 , spaces, +ns_to_usf (duration));return 0 ; }
@@ -408,8 +418,10 @@ static int timerlat_aa_softirq_handler(s taa_data->thread_softirq_sum += duration; -trace_seq_printf (taa_data->softirqs_seq,"\t%24s:%-3llu \t %9.2f us\n" , - softirq_name[vector], vector,ns_to_usf (duration)); +trace_seq_printf (taa_data->softirqs_seq," %24s:%-3llu %.*s %9.2f us\n" , + softirq_name[vector], vector, +24 , spaces, +ns_to_usf (duration));return 0 ; }
@@ -452,8 +464,10 @@ static int timerlat_aa_thread_handler(st }else { taa_data->thread_thread_sum += duration; -trace_seq_printf (taa_data->threads_seq,"\t%24s:%-3llu \t\t%9.2f us\n" , - comm, pid,ns_to_usf (duration)); +trace_seq_printf (taa_data->threads_seq," %24s:%-12llu %.*s %9.2f us\n" , + comm, pid, +15 , spaces, +ns_to_usf (duration)); }return 0 ;
@@ -482,7 +496,8 @@ static int timerlat_aa_stack_handler(str function =tep_find_function (taa_ctx->tool->trace.tep, caller[i]);if (!function)break ; -trace_seq_printf (taa_data->stack_seq,"\t\t-> %s\n" , function); +trace_seq_printf (taa_data->stack_seq," %.*s -> %s\n" , +14 , spaces, function); } }return 0 ;
@@ -568,23 +583,24 @@ static void timerlat_thread_analysis(str exp_irq_ts = taa_data->timer_irq_start_time - taa_data->timer_irq_start_delay;if (exp_irq_ts < taa_data->prev_irq_timstamp + taa_data->prev_irq_duration) {if (taa_data->prev_irq_timstamp < taa_data->timer_irq_start_time) -printf (" Previous IRQ interference: \t\t up to %9.2f us\n" , -ns_to_usf (taa_data->prev_irq_duration)); +printf (" Previous IRQ interference: %.*s up to %9.2f us\n" , +16 , spaces, +ns_to_usf (taa_data->prev_irq_duration)); }/* * The delay that the IRQ suffered before starting. */ -printf (" IRQ handler delay: %16s %9.2f us (%.2f %%)\n" , - (ns_to_usf (taa_data->timer_exit_from_idle) >10 ) ?"(exit from idle)" :"" , -ns_to_usf (taa_data->timer_irq_start_delay), -ns_to_per (total, taa_data->timer_irq_start_delay)); +printf (" IRQ handler delay: %.*s %16s %9.2f us (%.2f %%)\n" ,16 , spaces, + (ns_to_usf (taa_data->timer_exit_from_idle) >10 ) ?"(exit from idle)" :"" , +ns_to_usf (taa_data->timer_irq_start_delay), +ns_to_per (total, taa_data->timer_irq_start_delay));/* * Timerlat IRQ. */ -printf (" IRQ latency: \t\t\t\t %9.2f us\n" , -ns_to_usf (taa_data->tlat_irq_latency)); +printf (" IRQ latency: %.*s %9.2f us\n" ,40 , spaces, +ns_to_usf (taa_data->tlat_irq_latency));if (irq) {/*
@@ -595,15 +611,16 @@ static void timerlat_thread_analysis(str* so it will be displayed, it is the key. */ printf (" Blocking thread:\n" ); -printf (" %24s:%-9llu\n" , - taa_data->run_thread_comm, taa_data->run_thread_pid); +printf (" %.*s %24s:%-9llu\n" ,6 , spaces, taa_data->run_thread_comm, + taa_data->run_thread_pid); }else {/* * The duration of the IRQ handler that handled the timerlat IRQ. */ -printf (" Timerlat IRQ duration: \t\t %9.2f us (%.2f %%)\n" , -ns_to_usf (taa_data->timer_irq_duration), -ns_to_per (total, taa_data->timer_irq_duration)); +printf (" Timerlat IRQ duration: %.*s %9.2f us (%.2f %%)\n" , +30 , spaces, +ns_to_usf (taa_data->timer_irq_duration), +ns_to_per (total, taa_data->timer_irq_duration));/* * The amount of time that the current thread postponed the scheduler.
@@ -611,13 +628,13 @@ static void timerlat_thread_analysis(str* Recalling that it is net from NMI/IRQ/Softirq interference, so there * is no need to compute values here. */ -printf (" Blocking thread: \t\t\t %9.2f us (%.2f %%)\n" , -ns_to_usf (taa_data->thread_blocking_duration), -ns_to_per (total, taa_data->thread_blocking_duration)); - -printf (" %24s:%-9llu %9.2f us\n" , - taa_data->run_thread_comm, taa_data->run_thread_pid, -ns_to_usf (taa_data->thread_blocking_duration)); +printf (" Blocking thread: %.*s %9.2f us (%.2f %%)\n" ,36 , spaces, +ns_to_usf (taa_data->thread_blocking_duration), +ns_to_per (total, taa_data->thread_blocking_duration)); + +printf (" %.*s %24s:%-9llu %.*s %9.2f us\n" ,6 , spaces, + taa_data->run_thread_comm, taa_data->run_thread_pid, +12 , spaces,ns_to_usf (taa_data->thread_blocking_duration)); }/*
@@ -629,9 +646,9 @@ static void timerlat_thread_analysis(str* NMIs can happen during the IRQ, so they are always possible. */ if (taa_data->thread_nmi_sum) -printf (" NMI interference \t\t\t %9.2f us (%.2f %%)\n" , -ns_to_usf (taa_data->thread_nmi_sum), -ns_to_per (total, taa_data->thread_nmi_sum)); +printf (" NMI interference %.*s %9.2f us (%.2f %%)\n" ,36 , spaces, +ns_to_usf (taa_data->thread_nmi_sum), +ns_to_per (total, taa_data->thread_nmi_sum));/* * If it is an IRQ latency, the other factors can be skipped.
@@ -643,9 +660,9 @@ static void timerlat_thread_analysis(str* Prints the interference caused by IRQs to the thread latency. */ if (taa_data->thread_irq_sum) { -printf (" IRQ interference \t\t\t %9.2f us (%.2f %%)\n" , -ns_to_usf (taa_data->thread_irq_sum), -ns_to_per (total, taa_data->thread_irq_sum)); +printf (" IRQ interference %.*s %9.2f us (%.2f %%)\n" ,36 , spaces, +ns_to_usf (taa_data->thread_irq_sum), +ns_to_per (total, taa_data->thread_irq_sum));trace_seq_do_printf (taa_data->irqs_seq); }
@@ -654,9 +671,9 @@ static void timerlat_thread_analysis(str* Prints the interference caused by Softirqs to the thread latency. */ if (taa_data->thread_softirq_sum) { -printf (" Softirq interference \t\t\t %9.2f us (%.2f %%)\n" , -ns_to_usf (taa_data->thread_softirq_sum), -ns_to_per (total, taa_data->thread_softirq_sum)); +printf (" Softirq interference %.*s %9.2f us (%.2f %%)\n" ,32 , spaces, +ns_to_usf (taa_data->thread_softirq_sum), +ns_to_per (total, taa_data->thread_softirq_sum));trace_seq_do_printf (taa_data->softirqs_seq); }
@@ -670,9 +687,9 @@ static void timerlat_thread_analysis(str* timer handling latency. */ if (taa_data->thread_thread_sum) { -printf (" Thread interference \t\t\t %9.2f us (%.2f %%)\n" , -ns_to_usf (taa_data->thread_thread_sum), -ns_to_per (total, taa_data->thread_thread_sum)); +printf (" Thread interference %.*s %9.2f us (%.2f %%)\n" ,33 , spaces, +ns_to_usf (taa_data->thread_thread_sum), +ns_to_per (total, taa_data->thread_thread_sum));trace_seq_do_printf (taa_data->threads_seq); }
@@ -682,8 +699,8 @@ static void timerlat_thread_analysis(str*/ print_total:printf ("------------------------------------------------------------------------\n" ); -printf (" %s latency: \t\t\t %9.2f us (100%%)\n" , irq ?"IRQ" :"Thread" , -ns_to_usf (total)); +printf (" %s latency: %.*s %9.2f us (100%%)\n" , irq ?" IRQ" :"Thread" , +37 , spaces,ns_to_usf (total)); }static int timerlat_auto_analysis_collect_trace (struct timerlat_aa_context *taa_ctx)
Greg Kroah-Hartman
maintainerPATCH 215/267 drm/i915/gt: Disarm breadcrumbs if engines are already idle
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris Wilson <[email protected]>
commit 70cb9188ffc75e643debf292fcddff36c9dbd4ae upstream.
The breadcrumbs use a GT wakeref for guarding the interrupt, but are disarmed during release of the engine wakeref. This leaves a hole where we may attach a breadcrumb just as the engine is parking (after it has parked its breadcrumbs), execute the irq worker with some signalers still attached, but never be woken again.
That issue manifests itself in CI with IGT runner timeouts while tests are waiting indefinitely for release of all GT wakerefs.
<6> [209.151778] i915: Running live_engine_pm_selftests/live_engine_busy_stats
<7> [209.231628] i915 0000:00:02.0: [drm:intel_power_well_disable [i915]] disabling PW_5 <7> [209.231816] i915 0000:00:02.0: [drm:intel_power_well_disable [i915]] disabling PW_4 <7> [209.231944] i915 0000:00:02.0: [drm:intel_power_well_disable [i915]] disabling PW_3 <7> [209.232056] i915 0000:00:02.0: [drm:intel_power_well_disable [i915]] disabling PW_2 <7> [209.232166] i915 0000:00:02.0: [drm:intel_power_well_disable [i915]] disabling DC_off <7> [209.232270] i915 0000:00:02.0: [drm:skl_enable_dc6 [i915]] Enabling DC6
<7> [209.232368] i915 0000:00:02.0: [drm:gen9_set_dc_state.part.0 [i915]] Setting DC state from 00 to 02 <4> [299.356116] [IGT] Inactivity timeout exceeded. Killing the current test with SIGQUIT.
...
<6> [299.356526] sysrq: Show State
...
<6> [299.373964] task:i915_selftest state:D stack:11784 pid:5578 tgid:5578 ppid:873 flags:0x00004002
<6> [299.373967] Call Trace:
<6> [299.373968] <TASK> <6> [299.373970] __schedule+0x3bb/0xda0 <6> [299.373974] schedule+0x41/0x110 <6> [299.373976] intel_wakeref_wait_for_idle+0x82/0x100 [i915] <6> [299.374083] ? __pfx_var_wake_function+0x10/0x10 <6> [299.374087] live_engine_busy_stats+0x9b/0x500 [i915] <6> [299.374173] __i915_subtests+0xbe/0x240 [i915] <6> [299.374277] ? __pfx___intel_gt_live_setup+0x10/0x10 [i915] <6> [299.374369] ? __pfx___intel_gt_live_teardown+0x10/0x10 [i915] <6> [299.374456] intel_engine_live_selftests+0x1c/0x30 [i915] <6> [299.374547] __run_selftests+0xbb/0x190 [i915] <6> [299.374635] i915_live_selftests+0x4b/0x90 [i915] <6> [299.374717] i915_pci_probe+0x10d/0x210 [i915]
At the end of the interrupt worker, if there are no more engines awake, disarm the breadcrumb and go to sleep.
--- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +7 -8
@@ -258,8 +258,13 @@ static void signal_irq_work(struct irq_wi915_request_put (rq); } +/* Lazy irq enabling after HW submission */ if (!READ_ONCE (b->irq_armed) && !list_empty (&b->signalers))intel_breadcrumbs_arm_irq (b); + +/* And confirm that we still want irqs enabled before we yield */ +if (READ_ONCE (b->irq_armed) && !atomic_read (&b->active)) +intel_breadcrumbs_disarm_irq (b); } struct intel_breadcrumbs *
@@ -310,13 +315,7 @@ void __intel_breadcrumbs_park(struct intreturn ;/* Kick the work once more to drain the signalers, and disarm the irq */ -irq_work_sync (&b->irq_work); -while (READ_ONCE (b->irq_armed) && !atomic_read (&b->active)) { -local_irq_disable (); -signal_irq_work (&b->irq_work); -local_irq_enable (); -cond_resched (); - } +irq_work_queue (&b->irq_work); }void intel_breadcrumbs_free (struct kref *kref)
@@ -399,7 +398,7 @@ static void insert_breadcrumb(struct i91* the request as it may have completed and raised the interrupt as * we were attaching it into the lists. */ -if (!b->irq_armed ||__i915_request_is_complete (rq)) +if (!READ_ONCE (b->irq_armed) ||__i915_request_is_complete (rq))irq_work_queue (&b->irq_work); }
Greg Kroah-Hartman
maintainerPATCH 216/267 drm/shmem-helper: Fix BUG_ON() on mmap(PROT_WRITE, MAP_PRIVATE)
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wachowski, Karol <[email protected]>
commit 39bc27bd688066a63e56f7f64ad34fae03fbe3b8 upstream.
Lack of check for copy-on-write (COW) mapping in drm_gem_shmem_mmap allows users to call mmap with PROT_WRITE and MAP_PRIVATE flag causing a kernel panic due to BUG_ON in vmf_insert_pfn_prot:BUG_ON((vma->vm_flags & VM_PFNMAP) && is_cow_mapping(vma->vm_flags));
Return -EINVAL early if COW mapping is detected.
This bug affects all drm drivers using default shmem helpers. It can be reproduced by this simple example:
void *ptr = mmap(0, size, PROT_WRITE, MAP_PRIVATE, fd, mmap_offset); ptr[0] = 0;
--- drivers/gpu/drm/drm_gem_shmem_helper.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/drm_gem_shmem_helper.c +3 -0
@@ -610,6 +610,9 @@ int drm_gem_shmem_mmap(struct drm_gem_shreturn ret; } +if (is_cow_mapping (vma->vm_flags)) +return -EINVAL ; +dma_resv_lock (shmem->base.resv,NULL ); ret =drm_gem_shmem_get_pages (shmem);dma_resv_unlock (shmem->base.resv);
Greg Kroah-Hartman
maintainerPATCH 217/267 drm/i915/dpt: Make DPT object unshrinkable
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vidya Srinivas <[email protected]>
commit 43e2b37e2ab660c3565d4cff27922bc70e79c3f1 upstream.
In some scenarios, the DPT object gets shrunk but the actual framebuffer did not and thus its still there on the DPT's vm->bound_list. Then it tries to rewrite the PTEs via a stale CPU mapping. This causes panic.
--- drivers/gpu/drm/i915/gem/i915_gem_object.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/gem/i915_gem_object.h +3 -1
@@ -285,7 +285,9 @@ bool i915_gem_object_has_iomem(const strstatic inline bool i915_gem_object_is_shrinkable (const struct drm_i915_gem_object *obj) { -return i915_gem_object_type_has (obj,I915_GEM_OBJECT_IS_SHRINKABLE ); +/* TODO: make DPT shrinkable when it has no bound vmas */ +return i915_gem_object_type_has (obj,I915_GEM_OBJECT_IS_SHRINKABLE ) && + !obj->is_dpt; } static inline bool
Greg Kroah-Hartman
maintainerPATCH 218/267 drm/i915: Fix audio component initialization
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Imre Deak <[email protected]>
commit 75800e2e4203ea83bbc9d4f63ad97ea582244a08 upstream.
After registering the audio component in i915_audio_component_init() the audio driver may call i915_audio_component_get_power() via the component ops. This could program AUD_FREQ_CNTRL with an uninitialized value if the latter function is called before display.audio.freq_cntrl gets initialized. The get_power() function also does a modeset which in the above case happens too early before the initialization step and triggers the
"Reject display access from task"
error message added by the Fixes: commit below.
Fix the above issue by registering the audio component only after the initialization step.
--- drivers/gpu/drm/i915/display/intel_audio.c | 32 +++++++++++++------- drivers/gpu/drm/i915/display/intel_audio.h | 1 drivers/gpu/drm/i915/display/intel_display_driver.c | 2 + 3 files changed, 24 insertions(+), 11 deletions(-)
drivers/gpu/drm/i915/display/intel_audio.c +21 -11
@@ -1251,17 +1251,6 @@ static const struct component_ops i915_astatic void i915_audio_component_init (struct drm_i915_private *i915) {u32 aud_freq, aud_freq_init; -int ret; - - ret =component_add_typed (i915->drm.dev, - &i915_audio_component_bind_ops, -I915_COMPONENT_AUDIO ); -if (ret <0 ) { -drm_err (&i915->drm, -"failed to add audio component (%d)\n" , ret); -/* continue with reduced functionality */ -return ; - }if (DISPLAY_VER (i915) >=9 ) { aud_freq_init =intel_de_read (i915,AUD_FREQ_CNTRL );
@@ -1284,6 +1273,21 @@ static void i915_audio_component_init(st/* init with current cdclk */ intel_audio_cdclk_change_post (i915); +} + +static void i915_audio_component_register (struct drm_i915_private *i915) +{ +int ret; + + ret =component_add_typed (i915->drm.dev, + &i915_audio_component_bind_ops, +I915_COMPONENT_AUDIO ); +if (ret <0 ) { +drm_err (&i915->drm, +"failed to add audio component (%d)\n" , ret); +/* continue with reduced functionality */ +return ; + } i915->display.audio.component_registered = true; }
@@ -1316,6 +1320,12 @@ void intel_audio_init(struct drm_i915_pri915_audio_component_init (i915); } +void intel_audio_register (struct drm_i915_private *i915) +{ +if (!i915->display.audio.lpe.platdev) +i915_audio_component_register (i915); +} +/** * intel_audio_deinit() - deinitialize the audio driver * @i915: the i915 drm device private data
drivers/gpu/drm/i915/display/intel_audio.h +1 -0
@@ -28,6 +28,7 @@ void intel_audio_codec_get_config(structvoid intel_audio_cdclk_change_pre (struct drm_i915_private *dev_priv);void intel_audio_cdclk_change_post (struct drm_i915_private *dev_priv);void intel_audio_init (struct drm_i915_private *dev_priv); +void intel_audio_register (struct drm_i915_private *i915);void intel_audio_deinit (struct drm_i915_private *dev_priv);void intel_audio_sdp_split_update (struct intel_encoder *encoder,const struct intel_crtc_state *crtc_state);
drivers/gpu/drm/i915/display/intel_display_driver.c +2 -0
@@ -386,6 +386,8 @@ void intel_display_driver_register(strucintel_audio_init (i915); +intel_audio_register (i915); +intel_display_debugfs_register (i915);/*
Greg Kroah-Hartman
maintainerPATCH 219/267 intel_th: pci: Add Granite Rapids support
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Shishkin <[email protected]>
commit e44937889bdf4ecd1f0c25762b7226406b9b7a69 upstream.
Add support for the Trace Hub in Granite Rapids.
--- drivers/hwtracing/intel_th/pci.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/hwtracing/intel_th/pci.c +5 -0
@@ -305,6 +305,11 @@ static const struct pci_device_id intel_ .driver_data = (kernel_ulong_t)&intel_th_2x, }, { +/* Granite Rapids */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0963), + .driver_data = (kernel_ulong_t)&intel_th_2x, + }, + {/* Alder Lake CPU */ PCI_DEVICE (PCI_VENDOR_ID_INTEL ,0x466f ), .driver_data = (kernel_ulong_t)&intel_th_2x,
Greg Kroah-Hartman
maintainerPATCH 220/267 intel_th: pci: Add Granite Rapids SOC support
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Shishkin <[email protected]>
commit 854afe461b009801a171b3a49c5f75ea43e4c04c upstream.
Add support for the Trace Hub in Granite Rapids SOC.
--- drivers/hwtracing/intel_th/pci.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/hwtracing/intel_th/pci.c +5 -0
@@ -310,6 +310,11 @@ static const struct pci_device_id intel_ .driver_data = (kernel_ulong_t)&intel_th_2x, }, { +/* Granite Rapids SOC */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3256), + .driver_data = (kernel_ulong_t)&intel_th_2x, + }, + {/* Alder Lake CPU */ PCI_DEVICE (PCI_VENDOR_ID_INTEL ,0x466f ), .driver_data = (kernel_ulong_t)&intel_th_2x,
Greg Kroah-Hartman
maintainerPATCH 221/267 intel_th: pci: Add Sapphire Rapids SOC support
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Shishkin <[email protected]>
commit 2e1da7efabe05cb0cf0b358883b2bc89080ed0eb upstream.
Add support for the Trace Hub in Sapphire Rapids SOC.
--- drivers/hwtracing/intel_th/pci.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/hwtracing/intel_th/pci.c +5 -0
@@ -315,6 +315,11 @@ static const struct pci_device_id intel_ .driver_data = (kernel_ulong_t)&intel_th_2x, }, { +/* Sapphire Rapids SOC */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3456), + .driver_data = (kernel_ulong_t)&intel_th_2x, + }, + {/* Alder Lake CPU */ PCI_DEVICE (PCI_VENDOR_ID_INTEL ,0x466f ), .driver_data = (kernel_ulong_t)&intel_th_2x,
Greg Kroah-Hartman
maintainerPATCH 222/267 intel_th: pci: Add Meteor Lake-S support
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Shishkin <[email protected]>
commit c4a30def564d75e84718b059d1a62cc79b137cf9 upstream.
Add support for the Trace Hub in Meteor Lake-S.
--- drivers/hwtracing/intel_th/pci.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/hwtracing/intel_th/pci.c +5 -0
@@ -295,6 +295,11 @@ static const struct pci_device_id intel_ .driver_data = (kernel_ulong_t)&intel_th_2x, }, { +/* Meteor Lake-S */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7f26), + .driver_data = (kernel_ulong_t)&intel_th_2x, + }, + {/* Raptor Lake-S */ PCI_DEVICE (PCI_VENDOR_ID_INTEL ,0x7a26 ), .driver_data = (kernel_ulong_t)&intel_th_2x,
Greg Kroah-Hartman
maintainerPATCH 223/267 intel_th: pci: Add Lunar Lake support
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Shishkin <[email protected]>
commit f866b65322bfbc8fcca13c25f49e1a5c5a93ae4d upstream.
Add support for the Trace Hub in Lunar Lake.
--- drivers/hwtracing/intel_th/pci.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/hwtracing/intel_th/pci.c +5 -0
@@ -325,6 +325,11 @@ static const struct pci_device_id intel_ .driver_data = (kernel_ulong_t)&intel_th_2x, }, { +/* Lunar Lake */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa824), + .driver_data = (kernel_ulong_t)&intel_th_2x, + }, + {/* Alder Lake CPU */ PCI_DEVICE (PCI_VENDOR_ID_INTEL ,0x466f ), .driver_data = (kernel_ulong_t)&intel_th_2x,
Greg Kroah-Hartman
maintainerPATCH 224/267 pmdomain: ti-sci: Fix duplicate PD referrals
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tomi Valkeinen <[email protected]>
commit 670c900f69645db394efb38934b3344d8804171a upstream.
When the dts file has multiple referrers to a single PD (e.g. simple-framebuffer and dss nodes both point to the DSS power-domain) the ti-sci driver will create two power domains, both with the same ID, and that will cause problems as one of the power domains will hide the other one.
Fix this checking if a PD with the ID has already been created, and only create a PD for new IDs.
--- drivers/pmdomain/ti/ti_sci_pm_domains.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
drivers/pmdomain/ti/ti_sci_pm_domains.c +19 -1
@@ -114,6 +114,18 @@ static const struct of_device_id ti_sci_ };MODULE_DEVICE_TABLE (of, ti_sci_pm_domain_matches); +static bool ti_sci_pm_idx_exists (struct ti_sci_genpd_provider *pd_provider,u32 idx) +{ +struct ti_sci_pm_domain *pd; + +list_for_each_entry (pd, &pd_provider->pd_list, node) { +if (pd->idx == idx) +return true; + } + +return false; +} +static int ti_sci_pm_domain_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;
@@ -149,8 +161,14 @@ static int ti_sci_pm_domain_probe(structbreak ;if (args.args_count >=1 && args.np == dev->of_node) { -if (args.args[0 ] > max_id) +if (args.args[0 ] > max_id) { max_id = args.args[0 ]; + }else { +if (ti_sci_pm_idx_exists (pd_provider, args.args[0 ])) { + index++; +continue ; + } + } pd =devm_kzalloc (dev,sizeof (*pd),GFP_KERNEL );if (!pd)
Greg Kroah-Hartman
maintainerPATCH 225/267 btrfs: zoned: introduce a zone_info struct in btrfs_load_block_group_zone_info
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig <[email protected]>
commit 15c12fcc50a1b12a747f8b6ec05cdb18c537a4d1 upstream.
Add a new zone_info structure to hold per-zone information in btrfs_load_block_group_zone_info and prepare for breaking out helpers from it.
--- fs/btrfs/zoned.c | 84 ++++++++++++++++++++++++------------------------------- 1 file changed, 37 insertions(+), 47 deletions(-)
fs/btrfs/zoned.c +37 -47
@@ -1282,6 +1282,12 @@ out:return ret; } +struct zone_info { +u64 physical; +u64 capacity; +u64 alloc_offset; +}; +int btrfs_load_block_group_zone_info (struct btrfs_block_group *cache,bool new) {struct btrfs_fs_info *fs_info = cache->fs_info;
@@ -1291,12 +1297,10 @@ int btrfs_load_block_group_zone_info(strstruct btrfs_device *device;u64 logical = cache->start;u64 length = cache->length; +struct zone_info *zone_info =NULL ;int ret;int i;unsigned int nofs_flag; -u64 *alloc_offsets =NULL ; -u64 *caps =NULL ; -u64 *physical =NULL ;unsigned long *active =NULL ;u64 last_alloc =0 ;u32 num_sequential =0 , num_conventional =0 ;
@@ -1328,20 +1332,8 @@ int btrfs_load_block_group_zone_info(str goto out; } - alloc_offsets =kcalloc (map->num_stripes,sizeof (*alloc_offsets),GFP_NOFS ); -if (!alloc_offsets) { - ret = -ENOMEM ; - goto out; - } - - caps =kcalloc (map->num_stripes,sizeof (*caps),GFP_NOFS ); -if (!caps) { - ret = -ENOMEM ; - goto out; - } - - physical =kcalloc (map->num_stripes,sizeof (*physical),GFP_NOFS ); -if (!physical) { + zone_info =kcalloc (map->num_stripes,sizeof (*zone_info),GFP_NOFS ); +if (!zone_info) { ret = -ENOMEM ; goto out; }
@@ -1353,20 +1345,21 @@ int btrfs_load_block_group_zone_info(str }for (i =0 ; i < map->num_stripes; i++) { +struct zone_info *info = &zone_info[i];bool is_sequential;struct blk_zone zone;struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;int dev_replace_is_ongoing =0 ; device = map->stripes[i].dev; - physical[i] = map->stripes[i].physical; + info->physical = map->stripes[i].physical;if (device->bdev ==NULL ) { - alloc_offsets[i] =WP_MISSING_DEV ; + info->alloc_offset =WP_MISSING_DEV ;continue ; } - is_sequential =btrfs_dev_is_sequential (device, physical[i]); + is_sequential =btrfs_dev_is_sequential (device, info->physical);if (is_sequential) num_sequential++;else
@@ -1380,7 +1373,7 @@ int btrfs_load_block_group_zone_info(str__set_bit (i, active);if (!is_sequential) { - alloc_offsets[i] =WP_CONVENTIONAL ; + info->alloc_offset =WP_CONVENTIONAL ;continue ; }
@@ -1388,25 +1381,25 @@ int btrfs_load_block_group_zone_info(str* This zone will be used for allocation, so mark this zone * non-empty. */ -btrfs_dev_clear_zone_empty (device, physical[i]); +btrfs_dev_clear_zone_empty (device, info->physical);down_read (&dev_replace->rwsem); dev_replace_is_ongoing =btrfs_dev_replace_is_ongoing (dev_replace);if (dev_replace_is_ongoing && dev_replace->tgtdev !=NULL ) -btrfs_dev_clear_zone_empty (dev_replace->tgtdev, physical[i]); +btrfs_dev_clear_zone_empty (dev_replace->tgtdev, info->physical);up_read (&dev_replace->rwsem);/* * The group is mapped to a sequential zone. Get the zone write * pointer to determine the allocation offset within the zone. */ -WARN_ON (!IS_ALIGNED (physical[i], fs_info->zone_size)); +WARN_ON (!IS_ALIGNED (info->physical, fs_info->zone_size)); nofs_flag =memalloc_nofs_save (); - ret =btrfs_get_dev_zone (device, physical[i], &zone); + ret =btrfs_get_dev_zone (device, info->physical, &zone);memalloc_nofs_restore (nofs_flag);if (ret == -EIO || ret == -EOPNOTSUPP ) { ret =0 ; - alloc_offsets[i] =WP_MISSING_DEV ; + info->alloc_offset =WP_MISSING_DEV ;continue ; }else if (ret) { goto out;
@@ -1421,27 +1414,26 @@ int btrfs_load_block_group_zone_info(str goto out; } - caps[i] = (zone.capacity <<SECTOR_SHIFT ); + info->capacity = (zone.capacity <<SECTOR_SHIFT );switch (zone.cond) {case BLK_ZONE_COND_OFFLINE :case BLK_ZONE_COND_READONLY :btrfs_err (fs_info,"zoned: offline/readonly zone %llu on device %s (devid %llu)" , - physical[i] >> device->zone_info->zone_size_shift, + info->physical >> device->zone_info->zone_size_shift,rcu_str_deref (device->name), device->devid); - alloc_offsets[i] =WP_MISSING_DEV ; + info->alloc_offset =WP_MISSING_DEV ;break ;case BLK_ZONE_COND_EMPTY : - alloc_offsets[i] =0 ; + info->alloc_offset =0 ;break ;case BLK_ZONE_COND_FULL : - alloc_offsets[i] = caps[i]; + info->alloc_offset = info->capacity;break ;default :/* Partially used zone */ - alloc_offsets[i] = - ((zone.wp - zone.start) <<SECTOR_SHIFT ); + info->alloc_offset = ((zone.wp - zone.start) <<SECTOR_SHIFT );__set_bit (i, active);break ; }
@@ -1468,15 +1460,15 @@ int btrfs_load_block_group_zone_info(strswitch (map->type &BTRFS_BLOCK_GROUP_PROFILE_MASK ) {case 0 :/* single */ -if (alloc_offsets[0 ] ==WP_MISSING_DEV ) { +if (zone_info[0 ].alloc_offset ==WP_MISSING_DEV ) {btrfs_err (fs_info,"zoned: cannot recover write pointer for zone %llu" , - physical[0 ]); + zone_info[0 ].physical); ret = -EIO ; goto out; } - cache->alloc_offset = alloc_offsets[0 ]; - cache->zone_capacity = caps[0 ]; + cache->alloc_offset = zone_info[0 ].alloc_offset; + cache->zone_capacity = zone_info[0 ].capacity;if (test_bit (0 , active))set_bit (BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE , &cache->runtime_flags);break ;
@@ -1486,21 +1478,21 @@ int btrfs_load_block_group_zone_info(str ret = -EINVAL ; goto out; } -if (alloc_offsets[0 ] ==WP_MISSING_DEV ) { +if (zone_info[0 ].alloc_offset ==WP_MISSING_DEV ) {btrfs_err (fs_info,"zoned: cannot recover write pointer for zone %llu" , - physical[0 ]); + zone_info[0 ].physical); ret = -EIO ; goto out; } -if (alloc_offsets[1 ] ==WP_MISSING_DEV ) { +if (zone_info[1 ].alloc_offset ==WP_MISSING_DEV ) {btrfs_err (fs_info,"zoned: cannot recover write pointer for zone %llu" , - physical[1 ]); + zone_info[1 ].physical); ret = -EIO ; goto out; } -if (alloc_offsets[0 ] != alloc_offsets[1 ]) { +if (zone_info[0 ].alloc_offset != zone_info[1 ].alloc_offset) {btrfs_err (fs_info,"zoned: write pointer offset mismatch of zones in DUP profile" ); ret = -EIO ;
@@ -1516,8 +1508,8 @@ int btrfs_load_block_group_zone_info(strset_bit (BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE , &cache->runtime_flags); } - cache->alloc_offset = alloc_offsets[0 ]; - cache->zone_capacity =min (caps[0 ], caps[1 ]); + cache->alloc_offset = zone_info[0 ].alloc_offset; + cache->zone_capacity =min (zone_info[0 ].capacity, zone_info[1 ].capacity);break ;case BTRFS_BLOCK_GROUP_RAID1 :case BTRFS_BLOCK_GROUP_RAID0 :
@@ -1570,9 +1562,7 @@ out: cache->physical_map =NULL ; }bitmap_free (active); -kfree (physical); -kfree (caps); -kfree (alloc_offsets); +kfree (zone_info);free_extent_map (em);return ret;
Greg Kroah-Hartman
maintainerPATCH 226/267 btrfs: zoned: factor out per-zone logic from btrfs_load_block_group_zone_info
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig <[email protected]>
commit 09a46725cc84165af452d978a3532d6b97a28796 upstream.
Split out a helper for the body of the per-zone loop in btrfs_load_block_group_zone_info to make the function easier to read and modify.
--- fs/btrfs/zoned.c | 184 +++++++++++++++++++++++++++---------------------------- 1 file changed, 92 insertions(+), 92 deletions(-)
fs/btrfs/zoned.c +92 -92
@@ -1288,19 +1288,103 @@ struct zone_info {u64 alloc_offset; }; +static int btrfs_load_zone_info (struct btrfs_fs_info *fs_info,int zone_idx, +struct zone_info *info,unsigned long *active, +struct map_lookup *map) +{ +struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace; +struct btrfs_device *device = map->stripes[zone_idx].dev; +int dev_replace_is_ongoing =0 ; +unsigned int nofs_flag; +struct blk_zone zone; +int ret; + + info->physical = map->stripes[zone_idx].physical; + +if (!device->bdev) { + info->alloc_offset =WP_MISSING_DEV ; +return 0 ; + } + +/* Consider a zone as active if we can allow any number of active zones. */ +if (!device->zone_info->max_active_zones) +__set_bit (zone_idx, active); + +if (!btrfs_dev_is_sequential (device, info->physical)) { + info->alloc_offset =WP_CONVENTIONAL ; +return 0 ; + } + +/* This zone will be used for allocation, so mark this zone non-empty. */ +btrfs_dev_clear_zone_empty (device, info->physical); + +down_read (&dev_replace->rwsem); + dev_replace_is_ongoing =btrfs_dev_replace_is_ongoing (dev_replace); +if (dev_replace_is_ongoing && dev_replace->tgtdev !=NULL ) +btrfs_dev_clear_zone_empty (dev_replace->tgtdev, info->physical); +up_read (&dev_replace->rwsem); + +/* +* The group is mapped to a sequential zone. Get the zone write pointer +* to determine the allocation offset within the zone. +*/ +WARN_ON (!IS_ALIGNED (info->physical, fs_info->zone_size)); + nofs_flag =memalloc_nofs_save (); + ret =btrfs_get_dev_zone (device, info->physical, &zone); +memalloc_nofs_restore (nofs_flag); +if (ret) { +if (ret != -EIO && ret != -EOPNOTSUPP ) +return ret; + info->alloc_offset =WP_MISSING_DEV ; +return 0 ; + } + +if (zone.type ==BLK_ZONE_TYPE_CONVENTIONAL ) { +btrfs_err_in_rcu (fs_info, +"zoned: unexpected conventional zone %llu on device %s (devid %llu)" , + zone.start <<SECTOR_SHIFT ,rcu_str_deref (device->name), + device->devid); +return -EIO ; + } + + info->capacity = (zone.capacity <<SECTOR_SHIFT ); + +switch (zone.cond) { +case BLK_ZONE_COND_OFFLINE : +case BLK_ZONE_COND_READONLY : +btrfs_err (fs_info, +"zoned: offline/readonly zone %llu on device %s (devid %llu)" , + (info->physical >> device->zone_info->zone_size_shift), +rcu_str_deref (device->name), device->devid); + info->alloc_offset =WP_MISSING_DEV ; +break ; +case BLK_ZONE_COND_EMPTY : + info->alloc_offset =0 ; +break ; +case BLK_ZONE_COND_FULL : + info->alloc_offset = info->capacity; +break ; +default : +/* Partially used zone. */ + info->alloc_offset = ((zone.wp - zone.start) <<SECTOR_SHIFT ); +__set_bit (zone_idx, active); +break ; + } + +return 0 ; +} +int btrfs_load_block_group_zone_info (struct btrfs_block_group *cache,bool new) {struct btrfs_fs_info *fs_info = cache->fs_info;struct extent_map_tree *em_tree = &fs_info->mapping_tree;struct extent_map *em;struct map_lookup *map; -struct btrfs_device *device;u64 logical = cache->start;u64 length = cache->length;struct zone_info *zone_info =NULL ;int ret;int i; -unsigned int nofs_flag;unsigned long *active =NULL ;u64 last_alloc =0 ;u32 num_sequential =0 , num_conventional =0 ;
@@ -1345,98 +1429,14 @@ int btrfs_load_block_group_zone_info(str }for (i =0 ; i < map->num_stripes; i++) { -struct zone_info *info = &zone_info[i]; -bool is_sequential; -struct blk_zone zone; -struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace; -int dev_replace_is_ongoing =0 ; - - device = map->stripes[i].dev; - info->physical = map->stripes[i].physical; - -if (device->bdev ==NULL ) { - info->alloc_offset =WP_MISSING_DEV ; -continue ; - } - - is_sequential =btrfs_dev_is_sequential (device, info->physical); -if (is_sequential) - num_sequential++; -else - num_conventional++; - -/* -* Consider a zone as active if we can allow any number of -* active zones. -*/ -if (!device->zone_info->max_active_zones) -__set_bit (i, active); - -if (!is_sequential) { - info->alloc_offset =WP_CONVENTIONAL ; -continue ; - } - -/* -* This zone will be used for allocation, so mark this zone -* non-empty. -*/ -btrfs_dev_clear_zone_empty (device, info->physical); - -down_read (&dev_replace->rwsem); - dev_replace_is_ongoing =btrfs_dev_replace_is_ongoing (dev_replace); -if (dev_replace_is_ongoing && dev_replace->tgtdev !=NULL ) -btrfs_dev_clear_zone_empty (dev_replace->tgtdev, info->physical); -up_read (&dev_replace->rwsem); - -/* -* The group is mapped to a sequential zone. Get the zone write -* pointer to determine the allocation offset within the zone. -*/ -WARN_ON (!IS_ALIGNED (info->physical, fs_info->zone_size)); - nofs_flag =memalloc_nofs_save (); - ret =btrfs_get_dev_zone (device, info->physical, &zone); -memalloc_nofs_restore (nofs_flag); -if (ret == -EIO || ret == -EOPNOTSUPP ) { - ret =0 ; - info->alloc_offset =WP_MISSING_DEV ; -continue ; - }else if (ret) { + ret =btrfs_load_zone_info (fs_info, i, &zone_info[i], active, map); +if (ret) goto out; - } - -if (zone.type ==BLK_ZONE_TYPE_CONVENTIONAL ) { -btrfs_err_in_rcu (fs_info, -"zoned: unexpected conventional zone %llu on device %s (devid %llu)" , - zone.start <<SECTOR_SHIFT , -rcu_str_deref (device->name), device->devid); - ret = -EIO ; - goto out; - } - - info->capacity = (zone.capacity <<SECTOR_SHIFT ); -switch (zone.cond) { -case BLK_ZONE_COND_OFFLINE : -case BLK_ZONE_COND_READONLY : -btrfs_err (fs_info, -"zoned: offline/readonly zone %llu on device %s (devid %llu)" , - info->physical >> device->zone_info->zone_size_shift, -rcu_str_deref (device->name), device->devid); - info->alloc_offset =WP_MISSING_DEV ; -break ; -case BLK_ZONE_COND_EMPTY : - info->alloc_offset =0 ; -break ; -case BLK_ZONE_COND_FULL : - info->alloc_offset = info->capacity; -break ; -default : -/* Partially used zone */ - info->alloc_offset = ((zone.wp - zone.start) <<SECTOR_SHIFT ); -__set_bit (i, active); -break ; - } +if (zone_info[i].alloc_offset ==WP_CONVENTIONAL ) + num_conventional++; +else + num_sequential++; }if (num_sequential >0 )
Greg Kroah-Hartman
maintainerPATCH 227/267 btrfs: zoned: factor out single bg handling from btrfs_load_block_group_zone_info
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig <[email protected]>
commit 9e0e3e74dc6928a0956f4e27e24d473c65887e96 upstream.
Split the code handling a type single block group from btrfs_load_block_group_zone_info to make the code more readable.
--- fs/btrfs/zoned.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-)
fs/btrfs/zoned.c +19 -11
@@ -1374,6 +1374,24 @@ static int btrfs_load_zone_info(struct breturn 0 ; } +static int btrfs_load_block_group_single (struct btrfs_block_group *bg, +struct zone_info *info, +unsigned long *active) +{ +if (info->alloc_offset ==WP_MISSING_DEV ) { +btrfs_err (bg->fs_info, +"zoned: cannot recover write pointer for zone %llu" , + info->physical); +return -EIO ; + } + + bg->alloc_offset = info->alloc_offset; + bg->zone_capacity = info->capacity; +if (test_bit (0 , active)) +set_bit (BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE , &bg->runtime_flags); +return 0 ; +} +int btrfs_load_block_group_zone_info (struct btrfs_block_group *cache,bool new) {struct btrfs_fs_info *fs_info = cache->fs_info;
@@ -1460,17 +1478,7 @@ int btrfs_load_block_group_zone_info(strswitch (map->type &BTRFS_BLOCK_GROUP_PROFILE_MASK ) {case 0 :/* single */ -if (zone_info[0 ].alloc_offset ==WP_MISSING_DEV ) { -btrfs_err (fs_info, -"zoned: cannot recover write pointer for zone %llu" , - zone_info[0 ].physical); - ret = -EIO ; - goto out; - } - cache->alloc_offset = zone_info[0 ].alloc_offset; - cache->zone_capacity = zone_info[0 ].capacity; -if (test_bit (0 , active)) -set_bit (BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE , &cache->runtime_flags); + ret =btrfs_load_block_group_single (cache, &zone_info[0 ], active);break ;case BTRFS_BLOCK_GROUP_DUP :if (map->type &BTRFS_BLOCK_GROUP_DATA ) {
Greg Kroah-Hartman
maintainerPATCH 228/267 btrfs: zoned: factor out DUP bg handling from btrfs_load_block_group_zone_info
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig <[email protected]>
commit 87463f7e0250d471fac41e7c9c45ae21d83b5f85 upstream.
Split the code handling a type DUP block group from btrfs_load_block_group_zone_info to make the code more readable.
--- fs/btrfs/zoned.c | 79 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 37 deletions(-)
fs/btrfs/zoned.c +42 -37
@@ -1392,6 +1392,47 @@ static int btrfs_load_block_group_singlereturn 0 ; } +static int btrfs_load_block_group_dup (struct btrfs_block_group *bg, +struct map_lookup *map, +struct zone_info *zone_info, +unsigned long *active) +{ +if (map->type &BTRFS_BLOCK_GROUP_DATA ) { +btrfs_err (bg->fs_info, +"zoned: profile DUP not yet supported on data bg" ); +return -EINVAL ; + } + +if (zone_info[0 ].alloc_offset ==WP_MISSING_DEV ) { +btrfs_err (bg->fs_info, +"zoned: cannot recover write pointer for zone %llu" , + zone_info[0 ].physical); +return -EIO ; + } +if (zone_info[1 ].alloc_offset ==WP_MISSING_DEV ) { +btrfs_err (bg->fs_info, +"zoned: cannot recover write pointer for zone %llu" , + zone_info[1 ].physical); +return -EIO ; + } +if (zone_info[0 ].alloc_offset != zone_info[1 ].alloc_offset) { +btrfs_err (bg->fs_info, +"zoned: write pointer offset mismatch of zones in DUP profile" ); +return -EIO ; + } + +if (test_bit (0 , active) !=test_bit (1 , active)) { +if (!btrfs_zone_activate (bg)) +return -EIO ; + }else if (test_bit (0 , active)) { +set_bit (BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE , &bg->runtime_flags); + } + + bg->alloc_offset = zone_info[0 ].alloc_offset; + bg->zone_capacity =min (zone_info[0 ].capacity, zone_info[1 ].capacity); +return 0 ; +} +int btrfs_load_block_group_zone_info (struct btrfs_block_group *cache,bool new) {struct btrfs_fs_info *fs_info = cache->fs_info;
@@ -1481,43 +1522,7 @@ int btrfs_load_block_group_zone_info(str ret =btrfs_load_block_group_single (cache, &zone_info[0 ], active);break ;case BTRFS_BLOCK_GROUP_DUP : -if (map->type &BTRFS_BLOCK_GROUP_DATA ) { -btrfs_err (fs_info,"zoned: profile DUP not yet supported on data bg" ); - ret = -EINVAL ; - goto out; - } -if (zone_info[0 ].alloc_offset ==WP_MISSING_DEV ) { -btrfs_err (fs_info, -"zoned: cannot recover write pointer for zone %llu" , - zone_info[0 ].physical); - ret = -EIO ; - goto out; - } -if (zone_info[1 ].alloc_offset ==WP_MISSING_DEV ) { -btrfs_err (fs_info, -"zoned: cannot recover write pointer for zone %llu" , - zone_info[1 ].physical); - ret = -EIO ; - goto out; - } -if (zone_info[0 ].alloc_offset != zone_info[1 ].alloc_offset) { -btrfs_err (fs_info, -"zoned: write pointer offset mismatch of zones in DUP profile" ); - ret = -EIO ; - goto out; - } -if (test_bit (0 , active) !=test_bit (1 , active)) { -if (!btrfs_zone_activate (cache)) { - ret = -EIO ; - goto out; - } - }else { -if (test_bit (0 , active)) -set_bit (BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE , - &cache->runtime_flags); - } - cache->alloc_offset = zone_info[0 ].alloc_offset; - cache->zone_capacity =min (zone_info[0 ].capacity, zone_info[1 ].capacity); + ret =btrfs_load_block_group_dup (cache, map, zone_info, active);break ;case BTRFS_BLOCK_GROUP_RAID1 :case BTRFS_BLOCK_GROUP_RAID0 :
Greg Kroah-Hartman
maintainerPATCH 229/267 btrfs: zoned: fix use-after-free due to race with dev replace
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
commit 0090d6e1b210551e63cf43958dc7a1ec942cdde9 upstream.
While loading a zone's info during creation of a block group, we can race with a device replace operation and then trigger a use-after-free on the device that was just replaced (source device of the replace operation).
This happens because at btrfs_load_zone_info() we extract a device from the chunk map into a local variable and then use the device while not under the protection of the device replace rwsem. So if there's a device replace operation happening when we extract the device and that device is the source of the replace operation, we will trigger a use-after-free if before we finish using the device the replace operation finishes and frees the device.
Fix this by enlarging the critical section under the protection of the device replace rwsem so that all uses of the device are done inside the critical section.
--- fs/btrfs/zoned.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
fs/btrfs/zoned.c +10 -3
@@ -1293,7 +1293,7 @@ static int btrfs_load_zone_info(struct b struct map_lookup *map) {struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace; -struct btrfs_device *device = map->stripes[zone_idx].dev; +struct btrfs_device *device;int dev_replace_is_ongoing =0 ;unsigned int nofs_flag;struct blk_zone zone;
@@ -1301,7 +1301,11 @@ static int btrfs_load_zone_info(struct b info->physical = map->stripes[zone_idx].physical; +down_read (&dev_replace->rwsem); + device = map->stripes[zone_idx].dev; +if (!device->bdev) { +up_read (&dev_replace->rwsem); info->alloc_offset =WP_MISSING_DEV ;return 0 ; }
@@ -1311,6 +1315,7 @@ static int btrfs_load_zone_info(struct b__set_bit (zone_idx, active);if (!btrfs_dev_is_sequential (device, info->physical)) { +up_read (&dev_replace->rwsem); info->alloc_offset =WP_CONVENTIONAL ;return 0 ; }
@@ -1318,11 +1323,9 @@ static int btrfs_load_zone_info(struct b/* This zone will be used for allocation, so mark this zone non-empty. */ btrfs_dev_clear_zone_empty (device, info->physical); -down_read (&dev_replace->rwsem); dev_replace_is_ongoing =btrfs_dev_replace_is_ongoing (dev_replace);if (dev_replace_is_ongoing && dev_replace->tgtdev !=NULL )btrfs_dev_clear_zone_empty (dev_replace->tgtdev, info->physical); -up_read (&dev_replace->rwsem);/* * The group is mapped to a sequential zone. Get the zone write pointer
@@ -1333,6 +1336,7 @@ static int btrfs_load_zone_info(struct b ret =btrfs_get_dev_zone (device, info->physical, &zone);memalloc_nofs_restore (nofs_flag);if (ret) { +up_read (&dev_replace->rwsem);if (ret != -EIO && ret != -EOPNOTSUPP )return ret; info->alloc_offset =WP_MISSING_DEV ;
@@ -1344,6 +1348,7 @@ static int btrfs_load_zone_info(struct b"zoned: unexpected conventional zone %llu on device %s (devid %llu)" , zone.start <<SECTOR_SHIFT ,rcu_str_deref (device->name), device->devid); +up_read (&dev_replace->rwsem);return -EIO ; }
@@ -1371,6 +1376,8 @@ static int btrfs_load_zone_info(struct bbreak ; } +up_read (&dev_replace->rwsem); +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 230/267 xfs: fix imprecise logic in xchk_btree_check_block_owner
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Darrick J. Wong" <[email protected]>
commit c0afba9a8363f17d4efed22a8764df33389aebe8 upstream.
A reviewer was confused by the init_sa logic in this function. Upon checking the logic, I discovered that the code is imprecise. What we want to do here is check that there is an ownership record in the rmap btree for the AG that contains a btree block.
For an inode-rooted btree (e.g. the bmbt) the per-AG btree cursors have not been initialized because inode btrees can span multiple AGs. Therefore, we must initialize the per-AG btree cursors in sc->sa before proceeding. That is what init_sa controls, and hence the logic should be gated on XFS_BTREE_ROOT_IN_INODE, not XFS_BTREE_LONG_PTRS.
In practice, ROOT_IN_INODE and LONG_PTRS are coincident so this hasn't mattered. However, we're about to refactor both of those flags into separate btree_ops fields so we want this the logic to make sense afterwards.
--- fs/xfs/scrub/btree.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
fs/xfs/scrub/btree.c +6 -1
@@ -385,7 +385,12 @@ xchk_btree_check_block_owner( agno =xfs_daddr_to_agno (bs->cur->bc_mp, daddr); agbno =xfs_daddr_to_agbno (bs->cur->bc_mp, daddr); - init_sa = bs->cur->bc_flags &XFS_BTREE_LONG_PTRS ; +/* +* If the btree being examined is not itself a per-AG btree, initialize +* sc->sa so that we can check for the presence of an ownership record +* in the rmap btree for the AG containing the block. +*/ + init_sa = bs->cur->bc_flags &XFS_BTREE_ROOT_IN_INODE ; if (init_sa) { error = xchk_ag_init_existing(bs->sc, agno, &bs->sc->sa); if (!xchk_btree_xref_process_error(bs->sc, bs->cur,
Greg Kroah-Hartman
maintainerPATCH 231/267 xfs: fix scrub stats file permissions
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Darrick J. Wong" <[email protected]>
commit e610e856b938a1fc86e7ee83ad2f39716082bca7 upstream.
When the kernel is in lockdown mode, debugfs will only show files that are world-readable and cannot be written, mmaped, or used with ioctl. That more or less describes the scrub stats file, except that the permissions are wrong -- they should be 0444, not 0644. You can't write the stats file, so the 0200 makes no sense.
Meanwhile, the clear_stats file is only writable, but it got mode 0400 instead of 0200, which would make more sense.
Fix both files so that they make sense.
--- fs/xfs/scrub/stats.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/xfs/scrub/stats.c +2 -2
@@ -329,9 +329,9 @@ xchk_stats_register(if (!cs->cs_debugfs)return ; -debugfs_create_file ("stats" ,0644 , cs->cs_debugfs, cs, +debugfs_create_file ("stats" ,0444 , cs->cs_debugfs, cs, &scrub_stats_fops); -debugfs_create_file ("clear_stats" ,0400 , cs->cs_debugfs, cs, +debugfs_create_file ("clear_stats" ,0200 , cs->cs_debugfs, cs, &clear_scrub_stats_fops); }
Greg Kroah-Hartman
maintainerPATCH 232/267 xfs: fix SEEK_HOLE/DATA for regions with active COW extents
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Chinner <[email protected]>
commit 4b2f459d86252619448455013f581836c8b1b7da upstream.
A data corruption problem was reported by CoreOS image builders when using reflink based disk image copies and then converting them to qcow2 images. The converted images failed the conversion verification step, and it was isolated down to the fact that qemu-img uses SEEK_HOLE/SEEK_DATA to find the data it is supposed to copy.
The reproducer allowed me to isolate the issue down to a region of the file that had overlapping data and COW fork extents, and the problem was that the COW fork extent was being reported in it's entirity by xfs_seek_iomap_begin() and so skipping over the real data fork extents in that range.
This was somewhat hidden by the fact that 'xfs_bmap -vvp' reported all the extents correctly, and reading the file completely (i.e. not using seek to skip holes) would map the file correctly and all the correct data extents are read. Hence the problem is isolated to just the xfs_seek_iomap_begin() implementation.
Instrumentation with trace_printk made the problem obvious: we are passing the wrong length to xfs_trim_extent() in xfs_seek_iomap_begin(). We are passing the end_fsb, not the maximum length of the extent we want to trim the map too. Hence the COW extent map never gets trimmed to the start of the next data fork extent, and so the seek code treats the entire COW fork extent as unwritten and skips entirely over the data fork extents in that range.
--- fs/xfs/xfs_iomap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/xfs/xfs_iomap.c +2 -2
@@ -1323,7 +1323,7 @@ xfs_seek_iomap_begin(if (cow_fsb !=NULLFILEOFF && cow_fsb <= offset_fsb) {if (data_fsb < cow_fsb + cmap.br_blockcount) end_fsb =min (end_fsb, data_fsb); -xfs_trim_extent (&cmap, offset_fsb, end_fsb); +xfs_trim_extent (&cmap, offset_fsb, end_fsb - offset_fsb); seq =xfs_iomap_inode_sequence (ip,IOMAP_F_SHARED ); error =xfs_bmbt_to_iomap (ip, iomap, &cmap, flags,IOMAP_F_SHARED , seq);
@@ -1348,7 +1348,7 @@ xfs_seek_iomap_begin( imap.br_state =XFS_EXT_NORM ; done: seq =xfs_iomap_inode_sequence (ip,0 ); -xfs_trim_extent (&imap, offset_fsb, end_fsb); +xfs_trim_extent (&imap, offset_fsb, end_fsb - offset_fsb); error =xfs_bmbt_to_iomap (ip, iomap, &imap, flags,0 , seq); out_unlock:xfs_iunlock (ip, lockmode);
Greg Kroah-Hartman
maintainerPATCH 233/267 xfs: shrink failure needs to hold AGI buffer
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Chinner <[email protected]>
commit 75bcffbb9e7563259b7aed0fa77459d6a3a35627 upstream.
Chandan reported a AGI/AGF lock order hang on xfs/168 during recent testing. The cause of the problem was the task running xfs_growfs to shrink the filesystem. A failure occurred trying to remove the free space from the btrees that the shrink would make disappear, and that meant it ran the error handling for a partial failure.
This error path involves restoring the per-ag block reservations, and that requires calculating the amount of space needed to be reserved for the free inode btree. The growfs operation hung here:
[18679.536829] down+0x71/0xa0 [18679.537657] xfs_buf_lock+0xa4/0x290 [xfs] [18679.538731] xfs_buf_find_lock+0xf7/0x4d0 [xfs] [18679.539920] xfs_buf_lookup.constprop.0+0x289/0x500 [xfs] [18679.542628] xfs_buf_get_map+0x2b3/0xe40 [xfs] [18679.547076] xfs_buf_read_map+0xbb/0x900 [xfs] [18679.562616] xfs_trans_read_buf_map+0x449/0xb10 [xfs] [18679.569778] xfs_read_agi+0x1cd/0x500 [xfs] [18679.573126] xfs_ialloc_read_agi+0xc2/0x5b0 [xfs] [18679.578708] xfs_finobt_calc_reserves+0xe7/0x4d0 [xfs] [18679.582480] xfs_ag_resv_init+0x2c5/0x490 [xfs] [18679.586023] xfs_ag_shrink_space+0x736/0xd30 [xfs] [18679.590730] xfs_growfs_data_private.isra.0+0x55e/0x990 [xfs] [18679.599764] xfs_growfs_data+0x2f1/0x410 [xfs] [18679.602212] xfs_file_ioctl+0xd1e/0x1370 [xfs]
trying to get the AGI lock. The AGI lock was held by a fstress task trying to do an inode allocation, and it was waiting on the AGF lock to allocate a new inode chunk on disk. Hence deadlock.
The fix for this is for the growfs code to hold the AGI over the transaction roll it does in the error path. It already holds the AGF locked across this, and that is what causes the lock order inversion in the xfs_ag_resv_init() call.
--- fs/xfs/libxfs/xfs_ag.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
fs/xfs/libxfs/xfs_ag.c +10 -1
@@ -979,14 +979,23 @@ xfs_ag_shrink_space(if (error) {/* -* if extent allocation fails, need to roll the transaction to +* If extent allocation fails, need to roll the transaction to * ensure that the AGFL fixup has been committed anyway. +* +* We need to hold the AGF across the roll to ensure nothing can +* access the AG for allocation until the shrink is fully +* cleaned up. And due to the resetting of the AG block +* reservation space needing to lock the AGI, we also have to +* hold that so we don't get AGI/AGF lock order inversions in +* the error handling path. */ xfs_trans_bhold (*tpp, agfbp); +xfs_trans_bhold (*tpp, agibp); err2 =xfs_trans_roll (tpp);if (err2)return err2;xfs_trans_bjoin (*tpp, agfbp); +xfs_trans_bjoin (*tpp, agibp); goto resv_init_out; }
Greg Kroah-Hartman
maintainerPATCH 234/267 xfs: ensure submit buffers on LSN boundaries in error handlers
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Long Li <[email protected]>
commit e4c3b72a6ea93ed9c1815c74312eee9305638852 upstream.
While performing the IO fault injection test, I caught the following data corruption report:
XFS (dm-0): Internal error ltbno + ltlen > bno at line 1957 of file fs/xfs/libxfs/xfs_alloc.c. Caller xfs_free_ag_extent+0x79c/0x1130
CPU: 3 PID: 33 Comm: kworker/3:0 Not tainted 6.5.0-rc7-next-20230825-00001-g7f8666926889 #214 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ?-20190727_073836-buildvm-ppc64le-16.ppc.fedoraproject.org-3.fc31 04/01/2014 Workqueue: xfs-inodegc/dm-0 xfs_inodegc_worker Call Trace: <TASK> dump_stack_lvl+0x50/0x70 xfs_corruption_error+0x134/0x150 xfs_free_ag_extent+0x7d3/0x1130 __xfs_free_extent+0x201/0x3c0 xfs_trans_free_extent+0x29b/0xa10 xfs_extent_free_finish_item+0x2a/0xb0 xfs_defer_finish_noroll+0x8d1/0x1b40 xfs_defer_finish+0x21/0x200 xfs_itruncate_extents_flags+0x1cb/0x650 xfs_free_eofblocks+0x18f/0x250 xfs_inactive+0x485/0x570 xfs_inodegc_worker+0x207/0x530 process_scheduled_works+0x24a/0xe10 worker_thread+0x5ac/0xc60 kthread+0x2cd/0x3c0 ret_from_fork+0x4a/0x80 ret_from_fork_asm+0x11/0x20 </TASK> XFS (dm-0): Corruption detected. Unmount and run xfs_repair
After analyzing the disk image, it was found that the corruption was triggered by the fact that extent was recorded in both inode datafork and AGF btree blocks. After a long time of reproduction and analysis, we found that the reason of free sapce btree corruption was that the AGF btree was not recovered correctly.
Consider the following situation, Checkpoint A and Checkpoint B are in the same record and share the same start LSN1, buf items of same object (AGF btree block) is included in both Checkpoint A and Checkpoint B. If the buf item in Checkpoint A has been recovered and updates metadata LSN permanently, then the buf item in Checkpoint B cannot be recovered, because log recovery skips items with a metadata LSN >= the current LSN of the recovery item. If there is still an inode item in Checkpoint B that records the Extent X, the Extent X will be recorded in both inode datafork and AGF btree block after Checkpoint B is recovered. Such transaction can be seen when allocing enxtent for inode bmap, it record both the addition of extent to the inode extent list and the removing extent from the AGF.
|------------Record (LSN1)------------------|---Record (LSN2)---| |-------Checkpoint A----------|----------Checkpoint B-----------| | Buf Item(Extent X) | Buf Item / Inode item(Extent X) | | Extent X is freed | Extent X is allocated |
After commit 12818d24db8a ("xfs: rework log recovery to submit buffers on LSN boundaries") was introduced, we submit buffers on lsn boundaries during log recovery. The above problem can be avoided under normal paths, but it's not guaranteed under abnormal paths. Consider the following process, if an error was encountered after recover buf item in Checkpoint A and before recover buf item in Checkpoint B, buffers that have been added to the buffer_list will still be submitted, this violates the submits rule on lsn boundaries. So buf item in Checkpoint B cannot be recovered on the next mount due to current lsn of transaction equal to metadata lsn on disk. The detailed process of the problem is as follows.
First Mount:
xlog_do_recovery_pass
error = xlog_recover_process
xlog_recover_process_data
xlog_recover_process_ophdr
xlog_recovery_process_trans
...
/* recover buf item in Checkpoint A */
xlog_recover_buf_commit_pass2
xlog_recover_do_reg_buffer
/* add buffer of agf btree block to buffer_list */
xfs_buf_delwri_queue(bp, buffer_list)
...
==> Encounter read IO error and return
/* submit buffers regardless of error */
if (!list_empty(&buffer_list))
xfs_buf_delwri_submit(&buffer_list);
<buf items of agf btree block in Checkpoint A recovery success>Second Mount:
xlog_do_recovery_pass
error = xlog_recover_process
xlog_recover_process_data
xlog_recover_process_ophdr
xlog_recovery_process_trans
...
/* recover buf item in Checkpoint B */
xlog_recover_buf_commit_pass2
/* buffer of agf btree block wouldn't added to
buffer_list due to lsn equal to current_lsn */
if (XFS_LSN_CMP(lsn, current_lsn) >= 0)
goto out_release
<buf items of agf btree block in Checkpoint B wouldn't recovery>In order to make sure that submits buffers on lsn boundaries in the abnormal paths, we need to check error status before submit buffers that have been added from the last record processed. If error status exist, buffers in the bufffer_list should not be writen to disk.
Canceling the buffers in the buffer_list directly isn't correct, unlike any other place where write list was canceled, these buffers has been initialized by xfs_buf_item_init() during recovery and held by buf item, buf items will not be released in xfs_buf_delwri_cancel(), it's not easy to solve.
If the filesystem has been shut down, then delwri list submission will error out all buffers on the list via IO submission/completion and do all the correct cleanup automatically. So shutting down the filesystem could prevents buffers in the bufffer_list from being written to disk.
--- fs/xfs/xfs_log_recover.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-)
fs/xfs/xfs_log_recover.c +20 -3
@@ -3203,11 +3203,28 @@ xlog_do_recovery_pass(kmem_free (hbp);/* -* Submit buffers that have been added from the last record processed, -* regardless of error status. +* Submit buffers that have been dirtied by the last record recovered. */ -if (!list_empty (&buffer_list)) +if (!list_empty (&buffer_list)) { +if (error) { +/* +* If there has been an item recovery error then we +* cannot allow partial checkpoint writeback to +* occur. We might have multiple checkpoints with the +* same start LSN in this buffer list, and partial +* writeback of a checkpoint in this situation can +* prevent future recovery of all the changes in the +* checkpoints at this start LSN. +* +* Note: Shutting down the filesystem will result in the +* delwri submission marking all the buffers stale, +* completing them and cleaning up _XBF_LOGRECOVERY +* state without doing any IO. +*/ +xlog_force_shutdown (log,SHUTDOWN_LOG_IO_ERROR ); + } error2 =xfs_buf_delwri_submit (&buffer_list); + }if (error && first_bad) *first_bad = rhead_blk;
Greg Kroah-Hartman
maintainerPATCH 235/267 xfs: allow sunit mount option to repair bad primary sb stripe values
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Chinner <[email protected]>
commit 15922f5dbf51dad334cde888ce6835d377678dc9 upstream.
If a filesystem has a busted stripe alignment configuration on disk (e.g. because broken RAID firmware told mkfs that swidth was smaller than sunit), then the filesystem will refuse to mount due to the stripe validation failing. This failure is triggering during distro upgrades from old kernels lacking this check to newer kernels with this check, and currently the only way to fix it is with offline xfs_db surgery.
This runtime validity checking occurs when we read the superblock for the first time and causes the mount to fail immediately. This prevents the rewrite of stripe unit/width via
mount options that occurs later in the mount process. Hence there is no way to recover this situation without resorting to offline xfs_db rewrite of the values.
However, we parse the mount options long before we read the superblock, and we know if the mount has been asked to re-write the stripe alignment configuration when we are reading the superblock and verifying it for the first time. Hence we can conditionally ignore stripe verification failures if the mount options specified will correct the issue.
We validate that the new stripe unit/width are valid before we overwrite the superblock values, so we can ignore the invalid config at verification and fail the mount later if the new values are not valid. This, at least, gives users the chance of correcting the issue after a kernel upgrade without having to resort to xfs-db hacks.
--- fs/xfs/libxfs/xfs_sb.c | 40 +++++++++++++++++++++++++++++++--------- fs/xfs/libxfs/xfs_sb.h | 5 +++-- 2 files changed, 34 insertions(+), 11 deletions(-)
fs/xfs/libxfs/xfs_sb.c +31 -9
@@ -530,7 +530,8 @@ xfs_validate_sb_common( }if (!xfs_validate_stripe_geometry (mp,XFS_FSB_TO_B (mp, sbp->sb_unit), -XFS_FSB_TO_B (mp, sbp->sb_width),0 , false)) +XFS_FSB_TO_B (mp, sbp->sb_width),0 , +xfs_buf_daddr (bp) ==XFS_SB_DADDR , false))return -EFSCORRUPTED ;/*
@@ -1319,8 +1320,10 @@ xfs_sb_get_secondary( }/* -* sunit, swidth, sectorsize(optional with 0) should be all in bytes, -* so users won't be confused by values in error messages. +* sunit, swidth, sectorsize(optional with 0) should be all in bytes, so users +* won't be confused by values in error messages. This function returns false +* if the stripe geometry is invalid and the caller is unable to repair the +* stripe configuration later in the mount process. */ bool xfs_validate_stripe_geometry(
@@ -1328,20 +1331,21 @@ xfs_validate_stripe_geometry( __s64 sunit, __s64 swidth, int sectorsize, + bool may_repair, bool silent) { if (swidth > INT_MAX) { if (!silent) xfs_notice(mp, "stripe width (%lld) is too large", swidth); -return false; + goto check_override; }if (sunit > swidth) {if (!silent)xfs_notice (mp,"stripe unit (%lld) is larger than the stripe width (%lld)" , sunit, swidth); -return false; + goto check_override; }if (sectorsize && (int )sunit % sectorsize) {
@@ -1349,21 +1353,21 @@ xfs_validate_stripe_geometry(xfs_notice (mp,"stripe unit (%lld) must be a multiple of the sector size (%d)" , sunit, sectorsize); -return false; + goto check_override; }if (sunit && !swidth) {if (!silent)xfs_notice (mp,"invalid stripe unit (%lld) and stripe width of 0" , sunit); -return false; + goto check_override; }if (!sunit && swidth) {if (!silent)xfs_notice (mp,"invalid stripe width (%lld) and stripe unit of 0" , swidth); -return false; + goto check_override; }if (sunit && (int )swidth % (int )sunit) {
@@ -1371,9 +1375,27 @@ xfs_validate_stripe_geometry(xfs_notice (mp,"stripe width (%lld) must be a multiple of the stripe unit (%lld)" , swidth, sunit); -return false; + goto check_override; }return true; + +check_override: +if (!may_repair) +return false; +/* +* During mount, mp->m_dalign will not be set unless the sunit mount +* option was set. If it was set, ignore the bad stripe alignment values +* and allow the validation and overwrite later in the mount process to +* attempt to overwrite the bad stripe alignment values with the values +* supplied by mount options. +*/ +if (!mp->m_dalign) +return false; +if (!silent) +xfs_notice (mp, +"Will try to correct with specified mount options sunit (%d) and swidth (%d)" , +BBTOB (mp->m_dalign),BBTOB (mp->m_swidth)); +return true; }/*
fs/xfs/libxfs/xfs_sb.h +3 -2
@@ -35,8 +35,9 @@ extern int xfs_sb_get_secondary(struct x struct xfs_trans *tp, xfs_agnumber_t agno, struct xfs_buf **bpp); -extern bool xfs_validate_stripe_geometry (struct xfs_mount *mp, -__s64 sunit,__s64 swidth,int sectorsize,bool silent); +bool xfs_validate_stripe_geometry (struct xfs_mount *mp, +__s64 sunit,__s64 swidth,int sectorsize,bool may_repair, +bool silent);uint8_t xfs_compute_rextslog (xfs_rtbxlen_t rtextents);
Greg Kroah-Hartman
maintainerPATCH 236/267 xfs: dont use current->journal_info
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Chinner <[email protected]>
commit f2e812c1522dab847912309b00abcc762dd696da upstream.
syzbot reported an ext4 panic during a page fault where found a journal handle when it didn't expect to find one. The structure it tripped over had a value of 'TRAN' in the first entry in the structure, and that indicates it tripped over a struct xfs_trans instead of a jbd2 handle.
The reason for this is that the page fault was taken during a copy-out to a user buffer from an xfs bulkstat operation. XFS uses an "empty" transaction context for bulkstat to do automated metadata buffer cleanup, and so the transaction context is valid across the copyout of the bulkstat info into the user buffer.
We are using empty transaction contexts like this in XFS to reduce the risk of failing to release objects we reference during the operation, especially during error handling. Hence we really need to ensure that we can take page faults from these contexts without leaving landmines for the code processing the page fault to trip over.
However, this same behaviour could happen from any other filesystem that triggers a page fault or any other exception that is handled on-stack from within a task context that has current->journal_info set. Having a page fault from some other filesystem bounce into XFS where we have to run a transaction isn't a bug at all, but the usage of current->journal_info means that this could result corruption of the outer task's journal_info structure.
The problem is purely that we now have two different contexts that now think they own current->journal_info. IOWs, no filesystem can allow page faults or on-stack exceptions while current->journal_info is set by the filesystem because the exception processing might use current->journal_info itself.
If we end up with nested XFS transactions whilst holding an empty transaction, then it isn't an issue as the outer transaction does not hold a log reservation. If we ignore the current->journal_info usage, then the only problem that might occur is a deadlock if the exception tries to take the same locks the upper context holds. That, however, is not a problem that setting current->journal_info would solve, so it's largely an irrelevant concern here.
IOWs, we really only use current->journal_info for a warning check in xfs_vm_writepages() to ensure we aren't doing writeback from a transaction context. Writeback might need to do allocation, so it can need to run transactions itself. Hence it's a debug check to warn us that we've done something silly, and largely it is not all that useful.
So let's just remove all the use of current->journal_info in XFS and get rid of all the potential issues from nested contexts where current->journal_info might get misused by another filesystem context.
--- fs/xfs/scrub/common.c | 4 +--- fs/xfs/xfs_aops.c | 7 ------- fs/xfs/xfs_icache.c | 8 +++++--- fs/xfs/xfs_trans.h | 9 +-------- 4 files changed, 7 insertions(+), 21 deletions(-)
fs/xfs/scrub/common.c +1 -3
@@ -978,9 +978,7 @@ xchk_irele( struct xfs_scrub *sc, struct xfs_inode *ip) { -if (current->journal_info !=NULL ) { -ASSERT (current->journal_info == sc->tp); - +if (sc->tp) {/* * If we are in a transaction, we /cannot/ drop the inode * ourselves, because the VFS will trigger writeback, which
fs/xfs/xfs_aops.c +0 -7
@@ -502,13 +502,6 @@ xfs_vm_writepages( {struct xfs_writepage_ctx wpc = { }; -/* -* Writing back data in a transaction context can result in recursive -* transactions. This is bad, so issue a warning and get out of here. -*/ -if (WARN_ON_ONCE (current->journal_info)) -return 0 ; -xfs_iflags_clear (XFS_I (mapping->host),XFS_ITRUNCATED );return iomap_writepages (mapping, wbc, &wpc.ctx, &xfs_writeback_ops); }
fs/xfs/xfs_icache.c +5 -3
@@ -2031,8 +2031,10 @@ xfs_inodegc_want_queue_work(* - Memory shrinkers queued the inactivation worker and it hasn't finished. * - The queue depth exceeds the maximum allowable percpu backlog. * -* Note: If the current thread is running a transaction, we don't ever want to -* wait for other transactions because that could introduce a deadlock. +* Note: If we are in a NOFS context here (e.g. current thread is running a +* transaction) the we don't want to block here as inodegc progress may require +* filesystem resources we hold to make progress and that could result in a +* deadlock. Hence we skip out of here if we are in a scoped NOFS context. */ static inline bool xfs_inodegc_want_flush_work(
@@ -2040,7 +2042,7 @@ xfs_inodegc_want_flush_work( unsigned int items, unsigned int shrinker_hits) { -if (current->journal_info) +if (current->flags &PF_MEMALLOC_NOFS )return false;if (shrinker_hits >0 )
fs/xfs/xfs_trans.h +1 -8
@@ -277,19 +277,14 @@ static inline voidxfs_trans_set_context ( struct xfs_trans *tp) { -ASSERT (current->journal_info ==NULL ); tp->t_pflags =memalloc_nofs_save (); - current->journal_info = tp; }static inline void xfs_trans_clear_context (struct xfs_trans *tp) { -if (current->journal_info == tp) { -memalloc_nofs_restore (tp->t_pflags); - current->journal_info =NULL ; - } +memalloc_nofs_restore (tp->t_pflags); } static inline void
@@ -297,10 +292,8 @@ xfs_trans_switch_context(struct xfs_trans *old_tp, struct xfs_trans *new_tp) { - ASSERT(current->journal_info == old_tp); new_tp->t_pflags = old_tp->t_pflags; old_tp->t_pflags =0 ; - current->journal_info = new_tp; }#endif /* __XFS_TRANS_H__ */
Greg Kroah-Hartman
maintainerPATCH 237/267 xfs: allow cross-linking special files without project quota
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrey Albershteyn <[email protected]>
commit e23d7e82b707d1d0a627e334fb46370e4f772c11 upstream.
There's an issue that if special files is created before quota project is enabled, then it's not possible to link this file. This works fine for normal files. This happens because xfs_quota skips special files (no ioctls to set necessary flags). The check for having the same project ID for source and destination then fails as source file doesn't have any ID.
mkfs.xfs -f /dev/sda
mount -o prjquota /dev/sda /mnt/test
mkdir /mnt/test/foo
mkfifo /mnt/test/foo/fifo1
xfs_quota -xc "project -sp /mnt/test/foo 9" /mnt/test
Quoted 3 lines
Setting up project 9 (path
/mnt/test/foo)...xfs_quota: skipping special file/mnt/test/foo/fifo1
Processed 1 (/etc/projectsand cmdline) paths for project 9 with recursion depth infinite (-1).
ln /mnt/test/foo/fifo1 /mnt/test/foo/fifo1_link
Quoted 1 line
ln: failed to create hard link '
/mnt/test/testdir/fifo1_link' => '/mnt/test/testdir/fifo1': Invalid cross-device link
mkfifo /mnt/test/foo/fifo2
ln /mnt/test/foo/fifo2 /mnt/test/foo/fifo2_link
Fix this by allowing linking of special files to the project quota if special files doesn't have any ID set (ID = 0).
--- fs/xfs/xfs_inode.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
fs/xfs/xfs_inode.c +13 -2
@@ -1239,8 +1239,19 @@ xfs_link(*/ if (unlikely ((tdp->i_diflags &XFS_DIFLAG_PROJINHERIT ) && tdp->i_projid != sip->i_projid)) { - error = -EXDEV ; - goto error_return; +/* +* Project quota setup skips special files which can +* leave inodes in a PROJINHERIT directory without a +* project ID set. We need to allow links to be made +* to these "project-less" inodes because userspace +* expects them to succeed after project ID setup, +* but everything else should be rejected. +*/ +if (!special_file (VFS_I (sip)->i_mode) || + sip->i_projid !=0 ) { + error = -EXDEV ; + goto error_return; + } }if (!resblks) {
Greg Kroah-Hartman
maintainerPATCH 238/267 swiotlb: Enforce page alignment in swiotlb_alloc()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Will Deacon <[email protected]>
commit 823353b7cf0ea9dfb09f5181d5fb2825d727200b upstream.
When allocating pages from a restricted DMA pool in swiotlb_alloc(), the buffer address is blindly converted to a 'struct page *' that is returned to the caller. In the unlikely event of an allocation bug, page-unaligned addresses are not detected and slots can silently be double-allocated.
Add a simple check of the buffer alignment in swiotlb_alloc() to make debugging a little easier if something has gone wonky.
--- kernel/dma/swiotlb.c | 6 ++++++ 1 file changed, 6 insertions(+)
kernel/dma/swiotlb.c +6 -0
@@ -1627,6 +1627,12 @@ struct page *swiotlb_alloc(struct devicereturn NULL ; tlb_addr =slot_addr (pool->start, index); +if (unlikely (!PAGE_ALIGNED (tlb_addr))) { +dev_WARN_ONCE (dev,1 ,"Cannot allocate pages from non page-aligned swiotlb addr 0x%pa.\n" , + &tlb_addr); +swiotlb_release_slots (dev, tlb_addr); +return NULL ; + }return pfn_to_page (PFN_DOWN (tlb_addr)); }
Greg Kroah-Hartman
maintainerPATCH 239/267 swiotlb: Reinstate page-alignment for mappings >= PAGE_SIZE
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Will Deacon <[email protected]>
commit 14cebf689a78e8a1c041138af221ef6eac6bc7da upstream.
For swiotlb allocations >= PAGE_SIZE, the slab search historically adjusted the stride to avoid checking unaligned slots. This had the side-effect of aligning large mapping requests to PAGE_SIZE, but that was broken by 0eee5ae10256 ("swiotlb: fix slot alignment checks").
Since this alignment could be relied upon drivers, reinstate PAGE_SIZE alignment for swiotlb mappings >= PAGE_SIZE.
--- kernel/dma/swiotlb.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
kernel/dma/swiotlb.c +11 -7
@@ -993,6 +993,17 @@ static int swiotlb_area_find_slots(strucBUG_ON (area_index >= pool->nareas);/* +* Historically, swiotlb allocations >= PAGE_SIZE were guaranteed to be +* page-aligned in the absence of any other alignment requirements. +* 'alloc_align_mask' was later introduced to specify the alignment +* explicitly, however this is passed as zero for streaming mappings +* and so we preserve the old behaviour there in case any drivers are +* relying on it. +*/ +if (!alloc_align_mask && !iotlb_align_mask && alloc_size >=PAGE_SIZE ) + alloc_align_mask =PAGE_SIZE -1 ; + +/* * Ensure that the allocation is at least slot-aligned and update * 'iotlb_align_mask' to ignore bits that will be preserved when * offsetting into the allocation.
@@ -1006,13 +1017,6 @@ static int swiotlb_area_find_slots(struc*/ stride =get_max_slots (max (alloc_align_mask, iotlb_align_mask)); -/* -* For allocations of PAGE_SIZE or larger only look for page aligned -* allocations. -*/ -if (alloc_size >=PAGE_SIZE ) - stride =umax (stride,PAGE_SHIFT -IO_TLB_SHIFT +1 ); -spin_lock_irqsave (&area->lock, flags);if (unlikely (nslots > pool->area_nslabs - area->used)) goto not_found;
Greg Kroah-Hartman
maintainerPATCH 240/267 swiotlb: extend buffer pre-padding to alloc_align_mask if necessary
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Petr Tesarik <[email protected]>
commit af133562d5aff41fcdbe51f1a504ae04788b5fc0 upstream.
Allow a buffer pre-padding of up to alloc_align_mask, even if it requires allocating additional IO TLB slots.
If the allocation alignment is bigger than IO_TLB_SIZE and min_align_mask covers any non-zero bits in the original address between IO_TLB_SIZE and alloc_align_mask, these bits are not preserved in the swiotlb buffer address.
To fix this case, increase the allocation size and use a larger offset within the allocated buffer. As a result, extra padding slots may be allocated before the mapping start address.
Leave orig_addr in these padding slots initialized to INVALID_PHYS_ADDR. These slots do not correspond to any CPU buffer, so attempts to sync the data should be ignored.
The padding slots should be automatically released when the buffer is unmapped. However, swiotlb_tbl_unmap_single() takes only the address of the DMA buffer slot, not the first padding slot. Save the number of padding slots in struct io_tlb_slot and use it to adjust the slot index in swiotlb_release_slots(), so all allocated slots are properly freed.
--- kernel/dma/swiotlb.c | 59 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 13 deletions(-)
kernel/dma/swiotlb.c +46 -13
@@ -69,11 +69,14 @@* @alloc_size: Size of the allocated buffer. * @list: The free list describing the number of free entries available * from each index. +* @pad_slots: Number of preceding padding slots. Valid only in the first +* allocated non-padding slot. */ struct io_tlb_slot {phys_addr_t orig_addr;size_t alloc_size; -unsigned int list; +unsigned short list; +unsigned short pad_slots; };static bool swiotlb_force_bounce;
@@ -287,6 +290,7 @@ static void swiotlb_init_io_tlb_pool(str mem->nslabs - i); mem->slots[i].orig_addr =INVALID_PHYS_ADDR ; mem->slots[i].alloc_size =0 ; + mem->slots[i].pad_slots =0 ; }memset (vaddr,0 , bytes);
@@ -821,12 +825,30 @@ void swiotlb_dev_init(struct device *dev#endif } -/* -* Return the offset into a iotlb slot required to keep the device happy. +/** +* swiotlb_align_offset() - Get required offset into an IO TLB allocation. +* @dev: Owning device. +* @align_mask: Allocation alignment mask. +* @addr: DMA address. +* +* Return the minimum offset from the start of an IO TLB allocation which is +* required for a given buffer address and allocation alignment to keep the +* device happy. +* +* First, the address bits covered by min_align_mask must be identical in the +* original address and the bounce buffer address. High bits are preserved by +* choosing a suitable IO TLB slot, but bits below IO_TLB_SHIFT require extra +* padding bytes before the bounce buffer. +* +* Second, @align_mask specifies which bits of the first allocated slot must +* be zero. This may require allocating additional padding slots, and then the +* offset (in bytes) from the first such padding slot is returned. */ -static unsigned int swiotlb_align_offset (struct device *dev,u64 addr) +static unsigned int swiotlb_align_offset (struct device *dev, +unsigned int align_mask,u64 addr) { -return addr &dma_get_min_align_mask (dev) & (IO_TLB_SIZE -1 ); +return addr &dma_get_min_align_mask (dev) & + (align_mask | (IO_TLB_SIZE -1 )); }/*
@@ -847,7 +869,7 @@ static void swiotlb_bounce(struct devicereturn ; tlb_offset = tlb_addr & (IO_TLB_SIZE -1 ); - orig_addr_offset =swiotlb_align_offset (dev, orig_addr); + orig_addr_offset =swiotlb_align_offset (dev,0 , orig_addr);if (tlb_offset < orig_addr_offset) { dev_WARN_ONCE(dev, 1, "Access before mapping start detected. orig offset %u, requested offset %u.\n",
@@ -983,7 +1005,7 @@ static int swiotlb_area_find_slots(strucunsigned long max_slots =get_max_slots (boundary_mask);unsigned int iotlb_align_mask =dma_get_min_align_mask (dev);unsigned int nslots =nr_slots (alloc_size), stride; -unsigned int offset =swiotlb_align_offset (dev, orig_addr); +unsigned int offset =swiotlb_align_offset (dev,0 , orig_addr);unsigned int index, slots_checked, count =0 , i;unsigned long flags;unsigned int slot_base;
@@ -1282,11 +1304,12 @@ phys_addr_t swiotlb_tbl_map_single(struc unsigned long attrs) {struct io_tlb_mem *mem = dev->dma_io_tlb_mem; -unsigned int offset =swiotlb_align_offset (dev, orig_addr); +unsigned int offset;struct io_tlb_pool *pool;unsigned int i;int index;phys_addr_t tlb_addr; +unsigned short pad_slots;if (!mem || !mem->nslabs) { dev_warn_ratelimited(dev,
@@ -1303,6 +1326,7 @@ phys_addr_t swiotlb_tbl_map_single(strucreturn (phys_addr_t )DMA_MAPPING_ERROR ; } + offset =swiotlb_align_offset (dev, alloc_align_mask, orig_addr); index =swiotlb_find_slots (dev, orig_addr, alloc_size + offset, alloc_align_mask, &pool);if (index ==-1 ) {
@@ -1318,6 +1342,10 @@ phys_addr_t swiotlb_tbl_map_single(struc* This is needed when we sync the memory. Then we sync the buffer if * needed. */ + pad_slots = offset >>IO_TLB_SHIFT ; + offset &= (IO_TLB_SIZE -1 ); + index += pad_slots; + pool->slots[index].pad_slots = pad_slots;for (i =0 ; i <nr_slots (alloc_size + offset); i++) pool->slots[index + i].orig_addr =slot_addr (orig_addr, i); tlb_addr =slot_addr (pool->start, index) + offset;
@@ -1336,13 +1364,17 @@ static void swiotlb_release_slots(struct {struct io_tlb_pool *mem =swiotlb_find_pool (dev, tlb_addr);unsigned long flags; -unsigned int offset =swiotlb_align_offset (dev, tlb_addr); -int index = (tlb_addr - offset - mem->start) >>IO_TLB_SHIFT ; -int nslots =nr_slots (mem->slots[index].alloc_size + offset); -int aindex = index / mem->area_nslabs; -struct io_tlb_area *area = &mem->areas[aindex]; +unsigned int offset =swiotlb_align_offset (dev,0 , tlb_addr); +int index, nslots, aindex; +struct io_tlb_area *area;int count, i; + index = (tlb_addr - offset - mem->start) >>IO_TLB_SHIFT ; + index -= mem->slots[index].pad_slots; + nslots =nr_slots (mem->slots[index].alloc_size + offset); + aindex = index / mem->area_nslabs; + area = &mem->areas[aindex]; +/* * Return the buffer to the free list by setting the corresponding * entries to indicate the number of contiguous entries available.
@@ -1365,6 +1397,7 @@ static void swiotlb_release_slots(struct mem->slots[i].list = ++count; mem->slots[i].orig_addr =INVALID_PHYS_ADDR ; mem->slots[i].alloc_size =0 ; + mem->slots[i].pad_slots =0 ; }/*
Greg Kroah-Hartman
maintainerPATCH 241/267 nilfs2: fix potential kernel bug due to lack of writeback flag waiting
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryusuke Konishi <[email protected]>
commit a4ca369ca221bb7e06c725792ac107f0e48e82e7 upstream.
Destructive writes to a block device on which nilfs2 is mounted can cause a kernel bug in the folio/page writeback start routine or writeback end routine (__folio_start_writeback in the log below):
kernel BUG at mm/page-writeback.c:3070!
Oops: invalid opcode: 0000 [#1] PREEMPT SMP KASAN PTI ... RIP: 0010:__folio_start_writeback+0xbaa/0x10e0 Code: 25 ff 0f 00 00 0f 84 18 01 00 00 e8 40 ca c6 ff e9 17 f6 ff ff e8 36 ca c6 ff 4c 89 f7 48 c7 c6 80 c0 12 84 e8 e7 b3 0f 00 90 <0f> 0b e8 1f ca c6 ff 4c 89 f7 48 c7 c6 a0 c6 12 84 e8 d0 b3 0f 00 ... Call Trace: <TASK> nilfs_segctor_do_construct+0x4654/0x69d0 [nilfs2] nilfs_segctor_construct+0x181/0x6b0 [nilfs2] nilfs_segctor_thread+0x548/0x11c0 [nilfs2] kthread+0x2f0/0x390 ret_from_fork+0x4b/0x80 ret_from_fork_asm+0x1a/0x30 </TASK>
This is because when the log writer starts a writeback for segment summary blocks or a super root block that use the backing device's page cache, it does not wait for the ongoing folio/page writeback, resulting in an inconsistent writeback state.
Fix this issue by waiting for ongoing writebacks when putting folios/pages on the backing device into writeback state.
--- fs/nilfs2/segment.c | 3 +++ 1 file changed, 3 insertions(+)
fs/nilfs2/segment.c +3 -0
@@ -1694,6 +1694,7 @@ static void nilfs_segctor_prepare_write(if (bh->b_page != bd_page) {if (bd_page) {lock_page (bd_page); +wait_on_page_writeback (bd_page);clear_page_dirty_for_io (bd_page);set_page_writeback (bd_page);unlock_page (bd_page);
@@ -1707,6 +1708,7 @@ static void nilfs_segctor_prepare_write(if (bh == segbuf->sb_super_root) {if (bh->b_page != bd_page) {lock_page (bd_page); +wait_on_page_writeback (bd_page);clear_page_dirty_for_io (bd_page);set_page_writeback (bd_page);unlock_page (bd_page);
@@ -1723,6 +1725,7 @@ static void nilfs_segctor_prepare_write( }if (bd_page) {lock_page (bd_page); +wait_on_page_writeback (bd_page);clear_page_dirty_for_io (bd_page);set_page_writeback (bd_page);unlock_page (bd_page);
Greg Kroah-Hartman
maintainerPATCH 242/267 tick/nohz_full: Dont abuse smp_call_function_single() in tick_setup_device()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oleg Nesterov <[email protected]>
commit 07c54cc5988f19c9642fd463c2dbdac7fc52f777 upstream.
After the recent commit 5097cbcb38e6 ("sched/isolation: Prevent boot crash when the boot CPU is nohz_full") the kernel no longer crashes, but there is another problem.
In this case tick_setup_device() calls tick_take_do_timer_from_boot() to update tick_do_timer_cpu and this triggers the WARN_ON_ONCE(irqs_disabled) in smp_call_function_single().
Kill tick_take_do_timer_from_boot() and just use WRITE_ONCE(), the new comment explains why this is safe (thanks Thomas!).
--- kernel/time/tick-common.c | 42 ++++++++++++++---------------------------- 1 file changed, 14 insertions(+), 28 deletions(-)
kernel/time/tick-common.c +14 -28
@@ -179,26 +179,6 @@ void tick_setup_periodic(struct clock_ev } } -#ifdef CONFIG_NO_HZ_FULL -static void giveup_do_timer (void *info) -{ -int cpu = *(unsigned int *)info; - -WARN_ON (tick_do_timer_cpu !=smp_processor_id ()); - - tick_do_timer_cpu = cpu; -} - -static void tick_take_do_timer_from_boot (void ) -{ -int cpu =smp_processor_id (); -int from = tick_do_timer_boot_cpu; - -if (from >=0 && from != cpu) -smp_call_function_single (from, giveup_do_timer, &cpu,1 ); -} -#endif -/* * Setup the tick device */
@@ -222,19 +202,25 @@ static void tick_setup_device(struct tic tick_next_period =ktime_get ();#ifdef CONFIG_NO_HZ_FULL /* -* The boot CPU may be nohz_full, in which case set -* tick_do_timer_boot_cpu so the first housekeeping -* secondary that comes up will take do_timer from -* us. +* The boot CPU may be nohz_full, in which case the +* first housekeeping secondary will take do_timer() +* from it. */ if (tick_nohz_full_cpu (cpu)) tick_do_timer_boot_cpu = cpu; - }else if (tick_do_timer_boot_cpu !=-1 && - !tick_nohz_full_cpu (cpu)) { -tick_take_do_timer_from_boot (); + }else if (tick_do_timer_boot_cpu !=-1 && !tick_nohz_full_cpu (cpu)) { tick_do_timer_boot_cpu =-1 ; -WARN_ON (tick_do_timer_cpu != cpu); +/* +* The boot CPU will stay in periodic (NOHZ disabled) +* mode until clocksource_done_booting() called after +* smp_init() selects a high resolution clocksource and +* timekeeping_notify() kicks the NOHZ stuff alive. +* +* So this WRITE_ONCE can only race with the READ_ONCE +* check in tick_periodic() but this race is harmless. +*/ +WRITE_ONCE (tick_do_timer_cpu, cpu);#endif }
Greg Kroah-Hartman
maintainerPATCH 243/267 mm/huge_memory: dont unpoison huge_zero_folio
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miaohe Lin <[email protected]>
commit fe6f86f4b40855a130a19aa589f9ba7f650423f4 upstream.
When I did memory failure tests recently, below panic occurs:
kernel BUG at include/linux/mm.h:1135!
invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
CPU: 9 PID: 137 Comm: kswapd1 Not tainted 6.9.0-rc4-00491-gd5ce28f156fe-dirty #14 RIP: 0010:shrink_huge_zero_page_scan+0x168/0x1a0 RSP: 0018:ffff9933c6c57bd0 EFLAGS: 00000246 RAX: 000000000000003e RBX: 0000000000000000 RCX: ffff88f61fc5c9c8 RDX: 0000000000000000 RSI: 0000000000000027 RDI: ffff88f61fc5c9c0 RBP: ffffcd7c446b0000 R08: ffffffff9a9405f0 R09: 0000000000005492 R10: 00000000000030ea R11: ffffffff9a9405f0 R12: 0000000000000000 R13: 0000000000000000 R14: 0000000000000000 R15: ffff88e703c4ac00 FS: 0000000000000000(0000) GS:ffff88f61fc40000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055f4da6e9878 CR3: 0000000c71048000 CR4: 00000000000006f0 Call Trace: <TASK> do_shrink_slab+0x14f/0x6a0 shrink_slab+0xca/0x8c0 shrink_node+0x2d0/0x7d0 balance_pgdat+0x33a/0x720 kswapd+0x1f3/0x410 kthread+0xd5/0x100 ret_from_fork+0x2f/0x50 ret_from_fork_asm+0x1a/0x30 </TASK> Modules linked in: mce_inject hwpoison_inject ---[ end trace 0000000000000000 ]--- RIP: 0010:shrink_huge_zero_page_scan+0x168/0x1a0 RSP: 0018:ffff9933c6c57bd0 EFLAGS: 00000246 RAX: 000000000000003e RBX: 0000000000000000 RCX: ffff88f61fc5c9c8 RDX: 0000000000000000 RSI: 0000000000000027 RDI: ffff88f61fc5c9c0 RBP: ffffcd7c446b0000 R08: ffffffff9a9405f0 R09: 0000000000005492 R10: 00000000000030ea R11: ffffffff9a9405f0 R12: 0000000000000000 R13: 0000000000000000 R14: 0000000000000000 R15: ffff88e703c4ac00 FS: 0000000000000000(0000) GS:ffff88f61fc40000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055f4da6e9878 CR3: 0000000c71048000 CR4: 00000000000006f0
The root cause is that HWPoison flag will be set for huge_zero_folio without increasing the folio refcnt. But then unpoison_memory() will decrease the folio refcnt unexpectedly as it appears like a successfully hwpoisoned folio leading to VM_BUG_ON_PAGE(page_ref_count(page) == 0) when releasing huge_zero_folio.
Skip unpoisoning huge_zero_folio in unpoison_memory() to fix this issue. We're not prepared to unpoison huge_zero_folio yet.
--- mm/memory-failure.c | 7 +++++++ 1 file changed, 7 insertions(+)
mm/memory-failure.c +7 -0
@@ -2535,6 +2535,13 @@ int unpoison_memory(unsigned long pfn) goto unlock_mutex; } +if (is_huge_zero_page (&folio->page)) { +unpoison_pr_info ("Unpoison: huge zero page is not supported %#lx\n" , + pfn, &unpoison_rs); + ret = -EOPNOTSUPP ; + goto unlock_mutex; + } +if (!PageHWPoison (p)) {unpoison_pr_info ("Unpoison: Page was already unpoisoned %#lx\n" , pfn, &unpoison_rs);
Greg Kroah-Hartman
maintainerPATCH 244/267 serial: 8250_pxa: Configure tx_loadsz to match FIFO IRQ level
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Doug Brown <[email protected]>
commit 5208e7ced520a813b4f4774451fbac4e517e78b2 upstream.
The FIFO is 64 bytes, but the FCR is configured to fire the TX interrupt when the FIFO is half empty (bit 3 = 0). Thus, we should only write 32 bytes when a TX interrupt occurs.
This fixes a problem observed on the PXA168 that dropped a bunch of TX bytes during large transmissions.
--- drivers/tty/serial/8250/8250_pxa.c | 1 + 1 file changed, 1 insertion(+)
drivers/tty/serial/8250/8250_pxa.c +1 -0
@@ -124,6 +124,7 @@ static int serial_pxa_probe(struct platf uart.port.regshift =2 ; uart.port.irq = irq; uart.port.fifosize =64 ; + uart.tx_loadsz =32 ; uart.port.flags =UPF_IOREMAP |UPF_SKIP_TEST |UPF_FIXED_TYPE ; uart.port.dev = &pdev->dev; uart.port.uartclk =clk_get_rate (data->clk);
Greg Kroah-Hartman
maintainerPATCH 245/267 Revert "fork: defer linking file vma until vma is fully initialized"
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sam James <[email protected]>
This reverts commit cec11fa2eb512ebe3a459c185f4aca1d44059bbf which is commit 35e351780fa9d8240dd6f7e4f245f9ea37e96c19 upstream.
The backport is incomplete and causes xfstests failures. The consequences of the incomplete backport seem worse than the original issue, so pick the lesser evil and revert until a full backport is ready.
--- kernel/fork.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
kernel/fork.c +9 -9
@@ -727,15 +727,6 @@ static __latent_entropy int dup_mmap(str }else if (anon_vma_fork (tmp, mpnt)) goto fail_nomem_anon_vma_fork;vm_flags_clear (tmp,VM_LOCKED_MASK ); -/* -* Copy/update hugetlb private vma information. -*/ -if (is_vm_hugetlb_page (tmp)) -hugetlb_dup_vma_private (tmp); - -if (tmp->vm_ops && tmp->vm_ops->open) - tmp->vm_ops->open (tmp); - file = tmp->vm_file;if (file) {struct address_space *mapping = file->f_mapping;
@@ -752,6 +743,12 @@ static __latent_entropy int dup_mmap(stri_mmap_unlock_write (mapping); } +/* +* Copy/update hugetlb private vma information. +*/ +if (is_vm_hugetlb_page (tmp)) +hugetlb_dup_vma_private (tmp); +/* Link the vma into the MT */ if (vma_iter_bulk_store (&vmi, tmp)) goto fail_nomem_vmi_store;
@@ -760,6 +757,9 @@ static __latent_entropy int dup_mmap(strif (!(tmp->vm_flags &VM_WIPEONFORK )) retval =copy_page_range (tmp, mpnt); +if (tmp->vm_ops && tmp->vm_ops->open) + tmp->vm_ops->open (tmp); +if (retval) goto loop_out; }
Greg Kroah-Hartman
maintainerPATCH 246/267 selftests/net: add lib.sh
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hangbin Liu <[email protected]>
commit 25ae948b447881bf689d459cd5bd4629d9c04b20 upstream.
Add a lib.sh for net selftests. This file can be used to define commonly used variables and functions. Some commonly used functions can be moved from forwarding/lib.sh to this lib file. e.g. busywait().
Add function setup_ns() for user to create unique namespaces with given prefix name.
[PHLin: add lib.sh to TEST_FILES directly as we already have upstream
commit 06efafd8 landed in 6.6.y]
--- tools/testing/selftests/net/Makefile | 2 tools/testing/selftests/net/forwarding/lib.sh | 27 -------- tools/testing/selftests/net/lib.sh | 85 ++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 27 deletions(-) create mode 100644 tools/testing/selftests/net/lib.sh
tools/testing/selftests/net/Makefile +1 -1
@@ -92,7 +92,7 @@ TEST_PROGS += test_vxlan_nolocalbypass.s TEST_PROGS += test_bridge_backup_port.sh TEST_FILES := settings -TEST_FILES += in_netns.sh net_helper.sh setup_loopback.sh setup_veth.sh +TEST_FILES += in_netns.sh lib.sh net_helper.sh setup_loopback.sh setup_veth.sh include ../lib.mk
tools/testing/selftests/net/forwarding/lib.sh +1 -26
@@ -4,9 +4,6 @@ ############################################################################## # Defines -# Kselftest framework requirement - SKIP code is 4. -ksft_skip=4 - # Can be overridden by the configuration file. PING=${PING:=ping} PING6=${PING6:=ping6}
@@ -41,6 +38,7 @@ if [[ -f $relative_path/forwarding.confi source "$relative_path/forwarding.config" fi +source ../lib.sh ############################################################################## # Sanity checks
@@ -395,29 +393,6 @@ log_info() echo "INFO: $msg" } -busywait() -{ - local timeout=$1; shift - - local start_time="$(date -u +%s%3N)" - while true - do - local out - out=$("$@") - local ret=$? - if ((!ret)); then - echo -n "$out" - return 0 - fi - - local current_time="$(date -u +%s%3N)" - if ((current_time - start_time > timeout)); then - echo -n "$out" - return 1 - fi - done -} - not() { "$@"
tools/testing/selftests/net/lib.sh new file +85 -0
85 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 247/267 selftests/net: add variable NS_LIST for lib.sh
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hangbin Liu <[email protected]>
commit b6925b4ed57cccf42ca0fb46c7446f0859e7ad4b upstream.
Add a global variable NS_LIST to store all the namespaces that setup_ns created, so the caller could call cleanup_all_ns() instead of remember all the netns names when using cleanup_ns().
--- tools/testing/selftests/net/lib.sh | 8 ++++++++ 1 file changed, 8 insertions(+)
tools/testing/selftests/net/lib.sh +8 -0
@@ -6,6 +6,8 @@ # Kselftest framework requirement - SKIP code is 4. ksft_skip=4 +# namespace list created by setup_ns +NS_LIST="" ############################################################################## # Helpers
@@ -56,6 +58,11 @@ cleanup_ns() return $ret } +cleanup_all_ns() +{ + cleanup_ns $NS_LIST +} + # setup netns with given names as prefix. e.g # setup_ns local remote setup_ns()
@@ -82,4 +89,5 @@ setup_ns() ip -n "$ns" link set lo up ns_list="$ns_list $ns" done + NS_LIST="$NS_LIST $ns_list" }
Greg Kroah-Hartman
maintainerPATCH 248/267 selftests: forwarding: Avoid failures to source net/lib.sh
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Poirier <[email protected]>
commit 2114e83381d3289a88378850f43069e79f848083 upstream.
The expression "source ../lib.sh" added to net/forwarding/lib.sh in commit 25ae948b4478 ("selftests/net: add lib.sh") does not work for tests outside net/forwarding which source net/forwarding/lib.sh (1). It also does not work in some cases where only a subset of tests are exported (2).
Avoid the problems mentioned above by replacing the faulty expression with a copy of the content from net/lib.sh which is used by files under net/forwarding.
A more thorough solution which avoids duplicating content between net/lib.sh and net/forwarding/lib.sh has been posted here:
https://lore.kernel.org/netdev/[email protected]/
The approach in the current patch is a stopgap solution to avoid submitting large changes at the eleventh hour of this development cycle.
Example of problem 1)
tools/testing/selftests/drivers/net/bonding$ ./dev_addr_lists.sh ./net_forwarding_lib.sh: line 41: ../lib.sh: No such file or directory
TEST: bonding cleanup mode active-backup [ OK ]
TEST: bonding cleanup mode 802.3ad [ OK ]
TEST: bonding LACPDU multicast address to slave (from bond down) [ OK ]
TEST: bonding LACPDU multicast address to slave (from bond up) [ OK ]
An error message is printed but since the test does not use functions from net/lib.sh, the test results are not affected.
Example of problem 2)
tools/testing/selftests$ make install TARGETS="net/forwarding" tools/testing/selftests$ cd kselftest_install/net/forwarding/ tools/testing/selftests/kselftest_install/net/forwarding$ ./pedit_ip.sh veth{0..3} lib.sh: line 41: ../lib.sh: No such file or directory
TEST: ping [ OK ]
TEST: ping6 [ OK ]
./pedit_ip.sh: line 135: busywait: command not found
TEST: dev veth1 ingress pedit ip src set 198.51.100.1 [FAIL]
Expected to get 10 packets, but got .
./pedit_ip.sh: line 135: busywait: command not found
TEST: dev veth2 egress pedit ip src set 198.51.100.1 [FAIL]
Expected to get 10 packets, but got .
./pedit_ip.sh: line 135: busywait: command not found
TEST: dev veth1 ingress pedit ip dst set 198.51.100.1 [FAIL]
Expected to get 10 packets, but got .
./pedit_ip.sh: line 135: busywait: command not found
TEST: dev veth2 egress pedit ip dst set 198.51.100.1 [FAIL]
Expected to get 10 packets, but got .
./pedit_ip.sh: line 135: busywait: command not found
TEST: dev veth1 ingress pedit ip6 src set 2001:db8:2::1 [FAIL]
Expected to get 10 packets, but got .
./pedit_ip.sh: line 135: busywait: command not found
TEST: dev veth2 egress pedit ip6 src set 2001:db8:2::1 [FAIL]
Expected to get 10 packets, but got .
./pedit_ip.sh: line 135: busywait: command not found
TEST: dev veth1 ingress pedit ip6 dst set 2001:db8:2::1 [FAIL]
Expected to get 10 packets, but got .
./pedit_ip.sh: line 135: busywait: command not found
TEST: dev veth2 egress pedit ip6 dst set 2001:db8:2::1 [FAIL]
Expected to get 10 packets, but got .
In this case, the test results are affected.
--- tools/testing/selftests/net/forwarding/lib.sh | 27 +++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-)
tools/testing/selftests/net/forwarding/lib.sh +26 -1
@@ -38,7 +38,32 @@ if [[ -f $relative_path/forwarding.confi source "$relative_path/forwarding.config" fi -source ../lib.sh +# Kselftest framework requirement - SKIP code is 4. +ksft_skip=4 + +busywait() +{ + local timeout=$1; shift + + local start_time="$(date -u +%s%3N)" + while true + do + local out + out=$("$@") + local ret=$? + if ((!ret)); then + echo -n "$out" + return 0 + fi + + local current_time="$(date -u +%s%3N)" + if ((current_time - start_time > timeout)); then + echo -n "$out" + return 1 + fi + done +} + ############################################################################## # Sanity checks
Greg Kroah-Hartman
maintainerPATCH 249/267 remoteproc: k3-r5: Jump to error handling labels in start/stop errors
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Beleswar Padhi <[email protected]>
commit 1dc7242f6ee0c99852cb90676d7fe201cf5de422 upstream.
In case of errors during core start operation from sysfs, the driver directly returns with the -EPERM error code. Fix this to ensure that mailbox channels are freed on error before returning by jumping to the 'put_mbox' error handling label. Similarly, jump to the 'out' error handling label to return with required -EPERM error code during the core stop operation from sysfs.
--- drivers/remoteproc/ti_k3_r5_remoteproc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/remoteproc/ti_k3_r5_remoteproc.c +4 -2
@@ -580,7 +580,8 @@ static int k3_r5_rproc_start(struct rproif (core != core0 && core0->rproc->state ==RPROC_OFFLINE ) {dev_err (dev,"%s: can not start core 1 before core 0\n" , __func__); -return -EPERM ; + ret = -EPERM ; + goto put_mbox; } ret =k3_r5_core_run (core);
@@ -648,7 +649,8 @@ static int k3_r5_rproc_stop(struct rprocif (core != core1 && core1->rproc->state !=RPROC_OFFLINE ) {dev_err (dev,"%s: can not stop core 0 before core 1\n" , __func__); -return -EPERM ; + ret = -EPERM ; + goto out; } ret =k3_r5_core_halt (core);
Greg Kroah-Hartman
maintainerPATCH 250/267 cachefiles, erofs: Fix NULL deref in when cachefiles is not doing ondemand-mode
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <[email protected]>
commit c3d6569a43322f371e7ba0ad386112723757ac8f upstream.
cachefiles_ondemand_init_object() as called from cachefiles_open_file() and cachefiles_create_tmpfile() does not check if object->ondemand is set before dereferencing it, leading to an oops something like:
RIP: 0010:cachefiles_ondemand_init_object+0x9/0x41 ... Call Trace: <TASK> cachefiles_open_file+0xc9/0x187 cachefiles_lookup_cookie+0x122/0x2be fscache_cookie_state_machine+0xbe/0x32b fscache_cookie_worker+0x1f/0x2d process_one_work+0x136/0x208 process_scheduled_works+0x3a/0x41 worker_thread+0x1a2/0x1f6 kthread+0xca/0xd2 ret_from_fork+0x21/0x33
Fix this by making cachefiles_ondemand_init_object() return immediately if cachefiles->ondemand is NULL.
--- fs/cachefiles/ondemand.c | 3 +++ 1 file changed, 3 insertions(+)
fs/cachefiles/ondemand.c +3 -0
@@ -611,6 +611,9 @@ int cachefiles_ondemand_init_object(strustruct fscache_volume *volume = object->volume->vcookie;size_t volume_key_size, cookie_key_size, data_len; +if (!object->ondemand) +return 0 ; +/* * CacheFiles will firstly check the cache file under the root cache * directory. If the coherency check failed, it will fallback to
Greg Kroah-Hartman
maintainerPATCH 251/267 selftests/net/lib: update busywait timeout value
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hangbin Liu <[email protected]>
commit fc836129f708407502632107e58d48f54b1caf75 upstream.
The busywait timeout value is a millisecond, not a second. So the current setting 2 is too small. On slow/busy host (or VMs) the current timeout can expire even on "correct" execution, causing random failures. Let's copy the WAIT_TIMEOUT from forwarding/lib.sh and set BUSYWAIT_TIMEOUT here.
--- tools/testing/selftests/net/lib.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
tools/testing/selftests/net/lib.sh +4 -1
@@ -4,6 +4,9 @@ ############################################################################## # Defines +WAIT_TIMEOUT=${WAIT_TIMEOUT:=20} +BUSYWAIT_TIMEOUT=$((WAIT_TIMEOUT * 1000)) # ms + # Kselftest framework requirement - SKIP code is 4. ksft_skip=4 # namespace list created by setup_ns
@@ -48,7 +51,7 @@ cleanup_ns() for ns in "$@"; do ip netns delete "${ns}" &> /dev/null - if ! busywait 2 ip netns list \| grep -vq "^$ns$" &> /dev/null; then + if ! busywait $BUSYWAIT_TIMEOUT ip netns list \| grep -vq "^$ns$" &> /dev/null; then echo "Warn: Failed to remove namespace $ns" ret=1 fi
Greg Kroah-Hartman
maintainerPATCH 252/267 selftests/net/lib: no need to record ns name if it already exist
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hangbin Liu <[email protected]>
commit 83e93942796db58652288f0391ac00072401816f upstream.
There is no need to add the name to ns_list again if the netns already recoreded.
--- tools/testing/selftests/net/lib.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
tools/testing/selftests/net/lib.sh +4 -2
@@ -73,15 +73,17 @@ setup_ns() local ns="" local ns_name="" local ns_list="" + local ns_exist= for ns_name in "$@"; do # Some test may setup/remove same netns multi times if unset ${ns_name} 2> /dev/null; then ns="${ns_name,,}-$(mktemp -u XXXXXX)" eval readonly ${ns_name}="$ns" + ns_exist=false else eval ns='$'${ns_name} cleanup_ns "$ns" - + ns_exist=true fi if ! ip netns add "$ns"; then
@@ -90,7 +92,7 @@ setup_ns() return $ksft_skip fi ip -n "$ns" link set lo up - ns_list="$ns_list $ns" + ! $ns_exist && ns_list="$ns_list $ns" done NS_LIST="$NS_LIST $ns_list" }
Greg Kroah-Hartman
maintainerPATCH 253/267 selftests: net: lib: support errexit with busywait
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit 41b02ea4c0adfcc6761fbfed42c3ce6b6412d881 upstream.
If errexit is enabled ('set -e'), loopy_wait -- or busywait and others using it -- will stop after the first failure.
Note that if the returned status of loopy_wait is checked, and even if errexit is enabled, Bash will not stop at the first error.
--- tools/testing/selftests/net/lib.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
tools/testing/selftests/net/lib.sh +1 -3
@@ -22,9 +22,7 @@ busywait() while true do local out - out=$("$@") - local ret=$? - if ((!ret)); then + if out=$("$@"); then echo -n "$out" return 0 fi
Greg Kroah-Hartman
maintainerPATCH 254/267 selftests: net: lib: avoid error removing empty netns name
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit 79322174bcc780b99795cb89d237b26006a8b94b upstream.
If there is an error to create the first netns with 'setup_ns()', 'cleanup_ns()' will be called with an empty string as first parameter.
The consequences is that 'cleanup_ns()' will try to delete an invalid netns, and wait 20 seconds if the netns list is empty.
Instead of just checking if the name is not empty, convert the string separated by spaces to an array. Manipulating the array is cleaner, and calling 'cleanup_ns()' with an empty array will be a no-op.
--- tools/testing/selftests/net/lib.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
tools/testing/selftests/net/lib.sh +7 -6
@@ -10,7 +10,7 @@ BUSYWAIT_TIMEOUT=$((WAIT_TIMEOUT * 1000) # Kselftest framework requirement - SKIP code is 4. ksft_skip=4 # namespace list created by setup_ns -NS_LIST="" +NS_LIST=() ############################################################################## # Helpers
@@ -48,6 +48,7 @@ cleanup_ns() fi for ns in "$@"; do + [ -z "${ns}" ] && continue ip netns delete "${ns}" &> /dev/null if ! busywait $BUSYWAIT_TIMEOUT ip netns list \| grep -vq "^$ns$" &> /dev/null; then echo "Warn: Failed to remove namespace $ns"
@@ -61,7 +62,7 @@ cleanup_ns() cleanup_all_ns() { - cleanup_ns $NS_LIST + cleanup_ns "${NS_LIST[@]}" } # setup netns with given names as prefix. e.g
@@ -70,7 +71,7 @@ setup_ns() { local ns="" local ns_name="" - local ns_list="" + local ns_list=() local ns_exist= for ns_name in "$@"; do # Some test may setup/remove same netns multi times
@@ -86,11 +87,11 @@ setup_ns() if ! ip netns add "$ns"; then echo "Failed to create namespace $ns_name" - cleanup_ns "$ns_list" + cleanup_ns "${ns_list[@]}" return $ksft_skip fi ip -n "$ns" link set lo up - ! $ns_exist && ns_list="$ns_list $ns" + ! $ns_exist && ns_list+=("$ns") done - NS_LIST="$NS_LIST $ns_list" + NS_LIST+=("${ns_list[@]}") }
Greg Kroah-Hartman
maintainerPATCH 255/267 greybus: Fix use-after-free bug in gb_interface_release due to race condition.
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sicong Huang <[email protected]>
commit 5c9c5d7f26acc2c669c1dcf57d1bb43ee99220ce upstream.
In gb_interface_create, &intf->mode_switch_completion is bound with gb_interface_mode_switch_work. Then it will be started by gb_interface_request_mode_switch. Here is the relevant code.
if (!queue_work(system_long_wq, &intf->mode_switch_work)) {
...
}If we call gb_interface_release to make cleanup, there may be an unfinished work. This function will call kfree to free the object "intf". However, if gb_interface_mode_switch_work is scheduled to run after kfree, it may cause use-after-free error as gb_interface_mode_switch_work will use the object "intf". The possible execution flow that may lead to the issue is as follows:
CPU0 CPU1
| gb_interface_create
| gb_interface_request_mode_switch
gb_interface_release |
kfree(intf) (free) |
| gb_interface_mode_switch_work
| mutex_lock(&intf->mutex) (use)Fix it by canceling the work before kfree.
--- drivers/greybus/interface.c | 1 + 1 file changed, 1 insertion(+)
drivers/greybus/interface.c +1 -0
@@ -694,6 +694,7 @@ static void gb_interface_release(structtrace_gb_interface_release (intf); +cancel_work_sync (&intf->mode_switch_work);kfree (intf); }
Greg Kroah-Hartman
maintainerPATCH 256/267 ima: Fix use-after-free on a dentrys dname.name
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Berger <[email protected]>
commit be84f32bb2c981ca670922e047cdde1488b233de upstream.
->d_name.name can change on rename and the earlier value can be freed; there are conditions sufficient to stabilize it (->d_lock on dentry, ->d_lock on its parent, ->i_rwsem exclusive on the parent's inode, rename_lock), but none of those are met at any of the sites. Take a stable snapshot of the name instead.
--- security/integrity/ima/ima_api.c | 16 ++++++++++++---- security/integrity/ima/ima_template_lib.c | 17 ++++++++++++++--- 2 files changed, 26 insertions(+), 7 deletions(-)
security/integrity/ima/ima_api.c +12 -4
@@ -244,8 +244,8 @@ int ima_collect_measurement(struct integconst char *audit_cause ="failed" ;struct inode *inode =file_inode (file);struct inode *real_inode =d_real_inode (file_dentry (file)); -const char *filename = file->f_path.dentry->d_name.name;struct ima_max_digest_data hash; +struct name_snapshot filename;struct kstat stat;int result =0 ;int length;
@@ -316,9 +316,13 @@ out:if (file->f_flags &O_DIRECT ) audit_cause ="failed(directio)" ; +take_dentry_name_snapshot (&filename, file->f_path.dentry); +integrity_audit_msg (AUDIT_INTEGRITY_DATA , inode, - filename,"collect_data" , audit_cause, - result,0 ); + filename.name.name,"collect_data" , + audit_cause, result,0 ); + +release_dentry_name_snapshot (&filename); }return result; }
@@ -431,6 +435,7 @@ out:*/ const char *ima_d_path (const struct path *path,char **pathbuf,char *namebuf) { +struct name_snapshot filename;char *pathname =NULL ; *pathbuf =__getname ();
@@ -444,7 +449,10 @@ const char *ima_d_path(const struct path }if (!pathname) { -strscpy (namebuf, path->dentry->d_name.name,NAME_MAX ); +take_dentry_name_snapshot (&filename, path->dentry); +strscpy (namebuf, filename.name.name,NAME_MAX ); +release_dentry_name_snapshot (&filename); + pathname = namebuf; }
security/integrity/ima/ima_template_lib.c +14 -3
@@ -483,7 +483,10 @@ static int ima_eventname_init_common(str bool size_limit) {const char *cur_filename =NULL ; +struct name_snapshot filename;u32 cur_filename_len =0 ; +bool snapshot = false; +int ret;BUG_ON (event_data->filename ==NULL && event_data->file ==NULL );
@@ -496,7 +499,10 @@ static int ima_eventname_init_common(str }if (event_data->file) { - cur_filename = event_data->file->f_path.dentry->d_name.name; +take_dentry_name_snapshot (&filename, + event_data->file->f_path.dentry); + snapshot = true; + cur_filename = filename.name.name; cur_filename_len =strlen (cur_filename); }else /*
@@ -505,8 +511,13 @@ static int ima_eventname_init_common(str*/ cur_filename_len =IMA_EVENT_NAME_LEN_MAX ; out: -return ima_write_template_field_data (cur_filename, cur_filename_len, -DATA_FMT_STRING , field_data); + ret =ima_write_template_field_data (cur_filename, cur_filename_len, +DATA_FMT_STRING , field_data); + +if (snapshot) +release_dentry_name_snapshot (&filename); + +return ret; }/*
Greg Kroah-Hartman
maintainerPATCH 257/267 device property: Implement device_is_big_endian()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
[ Upstream commit 826a5d8c9df9605fb4fdefa45432f95580241a1f ]
Some users want to use the struct device pointer to see if the device is big endian in terms of Open Firmware specifications, i.e. if it has a "big-endian" property, or if the kernel was compiled for BE *and* the device has a "native-endian" property.
Provide inline helper for the users.
Stable-dep-of: 87d80bfbd577 ("serial: 8250_dw: Don't use struct dw8250_data outside of 8250_dw")
--- include/linux/property.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
include/linux/property.h +26 -0
@@ -79,12 +79,38 @@ int fwnode_property_match_string(const struct fwnode_handle *fwnode,bool fwnode_device_is_available (const struct fwnode_handle *fwnode); +static inline bool fwnode_device_is_big_endian (const struct fwnode_handle *fwnode) +{ +if (fwnode_property_present (fwnode,"big-endian" )) +return true; +if (IS_ENABLED (CONFIG_CPU_BIG_ENDIAN ) && +fwnode_property_present (fwnode,"native-endian" )) +return true; +return false; +} +static inline bool fwnode_device_is_compatible (const struct fwnode_handle *fwnode,const char *compat) {return fwnode_property_match_string (fwnode,"compatible" , compat) >=0 ; } +/** +* device_is_big_endian - check if a device has BE registers +* @dev: Pointer to the struct device +* +* Returns: true if the device has a "big-endian" property, or if the kernel +* was compiled for BE *and* the device has a "native-endian" property. +* Returns false otherwise. +* +* Callers would nominally use ioread32be/iowrite32be if +* device_is_big_endian() == true, or readl/writel otherwise. +*/ +static inline bool device_is_big_endian (const struct device *dev) +{ +return fwnode_device_is_big_endian (dev_fwnode (dev)); +} +/** * device_is_compatible - match 'compatible' property of the device with a given string * @dev: Pointer to the struct device
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 258/267 serial: core: Add UPIO_UNKNOWN constant for unknown port type
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
[ Upstream commit 79d713baf63c8f23cc58b304c40be33d64a12aaf ]
In some APIs we would like to assign the special value to iotype and compare against it in another places. Introduce UPIO_UNKNOWN for this purpose.
Note, we can't use 0, because it's a valid value for IO port access.
Stable-dep-of: 87d80bfbd577 ("serial: 8250_dw: Don't use struct dw8250_data outside of 8250_dw")
--- include/linux/serial_core.h | 1 + 1 file changed, 1 insertion(+)
include/linux/serial_core.h +1 -0
@@ -470,6 +470,7 @@ struct uart_port {unsigned char iotype;/* io access style */ unsigned char quirks;/* internal quirks */ +#define UPIO_UNKNOWN ((unsigned char)~0U)/* UCHAR_MAX */ #define UPIO_PORT (SERIAL_IO_PORT)/* 8b I/O port access */ #define UPIO_HUB6 (SERIAL_IO_HUB6)/* Hub6 ISA card */ #define UPIO_MEM (SERIAL_IO_MEM)/* driver-specific */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 259/267 serial: port: Introduce a common helper to read properties
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
[ Upstream commit e894b6005dce0ed621b2788d6a249708fb6f95f9 ]
Several serial drivers want to read the same or similar set of the port properties. Make a common helper for them.
Stable-dep-of: 87d80bfbd577 ("serial: 8250_dw: Don't use struct dw8250_data outside of 8250_dw")
--- drivers/tty/serial/serial_port.c | 145 +++++++++++++++++++++++++++++++ include/linux/serial_core.h | 2 + 2 files changed, 147 insertions(+)
drivers/tty/serial/serial_port.c +145 -0
@@ -8,7 +8,10 @@#include <linux/device.h> #include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <linux/property.h> #include <linux/serial_core.h> #include <linux/spinlock.h>
@@ -146,6 +149,148 @@ void uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) }EXPORT_SYMBOL (uart_remove_one_port); +/** +* __uart_read_properties - read firmware properties of the given UART port +* @port: corresponding port +* @use_defaults: apply defaults (when %true) or validate the values (when %false) +* +* The following device properties are supported: +* - clock-frequency (optional) +* - fifo-size (optional) +* - no-loopback-test (optional) +* - reg-shift (defaults may apply) +* - reg-offset (value may be validated) +* - reg-io-width (defaults may apply or value may be validated) +* - interrupts (OF only) +* - serial [alias ID] (OF only) +* +* If the port->dev is of struct platform_device type the interrupt line +* will be retrieved via platform_get_irq() call against that device. +* Otherwise it will be assigned by fwnode_irq_get() call. In both cases +* the index 0 of the resource is used. +* +* The caller is responsible to initialize the following fields of the @port +* ->dev (must be valid) +* ->flags +* ->mapbase +* ->mapsize +* ->regshift (if @use_defaults is false) +* before calling this function. Alternatively the above mentioned fields +* may be zeroed, in such case the only ones, that have associated properties +* found, will be set to the respective values. +* +* If no error happened, the ->irq, ->mapbase, ->mapsize will be altered. +* The ->iotype is always altered. +* +* When @use_defaults is true and the respective property is not found +* the following values will be applied: +* ->regshift = 0 +* In this case IRQ must be provided, otherwise an error will be returned. +* +* When @use_defaults is false and the respective property is found +* the following values will be validated: +* - reg-io-width (->iotype) +* - reg-offset (->mapsize against ->mapbase) +* +* Returns: 0 on success or negative errno on failure +*/ +static int __uart_read_properties (struct uart_port *port,bool use_defaults) +{ +struct device *dev = port->dev; +u32 value; +int ret; + +/* Read optional UART functional clock frequency */ +device_property_read_u32 (dev,"clock-frequency" , &port->uartclk); + +/* Read the registers alignment (default: 8-bit) */ + ret =device_property_read_u32 (dev,"reg-shift" , &value); +if (ret) + port->regshift = use_defaults ?0 : port->regshift; +else + port->regshift = value; + +/* Read the registers I/O access type (default: MMIO 8-bit) */ + ret =device_property_read_u32 (dev,"reg-io-width" , &value); +if (ret) { + port->iotype =UPIO_MEM ; + }else { +switch (value) { +case 1 : + port->iotype =UPIO_MEM ; +break ; +case 2 : + port->iotype =UPIO_MEM16 ; +break ; +case 4 : + port->iotype =device_is_big_endian (dev) ?UPIO_MEM32BE :UPIO_MEM32 ; +break ; +default : +if (!use_defaults) { +dev_err (dev,"Unsupported reg-io-width (%u)\n" , value); +return -EINVAL ; + } + port->iotype =UPIO_UNKNOWN ; +break ; + } + } + +/* Read the address mapping base offset (default: no offset) */ + ret =device_property_read_u32 (dev,"reg-offset" , &value); +if (ret) + value =0 ; + +/* Check for shifted address mapping overflow */ +if (!use_defaults && port->mapsize < value) { +dev_err (dev,"reg-offset %u exceeds region size %pa\n" , value, &port->mapsize); +return -EINVAL ; + } + + port->mapbase += value; + port->mapsize -= value; + +/* Read optional FIFO size */ +device_property_read_u32 (dev,"fifo-size" , &port->fifosize); + +if (device_property_read_bool (dev,"no-loopback-test" )) + port->flags |=UPF_SKIP_TEST ; + +/* Get index of serial line, if found in DT aliases */ + ret =of_alias_get_id (dev_of_node (dev),"serial" ); +if (ret >=0 ) + port->line = ret; + +if (dev_is_platform (dev)) + ret =platform_get_irq (to_platform_device (dev),0 ); +else + ret =fwnode_irq_get (dev_fwnode (dev),0 ); +if (ret == -EPROBE_DEFER ) +return ret; +if (ret >0 ) + port->irq = ret; +else if (use_defaults) +/* By default IRQ support is mandatory */ +return ret; +else + port->irq =0 ; + + port->flags |=UPF_SHARE_IRQ ; + +return 0 ; +} + +int uart_read_port_properties (struct uart_port *port) +{ +return __uart_read_properties (port, true); +} +EXPORT_SYMBOL_GPL (uart_read_port_properties); + +int uart_read_and_validate_port_properties (struct uart_port *port) +{ +return __uart_read_properties (port, false); +} +EXPORT_SYMBOL_GPL (uart_read_and_validate_port_properties); +static struct device_driver serial_port_driver = { .name ="port" , .suppress_bind_attrs = true,
include/linux/serial_core.h +2 -0
@@ -961,6 +961,8 @@ int uart_register_driver(struct uart_driver *uart);void uart_unregister_driver (struct uart_driver *uart);int uart_add_one_port (struct uart_driver *reg,struct uart_port *port);void uart_remove_one_port (struct uart_driver *reg,struct uart_port *port); +int uart_read_port_properties (struct uart_port *port); +int uart_read_and_validate_port_properties (struct uart_port *port);bool uart_match_port (const struct uart_port *port1,const struct uart_port *port2);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 260/267 serial: 8250_dw: Switch to use uart_read_port_properties()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
[ Upstream commit e6a46d073e11baba785245860c9f51adbbb8b68d ]
Since we have now a common helper to read port properties use it instead of sparse home grown solution.
Stable-dep-of: 87d80bfbd577 ("serial: 8250_dw: Don't use struct dw8250_data outside of 8250_dw")
--- drivers/tty/serial/8250/8250_dw.c | 67 +++++++++++++------------------ 1 file changed, 27 insertions(+), 40 deletions(-)
drivers/tty/serial/8250/8250_dw.c +27 -40
@@ -17,7 +17,6 @@#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/notifier.h> -#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/property.h>
@@ -449,12 +448,7 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)if (np) {unsigned int quirks = data->pdata->quirks; -int id; -/* get index of serial line, if found in DT aliases */ - id =of_alias_get_id (np,"serial" ); -if (id >=0 ) - p->line = id;#ifdef CONFIG_64BIT if (quirks &DW_UART_QUIRK_OCTEON ) { p->serial_in = dw8250_serial_inq;
@@ -465,12 +459,6 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) }#endif -if (of_device_is_big_endian (np)) { - p->iotype =UPIO_MEM32BE ; - p->serial_in = dw8250_serial_in32be; - p->serial_out = dw8250_serial_out32be; - } -if (quirks &DW_UART_QUIRK_ARMADA_38X ) p->serial_out = dw8250_serial_out38x;if (quirks &DW_UART_QUIRK_SKIP_SET_RATE )
@@ -515,39 +503,21 @@ static int dw8250_probe(struct platform_device *pdev)struct device *dev = &pdev->dev;struct dw8250_data *data;struct resource *regs; -int irq;int err; -u32 val; regs =platform_get_resource (pdev,IORESOURCE_MEM ,0 );if (!regs)return dev_err_probe (dev, -EINVAL ,"no registers defined\n" ); - irq =platform_get_irq_optional (pdev,0 ); -/* no interrupt -> fall back to polling */ -if (irq == -ENXIO ) - irq =0 ; -if (irq <0 ) -return irq; -spin_lock_init (&p->lock); - p->mapbase = regs->start; - p->irq = irq; p->handle_irq = dw8250_handle_irq; p->pm = dw8250_do_pm; p->type =PORT_8250 ; - p->flags =UPF_SHARE_IRQ |UPF_FIXED_PORT ; + p->flags =UPF_FIXED_PORT ; p->dev = dev; - p->iotype =UPIO_MEM ; - p->serial_in = dw8250_serial_in; - p->serial_out = dw8250_serial_out; p->set_ldisc = dw8250_set_ldisc; p->set_termios = dw8250_set_termios; - p->membase =devm_ioremap (dev, regs->start,resource_size (regs)); -if (!p->membase) -return -ENOMEM ; - data =devm_kzalloc (dev,sizeof (*data),GFP_KERNEL );if (!data)return -ENOMEM ;
@@ -559,15 +529,35 @@ static int dw8250_probe(struct platform_device *pdev) data->uart_16550_compatible =device_property_read_bool (dev,"snps,uart-16550-compatible" ); - err =device_property_read_u32 (dev,"reg-shift" , &val); -if (!err) - p->regshift = val; + p->mapbase = regs->start; + p->mapsize =resource_size (regs); - err =device_property_read_u32 (dev,"reg-io-width" , &val); -if (!err && val ==4 ) { - p->iotype =UPIO_MEM32 ; + p->membase =devm_ioremap (dev, p->mapbase, p->mapsize); +if (!p->membase) +return -ENOMEM ; + + err =uart_read_port_properties (p); +/* no interrupt -> fall back to polling */ +if (err == -ENXIO ) + err =0 ; +if (err) +return err; + +switch (p->iotype) { +case UPIO_MEM : + p->serial_in = dw8250_serial_in; + p->serial_out = dw8250_serial_out; +break ; +case UPIO_MEM32 : p->serial_in = dw8250_serial_in32; p->serial_out = dw8250_serial_out32; +break ; +case UPIO_MEM32BE : + p->serial_in = dw8250_serial_in32be; + p->serial_out = dw8250_serial_out32be; +break ; +default : +return -ENODEV ; }if (device_property_read_bool (dev,"dcd-override" )) {
@@ -594,9 +584,6 @@ static int dw8250_probe(struct platform_device *pdev) data->msr_mask_off |=UART_MSR_TERI ; } -/* Always ask for fixed clock rate from a property. */ -device_property_read_u32 (dev,"clock-frequency" , &p->uartclk); -/* If there is separate baudclk, get the rate from it. */ data->clk =devm_clk_get_optional (dev,"baudclk" );if (data->clk ==NULL )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 261/267 serial: 8250_dw: Replace ACPI device check by a quirk
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
[ Upstream commit 173b097dcc8d74d6e135aed1bad38dbfa21c4d04 ]
Instead of checking for APMC0D08 ACPI device presence, use a quirk based on driver data.
Stable-dep-of: 87d80bfbd577 ("serial: 8250_dw: Don't use struct dw8250_data outside of 8250_dw")
--- drivers/tty/serial/8250/8250_dw.c | 51 ++++++++++++++++--------------- 1 file changed, 26 insertions(+), 25 deletions(-)
drivers/tty/serial/8250/8250_dw.c +26 -25
@@ -9,7 +9,6 @@* LCR is written whilst busy. If it is, then a busy detect interrupt is * raised, the LCR needs to be rewritten and the uart status register read. */ -#include <linux/acpi.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/device.h>
@@ -55,6 +54,7 @@#define DW_UART_QUIRK_ARMADA_38X BIT(1)#define DW_UART_QUIRK_SKIP_SET_RATE BIT(2)#define DW_UART_QUIRK_IS_DMA_FC BIT(3) +#define DW_UART_QUIRK_APMC0D08 BIT(4)static inline struct dw8250_data *clk_to_dw8250_data (struct notifier_block *nb) {
@@ -444,33 +444,29 @@ static void dw8250_prepare_rx_dma(struct uart_8250_port *p)static void dw8250_quirks (struct uart_port *p,struct dw8250_data *data) { -struct device_node *np = p->dev->of_node; - -if (np) { -unsigned int quirks = data->pdata->quirks; +unsigned int quirks = data->pdata ? data->pdata->quirks :0 ;#ifdef CONFIG_64BIT -if (quirks &DW_UART_QUIRK_OCTEON ) { - p->serial_in = dw8250_serial_inq; - p->serial_out = dw8250_serial_outq; - p->flags =UPF_SKIP_TEST |UPF_SHARE_IRQ |UPF_FIXED_TYPE ; - p->type =PORT_OCTEON ; - data->skip_autocfg = true; - } +if (quirks &DW_UART_QUIRK_OCTEON ) { + p->serial_in = dw8250_serial_inq; + p->serial_out = dw8250_serial_outq; + p->flags =UPF_SKIP_TEST |UPF_SHARE_IRQ |UPF_FIXED_TYPE ; + p->type =PORT_OCTEON ; + data->skip_autocfg = true; + }#endif -if (quirks &DW_UART_QUIRK_ARMADA_38X ) - p->serial_out = dw8250_serial_out38x; -if (quirks &DW_UART_QUIRK_SKIP_SET_RATE ) - p->set_termios = dw8250_do_set_termios; -if (quirks &DW_UART_QUIRK_IS_DMA_FC ) { - data->data.dma.txconf.device_fc =1 ; - data->data.dma.rxconf.device_fc =1 ; - data->data.dma.prepare_tx_dma = dw8250_prepare_tx_dma; - data->data.dma.prepare_rx_dma = dw8250_prepare_rx_dma; - } - - }else if (acpi_dev_present ("APMC0D08" ,NULL ,-1 )) { +if (quirks &DW_UART_QUIRK_ARMADA_38X ) + p->serial_out = dw8250_serial_out38x; +if (quirks &DW_UART_QUIRK_SKIP_SET_RATE ) + p->set_termios = dw8250_do_set_termios; +if (quirks &DW_UART_QUIRK_IS_DMA_FC ) { + data->data.dma.txconf.device_fc =1 ; + data->data.dma.rxconf.device_fc =1 ; + data->data.dma.prepare_tx_dma = dw8250_prepare_tx_dma; + data->data.dma.prepare_rx_dma = dw8250_prepare_rx_dma; + } +if (quirks &DW_UART_QUIRK_APMC0D08 ) { p->iotype =UPIO_MEM32 ; p->regshift =2 ; p->serial_in = dw8250_serial_in32;
@@ -772,13 +768,18 @@ static const struct of_device_id dw8250_of_match[] = { };MODULE_DEVICE_TABLE (of, dw8250_of_match); +static const struct dw8250_platform_data dw8250_apmc0d08 = { + .usr_reg =DW_UART_USR , + .quirks =DW_UART_QUIRK_APMC0D08 , +}; +static const struct acpi_device_id dw8250_acpi_match[] = { {"80860F0A" , (kernel_ulong_t)&dw8250_dw_apb }, {"8086228A" , (kernel_ulong_t)&dw8250_dw_apb }, {"AMD0020" , (kernel_ulong_t)&dw8250_dw_apb }, {"AMDI0020" , (kernel_ulong_t)&dw8250_dw_apb }, {"AMDI0022" , (kernel_ulong_t)&dw8250_dw_apb }, - {"APMC0D08" , (kernel_ulong_t)&dw8250_dw_apb}, + {"APMC0D08" , (kernel_ulong_t)&dw8250_apmc0d08 }, {"BRCM2032" , (kernel_ulong_t)&dw8250_dw_apb }, {"HISI0031" , (kernel_ulong_t)&dw8250_dw_apb }, {"INT33C4" , (kernel_ulong_t)&dw8250_dw_apb },
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 262/267 serial: 8250_dw: Dont use struct dw8250_data outside of 8250_dw
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
[ Upstream commit 87d80bfbd577912462061b1a45c0ed9c7fcb872f ]
The container of the struct dw8250_port_data is private to the actual driver. In particular, 8250_lpss and 8250_dw use different data types that are assigned to the UART port private_data. Hence, it must not be used outside the specific driver.
Currently the only cpr_val is required by the common code, make it be available via struct dw8250_port_data.
This fixes the UART breakage on Intel Galileo boards.
--- drivers/tty/serial/8250/8250_dw.c | 9 +++++++-- drivers/tty/serial/8250/8250_dwlib.c | 3 +-- drivers/tty/serial/8250/8250_dwlib.h | 3 ++- 3 files changed, 10 insertions(+), 5 deletions(-)
drivers/tty/serial/8250/8250_dw.c +7 -2
@@ -55,6 +55,7 @@#define DW_UART_QUIRK_SKIP_SET_RATE BIT(2)#define DW_UART_QUIRK_IS_DMA_FC BIT(3)#define DW_UART_QUIRK_APMC0D08 BIT(4) +#define DW_UART_QUIRK_CPR_VALUE BIT(5)static inline struct dw8250_data *clk_to_dw8250_data (struct notifier_block *nb) {
@@ -445,6 +446,10 @@ static void dw8250_prepare_rx_dma(struct uart_8250_port *p)static void dw8250_quirks (struct uart_port *p,struct dw8250_data *data) {unsigned int quirks = data->pdata ? data->pdata->quirks :0 ; +u32 cpr_value = data->pdata ? data->pdata->cpr_value :0 ; + +if (quirks &DW_UART_QUIRK_CPR_VALUE ) + data->data.cpr_value = cpr_value;#ifdef CONFIG_64BIT if (quirks &DW_UART_QUIRK_OCTEON ) {
@@ -749,8 +754,8 @@ static const struct dw8250_platform_data dw8250_armada_38x_data = {static const struct dw8250_platform_data dw8250_renesas_rzn1_data = { .usr_reg =DW_UART_USR , - .cpr_val =0x00012f32 , - .quirks =DW_UART_QUIRK_IS_DMA_FC , + .cpr_value =0x00012f32 , + .quirks =DW_UART_QUIRK_CPR_VALUE |DW_UART_QUIRK_IS_DMA_FC , };static const struct dw8250_platform_data dw8250_starfive_jh7100_data = {
drivers/tty/serial/8250/8250_dwlib.c +1 -2
@@ -242,7 +242,6 @@ static const struct serial_rs485 dw8250_rs485_supported = {void dw8250_setup_port (struct uart_port *p) {struct dw8250_port_data *pd = p->private_data; -struct dw8250_data *data =to_dw8250_data (pd);struct uart_8250_port *up =up_to_u8250p (p);u32 reg, old_dlf;
@@ -284,7 +283,7 @@ void dw8250_setup_port(struct uart_port *p) reg =dw8250_readl_ext (p,DW_UART_CPR );if (!reg) { - reg = data->pdata->cpr_val; + reg = pd->cpr_value;dev_dbg (p->dev,"CPR is not available, using 0x%08x instead\n" , reg); }if (!reg)
drivers/tty/serial/8250/8250_dwlib.h +2 -1
@@ -19,6 +19,7 @@ struct dw8250_port_data {struct uart_8250_dma dma;/* Hardware configuration */ +u32 cpr_value;u8 dlf_size;/* RS485 variables */
@@ -27,7 +28,7 @@ struct dw8250_port_data {struct dw8250_platform_data {u8 usr_reg; -u32 cpr_val; +u32 cpr_value;unsigned int quirks; };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 263/267 usb-storage: alauda: Check whether the media is initialized
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shichao Lai <[email protected]>
[ Upstream commit 16637fea001ab3c8df528a8995b3211906165a30 ]
The member "uzonesize" of struct alauda_info will remain 0 if alauda_init_media() fails, potentially causing divide errors in alauda_read_data() and alauda_write_lba().
- Add a member "media_initialized" to struct alauda_info.
- Change a condition in alauda_check_media() to ensure the first initialization.
- Add an error check for the return value of alauda_init_media().
--- drivers/usb/storage/alauda.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/usb/storage/alauda.c +6 -3
@@ -105,6 +105,8 @@ struct alauda_info {unsigned char sense_key;unsigned long sense_asc;/* additional sense code */ unsigned long sense_ascq;/* additional sense code qualifier */ + +bool media_initialized; };#define short_pack (lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
@@ -476,11 +478,12 @@ static int alauda_check_media(struct us_data *us) }/* Check for media change */ -if (status[0 ] &0x08 ) { +if (status[0 ] &0x08 || !info->media_initialized) {usb_stor_dbg (us,"Media change detected\n" );alauda_free_maps (&MEDIA_INFO (us)); -alauda_init_media (us); - + rc =alauda_init_media (us); +if (rc ==USB_STOR_TRANSPORT_GOOD ) + info->media_initialized = true; info->sense_key =UNIT_ATTENTION ; info->sense_asc =0x28 ; info->sense_ascq =0x00 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 264/267 misc: microchip: pci1xxxx: Fix a memory leak in the error handling of gp_aux_bus_probe()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yongzhi Liu <[email protected]>
[ Upstream commit 77427e3d5c353e3dd98c7c0af322f8d9e3131ace ]
There is a memory leak (forget to free allocated buffers) in a memory allocation failure path.
Fix it to jump to the correct error handling code.
--- drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c +4 -2
@@ -69,8 +69,10 @@ static int gp_aux_bus_probe(struct pci_dev *pdev, const struct pci_device_id *id aux_bus->aux_device_wrapper[1 ] =kzalloc (sizeof (*aux_bus->aux_device_wrapper[1 ]),GFP_KERNEL ); -if (!aux_bus->aux_device_wrapper[1 ]) -return -ENOMEM ; +if (!aux_bus->aux_device_wrapper[1 ]) { + retval = -ENOMEM ; + goto err_aux_dev_add_0; + } retval =ida_alloc (&gp_client_ida,GFP_KERNEL );if (retval <0 )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 265/267 i2c: at91: Fix the functionality flags of the slave-only interface
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jean Delvare <[email protected]>
[ Upstream commit d6d5645e5fc1233a7ba950de4a72981c394a2557 ]
When an I2C adapter acts only as a slave, it should not claim to support I2C master capabilities.
--- drivers/i2c/busses/i2c-at91-slave.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/i2c/busses/i2c-at91-slave.c +1 -2
@@ -106,8 +106,7 @@ static int at91_unreg_slave(struct i2c_client *slave)static u32 at91_twi_func (struct i2c_adapter *adapter) { -return I2C_FUNC_SLAVE |I2C_FUNC_I2C |I2C_FUNC_SMBUS_EMUL - |I2C_FUNC_SMBUS_READ_BLOCK_DATA ; +return I2C_FUNC_SLAVE ; }static const struct i2c_algorithm at91_twi_algorithm_slave = {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 266/267 i2c: designware: Fix the functionality flags of the slave-only interface
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jean Delvare <[email protected]>
[ Upstream commit cbf3fb5b29e99e3689d63a88c3cddbffa1b8de99 ]
When an I2C adapter acts only as a slave, it should not claim to support I2C master capabilities.
--- drivers/i2c/busses/i2c-designware-slave.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/i2c/busses/i2c-designware-slave.c +1 -1
@@ -220,7 +220,7 @@ static const struct i2c_algorithm i2c_dw_algo = {void i2c_dw_configure_slave (struct dw_i2c_dev *dev) { - dev->functionality =I2C_FUNC_SLAVE |DW_IC_DEFAULT_FUNCTIONALITY ; + dev->functionality =I2C_FUNC_SLAVE ; dev->slave_cfg =DW_IC_CON_RX_FIFO_FULL_HLD_CTRL |DW_IC_CON_RESTART_EN |DW_IC_CON_STOP_DET_IFADDRESSED ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 267/267 zap_pid_ns_processes: clear TIF_NOTIFY_SIGNAL along with TIF_SIGPENDING
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oleg Nesterov <[email protected]>
[ Upstream commit 7fea700e04bd3f424c2d836e98425782f97b494e ]
kernel_wait4() doesn't sleep and returns -EINTR if there is no eligible child and signal_pending() is true.
That is why zap_pid_ns_processes() clears TIF_SIGPENDING but this is not enough, it should also clear TIF_NOTIFY_SIGNAL to make signal_pending() return false and avoid a busy-wait loop.
--- kernel/pid_namespace.c | 1 + 1 file changed, 1 insertion(+)
kernel/pid_namespace.c +1 -0
@@ -217,6 +217,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)*/ do {clear_thread_flag (TIF_SIGPENDING ); +clear_thread_flag (TIF_NOTIFY_SIGNAL ); rc =kernel_wait4 (-1 ,NULL , __WALL,NULL ); }while (rc != -ECHILD );
Signature · 1 line
2.43.0
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.6.35 release. There are 267 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 21 Jun 2024 12:55:11 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.6.35-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.6.y
and the diffstat can be found below.thanks,
greg k-h
On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels, build tested on BMIPS_GENERIC:
--
Florian