Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/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 *mei_flow_control;
296
297         mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
298         mei_hdr->host_addr = 0;
299         mei_hdr->me_addr = 0;
300         mei_hdr->length = sizeof(struct hbm_flow_control);
301         mei_hdr->msg_complete = 1;
302         mei_hdr->reserved = 0;
303
304         mei_flow_control = (struct hbm_flow_control *) &dev->wr_msg_buf[1];
305         memset(mei_flow_control, 0, sizeof(*mei_flow_control));
306         mei_flow_control->host_addr = cl->host_client_id;
307         mei_flow_control->me_addr = cl->me_client_id;
308         mei_flow_control->hbm_cmd = MEI_FLOW_CONTROL_CMD;
309         memset(mei_flow_control->reserved, 0,
310                         sizeof(mei_flow_control->reserved));
311         dev_dbg(&dev->pdev->dev, "sending flow control host client = %d, ME client = %d\n",
312                 cl->host_client_id, cl->me_client_id);
313
314         return mei_write_message(dev, mei_hdr,
315                                 (unsigned char *) mei_flow_control,
316                                 sizeof(struct hbm_flow_control));
317 }
318
319 /**
320  * mei_other_client_is_connecting - checks if other
321  *    client with the same client id is connected.
322  *
323  * @dev: the device structure
324  * @cl: private data of the file object
325  *
326  * returns 1 if other client is connected, 0 - otherwise.
327  */
328 int mei_other_client_is_connecting(struct mei_device *dev,
329                                 struct mei_cl *cl)
330 {
331         struct mei_cl *cl_pos = NULL;
332         struct mei_cl *cl_next = NULL;
333
334         list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
335                 if ((cl_pos->state == MEI_FILE_CONNECTING) &&
336                         (cl_pos != cl) &&
337                         cl->me_client_id == cl_pos->me_client_id)
338                         return 1;
339
340         }
341         return 0;
342 }
343
344 /**
345  * mei_disconnect - sends disconnect message to fw.
346  *
347  * @dev: the device structure
348  * @cl: private data of the file object
349  *
350  * This function returns -EIO on write failure
351  */
352 int mei_disconnect(struct mei_device *dev, struct mei_cl *cl)
353 {
354         struct mei_msg_hdr *mei_hdr;
355         struct hbm_client_disconnect_request *mei_cli_disconnect;
356
357         mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
358         mei_hdr->host_addr = 0;
359         mei_hdr->me_addr = 0;
360         mei_hdr->length = sizeof(struct hbm_client_disconnect_request);
361         mei_hdr->msg_complete = 1;
362         mei_hdr->reserved = 0;
363
364         mei_cli_disconnect =
365             (struct hbm_client_disconnect_request *) &dev->wr_msg_buf[1];
366         memset(mei_cli_disconnect, 0, sizeof(*mei_cli_disconnect));
367         mei_cli_disconnect->host_addr = cl->host_client_id;
368         mei_cli_disconnect->me_addr = cl->me_client_id;
369         mei_cli_disconnect->hbm_cmd = CLIENT_DISCONNECT_REQ_CMD;
370         mei_cli_disconnect->reserved[0] = 0;
371
372         return mei_write_message(dev, mei_hdr,
373                                 (unsigned char *) mei_cli_disconnect,
374                                 sizeof(struct hbm_client_disconnect_request));
375 }
376
377 /**
378  * mei_connect - sends connect message to fw.
379  *
380  * @dev: the device structure
381  * @cl: private data of the file object
382  *
383  * This function returns -EIO on write failure
384  */
385 int mei_connect(struct mei_device *dev, struct mei_cl *cl)
386 {
387         struct mei_msg_hdr *mei_hdr;
388         struct hbm_client_connect_request *mei_cli_connect;
389
390         mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
391         mei_hdr->host_addr = 0;
392         mei_hdr->me_addr = 0;
393         mei_hdr->length = sizeof(struct hbm_client_connect_request);
394         mei_hdr->msg_complete = 1;
395         mei_hdr->reserved = 0;
396
397         mei_cli_connect =
398             (struct hbm_client_connect_request *) &dev->wr_msg_buf[1];
399         mei_cli_connect->host_addr = cl->host_client_id;
400         mei_cli_connect->me_addr = cl->me_client_id;
401         mei_cli_connect->hbm_cmd = CLIENT_CONNECT_REQ_CMD;
402         mei_cli_connect->reserved = 0;
403
404         return mei_write_message(dev, mei_hdr,
405                                 (unsigned char *) mei_cli_connect,
406                                 sizeof(struct hbm_client_connect_request));
407 }