summaryrefslogtreecommitdiff
path: root/drivers/staging/mei
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/mei')
-rw-r--r--drivers/staging/mei/Kconfig28
-rw-r--r--drivers/staging/mei/Makefile11
-rw-r--r--drivers/staging/mei/TODO10
-rw-r--r--drivers/staging/mei/hw.h332
-rw-r--r--drivers/staging/mei/init.c735
-rw-r--r--drivers/staging/mei/interface.c428
-rw-r--r--drivers/staging/mei/interface.h76
-rw-r--r--drivers/staging/mei/interrupt.c1590
-rw-r--r--drivers/staging/mei/iorw.c590
-rw-r--r--drivers/staging/mei/main.c1237
-rw-r--r--drivers/staging/mei/mei-amt-version.c481
-rw-r--r--drivers/staging/mei/mei.h110
-rw-r--r--drivers/staging/mei/mei.txt215
-rw-r--r--drivers/staging/mei/mei_dev.h428
-rw-r--r--drivers/staging/mei/wd.c379
15 files changed, 0 insertions, 6650 deletions
diff --git a/drivers/staging/mei/Kconfig b/drivers/staging/mei/Kconfig
deleted file mode 100644
index 47d78a7..0000000
--- a/drivers/staging/mei/Kconfig
+++ /dev/null
@@ -1,28 +0,0 @@
-config INTEL_MEI
- tristate "Intel Management Engine Interface (Intel MEI)"
- depends on X86 && PCI && EXPERIMENTAL && WATCHDOG_CORE
- help
- The Intel Management Engine (Intel ME) provides Manageability,
- Security and Media services for system containing Intel chipsets.
- if selected /dev/mei misc device will be created.
-
- Supported Chipsets are:
- 7 Series Chipset Family
- 6 Series Chipset Family
- 5 Series Chipset Family
- 4 Series Chipset Family
- Mobile 4 Series Chipset Family
- ICH9
- 82946GZ/GL
- 82G35 Express
- 82Q963/Q965
- 82P965/G965
- Mobile PM965/GM965
- Mobile GME965/GLE960
- 82Q35 Express
- 82G33/G31/P35/P31 Express
- 82Q33 Express
- 82X38/X48 Express
-
- For more information see
- <http://software.intel.com/en-us/manageability/>
diff --git a/drivers/staging/mei/Makefile b/drivers/staging/mei/Makefile
deleted file mode 100644
index 57168db..0000000
--- a/drivers/staging/mei/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Makefile - Intel Management Engine Interface (Intel MEI) Linux driver
-# Copyright (c) 2010-2011, Intel Corporation.
-#
-obj-$(CONFIG_INTEL_MEI) += mei.o
-mei-objs := init.o
-mei-objs += interrupt.o
-mei-objs += interface.o
-mei-objs += iorw.o
-mei-objs += main.o
-mei-objs += wd.o
diff --git a/drivers/staging/mei/TODO b/drivers/staging/mei/TODO
deleted file mode 100644
index fc26601..0000000
--- a/drivers/staging/mei/TODO
+++ /dev/null
@@ -1,10 +0,0 @@
-TODO:
- - Cleanup and split the timer function
-Upon Unstaging:
- - move mei.h to include/linux/mei.h
- - Documentation/ioctl/ioctl-number.txt
- - move mei.txt under Documentation/mei/
- - move mei-amt-version.c under Documentation/mei
- - add hostprogs-y for mei-amt-version.c
- - drop mei_version.h
- - Updated MAINTAINERS
diff --git a/drivers/staging/mei/hw.h b/drivers/staging/mei/hw.h
deleted file mode 100644
index 24c4c96..0000000
--- a/drivers/staging/mei/hw.h
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef _MEI_HW_TYPES_H_
-#define _MEI_HW_TYPES_H_
-
-#include <linux/uuid.h>
-
-/*
- * Timeouts
- */
-#define MEI_INTEROP_TIMEOUT (HZ * 7)
-#define MEI_CONNECT_TIMEOUT 3 /* at least 2 seconds */
-
-#define CONNECT_TIMEOUT 15 /* HPS definition */
-#define INIT_CLIENTS_TIMEOUT 15 /* HPS definition */
-
-#define IAMTHIF_STALL_TIMER 12 /* seconds */
-#define IAMTHIF_READ_TIMER 10000 /* ms */
-
-/*
- * Internal Clients Number
- */
-#define MEI_WD_HOST_CLIENT_ID 1
-#define MEI_IAMTHIF_HOST_CLIENT_ID 2
-
-/*
- * MEI device IDs
- */
-#define MEI_DEV_ID_82946GZ 0x2974 /* 82946GZ/GL */
-#define MEI_DEV_ID_82G35 0x2984 /* 82G35 Express */
-#define MEI_DEV_ID_82Q965 0x2994 /* 82Q963/Q965 */
-#define MEI_DEV_ID_82G965 0x29A4 /* 82P965/G965 */
-
-#define MEI_DEV_ID_82GM965 0x2A04 /* Mobile PM965/GM965 */
-#define MEI_DEV_ID_82GME965 0x2A14 /* Mobile GME965/GLE960 */
-
-#define MEI_DEV_ID_ICH9_82Q35 0x29B4 /* 82Q35 Express */
-#define MEI_DEV_ID_ICH9_82G33 0x29C4 /* 82G33/G31/P35/P31 Express */
-#define MEI_DEV_ID_ICH9_82Q33 0x29D4 /* 82Q33 Express */
-#define MEI_DEV_ID_ICH9_82X38 0x29E4 /* 82X38/X48 Express */
-#define MEI_DEV_ID_ICH9_3200 0x29F4 /* 3200/3210 Server */
-
-#define MEI_DEV_ID_ICH9_6 0x28B4 /* Bearlake */
-#define MEI_DEV_ID_ICH9_7 0x28C4 /* Bearlake */
-#define MEI_DEV_ID_ICH9_8 0x28D4 /* Bearlake */
-#define MEI_DEV_ID_ICH9_9 0x28E4 /* Bearlake */
-#define MEI_DEV_ID_ICH9_10 0x28F4 /* Bearlake */
-
-#define MEI_DEV_ID_ICH9M_1 0x2A44 /* Cantiga */
-#define MEI_DEV_ID_ICH9M_2 0x2A54 /* Cantiga */
-#define MEI_DEV_ID_ICH9M_3 0x2A64 /* Cantiga */
-#define MEI_DEV_ID_ICH9M_4 0x2A74 /* Cantiga */
-
-#define MEI_DEV_ID_ICH10_1 0x2E04 /* Eaglelake */
-#define MEI_DEV_ID_ICH10_2 0x2E14 /* Eaglelake */
-#define MEI_DEV_ID_ICH10_3 0x2E24 /* Eaglelake */
-#define MEI_DEV_ID_ICH10_4 0x2E34 /* Eaglelake */
-
-#define MEI_DEV_ID_IBXPK_1 0x3B64 /* Calpella */
-#define MEI_DEV_ID_IBXPK_2 0x3B65 /* Calpella */
-
-#define MEI_DEV_ID_CPT_1 0x1C3A /* Cougerpoint */
-#define MEI_DEV_ID_PBG_1 0x1D3A /* PBG */
-
-#define MEI_DEV_ID_PPT_1 0x1E3A /* Pantherpoint PPT */
-#define MEI_DEV_ID_PPT_2 0x1CBA /* Pantherpoint PPT */
-#define MEI_DEV_ID_PPT_3 0x1DBA /* Pantherpoint PPT */
-
-
-/*
- * MEI HW Section
- */
-
-/* MEI registers */
-/* H_CB_WW - Host Circular Buffer (CB) Write Window register */
-#define H_CB_WW 0
-/* H_CSR - Host Control Status register */
-#define H_CSR 4
-/* ME_CB_RW - ME Circular Buffer Read Window register (read only) */
-#define ME_CB_RW 8
-/* ME_CSR_HA - ME Control Status Host Access register (read only) */
-#define ME_CSR_HA 0xC
-
-
-/* register bits of H_CSR (Host Control Status register) */
-/* Host Circular Buffer Depth - maximum number of 32-bit entries in CB */
-#define H_CBD 0xFF000000
-/* Host Circular Buffer Write Pointer */
-#define H_CBWP 0x00FF0000
-/* Host Circular Buffer Read Pointer */
-#define H_CBRP 0x0000FF00
-/* Host Reset */
-#define H_RST 0x00000010
-/* Host Ready */
-#define H_RDY 0x00000008
-/* Host Interrupt Generate */
-#define H_IG 0x00000004
-/* Host Interrupt Status */
-#define H_IS 0x00000002
-/* Host Interrupt Enable */
-#define H_IE 0x00000001
-
-
-/* register bits of ME_CSR_HA (ME Control Status Host Access register) */
-/* ME CB (Circular Buffer) Depth HRA (Host Read Access) - host read only
-access to ME_CBD */
-#define ME_CBD_HRA 0xFF000000
-/* ME CB Write Pointer HRA - host read only access to ME_CBWP */
-#define ME_CBWP_HRA 0x00FF0000
-/* ME CB Read Pointer HRA - host read only access to ME_CBRP */
-#define ME_CBRP_HRA 0x0000FF00
-/* ME Reset HRA - host read only access to ME_RST */
-#define ME_RST_HRA 0x00000010
-/* ME Ready HRA - host read only access to ME_RDY */
-#define ME_RDY_HRA 0x00000008
-/* ME Interrupt Generate HRA - host read only access to ME_IG */
-#define ME_IG_HRA 0x00000004
-/* ME Interrupt Status HRA - host read only access to ME_IS */
-#define ME_IS_HRA 0x00000002
-/* ME Interrupt Enable HRA - host read only access to ME_IE */
-#define ME_IE_HRA 0x00000001
-
-/*
- * MEI Version
- */
-#define HBM_MINOR_VERSION 0
-#define HBM_MAJOR_VERSION 1
-#define HBM_TIMEOUT 1 /* 1 second */
-
-/* Host bus message command opcode */
-#define MEI_HBM_CMD_OP_MSK 0x7f
-/* Host bus message command RESPONSE */
-#define MEI_HBM_CMD_RES_MSK 0x80
-
-/*
- * MEI Bus Message Command IDs
- */
-#define HOST_START_REQ_CMD 0x01
-#define HOST_START_RES_CMD 0x81
-
-#define HOST_STOP_REQ_CMD 0x02
-#define HOST_STOP_RES_CMD 0x82
-
-#define ME_STOP_REQ_CMD 0x03
-
-#define HOST_ENUM_REQ_CMD 0x04
-#define HOST_ENUM_RES_CMD 0x84
-
-#define HOST_CLIENT_PROPERTIES_REQ_CMD 0x05
-#define HOST_CLIENT_PROPERTIES_RES_CMD 0x85
-
-#define CLIENT_CONNECT_REQ_CMD 0x06
-#define CLIENT_CONNECT_RES_CMD 0x86
-
-#define CLIENT_DISCONNECT_REQ_CMD 0x07
-#define CLIENT_DISCONNECT_RES_CMD 0x87
-
-#define MEI_FLOW_CONTROL_CMD 0x08
-
-/*
- * MEI Stop Reason
- * used by hbm_host_stop_request.reason
- */
-enum mei_stop_reason_types {
- DRIVER_STOP_REQUEST = 0x00,
- DEVICE_D1_ENTRY = 0x01,
- DEVICE_D2_ENTRY = 0x02,
- DEVICE_D3_ENTRY = 0x03,
- SYSTEM_S1_ENTRY = 0x04,
- SYSTEM_S2_ENTRY = 0x05,
- SYSTEM_S3_ENTRY = 0x06,
- SYSTEM_S4_ENTRY = 0x07,
- SYSTEM_S5_ENTRY = 0x08
-};
-
-/*
- * Client Connect Status
- * used by hbm_client_connect_response.status
- */
-enum client_connect_status_types {
- CCS_SUCCESS = 0x00,
- CCS_NOT_FOUND = 0x01,
- CCS_ALREADY_STARTED = 0x02,
- CCS_OUT_OF_RESOURCES = 0x03,
- CCS_MESSAGE_SMALL = 0x04
-};
-
-/*
- * Client Disconnect Status
- */
-enum client_disconnect_status_types {
- CDS_SUCCESS = 0x00
-};
-
-/*
- * MEI BUS Interface Section
- */
-struct mei_msg_hdr {
- u32 me_addr:8;
- u32 host_addr:8;
- u32 length:9;
- u32 reserved:6;
- u32 msg_complete:1;
-} __packed;
-
-
-struct mei_bus_message {
- u8 hbm_cmd;
- u8 data[0];
-} __packed;
-
-struct hbm_version {
- u8 minor_version;
- u8 major_version;
-} __packed;
-
-struct hbm_host_version_request {
- u8 hbm_cmd;
- u8 reserved;
- struct hbm_version host_version;
-} __packed;
-
-struct hbm_host_version_response {
- u8 hbm_cmd;
- u8 host_version_supported;
- struct hbm_version me_max_version;
-} __packed;
-
-struct hbm_host_stop_request {
- u8 hbm_cmd;
- u8 reason;
- u8 reserved[2];
-} __packed;
-
-struct hbm_host_stop_response {
- u8 hbm_cmd;
- u8 reserved[3];
-} __packed;
-
-struct hbm_me_stop_request {
- u8 hbm_cmd;
- u8 reason;
- u8 reserved[2];
-} __packed;
-
-struct hbm_host_enum_request {
- u8 hbm_cmd;
- u8 reserved[3];
-} __packed;
-
-struct hbm_host_enum_response {
- u8 hbm_cmd;
- u8 reserved[3];
- u8 valid_addresses[32];
-} __packed;
-
-struct mei_client_properties {
- uuid_le protocol_name;
- u8 protocol_version;
- u8 max_number_of_connections;
- u8 fixed_address;
- u8 single_recv_buf;
- u32 max_msg_length;
-} __packed;
-
-struct hbm_props_request {
- u8 hbm_cmd;
- u8 address;
- u8 reserved[2];
-} __packed;
-
-
-struct hbm_props_response {
- u8 hbm_cmd;
- u8 address;
- u8 status;
- u8 reserved[1];
- struct mei_client_properties client_properties;
-} __packed;
-
-struct hbm_client_connect_request {
- u8 hbm_cmd;
- u8 me_addr;
- u8 host_addr;
- u8 reserved;
-} __packed;
-
-struct hbm_client_connect_response {
- u8 hbm_cmd;
- u8 me_addr;
- u8 host_addr;
- u8 status;
-} __packed;
-
-struct hbm_client_disconnect_request {
- u8 hbm_cmd;
- u8 me_addr;
- u8 host_addr;
- u8 reserved[1];
-} __packed;
-
-#define MEI_FC_MESSAGE_RESERVED_LENGTH 5
-
-struct hbm_flow_control {
- u8 hbm_cmd;
- u8 me_addr;
- u8 host_addr;
- u8 reserved[MEI_FC_MESSAGE_RESERVED_LENGTH];
-} __packed;
-
-struct mei_me_client {
- struct mei_client_properties props;
- u8 client_id;
- u8 mei_flow_ctrl_creds;
-} __packed;
-
-
-#endif
diff --git a/drivers/staging/mei/init.c b/drivers/staging/mei/init.c
deleted file mode 100644
index eab711f..0000000
--- a/drivers/staging/mei/init.c
+++ /dev/null
@@ -1,735 +0,0 @@
-/*
- *
- * 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/sched.h>
-#include <linux/wait.h>
-#include <linux/delay.h>
-
-#include "mei_dev.h"
-#include "hw.h"
-#include "interface.h"
-#include "mei.h"
-
-const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
- 0xa8, 0x46, 0xe0, 0xff, 0x65,
- 0x81, 0x4c);
-
-/**
- * mei_io_list_init - Sets up a queue list.
- *
- * @list: An instance io list structure
- * @dev: the device structure
- */
-void mei_io_list_init(struct mei_io_list *list)
-{
- /* initialize our queue list */
- INIT_LIST_HEAD(&list->mei_cb.cb_list);
-}
-
-/**
- * mei_io_list_flush - removes list entry belonging to cl.
- *
- * @list: An instance of our list structure
- * @cl: private data of the file object
- */
-void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl)
-{
- struct mei_cl_cb *pos;
- struct mei_cl_cb *next;
-
- list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) {
- if (pos->file_private) {
- struct mei_cl *cl_tmp;
- cl_tmp = (struct mei_cl *)pos->file_private;
- if (mei_cl_cmp_id(cl, cl_tmp))
- list_del(&pos->cb_list);
- }
- }
-}
-/**
- * mei_cl_flush_queues - flushes queue lists belonging to cl.
- *
- * @dev: the device structure
- * @cl: private data of the file object
- */
-int mei_cl_flush_queues(struct mei_cl *cl)
-{
- if (!cl || !cl->dev)
- return -EINVAL;
-
- dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n");
- mei_io_list_flush(&cl->dev->read_list, cl);
- mei_io_list_flush(&cl->dev->write_list, cl);
- mei_io_list_flush(&cl->dev->write_waiting_list, cl);
- mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
- mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
- mei_io_list_flush(&cl->dev->amthi_cmd_list, cl);
- mei_io_list_flush(&cl->dev->amthi_read_complete_list, cl);
- return 0;
-}
-
-
-
-/**
- * mei_reset_iamthif_params - initializes mei device iamthif
- *
- * @dev: the device structure
- */
-static void mei_reset_iamthif_params(struct mei_device *dev)
-{
- /* reset iamthif parameters. */
- dev->iamthif_current_cb = NULL;
- dev->iamthif_msg_buf_size = 0;
- dev->iamthif_msg_buf_index = 0;
- dev->iamthif_canceled = false;
- dev->iamthif_ioctl = false;
- dev->iamthif_state = MEI_IAMTHIF_IDLE;
- dev->iamthif_timer = 0;
-}
-
-/**
- * init_mei_device - allocates and initializes the mei device structure
- *
- * @pdev: The pci device structure
- *
- * returns The mei_device_device pointer on success, NULL on failure.
- */
-struct mei_device *mei_device_init(struct pci_dev *pdev)
-{
- struct mei_device *dev;
-
- dev = kzalloc(sizeof(struct mei_device), GFP_KERNEL);
- if (!dev)
- return NULL;
-
- /* setup our list array */
- INIT_LIST_HEAD(&dev->file_list);
- INIT_LIST_HEAD(&dev->wd_cl.link);
- INIT_LIST_HEAD(&dev->iamthif_cl.link);
- mutex_init(&dev->device_lock);
- init_waitqueue_head(&dev->wait_recvd_msg);
- init_waitqueue_head(&dev->wait_stop_wd);
- dev->mei_state = MEI_INITIALIZING;
- dev->iamthif_state = MEI_IAMTHIF_IDLE;
- dev->wd_interface_reg = false;
-
-
- mei_io_list_init(&dev->read_list);
- mei_io_list_init(&dev->write_list);
- mei_io_list_init(&dev->write_waiting_list);
- mei_io_list_init(&dev->ctrl_wr_list);
- mei_io_list_init(&dev->ctrl_rd_list);
- mei_io_list_init(&dev->amthi_cmd_list);
- mei_io_list_init(&dev->amthi_read_complete_list);
- dev->pdev = pdev;
- return dev;
-}
-
-/**
- * mei_hw_init - initializes host and fw to start work.
- *
- * @dev: the device structure
- *
- * returns 0 on success, <0 on failure.
- */
-int mei_hw_init(struct mei_device *dev)
-{
- int err = 0;
- int ret;
-
- mutex_lock(&dev->device_lock);
-
- dev->host_hw_state = mei_hcsr_read(dev);
- dev->me_hw_state = mei_mecsr_read(dev);
- dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, mestate = 0x%08x.\n",
- dev->host_hw_state, dev->me_hw_state);
-
- /* acknowledge interrupt and stop interupts */
- if ((dev->host_hw_state & H_IS) == H_IS)
- mei_reg_write(dev, H_CSR, dev->host_hw_state);
-
- dev->recvd_msg = false;
- dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n");
-
- mei_reset(dev, 1);
-
- dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
- dev->host_hw_state, dev->me_hw_state);
-
- /* wait for ME to turn on ME_RDY */
- if (!dev->recvd_msg) {
- mutex_unlock(&dev->device_lock);
- err = wait_event_interruptible_timeout(dev->wait_recvd_msg,
- dev->recvd_msg, MEI_INTEROP_TIMEOUT);
- mutex_lock(&dev->device_lock);
- }
-
- if (err <= 0 && !dev->recvd_msg) {
- dev->mei_state = MEI_DISABLED;
- dev_dbg(&dev->pdev->dev,
- "wait_event_interruptible_timeout failed"
- "on wait for ME to turn on ME_RDY.\n");
- ret = -ENODEV;
- goto out;
- }
-
- if (!(((dev->host_hw_state & H_RDY) == H_RDY) &&
- ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) {
- dev->mei_state = MEI_DISABLED;
- dev_dbg(&dev->pdev->dev,
- "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
- dev->host_hw_state, dev->me_hw_state);
-
- if (!(dev->host_hw_state & H_RDY))
- dev_dbg(&dev->pdev->dev, "host turn off H_RDY.\n");
-
- if (!(dev->me_hw_state & ME_RDY_HRA))
- dev_dbg(&dev->pdev->dev, "ME turn off ME_RDY.\n");
-
- printk(KERN_ERR "mei: link layer initialization failed.\n");
- ret = -ENODEV;
- goto out;
- }
-
- if (dev->version.major_version != HBM_MAJOR_VERSION ||
- dev->version.minor_version != HBM_MINOR_VERSION) {
- dev_dbg(&dev->pdev->dev, "MEI start failed.\n");
- ret = -ENODEV;
- goto out;
- }
-
- dev->recvd_msg = false;
- dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
- dev->host_hw_state, dev->me_hw_state);
- dev_dbg(&dev->pdev->dev, "ME turn on ME_RDY and host turn on H_RDY.\n");
- dev_dbg(&dev->pdev->dev, "link layer has been established.\n");
- dev_dbg(&dev->pdev->dev, "MEI start success.\n");
- ret = 0;
-
-out:
- mutex_unlock(&dev->device_lock);
- return ret;
-}
-
-/**
- * mei_hw_reset - resets fw via mei csr register.
- *
- * @dev: the device structure
- * @interrupts_enabled: if interrupt should be enabled after reset.
- */
-static void mei_hw_reset(struct mei_device *dev, int interrupts_enabled)
-{
- dev->host_hw_state |= (H_RST | H_IG);
-
- if (interrupts_enabled)
- mei_enable_interrupts(dev);
- else
- mei_disable_interrupts(dev);
-}
-
-/**
- * mei_reset - resets host and fw.
- *
- * @dev: the device structure
- * @interrupts_enabled: if interrupt should be enabled after reset.
- */
-void mei_reset(struct mei_device *dev, int interrupts_enabled)
-{
- struct mei_cl *cl_pos = NULL;
- struct mei_cl *cl_next = NULL;
- struct mei_cl_cb *cb_pos = NULL;
- struct mei_cl_cb *cb_next = NULL;
- bool unexpected;
-
- if (dev->mei_state == MEI_RECOVERING_FROM_RESET) {
- dev->need_reset = true;
- return;
- }
-
- unexpected = (dev->mei_state != MEI_INITIALIZING &&
- dev->mei_state != MEI_DISABLED &&
- dev->mei_state != MEI_POWER_DOWN &&
- dev->mei_state != MEI_POWER_UP);
-
- dev->host_hw_state = mei_hcsr_read(dev);
-
- dev_dbg(&dev->pdev->dev, "before reset host_hw_state = 0x%08x.\n",
- dev->host_hw_state);
-
- mei_hw_reset(dev, interrupts_enabled);
-
- dev->host_hw_state &= ~H_RST;
- dev->host_hw_state |= H_IG;
-
- mei_hcsr_set(dev);
-
- dev_dbg(&dev->pdev->dev, "currently saved host_hw_state = 0x%08x.\n",
- dev->host_hw_state);
-
- dev->need_reset = false;
-
- if (dev->mei_state != MEI_INITIALIZING) {
- if (dev->mei_state != MEI_DISABLED &&
- dev->mei_state != MEI_POWER_DOWN)
- dev->mei_state = MEI_RESETING;
-
- list_for_each_entry_safe(cl_pos,
- cl_next, &dev->file_list, link) {
- cl_pos->state = MEI_FILE_DISCONNECTED;
- cl_pos->mei_flow_ctrl_creds = 0;
- cl_pos->read_cb = NULL;
- cl_pos->timer_count = 0;
- }
- /* remove entry if already in list */
- dev_dbg(&dev->pdev->dev, "list del iamthif and wd file list.\n");
- mei_remove_client_from_file_list(dev,
- dev->wd_cl.host_client_id);
-
- mei_remove_client_from_file_list(dev,
- dev->iamthif_cl.host_client_id);
-
- mei_reset_iamthif_params(dev);
- dev->wd_due_counter = 0;
- dev->extra_write_index = 0;
- }
-
- dev->me_clients_num = 0;
- dev->rd_msg_hdr = 0;
- dev->stop = false;
- dev->wd_pending = false;
-
- /* update the state of the registers after reset */
- dev->host_hw_state = mei_hcsr_read(dev);
- dev->me_hw_state = mei_mecsr_read(dev);
-
- dev_dbg(&dev->pdev->dev, "after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
- dev->host_hw_state, dev->me_hw_state);
-
- if (unexpected)
- dev_warn(&dev->pdev->dev, "unexpected reset.\n");
-
- /* Wake up all readings so they can be interrupted */
- list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
- if (waitqueue_active(&cl_pos->rx_wait)) {
- dev_dbg(&dev->pdev->dev, "Waking up client!\n");
- wake_up_interruptible(&cl_pos->rx_wait);
- }
- }
- /* remove all waiting requests */
- list_for_each_entry_safe(cb_pos, cb_next,
- &dev->write_list.mei_cb.cb_list, cb_list) {
- list_del(&cb_pos->cb_list);
- mei_free_cb_private(cb_pos);
- }
-}
-
-
-
-/**
- * host_start_message - mei host sends start message.
- *
- * @dev: the device structure
- *
- * returns none.
- */
-void mei_host_start_message(struct mei_device *dev)
-{
- struct mei_msg_hdr *mei_hdr;
- struct hbm_host_version_request *host_start_req;
-
- /* host start message */
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- mei_hdr->host_addr = 0;
- mei_hdr->me_addr = 0;
- mei_hdr->length = sizeof(struct hbm_host_version_request);
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
-
- host_start_req =
- (struct hbm_host_version_request *) &dev->wr_msg_buf[1];
- memset(host_start_req, 0, sizeof(struct hbm_host_version_request));
- host_start_req->hbm_cmd = HOST_START_REQ_CMD;
- host_start_req->host_version.major_version = HBM_MAJOR_VERSION;
- host_start_req->host_version.minor_version = HBM_MINOR_VERSION;
- dev->recvd_msg = false;
- if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req,
- mei_hdr->length)) {
- dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n");
- dev->mei_state = MEI_RESETING;
- mei_reset(dev, 1);
- }
- dev->init_clients_state = MEI_START_MESSAGE;
- dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
- return ;
-}
-
-/**
- * host_enum_clients_message - host sends enumeration client request message.
- *
- * @dev: the device structure
- *
- * returns none.
- */
-void mei_host_enum_clients_message(struct mei_device *dev)
-{
- struct mei_msg_hdr *mei_hdr;
- struct hbm_host_enum_request *host_enum_req;
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- /* enumerate clients */
- mei_hdr->host_addr = 0;
- mei_hdr->me_addr = 0;
- mei_hdr->length = sizeof(struct hbm_host_enum_request);
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
-
- host_enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1];
- memset(host_enum_req, 0, sizeof(struct hbm_host_enum_request));
- host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
- if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req,
- mei_hdr->length)) {
- dev->mei_state = MEI_RESETING;
- dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
- mei_reset(dev, 1);
- }
- dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE;
- dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
- return;
-}
-
-
-/**
- * allocate_me_clients_storage - allocates storage for me clients
- *
- * @dev: the device structure
- *
- * returns none.
- */
-void mei_allocate_me_clients_storage(struct mei_device *dev)
-{
- struct mei_me_client *clients;
- int b;
-
- /* count how many ME clients we have */
- for_each_set_bit(b, dev->me_clients_map, MEI_CLIENTS_MAX)
- dev->me_clients_num++;
-
- if (dev->me_clients_num <= 0)
- return ;
-
-
- if (dev->me_clients != NULL) {
- kfree(dev->me_clients);
- dev->me_clients = NULL;
- }
- dev_dbg(&dev->pdev->dev, "memory allocation for ME clients size=%zd.\n",
- dev->me_clients_num * sizeof(struct mei_me_client));
- /* allocate storage for ME clients representation */
- clients = kcalloc(dev->me_clients_num,
- sizeof(struct mei_me_client), GFP_KERNEL);
- if (!clients) {
- dev_dbg(&dev->pdev->dev, "memory allocation for ME clients failed.\n");
- dev->mei_state = MEI_RESETING;
- mei_reset(dev, 1);
- return ;
- }
- dev->me_clients = clients;
- return ;
-}
-/**
- * host_client_properties - reads properties for client
- *
- * @dev: the device structure
- *
- * returns:
- * < 0 - Error.
- * = 0 - no more clients.
- * = 1 - still have clients to send properties request.
- */
-int mei_host_client_properties(struct mei_device *dev)
-{
- struct mei_msg_hdr *mei_header;
- struct hbm_props_request *host_cli_req;
- int b;
- u8 client_num = dev->me_client_presentation_num;
-
- b = dev->me_client_index;
- b = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, b);
- if (b < MEI_CLIENTS_MAX) {
- dev->me_clients[client_num].client_id = b;
- dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
- mei_header = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
- mei_header->host_addr = 0;
- mei_header->me_addr = 0;
- mei_header->length = sizeof(struct hbm_props_request);
- mei_header->msg_complete = 1;
- mei_header->reserved = 0;
-
- host_cli_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];
-
- memset(host_cli_req, 0, sizeof(struct hbm_props_request));
-
- host_cli_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
- host_cli_req->address = b;
-
- if (mei_write_message(dev, mei_header,
- (unsigned char *)host_cli_req,
- mei_header->length)) {
- dev->mei_state = MEI_RESETING;
- dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
- mei_reset(dev, 1);
- return -EIO;
- }
-
- dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
- dev->me_client_index = b;
- return 1;
- }
-
- return 0;
-}
-
-/**
- * mei_init_file_private - initializes private file structure.
- *
- * @priv: private file structure to be initialized
- * @file: the file structure
- */
-void mei_cl_init(struct mei_cl *priv, struct mei_device *dev)
-{
- memset(priv, 0, sizeof(struct mei_cl));
- init_waitqueue_head(&priv->wait);
- init_waitqueue_head(&priv->rx_wait);
- init_waitqueue_head(&priv->tx_wait);
- INIT_LIST_HEAD(&priv->link);
- priv->reading_state = MEI_IDLE;
- priv->writing_state = MEI_IDLE;
- priv->dev = dev;
-}
-
-int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid)
-{
- int i, res = -1;
-
- for (i = 0; i < dev->me_clients_num; ++i)
- if (uuid_le_cmp(cuuid,
- dev->me_clients[i].props.protocol_name) == 0) {
- res = i;
- break;
- }
-
- return res;
-}
-
-
-/**
- * mei_find_me_client_update_filext - searches for ME client guid
- * sets client_id in mei_file_private if found
- * @dev: the device structure
- * @priv: private file structure to set client_id in
- * @cguid: searched guid of ME client
- * @client_id: id of host client to be set in file private structure
- *
- * returns ME client index
- */
-u8 mei_find_me_client_update_filext(struct mei_device *dev, struct mei_cl *priv,
- const uuid_le *cguid, u8 client_id)
-{
- int i;
-
- if (!dev || !priv || !cguid)
- return 0;
-
- /* check for valid client id */
- i = mei_find_me_client_index(dev, *cguid);
- if (i >= 0) {
- priv->me_client_id = dev->me_clients[i].client_id;
- priv->state = MEI_FILE_CONNECTING;
- priv->host_client_id = client_id;
-
- list_add_tail(&priv->link, &dev->file_list);
- return (u8)i;
- }
-
- return 0;
-}
-
-/**
- * host_init_iamthif - mei initialization iamthif client.
- *
- * @dev: the device structure
- *
- */
-void mei_host_init_iamthif(struct mei_device *dev)
-{
- u8 i;
- unsigned char *msg_buf;
-
- mei_cl_init(&dev->iamthif_cl, dev);
- dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
-
- /* find ME amthi client */
- i = mei_find_me_client_update_filext(dev, &dev->iamthif_cl,
- &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID);
- if (dev->iamthif_cl.state != MEI_FILE_CONNECTING) {
- dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n");
- return;
- }
-
- /* Assign iamthif_mtu to the value received from ME */
-
- dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length;
- dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n",
- dev->me_clients[i].props.max_msg_length);
-
- kfree(dev->iamthif_msg_buf);
- dev->iamthif_msg_buf = NULL;
-
- /* allocate storage for ME message buffer */
- msg_buf = kcalloc(dev->iamthif_mtu,
- sizeof(unsigned char), GFP_KERNEL);
- if (!msg_buf) {
- dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n");
- return;
- }
-
- dev->iamthif_msg_buf = msg_buf;
-
- if (mei_connect(dev, &dev->iamthif_cl)) {
- dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n");
- dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
- dev->iamthif_cl.host_client_id = 0;
- } else {
- dev->iamthif_cl.timer_count = CONNECT_TIMEOUT;
- }
-}
-
-/**
- * mei_alloc_file_private - allocates a private file structure and sets it up.
- * @file: the file structure
- *
- * returns The allocated file or NULL on failure
- */
-struct mei_cl *mei_cl_allocate(struct mei_device *dev)
-{
- struct mei_cl *cl;
-
- cl = kmalloc(sizeof(struct mei_cl), GFP_KERNEL);
- if (!cl)
- return NULL;
-
- mei_cl_init(cl, dev);
-
- return cl;
-}
-
-
-
-/**
- * mei_disconnect_host_client - sends disconnect message to fw from host client.
- *
- * @dev: the device structure
- * @cl: private data of the file object
- *
- * Locking: called under "dev->device_lock" lock
- *
- * returns 0 on success, <0 on failure.
- */
-int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
-{
- int rets, err;
- long timeout = 15; /* 15 seconds */
- struct mei_cl_cb *cb;
-
- if (!dev || !cl)
- return -ENODEV;
-
- if (cl->state != MEI_FILE_DISCONNECTING)
- return 0;
-
- cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
- if (!cb)
- return -ENOMEM;
-
- INIT_LIST_HEAD(&cb->cb_list);
- cb->file_private = cl;
- cb->major_file_operations = MEI_CLOSE;
- if (dev->mei_host_buffer_is_empty) {
- dev->mei_host_buffer_is_empty = false;
- if (mei_disconnect(dev, cl)) {
- rets = -ENODEV;
- dev_dbg(&dev->pdev->dev, "failed to call mei_disconnect.\n");
- goto free;
- }
- mdelay(10); /* Wait for hardware disconnection ready */
- list_add_tail(&cb->cb_list, &dev->ctrl_rd_list.mei_cb.cb_list);
- } else {
- dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n");
- list_add_tail(&cb->cb_list,
- &dev->ctrl_wr_list.mei_cb.cb_list);
- }
- mutex_unlock(&dev->device_lock);
-
- err = wait_event_timeout(dev->wait_recvd_msg,
- (MEI_FILE_DISCONNECTED == cl->state),
- timeout * HZ);
-
- mutex_lock(&dev->device_lock);
- if (MEI_FILE_DISCONNECTED == cl->state) {
- rets = 0;
- dev_dbg(&dev->pdev->dev, "successfully disconnected from FW client.\n");
- } else {
- rets = -ENODEV;
- if (MEI_FILE_DISCONNECTED != cl->state)
- dev_dbg(&dev->pdev->dev, "wrong status client disconnect.\n");
-
- if (err)
- dev_dbg(&dev->pdev->dev,
- "wait failed disconnect err=%08x\n",
- err);
-
- dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n");
- }
-
- mei_io_list_flush(&dev->ctrl_rd_list, cl);
- mei_io_list_flush(&dev->ctrl_wr_list, cl);
-free:
- mei_free_cb_private(cb);
- return rets;
-}
-
-/**
- * mei_remove_client_from_file_list -
- * removes file private data from device file list
- *
- * @dev: the device structure
- * @host_client_id: host client id to be removed
- */
-void mei_remove_client_from_file_list(struct mei_device *dev,
- u8 host_client_id)
-{
- struct mei_cl *cl_pos = NULL;
- struct mei_cl *cl_next = NULL;
- list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
- if (host_client_id == cl_pos->host_client_id) {
- dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n",
- cl_pos->host_client_id,
- cl_pos->me_client_id);
- list_del_init(&cl_pos->link);
- break;
- }
- }
-}
diff --git a/drivers/staging/mei/interface.c b/drivers/staging/mei/interface.c
deleted file mode 100644
index 9a2cfaf..0000000
--- a/drivers/staging/mei/interface.c
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- *
- * 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 "mei_dev.h"
-#include "mei.h"
-#include "interface.h"
-
-
-
-/**
- * mei_set_csr_register - writes H_CSR register to the mei device,
- * and ignores the H_IS bit for it is write-one-to-zero.
- *
- * @dev: the device structure
- */
-void mei_hcsr_set(struct mei_device *dev)
-{
- if ((dev->host_hw_state & H_IS) == H_IS)
- dev->host_hw_state &= ~H_IS;
- mei_reg_write(dev, H_CSR, dev->host_hw_state);
- dev->host_hw_state = mei_hcsr_read(dev);
-}
-
-/**
- * mei_csr_enable_interrupts - enables mei device interrupts
- *
- * @dev: the device structure
- */
-void mei_enable_interrupts(struct mei_device *dev)
-{
- dev->host_hw_state |= H_IE;
- mei_hcsr_set(dev);
-}
-
-/**
- * mei_csr_disable_interrupts - disables mei device interrupts
- *
- * @dev: the device structure
- */
-void mei_disable_interrupts(struct mei_device *dev)
-{
- dev->host_hw_state &= ~H_IE;
- mei_hcsr_set(dev);
-}
-
-/**
- * _host_get_filled_slots - gets number of device filled buffer slots
- *
- * @device: the device structure
- *
- * returns number of filled slots
- */
-static unsigned char _host_get_filled_slots(const struct mei_device *dev)
-{
- char read_ptr, write_ptr;
-
- read_ptr = (char) ((dev->host_hw_state & H_CBRP) >> 8);
- write_ptr = (char) ((dev->host_hw_state & H_CBWP) >> 16);
-
- return (unsigned char) (write_ptr - read_ptr);
-}
-
-/**
- * mei_host_buffer_is_empty - checks if host buffer is empty.
- *
- * @dev: the device structure
- *
- * returns 1 if empty, 0 - otherwise.
- */
-int mei_host_buffer_is_empty(struct mei_device *dev)
-{
- unsigned char filled_slots;
-
- dev->host_hw_state = mei_hcsr_read(dev);
- filled_slots = _host_get_filled_slots(dev);
-
- if (filled_slots == 0)
- return 1;
-
- return 0;
-}
-
-/**
- * mei_count_empty_write_slots - counts write empty slots.
- *
- * @dev: the device structure
- *
- * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count
- */
-int mei_count_empty_write_slots(struct mei_device *dev)
-{
- unsigned char buffer_depth, filled_slots, empty_slots;
-
- dev->host_hw_state = mei_hcsr_read(dev);
- buffer_depth = (unsigned char) ((dev->host_hw_state & H_CBD) >> 24);
- filled_slots = _host_get_filled_slots(dev);
- empty_slots = buffer_depth - filled_slots;
-
- /* check for overflow */
- if (filled_slots > buffer_depth)
- return -EOVERFLOW;
-
- return empty_slots;
-}
-
-/**
- * mei_write_message - writes a message to mei device.
- *
- * @dev: the device structure
- * @header: header of message
- * @write_buffer: message buffer will be written
- * @write_length: message size will be written
- *
- * This function returns -EIO if write has failed
- */
-int mei_write_message(struct mei_device *dev,
- struct mei_msg_hdr *header,
- unsigned char *write_buffer,
- unsigned long write_length)
-{
- u32 temp_msg = 0;
- unsigned long bytes_written = 0;
- unsigned char buffer_depth, filled_slots, empty_slots;
- unsigned long dw_to_write;
-
- dev->host_hw_state = mei_hcsr_read(dev);
-
- dev_dbg(&dev->pdev->dev,
- "host_hw_state = 0x%08x.\n",
- dev->host_hw_state);
-
- dev_dbg(&dev->pdev->dev,
- "mei_write_message header=%08x.\n",
- *((u32 *) header));
-
- buffer_depth = (unsigned char) ((dev->host_hw_state & H_CBD) >> 24);
- filled_slots = _host_get_filled_slots(dev);
- empty_slots = buffer_depth - filled_slots;
- dev_dbg(&dev->pdev->dev,
- "filled = %hu, empty = %hu.\n",
- filled_slots, empty_slots);
-
- dw_to_write = ((write_length + 3) / 4);
-
- if (dw_to_write > empty_slots)
- return -EIO;
-
- mei_reg_write(dev, H_CB_WW, *((u32 *) header));
-
- while (write_length >= 4) {
- mei_reg_write(dev, H_CB_WW,
- *(u32 *) (write_buffer + bytes_written));
- bytes_written += 4;
- write_length -= 4;
- }
-
- if (write_length > 0) {
- memcpy(&temp_msg, &write_buffer[bytes_written], write_length);
- mei_reg_write(dev, H_CB_WW, temp_msg);
- }
-
- dev->host_hw_state |= H_IG;
- mei_hcsr_set(dev);
- dev->me_hw_state = mei_mecsr_read(dev);
- if ((dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA)
- return -EIO;
-
- return 0;
-}
-
-/**
- * mei_count_full_read_slots - counts read full slots.
- *
- * @dev: the device structure
- *
- * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise filled slots count
- */
-int mei_count_full_read_slots(struct mei_device *dev)
-{
- char read_ptr, write_ptr;
- unsigned char buffer_depth, filled_slots;
-
- dev->me_hw_state = mei_mecsr_read(dev);
- buffer_depth = (unsigned char)((dev->me_hw_state & ME_CBD_HRA) >> 24);
- read_ptr = (char) ((dev->me_hw_state & ME_CBRP_HRA) >> 8);
- write_ptr = (char) ((dev->me_hw_state & ME_CBWP_HRA) >> 16);
- filled_slots = (unsigned char) (write_ptr - read_ptr);
-
- /* check for overflow */
- if (filled_slots > buffer_depth)
- return -EOVERFLOW;
-
- dev_dbg(&dev->pdev->dev, "filled_slots =%08x\n", filled_slots);
- return (int)filled_slots;
-}
-
-/**
- * mei_read_slots - reads a message from mei device.
- *
- * @dev: the device structure
- * @buffer: message buffer will be written
- * @buffer_length: message size will be read
- */
-void mei_read_slots(struct mei_device *dev, unsigned char *buffer,
- unsigned long buffer_length)
-{
- u32 *reg_buf = (u32 *)buffer;
-
- for (; buffer_length >= sizeof(u32); buffer_length -= sizeof(u32))
- *reg_buf++ = mei_mecbrw_read(dev);
-
- if (buffer_length > 0) {
- u32 reg = mei_mecbrw_read(dev);
- memcpy(reg_buf, &reg, buffer_length);
- }
-
- dev->host_hw_state |= H_IG;
- mei_hcsr_set(dev);
-}
-
-/**
- * mei_flow_ctrl_creds - checks flow_control credentials.
- *
- * @dev: the device structure
- * @cl: private data of the file object
- *
- * returns 1 if mei_flow_ctrl_creds >0, 0 - otherwise.
- * -ENOENT if mei_cl is not present
- * -EINVAL if single_recv_buf == 0
- */
-int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl)
-{
- int i;
-
- if (!dev->me_clients_num)
- return 0;
-
- if (cl->mei_flow_ctrl_creds > 0)
- return 1;
-
- for (i = 0; i < dev->me_clients_num; i++) {
- struct mei_me_client *me_cl = &dev->me_clients[i];
- if (me_cl->client_id == cl->me_client_id) {
- if (me_cl->mei_flow_ctrl_creds) {
- if (WARN_ON(me_cl->props.single_recv_buf == 0))
- return -EINVAL;
- return 1;
- } else {
- return 0;
- }
- }
- }
- return -ENOENT;
-}
-
-/**
- * mei_flow_ctrl_reduce - reduces flow_control.
- *
- * @dev: the device structure
- * @cl: private data of the file object
- * @returns
- * 0 on success
- * -ENOENT when me client is not found
- * -EINVAL when ctrl credits are <= 0
- */
-int mei_flow_ctrl_reduce(struct mei_device *dev, struct mei_cl *cl)
-{
- int i;
-
- if (!dev->me_clients_num)
- return -ENOENT;
-
- for (i = 0; i < dev->me_clients_num; i++) {
- struct mei_me_client *me_cl = &dev->me_clients[i];
- if (me_cl->client_id == cl->me_client_id) {
- if (me_cl->props.single_recv_buf != 0) {
- if (WARN_ON(me_cl->mei_flow_ctrl_creds <= 0))
- return -EINVAL;
- dev->me_clients[i].mei_flow_ctrl_creds--;
- } else {
- if (WARN_ON(cl->mei_flow_ctrl_creds <= 0))
- return -EINVAL;
- cl->mei_flow_ctrl_creds--;
- }
- return 0;
- }
- }
- return -ENOENT;
-}
-
-/**
- * mei_send_flow_control - sends flow control to fw.
- *
- * @dev: the device structure
- * @cl: private data of the file object
- *
- * This function returns -EIO on write failure
- */
-int mei_send_flow_control(struct mei_device *dev, struct mei_cl *cl)
-{
- struct mei_msg_hdr *mei_hdr;
- struct hbm_flow_control *mei_flow_control;
-
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- mei_hdr->host_addr = 0;
- mei_hdr->me_addr = 0;
- mei_hdr->length = sizeof(struct hbm_flow_control);
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
-
- mei_flow_control = (struct hbm_flow_control *) &dev->wr_msg_buf[1];
- memset(mei_flow_control, 0, sizeof(*mei_flow_control));
- mei_flow_control->host_addr = cl->host_client_id;
- mei_flow_control->me_addr = cl->me_client_id;
- mei_flow_control->hbm_cmd = MEI_FLOW_CONTROL_CMD;
- memset(mei_flow_control->reserved, 0,
- sizeof(mei_flow_control->reserved));
- dev_dbg(&dev->pdev->dev, "sending flow control host client = %d, ME client = %d\n",
- cl->host_client_id, cl->me_client_id);
-
- return mei_write_message(dev, mei_hdr,
- (unsigned char *) mei_flow_control,
- sizeof(struct hbm_flow_control));
-}
-
-/**
- * mei_other_client_is_connecting - checks if other
- * client with the same client id is connected.
- *
- * @dev: the device structure
- * @cl: private data of the file object
- *
- * returns 1 if other client is connected, 0 - otherwise.
- */
-int mei_other_client_is_connecting(struct mei_device *dev,
- struct mei_cl *cl)
-{
- struct mei_cl *cl_pos = NULL;
- struct mei_cl *cl_next = NULL;
-
- list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
- if ((cl_pos->state == MEI_FILE_CONNECTING) &&
- (cl_pos != cl) &&
- cl->me_client_id == cl_pos->me_client_id)
- return 1;
-
- }
- return 0;
-}
-
-/**
- * mei_disconnect - sends disconnect message to fw.
- *
- * @dev: the device structure
- * @cl: private data of the file object
- *
- * This function returns -EIO on write failure
- */
-int mei_disconnect(struct mei_device *dev, struct mei_cl *cl)
-{
- struct mei_msg_hdr *mei_hdr;
- struct hbm_client_disconnect_request *mei_cli_disconnect;
-
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- mei_hdr->host_addr = 0;
- mei_hdr->me_addr = 0;
- mei_hdr->length = sizeof(struct hbm_client_disconnect_request);
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
-
- mei_cli_disconnect =
- (struct hbm_client_disconnect_request *) &dev->wr_msg_buf[1];
- memset(mei_cli_disconnect, 0, sizeof(*mei_cli_disconnect));
- mei_cli_disconnect->host_addr = cl->host_client_id;
- mei_cli_disconnect->me_addr = cl->me_client_id;
- mei_cli_disconnect->hbm_cmd = CLIENT_DISCONNECT_REQ_CMD;
- mei_cli_disconnect->reserved[0] = 0;
-
- return mei_write_message(dev, mei_hdr,
- (unsigned char *) mei_cli_disconnect,
- sizeof(struct hbm_client_disconnect_request));
-}
-
-/**
- * mei_connect - sends connect message to fw.
- *
- * @dev: the device structure
- * @cl: private data of the file object
- *
- * This function returns -EIO on write failure
- */
-int mei_connect(struct mei_device *dev, struct mei_cl *cl)
-{
- struct mei_msg_hdr *mei_hdr;
- struct hbm_client_connect_request *mei_cli_connect;
-
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- mei_hdr->host_addr = 0;
- mei_hdr->me_addr = 0;
- mei_hdr->length = sizeof(struct hbm_client_connect_request);
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
-
- mei_cli_connect =
- (struct hbm_client_connect_request *) &dev->wr_msg_buf[1];
- mei_cli_connect->host_addr = cl->host_client_id;
- mei_cli_connect->me_addr = cl->me_client_id;
- mei_cli_connect->hbm_cmd = CLIENT_CONNECT_REQ_CMD;
- mei_cli_connect->reserved = 0;
-
- return mei_write_message(dev, mei_hdr,
- (unsigned char *) mei_cli_connect,
- sizeof(struct hbm_client_connect_request));
-}
diff --git a/drivers/staging/mei/interface.h b/drivers/staging/mei/interface.h
deleted file mode 100644
index fb90c6f..0000000
--- a/drivers/staging/mei/interface.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-
-
-#ifndef _MEI_INTERFACE_H_
-#define _MEI_INTERFACE_H_
-
-#include "mei.h"
-#include "mei_dev.h"
-
-
-#define AMT_WD_DEFAULT_TIMEOUT 120 /* seconds */
-#define AMT_WD_MIN_TIMEOUT 120 /* seconds */
-#define AMT_WD_MAX_TIMEOUT 65535 /* seconds */
-
-#define MEI_WATCHDOG_DATA_SIZE 16
-#define MEI_START_WD_DATA_SIZE 20
-#define MEI_WD_PARAMS_SIZE 4
-
-
-void mei_read_slots(struct mei_device *dev,
- unsigned char *buffer,
- unsigned long buffer_length);
-
-int mei_write_message(struct mei_device *dev,
- struct mei_msg_hdr *header,
- unsigned char *write_buffer,
- unsigned long write_length);
-
-int mei_host_buffer_is_empty(struct mei_device *dev);
-
-int mei_count_full_read_slots(struct mei_device *dev);
-
-int mei_count_empty_write_slots(struct mei_device *dev);
-
-int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl);
-
-int mei_wd_send(struct mei_device *dev);
-int mei_wd_stop(struct mei_device *dev, bool preserve);
-bool mei_wd_host_init(struct mei_device *dev);
-void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout);
-/*
- * mei_watchdog_register - Registering watchdog interface
- * once we got connection to the WD Client
- * @dev - mei device
- */
-void mei_watchdog_register(struct mei_device *dev);
-/*
- * mei_watchdog_unregister - Unregistering watchdog interface
- * @dev - mei device
- */
-void mei_watchdog_unregister(struct mei_device *dev);
-
-int mei_flow_ctrl_reduce(struct mei_device *dev, struct mei_cl *cl);
-
-int mei_send_flow_control(struct mei_device *dev, struct mei_cl *cl);
-
-int mei_disconnect(struct mei_device *dev, struct mei_cl *cl);
-int mei_other_client_is_connecting(struct mei_device *dev, struct mei_cl *cl);
-int mei_connect(struct mei_device *dev, struct mei_cl *cl);
-
-#endif /* _MEI_INTERFACE_H_ */
diff --git a/drivers/staging/mei/interrupt.c b/drivers/staging/mei/interrupt.c
deleted file mode 100644
index 2007d24..0000000
--- a/drivers/staging/mei/interrupt.c
+++ /dev/null
@@ -1,1590 +0,0 @@
-/*
- *
- * 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 "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_free_cb_private(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_cmpl_iamthif - processes completed iamthif operation.
- *
- * @dev: the device structure.
- * @cb_pos: callback block.
- */
-static void _mei_cmpl_iamthif(struct mei_device *dev, struct mei_cl_cb *cb_pos)
-{
- if (dev->iamthif_canceled != 1) {
- dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
- dev->iamthif_stall_timer = 0;
- memcpy(cb_pos->response_buffer.data,
- dev->iamthif_msg_buf,
- dev->iamthif_msg_buf_index);
- list_add_tail(&cb_pos->cb_list,
- &dev->amthi_read_complete_list.mei_cb.cb_list);
- dev_dbg(&dev->pdev->dev, "amthi read completed.\n");
- dev->iamthif_timer = jiffies;
- dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
- dev->iamthif_timer);
- } else {
- mei_run_next_iamthif_cmd(dev);
- }
-
- dev_dbg(&dev->pdev->dev, "completing amthi call back.\n");
- wake_up_interruptible(&dev->iamthif_cl.wait);
-}
-
-
-/**
- * mei_irq_thread_read_amthi_message - bottom half read routine after ISR to
- * handle the read amthi message data processing.
- *
- * @complete_list: An instance of our list structure
- * @dev: the device structure
- * @mei_hdr: header of amthi message
- *
- * returns 0 on success, <0 on failure.
- */
-static int mei_irq_thread_read_amthi_message(struct mei_io_list *complete_list,
- struct mei_device *dev,
- struct mei_msg_hdr *mei_hdr)
-{
- struct mei_cl *cl;
- struct mei_cl_cb *cb;
- unsigned char *buffer;
-
- BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id);
- BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING);
-
- buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index;
- BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length);
-
- mei_read_slots(dev, buffer, mei_hdr->length);
-
- dev->iamthif_msg_buf_index += mei_hdr->length;
-
- if (!mei_hdr->msg_complete)
- return 0;
-
- dev_dbg(&dev->pdev->dev,
- "amthi_message_buffer_index =%d\n",
- mei_hdr->length);
-
- dev_dbg(&dev->pdev->dev, "completed amthi read.\n ");
- if (!dev->iamthif_current_cb)
- return -ENODEV;
-
- cb = dev->iamthif_current_cb;
- dev->iamthif_current_cb = NULL;
-
- cl = (struct mei_cl *)cb->file_private;
- if (!cl)
- return -ENODEV;
-
- dev->iamthif_stall_timer = 0;
- cb->information = dev->iamthif_msg_buf_index;
- cb->read_time = jiffies;
- if (dev->iamthif_ioctl && cl == &dev->iamthif_cl) {
- /* found the iamthif cb */
- dev_dbg(&dev->pdev->dev, "complete the amthi read cb.\n ");
- dev_dbg(&dev->pdev->dev, "add the amthi read cb to complete.\n ");
- list_add_tail(&cb->cb_list,
- &complete_list->mei_cb.cb_list);
- }
- return 0;
-}
-
-/**
- * _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.
- *
- * @complete_list: An instance of our list structure
- * @dev: the device structure
- * @mei_hdr: header of mei client message
- *
- * returns 0 on success, <0 on failure.
- */
-static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list,
- struct mei_device *dev,
- struct mei_msg_hdr *mei_hdr)
-{
- struct mei_cl *cl;
- struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
- unsigned char *buffer = NULL;
-
- dev_dbg(&dev->pdev->dev, "start client msg\n");
- if (list_empty(&dev->read_list.mei_cb.cb_list))
- goto quit;
-
- list_for_each_entry_safe(cb_pos, cb_next,
- &dev->read_list.mei_cb.cb_list, cb_list) {
- cl = (struct mei_cl *)cb_pos->file_private;
- if (cl && _mei_irq_thread_state_ok(cl, mei_hdr)) {
- cl->reading_state = MEI_READING;
- buffer = cb_pos->response_buffer.data + cb_pos->information;
-
- if (cb_pos->response_buffer.size <
- mei_hdr->length + cb_pos->information) {
- dev_dbg(&dev->pdev->dev, "message overflow.\n");
- list_del(&cb_pos->cb_list);
- return -ENOMEM;
- }
- if (buffer)
- mei_read_slots(dev, buffer, mei_hdr->length);
-
- cb_pos->information += mei_hdr->length;
- if (mei_hdr->msg_complete) {
- cl->status = 0;
- list_del(&cb_pos->cb_list);
- dev_dbg(&dev->pdev->dev,
- "completed read host client = %d,"
- "ME client = %d, "
- "data length = %lu\n",
- cl->host_client_id,
- cl->me_client_id,
- cb_pos->information);
-
- *(cb_pos->response_buffer.data +
- cb_pos->information) = '\0';
- dev_dbg(&dev->pdev->dev, "cb_pos->res_buffer - %s\n",
- cb_pos->response_buffer.data);
- list_add_tail(&cb_pos->cb_list,
- &complete_list->mei_cb.cb_list);
- }
-
- break;
- }
-
- }
-
-quit:
- dev_dbg(&dev->pdev->dev, "message read\n");
- if (!buffer) {
- mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
- dev_dbg(&dev->pdev->dev, "discarding message, header =%08x.\n",
- *(u32 *) dev->rd_msg_buf);
- }
-
- return 0;
-}
-
-/**
- * _mei_irq_thread_iamthif_read - prepares to read iamthif data.
- *
- * @dev: the device structure.
- * @slots: free slots.
- *
- * returns 0, OK; otherwise, error.
- */
-static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots)
-{
-
- if (((*slots) * sizeof(u32)) < (sizeof(struct mei_msg_hdr)
- + sizeof(struct hbm_flow_control))) {
- return -EMSGSIZE;
- }
- *slots -= (sizeof(struct mei_msg_hdr) +
- sizeof(struct hbm_flow_control) + 3) / 4;
- if (mei_send_flow_control(dev, &dev->iamthif_cl)) {
- dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
- return -EIO;
- }
-
- dev_dbg(&dev->pdev->dev, "iamthif flow control success\n");
- dev->iamthif_state = MEI_IAMTHIF_READING;
- dev->iamthif_flow_control_pending = false;
- dev->iamthif_msg_buf_index = 0;
- dev->iamthif_msg_buf_size = 0;
- dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER;
- dev->mei_host_buffer_is_empty = mei_host_buffer_is_empty(dev);
- return 0;
-}
-
-/**
- * _mei_irq_thread_close - processes close related operation.
- *
- * @dev: the device structure.
- * @slots: free slots.
- * @cb_pos: callback block.
- * @cl: private data of the file object.
- * @cmpl_list: complete list.
- *
- * returns 0, OK; otherwise, error.
- */
-static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
- struct mei_cl_cb *cb_pos,
- struct mei_cl *cl,
- struct mei_io_list *cmpl_list)
-{
- if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
- sizeof(struct hbm_client_disconnect_request))) {
- *slots -= (sizeof(struct mei_msg_hdr) +
- sizeof(struct hbm_client_disconnect_request) + 3) / 4;
-
- if (mei_disconnect(dev, cl)) {
- cl->status = 0;
- cb_pos->information = 0;
- list_move_tail(&cb_pos->cb_list,
- &cmpl_list->mei_cb.cb_list);
- return -EMSGSIZE;
- } else {
- cl->state = MEI_FILE_DISCONNECTING;
- cl->status = 0;
- cb_pos->information = 0;
- list_move_tail(&cb_pos->cb_list,
- &dev->ctrl_rd_list.mei_cb.cb_list);
- cl->timer_count = MEI_CONNECT_TIMEOUT;
- }
- } else {
- /* return the cancel routine */
- return -EBADMSG;
- }
-
- return 0;
-}
-
-/**
- * is_treat_specially_client - checks if the message belongs
- * to the file private data.
- *
- * @cl: private data of the file object
- * @rs: connect response bus message
- *
- */
-static bool is_treat_specially_client(struct mei_cl *cl,
- struct hbm_client_connect_response *rs)
-{
-
- if (cl->host_client_id == rs->host_addr &&
- cl->me_client_id == rs->me_addr) {
- if (!rs->status) {
- cl->state = MEI_FILE_CONNECTED;
- cl->status = 0;
-
- } else {
- cl->state = MEI_FILE_DISCONNECTED;
- cl->status = -ENODEV;
- }
- cl->timer_count = 0;
-
- return true;
- }
- return false;
-}
-
-/**
- * mei_client_connect_response - connects to response irq routine
- *
- * @dev: the device structure
- * @rs: connect response bus message
- */
-static void mei_client_connect_response(struct mei_device *dev,
- struct hbm_client_connect_response *rs)
-{
-
- struct mei_cl *cl;
- struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
-
- dev_dbg(&dev->pdev->dev,
- "connect_response:\n"
- "ME Client = %d\n"
- "Host Client = %d\n"
- "Status = %d\n",
- rs->me_addr,
- rs->host_addr,
- rs->status);
-
- /* if WD or iamthif client treat specially */
-
- if (is_treat_specially_client(&(dev->wd_cl), rs)) {
- dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n");
- mei_watchdog_register(dev);
-
- /* next step in the state maching */
- mei_host_init_iamthif(dev);
- return;
- }
-
- if (is_treat_specially_client(&(dev->iamthif_cl), rs)) {
- dev->iamthif_state = MEI_IAMTHIF_IDLE;
- return;
- }
- list_for_each_entry_safe(cb_pos, cb_next,
- &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
-
- cl = (struct mei_cl *)cb_pos->file_private;
- if (!cl) {
- list_del(&cb_pos->cb_list);
- return;
- }
- if (MEI_IOCTL == cb_pos->major_file_operations) {
- if (is_treat_specially_client(cl, rs)) {
- list_del(&cb_pos->cb_list);
- cl->status = 0;
- cl->timer_count = 0;
- break;
- }
- }
- }
-}
-
-/**
- * mei_client_disconnect_response - disconnects from response irq routine
- *
- * @dev: the device structure
- * @rs: disconnect response bus message
- */
-static void mei_client_disconnect_response(struct mei_device *dev,
- struct hbm_client_connect_response *rs)
-{
- struct mei_cl *cl;
- struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
-
- dev_dbg(&dev->pdev->dev,
- "disconnect_response:\n"
- "ME Client = %d\n"
- "Host Client = %d\n"
- "Status = %d\n",
- rs->me_addr,
- rs->host_addr,
- rs->status);
-
- list_for_each_entry_safe(cb_pos, cb_next,
- &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
- cl = (struct mei_cl *)cb_pos->file_private;
-
- if (!cl) {
- list_del(&cb_pos->cb_list);
- return;
- }
-
- dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in ctrl_rd_list.\n");
- if (cl->host_client_id == rs->host_addr &&
- cl->me_client_id == rs->me_addr) {
-
- list_del(&cb_pos->cb_list);
- if (!rs->status)
- cl->state = MEI_FILE_DISCONNECTED;
-
- cl->status = 0;
- cl->timer_count = 0;
- break;
- }
- }
-}
-
-/**
- * same_flow_addr - tells if they have the same address.
- *
- * @file: private data of the file object.
- * @flow: flow control.
- *
- * returns !=0, same; 0,not.
- */
-static int same_flow_addr(struct mei_cl *cl, struct hbm_flow_control *flow)
-{
- return (cl->host_client_id == flow->host_addr &&
- cl->me_client_id == flow->me_addr);
-}
-
-/**
- * add_single_flow_creds - adds single buffer credentials.
- *
- * @file: private data ot the file object.
- * @flow: flow control.
- */
-static void add_single_flow_creds(struct mei_device *dev,
- struct hbm_flow_control *flow)
-{
- struct mei_me_client *client;
- int i;
-
- for (i = 0; i < dev->me_clients_num; i++) {
- client = &dev->me_clients[i];
- if (client && flow->me_addr == client->client_id) {
- if (client->props.single_recv_buf) {
- client->mei_flow_ctrl_creds++;
- dev_dbg(&dev->pdev->dev, "recv flow ctrl msg ME %d (single).\n",
- flow->me_addr);
- dev_dbg(&dev->pdev->dev, "flow control credentials =%d.\n",
- client->mei_flow_ctrl_creds);
- } else {
- BUG(); /* error in flow control */
- }
- }
- }
-}
-
-/**
- * mei_client_flow_control_response - flow control response irq routine
- *
- * @dev: the device structure
- * @flow_control: flow control response bus message
- */
-static void mei_client_flow_control_response(struct mei_device *dev,
- struct hbm_flow_control *flow_control)
-{
- struct mei_cl *cl_pos = NULL;
- struct mei_cl *cl_next = NULL;
-
- if (!flow_control->host_addr) {
- /* single receive buffer */
- add_single_flow_creds(dev, flow_control);
- } else {
- /* normal connection */
- list_for_each_entry_safe(cl_pos, cl_next,
- &dev->file_list, link) {
- dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in file_list\n");
-
- dev_dbg(&dev->pdev->dev, "cl of host client %d ME client %d.\n",
- cl_pos->host_client_id,
- cl_pos->me_client_id);
- dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d.\n",
- flow_control->host_addr,
- flow_control->me_addr);
- if (same_flow_addr(cl_pos, flow_control)) {
- dev_dbg(&dev->pdev->dev, "recv ctrl msg for host %d ME %d.\n",
- flow_control->host_addr,
- flow_control->me_addr);
- cl_pos->mei_flow_ctrl_creds++;
- dev_dbg(&dev->pdev->dev, "flow control credentials = %d.\n",
- cl_pos->mei_flow_ctrl_creds);
- break;
- }
- }
- }
-}
-
-/**
- * same_disconn_addr - tells if they have the same address
- *
- * @file: private data of the file object.
- * @disconn: disconnection request.
- *
- * returns !=0, same; 0,not.
- */
-static int same_disconn_addr(struct mei_cl *cl,
- struct hbm_client_disconnect_request *disconn)
-{
- return (cl->host_client_id == disconn->host_addr &&
- cl->me_client_id == disconn->me_addr);
-}
-
-/**
- * mei_client_disconnect_request - disconnects from request irq routine
- *
- * @dev: the device structure.
- * @disconnect_req: disconnect request bus message.
- */
-static void mei_client_disconnect_request(struct mei_device *dev,
- struct hbm_client_disconnect_request *disconnect_req)
-{
- struct mei_msg_hdr *mei_hdr;
- struct hbm_client_connect_response *disconnect_res;
- struct mei_cl *cl_pos = NULL;
- struct mei_cl *cl_next = NULL;
-
- list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
- if (same_disconn_addr(cl_pos, disconnect_req)) {
- dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n",
- disconnect_req->host_addr,
- disconnect_req->me_addr);
- cl_pos->state = MEI_FILE_DISCONNECTED;
- cl_pos->timer_count = 0;
- if (cl_pos == &dev->wd_cl) {
- dev->wd_due_counter = 0;
- dev->wd_pending = false;
- } else if (cl_pos == &dev->iamthif_cl)
- dev->iamthif_timer = 0;
-
- /* prepare disconnect response */
- mei_hdr =
- (struct mei_msg_hdr *) &dev->ext_msg_buf[0];
- mei_hdr->host_addr = 0;
- mei_hdr->me_addr = 0;
- mei_hdr->length =
- sizeof(struct hbm_client_connect_response);
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
-
- disconnect_res =
- (struct hbm_client_connect_response *)
- &dev->ext_msg_buf[1];
- disconnect_res->host_addr = cl_pos->host_client_id;
- disconnect_res->me_addr = cl_pos->me_client_id;
- disconnect_res->hbm_cmd = CLIENT_DISCONNECT_RES_CMD;
- disconnect_res->status = 0;
- dev->extra_write_index = 2;
- break;
- }
- }
-}
-
-
-/**
- * mei_irq_thread_read_bus_message - bottom half read routine after ISR to
- * handle the read bus message cmd processing.
- *
- * @dev: the device structure
- * @mei_hdr: header of bus message
- */
-static void mei_irq_thread_read_bus_message(struct mei_device *dev,
- struct mei_msg_hdr *mei_hdr)
-{
- struct mei_bus_message *mei_msg;
- struct hbm_host_version_response *version_res;
- struct hbm_client_connect_response *connect_res;
- struct hbm_client_connect_response *disconnect_res;
- struct hbm_flow_control *flow_control;
- struct hbm_props_response *props_res;
- struct hbm_host_enum_response *enum_res;
- struct hbm_client_disconnect_request *disconnect_req;
- struct hbm_host_stop_request *host_stop_req;
- int res;
-
-
- /* read the message to our buffer */
- BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf));
- mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
- mei_msg = (struct mei_bus_message *)dev->rd_msg_buf;
-
- switch (mei_msg->hbm_cmd) {
- case HOST_START_RES_CMD:
- version_res = (struct hbm_host_version_response *) mei_msg;
- if (version_res->host_version_supported) {
- dev->version.major_version = HBM_MAJOR_VERSION;
- dev->version.minor_version = HBM_MINOR_VERSION;
- if (dev->mei_state == MEI_INIT_CLIENTS &&
- dev->init_clients_state == MEI_START_MESSAGE) {
- dev->init_clients_timer = 0;
- mei_host_enum_clients_message(dev);
- } else {
- dev->recvd_msg = false;
- dev_dbg(&dev->pdev->dev, "IMEI reset due to received host start response bus message.\n");
- mei_reset(dev, 1);
- return;
- }
- } else {
- dev->version = version_res->me_max_version;
- /* send stop message */
- mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
- mei_hdr->host_addr = 0;
- mei_hdr->me_addr = 0;
- mei_hdr->length = sizeof(struct hbm_host_stop_request);
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
-
- host_stop_req = (struct hbm_host_stop_request *)
- &dev->wr_msg_buf[1];
-
- memset(host_stop_req,
- 0,
- sizeof(struct hbm_host_stop_request));
- host_stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
- host_stop_req->reason = DRIVER_STOP_REQUEST;
- mei_write_message(dev, mei_hdr,
- (unsigned char *) (host_stop_req),
- mei_hdr->length);
- dev_dbg(&dev->pdev->dev, "version mismatch.\n");
- return;
- }
-
- dev->recvd_msg = true;
- dev_dbg(&dev->pdev->dev, "host start response message received.\n");
- break;
-
- case CLIENT_CONNECT_RES_CMD:
- connect_res =
- (struct hbm_client_connect_response *) mei_msg;
- mei_client_connect_response(dev, connect_res);
- dev_dbg(&dev->pdev->dev, "client connect response message received.\n");
- wake_up(&dev->wait_recvd_msg);
- break;
-
- case CLIENT_DISCONNECT_RES_CMD:
- disconnect_res =
- (struct hbm_client_connect_response *) mei_msg;
- mei_client_disconnect_response(dev, disconnect_res);
- dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n");
- wake_up(&dev->wait_recvd_msg);
- break;
-
- case MEI_FLOW_CONTROL_CMD:
- flow_control = (struct hbm_flow_control *) mei_msg;
- mei_client_flow_control_response(dev, flow_control);
- dev_dbg(&dev->pdev->dev, "client flow control response message received.\n");
- break;
-
- case HOST_CLIENT_PROPERTIES_RES_CMD:
- props_res = (struct hbm_props_response *)mei_msg;
- if (props_res->status || !dev->me_clients) {
- dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n");
- mei_reset(dev, 1);
- return;
- }
- if (dev->me_clients[dev->me_client_presentation_num]
- .client_id == props_res->address) {
-
- dev->me_clients[dev->me_client_presentation_num].props
- = props_res->client_properties;
-
- if (dev->mei_state == MEI_INIT_CLIENTS &&
- dev->init_clients_state ==
- MEI_CLIENT_PROPERTIES_MESSAGE) {
- dev->me_client_index++;
- dev->me_client_presentation_num++;
-
- /** Send Client Properties request **/
- res = mei_host_client_properties(dev);
- if (res < 0) {
- dev_dbg(&dev->pdev->dev, "mei_host_client_properties() failed");
- return;
- } else if (!res) {
- /*
- * No more clients to send to.
- * Clear Map for indicating now ME clients
- * with associated host client
- */
- bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
- dev->open_handle_count = 0;
-
- /*
- * Reserving the first three client IDs
- * Client Id 0 - Reserved for MEI Bus Message communications
- * Client Id 1 - Reserved for Watchdog
- * Client ID 2 - Reserved for AMTHI
- */
- bitmap_set(dev->host_clients_map, 0, 3);
- dev->mei_state = MEI_ENABLED;
-
- /* if wd initialization fails, initialization the AMTHI client,
- * otherwise the AMTHI client will be initialized after the WD client connect response
- * will be received
- */
- if (mei_wd_host_init(dev))
- mei_host_init_iamthif(dev);
- }
-
- } else {
- dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message");
- mei_reset(dev, 1);
- return;
- }
- } else {
- dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message for wrong client ID\n");
- mei_reset(dev, 1);
- return;
- }
- break;
-
- case HOST_ENUM_RES_CMD:
- enum_res = (struct hbm_host_enum_response *) mei_msg;
- memcpy(dev->me_clients_map, enum_res->valid_addresses, 32);
- if (dev->mei_state == MEI_INIT_CLIENTS &&
- dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) {
- dev->init_clients_timer = 0;
- dev->me_client_presentation_num = 0;
- dev->me_client_index = 0;
- mei_allocate_me_clients_storage(dev);
- dev->init_clients_state =
- MEI_CLIENT_PROPERTIES_MESSAGE;
- mei_host_client_properties(dev);
- } else {
- dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n");
- mei_reset(dev, 1);
- return;
- }
- break;
-
- case HOST_STOP_RES_CMD:
- dev->mei_state = MEI_DISABLED;
- dev_dbg(&dev->pdev->dev, "resetting because of FW stop response.\n");
- mei_reset(dev, 1);
- break;
-
- case CLIENT_DISCONNECT_REQ_CMD:
- /* search for client */
- disconnect_req =
- (struct hbm_client_disconnect_request *) mei_msg;
- mei_client_disconnect_request(dev, disconnect_req);
- break;
-
- case ME_STOP_REQ_CMD:
- /* prepare stop request */
- mei_hdr = (struct mei_msg_hdr *) &dev->ext_msg_buf[0];
- mei_hdr->host_addr = 0;
- mei_hdr->me_addr = 0;
- mei_hdr->length = sizeof(struct hbm_host_stop_request);
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
- host_stop_req =
- (struct hbm_host_stop_request *) &dev->ext_msg_buf[1];
- memset(host_stop_req, 0, sizeof(struct hbm_host_stop_request));
- host_stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
- host_stop_req->reason = DRIVER_STOP_REQUEST;
- host_stop_req->reserved[0] = 0;
- host_stop_req->reserved[1] = 0;
- dev->extra_write_index = 2;
- break;
-
- default:
- BUG();
- break;
-
- }
-}
-
-
-/**
- * _mei_hb_read - processes read related operation.
- *
- * @dev: the device structure.
- * @slots: free slots.
- * @cb_pos: callback block.
- * @cl: private data of the file object.
- * @cmpl_list: complete list.
- *
- * returns 0, OK; otherwise, error.
- */
-static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots,
- struct mei_cl_cb *cb_pos,
- struct mei_cl *cl,
- struct mei_io_list *cmpl_list)
-{
- if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
- sizeof(struct hbm_flow_control))) {
- /* return the cancel routine */
- list_del(&cb_pos->cb_list);
- return -EBADMSG;
- }
-
- *slots -= (sizeof(struct mei_msg_hdr) +
- sizeof(struct hbm_flow_control) + 3) / 4;
- if (mei_send_flow_control(dev, cl)) {
- cl->status = -ENODEV;
- cb_pos->information = 0;
- list_move_tail(&cb_pos->cb_list, &cmpl_list->mei_cb.cb_list);
- return -ENODEV;
- }
- list_move_tail(&cb_pos->cb_list, &dev->read_list.mei_cb.cb_list);
-
- return 0;
-}
-
-
-/**
- * _mei_irq_thread_ioctl - processes ioctl related operation.
- *
- * @dev: the device structure.
- * @slots: free slots.
- * @cb_pos: callback block.
- * @cl: private data of the file object.
- * @cmpl_list: complete list.
- *
- * returns 0, OK; otherwise, error.
- */
-static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
- struct mei_cl_cb *cb_pos,
- struct mei_cl *cl,
- struct mei_io_list *cmpl_list)
-{
- if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
- sizeof(struct hbm_client_connect_request))) {
- cl->state = MEI_FILE_CONNECTING;
- *slots -= (sizeof(struct mei_msg_hdr) +
- sizeof(struct hbm_client_connect_request) + 3) / 4;
- if (mei_connect(dev, cl)) {
- cl->status = -ENODEV;
- cb_pos->information = 0;
- list_del(&cb_pos->cb_list);
- return -ENODEV;
- } else {
- list_move_tail(&cb_pos->cb_list,
- &dev->ctrl_rd_list.mei_cb.cb_list);
- cl->timer_count = MEI_CONNECT_TIMEOUT;
- }
- } else {
- /* return the cancel routine */
- list_del(&cb_pos->cb_list);
- return -EBADMSG;
- }
-
- return 0;
-}
-
-/**
- * _mei_irq_thread_cmpl - processes completed and no-iamthif operation.
- *
- * @dev: the device structure.
- * @slots: free slots.
- * @cb_pos: callback block.
- * @cl: private data of the file object.
- * @cmpl_list: complete list.
- *
- * returns 0, OK; otherwise, error.
- */
-static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots,
- struct mei_cl_cb *cb_pos,
- struct mei_cl *cl,
- struct mei_io_list *cmpl_list)
-{
- struct mei_msg_hdr *mei_hdr;
-
- if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
- (cb_pos->request_buffer.size -
- cb_pos->information))) {
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- mei_hdr->host_addr = cl->host_client_id;
- mei_hdr->me_addr = cl->me_client_id;
- mei_hdr->length = cb_pos->request_buffer.size -
- cb_pos->information;
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
- dev_dbg(&dev->pdev->dev, "cb_pos->request_buffer.size =%d"
- "mei_hdr->msg_complete = %d\n",
- cb_pos->request_buffer.size,
- mei_hdr->msg_complete);
- dev_dbg(&dev->pdev->dev, "cb_pos->information =%lu\n",
- cb_pos->information);
- dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
- mei_hdr->length);
- *slots -= (sizeof(struct mei_msg_hdr) +
- mei_hdr->length + 3) / 4;
- if (mei_write_message(dev, mei_hdr,
- (unsigned char *)
- (cb_pos->request_buffer.data +
- cb_pos->information),
- mei_hdr->length)) {
- cl->status = -ENODEV;
- list_move_tail(&cb_pos->cb_list,
- &cmpl_list->mei_cb.cb_list);
- return -ENODEV;
- } else {
- if (mei_flow_ctrl_reduce(dev, cl))
- return -ENODEV;
- cl->status = 0;
- cb_pos->information += mei_hdr->length;
- list_move_tail(&cb_pos->cb_list,
- &dev->write_waiting_list.mei_cb.cb_list);
- }
- } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
- /* buffer is still empty */
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- mei_hdr->host_addr = cl->host_client_id;
- mei_hdr->me_addr = cl->me_client_id;
- mei_hdr->length =
- (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
- mei_hdr->msg_complete = 0;
- mei_hdr->reserved = 0;
-
- (*slots) -= (sizeof(struct mei_msg_hdr) +
- mei_hdr->length + 3) / 4;
- if (mei_write_message(dev, mei_hdr,
- (unsigned char *)
- (cb_pos->request_buffer.data +
- cb_pos->information),
- mei_hdr->length)) {
- cl->status = -ENODEV;
- list_move_tail(&cb_pos->cb_list,
- &cmpl_list->mei_cb.cb_list);
- return -ENODEV;
- } else {
- cb_pos->information += mei_hdr->length;
- dev_dbg(&dev->pdev->dev,
- "cb_pos->request_buffer.size =%d"
- " mei_hdr->msg_complete = %d\n",
- cb_pos->request_buffer.size,
- mei_hdr->msg_complete);
- dev_dbg(&dev->pdev->dev, "cb_pos->information =%lu\n",
- cb_pos->information);
- dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
- mei_hdr->length);
- }
- return -EMSGSIZE;
- } else {
- return -EBADMSG;
- }
-
- return 0;
-}
-
-/**
- * _mei_irq_thread_cmpl_iamthif - processes completed iamthif operation.
- *
- * @dev: the device structure.
- * @slots: free slots.
- * @cb_pos: callback block.
- * @cl: private data of the file object.
- * @cmpl_list: complete list.
- *
- * returns 0, OK; otherwise, error.
- */
-static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
- struct mei_cl_cb *cb_pos,
- struct mei_cl *cl,
- struct mei_io_list *cmpl_list)
-{
- struct mei_msg_hdr *mei_hdr;
-
- if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
- dev->iamthif_msg_buf_size -
- dev->iamthif_msg_buf_index)) {
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- mei_hdr->host_addr = cl->host_client_id;
- mei_hdr->me_addr = cl->me_client_id;
- mei_hdr->length = dev->iamthif_msg_buf_size -
- dev->iamthif_msg_buf_index;
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
-
- *slots -= (sizeof(struct mei_msg_hdr) +
- mei_hdr->length + 3) / 4;
-
- if (mei_write_message(dev, mei_hdr,
- (dev->iamthif_msg_buf +
- dev->iamthif_msg_buf_index),
- mei_hdr->length)) {
- dev->iamthif_state = MEI_IAMTHIF_IDLE;
- cl->status = -ENODEV;
- list_del(&cb_pos->cb_list);
- return -ENODEV;
- } else {
- if (mei_flow_ctrl_reduce(dev, cl))
- return -ENODEV;
- dev->iamthif_msg_buf_index += mei_hdr->length;
- cb_pos->information = dev->iamthif_msg_buf_index;
- cl->status = 0;
- dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
- dev->iamthif_flow_control_pending = true;
- /* save iamthif cb sent to amthi client */
- dev->iamthif_current_cb = cb_pos;
- list_move_tail(&cb_pos->cb_list,
- &dev->write_waiting_list.mei_cb.cb_list);
-
- }
- } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
- /* buffer is still empty */
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- mei_hdr->host_addr = cl->host_client_id;
- mei_hdr->me_addr = cl->me_client_id;
- mei_hdr->length =
- (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
- mei_hdr->msg_complete = 0;
- mei_hdr->reserved = 0;
-
- *slots -= (sizeof(struct mei_msg_hdr) +
- mei_hdr->length + 3) / 4;
-
- if (mei_write_message(dev, mei_hdr,
- (dev->iamthif_msg_buf +
- dev->iamthif_msg_buf_index),
- mei_hdr->length)) {
- cl->status = -ENODEV;
- list_del(&cb_pos->cb_list);
- } else {
- dev->iamthif_msg_buf_index += mei_hdr->length;
- }
- return -EMSGSIZE;
- } else {
- return -EBADMSG;
- }
-
- return 0;
-}
-
-/**
- * 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
- * @slots: slots to read.
- *
- * returns 0 on success, <0 on failure.
- */
-static int mei_irq_thread_read_handler(struct mei_io_list *cmpl_list,
- struct mei_device *dev,
- s32 *slots)
-{
- struct mei_msg_hdr *mei_hdr;
- struct mei_cl *cl_pos = NULL;
- struct mei_cl *cl_next = NULL;
- int ret = 0;
-
- if (!dev->rd_msg_hdr) {
- dev->rd_msg_hdr = mei_mecbrw_read(dev);
- dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
- (*slots)--;
- dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
- }
- mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr;
- dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", mei_hdr->length);
-
- if (mei_hdr->reserved || !dev->rd_msg_hdr) {
- dev_dbg(&dev->pdev->dev, "corrupted message header.\n");
- ret = -EBADMSG;
- goto end;
- }
-
- if (mei_hdr->host_addr || mei_hdr->me_addr) {
- list_for_each_entry_safe(cl_pos, cl_next,
- &dev->file_list, link) {
- dev_dbg(&dev->pdev->dev,
- "list_for_each_entry_safe read host"
- " client = %d, ME client = %d\n",
- cl_pos->host_client_id,
- cl_pos->me_client_id);
- if (cl_pos->host_client_id == mei_hdr->host_addr &&
- cl_pos->me_client_id == mei_hdr->me_addr)
- break;
- }
-
- if (&cl_pos->link == &dev->file_list) {
- dev_dbg(&dev->pdev->dev, "corrupted message header\n");
- ret = -EBADMSG;
- goto end;
- }
- }
- if (((*slots) * sizeof(u32)) < mei_hdr->length) {
- dev_dbg(&dev->pdev->dev,
- "we can't read the message slots =%08x.\n",
- *slots);
- /* we can't read the message */
- ret = -ERANGE;
- goto end;
- }
-
- /* decide where to read the message too */
- if (!mei_hdr->host_addr) {
- dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n");
- mei_irq_thread_read_bus_message(dev, mei_hdr);
- dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n");
- } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
- (MEI_FILE_CONNECTED == dev->iamthif_cl.state) &&
- (dev->iamthif_state == MEI_IAMTHIF_READING)) {
- dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n");
- dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
- mei_hdr->length);
- ret = mei_irq_thread_read_amthi_message(cmpl_list,
- dev, mei_hdr);
- if (ret)
- goto end;
-
- } else {
- dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_client_message.\n");
- ret = mei_irq_thread_read_client_message(cmpl_list,
- dev, mei_hdr);
- if (ret)
- goto end;
-
- }
-
- /* reset the number of slots and header */
- *slots = mei_count_full_read_slots(dev);
- dev->rd_msg_hdr = 0;
-
- if (*slots == -EOVERFLOW) {
- /* overflow - reset */
- dev_dbg(&dev->pdev->dev, "resetting due to slots overflow.\n");
- /* set the event since message has been read */
- ret = -ERANGE;
- goto end;
- }
-end:
- return ret;
-}
-
-
-/**
- * mei_irq_thread_write_handler - bottom half write routine after
- * ISR to handle the write processing.
- *
- * @cmpl_list: An instance of our list structure
- * @dev: the device structure
- * @slots: slots to write.
- *
- * returns 0 on success, <0 on failure.
- */
-static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
- struct mei_device *dev,
- s32 *slots)
-{
-
- struct mei_cl *cl;
- struct mei_cl_cb *pos = NULL, *next = NULL;
- struct mei_io_list *list;
- int ret;
-
- if (!mei_host_buffer_is_empty(dev)) {
- dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
- return 0;
- }
- *slots = mei_count_empty_write_slots(dev);
- /* complete all waiting for write CB */
- dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
-
- list = &dev->write_waiting_list;
- list_for_each_entry_safe(pos, next,
- &list->mei_cb.cb_list, cb_list) {
- cl = (struct mei_cl *)pos->file_private;
- if (cl == NULL)
- continue;
-
- cl->status = 0;
- list_del(&pos->cb_list);
- if (MEI_WRITING == cl->writing_state &&
- (pos->major_file_operations == MEI_WRITE) &&
- (cl != &dev->iamthif_cl)) {
- dev_dbg(&dev->pdev->dev,
- "MEI WRITE COMPLETE\n");
- cl->writing_state = MEI_WRITE_COMPLETE;
- list_add_tail(&pos->cb_list,
- &cmpl_list->mei_cb.cb_list);
- }
- if (cl == &dev->iamthif_cl) {
- dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
- if (dev->iamthif_flow_control_pending) {
- ret = _mei_irq_thread_iamthif_read(
- dev, slots);
- if (ret)
- return ret;
- }
- }
- }
-
- if (dev->stop && !dev->wd_pending) {
- dev->wd_stopped = true;
- wake_up_interruptible(&dev->wait_stop_wd);
- return 0;
- }
-
- if (dev->extra_write_index) {
- dev_dbg(&dev->pdev->dev, "extra_write_index =%d.\n",
- dev->extra_write_index);
- mei_write_message(dev,
- (struct mei_msg_hdr *) &dev->ext_msg_buf[0],
- (unsigned char *) &dev->ext_msg_buf[1],
- (dev->extra_write_index - 1) * sizeof(u32));
- *slots -= dev->extra_write_index;
- dev->extra_write_index = 0;
- }
- if (dev->mei_state == MEI_ENABLED) {
- if (dev->wd_pending &&
- mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
- if (mei_wd_send(dev))
- dev_dbg(&dev->pdev->dev, "wd send failed.\n");
- else
- if (mei_flow_ctrl_reduce(dev, &dev->wd_cl))
- return -ENODEV;
-
- dev->wd_pending = false;
-
- if (dev->wd_timeout) {
- *slots -= (sizeof(struct mei_msg_hdr) +
- MEI_START_WD_DATA_SIZE + 3) / 4;
- dev->wd_due_counter = 2;
- } else {
- *slots -= (sizeof(struct mei_msg_hdr) +
- MEI_WD_PARAMS_SIZE + 3) / 4;
- dev->wd_due_counter = 0;
- }
-
- }
- }
- if (dev->stop)
- return -ENODEV;
-
- /* complete control write list CB */
- dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
- list_for_each_entry_safe(pos, next,
- &dev->ctrl_wr_list.mei_cb.cb_list, cb_list) {
- cl = (struct mei_cl *) pos->file_private;
- if (!cl) {
- list_del(&pos->cb_list);
- return -ENODEV;
- }
- switch (pos->major_file_operations) {
- case MEI_CLOSE:
- /* send disconnect message */
- ret = _mei_irq_thread_close(dev, slots, pos, cl, cmpl_list);
- if (ret)
- return ret;
-
- break;
- case MEI_READ:
- /* send flow control message */
- ret = _mei_irq_thread_read(dev, slots, pos, cl, cmpl_list);
- if (ret)
- return ret;
-
- break;
- case MEI_IOCTL:
- /* connect message */
- if (mei_other_client_is_connecting(dev, cl))
- continue;
- ret = _mei_irq_thread_ioctl(dev, slots, pos, cl, cmpl_list);
- if (ret)
- return ret;
-
- break;
-
- default:
- BUG();
- }
-
- }
- /* complete write list CB */
- dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
- list_for_each_entry_safe(pos, next,
- &dev->write_list.mei_cb.cb_list, cb_list) {
- cl = (struct mei_cl *)pos->file_private;
- if (cl == NULL)
- continue;
-
- if (cl != &dev->iamthif_cl) {
- if (!mei_flow_ctrl_creds(dev, cl)) {
- dev_dbg(&dev->pdev->dev,
- "No flow control"
- " credentials for client"
- " %d, not sending.\n",
- cl->host_client_id);
- continue;
- }
- ret = _mei_irq_thread_cmpl(dev, slots,
- pos,
- cl, cmpl_list);
- if (ret)
- return ret;
-
- } else if (cl == &dev->iamthif_cl) {
- /* IAMTHIF IOCTL */
- dev_dbg(&dev->pdev->dev, "complete amthi write cb.\n");
- if (!mei_flow_ctrl_creds(dev, cl)) {
- dev_dbg(&dev->pdev->dev,
- "No flow control"
- " credentials for amthi"
- " client %d.\n",
- cl->host_client_id);
- continue;
- }
- ret = _mei_irq_thread_cmpl_iamthif(dev,
- slots,
- pos,
- cl,
- cmpl_list);
- if (ret)
- return ret;
-
- }
-
- }
- return 0;
-}
-
-
-
-/**
- * mei_timer - timer function.
- *
- * @work: pointer to the work_struct structure
- *
- * NOTE: This function is called by timer interrupt work
- */
-void mei_timer(struct work_struct *work)
-{
- unsigned long timeout;
- struct mei_cl *cl_pos = NULL;
- struct mei_cl *cl_next = NULL;
- struct list_head *amthi_complete_list = NULL;
- struct mei_cl_cb *cb_pos = NULL;
- struct mei_cl_cb *cb_next = NULL;
-
- struct mei_device *dev = container_of(work,
- struct mei_device, timer_work.work);
-
-
- mutex_lock(&dev->device_lock);
- if (dev->mei_state != MEI_ENABLED) {
- if (dev->mei_state == MEI_INIT_CLIENTS) {
- if (dev->init_clients_timer) {
- if (--dev->init_clients_timer == 0) {
- dev_dbg(&dev->pdev->dev, "IMEI reset due to init clients timeout ,init clients state = %d.\n",
- dev->init_clients_state);
- mei_reset(dev, 1);
- }
- }
- }
- goto out;
- }
- /*** connect/disconnect timeouts ***/
- list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
- if (cl_pos->timer_count) {
- if (--cl_pos->timer_count == 0) {
- dev_dbg(&dev->pdev->dev, "HECI reset due to connect/disconnect timeout.\n");
- mei_reset(dev, 1);
- goto out;
- }
- }
- }
-
- if (dev->iamthif_stall_timer) {
- if (--dev->iamthif_stall_timer == 0) {
- dev_dbg(&dev->pdev->dev, "resetting because of hang to amthi.\n");
- mei_reset(dev, 1);
- dev->iamthif_msg_buf_size = 0;
- dev->iamthif_msg_buf_index = 0;
- dev->iamthif_canceled = false;
- dev->iamthif_ioctl = true;
- dev->iamthif_state = MEI_IAMTHIF_IDLE;
- dev->iamthif_timer = 0;
-
- if (dev->iamthif_current_cb)
- mei_free_cb_private(dev->iamthif_current_cb);
-
- dev->iamthif_file_object = NULL;
- dev->iamthif_current_cb = NULL;
- mei_run_next_iamthif_cmd(dev);
- }
- }
-
- if (dev->iamthif_timer) {
-
- timeout = dev->iamthif_timer +
- msecs_to_jiffies(IAMTHIF_READ_TIMER);
-
- dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
- dev->iamthif_timer);
- dev_dbg(&dev->pdev->dev, "timeout = %ld\n", timeout);
- dev_dbg(&dev->pdev->dev, "jiffies = %ld\n", jiffies);
- if (time_after(jiffies, timeout)) {
- /*
- * User didn't read the AMTHI data on time (15sec)
- * freeing AMTHI for other requests
- */
-
- dev_dbg(&dev->pdev->dev, "freeing AMTHI for other requests\n");
-
- amthi_complete_list = &dev->amthi_read_complete_list.
- mei_cb.cb_list;
-
- list_for_each_entry_safe(cb_pos, cb_next, amthi_complete_list, cb_list) {
-
- cl_pos = cb_pos->file_object->private_data;
-
- /* Finding the AMTHI entry. */
- if (cl_pos == &dev->iamthif_cl)
- list_del(&cb_pos->cb_list);
- }
- if (dev->iamthif_current_cb)
- mei_free_cb_private(dev->iamthif_current_cb);
-
- dev->iamthif_file_object->private_data = NULL;
- dev->iamthif_file_object = NULL;
- dev->iamthif_current_cb = NULL;
- dev->iamthif_timer = 0;
- mei_run_next_iamthif_cmd(dev);
-
- }
- }
-out:
- schedule_delayed_work(&dev->timer_work, 2 * HZ);
- 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_io_list 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);
- dev->host_hw_state = mei_hcsr_read(dev);
-
- /* Ack the interrupt here
- * In case of MSI we don't go through the quick handler */
- if (pci_dev_msi_enabled(dev->pdev))
- mei_reg_write(dev, H_CSR, dev->host_hw_state);
-
- dev->me_hw_state = mei_mecsr_read(dev);
-
- /* check if ME wants a reset */
- if ((dev->me_hw_state & ME_RDY_HRA) == 0 &&
- dev->mei_state != MEI_RESETING &&
- dev->mei_state != MEI_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 ((dev->host_hw_state & H_RDY) == 0) {
- if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) {
- dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
- dev->host_hw_state |= (H_IE | H_IG | H_RDY);
- mei_hcsr_set(dev);
- dev->mei_state = MEI_INIT_CLIENTS;
- dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
- /* link is established
- * start sending messages.
- */
- mei_host_start_message(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);
- dev_dbg(&dev->pdev->dev, "slots =%08x extra_write_index =%08x.\n",
- slots, dev->extra_write_index);
- while (slots > 0 && !dev->extra_write_index) {
- dev_dbg(&dev->pdev->dev, "slots =%08x extra_write_index =%08x.\n",
- slots, dev->extra_write_index);
- 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(&complete_list, dev, &slots);
-end:
- dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
- dev->host_hw_state = mei_hcsr_read(dev);
- dev->mei_host_buffer_is_empty = mei_host_buffer_is_empty(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.mei_cb.cb_list))
- return IRQ_HANDLED;
-
-
- list_for_each_entry_safe(cb_pos, cb_next,
- &complete_list.mei_cb.cb_list, cb_list) {
- cl = (struct mei_cl *)cb_pos->file_private;
- list_del(&cb_pos->cb_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_cmpl_iamthif(dev, cb_pos);
- }
- }
- }
- return IRQ_HANDLED;
-}
diff --git a/drivers/staging/mei/iorw.c b/drivers/staging/mei/iorw.c
deleted file mode 100644
index 0a80dc4..0000000
--- a/drivers/staging/mei/iorw.c
+++ /dev/null
@@ -1,590 +0,0 @@
-/*
- *
- * 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/kernel.h>
-#include <linux/fs.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/aio.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ioctl.h>
-#include <linux/cdev.h>
-#include <linux/list.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/uuid.h>
-#include <linux/jiffies.h>
-#include <linux/uaccess.h>
-
-
-#include "mei_dev.h"
-#include "hw.h"
-#include "mei.h"
-#include "interface.h"
-
-
-
-/**
- * mei_ioctl_connect_client - the connect to fw client IOCTL function
- *
- * @dev: the device structure
- * @data: IOCTL connect data, input and output parameters
- * @file: private data of the file object
- *
- * Locking: called under "dev->device_lock" lock
- *
- * returns 0 on success, <0 on failure.
- */
-int mei_ioctl_connect_client(struct file *file,
- struct mei_connect_client_data *data)
-{
- struct mei_device *dev;
- struct mei_cl_cb *cb;
- struct mei_client *client;
- struct mei_cl *cl;
- struct mei_cl *cl_pos = NULL;
- struct mei_cl *cl_next = NULL;
- long timeout = CONNECT_TIMEOUT;
- int i;
- int err;
- int rets;
-
- cl = file->private_data;
- if (WARN_ON(!cl || !cl->dev))
- return -ENODEV;
-
- dev = cl->dev;
-
- dev_dbg(&dev->pdev->dev, "mei_ioctl_connect_client() Entry\n");
-
-
- /* buffered ioctl cb */
- cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
- if (!cb) {
- rets = -ENOMEM;
- goto end;
- }
- INIT_LIST_HEAD(&cb->cb_list);
-
- cb->major_file_operations = MEI_IOCTL;
-
- if (dev->mei_state != MEI_ENABLED) {
- rets = -ENODEV;
- goto end;
- }
- if (cl->state != MEI_FILE_INITIALIZING &&
- cl->state != MEI_FILE_DISCONNECTED) {
- rets = -EBUSY;
- goto end;
- }
-
- /* find ME client we're trying to connect to */
- i = mei_find_me_client_index(dev, data->in_client_uuid);
- if (i >= 0 && !dev->me_clients[i].props.fixed_address) {
- cl->me_client_id = dev->me_clients[i].client_id;
- cl->state = MEI_FILE_CONNECTING;
- }
-
- dev_dbg(&dev->pdev->dev, "Connect to FW Client ID = %d\n",
- cl->me_client_id);
- dev_dbg(&dev->pdev->dev, "FW Client - Protocol Version = %d\n",
- dev->me_clients[i].props.protocol_version);
- dev_dbg(&dev->pdev->dev, "FW Client - Max Msg Len = %d\n",
- dev->me_clients[i].props.max_msg_length);
-
- /* if we're connecting to amthi client then we will use the
- * existing connection
- */
- if (uuid_le_cmp(data->in_client_uuid, mei_amthi_guid) == 0) {
- dev_dbg(&dev->pdev->dev, "FW Client is amthi\n");
- if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
- rets = -ENODEV;
- goto end;
- }
- clear_bit(cl->host_client_id, dev->host_clients_map);
- list_for_each_entry_safe(cl_pos, cl_next,
- &dev->file_list, link) {
- if (mei_cl_cmp_id(cl, cl_pos)) {
- dev_dbg(&dev->pdev->dev,
- "remove file private data node host"
- " client = %d, ME client = %d.\n",
- cl_pos->host_client_id,
- cl_pos->me_client_id);
- list_del(&cl_pos->link);
- }
-
- }
- dev_dbg(&dev->pdev->dev, "free file private data memory.\n");
- kfree(cl);
-
- cl = NULL;
- file->private_data = &dev->iamthif_cl;
-
- client = &data->out_client_properties;
- client->max_msg_length =
- dev->me_clients[i].props.max_msg_length;
- client->protocol_version =
- dev->me_clients[i].props.protocol_version;
- rets = dev->iamthif_cl.status;
-
- goto end;
- }
-
- if (cl->state != MEI_FILE_CONNECTING) {
- rets = -ENODEV;
- goto end;
- }
-
-
- /* prepare the output buffer */
- client = &data->out_client_properties;
- client->max_msg_length = dev->me_clients[i].props.max_msg_length;
- client->protocol_version = dev->me_clients[i].props.protocol_version;
- dev_dbg(&dev->pdev->dev, "Can connect?\n");
- if (dev->mei_host_buffer_is_empty
- && !mei_other_client_is_connecting(dev, cl)) {
- dev_dbg(&dev->pdev->dev, "Sending Connect Message\n");
- dev->mei_host_buffer_is_empty = false;
- if (mei_connect(dev, cl)) {
- dev_dbg(&dev->pdev->dev, "Sending connect message - failed\n");
- rets = -ENODEV;
- goto end;
- } else {
- dev_dbg(&dev->pdev->dev, "Sending connect message - succeeded\n");
- cl->timer_count = MEI_CONNECT_TIMEOUT;
- cb->file_private = cl;
- list_add_tail(&cb->cb_list,
- &dev->ctrl_rd_list.mei_cb.
- cb_list);
- }
-
-
- } else {
- dev_dbg(&dev->pdev->dev, "Queuing the connect request due to device busy\n");
- cb->file_private = cl;
- dev_dbg(&dev->pdev->dev, "add connect cb to control write list.\n");
- list_add_tail(&cb->cb_list,
- &dev->ctrl_wr_list.mei_cb.cb_list);
- }
- mutex_unlock(&dev->device_lock);
- err = wait_event_timeout(dev->wait_recvd_msg,
- (MEI_FILE_CONNECTED == cl->state ||
- MEI_FILE_DISCONNECTED == cl->state),
- timeout * HZ);
-
- mutex_lock(&dev->device_lock);
- if (MEI_FILE_CONNECTED == cl->state) {
- dev_dbg(&dev->pdev->dev, "successfully connected to FW client.\n");
- rets = cl->status;
- goto end;
- } else {
- dev_dbg(&dev->pdev->dev, "failed to connect to FW client.cl->state = %d.\n",
- cl->state);
- if (!err) {
- dev_dbg(&dev->pdev->dev,
- "wait_event_interruptible_timeout failed on client"
- " connect message fw response message.\n");
- }
- rets = -EFAULT;
-
- mei_io_list_flush(&dev->ctrl_rd_list, cl);
- mei_io_list_flush(&dev->ctrl_wr_list, cl);
- goto end;
- }
- rets = 0;
-end:
- dev_dbg(&dev->pdev->dev, "free connect cb memory.");
- kfree(cb);
- return rets;
-}
-
-/**
- * find_amthi_read_list_entry - finds a amthilist entry for current file
- *
- * @dev: the device structure
- * @file: pointer to file object
- *
- * returns returned a list entry on success, NULL on failure.
- */
-struct mei_cl_cb *find_amthi_read_list_entry(
- struct mei_device *dev,
- struct file *file)
-{
- struct mei_cl *cl_temp;
- struct mei_cl_cb *pos = NULL;
- struct mei_cl_cb *next = NULL;
-
- list_for_each_entry_safe(pos, next,
- &dev->amthi_read_complete_list.mei_cb.cb_list, cb_list) {
- cl_temp = (struct mei_cl *)pos->file_private;
- if (cl_temp && cl_temp == &dev->iamthif_cl &&
- pos->file_object == file)
- return pos;
- }
- return NULL;
-}
-
-/**
- * amthi_read - read data from AMTHI client
- *
- * @dev: the device structure
- * @if_num: minor number
- * @file: pointer to file object
- * @*ubuf: pointer to user data in user space
- * @length: data length to read
- * @offset: data read offset
- *
- * Locking: called under "dev->device_lock" lock
- *
- * returns
- * returned data length on success,
- * zero if no data to read,
- * negative on failure.
- */
-int amthi_read(struct mei_device *dev, struct file *file,
- char __user *ubuf, size_t length, loff_t *offset)
-{
- int rets;
- int wait_ret;
- struct mei_cl_cb *cb = NULL;
- struct mei_cl *cl = file->private_data;
- unsigned long timeout;
- int i;
-
- /* Only Posible if we are in timeout */
- if (!cl || cl != &dev->iamthif_cl) {
- dev_dbg(&dev->pdev->dev, "bad file ext.\n");
- return -ETIMEDOUT;
- }
-
- for (i = 0; i < dev->me_clients_num; i++) {
- if (dev->me_clients[i].client_id ==
- dev->iamthif_cl.me_client_id)
- break;
- }
-
- if (i == dev->me_clients_num) {
- dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
- return -ENODEV;
- }
- if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id))
- return -ENODEV;
-
- dev_dbg(&dev->pdev->dev, "checking amthi data\n");
- cb = find_amthi_read_list_entry(dev, file);
-
- /* Check for if we can block or not*/
- if (cb == NULL && file->f_flags & O_NONBLOCK)
- return -EAGAIN;
-
-
- dev_dbg(&dev->pdev->dev, "waiting for amthi data\n");
- while (cb == NULL) {
- /* unlock the Mutex */
- mutex_unlock(&dev->device_lock);
-
- wait_ret = wait_event_interruptible(dev->iamthif_cl.wait,
- (cb = find_amthi_read_list_entry(dev, file)));
-
- if (wait_ret)
- return -ERESTARTSYS;
-
- dev_dbg(&dev->pdev->dev, "woke up from sleep\n");
-
- /* Locking again the Mutex */
- mutex_lock(&dev->device_lock);
- }
-
-
- dev_dbg(&dev->pdev->dev, "Got amthi data\n");
- dev->iamthif_timer = 0;
-
- if (cb) {
- timeout = cb->read_time +
- msecs_to_jiffies(IAMTHIF_READ_TIMER);
- dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n",
- timeout);
-
- if (time_after(jiffies, timeout)) {
- dev_dbg(&dev->pdev->dev, "amthi Time out\n");
- /* 15 sec for the message has expired */
- list_del(&cb->cb_list);
- rets = -ETIMEDOUT;
- goto free;
- }
- }
- /* if the whole message will fit remove it from the list */
- if (cb->information >= *offset && length >= (cb->information - *offset))
- list_del(&cb->cb_list);
- else if (cb->information > 0 && cb->information <= *offset) {
- /* end of the message has been reached */
- list_del(&cb->cb_list);
- rets = 0;
- goto free;
- }
- /* else means that not full buffer will be read and do not
- * remove message from deletion list
- */
-
- dev_dbg(&dev->pdev->dev, "amthi cb->response_buffer size - %d\n",
- cb->response_buffer.size);
- dev_dbg(&dev->pdev->dev, "amthi cb->information - %lu\n",
- cb->information);
-
- /* length is being turncated to PAGE_SIZE, however,
- * the information may be longer */
- length = min_t(size_t, length, (cb->information - *offset));
-
- if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length))
- rets = -EFAULT;
- else {
- rets = length;
- if ((*offset + length) < cb->information) {
- *offset += length;
- goto out;
- }
- }
-free:
- dev_dbg(&dev->pdev->dev, "free amthi cb memory.\n");
- *offset = 0;
- mei_free_cb_private(cb);
-out:
- return rets;
-}
-
-/**
- * mei_start_read - the start read client message function.
- *
- * @dev: the device structure
- * @if_num: minor number
- * @cl: private data of the file object
- *
- * returns 0 on success, <0 on failure.
- */
-int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
-{
- struct mei_cl_cb *cb;
- int rets = 0;
- int i;
-
- if (cl->state != MEI_FILE_CONNECTED)
- return -ENODEV;
-
- if (dev->mei_state != MEI_ENABLED)
- return -ENODEV;
-
- dev_dbg(&dev->pdev->dev, "check if read is pending.\n");
- if (cl->read_pending || cl->read_cb) {
- dev_dbg(&dev->pdev->dev, "read is pending.\n");
- return -EBUSY;
- }
-
- cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
- if (!cb)
- return -ENOMEM;
-
- dev_dbg(&dev->pdev->dev, "allocation call back successful. host client = %d, ME client = %d\n",
- cl->host_client_id, cl->me_client_id);
-
- for (i = 0; i < dev->me_clients_num; i++) {
- if (dev->me_clients[i].client_id == cl->me_client_id)
- break;
-
- }
-
- if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) {
- rets = -ENODEV;
- goto unlock;
- }
-
- if (i == dev->me_clients_num) {
- rets = -ENODEV;
- goto unlock;
- }
-
- cb->response_buffer.size = dev->me_clients[i].props.max_msg_length;
- cb->response_buffer.data =
- kmalloc(cb->response_buffer.size, GFP_KERNEL);
- if (!cb->response_buffer.data) {
- rets = -ENOMEM;
- goto unlock;
- }
- dev_dbg(&dev->pdev->dev, "allocation call back data success.\n");
- cb->major_file_operations = MEI_READ;
- /* make sure information is zero before we start */
- cb->information = 0;
- cb->file_private = (void *) cl;
- cl->read_cb = cb;
- if (dev->mei_host_buffer_is_empty) {
- dev->mei_host_buffer_is_empty = false;
- if (mei_send_flow_control(dev, cl)) {
- rets = -ENODEV;
- goto unlock;
- }
- list_add_tail(&cb->cb_list, &dev->read_list.mei_cb.cb_list);
- } else {
- list_add_tail(&cb->cb_list, &dev->ctrl_wr_list.mei_cb.cb_list);
- }
- return rets;
-unlock:
- mei_free_cb_private(cb);
- return rets;
-}
-
-/**
- * amthi_write - write iamthif data to amthi client
- *
- * @dev: the device structure
- * @cb: mei call back struct
- *
- * returns 0 on success, <0 on failure.
- */
-int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
-{
- struct mei_msg_hdr mei_hdr;
- int ret;
-
- if (!dev || !cb)
- return -ENODEV;
-
- dev_dbg(&dev->pdev->dev, "write data to amthi client.\n");
-
- dev->iamthif_state = MEI_IAMTHIF_WRITING;
- dev->iamthif_current_cb = cb;
- dev->iamthif_file_object = cb->file_object;
- dev->iamthif_canceled = false;
- dev->iamthif_ioctl = true;
- dev->iamthif_msg_buf_size = cb->request_buffer.size;
- memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
- cb->request_buffer.size);
-
- ret = mei_flow_ctrl_creds(dev, &dev->iamthif_cl);
- if (ret < 0)
- return ret;
-
- if (ret && dev->mei_host_buffer_is_empty) {
- ret = 0;
- dev->mei_host_buffer_is_empty = false;
- if (cb->request_buffer.size >
- (((dev->host_hw_state & H_CBD) >> 24) * sizeof(u32))
- -sizeof(struct mei_msg_hdr)) {
- mei_hdr.length =
- (((dev->host_hw_state & H_CBD) >> 24) *
- sizeof(u32)) - sizeof(struct mei_msg_hdr);
- mei_hdr.msg_complete = 0;
- } else {
- mei_hdr.length = cb->request_buffer.size;
- mei_hdr.msg_complete = 1;
- }
-
- mei_hdr.host_addr = dev->iamthif_cl.host_client_id;
- mei_hdr.me_addr = dev->iamthif_cl.me_client_id;
- mei_hdr.reserved = 0;
- dev->iamthif_msg_buf_index += mei_hdr.length;
- if (mei_write_message(dev, &mei_hdr,
- (unsigned char *)(dev->iamthif_msg_buf),
- mei_hdr.length))
- return -ENODEV;
-
- if (mei_hdr.msg_complete) {
- if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl))
- return -ENODEV;
- dev->iamthif_flow_control_pending = true;
- dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
- dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n");
- dev->iamthif_current_cb = cb;
- dev->iamthif_file_object = cb->file_object;
- list_add_tail(&cb->cb_list,
- &dev->write_waiting_list.mei_cb.cb_list);
- } else {
- dev_dbg(&dev->pdev->dev, "message does not complete, "
- "so add amthi cb to write list.\n");
- list_add_tail(&cb->cb_list,
- &dev->write_list.mei_cb.cb_list);
- }
- } else {
- if (!(dev->mei_host_buffer_is_empty))
- dev_dbg(&dev->pdev->dev, "host buffer is not empty");
-
- dev_dbg(&dev->pdev->dev, "No flow control credentials, "
- "so add iamthif cb to write list.\n");
- list_add_tail(&cb->cb_list, &dev->write_list.mei_cb.cb_list);
- }
- return 0;
-}
-
-/**
- * iamthif_ioctl_send_msg - send cmd data to amthi client
- *
- * @dev: the device structure
- *
- * returns 0 on success, <0 on failure.
- */
-void mei_run_next_iamthif_cmd(struct mei_device *dev)
-{
- struct mei_cl *cl_tmp;
- struct mei_cl_cb *pos = NULL;
- struct mei_cl_cb *next = NULL;
- int status;
-
- if (!dev)
- return;
-
- dev->iamthif_msg_buf_size = 0;
- dev->iamthif_msg_buf_index = 0;
- dev->iamthif_canceled = false;
- dev->iamthif_ioctl = true;
- dev->iamthif_state = MEI_IAMTHIF_IDLE;
- dev->iamthif_timer = 0;
- dev->iamthif_file_object = NULL;
-
- dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n");
-
- list_for_each_entry_safe(pos, next,
- &dev->amthi_cmd_list.mei_cb.cb_list, cb_list) {
- list_del(&pos->cb_list);
- cl_tmp = (struct mei_cl *)pos->file_private;
-
- if (cl_tmp && cl_tmp == &dev->iamthif_cl) {
- status = amthi_write(dev, pos);
- if (status) {
- dev_dbg(&dev->pdev->dev,
- "amthi write failed status = %d\n",
- status);
- return;
- }
- break;
- }
- }
-}
-
-/**
- * mei_free_cb_private - free mei_cb_private related memory
- *
- * @cb: mei callback struct
- */
-void mei_free_cb_private(struct mei_cl_cb *cb)
-{
- if (cb == NULL)
- return;
-
- kfree(cb->request_buffer.data);
- kfree(cb->response_buffer.data);
- kfree(cb);
-}
diff --git a/drivers/staging/mei/main.c b/drivers/staging/mei/main.c
deleted file mode 100644
index 7c9321f..0000000
--- a/drivers/staging/mei/main.c
+++ /dev/null
@@ -1,1237 +0,0 @@
-/*
- *
- * 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/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/aio.h>
-#include <linux/pci.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/ioctl.h>
-#include <linux/cdev.h>
-#include <linux/sched.h>
-#include <linux/uuid.h>
-#include <linux/compat.h>
-#include <linux/jiffies.h>
-#include <linux/interrupt.h>
-#include <linux/miscdevice.h>
-
-#include "mei_dev.h"
-#include "mei.h"
-#include "interface.h"
-
-
-#define MEI_READ_TIMEOUT 45
-#define MEI_DRIVER_NAME "mei"
-#define MEI_DEV_NAME "mei"
-
-/*
- * mei driver strings
- */
-static char mei_driver_name[] = MEI_DRIVER_NAME;
-static const char mei_driver_string[] = "Intel(R) Management Engine Interface";
-
-/* The device pointer */
-/* Currently this driver works as long as there is only a single AMT device. */
-struct pci_dev *mei_device;
-
-/* mei_pci_tbl - PCI Device ID Table */
-static DEFINE_PCI_DEVICE_TABLE(mei_pci_tbl) = {
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82946GZ)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82G35)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82Q965)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82G965)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82GM965)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82GME965)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82Q35)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82G33)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82Q33)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82X38)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_3200)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_6)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_7)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_8)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_9)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_10)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_1)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_2)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_3)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_4)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_1)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_2)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_3)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_4)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_IBXPK_1)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_IBXPK_2)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_CPT_1)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PBG_1)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_1)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_2)},
- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_3)},
-
- /* required last entry */
- {0, }
-};
-
-MODULE_DEVICE_TABLE(pci, mei_pci_tbl);
-
-static DEFINE_MUTEX(mei_mutex);
-
-
-/**
- * mei_clear_list - removes all callbacks associated with file
- * from mei_cb_list
- *
- * @dev: device structure.
- * @file: file structure
- * @mei_cb_list: callbacks list
- *
- * mei_clear_list is called to clear resources associated with file
- * when application calls close function or Ctrl-C was pressed
- *
- * returns true if callback removed from the list, false otherwise
- */
-static bool mei_clear_list(struct mei_device *dev,
- struct file *file, struct list_head *mei_cb_list)
-{
- struct mei_cl_cb *cb_pos = NULL;
- struct mei_cl_cb *cb_next = NULL;
- struct file *file_temp;
- bool removed = false;
-
- /* list all list member */
- list_for_each_entry_safe(cb_pos, cb_next, mei_cb_list, cb_list) {
- file_temp = (struct file *)cb_pos->file_object;
- /* check if list member associated with a file */
- if (file_temp == file) {
- /* remove member from the list */
- list_del(&cb_pos->cb_list);
- /* check if cb equal to current iamthif cb */
- if (dev->iamthif_current_cb == cb_pos) {
- dev->iamthif_current_cb = NULL;
- /* send flow control to iamthif client */
- mei_send_flow_control(dev, &dev->iamthif_cl);
- }
- /* free all allocated buffers */
- mei_free_cb_private(cb_pos);
- cb_pos = NULL;
- removed = true;
- }
- }
- return removed;
-}
-
-/**
- * mei_clear_lists - removes all callbacks associated with file
- *
- * @dev: device structure
- * @file: file structure
- *
- * mei_clear_lists is called to clear resources associated with file
- * when application calls close function or Ctrl-C was pressed
- *
- * returns true if callback removed from the list, false otherwise
- */
-static bool mei_clear_lists(struct mei_device *dev, struct file *file)
-{
- bool removed = false;
-
- /* remove callbacks associated with a file */
- mei_clear_list(dev, file, &dev->amthi_cmd_list.mei_cb.cb_list);
- if (mei_clear_list(dev, file,
- &dev->amthi_read_complete_list.mei_cb.cb_list))
- removed = true;
-
- mei_clear_list(dev, file, &dev->ctrl_rd_list.mei_cb.cb_list);
-
- if (mei_clear_list(dev, file, &dev->ctrl_wr_list.mei_cb.cb_list))
- removed = true;
-
- if (mei_clear_list(dev, file, &dev->write_waiting_list.mei_cb.cb_list))
- removed = true;
-
- if (mei_clear_list(dev, file, &dev->write_list.mei_cb.cb_list))
- removed = true;
-
- /* check if iamthif_current_cb not NULL */
- if (dev->iamthif_current_cb && !removed) {
- /* check file and iamthif current cb association */
- if (dev->iamthif_current_cb->file_object == file) {
- /* remove cb */
- mei_free_cb_private(dev->iamthif_current_cb);
- dev->iamthif_current_cb = NULL;
- removed = true;
- }
- }
- return removed;
-}
-/**
- * find_read_list_entry - find read list entry
- *
- * @dev: device structure
- * @file: pointer to file structure
- *
- * returns cb on success, NULL on error
- */
-static struct mei_cl_cb *find_read_list_entry(
- struct mei_device *dev,
- struct mei_cl *cl)
-{
- struct mei_cl_cb *pos = NULL;
- struct mei_cl_cb *next = NULL;
-
- dev_dbg(&dev->pdev->dev, "remove read_list CB\n");
- list_for_each_entry_safe(pos, next,
- &dev->read_list.mei_cb.cb_list, cb_list) {
- struct mei_cl *cl_temp;
- cl_temp = (struct mei_cl *)pos->file_private;
-
- if (mei_cl_cmp_id(cl, cl_temp))
- return pos;
- }
- return NULL;
-}
-
-/**
- * mei_open - the open function
- *
- * @inode: pointer to inode structure
- * @file: pointer to file structure
- *
- * returns 0 on success, <0 on error
- */
-static int mei_open(struct inode *inode, struct file *file)
-{
- struct mei_cl *cl;
- struct mei_device *dev;
- unsigned long cl_id;
- int err;
-
- err = -ENODEV;
- if (!mei_device)
- goto out;
-
- dev = pci_get_drvdata(mei_device);
- if (!dev)
- goto out;
-
- mutex_lock(&dev->device_lock);
- err = -ENOMEM;
- cl = mei_cl_allocate(dev);
- if (!cl)
- goto out_unlock;
-
- err = -ENODEV;
- if (dev->mei_state != MEI_ENABLED) {
- dev_dbg(&dev->pdev->dev, "mei_state != MEI_ENABLED mei_state= %d\n",
- dev->mei_state);
- goto out_unlock;
- }
- err = -EMFILE;
- if (dev->open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT)
- goto out_unlock;
-
- cl_id = find_first_zero_bit(dev->host_clients_map, MEI_CLIENTS_MAX);
- if (cl_id >= MEI_CLIENTS_MAX)
- goto out_unlock;
-
- cl->host_client_id = cl_id;
-
- dev_dbg(&dev->pdev->dev, "client_id = %d\n", cl->host_client_id);
-
- dev->open_handle_count++;
-
- list_add_tail(&cl->link, &dev->file_list);
-
- set_bit(cl->host_client_id, dev->host_clients_map);
- cl->state = MEI_FILE_INITIALIZING;
- cl->sm_state = 0;
-
- file->private_data = cl;
- mutex_unlock(&dev->device_lock);
-
- return nonseekable_open(inode, file);
-
-out_unlock:
- mutex_unlock(&dev->device_lock);
- kfree(cl);
-out:
- return err;
-}
-
-/**
- * mei_release - the release function
- *
- * @inode: pointer to inode structure
- * @file: pointer to file structure
- *
- * returns 0 on success, <0 on error
- */
-static int mei_release(struct inode *inode, struct file *file)
-{
- struct mei_cl *cl = file->private_data;
- struct mei_cl_cb *cb;
- struct mei_device *dev;
- int rets = 0;
-
- if (WARN_ON(!cl || !cl->dev))
- return -ENODEV;
-
- dev = cl->dev;
-
- mutex_lock(&dev->device_lock);
- if (cl != &dev->iamthif_cl) {
- if (cl->state == MEI_FILE_CONNECTED) {
- cl->state = MEI_FILE_DISCONNECTING;
- dev_dbg(&dev->pdev->dev,
- "disconnecting client host client = %d, "
- "ME client = %d\n",
- cl->host_client_id,
- cl->me_client_id);
- rets = mei_disconnect_host_client(dev, cl);
- }
- mei_cl_flush_queues(cl);
- dev_dbg(&dev->pdev->dev, "remove client host client = %d, ME client = %d\n",
- cl->host_client_id,
- cl->me_client_id);
-
- if (dev->open_handle_count > 0) {
- clear_bit(cl->host_client_id, dev->host_clients_map);
- dev->open_handle_count--;
- }
- mei_remove_client_from_file_list(dev, cl->host_client_id);
-
- /* free read cb */
- cb = NULL;
- if (cl->read_cb) {
- cb = find_read_list_entry(dev, cl);
- /* Remove entry from read list */
- if (cb)
- list_del(&cb->cb_list);
-
- cb = cl->read_cb;
- cl->read_cb = NULL;
- }
-
- file->private_data = NULL;
-
- if (cb) {
- mei_free_cb_private(cb);
- cb = NULL;
- }
-
- kfree(cl);
- } else {
- if (dev->open_handle_count > 0)
- dev->open_handle_count--;
-
- if (dev->iamthif_file_object == file &&
- dev->iamthif_state != MEI_IAMTHIF_IDLE) {
-
- dev_dbg(&dev->pdev->dev, "amthi canceled iamthif state %d\n",
- dev->iamthif_state);
- dev->iamthif_canceled = true;
- if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) {
- dev_dbg(&dev->pdev->dev, "run next amthi iamthif cb\n");
- mei_run_next_iamthif_cmd(dev);
- }
- }
-
- if (mei_clear_lists(dev, file))
- dev->iamthif_state = MEI_IAMTHIF_IDLE;
-
- }
- mutex_unlock(&dev->device_lock);
- return rets;
-}
-
-
-/**
- * mei_read - the read function.
- *
- * @file: pointer to file structure
- * @ubuf: pointer to user buffer
- * @length: buffer length
- * @offset: data offset in buffer
- *
- * returns >=0 data length on success , <0 on error
- */
-static ssize_t mei_read(struct file *file, char __user *ubuf,
- size_t length, loff_t *offset)
-{
- struct mei_cl *cl = file->private_data;
- struct mei_cl_cb *cb_pos = NULL;
- struct mei_cl_cb *cb = NULL;
- struct mei_device *dev;
- int i;
- int rets;
- int err;
-
-
- if (WARN_ON(!cl || !cl->dev))
- return -ENODEV;
-
- dev = cl->dev;
-
- mutex_lock(&dev->device_lock);
- if (dev->mei_state != MEI_ENABLED) {
- rets = -ENODEV;
- goto out;
- }
-
- if ((cl->sm_state & MEI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) {
- /* Do not allow to read watchdog client */
- i = mei_find_me_client_index(dev, mei_wd_guid);
- if (i >= 0) {
- struct mei_me_client *me_client = &dev->me_clients[i];
-
- if (cl->me_client_id == me_client->client_id) {
- rets = -EBADF;
- goto out;
- }
- }
- } else {
- cl->sm_state &= ~MEI_WD_STATE_INDEPENDENCE_MSG_SENT;
- }
-
- if (cl == &dev->iamthif_cl) {
- rets = amthi_read(dev, file, ubuf, length, offset);
- goto out;
- }
-
- if (cl->read_cb && cl->read_cb->information > *offset) {
- cb = cl->read_cb;
- goto copy_buffer;
- } else if (cl->read_cb && cl->read_cb->information > 0 &&
- cl->read_cb->information <= *offset) {
- cb = cl->read_cb;
- rets = 0;
- goto free;
- } else if ((!cl->read_cb || !cl->read_cb->information) &&
- *offset > 0) {
- /*Offset needs to be cleaned for contiguous reads*/
- *offset = 0;
- rets = 0;
- goto out;
- }
-
- err = mei_start_read(dev, cl);
- if (err && err != -EBUSY) {
- dev_dbg(&dev->pdev->dev,
- "mei start read failure with status = %d\n", err);
- rets = err;
- goto out;
- }
-
- if (MEI_READ_COMPLETE != cl->reading_state &&
- !waitqueue_active(&cl->rx_wait)) {
- if (file->f_flags & O_NONBLOCK) {
- rets = -EAGAIN;
- goto out;
- }
-
- mutex_unlock(&dev->device_lock);
-
- if (wait_event_interruptible(cl->rx_wait,
- (MEI_READ_COMPLETE == cl->reading_state ||
- MEI_FILE_INITIALIZING == cl->state ||
- MEI_FILE_DISCONNECTED == cl->state ||
- MEI_FILE_DISCONNECTING == cl->state))) {
- if (signal_pending(current))
- return -EINTR;
- return -ERESTARTSYS;
- }
-
- mutex_lock(&dev->device_lock);
- if (MEI_FILE_INITIALIZING == cl->state ||
- MEI_FILE_DISCONNECTED == cl->state ||
- MEI_FILE_DISCONNECTING == cl->state) {
- rets = -EBUSY;
- goto out;
- }
- }
-
- cb = cl->read_cb;
-
- if (!cb) {
- rets = -ENODEV;
- goto out;
- }
- if (cl->reading_state != MEI_READ_COMPLETE) {
- rets = 0;
- goto out;
- }
- /* now copy the data to user space */
-copy_buffer:
- dev_dbg(&dev->pdev->dev, "cb->response_buffer size - %d\n",
- cb->response_buffer.size);
- dev_dbg(&dev->pdev->dev, "cb->information - %lu\n",
- cb->information);
- if (length == 0 || ubuf == NULL || *offset > cb->information) {
- rets = -EMSGSIZE;
- goto free;
- }
-
- /* length is being truncated to PAGE_SIZE, however, */
- /* information size may be longer */
- length = min_t(size_t, length, (cb->information - *offset));
-
- if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
- rets = -EFAULT;
- goto free;
- }
-
- rets = length;
- *offset += length;
- if ((unsigned long)*offset < cb->information)
- goto out;
-
-free:
- cb_pos = find_read_list_entry(dev, cl);
- /* Remove entry from read list */
- if (cb_pos)
- list_del(&cb_pos->cb_list);
- mei_free_cb_private(cb);
- cl->reading_state = MEI_IDLE;
- cl->read_cb = NULL;
- cl->read_pending = 0;
-out:
- dev_dbg(&dev->pdev->dev, "end mei read rets= %d\n", rets);
- mutex_unlock(&dev->device_lock);
- return rets;
-}
-
-/**
- * mei_write - the write function.
- *
- * @file: pointer to file structure
- * @ubuf: pointer to user buffer
- * @length: buffer length
- * @offset: data offset in buffer
- *
- * returns >=0 data length on success , <0 on error
- */
-static ssize_t mei_write(struct file *file, const char __user *ubuf,
- size_t length, loff_t *offset)
-{
- struct mei_cl *cl = file->private_data;
- struct mei_cl_cb *write_cb = NULL;
- struct mei_msg_hdr mei_hdr;
- struct mei_device *dev;
- unsigned long timeout = 0;
- int rets;
- int i;
-
- if (WARN_ON(!cl || !cl->dev))
- return -ENODEV;
-
- dev = cl->dev;
-
- mutex_lock(&dev->device_lock);
-
- if (dev->mei_state != MEI_ENABLED) {
- mutex_unlock(&dev->device_lock);
- return -ENODEV;
- }
-
- if (cl == &dev->iamthif_cl) {
- write_cb = find_amthi_read_list_entry(dev, file);
-
- if (write_cb) {
- timeout = write_cb->read_time +
- msecs_to_jiffies(IAMTHIF_READ_TIMER);
-
- if (time_after(jiffies, timeout) ||
- cl->reading_state == MEI_READ_COMPLETE) {
- *offset = 0;
- list_del(&write_cb->cb_list);
- mei_free_cb_private(write_cb);
- write_cb = NULL;
- }
- }
- }
-
- /* free entry used in read */
- if (cl->reading_state == MEI_READ_COMPLETE) {
- *offset = 0;
- write_cb = find_read_list_entry(dev, cl);
- if (write_cb) {
- list_del(&write_cb->cb_list);
- mei_free_cb_private(write_cb);
- write_cb = NULL;
- cl->reading_state = MEI_IDLE;
- cl->read_cb = NULL;
- cl->read_pending = 0;
- }
- } else if (cl->reading_state == MEI_IDLE && !cl->read_pending)
- *offset = 0;
-
-
- write_cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
- if (!write_cb) {
- mutex_unlock(&dev->device_lock);
- return -ENOMEM;
- }
-
- write_cb->file_object = file;
- write_cb->file_private = cl;
- write_cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
- rets = -ENOMEM;
- if (!write_cb->request_buffer.data)
- goto unlock_dev;
-
- dev_dbg(&dev->pdev->dev, "length =%d\n", (int) length);
-
- rets = -EFAULT;
- if (copy_from_user(write_cb->request_buffer.data, ubuf, length))
- goto unlock_dev;
-
- cl->sm_state = 0;
- if (length == 4 &&
- ((memcmp(mei_wd_state_independence_msg[0],
- write_cb->request_buffer.data, 4) == 0) ||
- (memcmp(mei_wd_state_independence_msg[1],
- write_cb->request_buffer.data, 4) == 0) ||
- (memcmp(mei_wd_state_independence_msg[2],
- write_cb->request_buffer.data, 4) == 0)))
- cl->sm_state |= MEI_WD_STATE_INDEPENDENCE_MSG_SENT;
-
- INIT_LIST_HEAD(&write_cb->cb_list);
- if (cl == &dev->iamthif_cl) {
- write_cb->response_buffer.data =
- kmalloc(dev->iamthif_mtu, GFP_KERNEL);
- if (!write_cb->response_buffer.data) {
- rets = -ENOMEM;
- goto unlock_dev;
- }
- if (dev->mei_state != MEI_ENABLED) {
- rets = -ENODEV;
- goto unlock_dev;
- }
- for (i = 0; i < dev->me_clients_num; i++) {
- if (dev->me_clients[i].client_id ==
- dev->iamthif_cl.me_client_id)
- break;
- }
-
- if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) {
- rets = -ENODEV;
- goto unlock_dev;
- }
- if (i == dev->me_clients_num ||
- (dev->me_clients[i].client_id !=
- dev->iamthif_cl.me_client_id)) {
- rets = -ENODEV;
- goto unlock_dev;
- } else if (length > dev->me_clients[i].props.max_msg_length ||
- length <= 0) {
- rets = -EMSGSIZE;
- goto unlock_dev;
- }
-
- write_cb->response_buffer.size = dev->iamthif_mtu;
- write_cb->major_file_operations = MEI_IOCTL;
- write_cb->information = 0;
- write_cb->request_buffer.size = length;
- if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
- rets = -ENODEV;
- goto unlock_dev;
- }
-
- if (!list_empty(&dev->amthi_cmd_list.mei_cb.cb_list) ||
- dev->iamthif_state != MEI_IAMTHIF_IDLE) {
- dev_dbg(&dev->pdev->dev, "amthi_state = %d\n",
- (int) dev->iamthif_state);
- dev_dbg(&dev->pdev->dev, "add amthi cb to amthi cmd waiting list\n");
- list_add_tail(&write_cb->cb_list,
- &dev->amthi_cmd_list.mei_cb.cb_list);
- rets = length;
- } else {
- dev_dbg(&dev->pdev->dev, "call amthi write\n");
- rets = amthi_write(dev, write_cb);
-
- if (rets) {
- dev_dbg(&dev->pdev->dev, "amthi write failed with status = %d\n",
- rets);
- goto unlock_dev;
- }
- rets = length;
- }
- mutex_unlock(&dev->device_lock);
- return rets;
- }
-
- write_cb->major_file_operations = MEI_WRITE;
- /* make sure information is zero before we start */
-
- write_cb->information = 0;
- write_cb->request_buffer.size = length;
-
- dev_dbg(&dev->pdev->dev, "host client = %d, ME client = %d\n",
- cl->host_client_id, cl->me_client_id);
- if (cl->state != MEI_FILE_CONNECTED) {
- rets = -ENODEV;
- dev_dbg(&dev->pdev->dev, "host client = %d, is not connected to ME client = %d",
- cl->host_client_id,
- cl->me_client_id);
- goto unlock_dev;
- }
- for (i = 0; i < dev->me_clients_num; i++) {
- if (dev->me_clients[i].client_id ==
- cl->me_client_id)
- break;
- }
- if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) {
- rets = -ENODEV;
- goto unlock_dev;
- }
- if (i == dev->me_clients_num) {
- rets = -ENODEV;
- goto unlock_dev;
- }
- if (length > dev->me_clients[i].props.max_msg_length || length <= 0) {
- rets = -EINVAL;
- goto unlock_dev;
- }
- write_cb->file_private = cl;
-
- rets = mei_flow_ctrl_creds(dev, cl);
- if (rets < 0)
- goto unlock_dev;
-
- if (rets && dev->mei_host_buffer_is_empty) {
- rets = 0;
- dev->mei_host_buffer_is_empty = false;
- if (length > ((((dev->host_hw_state & H_CBD) >> 24) *
- sizeof(u32)) - sizeof(struct mei_msg_hdr))) {
-
- mei_hdr.length =
- (((dev->host_hw_state & H_CBD) >> 24) *
- sizeof(u32)) -
- sizeof(struct mei_msg_hdr);
- mei_hdr.msg_complete = 0;
- } else {
- mei_hdr.length = length;
- mei_hdr.msg_complete = 1;
- }
- mei_hdr.host_addr = cl->host_client_id;
- mei_hdr.me_addr = cl->me_client_id;
- mei_hdr.reserved = 0;
- dev_dbg(&dev->pdev->dev, "call mei_write_message header=%08x.\n",
- *((u32 *) &mei_hdr));
- if (mei_write_message(dev, &mei_hdr,
- (unsigned char *) (write_cb->request_buffer.data),
- mei_hdr.length)) {
- rets = -ENODEV;
- goto unlock_dev;
- }
- cl->writing_state = MEI_WRITING;
- write_cb->information = mei_hdr.length;
- if (mei_hdr.msg_complete) {
- if (mei_flow_ctrl_reduce(dev, cl)) {
- rets = -ENODEV;
- goto unlock_dev;
- }
- list_add_tail(&write_cb->cb_list,
- &dev->write_waiting_list.mei_cb.cb_list);
- } else {
- list_add_tail(&write_cb->cb_list,
- &dev->write_list.mei_cb.cb_list);
- }
-
- } else {
-
- write_cb->information = 0;
- cl->writing_state = MEI_WRITING;
- list_add_tail(&write_cb->cb_list,
- &dev->write_list.mei_cb.cb_list);
- }
- mutex_unlock(&dev->device_lock);
- return length;
-
-unlock_dev:
- mutex_unlock(&dev->device_lock);
- mei_free_cb_private(write_cb);
- return rets;
-}
-
-
-/**
- * mei_ioctl - the IOCTL function
- *
- * @file: pointer to file structure
- * @cmd: ioctl command
- * @data: pointer to mei message structure
- *
- * returns 0 on success , <0 on error
- */
-static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data)
-{
- struct mei_device *dev;
- struct mei_cl *cl = file->private_data;
- struct mei_connect_client_data *connect_data = NULL;
- int rets;
-
- if (cmd != IOCTL_MEI_CONNECT_CLIENT)
- return -EINVAL;
-
- if (WARN_ON(!cl || !cl->dev))
- return -ENODEV;
-
- dev = cl->dev;
-
- dev_dbg(&dev->pdev->dev, "IOCTL cmd = 0x%x", cmd);
-
- mutex_lock(&dev->device_lock);
- if (dev->mei_state != MEI_ENABLED) {
- rets = -ENODEV;
- goto out;
- }
-
- dev_dbg(&dev->pdev->dev, ": IOCTL_MEI_CONNECT_CLIENT.\n");
-
- connect_data = kzalloc(sizeof(struct mei_connect_client_data),
- GFP_KERNEL);
- if (!connect_data) {
- rets = -ENOMEM;
- goto out;
- }
- dev_dbg(&dev->pdev->dev, "copy connect data from user\n");
- if (copy_from_user(connect_data, (char __user *)data,
- sizeof(struct mei_connect_client_data))) {
- dev_dbg(&dev->pdev->dev, "failed to copy data from userland\n");
- rets = -EFAULT;
- goto out;
- }
- rets = mei_ioctl_connect_client(file, connect_data);
-
- /* if all is ok, copying the data back to user. */
- if (rets)
- goto out;
-
- dev_dbg(&dev->pdev->dev, "copy connect data to user\n");
- if (copy_to_user((char __user *)data, connect_data,
- sizeof(struct mei_connect_client_data))) {
- dev_dbg(&dev->pdev->dev, "failed to copy data to userland\n");
- rets = -EFAULT;
- goto out;
- }
-
-out:
- kfree(connect_data);
- mutex_unlock(&dev->device_lock);
- return rets;
-}
-
-/**
- * mei_compat_ioctl - the compat IOCTL function
- *
- * @file: pointer to file structure
- * @cmd: ioctl command
- * @data: pointer to mei message structure
- *
- * returns 0 on success , <0 on error
- */
-#ifdef CONFIG_COMPAT
-static long mei_compat_ioctl(struct file *file,
- unsigned int cmd, unsigned long data)
-{
- return mei_ioctl(file, cmd, (unsigned long)compat_ptr(data));
-}
-#endif
-
-
-/**
- * mei_poll - the poll function
- *
- * @file: pointer to file structure
- * @wait: pointer to poll_table structure
- *
- * returns poll mask
- */
-static unsigned int mei_poll(struct file *file, poll_table *wait)
-{
- struct mei_cl *cl = file->private_data;
- struct mei_device *dev;
- unsigned int mask = 0;
-
- if (WARN_ON(!cl || !cl->dev))
- return mask;
-
- dev = cl->dev;
-
- mutex_lock(&dev->device_lock);
-
- if (dev->mei_state != MEI_ENABLED)
- goto out;
-
-
- if (cl == &dev->iamthif_cl) {
- mutex_unlock(&dev->device_lock);
- poll_wait(file, &dev->iamthif_cl.wait, wait);
- mutex_lock(&dev->device_lock);
- if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
- dev->iamthif_file_object == file) {
- mask |= (POLLIN | POLLRDNORM);
- dev_dbg(&dev->pdev->dev, "run next amthi cb\n");
- mei_run_next_iamthif_cmd(dev);
- }
- goto out;
- }
-
- mutex_unlock(&dev->device_lock);
- poll_wait(file, &cl->tx_wait, wait);
- mutex_lock(&dev->device_lock);
- if (MEI_WRITE_COMPLETE == cl->writing_state)
- mask |= (POLLIN | POLLRDNORM);
-
-out:
- mutex_unlock(&dev->device_lock);
- return mask;
-}
-
-/*
- * file operations structure will be used for mei char device.
- */
-static const struct file_operations mei_fops = {
- .owner = THIS_MODULE,
- .read = mei_read,
- .unlocked_ioctl = mei_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = mei_compat_ioctl,
-#endif
- .open = mei_open,
- .release = mei_release,
- .write = mei_write,
- .poll = mei_poll,
- .llseek = no_llseek
-};
-
-
-/*
- * Misc Device Struct
- */
-static struct miscdevice mei_misc_device = {
- .name = MEI_DRIVER_NAME,
- .fops = &mei_fops,
- .minor = MISC_DYNAMIC_MINOR,
-};
-
-/**
- * mei_probe - Device Initialization Routine
- *
- * @pdev: PCI device structure
- * @ent: entry in kcs_pci_tbl
- *
- * returns 0 on success, <0 on failure.
- */
-static int __devinit mei_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- struct mei_device *dev;
- int err;
-
- mutex_lock(&mei_mutex);
- if (mei_device) {
- err = -EEXIST;
- goto end;
- }
- /* enable pci dev */
- err = pci_enable_device(pdev);
- if (err) {
- printk(KERN_ERR "mei: Failed to enable pci device.\n");
- goto end;
- }
- /* set PCI host mastering */
- pci_set_master(pdev);
- /* pci request regions for mei driver */
- err = pci_request_regions(pdev, mei_driver_name);
- if (err) {
- printk(KERN_ERR "mei: Failed to get pci regions.\n");
- goto disable_device;
- }
- /* allocates and initializes the mei dev structure */
- dev = mei_device_init(pdev);
- if (!dev) {
- err = -ENOMEM;
- goto release_regions;
- }
- /* mapping IO device memory */
- dev->mem_addr = pci_iomap(pdev, 0, 0);
- if (!dev->mem_addr) {
- printk(KERN_ERR "mei: mapping I/O device memory failure.\n");
- err = -ENOMEM;
- goto free_device;
- }
- pci_enable_msi(pdev);
-
- /* request and enable interrupt */
- if (pci_dev_msi_enabled(pdev))
- err = request_threaded_irq(pdev->irq,
- NULL,
- mei_interrupt_thread_handler,
- 0, mei_driver_name, dev);
- else
- err = request_threaded_irq(pdev->irq,
- mei_interrupt_quick_handler,
- mei_interrupt_thread_handler,
- IRQF_SHARED, mei_driver_name, dev);
-
- if (err) {
- printk(KERN_ERR "mei: request_threaded_irq failure. irq = %d\n",
- pdev->irq);
- goto unmap_memory;
- }
- INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
- if (mei_hw_init(dev)) {
- printk(KERN_ERR "mei: Init hw failure.\n");
- err = -ENODEV;
- goto release_irq;
- }
-
- err = misc_register(&mei_misc_device);
- if (err)
- goto release_irq;
-
- mei_device = pdev;
- pci_set_drvdata(pdev, dev);
-
-
- schedule_delayed_work(&dev->timer_work, HZ);
-
- mutex_unlock(&mei_mutex);
-
- pr_debug("mei: Driver initialization successful.\n");
-
- return 0;
-
-release_irq:
- /* disable interrupts */
- dev->host_hw_state = mei_hcsr_read(dev);
- mei_disable_interrupts(dev);
- flush_scheduled_work();
- free_irq(pdev->irq, dev);
- pci_disable_msi(pdev);
-unmap_memory:
- pci_iounmap(pdev, dev->mem_addr);
-free_device:
- kfree(dev);
-release_regions:
- pci_release_regions(pdev);
-disable_device:
- pci_disable_device(pdev);
-end:
- mutex_unlock(&mei_mutex);
- printk(KERN_ERR "mei: Driver initialization failed.\n");
- return err;
-}
-
-/**
- * mei_remove - Device Removal Routine
- *
- * @pdev: PCI device structure
- *
- * mei_remove is called by the PCI subsystem to alert the driver
- * that it should release a PCI device.
- */
-static void __devexit mei_remove(struct pci_dev *pdev)
-{
- struct mei_device *dev;
-
- if (mei_device != pdev)
- return;
-
- dev = pci_get_drvdata(pdev);
- if (!dev)
- return;
-
- mutex_lock(&dev->device_lock);
-
- mei_wd_stop(dev, false);
-
- mei_device = NULL;
-
- if (dev->iamthif_cl.state == MEI_FILE_CONNECTED) {
- dev->iamthif_cl.state = MEI_FILE_DISCONNECTING;
- mei_disconnect_host_client(dev, &dev->iamthif_cl);
- }
- if (dev->wd_cl.state == MEI_FILE_CONNECTED) {
- dev->wd_cl.state = MEI_FILE_DISCONNECTING;
- mei_disconnect_host_client(dev, &dev->wd_cl);
- }
-
- /* Unregistering watchdog device */
- mei_watchdog_unregister(dev);
-
- /* remove entry if already in list */
- dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n");
- mei_remove_client_from_file_list(dev, dev->wd_cl.host_client_id);
- mei_remove_client_from_file_list(dev, dev->iamthif_cl.host_client_id);
-
- dev->iamthif_current_cb = NULL;
- dev->me_clients_num = 0;
-
- mutex_unlock(&dev->device_lock);
-
- flush_scheduled_work();
-
- /* disable interrupts */
- mei_disable_interrupts(dev);
-
- free_irq(pdev->irq, dev);
- pci_disable_msi(pdev);
- pci_set_drvdata(pdev, NULL);
-
- if (dev->mem_addr)
- pci_iounmap(pdev, dev->mem_addr);
-
- kfree(dev);
-
- pci_release_regions(pdev);
- pci_disable_device(pdev);
-}
-#ifdef CONFIG_PM
-static int mei_pci_suspend(struct device *device)
-{
- struct pci_dev *pdev = to_pci_dev(device);
- struct mei_device *dev = pci_get_drvdata(pdev);
- int err;
-
- if (!dev)
- return -ENODEV;
- mutex_lock(&dev->device_lock);
- /* Stop watchdog if exists */
- err = mei_wd_stop(dev, true);
- /* Set new mei state */
- if (dev->mei_state == MEI_ENABLED ||
- dev->mei_state == MEI_RECOVERING_FROM_RESET) {
- dev->mei_state = MEI_POWER_DOWN;
- mei_reset(dev, 0);
- }
- mutex_unlock(&dev->device_lock);
-
- free_irq(pdev->irq, dev);
- pci_disable_msi(pdev);
-
- return err;
-}
-
-static int mei_pci_resume(struct device *device)
-{
- struct pci_dev *pdev = to_pci_dev(device);
- struct mei_device *dev;
- int err;
-
- dev = pci_get_drvdata(pdev);
- if (!dev)
- return -ENODEV;
-
- pci_enable_msi(pdev);
-
- /* request and enable interrupt */
- if (pci_dev_msi_enabled(pdev))
- err = request_threaded_irq(pdev->irq,
- NULL,
- mei_interrupt_thread_handler,
- 0, mei_driver_name, dev);
- else
- err = request_threaded_irq(pdev->irq,
- mei_interrupt_quick_handler,
- mei_interrupt_thread_handler,
- IRQF_SHARED, mei_driver_name, dev);
-
- if (err) {
- printk(KERN_ERR "mei: Request_irq failure. irq = %d\n",
- pdev->irq);
- return err;
- }
-
- mutex_lock(&dev->device_lock);
- dev->mei_state = MEI_POWER_UP;
- mei_reset(dev, 1);
- mutex_unlock(&dev->device_lock);
-
- /* Start timer if stopped in suspend */
- schedule_delayed_work(&dev->timer_work, HZ);
-
- return err;
-}
-static SIMPLE_DEV_PM_OPS(mei_pm_ops, mei_pci_suspend, mei_pci_resume);
-#define MEI_PM_OPS (&mei_pm_ops)
-#else
-#define MEI_PM_OPS NULL
-#endif /* CONFIG_PM */
-/*
- * PCI driver structure
- */
-static struct pci_driver mei_driver = {
- .name = mei_driver_name,
- .id_table = mei_pci_tbl,
- .probe = mei_probe,
- .remove = __devexit_p(mei_remove),
- .shutdown = __devexit_p(mei_remove),
- .driver.pm = MEI_PM_OPS,
-};
-
-/**
- * mei_init_module - Driver Registration Routine
- *
- * mei_init_module is the first routine called when the driver is
- * loaded. All it does is to register with the PCI subsystem.
- *
- * returns 0 on success, <0 on failure.
- */
-static int __init mei_init_module(void)
-{
- int ret;
-
- pr_debug("mei: %s\n", mei_driver_string);
- /* init pci module */
- ret = pci_register_driver(&mei_driver);
- if (ret < 0)
- printk(KERN_ERR "mei: Error registering driver.\n");
-
- return ret;
-}
-
-module_init(mei_init_module);
-
-/**
- * mei_exit_module - Driver Exit Cleanup Routine
- *
- * mei_exit_module is called just before the driver is removed
- * from memory.
- */
-static void __exit mei_exit_module(void)
-{
- misc_deregister(&mei_misc_device);
- pci_unregister_driver(&mei_driver);
-
- pr_debug("mei: Driver unloaded successfully.\n");
-}
-
-module_exit(mei_exit_module);
-
-
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Intel(R) Management Engine Interface");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/mei/mei-amt-version.c b/drivers/staging/mei/mei-amt-version.c
deleted file mode 100644
index ac2a507..0000000
--- a/drivers/staging/mei/mei-amt-version.c
+++ /dev/null
@@ -1,481 +0,0 @@
-/******************************************************************************
- * Intel Management Engine Interface (Intel MEI) Linux driver
- * Intel MEI Interface Header
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2012 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- * Intel Corporation.
- * linux-mei@linux.intel.com
- * http://www.intel.com
- *
- * BSD LICENSE
- *
- * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *****************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <bits/wordsize.h>
-#include "mei.h"
-
-/*****************************************************************************
- * Intel Management Engine Interface
- *****************************************************************************/
-
-#define mei_msg(_me, fmt, ARGS...) do { \
- if (_me->verbose) \
- fprintf(stderr, fmt, ##ARGS); \
-} while (0)
-
-#define mei_err(_me, fmt, ARGS...) do { \
- fprintf(stderr, "Error: " fmt, ##ARGS); \
-} while (0)
-
-struct mei {
- uuid_le guid;
- bool initialized;
- bool verbose;
- unsigned int buf_size;
- unsigned char prot_ver;
- int fd;
-};
-
-static void mei_deinit(struct mei *cl)
-{
- if (cl->fd != -1)
- close(cl->fd);
- cl->fd = -1;
- cl->buf_size = 0;
- cl->prot_ver = 0;
- cl->initialized = false;
-}
-
-static bool mei_init(struct mei *me, const uuid_le *guid,
- unsigned char req_protocol_version, bool verbose)
-{
- int result;
- struct mei_client *cl;
- struct mei_connect_client_data data;
-
- mei_deinit(me);
-
- me->verbose = verbose;
-
- me->fd = open("/dev/mei", O_RDWR);
- if (me->fd == -1) {
- mei_err(me, "Cannot establish a handle to the Intel MEI driver\n");
- goto err;
- }
- memcpy(&me->guid, guid, sizeof(*guid));
- memset(&data, 0, sizeof(data));
- me->initialized = true;
-
- memcpy(&data.in_client_uuid, &me->guid, sizeof(me->guid));
- result = ioctl(me->fd, IOCTL_MEI_CONNECT_CLIENT, &data);
- if (result) {
- mei_err(me, "IOCTL_MEI_CONNECT_CLIENT receive message. err=%d\n", result);
- goto err;
- }
- cl = &data.out_client_properties;
- mei_msg(me, "max_message_length %d\n", cl->max_msg_length);
- mei_msg(me, "protocol_version %d\n", cl->protocol_version);
-
- if ((req_protocol_version > 0) &&
- (cl->protocol_version != req_protocol_version)) {
- mei_err(me, "Intel MEI protocol version not supported\n");
- goto err;
- }
-
- me->buf_size = cl->max_msg_length;
- me->prot_ver = cl->protocol_version;
-
- return true;
-err:
- mei_deinit(me);
- return false;
-}
-
-static ssize_t mei_recv_msg(struct mei *me, unsigned char *buffer,
- ssize_t len, unsigned long timeout)
-{
- ssize_t rc;
-
- mei_msg(me, "call read length = %zd\n", len);
-
- rc = read(me->fd, buffer, len);
- if (rc < 0) {
- mei_err(me, "read failed with status %zd %s\n",
- rc, strerror(errno));
- mei_deinit(me);
- } else {
- mei_msg(me, "read succeeded with result %zd\n", rc);
- }
- return rc;
-}
-
-static ssize_t mei_send_msg(struct mei *me, const unsigned char *buffer,
- ssize_t len, unsigned long timeout)
-{
- struct timeval tv;
- ssize_t written;
- ssize_t rc;
- fd_set set;
-
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000000;
-
- mei_msg(me, "call write length = %zd\n", len);
-
- written = write(me->fd, buffer, len);
- if (written < 0) {
- rc = -errno;
- mei_err(me, "write failed with status %zd %s\n",
- written, strerror(errno));
- goto out;
- }
-
- FD_ZERO(&set);
- FD_SET(me->fd, &set);
- rc = select(me->fd + 1 , &set, NULL, NULL, &tv);
- if (rc > 0 && FD_ISSET(me->fd, &set)) {
- mei_msg(me, "write success\n");
- } else if (rc == 0) {
- mei_err(me, "write failed on timeout with status\n");
- goto out;
- } else { /* rc < 0 */
- mei_err(me, "write failed on select with status %zd\n", rc);
- goto out;
- }
-
- rc = written;
-out:
- if (rc < 0)
- mei_deinit(me);
-
- return rc;
-}
-
-/***************************************************************************
- * Intel Advanced Management Technolgy ME Client
- ***************************************************************************/
-
-#define AMT_MAJOR_VERSION 1
-#define AMT_MINOR_VERSION 1
-
-#define AMT_STATUS_SUCCESS 0x0
-#define AMT_STATUS_INTERNAL_ERROR 0x1
-#define AMT_STATUS_NOT_READY 0x2
-#define AMT_STATUS_INVALID_AMT_MODE 0x3
-#define AMT_STATUS_INVALID_MESSAGE_LENGTH 0x4
-
-#define AMT_STATUS_HOST_IF_EMPTY_RESPONSE 0x4000
-#define AMT_STATUS_SDK_RESOURCES 0x1004
-
-
-#define AMT_BIOS_VERSION_LEN 65
-#define AMT_VERSIONS_NUMBER 50
-#define AMT_UNICODE_STRING_LEN 20
-
-struct amt_unicode_string {
- uint16_t length;
- char string[AMT_UNICODE_STRING_LEN];
-} __attribute__((packed));
-
-struct amt_version_type {
- struct amt_unicode_string description;
- struct amt_unicode_string version;
-} __attribute__((packed));
-
-struct amt_version {
- uint8_t major;
- uint8_t minor;
-} __attribute__((packed));
-
-struct amt_code_versions {
- uint8_t bios[AMT_BIOS_VERSION_LEN];
- uint32_t count;
- struct amt_version_type versions[AMT_VERSIONS_NUMBER];
-} __attribute__((packed));
-
-/***************************************************************************
- * Intel Advanced Management Technolgy Host Interface
- ***************************************************************************/
-
-struct amt_host_if_msg_header {
- struct amt_version version;
- uint16_t _reserved;
- uint32_t command;
- uint32_t length;
-} __attribute__((packed));
-
-struct amt_host_if_resp_header {
- struct amt_host_if_msg_header header;
- uint32_t status;
- unsigned char data[0];
-} __attribute__((packed));
-
-const uuid_le MEI_IAMTHIF = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, \
- 0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, 0x81, 0x4c);
-
-#define AMT_HOST_IF_CODE_VERSIONS_REQUEST 0x0400001A
-#define AMT_HOST_IF_CODE_VERSIONS_RESPONSE 0x0480001A
-
-const struct amt_host_if_msg_header CODE_VERSION_REQ = {
- .version = {AMT_MAJOR_VERSION, AMT_MINOR_VERSION},
- ._reserved = 0,
- .command = AMT_HOST_IF_CODE_VERSIONS_REQUEST,
- .length = 0
-};
-
-
-struct amt_host_if {
- struct mei mei_cl;
- unsigned long send_timeout;
- bool initialized;
-};
-
-
-static bool amt_host_if_init(struct amt_host_if *acmd,
- unsigned long send_timeout, bool verbose)
-{
- acmd->send_timeout = (send_timeout) ? send_timeout : 20000;
- acmd->initialized = mei_init(&acmd->mei_cl, &MEI_IAMTHIF, 0, verbose);
- return acmd->initialized;
-}
-
-static void amt_host_if_deinit(struct amt_host_if *acmd)
-{
- mei_deinit(&acmd->mei_cl);
- acmd->initialized = false;
-}
-
-static uint32_t amt_verify_code_versions(const struct amt_host_if_resp_header *resp)
-{
- uint32_t status = AMT_STATUS_SUCCESS;
- struct amt_code_versions *code_ver;
- size_t code_ver_len;
- uint32_t ver_type_cnt;
- uint32_t len;
- uint32_t i;
-
- code_ver = (struct amt_code_versions *)resp->data;
- /* length - sizeof(status) */
- code_ver_len = resp->header.length - sizeof(uint32_t);
- ver_type_cnt = code_ver_len -
- sizeof(code_ver->bios) -
- sizeof(code_ver->count);
- if (code_ver->count != ver_type_cnt / sizeof(struct amt_version_type)) {
- status = AMT_STATUS_INTERNAL_ERROR;
- goto out;
- }
-
- for (i = 0; i < code_ver->count; i++) {
- len = code_ver->versions[i].description.length;
-
- if (len > AMT_UNICODE_STRING_LEN) {
- status = AMT_STATUS_INTERNAL_ERROR;
- goto out;
- }
-
- len = code_ver->versions[i].version.length;
- if (code_ver->versions[i].version.string[len] != '\0' ||
- len != strlen(code_ver->versions[i].version.string)) {
- status = AMT_STATUS_INTERNAL_ERROR;
- goto out;
- }
- }
-out:
- return status;
-}
-
-static uint32_t amt_verify_response_header(uint32_t command,
- const struct amt_host_if_msg_header *resp_hdr,
- uint32_t response_size)
-{
- if (response_size < sizeof(struct amt_host_if_resp_header)) {
- return AMT_STATUS_INTERNAL_ERROR;
- } else if (response_size != (resp_hdr->length +
- sizeof(struct amt_host_if_msg_header))) {
- return AMT_STATUS_INTERNAL_ERROR;
- } else if (resp_hdr->command != command) {
- return AMT_STATUS_INTERNAL_ERROR;
- } else if (resp_hdr->_reserved != 0) {
- return AMT_STATUS_INTERNAL_ERROR;
- } else if (resp_hdr->version.major != AMT_MAJOR_VERSION ||
- resp_hdr->version.minor < AMT_MINOR_VERSION) {
- return AMT_STATUS_INTERNAL_ERROR;
- }
- return AMT_STATUS_SUCCESS;
-}
-
-static uint32_t amt_host_if_call(struct amt_host_if *acmd,
- const unsigned char *command, ssize_t command_sz,
- uint8_t **read_buf, uint32_t rcmd,
- unsigned int expected_sz)
-{
- uint32_t in_buf_sz;
- uint32_t out_buf_sz;
- ssize_t written;
- uint32_t status;
- struct amt_host_if_resp_header *msg_hdr;
-
- in_buf_sz = acmd->mei_cl.buf_size;
- *read_buf = (uint8_t *)malloc(sizeof(uint8_t) * in_buf_sz);
- if (*read_buf == NULL)
- return AMT_STATUS_SDK_RESOURCES;
- memset(*read_buf, 0, in_buf_sz);
- msg_hdr = (struct amt_host_if_resp_header *)*read_buf;
-
- written = mei_send_msg(&acmd->mei_cl,
- command, command_sz, acmd->send_timeout);
- if (written != command_sz)
- return AMT_STATUS_INTERNAL_ERROR;
-
- out_buf_sz = mei_recv_msg(&acmd->mei_cl, *read_buf, in_buf_sz, 2000);
- if (out_buf_sz <= 0)
- return AMT_STATUS_HOST_IF_EMPTY_RESPONSE;
-
- status = msg_hdr->status;
- if (status != AMT_STATUS_SUCCESS)
- return status;
-
- status = amt_verify_response_header(rcmd,
- &msg_hdr->header, out_buf_sz);
- if (status != AMT_STATUS_SUCCESS)
- return status;
-
- if (expected_sz && expected_sz != out_buf_sz)
- return AMT_STATUS_INTERNAL_ERROR;
-
- return AMT_STATUS_SUCCESS;
-}
-
-
-static uint32_t amt_get_code_versions(struct amt_host_if *cmd,
- struct amt_code_versions *versions)
-{
- struct amt_host_if_resp_header *response = NULL;
- uint32_t status;
-
- status = amt_host_if_call(cmd,
- (const unsigned char *)&CODE_VERSION_REQ,
- sizeof(CODE_VERSION_REQ),
- (uint8_t **)&response,
- AMT_HOST_IF_CODE_VERSIONS_RESPONSE, 0);
-
- if (status != AMT_STATUS_SUCCESS)
- goto out;
-
- status = amt_verify_code_versions(response);
- if (status != AMT_STATUS_SUCCESS)
- goto out;
-
- memcpy(versions, response->data, sizeof(struct amt_code_versions));
-out:
- if (response != NULL)
- free(response);
-
- return status;
-}
-
-/************************** end of amt_host_if_command ***********************/
-int main(int argc, char **argv)
-{
- struct amt_code_versions ver;
- struct amt_host_if acmd;
- unsigned int i;
- uint32_t status;
- int ret;
- bool verbose;
-
- verbose = (argc > 1 && strcmp(argv[1], "-v") == 0);
-
- if (!amt_host_if_init(&acmd, 5000, verbose)) {
- ret = 1;
- goto out;
- }
-
- status = amt_get_code_versions(&acmd, &ver);
-
- amt_host_if_deinit(&acmd);
-
- switch (status) {
- case AMT_STATUS_HOST_IF_EMPTY_RESPONSE:
- printf("Intel AMT: DISABLED\n");
- ret = 0;
- break;
- case AMT_STATUS_SUCCESS:
- printf("Intel AMT: ENABLED\n");
- for (i = 0; i < ver.count; i++) {
- printf("%s:\t%s\n", ver.versions[i].description.string,
- ver.versions[i].version.string);
- }
- ret = 0;
- break;
- default:
- printf("An error has occurred\n");
- ret = 1;
- break;
- }
-
-out:
- return ret;
-}
diff --git a/drivers/staging/mei/mei.h b/drivers/staging/mei/mei.h
deleted file mode 100644
index bc0d8b6..0000000
--- a/drivers/staging/mei/mei.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/******************************************************************************
- * Intel Management Engine Interface (Intel MEI) Linux driver
- * Intel MEI Interface Header
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- * Intel Corporation.
- * linux-mei@linux.intel.com
- * http://www.intel.com
- *
- * BSD LICENSE
- *
- * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *****************************************************************************/
-
-#ifndef _LINUX_MEI_H
-#define _LINUX_MEI_H
-
-#include <linux/uuid.h>
-
-/*
- * This IOCTL is used to associate the current file descriptor with a
- * FW Client (given by UUID). This opens a communication channel
- * between a host client and a FW client. From this point every read and write
- * will communicate with the associated FW client.
- * Only in close() (file_operation release()) the communication between
- * the clients is disconnected
- *
- * The IOCTL argument is a struct with a union that contains
- * the input parameter and the output parameter for this IOCTL.
- *
- * The input parameter is UUID of the FW Client.
- * The output parameter is the properties of the FW client
- * (FW protocol version and max message size).
- *
- */
-#define IOCTL_MEI_CONNECT_CLIENT \
- _IOWR('H' , 0x01, struct mei_connect_client_data)
-
-/*
- * Intel MEI client information struct
- */
-struct mei_client {
- __u32 max_msg_length;
- __u8 protocol_version;
- __u8 reserved[3];
-};
-
-/*
- * IOCTL Connect Client Data structure
- */
-struct mei_connect_client_data {
- union {
- uuid_le in_client_uuid;
- struct mei_client out_client_properties;
- };
-};
-
-#endif /* _LINUX_MEI_H */
diff --git a/drivers/staging/mei/mei.txt b/drivers/staging/mei/mei.txt
deleted file mode 100644
index 2785697..0000000
--- a/drivers/staging/mei/mei.txt
+++ /dev/null
@@ -1,215 +0,0 @@
-Intel(R) Management Engine Interface (Intel(R) MEI)
-=======================
-
-Introduction
-=======================
-
-The Intel Management Engine (Intel ME) is an isolated and protected computing
-resource (Co-processor) residing inside certain Intel chipsets. The Intel ME
-provides support for computer/IT management features. The feature set
-depends on the Intel chipset SKU.
-
-The Intel Management Engine Interface (Intel MEI, previously known as HECI)
-is the interface between the Host and Intel ME. This interface is exposed
-to the host as a PCI device. The Intel MEI Driver is in charge of the
-communication channel between a host application and the Intel ME feature.
-
-Each Intel ME feature (Intel ME Client) is addressed by a GUID/UUID and
-each client has its own protocol. The protocol is message-based with a
-header and payload up to 512 bytes.
-
-Prominent usage of the Intel ME Interface is to communicate with Intel(R)
-Active Management Technology (Intel AMT)implemented in firmware running on
-the Intel ME.
-
-Intel AMT provides the ability to manage a host remotely out-of-band (OOB)
-even when the operating system running on the host processor has crashed or
-is in a sleep state.
-
-Some examples of Intel AMT usage are:
- - Monitoring hardware state and platform components
- - Remote power off/on (useful for green computing or overnight IT
- maintenance)
- - OS updates
- - Storage of useful platform information such as software assets
- - Built-in hardware KVM
- - Selective network isolation of Ethernet and IP protocol flows based
- on policies set by a remote management console
- - IDE device redirection from remote management console
-
-Intel AMT (OOB) communication is based on SOAP (deprecated
-starting with Release 6.0) over HTTP/S or WS-Management protocol over
-HTTP/S that are received from a remote management console application.
-
-For more information about Intel AMT:
-http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide
-
-Intel MEI Driver
-=======================
-
-The driver exposes a misc device called /dev/mei.
-
-An application maintains communication with an Intel ME feature while
-/dev/mei is open. The binding to a specific features is performed by calling
-MEI_CONNECT_CLIENT_IOCTL, which passes the desired UUID.
-The number of instances of an Intel ME feature that can be opened
-at the same time depends on the Intel ME feature, but most of the
-features allow only a single instance.
-
-The Intel AMT Host Interface (Intel AMTHI) feature supports multiple
-simultaneous user applications. Therefore, the Intel MEI driver handles
-this internally by maintaining request queues for the applications.
-
-The driver is oblivious to data that is passed between firmware feature
-and host application.
-
-Because some of the Intel ME features can change the system
-configuration, the driver by default allows only a privileged
-user to access it.
-
-A code snippet for an application communicating with
-Intel AMTHI client:
- struct mei_connect_client_data data;
- fd = open(MEI_DEVICE);
-
- data.d.in_client_uuid = AMTHI_UUID;
-
- ioctl(fd, IOCTL_MEI_CONNECT_CLIENT, &data);
-
- printf("Ver=%d, MaxLen=%ld\n",
- data.d.in_client_uuid.protocol_version,
- data.d.in_client_uuid.max_msg_length);
-
- [...]
-
- write(fd, amthi_req_data, amthi_req_data_len);
-
- [...]
-
- read(fd, &amthi_res_data, amthi_res_data_len);
-
- [...]
- close(fd);
-
-IOCTL:
-======
-The Intel MEI Driver supports the following IOCTL command:
- IOCTL_MEI_CONNECT_CLIENT Connect to firmware Feature (client).
-
- usage:
- struct mei_connect_client_data clientData;
- ioctl(fd, IOCTL_MEI_CONNECT_CLIENT, &clientData);
-
- inputs:
- mei_connect_client_data struct contain the following
- input field:
-
- in_client_uuid - UUID of the FW Feature that needs
- to connect to.
- outputs:
- out_client_properties - Client Properties: MTU and Protocol Version.
-
- error returns:
- EINVAL Wrong IOCTL Number
- ENODEV Device or Connection is not initialized or ready.
- (e.g. Wrong UUID)
- ENOMEM Unable to allocate memory to client internal data.
- EFAULT Fatal Error (e.g. Unable to access user input data)
- EBUSY Connection Already Open
-
- Notes:
- max_msg_length (MTU) in client properties describes the maximum
- data that can be sent or received. (e.g. if MTU=2K, can send
- requests up to bytes 2k and received responses upto 2k bytes).
-
-Intel ME Applications:
-==============
-
-1) Intel Local Management Service (Intel LMS)
-
- Applications running locally on the platform communicate with Intel AMT Release
- 2.0 and later releases in the same way that network applications do via SOAP
- over HTTP (deprecated starting with Release 6.0) or with WS-Management over
- SOAP over HTTP. This means that some Intel AMT features can be accessed from a
- local application using the same network interface as a remote application
- communicating with Intel AMT over the network.
-
- When a local application sends a message addressed to the local Intel AMT host
- name, the Intel LMS, which listens for traffic directed to the host name,
- intercepts the message and routes it to the Intel MEI.
- For more information:
- http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide
- Under "About Intel AMT" => "Local Access"
-
- For downloading Intel LMS:
- http://software.intel.com/en-us/articles/download-the-latest-intel-amt-open-source-drivers/
-
- The Intel LMS opens a connection using the Intel MEI driver to the Intel LMS
- firmware feature using a defined UUID and then communicates with the feature
- using a protocol called Intel AMT Port Forwarding Protocol(Intel APF protocol).
- The protocol is used to maintain multiple sessions with Intel AMT from a
- single application.
-
- See the protocol specification in the Intel AMT Software Development Kit(SDK)
- http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide
- Under "SDK Resources" => "Intel(R) vPro(TM) Gateway(MPS)"
- => "Information for Intel(R) vPro(TM) Gateway Developers"
- => "Description of the Intel AMT Port Forwarding (APF)Protocol"
-
- 2) Intel AMT Remote configuration using a Local Agent
- A Local Agent enables IT personnel to configure Intel AMT out-of-the-box
- without requiring installing additional data to enable setup. The remote
- configuration process may involve an ISV-developed remote configuration
- agent that runs on the host.
- For more information:
- http://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide
- Under "Setup and Configuration of Intel AMT" =>
- "SDK Tools Supporting Setup and Configuration" =>
- "Using the Local Agent Sample"
-
- An open source Intel AMT configuration utility, implementing a local agent
- that accesses the Intel MEI driver, can be found here:
- http://software.intel.com/en-us/articles/download-the-latest-intel-amt-open-source-drivers/
-
-
-Intel AMT OS Health Watchdog:
-=============================
-The Intel AMT Watchdog is an OS Health (Hang/Crash) watchdog.
-Whenever the OS hangs or crashes, Intel AMT will send an event
-to any subscriber to this event. This mechanism means that
-IT knows when a platform crashes even when there is a hard failure on the host.
-
-The Intel AMT Watchdog is composed of two parts:
- 1) Firmware feature - receives the heartbeats
- and sends an event when the heartbeats stop.
- 2) Intel MEI driver - connects to the watchdog feature, configures the
- watchdog and sends the heartbeats.
-
-The Intel MEI driver uses the kernel watchdog to configure the Intel AMT
-Watchdog and to send heartbeats to it. The default timeout of the
-watchdog is 120 seconds.
-
-If the Intel AMT Watchdog feature does not exist (i.e. the connection failed),
-the Intel MEI driver will disable the sending of heartbeats.
-
-Supported Chipsets:
-==================
-7 Series Chipset Family
-6 Series Chipset Family
-5 Series Chipset Family
-4 Series Chipset Family
-Mobile 4 Series Chipset Family
-ICH9
-82946GZ/GL
-82G35 Express
-82Q963/Q965
-82P965/G965
-Mobile PM965/GM965
-Mobile GME965/GLE960
-82Q35 Express
-82G33/G31/P35/P31 Express
-82Q33 Express
-82X38/X48 Express
-
----
-linux-mei@linux.intel.com
diff --git a/drivers/staging/mei/mei_dev.h b/drivers/staging/mei/mei_dev.h
deleted file mode 100644
index 10b1b4e..0000000
--- a/drivers/staging/mei/mei_dev.h
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef _MEI_DEV_H_
-#define _MEI_DEV_H_
-
-#include <linux/types.h>
-#include <linux/watchdog.h>
-#include "mei.h"
-#include "hw.h"
-
-/*
- * watch dog definition
- */
-#define MEI_WATCHDOG_DATA_SIZE 16
-#define MEI_START_WD_DATA_SIZE 20
-#define MEI_WD_PARAMS_SIZE 4
-#define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0)
-
-#define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32))
-
-/*
- * MEI PCI Device object
- */
-extern struct pci_dev *mei_device;
-
-
-/*
- * AMTHI Client UUID
- */
-extern const uuid_le mei_amthi_guid;
-
-/*
- * Watchdog Client UUID
- */
-extern const uuid_le mei_wd_guid;
-
-/*
- * Watchdog independence state message
- */
-extern const u8 mei_wd_state_independence_msg[3][4];
-
-/*
- * Number of File descriptors/handles
- * that can be opened to the driver.
- *
- * Limit to 253: 255 Total Clients
- * minus internal client for AMTHI
- * minus internal client for Watchdog
- */
-#define MEI_MAX_OPEN_HANDLE_COUNT 253
-
-/*
- * Number of Maximum MEI Clients
- */
-#define MEI_CLIENTS_MAX 255
-
-/* File state */
-enum file_state {
- MEI_FILE_INITIALIZING = 0,
- MEI_FILE_CONNECTING,
- MEI_FILE_CONNECTED,
- MEI_FILE_DISCONNECTING,
- MEI_FILE_DISCONNECTED
-};
-
-/* MEI device states */
-enum mei_states {
- MEI_INITIALIZING = 0,
- MEI_INIT_CLIENTS,
- MEI_ENABLED,
- MEI_RESETING,
- MEI_DISABLED,
- MEI_RECOVERING_FROM_RESET,
- MEI_POWER_DOWN,
- MEI_POWER_UP
-};
-
-/* init clients states*/
-enum mei_init_clients_states {
- MEI_START_MESSAGE = 0,
- MEI_ENUM_CLIENTS_MESSAGE,
- MEI_CLIENT_PROPERTIES_MESSAGE
-};
-
-enum iamthif_states {
- MEI_IAMTHIF_IDLE,
- MEI_IAMTHIF_WRITING,
- MEI_IAMTHIF_FLOW_CONTROL,
- MEI_IAMTHIF_READING,
- MEI_IAMTHIF_READ_COMPLETE
-};
-
-enum mei_file_transaction_states {
- MEI_IDLE,
- MEI_WRITING,
- MEI_WRITE_COMPLETE,
- MEI_FLOW_CONTROL,
- MEI_READING,
- MEI_READ_COMPLETE
-};
-
-/* MEI CB */
-enum mei_cb_major_types {
- MEI_READ = 0,
- MEI_WRITE,
- MEI_IOCTL,
- MEI_OPEN,
- MEI_CLOSE
-};
-
-/*
- * Intel MEI message data struct
- */
-struct mei_message_data {
- u32 size;
- unsigned char *data;
-} __packed;
-
-
-struct mei_cl_cb {
- struct list_head cb_list;
- enum mei_cb_major_types major_file_operations;
- void *file_private;
- struct mei_message_data request_buffer;
- struct mei_message_data response_buffer;
- unsigned long information;
- unsigned long read_time;
- struct file *file_object;
-};
-
-/* MEI client instance carried as file->pirvate_data*/
-struct mei_cl {
- struct list_head link;
- struct mei_device *dev;
- enum file_state state;
- wait_queue_head_t tx_wait;
- wait_queue_head_t rx_wait;
- wait_queue_head_t wait;
- int read_pending;
- int status;
- /* ID of client connected */
- u8 host_client_id;
- u8 me_client_id;
- u8 mei_flow_ctrl_creds;
- u8 timer_count;
- enum mei_file_transaction_states reading_state;
- enum mei_file_transaction_states writing_state;
- int sm_state;
- struct mei_cl_cb *read_cb;
-};
-
-struct mei_io_list {
- struct mei_cl_cb mei_cb;
-};
-
-/* MEI private device struct */
-struct mei_device {
- struct pci_dev *pdev; /* pointer to pci device struct */
- /*
- * lists of queues
- */
- /* array of pointers to aio lists */
- struct mei_io_list read_list; /* driver read queue */
- struct mei_io_list write_list; /* driver write queue */
- struct mei_io_list write_waiting_list; /* write waiting queue */
- struct mei_io_list ctrl_wr_list; /* managed write IOCTL list */
- struct mei_io_list ctrl_rd_list; /* managed read IOCTL list */
- struct mei_io_list amthi_cmd_list; /* amthi list for cmd waiting */
-
- /* driver managed amthi list for reading completed amthi cmd data */
- struct mei_io_list amthi_read_complete_list;
- /*
- * list of files
- */
- struct list_head file_list;
- long open_handle_count;
- /*
- * memory of device
- */
- unsigned int mem_base;
- unsigned int mem_length;
- void __iomem *mem_addr;
- /*
- * lock for the device
- */
- struct mutex device_lock; /* device lock */
- struct delayed_work timer_work; /* MEI timer delayed work (timeouts) */
- bool recvd_msg;
- /*
- * hw states of host and fw(ME)
- */
- u32 host_hw_state;
- u32 me_hw_state;
- /*
- * waiting queue for receive message from FW
- */
- wait_queue_head_t wait_recvd_msg;
- wait_queue_head_t wait_stop_wd;
-
- /*
- * mei device states
- */
- enum mei_states mei_state;
- enum mei_init_clients_states init_clients_state;
- u16 init_clients_timer;
- bool stop;
- bool need_reset;
-
- u32 extra_write_index;
- unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; /* control messages */
- u32 wr_msg_buf[128]; /* used for control messages */
- u32 ext_msg_buf[8]; /* for control responses */
- u32 rd_msg_hdr;
-
- struct hbm_version version;
-
- struct mei_me_client *me_clients; /* Note: memory has to be allocated */
- DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX);
- DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX);
- u8 me_clients_num;
- u8 me_client_presentation_num;
- u8 me_client_index;
- bool mei_host_buffer_is_empty;
-
- struct mei_cl wd_cl;
- bool wd_pending;
- bool wd_stopped;
- bool wd_bypass; /* if false, don't refresh watchdog ME client */
- u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */
- u16 wd_due_counter;
- unsigned char wd_data[MEI_START_WD_DATA_SIZE];
-
-
-
- struct file *iamthif_file_object;
- struct mei_cl iamthif_cl;
- struct mei_cl_cb *iamthif_current_cb;
- int iamthif_mtu;
- unsigned long iamthif_timer;
- u32 iamthif_stall_timer;
- unsigned char *iamthif_msg_buf; /* Note: memory has to be allocated */
- u32 iamthif_msg_buf_size;
- u32 iamthif_msg_buf_index;
- enum iamthif_states iamthif_state;
- bool iamthif_flow_control_pending;
- bool iamthif_ioctl;
- bool iamthif_canceled;
-
- bool wd_interface_reg;
-};
-
-
-/*
- * mei init function prototypes
- */
-struct mei_device *mei_device_init(struct pci_dev *pdev);
-void mei_reset(struct mei_device *dev, int interrupts);
-int mei_hw_init(struct mei_device *dev);
-int mei_task_initialize_clients(void *data);
-int mei_initialize_clients(struct mei_device *dev);
-int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl);
-void mei_remove_client_from_file_list(struct mei_device *dev, u8 host_client_id);
-void mei_host_init_iamthif(struct mei_device *dev);
-void mei_allocate_me_clients_storage(struct mei_device *dev);
-
-
-u8 mei_find_me_client_update_filext(struct mei_device *dev,
- struct mei_cl *priv,
- const uuid_le *cguid, u8 client_id);
-
-/*
- * MEI IO List Functions
- */
-void mei_io_list_init(struct mei_io_list *list);
-void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl);
-
-/*
- * MEI ME Client Functions
- */
-
-struct mei_cl *mei_cl_allocate(struct mei_device *dev);
-void mei_cl_init(struct mei_cl *cl, struct mei_device *dev);
-int mei_cl_flush_queues(struct mei_cl *cl);
-/**
- * mei_cl_cmp_id - tells if file private data have same id
- *
- * @fe1: private data of 1. file object
- * @fe2: private data of 2. file object
- *
- * returns true - if ids are the same and not NULL
- */
-static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
- const struct mei_cl *cl2)
-{
- return cl1 && cl2 &&
- (cl1->host_client_id == cl2->host_client_id) &&
- (cl1->me_client_id == cl2->me_client_id);
-}
-
-
-
-/*
- * MEI Host Client Functions
- */
-void mei_host_start_message(struct mei_device *dev);
-void mei_host_enum_clients_message(struct mei_device *dev);
-int mei_host_client_properties(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);
-
-/*
- * MEI input output function prototype
- */
-int mei_ioctl_connect_client(struct file *file,
- struct mei_connect_client_data *data);
-
-int mei_start_read(struct mei_device *dev, struct mei_cl *cl);
-
-int amthi_write(struct mei_device *dev, struct mei_cl_cb *priv_cb);
-
-int amthi_read(struct mei_device *dev, struct file *file,
- char __user *ubuf, size_t length, loff_t *offset);
-
-struct mei_cl_cb *find_amthi_read_list_entry(struct mei_device *dev,
- struct file *file);
-
-void mei_run_next_iamthif_cmd(struct mei_device *dev);
-
-void mei_free_cb_private(struct mei_cl_cb *priv_cb);
-
-int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid);
-
-/*
- * Register Access Function
- */
-
-/**
- * mei_reg_read - Reads 32bit data from the mei device
- *
- * @dev: the device structure
- * @offset: offset from which to read the data
- *
- * returns register value (u32)
- */
-static inline u32 mei_reg_read(struct mei_device *dev, unsigned long offset)
-{
- return ioread32(dev->mem_addr + offset);
-}
-
-/**
- * mei_reg_write - Writes 32bit data to the mei device
- *
- * @dev: the device structure
- * @offset: offset from which to write the data
- * @value: register value to write (u32)
- */
-static inline void mei_reg_write(struct mei_device *dev,
- unsigned long offset, u32 value)
-{
- iowrite32(value, dev->mem_addr + offset);
-}
-
-/**
- * mei_hcsr_read - Reads 32bit data from the host CSR
- *
- * @dev: the device structure
- *
- * returns the byte read.
- */
-static inline u32 mei_hcsr_read(struct mei_device *dev)
-{
- return mei_reg_read(dev, H_CSR);
-}
-
-/**
- * mei_mecsr_read - Reads 32bit data from the ME CSR
- *
- * @dev: the device structure
- *
- * returns ME_CSR_HA register value (u32)
- */
-static inline u32 mei_mecsr_read(struct mei_device *dev)
-{
- return mei_reg_read(dev, ME_CSR_HA);
-}
-
-/**
- * get_me_cb_rw - Reads 32bit data from the mei ME_CB_RW register
- *
- * @dev: the device structure
- *
- * returns ME_CB_RW register value (u32)
- */
-static inline u32 mei_mecbrw_read(struct mei_device *dev)
-{
- return mei_reg_read(dev, ME_CB_RW);
-}
-
-
-/*
- * mei interface function prototypes
- */
-void mei_hcsr_set(struct mei_device *dev);
-void mei_csr_clear_his(struct mei_device *dev);
-
-void mei_enable_interrupts(struct mei_device *dev);
-void mei_disable_interrupts(struct mei_device *dev);
-
-#endif
diff --git a/drivers/staging/mei/wd.c b/drivers/staging/mei/wd.c
deleted file mode 100644
index cf4c29d..0000000
--- a/drivers/staging/mei/wd.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- *
- * 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/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/watchdog.h>
-
-#include "mei_dev.h"
-#include "hw.h"
-#include "interface.h"
-#include "mei.h"
-
-static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 };
-static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 };
-
-const u8 mei_wd_state_independence_msg[3][4] = {
- {0x05, 0x02, 0x51, 0x10},
- {0x05, 0x02, 0x52, 0x10},
- {0x07, 0x02, 0x01, 0x10}
-};
-
-/*
- * AMT Watchdog Device
- */
-#define INTEL_AMT_WATCHDOG_ID "INTCAMT"
-
-/* UUIDs for AMT F/W clients */
-const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89,
- 0x9D, 0xA9, 0x15, 0x14, 0xCB,
- 0x32, 0xAB);
-
-void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
-{
- dev_dbg(&dev->pdev->dev, "timeout=%d.\n", timeout);
- memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_PARAMS_SIZE);
- memcpy(dev->wd_data + MEI_WD_PARAMS_SIZE,
- &timeout, sizeof(u16));
-}
-
-/**
- * host_init_wd - mei initialization wd.
- *
- * @dev: the device structure
- */
-bool mei_wd_host_init(struct mei_device *dev)
-{
- bool ret = false;
-
- mei_cl_init(&dev->wd_cl, dev);
-
- /* look for WD client and connect to it */
- dev->wd_cl.state = MEI_FILE_DISCONNECTED;
- dev->wd_timeout = AMT_WD_DEFAULT_TIMEOUT;
-
- /* find ME WD client */
- mei_find_me_client_update_filext(dev, &dev->wd_cl,
- &mei_wd_guid, MEI_WD_HOST_CLIENT_ID);
-
- dev_dbg(&dev->pdev->dev, "check wd_cl\n");
- if (MEI_FILE_CONNECTING == dev->wd_cl.state) {
- if (mei_connect(dev, &dev->wd_cl)) {
- dev_dbg(&dev->pdev->dev, "Failed to connect to WD client\n");
- dev->wd_cl.state = MEI_FILE_DISCONNECTED;
- dev->wd_cl.host_client_id = 0;
- ret = false;
- goto end;
- } else {
- dev->wd_cl.timer_count = CONNECT_TIMEOUT;
- }
- } else {
- dev_dbg(&dev->pdev->dev, "Failed to find WD client\n");
- ret = false;
- goto end;
- }
-
-end:
- return ret;
-}
-
-/**
- * mei_wd_send - sends watch dog message to fw.
- *
- * @dev: the device structure
- *
- * returns 0 if success,
- * -EIO when message send fails
- * -EINVAL when invalid message is to be sent
- */
-int mei_wd_send(struct mei_device *dev)
-{
- struct mei_msg_hdr *mei_hdr;
-
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- mei_hdr->host_addr = dev->wd_cl.host_client_id;
- mei_hdr->me_addr = dev->wd_cl.me_client_id;
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
-
- if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_PARAMS_SIZE))
- mei_hdr->length = MEI_START_WD_DATA_SIZE;
- else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE))
- mei_hdr->length = MEI_WD_PARAMS_SIZE;
- else
- return -EINVAL;
-
- return mei_write_message(dev, mei_hdr, dev->wd_data, mei_hdr->length);
-}
-
-/**
- * mei_wd_stop - sends watchdog stop message to fw.
- *
- * @dev: the device structure
- * @preserve: indicate if to keep the timeout value
- *
- * returns 0 if success,
- * -EIO when message send fails
- * -EINVAL when invalid message is to be sent
- */
-int mei_wd_stop(struct mei_device *dev, bool preserve)
-{
- int ret;
- u16 wd_timeout = dev->wd_timeout;
-
- cancel_delayed_work(&dev->timer_work);
- if (dev->wd_cl.state != MEI_FILE_CONNECTED || !dev->wd_timeout)
- return 0;
-
- dev->wd_timeout = 0;
- dev->wd_due_counter = 0;
- memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE);
- dev->stop = true;
-
- ret = mei_flow_ctrl_creds(dev, &dev->wd_cl);
- if (ret < 0)
- goto out;
-
- if (ret && dev->mei_host_buffer_is_empty) {
- ret = 0;
- dev->mei_host_buffer_is_empty = false;
-
- if (!mei_wd_send(dev)) {
- ret = mei_flow_ctrl_reduce(dev, &dev->wd_cl);
- if (ret)
- goto out;
- } else {
- dev_dbg(&dev->pdev->dev, "send stop WD failed\n");
- }
-
- dev->wd_pending = false;
- } else {
- dev->wd_pending = true;
- }
- dev->wd_stopped = false;
- mutex_unlock(&dev->device_lock);
-
- ret = wait_event_interruptible_timeout(dev->wait_stop_wd,
- dev->wd_stopped, 10 * HZ);
- mutex_lock(&dev->device_lock);
- if (dev->wd_stopped) {
- dev_dbg(&dev->pdev->dev, "stop wd complete ret=%d.\n", ret);
- ret = 0;
- } else {
- if (!ret)
- ret = -ETIMEDOUT;
- dev_warn(&dev->pdev->dev,
- "stop wd failed to complete ret=%d.\n", ret);
- }
-
- if (preserve)
- dev->wd_timeout = wd_timeout;
-
-out:
- return ret;
-}
-
-/*
- * mei_wd_ops_start - wd start command from the watchdog core.
- *
- * @wd_dev - watchdog device struct
- *
- * returns 0 if success, negative errno code for failure
- */
-static int mei_wd_ops_start(struct watchdog_device *wd_dev)
-{
- int err = -ENODEV;
- struct mei_device *dev;
-
- dev = pci_get_drvdata(mei_device);
- if (!dev)
- return -ENODEV;
-
- mutex_lock(&dev->device_lock);
-
- if (dev->mei_state != MEI_ENABLED) {
- dev_dbg(&dev->pdev->dev, "mei_state != MEI_ENABLED mei_state= %d\n",
- dev->mei_state);
- goto end_unlock;
- }
-
- if (dev->wd_cl.state != MEI_FILE_CONNECTED) {
- dev_dbg(&dev->pdev->dev, "MEI Driver is not connected to Watchdog Client\n");
- goto end_unlock;
- }
-
- mei_wd_set_start_timeout(dev, dev->wd_timeout);
-
- err = 0;
-end_unlock:
- mutex_unlock(&dev->device_lock);
- return err;
-}
-
-/*
- * mei_wd_ops_stop - wd stop command from the watchdog core.
- *
- * @wd_dev - watchdog device struct
- *
- * returns 0 if success, negative errno code for failure
- */
-static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
-{
- struct mei_device *dev;
- dev = pci_get_drvdata(mei_device);
-
- if (!dev)
- return -ENODEV;
-
- mutex_lock(&dev->device_lock);
- mei_wd_stop(dev, false);
- mutex_unlock(&dev->device_lock);
-
- return 0;
-}
-
-/*
- * mei_wd_ops_ping - wd ping command from the watchdog core.
- *
- * @wd_dev - watchdog device struct
- *
- * returns 0 if success, negative errno code for failure
- */
-static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
-{
- int ret = 0;
- struct mei_device *dev;
- dev = pci_get_drvdata(mei_device);
-
- if (!dev)
- return -ENODEV;
-
- mutex_lock(&dev->device_lock);
-
- if (dev->wd_cl.state != MEI_FILE_CONNECTED) {
- dev_dbg(&dev->pdev->dev, "wd is not connected.\n");
- ret = -ENODEV;
- goto end;
- }
-
- /* Check if we can send the ping to HW*/
- if (dev->mei_host_buffer_is_empty &&
- mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
-
- dev->mei_host_buffer_is_empty = false;
- dev_dbg(&dev->pdev->dev, "sending watchdog ping\n");
-
- if (mei_wd_send(dev)) {
- dev_dbg(&dev->pdev->dev, "wd send failed.\n");
- ret = -EIO;
- goto end;
- }
-
- if (mei_flow_ctrl_reduce(dev, &dev->wd_cl)) {
- dev_dbg(&dev->pdev->dev, "mei_flow_ctrl_reduce() failed.\n");
- ret = -EIO;
- goto end;
- }
-
- } else {
- dev->wd_pending = true;
- }
-
-end:
- mutex_unlock(&dev->device_lock);
- return ret;
-}
-
-/*
- * mei_wd_ops_set_timeout - wd set timeout command from the watchdog core.
- *
- * @wd_dev - watchdog device struct
- * @timeout - timeout value to set
- *
- * returns 0 if success, negative errno code for failure
- */
-static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, unsigned int timeout)
-{
- struct mei_device *dev;
- dev = pci_get_drvdata(mei_device);
-
- if (!dev)
- return -ENODEV;
-
- /* Check Timeout value */
- if (timeout < AMT_WD_MIN_TIMEOUT || timeout > AMT_WD_MAX_TIMEOUT)
- return -EINVAL;
-
- mutex_lock(&dev->device_lock);
-
- dev->wd_timeout = timeout;
- wd_dev->timeout = timeout;
- mei_wd_set_start_timeout(dev, dev->wd_timeout);
-
- mutex_unlock(&dev->device_lock);
-
- return 0;
-}
-
-/*
- * Watchdog Device structs
- */
-static const struct watchdog_ops wd_ops = {
- .owner = THIS_MODULE,
- .start = mei_wd_ops_start,
- .stop = mei_wd_ops_stop,
- .ping = mei_wd_ops_ping,
- .set_timeout = mei_wd_ops_set_timeout,
-};
-static const struct watchdog_info wd_info = {
- .identity = INTEL_AMT_WATCHDOG_ID,
- .options = WDIOF_KEEPALIVEPING,
-};
-
-struct watchdog_device amt_wd_dev = {
- .info = &wd_info,
- .ops = &wd_ops,
- .timeout = AMT_WD_DEFAULT_TIMEOUT,
- .min_timeout = AMT_WD_MIN_TIMEOUT,
- .max_timeout = AMT_WD_MAX_TIMEOUT,
-};
-
-
-void mei_watchdog_register(struct mei_device *dev)
-{
- dev_dbg(&dev->pdev->dev, "dev->wd_timeout =%d.\n", dev->wd_timeout);
-
- dev->wd_due_counter = !!dev->wd_timeout;
-
- if (watchdog_register_device(&amt_wd_dev)) {
- dev_err(&dev->pdev->dev, "unable to register watchdog device.\n");
- dev->wd_interface_reg = false;
- } else {
- dev_dbg(&dev->pdev->dev, "successfully register watchdog interface.\n");
- dev->wd_interface_reg = true;
- }
-}
-
-void mei_watchdog_unregister(struct mei_device *dev)
-{
- if (dev->wd_interface_reg)
- watchdog_unregister_device(&amt_wd_dev);
- dev->wd_interface_reg = false;
-}
-