diff options
Diffstat (limited to 'drivers/firewire/fw-device-cdev.c')
-rw-r--r-- | drivers/firewire/fw-device-cdev.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c index 33fe5768a078..9f3c96c7af29 100644 --- a/drivers/firewire/fw-device-cdev.c +++ b/drivers/firewire/fw-device-cdev.c | |||
@@ -50,6 +50,11 @@ struct event { | |||
50 | struct list_head link; | 50 | struct list_head link; |
51 | }; | 51 | }; |
52 | 52 | ||
53 | struct bus_reset { | ||
54 | struct event event; | ||
55 | struct fw_cdev_event_bus_reset reset; | ||
56 | }; | ||
57 | |||
53 | struct response { | 58 | struct response { |
54 | struct event event; | 59 | struct event event; |
55 | struct fw_transaction transaction; | 60 | struct fw_transaction transaction; |
@@ -75,6 +80,8 @@ struct client { | |||
75 | struct fw_iso_context *iso_context; | 80 | struct fw_iso_context *iso_context; |
76 | struct fw_iso_buffer buffer; | 81 | struct fw_iso_buffer buffer; |
77 | unsigned long vm_start; | 82 | unsigned long vm_start; |
83 | |||
84 | struct list_head link; | ||
78 | }; | 85 | }; |
79 | 86 | ||
80 | static inline void __user * | 87 | static inline void __user * |
@@ -93,6 +100,7 @@ static int fw_device_op_open(struct inode *inode, struct file *file) | |||
93 | { | 100 | { |
94 | struct fw_device *device; | 101 | struct fw_device *device; |
95 | struct client *client; | 102 | struct client *client; |
103 | unsigned long flags; | ||
96 | 104 | ||
97 | device = container_of(inode->i_cdev, struct fw_device, cdev); | 105 | device = container_of(inode->i_cdev, struct fw_device, cdev); |
98 | 106 | ||
@@ -110,6 +118,10 @@ static int fw_device_op_open(struct inode *inode, struct file *file) | |||
110 | 118 | ||
111 | file->private_data = client; | 119 | file->private_data = client; |
112 | 120 | ||
121 | spin_lock_irqsave(&device->card->lock, flags); | ||
122 | list_add_tail(&client->link, &device->client_list); | ||
123 | spin_unlock_irqrestore(&device->card->lock, flags); | ||
124 | |||
113 | return 0; | 125 | return 0; |
114 | } | 126 | } |
115 | 127 | ||
@@ -177,6 +189,45 @@ fw_device_op_read(struct file *file, | |||
177 | return dequeue_event(client, buffer, count); | 189 | return dequeue_event(client, buffer, count); |
178 | } | 190 | } |
179 | 191 | ||
192 | static void | ||
193 | queue_bus_reset_event(struct client *client) | ||
194 | { | ||
195 | struct bus_reset *bus_reset; | ||
196 | struct fw_device *device = client->device; | ||
197 | struct fw_card *card = device->card; | ||
198 | |||
199 | bus_reset = kzalloc(sizeof *bus_reset, GFP_ATOMIC); | ||
200 | if (bus_reset == NULL) { | ||
201 | fw_notify("Out of memory when allocating bus reset event\n"); | ||
202 | return; | ||
203 | } | ||
204 | |||
205 | bus_reset->reset.type = FW_CDEV_EVENT_BUS_RESET; | ||
206 | bus_reset->reset.node_id = device->node_id; | ||
207 | bus_reset->reset.local_node_id = card->local_node->node_id; | ||
208 | bus_reset->reset.bm_node_id = 0; /* FIXME: We don't track the BM. */ | ||
209 | bus_reset->reset.irm_node_id = card->irm_node->node_id; | ||
210 | bus_reset->reset.root_node_id = card->root_node->node_id; | ||
211 | bus_reset->reset.generation = card->generation; | ||
212 | |||
213 | queue_event(client, &bus_reset->event, | ||
214 | &bus_reset->reset, sizeof bus_reset->reset, NULL, 0); | ||
215 | } | ||
216 | |||
217 | void fw_device_cdev_update(struct fw_device *device) | ||
218 | { | ||
219 | struct fw_card *card = device->card; | ||
220 | struct client *c; | ||
221 | unsigned long flags; | ||
222 | |||
223 | spin_lock_irqsave(&card->lock, flags); | ||
224 | |||
225 | list_for_each_entry(c, &device->client_list, link) | ||
226 | queue_bus_reset_event(c); | ||
227 | |||
228 | spin_unlock_irqrestore(&card->lock, flags); | ||
229 | } | ||
230 | |||
180 | static int ioctl_config_rom(struct client *client, void __user *arg) | 231 | static int ioctl_config_rom(struct client *client, void __user *arg) |
181 | { | 232 | { |
182 | struct fw_cdev_get_config_rom rom; | 233 | struct fw_cdev_get_config_rom rom; |
@@ -633,6 +684,7 @@ static int fw_device_op_release(struct inode *inode, struct file *file) | |||
633 | struct client *client = file->private_data; | 684 | struct client *client = file->private_data; |
634 | struct address_handler *h, *next; | 685 | struct address_handler *h, *next; |
635 | struct request *r, *next_r; | 686 | struct request *r, *next_r; |
687 | unsigned long flags; | ||
636 | 688 | ||
637 | if (client->buffer.pages) | 689 | if (client->buffer.pages) |
638 | fw_iso_buffer_destroy(&client->buffer, client->device->card); | 690 | fw_iso_buffer_destroy(&client->buffer, client->device->card); |
@@ -657,6 +709,10 @@ static int fw_device_op_release(struct inode *inode, struct file *file) | |||
657 | while (!list_empty(&client->event_list)) | 709 | while (!list_empty(&client->event_list)) |
658 | dequeue_event(client, NULL, 0); | 710 | dequeue_event(client, NULL, 0); |
659 | 711 | ||
712 | spin_lock_irqsave(&client->device->card->lock, flags); | ||
713 | list_del(&client->link); | ||
714 | spin_unlock_irqrestore(&client->device->card->lock, flags); | ||
715 | |||
660 | fw_device_put(client->device); | 716 | fw_device_put(client->device); |
661 | kfree(client); | 717 | kfree(client); |
662 | 718 | ||