aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/mei/init.c')
-rw-r--r--drivers/misc/mei/init.c41
1 files changed, 30 insertions, 11 deletions
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index cdd31c2a2a2b..214dcef9750a 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -116,7 +116,6 @@ int mei_reset(struct mei_device *dev)
116 mei_cl_unlink(&dev->wd_cl); 116 mei_cl_unlink(&dev->wd_cl);
117 mei_cl_unlink(&dev->iamthif_cl); 117 mei_cl_unlink(&dev->iamthif_cl);
118 mei_amthif_reset_params(dev); 118 mei_amthif_reset_params(dev);
119 memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg));
120 } 119 }
121 120
122 121
@@ -126,7 +125,6 @@ int mei_reset(struct mei_device *dev)
126 125
127 if (ret) { 126 if (ret) {
128 dev_err(&dev->pdev->dev, "hw_reset failed ret = %d\n", ret); 127 dev_err(&dev->pdev->dev, "hw_reset failed ret = %d\n", ret);
129 dev->dev_state = MEI_DEV_DISABLED;
130 return ret; 128 return ret;
131 } 129 }
132 130
@@ -139,7 +137,6 @@ int mei_reset(struct mei_device *dev)
139 ret = mei_hw_start(dev); 137 ret = mei_hw_start(dev);
140 if (ret) { 138 if (ret) {
141 dev_err(&dev->pdev->dev, "hw_start failed ret = %d\n", ret); 139 dev_err(&dev->pdev->dev, "hw_start failed ret = %d\n", ret);
142 dev->dev_state = MEI_DEV_DISABLED;
143 return ret; 140 return ret;
144 } 141 }
145 142
@@ -149,7 +146,7 @@ int mei_reset(struct mei_device *dev)
149 ret = mei_hbm_start_req(dev); 146 ret = mei_hbm_start_req(dev);
150 if (ret) { 147 if (ret) {
151 dev_err(&dev->pdev->dev, "hbm_start failed ret = %d\n", ret); 148 dev_err(&dev->pdev->dev, "hbm_start failed ret = %d\n", ret);
152 dev->dev_state = MEI_DEV_DISABLED; 149 dev->dev_state = MEI_DEV_RESETTING;
153 return ret; 150 return ret;
154 } 151 }
155 152
@@ -166,6 +163,7 @@ EXPORT_SYMBOL_GPL(mei_reset);
166 */ 163 */
167int mei_start(struct mei_device *dev) 164int mei_start(struct mei_device *dev)
168{ 165{
166 int ret;
169 mutex_lock(&dev->device_lock); 167 mutex_lock(&dev->device_lock);
170 168
171 /* acknowledge interrupt and stop interrupts */ 169 /* acknowledge interrupt and stop interrupts */
@@ -175,10 +173,18 @@ int mei_start(struct mei_device *dev)
175 173
176 dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n"); 174 dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n");
177 175
178 dev->dev_state = MEI_DEV_INITIALIZING;
179 dev->reset_count = 0; 176 dev->reset_count = 0;
180 mei_reset(dev); 177 do {
178 dev->dev_state = MEI_DEV_INITIALIZING;
179 ret = mei_reset(dev);
180
181 if (ret == -ENODEV || dev->dev_state == MEI_DEV_DISABLED) {
182 dev_err(&dev->pdev->dev, "reset failed ret = %d", ret);
183 goto err;
184 }
185 } while (ret);
181 186
187 /* we cannot start the device w/o hbm start message completed */
182 if (dev->dev_state == MEI_DEV_DISABLED) { 188 if (dev->dev_state == MEI_DEV_DISABLED) {
183 dev_err(&dev->pdev->dev, "reset failed"); 189 dev_err(&dev->pdev->dev, "reset failed");
184 goto err; 190 goto err;
@@ -238,27 +244,40 @@ int mei_restart(struct mei_device *dev)
238 244
239 mutex_unlock(&dev->device_lock); 245 mutex_unlock(&dev->device_lock);
240 246
241 if (err || dev->dev_state == MEI_DEV_DISABLED) 247 if (err == -ENODEV || dev->dev_state == MEI_DEV_DISABLED) {
248 dev_err(&dev->pdev->dev, "device disabled = %d\n", err);
242 return -ENODEV; 249 return -ENODEV;
250 }
251
252 /* try to start again */
253 if (err)
254 schedule_work(&dev->reset_work);
255
243 256
244 return 0; 257 return 0;
245} 258}
246EXPORT_SYMBOL_GPL(mei_restart); 259EXPORT_SYMBOL_GPL(mei_restart);
247 260
248
249static void mei_reset_work(struct work_struct *work) 261static void mei_reset_work(struct work_struct *work)
250{ 262{
251 struct mei_device *dev = 263 struct mei_device *dev =
252 container_of(work, struct mei_device, reset_work); 264 container_of(work, struct mei_device, reset_work);
265 int ret;
253 266
254 mutex_lock(&dev->device_lock); 267 mutex_lock(&dev->device_lock);
255 268
256 mei_reset(dev); 269 ret = mei_reset(dev);
257 270
258 mutex_unlock(&dev->device_lock); 271 mutex_unlock(&dev->device_lock);
259 272
260 if (dev->dev_state == MEI_DEV_DISABLED) 273 if (dev->dev_state == MEI_DEV_DISABLED) {
261 dev_err(&dev->pdev->dev, "reset failed"); 274 dev_err(&dev->pdev->dev, "device disabled = %d\n", ret);
275 return;
276 }
277
278 /* retry reset in case of failure */
279 if (ret)
280 schedule_work(&dev->reset_work);
262} 281}
263 282
264void mei_stop(struct mei_device *dev) 283void mei_stop(struct mei_device *dev)