From d81448849a6a919bdc6366b44a7664f817c94d84 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 27 Oct 2014 13:31:01 +0800 Subject: [PATCH] greybus: gbuf: implement gbuf_kill_gbuf() Hook up gbuf_kill_gbuf() by implementing yet-another-host-controller callback and a gbuf-specific pointer to hold the tracking data the hcd needs in order to be able to abort a transfer. Signed-off-by: Greg Kroah-Hartman Reviewed-by: Alex Elder --- drivers/staging/greybus/es1-ap-usb.c | 15 +++++++++++++++ drivers/staging/greybus/gbuf.c | 8 ++++++-- drivers/staging/greybus/greybus.h | 2 ++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c index bd416b4849bd..a2072944325d 100644 --- a/drivers/staging/greybus/es1-ap-usb.c +++ b/drivers/staging/greybus/es1-ap-usb.c @@ -224,6 +224,8 @@ static int submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) if (!urb) return -ENOMEM; + gbuf->hcd_data = urb; + usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, es1->cport_out_endpoint), buffer, gbuf->transfer_buffer_length + 1, @@ -232,12 +234,24 @@ static int submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) return retval; } +static int abort_gbuf(struct gbuf *gbuf) +{ + struct urb *urb = gbuf->hcd_data; + + if (!urb) + return -EINVAL; + + usb_kill_urb(urb); + return 0; +} + static struct greybus_host_driver es1_driver = { .hd_priv_size = sizeof(struct es1_ap_dev), .alloc_gbuf_data = alloc_gbuf_data, .free_gbuf_data = free_gbuf_data, .submit_svc = submit_svc, .submit_gbuf = submit_gbuf, + .abort_gbuf = abort_gbuf, }; /* Common function to report consistent warnings based on URB status */ @@ -387,6 +401,7 @@ static void cport_out_callback(struct urb *urb) /* Record whether the transfer was successful */ gbuf->status = check_urb_status(urb); + gbuf->hcd_data = NULL; /* * See if this was an urb in our pool, if so mark it "free", otherwise diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index 9b435af27cca..726a1f4bac41 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -106,8 +106,12 @@ int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t gfp_mask) int greybus_kill_gbuf(struct gbuf *gbuf) { - // FIXME - implement - return -ENOMEM; + struct greybus_host_device *hd = gbuf->connection->hd; + + if (gbuf->status != -EINPROGRESS) + return -EINVAL; + + return hd->driver->abort_gbuf(gbuf); } #define MAX_CPORTS 1024 diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index f287f3b0a3e5..8b6ea0544598 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -134,6 +134,7 @@ struct gbuf { bool outbound; /* AP-relative data direction */ void *context; + void *hcd_data; /* for the HCD to track the gbuf */ gbuf_complete_t complete; }; @@ -169,6 +170,7 @@ struct greybus_host_driver { int (*submit_svc)(struct svc_msg *svc_msg, struct greybus_host_device *hd); int (*submit_gbuf)(struct gbuf *gbuf, gfp_t gfp_mask); + int (*abort_gbuf)(struct gbuf *gbuf); }; struct greybus_host_device { -- 2.20.1