comedi_buf.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * comedi_buf.c
  4. *
  5. * COMEDI - Linux Control and Measurement Device Interface
  6. * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
  7. * Copyright (C) 2002 Frank Mori Hess <fmhess@users.sourceforge.net>
  8. */
  9. #include <linux/vmalloc.h>
  10. #include <linux/slab.h>
  11. #include "comedidev.h"
  12. #include "comedi_internal.h"
  13. #ifdef PAGE_KERNEL_NOCACHE
  14. #define COMEDI_PAGE_PROTECTION PAGE_KERNEL_NOCACHE
  15. #else
  16. #define COMEDI_PAGE_PROTECTION PAGE_KERNEL
  17. #endif
  18. static void comedi_buf_map_kref_release(struct kref *kref)
  19. {
  20. struct comedi_buf_map *bm =
  21. container_of(kref, struct comedi_buf_map, refcount);
  22. struct comedi_buf_page *buf;
  23. unsigned int i;
  24. if (bm->page_list) {
  25. if (bm->dma_dir != DMA_NONE) {
  26. /*
  27. * DMA buffer was allocated as a single block.
  28. * Address is in page_list[0].
  29. */
  30. buf = &bm->page_list[0];
  31. dma_free_coherent(bm->dma_hw_dev,
  32. PAGE_SIZE * bm->n_pages,
  33. buf->virt_addr, buf->dma_addr);
  34. } else {
  35. for (i = 0; i < bm->n_pages; i++) {
  36. buf = &bm->page_list[i];
  37. ClearPageReserved(virt_to_page(buf->virt_addr));
  38. free_page((unsigned long)buf->virt_addr);
  39. }
  40. }
  41. vfree(bm->page_list);
  42. }
  43. if (bm->dma_dir != DMA_NONE)
  44. put_device(bm->dma_hw_dev);
  45. kfree(bm);
  46. }
  47. static void __comedi_buf_free(struct comedi_device *dev,
  48. struct comedi_subdevice *s)
  49. {
  50. struct comedi_async *async = s->async;
  51. struct comedi_buf_map *bm;
  52. unsigned long flags;
  53. if (async->prealloc_buf) {
  54. if (s->async_dma_dir == DMA_NONE)
  55. vunmap(async->prealloc_buf);
  56. async->prealloc_buf = NULL;
  57. async->prealloc_bufsz = 0;
  58. }
  59. spin_lock_irqsave(&s->spin_lock, flags);
  60. bm = async->buf_map;
  61. async->buf_map = NULL;
  62. spin_unlock_irqrestore(&s->spin_lock, flags);
  63. comedi_buf_map_put(bm);
  64. }
  65. static struct comedi_buf_map *
  66. comedi_buf_map_alloc(struct comedi_device *dev, enum dma_data_direction dma_dir,
  67. unsigned int n_pages)
  68. {
  69. struct comedi_buf_map *bm;
  70. struct comedi_buf_page *buf;
  71. unsigned int i;
  72. bm = kzalloc(sizeof(*bm), GFP_KERNEL);
  73. if (!bm)
  74. return NULL;
  75. kref_init(&bm->refcount);
  76. bm->dma_dir = dma_dir;
  77. if (bm->dma_dir != DMA_NONE) {
  78. /* Need ref to hardware device to free buffer later. */
  79. bm->dma_hw_dev = get_device(dev->hw_dev);
  80. }
  81. bm->page_list = vzalloc(sizeof(*buf) * n_pages);
  82. if (!bm->page_list)
  83. goto err;
  84. if (bm->dma_dir != DMA_NONE) {
  85. void *virt_addr;
  86. dma_addr_t dma_addr;
  87. /*
  88. * Currently, the DMA buffer needs to be allocated as a
  89. * single block so that it can be mmap()'ed.
  90. */
  91. virt_addr = dma_alloc_coherent(bm->dma_hw_dev,
  92. PAGE_SIZE * n_pages, &dma_addr,
  93. GFP_KERNEL);
  94. if (!virt_addr)
  95. goto err;
  96. for (i = 0; i < n_pages; i++) {
  97. buf = &bm->page_list[i];
  98. buf->virt_addr = virt_addr + (i << PAGE_SHIFT);
  99. buf->dma_addr = dma_addr + (i << PAGE_SHIFT);
  100. }
  101. bm->n_pages = i;
  102. } else {
  103. for (i = 0; i < n_pages; i++) {
  104. buf = &bm->page_list[i];
  105. buf->virt_addr = (void *)get_zeroed_page(GFP_KERNEL);
  106. if (!buf->virt_addr)
  107. break;
  108. SetPageReserved(virt_to_page(buf->virt_addr));
  109. }
  110. bm->n_pages = i;
  111. if (i < n_pages)
  112. goto err;
  113. }
  114. return bm;
  115. err:
  116. comedi_buf_map_put(bm);
  117. return NULL;
  118. }
  119. static void __comedi_buf_alloc(struct comedi_device *dev,
  120. struct comedi_subdevice *s,
  121. unsigned int n_pages)
  122. {
  123. struct comedi_async *async = s->async;
  124. struct page **pages = NULL;
  125. struct comedi_buf_map *bm;
  126. struct comedi_buf_page *buf;
  127. unsigned long flags;
  128. unsigned int i;
  129. if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir != DMA_NONE) {
  130. dev_err(dev->class_dev,
  131. "dma buffer allocation not supported\n");
  132. return;
  133. }
  134. bm = comedi_buf_map_alloc(dev, s->async_dma_dir, n_pages);
  135. if (!bm)
  136. return;
  137. spin_lock_irqsave(&s->spin_lock, flags);
  138. async->buf_map = bm;
  139. spin_unlock_irqrestore(&s->spin_lock, flags);
  140. if (bm->dma_dir != DMA_NONE) {
  141. /*
  142. * DMA buffer was allocated as a single block.
  143. * Address is in page_list[0].
  144. */
  145. buf = &bm->page_list[0];
  146. async->prealloc_buf = buf->virt_addr;
  147. } else {
  148. pages = vmalloc(sizeof(struct page *) * n_pages);
  149. if (!pages)
  150. return;
  151. for (i = 0; i < n_pages; i++) {
  152. buf = &bm->page_list[i];
  153. pages[i] = virt_to_page(buf->virt_addr);
  154. }
  155. /* vmap the pages to prealloc_buf */
  156. async->prealloc_buf = vmap(pages, n_pages, VM_MAP,
  157. COMEDI_PAGE_PROTECTION);
  158. vfree(pages);
  159. }
  160. }
  161. void comedi_buf_map_get(struct comedi_buf_map *bm)
  162. {
  163. if (bm)
  164. kref_get(&bm->refcount);
  165. }
  166. int comedi_buf_map_put(struct comedi_buf_map *bm)
  167. {
  168. if (bm)
  169. return kref_put(&bm->refcount, comedi_buf_map_kref_release);
  170. return 1;
  171. }
  172. /* helper for "access" vm operation */
  173. int comedi_buf_map_access(struct comedi_buf_map *bm, unsigned long offset,
  174. void *buf, int len, int write)
  175. {
  176. unsigned int pgoff = offset_in_page(offset);
  177. unsigned long pg = offset >> PAGE_SHIFT;
  178. int done = 0;
  179. while (done < len && pg < bm->n_pages) {
  180. int l = min_t(int, len - done, PAGE_SIZE - pgoff);
  181. void *b = bm->page_list[pg].virt_addr + pgoff;
  182. if (write)
  183. memcpy(b, buf, l);
  184. else
  185. memcpy(buf, b, l);
  186. buf += l;
  187. done += l;
  188. pg++;
  189. pgoff = 0;
  190. }
  191. return done;
  192. }
  193. /* returns s->async->buf_map and increments its kref refcount */
  194. struct comedi_buf_map *
  195. comedi_buf_map_from_subdev_get(struct comedi_subdevice *s)
  196. {
  197. struct comedi_async *async = s->async;
  198. struct comedi_buf_map *bm = NULL;
  199. unsigned long flags;
  200. if (!async)
  201. return NULL;
  202. spin_lock_irqsave(&s->spin_lock, flags);
  203. bm = async->buf_map;
  204. /* only want it if buffer pages allocated */
  205. if (bm && bm->n_pages)
  206. comedi_buf_map_get(bm);
  207. else
  208. bm = NULL;
  209. spin_unlock_irqrestore(&s->spin_lock, flags);
  210. return bm;
  211. }
  212. bool comedi_buf_is_mmapped(struct comedi_subdevice *s)
  213. {
  214. struct comedi_buf_map *bm = s->async->buf_map;
  215. return bm && (kref_read(&bm->refcount) > 1);
  216. }
  217. int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
  218. unsigned long new_size)
  219. {
  220. struct comedi_async *async = s->async;
  221. lockdep_assert_held(&dev->mutex);
  222. /* Round up new_size to multiple of PAGE_SIZE */
  223. new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
  224. /* if no change is required, do nothing */
  225. if (async->prealloc_buf && async->prealloc_bufsz == new_size)
  226. return 0;
  227. /* deallocate old buffer */
  228. __comedi_buf_free(dev, s);
  229. /* allocate new buffer */
  230. if (new_size) {
  231. unsigned int n_pages = new_size >> PAGE_SHIFT;
  232. __comedi_buf_alloc(dev, s, n_pages);
  233. if (!async->prealloc_buf) {
  234. /* allocation failed */
  235. __comedi_buf_free(dev, s);
  236. return -ENOMEM;
  237. }
  238. }
  239. async->prealloc_bufsz = new_size;
  240. return 0;
  241. }
  242. void comedi_buf_reset(struct comedi_subdevice *s)
  243. {
  244. struct comedi_async *async = s->async;
  245. async->buf_write_alloc_count = 0;
  246. async->buf_write_count = 0;
  247. async->buf_read_alloc_count = 0;
  248. async->buf_read_count = 0;
  249. async->buf_write_ptr = 0;
  250. async->buf_read_ptr = 0;
  251. async->cur_chan = 0;
  252. async->scans_done = 0;
  253. async->scan_progress = 0;
  254. async->munge_chan = 0;
  255. async->munge_count = 0;
  256. async->munge_ptr = 0;
  257. async->events = 0;
  258. }
  259. static unsigned int comedi_buf_write_n_unalloc(struct comedi_subdevice *s)
  260. {
  261. struct comedi_async *async = s->async;
  262. unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
  263. return free_end - async->buf_write_alloc_count;
  264. }
  265. unsigned int comedi_buf_write_n_available(struct comedi_subdevice *s)
  266. {
  267. struct comedi_async *async = s->async;
  268. unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
  269. return free_end - async->buf_write_count;
  270. }
  271. /**
  272. * comedi_buf_write_alloc() - Reserve buffer space for writing
  273. * @s: COMEDI subdevice.
  274. * @nbytes: Maximum space to reserve in bytes.
  275. *
  276. * Reserve up to @nbytes bytes of space to be written in the COMEDI acquisition
  277. * data buffer associated with the subdevice. The amount reserved is limited
  278. * by the space available.
  279. *
  280. * Return: The amount of space reserved in bytes.
  281. */
  282. unsigned int comedi_buf_write_alloc(struct comedi_subdevice *s,
  283. unsigned int nbytes)
  284. {
  285. struct comedi_async *async = s->async;
  286. unsigned int unalloc = comedi_buf_write_n_unalloc(s);
  287. if (nbytes > unalloc)
  288. nbytes = unalloc;
  289. async->buf_write_alloc_count += nbytes;
  290. /*
  291. * ensure the async buffer 'counts' are read and updated
  292. * before we write data to the write-alloc'ed buffer space
  293. */
  294. smp_mb();
  295. return nbytes;
  296. }
  297. EXPORT_SYMBOL_GPL(comedi_buf_write_alloc);
  298. /*
  299. * munging is applied to data by core as it passes between user
  300. * and kernel space
  301. */
  302. static unsigned int comedi_buf_munge(struct comedi_subdevice *s,
  303. unsigned int num_bytes)
  304. {
  305. struct comedi_async *async = s->async;
  306. unsigned int count = 0;
  307. const unsigned int num_sample_bytes = comedi_bytes_per_sample(s);
  308. if (!s->munge || (async->cmd.flags & CMDF_RAWDATA)) {
  309. async->munge_count += num_bytes;
  310. count = num_bytes;
  311. } else {
  312. /* don't munge partial samples */
  313. num_bytes -= num_bytes % num_sample_bytes;
  314. while (count < num_bytes) {
  315. int block_size = num_bytes - count;
  316. unsigned int buf_end;
  317. buf_end = async->prealloc_bufsz - async->munge_ptr;
  318. if (block_size > buf_end)
  319. block_size = buf_end;
  320. s->munge(s->device, s,
  321. async->prealloc_buf + async->munge_ptr,
  322. block_size, async->munge_chan);
  323. /*
  324. * ensure data is munged in buffer before the
  325. * async buffer munge_count is incremented
  326. */
  327. smp_wmb();
  328. async->munge_chan += block_size / num_sample_bytes;
  329. async->munge_chan %= async->cmd.chanlist_len;
  330. async->munge_count += block_size;
  331. async->munge_ptr += block_size;
  332. async->munge_ptr %= async->prealloc_bufsz;
  333. count += block_size;
  334. }
  335. }
  336. return count;
  337. }
  338. unsigned int comedi_buf_write_n_allocated(struct comedi_subdevice *s)
  339. {
  340. struct comedi_async *async = s->async;
  341. return async->buf_write_alloc_count - async->buf_write_count;
  342. }
  343. /**
  344. * comedi_buf_write_free() - Free buffer space after it is written
  345. * @s: COMEDI subdevice.
  346. * @nbytes: Maximum space to free in bytes.
  347. *
  348. * Free up to @nbytes bytes of space previously reserved for writing in the
  349. * COMEDI acquisition data buffer associated with the subdevice. The amount of
  350. * space freed is limited to the amount that was reserved. The freed space is
  351. * assumed to have been filled with sample data by the writer.
  352. *
  353. * If the samples in the freed space need to be "munged", do so here. The
  354. * freed space becomes available for allocation by the reader.
  355. *
  356. * Return: The amount of space freed in bytes.
  357. */
  358. unsigned int comedi_buf_write_free(struct comedi_subdevice *s,
  359. unsigned int nbytes)
  360. {
  361. struct comedi_async *async = s->async;
  362. unsigned int allocated = comedi_buf_write_n_allocated(s);
  363. if (nbytes > allocated)
  364. nbytes = allocated;
  365. async->buf_write_count += nbytes;
  366. async->buf_write_ptr += nbytes;
  367. comedi_buf_munge(s, async->buf_write_count - async->munge_count);
  368. if (async->buf_write_ptr >= async->prealloc_bufsz)
  369. async->buf_write_ptr %= async->prealloc_bufsz;
  370. return nbytes;
  371. }
  372. EXPORT_SYMBOL_GPL(comedi_buf_write_free);
  373. /**
  374. * comedi_buf_read_n_available() - Determine amount of readable buffer space
  375. * @s: COMEDI subdevice.
  376. *
  377. * Determine the amount of readable buffer space in the COMEDI acquisition data
  378. * buffer associated with the subdevice. The readable buffer space is that
  379. * which has been freed by the writer and "munged" to the sample data format
  380. * expected by COMEDI if necessary.
  381. *
  382. * Return: The amount of readable buffer space.
  383. */
  384. unsigned int comedi_buf_read_n_available(struct comedi_subdevice *s)
  385. {
  386. struct comedi_async *async = s->async;
  387. unsigned int num_bytes;
  388. if (!async)
  389. return 0;
  390. num_bytes = async->munge_count - async->buf_read_count;
  391. /*
  392. * ensure the async buffer 'counts' are read before we
  393. * attempt to read data from the buffer
  394. */
  395. smp_rmb();
  396. return num_bytes;
  397. }
  398. EXPORT_SYMBOL_GPL(comedi_buf_read_n_available);
  399. /**
  400. * comedi_buf_read_alloc() - Reserve buffer space for reading
  401. * @s: COMEDI subdevice.
  402. * @nbytes: Maximum space to reserve in bytes.
  403. *
  404. * Reserve up to @nbytes bytes of previously written and "munged" buffer space
  405. * for reading in the COMEDI acquisition data buffer associated with the
  406. * subdevice. The amount reserved is limited to the space available. The
  407. * reader can read from the reserved space and then free it. A reader is also
  408. * allowed to read from the space before reserving it as long as it determines
  409. * the amount of readable data available, but the space needs to be marked as
  410. * reserved before it can be freed.
  411. *
  412. * Return: The amount of space reserved in bytes.
  413. */
  414. unsigned int comedi_buf_read_alloc(struct comedi_subdevice *s,
  415. unsigned int nbytes)
  416. {
  417. struct comedi_async *async = s->async;
  418. unsigned int available;
  419. available = async->munge_count - async->buf_read_alloc_count;
  420. if (nbytes > available)
  421. nbytes = available;
  422. async->buf_read_alloc_count += nbytes;
  423. /*
  424. * ensure the async buffer 'counts' are read before we
  425. * attempt to read data from the read-alloc'ed buffer space
  426. */
  427. smp_rmb();
  428. return nbytes;
  429. }
  430. EXPORT_SYMBOL_GPL(comedi_buf_read_alloc);
  431. static unsigned int comedi_buf_read_n_allocated(struct comedi_async *async)
  432. {
  433. return async->buf_read_alloc_count - async->buf_read_count;
  434. }
  435. /**
  436. * comedi_buf_read_free() - Free buffer space after it has been read
  437. * @s: COMEDI subdevice.
  438. * @nbytes: Maximum space to free in bytes.
  439. *
  440. * Free up to @nbytes bytes of buffer space previously reserved for reading in
  441. * the COMEDI acquisition data buffer associated with the subdevice. The
  442. * amount of space freed is limited to the amount that was reserved.
  443. *
  444. * The freed space becomes available for allocation by the writer.
  445. *
  446. * Return: The amount of space freed in bytes.
  447. */
  448. unsigned int comedi_buf_read_free(struct comedi_subdevice *s,
  449. unsigned int nbytes)
  450. {
  451. struct comedi_async *async = s->async;
  452. unsigned int allocated;
  453. /*
  454. * ensure data has been read out of buffer before
  455. * the async read count is incremented
  456. */
  457. smp_mb();
  458. allocated = comedi_buf_read_n_allocated(async);
  459. if (nbytes > allocated)
  460. nbytes = allocated;
  461. async->buf_read_count += nbytes;
  462. async->buf_read_ptr += nbytes;
  463. async->buf_read_ptr %= async->prealloc_bufsz;
  464. return nbytes;
  465. }
  466. EXPORT_SYMBOL_GPL(comedi_buf_read_free);
  467. static void comedi_buf_memcpy_to(struct comedi_subdevice *s,
  468. const void *data, unsigned int num_bytes)
  469. {
  470. struct comedi_async *async = s->async;
  471. unsigned int write_ptr = async->buf_write_ptr;
  472. while (num_bytes) {
  473. unsigned int block_size;
  474. if (write_ptr + num_bytes > async->prealloc_bufsz)
  475. block_size = async->prealloc_bufsz - write_ptr;
  476. else
  477. block_size = num_bytes;
  478. memcpy(async->prealloc_buf + write_ptr, data, block_size);
  479. data += block_size;
  480. num_bytes -= block_size;
  481. write_ptr = 0;
  482. }
  483. }
  484. static void comedi_buf_memcpy_from(struct comedi_subdevice *s,
  485. void *dest, unsigned int nbytes)
  486. {
  487. void *src;
  488. struct comedi_async *async = s->async;
  489. unsigned int read_ptr = async->buf_read_ptr;
  490. while (nbytes) {
  491. unsigned int block_size;
  492. src = async->prealloc_buf + read_ptr;
  493. if (nbytes >= async->prealloc_bufsz - read_ptr)
  494. block_size = async->prealloc_bufsz - read_ptr;
  495. else
  496. block_size = nbytes;
  497. memcpy(dest, src, block_size);
  498. nbytes -= block_size;
  499. dest += block_size;
  500. read_ptr = 0;
  501. }
  502. }
  503. /**
  504. * comedi_buf_write_samples() - Write sample data to COMEDI buffer
  505. * @s: COMEDI subdevice.
  506. * @data: Pointer to source samples.
  507. * @nsamples: Number of samples to write.
  508. *
  509. * Write up to @nsamples samples to the COMEDI acquisition data buffer
  510. * associated with the subdevice, mark it as written and update the
  511. * acquisition scan progress. If there is not enough room for the specified
  512. * number of samples, the number of samples written is limited to the number
  513. * that will fit and the %COMEDI_CB_OVERFLOW event flag is set to cause the
  514. * acquisition to terminate with an overrun error. Set the %COMEDI_CB_BLOCK
  515. * event flag if any samples are written to cause waiting tasks to be woken
  516. * when the event flags are processed.
  517. *
  518. * Return: The amount of data written in bytes.
  519. */
  520. unsigned int comedi_buf_write_samples(struct comedi_subdevice *s,
  521. const void *data, unsigned int nsamples)
  522. {
  523. unsigned int max_samples;
  524. unsigned int nbytes;
  525. /*
  526. * Make sure there is enough room in the buffer for all the samples.
  527. * If not, clamp the nsamples to the number that will fit, flag the
  528. * buffer overrun and add the samples that fit.
  529. */
  530. max_samples = comedi_bytes_to_samples(s, comedi_buf_write_n_unalloc(s));
  531. if (nsamples > max_samples) {
  532. dev_warn(s->device->class_dev, "buffer overrun\n");
  533. s->async->events |= COMEDI_CB_OVERFLOW;
  534. nsamples = max_samples;
  535. }
  536. if (nsamples == 0)
  537. return 0;
  538. nbytes = comedi_buf_write_alloc(s,
  539. comedi_samples_to_bytes(s, nsamples));
  540. comedi_buf_memcpy_to(s, data, nbytes);
  541. comedi_buf_write_free(s, nbytes);
  542. comedi_inc_scan_progress(s, nbytes);
  543. s->async->events |= COMEDI_CB_BLOCK;
  544. return nbytes;
  545. }
  546. EXPORT_SYMBOL_GPL(comedi_buf_write_samples);
  547. /**
  548. * comedi_buf_read_samples() - Read sample data from COMEDI buffer
  549. * @s: COMEDI subdevice.
  550. * @data: Pointer to destination.
  551. * @nsamples: Maximum number of samples to read.
  552. *
  553. * Read up to @nsamples samples from the COMEDI acquisition data buffer
  554. * associated with the subdevice, mark it as read and update the acquisition
  555. * scan progress. Limit the number of samples read to the number available.
  556. * Set the %COMEDI_CB_BLOCK event flag if any samples are read to cause waiting
  557. * tasks to be woken when the event flags are processed.
  558. *
  559. * Return: The amount of data read in bytes.
  560. */
  561. unsigned int comedi_buf_read_samples(struct comedi_subdevice *s,
  562. void *data, unsigned int nsamples)
  563. {
  564. unsigned int max_samples;
  565. unsigned int nbytes;
  566. /* clamp nsamples to the number of full samples available */
  567. max_samples = comedi_bytes_to_samples(s,
  568. comedi_buf_read_n_available(s));
  569. if (nsamples > max_samples)
  570. nsamples = max_samples;
  571. if (nsamples == 0)
  572. return 0;
  573. nbytes = comedi_buf_read_alloc(s,
  574. comedi_samples_to_bytes(s, nsamples));
  575. comedi_buf_memcpy_from(s, data, nbytes);
  576. comedi_buf_read_free(s, nbytes);
  577. comedi_inc_scan_progress(s, nbytes);
  578. s->async->events |= COMEDI_CB_BLOCK;
  579. return nbytes;
  580. }
  581. EXPORT_SYMBOL_GPL(comedi_buf_read_samples);