diff options
Diffstat (limited to 'drivers/misc/mei/interface.c')
| -rw-r--r-- | drivers/misc/mei/interface.c | 85 | 
1 files changed, 32 insertions, 53 deletions
| diff --git a/drivers/misc/mei/interface.c b/drivers/misc/mei/interface.c index 428d21e36416..509c3957ff45 100644 --- a/drivers/misc/mei/interface.c +++ b/drivers/misc/mei/interface.c | |||
| @@ -58,16 +58,18 @@ void mei_disable_interrupts(struct mei_device *dev) | |||
| 58 | } | 58 | } | 
| 59 | 59 | ||
| 60 | /** | 60 | /** | 
| 61 | * _host_get_filled_slots - gets number of device filled buffer slots | 61 | * mei_hbuf_filled_slots - gets number of device filled buffer slots | 
| 62 | * | 62 | * | 
| 63 | * @device: the device structure | 63 | * @device: the device structure | 
| 64 | * | 64 | * | 
| 65 | * returns number of filled slots | 65 | * returns number of filled slots | 
| 66 | */ | 66 | */ | 
| 67 | static unsigned char _host_get_filled_slots(const struct mei_device *dev) | 67 | static unsigned char mei_hbuf_filled_slots(struct mei_device *dev) | 
| 68 | { | 68 | { | 
| 69 | char read_ptr, write_ptr; | 69 | char read_ptr, write_ptr; | 
| 70 | 70 | ||
| 71 | dev->host_hw_state = mei_hcsr_read(dev); | ||
| 72 | |||
| 71 | read_ptr = (char) ((dev->host_hw_state & H_CBRP) >> 8); | 73 | read_ptr = (char) ((dev->host_hw_state & H_CBRP) >> 8); | 
| 72 | write_ptr = (char) ((dev->host_hw_state & H_CBWP) >> 16); | 74 | write_ptr = (char) ((dev->host_hw_state & H_CBWP) >> 16); | 
| 73 | 75 | ||
| @@ -75,43 +77,33 @@ static unsigned char _host_get_filled_slots(const struct mei_device *dev) | |||
| 75 | } | 77 | } | 
| 76 | 78 | ||
| 77 | /** | 79 | /** | 
| 78 | * mei_host_buffer_is_empty - checks if host buffer is empty. | 80 | * mei_hbuf_is_empty - checks if host buffer is empty. | 
| 79 | * | 81 | * | 
| 80 | * @dev: the device structure | 82 | * @dev: the device structure | 
| 81 | * | 83 | * | 
| 82 | * returns 1 if empty, 0 - otherwise. | 84 | * returns true if empty, false - otherwise. | 
| 83 | */ | 85 | */ | 
| 84 | int mei_host_buffer_is_empty(struct mei_device *dev) | 86 | bool mei_hbuf_is_empty(struct mei_device *dev) | 
| 85 | { | 87 | { | 
| 86 | unsigned char filled_slots; | 88 | return mei_hbuf_filled_slots(dev) == 0; | 
| 87 | |||
| 88 | dev->host_hw_state = mei_hcsr_read(dev); | ||
| 89 | filled_slots = _host_get_filled_slots(dev); | ||
| 90 | |||
| 91 | if (filled_slots == 0) | ||
| 92 | return 1; | ||
| 93 | |||
| 94 | return 0; | ||
| 95 | } | 89 | } | 
| 96 | 90 | ||
| 97 | /** | 91 | /** | 
| 98 | * mei_count_empty_write_slots - counts write empty slots. | 92 | * mei_hbuf_empty_slots - counts write empty slots. | 
| 99 | * | 93 | * | 
| 100 | * @dev: the device structure | 94 | * @dev: the device structure | 
| 101 | * | 95 | * | 
| 102 | * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count | 96 | * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count | 
| 103 | */ | 97 | */ | 
| 104 | int mei_count_empty_write_slots(struct mei_device *dev) | 98 | int mei_hbuf_empty_slots(struct mei_device *dev) | 
| 105 | { | 99 | { | 
| 106 | unsigned char buffer_depth, filled_slots, empty_slots; | 100 | unsigned char filled_slots, empty_slots; | 
| 107 | 101 | ||
| 108 | dev->host_hw_state = mei_hcsr_read(dev); | 102 | filled_slots = mei_hbuf_filled_slots(dev); | 
| 109 | buffer_depth = (unsigned char) ((dev->host_hw_state & H_CBD) >> 24); | 103 | empty_slots = dev->hbuf_depth - filled_slots; | 
| 110 | filled_slots = _host_get_filled_slots(dev); | ||
| 111 | empty_slots = buffer_depth - filled_slots; | ||
| 112 | 104 | ||
| 113 | /* check for overflow */ | 105 | /* check for overflow */ | 
| 114 | if (filled_slots > buffer_depth) | 106 | if (filled_slots > dev->hbuf_depth) | 
| 115 | return -EOVERFLOW; | 107 | return -EOVERFLOW; | 
| 116 | 108 | ||
| 117 | return empty_slots; | 109 | return empty_slots; | 
| @@ -127,52 +119,39 @@ int mei_count_empty_write_slots(struct mei_device *dev) | |||
| 127 | * | 119 | * | 
| 128 | * This function returns -EIO if write has failed | 120 | * This function returns -EIO if write has failed | 
| 129 | */ | 121 | */ | 
| 130 | int mei_write_message(struct mei_device *dev, | 122 | int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header, | 
| 131 | struct mei_msg_hdr *header, | 123 | unsigned char *buf, unsigned long length) | 
| 132 | unsigned char *write_buffer, | ||
| 133 | unsigned long write_length) | ||
| 134 | { | 124 | { | 
| 135 | u32 temp_msg = 0; | 125 | unsigned long rem, dw_cnt; | 
| 136 | unsigned long bytes_written = 0; | 126 | u32 *reg_buf = (u32 *)buf; | 
| 137 | unsigned char buffer_depth, filled_slots, empty_slots; | 127 | int i; | 
| 138 | unsigned long dw_to_write; | 128 | int empty_slots; | 
| 139 | |||
| 140 | dev->host_hw_state = mei_hcsr_read(dev); | ||
| 141 | 129 | ||
| 142 | dev_dbg(&dev->pdev->dev, | ||
| 143 | "host_hw_state = 0x%08x.\n", | ||
| 144 | dev->host_hw_state); | ||
| 145 | 130 | ||
| 146 | dev_dbg(&dev->pdev->dev, | 131 | dev_dbg(&dev->pdev->dev, | 
| 147 | "mei_write_message header=%08x.\n", | 132 | "mei_write_message header=%08x.\n", | 
| 148 | *((u32 *) header)); | 133 | *((u32 *) header)); | 
| 149 | 134 | ||
| 150 | buffer_depth = (unsigned char) ((dev->host_hw_state & H_CBD) >> 24); | 135 | empty_slots = mei_hbuf_empty_slots(dev); | 
| 151 | filled_slots = _host_get_filled_slots(dev); | 136 | dev_dbg(&dev->pdev->dev, "empty slots = %hu.\n", empty_slots); | 
| 152 | empty_slots = buffer_depth - filled_slots; | ||
| 153 | dev_dbg(&dev->pdev->dev, | ||
| 154 | "filled = %hu, empty = %hu.\n", | ||
| 155 | filled_slots, empty_slots); | ||
| 156 | |||
| 157 | dw_to_write = ((write_length + 3) / 4); | ||
| 158 | 137 | ||
| 159 | if (dw_to_write > empty_slots) | 138 | dw_cnt = mei_data2slots(length); | 
| 139 | if (empty_slots < 0 || dw_cnt > empty_slots) | ||
| 160 | return -EIO; | 140 | return -EIO; | 
| 161 | 141 | ||
| 162 | mei_reg_write(dev, H_CB_WW, *((u32 *) header)); | 142 | mei_reg_write(dev, H_CB_WW, *((u32 *) header)); | 
| 163 | 143 | ||
| 164 | while (write_length >= 4) { | 144 | for (i = 0; i < length / 4; i++) | 
| 165 | mei_reg_write(dev, H_CB_WW, | 145 | mei_reg_write(dev, H_CB_WW, reg_buf[i]); | 
| 166 | *(u32 *) (write_buffer + bytes_written)); | ||
| 167 | bytes_written += 4; | ||
| 168 | write_length -= 4; | ||
| 169 | } | ||
| 170 | 146 | ||
| 171 | if (write_length > 0) { | 147 | rem = length & 0x3; | 
| 172 | memcpy(&temp_msg, &write_buffer[bytes_written], write_length); | 148 | if (rem > 0) { | 
| 173 | mei_reg_write(dev, H_CB_WW, temp_msg); | 149 | u32 reg = 0; | 
| 150 | memcpy(®, &buf[length - rem], rem); | ||
| 151 | mei_reg_write(dev, H_CB_WW, reg); | ||
| 174 | } | 152 | } | 
| 175 | 153 | ||
| 154 | dev->host_hw_state = mei_hcsr_read(dev); | ||
| 176 | dev->host_hw_state |= H_IG; | 155 | dev->host_hw_state |= H_IG; | 
| 177 | mei_hcsr_set(dev); | 156 | mei_hcsr_set(dev); | 
| 178 | dev->me_hw_state = mei_mecsr_read(dev); | 157 | dev->me_hw_state = mei_mecsr_read(dev); | 
