diff options
Diffstat (limited to 'drivers/misc/mei/init.c')
-rw-r--r-- | drivers/misc/mei/init.c | 41 |
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 | */ |
167 | int mei_start(struct mei_device *dev) | 164 | int 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 | } |
246 | EXPORT_SYMBOL_GPL(mei_restart); | 259 | EXPORT_SYMBOL_GPL(mei_restart); |
247 | 260 | ||
248 | |||
249 | static void mei_reset_work(struct work_struct *work) | 261 | static 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 | ||
264 | void mei_stop(struct mei_device *dev) | 283 | void mei_stop(struct mei_device *dev) |