mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 05:39:54 -04:00
Merge "i2c-msm-geni: KASAN: use-after-free in __list_add_valid+0x2c/0xc4"
This commit is contained in:
commit
e531d35984
1 changed files with 51 additions and 4 deletions
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
|
|
@ -136,10 +137,12 @@ struct geni_i2c_dev {
|
|||
bool disable_dma_mode;
|
||||
bool prev_cancel_pending; //Halt cancel till IOS in good state
|
||||
bool is_i2c_rtl_based; /* doing pending cancel only for rtl based SE's */
|
||||
atomic_t is_xfer_in_progress; /* Used to maintain xfer inprogress status */
|
||||
};
|
||||
|
||||
static struct geni_i2c_dev *gi2c_dev_dbg[MAX_SE];
|
||||
static int arr_idx;
|
||||
static int geni_i2c_runtime_suspend(struct device *dev);
|
||||
|
||||
struct geni_i2c_err_log {
|
||||
int err;
|
||||
|
|
@ -1052,11 +1055,13 @@ static int geni_i2c_xfer(struct i2c_adapter *adap,
|
|||
int i, ret = 0, timeout = 0;
|
||||
|
||||
gi2c->err = 0;
|
||||
atomic_set(&gi2c->is_xfer_in_progress, 1);
|
||||
|
||||
/* Client to respect system suspend */
|
||||
if (!pm_runtime_enabled(gi2c->dev)) {
|
||||
GENI_SE_ERR(gi2c->ipcl, false, gi2c->dev,
|
||||
"%s: System suspended\n", __func__);
|
||||
atomic_set(&gi2c->is_xfer_in_progress, 0);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
|
|
@ -1068,6 +1073,7 @@ static int geni_i2c_xfer(struct i2c_adapter *adap,
|
|||
pm_runtime_put_noidle(gi2c->dev);
|
||||
/* Set device in suspended since resume failed */
|
||||
pm_runtime_set_suspended(gi2c->dev);
|
||||
atomic_set(&gi2c->is_xfer_in_progress, 0);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -1078,12 +1084,13 @@ static int geni_i2c_xfer(struct i2c_adapter *adap,
|
|||
if (ret) {
|
||||
pm_runtime_mark_last_busy(gi2c->dev);
|
||||
pm_runtime_put_autosuspend(gi2c->dev);
|
||||
atomic_set(&gi2c->is_xfer_in_progress, 0);
|
||||
return ret; //Don't perform xfer is cancel failed
|
||||
}
|
||||
}
|
||||
|
||||
GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
|
||||
"n:%d addr:0x%x\n", num, msgs[0].addr);
|
||||
"n:%d addr:0x%x\n", num, msgs[0].addr);
|
||||
|
||||
gi2c->dbg_num = num;
|
||||
kfree(gi2c->dbg_buf_ptr);
|
||||
|
|
@ -1268,7 +1275,7 @@ geni_i2c_txn_ret:
|
|||
pm_runtime_mark_last_busy(gi2c->dev);
|
||||
pm_runtime_put_autosuspend(gi2c->dev);
|
||||
}
|
||||
|
||||
atomic_set(&gi2c->is_xfer_in_progress, 0);
|
||||
gi2c->cur = NULL;
|
||||
GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
|
||||
"i2c txn ret:%d, num:%d, err:%d\n", ret, num, gi2c->err);
|
||||
|
|
@ -1476,10 +1483,10 @@ static int geni_i2c_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
atomic_set(&gi2c->is_xfer_in_progress, 0);
|
||||
snprintf(boot_marker, sizeof(boot_marker),
|
||||
"M - DRIVER GENI_I2C_%d Ready", gi2c->adap.nr);
|
||||
"M - DRIVER GENI_I2C_%d Ready", gi2c->adap.nr);
|
||||
place_marker(boot_marker);
|
||||
|
||||
dev_info(gi2c->dev, "I2C probed\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1489,6 +1496,33 @@ static int geni_i2c_remove(struct platform_device *pdev)
|
|||
struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
if (atomic_read(&gi2c->is_xfer_in_progress)) {
|
||||
GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
|
||||
"%s: Xfer is in progress\n", __func__);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!pm_runtime_status_suspended(gi2c->dev)) {
|
||||
if (geni_i2c_runtime_suspend(gi2c->dev))
|
||||
GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
|
||||
"%s: runtime suspend failed\n", __func__);
|
||||
}
|
||||
|
||||
if (gi2c->se_mode == GSI_ONLY) {
|
||||
if (gi2c->tx_c) {
|
||||
GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
|
||||
"%s: clearing tx dma resource\n", __func__);
|
||||
dma_release_channel(gi2c->tx_c);
|
||||
}
|
||||
if (gi2c->rx_c) {
|
||||
GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
|
||||
"%s: clearing rx dma resource\n", __func__);
|
||||
dma_release_channel(gi2c->rx_c);
|
||||
}
|
||||
}
|
||||
|
||||
pm_runtime_put_noidle(gi2c->dev);
|
||||
pm_runtime_set_suspended(gi2c->dev);
|
||||
pm_runtime_disable(gi2c->dev);
|
||||
i2c_del_adapter(&gi2c->adap);
|
||||
|
||||
|
|
@ -1594,6 +1628,19 @@ static int geni_i2c_suspend_late(struct device *device)
|
|||
int ret;
|
||||
|
||||
GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, "%s\n", __func__);
|
||||
|
||||
if (atomic_read(&gi2c->is_xfer_in_progress)) {
|
||||
if (!pm_runtime_status_suspended(gi2c->dev)) {
|
||||
GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
|
||||
":%s: runtime PM is active\n", __func__);
|
||||
return -EBUSY;
|
||||
}
|
||||
GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
|
||||
"%s System suspend not allowed while xfer in progress\n",
|
||||
__func__);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Make sure no transactions are pending */
|
||||
ret = i2c_trylock_bus(&gi2c->adap, I2C_LOCK_SEGMENT);
|
||||
if (!ret) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue