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

init.c (9476B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2012-2019, Intel Corporation. All rights reserved.
      4 * Intel Management Engine Interface (Intel MEI) Linux driver
      5 */
      6
      7#include <linux/export.h>
      8#include <linux/sched.h>
      9#include <linux/wait.h>
     10#include <linux/delay.h>
     11
     12#include <linux/mei.h>
     13
     14#include "mei_dev.h"
     15#include "hbm.h"
     16#include "client.h"
     17
     18const char *mei_dev_state_str(int state)
     19{
     20#define MEI_DEV_STATE(state) case MEI_DEV_##state: return #state
     21	switch (state) {
     22	MEI_DEV_STATE(INITIALIZING);
     23	MEI_DEV_STATE(INIT_CLIENTS);
     24	MEI_DEV_STATE(ENABLED);
     25	MEI_DEV_STATE(RESETTING);
     26	MEI_DEV_STATE(DISABLED);
     27	MEI_DEV_STATE(POWERING_DOWN);
     28	MEI_DEV_STATE(POWER_DOWN);
     29	MEI_DEV_STATE(POWER_UP);
     30	default:
     31		return "unknown";
     32	}
     33#undef MEI_DEV_STATE
     34}
     35
     36const char *mei_pg_state_str(enum mei_pg_state state)
     37{
     38#define MEI_PG_STATE(state) case MEI_PG_##state: return #state
     39	switch (state) {
     40	MEI_PG_STATE(OFF);
     41	MEI_PG_STATE(ON);
     42	default:
     43		return "unknown";
     44	}
     45#undef MEI_PG_STATE
     46}
     47
     48/**
     49 * mei_fw_status2str - convert fw status registers to printable string
     50 *
     51 * @fw_status:  firmware status
     52 * @buf: string buffer at minimal size MEI_FW_STATUS_STR_SZ
     53 * @len: buffer len must be >= MEI_FW_STATUS_STR_SZ
     54 *
     55 * Return: number of bytes written or -EINVAL if buffer is to small
     56 */
     57ssize_t mei_fw_status2str(struct mei_fw_status *fw_status,
     58			  char *buf, size_t len)
     59{
     60	ssize_t cnt = 0;
     61	int i;
     62
     63	buf[0] = '\0';
     64
     65	if (len < MEI_FW_STATUS_STR_SZ)
     66		return -EINVAL;
     67
     68	for (i = 0; i < fw_status->count; i++)
     69		cnt += scnprintf(buf + cnt, len - cnt, "%08X ",
     70				fw_status->status[i]);
     71
     72	/* drop last space */
     73	buf[cnt] = '\0';
     74	return cnt;
     75}
     76EXPORT_SYMBOL_GPL(mei_fw_status2str);
     77
     78/**
     79 * mei_cancel_work - Cancel mei background jobs
     80 *
     81 * @dev: the device structure
     82 */
     83void mei_cancel_work(struct mei_device *dev)
     84{
     85	cancel_work_sync(&dev->reset_work);
     86	cancel_work_sync(&dev->bus_rescan_work);
     87
     88	cancel_delayed_work_sync(&dev->timer_work);
     89}
     90EXPORT_SYMBOL_GPL(mei_cancel_work);
     91
     92/**
     93 * mei_reset - resets host and fw.
     94 *
     95 * @dev: the device structure
     96 *
     97 * Return: 0 on success or < 0 if the reset hasn't succeeded
     98 */
     99int mei_reset(struct mei_device *dev)
    100{
    101	enum mei_dev_state state = dev->dev_state;
    102	bool interrupts_enabled;
    103	int ret;
    104
    105	if (state != MEI_DEV_INITIALIZING &&
    106	    state != MEI_DEV_DISABLED &&
    107	    state != MEI_DEV_POWER_DOWN &&
    108	    state != MEI_DEV_POWER_UP) {
    109		char fw_sts_str[MEI_FW_STATUS_STR_SZ];
    110
    111		mei_fw_status_str(dev, fw_sts_str, MEI_FW_STATUS_STR_SZ);
    112		dev_warn(dev->dev, "unexpected reset: dev_state = %s fw status = %s\n",
    113			 mei_dev_state_str(state), fw_sts_str);
    114	}
    115
    116	mei_clear_interrupts(dev);
    117
    118	/* we're already in reset, cancel the init timer
    119	 * if the reset was called due the hbm protocol error
    120	 * we need to call it before hw start
    121	 * so the hbm watchdog won't kick in
    122	 */
    123	mei_hbm_idle(dev);
    124
    125	/* enter reset flow */
    126	interrupts_enabled = state != MEI_DEV_POWER_DOWN;
    127	mei_set_devstate(dev, MEI_DEV_RESETTING);
    128
    129	dev->reset_count++;
    130	if (dev->reset_count > MEI_MAX_CONSEC_RESET) {
    131		dev_err(dev->dev, "reset: reached maximal consecutive resets: disabling the device\n");
    132		mei_set_devstate(dev, MEI_DEV_DISABLED);
    133		return -ENODEV;
    134	}
    135
    136	ret = mei_hw_reset(dev, interrupts_enabled);
    137	/* fall through and remove the sw state even if hw reset has failed */
    138
    139	/* no need to clean up software state in case of power up */
    140	if (state != MEI_DEV_INITIALIZING && state != MEI_DEV_POWER_UP)
    141		mei_cl_all_disconnect(dev);
    142
    143	mei_hbm_reset(dev);
    144
    145	memset(dev->rd_msg_hdr, 0, sizeof(dev->rd_msg_hdr));
    146
    147	if (ret) {
    148		dev_err(dev->dev, "hw_reset failed ret = %d\n", ret);
    149		return ret;
    150	}
    151
    152	if (state == MEI_DEV_POWER_DOWN) {
    153		dev_dbg(dev->dev, "powering down: end of reset\n");
    154		mei_set_devstate(dev, MEI_DEV_DISABLED);
    155		return 0;
    156	}
    157
    158	ret = mei_hw_start(dev);
    159	if (ret) {
    160		dev_err(dev->dev, "hw_start failed ret = %d\n", ret);
    161		return ret;
    162	}
    163
    164	if (dev->dev_state != MEI_DEV_RESETTING) {
    165		dev_dbg(dev->dev, "wrong state = %d on link start\n", dev->dev_state);
    166		return 0;
    167	}
    168
    169	dev_dbg(dev->dev, "link is established start sending messages.\n");
    170
    171	mei_set_devstate(dev, MEI_DEV_INIT_CLIENTS);
    172	ret = mei_hbm_start_req(dev);
    173	if (ret) {
    174		dev_err(dev->dev, "hbm_start failed ret = %d\n", ret);
    175		mei_set_devstate(dev, MEI_DEV_RESETTING);
    176		return ret;
    177	}
    178
    179	return 0;
    180}
    181EXPORT_SYMBOL_GPL(mei_reset);
    182
    183/**
    184 * mei_start - initializes host and fw to start work.
    185 *
    186 * @dev: the device structure
    187 *
    188 * Return: 0 on success, <0 on failure.
    189 */
    190int mei_start(struct mei_device *dev)
    191{
    192	int ret;
    193
    194	mutex_lock(&dev->device_lock);
    195
    196	/* acknowledge interrupt and stop interrupts */
    197	mei_clear_interrupts(dev);
    198
    199	ret = mei_hw_config(dev);
    200	if (ret)
    201		goto err;
    202
    203	dev_dbg(dev->dev, "reset in start the mei device.\n");
    204
    205	dev->reset_count = 0;
    206	do {
    207		mei_set_devstate(dev, MEI_DEV_INITIALIZING);
    208		ret = mei_reset(dev);
    209
    210		if (ret == -ENODEV || dev->dev_state == MEI_DEV_DISABLED) {
    211			dev_err(dev->dev, "reset failed ret = %d", ret);
    212			goto err;
    213		}
    214	} while (ret);
    215
    216	if (mei_hbm_start_wait(dev)) {
    217		dev_err(dev->dev, "HBM haven't started");
    218		goto err;
    219	}
    220
    221	if (!mei_host_is_ready(dev)) {
    222		dev_err(dev->dev, "host is not ready.\n");
    223		goto err;
    224	}
    225
    226	if (!mei_hw_is_ready(dev)) {
    227		dev_err(dev->dev, "ME is not ready.\n");
    228		goto err;
    229	}
    230
    231	if (!mei_hbm_version_is_supported(dev)) {
    232		dev_dbg(dev->dev, "MEI start failed.\n");
    233		goto err;
    234	}
    235
    236	dev_dbg(dev->dev, "link layer has been established.\n");
    237
    238	mutex_unlock(&dev->device_lock);
    239	return 0;
    240err:
    241	dev_err(dev->dev, "link layer initialization failed.\n");
    242	mei_set_devstate(dev, MEI_DEV_DISABLED);
    243	mutex_unlock(&dev->device_lock);
    244	return -ENODEV;
    245}
    246EXPORT_SYMBOL_GPL(mei_start);
    247
    248/**
    249 * mei_restart - restart device after suspend
    250 *
    251 * @dev: the device structure
    252 *
    253 * Return: 0 on success or -ENODEV if the restart hasn't succeeded
    254 */
    255int mei_restart(struct mei_device *dev)
    256{
    257	int err;
    258
    259	mutex_lock(&dev->device_lock);
    260
    261	mei_set_devstate(dev, MEI_DEV_POWER_UP);
    262	dev->reset_count = 0;
    263
    264	err = mei_reset(dev);
    265
    266	mutex_unlock(&dev->device_lock);
    267
    268	if (err == -ENODEV || dev->dev_state == MEI_DEV_DISABLED) {
    269		dev_err(dev->dev, "device disabled = %d\n", err);
    270		return -ENODEV;
    271	}
    272
    273	/* try to start again */
    274	if (err)
    275		schedule_work(&dev->reset_work);
    276
    277
    278	return 0;
    279}
    280EXPORT_SYMBOL_GPL(mei_restart);
    281
    282static void mei_reset_work(struct work_struct *work)
    283{
    284	struct mei_device *dev =
    285		container_of(work, struct mei_device,  reset_work);
    286	int ret;
    287
    288	mei_clear_interrupts(dev);
    289	mei_synchronize_irq(dev);
    290
    291	mutex_lock(&dev->device_lock);
    292
    293	ret = mei_reset(dev);
    294
    295	mutex_unlock(&dev->device_lock);
    296
    297	if (dev->dev_state == MEI_DEV_DISABLED) {
    298		dev_err(dev->dev, "device disabled = %d\n", ret);
    299		return;
    300	}
    301
    302	/* retry reset in case of failure */
    303	if (ret)
    304		schedule_work(&dev->reset_work);
    305}
    306
    307void mei_stop(struct mei_device *dev)
    308{
    309	dev_dbg(dev->dev, "stopping the device.\n");
    310
    311	mutex_lock(&dev->device_lock);
    312	mei_set_devstate(dev, MEI_DEV_POWERING_DOWN);
    313	mutex_unlock(&dev->device_lock);
    314	mei_cl_bus_remove_devices(dev);
    315	mutex_lock(&dev->device_lock);
    316	mei_set_devstate(dev, MEI_DEV_POWER_DOWN);
    317	mutex_unlock(&dev->device_lock);
    318
    319	mei_cancel_work(dev);
    320
    321	mei_clear_interrupts(dev);
    322	mei_synchronize_irq(dev);
    323
    324	mutex_lock(&dev->device_lock);
    325
    326	mei_reset(dev);
    327	/* move device to disabled state unconditionally */
    328	mei_set_devstate(dev, MEI_DEV_DISABLED);
    329
    330	mutex_unlock(&dev->device_lock);
    331}
    332EXPORT_SYMBOL_GPL(mei_stop);
    333
    334/**
    335 * mei_write_is_idle - check if the write queues are idle
    336 *
    337 * @dev: the device structure
    338 *
    339 * Return: true of there is no pending write
    340 */
    341bool mei_write_is_idle(struct mei_device *dev)
    342{
    343	bool idle = (dev->dev_state == MEI_DEV_ENABLED &&
    344		list_empty(&dev->ctrl_wr_list) &&
    345		list_empty(&dev->write_list)   &&
    346		list_empty(&dev->write_waiting_list));
    347
    348	dev_dbg(dev->dev, "write pg: is idle[%d] state=%s ctrl=%01d write=%01d wwait=%01d\n",
    349		idle,
    350		mei_dev_state_str(dev->dev_state),
    351		list_empty(&dev->ctrl_wr_list),
    352		list_empty(&dev->write_list),
    353		list_empty(&dev->write_waiting_list));
    354
    355	return idle;
    356}
    357EXPORT_SYMBOL_GPL(mei_write_is_idle);
    358
    359/**
    360 * mei_device_init  -- initialize mei_device structure
    361 *
    362 * @dev: the mei device
    363 * @device: the device structure
    364 * @hw_ops: hw operations
    365 */
    366void mei_device_init(struct mei_device *dev,
    367		     struct device *device,
    368		     const struct mei_hw_ops *hw_ops)
    369{
    370	/* setup our list array */
    371	INIT_LIST_HEAD(&dev->file_list);
    372	INIT_LIST_HEAD(&dev->device_list);
    373	INIT_LIST_HEAD(&dev->me_clients);
    374	mutex_init(&dev->device_lock);
    375	init_rwsem(&dev->me_clients_rwsem);
    376	mutex_init(&dev->cl_bus_lock);
    377	init_waitqueue_head(&dev->wait_hw_ready);
    378	init_waitqueue_head(&dev->wait_pg);
    379	init_waitqueue_head(&dev->wait_hbm_start);
    380	dev->dev_state = MEI_DEV_INITIALIZING;
    381	dev->reset_count = 0;
    382
    383	INIT_LIST_HEAD(&dev->write_list);
    384	INIT_LIST_HEAD(&dev->write_waiting_list);
    385	INIT_LIST_HEAD(&dev->ctrl_wr_list);
    386	INIT_LIST_HEAD(&dev->ctrl_rd_list);
    387	dev->tx_queue_limit = MEI_TX_QUEUE_LIMIT_DEFAULT;
    388
    389	INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
    390	INIT_WORK(&dev->reset_work, mei_reset_work);
    391	INIT_WORK(&dev->bus_rescan_work, mei_cl_bus_rescan_work);
    392
    393	bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
    394	dev->open_handle_count = 0;
    395
    396	/*
    397	 * Reserving the first client ID
    398	 * 0: Reserved for MEI Bus Message communications
    399	 */
    400	bitmap_set(dev->host_clients_map, 0, 1);
    401
    402	dev->pg_event = MEI_PG_EVENT_IDLE;
    403	dev->ops      = hw_ops;
    404	dev->dev      = device;
    405}
    406EXPORT_SYMBOL_GPL(mei_device_init);
    407