5.10.4-rc1 review
Subsystems (8)
Greg Kroah-Hartman
maintainerPATCH 626/717 ubifs: wbuf: Dont leak kernel memory to flash
In reply to Greg Kroah-HartmanFrom: Richard Weinberger <[email protected]>
commit 20f1431160c6b590cdc269a846fc5a448abf5b98 upstream.
Write buffers use a kmalloc()'ed buffer, they can leak up to seven bytes of kernel memory to flash if writes are not aligned.
So use ubifs_pad() to fill these gaps with padding bytes. This was never a problem while scanning because the scanner logic manually aligns node lengths and skips over these gaps.
--- fs/ubifs/io.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
fs/ubifs/io.c +11 -2
@@ -319,7 +319,7 @@ void ubifs_pad(const struct ubifs_info * {uint32_t crc; -ubifs_assert (c, pad >=0 && !(pad &7 )); +ubifs_assert (c, pad >=0 );if (pad >=UBIFS_PAD_NODE_SZ ) {struct ubifs_ch *ch = buf;
@@ -764,6 +764,10 @@ int ubifs_wbuf_write_nolock(struct ubifs* write-buffer. */ memcpy (wbuf->buf + wbuf->used, buf, len); +if (aligned_len > len) { +ubifs_assert (c, aligned_len - len <8 ); +ubifs_pad (c, wbuf->buf + wbuf->used + len, aligned_len - len); + }if (aligned_len == wbuf->avail) { dbg_io("flush jhead %s wbuf to LEB %d:%d",
@@ -856,13 +860,18 @@ int ubifs_wbuf_write_nolock(struct ubifs }spin_lock (&wbuf->lock); -if (aligned_len) +if (aligned_len) {/* * And now we have what's left and what does not take whole * max. write unit, so write it to the write-buffer and we are * done. */ memcpy (wbuf->buf, buf + written, len); +if (aligned_len > len) { +ubifs_assert (c, aligned_len - len <8 ); +ubifs_pad (c, wbuf->buf + len, aligned_len - len); + } + }if (c->leb_size - wbuf->offs >= c->max_write_size) wbuf->size = c->max_write_size;
Greg Kroah-Hartman
maintainerPATCH 627/717 jffs2: Fix GC exit abnormally
In reply to Greg Kroah-HartmanFrom: Zhe Li <[email protected]>
commit 9afc9a8a4909fece0e911e72b1060614ba2f7969 upstream.
The log of this problem is:
jffs2: Error garbage collecting node at 0x***!
jffs2: No space for garbage collection. Aborting GC thread
This is because GC believe that it do nothing, so it abort.
After going over the image of jffs2, I find a scene that can trigger this problem stably.
The scene is: there is a normal dirent node at summary-area, but abnormal at corresponding not-summary-area with error name_crc.
The reason that GC exit abnormally is because it find that abnormal dirent node to GC, but when it goes to function jffs2_add_fd_to_list, it cannot meet the condition listed below:
if ((*prev)->nhash == new->nhash && !strcmp((*prev)->name, new->name))
So no node is marked obsolete, statistical information of erase_block do not change, which cause GC exit abnormally.
The root cause of this problem is: we do not check the name_crc of the abnormal dirent node with summary is enabled.
Noticed that in function jffs2_scan_dirent_node, we use function jffs2_scan_dirty_space to deal with the dirent node with error name_crc. So this patch add a checking code in function read_direntry to ensure the correctness of dirent node. If checked failed, the dirent node will be marked obsolete so GC will pass this node and this problem will be fixed.
--- fs/jffs2/readinode.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
fs/jffs2/readinode.c +16 -0
@@ -672,6 +672,22 @@ static inline int read_direntry(struct jjffs2_free_full_dirent (fd);return -EIO ; } + +#ifdef CONFIG_JFFS2_SUMMARY +/* +* we use CONFIG_JFFS2_SUMMARY because without it, we +* have checked it while mounting +*/ + crc =crc32 (0 , fd->name, rd->nsize); +if (unlikely (crc !=je32_to_cpu (rd->name_crc))) { +JFFS2_NOTICE ("name CRC failed on dirent node at" +"%#08x: read %#08x,calculated %#08x\n" , +ref_offset (ref),je32_to_cpu (rd->node_crc), crc); +jffs2_mark_node_obsolete (c, ref); +jffs2_free_full_dirent (fd); +return 0 ; + } +#endif } fd->nhash =full_name_hash (NULL , fd->name, rd->nsize);
Greg Kroah-Hartman
maintainerPATCH 628/717 jffs2: Fix ignoring mounting options problem during remounting
In reply to Greg Kroah-HartmanFrom: lizhe <[email protected]>
commit 08cd274f9b8283a1da93e2ccab216a336da83525 upstream.
The jffs2 mount options will be ignored when remounting jffs2. It can be easily reproduced with the steps listed below.
1. mount -t jffs2 -o compr=none /dev/mtdblockx /mnt
2. mount -o remount compr=zlib /mnt
Since ec10a24f10c8, the option parsing happens before fill_super and then pass fc, which contains the options parsing results, to function jffs2_reconfigure during remounting. But function jffs2_reconfigure do not update c->mount_opts.
This patch add a function jffs2_update_mount_opts to fix this problem.
By the way, I notice that tmpfs use the same way to update remounting options. If it is necessary to unify them?
--- fs/jffs2/super.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
fs/jffs2/super.c +17 -0
@@ -215,11 +215,28 @@ static int jffs2_parse_param(struct fs_creturn 0 ; } +static inline void jffs2_update_mount_opts (struct fs_context *fc) +{ +struct jffs2_sb_info *new_c = fc->s_fs_info; +struct jffs2_sb_info *c =JFFS2_SB_INFO (fc->root->d_sb); + +mutex_lock (&c->alloc_sem); +if (new_c->mount_opts.override_compr) { + c->mount_opts.override_compr = new_c->mount_opts.override_compr; + c->mount_opts.compr = new_c->mount_opts.compr; + } +if (new_c->mount_opts.rp_size) + c->mount_opts.rp_size = new_c->mount_opts.rp_size; +mutex_unlock (&c->alloc_sem); +} +static int jffs2_reconfigure (struct fs_context *fc) {struct super_block *sb = fc->root->d_sb;sync_filesystem (sb); +jffs2_update_mount_opts (fc); +return jffs2_do_remount_fs (sb, fc); }
Greg Kroah-Hartman
maintainerPATCH 629/717 fsnotify: generalize handle_inode_event()
In reply to Greg Kroah-HartmanFrom: Amir Goldstein <[email protected]>
commit 950cc0d2bef078e1f6459900ca4d4b2a2e0e3c37 upstream.
The handle_inode_event() interface was added as (quoting comment):
"a simple variant of handle_event() for groups that only have inode marks and don't have ignore mask".
In other words, all backends except fanotify. The inotify backend also falls under this category, but because it required extra arguments it was left out of the initial pass of backends conversion to the simple interface.
This results in code duplication between the generic helper fsnotify_handle_event() and the inotify_handle_event() callback which also happen to be buggy code.
Generalize the handle_inode_event() arguments and add the check for FS_EXCL_UNLINK flag to the generic helper, so inotify backend could be converted to use the simple interface.
--- fs/nfsd/filecache.c | 2 +- fs/notify/dnotify/dnotify.c | 2 +- fs/notify/fsnotify.c | 31 ++++++++++++++++++++++++------- include/linux/fsnotify_backend.h | 3 ++- kernel/audit_fsnotify.c | 2 +- kernel/audit_tree.c | 2 +- kernel/audit_watch.c | 2 +- 7 files changed, 31 insertions(+), 13 deletions(-)
fs/nfsd/filecache.c +1 -1
@@ -600,7 +600,7 @@ static struct notifier_block nfsd_file_lstatic int nfsd_file_fsnotify_handle_event (struct fsnotify_mark *mark,u32 mask,struct inode *inode,struct inode *dir, -const struct qstr *name) +const struct qstr *name,u32 cookie) {trace_nfsd_file_fsnotify_handle_event (inode, mask);
fs/notify/dnotify/dnotify.c +1 -1
@@ -72,7 +72,7 @@ static void dnotify_recalc_inode_mask(st*/ static int dnotify_handle_event (struct fsnotify_mark *inode_mark,u32 mask,struct inode *inode,struct inode *dir, -const struct qstr *name) +const struct qstr *name,u32 cookie) {struct dnotify_mark *dn_mark;struct dnotify_struct *dn;
fs/notify/fsnotify.c +24 -7
@@ -232,6 +232,26 @@ notify: }EXPORT_SYMBOL_GPL (__fsnotify_parent); +static int fsnotify_handle_inode_event (struct fsnotify_group *group, +struct fsnotify_mark *inode_mark, +u32 mask,const void *data,int data_type, +struct inode *dir,const struct qstr *name, +u32 cookie) +{ +const struct path *path =fsnotify_data_path (data, data_type); +struct inode *inode =fsnotify_data_inode (data, data_type); +const struct fsnotify_ops *ops = group->ops; + +if (WARN_ON_ONCE (!ops->handle_inode_event)) +return 0 ; + +if ((inode_mark->mask &FS_EXCL_UNLINK ) && + path &&d_unlinked (path->dentry)) +return 0 ; + +return ops->handle_inode_event (inode_mark, mask, inode, dir, name, cookie); +} + static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask, const void *data, int data_type, struct inode *dir, const struct qstr *name,
@@ -239,13 +259,8 @@ static int fsnotify_handle_event(struct {struct fsnotify_mark *inode_mark =fsnotify_iter_inode_mark (iter_info);struct fsnotify_mark *child_mark =fsnotify_iter_child_mark (iter_info); -struct inode *inode =fsnotify_data_inode (data, data_type); -const struct fsnotify_ops *ops = group->ops;int ret; -if (WARN_ON_ONCE (!ops->handle_inode_event)) -return 0 ; -if (WARN_ON_ONCE (fsnotify_iter_sb_mark (iter_info)) ||WARN_ON_ONCE (fsnotify_iter_vfsmount_mark (iter_info)))return 0 ;
@@ -262,7 +277,8 @@ static int fsnotify_handle_event(struct name =NULL ; } - ret = ops->handle_inode_event (inode_mark, mask, inode, dir, name); + ret =fsnotify_handle_inode_event (group, inode_mark, mask, data, data_type, + dir, name, cookie);if (ret || !child_mark)return ret;
@@ -272,7 +288,8 @@ static int fsnotify_handle_event(struct* report the event once to parent dir with name and once to child * without name. */ -return ops->handle_inode_event (child_mark, mask, inode,NULL ,NULL ); +return fsnotify_handle_inode_event (group, child_mark, mask, data, data_type, +NULL ,NULL ,0 ); } static int send_to_group(__u32 mask, const void *data, int data_type,
include/linux/fsnotify_backend.h +2 -1
@@ -137,6 +137,7 @@ struct mem_cgroup;* if @file_name is not NULL, this is the directory that * @file_name is relative to. * @file_name: optional file name associated with event +* @cookie: inotify rename cookie * * free_group_priv - called when a group refcnt hits 0 to clean up the private union * freeing_mark - called when a mark is being destroyed for some reason. The group
@@ -151,7 +152,7 @@ struct fsnotify_ops { struct fsnotify_iter_info *iter_info);int (*handle_inode_event)(struct fsnotify_mark *mark,u32 mask,struct inode *inode,struct inode *dir, -const struct qstr *file_name); +const struct qstr *file_name,u32 cookie);void (*free_group_priv)(struct fsnotify_group *group);void (*freeing_mark)(struct fsnotify_mark *mark,struct fsnotify_group *group);void (*free_event)(struct fsnotify_event *event);
kernel/audit_fsnotify.c +1 -1
@@ -154,7 +154,7 @@ static void audit_autoremove_mark_rule(s/* Update mark data in audit rules based on fsnotify events. */ static int audit_mark_handle_event (struct fsnotify_mark *inode_mark,u32 mask,struct inode *inode,struct inode *dir, -const struct qstr *dname) +const struct qstr *dname,u32 cookie) {struct audit_fsnotify_mark *audit_mark;
kernel/audit_tree.c +1 -1
@@ -1037,7 +1037,7 @@ static void evict_chunk(struct audit_chustatic int audit_tree_handle_event (struct fsnotify_mark *mark,u32 mask,struct inode *inode,struct inode *dir, -const struct qstr *file_name) +const struct qstr *file_name,u32 cookie) {return 0 ; }
kernel/audit_watch.c +1 -1
@@ -466,7 +466,7 @@ void audit_remove_watch_rule(struct audi/* Update watch data in audit rules based on fsnotify events. */ static int audit_watch_handle_event (struct fsnotify_mark *inode_mark,u32 mask,struct inode *inode,struct inode *dir, -const struct qstr *dname) +const struct qstr *dname,u32 cookie) {struct audit_parent *parent;
Greg Kroah-Hartman
maintainerPATCH 630/717 inotify: convert to handle_inode_event() interface
In reply to Greg Kroah-HartmanFrom: Amir Goldstein <[email protected]>
commit 1a2620a99803ad660edc5d22fd9c66cce91ceb1c upstream.
Convert inotify to use the simple handle_inode_event() interface to get rid of the code duplication between the generic helper fsnotify_handle_event() and the inotify_handle_event() callback, which also happen to be buggy code.
The bug will be fixed in the generic helper.
--- fs/notify/inotify/inotify.h | 9 ++---- fs/notify/inotify/inotify_fsnotify.c | 51 +++++------------------------------ fs/notify/inotify/inotify_user.c | 8 +---- 3 files changed, 14 insertions(+), 54 deletions(-)
fs/notify/inotify/inotify.h +4 -5
@@ -24,11 +24,10 @@ static inline struct inotify_event_infoextern void inotify_ignored_and_remove_idr (struct fsnotify_mark *fsn_mark,struct fsnotify_group *group); -extern int inotify_handle_event (struct fsnotify_group *group,u32 mask, -const void *data,int data_type, -struct inode *dir, -const struct qstr *file_name,u32 cookie, -struct fsnotify_iter_info *iter_info); +extern int inotify_handle_inode_event (struct fsnotify_mark *inode_mark, +u32 mask,struct inode *inode, +struct inode *dir, +const struct qstr *name,u32 cookie);extern const struct fsnotify_ops inotify_fsnotify_ops;extern struct kmem_cache *inotify_inode_mark_cachep;
fs/notify/inotify/inotify_fsnotify.c +8 -43
84 lines not on this page · raw message
fs/notify/inotify/inotify_user.c +2 -6
@@ -486,14 +486,10 @@ void inotify_ignored_and_remove_idr(stru struct fsnotify_group *group) {struct inotify_inode_mark *i_mark; -struct fsnotify_iter_info iter_info = { }; - -fsnotify_iter_set_report_type_mark (&iter_info,FSNOTIFY_OBJ_TYPE_INODE , - fsn_mark);/* Queue ignore event for the watch */ -inotify_handle_event (group,FS_IN_IGNORED ,NULL ,FSNOTIFY_EVENT_NONE , -NULL ,NULL ,0 , &iter_info); +inotify_handle_inode_event (fsn_mark,FS_IN_IGNORED ,NULL ,NULL ,NULL , +0 ); i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);/* remove this mark from the idr */
Greg Kroah-Hartman
maintainerPATCH 631/717 fsnotify: fix events reported to watching parent and child
In reply to Greg Kroah-HartmanFrom: Amir Goldstein <[email protected]>
commit fecc4559780d52d174ea05e3bf543669165389c3 upstream.
fsnotify_parent() used to send two separate events to backends when a parent inode is watching children and the child inode is also watching. In an attempt to avoid duplicate events in fanotify, we unified the two backend callbacks to a single callback and handled the reporting of the two separate events for the relevant backends (inotify and dnotify). However the handling is buggy and can result in inotify and dnotify listeners receiving events of the type they never asked for or spurious events.
The problem is the unified event callback with two inode marks (parent and child) is called when any of the parent and child inodes are watched and interested in the event, but the parent inode's mark that is interested in the event on the child is not necessarily the one we are currently reporting to (it could belong to a different group).
So before reporting the parent or child event flavor to backend we need to check that the mark is really interested in that event flavor.
The semantics of INODE and CHILD marks were hard to follow and made the logic more complicated than it should have been. Replace it with INODE and PARENT marks semantics to hopefully make the logic more clear.
Thanks to Hugh Dickins for spotting a bug in the earlier version of this patch.
--- fs/notify/fanotify/fanotify.c | 7 +-- fs/notify/fsnotify.c | 84 +++++++++++++++++++++++---------------- include/linux/fsnotify_backend.h | 6 +- 3 files changed, 57 insertions(+), 40 deletions(-)
fs/notify/fanotify/fanotify.c +3 -4
@@ -268,12 +268,11 @@ static u32 fanotify_group_event_mask(strcontinue ;/* -* If the event is for a child and this mark is on a parent not +* If the event is on a child and this mark is on a parent not * watching children, don't send it! */ -if (event_mask &FS_EVENT_ON_CHILD && - type ==FSNOTIFY_OBJ_TYPE_INODE && - !(mark->mask &FS_EVENT_ON_CHILD )) +if (type ==FSNOTIFY_OBJ_TYPE_PARENT && + !(mark->mask &FS_EVENT_ON_CHILD ))continue ; marks_mask |= mark->mask;
fs/notify/fsnotify.c +51 -33
143 lines not on this page · raw message
include/linux/fsnotify_backend.h +3 -3
@@ -278,7 +278,7 @@ static inline const struct path *fsnotifenum fsnotify_obj_type {FSNOTIFY_OBJ_TYPE_INODE , -FSNOTIFY_OBJ_TYPE_CHILD , +FSNOTIFY_OBJ_TYPE_PARENT ,FSNOTIFY_OBJ_TYPE_VFSMOUNT ,FSNOTIFY_OBJ_TYPE_SB ,FSNOTIFY_OBJ_TYPE_COUNT ,
@@ -286,7 +286,7 @@ enum fsnotify_obj_type { };#define FSNOTIFY_OBJ_TYPE_INODE_FL (1U << FSNOTIFY_OBJ_TYPE_INODE) -#define FSNOTIFY_OBJ_TYPE_CHILD_FL (1U << FSNOTIFY_OBJ_TYPE_CHILD) +#define FSNOTIFY_OBJ_TYPE_PARENT_FL (1U << FSNOTIFY_OBJ_TYPE_PARENT)#define FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL (1U << FSNOTIFY_OBJ_TYPE_VFSMOUNT)#define FSNOTIFY_OBJ_TYPE_SB_FL (1U << FSNOTIFY_OBJ_TYPE_SB)#define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1)
@@ -331,7 +331,7 @@ static inline struct fsnotify_mark *fsno } FSNOTIFY_ITER_FUNCS(inode, INODE) -FSNOTIFY_ITER_FUNCS(child, CHILD) +FSNOTIFY_ITER_FUNCS(parent, PARENT) FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT)FSNOTIFY_ITER_FUNCS (sb,SB )
Greg Kroah-Hartman
maintainerPATCH 632/717 jfs: Fix array index bounds check in dbAdjTree
In reply to Greg Kroah-HartmanFrom: Dave Kleikamp <[email protected]>
commit c61b3e4839007668360ed8b87d7da96d2e59fc6c upstream.
Bounds checking tools can flag a bug in dbAdjTree() for an array index out of bounds in dmt_stree. Since dmt_stree can refer to the stree in both structures dmaptree and dmapctl, use the larger array to eliminate the false positive.
--- fs/jfs/jfs_dmap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/jfs/jfs_dmap.h +1 -1
@@ -183,7 +183,7 @@ typedef union dmtree {#define dmt_leafidx t1.leafidx#define dmt_height t1.height#define dmt_budmin t1.budmin -#define dmt_stree t1.stree +#define dmt_stree t2.stree/* * on-disk aggregate disk allocation map descriptor.
Greg Kroah-Hartman
maintainerPATCH 633/717 drm/panfrost: Fix job timeout handling
In reply to Greg Kroah-HartmanFrom: Boris Brezillon <[email protected]>
commit 1a11a88cfd9a97e13be8bc880c4795f9844fbbec upstream.
If more than two jobs end up timeout-ing concurrently, only one of them (the one attached to the scheduler acquiring the lock) is fully handled. The other one remains in a dangling state where it's no longer part of the scheduling queue, but still blocks something in scheduler, leading to repetitive timeouts when new jobs are queued.
Let's make sure all bad jobs are properly handled by the thread acquiring the lock.
v3:
- Add Steven's R-b
- Don't take the sched_lock when stopping the schedulers
v2:
- Fix the subject prefix
- Stop the scheduler before returning from panfrost_job_timedout()
- Call cancel_delayed_work_sync() after drm_sched_stop() to make sure no timeout handlers are in flight when we reset the GPU (Steven Price)
- Make sure we release the reset lock before restarting the schedulers (Steven Price)
--- drivers/gpu/drm/panfrost/panfrost_job.c | 62 +++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 9 deletions(-)
drivers/gpu/drm/panfrost/panfrost_job.c +53 -9
@@ -25,7 +25,8 @@struct panfrost_queue_state {struct drm_gpu_scheduler sched; - +bool stopped; +struct mutex lock;u64 fence_context;u64 emit_seqno; };
@@ -369,6 +370,24 @@ void panfrost_job_enable_interrupts(strujob_write (pfdev,JOB_INT_MASK , irq_mask); } +static bool panfrost_scheduler_stop (struct panfrost_queue_state *queue, +struct drm_sched_job *bad) +{ +bool stopped = false; + +mutex_lock (&queue->lock); +if (!queue->stopped) { +drm_sched_stop (&queue->sched, bad); +if (bad) +drm_sched_increase_karma (bad); + queue->stopped = true; + stopped = true; + } +mutex_unlock (&queue->lock); + +return stopped; +} +static void panfrost_job_timedout (struct drm_sched_job *sched_job) {struct panfrost_job *job =to_panfrost_job (sched_job);
@@ -392,19 +411,39 @@ static void panfrost_job_timedout(structjob_read (pfdev,JS_TAIL_LO (js)), sched_job); +/* Scheduler is already stopped, nothing to do. */ +if (!panfrost_scheduler_stop (&pfdev->js->queue[js], sched_job)) +return ; +if (!mutex_trylock (&pfdev->reset_lock))return ;for (i =0 ; i <NUM_JOB_SLOTS ; i++) {struct drm_gpu_scheduler *sched = &pfdev->js->queue[i].sched; -drm_sched_stop (sched, sched_job); -if (js != i) -/* Ensure any timeouts on other slots have finished */ +/* +* If the queue is still active, make sure we wait for any +* pending timeouts. +*/ +if (!pfdev->js->queue[i].stopped) +cancel_delayed_work_sync (&sched->work_tdr); + +/* +* If the scheduler was not already stopped, there's a tiny +* chance a timeout has expired just before we stopped it, and +* drm_sched_stop() does not flush pending works. Let's flush +* them now so the timeout handler doesn't get called in the +* middle of a reset. +*/ +if (panfrost_scheduler_stop (&pfdev->js->queue[i],NULL ))cancel_delayed_work_sync (&sched->work_tdr); - } -drm_sched_increase_karma (sched_job); +/* +* Now that we cancelled the pending timeouts, we can safely +* reset the stopped state. +*/ + pfdev->js->queue[i].stopped = false; + }spin_lock_irqsave (&pfdev->js->job_lock, flags);for (i =0 ; i <NUM_JOB_SLOTS ; i++) {
@@ -421,11 +460,11 @@ static void panfrost_job_timedout(structfor (i =0 ; i <NUM_JOB_SLOTS ; i++)drm_sched_resubmit_jobs (&pfdev->js->queue[i].sched); +mutex_unlock (&pfdev->reset_lock); +/* restart scheduler after GPU is usable again */ for (i =0 ; i <NUM_JOB_SLOTS ; i++)drm_sched_start (&pfdev->js->queue[i].sched, true); - -mutex_unlock (&pfdev->reset_lock); }static const struct drm_sched_backend_ops panfrost_sched_ops = {
@@ -558,6 +597,7 @@ int panfrost_job_open(struct panfrost_fiint ret, i;for (i =0 ; i <NUM_JOB_SLOTS ; i++) { +mutex_init (&js->queue[i].lock); sched = &js->queue[i].sched; ret = drm_sched_entity_init(&panfrost_priv->sched_entity[i], DRM_SCHED_PRIORITY_NORMAL, &sched,
@@ -570,10 +610,14 @@ int panfrost_job_open(struct panfrost_fivoid panfrost_job_close (struct panfrost_file_priv *panfrost_priv) { +struct panfrost_device *pfdev = panfrost_priv->pfdev; +struct panfrost_job_slot *js = pfdev->js;int i; -for (i =0 ; i <NUM_JOB_SLOTS ; i++) +for (i =0 ; i <NUM_JOB_SLOTS ; i++) {drm_sched_entity_destroy (&panfrost_priv->sched_entity[i]); +mutex_destroy (&js->queue[i].lock); + } }int panfrost_job_is_idle (struct panfrost_device *pfdev)
Greg Kroah-Hartman
maintainerPATCH 634/717 drm/panfrost: Move the GPU reset bits outside the timeout handler
In reply to Greg Kroah-HartmanFrom: Boris Brezillon <[email protected]>
commit 5bc5cc2819c2c0adb644919e3e790b504ea47e0a upstream.
We've fixed many races in panfrost_job_timedout() but some remain. Instead of trying to fix it again, let's simplify the logic and move the reset bits to a separate work scheduled when one of the queue reports a timeout.
v5:
- Simplify panfrost_scheduler_stop() (Steven Price)
- Always restart the queue in panfrost_scheduler_start() even if the status is corrupted (Steven Price)
v4:
- Rework the logic to prevent a race between drm_sched_start() (reset work) and drm_sched_job_timedout() (timeout work)
- Drop Steven's R-b
- Add dma_fence annotation to the panfrost_reset() function (Daniel Vetter)
v3:
- Replace the atomic_cmpxchg() by an atomic_xchg() (Robin Murphy)
- Add Steven's R-b
v2:
- Use atomic_cmpxchg() to conditionally schedule the reset work (Steven Price)
--- drivers/gpu/drm/panfrost/panfrost_device.c | 1 drivers/gpu/drm/panfrost/panfrost_device.h | 6 drivers/gpu/drm/panfrost/panfrost_job.c | 187 +++++++++++++++++++---------- 3 files changed, 130 insertions(+), 64 deletions(-)
drivers/gpu/drm/panfrost/panfrost_device.c +0 -1
@@ -206,7 +206,6 @@ int panfrost_device_init(struct panfroststruct resource *res;mutex_init (&pfdev->sched_lock); -mutex_init (&pfdev->reset_lock);INIT_LIST_HEAD (&pfdev->scheduled_jobs);INIT_LIST_HEAD (&pfdev->as_lru_list);
drivers/gpu/drm/panfrost/panfrost_device.h +5 -1
@@ -105,7 +105,11 @@ struct panfrost_device {struct panfrost_perfcnt *perfcnt;struct mutex sched_lock; -struct mutex reset_lock; + +struct { +struct work_struct work; +atomic_t pending; + } reset;struct mutex shrinker_lock;struct list_head shrinker_list;
drivers/gpu/drm/panfrost/panfrost_job.c +125 -62
252 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 635/717 drm/amd/display: Honor the offset for plane 0.
In reply to Greg Kroah-HartmanFrom: Bas Nieuwenhuizen <[email protected]>
commit be7b9b327e79cd2db07b659af599867b629b2f66 upstream.
With modifiers I'd like to support non-dedicated buffers for images.
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +9 -5
@@ -3746,6 +3746,7 @@ fill_plane_dcc_attributes(struct amdgpu_struct dc *dc = adev->dm.dc;struct dc_dcc_surface_param input;struct dc_surface_dcc_cap output; +uint64_t plane_address = afb->address + afb->base.offsets[0 ];uint32_t offset =AMDGPU_TILING_GET (info,DCC_OFFSET_256B );uint32_t i64b =AMDGPU_TILING_GET (info,DCC_INDEPENDENT_64B ) !=0 ;uint64_t dcc_address;
@@ -3789,7 +3790,7 @@ fill_plane_dcc_attributes(struct amdgpu_AMDGPU_TILING_GET (info,DCC_PITCH_MAX ) +1 ; dcc->independent_64b_blks = i64b; - dcc_address =get_dcc_address (afb->address, info); + dcc_address =get_dcc_address (plane_address, info); address->grph.meta_addr.low_part =lower_32_bits (dcc_address); address->grph.meta_addr.high_part =upper_32_bits (dcc_address);
@@ -3820,6 +3821,8 @@ fill_plane_buffer_attributes(struct amdg address->tmz_surface = tmz_surface;if (format <SURFACE_PIXEL_FORMAT_VIDEO_BEGIN ) { +uint64_t addr = afb->address + fb->offsets[0 ]; + plane_size->surface_size.x =0 ; plane_size->surface_size.y =0 ; plane_size->surface_size.width = fb->width;
@@ -3828,9 +3831,10 @@ fill_plane_buffer_attributes(struct amdg fb->pitches[0 ] / fb->format->cpp[0 ]; address->type =PLN_ADDR_TYPE_GRAPHICS ; - address->grph.addr.low_part =lower_32_bits (afb->address); - address->grph.addr.high_part =upper_32_bits (afb->address); + address->grph.addr.low_part =lower_32_bits (addr); + address->grph.addr.high_part =upper_32_bits (addr); }else if (format <SURFACE_PIXEL_FORMAT_INVALID ) { +uint64_t luma_addr = afb->address + fb->offsets[0 ];uint64_t chroma_addr = afb->address + fb->offsets[1 ]; plane_size->surface_size.x =0 ;
@@ -3851,9 +3855,9 @@ fill_plane_buffer_attributes(struct amdg address->type =PLN_ADDR_TYPE_VIDEO_PROGRESSIVE ; address->video_progressive.luma_addr.low_part = -lower_32_bits (afb->address); +lower_32_bits (luma_addr); address->video_progressive.luma_addr.high_part = -upper_32_bits (afb->address); +upper_32_bits (luma_addr); address->video_progressive.chroma_addr.low_part =lower_32_bits (chroma_addr); address->video_progressive.chroma_addr.high_part =
Re: [PATCH 5.10 635/717] drm/amd/display: Honor the offset for plane 0.
Hi Greg,
Someone bisected a non-booting computer with 5.10.4-rc1 to this commit. Would it be possible to back out of backporting this commit (was backported to 5.4 and 5.10)? I suspect we may need 53f4cb8b5580a20d01449a7d8e1cbfdaed9ff6b6 to be picked too to avoid regressing, but I'm not sure about process (e.g. timeline to confirm things) here and a not booting computer is really bad.
Thanks,
Bas
Quoted 74 lines · Greg Kroah-Hartman
From: Bas Nieuwenhuizen <[email protected]>
commit
be7b9b327e79cd2db07b659af599867b629b2f66upstream.With modifiers I'd like to support non-dedicated buffers for images.
Signed-off-by Bas Nieuwenhuizen <[email protected]>Reviewed-by Alex Deucher <[email protected]>Reviewed-by Nicholas Kazlauskas <[email protected]>Cc [email protected] # 5.1.0Signed-off-by Alex Deucher <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +9
-5@@ -3746,6 +3746,7 @@ fill_plane_dcc_attributes(struct amdgpu_struct dc *dc = adev->dm.dc;struct dc_dcc_surface_param input;struct dc_surface_dcc_cap output; +uint64_t plane_address = afb->address + afb->base.offsets[0 ];uint32_t offset =AMDGPU_TILING_GET (info,DCC_OFFSET_256B );uint32_t i64b =AMDGPU_TILING_GET (info,DCC_INDEPENDENT_64B ) !=0 ;uint64_t dcc_address;@@ -3789,7 +3790,7 @@ fill_plane_dcc_attributes(struct amdgpu_AMDGPU_TILING_GET (info,DCC_PITCH_MAX ) +1 ; dcc->independent_64b_blks = i64b; - dcc_address =get_dcc_address (afb->address, info); + dcc_address =get_dcc_address (plane_address, info); address->grph.meta_addr.low_part =lower_32_bits (dcc_address); address->grph.meta_addr.high_part =upper_32_bits (dcc_address);@@ -3820,6 +3821,8 @@ fill_plane_buffer_attributes(struct amdg address->tmz_surface = tmz_surface;if (format <SURFACE_PIXEL_FORMAT_VIDEO_BEGIN ) { +uint64_t addr = afb->address + fb->offsets[0 ]; + plane_size->surface_size.x =0 ; plane_size->surface_size.y =0 ; plane_size->surface_size.width = fb->width;@@ -3828,9 +3831,10 @@ fill_plane_buffer_attributes(struct amdg fb->pitches[0 ] / fb->format->cpp[0 ]; address->type =PLN_ADDR_TYPE_GRAPHICS ; - address->grph.addr.low_part =lower_32_bits (afb->address); - address->grph.addr.high_part =upper_32_bits (afb->address); + address->grph.addr.low_part =lower_32_bits (addr); + address->grph.addr.high_part =upper_32_bits (addr); }else if (format <SURFACE_PIXEL_FORMAT_INVALID ) { +uint64_t luma_addr = afb->address + fb->offsets[0 ];uint64_t chroma_addr = afb->address + fb->offsets[1 ]; plane_size->surface_size.x =0 ;@@ -3851,9 +3855,9 @@ fill_plane_buffer_attributes(struct amdg address->type =PLN_ADDR_TYPE_VIDEO_PROGRESSIVE ; address->video_progressive.luma_addr.low_part = -lower_32_bits (afb->address); +lower_32_bits (luma_addr); address->video_progressive.luma_addr.high_part = -upper_32_bits (afb->address); +upper_32_bits (luma_addr); address->video_progressive.chroma_addr.low_part =lower_32_bits (chroma_addr); address->video_progressive.chroma_addr.high_part =
Greg Kroah-Hartman
maintainerRe: [PATCH 5.10 635/717] drm/amd/display: Honor the offset for plane 0.
Quoted 8 lines · Bas Nieuwenhuizen
Hi Greg,
Someone bisected a non-booting computer with 5.10.4-rc1 to this commit. Would it be possible to back out of backporting this commit (was backported to 5.4 and 5.10)? I suspect we may need
53f4cb8b5580a20d01449a7d8e1cbfdaed9ff6b6to be picked too to avoid regressing, but I'm not sure about process (e.g. timeline to confirm things) here and a not booting computer is really bad.
Thanks for the report, now dropped from both queues. If this needs to be added, after testing, please let [email protected] know and we will be glad to add it back.
thanks,
greg k-h
Greg Kroah-Hartman
maintainerPATCH 636/717 drm/amdgpu: only set DP subconnector type on DP and eDP connectors
In reply to Greg Kroah-HartmanFrom: Alex Deucher <[email protected]>
commit 05211e7fbbf042dd7f51155ebe64eb2ecacb25cb upstream.
Fixes a crash in drm_object_property_set_value() because the property is not set for internal DP ports that connect to a bridge chips (e.g., DP to VGA or DP to LVDS).
--- drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +6 -4
@@ -1414,10 +1414,12 @@ out:pm_runtime_put_autosuspend (connector->dev->dev); } -drm_dp_set_subconnector_property (&amdgpu_connector->base, - ret, - amdgpu_dig_connector->dpcd, - amdgpu_dig_connector->downstream_ports); +if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort || + connector->connector_type == DRM_MODE_CONNECTOR_eDP) +drm_dp_set_subconnector_property (&amdgpu_connector->base, + ret, + amdgpu_dig_connector->dpcd, + amdgpu_dig_connector->downstream_ports);return ret; }
Greg Kroah-Hartman
maintainerPATCH 637/717 drm/amd/display: Fix memory leaks in S3 resume
In reply to Greg Kroah-HartmanFrom: Stylon Wang <[email protected]>
commit a135a1b4c4db1f3b8cbed9676a40ede39feb3362 upstream.
EDID parsing in S3 resume pushes new display modes
to probed_modes list but doesn't consolidate to actual mode list. This creates a race condition when amdgpu_dm_connector_ddc_get_modes() re-initializes the list head without walking the list and results in memory leak.
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +2 -1
@@ -2278,7 +2278,8 @@ void amdgpu_dm_update_connector_after_dedrm_connector_update_edid_property (connector, aconnector->edid); -drm_add_edid_modes (connector, aconnector->edid); + aconnector->num_modes =drm_add_edid_modes (connector, aconnector->edid); +drm_connector_list_update (connector);if (aconnector->dc_link->aux_mode) drm_dp_cec_set_edid(&aconnector->dm_dp_aux.aux,
Re: [PATCH 5.10 637/717] drm/amd/display: Fix memory leaks in S3 resume
Quoted 9 lines · Greg Kroah-Hartman
From: Stylon Wang <[email protected]>
commit
a135a1b4c4db1f3b8cbed9676a40ede39feb3362upstream.EDID parsing in S3 resume pushes new display modes
toprobed_modeslist but doesn't consolidate to actual mode list. This creates a race condition whenamdgpu_dm_connector_ddc_get_modes()re-initializes the list head without walking the list and results in memory leak.
This commit is causing me problems on 5.10.4: when I turn off the display (a LG TV in this case), and turn it back on again later there is no video output and I get the following in the kernel log:
[ 8245.259628] [drm:dm_restore_drm_connector_state [amdgpu]] *ERROR* Restoring old state failed with -12
I've found another report on this commit as well:
https://bugzilla.kernel.org/show_bug.cgi?id=211033
And I suspect this is the same:
https://bugs.archlinux.org/task/69202
Reverting it from 5.10.4 makes things behave again.
Have not tested 5.4.86 or 5.11-rc.
I'm using a RX570 Polaris based card.
Re: [PATCH 5.10 637/717] drm/amd/display: Fix memory leaks in S3 resume
Quoted 11 lines · Andre Tomt
Quoted 9 lines · Greg Kroah-Hartman
From: Stylon Wang <[email protected]>
commit
a135a1b4c4db1f3b8cbed9676a40ede39feb3362upstream.EDID parsing in S3 resume pushes new display modes
toprobed_modeslist but doesn't consolidate to actual mode list. This creates a race condition whenamdgpu_dm_connector_ddc_get_modes()re-initializes the list head without walking the list and results in memory leak.
Quoted 6 lines
This commit is causing me problems on 5.10.4: when I turn off the display (a LG TV in this case), and turn it back on again later there is no video output and I get the following in the kernel log:
[ 8245.259628] [drm:dm_restore_drm_connector_state [amdgpu]] *ERROR*Restoring old state failed with -12
Uh, it seems you've just saved me a ton of gray hair. I have the very same issue and I'm going to revert this patch now in order to check whether it makes any difference.
Thanks!
Quoted 12 lines
I've found another report on this commit as well:
https://bugzilla.kernel.org/show_bug.cgi?id=211033And I suspect this is the same:
https://bugs.archlinux.org/task/69202Reverting it from 5.10.4 makes things behave again.
Have not tested 5.4.86 or 5.11-rc.
I'm using a RX570 Polaris based card.
Signature · 1 line
Oleksandr Natalenko (post-factum)
Re: [PATCH 5.10 637/717] drm/amd/display: Fix memory leaks in S3 resume
Quoted 16 lines · Oleksandr Natalenko
Quoted 15 lines · Andre Tomt
Quoted 9 lines · Greg Kroah-Hartman
From: Stylon Wang <[email protected]>
commit
a135a1b4c4db1f3b8cbed9676a40ede39feb3362upstream.EDID parsing in S3 resume pushes new display modes
toprobed_modeslist but doesn't consolidate to actual mode list. This creates a race condition whenamdgpu_dm_connector_ddc_get_modes()re-initializes the list head without walking the list and results in memory leak.This commit is causing me problems on 5.10.4: when I turn off the display (a LG TV in this case), and turn it back on again later there is no video output and I get the following in the kernel log:
Quoted 6 lines
Quoted 2 lines
[ 8245.259628] [drm:dm_restore_drm_connector_state [amdgpu]] *ERROR*Restoring old state failed with -12
Uh, it seems you've just saved me a ton of gray hair. I have the very same issue and I'm going to revert this patch now in order to check whether it makes any difference.
Confirmed, reverting this patch makes my monitor light back after turning off/on.
Also, during testing, I've noticed that with the stock v5.10.4 kernel once reboot sequence is initiated and xorg gets killed, the monitor also lights back and shows the console.
My HW:
0a:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Lexa PRO [Radeon 540/540X/550/550X / RX 540X/550/550X] (rev c7)
Quoted 15 lines
Thanks!
Quoted 12 lines
I've found another report on this commit as well:
https://bugzilla.kernel.org/show_bug.cgi?id=211033And I suspect this is the same:
https://bugs.archlinux.org/task/69202Reverting it from 5.10.4 makes things behave again.
Have not tested 5.4.86 or 5.11-rc.
I'm using a RX570 Polaris based card.
Signature · 1 line
Oleksandr Natalenko (post-factum)
Greg Kroah-Hartman
maintainerRe: [PATCH 5.10 637/717] drm/amd/display: Fix memory leaks in S3 resume
In reply to Andre TomtQuoted 21 lines · Andre Tomt
Quoted 9 lines · Greg Kroah-Hartman
From: Stylon Wang <[email protected]>
commit
a135a1b4c4db1f3b8cbed9676a40ede39feb3362upstream.EDID parsing in S3 resume pushes new display modes
toprobed_modeslist but doesn't consolidate to actual mode list. This creates a race condition whenamdgpu_dm_connector_ddc_get_modes()re-initializes the list head without walking the list and results in memory leak.This commit is causing me problems on 5.10.4: when I turn off the display (a LG TV in this case), and turn it back on again later there is no video output and I get the following in the kernel log:
[ 8245.259628] [drm:dm_restore_drm_connector_state [amdgpu]] *ERROR*Restoring old state failed with -12
I've found another report on this commit as well:
https://bugzilla.kernel.org/show_bug.cgi?id=211033
Quoted 8 lines
And I suspect this is the same:
https://bugs.archlinux.org/task/69202Reverting it from 5.10.4 makes things behave again.
Have not tested 5.4.86 or 5.11-rc.
I'm using a RX570 Polaris based card.
Can you test 5.11-rc to see if this issue is there as well?
thanks,
greg k-h
Re: [PATCH 5.10 637/717] drm/amd/display: Fix memory leaks in S3 resume
Quoted 25 lines · Greg Kroah-Hartman
Quoted 24 lines · Andre Tomt
Quoted 9 lines · Greg Kroah-Hartman
From: Stylon Wang <[email protected]>
commit
a135a1b4c4db1f3b8cbed9676a40ede39feb3362upstream.EDID parsing in S3 resume pushes new display modes
toprobed_modeslist but doesn't consolidate to actual mode list. This creates a race condition whenamdgpu_dm_connector_ddc_get_modes()re-initializes the list head without walking the list and results in memory leak.This commit is causing me problems on 5.10.4: when I turn off the display (a LG TV in this case), and turn it back on again later there is no video output and I get the following in the kernel log:
[ 8245.259628] [drm:dm_restore_drm_connector_state [amdgpu]] *ERROR*Restoring old state failed with -12
I've found another report on this commit as well:
https://bugzilla.kernel.org/show_bug.cgi?id=211033And I suspect this is the same:
https://bugs.archlinux.org/task/69202
Quoted 7 lines
Quoted 5 lines
Reverting it from 5.10.4 makes things behave again.
Have not tested 5.4.86 or 5.11-rc.
I'm using a RX570 Polaris based card.
Can you test 5.11-rc to see if this issue is there as well?
Just did, and have the same issue on 5.11-rc2. Reverting it also solves the problem on 5.11-rc2, as it does on 5.10.4
FWIW one easy way to reproduce seems to be unplugging and re-plugging the HDMI.
RE: [PATCH 5.10 637/717] drm/amd/display: Fix memory leaks in S3 resume
[AMD Public Use]
Quoted 79 lines
-----Original Message-----
From: Andre Tomt <[email protected]>
Sent: Tuesday, January 5, 2021 11:32 AM
To: Greg Kroah-Hartman <[email protected]>
Cc: [email protected]; [email protected]; Wentland, Harry <[email protected]>; Deucher, Alexander <[email protected]>; Kazlauskas, Nicholas <[email protected]>; Wang, Chao-kai (Stylon) <[email protected]>
Subject: Re: [PATCH 5.10 637/717] drm/amd/display: Fix memory leaks in S3 resumeQuoted 12 lines · Greg Kroah-Hartman
Quoted 11 lines · Andre Tomt
Quoted 9 lines · Greg Kroah-Hartman
From: Stylon Wang <[email protected]>
commit
a135a1b4c4db1f3b8cbed9676a40ede39feb3362upstream.EDID parsing in S3 resume pushes new display modes to
probed_modeslist but doesn't consolidate to actual mode list. This creates a race condition whenamdgpu_dm_connector_ddc_get_modes()re-initializes the list head without walking the list and results in memory leak.Quoted 5 lines
Quoted 5 lines
This commit is causing me problems on 5.10.4: when I turn off the display (a LG TV in this case), and turn it back on again later there is no video output and I get the following in the kernel log:
[ 8245.259628] [drm:dm_restore_drm_connector_state [amdgpu]]*ERROR*
Quoted 4 lines
Quoted 4 lines
Restoring old state failed with -12
I've found another report on this commit as well:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbug
Quoted 1 line
Quoted 1 line
zilla.kernel.org%2Fshow_bug.cgi%3Fid%3D211033&data=04%7C01%7Cal ex
Quoted 1 line
Quoted 1 line
ander.deucher%40amd.com%7Cad673e351bab4f6af94508d8b1977ed8%7C3d d8961f
Quoted 1 line
Quoted 1 line
e4884e608e11a82d994e183d%7C0%7C0%7C637454612140560971%7CUnknow n%7CTWF
Quoted 1 line
Quoted 1 line
pbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXV CI6
Quoted 1 line
Quoted 1 line
Mn0%3D%7C3000&sdata=8Rsnbfh4P5GmFUlybb31mT7C0Ee4vDInxJ1gt C3jrVI%3
Quoted 4 lines
Quoted 4 lines
D&reserved=0
And I suspect this is the same:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbug
Quoted 1 line
Quoted 1 line
s.archlinux.org%2Ftask%2F69202&data=04%7C01%7Calexander.deuche r%4
Quoted 1 line
Quoted 1 line
0amd.com%7Cad673e351bab4f6af94508d8b1977ed8%7C3dd8961fe4884e608 e11a82
Quoted 1 line
Quoted 1 line
d994e183d%7C0%7C0%7C637454612140560971%7CUnknown%7CTWFpbGZsb 3d8eyJWIj
Quoted 1 line
Quoted 1 line
oiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3 000&a
Quoted 1 line
Quoted 1 line
mp;sdata=1149tCcm3rcaj1MkVPbWqWhWFIPgkeBoYxo0oVv%2FzNI%3D&a mp;reserve
Quoted 8 lines
Quoted 7 lines
d=0
Reverting it from 5.10.4 makes things behave again.
Have not tested 5.4.86 or 5.11-rc.
I'm using a RX570 Polaris based card.
Quoted 7 lines
Quoted 1 line
Can you test 5.11-rc to see if this issue is there as well?
Just did, and have the same issue on 5.11-rc2. Reverting it also solves the problem on 5.11-rc2, as it does on 5.10.4
FWIW one easy way to reproduce seems to be unplugging and re-plugging the HDMI.
We are looking into the root cause, but I'll send out the revert for now.
Thanks,
Alex
Greg Kroah-Hartman
maintainerPATCH 638/717 drm/dp_aux_dev: check aux_dev before use in drm_dp_aux_dev_get_by_minor()
In reply to Greg Kroah-HartmanFrom: Zwane Mwaikambo <[email protected]>
commit 73b62cdb93b68d7e2c1d373c6a411bc00c53e702 upstream.
I observed this when unplugging a DP monitor whilst a computer is asleep and then waking it up. This left DP chardev nodes still being present on the filesystem and accessing these device nodes caused an oops because drm_dp_aux_dev_get_by_minor() assumes a device exists if it is opened. This can also be reproduced by creating a device node with mknod(1) and issuing an open(2)
[166164.933198] BUG: kernel NULL pointer dereference, address: 0000000000000018 [166164.933202] #PF: supervisor read access in kernel mode [166164.933204] #PF: error_code(0x0000) - not-present page [166164.933205] PGD 0 P4D 0 [166164.933208] Oops: 0000 [#1] PREEMPT SMP NOPTI [166164.933211] CPU: 4 PID: 99071 Comm: fwupd Tainted: G W 5.8.0-rc6+ #1 [166164.933213] Hardware name: LENOVO 20RD002VUS/20RD002VUS, BIOS R16ET25W (1.11 ) 04/21/2020 [166164.933232] RIP: 0010:drm_dp_aux_dev_get_by_minor+0x29/0x70 [drm_kms_helper] [166164.933234] Code: 00 0f 1f 44 00 00 55 48 89 e5 41 54 41 89 fc 48 c7 c7 60 01 a4 c0 e8 26 ab 30 d7 44 89 e6 48 c7 c7 80 01 a4 c0 e8 47 94 d6 d6 <8b> 50 18 49 89 c4 48 8d 78 18 85 d2 74 33 8d 4a 01 89 d0 f0 0f b1 [166164.933236] RSP: 0018:ffffb7d7c41cbbf0 EFLAGS: 00010246 [166164.933237] RAX: 0000000000000000 RBX: ffff8a90001fe900 RCX: 0000000000000000 [166164.933238] RDX: 0000000000000000 RSI: 0000000000000003 RDI: ffffffffc0a40180 [166164.933239] RBP: ffffb7d7c41cbbf8 R08: 0000000000000000 R09: ffff8a93e157d6d0 [166164.933240] R10: 0000000000000000 R11: ffffffffc0a40188 R12: 0000000000000003 [166164.933241] R13: ffff8a9402200e80 R14: ffff8a90001fe900 R15: 0000000000000000 [166164.933244] FS: 00007f7fb041eb00(0000) GS:ffff8a9411500000(0000) knlGS:0000000000000000 [166164.933245] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [166164.933246] CR2: 0000000000000018 CR3: 00000000352c2003 CR4: 00000000003606e0 [166164.933247] Call Trace: [166164.933264] auxdev_open+0x1b/0x40 [drm_kms_helper] [166164.933278] chrdev_open+0xa7/0x1c0 [166164.933282] ? cdev_put.part.0+0x20/0x20 [166164.933287] do_dentry_open+0x161/0x3c0 [166164.933291] vfs_open+0x2d/0x30 [166164.933297] path_openat+0xb27/0x10e0 [166164.933306] ? atime_needs_update+0x73/0xd0 [166164.933309] do_filp_open+0x91/0x100 [166164.933313] ? __alloc_fd+0xb2/0x150 [166164.933316] do_sys_openat2+0x210/0x2d0 [166164.933318] do_sys_open+0x46/0x80 [166164.933320] __x64_sys_openat+0x20/0x30 [166164.933328] do_syscall_64+0x52/0xc0 [166164.933336] entry_SYSCALL_64_after_hwframe+0x44/0xa9
(gdb) disassemble drm_dp_aux_dev_get_by_minor+0x29 Dump of assembler code for function drm_dp_aux_dev_get_by_minor:
0x0000000000017b10 <+0>: callq 0x17b15 <drm_dp_aux_dev_get_by_minor+5> 0x0000000000017b15 <+5>: push %rbp 0x0000000000017b16 <+6>: mov %rsp,%rbp 0x0000000000017b19 <+9>: push %r12 0x0000000000017b1b <+11>: mov %edi,%r12d 0x0000000000017b1e <+14>: mov $0x0,%rdi 0x0000000000017b25 <+21>: callq 0x17b2a <drm_dp_aux_dev_get_by_minor+26> 0x0000000000017b2a <+26>: mov %r12d,%esi 0x0000000000017b2d <+29>: mov $0x0,%rdi 0x0000000000017b34 <+36>: callq 0x17b39 <drm_dp_aux_dev_get_by_minor+41> 0x0000000000017b39 <+41>: mov 0x18(%rax),%edx <========= 0x0000000000017b3c <+44>: mov %rax,%r12 0x0000000000017b3f <+47>: lea 0x18(%rax),%rdi 0x0000000000017b43 <+51>: test %edx,%edx 0x0000000000017b45 <+53>: je 0x17b7a <drm_dp_aux_dev_get_by_minor+106> 0x0000000000017b47 <+55>: lea 0x1(%rdx),%ecx 0x0000000000017b4a <+58>: mov %edx,%eax 0x0000000000017b4c <+60>: lock cmpxchg %ecx,(%rdi) 0x0000000000017b50 <+64>: jne 0x17b76 <drm_dp_aux_dev_get_by_minor+102> 0x0000000000017b52 <+66>: test %edx,%edx 0x0000000000017b54 <+68>: js 0x17b6d <drm_dp_aux_dev_get_by_minor+93> 0x0000000000017b56 <+70>: test %ecx,%ecx 0x0000000000017b58 <+72>: js 0x17b6d <drm_dp_aux_dev_get_by_minor+93> 0x0000000000017b5a <+74>: mov $0x0,%rdi 0x0000000000017b61 <+81>: callq 0x17b66 <drm_dp_aux_dev_get_by_minor+86> 0x0000000000017b66 <+86>: mov %r12,%rax 0x0000000000017b69 <+89>: pop %r12 0x0000000000017b6b <+91>: pop %rbp 0x0000000000017b6c <+92>: retq 0x0000000000017b6d <+93>: xor %esi,%esi 0x0000000000017b6f <+95>: callq 0x17b74 <drm_dp_aux_dev_get_by_minor+100> 0x0000000000017b74 <+100>: jmp 0x17b5a <drm_dp_aux_dev_get_by_minor+74> 0x0000000000017b76 <+102>: mov %eax,%edx 0x0000000000017b78 <+104>: jmp 0x17b43 <drm_dp_aux_dev_get_by_minor+51> 0x0000000000017b7a <+106>: xor %r12d,%r12d 0x0000000000017b7d <+109>: jmp 0x17b5a <drm_dp_aux_dev_get_by_minor+74>
End of assembler dump.
(gdb) list *drm_dp_aux_dev_get_by_minor+0x290x17b39 is in drm_dp_aux_dev_get_by_minor (drivers/gpu/drm/drm_dp_aux_dev.c:65).
60 static struct drm_dp_aux_dev *drm_dp_aux_dev_get_by_minor(unsigned index)
61 {
62 struct drm_dp_aux_dev *aux_dev = NULL;
63
64 mutex_lock(&aux_idr_mutex); 65 aux_dev = idr_find(&aux_idr, index); 66 if (!kref_get_unless_zero(&aux_dev->refcount))
67 aux_dev = NULL;
68 mutex_unlock(&aux_idr_mutex);
69
(gdb) p/x &((struct drm_dp_aux_dev *)(0x0))->refcount $8 = 0x18
Looking at the caller, checks on the minor are pushed down to drm_dp_aux_dev_get_by_minor()
static int auxdev_open(struct inode *inode, struct file *file)
{
unsigned int minor = iminor(inode);
struct drm_dp_aux_dev *aux_dev;
aux_dev = drm_dp_aux_dev_get_by_minor(minor); <====
if (!aux_dev)
return -ENODEV;
file->private_data = aux_dev;
return 0;
}--- drivers/gpu/drm/drm_dp_aux_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/drm_dp_aux_dev.c +1 -1
@@ -63,7 +63,7 @@ static struct drm_dp_aux_dev *drm_dp_auxmutex_lock (&aux_idr_mutex); aux_dev =idr_find (&aux_idr, index); -if (!kref_get_unless_zero (&aux_dev->refcount)) +if (aux_dev && !kref_get_unless_zero (&aux_dev->refcount)) aux_dev =NULL ;mutex_unlock (&aux_idr_mutex);
Greg Kroah-Hartman
maintainerPATCH 639/717 drm/i915: Fix mismatch between misplaced vma check and vma insert
In reply to Greg Kroah-HartmanFrom: Chris Wilson <[email protected]>
commit 0e53656ad8abc99e0a80c3de611e593ebbf55829 upstream.
When inserting a VMA, we restrict the placement to the low 4G unless the caller opts into using the full range. This was done to allow usersapce the opportunity to transition slowly from a 32b address space, and to avoid breaking inherent 32b assumptions of some commands.
However, for insert we limited ourselves to 4G-4K, but on verification we allowed the full 4G. This causes some attempts to bind a new buffer to sporadically fail with -ENOSPC, but at other times be bound successfully.
commit 48ea1e32c39d ("drm/i915/gen9: Set PIN_ZONE_4G end to 4GB - 1 page") suggests that there is a genuine problem with stateless addressing that cannot utilize the last page in 4G and so we purposefully excluded it. This means that the quick pin pass may cause us to utilize a buggy placement.
Testcase: igt/gem_exec_params/larger-than-life-batch
--- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +1 -1
@@ -382,7 +382,7 @@ eb_vma_misplaced(const struct drm_i915_greturn true;if (!(flags &EXEC_OBJECT_SUPPORTS_48B_ADDRESS ) && - (vma->node.start + vma->node.size -1 ) >>32 ) + (vma->node.start + vma->node.size +4095 ) >>32 )return true; if (flags & __EXEC_OBJECT_NEEDS_MAP &&
Greg Kroah-Hartman
maintainerPATCH 640/717 iio: ad_sigma_delta: Dont put SPI transfer buffer on the stack
In reply to Greg Kroah-HartmanFrom: Lars-Peter Clausen <[email protected]>
commit 0fb6ee8d0b5e90b72f870f76debc8bd31a742014 upstream.
Use a heap allocated memory for the SPI transfer buffer. Using stack memory can corrupt stack memory when using DMA on some systems.
This change moves the buffer from the stack of the trigger handler call to the heap of the buffer of the state struct. The size increases takes into account the alignment for the timestamp, which is 8 bytes.
The 'data' buffer is split into 'tx_buf' and 'rx_buf', to make a clearer separation of which part of the buffer should be used for TX & RX.
--- drivers/iio/adc/ad_sigma_delta.c | 18 ++++++++---------- include/linux/iio/adc/ad_sigma_delta.h | 6 +++++- 2 files changed, 13 insertions(+), 11 deletions(-)
drivers/iio/adc/ad_sigma_delta.c +8 -10
@@ -57,7 +57,7 @@ EXPORT_SYMBOL_GPL(ad_sd_set_comm);int ad_sd_write_reg (struct ad_sigma_delta *sigma_delta,unsigned int reg,unsigned int size,unsigned int val) { -uint8_t *data = sigma_delta->data; +uint8_t *data = sigma_delta->tx_buf;struct spi_transfer t = { .tx_buf = data, .len = size +1 ,
@@ -99,7 +99,7 @@ EXPORT_SYMBOL_GPL(ad_sd_write_reg);static int ad_sd_read_reg_raw (struct ad_sigma_delta *sigma_delta,unsigned int reg,unsigned int size,uint8_t *val) { -uint8_t *data = sigma_delta->data; +uint8_t *data = sigma_delta->tx_buf;int ret;struct spi_transfer t[] = { {
@@ -146,22 +146,22 @@ int ad_sd_read_reg(struct ad_sigma_delta {int ret; - ret =ad_sd_read_reg_raw (sigma_delta, reg, size, sigma_delta->data); + ret =ad_sd_read_reg_raw (sigma_delta, reg, size, sigma_delta->rx_buf);if (ret <0 ) goto out;switch (size) {case 4 : - *val =get_unaligned_be32 (sigma_delta->data); + *val =get_unaligned_be32 (sigma_delta->rx_buf);break ;case 3 : - *val =get_unaligned_be24 (&sigma_delta->data[0 ]); + *val =get_unaligned_be24 (sigma_delta->rx_buf);break ;case 2 : - *val =get_unaligned_be16 (sigma_delta->data); + *val =get_unaligned_be16 (sigma_delta->rx_buf);break ;case 1 : - *val = sigma_delta->data[0 ]; + *val = sigma_delta->rx_buf[0 ];break ;default : ret = -EINVAL ;
@@ -395,11 +395,9 @@ static irqreturn_t ad_sd_trigger_handlerstruct iio_poll_func *pf = p;struct iio_dev *indio_dev = pf->indio_dev;struct ad_sigma_delta *sigma_delta =iio_device_get_drvdata (indio_dev); +uint8_t *data = sigma_delta->rx_buf;unsigned int reg_size;unsigned int data_reg; -uint8_t data[16 ]; - -memset (data,0x00 ,16 ); reg_size = indio_dev->channels[0 ].scan_type.realbits + indio_dev->channels[0 ].scan_type.shift;
include/linux/iio/adc/ad_sigma_delta.h +5 -1
@@ -79,8 +79,12 @@ struct ad_sigma_delta {/* * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. +* 'tx_buf' is up to 32 bits. +* 'rx_buf' is up to 32 bits per sample + 64 bit timestamp, +* rounded to 16 bytes to take into account padding. */ -uint8_t data[4 ]____cacheline_aligned ; +uint8_t tx_buf[4 ]____cacheline_aligned ; +uint8_t rx_buf[16 ]__aligned(8) ; }; static inline int ad_sigma_delta_set_channel(struct ad_sigma_delta *sd,
Greg Kroah-Hartman
maintainerPATCH 641/717 spi: pxa2xx: Fix use-after-free on unbind
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 5626308bb94d9f930aa5f7c77327df4c6daa7759 upstream.
pxa2xx_spi_remove() accesses the driver's private data after calling spi_unregister_controller() even though that function releases the last reference on the spi_controller and thereby frees the private data.
Fix by switching over to the new devm_spi_alloc_master/slave() helper which keeps the private data accessible until the driver has unbound.
--- drivers/spi/spi-pxa2xx.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/spi/spi-pxa2xx.c +2 -3
@@ -1686,9 +1686,9 @@ static int pxa2xx_spi_probe(struct platf }if (platform_info->is_slave) - controller =spi_alloc_slave (dev,sizeof (struct driver_data )); + controller =devm_spi_alloc_slave (dev,sizeof (*drv_data));else - controller =spi_alloc_master (dev,sizeof (struct driver_data )); + controller =devm_spi_alloc_master (dev,sizeof (*drv_data));if (!controller) {dev_err (&pdev->dev,"cannot alloc spi_controller\n" );
@@ -1911,7 +1911,6 @@ out_error_dma_irq_alloc:free_irq (ssp->irq, drv_data); out_error_controller_alloc: -spi_controller_put (controller);pxa_ssp_free (ssp);return status; }
Greg Kroah-Hartman
maintainerPATCH 642/717 spi: spi-sh: Fix use-after-free on unbind
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit e77df3eca12be4b17f13cf9f215cff248c57d98f upstream.
spi_sh_remove() accesses the driver's private data after calling spi_unregister_master() even though that function releases the last reference on the spi_master and thereby frees the private data.
Fix by switching over to the new devm_spi_alloc_master() helper which keeps the private data accessible until the driver has unbound.
--- drivers/spi/spi-sh.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-)
drivers/spi/spi-sh.c +4 -9
@@ -440,7 +440,7 @@ static int spi_sh_probe(struct platform_if (irq <0 )return irq; - master =spi_alloc_master (&pdev->dev,sizeof (struct spi_sh_data )); + master =devm_spi_alloc_master (&pdev->dev,sizeof (struct spi_sh_data ));if (master ==NULL ) {dev_err (&pdev->dev,"spi_alloc_master error.\n" );return -ENOMEM ;
@@ -458,16 +458,14 @@ static int spi_sh_probe(struct platform_break ;default :dev_err (&pdev->dev,"No support width\n" ); - ret = -ENODEV ; - goto error1; +return -ENODEV ; } ss->irq = irq; ss->master = master; ss->addr =devm_ioremap (&pdev->dev, res->start,resource_size (res));if (ss->addr ==NULL ) {dev_err (&pdev->dev,"ioremap error.\n" ); - ret = -ENOMEM ; - goto error1; +return -ENOMEM ; }INIT_LIST_HEAD (&ss->queue);spin_lock_init (&ss->lock);
@@ -477,7 +475,7 @@ static int spi_sh_probe(struct platform_ ret =request_irq (irq, spi_sh_irq,0 ,"spi_sh" , ss);if (ret <0 ) {dev_err (&pdev->dev,"request_irq error\n" ); - goto error1; +return ret; } master->num_chipselect =2 ;
@@ -496,9 +494,6 @@ static int spi_sh_probe(struct platform_ error3:free_irq (irq, ss); - error1: -spi_master_put (master); -return ret; }
Greg Kroah-Hartman
maintainerPATCH 643/717 spi: atmel-quadspi: Fix use-after-free on unbind
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit c7b884561cb5b641f3dbba950094110794119a6d upstream.
atmel_qspi_remove() accesses the driver's private data after calling spi_unregister_controller() even though that function releases the last reference on the spi_controller and thereby frees the private data.
Fix by switching over to the new devm_spi_alloc_master() helper which keeps the private data accessible until the driver has unbound.
--- drivers/spi/atmel-quadspi.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-)
drivers/spi/atmel-quadspi.c +5 -10
@@ -535,7 +535,7 @@ static int atmel_qspi_probe(struct platfstruct resource *res;int irq, err =0 ; - ctrl =spi_alloc_master (&pdev->dev,sizeof (*aq)); + ctrl =devm_spi_alloc_master (&pdev->dev,sizeof (*aq));if (!ctrl)return -ENOMEM ;
@@ -557,8 +557,7 @@ static int atmel_qspi_probe(struct platf aq->regs =devm_ioremap_resource (&pdev->dev, res);if (IS_ERR (aq->regs)) {dev_err (&pdev->dev,"missing registers\n" ); - err =PTR_ERR (aq->regs); - goto exit; +return PTR_ERR (aq->regs); }/* Map the AHB memory */
@@ -566,8 +565,7 @@ static int atmel_qspi_probe(struct platf aq->mem =devm_ioremap_resource (&pdev->dev, res);if (IS_ERR (aq->mem)) {dev_err (&pdev->dev,"missing AHB memory\n" ); - err =PTR_ERR (aq->mem); - goto exit; +return PTR_ERR (aq->mem); } aq->mmap_size =resource_size (res);
@@ -579,15 +577,14 @@ static int atmel_qspi_probe(struct platfif (IS_ERR (aq->pclk)) {dev_err (&pdev->dev,"missing peripheral clock\n" ); - err =PTR_ERR (aq->pclk); - goto exit; +return PTR_ERR (aq->pclk); }/* Enable the peripheral clock */ err =clk_prepare_enable (aq->pclk);if (err) {dev_err (&pdev->dev,"failed to enable the peripheral clock\n" ); - goto exit; +return err; } aq->caps =of_device_get_match_data (&pdev->dev);
@@ -638,8 +635,6 @@ disable_qspick:clk_disable_unprepare (aq->qspick); disable_pclk:clk_disable_unprepare (aq->pclk); -exit: -spi_controller_put (ctrl);return err; }
Greg Kroah-Hartman
maintainerPATCH 644/717 spi: spi-mtk-nor: Dont leak SPI master in probe error path
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 0f4ad8d59f33b24dd86739f3be23e6af1a86f5a9 upstream.
If the call to devm_spi_register_controller() fails on probe of the MediaTek SPI NOR driver, the spi_controller struct is erroneously not freed.
Since commit a1daaa991ed1 ("spi: spi-mtk-nor: use dma_alloc_coherent() for bounce buffer"), the same happens if the call to dmam_alloc_coherent() fails.
Since commit 3bfd9103c7af ("spi: spi-mtk-nor: Add power management support"), the same happens if the call to mtk_nor_enable_clk() fails.
Fix by switching over to the new devm_spi_alloc_master() helper.
--- drivers/spi/spi-mtk-nor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/spi/spi-mtk-nor.c +1 -1
@@ -768,7 +768,7 @@ static int mtk_nor_probe(struct platformreturn -EINVAL ; } - ctlr =spi_alloc_master (&pdev->dev,sizeof (*sp)); + ctlr =devm_spi_alloc_master (&pdev->dev,sizeof (*sp));if (!ctlr) {dev_err (&pdev->dev,"failed to allocate spi controller\n" );return -ENOMEM ;
Greg Kroah-Hartman
maintainerPATCH 645/717 spi: ar934x: Dont leak SPI master in probe error path
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 236924ee531d6251c8d10e9177b7742a60534ed5 upstream.
If the call to devm_spi_register_controller() fails on probe of the Qualcomm Atheros AR934x/QCA95xx SPI driver, the spi_controller struct is erroneously not freed. Fix by switching over to the new devm_spi_alloc_master() helper.
Moreover, the controller's clock is enabled on probe but not disabled if any of the subsequent probe steps fail.
Finally, there's an ordering issue in ar934x_spi_remove() wherein the clock is disabled even though the controller is not yet unregistered. It is unregistered after ar934x_spi_remove() by the devres framework. As long as it is not unregistered, SPI transfers may still be ongoing and disabling the clock may break them. It is not possible to use devm_spi_register_controller() in this case, so move to the non-devm variant.
All of these bugs have existed since the driver was first introduced, so it seems fair to fix them together in a single commit.
--- drivers/spi/spi-ar934x.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
drivers/spi/spi-ar934x.c +11 -3
@@ -176,10 +176,11 @@ static int ar934x_spi_probe(struct platfif (ret)return ret; - ctlr =spi_alloc_master (&pdev->dev,sizeof (*sp)); + ctlr =devm_spi_alloc_master (&pdev->dev,sizeof (*sp));if (!ctlr) {dev_info (&pdev->dev,"failed to allocate spi controller\n" ); -return -ENOMEM ; + ret = -ENOMEM ; + goto err_clk_disable; }/* disable flash mapping and expose spi controller registers */
@@ -202,7 +203,13 @@ static int ar934x_spi_probe(struct platf sp->clk_freq =clk_get_rate (clk); sp->ctlr = ctlr; -return devm_spi_register_controller (&pdev->dev, ctlr); + ret =spi_register_controller (ctlr); +if (!ret) +return 0 ; + +err_clk_disable: +clk_disable_unprepare (clk); +return ret; }static int ar934x_spi_remove (struct platform_device *pdev)
@@ -213,6 +220,7 @@ static int ar934x_spi_remove(struct plat ctlr =dev_get_drvdata (&pdev->dev); sp =spi_controller_get_devdata (ctlr); +spi_unregister_controller (ctlr);clk_disable_unprepare (sp->clk);return 0 ;
Greg Kroah-Hartman
maintainerPATCH 646/717 spi: davinci: Fix use-after-free on unbind
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 373afef350a93519b4b8d636b0895da8650b714b upstream.
davinci_spi_remove() accesses the driver's private data after it's been freed with spi_master_put().
Fix by moving the spi_master_put() to the end of the function.
--- drivers/spi/spi-davinci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/spi/spi-davinci.c +1 -1
@@ -1040,13 +1040,13 @@ static int davinci_spi_remove(struct plaspi_bitbang_stop (&dspi->bitbang);clk_disable_unprepare (dspi->clk); -spi_master_put (master);if (dspi->dma_rx) {dma_release_channel (dspi->dma_rx);dma_release_channel (dspi->dma_tx); } +spi_master_put (master);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 647/717 spi: fsl: fix use of spisel_boot signal on MPC8309
In reply to Greg Kroah-HartmanFrom: Rasmus Villemoes <[email protected]>
commit 122541f2b10897b08f7f7e6db5f1eb693e51f0a1 upstream.
Commit 0f0581b24bd0 ("spi: fsl: Convert to use CS GPIO descriptors") broke the use of the SPISEL_BOOT signal as a chip select on the MPC8309.
pdata->max_chipselect, which becomes master->num_chipselect, must be initialized to take into account the possibility that there's one more chip select in use than the number of GPIO chip selects.
--- drivers/spi/spi-fsl-spi.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
drivers/spi/spi-fsl-spi.c +8 -3
@@ -716,10 +716,11 @@ static int of_fsl_spi_probe(struct platf type =fsl_spi_get_type (&ofdev->dev);if (type ==TYPE_FSL ) {struct fsl_spi_platform_data *pdata =dev_get_platdata (dev); +bool spisel_boot = false;#if IS_ENABLED (CONFIG_FSL_SOC )struct mpc8xxx_spi_probe_info *pinfo =to_of_pinfo (pdata); -bool spisel_boot =of_property_read_bool (np,"fsl,spisel_boot" ); + spisel_boot =of_property_read_bool (np,"fsl,spisel_boot" );if (spisel_boot) { pinfo->immr_spi_cs =ioremap (get_immrbase () +IMMR_SPI_CS_OFFSET ,4 );if (!pinfo->immr_spi_cs)
@@ -734,10 +735,14 @@ static int of_fsl_spi_probe(struct platf* supported on the GRLIB variant. */ ret =gpiod_count (dev,"cs" ); -if (ret <=0 ) +if (ret <0 ) + ret =0 ; +if (ret ==0 && !spisel_boot) { pdata->max_chipselect =1 ; -else + }else { + pdata->max_chipselect = ret + spisel_boot; pdata->cs_control = fsl_spi_cs_control; + } } ret =of_address_to_resource (np,0 , &mem);
Greg Kroah-Hartman
maintainerPATCH 648/717 spi: gpio: Dont leak SPI master in probe error path
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 7174dc655ef0578877b0b4598e69619d2be28b4d upstream.
If the call to devm_spi_register_master() fails on probe of the GPIO SPI driver, the spi_master struct is erroneously not freed:
After allocating the spi_master, its reference count is 1. The driver unconditionally decrements the reference count on unbind using a devm action. Before calling devm_spi_register_master(), the driver unconditionally increments the reference count because on success, that function will decrement the reference count on unbind. However on failure, devm_spi_register_master() does *not* decrement the reference count, so the spi_master is leaked.
The issue was introduced by commits 8b797490b4db ("spi: gpio: Make sure spi_master_put() is called in every error path") and 79567c1a321e ("spi:
gpio: Use devm_spi_register_master()"), which sought to plug leaks introduced by 9b00bc7b901f ("spi: spi-gpio: Rewrite to use GPIO descriptors") but missed this remaining leak.
The situation was later aggravated by commit d3b0ffa1d75d ("spi: gpio:
prevent memory leak in spi_gpio_probe"), which introduced a use-after-free because it releases a reference on the spi_master if devm_add_action_or_reset() fails even though the function already does that.
Fix by switching over to the new devm_spi_alloc_master() helper.
--- drivers/spi/spi-gpio.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-)
drivers/spi/spi-gpio.c +2 -13
@@ -350,11 +350,6 @@ static int spi_gpio_probe_pdata(struct preturn 0 ; } -static void spi_gpio_put (void *data) -{ -spi_master_put (data); -} -static int spi_gpio_probe (struct platform_device *pdev) {int status;
@@ -363,16 +358,10 @@ static int spi_gpio_probe(struct platforstruct device *dev = &pdev->dev;struct spi_bitbang *bb; - master =spi_alloc_master (dev,sizeof (*spi_gpio)); + master =devm_spi_alloc_master (dev,sizeof (*spi_gpio));if (!master)return -ENOMEM ; - status =devm_add_action_or_reset (&pdev->dev, spi_gpio_put, master); -if (status) { -spi_master_put (master); -return status; - } -if (pdev->dev.of_node) status =spi_gpio_probe_dt (pdev, master);else
@@ -432,7 +421,7 @@ static int spi_gpio_probe(struct platforif (status)return status; -return devm_spi_register_master (&pdev->dev,spi_master_get (master)); +return devm_spi_register_master (&pdev->dev, master); }MODULE_ALIAS ("platform:" DRIVER_NAME );
Greg Kroah-Hartman
maintainerPATCH 649/717 spi: mxic: Dont leak SPI master in probe error path
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit cc53711b2191cf3b3210283ae89bf0abb98c70a3 upstream.
If the calls to devm_clk_get() or devm_ioremap_resource() fail on probe of the Macronix SPI driver, the spi_master struct is erroneously not freed.
Fix by switching over to the new devm_spi_alloc_master() helper.
--- drivers/spi/spi-mxic.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-)
drivers/spi/spi-mxic.c +2 -8
@@ -529,7 +529,7 @@ static int mxic_spi_probe(struct platforstruct mxic_spi *mxic;int ret; - master =spi_alloc_master (&pdev->dev,sizeof (struct mxic_spi )); + master =devm_spi_alloc_master (&pdev->dev,sizeof (struct mxic_spi ));if (!master)return -ENOMEM ;
@@ -574,15 +574,9 @@ static int mxic_spi_probe(struct platfor ret =spi_register_master (master);if (ret) {dev_err (&pdev->dev,"spi_register_master failed\n" ); - goto err_put_master; +pm_runtime_disable (&pdev->dev); } -return 0 ; - -err_put_master: -spi_master_put (master); -pm_runtime_disable (&pdev->dev); -return ret; }
Greg Kroah-Hartman
maintainerPATCH 650/717 spi: npcm-fiu: Disable clock in probe error path
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 234266a5168bbe8220d263e3aa7aa80cf921c483 upstream.
If the call to devm_spi_register_master() fails on probe of the NPCM FIU SPI driver, the clock "fiu->clk" is erroneously not unprepared and disabled. Fix it.
--- drivers/spi/spi-npcm-fiu.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/spi/spi-npcm-fiu.c +6 -2
@@ -677,7 +677,7 @@ static int npcm_fiu_probe(struct platforstruct npcm_fiu_spi *fiu;void __iomem *regbase;struct resource *res; -int id; +int id, ret; ctrl =devm_spi_alloc_master (dev,sizeof (*fiu));if (!ctrl)
@@ -735,7 +735,11 @@ static int npcm_fiu_probe(struct platfor ctrl->num_chipselect = fiu->info->max_cs; ctrl->dev.of_node = dev->of_node; -return devm_spi_register_master (dev, ctrl); + ret =devm_spi_register_master (dev, ctrl); +if (ret) +clk_disable_unprepare (fiu->clk); + +return ret; }static int npcm_fiu_remove (struct platform_device *pdev)
Greg Kroah-Hartman
maintainerPATCH 651/717 spi: pic32: Dont leak DMA channels in probe error path
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit c575e9113bff5e024d75481613faed5ef9d465b2 upstream.
If the calls to devm_request_irq() or devm_spi_register_master() fail on probe of the PIC32 SPI driver, the DMA channels requested by pic32_spi_dma_prep() are erroneously not released. Plug the leak.
--- drivers/spi/spi-pic32.c | 1 + 1 file changed, 1 insertion(+)
drivers/spi/spi-pic32.c +1 -0
@@ -839,6 +839,7 @@ static int pic32_spi_probe(struct platforeturn 0 ; err_bailout: +pic32_spi_dma_unprep (pic32s);clk_disable_unprepare (pic32s->clk); err_master:spi_master_put (master);
Greg Kroah-Hartman
maintainerPATCH 652/717 spi: rb4xx: Dont leak SPI master in probe error path
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit a4729c3506c3eb1a6ca5c0289f4e7cafa4115065 upstream.
If the calls to devm_clk_get(), devm_spi_register_master() or clk_prepare_enable() fail on probe of the Mikrotik RB4xx SPI driver, the spi_master struct is erroneously not freed.
Fix by switching over to the new devm_spi_alloc_master() helper.
--- drivers/spi/spi-rb4xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/spi/spi-rb4xx.c +1 -1
@@ -143,7 +143,7 @@ static int rb4xx_spi_probe(struct platfoif (IS_ERR (spi_base))return PTR_ERR (spi_base); - master =spi_alloc_master (&pdev->dev,sizeof (*rbspi)); + master =devm_spi_alloc_master (&pdev->dev,sizeof (*rbspi));if (!master)return -ENOMEM ;
Greg Kroah-Hartman
maintainerPATCH 653/717 spi: rpc-if: Fix use-after-free on unbind
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 393f981ca5f797b58b882d42b7621fb6e43c7f5b upstream.
rpcif_spi_remove() accesses the driver's private data after calling spi_unregister_controller() even though that function releases the last reference on the spi_controller and thereby frees the private data.
Fix by switching over to the new devm_spi_alloc_master() helper which keeps the private data accessible until the driver has unbound.
--- drivers/spi/spi-rpc-if.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-)
drivers/spi/spi-rpc-if.c +2 -7
@@ -134,7 +134,7 @@ static int rpcif_spi_probe(struct platfostruct rpcif *rpc;int error; - ctlr =spi_alloc_master (&pdev->dev,sizeof (*rpc)); + ctlr =devm_spi_alloc_master (&pdev->dev,sizeof (*rpc));if (!ctlr)return -ENOMEM ;
@@ -159,13 +159,8 @@ static int rpcif_spi_probe(struct platfo error =spi_register_controller (ctlr);if (error) {dev_err (&pdev->dev,"spi_register_controller failed\n" ); - goto err_put_ctlr; +rpcif_disable_rpm (rpc); } -return 0 ; - -err_put_ctlr: -rpcif_disable_rpm (rpc); -spi_controller_put (ctlr);return error; }
Greg Kroah-Hartman
maintainerPATCH 654/717 spi: sc18is602: Dont leak SPI master in probe error path
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 5b8c88462d83331dacb48aeaec8388117fef82e0 upstream.
If the call to devm_gpiod_get_optional() fails on probe of the NXP SC18IS602/603 SPI driver, the spi_master struct is erroneously not freed.
Fix by switching over to the new devm_spi_alloc_master() helper.
--- drivers/spi/spi-sc18is602.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-)
drivers/spi/spi-sc18is602.c +2 -11
@@ -238,13 +238,12 @@ static int sc18is602_probe(struct i2c_clstruct sc18is602_platform_data *pdata =dev_get_platdata (dev);struct sc18is602 *hw;struct spi_master *master; -int error;if (!i2c_check_functionality (client->adapter,I2C_FUNC_I2C |I2C_FUNC_SMBUS_WRITE_BYTE_DATA ))return -EINVAL ; - master =spi_alloc_master (dev,sizeof (struct sc18is602 )); + master =devm_spi_alloc_master (dev,sizeof (struct sc18is602 ));if (!master)return -ENOMEM ;
@@ -298,15 +297,7 @@ static int sc18is602_probe(struct i2c_cl master->min_speed_hz = hw->freq /128 ; master->max_speed_hz = hw->freq /4 ; - error =devm_spi_register_master (dev, master); -if (error) - goto error_reg; - -return 0 ; - -error_reg: -spi_master_put (master); -return error; +return devm_spi_register_master (dev, master); }static const struct i2c_device_id sc18is602_id[] = {
Greg Kroah-Hartman
maintainerPATCH 655/717 spi: spi-geni-qcom: Fix use-after-free on unbind
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 8f96c434dfbc85ffa755d6634c8c1cb2233fcf24 upstream.
spi_geni_remove() accesses the driver's private data after calling spi_unregister_master() even though that function releases the last reference on the spi_master and thereby frees the private data.
Moreover, since commit 1a9e489e6128 ("spi: spi-geni-qcom: Use OPP API to set clk/perf state"), spi_geni_probe() leaks the spi_master allocation if the calls to dev_pm_opp_set_clkname() or dev_pm_opp_of_add_table() fail.
Fix by switching over to the new devm_spi_alloc_master() helper which keeps the private data accessible until the driver has unbound and also avoids the spi_master leak on probe.
--- drivers/spi/spi-geni-qcom.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/spi/spi-geni-qcom.c +1 -2
@@ -603,7 +603,7 @@ static int spi_geni_probe(struct platforif (IS_ERR (clk))return PTR_ERR (clk); - spi =spi_alloc_master (dev,sizeof (*mas)); + spi =devm_spi_alloc_master (dev,sizeof (*mas));if (!spi)return -ENOMEM ;
@@ -673,7 +673,6 @@ spi_geni_probe_free_irq:free_irq (mas->irq, spi); spi_geni_probe_runtime_disable:pm_runtime_disable (dev); -spi_master_put (spi);dev_pm_opp_of_remove_table (&pdev->dev); put_clkname:dev_pm_opp_put_clkname (mas->se.opp_table);
Greg Kroah-Hartman
maintainerPATCH 656/717 spi: spi-qcom-qspi: Fix use-after-free on unbind
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 6cfd39e212dee2e77a0227ce4e0f55fa06d79f46 upstream.
qcom_qspi_remove() accesses the driver's private data after calling spi_unregister_master() even though that function releases the last reference on the spi_master and thereby frees the private data.
Fix by switching over to the new devm_spi_alloc_master() helper which keeps the private data accessible until the driver has unbound.
--- drivers/spi/spi-qcom-qspi.c | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-)
drivers/spi/spi-qcom-qspi.c +16 -26
@@ -462,7 +462,7 @@ static int qcom_qspi_probe(struct platfo dev = &pdev->dev; - master =spi_alloc_master (dev,sizeof (*ctrl)); + master =devm_spi_alloc_master (dev,sizeof (*ctrl));if (!master)return -ENOMEM ;
@@ -473,54 +473,49 @@ static int qcom_qspi_probe(struct platfospin_lock_init (&ctrl->lock); ctrl->dev = dev; ctrl->base =devm_platform_ioremap_resource (pdev,0 ); -if (IS_ERR (ctrl->base)) { - ret =PTR_ERR (ctrl->base); - goto exit_probe_master_put; - } +if (IS_ERR (ctrl->base)) +return PTR_ERR (ctrl->base); ctrl->clks =devm_kcalloc (dev,QSPI_NUM_CLKS ,sizeof (*ctrl->clks),GFP_KERNEL ); -if (!ctrl->clks) { - ret = -ENOMEM ; - goto exit_probe_master_put; - } +if (!ctrl->clks) +return -ENOMEM ; ctrl->clks[QSPI_CLK_CORE ].id ="core" ; ctrl->clks[QSPI_CLK_IFACE ].id ="iface" ; ret =devm_clk_bulk_get (dev,QSPI_NUM_CLKS , ctrl->clks);if (ret) - goto exit_probe_master_put; +return ret; ctrl->icc_path_cpu_to_qspi =devm_of_icc_get (dev,"qspi-config" ); -if (IS_ERR (ctrl->icc_path_cpu_to_qspi)) { - ret =dev_err_probe (dev,PTR_ERR (ctrl->icc_path_cpu_to_qspi), -"Failed to get cpu path\n" ); - goto exit_probe_master_put; - } +if (IS_ERR (ctrl->icc_path_cpu_to_qspi)) +return dev_err_probe (dev,PTR_ERR (ctrl->icc_path_cpu_to_qspi), +"Failed to get cpu path\n" ); +/* Set BW vote for register access */ ret =icc_set_bw (ctrl->icc_path_cpu_to_qspi,Bps_to_icc (1000 ),Bps_to_icc (1000 ));if (ret) {dev_err (ctrl->dev,"%s: ICC BW voting failed for cpu: %d\n" , __func__, ret); - goto exit_probe_master_put; +return ret; } ret =icc_disable (ctrl->icc_path_cpu_to_qspi);if (ret) {dev_err (ctrl->dev,"%s: ICC disable failed for cpu: %d\n" , __func__, ret); - goto exit_probe_master_put; +return ret; } ret =platform_get_irq (pdev,0 );if (ret <0 ) - goto exit_probe_master_put; +return ret; ret =devm_request_irq (dev, ret, qcom_qspi_irq,IRQF_TRIGGER_HIGH ,dev_name (dev), ctrl);if (ret) {dev_err (dev,"Failed to request irq %d\n" , ret); - goto exit_probe_master_put; +return ret; } master->max_speed_hz =300000000 ;
@@ -537,10 +532,8 @@ static int qcom_qspi_probe(struct platfo master->auto_runtime_pm = true; ctrl->opp_table =dev_pm_opp_set_clkname (&pdev->dev,"core" ); -if (IS_ERR (ctrl->opp_table)) { - ret =PTR_ERR (ctrl->opp_table); - goto exit_probe_master_put; - } +if (IS_ERR (ctrl->opp_table)) +return PTR_ERR (ctrl->opp_table);/* OPP table is optional */ ret =dev_pm_opp_of_add_table (&pdev->dev);if (ret && ret != -ENODEV ) {
@@ -562,9 +555,6 @@ static int qcom_qspi_probe(struct platfo exit_probe_put_clkname:dev_pm_opp_put_clkname (ctrl->opp_table); -exit_probe_master_put: -spi_master_put (master); -return ret; }
Greg Kroah-Hartman
maintainerPATCH 657/717 spi: st-ssc4: Fix unbalanced pm_runtime_disable() in probe error path
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 5ef76dac0f2c26aeae4ee79eb830280f16d5aceb upstream.
If the calls to devm_platform_ioremap_resource(), irq_of_parse_and_map() or devm_request_irq() fail on probe of the ST SSC4 SPI driver, the runtime PM disable depth is incremented even though it was not decremented before. Fix it.
--- drivers/spi/spi-st-ssc4.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/spi/spi-st-ssc4.c +3 -2
@@ -375,13 +375,14 @@ static int spi_st_probe(struct platform_ ret =devm_spi_register_master (&pdev->dev, master);if (ret) {dev_err (&pdev->dev,"Failed to register master\n" ); - goto clk_disable; + goto rpm_disable; }return 0 ; -clk_disable: +rpm_disable:pm_runtime_disable (&pdev->dev); +clk_disable:clk_disable_unprepare (spi_st->clk); put_master:spi_master_put (master);
Greg Kroah-Hartman
maintainerPATCH 658/717 spi: synquacer: Disable clock in probe error path
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 8853b2503014aca5c793d2c7f0aabc990b32bdad upstream.
If the calls to platform_get_irq() or devm_request_irq() fail on probe of the SynQuacer SPI driver, the clock "sspi->clk" is erroneously not unprepared and disabled.
If the clock rate "master->max_speed_hz" cannot be determined, the same happens and in addition the spi_master struct is not freed.
Fix it.
--- drivers/spi/spi-synquacer.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
drivers/spi/spi-synquacer.c +8 -7
@@ -657,7 +657,8 @@ static int synquacer_spi_probe(struct plif (!master->max_speed_hz) {dev_err (&pdev->dev,"missing clock source\n" ); -return -EINVAL ; + ret = -EINVAL ; + goto disable_clk; } master->min_speed_hz = master->max_speed_hz /254 ;
@@ -670,7 +671,7 @@ static int synquacer_spi_probe(struct pl rx_irq =platform_get_irq (pdev,0 );if (rx_irq <=0 ) { ret = rx_irq; - goto put_spi; + goto disable_clk; }snprintf (sspi->rx_irq_name,SYNQUACER_HSSPI_IRQ_NAME_MAX ,"%s-rx" ,dev_name (&pdev->dev));
@@ -678,13 +679,13 @@ static int synquacer_spi_probe(struct pl 0, sspi->rx_irq_name, sspi);if (ret) {dev_err (&pdev->dev,"request rx_irq failed (%d)\n" , ret); - goto put_spi; + goto disable_clk; } tx_irq =platform_get_irq (pdev,1 );if (tx_irq <=0 ) { ret = tx_irq; - goto put_spi; + goto disable_clk; }snprintf (sspi->tx_irq_name,SYNQUACER_HSSPI_IRQ_NAME_MAX ,"%s-tx" ,dev_name (&pdev->dev));
@@ -692,7 +693,7 @@ static int synquacer_spi_probe(struct pl 0, sspi->tx_irq_name, sspi);if (ret) {dev_err (&pdev->dev,"request tx_irq failed (%d)\n" , ret); - goto put_spi; + goto disable_clk; } master->dev.of_node = np;
@@ -710,7 +711,7 @@ static int synquacer_spi_probe(struct pl ret =synquacer_spi_enable (master);if (ret) - goto fail_enable; + goto disable_clk;pm_runtime_set_active (sspi->dev);pm_runtime_enable (sspi->dev);
@@ -723,7 +724,7 @@ static int synquacer_spi_probe(struct pl disable_pm:pm_runtime_disable (sspi->dev); -fail_enable: +disable_clk:clk_disable_unprepare (sspi->clk); put_spi:spi_master_put (master);
Greg Kroah-Hartman
maintainerPATCH 659/717 spi: mt7621: Disable clock in probe error path
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 24f7033405abe195224ec793dbc3d7a27dec0b98 upstream.
Commit 702b15cb9712 ("spi: mt7621: fix missing clk_disable_unprepare() on error in mt7621_spi_probe") sought to disable the SYS clock on probe errors, but only did so for 2 of 3 potentially failing calls: The clock needs to be disabled on failure of devm_spi_register_controller() as well.
Moreover, the commit purports to fix a bug in commit cbd66c626e16 ("spi:
mt7621: Move SPI driver out of staging") but in reality the bug has existed since the driver was first introduced.
--- drivers/spi/spi-mt7621.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/spi/spi-mt7621.c +5 -1
@@ -382,7 +382,11 @@ static int mt7621_spi_probe(struct platfreturn ret; } -return devm_spi_register_controller (&pdev->dev, master); + ret =devm_spi_register_controller (&pdev->dev, master); +if (ret) +clk_disable_unprepare (clk); + +return ret; }static int mt7621_spi_remove (struct platform_device *pdev)
Greg Kroah-Hartman
maintainerPATCH 660/717 spi: mt7621: Dont leak SPI master in probe error path
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 46b5c4fb87ce8211e0f9b0383dbde72c3652d2ba upstream.
If the calls to device_reset() or devm_spi_register_controller() fail on probe of the MediaTek MT7621 SPI driver, the spi_controller struct is erroneously not freed. Fix by switching over to the new devm_spi_alloc_master() helper.
Additionally, there's an ordering issue in mt7621_spi_remove() wherein the spi_controller is unregistered after disabling the SYS clock. The correct order is to call spi_unregister_controller() *before* this teardown step because bus accesses may still be ongoing until that function returns.
All of these bugs have existed since the driver was first introduced, so it seems fair to fix them together in a single commit.
--- drivers/spi/spi-mt7621.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/spi/spi-mt7621.c +3 -2
@@ -350,7 +350,7 @@ static int mt7621_spi_probe(struct platfif (status)return status; - master =spi_alloc_master (&pdev->dev,sizeof (*rs)); + master =devm_spi_alloc_master (&pdev->dev,sizeof (*rs));if (!master) {dev_info (&pdev->dev,"master allocation failed\n" );clk_disable_unprepare (clk);
@@ -382,7 +382,7 @@ static int mt7621_spi_probe(struct platfreturn ret; } - ret =devm_spi_register_controller (&pdev->dev, master); + ret =spi_register_controller (master);if (ret)clk_disable_unprepare (clk);
@@ -397,6 +397,7 @@ static int mt7621_spi_remove(struct plat master =dev_get_drvdata (&pdev->dev); rs =spi_controller_get_devdata (master); +spi_unregister_controller (master);clk_disable_unprepare (rs->clk);return 0 ;
Greg Kroah-Hartman
maintainerPATCH 661/717 spi: atmel-quadspi: Disable clock in probe error path
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 0e685017c7ba1a2fe9f6f1e7a9302890747d934c upstream.
If the call to of_device_get_match_data() fails on probe of the Atmel QuadSPI driver, the clock "aq->pclk" is erroneously not unprepared and disabled. Fix it.
--- drivers/spi/atmel-quadspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/spi/atmel-quadspi.c +1 -1
@@ -591,7 +591,7 @@ static int atmel_qspi_probe(struct platfif (!aq->caps) {dev_err (&pdev->dev,"Could not retrieve QSPI caps\n" ); err = -EINVAL ; - goto exit; + goto disable_pclk; }if (aq->caps->has_qspick) {
Greg Kroah-Hartman
maintainerPATCH 662/717 spi: atmel-quadspi: Fix AHB memory accesses
In reply to Greg Kroah-HartmanFrom: Tudor Ambarus <[email protected]>
commit cac8c821059639b015586abf61623c62cc549a13 upstream.
Following error was seen when mounting a 16MByte ubifs:
UBIFS error (ubi0:0 pid 1893): check_lpt_type.constprop.6: invalid type (15) in LPT node type
QSPI_IFR.TFRTYP was not set correctly. When data transfer is enabled and one wants to access the serial memory through AHB in order to:
- read in the serial memory, but not a memory data, for example a JEDEC-ID, QSPI_IFR.TFRTYP must be written to '0' (both sama5d2 and sam9x60).
- read in the serial memory, and particularly a memory data, TFRTYP must be written to '1' (both sama5d2 and sam9x60).
- write in the serial memory, but not a memory data, for example writing the configuration or the QSPI_SR, TFRTYP must be written to '2' for sama5d2 and to '0' for sam9x60.
- write in the serial memory in particular to program a memory data, TFRTYP must be written to '3' for sama5d2 and to '1' for sam9x60.
Fix the setting of the QSPI_IFR.TFRTYP field.
--- drivers/spi/atmel-quadspi.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/spi/atmel-quadspi.c +7 -3
@@ -365,10 +365,14 @@ static int atmel_qspi_set_cfg(struct atmif (dummy_cycles) ifr |=QSPI_IFR_NBDUM (dummy_cycles); -/* Set data enable */ -if (op->data.nbytes) +/* Set data enable and data transfer type. */ +if (op->data.nbytes) { ifr |=QSPI_IFR_DATAEN ; +if (op->addr.nbytes) + ifr |=QSPI_IFR_TFRTYP_MEM ; + } +/* * If the QSPI controller is set in regular SPI mode, set it in * Serial Memory Mode (SMM).
@@ -393,7 +397,7 @@ static int atmel_qspi_set_cfg(struct atmatmel_qspi_write (icr, aq,QSPI_WICR );atmel_qspi_write (ifr, aq,QSPI_IFR ); }else { -if (op->data.dir ==SPI_MEM_DATA_OUT ) +if (op->data.nbytes && op->data.dir ==SPI_MEM_DATA_OUT ) ifr |=QSPI_IFR_SAMA5D2_WRITE_TRSFR ;/* Set QSPI Instruction Frame registers */
Greg Kroah-Hartman
maintainerPATCH 663/717 soc: qcom: smp2p: Safely acquire spinlock without IRQs
In reply to Greg Kroah-HartmanFrom: Evan Green <[email protected]>
commit fc3e62e25c3896855b7c3d72df19ca6be3459c9f upstream.
smp2p_update_bits() should disable interrupts when it acquires its spinlock. This is important because without the _irqsave, a priority inversion can occur.
This function is called both with interrupts enabled in qcom_q6v5_request_stop(), and with interrupts disabled in ipa_smp2p_panic_notifier(). IRQ handling of spinlocks should be consistent to avoid the panic notifier deadlocking because it's sitting on the thread that's already got the lock via _request_stop().
Found via lockdep.
--- drivers/soc/qcom/smp2p.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/soc/qcom/smp2p.c +3 -2
@@ -318,15 +318,16 @@ static int qcom_smp2p_inbound_entry(strustatic int smp2p_update_bits (void *data,u32 mask,u32 value) {struct smp2p_entry *entry = data; +unsigned long flags;u32 orig;u32 val; -spin_lock (&entry->lock); +spin_lock_irqsave (&entry->lock, flags); val = orig =readl (entry->value); val &= ~mask; val |= value;writel (val, entry->value); -spin_unlock (&entry->lock); +spin_unlock_irqrestore (&entry->lock, flags);if (val != orig)qcom_smp2p_kick (entry->smp2p);
Greg Kroah-Hartman
maintainerPATCH 664/717 mtd: spinand: Fix OOB read
In reply to Greg Kroah-HartmanFrom: Miquel Raynal <[email protected]>
commit 868cbe2a6dcee451bd8f87cbbb2a73cf463b57e5 upstream.
So far OOB have never been used in SPI-NAND, add the missing memcpy to make it work properly.
--- drivers/mtd/nand/spi/core.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/mtd/nand/spi/core.c +4 -0
@@ -318,6 +318,10 @@ static int spinand_write_to_cache_op(str buf += ret; } +if (req->ooblen) +memcpy (req->oobbuf.in, spinand->oobbuf + req->ooboffs, + req->ooblen); +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 665/717 mtd: parser: cmdline: Fix parsing of part-names with colons
In reply to Greg Kroah-HartmanFrom: Sven Eckelmann <[email protected]>
commit 639a82434f16a6df0ce0e7c8595976f1293940fd upstream.
Some devices (especially QCA ones) are already using hardcoded partition names with colons in it. The OpenMesh A62 for example provides following mtd relevant information via cmdline:
root=31:11 mtdparts=spi0.0:256k(0:SBL1),128k(0:MIBIB),384k(0:QSEE),64k(0:CDT),64k(0:DDRPARAMS),64k(0:APPSBLENV),512k(0:APPSBL),64k(0:ART),64k(custom),64k(0:KEYS),0x002b0000(kernel),0x00c80000(rootfs),15552k(inactive) rootfsname=rootfs rootwait
The change to split only on the last colon between mtd-id and partitions will cause newpart to see following string for the first partition:
KEYS),0x002b0000(kernel),0x00c80000(rootfs),15552k(inactive)
Such a partition list cannot be parsed and thus the device fails to boot.
Avoid this behavior by making sure that the start of the first part-name ("(") will also be the last byte the mtd-id split algorithm is using for its colon search.
--- drivers/mtd/parsers/cmdlinepart.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
drivers/mtd/parsers/cmdlinepart.c +13 -1
@@ -226,7 +226,7 @@ static int mtdpart_setup_real(char *s)struct cmdline_mtd_partition *this_mtd;struct mtd_partition *parts;int mtd_id_len, num_parts; -char *p, *mtd_id, *semicol; +char *p, *mtd_id, *semicol, *open_parenth;/* * Replace the first ';' by a NULL char so strrchr can work
@@ -236,6 +236,14 @@ static int mtdpart_setup_real(char *s)if (semicol) *semicol ='\0' ; +/* +* make sure that part-names with ":" will not be handled as +* part of the mtd-id with an ":" +*/ + open_parenth =strchr (s,'(' ); +if (open_parenth) + *open_parenth ='\0' ; + mtd_id = s;/*
@@ -245,6 +253,10 @@ static int mtdpart_setup_real(char *s)*/ p =strrchr (s,':' ); +/* Restore the '(' now. */ +if (open_parenth) + *open_parenth ='(' ; +/* Restore the ';' now. */ if (semicol) *semicol =';' ;
Greg Kroah-Hartman
maintainerPATCH 666/717 mtd: core: Fix refcounting for unpartitioned MTDs
In reply to Greg Kroah-HartmanFrom: Richard Weinberger <[email protected]>
commit 1ca71415f075353974524e96ed175306d8a937a8 upstream.
Apply changes to usecount also to the master partition. Otherwise we have no refcounting at all if an MTD has no partitions.
--- drivers/mtd/mtdcore.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/mtd/mtdcore.c +4 -0
@@ -993,6 +993,8 @@ int __get_mtd_device(struct mtd_info *mt } } + master->usecount++; +while (mtd->parent) { mtd->usecount++; mtd = mtd->parent;
@@ -1059,6 +1061,8 @@ void __put_mtd_device(struct mtd_info *m mtd = mtd->parent; } + master->usecount--; +if (master->_put_device) master->_put_device (master);
Greg Kroah-Hartman
maintainerPATCH 667/717 mtd: rawnand: qcom: Fix DMA sync on FLASH_STATUS register read
In reply to Greg Kroah-HartmanFrom: Praveenkumar I <[email protected]>
commit bc3686021122de953858a5be4cbf6e3f1d821e79 upstream.
After each codeword NAND_FLASH_STATUS is read for possible operational failures. But there is no DMA sync for CPU operation before reading it and this leads to incorrect or older copy of DMA buffer in reg_read_buf.
This patch adds the DMA sync on reg_read_buf for CPU before reading it.
--- drivers/mtd/nand/raw/qcom_nandc.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/mtd/nand/raw/qcom_nandc.c +2 -0
@@ -1570,6 +1570,8 @@ static int check_flash_errors(struct qcostruct qcom_nand_controller *nandc =get_qcom_nand_controller (chip);int i; +nandc_read_buffer_sync (nandc, true); +for (i =0 ; i < cw_cnt; i++) {u32 flash =le32_to_cpu (nandc->reg_read_buf[i]);
Greg Kroah-Hartman
maintainerPATCH 668/717 mtd: rawnand: meson: fix meson_nfc_dma_buffer_release() arguments
In reply to Greg Kroah-HartmanFrom: Sergei Antonov <[email protected]>
commit c13d845e9a69580424d40b7b101c37d4f71bcd63 upstream.
Arguments 'infolen' and 'datalen' to meson_nfc_dma_buffer_release() were mixed up.
--- drivers/mtd/nand/raw/meson_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mtd/nand/raw/meson_nand.c +1 -1
@@ -510,7 +510,7 @@ static int meson_nfc_dma_buffer_setup(st }static void meson_nfc_dma_buffer_release (struct nand_chip *nand, -int infolen,int datalen, +int datalen,int infolen,enum dma_data_direction dir) {struct meson_nfc *nfc =nand_get_controller_data (nand);
Greg Kroah-Hartman
maintainerPATCH 669/717 scsi: qla2xxx: Fix crash during driver load on big endian machines
In reply to Greg Kroah-HartmanFrom: Arun Easi <[email protected]>
commit 8de309e7299a00b3045fb274f82b326f356404f0 upstream.
Crash stack:
[576544.715489] Unable to handle kernel paging request for data at address 0xd00000000f970000 [576544.715497] Faulting instruction address: 0xd00000000f880f64 [576544.715503] Oops: Kernel access of bad area, sig: 11 [#1] [576544.715506] SMP NR_CPUS=2048 NUMA pSeries : [576544.715703] NIP [d00000000f880f64] .qla27xx_fwdt_template_valid+0x94/0x100 [qla2xxx] [576544.715722] LR [d00000000f7952dc] .qla24xx_load_risc_flash+0x2fc/0x590 [qla2xxx] [576544.715726] Call Trace: [576544.715731] [c0000004d0ffb000] [c0000006fe02c350] 0xc0000006fe02c350 (unreliable) [576544.715750] [c0000004d0ffb080] [d00000000f7952dc] .qla24xx_load_risc_flash+0x2fc/0x590 [qla2xxx] [576544.715770] [c0000004d0ffb170] [d00000000f7aa034] .qla81xx_load_risc+0x84/0x1a0 [qla2xxx] [576544.715789] [c0000004d0ffb210] [d00000000f79f7c8] .qla2x00_setup_chip+0xc8/0x910 [qla2xxx] [576544.715808] [c0000004d0ffb300] [d00000000f7a631c] .qla2x00_initialize_adapter+0x4dc/0xb00 [qla2xxx] [576544.715826] [c0000004d0ffb3e0] [d00000000f78ce28] .qla2x00_probe_one+0xf08/0x2200 [qla2xxx]
--- drivers/scsi/qla2xxx/qla_tmpl.c | 9 +++++---- drivers/scsi/qla2xxx/qla_tmpl.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-)
drivers/scsi/qla2xxx/qla_tmpl.c +5 -4
@@ -928,7 +928,8 @@ qla27xx_template_checksum(void *p, ulongstatic inline int qla27xx_verify_template_checksum (struct qla27xx_fwdt_template *tmp) { -return qla27xx_template_checksum (tmp, tmp->template_size) ==0 ; +return qla27xx_template_checksum (tmp, +le32_to_cpu (tmp->template_size)) ==0 ; } static inline int
@@ -944,7 +945,7 @@ qla27xx_execute_fwdt_template(struct scsulong len =0 ;if (qla27xx_fwdt_template_valid (tmp)) { - len = tmp->template_size; + len =le32_to_cpu (tmp->template_size); tmp =memcpy (buf, tmp, len);ql27xx_edit_template (vha, tmp);qla27xx_walk_template (vha, tmp, buf, &len);
@@ -960,7 +961,7 @@ qla27xx_fwdt_calculate_dump_size(structulong len =0 ;if (qla27xx_fwdt_template_valid (tmp)) { - len = tmp->template_size; + len =le32_to_cpu (tmp->template_size);qla27xx_walk_template (vha, tmp,NULL , &len); }
@@ -972,7 +973,7 @@ qla27xx_fwdt_template_size(void *p) {struct qla27xx_fwdt_template *tmp = p; -return tmp->template_size; +return le32_to_cpu (tmp->template_size); }int
drivers/scsi/qla2xxx/qla_tmpl.h +1 -1
@@ -12,7 +12,7 @@struct __packed qla27xx_fwdt_template {__le32 template_type;__le32 entry_offset; -uint32_t template_size; +__le32 template_size;uint32_t count;/* borrow field for running/residual count */ __le32 entry_count;
Greg Kroah-Hartman
maintainerPATCH 670/717 scsi: lpfc: Fix invalid sleeping context in lpfc_sli4_nvmet_alloc()
In reply to Greg Kroah-HartmanFrom: James Smart <[email protected]>
commit 62e3a931db60daf94fdb3159d685a5bc6ad4d0cf upstream.
The following calltrace was seen:
BUG: sleeping function called from invalid context at mm/slab.h:494 ... Call Trace: dump_stack+0x9a/0xf0 ___might_sleep.cold.63+0x13d/0x178 slab_pre_alloc_hook+0x6a/0x90 kmem_cache_alloc_trace+0x3a/0x2d0 lpfc_sli4_nvmet_alloc+0x4c/0x280 [lpfc] lpfc_post_rq_buffer+0x2e7/0xa60 [lpfc] lpfc_sli4_hba_setup+0x6b4c/0xa4b0 [lpfc] lpfc_pci_probe_one_s4.isra.15+0x14f8/0x2280 [lpfc] lpfc_pci_probe_one+0x260/0x2880 [lpfc] local_pci_probe+0xd4/0x180 work_for_cpu_fn+0x51/0xa0 process_one_work+0x8f0/0x17b0 worker_thread+0x536/0xb50 kthread+0x30c/0x3d0 ret_from_fork+0x3a/0x50
A prior patch introduced a spin_lock_irqsave(hbalock) in the lpfc_post_rq_buffer() routine. Call trace is seen as the hbalock is held with interrupts disabled during a GFP_KERNEL allocation in lpfc_sli4_nvmet_alloc().
Fix by reordering locking so that hbalock not held when calling sli4_nvmet_alloc() (aka rqb_buf_list()).
--- drivers/scsi/lpfc/lpfc_mem.c | 4 +--- drivers/scsi/lpfc/lpfc_sli.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 5 deletions(-)
drivers/scsi/lpfc/lpfc_mem.c +1 -3
@@ -588,8 +588,6 @@ lpfc_sli4_rb_free(struct lpfc_hba *phba,* Description: Allocates a DMA-mapped receive buffer from the lpfc_hrb_pool PCI * pool along a non-DMA-mapped container for it. * -* Notes: Not interrupt-safe. Must be called with no locks held. -* * Returns: * pointer to HBQ on success * NULL on failure
@@ -599,7 +597,7 @@ lpfc_sli4_nvmet_alloc(struct lpfc_hba *p {struct rqb_dmabuf *dma_buf; - dma_buf =kzalloc (sizeof (struct rqb_dmabuf ),GFP_KERNEL ); + dma_buf =kzalloc (sizeof (*dma_buf),GFP_KERNEL );if (!dma_buf)return NULL ;
drivers/scsi/lpfc/lpfc_sli.c +8 -2
@@ -7248,12 +7248,16 @@ lpfc_post_rq_buffer(struct lpfc_hba *phbstruct rqb_dmabuf *rqb_buffer;LIST_HEAD (rqb_buf_list); -spin_lock_irqsave (&phba->hbalock, flags); rqbp = hrq->rqbp;for (i =0 ; i < count; i++) { +spin_lock_irqsave (&phba->hbalock, flags);/* IF RQ is already full, don't bother */ -if (rqbp->buffer_count + i >= rqbp->entry_count -1 ) +if (rqbp->buffer_count + i >= rqbp->entry_count -1 ) { +spin_unlock_irqrestore (&phba->hbalock, flags);break ; + } +spin_unlock_irqrestore (&phba->hbalock, flags); + rqb_buffer = rqbp->rqb_alloc_buffer (phba);if (!rqb_buffer)break ;
@@ -7262,6 +7266,8 @@ lpfc_post_rq_buffer(struct lpfc_hba *phb rqb_buffer->idx = idx;list_add_tail (&rqb_buffer->hbuf.list, &rqb_buf_list); } + +spin_lock_irqsave (&phba->hbalock, flags);while (!list_empty (&rqb_buf_list)) { list_remove_head(&rqb_buf_list, rqb_buffer, struct rqb_dmabuf, hbuf.list);
Greg Kroah-Hartman
maintainerPATCH 671/717 scsi: lpfc: Fix scheduling call while in softirq context in lpfc_unreg_rpi
In reply to Greg Kroah-HartmanFrom: James Smart <[email protected]>
commit e7dab164a9aa457f89d4528452bdfc3e15ac98b6 upstream.
The following call trace was seen during HBA reset testing:
BUG: scheduling while atomic: swapper/2/0/0x10000100 ... Call Trace: dump_stack+0x19/0x1b __schedule_bug+0x64/0x72 __schedule+0x782/0x840 __cond_resched+0x26/0x30 _cond_resched+0x3a/0x50 mempool_alloc+0xa0/0x170 lpfc_unreg_rpi+0x151/0x630 [lpfc] lpfc_sli_abts_recover_port+0x171/0x190 [lpfc] lpfc_sli4_abts_err_handler+0xb2/0x1f0 [lpfc] lpfc_sli4_io_xri_aborted+0x256/0x300 [lpfc] lpfc_sli4_sp_handle_abort_xri_wcqe.isra.51+0xa3/0x190 [lpfc] lpfc_sli4_fp_handle_cqe+0x89/0x4d0 [lpfc] __lpfc_sli4_process_cq+0xdb/0x2e0 [lpfc] __lpfc_sli4_hba_process_cq+0x41/0x100 [lpfc] lpfc_cq_poll_hdler+0x1a/0x30 [lpfc] irq_poll_softirq+0xc7/0x100 __do_softirq+0xf5/0x280 call_softirq+0x1c/0x30 do_softirq+0x65/0xa0 irq_exit+0x105/0x110 do_IRQ+0x56/0xf0 common_interrupt+0x16a/0x16a
With the conversion to blk_io_poll for better interrupt latency in normal cases, it introduced this code path, executed when I/O aborts or logouts are seen, which attempts to allocate memory for a mailbox command to be issued. The allocation is GFP_KERNEL, thus it could attempt to sleep.
Fix by creating a work element that performs the event handling for the remote port. This will have the mailbox commands and other items performed in the work element, not the irq. A much better method as the "irq" routine does not stall while performing all this deep handling code.
Ensure that allocation failures are handled and send LOGO on failure.
Additionally, enlarge the mailbox memory pool to reduce the possibility of additional allocation in this path.
--- drivers/scsi/lpfc/lpfc.h | 2 - drivers/scsi/lpfc/lpfc_disc.h | 2 + drivers/scsi/lpfc/lpfc_hbadisc.c | 35 +++++++++++++++++++++ drivers/scsi/lpfc/lpfc_init.c | 46 ++++++++++++++++------------ drivers/scsi/lpfc/lpfc_mem.c | 5 +-- drivers/scsi/lpfc/lpfc_nvme.c | 18 +++++++--- drivers/scsi/lpfc/lpfc_sli.c | 64 +++++++++++++++++++++++++++++++-------- drivers/scsi/lpfc/lpfc_sli4.h | 6 +-- 8 files changed, 136 insertions(+), 42 deletions(-)
drivers/scsi/lpfc/lpfc.h +1 -1
@@ -753,7 +753,7 @@ struct lpfc_hba {#define HBA_SP_QUEUE_EVT 0x8/* Slow-path qevt posted to worker thread*/ #define HBA_POST_RECEIVE_BUFFER 0x10/* Rcv buffers need to be posted */ #define HBA_PERSISTENT_TOPO 0x20/* Persistent topology support in hba */ -#define ELS_XRI_ABORT_EVENT 0x40 +#define ELS_XRI_ABORT_EVENT 0x40/* ELS_XRI abort event was queued */ #define ASYNC_EVENT 0x80#define LINK_DISABLED 0x100/* Link disabled by user */ #define FCF_TS_INPROG 0x200/* FCF table scan in progress */
drivers/scsi/lpfc/lpfc_disc.h +2 -0
@@ -41,6 +41,7 @@ enum lpfc_work_type {LPFC_EVT_DEV_LOSS ,LPFC_EVT_FASTPATH_MGMT_EVT ,LPFC_EVT_RESET_HBA , + LPFC_EVT_RECOVER_PORT };/* structure used to queue event to the discovery tasklet */
@@ -128,6 +129,7 @@ struct lpfc_nodelist {struct lpfc_vport *vport;struct lpfc_work_evt els_retry_evt;struct lpfc_work_evt dev_loss_evt; +struct lpfc_work_evt recovery_evt;struct kref kref;atomic_t cmd_pending;uint32_t cmd_qdepth;
drivers/scsi/lpfc/lpfc_hbadisc.c +35 -0
@@ -552,6 +552,15 @@ lpfc_work_list_done(struct lpfc_hba *phb fcf_inuse, nlp_did);break ; +case LPFC_EVT_RECOVER_PORT : + ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1); +lpfc_sli_abts_recover_port (ndlp->vport, ndlp); + free_evt =0 ; +/* decrement the node reference count held for +* this queued work +*/ +lpfc_nlp_put (ndlp); +break ;case LPFC_EVT_ONLINE :if (phba->link_state <LPFC_LINK_DOWN ) *(int *) (evtp->evt_arg1) =lpfc_online (phba);
@@ -4515,6 +4524,8 @@ lpfc_initialize_node(struct lpfc_vport *INIT_LIST_HEAD (&ndlp->els_retry_evt.evt_listp);INIT_LIST_HEAD (&ndlp->dev_loss_evt.evt_listp);timer_setup (&ndlp->nlp_delayfunc, lpfc_els_retry_delay,0 ); +INIT_LIST_HEAD (&ndlp->recovery_evt.evt_listp); + ndlp->nlp_DID = did; ndlp->vport = vport; ndlp->phba = vport->phba;
@@ -5011,6 +5022,29 @@ lpfc_unreg_rpi(struct lpfc_vport *vport,mempool_free (mbox, phba->mbox_mem_pool); acc_plogi =1 ; } + }else { +lpfc_printf_vlog (vport,KERN_INFO , +LOG_NODE |LOG_DISCOVERY , +"1444 Failed to allocate mempool " +"unreg_rpi UNREG x%x, " +"DID x%x, flag x%x, " +"ndlp x%px\n" , + ndlp->nlp_rpi, ndlp->nlp_DID, + ndlp->nlp_flag, ndlp); + +/* Because mempool_alloc failed, we +* will issue a LOGO here and keep the rpi alive if +* not unloading. +*/ +if (!(vport->load_flag &FC_UNLOADING )) { + ndlp->nlp_flag &= ~NLP_UNREG_INP ; +lpfc_issue_els_logo (vport, ndlp,0 ); + ndlp->nlp_prev_state = ndlp->nlp_state; +lpfc_nlp_set_state (vport, ndlp, +NLP_STE_NPR_NODE ); + } + +return 1 ; }lpfc_no_rpi (phba, ndlp); out:
@@ -5214,6 +5248,7 @@ lpfc_cleanup_node(struct lpfc_vport *vpolist_del_init (&ndlp->els_retry_evt.evt_listp);list_del_init (&ndlp->dev_loss_evt.evt_listp); +list_del_init (&ndlp->recovery_evt.evt_listp);lpfc_cleanup_vports_rrqs (vport, ndlp);if (phba->sli_rev ==LPFC_SLI_REV4 ) ndlp->nlp_flag |=NLP_RELEASE_RPI ;
drivers/scsi/lpfc/lpfc_init.c +27 -19
94 lines not on this page · raw message
drivers/scsi/lpfc/lpfc_mem.c +3 -2
@@ -46,6 +46,7 @@#define LPFC_MEM_POOL_SIZE 64/* max elem in non-DMA safety pool */ #define LPFC_DEVICE_DATA_POOL_SIZE 64/* max elements in device data pool */ #define LPFC_RRQ_POOL_SIZE 256/* max elements in non-DMA pool */ +#define LPFC_MBX_POOL_SIZE 256/* max elements in MBX non-DMA pool */ int lpfc_mem_alloc_active_rrq_pool_s4 (struct lpfc_hba *phba) {
@@ -111,8 +112,8 @@ lpfc_mem_alloc(struct lpfc_hba *phba, in pool->current_count++; } - phba->mbox_mem_pool =mempool_create_kmalloc_pool (LPFC_MEM_POOL_SIZE , -sizeof (LPFC_MBOXQ_t)); + phba->mbox_mem_pool =mempool_create_kmalloc_pool (LPFC_MBX_POOL_SIZE , +sizeof (LPFC_MBOXQ_t));if (!phba->mbox_mem_pool) goto fail_free_mbuf_pool;
drivers/scsi/lpfc/lpfc_nvme.c +13 -5
@@ -2280,6 +2280,8 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vint ret, i, pending =0 ;struct lpfc_sli_ring *pring;struct lpfc_hba *phba = vport->phba; +struct lpfc_sli4_hdw_queue *qp; +int abts_scsi, abts_nvme;/* Host transport has to clean up and confirm requiring an indefinite * wait. Print a message if a 10 second wait expires and renew the
@@ -2290,17 +2292,23 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_v ret =wait_for_completion_timeout (lport_unreg_cmp, wait_tmo);if (unlikely (!ret)) { pending =0 ; + abts_scsi =0 ; + abts_nvme =0 ;for (i =0 ; i < phba->cfg_hdw_queue; i++) { - pring = phba->sli4_hba.hdwq[i].io_wq->pring; + qp = &phba->sli4_hba.hdwq[i]; + pring = qp->io_wq->pring;if (!pring)continue ; -if (pring->txcmplq_cnt) - pending += pring->txcmplq_cnt; + pending += pring->txcmplq_cnt; + abts_scsi += qp->abts_scsi_io_bufs; + abts_nvme += qp->abts_nvme_io_bufs; }lpfc_printf_vlog (vport,KERN_ERR ,LOG_TRACE_EVENT ,"6176 Lport x%px Localport x%px wait " -"timed out. Pending %d. Renewing.\n" , - lport, vport->localport, pending); +"timed out. Pending %d [%d:%d]. " +"Renewing.\n" , + lport, vport->localport, pending, + abts_scsi, abts_nvme);continue ; }break ;
drivers/scsi/lpfc/lpfc_sli.c +52 -12
114 lines not on this page · raw message
drivers/scsi/lpfc/lpfc_sli4.h +3 -3
@@ -920,8 +920,9 @@ struct lpfc_sli4_hba {struct list_head sp_queue_event;struct list_head sp_cqe_event_pool;struct list_head sp_asynce_work_queue; -struct list_head sp_fcp_xri_aborted_work_queue; +spinlock_t asynce_list_lock;/* protect sp_asynce_work_queue list */ struct list_head sp_els_xri_aborted_work_queue; +spinlock_t els_xri_abrt_list_lock;/* protect els_xri_aborted list */ struct list_head sp_unsol_work_queue;struct lpfc_sli4_link link_state;struct lpfc_sli4_lnk_info lnk_info;
@@ -1103,8 +1104,7 @@ void lpfc_sli4_async_event_proc(struct lvoid lpfc_sli4_fcf_redisc_event_proc (struct lpfc_hba *);int lpfc_sli4_resume_rpi (struct lpfc_nodelist *,void (*)(struct lpfc_hba *,LPFC_MBOXQ_t *),void *); -void lpfc_sli4_fcp_xri_abort_event_proc (struct lpfc_hba *); -void lpfc_sli4_els_xri_abort_event_proc (struct lpfc_hba *); +void lpfc_sli4_els_xri_abort_event_proc (struct lpfc_hba *phba);void lpfc_sli4_nvme_xri_aborted (struct lpfc_hba *phba,struct sli4_wcqe_xri_aborted *axri,struct lpfc_io_buf *lpfc_ncmd);
Greg Kroah-Hartman
maintainerPATCH 672/717 scsi: lpfc: Re-fix use after free in lpfc_rq_buf_free()
In reply to Greg Kroah-HartmanFrom: James Smart <[email protected]>
commit e5785d3ec32f5f44dd88cd7b398e496742630469 upstream.
Commit 9816ef6ecbc1 ("scsi: lpfc: Use after free in lpfc_rq_buf_free()") was made to correct a use after free condition in lpfc_rq_buf_free(). Unfortunately, a subsequent patch cut on a tree without the fix inadvertently reverted the fix.
Put the fix back: Move the freeing of the rqb_entry to after the print function that references it.
--- drivers/scsi/lpfc/lpfc_mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/lpfc/lpfc_mem.c +1 -1
@@ -721,7 +721,6 @@ lpfc_rq_buf_free(struct lpfc_hba *phba, drqe.address_hi =putPaddrHigh (rqb_entry->dbuf.phys); rc =lpfc_sli4_rq_put (rqb_entry->hrq, rqb_entry->drq, &hrqe, &drqe);if (rc <0 ) { - (rqbp->rqb_free_buffer)(phba, rqb_entry); lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "6409 Cannot post to HRQ %d: %x %x %x " "DRQ %x %x\n",
@@ -731,6 +730,7 @@ lpfc_rq_buf_free(struct lpfc_hba *phba, rqb_entry->hrq->entry_count, rqb_entry->drq->host_index, rqb_entry->drq->hba_index); + (rqbp->rqb_free_buffer)(phba, rqb_entry); }else {list_add_tail (&rqb_entry->hbuf.list, &rqbp->rqb_buffer_list); rqbp->buffer_count++;
Greg Kroah-Hartman
maintainerPATCH 673/717 openat2: reject RESOLVE_BENEATH|RESOLVE_IN_ROOT
In reply to Greg Kroah-HartmanFrom: Aleksa Sarai <[email protected]>
commit 398840f8bb935d33c64df4ec4fed77a7d24c267d upstream.
This was an oversight in the original implementation, as it makes no sense to specify both scoping flags to the same openat2(2) invocation (before this patch, the result of such an invocation was equivalent to RESOLVE_IN_ROOT being ignored).
This is a userspace-visible ABI change, but the only user of openat2(2) at the moment is LXC which doesn't specify both flags and so no userspace programs will break as a result.
--- fs/open.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/open.c +4 -0
@@ -1010,6 +1010,10 @@ inline int build_open_flags(const structif (how->resolve & ~VALID_RESOLVE_FLAGS )return -EINVAL ; +/* Scoping flags are mutually exclusive. */ +if ((how->resolve &RESOLVE_BENEATH ) && (how->resolve &RESOLVE_IN_ROOT )) +return -EINVAL ; +/* Deal with the mode. */ if (WILL_CREATE (flags)) {if (how->mode & ~S_IALLUGO )
Greg Kroah-Hartman
maintainerPATCH 674/717 iio: buffer: Fix demux update
In reply to Greg Kroah-HartmanFrom: Nuno Sá <[email protected]>
commit 19ef7b70ca9487773c29b449adf0c70f540a0aab upstream.
When updating the buffer demux, we will skip a scan element from the device in the case in_ind != out_ind and we enter the while loop. in_ind should only be refreshed with find_next_bit() in the end of the loop.
Note, to cause problems we need a situation where we are skippig over an element (channel not enabled) that happens to not have the same size
as the next element. Whilst this is a possible situation we haven't
actually identified any cases in mainline where it happens as most drivers have consistent channel storage sizes with the exception of the timestamp which is the last element and hence never skipped over.
--- drivers/iio/industrialio-buffer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/iio/industrialio-buffer.c +3 -3
@@ -865,12 +865,12 @@ static int iio_buffer_update_demux(struc indio_dev->masklength, in_ind + 1);while (in_ind != out_ind) { - in_ind =find_next_bit (indio_dev->active_scan_mask, - indio_dev->masklength, - in_ind +1 ); length =iio_storage_bytes_for_si (indio_dev, in_ind);/* Make sure we are aligned */ in_loc =roundup (in_loc, length) + length; + in_ind =find_next_bit (indio_dev->active_scan_mask, + indio_dev->masklength, + in_ind +1 ); } length =iio_storage_bytes_for_si (indio_dev, in_ind); out_loc =roundup (out_loc, length);
Greg Kroah-Hartman
maintainerPATCH 675/717 iio: adc: rockchip_saradc: fix missing clk_disable_unprepare() on error in rockchip_saradc_resume
In reply to Greg Kroah-HartmanFrom: Qinglang Miao <[email protected]>
commit 560c6b914c6ec7d9d9a69fddbb5bf3bf71433e8b upstream.
Fix the missing clk_disable_unprepare() of info->pclk before return from rockchip_saradc_resume in the error handling case when fails to prepare and enable info->clk.
--- drivers/iio/adc/rockchip_saradc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iio/adc/rockchip_saradc.c +1 -1
@@ -462,7 +462,7 @@ static int rockchip_saradc_resume(struct ret =clk_prepare_enable (info->clk);if (ret) -return ret; +clk_disable_unprepare (info->pclk);return ret; }
Greg Kroah-Hartman
maintainerPATCH 676/717 iio: imu: st_lsm6dsx: fix edge-trigger interrupts
In reply to Greg Kroah-HartmanFrom: Lorenzo Bianconi <[email protected]>
commit 3f9bce7a22a3f8ac9d885c9d75bc45569f24ac8b upstream.
If we are using edge IRQs, new samples can arrive while processing current interrupt since there are no hw guarantees the irq line stays "low" long enough to properly detect the new interrupt. In this case the new sample will be missed.
Polling FIFO status register in st_lsm6dsx_handler_thread routine allow us to read new samples even if the interrupt arrives while processing previous data and the timeslot where the line is "low" is too short to be properly detected.
--- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-)
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +21 -5
@@ -2255,19 +2255,35 @@ st_lsm6dsx_report_motion_event(struct ststatic irqreturn_t st_lsm6dsx_handler_thread (int irq,void *private) {struct st_lsm6dsx_hw *hw = private; +int fifo_len =0 , len;bool event; -int count; event =st_lsm6dsx_report_motion_event (hw);if (!hw->settings->fifo_ops.read_fifo)return event ?IRQ_HANDLED :IRQ_NONE ; -mutex_lock (&hw->fifo_lock); - count = hw->settings->fifo_ops.read_fifo (hw); -mutex_unlock (&hw->fifo_lock); +/* +* If we are using edge IRQs, new samples can arrive while +* processing current interrupt since there are no hw +* guarantees the irq line stays "low" long enough to properly +* detect the new interrupt. In this case the new sample will +* be missed. +* Polling FIFO status register allow us to read new +* samples even if the interrupt arrives while processing +* previous data and the timeslot where the line is "low" is +* too short to be properly detected. +*/ +do { +mutex_lock (&hw->fifo_lock); + len = hw->settings->fifo_ops.read_fifo (hw); +mutex_unlock (&hw->fifo_lock); -return count || event ?IRQ_HANDLED :IRQ_NONE ; +if (len >0 ) + fifo_len += len; + }while (len >0 ); + +return fifo_len || event ?IRQ_HANDLED :IRQ_NONE ; }static int st_lsm6dsx_irq_setup (struct st_lsm6dsx_hw *hw)
Greg Kroah-Hartman
maintainerPATCH 677/717 iio:light:rpr0521: Fix timestamp alignment and prevent data leak.
In reply to Greg Kroah-HartmanFrom: Jonathan Cameron <[email protected]>
commit a61817216bcc755eabbcb1cf281d84ccad267ed1 upstream.
One of a class of bugs pointed out by Lars in a recent review. iio_push_to_buffers_with_timestamp() assumes the buffer used is aligned to the size of the timestamp (8 bytes). This is not guaranteed in this driver which uses an array of smaller elements on the stack. As Lars also noted this anti pattern can involve a leak of data to userspace and that indeed can happen here. We close both issues by moving to a suitable structure in the iio_priv().
This data is allocated with kzalloc() so no data can leak apart from previous readings and in this case the status byte from the device.
The forced alignment of ts is not necessary in this case but it potentially makes the code less fragile.
Quoted 1 line
From personal communications with Mikko:
We could probably split the reading of the int register, but it would mean a significant performance cost of 20 i2c clock cycles.
--- drivers/iio/light/rpr0521.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
drivers/iio/light/rpr0521.c +13 -4
@@ -194,6 +194,17 @@ struct rpr0521_data {bool pxs_need_dis;struct regmap *regmap; + +/* +* Ensure correct naturally aligned timestamp. +* Note that the read will put garbage data into +* the padding but this should not be a problem +*/ +struct { +__le16 channels[3 ]; +u8 garbage; +s64 ts__aligned(8) ; + } scan; }; static IIO_CONST_ATTR(in_intensity_scale_available, RPR0521_ALS_SCALE_AVAIL);
@@ -449,8 +460,6 @@ static irqreturn_t rpr0521_trigger_consustruct rpr0521_data *data =iio_priv (indio_dev);int err; -u8 buffer[16 ];/* 3 16-bit channels + padding + ts */ -/* Use irq timestamp when reasonable. */ if (iio_trigger_using_own (indio_dev) && data->irq_timestamp) { pf->timestamp = data->irq_timestamp;
@@ -461,11 +470,11 @@ static irqreturn_t rpr0521_trigger_consu pf->timestamp =iio_get_time_ns (indio_dev); err =regmap_bulk_read (data->regmap,RPR0521_REG_PXS_DATA , - &buffer, + data->scan.channels, (3 *2 ) +1 );/* 3 * 16-bit + (discarded) int clear reg. */ if (!err)iio_push_to_buffers_with_timestamp (indio_dev, - buffer, pf->timestamp); + &data->scan, pf->timestamp);else dev_err (&data->client->dev,"Trigger consumer can't read from sensor.\n" );
Greg Kroah-Hartman
maintainerPATCH 678/717 iio:light:st_uvis25: Fix timestamp alignment and prevent data leak.
In reply to Greg Kroah-HartmanFrom: Jonathan Cameron <[email protected]>
commit d837a996f57c29a985177bc03b0e599082047f27 upstream.
One of a class of bugs pointed out by Lars in a recent review. iio_push_to_buffers_with_timestamp() assumes the buffer used is aligned to the size of the timestamp (8 bytes). This is not guaranteed in this driver which uses an array of smaller elements on the stack. As Lars also noted this anti pattern can involve a leak of data to userspace and that indeed can happen here. We close both issues by moving to a suitable structure in the iio_priv()
This data is allocated with kzalloc() so no data can leak apart from previous readings.
A local unsigned int variable is used for the regmap call so it is clear there is no potential issue with writing into the padding of the structure.
--- drivers/iio/light/st_uvis25.h | 5 +++++ drivers/iio/light/st_uvis25_core.c | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-)
drivers/iio/light/st_uvis25.h +5 -0
@@ -27,6 +27,11 @@ struct st_uvis25_hw {struct iio_trigger *trig;bool enabled;int irq; +/* Ensure timestamp is naturally aligned */ +struct { +u8 chan; +s64 ts__aligned(8) ; + } scan; };extern const struct dev_pm_ops st_uvis25_pm_ops;
drivers/iio/light/st_uvis25_core.c +5 -3
@@ -232,17 +232,19 @@ static const struct iio_buffer_setup_opsstatic irqreturn_t st_uvis25_buffer_handler_thread (int irq,void *p) { -u8 buffer[ALIGN (sizeof (u8),sizeof (s64)) +sizeof (s64)];struct iio_poll_func *pf = p;struct iio_dev *iio_dev = pf->indio_dev;struct st_uvis25_hw *hw =iio_priv (iio_dev); +unsigned int val;int err; - err =regmap_read (hw->regmap,ST_UVIS25_REG_OUT_ADDR , (int *)buffer); + err =regmap_read (hw->regmap,ST_UVIS25_REG_OUT_ADDR , &val);if (err <0 ) goto out; -iio_push_to_buffers_with_timestamp (iio_dev, buffer, + hw->scan.chan = val; + +iio_push_to_buffers_with_timestamp (iio_dev, &hw->scan,iio_get_time_ns (iio_dev)); out:
Greg Kroah-Hartman
maintainerPATCH 679/717 iio:magnetometer:mag3110: Fix alignment and data leak issues.
In reply to Greg Kroah-HartmanFrom: Jonathan Cameron <[email protected]>
commit 89deb1334252ea4a8491d47654811e28b0790364 upstream.
One of a class of bugs pointed out by Lars in a recent review. iio_push_to_buffers_with_timestamp() assumes the buffer used is aligned to the size of the timestamp (8 bytes). This is not guaranteed in this driver which uses an array of smaller elements on the stack. As Lars also noted this anti pattern can involve a leak of data to userspace and that indeed can happen here. We close both issues by moving to a suitable structure in the iio_priv() data.
This data is allocated with kzalloc() so no data can leak apart from previous readings.
The explicit alignment of ts is not necessary in this case but does make the code slightly less fragile so I have included it.
--- drivers/iio/magnetometer/mag3110.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/iio/magnetometer/mag3110.c +9 -4
@@ -56,6 +56,12 @@ struct mag3110_data {int sleep_val;struct regulator *vdd_reg;struct regulator *vddio_reg; +/* Ensure natural alignment of timestamp */ +struct { +__be16 channels[3 ]; +u8 temperature; +s64 ts__aligned(8) ; + } scan; };static int mag3110_request (struct mag3110_data *data)
@@ -387,10 +393,9 @@ static irqreturn_t mag3110_trigger_handlstruct iio_poll_func *pf = p;struct iio_dev *indio_dev = pf->indio_dev;struct mag3110_data *data =iio_priv (indio_dev); -u8 buffer[16 ];/* 3 16-bit channels + 1 byte temp + padding + ts */ int ret; - ret =mag3110_read (data, (__be16 *) buffer); + ret =mag3110_read (data, data->scan.channels);if (ret <0 ) goto done;
@@ -399,10 +404,10 @@ static irqreturn_t mag3110_trigger_handl MAG3110_DIE_TEMP);if (ret <0 ) goto done; - buffer[6 ] = ret; + data->scan.temperature = ret; } -iio_push_to_buffers_with_timestamp (indio_dev, buffer, +iio_push_to_buffers_with_timestamp (indio_dev, &data->scan,iio_get_time_ns (indio_dev)); done:
Greg Kroah-Hartman
maintainerPATCH 680/717 iio:pressure:mpl3115: Force alignment of buffer
In reply to Greg Kroah-HartmanFrom: Jonathan Cameron <[email protected]>
commit 198cf32f0503d2ad60d320b95ef6fb8243db857f upstream.
Whilst this is another case of the issue Lars reported with an array of elements of smaller than 8 bytes being passed to iio_push_to_buffers_with_timestamp(), the solution here is a bit different from the other cases and relies on __aligned working on the stack (true since 4.6?)
This one is unusual. We have to do an explicit memset() each time as we are reading 3 bytes into a potential 4 byte channel which may sometimes be a 2 byte channel depending on what is enabled. As such, moving the buffer to the heap in the iio_priv structure doesn't save us much. We can't use a nice explicit structure on the stack either as the data channels have different storage sizes and are all separately controlled.
--- drivers/iio/pressure/mpl3115.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/iio/pressure/mpl3115.c +8 -1
@@ -144,7 +144,14 @@ static irqreturn_t mpl3115_trigger_handlstruct iio_poll_func *pf = p;struct iio_dev *indio_dev = pf->indio_dev;struct mpl3115_data *data =iio_priv (indio_dev); -u8 buffer[16 ];/* 32-bit channel + 16-bit channel + padding + ts */ +/* +* 32-bit channel + 16-bit channel + padding + ts +* Note that it is possible for only one of the first 2 +* channels to be enabled. If that happens, the first element +* of the buffer may be either 16 or 32-bits. As such we cannot +* use a simple structure definition to express this data layout. +*/ +u8 buffer[16 ]__aligned(8) ;int ret, pos =0 ;mutex_lock (&data->lock);
Greg Kroah-Hartman
maintainerPATCH 681/717 iio:imu:bmi160: Fix too large a buffer.
In reply to Greg Kroah-HartmanFrom: Jonathan Cameron <[email protected]>
commit dc7de42d6b50a07b37feeba4c6b5136290fcee81 upstream.
The comment implies this device has 3 sensor types, but it only has an accelerometer and a gyroscope (both 3D). As such the buffer does not need to be as long as stated.
Note I've separated this from the following patch which fixes the alignment for passing to iio_push_to_buffers_with_timestamp() as they are different issues even if they affect the same line of code.
--- drivers/iio/imu/bmi160/bmi160_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/iio/imu/bmi160/bmi160_core.c +2 -2
@@ -427,8 +427,8 @@ static irqreturn_t bmi160_trigger_handlestruct iio_poll_func *pf = p;struct iio_dev *indio_dev = pf->indio_dev;struct bmi160_data *data =iio_priv (indio_dev); -__le16 buf[16 ]; -/* 3 sens x 3 axis x __le16 + 3 x __le16 pad + 4 x __le16 tstamp */ +__le16 buf[12 ]; +/* 2 sens x 3 axis x __le16 + 2 x __le16 pad + 4 x __le16 tstamp */ int i, ret, j =0 , base =BMI160_REG_DATA_MAGN_XOUT_L ;__le16 sample;
Greg Kroah-Hartman
maintainerPATCH 682/717 iio:imu:bmi160: Fix alignment and data leak issues
In reply to Greg Kroah-HartmanFrom: Jonathan Cameron <[email protected]>
commit 7b6b51234df6cd8b04fe736b0b89c25612d896b8 upstream.
One of a class of bugs pointed out by Lars in a recent review. iio_push_to_buffers_with_timestamp assumes the buffer used is aligned to the size of the timestamp (8 bytes). This is not guaranteed in this driver which uses an array of smaller elements on the stack. As Lars also noted this anti pattern can involve a leak of data to userspace and that indeed can happen here. We close both issues by moving to a suitable array in the iio_priv() data with alignment explicitly requested. This data is allocated with kzalloc() so no data can leak apart from previous readings.
In this driver, depending on which channels are enabled, the timestamp can be in a number of locations. Hence we cannot use a structure to specify the data layout without it being misleading.
--- drivers/iio/imu/bmi160/bmi160.h | 7 +++++++ drivers/iio/imu/bmi160/bmi160_core.c | 6 ++---- 2 files changed, 9 insertions(+), 4 deletions(-)
drivers/iio/imu/bmi160/bmi160.h +7 -0
@@ -10,6 +10,13 @@ struct bmi160_data {struct iio_trigger *trig;struct regulator_bulk_data supplies[2 ];struct iio_mount_matrix orientation; +/* +* Ensure natural alignment for timestamp if present. +* Max length needed: 2 * 3 channels + 4 bytes padding + 8 byte ts. +* If fewer channels are enabled, less space may be needed, as +* long as the timestamp is still aligned to 8 bytes. +*/ +__le16 buf[12 ]__aligned(8) ; };extern const struct regmap_config bmi160_regmap_config;
drivers/iio/imu/bmi160/bmi160_core.c +2 -4
@@ -427,8 +427,6 @@ static irqreturn_t bmi160_trigger_handlestruct iio_poll_func *pf = p;struct iio_dev *indio_dev = pf->indio_dev;struct bmi160_data *data =iio_priv (indio_dev); -__le16 buf[12 ]; -/* 2 sens x 3 axis x __le16 + 2 x __le16 pad + 4 x __le16 tstamp */ int i, ret, j =0 , base =BMI160_REG_DATA_MAGN_XOUT_L ;__le16 sample;
@@ -438,10 +436,10 @@ static irqreturn_t bmi160_trigger_handle &sample, sizeof(sample));if (ret) goto done; - buf[j++] = sample; + data->buf[j++] = sample; } -iio_push_to_buffers_with_timestamp (indio_dev, buf, pf->timestamp); +iio_push_to_buffers_with_timestamp (indio_dev, data->buf, pf->timestamp); done:iio_trigger_notify_done (indio_dev->trig);return IRQ_HANDLED ;
Greg Kroah-Hartman
maintainerPATCH 683/717 iio:adc:ti-ads124s08: Fix buffer being too long.
In reply to Greg Kroah-HartmanFrom: Jonathan Cameron <[email protected]>
commit b0bd27f02d768e3a861c4e6c27f8e369720e6c25 upstream.
The buffer is expressed as a u32 array, yet the extra space for the s64 timestamp was expressed as sizeof(s64)/sizeof(u16). This will result in 2 extra u32 elements.
Fix by dividing by sizeof(u32).
--- drivers/iio/adc/ti-ads124s08.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iio/adc/ti-ads124s08.c +1 -1
@@ -269,7 +269,7 @@ static irqreturn_t ads124s_trigger_handlstruct iio_poll_func *pf = p;struct iio_dev *indio_dev = pf->indio_dev;struct ads124s_private *priv =iio_priv (indio_dev); -u32 buffer[ADS124S08_MAX_CHANNELS +sizeof (s64)/sizeof (u16)]; +u32 buffer[ADS124S08_MAX_CHANNELS +sizeof (s64)/sizeof (u32)];int scan_index, j =0 ;int ret;
Greg Kroah-Hartman
maintainerPATCH 684/717 iio:adc:ti-ads124s08: Fix alignment and data leak issues.
In reply to Greg Kroah-HartmanFrom: Jonathan Cameron <[email protected]>
commit 1e405bc2512f80a903ddd6ba8740cee885238d7f upstream.
One of a class of bugs pointed out by Lars in a recent review. iio_push_to_buffers_with_timestamp() assumes the buffer used is aligned to the size of the timestamp (8 bytes). This is not guaranteed in this driver which uses an array of smaller elements on the stack. As Lars also noted this anti pattern can involve a leak of data to userspace and that indeed can happen here. We close both issues by moving to a suitable structure in the iio_priv() data with alignment explicitly requested. This data is allocated with kzalloc() so no data can leak apart from previous readings.
In this driver the timestamp can end up in various different locations depending on what other channels are enabled. As a result, we don't use a structure to specify it's position as that would be misleading.
--- drivers/iio/adc/ti-ads124s08.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
drivers/iio/adc/ti-ads124s08.c +10 -3
@@ -99,6 +99,14 @@ struct ads124s_private {struct gpio_desc *reset_gpio;struct spi_device *spi;struct mutex lock; +/* +* Used to correctly align data. +* Ensure timestamp is naturally aligned. +* Note that the full buffer length may not be needed if not +* all channels are enabled, as long as the alignment of the +* timestamp is maintained. +*/ +u32 buffer[ADS124S08_MAX_CHANNELS +sizeof (s64)/sizeof (u32)]__aligned(8) ;u8 data[5 ]____cacheline_aligned ; };
@@ -269,7 +277,6 @@ static irqreturn_t ads124s_trigger_handlstruct iio_poll_func *pf = p;struct iio_dev *indio_dev = pf->indio_dev;struct ads124s_private *priv =iio_priv (indio_dev); -u32 buffer[ADS124S08_MAX_CHANNELS +sizeof (s64)/sizeof (u32)];int scan_index, j =0 ;int ret;
@@ -284,7 +291,7 @@ static irqreturn_t ads124s_trigger_handlif (ret)dev_err (&priv->spi->dev,"Start ADC conversions failed\n" ); - buffer[j] =ads124s_read (indio_dev, scan_index); + priv->buffer[j] =ads124s_read (indio_dev, scan_index); ret =ads124s_write_cmd (indio_dev,ADS124S08_STOP_CONV );if (ret)dev_err (&priv->spi->dev,"Stop ADC conversions failed\n" );
@@ -292,7 +299,7 @@ static irqreturn_t ads124s_trigger_handl j++; } -iio_push_to_buffers_with_timestamp (indio_dev, buffer, +iio_push_to_buffers_with_timestamp (indio_dev, priv->buffer, pf->timestamp);iio_trigger_notify_done (indio_dev->trig);
Greg Kroah-Hartman
maintainerPATCH 685/717 md/cluster: block reshape with remote resync job
In reply to Greg Kroah-HartmanFrom: Zhao Heming <[email protected]>
commit a8da01f79c89755fad55ed0ea96e8d2103242a72 upstream.
Reshape request should be blocked with ongoing resync job. In cluster env, a node can start resync job even if the resync cmd isn't executed on it, e.g., user executes "mdadm --grow" on node A, sometimes node B will start resync job. However, current update_raid_disks() only check local recovery status, which is incomplete. As a result, we see user will execute "mdadm --grow" successfully on local, while the remote node deny to do reshape job when it doing resync job. The inconsistent handling cause array enter unexpected status. If user doesn't observe this issue and continue executing mdadm cmd, the array doesn't work at last.
Fix this issue by blocking reshape request. When node executes "--grow" and detects ongoing resync, it should stop and report error to user.
The following script reproduces the issue with ~100% probability. (two nodes share 3 iSCSI luns: sdg/sdh/sdi. Each lun size is 1GB)
```
# on node1, node2 is the remote node.
ssh root@node2 "mdadm -S --scan"
mdadm -S --scan
for i in {g,h,i};do dd if=/dev/zero of=/dev/sd$i oflag=direct bs=1M \
count=20; done
mdadm -C /dev/md0 -b clustered -e 1.2 -n 2 -l mirror /dev/sdg /dev/sdh
ssh root@node2 "mdadm -A /dev/md0 /dev/sdg /dev/sdh"
sleep 5
mdadm --manage --add /dev/md0 /dev/sdi
mdadm --wait /dev/md0
mdadm --grow --raid-devices=3 /dev/md0
mdadm /dev/md0 --fail /dev/sdg
mdadm /dev/md0 --remove /dev/sdg
mdadm --grow --raid-devices=2 /dev/md0
```--- drivers/md/md.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/md/md.c +6 -2
@@ -7278,6 +7278,7 @@ static int update_raid_disks(struct mddereturn -EINVAL ;if (mddev->sync_thread ||test_bit (MD_RECOVERY_RUNNING , &mddev->recovery) || +test_bit (MD_RESYNCING_REMOTE , &mddev->recovery) || mddev->reshape_position != MaxSector)return -EBUSY ;
@@ -9645,8 +9646,11 @@ static void check_sb_changes(struct mdde } } -if (mddev->raid_disks !=le32_to_cpu (sb->raid_disks)) -update_raid_disks (mddev,le32_to_cpu (sb->raid_disks)); +if (mddev->raid_disks !=le32_to_cpu (sb->raid_disks)) { + ret =update_raid_disks (mddev,le32_to_cpu (sb->raid_disks)); +if (ret) +pr_warn ("md: updating array disks failed. %d\n" , ret); + }/* * Since mddev->delta_disks has already updated in update_raid_disks,
Greg Kroah-Hartman
maintainerPATCH 686/717 md/cluster: fix deadlock when node is doing resync job
In reply to Greg Kroah-HartmanFrom: Zhao Heming <[email protected]>
commit bca5b0658020be90b6b504ca514fd80110204f71 upstream.
md-cluster uses MD_CLUSTER_SEND_LOCK to make node can exclusively send msg. During sending msg, node can concurrently receive msg from another node. When node does resync job, grab token_lockres:EX may trigger a deadlock:
```
nodeA nodeB
-------------------- --------------------
a.
send METADATA_UPDATED
held token_lockres:EX
b.
md_do_sync
resync_info_update
send RESYNCING
+ set MD_CLUSTER_SEND_LOCK
+ wait for holding token_lockres:EX
c.
mdadm /dev/md0 --remove /dev/sdg
+ held reconfig_mutex
+ send REMOVE
+ wait_event(MD_CLUSTER_SEND_LOCK)
d.
recv_daemon //METADATA_UPDATED from A
process_metadata_update
+ (mddev_trylock(mddev) ||
MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD)
//this time, both return false forever
```Explaination:
a. A send METADATA_UPDATED
This will block another node to send msg
b. B does sync jobs, which will send RESYNCING at intervals.
This will be block for holding token_lockres:EX lock.
c. B do "mdadm --remove", which will send REMOVE.
This will be blocked by step <b>: MD_CLUSTER_SEND_LOCK is 1.
d. B recv METADATA_UPDATED msg, which send from A in step <a>.
This will be blocked by step <c>: holding mddev lock, it makes wait_event can't hold mddev lock. (btw, MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD keep ZERO in this scenario.)
There is a similar deadlock in commit 0ba959774e93 ("md-cluster: use sync way to handle METADATA_UPDATED msg") In that commit, step c is "update sb". This patch step c is "mdadm --remove".
For fixing this issue, we can refer the solution of function:metadata_update_start. Which does the same grab lock_token action. lock_comm can use the same steps to avoid deadlock. By moving MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD from lock_token to lock_comm. It enlarge a little bit window of MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, but it is safe & can break deadlock.
Repro steps (I only triggered 3 times with hundreds tests):
two nodes share 3 iSCSI luns: sdg/sdh/sdi. Each lun size is 1GB.
```
ssh root@node2 "mdadm -S --scan"
mdadm -S --scan
for i in {g,h,i};do dd if=/dev/zero of=/dev/sd$i oflag=direct bs=1M \
count=20; done
mdadm -C /dev/md0 -b clustered -e 1.2 -n 2 -l mirror /dev/sdg /dev/sdh \
--bitmap-chunk=1M
ssh root@node2 "mdadm -A /dev/md0 /dev/sdg /dev/sdh"
sleep 5
mkfs.xfs /dev/md0
mdadm --manage --add /dev/md0 /dev/sdi
mdadm --wait /dev/md0
mdadm --grow --raid-devices=3 /dev/md0
mdadm /dev/md0 --fail /dev/sdg
mdadm /dev/md0 --remove /dev/sdg
mdadm --grow --raid-devices=2 /dev/md0
```test script will hung when executing "mdadm --remove".
``` # dump stacks by "echo t > /proc/sysrq-trigger" md0_cluster_rec D 0 5329 2 0x80004000 Call Trace: __schedule+0x1f6/0x560 ? _cond_resched+0x2d/0x40 ? schedule+0x4a/0xb0 ? process_metadata_update.isra.0+0xdb/0x140 [md_cluster] ? wait_woken+0x80/0x80 ? process_recvd_msg+0x113/0x1d0 [md_cluster] ? recv_daemon+0x9e/0x120 [md_cluster] ? md_thread+0x94/0x160 [md_mod] ? wait_woken+0x80/0x80 ? md_congested+0x30/0x30 [md_mod] ? kthread+0x115/0x140 ? __kthread_bind_mask+0x60/0x60 ? ret_from_fork+0x1f/0x40 mdadm D 0 5423 1 0x00004004 Call Trace: __schedule+0x1f6/0x560 ? __schedule+0x1fe/0x560 ? schedule+0x4a/0xb0 ? lock_comm.isra.0+0x7b/0xb0 [md_cluster] ? wait_woken+0x80/0x80 ? remove_disk+0x4f/0x90 [md_cluster] ? hot_remove_disk+0xb1/0x1b0 [md_mod] ? md_ioctl+0x50c/0xba0 [md_mod] ? wait_woken+0x80/0x80 ? blkdev_ioctl+0xa2/0x2a0 ? block_ioctl+0x39/0x40 ? ksys_ioctl+0x82/0xc0 ? __x64_sys_ioctl+0x16/0x20 ? do_syscall_64+0x5f/0x150 ? entry_SYSCALL_64_after_hwframe+0x44/0xa9 md0_resync D 0 5425 2 0x80004000 Call Trace: __schedule+0x1f6/0x560 ? schedule+0x4a/0xb0 ? dlm_lock_sync+0xa1/0xd0 [md_cluster] ? wait_woken+0x80/0x80 ? lock_token+0x2d/0x90 [md_cluster] ? resync_info_update+0x95/0x100 [md_cluster] ? raid1_sync_request+0x7d3/0xa40 [raid1] ? md_do_sync.cold+0x737/0xc8f [md_mod] ? md_thread+0x94/0x160 [md_mod] ? md_congested+0x30/0x30 [md_mod] ? kthread+0x115/0x140 ? __kthread_bind_mask+0x60/0x60 ? ret_from_fork+0x1f/0x40 ```
At last, thanks for Xiao's solution.
--- drivers/md/md-cluster.c | 67 +++++++++++++++++++++++++++--------------------- drivers/md/md.c | 6 ++-- 2 files changed, 42 insertions(+), 31 deletions(-)
drivers/md/md-cluster.c +38 -29
@@ -664,9 +664,27 @@ out:* Takes the lock on the TOKEN lock resource so no other * node can communicate while the operation is underway. */ -static int lock_token (struct md_cluster_info *cinfo,bool mddev_locked) +static int lock_token (struct md_cluster_info *cinfo) { -int error, set_bit =0 ; +int error; + + error =dlm_lock_sync (cinfo->token_lockres,DLM_LOCK_EX ); +if (error) { +pr_err ("md-cluster(%s:%d): failed to get EX on TOKEN (%d)\n" , + __func__, __LINE__, error); + }else { +/* Lock the receive sequence */ +mutex_lock (&cinfo->recv_mutex); + } +return error; +} + +/* lock_comm() +* Sets the MD_CLUSTER_SEND_LOCK bit to lock the send channel. +*/ +static int lock_comm (struct md_cluster_info *cinfo,bool mddev_locked) +{ +int rv, set_bit =0 ;struct mddev *mddev = cinfo->mddev;/*
@@ -677,34 +695,19 @@ static int lock_token(struct md_cluster_*/ if (mddev_locked && !test_bit (MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD , &cinfo->state)) { - error =test_and_set_bit_lock (MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD , + rv =test_and_set_bit_lock (MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD , &cinfo->state); -WARN_ON_ONCE (error); +WARN_ON_ONCE (rv);md_wakeup_thread (mddev->thread); set_bit =1 ; } - error =dlm_lock_sync (cinfo->token_lockres,DLM_LOCK_EX ); -if (set_bit) -clear_bit_unlock (MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD , &cinfo->state); -if (error) -pr_err ("md-cluster(%s:%d): failed to get EX on TOKEN (%d)\n" , - __func__, __LINE__, error); - -/* Lock the receive sequence */ -mutex_lock (&cinfo->recv_mutex); -return error; -} - -/* lock_comm() -* Sets the MD_CLUSTER_SEND_LOCK bit to lock the send channel. -*/ -static int lock_comm (struct md_cluster_info *cinfo,bool mddev_locked) -{wait_event (cinfo->wait, !test_and_set_bit (MD_CLUSTER_SEND_LOCK , &cinfo->state)); - -return lock_token (cinfo, mddev_locked); + rv =lock_token (cinfo); +if (set_bit) +clear_bit_unlock (MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD , &cinfo->state); +return rv; }static void unlock_comm (struct md_cluster_info *cinfo)
@@ -784,9 +787,11 @@ static int sendmsg(struct md_cluster_inf {int ret; -lock_comm (cinfo, mddev_locked); - ret =__sendmsg (cinfo, cmsg); -unlock_comm (cinfo); + ret =lock_comm (cinfo, mddev_locked); +if (!ret) { + ret =__sendmsg (cinfo, cmsg); +unlock_comm (cinfo); + }return ret; }
@@ -1061,7 +1066,7 @@ static int metadata_update_start(structreturn 0 ; } - ret =lock_token (cinfo,1 ); + ret =lock_token (cinfo);clear_bit_unlock (MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD , &cinfo->state);return ret; }
@@ -1255,7 +1260,10 @@ static void update_size(struct mddev *mdint raid_slot =-1 ;md_update_sb (mddev,1 ); -lock_comm (cinfo,1 ); +if (lock_comm (cinfo,1 )) { +pr_err ("%s: lock_comm failed\n" , __func__); +return ; + }memset (&cmsg,0 ,sizeof (cmsg)); cmsg.type =cpu_to_le32 (METADATA_UPDATED );
@@ -1407,7 +1415,8 @@ static int add_new_disk(struct mddev *md cmsg.type =cpu_to_le32 (NEWDISK );memcpy (cmsg.uuid, uuid,16 ); cmsg.raid_slot =cpu_to_le32 (rdev->desc_nr); -lock_comm (cinfo,1 ); +if (lock_comm (cinfo,1 )) +return -EAGAIN ; ret =__sendmsg (cinfo, &cmsg);if (ret) {unlock_comm (cinfo);
drivers/md/md.c +4 -2
@@ -6948,8 +6948,10 @@ static int hot_remove_disk(struct mddev goto busy; kick_rdev: -if (mddev_is_clustered (mddev)) - md_cluster_ops->remove_disk (mddev, rdev); +if (mddev_is_clustered (mddev)) { +if (md_cluster_ops->remove_disk (mddev, rdev)) + goto busy; + }md_kick_rdev_from_array (rdev);set_bit (MD_SB_CHANGE_DEVS , &mddev->sb_flags);
Greg Kroah-Hartman
maintainerPATCH 687/717 pinctrl: sunxi: Always call chained_irq_{enter, exit} in sunxi_pinctrl_irq_handler
In reply to Greg Kroah-HartmanFrom: Yangtao Li <[email protected]>
commit a1158e36f876f6269978a4176e3a1d48d27fe7a1 upstream.
It is found on many allwinner soc that there is a low probability that the interrupt status cannot be read in sunxi_pinctrl_irq_handler. This will cause the interrupt status of a gpio bank to always be active on gic, preventing gic from responding to other spi interrupts correctly.
So we should call the chained_irq_* each time enter sunxi_pinctrl_irq_handler().
--- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/pinctrl/sunxi/pinctrl-sunxi.c +4 -2
@@ -1142,20 +1142,22 @@ static void sunxi_pinctrl_irq_handler(stif (bank == pctl->desc->irq_banks)return ; +chained_irq_enter (chip, desc); + reg =sunxi_irq_status_reg_from_bank (pctl->desc, bank); val =readl (pctl->membase + reg);if (val) {int irqoffset; -chained_irq_enter (chip, desc);for_each_set_bit (irqoffset, &val,IRQ_PER_BANK ) {int pin_irq =irq_find_mapping (pctl->domain, bank *IRQ_PER_BANK + irqoffset);generic_handle_irq (pin_irq); } -chained_irq_exit (chip, desc); } + +chained_irq_exit (chip, desc); } static int sunxi_pinctrl_add_function(struct sunxi_pinctrl *pctl,
Greg Kroah-Hartman
maintainerPATCH 688/717 clk: ingenic: Fix divider calculation with div tables
In reply to Greg Kroah-HartmanFrom: Paul Cercueil <[email protected]>
commit 11a163f2c7d6a9f27ce144cd7e367a81c851621a upstream.
The previous code assumed that a higher hardware value always resulted in a bigger divider, which is correct for the regular clocks, but is an invalid assumption when a divider table is provided for the clock.
Perfect example of this is the PLL0_HALF clock, which applies a /2 divider with the hardware value 0, and a /1 divider otherwise.
--- drivers/clk/ingenic/cgu.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/clk/ingenic/cgu.c +10 -4
@@ -392,15 +392,21 @@ static unsigned int ingenic_clk_calc_hw_div(const struct ingenic_cgu_clk_info *clk_info, unsigned int div) { - unsigned int i; + unsigned int i, best_i = 0, best = (unsigned int)-1;for (i =0 ; i < (1 << clk_info->div.bits) && clk_info->div.div_table[i]; i++) { -if (clk_info->div.div_table[i] >= div) -return i; +if (clk_info->div.div_table[i] >= div && + clk_info->div.div_table[i] < best) { + best = clk_info->div.div_table[i]; + best_i = i; + +if (div == best) +break ; + } } -return i -1 ; +return best_i; } static unsigned
Greg Kroah-Hartman
maintainerPATCH 689/717 clk: mvebu: a3700: fix the XTAL MODE pin to MPP1_9
In reply to Greg Kroah-HartmanFrom: Terry Zhou <[email protected]>
commit 6f37689cf6b38fff96de52e7f0d3e78f22803ba0 upstream.
There is an error in the current code that the XTAL MODE pin was set to NB MPP1_31 which should be NB MPP1_9. The latch register of NB MPP1_9 has different offset of 0x8.
--- drivers/clk/mvebu/armada-37xx-xtal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/clk/mvebu/armada-37xx-xtal.c +2 -2
@@ -13,8 +13,8 @@#include <linux/platform_device.h> #include <linux/regmap.h> -#define NB_GPIO1_LATCH 0xC -#define XTAL_MODE BIT(31) +#define NB_GPIO1_LATCH 0x8 +#define XTAL_MODE BIT(9)static int armada_3700_xtal_clock_probe (struct platform_device *pdev) {
Greg Kroah-Hartman
maintainerPATCH 690/717 clk: tegra: Do not return 0 on failure
In reply to Greg Kroah-HartmanFrom: Nicolin Chen <[email protected]>
commit 6160aca443148416994c022a35c77daeba948ea6 upstream.
Return values from read_dt_param() will be either TRUE (1) or FALSE (0), while dfll_fetch_pwm_params() returns 0 on success or an ERR code on failure.
So this patch fixes the bug of returning 0 on failure.
--- drivers/clk/tegra/clk-dfll.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/clk/tegra/clk-dfll.c +2 -2
@@ -1856,13 +1856,13 @@ static int dfll_fetch_pwm_params(struct &td->reg_init_uV);if (!ret) {dev_err (td->dev,"couldn't get initialized voltage\n" ); -return ret; +return -EINVAL ; } ret =read_dt_param (td,"nvidia,pwm-period-nanoseconds" , &pwm_period);if (!ret) {dev_err (td->dev,"couldn't get PWM period\n" ); -return ret; +return -EINVAL ; } td->pwm_rate = (NSEC_PER_SEC / pwm_period) * (MAX_DFLL_VOLTAGES -1 );
Greg Kroah-Hartman
maintainerPATCH 691/717 counter: microchip-tcb-capture: Fix CMR value check
In reply to Greg Kroah-HartmanFrom: William Breathitt Gray <[email protected]>
commit 3418bd7cfce0bd8ef1ccedc4655f9f86f6c3b0ca upstream.
The ATMEL_TC_ETRGEDG_* defines are not masks but rather possible values for CMR. This patch fixes the action_get() callback to properly check for these values rather than mask them.
--- drivers/counter/microchip-tcb-capture.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
drivers/counter/microchip-tcb-capture.c +10 -6
@@ -183,16 +183,20 @@ static int mchp_tc_count_action_get(struregmap_read (priv->regmap,ATMEL_TC_REG (priv->channel[0 ],CMR ), &cmr); - *action =MCHP_TC_SYNAPSE_ACTION_NONE ; - -if (cmr &ATMEL_TC_ETRGEDG_NONE ) +switch (cmr &ATMEL_TC_ETRGEDG ) { +default : *action =MCHP_TC_SYNAPSE_ACTION_NONE ; -else if (cmr &ATMEL_TC_ETRGEDG_RISING ) +break ; +case ATMEL_TC_ETRGEDG_RISING : *action =MCHP_TC_SYNAPSE_ACTION_RISING_EDGE ; -else if (cmr &ATMEL_TC_ETRGEDG_FALLING ) +break ; +case ATMEL_TC_ETRGEDG_FALLING : *action =MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE ; -else if (cmr &ATMEL_TC_ETRGEDG_BOTH ) +break ; +case ATMEL_TC_ETRGEDG_BOTH : *action =MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE ; +break ; + }return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 692/717 device-dax/core: Fix memory leak when rmmod dax.ko
In reply to Greg Kroah-HartmanFrom: Wang Hai <[email protected]>
commit 1aa574312518ef1d60d2dc62d58f7021db3b163a upstream.
When I repeatedly modprobe and rmmod dax.ko, kmemleak report a memory leak as follows:
unreferenced object 0xffff9a5588c05088 (size 8):
comm "modprobe", pid 261, jiffies 4294693644 (age 42.063s)
...
backtrace:
[<00000000e007ced0>] kstrdup+0x35/0x70
[<000000002ae73897>] kstrdup_const+0x3d/0x50
[<000000002b00c9c3>] kvasprintf_const+0xbc/0xf0
[<000000008023282f>] kobject_set_name_vargs+0x3b/0xd0
[<00000000d2cbaa4e>] kobject_set_name+0x62/0x90
[<00000000202e7a22>] bus_register+0x7f/0x2b0
[<000000000b77792c>] 0xffffffffc02840f7
[<000000002d5be5ac>] 0xffffffffc02840b4
[<00000000dcafb7cd>] do_one_initcall+0x58/0x240
[<00000000049fe480>] do_init_module+0x56/0x1e2
[<0000000022671491>] load_module+0x2517/0x2840
[<000000001a2201cb>] __do_sys_finit_module+0x9c/0xe0
[<000000003eb304e7>] do_syscall_64+0x33/0x40
[<0000000051c5fd06>] entry_SYSCALL_64_after_hwframe+0x44/0xa9When rmmod dax is executed, dax_bus_exit() is missing. This patch can fix this bug.
--- drivers/dax/super.c | 1 + 1 file changed, 1 insertion(+)
drivers/dax/super.c +1 -0
@@ -752,6 +752,7 @@ err_chrdev: static void __exit dax_core_exit(void) { +dax_bus_exit ();unregister_chrdev_region (dax_devt,MINORMASK +1 );ida_destroy (&dax_minor_ida);dax_fs_exit ();
Greg Kroah-Hartman
maintainerPATCH 693/717 dma-buf/dma-resv: Respect num_fences when initializing the shared fence list.
In reply to Greg Kroah-HartmanFrom: Maarten Lankhorst <[email protected]>
commit bf8975837dac156c33a4d15d46602700998cb6dd upstream.
We hardcode the maximum number of shared fences to 4, instead of respecting num_fences. Use a minimum of 4, but more if num_fences is higher.
This seems to have been an oversight when first implementing the api.
--- drivers/dma-buf/dma-resv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma-buf/dma-resv.c +1 -1
@@ -200,7 +200,7 @@ int dma_resv_reserve_shared(struct dma_r max =max (old->shared_count + num_fences, old->shared_max *2 ); }else { - max =4 ; + max =max (4ul ,roundup_pow_of_two (num_fences)); } new =dma_resv_list_alloc (max);
Greg Kroah-Hartman
maintainerPATCH 694/717 driver: core: Fix list corruption after device_del()
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit 66482f640755b31cb94371ff6cef17400cda6db5 upstream.
The device_links_purge() function (called from device_del()) tries to remove the links.needs_suppliers list entry, but it's using list_del(), hence it doesn't initialize after the removal. This is OK for normal cases where device_del() is called via device_destroy(). However, it's not guaranteed that the device object will be really deleted soon after device_del(). In a minor case like HD-audio codec reconfiguration that re-initializes the device after device_del(), it may lead to a crash by the corrupted list entry.
As a simple fix, replace list_del() with list_del_init() in order to make the list intact after the device_del() call.
--- drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/base/core.c +1 -1
@@ -1386,7 +1386,7 @@ static void device_links_purge(struct dereturn ;mutex_lock (&wfs_lock); -list_del (&dev->links.needs_suppliers); +list_del_init (&dev->links.needs_suppliers);mutex_unlock (&wfs_lock);/*
Greg Kroah-Hartman
maintainerPATCH 695/717 xen-blkback: set ring->xenblkd to NULL after kthread_stop()
In reply to Greg Kroah-HartmanFrom: Pawel Wieczorkiewicz <[email protected]>
commit 1c728719a4da6e654afb9cc047164755072ed7c9 upstream.
When xen_blkif_disconnect() is called, the kernel thread behind the block interface is stopped by calling kthread_stop(ring->xenblkd). The ring->xenblkd thread pointer being non-NULL determines if the thread has been already stopped.
Normally, the thread's function xen_blkif_schedule() sets the ring->xenblkd to NULL, when the thread's main loop ends.
However, when the thread has not been started yet (i.e. wake_up_process() has not been called on it), the xen_blkif_schedule() function would not be called yet.
In such case the kthread_stop() call returns -EINTR and the ring->xenblkd remains dangling.
When this happens, any consecutive call to xen_blkif_disconnect (for example in frontend_changed() callback) leads to a kernel crash in kthread_stop() (e.g. NULL pointer dereference in exit_creds()).
This is XSA-350.
--- drivers/block/xen-blkback/xenbus.c | 1 + 1 file changed, 1 insertion(+)
drivers/block/xen-blkback/xenbus.c +1 -0
@@ -274,6 +274,7 @@ static int xen_blkif_disconnect(struct xif (ring->xenblkd) {kthread_stop (ring->xenblkd); + ring->xenblkd =NULL ;wake_up (&ring->shutdown_wq); }
Greg Kroah-Hartman
maintainerPATCH 696/717 xen/xenbus: Allow watches discard events before queueing
In reply to Greg Kroah-HartmanFrom: SeongJae Park <[email protected]>
commit fed1755b118147721f2c87b37b9d66e62c39b668 upstream.
If handling logics of watch events are slower than the events enqueue logic and the events can be created from the guests, the guests could trigger memory pressure by intensively inducing the events, because it will create a huge number of pending events that exhausting the memory.
Fortunately, some watch events could be ignored, depending on its handler callback. For example, if the callback has interest in only one single path, the watch wouldn't want multiple pending events. Or, some watches could ignore events to same path.
To let such watches to volutarily help avoiding the memory pressure situation, this commit introduces new watch callback, 'will_handle'. If it is not NULL, it will be called for each new event just before enqueuing it. Then, if the callback returns false, the event will be discarded. No watch is using the callback for now, though.
This is part of XSA-349
--- drivers/net/xen-netback/xenbus.c | 4 ++++ drivers/xen/xenbus/xenbus_client.c | 1 + drivers/xen/xenbus/xenbus_xs.c | 5 ++++- include/xen/xenbus.h | 7 +++++++ 4 files changed, 16 insertions(+), 1 deletion(-)
drivers/net/xen-netback/xenbus.c +4 -0
@@ -557,12 +557,14 @@ static int xen_register_credit_watch(strreturn -ENOMEM ;snprintf (node, maxlen,"%s/rate" , dev->nodename); vif->credit_watch.node = node; + vif->credit_watch.will_handle =NULL ; vif->credit_watch.callback = xen_net_rate_changed; err =register_xenbus_watch (&vif->credit_watch);if (err) {pr_err ("Failed to set watcher %s\n" , vif->credit_watch.node);kfree (node); vif->credit_watch.node =NULL ; + vif->credit_watch.will_handle =NULL ; vif->credit_watch.callback =NULL ; }return err;
@@ -609,6 +611,7 @@ static int xen_register_mcast_ctrl_watchsnprintf (node, maxlen,"%s/request-multicast-control" , dev->otherend); vif->mcast_ctrl_watch.node = node; + vif->mcast_ctrl_watch.will_handle =NULL ; vif->mcast_ctrl_watch.callback = xen_mcast_ctrl_changed; err =register_xenbus_watch (&vif->mcast_ctrl_watch);if (err) {
@@ -616,6 +619,7 @@ static int xen_register_mcast_ctrl_watch vif->mcast_ctrl_watch.node);kfree (node); vif->mcast_ctrl_watch.node =NULL ; + vif->mcast_ctrl_watch.will_handle =NULL ; vif->mcast_ctrl_watch.callback =NULL ; }return err;
drivers/xen/xenbus/xenbus_client.c +1 -0
@@ -133,6 +133,7 @@ int xenbus_watch_path(struct xenbus_deviint err; watch->node = path; + watch->will_handle =NULL ; watch->callback = callback; err =register_xenbus_watch (watch);
drivers/xen/xenbus/xenbus_xs.c +4 -1
@@ -705,7 +705,10 @@ int xs_watch_msg(struct xs_watch_event *spin_lock (&watches_lock); event->handle =find_watch (event->token); -if (event->handle !=NULL ) { +if (event->handle !=NULL && + (!event->handle->will_handle || + event->handle->will_handle (event->handle, + event->path, event->token))) {spin_lock (&watch_events_lock);list_add_tail (&event->list, &watch_events);wake_up (&watch_events_waitq);
include/xen/xenbus.h +7 -0
@@ -61,6 +61,13 @@ struct xenbus_watch/* Path being watched. */ const char *node; +/* +* Called just before enqueing new event while a spinlock is held. +* The event will be discarded if this callback returns false. +*/ +bool (*will_handle)(struct xenbus_watch *, +const char *path,const char *token); +/* Callback (executed in a process context with no locks held). */ void (*callback)(struct xenbus_watch *,const char *path,const char *token);
Greg Kroah-Hartman
maintainerPATCH 697/717 xen/xenbus: Add will_handle callback support in xenbus_watch_path()
In reply to Greg Kroah-HartmanFrom: SeongJae Park <[email protected]>
commit 2e85d32b1c865bec703ce0c962221a5e955c52c2 upstream.
Some code does not directly make 'xenbus_watch' object and call 'register_xenbus_watch()' but use 'xenbus_watch_path()' instead. This commit adds support of 'will_handle' callback in the 'xenbus_watch_path()' and it's wrapper, 'xenbus_watch_pathfmt()'.
This is part of XSA-349
--- drivers/block/xen-blkback/xenbus.c | 3 ++- drivers/net/xen-netback/xenbus.c | 2 +- drivers/xen/xen-pciback/xenbus.c | 2 +- drivers/xen/xenbus/xenbus_client.c | 9 +++++++-- drivers/xen/xenbus/xenbus_probe.c | 2 +- include/xen/xenbus.h | 6 +++++- 6 files changed, 17 insertions(+), 7 deletions(-)
drivers/block/xen-blkback/xenbus.c +2 -1
@@ -676,7 +676,8 @@ static int xen_blkbk_probe(struct xenbus/* setup back pointer */ be->blkif->be = be; - err =xenbus_watch_pathfmt (dev, &be->backend_watch, backend_changed, + err =xenbus_watch_pathfmt (dev, &be->backend_watch,NULL , + backend_changed,"%s/%s" , dev->nodename,"physical-device" );if (err) goto fail;
drivers/net/xen-netback/xenbus.c +1 -1
@@ -824,7 +824,7 @@ static void connect(struct backend_infoxenvif_carrier_on (be->vif);unregister_hotplug_status_watch (be); - err =xenbus_watch_pathfmt (dev, &be->hotplug_status_watch, + err =xenbus_watch_pathfmt (dev, &be->hotplug_status_watch,NULL , hotplug_status_changed,"%s/%s" , dev->nodename,"hotplug-status" );if (!err)
drivers/xen/xen-pciback/xenbus.c +1 -1
@@ -689,7 +689,7 @@ static int xen_pcibk_xenbus_probe(struct/* watch the backend node for backend configuration information */ err =xenbus_watch_path (dev, dev->nodename, &pdev->be_watch, - xen_pcibk_be_watch); +NULL , xen_pcibk_be_watch);if (err) goto out;
drivers/xen/xenbus/xenbus_client.c +7 -2
@@ -127,19 +127,22 @@ EXPORT_SYMBOL_GPL(xenbus_strstate);*/ int xenbus_watch_path (struct xenbus_device *dev,const char *path,struct xenbus_watch *watch, +bool (*will_handle)(struct xenbus_watch *, +const char *,const char *),void (*callback)(struct xenbus_watch *,const char *,const char *)) {int err; watch->node = path; - watch->will_handle =NULL ; + watch->will_handle = will_handle; watch->callback = callback; err =register_xenbus_watch (watch);if (err) { watch->node =NULL ; + watch->will_handle =NULL ; watch->callback =NULL ;xenbus_dev_fatal (dev, err,"adding watch on %s" , path); }
@@ -166,6 +169,8 @@ EXPORT_SYMBOL_GPL(xenbus_watch_path);*/ int xenbus_watch_pathfmt (struct xenbus_device *dev,struct xenbus_watch *watch, +bool (*will_handle)(struct xenbus_watch *, +const char *,const char *),void (*callback)(struct xenbus_watch *,const char *,const char *),const char *pathfmt, ...)
@@ -182,7 +187,7 @@ int xenbus_watch_pathfmt(struct xenbus_dxenbus_dev_fatal (dev, -ENOMEM ,"allocating path for watch" );return -ENOMEM ; } - err =xenbus_watch_path (dev, path, watch, callback); + err =xenbus_watch_path (dev, path, watch, will_handle, callback);if (err)kfree (path);
drivers/xen/xenbus/xenbus_probe.c +1 -1
@@ -136,7 +136,7 @@ static int watch_otherend(struct xenbus_ container_of(dev->dev.bus, struct xen_bus_type, bus);return xenbus_watch_pathfmt (dev, &dev->otherend_watch, - bus->otherend_changed, +NULL , bus->otherend_changed,"%s/%s" , dev->otherend,"state" ); }
include/xen/xenbus.h +5 -1
@@ -204,10 +204,14 @@ void xenbus_probe(struct work_struct *);int xenbus_watch_path (struct xenbus_device *dev,const char *path,struct xenbus_watch *watch, +bool (*will_handle)(struct xenbus_watch *, +const char *,const char *),void (*callback)(struct xenbus_watch *,const char *,const char *)); -__printf(4, 5) +__printf(5, 6)int xenbus_watch_pathfmt (struct xenbus_device *dev,struct xenbus_watch *watch, +bool (*will_handle)(struct xenbus_watch *, +const char *,const char *),void (*callback)(struct xenbus_watch *,const char *,const char *),const char *pathfmt, ...);
Greg Kroah-Hartman
maintainerPATCH 698/717 xen/xenbus/xen_bus_type: Support will_handle watch callback
In reply to Greg Kroah-HartmanFrom: SeongJae Park <[email protected]>
commit be987200fbaceaef340872841d4f7af2c5ee8dc3 upstream.
This commit adds support of the 'will_handle' watch callback for 'xen_bus_type' users.
This is part of XSA-349
--- drivers/xen/xenbus/xenbus.h | 2 ++ drivers/xen/xenbus/xenbus_probe.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-)
drivers/xen/xenbus/xenbus.h +2 -0
@@ -44,6 +44,8 @@ struct xen_bus_type {int (*get_bus_id)(char bus_id[XEN_BUS_ID_SIZE ],const char *nodename);int (*probe)(struct xen_bus_type *bus,const char *type,const char *dir); +bool (*otherend_will_handle)(struct xenbus_watch *watch, +const char *path,const char *token);void (*otherend_changed)(struct xenbus_watch *watch,const char *path,const char *token);struct bus_type bus;
drivers/xen/xenbus/xenbus_probe.c +2 -1
@@ -136,7 +136,8 @@ static int watch_otherend(struct xenbus_ container_of(dev->dev.bus, struct xen_bus_type, bus);return xenbus_watch_pathfmt (dev, &dev->otherend_watch, -NULL , bus->otherend_changed, + bus->otherend_will_handle, + bus->otherend_changed,"%s/%s" , dev->otherend,"state" ); }
Greg Kroah-Hartman
maintainerPATCH 699/717 xen/xenbus: Count pending messages for each watch
In reply to Greg Kroah-HartmanFrom: SeongJae Park <[email protected]>
commit 3dc86ca6b4c8cfcba9da7996189d1b5a358a94fc upstream.
This commit adds a counter of pending messages for each watch in the struct. It is used to skip unnecessary pending messages lookup in 'unregister_xenbus_watch()'. It could also be used in 'will_handle' callback.
This is part of XSA-349
--- drivers/xen/xenbus/xenbus_xs.c | 29 ++++++++++++++++++----------- include/xen/xenbus.h | 2 ++ 2 files changed, 20 insertions(+), 11 deletions(-)
drivers/xen/xenbus/xenbus_xs.c +18 -11
@@ -711,6 +711,7 @@ int xs_watch_msg(struct xs_watch_event * event->path, event->token))) {spin_lock (&watch_events_lock);list_add_tail (&event->list, &watch_events); + event->handle->nr_pending++;wake_up (&watch_events_waitq);spin_unlock (&watch_events_lock); } else
@@ -768,6 +769,8 @@ int register_xenbus_watch(struct xenbus_sprintf (token,"%lX" , (long )watch); + watch->nr_pending =0 ; +down_read (&xs_watch_rwsem);spin_lock (&watches_lock);
@@ -817,11 +820,14 @@ void unregister_xenbus_watch(struct xenb/* Cancel pending watch events. */ spin_lock (&watch_events_lock); -list_for_each_entry_safe (event, tmp, &watch_events, list) { -if (event->handle != watch) -continue ; -list_del (&event->list); -kfree (event); +if (watch->nr_pending) { +list_for_each_entry_safe (event, tmp, &watch_events, list) { +if (event->handle != watch) +continue ; +list_del (&event->list); +kfree (event); + } + watch->nr_pending =0 ; }spin_unlock (&watch_events_lock);
@@ -868,7 +874,6 @@ void xs_suspend_cancel(void)static int xenwatch_thread (void *unused) { -struct list_head *ent;struct xs_watch_event *event; xenwatch_pid = current->pid;
@@ -883,13 +888,15 @@ static int xenwatch_thread(void *unused)mutex_lock (&xenwatch_mutex);spin_lock (&watch_events_lock); - ent = watch_events.next; -if (ent != &watch_events) -list_del (ent); + event =list_first_entry_or_null (&watch_events, + struct xs_watch_event, list); +if (event) { +list_del (&event->list); + event->handle->nr_pending--; + }spin_unlock (&watch_events_lock); -if (ent != &watch_events) { - event = list_entry(ent, struct xs_watch_event, list); +if (event) { event->handle->callback (event->handle, event->path, event->token);kfree (event);
include/xen/xenbus.h +2 -0
@@ -61,6 +61,8 @@ struct xenbus_watch/* Path being watched. */ const char *node; +unsigned int nr_pending; +/* * Called just before enqueing new event while a spinlock is held. * The event will be discarded if this callback returns false.
Greg Kroah-Hartman
maintainerPATCH 700/717 xenbus/xenbus_backend: Disallow pending watch messages
In reply to Greg Kroah-HartmanFrom: SeongJae Park <[email protected]>
commit 9996bd494794a2fe393e97e7a982388c6249aa76 upstream.
'xenbus_backend' watches 'state' of devices, which is writable by guests. Hence, if guests intensively updates it, dom0 will have lots of pending events that exhausting memory of dom0. In other words, guests can trigger dom0 memory pressure. This is known as XSA-349. However, the watch callback of it, 'frontend_changed()', reads only 'state', so doesn't need to have the pending events.
To avoid the problem, this commit disallows pending watch messages for 'xenbus_backend' using the 'will_handle()' watch callback.
This is part of XSA-349
--- drivers/xen/xenbus/xenbus_probe_backend.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/xen/xenbus/xenbus_probe_backend.c +7 -0
@@ -180,6 +180,12 @@ static int xenbus_probe_backend(struct xreturn err; } +static bool frontend_will_handle (struct xenbus_watch *watch, +const char *path,const char *token) +{ +return watch->nr_pending ==0 ; +} +static void frontend_changed (struct xenbus_watch *watch,const char *path,const char *token) {
@@ -191,6 +197,7 @@ static struct xen_bus_type xenbus_backen .levels = 3, /* backend/type/<frontend>/<id> */ .get_bus_id = backend_bus_id, .probe = xenbus_probe_backend, + .otherend_will_handle = frontend_will_handle, .otherend_changed = frontend_changed, .bus = { .name = "xen-backend",
Greg Kroah-Hartman
maintainerPATCH 701/717 memory: jz4780_nemc: Fix an error pointer vs NULL check in probe()
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
commit 96999c797ec1ef41259f00b4ddf9cf33b342cb78 upstream.
The devm_ioremap() function returns NULL on error, it doesn't return error pointers. This bug could lead to an Oops during probe.
--- drivers/memory/jz4780-nemc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/memory/jz4780-nemc.c +2 -2
@@ -306,9 +306,9 @@ static int jz4780_nemc_probe(struct plat } nemc->base =devm_ioremap (dev, res->start,NEMC_REG_LEN ); -if (IS_ERR (nemc->base)) { +if (!nemc->base) {dev_err (dev,"failed to get I/O memory\n" ); -return PTR_ERR (nemc->base); +return -ENOMEM ; }writel (0 , nemc->base +NEMC_NFCSR );
Greg Kroah-Hartman
maintainerPATCH 702/717 memory: renesas-rpc-if: Fix a node reference leak in rpcif_probe()
In reply to Greg Kroah-HartmanFrom: Lad Prabhakar <[email protected]>
commit 4e6b86b409f9fc63fedb39d6e3a0202c4b0244ce upstream.
Release the node reference by calling of_node_put(flash) in the probe.
--- drivers/memory/renesas-rpc-if.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/memory/renesas-rpc-if.c +2 -0
@@ -560,9 +560,11 @@ static int rpcif_probe(struct platform_d }else if (of_device_is_compatible (flash,"cfi-flash" )) { name ="rpc-if-hyperflash" ; }else { +of_node_put (flash);dev_warn (&pdev->dev,"unknown flash type\n" );return -ENODEV ; } +of_node_put (flash); vdev =platform_device_alloc (name, pdev->id);if (!vdev)
Greg Kroah-Hartman
maintainerPATCH 703/717 memory: renesas-rpc-if: Return correct value to the caller of rpcif_manual_xfer()
In reply to Greg Kroah-HartmanFrom: Lad Prabhakar <[email protected]>
commit a0453f4ed066cae651b3119ed11f52d31dae1eca upstream.
In the error path of rpcif_manual_xfer() the value of ret is overwritten by value returned by reset_control_reset() function and thus returning incorrect value to the caller.
This patch makes sure the correct value is returned to the caller of rpcif_manual_xfer() by dropping the overwrite of ret in error path. Also now we ignore the value returned by reset_control_reset() in the error path and instead print a error message when it fails.
--- drivers/memory/renesas-rpc-if.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/memory/renesas-rpc-if.c +2 -1
@@ -508,7 +508,8 @@ exit:return ret; err_out: - ret =reset_control_reset (rpc->rstc); +if (reset_control_reset (rpc->rstc)) +dev_err (rpc->dev,"Failed to reset HW\n" );rpcif_hw_init (rpc, rpc->bus_size ==2 ); goto exit; }
Greg Kroah-Hartman
maintainerPATCH 704/717 memory: renesas-rpc-if: Fix unbalanced pm_runtime_enable in rpcif_{enable,disable}_rpm
In reply to Greg Kroah-HartmanFrom: Lad Prabhakar <[email protected]>
commit 61a6d854b9555b420fbfae62ef26baa8b9493b32 upstream.
rpcif_enable_rpm calls pm_runtime_enable, so rpcif_disable_rpm needs to call pm_runtime_disable and not pm_runtime_put_sync.
--- drivers/memory/renesas-rpc-if.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/memory/renesas-rpc-if.c +1 -1
@@ -212,7 +212,7 @@ EXPORT_SYMBOL(rpcif_enable_rpm);void rpcif_disable_rpm (struct rpcif *rpc) { -pm_runtime_put_sync (rpc->dev); +pm_runtime_disable (rpc->dev); }EXPORT_SYMBOL (rpcif_disable_rpm);
Greg Kroah-Hartman
maintainerPATCH 705/717 libnvdimm/namespace: Fix reaping of invalidated block-window-namespace labels
In reply to Greg Kroah-HartmanFrom: Dan Williams <[email protected]>
commit 2dd2a1740ee19cd2636d247276cf27bfa434b0e2 upstream.
A recent change to ndctl to attempt to reconfigure namespaces in place uncovered a label accounting problem in block-window-type namespaces. The ndctl "create.sh" test is able to trigger this signature:
WARNING: CPU: 34 PID: 9167 at drivers/nvdimm/label.c:1100 __blk_label_update+0x9a3/0xbc0 [libnvdimm] [..] RIP: 0010:__blk_label_update+0x9a3/0xbc0 [libnvdimm] [..] Call Trace: uuid_store+0x21b/0x2f0 [libnvdimm] kernfs_fop_write+0xcf/0x1c0 vfs_write+0xcc/0x380 ksys_write+0x68/0xe0
When allocated capacity for a namespace is renamed (new UUID) the labels with the old UUID need to be deleted. The ndctl behavior to always destroy namespaces on reconfiguration hid this problem.
The immediate impact of this bug is limited since block-window-type namespaces only seem to exist in the specification and not in any shipping products. However, the label handling code is being reused for other technologies like CXL region labels, so there is a benefit to making sure both vertical labels sets (block-window) and horizontal label sets (pmem) have a functional reference implementation in libnvdimm.
--- drivers/nvdimm/label.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/nvdimm/label.c +9 -0
@@ -980,6 +980,15 @@ static int __blk_label_update(struct nd_ } } +/* release slots associated with any invalidated UUIDs */ +mutex_lock (&nd_mapping->lock); +list_for_each_entry_safe (label_ent, e, &nd_mapping->labels, list) +if (test_and_clear_bit (ND_LABEL_REAP , &label_ent->flags)) { +reap_victim (nd_mapping, label_ent); +list_move (&label_ent->list, &list); + } +mutex_unlock (&nd_mapping->lock); +/* * Find the resource associated with the first label in the set * per the v1.2 namespace specification.
Greg Kroah-Hartman
maintainerPATCH 706/717 platform/x86: intel-vbtn: Allow switch events on Acer Switch Alpha 12
In reply to Greg Kroah-HartmanFrom: Carlos Garnacho <[email protected]>
commit fe6000990394639ed374cb76c313be3640714f47 upstream.
This 2-in-1 model (Product name: Switch SA5-271) features a SW_TABLET_MODE that works as it would be expected, both when detaching the keyboard and when folding it behind the tablet body.
It used to work until the introduction of the allow list at commit 8169bd3e6e193 ("platform/x86: intel-vbtn: Switch to an allow-list for SW_TABLET_MODE reporting"). Add this model to it, so that the Virtual Buttons device announces the EV_SW features again.
--- drivers/platform/x86/intel-vbtn.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/platform/x86/intel-vbtn.c +6 -0
@@ -216,6 +216,12 @@ static const struct dmi_system_id dmi_sw DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion 13 x360 PC"), }, }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271"), + }, + }, {}/* Array terminator */ };
Greg Kroah-Hartman
maintainerPATCH 707/717 tracing: Disable ftrace selftests when any tracer is running
In reply to Greg Kroah-HartmanFrom: Masami Hiramatsu <[email protected]>
commit 60efe21e5976d3d4170a8190ca76a271d6419754 upstream.
Disable ftrace selftests when any tracer (kernel command line options like ftrace=, trace_events=, kprobe_events=, and boot-time tracing) starts running because selftest can disturb it.
Currently ftrace= and trace_events= are checked, but kprobe_events has a different flag, and boot-time tracing didn't checked. This unifies the disabled flag and all of those boot-time tracing features sets the flag.
This also fixes warnings on kprobe-event selftest (CONFIG_FTRACE_STARTUP_TEST=y and CONFIG_KPROBE_EVENTS=y) with boot-time tracing (ftrace.event.kprobes.EVENT.probes) like below;
[ 59.803496] trace_kprobe: Testing kprobe tracing: [ 59.804258] ------------[ cut here ]------------ [ 59.805682] WARNING: CPU: 3 PID: 1 at kernel/trace/trace_kprobe.c:1987 kprobe_trace_self_tests_ib [ 59.806944] Modules linked in: [ 59.807335] CPU: 3 PID: 1 Comm: swapper/0 Not tainted 5.10.0-rc7+ #172 [ 59.808029] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1 04/01/204 [ 59.808999] RIP: 0010:kprobe_trace_self_tests_init+0x5f/0x42b [ 59.809696] Code: e8 03 00 00 48 c7 c7 30 8e 07 82 e8 6d 3c 46 ff 48 c7 c6 00 b2 1a 81 48 c7 c7 7 [ 59.812439] RSP: 0018:ffffc90000013e78 EFLAGS: 00010282 [ 59.813038] RAX: 00000000ffffffef RBX: 0000000000000000 RCX: 0000000000049443 [ 59.813780] RDX: 0000000000049403 RSI: 0000000000049403 RDI: 000000000002deb0 [ 59.814589] RBP: ffffc90000013e90 R08: 0000000000000001 R09: 0000000000000001 [ 59.815349] R10: 0000000000000001 R11: 0000000000000000 R12: 00000000ffffffef [ 59.816138] R13: ffff888004613d80 R14: ffffffff82696940 R15: ffff888004429138 [ 59.816877] FS: 0000000000000000(0000) GS:ffff88807dcc0000(0000) knlGS:0000000000000000 [ 59.817772] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 59.818395] CR2: 0000000001a8dd38 CR3: 0000000002222000 CR4: 00000000000006a0 [ 59.819144] Call Trace: [ 59.819469] ? init_kprobe_trace+0x6b/0x6b [ 59.819948] do_one_initcall+0x5f/0x300 [ 59.820392] ? rcu_read_lock_sched_held+0x4f/0x80 [ 59.820916] kernel_init_freeable+0x22a/0x271 [ 59.821416] ? rest_init+0x241/0x241 [ 59.821841] kernel_init+0xe/0x10f [ 59.822251] ret_from_fork+0x22/0x30 [ 59.822683] irq event stamp: 16403349 [ 59.823121] hardirqs last enabled at (16403359): [<ffffffff810db81e>] console_unlock+0x48e/0x580 [ 59.824074] hardirqs last disabled at (16403368): [<ffffffff810db786>] console_unlock+0x3f6/0x580 [ 59.825036] softirqs last enabled at (16403200): [<ffffffff81c0033a>] __do_softirq+0x33a/0x484 [ 59.825982] softirqs last disabled at (16403087): [<ffffffff81a00f02>] asm_call_irq_on_stack+0x10 [ 59.827034] ---[ end trace 200c544775cdfeb3 ]--- [ 59.827635] trace_kprobe: error on probing function entry.
--- kernel/trace/trace.c | 19 +++++++++++++------ kernel/trace/trace.h | 5 +++++ kernel/trace/trace_boot.c | 2 ++ kernel/trace/trace_events.c | 2 +- kernel/trace/trace_kprobe.c | 9 +++------ kernel/trace/trace_selftest.c | 2 +- 6 files changed, 25 insertions(+), 14 deletions(-)
kernel/trace/trace.c +13 -6
@@ -68,10 +68,21 @@ bool ring_buffer_expanded;static bool __read_mostly tracing_selftest_running;/* -* If a tracer is running, we do not want to run SELFTEST. +* If boot-time tracing including tracers/events via kernel cmdline +* is running, we do not want to run SELFTEST. */ bool __read_mostly tracing_selftest_disabled; +#ifdef CONFIG_FTRACE_STARTUP_TEST +void __init disable_tracing_selftest (const char *reason) +{ +if (!tracing_selftest_disabled) { + tracing_selftest_disabled = true; +pr_info ("Ftrace startup test is disabled due to %s\n" , reason); + } +} +#endif +/* Pipe tracepoints to printk */ struct trace_iterator *tracepoint_print_iter;int tracepoint_printk;
@@ -2113,11 +2124,7 @@ int __init register_tracer(struct tracerapply_trace_boot_options ();/* disable other selftests, since this will break it. */ - tracing_selftest_disabled = true; -#ifdef CONFIG_FTRACE_STARTUP_TEST -printk (KERN_INFO "Disabling FTRACE selftests due to running tracer '%s'\n" , - type->name); -#endif +disable_tracing_selftest ("running a tracer" ); out_unlock:return ret;
kernel/trace/trace.h +5 -0
@@ -896,6 +896,8 @@ extern bool ring_buffer_expanded;extern bool tracing_selftest_disabled;#ifdef CONFIG_FTRACE_STARTUP_TEST +extern void __init disable_tracing_selftest (const char *reason); +extern int trace_selftest_startup_function (struct tracer *trace,struct trace_array *tr); extern int trace_selftest_startup_function_graph(struct tracer *trace,
@@ -919,6 +921,9 @@ extern int trace_selftest_startup_branch*/ #define __tracer_data __refdata#else +static inline void __init disable_tracing_selftest (const char *reason) +{ +}/* Tracers are seldom changed. Optimize when selftests are disabled. */ #define __tracer_data __read_mostly#endif /* CONFIG_FTRACE_STARTUP_TEST */
kernel/trace/trace_boot.c +2 -0
@@ -344,6 +344,8 @@ static int __init trace_boot_init(void)trace_boot_init_one_instance (tr, trace_node);trace_boot_init_instances (trace_node); +disable_tracing_selftest ("running boot-time tracing" ); +return 0 ; }/*
kernel/trace/trace_events.c +1 -1
@@ -3201,7 +3201,7 @@ static __init int setup_trace_event(char {strlcpy (bootup_event_buf, str,COMMAND_LINE_SIZE ); ring_buffer_expanded = true; - tracing_selftest_disabled = true; +disable_tracing_selftest ("running event tracing" );return 1 ; }
kernel/trace/trace_kprobe.c +3 -6
@@ -25,11 +25,12 @@/* Kprobe early definition from command line */ static char kprobe_boot_events_buf[COMMAND_LINE_SIZE ]__initdata ; -static bool kprobe_boot_events_enabled__initdata ;static int __init set_kprobe_boot_events (char *str) {strlcpy (kprobe_boot_events_buf, str,COMMAND_LINE_SIZE ); +disable_tracing_selftest ("running kprobe events" ); +return 0 ; }__setup ("kprobe_event=" , set_kprobe_boot_events);
@@ -1887,8 +1888,6 @@ static __init void setup_boot_kprobe_eve ret =trace_run_command (cmd, create_or_delete_trace_kprobe);if (ret)pr_warn ("Failed to add event(%d): %s\n" , ret, cmd); -else - kprobe_boot_events_enabled = true; cmd = p; }
@@ -1973,10 +1972,8 @@ static __init int kprobe_trace_self_testif (tracing_is_disabled ())return -ENODEV ; -if (kprobe_boot_events_enabled) { -pr_info ("Skipping kprobe tests due to kprobe_event on cmdline\n" ); +if (tracing_selftest_disabled)return 0 ; - } target = kprobe_trace_selftest_target;
kernel/trace/trace_selftest.c +1 -1
@@ -787,7 +787,7 @@ trace_selftest_startup_function_graph(st/* Have we just recovered from a hang? */ if (graph_hang_thresh >GRAPH_MAX_FUNC_TEST ) { - tracing_selftest_disabled = true; +disable_tracing_selftest ("recovering from a hang" ); ret =-1 ; goto out; }
Greg Kroah-Hartman
maintainerPATCH 708/717 mt76: add back the SUPPORTS_REORDERING_BUFFER flag
In reply to Greg Kroah-HartmanFrom: Felix Fietkau <[email protected]>
commit ed89b89330b521f20682ead6bf93e1014b21a200 upstream.
It was accidentally dropped while adding multiple wiphy support Fixes fast-rx support and avoids handling reordering in both mac80211 and the driver
--- drivers/net/wireless/mediatek/mt76/mac80211.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/mediatek/mt76/mac80211.c +1 -0
@@ -305,6 +305,7 @@ mt76_phy_init(struct mt76_dev *dev, struieee80211_hw_set (hw,SUPPORT_FAST_XMIT );ieee80211_hw_set (hw,SUPPORTS_CLONED_SKBS );ieee80211_hw_set (hw,SUPPORTS_AMSDU_IN_AMPDU ); +ieee80211_hw_set (hw,SUPPORTS_REORDERING_BUFFER );if (!(dev->drv->drv_flags &MT_DRV_AMSDU_OFFLOAD )) {ieee80211_hw_set (hw,TX_AMSDU );
Greg Kroah-Hartman
maintainerPATCH 709/717 of: fix linker-section match-table corruption
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit 5812b32e01c6d86ba7a84110702b46d8a8531fe9 upstream.
Specify type alignment when declaring linker-section match-table entries to prevent gcc from increasing alignment and corrupting the various tables with padding (e.g. timers, irqchips, clocks, reserved memory).
This is specifically needed on x86 where gcc (typically) aligns larger objects like struct of_device_id with static extent on 32-byte boundaries which at best prevents matching on anything but the first entry. Specifying alignment when declaring variables suppresses this optimisation.
Here's a 64-bit example where all entries are corrupt as 16 bytes of padding has been inserted before the first entry:
ffffffff8266b4b0 D __clk_of_table ffffffff8266b4c0 d __of_table_fixed_factor_clk ffffffff8266b5a0 d __of_table_fixed_clk ffffffff8266b680 d __clk_of_table_sentinel
And here's a 32-bit example where the 8-byte-aligned table happens to be placed on a 32-byte boundary so that all but the first entry are corrupt due to the 28 bytes of padding inserted between entries:
812b3ec0 D __irqchip_of_table 812b3ec0 d __of_table_irqchip1 812b3fa0 d __of_table_irqchip2 812b4080 d __of_table_irqchip3 812b4160 d irqchip_of_match_end
Verified on x86 using gcc-9.3 and gcc-4.9 (which uses 64-byte alignment), and on arm using gcc-7.2.
Note that there are no in-tree users of these tables on x86 currently (even if they are included in the image).
--- include/linux/of.h | 1 + 1 file changed, 1 insertion(+)
include/linux/of.h +1 -0
@@ -1300,6 +1300,7 @@ static inline int of_get_available_child#define _OF_DECLARE (table, name, compat, fn, fn_type) \ static const struct of_device_id __of_table_##name \ __used __section("__" #table "_of_table") \ + __aligned(__alignof__(struct of_device_id)) \ = { .compatible = compat, \ .data = (fn == (fn_type)NULL) ? fn : fn }#else
Greg Kroah-Hartman
maintainerPATCH 710/717 PCI: Fix pci_slot_release() NULL pointer dereference
In reply to Greg Kroah-HartmanFrom: Jubin Zhong <[email protected]>
commit 4684709bf81a2d98152ed6b610e3d5c403f9bced upstream.
If kobject_init_and_add() fails, pci_slot_release() is called to delete slot->list from parent->slots. But slot->list hasn't been initialized yet, so we dereference a NULL pointer:
Unable to handle kernel NULL pointer dereference at virtual address 00000000 ... CPU: 10 PID: 1 Comm: swapper/0 Not tainted 4.4.240 #197 task: ffffeb398a45ef10 task.stack: ffffeb398a470000 PC is at __list_del_entry_valid+0x5c/0xb0 LR is at pci_slot_release+0x84/0xe4 ... __list_del_entry_valid+0x5c/0xb0 pci_slot_release+0x84/0xe4 kobject_put+0x184/0x1c4 pci_create_slot+0x17c/0x1b4 __pci_hp_initialize+0x68/0xa4 pciehp_probe+0x1a4/0x2fc pcie_port_probe_service+0x58/0x84 driver_probe_device+0x320/0x470
Initialize slot->list before calling kobject_init_and_add() to avoid this.
--- drivers/pci/slot.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/pci/slot.c +3 -3
@@ -272,6 +272,9 @@ placeholder: goto err; } +INIT_LIST_HEAD (&slot->list); +list_add (&slot->list, &parent->slots); + err =kobject_init_and_add (&slot->kobj, &pci_slot_ktype,NULL ,"%s" , slot_name);if (err) {
@@ -279,9 +282,6 @@ placeholder: goto err; } -INIT_LIST_HEAD (&slot->list); -list_add (&slot->list, &parent->slots); -down_read (&pci_bus_sem);list_for_each_entry (dev, &parent->devices, bus_list)if (PCI_SLOT (dev->devfn) == slot_nr)
Greg Kroah-Hartman
maintainerPATCH 711/717 regulator: axp20x: Fix DLDO2 voltage control register mask for AXP22x
In reply to Greg Kroah-HartmanFrom: DingHua Ma <[email protected]>
commit 291de1d102fafef0798cdad9666cd4f8da7da7cc upstream.
When I use the axp20x chip to power my SDIO device on the 5.4 kernel, the output voltage of DLDO2 is wrong. After comparing the register manual and source code of the chip, I found that the mask bit of the driver register of the port was wrong. I fixed this error by modifying the mask register of the source code. This error seems to be a copy error of the macro when writing the code. Now the voltage output of the DLDO2 port of axp20x is correct. My development environment is Allwinner A40I of arm architecture, and the kernel version is 5.4.
--- drivers/regulator/axp20x-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/regulator/axp20x-regulator.c +1 -1
@@ -594,7 +594,7 @@ static const struct regulator_desc axp22 AXP22X_DLDO1_V_OUT, AXP22X_DLDO1_V_OUT_MASK, AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO1_MASK),AXP_DESC (AXP22X ,DLDO2 ,"dldo2" ,"dldoin" ,700 ,3300 ,100 , -AXP22X_DLDO2_V_OUT ,AXP22X_PWR_OUT_DLDO2_MASK , +AXP22X_DLDO2_V_OUT ,AXP22X_DLDO2_V_OUT_MASK ,AXP22X_PWR_OUT_CTRL2 ,AXP22X_PWR_OUT_DLDO2_MASK ), AXP_DESC(AXP22X, DLDO3, "dldo3", "dldoin", 700, 3300, 100, AXP22X_DLDO3_V_OUT, AXP22X_DLDO3_V_OUT_MASK,
Greg Kroah-Hartman
maintainerPATCH 712/717 remoteproc: sysmon: Ensure remote notification ordering
In reply to Greg Kroah-HartmanFrom: Bjorn Andersson <[email protected]>
commit 138a6428ba9023ae29e103e87a223575fbc3d2b7 upstream.
The reliance on the remoteproc's state for determining when to send sysmon notifications to a remote processor is racy with regard to concurrent remoteproc operations.
Further more the advertisement of the state of other remote processor to a newly started remote processor might not only send the wrong state, but might result in a stream of state changes that are out of order.
Address this by introducing state tracking within the sysmon instances themselves and extend the locking to ensure that the notifications are consistent with this state.
--- drivers/remoteproc/qcom_sysmon.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)
drivers/remoteproc/qcom_sysmon.c +21 -4
@@ -22,6 +22,9 @@ struct qcom_sysmon {struct rproc_subdev subdev;struct rproc *rproc; +int state; +struct mutex state_lock; +struct list_head node;const char *name;
@@ -448,7 +451,10 @@ static int sysmon_prepare(struct rproc_s .ssr_event = SSCTL_SSR_EVENT_BEFORE_POWERUP }; +mutex_lock (&sysmon->state_lock); + sysmon->state =SSCTL_SSR_EVENT_BEFORE_POWERUP ;blocking_notifier_call_chain (&sysmon_notifiers,0 , (void *)&event); +mutex_unlock (&sysmon->state_lock);return 0 ; }
@@ -472,20 +478,25 @@ static int sysmon_start(struct rproc_sub .ssr_event = SSCTL_SSR_EVENT_AFTER_POWERUP }; +mutex_lock (&sysmon->state_lock); + sysmon->state =SSCTL_SSR_EVENT_AFTER_POWERUP ;blocking_notifier_call_chain (&sysmon_notifiers,0 , (void *)&event); +mutex_unlock (&sysmon->state_lock);mutex_lock (&sysmon_lock);list_for_each_entry (target, &sysmon_list, node) { -if (target == sysmon || - target->rproc->state !=RPROC_RUNNING ) +if (target == sysmon)continue ; +mutex_lock (&target->state_lock); event.subsys_name = target->name; + event.ssr_event = target->state;if (sysmon->ssctl_version ==2 )ssctl_send_event (sysmon, &event);else if (sysmon->ept)sysmon_send_event (sysmon, &event); +mutex_unlock (&target->state_lock); }mutex_unlock (&sysmon_lock);
@@ -500,7 +511,10 @@ static void sysmon_stop(struct rproc_sub .ssr_event = SSCTL_SSR_EVENT_BEFORE_SHUTDOWN }; +mutex_lock (&sysmon->state_lock); + sysmon->state =SSCTL_SSR_EVENT_BEFORE_SHUTDOWN ;blocking_notifier_call_chain (&sysmon_notifiers,0 , (void *)&event); +mutex_unlock (&sysmon->state_lock);/* Don't request graceful shutdown if we've crashed */ if (crashed)
@@ -521,7 +535,10 @@ static void sysmon_unprepare(struct rpro .ssr_event = SSCTL_SSR_EVENT_AFTER_SHUTDOWN }; +mutex_lock (&sysmon->state_lock); + sysmon->state =SSCTL_SSR_EVENT_AFTER_SHUTDOWN ;blocking_notifier_call_chain (&sysmon_notifiers,0 , (void *)&event); +mutex_unlock (&sysmon->state_lock); }/**
@@ -534,11 +551,10 @@ static int sysmon_notify(struct notifier void *data) { struct qcom_sysmon *sysmon = container_of(nb, struct qcom_sysmon, nb); -struct rproc *rproc = sysmon->rproc;struct sysmon_event *sysmon_event = data;/* Skip non-running rprocs and the originating instance */ -if (rproc->state !=RPROC_RUNNING || +if (sysmon->state !=SSCTL_SSR_EVENT_AFTER_POWERUP || !strcmp (sysmon_event->subsys_name, sysmon->name)) {dev_dbg (sysmon->dev,"not notifying %s\n" , sysmon->name);return NOTIFY_DONE ;
@@ -591,6 +607,7 @@ struct qcom_sysmon *qcom_add_sysmon_subdinit_completion (&sysmon->ind_comp);init_completion (&sysmon->shutdown_comp);mutex_init (&sysmon->lock); +mutex_init (&sysmon->state_lock); sysmon->shutdown_irq =of_irq_get_byname (sysmon->dev->of_node,"shutdown-ack" );
Greg Kroah-Hartman
maintainerPATCH 713/717 thermal/drivers/cpufreq_cooling: Update cpufreq_state only if state has changed
In reply to Greg Kroah-HartmanFrom: Zhuguangqing <[email protected]>
commit 236761f19a4f373354f1dcf399b57753f1f4b871 upstream.
If state has not changed successfully and we updated cpufreq_state, next time when the new state is equal to cpufreq_state (not changed successfully last time), we will return directly and miss a freq_qos_update_request() that should have been.
--- drivers/thermal/cpufreq_cooling.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/thermal/cpufreq_cooling.c +1 -3
@@ -438,13 +438,11 @@ static int cpufreq_set_cur_state(structif (cpufreq_cdev->cpufreq_state == state)return 0 ; - cpufreq_cdev->cpufreq_state = state; - frequency =get_state_freq (cpufreq_cdev, state); ret =freq_qos_update_request (&cpufreq_cdev->qos_req, frequency); -if (ret >0 ) { + cpufreq_cdev->cpufreq_state = state; cpus = cpufreq_cdev->policy->cpus; max_capacity =arch_scale_cpu_capacity (cpumask_first (cpus)); capacity = frequency * max_capacity;
Greg Kroah-Hartman
maintainerPATCH 714/717 rtc: ep93xx: Fix NULL pointer dereference in ep93xx_rtc_read_time
In reply to Greg Kroah-HartmanFrom: Nikita Shubin <[email protected]>
commit 00c33482bb6110bce8110daa351f9b3baf4df7dc upstream.
Mismatch in probe platform_set_drvdata set's and method's that call dev_get_platdata will result in "Unable to handle kernel NULL pointer dereference", let's use according method for getting driver data after platform_set_drvdata.
8<--- cut here ---
Unable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = (ptrval) [00000000] *pgd=00000000 Internal error: Oops: 5 [#1] ARM Modules linked in: CPU: 0 PID: 1 Comm: swapper Not tainted 5.9.10-00003-g723e101e0037-dirty #4 Hardware name: Technologic Systems TS-72xx SBC PC is at ep93xx_rtc_read_time+0xc/0x2c LR is at __rtc_read_time+0x4c/0x8c
[...]
[<c02b01c8>] (ep93xx_rtc_read_time) from [<c02ac38c>] (__rtc_read_time+0x4c/0x8c) [<c02ac38c>] (__rtc_read_time) from [<c02ac3f8>] (rtc_read_time+0x2c/0x4c) [<c02ac3f8>] (rtc_read_time) from [<c02acc54>] (__rtc_read_alarm+0x28/0x358) [<c02acc54>] (__rtc_read_alarm) from [<c02abd80>] (__rtc_register_device+0x124/0x2ec) [<c02abd80>] (__rtc_register_device) from [<c02b028c>] (ep93xx_rtc_probe+0xa4/0xac) [<c02b028c>] (ep93xx_rtc_probe) from [<c026424c>] (platform_drv_probe+0x24/0x5c) [<c026424c>] (platform_drv_probe) from [<c0262918>] (really_probe+0x218/0x374) [<c0262918>] (really_probe) from [<c0262da0>] (device_driver_attach+0x44/0x60) [<c0262da0>] (device_driver_attach) from [<c0262e70>] (__driver_attach+0xb4/0xc0) [<c0262e70>] (__driver_attach) from [<c0260d44>] (bus_for_each_dev+0x68/0xac) [<c0260d44>] (bus_for_each_dev) from [<c026223c>] (driver_attach+0x18/0x24) [<c026223c>] (driver_attach) from [<c0261dd8>] (bus_add_driver+0x150/0x1b4) [<c0261dd8>] (bus_add_driver) from [<c026342c>] (driver_register+0xb0/0xf4) [<c026342c>] (driver_register) from [<c0264210>] (__platform_driver_register+0x30/0x48) [<c0264210>] (__platform_driver_register) from [<c04cb9ac>] (ep93xx_rtc_driver_init+0x10/0x1c) [<c04cb9ac>] (ep93xx_rtc_driver_init) from [<c000973c>] (do_one_initcall+0x7c/0x1c0) [<c000973c>] (do_one_initcall) from [<c04b9ecc>] (kernel_init_freeable+0x168/0x1ac) [<c04b9ecc>] (kernel_init_freeable) from [<c03b2228>] (kernel_init+0x8/0xf4) [<c03b2228>] (kernel_init) from [<c00082c0>] (ret_from_fork+0x14/0x34)
Exception stack(0xc441dfb0 to 0xc441dff8) dfa0: 00000000 00000000 00000000 00000000 dfc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 dfe0: 00000000 00000000 00000000 00000000 00000013 00000000 Code: e12fff1e e92d4010 e590303c e1a02001 (e5933000) ---[ end trace c914d6030eaa95c8 ]---
--- drivers/rtc/rtc-ep93xx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/rtc/rtc-ep93xx.c +3 -3
@@ -33,7 +33,7 @@ struct ep93xx_rtc {static int ep93xx_rtc_get_swcomp (struct device *dev,unsigned short *preload,unsigned short *delete) { -struct ep93xx_rtc *ep93xx_rtc =dev_get_platdata (dev); +struct ep93xx_rtc *ep93xx_rtc =dev_get_drvdata (dev);unsigned long comp; comp =readl (ep93xx_rtc->mmio_base +EP93XX_RTC_SWCOMP );
@@ -51,7 +51,7 @@ static int ep93xx_rtc_get_swcomp(structstatic int ep93xx_rtc_read_time (struct device *dev,struct rtc_time *tm) { -struct ep93xx_rtc *ep93xx_rtc =dev_get_platdata (dev); +struct ep93xx_rtc *ep93xx_rtc =dev_get_drvdata (dev);unsigned long time; time =readl (ep93xx_rtc->mmio_base +EP93XX_RTC_DATA );
@@ -62,7 +62,7 @@ static int ep93xx_rtc_read_time(struct dstatic int ep93xx_rtc_set_time (struct device *dev,struct rtc_time *tm) { -struct ep93xx_rtc *ep93xx_rtc =dev_get_platdata (dev); +struct ep93xx_rtc *ep93xx_rtc =dev_get_drvdata (dev);unsigned long secs =rtc_tm_to_time64 (tm);writel (secs +1 , ep93xx_rtc->mmio_base +EP93XX_RTC_LOAD );
Greg Kroah-Hartman
maintainerPATCH 715/717 Revert: "ring-buffer: Remove HAVE_64BIT_ALIGNED_ACCESS"
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (VMware) <[email protected]>
commit adab66b71abfe206a020f11e561f4df41f0b2aba upstream.
It was believed that metag was the only architecture that required the ring buffer to keep 8 byte words aligned on 8 byte architectures, and with its removal, it was assumed that the ring buffer code did not need to handle this case. It appears that sparc64 also requires this.
The following was reported on a sparc64 boot up:
kernel: futex hash table entries: 65536 (order: 9, 4194304 bytes, linear)
kernel: Running postponed tracer tests:
kernel: Testing tracer function:
kernel: Kernel unaligned access at TPC[552a20] trace_function+0x40/0x140
kernel: Kernel unaligned access at TPC[552a24] trace_function+0x44/0x140
kernel: Kernel unaligned access at TPC[552a20] trace_function+0x40/0x140
kernel: Kernel unaligned access at TPC[552a24] trace_function+0x44/0x140
kernel: Kernel unaligned access at TPC[552a20] trace_function+0x40/0x140
kernel: PASSED
Need to put back the 64BIT aligned code for the ring buffer.
--- arch/Kconfig | 16 ++++++++++++++++ kernel/trace/ring_buffer.c | 17 +++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-)
arch/Kconfig +16 -0
@@ -143,6 +143,22 @@ config UPROBES managed by the kernel and kept transparent to the probed application. ) +config HAVE_64BIT_ALIGNED_ACCESS + def_bool 64BIT && !HAVE_EFFICIENT_UNALIGNED_ACCESS + help + Some architectures require 64 bit accesses to be 64 bit + aligned, which also requires structs containing 64 bit values + to be 64 bit aligned too. This includes some 32 bit + architectures which can do 64 bit accesses, as well as 64 bit + architectures without unaligned access. + + This symbol should be selected by an architecture if 64 bit + accesses are required to be 64 bit aligned in this way even + though it is not a 64 bit architecture. + + See Documentation/unaligned-memory-access.txt for more + information on the topic of unaligned memory accesses. + config HAVE_EFFICIENT_UNALIGNED_ACCESS bool help
kernel/trace/ring_buffer.c +13 -4
@@ -129,7 +129,16 @@ int ring_buffer_print_entry_header(struc#define RB_ALIGNMENT 4U#define RB_MAX_SMALL_DATA (RB_ALIGNMENT * RINGBUF_TYPE_DATA_TYPE_LEN_MAX)#define RB_EVNT_MIN_SIZE 8U/* two 32bit words */ -#define RB_ALIGN_DATA __aligned(RB_ALIGNMENT) + +#ifndef CONFIG_HAVE_64BIT_ALIGNED_ACCESS +# define RB_FORCE_8BYTE_ALIGNMENT 0 +# define RB_ARCH_ALIGNMENT RB_ALIGNMENT +#else +# define RB_FORCE_8BYTE_ALIGNMENT 1 +# define RB_ARCH_ALIGNMENT 8U +#endif + +#define RB_ALIGN_DATA __aligned(RB_ARCH_ALIGNMENT)/* define RINGBUF_TYPE_DATA for 'case RINGBUF_TYPE_DATA:' */ #define RINGBUF_TYPE_DATA 0 ... RINGBUF_TYPE_DATA_TYPE_LEN_MAX
@@ -2719,7 +2728,7 @@ rb_update_event(struct ring_buffer_per_c event->time_delta = delta; length -=RB_EVNT_HDR_SIZE ; -if (length >RB_MAX_SMALL_DATA ) { +if (length >RB_MAX_SMALL_DATA ||RB_FORCE_8BYTE_ALIGNMENT ) { event->type_len =0 ; event->array[0 ] = length; }else
@@ -2734,11 +2743,11 @@ static unsigned rb_calculate_event_lengtif (!length) length++; -if (length >RB_MAX_SMALL_DATA ) +if (length >RB_MAX_SMALL_DATA ||RB_FORCE_8BYTE_ALIGNMENT ) length +=sizeof (event.array[0 ]); length +=RB_EVNT_HDR_SIZE ; - length =ALIGN (length,RB_ALIGNMENT ); + length =ALIGN (length,RB_ARCH_ALIGNMENT );/* * In case the time delta is larger than the 27 bits for it
Greg Kroah-Hartman
maintainerPATCH 716/717 null_blk: Fix zone size initialization
In reply to Greg Kroah-HartmanFrom: Damien Le Moal <[email protected]>
commit 0ebcdd702f49aeb0ad2e2d894f8c124a0acc6e23 upstream.
For a null_blk device with zoned mode enabled is currently initialized with a number of zones equal to the device capacity divided by the zone size, without considering if the device capacity is a multiple of the zone size. If the zone size is not a divisor of the capacity, the zones end up not covering the entire capacity, potentially resulting is out of bounds accesses to the zone array.
Fix this by adding one last smaller zone with a size equal to the remainder of the disk capacity divided by the zone size if the capacity is not a multiple of the zone size. For such smaller last zone, the zone capacity is also checked so that it does not exceed the smaller zone size.
--- drivers/block/null_blk_zoned.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-)
drivers/block/null_blk_zoned.c +15 -8
@@ -6,8 +6,7 @@#define CREATE_TRACE_POINTS #include "null_blk_trace.h" -/* zone_size in MBs to sectors. */ -#define ZONE_SIZE_SHIFT 11 +#define MB_TO_SECTS (mb) (((sector_t)mb * SZ_1M) >> SECTOR_SHIFT)static inline unsigned int null_zone_no (struct nullb_device *dev,sector_t sect) {
@@ -16,7 +15,7 @@ static inline unsigned int null_zone_no(int null_init_zoned_dev (struct nullb_device *dev,struct request_queue *q) { -sector_t dev_size = (sector_t )dev->size *1024 *1024 ; +sector_t dev_capacity_sects, zone_capacity_sects;sector_t sector =0 ;unsigned int i;
@@ -38,9 +37,13 @@ int null_init_zoned_dev(struct nullb_devreturn -EINVAL ; } - dev->zone_size_sects = dev->zone_size <<ZONE_SIZE_SHIFT ; - dev->nr_zones = dev_size >> - (SECTOR_SHIFT +ilog2 (dev->zone_size_sects)); + zone_capacity_sects =MB_TO_SECTS (dev->zone_capacity); + dev_capacity_sects =MB_TO_SECTS (dev->size); + dev->zone_size_sects =MB_TO_SECTS (dev->zone_size); + dev->nr_zones = dev_capacity_sects >>ilog2 (dev->zone_size_sects); +if (dev_capacity_sects & (dev->zone_size_sects -1 )) + dev->nr_zones++; + dev->zones =kvmalloc_array (dev->nr_zones,sizeof (struct blk_zone ),GFP_KERNEL | __GFP_ZERO);if (!dev->zones)
@@ -101,8 +104,12 @@ int null_init_zoned_dev(struct nullb_devstruct blk_zone *zone = &dev->zones[i]; zone->start = zone->wp = sector; - zone->len = dev->zone_size_sects; - zone->capacity = dev->zone_capacity <<ZONE_SIZE_SHIFT ; +if (zone->start + dev->zone_size_sects > dev_capacity_sects) + zone->len = dev_capacity_sects - zone->start; +else + zone->len = dev->zone_size_sects; + zone->capacity = +min_t (sector_t, zone->len, zone_capacity_sects); zone->type =BLK_ZONE_TYPE_SEQWRITE_REQ ; zone->cond =BLK_ZONE_COND_EMPTY ;
Greg Kroah-Hartman
maintainerPATCH 717/717 null_blk: Fail zone append to conventional zones
In reply to Greg Kroah-HartmanFrom: Damien Le Moal <[email protected]>
commit 2e896d89510f23927ec393bee1e0570db3d5a6c6 upstream.
Conventional zones do not have a write pointer and so cannot accept zone append writes. Make sure to fail any zone append write command issued to a conventional zone.
--- drivers/block/null_blk_zoned.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/block/null_blk_zoned.c +4 -1
@@ -339,8 +339,11 @@ static blk_status_t null_zone_write(strutrace_nullb_zone_op (cmd, zno, zone->cond); -if (zone->type ==BLK_ZONE_TYPE_CONVENTIONAL ) +if (zone->type ==BLK_ZONE_TYPE_CONVENTIONAL ) { +if (append) +return BLK_STS_IOERR ;return null_process_cmd (cmd,REQ_OP_WRITE , sector, nr_sectors); + }null_lock_zone (dev, zno);
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.4 release. There are 717 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 Wed, 30 Dec 2020 12:48:23 +0000. Anything received after that time might be too late.
Build results:
total: 154 pass: 154 fail: 0 Qemu test results: total: 427 pass: 427 fail: 0
Guenter
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.4 release. There are 717 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 Wed, 30 Dec 2020 12:48:23 +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/v5.x/stable-review/patch-5.10.4-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.10.y
and the diffstat can be found below.thanks,
greg k-h
All tests passing for Tegra ...
Test results for stable-v5.10:
12 builds: 12 pass, 0 fail
26 boots: 26 pass, 0 fail
64 tests: 64 pass, 0 failLinux version: 5.10.4-rc1-g404b2e8f23fd
Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000,
tegra194-p2972-0000, tegra20-ventana,
tegra210-p2371-2180, tegra210-p3450-0000,
tegra30-cardhu-a04Jon
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.4 release. There are 717 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 Wed, 30 Dec 2020 12:48:23 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.4-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.10.y
and the diffstat can be found below.thanks,
greg k-h
Results from Linaro’s test farm.
No regressions on arm64, arm, x86_64, and i386.
Summary
------------------------------------------------------------------------
kernel: 5.10.4-rc1
git repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
git branch: linux-5.10.y
git commit: 404b2e8f23fd9530a213b3eb2b10868346c18c1f
git describe: v5.10.3-718-g404b2e8f23fd
Test details: https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-5.10.y/build/v5.10.3-718-g404b2e8f23fd
No regressions (compared to build v5.10.3)
No fixes (compared to build v5.10.3)
Ran 52627 total tests in the following environments and test suites.
Environments
--------------
- arc
- arm
- arm64
- dragonboard-410c
- hi6220-hikey
- i386
- juno-r2
- juno-r2-compat
- juno-r2-kasan
- mips
- parisc
- powerpc
- qemu-arm-clang
- qemu-arm64-clang
- qemu-arm64-kasan
- qemu-i386-clang
- qemu-x86_64-clang
- qemu-x86_64-kasan
- qemu-x86_64-kcsan
- qemu_arm
- qemu_arm64
- qemu_arm64-compat
- qemu_i386
- qemu_x86_64
- qemu_x86_64-compat
- riscv
- s390
- sh
- sparc
- x15
- x86
- x86-kasan
Test Suites
-----------
* build
* linux-log-parser
* install-android-platform-tools-r2600
* ltp-commands-tests
* ltp-dio-tests
* ltp-fcntl-locktests-tests
* ltp-filecaps-tests
* ltp-fs_bind-tests
* ltp-fs_perms_simple-tests
* ltp-fsx-tests
* ltp-io-tests
* ltp-ipc-tests
* ltp-math-tests
* ltp-nptl-tests
* ltp-pty-tests
* ltp-securebits-tests
* ltp-syscalls-tests
* ltp-tracing-tests
* fwts
* kselftest
* kvm-unit-tests
* libhugetlbfs
* ltp-cap_bounds-tests
* ltp-containers-tests
* ltp-cpuhotplug-tests
* ltp-crypto-tests
* ltp-cve-tests
* ltp-fs-tests
* ltp-hugetlb-tests
* ltp-mm-tests
* ltp-sched-tests
* network-basic-tests
* ltp-controllers-tests
* ltp-open-posix-tests
* perf
* v4l2-compliance
* kunit
* rcutorture
* kselftest-vsyscall-mode-native
* kselftest-vsyscall-mode-none
Signature · 2 lines
Linaro LKFT https://lkft.linaro.org