aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/firewire/fw-device-cdev.c65
-rw-r--r--drivers/firewire/fw-device-cdev.h31
2 files changed, 75 insertions, 21 deletions
diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c
index 79e095ea552d..d9f3bb2be1c2 100644
--- a/drivers/firewire/fw-device-cdev.c
+++ b/drivers/firewire/fw-device-cdev.c
@@ -68,6 +68,7 @@ struct iso_interrupt {
68}; 68};
69 69
70struct client { 70struct client {
71 u32 version;
71 struct fw_device *device; 72 struct fw_device *device;
72 spinlock_t lock; 73 spinlock_t lock;
73 struct list_head handler_list; 74 struct list_head handler_list;
@@ -190,11 +191,25 @@ fw_device_op_read(struct file *file,
190} 191}
191 192
192static void 193static void
194fill_bus_reset_event(struct fw_cdev_event_bus_reset *event,
195 struct fw_device *device)
196{
197 struct fw_card *card = device->card;
198
199 event->type = FW_CDEV_EVENT_BUS_RESET;
200 event->node_id = device->node_id;
201 event->local_node_id = card->local_node->node_id;
202 event->bm_node_id = 0; /* FIXME: We don't track the BM. */
203 event->irm_node_id = card->irm_node->node_id;
204 event->root_node_id = card->root_node->node_id;
205 event->generation = card->generation;
206}
207
208static void
193queue_bus_reset_event(struct client *client) 209queue_bus_reset_event(struct client *client)
194{ 210{
195 struct bus_reset *bus_reset; 211 struct bus_reset *bus_reset;
196 struct fw_device *device = client->device; 212 struct fw_device *device = client->device;
197 struct fw_card *card = device->card;
198 213
199 bus_reset = kzalloc(sizeof *bus_reset, GFP_ATOMIC); 214 bus_reset = kzalloc(sizeof *bus_reset, GFP_ATOMIC);
200 if (bus_reset == NULL) { 215 if (bus_reset == NULL) {
@@ -202,13 +217,7 @@ queue_bus_reset_event(struct client *client)
202 return; 217 return;
203 } 218 }
204 219
205 bus_reset->reset.type = FW_CDEV_EVENT_BUS_RESET; 220 fill_bus_reset_event(&bus_reset->reset, device);
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 221
213 queue_event(client, &bus_reset->event, 222 queue_event(client, &bus_reset->event,
214 &bus_reset->reset, sizeof bus_reset->reset, NULL, 0); 223 &bus_reset->reset, sizeof bus_reset->reset, NULL, 0);
@@ -228,14 +237,36 @@ void fw_device_cdev_update(struct fw_device *device)
228 spin_unlock_irqrestore(&card->lock, flags); 237 spin_unlock_irqrestore(&card->lock, flags);
229} 238}
230 239
231static int ioctl_config_rom(struct client *client, void __user *arg) 240static int ioctl_get_info(struct client *client, void __user *arg)
232{ 241{
233 struct fw_cdev_get_config_rom rom; 242 struct fw_cdev_get_info get_info;
243 struct fw_cdev_event_bus_reset bus_reset;
244
245 if (copy_from_user(&get_info, arg, sizeof get_info))
246 return -EFAULT;
247
248 client->version = get_info.version;
249 get_info.version = FW_CDEV_VERSION;
250
251 if (get_info.rom != 0) {
252 void __user *uptr = u64_to_uptr(get_info.rom);
253 size_t length = min(get_info.rom_length,
254 client->device->config_rom_length * 4);
255
256 if (copy_to_user(uptr, client->device->config_rom, length))
257 return -EFAULT;
258 }
259 get_info.rom_length = client->device->config_rom_length * 4;
260
261 if (get_info.bus_reset != 0) {
262 void __user *uptr = u64_to_uptr(get_info.bus_reset);
263
264 fill_bus_reset_event(&bus_reset, client->device);
265 if (copy_to_user(uptr, &bus_reset, sizeof bus_reset))
266 return -EFAULT;
267 }
234 268
235 rom.length = client->device->config_rom_length; 269 if (copy_to_user(arg, &get_info, sizeof get_info))
236 memcpy(rom.data, client->device->config_rom, rom.length * 4);
237 if (copy_to_user(arg, &rom,
238 (char *)&rom.data[rom.length] - (char *)&rom))
239 return -EFAULT; 270 return -EFAULT;
240 271
241 return 0; 272 return 0;
@@ -290,7 +321,7 @@ static ssize_t ioctl_send_request(struct client *client, void __user *arg)
290 } 321 }
291 322
292 fw_send_request(device->card, &response->transaction, 323 fw_send_request(device->card, &response->transaction,
293 request.tcode, 324 request.tcode & 0x1f,
294 device->node->node_id, 325 device->node->node_id,
295 device->card->generation, 326 device->card->generation,
296 device->node->max_speed, 327 device->node->max_speed,
@@ -611,8 +642,8 @@ static int
611dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) 642dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg)
612{ 643{
613 switch (cmd) { 644 switch (cmd) {
614 case FW_CDEV_IOC_GET_CONFIG_ROM: 645 case FW_CDEV_IOC_GET_INFO:
615 return ioctl_config_rom(client, arg); 646 return ioctl_get_info(client, arg);
616 case FW_CDEV_IOC_SEND_REQUEST: 647 case FW_CDEV_IOC_SEND_REQUEST:
617 return ioctl_send_request(client, arg); 648 return ioctl_send_request(client, arg);
618 case FW_CDEV_IOC_ALLOCATE: 649 case FW_CDEV_IOC_ALLOCATE:
diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h
index 8a8b390d5996..c6ea6f32a94b 100644
--- a/drivers/firewire/fw-device-cdev.h
+++ b/drivers/firewire/fw-device-cdev.h
@@ -104,7 +104,7 @@ struct fw_cdev_event_iso_interrupt {
104 __u32 header[0]; 104 __u32 header[0];
105}; 105};
106 106
107#define FW_CDEV_IOC_GET_CONFIG_ROM _IOR('#', 0x00, struct fw_cdev_get_config_rom) 107#define FW_CDEV_IOC_GET_INFO _IO('#', 0x00)
108#define FW_CDEV_IOC_SEND_REQUEST _IO('#', 0x01) 108#define FW_CDEV_IOC_SEND_REQUEST _IO('#', 0x01)
109#define FW_CDEV_IOC_ALLOCATE _IO('#', 0x02) 109#define FW_CDEV_IOC_ALLOCATE _IO('#', 0x02)
110#define FW_CDEV_IOC_SEND_RESPONSE _IO('#', 0x03) 110#define FW_CDEV_IOC_SEND_RESPONSE _IO('#', 0x03)
@@ -114,9 +114,32 @@ struct fw_cdev_event_iso_interrupt {
114#define FW_CDEV_IOC_START_ISO _IO('#', 0x07) 114#define FW_CDEV_IOC_START_ISO _IO('#', 0x07)
115#define FW_CDEV_IOC_STOP_ISO _IO('#', 0x08) 115#define FW_CDEV_IOC_STOP_ISO _IO('#', 0x08)
116 116
117struct fw_cdev_get_config_rom { 117/* FW_CDEV_VERSION History
118 __u32 length; 118 *
119 __u32 data[256]; 119 * 1 Feb 18, 2007: Initial version.
120 */
121#define FW_CDEV_VERSION 1
122
123struct fw_cdev_get_info {
124 /* The version field is just a running serial number. We
125 * never break backwards compatibility. Userspace passes in
126 * the version it expects and the kernel passes back the
127 * highest version it can provide. Even if the structs in
128 * this interface are extended in a later version, the kernel
129 * will not copy back more data than what was present in the
130 * interface version userspace expects. */
131 __u32 version;
132
133 /* If non-zero, at most rom_length bytes of config rom will be
134 * copied into that user space address. In either case,
135 * rom_length is updated with the actual length of the config
136 * rom. */
137 __u32 rom_length;
138 __u64 rom;
139
140 /* If non-zero, a fw_cdev_event_bus_reset struct will be
141 * copied here with the current state of the bus. */
142 __u64 bus_reset;
120}; 143};
121 144
122struct fw_cdev_send_request { 145struct fw_cdev_send_request {