init.c (da0851fe3a8ebc416ab61ce50ef2fb3c3d7375c9) | init.c (9b0d5efc421ac79d9a6d97c681eff93288093784) |
---|---|
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 | 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> |
|
17#include <linux/pci.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" | 18#include <linux/pci.h> 19#include <linux/sched.h> 20#include <linux/wait.h> 21#include <linux/delay.h> 22 23#include <linux/mei.h> 24 25#include "mei_dev.h" |
26#include "hbm.h" |
|
25#include "client.h" 26 27const char *mei_dev_state_str(int state) 28{ 29#define MEI_DEV_STATE(state) case MEI_DEV_##state: return #state 30 switch (state) { 31 MEI_DEV_STATE(INITIALIZING); 32 MEI_DEV_STATE(INIT_CLIENTS); 33 MEI_DEV_STATE(ENABLED); 34 MEI_DEV_STATE(RESETING); 35 MEI_DEV_STATE(DISABLED); | 27#include "client.h" 28 29const char *mei_dev_state_str(int state) 30{ 31#define MEI_DEV_STATE(state) case MEI_DEV_##state: return #state 32 switch (state) { 33 MEI_DEV_STATE(INITIALIZING); 34 MEI_DEV_STATE(INIT_CLIENTS); 35 MEI_DEV_STATE(ENABLED); 36 MEI_DEV_STATE(RESETING); 37 MEI_DEV_STATE(DISABLED); |
36 MEI_DEV_STATE(RECOVERING_FROM_RESET); | |
37 MEI_DEV_STATE(POWER_DOWN); 38 MEI_DEV_STATE(POWER_UP); 39 default: 40 return "unkown"; 41 } 42#undef MEI_DEV_STATE 43} 44 45void mei_device_init(struct mei_device *dev) 46{ 47 /* setup our list array */ 48 INIT_LIST_HEAD(&dev->file_list); | 38 MEI_DEV_STATE(POWER_DOWN); 39 MEI_DEV_STATE(POWER_UP); 40 default: 41 return "unkown"; 42 } 43#undef MEI_DEV_STATE 44} 45 46void mei_device_init(struct mei_device *dev) 47{ 48 /* setup our list array */ 49 INIT_LIST_HEAD(&dev->file_list); |
50 INIT_LIST_HEAD(&dev->device_list); |
|
49 mutex_init(&dev->device_lock); | 51 mutex_init(&dev->device_lock); |
52 init_waitqueue_head(&dev->wait_hw_ready); |
|
50 init_waitqueue_head(&dev->wait_recvd_msg); 51 init_waitqueue_head(&dev->wait_stop_wd); 52 dev->dev_state = MEI_DEV_INITIALIZING; 53 54 mei_io_list_init(&dev->read_list); 55 mei_io_list_init(&dev->write_list); 56 mei_io_list_init(&dev->write_waiting_list); 57 mei_io_list_init(&dev->ctrl_wr_list); 58 mei_io_list_init(&dev->ctrl_rd_list); | 53 init_waitqueue_head(&dev->wait_recvd_msg); 54 init_waitqueue_head(&dev->wait_stop_wd); 55 dev->dev_state = MEI_DEV_INITIALIZING; 56 57 mei_io_list_init(&dev->read_list); 58 mei_io_list_init(&dev->write_list); 59 mei_io_list_init(&dev->write_waiting_list); 60 mei_io_list_init(&dev->ctrl_wr_list); 61 mei_io_list_init(&dev->ctrl_rd_list); |
62 63 INIT_DELAYED_WORK(&dev->timer_work, mei_timer); 64 INIT_WORK(&dev->init_work, mei_host_client_init); 65 66 INIT_LIST_HEAD(&dev->wd_cl.link); 67 INIT_LIST_HEAD(&dev->iamthif_cl.link); 68 mei_io_list_init(&dev->amthif_cmd_list); 69 mei_io_list_init(&dev->amthif_rd_complete_list); 70 |
|
59} | 71} |
72EXPORT_SYMBOL_GPL(mei_device_init); |
|
60 61/** | 73 74/** |
62 * mei_hw_init - initializes host and fw to start work. | 75 * mei_start - initializes host and fw to start work. |
63 * 64 * @dev: the device structure 65 * 66 * returns 0 on success, <0 on failure. 67 */ | 76 * 77 * @dev: the device structure 78 * 79 * returns 0 on success, <0 on failure. 80 */ |
68int mei_hw_init(struct mei_device *dev) | 81int mei_start(struct mei_device *dev) |
69{ | 82{ |
70 int ret = 0; 71 | |
72 mutex_lock(&dev->device_lock); 73 74 /* acknowledge interrupt and stop interupts */ 75 mei_clear_interrupts(dev); 76 77 mei_hw_config(dev); 78 | 83 mutex_lock(&dev->device_lock); 84 85 /* acknowledge interrupt and stop interupts */ 86 mei_clear_interrupts(dev); 87 88 mei_hw_config(dev); 89 |
79 dev->recvd_msg = false; | |
80 dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n"); 81 82 mei_reset(dev, 1); 83 | 90 dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n"); 91 92 mei_reset(dev, 1); 93 |
84 /* wait for ME to turn on ME_RDY */ 85 if (!dev->recvd_msg) { 86 mutex_unlock(&dev->device_lock); 87 ret = wait_event_interruptible_timeout(dev->wait_recvd_msg, 88 dev->recvd_msg, 89 mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT)); 90 mutex_lock(&dev->device_lock); 91 } 92 93 if (ret <= 0 && !dev->recvd_msg) { 94 dev->dev_state = MEI_DEV_DISABLED; 95 dev_dbg(&dev->pdev->dev, 96 "wait_event_interruptible_timeout failed" 97 "on wait for ME to turn on ME_RDY.\n"); | 94 if (mei_hbm_start_wait(dev)) { 95 dev_err(&dev->pdev->dev, "HBM haven't started"); |
98 goto err; 99 } 100 | 96 goto err; 97 } 98 |
101 | |
102 if (!mei_host_is_ready(dev)) { 103 dev_err(&dev->pdev->dev, "host is not ready.\n"); 104 goto err; 105 } 106 107 if (!mei_hw_is_ready(dev)) { 108 dev_err(&dev->pdev->dev, "ME is not ready.\n"); 109 goto err; 110 } 111 112 if (dev->version.major_version != HBM_MAJOR_VERSION || 113 dev->version.minor_version != HBM_MINOR_VERSION) { 114 dev_dbg(&dev->pdev->dev, "MEI start failed.\n"); 115 goto err; 116 } 117 | 99 if (!mei_host_is_ready(dev)) { 100 dev_err(&dev->pdev->dev, "host is not ready.\n"); 101 goto err; 102 } 103 104 if (!mei_hw_is_ready(dev)) { 105 dev_err(&dev->pdev->dev, "ME is not ready.\n"); 106 goto err; 107 } 108 109 if (dev->version.major_version != HBM_MAJOR_VERSION || 110 dev->version.minor_version != HBM_MINOR_VERSION) { 111 dev_dbg(&dev->pdev->dev, "MEI start failed.\n"); 112 goto err; 113 } 114 |
118 dev->recvd_msg = false; | |
119 dev_dbg(&dev->pdev->dev, "link layer has been established.\n"); 120 121 mutex_unlock(&dev->device_lock); 122 return 0; 123err: 124 dev_err(&dev->pdev->dev, "link layer initialization failed.\n"); 125 dev->dev_state = MEI_DEV_DISABLED; 126 mutex_unlock(&dev->device_lock); 127 return -ENODEV; 128} | 115 dev_dbg(&dev->pdev->dev, "link layer has been established.\n"); 116 117 mutex_unlock(&dev->device_lock); 118 return 0; 119err: 120 dev_err(&dev->pdev->dev, "link layer initialization failed.\n"); 121 dev->dev_state = MEI_DEV_DISABLED; 122 mutex_unlock(&dev->device_lock); 123 return -ENODEV; 124} |
125EXPORT_SYMBOL_GPL(mei_start); |
|
129 130/** 131 * mei_reset - resets host and fw. 132 * 133 * @dev: the device structure 134 * @interrupts_enabled: if interrupt should be enabled after reset. 135 */ 136void mei_reset(struct mei_device *dev, int interrupts_enabled) 137{ 138 bool unexpected; 139 | 126 127/** 128 * mei_reset - resets host and fw. 129 * 130 * @dev: the device structure 131 * @interrupts_enabled: if interrupt should be enabled after reset. 132 */ 133void mei_reset(struct mei_device *dev, int interrupts_enabled) 134{ 135 bool unexpected; 136 |
140 if (dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) 141 return; 142 | |
143 unexpected = (dev->dev_state != MEI_DEV_INITIALIZING && 144 dev->dev_state != MEI_DEV_DISABLED && 145 dev->dev_state != MEI_DEV_POWER_DOWN && 146 dev->dev_state != MEI_DEV_POWER_UP); 147 148 mei_hw_reset(dev, interrupts_enabled); 149 | 137 unexpected = (dev->dev_state != MEI_DEV_INITIALIZING && 138 dev->dev_state != MEI_DEV_DISABLED && 139 dev->dev_state != MEI_DEV_POWER_DOWN && 140 dev->dev_state != MEI_DEV_POWER_UP); 141 142 mei_hw_reset(dev, interrupts_enabled); 143 |
144 dev->hbm_state = MEI_HBM_IDLE; |
|
150 151 if (dev->dev_state != MEI_DEV_INITIALIZING) { 152 if (dev->dev_state != MEI_DEV_DISABLED && 153 dev->dev_state != MEI_DEV_POWER_DOWN) 154 dev->dev_state = MEI_DEV_RESETING; 155 156 mei_cl_all_disconnect(dev); 157 --- 13 unchanged lines hidden (view full) --- 171 dev->me_clients_num = 0; 172 dev->rd_msg_hdr = 0; 173 dev->wd_pending = false; 174 175 if (unexpected) 176 dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n", 177 mei_dev_state_str(dev->dev_state)); 178 | 145 146 if (dev->dev_state != MEI_DEV_INITIALIZING) { 147 if (dev->dev_state != MEI_DEV_DISABLED && 148 dev->dev_state != MEI_DEV_POWER_DOWN) 149 dev->dev_state = MEI_DEV_RESETING; 150 151 mei_cl_all_disconnect(dev); 152 --- 13 unchanged lines hidden (view full) --- 166 dev->me_clients_num = 0; 167 dev->rd_msg_hdr = 0; 168 dev->wd_pending = false; 169 170 if (unexpected) 171 dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n", 172 mei_dev_state_str(dev->dev_state)); 173 |
174 if (!interrupts_enabled) { 175 dev_dbg(&dev->pdev->dev, "intr not enabled end of reset\n"); 176 return; 177 } 178 179 mei_hw_start(dev); 180 181 dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n"); 182 /* link is established * start sending messages. */ 183 184 dev->dev_state = MEI_DEV_INIT_CLIENTS; 185 186 mei_hbm_start_req(dev); 187 |
|
179 /* wake up all readings so they can be interrupted */ 180 mei_cl_all_read_wakeup(dev); 181 182 /* remove all waiting requests */ 183 mei_cl_all_write_clear(dev); 184} | 188 /* wake up all readings so they can be interrupted */ 189 mei_cl_all_read_wakeup(dev); 190 191 /* remove all waiting requests */ 192 mei_cl_all_write_clear(dev); 193} |
194EXPORT_SYMBOL_GPL(mei_reset); |
|
185 186void mei_stop(struct mei_device *dev) 187{ 188 dev_dbg(&dev->pdev->dev, "stopping the device.\n"); 189 190 mutex_lock(&dev->device_lock); 191 192 cancel_delayed_work(&dev->timer_work); 193 194 mei_wd_stop(dev); 195 | 195 196void mei_stop(struct mei_device *dev) 197{ 198 dev_dbg(&dev->pdev->dev, "stopping the device.\n"); 199 200 mutex_lock(&dev->device_lock); 201 202 cancel_delayed_work(&dev->timer_work); 203 204 mei_wd_stop(dev); 205 |
206 mei_nfc_host_exit(); 207 |
|
196 dev->dev_state = MEI_DEV_POWER_DOWN; 197 mei_reset(dev, 0); 198 199 mutex_unlock(&dev->device_lock); 200 201 flush_scheduled_work(); | 208 dev->dev_state = MEI_DEV_POWER_DOWN; 209 mei_reset(dev, 0); 210 211 mutex_unlock(&dev->device_lock); 212 213 flush_scheduled_work(); |
214 215 mei_watchdog_unregister(dev); |
|
202} | 216} |
217EXPORT_SYMBOL_GPL(mei_stop); |
|
203 204 205 | 218 219 220 |
206 | |