greybus: interface: read DME attributes at activation
authorJohan Hovold <johan@hovoldconsulting.com>
Tue, 29 Mar 2016 22:56:08 +0000 (18:56 -0400)
committerGreg Kroah-Hartman <gregkh@google.com>
Wed, 30 Mar 2016 21:23:19 +0000 (14:23 -0700)
Read the DDBL1 and Ara DME attributes when activating an interface.

These values are currently provided by the SVC in the intf_hotplug
request, which is about to go away.

Note that there are currently no standard Ara VID and PID attributes and
that Toshiba uses attributes from the reserved space in ES3. For now, we
therefore refuse to enumerate any non-Toshiba bridges.

Also note that the Ara serial number is currently not supported.

Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/interface.c
drivers/staging/greybus/interface.h
drivers/staging/greybus/svc.c

index 823debb..c7793a9 100644 (file)
 
 #define GB_INTERFACE_DEVICE_ID_BAD     0xff
 
+/* DME attributes */
+#define DME_DDBL1_MANUFACTURERID       0x5003
+#define DME_DDBL1_PRODUCTID            0x5004
+
+#define DME_TOSHIBA_ARA_VID            0x6000
+#define DME_TOSHIBA_ARA_PID            0x6001
+
+/* DDBL1 Manufacturer and Product ids */
+#define TOSHIBA_DMID                   0x0126
+#define TOSHIBA_ES2_BRIDGE_DPID                0x1000
+#define TOSHIBA_ES3_APBRIDGE_DPID      0x1001
+#define TOSHIBA_ES3_GPBRIDGE_DPID      0x1002
+
+
+static int gb_interface_dme_attr_get(struct gb_interface *intf,
+                                                       u16 attr, u32 *val)
+{
+       return gb_svc_dme_peer_get(intf->hd->svc, intf->interface_id,
+                                       attr, DME_ATTR_SELECTOR_INDEX_NULL,
+                                       val);
+}
+
+static int gb_interface_read_ara_dme(struct gb_interface *intf)
+{
+       int ret;
+
+       /*
+        * Unless this is a Toshiba bridge, bail out until we have defined
+        * standard Ara attributes.
+        */
+       if (intf->ddbl1_manufacturer_id != TOSHIBA_DMID) {
+               dev_err(&intf->dev, "unknown manufacturer %08x\n",
+                               intf->ddbl1_manufacturer_id);
+               return -ENODEV;
+       }
+
+       ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_ARA_VID,
+                                       &intf->vendor_id);
+       if (ret)
+               return ret;
+
+       ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_ARA_PID,
+                                       &intf->product_id);
+       if (ret)
+               return ret;
+
+       /* FIXME: serial number not implemented */
+       intf->serial_number = 0;
+
+       return 0;
+}
+
+static int gb_interface_read_dme(struct gb_interface *intf)
+{
+       int ret;
+
+       ret = gb_interface_dme_attr_get(intf, DME_DDBL1_MANUFACTURERID,
+                                       &intf->ddbl1_manufacturer_id);
+       if (ret)
+               return ret;
+
+       ret = gb_interface_dme_attr_get(intf, DME_DDBL1_PRODUCTID,
+                                       &intf->ddbl1_product_id);
+       if (ret)
+               return ret;
+
+       return gb_interface_read_ara_dme(intf);
+}
 
 static int gb_interface_route_create(struct gb_interface *intf)
 {
@@ -279,6 +347,10 @@ int gb_interface_activate(struct gb_interface *intf)
 {
        int ret;
 
+       ret = gb_interface_read_dme(intf);
+       if (ret)
+               return ret;
+
        ret = gb_interface_route_create(intf);
        if (ret)
                return ret;
index 8b6fcfe..1a6ce5c 100644 (file)
@@ -27,7 +27,6 @@ struct gb_interface {
        char *vendor_string;
        char *product_string;
 
-       /* Information taken from the hotplug event */
        u32 ddbl1_manufacturer_id;
        u32 ddbl1_product_id;
        u32 vendor_id;
index 96d3d55..0659815 100644 (file)
@@ -460,11 +460,12 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation)
                return;
        }
 
-       intf->ddbl1_manufacturer_id = le32_to_cpu(request->data.ddbl1_mfr_id);
-       intf->ddbl1_product_id = le32_to_cpu(request->data.ddbl1_prod_id);
-       intf->vendor_id = le32_to_cpu(request->data.ara_vend_id);
-       intf->product_id = le32_to_cpu(request->data.ara_prod_id);
-       intf->serial_number = le64_to_cpu(request->data.serial_number);
+       ret = gb_interface_activate(intf);
+       if (ret) {
+               dev_err(&svc->dev, "failed to activate interface %u: %d\n",
+                               intf_id, ret);
+               goto err_interface_add;
+       }
 
        /*
         * Use VID/PID specified at hotplug if:
@@ -480,13 +481,6 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation)
                intf->product_id = product_id;
        }
 
-       ret = gb_interface_activate(intf);
-       if (ret) {
-               dev_err(&svc->dev, "failed to activate interface %u: %d\n",
-                               intf_id, ret);
-               goto err_interface_add;
-       }
-
        ret = gb_interface_enable(intf);
        if (ret) {
                dev_err(&svc->dev, "failed to enable interface %u: %d\n",