diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2013-02-06 07:06:41 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-02-06 14:23:47 -0500 |
commit | 827eef51f8dd9a4ab62b4ad270c15472f46938f2 (patch) | |
tree | 15798db67af269512bdb4ae54f36e0a26d178d4a | |
parent | 52c34561415b420301f1580413a9d1891d079494 (diff) |
mei: separate compilation of the ME hardware specifics
We add struct mei_hw_ops to virtualize access to hw specific
configurations. This allows us to separate the compilation
of the ME interface from the ME hardware specifics
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/misc/mei/Kconfig | 17 | ||||
-rw-r--r-- | drivers/misc/mei/Makefile | 6 | ||||
-rw-r--r-- | drivers/misc/mei/amthif.c | 6 | ||||
-rw-r--r-- | drivers/misc/mei/hw-me.c | 87 | ||||
-rw-r--r-- | drivers/misc/mei/hw-me.h | 19 | ||||
-rw-r--r-- | drivers/misc/mei/init.c | 2 | ||||
-rw-r--r-- | drivers/misc/mei/interrupt.c | 10 | ||||
-rw-r--r-- | drivers/misc/mei/main.c | 5 | ||||
-rw-r--r-- | drivers/misc/mei/mei_dev.h | 132 |
9 files changed, 210 insertions, 74 deletions
diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig index 5a79ccde2fdf..fa5c24982c88 100644 --- a/drivers/misc/mei/Kconfig +++ b/drivers/misc/mei/Kconfig | |||
@@ -1,11 +1,22 @@ | |||
1 | config INTEL_MEI | 1 | config INTEL_MEI |
2 | tristate "Intel Management Engine Interface (Intel MEI)" | 2 | tristate "Intel Management Engine Interface" |
3 | depends on X86 && PCI && WATCHDOG_CORE | 3 | depends on X86 && PCI |
4 | help | 4 | help |
5 | The Intel Management Engine (Intel ME) provides Manageability, | 5 | The Intel Management Engine (Intel ME) provides Manageability, |
6 | Security and Media services for system containing Intel chipsets. | 6 | Security and Media services for system containing Intel chipsets. |
7 | if selected /dev/mei misc device will be created. | 7 | if selected /dev/mei misc device will be created. |
8 | 8 | ||
9 | For more information see | ||
10 | <http://software.intel.com/en-us/manageability/> | ||
11 | |||
12 | config INTEL_MEI_ME | ||
13 | bool "ME Enabled Intel Chipsets" | ||
14 | depends on INTEL_MEI | ||
15 | depends on X86 && PCI && WATCHDOG_CORE | ||
16 | default y | ||
17 | help | ||
18 | MEI support for ME Enabled Intel chipsets. | ||
19 | |||
9 | Supported Chipsets are: | 20 | Supported Chipsets are: |
10 | 7 Series Chipset Family | 21 | 7 Series Chipset Family |
11 | 6 Series Chipset Family | 22 | 6 Series Chipset Family |
@@ -24,5 +35,3 @@ config INTEL_MEI | |||
24 | 82Q33 Express | 35 | 82Q33 Express |
25 | 82X38/X48 Express | 36 | 82X38/X48 Express |
26 | 37 | ||
27 | For more information see | ||
28 | <http://software.intel.com/en-us/manageability/> | ||
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile index 068f55354811..040af6c7b147 100644 --- a/drivers/misc/mei/Makefile +++ b/drivers/misc/mei/Makefile | |||
@@ -6,9 +6,9 @@ obj-$(CONFIG_INTEL_MEI) += mei.o | |||
6 | mei-objs := init.o | 6 | mei-objs := init.o |
7 | mei-objs += hbm.o | 7 | mei-objs += hbm.o |
8 | mei-objs += interrupt.o | 8 | mei-objs += interrupt.o |
9 | mei-objs += hw-me.o | 9 | mei-objs += client.o |
10 | mei-objs += main.o | 10 | mei-objs += main.o |
11 | mei-objs += amthif.o | 11 | mei-objs += amthif.o |
12 | mei-objs += wd.o | 12 | mei-objs += wd.o |
13 | mei-objs += client.o | 13 | mei-$(CONFIG_INTEL_MEI_ME) += pci-me.o |
14 | mei-objs += pci-me.o | 14 | mei-$(CONFIG_INTEL_MEI_ME) += hw-me.o |
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 263ed4ccd6f2..a7c483850083 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c | |||
@@ -300,8 +300,8 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb) | |||
300 | if (ret && dev->mei_host_buffer_is_empty) { | 300 | if (ret && dev->mei_host_buffer_is_empty) { |
301 | ret = 0; | 301 | ret = 0; |
302 | dev->mei_host_buffer_is_empty = false; | 302 | dev->mei_host_buffer_is_empty = false; |
303 | if (cb->request_buffer.size > mei_hbuf_max_data(dev)) { | 303 | if (cb->request_buffer.size > mei_hbuf_max_len(dev)) { |
304 | mei_hdr.length = mei_hbuf_max_data(dev); | 304 | mei_hdr.length = mei_hbuf_max_len(dev); |
305 | mei_hdr.msg_complete = 0; | 305 | mei_hdr.msg_complete = 0; |
306 | } else { | 306 | } else { |
307 | mei_hdr.length = cb->request_buffer.size; | 307 | mei_hdr.length = cb->request_buffer.size; |
@@ -583,7 +583,7 @@ int mei_amthif_irq_read(struct mei_device *dev, s32 *slots) | |||
583 | dev->iamthif_msg_buf_index = 0; | 583 | dev->iamthif_msg_buf_index = 0; |
584 | dev->iamthif_msg_buf_size = 0; | 584 | dev->iamthif_msg_buf_size = 0; |
585 | dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER; | 585 | dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER; |
586 | dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev); | 586 | dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev); |
587 | return 0; | 587 | return 0; |
588 | } | 588 | } |
589 | 589 | ||
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 3bdf22848a91..6300943497ae 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c | |||
@@ -56,7 +56,7 @@ static inline void mei_reg_write(const struct mei_me_hw *hw, | |||
56 | * | 56 | * |
57 | * returns ME_CB_RW register value (u32) | 57 | * returns ME_CB_RW register value (u32) |
58 | */ | 58 | */ |
59 | u32 mei_mecbrw_read(const struct mei_device *dev) | 59 | static u32 mei_me_mecbrw_read(const struct mei_device *dev) |
60 | { | 60 | { |
61 | return mei_reg_read(to_me_hw(dev), ME_CB_RW); | 61 | return mei_reg_read(to_me_hw(dev), ME_CB_RW); |
62 | } | 62 | } |
@@ -102,7 +102,7 @@ static inline void mei_hcsr_set(struct mei_me_hw *hw, u32 hcsr) | |||
102 | * | 102 | * |
103 | * @dev: mei device | 103 | * @dev: mei device |
104 | */ | 104 | */ |
105 | void mei_hw_config(struct mei_device *dev) | 105 | static void mei_me_hw_config(struct mei_device *dev) |
106 | { | 106 | { |
107 | u32 hcsr = mei_hcsr_read(to_me_hw(dev)); | 107 | u32 hcsr = mei_hcsr_read(to_me_hw(dev)); |
108 | /* Doesn't change in runtime */ | 108 | /* Doesn't change in runtime */ |
@@ -113,20 +113,19 @@ void mei_hw_config(struct mei_device *dev) | |||
113 | * | 113 | * |
114 | * @dev: the device structure | 114 | * @dev: the device structure |
115 | */ | 115 | */ |
116 | void mei_clear_interrupts(struct mei_device *dev) | 116 | static void mei_me_intr_clear(struct mei_device *dev) |
117 | { | 117 | { |
118 | struct mei_me_hw *hw = to_me_hw(dev); | 118 | struct mei_me_hw *hw = to_me_hw(dev); |
119 | u32 hcsr = mei_hcsr_read(hw); | 119 | u32 hcsr = mei_hcsr_read(hw); |
120 | if ((hcsr & H_IS) == H_IS) | 120 | if ((hcsr & H_IS) == H_IS) |
121 | mei_reg_write(hw, H_CSR, hcsr); | 121 | mei_reg_write(hw, H_CSR, hcsr); |
122 | } | 122 | } |
123 | |||
124 | /** | 123 | /** |
125 | * mei_enable_interrupts - enables mei device interrupts | 124 | * mei_me_intr_enable - enables mei device interrupts |
126 | * | 125 | * |
127 | * @dev: the device structure | 126 | * @dev: the device structure |
128 | */ | 127 | */ |
129 | void mei_enable_interrupts(struct mei_device *dev) | 128 | static void mei_me_intr_enable(struct mei_device *dev) |
130 | { | 129 | { |
131 | struct mei_me_hw *hw = to_me_hw(dev); | 130 | struct mei_me_hw *hw = to_me_hw(dev); |
132 | u32 hcsr = mei_hcsr_read(hw); | 131 | u32 hcsr = mei_hcsr_read(hw); |
@@ -139,7 +138,7 @@ void mei_enable_interrupts(struct mei_device *dev) | |||
139 | * | 138 | * |
140 | * @dev: the device structure | 139 | * @dev: the device structure |
141 | */ | 140 | */ |
142 | void mei_disable_interrupts(struct mei_device *dev) | 141 | static void mei_me_intr_disable(struct mei_device *dev) |
143 | { | 142 | { |
144 | struct mei_me_hw *hw = to_me_hw(dev); | 143 | struct mei_me_hw *hw = to_me_hw(dev); |
145 | u32 hcsr = mei_hcsr_read(hw); | 144 | u32 hcsr = mei_hcsr_read(hw); |
@@ -148,12 +147,12 @@ void mei_disable_interrupts(struct mei_device *dev) | |||
148 | } | 147 | } |
149 | 148 | ||
150 | /** | 149 | /** |
151 | * mei_hw_reset - resets fw via mei csr register. | 150 | * mei_me_hw_reset - resets fw via mei csr register. |
152 | * | 151 | * |
153 | * @dev: the device structure | 152 | * @dev: the device structure |
154 | * @interrupts_enabled: if interrupt should be enabled after reset. | 153 | * @interrupts_enabled: if interrupt should be enabled after reset. |
155 | */ | 154 | */ |
156 | void mei_hw_reset(struct mei_device *dev, bool intr_enable) | 155 | static void mei_me_hw_reset(struct mei_device *dev, bool intr_enable) |
157 | { | 156 | { |
158 | struct mei_me_hw *hw = to_me_hw(dev); | 157 | struct mei_me_hw *hw = to_me_hw(dev); |
159 | u32 hcsr = mei_hcsr_read(hw); | 158 | u32 hcsr = mei_hcsr_read(hw); |
@@ -180,25 +179,25 @@ void mei_hw_reset(struct mei_device *dev, bool intr_enable) | |||
180 | } | 179 | } |
181 | 180 | ||
182 | /** | 181 | /** |
183 | * mei_host_set_ready - enable device | 182 | * mei_me_host_set_ready - enable device |
184 | * | 183 | * |
185 | * @dev - mei device | 184 | * @dev - mei device |
186 | * returns bool | 185 | * returns bool |
187 | */ | 186 | */ |
188 | 187 | ||
189 | void mei_host_set_ready(struct mei_device *dev) | 188 | static void mei_me_host_set_ready(struct mei_device *dev) |
190 | { | 189 | { |
191 | struct mei_me_hw *hw = to_me_hw(dev); | 190 | struct mei_me_hw *hw = to_me_hw(dev); |
192 | hw->host_hw_state |= H_IE | H_IG | H_RDY; | 191 | hw->host_hw_state |= H_IE | H_IG | H_RDY; |
193 | mei_hcsr_set(hw, hw->host_hw_state); | 192 | mei_hcsr_set(hw, hw->host_hw_state); |
194 | } | 193 | } |
195 | /** | 194 | /** |
196 | * mei_host_is_ready - check whether the host has turned ready | 195 | * mei_me_host_is_ready - check whether the host has turned ready |
197 | * | 196 | * |
198 | * @dev - mei device | 197 | * @dev - mei device |
199 | * returns bool | 198 | * returns bool |
200 | */ | 199 | */ |
201 | bool mei_host_is_ready(struct mei_device *dev) | 200 | static bool mei_me_host_is_ready(struct mei_device *dev) |
202 | { | 201 | { |
203 | struct mei_me_hw *hw = to_me_hw(dev); | 202 | struct mei_me_hw *hw = to_me_hw(dev); |
204 | hw->host_hw_state = mei_hcsr_read(hw); | 203 | hw->host_hw_state = mei_hcsr_read(hw); |
@@ -206,12 +205,12 @@ bool mei_host_is_ready(struct mei_device *dev) | |||
206 | } | 205 | } |
207 | 206 | ||
208 | /** | 207 | /** |
209 | * mei_me_is_ready - check whether the me has turned ready | 208 | * mei_me_hw_is_ready - check whether the me(hw) has turned ready |
210 | * | 209 | * |
211 | * @dev - mei device | 210 | * @dev - mei device |
212 | * returns bool | 211 | * returns bool |
213 | */ | 212 | */ |
214 | bool mei_me_is_ready(struct mei_device *dev) | 213 | static bool mei_me_hw_is_ready(struct mei_device *dev) |
215 | { | 214 | { |
216 | struct mei_me_hw *hw = to_me_hw(dev); | 215 | struct mei_me_hw *hw = to_me_hw(dev); |
217 | hw->me_hw_state = mei_mecsr_read(hw); | 216 | hw->me_hw_state = mei_mecsr_read(hw); |
@@ -268,19 +267,19 @@ static unsigned char mei_hbuf_filled_slots(struct mei_device *dev) | |||
268 | * | 267 | * |
269 | * returns true if empty, false - otherwise. | 268 | * returns true if empty, false - otherwise. |
270 | */ | 269 | */ |
271 | bool mei_hbuf_is_empty(struct mei_device *dev) | 270 | static bool mei_me_hbuf_is_empty(struct mei_device *dev) |
272 | { | 271 | { |
273 | return mei_hbuf_filled_slots(dev) == 0; | 272 | return mei_hbuf_filled_slots(dev) == 0; |
274 | } | 273 | } |
275 | 274 | ||
276 | /** | 275 | /** |
277 | * mei_hbuf_empty_slots - counts write empty slots. | 276 | * mei_me_hbuf_empty_slots - counts write empty slots. |
278 | * | 277 | * |
279 | * @dev: the device structure | 278 | * @dev: the device structure |
280 | * | 279 | * |
281 | * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count | 280 | * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count |
282 | */ | 281 | */ |
283 | int mei_hbuf_empty_slots(struct mei_device *dev) | 282 | static int mei_me_hbuf_empty_slots(struct mei_device *dev) |
284 | { | 283 | { |
285 | unsigned char filled_slots, empty_slots; | 284 | unsigned char filled_slots, empty_slots; |
286 | 285 | ||
@@ -294,6 +293,12 @@ int mei_hbuf_empty_slots(struct mei_device *dev) | |||
294 | return empty_slots; | 293 | return empty_slots; |
295 | } | 294 | } |
296 | 295 | ||
296 | static size_t mei_me_hbuf_max_len(const struct mei_device *dev) | ||
297 | { | ||
298 | return dev->hbuf_depth * sizeof(u32) - sizeof(struct mei_msg_hdr); | ||
299 | } | ||
300 | |||
301 | |||
297 | /** | 302 | /** |
298 | * mei_write_message - writes a message to mei device. | 303 | * mei_write_message - writes a message to mei device. |
299 | * | 304 | * |
@@ -303,8 +308,9 @@ int mei_hbuf_empty_slots(struct mei_device *dev) | |||
303 | * | 308 | * |
304 | * This function returns -EIO if write has failed | 309 | * This function returns -EIO if write has failed |
305 | */ | 310 | */ |
306 | int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header, | 311 | static int mei_me_write_message(struct mei_device *dev, |
307 | unsigned char *buf) | 312 | struct mei_msg_hdr *header, |
313 | unsigned char *buf) | ||
308 | { | 314 | { |
309 | struct mei_me_hw *hw = to_me_hw(dev); | 315 | struct mei_me_hw *hw = to_me_hw(dev); |
310 | unsigned long rem, dw_cnt; | 316 | unsigned long rem, dw_cnt; |
@@ -337,20 +343,20 @@ int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header, | |||
337 | 343 | ||
338 | hcsr = mei_hcsr_read(hw) | H_IG; | 344 | hcsr = mei_hcsr_read(hw) | H_IG; |
339 | mei_hcsr_set(hw, hcsr); | 345 | mei_hcsr_set(hw, hcsr); |
340 | if (!mei_me_is_ready(dev)) | 346 | if (!mei_me_hw_is_ready(dev)) |
341 | return -EIO; | 347 | return -EIO; |
342 | 348 | ||
343 | return 0; | 349 | return 0; |
344 | } | 350 | } |
345 | 351 | ||
346 | /** | 352 | /** |
347 | * mei_count_full_read_slots - counts read full slots. | 353 | * mei_me_count_full_read_slots - counts read full slots. |
348 | * | 354 | * |
349 | * @dev: the device structure | 355 | * @dev: the device structure |
350 | * | 356 | * |
351 | * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise filled slots count | 357 | * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise filled slots count |
352 | */ | 358 | */ |
353 | int mei_count_full_read_slots(struct mei_device *dev) | 359 | static int mei_me_count_full_read_slots(struct mei_device *dev) |
354 | { | 360 | { |
355 | struct mei_me_hw *hw = to_me_hw(dev); | 361 | struct mei_me_hw *hw = to_me_hw(dev); |
356 | char read_ptr, write_ptr; | 362 | char read_ptr, write_ptr; |
@@ -371,13 +377,13 @@ int mei_count_full_read_slots(struct mei_device *dev) | |||
371 | } | 377 | } |
372 | 378 | ||
373 | /** | 379 | /** |
374 | * mei_read_slots - reads a message from mei device. | 380 | * mei_me_read_slots - reads a message from mei device. |
375 | * | 381 | * |
376 | * @dev: the device structure | 382 | * @dev: the device structure |
377 | * @buffer: message buffer will be written | 383 | * @buffer: message buffer will be written |
378 | * @buffer_length: message size will be read | 384 | * @buffer_length: message size will be read |
379 | */ | 385 | */ |
380 | void mei_read_slots(struct mei_device *dev, unsigned char *buffer, | 386 | static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer, |
381 | unsigned long buffer_length) | 387 | unsigned long buffer_length) |
382 | { | 388 | { |
383 | struct mei_me_hw *hw = to_me_hw(dev); | 389 | struct mei_me_hw *hw = to_me_hw(dev); |
@@ -385,17 +391,42 @@ void mei_read_slots(struct mei_device *dev, unsigned char *buffer, | |||
385 | u32 hcsr; | 391 | u32 hcsr; |
386 | 392 | ||
387 | for (; buffer_length >= sizeof(u32); buffer_length -= sizeof(u32)) | 393 | for (; buffer_length >= sizeof(u32); buffer_length -= sizeof(u32)) |
388 | *reg_buf++ = mei_mecbrw_read(dev); | 394 | *reg_buf++ = mei_me_mecbrw_read(dev); |
389 | 395 | ||
390 | if (buffer_length > 0) { | 396 | if (buffer_length > 0) { |
391 | u32 reg = mei_mecbrw_read(dev); | 397 | u32 reg = mei_me_mecbrw_read(dev); |
392 | memcpy(reg_buf, ®, buffer_length); | 398 | memcpy(reg_buf, ®, buffer_length); |
393 | } | 399 | } |
394 | 400 | ||
395 | hcsr = mei_hcsr_read(hw) | H_IG; | 401 | hcsr = mei_hcsr_read(hw) | H_IG; |
396 | mei_hcsr_set(hw, hcsr); | 402 | mei_hcsr_set(hw, hcsr); |
403 | return 0; | ||
397 | } | 404 | } |
398 | 405 | ||
406 | static const struct mei_hw_ops mei_me_hw_ops = { | ||
407 | |||
408 | .host_set_ready = mei_me_host_set_ready, | ||
409 | .host_is_ready = mei_me_host_is_ready, | ||
410 | |||
411 | .hw_is_ready = mei_me_hw_is_ready, | ||
412 | .hw_reset = mei_me_hw_reset, | ||
413 | .hw_config = mei_me_hw_config, | ||
414 | |||
415 | .intr_clear = mei_me_intr_clear, | ||
416 | .intr_enable = mei_me_intr_enable, | ||
417 | .intr_disable = mei_me_intr_disable, | ||
418 | |||
419 | .hbuf_free_slots = mei_me_hbuf_empty_slots, | ||
420 | .hbuf_is_ready = mei_me_hbuf_is_empty, | ||
421 | .hbuf_max_len = mei_me_hbuf_max_len, | ||
422 | |||
423 | .write = mei_me_write_message, | ||
424 | |||
425 | .rdbuf_full_slots = mei_me_count_full_read_slots, | ||
426 | .read_hdr = mei_me_mecbrw_read, | ||
427 | .read = mei_me_read_slots | ||
428 | }; | ||
429 | |||
399 | /** | 430 | /** |
400 | * init_mei_device - allocates and initializes the mei device structure | 431 | * init_mei_device - allocates and initializes the mei device structure |
401 | * | 432 | * |
@@ -422,6 +453,8 @@ struct mei_device *mei_me_dev_init(struct pci_dev *pdev) | |||
422 | INIT_DELAYED_WORK(&dev->timer_work, mei_timer); | 453 | INIT_DELAYED_WORK(&dev->timer_work, mei_timer); |
423 | INIT_WORK(&dev->init_work, mei_host_client_init); | 454 | INIT_WORK(&dev->init_work, mei_host_client_init); |
424 | 455 | ||
456 | dev->ops = &mei_me_hw_ops; | ||
457 | |||
425 | dev->pdev = pdev; | 458 | dev->pdev = pdev; |
426 | return dev; | 459 | return dev; |
427 | } | 460 | } |
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h index 53bcc0087e26..9a3aaab9bcf0 100644 --- a/drivers/misc/mei/hw-me.h +++ b/drivers/misc/mei/hw-me.h | |||
@@ -36,29 +36,10 @@ struct mei_me_hw { | |||
36 | 36 | ||
37 | struct mei_device *mei_me_dev_init(struct pci_dev *pdev); | 37 | struct mei_device *mei_me_dev_init(struct pci_dev *pdev); |
38 | 38 | ||
39 | void mei_read_slots(struct mei_device *dev, | ||
40 | unsigned char *buffer, | ||
41 | unsigned long buffer_length); | ||
42 | |||
43 | int mei_write_message(struct mei_device *dev, | ||
44 | struct mei_msg_hdr *header, | ||
45 | unsigned char *buf); | ||
46 | |||
47 | bool mei_hbuf_is_empty(struct mei_device *dev); | ||
48 | |||
49 | int mei_hbuf_empty_slots(struct mei_device *dev); | ||
50 | |||
51 | static inline size_t mei_hbuf_max_data(const struct mei_device *dev) | ||
52 | { | ||
53 | return dev->hbuf_depth * sizeof(u32) - sizeof(struct mei_msg_hdr); | ||
54 | } | ||
55 | |||
56 | /* get slots (dwords) from a message length + header (bytes) */ | 39 | /* get slots (dwords) from a message length + header (bytes) */ |
57 | static inline unsigned char mei_data2slots(size_t length) | 40 | static inline unsigned char mei_data2slots(size_t length) |
58 | { | 41 | { |
59 | return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4); | 42 | return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4); |
60 | } | 43 | } |
61 | 44 | ||
62 | int mei_count_full_read_slots(struct mei_device *dev); | ||
63 | |||
64 | #endif /* _MEI_INTERFACE_H_ */ | 45 | #endif /* _MEI_INTERFACE_H_ */ |
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 1e1876ff25b1..51a005e80952 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c | |||
@@ -104,7 +104,7 @@ int mei_hw_init(struct mei_device *dev) | |||
104 | goto err; | 104 | goto err; |
105 | } | 105 | } |
106 | 106 | ||
107 | if (!mei_me_is_ready(dev)) { | 107 | if (!mei_hw_is_ready(dev)) { |
108 | dev_err(&dev->pdev->dev, "ME is not ready.\n"); | 108 | dev_err(&dev->pdev->dev, "ME is not ready.\n"); |
109 | goto err; | 109 | goto err; |
110 | } | 110 | } |
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index b04ed9bdf758..431aa91fd002 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c | |||
@@ -329,7 +329,7 @@ static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list, | |||
329 | int ret = 0; | 329 | int ret = 0; |
330 | 330 | ||
331 | if (!dev->rd_msg_hdr) { | 331 | if (!dev->rd_msg_hdr) { |
332 | dev->rd_msg_hdr = mei_mecbrw_read(dev); | 332 | dev->rd_msg_hdr = mei_read_hdr(dev); |
333 | dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); | 333 | dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); |
334 | (*slots)--; | 334 | (*slots)--; |
335 | dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); | 335 | dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); |
@@ -430,7 +430,7 @@ static int mei_irq_thread_write_handler(struct mei_device *dev, | |||
430 | s32 slots; | 430 | s32 slots; |
431 | int ret; | 431 | int ret; |
432 | 432 | ||
433 | if (!mei_hbuf_is_empty(dev)) { | 433 | if (!mei_hbuf_is_ready(dev)) { |
434 | dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n"); | 434 | dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n"); |
435 | return 0; | 435 | return 0; |
436 | } | 436 | } |
@@ -698,7 +698,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) | |||
698 | mei_clear_interrupts(dev); | 698 | mei_clear_interrupts(dev); |
699 | 699 | ||
700 | /* check if ME wants a reset */ | 700 | /* check if ME wants a reset */ |
701 | if (!mei_me_is_ready(dev) && | 701 | if (!mei_hw_is_ready(dev) && |
702 | dev->dev_state != MEI_DEV_RESETING && | 702 | dev->dev_state != MEI_DEV_RESETING && |
703 | dev->dev_state != MEI_DEV_INITIALIZING) { | 703 | dev->dev_state != MEI_DEV_INITIALIZING) { |
704 | dev_dbg(&dev->pdev->dev, "FW not ready.\n"); | 704 | dev_dbg(&dev->pdev->dev, "FW not ready.\n"); |
@@ -709,7 +709,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) | |||
709 | 709 | ||
710 | /* check if we need to start the dev */ | 710 | /* check if we need to start the dev */ |
711 | if (!mei_host_is_ready(dev)) { | 711 | if (!mei_host_is_ready(dev)) { |
712 | if (mei_me_is_ready(dev)) { | 712 | if (mei_hw_is_ready(dev)) { |
713 | dev_dbg(&dev->pdev->dev, "we need to start the dev.\n"); | 713 | dev_dbg(&dev->pdev->dev, "we need to start the dev.\n"); |
714 | 714 | ||
715 | mei_host_set_ready(dev); | 715 | mei_host_set_ready(dev); |
@@ -743,7 +743,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) | |||
743 | rets = mei_irq_thread_write_handler(dev, &complete_list); | 743 | rets = mei_irq_thread_write_handler(dev, &complete_list); |
744 | end: | 744 | end: |
745 | dev_dbg(&dev->pdev->dev, "end of bottom half function.\n"); | 745 | dev_dbg(&dev->pdev->dev, "end of bottom half function.\n"); |
746 | dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev); | 746 | dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev); |
747 | 747 | ||
748 | bus_message_received = false; | 748 | bus_message_received = false; |
749 | if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) { | 749 | if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) { |
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 018623c9a8e1..843ae2febc70 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c | |||
@@ -462,8 +462,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, | |||
462 | } | 462 | } |
463 | 463 | ||
464 | dev->mei_host_buffer_is_empty = false; | 464 | dev->mei_host_buffer_is_empty = false; |
465 | if (length > mei_hbuf_max_data(dev)) { | 465 | if (length > mei_hbuf_max_len(dev)) { |
466 | mei_hdr.length = mei_hbuf_max_data(dev); | 466 | mei_hdr.length = mei_hbuf_max_len(dev); |
467 | mei_hdr.msg_complete = 0; | 467 | mei_hdr.msg_complete = 0; |
468 | } else { | 468 | } else { |
469 | mei_hdr.length = length; | 469 | mei_hdr.length = length; |
@@ -765,4 +765,5 @@ void mei_deregister(void) | |||
765 | mei_misc_device.parent = NULL; | 765 | mei_misc_device.parent = NULL; |
766 | } | 766 | } |
767 | 767 | ||
768 | MODULE_LICENSE("GPL v2"); | ||
768 | 769 | ||
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index bb759fd9ee4a..c974292f16d6 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h | |||
@@ -211,6 +211,58 @@ struct mei_cl { | |||
211 | struct mei_cl_cb *read_cb; | 211 | struct mei_cl_cb *read_cb; |
212 | }; | 212 | }; |
213 | 213 | ||
214 | /** struct mei_hw_ops | ||
215 | * | ||
216 | * @host_set_ready - notify FW that host side is ready | ||
217 | * @host_is_ready - query for host readiness | ||
218 | |||
219 | * @hw_is_ready - query if hw is ready | ||
220 | * @hw_reset - reset hw | ||
221 | * @hw_config - configure hw | ||
222 | |||
223 | * @intr_clear - clear pending interrupts | ||
224 | * @intr_enable - enable interrupts | ||
225 | * @intr_disable - disable interrupts | ||
226 | |||
227 | * @hbuf_free_slots - query for write buffer empty slots | ||
228 | * @hbuf_is_ready - query if write buffer is empty | ||
229 | * @hbuf_max_len - query for write buffer max len | ||
230 | |||
231 | * @write - write a message to FW | ||
232 | |||
233 | * @rdbuf_full_slots - query how many slots are filled | ||
234 | |||
235 | * @read_hdr - get first 4 bytes (header) | ||
236 | * @read - read a buffer from the FW | ||
237 | */ | ||
238 | struct mei_hw_ops { | ||
239 | |||
240 | void (*host_set_ready) (struct mei_device *dev); | ||
241 | bool (*host_is_ready) (struct mei_device *dev); | ||
242 | |||
243 | bool (*hw_is_ready) (struct mei_device *dev); | ||
244 | void (*hw_reset) (struct mei_device *dev, bool enable); | ||
245 | void (*hw_config) (struct mei_device *dev); | ||
246 | |||
247 | void (*intr_clear) (struct mei_device *dev); | ||
248 | void (*intr_enable) (struct mei_device *dev); | ||
249 | void (*intr_disable) (struct mei_device *dev); | ||
250 | |||
251 | int (*hbuf_free_slots) (struct mei_device *dev); | ||
252 | bool (*hbuf_is_ready) (struct mei_device *dev); | ||
253 | size_t (*hbuf_max_len) (const struct mei_device *dev); | ||
254 | |||
255 | int (*write)(struct mei_device *dev, | ||
256 | struct mei_msg_hdr *hdr, | ||
257 | unsigned char *buf); | ||
258 | |||
259 | int (*rdbuf_full_slots)(struct mei_device *dev); | ||
260 | |||
261 | u32 (*read_hdr)(const struct mei_device *dev); | ||
262 | int (*read) (struct mei_device *dev, | ||
263 | unsigned char *buf, unsigned long len); | ||
264 | }; | ||
265 | |||
214 | /** | 266 | /** |
215 | * struct mei_device - MEI private device struct | 267 | * struct mei_device - MEI private device struct |
216 | * @mem_addr - mem mapped base register address | 268 | * @mem_addr - mem mapped base register address |
@@ -306,6 +358,8 @@ struct mei_device { | |||
306 | bool iamthif_canceled; | 358 | bool iamthif_canceled; |
307 | 359 | ||
308 | struct work_struct init_work; | 360 | struct work_struct init_work; |
361 | |||
362 | const struct mei_hw_ops *ops; | ||
309 | char hw[0] __aligned(sizeof(void *)); | 363 | char hw[0] __aligned(sizeof(void *)); |
310 | }; | 364 | }; |
311 | 365 | ||
@@ -376,26 +430,84 @@ void mei_watchdog_register(struct mei_device *dev); | |||
376 | */ | 430 | */ |
377 | void mei_watchdog_unregister(struct mei_device *dev); | 431 | void mei_watchdog_unregister(struct mei_device *dev); |
378 | 432 | ||
379 | |||
380 | /* | 433 | /* |
381 | * Register Access Function | 434 | * Register Access Function |
382 | */ | 435 | */ |
383 | 436 | ||
384 | void mei_hw_config(struct mei_device *dev); | 437 | static inline void mei_hw_config(struct mei_device *dev) |
385 | void mei_hw_reset(struct mei_device *dev, bool intr_enable); | 438 | { |
386 | u32 mei_mecbrw_read(const struct mei_device *dev); | 439 | dev->ops->hw_config(dev); |
440 | } | ||
441 | static inline void mei_hw_reset(struct mei_device *dev, bool enable) | ||
442 | { | ||
443 | dev->ops->hw_reset(dev, enable); | ||
444 | } | ||
445 | |||
446 | static inline void mei_clear_interrupts(struct mei_device *dev) | ||
447 | { | ||
448 | dev->ops->intr_clear(dev); | ||
449 | } | ||
450 | |||
451 | static inline void mei_enable_interrupts(struct mei_device *dev) | ||
452 | { | ||
453 | dev->ops->intr_enable(dev); | ||
454 | } | ||
387 | 455 | ||
456 | static inline void mei_disable_interrupts(struct mei_device *dev) | ||
457 | { | ||
458 | dev->ops->intr_disable(dev); | ||
459 | } | ||
388 | 460 | ||
461 | static inline void mei_host_set_ready(struct mei_device *dev) | ||
462 | { | ||
463 | dev->ops->host_set_ready(dev); | ||
464 | } | ||
465 | static inline bool mei_host_is_ready(struct mei_device *dev) | ||
466 | { | ||
467 | return dev->ops->host_is_ready(dev); | ||
468 | } | ||
469 | static inline bool mei_hw_is_ready(struct mei_device *dev) | ||
470 | { | ||
471 | return dev->ops->hw_is_ready(dev); | ||
472 | } | ||
389 | 473 | ||
390 | void mei_clear_interrupts(struct mei_device *dev); | 474 | static inline bool mei_hbuf_is_ready(struct mei_device *dev) |
391 | void mei_enable_interrupts(struct mei_device *dev); | 475 | { |
392 | void mei_disable_interrupts(struct mei_device *dev); | 476 | return dev->ops->hbuf_is_ready(dev); |
477 | } | ||
393 | 478 | ||
394 | void mei_host_set_ready(struct mei_device *dev); | 479 | static inline int mei_hbuf_empty_slots(struct mei_device *dev) |
395 | bool mei_host_is_ready(struct mei_device *dev); | 480 | { |
396 | bool mei_me_is_ready(struct mei_device *dev); | 481 | return dev->ops->hbuf_free_slots(dev); |
482 | } | ||
397 | 483 | ||
484 | static inline size_t mei_hbuf_max_len(const struct mei_device *dev) | ||
485 | { | ||
486 | return dev->ops->hbuf_max_len(dev); | ||
487 | } | ||
398 | 488 | ||
489 | static inline int mei_write_message(struct mei_device *dev, | ||
490 | struct mei_msg_hdr *hdr, | ||
491 | unsigned char *buf) | ||
492 | { | ||
493 | return dev->ops->write(dev, hdr, buf); | ||
494 | } | ||
495 | |||
496 | static inline u32 mei_read_hdr(const struct mei_device *dev) | ||
497 | { | ||
498 | return dev->ops->read_hdr(dev); | ||
499 | } | ||
500 | |||
501 | static inline void mei_read_slots(struct mei_device *dev, | ||
502 | unsigned char *buf, unsigned long len) | ||
503 | { | ||
504 | dev->ops->read(dev, buf, len); | ||
505 | } | ||
506 | |||
507 | static inline int mei_count_full_read_slots(struct mei_device *dev) | ||
508 | { | ||
509 | return dev->ops->rdbuf_full_slots(dev); | ||
510 | } | ||
399 | 511 | ||
400 | int mei_register(struct device *dev); | 512 | int mei_register(struct device *dev); |
401 | void mei_deregister(void); | 513 | void mei_deregister(void); |