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 823debb402726bb43cf150f5a7af0b5875c3815e..c7793a93c8027d0d2a8f9154ca6770e6b6a01e6b 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 8b6fcfe90883353a90f582af6e7839576a277b32..1a6ce5ce6e6c95179664957f74ba4da294ac4bba 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 96d3d55f54ed3c47ea8586d1debc9176e23e9d14..0659815248f926a01779156c8c9a1ac6ecfdc940 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",