greybus: es2: add support for CDSI1 allocation
authorJohan Hovold <johan@hovoldconsulting.com>
Wed, 11 May 2016 08:18:04 +0000 (10:18 +0200)
committerGreg Kroah-Hartman <gregkh@google.com>
Fri, 13 May 2016 13:32:48 +0000 (15:32 +0200)
Use the new CPort-allocation callbacks to allow for rudimentary resource
management of the CDSI CPorts.

How to manage offloaded resources in a generic fashion is yet to be
determined, but this minimal implementation will allow core to manage
the camera data connection so that the current camera-driver hacks can
be removed. This is specifically required to be able to implement proper
connection closing and for power management.

Note that the CDSI CPorts can not (currently) be reset through the
USB vendor request.

Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/connection.h
drivers/staging/greybus/es2.c

index a8da9ca..b152e23 100644 (file)
@@ -16,6 +16,7 @@
 #define GB_CONNECTION_FLAG_CSD         BIT(0)
 #define GB_CONNECTION_FLAG_NO_FLOWCTRL BIT(1)
 #define GB_CONNECTION_FLAG_OFFLOADED   BIT(2)
+#define GB_CONNECTION_FLAG_CDSI1       BIT(3)
 
 enum gb_connection_state {
        GB_CONNECTION_STATE_INVALID     = 0,
index f06a322..998b41e 100644 (file)
@@ -99,6 +99,8 @@ struct es2_ap_dev {
        bool cport_out_urb_cancelled[NUM_CPORT_OUT_URB];
        spinlock_t cport_out_urb_lock;
 
+       bool cdsi1_in_use;
+
        int *cport_to_ep;
 
        struct task_struct *apb_log_task;
@@ -508,6 +510,8 @@ static int cport_reset(struct gb_host_device *hd, u16 cport_id)
 
        switch (cport_id) {
        case GB_SVC_CPORT_ID:
+       case ES2_CPORT_CDSI0:
+       case ES2_CPORT_CDSI1:
                return 0;
        }
 
@@ -525,6 +529,59 @@ static int cport_reset(struct gb_host_device *hd, u16 cport_id)
        return 0;
 }
 
+static int es2_cport_allocate(struct gb_host_device *hd, int cport_id,
+                               unsigned long flags)
+{
+       struct es2_ap_dev *es2 = hd_to_es2(hd);
+       struct ida *id_map = &hd->cport_id_map;
+       int ida_start, ida_end;
+
+       switch (cport_id) {
+       case ES2_CPORT_CDSI0:
+       case ES2_CPORT_CDSI1:
+               dev_err(&hd->dev, "cport %d not available\n", cport_id);
+               return -EBUSY;
+       }
+
+       if (flags & GB_CONNECTION_FLAG_OFFLOADED &&
+                       flags & GB_CONNECTION_FLAG_CDSI1) {
+               if (es2->cdsi1_in_use) {
+                       dev_err(&hd->dev, "CDSI1 already in use\n");
+                       return -EBUSY;
+               }
+
+               es2->cdsi1_in_use = true;
+
+               return ES2_CPORT_CDSI1;
+       }
+
+       if (cport_id < 0) {
+               ida_start = 0;
+               ida_end = hd->num_cports;
+       } else if (cport_id < hd->num_cports) {
+               ida_start = cport_id;
+               ida_end = cport_id + 1;
+       } else {
+               dev_err(&hd->dev, "cport %d not available\n", cport_id);
+               return -EINVAL;
+       }
+
+       return ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL);
+}
+
+static void es2_cport_release(struct gb_host_device *hd, u16 cport_id)
+{
+       struct es2_ap_dev *es2 = hd_to_es2(hd);
+
+       switch (cport_id) {
+       case ES2_CPORT_CDSI1:
+               es2->cdsi1_in_use = false;
+               return;
+       }
+
+       ida_simple_remove(&hd->cport_id_map, cport_id);
+}
+
 static int cport_enable(struct gb_host_device *hd, u16 cport_id)
 {
        int retval;
@@ -621,6 +678,8 @@ static struct gb_hd_driver es2_driver = {
        .hd_priv_size           = sizeof(struct es2_ap_dev),
        .message_send           = message_send,
        .message_cancel         = message_cancel,
+       .cport_allocate         = es2_cport_allocate,
+       .cport_release          = es2_cport_release,
        .cport_enable           = cport_enable,
        .latency_tag_enable     = latency_tag_enable,
        .latency_tag_disable    = latency_tag_disable,