]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/misc/mei/interface.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[karo-tx-linux.git] / drivers / misc / mei / interface.c
1 /*
2  *
3  * Intel Management Engine Interface (Intel MEI) Linux driver
4  * Copyright (c) 2003-2012, Intel Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  */
16
17 #include <linux/pci.h>
18 #include "mei_dev.h"
19 #include <linux/mei.h>
20 #include "interface.h"
21
22
23
24 /**
25  * mei_set_csr_register - writes H_CSR register to the mei device,
26  * and ignores the H_IS bit for it is write-one-to-zero.
27  *
28  * @dev: the device structure
29  */
30 void mei_hcsr_set(struct mei_device *dev)
31 {
32         if ((dev->host_hw_state & H_IS) == H_IS)
33                 dev->host_hw_state &= ~H_IS;
34         mei_reg_write(dev, H_CSR, dev->host_hw_state);
35         dev->host_hw_state = mei_hcsr_read(dev);
36 }
37
38 /**
39  * mei_csr_enable_interrupts - enables mei device interrupts
40  *
41  * @dev: the device structure
42  */
43 void mei_enable_interrupts(struct mei_device *dev)
44 {
45         dev->host_hw_state |= H_IE;
46         mei_hcsr_set(dev);
47 }
48
49 /**
50  * mei_csr_disable_interrupts - disables mei device interrupts
51  *
52  * @dev: the device structure
53  */
54 void mei_disable_interrupts(struct mei_device *dev)
55 {
56         dev->host_hw_state &= ~H_IE;
57         mei_hcsr_set(dev);
58 }
59
60 /**
61  * mei_hbuf_filled_slots - gets number of device filled buffer slots
62  *
63  * @device: the device structure
64  *
65  * returns number of filled slots
66  */
67 static unsigned char mei_hbuf_filled_slots(struct mei_device *dev)
68 {
69         char read_ptr, write_ptr;
70
71         dev->host_hw_state = mei_hcsr_read(dev);
72
73         read_ptr = (char) ((dev->host_hw_state & H_CBRP) >> 8);
74         write_ptr = (char) ((dev->host_hw_state & H_CBWP) >> 16);
75
76         return (unsigned char) (write_ptr - read_ptr);
77 }
78
79 /**
80  * mei_hbuf_is_empty - checks if host buffer is empty.
81  *
82  * @dev: the device structure
83  *
84  * returns true if empty, false - otherwise.
85  */
86 bool mei_hbuf_is_empty(struct mei_device *dev)
87 {
88         return mei_hbuf_filled_slots(dev) == 0;
89 }
90
91 /**
92  * mei_hbuf_empty_slots - counts write empty slots.
93  *
94  * @dev: the device structure
95  *
96  * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count
97  */
98 int mei_hbuf_empty_slots(struct mei_device *dev)
99 {
100         unsigned char filled_slots, empty_slots;
101
102         filled_slots = mei_hbuf_filled_slots(dev);
103         empty_slots = dev->hbuf_depth - filled_slots;
104
105         /* check for overflow */
106         if (filled_slots > dev->hbuf_depth)
107                 return -EOVERFLOW;
108
109         return empty_slots;
110 }
111
112 /**
113  * mei_write_message - writes a message to mei device.
114  *
115  * @dev: the device structure
116  * @header: header of message
117  * @write_buffer: message buffer will be written
118  * @write_length: message size will be written
119  *
120  * This function returns -EIO if write has failed
121  */
122 int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header,
123                       unsigned char *buf, unsigned long length)
124 {
125         unsigned long rem, dw_cnt;
126         u32 *reg_buf = (u32 *)buf;
127         int i;
128         int empty_slots;
129
130
131         dev_dbg(&dev->pdev->dev,
132                         "mei_write_message header=%08x.\n",
133                         *((u32 *) header));
134
135         empty_slots = mei_hbuf_empty_slots(dev);
136         dev_dbg(&dev->pdev->dev, "empty slots = %hu.\n", empty_slots);
137
138         dw_cnt = mei_data2slots(length);
139         if (empty_slots < 0 || dw_cnt > empty_slots)
140                 return -EIO;
141
142         mei_reg_write(dev, H_CB_WW, *((u32 *) header));
143
144         for (i = 0; i < length / 4; i++)
145                 mei_reg_write(dev, H_CB_WW, reg_buf[i]);
146
147         rem = length & 0x3;
148         if (rem > 0) {
149                 u32 reg = 0;
150                 memcpy(&reg, &buf[length - rem], rem);
151                 mei_reg_write(dev, H_CB_WW, reg);
152         }
153
154         dev->host_hw_state = mei_hcsr_read(dev);
155         dev->host_hw_state |= H_IG;
156         mei_hcsr_set(dev);
157         dev->me_hw_state = mei_mecsr_read(dev);
158         if ((dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA)
159                 return -EIO;
160
161         return 0;
162 }
163
164 /**
165  * mei_count_full_read_slots - counts read full slots.
166  *
167  * @dev: the device structure
168  *
169  * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise filled slots count
170  */
171 int mei_count_full_read_slots(struct mei_device *dev)
172 {
173         char read_ptr, write_ptr;
174         unsigned char buffer_depth, filled_slots;
175
176         dev->me_hw_state = mei_mecsr_read(dev);
177         buffer_depth = (unsigned char)((dev->me_hw_state & ME_CBD_HRA) >> 24);
178         read_ptr = (char) ((dev->me_hw_state & ME_CBRP_HRA) >> 8);
179         write_ptr = (char) ((dev->me_hw_state & ME_CBWP_HRA) >> 16);
180         filled_slots = (unsigned char) (write_ptr - read_ptr);
181
182         /* check for overflow */
183         if (filled_slots > buffer_depth)
184                 return -EOVERFLOW;
185
186         dev_dbg(&dev->pdev->dev, "filled_slots =%08x\n", filled_slots);
187         return (int)filled_slots;
188 }
189
190 /**
191  * mei_read_slots - reads a message from mei device.
192  *
193  * @dev: the device structure
194  * @buffer: message buffer will be written
195  * @buffer_length: message size will be read
196  */
197 void mei_read_slots(struct mei_device *dev, unsigned char *buffer,
198                     unsigned long buffer_length)
199 {
200         u32 *reg_buf = (u32 *)buffer;
201
202         for (; buffer_length >= sizeof(u32); buffer_length -= sizeof(u32))
203                 *reg_buf++ = mei_mecbrw_read(dev);
204
205         if (buffer_length > 0) {
206                 u32 reg = mei_mecbrw_read(dev);
207                 memcpy(reg_buf, &reg, buffer_length);
208         }
209
210         dev->host_hw_state |= H_IG;
211         mei_hcsr_set(dev);
212 }
213
214 /**
215  * mei_flow_ctrl_creds - checks flow_control credentials.
216  *
217  * @dev: the device structure
218  * @cl: private data of the file object
219  *
220  * returns 1 if mei_flow_ctrl_creds >0, 0 - otherwise.
221  *      -ENOENT if mei_cl is not present
222  *      -EINVAL if single_recv_buf == 0
223  */
224 int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl)
225 {
226         int i;
227
228         if (!dev->me_clients_num)
229                 return 0;
230
231         if (cl->mei_flow_ctrl_creds > 0)
232                 return 1;
233
234         for (i = 0; i < dev->me_clients_num; i++) {
235                 struct mei_me_client  *me_cl = &dev->me_clients[i];
236                 if (me_cl->client_id == cl->me_client_id) {
237                         if (me_cl->mei_flow_ctrl_creds) {
238                                 if (WARN_ON(me_cl->props.single_recv_buf == 0))
239                                         return -EINVAL;
240                                 return 1;
241                         } else {
242                                 return 0;
243                         }
244                 }
245         }
246         return -ENOENT;
247 }
248
249 /**
250  * mei_flow_ctrl_reduce - reduces flow_control.
251  *
252  * @dev: the device structure
253  * @cl: private data of the file object
254  * @returns
255  *      0 on success
256  *      -ENOENT when me client is not found
257  *      -EINVAL when ctrl credits are <= 0
258  */
259 int mei_flow_ctrl_reduce(struct mei_device *dev, struct mei_cl *cl)
260 {
261         int i;
262
263         if (!dev->me_clients_num)
264                 return -ENOENT;
265
266         for (i = 0; i < dev->me_clients_num; i++) {
267                 struct mei_me_client  *me_cl = &dev->me_clients[i];
268                 if (me_cl->client_id == cl->me_client_id) {
269                         if (me_cl->props.single_recv_buf != 0) {
270                                 if (WARN_ON(me_cl->mei_flow_ctrl_creds <= 0))
271                                         return -EINVAL;
272                                 dev->me_clients[i].mei_flow_ctrl_creds--;
273                         } else {
274                                 if (WARN_ON(cl->mei_flow_ctrl_creds <= 0))
275                                         return -EINVAL;
276                                 cl->mei_flow_ctrl_creds--;
277                         }
278                         return 0;
279                 }
280         }
281         return -ENOENT;
282 }
283
284 /**
285  * mei_send_flow_control - sends flow control to fw.
286  *
287  * @dev: the device structure
288  * @cl: private data of the file object
289  *
290  * This function returns -EIO on write failure
291  */
292 int mei_send_flow_control(struct mei_device *dev, struct mei_cl *cl)
293 {
294         struct mei_msg_hdr *mei_hdr;
295         struct hbm_flow_control *flow_ctrl;
296         const size_t len = sizeof(struct hbm_flow_control);
297
298         mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
299
300         flow_ctrl = (struct hbm_flow_control *)&dev->wr_msg_buf[1];
301         memset(flow_ctrl, 0, len);
302         flow_ctrl->hbm_cmd = MEI_FLOW_CONTROL_CMD;
303         flow_ctrl->host_addr = cl->host_client_id;
304         flow_ctrl->me_addr = cl->me_client_id;
305         /* FIXME: reserved !? */
306         memset(flow_ctrl->reserved, 0, sizeof(flow_ctrl->reserved));
307         dev_dbg(&dev->pdev->dev, "sending flow control host client = %d, ME client = %d\n",
308                 cl->host_client_id, cl->me_client_id);
309
310         return mei_write_message(dev, mei_hdr,
311                         (unsigned char *) flow_ctrl, len);
312 }
313
314 /**
315  * mei_other_client_is_connecting - checks if other
316  *    client with the same client id is connected.
317  *
318  * @dev: the device structure
319  * @cl: private data of the file object
320  *
321  * returns 1 if other client is connected, 0 - otherwise.
322  */
323 int mei_other_client_is_connecting(struct mei_device *dev,
324                                 struct mei_cl *cl)
325 {
326         struct mei_cl *cl_pos = NULL;
327         struct mei_cl *cl_next = NULL;
328
329         list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
330                 if ((cl_pos->state == MEI_FILE_CONNECTING) &&
331                         (cl_pos != cl) &&
332                         cl->me_client_id == cl_pos->me_client_id)
333                         return 1;
334
335         }
336         return 0;
337 }
338
339 /**
340  * mei_disconnect - sends disconnect message to fw.
341  *
342  * @dev: the device structure
343  * @cl: private data of the file object
344  *
345  * This function returns -EIO on write failure
346  */
347 int mei_disconnect(struct mei_device *dev, struct mei_cl *cl)
348 {
349         struct mei_msg_hdr *mei_hdr;
350         struct hbm_client_connect_request *req;
351         const size_t len = sizeof(struct hbm_client_connect_request);
352
353         mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
354
355         req = (struct hbm_client_connect_request *)&dev->wr_msg_buf[1];
356         memset(req, 0, len);
357         req->hbm_cmd = CLIENT_DISCONNECT_REQ_CMD;
358         req->host_addr = cl->host_client_id;
359         req->me_addr = cl->me_client_id;
360         req->reserved = 0;
361
362         return mei_write_message(dev, mei_hdr, (unsigned char *)req, len);
363 }
364
365 /**
366  * mei_connect - sends connect message to fw.
367  *
368  * @dev: the device structure
369  * @cl: private data of the file object
370  *
371  * This function returns -EIO on write failure
372  */
373 int mei_connect(struct mei_device *dev, struct mei_cl *cl)
374 {
375         struct mei_msg_hdr *mei_hdr;
376         struct hbm_client_connect_request *req;
377         const size_t len = sizeof(struct hbm_client_connect_request);
378
379         mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
380
381         req = (struct hbm_client_connect_request *) &dev->wr_msg_buf[1];
382         req->hbm_cmd = CLIENT_CONNECT_REQ_CMD;
383         req->host_addr = cl->host_client_id;
384         req->me_addr = cl->me_client_id;
385         req->reserved = 0;
386
387         return mei_write_message(dev, mei_hdr, (unsigned char *) req, len);
388 }