]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
plugin-manager: Add support for partial and GE match
authorLaxman Dewangan <ldewangan@nvidia.com>
Sun, 3 Apr 2016 14:22:38 +0000 (19:52 +0530)
committerWinnie Hsu <whsu@nvidia.com>
Thu, 21 Apr 2016 20:12:00 +0000 (13:12 -0700)
Currently the matching of board ID on board is done with exact
match. Add support for partial and >=fab ID support.

Partial match:
==============
 If matching string start with '^' or having the '*' in id string
 then apply partial match with board ID based on how string provided.
  Example: Suppose Board ID is 3310-1000-100, then the matching is
  done by saying ^3310-1000, 3310-1000-*, 3310-* etc.
  ^3310-1000 or 3310-1000-* means all fab ID of 3310-1000-,
  3310-* means all SKU and fab ID of 3310.

Greater than-equal to match:
===========================
  If matching string start with ">=" then it is applied for all board
  of same type of module having fab ID >= sting fab ID.
  Example: ">=3310-1000-100" means all fab 3310-1000-100 and later like
  3310-1000-200, 3310-1000-300 etc.

bug 1750159

Change-Id: I1223d7c8add653cd54505e0d98693f72a5c3c824
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: http://git-master/r/1119438
(cherry picked from commit d3a7f2399b1617a61f7cf2d5abb159ecf6fbf44d from dev-kernel-3.18 in linux-3.18)
Reviewed-on: http://git-master/r/1120768
(cherry picked from commit b0cb5e66ed570cf06ee3560fcf616930ba61cbf9)
Reviewed-on: http://git-master/r/1128341
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Tested-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-by: Winnie Hsu <whsu@nvidia.com>
drivers/of/plugin-manager.c

index 440031f5947d5bbafb458e1b40c216350999acb3..2017aeb994663f2e315cb6c337e8f12564fe6e65 100644 (file)
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 
+enum plugin_manager_match_type {
+       PLUGIN_MANAGER_MATCH_EXACT,
+       PLUGIN_MANAGER_MATCH_PARTIAL,
+       PLUGIN_MANAGER_MATCH_GE,
+};
+
 static struct property *__of_copy_property(const struct property *prop,
                gfp_t flags)
 {
@@ -106,6 +112,102 @@ static int __init update_target_node_from_overlay(
        return 0;
 }
 
+static int plugin_manager_get_fabid(const char *id_str)
+{
+       int fabid = 0;
+       int i;
+
+       if (strlen(id_str) < 13)
+               return -EINVAL;
+
+       for (i = 0; i < 3; ++i) {
+               if ((id_str[10 + i] >= '0') && (id_str[10 + i] <= '9'))
+                       fabid = fabid * 10 + id_str[10 + i] - '0';
+               else
+                       return -EINVAL;
+       }
+
+       return fabid;
+}
+
+static bool plugin_manager_match_id(struct device_node *np, const char *id_name)
+{
+       struct property *prop;
+       const char *in_str = id_name;
+       int match_type = PLUGIN_MANAGER_MATCH_EXACT;
+       int valid_str_len = strlen(id_name);
+       int fabid = 0, prop_fabid;
+       int i;
+
+       if ((valid_str_len > 2) && (in_str[0] == '>') && (in_str[1] == '=')) {
+               in_str += 2;
+               valid_str_len -= 2;
+               match_type = PLUGIN_MANAGER_MATCH_GE;
+               goto match_type_done;
+       }
+
+       if ((valid_str_len > 1) && (in_str[0] == '^')) {
+               in_str += 1;
+               valid_str_len -= 1;
+               match_type = PLUGIN_MANAGER_MATCH_PARTIAL;
+               goto match_type_done;
+       }
+
+       for (i = 0; i < valid_str_len; ++i) {
+               if (in_str[i] == '*') {
+                       valid_str_len = i;
+                       match_type = PLUGIN_MANAGER_MATCH_PARTIAL;
+                       break;
+               }
+       }
+
+match_type_done:
+       if (match_type == PLUGIN_MANAGER_MATCH_GE) {
+               fabid = plugin_manager_get_fabid(in_str);
+               if (fabid < 0)
+                       return false;
+       }
+
+       for_each_property_of_node(np, prop) {
+               /* Skip those we do not want to proceed */
+               if (!strcmp(prop->name, "name") ||
+                       !strcmp(prop->name, "phandle") ||
+                       !strcmp(prop->name, "linux,phandle"))
+                               continue;
+               switch (match_type) {
+               case PLUGIN_MANAGER_MATCH_EXACT:
+                       if (strlen(prop->name) != valid_str_len)
+                               break;
+                       if (!memcmp(in_str, prop->name, valid_str_len))
+                               return true;
+                       break;
+
+               case PLUGIN_MANAGER_MATCH_PARTIAL:
+                       if (strlen(prop->name) < valid_str_len)
+                               break;
+                       if (!memcmp(in_str, prop->name, valid_str_len))
+                               return true;
+                       break;
+
+               case PLUGIN_MANAGER_MATCH_GE:
+                       if (strlen(prop->name) < 13)
+                               break;
+                       if (memcmp(in_str, prop->name, 10))
+                               break;
+                       prop_fabid = plugin_manager_get_fabid(prop->name);
+                       if (prop_fabid < 0)
+                               break;
+                       if (prop_fabid >= fabid)
+                               return true;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return false;
+}
+
 static int __init update_target_node(struct device_node *target,
        struct device_node *overlay)
 {
@@ -172,7 +274,7 @@ static int __init parse_fragment(struct device_node *np)
 
        if ((board_count > 0) && board_np) {
                of_property_for_each_string(np, "ids", prop, bname) {
-                       found = of_property_read_bool(board_np, bname);
+                       found = plugin_manager_match_id(board_np, bname);
                        if (found) {
                                pr_info("node %s match with board %s\n",
                                        np->full_name, bname);