From 4a9bde9b8ab55a2bb51b57cad215a97bcf80bae2 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 20 Feb 2010 22:24:43 +0100 Subject: firewire: get_cycle_timer optimization and cleanup ohci: Break out of the retry loop if too many attempts were necessary. This may theoretically happen if the chip is fatally defective or if the get_cycle_timer ioctl was performed after a CardBus controller was ejected. Also micro-optimize the loop by re-using the last two register reads in the next iteration, remove a questionable inline keyword, and shuffle a comment around. core: ioctl_get_cycle_timer() is always called with interrupts on, therefore local_irq_save() can be replaced by local_irq_disable(). Disabled local IRQs imply disabled preemption, hence preempt_disable() can be removed. Signed-off-by: Stefan Richter --- drivers/firewire/core-cdev.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers/firewire/core-cdev.c') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index e6d63849e78e..ecd0a4d81abf 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -1013,21 +1013,19 @@ static int ioctl_get_cycle_timer(struct client *client, void *buffer) { struct fw_cdev_get_cycle_timer *request = buffer; struct fw_card *card = client->device->card; - unsigned long long bus_time; struct timeval tv; - unsigned long flags; + u32 cycle_time; - preempt_disable(); - local_irq_save(flags); + local_irq_disable(); - bus_time = card->driver->get_bus_time(card); + cycle_time = card->driver->get_bus_time(card); do_gettimeofday(&tv); - local_irq_restore(flags); - preempt_enable(); + local_irq_enable(); request->local_time = tv.tv_sec * 1000000ULL + tv.tv_usec; - request->cycle_timer = bus_time & 0xffffffff; + request->cycle_timer = cycle_time; + return 0; } -- cgit v1.2.3 From 168cf9af699e87d5a6f44b684583714ecabb8e71 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 14 Feb 2010 18:49:18 +0100 Subject: firewire: remove incomplete Bus_Time CSR support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current implementation of Bus_Time read access was buggy since it did not ensure that Bus_Time.second_count_hi and second_count_lo came from the same 128 seconds period. Reported-by: HÃ¥kan Johansson Instead of a fix, remove Bus_Time register support altogether. The spec requires all cycle master capable nodes to implement this (all Linux nodes are cycle master capable) while it also says that it "may" be initialized by the bus manager or by the IRM standing in for a bus manager. (Neither Linux' firewire-core nor ieee1394 nodemgr implement this.) Since we cannot rely on Bus_Time having been initialized by a bus manager, it is better to return an error instead of a nonsensical value on a read request to Bus_Time. Alternatively, we could fix the Bus_Time read integrity bug _and_ implement (a) cycle master's write support of the register as well as (b) bus manager's Bus_Time initialization service, i.e. preservation of the Bus_Time when the cycle master node of a bus changes. However, that would be quite some code for a feature that is unreliable to begin with and very likely unused in practice. Signed-off-by: Stefan Richter --- drivers/firewire/core-cdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/firewire/core-cdev.c') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index ecd0a4d81abf..5538d5130f7b 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -1018,7 +1018,7 @@ static int ioctl_get_cycle_timer(struct client *client, void *buffer) local_irq_disable(); - cycle_time = card->driver->get_bus_time(card); + cycle_time = card->driver->get_cycle_time(card); do_gettimeofday(&tv); local_irq_enable(); -- cgit v1.2.3 From abfe5a01ef1e463cbafdae461b693db34e308c02 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 20 Feb 2010 12:13:49 +0100 Subject: firewire: cdev: add more flexible cycle timer ioctl The system time from CLOCK_REALTIME is not monotonic, hence problematic for the main user of the FW_CDEV_IOC_GET_CYCLE_TIMER ioctl. This issue exists in its successor ABI, i.e. raw1394, too. http://subversion.ffado.org/ticket/242 We now offer an alternative ioctl which lets the caller choose between CLOCK_REALTIME, CLOCK_MONOTONIC, and CLOCK_MONOTONIC_RAW as source of the local time, very similar to the clock_gettime libc function. The format of the local time return value matches that of clock_gettime (seconds and nanoseconds, instead of a single microseconds value from the existing ioctl). Signed-off-by: Stefan Richter --- drivers/firewire/core-cdev.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) (limited to 'drivers/firewire/core-cdev.c') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 3c1ac0933d24..a4aa477b9b2c 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -1031,22 +1031,46 @@ static int ioctl_stop_iso(struct client *client, void *buffer) return fw_iso_context_stop(client->iso_context); } -static int ioctl_get_cycle_timer(struct client *client, void *buffer) +static int ioctl_get_cycle_timer2(struct client *client, void *buffer) { - struct fw_cdev_get_cycle_timer *request = buffer; + struct fw_cdev_get_cycle_timer2 *request = buffer; struct fw_card *card = client->device->card; - struct timeval tv; + struct timespec ts = {0, 0}; u32 cycle_time; + int ret = 0; local_irq_disable(); cycle_time = card->driver->get_cycle_time(card); - do_gettimeofday(&tv); + + switch (request->clk_id) { + case CLOCK_REALTIME: getnstimeofday(&ts); break; + case CLOCK_MONOTONIC: do_posix_clock_monotonic_gettime(&ts); break; + case CLOCK_MONOTONIC_RAW: getrawmonotonic(&ts); break; + default: + ret = -EINVAL; + } local_irq_enable(); - request->local_time = tv.tv_sec * 1000000ULL + tv.tv_usec; - request->cycle_timer = cycle_time; + request->tv_sec = ts.tv_sec; + request->tv_nsec = ts.tv_nsec; + request->cycle_timer = cycle_time; + + return ret; +} + +static int ioctl_get_cycle_timer(struct client *client, void *buffer) +{ + struct fw_cdev_get_cycle_timer *request = buffer; + struct fw_cdev_get_cycle_timer2 ct2; + + ct2.clk_id = CLOCK_REALTIME; + ioctl_get_cycle_timer2(client, &ct2); + + request->local_time = ct2.tv_sec * USEC_PER_SEC + + ct2.tv_nsec / NSEC_PER_USEC; + request->cycle_timer = ct2.cycle_timer; return 0; } @@ -1320,6 +1344,7 @@ static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { ioctl_get_speed, ioctl_send_broadcast_request, ioctl_send_stream_packet, + ioctl_get_cycle_timer2, }; static int dispatch_ioctl(struct client *client, @@ -1341,6 +1366,7 @@ static int dispatch_ioctl(struct client *client, struct fw_cdev_get_cycle_timer _0c; struct fw_cdev_allocate_iso_resource _0d; struct fw_cdev_send_stream_packet _13; + struct fw_cdev_get_cycle_timer2 _14; })]; int ret; -- cgit v1.2.3 From 6e95dea728f4af36c033fcf2318529bd46dae540 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 21 Feb 2010 17:56:21 +0100 Subject: firewire: core: change type of a data buffer from array of char to union of structs. I already used a union to size the buffer which holds ioctl arguments; more consequent is to define it as an instance of this union in the first place. Also rename several local variables from "request" to "a"(rgument) since the term request can be mistaken to mean a transaction subaction, e.g. an instance of struct fw_request. Signed-off-by: Stefan Richter --- drivers/firewire/core-cdev.c | 325 ++++++++++++++++++++----------------------- 1 file changed, 152 insertions(+), 173 deletions(-) (limited to 'drivers/firewire/core-cdev.c') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index a4aa477b9b2c..d7de17a0f250 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -368,39 +368,56 @@ void fw_device_cdev_remove(struct fw_device *device) for_each_client(device, wake_up_client); } -static int ioctl_get_info(struct client *client, void *buffer) +union ioctl_arg { + struct fw_cdev_get_info get_info; + struct fw_cdev_send_request send_request; + struct fw_cdev_allocate allocate; + struct fw_cdev_deallocate deallocate; + struct fw_cdev_send_response send_response; + struct fw_cdev_initiate_bus_reset initiate_bus_reset; + struct fw_cdev_add_descriptor add_descriptor; + struct fw_cdev_remove_descriptor remove_descriptor; + struct fw_cdev_create_iso_context create_iso_context; + struct fw_cdev_queue_iso queue_iso; + struct fw_cdev_start_iso start_iso; + struct fw_cdev_stop_iso stop_iso; + struct fw_cdev_get_cycle_timer get_cycle_timer; + struct fw_cdev_allocate_iso_resource allocate_iso_resource; + struct fw_cdev_send_stream_packet send_stream_packet; + struct fw_cdev_get_cycle_timer2 get_cycle_timer2; +}; + +static int ioctl_get_info(struct client *client, union ioctl_arg *arg) { - struct fw_cdev_get_info *get_info = buffer; + struct fw_cdev_get_info *a = &arg->get_info; struct fw_cdev_event_bus_reset bus_reset; unsigned long ret = 0; - client->version = get_info->version; - get_info->version = FW_CDEV_VERSION; - get_info->card = client->device->card->index; + client->version = a->version; + a->version = FW_CDEV_VERSION; + a->card = client->device->card->index; down_read(&fw_device_rwsem); - if (get_info->rom != 0) { - void __user *uptr = u64_to_uptr(get_info->rom); - size_t want = get_info->rom_length; + if (a->rom != 0) { + size_t want = a->rom_length; size_t have = client->device->config_rom_length * 4; - ret = copy_to_user(uptr, client->device->config_rom, - min(want, have)); + ret = copy_to_user(u64_to_uptr(a->rom), + client->device->config_rom, min(want, have)); } - get_info->rom_length = client->device->config_rom_length * 4; + a->rom_length = client->device->config_rom_length * 4; up_read(&fw_device_rwsem); if (ret != 0) return -EFAULT; - client->bus_reset_closure = get_info->bus_reset_closure; - if (get_info->bus_reset != 0) { - void __user *uptr = u64_to_uptr(get_info->bus_reset); - + client->bus_reset_closure = a->bus_reset_closure; + if (a->bus_reset != 0) { fill_bus_reset_event(&bus_reset, client); - if (copy_to_user(uptr, &bus_reset, sizeof(bus_reset))) + if (copy_to_user(u64_to_uptr(a->bus_reset), + &bus_reset, sizeof(bus_reset))) return -EFAULT; } @@ -571,11 +588,9 @@ static int init_request(struct client *client, return ret; } -static int ioctl_send_request(struct client *client, void *buffer) +static int ioctl_send_request(struct client *client, union ioctl_arg *arg) { - struct fw_cdev_send_request *request = buffer; - - switch (request->tcode) { + switch (arg->send_request.tcode) { case TCODE_WRITE_QUADLET_REQUEST: case TCODE_WRITE_BLOCK_REQUEST: case TCODE_READ_QUADLET_REQUEST: @@ -592,7 +607,7 @@ static int ioctl_send_request(struct client *client, void *buffer) return -EINVAL; } - return init_request(client, request, client->device->node_id, + return init_request(client, &arg->send_request, client->device->node_id, client->device->max_speed); } @@ -683,9 +698,9 @@ static void release_address_handler(struct client *client, kfree(r); } -static int ioctl_allocate(struct client *client, void *buffer) +static int ioctl_allocate(struct client *client, union ioctl_arg *arg) { - struct fw_cdev_allocate *request = buffer; + struct fw_cdev_allocate *a = &arg->allocate; struct address_handler_resource *r; struct fw_address_region region; int ret; @@ -694,13 +709,13 @@ static int ioctl_allocate(struct client *client, void *buffer) if (r == NULL) return -ENOMEM; - region.start = request->offset; - region.end = request->offset + request->length; - r->handler.length = request->length; + region.start = a->offset; + region.end = a->offset + a->length; + r->handler.length = a->length; r->handler.address_callback = handle_request; - r->handler.callback_data = r; - r->closure = request->closure; - r->client = client; + r->handler.callback_data = r; + r->closure = a->closure; + r->client = client; ret = fw_core_add_address_handler(&r->handler, ®ion); if (ret < 0) { @@ -714,27 +729,25 @@ static int ioctl_allocate(struct client *client, void *buffer) release_address_handler(client, &r->resource); return ret; } - request->handle = r->resource.handle; + a->handle = r->resource.handle; return 0; } -static int ioctl_deallocate(struct client *client, void *buffer) +static int ioctl_deallocate(struct client *client, union ioctl_arg *arg) { - struct fw_cdev_deallocate *request = buffer; - - return release_client_resource(client, request->handle, + return release_client_resource(client, arg->deallocate.handle, release_address_handler, NULL); } -static int ioctl_send_response(struct client *client, void *buffer) +static int ioctl_send_response(struct client *client, union ioctl_arg *arg) { - struct fw_cdev_send_response *request = buffer; + struct fw_cdev_send_response *a = &arg->send_response; struct client_resource *resource; struct inbound_transaction_resource *r; int ret = 0; - if (release_client_resource(client, request->handle, + if (release_client_resource(client, a->handle, release_request, &resource) < 0) return -EINVAL; @@ -743,28 +756,24 @@ static int ioctl_send_response(struct client *client, void *buffer) if (is_fcp_request(r->request)) goto out; - if (request->length < r->length) - r->length = request->length; - if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) { + if (a->length < r->length) + r->length = a->length; + if (copy_from_user(r->data, u64_to_uptr(a->data), r->length)) { ret = -EFAULT; kfree(r->request); goto out; } - fw_send_response(client->device->card, r->request, request->rcode); + fw_send_response(client->device->card, r->request, a->rcode); out: kfree(r); return ret; } -static int ioctl_initiate_bus_reset(struct client *client, void *buffer) +static int ioctl_initiate_bus_reset(struct client *client, union ioctl_arg *arg) { - struct fw_cdev_initiate_bus_reset *request = buffer; - int short_reset; - - short_reset = (request->type == FW_CDEV_SHORT_RESET); - - return fw_core_initiate_bus_reset(client->device->card, short_reset); + return fw_core_initiate_bus_reset(client->device->card, + arg->initiate_bus_reset.type == FW_CDEV_SHORT_RESET); } static void release_descriptor(struct client *client, @@ -777,9 +786,9 @@ static void release_descriptor(struct client *client, kfree(r); } -static int ioctl_add_descriptor(struct client *client, void *buffer) +static int ioctl_add_descriptor(struct client *client, union ioctl_arg *arg) { - struct fw_cdev_add_descriptor *request = buffer; + struct fw_cdev_add_descriptor *a = &arg->add_descriptor; struct descriptor_resource *r; int ret; @@ -787,22 +796,21 @@ static int ioctl_add_descriptor(struct client *client, void *buffer) if (!client->device->is_local) return -ENOSYS; - if (request->length > 256) + if (a->length > 256) return -EINVAL; - r = kmalloc(sizeof(*r) + request->length * 4, GFP_KERNEL); + r = kmalloc(sizeof(*r) + a->length * 4, GFP_KERNEL); if (r == NULL) return -ENOMEM; - if (copy_from_user(r->data, - u64_to_uptr(request->data), request->length * 4)) { + if (copy_from_user(r->data, u64_to_uptr(a->data), a->length * 4)) { ret = -EFAULT; goto failed; } - r->descriptor.length = request->length; - r->descriptor.immediate = request->immediate; - r->descriptor.key = request->key; + r->descriptor.length = a->length; + r->descriptor.immediate = a->immediate; + r->descriptor.key = a->key; r->descriptor.data = r->data; ret = fw_core_add_descriptor(&r->descriptor); @@ -815,7 +823,7 @@ static int ioctl_add_descriptor(struct client *client, void *buffer) fw_core_remove_descriptor(&r->descriptor); goto failed; } - request->handle = r->resource.handle; + a->handle = r->resource.handle; return 0; failed: @@ -824,11 +832,9 @@ static int ioctl_add_descriptor(struct client *client, void *buffer) return ret; } -static int ioctl_remove_descriptor(struct client *client, void *buffer) +static int ioctl_remove_descriptor(struct client *client, union ioctl_arg *arg) { - struct fw_cdev_remove_descriptor *request = buffer; - - return release_client_resource(client, request->handle, + return release_client_resource(client, arg->remove_descriptor.handle, release_descriptor, NULL); } @@ -851,49 +857,44 @@ static void iso_callback(struct fw_iso_context *context, u32 cycle, sizeof(e->interrupt) + header_length, NULL, 0); } -static int ioctl_create_iso_context(struct client *client, void *buffer) +static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg) { - struct fw_cdev_create_iso_context *request = buffer; + struct fw_cdev_create_iso_context *a = &arg->create_iso_context; struct fw_iso_context *context; /* We only support one context at this time. */ if (client->iso_context != NULL) return -EBUSY; - if (request->channel > 63) + if (a->channel > 63) return -EINVAL; - switch (request->type) { + switch (a->type) { case FW_ISO_CONTEXT_RECEIVE: - if (request->header_size < 4 || (request->header_size & 3)) + if (a->header_size < 4 || (a->header_size & 3)) return -EINVAL; - break; case FW_ISO_CONTEXT_TRANSMIT: - if (request->speed > SCODE_3200) + if (a->speed > SCODE_3200) return -EINVAL; - break; default: return -EINVAL; } - context = fw_iso_context_create(client->device->card, - request->type, - request->channel, - request->speed, - request->header_size, - iso_callback, client); + context = fw_iso_context_create(client->device->card, a->type, + a->channel, a->speed, a->header_size, + iso_callback, client); if (IS_ERR(context)) return PTR_ERR(context); - client->iso_closure = request->closure; + client->iso_closure = a->closure; client->iso_context = context; /* We only support one context at this time. */ - request->handle = 0; + a->handle = 0; return 0; } @@ -906,9 +907,9 @@ static int ioctl_create_iso_context(struct client *client, void *buffer) #define GET_SY(v) (((v) >> 20) & 0x0f) #define GET_HEADER_LENGTH(v) (((v) >> 24) & 0xff) -static int ioctl_queue_iso(struct client *client, void *buffer) +static int ioctl_queue_iso(struct client *client, union ioctl_arg *arg) { - struct fw_cdev_queue_iso *request = buffer; + struct fw_cdev_queue_iso *a = &arg->queue_iso; struct fw_cdev_iso_packet __user *p, *end, *next; struct fw_iso_context *ctx = client->iso_context; unsigned long payload, buffer_end, header_length; @@ -919,7 +920,7 @@ static int ioctl_queue_iso(struct client *client, void *buffer) u8 header[256]; } u; - if (ctx == NULL || request->handle != 0) + if (ctx == NULL || a->handle != 0) return -EINVAL; /* @@ -929,23 +930,23 @@ static int ioctl_queue_iso(struct client *client, void *buffer) * set them both to 0, which will still let packets with * payload_length == 0 through. In other words, if no packets * use the indirect payload, the iso buffer need not be mapped - * and the request->data pointer is ignored. + * and the a->data pointer is ignored. */ - payload = (unsigned long)request->data - client->vm_start; + payload = (unsigned long)a->data - client->vm_start; buffer_end = client->buffer.page_count << PAGE_SHIFT; - if (request->data == 0 || client->buffer.pages == NULL || + if (a->data == 0 || client->buffer.pages == NULL || payload >= buffer_end) { payload = 0; buffer_end = 0; } - p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(request->packets); + p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(a->packets); - if (!access_ok(VERIFY_READ, p, request->size)) + if (!access_ok(VERIFY_READ, p, a->size)) return -EFAULT; - end = (void __user *)p + request->size; + end = (void __user *)p + a->size; count = 0; while (p < end) { if (get_user(control, &p->control)) @@ -995,45 +996,41 @@ static int ioctl_queue_iso(struct client *client, void *buffer) count++; } - request->size -= uptr_to_u64(p) - request->packets; - request->packets = uptr_to_u64(p); - request->data = client->vm_start + payload; + a->size -= uptr_to_u64(p) - a->packets; + a->packets = uptr_to_u64(p); + a->data = client->vm_start + payload; return count; } -static int ioctl_start_iso(struct client *client, void *buffer) +static int ioctl_start_iso(struct client *client, union ioctl_arg *arg) { - struct fw_cdev_start_iso *request = buffer; + struct fw_cdev_start_iso *a = &arg->start_iso; - if (client->iso_context == NULL || request->handle != 0) + if (client->iso_context == NULL || a->handle != 0) return -EINVAL; - if (client->iso_context->type == FW_ISO_CONTEXT_RECEIVE) { - if (request->tags == 0 || request->tags > 15) - return -EINVAL; - - if (request->sync > 15) - return -EINVAL; - } + if (client->iso_context->type == FW_ISO_CONTEXT_RECEIVE && + (a->tags == 0 || a->tags > 15 || a->sync > 15)) + return -EINVAL; - return fw_iso_context_start(client->iso_context, request->cycle, - request->sync, request->tags); + return fw_iso_context_start(client->iso_context, + a->cycle, a->sync, a->tags); } -static int ioctl_stop_iso(struct client *client, void *buffer) +static int ioctl_stop_iso(struct client *client, union ioctl_arg *arg) { - struct fw_cdev_stop_iso *request = buffer; + struct fw_cdev_stop_iso *a = &arg->stop_iso; - if (client->iso_context == NULL || request->handle != 0) + if (client->iso_context == NULL || a->handle != 0) return -EINVAL; return fw_iso_context_stop(client->iso_context); } -static int ioctl_get_cycle_timer2(struct client *client, void *buffer) +static int ioctl_get_cycle_timer2(struct client *client, union ioctl_arg *arg) { - struct fw_cdev_get_cycle_timer2 *request = buffer; + struct fw_cdev_get_cycle_timer2 *a = &arg->get_cycle_timer2; struct fw_card *card = client->device->card; struct timespec ts = {0, 0}; u32 cycle_time; @@ -1043,7 +1040,7 @@ static int ioctl_get_cycle_timer2(struct client *client, void *buffer) cycle_time = card->driver->get_cycle_time(card); - switch (request->clk_id) { + switch (a->clk_id) { case CLOCK_REALTIME: getnstimeofday(&ts); break; case CLOCK_MONOTONIC: do_posix_clock_monotonic_gettime(&ts); break; case CLOCK_MONOTONIC_RAW: getrawmonotonic(&ts); break; @@ -1053,24 +1050,23 @@ static int ioctl_get_cycle_timer2(struct client *client, void *buffer) local_irq_enable(); - request->tv_sec = ts.tv_sec; - request->tv_nsec = ts.tv_nsec; - request->cycle_timer = cycle_time; + a->tv_sec = ts.tv_sec; + a->tv_nsec = ts.tv_nsec; + a->cycle_timer = cycle_time; return ret; } -static int ioctl_get_cycle_timer(struct client *client, void *buffer) +static int ioctl_get_cycle_timer(struct client *client, union ioctl_arg *arg) { - struct fw_cdev_get_cycle_timer *request = buffer; + struct fw_cdev_get_cycle_timer *a = &arg->get_cycle_timer; struct fw_cdev_get_cycle_timer2 ct2; ct2.clk_id = CLOCK_REALTIME; - ioctl_get_cycle_timer2(client, &ct2); + ioctl_get_cycle_timer2(client, (union ioctl_arg *)&ct2); - request->local_time = ct2.tv_sec * USEC_PER_SEC + - ct2.tv_nsec / NSEC_PER_USEC; - request->cycle_timer = ct2.cycle_timer; + a->local_time = ct2.tv_sec * USEC_PER_SEC + ct2.tv_nsec / NSEC_PER_USEC; + a->cycle_timer = ct2.cycle_timer; return 0; } @@ -1242,33 +1238,32 @@ static int init_iso_resource(struct client *client, return ret; } -static int ioctl_allocate_iso_resource(struct client *client, void *buffer) +static int ioctl_allocate_iso_resource(struct client *client, + union ioctl_arg *arg) { - struct fw_cdev_allocate_iso_resource *request = buffer; - - return init_iso_resource(client, request, ISO_RES_ALLOC); + return init_iso_resource(client, + &arg->allocate_iso_resource, ISO_RES_ALLOC); } -static int ioctl_deallocate_iso_resource(struct client *client, void *buffer) +static int ioctl_deallocate_iso_resource(struct client *client, + union ioctl_arg *arg) { - struct fw_cdev_deallocate *request = buffer; - - return release_client_resource(client, request->handle, - release_iso_resource, NULL); + return release_client_resource(client, + arg->deallocate.handle, release_iso_resource, NULL); } -static int ioctl_allocate_iso_resource_once(struct client *client, void *buffer) +static int ioctl_allocate_iso_resource_once(struct client *client, + union ioctl_arg *arg) { - struct fw_cdev_allocate_iso_resource *request = buffer; - - return init_iso_resource(client, request, ISO_RES_ALLOC_ONCE); + return init_iso_resource(client, + &arg->allocate_iso_resource, ISO_RES_ALLOC_ONCE); } -static int ioctl_deallocate_iso_resource_once(struct client *client, void *buffer) +static int ioctl_deallocate_iso_resource_once(struct client *client, + union ioctl_arg *arg) { - struct fw_cdev_allocate_iso_resource *request = buffer; - - return init_iso_resource(client, request, ISO_RES_DEALLOC_ONCE); + return init_iso_resource(client, + &arg->allocate_iso_resource, ISO_RES_DEALLOC_ONCE); } /* @@ -1276,16 +1271,17 @@ static int ioctl_deallocate_iso_resource_once(struct client *client, void *buffe * limited by the device's link speed, the local node's link speed, * and all PHY port speeds between the two links. */ -static int ioctl_get_speed(struct client *client, void *buffer) +static int ioctl_get_speed(struct client *client, union ioctl_arg *arg) { return client->device->max_speed; } -static int ioctl_send_broadcast_request(struct client *client, void *buffer) +static int ioctl_send_broadcast_request(struct client *client, + union ioctl_arg *arg) { - struct fw_cdev_send_request *request = buffer; + struct fw_cdev_send_request *a = &arg->send_request; - switch (request->tcode) { + switch (a->tcode) { case TCODE_WRITE_QUADLET_REQUEST: case TCODE_WRITE_BLOCK_REQUEST: break; @@ -1294,36 +1290,36 @@ static int ioctl_send_broadcast_request(struct client *client, void *buffer) } /* Security policy: Only allow accesses to Units Space. */ - if (request->offset < CSR_REGISTER_BASE + CSR_CONFIG_ROM_END) + if (a->offset < CSR_REGISTER_BASE + CSR_CONFIG_ROM_END) return -EACCES; - return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100); + return init_request(client, a, LOCAL_BUS | 0x3f, SCODE_100); } -static int ioctl_send_stream_packet(struct client *client, void *buffer) +static int ioctl_send_stream_packet(struct client *client, union ioctl_arg *arg) { - struct fw_cdev_send_stream_packet *p = buffer; + struct fw_cdev_send_stream_packet *a = &arg->send_stream_packet; struct fw_cdev_send_request request; int dest; - if (p->speed > client->device->card->link_speed || - p->length > 1024 << p->speed) + if (a->speed > client->device->card->link_speed || + a->length > 1024 << a->speed) return -EIO; - if (p->tag > 3 || p->channel > 63 || p->sy > 15) + if (a->tag > 3 || a->channel > 63 || a->sy > 15) return -EINVAL; - dest = fw_stream_packet_destination_id(p->tag, p->channel, p->sy); + dest = fw_stream_packet_destination_id(a->tag, a->channel, a->sy); request.tcode = TCODE_STREAM_DATA; - request.length = p->length; - request.closure = p->closure; - request.data = p->data; - request.generation = p->generation; + request.length = a->length; + request.closure = a->closure; + request.data = a->data; + request.generation = a->generation; - return init_request(client, &request, dest, p->speed); + return init_request(client, &request, dest, a->speed); } -static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { +static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = { ioctl_get_info, ioctl_send_request, ioctl_allocate, @@ -1350,24 +1346,7 @@ static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { static int dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) { - char buffer[sizeof(union { - struct fw_cdev_get_info _00; - struct fw_cdev_send_request _01; - struct fw_cdev_allocate _02; - struct fw_cdev_deallocate _03; - struct fw_cdev_send_response _04; - struct fw_cdev_initiate_bus_reset _05; - struct fw_cdev_add_descriptor _06; - struct fw_cdev_remove_descriptor _07; - struct fw_cdev_create_iso_context _08; - struct fw_cdev_queue_iso _09; - struct fw_cdev_start_iso _0a; - struct fw_cdev_stop_iso _0b; - struct fw_cdev_get_cycle_timer _0c; - struct fw_cdev_allocate_iso_resource _0d; - struct fw_cdev_send_stream_packet _13; - struct fw_cdev_get_cycle_timer2 _14; - })]; + union ioctl_arg buffer; int ret; if (_IOC_TYPE(cmd) != '#' || @@ -1376,17 +1355,17 @@ static int dispatch_ioctl(struct client *client, if (_IOC_DIR(cmd) & _IOC_WRITE) { if (_IOC_SIZE(cmd) > sizeof(buffer) || - copy_from_user(buffer, arg, _IOC_SIZE(cmd))) + copy_from_user(&buffer, arg, _IOC_SIZE(cmd))) return -EFAULT; } - ret = ioctl_handlers[_IOC_NR(cmd)](client, buffer); + ret = ioctl_handlers[_IOC_NR(cmd)](client, &buffer); if (ret < 0) return ret; if (_IOC_DIR(cmd) & _IOC_READ) { if (_IOC_SIZE(cmd) > sizeof(buffer) || - copy_to_user(arg, buffer, _IOC_SIZE(cmd))) + copy_to_user(arg, &buffer, _IOC_SIZE(cmd))) return -EFAULT; } -- cgit v1.2.3 From 64582298b9c29535188380f488873e7d2196a2eb Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 21 Feb 2010 17:56:42 +0100 Subject: firewire: core: combine a bit of repeated code Signed-off-by: Stefan Richter --- drivers/firewire/core-cdev.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'drivers/firewire/core-cdev.c') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index d7de17a0f250..8be720b278b7 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -1349,6 +1349,9 @@ static int dispatch_ioctl(struct client *client, union ioctl_arg buffer; int ret; + if (fw_device_is_shutdown(client->device)) + return -ENODEV; + if (_IOC_TYPE(cmd) != '#' || _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers)) return -EINVAL; @@ -1375,24 +1378,14 @@ static int dispatch_ioctl(struct client *client, static long fw_device_op_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct client *client = file->private_data; - - if (fw_device_is_shutdown(client->device)) - return -ENODEV; - - return dispatch_ioctl(client, cmd, (void __user *) arg); + return dispatch_ioctl(file->private_data, cmd, (void __user *)arg); } #ifdef CONFIG_COMPAT static long fw_device_op_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct client *client = file->private_data; - - if (fw_device_is_shutdown(client->device)) - return -ENODEV; - - return dispatch_ioctl(client, cmd, compat_ptr(arg)); + return dispatch_ioctl(file->private_data, cmd, compat_ptr(arg)); } #endif -- cgit v1.2.3