diff options
Diffstat (limited to 'drivers/firewire/core-cdev.c')
| -rw-r--r-- | drivers/firewire/core-cdev.c | 54 |
1 files changed, 25 insertions, 29 deletions
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 2783f69dada..d7d5c8af92b 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -54,6 +54,7 @@ #define FW_CDEV_KERNEL_VERSION 5 #define FW_CDEV_VERSION_EVENT_REQUEST2 4 #define FW_CDEV_VERSION_ALLOCATE_REGION_END 4 +#define FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW 5 struct client { u32 version; @@ -389,10 +390,8 @@ static void queue_bus_reset_event(struct client *client) struct bus_reset_event *e; e = kzalloc(sizeof(*e), GFP_KERNEL); - if (e == NULL) { - fw_notice(client->device->card, "out of memory when allocating event\n"); + if (e == NULL) return; - } fill_bus_reset_event(&e->reset, client); @@ -473,8 +472,8 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg) client->bus_reset_closure = a->bus_reset_closure; if (a->bus_reset != 0) { fill_bus_reset_event(&bus_reset, client); - ret = copy_to_user(u64_to_uptr(a->bus_reset), - &bus_reset, sizeof(bus_reset)); + /* unaligned size of bus_reset is 36 bytes */ + ret = copy_to_user(u64_to_uptr(a->bus_reset), &bus_reset, 36); } if (ret == 0 && list_empty(&client->link)) list_add_tail(&client->link, &client->device->client_list); @@ -487,27 +486,28 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg) static int add_client_resource(struct client *client, struct client_resource *resource, gfp_t gfp_mask) { + bool preload = !!(gfp_mask & __GFP_WAIT); unsigned long flags; int ret; - retry: - if (idr_pre_get(&client->resource_idr, gfp_mask) == 0) - return -ENOMEM; - + if (preload) + idr_preload(gfp_mask); spin_lock_irqsave(&client->lock, flags); + if (client->in_shutdown) ret = -ECANCELED; else - ret = idr_get_new(&client->resource_idr, resource, - &resource->handle); + ret = idr_alloc(&client->resource_idr, resource, 0, 0, + GFP_NOWAIT); if (ret >= 0) { + resource->handle = ret; client_get(client); schedule_if_iso_resource(resource); } - spin_unlock_irqrestore(&client->lock, flags); - if (ret == -EAGAIN) - goto retry; + spin_unlock_irqrestore(&client->lock, flags); + if (preload) + idr_preload_end(); return ret < 0 ? ret : 0; } @@ -692,10 +692,9 @@ static void handle_request(struct fw_card *card, struct fw_request *request, r = kmalloc(sizeof(*r), GFP_ATOMIC); e = kmalloc(sizeof(*e), GFP_ATOMIC); - if (r == NULL || e == NULL) { - fw_notice(card, "out of memory when allocating event\n"); + if (r == NULL || e == NULL) goto failed; - } + r->card = card; r->request = request; r->data = payload; @@ -929,10 +928,9 @@ static void iso_callback(struct fw_iso_context *context, u32 cycle, struct iso_interrupt_event *e; e = kmalloc(sizeof(*e) + header_length, GFP_ATOMIC); - if (e == NULL) { - fw_notice(context->card, "out of memory when allocating event\n"); + if (e == NULL) return; - } + e->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT; e->interrupt.closure = client->iso_closure; e->interrupt.cycle = cycle; @@ -949,10 +947,9 @@ static void iso_mc_callback(struct fw_iso_context *context, struct iso_interrupt_mc_event *e; e = kmalloc(sizeof(*e), GFP_ATOMIC); - if (e == NULL) { - fw_notice(context->card, "out of memory when allocating event\n"); + if (e == NULL) return; - } + e->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL; e->interrupt.closure = client->iso_closure; e->interrupt.completed = fw_iso_buffer_lookup(&client->buffer, @@ -1009,6 +1006,8 @@ static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg) a->channel, a->speed, a->header_size, cb, client); if (IS_ERR(context)) return PTR_ERR(context); + if (client->version < FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW) + context->drop_overflow_headers = true; /* We only support one context at this time. */ spin_lock_irq(&client->lock); @@ -1365,8 +1364,7 @@ static int init_iso_resource(struct client *client, int ret; if ((request->channels == 0 && request->bandwidth == 0) || - request->bandwidth > BANDWIDTH_AVAILABLE_INITIAL || - request->bandwidth < 0) + request->bandwidth > BANDWIDTH_AVAILABLE_INITIAL) return -EINVAL; r = kmalloc(sizeof(*r), GFP_KERNEL); @@ -1581,10 +1579,9 @@ void fw_cdev_handle_phy_packet(struct fw_card *card, struct fw_packet *p) list_for_each_entry(client, &card->phy_receiver_list, phy_receiver_link) { e = kmalloc(sizeof(*e) + 8, GFP_ATOMIC); - if (e == NULL) { - fw_notice(card, "out of memory when allocating event\n"); + if (e == NULL) break; - } + e->phy_packet.closure = client->phy_receiver_closure; e->phy_packet.type = FW_CDEV_EVENT_PHY_PACKET_RECEIVED; e->phy_packet.rcode = RCODE_COMPLETE; @@ -1779,7 +1776,6 @@ static int fw_device_op_release(struct inode *inode, struct file *file) wait_event(client->tx_flush_wait, !has_outbound_transactions(client)); idr_for_each(&client->resource_idr, shutdown_resource, client); - idr_remove_all(&client->resource_idr); idr_destroy(&client->resource_idr); list_for_each_entry_safe(event, next_event, &client->event_list, link) |
