aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2013-02-06 07:06:42 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-02-06 14:24:33 -0500
commit06ecd6459800962155c485e27d9dd30268b579bf (patch)
tree76ddf71e529f45b7256d6b7bdf3efe49ec2a52db /drivers/misc
parent827eef51f8dd9a4ab62b4ad270c15472f46938f2 (diff)
mei: move interrupt handlers to be me hw specific
interrupt handler are platform specifics so we move them to hw-mei.c. For sake of that we need to export write, read, and complete handlers from the interrupt.c Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/mei/hw-me.c164
-rw-r--r--drivers/misc/mei/hw-me.h3
-rw-r--r--drivers/misc/mei/interrupt.c126
-rw-r--r--drivers/misc/mei/mei_dev.h9
-rw-r--r--drivers/misc/mei/pci-me.c12
5 files changed, 164 insertions, 150 deletions
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 6300943497ae..3bebf8d85ff9 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -15,11 +15,16 @@
15 */ 15 */
16 16
17#include <linux/pci.h> 17#include <linux/pci.h>
18#include <linux/mei.h> 18
19#include <linux/kthread.h>
20#include <linux/interrupt.h>
19 21
20#include "mei_dev.h" 22#include "mei_dev.h"
21#include "hw-me.h" 23#include "hw-me.h"
22 24
25#include "hbm.h"
26
27
23/** 28/**
24 * mei_reg_read - Reads 32bit data from the mei device 29 * mei_reg_read - Reads 32bit data from the mei device
25 * 30 *
@@ -218,29 +223,6 @@ static bool mei_me_hw_is_ready(struct mei_device *dev)
218} 223}
219 224
220/** 225/**
221 * mei_interrupt_quick_handler - The ISR of the MEI device
222 *
223 * @irq: The irq number
224 * @dev_id: pointer to the device structure
225 *
226 * returns irqreturn_t
227 */
228irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id)
229{
230 struct mei_device *dev = (struct mei_device *) dev_id;
231 struct mei_me_hw *hw = to_me_hw(dev);
232 u32 csr_reg = mei_hcsr_read(hw);
233
234 if ((csr_reg & H_IS) != H_IS)
235 return IRQ_NONE;
236
237 /* clear H_IS bit in H_CSR */
238 mei_reg_write(hw, H_CSR, csr_reg);
239
240 return IRQ_WAKE_THREAD;
241}
242
243/**
244 * mei_hbuf_filled_slots - gets number of device filled buffer slots 226 * mei_hbuf_filled_slots - gets number of device filled buffer slots
245 * 227 *
246 * @dev: the device structure 228 * @dev: the device structure
@@ -403,6 +385,139 @@ static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer,
403 return 0; 385 return 0;
404} 386}
405 387
388/**
389 * mei_me_irq_quick_handler - The ISR of the MEI device
390 *
391 * @irq: The irq number
392 * @dev_id: pointer to the device structure
393 *
394 * returns irqreturn_t
395 */
396
397irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id)
398{
399 struct mei_device *dev = (struct mei_device *) dev_id;
400 struct mei_me_hw *hw = to_me_hw(dev);
401 u32 csr_reg = mei_hcsr_read(hw);
402
403 if ((csr_reg & H_IS) != H_IS)
404 return IRQ_NONE;
405
406 /* clear H_IS bit in H_CSR */
407 mei_reg_write(hw, H_CSR, csr_reg);
408
409 return IRQ_WAKE_THREAD;
410}
411
412/**
413 * mei_me_irq_thread_handler - function called after ISR to handle the interrupt
414 * processing.
415 *
416 * @irq: The irq number
417 * @dev_id: pointer to the device structure
418 *
419 * returns irqreturn_t
420 *
421 */
422irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
423{
424 struct mei_device *dev = (struct mei_device *) dev_id;
425 struct mei_cl_cb complete_list;
426 struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
427 struct mei_cl *cl;
428 s32 slots;
429 int rets;
430 bool bus_message_received;
431
432
433 dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
434 /* initialize our complete list */
435 mutex_lock(&dev->device_lock);
436 mei_io_list_init(&complete_list);
437
438 /* Ack the interrupt here
439 * In case of MSI we don't go through the quick handler */
440 if (pci_dev_msi_enabled(dev->pdev))
441 mei_clear_interrupts(dev);
442
443 /* check if ME wants a reset */
444 if (!mei_hw_is_ready(dev) &&
445 dev->dev_state != MEI_DEV_RESETING &&
446 dev->dev_state != MEI_DEV_INITIALIZING) {
447 dev_dbg(&dev->pdev->dev, "FW not ready.\n");
448 mei_reset(dev, 1);
449 mutex_unlock(&dev->device_lock);
450 return IRQ_HANDLED;
451 }
452
453 /* check if we need to start the dev */
454 if (!mei_host_is_ready(dev)) {
455 if (mei_hw_is_ready(dev)) {
456 dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
457
458 mei_host_set_ready(dev);
459
460 dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
461 /* link is established * start sending messages. */
462
463 dev->dev_state = MEI_DEV_INIT_CLIENTS;
464
465 mei_hbm_start_req(dev);
466 mutex_unlock(&dev->device_lock);
467 return IRQ_HANDLED;
468 } else {
469 dev_dbg(&dev->pdev->dev, "FW not ready.\n");
470 mutex_unlock(&dev->device_lock);
471 return IRQ_HANDLED;
472 }
473 }
474 /* check slots available for reading */
475 slots = mei_count_full_read_slots(dev);
476 while (slots > 0) {
477 /* we have urgent data to send so break the read */
478 if (dev->wr_ext_msg.hdr.length)
479 break;
480 dev_dbg(&dev->pdev->dev, "slots =%08x\n", slots);
481 dev_dbg(&dev->pdev->dev, "call mei_irq_read_handler.\n");
482 rets = mei_irq_read_handler(dev, &complete_list, &slots);
483 if (rets)
484 goto end;
485 }
486 rets = mei_irq_write_handler(dev, &complete_list);
487end:
488 dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
489 dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev);
490
491 bus_message_received = false;
492 if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
493 dev_dbg(&dev->pdev->dev, "received waiting bus message\n");
494 bus_message_received = true;
495 }
496 mutex_unlock(&dev->device_lock);
497 if (bus_message_received) {
498 dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n");
499 wake_up_interruptible(&dev->wait_recvd_msg);
500 bus_message_received = false;
501 }
502 if (list_empty(&complete_list.list))
503 return IRQ_HANDLED;
504
505
506 list_for_each_entry_safe(cb_pos, cb_next, &complete_list.list, list) {
507 cl = cb_pos->cl;
508 list_del(&cb_pos->list);
509 if (cl) {
510 if (cl != &dev->iamthif_cl) {
511 dev_dbg(&dev->pdev->dev, "completing call back.\n");
512 mei_irq_complete_handler(cl, cb_pos);
513 cb_pos = NULL;
514 } else if (cl == &dev->iamthif_cl) {
515 mei_amthif_complete(dev, cb_pos);
516 }
517 }
518 }
519 return IRQ_HANDLED;
520}
406static const struct mei_hw_ops mei_me_hw_ops = { 521static const struct mei_hw_ops mei_me_hw_ops = {
407 522
408 .host_set_ready = mei_me_host_set_ready, 523 .host_set_ready = mei_me_host_set_ready,
@@ -458,3 +573,4 @@ struct mei_device *mei_me_dev_init(struct pci_dev *pdev)
458 dev->pdev = pdev; 573 dev->pdev = pdev;
459 return dev; 574 return dev;
460} 575}
576
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index 9a3aaab9bcf0..8518d3eeb838 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -42,4 +42,7 @@ static inline unsigned char mei_data2slots(size_t length)
42 return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4); 42 return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4);
43} 43}
44 44
45irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id);
46irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id);
47
45#endif /* _MEI_INTERFACE_H_ */ 48#endif /* _MEI_INTERFACE_H_ */
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 431aa91fd002..3535b2676c97 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -30,12 +30,12 @@
30 30
31 31
32/** 32/**
33 * _mei_cmpl - processes completed operation. 33 * mei_complete_handler - processes completed operation.
34 * 34 *
35 * @cl: private data of the file object. 35 * @cl: private data of the file object.
36 * @cb_pos: callback block. 36 * @cb_pos: callback block.
37 */ 37 */
38static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos) 38void mei_irq_complete_handler(struct mei_cl *cl, struct mei_cl_cb *cb_pos)
39{ 39{
40 if (cb_pos->fop_type == MEI_FOP_WRITE) { 40 if (cb_pos->fop_type == MEI_FOP_WRITE) {
41 mei_io_cb_free(cb_pos); 41 mei_io_cb_free(cb_pos);
@@ -313,15 +313,14 @@ static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots,
313 * mei_irq_thread_read_handler - bottom half read routine after ISR to 313 * mei_irq_thread_read_handler - bottom half read routine after ISR to
314 * handle the read processing. 314 * handle the read processing.
315 * 315 *
316 * @cmpl_list: An instance of our list structure
317 * @dev: the device structure 316 * @dev: the device structure
317 * @cmpl_list: An instance of our list structure
318 * @slots: slots to read. 318 * @slots: slots to read.
319 * 319 *
320 * returns 0 on success, <0 on failure. 320 * returns 0 on success, <0 on failure.
321 */ 321 */
322static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list, 322int mei_irq_read_handler(struct mei_device *dev,
323 struct mei_device *dev, 323 struct mei_cl_cb *cmpl_list, s32 *slots)
324 s32 *slots)
325{ 324{
326 struct mei_msg_hdr *mei_hdr; 325 struct mei_msg_hdr *mei_hdr;
327 struct mei_cl *cl_pos = NULL; 326 struct mei_cl *cl_pos = NULL;
@@ -412,15 +411,15 @@ end:
412 411
413 412
414/** 413/**
415 * mei_irq_thread_write_handler - bottom half write routine after 414 * mei_irq_write_handler - dispatch write requests
416 * ISR to handle the write processing. 415 * after irq received
417 * 416 *
418 * @dev: the device structure 417 * @dev: the device structure
419 * @cmpl_list: An instance of our list structure 418 * @cmpl_list: An instance of our list structure
420 * 419 *
421 * returns 0 on success, <0 on failure. 420 * returns 0 on success, <0 on failure.
422 */ 421 */
423static int mei_irq_thread_write_handler(struct mei_device *dev, 422int mei_irq_write_handler(struct mei_device *dev,
424 struct mei_cl_cb *cmpl_list) 423 struct mei_cl_cb *cmpl_list)
425{ 424{
426 425
@@ -666,112 +665,3 @@ out:
666 mutex_unlock(&dev->device_lock); 665 mutex_unlock(&dev->device_lock);
667} 666}
668 667
669/**
670 * mei_interrupt_thread_handler - function called after ISR to handle the interrupt
671 * processing.
672 *
673 * @irq: The irq number
674 * @dev_id: pointer to the device structure
675 *
676 * returns irqreturn_t
677 *
678 */
679irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
680{
681 struct mei_device *dev = (struct mei_device *) dev_id;
682 struct mei_cl_cb complete_list;
683 struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
684 struct mei_cl *cl;
685 s32 slots;
686 int rets;
687 bool bus_message_received;
688
689
690 dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
691 /* initialize our complete list */
692 mutex_lock(&dev->device_lock);
693 mei_io_list_init(&complete_list);
694
695 /* Ack the interrupt here
696 * In case of MSI we don't go through the quick handler */
697 if (pci_dev_msi_enabled(dev->pdev))
698 mei_clear_interrupts(dev);
699
700 /* check if ME wants a reset */
701 if (!mei_hw_is_ready(dev) &&
702 dev->dev_state != MEI_DEV_RESETING &&
703 dev->dev_state != MEI_DEV_INITIALIZING) {
704 dev_dbg(&dev->pdev->dev, "FW not ready.\n");
705 mei_reset(dev, 1);
706 mutex_unlock(&dev->device_lock);
707 return IRQ_HANDLED;
708 }
709
710 /* check if we need to start the dev */
711 if (!mei_host_is_ready(dev)) {
712 if (mei_hw_is_ready(dev)) {
713 dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
714
715 mei_host_set_ready(dev);
716
717 dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
718 /* link is established * start sending messages. */
719
720 dev->dev_state = MEI_DEV_INIT_CLIENTS;
721
722 mei_hbm_start_req(dev);
723 mutex_unlock(&dev->device_lock);
724 return IRQ_HANDLED;
725 } else {
726 dev_dbg(&dev->pdev->dev, "FW not ready.\n");
727 mutex_unlock(&dev->device_lock);
728 return IRQ_HANDLED;
729 }
730 }
731 /* check slots available for reading */
732 slots = mei_count_full_read_slots(dev);
733 while (slots > 0) {
734 /* we have urgent data to send so break the read */
735 if (dev->wr_ext_msg.hdr.length)
736 break;
737 dev_dbg(&dev->pdev->dev, "slots =%08x\n", slots);
738 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n");
739 rets = mei_irq_thread_read_handler(&complete_list, dev, &slots);
740 if (rets)
741 goto end;
742 }
743 rets = mei_irq_thread_write_handler(dev, &complete_list);
744end:
745 dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
746 dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev);
747
748 bus_message_received = false;
749 if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
750 dev_dbg(&dev->pdev->dev, "received waiting bus message\n");
751 bus_message_received = true;
752 }
753 mutex_unlock(&dev->device_lock);
754 if (bus_message_received) {
755 dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n");
756 wake_up_interruptible(&dev->wait_recvd_msg);
757 bus_message_received = false;
758 }
759 if (list_empty(&complete_list.list))
760 return IRQ_HANDLED;
761
762
763 list_for_each_entry_safe(cb_pos, cb_next, &complete_list.list, list) {
764 cl = cb_pos->cl;
765 list_del(&cb_pos->list);
766 if (cl) {
767 if (cl != &dev->iamthif_cl) {
768 dev_dbg(&dev->pdev->dev, "completing call back.\n");
769 _mei_cmpl(cl, cb_pos);
770 cb_pos = NULL;
771 } else if (cl == &dev->iamthif_cl) {
772 mei_amthif_complete(dev, cb_pos);
773 }
774 }
775 }
776 return IRQ_HANDLED;
777}
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index c974292f16d6..7d07cef75664 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -379,9 +379,14 @@ int mei_hw_init(struct mei_device *dev);
379/* 379/*
380 * MEI interrupt functions prototype 380 * MEI interrupt functions prototype
381 */ 381 */
382irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id); 382
383irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id);
384void mei_timer(struct work_struct *work); 383void mei_timer(struct work_struct *work);
384int mei_irq_read_handler(struct mei_device *dev,
385 struct mei_cl_cb *cmpl_list, s32 *slots);
386
387int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list);
388
389void mei_irq_complete_handler(struct mei_cl *cl, struct mei_cl_cb *cb_pos);
385 390
386/* 391/*
387 * AMTHIF - AMT Host Interface Functions 392 * AMTHIF - AMT Host Interface Functions
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 27ac71767981..b40ec0601ab0 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -170,12 +170,12 @@ static int mei_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
170 if (pci_dev_msi_enabled(pdev)) 170 if (pci_dev_msi_enabled(pdev))
171 err = request_threaded_irq(pdev->irq, 171 err = request_threaded_irq(pdev->irq,
172 NULL, 172 NULL,
173 mei_interrupt_thread_handler, 173 mei_me_irq_thread_handler,
174 IRQF_ONESHOT, KBUILD_MODNAME, dev); 174 IRQF_ONESHOT, KBUILD_MODNAME, dev);
175 else 175 else
176 err = request_threaded_irq(pdev->irq, 176 err = request_threaded_irq(pdev->irq,
177 mei_interrupt_quick_handler, 177 mei_me_irq_quick_handler,
178 mei_interrupt_thread_handler, 178 mei_me_irq_thread_handler,
179 IRQF_SHARED, KBUILD_MODNAME, dev); 179 IRQF_SHARED, KBUILD_MODNAME, dev);
180 180
181 if (err) { 181 if (err) {
@@ -348,12 +348,12 @@ static int mei_pci_resume(struct device *device)
348 if (pci_dev_msi_enabled(pdev)) 348 if (pci_dev_msi_enabled(pdev))
349 err = request_threaded_irq(pdev->irq, 349 err = request_threaded_irq(pdev->irq,
350 NULL, 350 NULL,
351 mei_interrupt_thread_handler, 351 mei_me_irq_thread_handler,
352 IRQF_ONESHOT, KBUILD_MODNAME, dev); 352 IRQF_ONESHOT, KBUILD_MODNAME, dev);
353 else 353 else
354 err = request_threaded_irq(pdev->irq, 354 err = request_threaded_irq(pdev->irq,
355 mei_interrupt_quick_handler, 355 mei_me_irq_quick_handler,
356 mei_interrupt_thread_handler, 356 mei_me_irq_thread_handler,
357 IRQF_SHARED, KBUILD_MODNAME, dev); 357 IRQF_SHARED, KBUILD_MODNAME, dev);
358 358
359 if (err) { 359 if (err) {