mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 14:19:09 -04:00
Merge tag 'LA.UM.9.14.1.r1-14100-QCM6490.QSSI14.0' of https://git.codelinaro.org/clo/la/kernel/msm-5.4 into android13-5.4-lahaina
"LA.UM.9.14.1.r1-14100-QCM6490.QSSI14.0" * tag 'LA.UM.9.14.1.r1-14100-QCM6490.QSSI14.0' of https://git.codelinaro.org/clo/la/kernel/msm-5.4: msm: adsprpc: use-after-free (UAF) in global maps sdxnightJar.config: kernel changes for TRIGGER target msm: mhi_dev: Add UCI support if client req > TRE length usb: gadget: f_cdev: Call function wakeup if func_wakeup_pending is set usb: gadget: f_cdev: Bail out from cer_resume if func_suspended msm: kgsl: Do not release dma and anon buffers if unmap fails ALSA: compress: Remove redefinition BACKPORT: media: venus: hfi: fix the check in session buffer requirement msm: kgsl: Do not free sharedmem if it cannot be unmapped ALSA: compress: allow pause and resume during draining securemsm-kernel: Fix multiple listener registration on same fd Configured process_madvise with upstream syscall number msm: kgsl: Limit the syncpoint count for AUX commands msm: kgsl: Prevent wrap around during user address mapping iommu: Fix missing return check of arm_lpae_init_pte Change-Id: I59256059b3d15fed896a7ce58d09f0950829dabb
This commit is contained in:
commit
bb1bc18ab1
6 changed files with 164 additions and 81 deletions
1
arch/arm/configs/vendor/sdxnightjar.config
vendored
1
arch/arm/configs/vendor/sdxnightjar.config
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
Loading…
Reference in a new issue