aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/w1
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/w1')
-rw-r--r--drivers/w1/w1_netlink.c142
1 files changed, 77 insertions, 65 deletions
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
index 8a7021577f32..a94336be7654 100644
--- a/drivers/w1/w1_netlink.c
+++ b/drivers/w1/w1_netlink.c
@@ -95,51 +95,8 @@ static int w1_process_search_command(struct w1_master *dev, struct cn_msg *msg,
95 return 0; 95 return 0;
96} 96}
97 97
98static int w1_process_command_master(struct w1_master *dev, struct cn_msg *req_msg, 98static int w1_send_read_reply(struct cn_msg *msg, struct w1_netlink_msg *hdr,
99 struct w1_netlink_msg *req_hdr, struct w1_netlink_cmd *req_cmd) 99 struct w1_netlink_cmd *cmd)
100{
101 int err = -EINVAL;
102 struct cn_msg *msg;
103 struct w1_netlink_msg *hdr;
104 struct w1_netlink_cmd *cmd;
105
106 msg = kzalloc(PAGE_SIZE, GFP_KERNEL);
107 if (!msg)
108 return -ENOMEM;
109
110 msg->id = req_msg->id;
111 msg->seq = req_msg->seq;
112 msg->ack = 0;
113 msg->len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd);
114
115 hdr = (struct w1_netlink_msg *)(msg + 1);
116 cmd = (struct w1_netlink_cmd *)(hdr + 1);
117
118 hdr->type = W1_MASTER_CMD;
119 hdr->id = req_hdr->id;
120 hdr->len = sizeof(struct w1_netlink_cmd);
121
122 cmd->cmd = req_cmd->cmd;
123 cmd->len = 0;
124
125 switch (cmd->cmd) {
126 case W1_CMD_SEARCH:
127 case W1_CMD_ALARM_SEARCH:
128 err = w1_process_search_command(dev, msg,
129 PAGE_SIZE - msg->len - sizeof(struct cn_msg));
130 break;
131 default:
132 cmd->res = EINVAL;
133 cn_netlink_send(msg, 0, GFP_KERNEL);
134 break;
135 }
136
137 kfree(msg);
138 return err;
139}
140
141static int w1_send_read_reply(struct w1_slave *sl, struct cn_msg *msg,
142 struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd)
143{ 100{
144 void *data; 101 void *data;
145 struct w1_netlink_msg *h; 102 struct w1_netlink_msg *h;
@@ -163,7 +120,8 @@ static int w1_send_read_reply(struct w1_slave *sl, struct cn_msg *msg,
163 memcpy(c, cmd, sizeof(struct w1_netlink_cmd)); 120 memcpy(c, cmd, sizeof(struct w1_netlink_cmd));
164 121
165 cm->ack = msg->seq+1; 122 cm->ack = msg->seq+1;
166 cm->len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd) + cmd->len; 123 cm->len = sizeof(struct w1_netlink_msg) +
124 sizeof(struct w1_netlink_cmd) + cmd->len;
167 125
168 h->len = sizeof(struct w1_netlink_cmd) + cmd->len; 126 h->len = sizeof(struct w1_netlink_cmd) + cmd->len;
169 127
@@ -176,35 +134,89 @@ static int w1_send_read_reply(struct w1_slave *sl, struct cn_msg *msg,
176 return err; 134 return err;
177} 135}
178 136
179static int w1_process_command_slave(struct w1_slave *sl, struct cn_msg *msg, 137static int w1_process_command_io(struct w1_master *dev, struct cn_msg *msg,
180 struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd) 138 struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd)
181{ 139{
182 int err = 0; 140 int err = 0;
183 141
184 dev_dbg(&sl->master->dev, "%s: %02x.%012llx.%02x: cmd=%02x, len=%u.\n", 142 switch (cmd->cmd) {
185 __func__, sl->reg_num.family, (unsigned long long)sl->reg_num.id, sl->reg_num.crc, 143 case W1_CMD_TOUCH:
186 cmd->cmd, cmd->len); 144 w1_touch_block(dev, cmd->data, cmd->len);
145 w1_send_read_reply(msg, hdr, cmd);
146 break;
147 case W1_CMD_READ:
148 w1_read_block(dev, cmd->data, cmd->len);
149 w1_send_read_reply(msg, hdr, cmd);
150 break;
151 case W1_CMD_WRITE:
152 w1_write_block(dev, cmd->data, cmd->len);
153 break;
154 default:
155 err = -1;
156 break;
157 }
158
159 return err;
160}
161
162static int w1_process_command_master(struct w1_master *dev, struct cn_msg *req_msg,
163 struct w1_netlink_msg *req_hdr, struct w1_netlink_cmd *req_cmd)
164{
165 int err = -EINVAL;
166 struct cn_msg *msg;
167 struct w1_netlink_msg *hdr;
168 struct w1_netlink_cmd *cmd;
169
170 msg = kzalloc(PAGE_SIZE, GFP_KERNEL);
171 if (!msg)
172 return -ENOMEM;
173
174 msg->id = req_msg->id;
175 msg->seq = req_msg->seq;
176 msg->ack = 0;
177 msg->len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd);
178
179 hdr = (struct w1_netlink_msg *)(msg + 1);
180 cmd = (struct w1_netlink_cmd *)(hdr + 1);
181
182 hdr->type = W1_MASTER_CMD;
183 hdr->id = req_hdr->id;
184 hdr->len = sizeof(struct w1_netlink_cmd);
185
186 cmd->cmd = req_cmd->cmd;
187 cmd->len = 0;
187 188
188 switch (cmd->cmd) { 189 switch (cmd->cmd) {
189 case W1_CMD_TOUCH: 190 case W1_CMD_SEARCH:
190 w1_touch_block(sl->master, cmd->data, cmd->len); 191 case W1_CMD_ALARM_SEARCH:
191 w1_send_read_reply(sl, msg, hdr, cmd); 192 err = w1_process_search_command(dev, msg,
192 break; 193 PAGE_SIZE - msg->len - sizeof(struct cn_msg));
193 case W1_CMD_READ: 194 break;
194 w1_read_block(sl->master, cmd->data, cmd->len); 195 case W1_CMD_READ:
195 w1_send_read_reply(sl, msg, hdr, cmd); 196 case W1_CMD_WRITE:
196 break; 197 case W1_CMD_TOUCH:
197 case W1_CMD_WRITE: 198 err = w1_process_command_io(dev, msg, hdr, cmd);
198 w1_write_block(sl->master, cmd->data, cmd->len); 199 break;
199 break; 200 default:
200 default: 201 cmd->res = EINVAL;
201 err = -1; 202 cn_netlink_send(msg, 0, GFP_KERNEL);
202 break; 203 break;
203 } 204 }
204 205
206 kfree(msg);
205 return err; 207 return err;
206} 208}
207 209
210static int w1_process_command_slave(struct w1_slave *sl, struct cn_msg *msg,
211 struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd)
212{
213 dev_dbg(&sl->master->dev, "%s: %02x.%012llx.%02x: cmd=%02x, len=%u.\n",
214 __func__, sl->reg_num.family, (unsigned long long)sl->reg_num.id,
215 sl->reg_num.crc, cmd->cmd, cmd->len);
216
217 return w1_process_command_io(sl->master, msg, hdr, cmd);
218}
219
208static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mcmd) 220static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mcmd)
209{ 221{
210 struct w1_master *m; 222 struct w1_master *m;
@@ -214,7 +226,7 @@ static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mc
214 226
215 if (mcmd->type != W1_LIST_MASTERS) { 227 if (mcmd->type != W1_LIST_MASTERS) {
216 printk(KERN_NOTICE "%s: msg: %x.%x, wrong type: %u, len: %u.\n", 228 printk(KERN_NOTICE "%s: msg: %x.%x, wrong type: %u, len: %u.\n",
217 __func__, msg->id.idx, msg->id.val, mcmd->type, mcmd->len); 229 __func__, msg->id.idx, msg->id.val, mcmd->type, mcmd->len);
218 return -EPROTO; 230 return -EPROTO;
219 } 231 }
220 232