firewire: core: change type of a data buffer
authorStefan Richter <stefanr@s5r6.in-berlin.de>
Sun, 21 Feb 2010 16:56:21 +0000 (17:56 +0100)
committerStefan Richter <stefanr@s5r6.in-berlin.de>
Wed, 24 Feb 2010 19:36:55 +0000 (20:36 +0100)
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 <stefanr@s5r6.in-berlin.de>
drivers/firewire/core-cdev.c

index a4aa477b9b2c3d2e1d6af6a3a06a7b2a635e26ca..d7de17a0f250a7b8913a471999eb98fe4cb07d0d 100644 (file)
@@ -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, &region);
        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;
        }