1a59d1b8e05ea drivers/firewire/core-cdev.c (Thomas Gleixner 2019-05-27 08:55:05 +0200 1) // SPDX-License-Identifier: GPL-2.0-or-later
c781c06d119d0 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-07 20:33:32 -0400 2) /*
c781c06d119d0 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-07 20:33:32 -0400 3) * Char device for device raw access
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 4) *
c781c06d119d0 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-07 20:33:32 -0400 5) * Copyright (C) 2005-2007 Kristian Hoegsberg <krh@bitplanet.net>
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 6) */
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 7)
eb5b35a560510 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-07 14:13:14 +0200 8) #include <linux/bug.h>
be5bbd6756b44 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 9) #include <linux/compat.h>
be5bbd6756b44 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 10) #include <linux/delay.h>
be5bbd6756b44 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 11) #include <linux/device.h>
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 12) #include <linux/dma-mapping.h>
be5bbd6756b44 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 13) #include <linux/errno.h>
77c9a5daa9c4d drivers/firewire/fw-cdev.c (Stefan Richter 2009-06-05 16:26:18 +0200 14) #include <linux/firewire.h>
be5bbd6756b44 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 15) #include <linux/firewire-cdev.h>
be5bbd6756b44 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 16) #include <linux/idr.h>
4a9bde9b8ab55 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 22:24:43 +0100 17) #include <linux/irqflags.h>
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 18) #include <linux/jiffies.h>
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 19) #include <linux/kernel.h>
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 20) #include <linux/kref.h>
be5bbd6756b44 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 21) #include <linux/mm.h>
be5bbd6756b44 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 22) #include <linux/module.h>
d67cfb9613f37 drivers/firewire/fw-cdev.c (Stefan Richter 2008-10-05 10:37:11 +0200 23) #include <linux/mutex.h>
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 24) #include <linux/poll.h>
ae2a97661482c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 09:31:56 +0200 25) #include <linux/sched.h> /* required for linux/wait.h */
5a0e3ad6af866 drivers/firewire/core-cdev.c (Tejun Heo 2010-03-24 17:04:11 +0900 26) #include <linux/slab.h>
cf417e5494582 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-10-03 11:19:09 -0400 27) #include <linux/spinlock.h>
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 28) #include <linux/string.h>
be5bbd6756b44 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 29) #include <linux/time.h>
e034d242593f1 drivers/firewire/core-cdev.c (Stefan Richter 2009-06-06 18:36:24 +0200 30) #include <linux/uaccess.h>
be5bbd6756b44 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 31) #include <linux/vmalloc.h>
be5bbd6756b44 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 32) #include <linux/wait.h>
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 33) #include <linux/workqueue.h>
be5bbd6756b44 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 34)
be5bbd6756b44 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 35)
77c9a5daa9c4d drivers/firewire/fw-cdev.c (Stefan Richter 2009-06-05 16:26:18 +0200 36) #include "core.h"
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 37)
604f45167824e drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:52:55 +0200 38) /*
604f45167824e drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:52:55 +0200 39) * ABI version history is documented in linux/firewire-cdev.h.
604f45167824e drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:52:55 +0200 40) */
18d627113b830 drivers/firewire/core-cdev.c (Clemens Ladisch 2012-03-18 19:05:29 +0100 41) #define FW_CDEV_KERNEL_VERSION 5
8e2b2b46ea4ca drivers/firewire/core-cdev.c (Stefan Richter 2010-07-23 13:05:39 +0200 42) #define FW_CDEV_VERSION_EVENT_REQUEST2 4
8e2b2b46ea4ca drivers/firewire/core-cdev.c (Stefan Richter 2010-07-23 13:05:39 +0200 43) #define FW_CDEV_VERSION_ALLOCATE_REGION_END 4
0699a73af3811 drivers/firewire/core-cdev.c (Clemens Ladisch 2013-07-22 21:32:09 +0200 44) #define FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW 5
604f45167824e drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:52:55 +0200 45)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 46) struct client {
344bbc4de14e7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:43 -0500 47) u32 version;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 48) struct fw_device *device;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 49)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 50) spinlock_t lock;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 51) bool in_shutdown;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 52) struct idr resource_idr;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 53) struct list_head event_list;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 54) wait_queue_head_t wait;
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 55) wait_queue_head_t tx_flush_wait;
da8ecffaed434 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:39 -0400 56) u64 bus_reset_closure;
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 57)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 58) struct fw_iso_context *iso_context;
abaa5743e340c drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:14 -0400 59) u64 iso_closure;
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 60) struct fw_iso_buffer buffer;
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 61) unsigned long vm_start;
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 62) bool buffer_is_mapped;
97bd9efa5a4d8 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:41 -0500 63)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 64) struct list_head phy_receiver_link;
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 65) u64 phy_receiver_closure;
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 66)
97bd9efa5a4d8 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:41 -0500 67) struct list_head link;
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 68) struct kref kref;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 69) };
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 70)
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 71) static inline void client_get(struct client *client)
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 72) {
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 73) kref_get(&client->kref);
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 74) }
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 75)
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 76) static void client_release(struct kref *kref)
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 77) {
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 78) struct client *client = container_of(kref, struct client, kref);
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 79)
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 80) fw_device_put(client->device);
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 81) kfree(client);
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 82) }
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 83)
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 84) static void client_put(struct client *client)
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 85) {
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 86) kref_put(&client->kref, client_release);
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 87) }
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 88)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 89) struct client_resource;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 90) typedef void (*client_resource_release_fn_t)(struct client *,
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 91) struct client_resource *);
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 92) struct client_resource {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 93) client_resource_release_fn_t release;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 94) int handle;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 95) };
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 96)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 97) struct address_handler_resource {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 98) struct client_resource resource;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 99) struct fw_address_handler handler;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 100) __u64 closure;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 101) struct client *client;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 102) };
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 103)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 104) struct outbound_transaction_resource {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 105) struct client_resource resource;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 106) struct fw_transaction transaction;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 107) };
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 108)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 109) struct inbound_transaction_resource {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 110) struct client_resource resource;
08bd34c98d631 drivers/firewire/core-cdev.c (Jay Fenlason 2010-05-18 14:02:45 -0400 111) struct fw_card *card;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 112) struct fw_request *request;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 113) void *data;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 114) size_t length;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 115) };
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 116)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 117) struct descriptor_resource {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 118) struct client_resource resource;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 119) struct fw_descriptor descriptor;
c38e7e212acdb drivers/firewire/core-cdev.c (Gustavo A. R. Silva 2020-05-28 09:35:11 -0500 120) u32 data[];
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 121) };
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 122)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 123) struct iso_resource {
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 124) struct client_resource resource;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 125) struct client *client;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 126) /* Schedule work and access todo only with client->lock held. */
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 127) struct delayed_work work;
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 128) enum {ISO_RES_ALLOC, ISO_RES_REALLOC, ISO_RES_DEALLOC,
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 129) ISO_RES_ALLOC_ONCE, ISO_RES_DEALLOC_ONCE,} todo;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 130) int generation;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 131) u64 channels;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 132) s32 bandwidth;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 133) struct iso_resource_event *e_alloc, *e_dealloc;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 134) };
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 135)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 136) static void release_iso_resource(struct client *, struct client_resource *);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 137)
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 138) static void schedule_iso_resource(struct iso_resource *r, unsigned long delay)
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 139) {
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 140) client_get(r->client);
105e53f863c04 drivers/firewire/core-cdev.c (Stefan Richter 2011-05-01 20:50:31 +0200 141) if (!queue_delayed_work(fw_workqueue, &r->work, delay))
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 142) client_put(r->client);
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 143) }
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 144)
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 145) static void schedule_if_iso_resource(struct client_resource *resource)
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 146) {
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 147) if (resource->release == release_iso_resource)
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 148) schedule_iso_resource(container_of(resource,
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 149) struct iso_resource, resource), 0);
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 150) }
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 151)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 152) /*
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 153) * dequeue_event() just kfree()'s the event, so the event has to be
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 154) * the first field in a struct XYZ_event.
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 155) */
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 156) struct event {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 157) struct { void *data; size_t size; } v[2];
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 158) struct list_head link;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 159) };
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 160)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 161) struct bus_reset_event {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 162) struct event event;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 163) struct fw_cdev_event_bus_reset reset;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 164) };
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 165)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 166) struct outbound_transaction_event {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 167) struct event event;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 168) struct client *client;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 169) struct outbound_transaction_resource r;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 170) struct fw_cdev_event_response response;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 171) };
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 172)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 173) struct inbound_transaction_event {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 174) struct event event;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 175) union {
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 176) struct fw_cdev_event_request request;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 177) struct fw_cdev_event_request2 request2;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 178) } req;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 179) };
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 180)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 181) struct iso_interrupt_event {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 182) struct event event;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 183) struct fw_cdev_event_iso_interrupt interrupt;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 184) };
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 185)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 186) struct iso_interrupt_mc_event {
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 187) struct event event;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 188) struct fw_cdev_event_iso_interrupt_mc interrupt;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 189) };
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 190)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 191) struct iso_resource_event {
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 192) struct event event;
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 193) struct fw_cdev_event_iso_resource iso_resource;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 194) };
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 195)
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 196) struct outbound_phy_packet_event {
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 197) struct event event;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 198) struct client *client;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 199) struct fw_packet p;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 200) struct fw_cdev_event_phy_packet phy_packet;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 201) };
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 202)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 203) struct inbound_phy_packet_event {
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 204) struct event event;
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 205) struct fw_cdev_event_phy_packet phy_packet;
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 206) };
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 207)
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 208) #ifdef CONFIG_COMPAT
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 209) static void __user *u64_to_uptr(u64 value)
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 210) {
a25045ff32dfb drivers/firewire/core-cdev.c (Andy Lutomirski 2016-03-22 14:25:13 -0700 211) if (in_compat_syscall())
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 212) return compat_ptr(value);
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 213) else
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 214) return (void __user *)(unsigned long)value;
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 215) }
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 216)
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 217) static u64 uptr_to_u64(void __user *ptr)
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 218) {
a25045ff32dfb drivers/firewire/core-cdev.c (Andy Lutomirski 2016-03-22 14:25:13 -0700 219) if (in_compat_syscall())
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 220) return ptr_to_compat(ptr);
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 221) else
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 222) return (u64)(unsigned long)ptr;
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 223) }
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 224) #else
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 225) static inline void __user *u64_to_uptr(u64 value)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 226) {
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 227) return (void __user *)(unsigned long)value;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 228) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 229)
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 230) static inline u64 uptr_to_u64(void __user *ptr)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 231) {
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 232) return (u64)(unsigned long)ptr;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 233) }
9c1176b6a2885 drivers/firewire/core-cdev.c (Stefan Richter 2011-08-11 00:06:04 +0200 234) #endif /* CONFIG_COMPAT */
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 235)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 236) static int fw_device_op_open(struct inode *inode, struct file *file)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 237) {
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 238) struct fw_device *device;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 239) struct client *client;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 240)
96b19062e741b drivers/firewire/fw-cdev.c (Stefan Richter 2008-02-02 15:01:09 +0100 241) device = fw_device_get_by_devt(inode->i_rdev);
a3aca3dabbcf0 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:44 -0500 242) if (device == NULL)
a3aca3dabbcf0 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:44 -0500 243) return -ENODEV;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 244)
551f4cb9de716 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-05-16 11:15:23 -0400 245) if (fw_device_is_shutdown(device)) {
551f4cb9de716 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-05-16 11:15:23 -0400 246) fw_device_put(device);
551f4cb9de716 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-05-16 11:15:23 -0400 247) return -ENODEV;
551f4cb9de716 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-05-16 11:15:23 -0400 248) }
551f4cb9de716 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-05-16 11:15:23 -0400 249)
2d826cc5c791b drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-09 19:23:14 -0400 250) client = kzalloc(sizeof(*client), GFP_KERNEL);
96b19062e741b drivers/firewire/fw-cdev.c (Stefan Richter 2008-02-02 15:01:09 +0100 251) if (client == NULL) {
96b19062e741b drivers/firewire/fw-cdev.c (Stefan Richter 2008-02-02 15:01:09 +0100 252) fw_device_put(device);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 253) return -ENOMEM;
96b19062e741b drivers/firewire/fw-cdev.c (Stefan Richter 2008-02-02 15:01:09 +0100 254) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 255)
96b19062e741b drivers/firewire/fw-cdev.c (Stefan Richter 2008-02-02 15:01:09 +0100 256) client->device = device;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 257) spin_lock_init(&client->lock);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 258) idr_init(&client->resource_idr);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 259) INIT_LIST_HEAD(&client->event_list);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 260) init_waitqueue_head(&client->wait);
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 261) init_waitqueue_head(&client->tx_flush_wait);
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 262) INIT_LIST_HEAD(&client->phy_receiver_link);
93b37905f7008 drivers/firewire/core-cdev.c (Stefan Richter 2011-07-09 16:43:22 +0200 263) INIT_LIST_HEAD(&client->link);
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 264) kref_init(&client->kref);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 265)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 266) file->private_data = client;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 267)
3ac26b2ee3000 drivers/firewire/core-cdev.c (Stefan Richter 2010-04-10 16:38:05 +0100 268) return nonseekable_open(inode, file);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 269) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 270)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 271) static void queue_event(struct client *client, struct event *event,
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 272) void *data0, size_t size0, void *data1, size_t size1)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 273) {
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 274) unsigned long flags;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 275)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 276) event->v[0].data = data0;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 277) event->v[0].size = size0;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 278) event->v[1].data = data1;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 279) event->v[1].size = size1;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 280)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 281) spin_lock_irqsave(&client->lock, flags);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 282) if (client->in_shutdown)
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 283) kfree(event);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 284) else
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 285) list_add_tail(&event->link, &client->event_list);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 286) spin_unlock_irqrestore(&client->lock, flags);
83431cba3d847 drivers/firewire/fw-cdev.c (Jay Fenlason 2007-10-08 17:00:29 -0400 287)
83431cba3d847 drivers/firewire/fw-cdev.c (Jay Fenlason 2007-10-08 17:00:29 -0400 288) wake_up_interruptible(&client->wait);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 289) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 290)
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 291) static int dequeue_event(struct client *client,
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 292) char __user *buffer, size_t count)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 293) {
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 294) struct event *event;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 295) size_t size, total;
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 296) int i, ret;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 297)
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 298) ret = wait_event_interruptible(client->wait,
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 299) !list_empty(&client->event_list) ||
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 300) fw_device_is_shutdown(client->device));
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 301) if (ret < 0)
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 302) return ret;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 303)
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 304) if (list_empty(&client->event_list) &&
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 305) fw_device_is_shutdown(client->device))
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 306) return -ENODEV;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 307)
3ba949868a6dc drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 308) spin_lock_irq(&client->lock);
a459b8ab9c176 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-21 16:49:57 +0100 309) event = list_first_entry(&client->event_list, struct event, link);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 310) list_del(&event->link);
3ba949868a6dc drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 311) spin_unlock_irq(&client->lock);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 312)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 313) total = 0;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 314) for (i = 0; i < ARRAY_SIZE(event->v) && total < count; i++) {
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 315) size = min(event->v[i].size, count - total);
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 316) if (copy_to_user(buffer + total, event->v[i].data, size)) {
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 317) ret = -EFAULT;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 318) goto out;
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 319) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 320) total += size;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 321) }
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 322) ret = total;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 323)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 324) out:
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 325) kfree(event);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 326)
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 327) return ret;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 328) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 329)
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 330) static ssize_t fw_device_op_read(struct file *file, char __user *buffer,
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 331) size_t count, loff_t *offset)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 332) {
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 333) struct client *client = file->private_data;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 334)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 335) return dequeue_event(client, buffer, count);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 336) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 337)
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 338) static void fill_bus_reset_event(struct fw_cdev_event_bus_reset *event,
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 339) struct client *client)
344bbc4de14e7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:43 -0500 340) {
da8ecffaed434 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:39 -0400 341) struct fw_card *card = client->device->card;
cf417e5494582 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-10-03 11:19:09 -0400 342)
3ba949868a6dc drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 343) spin_lock_irq(&card->lock);
344bbc4de14e7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:43 -0500 344)
da8ecffaed434 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:39 -0400 345) event->closure = client->bus_reset_closure;
344bbc4de14e7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:43 -0500 346) event->type = FW_CDEV_EVENT_BUS_RESET;
cf5a56ac8083d drivers/firewire/fw-cdev.c (Stefan Richter 2008-01-24 01:53:51 +0100 347) event->generation = client->device->generation;
da8ecffaed434 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:39 -0400 348) event->node_id = client->device->node_id;
344bbc4de14e7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:43 -0500 349) event->local_node_id = card->local_node->node_id;
250b2b6dd421c drivers/firewire/core-cdev.c (Stefan Richter 2010-06-21 23:24:35 +0200 350) event->bm_node_id = card->bm_node_id;
344bbc4de14e7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:43 -0500 351) event->irm_node_id = card->irm_node->node_id;
344bbc4de14e7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:43 -0500 352) event->root_node_id = card->root_node->node_id;
cf417e5494582 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-10-03 11:19:09 -0400 353)
3ba949868a6dc drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 354) spin_unlock_irq(&card->lock);
344bbc4de14e7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:43 -0500 355) }
344bbc4de14e7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:43 -0500 356)
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 357) static void for_each_client(struct fw_device *device,
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 358) void (*callback)(struct client *client))
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 359) {
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 360) struct client *c;
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 361)
d67cfb9613f37 drivers/firewire/fw-cdev.c (Stefan Richter 2008-10-05 10:37:11 +0200 362) mutex_lock(&device->client_list_mutex);
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 363) list_for_each_entry(c, &device->client_list, link)
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 364) callback(c);
d67cfb9613f37 drivers/firewire/fw-cdev.c (Stefan Richter 2008-10-05 10:37:11 +0200 365) mutex_unlock(&device->client_list_mutex);
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 366) }
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 367)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 368) static int schedule_reallocations(int id, void *p, void *data)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 369) {
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 370) schedule_if_iso_resource(p);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 371)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 372) return 0;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 373) }
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 374)
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 375) static void queue_bus_reset_event(struct client *client)
97bd9efa5a4d8 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:41 -0500 376) {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 377) struct bus_reset_event *e;
97bd9efa5a4d8 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:41 -0500 378)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 379) e = kzalloc(sizeof(*e), GFP_KERNEL);
cfb0c9d1ffbf9 drivers/firewire/core-cdev.c (Stefan Richter 2013-03-24 17:32:00 +0100 380) if (e == NULL)
97bd9efa5a4d8 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:41 -0500 381) return;
97bd9efa5a4d8 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:41 -0500 382)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 383) fill_bus_reset_event(&e->reset, client);
97bd9efa5a4d8 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:41 -0500 384)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 385) queue_event(client, &e->event,
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 386) &e->reset, sizeof(e->reset), NULL, 0);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 387)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 388) spin_lock_irq(&client->lock);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 389) idr_for_each(&client->resource_idr, schedule_reallocations, client);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 390) spin_unlock_irq(&client->lock);
97bd9efa5a4d8 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:41 -0500 391) }
97bd9efa5a4d8 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:41 -0500 392)
97bd9efa5a4d8 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:41 -0500 393) void fw_device_cdev_update(struct fw_device *device)
97bd9efa5a4d8 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:41 -0500 394) {
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 395) for_each_client(device, queue_bus_reset_event);
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 396) }
97bd9efa5a4d8 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:41 -0500 397)
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 398) static void wake_up_client(struct client *client)
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 399) {
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 400) wake_up_interruptible(&client->wait);
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 401) }
97bd9efa5a4d8 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:41 -0500 402)
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 403) void fw_device_cdev_remove(struct fw_device *device)
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 404) {
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 405) for_each_client(device, wake_up_client);
97bd9efa5a4d8 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:41 -0500 406) }
97bd9efa5a4d8 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:41 -0500 407)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 408) union ioctl_arg {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 409) struct fw_cdev_get_info get_info;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 410) struct fw_cdev_send_request send_request;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 411) struct fw_cdev_allocate allocate;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 412) struct fw_cdev_deallocate deallocate;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 413) struct fw_cdev_send_response send_response;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 414) struct fw_cdev_initiate_bus_reset initiate_bus_reset;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 415) struct fw_cdev_add_descriptor add_descriptor;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 416) struct fw_cdev_remove_descriptor remove_descriptor;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 417) struct fw_cdev_create_iso_context create_iso_context;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 418) struct fw_cdev_queue_iso queue_iso;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 419) struct fw_cdev_start_iso start_iso;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 420) struct fw_cdev_stop_iso stop_iso;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 421) struct fw_cdev_get_cycle_timer get_cycle_timer;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 422) struct fw_cdev_allocate_iso_resource allocate_iso_resource;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 423) struct fw_cdev_send_stream_packet send_stream_packet;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 424) struct fw_cdev_get_cycle_timer2 get_cycle_timer2;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 425) struct fw_cdev_send_phy_packet send_phy_packet;
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 426) struct fw_cdev_receive_phy_packets receive_phy_packets;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 427) struct fw_cdev_set_iso_channels set_iso_channels;
d1bbd20972936 drivers/firewire/core-cdev.c (Clemens Ladisch 2012-03-18 19:06:39 +0100 428) struct fw_cdev_flush_iso flush_iso;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 429) };
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 430)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 431) static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 432) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 433) struct fw_cdev_get_info *a = &arg->get_info;
344bbc4de14e7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:43 -0500 434) struct fw_cdev_event_bus_reset bus_reset;
c9755e14a0198 drivers/firewire/fw-cdev.c (Stefan Richter 2008-03-24 20:54:28 +0100 435) unsigned long ret = 0;
344bbc4de14e7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:43 -0500 436)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 437) client->version = a->version;
604f45167824e drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:52:55 +0200 438) a->version = FW_CDEV_KERNEL_VERSION;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 439) a->card = client->device->card->index;
344bbc4de14e7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:43 -0500 440)
c9755e14a0198 drivers/firewire/fw-cdev.c (Stefan Richter 2008-03-24 20:54:28 +0100 441) down_read(&fw_device_rwsem);
c9755e14a0198 drivers/firewire/fw-cdev.c (Stefan Richter 2008-03-24 20:54:28 +0100 442)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 443) if (a->rom != 0) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 444) size_t want = a->rom_length;
d84702a5d7b50 drivers/firewire/fw-device-cdev.c (Stefan Richter 2007-03-20 19:42:15 +0100 445) size_t have = client->device->config_rom_length * 4;
344bbc4de14e7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:43 -0500 446)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 447) ret = copy_to_user(u64_to_uptr(a->rom),
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 448) client->device->config_rom, min(want, have));
344bbc4de14e7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:43 -0500 449) }
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 450) a->rom_length = client->device->config_rom_length * 4;
344bbc4de14e7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:43 -0500 451)
c9755e14a0198 drivers/firewire/fw-cdev.c (Stefan Richter 2008-03-24 20:54:28 +0100 452) up_read(&fw_device_rwsem);
c9755e14a0198 drivers/firewire/fw-cdev.c (Stefan Richter 2008-03-24 20:54:28 +0100 453)
c9755e14a0198 drivers/firewire/fw-cdev.c (Stefan Richter 2008-03-24 20:54:28 +0100 454) if (ret != 0)
c9755e14a0198 drivers/firewire/fw-cdev.c (Stefan Richter 2008-03-24 20:54:28 +0100 455) return -EFAULT;
c9755e14a0198 drivers/firewire/fw-cdev.c (Stefan Richter 2008-03-24 20:54:28 +0100 456)
93b37905f7008 drivers/firewire/core-cdev.c (Stefan Richter 2011-07-09 16:43:22 +0200 457) mutex_lock(&client->device->client_list_mutex);
93b37905f7008 drivers/firewire/core-cdev.c (Stefan Richter 2011-07-09 16:43:22 +0200 458)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 459) client->bus_reset_closure = a->bus_reset_closure;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 460) if (a->bus_reset != 0) {
da8ecffaed434 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:39 -0400 461) fill_bus_reset_event(&bus_reset, client);
790198f74c9d1 drivers/firewire/core-cdev.c (Stefan Richter 2012-10-06 14:12:56 +0200 462) /* unaligned size of bus_reset is 36 bytes */
790198f74c9d1 drivers/firewire/core-cdev.c (Stefan Richter 2012-10-06 14:12:56 +0200 463) ret = copy_to_user(u64_to_uptr(a->bus_reset), &bus_reset, 36);
344bbc4de14e7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:43 -0500 464) }
93b37905f7008 drivers/firewire/core-cdev.c (Stefan Richter 2011-07-09 16:43:22 +0200 465) if (ret == 0 && list_empty(&client->link))
93b37905f7008 drivers/firewire/core-cdev.c (Stefan Richter 2011-07-09 16:43:22 +0200 466) list_add_tail(&client->link, &client->device->client_list);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 467)
93b37905f7008 drivers/firewire/core-cdev.c (Stefan Richter 2011-07-09 16:43:22 +0200 468) mutex_unlock(&client->device->client_list_mutex);
93b37905f7008 drivers/firewire/core-cdev.c (Stefan Richter 2011-07-09 16:43:22 +0200 469)
93b37905f7008 drivers/firewire/core-cdev.c (Stefan Richter 2011-07-09 16:43:22 +0200 470) return ret ? -EFAULT : 0;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 471) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 472)
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 473) static int add_client_resource(struct client *client,
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 474) struct client_resource *resource, gfp_t gfp_mask)
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 475) {
d0164adc89f6b drivers/firewire/core-cdev.c (Mel Gorman 2015-11-06 16:28:21 -0800 476) bool preload = gfpflags_allow_blocking(gfp_mask);
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 477) unsigned long flags;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 478) int ret;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 479)
37b61890d757f drivers/firewire/core-cdev.c (Tejun Heo 2013-02-27 17:04:05 -0800 480) if (preload)
37b61890d757f drivers/firewire/core-cdev.c (Tejun Heo 2013-02-27 17:04:05 -0800 481) idr_preload(gfp_mask);
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 482) spin_lock_irqsave(&client->lock, flags);
37b61890d757f drivers/firewire/core-cdev.c (Tejun Heo 2013-02-27 17:04:05 -0800 483)
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 484) if (client->in_shutdown)
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 485) ret = -ECANCELED;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 486) else
37b61890d757f drivers/firewire/core-cdev.c (Tejun Heo 2013-02-27 17:04:05 -0800 487) ret = idr_alloc(&client->resource_idr, resource, 0, 0,
37b61890d757f drivers/firewire/core-cdev.c (Tejun Heo 2013-02-27 17:04:05 -0800 488) GFP_NOWAIT);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 489) if (ret >= 0) {
37b61890d757f drivers/firewire/core-cdev.c (Tejun Heo 2013-02-27 17:04:05 -0800 490) resource->handle = ret;
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 491) client_get(client);
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 492) schedule_if_iso_resource(resource);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 493) }
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 494)
37b61890d757f drivers/firewire/core-cdev.c (Tejun Heo 2013-02-27 17:04:05 -0800 495) spin_unlock_irqrestore(&client->lock, flags);
37b61890d757f drivers/firewire/core-cdev.c (Tejun Heo 2013-02-27 17:04:05 -0800 496) if (preload)
37b61890d757f drivers/firewire/core-cdev.c (Tejun Heo 2013-02-27 17:04:05 -0800 497) idr_preload_end();
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 498)
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 499) return ret < 0 ? ret : 0;
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 500) }
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 501)
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 502) static int release_client_resource(struct client *client, u32 handle,
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 503) client_resource_release_fn_t release,
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 504) struct client_resource **return_resource)
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 505) {
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 506) struct client_resource *resource;
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 507)
3ba949868a6dc drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 508) spin_lock_irq(&client->lock);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 509) if (client->in_shutdown)
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 510) resource = NULL;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 511) else
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 512) resource = idr_find(&client->resource_idr, handle);
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 513) if (resource && resource->release == release)
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 514) idr_remove(&client->resource_idr, handle);
3ba949868a6dc drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 515) spin_unlock_irq(&client->lock);
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 516)
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 517) if (!(resource && resource->release == release))
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 518) return -EINVAL;
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 519)
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 520) if (return_resource)
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 521) *return_resource = resource;
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 522) else
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 523) resource->release(client, resource);
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 524)
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 525) client_put(client);
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 526)
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 527) return 0;
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 528) }
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 529)
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 530) static void release_transaction(struct client *client,
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 531) struct client_resource *resource)
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 532) {
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 533) }
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 534)
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 535) static void complete_transaction(struct fw_card *card, int rcode,
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 536) void *payload, size_t length, void *data)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 537) {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 538) struct outbound_transaction_event *e = data;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 539) struct fw_cdev_event_response *rsp = &e->response;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 540) struct client *client = e->client;
28cf6a04c8285 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:50 -0500 541) unsigned long flags;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 542)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 543) if (length < rsp->length)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 544) rsp->length = length;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 545) if (rcode == RCODE_COMPLETE)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 546) memcpy(rsp->data, payload, rsp->length);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 547)
28cf6a04c8285 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:50 -0500 548) spin_lock_irqsave(&client->lock, flags);
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 549) idr_remove(&client->resource_idr, e->r.resource.handle);
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 550) if (client->in_shutdown)
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 551) wake_up(&client->tx_flush_wait);
28cf6a04c8285 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:50 -0500 552) spin_unlock_irqrestore(&client->lock, flags);
28cf6a04c8285 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:50 -0500 553)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 554) rsp->type = FW_CDEV_EVENT_RESPONSE;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 555) rsp->rcode = rcode;
8401d92ba46a1 drivers/firewire/fw-cdev.c (David Moore 2008-07-29 23:46:25 -0700 556)
8401d92ba46a1 drivers/firewire/fw-cdev.c (David Moore 2008-07-29 23:46:25 -0700 557) /*
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 558) * In the case that sizeof(*rsp) doesn't align with the position of the
8401d92ba46a1 drivers/firewire/fw-cdev.c (David Moore 2008-07-29 23:46:25 -0700 559) * data, and the read is short, preserve an extra copy of the data
8401d92ba46a1 drivers/firewire/fw-cdev.c (David Moore 2008-07-29 23:46:25 -0700 560) * to stay compatible with a pre-2.6.27 bug. Since the bug is harmless
8401d92ba46a1 drivers/firewire/fw-cdev.c (David Moore 2008-07-29 23:46:25 -0700 561) * for short reads and some apps depended on it, this is both safe
8401d92ba46a1 drivers/firewire/fw-cdev.c (David Moore 2008-07-29 23:46:25 -0700 562) * and prudent for compatibility.
8401d92ba46a1 drivers/firewire/fw-cdev.c (David Moore 2008-07-29 23:46:25 -0700 563) */
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 564) if (rsp->length <= sizeof(*rsp) - offsetof(typeof(*rsp), data))
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 565) queue_event(client, &e->event, rsp, sizeof(*rsp),
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 566) rsp->data, rsp->length);
8401d92ba46a1 drivers/firewire/fw-cdev.c (David Moore 2008-07-29 23:46:25 -0700 567) else
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 568) queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length,
8401d92ba46a1 drivers/firewire/fw-cdev.c (David Moore 2008-07-29 23:46:25 -0700 569) NULL, 0);
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 570)
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 571) /* Drop the idr's reference */
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 572) client_put(client);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 573) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 574)
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 575) static int init_request(struct client *client,
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 576) struct fw_cdev_send_request *request,
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 577) int destination_id, int speed)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 578) {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 579) struct outbound_transaction_event *e;
1f3125af8ed74 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-05 22:44:42 +0100 580) int ret;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 581)
18e9b10fcdc09 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 21:02:21 +0100 582) if (request->tcode != TCODE_STREAM_DATA &&
18e9b10fcdc09 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 21:02:21 +0100 583) (request->length > 4096 || request->length > 512 << speed))
5d3fd692a7196 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 584) return -EIO;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 585)
a8e93f3dccc06 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-07-07 14:37:30 +0200 586) if (request->tcode == TCODE_WRITE_QUADLET_REQUEST &&
a8e93f3dccc06 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-07-07 14:37:30 +0200 587) request->length < 4)
a8e93f3dccc06 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-07-07 14:37:30 +0200 588) return -EINVAL;
a8e93f3dccc06 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-07-07 14:37:30 +0200 589)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 590) e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL);
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 591) if (e == NULL)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 592) return -ENOMEM;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 593)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 594) e->client = client;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 595) e->response.length = request->length;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 596) e->response.closure = request->closure;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 597)
4f2592232ea95 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:13 -0400 598) if (request->data &&
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 599) copy_from_user(e->response.data,
4f2592232ea95 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:13 -0400 600) u64_to_uptr(request->data), request->length)) {
1f3125af8ed74 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-05 22:44:42 +0100 601) ret = -EFAULT;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 602) goto failed;
1f3125af8ed74 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-05 22:44:42 +0100 603) }
1f3125af8ed74 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-05 22:44:42 +0100 604)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 605) e->r.resource.release = release_transaction;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 606) ret = add_client_resource(client, &e->r.resource, GFP_KERNEL);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 607) if (ret < 0)
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 608) goto failed;
28cf6a04c8285 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:50 -0500 609)
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 610) fw_send_request(client->device->card, &e->r.transaction,
664d8010b170a drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 21:01:54 +0100 611) request->tcode, destination_id, request->generation,
664d8010b170a drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 21:01:54 +0100 612) speed, request->offset, e->response.data,
664d8010b170a drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 21:01:54 +0100 613) request->length, complete_transaction, e);
664d8010b170a drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 21:01:54 +0100 614) return 0;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 615)
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 616) failed:
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 617) kfree(e);
1f3125af8ed74 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-05 22:44:42 +0100 618)
1f3125af8ed74 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-05 22:44:42 +0100 619) return ret;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 620) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 621)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 622) static int ioctl_send_request(struct client *client, union ioctl_arg *arg)
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 623) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 624) switch (arg->send_request.tcode) {
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 625) case TCODE_WRITE_QUADLET_REQUEST:
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 626) case TCODE_WRITE_BLOCK_REQUEST:
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 627) case TCODE_READ_QUADLET_REQUEST:
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 628) case TCODE_READ_BLOCK_REQUEST:
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 629) case TCODE_LOCK_MASK_SWAP:
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 630) case TCODE_LOCK_COMPARE_SWAP:
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 631) case TCODE_LOCK_FETCH_ADD:
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 632) case TCODE_LOCK_LITTLE_ADD:
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 633) case TCODE_LOCK_BOUNDED_ADD:
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 634) case TCODE_LOCK_WRAP_ADD:
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 635) case TCODE_LOCK_VENDOR_DEPENDENT:
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 636) break;
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 637) default:
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 638) return -EINVAL;
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 639) }
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 640)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 641) return init_request(client, &arg->send_request, client->device->node_id,
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 642) client->device->max_speed);
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 643) }
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 644)
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 645) static inline bool is_fcp_request(struct fw_request *request)
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 646) {
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 647) return request == NULL;
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 648) }
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 649)
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 650) static void release_request(struct client *client,
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 651) struct client_resource *resource)
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 652) {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 653) struct inbound_transaction_resource *r = container_of(resource,
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 654) struct inbound_transaction_resource, resource);
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 655)
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 656) if (is_fcp_request(r->request))
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 657) kfree(r->data);
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 658) else
08bd34c98d631 drivers/firewire/core-cdev.c (Jay Fenlason 2010-05-18 14:02:45 -0400 659) fw_send_response(r->card, r->request, RCODE_CONFLICT_ERROR);
0244f57302f7e drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:52:27 +0200 660)
0244f57302f7e drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:52:27 +0200 661) fw_card_put(r->card);
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 662) kfree(r);
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 663) }
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 664)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 665) static void handle_request(struct fw_card *card, struct fw_request *request,
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 666) int tcode, int destination, int source,
33e553fe2b4a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:50:35 +0200 667) int generation, unsigned long long offset,
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 668) void *payload, size_t length, void *callback_data)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 669) {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 670) struct address_handler_resource *handler = callback_data;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 671) struct inbound_transaction_resource *r;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 672) struct inbound_transaction_event *e;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 673) size_t event_size0;
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 674) void *fcp_frame = NULL;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 675) int ret;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 676)
0244f57302f7e drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:52:27 +0200 677) /* card may be different from handler->client->device->card */
0244f57302f7e drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:52:27 +0200 678) fw_card_get(card);
0244f57302f7e drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:52:27 +0200 679)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 680) r = kmalloc(sizeof(*r), GFP_ATOMIC);
2d826cc5c791b drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-09 19:23:14 -0400 681) e = kmalloc(sizeof(*e), GFP_ATOMIC);
cfb0c9d1ffbf9 drivers/firewire/core-cdev.c (Stefan Richter 2013-03-24 17:32:00 +0100 682) if (r == NULL || e == NULL)
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 683) goto failed;
cfb0c9d1ffbf9 drivers/firewire/core-cdev.c (Stefan Richter 2013-03-24 17:32:00 +0100 684)
08bd34c98d631 drivers/firewire/core-cdev.c (Jay Fenlason 2010-05-18 14:02:45 -0400 685) r->card = card;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 686) r->request = request;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 687) r->data = payload;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 688) r->length = length;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 689)
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 690) if (is_fcp_request(request)) {
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 691) /*
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 692) * FIXME: Let core-transaction.c manage a
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 693) * single reference-counted copy?
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 694) */
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 695) fcp_frame = kmemdup(payload, length, GFP_ATOMIC);
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 696) if (fcp_frame == NULL)
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 697) goto failed;
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 698)
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 699) r->data = fcp_frame;
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 700) }
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 701)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 702) r->resource.release = release_request;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 703) ret = add_client_resource(handler->client, &r->resource, GFP_ATOMIC);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 704) if (ret < 0)
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 705) goto failed;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 706)
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 707) if (handler->client->version < FW_CDEV_VERSION_EVENT_REQUEST2) {
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 708) struct fw_cdev_event_request *req = &e->req.request;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 709)
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 710) if (tcode & 0x10)
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 711) tcode = TCODE_LOCK_REQUEST;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 712)
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 713) req->type = FW_CDEV_EVENT_REQUEST;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 714) req->tcode = tcode;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 715) req->offset = offset;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 716) req->length = length;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 717) req->handle = r->resource.handle;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 718) req->closure = handler->closure;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 719) event_size0 = sizeof(*req);
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 720) } else {
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 721) struct fw_cdev_event_request2 *req = &e->req.request2;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 722)
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 723) req->type = FW_CDEV_EVENT_REQUEST2;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 724) req->tcode = tcode;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 725) req->offset = offset;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 726) req->source_node_id = source;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 727) req->destination_node_id = destination;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 728) req->card = card->index;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 729) req->generation = generation;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 730) req->length = length;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 731) req->handle = r->resource.handle;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 732) req->closure = handler->closure;
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 733) event_size0 = sizeof(*req);
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 734) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 735)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 736) queue_event(handler->client, &e->event,
e205597d188a9 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:53:55 +0200 737) &e->req, event_size0, r->data, length);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 738) return;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 739)
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 740) failed:
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 741) kfree(r);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 742) kfree(e);
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 743) kfree(fcp_frame);
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 744)
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 745) if (!is_fcp_request(request))
db5d247ae811f drivers/firewire/core-cdev.c (Clemens Ladisch 2009-12-24 12:05:58 +0100 746) fw_send_response(card, request, RCODE_CONFLICT_ERROR);
0244f57302f7e drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:52:27 +0200 747)
0244f57302f7e drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:52:27 +0200 748) fw_card_put(card);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 749) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 750)
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 751) static void release_address_handler(struct client *client,
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 752) struct client_resource *resource)
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 753) {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 754) struct address_handler_resource *r =
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 755) container_of(resource, struct address_handler_resource, resource);
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 756)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 757) fw_core_remove_address_handler(&r->handler);
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 758) kfree(r);
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 759) }
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 760)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 761) static int ioctl_allocate(struct client *client, union ioctl_arg *arg)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 762) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 763) struct fw_cdev_allocate *a = &arg->allocate;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 764) struct address_handler_resource *r;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 765) struct fw_address_region region;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 766) int ret;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 767)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 768) r = kmalloc(sizeof(*r), GFP_KERNEL);
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 769) if (r == NULL)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 770) return -ENOMEM;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 771)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 772) region.start = a->offset;
8e2b2b46ea4ca drivers/firewire/core-cdev.c (Stefan Richter 2010-07-23 13:05:39 +0200 773) if (client->version < FW_CDEV_VERSION_ALLOCATE_REGION_END)
8e2b2b46ea4ca drivers/firewire/core-cdev.c (Stefan Richter 2010-07-23 13:05:39 +0200 774) region.end = a->offset + a->length;
8e2b2b46ea4ca drivers/firewire/core-cdev.c (Stefan Richter 2010-07-23 13:05:39 +0200 775) else
8e2b2b46ea4ca drivers/firewire/core-cdev.c (Stefan Richter 2010-07-23 13:05:39 +0200 776) region.end = a->region_end;
8e2b2b46ea4ca drivers/firewire/core-cdev.c (Stefan Richter 2010-07-23 13:05:39 +0200 777)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 778) r->handler.length = a->length;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 779) r->handler.address_callback = handle_request;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 780) r->handler.callback_data = r;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 781) r->closure = a->closure;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 782) r->client = client;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 783)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 784) ret = fw_core_add_address_handler(&r->handler, ®ion);
3e0b5f0d7cb5f drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 19:21:01 +0100 785) if (ret < 0) {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 786) kfree(r);
3e0b5f0d7cb5f drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 19:21:01 +0100 787) return ret;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 788) }
8e2b2b46ea4ca drivers/firewire/core-cdev.c (Stefan Richter 2010-07-23 13:05:39 +0200 789) a->offset = r->handler.offset;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 790)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 791) r->resource.release = release_address_handler;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 792) ret = add_client_resource(client, &r->resource, GFP_KERNEL);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 793) if (ret < 0) {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 794) release_address_handler(client, &r->resource);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 795) return ret;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 796) }
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 797) a->handle = r->resource.handle;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 798)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 799) return 0;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 800) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 801)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 802) static int ioctl_deallocate(struct client *client, union ioctl_arg *arg)
9472316b6eab3 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-14 17:34:55 -0400 803) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 804) return release_client_resource(client, arg->deallocate.handle,
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 805) release_address_handler, NULL);
9472316b6eab3 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-14 17:34:55 -0400 806) }
9472316b6eab3 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-14 17:34:55 -0400 807)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 808) static int ioctl_send_response(struct client *client, union ioctl_arg *arg)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 809) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 810) struct fw_cdev_send_response *a = &arg->send_response;
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 811) struct client_resource *resource;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 812) struct inbound_transaction_resource *r;
7e44c0b56b07a drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:39:56 +0200 813) int ret = 0;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 814)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 815) if (release_client_resource(client, a->handle,
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 816) release_request, &resource) < 0)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 817) return -EINVAL;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 818)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 819) r = container_of(resource, struct inbound_transaction_resource,
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 820) resource);
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 821) if (is_fcp_request(r->request))
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 822) goto out;
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 823)
a10c0ce760988 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-05-19 08:28:32 +0200 824) if (a->length != fw_get_response_length(r->request)) {
a10c0ce760988 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-05-19 08:28:32 +0200 825) ret = -EINVAL;
a10c0ce760988 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-05-19 08:28:32 +0200 826) kfree(r->request);
a10c0ce760988 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-05-19 08:28:32 +0200 827) goto out;
a10c0ce760988 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-05-19 08:28:32 +0200 828) }
a10c0ce760988 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-05-19 08:28:32 +0200 829) if (copy_from_user(r->data, u64_to_uptr(a->data), a->length)) {
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 830) ret = -EFAULT;
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 831) kfree(r->request);
281e20323ab72 drivers/firewire/core-cdev.c (Stefan Richter 2010-01-24 16:45:03 +0100 832) goto out;
7e44c0b56b07a drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:39:56 +0200 833) }
08bd34c98d631 drivers/firewire/core-cdev.c (Jay Fenlason 2010-05-18 14:02:45 -0400 834) fw_send_response(r->card, r->request, a->rcode);
7e44c0b56b07a drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:39:56 +0200 835) out:
0244f57302f7e drivers/firewire/core-cdev.c (Stefan Richter 2010-06-20 22:52:27 +0200 836) fw_card_put(r->card);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 837) kfree(r);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 838)
7e44c0b56b07a drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:39:56 +0200 839) return ret;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 840) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 841)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 842) static int ioctl_initiate_bus_reset(struct client *client, union ioctl_arg *arg)
5371842b723dd drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:42 -0500 843) {
02d37bed188c5 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-08 16:09:06 +0200 844) fw_schedule_bus_reset(client->device->card, true,
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 845) arg->initiate_bus_reset.type == FW_CDEV_SHORT_RESET);
02d37bed188c5 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-08 16:09:06 +0200 846) return 0;
5371842b723dd drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:42 -0500 847) }
5371842b723dd drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:42 -0500 848)
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 849) static void release_descriptor(struct client *client,
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 850) struct client_resource *resource)
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 851) {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 852) struct descriptor_resource *r =
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 853) container_of(resource, struct descriptor_resource, resource);
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 854)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 855) fw_core_remove_descriptor(&r->descriptor);
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 856) kfree(r);
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 857) }
3964a4496eaa4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-27 01:43:41 -0400 858)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 859) static int ioctl_add_descriptor(struct client *client, union ioctl_arg *arg)
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 860) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 861) struct fw_cdev_add_descriptor *a = &arg->add_descriptor;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 862) struct descriptor_resource *r;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 863) int ret;
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 864)
de487da8ca583 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 21:00:23 +0100 865) /* Access policy: Allow this ioctl only on local nodes' device files. */
92368890d5517 drivers/firewire/fw-cdev.c (Stefan Richter 2009-05-13 21:42:14 +0200 866) if (!client->device->is_local)
de487da8ca583 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 21:00:23 +0100 867) return -ENOSYS;
de487da8ca583 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 21:00:23 +0100 868)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 869) if (a->length > 256)
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 870) return -EINVAL;
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 871)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 872) r = kmalloc(sizeof(*r) + a->length * 4, GFP_KERNEL);
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 873) if (r == NULL)
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 874) return -ENOMEM;
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 875)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 876) if (copy_from_user(r->data, u64_to_uptr(a->data), a->length * 4)) {
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 877) ret = -EFAULT;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 878) goto failed;
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 879) }
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 880)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 881) r->descriptor.length = a->length;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 882) r->descriptor.immediate = a->immediate;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 883) r->descriptor.key = a->key;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 884) r->descriptor.data = r->data;
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 885)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 886) ret = fw_core_add_descriptor(&r->descriptor);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 887) if (ret < 0)
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 888) goto failed;
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 889)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 890) r->resource.release = release_descriptor;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 891) ret = add_client_resource(client, &r->resource, GFP_KERNEL);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 892) if (ret < 0) {
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 893) fw_core_remove_descriptor(&r->descriptor);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 894) goto failed;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 895) }
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 896) a->handle = r->resource.handle;
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 897)
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 898) return 0;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 899) failed:
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 900) kfree(r);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 901)
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 902) return ret;
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 903) }
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 904)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 905) static int ioctl_remove_descriptor(struct client *client, union ioctl_arg *arg)
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 906) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 907) return release_client_resource(client, arg->remove_descriptor.handle,
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 908) release_descriptor, NULL);
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 909) }
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 910)
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 911) static void iso_callback(struct fw_iso_context *context, u32 cycle,
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 912) size_t header_length, void *header, void *data)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 913) {
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 914) struct client *client = data;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 915) struct iso_interrupt_event *e;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 916)
56d04cb189f95 drivers/firewire/core-cdev.c (Stefan Richter 2010-06-08 00:20:10 +0200 917) e = kmalloc(sizeof(*e) + header_length, GFP_ATOMIC);
cfb0c9d1ffbf9 drivers/firewire/core-cdev.c (Stefan Richter 2013-03-24 17:32:00 +0100 918) if (e == NULL)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 919) return;
cfb0c9d1ffbf9 drivers/firewire/core-cdev.c (Stefan Richter 2013-03-24 17:32:00 +0100 920)
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 921) e->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 922) e->interrupt.closure = client->iso_closure;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 923) e->interrupt.cycle = cycle;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 924) e->interrupt.header_length = header_length;
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 925) memcpy(e->interrupt.header, header, header_length);
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 926) queue_event(client, &e->event, &e->interrupt,
97c18b7fd6df4 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 927) sizeof(e->interrupt) + header_length, NULL, 0);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 928) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 929)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 930) static void iso_mc_callback(struct fw_iso_context *context,
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 931) dma_addr_t completed, void *data)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 932) {
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 933) struct client *client = data;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 934) struct iso_interrupt_mc_event *e;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 935)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 936) e = kmalloc(sizeof(*e), GFP_ATOMIC);
cfb0c9d1ffbf9 drivers/firewire/core-cdev.c (Stefan Richter 2013-03-24 17:32:00 +0100 937) if (e == NULL)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 938) return;
cfb0c9d1ffbf9 drivers/firewire/core-cdev.c (Stefan Richter 2013-03-24 17:32:00 +0100 939)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 940) e->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 941) e->interrupt.closure = client->iso_closure;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 942) e->interrupt.completed = fw_iso_buffer_lookup(&client->buffer,
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 943) completed);
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 944) queue_event(client, &e->event, &e->interrupt,
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 945) sizeof(e->interrupt), NULL, 0);
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 946) }
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 947)
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 948) static enum dma_data_direction iso_dma_direction(struct fw_iso_context *context)
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 949) {
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 950) if (context->type == FW_ISO_CONTEXT_TRANSMIT)
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 951) return DMA_TO_DEVICE;
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 952) else
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 953) return DMA_FROM_DEVICE;
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 954) }
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 955)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 956) static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 957) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 958) struct fw_cdev_create_iso_context *a = &arg->create_iso_context;
24315c5e6f508 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-06-20 17:48:07 -0400 959) struct fw_iso_context *context;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 960) fw_iso_callback_t cb;
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 961) int ret;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 962)
eb5b35a560510 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-07 14:13:14 +0200 963) BUILD_BUG_ON(FW_CDEV_ISO_CONTEXT_TRANSMIT != FW_ISO_CONTEXT_TRANSMIT ||
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 964) FW_CDEV_ISO_CONTEXT_RECEIVE != FW_ISO_CONTEXT_RECEIVE ||
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 965) FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL !=
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 966) FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL);
21efb3cfc6ed4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:50 -0500 967)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 968) switch (a->type) {
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 969) case FW_ISO_CONTEXT_TRANSMIT:
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 970) if (a->speed > SCODE_3200 || a->channel > 63)
c70dc788fd8d3 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-14 17:34:53 -0400 971) return -EINVAL;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 972)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 973) cb = iso_callback;
c70dc788fd8d3 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-14 17:34:53 -0400 974) break;
c70dc788fd8d3 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-14 17:34:53 -0400 975)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 976) case FW_ISO_CONTEXT_RECEIVE:
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 977) if (a->header_size < 4 || (a->header_size & 3) ||
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 978) a->channel > 63)
c70dc788fd8d3 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-14 17:34:53 -0400 979) return -EINVAL;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 980)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 981) cb = iso_callback;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 982) break;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 983)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 984) case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 985) cb = (fw_iso_callback_t)iso_mc_callback;
c70dc788fd8d3 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-14 17:34:53 -0400 986) break;
c70dc788fd8d3 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-14 17:34:53 -0400 987)
c70dc788fd8d3 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-14 17:34:53 -0400 988) default:
21efb3cfc6ed4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:50 -0500 989) return -EINVAL;
c70dc788fd8d3 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-14 17:34:53 -0400 990) }
c70dc788fd8d3 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-14 17:34:53 -0400 991)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 992) context = fw_iso_context_create(client->device->card, a->type,
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 993) a->channel, a->speed, a->header_size, cb, client);
24315c5e6f508 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-06-20 17:48:07 -0400 994) if (IS_ERR(context))
24315c5e6f508 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-06-20 17:48:07 -0400 995) return PTR_ERR(context);
0699a73af3811 drivers/firewire/core-cdev.c (Clemens Ladisch 2013-07-22 21:32:09 +0200 996) if (client->version < FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW)
0699a73af3811 drivers/firewire/core-cdev.c (Clemens Ladisch 2013-07-22 21:32:09 +0200 997) context->drop_overflow_headers = true;
24315c5e6f508 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-06-20 17:48:07 -0400 998)
bdfe273ee54b2 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-06-14 11:46:25 +0200 999) /* We only support one context at this time. */
bdfe273ee54b2 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-06-14 11:46:25 +0200 1000) spin_lock_irq(&client->lock);
bdfe273ee54b2 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-06-14 11:46:25 +0200 1001) if (client->iso_context != NULL) {
bdfe273ee54b2 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-06-14 11:46:25 +0200 1002) spin_unlock_irq(&client->lock);
bdfe273ee54b2 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-06-14 11:46:25 +0200 1003) fw_iso_context_destroy(context);
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1004)
bdfe273ee54b2 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-06-14 11:46:25 +0200 1005) return -EBUSY;
bdfe273ee54b2 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-06-14 11:46:25 +0200 1006) }
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1007) if (!client->buffer_is_mapped) {
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1008) ret = fw_iso_buffer_map_dma(&client->buffer,
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1009) client->device->card,
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1010) iso_dma_direction(context));
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1011) if (ret < 0) {
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1012) spin_unlock_irq(&client->lock);
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1013) fw_iso_context_destroy(context);
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1014)
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1015) return ret;
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1016) }
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1017) client->buffer_is_mapped = true;
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1018) }
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1019) client->iso_closure = a->closure;
24315c5e6f508 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-06-20 17:48:07 -0400 1020) client->iso_context = context;
bdfe273ee54b2 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-06-14 11:46:25 +0200 1021) spin_unlock_irq(&client->lock);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1022)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1023) a->handle = 0;
abaa5743e340c drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:14 -0400 1024)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1025) return 0;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1026) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1027)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1028) static int ioctl_set_iso_channels(struct client *client, union ioctl_arg *arg)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1029) {
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1030) struct fw_cdev_set_iso_channels *a = &arg->set_iso_channels;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1031) struct fw_iso_context *ctx = client->iso_context;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1032)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1033) if (ctx == NULL || a->handle != 0)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1034) return -EINVAL;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1035)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1036) return fw_iso_context_set_channels(ctx, &a->channels);
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1037) }
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1038)
1ca31ae7cfed3 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-31 11:16:43 -0400 1039) /* Macros for decoding the iso packet control header. */
1ca31ae7cfed3 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-31 11:16:43 -0400 1040) #define GET_PAYLOAD_LENGTH(v) ((v) & 0xffff)
1ca31ae7cfed3 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-31 11:16:43 -0400 1041) #define GET_INTERRUPT(v) (((v) >> 16) & 0x01)
1ca31ae7cfed3 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-31 11:16:43 -0400 1042) #define GET_SKIP(v) (((v) >> 17) & 0x01)
7a1003449c693 drivers/firewire/fw-cdev.c (Stefan Richter 2008-09-12 18:09:55 +0200 1043) #define GET_TAG(v) (((v) >> 18) & 0x03)
7a1003449c693 drivers/firewire/fw-cdev.c (Stefan Richter 2008-09-12 18:09:55 +0200 1044) #define GET_SY(v) (((v) >> 20) & 0x0f)
1ca31ae7cfed3 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-31 11:16:43 -0400 1045) #define GET_HEADER_LENGTH(v) (((v) >> 24) & 0xff)
1ca31ae7cfed3 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-31 11:16:43 -0400 1046)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1047) static int ioctl_queue_iso(struct client *client, union ioctl_arg *arg)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1048) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1049) struct fw_cdev_queue_iso *a = &arg->queue_iso;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1050) struct fw_cdev_iso_packet __user *p, *end, *next;
9b32d5f3074e9 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:44 -0500 1051) struct fw_iso_context *ctx = client->iso_context;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1052) unsigned long payload, buffer_end, transmit_header_bytes = 0;
1ca31ae7cfed3 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-31 11:16:43 -0400 1053) u32 control;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1054) int count;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1055) struct {
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1056) struct fw_iso_packet packet;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1057) u8 header[256];
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1058) } u;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1059)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1060) if (ctx == NULL || a->handle != 0)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1061) return -EINVAL;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1062)
c781c06d119d0 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-07 20:33:32 -0400 1063) /*
c781c06d119d0 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-07 20:33:32 -0400 1064) * If the user passes a non-NULL data pointer, has mmap()'ed
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1065) * the iso buffer, and the pointer points inside the buffer,
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1066) * we setup the payload pointers accordingly. Otherwise we
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 1067) * set them both to 0, which will still let packets with
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1068) * payload_length == 0 through. In other words, if no packets
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1069) * use the indirect payload, the iso buffer need not be mapped
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1070) * and the a->data pointer is ignored.
c781c06d119d0 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-07 20:33:32 -0400 1071) */
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1072) payload = (unsigned long)a->data - client->vm_start;
ef370ee74b7a9 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 20:46:23 +0200 1073) buffer_end = client->buffer.page_count << PAGE_SHIFT;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1074) if (a->data == 0 || client->buffer.pages == NULL ||
ef370ee74b7a9 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 20:46:23 +0200 1075) payload >= buffer_end) {
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 1076) payload = 0;
ef370ee74b7a9 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 20:46:23 +0200 1077) buffer_end = 0;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1078) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1079)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1080) if (ctx->type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL && payload & 3)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1081) return -EINVAL;
1ccc9147f6a06 drivers/firewire/fw-cdev.c (Al Viro 2007-10-14 19:34:40 +0100 1082)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1083) p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(a->packets);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1084)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1085) end = (void __user *)p + a->size;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1086) count = 0;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1087) while (p < end) {
1ca31ae7cfed3 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-31 11:16:43 -0400 1088) if (get_user(control, &p->control))
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1089) return -EFAULT;
1ca31ae7cfed3 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-31 11:16:43 -0400 1090) u.packet.payload_length = GET_PAYLOAD_LENGTH(control);
1ca31ae7cfed3 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-31 11:16:43 -0400 1091) u.packet.interrupt = GET_INTERRUPT(control);
1ca31ae7cfed3 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-31 11:16:43 -0400 1092) u.packet.skip = GET_SKIP(control);
1ca31ae7cfed3 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-31 11:16:43 -0400 1093) u.packet.tag = GET_TAG(control);
1ca31ae7cfed3 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-31 11:16:43 -0400 1094) u.packet.sy = GET_SY(control);
1ca31ae7cfed3 drivers/firewire/fw-cdev.c (Kristian Høgsberg 2007-05-31 11:16:43 -0400 1095) u.packet.header_length = GET_HEADER_LENGTH(control);
295e3feb92e50 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:40 -0500 1096)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1097) switch (ctx->type) {
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1098) case FW_ISO_CONTEXT_TRANSMIT:
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1099) if (u.packet.header_length & 3)
385ab5bcd4be5 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-03-31 16:26:46 +0200 1100) return -EINVAL;
ae2a97661482c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 09:31:56 +0200 1101) transmit_header_bytes = u.packet.header_length;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1102) break;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1103)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1104) case FW_ISO_CONTEXT_RECEIVE:
69e61d0c07fa2 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-28 23:49:45 +0200 1105) if (u.packet.header_length == 0 ||
69e61d0c07fa2 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-28 23:49:45 +0200 1106) u.packet.header_length % ctx->header_size != 0)
385ab5bcd4be5 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-03-31 16:26:46 +0200 1107) return -EINVAL;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1108) break;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1109)
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1110) case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1111) if (u.packet.payload_length == 0 ||
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1112) u.packet.payload_length & 3)
295e3feb92e50 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:40 -0500 1113) return -EINVAL;
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1114) break;
295e3feb92e50 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:40 -0500 1115) }
295e3feb92e50 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:40 -0500 1116)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1117) next = (struct fw_cdev_iso_packet __user *)
ae2a97661482c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 09:31:56 +0200 1118) &p->header[transmit_header_bytes / 4];
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1119) if (next > end)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1120) return -EINVAL;
daa98831dddc8 drivers/firewire/core-cdev.c (Al Viro 2020-02-18 15:40:40 -0500 1121) if (copy_from_user
ae2a97661482c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 09:31:56 +0200 1122) (u.packet.header, p->header, transmit_header_bytes))
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1123) return -EFAULT;
98b6cbe83b6e8 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:51 -0500 1124) if (u.packet.skip && ctx->type == FW_ISO_CONTEXT_TRANSMIT &&
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1125) u.packet.header_length + u.packet.payload_length > 0)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1126) return -EINVAL;
ef370ee74b7a9 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 20:46:23 +0200 1127) if (payload + u.packet.payload_length > buffer_end)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1128) return -EINVAL;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1129)
9b32d5f3074e9 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:44 -0500 1130) if (fw_iso_context_queue(ctx, &u.packet,
9b32d5f3074e9 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:44 -0500 1131) &client->buffer, payload))
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1132) break;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1133)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1134) p = next;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1135) payload += u.packet.payload_length;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1136) count++;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1137) }
13882a82ee164 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-05-02 09:33:56 +0200 1138) fw_iso_context_queue_flush(ctx);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1139)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1140) a->size -= uptr_to_u64(p) - a->packets;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1141) a->packets = uptr_to_u64(p);
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1142) a->data = client->vm_start + payload;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1143)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1144) return count;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1145) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1146)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1147) static int ioctl_start_iso(struct client *client, union ioctl_arg *arg)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1148) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1149) struct fw_cdev_start_iso *a = &arg->start_iso;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1150)
eb5b35a560510 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-07 14:13:14 +0200 1151) BUILD_BUG_ON(
eb5b35a560510 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-07 14:13:14 +0200 1152) FW_CDEV_ISO_CONTEXT_MATCH_TAG0 != FW_ISO_CONTEXT_MATCH_TAG0 ||
eb5b35a560510 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-07 14:13:14 +0200 1153) FW_CDEV_ISO_CONTEXT_MATCH_TAG1 != FW_ISO_CONTEXT_MATCH_TAG1 ||
eb5b35a560510 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-07 14:13:14 +0200 1154) FW_CDEV_ISO_CONTEXT_MATCH_TAG2 != FW_ISO_CONTEXT_MATCH_TAG2 ||
eb5b35a560510 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-07 14:13:14 +0200 1155) FW_CDEV_ISO_CONTEXT_MATCH_TAG3 != FW_ISO_CONTEXT_MATCH_TAG3 ||
eb5b35a560510 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-07 14:13:14 +0200 1156) FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS != FW_ISO_CONTEXT_MATCH_ALL_TAGS);
eb5b35a560510 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-07 14:13:14 +0200 1157)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1158) if (client->iso_context == NULL || a->handle != 0)
abaa5743e340c drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:14 -0400 1159) return -EINVAL;
fae603121428b drivers/firewire/fw-cdev.c (Stefan Richter 2008-02-20 21:10:06 +0100 1160)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1161) if (client->iso_context->type == FW_ISO_CONTEXT_RECEIVE &&
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1162) (a->tags == 0 || a->tags > 15 || a->sync > 15))
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1163) return -EINVAL;
eb0306eac0aad drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-14 17:34:54 -0400 1164)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1165) return fw_iso_context_start(client->iso_context,
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1166) a->cycle, a->sync, a->tags);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1167) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1168)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1169) static int ioctl_stop_iso(struct client *client, union ioctl_arg *arg)
b82956685aab4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:42 -0500 1170) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1171) struct fw_cdev_stop_iso *a = &arg->stop_iso;
abaa5743e340c drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:14 -0400 1172)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1173) if (client->iso_context == NULL || a->handle != 0)
abaa5743e340c drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:14 -0400 1174) return -EINVAL;
abaa5743e340c drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:14 -0400 1175)
b82956685aab4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:42 -0500 1176) return fw_iso_context_stop(client->iso_context);
b82956685aab4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:42 -0500 1177) }
b82956685aab4 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:42 -0500 1178)
d1bbd20972936 drivers/firewire/core-cdev.c (Clemens Ladisch 2012-03-18 19:06:39 +0100 1179) static int ioctl_flush_iso(struct client *client, union ioctl_arg *arg)
d1bbd20972936 drivers/firewire/core-cdev.c (Clemens Ladisch 2012-03-18 19:06:39 +0100 1180) {
d1bbd20972936 drivers/firewire/core-cdev.c (Clemens Ladisch 2012-03-18 19:06:39 +0100 1181) struct fw_cdev_flush_iso *a = &arg->flush_iso;
d1bbd20972936 drivers/firewire/core-cdev.c (Clemens Ladisch 2012-03-18 19:06:39 +0100 1182)
d1bbd20972936 drivers/firewire/core-cdev.c (Clemens Ladisch 2012-03-18 19:06:39 +0100 1183) if (client->iso_context == NULL || a->handle != 0)
d1bbd20972936 drivers/firewire/core-cdev.c (Clemens Ladisch 2012-03-18 19:06:39 +0100 1184) return -EINVAL;
d1bbd20972936 drivers/firewire/core-cdev.c (Clemens Ladisch 2012-03-18 19:06:39 +0100 1185)
d1bbd20972936 drivers/firewire/core-cdev.c (Clemens Ladisch 2012-03-18 19:06:39 +0100 1186) return fw_iso_context_flush_completions(client->iso_context);
d1bbd20972936 drivers/firewire/core-cdev.c (Clemens Ladisch 2012-03-18 19:06:39 +0100 1187) }
d1bbd20972936 drivers/firewire/core-cdev.c (Clemens Ladisch 2012-03-18 19:06:39 +0100 1188)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1189) static int ioctl_get_cycle_timer2(struct client *client, union ioctl_arg *arg)
a64408b96b5f6 drivers/firewire/fw-cdev.c (Stefan Richter 2007-09-29 10:41:58 +0200 1190) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1191) struct fw_cdev_get_cycle_timer2 *a = &arg->get_cycle_timer2;
a64408b96b5f6 drivers/firewire/fw-cdev.c (Stefan Richter 2007-09-29 10:41:58 +0200 1192) struct fw_card *card = client->device->card;
2c1bb29aa6e7b drivers/firewire/core-cdev.c (Arnd Bergmann 2018-08-17 15:43:44 -0700 1193) struct timespec64 ts = {0, 0};
4a9bde9b8ab55 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 22:24:43 +0100 1194) u32 cycle_time;
abfe5a01ef1e4 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 12:13:49 +0100 1195) int ret = 0;
a64408b96b5f6 drivers/firewire/fw-cdev.c (Stefan Richter 2007-09-29 10:41:58 +0200 1196)
4a9bde9b8ab55 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 22:24:43 +0100 1197) local_irq_disable();
a64408b96b5f6 drivers/firewire/fw-cdev.c (Stefan Richter 2007-09-29 10:41:58 +0200 1198)
0fcff4e39323f drivers/firewire/core-cdev.c (Stefan Richter 2010-06-12 20:35:52 +0200 1199) cycle_time = card->driver->read_csr(card, CSR_CYCLE_TIME);
abfe5a01ef1e4 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 12:13:49 +0100 1200)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1201) switch (a->clk_id) {
2c1bb29aa6e7b drivers/firewire/core-cdev.c (Arnd Bergmann 2018-08-17 15:43:44 -0700 1202) case CLOCK_REALTIME: ktime_get_real_ts64(&ts); break;
2c1bb29aa6e7b drivers/firewire/core-cdev.c (Arnd Bergmann 2018-08-17 15:43:44 -0700 1203) case CLOCK_MONOTONIC: ktime_get_ts64(&ts); break;
2c1bb29aa6e7b drivers/firewire/core-cdev.c (Arnd Bergmann 2018-08-17 15:43:44 -0700 1204) case CLOCK_MONOTONIC_RAW: ktime_get_raw_ts64(&ts); break;
abfe5a01ef1e4 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 12:13:49 +0100 1205) default:
abfe5a01ef1e4 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 12:13:49 +0100 1206) ret = -EINVAL;
abfe5a01ef1e4 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 12:13:49 +0100 1207) }
a64408b96b5f6 drivers/firewire/fw-cdev.c (Stefan Richter 2007-09-29 10:41:58 +0200 1208)
4a9bde9b8ab55 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 22:24:43 +0100 1209) local_irq_enable();
a64408b96b5f6 drivers/firewire/fw-cdev.c (Stefan Richter 2007-09-29 10:41:58 +0200 1210)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1211) a->tv_sec = ts.tv_sec;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1212) a->tv_nsec = ts.tv_nsec;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1213) a->cycle_timer = cycle_time;
abfe5a01ef1e4 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 12:13:49 +0100 1214)
abfe5a01ef1e4 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 12:13:49 +0100 1215) return ret;
abfe5a01ef1e4 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 12:13:49 +0100 1216) }
abfe5a01ef1e4 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 12:13:49 +0100 1217)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1218) static int ioctl_get_cycle_timer(struct client *client, union ioctl_arg *arg)
abfe5a01ef1e4 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 12:13:49 +0100 1219) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1220) struct fw_cdev_get_cycle_timer *a = &arg->get_cycle_timer;
abfe5a01ef1e4 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 12:13:49 +0100 1221) struct fw_cdev_get_cycle_timer2 ct2;
abfe5a01ef1e4 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 12:13:49 +0100 1222)
abfe5a01ef1e4 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 12:13:49 +0100 1223) ct2.clk_id = CLOCK_REALTIME;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1224) ioctl_get_cycle_timer2(client, (union ioctl_arg *)&ct2);
abfe5a01ef1e4 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 12:13:49 +0100 1225)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1226) a->local_time = ct2.tv_sec * USEC_PER_SEC + ct2.tv_nsec / NSEC_PER_USEC;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1227) a->cycle_timer = ct2.cycle_timer;
4a9bde9b8ab55 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-20 22:24:43 +0100 1228)
a64408b96b5f6 drivers/firewire/fw-cdev.c (Stefan Richter 2007-09-29 10:41:58 +0200 1229) return 0;
a64408b96b5f6 drivers/firewire/fw-cdev.c (Stefan Richter 2007-09-29 10:41:58 +0200 1230) }
a64408b96b5f6 drivers/firewire/fw-cdev.c (Stefan Richter 2007-09-29 10:41:58 +0200 1231)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1232) static void iso_resource_work(struct work_struct *work)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1233) {
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1234) struct iso_resource_event *e;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1235) struct iso_resource *r =
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1236) container_of(work, struct iso_resource, work.work);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1237) struct client *client = r->client;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1238) int generation, channel, bandwidth, todo;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1239) bool skip, free, success;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1240)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1241) spin_lock_irq(&client->lock);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1242) generation = client->device->generation;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1243) todo = r->todo;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1244) /* Allow 1000ms grace period for other reallocations. */
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1245) if (todo == ISO_RES_ALLOC &&
e71084af58cf1 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-22 15:05:03 +0100 1246) time_before64(get_jiffies_64(),
e71084af58cf1 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-22 15:05:03 +0100 1247) client->device->card->reset_jiffies + HZ)) {
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 1248) schedule_iso_resource(r, DIV_ROUND_UP(HZ, 3));
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1249) skip = true;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1250) } else {
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1251) /* We could be called twice within the same generation. */
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1252) skip = todo == ISO_RES_REALLOC &&
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1253) r->generation == generation;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1254) }
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1255) free = todo == ISO_RES_DEALLOC ||
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1256) todo == ISO_RES_ALLOC_ONCE ||
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1257) todo == ISO_RES_DEALLOC_ONCE;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1258) r->generation = generation;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1259) spin_unlock_irq(&client->lock);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1260)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1261) if (skip)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1262) goto out;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1263)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1264) bandwidth = r->bandwidth;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1265)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1266) fw_iso_resource_manage(client->device->card, generation,
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1267) r->channels, &channel, &bandwidth,
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1268) todo == ISO_RES_ALLOC ||
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1269) todo == ISO_RES_REALLOC ||
f30e6d3e419bf drivers/firewire/core-cdev.c (Stefan Richter 2011-04-22 15:13:54 +0200 1270) todo == ISO_RES_ALLOC_ONCE);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1271) /*
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1272) * Is this generation outdated already? As long as this resource sticks
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1273) * in the idr, it will be scheduled again for a newer generation or at
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1274) * shutdown.
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1275) */
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1276) if (channel == -EAGAIN &&
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1277) (todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC))
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1278) goto out;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1279)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1280) success = channel >= 0 || bandwidth > 0;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1281)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1282) spin_lock_irq(&client->lock);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1283) /*
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1284) * Transit from allocation to reallocation, except if the client
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1285) * requested deallocation in the meantime.
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1286) */
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1287) if (r->todo == ISO_RES_ALLOC)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1288) r->todo = ISO_RES_REALLOC;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1289) /*
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1290) * Allocation or reallocation failure? Pull this resource out of the
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1291) * idr and prepare for deletion, unless the client is shutting down.
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1292) */
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1293) if (r->todo == ISO_RES_REALLOC && !success &&
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1294) !client->in_shutdown &&
d3e709e63e97e drivers/firewire/core-cdev.c (Matthew Wilcox 2016-12-22 13:30:22 -0500 1295) idr_remove(&client->resource_idr, r->resource.handle)) {
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1296) client_put(client);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1297) free = true;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1298) }
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1299) spin_unlock_irq(&client->lock);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1300)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1301) if (todo == ISO_RES_ALLOC && channel >= 0)
5d9cb7d276a9c drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-08 23:07:40 +0100 1302) r->channels = 1ULL << channel;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1303)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1304) if (todo == ISO_RES_REALLOC && success)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1305) goto out;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1306)
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1307) if (todo == ISO_RES_ALLOC || todo == ISO_RES_ALLOC_ONCE) {
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1308) e = r->e_alloc;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1309) r->e_alloc = NULL;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1310) } else {
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1311) e = r->e_dealloc;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1312) r->e_dealloc = NULL;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1313) }
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 1314) e->iso_resource.handle = r->resource.handle;
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 1315) e->iso_resource.channel = channel;
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 1316) e->iso_resource.bandwidth = bandwidth;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1317)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1318) queue_event(client, &e->event,
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 1319) &e->iso_resource, sizeof(e->iso_resource), NULL, 0);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1320)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1321) if (free) {
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1322) cancel_delayed_work(&r->work);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1323) kfree(r->e_alloc);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1324) kfree(r->e_dealloc);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1325) kfree(r);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1326) }
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1327) out:
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1328) client_put(client);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1329) }
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1330)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1331) static void release_iso_resource(struct client *client,
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1332) struct client_resource *resource)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1333) {
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1334) struct iso_resource *r =
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1335) container_of(resource, struct iso_resource, resource);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1336)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1337) spin_lock_irq(&client->lock);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1338) r->todo = ISO_RES_DEALLOC;
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 1339) schedule_iso_resource(r, 0);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1340) spin_unlock_irq(&client->lock);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1341) }
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1342)
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1343) static int init_iso_resource(struct client *client,
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1344) struct fw_cdev_allocate_iso_resource *request, int todo)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1345) {
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1346) struct iso_resource_event *e1, *e2;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1347) struct iso_resource *r;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1348) int ret;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1349)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1350) if ((request->channels == 0 && request->bandwidth == 0) ||
bdabfa54635e5 drivers/firewire/core-cdev.c (Stefan Richter 2013-03-24 17:31:09 +0100 1351) request->bandwidth > BANDWIDTH_AVAILABLE_INITIAL)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1352) return -EINVAL;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1353)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1354) r = kmalloc(sizeof(*r), GFP_KERNEL);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1355) e1 = kmalloc(sizeof(*e1), GFP_KERNEL);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1356) e2 = kmalloc(sizeof(*e2), GFP_KERNEL);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1357) if (r == NULL || e1 == NULL || e2 == NULL) {
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1358) ret = -ENOMEM;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1359) goto fail;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1360) }
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1361)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1362) INIT_DELAYED_WORK(&r->work, iso_resource_work);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1363) r->client = client;
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1364) r->todo = todo;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1365) r->generation = -1;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1366) r->channels = request->channels;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1367) r->bandwidth = request->bandwidth;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1368) r->e_alloc = e1;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1369) r->e_dealloc = e2;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1370)
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 1371) e1->iso_resource.closure = request->closure;
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 1372) e1->iso_resource.type = FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED;
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 1373) e2->iso_resource.closure = request->closure;
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 1374) e2->iso_resource.type = FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1375)
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1376) if (todo == ISO_RES_ALLOC) {
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1377) r->resource.release = release_iso_resource;
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1378) ret = add_client_resource(client, &r->resource, GFP_KERNEL);
81610b8fbfc02 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-11 13:44:46 +0100 1379) if (ret < 0)
81610b8fbfc02 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-11 13:44:46 +0100 1380) goto fail;
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1381) } else {
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1382) r->resource.release = NULL;
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1383) r->resource.handle = -1;
9fb551bf72929 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:10 +0200 1384) schedule_iso_resource(r, 0);
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1385) }
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1386) request->handle = r->resource.handle;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1387)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1388) return 0;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1389) fail:
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1390) kfree(r);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1391) kfree(e1);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1392) kfree(e2);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1393)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1394) return ret;
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1395) }
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1396)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1397) static int ioctl_allocate_iso_resource(struct client *client,
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1398) union ioctl_arg *arg)
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1399) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1400) return init_iso_resource(client,
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1401) &arg->allocate_iso_resource, ISO_RES_ALLOC);
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1402) }
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1403)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1404) static int ioctl_deallocate_iso_resource(struct client *client,
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1405) union ioctl_arg *arg)
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1406) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1407) return release_client_resource(client,
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1408) arg->deallocate.handle, release_iso_resource, NULL);
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1409) }
b1bda4cdc2037 drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1410)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1411) static int ioctl_allocate_iso_resource_once(struct client *client,
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1412) union ioctl_arg *arg)
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1413) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1414) return init_iso_resource(client,
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1415) &arg->allocate_iso_resource, ISO_RES_ALLOC_ONCE);
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1416) }
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1417)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1418) static int ioctl_deallocate_iso_resource_once(struct client *client,
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1419) union ioctl_arg *arg)
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1420) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1421) return init_iso_resource(client,
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1422) &arg->allocate_iso_resource, ISO_RES_DEALLOC_ONCE);
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1423) }
1ec3c0269d719 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1424)
c8a25900f35e5 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 20:59:16 +0100 1425) /*
c8a25900f35e5 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 20:59:16 +0100 1426) * Returns a speed code: Maximum speed to or from this device,
c8a25900f35e5 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 20:59:16 +0100 1427) * limited by the device's link speed, the local node's link speed,
c8a25900f35e5 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 20:59:16 +0100 1428) * and all PHY port speeds between the two links.
c8a25900f35e5 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 20:59:16 +0100 1429) */
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1430) static int ioctl_get_speed(struct client *client, union ioctl_arg *arg)
33580a3ef5ba3 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1431) {
c8a25900f35e5 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 20:59:16 +0100 1432) return client->device->max_speed;
33580a3ef5ba3 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1433) }
33580a3ef5ba3 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1434)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1435) static int ioctl_send_broadcast_request(struct client *client,
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1436) union ioctl_arg *arg)
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1437) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1438) struct fw_cdev_send_request *a = &arg->send_request;
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1439)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1440) switch (a->tcode) {
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1441) case TCODE_WRITE_QUADLET_REQUEST:
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1442) case TCODE_WRITE_BLOCK_REQUEST:
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1443) break;
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1444) default:
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1445) return -EINVAL;
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1446) }
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1447)
1566f3dc3e598 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1448) /* Security policy: Only allow accesses to Units Space. */
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1449) if (a->offset < CSR_REGISTER_BASE + CSR_CONFIG_ROM_END)
1566f3dc3e598 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1450) return -EACCES;
1566f3dc3e598 drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1451)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1452) return init_request(client, a, LOCAL_BUS | 0x3f, SCODE_100);
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1453) }
acfe8333572ca drivers/firewire/fw-cdev.c (Jay Fenlason, Stefan Richter 2009-01-04 16:23:29 +0100 1454)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1455) static int ioctl_send_stream_packet(struct client *client, union ioctl_arg *arg)
f8c2287c65f8f drivers/firewire/fw-cdev.c (Jay Fenlason 2009-03-05 19:08:40 +0100 1456) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1457) struct fw_cdev_send_stream_packet *a = &arg->send_stream_packet;
18e9b10fcdc09 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 21:02:21 +0100 1458) struct fw_cdev_send_request request;
18e9b10fcdc09 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 21:02:21 +0100 1459) int dest;
f8c2287c65f8f drivers/firewire/fw-cdev.c (Jay Fenlason 2009-03-05 19:08:40 +0100 1460)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1461) if (a->speed > client->device->card->link_speed ||
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1462) a->length > 1024 << a->speed)
18e9b10fcdc09 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 21:02:21 +0100 1463) return -EIO;
f8c2287c65f8f drivers/firewire/fw-cdev.c (Jay Fenlason 2009-03-05 19:08:40 +0100 1464)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1465) if (a->tag > 3 || a->channel > 63 || a->sy > 15)
18e9b10fcdc09 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 21:02:21 +0100 1466) return -EINVAL;
18e9b10fcdc09 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 21:02:21 +0100 1467)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1468) dest = fw_stream_packet_destination_id(a->tag, a->channel, a->sy);
18e9b10fcdc09 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 21:02:21 +0100 1469) request.tcode = TCODE_STREAM_DATA;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1470) request.length = a->length;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1471) request.closure = a->closure;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1472) request.data = a->data;
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1473) request.generation = a->generation;
18e9b10fcdc09 drivers/firewire/fw-cdev.c (Stefan Richter 2009-03-10 21:02:21 +0100 1474)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1475) return init_request(client, &request, dest, a->speed);
f8c2287c65f8f drivers/firewire/fw-cdev.c (Jay Fenlason 2009-03-05 19:08:40 +0100 1476) }
f8c2287c65f8f drivers/firewire/fw-cdev.c (Jay Fenlason 2009-03-05 19:08:40 +0100 1477)
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1478) static void outbound_phy_packet_callback(struct fw_packet *packet,
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1479) struct fw_card *card, int status)
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1480) {
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1481) struct outbound_phy_packet_event *e =
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1482) container_of(packet, struct outbound_phy_packet_event, p);
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1483)
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1484) switch (status) {
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1485) /* expected: */
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1486) case ACK_COMPLETE: e->phy_packet.rcode = RCODE_COMPLETE; break;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1487) /* should never happen with PHY packets: */
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1488) case ACK_PENDING: e->phy_packet.rcode = RCODE_COMPLETE; break;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1489) case ACK_BUSY_X:
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1490) case ACK_BUSY_A:
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1491) case ACK_BUSY_B: e->phy_packet.rcode = RCODE_BUSY; break;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1492) case ACK_DATA_ERROR: e->phy_packet.rcode = RCODE_DATA_ERROR; break;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1493) case ACK_TYPE_ERROR: e->phy_packet.rcode = RCODE_TYPE_ERROR; break;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1494) /* stale generation; cancelled; on certain controllers: no ack */
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1495) default: e->phy_packet.rcode = status; break;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1496) }
cc550216ae9a2 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-18 13:00:50 +0200 1497) e->phy_packet.data[0] = packet->timestamp;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1498)
cc550216ae9a2 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-18 13:00:50 +0200 1499) queue_event(e->client, &e->event, &e->phy_packet,
cc550216ae9a2 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-18 13:00:50 +0200 1500) sizeof(e->phy_packet) + e->phy_packet.length, NULL, 0);
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1501) client_put(e->client);
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1502) }
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1503)
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1504) static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg)
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1505) {
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1506) struct fw_cdev_send_phy_packet *a = &arg->send_phy_packet;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1507) struct fw_card *card = client->device->card;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1508) struct outbound_phy_packet_event *e;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1509)
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1510) /* Access policy: Allow this ioctl only on local nodes' device files. */
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1511) if (!client->device->is_local)
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1512) return -ENOSYS;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1513)
cc550216ae9a2 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-18 13:00:50 +0200 1514) e = kzalloc(sizeof(*e) + 4, GFP_KERNEL);
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1515) if (e == NULL)
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1516) return -ENOMEM;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1517)
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1518) client_get(client);
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1519) e->client = client;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1520) e->p.speed = SCODE_100;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1521) e->p.generation = a->generation;
5b06db166c4d3 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-11-30 08:24:47 +0100 1522) e->p.header[0] = TCODE_LINK_INTERNAL << 4;
5b06db166c4d3 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-11-30 08:24:47 +0100 1523) e->p.header[1] = a->data[0];
5b06db166c4d3 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-11-30 08:24:47 +0100 1524) e->p.header[2] = a->data[1];
5b06db166c4d3 drivers/firewire/core-cdev.c (Clemens Ladisch 2010-11-30 08:24:47 +0100 1525) e->p.header_length = 12;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1526) e->p.callback = outbound_phy_packet_callback;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1527) e->phy_packet.closure = a->closure;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1528) e->phy_packet.type = FW_CDEV_EVENT_PHY_PACKET_SENT;
cc550216ae9a2 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-18 13:00:50 +0200 1529) if (is_ping_packet(a->data))
cc550216ae9a2 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-18 13:00:50 +0200 1530) e->phy_packet.length = 4;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1531)
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1532) card->driver->send_request(card, &e->p);
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1533)
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1534) return 0;
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1535) }
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1536)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1537) static int ioctl_receive_phy_packets(struct client *client, union ioctl_arg *arg)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1538) {
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1539) struct fw_cdev_receive_phy_packets *a = &arg->receive_phy_packets;
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1540) struct fw_card *card = client->device->card;
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1541)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1542) /* Access policy: Allow this ioctl only on local nodes' device files. */
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1543) if (!client->device->is_local)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1544) return -ENOSYS;
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1545)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1546) spin_lock_irq(&card->lock);
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1547)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1548) list_move_tail(&client->phy_receiver_link, &card->phy_receiver_list);
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1549) client->phy_receiver_closure = a->closure;
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1550)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1551) spin_unlock_irq(&card->lock);
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1552)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1553) return 0;
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1554) }
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1555)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1556) void fw_cdev_handle_phy_packet(struct fw_card *card, struct fw_packet *p)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1557) {
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1558) struct client *client;
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1559) struct inbound_phy_packet_event *e;
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1560) unsigned long flags;
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1561)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1562) spin_lock_irqsave(&card->lock, flags);
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1563)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1564) list_for_each_entry(client, &card->phy_receiver_list, phy_receiver_link) {
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1565) e = kmalloc(sizeof(*e) + 8, GFP_ATOMIC);
cfb0c9d1ffbf9 drivers/firewire/core-cdev.c (Stefan Richter 2013-03-24 17:32:00 +0100 1566) if (e == NULL)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1567) break;
cfb0c9d1ffbf9 drivers/firewire/core-cdev.c (Stefan Richter 2013-03-24 17:32:00 +0100 1568)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1569) e->phy_packet.closure = client->phy_receiver_closure;
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1570) e->phy_packet.type = FW_CDEV_EVENT_PHY_PACKET_RECEIVED;
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1571) e->phy_packet.rcode = RCODE_COMPLETE;
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1572) e->phy_packet.length = 8;
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1573) e->phy_packet.data[0] = p->header[1];
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1574) e->phy_packet.data[1] = p->header[2];
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1575) queue_event(client, &e->event,
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1576) &e->phy_packet, sizeof(e->phy_packet) + 8, NULL, 0);
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1577) }
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1578)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1579) spin_unlock_irqrestore(&card->lock, flags);
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1580) }
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1581)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1582) static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = {
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1583) [0x00] = ioctl_get_info,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1584) [0x01] = ioctl_send_request,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1585) [0x02] = ioctl_allocate,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1586) [0x03] = ioctl_deallocate,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1587) [0x04] = ioctl_send_response,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1588) [0x05] = ioctl_initiate_bus_reset,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1589) [0x06] = ioctl_add_descriptor,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1590) [0x07] = ioctl_remove_descriptor,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1591) [0x08] = ioctl_create_iso_context,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1592) [0x09] = ioctl_queue_iso,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1593) [0x0a] = ioctl_start_iso,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1594) [0x0b] = ioctl_stop_iso,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1595) [0x0c] = ioctl_get_cycle_timer,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1596) [0x0d] = ioctl_allocate_iso_resource,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1597) [0x0e] = ioctl_deallocate_iso_resource,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1598) [0x0f] = ioctl_allocate_iso_resource_once,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1599) [0x10] = ioctl_deallocate_iso_resource_once,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1600) [0x11] = ioctl_get_speed,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1601) [0x12] = ioctl_send_broadcast_request,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1602) [0x13] = ioctl_send_stream_packet,
b9dc61cf40416 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:24:29 +0200 1603) [0x14] = ioctl_get_cycle_timer2,
850bb6f23b93c drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:14 +0200 1604) [0x15] = ioctl_send_phy_packet,
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1605) [0x16] = ioctl_receive_phy_packets,
872e330e38806 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-29 18:19:22 +0200 1606) [0x17] = ioctl_set_iso_channels,
d1bbd20972936 drivers/firewire/core-cdev.c (Clemens Ladisch 2012-03-18 19:06:39 +0100 1607) [0x18] = ioctl_flush_iso,
4f2592232ea95 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:13 -0400 1608) };
4f2592232ea95 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:13 -0400 1609)
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 1610) static int dispatch_ioctl(struct client *client,
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 1611) unsigned int cmd, void __user *arg)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1612) {
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1613) union ioctl_arg buffer;
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 1614) int ret;
4f2592232ea95 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:13 -0400 1615)
64582298b9c29 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:42 +0100 1616) if (fw_device_is_shutdown(client->device))
64582298b9c29 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:42 +0100 1617) return -ENODEV;
64582298b9c29 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:42 +0100 1618)
4f2592232ea95 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:13 -0400 1619) if (_IOC_TYPE(cmd) != '#' ||
9cac00b8f0079 drivers/firewire/core-cdev.c (Stefan Richter 2010-04-07 08:30:50 +0200 1620) _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers) ||
9cac00b8f0079 drivers/firewire/core-cdev.c (Stefan Richter 2010-04-07 08:30:50 +0200 1621) _IOC_SIZE(cmd) > sizeof(buffer))
d873d794235ef drivers/firewire/core-cdev.c (Stefan Richter 2011-07-09 16:42:26 +0200 1622) return -ENOTTY;
4f2592232ea95 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:13 -0400 1623)
eaca2d8e75e90 drivers/firewire/core-cdev.c (Stefan Richter 2014-11-11 17:16:44 +0100 1624) memset(&buffer, 0, sizeof(buffer));
9cac00b8f0079 drivers/firewire/core-cdev.c (Stefan Richter 2010-04-07 08:30:50 +0200 1625)
9cac00b8f0079 drivers/firewire/core-cdev.c (Stefan Richter 2010-04-07 08:30:50 +0200 1626) if (_IOC_DIR(cmd) & _IOC_WRITE)
9cac00b8f0079 drivers/firewire/core-cdev.c (Stefan Richter 2010-04-07 08:30:50 +0200 1627) if (copy_from_user(&buffer, arg, _IOC_SIZE(cmd)))
4f2592232ea95 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:13 -0400 1628) return -EFAULT;
4f2592232ea95 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:13 -0400 1629)
6e95dea728f4a drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:21 +0100 1630) ret = ioctl_handlers[_IOC_NR(cmd)](client, &buffer);
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 1631) if (ret < 0)
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 1632) return ret;
4f2592232ea95 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:13 -0400 1633)
9cac00b8f0079 drivers/firewire/core-cdev.c (Stefan Richter 2010-04-07 08:30:50 +0200 1634) if (_IOC_DIR(cmd) & _IOC_READ)
9cac00b8f0079 drivers/firewire/core-cdev.c (Stefan Richter 2010-04-07 08:30:50 +0200 1635) if (copy_to_user(arg, &buffer, _IOC_SIZE(cmd)))
4f2592232ea95 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:13 -0400 1636) return -EFAULT;
4f2592232ea95 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-04-30 15:03:13 -0400 1637)
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 1638) return ret;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1639) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1640)
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 1641) static long fw_device_op_ioctl(struct file *file,
53dca51175cc2 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:47:04 +0100 1642) unsigned int cmd, unsigned long arg)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1643) {
64582298b9c29 drivers/firewire/core-cdev.c (Stefan Richter 2010-02-21 17:56:42 +0100 1644) return dispatch_ioctl(file->private_data, cmd, (void __user *)arg);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1645) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1646)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1647) static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1648) {
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1649) struct client *client = file->private_data;
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 1650) unsigned long size;
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 1651) int page_count, ret;
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 1652)
551f4cb9de716 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-05-16 11:15:23 -0400 1653) if (fw_device_is_shutdown(client->device))
551f4cb9de716 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-05-16 11:15:23 -0400 1654) return -ENODEV;
551f4cb9de716 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-05-16 11:15:23 -0400 1655)
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 1656) /* FIXME: We could support multiple buffers, but we don't. */
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 1657) if (client->buffer.pages != NULL)
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 1658) return -EBUSY;
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 1659)
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 1660) if (!(vma->vm_flags & VM_SHARED))
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 1661) return -EINVAL;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1662)
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 1663) if (vma->vm_start & ~PAGE_MASK)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1664) return -EINVAL;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1665)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1666) client->vm_start = vma->vm_start;
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 1667) size = vma->vm_end - vma->vm_start;
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 1668) page_count = size >> PAGE_SHIFT;
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 1669) if (size & ~PAGE_MASK)
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 1670) return -EINVAL;
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 1671)
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1672) ret = fw_iso_buffer_alloc(&client->buffer, page_count);
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 1673) if (ret < 0)
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 1674) return ret;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1675)
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1676) spin_lock_irq(&client->lock);
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1677) if (client->iso_context) {
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1678) ret = fw_iso_buffer_map_dma(&client->buffer,
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1679) client->device->card,
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1680) iso_dma_direction(client->iso_context));
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1681) client->buffer_is_mapped = (ret == 0);
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1682) }
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1683) spin_unlock_irq(&client->lock);
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 1684) if (ret < 0)
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1685) goto fail;
9aad8125389a7 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-02-16 17:34:38 -0500 1686)
7807759e4ad8d drivers/firewire/core-cdev.c (Stefan Richter 2019-11-05 14:49:39 +0100 1687) ret = vm_map_pages_zero(vma, client->buffer.pages,
7807759e4ad8d drivers/firewire/core-cdev.c (Stefan Richter 2019-11-05 14:49:39 +0100 1688) client->buffer.page_count);
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1689) if (ret < 0)
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1690) goto fail;
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1691)
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1692) return 0;
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1693) fail:
0b6c4857f7684 drivers/firewire/core-cdev.c (Stefan Richter 2012-04-09 20:51:18 +0200 1694) fw_iso_buffer_destroy(&client->buffer, client->device->card);
2dbd7d7e2327b drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 21:45:45 +0100 1695) return ret;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1696) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1697)
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1698) static int is_outbound_transaction_resource(int id, void *p, void *data)
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1699) {
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1700) struct client_resource *resource = p;
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1701)
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1702) return resource->release == release_transaction;
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1703) }
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1704)
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1705) static int has_outbound_transactions(struct client *client)
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1706) {
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1707) int ret;
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1708)
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1709) spin_lock_irq(&client->lock);
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1710) ret = idr_for_each(&client->resource_idr,
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1711) is_outbound_transaction_resource, NULL);
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1712) spin_unlock_irq(&client->lock);
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1713)
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1714) return ret;
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1715) }
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1716)
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 1717) static int shutdown_resource(int id, void *p, void *data)
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 1718) {
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 1719) struct client_resource *resource = p;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 1720) struct client *client = data;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 1721)
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 1722) resource->release(client, resource);
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1723) client_put(client);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 1724)
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 1725) return 0;
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 1726) }
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 1727)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1728) static int fw_device_op_release(struct inode *inode, struct file *file)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1729) {
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1730) struct client *client = file->private_data;
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 1731) struct event *event, *next_event;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1732)
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1733) spin_lock_irq(&client->device->card->lock);
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1734) list_del(&client->phy_receiver_link);
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1735) spin_unlock_irq(&client->device->card->lock);
bf54e1462b919 drivers/firewire/core-cdev.c (Stefan Richter 2010-07-16 22:25:51 +0200 1736)
97811e3473107 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 19:19:23 +0100 1737) mutex_lock(&client->device->client_list_mutex);
97811e3473107 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 19:19:23 +0100 1738) list_del(&client->link);
97811e3473107 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 19:19:23 +0100 1739) mutex_unlock(&client->device->client_list_mutex);
97811e3473107 drivers/firewire/fw-cdev.c (Stefan Richter 2008-12-14 19:19:23 +0100 1740)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1741) if (client->iso_context)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1742) fw_iso_context_destroy(client->iso_context);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1743)
36a755cfc398f drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-05 20:28:10 +0100 1744) if (client->buffer.pages)
36a755cfc398f drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-05 20:28:10 +0100 1745) fw_iso_buffer_destroy(&client->buffer, client->device->card);
36a755cfc398f drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-05 20:28:10 +0100 1746)
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 1747) /* Freeze client->resource_idr and client->event_list */
3ba949868a6dc drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1748) spin_lock_irq(&client->lock);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 1749) client->in_shutdown = true;
3ba949868a6dc drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1750) spin_unlock_irq(&client->lock);
66dea3e5f69ab drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-28 21:26:42 +0200 1751)
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1752) wait_event(client->tx_flush_wait, !has_outbound_transactions(client));
5a5e62da9be25 drivers/firewire/core-cdev.c (Clemens Ladisch 2011-01-10 17:28:39 +0100 1753)
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 1754) idr_for_each(&client->resource_idr, shutdown_resource, client);
45ee3199eb3e4 drivers/firewire/fw-cdev.c (Jay Fenlason 2008-12-21 16:47:17 +0100 1755) idr_destroy(&client->resource_idr);
28cf6a04c8285 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:50 -0500 1756)
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 1757) list_for_each_entry_safe(event, next_event, &client->event_list, link)
e21fcf798e246 drivers/firewire/core-cdev.c (Stefan Richter 2009-10-08 00:41:38 +0200 1758) kfree(event);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1759)
fb4430367b0bb drivers/firewire/fw-cdev.c (Stefan Richter 2009-01-04 16:23:29 +0100 1760) client_put(client);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1761)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1762) return 0;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1763) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1764)
afc9a42b7464f drivers/firewire/core-cdev.c (Al Viro 2017-07-03 06:39:46 -0400 1765) static __poll_t fw_device_op_poll(struct file *file, poll_table * pt)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1766) {
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1767) struct client *client = file->private_data;
afc9a42b7464f drivers/firewire/core-cdev.c (Al Viro 2017-07-03 06:39:46 -0400 1768) __poll_t mask = 0;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1769)
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1770) poll_wait(file, &client->wait, pt);
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1771)
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 1772) if (fw_device_is_shutdown(client->device))
a9a08845e9acb drivers/firewire/core-cdev.c (Linus Torvalds 2018-02-11 14:34:03 -0800 1773) mask |= EPOLLHUP | EPOLLERR;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1774) if (!list_empty(&client->event_list))
a9a08845e9acb drivers/firewire/core-cdev.c (Linus Torvalds 2018-02-11 14:34:03 -0800 1775) mask |= EPOLLIN | EPOLLRDNORM;
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 1776)
2603bf219e9be drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2007-03-07 12:12:48 -0500 1777) return mask;
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1778) }
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1779)
21ebcd1224d05 drivers/firewire/fw-device-cdev.c (Stefan Richter 2007-01-14 15:29:07 +0100 1780) const struct file_operations fw_device_ops = {
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1781) .owner = THIS_MODULE,
3ac26b2ee3000 drivers/firewire/core-cdev.c (Stefan Richter 2010-04-10 16:38:05 +0100 1782) .llseek = no_llseek,
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1783) .open = fw_device_op_open,
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1784) .read = fw_device_op_read,
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1785) .unlocked_ioctl = fw_device_op_ioctl,
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1786) .mmap = fw_device_op_mmap,
3ac26b2ee3000 drivers/firewire/core-cdev.c (Stefan Richter 2010-04-10 16:38:05 +0100 1787) .release = fw_device_op_release,
3ac26b2ee3000 drivers/firewire/core-cdev.c (Stefan Richter 2010-04-10 16:38:05 +0100 1788) .poll = fw_device_op_poll,
407e9ef72476e drivers/firewire/core-cdev.c (Arnd Bergmann 2018-09-11 17:23:00 +0200 1789) .compat_ioctl = compat_ptr_ioctl,
19a15b937b266 drivers/firewire/fw-device-cdev.c (Kristian Høgsberg 2006-12-19 19:58:31 -0500 1790) };