greybus: hd: rename host-device structure
[cascardo/linux.git] / drivers / staging / greybus / operation.c
index 63c4a5b..1643880 100644 (file)
 #include <linux/workqueue.h>
 
 #include "greybus.h"
+#include "greybus_trace.h"
 
 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;
+static struct workqueue_struct *gb_operation_completion_wq;
 
 /* Wait queue for synchronous cancellations. */
 static DECLARE_WAIT_QUEUE_HEAD(gb_operation_cancellation_queue);
@@ -197,10 +198,11 @@ static int gb_message_send(struct gb_message *message, gfp_t gfp)
 {
        struct gb_connection *connection = message->operation->connection;
 
+       trace_gb_message_send(message);
        return connection->hd->driver->message_send(connection->hd,
                                        connection->hd_cport_id,
                                        message,
-                                       GFP_KERNEL);
+                                       gfp);
 }
 
 /*
@@ -208,7 +210,7 @@ static int gb_message_send(struct gb_message *message, gfp_t gfp)
  */
 static void gb_message_cancel(struct gb_message *message)
 {
-       struct greybus_host_device *hd = message->operation->connection->hd;
+       struct gb_host_device *hd = message->operation->connection->hd;
 
        hd->driver->message_cancel(message);
 }
@@ -225,7 +227,7 @@ static void gb_operation_request_handle(struct gb_operation *operation)
        if (protocol->request_recv) {
                status = protocol->request_recv(operation->type, operation);
        } else {
-               dev_err(&operation->connection->dev,
+               dev_err(&operation->connection->bundle->dev,
                        "unexpected incoming request type 0x%02hhx\n",
                        operation->type);
 
@@ -234,9 +236,9 @@ static void gb_operation_request_handle(struct gb_operation *operation)
 
        ret = gb_operation_response_send(operation, status);
        if (ret) {
-               dev_err(&operation->connection->dev,
-                       "failed to send response %d: %d\n",
-                       status, ret);
+               dev_err(&operation->connection->bundle->dev,
+                       "failed to send response %d for type 0x%02hhx: %d\n",
+                       status, operation->type, ret);
                        return;
        }
 }
@@ -267,7 +269,7 @@ static void gb_operation_work(struct work_struct *work)
        gb_operation_put(operation);
 }
 
