diff options
-rw-r--r-- | drivers/w1/w1_netlink.c | 56 | ||||
-rw-r--r-- | drivers/w1/w1_netlink.h | 1 |
2 files changed, 57 insertions, 0 deletions
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c index 65c5ebd0787e..2e07b59b9859 100644 --- a/drivers/w1/w1_netlink.c +++ b/drivers/w1/w1_netlink.c | |||
@@ -128,6 +128,59 @@ static int w1_process_command_slave(struct w1_slave *sl, struct cn_msg *msg, | |||
128 | return err; | 128 | return err; |
129 | } | 129 | } |
130 | 130 | ||
131 | static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mcmd) | ||
132 | { | ||
133 | struct w1_master *m; | ||
134 | struct cn_msg *cn; | ||
135 | struct w1_netlink_msg *w; | ||
136 | u32 *id; | ||
137 | |||
138 | if (mcmd->type != W1_LIST_MASTERS) { | ||
139 | printk(KERN_NOTICE "%s: msg: %x.%x, wrong type: %u, len: %u.\n", | ||
140 | __func__, msg->id.idx, msg->id.val, mcmd->type, mcmd->len); | ||
141 | return -EPROTO; | ||
142 | } | ||
143 | |||
144 | cn = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
145 | if (!cn) | ||
146 | return -ENOMEM; | ||
147 | |||
148 | cn->id.idx = CN_W1_IDX; | ||
149 | cn->id.val = CN_W1_VAL; | ||
150 | |||
151 | cn->seq = msg->seq; | ||
152 | cn->ack = 1; | ||
153 | cn->len = sizeof(struct w1_netlink_msg); | ||
154 | w = (struct w1_netlink_msg *)(cn + 1); | ||
155 | |||
156 | w->type = W1_LIST_MASTERS; | ||
157 | w->reserved = 0; | ||
158 | w->len = 0; | ||
159 | id = (u32 *)(w + 1); | ||
160 | |||
161 | mutex_lock(&w1_mlock); | ||
162 | list_for_each_entry(m, &w1_masters, w1_master_entry) { | ||
163 | if (cn->len + sizeof(*id) > PAGE_SIZE - sizeof(struct cn_msg)) { | ||
164 | cn_netlink_send(cn, 0, GFP_KERNEL); | ||
165 | cn->ack++; | ||
166 | cn->len = sizeof(struct w1_netlink_msg); | ||
167 | w->len = 0; | ||
168 | id = (u32 *)(w + 1); | ||
169 | } | ||
170 | |||
171 | *id = m->id; | ||
172 | w->len += sizeof(*id); | ||
173 | cn->len += sizeof(*id); | ||
174 | id++; | ||
175 | } | ||
176 | cn->ack = 0; | ||
177 | cn_netlink_send(cn, 0, GFP_KERNEL); | ||
178 | mutex_unlock(&w1_mlock); | ||
179 | |||
180 | kfree(cn); | ||
181 | return 0; | ||
182 | } | ||
183 | |||
131 | static void w1_cn_callback(void *data) | 184 | static void w1_cn_callback(void *data) |
132 | { | 185 | { |
133 | struct cn_msg *msg = data; | 186 | struct cn_msg *msg = data; |
@@ -164,6 +217,9 @@ static void w1_cn_callback(void *data) | |||
164 | sl = w1_search_slave(&id); | 217 | sl = w1_search_slave(&id); |
165 | if (sl) | 218 | if (sl) |
166 | dev = sl->master; | 219 | dev = sl->master; |
220 | } else { | ||
221 | err = w1_process_command_root(msg, m); | ||
222 | goto out_cont; | ||
167 | } | 223 | } |
168 | 224 | ||
169 | if (!dev) { | 225 | if (!dev) { |
diff --git a/drivers/w1/w1_netlink.h b/drivers/w1/w1_netlink.h index 56122b9e9294..21913dfc0f3a 100644 --- a/drivers/w1/w1_netlink.h +++ b/drivers/w1/w1_netlink.h | |||
@@ -34,6 +34,7 @@ enum w1_netlink_message_types { | |||
34 | W1_MASTER_REMOVE, | 34 | W1_MASTER_REMOVE, |
35 | W1_MASTER_CMD, | 35 | W1_MASTER_CMD, |
36 | W1_SLAVE_CMD, | 36 | W1_SLAVE_CMD, |
37 | W1_LIST_MASTERS, | ||
37 | }; | 38 | }; |
38 | 39 | ||
39 | struct w1_netlink_msg | 40 | struct w1_netlink_msg |