diff options
Diffstat (limited to 'drivers/w1')
-rw-r--r-- | drivers/w1/w1_netlink.c | 142 |
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 | ||
98 | static int w1_process_command_master(struct w1_master *dev, struct cn_msg *req_msg, | 98 | static 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 | |||
141 | static 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 | ||
179 | static int w1_process_command_slave(struct w1_slave *sl, struct cn_msg *msg, | 137 | static 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 | |||
162 | static 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 | ||
210 | static 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 | |||
208 | static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mcmd) | 220 | static 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 | ||