aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-device-cdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firewire/fw-device-cdev.c')
-rw-r--r--drivers/firewire/fw-device-cdev.c65
1 files changed, 48 insertions, 17 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: