5.15.61-rc1 review
Subsystems (11)
Greg Kroah-Hartman
maintainerPATCH 554/779 block/bio: remove duplicate append pages code
In reply to Greg Kroah-HartmanFrom: Keith Busch <[email protected]>
[ Upstream commit c58c0074c54c2e2bb3bb0d5a4d8896bb660cc8bc ]
The getting pages setup for zone append and normal IO are identical. Use common code for each.
--- block/bio.c | 102 ++++++++++++++++++++++------------------------------ 1 file changed, 42 insertions(+), 60 deletions(-)
block/bio.c +42 -60
@@ -1071,6 +1071,37 @@ static void bio_put_pages(struct page **pages, size_t size, size_t off)put_page (pages[i]); } +static int bio_iov_add_page (struct bio *bio,struct page *page, +unsigned int len,unsigned int offset) +{ +bool same_page = false; + +if (!__bio_try_merge_page (bio, page, len, offset, &same_page)) { +if (WARN_ON_ONCE (bio_full (bio, len))) +return -EINVAL ; +__bio_add_page (bio, page, len, offset); +return 0 ; + } + +if (same_page) +put_page (page); +return 0 ; +} + +static int bio_iov_add_zone_append_page (struct bio *bio,struct page *page, +unsigned int len,unsigned int offset) +{ +struct request_queue *q =bdev_get_queue (bio->bi_bdev); +bool same_page = false; + +if (bio_add_hw_page (q, bio, page, len, offset, +queue_max_zone_append_sectors (q), &same_page) != len) +return -EINVAL ; +if (same_page) +put_page (page); +return 0 ; +} +#define PAGE_PTRS_PER_BVEC (sizeof(struct bio_vec) / sizeof(struct page *))/**
@@ -1089,7 +1120,6 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)unsigned short entries_left = bio->bi_max_vecs - bio->bi_vcnt;struct bio_vec *bv = bio->bi_io_vec + bio->bi_vcnt;struct page **pages = (struct page **)bv; -bool same_page = false;ssize_t size, left;unsigned len, i;size_t offset;
@@ -1098,7 +1128,7 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)* Move page array up in the allocated memory for the bio vecs as far as * possible so that we can start filling biovecs from the beginning * without overwriting the temporary page array. -*/ +*/ BUILD_BUG_ON (PAGE_PTRS_PER_BVEC <2 ); pages += entries_left * (PAGE_PTRS_PER_BVEC -1 );
@@ -1108,18 +1138,18 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)for (left = size, i =0 ; left >0 ; left -= len, i++) {struct page *page = pages[i]; +int ret; len =min_t (size_t,PAGE_SIZE - offset, left); +if (bio_op (bio) ==REQ_OP_ZONE_APPEND ) + ret =bio_iov_add_zone_append_page (bio, page, len, + offset); +else + ret =bio_iov_add_page (bio, page, len, offset); -if (__bio_try_merge_page (bio, page, len, offset, &same_page)) { -if (same_page) -put_page (page); - }else { -if (WARN_ON_ONCE (bio_full (bio, len))) { -bio_put_pages (pages + i, left, offset); -return -EINVAL ; - } -__bio_add_page (bio, page, len, offset); +if (ret) { +bio_put_pages (pages + i, left, offset); +return ret; } offset =0 ; }
@@ -1128,51 +1158,6 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)return 0 ; } -static int __bio_iov_append_get_pages (struct bio *bio,struct iov_iter *iter) -{ -unsigned short nr_pages = bio->bi_max_vecs - bio->bi_vcnt; -unsigned short entries_left = bio->bi_max_vecs - bio->bi_vcnt; -struct request_queue *q =bdev_get_queue (bio->bi_bdev); -unsigned int max_append_sectors =queue_max_zone_append_sectors (q); -struct bio_vec *bv = bio->bi_io_vec + bio->bi_vcnt; -struct page **pages = (struct page **)bv; -ssize_t size, left; -unsigned len, i; -size_t offset; -int ret =0 ; - -/* -* Move page array up in the allocated memory for the bio vecs as far as -* possible so that we can start filling biovecs from the beginning -* without overwriting the temporary page array. -*/ -BUILD_BUG_ON (PAGE_PTRS_PER_BVEC <2 ); - pages += entries_left * (PAGE_PTRS_PER_BVEC -1 ); - - size =iov_iter_get_pages (iter, pages,LONG_MAX , nr_pages, &offset); -if (unlikely (size <=0 )) -return size ? size : -EFAULT ; - -for (left = size, i =0 ; left >0 ; left -= len, i++) { -struct page *page = pages[i]; -bool same_page = false; - - len =min_t (size_t,PAGE_SIZE - offset, left); -if (bio_add_hw_page (q, bio, page, len, offset, - max_append_sectors, &same_page) != len) { -bio_put_pages (pages + i, left, offset); - ret = -EINVAL ; -break ; - } -if (same_page) -put_page (page); - offset =0 ; - } - -iov_iter_advance (iter, size - left); -return ret; -} -/** * bio_iov_iter_get_pages - add user or kernel pages to a bio * @bio: bio to add pages to
@@ -1207,10 +1192,7 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter) }do { -if (bio_op (bio) ==REQ_OP_ZONE_APPEND ) - ret =__bio_iov_append_get_pages (bio, iter); -else - ret =__bio_iov_iter_get_pages (bio, iter); + ret =__bio_iov_iter_get_pages (bio, iter); }while (!ret &&iov_iter_count (iter) && !bio_full (bio,0 ));/* don't account direct I/O as memory stall */
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 555/779 block: ensure iov_iter advances for added pages
In reply to Greg Kroah-HartmanFrom: Keith Busch <[email protected]>
[ Upstream commit 325347d965e7ccf5424a05398807a6d801846612 ]
There are cases where a bio may not accept additional pages, and the iov needs to advance to the last data length that was accepted. The zone append used to handle this correctly, but was inadvertently broken when the setup was made common with the normal r/w case.
--- block/bio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
block/bio.c +4 -4
@@ -1123,6 +1123,7 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)ssize_t size, left;unsigned len, i;size_t offset; +int ret =0 ;/* * Move page array up in the allocated memory for the bio vecs as far as
@@ -1138,7 +1139,6 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)for (left = size, i =0 ; left >0 ; left -= len, i++) {struct page *page = pages[i]; -int ret; len =min_t (size_t,PAGE_SIZE - offset, left);if (bio_op (bio) ==REQ_OP_ZONE_APPEND )
@@ -1149,13 +1149,13 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)if (ret) {bio_put_pages (pages + i, left, offset); -return ret; +break ; } offset =0 ; } -iov_iter_advance (iter, size); -return 0 ; +iov_iter_advance (iter, size - left); +return ret; }/**
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 556/779 jbd2: fix outstanding credits assert in jbd2_journal_commit_transaction()
In reply to Greg Kroah-HartmanFrom: Zhang Yi <[email protected]>
[ Upstream commit a89573ce4ad32f19f43ec669771726817e185be0 ]
We catch an assert problem in jbd2_journal_commit_transaction() when doing fsstress and request falut injection tests. The problem is happened in a race condition between jbd2_journal_commit_transaction() and ext4_end_io_end(). Firstly, ext4_writepages() writeback dirty pages and start reserved handle, and then the journal was aborted due to some previous metadata IO error, jbd2_journal_abort() start to commit current running transaction, the committing procedure could be raced by ext4_end_io_end() and lead to subtract j_reserved_credits twice from commit_transaction->t_outstanding_credits, finally the t_outstanding_credits is mistakenly smaller than t_nr_buffers and trigger assert.
kjournald2 kworker
jbd2_journal_commit_transaction()
write_unlock(&journal->j_state_lock); atomic_sub(j_reserved_credits, t_outstanding_credits); //sub once
jbd2_journal_start_reserved()
start_this_handle() //detect aborted journal
jbd2_journal_free_reserved() //get running transaction
read_lock(&journal->j_state_lock)
__jbd2_journal_unreserve_handle()
atomic_sub(j_reserved_credits, t_outstanding_credits);
//sub again
read_unlock(&journal->j_state_lock); journal->j_running_transaction = NULL; J_ASSERT(t_nr_buffers <= t_outstanding_credits) //bomb!!!
Fix this issue by using journal->j_state_lock to protect the subtraction in jbd2_journal_commit_transaction().
--- fs/jbd2/commit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/jbd2/commit.c +1 -1
@@ -564,13 +564,13 @@ void jbd2_journal_commit_transaction(journal_t *journal)*/ jbd2_journal_switch_revoke_table (journal); +write_lock (&journal->j_state_lock);/* * Reserved credits cannot be claimed anymore, free them */ atomic_sub (atomic_read (&journal->j_reserved_credits), &commit_transaction->t_outstanding_credits); -write_lock (&journal->j_state_lock);trace_jbd2_commit_flushing (journal, commit_transaction); stats.run.rs_flushing = jiffies; stats.run.rs_locked = jbd2_time_diff(stats.run.rs_locked,
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 557/779 ext4: recover csum seed of tmp_inode after migrating to extents
In reply to Greg Kroah-HartmanFrom: Li Lingfeng <[email protected]>
[ Upstream commit 07ea7a617d6b278fb7acedb5cbe1a81ce2de7d0c ]
When migrating to extents, the checksum seed of temporary inode need to be replaced by inode's, otherwise the inode checksums will be incorrect when swapping the inodes data.
However, the temporary inode can not match it's checksum to itself since it has lost it's own checksum seed.
mkfs.ext4 -F /dev/sdc
mount /dev/sdc /mnt/sdcxfs_io -fc "pwrite 4k 4k" -c "fsync" /mnt/sdc/testfile chattr -e /mnt/sdc/testfile
chattr +e /mnt/sdc/testfile
umount /dev/sdc
fsck -fn /dev/sdc
========
...
Pass 1: Checking inodes, blocks, and sizes
Inode 13 passes checks, but checksum does not match inode. Fix? no
...
========
The fix is simple, save the checksum seed of temporary inode, and recover it after migrating to extents.
--- fs/ext4/migrate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/ext4/migrate.c +3 -1
@@ -417,7 +417,7 @@ int ext4_ext_migrate(struct inode *inode)struct inode *tmp_inode =NULL ;struct migrate_struct lb;unsigned long max_entries; -__u32 goal; +__u32 goal, tmp_csum_seed;uid_t owner[2 ];/*
@@ -465,6 +465,7 @@ int ext4_ext_migrate(struct inode *inode)* the migration. */ ei =EXT4_I (inode); + tmp_csum_seed =EXT4_I (tmp_inode)->i_csum_seed;EXT4_I (tmp_inode)->i_csum_seed = ei->i_csum_seed;i_size_write (tmp_inode,i_size_read (inode));/*
@@ -575,6 +576,7 @@ int ext4_ext_migrate(struct inode *inode)* the inode is not visible to user space. */ tmp_inode->i_blocks =0 ; +EXT4_I (tmp_inode)->i_csum_seed = tmp_csum_seed;/* Reset the extent details */ ext4_ext_tree_init (handle, tmp_inode);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 558/779 jbd2: fix assertion jh->b_frozen_data == NULL failure when journal aborted
In reply to Greg Kroah-HartmanFrom: Zhihao Cheng <[email protected]>
[ Upstream commit 4a734f0869f970b8a9b65062ea40b09a5da9dba8 ]
Following process will fail assertion 'jh->b_frozen_data == NULL' in jbd2_journal_dirty_metadata():
jbd2_journal_commit_transaction
unlink(dir/a)
jh->b_transaction = trans1
jh->b_jlist = BJ_Metadata
journal->j_running_transaction = NULL
trans1->t_state = T_COMMITunlink(dir/b)
handle->h_trans = trans2
do_get_write_access
jh->b_modified = 0
jh->b_frozen_data = frozen_buffer
jh->b_next_transaction = trans2
jbd2_journal_dirty_metadata
is_handle_aborted
is_journal_aborted // return false
--> jbd2 abort <--
while (commit_transaction->t_buffers)
if (is_journal_aborted)
jbd2_journal_refile_buffer
__jbd2_journal_refile_buffer
WRITE_ONCE(jh->b_transaction,
jh->b_next_transaction)
WRITE_ONCE(jh->b_next_transaction, NULL)
__jbd2_journal_file_buffer(jh, BJ_Reserved)
J_ASSERT_JH(jh, jh->b_frozen_data == NULL) // assertion failure !The reproducer (See detail in [Link]) reports:
------------[ cut here ]------------ kernel BUG at fs/jbd2/transaction.c:1629! invalid opcode: 0000 [#1] PREEMPT SMP CPU: 2 PID: 584 Comm: unlink Tainted: G W 5.19.0-rc6-00115-g4a57a8400075-dirty #697 RIP: 0010:jbd2_journal_dirty_metadata+0x3c5/0x470 RSP: 0018:ffffc90000be7ce0 EFLAGS: 00010202 Call Trace: <TASK> __ext4_handle_dirty_metadata+0xa0/0x290 ext4_handle_dirty_dirblock+0x10c/0x1d0 ext4_delete_entry+0x104/0x200 __ext4_unlink+0x22b/0x360 ext4_unlink+0x275/0x390 vfs_unlink+0x20b/0x4c0 do_unlinkat+0x42f/0x4c0 __x64_sys_unlink+0x37/0x50 do_syscall_64+0x35/0x80
After journal aborting, __jbd2_journal_refile_buffer() is executed with holding @jh->b_state_lock, we can fix it by moving 'is_handle_aborted()' into the area protected by @jh->b_state_lock.
--- fs/jbd2/transaction.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
fs/jbd2/transaction.c +12 -2
@@ -1477,8 +1477,6 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)struct journal_head *jh;int ret =0 ; -if (is_handle_aborted (handle)) -return -EROFS ;if (!buffer_jbd (bh))return -EUCLEAN ;
@@ -1525,6 +1523,18 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) journal = transaction->t_journal;spin_lock (&jh->b_state_lock); +if (is_handle_aborted (handle)) { +/* +* Check journal aborting with @jh->b_state_lock locked, +* since 'jh->b_transaction' could be replaced with +* 'jh->b_next_transaction' during old transaction +* committing if journal aborted, which may fail +* assertion on 'jh->b_frozen_data == NULL'. +*/ + ret = -EROFS ; + goto out_unlock_bh; + } +if (jh->b_modified ==0 ) {/* * This buffer's got modified and becoming part
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 559/779 usb: cdns3: Dont use priv_dev uninitialized in cdns3_gadget_ep_enable()
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
[ Upstream commit 78acd4ca433425e6dd4032cfc2156c60e34931f2 ]
Clang warns:
drivers/usb/cdns3/cdns3-gadget.c:2290:11: error: variable 'priv_dev' is uninitialized when used here [-Werror,-Wuninitialized]
dev_dbg(priv_dev->dev, "usbss: invalid parameters\n");
^~~~~~~~
include/linux/dev_printk.h:155:18: note: expanded from macro 'dev_dbg'
dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__)
^~~
include/linux/dynamic_debug.h:167:7: note: expanded from macro 'dynamic_dev_dbg'
dev, fmt, ##__VA_ARGS__)
^~~
include/linux/dynamic_debug.h:152:56: note: expanded from macro '_dynamic_func_call'
__dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
^~~~~~~~~~~
include/linux/dynamic_debug.h:134:15: note: expanded from macro '__dynamic_func_call'
func(&id, ##__VA_ARGS__); \
^~~~~~~~~~~
drivers/usb/cdns3/cdns3-gadget.c:2278:31: note: initialize the variable 'priv_dev' to silence this warning
struct cdns3_device *priv_dev;
^
= NULL1 error generated.
The priv_dev assignment was moved below the if statement to avoid potentially dereferencing ep before it was checked but priv_dev is used in the dev_dbg() call.
To fix this, move the priv_dev and comp_desc assignments back to their original spot and hoist the ep check above those assignments with a call to pr_debug() instead of dev_dbg().
--- drivers/usb/cdns3/cdns3-gadget.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/usb/cdns3/cdns3-gadget.c +8 -4
@@ -2280,16 +2280,20 @@ static int cdns3_gadget_ep_enable(struct usb_ep *ep,int ret =0 ;int val; +if (!ep) { +pr_debug ("usbss: ep not configured?\n" ); +return -EINVAL ; + } + priv_ep =ep_to_cdns3_ep (ep); + priv_dev = priv_ep->cdns3_dev; + comp_desc = priv_ep->endpoint.comp_desc; -if (!ep || !desc || desc->bDescriptorType !=USB_DT_ENDPOINT ) { +if (!desc || desc->bDescriptorType !=USB_DT_ENDPOINT ) {dev_dbg (priv_dev->dev,"usbss: invalid parameters\n" );return -EINVAL ; } - comp_desc = priv_ep->endpoint.comp_desc; - priv_dev = priv_ep->cdns3_dev; -if (!desc->wMaxPacketSize) {dev_err (priv_dev->dev,"usbss: missing wMaxPacketSize\n" );return -EINVAL ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 560/779 opp: Fix error check in dev_pm_opp_attach_genpd()
In reply to Greg Kroah-HartmanFrom: Tang Bin <[email protected]>
[ Upstream commit 4ea9496cbc959eb5c78f3e379199aca9ef4e386b ]
dev_pm_domain_attach_by_name() may return NULL in some cases, so IS_ERR() doesn't meet the requirements. Thus fix it.
--- drivers/opp/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/opp/core.c +2 -2
@@ -2388,8 +2388,8 @@ struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, } virt_dev =dev_pm_domain_attach_by_name (dev, *name); -if (IS_ERR (virt_dev)) { - ret =PTR_ERR (virt_dev); +if (IS_ERR_OR_NULL (virt_dev)) { + ret =PTR_ERR (virt_dev) ? : -ENODEV ;dev_err (dev,"Couldn't attach to pm_domain: %d\n" , ret); goto err; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 561/779 ASoC: cros_ec_codec: Fix refcount leak in cros_ec_codec_platform_probe
In reply to Greg Kroah-HartmanFrom: Miaoqian Lin <[email protected]>
[ Upstream commit 0a034d93ee929a9ea89f3fa5f1d8492435b9ee6e ]
of_parse_phandle() returns a node pointer with refcount incremented, we should use of_node_put() on it when not need anymore. Add missing of_node_put() to avoid refcount leak.
--- sound/soc/codecs/cros_ec_codec.c | 1 + 1 file changed, 1 insertion(+)
sound/soc/codecs/cros_ec_codec.c +1 -0
@@ -994,6 +994,7 @@ static int cros_ec_codec_platform_probe(struct platform_device *pdev)dev_dbg (dev,"ap_shm_phys_addr=%#llx len=%#x\n" , priv->ap_shm_phys_addr, priv->ap_shm_len); } +of_node_put (node); }#endif
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 562/779 ASoC: samsung: Fix error handling in aries_audio_probe
In reply to Greg Kroah-HartmanFrom: Miaoqian Lin <[email protected]>
[ Upstream commit 3e2649c5e8643bea0867bb1dd970fedadb0eb7f3 ]
of_get_child_by_name() returns a node pointer with refcount incremented, we should use of_node_put() on it when not need anymore. This function is missing of_node_put(cpu) in the error path. Fix this by goto out label. of_node_put() will check NULL pointer.
--- sound/soc/samsung/aries_wm8994.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
sound/soc/samsung/aries_wm8994.c +4 -2
@@ -628,8 +628,10 @@ static int aries_audio_probe(struct platform_device *pdev)return -EINVAL ; codec =of_get_child_by_name (dev->of_node,"codec" ); -if (!codec) -return -EINVAL ; +if (!codec) { + ret = -EINVAL ; + goto out; + }for_each_card_prelinks (card, i, dai_link) { dai_link->codecs->of_node = of_parse_phandle(codec,
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 563/779 ASoC: imx-audmux: Silence a clang warning
In reply to Greg Kroah-HartmanFrom: Fabio Estevam <[email protected]>
[ Upstream commit 2f4a8171da06609bb6a063630ed546ee3d93dad7 ]
Change the of_device_get_match_data() cast to (uintptr_t) to silence the following clang warning:
sound/soc/fsl/imx-audmux.c:301:16: warning: cast to smaller integer type 'enum imx_audmux_type' from 'const void *' [-Wvoid-pointer-to-enum-cast]
--- sound/soc/fsl/imx-audmux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/fsl/imx-audmux.c +1 -1
@@ -298,7 +298,7 @@ static int imx_audmux_probe(struct platform_device *pdev) audmux_clk =NULL ; } - audmux_type = (enum imx_audmux_type )of_device_get_match_data (&pdev->dev); + audmux_type = (uintptr_t )of_device_get_match_data (&pdev->dev);switch (audmux_type) {case IMX31_AUDMUX :
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 564/779 ASoC: mediatek: mt8173: Fix refcount leak in mt8173_rt5650_rt5676_dev_probe
In reply to Greg Kroah-HartmanFrom: Miaoqian Lin <[email protected]>
[ Upstream commit ae4f11c1ed2d67192fdf3d89db719ee439827c11 ]
of_parse_phandle() returns a node pointer with refcount incremented, we should use of_node_put() on it when not need anymore. Fix missing of_node_put() in error paths.
--- sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c +7 -3
@@ -256,14 +256,16 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev)if (!mt8173_rt5650_rt5676_dais[DAI_LINK_CODEC_I2S ].codecs[0 ].of_node) {dev_err (&pdev->dev,"Property 'audio-codec' missing or invalid\n" ); -return -EINVAL ; + ret = -EINVAL ; + goto put_node; } mt8173_rt5650_rt5676_dais[DAI_LINK_CODEC_I2S ].codecs[1 ].of_node =of_parse_phandle (pdev->dev.of_node,"mediatek,audio-codec" ,1 );if (!mt8173_rt5650_rt5676_dais[DAI_LINK_CODEC_I2S ].codecs[1 ].of_node) {dev_err (&pdev->dev,"Property 'audio-codec' missing or invalid\n" ); -return -EINVAL ; + ret = -EINVAL ; + goto put_node; } mt8173_rt5650_rt5676_codec_conf[0 ].dlc.of_node = mt8173_rt5650_rt5676_dais[DAI_LINK_CODEC_I2S ].codecs[1 ].of_node;
@@ -276,7 +278,8 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev)if (!mt8173_rt5650_rt5676_dais[DAI_LINK_HDMI_I2S ].codecs->of_node) {dev_err (&pdev->dev,"Property 'audio-codec' missing or invalid\n" ); -return -EINVAL ; + ret = -EINVAL ; + goto put_node; } card->dev = &pdev->dev;
@@ -286,6 +289,7 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev)dev_err (&pdev->dev,"%s snd_soc_register_card fail %d\n" , __func__, ret); +put_node:of_node_put (platform_node);return ret; }
Signature · 1 line
2.35.1
Re: [PATCH 5.15 564/779] ASoC: mediatek: mt8173: Fix refcount leak in mt8173_rt5650_rt5676_dev_probe
Hi!
Quoted 7 lines
From: Miaoqian Lin <[email protected]>
[ Upstream commit
ae4f11c1ed2d67192fdf3d89db719ee439827c11]
of_parse_phandle()returns a node pointer with refcount incremented, we should useof_node_put()on it when not need anymore. Fix missingof_node_put()in error paths.
Is this correct?
Quoted 9 lines
+++
b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.csound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c +2
-1@@ -256,14 +256,16 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev)if (!mt8173_rt5650_rt5676_dais[DAI_LINK_CODEC_I2S ].codecs[0 ].of_node) {dev_err (&pdev->dev,"Property 'audio-codec' missing or invalid\n" ); -return -EINVAL ; + ret = -EINVAL ; + goto put_node; }
...
sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev) · line 295
Quoted 7 lines
sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c +1
-0dev_err (&pdev->dev,"%s snd_soc_register_card fail %d\n" , __func__, ret); +put_node:of_node_put (platform_node);return ret; }
In success case, platform_node is stored:
dai_link->platforms->of_node = platform_node;
I guess we should not be doing put in that case.
Best regards,
Pavel
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Greg Kroah-Hartman
maintainerPATCH 565/779 ASoC: mt6797-mt6351: Fix refcount leak in mt6797_mt6351_dev_probe
In reply to Greg Kroah-HartmanFrom: Miaoqian Lin <[email protected]>
[ Upstream commit 7472eb8d7dd12b6b9b1a4f4527719cc9c7f5965f ]
of_parse_phandle() returns a node pointer with refcount incremented, we should use of_node_put() on it when not need anymore. Add missing of_node_put() to avoid refcount leak.
--- sound/soc/mediatek/mt6797/mt6797-mt6351.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
sound/soc/mediatek/mt6797/mt6797-mt6351.c +5 -1
@@ -217,7 +217,8 @@ static int mt6797_mt6351_dev_probe(struct platform_device *pdev)if (!codec_node) {dev_err (&pdev->dev,"Property 'audio-codec' missing or invalid\n" ); -return -EINVAL ; + ret = -EINVAL ; + goto put_platform_node; }for_each_card_prelinks (card, i, dai_link) {if (dai_link->codecs->name)
@@ -230,6 +231,9 @@ static int mt6797_mt6351_dev_probe(struct platform_device *pdev)dev_err (&pdev->dev,"%s snd_soc_register_card fail %d\n" , __func__, ret); +of_node_put (codec_node); +put_platform_node: +of_node_put (platform_node);return ret; }
Signature · 1 line
2.35.1
Re: [PATCH 5.15 565/779] ASoC: mt6797-mt6351: Fix refcount leak in mt6797_mt6351_dev_probe
Hi!
Quoted 7 lines
From: Miaoqian Lin <[email protected]>
[ Upstream commit
7472eb8d7dd12b6b9b1a4f4527719cc9c7f5965f]
of_parse_phandle()returns a node pointer with refcount incremented, we should useof_node_put()on it when not need anymore. Add missingof_node_put()to avoid refcount leak.
AFAICT this has serious problems:
Quoted 12 lines
+++
b/sound/soc/mediatek/mt6797/mt6797-mt6351.csound/soc/mediatek/mt6797/mt6797-mt6351.c +2
-1@@ -217,7 +217,8 @@ static int mt6797_mt6351_dev_probe(struct platform_device *pdev)if (!codec_node) {dev_err (&pdev->dev,"Property 'audio-codec' missing or invalid\n" ); -return -EINVAL ; + ret = -EINVAL ; + goto put_platform_node; }for_each_card_prelinks (card, i, dai_link) {if (dai_link->codecs->name)
sound/soc/mediatek/mt6797/mt6797-mt6351.c static int mt6797_mt6351_dev_probe(struct platform_device *pdev) · line 238
Quoted 8 lines
sound/soc/mediatek/mt6797/mt6797-mt6351.c +3
-0@@ -230,6 +231,9 @@ static int mt6797_mt6351_dev_probe(struct platform_device *pdev)dev_err (&pdev->dev,"%s snd_soc_register_card fail %d\n" , __func__, ret); +of_node_put (codec_node); +put_platform_node: +of_node_put (platform_node);return ret; }
platform_node is stashed away in struct, and so is codec_node; we should not be freeing those references in success case, right?
dai_link->platforms->of_node = platform_node;
Best regards,
Pavel
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Greg Kroah-Hartman
maintainerPATCH 566/779 ASoC: codecs: da7210: add check for i2c_add_driver
In reply to Greg Kroah-HartmanFrom: Jiasheng Jiang <[email protected]>
[ Upstream commit 82fa8f581a954ddeec1602bed9f8b4a09d100e6e ]
As i2c_add_driver could return error if fails, it should be better to check the return value.
However, if the CONFIG_I2C and CONFIG_SPI_MASTER are both true, the return value of i2c_add_driver will be covered by spi_register_driver.
Therefore, it is necessary to add check and return error if fails.
--- sound/soc/codecs/da7210.c | 2 ++ 1 file changed, 2 insertions(+)
sound/soc/codecs/da7210.c +2 -0
@@ -1336,6 +1336,8 @@ static int __init da7210_modinit(void)int ret =0 ;#if IS_ENABLED (CONFIG_I2C ) ret =i2c_add_driver (&da7210_i2c_driver); +if (ret) +return ret;#endif #if defined(CONFIG_SPI_MASTER ) ret =spi_register_driver (&da7210_spi_driver);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 567/779 ASoC: mediatek: mt8173-rt5650: Fix refcount leak in mt8173_rt5650_dev_probe
In reply to Greg Kroah-HartmanFrom: Miaoqian Lin <[email protected]>
[ Upstream commit efe2178d1a32492f99e7f1f2568eea5c88a85729 ]
of_parse_phandle() returns a node pointer with refcount incremented, we should use of_node_put() on it when not need anymore. Fix refcount leak in some error paths.
--- sound/soc/mediatek/mt8173/mt8173-rt5650.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
sound/soc/mediatek/mt8173/mt8173-rt5650.c +6 -3
@@ -280,7 +280,8 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev)if (!mt8173_rt5650_dais[DAI_LINK_CODEC_I2S ].codecs[0 ].of_node) {dev_err (&pdev->dev,"Property 'audio-codec' missing or invalid\n" ); -return -EINVAL ; + ret = -EINVAL ; + goto put_platform_node; } mt8173_rt5650_dais[DAI_LINK_CODEC_I2S ].codecs[1 ].of_node = mt8173_rt5650_dais[DAI_LINK_CODEC_I2S ].codecs[0 ].of_node;
@@ -293,7 +294,7 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev)dev_err (&pdev->dev,"%s codec_capture_dai name fail %d\n" , __func__, ret); -return ret; + goto put_platform_node; } mt8173_rt5650_dais[DAI_LINK_CODEC_I2S ].codecs[1 ].dai_name = codec_capture_dai;
@@ -315,7 +316,8 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev)if (!mt8173_rt5650_dais[DAI_LINK_HDMI_I2S ].codecs->of_node) {dev_err (&pdev->dev,"Property 'audio-codec' missing or invalid\n" ); -return -EINVAL ; + ret = -EINVAL ; + goto put_platform_node; } card->dev = &pdev->dev;
@@ -324,6 +326,7 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev)dev_err (&pdev->dev,"%s snd_soc_register_card fail %d\n" , __func__, ret); +put_platform_node:of_node_put (platform_node);return ret; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 568/779 serial: 8250: Export ICR access helpers for internal use
In reply to Greg Kroah-HartmanFrom: Maciej W. Rozycki <[email protected]>
[ Upstream commit cb5a40e3143bc64437858b337273fd63cc42e9c2 ]
Make ICR access helpers available outside 8250_port.c, however retain them as ordinary static functions so as not to regress code generation.
This is because serial_icr_write' is currently automatically inlined by GCC, however serial_icr_read' is not. Making them both static inline would grow code produced, e.g.:
$ i386-linux-gnu-size --format=gnu 8250_port-{old,new}.o
text data bss total filename
15065 3378 0 18443 8250_port-old.o
15289 3378 0 18667 8250_port-new.oand:
$ riscv64-linux-gnu-size --format=gnu 8250_port-{old,new}.o
text data bss total filename
16980 5306 0 22286 8250_port-old.o
17124 5306 0 22430 8250_port-new.owhile making them external would needlessly add a new module interface and lose the benefit from `serial_icr_write' getting inlined outside 8250_port.o.
--- drivers/tty/serial/8250/8250.h | 22 ++++++++++++++++++++++ drivers/tty/serial/8250/8250_port.c | 21 --------------------- 2 files changed, 22 insertions(+), 21 deletions(-)
drivers/tty/serial/8250/8250.h +22 -0
@@ -120,6 +120,28 @@ static inline void serial_out(struct uart_8250_port *up, int offset, int value) up->port.serial_out (&up->port, offset, value); } +/* +* For the 16C950 +*/ +static void serial_icr_write (struct uart_8250_port *up,int offset,int value) +{ +serial_out (up,UART_SCR , offset); +serial_out (up,UART_ICR , value); +} + +static unsigned int __maybe_unused serial_icr_read (struct uart_8250_port *up, +int offset) +{ +unsigned int value; + +serial_icr_write (up,UART_ACR , up->acr |UART_ACR_ICRRD ); +serial_out (up,UART_SCR , offset); + value =serial_in (up,UART_ICR ); +serial_icr_write (up,UART_ACR , up->acr); + +return value; +} +void serial8250_clear_and_reinit_fifos (struct uart_8250_port *p);static inline int serial_dl_read (struct uart_8250_port *up)
drivers/tty/serial/8250/8250_port.c +0 -21
@@ -537,27 +537,6 @@ serial_port_out_sync(struct uart_port *p, int offset, int value) } } -/* -* For the 16C950 -*/ -static void serial_icr_write (struct uart_8250_port *up,int offset,int value) -{ -serial_out (up,UART_SCR , offset); -serial_out (up,UART_ICR , value); -} - -static unsigned int serial_icr_read (struct uart_8250_port *up,int offset) -{ -unsigned int value; - -serial_icr_write (up,UART_ACR , up->acr |UART_ACR_ICRRD ); -serial_out (up,UART_SCR , offset); - value =serial_in (up,UART_ICR ); -serial_icr_write (up,UART_ACR , up->acr); - -return value; -} -/* * FIFO support. */
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 569/779 serial: 8250: dma: Allow driver operations before starting DMA transfers
In reply to Greg Kroah-HartmanFrom: Miquel Raynal <[email protected]>
[ Upstream commit e4fb03fe10c5e7a5d9aef7cefe815253274fb9ee ]
One situation where this could be used is when configuring the UART controller to be the DMA flow controller. This is a typical case where the driver might need to program a few more registers before starting a DMA transfer. Provide the necessary infrastructure to support this case.
--- drivers/tty/serial/8250/8250.h | 18 ++++++++++++++++++ drivers/tty/serial/8250/8250_dma.c | 4 ++++ 2 files changed, 22 insertions(+)
drivers/tty/serial/8250/8250.h +18 -0
@@ -17,6 +17,8 @@struct uart_8250_dma {int (*tx_dma)(struct uart_8250_port *p);int (*rx_dma)(struct uart_8250_port *p); +void (*prepare_tx_dma)(struct uart_8250_port *p); +void (*prepare_rx_dma)(struct uart_8250_port *p);/* Filter function */ dma_filter_fn fn;
@@ -331,6 +333,22 @@ extern int serial8250_rx_dma(struct uart_8250_port *);extern void serial8250_rx_dma_flush (struct uart_8250_port *);extern int serial8250_request_dma (struct uart_8250_port *);extern void serial8250_release_dma (struct uart_8250_port *); + +static inline void serial8250_do_prepare_tx_dma (struct uart_8250_port *p) +{ +struct uart_8250_dma *dma = p->dma; + +if (dma->prepare_tx_dma) + dma->prepare_tx_dma (p); +} + +static inline void serial8250_do_prepare_rx_dma (struct uart_8250_port *p) +{ +struct uart_8250_dma *dma = p->dma; + +if (dma->prepare_rx_dma) + dma->prepare_rx_dma (p); +}#else static inline int serial8250_tx_dma (struct uart_8250_port *p) {
drivers/tty/serial/8250/8250_dma.c +4 -0
@@ -86,6 +86,8 @@ int serial8250_tx_dma(struct uart_8250_port *p) dma->tx_size =CIRC_CNT_TO_END (xmit->head, xmit->tail,UART_XMIT_SIZE ); +serial8250_do_prepare_tx_dma (p); + desc = dmaengine_prep_slave_single(dma->txchan, dma->tx_addr + xmit->tail, dma->tx_size, DMA_MEM_TO_DEV,
@@ -123,6 +125,8 @@ int serial8250_rx_dma(struct uart_8250_port *p)if (dma->rx_running)return 0 ; +serial8250_do_prepare_rx_dma (p); + desc =dmaengine_prep_slave_single (dma->rxchan, dma->rx_addr, dma->rx_size,DMA_DEV_TO_MEM ,DMA_PREP_INTERRUPT |DMA_CTRL_ACK );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 570/779 serial: 8250_dw: Store LSR into lsr_saved_flags in dw8250_tx_wait_empty()
In reply to Greg Kroah-HartmanFrom: Ilpo Järvinen <[email protected]>
[ Upstream commit af14f3007e2dca0d112f10f6717ba43093f74e81 ]
Make sure LSR flags are preserved in dw8250_tx_wait_empty(). This function is called from a low-level out function and therefore cannot call serial_lsr_in() as it would lead to infinite recursion.
It is borderline if the flags need to be saved here at all since this code relates to writing LCR register which usually implies no important characters should be arriving.
--- drivers/tty/serial/8250/8250_dw.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/tty/serial/8250/8250_dw.c +3 -0
@@ -124,12 +124,15 @@ static void dw8250_check_lcr(struct uart_port *p, int value)/* Returns once the transmitter is empty or we run out of retries */ static void dw8250_tx_wait_empty (struct uart_port *p) { +struct uart_8250_port *up =up_to_u8250p (p);unsigned int tries =20000 ;unsigned int delay_threshold = tries -1000 ;unsigned int lsr;while (tries--) { lsr =readb (p->membase + (UART_LSR << p->regshift)); + up->lsr_saved_flags |= lsr &LSR_SAVE_FLAGS ; +if (lsr &UART_LSR_TEMT )break ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 571/779 ASoC: codecs: msm8916-wcd-digital: move gains from SX_TLV to S8_TLV
In reply to Greg Kroah-HartmanFrom: Srinivas Kandagatla <[email protected]>
[ Upstream commit 5babb012c847beb6c8c7108fd78f650b7a2c6054 ]
move all the digital gains form using SX_TLV to S8_TLV, these gains are actually 8 bit gains with 7th signed bit and ranges from -84dB to +40dB
rest of the Qualcomm wcd codecs uses these properly.
--- sound/soc/codecs/msm8916-wcd-digital.c | 46 +++++++++++++------------- 1 file changed, 23 insertions(+), 23 deletions(-)
sound/soc/codecs/msm8916-wcd-digital.c +23 -23
@@ -328,8 +328,8 @@ static const struct snd_kcontrol_new rx1_mix2_inp1_mux = SOC_DAPM_ENUM(static const struct snd_kcontrol_new rx2_mix2_inp1_mux =SOC_DAPM_ENUM ("RX2 MIX2 INP1 Mux" , rx2_mix2_inp1_chain_enum); -/* Digital Gain control -38.4 dB to +38.4 dB in 0.3 dB steps */ -static const DECLARE_TLV_DB_SCALE(digital_gain, -3840, 30, 0); +/* Digital Gain control -84 dB to +40 dB in 1 dB steps */ +static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400);/* Cutoff Freq for High Pass Filter at -3dB */ static const char *const hpf_cutoff_text[] = {
@@ -510,15 +510,15 @@ static int wcd_iir_filter_info(struct snd_kcontrol *kcontrol,static const struct snd_kcontrol_new msm8916_wcd_digital_snd_controls[] = {SOC_SINGLE_S8_TLV ("RX1 Digital Volume" ,LPASS_CDC_RX1_VOL_CTL_B2_CTL , --128 ,127 , digital_gain), +-84 ,40 , digital_gain),SOC_SINGLE_S8_TLV ("RX2 Digital Volume" ,LPASS_CDC_RX2_VOL_CTL_B2_CTL , --128 ,127 , digital_gain), +-84 ,40 , digital_gain),SOC_SINGLE_S8_TLV ("RX3 Digital Volume" ,LPASS_CDC_RX3_VOL_CTL_B2_CTL , --128 ,127 , digital_gain), +-84 ,40 , digital_gain),SOC_SINGLE_S8_TLV ("TX1 Digital Volume" ,LPASS_CDC_TX1_VOL_CTL_GAIN , --128 ,127 , digital_gain), +-84 ,40 , digital_gain),SOC_SINGLE_S8_TLV ("TX2 Digital Volume" ,LPASS_CDC_TX2_VOL_CTL_GAIN , --128 ,127 , digital_gain), +-84 ,40 , digital_gain),SOC_ENUM ("TX1 HPF Cutoff" , tx1_hpf_cutoff_enum),SOC_ENUM ("TX2 HPF Cutoff" , tx2_hpf_cutoff_enum),SOC_SINGLE ("TX1 HPF Switch" ,LPASS_CDC_TX1_MUX_CTL ,3 ,1 ,0 ),
@@ -553,22 +553,22 @@ static const struct snd_kcontrol_new msm8916_wcd_digital_snd_controls[] = {WCD_IIR_FILTER_CTL ("IIR2 Band3" ,IIR2 ,BAND3 ),WCD_IIR_FILTER_CTL ("IIR2 Band4" ,IIR2 ,BAND4 ),WCD_IIR_FILTER_CTL ("IIR2 Band5" ,IIR2 ,BAND5 ), -SOC_SINGLE_SX_TLV ("IIR1 INP1 Volume" ,LPASS_CDC_IIR1_GAIN_B1_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("IIR1 INP2 Volume" ,LPASS_CDC_IIR1_GAIN_B2_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("IIR1 INP3 Volume" ,LPASS_CDC_IIR1_GAIN_B3_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("IIR1 INP4 Volume" ,LPASS_CDC_IIR1_GAIN_B4_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("IIR2 INP1 Volume" ,LPASS_CDC_IIR2_GAIN_B1_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("IIR2 INP2 Volume" ,LPASS_CDC_IIR2_GAIN_B2_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("IIR2 INP3 Volume" ,LPASS_CDC_IIR2_GAIN_B3_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("IIR2 INP4 Volume" ,LPASS_CDC_IIR2_GAIN_B4_CTL , - 0, -84, 40, digital_gain), +SOC_SINGLE_S8_TLV ("IIR1 INP1 Volume" ,LPASS_CDC_IIR1_GAIN_B1_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("IIR1 INP2 Volume" ,LPASS_CDC_IIR1_GAIN_B2_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("IIR1 INP3 Volume" ,LPASS_CDC_IIR1_GAIN_B3_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("IIR1 INP4 Volume" ,LPASS_CDC_IIR1_GAIN_B4_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("IIR2 INP1 Volume" ,LPASS_CDC_IIR2_GAIN_B1_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("IIR2 INP2 Volume" ,LPASS_CDC_IIR2_GAIN_B2_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("IIR2 INP3 Volume" ,LPASS_CDC_IIR2_GAIN_B3_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("IIR2 INP4 Volume" ,LPASS_CDC_IIR2_GAIN_B4_CTL , + -84, 40, digital_gain), };
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 572/779 ASoC: codecs: wcd9335: move gains from SX_TLV to S8_TLV
In reply to Greg Kroah-HartmanFrom: Srinivas Kandagatla <[email protected]>
[ Upstream commit 2fbe0953732e06b471cdedbf6f615b84235580d8 ]
move all the digital gains form using SX_TLV to S8_TLV, these gains are actually 8 bit gains with 7th signed bit and ranges from -84dB to +40dB
rest of the Qualcomm wcd codecs uses these properly.
--- sound/soc/codecs/wcd9335.c | 81 +++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 45 deletions(-)
sound/soc/codecs/wcd9335.c +36 -45
@@ -2252,51 +2252,42 @@ static int wcd9335_rx_hph_mode_put(struct snd_kcontrol *kc,static const struct snd_kcontrol_new wcd9335_snd_controls[] = {/* -84dB min - 40dB max */ -SOC_SINGLE_SX_TLV ("RX0 Digital Volume" ,WCD9335_CDC_RX0_RX_VOL_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("RX1 Digital Volume" ,WCD9335_CDC_RX1_RX_VOL_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("RX2 Digital Volume" ,WCD9335_CDC_RX2_RX_VOL_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("RX3 Digital Volume" ,WCD9335_CDC_RX3_RX_VOL_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("RX4 Digital Volume" ,WCD9335_CDC_RX4_RX_VOL_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("RX5 Digital Volume" ,WCD9335_CDC_RX5_RX_VOL_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("RX6 Digital Volume" ,WCD9335_CDC_RX6_RX_VOL_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("RX7 Digital Volume" ,WCD9335_CDC_RX7_RX_VOL_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("RX8 Digital Volume" ,WCD9335_CDC_RX8_RX_VOL_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("RX0 Mix Digital Volume" , -WCD9335_CDC_RX0_RX_VOL_MIX_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("RX1 Mix Digital Volume" , -WCD9335_CDC_RX1_RX_VOL_MIX_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("RX2 Mix Digital Volume" , -WCD9335_CDC_RX2_RX_VOL_MIX_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("RX3 Mix Digital Volume" , -WCD9335_CDC_RX3_RX_VOL_MIX_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("RX4 Mix Digital Volume" , -WCD9335_CDC_RX4_RX_VOL_MIX_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("RX5 Mix Digital Volume" , -WCD9335_CDC_RX5_RX_VOL_MIX_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("RX6 Mix Digital Volume" , -WCD9335_CDC_RX6_RX_VOL_MIX_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("RX7 Mix Digital Volume" , -WCD9335_CDC_RX7_RX_VOL_MIX_CTL , -0 ,-84 ,40 , digital_gain), -SOC_SINGLE_SX_TLV ("RX8 Mix Digital Volume" , -WCD9335_CDC_RX8_RX_VOL_MIX_CTL , -0 ,-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX0 Digital Volume" ,WCD9335_CDC_RX0_RX_VOL_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX1 Digital Volume" ,WCD9335_CDC_RX1_RX_VOL_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX2 Digital Volume" ,WCD9335_CDC_RX2_RX_VOL_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX3 Digital Volume" ,WCD9335_CDC_RX3_RX_VOL_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX4 Digital Volume" ,WCD9335_CDC_RX4_RX_VOL_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX5 Digital Volume" ,WCD9335_CDC_RX5_RX_VOL_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX6 Digital Volume" ,WCD9335_CDC_RX6_RX_VOL_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX7 Digital Volume" ,WCD9335_CDC_RX7_RX_VOL_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX8 Digital Volume" ,WCD9335_CDC_RX8_RX_VOL_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX0 Mix Digital Volume" ,WCD9335_CDC_RX0_RX_VOL_MIX_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX1 Mix Digital Volume" ,WCD9335_CDC_RX1_RX_VOL_MIX_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX2 Mix Digital Volume" ,WCD9335_CDC_RX2_RX_VOL_MIX_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX3 Mix Digital Volume" ,WCD9335_CDC_RX3_RX_VOL_MIX_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX4 Mix Digital Volume" ,WCD9335_CDC_RX4_RX_VOL_MIX_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX5 Mix Digital Volume" ,WCD9335_CDC_RX5_RX_VOL_MIX_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX6 Mix Digital Volume" ,WCD9335_CDC_RX6_RX_VOL_MIX_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX7 Mix Digital Volume" ,WCD9335_CDC_RX7_RX_VOL_MIX_CTL , +-84 ,40 , digital_gain), +SOC_SINGLE_S8_TLV ("RX8 Mix Digital Volume" ,WCD9335_CDC_RX8_RX_VOL_MIX_CTL , +-84 ,40 , digital_gain),SOC_ENUM ("RX INT0_1 HPF cut off" , cf_int0_1_enum),SOC_ENUM ("RX INT0_2 HPF cut off" , cf_int0_2_enum),SOC_ENUM ("RX INT1_1 HPF cut off" , cf_int1_1_enum),
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 573/779 rpmsg: char: Add mutex protection for rpmsg_eptdev_open()
In reply to Greg Kroah-HartmanFrom: Shengjiu Wang <[email protected]>
[ Upstream commit abe13e9a561d6b3e82b21362c0d6dd3ecd8a5b13 ]
There is no mutex protection for rpmsg_eptdev_open(), especially for eptdev->ept read and write operation. It may cause issues when multiple instances call rpmsg_eptdev_open() in parallel,the return state may be success or EBUSY.
--- drivers/rpmsg/rpmsg_char.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/rpmsg/rpmsg_char.c +6 -1
@@ -127,8 +127,11 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)struct rpmsg_device *rpdev = eptdev->rpdev;struct device *dev = &eptdev->dev; -if (eptdev->ept) +mutex_lock (&eptdev->ept_lock); +if (eptdev->ept) { +mutex_unlock (&eptdev->ept_lock);return -EBUSY ; + }get_device (dev);
@@ -136,11 +139,13 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)if (!ept) {dev_err (dev,"failed to open %s\n" , eptdev->chinfo.name);put_device (dev); +mutex_unlock (&eptdev->ept_lock);return -EINVAL ; } eptdev->ept = ept; filp->private_data = eptdev; +mutex_unlock (&eptdev->ept_lock);return 0 ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 574/779 rpmsg: mtk_rpmsg: Fix circular locking dependency
In reply to Greg Kroah-HartmanFrom: AngeloGioacchino Del Regno <[email protected]>
[ Upstream commit 353d9214682e65c55cdffad8c82139a3321c5f13 ]
During execution of the worker that's used to register rpmsg devices we are safely locking the channels mutex but, when creating a new endpoint for such devices, we are registering a IPI on the SCP, which then makes the SCP to trigger an interrupt, lock its own mutex and in turn register more subdevices.
This creates a circular locking dependency situation, as the mtk_rpmsg channels_lock will then depend on the SCP IPI lock.
[ 15.447736] ======================================================
[ 15.460158] WARNING: possible circular locking dependency detected
[ 15.460161] 5.17.0-next-20220324+ #399 Not tainted
[ 15.460165] ------------------------------------------------------
[ 15.460166] kworker/0:3/155 is trying to acquire lock:
[ 15.460170] ffff5b4d0eaf1308 (&scp->ipi_desc[i].lock){+.+.}-{4:4}, at: scp_ipi_lock+0x34/0x50 [mtk_scp_ipi]
[ 15.504958]
[] but task is already holding lock:
[ 15.504960] ffff5b4d0e8f1918 (&mtk_subdev->channels_lock){+.+.}-{4:4}, at: mtk_register_device_work_function+0x50/0x1cc [mtk_rpmsg]
[ 15.504978][] which lock already depends on the new lock.
[ 15.504980]
[] the existing dependency chain (in reverse order) is:
[ 15.504982]
[] -> #1 (&mtk_subdev->channels_lock){+.+.}-{4:4}:
[ 15.504990] lock_acquire+0x68/0x84
[ 15.504999] __mutex_lock+0xa4/0x3e0
[ 15.505007] mutex_lock_nested+0x40/0x70
[ 15.505012] mtk_rpmsg_ns_cb+0xe4/0x134 [mtk_rpmsg]
[ 15.641684] mtk_rpmsg_ipi_handler+0x38/0x64 [mtk_rpmsg]
[ 15.641693] scp_ipi_handler+0xbc/0x180 [mtk_scp]
[ 15.663905] mt8192_scp_irq_handler+0x44/0xa4 [mtk_scp]
[ 15.663915] scp_irq_handler+0x6c/0xa0 [mtk_scp]
[ 15.685779] irq_thread_fn+0x34/0xa0
[ 15.685785] irq_thread+0x18c/0x240
[ 15.685789] kthread+0x104/0x110
[ 15.709579] ret_from_fork+0x10/0x20
[ 15.709586]
[] -> #0 (&scp->ipi_desc[i].lock){+.+.}-{4:4}:
[ 15.731271] __lock_acquire+0x11e4/0x1910
[ 15.740367] lock_acquire.part.0+0xd8/0x220
[ 15.749813] lock_acquire+0x68/0x84
[ 15.757861] __mutex_lock+0xa4/0x3e0
[ 15.766084] mutex_lock_nested+0x40/0x70
[ 15.775006] scp_ipi_lock+0x34/0x50 [mtk_scp_ipi]
[ 15.785503] scp_ipi_register+0x40/0xa4 [mtk_scp_ipi]
[ 15.796697] scp_register_ipi+0x1c/0x30 [mtk_scp]
[ 15.807194] mtk_rpmsg_create_ept+0xa0/0x108 [mtk_rpmsg]
[ 15.818912] rpmsg_create_ept+0x44/0x60
[ 15.827660] cros_ec_rpmsg_probe+0x15c/0x1f0
[ 15.837282] rpmsg_dev_probe+0x128/0x1d0
[ 15.846203] really_probe.part.0+0xa4/0x2a0
[ 15.855649] __driver_probe_device+0xa0/0x150
[ 15.865443] driver_probe_device+0x48/0x150
[ 15.877157] __device_attach_driver+0xc0/0x12c
[ 15.889359] bus_for_each_drv+0x80/0xe0
[ 15.900330] __device_attach+0xe4/0x190
[ 15.911303] device_initial_probe+0x1c/0x2c
[ 15.922969] bus_probe_device+0xa8/0xb0
[ 15.933927] device_add+0x3a8/0x8a0
[ 15.944193] device_register+0x28/0x40
[ 15.954970] rpmsg_register_device+0x5c/0xa0
[ 15.966782] mtk_register_device_work_function+0x148/0x1cc [mtk_rpmsg]
[ 15.983146] process_one_work+0x294/0x664
[ 15.994458] worker_thread+0x7c/0x45c
[ 16.005069] kthread+0x104/0x110
[ 16.014789] ret_from_fork+0x10/0x20
[ 16.025201][] other info that might help us debug this:
[ 16.047769] Possible unsafe locking scenario:
[ 16.063942] CPU0 CPU1 [ 16.075166] ---- ---- [ 16.086376] lock(&mtk_subdev->channels_lock); [ 16.097592] lock(&scp->ipi_desc[i].lock); [ 16.113188] lock(&mtk_subdev->channels_lock); [ 16.129482] lock(&scp->ipi_desc[i].lock); [ 16.140020]
[] *** DEADLOCK ***
[ 16.158282] 4 locks held by kworker/0:3/155:
[ 16.168978] #0: ffff5b4d00008748 ((wq_completion)events){+.+.}-{0:0}, at: process_one_work+0x1fc/0x664
[ 16.190017] #1: ffff80000953bdc8 ((work_completion)(&mtk_subdev->register_work)){+.+.}-{0:0}, at: process_one_work+0x1fc/0x664
[ 16.215269] #2: ffff5b4d0e8f1918 (&mtk_subdev->channels_lock){+.+.}-{4:4}, at: mtk_register_device_work_function+0x50/0x1cc [mtk_rpmsg]
[ 16.242131] #3: ffff5b4d05964190 (&dev->mutex){....}-{4:4}, at: __device_attach+0x44/0x190To solve this, simply unlock the channels_lock mutex before calling mtk_rpmsg_register_device() and relock it right after, as safety is still ensured by the locking mechanism that happens right after through SCP.
--- drivers/rpmsg/mtk_rpmsg.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/rpmsg/mtk_rpmsg.c +2 -0
@@ -234,7 +234,9 @@ static void mtk_register_device_work_function(struct work_struct *register_work)if (info->registered)continue ; +mutex_unlock (&subdev->channels_lock); ret =mtk_rpmsg_register_device (subdev, &info->info); +mutex_lock (&subdev->channels_lock);if (ret) {dev_err (&pdev->dev,"Can't create rpmsg_device\n" );continue ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 575/779 remoteproc: k3-r5: Fix refcount leak in k3_r5_cluster_of_init
In reply to Greg Kroah-HartmanFrom: Miaoqian Lin <[email protected]>
[ Upstream commit fa220c05d282e7479abe08b54e3bdffd06c25e97 ]
Every iteration of for_each_available_child_of_node() decrements the reference count of the previous node.
When breaking early from a for_each_available_child_of_node() loop, we need to explicitly call of_node_put() on the child node. Add missing of_node_put() to avoid refcount leak.
--- drivers/remoteproc/ti_k3_r5_remoteproc.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/remoteproc/ti_k3_r5_remoteproc.c +2 -0
@@ -1430,6 +1430,7 @@ static int k3_r5_cluster_of_init(struct platform_device *pdev)if (!cpdev) { ret = -ENODEV ;dev_err (dev,"could not get R5 core platform device\n" ); +of_node_put (child); goto fail; }
@@ -1438,6 +1439,7 @@ static int k3_r5_cluster_of_init(struct platform_device *pdev)dev_err (dev,"k3_r5_core_of_init failed, ret = %d\n" , ret);put_device (&cpdev->dev); +of_node_put (child); goto fail; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 576/779 selftests/livepatch: better synchronize test_klp_callbacks_busy
In reply to Greg Kroah-HartmanFrom: Joe Lawrence <[email protected]>
[ Upstream commit 55eb9a6c8bf3e2099863118ef53e02d9f44f85a8 ]
The test_klp_callbacks_busy module conditionally blocks a future livepatch transition by busy waiting inside its workqueue function, busymod_work_func(). After scheduling this work, a test livepatch is loaded, introducing the transition under test.
Both events are marked in the kernel log for later verification, but there is no synchronization to ensure that busymod_work_func() logs its function entry message before subsequent selftest commands log their own messages. This can lead to a rare test failure due to unexpected ordering like:
# --- expected # +++ result # @@ -1,7 +1,7 @@
# % modprobe test_klp_callbacks_busy block_transition=Y
# test_klp_callbacks_busy: test_klp_callbacks_busy_init
# -test_klp_callbacks_busy: busymod_work_func enter
# % modprobe test_klp_callbacks_demo
# +test_klp_callbacks_busy: busymod_work_func enter
# livepatch: enabling patch 'test_klp_callbacks_demo' # livepatch: 'test_klp_callbacks_demo': initializing patching transition # test_klp_callbacks_demo: pre_patch_callback: vmlinux
Force the module init function to wait until busymod_work_func() has started (and logged its message), before exiting to the next selftest steps.
--- lib/livepatch/test_klp_callbacks_busy.c | 8 ++++++++ 1 file changed, 8 insertions(+)
lib/livepatch/test_klp_callbacks_busy.c +8 -0
@@ -16,10 +16,12 @@ MODULE_PARM_DESC(block_transition, "blocstatic void busymod_work_func (struct work_struct *work); static DECLARE_WORK(work, busymod_work_func); +static DECLARE_COMPLETION (busymod_work_started);static void busymod_work_func (struct work_struct *work) {pr_info ("%s enter\n" , __func__); +complete (&busymod_work_started);while (READ_ONCE (block_transition)) {/*
@@ -37,6 +39,12 @@ static int test_klp_callbacks_busy_init(pr_info ("%s\n" , __func__);schedule_work (&work); +/* +* To synchronize kernel messages, hold the init function from +* exiting until the work function's entry message has printed. +*/ +wait_for_completion (&busymod_work_started); +if (!block_transition) {/* * Serialize output: print all messages from the work
Greg Kroah-Hartman
maintainerPATCH 577/779 profiling: fix shift too large makes kernel panic
In reply to Greg Kroah-HartmanFrom: Chen Zhongjin <[email protected]>
[ Upstream commit 0fe6ee8f123a4dfb529a5aff07536bb481f34043 ]
2d186afd04d6 ("profiling: fix shift-out-of-bounds bugs") limits shift value by [0, BITS_PER_LONG -1], which means [0, 63].
However, syzbot found that the max shift value should be the bit number of (_etext - _stext). If shift is outside of this, the "buffer_bytes" will be zero and will cause kzalloc(0). Then the kernel panics due to dereferencing the returned pointer 16.
This can be easily reproduced by passing a large number like 60 to enable profiling and then run readprofile.
LOGS:
BUG: kernel NULL pointer dereference, address: 0000000000000010 #PF: supervisor write access in kernel mode #PF: error_code(0x0002) - not-present page PGD 6148067 P4D 6148067 PUD 6142067 PMD 0 PREEMPT SMP CPU: 4 PID: 184 Comm: readprofile Not tainted 5.18.0+ #162 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.15.0-0-g2dd4b9b3f840-prebuilt.qemu.org 04/01/2014 RIP: 0010:read_profile+0x104/0x220 RSP: 0018:ffffc900006fbe80 EFLAGS: 00000202 RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000 RDX: ffff888006150000 RSI: 0000000000000001 RDI: ffffffff82aba4a0 RBP: 000000000188bb60 R08: 0000000000000010 R09: ffff888006151000 R10: 0000000000000000 R11: 0000000000000000 R12: ffffffff82aba4a0 R13: 0000000000000000 R14: ffffc900006fbf08 R15: 0000000000020c30 FS: 000000000188a8c0(0000) GS:ffff88803ed00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000010 CR3: 0000000006144000 CR4: 00000000000006e0 Call Trace: <TASK> proc_reg_read+0x56/0x70 vfs_read+0x9a/0x1b0 ksys_read+0xa1/0xe0 ? fpregs_assert_state_consistent+0x1e/0x40 do_syscall_64+0x3a/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0 RIP: 0033:0x4d4b4e RSP: 002b:00007ffebb668d58 EFLAGS: 00000246 ORIG_RAX: 0000000000000000 RAX: ffffffffffffffda RBX: 000000000188a8a0 RCX: 00000000004d4b4e RDX: 0000000000000400 RSI: 000000000188bb60 RDI: 0000000000000003 RBP: 0000000000000003 R08: 000000000000006e R09: 0000000000000000 R10: 0000000000000041 R11: 0000000000000246 R12: 000000000188bb60 R13: 0000000000000400 R14: 0000000000000000 R15: 000000000188bb60 </TASK> Modules linked in: CR2: 0000000000000010 Killed ---[ end trace 0000000000000000 ]---
Check prof_len in profile_init() to prevent it be zero.
--- kernel/profile.c | 7 +++++++ 1 file changed, 7 insertions(+)
kernel/profile.c +7 -0
@@ -109,6 +109,13 @@ int __ref profile_init(void)/* only text is profiled */ prof_len = (_etext - _stext) >> prof_shift; + +if (!prof_len) { +pr_warn ("profiling shift: %u too large\n" , prof_shift); + prof_on =0 ; +return -EINVAL ; + } + buffer_bytes = prof_len*sizeof (atomic_t);if (!alloc_cpumask_var (&prof_cpu_mask,GFP_KERNEL ))
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 578/779 remoteproc: imx_rproc: Fix refcount leak in imx_rproc_addr_init
In reply to Greg Kroah-HartmanFrom: Miaoqian Lin <[email protected]>
[ Upstream commit 61afafe8b938bc74841cf4b1a73dd08b9d287c5a ]
of_parse_phandle() returns a node pointer with refcount incremented, we should use of_node_put() on it when not needed anymore. This function has two paths missing of_node_put().
--- drivers/remoteproc/imx_rproc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/remoteproc/imx_rproc.c +4 -3
@@ -586,16 +586,17 @@ static int imx_rproc_addr_init(struct imx_rproc *priv, node =of_parse_phandle (np,"memory-region" , a);/* Not map vdevbuffer, vdevring region */ -if (!strncmp (node->name,"vdev" ,strlen ("vdev" ))) +if (!strncmp (node->name,"vdev" ,strlen ("vdev" ))) { +of_node_put (node);continue ; + } err =of_address_to_resource (node,0 , &res); +of_node_put (node);if (err) {dev_err (dev,"unable to resolve memory region\n" );return err; } -of_node_put (node); -if (b >=IMX_RPROC_MEM_MAX )break ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 579/779 ASoC: samsung: h1940_uda1380: include proepr GPIO consumer header
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
[ Upstream commit bd10b0dafdcf0ec1677cad70101e1f97b9e28f2e ]
h1940_uda1380 uses gpiod*/GPIOD* so it should include GPIO consumer header.
--- sound/soc/samsung/h1940_uda1380.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/samsung/h1940_uda1380.c +1 -1
@@ -8,7 +8,7 @@// Based on version from Arnaud Patard <[email protected]> #include <linux/types.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/module.h> #include <sound/soc.h>
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 580/779 powerpc/perf: Optimize clearing the pending PMI and remove WARN_ON for PMI check in power_pmu_disable
In reply to Greg Kroah-HartmanFrom: Athira Rajeev <[email protected]>
[ Upstream commit 890005a7d98f7452cfe86dcfb2aeeb7df01132ce ]
commit 2c9ac51b850d ("powerpc/perf: Fix PMU callbacks to clear pending PMI before resetting an overflown PMC") added a new function "pmi_irq_pending" in hw_irq.h. This function is to check if there is a PMI marked as pending in Paca (PACA_IRQ_PMI).This is used in power_pmu_disable in a WARN_ON. The intention here is to provide a warning if there is PMI pending, but no counter is found overflown.
During some of the perf runs, below warning is hit:
WARNING: CPU: 36 PID: 0 at arch/powerpc/perf/core-book3s.c:1332 power_pmu_disable+0x25c/0x2c0 Modules linked in: -----
NIP [c000000000141c3c] power_pmu_disable+0x25c/0x2c0 LR [c000000000141c8c] power_pmu_disable+0x2ac/0x2c0
Call Trace: [c000000baffcfb90] [c000000000141c8c] power_pmu_disable+0x2ac/0x2c0 (unreliable) [c000000baffcfc10] [c0000000003e2f8c] perf_pmu_disable+0x4c/0x60 [c000000baffcfc30] [c0000000003e3344] group_sched_out.part.124+0x44/0x100 [c000000baffcfc80] [c0000000003e353c] __perf_event_disable+0x13c/0x240 [c000000baffcfcd0] [c0000000003dd334] event_function+0xc4/0x140 [c000000baffcfd20] [c0000000003d855c] remote_function+0x7c/0xa0 [c000000baffcfd50] [c00000000026c394] flush_smp_call_function_queue+0xd4/0x300 [c000000baffcfde0] [c000000000065b24] smp_ipi_demux_relaxed+0xa4/0x100 [c000000baffcfe20] [c0000000000cb2b0] xive_muxed_ipi_action+0x20/0x40 [c000000baffcfe40] [c000000000207c3c] __handle_irq_event_percpu+0x8c/0x250 [c000000baffcfee0] [c000000000207e2c] handle_irq_event_percpu+0x2c/0xa0 [c000000baffcff10] [c000000000210a04] handle_percpu_irq+0x84/0xc0 [c000000baffcff40] [c000000000205f14] generic_handle_irq+0x54/0x80 [c000000baffcff60] [c000000000015740] __do_irq+0x90/0x1d0 [c000000baffcff90] [c000000000016990] __do_IRQ+0xc0/0x140 [c0000009732f3940] [c000000bafceaca8] 0xc000000bafceaca8 [c0000009732f39d0] [c000000000016b78] do_IRQ+0x168/0x1c0 [c0000009732f3a00] [c0000000000090c8] hardware_interrupt_common_virt+0x218/0x220
This means that there is no PMC overflown among the active events in the PMU, but there is a PMU pending in Paca. The function "any_pmc_overflown" checks the PMCs on active events in cpuhw->n_events. Code snippet:
<<>>
if (any_pmc_overflown(cpuhw))
clear_pmi_irq_pending();
else
WARN_ON(pmi_irq_pending());
<<>>
Here the PMC overflown is not from active event. Example: When we do perf record, default cycles and instructions will be running on PMC6 and PMC5 respectively. It could happen that overflowed event is currently not active and pending PMI is for the inactive event. Debug logs from trace_printk:
<<>>any_pmc_overflown: idx is 5: pmc value is 0xd9apower_pmu_disable: PMC1: 0x0, PMC2: 0x0, PMC3: 0x0, PMC4: 0x0, PMC5: 0xd9a, PMC6: 0x80002011 <<>>
Here active PMC (from idx) is PMC5 , but overflown PMC is PMC6(0x80002011). When we handle PMI interrupt for such cases, if the PMC overflown is from inactive event, it will be ignored. Reference commit:
commit bc09c219b2e6 ("powerpc/perf: Fix finding overflowed PMC in interrupt")
Patch addresses two changes:
1) Fix 1 : Removal of warning ( WARN_ON(pmi_irq_pending()); ) We were printing warning if no PMC is found overflown among active PMU events, but PMI pending in PACA. But this could happen in cases where PMC overflown is not in active PMC. An inactive event could have caused the overflow. Hence the warning is not needed. To know pending PMI is from an inactive event, we need to loop through all PMC's which will cause more SPR reads via mfspr and increase in context switch. Also in existing function: perf_event_interrupt, already we ignore PMI's overflown when it is from an inactive PMC.
2) Fix 2: optimization in clearing pending PMI.
Currently we check for any active PMC overflown before clearing PMI pending in Paca. This is causing additional SPR read also. From point 1, we know that if PMI pending in Paca from inactive cases, that is going to be ignored during replay. Hence if there is pending PMI in Paca, just clear it irrespective of PMC overflown or not.
In summary, remove the any_pmc_overflown check entirely in power_pmu_disable. ie If there is a pending PMI in Paca, clear it, since we are in pmu_disable. There could be cases where PMI is pending because of inactive PMC ( which later when replayed also will get ignored ), so WARN_ON could give false warning. Hence removing it.
--- arch/powerpc/perf/core-book3s.c | 35 ++++++++++++++------------------- 1 file changed, 15 insertions(+), 20 deletions(-)
arch/powerpc/perf/core-book3s.c +15 -20
@@ -1320,27 +1320,22 @@ static void power_pmu_disable(struct pmu *pmu)* a PMI happens during interrupt replay and perf counter * values are cleared by PMU callbacks before replay. * -* If any PMC corresponding to the active PMU events are -* overflown, disable the interrupt by clearing the paca -* bit for PMI since we are disabling the PMU now. -* Otherwise provide a warning if there is PMI pending, but -* no counter is found overflown. +* Disable the interrupt by clearing the paca bit for PMI +* since we are disabling the PMU now. Otherwise provide a +* warning if there is PMI pending, but no counter is found +* overflown. +* +* Since power_pmu_disable runs under local_irq_save, it +* could happen that code hits a PMC overflow without PMI +* pending in paca. Hence only clear PMI pending if it was +* set. +* +* If a PMI is pending, then MSR[EE] must be disabled (because +* the masked PMI handler disabling EE). So it is safe to +* call clear_pmi_irq_pending(). */ -if (any_pmc_overflown (cpuhw)) { -/* -* Since power_pmu_disable runs under local_irq_save, it -* could happen that code hits a PMC overflow without PMI -* pending in paca. Hence only clear PMI pending if it was -* set. -* -* If a PMI is pending, then MSR[EE] must be disabled (because -* the masked PMI handler disabling EE). So it is safe to -* call clear_pmi_irq_pending(). -*/ -if (pmi_irq_pending ()) -clear_pmi_irq_pending (); - }else -WARN_ON (pmi_irq_pending ()); +if (pmi_irq_pending ()) +clear_pmi_irq_pending (); val = mmcra = cpuhw->mmcr.mmcra;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 581/779 ASoC: samsung: change gpiod_speaker_power and rx1950_audio from global to static variables
In reply to Greg Kroah-HartmanFrom: Tom Rix <[email protected]>
[ Upstream commit d2294461b90e0c5b3bbfaaf2c8baff4fd3e2bb13 ]
sparse reportssound/soc/samsung/rx1950_uda1380.c:131:18: warning: symbol 'gpiod_speaker_power' was not declared. Should it be static? sound/soc/samsung/rx1950_uda1380.c:231:24: warning: symbol 'rx1950_audio' was not declared. Should it be static?
Both gpiod_speaker_power and rx1950_audio are only used in rx1950_uda1380.c, so their storage class specifiers should be static.
--- sound/soc/samsung/rx1950_uda1380.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
sound/soc/samsung/rx1950_uda1380.c +2 -2
@@ -128,7 +128,7 @@ static int rx1950_startup(struct snd_pcm_substream *substream) &hw_rates); } -struct gpio_desc *gpiod_speaker_power; +static struct gpio_desc *gpiod_speaker_power;static int rx1950_spk_power (struct snd_soc_dapm_widget *w,struct snd_kcontrol *kcontrol,int event)
@@ -227,7 +227,7 @@ static int rx1950_probe(struct platform_device *pdev)return devm_snd_soc_register_card (dev, &rx1950_asoc); } -struct platform_driver rx1950_audio = { +static struct platform_driver rx1950_audio = { .driver = { .name ="rx1950-audio" , .pm = &snd_soc_pm_ops,
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 582/779 tty: n_gsm: Delete gsmtty open SABM frame when config requester
In reply to Greg Kroah-HartmanFrom: Zhenguo Zhao <[email protected]>
[ Upstream commit cbff2b32516881bef30bbebf413d1b49495bab1d ]
When n_gsm config "initiator=0",as requester ,it doesn't need to send SABM frame data during gsmtty open.
Example,when gsmtty open,it will send SABM frame.for initiator,it maybe not want to receive the frame.
[ 88.410426] c1 gsmld_output: 00000000: f9 07 3f 01 de f9 [ 88.420839] c1 --> 1) R: SABM(F)
--- drivers/tty/n_gsm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/tty/n_gsm.c +3 -1
@@ -3214,6 +3214,7 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp) {struct gsm_dlci *dlci = tty->driver_data;struct tty_port *port = &dlci->port; +struct gsm_mux *gsm = dlci->gsm; port->count++;tty_port_tty_set (port, tty);
@@ -3223,7 +3224,8 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)a DM straight back. This is ok as that will have caused a hangup */ tty_port_set_initialized (port,1 );/* Start sending off SABM messages */ -gsm_dlci_begin_open (dlci); +if (gsm->initiator) +gsm_dlci_begin_open (dlci);/* And wait for virtual carrier */ return tty_port_block_til_ready (port, tty, filp); }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 583/779 tty: n_gsm: fix user open not possible at responder until initiator open
In reply to Greg Kroah-HartmanFrom: Daniel Starke <[email protected]>
[ Upstream commit ac77f0077c3265197d378158c85a55eee6d21508 ]
After setting up the control channel on both sides the responder side may want to open a virtual tty to listen on until the initiator starts an application on a user channel. The current implementation allows the open() but no other operation, like termios. These fail with EINVAL. The responder sided application has no means to detect an open by the initiator sided application this way. And the initiator sided applications usually expect the responder sided application to listen on the user channel upon open.
Set the user channel into half-open state on responder side once a user application opens the virtual tty to allow IO operations on it. Furthermore, keep the user channel constipated until the initiator side opens it to give the responder sided application the chance to detect the new connection and to avoid data loss if the responder sided application starts sending before the user channel is open.
--- drivers/tty/n_gsm.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-)
drivers/tty/n_gsm.c +29 -2
@@ -1524,6 +1524,8 @@ static void gsm_dlci_close(struct gsm_dlci *dlci)if (debug &8 )pr_debug ("DLCI %d goes closed.\n" , dlci->addr); dlci->state =DLCI_CLOSED ; +/* Prevent us from sending data before the link is up again */ + dlci->constipated = true;if (dlci->addr !=0 ) {tty_port_tty_hangup (&dlci->port, false);spin_lock_irqsave (&dlci->lock, flags);
@@ -1553,6 +1555,7 @@ static void gsm_dlci_open(struct gsm_dlci *dlci)del_timer (&dlci->t1);/* This will let a tty open continue */ dlci->state =DLCI_OPEN ; + dlci->constipated = false;if (debug &8 )pr_debug ("DLCI %d goes open.\n" , dlci->addr);/* Send current modem state */
@@ -1633,6 +1636,25 @@ static void gsm_dlci_begin_open(struct gsm_dlci *dlci)mod_timer (&dlci->t1, jiffies + gsm->t1 *HZ /100 ); } +/** +* gsm_dlci_set_opening - change state to opening +* @dlci: DLCI to open +* +* Change internal state to wait for DLCI open from initiator side. +* We set off timers and responses upon reception of an SABM. +*/ +static void gsm_dlci_set_opening (struct gsm_dlci *dlci) +{ +switch (dlci->state) { +case DLCI_CLOSED : +case DLCI_CLOSING : + dlci->state =DLCI_OPENING ; +break ; +default : +break ; + } +} +/** * gsm_dlci_begin_close - start channel open procedure * @dlci: DLCI to open
@@ -1776,10 +1798,13 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr) dlci->addr = addr; dlci->adaption = gsm->adaption; dlci->state =DLCI_CLOSED ; -if (addr) +if (addr) { dlci->data = gsm_dlci_data; -else +/* Prevent us from sending data before the link is up */ + dlci->constipated = true; + }else { dlci->data = gsm_dlci_command; + } gsm->dlci[addr] = dlci;return dlci; }
@@ -3226,6 +3251,8 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)/* Start sending off SABM messages */ if (gsm->initiator)gsm_dlci_begin_open (dlci); +else +gsm_dlci_set_opening (dlci);/* And wait for virtual carrier */ return tty_port_block_til_ready (port, tty, filp); }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 584/779 tty: n_gsm: fix tty registration before control channel open
In reply to Greg Kroah-HartmanFrom: Daniel Starke <[email protected]>
[ Upstream commit 01aecd917114577c423f07cec0d186ad007d76fc ]
The current implementation registers/deregisters the user ttys at mux attach/detach. That means that the user devices are available before any control channel is open. However, user channel initialization requires an open control channel. Furthermore, the user is not informed if the mux restarts due to configuration changes.
Put the registration/deregistration procedure into separate function to improve readability.
Move registration to mux activation and deregistration to mux cleanup to keep the user devices only open as long as a control channel exists. The user will be informed via the device driver if the mux was reconfigured in a way that required a mux re-activation.
This makes it necessary to add T2 initialization to gsmld_open() for the ldisc open code path (not the reconfiguration code path) to avoid deletion of an uninitialized T2 at mux cleanup.
--- drivers/tty/n_gsm.c | 117 ++++++++++++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 38 deletions(-)
drivers/tty/n_gsm.c +79 -38
@@ -235,6 +235,7 @@ struct gsm_mux {struct gsm_dlci *dlci[NUM_DLCI ];int old_c_iflag;/* termios c_iflag value before attach */ bool constipated;/* Asked by remote to shut up */ +bool has_devices;/* Devices were registered */ spinlock_t tx_lock;unsigned int tx_bytes;/* TX data outstanding */
@@ -467,6 +468,68 @@ static void gsm_hex_dump_bytes(const char *fname, const u8 *data,kfree (prefix); } +/** +* gsm_register_devices - register all tty devices for a given mux index +* +* @driver: the tty driver that describes the tty devices +* @index: the mux number is used to calculate the minor numbers of the +* ttys for this mux and may differ from the position in the +* mux array. +*/ +static int gsm_register_devices (struct tty_driver *driver,unsigned int index) +{ +struct device *dev; +int i; +unsigned int base; + +if (!driver || index >=MAX_MUX ) +return -EINVAL ; + + base = index *NUM_DLCI ;/* first minor for this index */ +for (i =1 ; i <NUM_DLCI ; i++) { +/* Don't register device 0 - this is the control channel +* and not a usable tty interface +*/ + dev =tty_register_device (gsm_tty_driver, base + i,NULL ); +if (IS_ERR (dev)) { +if (debug &8 ) +pr_info ("%s failed to register device minor %u" , + __func__, base + i); +for (i--; i >=1 ; i--) +tty_unregister_device (gsm_tty_driver, base + i); +return PTR_ERR (dev); + } + } + +return 0 ; +} + +/** +* gsm_unregister_devices - unregister all tty devices for a given mux index +* +* @driver: the tty driver that describes the tty devices +* @index: the mux number is used to calculate the minor numbers of the +* ttys for this mux and may differ from the position in the +* mux array. +*/ +static void gsm_unregister_devices (struct tty_driver *driver, +unsigned int index) +{ +int i; +unsigned int base; + +if (!driver || index >=MAX_MUX ) +return ; + + base = index *NUM_DLCI ;/* first minor for this index */ +for (i =1 ; i <NUM_DLCI ; i++) { +/* Don't unregister device 0 - this is the control +* channel and not a usable tty interface +*/ +tty_unregister_device (gsm_tty_driver, base + i); + } +} +/** * gsm_print_packet - display a frame for debug * @hdr: header to print before decode
@@ -2256,6 +2319,10 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)del_timer_sync (&gsm->t2_timer);/* Free up any link layer users and finally the control channel */ +if (gsm->has_devices) { +gsm_unregister_devices (gsm_tty_driver, gsm->num); + gsm->has_devices = false; + }for (i =NUM_DLCI -1 ; i >=0 ; i--)if (gsm->dlci[i])gsm_dlci_release (gsm->dlci[i]);
@@ -2279,6 +2346,7 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)static int gsm_activate_mux (struct gsm_mux *gsm) {struct gsm_dlci *dlci; +int ret;timer_setup (&gsm->t2_timer, gsm_control_retransmit,0 );init_waitqueue_head (&gsm->event);
@@ -2290,9 +2358,14 @@ static int gsm_activate_mux(struct gsm_mux *gsm)else gsm->receive = gsm1_receive; + ret =gsm_register_devices (gsm_tty_driver, gsm->num); +if (ret) +return ret; + dlci =gsm_dlci_alloc (gsm,0 );if (dlci ==NULL )return -ENOMEM ; + gsm->has_devices = true; gsm->dead = false;/* Tty opens are now permissible */ return 0 ; }
@@ -2552,39 +2625,14 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len)* will need moving to an ioctl path. */ -static int gsmld_attach_gsm (struct tty_struct *tty,struct gsm_mux *gsm) +static void gsmld_attach_gsm (struct tty_struct *tty,struct gsm_mux *gsm) { -unsigned int base; -int ret, i; - gsm->tty =tty_kref_get (tty);/* Turn off tty XON/XOFF handling to handle it explicitly. */ gsm->old_c_iflag = tty->termios.c_iflag; tty->termios.c_iflag &= (IXON |IXOFF ); - ret =gsm_activate_mux (gsm); -if (ret !=0 ) -tty_kref_put (gsm->tty); -else { -/* Don't register device 0 - this is the control channel and not -a usable tty interface */ - base =mux_num_to_base (gsm);/* Base for this MUX */ -for (i =1 ; i <NUM_DLCI ; i++) { -struct device *dev; - - dev =tty_register_device (gsm_tty_driver, - base + i,NULL ); -if (IS_ERR (dev)) { -for (i--; i >=1 ; i--) -tty_unregister_device (gsm_tty_driver, - base + i); -return PTR_ERR (dev); - } - } - } -return ret; } -/** * gsmld_detach_gsm - stop doing 0710 mux * @tty: tty attached to the mux
@@ -2595,12 +2643,7 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)static void gsmld_detach_gsm (struct tty_struct *tty,struct gsm_mux *gsm) { -unsigned int base =mux_num_to_base (gsm);/* Base for this MUX */ -int i; -WARN_ON (tty != gsm->tty); -for (i =1 ; i <NUM_DLCI ; i++) -tty_unregister_device (gsm_tty_driver, base + i);/* Restore tty XON/XOFF handling. */ gsm->tty->termios.c_iflag = gsm->old_c_iflag;tty_kref_put (gsm->tty);
@@ -2692,7 +2735,6 @@ static void gsmld_close(struct tty_struct *tty)static int gsmld_open (struct tty_struct *tty) {struct gsm_mux *gsm; -int ret;if (tty->ops->write ==NULL )return -EINVAL ;
@@ -2708,12 +2750,11 @@ static int gsmld_open(struct tty_struct *tty)/* Attach the initial passive connection */ gsm->encoding =1 ; - ret =gsmld_attach_gsm (tty, gsm); -if (ret !=0 ) { -gsm_cleanup_mux (gsm, false); -mux_put (gsm); - } -return ret; +gsmld_attach_gsm (tty, gsm); + +timer_setup (&gsm->t2_timer, gsm_control_retransmit,0 ); + +return 0 ; }/**
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 585/779 tty: n_gsm: fix wrong queuing behavior in gsm_dlci_data_output()
In reply to Greg Kroah-HartmanFrom: Daniel Starke <[email protected]>
[ Upstream commit 556fc8ac06513cced381588d6d58c184d95cc4fe ]
1) The function drains the fifo for the given user tty/DLCI without considering 'TX_THRESH_HI' and different to gsm_dlci_data_output_framed(), which moves only one packet from the user side to the internal transmission queue. We can only handle one packet at a time here if we want to allow DLCI priority handling in gsm_dlci_data_sweep() to avoid link starvation.
2) Furthermore, the additional header octet from convergence layer type 2 is not counted against MTU. It is part of the UI/UIH frame message which needs to be limited to MTU. Hence, it is wrong not to consider this octet.
3) Finally, the waiting user tty is not informed about freed space in its send queue.
Take at most one packet worth of data out of the DLCI fifo to fix 1). Limit the max user data size per packet to MTU - 1 in case of convergence layer type 2 to leave space for the control signal octet which is added in the later part of the function. This fixes 2).
Add tty_port_tty_wakeup() to wake up the user tty if new write space has been made available to fix 3).
--- drivers/tty/n_gsm.c | 74 +++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 32 deletions(-)
drivers/tty/n_gsm.c +42 -32
@@ -886,41 +886,51 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci) {struct gsm_msg *msg;u8 *dp; -int len, total_size, size; -int h = dlci->adaption -1 ; +int h, len, size; - total_size =0 ; -while (1 ) { - len =kfifo_len (&dlci->fifo); -if (len ==0 ) -return total_size; - -/* MTU/MRU count only the data bits */ -if (len > gsm->mtu) - len = gsm->mtu; - - size = len + h; - - msg =gsm_data_alloc (gsm, dlci->addr, size, gsm->ftype); -/* FIXME: need a timer or something to kick this so it can't -get stuck with no work outstanding and no buffer free */ -if (msg ==NULL ) -return -ENOMEM ; - dp = msg->data; -switch (dlci->adaption) { -case 1 :/* Unstructured */ -break ; -case 2 :/* Unstructed with modem bits. -Always one byte as we never send inline break data */ - *dp++ = (gsm_encode_modem (dlci) <<1 ) |EA ; -break ; - } -WARN_ON (kfifo_out_locked (&dlci->fifo, dp , len, &dlci->lock) != len); -__gsm_data_queue (dlci, msg); - total_size += size; +/* for modem bits without break data */ + h = ((dlci->adaption ==1 ) ?0 :1 ); + + len =kfifo_len (&dlci->fifo); +if (len ==0 ) +return 0 ; + +/* MTU/MRU count only the data bits but watch adaption mode */ +if ((len + h) > gsm->mtu) + len = gsm->mtu - h; + + size = len + h; + + msg =gsm_data_alloc (gsm, dlci->addr, size, gsm->ftype); +/* FIXME: need a timer or something to kick this so it can't +* get stuck with no work outstanding and no buffer free +*/ +if (!msg) +return -ENOMEM ; + dp = msg->data; +switch (dlci->adaption) { +case 1 :/* Unstructured */ +break ; +case 2 :/* Unstructured with modem bits. +* Always one byte as we never send inline break data +*/ + *dp++ = (gsm_encode_modem (dlci) <<1 ) |EA ; +break ; +default : +pr_err ("%s: unsupported adaption %d\n" , __func__, + dlci->adaption); +break ; } + +WARN_ON (len !=kfifo_out_locked (&dlci->fifo, dp, len, + &dlci->lock)); + +/* Notify upper layer about available send space. */ +tty_port_tty_wakeup (&dlci->port); + +__gsm_data_queue (dlci, msg);/* Bytes of data we used up */ -return total_size; +return size; }/**
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 586/779 tty: n_gsm: fix missing timer to handle stalled links
In reply to Greg Kroah-HartmanFrom: Daniel Starke <[email protected]>
[ Upstream commit c568f7086c6e771c77aad13d727c70ef70e07243 ]
The current implementation does not handle the situation that no data is in the internal queue and needs to be sent out while the user tty fifo is full.
Add a timer that moves more data from user tty down to the internal queue which is then serialized on the ldisc. This timer is triggered if no data was moved from a user tty to the internal queue within 10 * T1.
--- drivers/tty/n_gsm.c | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-)
drivers/tty/n_gsm.c +35 -8
@@ -244,6 +244,7 @@ struct gsm_mux {struct list_head tx_list;/* Pending data packets */ /* Control messages */ +struct timer_list kick_timer;/* Kick TX queuing on timeout */ struct timer_list t2_timer;/* Retransmit timer for commands */ int cretries;/* Command retry counter */ struct gsm_control *pending_cmd;/* Our current pending command */
@@ -850,6 +851,7 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg)list_add_tail (&msg->list, &gsm->tx_list); gsm->tx_bytes += msg->len;gsm_data_kick (gsm, dlci); +mod_timer (&gsm->kick_timer, jiffies +10 * gsm->t1 *HZ /100 ); }/**
@@ -902,9 +904,6 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci) size = len + h; msg =gsm_data_alloc (gsm, dlci->addr, size, gsm->ftype); -/* FIXME: need a timer or something to kick this so it can't -* get stuck with no work outstanding and no buffer free -*/ if (!msg)return -ENOMEM ; dp = msg->data;
@@ -981,9 +980,6 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, size = len + overhead; msg =gsm_data_alloc (gsm, dlci->addr, size, gsm->ftype); - -/* FIXME: need a timer or something to kick this so it can't -get stuck with no work outstanding and no buffer free */ if (msg ==NULL ) {skb_queue_tail (&dlci->skb_list, dlci->skb); dlci->skb =NULL ;
@@ -1079,9 +1075,9 @@ static int gsm_dlci_modem_output(struct gsm_mux *gsm, struct gsm_dlci *dlci,* renegotiate DLCI priorities with optional stuff. Needs optimising. */ -static void gsm_dlci_data_sweep (struct gsm_mux *gsm) +static int gsm_dlci_data_sweep (struct gsm_mux *gsm) { -int len; +int len, ret =0 ;/* Priority ordering: We should do priority with RR of the groups */ int i =1 ;
@@ -1104,7 +1100,11 @@ static void gsm_dlci_data_sweep(struct gsm_mux *gsm)/* DLCI empty - try the next */ if (len ==0 ) i++; +else + ret++; } + +return ret; }/**
@@ -1837,6 +1837,30 @@ static void gsm_dlci_command(struct gsm_dlci *dlci, const u8 *data, int len) } } +/** +* gsm_kick_timer - transmit if possible +* @t: timer contained in our gsm object +* +* Transmit data from DLCIs if the queue is empty. We can't rely on +* a tty wakeup except when we filled the pipe so we need to fire off +* new data ourselves in other cases. +*/ +static void gsm_kick_timer (struct timer_list *t) +{ +struct gsm_mux *gsm =from_timer (gsm, t, kick_timer); +unsigned long flags; +int sent =0 ; + +spin_lock_irqsave (&gsm->tx_lock, flags); +/* If we have nothing running then we need to fire up */ +if (gsm->tx_bytes <TX_THRESH_LO ) + sent =gsm_dlci_data_sweep (gsm); +spin_unlock_irqrestore (&gsm->tx_lock, flags); + +if (sent && debug &4 ) +pr_info ("%s TX queue stalled\n" , __func__); +} +/* * Allocate/Free DLCI channels */
@@ -2326,6 +2350,7 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc) }/* Finish outstanding timers, making sure they are done */ +del_timer_sync (&gsm->kick_timer);del_timer_sync (&gsm->t2_timer);/* Free up any link layer users and finally the control channel */
@@ -2358,6 +2383,7 @@ static int gsm_activate_mux(struct gsm_mux *gsm)struct gsm_dlci *dlci;int ret; +timer_setup (&gsm->kick_timer, gsm_kick_timer,0 );timer_setup (&gsm->t2_timer, gsm_control_retransmit,0 );init_waitqueue_head (&gsm->event);spin_lock_init (&gsm->control_lock);
@@ -2762,6 +2788,7 @@ static int gsmld_open(struct tty_struct *tty)gsmld_attach_gsm (tty, gsm); +timer_setup (&gsm->kick_timer, gsm_kick_timer,0 );timer_setup (&gsm->t2_timer, gsm_control_retransmit,0 );return 0 ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 587/779 tty: n_gsm: fix non flow control frames during mux flow off
In reply to Greg Kroah-HartmanFrom: Daniel Starke <[email protected]>
[ Upstream commit bec0224816d19abe4fe503586d16d51890540615 ]
n_gsm is based on the 3GPP 07.010 and its newer version is the 3GPP 27.010.
See https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=1516
The changes from 07.010 to 27.010 are non-functional. Therefore, I refer to
the newer 27.010 here. Chapter 5.4.6.3.6 states that FCoff stops the
transmission on all channels except the control channel. This is already
implemented in gsm_data_kick(). However, chapter 5.4.8.1 explains that this
shall result in the same behavior as software flow control on the ldisc in
advanced option mode. That means only flow control frames shall be sent
during flow off. The current implementation does not consider this case.
Change gsm_data_kick() to send only flow control frames if constipated to abide the standard. gsm_read_ea_val() and gsm_is_flow_ctrl_msg() are introduced as helper functions for this.
It is planned to use gsm_read_ea_val() in later code cleanups for other functions, too.
--- drivers/tty/n_gsm.c | 54 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-)
drivers/tty/n_gsm.c +53 -1
@@ -425,6 +425,27 @@ static int gsm_read_ea(unsigned int *val, u8 c)return c &EA ; } +/** +* gsm_read_ea_val - read a value until EA +* @val: variable holding value +* @data: buffer of data +* @dlen: length of data +* +* Processes an EA value. Updates the passed variable and +* returns the processed data length. +*/ +static unsigned int gsm_read_ea_val (unsigned int *val,const u8 *data,int dlen) +{ +unsigned int len =0 ; + +for (; dlen >0 ; dlen--) { + len++; +if (gsm_read_ea (val, *data++)) +break ; + } +return len; +} +/** * gsm_encode_modem - encode modem data bits * @dlci: DLCI to encode from
@@ -746,6 +767,37 @@ static struct gsm_msg *gsm_data_alloc(struct gsm_mux *gsm, u8 addr, int len,return m; } +/** +* gsm_is_flow_ctrl_msg - checks if flow control message +* @msg: message to check +* +* Returns true if the given message is a flow control command of the +* control channel. False is returned in any other case. +*/ +static bool gsm_is_flow_ctrl_msg (struct gsm_msg *msg) +{ +unsigned int cmd; + +if (msg->addr >0 ) +return false; + +switch (msg->ctrl & ~PF ) { +case UI : +case UIH : + cmd =0 ; +if (gsm_read_ea_val (&cmd, msg->data +2 , msg->len -2 ) <1 ) +break ; +switch (cmd & ~PF ) { +case CMD_FCOFF : +case CMD_FCON : +return true; + } +break ; + } + +return false; +} +/** * gsm_data_kick - poke the queue * @gsm: GSM Mux
@@ -765,7 +817,7 @@ static void gsm_data_kick(struct gsm_mux *gsm, struct gsm_dlci *dlci)int len;list_for_each_entry_safe (msg, nmsg, &gsm->tx_list, list) { -if (gsm->constipated && msg->addr) +if (gsm->constipated && !gsm_is_flow_ctrl_msg (msg))continue ;if (gsm->encoding !=0 ) { gsm->txframe[0 ] =GSM1_SOF ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 588/779 tty: n_gsm: fix packet re-transmission without open control channel
In reply to Greg Kroah-HartmanFrom: Daniel Starke <[email protected]>
[ Upstream commit 4fae831b3a71fc5a44cc5c7d0b8c1267ee7659f5 ]
In the current implementation control packets are re-transmitted even if the control channel closed down during T2. This is wrong. Check whether the control channel is open before re-transmitting any packets. Note that control channel open/close is handled by T1 and not T2 and remains unaffected by this.
--- drivers/tty/n_gsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/tty/n_gsm.c +1 -1
@@ -1546,7 +1546,7 @@ static void gsm_control_retransmit(struct timer_list *t)spin_lock_irqsave (&gsm->control_lock, flags); ctrl = gsm->pending_cmd;if (ctrl) { -if (gsm->cretries ==0 ) { +if (gsm->cretries ==0 || !gsm->dlci[0 ] || gsm->dlci[0 ]->dead) { gsm->pending_cmd =NULL ; ctrl->error = -ETIMEDOUT ; ctrl->done =1 ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 589/779 tty: n_gsm: fix race condition in gsmld_write()
In reply to Greg Kroah-HartmanFrom: Daniel Starke <[email protected]>
[ Upstream commit 32dd59f96924f45e33bc79854f7a00679c0fa28e ]
The function may be used by the user directly and also by the n_gsm internal functions. They can lead into a race condition which results in interleaved frames if both are writing at the same time. The receiving side is not able to decode those interleaved frames correctly.
Add a lock around the low side tty write to avoid race conditions and frame interleaving between user originated writes and n_gsm writes.
--- drivers/tty/n_gsm.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-)
drivers/tty/n_gsm.c +17 -4
@@ -2911,11 +2911,24 @@ static ssize_t gsmld_read(struct tty_struct *tty, struct file *file,static ssize_t gsmld_write (struct tty_struct *tty,struct file *file,const unsigned char *buf,size_t nr) { -int space =tty_write_room (tty); +struct gsm_mux *gsm = tty->disc_data; +unsigned long flags; +int space; +int ret; + +if (!gsm) +return -ENODEV ; + + ret = -ENOBUFS ; +spin_lock_irqsave (&gsm->tx_lock, flags); + space =tty_write_room (tty);if (space >= nr) -return tty->ops->write (tty, buf, nr); -set_bit (TTY_DO_WRITE_WAKEUP , &tty->flags); -return -ENOBUFS ; + ret = tty->ops->write (tty, buf, nr); +else +set_bit (TTY_DO_WRITE_WAKEUP , &tty->flags); +spin_unlock_irqrestore (&gsm->tx_lock, flags); + +return ret; }/**
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 590/779 tty: n_gsm: fix resource allocation order in gsm_activate_mux()
In reply to Greg Kroah-HartmanFrom: Daniel Starke <[email protected]>
[ Upstream commit 7349660438603ed19282e75949561406531785a5 ]
Within gsm_activate_mux() all timers and locks are initiated before the actual resource for the control channel is allocated. This can lead to race conditions.
Allocate the control channel DLCI object first to avoid race conditions.
--- drivers/tty/n_gsm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/tty/n_gsm.c +4 -3
@@ -2435,6 +2435,10 @@ static int gsm_activate_mux(struct gsm_mux *gsm)struct gsm_dlci *dlci;int ret; + dlci =gsm_dlci_alloc (gsm,0 ); +if (dlci ==NULL ) +return -ENOMEM ; +timer_setup (&gsm->kick_timer, gsm_kick_timer,0 );timer_setup (&gsm->t2_timer, gsm_control_retransmit,0 );init_waitqueue_head (&gsm->event);
@@ -2450,9 +2454,6 @@ static int gsm_activate_mux(struct gsm_mux *gsm)if (ret)return ret; - dlci =gsm_dlci_alloc (gsm,0 ); -if (dlci ==NULL ) -return -ENOMEM ; gsm->has_devices = true; gsm->dead = false;/* Tty opens are now permissible */ return 0 ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 591/779 ASoC: qcom: Fix missing of_node_put() in asoc_qcom_lpass_cpu_platform_probe()
In reply to Greg Kroah-HartmanFrom: Liang He <[email protected]>
[ Upstream commit f507c0c67dac57d2bcd5dcae4b6139b0305d8957 ]
We should call of_node_put() for the reference 'dsp_of_node' returned by of_parse_phandle() which will increase the refcount.
--- sound/soc/qcom/lpass-cpu.c | 1 + 1 file changed, 1 insertion(+)
sound/soc/qcom/lpass-cpu.c +1 -0
@@ -880,6 +880,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) dsp_of_node =of_parse_phandle (pdev->dev.of_node,"qcom,adsp" ,0 );if (dsp_of_node) {dev_err (dev,"DSP exists and holds audio resources\n" ); +of_node_put (dsp_of_node);return -EBUSY ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 592/779 ASoC: imx-card: Fix DSD/PDM mclk frequency
In reply to Greg Kroah-HartmanFrom: Shengjiu Wang <[email protected]>
[ Upstream commit c0fabd12a8570cb932f13d9388f3d887ad44369b ]
The DSD/PDM rate not only DSD64/128/256/512, which are the multiple rate of 44.1kHz, but also support the multiple rate of 8kHz, so can't force all mclk frequency to be 22579200Hz, need to assign the frequency according to rate.
--- sound/soc/fsl/imx-card.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
sound/soc/fsl/imx-card.c +11 -3
@@ -17,6 +17,9 @@#include "fsl_sai.h" +#define IMX_CARD_MCLK_22P5792MHZ 22579200 +#define IMX_CARD_MCLK_24P576MHZ 24576000 +enum codec_type {CODEC_DUMMY =0 ,CODEC_AK5558 =1 ,
@@ -353,9 +356,14 @@ static int imx_aif_hw_params(struct snd_pcm_substream *substream, mclk_freq =akcodec_get_mclk_rate (substream, params, slots, slot_width); else mclk_freq =params_rate (params) * slots * slot_width; -/* Use the maximum freq from DSD512 (512*44100 = 22579200) */ -if (format_is_dsd (params)) - mclk_freq =22579200 ; + +if (format_is_dsd (params)) { +/* Use the maximum freq from DSD512 (512*44100 = 22579200) */ +if (!(params_rate (params) %11025 )) + mclk_freq =IMX_CARD_MCLK_22P5792MHZ ; +else + mclk_freq =IMX_CARD_MCLK_24P576MHZ ; + } ret =snd_soc_dai_set_sysclk (cpu_dai, link_data->cpu_sysclk_id, mclk_freq,SND_SOC_CLOCK_OUT );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 593/779 remoteproc: qcom: wcnss: Fix handling of IRQs
In reply to Greg Kroah-HartmanFrom: Sireesh Kodali <[email protected]>
[ Upstream commit bed0adac1ded4cb486ba19a3a7e730fbd9a1c9c6 ]
The wcnss_get_irq function is expected to return a value > 0 in the event that an IRQ is succssfully obtained, but it instead returns 0. This causes the stop and ready IRQs to never actually be used despite being defined in the device-tree. This patch fixes that.
--- drivers/remoteproc/qcom_wcnss.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/remoteproc/qcom_wcnss.c +8 -2
@@ -468,6 +468,7 @@ static int wcnss_request_irq(struct qcom_wcnss *wcnss, irq_handler_t thread_fn) {int ret; +int irq_number; ret =platform_get_irq_byname (pdev, name);if (ret <0 && optional) {
@@ -478,14 +479,19 @@ static int wcnss_request_irq(struct qcom_wcnss *wcnss,return ret; } + irq_number = ret; + ret =devm_request_threaded_irq (&pdev->dev, ret,NULL , thread_fn,IRQF_TRIGGER_RISING |IRQF_ONESHOT ,"wcnss" , wcnss); -if (ret) +if (ret) {dev_err (&pdev->dev,"request %s IRQ failed\n" , name); +return ret; + } -return ret; +/* Return the IRQ number if the IRQ was successfully acquired */ +return irq_number; }static int wcnss_alloc_memory_region (struct qcom_wcnss *wcnss)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 594/779 vfio/ccw: Do not change FSM state in subchannel event
In reply to Greg Kroah-HartmanFrom: Eric Farman <[email protected]>
[ Upstream commit cffcc109fd682075dee79bade3d60a07152a8fd1 ]
The routine vfio_ccw_sch_event() is tasked with handling subchannel events, specifically machine checks, on behalf of vfio-ccw. It correctly calls cio_update_schib(), and if that fails (meaning the subchannel is gone) it makes an FSM event call to mark the subchannel Not Operational.
If that worked, however, then it decides that if the FSM state was already Not Operational (implying the subchannel just came back), then it should simply change the FSM to partially- or fully-open.
Remove this trickery, since a subchannel returning will require more probing than simply "oh all is well again" to ensure it works correctly.
--- drivers/s390/cio/vfio_ccw_drv.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-)
drivers/s390/cio/vfio_ccw_drv.c +3 -11
@@ -287,19 +287,11 @@ static int vfio_ccw_sch_event(struct subchannel *sch, int process)if (work_pending (&sch->todo_work)) goto out_unlock; -if (cio_update_schib (sch)) { -vfio_ccw_fsm_event (private,VFIO_CCW_EVENT_NOT_OPER ); - rc =0 ; - goto out_unlock; - } - - private =dev_get_drvdata (&sch->dev); -if (private->state ==VFIO_CCW_STATE_NOT_OPER ) { - private->state = private->mdev ?VFIO_CCW_STATE_IDLE : -VFIO_CCW_STATE_STANDBY ; - } rc =0 ; +if (cio_update_schib (sch)) +vfio_ccw_fsm_event (private,VFIO_CCW_EVENT_NOT_OPER ); + out_unlock:spin_unlock_irqrestore (sch->lock, flags);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 595/779 serial: 8250_fsl: Dont report FE, PE and OE twice
In reply to Greg Kroah-HartmanFrom: Uwe Kleine-König <[email protected]>
[ Upstream commit 9d3aaceb73acadf134596a2f8db9c451c1332d3d ]
Some Freescale 8250 implementations have the problem that a single long break results in one irq per character frame time. The code in fsl8250_handle_irq() that is supposed to handle that uses the BI bit in lsr_saved_flags to detect such a situation and then skip the second received character. However it also stores other error bits and so after a single frame error the character received in the next irq handling is passed to the upper layer with a frame error, too.
So after a spike on the data line (which is correctly recognized as a frame error) the following valid character is thrown away, because the driver reports a frame error for that one, too.
To weaken this problem restrict saving LSR to only the BI bit.
Note however that the handling is still broken:
- lsr_saved_flags is updated using orig_lsr which is the LSR content for the first received char, but there might be more in the FIFO, so a character is thrown away that is received later and not necessarily the one following the break.
- The doubled break might be the 2nd and 3rd char in the FIFO, so the workaround doesn't catch these, because serial8250_rx_chars() doesn't handle the workaround.
- lsr_saved_flags might have set UART_LSR_BI at the entry of fsl8250_handle_irq() which doesn't originate from fsl8250_handle_irq()'s "up->lsr_saved_flags |= orig_lsr & UART_LSR_BI;" but from e.g. from serial8250_tx_empty().
- For a long or a short break this isn't about two characters, but more or only a single one.
--- drivers/tty/serial/8250/8250_fsl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/tty/serial/8250/8250_fsl.c +1 -1
@@ -81,7 +81,7 @@ int fsl8250_handle_irq(struct uart_port *port)if ((lsr &UART_LSR_THRE ) && (up->ier &UART_IER_THRI ))serial8250_tx_chars (up); - up->lsr_saved_flags = orig_lsr; + up->lsr_saved_flags |= orig_lsr &UART_LSR_BI ;uart_unlock_and_check_sysrq_irqrestore (&up->port, flags);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 596/779 tty: n_gsm: fix wrong T1 retry count handling
In reply to Greg Kroah-HartmanFrom: Daniel Starke <[email protected]>
[ Upstream commit f30e10caa80aa1f35508bc17fc302dbbde9a833c ]
n_gsm is based on the 3GPP 07.010 and its newer version is the 3GPP 27.010.
See https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=1516
The changes from 07.010 to 27.010 are non-functional. Therefore, I refer to
the newer 27.010 here. Chapter 5.7.3 states that the valid range for the
maximum number of retransmissions (N2) is from 0 to 255 (both including).gsm_dlci_t1() handles this number incorrectly by performing N2 - 1
retransmission attempts. Setting N2 to zero results in more than 255
retransmission attempts.
Fix gsm_dlci_t1() to comply with 3GPP 27.010.
--- drivers/tty/n_gsm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/tty/n_gsm.c +2 -2
@@ -1711,8 +1711,8 @@ static void gsm_dlci_t1(struct timer_list *t)switch (dlci->state) {case DLCI_OPENING : - dlci->retries--;if (dlci->retries) { + dlci->retries--;gsm_command (dlci->gsm, dlci->addr,SABM |PF );mod_timer (&dlci->t1, jiffies + gsm->t1 *HZ /100 ); }else if (!dlci->addr && gsm->control == (DM |PF )) {
@@ -1727,8 +1727,8 @@ static void gsm_dlci_t1(struct timer_list *t)break ;case DLCI_CLOSING : - dlci->retries--;if (dlci->retries) { + dlci->retries--;gsm_command (dlci->gsm, dlci->addr,DISC |PF );mod_timer (&dlci->t1, jiffies + gsm->t1 *HZ /100 ); }else
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 597/779 tty: n_gsm: fix DM command
In reply to Greg Kroah-HartmanFrom: Daniel Starke <[email protected]>
[ Upstream commit 18a948c7d90995d127785e308fa7b701df4c499f ]
n_gsm is based on the 3GPP 07.010 and its newer version is the 3GPP 27.010.
See https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=1516
The changes from 07.010 to 27.010 are non-functional. Therefore, I refer to
the newer 27.010 here. Chapter 5.3.3 defines the DM response. There exists
no DM command. However, the current implementation incorrectly sends DM as
command in case of unexpected UIH frames in gsm_queue().
Correct this behavior by always sending DM as response.
--- drivers/tty/n_gsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/tty/n_gsm.c +1 -1
@@ -2148,7 +2148,7 @@ static void gsm_queue(struct gsm_mux *gsm) goto invalid;#endif if (dlci ==NULL || dlci->state !=DLCI_OPEN ) { -gsm_command (gsm, address,DM |PF ); +gsm_response (gsm, address,DM |PF );return ; } dlci->data (dlci, gsm->buf, gsm->len);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 598/779 tty: n_gsm: fix missing corner cases in gsmld_poll()
In reply to Greg Kroah-HartmanFrom: Daniel Starke <[email protected]>
[ Upstream commit 7e5b4322cde067e1d0f1bf8f490e93f664a7c843 ]
gsmld_poll() currently fails to handle the following corner cases correctly:
- remote party closed the associated tty
Add the missing checks and map those to EPOLLHUP. Reorder the checks to group them by their reaction.
--- drivers/tty/n_gsm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/tty/n_gsm.c +5 -2
@@ -2954,12 +2954,15 @@ static __poll_t gsmld_poll(struct tty_struct *tty, struct file *file,poll_wait (file, &tty->read_wait, wait);poll_wait (file, &tty->write_wait, wait); + +if (gsm->dead) + mask |=EPOLLHUP ;if (tty_hung_up_p (file)) mask |=EPOLLHUP ; +if (test_bit (TTY_OTHER_CLOSED , &tty->flags)) + mask |=EPOLLHUP ;if (!tty_is_writelocked (tty) &&tty_write_room (tty) >0 ) mask |=EPOLLOUT |EPOLLWRNORM ; -if (gsm->dead) - mask |=EPOLLHUP ;return mask; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 599/779 MIPS: vdso: Utilize __pa() for gic_pfn
In reply to Greg Kroah-HartmanFrom: Florian Fainelli <[email protected]>
[ Upstream commit 8baa65126e19af5ee9f3c07e7bb53da41c39e4b1 ]
The GIC user offset is mapped into every process' virtual address and is therefore part of the hot-path of arch_setup_additional_pages(). Utilize __pa() such that we are more optimal even when CONFIG_DEBUG_VIRTUAL is enabled, and while at it utilize PFN_DOWN() instead of open-coding the right shift by PAGE_SHIFT.
--- arch/mips/kernel/vdso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/mips/kernel/vdso.c +1 -1
@@ -159,7 +159,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)/* Map GIC user page. */ if (gic_size) { gic_base = (unsigned long )mips_gic_base +MIPS_GIC_USER_OFS ; - gic_pfn =virt_to_phys ((void *)gic_base) >>PAGE_SHIFT ; + gic_pfn =PFN_DOWN (__pa (gic_base)); ret =io_remap_pfn_range (vma, base, gic_pfn, gic_size,pgprot_noncached (vma->vm_page_prot));
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 600/779 swiotlb: fail map correctly with failed io_tlb_default_mem
In reply to Greg Kroah-HartmanFrom: Robin Murphy <[email protected]>
[ Upstream commit c51ba246cb172c9e947dc6fb8868a1eaf0b2a913 ]
In the failure case of trying to use a buffer which we'd previously failed to allocate, the "!mem" condition is no longer sufficient since io_tlb_default_mem became static and assigned by default. Update the condition to work as intended per the rest of that conversion.
--- kernel/dma/swiotlb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/dma/swiotlb.c +1 -1
@@ -551,7 +551,7 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,int index;phys_addr_t tlb_addr; -if (!mem) +if (!mem || !mem->nslabs)panic ("Can not allocate SWIOTLB buffer earlier and can't now provide you with the DMA bounce buffer" );if (mem_encrypt_active ())
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 601/779 ASoC: mt6359: Fix refcount leak bug
In reply to Greg Kroah-HartmanFrom: Liang He <[email protected]>
[ Upstream commit a8d5df69e2ec702d979f7d04ed519caf8691a032 ]
In mt6359_parse_dt() and mt6359_accdet_parse_dt(), we should call of_node_put() for the reference returned by of_get_child_by_name() which has increased the refcount.
--- sound/soc/codecs/mt6359-accdet.c | 1 + sound/soc/codecs/mt6359.c | 1 + 2 files changed, 2 insertions(+)
sound/soc/codecs/mt6359-accdet.c +1 -0
@@ -675,6 +675,7 @@ static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv) sizeof(struct three_key_threshold)); } +of_node_put (node);dev_warn (priv->dev,"accdet caps=%x\n" , priv->caps);return 0 ;
sound/soc/codecs/mt6359.c +1 -0
@@ -2780,6 +2780,7 @@ static int mt6359_parse_dt(struct mt6359_priv *priv) ret =of_property_read_u32 (np,"mediatek,mic-type-2" , &priv->mux_select[MUX_MIC_TYPE_2 ]); +of_node_put (np);if (ret) { dev_info(priv->dev, "%s() failed to read mic-type-2, use default (%d)\n",
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 602/779 serial: 8250_bcm7271: Save/restore RTS in suspend/resume
In reply to Greg Kroah-HartmanFrom: Doug Berger <[email protected]>
[ Upstream commit 3182efd036c1b955403d131258234896cbd9fbeb ]
Commit 9cabe26e65a8 ("serial: 8250_bcm7271: UART errors after resuming from S2") prevented an early enabling of RTS during resume, but it did not actively restore the RTS state after resume.
--- drivers/tty/serial/8250/8250_bcm7271.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
drivers/tty/serial/8250/8250_bcm7271.c +18 -6
@@ -1141,16 +1141,19 @@ static int __maybe_unused brcmuart_suspend(struct device *dev)struct brcmuart_priv *priv =dev_get_drvdata (dev);struct uart_8250_port *up =serial8250_get_port (priv->line);struct uart_port *port = &up->port; - -serial8250_suspend_port (priv->line); -clk_disable_unprepare (priv->baud_mux_clk); +unsigned long flags;/* * This will prevent resume from enabling RTS before the -* baud rate has been resored. +* baud rate has been restored. */ +spin_lock_irqsave (&port->lock, flags); priv->saved_mctrl = port->mctrl; - port->mctrl =0 ; + port->mctrl &= ~TIOCM_RTS ; +spin_unlock_irqrestore (&port->lock, flags); + +serial8250_suspend_port (priv->line); +clk_disable_unprepare (priv->baud_mux_clk);return 0 ; }
@@ -1160,6 +1163,7 @@ static int __maybe_unused brcmuart_resume(struct device *dev)struct brcmuart_priv *priv =dev_get_drvdata (dev);struct uart_8250_port *up =serial8250_get_port (priv->line);struct uart_port *port = &up->port; +unsigned long flags;int ret; ret =clk_prepare_enable (priv->baud_mux_clk);
@@ -1182,7 +1186,15 @@ static int __maybe_unused brcmuart_resume(struct device *dev)start_rx_dma (serial8250_get_port (priv->line)); }serial8250_resume_port (priv->line); - port->mctrl = priv->saved_mctrl; + +if (priv->saved_mctrl &TIOCM_RTS ) { +/* Restore RTS */ +spin_lock_irqsave (&port->lock, flags); + port->mctrl |=TIOCM_RTS ; + port->ops->set_mctrl (port, port->mctrl); +spin_unlock_irqrestore (&port->lock, flags); + } +return 0 ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 603/779 iommu/exynos: Handle failed IOMMU device registration properly
In reply to Greg Kroah-HartmanFrom: Sam Protsenko <[email protected]>
[ Upstream commit fce398d2d02c0a9a2bedf7c7201b123e153e8963 ]
If iommu_device_register() fails in exynos_sysmmu_probe(), the previous calls have to be cleaned up. In this case, the iommu_device_sysfs_add() should be cleaned up, by calling its remove counterpart call.
--- drivers/iommu/exynos-iommu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/iommu/exynos-iommu.c +5 -1
@@ -630,7 +630,7 @@ static int exynos_sysmmu_probe(struct platform_device *pdev) ret =iommu_device_register (&data->iommu, &exynos_iommu_ops, dev);if (ret) -return ret; + goto err_iommu_register;platform_set_drvdata (pdev, data);
@@ -657,6 +657,10 @@ static int exynos_sysmmu_probe(struct platform_device *pdev)pm_runtime_enable (dev);return 0 ; + +err_iommu_register: +iommu_device_sysfs_remove (&data->iommu); +return ret; }static int __maybe_unused exynos_sysmmu_suspend (struct device *dev)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 604/779 9p: fix a bunch of checkpatch warnings
In reply to Greg Kroah-HartmanFrom: Dominique Martinet <[email protected]>
[ Upstream commit 6e195b0f7c8e50927fa31946369c22a0534ec7e2 ]
Sohaib Mohamed started a serie of tiny and incomplete checkpatch fixes but seemingly stopped halfway -- take over and do most of it.
This is still missing net/9p/trans* and net/9p/protocol.c for a later time...
--- fs/9p/acl.c | 1 + fs/9p/acl.h | 17 +- fs/9p/cache.c | 4 +- fs/9p/v9fs.c | 4 + fs/9p/v9fs_vfs.h | 11 +- fs/9p/vfs_addr.c | 6 +- fs/9p/vfs_dentry.c | 2 + fs/9p/vfs_file.c | 1 + fs/9p/vfs_inode.c | 14 +- fs/9p/vfs_inode_dotl.c | 9 +- fs/9p/vfs_super.c | 7 +- fs/9p/xattr.h | 19 +- include/net/9p/9p.h | 10 +- include/net/9p/client.h | 22 +- include/net/9p/transport.h | 18 +- net/9p/client.c | 432 ++++++++++++++++++------------------- net/9p/error.c | 2 +- net/9p/mod.c | 9 +- net/9p/protocol.c | 36 ++-- net/9p/protocol.h | 2 +- net/9p/trans_common.h | 2 +- 21 files changed, 323 insertions(+), 305 deletions(-)
fs/9p/acl.c +1 -0
@@ -123,6 +123,7 @@ static int v9fs_set_acl(struct p9_fid *fid, int type, struct posix_acl *acl)char *name;size_t size;void *buffer; +if (!acl)return 0 ;
fs/9p/acl.h +9 -8
@@ -15,14 +15,15 @@#define FS_9P_ACL_H #ifdef CONFIG_9P_FS_POSIX_ACL -extern int v9fs_get_acl (struct inode *,struct p9_fid *); -extern struct posix_acl *v9fs_iop_get_acl (struct inode *inode,int type,bool rcu); -extern int v9fs_acl_chmod (struct inode *,struct p9_fid *); -extern int v9fs_set_create_acl (struct inode *,struct p9_fid *, -struct posix_acl *,struct posix_acl *); -extern int v9fs_acl_mode (struct inode *dir,umode_t *modep, -struct posix_acl **dpacl,struct posix_acl **pacl); -extern void v9fs_put_acl (struct posix_acl *dacl,struct posix_acl *acl); +int v9fs_get_acl (struct inode *inode,struct p9_fid *fid); +struct posix_acl *v9fs_iop_get_acl (struct inode *inode,int type, +bool rcu); +int v9fs_acl_chmod (struct inode *inode,struct p9_fid *fid); +int v9fs_set_create_acl (struct inode *inode,struct p9_fid *fid, +struct posix_acl *dacl,struct posix_acl *acl); +int v9fs_acl_mode (struct inode *dir,umode_t *modep, +struct posix_acl **dpacl,struct posix_acl **pacl); +void v9fs_put_acl (struct posix_acl *dacl,struct posix_acl *acl);#else #define v9fs_iop_get_acl NULLstatic inline int v9fs_get_acl (struct inode *inode,struct p9_fid *fid)
fs/9p/cache.c +2 -2
@@ -19,8 +19,8 @@#define CACHETAG_LEN 11struct fscache_netfs v9fs_cache_netfs = { - .name ="9p" , - .version =0 , + .name ="9p" , + .version =0 , };/*
fs/9p/v9fs.c +4 -0
@@ -190,8 +190,10 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)while ((p =strsep (&options,"," )) !=NULL ) {int token, r; +if (!*p)continue ; + token =match_token (p, tokens, args);switch (token) {case Opt_debug:
@@ -659,6 +661,7 @@ static void v9fs_destroy_inode_cache(void)static int v9fs_cache_register (void ) {int ret; + ret =v9fs_init_inode_cache ();if (ret <0 )return ret;
@@ -686,6 +689,7 @@ static void v9fs_cache_unregister(void)static int __init init_v9fs (void ) {int err; +pr_info ("Installing v9fs 9p2000 file system support\n" );/* TODO: Setup list of registered trasnport modules */
fs/9p/v9fs_vfs.h +6 -5
@@ -44,9 +44,10 @@ extern struct kmem_cache *v9fs_inode_cache;struct inode *v9fs_alloc_inode (struct super_block *sb);void v9fs_free_inode (struct inode *inode); -struct inode *v9fs_get_inode (struct super_block *sb,umode_t mode,dev_t ); +struct inode *v9fs_get_inode (struct super_block *sb,umode_t mode, +dev_t rdev);int v9fs_init_inode (struct v9fs_session_info *v9ses, -struct inode *inode,umode_t mode,dev_t ); +struct inode *inode,umode_t mode,dev_t rdev);void v9fs_evict_inode (struct inode *inode);ino_t v9fs_qid2ino (struct p9_qid *qid); void v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
@@ -59,8 +60,8 @@ void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat);int v9fs_uflags2omode (int uflags,int extended);void v9fs_blank_wstat (struct p9_wstat *wstat); -int v9fs_vfs_setattr_dotl (struct user_namespace *,struct dentry *, -struct iattr *); +int v9fs_vfs_setattr_dotl (struct user_namespace *mnt_userns, +struct dentry *dentry,struct iattr *iattr);int v9fs_file_fsync_dotl (struct file *filp,loff_t start,loff_t end,int datasync);int v9fs_refresh_inode (struct p9_fid *fid,struct inode *inode);
@@ -68,9 +69,9 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode);static inline void v9fs_invalidate_inode_attr (struct inode *inode) {struct v9fs_inode *v9inode; + v9inode =V9FS_I (inode); v9inode->cache_validity |=V9FS_INO_INVALID_ATTR ; -return ; }int v9fs_open_to_dotl_flags (int flags);
fs/9p/vfs_addr.c +4 -2
@@ -242,11 +242,13 @@ v9fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)loff_t pos = iocb->ki_pos;ssize_t n;int err =0 ; +if (iov_iter_rw (iter) ==WRITE ) { n =p9_client_write (file->private_data, pos, iter, &err);if (n) {struct inode *inode =file_inode (file);loff_t i_size =i_size_read (inode); +if (pos + n > i_size)inode_add_bytes (inode, pos + n - i_size); }
@@ -257,7 +259,7 @@ v9fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) }static int v9fs_write_begin (struct file *filp,struct address_space *mapping, -loff_t pos,unsigned len,unsigned flags, +loff_t pos,unsigned int len,unsigned int flags,struct page **pagep,void **fsdata) {int retval =0 ;
@@ -293,7 +295,7 @@ static int v9fs_write_begin(struct file *filp, struct address_space *mapping, }static int v9fs_write_end (struct file *filp,struct address_space *mapping, -loff_t pos,unsigned len,unsigned copied, +loff_t pos,unsigned int len,unsigned int copied,struct page *page,void *fsdata) {loff_t last_pos = pos + copied;
fs/9p/vfs_dentry.c +2 -0
@@ -52,6 +52,7 @@ static int v9fs_cached_dentry_delete(const struct dentry *dentry)static void v9fs_dentry_release (struct dentry *dentry) {struct hlist_node *p, *n; +p9_debug (P9_DEBUG_VFS ," dentry: %pd (%p)\n" , dentry, dentry);hlist_for_each_safe (p, n, (struct hlist_head *)&dentry->d_fsdata)
@@ -76,6 +77,7 @@ static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)if (v9inode->cache_validity &V9FS_INO_INVALID_ATTR ) {int retval;struct v9fs_session_info *v9ses; + fid =v9fs_fid_lookup (dentry);if (IS_ERR (fid))return PTR_ERR (fid);
fs/9p/vfs_file.c +1 -0
@@ -408,6 +408,7 @@ v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)struct inode *inode =file_inode (file);loff_t i_size;unsigned long pg_start, pg_end; + pg_start = origin >>PAGE_SHIFT ; pg_end = (origin + retval -1 ) >>PAGE_SHIFT ;if (inode->i_mapping && inode->i_mapping->nrpages)
fs/9p/vfs_inode.c +9 -5
@@ -49,6 +49,7 @@ static const struct inode_operations v9fs_symlink_inode_operations;static u32 unixmode2p9mode (struct v9fs_session_info *v9ses,umode_t mode) {int res; + res = mode &0777 ;if (S_ISDIR (mode)) res |=P9_DMDIR ;
@@ -223,6 +224,7 @@ v9fs_blank_wstat(struct p9_wstat *wstat)struct inode *v9fs_alloc_inode (struct super_block *sb) {struct v9fs_inode *v9inode; + v9inode =kmem_cache_alloc (v9fs_inode_cache,GFP_KERNEL );if (!v9inode)return NULL ;
@@ -251,7 +253,7 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses, {int err =0 ; -inode_init_owner (&init_user_ns,inode,NULL , mode); +inode_init_owner (&init_user_ns, inode,NULL , mode); inode->i_blocks =0 ; inode->i_rdev = rdev; inode->i_atime = inode->i_mtime = inode->i_ctime =current_time (inode);
@@ -440,7 +442,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,unsigned long i_ino;struct inode *inode;struct v9fs_session_info *v9ses = sb->s_fs_info; -int (*test)(struct inode *,void *); +int (*test)(struct inode *inode,void *data);if (new) test = v9fs_test_new_inode;
@@ -499,8 +501,10 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,static int v9fs_at_to_dotl_flags (int flags) {int rflags =0 ; +if (flags &AT_REMOVEDIR ) rflags |=P9_DOTL_AT_REMOVEDIR ; +return rflags; }
@@ -797,7 +801,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,static int v9fs_vfs_atomic_open (struct inode *dir,struct dentry *dentry, -struct file *file,unsigned flags,umode_t mode) +struct file *file,unsigned int flags,umode_t mode) {int err;u32 perm;
@@ -1084,7 +1088,7 @@ static int v9fs_vfs_setattr(struct user_namespace *mnt_userns, fid =v9fs_fid_lookup (dentry); use_dentry =1 ; } -if (IS_ERR (fid)) +if (IS_ERR (fid))return PTR_ERR (fid);v9fs_blank_wstat (&wstat);
@@ -1364,7 +1368,7 @@ v9fs_vfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,char name[2 +U32_MAX_DIGITS +1 +U32_MAX_DIGITS +1 ];u32 perm; -p9_debug (P9_DEBUG_VFS ," %lu,%pd mode: %hx MAJOR: %u MINOR: %u\n" , +p9_debug (P9_DEBUG_VFS ," %lu,%pd mode: %x MAJOR: %u MINOR: %u\n" , dir->i_ino, dentry, mode,MAJOR (rdev),MINOR (rdev));
fs/9p/vfs_inode_dotl.c +5 -4
@@ -107,7 +107,7 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,unsigned long i_ino;struct inode *inode;struct v9fs_session_info *v9ses = sb->s_fs_info; -int (*test)(struct inode *,void *); +int (*test)(struct inode *inode,void *data);if (new) test = v9fs_test_new_inode_dotl;
@@ -230,7 +230,7 @@ v9fs_vfs_create_dotl(struct user_namespace *mnt_userns, struct inode *dir,static int v9fs_vfs_atomic_open_dotl (struct inode *dir,struct dentry *dentry, -struct file *file,unsigned flags,umode_t omode) +struct file *file,unsigned int flags,umode_t omode) {int err =0 ;kgid_t gid;
@@ -261,7 +261,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, v9ses =v9fs_inode2v9ses (dir); name = dentry->d_name.name; -p9_debug (P9_DEBUG_VFS ,"name:%s flags:0x%x mode:0x%hx\n" , +p9_debug (P9_DEBUG_VFS ,"name:%s flags:0x%x mode:0x%x\n" , name, flags, omode); dfid =v9fs_parent_fid (dentry);
@@ -821,6 +821,7 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,if (v9ses->cache ==CACHE_LOOSE || v9ses->cache ==CACHE_FSCACHE ) {/* Get the latest stat info from server. */ struct p9_fid *fid; + fid =v9fs_fid_lookup (old_dentry);if (IS_ERR (fid))return PTR_ERR (fid);
@@ -857,7 +858,7 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,struct p9_qid qid;struct posix_acl *dacl =NULL , *pacl =NULL ; -p9_debug (P9_DEBUG_VFS ," %lu,%pd mode: %hx MAJOR: %u MINOR: %u\n" , +p9_debug (P9_DEBUG_VFS ," %lu,%pd mode: %x MAJOR: %u MINOR: %u\n" , dir->i_ino, dentry, omode,MAJOR (rdev),MINOR (rdev));
fs/9p/vfs_super.c +5 -2
@@ -113,7 +113,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,struct inode *inode =NULL ;struct dentry *root =NULL ;struct v9fs_session_info *v9ses =NULL ; -umode_t mode =S_IRWXUGO |S_ISVTX ; +umode_t mode =0777 |S_ISVTX ;struct p9_fid *fid;int retval =0 ;
@@ -157,6 +157,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, sb->s_root = root;if (v9fs_proto_dotl (v9ses)) {struct p9_stat_dotl *st =NULL ; + st =p9_client_getattr_dotl (fid,P9_STATS_BASIC );if (IS_ERR (st)) { retval =PTR_ERR (st);
@@ -167,6 +168,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,kfree (st); }else {struct p9_wstat *st =NULL ; + st =p9_client_stat (fid);if (IS_ERR (st)) { retval =PTR_ERR (st);
@@ -275,12 +277,13 @@ static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf)static int v9fs_drop_inode (struct inode *inode) {struct v9fs_session_info *v9ses; + v9ses =v9fs_inode2v9ses (inode);if (v9ses->cache ==CACHE_LOOSE || v9ses->cache ==CACHE_FSCACHE )return generic_drop_inode (inode);/* * in case of non cached mode always drop the -* the inode because we want the inode attribute +* inode because we want the inode attribute * to always match that on the server. */ return 1 ;
fs/9p/xattr.h +10 -9
@@ -22,13 +22,14 @@ extern const struct xattr_handler *v9fs_xattr_handlers[];extern const struct xattr_handler v9fs_xattr_acl_access_handler;extern const struct xattr_handler v9fs_xattr_acl_default_handler; -extern ssize_t v9fs_fid_xattr_get (struct p9_fid *,const char *, -void *,size_t ); -extern ssize_t v9fs_xattr_get (struct dentry *,const char *, -void *,size_t ); -extern int v9fs_fid_xattr_set (struct p9_fid *,const char *, -const void *,size_t ,int ); -extern int v9fs_xattr_set (struct dentry *,const char *, -const void *,size_t ,int ); -extern ssize_t v9fs_listxattr (struct dentry *,char *,size_t ); +ssize_t v9fs_fid_xattr_get (struct p9_fid *fid,const char *name, +void *buffer,size_t buffer_size); +ssize_t v9fs_xattr_get (struct dentry *dentry,const char *name, +void *buffer,size_t buffer_size); +int v9fs_fid_xattr_set (struct p9_fid *fid,const char *name, +const void *value,size_t value_len,int flags); +int v9fs_xattr_set (struct dentry *dentry,const char *name, +const void *value,size_t value_len,int flags); +ssize_t v9fs_listxattr (struct dentry *dentry,char *buffer, +size_t buffer_size);#endif /* FS_9P_XATTR_H */
include/net/9p/9p.h +5 -5
@@ -32,13 +32,13 @@*/ enum p9_debug_flags { -P9_DEBUG_ERROR = (1 <<0 ), -P9_DEBUG_9P = (1 <<2 ), +P9_DEBUG_ERROR = (1 <<0 ), +P9_DEBUG_9P = (1 <<2 ),P9_DEBUG_VFS = (1 <<3 ),P9_DEBUG_CONV = (1 <<4 ),P9_DEBUG_MUX = (1 <<5 ),P9_DEBUG_TRANS = (1 <<6 ), -P9_DEBUG_SLABS = (1 <<7 ), +P9_DEBUG_SLABS = (1 <<7 ),P9_DEBUG_FCALL = (1 <<8 ),P9_DEBUG_FID = (1 <<9 ),P9_DEBUG_PKT = (1 <<10 ),
@@ -317,8 +317,8 @@ enum p9_qid_t { };/* 9P Magic Numbers */ -#define P9_NOTAG (u16)(~0) -#define P9_NOFID (u32)(~0) +#define P9_NOTAG ((u16)(~0)) +#define P9_NOFID ((u32)(~0))#define P9_MAXWELEM 16/* Minimal header size: size[4] type[1] tag[2] */
include/net/9p/client.h +13 -9
@@ -23,7 +23,7 @@* @p9_proto_2000L: 9P2000.L extension */ -enum p9_proto_versions { +enum p9_proto_versions { p9_proto_legacy, p9_proto_2000u, p9_proto_2000L,
@@ -219,13 +219,13 @@ struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid, u64 request_mask);int p9_client_mknod_dotl (struct p9_fid *oldfid,const char *name,int mode, -dev_t rdev,kgid_t gid,struct p9_qid *); +dev_t rdev,kgid_t gid,struct p9_qid *qid);int p9_client_mkdir_dotl (struct p9_fid *fid,const char *name,int mode, -kgid_t gid,struct p9_qid *); +kgid_t gid,struct p9_qid *qid);int p9_client_lock_dotl (struct p9_fid *fid,struct p9_flock *flock,u8 *status);int p9_client_getlock_dotl (struct p9_fid *fid,struct p9_getlock *fl);void p9_fcall_fini (struct p9_fcall *fc); -struct p9_req_t *p9_tag_lookup (struct p9_client *,u16 ); +struct p9_req_t *p9_tag_lookup (struct p9_client *c,u16 tag);static inline void p9_req_get (struct p9_req_t *r) {
@@ -241,14 +241,18 @@ int p9_req_put(struct p9_req_t *r);void p9_client_cb (struct p9_client *c,struct p9_req_t *req,int status); -int p9_parse_header (struct p9_fcall *,int32_t *,int8_t *,int16_t *,int ); -int p9stat_read (struct p9_client *,char *,int ,struct p9_wstat *); -void p9stat_free (struct p9_wstat *); +int p9_parse_header (struct p9_fcall *pdu,int32_t *size,int8_t *type, +int16_t *tag,int rewind); +int p9stat_read (struct p9_client *clnt,char *buf,int len, +struct p9_wstat *st); +void p9stat_free (struct p9_wstat *stbuf);int p9_is_proto_dotu (struct p9_client *clnt);int p9_is_proto_dotl (struct p9_client *clnt); -struct p9_fid *p9_client_xattrwalk (struct p9_fid *,const char *,u64 *); -int p9_client_xattrcreate (struct p9_fid *,const char *,u64 ,int ); +struct p9_fid *p9_client_xattrwalk (struct p9_fid *file_fid, +const char *attr_name,u64 *attr_size); +int p9_client_xattrcreate (struct p9_fid *fid,const char *name, +u64 attr_size,int flags);int p9_client_readlink (struct p9_fid *fid,char **target);int p9_client_init (void );
include/net/9p/transport.h +10 -8
@@ -40,14 +40,16 @@ struct p9_trans_module {int maxsize;/* max message size of transport */ int def;/* this transport should be default */ struct module *owner; -int (*create)(struct p9_client *,const char *,char *); -void (*close) (struct p9_client *); -int (*request) (struct p9_client *,struct p9_req_t *req); -int (*cancel) (struct p9_client *,struct p9_req_t *req); -int (*cancelled)(struct p9_client *,struct p9_req_t *req); -int (*zc_request)(struct p9_client *,struct p9_req_t *, -struct iov_iter *,struct iov_iter *,int ,int ,int ); -int (*show_options)(struct seq_file *,struct p9_client *); +int (*create)(struct p9_client *client, +const char *devname,char *args); +void (*close)(struct p9_client *client); +int (*request)(struct p9_client *client,struct p9_req_t *req); +int (*cancel)(struct p9_client *client,struct p9_req_t *req); +int (*cancelled)(struct p9_client *client,struct p9_req_t *req); +int (*zc_request)(struct p9_client *client,struct p9_req_t *req, +struct iov_iter *uidata,struct iov_iter *uodata, +int inlen,int outlen,int in_hdr_len); +int (*show_options)(struct seq_file *m,struct p9_client *client); };void v9fs_register_trans (struct p9_trans_module *m);
net/9p/client.c +212 -220
1,043 lines not on this page · raw message
net/9p/error.c +1 -1
@@ -185,7 +185,7 @@ int p9_error_init(void)INIT_HLIST_HEAD (&hash_errmap[bucket]);/* load initial error map into hash table */ -for (c = errmap; c->name !=NULL ; c++) { +for (c = errmap; c->name; c++) { c->namelen =strlen (c->name); bucket =jhash (c->name, c->namelen,0 ) %ERRHASHSZ ;INIT_HLIST_NODE (&c->list);
net/9p/mod.c +3 -6
@@ -24,13 +24,13 @@#include <linux/spinlock.h> #ifdef CONFIG_NET_9P_DEBUG -unsigned int p9_debug_level =0 ;/* feature-rific global debug level */ +unsigned int p9_debug_level;/* feature-rific global debug level */ EXPORT_SYMBOL (p9_debug_level);module_param_named (debug, p9_debug_level, uint,0 );MODULE_PARM_DESC (debug,"9P debugging level" );void _p9_debug (enum p9_debug_flags level,const char *func, -const char *fmt, ...) +const char *fmt, ...) {struct va_format vaf;va_list args;
@@ -53,10 +53,7 @@ void _p9_debug(enum p9_debug_flags level, const char *func,EXPORT_SYMBOL (_p9_debug);#endif -/* -* Dynamic Transport Registration Routines -* -*/ +/* Dynamic Transport Registration Routines */ static DEFINE_SPINLOCK (v9fs_trans_lock);static LIST_HEAD (v9fs_trans_list);
net/9p/protocol.c +19 -17
@@ -46,6 +46,7 @@ EXPORT_SYMBOL(p9stat_free);size_t pdu_read (struct p9_fcall *pdu,void *data,size_t size) {size_t len =min (pdu->size - pdu->offset, size); +memcpy (data, &pdu->sdata[pdu->offset], len); pdu->offset += len;return size - len;
@@ -54,6 +55,7 @@ size_t pdu_read(struct p9_fcall *pdu, void *data, size_t size)static size_t pdu_write (struct p9_fcall *pdu,const void *data,size_t size) {size_t len =min (pdu->capacity - pdu->size, size); +memcpy (&pdu->sdata[pdu->size], data, len); pdu->size += len;return size - len;
@@ -64,6 +66,7 @@ pdu_write_u(struct p9_fcall *pdu, struct iov_iter *from, size_t size) {size_t len =min (pdu->capacity - pdu->size, size);struct iov_iter i = *from; +if (!copy_from_iter_full (&pdu->sdata[pdu->size], len, &i)) len =0 ;
@@ -71,26 +74,25 @@ pdu_write_u(struct p9_fcall *pdu, struct iov_iter *from, size_t size)return size - len; } -/* -b - int8_t -w - int16_t -d - int32_t -q - int64_t -s - string -u - numeric uid -g - numeric gid -S - stat -Q - qid -D - data blob (int32_t size followed by void *, results are not freed) -T - array of strings (int16_t count, followed by strings) -R - array of qids (int16_t count, followed by qids) -A - stat for 9p2000.L (p9_stat_dotl) -? - if optional = 1, continue parsing -*/ +/* b - int8_t +* w - int16_t +* d - int32_t +* q - int64_t +* s - string +* u - numeric uid +* g - numeric gid +* S - stat +* Q - qid +* D - data blob (int32_t size followed by void *, results are not freed) +* T - array of strings (int16_t count, followed by strings) +* R - array of qids (int16_t count, followed by qids) +* A - stat for 9p2000.L (p9_stat_dotl) +* ? - if optional = 1, continue parsing +*/ static int p9pdu_vreadf (struct p9_fcall *pdu,int proto_version,const char *fmt, -va_list ap) +va_list ap) {const char *ptr;int errcode =0 ;
net/9p/protocol.h +1 -1
@@ -11,7 +11,7 @@*/ int p9pdu_vwritef (struct p9_fcall *pdu,int proto_version,const char *fmt, -va_list ap); +va_list ap);int p9pdu_readf (struct p9_fcall *pdu,int proto_version,const char *fmt, ...);int p9pdu_prepare (struct p9_fcall *pdu,int16_t tag,int8_t type);int p9pdu_finalize (struct p9_client *clnt,struct p9_fcall *pdu);
net/9p/trans_common.h +1 -1
@@ -12,4 +12,4 @@* */ -void p9_release_pages (struct page **,int ); +void p9_release_pages (struct page **pages,int nr_pages);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 605/779 9p: Drop kref usage
In reply to Greg Kroah-HartmanFrom: Kent Overstreet <[email protected]>
[ Upstream commit 6cda12864cb0f99810a5809e11e3ee5b102c9a47 ]
An upcoming patch is going to require passing the client through p9_req_put() -> p9_req_free(), but that's awkward with the kref indirection - so this patch switches to using refcount_t directly.
--- include/net/9p/client.h | 6 +++--- net/9p/client.c | 19 ++++++++----------- 2 files changed, 11 insertions(+), 14 deletions(-)
include/net/9p/client.h +3 -3
@@ -78,7 +78,7 @@ enum p9_req_status_t {struct p9_req_t {int status;int t_err; -struct kref refcount; +refcount_t refcount;wait_queue_head_t wq;struct p9_fcall tc;struct p9_fcall rc;
@@ -229,12 +229,12 @@ struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag);static inline void p9_req_get (struct p9_req_t *r) { -kref_get (&r->refcount); +refcount_inc (&r->refcount); }static inline int p9_req_try_get (struct p9_req_t *r) { -return kref_get_unless_zero (&r->refcount); +return refcount_inc_not_zero (&r->refcount); }int p9_req_put (struct p9_req_t *r);
net/9p/client.c +8 -11
@@ -307,7 +307,7 @@ p9_tag_alloc(struct p9_client *c, int8_t type, unsigned int max_size)* callback), so p9_client_cb eats the second ref there * as the pointer is duplicated directly by virtqueue_add_sgs() */ -refcount_set (&req->refcount.refcount,2 ); +refcount_set (&req->refcount,2 );return req;
@@ -372,18 +372,15 @@ static int p9_tag_remove(struct p9_client *c, struct p9_req_t *r)return p9_req_put (r); } -static void p9_req_free (struct kref *ref) -{ - struct p9_req_t *r = container_of(ref, struct p9_req_t, refcount); - -p9_fcall_fini (&r->tc); -p9_fcall_fini (&r->rc); -kmem_cache_free (p9_req_cache, r); -} -int p9_req_put (struct p9_req_t *r) { -return kref_put (&r->refcount, p9_req_free); +if (refcount_dec_and_test (&r->refcount)) { +p9_fcall_fini (&r->tc); +p9_fcall_fini (&r->rc); +kmem_cache_free (p9_req_cache, r); +return 1 ; + } +return 0 ; }EXPORT_SYMBOL (p9_req_put);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 606/779 9p: Add client parameter to p9_req_put()
In reply to Greg Kroah-HartmanFrom: Kent Overstreet <[email protected]>
[ Upstream commit 8b11ff098af42b1fa57fc817daadd53c8b244a0c ]
This is to aid in adding mempools, in the next patch.
--- include/net/9p/client.h | 2 +- net/9p/client.c | 12 ++++++------ net/9p/trans_fd.c | 12 ++++++------ net/9p/trans_rdma.c | 2 +- net/9p/trans_virtio.c | 4 ++-- net/9p/trans_xen.c | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-)
include/net/9p/client.h +1 -1
@@ -237,7 +237,7 @@ static inline int p9_req_try_get(struct p9_req_t *r)return refcount_inc_not_zero (&r->refcount); } -int p9_req_put (struct p9_req_t *r); +int p9_req_put (struct p9_client *c,struct p9_req_t *r);void p9_client_cb (struct p9_client *c,struct p9_req_t *req,int status);
net/9p/client.c +6 -6
@@ -343,7 +343,7 @@ struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)if (!p9_req_try_get (req)) goto again;if (req->tc.tag != tag) { -p9_req_put (req); +p9_req_put (c, req); goto again; } }
@@ -369,10 +369,10 @@ static int p9_tag_remove(struct p9_client *c, struct p9_req_t *r)spin_lock_irqsave (&c->lock, flags);idr_remove (&c->reqs, tag);spin_unlock_irqrestore (&c->lock, flags); -return p9_req_put (r); +return p9_req_put (c, r); } -int p9_req_put (struct p9_req_t *r) +int p9_req_put (struct p9_client *c,struct p9_req_t *r) {if (refcount_dec_and_test (&r->refcount)) {p9_fcall_fini (&r->tc);
@@ -425,7 +425,7 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status)wake_up (&req->wq);p9_debug (P9_DEBUG_MUX ,"wakeup: %d\n" , req->tc.tag); -p9_req_put (req); +p9_req_put (c, req); }EXPORT_SYMBOL (p9_client_cb);
@@ -708,7 +708,7 @@ static struct p9_req_t *p9_client_prepare_req(struct p9_client *c, reterr:p9_tag_remove (c, req);/* We have to put also the 2nd reference as it won't be used */ -p9_req_put (req); +p9_req_put (c, req);return ERR_PTR (err); }
@@ -745,7 +745,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) err = c->trans_mod->request (c, req);if (err <0 ) {/* write won't happen */ -p9_req_put (req); +p9_req_put (c, req);if (err != -ERESTARTSYS && err != -EFAULT ) c->status = Disconnected; goto recalc_sigpending;
net/9p/trans_fd.c +6 -6
@@ -380,7 +380,7 @@ static void p9_read_work(struct work_struct *work) m->rc.sdata =NULL ; m->rc.offset =0 ; m->rc.capacity =0 ; -p9_req_put (m->rreq); +p9_req_put (m->client, m->rreq); m->rreq =NULL ; }
@@ -494,7 +494,7 @@ static void p9_write_work(struct work_struct *work) m->wpos += err;if (m->wpos == m->wsize) { m->wpos = m->wsize =0 ; -p9_req_put (m->wreq); +p9_req_put (m->client, m->wreq); m->wreq =NULL ; }
@@ -697,7 +697,7 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req)if (req->status ==REQ_STATUS_UNSENT ) {list_del (&req->req_list); req->status =REQ_STATUS_FLSHD ; -p9_req_put (req); +p9_req_put (client, req); ret =0 ; }spin_unlock (&client->lock);
@@ -724,7 +724,7 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req)list_del (&req->req_list); req->status =REQ_STATUS_FLSHD ;spin_unlock (&client->lock); -p9_req_put (req); +p9_req_put (client, req);return 0 ; }
@@ -885,12 +885,12 @@ static void p9_conn_destroy(struct p9_conn *m)p9_mux_poll_stop (m);cancel_work_sync (&m->rq);if (m->rreq) { -p9_req_put (m->rreq); +p9_req_put (m->client, m->rreq); m->rreq =NULL ; }cancel_work_sync (&m->wq);if (m->wreq) { -p9_req_put (m->wreq); +p9_req_put (m->client, m->wreq); m->wreq =NULL ; }
net/9p/trans_rdma.c +1 -1
@@ -352,7 +352,7 @@ send_done(struct ib_cq *cq, struct ib_wc *wc) c->busa, c->req->tc.size, DMA_TO_DEVICE);up (&rdma->sq_sem); -p9_req_put (c->req); +p9_req_put (client, c->req);kfree (c); }
net/9p/trans_virtio.c +2 -2
@@ -199,7 +199,7 @@ static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req)/* Reply won't come, so drop req ref */ static int p9_virtio_cancelled (struct p9_client *client,struct p9_req_t *req) { -p9_req_put (req); +p9_req_put (client, req);return 0 ; }
@@ -523,7 +523,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,kvfree (out_pages);if (!kicked) {/* reply won't come */ -p9_req_put (req); +p9_req_put (client, req); }return err; }
net/9p/trans_xen.c +1 -1
@@ -186,7 +186,7 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req) ring->intf->out_prod = prod;spin_unlock_irqrestore (&ring->lock, flags);notify_remote_via_irq (ring->irq); -p9_req_put (p9_req); +p9_req_put (client, p9_req);return 0 ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 607/779 net: 9p: fix refcount leak in p9_read_work() error handling
In reply to Greg Kroah-HartmanFrom: Hangyu Hua <[email protected]>
[ Upstream commit 4ac7573e1f9333073fa8d303acc941c9b7ab7f61 ]
p9_req_put need to be called when m->rreq->rc.sdata is NULL to avoid temporary refcount leak.
--- net/9p/trans_fd.c | 1 + 1 file changed, 1 insertion(+)
net/9p/trans_fd.c +1 -0
@@ -345,6 +345,7 @@ static void p9_read_work(struct work_struct *work)p9_debug (P9_DEBUG_ERROR ,"No recv fcall for tag %d (req %p), disconnecting!\n" , m->rc.tag, m->rreq); +p9_req_put (m->client, m->rreq); m->rreq =NULL ; err = -EIO ; goto error;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 608/779 MIPS: Fixed __debug_virt_addr_valid()
In reply to Greg Kroah-HartmanFrom: Florian Fainelli <[email protected]>
[ Upstream commit 8a2b456665d1e797123669581524cbb095fb003b ]
It is permissible for kernel code to call virt_to_phys() against virtual addresses that are in KSEG0 or KSEG1 and we need to be dealing with both types. Rewrite the test condition to ensure that the kernel virtual addresses are above PAGE_OFFSET which they must be, and below KSEG2 where the non-linear mapping starts.
For EVA, there is not much that we can do given the linear address range that is offered, so just return any virtual address as being valid.
Finally, when HIGHMEM is not enabled, all virtual addresses are assumed to be valid as well.
--- arch/mips/mm/physaddr.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-)
arch/mips/mm/physaddr.c +4 -10
@@ -5,6 +5,7 @@#include <linux/mmdebug.h> #include <linux/mm.h> +#include <asm/addrspace.h> #include <asm/sections.h> #include <asm/io.h> #include <asm/page.h>
@@ -12,15 +13,6 @@static inline bool __debug_virt_addr_valid (unsigned long x) { -/* high_memory does not get immediately defined, and there -* are early callers of __pa() against PAGE_OFFSET -*/ -if (!high_memory && x >=PAGE_OFFSET ) -return true; - -if (high_memory && x >=PAGE_OFFSET && x < (unsigned long )high_memory) -return true; -/* * MAX_DMA_ADDRESS is a virtual address that may not correspond to an * actual physical address. Enough code relies on
@@ -30,7 +22,9 @@ static inline bool __debug_virt_addr_valid(unsigned long x)if (x ==MAX_DMA_ADDRESS )return true; -return false; +return x >=PAGE_OFFSET && (KSEGX (x) <KSEG2 || +IS_ENABLED (CONFIG_EVA ) || + !IS_ENABLED (CONFIG_HIGHMEM )); }phys_addr_t __virt_to_phys (volatile const void *x)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 609/779 rpmsg: qcom_smd: Fix refcount leak in qcom_smd_parse_edge
In reply to Greg Kroah-HartmanFrom: Miaoqian Lin <[email protected]>
[ Upstream commit 65382585f067d4256ba087934f30f85c9b6984de ]
of_parse_phandle() returns a node pointer with refcount incremented, we should use of_node_put() on it when done.
--- drivers/rpmsg/qcom_smd.c | 1 + 1 file changed, 1 insertion(+)
drivers/rpmsg/qcom_smd.c +1 -0
@@ -1380,6 +1380,7 @@ static int qcom_smd_parse_edge(struct device *dev, } edge->ipc_regmap =syscon_node_to_regmap (syscon_np); +of_node_put (syscon_np);if (IS_ERR (edge->ipc_regmap)) { ret =PTR_ERR (edge->ipc_regmap); goto put_node;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 610/779 kfifo: fix kfifo_to_user() return type
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
[ Upstream commit 045ed31e23aea840648c290dbde04797064960db ]
The kfifo_to_user() macro is supposed to return zero for success or negative error codes. Unfortunately, there is a signedness bug so it returns unsigned int. This only affects callers which try to save the result in ssize_t and as far as I can see the only place which does that is line6_hwdep_read().
TL;DR: s/_uint/_int/.
--- include/linux/kfifo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/kfifo.h +1 -1
@@ -688,7 +688,7 @@ __kfifo_uint_must_check_helper( \* writer, you don't need extra locking to use these macro. */ #define kfifo_to_user (fifo, to, len, copied) \ -__kfifo_uint_must_check_helper( \ +__kfifo_int_must_check_helper( \ ({ \ typeof((fifo) + 1) __tmp = (fifo); \ void __user *__to = (to); \
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 611/779 lib/smp_processor_id: fix imbalanced instrumentation_end() call
In reply to Greg Kroah-HartmanFrom: Tetsuo Handa <[email protected]>
[ Upstream commit bd27acaac24e4b252ee28dddcabaee80456d0faf ]
Currently instrumentation_end() won't be called if printk_ratelimit() returned false.
--- lib/smp_processor_id.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
lib/smp_processor_id.c +1 -1
@@ -47,9 +47,9 @@ unsigned int check_preemption_disabled(const char *what1, const char *what2)printk ("caller is %pS\n" ,__builtin_return_address (0 ));dump_stack (); -instrumentation_end (); out_enable: +instrumentation_end ();preempt_enable_no_resched_notrace (); out:return this_cpu;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 612/779 proc: fix a dentry lock race between release_task and lookup
In reply to Greg Kroah-HartmanFrom: Zhihao Cheng <[email protected]>
[ Upstream commit d919a1e79bac890421537cf02ae773007bf55e6b ]
Commit 7bc3e6e55acf06 ("proc: Use a list of inodes to flush from proc") moved proc_flush_task() behind __exit_signal(). Then, process systemd can take long period high cpu usage during releasing task in following concurrent processes:
systemd pskernel_waitid stat(/proc/tgid)
do_wait filename_lookup
wait_consider_task lookup_fast
release_task
__exit_signal
__unhash_process
detach_pid
__change_pid // remove task->pid_links
d_revalidate -> pid_revalidate // 0
d_invalidate(/proc/tgid)
shrink_dcache_parent(/proc/tgid)
d_walk(/proc/tgid)
spin_lock_nested(/proc/tgid/fd)
// iterating opened fd
proc_flush_pid |
d_invalidate (/proc/tgid/fd) |
shrink_dcache_parent(/proc/tgid/fd) |
shrink_dentry_list(subdirs) ↓
shrink_lock_dentry(/proc/tgid/fd) --> race on dentry lockFunction d_invalidate() will remove dentry from hash firstly, but why does proc_flush_pid() process dentry '/proc/tgid/fd' before dentry '/proc/tgid'? That's because proc_pid_make_inode() adds proc inode in reverse order by invoking hlist_add_head_rcu(). But proc should not add any inodes under '/proc/tgid' except '/proc/tgid/task/pid', fix it by adding inode into 'pid->inodes' only if the inode is /proc/tgid or /proc/tgid/task/pid.
Performance regression:
Create 200 tasks, each task open one file for 50,000 times. Kill all tasks when opened files exceed 10,000,000 (cat /proc/sys/fs/file-nr).
Before fix:
$ time killall -wq aa real 4m40.946s # During this period, we can see 'ps' and 'systemd' taking high cpu usage.
After fix:
$ time killall -wq aa real 1m20.732s # During this period, we can see 'systemd' taking high cpu usage.
--- fs/proc/base.c | 46 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-)
fs/proc/base.c +38 -8
@@ -1886,7 +1886,7 @@ void proc_pid_evict_inode(struct proc_inode *ei)put_pid (pid); } -struct inode *proc_pid_make_inode (struct super_block * sb, +struct inode *proc_pid_make_inode (struct super_block *sb,struct task_struct *task,umode_t mode) {struct inode * inode;
@@ -1915,11 +1915,6 @@ struct inode *proc_pid_make_inode(struct super_block * sb,/* Let the pid remember us for quick removal */ ei->pid = pid; -if (S_ISDIR (mode)) { -spin_lock (&pid->lock); -hlist_add_head_rcu (&ei->sibling_inodes, &pid->inodes); -spin_unlock (&pid->lock); - }task_dump_owner (task,0 , &inode->i_uid, &inode->i_gid);security_task_to_inode (task, inode);
@@ -1932,6 +1927,39 @@ struct inode *proc_pid_make_inode(struct super_block * sb,return NULL ; } +/* +* Generating an inode and adding it into @pid->inodes, so that task will +* invalidate inode's dentry before being released. +* +* This helper is used for creating dir-type entries under '/proc' and +* '/proc/<tgid>/task'. Other entries(eg. fd, stat) under '/proc/<tgid>' +* can be released by invalidating '/proc/<tgid>' dentry. +* In theory, dentries under '/proc/<tgid>/task' can also be released by +* invalidating '/proc/<tgid>' dentry, we reserve it to handle single +* thread exiting situation: Any one of threads should invalidate its +* '/proc/<tgid>/task/<pid>' dentry before released. +*/ +static struct inode *proc_pid_make_base_inode (struct super_block *sb, +struct task_struct *task,umode_t mode) +{ +struct inode *inode; +struct proc_inode *ei; +struct pid *pid; + + inode =proc_pid_make_inode (sb, task, mode); +if (!inode) +return NULL ; + +/* Let proc_flush_pid find this directory inode */ + ei =PROC_I (inode); + pid = ei->pid; +spin_lock (&pid->lock); +hlist_add_head_rcu (&ei->sibling_inodes, &pid->inodes); +spin_unlock (&pid->lock); + +return inode; +} +int pid_getattr (struct user_namespace *mnt_userns,const struct path *path,struct kstat *stat,u32 request_mask,unsigned int query_flags) {
@@ -3349,7 +3377,8 @@ static struct dentry *proc_pid_instantiate(struct dentry * dentry, {struct inode *inode; - inode =proc_pid_make_inode (dentry->d_sb, task,S_IFDIR |S_IRUGO |S_IXUGO ); + inode =proc_pid_make_base_inode (dentry->d_sb, task, +S_IFDIR |S_IRUGO |S_IXUGO );if (!inode)return ERR_PTR (-ENOENT );
@@ -3648,7 +3677,8 @@ static struct dentry *proc_task_instantiate(struct dentry *dentry, struct task_struct *task, const void *ptr) { struct inode *inode; - inode =proc_pid_make_inode (dentry->d_sb, task,S_IFDIR |S_IRUGO |S_IXUGO ); + inode =proc_pid_make_base_inode (dentry->d_sb, task, +S_IFDIR |S_IRUGO |S_IXUGO );if (!inode)return ERR_PTR (-ENOENT );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 613/779 remoteproc: qcom: pas: Check if coredump is enabled
In reply to Greg Kroah-HartmanFrom: Siddharth Gupta <[email protected]>
[ Upstream commit 7b6ece968fca4ec9e42d34caff7e06dc84c45717 ]
Client drivers need to check if coredump is enabled for the rproc before continuing with coredump generation. This change adds a check in the PAS driver.
--- drivers/remoteproc/qcom_q6v5_pas.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/remoteproc/qcom_q6v5_pas.c +3 -0
@@ -87,6 +87,9 @@ static void adsp_minidump(struct rproc *rproc) {struct qcom_adsp *adsp = rproc->priv; +if (rproc->dump_conf ==RPROC_COREDUMP_DISABLED ) +return ; +qcom_minidump (rproc, adsp->minidump_id); }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 614/779 remoteproc: sysmon: Wait for SSCTL service to come up
In reply to Greg Kroah-HartmanFrom: Sibi Sankar <[email protected]>
[ Upstream commit 47c04e00eff86a81cd357c3feed04c86089bcb85 ]
The SSCTL service comes up after a finite time when the remote Q6 comes out of reset. Any graceful shutdowns requested during this period will be a NOP and abrupt tearing down of the glink channel might lead to pending transactions on the remote Q6 side and will ultimately lead to a fatal error. Fix this by waiting for the SSCTL service when a graceful shutdown is requested.
--- drivers/remoteproc/qcom_sysmon.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/remoteproc/qcom_sysmon.c +10 -0
@@ -41,6 +41,7 @@ struct qcom_sysmon {struct completion comp;struct completion ind_comp;struct completion shutdown_comp; +struct completion ssctl_comp;struct mutex lock;bool ssr_ack;
@@ -445,6 +446,8 @@ static int ssctl_new_server(struct qmi_handle *qmi, struct qmi_service *svc) svc->priv = sysmon; +complete (&sysmon->ssctl_comp); +return 0 ; }
@@ -501,6 +504,7 @@ static int sysmon_start(struct rproc_subdev *subdev) .ssr_event = SSCTL_SSR_EVENT_AFTER_POWERUP }; +reinit_completion (&sysmon->ssctl_comp);mutex_lock (&sysmon->state_lock); sysmon->state =SSCTL_SSR_EVENT_AFTER_POWERUP ;blocking_notifier_call_chain (&sysmon_notifiers,0 , (void *)&event);
@@ -545,6 +549,11 @@ static void sysmon_stop(struct rproc_subdev *subdev, bool crashed)if (crashed)return ; +if (sysmon->ssctl_instance) { +if (!wait_for_completion_timeout (&sysmon->ssctl_comp,HZ /2 )) +dev_err (sysmon->dev,"timeout waiting for ssctl service\n" ); + } +if (sysmon->ssctl_version) sysmon->shutdown_acked =ssctl_request_shutdown (sysmon);else if (sysmon->ept)
@@ -631,6 +640,7 @@ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,init_completion (&sysmon->comp);init_completion (&sysmon->ind_comp);init_completion (&sysmon->shutdown_comp); +init_completion (&sysmon->ssctl_comp);mutex_init (&sysmon->lock);mutex_init (&sysmon->state_lock);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 615/779 mfd: t7l66xb: Drop platform disable callback
In reply to Greg Kroah-HartmanFrom: Uwe Kleine-König <[email protected]>
[ Upstream commit 128ac294e1b437cb8a7f2ff8ede1cde9082bddbe ]
None of the in-tree instantiations of struct t7l66xb_platform_data provides a disable callback. So better don't dereference this function pointer unconditionally. As there is no user, drop it completely instead of calling it conditional.
This is a preparation for making platform remove callbacks return void.
--- drivers/mfd/t7l66xb.c | 6 +----- include/linux/mfd/t7l66xb.h | 1 - 2 files changed, 1 insertion(+), 6 deletions(-)
drivers/mfd/t7l66xb.c +1 -5
@@ -397,11 +397,8 @@ static int t7l66xb_probe(struct platform_device *dev)static int t7l66xb_remove (struct platform_device *dev) { -struct t7l66xb_platform_data *pdata =dev_get_platdata (&dev->dev);struct t7l66xb *t7l66xb =platform_get_drvdata (dev); -int ret; - ret = pdata->disable (dev);clk_disable_unprepare (t7l66xb->clk48m);clk_put (t7l66xb->clk48m);clk_disable_unprepare (t7l66xb->clk32k);
@@ -412,8 +409,7 @@ static int t7l66xb_remove(struct platform_device *dev)mfd_remove_devices (&dev->dev);kfree (t7l66xb); -return ret; - +return 0 ; }static struct platform_driver t7l66xb_platform_driver = {
include/linux/mfd/t7l66xb.h +0 -1
@@ -12,7 +12,6 @@struct t7l66xb_platform_data {int (*enable)(struct platform_device *dev); -int (*disable)(struct platform_device *dev);int (*suspend)(struct platform_device *dev);int (*resume)(struct platform_device *dev);
Signature · 1 line
2.35.1
Re: [PATCH 5.15 615/779] mfd: t7l66xb: Drop platform disable callback
Hi!
Quoted 10 lines · Greg Kroah-Hartman
From: Uwe Kleine-König <[email protected]>
[ Upstream commit
128ac294e1b437cb8a7f2ff8ede1cde9082bddbe]None of the in-tree instantiations of struct
t7l66xb_platform_dataprovides a disable callback. So better don't dereference this function pointer unconditionally. As there is no user, drop it completely instead of calling it conditional.This is a preparation for making platform remove callbacks return void.
I'm not sure if we need this in stable; this does not really fix anything, it is just a cleanup.
Best regards,
Pavel
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Greg Kroah-Hartman
maintainerPATCH 616/779 mfd: max77620: Fix refcount leak in max77620_initialise_fps
In reply to Greg Kroah-HartmanFrom: Miaoqian Lin <[email protected]>
[ Upstream commit 1520669c8255bd637c6b248b2be910e2688d38dd ]
of_get_child_by_name() returns a node pointer with refcount incremented, we should use of_node_put() on it when not need anymore. Add missing of_node_put() to avoid refcount leak.
--- drivers/mfd/max77620.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/mfd/max77620.c +2 -0
@@ -419,9 +419,11 @@ static int max77620_initialise_fps(struct max77620_chip *chip) ret =max77620_config_fps (chip, fps_child);if (ret <0 ) {of_node_put (fps_child); +of_node_put (fps_np);return ret; } } +of_node_put (fps_np); config = chip->enable_global_lpm ?MAX77620_ONOFFCNFG2_SLP_LPM_MSK :0 ; ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 617/779 iommu/arm-smmu: qcom_iommu: Add of_node_put() when breaking out of loop
In reply to Greg Kroah-HartmanFrom: Liang He <[email protected]>
[ Upstream commit a91eb6803c1c715738682fece095145cbd68fe0b ]
In qcom_iommu_has_secure_context(), we should call of_node_put() for the reference 'child' when breaking out of for_each_child_of_node() which will automatically increase and decrease the refcount.
--- drivers/iommu/arm/arm-smmu/qcom_iommu.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/iommu/arm/arm-smmu/qcom_iommu.c +5 -2
@@ -748,9 +748,12 @@ static bool qcom_iommu_has_secure_context(struct qcom_iommu_dev *qcom_iommu) {struct device_node *child; -for_each_child_of_node (qcom_iommu->dev->of_node, child) -if (of_device_is_compatible (child,"qcom,msm-iommu-v1-sec" )) +for_each_child_of_node (qcom_iommu->dev->of_node, child) { +if (of_device_is_compatible (child,"qcom,msm-iommu-v1-sec" )) { +of_node_put (child);return true; + } + }return false; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 618/779 perf tools: Fix dso_id inode generation comparison
In reply to Greg Kroah-HartmanFrom: Adrian Hunter <[email protected]>
[ Upstream commit 68566a7cf56bf3148797c218ed45a9de078ef47c ]
Synthesized MMAP events have zero ino_generation, so do not compare them to DSOs with a real ino_generation otherwise we end up with a DSO without a build id.
--- tools/perf/util/dsos.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
tools/perf/util/dsos.c +13 -2
@@ -20,8 +20,19 @@ static int __dso_id__cmp(struct dso_id *a, struct dso_id *b)if (a->ino > b->ino)return -1 ;if (a->ino < b->ino)return 1 ; -if (a->ino_generation > b->ino_generation)return -1 ; -if (a->ino_generation < b->ino_generation)return 1 ; +/* +* Synthesized MMAP events have zero ino_generation, avoid comparing +* them with MMAP events with actual ino_generation. +* +* I found it harmful because the mismatch resulted in a new +* dso that did not have a build ID whereas the original dso did have a +* build ID. The build ID was essential because the object was not found +* otherwise. - Adrian +*/ +if (a->ino_generation && b->ino_generation) { +if (a->ino_generation > b->ino_generation)return -1 ; +if (a->ino_generation < b->ino_generation)return 1 ; + }return 0 ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 619/779 s390/dump: fix old lowcore virtual vs physical address confusion
In reply to Greg Kroah-HartmanFrom: Alexander Gordeev <[email protected]>
[ Upstream commit dc306186a130c6d9feb0aabc1c71b8ed1674a3bf ]
Virtual addresses of vmcore_info and os_info members are wrongly passed to copy_oldmem_kernel(), while the function expects physical address of the source. Instead, __pa() macro should have been applied.
Yet, use of __pa() macro could be somehow confusing, since copy_oldmem_kernel() may treat the source as an offset, not as a direct physical address (that depens from the oldmem availability and location).
Fix the virtual vs physical address confusion and make the way the old lowcore is read consistent across all sources.
--- arch/s390/kernel/asm-offsets.c | 2 ++ arch/s390/kernel/crash_dump.c | 2 +- arch/s390/kernel/os_info.c | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-)
arch/s390/kernel/asm-offsets.c +2 -0
@@ -128,6 +128,8 @@ int main(void)OFFSET (__LC_BR_R1, lowcore, br_r1_trampoline);/* software defined ABI-relevant lowcore locations 0xe00 - 0xe20 */ OFFSET (__LC_DUMP_REIPL, lowcore, ipib); +OFFSET (__LC_VMCORE_INFO, lowcore, vmcore_info); +OFFSET (__LC_OS_INFO, lowcore, os_info);/* hardware defined lowcore locations 0x1000 - 0x18ff */ OFFSET (__LC_MCESAD, lowcore, mcesad);OFFSET (__LC_EXT_PARAMS2, lowcore, ext_params2);
arch/s390/kernel/crash_dump.c +1 -1
@@ -432,7 +432,7 @@ static void *get_vmcoreinfo_old(unsigned long *size)Elf64_Nhdr note;void *addr; -if (copy_oldmem_kernel (&addr, &S390_lowcore.vmcore_info,sizeof (addr))) +if (copy_oldmem_kernel (&addr, (void *)__LC_VMCORE_INFO,sizeof (addr)))return NULL ;memset (nt_name,0 ,sizeof (nt_name));if (copy_oldmem_kernel (¬e, addr,sizeof (note)))
arch/s390/kernel/os_info.c +2 -1
@@ -15,6 +15,7 @@#include <asm/checksum.h> #include <asm/lowcore.h> #include <asm/os_info.h> +#include <asm/asm-offsets.h> /* * OS info structure has to be page aligned
@@ -123,7 +124,7 @@ static void os_info_old_init(void)return ;if (!oldmem_data.start) goto fail; -if (copy_oldmem_kernel (&addr, &S390_lowcore.os_info,sizeof (addr))) +if (copy_oldmem_kernel (&addr, (void *)__LC_OS_INFO,sizeof (addr))) goto fail;if (addr ==0 || addr %PAGE_SIZE ) goto fail;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 620/779 s390/maccess: fix semantics of memcpy_real() and its callers
In reply to Greg Kroah-HartmanFrom: Alexander Gordeev <[email protected]>
[ Upstream commit 303fd988ed644c7daa260410f3ac99266573557d ]
There is a confusion with regard to the source address of memcpy_real() and calling functions. While the declared type for a source assumes a virtual address, in fact it always called with physical address of the source.
This confusion led to bugs in copy_oldmem_kernel() and copy_oldmem_user() functions, where __pa() macro applied mistakenly to physical addresses. It does not lead to a real issue, since virtual and physical addresses are currently the same.
Fix both the bugs and memcpy_real() prototype by making type of source address consistent to the function name and the way it actually used.
--- arch/s390/include/asm/os_info.h | 2 +- arch/s390/include/asm/processor.h | 2 +- arch/s390/include/asm/uaccess.h | 2 +- arch/s390/kernel/crash_dump.c | 58 +++++++++++++++---------------- arch/s390/kernel/os_info.c | 7 ++-- arch/s390/kernel/smp.c | 2 +- arch/s390/mm/maccess.c | 4 +-- drivers/s390/char/zcore.c | 3 +- 8 files changed, 38 insertions(+), 42 deletions(-)
arch/s390/include/asm/os_info.h +1 -1
@@ -39,7 +39,7 @@ u32 os_info_csum(struct os_info *os_info);#ifdef CONFIG_CRASH_DUMP void *os_info_old_entry (int nr,unsigned long *size); -int copy_oldmem_kernel (void *dst,void *src,size_t count); +int copy_oldmem_kernel (void *dst,unsigned long src,size_t count);#else static inline void *os_info_old_entry (int nr,unsigned long *size) {
arch/s390/include/asm/processor.h +1 -1
@@ -318,7 +318,7 @@ extern void (*s390_base_pgm_handler_fn)(void);#define ARCH_LOW_ADDRESS_LIMIT 0x7fffffffUL -extern int memcpy_real (void *,void *,size_t ); +extern int memcpy_real (void *,unsigned long ,size_t );extern void memcpy_absolute (void *,void *,size_t );#define mem_assign_absolute (dest, val) do { \
arch/s390/include/asm/uaccess.h +1 -1
@@ -245,7 +245,7 @@ static inline unsigned long __must_check clear_user(void __user *to, unsigned loreturn __clear_user (to, n); } -int copy_to_user_real (void __user *dest,void *src,unsigned long count); +int copy_to_user_real (void __user *dest,unsigned long src,unsigned long count);void *s390_kernel_write (void *dst,const void *src,size_t size);#define HAVE_GET_KERNEL_NOFAULT
arch/s390/kernel/crash_dump.c +28 -30
116 lines not on this page · raw message
arch/s390/kernel/os_info.c +3 -4
@@ -91,7 +91,7 @@ static void os_info_old_alloc(int nr, int align) goto fail; } buf_align =PTR_ALIGN (buf, align); -if (copy_oldmem_kernel (buf_align, (void *) addr, size)) { +if (copy_oldmem_kernel (buf_align, addr, size)) { msg ="copy failed" ; goto fail_free; }
@@ -124,15 +124,14 @@ static void os_info_old_init(void)return ;if (!oldmem_data.start) goto fail; -if (copy_oldmem_kernel (&addr, (void *)__LC_OS_INFO,sizeof (addr))) +if (copy_oldmem_kernel (&addr, __LC_OS_INFO,sizeof (addr))) goto fail;if (addr ==0 || addr %PAGE_SIZE ) goto fail; os_info_old =kzalloc (sizeof (*os_info_old),GFP_KERNEL );if (!os_info_old) goto fail; -if (copy_oldmem_kernel (os_info_old, (void *) addr, -sizeof (*os_info_old))) +if (copy_oldmem_kernel (os_info_old, addr,sizeof (*os_info_old))) goto fail_free;if (os_info_old->magic !=OS_INFO_MAGIC ) goto fail_free;
arch/s390/kernel/smp.c +1 -1
@@ -675,7 +675,7 @@ static __init void smp_save_cpu_regs(struct save_area *sa, u16 addr,void *regs = (void *) page;if (is_boot_cpu) -copy_oldmem_kernel (regs, (void *) __LC_FPREGS_SAVE_AREA,512 ); +copy_oldmem_kernel (regs, __LC_FPREGS_SAVE_AREA,512 );else __pcpu_sigp_relax (addr,SIGP_STORE_STATUS_AT_ADDRESS , page);save_area_add_regs (sa, regs);
arch/s390/mm/maccess.c +2 -2
@@ -123,7 +123,7 @@ static unsigned long __no_sanitize_address _memcpy_real(unsigned long dest,/* * Copy memory in real mode (kernel to kernel) */ -int memcpy_real (void *dest,void *src,size_t count) +int memcpy_real (void *dest,unsigned long src,size_t count) {unsigned long _dest = (unsigned long )dest;unsigned long _src = (unsigned long )src;
@@ -175,7 +175,7 @@ void memcpy_absolute(void *dest, void *src, size_t count)/* * Copy memory from kernel (real) to user (virtual) */ -int copy_to_user_real (void __user *dest,void *src,unsigned long count) +int copy_to_user_real (void __user *dest,unsigned long src,unsigned long count) {int offs =0 , size, rc;char *buf;
drivers/s390/char/zcore.c +1 -2
@@ -229,8 +229,7 @@ static int __init zcore_reipl_init(void) rc =memcpy_hsa_kernel (zcore_ipl_block, ipib_info.ipib,PAGE_SIZE ); else - rc =memcpy_real (zcore_ipl_block, (void *) ipib_info.ipib, -PAGE_SIZE ); + rc =memcpy_real (zcore_ipl_block, ipib_info.ipib,PAGE_SIZE );if (rc || (__force u32 )csum_partial (zcore_ipl_block, zcore_ipl_block->hdr.len,0 ) != ipib_info.checksum) {TRACE ("Checksum does not match\n" );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 621/779 s390/crash: fix incorrect number of bytes to copy to user space
In reply to Greg Kroah-HartmanFrom: Alexander Gordeev <[email protected]>
[ Upstream commit f6749da17a34eb08c9665f072ce7c812ff68aad2 ]
The number of bytes in a chunk is correctly calculated, but instead the total number of bytes is passed to copy_to_user_real() function.
--- arch/s390/kernel/crash_dump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/s390/kernel/crash_dump.c +1 -1
@@ -198,7 +198,7 @@ static int copy_oldmem_user(void __user *dst, unsigned long src, size_t count) }else { len = count; } - rc =copy_to_user_real (dst, src, count); + rc =copy_to_user_real (dst, src, len);if (rc)return rc; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 622/779 s390/zcore: fix race when reading from hardware system area
In reply to Greg Kroah-HartmanFrom: Alexander Gordeev <[email protected]>
[ Upstream commit 9ffed254d938c9e99eb7761c7f739294c84e0367 ]
Memory buffer used for reading out data from hardware system area is not protected against concurrent access.
--- drivers/s390/char/zcore.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/s390/char/zcore.c +10 -1
@@ -50,6 +50,7 @@ static struct dentry *zcore_reipl_file;static struct dentry *zcore_hsa_file;static struct ipl_parameter_block *zcore_ipl_block; +static DEFINE_MUTEX (hsa_buf_mutex);static char hsa_buf[PAGE_SIZE ]__aligned(PAGE_SIZE) ;/*
@@ -66,19 +67,24 @@ int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count)if (!hsa_available)return -ENODATA ; +mutex_lock (&hsa_buf_mutex);while (count) {if (sclp_sdias_copy (hsa_buf, src /PAGE_SIZE +2 ,1 )) {TRACE ("sclp_sdias_copy() failed\n" ); +mutex_unlock (&hsa_buf_mutex);return -EIO ; } offset = src %PAGE_SIZE ; bytes =min (PAGE_SIZE - offset, count); -if (copy_to_user (dest, hsa_buf + offset, bytes)) +if (copy_to_user (dest, hsa_buf + offset, bytes)) { +mutex_unlock (&hsa_buf_mutex);return -EFAULT ; + } src += bytes; dest += bytes; count -= bytes; } +mutex_unlock (&hsa_buf_mutex);return 0 ; }
@@ -96,9 +102,11 @@ int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count)if (!hsa_available)return -ENODATA ; +mutex_lock (&hsa_buf_mutex);while (count) {if (sclp_sdias_copy (hsa_buf, src /PAGE_SIZE +2 ,1 )) {TRACE ("sclp_sdias_copy() failed\n" ); +mutex_unlock (&hsa_buf_mutex);return -EIO ; } offset = src %PAGE_SIZE ;
@@ -108,6 +116,7 @@ int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count) dest += bytes; count -= bytes; } +mutex_unlock (&hsa_buf_mutex);return 0 ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 623/779 ASoC: fsl_asrc: force cast the asrc_format type
In reply to Greg Kroah-HartmanFrom: Shengjiu Wang <[email protected]>
[ Upstream commit c49932726de24405d45516b3f8ad2735714fdf05 ]
Fix sparse warning:sound/soc/fsl/fsl_asrc.c:1177:60: sparse: warning: incorrect type in argument 3 (different base types)sound/soc/fsl/fsl_asrc.c:1177:60: sparse: expected unsigned int [usertype] *out_valuesound/soc/fsl/fsl_asrc.c:1177:60: sparse: got restricted snd_pcm_format_t *sound/soc/fsl/fsl_asrc.c:1200:47: sparse: warning: restricted snd_pcm_format_t degrades to integer
--- sound/soc/fsl/fsl_asrc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
sound/soc/fsl/fsl_asrc.c +4 -2
@@ -1066,6 +1066,7 @@ static int fsl_asrc_probe(struct platform_device *pdev)struct resource *res;void __iomem *regs;int irq, ret, i; +u32 asrc_fmt =0 ;u32 map_idx;char tmp[16 ];u32 width;
@@ -1174,7 +1175,8 @@ static int fsl_asrc_probe(struct platform_device *pdev)return ret; } - ret =of_property_read_u32 (np,"fsl,asrc-format" , &asrc->asrc_format); + ret =of_property_read_u32 (np,"fsl,asrc-format" , &asrc_fmt); + asrc->asrc_format = (__force snd_pcm_format_t )asrc_fmt;if (ret) { ret =of_property_read_u32 (np,"fsl,asrc-width" , &width);if (ret) {
@@ -1197,7 +1199,7 @@ static int fsl_asrc_probe(struct platform_device *pdev) } } -if (!(FSL_ASRC_FORMATS & (1ULL << asrc->asrc_format))) { +if (!(FSL_ASRC_FORMATS &pcm_format_to_bits (asrc->asrc_format))) {dev_warn (&pdev->dev,"unsupported width, use default S24_LE\n" ); asrc->asrc_format =SNDRV_PCM_FORMAT_S24_LE ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 624/779 ASoC: fsl-asoc-card: force cast the asrc_format type
In reply to Greg Kroah-HartmanFrom: Shengjiu Wang <[email protected]>
[ Upstream commit 6c7b077dad62178c33f9a3ae17f90d6b0bf6e2e5 ]
Fix sparse warning:sound/soc/fsl/fsl-asoc-card.c:833:45: sparse: warning: incorrect type in argument 3 (different base types)sound/soc/fsl/fsl-asoc-card.c:833:45: sparse: expected unsigned int [usertype] *out_valuesound/soc/fsl/fsl-asoc-card.c:833:45: sparse: got restricted snd_pcm_format_t *
--- sound/soc/fsl/fsl-asoc-card.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
sound/soc/fsl/fsl-asoc-card.c +3 -2
@@ -540,6 +540,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)struct device *codec_dev =NULL ;const char *codec_dai_name;const char *codec_dev_name; +u32 asrc_fmt =0 ;u32 width;int ret;
@@ -817,8 +818,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) goto asrc_fail; } - ret =of_property_read_u32 (asrc_np,"fsl,asrc-format" , - &priv->asrc_format); + ret =of_property_read_u32 (asrc_np,"fsl,asrc-format" , &asrc_fmt); + priv->asrc_format = (__force snd_pcm_format_t )asrc_fmt;if (ret) {/* Fallback to old binding; translate to asrc_format */ ret = of_property_read_u32(asrc_np, "fsl,asrc-width",
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 625/779 ASoC: fsl_easrc: use snd_pcm_format_t type for sample_format
In reply to Greg Kroah-HartmanFrom: Shengjiu Wang <[email protected]>
[ Upstream commit de27216cf2d645c2fd14e513707bdcd54e5b1de4 ]
Fix sparse warning:sound/soc/fsl/fsl_easrc.c:562:33: sparse: warning: restricted snd_pcm_format_t degrades to integer sound/soc/fsl/fsl_easrc.c:563:34: sparse: warning: restricted snd_pcm_format_t degrades to integer sound/soc/fsl/fsl_easrc.c:565:38: sparse: warning: restricted snd_pcm_format_t degrades to integer sound/soc/fsl/fsl_easrc.c:566:39: sparse: warning: restricted snd_pcm_format_t degrades to integer sound/soc/fsl/fsl_easrc.c:608:33: sparse: warning: restricted snd_pcm_format_t degrades to integer sound/soc/fsl/fsl_easrc.c:609:34: sparse: warning: restricted snd_pcm_format_t degrades to integer sound/soc/fsl/fsl_easrc.c:615:40: sparse: warning: restricted snd_pcm_format_t degrades to integer sound/soc/fsl/fsl_easrc.c:616:41: sparse: warning: restricted snd_pcm_format_t degrades to integer
sound/soc/fsl/fsl_easrc.c:1465:51: sparse: warning: incorrect type in assignment (different base types)sound/soc/fsl/fsl_easrc.c:1465:51: sparse: expected unsigned int sample_formatsound/soc/fsl/fsl_easrc.c:1465:51: sparse: got restricted snd_pcm_format_t [usertype] formatsound/soc/fsl/fsl_easrc.c:1467:52: sparse: warning: incorrect type in assignment (different base types)sound/soc/fsl/fsl_easrc.c:1467:52: sparse: expected unsigned int sample_formatsound/soc/fsl/fsl_easrc.c:1467:52: sparse: got restricted snd_pcm_format_t [usertype] asrc_formatsound/soc/fsl/fsl_easrc.c:1470:52: sparse: warning: incorrect type in assignment (different base types)sound/soc/fsl/fsl_easrc.c:1470:52: sparse: expected unsigned int sample_formatsound/soc/fsl/fsl_easrc.c:1470:52: sparse: got restricted snd_pcm_format_t [usertype] formatsound/soc/fsl/fsl_easrc.c:1472:51: sparse: warning: incorrect type in assignment (different base types)sound/soc/fsl/fsl_easrc.c:1472:51: sparse: expected unsigned int sample_formatsound/soc/fsl/fsl_easrc.c:1472:51: sparse: got restricted snd_pcm_format_t [usertype] asrc_formatsound/soc/fsl/fsl_easrc.c:1484:41: sparse: warning: incorrect type in argument 2 (different base types)sound/soc/fsl/fsl_easrc.c:1484:41: sparse: expected restricted snd_pcm_format_t [usertype] *in_raw_formatsound/soc/fsl/fsl_easrc.c:1484:41: sparse: got unsigned int *sound/soc/fsl/fsl_easrc.c:1485:41: sparse: warning: incorrect type in argument 3 (different base types)sound/soc/fsl/fsl_easrc.c:1485:41: sparse: expected restricted snd_pcm_format_t [usertype] *out_raw_formatsound/soc/fsl/fsl_easrc.c:1485:41: sparse: got unsigned int *sound/soc/fsl/fsl_easrc.c:1937:60: sparse: warning: incorrect type in argument 3 (different base types)sound/soc/fsl/fsl_easrc.c:1937:60: sparse: expected unsigned int [usertype] *out_valuesound/soc/fsl/fsl_easrc.c:1937:60: sparse: got restricted snd_pcm_format_t *sound/soc/fsl/fsl_easrc.c:1943:49: sparse: warning: restricted snd_pcm_format_t degrades to integer
--- sound/soc/fsl/fsl_easrc.c | 9 ++++++--- sound/soc/fsl/fsl_easrc.h | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-)
sound/soc/fsl/fsl_easrc.c +6 -3
@@ -476,7 +476,8 @@ static int fsl_easrc_prefilter_config(struct fsl_asrc *easrc,struct fsl_asrc_pair *ctx;struct device *dev;u32 inrate, outrate, offset =0 ; -u32 in_s_rate, out_s_rate, in_s_fmt, out_s_fmt; +u32 in_s_rate, out_s_rate; +snd_pcm_format_t in_s_fmt, out_s_fmt;int ret, i;if (!easrc)
@@ -1873,6 +1874,7 @@ static int fsl_easrc_probe(struct platform_device *pdev)struct resource *res;struct device_node *np;void __iomem *regs; +u32 asrc_fmt =0 ;int ret, irq; easrc =devm_kzalloc (dev,sizeof (*easrc),GFP_KERNEL );
@@ -1933,13 +1935,14 @@ static int fsl_easrc_probe(struct platform_device *pdev)return ret; } - ret =of_property_read_u32 (np,"fsl,asrc-format" , &easrc->asrc_format); + ret =of_property_read_u32 (np,"fsl,asrc-format" , &asrc_fmt); + easrc->asrc_format = (__force snd_pcm_format_t )asrc_fmt;if (ret) {dev_err (dev,"failed to asrc format\n" );return ret; } -if (!(FSL_EASRC_FORMATS & (1ULL << easrc->asrc_format))) { +if (!(FSL_EASRC_FORMATS & (pcm_format_to_bits (easrc->asrc_format)))) {dev_warn (dev,"unsupported format, switching to S24_LE\n" ); easrc->asrc_format =SNDRV_PCM_FORMAT_S24_LE ; }
sound/soc/fsl/fsl_easrc.h +1 -1
@@ -569,7 +569,7 @@ struct fsl_easrc_io_params {unsigned int access_len;unsigned int fifo_wtmk;unsigned int sample_rate; -unsigned int sample_format; +snd_pcm_format_t sample_format;unsigned int norm_rate; };
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 626/779 ASoC: imx-card: use snd_pcm_format_t type for asrc_format
In reply to Greg Kroah-HartmanFrom: Shengjiu Wang <[email protected]>
[ Upstream commit 409a8652e909e323c715f3088e6c3133e37c8881 ]
Fix sparse warning:sound/soc/fsl/imx-card.c:653:59: sparse: warning: incorrect type in assignment (different base types)sound/soc/fsl/imx-card.c:653:59: sparse: expected unsigned int [usertype] asrc_formatsound/soc/fsl/imx-card.c:653:59: sparse: got restricted snd_pcm_format_t [usertype]sound/soc/fsl/imx-card.c:655:59: sparse: warning: incorrect type in assignment (different base types)sound/soc/fsl/imx-card.c:655:59: sparse: expected unsigned int [usertype] asrc_formatsound/soc/fsl/imx-card.c:655:59: sparse: got restricted snd_pcm_format_t [usertype]
--- sound/soc/fsl/imx-card.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
sound/soc/fsl/imx-card.c +5 -3
@@ -118,7 +118,7 @@ struct imx_card_data {struct snd_soc_card card;int num_dapm_routes;u32 asrc_rate; -u32 asrc_format; +snd_pcm_format_t asrc_format; };static struct imx_akcodec_fs_mul ak4458_fs_mul[] = {
@@ -474,7 +474,7 @@ static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, mask =hw_param_mask (params,SNDRV_PCM_HW_PARAM_FORMAT );snd_mask_none (mask); -snd_mask_set (mask, data->asrc_format); +snd_mask_set (mask, (__force unsigned int )data->asrc_format);return 0 ; }
@@ -493,6 +493,7 @@ static int imx_card_parse_of(struct imx_card_data *data)struct dai_link_data *link_data;struct of_phandle_args args;int ret, num_links; +u32 asrc_fmt =0 ;u32 width; ret =snd_soc_of_parse_card_name (card,"model" );
@@ -639,7 +640,8 @@ static int imx_card_parse_of(struct imx_card_data *data) goto err; } - ret =of_property_read_u32 (args.np,"fsl,asrc-format" , &data->asrc_format); + ret =of_property_read_u32 (args.np,"fsl,asrc-format" , &asrc_fmt); + data->asrc_format = (__force snd_pcm_format_t )asrc_fmt;if (ret) {/* Fallback to old binding; translate to asrc_format */ ret =of_property_read_u32 (args.np,"fsl,asrc-width" , &width);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 627/779 ASoC: qcom: q6dsp: Fix an off-by-one in q6adm_alloc_copp()
In reply to Greg Kroah-HartmanFrom: Christophe JAILLET <[email protected]>
[ Upstream commit 673f58f62ca6fc98979d1cf3fe89c3ff33f29b2e ]
find_first_zero_bit() returns MAX_COPPS_PER_PORT at max here. So 'idx' should be tested with ">=" or the test can't match.
--- sound/soc/qcom/qdsp6/q6adm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/qcom/qdsp6/q6adm.c +1 -1
@@ -217,7 +217,7 @@ static struct q6copp *q6adm_alloc_copp(struct q6adm *adm, int port_idx) idx =find_first_zero_bit (&adm->copp_bitmap[port_idx],MAX_COPPS_PER_PORT ); -if (idx >MAX_COPPS_PER_PORT ) +if (idx >=MAX_COPPS_PER_PORT )return ERR_PTR (-EBUSY ); c =kzalloc (sizeof (*c),GFP_ATOMIC );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 628/779 fuse: Remove the control interface for virtio-fs
In reply to Greg Kroah-HartmanFrom: Xie Yongji <[email protected]>
[ Upstream commit c64797809a64c73497082aa05e401a062ec1af34 ]
The commit 15c8e72e88e0 ("fuse: allow skipping control interface and forced unmount") tries to remove the control interface for virtio-fs since it does not support aborting requests which are being processed. But it doesn't work now.
This patch fixes it by skipping creating the control interface if fuse_conn->no_control is set.
--- fs/fuse/control.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/fuse/control.c +2 -2
@@ -275,7 +275,7 @@ int fuse_ctl_add_conn(struct fuse_conn *fc)struct dentry *parent;char name[32 ]; -if (!fuse_control_sb) +if (!fuse_control_sb || fc->no_control)return 0 ; parent = fuse_control_sb->s_root;
@@ -313,7 +313,7 @@ void fuse_ctl_remove_conn(struct fuse_conn *fc) {int i; -if (!fuse_control_sb) +if (!fuse_control_sb || fc->no_control)return ;for (i = fc->ctl_ndents -1 ; i >=0 ; i--) {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 629/779 ASoC: audio-graph-card: Add of_node_put() in fail path
In reply to Greg Kroah-HartmanFrom: Liang He <[email protected]>
[ Upstream commit 65fb8e2ef3531a6e950060fca6e551c923fb0f0e ]
In asoc_simple_parse_dai(), we should call of_node_put() for the reference returned by of_graph_get_port_parent() in fail path.
--- sound/soc/generic/audio-graph-card.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
sound/soc/generic/audio-graph-card.c +3 -1
@@ -158,8 +158,10 @@ static int asoc_simple_parse_dai(struct device_node *ep,* if he unbinded CPU or Codec. */ ret =snd_soc_get_dai_name (&args, &dlc->dai_name); -if (ret <0 ) +if (ret <0 ) { +of_node_put (node);return ret; + } dlc->of_node = node;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 630/779 watchdog: sp5100_tco: Fix a memory leak of EFCH MMIO resource
In reply to Greg Kroah-HartmanFrom: Jean Delvare <[email protected]>
[ Upstream commit c6d9c0798ed366a09a9e53d71edcd2266e34a6eb ]
Unlike release_mem_region(), a call to release_resource() does not free the resource, so it has to be freed explicitly to avoid a memory leak.
--- drivers/watchdog/sp5100_tco.c | 1 + 1 file changed, 1 insertion(+)
drivers/watchdog/sp5100_tco.c +1 -0
@@ -394,6 +394,7 @@ static int sp5100_tco_setupdevice_mmio(struct device *dev,iounmap (addr);release_resource (res); +kfree (res);return ret; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 631/779 watchdog: armada_37xx_wdt: check the return value of devm_ioremap() in armada_37xx_wdt_probe()
In reply to Greg Kroah-HartmanFrom: William Dean <[email protected]>
[ Upstream commit 2d27e52841092e5831dd41f313028c668d816eb0 ]
The function devm_ioremap() in armada_37xx_wdt_probe() can fail, so its return value should be checked.
--- drivers/watchdog/armada_37xx_wdt.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/watchdog/armada_37xx_wdt.c +2 -0
@@ -274,6 +274,8 @@ static int armada_37xx_wdt_probe(struct platform_device *pdev)if (!res)return -ENODEV ; dev->reg =devm_ioremap (&pdev->dev, res->start,resource_size (res)); +if (!dev->reg) +return -ENOMEM ;/* init clock */ dev->clk =devm_clk_get (&pdev->dev,NULL );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 632/779 video: fbdev: amba-clcd: Fix refcount leak bugs
In reply to Greg Kroah-HartmanFrom: Liang He <[email protected]>
[ Upstream commit 26c2b7d9fac42eb8317f3ceefa4c1a9a9170ca69 ]
In clcdfb_of_init_display(), we should call of_node_put() for the references returned by of_graph_get_next_endpoint() and of_graph_get_remote_port_parent() which have increased the refcount.
Besides, we should call of_node_put() both in fail path or when the references are not used anymore.
--- drivers/video/fbdev/amba-clcd.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
drivers/video/fbdev/amba-clcd.c +18 -6
@@ -698,16 +698,18 @@ static int clcdfb_of_init_display(struct clcd_fb *fb)return -ENODEV ; panel =of_graph_get_remote_port_parent (endpoint); -if (!panel) -return -ENODEV ; +if (!panel) { + err = -ENODEV ; + goto out_endpoint_put; + } err =clcdfb_of_get_backlight (&fb->dev->dev, fb->panel);if (err) -return err; + goto out_panel_put; err =clcdfb_of_get_mode (&fb->dev->dev, panel, fb->panel);if (err) -return err; + goto out_panel_put; err =of_property_read_u32 (fb->dev->dev.of_node,"max-memory-bandwidth" , &max_bandwidth);
@@ -736,11 +738,21 @@ static int clcdfb_of_init_display(struct clcd_fb *fb)if (of_property_read_u32_array (endpoint,"arm,pl11x,tft-r0g0b0-pads" , - tft_r0b0g0,ARRAY_SIZE (tft_r0b0g0)) !=0 ) -return -ENOENT ; + tft_r0b0g0,ARRAY_SIZE (tft_r0b0g0)) !=0 ) { + err = -ENOENT ; + goto out_panel_put; + } + +of_node_put (panel); +of_node_put (endpoint);return clcdfb_of_init_tft_panel (fb, tft_r0b0g0[0 ], tft_r0b0g0[1 ], tft_r0b0g0[2 ]); +out_panel_put: +of_node_put (panel); +out_endpoint_put: +of_node_put (endpoint); +return err; }static int clcdfb_of_vram_setup (struct clcd_fb *fb)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 633/779 video: fbdev: sis: fix typos in SiS_GetModeID()
In reply to Greg Kroah-HartmanFrom: Rustam Subkhankulov <[email protected]>
[ Upstream commit 3eb8fccc244bfb41a7961969e4db280d44911226 ]
The second operand of a '&&' operator has no impact on expression result for cases 400 and 512 in SiS_GetModeID().
Judging by the logic and the names of the variables, in both cases a typo was made.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/video/fbdev/sis/init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/video/fbdev/sis/init.c +2 -2
@@ -355,12 +355,12 @@ SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, }break ;case 400 : -if ((!(VBFlags &CRT1_LCDA )) || ((LCDwidth >=800 ) && (LCDwidth >=600 ))) { +if ((!(VBFlags &CRT1_LCDA )) || ((LCDwidth >=800 ) && (LCDheight >=600 ))) {if (VDisplay ==300 ) ModeIndex = ModeIndex_400x300[Depth]; }break ;case 512 : -if ((!(VBFlags &CRT1_LCDA )) || ((LCDwidth >=1024 ) && (LCDwidth >=768 ))) { +if ((!(VBFlags &CRT1_LCDA )) || ((LCDwidth >=1024 ) && (LCDheight >=768 ))) {if (VDisplay ==384 ) ModeIndex = ModeIndex_512x384[Depth]; }break ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 634/779 ASoC: mchp-spdifrx: disable end of block interrupt on failures
In reply to Greg Kroah-HartmanFrom: Claudiu Beznea <[email protected]>
[ Upstream commit 768ac4f12ca0fda935f58eb8c5120e9d795bc6e3 ]
Disable end of block interrupt in case of wait for completion timeout or errors to undo previously enable operation (done in mchp_spdifrx_isr_blockend_en()). Otherwise we can end up with an unbalanced reference counter for this interrupt.
--- sound/soc/atmel/mchp-spdifrx.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
sound/soc/atmel/mchp-spdifrx.c +6 -3
@@ -288,15 +288,17 @@ static void mchp_spdifrx_isr_blockend_en(struct mchp_spdifrx_dev *dev)spin_unlock_irqrestore (&dev->blockend_lock, flags); } -/* called from atomic context only */ +/* called from atomic/non-atomic context */ static void mchp_spdifrx_isr_blockend_dis (struct mchp_spdifrx_dev *dev) { -spin_lock (&dev->blockend_lock); +unsigned long flags; + +spin_lock_irqsave (&dev->blockend_lock, flags); dev->blockend_refcount--;/* don't enable BLOCKEND interrupt if it's already enabled */ if (dev->blockend_refcount ==0 )regmap_write (dev->regmap,SPDIFRX_IDR ,SPDIFRX_IR_BLOCKEND ); -spin_unlock (&dev->blockend_lock); +spin_unlock_irqrestore (&dev->blockend_lock, flags); }static irqreturn_t mchp_spdif_interrupt (int irq,void *dev_id)
@@ -575,6 +577,7 @@ static int mchp_spdifrx_subcode_ch_get(struct mchp_spdifrx_dev *dev,if (ret <=0 ) {dev_dbg (dev->dev,"user data for channel %d timeout\n" , channel); +mchp_spdifrx_isr_blockend_dis (dev);return ret; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 635/779 powerpc/32: Call mmu_mark_initmem_nx() regardless of data block mapping.
In reply to Greg Kroah-HartmanFrom: Christophe Leroy <[email protected]>
[ Upstream commit 980bbf7ca72012d317617fcdbfabe8708e4cef29 ]
mark_initmem_nx() calls either mmu_mark_initmem_nx() or set_memory_attr() based on return from v_block_mapped() of _sinittext.
But we can now handle text and data independently, so that text may be mapped by block even when data is mapped by pages.
On the 8xx for instance, at startup 32Mbytes of memory are pinned in TLB. So the pinned entries need to go away for sinittext.
In next patch a BAT will be set to also covers sinittext on book3s/32. So it will also be needed to call mmu_mark_initmem_nx() even when data above sinittext is not mapped with BATs.
As this is highly dependent on the platform, call mmu_mark_initmem_nx() regardless of data block mapping. Then the platform will know what to do.
Modify 8xx mmu_mark_initmem_nx() so that inittext mapping is modified only when pagealloc debug and kfence are not active, otherwise inittext is mapped with standard pages. And don't do anything on kernel text which is already mapped with PAGE_KERNEL_TEXT.
--- arch/powerpc/mm/nohash/8xx.c | 4 ++-- arch/powerpc/mm/pgtable_32.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-)
arch/powerpc/mm/nohash/8xx.c +2 -2
@@ -183,8 +183,8 @@ void mmu_mark_initmem_nx(void)unsigned long boundary =strict_kernel_rwx_enabled () ? sinittext : etext8;unsigned long einittext8 =ALIGN (__pa (_einittext),SZ_8M ); -mmu_mapin_ram_chunk (0 , boundary,PAGE_KERNEL_TEXT , false); -mmu_mapin_ram_chunk (boundary, einittext8,PAGE_KERNEL , false); +if (!debug_pagealloc_enabled_or_kfence ()) +mmu_mapin_ram_chunk (boundary, einittext8,PAGE_KERNEL , false);mmu_pin_tlb (block_mapped_ram, false); }
arch/powerpc/mm/pgtable_32.c +3 -3
@@ -138,9 +138,9 @@ void mark_initmem_nx(void)unsigned long numpages =PFN_UP ((unsigned long )_einittext) -PFN_DOWN ((unsigned long )_sinittext); -if (v_block_mapped ((unsigned long )_sinittext)) { -mmu_mark_initmem_nx (); - }else { +mmu_mark_initmem_nx (); + +if (!v_block_mapped ((unsigned long )_sinittext)) {set_memory_nx ((unsigned long )_sinittext, numpages);set_memory_rw ((unsigned long )_sinittext, numpages); }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 636/779 powerpc/32: Do not allow selection of e5500 or e6500 CPUs on PPC32
In reply to Greg Kroah-HartmanFrom: Christophe Leroy <[email protected]>
[ Upstream commit 9be013b2a9ecb29b5168e4b9db0e48ed53acf37c ]
Commit 0e00a8c9fd92 ("powerpc: Allow CPU selection also on PPC32") enlarged the CPU selection logic to PPC32 by removing depend to PPC64, and failed to restrict that depend to E5500_CPU and E6500_CPU. Fortunately that got unnoticed because -mcpu=8540 will override the -mcpu=e500mc64 or -mpcu=e6500 as they are ealier, but that's fragile and may no be right in the future.
Add back the depend PPC64 on E5500_CPU and E6500_CPU.
--- arch/powerpc/platforms/Kconfig.cputype | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/powerpc/platforms/Kconfig.cputype +2 -2
@@ -170,11 +170,11 @@ config POWER9_CPU config E5500_CPU bool "Freescale e5500" - depends on E500 + depends on PPC64 && E500 config E6500_CPU bool "Freescale e6500" - depends on E500 + depends on PPC64 && E500 config 860_CPU bool "8xx family"
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 637/779 powerpc/iommu: Fix iommu_table_in_use for a small default DMA window case
In reply to Greg Kroah-HartmanFrom: Alexey Kardashevskiy <[email protected]>
[ Upstream commit d80f6de9d601c30b53c17f00cb7cfe3169f2ddad ]
The existing iommu_table_in_use() helper checks if the kernel is using any of TCEs. There are some reserved TCEs:
1) the very first one if DMA window starts from 0 to avoid having a zero but still valid DMA handle;
2) it_reserved_start..it_reserved_end to exclude MMIO32 window in case the default window spans across that - this is the default for the first DMA window on PowerNV.
When 1) is the case and 2) is not the helper does not skip 1) and returns wrong status.
This only seems occurring when passing through a PCI device to a nested guest (not something we support really well) so it has not been seen before.
This fixes the bug by adding a special case for no MMIO32 reservation.
--- arch/powerpc/kernel/iommu.c | 5 +++++ 1 file changed, 5 insertions(+)
arch/powerpc/kernel/iommu.c +5 -0
@@ -776,6 +776,11 @@ bool iommu_table_in_use(struct iommu_table *tbl)/* ignore reserved bit0 */ if (tbl->it_offset ==0 ) start =1 ; + +/* Simple case with no reserved MMIO32 region */ +if (!tbl->it_reserved_start && !tbl->it_reserved_end) +return find_next_bit (tbl->it_map, tbl->it_size, start) != tbl->it_size; + end = tbl->it_reserved_start - tbl->it_offset;if (find_next_bit (tbl->it_map, end, start) != end)return true;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 638/779 powerpc/pci: Prefer PCI domain assignment via DT linux,pci-domain and alias
In reply to Greg Kroah-HartmanFrom: Pali Rohár <[email protected]>
[ Upstream commit 0fe1e96fef0a5c53b4c0d1500d356f3906000f81 ]
Other Linux architectures use DT property 'linux,pci-domain' for specifying fixed PCI domain of PCI controller specified in Device-Tree.
And lot of Freescale powerpc boards have defined numbered pci alias in Device-Tree for every PCIe controller which number specify preferred PCI domain.
So prefer usage of DT property 'linux,pci-domain' (via function of_get_pci_domain_nr()) and DT pci alias (via function of_alias_get_id()) on powerpc architecture for assigning PCI domain to PCI controller.
--- arch/powerpc/kernel/pci-common.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-)
arch/powerpc/kernel/pci-common.c +19 -8
@@ -74,16 +74,30 @@ void set_pci_dma_ops(const struct dma_map_ops *dma_ops)static int get_phb_number (struct device_node *dn) {int ret, phb_id =-1 ; -u32 prop_32;u64 prop;/* * Try fixed PHB numbering first, by checking archs and reading -* the respective device-tree properties. Firstly, try powernv by -* reading "ibm,opal-phbid", only present in OPAL environment. +* the respective device-tree properties. Firstly, try reading +* standard "linux,pci-domain", then try reading "ibm,opal-phbid" +* (only present in powernv OPAL environment), then try device-tree +* alias and as the last try to use lower bits of "reg" property. */ - ret =of_property_read_u64 (dn,"ibm,opal-phbid" , &prop); + ret =of_get_pci_domain_nr (dn); +if (ret >=0 ) { + prop = ret; + ret =0 ; + } +if (ret) + ret =of_property_read_u64 (dn,"ibm,opal-phbid" , &prop); +if (ret) + ret =of_alias_get_id (dn,"pci" ); +if (ret >=0 ) { + prop = ret; + ret =0 ; + }if (ret) { +u32 prop_32; ret =of_property_read_u32_index (dn,"reg" ,1 , &prop_32); prop = prop_32; }
@@ -95,10 +109,7 @@ static int get_phb_number(struct device_node *dn)if ((phb_id >=0 ) && !test_and_set_bit (phb_id, phb_bitmap))return phb_id; -/* -* If not pseries nor powernv, or if fixed PHB numbering tried to add -* the same PHB number twice, then fallback to dynamic PHB numbering. -*/ +/* If everything fails then fallback to dynamic PHB numbering. */ phb_id =find_first_zero_bit (phb_bitmap,MAX_PHBS );BUG_ON (phb_id >=MAX_PHBS );set_bit (phb_id, phb_bitmap);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 639/779 tty: serial: fsl_lpuart: correct the count of break characters
In reply to Greg Kroah-HartmanFrom: Sherry Sun <[email protected]>
[ Upstream commit 707f816f25590c20e056b3bd4a17ce69b03fe856 ]
The LPUART can't distinguish between a break signal and a framing error, so need to count the break characters if there is a framing error and received data is zero instead of the parity error.
--- drivers/tty/serial/fsl_lpuart.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/tty/serial/fsl_lpuart.c +6 -6
@@ -982,12 +982,12 @@ static void lpuart32_rxint(struct lpuart_port *sport)if (sr & (UARTSTAT_PE |UARTSTAT_OR |UARTSTAT_FE )) {if (sr &UARTSTAT_PE ) { + sport->port.icount.parity++; + }else if (sr &UARTSTAT_FE ) {if (is_break) sport->port.icount.brk++;else - sport->port.icount.parity++; - }else if (sr &UARTSTAT_FE ) { - sport->port.icount.frame++; + sport->port.icount.frame++; }if (sr &UARTSTAT_OR )
@@ -1002,12 +1002,12 @@ static void lpuart32_rxint(struct lpuart_port *sport) sr &= sport->port.read_status_mask;if (sr &UARTSTAT_PE ) { + flg =TTY_PARITY ; + }else if (sr &UARTSTAT_FE ) {if (is_break) flg =TTY_BREAK ;else - flg =TTY_PARITY ; - }else if (sr &UARTSTAT_FE ) { - flg =TTY_FRAME ; + flg =TTY_FRAME ; }if (sr &UARTSTAT_OR )
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 640/779 s390/dump: fix os_info virtual vs physical address confusion
In reply to Greg Kroah-HartmanFrom: Alexander Gordeev <[email protected]>
[ Upstream commit 9de209c7d584d6e06ad92f120d83d4f27c200497 ]
Due to historical reasons os_info handling functions misuse the notion of physical vs virtual addresses difference.
Note: this does not fix a bug currently, since virtual and physical addresses are identical.
--- arch/s390/kernel/os_info.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/s390/kernel/os_info.c +2 -2
@@ -46,7 +46,7 @@ void os_info_crashkernel_add(unsigned long base, unsigned long size)*/ void os_info_entry_add (int nr,void *ptr,u64 size) { - os_info.entry[nr].addr = (u64 )(unsigned long )ptr; + os_info.entry[nr].addr =__pa (ptr); os_info.entry[nr].size = size; os_info.entry[nr].csum = (__force u32 )csum_partial (ptr, size,0 ); os_info.csum =os_info_csum (&os_info);
@@ -63,7 +63,7 @@ void __init os_info_init(void) os_info.version_minor =OS_INFO_VERSION_MINOR ; os_info.magic =OS_INFO_MAGIC ; os_info.csum =os_info_csum (&os_info); -mem_assign_absolute (S390_lowcore.os_info, (unsigned long ) ptr); +mem_assign_absolute (S390_lowcore.os_info,__pa (ptr)); }#ifdef CONFIG_CRASH_DUMP
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 641/779 s390/smp: cleanup target CPU callback starting
In reply to Greg Kroah-HartmanFrom: Alexander Gordeev <[email protected]>
[ Upstream commit dc2ab23b992c9d5dab93b9bf01b10b10465e537e ]
Macro mem_assign_absolute() is used to initialize a target CPU lowcore callback parameters. But despite the macro name it writes to the absolute lowcore only if the target CPU is offline. In case the CPU is online the macro does implicitly write to the normal memory.
That behaviour is correct, but extremely subtle. Sacrifice few program bits in favour of clarity and distinguish between online vs offline CPUs and normal vs absolute lowcore pointer.
--- arch/s390/kernel/smp.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
arch/s390/kernel/smp.c +11 -4
@@ -328,10 +328,17 @@ static void pcpu_delegate(struct pcpu *pcpu,/* Stop target cpu (if func returns this stops the current cpu). */ pcpu_sigp_retry (pcpu,SIGP_STOP ,0 );/* Restart func on the target cpu and stop the current cpu. */ -mem_assign_absolute (lc->restart_stack, stack); -mem_assign_absolute (lc->restart_fn, (unsigned long ) func); -mem_assign_absolute (lc->restart_data, (unsigned long ) data); -mem_assign_absolute (lc->restart_source, source_cpu); +if (lc) { + lc->restart_stack = stack; + lc->restart_fn = (unsigned long )func; + lc->restart_data = (unsigned long )data; + lc->restart_source = source_cpu; + }else { +mem_assign_absolute (lc->restart_stack, stack); +mem_assign_absolute (lc->restart_fn, (unsigned long )func); +mem_assign_absolute (lc->restart_data, (unsigned long )data); +mem_assign_absolute (lc->restart_source, source_cpu); + }__bpon (); asmvolatile ( "0: sigp 0,%0,%2 # sigp restart to target cpu\n"
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 642/779 s390/smp: cleanup control register update routines
In reply to Greg Kroah-HartmanFrom: Alexander Gordeev <[email protected]>
[ Upstream commit 9097fc793f74ef9c677f8c4aed0c24f6f07f0133 ]
Get rid of duplicate code and redundant data.
--- arch/s390/include/asm/ctl_reg.h | 16 ++++++++++----- arch/s390/kernel/smp.c | 36 +++++++++++---------------------- 2 files changed, 23 insertions(+), 29 deletions(-)
arch/s390/include/asm/ctl_reg.h +11 -5
@@ -72,8 +72,17 @@ static __always_inline void __ctl_clear_bit(unsigned int cr, unsigned int bit)__ctl_load (reg, cr, cr); } -void smp_ctl_set_bit (int cr,int bit); -void smp_ctl_clear_bit (int cr,int bit); +void smp_ctl_set_clear_bit (int cr,int bit,bool set); + +static inline void ctl_set_bit (int cr,int bit) +{ +smp_ctl_set_clear_bit (cr, bit, true); +} + +static inline void ctl_clear_bit (int cr,int bit) +{ +smp_ctl_set_clear_bit (cr, bit, false); +}union ctlreg0 {unsigned long val;
@@ -128,8 +137,5 @@ union ctlreg15 { }; }; -#define ctl_set_bit (cr, bit) smp_ctl_set_bit(cr, bit) -#define ctl_clear_bit (cr, bit) smp_ctl_clear_bit(cr, bit) -#endif /* __ASSEMBLY__ */ #endif /* __ASM_CTL_REG_H */
arch/s390/kernel/smp.c +12 -24
@@ -579,39 +579,27 @@ static void smp_ctl_bit_callback(void *info) }static DEFINE_SPINLOCK (ctl_lock); -static unsigned long ctlreg; -/* -* Set a bit in a control register of all cpus -*/ -void smp_ctl_set_bit (int cr,int bit) +void smp_ctl_set_clear_bit (int cr,int bit,bool set) { -struct ec_creg_mask_parms parms = {1UL << bit,-1UL , cr }; - -spin_lock (&ctl_lock); -memcpy_absolute (&ctlreg, &S390_lowcore.cregs_save_area[cr],sizeof (ctlreg)); -__set_bit (bit, &ctlreg); -memcpy_absolute (&S390_lowcore.cregs_save_area[cr], &ctlreg,sizeof (ctlreg)); -spin_unlock (&ctl_lock); -on_each_cpu (smp_ctl_bit_callback, &parms,1 ); -} -EXPORT_SYMBOL (smp_ctl_set_bit); - -/* -* Clear a bit in a control register of all cpus -*/ -void smp_ctl_clear_bit (int cr,int bit) -{ -struct ec_creg_mask_parms parms = {0 , ~(1UL << bit), cr }; +struct ec_creg_mask_parms parms = { .cr = cr, }; +u64 ctlreg; +if (set) { + parms.orval =1UL << bit; + parms.andval =-1UL ; + }else { + parms.orval =0 ; + parms.andval = ~(1UL << bit); + }spin_lock (&ctl_lock);memcpy_absolute (&ctlreg, &S390_lowcore.cregs_save_area[cr],sizeof (ctlreg)); -__clear_bit (bit, &ctlreg); + ctlreg = (ctlreg & parms.andval) | parms.orval;memcpy_absolute (&S390_lowcore.cregs_save_area[cr], &ctlreg,sizeof (ctlreg));spin_unlock (&ctl_lock);on_each_cpu (smp_ctl_bit_callback, &parms,1 ); } -EXPORT_SYMBOL (smp_ctl_clear_bit); +EXPORT_SYMBOL (smp_ctl_set_clear_bit);#ifdef CONFIG_CRASH_DUMP
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 643/779 s390/maccess: rework absolute lowcore accessors
In reply to Greg Kroah-HartmanFrom: Alexander Gordeev <[email protected]>
[ Upstream commit ed0192bc644f3553d64a5cb461bdd0b1fbae3fdf ]
Macro mem_assign_absolute() is able to access the whole memory, but is only used and makes sense when updating the absolute lowcore. Instead, introduce get_abs_lowcore() and put_abs_lowcore() macros that limit access to absolute lowcore addresses only.
--- arch/s390/include/asm/processor.h | 17 ++++++++++++----- arch/s390/kernel/ipl.c | 4 ++-- arch/s390/kernel/machine_kexec.c | 2 +- arch/s390/kernel/os_info.c | 2 +- arch/s390/kernel/setup.c | 19 ++++++++++--------- arch/s390/kernel/smp.c | 12 ++++++------ 6 files changed, 32 insertions(+), 24 deletions(-)
arch/s390/include/asm/processor.h +12 -5
@@ -321,11 +321,18 @@ extern void (*s390_base_pgm_handler_fn)(void);extern int memcpy_real (void *,unsigned long ,size_t );extern void memcpy_absolute (void *,void *,size_t ); -#define mem_assign_absolute (dest, val) do { \ - __typeof__(dest) __tmp = (val); \ - \ - BUILD_BUG_ON(sizeof(__tmp) != sizeof(val)); \ - memcpy_absolute(&(dest), &__tmp, sizeof(__tmp)); \ +#define put_abs_lowcore (member, x) do { \ + unsigned long __abs_address = offsetof(struct lowcore, member); \ + __typeof__(((struct lowcore *)0)->member) __tmp = (x); \ + \ + memcpy_absolute(__va(__abs_address), &__tmp, sizeof(__tmp)); \ +} while (0) + +#define get_abs_lowcore (x, member) do { \ + unsigned long __abs_address = offsetof(struct lowcore, member); \ + __typeof__(((struct lowcore *)0)->member) *__ptr = &(x); \ + \ + memcpy_absolute(__ptr, __va(__abs_address), sizeof(*__ptr)); \ } while (0)extern int s390_isolate_bp (void );
arch/s390/kernel/ipl.c +2 -2
@@ -1646,8 +1646,8 @@ static void dump_reipl_run(struct shutdown_trigger *trigger) csum = (__force unsigned int )csum_partial (reipl_block_actual, reipl_block_actual->hdr.len,0 ); -mem_assign_absolute (S390_lowcore.ipib, ipib); -mem_assign_absolute (S390_lowcore.ipib_checksum, csum); +put_abs_lowcore (ipib, ipib); +put_abs_lowcore (ipib_checksum, csum);dump_run (trigger); }
arch/s390/kernel/machine_kexec.c +1 -1
@@ -227,7 +227,7 @@ void arch_crash_save_vmcoreinfo(void)vmcoreinfo_append_str ("SAMODE31=%lx\n" , __samode31);vmcoreinfo_append_str ("EAMODE31=%lx\n" , __eamode31);vmcoreinfo_append_str ("KERNELOFFSET=%lx\n" ,kaslr_offset ()); -mem_assign_absolute (S390_lowcore.vmcore_info,paddr_vmcoreinfo_note ()); +put_abs_lowcore (vmcore_info,paddr_vmcoreinfo_note ()); }void machine_shutdown (void )
arch/s390/kernel/os_info.c +1 -1
@@ -63,7 +63,7 @@ void __init os_info_init(void) os_info.version_minor =OS_INFO_VERSION_MINOR ; os_info.magic =OS_INFO_MAGIC ; os_info.csum =os_info_csum (&os_info); -mem_assign_absolute (S390_lowcore.os_info,__pa (ptr)); +put_abs_lowcore (os_info,__pa (ptr)); }#ifdef CONFIG_CRASH_DUMP
arch/s390/kernel/setup.c +10 -9
@@ -479,11 +479,11 @@ static void __init setup_lowcore_dat_off(void) lc->mcck_stack = mcck_stack +STACK_INIT_OFFSET ;/* Setup absolute zero lowcore */ -mem_assign_absolute (S390_lowcore.restart_stack, lc->restart_stack); -mem_assign_absolute (S390_lowcore.restart_fn, lc->restart_fn); -mem_assign_absolute (S390_lowcore.restart_data, lc->restart_data); -mem_assign_absolute (S390_lowcore.restart_source, lc->restart_source); -mem_assign_absolute (S390_lowcore.restart_psw, lc->restart_psw); +put_abs_lowcore (restart_stack, lc->restart_stack); +put_abs_lowcore (restart_fn, lc->restart_fn); +put_abs_lowcore (restart_data, lc->restart_data); +put_abs_lowcore (restart_source, lc->restart_source); +put_abs_lowcore (restart_psw, lc->restart_psw); lc->spinlock_lockval =arch_spin_lockval (0 ); lc->spinlock_index =0 ;
@@ -500,6 +500,7 @@ static void __init setup_lowcore_dat_off(void)static void __init setup_lowcore_dat_on (void ) {struct lowcore *lc = lowcore_ptr[0 ]; +int cr;__ctl_clear_bit (0 ,28 ); S390_lowcore.external_new_psw.mask |=PSW_MASK_DAT ;
@@ -508,10 +509,10 @@ static void __init setup_lowcore_dat_on(void) S390_lowcore.io_new_psw.mask |=PSW_MASK_DAT ;__ctl_store (S390_lowcore.cregs_save_area,0 ,15 );__ctl_set_bit (0 ,28 ); -mem_assign_absolute (S390_lowcore.restart_flags,RESTART_FLAG_CTLREGS ); -mem_assign_absolute (S390_lowcore.program_new_psw, lc->program_new_psw); -memcpy_absolute (&S390_lowcore.cregs_save_area, lc->cregs_save_area, -sizeof (S390_lowcore.cregs_save_area)); +put_abs_lowcore (restart_flags,RESTART_FLAG_CTLREGS ); +put_abs_lowcore (program_new_psw, lc->program_new_psw); +for (cr =0 ; cr <ARRAY_SIZE (lc->cregs_save_area); cr++) +put_abs_lowcore (cregs_save_area[cr], lc->cregs_save_area[cr]); }static struct resource code_resource = {
arch/s390/kernel/smp.c +6 -6
@@ -334,10 +334,10 @@ static void pcpu_delegate(struct pcpu *pcpu, lc->restart_data = (unsigned long )data; lc->restart_source = source_cpu; }else { -mem_assign_absolute (lc->restart_stack, stack); -mem_assign_absolute (lc->restart_fn, (unsigned long )func); -mem_assign_absolute (lc->restart_data, (unsigned long )data); -mem_assign_absolute (lc->restart_source, source_cpu); +put_abs_lowcore (restart_stack, stack); +put_abs_lowcore (restart_fn, (unsigned long )func); +put_abs_lowcore (restart_data, (unsigned long )data); +put_abs_lowcore (restart_source, source_cpu); }__bpon (); asm volatile(
@@ -593,9 +593,9 @@ void smp_ctl_set_clear_bit(int cr, int bit, bool set) parms.andval = ~(1UL << bit); }spin_lock (&ctl_lock); -memcpy_absolute (&ctlreg, &S390_lowcore.cregs_save_area[cr],sizeof (ctlreg)); +get_abs_lowcore (ctlreg, cregs_save_area[cr]); ctlreg = (ctlreg & parms.andval) | parms.orval; -memcpy_absolute (&S390_lowcore.cregs_save_area[cr], &ctlreg,sizeof (ctlreg)); +put_abs_lowcore (cregs_save_area[cr], ctlreg);spin_unlock (&ctl_lock);on_each_cpu (smp_ctl_bit_callback, &parms,1 ); }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 644/779 s390/smp: enforce lowcore protection on CPU restart
In reply to Greg Kroah-HartmanFrom: Alexander Gordeev <[email protected]>
[ Upstream commit 6f5c672d17f583b081e283927f5040f726c54598 ]
As result of commit 915fea04f932 ("s390/smp: enable DAT before CPU restart callback is called") the low-address protection bit gets mistakenly unset in control register 0 save area of the absolute zero memory. That area is used when manual PSW restart happened to hit an offline CPU. In this case the low-address protection for that CPU will be dropped.
--- arch/s390/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/s390/kernel/setup.c +1 -1
@@ -507,8 +507,8 @@ static void __init setup_lowcore_dat_on(void) S390_lowcore.svc_new_psw.mask |=PSW_MASK_DAT ; S390_lowcore.program_new_psw.mask |=PSW_MASK_DAT ; S390_lowcore.io_new_psw.mask |=PSW_MASK_DAT ; -__ctl_store (S390_lowcore.cregs_save_area,0 ,15 );__ctl_set_bit (0 ,28 ); +__ctl_store (S390_lowcore.cregs_save_area,0 ,15 );put_abs_lowcore (restart_flags,RESTART_FLAG_CTLREGS );put_abs_lowcore (program_new_psw, lc->program_new_psw);for (cr =0 ; cr <ARRAY_SIZE (lc->cregs_save_area); cr++)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 645/779 f2fs: fix to remove F2FS_COMPR_FL and tag F2FS_NOCOMP_FL at the same time
In reply to Greg Kroah-HartmanFrom: Chao Liu <[email protected]>
[ Upstream commit 8ee236dcaa690d09ca612622e8bc8d09c302021d ]
If the inode has the compress flag, it will fail to use 'chattr -c +m' to remove its compress flag and tag no compress flag. However, the same command will be successful when executed again, as shown below:
$ touch foo.txt $ chattr +c foo.txt $ chattr -c +m foo.txt chattr: Invalid argument while setting flags on foo.txt $ chattr -c +m foo.txt $ f2fs_io getflags foo.txt get a flag on foo.txt ret=0, flags=nocompression,inline_data
Fix this by removing some checks in f2fs_setflags_common() that do not affect the original logic. I go through all the possible scenarios, and the results are as follows. Bold is the only thing that has changed.
+---------------+-----------+-----------+----------+ | | file flags | + command +-----------+-----------+----------+ | | no flag | compr | nocompr | +---------------+-----------+-----------+----------+ | chattr +c | compr | compr | -EINVAL | | chattr -c | no flag | no flag | nocompr | | chattr +m | nocompr | -EINVAL | nocompr | | chattr -m | no flag | compr | no flag | | chattr +c +m | -EINVAL | -EINVAL | -EINVAL | | chattr +c -m | compr | compr | compr | | chattr -c +m | nocompr | *nocompr* | nocompr | | chattr -c -m | no flag | no flag | no flag | +---------------+-----------+-----------+----------+
--- fs/f2fs/file.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-)
fs/f2fs/file.c +1 -8
@@ -1869,10 +1869,7 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask)if (masked_flags &F2FS_COMPR_FL ) {if (!f2fs_disable_compressed_file (inode))return -EINVAL ; - } -if (iflags &F2FS_NOCOMP_FL ) -return -EINVAL ; -if (iflags &F2FS_COMPR_FL ) { + }else {if (!f2fs_may_compress (inode))return -EINVAL ;if (S_ISREG (inode->i_mode) && inode->i_size)
@@ -1881,10 +1878,6 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask)set_compress_context (inode); } } -if ((iflags ^ masked_flags) &F2FS_NOCOMP_FL ) { -if (masked_flags &F2FS_COMPR_FL ) -return -EINVAL ; - } fi->i_flags = iflags | (fi->i_flags & ~mask); f2fs_bug_on(F2FS_I_SB(inode), (fi->i_flags & F2FS_COMPR_FL) &&
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 646/779 powerpc/spufs: Fix refcount leak in spufs_init_isolated_loader
In reply to Greg Kroah-HartmanFrom: Miaoqian Lin <[email protected]>
[ Upstream commit 6ac059dacffa8ab2f7798f20e4bd3333890c541c ]
of_find_node_by_path() returns remote device nodepointer with refcount incremented, we should use of_node_put() on it when done. Add missing of_node_put() to avoid refcount leak.
--- arch/powerpc/platforms/cell/spufs/inode.c | 1 + 1 file changed, 1 insertion(+)
arch/powerpc/platforms/cell/spufs/inode.c +1 -0
@@ -659,6 +659,7 @@ spufs_init_isolated_loader(void)return ; loader =of_get_property (dn,"loader" , &size); +of_node_put (dn);if (!loader)return ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 647/779 powerpc/xive: Fix refcount leak in xive_get_max_prio
In reply to Greg Kroah-HartmanFrom: Miaoqian Lin <[email protected]>
[ Upstream commit 255b650cbec6849443ce2e0cdd187fd5e61c218c ]
of_find_node_by_path() returns a node pointer with refcount incremented, we should use of_node_put() on it when done. Add missing of_node_put() to avoid refcount leak.
--- arch/powerpc/sysdev/xive/spapr.c | 1 + 1 file changed, 1 insertion(+)
arch/powerpc/sysdev/xive/spapr.c +1 -0
@@ -716,6 +716,7 @@ static bool xive_get_max_prio(u8 *max_prio) } reg =of_get_property (rootdn,"ibm,plat-res-int-priorities" , &len); +of_node_put (rootdn);if (!reg) {pr_err ("Failed to read 'ibm,plat-res-int-priorities' property\n" );return false;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 648/779 powerpc/cell/axon_msi: Fix refcount leak in setup_msi_msg_address
In reply to Greg Kroah-HartmanFrom: Miaoqian Lin <[email protected]>
[ Upstream commit df5d4b616ee76abc97e5bd348e22659c2b095b1c ]
of_get_next_parent() returns a node pointer with refcount incremented, we should use of_node_put() on it when not need anymore. Add missing of_node_put() in the error path to avoid refcount leak.
--- arch/powerpc/platforms/cell/axon_msi.c | 1 + 1 file changed, 1 insertion(+)
arch/powerpc/platforms/cell/axon_msi.c +1 -0
@@ -226,6 +226,7 @@ static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)if (!prop) {dev_dbg (&dev->dev,"axon_msi: no msi-address-(32|64) properties found\n" ); +of_node_put (dn);return -ENOENT ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 649/779 perf symbol: Fail to read phdr workaround
In reply to Greg Kroah-HartmanFrom: Ian Rogers <[email protected]>
[ Upstream commit 6d518ac7be6223811ab947897273b1bbef846180 ]
The perf jvmti agent doesn't create program headers, in this case fallback on section headers as happened previously.
Committer notes:
To test this, from a public post by Ian:
1) download a Java workload dacapo-9.12-MR1-bach.jar from
https://sourceforge.net/projects/dacapobench/
2) build perf such as "make -C tools/perf O=/tmp/perf NO_LIBBFD=1" it should detect Java and create /tmp/perf/libperf-jvmti.so
3) run perf with the jvmti agent:
perf record -k 1 java -agentpath:/tmp/perf/libperf-jvmti.so -jar dacapo-9.12-MR1-bach.jar -n 10 fop
4) run perf inject:
perf inject -i perf.data -o perf-injected.data -j
5) run perf report
perf report -i perf-injected.data | grep org.apache.fop
With this patch reverted I see lots of symbols like:
0.00% java jitted-388040-4656.so [.] org.apache.fop.fo.FObj.bind(org.apache.fop.fo.PropertyList)
With the patch (2d86612aacb7805f ("perf symbol: Correct address for bss symbols")) I see lots of:
dso__load_sym_internal: failed to find program header for symbol:
Lorg/apache/fop/fo/FObj;bind(Lorg/apache/fop/fo/PropertyList;)V
st_value: 0x40
--- tools/perf/util/symbol-elf.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-)
tools/perf/util/symbol-elf.c +20 -7
@@ -1294,16 +1294,29 @@ dso__load_sym_internal(struct dso *dso, struct map *map, struct symsrc *syms_ss,if (elf_read_program_header (syms_ss->elf, (u64 )sym.st_value, &phdr)) { -pr_warning ("%s: failed to find program header for " +pr_debug4 ("%s: failed to find program header for " "symbol: %s st_value: %#" PRIx64"\n" , __func__, elf_name, (u64 )sym.st_value); -continue ; +pr_debug4 ("%s: adjusting symbol: st_value: %#" PRIx64" " +"sh_addr: %#" PRIx64" sh_offset: %#" PRIx64"\n" , + __func__, (u64 )sym.st_value, (u64 )shdr.sh_addr, + (u64 )shdr.sh_offset); +/* +* Fail to find program header, let's rollback +* to use shdr.sh_addr and shdr.sh_offset to +* calibrate symbol's file address, though this +* is not necessary for normal C ELF file, we +* still need to handle java JIT symbols in this +* case. +*/ + sym.st_value -= shdr.sh_addr - shdr.sh_offset; + }else { +pr_debug4 ("%s: adjusting symbol: st_value: %#" PRIx64" " +"p_vaddr: %#" PRIx64" p_offset: %#" PRIx64"\n" , + __func__, (u64 )sym.st_value, (u64 )phdr.p_vaddr, + (u64 )phdr.p_offset); + sym.st_value -= phdr.p_vaddr - phdr.p_offset; } -pr_debug4 ("%s: adjusting symbol: st_value: %#" PRIx64" " -"p_vaddr: %#" PRIx64" p_offset: %#" PRIx64"\n" , - __func__, (u64 )sym.st_value, (u64 )phdr.p_vaddr, - (u64 )phdr.p_offset); - sym.st_value -= phdr.p_vaddr - phdr.p_offset; } demangled =demangle_sym (dso, kmodule, elf_name);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 650/779 kprobes: Forbid probing on trampoline and BPF code areas
In reply to Greg Kroah-HartmanFrom: Chen Zhongjin <[email protected]>
[ Upstream commit 28f6c37a2910f565b4f5960df52b2eccae28c891 ]
kernel_text_address() treats ftrace_trampoline, kprobe_insn_slot and bpf_text_address as valid kprobe addresses - which is not ideal.
These text areas are removable and changeable without any notification to kprobes, and probing on them can trigger unexpected behavior:
https://lkml.org/lkml/2022/7/26/1148
Considering that jump_label and static_call text are already forbiden to probe, kernel_text_address() should be replaced with core_kernel_text() and is_module_text_address() to check other text areas which are unsafe to kprobe.
[ mingo: Rewrote the changelog. ]
--- kernel/kprobes.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/kprobes.c +2 -1
@@ -1559,7 +1559,8 @@ static int check_kprobe_address_safe(struct kprobe *p,preempt_disable ();/* Ensure it is not in reserved area nor out of text */ - if (!kernel_text_address((unsigned long) p->addr) || + if (!(core_kernel_text((unsigned long) p->addr) || + is_module_text_address((unsigned long) p->addr)) || within_kprobe_blacklist((unsigned long) p->addr) || jump_label_text_reserved(p->addr, p->addr) || static_call_text_reserved(p->addr, p->addr) ||
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 651/779 x86/bus_lock: Dont assume the init value of DEBUGCTLMSR.BUS_LOCK_DETECT to be zero
In reply to Greg Kroah-HartmanFrom: Chenyi Qiang <[email protected]>
[ Upstream commit ffa6482e461ff550325356ae705b79e256702ea9 ]
It's possible that this kernel has been kexec'd from a kernel that enabled bus lock detection, or (hypothetically) BIOS/firmware has set DEBUGCTLMSR_BUS_LOCK_DETECT.
Disable bus lock detection explicitly if not wanted.
--- arch/x86/kernel/cpu/intel.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-)
arch/x86/kernel/cpu/intel.c +14 -13
@@ -1145,22 +1145,23 @@ static void bus_lock_init(void) {u64 val; -/* -* Warn and fatal are handled by #AC for split lock if #AC for -* split lock is supported. -*/ -if (!boot_cpu_has (X86_FEATURE_BUS_LOCK_DETECT ) || - (boot_cpu_has (X86_FEATURE_SPLIT_LOCK_DETECT ) && - (sld_state == sld_warn || sld_state == sld_fatal)) || - sld_state == sld_off) +if (!boot_cpu_has (X86_FEATURE_BUS_LOCK_DETECT ))return ; -/* -* Enable #DB for bus lock. All bus locks are handled in #DB except -* split locks are handled in #AC in the fatal case. -*/ rdmsrl (MSR_IA32_DEBUGCTLMSR , val); - val |=DEBUGCTLMSR_BUS_LOCK_DETECT ; + +if ((boot_cpu_has (X86_FEATURE_SPLIT_LOCK_DETECT ) && + (sld_state == sld_warn || sld_state == sld_fatal)) || + sld_state == sld_off) { +/* +* Warn and fatal are handled by #AC for split lock if #AC for +* split lock is supported. +*/ + val &= ~DEBUGCTLMSR_BUS_LOCK_DETECT ; + }else { + val |=DEBUGCTLMSR_BUS_LOCK_DETECT ; + } +wrmsrl (MSR_IA32_DEBUGCTLMSR , val); }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 652/779 powerpc/pci: Fix PHB numbering when using opal-phbid
In reply to Greg Kroah-HartmanFrom: Michael Ellerman <[email protected]>
[ Upstream commit f4b39e88b42d13366b831270306326b5c20971ca ]
The recent change to the PHB numbering logic has a logic error in the handling of "ibm,opal-phbid".
When an "ibm,opal-phbid" property is present, &prop is written to and ret is set to zero.
The following call to of_alias_get_id() is skipped because ret == 0.
But then the if (ret >= 0) is true, and the body of that if statement sets prop = ret which throws away the value that was just read from "ibm,opal-phbid".
Fix the logic by only doing the ret >= 0 check in the of_alias_get_id() case.
--- arch/powerpc/kernel/pci-common.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
arch/powerpc/kernel/pci-common.c +6 -4
@@ -90,11 +90,13 @@ static int get_phb_number(struct device_node *dn) }if (ret) ret =of_property_read_u64 (dn,"ibm,opal-phbid" , &prop); -if (ret) + +if (ret) { ret =of_alias_get_id (dn,"pci" ); -if (ret >=0 ) { - prop = ret; - ret =0 ; +if (ret >=0 ) { + prop = ret; + ret =0 ; + } }if (ret) {u32 prop_32;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 653/779 genelf: Use HAVE_LIBCRYPTO_SUPPORT, not the never defined HAVE_LIBCRYPTO
In reply to Greg Kroah-HartmanFrom: Arnaldo Carvalho de Melo <[email protected]>
[ Upstream commit 91cea6be90e436c55cde8770a15e4dac9d3032d0 ]
When genelf was introduced it tested for HAVE_LIBCRYPTO not HAVE_LIBCRYPTO_SUPPORT, which is the define the feature test for openssl defines, fix it.
This also adds disables the deprecation warning, someone has to fix this to build with openssl 3.0 before the warning becomes a hard error.
--- tools/perf/util/genelf.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
tools/perf/util/genelf.c +5 -1
@@ -30,7 +30,11 @@#define BUILD_ID_URANDOM /* different uuid for each run */ -#ifdef HAVE_LIBCRYPTO +// FIXME, remove this and fix the deprecation warnings before its removed and +// We'll break for good here... +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + +#ifdef HAVE_LIBCRYPTO_SUPPORT #define BUILD_ID_MD5 #undef BUILD_ID_SHA/* does not seem to work well when linked with Java */
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 654/779 scripts/faddr2line: Fix vmlinux detection on arm64
In reply to Greg Kroah-HartmanFrom: Josh Poimboeuf <[email protected]>
[ Upstream commit b6a5068854cfe372da7dee3224dcf023ed5b00cb ]
Since commit dcea997beed6 ("faddr2line: Fix overlapping text section failures, the sequel"), faddr2line is completely broken on arm64.
For some reason, on arm64, the vmlinux ELF object file type is ET_DYN rather than ET_EXEC. Check for both when determining whether the object is vmlinux.
Modules and vmlinux.o have type ET_REL on all arches.
--- scripts/faddr2line | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
scripts/faddr2line +3 -1
@@ -112,7 +112,9 @@ __faddr2line() { # section offsets. local file_type=$(${READELF} --file-header $objfile | ${AWK} '$1 == "Type:" { print $2; exit }') - [[ $file_type = "EXEC" ]] && is_vmlinux=1 + if [[ $file_type = "EXEC" ]] || [[ $file_type == "DYN" ]]; then + is_vmlinux=1 + fi # Go through each of the object's symbols which match the func name. # In rare cases there might be duplicates, in which case we print all
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 655/779 sched/deadline: Merge dl_task_can_attach() and dl_cpu_busy()
In reply to Greg Kroah-HartmanFrom: Dietmar Eggemann <[email protected]>
[ Upstream commit 772b6539fdda31462cc08368e78df60b31a58bab ]
Both functions are doing almost the same, that is checking if admission control is still respected.
With exclusive cpusets, dl_task_can_attach() checks if the destination cpuset (i.e. its root domain) has enough CPU capacity to accommodate the task.dl_cpu_busy() checks if there is enough CPU capacity in the cpuset in case the CPU is hot-plugged out.
dl_task_can_attach() is used to check if a task can be admitted while dl_cpu_busy() is used to check if a CPU can be hotplugged out.
Make dl_cpu_busy() able to deal with a task and use it instead of dl_task_can_attach() in task_can_attach().
--- kernel/sched/core.c | 13 +++++++---- kernel/sched/deadline.c | 52 +++++++++++------------------------------ kernel/sched/sched.h | 3 +-- 3 files changed, 24 insertions(+), 44 deletions(-)
kernel/sched/core.c +9 -4
@@ -8760,8 +8760,11 @@ int task_can_attach(struct task_struct *p, }if (dl_task (p) && !cpumask_intersects (task_rq (p)->rd->span, - cs_cpus_allowed)) - ret =dl_task_can_attach (p, cs_cpus_allowed); + cs_cpus_allowed)) { +int cpu =cpumask_any_and (cpu_active_mask, cs_cpus_allowed); + + ret =dl_cpu_busy (cpu, p); + } out:return ret;
@@ -9045,8 +9048,10 @@ static void cpuset_cpu_active(void)static int cpuset_cpu_inactive (unsigned int cpu) {if (!cpuhp_tasks_frozen) { -if (dl_cpu_busy (cpu)) -return -EBUSY ; +int ret =dl_cpu_busy (cpu,NULL ); + +if (ret) +return ret;cpuset_update_active_cpus (); }else { num_cpus_frozen++;
kernel/sched/deadline.c +14 -38
73 lines not on this page · raw message
kernel/sched/sched.h +1 -2
@@ -348,9 +348,8 @@ extern void __setparam_dl(struct task_struct *p, const struct sched_attr *attr);extern void __getparam_dl (struct task_struct *p,struct sched_attr *attr);extern bool __checkparam_dl (const struct sched_attr *attr);extern bool dl_param_changed (struct task_struct *p,const struct sched_attr *attr); -extern int dl_task_can_attach (struct task_struct *p,const struct cpumask *cs_cpus_allowed);extern int dl_cpuset_cpumask_can_shrink (const struct cpumask *cur,const struct cpumask *trial); -extern bool dl_cpu_busy (unsigned int cpu); +extern int dl_cpu_busy (int cpu,struct task_struct *p);#ifdef CONFIG_CGROUP_SCHED
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 656/779 sched, cpuset: Fix dl_cpu_busy() panic due to empty cs->cpus_allowed
In reply to Greg Kroah-HartmanFrom: Waiman Long <[email protected]>
[ Upstream commit b6e8d40d43ae4dec00c8fea2593eeea3114b8f44 ]
With cgroup v2, the cpuset's cpus_allowed mask can be empty indicating that the cpuset will just use the effective CPUs of its parent. So cpuset_can_attach() can call task_can_attach() with an empty mask. This can lead to cpumask_any_and() returns nr_cpu_ids causing the call to dl_bw_of() to crash due to percpu value access of an out of bound CPU value. For example:
[80468.182258] BUG: unable to handle page fault for address: ffffffff8b6648b0 : [80468.191019] RIP: 0010:dl_cpu_busy+0x30/0x2b0 : [80468.207946] Call Trace: [80468.208947] cpuset_can_attach+0xa0/0x140 [80468.209953] cgroup_migrate_execute+0x8c/0x490 [80468.210931] cgroup_update_dfl_csses+0x254/0x270 [80468.211898] cgroup_subtree_control_write+0x322/0x400 [80468.212854] kernfs_fop_write_iter+0x11c/0x1b0 [80468.213777] new_sync_write+0x11f/0x1b0 [80468.214689] vfs_write+0x1eb/0x280 [80468.215592] ksys_write+0x5f/0xe0 [80468.216463] do_syscall_64+0x5c/0x80 [80468.224287] entry_SYSCALL_64_after_hwframe+0x44/0xae
Fix that by using effective_cpus instead. For cgroup v1, effective_cpus is the same as cpus_allowed. For v2, effective_cpus is the real cpumask to be used by tasks within the cpuset anyway.
Also update task_can_attach()'s 2nd argument name to cs_effective_cpus to reflect the change. In addition, a check is added to task_can_attach() to guard against the possibility that cpumask_any_and() may return a value >= nr_cpu_ids.
--- include/linux/sched.h | 2 +- kernel/cgroup/cpuset.c | 2 +- kernel/sched/core.c | 8 +++++--- 3 files changed, 7 insertions(+), 5 deletions(-)
include/linux/sched.h +1 -1
@@ -1797,7 +1797,7 @@ current_restore_flags(unsigned long orig_flags, unsigned long flags) }extern int cpuset_cpumask_can_shrink (const struct cpumask *cur,const struct cpumask *trial); -extern int task_can_attach (struct task_struct *p,const struct cpumask *cs_cpus_allowed); +extern int task_can_attach (struct task_struct *p,const struct cpumask *cs_effective_cpus);#ifdef CONFIG_SMP extern void do_set_cpus_allowed (struct task_struct *p,const struct cpumask *new_mask);extern int set_cpus_allowed_ptr (struct task_struct *p,const struct cpumask *new_mask);
kernel/cgroup/cpuset.c +1 -1
@@ -2199,7 +2199,7 @@ static int cpuset_can_attach(struct cgroup_taskset *tset) goto out_unlock;cgroup_taskset_for_each (task, css, tset) { - ret =task_can_attach (task, cs->cpus_allowed); + ret =task_can_attach (task, cs->effective_cpus);if (ret) goto out_unlock; ret =security_task_setscheduler (task);
kernel/sched/core.c +5 -3
@@ -8741,7 +8741,7 @@ int cpuset_cpumask_can_shrink(const struct cpumask *cur, }int task_can_attach (struct task_struct *p, -const struct cpumask *cs_cpus_allowed) +const struct cpumask *cs_effective_cpus) {int ret =0 ;
@@ -8760,9 +8760,11 @@ int task_can_attach(struct task_struct *p, }if (dl_task (p) && !cpumask_intersects (task_rq (p)->rd->span, - cs_cpus_allowed)) { -int cpu =cpumask_any_and (cpu_active_mask, cs_cpus_allowed); + cs_effective_cpus)) { +int cpu =cpumask_any_and (cpu_active_mask, cs_effective_cpus); +if (unlikely (cpu >= nr_cpu_ids)) +return -EINVAL ; ret =dl_cpu_busy (cpu, p); }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 657/779 x86/numa: Use cpumask_available instead of hardcoded NULL check
In reply to Greg Kroah-HartmanFrom: Siddh Raman Pant <[email protected]>
[ Upstream commit 625395c4a0f4775e0fe00f616888d2e6c1ba49db ]
GCC-12 started triggering a new warning:
arch/x86/mm/numa.c: In function ‘cpumask_of_node’:
arch/x86/mm/numa.c:916:39: warning: the comparison will always evaluate as ‘false’ for the address of ‘node_to_cpumask_map’ will never be NULL [-Waddress]
916 | if (node_to_cpumask_map[node] == NULL) {
| ^~node_to_cpumask_map is of type cpumask_var_t[].
When CONFIG_CPUMASK_OFFSTACK is set, cpumask_var_t is typedef'd to a pointer for dynamic allocation, else to an array of one element. The "wicked game" can be checked on line 700 of include/linux/cpumask.h.
The original code in debug_cpumask_set_cpu() and cpumask_of_node() were probably written by the original authors with CONFIG_CPUMASK_OFFSTACK=y (i.e. dynamic allocation) in mind, checking if the cpumask was available via a direct NULL check.
When CONFIG_CPUMASK_OFFSTACK is not set, GCC gives the above warning while compiling the kernel.
Fix that by using cpumask_available(), which does the NULL check when CONFIG_CPUMASK_OFFSTACK is set, otherwise returns true. Use it wherever such checks are made.
Conditional definitions of cpumask_available() can be found along with the definition of cpumask_var_t. Check the cpumask.h reference mentioned above.
--- arch/x86/mm/numa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/mm/numa.c +2 -2
@@ -860,7 +860,7 @@ void debug_cpumask_set_cpu(int cpu, int node, bool enable)return ; } mask = node_to_cpumask_map[node]; -if (!mask) { +if (!cpumask_available (mask)) {pr_err ("node_to_cpumask_map[%i] NULL\n" , node);dump_stack ();return ;
@@ -906,7 +906,7 @@ const struct cpumask *cpumask_of_node(int node)dump_stack ();return cpu_none_mask; } -if (node_to_cpumask_map[node] ==NULL ) { +if (!cpumask_available (node_to_cpumask_map[node])) {printk (KERN_WARNING "cpumask_of_node(%d): no node_to_cpumask_map!\n" , node);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 658/779 video: fbdev: arkfb: Fix a divide-by-zero bug in ark_set_pixclock()
In reply to Greg Kroah-HartmanFrom: Zheyu Ma <[email protected]>
[ Upstream commit 2f1c4523f7a3aaabe7e53d3ebd378292947e95c8 ]
Since the user can control the arguments of the ioctl() from the user
space, under special arguments that may result in a divide-by-zero bug
in:
drivers/video/fbdev/arkfb.c:784: ark_set_pixclock(info, (hdiv * info->var.pixclock) / hmul);
with hdiv=1, pixclock=1 and hmul=2 you end up with (1*1)/2 = (int) 0.
and then in:
drivers/video/fbdev/arkfb.c:504: rv = dac_set_freq(par->dac, 0, 1000000000 / pixclock);
we'll get a division-by-zero.
The following log can reveal it:
divide error: 0000 [#1] PREEMPT SMP KASAN PTI
RIP: 0010:ark_set_pixclock drivers/video/fbdev/arkfb.c:504 [inline] RIP: 0010:arkfb_set_par+0x10fc/0x24c0 drivers/video/fbdev/arkfb.c:784 Call Trace: fb_set_var+0x604/0xeb0 drivers/video/fbdev/core/fbmem.c:1034 do_fb_ioctl+0x234/0x670 drivers/video/fbdev/core/fbmem.c:1110 fb_ioctl+0xdd/0x130 drivers/video/fbdev/core/fbmem.c:1189
Fix this by checking the argument of ark_set_pixclock() first.
--- drivers/video/fbdev/arkfb.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/video/fbdev/arkfb.c +6 -1
@@ -778,7 +778,12 @@ static int arkfb_set_par(struct fb_info *info)return -EINVAL ; } -ark_set_pixclock (info, (hdiv * info->var.pixclock) / hmul); + value = (hdiv * info->var.pixclock) / hmul; +if (!value) { +fb_dbg (info,"invalid pixclock\n" ); + value =1 ; + } +ark_set_pixclock (info, value); svga_set_timings(par->state.vgabase, &ark_timing_regs, &(info->var), hmul, hdiv, (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1,
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 659/779 tools/thermal: Fix possible path truncations
In reply to Greg Kroah-HartmanFrom: Florian Fainelli <[email protected]>
[ Upstream commit 6c58cf40e3a1d2f47c09d3489857e9476316788a ]
A build with -D_FORTIFY_SOURCE=2 enabled will produce the following warnings:
sysfs.c:63:30: warning: '%s' directive output may be truncated writing up to 255 bytes into a region of size between 0 and 255 [-Wformat-truncation=]
snprintf(filepath, 256, "%s/%s", path, filename);
^~Bump up the buffer to PATH_MAX which is the limit and account for all of the possible NUL and separators that could lead to exceeding the allocated buffer sizes.
--- tools/thermal/tmon/sysfs.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-)
tools/thermal/tmon/sysfs.c +13 -11
@@ -13,6 +13,7 @@#include <stdint.h> #include <dirent.h> #include <libintl.h> +#include <limits.h> #include <ctype.h> #include <time.h> #include <syslog.h>
@@ -33,9 +34,9 @@ int sysfs_set_ulong(char *path, char *filename, unsigned long val) {FILE *fd;int ret =-1 ; -char filepath[256 ]; +char filepath[PATH_MAX +2 ];/* NUL and '/' */ -snprintf (filepath,256 ,"%s/%s" , path, filename); +snprintf (filepath,sizeof (filepath),"%s/%s" , path, filename); fd =fopen (filepath,"w" );if (!fd) {
@@ -57,9 +58,9 @@ static int sysfs_get_ulong(char *path, char *filename, unsigned long *p_ulong) {FILE *fd;int ret =-1 ; -char filepath[256 ]; +char filepath[PATH_MAX +2 ];/* NUL and '/' */ -snprintf (filepath,256 ,"%s/%s" , path, filename); +snprintf (filepath,sizeof (filepath),"%s/%s" , path, filename); fd =fopen (filepath,"r" );if (!fd) {
@@ -76,9 +77,9 @@ static int sysfs_get_string(char *path, char *filename, char *str) {FILE *fd;int ret =-1 ; -char filepath[256 ]; +char filepath[PATH_MAX +2 ];/* NUL and '/' */ -snprintf (filepath,256 ,"%s/%s" , path, filename); +snprintf (filepath,sizeof (filepath),"%s/%s" , path, filename); fd =fopen (filepath,"r" );if (!fd) {
@@ -199,8 +200,8 @@ static int find_tzone_cdev(struct dirent *nl, char *tz_name, {unsigned long trip_instance =0 ;char cdev_name_linked[256 ]; -char cdev_name[256 ]; -char cdev_trip_name[256 ]; +char cdev_name[PATH_MAX ]; +char cdev_trip_name[PATH_MAX ];int cdev_id;if (nl->d_type ==DT_LNK ) {
@@ -213,7 +214,8 @@ static int find_tzone_cdev(struct dirent *nl, char *tz_name,return -EINVAL ; }/* find the link to real cooling device record binding */ -snprintf (cdev_name,256 ,"%s/%s" , tz_name, nl->d_name); +snprintf (cdev_name,sizeof (cdev_name) -2 ,"%s/%s" , + tz_name, nl->d_name);memset (cdev_name_linked,0 ,sizeof (cdev_name_linked));if (readlink (cdev_name, cdev_name_linked,sizeof (cdev_name_linked) -1 ) !=-1 ) {
@@ -226,8 +228,8 @@ static int find_tzone_cdev(struct dirent *nl, char *tz_name,/* find the trip point in which the cdev is binded to * in this tzone */ -snprintf (cdev_trip_name,256 ,"%s%s" , nl->d_name, -"_trip_point" ); +snprintf (cdev_trip_name,sizeof (cdev_trip_name) -1 , +"%s%s" , nl->d_name,"_trip_point" );sysfs_get_ulong (tz_name, cdev_trip_name, &trip_instance);/* validate trip point range, e.g. trip could return -1
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 660/779 sched: Fix the check of nr_running at queue wakelist
In reply to Greg Kroah-HartmanFrom: Tianchen Ding <[email protected]>
[ Upstream commit 28156108fecb1f808b21d216e8ea8f0d205a530c ]
The commit 2ebb17717550 ("sched/core: Offload wakee task activation if it the wakee is descheduling") checked rq->nr_running <= 1 to avoid task stacking when WF_ON_CPU.
Per the ordering of writes to p->on_rq and p->on_cpu, observing p->on_cpu (WF_ON_CPU) in ttwu_queue_cond() implies !p->on_rq, IOW p has gone through the deactivate_task() in __schedule(), thus p has been accounted out of rq->nr_running. As such, the task being the only runnable task on the rq implies reading rq->nr_running == 0 at that point.
The benchmark result is in [1].
[1] https://lore.kernel.org/all/[email protected]/
--- kernel/sched/core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
kernel/sched/core.c +5 -1
@@ -3735,8 +3735,12 @@ static inline bool ttwu_queue_cond(int cpu, int wake_flags)* CPU then use the wakelist to offload the task activation to * the soon-to-be-idle CPU as the current CPU is likely busy. * nr_running is checked to avoid unnecessary task stacking. +* +* Note that we can only get here with (wakee) p->on_rq=0, +* p->on_cpu can be whatever, we've done the dequeue, so +* the wakee has been accounted out of ->nr_running. */ -if ((wake_flags &WF_ON_CPU ) &&cpu_rq (cpu)->nr_running <=1 ) +if ((wake_flags &WF_ON_CPU ) && !cpu_rq (cpu)->nr_running)return true;return false;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 661/779 sched: Remove the limitation of WF_ON_CPU on wakelist if wakee cpu is idle
In reply to Greg Kroah-HartmanFrom: Tianchen Ding <[email protected]>
[ Upstream commit f3dd3f674555bd9455c5ae7fafce0696bd9931b3 ]
Wakelist can help avoid cache bouncing and offload the overhead of waker cpu. So far, using wakelist within the same llc only happens on WF_ON_CPU, and this limitation could be removed to further improve wakeup performance.
The commit 518cd6234178 ("sched: Only queue remote wakeups when crossing cache boundaries") disabled queuing tasks on wakelist when the cpus share llc. This is because, at that time, the scheduler must send IPIs to do ttwu_queue_wakelist. Nowadays, ttwu_queue_wakelist also supports TIF_POLLING, so this is not a problem now when the wakee cpu is in idle polling.
Benefits:
Queuing the task on idle cpu can help improving performance on waker cpu and utilization on wakee cpu, and further improve locality because the wakee cpu can handle its own rq. This patch helps improving rt on our real java workloads where wakeup happens frequently.
Consider the normal condition (CPU0 and CPU1 share same llc) Before this patch:
CPU0 CPU1
select_task_rq() idle
rq_lock(CPU1->rq)
enqueue_task(CPU1->rq)
notify CPU1 (by sending IPI or CPU1 polling)
resched()After this patch:
CPU0 CPU1
select_task_rq() idle
add to wakelist of CPU1
notify CPU1 (by sending IPI or CPU1 polling)
rq_lock(CPU1->rq) enqueue_task(CPU1->rq) resched()
We see CPU0 can finish its work earlier. It only needs to put task to wakelist and return.
While CPU1 is idle, so let itself handle its own runqueue data.
This patch brings no difference about IPI.
This patch only takes effect when the wakee cpu is:
1) idle polling
2) idle not polling
For 1), there will be no IPI with or without this patch.
For 2), there will always be an IPI before or after this patch. Before this patch: waker cpu will enqueue task and check preempt. Since "idle" will be sure to be preempted, waker cpu must send a resched IPI. After this patch: waker cpu will put the task to the wakelist of wakee cpu, and send an IPI.
Benchmark:
We've tested schbench, unixbench, and hachbench on both x86 and arm64.
On x86 (Intel Xeon Platinum 8269CY):
schbench -m 2 -t 8
Latency percentiles (usec) before after
50.0000th: 8 6
75.0000th: 10 7
90.0000th: 11 8
95.0000th: 12 8
*99.0000th: 13 10
99.5000th: 15 11
99.9000th: 18 14
Unixbench with full threads (104)
before after
Dhrystone 2 using register variables 3011862938 3009935994 -0.06%
Double-Precision Whetstone 617119.3 617298.5 0.03%
Execl Throughput 27667.3 27627.3 -0.14%
File Copy 1024 bufsize 2000 maxblocks 785871.4 784906.2 -0.12%
File Copy 256 bufsize 500 maxblocks 210113.6 212635.4 1.20%
File Copy 4096 bufsize 8000 maxblocks 2328862.2 2320529.1 -0.36%
Pipe Throughput 145535622.8 145323033.2 -0.15%
Pipe-based Context Switching 3221686.4 3583975.4 11.25%
Process Creation 101347.1 103345.4 1.97%
Shell Scripts (1 concurrent) 120193.5 123977.8 3.15%
Shell Scripts (8 concurrent) 17233.4 17138.4 -0.55%
System Call Overhead 5300604.8 5312213.6 0.22% hackbench -g 1 -l 100000
before after
Time 3.246 2.251
On arm64 (Ampere Altra):
schbench -m 2 -t 8
Latency percentiles (usec) before after
50.0000th: 14 10
75.0000th: 19 14
90.0000th: 22 16
95.0000th: 23 16
*99.0000th: 24 17
99.5000th: 24 17
99.9000th: 28 25
Unixbench with full threads (80)
before after
Dhrystone 2 using register variables 3536194249 3537019613 0.02%
Double-Precision Whetstone 629383.6 629431.6 0.01%
Execl Throughput 65920.5 65846.2 -0.11%
File Copy 1024 bufsize 2000 maxblocks 1063722.8 1064026.8 0.03%
File Copy 256 bufsize 500 maxblocks 322684.5 318724.5 -1.23%
File Copy 4096 bufsize 8000 maxblocks 2348285.3 2328804.8 -0.83%
Pipe Throughput 133542875.3 131619389.8 -1.44%
Pipe-based Context Switching 3215356.1 3576945.1 11.25%
Process Creation 108520.5 120184.6 10.75%
Shell Scripts (1 concurrent) 122636.3 121888 -0.61%
Shell Scripts (8 concurrent) 17462.1 17381.4 -0.46%
System Call Overhead 4429998.9 4435006.7 0.11% hackbench -g 1 -l 100000
before after
Time 4.217 2.916
Our patch has improvement on schbench, hackbench
and Pipe-based Context Switching of unixbench
when there exists idle cpus,
and no obvious regression on other tests of unixbench. This can help improve rt in scenes where wakeup happens frequently.
--- kernel/sched/core.c | 26 ++++++++++++++------------ kernel/sched/sched.h | 1 - 2 files changed, 14 insertions(+), 13 deletions(-)
kernel/sched/core.c +14 -12
@@ -3714,7 +3714,7 @@ bool cpus_share_cache(int this_cpu, int that_cpu)return per_cpu (sd_llc_id, this_cpu) ==per_cpu (sd_llc_id, that_cpu); } -static inline bool ttwu_queue_cond (int cpu,int wake_flags) +static inline bool ttwu_queue_cond (int cpu) {/* * Do not complicate things with the async wake_list while the CPU is
@@ -3730,17 +3730,21 @@ static inline bool ttwu_queue_cond(int cpu, int wake_flags)if (!cpus_share_cache (smp_processor_id (), cpu))return true; +if (cpu ==smp_processor_id ()) +return false; +/* -* If the task is descheduling and the only running task on the -* CPU then use the wakelist to offload the task activation to -* the soon-to-be-idle CPU as the current CPU is likely busy. -* nr_running is checked to avoid unnecessary task stacking. +* If the wakee cpu is idle, or the task is descheduling and the +* only running task on the CPU, then use the wakelist to offload +* the task activation to the idle (or soon-to-be-idle) CPU as +* the current CPU is likely busy. nr_running is checked to +* avoid unnecessary task stacking. * * Note that we can only get here with (wakee) p->on_rq=0, * p->on_cpu can be whatever, we've done the dequeue, so * the wakee has been accounted out of ->nr_running. */ -if ((wake_flags &WF_ON_CPU ) && !cpu_rq (cpu)->nr_running) +if (!cpu_rq (cpu)->nr_running)return true;return false;
@@ -3748,10 +3752,7 @@ static inline bool ttwu_queue_cond(int cpu, int wake_flags)static bool ttwu_queue_wakelist (struct task_struct *p,int cpu,int wake_flags) { -if (sched_feat (TTWU_QUEUE ) &&ttwu_queue_cond (cpu, wake_flags)) { -if (WARN_ON_ONCE (cpu ==smp_processor_id ())) -return false; - +if (sched_feat (TTWU_QUEUE ) &&ttwu_queue_cond (cpu)) {sched_clock_cpu (cpu);/* Sync clocks across CPUs */ __ttwu_queue_wakelist (p, cpu, wake_flags);return true;
@@ -4073,7 +4074,7 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)* scheduling. */ if (smp_load_acquire (&p->on_cpu) && -ttwu_queue_wakelist (p,task_cpu (p), wake_flags |WF_ON_CPU )) +ttwu_queue_wakelist (p,task_cpu (p), wake_flags)) goto unlock;/*
@@ -4589,7 +4590,8 @@ static inline void prepare_task(struct task_struct *next)* Claim the task as running, we do this before switching to it * such that any running task will have this set. * -* See the ttwu() WF_ON_CPU case and its ordering comment. +* See the smp_load_acquire(&p->on_cpu) case in ttwu() and +* its ordering comment. */ WRITE_ONCE (next->on_cpu,1 );#endif
kernel/sched/sched.h +0 -1
@@ -2052,7 +2052,6 @@ static inline int task_on_rq_migrating(struct task_struct *p)#define WF_SYNC 0x10/* Waker goes to sleep after wakeup */ #define WF_MIGRATED 0x20/* Internal use, task got migrated */ -#define WF_ON_CPU 0x40/* Wakee is on_cpu */ #ifdef CONFIG_SMP static_assert (WF_EXEC ==SD_BALANCE_EXEC );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 662/779 sched/core: Do not requeue task on CPU excluded from cpus_mask
In reply to Greg Kroah-HartmanFrom: Mel Gorman <[email protected]>
[ Upstream commit 751d4cbc43879229dbc124afefe240b70fd29a85 ]
The following warning was triggered on a large machine early in boot on a distribution kernel but the same problem should also affect mainline.
WARNING: CPU: 439 PID: 10 at ../kernel/workqueue.c:2231 process_one_work+0x4d/0x440
Call Trace:
<TASK>
rescuer_thread+0x1f6/0x360
kthread+0x156/0x180
ret_from_fork+0x22/0x30
</TASK>Commit c6e7bd7afaeb ("sched/core: Optimize ttwu() spinning on p->on_cpu") optimises ttwu by queueing a task that is descheduling on the wakelist, but does not check if the task descheduling is still allowed to run on that CPU.
In this warning, the problematic task is a workqueue rescue thread which checks if the rescue is for a per-cpu workqueue and running on the wrong CPU. While this is early in boot and it should be possible to create workers, the rescue thread may still used if the MAYDAY_INITIAL_TIMEOUT is reached or MAYDAY_INTERVAL and on a sufficiently large machine, the rescue thread is being used frequently.
Tracing confirmed that the task should have migrated properly using the stopper thread to handle the migration. However, a parallel wakeup from udev running on another CPU that does not share CPU cache observes p->on_cpu and uses task_cpu(p), queues the task on the old CPU and triggers the warning.
Check that the wakee task that is descheduling is still allowed to run on its current CPU and if not, wait for the descheduling to complete and select an allowed CPU.
--- kernel/sched/core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
kernel/sched/core.c +6 -2
@@ -3714,7 +3714,7 @@ bool cpus_share_cache(int this_cpu, int that_cpu)return per_cpu (sd_llc_id, this_cpu) ==per_cpu (sd_llc_id, that_cpu); } -static inline bool ttwu_queue_cond (int cpu) +static inline bool ttwu_queue_cond (struct task_struct *p,int cpu) {/* * Do not complicate things with the async wake_list while the CPU is
@@ -3723,6 +3723,10 @@ static inline bool ttwu_queue_cond(int cpu)if (!cpu_active (cpu))return false; +/* Ensure the task will still be allowed to run on the CPU. */ +if (!cpumask_test_cpu (cpu, p->cpus_ptr)) +return false; +/* * If the CPU does not share cache, then queue the task on the * remote rqs wakelist to avoid accessing remote data.
@@ -3752,7 +3756,7 @@ static inline bool ttwu_queue_cond(int cpu)static bool ttwu_queue_wakelist (struct task_struct *p,int cpu,int wake_flags) { -if (sched_feat (TTWU_QUEUE ) &&ttwu_queue_cond (cpu)) { +if (sched_feat (TTWU_QUEUE ) &&ttwu_queue_cond (p, cpu)) {sched_clock_cpu (cpu);/* Sync clocks across CPUs */ __ttwu_queue_wakelist (p, cpu, wake_flags);return true;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 663/779 x86/entry: Build thunk_$(BITS) only if CONFIG_PREEMPTION=y
In reply to Greg Kroah-HartmanFrom: Andrea Righi <[email protected]>
[ Upstream commit de979c83574abf6e78f3fa65b716515c91b2613d ]
With CONFIG_PREEMPTION disabled, arch/x86/entry/thunk_$(BITS).o becomes an empty object file.
With some old versions of binutils (i.e., 2.35.90.20210113-1ubuntu1) the GNU assembler doesn't generate a symbol table for empty object files and objtool fails with the following error when a valid symbol table cannot be found:
arch/x86/entry/thunk_64.o: warning: objtool: missing symbol table
To prevent this from happening, build thunk_$(BITS).o only if CONFIG_PREEMPTION is enabled.
--- arch/x86/entry/Makefile | 3 ++- arch/x86/entry/thunk_32.S | 2 -- arch/x86/entry/thunk_64.S | 4 ---- arch/x86/um/Makefile | 3 ++- 4 files changed, 4 insertions(+), 8 deletions(-)
arch/x86/entry/Makefile +2 -1
@@ -11,12 +11,13 @@ CFLAGS_REMOVE_common.o = $(CC_FLAGS_FTRACE) CFLAGS_common.o += -fno-stack-protector -obj-y := entry.o entry_$(BITS).o thunk_$(BITS).o syscall_$(BITS).o +obj-y := entry.o entry_$(BITS).o syscall_$(BITS).o obj-y += common.o obj-y += vdso/ obj-y += vsyscall/ +obj-$(CONFIG_PREEMPTION) += thunk_$(BITS).o obj-$(CONFIG_IA32_EMULATION) += entry_64_compat.o syscall_32.o obj-$(CONFIG_X86_X32_ABI) += syscall_x32.o
arch/x86/entry/thunk_32.S +0 -2
@@ -29,10 +29,8 @@ SYM_CODE_START_NOALIGN(\name) SYM_CODE_END(\name) .endm -#ifdef CONFIG_PREEMPTION THUNK preempt_schedule_thunk, preempt_schedule THUNK preempt_schedule_notrace_thunk, preempt_schedule_notrace EXPORT_SYMBOL(preempt_schedule_thunk) EXPORT_SYMBOL(preempt_schedule_notrace_thunk) -#endif
arch/x86/entry/thunk_64.S +0 -4
@@ -31,14 +31,11 @@ SYM_FUNC_END(\name) _ASM_NOKPROBE(\name) .endm -#ifdef CONFIG_PREEMPTION THUNK preempt_schedule_thunk, preempt_schedule THUNK preempt_schedule_notrace_thunk, preempt_schedule_notrace EXPORT_SYMBOL(preempt_schedule_thunk) EXPORT_SYMBOL(preempt_schedule_notrace_thunk) -#endif -#ifdef CONFIG_PREEMPTION SYM_CODE_START_LOCAL_NOALIGN(__thunk_restore) popq %r11 popq %r10
@@ -53,4 +50,3 @@ SYM_CODE_START_LOCAL_NOALIGN(__thunk_restore) RET _ASM_NOKPROBE(__thunk_restore) SYM_CODE_END(__thunk_restore) -#endif
arch/x86/um/Makefile +2 -1
@@ -28,7 +28,8 @@ else obj-y += syscalls_64.o vdso/ -subarch-y = ../lib/csum-partial_64.o ../lib/memcpy_64.o ../entry/thunk_64.o +subarch-y = ../lib/csum-partial_64.o ../lib/memcpy_64.o +subarch-$(CONFIG_PREEMPTION) += ../entry/thunk_64.o endif
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 664/779 f2fs: allow compression for mmap files in compress_mode=user
In reply to Greg Kroah-HartmanFrom: Sungjong Seo <[email protected]>
[ Upstream commit 66d34fcbbe63ebd8584b792e0d741f6648100894 ]
Since commit e3c548323d32 ("f2fs: let's allow compression for mmap files"), it has been allowed to compress mmap files. However, in compress_mode=user, it is not allowed yet. To keep the same concept in both compress_modes, f2fs_ioc_(de)compress_file() should also allow it.
Let's remove checking mmap files in f2fs_ioc_(de)compress_file() so that the compression for mmap files is also allowed in compress_mode=user.
--- fs/f2fs/file.c | 10 ---------- 1 file changed, 10 deletions(-)
fs/f2fs/file.c +0 -10
@@ -4011,11 +4011,6 @@ static int f2fs_ioc_decompress_file(struct file *filp, unsigned long arg) goto out; } -if (f2fs_is_mmap_file (inode)) { - ret = -EBUSY ; - goto out; - } - ret =filemap_write_and_wait_range (inode->i_mapping,0 ,LLONG_MAX );if (ret) goto out;
@@ -4083,11 +4078,6 @@ static int f2fs_ioc_compress_file(struct file *filp, unsigned long arg) goto out; } -if (f2fs_is_mmap_file (inode)) { - ret = -EBUSY ; - goto out; - } - ret =filemap_write_and_wait_range (inode->i_mapping,0 ,LLONG_MAX );if (ret) goto out;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 665/779 f2fs: do not allow to decompress files have FI_COMPRESS_RELEASED
In reply to Greg Kroah-HartmanFrom: Jaewook Kim <[email protected]>
[ Upstream commit 90be48bd9d29ece3965e5e8b21499b6db166e57b ]
If a file has FI_COMPRESS_RELEASED, all writes for it should not be allowed. However, as of now, in case of compress_mode=user, writes triggered by IOCTLs like F2FS_IOC_DE/COMPRESS_FILE are allowed unexpectly, which could crash that file.
To fix it, let's do not allow F2FS_IOC_DE/COMPRESS_IOCTL if a file already has FI_COMPRESS_RELEASED flag.
This is the reproduction process:
1. $ touch ./file 2. $ chattr +c ./file 3. $ dd if=/dev/random of=./file bs=4096 count=30 conv=notrunc 4. $ dd if=/dev/zero of=./file bs=4096 count=34 seek=30 conv=notrunc 5. $ sync 6. $ do_compress ./file ; call F2FS_IOC_COMPRESS_FILE 7. $ get_compr_blocks ./file ; call F2FS_IOC_GET_COMPRESS_BLOCKS 8. $ release ./file ; call F2FS_IOC_RELEASE_COMPRESS_BLOCKS 9. $ do_compress ./file ; call F2FS_IOC_COMPRESS_FILE again
10. $ get_compr_blocks ./file ; call F2FS_IOC_GET_COMPRESS_BLOCKS again
This reproduction process is tested in 128kb cluster size. You can find compr_blocks has a negative value.
--- fs/f2fs/file.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
fs/f2fs/file.c +10 -0
@@ -4011,6 +4011,11 @@ static int f2fs_ioc_decompress_file(struct file *filp, unsigned long arg) goto out; } +if (is_inode_flag_set (inode,FI_COMPRESS_RELEASED )) { + ret = -EINVAL ; + goto out; + } + ret =filemap_write_and_wait_range (inode->i_mapping,0 ,LLONG_MAX );if (ret) goto out;
@@ -4078,6 +4083,11 @@ static int f2fs_ioc_compress_file(struct file *filp, unsigned long arg) goto out; } +if (is_inode_flag_set (inode,FI_COMPRESS_RELEASED )) { + ret = -EINVAL ; + goto out; + } + ret =filemap_write_and_wait_range (inode->i_mapping,0 ,LLONG_MAX );if (ret) goto out;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 666/779 video: fbdev: vt8623fb: Check the size of screen before memset_io()
In reply to Greg Kroah-HartmanFrom: Zheyu Ma <[email protected]>
[ Upstream commit ec0754c60217248fa77cc9005d66b2b55200ac06 ]
In the function vt8623fb_set_par(), the value of 'screen_size' is calculated by the user input. If the user provides the improper value, the value of 'screen_size' may larger than 'info->screen_size', which may cause the following bug:
[ 583.339036] BUG: unable to handle page fault for address: ffffc90005000000 [ 583.339049] #PF: supervisor write access in kernel mode [ 583.339052] #PF: error_code(0x0002) - not-present page [ 583.339074] RIP: 0010:memset_orig+0x33/0xb0 [ 583.339110] Call Trace: [ 583.339118] vt8623fb_set_par+0x11cd/0x21e0 [ 583.339146] fb_set_var+0x604/0xeb0 [ 583.339181] do_fb_ioctl+0x234/0x670 [ 583.339209] fb_ioctl+0xdd/0x130
Fix the this by checking the value of 'screen_size' before memset_io().
--- drivers/video/fbdev/vt8623fb.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/video/fbdev/vt8623fb.c +2 -0
@@ -504,6 +504,8 @@ static int vt8623fb_set_par(struct fb_info *info) (info->var.vmode &FB_VMODE_DOUBLE ) ?2 :1 ,1 , 1, info->node); +if (screen_size > info->screen_size) + screen_size = info->screen_size;memset_io (info->screen_base,0x00 , screen_size);/* Device and screen back on */
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 667/779 video: fbdev: arkfb: Check the size of screen before memset_io()
In reply to Greg Kroah-HartmanFrom: Zheyu Ma <[email protected]>
[ Upstream commit 96b550971c65d54d64728d8ba973487878a06454 ]
In the function arkfb_set_par(), the value of 'screen_size' is calculated by the user input. If the user provides the improper value, the value of 'screen_size' may larger than 'info->screen_size', which may cause the following bug:
[ 659.399066] BUG: unable to handle page fault for address: ffffc90003000000 [ 659.399077] #PF: supervisor write access in kernel mode [ 659.399079] #PF: error_code(0x0002) - not-present page [ 659.399094] RIP: 0010:memset_orig+0x33/0xb0 [ 659.399116] Call Trace: [ 659.399122] arkfb_set_par+0x143f/0x24c0 [ 659.399130] fb_set_var+0x604/0xeb0 [ 659.399161] do_fb_ioctl+0x234/0x670 [ 659.399189] fb_ioctl+0xdd/0x130
Fix the this by checking the value of 'screen_size' before memset_io().
--- drivers/video/fbdev/arkfb.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/video/fbdev/arkfb.c +2 -0
@@ -794,6 +794,8 @@ static int arkfb_set_par(struct fb_info *info) value = ((value * hmul / hdiv) /8 ) -5 ;vga_wcrt (par->state.vgabase,0x42 , (value +1 ) /2 ); +if (screen_size > info->screen_size) + screen_size = info->screen_size;memset_io (info->screen_base,0x00 , screen_size);/* Device and screen back on */ svga_wcrt_mask (par->state.vgabase,0x17 ,0x80 ,0x80 );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 668/779 video: fbdev: s3fb: Check the size of screen before memset_io()
In reply to Greg Kroah-HartmanFrom: Zheyu Ma <[email protected]>
[ Upstream commit 6ba592fa014f21f35a8ee8da4ca7b95a018f13e8 ]
In the function s3fb_set_par(), the value of 'screen_size' is calculated by the user input. If the user provides the improper value, the value of 'screen_size' may larger than 'info->screen_size', which may cause the following bug:
[ 54.083733] BUG: unable to handle page fault for address: ffffc90003000000 [ 54.083742] #PF: supervisor write access in kernel mode [ 54.083744] #PF: error_code(0x0002) - not-present page [ 54.083760] RIP: 0010:memset_orig+0x33/0xb0 [ 54.083782] Call Trace: [ 54.083788] s3fb_set_par+0x1ec6/0x4040 [ 54.083806] fb_set_var+0x604/0xeb0 [ 54.083836] do_fb_ioctl+0x234/0x670
Fix the this by checking the value of 'screen_size' before memset_io().
--- drivers/video/fbdev/s3fb.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/video/fbdev/s3fb.c +2 -0
@@ -902,6 +902,8 @@ static int s3fb_set_par(struct fb_info *info) value =clamp ((htotal + hsstart +1 ) /2 +2 , hsstart +4 , htotal +1 );svga_wcrt_multi (par->state.vgabase, s3_dtpc_regs, value); +if (screen_size > info->screen_size) + screen_size = info->screen_size;memset_io (info->screen_base,0x00 , screen_size);/* Device and screen back on */ svga_wcrt_mask (par->state.vgabase,0x17 ,0x80 ,0x80 );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 669/779 scsi: ufs: core: Correct ufshcd_shutdown() flow
In reply to Greg Kroah-HartmanFrom: Peter Wang <[email protected]>
commit 00511d2abf5708ad05dd5d1c36adb2468d274698 upstream.
After ufshcd_wl_shutdown() set device power off and link off, ufshcd_shutdown() could turn off clock/power. Also remove pm_runtime_get_sync.
The reason why it is safe to remove pm_runtime_get_sync() is because:
- ufshcd_wl_shutdown() -> pm_runtime_get_sync() will resume hba->dev too.
- device resume(turn on clk/power) is not required, even if device is in RPM_SUSPENDED.
--- drivers/scsi/ufs/ufshcd.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
drivers/scsi/ufs/ufshcd.c +1 -5
@@ -9239,12 +9239,8 @@ EXPORT_SYMBOL(ufshcd_runtime_resume);int ufshcd_shutdown (struct ufs_hba *hba) {if (ufshcd_is_ufs_dev_poweroff (hba) &&ufshcd_is_link_off (hba)) - goto out; +ufshcd_suspend (hba); -pm_runtime_get_sync (hba->dev); - -ufshcd_suspend (hba); -out: hba->is_powered = false;/* allow force shutdown even in case of errors */ return 0 ;
Greg Kroah-Hartman
maintainerPATCH 670/779 scsi: zfcp: Fix missing auto port scan and thus missing target ports
In reply to Greg Kroah-HartmanFrom: Steffen Maier <[email protected]>
commit 4da8c5f76825269f28d6a89fa752934a4bcb6dfa upstream.
Case (1):
The only waiter on wka_port->completion_wq is zfcp_fc_wka_port_get() trying to open a WKA port. As such it should only be woken up by WKA port *open* responses, not by WKA port close responses.
Case (2):
A close WKA port response coming in just after having sent a new open WKA port request and before blocking for the open response with wait_event() in zfcp_fc_wka_port_get() erroneously renders the wait_event a NOP because the close handler overwrites wka_port->status. Hence the wait_event condition is erroneously true and it does not enter blocking state.
With non-negligible probability, the following time space sequence happens depending on timing without this fix:
user process ERP thread zfcp work queue tasklet system work queue
============ ========== =============== ======= =================
$ echo 1 > online
zfcp_ccw_set_online
zfcp_ccw_activate
zfcp_erp_adapter_reopen
msleep scan backoff zfcp_erp_strategy
| ...
| zfcp_erp_action_cleanup
| ...
| queue delayed scan_work
| queue ns_up_work
| ns_up_work:
| zfcp_fc_wka_port_get
| open wka request
| open response
| GSPN FC-GS
| RSPN FC-GS [NPIV-only]
| zfcp_fc_wka_port_put
| (--wka->refcount==0)
| sched delayed wka->work
|
~~~Case (1)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
zfcp_erp_wait
flush scan_work
| wka->work:
| wka->status=CLOSING
| close wka request
| scan_work:
| zfcp_fc_wka_port_get
| (wka->status==CLOSING)
| wka->status=OPENING
| open wka request
| wait_event
| | close response
| | wka->status=OFFLINE
| | wake_up /*WRONG*/
~~~Case (2)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| wka->work:
| wka->status=CLOSING
| close wka request
zfcp_erp_wait
flush scan_work
| scan_work:
| zfcp_fc_wka_port_get
| (wka->status==CLOSING)
| wka->status=OPENING
| open wka request
| close response
| wka->status=OFFLINE
| wake_up /*WRONG&NOP*/
| wait_event /*NOP*/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| (wka->status!=ONLINE)
| return -EIO
| return early
open response
wka->status=ONLINE
wake_up /*NOP*/So we erroneously end up with no automatic port scan. This is a big problem when it happens during boot. The timing is influenced by v3.19 commit 18f87a67e6d6 ("zfcp: auto port scan resiliency").
Fix it by fully mutually excluding zfcp_fc_wka_port_get() and zfcp_fc_wka_port_offline(). For that to work, we make the latter block until we got the response for a close WKA port. In order not to penalize the system workqueue, we move wka_port->work to our own adapter workqueue. Note that before v2.6.30 commit 828bc1212a68 ("[SCSI] zfcp: Set WKA-port to offline on adapter deactivation"), zfcp did block in zfcp_fc_wka_port_offline() as well, but with a different condition.
While at it, make non-functional cleanups to improve code reading in zfcp_fc_wka_port_get(). If we cannot send the WKA port open request, don't rely on the subsequent wait_event condition to immediately let this case pass without blocking. Also don't want to rely on the additional condition handling the refcount to be skipped just to finally return with -EIO.
--- drivers/s390/scsi/zfcp_fc.c | 29 ++++++++++++++++++++--------- drivers/s390/scsi/zfcp_fc.h | 6 ++++-- drivers/s390/scsi/zfcp_fsf.c | 4 ++-- 3 files changed, 26 insertions(+), 13 deletions(-)
drivers/s390/scsi/zfcp_fc.c +20 -9
@@ -145,27 +145,33 @@ void zfcp_fc_enqueue_event(struct zfcp_astatic int zfcp_fc_wka_port_get (struct zfcp_fc_wka_port *wka_port) { +int ret = -EIO ; +if (mutex_lock_interruptible (&wka_port->mutex))return -ERESTARTSYS ;if (wka_port->status ==ZFCP_FC_WKA_PORT_OFFLINE || wka_port->status ==ZFCP_FC_WKA_PORT_CLOSING ) { wka_port->status =ZFCP_FC_WKA_PORT_OPENING ; -if (zfcp_fsf_open_wka_port (wka_port)) +if (zfcp_fsf_open_wka_port (wka_port)) { +/* could not even send request, nothing to wait for */ wka_port->status =ZFCP_FC_WKA_PORT_OFFLINE ; + goto out; + } } -mutex_unlock (&wka_port->mutex); - -wait_event (wka_port->completion_wq, +wait_event (wka_port->opened, wka_port->status ==ZFCP_FC_WKA_PORT_ONLINE || wka_port->status ==ZFCP_FC_WKA_PORT_OFFLINE );if (wka_port->status ==ZFCP_FC_WKA_PORT_ONLINE ) {atomic_inc (&wka_port->refcount); -return 0 ; + ret =0 ; + goto out; } -return -EIO ; +out: +mutex_unlock (&wka_port->mutex); +return ret; }static void zfcp_fc_wka_port_offline (struct work_struct *work)
@@ -181,9 +187,12 @@ static void zfcp_fc_wka_port_offline(str wka_port->status =ZFCP_FC_WKA_PORT_CLOSING ;if (zfcp_fsf_close_wka_port (wka_port)) { +/* could not even send request, nothing to wait for */ wka_port->status =ZFCP_FC_WKA_PORT_OFFLINE ; -wake_up (&wka_port->completion_wq); + goto out; } +wait_event (wka_port->closed, + wka_port->status ==ZFCP_FC_WKA_PORT_OFFLINE ); out:mutex_unlock (&wka_port->mutex); }
@@ -193,13 +202,15 @@ static void zfcp_fc_wka_port_put(structif (atomic_dec_return (&wka_port->refcount) !=0 )return ;/* wait 10 milliseconds, other reqs might pop in */ -schedule_delayed_work (&wka_port->work,HZ /100 ); +queue_delayed_work (wka_port->adapter->work_queue, &wka_port->work, +msecs_to_jiffies (10 )); }static void zfcp_fc_wka_port_init (struct zfcp_fc_wka_port *wka_port,u32 d_id,struct zfcp_adapter *adapter) { -init_waitqueue_head (&wka_port->completion_wq); +init_waitqueue_head (&wka_port->opened); +init_waitqueue_head (&wka_port->closed); wka_port->adapter = adapter; wka_port->d_id = d_id;
drivers/s390/scsi/zfcp_fc.h +4 -2
@@ -185,7 +185,8 @@ enum zfcp_fc_wka_status {/** * struct zfcp_fc_wka_port - representation of well-known-address (WKA) FC port * @adapter: Pointer to adapter structure this WKA port belongs to -* @completion_wq: Wait for completion of open/close command +* @opened: Wait for completion of open command +* @closed: Wait for completion of close command * @status: Current status of WKA port * @refcount: Reference count to keep port open as long as it is in use * @d_id: FC destination id or well-known-address
@@ -195,7 +196,8 @@ enum zfcp_fc_wka_status {*/ struct zfcp_fc_wka_port {struct zfcp_adapter *adapter; -wait_queue_head_t completion_wq; +wait_queue_head_t opened; +wait_queue_head_t closed;enum zfcp_fc_wka_status status;atomic_t refcount;u32 d_id;
drivers/s390/scsi/zfcp_fsf.c +2 -2
@@ -1907,7 +1907,7 @@ static void zfcp_fsf_open_wka_port_handl wka_port->status =ZFCP_FC_WKA_PORT_ONLINE ; } out: -wake_up (&wka_port->completion_wq); +wake_up (&wka_port->opened); }/**
@@ -1966,7 +1966,7 @@ static void zfcp_fsf_close_wka_port_hand } wka_port->status =ZFCP_FC_WKA_PORT_OFFLINE ; -wake_up (&wka_port->completion_wq); +wake_up (&wka_port->closed); }/**
Greg Kroah-Hartman
maintainerPATCH 671/779 scsi: qla2xxx: Fix imbalance vha->vref_count
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
commit 63fa7f2644b4b48e1913af33092c044bf48e9321 upstream.
vref_count took an extra decrement in the task management path. Add an extra ref count to compensate the imbalance.
--- drivers/scsi/qla2xxx/qla_init.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/scsi/qla2xxx/qla_init.c +4 -0
@@ -161,6 +161,7 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sstruct srb_iocb *abt_iocb;srb_t *sp;int rval =QLA_FUNCTION_FAILED ; +uint8_t bail;/* ref: INIT for ABTS command */ sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp->fcport,
@@ -168,6 +169,7 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sif (!sp)return QLA_MEMORY_ALLOC_FAILED ; +QLA_VHA_MARK_BUSY (vha, bail); abt_iocb = &sp->u.iocb_cmd; sp->type =SRB_ABT_CMD ; sp->name ="abort" ;
@@ -2009,12 +2011,14 @@ qla2x00_async_tm_cmd(fc_port_t *fcport,struct srb_iocb *tm_iocb;srb_t *sp;int rval =QLA_FUNCTION_FAILED ; +uint8_t bail;/* ref: INIT */ sp =qla2x00_get_sp (vha, fcport,GFP_KERNEL );if (!sp) goto done; +QLA_VHA_MARK_BUSY (vha, bail); sp->type =SRB_TM_CMD ; sp->name ="tmf" ; qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha),
Greg Kroah-Hartman
maintainerPATCH 672/779 scsi: qla2xxx: Fix discovery issues in FC-AL topology
In reply to Greg Kroah-HartmanFrom: Arun Easi <[email protected]>
commit 47ccb113cead905bdc236571bf8ac6fed90321b3 upstream.
A direct attach tape device, when gets swapped with another, was not discovered. Fix this by looking at loop map and reinitialize link if there are devices present.
--- drivers/scsi/qla2xxx/qla_gbl.h | 3 ++- drivers/scsi/qla2xxx/qla_init.c | 29 +++++++++++++++++++++++++++++ drivers/scsi/qla2xxx/qla_mbx.c | 5 ++++- 3 files changed, 35 insertions(+), 2 deletions(-)
drivers/scsi/qla2xxx/qla_gbl.h +2 -1
@@ -433,7 +433,8 @@ extern intqla2x00_get_resource_cnts (scsi_qla_host_t *);extern int -qla2x00_get_fcal_position_map (scsi_qla_host_t *ha,char *pos_map); +qla2x00_get_fcal_position_map (scsi_qla_host_t *ha,char *pos_map, +u8 *num_entries); extern int qla2x00_get_link_status(scsi_qla_host_t *, uint16_t, struct link_statistics *,
drivers/scsi/qla2xxx/qla_init.c +29 -0
@@ -5510,6 +5510,22 @@ static int qla2x00_configure_n2n_loop(screturn QLA_FUNCTION_FAILED ; } +static void +qla_reinitialize_link (scsi_qla_host_t *vha) +{ +int rval; + +atomic_set (&vha->loop_state,LOOP_DOWN ); +atomic_set (&vha->loop_down_timer,LOOP_DOWN_TIME ); + rval =qla2x00_full_login_lip (vha); +if (rval ==QLA_SUCCESS ) { +ql_dbg (ql_dbg_disc, vha,0xd050 ,"Link reinitialized\n" ); + }else { +ql_dbg (ql_dbg_disc, vha,0xd051 , +"Link reinitialization failed (%d)\n" , rval); + } +} +/* * qla2x00_configure_local_loop * Updates Fibre Channel Device Database with local loop devices.
@@ -5561,6 +5577,19 @@ qla2x00_configure_local_loop(scsi_qla_hospin_unlock_irqrestore (&vha->work_lock, flags);if (vha->scan.scan_retry <MAX_SCAN_RETRIES ) { +u8 loop_map_entries =0 ; +int rc; + + rc =qla2x00_get_fcal_position_map (vha,NULL , + &loop_map_entries); +if (rc ==QLA_SUCCESS && loop_map_entries >1 ) { +/* +* There are devices that are still not logged +* in. Reinitialize to give them a chance. +*/ +qla_reinitialize_link (vha); +return QLA_FUNCTION_FAILED ; + }set_bit (LOCAL_LOOP_UPDATE , &vha->dpc_flags);set_bit (LOOP_RESYNC_NEEDED , &vha->dpc_flags); }
drivers/scsi/qla2xxx/qla_mbx.c +4 -1
@@ -3062,7 +3062,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_* Kernel context. */ int -qla2x00_get_fcal_position_map (scsi_qla_host_t *vha,char *pos_map) +qla2x00_get_fcal_position_map (scsi_qla_host_t *vha,char *pos_map, +u8 *num_entries) {int rval;mbx_cmd_t mc;
@@ -3102,6 +3103,8 @@ qla2x00_get_fcal_position_map(scsi_qla_hif (pos_map)memcpy (pos_map, pmap,FCAL_MAP_SIZE ); +if (num_entries) + *num_entries = pmap[0 ]; }dma_pool_free (ha->s_dma_pool, pmap, pmap_dma);
Greg Kroah-Hartman
maintainerPATCH 673/779 scsi: qla2xxx: Turn off multi-queue for 8G adapters
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
commit 5304673bdb1635e27555bd636fd5d6956f1cd552 upstream.
For 8G adapters, multi-queue was enabled accidentally. Make sure multi-queue is not enabled.
--- drivers/scsi/qla2xxx/qla_def.h | 4 ++-- drivers/scsi/qla2xxx/qla_isr.c | 16 ++++++---------- 2 files changed, 8 insertions(+), 12 deletions(-)
drivers/scsi/qla2xxx/qla_def.h +2 -2
@@ -4261,8 +4261,8 @@ struct qla_hw_data {#define IS_OEM_001 (ha) ((ha)->device_type & DT_OEM_001)#define HAS_EXTENDED_IDS (ha) ((ha)->device_type & DT_EXTENDED_IDS)#define IS_CT6_SUPPORTED (ha) ((ha)->device_type & DT_CT6_SUPPORTED) -#define IS_MQUE_CAPABLE (ha) ((ha)->mqenable || IS_QLA83XX(ha) || \ - IS_QLA27XX(ha) || IS_QLA28XX(ha)) +#define IS_MQUE_CAPABLE (ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \ + IS_QLA28XX(ha))#define IS_BIDI_CAPABLE (ha) \ (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))/* Bit 21 of fw_attributes decides the MCTP capabilities */
drivers/scsi/qla2xxx/qla_isr.c +6 -10
@@ -4415,16 +4415,12 @@ msix_register_fail: }/* Enable MSI-X vector for response queue update for queue 0 */ -if (IS_QLA83XX (ha) ||IS_QLA27XX (ha) ||IS_QLA28XX (ha)) { -if (ha->msixbase && ha->mqiobase && - (ha->max_rsp_queues >1 || ha->max_req_queues >1 || - ql2xmqsupport)) - ha->mqenable =1 ; - }else -if (ha->mqiobase && - (ha->max_rsp_queues >1 || ha->max_req_queues >1 || - ql2xmqsupport)) - ha->mqenable =1 ; +if (IS_MQUE_CAPABLE (ha) && + (ha->msixbase && ha->mqiobase && ha->max_qpairs)) + ha->mqenable =1 ; +else + ha->mqenable =0 ; +ql_dbg (ql_dbg_multiq, vha,0xc005 ,"mqiobase=%p, max_rsp_queues=%d, max_req_queues=%d.\n" , ha->mqiobase, ha->max_rsp_queues, ha->max_req_queues);
Greg Kroah-Hartman
maintainerPATCH 674/779 scsi: qla2xxx: Fix crash due to stale SRB access around I/O timeouts
In reply to Greg Kroah-HartmanFrom: Arun Easi <[email protected]>
commit c39587bc0abaf16593f7abcdf8aeec3c038c7d52 upstream.
Ensure SRB is returned during I/O timeout error escalation. If that is not possible fail the escalation path.
Following crash stack was seen:
BUG: unable to handle kernel paging request at 0000002f56aa90f8 IP: qla_chk_edif_rx_sa_delete_pending+0x14/0x30 [qla2xxx] Call Trace: ? qla2x00_status_entry+0x19f/0x1c50 [qla2xxx] ? qla2x00_start_sp+0x116/0x1170 [qla2xxx] ? dma_pool_alloc+0x1d6/0x210 ? mempool_alloc+0x54/0x130 ? qla24xx_process_response_queue+0x548/0x12b0 [qla2xxx] ? qla_do_work+0x2d/0x40 [qla2xxx] ? process_one_work+0x14c/0x390
--- drivers/scsi/qla2xxx/qla_os.c | 43 ++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-)
drivers/scsi/qla2xxx/qla_os.c +31 -12
@@ -1333,21 +1333,20 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)/* * Returns: QLA_SUCCESS or QLA_FUNCTION_FAILED. */ -int -qla2x00_eh_wait_for_pending_commands (scsi_qla_host_t *vha,unsigned int t, -uint64_t l,enum nexus_wait_type type) +static int +__qla2x00_eh_wait_for_pending_commands (struct qla_qpair *qpair,unsigned int t, +uint64_t l,enum nexus_wait_type type) {int cnt, match, status;unsigned long flags; -struct qla_hw_data *ha = vha->hw; -struct req_que *req; +scsi_qla_host_t *vha = qpair->vha; +struct req_que *req = qpair->req;srb_t *sp;struct scsi_cmnd *cmd; status =QLA_SUCCESS ; -spin_lock_irqsave (&ha->hardware_lock, flags); - req = vha->req; +spin_lock_irqsave (qpair->qp_lock_ptr, flags);for (cnt =1 ; status ==QLA_SUCCESS && cnt < req->num_outstanding_cmds; cnt++) { sp = req->outstanding_cmds[cnt];
@@ -1374,12 +1373,32 @@ qla2x00_eh_wait_for_pending_commands(scsif (!match)continue ; -spin_unlock_irqrestore (&ha->hardware_lock, flags); +spin_unlock_irqrestore (qpair->qp_lock_ptr, flags); status =qla2x00_eh_wait_on_command (cmd); -spin_lock_irqsave (&ha->hardware_lock, flags); +spin_lock_irqsave (qpair->qp_lock_ptr, flags); } -spin_unlock_irqrestore (&ha->hardware_lock, flags); +spin_unlock_irqrestore (qpair->qp_lock_ptr, flags); + +return status; +} + +int +qla2x00_eh_wait_for_pending_commands (scsi_qla_host_t *vha,unsigned int t, +uint64_t l,enum nexus_wait_type type) +{ +struct qla_qpair *qpair; +struct qla_hw_data *ha = vha->hw; +int i, status =QLA_SUCCESS ; + status =__qla2x00_eh_wait_for_pending_commands (ha->base_qpair, t, l, + type); +for (i =0 ; status ==QLA_SUCCESS && i < ha->max_qpairs; i++) { + qpair = ha->queue_pair_map[i]; +if (!qpair) +continue ; + status =__qla2x00_eh_wait_for_pending_commands (qpair, t, l, + type); + }return status; }
@@ -1416,7 +1435,7 @@ qla2xxx_eh_device_reset(struct scsi_cmndreturn err;if (fcport->deleted) -return SUCCESS ; +return FAILED ; ql_log(ql_log_info, vha, 0x8009, "DEVICE RESET ISSUED nexus=%ld:%d:%llu cmd=%p.\n", vha->host_no,
@@ -1484,7 +1503,7 @@ qla2xxx_eh_target_reset(struct scsi_cmndreturn err;if (fcport->deleted) -return SUCCESS ; +return FAILED ; ql_log(ql_log_info, vha, 0x8009, "TARGET RESET ISSUED nexus=%ld:%d cmd=%p.\n", vha->host_no,
Greg Kroah-Hartman
maintainerPATCH 675/779 scsi: qla2xxx: Fix excessive I/O error messages by default
In reply to Greg Kroah-HartmanFrom: Arun Easi <[email protected]>
commit bff4873c709085e09d0ffae0c25b8e65256e3205 upstream.
Disable printing I/O error messages by default. The messages will be printed only when logging was enabled.
--- drivers/scsi/qla2xxx/qla_isr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/scsi/qla2xxx/qla_isr.c +2 -2
@@ -2633,7 +2633,7 @@ static void qla24xx_nvme_iocb_entry(scsi }if (unlikely (logit)) - ql_log(ql_dbg_io, fcport->vha, 0x5060, + ql_dbg(ql_dbg_io, fcport->vha, 0x5060, "NVME-%s ERR Handling - hdl=%x status(%x) tr_len:%x resid=%x ox_id=%x\n", sp->name, sp->handle, comp_status, fd->transferred_length, le32_to_cpu(sts->residual_len),
@@ -3491,7 +3491,7 @@ check_scsi_status: out:if (logit) - ql_log(ql_dbg_io, fcport->vha, 0x3022, + ql_dbg(ql_dbg_io, fcport->vha, 0x3022, "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n", comp_status, scsi_status, res, vha->host_no, cp->device->id, cp->device->lun, fcport->d_id.b.domain,
Greg Kroah-Hartman
maintainerPATCH 676/779 scsi: qla2xxx: Fix erroneous mailbox timeout after PCI error injection
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
commit f260694e6463b63ae550aad25ddefe94cb1904da upstream.
Clear wait for mailbox interrupt flag to prevent stale mailbox:
Feb 22 05:22:56 ltcden4-lp7 kernel: qla2xxx [0135:90:00.1]-500a:4: LOOP UP detected (16 Gbps). Feb 22 05:22:59 ltcden4-lp7 kernel: qla2xxx [0135:90:00.1]-d04c:4: MBX Command timeout for cmd 69, ...
To fix the issue, driver needs to clear the MBX_INTR_WAIT flag on purging the mailbox. When the stale mailbox completion does arrive, it will be dropped.
--- drivers/scsi/qla2xxx/qla_mbx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/scsi/qla2xxx/qla_mbx.c +6 -6
@@ -276,6 +276,12 @@ qla2x00_mailbox_command(scsi_qla_host_tatomic_inc (&ha->num_pend_mbx_stage3);if (!wait_for_completion_timeout (&ha->mbx_intr_comp, mcp->tov *HZ )) { +ql_dbg (ql_dbg_mbx, vha,0x117a , +"cmd=%x Timeout.\n" , command); +spin_lock_irqsave (&ha->hardware_lock, flags); +clear_bit (MBX_INTR_WAIT , &ha->mbx_cmd_flags); +spin_unlock_irqrestore (&ha->hardware_lock, flags); +if (chip_reset != ha->chip_reset) { eeh_delay = ha->flags.eeh_busy ?1 :0 ;
@@ -288,12 +294,6 @@ qla2x00_mailbox_command(scsi_qla_host_t rval =QLA_ABORTED ; goto premature_exit; } -ql_dbg (ql_dbg_mbx, vha,0x117a , -"cmd=%x Timeout.\n" , command); -spin_lock_irqsave (&ha->hardware_lock, flags); -clear_bit (MBX_INTR_WAIT , &ha->mbx_cmd_flags); -spin_unlock_irqrestore (&ha->hardware_lock, flags); - }else if (ha->flags.purge_mbox || chip_reset != ha->chip_reset) { eeh_delay = ha->flags.eeh_busy ?1 :0 ;
Greg Kroah-Hartman
maintainerPATCH 677/779 scsi: qla2xxx: Wind down adapter after PCIe error
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
commit d3117c83ba316b3200d9f2fe900f2b9a5525a25c upstream.
Put adapter into a wind down state if OS does not make any attempt to recover the adapter after PCIe error.
--- drivers/scsi/qla2xxx/qla_bsg.c | 10 +++++++- drivers/scsi/qla2xxx/qla_def.h | 4 +++ drivers/scsi/qla2xxx/qla_init.c | 20 ++++++++++++++++ drivers/scsi/qla2xxx/qla_os.c | 48 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 1 deletion(-)
drivers/scsi/qla2xxx/qla_bsg.c +9 -1
@@ -2972,6 +2972,13 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_ql_log (ql_log_info, vha,0x708b ,"%s CMD timeout. bsg ptr %p.\n" , __func__, bsg_job); + +if (qla2x00_isp_reg_stat (ha)) { +ql_log (ql_log_info, vha,0x9007 , +"PCI/Register disconnect.\n" ); +qla_pci_set_eeh_busy (vha); + } +/* find the bsg job from the active list of commands */ spin_lock_irqsave (&ha->hardware_lock, flags);for (que =0 ; que < ha->max_req_queues; que++) {
@@ -2989,7 +2996,8 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_ sp->u.bsg_job == bsg_job) { req->outstanding_cmds[cnt] =NULL ;spin_unlock_irqrestore (&ha->hardware_lock, flags); -if (ha->isp_ops->abort_command (sp)) { + +if (!ha->flags.eeh_busy && ha->isp_ops->abort_command (sp)) {ql_log (ql_log_warn, vha,0x7089 ,"mbx abort_command failed.\n" ); bsg_reply->result = -EIO ;
drivers/scsi/qla2xxx/qla_def.h +4 -0
@@ -4045,6 +4045,9 @@ struct qla_hw_data { uint32_t n2n_fw_acc_sec:1; uint32_t plogi_template_valid:1; uint32_t port_isolated:1; + uint32_t eeh_flush:2; +#define EEH_FLUSH_RDY 1 +#define EEH_FLUSH_DONE 2 } flags;uint16_t max_exchg;
@@ -4079,6 +4082,7 @@ struct qla_hw_data {uint32_t rsp_que_len;uint32_t req_que_off;uint32_t rsp_que_off; +unsigned long eeh_jif;/* Multi queue data structs */ device_reg_t *mqiobase;
drivers/scsi/qla2xxx/qla_init.c +20 -0
@@ -47,6 +47,7 @@ qla2x00_sp_timeout(struct timer_list *t) {srb_t *sp =from_timer (sp, t, u.iocb_cmd.timer);struct srb_iocb *iocb; +scsi_qla_host_t *vha = sp->vha;WARN_ON (irqs_disabled ()); iocb = &sp->u.iocb_cmd;
@@ -54,6 +55,12 @@ qla2x00_sp_timeout(struct timer_list *t)/* ref: TMR */ kref_put (&sp->cmd_kref, qla2x00_sp_release); + +if (vha &&qla2x00_isp_reg_stat (vha->hw)) { +ql_log (ql_log_info, vha,0x9008 , +"PCI/Register disconnect.\n" ); +qla_pci_set_eeh_busy (vha); + } }void qla2x00_sp_free (srb_t *sp)
@@ -9731,6 +9738,12 @@ int qla2xxx_disable_port(struct Scsi_Hos vha->hw->flags.port_isolated =1 ; +if (qla2x00_isp_reg_stat (vha->hw)) { +ql_log (ql_log_info, vha,0x9006 , +"PCI/Register disconnect, exiting.\n" ); +qla_pci_set_eeh_busy (vha); +return FAILED ; + }if (qla2x00_chip_is_down (vha))return 0 ;
@@ -9746,6 +9759,13 @@ int qla2xxx_enable_port(struct Scsi_Host {scsi_qla_host_t *vha =shost_priv (host); +if (qla2x00_isp_reg_stat (vha->hw)) { +ql_log (ql_log_info, vha,0x9001 , +"PCI/Register disconnect, exiting.\n" ); +qla_pci_set_eeh_busy (vha); +return FAILED ; + } + vha->hw->flags.port_isolated =0 ;/* Set the flag to 1, so that isp_abort can proceed */ vha->flags.online =1 ;
drivers/scsi/qla2xxx/qla_os.c +48 -0
72 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 678/779 scsi: qla2xxx: Fix losing FCP-2 targets on long port disable with I/Os
In reply to Greg Kroah-HartmanFrom: Arun Easi <[email protected]>
commit 2416ccd3815ba1613e10a6da0a24ef21acfe5633 upstream.
FCP-2 devices were not coming back online once they were lost, login retries exhausted, and then came back up. Fix this by accepting RSCN when the device is not online.
--- drivers/scsi/qla2xxx/qla_init.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/scsi/qla2xxx/qla_init.c +8 -4
@@ -1836,7 +1836,8 @@ void qla2x00_handle_rscn(scsi_qla_host_tcase RSCN_PORT_ADDR : fcport =qla2x00_find_fcport_by_nportid (vha, &ea->id,1 );if (fcport) { -if (fcport->flags &FCF_FCP2_DEVICE ) { +if (fcport->flags &FCF_FCP2_DEVICE && +atomic_read (&fcport->state) ==FCS_ONLINE ) {ql_dbg (ql_dbg_disc, vha,0x2115 ,"Delaying session delete for FCP2 portid=%06x %8phC " , fcport->d_id.b24, fcport->port_name);
@@ -1868,7 +1869,8 @@ void qla2x00_handle_rscn(scsi_qla_host_tbreak ;case RSCN_AREA_ADDR :list_for_each_entry (fcport, &vha->vp_fcports, list) { -if (fcport->flags &FCF_FCP2_DEVICE ) +if (fcport->flags &FCF_FCP2_DEVICE && +atomic_read (&fcport->state) ==FCS_ONLINE )continue ;if ((ea->id.b24 &0xffff00 ) == (fcport->d_id.b24 &0xffff00 )) {
@@ -1879,7 +1881,8 @@ void qla2x00_handle_rscn(scsi_qla_host_tbreak ;case RSCN_DOM_ADDR :list_for_each_entry (fcport, &vha->vp_fcports, list) { -if (fcport->flags &FCF_FCP2_DEVICE ) +if (fcport->flags &FCF_FCP2_DEVICE && +atomic_read (&fcport->state) ==FCS_ONLINE )continue ;if ((ea->id.b24 &0xff0000 ) == (fcport->d_id.b24 &0xff0000 )) {
@@ -1891,7 +1894,8 @@ void qla2x00_handle_rscn(scsi_qla_host_tcase RSCN_FAB_ADDR :default :list_for_each_entry (fcport, &vha->vp_fcports, list) { -if (fcport->flags &FCF_FCP2_DEVICE ) +if (fcport->flags &FCF_FCP2_DEVICE && +atomic_read (&fcport->state) ==FCS_ONLINE )continue ; fcport->scan_needed =1 ;
Greg Kroah-Hartman
maintainerPATCH 679/779 scsi: qla2xxx: Fix losing target when it reappears during delete
In reply to Greg Kroah-HartmanFrom: Arun Easi <[email protected]>
commit 118b0c863c8f5629cc5271fc24d72d926e0715d9 upstream.
FC target disappeared during port perturbation tests due to a race that tramples target state. Fix the issue by adding state checks before proceeding.
--- drivers/scsi/qla2xxx/qla_attr.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-)
drivers/scsi/qla2xxx/qla_attr.c +17 -7
@@ -2705,17 +2705,24 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rpif (!fcport)return ; -/* Now that the rport has been deleted, set the fcport state to -FCS_DEVICE_DEAD */ -qla2x00_set_fcport_state (fcport,FCS_DEVICE_DEAD ); + +/* +* Now that the rport has been deleted, set the fcport state to +* FCS_DEVICE_DEAD, if the fcport is still lost. +*/ +if (fcport->scan_state !=QLA_FCPORT_FOUND ) +qla2x00_set_fcport_state (fcport,FCS_DEVICE_DEAD );/* * Transport has effectively 'deleted' the rport, clear * all local references. */ spin_lock_irqsave (host->host_lock, flags); - fcport->rport = fcport->drport =NULL ; - *((fc_port_t **)rport->dd_data) =NULL ; +/* Confirm port has not reappeared before clearing pointers. */ +if (rport->port_state !=FC_PORTSTATE_ONLINE ) { + fcport->rport = fcport->drport =NULL ; + *((fc_port_t **)rport->dd_data) =NULL ; + }spin_unlock_irqrestore (host->host_lock, flags);if (test_bit (ABORT_ISP_ACTIVE , &fcport->vha->dpc_flags))
@@ -2748,9 +2755,12 @@ qla2x00_terminate_rport_io(struct fc_rpo/* * At this point all fcport's software-states are cleared. Perform any * final cleanup of firmware resources (PCBs and XCBs). +* +* Attempt to cleanup only lost devices. */ if (fcport->loop_id !=FC_NO_LOOP_ID ) { -if (IS_FWI2_CAPABLE (fcport->vha->hw)) { +if (IS_FWI2_CAPABLE (fcport->vha->hw) && + fcport->scan_state !=QLA_FCPORT_FOUND ) {if (fcport->loop_id !=FC_NO_LOOP_ID ) fcport->logout_on_delete =1 ;
@@ -2760,7 +2770,7 @@ qla2x00_terminate_rport_io(struct fc_rpo __LINE__);qlt_schedule_sess_for_deletion (fcport); } - }else { + }else if (!IS_FWI2_CAPABLE (fcport->vha->hw)) {qla2x00_port_logout (fcport->vha, fcport); } }
Greg Kroah-Hartman
maintainerPATCH 680/779 scsi: qla2xxx: Fix losing FCP-2 targets during port perturbation tests
In reply to Greg Kroah-HartmanFrom: Arun Easi <[email protected]>
commit 58d1c124cd79ea686b512043c5bd515590b2ed95 upstream.
When a mix of FCP-2 (tape) and non-FCP-2 targets are present, FCP-2 target state was incorrectly transitioned when both of the targets were gone. Fix this by ignoring state transition for FCP-2 targets.
--- drivers/scsi/qla2xxx/qla_gs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/qla2xxx/qla_gs.c +1 -1
@@ -3628,7 +3628,7 @@ login_logout: do_delete) {if (fcport->loop_id !=FC_NO_LOOP_ID ) {if (fcport->flags &FCF_FCP2_DEVICE ) - fcport->logout_on_delete =0 ; +continue ; ql_log(ql_log_warn, vha, 0x20f0, "%s %d %8phC post del sess\n",
Greg Kroah-Hartman
maintainerPATCH 681/779 x86/bugs: Enable STIBP for IBPB mitigated RETBleed
In reply to Greg Kroah-HartmanFrom: Kim Phillips <[email protected]>
commit e6cfcdda8cbe81eaf821c897369a65fec987b404 upstream.
AMD's "Technical Guidance for Mitigating Branch Type Confusion, Rev. 1.0 2022-07-12" whitepaper, under section 6.1.2 "IBPB On Privileged Mode Entry / SMT Safety" says:
Similar to the Jmp2Ret mitigation, if the code on the sibling thread cannot be trusted, software should set STIBP to 1 or disable SMT to ensure SMT safety when using this mitigation.
So, like already being done for retbleed=unret, and now also for retbleed=ibpb, force STIBP on machines that have it, and report its SMT vulnerability status accordingly.
[ bp: Remove the "we" and remove "[AMD]" applicability parameter which
doesn't work here. ]
--- Documentation/admin-guide/kernel-parameters.txt | 29 +++++++++++++++++------- arch/x86/kernel/cpu/bugs.c | 10 ++++---- 2 files changed, 27 insertions(+), 12 deletions(-)
Documentation/admin-guide/kernel-parameters.txt +21 -8
@@ -4974,20 +4974,33 @@ Speculative Code Execution with Return Instructions) vulnerability. + AMD-based UNRET and IBPB mitigations alone do not stop + sibling threads from influencing the predictions of other + sibling threads. For that reason, STIBP is used on pro- + cessors that support it, and mitigate SMT on processors + that don't. + off - no mitigation auto - automatically select a migitation auto,nosmt - automatically select a mitigation, disabling SMT if necessary for the full mitigation (only on Zen1 and older without STIBP). - ibpb - mitigate short speculation windows on - basic block boundaries too. Safe, highest - perf impact. - unret - force enable untrained return thunks, - only effective on AMD f15h-f17h - based systems. - unret,nosmt - like unret, will disable SMT when STIBP - is not available. + ibpb - On AMD, mitigate short speculation + windows on basic block boundaries too. + Safe, highest perf impact. It also + enables STIBP if present. Not suitable + on Intel. + ibpb,nosmt - Like "ibpb" above but will disable SMT + when STIBP is not available. This is + the alternative for systems which do not + have STIBP. + unret - Force enable untrained return thunks, + only effective on AMD f15h-f17h based + systems. + unret,nosmt - Like unret, but will disable SMT when STIBP + is not available. This is the alternative for + systems which do not have STIBP. Selecting 'auto' will choose a mitigation method at run time according to the CPU.
arch/x86/kernel/cpu/bugs.c +6 -4
@@ -152,7 +152,7 @@ void __init check_bugs(void)/* * spectre_v2_user_select_mitigation() relies on the state set by * retbleed_select_mitigation(); specifically the STIBP selection is -* forced for UNRET. +* forced for UNRET or IBPB. */ spectre_v2_user_select_mitigation ();ssb_select_mitigation ();
@@ -1172,7 +1172,8 @@ spectre_v2_user_select_mitigation(void) boot_cpu_has(X86_FEATURE_AMD_STIBP_ALWAYS_ON)) mode =SPECTRE_V2_USER_STRICT_PREFERRED ; -if (retbleed_mitigation ==RETBLEED_MITIGATION_UNRET ) { +if (retbleed_mitigation ==RETBLEED_MITIGATION_UNRET || + retbleed_mitigation ==RETBLEED_MITIGATION_IBPB ) {if (mode !=SPECTRE_V2_USER_STRICT && mode !=SPECTRE_V2_USER_STRICT_PREFERRED )pr_info ("Selecting STIBP always-on mode to complement retbleed mitigation\n" );
@@ -2353,10 +2354,11 @@ static ssize_t srbds_show_state(char *bustatic ssize_t retbleed_show_state (char *buf) { -if (retbleed_mitigation ==RETBLEED_MITIGATION_UNRET ) { +if (retbleed_mitigation ==RETBLEED_MITIGATION_UNRET || + retbleed_mitigation ==RETBLEED_MITIGATION_IBPB ) {if (boot_cpu_data.x86_vendor !=X86_VENDOR_AMD && boot_cpu_data.x86_vendor !=X86_VENDOR_HYGON ) -return sprintf (buf,"Vulnerable: untrained return thunk on non-Zen uarch\n" ); +return sprintf (buf,"Vulnerable: untrained return thunk / IBPB on non-AMD based uarch\n" ); return sprintf(buf, "%s; SMT %s\n", retbleed_strings[retbleed_mitigation],
Greg Kroah-Hartman
maintainerPATCH 682/779 ftrace/x86: Add back ftrace_expected assignment
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (Google) <[email protected]>
commit ac6c1b2ca77e722a1e5d651f12f437f2f237e658 upstream.
When a ftrace_bug happens (where ftrace fails to modify a location) it is helpful to have what was at that location as well as what was expected to be there.
But with the conversion to text_poke() the variable that assigns the expected for debugging was dropped. Unfortunately, I noticed this when I needed it. Add it back.
--- arch/x86/kernel/ftrace.c | 1 + 1 file changed, 1 insertion(+)
arch/x86/kernel/ftrace.c +1 -0
@@ -93,6 +93,7 @@ static int ftrace_verify_code(unsigned l/* Make sure it is what we expect it to be */ if (memcmp (cur_code, old_code,MCOUNT_INSN_SIZE ) !=0 ) { + ftrace_expected = old_code;WARN_ON (1 );return -EINVAL ; }
Greg Kroah-Hartman
maintainerPATCH 683/779 x86/kprobes: Update kcb status flag after singlestepping
In reply to Greg Kroah-HartmanFrom: Masami Hiramatsu (Google) <[email protected]>
commit dec8784c9088b131a1523f582c2194cfc8107dc0 upstream.
Fix kprobes to update kcb (kprobes control block) status flag to KPROBE_HIT_SSDONE even if the kp->post_handler is not set.
This bug may cause a kernel panic if another INT3 user runs right after kprobes because kprobe_int3_handler() misunderstands the INT3 is kprobe's single stepping INT3.
--- arch/x86/kernel/kprobes/core.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
arch/x86/kernel/kprobes/core.c +11 -7
@@ -816,16 +816,20 @@ NOKPROBE_SYMBOL(arch_prepare_kretprobe);static void kprobe_post_process (struct kprobe *cur,struct pt_regs *regs,struct kprobe_ctlblk *kcb) { -if ((kcb->kprobe_status !=KPROBE_REENTER ) && cur->post_handler) { - kcb->kprobe_status =KPROBE_HIT_SSDONE ; - cur->post_handler (cur, regs,0 ); - } -/* Restore back the original saved kprobes variables and continue. */ -if (kcb->kprobe_status ==KPROBE_REENTER ) +if (kcb->kprobe_status ==KPROBE_REENTER ) { +/* This will restore both kcb and current_kprobe */ restore_previous_kprobe (kcb); -else + }else { +/* +* Always update the kcb status because +* reset_curent_kprobe() doesn't update kcb. +*/ + kcb->kprobe_status =KPROBE_HIT_SSDONE ; +if (cur->post_handler) + cur->post_handler (cur, regs,0 );reset_current_kprobe (); + } }NOKPROBE_SYMBOL (kprobe_post_process);
Greg Kroah-Hartman
maintainerPATCH 684/779 x86/olpc: fix logical not is only applied to the left hand side
In reply to Greg Kroah-HartmanFrom: Alexander Lobakin <[email protected]>
commit 3a2ba42cbd0b669ce3837ba400905f93dd06c79f upstream.
The bitops compile-time optimization series revealed one more problem in olpc-xo1-sci.c:send_ebook_state(), resulted in GCC warnings:
arch/x86/platform/olpc/olpc-xo1-sci.c: In function 'send_ebook_state':arch/x86/platform/olpc/olpc-xo1-sci.c:83:63: warning: logical not is only applied to the left hand side of comparison [-Wlogical-not-parentheses]
83 | if (!!test_bit(SW_TABLET_MODE, ebook_switch_idev->sw) == state)
| ^~arch/x86/platform/olpc/olpc-xo1-sci.c:83:13: note: add parentheses around left hand side expression to silence this warning
Despite this code working as intended, this redundant double negation of boolean value, together with comparing to char with no explicit conversion to bool, makes compilers think the author made some unintentional logical mistakes here. Make it the other way around and negate the char instead to silence the warnings.
--- arch/x86/platform/olpc/olpc-xo1-sci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/platform/olpc/olpc-xo1-sci.c +1 -1
@@ -80,7 +80,7 @@ static void send_ebook_state(void)return ; } -if (!!test_bit (SW_TABLET_MODE , ebook_switch_idev->sw) == state) +if (test_bit (SW_TABLET_MODE , ebook_switch_idev->sw) == !!state)return ;/* Nothing new to report. */ input_report_switch (ebook_switch_idev,SW_TABLET_MODE , state);
Greg Kroah-Hartman
maintainerPATCH 685/779 SMB3: fix lease break timeout when multiple deferred close handles for the same file.
In reply to Greg Kroah-HartmanFrom: Bharath SM <[email protected]>
commit 9e31678fb403eae0f4fe37c6374be098835c73cd upstream.
Solution is to send lease break ack immediately even in case of deferred close handles to avoid lease break request timing out and let deferred closed handle gets closed as scheduled. Later patches could optimize cases where we then close some of these handles sooner for the cases where lease break is to 'none'
--- fs/cifs/file.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-)
fs/cifs/file.c +1 -19
@@ -4855,8 +4855,6 @@ void cifs_oplock_break(struct work_strucstruct TCP_Server_Info *server = tcon->ses->server;int rc =0 ;bool purge_cache = false; -bool is_deferred = false; -struct cifs_deferred_close *dclose;wait_on_bit (&cinode->flags,CIFS_INODE_PENDING_WRITERS ,TASK_UNINTERRUPTIBLE );
@@ -4893,22 +4891,6 @@ void cifs_oplock_break(struct work_struc oplock_break_ack:/* -* When oplock break is received and there are no active -* file handles but cached, then schedule deferred close immediately. -* So, new open will not use cached handle. -*/ -spin_lock (&CIFS_I (inode)->deferred_lock); - is_deferred =cifs_is_deferred_close (cfile, &dclose); -spin_unlock (&CIFS_I (inode)->deferred_lock); -if (is_deferred && - cfile->deferred_close_scheduled && -delayed_work_pending (&cfile->deferred)) { -if (cancel_delayed_work (&cfile->deferred)) { -_cifsFileInfo_put (cfile, false, false); - goto oplock_break_done; - } - } -/* * releasing stale oplock after recent reconnect of smb session using * a now incorrect file handle is not a data integrity issue but do * not bother sending an oplock release if session to server still is
@@ -4919,7 +4901,7 @@ oplock_break_ack: cinode);cifs_dbg (FYI ,"Oplock release rc = %d\n" , rc); } -oplock_break_done: +_cifsFileInfo_put (cfile, false/* do not wait for ourself */ , false);cifs_done_oplock_break (cinode); }
Greg Kroah-Hartman
maintainerPATCH 686/779 posix-cpu-timers: Cleanup CPU timers before freeing them during exec
In reply to Greg Kroah-HartmanFrom: Thadeu Lima de Souza Cascardo <[email protected]>
commit e362359ace6f87c201531872486ff295df306d13 upstream.
Commit 55e8c8eb2c7b ("posix-cpu-timers: Store a reference to a pid not a task") started looking up tasks by PID when deleting a CPU timer.
When a non-leader thread calls execve, it will switch PIDs with the leader process. Then, as it calls exit_itimers, posix_cpu_timer_del cannot find the task because the timer still points out to the old PID.
That means that armed timers won't be disarmed, that is, they won't be removed from the timerqueue_list. exit_itimers will still release their memory, and when that list is later processed, it leads to a use-after-free.
Clean up the timers from the de-threaded task before freeing them. This prevents a reported use-after-free.
--- fs/exec.c | 3 +++ 1 file changed, 3 insertions(+)
fs/exec.c +3 -0
@@ -1298,6 +1298,9 @@ int begin_new_exec(struct linux_binprm * bprm->mm =NULL ;#ifdef CONFIG_POSIX_TIMERS +spin_lock_irq (&me->sighand->siglock); +posix_cpu_timers_exit (me); +spin_unlock_irq (&me->sighand->siglock);exit_itimers (me);flush_itimer_signals ();#endif
Greg Kroah-Hartman
maintainerPATCH 687/779 Input: gscps2 - check return value of ioremap() in gscps2_probe()
In reply to Greg Kroah-HartmanFrom: Xie Shaowen <[email protected]>
commit e61b3125a4f036b3c6b87ffd656fc1ab00440ae9 upstream.
The function ioremap() in gscps2_probe() can fail, so its return value should be checked.
--- drivers/input/serio/gscps2.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/input/serio/gscps2.c +4 -0
@@ -350,6 +350,10 @@ static int __init gscps2_probe(struct pa ps2port->port = serio; ps2port->padev = dev; ps2port->addr =ioremap (hpa,GSC_STATUS +4 ); +if (!ps2port->addr) { + ret = -ENOMEM ; + goto fail_nomem; + }spin_lock_init (&ps2port->lock);gscps2_reset (ps2port);
Greg Kroah-Hartman
maintainerPATCH 688/779 __follow_mount_rcu(): verify that mount_lock remains unchanged
In reply to Greg Kroah-HartmanFrom: Al Viro <[email protected]>
commit 20aac6c60981f5bfacd66661d090d907bf1482f0 upstream.
Validate mount_lock seqcount as soon as we cross into mount in RCU mode. Sure, ->mnt_root is pinned and will remain so until we do rcu_read_unlock() anyway, and we will eventually fail to unlazy if the mount_lock had been touched, but we might run into a hard error (e.g. -ENOENT) before trying to unlazy. And it's possible to end up with RCU pathwalk racing with rename() and umount() in a way that would fail with -ENOENT while non-RCU pathwalk would've succeeded with any timings.
Once upon a time we hadn't needed that, but analysis had been subtle, brittle and went out of window as soon as RENAME_EXCHANGE had been added.
It's narrow, hard to hit and won't get you anything other than stray -ENOENT that could be arranged in much easier way with the same priveleges, but it's a bug all the same.
Cc: [email protected]
X-sky-is-falling: unlikely
--- fs/namei.c | 2 ++ 1 file changed, 2 insertions(+)
fs/namei.c +2 -0
@@ -1461,6 +1461,8 @@ static bool __follow_mount_rcu(struct na* becoming unpinned. */ flags = dentry->d_flags; +if (read_seqretry (&mount_lock, nd->m_seq)) +return false;continue ; }if (read_seqretry (&mount_lock, nd->m_seq))
Greg Kroah-Hartman
maintainerPATCH 689/779 spmi: trace: fix stack-out-of-bound access in SPMI tracing functions
In reply to Greg Kroah-HartmanFrom: David Collins <[email protected]>
commit 2af28b241eea816e6f7668d1954f15894b45d7e3 upstream.
trace_spmi_write_begin() and trace_spmi_read_end() both call memcpy() with a length of "len + 1". This leads to one extra byte being read beyond the end of the specified buffer. Fix this out-of-bound memory access by using a length of "len" instead.
Here is a KASAN log showing the issue:
BUG: KASAN: stack-out-of-bounds in trace_event_raw_event_spmi_read_end+0x1d0/0x234 Read of size 2 at addr ffffffc0265b7540 by task [email protected]/1314 ... Call trace: dump_backtrace+0x0/0x3e8 show_stack+0x2c/0x3c dump_stack_lvl+0xdc/0x11c print_address_description+0x74/0x384 kasan_report+0x188/0x268 kasan_check_range+0x270/0x2b0 memcpy+0x90/0xe8 trace_event_raw_event_spmi_read_end+0x1d0/0x234 spmi_read_cmd+0x294/0x3ac spmi_ext_register_readl+0x84/0x9c regmap_spmi_ext_read+0x144/0x1b0 [regmap_spmi] _regmap_raw_read+0x40c/0x754 regmap_raw_read+0x3a0/0x514 regmap_bulk_read+0x418/0x494 adc5_gen3_poll_wait_hs+0xe8/0x1e0 [qcom_spmi_adc5_gen3] ... __arm64_sys_read+0x4c/0x60 invoke_syscall+0x80/0x218 el0_svc_common+0xec/0x1c8 ...
addr ffffffc0265b7540 is located in stack of task [email protected]/1314 at offset 32 in frame:
adc5_gen3_poll_wait_hs+0x0/0x1e0 [qcom_spmi_adc5_gen3]
this frame has 1 object:
[32, 33) 'status'
Memory state around the buggy address:
ffffffc0265b7400: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
ffffffc0265b7480: 04 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
>ffffffc0265b7500: 00 00 00 00 f1 f1 f1 f1 01 f3 f3 f3 00 00 00 00
^
ffffffc0265b7580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffffffc0265b7600: f1 f1 f1 f1 01 f2 07 f2 f2 f2 01 f3 00 00 00 00
==================================================================--- include/trace/events/spmi.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
include/trace/events/spmi.h +6 -6
@@ -21,15 +21,15 @@ TRACE_EVENT(spmi_write_begin,__field ( u8, sid ) __field ( u16, addr ) __field ( u8, len ) -__dynamic_array ( u8, buf, len +1 ) +__dynamic_array ( u8, buf, len ) ),TP_fast_assign ( __entry->opcode = opcode; __entry->sid = sid; __entry->addr = addr; - __entry->len = len +1 ; -memcpy (__get_dynamic_array (buf), buf, len +1 ); + __entry->len = len; +memcpy (__get_dynamic_array (buf), buf, len); ), TP_printk("opc=%d sid=%02d addr=0x%04x len=%d buf=0x[%*phD]",
@@ -92,7 +92,7 @@ TRACE_EVENT(spmi_read_end,__field ( u16, addr ) __field ( int, ret ) __field ( u8, len ) -__dynamic_array ( u8, buf, len +1 ) +__dynamic_array ( u8, buf, len ) ), TP_fast_assign(
@@ -100,8 +100,8 @@ TRACE_EVENT(spmi_read_end, __entry->sid = sid; __entry->addr = addr; __entry->ret = ret; - __entry->len = len +1 ; -memcpy (__get_dynamic_array (buf), buf, len +1 ); + __entry->len = len; +memcpy (__get_dynamic_array (buf), buf, len); ), TP_printk("opc=%d sid=%02d addr=0x%04x ret=%d len=%02d buf=0x[%*phD]",
Greg Kroah-Hartman
maintainerPATCH 690/779 drm/mediatek: Allow commands to be sent during video mode
In reply to Greg Kroah-HartmanFrom: Julien STEPHAN <[email protected]>
[ Upstream commit 81cc7e51c4f1686b71e30046437056ece6b2cb4d ]
Mipi dsi panel drivers can use mipi_dsi_dcs_{set,get}_display_brightness() to request backlight changes.
This can be done during panel initialization (dsi is in command mode) or afterwards (dsi is in Video Mode).
When the DSI is in Video Mode, all commands are rejected.
Detect current DSI mode in mtk_dsi_host_transfer() and switch modes temporarily to allow commands to be sent.
--- drivers/gpu/drm/mediatek/mtk_dsi.c | 33 ++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 9 deletions(-)
drivers/gpu/drm/mediatek/mtk_dsi.c +24 -9
@@ -910,24 +910,33 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,u8 read_data[16 ];void *src_addr;u8 irq_flag =CMD_DONE_INT_FLAG ; +u32 dsi_mode; +int ret; -if (readl (dsi->regs +DSI_MODE_CTRL ) &MODE ) { -DRM_ERROR ("dsi engine is not command mode\n" ); -return -EINVAL ; + dsi_mode =readl (dsi->regs +DSI_MODE_CTRL ); +if (dsi_mode &MODE ) { +mtk_dsi_stop (dsi); + ret =mtk_dsi_switch_to_cmd_mode (dsi,VM_DONE_INT_FLAG ,500 ); +if (ret) + goto restore_dsi_mode; }if (MTK_DSI_HOST_IS_READ (msg->type)) irq_flag |=LPRX_RD_RDY_INT_FLAG ; -if (mtk_dsi_host_send_cmd (dsi, msg, irq_flag) <0 ) -return -ETIME ; + ret =mtk_dsi_host_send_cmd (dsi, msg, irq_flag); +if (ret) + goto restore_dsi_mode; -if (!MTK_DSI_HOST_IS_READ (msg->type)) -return 0 ; +if (!MTK_DSI_HOST_IS_READ (msg->type)) { + recv_cnt =0 ; + goto restore_dsi_mode; + }if (!msg->rx_buf) {DRM_ERROR ("dsi receive buffer size may be NULL\n" ); -return -EINVAL ; + ret = -EINVAL ; + goto restore_dsi_mode; }for (i =0 ; i <16 ; i++)
@@ -952,7 +961,13 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,DRM_INFO ("dsi get %d byte data from the panel address(0x%x)\n" , recv_cnt, *((u8 *)(msg->tx_buf))); -return recv_cnt; +restore_dsi_mode: +if (dsi_mode &MODE ) { +mtk_dsi_set_mode (dsi); +mtk_dsi_start (dsi); + } + +return ret <0 ? ret : recv_cnt; }static const struct mipi_dsi_host_ops mtk_dsi_ops = {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 691/779 drm/mediatek: Keep dsi as LP00 before dcs cmds transfer
In reply to Greg Kroah-HartmanFrom: Jitao Shi <[email protected]>
[ Upstream commit 39e8d062b03c3dc257d880d82bd55cdd9e185a3b ]
To comply with the panel sequence, hold the mipi signal to LP00 before the dcs cmds transmission, and pull the mipi signal high from LP00 to LP11 until the start of the dcs cmds transmission.
The normal panel timing is :
(1) pp1800 DC pull up
(2) avdd & avee AC pull high
(3) lcm_reset pull high -> pull low -> pull high
(4) Pull MIPI signal high (LP11) -> initial code -> send video data (HS mode)
The power-off sequence is reversed.
If dsi is not in cmd mode, then dsi will pull the mipi signal high in the mtk_output_dsi_enable function. The delay in lane_ready func is the reaction time of dsi_rx after pulling up the mipi signal.
--- drivers/gpu/drm/mediatek/mtk_dsi.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-)
drivers/gpu/drm/mediatek/mtk_dsi.c +21 -7
@@ -203,6 +203,7 @@ struct mtk_dsi {struct mtk_phy_timing phy_timing;int refcount;bool enabled; +bool lanes_ready;u32 irq_data;wait_queue_head_t irq_wait_queue;const struct mtk_dsi_driver_data *driver_data;
@@ -649,18 +650,11 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi)mtk_dsi_reset_engine (dsi);mtk_dsi_phy_timconfig (dsi); -mtk_dsi_rxtx_control (dsi); -usleep_range (30 ,100 ); -mtk_dsi_reset_dphy (dsi);mtk_dsi_ps_control_vact (dsi);mtk_dsi_set_vm_cmd (dsi);mtk_dsi_config_vdo_timing (dsi);mtk_dsi_set_interrupt_enable (dsi); -mtk_dsi_clk_ulp_mode_leave (dsi); -mtk_dsi_lane0_ulp_mode_leave (dsi); -mtk_dsi_clk_hs_mode (dsi,0 ); -return 0 ; err_disable_engine_clk:clk_disable_unprepare (dsi->engine_clk);
@@ -691,6 +685,23 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi)clk_disable_unprepare (dsi->digital_clk);phy_power_off (dsi->phy); + + dsi->lanes_ready = false; +} + +static void mtk_dsi_lane_ready (struct mtk_dsi *dsi) +{ +if (!dsi->lanes_ready) { + dsi->lanes_ready = true; +mtk_dsi_rxtx_control (dsi); +usleep_range (30 ,100 ); +mtk_dsi_reset_dphy (dsi); +mtk_dsi_clk_ulp_mode_leave (dsi); +mtk_dsi_lane0_ulp_mode_leave (dsi); +mtk_dsi_clk_hs_mode (dsi,0 ); +msleep (20 ); +/* The reaction time after pulling up the mipi signal for dsi_rx */ + } }static void mtk_output_dsi_enable (struct mtk_dsi *dsi)
@@ -698,6 +709,7 @@ static void mtk_output_dsi_enable(struct mtk_dsi *dsi)if (dsi->enabled)return ; +mtk_dsi_lane_ready (dsi);mtk_dsi_set_mode (dsi);mtk_dsi_clk_hs_mode (dsi,1 );
@@ -924,6 +936,8 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,if (MTK_DSI_HOST_IS_READ (msg->type)) irq_flag |=LPRX_RD_RDY_INT_FLAG ; +mtk_dsi_lane_ready (dsi); + ret =mtk_dsi_host_send_cmd (dsi, msg, irq_flag);if (ret) goto restore_dsi_mode;
Signature · 1 line
2.35.1