mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 13:49:24 -04:00
vl53l1: fix i2c dma transfer crash
If the i2c master starts the dma transfer, the buffer must be physical continous. or i2c_transfer will crash. __dma_inv_area+0x28/0x58 geni_se_rx_dma_prep+0xb0/0x208 geni_i2c_xfer+0x2e8/0xf88 __i2c_transfer+0x598/0x790 i2c_transfer+0xa0/0xe8 cci_read.isra.1+0xa4/0x140 [stmvl53l1] VL53L1_ReadMulti+0x3c/0x54 [stmvl53l1] VL53L1_get_nvm_copy_data+0x40/0x88 [stmvl53l1] VL53L1_read_p2p_data+0xbc/0x210 [stmvl53l1] VL53L1_data_init+0x248/0x254 [stmvl53l1] VL53L1_DataInit+0x28/0xcc [stmvl53l1] stmvl53l1_setup+0x4a8/0x9f0 [stmvl53l1] stmvl53l1_probe+0x1e4/0x8c8 [stmvl53l1] i2c_device_probe+0x258/0x2e0 driver_probe_device+0x4c0/0x658 __driver_attach+0x104/0x1b0 bus_for_each_dev+0x8c/0xd8 driver_attach+0x2c/0x38 bus_add_driver+0x138/0x240 driver_register+0xac/0xf8 i2c_register_driver+0x4c/0xd0 stmvl53l1_init_i2c+0x44/0x188 [stmvl53l1] stmvl53l1_init+0x3c/0x1000 [stmvl53l1] Change-Id: I8c328f1e5187dbd1de80aa700aa560ef29a9ed4d Signed-off-by: liuyc20 <liuyc20@lenovo.com> Reviewed-on: https://gerrit.mot.com/1377597 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao <liaohs@motorola.com> Reviewed-by: Dawei Wang <wangdw10@motorola.com> Submit-Approved: Jira Key
This commit is contained in:
parent
c3001644d7
commit
e388a3537b
3 changed files with 52 additions and 6 deletions
|
|
@ -93,6 +93,12 @@ struct i2c_data {
|
|||
struct msgtctrl_t {
|
||||
unsigned unhandled_irq_vec:1;
|
||||
} msg_flag;
|
||||
|
||||
struct i2c_dma_data {
|
||||
struct mutex lock;
|
||||
uint8_t *data;
|
||||
unsigned int len;
|
||||
} dma_data;
|
||||
};
|
||||
|
||||
int stmvl53l1_init_i2c(void);
|
||||
|
|
|
|||
|
|
@ -111,7 +111,6 @@ static uint32_t tv_elapsed_ms(struct timeval *tv)
|
|||
static int cci_write(struct stmvl53l1_data *dev, int index,
|
||||
uint8_t *data, uint16_t len)
|
||||
{
|
||||
uint8_t buffer[STMVL53L1_MAX_CCI_XFER_SZ + 2];
|
||||
struct i2c_msg msg;
|
||||
struct i2c_data *i2c_client_obj = (struct i2c_data *)dev->client_object;
|
||||
struct i2c_client *client = (struct i2c_client *)i2c_client_obj->client;
|
||||
|
|
@ -122,16 +121,30 @@ static int cci_write(struct stmvl53l1_data *dev, int index,
|
|||
vl53l1_errmsg("invalid len %d\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mutex_lock(&i2c_client_obj->dma_data.lock);
|
||||
if (i2c_client_obj->dma_data.len < len + 2) {
|
||||
if (i2c_client_obj->dma_data.data)
|
||||
kfree(i2c_client_obj->dma_data.data);
|
||||
i2c_client_obj->dma_data.data = kzalloc(len + 2, GFP_KERNEL);
|
||||
if (!i2c_client_obj->dma_data.data) {
|
||||
i2c_client_obj->dma_data.len = 0;
|
||||
mutex_unlock(&i2c_client_obj->dma_data.lock);
|
||||
return -1;
|
||||
}
|
||||
i2c_client_obj->dma_data.len = len + 2;
|
||||
}
|
||||
|
||||
cci_access_start();
|
||||
/* build up little endian index in buffer */
|
||||
buffer[0] = (index >> 8) & 0xFF;
|
||||
buffer[1] = (index >> 0) & 0xFF;
|
||||
i2c_client_obj->dma_data.data[0] = (index >> 8) & 0xFF;
|
||||
i2c_client_obj->dma_data.data[1] = (index >> 0) & 0xFF;
|
||||
/* copy write data to buffer after index */
|
||||
memcpy(buffer + 2, data, len);
|
||||
memcpy(i2c_client_obj->dma_data.data + 2, data, len);
|
||||
/* set i2c msg */
|
||||
msg.addr = client->addr;
|
||||
msg.flags = client->flags;
|
||||
msg.buf = buffer;
|
||||
msg.buf = i2c_client_obj->dma_data.data;
|
||||
msg.len = len + 2;
|
||||
|
||||
rc = i2c_transfer(client->adapter, &msg, 1);
|
||||
|
|
@ -139,6 +152,9 @@ static int cci_write(struct stmvl53l1_data *dev, int index,
|
|||
vl53l1_errmsg("wr i2c_transfer err:%d, index 0x%x len %d\n",
|
||||
rc, index, len);
|
||||
}
|
||||
|
||||
mutex_unlock(&i2c_client_obj->dma_data.lock);
|
||||
|
||||
cci_access_over("rd status %d long %d ", rc != 1, len);
|
||||
return rc != 1;
|
||||
}
|
||||
|
|
@ -157,6 +173,20 @@ static int cci_read(struct stmvl53l1_data *dev, int index,
|
|||
vl53l1_errmsg("invalid len %d\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mutex_lock(&i2c_client_obj->dma_data.lock);
|
||||
if (i2c_client_obj->dma_data.len < len) {
|
||||
if (i2c_client_obj->dma_data.data)
|
||||
kfree(i2c_client_obj->dma_data.data);
|
||||
i2c_client_obj->dma_data.data = kzalloc(len, GFP_KERNEL);
|
||||
if (!i2c_client_obj->dma_data.data) {
|
||||
i2c_client_obj->dma_data.len = 0;
|
||||
mutex_unlock(&i2c_client_obj->dma_data.lock);
|
||||
return -1;
|
||||
}
|
||||
i2c_client_obj->dma_data.len = len;
|
||||
}
|
||||
|
||||
cci_access_start();
|
||||
|
||||
/* build up little endian index in buffer */
|
||||
|
|
@ -170,7 +200,7 @@ static int cci_read(struct stmvl53l1_data *dev, int index,
|
|||
/* read part of the i2c transaction */
|
||||
msg[1].addr = client->addr;
|
||||
msg[1].flags = I2C_M_RD | client->flags;
|
||||
msg[1].buf = data;
|
||||
msg[1].buf = i2c_client_obj->dma_data.data;
|
||||
msg[1].len = len;
|
||||
|
||||
rc = i2c_transfer(client->adapter, msg, 2);
|
||||
|
|
@ -179,6 +209,10 @@ static int cci_read(struct stmvl53l1_data *dev, int index,
|
|||
__func__, rc, client->addr, index, len);
|
||||
|
||||
}
|
||||
|
||||
memcpy(data, i2c_client_obj->dma_data.data, len);
|
||||
mutex_unlock(&i2c_client_obj->dma_data.lock);
|
||||
|
||||
cci_access_over(" wr len %d status %d", rc != 2, len);
|
||||
return rc != 2;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -506,6 +506,8 @@ static int stmvl53l1_probe(struct i2c_client *client,
|
|||
i2c_data->client = client;
|
||||
i2c_data->vl53l1_data = vl53l1_data;
|
||||
i2c_data->irq = -1 ; /* init to no irq */
|
||||
i2c_data->dma_data.len = 0;
|
||||
mutex_init(&i2c_data->dma_data.lock);
|
||||
|
||||
/* parse and configure hardware */
|
||||
rc = stmvl53l1_parse_tree(&i2c_data->client->dev, i2c_data);
|
||||
|
|
@ -921,6 +923,10 @@ static void memory_release(struct kref *kref)
|
|||
struct i2c_data *data = container_of(kref, struct i2c_data, ref);
|
||||
|
||||
vl53l1_dbgmsg("Enter\n");
|
||||
mutex_lock(&data->dma_data.lock);
|
||||
if (data->dma_data.len > 0 && data->dma_data.data)
|
||||
kfree(data->dma_data.data);
|
||||
mutex_unlock(&data->dma_data.lock);
|
||||
kfree(data->vl53l1_data);
|
||||
kfree(data);
|
||||
vl53l1_dbgmsg("End\n");
|
||||
|
|
|
|||
Loading…
Reference in a new issue