5.10.11-rc1 review
Subsystems (3)
Greg Kroah-Hartman
maintainerPATCH 159/199 net: dsa: mv88e6xxx: also read STU state in mv88e6250_g1_vtu_getnext
In reply to Greg Kroah-HartmanFrom: Rasmus Villemoes <[email protected]>
commit 87fe04367d842c4d97a77303242d4dd4ac351e46 upstream.
mv88e6xxx_port_vlan_join checks whether the VTU already contains an entry for the given vid (via mv88e6xxx_vtu_getnext), and if so, merely changes the relevant .member[] element and loads the updated entry into the VTU.
However, at least for the mv88e6250, the on-stack struct mv88e6xxx_vtu_entry vlan never has its .state[] array explicitly initialized, neither in mv88e6xxx_port_vlan_join() nor inside the getnext implementation. So the new entry has random garbage for the STU bits, breaking VLAN filtering.
When the VTU entry is initially created, those bits are all zero, and we should make sure to keep them that way when the entry is updated.
--- drivers/net/dsa/mv88e6xxx/global1_vtu.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/dsa/mv88e6xxx/global1_vtu.c +4 -0
@@ -351,6 +351,10 @@ int mv88e6250_g1_vtu_getnext(struct mv88if (err)return err; + err =mv88e6185_g1_stu_data_read (chip, entry); +if (err) +return err; +/* VTU DBNum[3:0] are located in VTU Operation 3:0 * VTU DBNum[5:4] are located in VTU Operation 9:8 */
Greg Kroah-Hartman
maintainerPATCH 160/199 selftests/powerpc: Fix exit status of pkey tests
In reply to Greg Kroah-HartmanFrom: Sandipan Das <[email protected]>
commit 92a5e1fdb286851d5bd0eb966b8d075be27cf5ee upstream.
Since main() does not return a value explicitly, the return values from FAIL_IF() conditions are ignored and the tests can still pass irrespective of failures. This makes sure that we always explicitly return the correct test exit status.
--- tools/testing/selftests/powerpc/mm/pkey_exec_prot.c | 2 +- tools/testing/selftests/powerpc/mm/pkey_siginfo.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
tools/testing/selftests/powerpc/mm/pkey_exec_prot.c +1 -1
@@ -290,5 +290,5 @@ static int test(void)int main (void ) { -test_harness (test,"pkey_exec_prot" ); +return test_harness (test,"pkey_exec_prot" ); }
tools/testing/selftests/powerpc/mm/pkey_siginfo.c +1 -1
@@ -329,5 +329,5 @@ static int test(void)int main (void ) { -test_harness (test,"pkey_siginfo" ); +return test_harness (test,"pkey_siginfo" ); }
Greg Kroah-Hartman
maintainerPATCH 161/199 sh_eth: Fix power down vs. is_opened flag ordering
In reply to Greg Kroah-HartmanFrom: Geert Uytterhoeven <[email protected]>
commit f6a2e94b3f9d89cb40771ff746b16b5687650cbb upstream.
sh_eth_close() does a synchronous power down of the device before marking it closed. Revert the order, to make sure the device is never marked opened while suspended.
While at it, use pm_runtime_put() instead of pm_runtime_put_sync(), as there is no reason to do a synchronous power down.
--- drivers/net/ethernet/renesas/sh_eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/renesas/sh_eth.c +2 -2
@@ -2606,10 +2606,10 @@ static int sh_eth_close(struct net_devic/* Free all the skbuffs in the Rx queue and the DMA buffer. */ sh_eth_ring_free (ndev); -pm_runtime_put_sync (&mdp->pdev->dev); - mdp->is_opened =0 ; +pm_runtime_put (&mdp->pdev->dev); +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 162/199 nvme-pci: refactor nvme_unmap_data
In reply to Greg Kroah-HartmanFrom: Christoph Hellwig <[email protected]>
commit 9275c206f88e5c49cb3e71932c81c8561083db9e upstream.
Split out three helpers from nvme_unmap_data that will allow finer grained unwinding from nvme_map_data.
--- drivers/nvme/host/pci.c | 77 ++++++++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 28 deletions(-)
drivers/nvme/host/pci.c +49 -28
@@ -542,50 +542,71 @@ static inline bool nvme_pci_use_sgls(strreturn true; } -static void nvme_unmap_data (struct nvme_dev *dev,struct request *req) +static void nvme_free_prps (struct nvme_dev *dev,struct request *req) { -struct nvme_iod *iod =blk_mq_rq_to_pdu (req);const int last_prp =NVME_CTRL_PAGE_SIZE /sizeof (__le64) -1 ; -dma_addr_t dma_addr = iod->first_dma, next_dma_addr; +struct nvme_iod *iod =blk_mq_rq_to_pdu (req); +dma_addr_t dma_addr = iod->first_dma;int i; -if (iod->dma_len) { -dma_unmap_page (dev->dev, dma_addr, iod->dma_len, -rq_dma_dir (req)); -return ; +for (i =0 ; i < iod->npages; i++) { +__le64 *prp_list =nvme_pci_iod_list (req)[i]; +dma_addr_t next_dma_addr =le64_to_cpu (prp_list[last_prp]); + +dma_pool_free (dev->prp_page_pool, prp_list, dma_addr); + dma_addr = next_dma_addr; } -WARN_ON_ONCE (!iod->nents); +} -if (is_pci_p2pdma_page (sg_page (iod->sg))) -pci_p2pdma_unmap_sg (dev->dev, iod->sg, iod->nents, -rq_dma_dir (req)); -else -dma_unmap_sg (dev->dev, iod->sg, iod->nents,rq_dma_dir (req)); +static void nvme_free_sgls (struct nvme_dev *dev,struct request *req) +{ +const int last_sg =SGES_PER_PAGE -1 ; +struct nvme_iod *iod =blk_mq_rq_to_pdu (req); +dma_addr_t dma_addr = iod->first_dma; +int i; +for (i =0 ; i < iod->npages; i++) { +struct nvme_sgl_desc *sg_list =nvme_pci_iod_list (req)[i]; +dma_addr_t next_dma_addr =le64_to_cpu ((sg_list[last_sg]).addr); -if (iod->npages ==0 ) -dma_pool_free (dev->prp_small_pool,nvme_pci_iod_list (req)[0 ], - dma_addr); +dma_pool_free (dev->prp_page_pool, sg_list, dma_addr); + dma_addr = next_dma_addr; + } -for (i =0 ; i < iod->npages; i++) { -void *addr =nvme_pci_iod_list (req)[i]; +} -if (iod->use_sgl) { -struct nvme_sgl_desc *sg_list = addr; +static void nvme_unmap_sg (struct nvme_dev *dev,struct request *req) +{ +struct nvme_iod *iod =blk_mq_rq_to_pdu (req); - next_dma_addr = -le64_to_cpu ((sg_list[SGES_PER_PAGE -1 ]).addr); - }else { -__le64 *prp_list = addr; +if (is_pci_p2pdma_page (sg_page (iod->sg))) +pci_p2pdma_unmap_sg (dev->dev, iod->sg, iod->nents, +rq_dma_dir (req)); +else +dma_unmap_sg (dev->dev, iod->sg, iod->nents,rq_dma_dir (req)); +} - next_dma_addr =le64_to_cpu (prp_list[last_prp]); - } +static void nvme_unmap_data (struct nvme_dev *dev,struct request *req) +{ +struct nvme_iod *iod =blk_mq_rq_to_pdu (req); -dma_pool_free (dev->prp_page_pool, addr, dma_addr); - dma_addr = next_dma_addr; +if (iod->dma_len) { +dma_unmap_page (dev->dev, iod->first_dma, iod->dma_len, +rq_dma_dir (req)); +return ; } +WARN_ON_ONCE (!iod->nents); + +nvme_unmap_sg (dev, req); +if (iod->npages ==0 ) +dma_pool_free (dev->prp_small_pool,nvme_pci_iod_list (req)[0 ], + iod->first_dma); +else if (iod->use_sgl) +nvme_free_sgls (dev, req); +else +nvme_free_prps (dev, req);mempool_free (iod->sg, dev->iod_mempool); }
Greg Kroah-Hartman
maintainerPATCH 163/199 nvme-pci: fix error unwind in nvme_map_data
In reply to Greg Kroah-HartmanFrom: Christoph Hellwig <[email protected]>
commit fa0732168fa1369dd089e5b06d6158a68229f7b7 upstream.
Properly unwind step by step using refactored helpers from nvme_unmap_data to avoid a potential double dma_unmap on a mapping failure.
--- drivers/nvme/host/pci.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-)
drivers/nvme/host/pci.c +18 -10
@@ -682,7 +682,7 @@ static blk_status_t nvme_pci_setup_prps(__le64 *old_prp_list = prp_list; prp_list =dma_pool_alloc (pool,GFP_ATOMIC , &prp_dma);if (!prp_list) -return BLK_STS_RESOURCE ; + goto free_prps; list[iod->npages++] = prp_list; prp_list[0 ] = old_prp_list[i -1 ]; old_prp_list[i -1 ] =cpu_to_le64 (prp_dma);
@@ -702,14 +702,14 @@ static blk_status_t nvme_pci_setup_prps( dma_addr =sg_dma_address (sg); dma_len =sg_dma_len (sg); } - done: cmnd->dptr.prp1 =cpu_to_le64 (sg_dma_address (iod->sg)); cmnd->dptr.prp2 =cpu_to_le64 (iod->first_dma); -return BLK_STS_OK ; - - bad_sgl: +free_prps: +nvme_free_prps (dev, req); +return BLK_STS_RESOURCE ; +bad_sgl:WARN (DO_ONCE (nvme_print_sgl, iod->sg, iod->nents),"Invalid SGL for payload:%d nents:%d\n" ,blk_rq_payload_bytes (req), iod->nents);
@@ -781,7 +781,7 @@ static blk_status_t nvme_pci_setup_sgls( sg_list =dma_pool_alloc (pool,GFP_ATOMIC , &sgl_dma);if (!sg_list) -return BLK_STS_RESOURCE ; + goto free_sgls; i =0 ;nvme_pci_iod_list (req)[iod->npages++] = sg_list;
@@ -794,6 +794,9 @@ static blk_status_t nvme_pci_setup_sgls( }while (--entries >0 );return BLK_STS_OK ; +free_sgls: +nvme_free_sgls (dev, req); +return BLK_STS_RESOURCE ; } static blk_status_t nvme_setup_prp_simple(struct nvme_dev *dev,
@@ -862,7 +865,7 @@ static blk_status_t nvme_map_data(structsg_init_table (iod->sg,blk_rq_nr_phys_segments (req)); iod->nents =blk_rq_map_sg (req->q, req, iod->sg);if (!iod->nents) - goto out; + goto out_free_sg;if (is_pci_p2pdma_page (sg_page (iod->sg))) nr_mapped = pci_p2pdma_map_sg_attrs(dev->dev, iod->sg,
@@ -871,16 +874,21 @@ static blk_status_t nvme_map_data(struct nr_mapped =dma_map_sg_attrs (dev->dev, iod->sg, iod->nents,rq_dma_dir (req),DMA_ATTR_NO_WARN );if (!nr_mapped) - goto out; + goto out_free_sg; iod->use_sgl =nvme_pci_use_sgls (dev, req);if (iod->use_sgl) ret =nvme_pci_setup_sgls (dev, req, &cmnd->rw, nr_mapped);else ret =nvme_pci_setup_prps (dev, req, &cmnd->rw); -out:if (ret !=BLK_STS_OK ) -nvme_unmap_data (dev, req); + goto out_unmap_sg; +return BLK_STS_OK ; + +out_unmap_sg: +nvme_unmap_sg (dev, req); +out_free_sg: +mempool_free (iod->sg, dev->iod_mempool);return ret; }
Greg Kroah-Hartman
maintainerPATCH 164/199 cachefiles: Drop superfluous readpages aops NULL check
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit db58465f1121086b524be80be39d1fedbe5387f3 upstream.
After the recent actions to convert readpages aops to readahead, the NULL checks of readpages aops in cachefiles_read_or_alloc_page() may hit falsely. More badly, it's an ASSERT() call, and this panics.
Drop the superfluous NULL checks for fixing this regression.
[DH: Note that cachefiles never actually used readpages, so this check was
never actually necessary]
--- fs/cachefiles/rdwr.c | 2 -- 1 file changed, 2 deletions(-)
fs/cachefiles/rdwr.c +0 -2
@@ -413,7 +413,6 @@ int cachefiles_read_or_alloc_page(struct inode =d_backing_inode (object->backer);ASSERT (S_ISREG (inode->i_mode)); -ASSERT (inode->i_mapping->a_ops->readpages);/* calculate the shift required to use bmap */ shift =PAGE_SHIFT - inode->i_sb->s_blocksize_bits;
@@ -713,7 +712,6 @@ int cachefiles_read_or_alloc_pages(struc inode =d_backing_inode (object->backer);ASSERT (S_ISREG (inode->i_mode)); -ASSERT (inode->i_mapping->a_ops->readpages);/* calculate the shift required to use bmap */ shift =PAGE_SHIFT - inode->i_sb->s_blocksize_bits;
Greg Kroah-Hartman
maintainerPATCH 165/199 lightnvm: fix memory leak when submit fails
In reply to Greg Kroah-HartmanFrom: Pan Bian <[email protected]>
commit 97784481757fba7570121a70dd37ca74a29f50a8 upstream.
The allocated page is not released if error occurs in nvm_submit_io_sync_raw(). __free_page() is moved ealier to avoid possible memory leak issue.
--- drivers/lightnvm/core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/lightnvm/core.c +1 -2
@@ -844,11 +844,10 @@ static int nvm_bb_chunk_sense(struct nvm rqd.ppa_addr =generic_to_dev_addr (dev, ppa); ret =nvm_submit_io_sync_raw (dev, &rqd); +__free_page (page);if (ret)return ret; -__free_page (page); -return rqd.error; }
Greg Kroah-Hartman
maintainerPATCH 166/199 skbuff: back tiny skbs with kmalloc() in __netdev_alloc_skb() too
In reply to Greg Kroah-HartmanFrom: Alexander Lobakin <[email protected]>
commit 66c556025d687dbdd0f748c5e1df89c977b6c02a upstream.
Commit 3226b158e67c ("net: avoid 32 x truesize under-estimation for tiny skbs") ensured that skbs with data size lower than 1025 bytes will be kmalloc'ed to avoid excessive page cache fragmentation and memory consumption.
However, the fix adressed only __napi_alloc_skb() (primarily for virtio_net and napi_get_frags()), but the issue can still be achieved through __netdev_alloc_skb(), which is still used by several drivers. Drivers often allocate a tiny skb for headers and place the rest of the frame to frags (so-called copybreak).
Mirror the condition to __netdev_alloc_skb() to handle this case too.
Since v1 [0]:
- fix "Fixes:" tag;
- refine commit message (mention copybreak usecase).
[0] https://lore.kernel.org/netdev/[email protected]
--- net/core/skbuff.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
net/core/skbuff.c +5 -1
@@ -432,7 +432,11 @@ struct sk_buff *__netdev_alloc_skb(struc len +=NET_SKB_PAD ; -if ((len >SKB_WITH_OVERHEAD (PAGE_SIZE )) || +/* If requested length is either too small or too big, +* we use kmalloc() for skb->head allocation. +*/ +if (len <=SKB_WITH_OVERHEAD (1024 ) || + len >SKB_WITH_OVERHEAD (PAGE_SIZE ) || (gfp_mask & (__GFP_DIRECT_RECLAIM |GFP_DMA ))) { skb =__alloc_skb (len, gfp_mask,SKB_ALLOC_RX ,NUMA_NO_NODE );if (!skb)
Greg Kroah-Hartman
maintainerPATCH 167/199 kasan: fix unaligned address is unhandled in kasan_remove_zero_shadow
In reply to Greg Kroah-HartmanFrom: Lecopzer Chen <[email protected]>
commit a11a496ee6e2ab6ed850233c96b94caf042af0b9 upstream.
During testing kasan_populate_early_shadow and kasan_remove_zero_shadow, if the shadow start and end address in kasan_remove_zero_shadow() is not aligned to PMD_SIZE, the remain unaligned PTE won't be removed.
In the test case for kasan_remove_zero_shadow():
shadow_start: 0xffffffb802000000, shadow end: 0xffffffbfbe000000
3-level page table:
PUD_SIZE: 0x40000000 PMD_SIZE: 0x200000 PAGE_SIZE: 4K0xffffffbf80000000 ~ 0xffffffbfbdf80000 will not be removed because in kasan_remove_pud_table(), kasan_pmd_table(*pud) is true but the next address is 0xffffffbfbdf80000 which is not aligned to PUD_SIZE.
In the correct condition, this should fallback to the next level kasan_remove_pmd_table() but the condition flow always continue to skip the unaligned part.
Fix by correcting the condition when next and addr are neither aligned.
--- mm/kasan/init.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-)
mm/kasan/init.c +12 -8
@@ -377,9 +377,10 @@ static void kasan_remove_pmd_table(pmd_tif (kasan_pte_table (*pmd)) {if (IS_ALIGNED (addr,PMD_SIZE ) && -IS_ALIGNED (next,PMD_SIZE )) +IS_ALIGNED (next,PMD_SIZE )) {pmd_clear (pmd); -continue ; +continue ; + } } pte =pte_offset_kernel (pmd, addr);kasan_remove_pte_table (pte, addr, next);
@@ -402,9 +403,10 @@ static void kasan_remove_pud_table(pud_tif (kasan_pmd_table (*pud)) {if (IS_ALIGNED (addr,PUD_SIZE ) && -IS_ALIGNED (next,PUD_SIZE )) +IS_ALIGNED (next,PUD_SIZE )) {pud_clear (pud); -continue ; +continue ; + } } pmd =pmd_offset (pud, addr); pmd_base =pmd_offset (pud,0 );
@@ -428,9 +430,10 @@ static void kasan_remove_p4d_table(p4d_tif (kasan_pud_table (*p4d)) {if (IS_ALIGNED (addr,P4D_SIZE ) && -IS_ALIGNED (next,P4D_SIZE )) +IS_ALIGNED (next,P4D_SIZE )) {p4d_clear (p4d); -continue ; +continue ; + } } pud =pud_offset (p4d, addr);kasan_remove_pud_table (pud, addr, next);
@@ -462,9 +465,10 @@ void kasan_remove_zero_shadow(void *starif (kasan_p4d_table (*pgd)) {if (IS_ALIGNED (addr,PGDIR_SIZE ) && -IS_ALIGNED (next,PGDIR_SIZE )) +IS_ALIGNED (next,PGDIR_SIZE )) {pgd_clear (pgd); -continue ; +continue ; + } } p4d =p4d_offset (pgd, addr);
Greg Kroah-Hartman
maintainerPATCH 168/199 kasan: fix incorrect arguments passing in kasan_add_zero_shadow
In reply to Greg Kroah-HartmanFrom: Lecopzer Chen <[email protected]>
commit 5dabd1712cd056814f9ab15f1d68157ceb04e741 upstream.
kasan_remove_zero_shadow() shall use original virtual address, start and size, instead of shadow address.
--- mm/kasan/init.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
mm/kasan/init.c +1 -2
@@ -492,7 +492,6 @@ int kasan_add_zero_shadow(void *start, u ret =kasan_populate_early_shadow (shadow_start, shadow_end);if (ret) -kasan_remove_zero_shadow (shadow_start, - size >>KASAN_SHADOW_SCALE_SHIFT ); +kasan_remove_zero_shadow (start, size);return ret; }
Greg Kroah-Hartman
maintainerPATCH 169/199 tcp: fix TCP socket rehash stats mis-accounting
In reply to Greg Kroah-HartmanFrom: Yuchung Cheng <[email protected]>
commit 9c30ae8398b0813e237bde387d67a7f74ab2db2d upstream.
The previous commit 32efcc06d2a1 ("tcp: export count for rehash attempts") would mis-account rehashing SNMP and socket stats:
a. During handshake of an active open, only counts the first
SYN timeout
b. After handshake of passive and active open, stop updating
after (roughly) TCP_RETRIES1 recurring RTOs
c. After the socket aborts, over count timeout_rehash by 1
This patch fixes this by checking the rehash result from sk_rethink_txhash.
--- include/net/sock.h | 17 ++++++++++++----- net/ipv4/tcp_input.c | 5 ++--- net/ipv4/tcp_timer.c | 22 ++++++++-------------- 3 files changed, 22 insertions(+), 22 deletions(-)
include/net/sock.h +12 -5
@@ -1903,10 +1903,13 @@ static inline void sk_set_txhash(struct sk->sk_txhash =net_tx_rndhash (); } -static inline void sk_rethink_txhash (struct sock *sk) +static inline bool sk_rethink_txhash (struct sock *sk) { -if (sk->sk_txhash) +if (sk->sk_txhash) {sk_set_txhash (sk); +return true; + } +return false; } static inline struct dst_entry *
@@ -1929,12 +1932,10 @@ sk_dst_get(struct sock *sk)return dst; } -static inline void dst_negative_advice (struct sock *sk) +static inline void __dst_negative_advice (struct sock *sk) {struct dst_entry *ndst, *dst =__sk_dst_get (sk); -sk_rethink_txhash (sk); -if (dst && dst->ops->negative_advice) { ndst = dst->ops->negative_advice (dst);
@@ -1946,6 +1947,12 @@ static inline void dst_negative_advice(s } } +static inline void dst_negative_advice (struct sock *sk) +{ +sk_rethink_txhash (sk); +__dst_negative_advice (sk); +} +static inline void __sk_dst_set (struct sock *sk,struct dst_entry *dst) {
net/ipv4/tcp_input.c +2 -3
@@ -4379,10 +4379,9 @@ static void tcp_rcv_spurious_retrans(str* The receiver remembers and reflects via DSACKs. Leverage the * DSACK state and change the txhash to re-route speculatively. */ -if (TCP_SKB_CB (skb)->seq ==tcp_sk (sk)->duplicate_sack[0 ].start_seq) { -sk_rethink_txhash (sk); +if (TCP_SKB_CB (skb)->seq ==tcp_sk (sk)->duplicate_sack[0 ].start_seq && +sk_rethink_txhash (sk))NET_INC_STATS (sock_net (sk),LINUX_MIB_TCPDUPLICATEDATAREHASH ); - } }static void tcp_send_dupack (struct sock *sk,const struct sk_buff *skb)
net/ipv4/tcp_timer.c +8 -14
@@ -219,14 +219,8 @@ static int tcp_write_timeout(struct sockint retry_until;if ((1 << sk->sk_state) & (TCPF_SYN_SENT |TCPF_SYN_RECV )) { -if (icsk->icsk_retransmits) { -dst_negative_advice (sk); - }else { -sk_rethink_txhash (sk); - tp->timeout_rehash++; -__NET_INC_STATS (sock_net (sk), -LINUX_MIB_TCPTIMEOUTREHASH ); - } +if (icsk->icsk_retransmits) +__dst_negative_advice (sk); retry_until = icsk->icsk_syn_retries ? : net->ipv4.sysctl_tcp_syn_retries; expired = icsk->icsk_retransmits >= retry_until; }else {
@@ -234,12 +228,7 @@ static int tcp_write_timeout(struct sock/* Black hole detection */ tcp_mtu_probing (icsk, sk); -dst_negative_advice (sk); - }else { -sk_rethink_txhash (sk); - tp->timeout_rehash++; -__NET_INC_STATS (sock_net (sk), -LINUX_MIB_TCPTIMEOUTREHASH ); +__dst_negative_advice (sk); } retry_until = net->ipv4.sysctl_tcp_retries2;
@@ -270,6 +259,11 @@ static int tcp_write_timeout(struct sockreturn 1 ; } +if (sk_rethink_txhash (sk)) { + tp->timeout_rehash++; +__NET_INC_STATS (sock_net (sk),LINUX_MIB_TCPTIMEOUTREHASH ); + } +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 170/199 net_sched: gen_estimator: support large ewma log
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
commit dd5e073381f2ada3630f36be42833c6e9c78b75e upstream.
syzbot report reminded us that very big ewma_log were supported in the past, even if they made litle sense.
tc qdisc replace dev xxx root est 1sec 131072sec ...
While fixing the bug, also add boundary checks for ewma_log, in line with range supported by iproute2.
UBSAN: shift-out-of-bounds in net/core/gen_estimator.c:83:38 shift exponent -1 is negative CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.10.0-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: <IRQ> __dump_stack lib/dump_stack.c:79 [inline] dump_stack+0x107/0x163 lib/dump_stack.c:120 ubsan_epilogue+0xb/0x5a lib/ubsan.c:148 __ubsan_handle_shift_out_of_bounds.cold+0xb1/0x181 lib/ubsan.c:395 est_timer.cold+0xbb/0x12d net/core/gen_estimator.c:83 call_timer_fn+0x1a5/0x710 kernel/time/timer.c:1417 expire_timers kernel/time/timer.c:1462 [inline] __run_timers.part.0+0x692/0xa80 kernel/time/timer.c:1731 __run_timers kernel/time/timer.c:1712 [inline] run_timer_softirq+0xb3/0x1d0 kernel/time/timer.c:1744 __do_softirq+0x2bc/0xa77 kernel/softirq.c:343 asm_call_irq_on_stack+0xf/0x20 </IRQ> __run_on_irqstack arch/x86/include/asm/irq_stack.h:26 [inline] run_on_irqstack_cond arch/x86/include/asm/irq_stack.h:77 [inline] do_softirq_own_stack+0xaa/0xd0 arch/x86/kernel/irq_64.c:77 invoke_softirq kernel/softirq.c:226 [inline] __irq_exit_rcu+0x17f/0x200 kernel/softirq.c:420 irq_exit_rcu+0x5/0x20 kernel/softirq.c:432 sysvec_apic_timer_interrupt+0x4d/0x100 arch/x86/kernel/apic/apic.c:1096 asm_sysvec_apic_timer_interrupt+0x12/0x20 arch/x86/include/asm/idtentry.h:628 RIP: 0010:native_save_fl arch/x86/include/asm/irqflags.h:29 [inline] RIP: 0010:arch_local_save_flags arch/x86/include/asm/irqflags.h:79 [inline] RIP: 0010:arch_irqs_disabled arch/x86/include/asm/irqflags.h:169 [inline] RIP: 0010:acpi_safe_halt drivers/acpi/processor_idle.c:111 [inline] RIP: 0010:acpi_idle_do_entry+0x1c9/0x250 drivers/acpi/processor_idle.c:516
--- net/core/gen_estimator.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
net/core/gen_estimator.c +7 -4
@@ -80,11 +80,11 @@ static void est_timer(struct timer_listu64 rate, brate;est_fetch_counters (est, &b); - brate = (b.bytes - est->last_bytes) << (10 - est->ewma_log - est->intvl_log); - brate -= (est->avbps >> est->ewma_log); + brate = (b.bytes - est->last_bytes) << (10 - est->intvl_log); + brate = (brate >> est->ewma_log) - (est->avbps >> est->ewma_log); - rate = (b.packets - est->last_packets) << (10 - est->ewma_log - est->intvl_log); - rate -= (est->avpps >> est->ewma_log); + rate = (b.packets - est->last_packets) << (10 - est->intvl_log); + rate = (rate >> est->ewma_log) - (est->avpps >> est->ewma_log);write_seqcount_begin (&est->seq); est->avbps += brate;
@@ -143,6 +143,9 @@ int gen_new_estimator(struct gnet_stats_if (parm->interval <-2 || parm->interval >3 )return -EINVAL ; +if (parm->ewma_log ==0 || parm->ewma_log >=31 ) +return -EINVAL ; + est =kzalloc (sizeof (*est),GFP_KERNEL );if (!est)return -ENOBUFS ;
Greg Kroah-Hartman
maintainerPATCH 171/199 udp: mask TOS bits in udp_v4_early_demux()
In reply to Greg Kroah-HartmanFrom: Guillaume Nault <[email protected]>
commit 8d2b51b008c25240914984208b2ced57d1dd25a5 upstream.
udp_v4_early_demux() is the only function that calls ip_mc_validate_source() with a TOS that hasn't been masked with IPTOS_RT_MASK.
This results in different behaviours for incoming multicast UDPv4 packets, depending on if ip_mc_validate_source() is called from the early-demux path (udp_v4_early_demux) or from the regular input path (ip_route_input_noref).
ECN would normally not be used with UDP multicast packets, so the practical consequences should be limited on that side. However, IPTOS_RT_MASK is used to also masks the TOS' high order bits, to align with the non-early-demux path behaviour.
Reproducer:
Setup two netns, connected with veth:
$ ip netns add ns0 $ ip netns add ns1 $ ip -netns ns0 link set dev lo up $ ip -netns ns1 link set dev lo up $ ip link add name veth01 netns ns0 type veth peer name veth10 netns ns1 $ ip -netns ns0 link set dev veth01 up $ ip -netns ns1 link set dev veth10 up $ ip -netns ns0 address add 192.0.2.10 peer 192.0.2.11/32 dev veth01 $ ip -netns ns1 address add 192.0.2.11 peer 192.0.2.10/32 dev veth10
In ns0, add route to multicast address 224.0.2.0/24 using source address 198.51.100.10:
$ ip -netns ns0 address add 198.51.100.10/32 dev lo $ ip -netns ns0 route add 224.0.2.0/24 dev veth01 src 198.51.100.10
In ns1, define route to 198.51.100.10, only for packets with TOS 4:
$ ip -netns ns1 route add 198.51.100.10/32 tos 4 dev veth10
Also activate rp_filter in ns1, so that incoming packets not matching the above route get dropped:
$ ip netns exec ns1 sysctl -wq net.ipv4.conf.veth10.rp_filter=1
Now try to receive packets on 224.0.2.11:
$ ip netns exec ns1 socat UDP-RECVFROM:1111,ip-add-membership=224.0.2.11:veth10,ignoreeof -
In ns0, send packet to 224.0.2.11 with TOS 4 and ECT(0) (that is, tos 6 for socat):
$ echo test0 | ip netns exec ns0 socat - UDP-DATAGRAM:224.0.2.11:1111,bind=:1111,tos=6
The "test0" message is properly received by socat in ns1, because early-demux has no cached dst to use, so source address validation is done by ip_route_input_mc(), which receives a TOS that has the ECN bits masked.
Now send another packet to 224.0.2.11, still with TOS 4 and ECT(0):
$ echo test1 | ip netns exec ns0 socat - UDP-DATAGRAM:224.0.2.11:1111,bind=:1111,tos=6
The "test1" message isn't received by socat in ns1, because, now, early-demux has a cached dst to use and calls ip_mc_validate_source() immediately, without masking the ECN bits.
--- net/ipv4/udp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/ipv4/udp.c +2 -1
@@ -2553,7 +2553,8 @@ int udp_v4_early_demux(struct sk_buff *s*/ if (!inet_sk (sk)->inet_daddr && in_dev)return ip_mc_validate_source (skb, iph->daddr, - iph->saddr, iph->tos, + iph->saddr, + iph->tos &IPTOS_RT_MASK , skb->dev, in_dev, &itag); }return 0 ;
Greg Kroah-Hartman
maintainerPATCH 172/199 ipv6: create multicast route with RTPROT_KERNEL
In reply to Greg Kroah-HartmanFrom: Matteo Croce <[email protected]>
commit a826b04303a40d52439aa141035fca5654ccaccd upstream.
The ff00::/8 multicast route is created without specifying the fc_protocol field, so the default RTPROT_BOOT value is used:
$ ip -6 -d route unicast ::1 dev lo proto kernel scope global metric 256 pref medium unicast fe80::/64 dev eth0 proto kernel scope global metric 256 pref medium unicast ff00::/8 dev eth0 proto boot scope global metric 256 pref medium
As the documentation says, this value identifies routes installed during boot, but the route is created when interface is set up. Change the value to RTPROT_KERNEL which is a better value.
--- net/ipv6/addrconf.c | 1 + 1 file changed, 1 insertion(+)
net/ipv6/addrconf.c +1 -0
@@ -2468,6 +2468,7 @@ static void addrconf_add_mroute(struct n .fc_flags = RTF_UP, .fc_type = RTN_UNICAST, .fc_nlinfo.nl_net = dev_net(dev), + .fc_protocol = RTPROT_KERNEL, };ipv6_addr_set (&cfg.fc_dst,htonl (0xFF000000 ),0 ,0 ,0 );
Greg Kroah-Hartman
maintainerPATCH 173/199 net_sched: avoid shift-out-of-bounds in tcindex_set_parms()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
commit bcd0cf19ef8258ac31b9a20248b05c15a1f4b4b0 upstream.
tc_index being 16bit wide, we need to check that TCA_TCINDEX_SHIFT attribute is not silly.
UBSAN: shift-out-of-bounds in net/sched/cls_tcindex.c:260:29 shift exponent 255 is too large for 32-bit type 'int' CPU: 0 PID: 8516 Comm: syz-executor228 Not tainted 5.10.0-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:79 [inline] dump_stack+0x107/0x163 lib/dump_stack.c:120 ubsan_epilogue+0xb/0x5a lib/ubsan.c:148 __ubsan_handle_shift_out_of_bounds.cold+0xb1/0x181 lib/ubsan.c:395 valid_perfect_hash net/sched/cls_tcindex.c:260 [inline] tcindex_set_parms.cold+0x1b/0x215 net/sched/cls_tcindex.c:425 tcindex_change+0x232/0x340 net/sched/cls_tcindex.c:546 tc_new_tfilter+0x13fb/0x21b0 net/sched/cls_api.c:2127 rtnetlink_rcv_msg+0x8b6/0xb80 net/core/rtnetlink.c:5555 netlink_rcv_skb+0x153/0x420 net/netlink/af_netlink.c:2494 netlink_unicast_kernel net/netlink/af_netlink.c:1304 [inline] netlink_unicast+0x533/0x7d0 net/netlink/af_netlink.c:1330 netlink_sendmsg+0x907/0xe40 net/netlink/af_netlink.c:1919 sock_sendmsg_nosec net/socket.c:652 [inline] sock_sendmsg+0xcf/0x120 net/socket.c:672 ____sys_sendmsg+0x6e8/0x810 net/socket.c:2336 ___sys_sendmsg+0xf3/0x170 net/socket.c:2390 __sys_sendmsg+0xe5/0x1b0 net/socket.c:2423 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xa9
--- net/sched/cls_tcindex.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
net/sched/cls_tcindex.c +6 -2
@@ -366,9 +366,13 @@ tcindex_set_parms(struct net *net, strucif (tb[TCA_TCINDEX_MASK ]) cp->mask =nla_get_u16 (tb[TCA_TCINDEX_MASK ]); -if (tb[TCA_TCINDEX_SHIFT ]) +if (tb[TCA_TCINDEX_SHIFT ]) { cp->shift =nla_get_u32 (tb[TCA_TCINDEX_SHIFT ]); - +if (cp->shift >16 ) { + err = -EINVAL ; + goto errout; + } + }if (!cp->hash) {/* Hash not specified, use perfect hash if the upper limit * of the hashing index is below the threshold.
Greg Kroah-Hartman
maintainerPATCH 174/199 net_sched: reject silly cell_log in qdisc_get_rtab()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
commit e4bedf48aaa5552bc1f49703abd17606e7e6e82a upstream.
iproute2 probably never goes beyond 8 for the cell exponent, but stick to the max shift exponent for signed 32bit.
UBSAN reported:
UBSAN: shift-out-of-bounds in net/sched/sch_api.c:389:22 shift exponent 130 is too large for 32-bit type 'int' CPU: 1 PID: 8450 Comm: syz-executor586 Not tainted 5.11.0-rc3-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:79 [inline] dump_stack+0x183/0x22e lib/dump_stack.c:120 ubsan_epilogue lib/ubsan.c:148 [inline] __ubsan_handle_shift_out_of_bounds+0x432/0x4d0 lib/ubsan.c:395 __detect_linklayer+0x2a9/0x330 net/sched/sch_api.c:389 qdisc_get_rtab+0x2b5/0x410 net/sched/sch_api.c:435 cbq_init+0x28f/0x12c0 net/sched/sch_cbq.c:1180 qdisc_create+0x801/0x1470 net/sched/sch_api.c:1246 tc_modify_qdisc+0x9e3/0x1fc0 net/sched/sch_api.c:1662 rtnetlink_rcv_msg+0xb1d/0xe60 net/core/rtnetlink.c:5564 netlink_rcv_skb+0x1f0/0x460 net/netlink/af_netlink.c:2494 netlink_unicast_kernel net/netlink/af_netlink.c:1304 [inline] netlink_unicast+0x7de/0x9b0 net/netlink/af_netlink.c:1330 netlink_sendmsg+0xaa6/0xe90 net/netlink/af_netlink.c:1919 sock_sendmsg_nosec net/socket.c:652 [inline] sock_sendmsg net/socket.c:672 [inline] ____sys_sendmsg+0x5a2/0x900 net/socket.c:2345 ___sys_sendmsg net/socket.c:2399 [inline] __sys_sendmsg+0x319/0x400 net/socket.c:2432 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xa9
--- net/sched/sch_api.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/sched/sch_api.c +2 -1
@@ -412,7 +412,8 @@ struct qdisc_rate_table *qdisc_get_rtab( {struct qdisc_rate_table *rtab; -if (tab ==NULL || r->rate ==0 || r->cell_log ==0 || +if (tab ==NULL || r->rate ==0 || + r->cell_log ==0 || r->cell_log >=32 ||nla_len (tab) !=TC_RTAB_SIZE ) {NL_SET_ERR_MSG (extack,"Invalid rate table parameters for searching" );return NULL ;
Greg Kroah-Hartman
maintainerPATCH 175/199 ipv6: set multicast flag on the multicast route
In reply to Greg Kroah-HartmanFrom: Matteo Croce <[email protected]>
commit ceed9038b2783d14e0422bdc6fd04f70580efb4c upstream.
The multicast route ff00::/8 is created with type RTN_UNICAST:
$ ip -6 -d route unicast ::1 dev lo proto kernel scope global metric 256 pref medium unicast fe80::/64 dev eth0 proto kernel scope global metric 256 pref medium unicast ff00::/8 dev eth0 proto kernel scope global metric 256 pref medium
Set the type to RTN_MULTICAST which is more appropriate.
--- net/ipv6/addrconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv6/addrconf.c +1 -1
@@ -2466,7 +2466,7 @@ static void addrconf_add_mroute(struct n .fc_ifindex = dev->ifindex, .fc_dst_len = 8, .fc_flags = RTF_UP, - .fc_type = RTN_UNICAST, + .fc_type = RTN_MULTICAST, .fc_nlinfo.nl_net = dev_net(dev), .fc_protocol = RTPROT_KERNEL, };
Greg Kroah-Hartman
maintainerPATCH 176/199 net: mscc: ocelot: allow offloading of bridge on top of LAG
In reply to Greg Kroah-HartmanFrom: Vladimir Oltean <[email protected]>
commit 79267ae22615496655feee2db0848f6786bcf67a upstream.
The blamed commit was too aggressive, and it made ocelot_netdevice_event react only to network interface events emitted for the ocelot switch ports.
In fact, only the PRECHANGEUPPER should have had that check.
When we ignore all events that are not for us, we miss the fact that the upper of the LAG changes, and the bonding interface gets enslaved to a bridge. This is an operation we could offload under certain conditions.
--- drivers/net/ethernet/mscc/ocelot_net.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/net/ethernet/mscc/ocelot_net.c +1 -3
@@ -952,10 +952,8 @@ static int ocelot_netdevice_event(structstruct net_device *dev =netdev_notifier_info_to_dev (ptr);int ret =0 ; -if (!ocelot_netdevice_dev_check (dev)) -return 0 ; -if (event ==NETDEV_PRECHANGEUPPER && +ocelot_netdevice_dev_check (dev) &&netif_is_lag_master (info->upper_dev)) {struct netdev_lag_upper_info *lag_upper_info = info->upper_info;struct netlink_ext_ack *extack;
Greg Kroah-Hartman
maintainerPATCH 177/199 net: Disable NETIF_F_HW_TLS_RX when RXCSUM is disabled
In reply to Greg Kroah-HartmanFrom: Tariq Toukan <[email protected]>
commit a3eb4e9d4c9218476d05c52dfd2be3d6fdce6b91 upstream.
With NETIF_F_HW_TLS_RX packets are decrypted in HW. This cannot be logically done when RXCSUM offload is off.
--- net/core/dev.c | 5 +++++ 1 file changed, 5 insertions(+)
net/core/dev.c +5 -0
@@ -9602,6 +9602,11 @@ static netdev_features_t netdev_fix_feat } } +if ((features &NETIF_F_HW_TLS_RX ) && !(features &NETIF_F_RXCSUM )) { +netdev_dbg (dev,"Dropping TLS RX HW offload feature since no RXCSUM feature.\n" ); + features &= ~NETIF_F_HW_TLS_RX ; + } +return features; }
Greg Kroah-Hartman
maintainerPATCH 178/199 net: dsa: b53: fix an off by one in checking "vlan->vid"
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
commit 8e4052c32d6b4b39c1e13c652c7e33748d447409 upstream.
The > comparison should be >= to prevent accessing one element beyond the end of the dev->vlans[] array in the caller function, b53_vlan_add(). The "dev->vlans" array is allocated in the b53_switch_init() function and it has "dev->num_vlans" elements.
--- drivers/net/dsa/b53/b53_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/dsa/b53/b53_common.c +1 -1
@@ -1404,7 +1404,7 @@ int b53_vlan_prepare(struct dsa_switch * !(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED))return -EINVAL ; -if (vlan->vid_end > dev->num_vlans) +if (vlan->vid_end >= dev->num_vlans)return -ERANGE ;b53_enable_vlan (dev, true, ds->vlan_filtering);
Greg Kroah-Hartman
maintainerPATCH 179/199 tcp: do not mess with cloned skbs in tcp_add_backlog()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
commit b160c28548bc0a87cbd16d5af6d3edcfd70b8c9a upstream.
Heiner Kallweit reported that some skbs were sent with the following invalid GSO properties :
- gso_size > 0
- gso_type == 0
This was triggerring a WARN_ON_ONCE() in rtl8169_tso_csum_v2.
Juerg Haefliger was able to reproduce a similar issue using a lan78xx NIC and a workload mixing TCP incoming traffic and forwarded packets.
The problem is that tcp_add_backlog() is writing
over gso_segs and gso_size even if the incoming packet will not be coalesced to the backlog tail packet.
While skb_try_coalesce() would bail out if tail packet is cloned, this overwriting would lead to corruptions of other packets cooked by lan78xx, sharing a common super-packet.
The strategy used by lan78xx is to use a big skb, and split it into all received packets using skb_clone() to avoid copies. The drawback of this strategy is that all the small skb share a common struct skb_shared_info.
This patch rewrites TCP gso_size/gso_segs handling to only happen on the tail skb, since skb_try_coalesce() made sure it was not cloned.
--- net/ipv4/tcp_ipv4.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-)
net/ipv4/tcp_ipv4.c +13 -12
@@ -1755,6 +1755,7 @@ int tcp_v4_early_demux(struct sk_buff *sbool tcp_add_backlog (struct sock *sk,struct sk_buff *skb) {u32 limit =READ_ONCE (sk->sk_rcvbuf) +READ_ONCE (sk->sk_sndbuf); +u32 tail_gso_size, tail_gso_segs;struct skb_shared_info *shinfo;const struct tcphdr *th;struct tcphdr *thtail;
@@ -1762,6 +1763,7 @@ bool tcp_add_backlog(struct sock *sk, stunsigned int hdrlen;bool fragstolen;u32 gso_segs; +u32 gso_size;int delta;/* In case all data was pulled from skb frags (in __pskb_pull_tail()),
@@ -1787,13 +1789,6 @@ bool tcp_add_backlog(struct sock *sk, st*/ th = (const struct tcphdr *)skb->data; hdrlen = th->doff *4 ; - shinfo =skb_shinfo (skb); - -if (!shinfo->gso_size) - shinfo->gso_size = skb->len - hdrlen; - -if (!shinfo->gso_segs) - shinfo->gso_segs =1 ; tail = sk->sk_backlog.tail;if (!tail)
@@ -1816,6 +1811,15 @@ bool tcp_add_backlog(struct sock *sk, st goto no_coalesce;__skb_pull (skb, hdrlen); + + shinfo =skb_shinfo (skb); + gso_size = shinfo->gso_size ?: skb->len; + gso_segs = shinfo->gso_segs ?:1 ; + + shinfo =skb_shinfo (tail); + tail_gso_size = shinfo->gso_size ?: (tail->len - hdrlen); + tail_gso_segs = shinfo->gso_segs ?:1 ; +if (skb_try_coalesce (tail, skb, &fragstolen, &delta)) {TCP_SKB_CB (tail)->end_seq =TCP_SKB_CB (skb)->end_seq;
@@ -1842,11 +1846,8 @@ bool tcp_add_backlog(struct sock *sk, st }/* Not as strict as GRO. We only need to carry mss max value */ -skb_shinfo (tail)->gso_size =max (shinfo->gso_size, -skb_shinfo (tail)->gso_size); - - gso_segs =skb_shinfo (tail)->gso_segs + shinfo->gso_segs; -skb_shinfo (tail)->gso_segs =min_t (u32, gso_segs,0xFFFF ); + shinfo->gso_size =max (gso_size, tail_gso_size); + shinfo->gso_segs =min_t (u32, gso_segs + tail_gso_segs,0xFFFF ); sk->sk_backlog.len += delta; __NET_INC_STATS(sock_net(sk),
Greg Kroah-Hartman
maintainerPATCH 180/199 tcp: fix TCP_USER_TIMEOUT with zero window
In reply to Greg Kroah-HartmanFrom: Enke Chen <[email protected]>
commit 9d9b1ee0b2d1c9e02b2338c4a4b0a062d2d3edac upstream.
The TCP session does not terminate with TCP_USER_TIMEOUT when data remain untransmitted due to zero window.
The number of unanswered zero-window probes (tcp_probes_out) is reset to zero with incoming acks irrespective of the window size, as described in tcp_probe_timer():
RFC 1122 4.2.2.17 requires the sender to stay open indefinitely as long as the receiver continues to respond probes. We support this by default and reset icsk_probes_out with incoming ACKs.
This counter, however, is the wrong one to be used in calculating the duration that the window remains closed and data remain untransmitted. Thanks to Jonathan Maxwell <[email protected]> for diagnosing the actual issue.
In this patch a new timestamp is introduced for the socket in order to track the elapsed time for the zero-window probes that have not been answered with any non-zero window ack.
--- include/net/inet_connection_sock.h | 3 +++ net/ipv4/inet_connection_sock.c | 1 + net/ipv4/tcp.c | 1 + net/ipv4/tcp_input.c | 1 + net/ipv4/tcp_output.c | 1 + net/ipv4/tcp_timer.c | 14 +++++++------- 6 files changed, 14 insertions(+), 7 deletions(-)
include/net/inet_connection_sock.h +3 -0
@@ -76,6 +76,8 @@ struct inet_connection_sock_af_ops {* @icsk_ext_hdr_len: Network protocol overhead (IP/IPv6 options) * @icsk_ack: Delayed ACK control data * @icsk_mtup; MTU probing control data +* @icsk_probes_tstamp: Probe timestamp (cleared by non-zero window ack) +* @icsk_user_timeout: TCP_USER_TIMEOUT value */ struct inet_connection_sock {/* inet_sock has to be the first member! */
@@ -129,6 +131,7 @@ struct inet_connection_sock {u32 probe_timestamp; } icsk_mtup; +u32 icsk_probes_tstamp;u32 icsk_user_timeout;u64 icsk_ca_priv[104 /sizeof (u64)];
net/ipv4/inet_connection_sock.c +1 -0
@@ -851,6 +851,7 @@ struct sock *inet_csk_clone_lock(const s newicsk->icsk_retransmits =0 ; newicsk->icsk_backoff =0 ; newicsk->icsk_probes_out =0 ; + newicsk->icsk_probes_tstamp =0 ;/* Deinitialize accept_queue to trap illegal accesses. */ memset (&newicsk->icsk_accept_queue,0 ,sizeof (newicsk->icsk_accept_queue));
net/ipv4/tcp.c +1 -0
@@ -2685,6 +2685,7 @@ int tcp_disconnect(struct sock *sk, int icsk->icsk_backoff =0 ; icsk->icsk_probes_out =0 ; + icsk->icsk_probes_tstamp =0 ; icsk->icsk_rto =TCP_TIMEOUT_INIT ; icsk->icsk_rto_min =TCP_RTO_MIN ; icsk->icsk_delack_max =TCP_DELACK_MAX ;
net/ipv4/tcp_input.c +1 -0
@@ -3370,6 +3370,7 @@ static void tcp_ack_probe(struct sock *sreturn ;if (!after (TCP_SKB_CB (head)->end_seq,tcp_wnd_end (tp))) { icsk->icsk_backoff =0 ; + icsk->icsk_probes_tstamp =0 ;inet_csk_clear_xmit_timer (sk,ICSK_TIME_PROBE0 );/* Socket must be waked up by subsequent tcp_data_snd_check(). * This function is not for random using!
net/ipv4/tcp_output.c +1 -0
@@ -4080,6 +4080,7 @@ void tcp_send_probe0(struct sock *sk)/* Cancel probe timer, if it is not required. */ icsk->icsk_probes_out =0 ; icsk->icsk_backoff =0 ; + icsk->icsk_probes_tstamp =0 ;return ; }
net/ipv4/tcp_timer.c +7 -7
@@ -343,6 +343,7 @@ static void tcp_probe_timer(struct sockif (tp->packets_out || !skb) { icsk->icsk_probes_out =0 ; + icsk->icsk_probes_tstamp =0 ;return ; }
@@ -354,13 +355,12 @@ static void tcp_probe_timer(struct sock* corresponding system limit. We also implement similar policy when * we use RTO to probe window in tcp_retransmit_timer(). */ -if (icsk->icsk_user_timeout) { -u32 elapsed =tcp_model_timeout (sk, icsk->icsk_probes_out, -tcp_probe0_base (sk)); - -if (elapsed >= icsk->icsk_user_timeout) - goto abort; - } +if (!icsk->icsk_probes_tstamp) + icsk->icsk_probes_tstamp = tcp_jiffies32; +else if (icsk->icsk_user_timeout && + (s32)(tcp_jiffies32 - icsk->icsk_probes_tstamp) >= +msecs_to_jiffies (icsk->icsk_user_timeout)) + goto abort; max_probes =sock_net (sk)->ipv4.sysctl_tcp_retries2;if (sock_flag (sk,SOCK_DEAD )) {
Greg Kroah-Hartman
maintainerPATCH 181/199 net: mscc: ocelot: Fix multicast to the CPU port
In reply to Greg Kroah-HartmanFrom: Alban Bedel <[email protected]>
commit 584b7cfcdc7d6d416a9d6fece9516764bd977d2e upstream.
Multicast entries in the MAC table use the high bits of the MAC address to encode the ports that should get the packets. But this port mask does not work for the CPU port, to receive these packets on the CPU port the MAC_CPU_COPY flag must be set.
Because of this IPv6 was effectively not working because neighbor solicitations were never received. This was not apparent before commit 9403c158 (net: mscc: ocelot: support IPv4, IPv6 and plain Ethernet mdb entries) as the IPv6 entries were broken so all incoming IPv6 multicast was then treated as unknown and flooded on all ports.
To fix this problem rework the ocelot_mact_learn() to set the MAC_CPU_COPY flag when a multicast entry that target the CPU port is added. For this we have to read back the ports endcoded in the pseudo MAC address by the caller. It is not a very nice design but that avoid changing the callers and should make backporting easier.
--- drivers/net/ethernet/mscc/ocelot.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-)
drivers/net/ethernet/mscc/ocelot.c +18 -5
@@ -60,14 +60,27 @@ int ocelot_mact_learn(struct ocelot *oceconst unsigned char mac[ETH_ALEN ], unsigned int vid, enum macaccess_entry_type type) { + u32 cmd = ANA_TABLES_MACACCESS_VALID | +ANA_TABLES_MACACCESS_DEST_IDX (port) | +ANA_TABLES_MACACCESS_ENTRYTYPE (type) | +ANA_TABLES_MACACCESS_MAC_TABLE_CMD (MACACCESS_CMD_LEARN ); +unsigned int mc_ports; + +/* Set MAC_CPU_COPY if the CPU port is used by a multicast entry */ +if (type == ENTRYTYPE_MACv4) + mc_ports = (mac[1 ] <<8 ) | mac[2 ]; +else if (type == ENTRYTYPE_MACv6) + mc_ports = (mac[0 ] <<8 ) | mac[1 ]; +else + mc_ports =0 ; + +if (mc_ports &BIT (ocelot->num_phys_ports)) + cmd |=ANA_TABLES_MACACCESS_MAC_CPU_COPY ; +ocelot_mact_select (ocelot, mac, vid);/* Issue a write command */ -ocelot_write (ocelot,ANA_TABLES_MACACCESS_VALID | -ANA_TABLES_MACACCESS_DEST_IDX (port) | -ANA_TABLES_MACACCESS_ENTRYTYPE (type) | -ANA_TABLES_MACACCESS_MAC_TABLE_CMD (MACACCESS_CMD_LEARN ), -ANA_TABLES_MACACCESS ); +ocelot_write (ocelot, cmd,ANA_TABLES_MACACCESS );return ocelot_mact_wait_for_completion (ocelot); }
Greg Kroah-Hartman
maintainerPATCH 182/199 net: core: devlink: use right genl user_ptr when handling port param get/set
In reply to Greg Kroah-HartmanFrom: Oleksandr Mazur <[email protected]>
commit 7e238de8283acd32c26c2bc2a50672d0ea862ff7 upstream.
Fix incorrect user_ptr dereferencing when handling port param get/set:
idx [0] stores the 'struct devlink' pointer;
idx [1] stores the 'struct devlink_port' pointer;--- net/core/devlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/core/devlink.c +2 -2
@@ -4134,7 +4134,7 @@ out:static int devlink_nl_cmd_port_param_get_doit (struct sk_buff *skb,struct genl_info *info) { -struct devlink_port *devlink_port = info->user_ptr[0 ]; +struct devlink_port *devlink_port = info->user_ptr[1 ];struct devlink_param_item *param_item;struct sk_buff *msg;int err;
@@ -4163,7 +4163,7 @@ static int devlink_nl_cmd_port_param_getstatic int devlink_nl_cmd_port_param_set_doit (struct sk_buff *skb,struct genl_info *info) { -struct devlink_port *devlink_port = info->user_ptr[0 ]; +struct devlink_port *devlink_port = info->user_ptr[1 ]; return __devlink_nl_cmd_param_set_doit(devlink_port->devlink, devlink_port->index,
Greg Kroah-Hartman
maintainerPATCH 183/199 pinctrl: qcom: Allow SoCs to specify a GPIO function thats not 0
In reply to Greg Kroah-HartmanFrom: Douglas Anderson <[email protected]>
commit a82e537807d5c85706cd4c16fd2de77a8495dc8d upstream.
There's currently a comment in the code saying function 0 is GPIO. Instead of hardcoding it, let's add a member where an SoC can specify it. No known SoCs use a number other than 0, but this just makes the code clearer. NOTE: no SoC code needs to be updated since we can rely on zero-initialization.
--- drivers/pinctrl/qcom/pinctrl-msm.c | 3 +-- drivers/pinctrl/qcom/pinctrl-msm.h | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-)
drivers/pinctrl/qcom/pinctrl-msm.c +1 -2
@@ -210,8 +210,7 @@ static int msm_pinmux_request_gpio(strucif (!g->nfuncs)return 0 ; -/* For now assume function 0 is GPIO because it always is */ -return msm_pinmux_set_mux (pctldev, g->funcs[0 ], offset); +return msm_pinmux_set_mux (pctldev, g->funcs[pctrl->soc->gpio_func], offset); }static const struct pinmux_ops msm_pinmux_ops = {
drivers/pinctrl/qcom/pinctrl-msm.h +2 -0
@@ -118,6 +118,7 @@ struct msm_gpio_wakeirq_map {* @wakeirq_dual_edge_errata: If true then GPIOs using the wakeirq_map need * to be aware that their parent can't handle dual * edge interrupts. +* @gpio_func: Which function number is GPIO (usually 0). */ struct msm_pinctrl_soc_data {const struct pinctrl_pin_desc *pins;
@@ -134,6 +135,7 @@ struct msm_pinctrl_soc_data {const struct msm_gpio_wakeirq_map *wakeirq_map;unsigned int nwakeirq_map;bool wakeirq_dual_edge_errata; +unsigned int gpio_func; };extern const struct dev_pm_ops msm_pinctrl_dev_pm_ops;
Greg Kroah-Hartman
maintainerPATCH 184/199 pinctrl: qcom: No need to read-modify-write the interrupt status
In reply to Greg Kroah-HartmanFrom: Douglas Anderson <[email protected]>
commit 4079d35fa4fca4ee0ffd66968312fc86a5e8c290 upstream.
When the Qualcomm pinctrl driver wants to Ack an interrupt, it does a read-modify-write on the interrupt status register. On some SoCs it makes sure that the status bit is 1 to "Ack" and on others it makes sure that the bit is 0 to "Ack". Presumably the first type of interrupt controller is a "write 1 to clear" type register and the second just let you directly set the interrupt status register.
As far as I can tell from scanning structure definitions, the interrupt status bit is always in a register by itself. Thus with both types of interrupt controllers it is safe to "Ack" interrupts without doing a read-modify-write. We can do a simple write.
It should be noted that if the interrupt status bit _was_ ever in a register with other things (like maybe status bits for other GPIOs):
a) For "write 1 clear" type controllers then read-modify-write would be totally wrong because we'd accidentally end up clearing interrupts we weren't looking at.
b) For "direct set" type controllers then read-modify-write would also be wrong because someone setting one of the other bits in the register might accidentally clear (or set) our interrupt.
I say this simply to show that the current read-modify-write doesn't provide any sort of "future proofing" of the code. In fact (for "write 1 clear" controllers) the new code is slightly more "future proof" since it would allow more than one interrupt status bits to share a register.
NOTE: this code fixes no bugs--it simply avoids an extra register read.
--- drivers/pinctrl/qcom/pinctrl-msm.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-)
drivers/pinctrl/qcom/pinctrl-msm.c +8 -15
@@ -791,16 +791,13 @@ static void msm_gpio_irq_clear_unmask(straw_spin_lock_irqsave (&pctrl->lock, flags); -if (status_clear) { -/* -* clear the interrupt status bit before unmask to avoid -* any erroneous interrupts that would have got latched -* when the interrupt is not in use. -*/ - val =msm_readl_intr_status (pctrl, g); - val &= ~BIT (g->intr_status_bit); -msm_writel_intr_status (val, pctrl, g); - } +/* +* clear the interrupt status bit before unmask to avoid +* any erroneous interrupts that would have got latched +* when the interrupt is not in use. +*/ +if (status_clear) +msm_writel_intr_status (0 , pctrl, g); val =msm_readl_intr_cfg (pctrl, g); val |=BIT (g->intr_raw_status_bit);
@@ -905,11 +902,7 @@ static void msm_gpio_irq_ack(struct irq_raw_spin_lock_irqsave (&pctrl->lock, flags); - val =msm_readl_intr_status (pctrl, g); -if (g->intr_ack_high) - val |=BIT (g->intr_status_bit); -else - val &= ~BIT (g->intr_status_bit); + val = g->intr_ack_high ?BIT (g->intr_status_bit) :0 ;msm_writel_intr_status (val, pctrl, g);if (test_bit (d->hwirq, pctrl->dual_edge_irqs))
Greg Kroah-Hartman
maintainerPATCH 185/199 pinctrl: qcom: Properly clear "intr_ack_high" interrupts when unmasking
In reply to Greg Kroah-HartmanFrom: Douglas Anderson <[email protected]>
commit a95881d6aa2c000e3649f27a1a7329cf356e6bb3 upstream.
In commit 4b7618fdc7e6 ("pinctrl: qcom: Add irq_enable callback for msm gpio") we tried to Ack interrupts during unmask. However, that patch forgot to check "intr_ack_high" so, presumably, it only worked for a certain subset of SoCs.
Let's add a small accessor so we don't need to open-code the logic in both places.
This was found by code inspection. I don't have any access to the hardware in question nor software that needs the Ack during unmask.
--- drivers/pinctrl/qcom/pinctrl-msm.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/pinctrl/qcom/pinctrl-msm.c +10 -4
@@ -96,6 +96,14 @@ MSM_ACCESSOR(intr_cfg)MSM_ACCESSOR (intr_status)MSM_ACCESSOR (intr_target) +static void msm_ack_intr_status (struct msm_pinctrl *pctrl, +const struct msm_pingroup *g) +{ + u32 val = g->intr_ack_high ? BIT(g->intr_status_bit) : 0; + + msm_writel_intr_status(val, pctrl, g); +} + static int msm_get_groups_count(struct pinctrl_dev *pctldev) {struct msm_pinctrl *pctrl =pinctrl_dev_get_drvdata (pctldev);
@@ -797,7 +805,7 @@ static void msm_gpio_irq_clear_unmask(st* when the interrupt is not in use. */ if (status_clear) -msm_writel_intr_status (0 , pctrl, g); +msm_ack_intr_status (pctrl, g); val =msm_readl_intr_cfg (pctrl, g); val |=BIT (g->intr_raw_status_bit);
@@ -890,7 +898,6 @@ static void msm_gpio_irq_ack(struct irq_struct msm_pinctrl *pctrl =gpiochip_get_data (gc);const struct msm_pingroup *g;unsigned long flags; -u32 val;if (test_bit (d->hwirq, pctrl->skip_wake_irqs)) {if (test_bit (d->hwirq, pctrl->dual_edge_irqs))
@@ -902,8 +909,7 @@ static void msm_gpio_irq_ack(struct irq_raw_spin_lock_irqsave (&pctrl->lock, flags); - val = g->intr_ack_high ?BIT (g->intr_status_bit) :0 ; -msm_writel_intr_status (val, pctrl, g); +msm_ack_intr_status (pctrl, g);if (test_bit (d->hwirq, pctrl->dual_edge_irqs))msm_gpio_update_dual_edge_pos (pctrl, g, d);
Greg Kroah-Hartman
maintainerPATCH 186/199 pinctrl: qcom: Dont clear pending interrupts when enabling
In reply to Greg Kroah-HartmanFrom: Douglas Anderson <[email protected]>
commit cf9d052aa6005f1e8dfaf491d83bf37f368af69e upstream.
In Linux, if a driver does disable_irq() and later does enable_irq() on its interrupt, I believe it's expecting these properties:
* If an interrupt was pending when the driver disabled then it will still be pending after the driver re-enables.
* If an edge-triggered interrupt comes in while an interrupt is disabled it should assert when the interrupt is re-enabled.
If you think that the above sounds a lot like the disable_irq() and enable_irq() are supposed to be masking/unmasking the interrupt instead of disabling/enabling it then you've made an astute observation. Specifically when talking about interrupts, "mask" usually means to stop posting interrupts but keep tracking them and "disable" means to fully shut off interrupt detection. It's unfortunate that this is so confusing, but presumably this is all the way it is for historical reasons.
Perhaps more confusing than the above is that, even though clients of IRQs themselves don't have a way to request mask/unmask vs. disable/enable calls, IRQ chips themselves can implement both. ...and yet more confusing is that if an IRQ chip implements disable/enable then they will be called when a client driver calls disable_irq() / enable_irq().
It does feel like some of the above could be cleared up. However, without any other core interrupt changes it should be clear that when an IRQ chip gets a request to "disable" an IRQ that it has to treat it like a mask of that IRQ.
In any case, after that long interlude you can see that the "unmask and clear" can break things. Maulik tried to fix it so that we no longer did "unmask and clear" in commit 71266d9d3936 ("pinctrl: qcom:
Move clearing pending IRQ to .irq_request_resources callback"), but it only handled the PDC case and it had problems (it caused sc7180-trogdor devices to fail to suspend). Let's fix.
Quoted 1 line
From my understanding the source of the phantom interrupt in the
were these two things:
1. One that could have been introduced in msm_gpio_irq_set_type() (only for the non-PDC case).
2. Edges could have been detected when a GPIO was muxed away.
Fixing case #1 is easy. We can just add a clear in msm_gpio_irq_set_type().
Fixing case #2 is harder. Let's use a concrete example. In sc7180-trogdor.dtsi we configure the uart3 to have two pinctrl states, sleep and default, and mux between the two during runtime PM and system suspend (see geni_se_resources_{on,off}() for more details). The difference between the sleep and default state is that the RX pin is muxed to a GPIO during sleep and muxed to the UART otherwise.
As per Qualcomm, when we mux the pin over to the UART function the PDC (or the non-PDC interrupt detection logic) is still watching it / latching edges. These edges don't cause interrupts because the current code masks the interrupt unless we're entering suspend. However, as soon as we enter suspend we unmask the interrupt and it's counted as a wakeup.
Let's deal with the problem like this:
* When we mux away, we'll mask our interrupt. This isn't necessary in the above case since the client already masked us, but it's a good idea in general.
* When we mux back will clear any interrupts and unmask.
--- drivers/pinctrl/qcom/pinctrl-msm.c | 74 +++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 24 deletions(-)
drivers/pinctrl/qcom/pinctrl-msm.c +50 -24
@@ -51,6 +51,7 @@* @dual_edge_irqs: Bitmap of irqs that need sw emulated dual edge * detection. * @skip_wake_irqs: Skip IRQs that are handled by wakeup interrupt controller +* @disabled_for_mux: These IRQs were disabled because we muxed away. * @soc: Reference to soc_data of platform specific data. * @regs: Base addresses for the TLMM tiles. * @phys_base: Physical base address
@@ -72,6 +73,7 @@ struct msm_pinctrl {DECLARE_BITMAP (dual_edge_irqs,MAX_NR_GPIO );DECLARE_BITMAP (enabled_irqs,MAX_NR_GPIO );DECLARE_BITMAP (skip_wake_irqs,MAX_NR_GPIO ); +DECLARE_BITMAP (disabled_for_mux,MAX_NR_GPIO );const struct msm_pinctrl_soc_data *soc;void __iomem *regs[MAX_NR_TILES ];
@@ -179,6 +181,10 @@ static int msm_pinmux_set_mux(struct pin unsigned group) {struct msm_pinctrl *pctrl =pinctrl_dev_get_drvdata (pctldev); +struct gpio_chip *gc = &pctrl->chip; +unsigned int irq =irq_find_mapping (gc->irq.domain, group); +struct irq_data *d =irq_get_irq_data (irq); +unsigned int gpio_func = pctrl->soc->gpio_func;const struct msm_pingroup *g;unsigned long flags;u32 val, mask;
@@ -195,6 +201,20 @@ static int msm_pinmux_set_mux(struct pinif (WARN_ON (i == g->nfuncs))return -EINVAL ; +/* +* If an GPIO interrupt is setup on this pin then we need special +* handling. Specifically interrupt detection logic will still see +* the pin twiddle even when we're muxed away. +* +* When we see a pin with an interrupt setup on it then we'll disable +* (mask) interrupts on it when we mux away until we mux back. Note +* that disable_irq() refcounts and interrupts are disabled as long as +* at least one disable_irq() has been called. +*/ +if (d && i != gpio_func && + !test_and_set_bit (d->hwirq, pctrl->disabled_for_mux)) +disable_irq (irq); +raw_spin_lock_irqsave (&pctrl->lock, flags); val =msm_readl_ctl (pctrl, g);
@@ -204,6 +224,20 @@ static int msm_pinmux_set_mux(struct pinraw_spin_unlock_irqrestore (&pctrl->lock, flags); +if (d && i == gpio_func && +test_and_clear_bit (d->hwirq, pctrl->disabled_for_mux)) { +/* +* Clear interrupts detected while not GPIO since we only +* masked things. +*/ +if (d->parent_data &&test_bit (d->hwirq, pctrl->skip_wake_irqs)) +irq_chip_set_parent_state (d,IRQCHIP_STATE_PENDING , false); +else +msm_ack_intr_status (pctrl, g); + +enable_irq (irq); + } +return 0 ; }
@@ -781,7 +815,7 @@ static void msm_gpio_irq_mask(struct irqraw_spin_unlock_irqrestore (&pctrl->lock, flags); } -static void msm_gpio_irq_clear_unmask (struct irq_data *d,bool status_clear) +static void msm_gpio_irq_unmask (struct irq_data *d) {struct gpio_chip *gc =irq_data_get_irq_chip_data (d);struct msm_pinctrl *pctrl =gpiochip_get_data (gc);
@@ -799,14 +833,6 @@ static void msm_gpio_irq_clear_unmask(straw_spin_lock_irqsave (&pctrl->lock, flags); -/* -* clear the interrupt status bit before unmask to avoid -* any erroneous interrupts that would have got latched -* when the interrupt is not in use. -*/ -if (status_clear) -msm_ack_intr_status (pctrl, g); - val =msm_readl_intr_cfg (pctrl, g); val |=BIT (g->intr_raw_status_bit); val |=BIT (g->intr_enable_bit);
@@ -826,7 +852,7 @@ static void msm_gpio_irq_enable(struct iirq_chip_enable_parent (d);if (!test_bit (d->hwirq, pctrl->skip_wake_irqs)) -msm_gpio_irq_clear_unmask (d, true); +msm_gpio_irq_unmask (d); }static void msm_gpio_irq_disable (struct irq_data *d)
@@ -841,11 +867,6 @@ static void msm_gpio_irq_disable(structmsm_gpio_irq_mask (d); } -static void msm_gpio_irq_unmask (struct irq_data *d) -{ -msm_gpio_irq_clear_unmask (d, false); -} -/** * msm_gpio_update_dual_edge_parent() - Prime next edge for IRQs handled by parent. * @d: The irq dta.
@@ -934,6 +955,7 @@ static int msm_gpio_irq_set_type(structstruct msm_pinctrl *pctrl =gpiochip_get_data (gc);const struct msm_pingroup *g;unsigned long flags; +bool was_enabled;u32 val;if (msm_gpio_needs_dual_edge_parent_workaround (d, type)) {
@@ -995,6 +1017,7 @@ static int msm_gpio_irq_set_type(struct* could cause the INTR_STATUS to be set for EDGE interrupts. */ val =msm_readl_intr_cfg (pctrl, g); + was_enabled = val &BIT (g->intr_raw_status_bit); val |=BIT (g->intr_raw_status_bit);if (g->intr_detection_width ==2 ) { val &= ~(3 << g->intr_detection_bit);
@@ -1044,6 +1067,14 @@ static int msm_gpio_irq_set_type(struct }msm_writel_intr_cfg (val, pctrl, g); +/* +* The first time we set RAW_STATUS_EN it could trigger an interrupt. +* Clear the interrupt. This is safe because we have +* IRQCHIP_SET_TYPE_MASKED. +*/ +if (!was_enabled) +msm_ack_intr_status (pctrl, g); +if (test_bit (d->hwirq, pctrl->dual_edge_irqs))msm_gpio_update_dual_edge_pos (pctrl, g, d);
@@ -1097,16 +1128,11 @@ static int msm_gpio_irq_reqres(struct ir }/* -* Clear the interrupt that may be pending before we enable -* the line. -* This is especially a problem with the GPIOs routed to the -* PDC. These GPIOs are direct-connect interrupts to the GIC. -* Disabling the interrupt line at the PDC does not prevent -* the interrupt from being latched at the GIC. The state at -* GIC needs to be cleared before enabling. +* The disable / clear-enable workaround we do in msm_pinmux_set_mux() +* only works if disable is not lazy since we only clear any bogus +* interrupt in hardware. Explicitly mark the interrupt as UNLAZY. */ -if (d->parent_data &&test_bit (d->hwirq, pctrl->skip_wake_irqs)) -irq_chip_set_parent_state (d,IRQCHIP_STATE_PENDING ,0 ); +irq_set_status_flags (d->irq,IRQ_DISABLE_UNLAZY );return 0 ; out:
Greg Kroah-Hartman
maintainerPATCH 187/199 x86/sev: Fix nonistr violation
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit a1d5c98aac33a5a0004ecf88905dcc261c52f988 upstream.
When the compiler fails to inline, it violates nonisntr:
vmlinux.o: warning: objtool: __sev_es_nmi_complete()+0xc7: call to sev_es_wr_ghcb_msr() leaves .noinstr.text section
--- arch/x86/kernel/sev-es.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kernel/sev-es.c +1 -1
@@ -225,7 +225,7 @@ static inline u64 sev_es_rd_ghcb_msr(voireturn __rdmsr (MSR_AMD64_SEV_ES_GHCB ); } -static inline void sev_es_wr_ghcb_msr (u64 val) +static __always_inline void sev_es_wr_ghcb_msr(u64 val) {u32 low, high;
Greg Kroah-Hartman
maintainerPATCH 188/199 tty: implement write_iter
In reply to Greg Kroah-HartmanFrom: Linus Torvalds <[email protected]>
commit 9bb48c82aced07698a2d08ee0f1475a6c4f6b266 upstream.
This makes the tty layer use the .write_iter() function instead of the traditional .write() functionality.
That allows writev(), but more importantly also makes it possible to enable .splice_write() for ttys, reinstating the "splice to tty" functionality that was lost in commit 36e2c7421f02 ("fs: don't allow splice read/write without explicit ops").
--- drivers/tty/tty_io.c | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-)
drivers/tty/tty_io.c +26 -22
@@ -143,9 +143,8 @@ LIST_HEAD(tty_drivers); /* linked listDEFINE_MUTEX (tty_mutex);static ssize_t tty_read (struct file *,char __user *,size_t ,loff_t *); -static ssize_t tty_write (struct file *,const char __user *,size_t ,loff_t *); -ssize_t redirected_tty_write (struct file *,const char __user *, -size_t ,loff_t *); +static ssize_t tty_write (struct kiocb *,struct iov_iter *); +ssize_t redirected_tty_write (struct kiocb *,struct iov_iter *);static __poll_t tty_poll (struct file *,poll_table *);static int tty_open (struct inode *,struct file *);long tty_ioctl (struct file *file,unsigned int cmd,unsigned long arg);
@@ -478,7 +477,8 @@ static void tty_show_fdinfo(struct seq_fstatic const struct file_operations tty_fops = { .llseek = no_llseek, .read = tty_read, - .write = tty_write, + .write_iter = tty_write, + .splice_write = iter_file_splice_write, .poll = tty_poll, .unlocked_ioctl = tty_ioctl, .compat_ioctl = tty_compat_ioctl,
@@ -491,7 +491,8 @@ static const struct file_operations tty_static const struct file_operations console_fops = { .llseek = no_llseek, .read = tty_read, - .write = redirected_tty_write, + .write_iter = redirected_tty_write, + .splice_write = iter_file_splice_write, .poll = tty_poll, .unlocked_ioctl = tty_ioctl, .compat_ioctl = tty_compat_ioctl,
@@ -607,9 +608,9 @@ static void __tty_hangup(struct tty_stru/* This breaks for file handles being sent over AF_UNIX sockets ? */ list_for_each_entry (priv, &tty->tty_files, list) { filp = priv->file; -if (filp->f_op->write == redirected_tty_write) +if (filp->f_op->write_iter == redirected_tty_write) cons_filp = filp; -if (filp->f_op->write != tty_write) +if (filp->f_op->write_iter != tty_write)continue ; closecount++;__tty_fasync (-1 , filp,0 );/* can't block */
@@ -902,9 +903,9 @@ static inline ssize_t do_tty_write(ssize_t (*write)(struct tty_struct *,struct file *,const unsigned char *,size_t ), struct tty_struct *tty, struct file *file, - const char __user *buf, - size_t count) + struct iov_iter *from) { + size_t count = iov_iter_count(from);ssize_t ret, written =0 ;unsigned int chunk;
@@ -956,14 +957,20 @@ static inline ssize_t do_tty_write(size_t size = count;if (size > chunk) size = chunk; + ret = -EFAULT ; -if (copy_from_user (tty->write_buf, buf, size)) +if (copy_from_iter (tty->write_buf, size, from) != size)break ; + ret =write (tty, file, tty->write_buf, size);if (ret <=0 )break ; + +/* FIXME! Have Al check this! */ +if (ret != size) +iov_iter_revert (from, size-ret); + written += ret; - buf += ret; count -= ret;if (!count)break ;
@@ -1023,9 +1030,9 @@ void tty_write_message(struct tty_struct* write method will not be invoked in parallel for each device. */ -static ssize_t tty_write (struct file *file,const char __user *buf, -size_t count,loff_t *ppos) +static ssize_t tty_write (struct kiocb *iocb,struct iov_iter *from) { +struct file *file = iocb->ki_filp;struct tty_struct *tty =file_tty (file);struct tty_ldisc *ld;ssize_t ret;
@@ -1038,18 +1045,15 @@ static ssize_t tty_write(struct file *fiif (tty->ops->write_room ==NULL )tty_err (tty,"missing write_room method\n" ); ld =tty_ldisc_ref_wait (tty); -if (!ld) -return hung_up_tty_write (file, buf, count, ppos); -if (!ld->ops->write) +if (!ld || !ld->ops->write) ret = -EIO ;else - ret =do_tty_write (ld->ops->write, tty, file, buf, count); + ret =do_tty_write (ld->ops->write, tty, file, from);tty_ldisc_deref (ld);return ret; } -ssize_t redirected_tty_write (struct file *file,const char __user *buf, -size_t count,loff_t *ppos) +ssize_t redirected_tty_write (struct kiocb *iocb,struct iov_iter *iter) {struct file *p =NULL ;
@@ -1060,11 +1064,11 @@ ssize_t redirected_tty_write(struct fileif (p) {ssize_t res; - res =vfs_write (p, buf, count, &p->f_pos); + res =vfs_iocb_iter_write (p, iocb, iter);fput (p);return res; } -return tty_write (file, buf, count, ppos); +return tty_write (iocb, iter); }/**
@@ -2293,7 +2297,7 @@ static int tioccons(struct file *file) {if (!capable (CAP_SYS_ADMIN ))return -EPERM ; -if (file->f_op->write == redirected_tty_write) { +if (file->f_op->write_iter == redirected_tty_write) {struct file *f;spin_lock (&redirect_lock); f = redirect;
Greg Kroah-Hartman
maintainerPATCH 189/199 tty: fix up hung_up_tty_write() conversion
In reply to Greg Kroah-HartmanFrom: Linus Torvalds <[email protected]>
commit 17749851eb9ca2298e7c3b81aae4228961b36f28 upstream.
In commit "tty: implement write_iter", I left the write_iter conversion of the hung up tty case alone, because I incorrectly thought it didn't matter.
Jiri showed me the errors of my ways, and pointed out the problems with that incomplete conversion. Fix it all up.
--- drivers/tty/tty_io.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/tty/tty_io.c +5 -4
@@ -437,8 +437,7 @@ static ssize_t hung_up_tty_read(struct freturn 0 ; } -static ssize_t hung_up_tty_write (struct file *file,const char __user *buf, -size_t count,loff_t *ppos) +static ssize_t hung_up_tty_write (struct kiocb *iocb,struct iov_iter *from) {return -EIO ; }
@@ -504,7 +503,7 @@ static const struct file_operations consstatic const struct file_operations hung_up_tty_fops = { .llseek = no_llseek, .read = hung_up_tty_read, - .write = hung_up_tty_write, + .write_iter = hung_up_tty_write, .poll = hung_up_tty_poll, .unlocked_ioctl = hung_up_tty_ioctl, .compat_ioctl = hung_up_tty_compat_ioctl,
@@ -1045,7 +1044,9 @@ static ssize_t tty_write(struct kiocb *iif (tty->ops->write_room ==NULL )tty_err (tty,"missing write_room method\n" ); ld =tty_ldisc_ref_wait (tty); -if (!ld || !ld->ops->write) +if (!ld) +return hung_up_tty_write (iocb, from); +if (!ld->ops->write) ret = -EIO ;else ret =do_tty_write (ld->ops->write, tty, file, from);
Greg Kroah-Hartman
maintainerPATCH 190/199 net: systemport: free dev before on error path
In reply to Greg Kroah-HartmanFrom: Pan Bian <[email protected]>
commit 0c630a66bf10991b0ef13d27c93d7545e692ef5b upstream.
On the error path, it should goto the error handling label to free allocated memory rather than directly return.
--- drivers/net/ethernet/broadcom/bcmsysport.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/ethernet/broadcom/bcmsysport.c +4 -2
@@ -2503,8 +2503,10 @@ static int bcm_sysport_probe(struct plat priv =netdev_priv (dev); priv->clk =devm_clk_get_optional (&pdev->dev,"sw_sysport" ); -if (IS_ERR (priv->clk)) -return PTR_ERR (priv->clk); +if (IS_ERR (priv->clk)) { + ret =PTR_ERR (priv->clk); + goto err_free_netdev; + }/* Allocate number of TX rings */ priv->tx_rings = devm_kcalloc(&pdev->dev, txq,
Greg Kroah-Hartman
maintainerPATCH 191/199 x86/sev-es: Handle string port IO to kernel memory properly
In reply to Greg Kroah-HartmanFrom: Hyunwook (Wooky) Baek <[email protected]>
commit 7024f60d655272bd2ca1d3a4c9e0a63319b1eea1 upstream.
Don't assume dest/source buffers are userspace addresses when manually copying data for string I/O or MOVS MMIO, as {get,put}_user() will fail if handed a kernel address and ultimately lead to a kernel panic.
When invoking INSB/OUTSB instructions in kernel space in a SEV-ES-enabled VM, the kernel crashes with the following message:
"SEV-ES: Unsupported exception in #VC instruction emulation - can't continue"
Handle that case properly.
[ bp: Massage commit message. ]
--- arch/x86/kernel/sev-es.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
arch/x86/kernel/sev-es.c +12 -0
@@ -286,6 +286,12 @@ static enum es_result vc_write_mem(strucu16 d2;u8 d1; +/* If instruction ran in kernel mode and the I/O buffer is in kernel space */ +if (!user_mode (ctxt->regs) && !access_ok (target, size)) { +memcpy (dst, buf, size); +return ES_OK ; + } +switch (size) {case 1 :memcpy (&d1, buf,1 );
@@ -335,6 +341,12 @@ static enum es_result vc_read_mem(structu16 d2;u8 d1; +/* If instruction ran in kernel mode and the I/O buffer is in kernel space */ +if (!user_mode (ctxt->regs) && !access_ok (s, size)) { +memcpy (buf, src, size); +return ES_OK ; + } +switch (size) {case 1 :if (get_user (d1, s))
Greg Kroah-Hartman
maintainerPATCH 192/199 tcp: Fix potential use-after-free due to double kfree()
In reply to Greg Kroah-HartmanFrom: Kuniyuki Iwashima <[email protected]>
commit c89dffc70b340780e5b933832d8c3e045ef3791e upstream.
Receiving ACK with a valid SYN cookie, cookie_v4_check() allocates struct request_sock and then can allocate inet_rsk(req)->ireq_opt. After that, tcp_v4_syn_recv_sock() allocates struct sock and copies ireq_opt to inet_sk(sk)->inet_opt. Normally, tcp_v4_syn_recv_sock() inserts the full socket into ehash and sets NULL to ireq_opt. Otherwise, tcp_v4_syn_recv_sock() has to reset inet_opt by NULL and free the full socket.
The commit 01770a1661657 ("tcp: fix race condition when creating child sockets from syncookies") added a new path, in which more than one cores create full sockets for the same SYN cookie. Currently, the core which loses the race frees the full socket without resetting inet_opt, resulting in that both sock_put() and reqsk_put() call kfree() for the same memory:
sock_put
sk_free
__sk_free
sk_destruct
__sk_destruct
sk->sk_destruct/inet_sock_destruct
kfree(rcu_dereference_protected(inet->inet_opt, 1));
reqsk_put
reqsk_free
__reqsk_free
req->rsk_ops->destructor/tcp_v4_reqsk_destructor
kfree(rcu_dereference_protected(inet_rsk(req)->ireq_opt, 1));Calling kmalloc() between the double kfree() can lead to use-after-free, so this patch fixes it by setting NULL to inet_opt before sock_put().
As a side note, this kind of issue does not happen for IPv6. This is because tcp_v6_syn_recv_sock() clones both ipv6_opt and pktopts which correspond to ireq_opt in IPv4.
--- net/ipv4/tcp_ipv4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/ipv4/tcp_ipv4.c +2 -2
@@ -1590,6 +1590,8 @@ struct sock *tcp_v4_syn_recv_sock(consttcp_move_syn (newtp, req); ireq->ireq_opt =NULL ; }else { + newinet->inet_opt =NULL ; +if (!req_unhash && found_dup_sk) {/* This code path should only be executed in the * syncookie case only
@@ -1597,8 +1599,6 @@ struct sock *tcp_v4_syn_recv_sock(constbh_unlock_sock (newsk);sock_put (newsk); newsk =NULL ; - }else { - newinet->inet_opt =NULL ; } }return newsk;
Greg Kroah-Hartman
maintainerPATCH 193/199 ASoC: SOF: Intel: hda: Avoid checking jack on system suspend
In reply to Greg Kroah-HartmanFrom: Kai-Heng Feng <[email protected]>
commit ef4d764c99f792b725d4754a3628830f094f5c58 upstream.
System takes a very long time to suspend after commit 215a22ed31a1 ("ALSA: hda: Refactor codec PM to use direct-complete optimization"):
[ 90.065964] PM: suspend entry (s2idle) [ 90.067337] Filesystems sync: 0.001 seconds [ 90.185758] Freezing user space processes ... (elapsed 0.002 seconds) done. [ 90.188713] OOM killer disabled. [ 90.188714] Freezing remaining freezable tasks ... (elapsed 0.001 seconds) done. [ 90.190024] printk: Suspending console(s) (use no_console_suspend to debug) [ 90.904912] intel_pch_thermal 0000:00:12.0: CPU-PCH is cool [49C], continue to suspend [ 321.262505] snd_hda_codec_realtek ehdaudio0D0: Unable to sync register 0x2b8000. -5 [ 328.426919] snd_hda_codec_realtek ehdaudio0D0: Unable to sync register 0x2b8000. -5 [ 329.490933] ACPI: EC: interrupt blocked
That commit keeps the codec suspended during the system suspend. However, mute/micmute LED will clear codec's direct-complete flag by dpm_clear_superiors_direct_complete().
This doesn't play well with SOF driver. When its runtime resume is called for system suspend, hda_codec_jack_check() schedules jackpoll_work which uses snd_hdac_is_power_on() to check whether codec is suspended. Because the direct-complete path isn't taken, pm_runtime_disable() isn't called so snd_hdac_is_power_on() returns false and jackpoll continues to run, and snd_hda_power_up_pm() cannot power up an already suspended codec in multiple attempts, causes the long delay on system suspend:
if (dev->power.direct_complete) {
if (pm_runtime_status_suspended(dev)) {
pm_runtime_disable(dev);
if (pm_runtime_status_suspended(dev)) {
pm_dev_dbg(dev, state, "direct-complete ");
goto Complete;
}
pm_runtime_enable(dev);
}
dev->power.direct_complete = false;
}When direct-complete path is taken, snd_hdac_is_power_on() returns true and hda_jackpoll_work() is skipped by accident. So this is still not correct.
If we were to use snd_hdac_is_power_on() in system PM path, pm_runtime_status_suspended() should be used instead of pm_runtime_suspended(), otherwise pm_runtime_{enable,disable}() may change the outcome of snd_hdac_is_power_on().
Because devices suspend in reverse order (i.e. child first), it doesn't make much sense to resume an already suspended codec from audio controller. So avoid the issue by making sure jackpoll isn't used in system PM process.
--- sound/soc/sof/intel/hda-dsp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
sound/soc/sof/intel/hda-dsp.c +4 -2
@@ -683,8 +683,10 @@ static int hda_resume(struct snd_sof_dev#if IS_ENABLED (CONFIG_SND_SOC_SOF_HDA )/* check jack status */ -if (runtime_resume) -hda_codec_jack_check (sdev); +if (runtime_resume) { +if (sdev->system_suspend_target ==SOF_SUSPEND_NONE ) +hda_codec_jack_check (sdev); + }/* turn off the links that were off before suspend */ list_for_each_entry (hlink, &bus->hlink_list, list) {
Greg Kroah-Hartman
maintainerPATCH 194/199 drm/i915/hdcp: Get conn while content_type changed
In reply to Greg Kroah-HartmanFrom: Anshuman Gupta <[email protected]>
commit 8662e1119a7d1baa1b2001689b2923e9050754bd upstream.
Get DRM connector reference count while scheduling a prop work to avoid any possible destroy of DRM connector when it is in DRM_CONNECTOR_REGISTERED state.
--- drivers/gpu/drm/i915/display/intel_hdcp.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/i915/display/intel_hdcp.c +1 -0
@@ -2187,6 +2187,7 @@ void intel_hdcp_update_pipe(struct intelif (content_protection_type_changed) {mutex_lock (&hdcp->mutex); hdcp->value =DRM_MODE_CONTENT_PROTECTION_DESIRED ; +drm_connector_get (&connector->base);schedule_work (&hdcp->prop_work);mutex_unlock (&hdcp->mutex); }
Greg Kroah-Hartman
maintainerPATCH 195/199 bpf: Local storage helpers should check nullness of owner ptr passed
In reply to Greg Kroah-HartmanFrom: KP Singh <[email protected]>
commit 1a9c72ad4c26821e215a396167c14959cf24a7f1 upstream.
The verifier allows ARG_PTR_TO_BTF_ID helper arguments to be NULL, so helper implementations need to check this before dereferencing them. This was already fixed for the socket storage helpers but not for task and inode.
The issue can be reproduced by attaching an LSM program to inode_rename hook (called when moving files) which tries to get the inode of the new file without checking for its nullness and then trying to move an existing file to a new path:
mv existing_file new_file_does_not_exist
The report including the sample program and the steps for reproducing the bug:
https://lore.kernel.org/bpf/CANaYP3HWkH91SN=wTNO9FL_2ztHfqcXKX38SSE-JJ2voh+vssw@mail.gmail.com
--- kernel/bpf/bpf_inode_storage.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
kernel/bpf/bpf_inode_storage.c +4 -1
@@ -176,7 +176,7 @@ BPF_CALL_4(bpf_inode_storage_get, struct* bpf_local_storage_update expects the owner to have a * valid storage pointer. */ -if (!inode_storage_ptr (inode)) +if (!inode || !inode_storage_ptr (inode))return (unsigned long )NULL ; sdata =inode_storage_lookup (inode, map, true);
@@ -200,6 +200,9 @@ BPF_CALL_4(bpf_inode_storage_get, structBPF_CALL_2 (bpf_inode_storage_delete, struct bpf_map *, map, struct inode *, inode) { +if (!inode) +return -EINVAL ; +/* This helper must only called from where the inode is gurranteed * to have a refcount and cannot be freed. */
Greg Kroah-Hartman
maintainerPATCH 196/199 kernfs: implement ->read_iter
In reply to Greg Kroah-HartmanFrom: Christoph Hellwig <[email protected]>
commit 4eaad21a6ac9865df7f31983232ed5928450458d upstream.
Switch kernfs to implement the read_iter method instead of plain old read to prepare to supporting splice and sendfile again.
--- fs/kernfs/file.c | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-)
fs/kernfs/file.c +12 -23
@@ -14,6 +14,7 @@#include <linux/pagemap.h> #include <linux/sched/mm.h> #include <linux/fsnotify.h> +#include <linux/uio.h> #include "kernfs-internal.h"
@@ -180,11 +181,10 @@ static const struct seq_operations kernf* it difficult to use seq_file. Implement simplistic custom buffering for * bin files. */ -static ssize_t kernfs_file_direct_read (struct kernfs_open_file *of, -char __user *user_buf,size_t count, -loff_t *ppos) +static ssize_t kernfs_file_read_iter (struct kiocb *iocb,struct iov_iter *iter) { -ssize_t len =min_t (size_t, count,PAGE_SIZE ); +struct kernfs_open_file *of =kernfs_of (iocb->ki_filp); +ssize_t len =min_t (size_t,iov_iter_count (iter),PAGE_SIZE );const struct kernfs_ops *ops;char *buf;
@@ -210,7 +210,7 @@ static ssize_t kernfs_file_direct_read(s of->event =atomic_read (&of->kn->attr.open->event); ops =kernfs_ops (of->kn);if (ops->read) - len = ops->read (of, buf, len, *ppos); + len = ops->read (of, buf, len, iocb->ki_pos);else len = -EINVAL ;
@@ -220,12 +220,12 @@ static ssize_t kernfs_file_direct_read(sif (len <0 ) goto out_free; -if (copy_to_user (user_buf, buf, len)) { +if (copy_to_iter (buf, len, iter) != len) { len = -EFAULT ; goto out_free; } - *ppos += len; + iocb->ki_pos += len; out_free:if (buf == of->prealloc_buf)
@@ -235,22 +235,11 @@ static ssize_t kernfs_file_direct_read(sreturn len; } -/** -* kernfs_fop_read - kernfs vfs read callback -* @file: file pointer -* @user_buf: data to write -* @count: number of bytes -* @ppos: starting offset -*/ -static ssize_t kernfs_fop_read (struct file *file,char __user *user_buf, -size_t count,loff_t *ppos) +static ssize_t kernfs_fop_read_iter (struct kiocb *iocb,struct iov_iter *iter) { -struct kernfs_open_file *of =kernfs_of (file); - -if (of->kn->flags &KERNFS_HAS_SEQ_SHOW ) -return seq_read (file, user_buf, count, ppos); -else -return kernfs_file_direct_read (of, user_buf, count, ppos); +if (kernfs_of (iocb->ki_filp)->kn->flags &KERNFS_HAS_SEQ_SHOW ) +return seq_read_iter (iocb, iter); +return kernfs_file_read_iter (iocb, iter); }/**
@@ -960,7 +949,7 @@ void kernfs_notify(struct kernfs_node *kEXPORT_SYMBOL_GPL (kernfs_notify);const struct file_operations kernfs_file_fops = { - .read = kernfs_fop_read, + .read_iter = kernfs_fop_read_iter, .write = kernfs_fop_write, .llseek = generic_file_llseek, .mmap = kernfs_fop_mmap,
Greg Kroah-Hartman
maintainerPATCH 197/199 kernfs: implement ->write_iter
In reply to Greg Kroah-HartmanFrom: Christoph Hellwig <[email protected]>
commit cc099e0b399889c6485c88368b19824b087c9f8c upstream.
Switch kernfs to implement the write_iter method instead of plain old write to prepare to supporting splice and sendfile again.
--- fs/kernfs/file.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-)
fs/kernfs/file.c +10 -18
@@ -242,13 +242,7 @@ static ssize_t kernfs_fop_read_iter(strureturn kernfs_file_read_iter (iocb, iter); } -/** -* kernfs_fop_write - kernfs vfs write callback -* @file: file pointer -* @user_buf: data to write -* @count: number of bytes -* @ppos: starting offset -* +/* * Copy data in from userland and pass it to the matching kernfs write * operation. *
@@ -258,20 +252,18 @@ static ssize_t kernfs_fop_read_iter(stru* modify only the the value you're changing, then write entire buffer * back. */ -static ssize_t kernfs_fop_write (struct file *file,const char __user *user_buf, -size_t count,loff_t *ppos) +static ssize_t kernfs_fop_write_iter (struct kiocb *iocb,struct iov_iter *iter) { -struct kernfs_open_file *of =kernfs_of (file); +struct kernfs_open_file *of =kernfs_of (iocb->ki_filp); +ssize_t len =iov_iter_count (iter);const struct kernfs_ops *ops; -ssize_t len;char *buf;if (of->atomic_write_len) { - len = count;if (len > of->atomic_write_len)return -E2BIG ; }else { - len =min_t (size_t, count,PAGE_SIZE ); + len =min_t (size_t, len,PAGE_SIZE ); } buf = of->prealloc_buf;
@@ -282,7 +274,7 @@ static ssize_t kernfs_fop_write(struct fif (!buf)return -ENOMEM ; -if (copy_from_user (buf, user_buf, len)) { +if (copy_from_iter (buf, len, iter) != len) { len = -EFAULT ; goto out_free; }
@@ -301,7 +293,7 @@ static ssize_t kernfs_fop_write(struct f ops =kernfs_ops (of->kn);if (ops->write) - len = ops->write (of, buf, len, *ppos); + len = ops->write (of, buf, len, iocb->ki_pos);else len = -EINVAL ;
@@ -309,7 +301,7 @@ static ssize_t kernfs_fop_write(struct fmutex_unlock (&of->mutex);if (len >0 ) - *ppos += len; + iocb->ki_pos += len; out_free:if (buf == of->prealloc_buf)
@@ -662,7 +654,7 @@ static int kernfs_fop_open(struct inode/* * Write path needs to atomic_write_len outside active reference. -* Cache it in open_file. See kernfs_fop_write() for details. +* Cache it in open_file. See kernfs_fop_write_iter() for details. */ of->atomic_write_len = ops->atomic_write_len;
@@ -950,7 +942,7 @@ EXPORT_SYMBOL_GPL(kernfs_notify);const struct file_operations kernfs_file_fops = { .read_iter = kernfs_fop_read_iter, - .write = kernfs_fop_write, + .write_iter = kernfs_fop_write_iter, .llseek = generic_file_llseek, .mmap = kernfs_fop_mmap, .open = kernfs_fop_open,
Greg Kroah-Hartman
maintainerPATCH 198/199 kernfs: wire up ->splice_read and ->splice_write
In reply to Greg Kroah-HartmanFrom: Christoph Hellwig <[email protected]>
commit f2d6c2708bd84ca953fa6b6ca5717e79eb0140c7 upstream.
Wire up the splice_read and splice_write methods to the default helpers using ->read_iter and ->write_iter now that those are implemented for kernfs. This restores support to use splice and sendfile on kernfs files.
--- fs/kernfs/file.c | 2 ++ 1 file changed, 2 insertions(+)
fs/kernfs/file.c +2 -0
@@ -949,6 +949,8 @@ const struct file_operations kernfs_file .release = kernfs_fop_release, .poll = kernfs_fop_poll, .fsync = noop_fsync, + .splice_read = generic_file_splice_read, + .splice_write = iter_file_splice_write, };/**
Greg Kroah-Hartman
maintainerPATCH 199/199 interconnect: imx8mq: Use icc_sync_state
In reply to Greg Kroah-HartmanFrom: Martin Kepplinger <[email protected]>
commit 67288f74d4837b82ef937170da3389b0779c17be upstream.
Add the icc_sync_state callback to notify the framework when consumers are probed and the bandwidth doesn't have to be kept at maximum anymore.
--- drivers/interconnect/imx/imx8mq.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/interconnect/imx/imx8mq.c +2 -0
@@ -7,6 +7,7 @@#include <linux/module.h> #include <linux/platform_device.h> +#include <linux/interconnect-provider.h> #include <dt-bindings/interconnect/imx8mq.h> #include "imx.h"
@@ -94,6 +95,7 @@ static struct platform_driver imx8mq_icc .remove = imx8mq_icc_remove, .driver = { .name = "imx8mq-interconnect", + .sync_state = icc_sync_state, }, };
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.11 release. There are 199 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 27 Jan 2021 18:31:44 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.11-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.10.y
and the diffstat can be found below.thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah
Quoted 16 lines · Shuah Khan
Quoted 15 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.11 release. There are 199 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 27 Jan 2021 18:31:44 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.11-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.10.y and the diffstat can be found below.
Quoted 9 lines
Quoted 4 lines
thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
Tested-by Shuah Khan <[email protected]>
Please ignore this. I tested rc2.
thanks,
-- Shuah