/*
*
* Intel Management Engine Interface (Intel MEI) Linux driver
* Copyright (c) 2003-2012, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#include <linux/pci.h>
#include <linux/kthread.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/jiffies.h>
#include "mei_dev.h"
#include <linux/mei.h>
#include "hw.h"
#include "interface.h"
/**
* 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;
u32 csr_reg = mei_hcsr_read(dev);
if ((csr_reg & H_IS) != H_IS)
return IRQ_NONE;
/* clear H_IS bit in H_CSR */
mei_reg_write(dev, H_CSR, csr_reg);
return IRQ_WAKE_THREAD;
}
/**
* _mei_cmpl - 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)
{
if (cb_pos->major_file_operations == MEI_WRITE) {
mei_io_cb_free(cb_pos);
cb_pos = NULL;
cl->writing_state = MEI_WRITE_COMPLETE;
if (waitqueue_active(&cl->tx_wait))
wake_up_interruptible(&cl->tx_wait);
} else if (cb_pos->major_file_operations == MEI_READ &&
MEI_READING == cl->reading_state) {
cl->reading_state = MEI_READ_COMPLETE;
if (waitqueue_active(&cl->rx_wait))
wake_up_interruptible(&cl->rx_wait);
}
}
/**
* _mei_irq_thread_state_ok - checks if mei header matches file private data
*
* @cl: private data of the file object
* @mei_hdr: header of mei client message
*
* returns !=0 if matches, 0 if no match.
*/
static int _mei_irq_thread_state_ok(struct mei_cl *cl,
struct mei_msg_hdr *mei_hdr)
{
return (cl->host_client_id == mei_hdr->host_addr &&
cl->me_client_id == mei_hdr->me_addr &&
cl->state == MEI_FILE_CONNECTED &&
MEI_READ_COMPLETE != cl->reading_state);
}
/**
* mei_irq_thread_read_client_message - bottom half read routine after ISR to
* handle the read mei client message data processing.
*
* @co