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>
This commit is contained in:
parent
827eef51f8
commit
06ecd64598
|
@ -15,11 +15,16 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/mei.h>
|
|
||||||
|
#include <linux/kthread.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
|
||||||
#include "mei_dev.h"
|
#include "mei_dev.h"
|
||||||
#include "hw-me.h"
|
#include "hw-me.h"
|
||||||
|
|
||||||
|
#include "hbm.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mei_reg_read - Reads 32bit data from the mei device
|
* mei_reg_read - Reads 32bit data from the mei device
|
||||||
*
|
*
|
||||||
|
@ -217,29 +222,6 @@ static bool mei_me_hw_is_ready(struct mei_device *dev)
|
||||||
return (hw->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA;
|
return (hw->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* mei_interrupt_quick_handler - The ISR of the MEI device
|
|
||||||
*
|
|
||||||
* @irq: The irq number
|
|
||||||
* @dev_id: pointer to the device structure
|
|
||||||
*
|
|
||||||
* returns irqreturn_t
|
|
||||||
*/
|
|
||||||
irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id)
|
|
||||||
{
|
|
||||||
struct mei_device *dev = (struct mei_device *) dev_id;
|
|
||||||
struct mei_me_hw *hw = to_me_hw(dev);
|
|
||||||
u32 csr_reg = mei_hcsr_read(hw);
|
|
||||||
|
|
||||||
if ((csr_reg & H_IS) != H_IS)
|
|
||||||
return IRQ_NONE;
|
|
||||||
|
|
||||||
/* clear H_IS bit in H_CSR */
|
|
||||||
mei_reg_write(hw, H_CSR, csr_reg);
|
|
||||||
|
|
||||||
return IRQ_WAKE_THREAD;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mei_hbuf_filled_slots - gets number of device filled buffer slots
|
* mei_hbuf_filled_slots - gets number of device filled buffer slots
|
||||||
*
|
*
|
||||||
|
@ -403,6 +385,139 @@ static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mei_me_irq_quick_handler - The ISR of the MEI device
|
||||||
|
*
|
||||||
|
* @irq: The irq number
|
||||||
|
* @dev_id: pointer to the device structure
|
||||||
|
*
|
||||||
|
* returns irqreturn_t
|
||||||
|
*/
|
||||||
|
|
||||||
|
irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct mei_device *dev = (struct mei_device *) dev_id;
|
||||||
|
struct mei_me_hw *hw = to_me_hw(dev);
|
||||||
|
u32 csr_reg = mei_hcsr_read(hw);
|
||||||
|
|
||||||
|
if ((csr_reg & H_IS) != H_IS)
|
||||||
|
return IRQ_NONE;
|
||||||
|
|
||||||
|
/* clear H_IS bit in H_CSR */
|
||||||
|
mei_reg_write(hw, H_CSR, csr_reg);
|
||||||
|
|
||||||
|
return IRQ_WAKE_THREAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mei_me_irq_thread_handler - function called after ISR to handle the interrupt
|
||||||
|
* processing.
|
||||||
|
*
|
||||||
|
* @irq: The irq number
|
||||||
|
* @dev_id: pointer to the device structure
|
||||||
|
*
|
||||||
|
* returns irqreturn_t
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct mei_device *dev = (struct mei_device *) dev_id;
|
||||||
|
struct mei_cl_cb complete_list;
|
||||||
|
struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
|
||||||
|
struct mei_cl *cl;
|
||||||
|
s32 slots;
|
||||||
|
int rets;
|
||||||
|
bool bus_message_received;
|
||||||
|
|
||||||
|
|
||||||
|
dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
|
||||||
|
/* initialize our complete list */
|
||||||
|
mutex_lock(&dev->device_lock);
|
||||||
|
mei_io_list_init(&complete_list);
|
||||||
|
|
||||||
|
/* Ack the interrupt here
|
||||||
|
* In case of MSI we don't go through the quick handler */
|
||||||
|
if (pci_dev_msi_enabled(dev->pdev))
|
||||||
|
mei_clear_interrupts(dev);
|
||||||
|
|
||||||
|
/* check if ME wants a reset */
|
||||||
|
if (!mei_hw_is_ready(dev) &&
|
||||||
|
dev->dev_state != MEI_DEV_RESETING &&
|
||||||
|
dev->dev_state != MEI_DEV_INITIALIZING) {
|
||||||
|
dev_dbg(&dev->pdev->dev, "FW not ready.\n");
|
||||||
|
mei_reset(dev, 1);
|
||||||
|
mutex_unlock(&dev->device_lock);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if we need to start the dev */
|
||||||
|
if (!mei_host_is_ready(dev)) {
|
||||||
|
if (mei_hw_is_ready(dev)) {
|
||||||
|
dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
|
||||||
|
|
||||||
|
mei_host_set_ready(dev);
|
||||||
|
|
||||||
|
dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
|
||||||
|
/* link is established * start sending messages. */
|
||||||
|
|
||||||
|
dev->dev_state = MEI_DEV_INIT_CLIENTS;
|
||||||
|
|
||||||
|
mei_hbm_start_req(dev);
|
||||||
|
mutex_unlock(&dev->device_lock);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
} else {
|
||||||
|
dev_dbg(&dev->pdev->dev, "FW not ready.\n");
|
||||||
|
mutex_unlock(&dev->device_lock);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* check slots available for reading */
|
||||||
|
slots = mei_count_full_read_slots(dev);
|
||||||
|
while (slots > 0) {
|
||||||
|
/* we have urgent data to send so break the read */
|
||||||
|
if (dev->wr_ext_msg.hdr.length)
|
||||||
|
break;
|
||||||
|
dev_dbg(&dev->pdev->dev, "slots =%08x\n", slots);
|
||||||
|
dev_dbg(&dev->pdev->dev, "call mei_irq_read_handler.\n");
|
||||||
|
rets = mei_irq_read_handler(dev, &complete_list, &slots);
|
||||||
|
if (rets)
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
rets = mei_irq_write_handler(dev, &complete_list);
|
||||||
|
end:
|
||||||
|
dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
|
||||||
|
dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev);
|
||||||
|
|
||||||
|
bus_message_received = false;
|
||||||
|
if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
|
||||||
|
dev_dbg(&dev->pdev->dev, "received waiting bus message\n");
|
||||||
|
bus_message_received = true;
|
||||||
|
}
|
||||||
|
mutex_unlock(&dev->device_lock);
|
||||||
|
if (bus_message_received) {
|
||||||
|
dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n");
|
||||||
|
wake_up_interruptible(&dev->wait_recvd_msg);
|
||||||
|
bus_message_received = false;
|
||||||
|
}
|
||||||
|
if (list_empty(&complete_list.list))
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
|
||||||
|
|
||||||
|
list_for_each_entry_safe(cb_pos, cb_next, &complete_list.list, list) {
|
||||||
|
cl = cb_pos->cl;
|
||||||
|
list_del(&cb_pos->list);
|
||||||
|
if (cl) {
|
||||||
|
if (cl != &dev->iamthif_cl) {
|
||||||
|
dev_dbg(&dev->pdev->dev, "completing call back.\n");
|
||||||
|
mei_irq_complete_handler(cl, cb_pos);
|
||||||
|
cb_pos = NULL;
|
||||||
|
} else if (cl == &dev->iamthif_cl) {
|
||||||
|
mei_amthif_complete(dev, cb_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
static const struct mei_hw_ops mei_me_hw_ops = {
|
static const struct mei_hw_ops mei_me_hw_ops = {
|
||||||
|
|
||||||
.host_set_ready = mei_me_host_set_ready,
|
.host_set_ready = mei_me_host_set_ready,
|
||||||
|
@ -458,3 +573,4 @@ struct mei_device *mei_me_dev_init(struct pci_dev *pdev)
|
||||||
dev->pdev = pdev;
|
dev->pdev = pdev;
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,4 +42,7 @@ static inline unsigned char mei_data2slots(size_t length)
|
||||||
return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4);
|
return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id);
|
||||||
|
irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id);
|
||||||
|
|
||||||
#endif /* _MEI_INTERFACE_H_ */
|
#endif /* _MEI_INTERFACE_H_ */
|
||||||
|
|
|
@ -30,12 +30,12 @@
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _mei_cmpl - processes completed operation.
|
* mei_complete_handler - processes completed operation.
|
||||||
*
|
*
|
||||||
* @cl: private data of the file object.
|
* @cl: private data of the file object.
|
||||||
* @cb_pos: callback block.
|
* @cb_pos: callback block.
|
||||||
*/
|
*/
|
||||||
static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos)
|
void mei_irq_complete_handler(struct mei_cl *cl, struct mei_cl_cb *cb_pos)
|
||||||
{
|
{
|
||||||
if (cb_pos->fop_type == MEI_FOP_WRITE) {
|
if (cb_pos->fop_type == MEI_FOP_WRITE) {
|
||||||
mei_io_cb_free(cb_pos);
|
mei_io_cb_free(cb_pos);
|
||||||
|
@ -313,15 +313,14 @@ static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots,
|
||||||
* mei_irq_thread_read_handler - bottom half read routine after ISR to
|
* mei_irq_thread_read_handler - bottom half read routine after ISR to
|
||||||
* handle the read processing.
|
* handle the read processing.
|
||||||
*
|
*
|
||||||
* @cmpl_list: An instance of our list structure
|
|
||||||
* @dev: the device structure
|
* @dev: the device structure
|
||||||
|
* @cmpl_list: An instance of our list structure
|
||||||
* @slots: slots to read.
|
* @slots: slots to read.
|
||||||
*
|
*
|
||||||
* returns 0 on success, <0 on failure.
|
* returns 0 on success, <0 on failure.
|
||||||
*/
|
*/
|
||||||
static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list,
|
int mei_irq_read_handler(struct mei_device *dev,
|
||||||
struct mei_device *dev,
|
struct mei_cl_cb *cmpl_list, s32 *slots)
|
||||||
s32 *slots)
|
|
||||||
{
|
{
|
||||||
struct mei_msg_hdr *mei_hdr;
|
struct mei_msg_hdr *mei_hdr;
|
||||||
struct mei_cl *cl_pos = NULL;
|
struct mei_cl *cl_pos = NULL;
|
||||||
|
@ -412,15 +411,15 @@ end:
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mei_irq_thread_write_handler - bottom half write routine after
|
* mei_irq_write_handler - dispatch write requests
|
||||||
* ISR to handle the write processing.
|
* after irq received
|
||||||
*
|
*
|
||||||
* @dev: the device structure
|
* @dev: the device structure
|
||||||
* @cmpl_list: An instance of our list structure
|
* @cmpl_list: An instance of our list structure
|
||||||
*
|
*
|
||||||
* returns 0 on success, <0 on failure.
|
* returns 0 on success, <0 on failure.
|
||||||
*/
|
*/
|
||||||
static int mei_irq_thread_write_handler(struct mei_device *dev,
|
int mei_irq_write_handler(struct mei_device *dev,
|
||||||
struct mei_cl_cb *cmpl_list)
|
struct mei_cl_cb *cmpl_list)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -666,112 +665,3 @@ out:
|
||||||
mutex_unlock(&dev->device_lock);
|
mutex_unlock(&dev->device_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* mei_interrupt_thread_handler - function called after ISR to handle the interrupt
|
|
||||||
* processing.
|
|
||||||
*
|
|
||||||
* @irq: The irq number
|
|
||||||
* @dev_id: pointer to the device structure
|
|
||||||
*
|
|
||||||
* returns irqreturn_t
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
|
|
||||||
{
|
|
||||||
struct mei_device *dev = (struct mei_device *) dev_id;
|
|
||||||
struct mei_cl_cb complete_list;
|
|
||||||
struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
|
|
||||||
struct mei_cl *cl;
|
|
||||||
s32 slots;
|
|
||||||
int rets;
|
|
||||||
bool bus_message_received;
|
|
||||||
|
|
||||||
|
|
||||||
dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
|
|
||||||
/* initialize our complete list */
|
|
||||||
mutex_lock(&dev->device_lock);
|
|
||||||
mei_io_list_init(&complete_list);
|
|
||||||
|
|
||||||
/* Ack the interrupt here
|
|
||||||
* In case of MSI we don't go through the quick handler */
|
|
||||||
if (pci_dev_msi_enabled(dev->pdev))
|
|
||||||
mei_clear_interrupts(dev);
|
|
||||||
|
|
||||||
/* check if ME wants a reset */
|
|
||||||
if (!mei_hw_is_ready(dev) &&
|
|
||||||
dev->dev_state != MEI_DEV_RESETING &&
|
|
||||||
dev->dev_state != MEI_DEV_INITIALIZING) {
|
|
||||||
dev_dbg(&dev->pdev->dev, "FW not ready.\n");
|
|
||||||
mei_reset(dev, 1);
|
|
||||||
mutex_unlock(&dev->device_lock);
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check if we need to start the dev */
|
|
||||||
if (!mei_host_is_ready(dev)) {
|
|
||||||
if (mei_hw_is_ready(dev)) {
|
|
||||||
dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
|
|
||||||
|
|
||||||
mei_host_set_ready(dev);
|
|
||||||
|
|
||||||
dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
|
|
||||||
/* link is established * start sending messages. */
|
|
||||||
|
|
||||||
dev->dev_state = MEI_DEV_INIT_CLIENTS;
|
|
||||||
|
|
||||||
mei_hbm_start_req(dev);
|
|
||||||
mutex_unlock(&dev->device_lock);
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
} else {
|
|
||||||
dev_dbg(&dev->pdev->dev, "FW not ready.\n");
|
|
||||||
mutex_unlock(&dev->device_lock);
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* check slots available for reading */
|
|
||||||
slots = mei_count_full_read_slots(dev);
|
|
||||||
while (slots > 0) {
|
|
||||||
/* we have urgent data to send so break the read */
|
|
||||||
if (dev->wr_ext_msg.hdr.length)
|
|
||||||
break;
|
|
||||||
dev_dbg(&dev->pdev->dev, "slots =%08x\n", slots);
|
|
||||||
dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n");
|
|
||||||
rets = mei_irq_thread_read_handler(&complete_list, dev, &slots);
|
|
||||||
if (rets)
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
rets = mei_irq_thread_write_handler(dev, &complete_list);
|
|
||||||
end:
|
|
||||||
dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
|
|
||||||
dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev);
|
|
||||||
|
|
||||||
bus_message_received = false;
|
|
||||||
if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
|
|
||||||
dev_dbg(&dev->pdev->dev, "received waiting bus message\n");
|
|
||||||
bus_message_received = true;
|
|
||||||
}
|
|
||||||
mutex_unlock(&dev->device_lock);
|
|
||||||
if (bus_message_received) {
|
|
||||||
dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n");
|
|
||||||
wake_up_interruptible(&dev->wait_recvd_msg);
|
|
||||||
bus_message_received = false;
|
|
||||||
}
|
|
||||||
if (list_empty(&complete_list.list))
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
|
|
||||||
|
|
||||||
list_for_each_entry_safe(cb_pos, cb_next, &complete_list.list, list) {
|
|
||||||
cl = cb_pos->cl;
|
|
||||||
list_del(&cb_pos->list);
|
|
||||||
if (cl) {
|
|
||||||
if (cl != &dev->iamthif_cl) {
|
|
||||||
dev_dbg(&dev->pdev->dev, "completing call back.\n");
|
|
||||||
_mei_cmpl(cl, cb_pos);
|
|
||||||
cb_pos = NULL;
|
|
||||||
} else if (cl == &dev->iamthif_cl) {
|
|
||||||
mei_amthif_complete(dev, cb_pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
}
|
|
||||||
|
|
|
@ -379,9 +379,14 @@ int mei_hw_init(struct mei_device *dev);
|
||||||
/*
|
/*
|
||||||
* MEI interrupt functions prototype
|
* MEI interrupt functions prototype
|
||||||
*/
|
*/
|
||||||
irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id);
|
|
||||||
irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id);
|
|
||||||
void mei_timer(struct work_struct *work);
|
void mei_timer(struct work_struct *work);
|
||||||
|
int mei_irq_read_handler(struct mei_device *dev,
|
||||||
|
struct mei_cl_cb *cmpl_list, s32 *slots);
|
||||||
|
|
||||||
|
int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list);
|
||||||
|
|
||||||
|
void mei_irq_complete_handler(struct mei_cl *cl, struct mei_cl_cb *cb_pos);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AMTHIF - AMT Host Interface Functions
|
* AMTHIF - AMT Host Interface Functions
|
||||||
|
|
|
@ -170,12 +170,12 @@ static int mei_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
if (pci_dev_msi_enabled(pdev))
|
if (pci_dev_msi_enabled(pdev))
|
||||||
err = request_threaded_irq(pdev->irq,
|
err = request_threaded_irq(pdev->irq,
|
||||||
NULL,
|
NULL,
|
||||||
mei_interrupt_thread_handler,
|
mei_me_irq_thread_handler,
|
||||||
IRQF_ONESHOT, KBUILD_MODNAME, dev);
|
IRQF_ONESHOT, KBUILD_MODNAME, dev);
|
||||||
else
|
else
|
||||||
err = request_threaded_irq(pdev->irq,
|
err = request_threaded_irq(pdev->irq,
|
||||||
mei_interrupt_quick_handler,
|
mei_me_irq_quick_handler,
|
||||||
mei_interrupt_thread_handler,
|
mei_me_irq_thread_handler,
|
||||||
IRQF_SHARED, KBUILD_MODNAME, dev);
|
IRQF_SHARED, KBUILD_MODNAME, dev);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -348,12 +348,12 @@ static int mei_pci_resume(struct device *device)
|
||||||
if (pci_dev_msi_enabled(pdev))
|
if (pci_dev_msi_enabled(pdev))
|
||||||
err = request_threaded_irq(pdev->irq,
|
err = request_threaded_irq(pdev->irq,
|
||||||
NULL,
|
NULL,
|
||||||
mei_interrupt_thread_handler,
|
mei_me_irq_thread_handler,
|
||||||
IRQF_ONESHOT, KBUILD_MODNAME, dev);
|
IRQF_ONESHOT, KBUILD_MODNAME, dev);
|
||||||
else
|
else
|
||||||
err = request_threaded_irq(pdev->irq,
|
err = request_threaded_irq(pdev->irq,
|
||||||
mei_interrupt_quick_handler,
|
mei_me_irq_quick_handler,
|
||||||
mei_interrupt_thread_handler,
|
mei_me_irq_thread_handler,
|
||||||
IRQF_SHARED, KBUILD_MODNAME, dev);
|
IRQF_SHARED, KBUILD_MODNAME, dev);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
Loading…
Reference in New Issue