-static void gb_operation_message_init(struct greybus_host_device *hd,
+static void gb_operation_message_init(struct gb_host_device *hd,
                                struct gb_message *message, u16 operation_id,
                                size_t payload_size, u8 type)
 {
@@ -318,7 +320,7 @@ static void gb_operation_message_init(struct greybus_host_device *hd,
  *     message payload /  the message size
  */
 static struct gb_message *
-gb_operation_message_alloc(struct greybus_host_device *hd, u8 type,
+gb_operation_message_alloc(struct gb_host_device *hd, u8 type,
                                size_t payload_size, gfp_t gfp_flags)
 {
        struct gb_message *message;
@@ -426,16 +428,15 @@ static u8 gb_operation_errno_map(int errno)
 }
 
 bool gb_operation_response_alloc(struct gb_operation *operation,
-                                       size_t response_size)
+                                       size_t response_size, gfp_t gfp)
 {
-       struct greybus_host_device *hd = operation->connection->hd;
+       struct gb_host_device *hd = operation->connection->hd;
        struct gb_operation_msg_hdr *request_header;
        struct gb_message *response;
        u8 type;
 
        type = operation->type | GB_MESSAGE_TYPE_RESPONSE;
-       response = gb_operation_message_alloc(hd, type, response_size,
-                                               GFP_KERNEL);
+       response = gb_operation_message_alloc(hd, type, response_size, gfp);
        if (!response)
                return false;
        response->operation = operation;
@@ -481,7 +482,7 @@ gb_operation_create_common(struct gb_connection *connection, u8 type,
                                size_t request_size, size_t response_size,
                                unsigned long op_flags, gfp_t gfp_flags)
 {
-       struct greybus_host_device *hd = connection->hd;
+       struct gb_host_device *hd = connection->hd;
        struct gb_operation *operation;
 
        operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags);
@@ -497,8 +498,10 @@ gb_operation_create_common(struct gb_connection *connection, u8 type,
 
        /* Allocate the response buffer for outgoing operations */
        if (!(op_flags & GB_OPERATION_FLAG_INCOMING)) {
-               if (!gb_operation_response_alloc(operation, response_size))
+               if (!gb_operation_response_alloc(operation, response_size,
+                                                gfp_flags)) {
                        goto err_request;
+               }
        }
 
        operation->flags = op_flags;
@@ -545,7 +548,7 @@ EXPORT_SYMBOL_GPL(gb_operation_create);
 
 size_t gb_operation_get_payload_size_max(struct gb_connection *connection)
 {
-       struct greybus_host_device *hd = connection->hd;
+       struct gb_host_device *hd = connection->hd;
 
        return hd->buffer_size_max - sizeof(struct gb_operation_msg_hdr);
 }
@@ -734,13 +737,13 @@ static int gb_operation_response_send(struct gb_operation *operation,
 
        if (!operation->response &&
                        !gb_operation_is_unidirectional(operation)) {
-               if (!gb_operation_response_alloc(operation, 0))
+               if (!gb_operation_response_alloc(operation, 0, GFP_KERNEL))
                        return -ENOMEM;
        }
 
        /* Record the result */
        if (!gb_operation_result_set(operation, errno)) {
-               dev_err(&connection->dev, "request result already set\n");
+               dev_err(&connection->bundle->dev, "request result already set\n");
                return -EIO;    /* Shouldn't happen */
        }
 
@@ -774,10 +777,11 @@ err_put:
 /*
  * This function is called when a message send request has completed.
  */
-void greybus_message_sent(struct greybus_host_device *hd,
+void greybus_message_sent(struct gb_host_device *hd,
                                        struct gb_message *message, int status)
 {
-       struct gb_operation *operation;
+       struct gb_operation *operation = message->operation;
+       struct gb_connection *connection = operation->connection;
 
        /*
         * If the message was a response, we just need to drop our
@@ -789,17 +793,19 @@ void greybus_message_sent(struct greybus_host_device *hd,
         * attempting to send it, record that as the result of
         * the operation and schedule its completion.
         */
-       operation = message->operation;
        if (message == operation->response) {
                if (status) {
-                       dev_err(&operation->connection->dev,
-                               "error sending response: %d\n", status);
+                       dev_err(&connection->bundle->dev,
+                               "error sending response type 0x%02hhx: %d\n",
+                               operation->type, status);
                }
                gb_operation_put_active(operation);
                gb_operation_put(operation);
        } else if (status) {
-               if (gb_operation_result_set(operation, status))
-                       queue_work(gb_operation_workqueue, &operation->work);
+               if (gb_operation_result_set(operation, status)) {
+                       queue_work(gb_operation_completion_wq,
+                                       &operation->work);
+               }
        }
 }
 EXPORT_SYMBOL_GPL(greybus_message_sent);
@@ -821,8 +827,9 @@ static void gb_connection_recv_request(struct gb_connection *connection,
        operation = gb_operation_create_incoming(connection, operation_id,
                                                type, data, size);
        if (!operation) {
-               dev_err(&connection->dev, "can't create operation\n");
-               return;         /* XXX Respond with pre-allocated ENOMEM */
+               dev_err(&connection->bundle->dev,
+                       "can't create incoming operation\n");
+               return;
        }
 
        ret = gb_operation_get_active(operation);
@@ -830,13 +837,14 @@ static void gb_connection_recv_request(struct gb_connection *connection,
                gb_operation_put(operation);
                return;
        }
+       trace_gb_message_recv_request(operation->request);
 
        /*
         * The initial reference to the operation will be dropped when the
         * request handler returns.
         */
        if (gb_operation_result_set(operation, -EINPROGRESS))
-               queue_work(gb_operation_workqueue, &operation->work);
+               queue_work(connection->wq, &operation->work);
 }
 
 /*
@@ -857,17 +865,20 @@ static void gb_connection_recv_response(struct gb_connection *connection,
 
        operation = gb_operation_find_outgoing(connection, operation_id);
        if (!operation) {
-               dev_err(&connection->dev, "operation not found\n");
+               dev_err(&connection->bundle->dev,
+                       "unexpected response 0x%04hx received\n", operation_id);
                return;
        }
 
        message = operation->response;
        message_size = sizeof(*message->header) + message->payload_size;
        if (!errno && size != message_size) {
-               dev_err(&connection->dev, "bad message size (%zu != %zu)\n",
-                       size, message_size);
+               dev_err(&connection->bundle->dev,
+                       "malformed response of type 0x%02hhx received (%zu != %zu)\n",
+                       message->header->type, size, message_size);
                errno = -EMSGSIZE;
        }
+       trace_gb_message_recv_response(operation->response);
 
        /* We must ignore the payload if a bad status is returned */
        if (errno)
@@ -876,7 +887,7 @@ static void gb_connection_recv_response(struct gb_connection *connection,
        /* 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(gb_operation_completion_wq, &operation->work);
        }
 
        gb_operation_put(operation);
@@ -891,17 +902,17 @@ void gb_connection_recv(struct gb_connection *connection,
                                void *data, size_t size)
 {
        struct gb_operation_msg_hdr header;
+       struct device *dev = &connection->bundle->dev;
        size_t msg_size;
        u16 operation_id;
 
        if (connection->state != GB_CONNECTION_STATE_ENABLED) {
-               dev_err(&connection->dev, "dropping %zu received bytes\n",
-                       size);
+               dev_warn(dev, "dropping %zu received bytes\n", size);
                return;
        }
 
        if (size < sizeof(header)) {
-               dev_err(&connection->dev, "message too small\n");
+               dev_err(dev, "short message received\n");
                return;
        }
 
@@ -909,9 +920,10 @@ void gb_connection_recv(struct gb_connection *connection,
        memcpy(&header, data, sizeof(header));
        msg_size = le16_to_cpu(header.size);
        if (size < msg_size) {
-               dev_err(&connection->dev,
-                       "incomplete message received: 0x%04x (%zu < %zu)\n",
-                       le16_to_cpu(header.operation_id), size, msg_size);
+               dev_err(dev,
+                       "incomplete message 0x%04hx of type 0x%02hhx received (%zu < %zu)\n",
+                       le16_to_cpu(header.operation_id), header.type, size,
+                       msg_size);
                return;         /* XXX Should still complete operation */
        }
 
@@ -935,8 +947,9 @@ void gb_operation_cancel(struct gb_operation *operation, int errno)
 
        if (gb_operation_result_set(operation, errno)) {
                gb_message_cancel(operation->request);
-               queue_work(gb_operation_workqueue, &operation->work);
+               queue_work(gb_operation_completion_wq, &operation->work);
        }
+       trace_gb_message_cancel_outgoing(operation->request);
 
        atomic_inc(&operation->waiters);
        wait_event(gb_operation_cancellation_queue,
@@ -963,6 +976,7 @@ void gb_operation_cancel_incoming(struct gb_operation *operation, int errno)
                if (!gb_operation_result_set(operation, errno))
                        gb_message_cancel(operation->response);
        }
+       trace_gb_message_cancel_incoming(operation->response);
 
        atomic_inc(&operation->waiters);
        wait_event(gb_operation_cancellation_queue,
@@ -978,6 +992,7 @@ void gb_operation_cancel_incoming(struct gb_operation *operation, int errno)
  * @request_size: size of @request
  * @response: pointer to a memory buffer to copy the response to
  * @response_size: the size of @response.
+ * @timeout: operation timeout in milliseconds
  *
  * This function implements a simple synchronous Greybus operation.  It sends
  * the provided operation request and waits (sleeps) until the corresponding
@@ -992,9 +1007,10 @@ void gb_operation_cancel_incoming(struct gb_operation *operation, int errno)
  *
  * If there is an error, the response buffer is left alone.
  */
-int gb_operation_sync(struct gb_connection *connection, int type,
-                     void *request, int request_size,
-                     void *response, int response_size)
+int gb_operation_sync_timeout(struct gb_connection *connection, int type,
+                               void *request, int request_size,
+                               void *response, int response_size,
+                               unsigned int timeout)
 {
        struct gb_operation *operation;
        int ret;
@@ -1012,21 +1028,23 @@ int gb_operation_sync(struct gb_connection *connection, int type,
        if (request_size)
                memcpy(operation->request->payload, request, request_size);
 
-       ret = gb_operation_request_send_sync(operation);
+       ret = gb_operation_request_send_sync_timeout(operation, timeout);
        if (ret) {
-               dev_err(&connection->dev, "synchronous operation failed: %d\n",
-                       ret);
+               dev_err(&connection->bundle->dev,
+                       "synchronous operation of type 0x%02hhx failed: %d\n",
+                       type, ret);
        } else {
                if (response_size) {
                        memcpy(response, operation->response->payload,
                               response_size);
                }
        }
-       gb_operation_destroy(operation);
+
+       gb_operation_put(operation);
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(gb_operation_sync);
+EXPORT_SYMBOL_GPL(gb_operation_sync_timeout);
 
 int __init gb_operation_init(void)
 {
@@ -1040,12 +1058,14 @@ int __init gb_operation_init(void)
        if (!gb_operation_cache)
                goto err_destroy_message_cache;
 
-       gb_operation_workqueue = alloc_workqueue("greybus_operation", 0, 1);
-       if (!gb_operation_workqueue)
-               goto err_operation;
+       gb_operation_completion_wq = alloc_workqueue("greybus_completion",
+                               0, 0);
+       if (!gb_operation_completion_wq)
+               goto err_destroy_operation_cache;
 
        return 0;
-err_operation:
+
+err_destroy_operation_cache:
        kmem_cache_destroy(gb_operation_cache);
        gb_operation_cache = NULL;
 err_destroy_message_cache:
@@ -1057,8 +1077,8 @@ err_destroy_message_cache:
 
 void gb_operation_exit(void)
 {
-       destroy_workqueue(gb_operation_workqueue);
-       gb_operation_workqueue = NULL;
+       destroy_workqueue(gb_operation_completion_wq);
+       gb_operation_completion_wq = NULL;
        kmem_cache_destroy(gb_operation_cache);
        gb_operation_cache = NULL;
        kmem_cache_destroy(gb_message_cache);