From 9dc64d6a26b016df52d222abe9279a92d9f7cc4c Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 8 Jan 2013 23:07:17 +0200 Subject: mei: rename interface to hw-me Rename hw-me.h to hw-me-regs.h as this file contains only register definitions. Files hw-me.[ch] now contains ME hw dependant functionality Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.c | 299 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 drivers/misc/mei/hw-me.c (limited to 'drivers/misc/mei/hw-me.c') diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c new file mode 100644 index 000000000000..4e6b657cd806 --- /dev/null +++ b/drivers/misc/mei/hw-me.c @@ -0,0 +1,299 @@ +/* + * + * Intel Management Engine Interface (Intel MEI) Linux driver + * Copyright (c) 2003-2012, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include + +#include "mei_dev.h" +#include "hw-me.h" + +/** + * mei_reg_read - Reads 32bit data from the mei device + * + * @dev: the device structure + * @offset: offset from which to read the data + * + * returns register value (u32) + */ +static inline u32 mei_reg_read(const struct mei_device *dev, + unsigned long offset) +{ + return ioread32(dev->mem_addr + offset); +} + + +/** + * mei_reg_write - Writes 32bit data to the mei device + * + * @dev: the device structure + * @offset: offset from which to write the data + * @value: register value to write (u32) + */ +static inline void mei_reg_write(const struct mei_device *dev, + unsigned long offset, u32 value) +{ + iowrite32(value, dev->mem_addr + offset); +} + +/** + * mei_hcsr_read - Reads 32bit data from the host CSR + * + * @dev: the device structure + * + * returns the byte read. + */ +u32 mei_hcsr_read(const struct mei_device *dev) +{ + return mei_reg_read(dev, H_CSR); +} + +u32 mei_mecbrw_read(const struct mei_device *dev) +{ + return mei_reg_read(dev, ME_CB_RW); +} +/** + * mei_mecsr_read - Reads 32bit data from the ME CSR + * + * @dev: the device structure + * + * returns ME_CSR_HA register value (u32) + */ +u32 mei_mecsr_read(const struct mei_device *dev) +{ + return mei_reg_read(dev, ME_CSR_HA); +} + +/** + * mei_set_csr_register - writes H_CSR register to the mei device, + * and ignores the H_IS bit for it is write-one-to-zero. + * + * @dev: the device structure + */ +void mei_hcsr_set(struct mei_device *dev) +{ + if ((dev->host_hw_state & H_IS) == H_IS) + dev->host_hw_state &= ~H_IS; + mei_reg_write(dev, H_CSR, dev->host_hw_state); + dev->host_hw_state = mei_hcsr_read(dev); +} + +/** + * mei_enable_interrupts - clear and stop interrupts + * + * @dev: the device structure + */ +void mei_clear_interrupts(struct mei_device *dev) +{ + if ((dev->host_hw_state & H_IS) == H_IS) + mei_reg_write(dev, H_CSR, dev->host_hw_state); +} + +/** + * mei_enable_interrupts - enables mei device interrupts + * + * @dev: the device structure + */ +void mei_enable_interrupts(struct mei_device *dev) +{ + dev->host_hw_state |= H_IE; + mei_hcsr_set(dev); +} + +/** + * mei_disable_interrupts - disables mei device interrupts + * + * @dev: the device structure + */ +void mei_disable_interrupts(struct mei_device *dev) +{ + dev->host_hw_state &= ~H_IE; + mei_hcsr_set(dev); +} + + +/** + * mei_interrupt_quick_handler - The ISR of the MEI device + * + * @irq: The irq number + * @dev_id: pointer to the device structure + * + * returns irqreturn_t + */ +irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id) +{ + struct mei_device *dev = (struct mei_device *) dev_id; + u32 csr_reg = mei_hcsr_read(dev); + + if ((csr_reg & H_IS) != H_IS) + return IRQ_NONE; + + /* clear H_IS bit in H_CSR */ + mei_reg_write(dev, H_CSR, csr_reg); + + return IRQ_WAKE_THREAD; +} + +/** + * mei_hbuf_filled_slots - gets number of device filled buffer slots + * + * @device: the device structure + * + * returns number of filled slots + */ +static unsigned char mei_hbuf_filled_slots(struct mei_device *dev) +{ + char read_ptr, write_ptr; + + dev->host_hw_state = mei_hcsr_read(dev); + + read_ptr = (char) ((dev->host_hw_state & H_CBRP) >> 8); + write_ptr = (char) ((dev->host_hw_state & H_CBWP) >> 16); + + return (unsigned char) (write_ptr - read_ptr); +} + +/** + * mei_hbuf_is_empty - checks if host buffer is empty. + * + * @dev: the device structure + * + * returns true if empty, false - otherwise. + */ +bool mei_hbuf_is_empty(struct mei_device *dev) +{ + return mei_hbuf_filled_slots(dev) == 0; +} + +/** + * mei_hbuf_empty_slots - counts write empty slots. + * + * @dev: the device structure + * + * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count + */ +int mei_hbuf_empty_slots(struct mei_device *dev) +{ + unsigned char filled_slots, empty_slots; + + filled_slots = mei_hbuf_filled_slots(dev); + empty_slots = dev->hbuf_depth - filled_slots; + + /* check for overflow */ + if (filled_slots > dev->hbuf_depth) + return -EOVERFLOW; + + return empty_slots; +} + +/** + * mei_write_message - writes a message to mei device. + * + * @dev: the device structure + * @hader: mei HECI header of message + * @buf: message payload will be written + * + * This function returns -EIO if write has failed + */ +int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header, + unsigned char *buf) +{ + unsigned long rem, dw_cnt; + unsigned long length = header->length; + u32 *reg_buf = (u32 *)buf; + int i; + int empty_slots; + + dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(header)); + + empty_slots = mei_hbuf_empty_slots(dev); + dev_dbg(&dev->pdev->dev, "empty slots = %hu.\n", empty_slots); + + dw_cnt = mei_data2slots(length); + if (empty_slots < 0 || dw_cnt > empty_slots) + return -EIO; + + mei_reg_write(dev, H_CB_WW, *((u32 *) header)); + + for (i = 0; i < length / 4; i++) + mei_reg_write(dev, H_CB_WW, reg_buf[i]); + + rem = length & 0x3; + if (rem > 0) { + u32 reg = 0; + memcpy(®, &buf[length - rem], rem); + mei_reg_write(dev, H_CB_WW, reg); + } + + dev->host_hw_state = mei_hcsr_read(dev); + dev->host_hw_state |= H_IG; + mei_hcsr_set(dev); + dev->me_hw_state = mei_mecsr_read(dev); + if ((dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA) + return -EIO; + + return 0; +} + +/** + * mei_count_full_read_slots - counts read full slots. + * + * @dev: the device structure + * + * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise filled slots count + */ +int mei_count_full_read_slots(struct mei_device *dev) +{ + char read_ptr, write_ptr; + unsigned char buffer_depth, filled_slots; + + dev->me_hw_state = mei_mecsr_read(dev); + buffer_depth = (unsigned char)((dev->me_hw_state & ME_CBD_HRA) >> 24); + read_ptr = (char) ((dev->me_hw_state & ME_CBRP_HRA) >> 8); + write_ptr = (char) ((dev->me_hw_state & ME_CBWP_HRA) >> 16); + filled_slots = (unsigned char) (write_ptr - read_ptr); + + /* check for overflow */ + if (filled_slots > buffer_depth) + return -EOVERFLOW; + + dev_dbg(&dev->pdev->dev, "filled_slots =%08x\n", filled_slots); + return (int)filled_slots; +} + +/** + * mei_read_slots - reads a message from mei device. + * + * @dev: the device structure + * @buffer: message buffer will be written + * @buffer_length: message size will be read + */ +void mei_read_slots(struct mei_device *dev, unsigned char *buffer, + unsigned long buffer_length) +{ + u32 *reg_buf = (u32 *)buffer; + + for (; buffer_length >= sizeof(u32); buffer_length -= sizeof(u32)) + *reg_buf++ = mei_mecbrw_read(dev); + + if (buffer_length > 0) { + u32 reg = mei_mecbrw_read(dev); + memcpy(reg_buf, ®, buffer_length); + } + + dev->host_hw_state |= H_IG; + mei_hcsr_set(dev); +} + -- cgit v1.2.3 From d025284d06458367cd833a5aceca901fb6da3785 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 8 Jan 2013 23:07:24 +0200 Subject: mei: hw-me.c fix kernel doc Fix the kernel doc for the functions in hw-me.c Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers/misc/mei/hw-me.c') diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 4e6b657cd806..1e82e3311ea2 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -49,17 +49,13 @@ static inline void mei_reg_write(const struct mei_device *dev, } /** - * mei_hcsr_read - Reads 32bit data from the host CSR + * mei_mecbrw_read - Reads 32bit data from ME circular buffer + * read window register * * @dev: the device structure * - * returns the byte read. + * returns ME_CB_RW register value (u32) */ -u32 mei_hcsr_read(const struct mei_device *dev) -{ - return mei_reg_read(dev, H_CSR); -} - u32 mei_mecbrw_read(const struct mei_device *dev) { return mei_reg_read(dev, ME_CB_RW); @@ -77,13 +73,26 @@ u32 mei_mecsr_read(const struct mei_device *dev) } /** - * mei_set_csr_register - writes H_CSR register to the mei device, + * mei_hcsr_read - Reads 32bit data from the host CSR + * + * @dev: the device structure + * + * returns H_CSR register value (u32) + */ +u32 mei_hcsr_read(const struct mei_device *dev) +{ + return mei_reg_read(dev, H_CSR); +} + +/** + * mei_hcsr_set - writes H_CSR register to the mei device, * and ignores the H_IS bit for it is write-one-to-zero. * * @dev: the device structure */ void mei_hcsr_set(struct mei_device *dev) { + if ((dev->host_hw_state & H_IS) == H_IS) dev->host_hw_state &= ~H_IS; mei_reg_write(dev, H_CSR, dev->host_hw_state); @@ -91,7 +100,7 @@ void mei_hcsr_set(struct mei_device *dev) } /** - * mei_enable_interrupts - clear and stop interrupts + * mei_clear_interrupts - clear and stop interrupts * * @dev: the device structure */ -- cgit v1.2.3 From adfba3220b625ce4bee08e7e6f48c8a27aac23bb Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 8 Jan 2013 23:07:27 +0200 Subject: mei: don't use cached value for hcsr in mei_hw_reset Open code mei_hw_reset to avoid using cached hcsr. Using cached hcsr can cause unwanted side effects. Move mei_hw_restet function to hw-me.c as it is hw dependent Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.c | 35 +++++++++++++++++++++++++++++++++++ drivers/misc/mei/init.c | 28 ---------------------------- drivers/misc/mei/mei_dev.h | 1 + 3 files changed, 36 insertions(+), 28 deletions(-) (limited to 'drivers/misc/mei/hw-me.c') diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 1e82e3311ea2..ec4ab895f03d 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -132,6 +132,41 @@ void mei_disable_interrupts(struct mei_device *dev) mei_hcsr_set(dev); } +/** + * mei_hw_reset - resets fw via mei csr register. + * + * @dev: the device structure + * @interrupts_enabled: if interrupt should be enabled after reset. + */ +void mei_hw_reset(struct mei_device *dev, bool intr_enable) +{ + u32 hcsr = mei_hcsr_read(dev); + + dev_dbg(&dev->pdev->dev, "before reset HCSR = 0x%08x.\n", hcsr); + + hcsr |= (H_RST | H_IG); + + if (intr_enable) + hcsr |= H_IE; + else + hcsr &= ~H_IE; + + hcsr &= ~H_IS; + + mei_reg_write(dev, H_CSR, hcsr); + hcsr = mei_hcsr_read(dev); + + hcsr &= ~H_RST; + hcsr |= H_IG; + hcsr &= ~H_IS; + + mei_reg_write(dev, H_CSR, hcsr); + + hcsr = mei_hcsr_read(dev); + + dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", hcsr); +} + /** * mei_interrupt_quick_handler - The ISR of the MEI device diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 2391832bfa6f..5c2054d06f6b 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -169,22 +169,6 @@ out: return ret; } -/** - * mei_hw_reset - resets fw via mei csr register. - * - * @dev: the device structure - * @interrupts_enabled: if interrupt should be enabled after reset. - */ -static void mei_hw_reset(struct mei_device *dev, int interrupts_enabled) -{ - dev->host_hw_state |= (H_RST | H_IG); - - if (interrupts_enabled) - mei_enable_interrupts(dev); - else - mei_disable_interrupts(dev); -} - /** * mei_reset - resets host and fw. * @@ -207,20 +191,8 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) dev->dev_state != MEI_DEV_POWER_DOWN && dev->dev_state != MEI_DEV_POWER_UP); - dev->host_hw_state = mei_hcsr_read(dev); - - dev_dbg(&dev->pdev->dev, "before reset host_hw_state = 0x%08x.\n", - dev->host_hw_state); - mei_hw_reset(dev, interrupts_enabled); - dev->host_hw_state &= ~H_RST; - dev->host_hw_state |= H_IG; - - mei_hcsr_set(dev); - - dev_dbg(&dev->pdev->dev, "currently saved host_hw_state = 0x%08x.\n", - dev->host_hw_state); if (dev->dev_state != MEI_DEV_INITIALIZING) { if (dev->dev_state != MEI_DEV_DISABLED && diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 88fa194ca30e..8692ac8c98d4 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -385,6 +385,7 @@ void mei_watchdog_unregister(struct mei_device *dev); * Register Access Function */ +void mei_hw_reset(struct mei_device *dev, bool intr_enable); u32 mei_hcsr_read(const struct mei_device *dev); void mei_hcsr_set(struct mei_device *dev); u32 mei_mecsr_read(const struct mei_device *dev); -- cgit v1.2.3 From 9ea73ddd4f144952b8f69fac93dc592ea48e4113 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 8 Jan 2013 23:07:28 +0200 Subject: mei: use non cached hcsr for interrupt enablement Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.c | 17 +++++++++++------ drivers/misc/mei/interrupt.c | 2 +- drivers/misc/mei/main.c | 2 -- 3 files changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers/misc/mei/hw-me.c') diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index ec4ab895f03d..ed61659fd388 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -106,8 +106,9 @@ void mei_hcsr_set(struct mei_device *dev) */ void mei_clear_interrupts(struct mei_device *dev) { - if ((dev->host_hw_state & H_IS) == H_IS) - mei_reg_write(dev, H_CSR, dev->host_hw_state); + u32 hcsr = mei_hcsr_read(dev); + if ((hcsr & H_IS) == H_IS) + mei_reg_write(dev, H_CSR, hcsr); } /** @@ -117,8 +118,10 @@ void mei_clear_interrupts(struct mei_device *dev) */ void mei_enable_interrupts(struct mei_device *dev) { - dev->host_hw_state |= H_IE; - mei_hcsr_set(dev); + u32 hcsr = mei_hcsr_read(dev); + hcsr |= H_IE; + hcsr &= ~H_IS; + mei_reg_write(dev, H_CSR, hcsr); } /** @@ -128,8 +131,10 @@ void mei_enable_interrupts(struct mei_device *dev) */ void mei_disable_interrupts(struct mei_device *dev) { - dev->host_hw_state &= ~H_IE; - mei_hcsr_set(dev); + u32 hcsr = mei_hcsr_read(dev); + hcsr &= ~H_IE; + hcsr &= ~H_IS; + mei_reg_write(dev, H_CSR, hcsr); } /** diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index d1ef92617c19..d7e1b797e87b 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -691,7 +691,6 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) /* initialize our complete list */ mutex_lock(&dev->device_lock); mei_io_list_init(&complete_list); - dev->host_hw_state = mei_hcsr_read(dev); /* Ack the interrupt here * In case of MSI we don't go through the quick handler */ @@ -710,6 +709,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) return IRQ_HANDLED; } + dev->host_hw_state = mei_hcsr_read(dev); /* check if we need to start the dev */ if ((dev->host_hw_state & H_RDY) == 0) { if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) { diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index ec5fd7a0e289..f72bb77fc279 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -915,8 +915,6 @@ static int mei_probe(struct pci_dev *pdev, return 0; release_irq: - /* disable interrupts */ - dev->host_hw_state = mei_hcsr_read(dev); mei_disable_interrupts(dev); flush_scheduled_work(); free_irq(pdev->irq, dev); -- cgit v1.2.3 From 115ba28c5e075c6bffd8106a2b5e23db88d0c3b5 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 8 Jan 2013 23:07:29 +0200 Subject: mei: abstract host and device readieness Add mei_host_set_ready function to enable the device and is_ready function to query the host and me readiness Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.c | 35 ++++++++++++++++++++++++++++++++++- drivers/misc/mei/init.c | 14 ++++++-------- drivers/misc/mei/interrupt.c | 19 ++++++++++--------- drivers/misc/mei/mei_dev.h | 4 ++++ 4 files changed, 54 insertions(+), 18 deletions(-) (limited to 'drivers/misc/mei/hw-me.c') diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index ed61659fd388..49b558ddf5b5 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -172,6 +172,39 @@ void mei_hw_reset(struct mei_device *dev, bool intr_enable) dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", hcsr); } +/** + * mei_host_set_ready - enable device + * + * @dev - mei device + * returns bool + */ + +void mei_host_set_ready(struct mei_device *dev) +{ + dev->host_hw_state |= H_IE | H_IG | H_RDY; + mei_hcsr_set(dev); +} +/** + * mei_host_is_ready - check whether the host has turned ready + * + * @dev - mei device + * returns bool + */ +bool mei_host_is_ready(struct mei_device *dev) +{ + return (dev->host_hw_state & H_RDY) == H_RDY; +} + +/** + * mei_me_is_ready - check whether the me has turned ready + * + * @dev - mei device + * returns bool + */ +bool mei_me_is_ready(struct mei_device *dev) +{ + return (dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA; +} /** * mei_interrupt_quick_handler - The ISR of the MEI device @@ -290,7 +323,7 @@ int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header, dev->host_hw_state |= H_IG; mei_hcsr_set(dev); dev->me_hw_state = mei_mecsr_read(dev); - if ((dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA) + if (!mei_me_is_ready(dev)) return -EIO; return 0; diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 5c2054d06f6b..d0ee02ac8201 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -131,18 +131,18 @@ int mei_hw_init(struct mei_device *dev) goto out; } - if (!(((dev->host_hw_state & H_RDY) == H_RDY) && - ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) { + if (!(mei_host_is_ready(dev) && mei_me_is_ready(dev))) { dev->dev_state = MEI_DEV_DISABLED; + dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", dev->host_hw_state, dev->me_hw_state); - if (!(dev->host_hw_state & H_RDY)) - dev_dbg(&dev->pdev->dev, "host turn off H_RDY.\n"); + if (!mei_host_is_ready(dev)) + dev_dbg(&dev->pdev->dev, "host is not ready.\n"); - if (!(dev->me_hw_state & ME_RDY_HRA)) - dev_dbg(&dev->pdev->dev, "ME turn off ME_RDY.\n"); + if (!mei_me_is_ready(dev)) + dev_dbg(&dev->pdev->dev, "ME is not ready.\n"); dev_err(&dev->pdev->dev, "link layer initialization failed.\n"); ret = -ENODEV; @@ -159,9 +159,7 @@ int mei_hw_init(struct mei_device *dev) dev->recvd_msg = false; dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", dev->host_hw_state, dev->me_hw_state); - dev_dbg(&dev->pdev->dev, "ME turn on ME_RDY and host turn on H_RDY.\n"); dev_dbg(&dev->pdev->dev, "link layer has been established.\n"); - dev_dbg(&dev->pdev->dev, "MEI start success.\n"); ret = 0; out: diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index d7e1b797e87b..27374b6b6424 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -700,7 +700,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) dev->me_hw_state = mei_mecsr_read(dev); /* check if ME wants a reset */ - if ((dev->me_hw_state & ME_RDY_HRA) == 0 && + if (!mei_me_is_ready(dev) && dev->dev_state != MEI_DEV_RESETING && dev->dev_state != MEI_DEV_INITIALIZING) { dev_dbg(&dev->pdev->dev, "FW not ready.\n"); @@ -711,16 +711,17 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) dev->host_hw_state = mei_hcsr_read(dev); /* check if we need to start the dev */ - if ((dev->host_hw_state & H_RDY) == 0) { - if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) { + if (!mei_host_is_ready(dev)) { + if (mei_me_is_ready(dev)) { dev_dbg(&dev->pdev->dev, "we need to start the dev.\n"); - dev->host_hw_state |= (H_IE | H_IG | H_RDY); - mei_hcsr_set(dev); - dev->dev_state = MEI_DEV_INIT_CLIENTS; + + mei_host_set_ready(dev); + dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n"); - /* link is established - * start sending messages. - */ + /* link is established * start sending messages. */ + + dev->dev_state = MEI_DEV_INIT_CLIENTS; + mei_hbm_start_req(dev); mutex_unlock(&dev->device_lock); return IRQ_HANDLED; diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 8692ac8c98d4..7b4365952be5 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -396,6 +396,10 @@ void mei_clear_interrupts(struct mei_device *dev); void mei_enable_interrupts(struct mei_device *dev); void mei_disable_interrupts(struct mei_device *dev); +void mei_host_set_ready(struct mei_device *dev); +bool mei_host_is_ready(struct mei_device *dev); +bool mei_me_is_ready(struct mei_device *dev); + #define MEI_HDR_FMT "hdr:host=%02d me=%02d len=%d comp=%1d" -- cgit v1.2.3 From 88eb99f29c0026f4b7d7702652eb529f04c69073 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 8 Jan 2013 23:07:30 +0200 Subject: mei: reenable mei_hcsr_set abstraction Now when mei_hcsr_set is local to hw-me.c we can benefit form the fact that it wraps H_IS removal from the host csr. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.c | 38 +++++++++++++++----------------------- drivers/misc/mei/mei_dev.h | 1 - 2 files changed, 15 insertions(+), 24 deletions(-) (limited to 'drivers/misc/mei/hw-me.c') diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 49b558ddf5b5..319002797578 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -90,13 +90,10 @@ u32 mei_hcsr_read(const struct mei_device *dev) * * @dev: the device structure */ -void mei_hcsr_set(struct mei_device *dev) +static inline void mei_hcsr_set(struct mei_device *dev, u32 hcsr) { - - if ((dev->host_hw_state & H_IS) == H_IS) - dev->host_hw_state &= ~H_IS; - mei_reg_write(dev, H_CSR, dev->host_hw_state); - dev->host_hw_state = mei_hcsr_read(dev); + hcsr &= ~H_IS; + mei_reg_write(dev, H_CSR, hcsr); } /** @@ -120,8 +117,7 @@ void mei_enable_interrupts(struct mei_device *dev) { u32 hcsr = mei_hcsr_read(dev); hcsr |= H_IE; - hcsr &= ~H_IS; - mei_reg_write(dev, H_CSR, hcsr); + mei_hcsr_set(dev, hcsr); } /** @@ -133,8 +129,7 @@ void mei_disable_interrupts(struct mei_device *dev) { u32 hcsr = mei_hcsr_read(dev); hcsr &= ~H_IE; - hcsr &= ~H_IS; - mei_reg_write(dev, H_CSR, hcsr); + mei_hcsr_set(dev, hcsr); } /** @@ -156,16 +151,12 @@ void mei_hw_reset(struct mei_device *dev, bool intr_enable) else hcsr &= ~H_IE; - hcsr &= ~H_IS; - - mei_reg_write(dev, H_CSR, hcsr); - hcsr = mei_hcsr_read(dev); + mei_hcsr_set(dev, hcsr); + hcsr = mei_hcsr_read(dev) | H_IG; hcsr &= ~H_RST; - hcsr |= H_IG; - hcsr &= ~H_IS; - mei_reg_write(dev, H_CSR, hcsr); + mei_hcsr_set(dev, hcsr); hcsr = mei_hcsr_read(dev); @@ -182,7 +173,7 @@ void mei_hw_reset(struct mei_device *dev, bool intr_enable) void mei_host_set_ready(struct mei_device *dev) { dev->host_hw_state |= H_IE | H_IG | H_RDY; - mei_hcsr_set(dev); + mei_hcsr_set(dev, dev->host_hw_state); } /** * mei_host_is_ready - check whether the host has turned ready @@ -295,6 +286,7 @@ int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header, unsigned long rem, dw_cnt; unsigned long length = header->length; u32 *reg_buf = (u32 *)buf; + u32 hcsr; int i; int empty_slots; @@ -319,9 +311,8 @@ int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header, mei_reg_write(dev, H_CB_WW, reg); } - dev->host_hw_state = mei_hcsr_read(dev); - dev->host_hw_state |= H_IG; - mei_hcsr_set(dev); + hcsr = mei_hcsr_read(dev) | H_IG; + mei_hcsr_set(dev, hcsr); dev->me_hw_state = mei_mecsr_read(dev); if (!mei_me_is_ready(dev)) return -EIO; @@ -366,6 +357,7 @@ void mei_read_slots(struct mei_device *dev, unsigned char *buffer, unsigned long buffer_length) { u32 *reg_buf = (u32 *)buffer; + u32 hcsr; for (; buffer_length >= sizeof(u32); buffer_length -= sizeof(u32)) *reg_buf++ = mei_mecbrw_read(dev); @@ -375,7 +367,7 @@ void mei_read_slots(struct mei_device *dev, unsigned char *buffer, memcpy(reg_buf, ®, buffer_length); } - dev->host_hw_state |= H_IG; - mei_hcsr_set(dev); + hcsr = mei_hcsr_read(dev) | H_IG; + mei_hcsr_set(dev, hcsr); } diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 7b4365952be5..ae4c5ffc712b 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -387,7 +387,6 @@ void mei_watchdog_unregister(struct mei_device *dev); void mei_hw_reset(struct mei_device *dev, bool intr_enable); u32 mei_hcsr_read(const struct mei_device *dev); -void mei_hcsr_set(struct mei_device *dev); u32 mei_mecsr_read(const struct mei_device *dev); u32 mei_mecbrw_read(const struct mei_device *dev); -- cgit v1.2.3 From e7e0c231aaa7a01df28634390381974cb76d3cb2 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 8 Jan 2013 23:07:31 +0200 Subject: mei: make host csr and me csr internal to hw-me Move csr reading into me hardware functional calls. Since we gave up on registers caching we remove some of the unnecessary queries in mei_hw_init ane mei_reset functions. We add mei_hw_config function to wrap up host buffer depth configuration. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.c | 19 ++++++++++--- drivers/misc/mei/init.c | 63 +++++++++++++------------------------------- drivers/misc/mei/interrupt.c | 4 --- drivers/misc/mei/mei_dev.h | 4 +-- 4 files changed, 37 insertions(+), 53 deletions(-) (limited to 'drivers/misc/mei/hw-me.c') diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 319002797578..93a2a56a5f2c 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -67,7 +67,7 @@ u32 mei_mecbrw_read(const struct mei_device *dev) * * returns ME_CSR_HA register value (u32) */ -u32 mei_mecsr_read(const struct mei_device *dev) +static inline u32 mei_mecsr_read(const struct mei_device *dev) { return mei_reg_read(dev, ME_CSR_HA); } @@ -79,7 +79,7 @@ u32 mei_mecsr_read(const struct mei_device *dev) * * returns H_CSR register value (u32) */ -u32 mei_hcsr_read(const struct mei_device *dev) +static inline u32 mei_hcsr_read(const struct mei_device *dev) { return mei_reg_read(dev, H_CSR); } @@ -96,6 +96,18 @@ static inline void mei_hcsr_set(struct mei_device *dev, u32 hcsr) mei_reg_write(dev, H_CSR, hcsr); } + +/** + * me_hw_config - configure hw dependent settings + * + * @dev: mei device + */ +void mei_hw_config(struct mei_device *dev) +{ + u32 hcsr = mei_hcsr_read(dev); + /* Doesn't change in runtime */ + dev->hbuf_depth = (hcsr & H_CBD) >> 24; +} /** * mei_clear_interrupts - clear and stop interrupts * @@ -183,6 +195,7 @@ void mei_host_set_ready(struct mei_device *dev) */ bool mei_host_is_ready(struct mei_device *dev) { + dev->host_hw_state = mei_hcsr_read(dev); return (dev->host_hw_state & H_RDY) == H_RDY; } @@ -194,6 +207,7 @@ bool mei_host_is_ready(struct mei_device *dev) */ bool mei_me_is_ready(struct mei_device *dev) { + dev->me_hw_state = mei_mecsr_read(dev); return (dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA; } @@ -313,7 +327,6 @@ int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header, hcsr = mei_hcsr_read(dev) | H_IG; mei_hcsr_set(dev, hcsr); - dev->me_hw_state = mei_mecsr_read(dev); if (!mei_me_is_ready(dev)) return -EIO; diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index d0ee02ac8201..98a7fc18a90a 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -89,82 +89,64 @@ struct mei_device *mei_device_init(struct pci_dev *pdev) */ int mei_hw_init(struct mei_device *dev) { - int err = 0; - int ret; + int ret = 0; mutex_lock(&dev->device_lock); - dev->host_hw_state = mei_hcsr_read(dev); - dev->me_hw_state = mei_mecsr_read(dev); - dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, mestate = 0x%08x.\n", - dev->host_hw_state, dev->me_hw_state); - /* acknowledge interrupt and stop interupts */ mei_clear_interrupts(dev); - /* Doesn't change in runtime */ - dev->hbuf_depth = (dev->host_hw_state & H_CBD) >> 24; + mei_hw_config(dev); dev->recvd_msg = false; dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n"); mei_reset(dev, 1); - dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", - dev->host_hw_state, dev->me_hw_state); - /* wait for ME to turn on ME_RDY */ if (!dev->recvd_msg) { mutex_unlock(&dev->device_lock); - err = wait_event_interruptible_timeout(dev->wait_recvd_msg, + ret = wait_event_interruptible_timeout(dev->wait_recvd_msg, dev->recvd_msg, mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT)); mutex_lock(&dev->device_lock); } - if (err <= 0 && !dev->recvd_msg) { + if (ret <= 0 && !dev->recvd_msg) { dev->dev_state = MEI_DEV_DISABLED; dev_dbg(&dev->pdev->dev, "wait_event_interruptible_timeout failed" "on wait for ME to turn on ME_RDY.\n"); - ret = -ENODEV; - goto out; + goto err; } - if (!(mei_host_is_ready(dev) && mei_me_is_ready(dev))) { - dev->dev_state = MEI_DEV_DISABLED; - - dev_dbg(&dev->pdev->dev, - "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", - dev->host_hw_state, dev->me_hw_state); - - if (!mei_host_is_ready(dev)) - dev_dbg(&dev->pdev->dev, "host is not ready.\n"); - if (!mei_me_is_ready(dev)) - dev_dbg(&dev->pdev->dev, "ME is not ready.\n"); + if (!mei_host_is_ready(dev)) { + dev_err(&dev->pdev->dev, "host is not ready.\n"); + goto err; + } - dev_err(&dev->pdev->dev, "link layer initialization failed.\n"); - ret = -ENODEV; - goto out; + if (!mei_me_is_ready(dev)) { + dev_err(&dev->pdev->dev, "ME is not ready.\n"); + goto err; } if (dev->version.major_version != HBM_MAJOR_VERSION || dev->version.minor_version != HBM_MINOR_VERSION) { dev_dbg(&dev->pdev->dev, "MEI start failed.\n"); - ret = -ENODEV; - goto out; + goto err; } dev->recvd_msg = false; - dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", - dev->host_hw_state, dev->me_hw_state); dev_dbg(&dev->pdev->dev, "link layer has been established.\n"); - ret = 0; -out: mutex_unlock(&dev->device_lock); - return ret; + return 0; +err: + dev_err(&dev->pdev->dev, "link layer initialization failed.\n"); + dev->dev_state = MEI_DEV_DISABLED; + mutex_unlock(&dev->device_lock); + return -ENODEV; } /** @@ -221,13 +203,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) dev->rd_msg_hdr = 0; dev->wd_pending = false; - /* update the state of the registers after reset */ - dev->host_hw_state = mei_hcsr_read(dev); - dev->me_hw_state = mei_mecsr_read(dev); - - dev_dbg(&dev->pdev->dev, "after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", - dev->host_hw_state, dev->me_hw_state); - if (unexpected) dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n", mei_dev_state_str(dev->dev_state)); diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 27374b6b6424..b04ed9bdf758 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -697,8 +697,6 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) if (pci_dev_msi_enabled(dev->pdev)) mei_clear_interrupts(dev); - dev->me_hw_state = mei_mecsr_read(dev); - /* check if ME wants a reset */ if (!mei_me_is_ready(dev) && dev->dev_state != MEI_DEV_RESETING && @@ -709,7 +707,6 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) return IRQ_HANDLED; } - dev->host_hw_state = mei_hcsr_read(dev); /* check if we need to start the dev */ if (!mei_host_is_ready(dev)) { if (mei_me_is_ready(dev)) { @@ -746,7 +743,6 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) rets = mei_irq_thread_write_handler(dev, &complete_list); end: dev_dbg(&dev->pdev->dev, "end of bottom half function.\n"); - dev->host_hw_state = mei_hcsr_read(dev); dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev); bus_message_received = false; diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index ae4c5ffc712b..d6589d0d305a 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -385,12 +385,12 @@ void mei_watchdog_unregister(struct mei_device *dev); * Register Access Function */ +void mei_hw_config(struct mei_device *dev); void mei_hw_reset(struct mei_device *dev, bool intr_enable); -u32 mei_hcsr_read(const struct mei_device *dev); -u32 mei_mecsr_read(const struct mei_device *dev); u32 mei_mecbrw_read(const struct mei_device *dev); + void mei_clear_interrupts(struct mei_device *dev); void mei_enable_interrupts(struct mei_device *dev); void mei_disable_interrupts(struct mei_device *dev); -- cgit v1.2.3 From 7353f85ce82baa363b0338ef4cb3745eb0686760 Mon Sep 17 00:00:00 2001 From: Sedat Dilek Date: Thu, 17 Jan 2013 19:54:15 +0100 Subject: mei: Fix some more kernel-doc typos in hw-me.c Signed-off-by: Sedat Dilek Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/misc/mei/hw-me.c') diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 93a2a56a5f2c..94b203ec9b1f 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -236,7 +236,7 @@ irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id) /** * mei_hbuf_filled_slots - gets number of device filled buffer slots * - * @device: the device structure + * @dev: the device structure * * returns number of filled slots */ @@ -289,7 +289,7 @@ int mei_hbuf_empty_slots(struct mei_device *dev) * mei_write_message - writes a message to mei device. * * @dev: the device structure - * @hader: mei HECI header of message + * @header: mei HECI header of message * @buf: message payload will be written * * This function returns -EIO if write has failed -- cgit v1.2.3 From 52c34561415b420301f1580413a9d1891d079494 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 6 Feb 2013 14:06:40 +0200 Subject: mei: initial extract of ME hw specifics from mei_device This is initial step of move the ME hw specifics out of mei_device structure into mei_me_hw Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.c | 131 +++++++++++++++++++++++++++++---------------- drivers/misc/mei/hw-me.h | 12 +++++ drivers/misc/mei/init.c | 28 +--------- drivers/misc/mei/mei_dev.h | 10 ++-- drivers/misc/mei/pci-me.c | 21 ++++---- 5 files changed, 114 insertions(+), 88 deletions(-) (limited to 'drivers/misc/mei/hw-me.c') diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 94b203ec9b1f..3bdf22848a91 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -28,10 +28,10 @@ * * returns register value (u32) */ -static inline u32 mei_reg_read(const struct mei_device *dev, +static inline u32 mei_reg_read(const struct mei_me_hw *hw, unsigned long offset) { - return ioread32(dev->mem_addr + offset); + return ioread32(hw->mem_addr + offset); } @@ -42,10 +42,10 @@ static inline u32 mei_reg_read(const struct mei_device *dev, * @offset: offset from which to write the data * @value: register value to write (u32) */ -static inline void mei_reg_write(const struct mei_device *dev, +static inline void mei_reg_write(const struct mei_me_hw *hw, unsigned long offset, u32 value) { - iowrite32(value, dev->mem_addr + offset); + iowrite32(value, hw->mem_addr + offset); } /** @@ -58,7 +58,7 @@ static inline void mei_reg_write(const struct mei_device *dev, */ u32 mei_mecbrw_read(const struct mei_device *dev) { - return mei_reg_read(dev, ME_CB_RW); + return mei_reg_read(to_me_hw(dev), ME_CB_RW); } /** * mei_mecsr_read - Reads 32bit data from the ME CSR @@ -67,9 +67,9 @@ u32 mei_mecbrw_read(const struct mei_device *dev) * * returns ME_CSR_HA register value (u32) */ -static inline u32 mei_mecsr_read(const struct mei_device *dev) +static inline u32 mei_mecsr_read(const struct mei_me_hw *hw) { - return mei_reg_read(dev, ME_CSR_HA); + return mei_reg_read(hw, ME_CSR_HA); } /** @@ -79,9 +79,9 @@ static inline u32 mei_mecsr_read(const struct mei_device *dev) * * returns H_CSR register value (u32) */ -static inline u32 mei_hcsr_read(const struct mei_device *dev) +static inline u32 mei_hcsr_read(const struct mei_me_hw *hw) { - return mei_reg_read(dev, H_CSR); + return mei_reg_read(hw, H_CSR); } /** @@ -90,10 +90,10 @@ static inline u32 mei_hcsr_read(const struct mei_device *dev) * * @dev: the device structure */ -static inline void mei_hcsr_set(struct mei_device *dev, u32 hcsr) +static inline void mei_hcsr_set(struct mei_me_hw *hw, u32 hcsr) { hcsr &= ~H_IS; - mei_reg_write(dev, H_CSR, hcsr); + mei_reg_write(hw, H_CSR, hcsr); } @@ -104,7 +104,7 @@ static inline void mei_hcsr_set(struct mei_device *dev, u32 hcsr) */ void mei_hw_config(struct mei_device *dev) { - u32 hcsr = mei_hcsr_read(dev); + u32 hcsr = mei_hcsr_read(to_me_hw(dev)); /* Doesn't change in runtime */ dev->hbuf_depth = (hcsr & H_CBD) >> 24; } @@ -115,9 +115,10 @@ void mei_hw_config(struct mei_device *dev) */ void mei_clear_interrupts(struct mei_device *dev) { - u32 hcsr = mei_hcsr_read(dev); + struct mei_me_hw *hw = to_me_hw(dev); + u32 hcsr = mei_hcsr_read(hw); if ((hcsr & H_IS) == H_IS) - mei_reg_write(dev, H_CSR, hcsr); + mei_reg_write(hw, H_CSR, hcsr); } /** @@ -127,9 +128,10 @@ void mei_clear_interrupts(struct mei_device *dev) */ void mei_enable_interrupts(struct mei_device *dev) { - u32 hcsr = mei_hcsr_read(dev); + struct mei_me_hw *hw = to_me_hw(dev); + u32 hcsr = mei_hcsr_read(hw); hcsr |= H_IE; - mei_hcsr_set(dev, hcsr); + mei_hcsr_set(hw, hcsr); } /** @@ -139,9 +141,10 @@ void mei_enable_interrupts(struct mei_device *dev) */ void mei_disable_interrupts(struct mei_device *dev) { - u32 hcsr = mei_hcsr_read(dev); + struct mei_me_hw *hw = to_me_hw(dev); + u32 hcsr = mei_hcsr_read(hw); hcsr &= ~H_IE; - mei_hcsr_set(dev, hcsr); + mei_hcsr_set(hw, hcsr); } /** @@ -152,7 +155,8 @@ void mei_disable_interrupts(struct mei_device *dev) */ void mei_hw_reset(struct mei_device *dev, bool intr_enable) { - u32 hcsr = mei_hcsr_read(dev); + struct mei_me_hw *hw = to_me_hw(dev); + u32 hcsr = mei_hcsr_read(hw); dev_dbg(&dev->pdev->dev, "before reset HCSR = 0x%08x.\n", hcsr); @@ -163,14 +167,14 @@ void mei_hw_reset(struct mei_device *dev, bool intr_enable) else hcsr &= ~H_IE; - mei_hcsr_set(dev, hcsr); + mei_hcsr_set(hw, hcsr); - hcsr = mei_hcsr_read(dev) | H_IG; + hcsr = mei_hcsr_read(hw) | H_IG; hcsr &= ~H_RST; - mei_hcsr_set(dev, hcsr); + mei_hcsr_set(hw, hcsr); - hcsr = mei_hcsr_read(dev); + hcsr = mei_hcsr_read(hw); dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", hcsr); } @@ -184,8 +188,9 @@ void mei_hw_reset(struct mei_device *dev, bool intr_enable) void mei_host_set_ready(struct mei_device *dev) { - dev->host_hw_state |= H_IE | H_IG | H_RDY; - mei_hcsr_set(dev, dev->host_hw_state); + struct mei_me_hw *hw = to_me_hw(dev); + hw->host_hw_state |= H_IE | H_IG | H_RDY; + mei_hcsr_set(hw, hw->host_hw_state); } /** * mei_host_is_ready - check whether the host has turned ready @@ -195,8 +200,9 @@ void mei_host_set_ready(struct mei_device *dev) */ bool mei_host_is_ready(struct mei_device *dev) { - dev->host_hw_state = mei_hcsr_read(dev); - return (dev->host_hw_state & H_RDY) == H_RDY; + struct mei_me_hw *hw = to_me_hw(dev); + hw->host_hw_state = mei_hcsr_read(hw); + return (hw->host_hw_state & H_RDY) == H_RDY; } /** @@ -207,8 +213,9 @@ bool mei_host_is_ready(struct mei_device *dev) */ bool mei_me_is_ready(struct mei_device *dev) { - dev->me_hw_state = mei_mecsr_read(dev); - return (dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA; + struct mei_me_hw *hw = to_me_hw(dev); + hw->me_hw_state = mei_mecsr_read(hw); + return (hw->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA; } /** @@ -222,13 +229,14 @@ bool mei_me_is_ready(struct mei_device *dev) irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id) { struct mei_device *dev = (struct mei_device *) dev_id; - u32 csr_reg = mei_hcsr_read(dev); + struct mei_me_hw *hw = to_me_hw(dev); + u32 csr_reg = mei_hcsr_read(hw); if ((csr_reg & H_IS) != H_IS) return IRQ_NONE; /* clear H_IS bit in H_CSR */ - mei_reg_write(dev, H_CSR, csr_reg); + mei_reg_write(hw, H_CSR, csr_reg); return IRQ_WAKE_THREAD; } @@ -242,12 +250,13 @@ irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id) */ static unsigned char mei_hbuf_filled_slots(struct mei_device *dev) { + struct mei_me_hw *hw = to_me_hw(dev); char read_ptr, write_ptr; - dev->host_hw_state = mei_hcsr_read(dev); + hw->host_hw_state = mei_hcsr_read(hw); - read_ptr = (char) ((dev->host_hw_state & H_CBRP) >> 8); - write_ptr = (char) ((dev->host_hw_state & H_CBWP) >> 16); + read_ptr = (char) ((hw->host_hw_state & H_CBRP) >> 8); + write_ptr = (char) ((hw->host_hw_state & H_CBWP) >> 16); return (unsigned char) (write_ptr - read_ptr); } @@ -297,6 +306,7 @@ int mei_hbuf_empty_slots(struct mei_device *dev) int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header, unsigned char *buf) { + struct mei_me_hw *hw = to_me_hw(dev); unsigned long rem, dw_cnt; unsigned long length = header->length; u32 *reg_buf = (u32 *)buf; @@ -313,20 +323,20 @@ int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header, if (empty_slots < 0 || dw_cnt > empty_slots) return -EIO; - mei_reg_write(dev, H_CB_WW, *((u32 *) header)); + mei_reg_write(hw, H_CB_WW, *((u32 *) header)); for (i = 0; i < length / 4; i++) - mei_reg_write(dev, H_CB_WW, reg_buf[i]); + mei_reg_write(hw, H_CB_WW, reg_buf[i]); rem = length & 0x3; if (rem > 0) { u32 reg = 0; memcpy(®, &buf[length - rem], rem); - mei_reg_write(dev, H_CB_WW, reg); + mei_reg_write(hw, H_CB_WW, reg); } - hcsr = mei_hcsr_read(dev) | H_IG; - mei_hcsr_set(dev, hcsr); + hcsr = mei_hcsr_read(hw) | H_IG; + mei_hcsr_set(hw, hcsr); if (!mei_me_is_ready(dev)) return -EIO; @@ -342,13 +352,14 @@ int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header, */ int mei_count_full_read_slots(struct mei_device *dev) { + struct mei_me_hw *hw = to_me_hw(dev); char read_ptr, write_ptr; unsigned char buffer_depth, filled_slots; - dev->me_hw_state = mei_mecsr_read(dev); - buffer_depth = (unsigned char)((dev->me_hw_state & ME_CBD_HRA) >> 24); - read_ptr = (char) ((dev->me_hw_state & ME_CBRP_HRA) >> 8); - write_ptr = (char) ((dev->me_hw_state & ME_CBWP_HRA) >> 16); + hw->me_hw_state = mei_mecsr_read(hw); + buffer_depth = (unsigned char)((hw->me_hw_state & ME_CBD_HRA) >> 24); + read_ptr = (char) ((hw->me_hw_state & ME_CBRP_HRA) >> 8); + write_ptr = (char) ((hw->me_hw_state & ME_CBWP_HRA) >> 16); filled_slots = (unsigned char) (write_ptr - read_ptr); /* check for overflow */ @@ -369,6 +380,7 @@ int mei_count_full_read_slots(struct mei_device *dev) void mei_read_slots(struct mei_device *dev, unsigned char *buffer, unsigned long buffer_length) { + struct mei_me_hw *hw = to_me_hw(dev); u32 *reg_buf = (u32 *)buffer; u32 hcsr; @@ -380,7 +392,36 @@ void mei_read_slots(struct mei_device *dev, unsigned char *buffer, memcpy(reg_buf, ®, buffer_length); } - hcsr = mei_hcsr_read(dev) | H_IG; - mei_hcsr_set(dev, hcsr); + hcsr = mei_hcsr_read(hw) | H_IG; + mei_hcsr_set(hw, hcsr); } +/** + * init_mei_device - allocates and initializes the mei device structure + * + * @pdev: The pci device structure + * + * returns The mei_device_device pointer on success, NULL on failure. + */ +struct mei_device *mei_me_dev_init(struct pci_dev *pdev) +{ + struct mei_device *dev; + + dev = kzalloc(sizeof(struct mei_device) + + sizeof(struct mei_me_hw), GFP_KERNEL); + if (!dev) + return NULL; + + mei_device_init(dev); + + INIT_LIST_HEAD(&dev->wd_cl.link); + INIT_LIST_HEAD(&dev->iamthif_cl.link); + mei_io_list_init(&dev->amthif_cmd_list); + mei_io_list_init(&dev->amthif_rd_complete_list); + + INIT_DELAYED_WORK(&dev->timer_work, mei_timer); + INIT_WORK(&dev->init_work, mei_host_client_init); + + dev->pdev = pdev; + return dev; +} diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h index 73bef545e4d5..53bcc0087e26 100644 --- a/drivers/misc/mei/hw-me.h +++ b/drivers/misc/mei/hw-me.h @@ -21,8 +21,20 @@ #include #include "mei_dev.h" +#include "client.h" +struct mei_me_hw { + void __iomem *mem_addr; + /* + * hw states of host and fw(ME) + */ + u32 host_hw_state; + u32 me_hw_state; +}; +#define to_me_hw(dev) (struct mei_me_hw *)((dev)->hw) + +struct mei_device *mei_me_dev_init(struct pci_dev *pdev); void mei_read_slots(struct mei_device *dev, unsigned char *buffer, diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 5d08db5b314e..1e1876ff25b1 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -42,28 +42,10 @@ const char *mei_dev_state_str(int state) #undef MEI_DEV_STATE } - - - -/** - * init_mei_device - allocates and initializes the mei device structure - * - * @pdev: The pci device structure - * - * returns The mei_device_device pointer on success, NULL on failure. - */ -struct mei_device *mei_device_init(struct pci_dev *pdev) +void mei_device_init(struct mei_device *dev) { - struct mei_device *dev; - - dev = kzalloc(sizeof(struct mei_device), GFP_KERNEL); - if (!dev) - return NULL; - /* setup our list array */ INIT_LIST_HEAD(&dev->file_list); - INIT_LIST_HEAD(&dev->wd_cl.link); - INIT_LIST_HEAD(&dev->iamthif_cl.link); mutex_init(&dev->device_lock); init_waitqueue_head(&dev->wait_recvd_msg); init_waitqueue_head(&dev->wait_stop_wd); @@ -74,14 +56,6 @@ struct mei_device *mei_device_init(struct pci_dev *pdev) mei_io_list_init(&dev->write_waiting_list); mei_io_list_init(&dev->ctrl_wr_list); mei_io_list_init(&dev->ctrl_rd_list); - mei_io_list_init(&dev->amthif_cmd_list); - mei_io_list_init(&dev->amthif_rd_complete_list); - - INIT_DELAYED_WORK(&dev->timer_work, mei_timer); - INIT_WORK(&dev->init_work, mei_host_client_init); - - dev->pdev = pdev; - return dev; } /** diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 3b2bca386e5a..bb759fd9ee4a 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -235,18 +235,13 @@ struct mei_device { struct list_head file_list; long open_handle_count; - void __iomem *mem_addr; /* * lock for the device */ struct mutex device_lock; /* device lock */ struct delayed_work timer_work; /* MEI timer delayed work (timeouts) */ bool recvd_msg; - /* - * hw states of host and fw(ME) - */ - u32 host_hw_state; - u32 me_hw_state; + u8 hbuf_depth; /* * waiting queue for receive message from FW @@ -311,6 +306,7 @@ struct mei_device { bool iamthif_canceled; struct work_struct init_work; + char hw[0] __aligned(sizeof(void *)); }; static inline unsigned long mei_secs_to_jiffies(unsigned long sec) @@ -322,7 +318,7 @@ static inline unsigned long mei_secs_to_jiffies(unsigned long sec) /* * mei init function prototypes */ -struct mei_device *mei_device_init(struct pci_dev *pdev); +void mei_device_init(struct mei_device *dev); void mei_reset(struct mei_device *dev, int interrupts); int mei_hw_init(struct mei_device *dev); diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index eaed398bed6b..27ac71767981 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -90,7 +90,6 @@ MODULE_DEVICE_TABLE(pci, mei_pci_tbl); static DEFINE_MUTEX(mei_mutex); - /** * mei_quirk_probe - probe for devices that doesn't valid ME interface * @pdev: PCI device structure @@ -120,10 +119,10 @@ static bool mei_quirk_probe(struct pci_dev *pdev, * * returns 0 on success, <0 on failure. */ -static int mei_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int mei_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct mei_device *dev; + struct mei_me_hw *hw; int err; mutex_lock(&mei_mutex); @@ -152,14 +151,15 @@ static int mei_probe(struct pci_dev *pdev, goto disable_device; } /* allocates and initializes the mei dev structure */ - dev = mei_device_init(pdev); + dev = mei_me_dev_init(pdev); if (!dev) { err = -ENOMEM; goto release_regions; } + hw = to_me_hw(dev); /* mapping IO device memory */ - dev->mem_addr = pci_iomap(pdev, 0, 0); - if (!dev->mem_addr) { + hw->mem_addr = pci_iomap(pdev, 0, 0); + if (!hw->mem_addr) { dev_err(&pdev->dev, "mapping I/O device memory failure.\n"); err = -ENOMEM; goto free_device; @@ -212,7 +212,7 @@ release_irq: free_irq(pdev->irq, dev); disable_msi: pci_disable_msi(pdev); - pci_iounmap(pdev, dev->mem_addr); + pci_iounmap(pdev, hw->mem_addr); free_device: kfree(dev); release_regions: @@ -236,6 +236,7 @@ end: static void mei_remove(struct pci_dev *pdev) { struct mei_device *dev; + struct mei_me_hw *hw; if (mei_pdev != pdev) return; @@ -244,6 +245,8 @@ static void mei_remove(struct pci_dev *pdev) if (!dev) return; + hw = to_me_hw(dev); + mutex_lock(&dev->device_lock); cancel_delayed_work(&dev->timer_work); @@ -289,8 +292,8 @@ static void mei_remove(struct pci_dev *pdev) pci_disable_msi(pdev); pci_set_drvdata(pdev, NULL); - if (dev->mem_addr) - pci_iounmap(pdev, dev->mem_addr); + if (hw->mem_addr) + pci_iounmap(pdev, hw->mem_addr); kfree(dev); -- cgit v1.2.3 From 827eef51f8dd9a4ab62b4ad270c15472f46938f2 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 6 Feb 2013 14:06:41 +0200 Subject: 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 Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/Kconfig | 17 ++++-- drivers/misc/mei/Makefile | 6 +- drivers/misc/mei/amthif.c | 6 +- drivers/misc/mei/hw-me.c | 87 +++++++++++++++++++--------- drivers/misc/mei/hw-me.h | 19 ------- drivers/misc/mei/init.c | 2 +- drivers/misc/mei/interrupt.c | 10 ++-- drivers/misc/mei/main.c | 5 +- drivers/misc/mei/mei_dev.h | 132 +++++++++++++++++++++++++++++++++++++++---- 9 files changed, 210 insertions(+), 74 deletions(-) (limited to 'drivers/misc/mei/hw-me.c') 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 @@ config INTEL_MEI - tristate "Intel Management Engine Interface (Intel MEI)" - depends on X86 && PCI && WATCHDOG_CORE + tristate "Intel Management Engine Interface" + depends on X86 && PCI help The Intel Management Engine (Intel ME) provides Manageability, Security and Media services for system containing Intel chipsets. if selected /dev/mei misc device will be created. + For more information see + + +config INTEL_MEI_ME + bool "ME Enabled Intel Chipsets" + depends on INTEL_MEI + depends on X86 && PCI && WATCHDOG_CORE + default y + help + MEI support for ME Enabled Intel chipsets. + Supported Chipsets are: 7 Series Chipset Family 6 Series Chipset Family @@ -24,5 +35,3 @@ config INTEL_MEI 82Q33 Express 82X38/X48 Express - For more information see - 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 mei-objs := init.o mei-objs += hbm.o mei-objs += interrupt.o -mei-objs += hw-me.o +mei-objs += client.o mei-objs += main.o mei-objs += amthif.o mei-objs += wd.o -mei-objs += client.o -mei-objs += pci-me.o +mei-$(CONFIG_INTEL_MEI_ME) += pci-me.o +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) if (ret && dev->mei_host_buffer_is_empty) { ret = 0; dev->mei_host_buffer_is_empty = false; - if (cb->request_buffer.size > mei_hbuf_max_data(dev)) { - mei_hdr.length = mei_hbuf_max_data(dev); + if (cb->request_buffer.size > mei_hbuf_max_len(dev)) { + mei_hdr.length = mei_hbuf_max_len(dev); mei_hdr.msg_complete = 0; } else { mei_hdr.length = cb->request_buffer.size; @@ -583,7 +583,7 @@ int mei_amthif_irq_read(struct mei_device *dev, s32 *slots) dev->iamthif_msg_buf_index = 0; dev->iamthif_msg_buf_size = 0; dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER; - dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev); + dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev); return 0; } 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, * * returns ME_CB_RW register value (u32) */ -u32 mei_mecbrw_read(const struct mei_device *dev) +static u32 mei_me_mecbrw_read(const struct mei_device *dev) { return mei_reg_read(to_me_hw(dev), ME_CB_RW); } @@ -102,7 +102,7 @@ static inline void mei_hcsr_set(struct mei_me_hw *hw, u32 hcsr) * * @dev: mei device */ -void mei_hw_config(struct mei_device *dev) +static void mei_me_hw_config(struct mei_device *dev) { u32 hcsr = mei_hcsr_read(to_me_hw(dev)); /* Doesn't change in runtime */ @@ -113,20 +113,19 @@ void mei_hw_config(struct mei_device *dev) * * @dev: the device structure */ -void mei_clear_interrupts(struct mei_device *dev) +static void mei_me_intr_clear(struct mei_device *dev) { struct mei_me_hw *hw = to_me_hw(dev); u32 hcsr = mei_hcsr_read(hw); if ((hcsr & H_IS) == H_IS) mei_reg_write(hw, H_CSR, hcsr); } - /** - * mei_enable_interrupts - enables mei device interrupts + * mei_me_intr_enable - enables mei device interrupts * * @dev: the device structure */ -void mei_enable_interrupts(struct mei_device *dev) +static void mei_me_intr_enable(struct mei_device *dev) { struct mei_me_hw *hw = to_me_hw(dev); u32 hcsr = mei_hcsr_read(hw); @@ -139,7 +138,7 @@ void mei_enable_interrupts(struct mei_device *dev) * * @dev: the device structure */ -void mei_disable_interrupts(struct mei_device *dev) +static void mei_me_intr_disable(struct mei_device *dev) { struct mei_me_hw *hw = to_me_hw(dev); u32 hcsr = mei_hcsr_read(hw); @@ -148,12 +147,12 @@ void mei_disable_interrupts(struct mei_device *dev) } /** - * mei_hw_reset - resets fw via mei csr register. + * mei_me_hw_reset - resets fw via mei csr register. * * @dev: the device structure * @interrupts_enabled: if interrupt should be enabled after reset. */ -void mei_hw_reset(struct mei_device *dev, bool intr_enable) +static void mei_me_hw_reset(struct mei_device *dev, bool intr_enable) { struct mei_me_hw *hw = to_me_hw(dev); u32 hcsr = mei_hcsr_read(hw); @@ -180,25 +179,25 @@ void mei_hw_reset(struct mei_device *dev, bool intr_enable) } /** - * mei_host_set_ready - enable device + * mei_me_host_set_ready - enable device * * @dev - mei device * returns bool */ -void mei_host_set_ready(struct mei_device *dev) +static void mei_me_host_set_ready(struct mei_device *dev) { struct mei_me_hw *hw = to_me_hw(dev); hw->host_hw_state |= H_IE | H_IG | H_RDY; mei_hcsr_set(hw, hw->host_hw_state); } /** - * mei_host_is_ready - check whether the host has turned ready + * mei_me_host_is_ready - check whether the host has turned ready * * @dev - mei device * returns bool */ -bool mei_host_is_ready(struct mei_device *dev) +static bool mei_me_host_is_ready(struct mei_device *dev) { struct mei_me_hw *hw = to_me_hw(dev); hw->host_hw_state = mei_hcsr_read(hw); @@ -206,12 +205,12 @@ bool mei_host_is_ready(struct mei_device *dev) } /** - * mei_me_is_ready - check whether the me has turned ready + * mei_me_hw_is_ready - check whether the me(hw) has turned ready * * @dev - mei device * returns bool */ -bool mei_me_is_ready(struct mei_device *dev) +static bool mei_me_hw_is_ready(struct mei_device *dev) { struct mei_me_hw *hw = to_me_hw(dev); hw->me_hw_state = mei_mecsr_read(hw); @@ -268,19 +267,19 @@ static unsigned char mei_hbuf_filled_slots(struct mei_device *dev) * * returns true if empty, false - otherwise. */ -bool mei_hbuf_is_empty(struct mei_device *dev) +static bool mei_me_hbuf_is_empty(struct mei_device *dev) { return mei_hbuf_filled_slots(dev) == 0; } /** - * mei_hbuf_empty_slots - counts write empty slots. + * mei_me_hbuf_empty_slots - counts write empty slots. * * @dev: the device structure * * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count */ -int mei_hbuf_empty_slots(struct mei_device *dev) +static int mei_me_hbuf_empty_slots(struct mei_device *dev) { unsigned char filled_slots, empty_slots; @@ -294,6 +293,12 @@ int mei_hbuf_empty_slots(struct mei_device *dev) return empty_slots; } +static size_t mei_me_hbuf_max_len(const struct mei_device *dev) +{ + return dev->hbuf_depth * sizeof(u32) - sizeof(struct mei_msg_hdr); +} + + /** * mei_write_message - writes a message to mei device. * @@ -303,8 +308,9 @@ int mei_hbuf_empty_slots(struct mei_device *dev) * * This function returns -EIO if write has failed */ -int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header, - unsigned char *buf) +static int mei_me_write_message(struct mei_device *dev, + struct mei_msg_hdr *header, + unsigned char *buf) { struct mei_me_hw *hw = to_me_hw(dev); unsigned long rem, dw_cnt; @@ -337,20 +343,20 @@ int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header, hcsr = mei_hcsr_read(hw) | H_IG; mei_hcsr_set(hw, hcsr); - if (!mei_me_is_ready(dev)) + if (!mei_me_hw_is_ready(dev)) return -EIO; return 0; } /** - * mei_count_full_read_slots - counts read full slots. + * mei_me_count_full_read_slots - counts read full slots. * * @dev: the device structure * * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise filled slots count */ -int mei_count_full_read_slots(struct mei_device *dev) +static int mei_me_count_full_read_slots(struct mei_device *dev) { struct mei_me_hw *hw = to_me_hw(dev); char read_ptr, write_ptr; @@ -371,13 +377,13 @@ int mei_count_full_read_slots(struct mei_device *dev) } /** - * mei_read_slots - reads a message from mei device. + * mei_me_read_slots - reads a message from mei device. * * @dev: the device structure * @buffer: message buffer will be written * @buffer_length: message size will be read */ -void mei_read_slots(struct mei_device *dev, unsigned char *buffer, +static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer, unsigned long buffer_length) { struct mei_me_hw *hw = to_me_hw(dev); @@ -385,17 +391,42 @@ void mei_read_slots(struct mei_device *dev, unsigned char *buffer, u32 hcsr; for (; buffer_length >= sizeof(u32); buffer_length -= sizeof(u32)) - *reg_buf++ = mei_mecbrw_read(dev); + *reg_buf++ = mei_me_mecbrw_read(dev); if (buffer_length > 0) { - u32 reg = mei_mecbrw_read(dev); + u32 reg = mei_me_mecbrw_read(dev); memcpy(reg_buf, ®, buffer_length); } hcsr = mei_hcsr_read(hw) | H_IG; mei_hcsr_set(hw, hcsr); + return 0; } +static const struct mei_hw_ops mei_me_hw_ops = { + + .host_set_ready = mei_me_host_set_ready, + .host_is_ready = mei_me_host_is_ready, + + .hw_is_ready = mei_me_hw_is_ready, + .hw_reset = mei_me_hw_reset, + .hw_config = mei_me_hw_config, + + .intr_clear = mei_me_intr_clear, + .intr_enable = mei_me_intr_enable, + .intr_disable = mei_me_intr_disable, + + .hbuf_free_slots = mei_me_hbuf_empty_slots, + .hbuf_is_ready = mei_me_hbuf_is_empty, + .hbuf_max_len = mei_me_hbuf_max_len, + + .write = mei_me_write_message, + + .rdbuf_full_slots = mei_me_count_full_read_slots, + .read_hdr = mei_me_mecbrw_read, + .read = mei_me_read_slots +}; + /** * init_mei_device - allocates and initializes the mei device structure * @@ -422,6 +453,8 @@ struct mei_device *mei_me_dev_init(struct pci_dev *pdev) INIT_DELAYED_WORK(&dev->timer_work, mei_timer); INIT_WORK(&dev->init_work, mei_host_client_init); + dev->ops = &mei_me_hw_ops; + dev->pdev = pdev; return dev; } 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 { struct mei_device *mei_me_dev_init(struct pci_dev *pdev); -void mei_read_slots(struct mei_device *dev, - unsigned char *buffer, - unsigned long buffer_length); - -int mei_write_message(struct mei_device *dev, - struct mei_msg_hdr *header, - unsigned char *buf); - -bool mei_hbuf_is_empty(struct mei_device *dev); - -int mei_hbuf_empty_slots(struct mei_device *dev); - -static inline size_t mei_hbuf_max_data(const struct mei_device *dev) -{ - return dev->hbuf_depth * sizeof(u32) - sizeof(struct mei_msg_hdr); -} - /* get slots (dwords) from a message length + header (bytes) */ static inline unsigned char mei_data2slots(size_t length) { return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4); } -int mei_count_full_read_slots(struct mei_device *dev); - #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) goto err; } - if (!mei_me_is_ready(dev)) { + if (!mei_hw_is_ready(dev)) { dev_err(&dev->pdev->dev, "ME is not ready.\n"); goto err; } 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, int ret = 0; if (!dev->rd_msg_hdr) { - dev->rd_msg_hdr = mei_mecbrw_read(dev); + dev->rd_msg_hdr = mei_read_hdr(dev); dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); (*slots)--; dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); @@ -430,7 +430,7 @@ static int mei_irq_thread_write_handler(struct mei_device *dev, s32 slots; int ret; - if (!mei_hbuf_is_empty(dev)) { + if (!mei_hbuf_is_ready(dev)) { dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n"); return 0; } @@ -698,7 +698,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) mei_clear_interrupts(dev); /* check if ME wants a reset */ - if (!mei_me_is_ready(dev) && + if (!mei_hw_is_ready(dev) && dev->dev_state != MEI_DEV_RESETING && dev->dev_state != MEI_DEV_INITIALIZING) { dev_dbg(&dev->pdev->dev, "FW not ready.\n"); @@ -709,7 +709,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) /* check if we need to start the dev */ if (!mei_host_is_ready(dev)) { - if (mei_me_is_ready(dev)) { + if (mei_hw_is_ready(dev)) { dev_dbg(&dev->pdev->dev, "we need to start the dev.\n"); mei_host_set_ready(dev); @@ -743,7 +743,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) rets = mei_irq_thread_write_handler(dev, &complete_list); end: dev_dbg(&dev->pdev->dev, "end of bottom half function.\n"); - dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev); + dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev); bus_message_received = false; 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, } dev->mei_host_buffer_is_empty = false; - if (length > mei_hbuf_max_data(dev)) { - mei_hdr.length = mei_hbuf_max_data(dev); + if (length > mei_hbuf_max_len(dev)) { + mei_hdr.length = mei_hbuf_max_len(dev); mei_hdr.msg_complete = 0; } else { mei_hdr.length = length; @@ -765,4 +765,5 @@ void mei_deregister(void) mei_misc_device.parent = NULL; } +MODULE_LICENSE("GPL v2"); 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 { struct mei_cl_cb *read_cb; }; +/** struct mei_hw_ops + * + * @host_set_ready - notify FW that host side is ready + * @host_is_ready - query for host readiness + + * @hw_is_ready - query if hw is ready + * @hw_reset - reset hw + * @hw_config - configure hw + + * @intr_clear - clear pending interrupts + * @intr_enable - enable interrupts + * @intr_disable - disable interrupts + + * @hbuf_free_slots - query for write buffer empty slots + * @hbuf_is_ready - query if write buffer is empty + * @hbuf_max_len - query for write buffer max len + + * @write - write a message to FW + + * @rdbuf_full_slots - query how many slots are filled + + * @read_hdr - get first 4 bytes (header) + * @read - read a buffer from the FW + */ +struct mei_hw_ops { + + void (*host_set_ready) (struct mei_device *dev); + bool (*host_is_ready) (struct mei_device *dev); + + bool (*hw_is_ready) (struct mei_device *dev); + void (*hw_reset) (struct mei_device *dev, bool enable); + void (*hw_config) (struct mei_device *dev); + + void (*intr_clear) (struct mei_device *dev); + void (*intr_enable) (struct mei_device *dev); + void (*intr_disable) (struct mei_device *dev); + + int (*hbuf_free_slots) (struct mei_device *dev); + bool (*hbuf_is_ready) (struct mei_device *dev); + size_t (*hbuf_max_len) (const struct mei_device *dev); + + int (*write)(struct mei_device *dev, + struct mei_msg_hdr *hdr, + unsigned char *buf); + + int (*rdbuf_full_slots)(struct mei_device *dev); + + u32 (*read_hdr)(const struct mei_device *dev); + int (*read) (struct mei_device *dev, + unsigned char *buf, unsigned long len); +}; + /** * struct mei_device - MEI private device struct * @mem_addr - mem mapped base register address @@ -306,6 +358,8 @@ struct mei_device { bool iamthif_canceled; struct work_struct init_work; + + const struct mei_hw_ops *ops; char hw[0] __aligned(sizeof(void *)); }; @@ -376,26 +430,84 @@ void mei_watchdog_register(struct mei_device *dev); */ void mei_watchdog_unregister(struct mei_device *dev); - /* * Register Access Function */ -void mei_hw_config(struct mei_device *dev); -void mei_hw_reset(struct mei_device *dev, bool intr_enable); -u32 mei_mecbrw_read(const struct mei_device *dev); +static inline void mei_hw_config(struct mei_device *dev) +{ + dev->ops->hw_config(dev); +} +static inline void mei_hw_reset(struct mei_device *dev, bool enable) +{ + dev->ops->hw_reset(dev, enable); +} + +static inline void mei_clear_interrupts(struct mei_device *dev) +{ + dev->ops->intr_clear(dev); +} + +static inline void mei_enable_interrupts(struct mei_device *dev) +{ + dev->ops->intr_enable(dev); +} +static inline void mei_disable_interrupts(struct mei_device *dev) +{ + dev->ops->intr_disable(dev); +} +static inline void mei_host_set_ready(struct mei_device *dev) +{ + dev->ops->host_set_ready(dev); +} +static inline bool mei_host_is_ready(struct mei_device *dev) +{ + return dev->ops->host_is_ready(dev); +} +static inline bool mei_hw_is_ready(struct mei_device *dev) +{ + return dev->ops->hw_is_ready(dev); +} -void mei_clear_interrupts(struct mei_device *dev); -void mei_enable_interrupts(struct mei_device *dev); -void mei_disable_interrupts(struct mei_device *dev); +static inline bool mei_hbuf_is_ready(struct mei_device *dev) +{ + return dev->ops->hbuf_is_ready(dev); +} -void mei_host_set_ready(struct mei_device *dev); -bool mei_host_is_ready(struct mei_device *dev); -bool mei_me_is_ready(struct mei_device *dev); +static inline int mei_hbuf_empty_slots(struct mei_device *dev) +{ + return dev->ops->hbuf_free_slots(dev); +} +static inline size_t mei_hbuf_max_len(const struct mei_device *dev) +{ + return dev->ops->hbuf_max_len(dev); +} +static inline int mei_write_message(struct mei_device *dev, + struct mei_msg_hdr *hdr, + unsigned char *buf) +{ + return dev->ops->write(dev, hdr, buf); +} + +static inline u32 mei_read_hdr(const struct mei_device *dev) +{ + return dev->ops->read_hdr(dev); +} + +static inline void mei_read_slots(struct mei_device *dev, + unsigned char *buf, unsigned long len) +{ + dev->ops->read(dev, buf, len); +} + +static inline int mei_count_full_read_slots(struct mei_device *dev) +{ + return dev->ops->rdbuf_full_slots(dev); +} int mei_register(struct device *dev); void mei_deregister(void); -- cgit v1.2.3 From 06ecd6459800962155c485e27d9dd30268b579bf Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 6 Feb 2013 14:06:42 +0200 Subject: mei: move interrupt handlers to be me hw specific interrupt handler are platform specifics so we move them to hw-mei.c. For sake of that we need to export write, read, and complete handlers from the interrupt.c Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.c | 164 ++++++++++++++++++++++++++++++++++++------- drivers/misc/mei/hw-me.h | 3 + drivers/misc/mei/interrupt.c | 126 +++------------------------------ drivers/misc/mei/mei_dev.h | 9 ++- drivers/misc/mei/pci-me.c | 12 ++-- 5 files changed, 164 insertions(+), 150 deletions(-) (limited to 'drivers/misc/mei/hw-me.c') diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 6300943497ae..3bebf8d85ff9 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -15,11 +15,16 @@ */ #include -#include + +#include +#include #include "mei_dev.h" #include "hw-me.h" +#include "hbm.h" + + /** * mei_reg_read - Reads 32bit data from the mei device * @@ -217,29 +222,6 @@ static bool mei_me_hw_is_ready(struct mei_device *dev) return (hw->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA; } -/** - * mei_interrupt_quick_handler - The ISR of the MEI device - * - * @irq: The irq number - * @dev_id: pointer to the device structure - * - * returns irqreturn_t - */ -irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id) -{ - struct mei_device *dev = (struct mei_device *) dev_id; - struct mei_me_hw *hw = to_me_hw(dev); - u32 csr_reg = mei_hcsr_read(hw); - - if ((csr_reg & H_IS) != H_IS) - return IRQ_NONE; - - /* clear H_IS bit in H_CSR */ - mei_reg_write(hw, H_CSR, csr_reg); - - return IRQ_WAKE_THREAD; -} - /** * mei_hbuf_filled_slots - gets number of device filled buffer slots * @@ -403,6 +385,139 @@ static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer, return 0; } +/** + * mei_me_irq_quick_handler - The ISR of the MEI device + * + * @irq: The irq number + * @dev_id: pointer to the device structure + * + * returns irqreturn_t + */ + +irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id) +{ + struct mei_device *dev = (struct mei_device *) dev_id; + struct mei_me_hw *hw = to_me_hw(dev); + u32 csr_reg = mei_hcsr_read(hw); + + if ((csr_reg & H_IS) != H_IS) + return IRQ_NONE; + + /* clear H_IS bit in H_CSR */ + mei_reg_write(hw, H_CSR, csr_reg); + + return IRQ_WAKE_THREAD; +} + +/** + * mei_me_irq_thread_handler - function called after ISR to handle the interrupt + * processing. + * + * @irq: The irq number + * @dev_id: pointer to the device structure + * + * returns irqreturn_t + * + */ +irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) +{ + struct mei_device *dev = (struct mei_device *) dev_id; + struct mei_cl_cb complete_list; + struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL; + struct mei_cl *cl; + s32 slots; + int rets; + bool bus_message_received; + + + dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n"); + /* initialize our complete list */ + mutex_lock(&dev->device_lock); + mei_io_list_init(&complete_list); + + /* Ack the interrupt here + * In case of MSI we don't go through the quick handler */ + if (pci_dev_msi_enabled(dev->pdev)) + mei_clear_interrupts(dev); + + /* check if ME wants a reset */ + if (!mei_hw_is_ready(dev) && + dev->dev_state != MEI_DEV_RESETING && + dev->dev_state != MEI_DEV_INITIALIZING) { + dev_dbg(&dev->pdev->dev, "FW not ready.\n"); + mei_reset(dev, 1); + mutex_unlock(&dev->device_lock); + return IRQ_HANDLED; + } + + /* check if we need to start the dev */ + if (!mei_host_is_ready(dev)) { + if (mei_hw_is_ready(dev)) { + dev_dbg(&dev->pdev->dev, "we need to start the dev.\n"); + + mei_host_set_ready(dev); + + dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n"); + /* link is established * start sending messages. */ + + dev->dev_state = MEI_DEV_INIT_CLIENTS; + + mei_hbm_start_req(dev); + mutex_unlock(&dev->device_lock); + return IRQ_HANDLED; + } else { + dev_dbg(&dev->pdev->dev, "FW not ready.\n"); + mutex_unlock(&dev->device_lock); + return IRQ_HANDLED; + } + } + /* check slots available for reading */ + slots = mei_count_full_read_slots(dev); + while (slots > 0) { + /* we have urgent data to send so break the read */ + if (dev->wr_ext_msg.hdr.length) + break; + dev_dbg(&dev->pdev->dev, "slots =%08x\n", slots); + dev_dbg(&dev->pdev->dev, "call mei_irq_read_handler.\n"); + rets = mei_irq_read_handler(dev, &complete_list, &slots); + if (rets) + goto end; + } + rets = mei_irq_write_handler(dev, &complete_list); +end: + dev_dbg(&dev->pdev->dev, "end of bottom half function.\n"); + dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev); + + bus_message_received = false; + if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) { + dev_dbg(&dev->pdev->dev, "received waiting bus message\n"); + bus_message_received = true; + } + mutex_unlock(&dev->device_lock); + if (bus_message_received) { + dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n"); + wake_up_interruptible(&dev->wait_recvd_msg); + bus_message_received = false; + } + if (list_empty(&complete_list.list)) + return IRQ_HANDLED; + + + list_for_each_entry_safe(cb_pos, cb_next, &complete_list.list, list) { + cl = cb_pos->cl; + list_del(&cb_pos->list); + if (cl) { + if (cl != &dev->iamthif_cl) { + dev_dbg(&dev->pdev->dev, "completing call back.\n"); + mei_irq_complete_handler(cl, cb_pos); + cb_pos = NULL; + } else if (cl == &dev->iamthif_cl) { + mei_amthif_complete(dev, cb_pos); + } + } + } + return IRQ_HANDLED; +} static const struct mei_hw_ops mei_me_hw_ops = { .host_set_ready = mei_me_host_set_ready, @@ -458,3 +573,4 @@ struct mei_device *mei_me_dev_init(struct pci_dev *pdev) dev->pdev = pdev; return dev; } + diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h index 9a3aaab9bcf0..8518d3eeb838 100644 --- a/drivers/misc/mei/hw-me.h +++ b/drivers/misc/mei/hw-me.h @@ -42,4 +42,7 @@ static inline unsigned char mei_data2slots(size_t length) return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4); } +irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id); +irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id); + #endif /* _MEI_INTERFACE_H_ */ diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 431aa91fd002..3535b2676c97 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -30,12 +30,12 @@ /** - * _mei_cmpl - processes completed operation. + * mei_complete_handler - processes completed operation. * * @cl: private data of the file object. * @cb_pos: callback block. */ -static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos) +void mei_irq_complete_handler(struct mei_cl *cl, struct mei_cl_cb *cb_pos) { if (cb_pos->fop_type == MEI_FOP_WRITE) { mei_io_cb_free(cb_pos); @@ -313,15 +313,14 @@ static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots, * mei_irq_thread_read_handler - bottom half read routine after ISR to * handle the read processing. * - * @cmpl_list: An instance of our list structure * @dev: the device structure + * @cmpl_list: An instance of our list structure * @slots: slots to read. * * returns 0 on success, <0 on failure. */ -static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list, - struct mei_device *dev, - s32 *slots) +int mei_irq_read_handler(struct mei_device *dev, + struct mei_cl_cb *cmpl_list, s32 *slots) { struct mei_msg_hdr *mei_hdr; struct mei_cl *cl_pos = NULL; @@ -412,15 +411,15 @@ end: /** - * mei_irq_thread_write_handler - bottom half write routine after - * ISR to handle the write processing. + * mei_irq_write_handler - dispatch write requests + * after irq received * * @dev: the device structure * @cmpl_list: An instance of our list structure * * returns 0 on success, <0 on failure. */ -static int mei_irq_thread_write_handler(struct mei_device *dev, +int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list) { @@ -666,112 +665,3 @@ out: mutex_unlock(&dev->device_lock); } -/** - * mei_interrupt_thread_handler - function called after ISR to handle the interrupt - * processing. - * - * @irq: The irq number - * @dev_id: pointer to the device structure - * - * returns irqreturn_t - * - */ -irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) -{ - struct mei_device *dev = (struct mei_device *) dev_id; - struct mei_cl_cb complete_list; - struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL; - struct mei_cl *cl; - s32 slots; - int rets; - bool bus_message_received; - - - dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n"); - /* initialize our complete list */ - mutex_lock(&dev->device_lock); - mei_io_list_init(&complete_list); - - /* Ack the interrupt here - * In case of MSI we don't go through the quick handler */ - if (pci_dev_msi_enabled(dev->pdev)) - mei_clear_interrupts(dev); - - /* check if ME wants a reset */ - if (!mei_hw_is_ready(dev) && - dev->dev_state != MEI_DEV_RESETING && - dev->dev_state != MEI_DEV_INITIALIZING) { - dev_dbg(&dev->pdev->dev, "FW not ready.\n"); - mei_reset(dev, 1); - mutex_unlock(&dev->device_lock); - return IRQ_HANDLED; - } - - /* check if we need to start the dev */ - if (!mei_host_is_ready(dev)) { - if (mei_hw_is_ready(dev)) { - dev_dbg(&dev->pdev->dev, "we need to start the dev.\n"); - - mei_host_set_ready(dev); - - dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n"); - /* link is established * start sending messages. */ - - dev->dev_state = MEI_DEV_INIT_CLIENTS; - - mei_hbm_start_req(dev); - mutex_unlock(&dev->device_lock); - return IRQ_HANDLED; - } else { - dev_dbg(&dev->pdev->dev, "FW not ready.\n"); - mutex_unlock(&dev->device_lock); - return IRQ_HANDLED; - } - } - /* check slots available for reading */ - slots = mei_count_full_read_slots(dev); - while (slots > 0) { - /* we have urgent data to send so break the read */ - if (dev->wr_ext_msg.hdr.length) - break; - dev_dbg(&dev->pdev->dev, "slots =%08x\n", slots); - dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n"); - rets = mei_irq_thread_read_handler(&complete_list, dev, &slots); - if (rets) - goto end; - } - rets = mei_irq_thread_write_handler(dev, &complete_list); -end: - dev_dbg(&dev->pdev->dev, "end of bottom half function.\n"); - dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev); - - bus_message_received = false; - if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) { - dev_dbg(&dev->pdev->dev, "received waiting bus message\n"); - bus_message_received = true; - } - mutex_unlock(&dev->device_lock); - if (bus_message_received) { - dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n"); - wake_up_interruptible(&dev->wait_recvd_msg); - bus_message_received = false; - } - if (list_empty(&complete_list.list)) - return IRQ_HANDLED; - - - list_for_each_entry_safe(cb_pos, cb_next, &complete_list.list, list) { - cl = cb_pos->cl; - list_del(&cb_pos->list); - if (cl) { - if (cl != &dev->iamthif_cl) { - dev_dbg(&dev->pdev->dev, "completing call back.\n"); - _mei_cmpl(cl, cb_pos); - cb_pos = NULL; - } else if (cl == &dev->iamthif_cl) { - mei_amthif_complete(dev, cb_pos); - } - } - } - return IRQ_HANDLED; -} diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index c974292f16d6..7d07cef75664 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -379,9 +379,14 @@ int mei_hw_init(struct mei_device *dev); /* * MEI interrupt functions prototype */ -irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id); -irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id); + void mei_timer(struct work_struct *work); +int mei_irq_read_handler(struct mei_device *dev, + struct mei_cl_cb *cmpl_list, s32 *slots); + +int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list); + +void mei_irq_complete_handler(struct mei_cl *cl, struct mei_cl_cb *cb_pos); /* * AMTHIF - AMT Host Interface Functions diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 27ac71767981..b40ec0601ab0 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -170,12 +170,12 @@ static int mei_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (pci_dev_msi_enabled(pdev)) err = request_threaded_irq(pdev->irq, NULL, - mei_interrupt_thread_handler, + mei_me_irq_thread_handler, IRQF_ONESHOT, KBUILD_MODNAME, dev); else err = request_threaded_irq(pdev->irq, - mei_interrupt_quick_handler, - mei_interrupt_thread_handler, + mei_me_irq_quick_handler, + mei_me_irq_thread_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (err) { @@ -348,12 +348,12 @@ static int mei_pci_resume(struct device *device) if (pci_dev_msi_enabled(pdev)) err = request_threaded_irq(pdev->irq, NULL, - mei_interrupt_thread_handler, + mei_me_irq_thread_handler, IRQF_ONESHOT, KBUILD_MODNAME, dev); else err = request_threaded_irq(pdev->irq, - mei_interrupt_quick_handler, - mei_interrupt_thread_handler, + mei_me_irq_quick_handler, + mei_me_irq_thread_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (err) { -- cgit v1.2.3 From 330dd7da5ec80e2c49c66bf353d8b4fa4fb8f5a9 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 6 Feb 2013 14:06:43 +0200 Subject: mei: rename to mei_host_buffer_is_empty to hbuf_is_ready we rename the mei_host_buffer_is_empty to keep naming convention of hbuf and also make the query more generic to be correct also for other under laying hardware Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 8 ++++---- drivers/misc/mei/client.c | 13 ++++++------- drivers/misc/mei/hw-me.c | 2 +- drivers/misc/mei/main.c | 4 ++-- drivers/misc/mei/mei_dev.h | 14 ++++++++++---- drivers/misc/mei/wd.c | 9 ++++----- 6 files changed, 27 insertions(+), 23 deletions(-) (limited to 'drivers/misc/mei/hw-me.c') diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index a7c483850083..c86d7e3839a4 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -297,9 +297,9 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb) if (ret < 0) return ret; - if (ret && dev->mei_host_buffer_is_empty) { + if (ret && dev->hbuf_is_ready) { ret = 0; - dev->mei_host_buffer_is_empty = false; + dev->hbuf_is_ready = false; if (cb->request_buffer.size > mei_hbuf_max_len(dev)) { mei_hdr.length = mei_hbuf_max_len(dev); mei_hdr.msg_complete = 0; @@ -330,7 +330,7 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb) list_add_tail(&cb->list, &dev->write_list.list); } } else { - if (!(dev->mei_host_buffer_is_empty)) + if (!dev->hbuf_is_ready) dev_dbg(&dev->pdev->dev, "host buffer is not empty"); dev_dbg(&dev->pdev->dev, "No flow control credentials, so add iamthif cb to write list.\n"); @@ -583,7 +583,7 @@ int mei_amthif_irq_read(struct mei_device *dev, s32 *slots) dev->iamthif_msg_buf_index = 0; dev->iamthif_msg_buf_size = 0; dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER; - dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev); + dev->hbuf_is_ready = mei_hbuf_is_ready(dev); return 0; } diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index a921001053ba..e46663ee76de 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -393,8 +393,8 @@ int mei_cl_disconnect(struct mei_cl *cl) return -ENOMEM; cb->fop_type = MEI_FOP_CLOSE; - if (dev->mei_host_buffer_is_empty) { - dev->mei_host_buffer_is_empty = false; + if (dev->hbuf_is_ready) { + dev->hbuf_is_ready = false; if (mei_hbm_cl_disconnect_req(dev, cl)) { rets = -ENODEV; dev_err(&dev->pdev->dev, "failed to disconnect.\n"); @@ -496,9 +496,8 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file) cb->fop_type = MEI_FOP_IOCTL; - if (dev->mei_host_buffer_is_empty && - !mei_cl_is_other_connecting(cl)) { - dev->mei_host_buffer_is_empty = false; + if (dev->hbuf_is_ready && !mei_cl_is_other_connecting(cl)) { + dev->hbuf_is_ready = false; if (mei_hbm_cl_connect_req(dev, cl)) { rets = -ENODEV; @@ -661,8 +660,8 @@ int mei_cl_read_start(struct mei_cl *cl) cb->fop_type = MEI_FOP_READ; cl->read_cb = cb; - if (dev->mei_host_buffer_is_empty) { - dev->mei_host_buffer_is_empty = false; + if (dev->hbuf_is_ready) { + dev->hbuf_is_ready = false; if (mei_hbm_cl_flow_control_req(dev, cl)) { rets = -ENODEV; goto err; diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 3bebf8d85ff9..45ea7185c003 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -486,7 +486,7 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) rets = mei_irq_write_handler(dev, &complete_list); end: dev_dbg(&dev->pdev->dev, "end of bottom half function.\n"); - dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev); + dev->hbuf_is_ready = mei_hbuf_is_ready(dev); bus_message_received = false; 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 843ae2febc70..903f809b21f7 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -454,14 +454,14 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, if (rets < 0) goto err; - if (rets == 0 || dev->mei_host_buffer_is_empty == false) { + if (rets == 0 || !dev->hbuf_is_ready) { write_cb->buf_idx = 0; mei_hdr.msg_complete = 0; cl->writing_state = MEI_WRITING; goto out; } - dev->mei_host_buffer_is_empty = false; + dev->hbuf_is_ready = false; if (length > mei_hbuf_max_len(dev)) { mei_hdr.length = mei_hbuf_max_len(dev); mei_hdr.msg_complete = 0; diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 7d07cef75664..cb80166161f0 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -265,9 +265,13 @@ struct mei_hw_ops { /** * struct mei_device - MEI private device struct + * @mem_addr - mem mapped base register address - * @hbuf_depth - depth of host(write) buffer - * @wr_ext_msg - buffer for hbm control responses (set in read cycle) + + * @hbuf_depth - depth of hardware host/write buffer is slots + * @hbuf_is_ready - query if the host host/write buffer is ready + * @wr_msg - the buffer for hbm control messages + * @wr_ext_msg - the buffer for hbm control responses (set in read cycle) */ struct mei_device { struct pci_dev *pdev; /* pointer to pci device struct */ @@ -294,7 +298,6 @@ struct mei_device { struct delayed_work timer_work; /* MEI timer delayed work (timeouts) */ bool recvd_msg; - u8 hbuf_depth; /* * waiting queue for receive message from FW */ @@ -311,6 +314,10 @@ struct mei_device { unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; /* control messages */ u32 rd_msg_hdr; + /* write buffer */ + u8 hbuf_depth; + bool hbuf_is_ready; + /* used for control messages */ struct { struct mei_msg_hdr hdr; @@ -330,7 +337,6 @@ struct mei_device { u8 me_clients_num; u8 me_client_presentation_num; u8 me_client_index; - bool mei_host_buffer_is_empty; struct mei_cl wd_cl; enum mei_wd_states wd_state; diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c index 77b3820380b0..2413247fc392 100644 --- a/drivers/misc/mei/wd.c +++ b/drivers/misc/mei/wd.c @@ -157,9 +157,9 @@ int mei_wd_stop(struct mei_device *dev) if (ret < 0) goto out; - if (ret && dev->mei_host_buffer_is_empty) { + if (ret && dev->hbuf_is_ready) { ret = 0; - dev->mei_host_buffer_is_empty = false; + dev->hbuf_is_ready = false; if (!mei_wd_send(dev)) { ret = mei_cl_flow_ctrl_reduce(&dev->wd_cl); @@ -282,10 +282,9 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev) dev->wd_state = MEI_WD_RUNNING; /* Check if we can send the ping to HW*/ - if (dev->mei_host_buffer_is_empty && - mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) { + if (dev->hbuf_is_ready && mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) { - dev->mei_host_buffer_is_empty = false; + dev->hbuf_is_ready = false; dev_dbg(&dev->pdev->dev, "wd: sending ping\n"); if (mei_wd_send(dev)) { -- cgit v1.2.3