Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 355060
b: refs/heads/master
c: 06ecd64
h: refs/heads/master
v: v3
  • Loading branch information
Tomas Winkler authored and Greg Kroah-Hartman committed Feb 6, 2013
1 parent b34097e commit 167e3fd
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 151 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 827eef51f8dd9a4ab62b4ad270c15472f46938f2
refs/heads/master: 06ecd6459800962155c485e27d9dd30268b579bf
164 changes: 140 additions & 24 deletions trunk/drivers/misc/mei/hw-me.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,16 @@
*/

#include <linux/pci.h>
#include <linux/mei.h>

#include <linux/kthread.h>
#include <linux/interrupt.h>

#include "mei_dev.h"
#include "hw-me.h"

#include "hbm.h"


/**
* mei_reg_read - Reads 32bit data from the mei device
*
Expand Down Expand Up @@ -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;
}

/**
* 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
*
Expand Down Expand Up @@ -403,6 +385,139 @@ static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer,
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 = {

.host_set_ready = mei_me_host_set_ready,
Expand Down Expand Up @@ -458,3 +573,4 @@ struct mei_device *mei_me_dev_init(struct pci_dev *pdev)
dev->pdev = pdev;
return dev;
}

3 changes: 3 additions & 0 deletions trunk/drivers/misc/mei/hw-me.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,7 @@ static inline unsigned char mei_data2slots(size_t length)
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_ */
126 changes: 8 additions & 118 deletions trunk/drivers/misc/mei/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@


/**
* _mei_cmpl - processes completed operation.
* mei_complete_handler - processes completed operation.
*
* @cl: private data of the file object.
* @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) {
mei_io_cb_free(cb_pos);
Expand Down Expand Up @@ -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
* handle the read processing.
*
* @cmpl_list: An instance of our list structure
* @dev: the device structure
* @cmpl_list: An instance of our list structure
* @slots: slots to read.
*
* returns 0 on success, <0 on failure.
*/
static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list,
struct mei_device *dev,
s32 *slots)
int mei_irq_read_handler(struct mei_device *dev,
struct mei_cl_cb *cmpl_list, s32 *slots)
{
struct mei_msg_hdr *mei_hdr;
struct mei_cl *cl_pos = NULL;
Expand Down Expand Up @@ -412,15 +411,15 @@ static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list,


/**
* mei_irq_thread_write_handler - bottom half write routine after
* ISR to handle the write processing.
* mei_irq_write_handler - dispatch write requests
* after irq received
*
* @dev: the device structure
* @cmpl_list: An instance of our list structure
*
* 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)
{

Expand Down Expand Up @@ -666,112 +665,3 @@ void mei_timer(struct work_struct *work)
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;
}
9 changes: 7 additions & 2 deletions trunk/drivers/misc/mei/mei_dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,14 @@ int mei_hw_init(struct mei_device *dev);
/*
* 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);
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
Expand Down
Loading

0 comments on commit 167e3fd

Please sign in to comment.