Linux 6.7-rc7
[linux-modified.git] / drivers / misc / mei / interrupt.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2003-2018, Intel Corporation. All rights reserved.
4  * Intel Management Engine Interface (Intel MEI) Linux driver
5  */
6
7 #include <linux/export.h>
8 #include <linux/kthread.h>
9 #include <linux/interrupt.h>
10 #include <linux/fs.h>
11 #include <linux/jiffies.h>
12 #include <linux/slab.h>
13 #include <linux/pm_runtime.h>
14
15 #include <linux/mei.h>
16
17 #include "mei_dev.h"
18 #include "hbm.h"
19 #include "client.h"
20
21
22 /**
23  * mei_irq_compl_handler - dispatch complete handlers
24  *      for the completed callbacks
25  *
26  * @dev: mei device
27  * @cmpl_list: list of completed cbs
28  */
29 void mei_irq_compl_handler(struct mei_device *dev, struct list_head *cmpl_list)
30 {
31         struct mei_cl_cb *cb, *next;
32         struct mei_cl *cl;
33
34         list_for_each_entry_safe(cb, next, cmpl_list, list) {
35                 cl = cb->cl;
36                 list_del_init(&cb->list);
37
38                 dev_dbg(dev->dev, "completing call back.\n");
39                 mei_cl_complete(cl, cb);
40         }
41 }
42 EXPORT_SYMBOL_GPL(mei_irq_compl_handler);
43
44 /**
45  * mei_cl_hbm_equal - check if hbm is addressed to the client
46  *
47  * @cl: host client
48  * @mei_hdr: header of mei client message
49  *
50  * Return: true if matches, false otherwise
51  */
52 static inline int mei_cl_hbm_equal(struct mei_cl *cl,
53                         struct mei_msg_hdr *mei_hdr)
54 {
55         return  mei_cl_host_addr(cl) == mei_hdr->host_addr &&
56                 mei_cl_me_id(cl) == mei_hdr->me_addr;
57 }
58
59 /**
60  * mei_irq_discard_msg  - discard received message
61  *
62  * @dev: mei device
63  * @hdr: message header
64  * @discard_len: the length of the message to discard (excluding header)
65  */
66 static void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr,
67                                 size_t discard_len)
68 {
69         if (hdr->dma_ring) {
70                 mei_dma_ring_read(dev, NULL,
71                                   hdr->extension[dev->rd_msg_hdr_count - 2]);
72                 discard_len = 0;
73         }
74         /*
75          * no need to check for size as it is guaranteed
76          * that length fits into rd_msg_buf
77          */
78         mei_read_slots(dev, dev->rd_msg_buf, discard_len);
79         dev_dbg(dev->dev, "discarding message " MEI_HDR_FMT "\n",
80                 MEI_HDR_PRM(hdr));
81 }
82
83 /**
84  * mei_cl_irq_read_msg - process client message
85  *
86  * @cl: reading client
87  * @mei_hdr: header of mei client message
88  * @meta: extend meta header
89  * @cmpl_list: completion list
90  *
91  * Return: always 0
92  */
93 static int mei_cl_irq_read_msg(struct mei_cl *cl,
94                                struct mei_msg_hdr *mei_hdr,
95                                struct mei_ext_meta_hdr *meta,
96                                struct list_head *cmpl_list)
97 {
98         struct mei_device *dev = cl->dev;
99         struct mei_cl_cb *cb;
100
101         struct mei_ext_hdr_vtag *vtag_hdr = NULL;
102         struct mei_ext_hdr_gsc_f2h *gsc_f2h = NULL;
103
104         size_t buf_sz;
105         u32 length;
106         u32 ext_len;
107
108         length = mei_hdr->length;
109         ext_len = 0;
110         if (mei_hdr->extended) {
111                 ext_len = sizeof(*meta) + mei_slots2data(meta->size);
112                 length -= ext_len;
113         }
114
115         cb = list_first_entry_or_null(&cl->rd_pending, struct mei_cl_cb, list);
116         if (!cb) {
117                 if (!mei_cl_is_fixed_address(cl)) {
118                         cl_err(dev, cl, "pending read cb not found\n");
119                         goto discard;
120                 }
121                 cb = mei_cl_alloc_cb(cl, mei_cl_mtu(cl), MEI_FOP_READ, cl->fp);
122                 if (!cb)
123                         goto discard;
124                 list_add_tail(&cb->list, &cl->rd_pending);
125         }
126
127         if (mei_hdr->extended) {
128                 struct mei_ext_hdr *ext = mei_ext_begin(meta);
129                 do {
130                         switch (ext->type) {
131                         case MEI_EXT_HDR_VTAG:
132                                 vtag_hdr = (struct mei_ext_hdr_vtag *)ext;
133                                 break;
134                         case MEI_EXT_HDR_GSC:
135                                 gsc_f2h = (struct mei_ext_hdr_gsc_f2h *)ext;
136                                 cb->ext_hdr = kzalloc(sizeof(*gsc_f2h), GFP_KERNEL);
137                                 if (!cb->ext_hdr) {
138                                         cb->status = -ENOMEM;
139                                         goto discard;
140                                 }
141                                 break;
142                         case MEI_EXT_HDR_NONE:
143                                 fallthrough;
144                         default:
145                                 cl_err(dev, cl, "unknown extended header\n");
146                                 cb->status = -EPROTO;
147                                 break;
148                         }
149
150                         ext = mei_ext_next(ext);
151                 } while (!mei_ext_last(meta, ext));
152
153                 if (!vtag_hdr && !gsc_f2h) {
154                         cl_dbg(dev, cl, "no vtag or gsc found in extended header.\n");
155                         cb->status = -EPROTO;
156                         goto discard;
157                 }
158         }
159
160         if (vtag_hdr) {
161                 cl_dbg(dev, cl, "vtag: %d\n", vtag_hdr->vtag);
162                 if (cb->vtag && cb->vtag != vtag_hdr->vtag) {
163                         cl_err(dev, cl, "mismatched tag: %d != %d\n",
164                                cb->vtag, vtag_hdr->vtag);
165                         cb->status = -EPROTO;
166                         goto discard;
167                 }
168                 cb->vtag = vtag_hdr->vtag;
169         }
170
171         if (gsc_f2h) {
172                 u32 ext_hdr_len = mei_ext_hdr_len(&gsc_f2h->hdr);
173
174                 if (!dev->hbm_f_gsc_supported) {
175                         cl_err(dev, cl, "gsc extended header is not supported\n");
176                         cb->status = -EPROTO;
177                         goto discard;
178                 }
179
180                 if (length) {
181                         cl_err(dev, cl, "no data allowed in cb with gsc\n");
182                         cb->status = -EPROTO;
183                         goto discard;
184                 }
185                 if (ext_hdr_len > sizeof(*gsc_f2h)) {
186                         cl_err(dev, cl, "gsc extended header is too big %u\n", ext_hdr_len);
187                         cb->status = -EPROTO;
188                         goto discard;
189                 }
190                 memcpy(cb->ext_hdr, gsc_f2h, ext_hdr_len);
191         }
192
193         if (!mei_cl_is_connected(cl)) {
194                 cl_dbg(dev, cl, "not connected\n");
195                 cb->status = -ENODEV;
196                 goto discard;
197         }
198
199         if (mei_hdr->dma_ring)
200                 length = mei_hdr->extension[mei_data2slots(ext_len)];
201
202         buf_sz = length + cb->buf_idx;
203         /* catch for integer overflow */
204         if (buf_sz < cb->buf_idx) {
205                 cl_err(dev, cl, "message is too big len %d idx %zu\n",
206                        length, cb->buf_idx);
207                 cb->status = -EMSGSIZE;
208                 goto discard;
209         }
210
211         if (cb->buf.size < buf_sz) {
212                 cl_dbg(dev, cl, "message overflow. size %zu len %d idx %zu\n",
213                         cb->buf.size, length, cb->buf_idx);
214                 cb->status = -EMSGSIZE;
215                 goto discard;
216         }
217
218         if (mei_hdr->dma_ring) {
219                 mei_dma_ring_read(dev, cb->buf.data + cb->buf_idx, length);
220                 /*  for DMA read 0 length to generate interrupt to the device */
221                 mei_read_slots(dev, cb->buf.data + cb->buf_idx, 0);
222         } else {
223                 mei_read_slots(dev, cb->buf.data + cb->buf_idx, length);
224         }
225
226         cb->buf_idx += length;
227
228         if (mei_hdr->msg_complete) {
229                 cl_dbg(dev, cl, "completed read length = %zu\n", cb->buf_idx);
230                 list_move_tail(&cb->list, cmpl_list);
231         } else {
232                 pm_runtime_mark_last_busy(dev->dev);
233                 pm_request_autosuspend(dev->dev);
234         }
235
236         return 0;
237
238 discard:
239         if (cb)
240                 list_move_tail(&cb->list, cmpl_list);
241         mei_irq_discard_msg(dev, mei_hdr, length);
242         return 0;
243 }
244
245 /**
246  * mei_cl_irq_disconnect_rsp - send disconnection response message
247  *
248  * @cl: client
249  * @cb: callback block.
250  * @cmpl_list: complete list.
251  *
252  * Return: 0, OK; otherwise, error.
253  */
254 static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb,
255                                      struct list_head *cmpl_list)
256 {
257         struct mei_device *dev = cl->dev;
258         u32 msg_slots;
259         int slots;
260         int ret;
261
262         msg_slots = mei_hbm2slots(sizeof(struct hbm_client_connect_response));
263         slots = mei_hbuf_empty_slots(dev);
264         if (slots < 0)
265                 return -EOVERFLOW;
266
267         if ((u32)slots < msg_slots)
268                 return -EMSGSIZE;
269
270         ret = mei_hbm_cl_disconnect_rsp(dev, cl);
271         list_move_tail(&cb->list, cmpl_list);
272
273         return ret;
274 }
275
276 /**
277  * mei_cl_irq_read - processes client read related operation from the
278  *      interrupt thread context - request for flow control credits
279  *
280  * @cl: client
281  * @cb: callback block.
282  * @cmpl_list: complete list.
283  *
284  * Return: 0, OK; otherwise, error.
285  */
286 static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
287                            struct list_head *cmpl_list)
288 {
289         struct mei_device *dev = cl->dev;
290         u32 msg_slots;
291         int slots;
292         int ret;
293
294         if (!list_empty(&cl->rd_pending))
295                 return 0;
296
297         msg_slots = mei_hbm2slots(sizeof(struct hbm_flow_control));
298         slots = mei_hbuf_empty_slots(dev);
299         if (slots < 0)
300                 return -EOVERFLOW;
301
302         if ((u32)slots < msg_slots)
303                 return -EMSGSIZE;
304
305         ret = mei_hbm_cl_flow_control_req(dev, cl);
306         if (ret) {
307                 cl->status = ret;
308                 cb->buf_idx = 0;
309                 list_move_tail(&cb->list, cmpl_list);
310                 return ret;
311         }
312
313         pm_runtime_mark_last_busy(dev->dev);
314         pm_request_autosuspend(dev->dev);
315
316         list_move_tail(&cb->list, &cl->rd_pending);
317
318         return 0;
319 }
320
321 static inline bool hdr_is_hbm(struct mei_msg_hdr *mei_hdr)
322 {
323         return mei_hdr->host_addr == 0 && mei_hdr->me_addr == 0;
324 }
325
326 static inline bool hdr_is_fixed(struct mei_msg_hdr *mei_hdr)
327 {
328         return mei_hdr->host_addr == 0 && mei_hdr->me_addr != 0;
329 }
330
331 static inline int hdr_is_valid(u32 msg_hdr)
332 {
333         struct mei_msg_hdr *mei_hdr;
334         u32 expected_len = 0;
335
336         mei_hdr = (struct mei_msg_hdr *)&msg_hdr;
337         if (!msg_hdr || mei_hdr->reserved)
338                 return -EBADMSG;
339
340         if (mei_hdr->dma_ring)
341                 expected_len += MEI_SLOT_SIZE;
342         if (mei_hdr->extended)
343                 expected_len += MEI_SLOT_SIZE;
344         if (mei_hdr->length < expected_len)
345                 return -EBADMSG;
346
347         return 0;
348 }
349
350 /**
351  * mei_irq_read_handler - bottom half read routine after ISR to
352  * handle the read processing.
353  *
354  * @dev: the device structure
355  * @cmpl_list: An instance of our list structure
356  * @slots: slots to read.
357  *
358  * Return: 0 on success, <0 on failure.
359  */
360 int mei_irq_read_handler(struct mei_device *dev,
361                          struct list_head *cmpl_list, s32 *slots)
362 {
363         struct mei_msg_hdr *mei_hdr;
364         struct mei_ext_meta_hdr *meta_hdr = NULL;
365         struct mei_cl *cl;
366         int ret;
367         u32 hdr_size_left;
368         u32 hdr_size_ext;
369         int i;
370         int ext_hdr_end;
371
372         if (!dev->rd_msg_hdr[0]) {
373                 dev->rd_msg_hdr[0] = mei_read_hdr(dev);
374                 dev->rd_msg_hdr_count = 1;
375                 (*slots)--;
376                 dev_dbg(dev->dev, "slots =%08x.\n", *slots);
377
378                 ret = hdr_is_valid(dev->rd_msg_hdr[0]);
379                 if (ret) {
380                         dev_err(dev->dev, "corrupted message header 0x%08X\n",
381                                 dev->rd_msg_hdr[0]);
382                         goto end;
383                 }
384         }
385
386         mei_hdr = (struct mei_msg_hdr *)dev->rd_msg_hdr;
387         dev_dbg(dev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr));
388
389         if (mei_slots2data(*slots) < mei_hdr->length) {
390                 dev_err(dev->dev, "less data available than length=%08x.\n",
391                                 *slots);
392                 /* we can't read the message */
393                 ret = -ENODATA;
394                 goto end;
395         }
396
397         ext_hdr_end = 1;
398         hdr_size_left = mei_hdr->length;
399
400         if (mei_hdr->extended) {
401                 if (!dev->rd_msg_hdr[1]) {
402                         dev->rd_msg_hdr[1] = mei_read_hdr(dev);
403                         dev->rd_msg_hdr_count++;
404                         (*slots)--;
405                         dev_dbg(dev->dev, "extended header is %08x\n", dev->rd_msg_hdr[1]);
406                 }
407                 meta_hdr = ((struct mei_ext_meta_hdr *)&dev->rd_msg_hdr[1]);
408                 if (check_add_overflow((u32)sizeof(*meta_hdr),
409                                        mei_slots2data(meta_hdr->size),
410                                        &hdr_size_ext)) {
411                         dev_err(dev->dev, "extended message size too big %d\n",
412                                 meta_hdr->size);
413                         return -EBADMSG;
414                 }
415                 if (hdr_size_left < hdr_size_ext) {
416                         dev_err(dev->dev, "corrupted message header len %d\n",
417                                 mei_hdr->length);
418                         return -EBADMSG;
419                 }
420                 hdr_size_left -= hdr_size_ext;
421
422                 ext_hdr_end = meta_hdr->size + 2;
423                 for (i = dev->rd_msg_hdr_count; i < ext_hdr_end; i++) {
424                         dev->rd_msg_hdr[i] = mei_read_hdr(dev);
425                         dev_dbg(dev->dev, "extended header %d is %08x\n", i,
426                                 dev->rd_msg_hdr[i]);
427                         dev->rd_msg_hdr_count++;
428                         (*slots)--;
429                 }
430         }
431
432         if (mei_hdr->dma_ring) {
433                 if (hdr_size_left != sizeof(dev->rd_msg_hdr[ext_hdr_end])) {
434                         dev_err(dev->dev, "corrupted message header len %d\n",
435                                 mei_hdr->length);
436                         return -EBADMSG;
437                 }
438
439                 dev->rd_msg_hdr[ext_hdr_end] = mei_read_hdr(dev);
440                 dev->rd_msg_hdr_count++;
441                 (*slots)--;
442                 mei_hdr->length -= sizeof(dev->rd_msg_hdr[ext_hdr_end]);
443         }
444
445         /*  HBM message */
446         if (hdr_is_hbm(mei_hdr)) {
447                 ret = mei_hbm_dispatch(dev, mei_hdr);
448                 if (ret) {
449                         dev_dbg(dev->dev, "mei_hbm_dispatch failed ret = %d\n",
450                                         ret);
451                         goto end;
452                 }
453                 goto reset_slots;
454         }
455
456         /* find recipient cl */
457         list_for_each_entry(cl, &dev->file_list, link) {
458                 if (mei_cl_hbm_equal(cl, mei_hdr)) {
459                         cl_dbg(dev, cl, "got a message\n");
460                         ret = mei_cl_irq_read_msg(cl, mei_hdr, meta_hdr, cmpl_list);
461                         goto reset_slots;
462                 }
463         }
464
465         /* if no recipient cl was found we assume corrupted header */
466         /* A message for not connected fixed address clients
467          * should be silently discarded
468          * On power down client may be force cleaned,
469          * silently discard such messages
470          */
471         if (hdr_is_fixed(mei_hdr) ||
472             dev->dev_state == MEI_DEV_POWER_DOWN) {
473                 mei_irq_discard_msg(dev, mei_hdr, mei_hdr->length);
474                 ret = 0;
475                 goto reset_slots;
476         }
477         dev_err(dev->dev, "no destination client found 0x%08X\n", dev->rd_msg_hdr[0]);
478         ret = -EBADMSG;
479         goto end;
480
481 reset_slots:
482         /* reset the number of slots and header */
483         memset(dev->rd_msg_hdr, 0, sizeof(dev->rd_msg_hdr));
484         dev->rd_msg_hdr_count = 0;
485         *slots = mei_count_full_read_slots(dev);
486         if (*slots == -EOVERFLOW) {
487                 /* overflow - reset */
488                 dev_err(dev->dev, "resetting due to slots overflow.\n");
489                 /* set the event since message has been read */
490                 ret = -ERANGE;
491                 goto end;
492         }
493 end:
494         return ret;
495 }
496 EXPORT_SYMBOL_GPL(mei_irq_read_handler);
497
498
499 /**
500  * mei_irq_write_handler -  dispatch write requests
501  *  after irq received
502  *
503  * @dev: the device structure
504  * @cmpl_list: An instance of our list structure
505  *
506  * Return: 0 on success, <0 on failure.
507  */
508 int mei_irq_write_handler(struct mei_device *dev, struct list_head *cmpl_list)
509 {
510
511         struct mei_cl *cl;
512         struct mei_cl_cb *cb, *next;
513         s32 slots;
514         int ret;
515
516
517         if (!mei_hbuf_acquire(dev))
518                 return 0;
519
520         slots = mei_hbuf_empty_slots(dev);
521         if (slots < 0)
522                 return -EOVERFLOW;
523
524         if (slots == 0)
525                 return -EMSGSIZE;
526
527         /* complete all waiting for write CB */
528         dev_dbg(dev->dev, "complete all waiting for write cb.\n");
529
530         list_for_each_entry_safe(cb, next, &dev->write_waiting_list, list) {
531                 cl = cb->cl;
532
533                 cl->status = 0;
534                 cl_dbg(dev, cl, "MEI WRITE COMPLETE\n");
535                 cl->writing_state = MEI_WRITE_COMPLETE;
536                 list_move_tail(&cb->list, cmpl_list);
537         }
538
539         /* complete control write list CB */
540         dev_dbg(dev->dev, "complete control write list cb.\n");
541         list_for_each_entry_safe(cb, next, &dev->ctrl_wr_list, list) {
542                 cl = cb->cl;
543                 switch (cb->fop_type) {
544                 case MEI_FOP_DISCONNECT:
545                         /* send disconnect message */
546                         ret = mei_cl_irq_disconnect(cl, cb, cmpl_list);
547                         if (ret)
548                                 return ret;
549
550                         break;
551                 case MEI_FOP_READ:
552                         /* send flow control message */
553                         ret = mei_cl_irq_read(cl, cb, cmpl_list);
554                         if (ret)
555                                 return ret;
556
557                         break;
558                 case MEI_FOP_CONNECT:
559                         /* connect message */
560                         ret = mei_cl_irq_connect(cl, cb, cmpl_list);
561                         if (ret)
562                                 return ret;
563
564                         break;
565                 case MEI_FOP_DISCONNECT_RSP:
566                         /* send disconnect resp */
567                         ret = mei_cl_irq_disconnect_rsp(cl, cb, cmpl_list);
568                         if (ret)
569                                 return ret;
570                         break;
571
572                 case MEI_FOP_NOTIFY_START:
573                 case MEI_FOP_NOTIFY_STOP:
574                         ret = mei_cl_irq_notify(cl, cb, cmpl_list);
575                         if (ret)
576                                 return ret;
577                         break;
578                 case MEI_FOP_DMA_MAP:
579                         ret = mei_cl_irq_dma_map(cl, cb, cmpl_list);
580                         if (ret)
581                                 return ret;
582                         break;
583                 case MEI_FOP_DMA_UNMAP:
584                         ret = mei_cl_irq_dma_unmap(cl, cb, cmpl_list);
585                         if (ret)
586                                 return ret;
587                         break;
588                 default:
589                         BUG();
590                 }
591
592         }
593         /* complete  write list CB */
594         dev_dbg(dev->dev, "complete write list cb.\n");
595         list_for_each_entry_safe(cb, next, &dev->write_list, list) {
596                 cl = cb->cl;
597                 ret = mei_cl_irq_write(cl, cb, cmpl_list);
598                 if (ret)
599                         return ret;
600         }
601         return 0;
602 }
603 EXPORT_SYMBOL_GPL(mei_irq_write_handler);
604
605
606 /**
607  * mei_connect_timeout  - connect/disconnect timeouts
608  *
609  * @cl: host client
610  */
611 static void mei_connect_timeout(struct mei_cl *cl)
612 {
613         struct mei_device *dev = cl->dev;
614
615         if (cl->state == MEI_FILE_CONNECTING) {
616                 if (dev->hbm_f_dot_supported) {
617                         cl->state = MEI_FILE_DISCONNECT_REQUIRED;
618                         wake_up(&cl->wait);
619                         return;
620                 }
621         }
622         mei_reset(dev);
623 }
624
625 #define MEI_STALL_TIMER_FREQ (2 * HZ)
626 /**
627  * mei_schedule_stall_timer - re-arm stall_timer work
628  *
629  * @dev: the device structure
630  *
631  * Schedule stall timer
632  */
633 void mei_schedule_stall_timer(struct mei_device *dev)
634 {
635         schedule_delayed_work(&dev->timer_work, MEI_STALL_TIMER_FREQ);
636 }
637
638 /**
639  * mei_timer - timer function.
640  *
641  * @work: pointer to the work_struct structure
642  *
643  */
644 void mei_timer(struct work_struct *work)
645 {
646         struct mei_cl *cl;
647         struct mei_device *dev = container_of(work,
648                                         struct mei_device, timer_work.work);
649         bool reschedule_timer = false;
650
651         mutex_lock(&dev->device_lock);
652
653         /* Catch interrupt stalls during HBM init handshake */
654         if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
655             dev->hbm_state != MEI_HBM_IDLE) {
656
657                 if (dev->init_clients_timer) {
658                         if (--dev->init_clients_timer == 0) {
659                                 dev_err(dev->dev, "timer: init clients timeout hbm_state = %d.\n",
660                                         dev->hbm_state);
661                                 mei_reset(dev);
662                                 goto out;
663                         }
664                         reschedule_timer = true;
665                 }
666         }
667
668         if (dev->dev_state != MEI_DEV_ENABLED)
669                 goto out;
670
671         /*** connect/disconnect timeouts ***/
672         list_for_each_entry(cl, &dev->file_list, link) {
673                 if (cl->timer_count) {
674                         if (--cl->timer_count == 0) {
675                                 dev_err(dev->dev, "timer: connect/disconnect timeout.\n");
676                                 mei_connect_timeout(cl);
677                                 goto out;
678                         }
679                         reschedule_timer = true;
680                 }
681         }
682
683 out:
684         if (dev->dev_state != MEI_DEV_DISABLED && reschedule_timer)
685                 mei_schedule_stall_timer(dev);
686
687         mutex_unlock(&dev->device_lock);
688 }