drivers/soc/qcom/qmi_interface.c
Source file repositories/reference/linux-study-clean/drivers/soc/qcom/qmi_interface.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/soc/qcom/qmi_interface.c- Extension
.c- Size
- 21591 bytes
- Lines
- 855
- Domain
- Driver Families
- Bucket
- drivers/soc
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/kernel.hlinux/module.hlinux/device.hlinux/qrtr.hlinux/net.hlinux/completion.hlinux/idr.hlinux/string.hnet/sock.hlinux/workqueue.htrace/events/sock.hlinux/soc/qcom/qmi.h
Detected Declarations
function qmi_recv_new_serverfunction qmi_recv_del_serverfunction list_for_each_entry_safefunction qmi_recv_byefunction qmi_recv_del_clientfunction qmi_recv_ctrl_pktfunction qmi_send_new_lookupfunction qmi_add_lookupfunction qmi_send_new_serverfunction qmi_add_serverfunction qmi_txn_initfunction qmi_txn_waitfunction qmi_txn_cancelfunction qmi_invoke_handlerfunction qmi_handle_net_resetfunction qmi_handle_messagefunction qmi_data_ready_workfunction qmi_data_readyfunction qmi_handle_initfunction qmi_handle_releasefunction qmi_send_messagefunction qmi_send_requestfunction qmi_send_responsefunction qmi_send_indicationexport qmi_add_lookupexport qmi_add_serverexport qmi_txn_initexport qmi_txn_waitexport qmi_txn_cancelexport qmi_handle_initexport qmi_handle_releaseexport qmi_send_requestexport qmi_send_responseexport qmi_send_indication
Annotated Snippet
if (!txn) {
mutex_unlock(&qmi->txn_lock);
return;
}
mutex_lock(&txn->lock);
mutex_unlock(&qmi->txn_lock);
if (txn->dest && txn->ei) {
ret = qmi_decode_message(buf, len, txn->ei, txn->dest);
if (ret < 0)
pr_err("failed to decode incoming message\n");
txn->result = ret;
complete(&txn->completion);
} else {
qmi_invoke_handler(qmi, sq, txn, buf, len);
}
mutex_unlock(&txn->lock);
} else {
/* Create a txn based on the txn_id of the incoming message */
memset(&tmp_txn, 0, sizeof(tmp_txn));
tmp_txn.id = le16_to_cpu(hdr->txn_id);
qmi_invoke_handler(qmi, sq, &tmp_txn, buf, len);
}
}
static void qmi_data_ready_work(struct work_struct *work)
{
struct qmi_handle *qmi = container_of(work, struct qmi_handle, work);
struct qmi_ops *ops = &qmi->ops;
struct sockaddr_qrtr sq;
struct msghdr msg = { .msg_name = &sq, .msg_namelen = sizeof(sq) };
struct kvec iv;
ssize_t msglen;
for (;;) {
iv.iov_base = qmi->recv_buf;
iv.iov_len = qmi->recv_buf_size;
mutex_lock(&qmi->sock_lock);
if (qmi->sock)
msglen = kernel_recvmsg(qmi->sock, &msg, &iv, 1,
iv.iov_len, MSG_DONTWAIT);
else
msglen = -EPIPE;
mutex_unlock(&qmi->sock_lock);
if (msglen == -EAGAIN)
break;
if (msglen == -ENETRESET) {
qmi_handle_net_reset(qmi);
/* The old qmi->sock is gone, our work is done */
break;
}
if (msglen < 0) {
pr_err("qmi recvmsg failed: %zd\n", msglen);
break;
}
if (sq.sq_node == qmi->sq.sq_node &&
sq.sq_port == QRTR_PORT_CTRL) {
qmi_recv_ctrl_pkt(qmi, qmi->recv_buf, msglen);
} else if (ops->msg_handler) {
ops->msg_handler(qmi, &sq, qmi->recv_buf, msglen);
} else {
qmi_handle_message(qmi, &sq, qmi->recv_buf, msglen);
}
}
}
static void qmi_data_ready(struct sock *sk)
{
struct qmi_handle *qmi = sk->sk_user_data;
trace_sk_data_ready(sk);
/*
* This will be NULL if we receive data while being in
* qmi_handle_release()
*/
if (!qmi)
return;
queue_work(qmi->wq, &qmi->work);
}
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/module.h`, `linux/device.h`, `linux/qrtr.h`, `linux/net.h`, `linux/completion.h`, `linux/idr.h`, `linux/string.h`.
- Detected declarations: `function qmi_recv_new_server`, `function qmi_recv_del_server`, `function list_for_each_entry_safe`, `function qmi_recv_bye`, `function qmi_recv_del_client`, `function qmi_recv_ctrl_pkt`, `function qmi_send_new_lookup`, `function qmi_add_lookup`, `function qmi_send_new_server`, `function qmi_add_server`.
- Atlas domain: Driver Families / drivers/soc.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.