firewire: core: fix fw_send_request kerneldoc comment
[deliverable/linux.git] / drivers / firewire / core-cdev.c
CommitLineData
c781c06d
KH
1/*
2 * Char device for device raw access
19a15b93 3 *
c781c06d 4 * Copyright (C) 2005-2007 Kristian Hoegsberg <krh@bitplanet.net>
19a15b93
KH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
be5bbd67
SR
21#include <linux/compat.h>
22#include <linux/delay.h>
23#include <linux/device.h>
24#include <linux/errno.h>
77c9a5da 25#include <linux/firewire.h>
be5bbd67
SR
26#include <linux/firewire-cdev.h>
27#include <linux/idr.h>
4a9bde9b 28#include <linux/irqflags.h>
b1bda4cd 29#include <linux/jiffies.h>
19a15b93 30#include <linux/kernel.h>
fb443036 31#include <linux/kref.h>
be5bbd67
SR
32#include <linux/mm.h>
33#include <linux/module.h>
d67cfb96 34#include <linux/mutex.h>
19a15b93 35#include <linux/poll.h>
a99bbaf5 36#include <linux/sched.h>
cf417e54 37#include <linux/spinlock.h>
281e2032 38#include <linux/string.h>
be5bbd67 39#include <linux/time.h>
e034d242 40#include <linux/uaccess.h>
be5bbd67
SR
41#include <linux/vmalloc.h>
42#include <linux/wait.h>
b1bda4cd 43#include <linux/workqueue.h>
be5bbd67 44
a64408b9 45#include <asm/system.h>
be5bbd67 46
77c9a5da 47#include "core.h"
19a15b93 48
604f4516
SR
49/*
50 * ABI version history is documented in linux/firewire-cdev.h.
51 */
e205597d
SR
52#define FW_CDEV_KERNEL_VERSION 4
53#define FW_CDEV_VERSION_EVENT_REQUEST2 4
604f4516 54
19a15b93 55struct client {
344bbc4d 56 u32 version;
19a15b93 57 struct fw_device *device;
45ee3199 58
19a15b93 59 spinlock_t lock;
45ee3199
JF
60 bool in_shutdown;
61 struct idr resource_idr;
19a15b93 62 struct list_head event_list;
19a15b93 63 wait_queue_head_t wait;
da8ecffa 64 u64 bus_reset_closure;
9aad8125 65
19a15b93 66 struct fw_iso_context *iso_context;
abaa5743 67 u64 iso_closure;
9aad8125
KH
68 struct fw_iso_buffer buffer;
69 unsigned long vm_start;
97bd9efa
KH
70
71 struct list_head link;
fb443036 72 struct kref kref;
19a15b93
KH
73};
74
fb443036
SR
75static inline void client_get(struct client *client)
76{
77 kref_get(&client->kref);
78}
79
80static void client_release(struct kref *kref)
81{
82 struct client *client = container_of(kref, struct client, kref);
83
84 fw_device_put(client->device);
85 kfree(client);
86}
87
88static void client_put(struct client *client)
89{
90 kref_put(&client->kref, client_release);
91}
92
97c18b7f
SR
93struct client_resource;
94typedef void (*client_resource_release_fn_t)(struct client *,
95 struct client_resource *);
96struct client_resource {
97 client_resource_release_fn_t release;
98 int handle;
99};
100
101struct address_handler_resource {
102 struct client_resource resource;
103 struct fw_address_handler handler;
104 __u64 closure;
105 struct client *client;
106};
107
108struct outbound_transaction_resource {
109 struct client_resource resource;
110 struct fw_transaction transaction;
111};
112
113struct inbound_transaction_resource {
114 struct client_resource resource;
08bd34c9 115 struct fw_card *card;
97c18b7f
SR
116 struct fw_request *request;
117 void *data;
118 size_t length;
119};
120
121struct descriptor_resource {
122 struct client_resource resource;
123 struct fw_descriptor descriptor;
124 u32 data[0];
125};
126
b1bda4cd
JFSR
127struct iso_resource {
128 struct client_resource resource;
129 struct client *client;
130 /* Schedule work and access todo only with client->lock held. */
131 struct delayed_work work;
1ec3c026
SR
132 enum {ISO_RES_ALLOC, ISO_RES_REALLOC, ISO_RES_DEALLOC,
133 ISO_RES_ALLOC_ONCE, ISO_RES_DEALLOC_ONCE,} todo;
b1bda4cd
JFSR
134 int generation;
135 u64 channels;
136 s32 bandwidth;
6fdc0370 137 __be32 transaction_data[2];
b1bda4cd
JFSR
138 struct iso_resource_event *e_alloc, *e_dealloc;
139};
140
b1bda4cd
JFSR
141static void release_iso_resource(struct client *, struct client_resource *);
142
9fb551bf
SR
143static void schedule_iso_resource(struct iso_resource *r, unsigned long delay)
144{
145 client_get(r->client);
146 if (!schedule_delayed_work(&r->work, delay))
147 client_put(r->client);
148}
149
150static void schedule_if_iso_resource(struct client_resource *resource)
151{
152 if (resource->release == release_iso_resource)
153 schedule_iso_resource(container_of(resource,
154 struct iso_resource, resource), 0);
155}
156
97c18b7f
SR
157/*
158 * dequeue_event() just kfree()'s the event, so the event has to be
159 * the first field in a struct XYZ_event.
160 */
161struct event {
162 struct { void *data; size_t size; } v[2];
163 struct list_head link;
164};
165
166struct bus_reset_event {
167 struct event event;
168 struct fw_cdev_event_bus_reset reset;
169};
170
171struct outbound_transaction_event {
172 struct event event;
173 struct client *client;
174 struct outbound_transaction_resource r;
175 struct fw_cdev_event_response response;
176};
177
178struct inbound_transaction_event {
179 struct event event;
e205597d
SR
180 union {
181 struct fw_cdev_event_request request;
182 struct fw_cdev_event_request2 request2;
183 } req;
97c18b7f
SR
184};
185
186struct iso_interrupt_event {
187 struct event event;
188 struct fw_cdev_event_iso_interrupt interrupt;
189};
190
b1bda4cd
JFSR
191struct iso_resource_event {
192 struct event event;
e21fcf79 193 struct fw_cdev_event_iso_resource iso_resource;
b1bda4cd
JFSR
194};
195
53dca511 196static inline void __user *u64_to_uptr(__u64 value)
19a15b93
KH
197{
198 return (void __user *)(unsigned long)value;
199}
200
53dca511 201static inline __u64 uptr_to_u64(void __user *ptr)
19a15b93
KH
202{
203 return (__u64)(unsigned long)ptr;
204}
205
206static int fw_device_op_open(struct inode *inode, struct file *file)
207{
208 struct fw_device *device;
209 struct client *client;
210
96b19062 211 device = fw_device_get_by_devt(inode->i_rdev);
a3aca3da
KH
212 if (device == NULL)
213 return -ENODEV;
19a15b93 214
551f4cb9
JF
215 if (fw_device_is_shutdown(device)) {
216 fw_device_put(device);
217 return -ENODEV;
218 }
219
2d826cc5 220 client = kzalloc(sizeof(*client), GFP_KERNEL);
96b19062
SR
221 if (client == NULL) {
222 fw_device_put(device);
19a15b93 223 return -ENOMEM;
96b19062 224 }
19a15b93 225
96b19062 226 client->device = device;
19a15b93 227 spin_lock_init(&client->lock);
45ee3199
JF
228 idr_init(&client->resource_idr);
229 INIT_LIST_HEAD(&client->event_list);
19a15b93 230 init_waitqueue_head(&client->wait);
fb443036 231 kref_init(&client->kref);
19a15b93
KH
232
233 file->private_data = client;
234
d67cfb96 235 mutex_lock(&device->client_list_mutex);
97bd9efa 236 list_add_tail(&client->link, &device->client_list);
d67cfb96 237 mutex_unlock(&device->client_list_mutex);
97bd9efa 238
3ac26b2e 239 return nonseekable_open(inode, file);
19a15b93
KH
240}
241
242static void queue_event(struct client *client, struct event *event,
243 void *data0, size_t size0, void *data1, size_t size1)
244{
245 unsigned long flags;
246
247 event->v[0].data = data0;
248 event->v[0].size = size0;
249 event->v[1].data = data1;
250 event->v[1].size = size1;
251
252 spin_lock_irqsave(&client->lock, flags);
45ee3199
JF
253 if (client->in_shutdown)
254 kfree(event);
255 else
256 list_add_tail(&event->link, &client->event_list);
19a15b93 257 spin_unlock_irqrestore(&client->lock, flags);
83431cba
JF
258
259 wake_up_interruptible(&client->wait);
19a15b93
KH
260}
261
53dca511
SR
262static int dequeue_event(struct client *client,
263 char __user *buffer, size_t count)
19a15b93 264{
19a15b93
KH
265 struct event *event;
266 size_t size, total;
2dbd7d7e 267 int i, ret;
19a15b93 268
2dbd7d7e
SR
269 ret = wait_event_interruptible(client->wait,
270 !list_empty(&client->event_list) ||
271 fw_device_is_shutdown(client->device));
272 if (ret < 0)
273 return ret;
19a15b93 274
2603bf21
KH
275 if (list_empty(&client->event_list) &&
276 fw_device_is_shutdown(client->device))
277 return -ENODEV;
19a15b93 278
3ba94986 279 spin_lock_irq(&client->lock);
a459b8ab 280 event = list_first_entry(&client->event_list, struct event, link);
19a15b93 281 list_del(&event->link);
3ba94986 282 spin_unlock_irq(&client->lock);
19a15b93 283
19a15b93
KH
284 total = 0;
285 for (i = 0; i < ARRAY_SIZE(event->v) && total < count; i++) {
286 size = min(event->v[i].size, count - total);
2603bf21 287 if (copy_to_user(buffer + total, event->v[i].data, size)) {
2dbd7d7e 288 ret = -EFAULT;
19a15b93 289 goto out;
2603bf21 290 }
19a15b93
KH
291 total += size;
292 }
2dbd7d7e 293 ret = total;
19a15b93
KH
294
295 out:
296 kfree(event);
297
2dbd7d7e 298 return ret;
19a15b93
KH
299}
300
53dca511
SR
301static ssize_t fw_device_op_read(struct file *file, char __user *buffer,
302 size_t count, loff_t *offset)
19a15b93
KH
303{
304 struct client *client = file->private_data;
305
306 return dequeue_event(client, buffer, count);
307}
308
53dca511
SR
309static void fill_bus_reset_event(struct fw_cdev_event_bus_reset *event,
310 struct client *client)
344bbc4d 311{
da8ecffa 312 struct fw_card *card = client->device->card;
cf417e54 313
3ba94986 314 spin_lock_irq(&card->lock);
344bbc4d 315
da8ecffa 316 event->closure = client->bus_reset_closure;
344bbc4d 317 event->type = FW_CDEV_EVENT_BUS_RESET;
cf5a56ac 318 event->generation = client->device->generation;
da8ecffa 319 event->node_id = client->device->node_id;
344bbc4d 320 event->local_node_id = card->local_node->node_id;
250b2b6d 321 event->bm_node_id = card->bm_node_id;
344bbc4d
KH
322 event->irm_node_id = card->irm_node->node_id;
323 event->root_node_id = card->root_node->node_id;
cf417e54 324
3ba94986 325 spin_unlock_irq(&card->lock);
344bbc4d
KH
326}
327
53dca511
SR
328static void for_each_client(struct fw_device *device,
329 void (*callback)(struct client *client))
2603bf21 330{
2603bf21 331 struct client *c;
2603bf21 332
d67cfb96 333 mutex_lock(&device->client_list_mutex);
2603bf21
KH
334 list_for_each_entry(c, &device->client_list, link)
335 callback(c);
d67cfb96 336 mutex_unlock(&device->client_list_mutex);
2603bf21
KH
337}
338
b1bda4cd
JFSR
339static int schedule_reallocations(int id, void *p, void *data)
340{
9fb551bf 341 schedule_if_iso_resource(p);
b1bda4cd 342
b1bda4cd
JFSR
343 return 0;
344}
345
53dca511 346static void queue_bus_reset_event(struct client *client)
97bd9efa 347{
97c18b7f 348 struct bus_reset_event *e;
97bd9efa 349
97c18b7f
SR
350 e = kzalloc(sizeof(*e), GFP_KERNEL);
351 if (e == NULL) {
97bd9efa
KH
352 fw_notify("Out of memory when allocating bus reset event\n");
353 return;
354 }
355
97c18b7f 356 fill_bus_reset_event(&e->reset, client);
97bd9efa 357
97c18b7f
SR
358 queue_event(client, &e->event,
359 &e->reset, sizeof(e->reset), NULL, 0);
b1bda4cd
JFSR
360
361 spin_lock_irq(&client->lock);
362 idr_for_each(&client->resource_idr, schedule_reallocations, client);
363 spin_unlock_irq(&client->lock);
97bd9efa
KH
364}
365
366void fw_device_cdev_update(struct fw_device *device)
367{
2603bf21
KH
368 for_each_client(device, queue_bus_reset_event);
369}
97bd9efa 370
2603bf21
KH
371static void wake_up_client(struct client *client)
372{
373 wake_up_interruptible(&client->wait);
374}
97bd9efa 375
2603bf21
KH
376void fw_device_cdev_remove(struct fw_device *device)
377{
378 for_each_client(device, wake_up_client);
97bd9efa
KH
379}
380
6e95dea7
SR
381union ioctl_arg {
382 struct fw_cdev_get_info get_info;
383 struct fw_cdev_send_request send_request;
384 struct fw_cdev_allocate allocate;
385 struct fw_cdev_deallocate deallocate;
386 struct fw_cdev_send_response send_response;
387 struct fw_cdev_initiate_bus_reset initiate_bus_reset;
388 struct fw_cdev_add_descriptor add_descriptor;
389 struct fw_cdev_remove_descriptor remove_descriptor;
390 struct fw_cdev_create_iso_context create_iso_context;
391 struct fw_cdev_queue_iso queue_iso;
392 struct fw_cdev_start_iso start_iso;
393 struct fw_cdev_stop_iso stop_iso;
394 struct fw_cdev_get_cycle_timer get_cycle_timer;
395 struct fw_cdev_allocate_iso_resource allocate_iso_resource;
396 struct fw_cdev_send_stream_packet send_stream_packet;
397 struct fw_cdev_get_cycle_timer2 get_cycle_timer2;
398};
399
400static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
19a15b93 401{
6e95dea7 402 struct fw_cdev_get_info *a = &arg->get_info;
344bbc4d 403 struct fw_cdev_event_bus_reset bus_reset;
c9755e14 404 unsigned long ret = 0;
344bbc4d 405
6e95dea7 406 client->version = a->version;
604f4516 407 a->version = FW_CDEV_KERNEL_VERSION;
6e95dea7 408 a->card = client->device->card->index;
344bbc4d 409
c9755e14
SR
410 down_read(&fw_device_rwsem);
411
6e95dea7
SR
412 if (a->rom != 0) {
413 size_t want = a->rom_length;
d84702a5 414 size_t have = client->device->config_rom_length * 4;
344bbc4d 415
6e95dea7
SR
416 ret = copy_to_user(u64_to_uptr(a->rom),
417 client->device->config_rom, min(want, have));
344bbc4d 418 }
6e95dea7 419 a->rom_length = client->device->config_rom_length * 4;
344bbc4d 420
c9755e14
SR
421 up_read(&fw_device_rwsem);
422
423 if (ret != 0)
424 return -EFAULT;
425
6e95dea7
SR
426 client->bus_reset_closure = a->bus_reset_closure;
427 if (a->bus_reset != 0) {
da8ecffa 428 fill_bus_reset_event(&bus_reset, client);
6e95dea7
SR
429 if (copy_to_user(u64_to_uptr(a->bus_reset),
430 &bus_reset, sizeof(bus_reset)))
344bbc4d
KH
431 return -EFAULT;
432 }
19a15b93 433
19a15b93
KH
434 return 0;
435}
436
53dca511
SR
437static int add_client_resource(struct client *client,
438 struct client_resource *resource, gfp_t gfp_mask)
3964a449
KH
439{
440 unsigned long flags;
45ee3199
JF
441 int ret;
442
443 retry:
444 if (idr_pre_get(&client->resource_idr, gfp_mask) == 0)
445 return -ENOMEM;
3964a449
KH
446
447 spin_lock_irqsave(&client->lock, flags);
45ee3199
JF
448 if (client->in_shutdown)
449 ret = -ECANCELED;
450 else
451 ret = idr_get_new(&client->resource_idr, resource,
452 &resource->handle);
b1bda4cd 453 if (ret >= 0) {
fb443036 454 client_get(client);
9fb551bf 455 schedule_if_iso_resource(resource);
b1bda4cd 456 }
3964a449 457 spin_unlock_irqrestore(&client->lock, flags);
45ee3199
JF
458
459 if (ret == -EAGAIN)
460 goto retry;
461
462 return ret < 0 ? ret : 0;
3964a449
KH
463}
464
53dca511
SR
465static int release_client_resource(struct client *client, u32 handle,
466 client_resource_release_fn_t release,
e21fcf79 467 struct client_resource **return_resource)
3964a449 468{
e21fcf79 469 struct client_resource *resource;
3964a449 470
3ba94986 471 spin_lock_irq(&client->lock);
45ee3199 472 if (client->in_shutdown)
e21fcf79 473 resource = NULL;
45ee3199 474 else
e21fcf79
SR
475 resource = idr_find(&client->resource_idr, handle);
476 if (resource && resource->release == release)
45ee3199 477 idr_remove(&client->resource_idr, handle);
3ba94986 478 spin_unlock_irq(&client->lock);
3964a449 479
e21fcf79 480 if (!(resource && resource->release == release))
3964a449
KH
481 return -EINVAL;
482
e21fcf79
SR
483 if (return_resource)
484 *return_resource = resource;
3964a449 485 else
e21fcf79 486 resource->release(client, resource);
3964a449 487
fb443036
SR
488 client_put(client);
489
3964a449
KH
490 return 0;
491}
492
53dca511
SR
493static void release_transaction(struct client *client,
494 struct client_resource *resource)
3964a449 495{
97c18b7f
SR
496 struct outbound_transaction_resource *r = container_of(resource,
497 struct outbound_transaction_resource, resource);
3964a449 498
97c18b7f 499 fw_cancel_transaction(client->device->card, &r->transaction);
3964a449
KH
500}
501
53dca511
SR
502static void complete_transaction(struct fw_card *card, int rcode,
503 void *payload, size_t length, void *data)
19a15b93 504{
97c18b7f
SR
505 struct outbound_transaction_event *e = data;
506 struct fw_cdev_event_response *rsp = &e->response;
507 struct client *client = e->client;
28cf6a04 508 unsigned long flags;
19a15b93 509
97c18b7f
SR
510 if (length < rsp->length)
511 rsp->length = length;
19a15b93 512 if (rcode == RCODE_COMPLETE)
97c18b7f 513 memcpy(rsp->data, payload, rsp->length);
19a15b93 514
28cf6a04 515 spin_lock_irqsave(&client->lock, flags);
45ee3199 516 /*
fb443036
SR
517 * 1. If called while in shutdown, the idr tree must be left untouched.
518 * The idr handle will be removed and the client reference will be
519 * dropped later.
520 * 2. If the call chain was release_client_resource ->
521 * release_transaction -> complete_transaction (instead of a normal
522 * conclusion of the transaction), i.e. if this resource was already
523 * unregistered from the idr, the client reference will be dropped
524 * by release_client_resource and we must not drop it here.
45ee3199 525 */
fb443036 526 if (!client->in_shutdown &&
97c18b7f
SR
527 idr_find(&client->resource_idr, e->r.resource.handle)) {
528 idr_remove(&client->resource_idr, e->r.resource.handle);
fb443036
SR
529 /* Drop the idr's reference */
530 client_put(client);
531 }
28cf6a04
KH
532 spin_unlock_irqrestore(&client->lock, flags);
533
97c18b7f
SR
534 rsp->type = FW_CDEV_EVENT_RESPONSE;
535 rsp->rcode = rcode;
8401d92b
DM
536
537 /*
97c18b7f 538 * In the case that sizeof(*rsp) doesn't align with the position of the
8401d92b
DM
539 * data, and the read is short, preserve an extra copy of the data
540 * to stay compatible with a pre-2.6.27 bug. Since the bug is harmless
541 * for short reads and some apps depended on it, this is both safe
542 * and prudent for compatibility.
543 */
97c18b7f
SR
544 if (rsp->length <= sizeof(*rsp) - offsetof(typeof(*rsp), data))
545 queue_event(client, &e->event, rsp, sizeof(*rsp),
546 rsp->data, rsp->length);
8401d92b 547 else
97c18b7f 548 queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length,
8401d92b 549 NULL, 0);
fb443036
SR
550
551 /* Drop the transaction callback's reference */
552 client_put(client);
19a15b93
KH
553}
554
acfe8333
JFSR
555static int init_request(struct client *client,
556 struct fw_cdev_send_request *request,
557 int destination_id, int speed)
19a15b93 558{
97c18b7f 559 struct outbound_transaction_event *e;
1f3125af 560 int ret;
19a15b93 561
18e9b10f
SR
562 if (request->tcode != TCODE_STREAM_DATA &&
563 (request->length > 4096 || request->length > 512 << speed))
5d3fd692 564 return -EIO;
19a15b93 565
a8e93f3d
CL
566 if (request->tcode == TCODE_WRITE_QUADLET_REQUEST &&
567 request->length < 4)
568 return -EINVAL;
569
97c18b7f
SR
570 e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL);
571 if (e == NULL)
19a15b93
KH
572 return -ENOMEM;
573
97c18b7f
SR
574 e->client = client;
575 e->response.length = request->length;
576 e->response.closure = request->closure;
19a15b93 577
4f259223 578 if (request->data &&
97c18b7f 579 copy_from_user(e->response.data,
4f259223 580 u64_to_uptr(request->data), request->length)) {
1f3125af 581 ret = -EFAULT;
45ee3199 582 goto failed;
1f3125af
SR
583 }
584
97c18b7f
SR
585 e->r.resource.release = release_transaction;
586 ret = add_client_resource(client, &e->r.resource, GFP_KERNEL);
45ee3199
JF
587 if (ret < 0)
588 goto failed;
28cf6a04 589
fb443036
SR
590 /* Get a reference for the transaction callback */
591 client_get(client);
592
acfe8333 593 fw_send_request(client->device->card, &e->r.transaction,
664d8010
SR
594 request->tcode, destination_id, request->generation,
595 speed, request->offset, e->response.data,
596 request->length, complete_transaction, e);
597 return 0;
19a15b93 598
45ee3199 599 failed:
97c18b7f 600 kfree(e);
1f3125af
SR
601
602 return ret;
19a15b93
KH
603}
604
6e95dea7 605static int ioctl_send_request(struct client *client, union ioctl_arg *arg)
acfe8333 606{
6e95dea7 607 switch (arg->send_request.tcode) {
acfe8333
JFSR
608 case TCODE_WRITE_QUADLET_REQUEST:
609 case TCODE_WRITE_BLOCK_REQUEST:
610 case TCODE_READ_QUADLET_REQUEST:
611 case TCODE_READ_BLOCK_REQUEST:
612 case TCODE_LOCK_MASK_SWAP:
613 case TCODE_LOCK_COMPARE_SWAP:
614 case TCODE_LOCK_FETCH_ADD:
615 case TCODE_LOCK_LITTLE_ADD:
616 case TCODE_LOCK_BOUNDED_ADD:
617 case TCODE_LOCK_WRAP_ADD:
618 case TCODE_LOCK_VENDOR_DEPENDENT:
619 break;
620 default:
621 return -EINVAL;
622 }
623
6e95dea7 624 return init_request(client, &arg->send_request, client->device->node_id,
acfe8333
JFSR
625 client->device->max_speed);
626}
627
281e2032
SR
628static inline bool is_fcp_request(struct fw_request *request)
629{
630 return request == NULL;
631}
632
53dca511
SR
633static void release_request(struct client *client,
634 struct client_resource *resource)
3964a449 635{
97c18b7f
SR
636 struct inbound_transaction_resource *r = container_of(resource,
637 struct inbound_transaction_resource, resource);
3964a449 638
281e2032
SR
639 if (is_fcp_request(r->request))
640 kfree(r->data);
641 else
08bd34c9 642 fw_send_response(r->card, r->request, RCODE_CONFLICT_ERROR);
0244f573
SR
643
644 fw_card_put(r->card);
97c18b7f 645 kfree(r);
3964a449
KH
646}
647
97c18b7f 648static void handle_request(struct fw_card *card, struct fw_request *request,
53dca511 649 int tcode, int destination, int source,
33e553fe 650 int generation, unsigned long long offset,
53dca511 651 void *payload, size_t length, void *callback_data)
19a15b93 652{
97c18b7f
SR
653 struct address_handler_resource *handler = callback_data;
654 struct inbound_transaction_resource *r;
655 struct inbound_transaction_event *e;
e205597d 656 size_t event_size0;
281e2032 657 void *fcp_frame = NULL;
45ee3199 658 int ret;
19a15b93 659
0244f573
SR
660 /* card may be different from handler->client->device->card */
661 fw_card_get(card);
662
97c18b7f 663 r = kmalloc(sizeof(*r), GFP_ATOMIC);
2d826cc5 664 e = kmalloc(sizeof(*e), GFP_ATOMIC);
97c18b7f 665 if (r == NULL || e == NULL)
45ee3199 666 goto failed;
19a15b93 667
08bd34c9 668 r->card = card;
97c18b7f
SR
669 r->request = request;
670 r->data = payload;
671 r->length = length;
19a15b93 672
281e2032
SR
673 if (is_fcp_request(request)) {
674 /*
675 * FIXME: Let core-transaction.c manage a
676 * single reference-counted copy?
677 */
678 fcp_frame = kmemdup(payload, length, GFP_ATOMIC);
679 if (fcp_frame == NULL)
680 goto failed;
681
682 r->data = fcp_frame;
683 }
684
97c18b7f
SR
685 r->resource.release = release_request;
686 ret = add_client_resource(handler->client, &r->resource, GFP_ATOMIC);
45ee3199
JF
687 if (ret < 0)
688 goto failed;
19a15b93 689
e205597d
SR
690 if (handler->client->version < FW_CDEV_VERSION_EVENT_REQUEST2) {
691 struct fw_cdev_event_request *req = &e->req.request;
692
693 if (tcode & 0x10)
694 tcode = TCODE_LOCK_REQUEST;
695
696 req->type = FW_CDEV_EVENT_REQUEST;
697 req->tcode = tcode;
698 req->offset = offset;
699 req->length = length;
700 req->handle = r->resource.handle;
701 req->closure = handler->closure;
702 event_size0 = sizeof(*req);
703 } else {
704 struct fw_cdev_event_request2 *req = &e->req.request2;
705
706 req->type = FW_CDEV_EVENT_REQUEST2;
707 req->tcode = tcode;
708 req->offset = offset;
709 req->source_node_id = source;
710 req->destination_node_id = destination;
711 req->card = card->index;
712 req->generation = generation;
713 req->length = length;
714 req->handle = r->resource.handle;
715 req->closure = handler->closure;
716 event_size0 = sizeof(*req);
717 }
19a15b93 718
97c18b7f 719 queue_event(handler->client, &e->event,
e205597d 720 &e->req, event_size0, r->data, length);
45ee3199
JF
721 return;
722
723 failed:
97c18b7f 724 kfree(r);
45ee3199 725 kfree(e);
281e2032
SR
726 kfree(fcp_frame);
727
728 if (!is_fcp_request(request))
db5d247a 729 fw_send_response(card, request, RCODE_CONFLICT_ERROR);
0244f573
SR
730
731 fw_card_put(card);
19a15b93
KH
732}
733
53dca511
SR
734static void release_address_handler(struct client *client,
735 struct client_resource *resource)
3964a449 736{
97c18b7f
SR
737 struct address_handler_resource *r =
738 container_of(resource, struct address_handler_resource, resource);
3964a449 739
97c18b7f
SR
740 fw_core_remove_address_handler(&r->handler);
741 kfree(r);
3964a449
KH
742}
743
6e95dea7 744static int ioctl_allocate(struct client *client, union ioctl_arg *arg)
19a15b93 745{
6e95dea7 746 struct fw_cdev_allocate *a = &arg->allocate;
97c18b7f 747 struct address_handler_resource *r;
19a15b93 748 struct fw_address_region region;
45ee3199 749 int ret;
19a15b93 750
97c18b7f
SR
751 r = kmalloc(sizeof(*r), GFP_KERNEL);
752 if (r == NULL)
19a15b93
KH
753 return -ENOMEM;
754
6e95dea7
SR
755 region.start = a->offset;
756 region.end = a->offset + a->length;
757 r->handler.length = a->length;
97c18b7f 758 r->handler.address_callback = handle_request;
6e95dea7
SR
759 r->handler.callback_data = r;
760 r->closure = a->closure;
761 r->client = client;
19a15b93 762
97c18b7f 763 ret = fw_core_add_address_handler(&r->handler, &region);
3e0b5f0d 764 if (ret < 0) {
97c18b7f 765 kfree(r);
3e0b5f0d 766 return ret;
19a15b93
KH
767 }
768
97c18b7f
SR
769 r->resource.release = release_address_handler;
770 ret = add_client_resource(client, &r->resource, GFP_KERNEL);
45ee3199 771 if (ret < 0) {
97c18b7f 772 release_address_handler(client, &r->resource);
45ee3199
JF
773 return ret;
774 }
6e95dea7 775 a->handle = r->resource.handle;
19a15b93
KH
776
777 return 0;
778}
779
6e95dea7 780static int ioctl_deallocate(struct client *client, union ioctl_arg *arg)
9472316b 781{
6e95dea7 782 return release_client_resource(client, arg->deallocate.handle,
45ee3199 783 release_address_handler, NULL);
9472316b
KH
784}
785
6e95dea7 786static int ioctl_send_response(struct client *client, union ioctl_arg *arg)
19a15b93 787{
6e95dea7 788 struct fw_cdev_send_response *a = &arg->send_response;
3964a449 789 struct client_resource *resource;
97c18b7f 790 struct inbound_transaction_resource *r;
7e44c0b5 791 int ret = 0;
19a15b93 792
6e95dea7 793 if (release_client_resource(client, a->handle,
45ee3199 794 release_request, &resource) < 0)
19a15b93 795 return -EINVAL;
45ee3199 796
97c18b7f
SR
797 r = container_of(resource, struct inbound_transaction_resource,
798 resource);
281e2032
SR
799 if (is_fcp_request(r->request))
800 goto out;
801
a10c0ce7
CL
802 if (a->length != fw_get_response_length(r->request)) {
803 ret = -EINVAL;
804 kfree(r->request);
805 goto out;
806 }
807 if (copy_from_user(r->data, u64_to_uptr(a->data), a->length)) {
281e2032
SR
808 ret = -EFAULT;
809 kfree(r->request);
810 goto out;
7e44c0b5 811 }
08bd34c9 812 fw_send_response(r->card, r->request, a->rcode);
7e44c0b5 813 out:
0244f573 814 fw_card_put(r->card);
19a15b93
KH
815 kfree(r);
816
7e44c0b5 817 return ret;
19a15b93
KH
818}
819
6e95dea7 820static int ioctl_initiate_bus_reset(struct client *client, union ioctl_arg *arg)
5371842b 821{
6e95dea7
SR
822 return fw_core_initiate_bus_reset(client->device->card,
823 arg->initiate_bus_reset.type == FW_CDEV_SHORT_RESET);
5371842b
KH
824}
825
3964a449
KH
826static void release_descriptor(struct client *client,
827 struct client_resource *resource)
828{
97c18b7f
SR
829 struct descriptor_resource *r =
830 container_of(resource, struct descriptor_resource, resource);
3964a449 831
97c18b7f
SR
832 fw_core_remove_descriptor(&r->descriptor);
833 kfree(r);
3964a449
KH
834}
835
6e95dea7 836static int ioctl_add_descriptor(struct client *client, union ioctl_arg *arg)
66dea3e5 837{
6e95dea7 838 struct fw_cdev_add_descriptor *a = &arg->add_descriptor;
97c18b7f 839 struct descriptor_resource *r;
45ee3199 840 int ret;
66dea3e5 841
de487da8 842 /* Access policy: Allow this ioctl only on local nodes' device files. */
92368890 843 if (!client->device->is_local)
de487da8
SR
844 return -ENOSYS;
845
6e95dea7 846 if (a->length > 256)
66dea3e5
KH
847 return -EINVAL;
848
6e95dea7 849 r = kmalloc(sizeof(*r) + a->length * 4, GFP_KERNEL);
97c18b7f 850 if (r == NULL)
66dea3e5
KH
851 return -ENOMEM;
852
6e95dea7 853 if (copy_from_user(r->data, u64_to_uptr(a->data), a->length * 4)) {
45ee3199
JF
854 ret = -EFAULT;
855 goto failed;
66dea3e5
KH
856 }
857
6e95dea7
SR
858 r->descriptor.length = a->length;
859 r->descriptor.immediate = a->immediate;
860 r->descriptor.key = a->key;
97c18b7f 861 r->descriptor.data = r->data;
66dea3e5 862
97c18b7f 863 ret = fw_core_add_descriptor(&r->descriptor);
45ee3199
JF
864 if (ret < 0)
865 goto failed;
66dea3e5 866
97c18b7f
SR
867 r->resource.release = release_descriptor;
868 ret = add_client_resource(client, &r->resource, GFP_KERNEL);
45ee3199 869 if (ret < 0) {
97c18b7f 870 fw_core_remove_descriptor(&r->descriptor);
45ee3199
JF
871 goto failed;
872 }
6e95dea7 873 a->handle = r->resource.handle;
66dea3e5
KH
874
875 return 0;
45ee3199 876 failed:
97c18b7f 877 kfree(r);
45ee3199
JF
878
879 return ret;
66dea3e5
KH
880}
881
6e95dea7 882static int ioctl_remove_descriptor(struct client *client, union ioctl_arg *arg)
66dea3e5 883{
6e95dea7 884 return release_client_resource(client, arg->remove_descriptor.handle,
45ee3199 885 release_descriptor, NULL);
66dea3e5
KH
886}
887
53dca511
SR
888static void iso_callback(struct fw_iso_context *context, u32 cycle,
889 size_t header_length, void *header, void *data)
19a15b93
KH
890{
891 struct client *client = data;
97c18b7f 892 struct iso_interrupt_event *e;
19a15b93 893
56d04cb1 894 e = kmalloc(sizeof(*e) + header_length, GFP_ATOMIC);
97c18b7f 895 if (e == NULL)
19a15b93
KH
896 return;
897
97c18b7f
SR
898 e->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT;
899 e->interrupt.closure = client->iso_closure;
900 e->interrupt.cycle = cycle;
901 e->interrupt.header_length = header_length;
902 memcpy(e->interrupt.header, header, header_length);
903 queue_event(client, &e->event, &e->interrupt,
904 sizeof(e->interrupt) + header_length, NULL, 0);
19a15b93
KH
905}
906
6e95dea7 907static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg)
19a15b93 908{
6e95dea7 909 struct fw_cdev_create_iso_context *a = &arg->create_iso_context;
24315c5e 910 struct fw_iso_context *context;
19a15b93 911
6e95dea7 912 if (a->channel > 63)
21efb3cf
KH
913 return -EINVAL;
914
6e95dea7 915 switch (a->type) {
c70dc788 916 case FW_ISO_CONTEXT_RECEIVE:
6e95dea7 917 if (a->header_size < 4 || (a->header_size & 3))
c70dc788 918 return -EINVAL;
c70dc788
KH
919 break;
920
921 case FW_ISO_CONTEXT_TRANSMIT:
6e95dea7 922 if (a->speed > SCODE_3200)
c70dc788 923 return -EINVAL;
c70dc788
KH
924 break;
925
926 default:
21efb3cf 927 return -EINVAL;
c70dc788
KH
928 }
929
6e95dea7
SR
930 context = fw_iso_context_create(client->device->card, a->type,
931 a->channel, a->speed, a->header_size,
932 iso_callback, client);
24315c5e
KH
933 if (IS_ERR(context))
934 return PTR_ERR(context);
935
bdfe273e
CL
936 /* We only support one context at this time. */
937 spin_lock_irq(&client->lock);
938 if (client->iso_context != NULL) {
939 spin_unlock_irq(&client->lock);
940 fw_iso_context_destroy(context);
941 return -EBUSY;
942 }
6e95dea7 943 client->iso_closure = a->closure;
24315c5e 944 client->iso_context = context;
bdfe273e 945 spin_unlock_irq(&client->lock);
19a15b93 946
6e95dea7 947 a->handle = 0;
abaa5743 948
19a15b93
KH
949 return 0;
950}
951
1ca31ae7
KH
952/* Macros for decoding the iso packet control header. */
953#define GET_PAYLOAD_LENGTH(v) ((v) & 0xffff)
954#define GET_INTERRUPT(v) (((v) >> 16) & 0x01)
955#define GET_SKIP(v) (((v) >> 17) & 0x01)
7a100344
SR
956#define GET_TAG(v) (((v) >> 18) & 0x03)
957#define GET_SY(v) (((v) >> 20) & 0x0f)
1ca31ae7
KH
958#define GET_HEADER_LENGTH(v) (((v) >> 24) & 0xff)
959
6e95dea7 960static int ioctl_queue_iso(struct client *client, union ioctl_arg *arg)
19a15b93 961{
6e95dea7 962 struct fw_cdev_queue_iso *a = &arg->queue_iso;
19a15b93 963 struct fw_cdev_iso_packet __user *p, *end, *next;
9b32d5f3 964 struct fw_iso_context *ctx = client->iso_context;
ef370ee7 965 unsigned long payload, buffer_end, header_length;
1ca31ae7 966 u32 control;
19a15b93
KH
967 int count;
968 struct {
969 struct fw_iso_packet packet;
970 u8 header[256];
971 } u;
972
6e95dea7 973 if (ctx == NULL || a->handle != 0)
19a15b93 974 return -EINVAL;
19a15b93 975
c781c06d
KH
976 /*
977 * If the user passes a non-NULL data pointer, has mmap()'ed
19a15b93
KH
978 * the iso buffer, and the pointer points inside the buffer,
979 * we setup the payload pointers accordingly. Otherwise we
9aad8125 980 * set them both to 0, which will still let packets with
19a15b93
KH
981 * payload_length == 0 through. In other words, if no packets
982 * use the indirect payload, the iso buffer need not be mapped
6e95dea7 983 * and the a->data pointer is ignored.
c781c06d 984 */
19a15b93 985
6e95dea7 986 payload = (unsigned long)a->data - client->vm_start;
ef370ee7 987 buffer_end = client->buffer.page_count << PAGE_SHIFT;
6e95dea7 988 if (a->data == 0 || client->buffer.pages == NULL ||
ef370ee7 989 payload >= buffer_end) {
9aad8125 990 payload = 0;
ef370ee7 991 buffer_end = 0;
19a15b93
KH
992 }
993
6e95dea7 994 p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(a->packets);
1ccc9147 995
6e95dea7 996 if (!access_ok(VERIFY_READ, p, a->size))
19a15b93
KH
997 return -EFAULT;
998
6e95dea7 999 end = (void __user *)p + a->size;
19a15b93
KH
1000 count = 0;
1001 while (p < end) {
1ca31ae7 1002 if (get_user(control, &p->control))
19a15b93 1003 return -EFAULT;
1ca31ae7
KH
1004 u.packet.payload_length = GET_PAYLOAD_LENGTH(control);
1005 u.packet.interrupt = GET_INTERRUPT(control);
1006 u.packet.skip = GET_SKIP(control);
1007 u.packet.tag = GET_TAG(control);
1008 u.packet.sy = GET_SY(control);
1009 u.packet.header_length = GET_HEADER_LENGTH(control);
295e3feb 1010
9b32d5f3 1011 if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) {
385ab5bc
CL
1012 if (u.packet.header_length % 4 != 0)
1013 return -EINVAL;
295e3feb
KH
1014 header_length = u.packet.header_length;
1015 } else {
c781c06d
KH
1016 /*
1017 * We require that header_length is a multiple of
1018 * the fixed header size, ctx->header_size.
1019 */
9b32d5f3
KH
1020 if (ctx->header_size == 0) {
1021 if (u.packet.header_length > 0)
1022 return -EINVAL;
4ba1d9c0
CL
1023 } else if (u.packet.header_length == 0 ||
1024 u.packet.header_length % ctx->header_size != 0) {
295e3feb 1025 return -EINVAL;
9b32d5f3 1026 }
295e3feb
KH
1027 header_length = 0;
1028 }
1029
19a15b93 1030 next = (struct fw_cdev_iso_packet __user *)
295e3feb 1031 &p->header[header_length / 4];
19a15b93
KH
1032 if (next > end)
1033 return -EINVAL;
1034 if (__copy_from_user
295e3feb 1035 (u.packet.header, p->header, header_length))
19a15b93 1036 return -EFAULT;
98b6cbe8 1037 if (u.packet.skip && ctx->type == FW_ISO_CONTEXT_TRANSMIT &&
19a15b93
KH
1038 u.packet.header_length + u.packet.payload_length > 0)
1039 return -EINVAL;
ef370ee7 1040 if (payload + u.packet.payload_length > buffer_end)
19a15b93
KH
1041 return -EINVAL;
1042
9b32d5f3
KH
1043 if (fw_iso_context_queue(ctx, &u.packet,
1044 &client->buffer, payload))
19a15b93
KH
1045 break;
1046
1047 p = next;
1048 payload += u.packet.payload_length;
1049 count++;
1050 }
1051
6e95dea7
SR
1052 a->size -= uptr_to_u64(p) - a->packets;
1053 a->packets = uptr_to_u64(p);
1054 a->data = client->vm_start + payload;
19a15b93
KH
1055
1056 return count;
1057}
1058
6e95dea7 1059static int ioctl_start_iso(struct client *client, union ioctl_arg *arg)
19a15b93 1060{
6e95dea7 1061 struct fw_cdev_start_iso *a = &arg->start_iso;
19a15b93 1062
6e95dea7 1063 if (client->iso_context == NULL || a->handle != 0)
abaa5743 1064 return -EINVAL;
fae60312 1065
6e95dea7
SR
1066 if (client->iso_context->type == FW_ISO_CONTEXT_RECEIVE &&
1067 (a->tags == 0 || a->tags > 15 || a->sync > 15))
1068 return -EINVAL;
eb0306ea 1069
6e95dea7
SR
1070 return fw_iso_context_start(client->iso_context,
1071 a->cycle, a->sync, a->tags);
19a15b93
KH
1072}
1073
6e95dea7 1074static int ioctl_stop_iso(struct client *client, union ioctl_arg *arg)
b8295668 1075{
6e95dea7 1076 struct fw_cdev_stop_iso *a = &arg->stop_iso;
abaa5743 1077
6e95dea7 1078 if (client->iso_context == NULL || a->handle != 0)
abaa5743
KH
1079 return -EINVAL;
1080
b8295668
KH
1081 return fw_iso_context_stop(client->iso_context);
1082}
1083
6e95dea7 1084static int ioctl_get_cycle_timer2(struct client *client, union ioctl_arg *arg)
a64408b9 1085{
6e95dea7 1086 struct fw_cdev_get_cycle_timer2 *a = &arg->get_cycle_timer2;
a64408b9 1087 struct fw_card *card = client->device->card;
abfe5a01 1088 struct timespec ts = {0, 0};
4a9bde9b 1089 u32 cycle_time;
abfe5a01 1090 int ret = 0;
a64408b9 1091
4a9bde9b 1092 local_irq_disable();
a64408b9 1093
0fcff4e3 1094 cycle_time = card->driver->read_csr(card, CSR_CYCLE_TIME);
abfe5a01 1095
6e95dea7 1096 switch (a->clk_id) {
abfe5a01
SR
1097 case CLOCK_REALTIME: getnstimeofday(&ts); break;
1098 case CLOCK_MONOTONIC: do_posix_clock_monotonic_gettime(&ts); break;
1099 case CLOCK_MONOTONIC_RAW: getrawmonotonic(&ts); break;
1100 default:
1101 ret = -EINVAL;
1102 }
a64408b9 1103
4a9bde9b 1104 local_irq_enable();
a64408b9 1105
6e95dea7
SR
1106 a->tv_sec = ts.tv_sec;
1107 a->tv_nsec = ts.tv_nsec;
1108 a->cycle_timer = cycle_time;
abfe5a01
SR
1109
1110 return ret;
1111}
1112
6e95dea7 1113static int ioctl_get_cycle_timer(struct client *client, union ioctl_arg *arg)
abfe5a01 1114{
6e95dea7 1115 struct fw_cdev_get_cycle_timer *a = &arg->get_cycle_timer;
abfe5a01
SR
1116 struct fw_cdev_get_cycle_timer2 ct2;
1117
1118 ct2.clk_id = CLOCK_REALTIME;
6e95dea7 1119 ioctl_get_cycle_timer2(client, (union ioctl_arg *)&ct2);
abfe5a01 1120
6e95dea7
SR
1121 a->local_time = ct2.tv_sec * USEC_PER_SEC + ct2.tv_nsec / NSEC_PER_USEC;
1122 a->cycle_timer = ct2.cycle_timer;
4a9bde9b 1123
a64408b9
SR
1124 return 0;
1125}
1126
b1bda4cd
JFSR
1127static void iso_resource_work(struct work_struct *work)
1128{
1129 struct iso_resource_event *e;
1130 struct iso_resource *r =
1131 container_of(work, struct iso_resource, work.work);
1132 struct client *client = r->client;
1133 int generation, channel, bandwidth, todo;
1134 bool skip, free, success;
1135
1136 spin_lock_irq(&client->lock);
1137 generation = client->device->generation;
1138 todo = r->todo;
1139 /* Allow 1000ms grace period for other reallocations. */
1140 if (todo == ISO_RES_ALLOC &&
1141 time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) {
9fb551bf 1142 schedule_iso_resource(r, DIV_ROUND_UP(HZ, 3));
b1bda4cd
JFSR
1143 skip = true;
1144 } else {
1145 /* We could be called twice within the same generation. */
1146 skip = todo == ISO_RES_REALLOC &&
1147 r->generation == generation;
1148 }
1ec3c026
SR
1149 free = todo == ISO_RES_DEALLOC ||
1150 todo == ISO_RES_ALLOC_ONCE ||
1151 todo == ISO_RES_DEALLOC_ONCE;
b1bda4cd
JFSR
1152 r->generation = generation;
1153 spin_unlock_irq(&client->lock);
1154
1155 if (skip)
1156 goto out;
1157
1158 bandwidth = r->bandwidth;
1159
1160 fw_iso_resource_manage(client->device->card, generation,
1161 r->channels, &channel, &bandwidth,
1ec3c026
SR
1162 todo == ISO_RES_ALLOC ||
1163 todo == ISO_RES_REALLOC ||
6fdc0370
SR
1164 todo == ISO_RES_ALLOC_ONCE,
1165 r->transaction_data);
b1bda4cd
JFSR
1166 /*
1167 * Is this generation outdated already? As long as this resource sticks
1168 * in the idr, it will be scheduled again for a newer generation or at
1169 * shutdown.
1170 */
1171 if (channel == -EAGAIN &&
1172 (todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC))
1173 goto out;
1174
1175 success = channel >= 0 || bandwidth > 0;
1176
1177 spin_lock_irq(&client->lock);
1178 /*
1179 * Transit from allocation to reallocation, except if the client
1180 * requested deallocation in the meantime.
1181 */
1182 if (r->todo == ISO_RES_ALLOC)
1183 r->todo = ISO_RES_REALLOC;
1184 /*
1185 * Allocation or reallocation failure? Pull this resource out of the
1186 * idr and prepare for deletion, unless the client is shutting down.
1187 */
1188 if (r->todo == ISO_RES_REALLOC && !success &&
1189 !client->in_shutdown &&
1190 idr_find(&client->resource_idr, r->resource.handle)) {
1191 idr_remove(&client->resource_idr, r->resource.handle);
1192 client_put(client);
1193 free = true;
1194 }
1195 spin_unlock_irq(&client->lock);
1196
1197 if (todo == ISO_RES_ALLOC && channel >= 0)
5d9cb7d2 1198 r->channels = 1ULL << channel;
b1bda4cd
JFSR
1199
1200 if (todo == ISO_RES_REALLOC && success)
1201 goto out;
1202
1ec3c026 1203 if (todo == ISO_RES_ALLOC || todo == ISO_RES_ALLOC_ONCE) {
b1bda4cd
JFSR
1204 e = r->e_alloc;
1205 r->e_alloc = NULL;
1206 } else {
1207 e = r->e_dealloc;
1208 r->e_dealloc = NULL;
1209 }
e21fcf79
SR
1210 e->iso_resource.handle = r->resource.handle;
1211 e->iso_resource.channel = channel;
1212 e->iso_resource.bandwidth = bandwidth;
b1bda4cd
JFSR
1213
1214 queue_event(client, &e->event,
e21fcf79 1215 &e->iso_resource, sizeof(e->iso_resource), NULL, 0);
b1bda4cd
JFSR
1216
1217 if (free) {
1218 cancel_delayed_work(&r->work);
1219 kfree(r->e_alloc);
1220 kfree(r->e_dealloc);
1221 kfree(r);
1222 }
1223 out:
1224 client_put(client);
1225}
1226
b1bda4cd
JFSR
1227static void release_iso_resource(struct client *client,
1228 struct client_resource *resource)
1229{
1230 struct iso_resource *r =
1231 container_of(resource, struct iso_resource, resource);
1232
1233 spin_lock_irq(&client->lock);
1234 r->todo = ISO_RES_DEALLOC;
9fb551bf 1235 schedule_iso_resource(r, 0);
b1bda4cd
JFSR
1236 spin_unlock_irq(&client->lock);
1237}
1238
1ec3c026
SR
1239static int init_iso_resource(struct client *client,
1240 struct fw_cdev_allocate_iso_resource *request, int todo)
b1bda4cd 1241{
b1bda4cd
JFSR
1242 struct iso_resource_event *e1, *e2;
1243 struct iso_resource *r;
1244 int ret;
1245
1246 if ((request->channels == 0 && request->bandwidth == 0) ||
1247 request->bandwidth > BANDWIDTH_AVAILABLE_INITIAL ||
1248 request->bandwidth < 0)
1249 return -EINVAL;
1250
1251 r = kmalloc(sizeof(*r), GFP_KERNEL);
1252 e1 = kmalloc(sizeof(*e1), GFP_KERNEL);
1253 e2 = kmalloc(sizeof(*e2), GFP_KERNEL);
1254 if (r == NULL || e1 == NULL || e2 == NULL) {
1255 ret = -ENOMEM;
1256 goto fail;
1257 }
1258
1259 INIT_DELAYED_WORK(&r->work, iso_resource_work);
1260 r->client = client;
1ec3c026 1261 r->todo = todo;
b1bda4cd
JFSR
1262 r->generation = -1;
1263 r->channels = request->channels;
1264 r->bandwidth = request->bandwidth;
1265 r->e_alloc = e1;
1266 r->e_dealloc = e2;
1267
e21fcf79
SR
1268 e1->iso_resource.closure = request->closure;
1269 e1->iso_resource.type = FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED;
1270 e2->iso_resource.closure = request->closure;
1271 e2->iso_resource.type = FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED;
b1bda4cd 1272
1ec3c026
SR
1273 if (todo == ISO_RES_ALLOC) {
1274 r->resource.release = release_iso_resource;
1275 ret = add_client_resource(client, &r->resource, GFP_KERNEL);
81610b8f
SR
1276 if (ret < 0)
1277 goto fail;
1ec3c026
SR
1278 } else {
1279 r->resource.release = NULL;
1280 r->resource.handle = -1;
9fb551bf 1281 schedule_iso_resource(r, 0);
1ec3c026 1282 }
b1bda4cd
JFSR
1283 request->handle = r->resource.handle;
1284
1285 return 0;
1286 fail:
1287 kfree(r);
1288 kfree(e1);
1289 kfree(e2);
1290
1291 return ret;
1292}
1293
6e95dea7
SR
1294static int ioctl_allocate_iso_resource(struct client *client,
1295 union ioctl_arg *arg)
1ec3c026 1296{
6e95dea7
SR
1297 return init_iso_resource(client,
1298 &arg->allocate_iso_resource, ISO_RES_ALLOC);
1ec3c026
SR
1299}
1300
6e95dea7
SR
1301static int ioctl_deallocate_iso_resource(struct client *client,
1302 union ioctl_arg *arg)
b1bda4cd 1303{
6e95dea7
SR
1304 return release_client_resource(client,
1305 arg->deallocate.handle, release_iso_resource, NULL);
b1bda4cd
JFSR
1306}
1307
6e95dea7
SR
1308static int ioctl_allocate_iso_resource_once(struct client *client,
1309 union ioctl_arg *arg)
1ec3c026 1310{
6e95dea7
SR
1311 return init_iso_resource(client,
1312 &arg->allocate_iso_resource, ISO_RES_ALLOC_ONCE);
1ec3c026
SR
1313}
1314
6e95dea7
SR
1315static int ioctl_deallocate_iso_resource_once(struct client *client,
1316 union ioctl_arg *arg)
1ec3c026 1317{
6e95dea7
SR
1318 return init_iso_resource(client,
1319 &arg->allocate_iso_resource, ISO_RES_DEALLOC_ONCE);
1ec3c026
SR
1320}
1321
c8a25900
SR
1322/*
1323 * Returns a speed code: Maximum speed to or from this device,
1324 * limited by the device's link speed, the local node's link speed,
1325 * and all PHY port speeds between the two links.
1326 */
6e95dea7 1327static int ioctl_get_speed(struct client *client, union ioctl_arg *arg)
33580a3e 1328{
c8a25900 1329 return client->device->max_speed;
33580a3e
SR
1330}
1331
6e95dea7
SR
1332static int ioctl_send_broadcast_request(struct client *client,
1333 union ioctl_arg *arg)
acfe8333 1334{
6e95dea7 1335 struct fw_cdev_send_request *a = &arg->send_request;
acfe8333 1336
6e95dea7 1337 switch (a->tcode) {
acfe8333
JFSR
1338 case TCODE_WRITE_QUADLET_REQUEST:
1339 case TCODE_WRITE_BLOCK_REQUEST:
1340 break;
1341 default:
1342 return -EINVAL;
1343 }
1344
1566f3dc 1345 /* Security policy: Only allow accesses to Units Space. */
6e95dea7 1346 if (a->offset < CSR_REGISTER_BASE + CSR_CONFIG_ROM_END)
1566f3dc
SR
1347 return -EACCES;
1348
6e95dea7 1349 return init_request(client, a, LOCAL_BUS | 0x3f, SCODE_100);
acfe8333
JFSR
1350}
1351
6e95dea7 1352static int ioctl_send_stream_packet(struct client *client, union ioctl_arg *arg)
f8c2287c 1353{
6e95dea7 1354 struct fw_cdev_send_stream_packet *a = &arg->send_stream_packet;
18e9b10f
SR
1355 struct fw_cdev_send_request request;
1356 int dest;
f8c2287c 1357
6e95dea7
SR
1358 if (a->speed > client->device->card->link_speed ||
1359 a->length > 1024 << a->speed)
18e9b10f 1360 return -EIO;
f8c2287c 1361
6e95dea7 1362 if (a->tag > 3 || a->channel > 63 || a->sy > 15)
18e9b10f
SR
1363 return -EINVAL;
1364
6e95dea7 1365 dest = fw_stream_packet_destination_id(a->tag, a->channel, a->sy);
18e9b10f 1366 request.tcode = TCODE_STREAM_DATA;
6e95dea7
SR
1367 request.length = a->length;
1368 request.closure = a->closure;
1369 request.data = a->data;
1370 request.generation = a->generation;
18e9b10f 1371
6e95dea7 1372 return init_request(client, &request, dest, a->speed);
f8c2287c
JF
1373}
1374
6e95dea7 1375static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = {
4f259223
KH
1376 ioctl_get_info,
1377 ioctl_send_request,
1378 ioctl_allocate,
1379 ioctl_deallocate,
1380 ioctl_send_response,
1381 ioctl_initiate_bus_reset,
1382 ioctl_add_descriptor,
1383 ioctl_remove_descriptor,
1384 ioctl_create_iso_context,
1385 ioctl_queue_iso,
1386 ioctl_start_iso,
1387 ioctl_stop_iso,
a64408b9 1388 ioctl_get_cycle_timer,
b1bda4cd
JFSR
1389 ioctl_allocate_iso_resource,
1390 ioctl_deallocate_iso_resource,
1ec3c026
SR
1391 ioctl_allocate_iso_resource_once,
1392 ioctl_deallocate_iso_resource_once,
33580a3e 1393 ioctl_get_speed,
acfe8333 1394 ioctl_send_broadcast_request,
f8c2287c 1395 ioctl_send_stream_packet,
abfe5a01 1396 ioctl_get_cycle_timer2,
4f259223
KH
1397};
1398
53dca511
SR
1399static int dispatch_ioctl(struct client *client,
1400 unsigned int cmd, void __user *arg)
19a15b93 1401{
6e95dea7 1402 union ioctl_arg buffer;
2dbd7d7e 1403 int ret;
4f259223 1404
64582298
SR
1405 if (fw_device_is_shutdown(client->device))
1406 return -ENODEV;
1407
4f259223 1408 if (_IOC_TYPE(cmd) != '#' ||
9cac00b8
SR
1409 _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers) ||
1410 _IOC_SIZE(cmd) > sizeof(buffer))
19a15b93 1411 return -EINVAL;
4f259223 1412
9cac00b8
SR
1413 if (_IOC_DIR(cmd) == _IOC_READ)
1414 memset(&buffer, 0, _IOC_SIZE(cmd));
1415
1416 if (_IOC_DIR(cmd) & _IOC_WRITE)
1417 if (copy_from_user(&buffer, arg, _IOC_SIZE(cmd)))
4f259223 1418 return -EFAULT;
4f259223 1419
6e95dea7 1420 ret = ioctl_handlers[_IOC_NR(cmd)](client, &buffer);
2dbd7d7e
SR
1421 if (ret < 0)
1422 return ret;
4f259223 1423
9cac00b8
SR
1424 if (_IOC_DIR(cmd) & _IOC_READ)
1425 if (copy_to_user(arg, &buffer, _IOC_SIZE(cmd)))
4f259223 1426 return -EFAULT;
4f259223 1427
2dbd7d7e 1428 return ret;
19a15b93
KH
1429}
1430
53dca511
SR
1431static long fw_device_op_ioctl(struct file *file,
1432 unsigned int cmd, unsigned long arg)
19a15b93 1433{
64582298 1434 return dispatch_ioctl(file->private_data, cmd, (void __user *)arg);
19a15b93
KH
1435}
1436
1437#ifdef CONFIG_COMPAT
53dca511
SR
1438static long fw_device_op_compat_ioctl(struct file *file,
1439 unsigned int cmd, unsigned long arg)
19a15b93 1440{
64582298 1441 return dispatch_ioctl(file->private_data, cmd, compat_ptr(arg));
19a15b93
KH
1442}
1443#endif
1444
1445static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma)
1446{
1447 struct client *client = file->private_data;
9aad8125
KH
1448 enum dma_data_direction direction;
1449 unsigned long size;
2dbd7d7e 1450 int page_count, ret;
9aad8125 1451
551f4cb9
JF
1452 if (fw_device_is_shutdown(client->device))
1453 return -ENODEV;
1454
9aad8125
KH
1455 /* FIXME: We could support multiple buffers, but we don't. */
1456 if (client->buffer.pages != NULL)
1457 return -EBUSY;
1458
1459 if (!(vma->vm_flags & VM_SHARED))
1460 return -EINVAL;
19a15b93 1461
9aad8125 1462 if (vma->vm_start & ~PAGE_MASK)
19a15b93
KH
1463 return -EINVAL;
1464
1465 client->vm_start = vma->vm_start;
9aad8125
KH
1466 size = vma->vm_end - vma->vm_start;
1467 page_count = size >> PAGE_SHIFT;
1468 if (size & ~PAGE_MASK)
1469 return -EINVAL;
1470
1471 if (vma->vm_flags & VM_WRITE)
1472 direction = DMA_TO_DEVICE;
1473 else
1474 direction = DMA_FROM_DEVICE;
1475
2dbd7d7e
SR
1476 ret = fw_iso_buffer_init(&client->buffer, client->device->card,
1477 page_count, direction);
1478 if (ret < 0)
1479 return ret;
19a15b93 1480
2dbd7d7e
SR
1481 ret = fw_iso_buffer_map(&client->buffer, vma);
1482 if (ret < 0)
9aad8125
KH
1483 fw_iso_buffer_destroy(&client->buffer, client->device->card);
1484
2dbd7d7e 1485 return ret;
19a15b93
KH
1486}
1487
45ee3199
JF
1488static int shutdown_resource(int id, void *p, void *data)
1489{
e21fcf79 1490 struct client_resource *resource = p;
45ee3199
JF
1491 struct client *client = data;
1492
e21fcf79 1493 resource->release(client, resource);
fb443036 1494 client_put(client);
45ee3199
JF
1495
1496 return 0;
1497}
1498
19a15b93
KH
1499static int fw_device_op_release(struct inode *inode, struct file *file)
1500{
1501 struct client *client = file->private_data;
e21fcf79 1502 struct event *event, *next_event;
19a15b93 1503
97811e34
SR
1504 mutex_lock(&client->device->client_list_mutex);
1505 list_del(&client->link);
1506 mutex_unlock(&client->device->client_list_mutex);
1507
19a15b93
KH
1508 if (client->iso_context)
1509 fw_iso_context_destroy(client->iso_context);
1510
36a755cf
SR
1511 if (client->buffer.pages)
1512 fw_iso_buffer_destroy(&client->buffer, client->device->card);
1513
45ee3199 1514 /* Freeze client->resource_idr and client->event_list */
3ba94986 1515 spin_lock_irq(&client->lock);
45ee3199 1516 client->in_shutdown = true;
3ba94986 1517 spin_unlock_irq(&client->lock);
66dea3e5 1518
45ee3199
JF
1519 idr_for_each(&client->resource_idr, shutdown_resource, client);
1520 idr_remove_all(&client->resource_idr);
1521 idr_destroy(&client->resource_idr);
28cf6a04 1522
e21fcf79
SR
1523 list_for_each_entry_safe(event, next_event, &client->event_list, link)
1524 kfree(event);
19a15b93 1525
fb443036 1526 client_put(client);
19a15b93
KH
1527
1528 return 0;
1529}
1530
1531static unsigned int fw_device_op_poll(struct file *file, poll_table * pt)
1532{
1533 struct client *client = file->private_data;
2603bf21 1534 unsigned int mask = 0;
19a15b93
KH
1535
1536 poll_wait(file, &client->wait, pt);
1537
2603bf21
KH
1538 if (fw_device_is_shutdown(client->device))
1539 mask |= POLLHUP | POLLERR;
19a15b93 1540 if (!list_empty(&client->event_list))
2603bf21
KH
1541 mask |= POLLIN | POLLRDNORM;
1542
1543 return mask;
19a15b93
KH
1544}
1545
21ebcd12 1546const struct file_operations fw_device_ops = {
19a15b93 1547 .owner = THIS_MODULE,
3ac26b2e 1548 .llseek = no_llseek,
19a15b93
KH
1549 .open = fw_device_op_open,
1550 .read = fw_device_op_read,
1551 .unlocked_ioctl = fw_device_op_ioctl,
19a15b93 1552 .mmap = fw_device_op_mmap,
3ac26b2e
SR
1553 .release = fw_device_op_release,
1554 .poll = fw_device_op_poll,
19a15b93 1555#ifdef CONFIG_COMPAT
5af4e5ea 1556 .compat_ioctl = fw_device_op_compat_ioctl,
19a15b93
KH
1557#endif
1558};
This page took 0.521142 seconds and 5 git commands to generate.