aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/comedi/comedi_fops.c659
1 files changed, 294 insertions, 365 deletions
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 06fc6569c859..44ca1feebe24 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -129,15 +129,295 @@ static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
129static int comedi_fasync(int fd, struct file *file, int on); 129static int comedi_fasync(int fd, struct file *file, int on);
130 130
131static int is_device_busy(struct comedi_device *dev); 131static int is_device_busy(struct comedi_device *dev);
132
132static int resize_async_buffer(struct comedi_device *dev, 133static int resize_async_buffer(struct comedi_device *dev,
133 struct comedi_subdevice *s, 134 struct comedi_subdevice *s,
134 struct comedi_async *async, unsigned new_size); 135 struct comedi_async *async, unsigned new_size)
136{
137 int retval;
138
139 if (new_size > async->max_bufsize)
140 return -EPERM;
141
142 if (s->busy) {
143 DPRINTK("subdevice is busy, cannot resize buffer\n");
144 return -EBUSY;
145 }
146 if (async->mmap_count) {
147 DPRINTK("subdevice is mmapped, cannot resize buffer\n");
148 return -EBUSY;
149 }
150
151 if (!async->prealloc_buf)
152 return -EINVAL;
135 153
136/* declarations for sysfs attribute files */ 154 /* make sure buffer is an integral number of pages
137static struct device_attribute dev_attr_max_read_buffer_kb; 155 * (we round up) */
138static struct device_attribute dev_attr_read_buffer_kb; 156 new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
139static struct device_attribute dev_attr_max_write_buffer_kb; 157
140static struct device_attribute dev_attr_write_buffer_kb; 158 retval = comedi_buf_alloc(dev, s, new_size);
159 if (retval < 0)
160 return retval;
161
162 if (s->buf_change) {
163 retval = s->buf_change(dev, s, new_size);
164 if (retval < 0)
165 return retval;
166 }
167
168 DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
169 dev->minor, (int)(s - dev->subdevices), async->prealloc_bufsz);
170 return 0;
171}
172
173/* sysfs attribute files */
174
175static const unsigned bytes_per_kibi = 1024;
176
177static ssize_t show_max_read_buffer_kb(struct device *dev,
178 struct device_attribute *attr, char *buf)
179{
180 ssize_t retval;
181 struct comedi_device_file_info *info = dev_get_drvdata(dev);
182 unsigned max_buffer_size_kb = 0;
183 struct comedi_subdevice *const read_subdevice =
184 comedi_get_read_subdevice(info);
185
186 mutex_lock(&info->device->mutex);
187 if (read_subdevice &&
188 (read_subdevice->subdev_flags & SDF_CMD_READ) &&
189 read_subdevice->async) {
190 max_buffer_size_kb = read_subdevice->async->max_bufsize /
191 bytes_per_kibi;
192 }
193 retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb);
194 mutex_unlock(&info->device->mutex);
195
196 return retval;
197}
198
199static ssize_t store_max_read_buffer_kb(struct device *dev,
200 struct device_attribute *attr,
201 const char *buf, size_t count)
202{
203 struct comedi_device_file_info *info = dev_get_drvdata(dev);
204 unsigned int new_max_size_kb;
205 unsigned int new_max_size;
206 int ret;
207 struct comedi_subdevice *const read_subdevice =
208 comedi_get_read_subdevice(info);
209
210 ret = kstrtouint(buf, 10, &new_max_size_kb);
211 if (ret)
212 return ret;
213 if (new_max_size_kb > (UINT_MAX / bytes_per_kibi))
214 return -EINVAL;
215 new_max_size = new_max_size_kb * bytes_per_kibi;
216
217 mutex_lock(&info->device->mutex);
218 if (read_subdevice == NULL ||
219 (read_subdevice->subdev_flags & SDF_CMD_READ) == 0 ||
220 read_subdevice->async == NULL) {
221 mutex_unlock(&info->device->mutex);
222 return -EINVAL;
223 }
224 read_subdevice->async->max_bufsize = new_max_size;
225 mutex_unlock(&info->device->mutex);
226
227 return count;
228}
229
230static DEVICE_ATTR(max_read_buffer_kb, S_IRUGO | S_IWUSR,
231 show_max_read_buffer_kb, store_max_read_buffer_kb);
232
233static ssize_t show_read_buffer_kb(struct device *dev,
234 struct device_attribute *attr, char *buf)
235{
236 ssize_t retval;
237 struct comedi_device_file_info *info = dev_get_drvdata(dev);
238 unsigned buffer_size_kb = 0;
239 struct comedi_subdevice *const read_subdevice =
240 comedi_get_read_subdevice(info);
241
242 mutex_lock(&info->device->mutex);
243 if (read_subdevice &&
244 (read_subdevice->subdev_flags & SDF_CMD_READ) &&
245 read_subdevice->async) {
246 buffer_size_kb = read_subdevice->async->prealloc_bufsz /
247 bytes_per_kibi;
248 }
249 retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb);
250 mutex_unlock(&info->device->mutex);
251
252 return retval;
253}
254
255static ssize_t store_read_buffer_kb(struct device *dev,
256 struct device_attribute *attr,
257 const char *buf, size_t count)
258{
259 struct comedi_device_file_info *info = dev_get_drvdata(dev);
260 unsigned int new_size_kb;
261 unsigned int new_size;
262 int retval;
263 int ret;
264 struct comedi_subdevice *const read_subdevice =
265 comedi_get_read_subdevice(info);
266
267 ret = kstrtouint(buf, 10, &new_size_kb);
268 if (ret)
269 return ret;
270 if (new_size_kb > (UINT_MAX / bytes_per_kibi))
271 return -EINVAL;
272 new_size = new_size_kb * bytes_per_kibi;
273
274 mutex_lock(&info->device->mutex);
275 if (read_subdevice == NULL ||
276 (read_subdevice->subdev_flags & SDF_CMD_READ) == 0 ||
277 read_subdevice->async == NULL) {
278 mutex_unlock(&info->device->mutex);
279 return -EINVAL;
280 }
281 retval = resize_async_buffer(info->device, read_subdevice,
282 read_subdevice->async, new_size);
283 mutex_unlock(&info->device->mutex);
284
285 if (retval < 0)
286 return retval;
287 return count;
288}
289
290static DEVICE_ATTR(read_buffer_kb, S_IRUGO | S_IWUSR | S_IWGRP,
291 show_read_buffer_kb, store_read_buffer_kb);
292
293static ssize_t show_max_write_buffer_kb(struct device *dev,
294 struct device_attribute *attr,
295 char *buf)
296{
297 ssize_t retval;
298 struct comedi_device_file_info *info = dev_get_drvdata(dev);
299 unsigned max_buffer_size_kb = 0;
300 struct comedi_subdevice *const write_subdevice =
301 comedi_get_write_subdevice(info);
302
303 mutex_lock(&info->device->mutex);
304 if (write_subdevice &&
305 (write_subdevice->subdev_flags & SDF_CMD_WRITE) &&
306 write_subdevice->async) {
307 max_buffer_size_kb = write_subdevice->async->max_bufsize /
308 bytes_per_kibi;
309 }
310 retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb);
311 mutex_unlock(&info->device->mutex);
312
313 return retval;
314}
315
316static ssize_t store_max_write_buffer_kb(struct device *dev,
317 struct device_attribute *attr,
318 const char *buf, size_t count)
319{
320 struct comedi_device_file_info *info = dev_get_drvdata(dev);
321 unsigned int new_max_size_kb;
322 unsigned int new_max_size;
323 int ret;
324 struct comedi_subdevice *const write_subdevice =
325 comedi_get_write_subdevice(info);
326
327 ret = kstrtouint(buf, 10, &new_max_size_kb);
328 if (ret)
329 return ret;
330 if (new_max_size_kb > (UINT_MAX / bytes_per_kibi))
331 return -EINVAL;
332 new_max_size = new_max_size_kb * bytes_per_kibi;
333
334 mutex_lock(&info->device->mutex);
335 if (write_subdevice == NULL ||
336 (write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 ||
337 write_subdevice->async == NULL) {
338 mutex_unlock(&info->device->mutex);
339 return -EINVAL;
340 }
341 write_subdevice->async->max_bufsize = new_max_size;
342 mutex_unlock(&info->device->mutex);
343
344 return count;
345}
346
347static DEVICE_ATTR(max_write_buffer_kb, S_IRUGO | S_IWUSR,
348 show_max_write_buffer_kb, store_max_write_buffer_kb);
349
350static ssize_t show_write_buffer_kb(struct device *dev,
351 struct device_attribute *attr, char *buf)
352{
353 ssize_t retval;
354 struct comedi_device_file_info *info = dev_get_drvdata(dev);
355 unsigned buffer_size_kb = 0;
356 struct comedi_subdevice *const write_subdevice =
357 comedi_get_write_subdevice(info);
358
359 mutex_lock(&info->device->mutex);
360 if (write_subdevice &&
361 (write_subdevice->subdev_flags & SDF_CMD_WRITE) &&
362 write_subdevice->async) {
363 buffer_size_kb = write_subdevice->async->prealloc_bufsz /
364 bytes_per_kibi;
365 }
366 retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb);
367 mutex_unlock(&info->device->mutex);
368
369 return retval;
370}
371
372static ssize_t store_write_buffer_kb(struct device *dev,
373 struct device_attribute *attr,
374 const char *buf, size_t count)
375{
376 struct comedi_device_file_info *info = dev_get_drvdata(dev);
377 unsigned int new_size_kb;
378 unsigned int new_size;
379 int retval;
380 int ret;
381 struct comedi_subdevice *const write_subdevice =
382 comedi_get_write_subdevice(info);
383
384 ret = kstrtouint(buf, 10, &new_size_kb);
385 if (ret)
386 return ret;
387 if (new_size_kb > (UINT_MAX / bytes_per_kibi))
388 return -EINVAL;
389 new_size = ((uint64_t) new_size_kb) * bytes_per_kibi;
390
391 mutex_lock(&info->device->mutex);
392 if (write_subdevice == NULL ||
393 (write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 ||
394 write_subdevice->async == NULL) {
395 mutex_unlock(&info->device->mutex);
396 return -EINVAL;
397 }
398 retval = resize_async_buffer(info->device, write_subdevice,
399 write_subdevice->async, new_size);
400 mutex_unlock(&info->device->mutex);
401
402 if (retval < 0)
403 return retval;
404 return count;
405}
406
407static DEVICE_ATTR(write_buffer_kb, S_IRUGO | S_IWUSR | S_IWGRP,
408 show_write_buffer_kb, store_write_buffer_kb);
409
410static struct attribute *comedi_attrs[] = {
411 &dev_attr_max_read_buffer_kb.attr,
412 &dev_attr_read_buffer_kb.attr,
413 &dev_attr_max_write_buffer_kb.attr,
414 &dev_attr_write_buffer_kb.attr,
415 NULL
416};
417
418static const struct attribute_group comedi_sysfs_files = {
419 .attrs = comedi_attrs,
420};
141 421
142static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, 422static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
143 unsigned long arg) 423 unsigned long arg)
@@ -2251,42 +2531,15 @@ int comedi_alloc_board_minor(struct device *hardware_device)
2251 if (!IS_ERR(csdev)) 2531 if (!IS_ERR(csdev))
2252 info->device->class_dev = csdev; 2532 info->device->class_dev = csdev;
2253 dev_set_drvdata(csdev, info); 2533 dev_set_drvdata(csdev, info);
2254 retval = device_create_file(csdev, &dev_attr_max_read_buffer_kb); 2534
2255 if (retval) { 2535 retval = sysfs_create_group(&csdev->kobj, &comedi_sysfs_files);
2256 printk(KERN_ERR
2257 "comedi: "
2258 "failed to create sysfs attribute file \"%s\".\n",
2259 dev_attr_max_read_buffer_kb.attr.name);
2260 comedi_free_board_minor(i);
2261 return retval;
2262 }
2263 retval = device_create_file(csdev, &dev_attr_read_buffer_kb);
2264 if (retval) {
2265 printk(KERN_ERR
2266 "comedi: "
2267 "failed to create sysfs attribute file \"%s\".\n",
2268 dev_attr_read_buffer_kb.attr.name);
2269 comedi_free_board_minor(i);
2270 return retval;
2271 }
2272 retval = device_create_file(csdev, &dev_attr_max_write_buffer_kb);
2273 if (retval) {
2274 printk(KERN_ERR
2275 "comedi: "
2276 "failed to create sysfs attribute file \"%s\".\n",
2277 dev_attr_max_write_buffer_kb.attr.name);
2278 comedi_free_board_minor(i);
2279 return retval;
2280 }
2281 retval = device_create_file(csdev, &dev_attr_write_buffer_kb);
2282 if (retval) { 2536 if (retval) {
2283 printk(KERN_ERR 2537 printk(KERN_ERR
2284 "comedi: " 2538 "comedi: failed to create sysfs attribute files\n");
2285 "failed to create sysfs attribute file \"%s\".\n",
2286 dev_attr_write_buffer_kb.attr.name);
2287 comedi_free_board_minor(i); 2539 comedi_free_board_minor(i);
2288 return retval; 2540 return retval;
2289 } 2541 }
2542
2290 return i; 2543 return i;
2291} 2544}
2292 2545
@@ -2367,42 +2620,15 @@ int comedi_alloc_subdevice_minor(struct comedi_device *dev,
2367 if (!IS_ERR(csdev)) 2620 if (!IS_ERR(csdev))
2368 s->class_dev = csdev; 2621 s->class_dev = csdev;
2369 dev_set_drvdata(csdev, info); 2622 dev_set_drvdata(csdev, info);
2370 retval = device_create_file(csdev, &dev_attr_max_read_buffer_kb); 2623
2371 if (retval) { 2624 retval = sysfs_create_group(&csdev->kobj, &comedi_sysfs_files);
2372 printk(KERN_ERR
2373 "comedi: "
2374 "failed to create sysfs attribute file \"%s\".\n",
2375 dev_attr_max_read_buffer_kb.attr.name);
2376 comedi_free_subdevice_minor(s);
2377 return retval;
2378 }
2379 retval = device_create_file(csdev, &dev_attr_read_buffer_kb);
2380 if (retval) {
2381 printk(KERN_ERR
2382 "comedi: "
2383 "failed to create sysfs attribute file \"%s\".\n",
2384 dev_attr_read_buffer_kb.attr.name);
2385 comedi_free_subdevice_minor(s);
2386 return retval;
2387 }
2388 retval = device_create_file(csdev, &dev_attr_max_write_buffer_kb);
2389 if (retval) {
2390 printk(KERN_ERR
2391 "comedi: "
2392 "failed to create sysfs attribute file \"%s\".\n",
2393 dev_attr_max_write_buffer_kb.attr.name);
2394 comedi_free_subdevice_minor(s);
2395 return retval;
2396 }
2397 retval = device_create_file(csdev, &dev_attr_write_buffer_kb);
2398 if (retval) { 2625 if (retval) {
2399 printk(KERN_ERR 2626 printk(KERN_ERR
2400 "comedi: " 2627 "comedi: failed to create sysfs attribute files\n");
2401 "failed to create sysfs attribute file \"%s\".\n",
2402 dev_attr_write_buffer_kb.attr.name);
2403 comedi_free_subdevice_minor(s); 2628 comedi_free_subdevice_minor(s);
2404 return retval; 2629 return retval;
2405 } 2630 }
2631
2406 return i; 2632 return i;
2407} 2633}
2408 2634
@@ -2441,300 +2667,3 @@ struct comedi_device_file_info *comedi_get_device_file_info(unsigned minor)
2441 return info; 2667 return info;
2442} 2668}
2443EXPORT_SYMBOL_GPL(comedi_get_device_file_info); 2669EXPORT_SYMBOL_GPL(comedi_get_device_file_info);
2444
2445static int resize_async_buffer(struct comedi_device *dev,
2446 struct comedi_subdevice *s,
2447 struct comedi_async *async, unsigned new_size)
2448{
2449 int retval;
2450
2451 if (new_size > async->max_bufsize)
2452 return -EPERM;
2453
2454 if (s->busy) {
2455 DPRINTK("subdevice is busy, cannot resize buffer\n");
2456 return -EBUSY;
2457 }
2458 if (async->mmap_count) {
2459 DPRINTK("subdevice is mmapped, cannot resize buffer\n");
2460 return -EBUSY;
2461 }
2462
2463 if (!async->prealloc_buf)
2464 return -EINVAL;
2465
2466 /* make sure buffer is an integral number of pages
2467 * (we round up) */
2468 new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
2469
2470 retval = comedi_buf_alloc(dev, s, new_size);
2471 if (retval < 0)
2472 return retval;
2473
2474 if (s->buf_change) {
2475 retval = s->buf_change(dev, s, new_size);
2476 if (retval < 0)
2477 return retval;
2478 }
2479
2480 DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
2481 dev->minor, (int)(s - dev->subdevices), async->prealloc_bufsz);
2482 return 0;
2483}
2484
2485/* sysfs attribute files */
2486
2487static const unsigned bytes_per_kibi = 1024;
2488
2489static ssize_t show_max_read_buffer_kb(struct device *dev,
2490 struct device_attribute *attr, char *buf)
2491{
2492 ssize_t retval;
2493 struct comedi_device_file_info *info = dev_get_drvdata(dev);
2494 unsigned max_buffer_size_kb = 0;
2495 struct comedi_subdevice *const read_subdevice =
2496 comedi_get_read_subdevice(info);
2497
2498 mutex_lock(&info->device->mutex);
2499 if (read_subdevice &&
2500 (read_subdevice->subdev_flags & SDF_CMD_READ) &&
2501 read_subdevice->async) {
2502 max_buffer_size_kb = read_subdevice->async->max_bufsize /
2503 bytes_per_kibi;
2504 }
2505 retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb);
2506 mutex_unlock(&info->device->mutex);
2507
2508 return retval;
2509}
2510
2511static ssize_t store_max_read_buffer_kb(struct device *dev,
2512 struct device_attribute *attr,
2513 const char *buf, size_t count)
2514{
2515 struct comedi_device_file_info *info = dev_get_drvdata(dev);
2516 unsigned int new_max_size_kb;
2517 unsigned int new_max_size;
2518 int ret;
2519 struct comedi_subdevice *const read_subdevice =
2520 comedi_get_read_subdevice(info);
2521
2522 ret = kstrtouint(buf, 10, &new_max_size_kb);
2523 if (ret)
2524 return ret;
2525 if (new_max_size_kb > (UINT_MAX / bytes_per_kibi))
2526 return -EINVAL;
2527 new_max_size = new_max_size_kb * bytes_per_kibi;
2528
2529 mutex_lock(&info->device->mutex);
2530 if (read_subdevice == NULL ||
2531 (read_subdevice->subdev_flags & SDF_CMD_READ) == 0 ||
2532 read_subdevice->async == NULL) {
2533 mutex_unlock(&info->device->mutex);
2534 return -EINVAL;
2535 }
2536 read_subdevice->async->max_bufsize = new_max_size;
2537 mutex_unlock(&info->device->mutex);
2538
2539 return count;
2540}
2541
2542static struct device_attribute dev_attr_max_read_buffer_kb = {
2543 .attr = {
2544 .name = "max_read_buffer_kb",
2545 .mode = S_IRUGO | S_IWUSR},
2546 .show = &show_max_read_buffer_kb,
2547 .store = &store_max_read_buffer_kb
2548};
2549
2550static ssize_t show_read_buffer_kb(struct device *dev,
2551 struct device_attribute *attr, char *buf)
2552{
2553 ssize_t retval;
2554 struct comedi_device_file_info *info = dev_get_drvdata(dev);
2555 unsigned buffer_size_kb = 0;
2556 struct comedi_subdevice *const read_subdevice =
2557 comedi_get_read_subdevice(info);
2558
2559 mutex_lock(&info->device->mutex);
2560 if (read_subdevice &&
2561 (read_subdevice->subdev_flags & SDF_CMD_READ) &&
2562 read_subdevice->async) {
2563 buffer_size_kb = read_subdevice->async->prealloc_bufsz /
2564 bytes_per_kibi;
2565 }
2566 retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb);
2567 mutex_unlock(&info->device->mutex);
2568
2569 return retval;
2570}
2571
2572static ssize_t store_read_buffer_kb(struct device *dev,
2573 struct device_attribute *attr,
2574 const char *buf, size_t count)
2575{
2576 struct comedi_device_file_info *info = dev_get_drvdata(dev);
2577 unsigned int new_size_kb;
2578 unsigned int new_size;
2579 int retval;
2580 int ret;
2581 struct comedi_subdevice *const read_subdevice =
2582 comedi_get_read_subdevice(info);
2583
2584 ret = kstrtouint(buf, 10, &new_size_kb);
2585 if (ret)
2586 return ret;
2587 if (new_size_kb > (UINT_MAX / bytes_per_kibi))
2588 return -EINVAL;
2589 new_size = new_size_kb * bytes_per_kibi;
2590
2591 mutex_lock(&info->device->mutex);
2592 if (read_subdevice == NULL ||
2593 (read_subdevice->subdev_flags & SDF_CMD_READ) == 0 ||
2594 read_subdevice->async == NULL) {
2595 mutex_unlock(&info->device->mutex);
2596 return -EINVAL;
2597 }
2598 retval = resize_async_buffer(info->device, read_subdevice,
2599 read_subdevice->async, new_size);
2600 mutex_unlock(&info->device->mutex);
2601
2602 if (retval < 0)
2603 return retval;
2604 return count;
2605}
2606
2607static struct device_attribute dev_attr_read_buffer_kb = {
2608 .attr = {
2609 .name = "read_buffer_kb",
2610 .mode = S_IRUGO | S_IWUSR | S_IWGRP},
2611 .show = &show_read_buffer_kb,
2612 .store = &store_read_buffer_kb
2613};
2614
2615static ssize_t show_max_write_buffer_kb(struct device *dev,
2616 struct device_attribute *attr,
2617 char *buf)
2618{
2619 ssize_t retval;
2620 struct comedi_device_file_info *info = dev_get_drvdata(dev);
2621 unsigned max_buffer_size_kb = 0;
2622 struct comedi_subdevice *const write_subdevice =
2623 comedi_get_write_subdevice(info);
2624
2625 mutex_lock(&info->device->mutex);
2626 if (write_subdevice &&
2627 (write_subdevice->subdev_flags & SDF_CMD_WRITE) &&
2628 write_subdevice->async) {
2629 max_buffer_size_kb = write_subdevice->async->max_bufsize /
2630 bytes_per_kibi;
2631 }
2632 retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb);
2633 mutex_unlock(&info->device->mutex);
2634
2635 return retval;
2636}
2637
2638static ssize_t store_max_write_buffer_kb(struct device *dev,
2639 struct device_attribute *attr,
2640 const char *buf, size_t count)
2641{
2642 struct comedi_device_file_info *info = dev_get_drvdata(dev);
2643 unsigned int new_max_size_kb;
2644 unsigned int new_max_size;
2645 int ret;
2646 struct comedi_subdevice *const write_subdevice =
2647 comedi_get_write_subdevice(info);
2648
2649 ret = kstrtouint(buf, 10, &new_max_size_kb);
2650 if (ret)
2651 return ret;
2652 if (new_max_size_kb > (UINT_MAX / bytes_per_kibi))
2653 return -EINVAL;
2654 new_max_size = new_max_size_kb * bytes_per_kibi;
2655
2656 mutex_lock(&info->device->mutex);
2657 if (write_subdevice == NULL ||
2658 (write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 ||
2659 write_subdevice->async == NULL) {
2660 mutex_unlock(&info->device->mutex);
2661 return -EINVAL;
2662 }
2663 write_subdevice->async->max_bufsize = new_max_size;
2664 mutex_unlock(&info->device->mutex);
2665
2666 return count;
2667}
2668
2669static struct device_attribute dev_attr_max_write_buffer_kb = {
2670 .attr = {
2671 .name = "max_write_buffer_kb",
2672 .mode = S_IRUGO | S_IWUSR},
2673 .show = &show_max_write_buffer_kb,
2674 .store = &store_max_write_buffer_kb
2675};
2676
2677static ssize_t show_write_buffer_kb(struct device *dev,
2678 struct device_attribute *attr, char *buf)
2679{
2680 ssize_t retval;
2681 struct comedi_device_file_info *info = dev_get_drvdata(dev);
2682 unsigned buffer_size_kb = 0;
2683 struct comedi_subdevice *const write_subdevice =
2684 comedi_get_write_subdevice(info);
2685
2686 mutex_lock(&info->device->mutex);
2687 if (write_subdevice &&
2688 (write_subdevice->subdev_flags & SDF_CMD_WRITE) &&
2689 write_subdevice->async) {
2690 buffer_size_kb = write_subdevice->async->prealloc_bufsz /
2691 bytes_per_kibi;
2692 }
2693 retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb);
2694 mutex_unlock(&info->device->mutex);
2695
2696 return retval;
2697}
2698
2699static ssize_t store_write_buffer_kb(struct device *dev,
2700 struct device_attribute *attr,
2701 const char *buf, size_t count)
2702{
2703 struct comedi_device_file_info *info = dev_get_drvdata(dev);
2704 unsigned int new_size_kb;
2705 unsigned int new_size;
2706 int retval;
2707 int ret;
2708 struct comedi_subdevice *const write_subdevice =
2709 comedi_get_write_subdevice(info);
2710
2711 ret = kstrtouint(buf, 10, &new_size_kb);
2712 if (ret)
2713 return ret;
2714 if (new_size_kb > (UINT_MAX / bytes_per_kibi))
2715 return -EINVAL;
2716 new_size = ((uint64_t) new_size_kb) * bytes_per_kibi;
2717
2718 mutex_lock(&info->device->mutex);
2719 if (write_subdevice == NULL ||
2720 (write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 ||
2721 write_subdevice->async == NULL) {
2722 mutex_unlock(&info->device->mutex);
2723 return -EINVAL;
2724 }
2725 retval = resize_async_buffer(info->device, write_subdevice,
2726 write_subdevice->async, new_size);
2727 mutex_unlock(&info->device->mutex);
2728
2729 if (retval < 0)
2730 return retval;
2731 return count;
2732}
2733
2734static struct device_attribute dev_attr_write_buffer_kb = {
2735 .attr = {
2736 .name = "write_buffer_kb",
2737 .mode = S_IRUGO | S_IWUSR | S_IWGRP},
2738 .show = &show_write_buffer_kb,
2739 .store = &store_write_buffer_kb
2740};