summaryrefslogtreecommitdiffstats
path: root/drivers/w1/w1_netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/w1/w1_netlink.c')
-rw-r--r--drivers/w1/w1_netlink.c56
1 files changed, 56 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,
return err;
}
+static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mcmd)
+{
+ struct w1_master *m;
+ struct cn_msg *cn;
+ struct w1_netlink_msg *w;
+ u32 *id;
+
+ if (mcmd->type != W1_LIST_MASTERS) {
+ printk(KERN_NOTICE "%s: msg: %x.%x, wrong type: %u, len: %u.\n",
+ __func__, msg->id.idx, msg->id.val, mcmd->type, mcmd->len);
+ return -EPROTO;
+ }
+
+ cn = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!cn)
+ return -ENOMEM;
+
+ cn->id.idx = CN_W1_IDX;
+ cn->id.val = CN_W1_VAL;
+
+ cn->seq = msg->seq;
+ cn->ack = 1;
+ cn->len = sizeof(struct w1_netlink_msg);
+ w = (struct w1_netlink_msg *)(cn + 1);
+
+ w->type = W1_LIST_MASTERS;
+ w->reserved = 0;
+ w->len = 0;
+ id = (u32 *)(w + 1);
+
+ mutex_lock(&w1_mlock);
+ list_for_each_entry(m, &w1_masters, w1_master_entry) {
+ if (cn->len + sizeof(*id) > PAGE_SIZE - sizeof(struct cn_msg)) {
+ cn_netlink_send(cn, 0, GFP_KERNEL);
+ cn->ack++;
+ cn->len = sizeof(struct w1_netlink_msg);
+ w->len = 0;
+ id = (u32 *)(w + 1);
+ }
+
+ *id = m->id;
+ w->len += sizeof(*id);
+ cn->len += sizeof(*id);
+ id++;
+ }
+ cn->ack = 0;
+ cn_netlink_send(cn, 0, GFP_KERNEL);
+ mutex_unlock(&w1_mlock);
+
+ kfree(cn);
+ return 0;
+}
+
static void w1_cn_callback(void *data)
{
struct cn_msg *msg = data;
@@ -164,6 +217,9 @@ static void w1_cn_callback(void *data)
sl = w1_search_slave(&id);
if (sl)
dev = sl->master;
+ } else {
+ err = w1_process_command_root(msg, m);
+ goto out_cont;
}
if (!dev) {