diff --git a/common/state/backend.c b/common/state/backend.c index 2f2e6df..5235bb0 100644 --- a/common/state/backend.c +++ b/common/state/backend.c @@ -164,7 +164,7 @@ if (ret) goto out_free_format; - backend->of_path = of_path; + backend->of_path = xstrdup(of_path); return 0; @@ -185,4 +185,5 @@ state_storage_free(&backend->storage); if (backend->format) state_format_free(backend->format); + free(backend->of_path); } diff --git a/common/state/state.c b/common/state/state.c index 9b1d4ed..075618e 100644 --- a/common/state/state.c +++ b/common/state/state.c @@ -202,15 +202,19 @@ enum state_convert conv) { struct device_node *child; - struct device_node *root; + struct device_node *root, *state_root; int ret; - root = of_new_node(parent, state->root->name); + state_root = of_find_node_by_path(state->of_path); + if (!state_root) + return ERR_PTR(-ENODEV); + + root = of_new_node(parent, state_root->name); ret = of_property_write_u32(root, "magic", state->magic); if (ret) goto out; - for_each_child_of_node(state->root, child) { + for_each_child_of_node(state_root, child) { ret = state_convert_node_variable(state, child, root, "", conv); if (ret) goto out; @@ -234,7 +238,7 @@ if (create) { conv = STATE_CONVERT_FROM_NODE_CREATE; - state->root = node; + state->of_path = xstrdup(node->full_name); state->magic = magic; } else { conv = STATE_CONVERT_FROM_NODE; @@ -291,7 +295,7 @@ int ret; phandle phandle; - node = of_find_node_by_path_from(root, state->root->full_name); + node = of_find_node_by_path_from(root, state->of_path); if (node) { /* replace existing node - it will be deleted later */ parent = node->parent; @@ -299,12 +303,12 @@ char *of_path, *c; /* look for parent, remove last '/' from path */ - of_path = xstrdup(state->root->full_name); + of_path = xstrdup(state->of_path); c = strrchr(of_path, '/'); if (!c) return -ENODEV; - *c = '0'; - parent = of_find_node_by_path(of_path); + *c = '\0'; + parent = of_find_node_by_path_from(root, of_path); if (!parent) parent = root; @@ -406,6 +410,7 @@ list_del(&state->list); unregister_device(&state->dev); state_backend_free(&state->backend); + free(state->of_path); free(state); } @@ -545,7 +550,7 @@ struct state *state; list_for_each_entry(state, &state_list, list) { - if (state->root == node) + if (!strcmp(state->of_path, node->full_name)) return state; } diff --git a/common/state/state.h b/common/state/state.h index 32146ca..bc6917d 100644 --- a/common/state/state.h +++ b/common/state/state.h @@ -87,14 +87,14 @@ struct state_backend { struct state_backend_format *format; struct state_backend_storage storage; - const char *of_path; + char *of_path; }; struct state { struct list_head list; /* Entry to enqueue on list of states */ struct device_d dev; - struct device_node *root; + char *of_path; const char *name; uint32_t magic; @@ -138,6 +138,7 @@ /* instance of a single variable */ struct state_variable { + struct state *state; enum state_variable_type type; struct list_head list; const char *name; @@ -152,7 +153,6 @@ struct state_uint32 { struct state_variable var; struct param_d *param; - struct state *state; uint32_t value; uint32_t value_default; }; @@ -185,13 +185,11 @@ struct state_string { struct state_variable var; struct param_d *param; - struct state *state; char *value; const char *value_default; char raw[]; }; -int state_set_dirty(struct param_d *p, void *priv); int state_from_node(struct state *state, struct device_node *node, bool create); struct device_node *state_to_node(struct state *state, struct device_node *parent, diff --git a/common/state/state_variables.c b/common/state/state_variables.c index 0d2a626..efc2456 100644 --- a/common/state/state_variables.c +++ b/common/state/state_variables.c @@ -34,11 +34,11 @@ * @param priv * @return */ -int state_set_dirty(struct param_d *p, void *priv) +static int state_set_dirty(struct param_d *p, void *priv) { - struct state *state = priv; + struct state_variable *sv = priv; - state->dirty = 1; + sv->state->dirty = 1; return 0; } @@ -90,13 +90,13 @@ static int state_uint8_set(struct param_d *p, void *priv) { - struct state_uint32 *su32 = priv; - struct state *state = su32->state; + struct state_variable *sv = priv; + struct state_uint32 *su32 = to_state_uint32(sv); if (su32->value > 255) return -ERANGE; - return state_set_dirty(p, state); + return state_set_dirty(p, sv); } static struct state_variable *state_uint8_create(struct state *state, @@ -109,7 +109,7 @@ su32 = xzalloc(sizeof(*su32)); param = dev_add_param_int(&state->dev, name, state_uint8_set, - NULL, &su32->value, "%u", su32); + NULL, &su32->value, "%u", &su32->var); if (IS_ERR(param)) { free(su32); return ERR_CAST(param); @@ -122,7 +122,7 @@ #else su32->var.raw = &su32->value + 3; #endif - su32->state = state; + su32->var.state = state; return &su32->var; } @@ -137,7 +137,7 @@ su32 = xzalloc(sizeof(*su32)); param = dev_add_param_int(&state->dev, name, state_set_dirty, - NULL, &su32->value, "%u", state); + NULL, &su32->value, "%u", &su32->var); if (IS_ERR(param)) { free(su32); return ERR_CAST(param); @@ -146,6 +146,7 @@ su32->param = param; su32->var.size = sizeof(uint32_t); su32->var.raw = &su32->value; + su32->var.state = state; return &su32->var; } @@ -235,6 +236,7 @@ enum32->num_names = num_names; enum32->var.size = sizeof(uint32_t); enum32->var.raw = &enum32->value; + enum32->var.state = state; for (i = 0; i < num_names; i++) { const char *name; @@ -247,7 +249,7 @@ enum32->param = dev_add_param_enum(&state->dev, name, state_set_dirty, NULL, &enum32->value, enum32->names, - num_names, state); + num_names, &enum32->var); if (IS_ERR(enum32->param)) { ret = PTR_ERR(enum32->param); goto out; @@ -307,9 +309,10 @@ mac->var.size = ARRAY_SIZE(mac->value); mac->var.raw = mac->value; + mac->var.state = state; mac->param = dev_add_param_mac(&state->dev, name, state_set_dirty, - NULL, mac->value, state); + NULL, mac->value, &mac->var); if (IS_ERR(mac->param)) { ret = PTR_ERR(mac->param); goto out; @@ -372,20 +375,21 @@ static int state_string_set(struct param_d *p, void *priv) { - struct state_string *string = priv; - struct state *state = string->state; + struct state_variable *sv = priv; + struct state_string *string = to_state_string(sv); int ret; ret = state_string_copy_to_raw(string, string->value); if (ret) return ret; - return state_set_dirty(p, state); + return state_set_dirty(p, sv->state); } static int state_string_get(struct param_d *p, void *priv) { - struct state_string *string = priv; + struct state_variable *sv = priv; + struct state_string *string = to_state_string(sv); free(string->value); if (string->raw[0]) @@ -418,11 +422,11 @@ string = xzalloc(sizeof(*string) + start_size[1]); string->var.size = start_size[1]; string->var.raw = &string->raw; - string->state = state; + string->var.state = state; string->param = dev_add_param_string(&state->dev, name, state_string_set, state_string_get, - &string->value, string); + &string->value, &string->var); if (IS_ERR(string->param)) { ret = PTR_ERR(string->param); goto out;