doc: SubmittingPatches: remove dead link, kerneltrap.org no longer works
[cascardo/linux.git] / drivers / w1 / w1_netlink.c
index 06d614a..5234964 100644 (file)
@@ -45,7 +45,7 @@ void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
 
        memcpy(w, msg, sizeof(struct w1_netlink_msg));
 
-       cn_netlink_send(m, 0, GFP_KERNEL);
+       cn_netlink_send(m, dev->portid, 0, GFP_KERNEL);
 }
 
 static void w1_send_slave(struct w1_master *dev, u64 rn)
@@ -60,7 +60,7 @@ static void w1_send_slave(struct w1_master *dev, u64 rn)
 
        if (avail < 8) {
                msg->ack++;
-               cn_netlink_send(msg, 0, GFP_KERNEL);
+               cn_netlink_send(msg, dev->portid, 0, GFP_KERNEL);
 
                msg->len = sizeof(struct w1_netlink_msg) +
                        sizeof(struct w1_netlink_cmd);
@@ -131,7 +131,7 @@ static int w1_get_slaves(struct w1_master *dev,
        }
 
        msg->ack = 0;
-       cn_netlink_send(msg, 0, GFP_KERNEL);
+       cn_netlink_send(msg, dev->portid, 0, GFP_KERNEL);
 
        dev->priv = NULL;
        dev->priv_size = 0;
@@ -142,7 +142,7 @@ static int w1_get_slaves(struct w1_master *dev,
 }
 
 static int w1_send_read_reply(struct cn_msg *msg, struct w1_netlink_msg *hdr,
-               struct w1_netlink_cmd *cmd)
+               struct w1_netlink_cmd *cmd, u32 portid)
 {
        void *data;
        struct w1_netlink_msg *h;
@@ -173,7 +173,7 @@ static int w1_send_read_reply(struct cn_msg *msg, struct w1_netlink_msg *hdr,
 
        memcpy(c->data, cmd->data, c->len);
 
-       err = cn_netlink_send(cm, 0, GFP_KERNEL);
+       err = cn_netlink_send(cm, portid, 0, GFP_KERNEL);
 
        kfree(data);
 
@@ -188,11 +188,11 @@ static int w1_process_command_io(struct w1_master *dev, struct cn_msg *msg,
        switch (cmd->cmd) {
        case W1_CMD_TOUCH:
                w1_touch_block(dev, cmd->data, cmd->len);
-               w1_send_read_reply(msg, hdr, cmd);
+               w1_send_read_reply(msg, hdr, cmd, dev->portid);
                break;
        case W1_CMD_READ:
                w1_read_block(dev, cmd->data, cmd->len);
-               w1_send_read_reply(msg, hdr, cmd);
+               w1_send_read_reply(msg, hdr, cmd, dev->portid);
                break;
        case W1_CMD_WRITE:
                w1_write_block(dev, cmd->data, cmd->len);
@@ -246,11 +246,16 @@ static int w1_process_command_master(struct w1_master *dev,
 {
        int err = -EINVAL;
 
+       /* drop bus_mutex for search (does it's own locking), and add/remove
+        * which doesn't use the bus
+        */
        switch (req_cmd->cmd) {
        case W1_CMD_SEARCH:
        case W1_CMD_ALARM_SEARCH:
        case W1_CMD_LIST_SLAVES:
+               mutex_unlock(&dev->bus_mutex);
                err = w1_get_slaves(dev, req_msg, req_hdr, req_cmd);
+               mutex_lock(&dev->bus_mutex);
                break;
        case W1_CMD_READ:
        case W1_CMD_WRITE:
@@ -262,8 +267,12 @@ static int w1_process_command_master(struct w1_master *dev,
                break;
        case W1_CMD_SLAVE_ADD:
        case W1_CMD_SLAVE_REMOVE:
+               mutex_unlock(&dev->bus_mutex);
+               mutex_lock(&dev->mutex);
                err = w1_process_command_addremove(dev, req_msg, req_hdr,
                        req_cmd);
+               mutex_unlock(&dev->mutex);
+               mutex_lock(&dev->bus_mutex);
                break;
        default:
                err = -EINVAL;
@@ -283,7 +292,8 @@ static int w1_process_command_slave(struct w1_slave *sl, struct cn_msg *msg,
        return w1_process_command_io(sl->master, msg, hdr, cmd);
 }
 
-static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mcmd)
+static int w1_process_command_root(struct cn_msg *msg,
+       struct w1_netlink_msg *mcmd, u32 portid)
 {
        struct w1_master *m;
        struct cn_msg *cn;
@@ -316,7 +326,7 @@ static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mc
        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_netlink_send(cn, portid, 0, GFP_KERNEL);
                        cn->ack++;
                        cn->len = sizeof(struct w1_netlink_msg);
                        w->len = 0;
@@ -329,7 +339,7 @@ static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mc
                id++;
        }
        cn->ack = 0;
-       cn_netlink_send(cn, 0, GFP_KERNEL);
+       cn_netlink_send(cn, portid, 0, GFP_KERNEL);
        mutex_unlock(&w1_mlock);
 
        kfree(cn);
@@ -337,7 +347,7 @@ static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mc
 }
 
 static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rmsg,
-               struct w1_netlink_cmd *rcmd, int error)
+               struct w1_netlink_cmd *rcmd, int portid, int error)
 {
        struct cn_msg *cmsg;
        struct w1_netlink_msg *msg;
@@ -364,7 +374,7 @@ static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rm
                cmsg->len += sizeof(*cmd);
        }
 
-       error = cn_netlink_send(cmsg, 0, GFP_KERNEL);
+       error = cn_netlink_send(cmsg, portid, 0, GFP_KERNEL);
        kfree(cmsg);
 
        return error;
@@ -375,6 +385,7 @@ static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rm
  */
 struct w1_cb_block {
        atomic_t refcnt;
+       u32 portid; /* Sending process port ID */
        struct cn_msg msg;
        /* cn_msg data */
        /* one or more variable length struct w1_cb_node */
@@ -398,7 +409,8 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd)
        struct w1_slave *sl = node->sl;
        struct w1_netlink_cmd *cmd = NULL;
 
-       mutex_lock(&dev->mutex);
+       mutex_lock(&dev->bus_mutex);
+       dev->portid = node->block->portid;
        if (sl && w1_reset_select_slave(sl))
                err = -ENODEV;
 
@@ -417,7 +429,8 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd)
                        err = w1_process_command_master(dev, &node->block->msg,
                                node->m, cmd);
 
-               w1_netlink_send_error(&node->block->msg, node->m, cmd, err);
+               w1_netlink_send_error(&node->block->msg, node->m, cmd,
+                       node->block->portid, err);
                err = 0;
 
                cmd_data += cmd->len + sizeof(struct w1_netlink_cmd);
@@ -425,13 +438,15 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd)
        }
 
        if (!cmd || err)
-               w1_netlink_send_error(&node->block->msg, node->m, cmd, err);
+               w1_netlink_send_error(&node->block->msg, node->m, cmd,
+                       node->block->portid, err);
 
        if (sl)
                w1_unref_slave(sl);
        else
                atomic_dec(&dev->refcnt);
-       mutex_unlock(&dev->mutex);
+       dev->portid = 0;
+       mutex_unlock(&dev->bus_mutex);
 
        mutex_lock(&dev->list_mutex);
        list_del(&async_cmd->async_entry);
@@ -476,10 +491,12 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
                        node_count*sizeof(struct w1_cb_node);
                block = kmalloc(size, GFP_KERNEL);
                if (!block) {
-                       w1_netlink_send_error(msg, m, NULL, -ENOMEM);
+                       w1_netlink_send_error(msg, m, NULL, nsp->portid,
+                               -ENOMEM);
                        return;
                }
                atomic_set(&block->refcnt, 1);
+               block->portid = nsp->portid;
                memcpy(&block->msg, msg, sizeof(*msg) + msg->len);
                node = (struct w1_cb_node *)((u8 *)block->msg.data + msg->len);
        }
@@ -509,7 +526,7 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
                        if (sl)
                                dev = sl->master;
                } else {
-                       err = w1_process_command_root(msg, m);
+                       err = w1_process_command_root(msg, m, nsp->portid);
                        goto out_cont;
                }
 
@@ -538,7 +555,7 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
 
 out_cont:
                if (err)
-                       w1_netlink_send_error(msg, m, NULL, err);
+                       w1_netlink_send_error(msg, m, NULL, nsp->portid, err);
                msg_len -= sizeof(struct w1_netlink_msg) + m->len;
                m = (struct w1_netlink_msg *)(((u8 *)m) + sizeof(struct w1_netlink_msg) + m->len);