cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ishtp_eclite.c (17983B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Intel ECLite opregion driver for talking to ECLite firmware running on
      4 * Intel Integrated Sensor Hub (ISH) using ISH Transport Protocol (ISHTP)
      5 *
      6 * Copyright (c) 2021, Intel Corporation.
      7 */
      8
      9#include <linux/acpi.h>
     10#include <linux/bitops.h>
     11#include <linux/device.h>
     12#include <linux/errno.h>
     13#include <linux/intel-ish-client-if.h>
     14#include <linux/kernel.h>
     15#include <linux/module.h>
     16#include <linux/mutex.h>
     17#include <linux/slab.h>
     18#include <linux/suspend.h>
     19#include <linux/types.h>
     20#include <linux/uuid.h>
     21#include <linux/uaccess.h>
     22
     23#define ECLITE_DATA_OPREGION_ID	0x9E
     24#define ECLITE_CMD_OPREGION_ID	0x9F
     25
     26#define ECL_MSG_DATA	0x1
     27#define ECL_MSG_EVENT	0x2
     28
     29#define ECL_ISH_READ	0x1
     30#define ECL_ISH_WRITE	0x2
     31#define ECL_ISH_HEADER_VERSION	0
     32
     33#define ECL_CL_RX_RING_SIZE	16
     34#define ECL_CL_TX_RING_SIZE	8
     35
     36#define ECL_DATA_OPR_BUFLEN	384
     37#define ECL_EVENTS_NOTIFY	333
     38
     39#define cmd_opr_offsetof(element)	offsetof(struct opregion_cmd, element)
     40#define cl_data_to_dev(opr_dev)	ishtp_device((opr_dev)->cl_device)
     41
     42#ifndef BITS_TO_BYTES
     43#define BITS_TO_BYTES(x) ((x) / 8)
     44#endif
     45
     46struct opregion_cmd {
     47	unsigned int command;
     48	unsigned int offset;
     49	unsigned int length;
     50	unsigned int event_id;
     51};
     52
     53struct opregion_data {
     54	char data[ECL_DATA_OPR_BUFLEN];
     55};
     56
     57struct opregion_context {
     58	struct opregion_cmd cmd_area;
     59	struct opregion_data data_area;
     60};
     61
     62struct ecl_message_header {
     63	unsigned int version:2;
     64	unsigned int data_type:2;
     65	unsigned int request_type:2;
     66	unsigned int offset:9;
     67	unsigned int data_len:9;
     68	unsigned int event:8;
     69};
     70
     71struct ecl_message {
     72	struct ecl_message_header header;
     73	char payload[ECL_DATA_OPR_BUFLEN];
     74};
     75
     76struct ishtp_opregion_dev {
     77	struct opregion_context opr_context;
     78	struct ishtp_cl *ecl_ishtp_cl;
     79	struct ishtp_cl_device *cl_device;
     80	struct ishtp_fw_client *fw_client;
     81	struct ishtp_cl_rb *rb;
     82	struct acpi_device *adev;
     83	unsigned int dsm_event_id;
     84	unsigned int ish_link_ready;
     85	unsigned int ish_read_done;
     86	unsigned int acpi_init_done;
     87	wait_queue_head_t read_wait;
     88	struct work_struct event_work;
     89	struct work_struct reset_work;
     90	/* lock for opregion context */
     91	struct mutex lock;
     92
     93};
     94
     95/* eclite ishtp client UUID: 6a19cc4b-d760-4de3-b14d-f25ebd0fbcd9 */
     96static const struct ishtp_device_id ecl_ishtp_id_table[] = {
     97	{ .guid = GUID_INIT(0x6a19cc4b, 0xd760, 0x4de3,
     98		  0xb1, 0x4d, 0xf2, 0x5e, 0xbd, 0xf, 0xbc, 0xd9), },
     99	{ }
    100};
    101MODULE_DEVICE_TABLE(ishtp, ecl_ishtp_id_table);
    102
    103/* ACPI DSM UUID: 91d936a7-1f01-49c6-a6b4-72f00ad8d8a5 */
    104static const guid_t ecl_acpi_guid =
    105	GUID_INIT(0x91d936a7, 0x1f01, 0x49c6, 0xa6,
    106		  0xb4, 0x72, 0xf0, 0x0a, 0xd8, 0xd8, 0xa5);
    107
    108/**
    109 * ecl_ish_cl_read() - Read data from eclite FW
    110 *
    111 * @opr_dev:  pointer to opregion device
    112 *
    113 * This function issues a read request to eclite FW and waits until it
    114 * receives a response. When response is received the read data is copied to
    115 * opregion buffer.
    116 */
    117static int ecl_ish_cl_read(struct ishtp_opregion_dev *opr_dev)
    118{
    119	struct ecl_message_header header;
    120	int len, rv;
    121
    122	if (!opr_dev->ish_link_ready)
    123		return -EIO;
    124
    125	if ((opr_dev->opr_context.cmd_area.offset +
    126	     opr_dev->opr_context.cmd_area.length) > ECL_DATA_OPR_BUFLEN) {
    127		return -EINVAL;
    128	}
    129
    130	header.version = ECL_ISH_HEADER_VERSION;
    131	header.data_type = ECL_MSG_DATA;
    132	header.request_type = ECL_ISH_READ;
    133	header.offset = opr_dev->opr_context.cmd_area.offset;
    134	header.data_len = opr_dev->opr_context.cmd_area.length;
    135	header.event = opr_dev->opr_context.cmd_area.event_id;
    136	len = sizeof(header);
    137
    138	opr_dev->ish_read_done = false;
    139	rv = ishtp_cl_send(opr_dev->ecl_ishtp_cl, (uint8_t *)&header, len);
    140	if (rv) {
    141		dev_err(cl_data_to_dev(opr_dev), "ish-read : send failed\n");
    142		return -EIO;
    143	}
    144
    145	dev_dbg(cl_data_to_dev(opr_dev),
    146		"[ish_rd] Req: off : %x, len : %x\n",
    147		header.offset,
    148		header.data_len);
    149
    150	rv = wait_event_interruptible_timeout(opr_dev->read_wait,
    151					      opr_dev->ish_read_done,
    152					      2 * HZ);
    153	if (!rv) {
    154		dev_err(cl_data_to_dev(opr_dev),
    155			"[ish_rd] No response from firmware\n");
    156		return -EIO;
    157	}
    158
    159	return 0;
    160}
    161
    162/**
    163 * ecl_ish_cl_write() - This function writes data to eclite FW.
    164 *
    165 * @opr_dev:  pointer to opregion device
    166 *
    167 * This function writes data to eclite FW.
    168 */
    169static int ecl_ish_cl_write(struct ishtp_opregion_dev *opr_dev)
    170{
    171	struct ecl_message message;
    172	int len;
    173
    174	if (!opr_dev->ish_link_ready)
    175		return -EIO;
    176
    177	if ((opr_dev->opr_context.cmd_area.offset +
    178	     opr_dev->opr_context.cmd_area.length) > ECL_DATA_OPR_BUFLEN) {
    179		return -EINVAL;
    180	}
    181
    182	message.header.version = ECL_ISH_HEADER_VERSION;
    183	message.header.data_type = ECL_MSG_DATA;
    184	message.header.request_type = ECL_ISH_WRITE;
    185	message.header.offset = opr_dev->opr_context.cmd_area.offset;
    186	message.header.data_len = opr_dev->opr_context.cmd_area.length;
    187	message.header.event = opr_dev->opr_context.cmd_area.event_id;
    188	len = sizeof(struct ecl_message_header) + message.header.data_len;
    189
    190	memcpy(message.payload,
    191	       opr_dev->opr_context.data_area.data + message.header.offset,
    192	       message.header.data_len);
    193
    194	dev_dbg(cl_data_to_dev(opr_dev),
    195		"[ish_wr] off : %x, len : %x\n",
    196		message.header.offset,
    197		message.header.data_len);
    198
    199	return ishtp_cl_send(opr_dev->ecl_ishtp_cl, (uint8_t *)&message, len);
    200}
    201
    202static acpi_status
    203ecl_opregion_cmd_handler(u32 function, acpi_physical_address address,
    204			 u32 bits, u64 *value64,
    205			 void *handler_context, void *region_context)
    206{
    207	struct ishtp_opregion_dev *opr_dev;
    208	struct opregion_cmd *cmd;
    209	acpi_status status = AE_OK;
    210
    211	if (!region_context || !value64)
    212		return AE_BAD_PARAMETER;
    213
    214	if (function == ACPI_READ)
    215		return AE_ERROR;
    216
    217	opr_dev = (struct ishtp_opregion_dev *)region_context;
    218
    219	mutex_lock(&opr_dev->lock);
    220
    221	cmd = &opr_dev->opr_context.cmd_area;
    222
    223	switch (address) {
    224	case cmd_opr_offsetof(command):
    225		cmd->command = (u32)*value64;
    226
    227		if (cmd->command == ECL_ISH_READ)
    228			status =  ecl_ish_cl_read(opr_dev);
    229		else if (cmd->command == ECL_ISH_WRITE)
    230			status = ecl_ish_cl_write(opr_dev);
    231		else
    232			status = AE_ERROR;
    233		break;
    234	case cmd_opr_offsetof(offset):
    235		cmd->offset = (u32)*value64;
    236		break;
    237	case cmd_opr_offsetof(length):
    238		cmd->length = (u32)*value64;
    239		break;
    240	case cmd_opr_offsetof(event_id):
    241		cmd->event_id = (u32)*value64;
    242		break;
    243	default:
    244		status = AE_ERROR;
    245	}
    246
    247	mutex_unlock(&opr_dev->lock);
    248
    249	return status;
    250}
    251
    252static acpi_status
    253ecl_opregion_data_handler(u32 function, acpi_physical_address address,
    254			  u32 bits, u64 *value64,
    255			  void *handler_context, void *region_context)
    256{
    257	struct ishtp_opregion_dev *opr_dev;
    258	unsigned int bytes = BITS_TO_BYTES(bits);
    259	void *data_addr;
    260
    261	if (!region_context || !value64)
    262		return AE_BAD_PARAMETER;
    263
    264	if (address + bytes > ECL_DATA_OPR_BUFLEN)
    265		return AE_BAD_PARAMETER;
    266
    267	opr_dev = (struct ishtp_opregion_dev *)region_context;
    268
    269	mutex_lock(&opr_dev->lock);
    270
    271	data_addr = &opr_dev->opr_context.data_area.data[address];
    272
    273	if (function == ACPI_READ) {
    274		memcpy(value64, data_addr, bytes);
    275	} else if (function == ACPI_WRITE) {
    276		memcpy(data_addr, value64, bytes);
    277	} else {
    278		mutex_unlock(&opr_dev->lock);
    279		return AE_BAD_PARAMETER;
    280	}
    281
    282	mutex_unlock(&opr_dev->lock);
    283
    284	return AE_OK;
    285}
    286
    287static int acpi_find_eclite_device(struct ishtp_opregion_dev *opr_dev)
    288{
    289	struct acpi_device *adev;
    290
    291	/* Find ECLite device and save reference */
    292	adev = acpi_dev_get_first_match_dev("INTC1035", NULL, -1);
    293	if (!adev) {
    294		dev_err(cl_data_to_dev(opr_dev), "eclite ACPI device not found\n");
    295		return -ENODEV;
    296	}
    297
    298	opr_dev->adev = adev;
    299
    300	return 0;
    301}
    302
    303static int acpi_opregion_init(struct ishtp_opregion_dev *opr_dev)
    304{
    305	acpi_status status;
    306
    307	status = acpi_install_address_space_handler(opr_dev->adev->handle,
    308						    ECLITE_CMD_OPREGION_ID,
    309						    ecl_opregion_cmd_handler,
    310						    NULL, opr_dev);
    311	if (ACPI_FAILURE(status)) {
    312		dev_err(cl_data_to_dev(opr_dev),
    313			"cmd space handler install failed\n");
    314		return -ENODEV;
    315	}
    316
    317	status = acpi_install_address_space_handler(opr_dev->adev->handle,
    318						    ECLITE_DATA_OPREGION_ID,
    319						    ecl_opregion_data_handler,
    320						    NULL, opr_dev);
    321	if (ACPI_FAILURE(status)) {
    322		dev_err(cl_data_to_dev(opr_dev),
    323			"data space handler install failed\n");
    324
    325		acpi_remove_address_space_handler(opr_dev->adev->handle,
    326						  ECLITE_CMD_OPREGION_ID,
    327						  ecl_opregion_cmd_handler);
    328		return -ENODEV;
    329	}
    330	opr_dev->acpi_init_done = true;
    331
    332	dev_dbg(cl_data_to_dev(opr_dev), "Opregion handlers are installed\n");
    333
    334	return 0;
    335}
    336
    337static void acpi_opregion_deinit(struct ishtp_opregion_dev *opr_dev)
    338{
    339	acpi_remove_address_space_handler(opr_dev->adev->handle,
    340					  ECLITE_CMD_OPREGION_ID,
    341					  ecl_opregion_cmd_handler);
    342
    343	acpi_remove_address_space_handler(opr_dev->adev->handle,
    344					  ECLITE_DATA_OPREGION_ID,
    345					  ecl_opregion_data_handler);
    346	opr_dev->acpi_init_done = false;
    347}
    348
    349static void ecl_acpi_invoke_dsm(struct work_struct *work)
    350{
    351	struct ishtp_opregion_dev *opr_dev;
    352	union acpi_object *obj;
    353
    354	opr_dev = container_of(work, struct ishtp_opregion_dev, event_work);
    355	if (!opr_dev->acpi_init_done)
    356		return;
    357
    358	obj = acpi_evaluate_dsm(opr_dev->adev->handle, &ecl_acpi_guid, 0,
    359				opr_dev->dsm_event_id, NULL);
    360	if (!obj) {
    361		dev_warn(cl_data_to_dev(opr_dev), "_DSM fn call failed\n");
    362		return;
    363	}
    364
    365	dev_dbg(cl_data_to_dev(opr_dev), "Exec DSM function code: %d success\n",
    366		opr_dev->dsm_event_id);
    367
    368	ACPI_FREE(obj);
    369}
    370
    371static void ecl_ish_process_rx_data(struct ishtp_opregion_dev *opr_dev)
    372{
    373	struct ecl_message *message =
    374		(struct ecl_message *)opr_dev->rb->buffer.data;
    375
    376	dev_dbg(cl_data_to_dev(opr_dev),
    377		"[ish_rd] Resp: off : %x, len : %x\n",
    378		message->header.offset,
    379		message->header.data_len);
    380
    381	if ((message->header.offset + message->header.data_len) >
    382			ECL_DATA_OPR_BUFLEN) {
    383		return;
    384	}
    385
    386	memcpy(opr_dev->opr_context.data_area.data + message->header.offset,
    387	       message->payload, message->header.data_len);
    388
    389	opr_dev->ish_read_done = true;
    390	wake_up_interruptible(&opr_dev->read_wait);
    391}
    392
    393static void ecl_ish_process_rx_event(struct ishtp_opregion_dev *opr_dev)
    394{
    395	struct ecl_message_header *header =
    396		(struct ecl_message_header *)opr_dev->rb->buffer.data;
    397
    398	dev_dbg(cl_data_to_dev(opr_dev),
    399		"[ish_ev] Evt received: %8x\n", header->event);
    400
    401	opr_dev->dsm_event_id = header->event;
    402	schedule_work(&opr_dev->event_work);
    403}
    404
    405static int ecl_ish_cl_enable_events(struct ishtp_opregion_dev *opr_dev,
    406				    bool config_enable)
    407{
    408	struct ecl_message message;
    409	int len;
    410
    411	message.header.version = ECL_ISH_HEADER_VERSION;
    412	message.header.data_type = ECL_MSG_DATA;
    413	message.header.request_type = ECL_ISH_WRITE;
    414	message.header.offset = ECL_EVENTS_NOTIFY;
    415	message.header.data_len = 1;
    416	message.payload[0] = config_enable;
    417
    418	len = sizeof(struct ecl_message_header) + message.header.data_len;
    419
    420	return ishtp_cl_send(opr_dev->ecl_ishtp_cl, (uint8_t *)&message, len);
    421}
    422
    423static void ecl_ishtp_cl_event_cb(struct ishtp_cl_device *cl_device)
    424{
    425	struct ishtp_cl *ecl_ishtp_cl = ishtp_get_drvdata(cl_device);
    426	struct ishtp_opregion_dev *opr_dev;
    427	struct ecl_message_header *header;
    428	struct ishtp_cl_rb *rb;
    429
    430	opr_dev = ishtp_get_client_data(ecl_ishtp_cl);
    431	while ((rb = ishtp_cl_rx_get_rb(opr_dev->ecl_ishtp_cl)) != NULL) {
    432		opr_dev->rb = rb;
    433		header = (struct ecl_message_header *)rb->buffer.data;
    434
    435		if (header->data_type == ECL_MSG_DATA)
    436			ecl_ish_process_rx_data(opr_dev);
    437		else if (header->data_type == ECL_MSG_EVENT)
    438			ecl_ish_process_rx_event(opr_dev);
    439		else
    440			/* Got an event with wrong data_type, ignore it */
    441			dev_err(cl_data_to_dev(opr_dev),
    442				"[ish_cb] Received wrong data_type\n");
    443
    444		ishtp_cl_io_rb_recycle(rb);
    445	}
    446}
    447
    448static int ecl_ishtp_cl_init(struct ishtp_cl *ecl_ishtp_cl)
    449{
    450	struct ishtp_opregion_dev *opr_dev =
    451		ishtp_get_client_data(ecl_ishtp_cl);
    452	struct ishtp_fw_client *fw_client;
    453	struct ishtp_device *dev;
    454	int rv;
    455
    456	rv = ishtp_cl_link(ecl_ishtp_cl);
    457	if (rv) {
    458		dev_err(cl_data_to_dev(opr_dev), "ishtp_cl_link failed\n");
    459		return	rv;
    460	}
    461
    462	dev = ishtp_get_ishtp_device(ecl_ishtp_cl);
    463
    464	/* Connect to FW client */
    465	ishtp_set_tx_ring_size(ecl_ishtp_cl, ECL_CL_TX_RING_SIZE);
    466	ishtp_set_rx_ring_size(ecl_ishtp_cl, ECL_CL_RX_RING_SIZE);
    467
    468	fw_client = ishtp_fw_cl_get_client(dev, &ecl_ishtp_id_table[0].guid);
    469	if (!fw_client) {
    470		dev_err(cl_data_to_dev(opr_dev), "fw client not found\n");
    471		return -ENOENT;
    472	}
    473
    474	ishtp_cl_set_fw_client_id(ecl_ishtp_cl,
    475				  ishtp_get_fw_client_id(fw_client));
    476
    477	ishtp_set_connection_state(ecl_ishtp_cl, ISHTP_CL_CONNECTING);
    478
    479	rv = ishtp_cl_connect(ecl_ishtp_cl);
    480	if (rv) {
    481		dev_err(cl_data_to_dev(opr_dev), "client connect failed\n");
    482
    483		ishtp_cl_unlink(ecl_ishtp_cl);
    484		return rv;
    485	}
    486
    487	dev_dbg(cl_data_to_dev(opr_dev), "Host connected to fw client\n");
    488
    489	return 0;
    490}
    491
    492static void ecl_ishtp_cl_deinit(struct ishtp_cl *ecl_ishtp_cl)
    493{
    494	ishtp_cl_unlink(ecl_ishtp_cl);
    495	ishtp_cl_flush_queues(ecl_ishtp_cl);
    496	ishtp_cl_free(ecl_ishtp_cl);
    497}
    498
    499static void ecl_ishtp_cl_reset_handler(struct work_struct *work)
    500{
    501	struct ishtp_opregion_dev *opr_dev;
    502	struct ishtp_cl_device *cl_device;
    503	struct ishtp_cl *ecl_ishtp_cl;
    504	int rv;
    505	int retry;
    506
    507	opr_dev = container_of(work, struct ishtp_opregion_dev, reset_work);
    508
    509	opr_dev->ish_link_ready = false;
    510
    511	cl_device = opr_dev->cl_device;
    512	ecl_ishtp_cl = opr_dev->ecl_ishtp_cl;
    513
    514	ecl_ishtp_cl_deinit(ecl_ishtp_cl);
    515
    516	ecl_ishtp_cl = ishtp_cl_allocate(cl_device);
    517	if (!ecl_ishtp_cl)
    518		return;
    519
    520	ishtp_set_drvdata(cl_device, ecl_ishtp_cl);
    521	ishtp_set_client_data(ecl_ishtp_cl, opr_dev);
    522
    523	opr_dev->ecl_ishtp_cl = ecl_ishtp_cl;
    524
    525	for (retry = 0; retry < 3; ++retry) {
    526		rv = ecl_ishtp_cl_init(ecl_ishtp_cl);
    527		if (!rv)
    528			break;
    529	}
    530	if (rv) {
    531		ishtp_cl_free(ecl_ishtp_cl);
    532		opr_dev->ecl_ishtp_cl = NULL;
    533		dev_err(cl_data_to_dev(opr_dev),
    534			"[ish_rst] Reset failed. Link not ready.\n");
    535		return;
    536	}
    537
    538	ishtp_register_event_cb(cl_device, ecl_ishtp_cl_event_cb);
    539	dev_info(cl_data_to_dev(opr_dev),
    540		 "[ish_rst] Reset Success. Link ready.\n");
    541
    542	opr_dev->ish_link_ready = true;
    543
    544	if (opr_dev->acpi_init_done)
    545		return;
    546
    547	rv = acpi_opregion_init(opr_dev);
    548	if (rv) {
    549		dev_err(cl_data_to_dev(opr_dev),
    550			"ACPI opregion init failed\n");
    551	}
    552}
    553
    554static int ecl_ishtp_cl_probe(struct ishtp_cl_device *cl_device)
    555{
    556	struct ishtp_cl *ecl_ishtp_cl;
    557	struct ishtp_opregion_dev *opr_dev;
    558	int rv;
    559
    560	opr_dev = devm_kzalloc(ishtp_device(cl_device), sizeof(*opr_dev),
    561			       GFP_KERNEL);
    562	if (!opr_dev)
    563		return -ENOMEM;
    564
    565	ecl_ishtp_cl = ishtp_cl_allocate(cl_device);
    566	if (!ecl_ishtp_cl)
    567		return -ENOMEM;
    568
    569	ishtp_set_drvdata(cl_device, ecl_ishtp_cl);
    570	ishtp_set_client_data(ecl_ishtp_cl, opr_dev);
    571	opr_dev->ecl_ishtp_cl = ecl_ishtp_cl;
    572	opr_dev->cl_device = cl_device;
    573
    574	init_waitqueue_head(&opr_dev->read_wait);
    575	INIT_WORK(&opr_dev->event_work, ecl_acpi_invoke_dsm);
    576	INIT_WORK(&opr_dev->reset_work, ecl_ishtp_cl_reset_handler);
    577
    578	/* Initialize ish client device */
    579	rv = ecl_ishtp_cl_init(ecl_ishtp_cl);
    580	if (rv) {
    581		dev_err(cl_data_to_dev(opr_dev), "Client init failed\n");
    582		goto err_exit;
    583	}
    584
    585	dev_dbg(cl_data_to_dev(opr_dev), "eclite-ishtp client initialised\n");
    586
    587	opr_dev->ish_link_ready = true;
    588	mutex_init(&opr_dev->lock);
    589
    590	rv = acpi_find_eclite_device(opr_dev);
    591	if (rv) {
    592		dev_err(cl_data_to_dev(opr_dev), "ECLite ACPI ID not found\n");
    593		goto err_exit;
    594	}
    595
    596	/* Register a handler for eclite fw events */
    597	ishtp_register_event_cb(cl_device, ecl_ishtp_cl_event_cb);
    598
    599	/* Now init opregion handlers */
    600	rv = acpi_opregion_init(opr_dev);
    601	if (rv) {
    602		dev_err(cl_data_to_dev(opr_dev), "ACPI opregion init failed\n");
    603		goto err_exit;
    604	}
    605
    606	/* Reprobe devices depending on ECLite - battery, fan, etc. */
    607	acpi_dev_clear_dependencies(opr_dev->adev);
    608
    609	return 0;
    610err_exit:
    611	ishtp_set_connection_state(ecl_ishtp_cl, ISHTP_CL_DISCONNECTING);
    612	ishtp_cl_disconnect(ecl_ishtp_cl);
    613	ecl_ishtp_cl_deinit(ecl_ishtp_cl);
    614
    615	return rv;
    616}
    617
    618static void ecl_ishtp_cl_remove(struct ishtp_cl_device *cl_device)
    619{
    620	struct ishtp_cl *ecl_ishtp_cl = ishtp_get_drvdata(cl_device);
    621	struct ishtp_opregion_dev *opr_dev =
    622		ishtp_get_client_data(ecl_ishtp_cl);
    623
    624	if (opr_dev->acpi_init_done)
    625		acpi_opregion_deinit(opr_dev);
    626
    627	acpi_dev_put(opr_dev->adev);
    628
    629	ishtp_set_connection_state(ecl_ishtp_cl, ISHTP_CL_DISCONNECTING);
    630	ishtp_cl_disconnect(ecl_ishtp_cl);
    631	ecl_ishtp_cl_deinit(ecl_ishtp_cl);
    632
    633	cancel_work_sync(&opr_dev->reset_work);
    634	cancel_work_sync(&opr_dev->event_work);
    635}
    636
    637static int ecl_ishtp_cl_reset(struct ishtp_cl_device *cl_device)
    638{
    639	struct ishtp_cl *ecl_ishtp_cl = ishtp_get_drvdata(cl_device);
    640	struct ishtp_opregion_dev *opr_dev =
    641		ishtp_get_client_data(ecl_ishtp_cl);
    642
    643	schedule_work(&opr_dev->reset_work);
    644
    645	return 0;
    646}
    647
    648static int ecl_ishtp_cl_suspend(struct device *device)
    649{
    650	struct ishtp_cl_device *cl_device = ishtp_dev_to_cl_device(device);
    651	struct ishtp_cl *ecl_ishtp_cl = ishtp_get_drvdata(cl_device);
    652	struct ishtp_opregion_dev *opr_dev =
    653		ishtp_get_client_data(ecl_ishtp_cl);
    654
    655	if (acpi_target_system_state() == ACPI_STATE_S0)
    656		return 0;
    657
    658	acpi_opregion_deinit(opr_dev);
    659	ecl_ish_cl_enable_events(opr_dev, false);
    660
    661	return 0;
    662}
    663
    664static int ecl_ishtp_cl_resume(struct device *device)
    665{
    666	/* A reset is expected to call after an Sx. At this point
    667	 * we are not sure if the link is up or not to restore anything,
    668	 * so do nothing in resume path
    669	 */
    670	return 0;
    671}
    672
    673static const struct dev_pm_ops ecl_ishtp_pm_ops = {
    674	.suspend = ecl_ishtp_cl_suspend,
    675	.resume = ecl_ishtp_cl_resume,
    676};
    677
    678static struct ishtp_cl_driver ecl_ishtp_cl_driver = {
    679	.name = "ishtp-eclite",
    680	.id = ecl_ishtp_id_table,
    681	.probe = ecl_ishtp_cl_probe,
    682	.remove = ecl_ishtp_cl_remove,
    683	.reset = ecl_ishtp_cl_reset,
    684	.driver.pm = &ecl_ishtp_pm_ops,
    685};
    686
    687static int __init ecl_ishtp_init(void)
    688{
    689	return ishtp_cl_driver_register(&ecl_ishtp_cl_driver, THIS_MODULE);
    690}
    691
    692static void __exit ecl_ishtp_exit(void)
    693{
    694	return ishtp_cl_driver_unregister(&ecl_ishtp_cl_driver);
    695}
    696
    697late_initcall(ecl_ishtp_init);
    698module_exit(ecl_ishtp_exit);
    699
    700MODULE_DESCRIPTION("ISH ISHTP eclite client opregion driver");
    701MODULE_AUTHOR("K Naduvalath, Sumesh <sumesh.k.naduvalath@intel.com>");
    702
    703MODULE_LICENSE("GPL v2");