Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: buffer-dmaengine: split requesting DMA channel from allocating buffer

Refactor the IIO dmaengine buffer code to split requesting the DMA
channel from allocating the buffer. We want to be able to add a new
function where the IIO device driver manages the DMA channel, so these
two actions need to be separate.

To do this, calling dma_request_chan() is moved from
iio_dmaengine_buffer_alloc() to iio_dmaengine_buffer_setup_ext(). A new
__iio_dmaengine_buffer_setup_ext() helper function is added to simplify
error unwinding and will also be used by a new function in a later
patch.

iio_dmaengine_buffer_free() now only frees the buffer and does not
release the DMA channel. A new iio_dmaengine_buffer_teardown() function
is added to unwind everything done in iio_dmaengine_buffer_setup_ext().
This keeps things more symmetrical with obvious pairs alloc/free and
setup/teardown.

Calling dma_get_slave_caps() in iio_dmaengine_buffer_alloc() is moved so
that we can avoid any gotos for error unwinding.

Reviewed-by: Nuno Sa <nuno.sa@analog.com>
Signed-off-by: David Lechner <dlechner@baylibre.com>
Link: https://patch.msgid.link/20250207-dlech-mainline-spi-engine-offload-2-v8-8-e48a489be48c@baylibre.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

David Lechner and committed by
Jonathan Cameron
4fe7fd17 a570114d

