Commit e94bc5d1 authored by Wolfram Sang's avatar Wolfram Sang Committed by Wolfram Sang

i2c: add helpers to ease DMA handling

One helper checks if DMA is suitable and optionally creates a bounce
buffer, if not. The other function returns the bounce buffer and makes
sure the data is properly copied back to the message.
Reviewed-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: default avatarWolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
parent 521a72e1
......@@ -2200,6 +2200,52 @@ void i2c_put_adapter(struct i2c_adapter *adap)
}
EXPORT_SYMBOL(i2c_put_adapter);
/**
* i2c_get_dma_safe_msg_buf() - get a DMA safe buffer for the given i2c_msg
* @msg: the message to be checked
* @threshold: the minimum number of bytes for which using DMA makes sense
*
* Return: NULL if a DMA safe buffer was not obtained. Use msg->buf with PIO.
* Or a valid pointer to be used with DMA. After use, release it by
* calling i2c_release_dma_safe_msg_buf().
*
* This function must only be called from process context!
*/
u8 *i2c_get_dma_safe_msg_buf(struct i2c_msg *msg, unsigned int threshold)
{
if (msg->len < threshold)
return NULL;
if (msg->flags & I2C_M_DMA_SAFE)
return msg->buf;
pr_debug("using bounce buffer for addr=0x%02x, len=%d\n",
msg->addr, msg->len);
if (msg->flags & I2C_M_RD)
return kzalloc(msg->len, GFP_KERNEL);
else
return kmemdup(msg->buf, msg->len, GFP_KERNEL);
}
EXPORT_SYMBOL_GPL(i2c_get_dma_safe_msg_buf);
/**
* i2c_release_dma_safe_msg_buf - release DMA safe buffer and sync with i2c_msg
* @msg: the message to be synced with
* @buf: the buffer obtained from i2c_get_dma_safe_msg_buf(). May be NULL.
*/
void i2c_release_dma_safe_msg_buf(struct i2c_msg *msg, u8 *buf)
{
if (!buf || buf == msg->buf)
return;
if (msg->flags & I2C_M_RD)
memcpy(msg->buf, buf, msg->len);
kfree(buf);
}
EXPORT_SYMBOL_GPL(i2c_release_dma_safe_msg_buf);
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C-Bus main module");
MODULE_LICENSE("GPL");
......@@ -768,6 +768,9 @@ static inline u8 i2c_8bit_addr_from_msg(const struct i2c_msg *msg)
return (msg->addr << 1) | (msg->flags & I2C_M_RD ? 1 : 0);
}
u8 *i2c_get_dma_safe_msg_buf(struct i2c_msg *msg, unsigned int threshold);
void i2c_release_dma_safe_msg_buf(struct i2c_msg *msg, u8 *buf);
int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr);
/**
* module_i2c_driver() - Helper macro for registering a modular I2C driver
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment