diff options
Diffstat (limited to 'drivers/firewire')
-rw-r--r-- | drivers/firewire/fw-device-cdev.c | 56 | ||||
-rw-r--r-- | drivers/firewire/fw-device-cdev.h | 17 | ||||
-rw-r--r-- | drivers/firewire/fw-device.c | 2 | ||||
-rw-r--r-- | drivers/firewire/fw-device.h | 3 |
4 files changed, 75 insertions, 3 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 | ||
diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h index 739f54fe08cf..4f94471b8078 100644 --- a/drivers/firewire/fw-device-cdev.h +++ b/drivers/firewire/fw-device-cdev.h | |||
@@ -58,15 +58,26 @@ | |||
58 | #define SCODE_1600 0x4 | 58 | #define SCODE_1600 0x4 |
59 | #define SCODE_3200 0x5 | 59 | #define SCODE_3200 0x5 |
60 | 60 | ||
61 | #define FW_CDEV_EVENT_RESPONSE 0x00 | 61 | #define FW_CDEV_EVENT_BUS_RESET 0x00 |
62 | #define FW_CDEV_EVENT_REQUEST 0x01 | 62 | #define FW_CDEV_EVENT_RESPONSE 0x01 |
63 | #define FW_CDEV_EVENT_ISO_INTERRUPT 0x02 | 63 | #define FW_CDEV_EVENT_REQUEST 0x02 |
64 | #define FW_CDEV_EVENT_ISO_INTERRUPT 0x03 | ||
64 | 65 | ||
65 | /* The 'closure' fields are for user space to use. Data passed in the | 66 | /* The 'closure' fields are for user space to use. Data passed in the |
66 | * 'closure' field for a request will be returned in the corresponding | 67 | * 'closure' field for a request will be returned in the corresponding |
67 | * event. It's a 64-bit type so that it's a fixed size type big | 68 | * event. It's a 64-bit type so that it's a fixed size type big |
68 | * enough to hold a pointer on all platforms. */ | 69 | * enough to hold a pointer on all platforms. */ |
69 | 70 | ||
71 | struct fw_cdev_event_bus_reset { | ||
72 | __u32 type; | ||
73 | __u32 node_id; | ||
74 | __u32 local_node_id; | ||
75 | __u32 bm_node_id; | ||
76 | __u32 irm_node_id; | ||
77 | __u32 root_node_id; | ||
78 | __u32 generation; | ||
79 | }; | ||
80 | |||
70 | struct fw_cdev_event_response { | 81 | struct fw_cdev_event_response { |
71 | __u32 type; | 82 | __u32 type; |
72 | __u32 rcode; | 83 | __u32 rcode; |
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index 5599265da4a6..ccc05e511a4f 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c | |||
@@ -535,6 +535,7 @@ static void fw_device_update(struct work_struct *work) | |||
535 | struct fw_device *device = | 535 | struct fw_device *device = |
536 | container_of(work, struct fw_device, work.work); | 536 | container_of(work, struct fw_device, work.work); |
537 | 537 | ||
538 | fw_device_cdev_update(device); | ||
538 | device_for_each_child(&device->device, NULL, update_unit); | 539 | device_for_each_child(&device->device, NULL, update_unit); |
539 | } | 540 | } |
540 | 541 | ||
@@ -564,6 +565,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) | |||
564 | device->node = fw_node_get(node); | 565 | device->node = fw_node_get(node); |
565 | device->node_id = node->node_id; | 566 | device->node_id = node->node_id; |
566 | device->generation = card->generation; | 567 | device->generation = card->generation; |
568 | INIT_LIST_HEAD(&device->client_list); | ||
567 | 569 | ||
568 | /* Set the node data to point back to this device so | 570 | /* Set the node data to point back to this device so |
569 | * FW_NODE_UPDATED callbacks can update the node_id | 571 | * FW_NODE_UPDATED callbacks can update the node_id |
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h index 402a785ceedb..4f731c2b121c 100644 --- a/drivers/firewire/fw-device.h +++ b/drivers/firewire/fw-device.h | |||
@@ -40,6 +40,7 @@ struct fw_device { | |||
40 | struct fw_card *card; | 40 | struct fw_card *card; |
41 | struct device device; | 41 | struct device device; |
42 | struct cdev cdev; | 42 | struct cdev cdev; |
43 | struct list_head client_list; | ||
43 | __be32 *config_rom; | 44 | __be32 *config_rom; |
44 | size_t config_rom_length; | 45 | size_t config_rom_length; |
45 | int config_rom_retries; | 46 | int config_rom_retries; |
@@ -56,6 +57,8 @@ struct fw_device *fw_device_get(struct fw_device *device); | |||
56 | void fw_device_put(struct fw_device *device); | 57 | void fw_device_put(struct fw_device *device); |
57 | int fw_device_enable_phys_dma(struct fw_device *device); | 58 | int fw_device_enable_phys_dma(struct fw_device *device); |
58 | 59 | ||
60 | void fw_device_cdev_update(struct fw_device *device); | ||
61 | |||
59 | struct fw_unit { | 62 | struct fw_unit { |
60 | struct device device; | 63 | struct device device; |
61 | u32 *directory; | 64 | u32 *directory; |