+68 -50
+1 -1
drivers/iio/adc/adi-axi-adc.c
··· 305 305 static void axi_adc_free_buffer(struct iio_backend *back, 306 306 struct iio_buffer *buffer) 307 307 { 308 - iio_dmaengine_buffer_free(buffer); 308 + iio_dmaengine_buffer_teardown(buffer); 309 309 } 310 310 311 311 static int axi_adc_reg_access(struct iio_backend *back, unsigned int reg,
+65 -47
drivers/iio/buffer/industrialio-buffer-dmaengine.c
··· 206 206 207 207 /** 208 208 * iio_dmaengine_buffer_alloc() - Allocate new buffer which uses DMAengine 209 - * @dev: DMA channel consumer device 210 - * @channel: DMA channel name, typically "rx". 209 + * @chan: DMA channel. 211 210 * 212 211 * This allocates a new IIO buffer which internally uses the DMAengine framework 213 - * to perform its transfers. The parent device will be used to request the DMA 214 - * channel. 212 + * to perform its transfers. 215 213 * 216 214 * Once done using the buffer iio_dmaengine_buffer_free() should be used to 217 215 * release it. 218 216 */ 219 - static struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev, 220 - const char *channel) 217 + static struct iio_buffer *iio_dmaengine_buffer_alloc(struct dma_chan *chan) 221 218 { 222 219 struct dmaengine_buffer *dmaengine_buffer; 223 220 unsigned int width, src_width, dest_width; 224 221 struct dma_slave_caps caps; 225 - struct dma_chan *chan; 226 222 int ret; 223 + 224 + ret = dma_get_slave_caps(chan, &caps); 225 + if (ret < 0) 226 + return ERR_PTR(ret); 227 227 228 228 dmaengine_buffer = kzalloc(sizeof(*dmaengine_buffer), GFP_KERNEL); 229 229 if (!dmaengine_buffer) 230 230 return ERR_PTR(-ENOMEM); 231 - 232 - chan = dma_request_chan(dev, channel); 233 - if (IS_ERR(chan)) { 234 - ret = PTR_ERR(chan); 235 - goto err_free; 236 - } 237 - 238 - ret = dma_get_slave_caps(chan, &caps); 239 - if (ret < 0) 240 - goto err_release; 241 231 242 232 /* Needs to be aligned to the maximum of the minimums */ 243 233 if (caps.src_addr_widths) ··· 252 262 dmaengine_buffer->queue.buffer.access = &iio_dmaengine_buffer_ops; 253 263 254 264 return &dmaengine_buffer->queue.buffer; 255 - 256 - err_release: 257 - dma_release_channel(chan); 258 - err_free: 259 - kfree(dmaengine_buffer); 260 - return ERR_PTR(ret); 261 265 } 262 266 263 267 /** ··· 260 276 * 261 277 * Frees a buffer previously allocated with iio_dmaengine_buffer_alloc(). 262 278 */ 263 - void iio_dmaengine_buffer_free(struct iio_buffer *buffer) 279 + static void iio_dmaengine_buffer_free(struct iio_buffer *buffer) 264 280 { 265 281 struct dmaengine_buffer *dmaengine_buffer = 266 282 iio_buffer_to_dmaengine_buffer(buffer); 267 283 268 284 iio_dma_buffer_exit(&dmaengine_buffer->queue); 269 - dma_release_channel(dmaengine_buffer->chan); 270 - 271 285 iio_buffer_put(buffer); 272 286 } 273 - EXPORT_SYMBOL_NS_GPL(iio_dmaengine_buffer_free, "IIO_DMAENGINE_BUFFER"); 274 287 275 288 /** 276 - * iio_dmaengine_buffer_setup_ext() - Setup a DMA buffer for an IIO device 277 - * @dev: DMA channel consumer device 278 - * @indio_dev: IIO device to which to attach this buffer. 279 - * @channel: DMA channel name, typically "rx". 280 - * @dir: Direction of buffer (in or out) 289 + * iio_dmaengine_buffer_teardown() - Releases DMA channel and frees buffer 290 + * @buffer: Buffer to free 281 291 * 282 - * This allocates a new IIO buffer with devm_iio_dmaengine_buffer_alloc() 283 - * and attaches it to an IIO device with iio_device_attach_buffer(). 284 - * It also appends the INDIO_BUFFER_HARDWARE mode to the supported modes of the 285 - * IIO device. 286 - * 287 - * Once done using the buffer iio_dmaengine_buffer_free() should be used to 288 - * release it. 292 + * Releases the DMA channel and frees the buffer previously setup with 293 + * iio_dmaengine_buffer_setup_ext(). 289 294 */ 290 - struct iio_buffer *iio_dmaengine_buffer_setup_ext(struct device *dev, 291 - struct iio_dev *indio_dev, 292 - const char *channel, 293 - enum iio_buffer_direction dir) 295 + void iio_dmaengine_buffer_teardown(struct iio_buffer *buffer) 296 + { 297 + struct dmaengine_buffer *dmaengine_buffer = 298 + iio_buffer_to_dmaengine_buffer(buffer); 299 + struct dma_chan *chan = dmaengine_buffer->chan; 300 + 301 + iio_dmaengine_buffer_free(buffer); 302 + dma_release_channel(chan); 303 + } 304 + EXPORT_SYMBOL_NS_GPL(iio_dmaengine_buffer_teardown, "IIO_DMAENGINE_BUFFER"); 305 + 306 + static struct iio_buffer 307 + *__iio_dmaengine_buffer_setup_ext(struct iio_dev *indio_dev, 308 + struct dma_chan *chan, 309 + enum iio_buffer_direction dir) 294 310 { 295 311 struct iio_buffer *buffer; 296 312 int ret; 297 313 298 - buffer = iio_dmaengine_buffer_alloc(dev, channel); 314 + buffer = iio_dmaengine_buffer_alloc(chan); 299 315 if (IS_ERR(buffer)) 300 316 return ERR_CAST(buffer); 301 317 ··· 311 327 312 328 return buffer; 313 329 } 330 + 331 + /** 332 + * iio_dmaengine_buffer_setup_ext() - Setup a DMA buffer for an IIO device 333 + * @dev: DMA channel consumer device 334 + * @indio_dev: IIO device to which to attach this buffer. 335 + * @channel: DMA channel name, typically "rx". 336 + * @dir: Direction of buffer (in or out) 337 + * 338 + * This allocates a new IIO buffer with devm_iio_dmaengine_buffer_alloc() 339 + * and attaches it to an IIO device with iio_device_attach_buffer(). 340 + * It also appends the INDIO_BUFFER_HARDWARE mode to the supported modes of the 341 + * IIO device. 342 + * 343 + * Once done using the buffer iio_dmaengine_buffer_teardown() should be used to 344 + * release it. 345 + */ 346 + struct iio_buffer *iio_dmaengine_buffer_setup_ext(struct device *dev, 347 + struct iio_dev *indio_dev, 348 + const char *channel, 349 + enum iio_buffer_direction dir) 350 + { 351 + struct dma_chan *chan; 352 + struct iio_buffer *buffer; 353 + 354 + chan = dma_request_chan(dev, channel); 355 + if (IS_ERR(chan)) 356 + return ERR_CAST(chan); 357 + 358 + buffer = __iio_dmaengine_buffer_setup_ext(indio_dev, chan, dir); 359 + if (IS_ERR(buffer)) 360 + dma_release_channel(chan); 361 + 362 + return buffer; 363 + } 314 364 EXPORT_SYMBOL_NS_GPL(iio_dmaengine_buffer_setup_ext, "IIO_DMAENGINE_BUFFER"); 315 365 316 - static void __devm_iio_dmaengine_buffer_free(void *buffer) 366 + static void devm_iio_dmaengine_buffer_teardown(void *buffer) 317 367 { 318 - iio_dmaengine_buffer_free(buffer); 368 + iio_dmaengine_buffer_teardown(buffer); 319 369 } 320 370 321 371 /** ··· 375 357 if (IS_ERR(buffer)) 376 358 return PTR_ERR(buffer); 377 359 378 - return devm_add_action_or_reset(dev, __devm_iio_dmaengine_buffer_free, 360 + return devm_add_action_or_reset(dev, devm_iio_dmaengine_buffer_teardown, 379 361 buffer); 380 362 } 381 363 EXPORT_SYMBOL_NS_GPL(devm_iio_dmaengine_buffer_setup_ext, "IIO_DMAENGINE_BUFFER");
+1 -1
drivers/iio/dac/adi-axi-dac.c
··· 168 168 static void axi_dac_free_buffer(struct iio_backend *back, 169 169 struct iio_buffer *buffer) 170 170 { 171 - iio_dmaengine_buffer_free(buffer); 171 + iio_dmaengine_buffer_teardown(buffer); 172 172 } 173 173 174 174 enum {
+1 -1
include/linux/iio/buffer-dmaengine.h
··· 12 12 struct iio_dev; 13 13 struct device; 14 14 15 - void iio_dmaengine_buffer_free(struct iio_buffer *buffer); 15 + void iio_dmaengine_buffer_teardown(struct iio_buffer *buffer); 16 16 struct iio_buffer *iio_dmaengine_buffer_setup_ext(struct device *dev, 17 17 struct iio_dev *indio_dev, 18 18 const char *channel,