aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2007-03-07 12:12:41 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-03-09 16:03:08 -0500
commit97bd9efa5a4d8a70b3bafe0d1e3e1a814fdac5bc (patch)
tree7f405323e9b6ccd690b7673cc4495d35e5926a06
parent1da0c93b31bb8f374a22f4e20dab02fd79f6c7e6 (diff)
firewire: Add a bus reset event type for fw-device-cdev.
Signed-off-by: Kristian Høgsberg <krh@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
-rw-r--r--drivers/firewire/fw-device-cdev.c56
-rw-r--r--drivers/firewire/fw-device-cdev.h17
-rw-r--r--drivers/firewire/fw-device.c2
-rw-r--r--drivers/firewire/fw-device.h3
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
53struct bus_reset {
54 struct event event;
55 struct fw_cdev_event_bus_reset reset;
56};
57
53struct response { 58struct 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
80static inline void __user * 87static 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
192static void
193queue_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
217void 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
180static int ioctl_config_rom(struct client *client, void __user *arg) 231static 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
71struct 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
70struct fw_cdev_event_response { 81struct 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);
56void fw_device_put(struct fw_device *device); 57void fw_device_put(struct fw_device *device);
57int fw_device_enable_phys_dma(struct fw_device *device); 58int fw_device_enable_phys_dma(struct fw_device *device);
58 59
60void fw_device_cdev_update(struct fw_device *device);
61
59struct fw_unit { 62struct fw_unit {
60 struct device device; 63 struct device device;
61 u32 *directory; 64 u32 *directory;