diff options
-rw-r--r-- | drivers/staging/comedi/comedi_fops.c | 659 |
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); | |||
129 | static int comedi_fasync(int fd, struct file *file, int on); | 129 | static int comedi_fasync(int fd, struct file *file, int on); |
130 | 130 | ||
131 | static int is_device_busy(struct comedi_device *dev); | 131 | static int is_device_busy(struct comedi_device *dev); |
132 | |||
132 | static int resize_async_buffer(struct comedi_device *dev, | 133 | static 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 |
137 | static struct device_attribute dev_attr_max_read_buffer_kb; | 155 | * (we round up) */ |
138 | static struct device_attribute dev_attr_read_buffer_kb; | 156 | new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK; |
139 | static struct device_attribute dev_attr_max_write_buffer_kb; | 157 | |
140 | static 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 | |||
175 | static const unsigned bytes_per_kibi = 1024; | ||
176 | |||
177 | static 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 | |||
199 | static 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 | |||
230 | static DEVICE_ATTR(max_read_buffer_kb, S_IRUGO | S_IWUSR, | ||
231 | show_max_read_buffer_kb, store_max_read_buffer_kb); | ||
232 | |||
233 | static 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 | |||
255 | static 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 | |||
290 | static DEVICE_ATTR(read_buffer_kb, S_IRUGO | S_IWUSR | S_IWGRP, | ||
291 | show_read_buffer_kb, store_read_buffer_kb); | ||
292 | |||
293 | static 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 | |||
316 | static 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 | |||
347 | static DEVICE_ATTR(max_write_buffer_kb, S_IRUGO | S_IWUSR, | ||
348 | show_max_write_buffer_kb, store_max_write_buffer_kb); | ||
349 | |||
350 | static 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 | |||
372 | static 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 | |||
407 | static DEVICE_ATTR(write_buffer_kb, S_IRUGO | S_IWUSR | S_IWGRP, | ||
408 | show_write_buffer_kb, store_write_buffer_kb); | ||
409 | |||
410 | static 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 | |||
418 | static const struct attribute_group comedi_sysfs_files = { | ||
419 | .attrs = comedi_attrs, | ||
420 | }; | ||
141 | 421 | ||
142 | static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, | 422 | static 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 | } |
2443 | EXPORT_SYMBOL_GPL(comedi_get_device_file_info); | 2669 | EXPORT_SYMBOL_GPL(comedi_get_device_file_info); |
2444 | |||
2445 | static 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 | |||
2487 | static const unsigned bytes_per_kibi = 1024; | ||
2488 | |||
2489 | static 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 | |||
2511 | static 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 | |||
2542 | static 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 | |||
2550 | static 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 | |||
2572 | static 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 | |||
2607 | static 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 | |||
2615 | static 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 | |||
2638 | static 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 | |||
2669 | static 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 | |||
2677 | static 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 | |||
2699 | static 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 | |||
2734 | static 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 | }; | ||