mirror of
https://github.com/torvalds/linux.git
synced 2025-11-30 23:16:01 +07:00
Merge tag 'char-misc-6.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver fixes from Greg KH: "Here are some small char/misc/android driver fixes for 6.18-rc3 for reported issues. Included in here are: - rust binder fixes for reported issues - mei device id addition - mei driver fixes - comedi bugfix - most usb driver bugfixes - fastrpc memory leak fix All of these have been in linux-next for a while with no reported issues" * tag 'char-misc-6.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: most: usb: hdm_probe: Fix calling put_device() before device initialization most: usb: Fix use-after-free in hdm_disconnect binder: remove "invalid inc weak" check mei: txe: fix initialization order comedi: fix divide-by-zero in comedi_buf_munge() mei: late_bind: Fix -Wincompatible-function-pointer-types-strict misc: fastrpc: Fix dma_buf object leak in fastrpc_map_lookup mei: me: add wildcat lake P DID misc: amd-sbi: Clarify that this is a BMC driver nvmem: rcar-efuse: add missing MODULE_DEVICE_TABLE binder: Fix missing kernel-doc entries in binder.c rust_binder: report freeze notification only when fully frozen rust_binder: don't delete FreezeListener if there are pending duplicates rust_binder: freeze_notif_done should resend if wrong state rust_binder: remove warning about orphan mappings rust_binder: clean `clippy::mem_replace_with_default` warning
This commit is contained in:
@@ -851,17 +851,8 @@ static int binder_inc_node_nilocked(struct binder_node *node, int strong,
|
||||
} else {
|
||||
if (!internal)
|
||||
node->local_weak_refs++;
|
||||
if (!node->has_weak_ref && list_empty(&node->work.entry)) {
|
||||
if (target_list == NULL) {
|
||||
pr_err("invalid inc weak node for %d\n",
|
||||
node->debug_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
/*
|
||||
* See comment above
|
||||
*/
|
||||
if (!node->has_weak_ref && target_list && list_empty(&node->work.entry))
|
||||
binder_enqueue_work_ilocked(&node->work, target_list);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2418,10 +2409,10 @@ err_fd_not_accepted:
|
||||
|
||||
/**
|
||||
* struct binder_ptr_fixup - data to be fixed-up in target buffer
|
||||
* @offset offset in target buffer to fixup
|
||||
* @skip_size bytes to skip in copy (fixup will be written later)
|
||||
* @fixup_data data to write at fixup offset
|
||||
* @node list node
|
||||
* @offset: offset in target buffer to fixup
|
||||
* @skip_size: bytes to skip in copy (fixup will be written later)
|
||||
* @fixup_data: data to write at fixup offset
|
||||
* @node: list node
|
||||
*
|
||||
* This is used for the pointer fixup list (pf) which is created and consumed
|
||||
* during binder_transaction() and is only accessed locally. No
|
||||
@@ -2438,10 +2429,10 @@ struct binder_ptr_fixup {
|
||||
|
||||
/**
|
||||
* struct binder_sg_copy - scatter-gather data to be copied
|
||||
* @offset offset in target buffer
|
||||
* @sender_uaddr user address in source buffer
|
||||
* @length bytes to copy
|
||||
* @node list node
|
||||
* @offset: offset in target buffer
|
||||
* @sender_uaddr: user address in source buffer
|
||||
* @length: bytes to copy
|
||||
* @node: list node
|
||||
*
|
||||
* This is used for the sg copy list (sgc) which is created and consumed
|
||||
* during binder_transaction() and is only accessed locally. No
|
||||
@@ -4063,14 +4054,15 @@ binder_freeze_notification_done(struct binder_proc *proc,
|
||||
|
||||
/**
|
||||
* binder_free_buf() - free the specified buffer
|
||||
* @proc: binder proc that owns buffer
|
||||
* @buffer: buffer to be freed
|
||||
* @is_failure: failed to send transaction
|
||||
* @proc: binder proc that owns buffer
|
||||
* @thread: binder thread performing the buffer release
|
||||
* @buffer: buffer to be freed
|
||||
* @is_failure: failed to send transaction
|
||||
*
|
||||
* If buffer for an async transaction, enqueue the next async
|
||||
* If the buffer is for an async transaction, enqueue the next async
|
||||
* transaction from the node.
|
||||
*
|
||||
* Cleanup buffer and free it.
|
||||
* Cleanup the buffer and free it.
|
||||
*/
|
||||
static void
|
||||
binder_free_buf(struct binder_proc *proc,
|
||||
|
||||
@@ -106,13 +106,22 @@ impl DeliverToRead for FreezeMessage {
|
||||
return Ok(true);
|
||||
}
|
||||
if freeze.is_clearing {
|
||||
_removed_listener = freeze_entry.remove_node();
|
||||
kernel::warn_on!(freeze.num_cleared_duplicates != 0);
|
||||
if freeze.num_pending_duplicates > 0 {
|
||||
// The primary freeze listener was deleted, so convert a pending duplicate back
|
||||
// into the primary one.
|
||||
freeze.num_pending_duplicates -= 1;
|
||||
freeze.is_pending = true;
|
||||
freeze.is_clearing = true;
|
||||
} else {
|
||||
_removed_listener = freeze_entry.remove_node();
|
||||
}
|
||||
drop(node_refs);
|
||||
writer.write_code(BR_CLEAR_FREEZE_NOTIFICATION_DONE)?;
|
||||
writer.write_payload(&self.cookie.0)?;
|
||||
Ok(true)
|
||||
} else {
|
||||
let is_frozen = freeze.node.owner.inner.lock().is_frozen;
|
||||
let is_frozen = freeze.node.owner.inner.lock().is_frozen.is_fully_frozen();
|
||||
if freeze.last_is_frozen == Some(is_frozen) {
|
||||
return Ok(true);
|
||||
}
|
||||
@@ -245,8 +254,9 @@ impl Process {
|
||||
);
|
||||
return Err(EINVAL);
|
||||
}
|
||||
if freeze.is_clearing {
|
||||
// Immediately send another FreezeMessage for BR_CLEAR_FREEZE_NOTIFICATION_DONE.
|
||||
let is_frozen = freeze.node.owner.inner.lock().is_frozen.is_fully_frozen();
|
||||
if freeze.is_clearing || freeze.last_is_frozen != Some(is_frozen) {
|
||||
// Immediately send another FreezeMessage.
|
||||
clear_msg = Some(FreezeMessage::init(alloc, cookie));
|
||||
}
|
||||
freeze.is_pending = false;
|
||||
|
||||
@@ -687,7 +687,7 @@ impl Node {
|
||||
);
|
||||
}
|
||||
if inner.freeze_list.is_empty() {
|
||||
_unused_capacity = mem::replace(&mut inner.freeze_list, KVVec::new());
|
||||
_unused_capacity = mem::take(&mut inner.freeze_list);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,33 @@ impl Mapping {
|
||||
const PROC_DEFER_FLUSH: u8 = 1;
|
||||
const PROC_DEFER_RELEASE: u8 = 2;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub(crate) enum IsFrozen {
|
||||
Yes,
|
||||
No,
|
||||
InProgress,
|
||||
}
|
||||
|
||||
impl IsFrozen {
|
||||
/// Whether incoming transactions should be rejected due to freeze.
|
||||
pub(crate) fn is_frozen(self) -> bool {
|
||||
match self {
|
||||
IsFrozen::Yes => true,
|
||||
IsFrozen::No => false,
|
||||
IsFrozen::InProgress => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether freeze notifications consider this process frozen.
|
||||
pub(crate) fn is_fully_frozen(self) -> bool {
|
||||
match self {
|
||||
IsFrozen::Yes => true,
|
||||
IsFrozen::No => false,
|
||||
IsFrozen::InProgress => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The fields of `Process` protected by the spinlock.
|
||||
pub(crate) struct ProcessInner {
|
||||
is_manager: bool,
|
||||
@@ -98,7 +125,7 @@ pub(crate) struct ProcessInner {
|
||||
/// are woken up.
|
||||
outstanding_txns: u32,
|
||||
/// Process is frozen and unable to service binder transactions.
|
||||
pub(crate) is_frozen: bool,
|
||||
pub(crate) is_frozen: IsFrozen,
|
||||
/// Process received sync transactions since last frozen.
|
||||
pub(crate) sync_recv: bool,
|
||||
/// Process received async transactions since last frozen.
|
||||
@@ -124,7 +151,7 @@ impl ProcessInner {
|
||||
started_thread_count: 0,
|
||||
defer_work: 0,
|
||||
outstanding_txns: 0,
|
||||
is_frozen: false,
|
||||
is_frozen: IsFrozen::No,
|
||||
sync_recv: false,
|
||||
async_recv: false,
|
||||
binderfs_file: None,
|
||||
@@ -1260,7 +1287,7 @@ impl Process {
|
||||
let is_manager = {
|
||||
let mut inner = self.inner.lock();
|
||||
inner.is_dead = true;
|
||||
inner.is_frozen = false;
|
||||
inner.is_frozen = IsFrozen::No;
|
||||
inner.sync_recv = false;
|
||||
inner.async_recv = false;
|
||||
inner.is_manager
|
||||
@@ -1346,10 +1373,6 @@ impl Process {
|
||||
.alloc
|
||||
.take_for_each(|offset, size, debug_id, odata| {
|
||||
let ptr = offset + address;
|
||||
pr_warn!(
|
||||
"{}: removing orphan mapping {offset}:{size}\n",
|
||||
self.pid_in_current_ns()
|
||||
);
|
||||
let mut alloc =
|
||||
Allocation::new(self.clone(), debug_id, offset, size, ptr, false);
|
||||
if let Some(data) = odata {
|
||||
@@ -1371,7 +1394,7 @@ impl Process {
|
||||
return;
|
||||
}
|
||||
inner.outstanding_txns -= 1;
|
||||
inner.is_frozen && inner.outstanding_txns == 0
|
||||
inner.is_frozen.is_frozen() && inner.outstanding_txns == 0
|
||||
};
|
||||
|
||||
if wake {
|
||||
@@ -1385,7 +1408,7 @@ impl Process {
|
||||
let mut inner = self.inner.lock();
|
||||
inner.sync_recv = false;
|
||||
inner.async_recv = false;
|
||||
inner.is_frozen = false;
|
||||
inner.is_frozen = IsFrozen::No;
|
||||
drop(inner);
|
||||
msgs.send_messages();
|
||||
return Ok(());
|
||||
@@ -1394,7 +1417,7 @@ impl Process {
|
||||
let mut inner = self.inner.lock();
|
||||
inner.sync_recv = false;
|
||||
inner.async_recv = false;
|
||||
inner.is_frozen = true;
|
||||
inner.is_frozen = IsFrozen::InProgress;
|
||||
|
||||
if info.timeout_ms > 0 {
|
||||
let mut jiffies = kernel::time::msecs_to_jiffies(info.timeout_ms);
|
||||
@@ -1408,7 +1431,7 @@ impl Process {
|
||||
.wait_interruptible_timeout(&mut inner, jiffies)
|
||||
{
|
||||
CondVarTimeoutResult::Signal { .. } => {
|
||||
inner.is_frozen = false;
|
||||
inner.is_frozen = IsFrozen::No;
|
||||
return Err(ERESTARTSYS);
|
||||
}
|
||||
CondVarTimeoutResult::Woken { jiffies: remaining } => {
|
||||
@@ -1422,17 +1445,18 @@ impl Process {
|
||||
}
|
||||
|
||||
if inner.txns_pending_locked() {
|
||||
inner.is_frozen = false;
|
||||
inner.is_frozen = IsFrozen::No;
|
||||
Err(EAGAIN)
|
||||
} else {
|
||||
drop(inner);
|
||||
match self.prepare_freeze_messages() {
|
||||
Ok(batch) => {
|
||||
self.inner.lock().is_frozen = IsFrozen::Yes;
|
||||
batch.send_messages();
|
||||
Ok(())
|
||||
}
|
||||
Err(kernel::alloc::AllocError) => {
|
||||
self.inner.lock().is_frozen = false;
|
||||
self.inner.lock().is_frozen = IsFrozen::No;
|
||||
Err(ENOMEM)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,7 +249,7 @@ impl Transaction {
|
||||
|
||||
if oneway {
|
||||
if let Some(target_node) = self.target_node.clone() {
|
||||
if process_inner.is_frozen {
|
||||
if process_inner.is_frozen.is_frozen() {
|
||||
process_inner.async_recv = true;
|
||||
if self.flags & TF_UPDATE_TXN != 0 {
|
||||
if let Some(t_outdated) =
|
||||
@@ -270,7 +270,7 @@ impl Transaction {
|
||||
}
|
||||
}
|
||||
|
||||
if process_inner.is_frozen {
|
||||
if process_inner.is_frozen.is_frozen() {
|
||||
return Err(BinderError::new_frozen_oneway());
|
||||
} else {
|
||||
return Ok(());
|
||||
@@ -280,7 +280,7 @@ impl Transaction {
|
||||
}
|
||||
}
|
||||
|
||||
if process_inner.is_frozen {
|
||||
if process_inner.is_frozen.is_frozen() {
|
||||
process_inner.sync_recv = true;
|
||||
return Err(BinderError::new_frozen());
|
||||
}
|
||||
|
||||
@@ -317,7 +317,7 @@ static unsigned int comedi_buf_munge(struct comedi_subdevice *s,
|
||||
unsigned int count = 0;
|
||||
const unsigned int num_sample_bytes = comedi_bytes_per_sample(s);
|
||||
|
||||
if (!s->munge || (async->cmd.flags & CMDF_RAWDATA)) {
|
||||
if (!s->munge || (async->cmd.flags & CMDF_RAWDATA) || async->cmd.chanlist_len == 0) {
|
||||
async->munge_count += num_bytes;
|
||||
return num_bytes;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
config AMD_SBRMI_I2C
|
||||
tristate "AMD side band RMI support"
|
||||
depends on I2C
|
||||
depends on ARM || ARM64 || COMPILE_TEST
|
||||
select REGMAP_I2C
|
||||
help
|
||||
Side band RMI over I2C support for AMD out of band management.
|
||||
This driver is intended to run on the BMC, not the managed node.
|
||||
|
||||
This driver can also be built as a module. If so, the module will
|
||||
be called sbrmi-i2c.
|
||||
|
||||
@@ -381,6 +381,8 @@ static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd,
|
||||
}
|
||||
spin_unlock(&fl->lock);
|
||||
|
||||
dma_buf_put(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -120,6 +120,8 @@
|
||||
#define MEI_DEV_ID_PTL_H 0xE370 /* Panther Lake H */
|
||||
#define MEI_DEV_ID_PTL_P 0xE470 /* Panther Lake P */
|
||||
|
||||
#define MEI_DEV_ID_WCL_P 0x4D70 /* Wildcat Lake P */
|
||||
|
||||
/*
|
||||
* MEI HW Section
|
||||
*/
|
||||
|
||||
@@ -134,8 +134,7 @@ static bool mei_lb_check_response(const struct device *dev, ssize_t bytes,
|
||||
return true;
|
||||
}
|
||||
|
||||
static int mei_lb_push_payload(struct device *dev,
|
||||
enum intel_lb_type type, u32 flags,
|
||||
static int mei_lb_push_payload(struct device *dev, u32 type, u32 flags,
|
||||
const void *payload, size_t payload_size)
|
||||
{
|
||||
struct mei_cl_device *cldev;
|
||||
|
||||
@@ -127,6 +127,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_PTL_H, MEI_ME_PCH15_CFG)},
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_PTL_P, MEI_ME_PCH15_CFG)},
|
||||
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_WCL_P, MEI_ME_PCH15_CFG)},
|
||||
|
||||
/* required last entry */
|
||||
{0, }
|
||||
};
|
||||
|
||||
@@ -109,19 +109,19 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
goto end;
|
||||
}
|
||||
|
||||
err = mei_register(dev, &pdev->dev);
|
||||
if (err)
|
||||
goto release_irq;
|
||||
|
||||
if (mei_start(dev)) {
|
||||
dev_err(&pdev->dev, "init hw failure.\n");
|
||||
err = -ENODEV;
|
||||
goto release_irq;
|
||||
goto deregister;
|
||||
}
|
||||
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_TXI_RPM_TIMEOUT);
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
|
||||
err = mei_register(dev, &pdev->dev);
|
||||
if (err)
|
||||
goto stop;
|
||||
|
||||
pci_set_drvdata(pdev, dev);
|
||||
|
||||
/*
|
||||
@@ -144,8 +144,8 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
return 0;
|
||||
|
||||
stop:
|
||||
mei_stop(dev);
|
||||
deregister:
|
||||
mei_deregister(dev);
|
||||
release_irq:
|
||||
mei_cancel_work(dev);
|
||||
mei_disable_interrupts(dev);
|
||||
|
||||
@@ -929,6 +929,10 @@ static void release_mdev(struct device *dev)
|
||||
{
|
||||
struct most_dev *mdev = to_mdev_from_dev(dev);
|
||||
|
||||
kfree(mdev->busy_urbs);
|
||||
kfree(mdev->cap);
|
||||
kfree(mdev->conf);
|
||||
kfree(mdev->ep_address);
|
||||
kfree(mdev);
|
||||
}
|
||||
/**
|
||||
@@ -1093,7 +1097,7 @@ err_free_cap:
|
||||
err_free_conf:
|
||||
kfree(mdev->conf);
|
||||
err_free_mdev:
|
||||
put_device(&mdev->dev);
|
||||
kfree(mdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1121,13 +1125,6 @@ static void hdm_disconnect(struct usb_interface *interface)
|
||||
if (mdev->dci)
|
||||
device_unregister(&mdev->dci->dev);
|
||||
most_deregister_interface(&mdev->iface);
|
||||
|
||||
kfree(mdev->busy_urbs);
|
||||
kfree(mdev->cap);
|
||||
kfree(mdev->conf);
|
||||
kfree(mdev->ep_address);
|
||||
put_device(&mdev->dci->dev);
|
||||
put_device(&mdev->dev);
|
||||
}
|
||||
|
||||
static int hdm_suspend(struct usb_interface *interface, pm_message_t message)
|
||||
|
||||
@@ -127,6 +127,7 @@ static const struct of_device_id rcar_fuse_match[] = {
|
||||
{ .compatible = "renesas,r8a779h0-otp", .data = &rcar_fuse_v4m },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rcar_fuse_match);
|
||||
|
||||
static struct platform_driver rcar_fuse_driver = {
|
||||
.probe = rcar_fuse_probe,
|
||||
|
||||
Reference in New Issue
Block a user