aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2007-03-27 01:43:41 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-03-28 15:30:15 -0400
commit3964a4496eaa4cb84772e8dfc6c3a72ec4ddca7a (patch)
treeadf0102386cc1d55712b41c3df2aefa4bceaba65 /drivers/firewire
parent66dea3e5f69abfdfa46b091ea117e497758351e7 (diff)
firewire: Generalize resource tracking for cdev implementation.
Generalize the way we keep track of the various resources and assign a unique handle to each resource. Signed-off-by: Kristian Høgsberg <krh@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/fw-device-cdev.c231
-rw-r--r--drivers/firewire/fw-device-cdev.h7
2 files changed, 119 insertions, 119 deletions
diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c
index e3c4a52a44a9..d02dbc5af91e 100644
--- a/drivers/firewire/fw-device-cdev.c
+++ b/drivers/firewire/fw-device-cdev.c
@@ -36,16 +36,16 @@
36#include "fw-device.h" 36#include "fw-device.h"
37#include "fw-device-cdev.h" 37#include "fw-device-cdev.h"
38 38
39/*
40 * todo
41 *
42 * - bus resets sends a new packet with new generation and node id
43 *
44 */
45
46/* dequeue_event() just kfree()'s the event, so the event has to be 39/* dequeue_event() just kfree()'s the event, so the event has to be
47 * the first field in the struct. */ 40 * the first field in the struct. */
48 41
42struct client;
43struct client_resource {
44 struct list_head link;
45 void (*release)(struct client *client, struct client_resource *r);
46 u32 handle;
47};
48
49struct event { 49struct event {
50 struct { void *data; size_t size; } v[2]; 50 struct { void *data; size_t size; } v[2];
51 struct list_head link; 51 struct list_head link;
@@ -60,7 +60,7 @@ struct response {
60 struct event event; 60 struct event event;
61 struct fw_transaction transaction; 61 struct fw_transaction transaction;
62 struct client *client; 62 struct client *client;
63 struct list_head link; 63 struct client_resource resource;
64 struct fw_cdev_event_response response; 64 struct fw_cdev_event_response response;
65}; 65};
66 66
@@ -74,11 +74,7 @@ struct client {
74 struct fw_device *device; 74 struct fw_device *device;
75 spinlock_t lock; 75 spinlock_t lock;
76 u32 resource_handle; 76 u32 resource_handle;
77 struct list_head handler_list; 77 struct list_head resource_list;
78 struct list_head request_list;
79 struct list_head transaction_list;
80 struct list_head descriptor_list;
81 u32 request_serial;
82 struct list_head event_list; 78 struct list_head event_list;
83 wait_queue_head_t wait; 79 wait_queue_head_t wait;
84 u64 bus_reset_closure; 80 u64 bus_reset_closure;
@@ -118,10 +114,7 @@ static int fw_device_op_open(struct inode *inode, struct file *file)
118 114
119 client->device = fw_device_get(device); 115 client->device = fw_device_get(device);
120 INIT_LIST_HEAD(&client->event_list); 116 INIT_LIST_HEAD(&client->event_list);
121 INIT_LIST_HEAD(&client->handler_list); 117 INIT_LIST_HEAD(&client->resource_list);
122 INIT_LIST_HEAD(&client->request_list);
123 INIT_LIST_HEAD(&client->transaction_list);
124 INIT_LIST_HEAD(&client->descriptor_list);
125 spin_lock_init(&client->lock); 118 spin_lock_init(&client->lock);
126 init_waitqueue_head(&client->wait); 119 init_waitqueue_head(&client->wait);
127 120
@@ -305,6 +298,53 @@ static int ioctl_get_info(struct client *client, void __user *arg)
305} 298}
306 299
307static void 300static void
301add_client_resource(struct client *client, struct client_resource *resource)
302{
303 unsigned long flags;
304
305 spin_lock_irqsave(&client->lock, flags);
306 list_add_tail(&resource->link, &client->resource_list);
307 resource->handle = client->resource_handle++;
308 spin_unlock_irqrestore(&client->lock, flags);
309}
310
311static int
312release_client_resource(struct client *client, u32 handle,
313 struct client_resource **resource)
314{
315 struct client_resource *r;
316 unsigned long flags;
317
318 spin_lock_irqsave(&client->lock, flags);
319 list_for_each_entry(r, &client->resource_list, link) {
320 if (r->handle == handle) {
321 list_del(&r->link);
322 break;
323 }
324 }
325 spin_unlock_irqrestore(&client->lock, flags);
326
327 if (&r->link == &client->resource_list)
328 return -EINVAL;
329
330 if (resource)
331 *resource = r;
332 else
333 r->release(client, r);
334
335 return 0;
336}
337
338static void
339release_transaction(struct client *client, struct client_resource *resource)
340{
341 struct response *response =
342 container_of(resource, struct response, resource);
343
344 fw_cancel_transaction(client->device->card, &response->transaction);
345}
346
347static void
308complete_transaction(struct fw_card *card, int rcode, 348complete_transaction(struct fw_card *card, int rcode,
309 void *payload, size_t length, void *data) 349 void *payload, size_t length, void *data)
310{ 350{
@@ -319,7 +359,7 @@ complete_transaction(struct fw_card *card, int rcode,
319 response->response.length); 359 response->response.length);
320 360
321 spin_lock_irqsave(&client->lock, flags); 361 spin_lock_irqsave(&client->lock, flags);
322 list_del(&response->link); 362 list_del(&response->resource.link);
323 spin_unlock_irqrestore(&client->lock, flags); 363 spin_unlock_irqrestore(&client->lock, flags);
324 364
325 response->response.type = FW_CDEV_EVENT_RESPONSE; 365 response->response.type = FW_CDEV_EVENT_RESPONSE;
@@ -334,7 +374,6 @@ static ssize_t ioctl_send_request(struct client *client, void __user *arg)
334 struct fw_device *device = client->device; 374 struct fw_device *device = client->device;
335 struct fw_cdev_send_request request; 375 struct fw_cdev_send_request request;
336 struct response *response; 376 struct response *response;
337 unsigned long flags;
338 377
339 if (copy_from_user(&request, arg, sizeof request)) 378 if (copy_from_user(&request, arg, sizeof request))
340 return -EFAULT; 379 return -EFAULT;
@@ -358,9 +397,8 @@ static ssize_t ioctl_send_request(struct client *client, void __user *arg)
358 return -EFAULT; 397 return -EFAULT;
359 } 398 }
360 399
361 spin_lock_irqsave(&client->lock, flags); 400 response->resource.release = release_transaction;
362 list_add_tail(&response->link, &client->transaction_list); 401 add_client_resource(client, &response->resource);
363 spin_unlock_irqrestore(&client->lock, flags);
364 402
365 fw_send_request(device->card, &response->transaction, 403 fw_send_request(device->card, &response->transaction,
366 request.tcode & 0x1f, 404 request.tcode & 0x1f,
@@ -381,15 +419,14 @@ struct address_handler {
381 struct fw_address_handler handler; 419 struct fw_address_handler handler;
382 __u64 closure; 420 __u64 closure;
383 struct client *client; 421 struct client *client;
384 struct list_head link; 422 struct client_resource resource;
385}; 423};
386 424
387struct request { 425struct request {
388 struct fw_request *request; 426 struct fw_request *request;
389 void *data; 427 void *data;
390 size_t length; 428 size_t length;
391 u32 serial; 429 struct client_resource resource;
392 struct list_head link;
393}; 430};
394 431
395struct request_event { 432struct request_event {
@@ -398,6 +435,17 @@ struct request_event {
398}; 435};
399 436
400static void 437static void
438release_request(struct client *client, struct client_resource *resource)
439{
440 struct request *request =
441 container_of(resource, struct request, resource);
442
443 fw_send_response(client->device->card, request->request,
444 RCODE_CONFLICT_ERROR);
445 kfree(request);
446}
447
448static void
401handle_request(struct fw_card *card, struct fw_request *r, 449handle_request(struct fw_card *card, struct fw_request *r,
402 int tcode, int destination, int source, 450 int tcode, int destination, int source,
403 int generation, int speed, 451 int generation, int speed,
@@ -407,7 +455,6 @@ handle_request(struct fw_card *card, struct fw_request *r,
407 struct address_handler *handler = callback_data; 455 struct address_handler *handler = callback_data;
408 struct request *request; 456 struct request *request;
409 struct request_event *e; 457 struct request_event *e;
410 unsigned long flags;
411 struct client *client = handler->client; 458 struct client *client = handler->client;
412 459
413 request = kmalloc(sizeof *request, GFP_ATOMIC); 460 request = kmalloc(sizeof *request, GFP_ATOMIC);
@@ -423,27 +470,35 @@ handle_request(struct fw_card *card, struct fw_request *r,
423 request->data = payload; 470 request->data = payload;
424 request->length = length; 471 request->length = length;
425 472
426 spin_lock_irqsave(&client->lock, flags); 473 request->resource.release = release_request;
427 request->serial = client->request_serial++; 474 add_client_resource(client, &request->resource);
428 list_add_tail(&request->link, &client->request_list);
429 spin_unlock_irqrestore(&client->lock, flags);
430 475
431 e->request.type = FW_CDEV_EVENT_REQUEST; 476 e->request.type = FW_CDEV_EVENT_REQUEST;
432 e->request.tcode = tcode; 477 e->request.tcode = tcode;
433 e->request.offset = offset; 478 e->request.offset = offset;
434 e->request.length = length; 479 e->request.length = length;
435 e->request.serial = request->serial; 480 e->request.handle = request->resource.handle;
436 e->request.closure = handler->closure; 481 e->request.closure = handler->closure;
437 482
438 queue_event(client, &e->event, 483 queue_event(client, &e->event,
439 &e->request, sizeof e->request, payload, length); 484 &e->request, sizeof e->request, payload, length);
440} 485}
441 486
487static void
488release_address_handler(struct client *client,
489 struct client_resource *resource)
490{
491 struct address_handler *handler =
492 container_of(resource, struct address_handler, resource);
493
494 fw_core_remove_address_handler(&handler->handler);
495 kfree(handler);
496}
497
442static int ioctl_allocate(struct client *client, void __user *arg) 498static int ioctl_allocate(struct client *client, void __user *arg)
443{ 499{
444 struct fw_cdev_allocate request; 500 struct fw_cdev_allocate request;
445 struct address_handler *handler; 501 struct address_handler *handler;
446 unsigned long flags;
447 struct fw_address_region region; 502 struct fw_address_region region;
448 503
449 if (copy_from_user(&request, arg, sizeof request)) 504 if (copy_from_user(&request, arg, sizeof request))
@@ -466,9 +521,12 @@ static int ioctl_allocate(struct client *client, void __user *arg)
466 return -EBUSY; 521 return -EBUSY;
467 } 522 }
468 523
469 spin_lock_irqsave(&client->lock, flags); 524 handler->resource.release = release_address_handler;
470 list_add_tail(&handler->link, &client->handler_list); 525 add_client_resource(client, &handler->resource);
471 spin_unlock_irqrestore(&client->lock, flags); 526 request.handle = handler->resource.handle;
527
528 if (copy_to_user(arg, &request, sizeof request))
529 return -EFAULT;
472 530
473 return 0; 531 return 0;
474} 532}
@@ -476,57 +534,30 @@ static int ioctl_allocate(struct client *client, void __user *arg)
476static int ioctl_deallocate(struct client *client, void __user *arg) 534static int ioctl_deallocate(struct client *client, void __user *arg)
477{ 535{
478 struct fw_cdev_deallocate request; 536 struct fw_cdev_deallocate request;
479 struct address_handler *handler;
480 unsigned long flags;
481 537
482 if (copy_from_user(&request, arg, sizeof request)) 538 if (copy_from_user(&request, arg, sizeof request))
483 return -EFAULT; 539 return -EFAULT;
484 540
485 spin_lock_irqsave(&client->lock, flags); 541 return release_client_resource(client, request.handle, NULL);
486 list_for_each_entry(handler, &client->handler_list, link) {
487 if (handler->handler.offset == request.offset) {
488 list_del(&handler->link);
489 break;
490 }
491 }
492 spin_unlock_irqrestore(&client->lock, flags);
493
494 if (&handler->link == &client->handler_list)
495 return -EINVAL;
496
497 fw_core_remove_address_handler(&handler->handler);
498
499 return 0;
500} 542}
501 543
502static int ioctl_send_response(struct client *client, void __user *arg) 544static int ioctl_send_response(struct client *client, void __user *arg)
503{ 545{
504 struct fw_cdev_send_response request; 546 struct fw_cdev_send_response request;
547 struct client_resource *resource;
505 struct request *r; 548 struct request *r;
506 unsigned long flags;
507 549
508 if (copy_from_user(&request, arg, sizeof request)) 550 if (copy_from_user(&request, arg, sizeof request))
509 return -EFAULT; 551 return -EFAULT;
510 552 if (release_client_resource(client, request.handle, &resource) < 0)
511 spin_lock_irqsave(&client->lock, flags);
512 list_for_each_entry(r, &client->request_list, link) {
513 if (r->serial == request.serial) {
514 list_del(&r->link);
515 break;
516 }
517 }
518 spin_unlock_irqrestore(&client->lock, flags);
519
520 if (&r->link == &client->request_list)
521 return -EINVAL; 553 return -EINVAL;
522 554 r = container_of(resource, struct request, resource);
523 if (request.length < r->length) 555 if (request.length < r->length)
524 r->length = request.length; 556 r->length = request.length;
525 if (copy_from_user(r->data, u64_to_uptr(request.data), r->length)) 557 if (copy_from_user(r->data, u64_to_uptr(request.data), r->length))
526 return -EFAULT; 558 return -EFAULT;
527 559
528 fw_send_response(client->device->card, r->request, request.rcode); 560 fw_send_response(client->device->card, r->request, request.rcode);
529
530 kfree(r); 561 kfree(r);
531 562
532 return 0; 563 return 0;
@@ -547,16 +578,24 @@ static int ioctl_initiate_bus_reset(struct client *client, void __user *arg)
547 578
548struct descriptor { 579struct descriptor {
549 struct fw_descriptor d; 580 struct fw_descriptor d;
550 struct list_head link; 581 struct client_resource resource;
551 u32 handle;
552 u32 data[0]; 582 u32 data[0];
553}; 583};
554 584
585static void release_descriptor(struct client *client,
586 struct client_resource *resource)
587{
588 struct descriptor *descriptor =
589 container_of(resource, struct descriptor, resource);
590
591 fw_core_remove_descriptor(&descriptor->d);
592 kfree(descriptor);
593}
594
555static int ioctl_add_descriptor(struct client *client, void __user *arg) 595static int ioctl_add_descriptor(struct client *client, void __user *arg)
556{ 596{
557 struct fw_cdev_add_descriptor request; 597 struct fw_cdev_add_descriptor request;
558 struct descriptor *descriptor; 598 struct descriptor *descriptor;
559 unsigned long flags;
560 int retval; 599 int retval;
561 600
562 if (copy_from_user(&request, arg, sizeof request)) 601 if (copy_from_user(&request, arg, sizeof request))
@@ -587,12 +626,10 @@ static int ioctl_add_descriptor(struct client *client, void __user *arg)
587 return retval; 626 return retval;
588 } 627 }
589 628
590 spin_lock_irqsave(&client->lock, flags); 629 descriptor->resource.release = release_descriptor;
591 list_add_tail(&descriptor->link, &client->descriptor_list); 630 add_client_resource(client, &descriptor->resource);
592 descriptor->handle = client->resource_handle++; 631 request.handle = descriptor->resource.handle;
593 spin_unlock_irqrestore(&client->lock, flags);
594 632
595 request.handle = descriptor->handle;
596 if (copy_to_user(arg, &request, sizeof request)) 633 if (copy_to_user(arg, &request, sizeof request))
597 return -EFAULT; 634 return -EFAULT;
598 635
@@ -602,28 +639,11 @@ static int ioctl_add_descriptor(struct client *client, void __user *arg)
602static int ioctl_remove_descriptor(struct client *client, void __user *arg) 639static int ioctl_remove_descriptor(struct client *client, void __user *arg)
603{ 640{
604 struct fw_cdev_remove_descriptor request; 641 struct fw_cdev_remove_descriptor request;
605 struct descriptor *d;
606 unsigned long flags;
607 642
608 if (copy_from_user(&request, arg, sizeof request)) 643 if (copy_from_user(&request, arg, sizeof request))
609 return -EFAULT; 644 return -EFAULT;
610 645
611 spin_lock_irqsave(&client->lock, flags); 646 return release_client_resource(client, request.handle, NULL);
612 list_for_each_entry(d, &client->descriptor_list, link) {
613 if (d->handle == request.handle) {
614 list_del(&d->link);
615 break;
616 }
617 }
618 spin_unlock_irqrestore(&client->lock, flags);
619
620 if (&d->link == &client->descriptor_list)
621 return -EINVAL;
622
623 fw_core_remove_descriptor(&d->d);
624 kfree(d);
625
626 return 0;
627} 647}
628 648
629static void 649static void
@@ -895,11 +915,8 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma)
895static int fw_device_op_release(struct inode *inode, struct file *file) 915static int fw_device_op_release(struct inode *inode, struct file *file)
896{ 916{
897 struct client *client = file->private_data; 917 struct client *client = file->private_data;
898 struct address_handler *h, *next_h;
899 struct request *r, *next_r;
900 struct event *e, *next_e; 918 struct event *e, *next_e;
901 struct response *t, *next_t; 919 struct client_resource *r, *next_r;
902 struct descriptor *d, *next_d;
903 unsigned long flags; 920 unsigned long flags;
904 921
905 if (client->buffer.pages) 922 if (client->buffer.pages)
@@ -908,26 +925,8 @@ static int fw_device_op_release(struct inode *inode, struct file *file)
908 if (client->iso_context) 925 if (client->iso_context)
909 fw_iso_context_destroy(client->iso_context); 926 fw_iso_context_destroy(client->iso_context);
910 927
911 list_for_each_entry_safe(h, next_h, &client->handler_list, link) { 928 list_for_each_entry_safe(r, next_r, &client->resource_list, link)
912 fw_core_remove_address_handler(&h->handler); 929 r->release(client, r);
913 kfree(h);
914 }
915
916 list_for_each_entry_safe(r, next_r, &client->request_list, link) {
917 fw_send_response(client->device->card, r->request,
918 RCODE_CONFLICT_ERROR);
919 kfree(r);
920 }
921
922 list_for_each_entry_safe(t, next_t, &client->transaction_list, link) {
923 fw_cancel_transaction(client->device->card, &t->transaction);
924 kfree(t);
925 }
926
927 list_for_each_entry_safe(d, next_d, &client->descriptor_list, link) {
928 fw_core_remove_descriptor(&d->d);
929 kfree(d);
930 }
931 930
932 /* FIXME: We should wait for the async tasklets to stop 931 /* FIXME: We should wait for the async tasklets to stop
933 * running before freeing the memory. */ 932 * running before freeing the memory. */
diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h
index 62f5f66ca101..a6340bf306fb 100644
--- a/drivers/firewire/fw-device-cdev.h
+++ b/drivers/firewire/fw-device-cdev.h
@@ -103,7 +103,7 @@ struct fw_cdev_event_request {
103 __u32 type; 103 __u32 type;
104 __u32 tcode; 104 __u32 tcode;
105 __u64 offset; 105 __u64 offset;
106 __u32 serial; 106 __u32 handle;
107 __u32 length; 107 __u32 length;
108 __u32 data[0]; 108 __u32 data[0];
109}; 109};
@@ -186,17 +186,18 @@ struct fw_cdev_send_response {
186 __u32 rcode; 186 __u32 rcode;
187 __u32 length; 187 __u32 length;
188 __u64 data; 188 __u64 data;
189 __u32 serial; 189 __u32 handle;
190}; 190};
191 191
192struct fw_cdev_allocate { 192struct fw_cdev_allocate {
193 __u64 offset; 193 __u64 offset;
194 __u64 closure; 194 __u64 closure;
195 __u32 length; 195 __u32 length;
196 __u32 handle;
196}; 197};
197 198
198struct fw_cdev_deallocate { 199struct fw_cdev_deallocate {
199 __u64 offset; 200 __u32 handle;
200}; 201};
201 202
202#define FW_CDEV_LONG_RESET 0 203#define FW_CDEV_LONG_RESET 0