diff options
-rw-r--r-- | drivers/i2c/i2c-core-base.c | 46 | ||||
-rw-r--r-- | include/linux/i2c.h | 3 |
2 files changed, 49 insertions, 0 deletions
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index bf52cca87363..b6ca97f0322b 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c | |||
@@ -2200,6 +2200,52 @@ void i2c_put_adapter(struct i2c_adapter *adap) | |||
2200 | } | 2200 | } |
2201 | EXPORT_SYMBOL(i2c_put_adapter); | 2201 | EXPORT_SYMBOL(i2c_put_adapter); |
2202 | 2202 | ||
2203 | /** | ||
2204 | * i2c_get_dma_safe_msg_buf() - get a DMA safe buffer for the given i2c_msg | ||
2205 | * @msg: the message to be checked | ||
2206 | * @threshold: the minimum number of bytes for which using DMA makes sense | ||
2207 | * | ||
2208 | * Return: NULL if a DMA safe buffer was not obtained. Use msg->buf with PIO. | ||
2209 | * Or a valid pointer to be used with DMA. After use, release it by | ||
2210 | * calling i2c_release_dma_safe_msg_buf(). | ||
2211 | * | ||
2212 | * This function must only be called from process context! | ||
2213 | */ | ||
2214 | u8 *i2c_get_dma_safe_msg_buf(struct i2c_msg *msg, unsigned int threshold) | ||
2215 | { | ||
2216 | if (msg->len < threshold) | ||
2217 | return NULL; | ||
2218 | |||
2219 | if (msg->flags & I2C_M_DMA_SAFE) | ||
2220 | return msg->buf; | ||
2221 | |||
2222 | pr_debug("using bounce buffer for addr=0x%02x, len=%d\n", | ||
2223 | msg->addr, msg->len); | ||
2224 | |||
2225 | if (msg->flags & I2C_M_RD) | ||
2226 | return kzalloc(msg->len, GFP_KERNEL); | ||
2227 | else | ||
2228 | return kmemdup(msg->buf, msg->len, GFP_KERNEL); | ||
2229 | } | ||
2230 | EXPORT_SYMBOL_GPL(i2c_get_dma_safe_msg_buf); | ||
2231 | |||
2232 | /** | ||
2233 | * i2c_release_dma_safe_msg_buf - release DMA safe buffer and sync with i2c_msg | ||
2234 | * @msg: the message to be synced with | ||
2235 | * @buf: the buffer obtained from i2c_get_dma_safe_msg_buf(). May be NULL. | ||
2236 | */ | ||
2237 | void i2c_release_dma_safe_msg_buf(struct i2c_msg *msg, u8 *buf) | ||
2238 | { | ||
2239 | if (!buf || buf == msg->buf) | ||
2240 | return; | ||
2241 | |||
2242 | if (msg->flags & I2C_M_RD) | ||
2243 | memcpy(msg->buf, buf, msg->len); | ||
2244 | |||
2245 | kfree(buf); | ||
2246 | } | ||
2247 | EXPORT_SYMBOL_GPL(i2c_release_dma_safe_msg_buf); | ||
2248 | |||
2203 | MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); | 2249 | MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); |
2204 | MODULE_DESCRIPTION("I2C-Bus main module"); | 2250 | MODULE_DESCRIPTION("I2C-Bus main module"); |
2205 | MODULE_LICENSE("GPL"); | 2251 | MODULE_LICENSE("GPL"); |
diff --git a/include/linux/i2c.h b/include/linux/i2c.h index a556db976fc6..9d9d379b5a15 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h | |||
@@ -768,6 +768,9 @@ static inline u8 i2c_8bit_addr_from_msg(const struct i2c_msg *msg) | |||
768 | return (msg->addr << 1) | (msg->flags & I2C_M_RD ? 1 : 0); | 768 | return (msg->addr << 1) | (msg->flags & I2C_M_RD ? 1 : 0); |
769 | } | 769 | } |
770 | 770 | ||
771 | u8 *i2c_get_dma_safe_msg_buf(struct i2c_msg *msg, unsigned int threshold); | ||
772 | void i2c_release_dma_safe_msg_buf(struct i2c_msg *msg, u8 *buf); | ||
773 | |||
771 | int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr); | 774 | int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr); |
772 | /** | 775 | /** |
773 | * module_i2c_driver() - Helper macro for registering a modular I2C driver | 776 | * module_i2c_driver() - Helper macro for registering a modular I2C driver |