static int mei_txe_write(struct mei_device *dev, struct mei_msg_hdr *header, unsigned char *buf) { struct mei_txe_hw *hw = to_txe_hw(dev); unsigned long rem; unsigned long length; int slots = dev->hbuf_depth; u32 *reg_buf = (u32 *)buf; u32 dw_cnt; int i; if (WARN_ON(!header || !buf)) return -EINVAL; length = header->length; dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(header)); dw_cnt = mei_data2slots(length); if (dw_cnt > slots) return -EMSGSIZE; if (WARN(!hw->aliveness, "txe write: aliveness not asserted\n")) return -EAGAIN; /* Enable Input Ready Interrupt. */ mei_txe_input_ready_interrupt_enable(dev); if (!mei_txe_is_input_ready(dev)) { struct mei_fw_status fw_status; mei_fw_status(dev, &fw_status); dev_err(&dev->pdev->dev, "Input is not ready " FW_STS_FMT "\n", FW_STS_PRM(fw_status)); return -EAGAIN; } mei_txe_input_payload_write(dev, 0, *((u32 *)header)); for (i = 0; i < length / 4; i++) mei_txe_input_payload_write(dev, i + 1, reg_buf[i]); rem = length & 0x3; if (rem > 0) { u32 reg = 0; memcpy(®, &buf[length - rem], rem); mei_txe_input_payload_write(dev, i + 1, reg); } /* after each write the whole buffer is consumed */ hw->slots = 0; /* Set Input-Doorbell */ mei_txe_input_doorbell_set(hw); return 0; }
/** * fw_status_show - mei device fw_status attribute show method * * @device: device pointer * @attr: attribute pointer * @buf: char out buffer * * Return: number of the bytes printed into buf or error */ static ssize_t fw_status_show(struct device *device, struct device_attribute *attr, char *buf) { struct mei_device *dev = dev_get_drvdata(device); struct mei_fw_status fw_status; int err, i; ssize_t cnt = 0; mutex_lock(&dev->device_lock); err = mei_fw_status(dev, &fw_status); mutex_unlock(&dev->device_lock); if (err) { dev_err(device, "read fw_status error = %d\n", err); return err; } for (i = 0; i < fw_status.count; i++) cnt += scnprintf(buf + cnt, PAGE_SIZE - cnt, "%08X\n", fw_status.status[i]); return cnt; }