diff --git a/arch/arm/configs/vendor/sdxnightjar.config b/arch/arm/configs/vendor/sdxnightjar.config index 86a9b16bd507..0772a299bf85 100644 --- a/arch/arm/configs/vendor/sdxnightjar.config +++ b/arch/arm/configs/vendor/sdxnightjar.config @@ -66,6 +66,7 @@ CONFIG_INTERCONNECT_QCOM=y CONFIG_DEBUG_FS=y CONFIG_ARCH_SDXNIGHTJAR=y CONFIG_ETHERNET=y +CONFIG_IP_NF_TARGET_TRIGGER_MODULE=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_NET_VENDOR_ADAPTEC is not set # CONFIG_NET_VENDOR_AGERE is not set diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 9268f39cb328..5debb2b4bc9c 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ /* Uncomment this block to log an error on every VERIFY failure */ @@ -1108,64 +1108,43 @@ static void fastrpc_remote_buf_list_free(struct fastrpc_file *fl) } while (free); } +static void fastrpc_mmap_add_global(struct fastrpc_mmap *map) +{ + struct fastrpc_apps *me = &gfa; + unsigned long irq_flags = 0; + + spin_lock_irqsave(&me->hlock, irq_flags); + hlist_add_head(&map->hn, &me->maps); + spin_unlock_irqrestore(&me->hlock, irq_flags); +} + static void fastrpc_mmap_add(struct fastrpc_mmap *map) { - if (map->flags == ADSP_MMAP_HEAP_ADDR || - map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { - struct fastrpc_apps *me = &gfa; + struct fastrpc_file *fl = map->fl; - spin_lock(&me->hlock); - hlist_add_head(&map->hn, &me->maps); - spin_unlock(&me->hlock); - } else { - struct fastrpc_file *fl = map->fl; - - hlist_add_head(&map->hn, &fl->maps); - } + hlist_add_head(&map->hn, &fl->maps); } static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd, uintptr_t va, size_t len, int mflags, int refs, struct fastrpc_mmap **ppmap) { - struct fastrpc_apps *me = &gfa; struct fastrpc_mmap *match = NULL, *map = NULL; struct hlist_node *n; if ((va + len) < va) return -EFAULT; - if (mflags == ADSP_MMAP_HEAP_ADDR || - mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) { - spin_lock(&me->hlock); - hlist_for_each_entry_safe(map, n, &me->maps, hn) { - if (va >= map->va && - va + len <= map->va + map->len && - map->fd == fd) { - if (refs) { - if (map->refs + 1 == INT_MAX) { - spin_unlock(&me->hlock); - return -ETOOMANYREFS; - } - map->refs++; - } - match = map; - break; - } - } - spin_unlock(&me->hlock); - } else { - hlist_for_each_entry_safe(map, n, &fl->maps, hn) { - if (va >= map->va && - va + len <= map->va + map->len && - map->fd == fd) { - if (refs) { - if (map->refs + 1 == INT_MAX) - return -ETOOMANYREFS; - map->refs++; - } - match = map; - break; + hlist_for_each_entry_safe(map, n, &fl->maps, hn) { + if (va >= map->va && + va + len <= map->va + map->len && + map->fd == fd) { + if (refs) { + if (map->refs + 1 == INT_MAX) + return -ETOOMANYREFS; + map->refs++; } + match = map; + break; } } if (match) { @@ -1641,7 +1620,9 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, } map->len = len; - fastrpc_mmap_add(map); + if ((mflags != ADSP_MMAP_HEAP_ADDR) && + (mflags != ADSP_MMAP_REMOTE_HEAP_ADDR)) + fastrpc_mmap_add(map); *ppmap = map; bail: @@ -4039,6 +4020,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_file *fl, spin_lock(&me->hlock); mem->in_use = true; spin_unlock(&me->hlock); + fastrpc_mmap_add_global(mem); } phys = mem->phys; size = mem->size; @@ -4772,7 +4754,7 @@ static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl) me->enable_ramdump = false; bail: if (err && match) - fastrpc_mmap_add(match); + fastrpc_mmap_add_global(match); return err; } @@ -4901,7 +4883,11 @@ static int fastrpc_internal_munmap(struct fastrpc_file *fl, bail: if (err && map) { mutex_lock(&fl->map_mutex); - fastrpc_mmap_add(map); + if ((map->flags == ADSP_MMAP_HEAP_ADDR) || + (map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR)) + fastrpc_mmap_add_global(map); + else + fastrpc_mmap_add(map); mutex_unlock(&fl->map_mutex); } mutex_unlock(&fl->internal_map_mutex); @@ -4988,6 +4974,9 @@ static int fastrpc_internal_mem_map(struct fastrpc_file *fl, if (err) goto bail; ud->m.vaddrout = map->raddr; + if (ud->m.flags == ADSP_MMAP_HEAP_ADDR || + ud->m.flags == ADSP_MMAP_REMOTE_HEAP_ADDR) + fastrpc_mmap_add_global(map); bail: if (err) { pr_err("adsprpc: %s failed to map fd %d flags %d err %d\n", @@ -5050,7 +5039,11 @@ bail: /* Add back to map list in case of error to unmap on DSP */ if (map) { mutex_lock(&fl->map_mutex); - fastrpc_mmap_add(map); + if ((map->flags == ADSP_MMAP_HEAP_ADDR) || + (map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR)) + fastrpc_mmap_add_global(map); + else + fastrpc_mmap_add(map); mutex_unlock(&fl->map_mutex); } } @@ -5119,6 +5112,9 @@ static int fastrpc_internal_mmap(struct fastrpc_file *fl, if (err) goto bail; map->raddr = raddr; + if (ud->flags == ADSP_MMAP_HEAP_ADDR || + ud->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) + fastrpc_mmap_add_global(map); } ud->vaddrout = raddr; bail: diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index 3720f4830682..68401a824bc2 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -2278,6 +2278,12 @@ static int mhi_dev_process_tre_ring(struct mhi_dev *mhi, ch = &mhi->ch[ring->id - mhi->ch_ring_start]; reason.ch_id = ch->ch_id; reason.reason = MHI_DEV_TRE_AVAILABLE; + /* + * Save lowest value of tre_len to split packets in UCI layer + * for write request of size more than tre_len. + */ + if (!ch->tre_size || ch->tre_size > el->tre.len) + ch->tre_size = el->tre.len; /* Invoke a callback to let the client know its data is ready. * Copy this event to the clients context so that it can be @@ -3466,7 +3472,7 @@ int mhi_dev_read_channel(struct mhi_req *mreq) uint64_t read_from_loc; ssize_t bytes_read = 0; size_t write_to_loc = 0; - uint32_t usr_buf_remaining; + uint32_t usr_buf_remaining, tre_size; int td_done = 0, rc = 0; struct mhi_dev_client *handle_client; @@ -3509,10 +3515,9 @@ int mhi_dev_read_channel(struct mhi_req *mreq) } el = &ring->ring_cache[ring->rd_offset]; - mhi_log(MHI_MSG_VERBOSE, "evtptr : 0x%llx\n", - el->tre.data_buf_ptr); - mhi_log(MHI_MSG_VERBOSE, "evntlen : 0x%x, offset:%lu\n", - el->tre.len, ring->rd_offset); + mhi_log(MHI_MSG_VERBOSE, + "TRE.PTR: 0x%llx, TRE.LEN: 0x%x, rd offset: %lu\n", + el->tre.data_buf_ptr, el->tre.len, ring->rd_offset); if (ch->tre_loc) { bytes_to_read = min(usr_buf_remaining, @@ -3531,17 +3536,15 @@ int mhi_dev_read_channel(struct mhi_req *mreq) ch->tre_loc = el->tre.data_buf_ptr; - ch->tre_size = el->tre.len; - ch->tre_bytes_left = ch->tre_size; - - mhi_log(MHI_MSG_VERBOSE, - "user_buf_remaining %d, ch->tre_size %d\n", - usr_buf_remaining, ch->tre_size); - bytes_to_read = min(usr_buf_remaining, ch->tre_size); + tre_size = el->tre.len; + ch->tre_bytes_left = el->tre.len; + mhi_log(MHI_MSG_VERBOSE, "user_buf_remaining %d, tre_size %d\n", + usr_buf_remaining, el->tre.len); + bytes_to_read = min(usr_buf_remaining, tre_size); } bytes_read += bytes_to_read; - addr_offset = ch->tre_size - ch->tre_bytes_left; + addr_offset = el->tre.len - ch->tre_bytes_left; read_from_loc = ch->tre_loc + addr_offset; write_to_loc = (size_t) mreq->buf + (mreq->len - usr_buf_remaining); diff --git a/drivers/platform/msm/mhi_dev/mhi_uci.c b/drivers/platform/msm/mhi_dev/mhi_uci.c index 8aca45f6957c..5862dd0a9fde 100644 --- a/drivers/platform/msm/mhi_dev/mhi_uci.c +++ b/drivers/platform/msm/mhi_dev/mhi_uci.c @@ -391,6 +391,7 @@ struct uci_client { int (*read)(struct uci_client *h, int *bytes); unsigned int tiocm; unsigned int at_ctrl_mask; + int tre_len; }; struct mhi_uci_ctxt_t { @@ -1466,8 +1467,9 @@ static ssize_t mhi_uci_client_write(struct file *file, { struct uci_client *uci_handle = NULL; void *data_loc; + const char __user *cur_buf; unsigned long memcpy_result; - int rc; + int rc = 0, tre_len, cur_rc = 0, count_left, cur_txfr_len; if (!file || !buf || !count || !file->private_data) { uci_log(UCI_DBG_DBG, "Invalid access to write\n"); @@ -1475,6 +1477,8 @@ static ssize_t mhi_uci_client_write(struct file *file, } uci_handle = file->private_data; + tre_len = uci_handle->tre_len; + if (!uci_handle->send || !uci_handle->out_handle) { uci_log(UCI_DBG_DBG, "Invalid handle or send\n"); return -EINVAL; @@ -1497,17 +1501,47 @@ static ssize_t mhi_uci_client_write(struct file *file, count, uci_handle->out_chan_attr->max_packet_size); } - data_loc = kmalloc(count, GFP_KERNEL); - if (!data_loc) - return -ENOMEM; + cur_txfr_len = count; - memcpy_result = copy_from_user(data_loc, buf, count); - if (memcpy_result) { - rc = -EFAULT; - goto error_memcpy; + if (!tre_len) + uci_log(UCI_DBG_ERROR, "tre_len is 0, not updated yet\n"); + else if (count > tre_len) { + uci_log(UCI_DBG_DBG, "Write req size (%d) > tre_len (%d)\n", count, tre_len); + cur_txfr_len = tre_len; } - rc = mhi_uci_send_packet(uci_handle, data_loc, count); + count_left = count; + cur_buf = buf; + + do { + data_loc = kmalloc(cur_txfr_len, GFP_KERNEL); + if (!data_loc) { + uci_log(UCI_DBG_ERROR, "Memory allocation failed\n"); + return -ENOMEM; + } + + memcpy_result = copy_from_user(data_loc, cur_buf, cur_txfr_len); + if (memcpy_result) { + uci_log(UCI_DBG_ERROR, "Mem copy failed\n"); + rc = -EFAULT; + goto error_memcpy; + } + + cur_rc = mhi_uci_send_packet(uci_handle, data_loc, cur_txfr_len); + if (cur_rc != cur_txfr_len) { + uci_log(UCI_DBG_ERROR, + "Send failed with error %d, after sending %d data\n", + cur_rc, rc); + rc = cur_rc; + goto error_memcpy; + } + rc += cur_rc; + cur_buf += cur_txfr_len; + count_left -= cur_txfr_len; + + if (count_left < tre_len) + cur_txfr_len = count_left; + } while (count_left); if (rc == count) return rc; @@ -1523,7 +1557,7 @@ static ssize_t mhi_uci_client_write_iter(struct kiocb *iocb, struct uci_client *uci_handle = NULL; void *data_loc; unsigned long memcpy_result; - int rc; + int rc = 0, tre_len, cur_rc = 0, count_left, cur_txfr_len; struct file *file = iocb->ki_filp; ssize_t count = iov_iter_count(buf); @@ -1533,6 +1567,8 @@ static ssize_t mhi_uci_client_write_iter(struct kiocb *iocb, } uci_handle = file->private_data; + tre_len = uci_handle->tre_len; + if (!uci_handle->send || !uci_handle->out_handle) { uci_log(UCI_DBG_DBG, "Invalid handle or send\n"); return -EINVAL; @@ -1555,17 +1591,44 @@ static ssize_t mhi_uci_client_write_iter(struct kiocb *iocb, count, uci_handle->out_chan_attr->max_packet_size); } - data_loc = kmalloc(count, GFP_KERNEL); - if (!data_loc) - return -ENOMEM; + cur_txfr_len = count; - memcpy_result = copy_from_iter_full(data_loc, count, buf); - if (!memcpy_result) { - rc = -EFAULT; - goto error_memcpy; + if (!tre_len) + uci_log(UCI_DBG_ERROR, "tre_len is 0, not updated yet\n"); + else if (count > tre_len) { + uci_log(UCI_DBG_DBG, "Write req size (%d) > tre_len (%d)\n", count, tre_len); + cur_txfr_len = tre_len; } - rc = mhi_uci_send_packet(uci_handle, data_loc, count); + count_left = count; + + do { + data_loc = kmalloc(cur_txfr_len, GFP_KERNEL); + if (!data_loc) { + uci_log(UCI_DBG_ERROR, "Memory allocation failed\n"); + return -ENOMEM; + } + + memcpy_result = copy_from_iter_full(data_loc, cur_txfr_len, buf); + if (!memcpy_result) { + uci_log(UCI_DBG_ERROR, "Mem copy failed\n"); + rc = -EFAULT; + goto error_memcpy; + } + cur_rc = mhi_uci_send_packet(uci_handle, data_loc, cur_txfr_len); + if (cur_rc != cur_txfr_len) { + uci_log(UCI_DBG_ERROR, + "Send failed with error %d, after sending %d data\n", + cur_rc, rc); + rc = cur_rc; + goto error_memcpy; + } + rc += cur_rc; + count_left -= cur_txfr_len; + if (count_left < tre_len) + cur_txfr_len = count_left; + } while (count_left); + if (rc == count) return rc; @@ -1683,6 +1746,7 @@ static void uci_event_notifier(struct mhi_dev_client_cb_reason *reason) uci_handle->in_chan); if (reason->ch_id % 2) { atomic_set(&uci_handle->write_data_ready, 1); + uci_handle->tre_len = uci_handle->out_handle->channel->tre_size; wake_up(&uci_handle->write_wq); } else { atomic_set(&uci_handle->read_data_ready, 1); diff --git a/drivers/usb/gadget/function/f_cdev.c b/drivers/usb/gadget/function/f_cdev.c index 1f9751d251de..50833c6e2c17 100644 --- a/drivers/usb/gadget/function/f_cdev.c +++ b/drivers/usb/gadget/function/f_cdev.c @@ -554,12 +554,26 @@ static void usb_cser_start_rx(struct f_cdev *port); static void usb_cser_resume(struct usb_function *f) { struct f_cdev *port = func_to_port(f); + struct usb_composite_dev *cdev = f->config->cdev; unsigned long flags; int ret; struct usb_request *req, *t; struct usb_ep *in; + /* + * Bail out if the interface is in USB3 Function Suspend state. + * In that case resume is done by Function Resume request (write). + */ + if ((cdev->gadget->speed >= USB_SPEED_SUPER) && + port->func_is_suspended) { + if (port->func_wakeup_pending) { + ret = usb_func_wakeup(f); + port->func_wakeup_pending = (ret == -EAGAIN) ? true : false; + } + return; + } + pr_debug("%s\n", __func__); port->is_suspended = false; @@ -1453,9 +1467,10 @@ ssize_t f_cdev_write(struct file *file, spin_unlock_irqrestore(&port->port_lock, flags); if (gadget->speed >= USB_SPEED_SUPER - && port->func_is_suspended) + && port->func_is_suspended) { ret = usb_func_wakeup(func); - else + port->func_wakeup_pending = (ret == -EAGAIN) ? true : false; + } else ret = usb_gadget_wakeup(gadget); if (ret < 0 && ret != -EACCES && ret != -EAGAIN) { diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index bd0f88cd0b1e..10304fc4f719 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -59,6 +59,7 @@ struct snd_compr_runtime { * @direction: stream direction, playback/recording * @metadata_set: metadata set flag, true when set * @next_track: has userspace signal next track transition, true when set + * @pause_in_draining: paused during draining state, true when set * @private_data: pointer to DSP private data */ struct snd_compr_stream { @@ -70,6 +71,7 @@ struct snd_compr_stream { enum snd_compr_direction direction; bool metadata_set; bool next_track; + bool pause_in_draining; void *private_data; #ifdef CONFIG_AUDIO_QGKI struct snd_soc_pcm_runtime *be; @@ -140,6 +142,7 @@ struct snd_compr_ops { * @direction: Playback or capture direction * @lock: device lock * @device: device id + * @use_pause_in_draining: allow pause in draining, true when set */ struct snd_compr { const char *name; @@ -150,6 +153,7 @@ struct snd_compr { unsigned int direction; struct mutex lock; int device; + bool use_pause_in_draining; #ifdef CONFIG_SND_VERBOSE_PROCFS /* private: */ char id[64];