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