From: Greg Kroah-Hartman <greg@kroah.com>
Date: Mon, 27 Oct 2014 05:31:01 +0000 (+0800)
Subject: greybus: gbuf: implement gbuf_kill_gbuf()
X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=d81448849a6a919bdc6366b44a7664f817c94d84;p=linux.git

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 <greg@kroah.com>
Reviewed-by: Alex Elder <elder@linaro.org>
---

diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c
index bd416b4849bd6..a2072944325df 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 9b435af27cca2..726a1f4bac41d 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 f287f3b0a3e55..8b6ea0544598d 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 {