struct event event;
struct fw_transaction transaction;
struct client *client;
+ struct list_head link;
struct fw_cdev_event_response response;
};
spinlock_t lock;
struct list_head handler_list;
struct list_head request_list;
+ struct list_head transaction_list;
u32 request_serial;
struct list_head event_list;
wait_queue_head_t wait;
INIT_LIST_HEAD(&client->event_list);
INIT_LIST_HEAD(&client->handler_list);
INIT_LIST_HEAD(&client->request_list);
+ INIT_LIST_HEAD(&client->transaction_list);
spin_lock_init(&client->lock);
init_waitqueue_head(&client->wait);
{
struct response *response = data;
struct client *client = response->client;
+ unsigned long flags;
if (length < response->response.length)
response->response.length = length;
memcpy(response->response.data, payload,
response->response.length);
+ spin_lock_irqsave(&client->lock, flags);
+ list_del(&response->link);
+ spin_unlock_irqrestore(&client->lock, flags);
+
response->response.type = FW_CDEV_EVENT_RESPONSE;
response->response.rcode = rcode;
queue_event(client, &response->event,
struct fw_device *device = client->device;
struct fw_cdev_send_request request;
struct response *response;
+ unsigned long flags;
if (copy_from_user(&request, arg, sizeof request))
return -EFAULT;
return -EFAULT;
}
+ spin_lock_irqsave(&client->lock, flags);
+ list_add_tail(&response->link, &client->transaction_list);
+ spin_unlock_irqrestore(&client->lock, flags);
+
fw_send_request(device->card, &response->transaction,
request.tcode & 0x1f,
device->node->node_id,
struct address_handler *h, *next_h;
struct request *r, *next_r;
struct event *e, *next_e;
+ struct response *t, *next_t;
unsigned long flags;
if (client->buffer.pages)
kfree(r);
}
- /* TODO: wait for all transactions to finish so
- * complete_transaction doesn't try to queue up responses
- * after we free client. */
+ list_for_each_entry_safe(t, next_t, &client->transaction_list, link)
+ fw_cancel_transaction(client->device->card, &t->transaction);
+
+ /* FIXME: We should wait for the async tasklets to stop
+ * running before freeing the memory. */
+
list_for_each_entry_safe(e, next_e, &client->event_list, link)
kfree(e);