diff options
Diffstat (limited to 'drivers/misc/mei')
-rw-r--r-- | drivers/misc/mei/hw-me.c | 15 | ||||
-rw-r--r-- | drivers/misc/mei/hw-txe.c | 43 | ||||
-rw-r--r-- | drivers/misc/mei/hw-txe.h | 14 | ||||
-rw-r--r-- | drivers/misc/mei/init.c | 2 | ||||
-rw-r--r-- | drivers/misc/mei/mei_dev.h | 38 |
5 files changed, 93 insertions, 19 deletions
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 7a7e66250dfd..02f3b0c3a2a3 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c | |||
@@ -113,6 +113,19 @@ static void mei_me_hw_config(struct mei_device *dev) | |||
113 | /* Doesn't change in runtime */ | 113 | /* Doesn't change in runtime */ |
114 | dev->hbuf_depth = (hcsr & H_CBD) >> 24; | 114 | dev->hbuf_depth = (hcsr & H_CBD) >> 24; |
115 | } | 115 | } |
116 | |||
117 | /** | ||
118 | * mei_me_pg_state - translate internal pg state | ||
119 | * to the mei power gating state | ||
120 | * | ||
121 | * @hw - me hardware | ||
122 | * returns: MEI_PG_OFF if aliveness is on and MEI_PG_ON otherwise | ||
123 | */ | ||
124 | static inline enum mei_pg_state mei_me_pg_state(struct mei_device *dev) | ||
125 | { | ||
126 | return MEI_PG_OFF; | ||
127 | } | ||
128 | |||
116 | /** | 129 | /** |
117 | * mei_clear_interrupts - clear and stop interrupts | 130 | * mei_clear_interrupts - clear and stop interrupts |
118 | * | 131 | * |
@@ -601,6 +614,8 @@ end: | |||
601 | } | 614 | } |
602 | static const struct mei_hw_ops mei_me_hw_ops = { | 615 | static const struct mei_hw_ops mei_me_hw_ops = { |
603 | 616 | ||
617 | .pg_state = mei_me_pg_state, | ||
618 | |||
604 | .host_is_ready = mei_me_host_is_ready, | 619 | .host_is_ready = mei_me_host_is_ready, |
605 | 620 | ||
606 | .hw_is_ready = mei_me_hw_is_ready, | 621 | .hw_is_ready = mei_me_hw_is_ready, |
diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c index 49f197a956c9..4a6f567f4f80 100644 --- a/drivers/misc/mei/hw-txe.c +++ b/drivers/misc/mei/hw-txe.c | |||
@@ -158,7 +158,7 @@ static bool mei_txe_aliveness_set(struct mei_device *dev, u32 req) | |||
158 | dev_dbg(&dev->pdev->dev, "Aliveness current=%d request=%d\n", | 158 | dev_dbg(&dev->pdev->dev, "Aliveness current=%d request=%d\n", |
159 | hw->aliveness, req); | 159 | hw->aliveness, req); |
160 | if (do_req) { | 160 | if (do_req) { |
161 | hw->recvd_aliveness = false; | 161 | dev->pg_event = MEI_PG_EVENT_WAIT; |
162 | mei_txe_br_reg_write(hw, SICR_HOST_ALIVENESS_REQ_REG, req); | 162 | mei_txe_br_reg_write(hw, SICR_HOST_ALIVENESS_REQ_REG, req); |
163 | } | 163 | } |
164 | return do_req; | 164 | return do_req; |
@@ -213,6 +213,7 @@ static int mei_txe_aliveness_poll(struct mei_device *dev, u32 expected) | |||
213 | do { | 213 | do { |
214 | hw->aliveness = mei_txe_aliveness_get(dev); | 214 | hw->aliveness = mei_txe_aliveness_get(dev); |
215 | if (hw->aliveness == expected) { | 215 | if (hw->aliveness == expected) { |
216 | dev->pg_event = MEI_PG_EVENT_IDLE; | ||
216 | dev_dbg(&dev->pdev->dev, | 217 | dev_dbg(&dev->pdev->dev, |
217 | "aliveness settled after %d msecs\n", t); | 218 | "aliveness settled after %d msecs\n", t); |
218 | return t; | 219 | return t; |
@@ -223,6 +224,7 @@ static int mei_txe_aliveness_poll(struct mei_device *dev, u32 expected) | |||
223 | t += MSEC_PER_SEC / 5; | 224 | t += MSEC_PER_SEC / 5; |
224 | } while (t < SEC_ALIVENESS_WAIT_TIMEOUT); | 225 | } while (t < SEC_ALIVENESS_WAIT_TIMEOUT); |
225 | 226 | ||
227 | dev->pg_event = MEI_PG_EVENT_IDLE; | ||
226 | dev_err(&dev->pdev->dev, "aliveness timed out\n"); | 228 | dev_err(&dev->pdev->dev, "aliveness timed out\n"); |
227 | return -ETIME; | 229 | return -ETIME; |
228 | } | 230 | } |
@@ -249,19 +251,22 @@ static int mei_txe_aliveness_wait(struct mei_device *dev, u32 expected) | |||
249 | return 0; | 251 | return 0; |
250 | 252 | ||
251 | mutex_unlock(&dev->device_lock); | 253 | mutex_unlock(&dev->device_lock); |
252 | err = wait_event_timeout(hw->wait_aliveness, | 254 | err = wait_event_timeout(hw->wait_aliveness_resp, |
253 | hw->recvd_aliveness, timeout); | 255 | dev->pg_event == MEI_PG_EVENT_RECEIVED, timeout); |
254 | mutex_lock(&dev->device_lock); | 256 | mutex_lock(&dev->device_lock); |
255 | 257 | ||
256 | hw->aliveness = mei_txe_aliveness_get(dev); | 258 | hw->aliveness = mei_txe_aliveness_get(dev); |
257 | ret = hw->aliveness == expected ? 0 : -ETIME; | 259 | ret = hw->aliveness == expected ? 0 : -ETIME; |
258 | 260 | ||
259 | if (ret) | 261 | if (ret) |
260 | dev_err(&dev->pdev->dev, "aliveness timed out"); | 262 | dev_warn(&dev->pdev->dev, "aliveness timed out = %ld aliveness = %d event = %d\n", |
263 | err, hw->aliveness, dev->pg_event); | ||
261 | else | 264 | else |
262 | dev_dbg(&dev->pdev->dev, "aliveness settled after %d msecs\n", | 265 | dev_dbg(&dev->pdev->dev, "aliveness settled after = %d msec aliveness = %d event = %d\n", |
263 | jiffies_to_msecs(timeout - err)); | 266 | jiffies_to_msecs(timeout - err), |
264 | hw->recvd_aliveness = false; | 267 | hw->aliveness, dev->pg_event); |
268 | |||
269 | dev->pg_event = MEI_PG_EVENT_IDLE; | ||
265 | return ret; | 270 | return ret; |
266 | } | 271 | } |
267 | 272 | ||
@@ -292,6 +297,20 @@ static bool mei_txe_pg_is_enabled(struct mei_device *dev) | |||
292 | } | 297 | } |
293 | 298 | ||
294 | /** | 299 | /** |
300 | * mei_txe_pg_state - translate aliveness register value | ||
301 | * to the mei power gating state | ||
302 | * | ||
303 | * @dev: the device structure | ||
304 | * | ||
305 | * returns: MEI_PG_OFF if aliveness is on and MEI_PG_ON otherwise | ||
306 | */ | ||
307 | static inline enum mei_pg_state mei_txe_pg_state(struct mei_device *dev) | ||
308 | { | ||
309 | struct mei_txe_hw *hw = to_txe_hw(dev); | ||
310 | return hw->aliveness ? MEI_PG_OFF : MEI_PG_ON; | ||
311 | } | ||
312 | |||
313 | /** | ||
295 | * mei_txe_input_ready_interrupt_enable - sets the Input Ready Interrupt | 314 | * mei_txe_input_ready_interrupt_enable - sets the Input Ready Interrupt |
296 | * | 315 | * |
297 | * @dev: the device structure | 316 | * @dev: the device structure |
@@ -972,9 +991,9 @@ irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id) | |||
972 | /* Clear the interrupt cause */ | 991 | /* Clear the interrupt cause */ |
973 | dev_dbg(&dev->pdev->dev, | 992 | dev_dbg(&dev->pdev->dev, |
974 | "Aliveness Interrupt: Status: %d\n", hw->aliveness); | 993 | "Aliveness Interrupt: Status: %d\n", hw->aliveness); |
975 | hw->recvd_aliveness = true; | 994 | dev->pg_event = MEI_PG_EVENT_RECEIVED; |
976 | if (waitqueue_active(&hw->wait_aliveness)) | 995 | if (waitqueue_active(&hw->wait_aliveness_resp)) |
977 | wake_up(&hw->wait_aliveness); | 996 | wake_up(&hw->wait_aliveness_resp); |
978 | } | 997 | } |
979 | 998 | ||
980 | 999 | ||
@@ -1024,6 +1043,8 @@ static const struct mei_hw_ops mei_txe_hw_ops = { | |||
1024 | 1043 | ||
1025 | .host_is_ready = mei_txe_host_is_ready, | 1044 | .host_is_ready = mei_txe_host_is_ready, |
1026 | 1045 | ||
1046 | .pg_state = mei_txe_pg_state, | ||
1047 | |||
1027 | .hw_is_ready = mei_txe_hw_is_ready, | 1048 | .hw_is_ready = mei_txe_hw_is_ready, |
1028 | .hw_reset = mei_txe_hw_reset, | 1049 | .hw_reset = mei_txe_hw_reset, |
1029 | .hw_config = mei_txe_hw_config, | 1050 | .hw_config = mei_txe_hw_config, |
@@ -1069,7 +1090,7 @@ struct mei_device *mei_txe_dev_init(struct pci_dev *pdev) | |||
1069 | 1090 | ||
1070 | hw = to_txe_hw(dev); | 1091 | hw = to_txe_hw(dev); |
1071 | 1092 | ||
1072 | init_waitqueue_head(&hw->wait_aliveness); | 1093 | init_waitqueue_head(&hw->wait_aliveness_resp); |
1073 | 1094 | ||
1074 | dev->ops = &mei_txe_hw_ops; | 1095 | dev->ops = &mei_txe_hw_ops; |
1075 | 1096 | ||
diff --git a/drivers/misc/mei/hw-txe.h b/drivers/misc/mei/hw-txe.h index 0812d98633a4..799f9f25f424 100644 --- a/drivers/misc/mei/hw-txe.h +++ b/drivers/misc/mei/hw-txe.h | |||
@@ -35,12 +35,11 @@ | |||
35 | /** | 35 | /** |
36 | * struct mei_txe_hw - txe hardware specifics | 36 | * struct mei_txe_hw - txe hardware specifics |
37 | * | 37 | * |
38 | * @mem_addr: SeC and BRIDGE bars | 38 | * @mem_addr: SeC and BRIDGE bars |
39 | * @aliveness: aliveness (power gating) state of the hardware | 39 | * @aliveness: aliveness (power gating) state of the hardware |
40 | * @readiness: readiness state of the hardware | 40 | * @readiness: readiness state of the hardware |
41 | * @wait_aliveness: aliveness wait queue | 41 | * @wait_aliveness_resp: aliveness wait queue |
42 | * @recvd_aliveness: aliveness interrupt was recived | 42 | * @intr_cause: translated interrupt cause |
43 | * @intr_cause: translated interrupt cause | ||
44 | */ | 43 | */ |
45 | struct mei_txe_hw { | 44 | struct mei_txe_hw { |
46 | void __iomem *mem_addr[NUM_OF_MEM_BARS]; | 45 | void __iomem *mem_addr[NUM_OF_MEM_BARS]; |
@@ -48,8 +47,7 @@ struct mei_txe_hw { | |||
48 | u32 readiness; | 47 | u32 readiness; |
49 | u32 slots; | 48 | u32 slots; |
50 | 49 | ||
51 | wait_queue_head_t wait_aliveness; | 50 | wait_queue_head_t wait_aliveness_resp; |
52 | bool recvd_aliveness; | ||
53 | 51 | ||
54 | unsigned long intr_cause; | 52 | unsigned long intr_cause; |
55 | }; | 53 | }; |
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index cc604e1d9457..4b1eb37344cb 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c | |||
@@ -341,6 +341,8 @@ void mei_device_init(struct mei_device *dev) | |||
341 | * 0: Reserved for MEI Bus Message communications | 341 | * 0: Reserved for MEI Bus Message communications |
342 | */ | 342 | */ |
343 | bitmap_set(dev->host_clients_map, 0, 1); | 343 | bitmap_set(dev->host_clients_map, 0, 1); |
344 | |||
345 | dev->pg_event = MEI_PG_EVENT_IDLE; | ||
344 | } | 346 | } |
345 | EXPORT_SYMBOL_GPL(mei_device_init); | 347 | EXPORT_SYMBOL_GPL(mei_device_init); |
346 | 348 | ||
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index ca7581ce0722..bec6adef68bd 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h | |||
@@ -220,6 +220,7 @@ struct mei_cl { | |||
220 | * @hw_start - start hw after reset | 220 | * @hw_start - start hw after reset |
221 | * @hw_config - configure hw | 221 | * @hw_config - configure hw |
222 | 222 | ||
223 | * @pg_state - power gating state of the device | ||
223 | * @pg_is_enabled - is power gating enabled | 224 | * @pg_is_enabled - is power gating enabled |
224 | 225 | ||
225 | * @intr_clear - clear pending interrupts | 226 | * @intr_clear - clear pending interrupts |
@@ -246,6 +247,7 @@ struct mei_hw_ops { | |||
246 | int (*hw_start)(struct mei_device *dev); | 247 | int (*hw_start)(struct mei_device *dev); |
247 | void (*hw_config)(struct mei_device *dev); | 248 | void (*hw_config)(struct mei_device *dev); |
248 | 249 | ||
250 | enum mei_pg_state (*pg_state)(struct mei_device *dev); | ||
249 | bool (*pg_is_enabled)(struct mei_device *dev); | 251 | bool (*pg_is_enabled)(struct mei_device *dev); |
250 | 252 | ||
251 | void (*intr_clear)(struct mei_device *dev); | 253 | void (*intr_clear)(struct mei_device *dev); |
@@ -335,11 +337,37 @@ struct mei_cl_device { | |||
335 | void *priv_data; | 337 | void *priv_data; |
336 | }; | 338 | }; |
337 | 339 | ||
340 | |||
341 | /** | ||
342 | * enum mei_pg_event - power gating transition events | ||
343 | * | ||
344 | * @MEI_PG_EVENT_IDLE: the driver is not in power gating transition | ||
345 | * @MEI_PG_EVENT_WAIT: the driver is waiting for a pg event to complete | ||
346 | * @MEI_PG_EVENT_RECEIVED: the driver received pg event | ||
347 | */ | ||
348 | enum mei_pg_event { | ||
349 | MEI_PG_EVENT_IDLE, | ||
350 | MEI_PG_EVENT_WAIT, | ||
351 | MEI_PG_EVENT_RECEIVED, | ||
352 | }; | ||
353 | |||
354 | /** | ||
355 | * enum mei_pg_state - device internal power gating state | ||
356 | * | ||
357 | * @MEI_PG_OFF: device is not power gated - it is active | ||
358 | * @MEI_PG_ON: device is power gated - it is in lower power state | ||
359 | */ | ||
360 | enum mei_pg_state { | ||
361 | MEI_PG_OFF = 0, | ||
362 | MEI_PG_ON = 1, | ||
363 | }; | ||
364 | |||
338 | /** | 365 | /** |
339 | * struct mei_device - MEI private device struct | 366 | * struct mei_device - MEI private device struct |
340 | 367 | ||
341 | * @reset_count - limits the number of consecutive resets | 368 | * @reset_count - limits the number of consecutive resets |
342 | * @hbm_state - state of host bus message protocol | 369 | * @hbm_state - state of host bus message protocol |
370 | * @pg_event - power gating event | ||
343 | * @mem_addr - mem mapped base register address | 371 | * @mem_addr - mem mapped base register address |
344 | 372 | ||
345 | * @hbuf_depth - depth of hardware host/write buffer is slots | 373 | * @hbuf_depth - depth of hardware host/write buffer is slots |
@@ -387,6 +415,11 @@ struct mei_device { | |||
387 | enum mei_hbm_state hbm_state; | 415 | enum mei_hbm_state hbm_state; |
388 | u16 init_clients_timer; | 416 | u16 init_clients_timer; |
389 | 417 | ||
418 | /* | ||
419 | * Power Gating support | ||
420 | */ | ||
421 | enum mei_pg_event pg_event; | ||
422 | |||
390 | unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; /* control messages */ | 423 | unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; /* control messages */ |
391 | u32 rd_msg_hdr; | 424 | u32 rd_msg_hdr; |
392 | 425 | ||
@@ -563,6 +596,11 @@ static inline void mei_hw_config(struct mei_device *dev) | |||
563 | dev->ops->hw_config(dev); | 596 | dev->ops->hw_config(dev); |
564 | } | 597 | } |
565 | 598 | ||
599 | static inline enum mei_pg_state mei_pg_state(struct mei_device *dev) | ||
600 | { | ||
601 | return dev->ops->pg_state(dev); | ||
602 | } | ||
603 | |||
566 | static inline bool mei_pg_is_enabled(struct mei_device *dev) | 604 | static inline bool mei_pg_is_enabled(struct mei_device *dev) |
567 | { | 605 | { |
568 | return dev->ops->pg_is_enabled(dev); | 606 | return dev->ops->pg_is_enabled(dev); |