]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
greybus: update gbuf status for completion handlers
authorAlex Elder <elder@linaro.org>
Fri, 17 Oct 2014 10:18:22 +0000 (05:18 -0500)
committerGreg Kroah-Hartman <greg@kroah.com>
Fri, 17 Oct 2014 16:15:25 +0000 (18:15 +0200)
Currently, if a USB urb completes with an error, that error status
is not transferred back to the gbuf that it's associated with.  For
inbound data there's not a lot we can do about an error, but for
outbound data, this means there is no notification to the submitter
that something went wrong.

For outbound data copy the urb status directly back to the gbuf as
its status.  Follow USB's lead and set the status to -EINPROGRESS
while a gbuf is "in flight."  Assign a gbuf an initial status value
of -EBADR to help identify use of never-set status values.

When an inbound urb fails (SVC or CPort), currently the urb is just
leaked, more or less (i.e., we lose an urb posted to receive
incoming data).  Change that so such an error is reported, but
then re-submitted.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
drivers/staging/greybus/es1-ap-usb.c
drivers/staging/greybus/gbuf.c
drivers/staging/greybus/operation.c

index 5acf5a75e44bdaf7a22ff5958447a1732ee6ec94..21fe4fdd4103e2e066b1467282f227b9d9a58e57 100644 (file)
@@ -274,10 +274,11 @@ static void svc_in_callback(struct urb *urb)
        int status = check_urb_status(urb);
        int retval;
 
-       if (status == -EAGAIN)
+       if (status) {
+               if (status != -EAGAIN)
+                       dev_err(dev, "urb svc in error %d (dropped)\n", status);
                goto exit;
-       if (status)
-               return;
+       }
 
        /* We have a message, create a new message structure, add it to the
         * list, and wake up our thread that will process the messages.
@@ -300,10 +301,12 @@ static void cport_in_callback(struct urb *urb)
        u8 cport;
        u8 *data;
 
-       if (status == -EAGAIN)
+       if (status) {
+               if (status != -EAGAIN)
+                       dev_err(dev, "urb cport in error %d (dropped)\n",
+                               status);
                goto exit;
-       if (status)
-               return;
+       }
 
        /* The size has to be at least one, for the cport id */
        if (!urb->actual_length) {
@@ -337,6 +340,9 @@ static void cport_out_callback(struct urb *urb)
        unsigned long flags;
        int i;
 
+       /* Record whether the transfer was successful */
+       gbuf->status = check_urb_status(urb);
+
        /*
         * See if this was an urb in our pool, if so mark it "free", otherwise
         * we need to free it ourselves.
index 348ee7c27a07e416391327230f4828c2001b49d2..9b435af27cca297e0ce046b8af43ba02f098d84e 100644 (file)
@@ -54,6 +54,7 @@ struct gbuf *greybus_alloc_gbuf(struct gb_connection *connection,
        gbuf->outbound = outbound;
        gbuf->complete = complete;
        gbuf->context = context;
+       gbuf->status = -EBADR;  /* Initial value--means "never set" */
 
        /* Host controller specific allocation for the actual buffer */
        retval = connection->hd->driver->alloc_gbuf_data(gbuf, size, gfp_mask);
@@ -98,6 +99,8 @@ int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask)
 {
        struct greybus_host_device *hd = gbuf->connection->hd;
 
+       gbuf->status = -EINPROGRESS;
+
        return hd->driver->submit_gbuf(gbuf, gfp_mask);
 }
 
index a49d92957c6b1c28012829b08bb1f016cd64000a..4d19eec790f0251c7b8a64f255cd823b71d0fb05 100644 (file)
@@ -424,6 +424,7 @@ void gb_connection_operation_recv(struct gb_connection *connection,
                }
                gb_operation_remove(operation);
                gbuf = operation->response;
+               gbuf->status = GB_OP_SUCCESS;   /* If we got here we're good */
                if (size > gbuf->transfer_buffer_length) {
                        gb_connection_err(connection, "recv buffer too small");
                        return;