static int btqcomsmd_send(struct hci_dev *hdev, struct sk_buff *skb) { struct btqcomsmd *btq = hci_get_drvdata(hdev); int ret; switch (bt_cb(skb)->pkt_type) { case HCI_ACLDATA_PKT: case HCI_SCODATA_PKT: ret = qcom_smd_send(btq->acl_channel, skb->data, skb->len); break; case HCI_COMMAND_PKT: ret = qcom_smd_send(btq->cmd_channel, skb->data, skb->len); break; default: ret = -ENODEV; break; } return ret; }
/** * qcom_rpm_smd_write - write @buf to @type:@id * @rpm: rpm handle * @type: resource type * @id: resource identifier * @buf: the data to be written * @count: number of bytes in @buf */ int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm, int state, u32 type, u32 id, void *buf, size_t count) { static unsigned msg_id = 1; int left; int ret; struct { struct qcom_rpm_header hdr; struct qcom_rpm_request req; u8 payload[]; } *pkt; size_t size = sizeof(*pkt) + count; /* SMD packets to the RPM may not exceed 256 bytes */ if (WARN_ON(size >= 256)) return -EINVAL; pkt = kmalloc(size, GFP_KERNEL); if (!pkt) return -ENOMEM; mutex_lock(&rpm->lock); pkt->hdr.service_type = cpu_to_le32(RPM_SERVICE_TYPE_REQUEST); pkt->hdr.length = cpu_to_le32(sizeof(struct qcom_rpm_request) + count); pkt->req.msg_id = cpu_to_le32(msg_id++); pkt->req.flags = cpu_to_le32(state); pkt->req.type = cpu_to_le32(type); pkt->req.id = cpu_to_le32(id); pkt->req.data_len = cpu_to_le32(count); memcpy(pkt->payload, buf, count); ret = qcom_smd_send(rpm->rpm_channel, pkt, size); if (ret) goto out; left = wait_for_completion_timeout(&rpm->ack, RPM_REQUEST_TIMEOUT); if (!left) ret = -ETIMEDOUT; else ret = rpm->ack_status; out: kfree(pkt); mutex_unlock(&rpm->lock); return ret; }
/** * qcom_rpm_smd_write - write @buf to @type:@id * @rpm: rpm handle * @type: resource type * @id: resource identifier * @buf: the data to be written * @count: number of bytes in @buf */ int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm, int state, u32 type, u32 id, void *buf, size_t count) { static unsigned msg_id = 1; int left; int ret; struct { struct qcom_rpm_header hdr; struct qcom_rpm_request req; u8 payload[count]; } pkt; /* SMD packets to the RPM may not exceed 256 bytes */ if (WARN_ON(sizeof(pkt) >= 256)) return -EINVAL; mutex_lock(&rpm->lock); pkt.hdr.service_type = RPM_SERVICE_TYPE_REQUEST; pkt.hdr.length = sizeof(struct qcom_rpm_request) + count; pkt.req.msg_id = msg_id++; pkt.req.flags = BIT(state); pkt.req.type = type; pkt.req.id = id; pkt.req.data_len = count; memcpy(pkt.payload, buf, count); ret = qcom_smd_send(rpm->rpm_channel, &pkt, sizeof(pkt)); if (ret) goto out; left = wait_for_completion_timeout(&rpm->ack, RPM_REQUEST_TIMEOUT); if (!left) ret = -ETIMEDOUT; else ret = rpm->ack_status; out: mutex_unlock(&rpm->lock); return ret; }