* Released under the GPLv2 only.
*/
+#include <linux/workqueue.h>
+
#include "greybus.h"
static DEFINE_SPINLOCK(gb_connections_lock);
{
struct gb_connection *connection = to_gb_connection(dev);
+ destroy_workqueue(connection->wq);
kfree(connection);
}
spin_lock_init(&connection->lock);
INIT_LIST_HEAD(&connection->operations);
+ connection->wq = alloc_workqueue("%s:%d", WQ_UNBOUND, 1,
+ dev_name(parent), cport_id);
+ if (!connection->wq)
+ goto err_free_connection;
+
connection->dev.parent = parent;
connection->dev.bus = &greybus_bus_type;
connection->dev.type = &greybus_connection_type;
return connection;
+err_free_connection:
+ kfree(connection);
err_remove_ida:
ida_simple_remove(id_map, hd_cport_id);
static struct kmem_cache *gb_operation_cache;
static struct kmem_cache *gb_message_cache;
-/* Workqueue to handle Greybus operation completions. */
-static struct workqueue_struct *gb_operation_workqueue;
-
/* Wait queue for synchronous cancellations. */
static DECLARE_WAIT_QUEUE_HEAD(gb_operation_cancellation_queue);
gb_operation_put(operation);
} else if (status) {
if (gb_operation_result_set(operation, status))
- queue_work(gb_operation_workqueue, &operation->work);
+ queue_work(connection->wq, &operation->work);
}
}
EXPORT_SYMBOL_GPL(greybus_message_sent);
* request handler returns.
*/
if (gb_operation_result_set(operation, -EINPROGRESS))
- queue_work(gb_operation_workqueue, &operation->work);
+ queue_work(connection->wq, &operation->work);
}
/*
/* The rest will be handled in work queue context */
if (gb_operation_result_set(operation, errno)) {
memcpy(message->header, data, size);
- queue_work(gb_operation_workqueue, &operation->work);
+ queue_work(connection->wq, &operation->work);
}
gb_operation_put(operation);
*/
void gb_operation_cancel(struct gb_operation *operation, int errno)
{
+ struct gb_connection *connection = operation->connection;
+
if (WARN_ON(gb_operation_is_incoming(operation)))
return;
if (gb_operation_result_set(operation, errno)) {
gb_message_cancel(operation->request);
- queue_work(gb_operation_workqueue, &operation->work);
+ queue_work(connection->wq, &operation->work);
}
atomic_inc(&operation->waiters);
if (!gb_operation_cache)
goto err_destroy_message_cache;
- gb_operation_workqueue = alloc_workqueue("greybus_operation",
- WQ_UNBOUND, 1);
- if (!gb_operation_workqueue)
- goto err_operation;
-
return 0;
-err_operation:
- kmem_cache_destroy(gb_operation_cache);
- gb_operation_cache = NULL;
+
err_destroy_message_cache:
kmem_cache_destroy(gb_message_cache);
gb_message_cache = NULL;
void gb_operation_exit(void)
{
- destroy_workqueue(gb_operation_workqueue);
- gb_operation_workqueue = NULL;
kmem_cache_destroy(gb_operation_cache);
gb_operation_cache = NULL;
kmem_cache_destroy(gb_message_cache);