Lines Matching +full:auto +full:- +full:flow +full:- +full:control

1 // SPDX-License-Identifier: GPL-2.0-only
20 /* auto-bind range */
29 * struct qrtr_hdr_v1 - (I|R)PCrouter packet header version 1
34 * @confirm_rx: boolean; whether a resume-tx packet should be send in reply
51 * struct qrtr_hdr_v2 - (I|R)PCrouter packet header later versions
116 * struct qrtr_node - endpoint node
140 * struct qrtr_tx_flow - tx flow control
172 struct qrtr_tx_flow *flow; in __qrtr_node_release() local
186 list_del(&node->item); in __qrtr_node_release()
189 skb_queue_purge(&node->rx_queue); in __qrtr_node_release()
191 /* Free tx flow counters */ in __qrtr_node_release()
192 radix_tree_for_each_slot(slot, &node->qrtr_tx_flow, &iter, 0) { in __qrtr_node_release()
193 flow = *slot; in __qrtr_node_release()
194 radix_tree_iter_delete(&node->qrtr_tx_flow, &iter, slot); in __qrtr_node_release()
195 kfree(flow); in __qrtr_node_release()
204 kref_get(&node->ref); in qrtr_node_acquire()
213 kref_put_mutex(&node->ref, __qrtr_node_release, &qrtr_node_lock); in qrtr_node_release()
217 * qrtr_tx_resume() - reset flow control counter
223 struct qrtr_ctrl_pkt *pkt = (struct qrtr_ctrl_pkt *)skb->data; in qrtr_tx_resume()
224 u64 remote_node = le32_to_cpu(pkt->client.node); in qrtr_tx_resume()
225 u32 remote_port = le32_to_cpu(pkt->client.port); in qrtr_tx_resume()
226 struct qrtr_tx_flow *flow; in qrtr_tx_resume() local
232 flow = radix_tree_lookup(&node->qrtr_tx_flow, key); in qrtr_tx_resume()
234 if (flow) { in qrtr_tx_resume()
235 spin_lock(&flow->resume_tx.lock); in qrtr_tx_resume()
236 flow->pending = 0; in qrtr_tx_resume()
237 spin_unlock(&flow->resume_tx.lock); in qrtr_tx_resume()
238 wake_up_interruptible_all(&flow->resume_tx); in qrtr_tx_resume()
245 * qrtr_tx_wait() - flow control for outgoing packets
251 * The flow control scheme is based around the low and high "watermarks". When
253 * message, which will trigger the remote to send a control message of the type
263 struct qrtr_tx_flow *flow; in qrtr_tx_wait() local
267 /* Never set confirm_rx on non-data packets */ in qrtr_tx_wait()
271 mutex_lock(&node->qrtr_tx_lock); in qrtr_tx_wait()
272 flow = radix_tree_lookup(&node->qrtr_tx_flow, key); in qrtr_tx_wait()
273 if (!flow) { in qrtr_tx_wait()
274 flow = kzalloc(sizeof(*flow), GFP_KERNEL); in qrtr_tx_wait()
275 if (flow) { in qrtr_tx_wait()
276 init_waitqueue_head(&flow->resume_tx); in qrtr_tx_wait()
277 if (radix_tree_insert(&node->qrtr_tx_flow, key, flow)) { in qrtr_tx_wait()
278 kfree(flow); in qrtr_tx_wait()
279 flow = NULL; in qrtr_tx_wait()
283 mutex_unlock(&node->qrtr_tx_lock); in qrtr_tx_wait()
285 /* Set confirm_rx if we where unable to find and allocate a flow */ in qrtr_tx_wait()
286 if (!flow) in qrtr_tx_wait()
289 spin_lock_irq(&flow->resume_tx.lock); in qrtr_tx_wait()
290 ret = wait_event_interruptible_locked_irq(flow->resume_tx, in qrtr_tx_wait()
291 flow->pending < QRTR_TX_FLOW_HIGH || in qrtr_tx_wait()
292 flow->tx_failed || in qrtr_tx_wait()
293 !node->ep); in qrtr_tx_wait()
296 } else if (!node->ep) { in qrtr_tx_wait()
297 confirm_rx = -EPIPE; in qrtr_tx_wait()
298 } else if (flow->tx_failed) { in qrtr_tx_wait()
299 flow->tx_failed = 0; in qrtr_tx_wait()
302 flow->pending++; in qrtr_tx_wait()
303 confirm_rx = flow->pending == QRTR_TX_FLOW_LOW; in qrtr_tx_wait()
305 spin_unlock_irq(&flow->resume_tx.lock); in qrtr_tx_wait()
311 * qrtr_tx_flow_failed() - flag that tx of confirm_rx flagged messages failed
317 * flow's "pending" counter will keep incrementing towards QRTR_TX_FLOW_HIGH,
320 * Work around this by marking the flow as having a failed transmission and
327 struct qrtr_tx_flow *flow; in qrtr_tx_flow_failed() local
330 flow = radix_tree_lookup(&node->qrtr_tx_flow, key); in qrtr_tx_flow_failed()
332 if (flow) { in qrtr_tx_flow_failed()
333 spin_lock_irq(&flow->resume_tx.lock); in qrtr_tx_flow_failed()
334 flow->tx_failed = 1; in qrtr_tx_flow_failed()
335 spin_unlock_irq(&flow->resume_tx.lock); in qrtr_tx_flow_failed()
345 size_t len = skb->len; in qrtr_node_enqueue()
348 confirm_rx = qrtr_tx_wait(node, to->sq_node, to->sq_port, type); in qrtr_node_enqueue()
355 hdr->version = cpu_to_le32(QRTR_PROTO_VER_1); in qrtr_node_enqueue()
356 hdr->type = cpu_to_le32(type); in qrtr_node_enqueue()
357 hdr->src_node_id = cpu_to_le32(from->sq_node); in qrtr_node_enqueue()
358 hdr->src_port_id = cpu_to_le32(from->sq_port); in qrtr_node_enqueue()
359 if (to->sq_port == QRTR_PORT_CTRL) { in qrtr_node_enqueue()
360 hdr->dst_node_id = cpu_to_le32(node->nid); in qrtr_node_enqueue()
361 hdr->dst_port_id = cpu_to_le32(QRTR_PORT_CTRL); in qrtr_node_enqueue()
363 hdr->dst_node_id = cpu_to_le32(to->sq_node); in qrtr_node_enqueue()
364 hdr->dst_port_id = cpu_to_le32(to->sq_port); in qrtr_node_enqueue()
367 hdr->size = cpu_to_le32(len); in qrtr_node_enqueue()
368 hdr->confirm_rx = !!confirm_rx; in qrtr_node_enqueue()
373 mutex_lock(&node->ep_lock); in qrtr_node_enqueue()
374 rc = -ENODEV; in qrtr_node_enqueue()
375 if (node->ep) in qrtr_node_enqueue()
376 rc = node->ep->xmit(node->ep, skb); in qrtr_node_enqueue()
379 mutex_unlock(&node->ep_lock); in qrtr_node_enqueue()
384 qrtr_tx_flow_failed(node, to->sq_node, to->sq_port); in qrtr_node_enqueue()
422 if (node->nid == QRTR_EP_NID_AUTO) in qrtr_node_assign()
423 node->nid = nid; in qrtr_node_assign()
428 * qrtr_endpoint_post() - post incoming data
437 struct qrtr_node *node = ep->node; in qrtr_endpoint_post()
448 return -EINVAL; in qrtr_endpoint_post()
452 return -ENOMEM; in qrtr_endpoint_post()
454 cb = (struct qrtr_cb *)skb->cb; in qrtr_endpoint_post()
466 cb->type = le32_to_cpu(v1->type); in qrtr_endpoint_post()
467 cb->src_node = le32_to_cpu(v1->src_node_id); in qrtr_endpoint_post()
468 cb->src_port = le32_to_cpu(v1->src_port_id); in qrtr_endpoint_post()
469 cb->confirm_rx = !!v1->confirm_rx; in qrtr_endpoint_post()
470 cb->dst_node = le32_to_cpu(v1->dst_node_id); in qrtr_endpoint_post()
471 cb->dst_port = le32_to_cpu(v1->dst_port_id); in qrtr_endpoint_post()
473 size = le32_to_cpu(v1->size); in qrtr_endpoint_post()
479 hdrlen = sizeof(*v2) + v2->optlen; in qrtr_endpoint_post()
481 cb->type = v2->type; in qrtr_endpoint_post()
482 cb->confirm_rx = !!(v2->flags & QRTR_FLAGS_CONFIRM_RX); in qrtr_endpoint_post()
483 cb->src_node = le16_to_cpu(v2->src_node_id); in qrtr_endpoint_post()
484 cb->src_port = le16_to_cpu(v2->src_port_id); in qrtr_endpoint_post()
485 cb->dst_node = le16_to_cpu(v2->dst_node_id); in qrtr_endpoint_post()
486 cb->dst_port = le16_to_cpu(v2->dst_port_id); in qrtr_endpoint_post()
488 if (cb->src_port == (u16)QRTR_PORT_CTRL) in qrtr_endpoint_post()
489 cb->src_port = QRTR_PORT_CTRL; in qrtr_endpoint_post()
490 if (cb->dst_port == (u16)QRTR_PORT_CTRL) in qrtr_endpoint_post()
491 cb->dst_port = QRTR_PORT_CTRL; in qrtr_endpoint_post()
493 size = le32_to_cpu(v2->size); in qrtr_endpoint_post()
500 if (cb->dst_port == QRTR_PORT_CTRL_LEGACY) in qrtr_endpoint_post()
501 cb->dst_port = QRTR_PORT_CTRL; in qrtr_endpoint_post()
506 if ((cb->type == QRTR_TYPE_NEW_SERVER || in qrtr_endpoint_post()
507 cb->type == QRTR_TYPE_RESUME_TX) && in qrtr_endpoint_post()
511 if (cb->dst_port != QRTR_PORT_CTRL && cb->type != QRTR_TYPE_DATA && in qrtr_endpoint_post()
512 cb->type != QRTR_TYPE_RESUME_TX) in qrtr_endpoint_post()
517 qrtr_node_assign(node, cb->src_node); in qrtr_endpoint_post()
519 if (cb->type == QRTR_TYPE_NEW_SERVER) { in qrtr_endpoint_post()
524 qrtr_node_assign(node, le32_to_cpu(pkt->server.node)); in qrtr_endpoint_post()
527 if (cb->type == QRTR_TYPE_RESUME_TX) { in qrtr_endpoint_post()
530 ipc = qrtr_port_lookup(cb->dst_port); in qrtr_endpoint_post()
534 if (sock_queue_rcv_skb(&ipc->sk, skb)) { in qrtr_endpoint_post()
546 return -EINVAL; in qrtr_endpoint_post()
552 * qrtr_alloc_ctrl_packet() - allocate control packet skb
559 * on success returns a reference to the control packet in @pkt.
578 * qrtr_endpoint_register() - register a new endpoint
580 * @nid: desired node id; may be QRTR_EP_NID_AUTO for auto-assignment
589 if (!ep || !ep->xmit) in qrtr_endpoint_register()
590 return -EINVAL; in qrtr_endpoint_register()
594 return -ENOMEM; in qrtr_endpoint_register()
596 kref_init(&node->ref); in qrtr_endpoint_register()
597 mutex_init(&node->ep_lock); in qrtr_endpoint_register()
598 skb_queue_head_init(&node->rx_queue); in qrtr_endpoint_register()
599 node->nid = QRTR_EP_NID_AUTO; in qrtr_endpoint_register()
600 node->ep = ep; in qrtr_endpoint_register()
602 INIT_RADIX_TREE(&node->qrtr_tx_flow, GFP_KERNEL); in qrtr_endpoint_register()
603 mutex_init(&node->qrtr_tx_lock); in qrtr_endpoint_register()
608 list_add(&node->item, &qrtr_all_nodes); in qrtr_endpoint_register()
610 ep->node = node; in qrtr_endpoint_register()
617 * qrtr_endpoint_unregister - unregister endpoint
622 struct qrtr_node *node = ep->node; in qrtr_endpoint_unregister()
623 struct sockaddr_qrtr src = {AF_QIPCRTR, node->nid, QRTR_PORT_CTRL}; in qrtr_endpoint_unregister()
627 struct qrtr_tx_flow *flow; in qrtr_endpoint_unregister() local
632 mutex_lock(&node->ep_lock); in qrtr_endpoint_unregister()
633 node->ep = NULL; in qrtr_endpoint_unregister()
634 mutex_unlock(&node->ep_lock); in qrtr_endpoint_unregister()
644 pkt->cmd = cpu_to_le32(QRTR_TYPE_BYE); in qrtr_endpoint_unregister()
650 /* Wake up any transmitters waiting for resume-tx from the node */ in qrtr_endpoint_unregister()
651 mutex_lock(&node->qrtr_tx_lock); in qrtr_endpoint_unregister()
652 radix_tree_for_each_slot(slot, &node->qrtr_tx_flow, &iter, 0) { in qrtr_endpoint_unregister()
653 flow = *slot; in qrtr_endpoint_unregister()
654 wake_up_interruptible_all(&flow->resume_tx); in qrtr_endpoint_unregister()
656 mutex_unlock(&node->qrtr_tx_lock); in qrtr_endpoint_unregister()
659 ep->node = NULL; in qrtr_endpoint_unregister()
677 sock_hold(&ipc->sk); in qrtr_port_lookup()
686 sock_put(&ipc->sk); in qrtr_port_put()
694 int port = ipc->us.sq_port; in qrtr_port_remove()
703 pkt->cmd = cpu_to_le32(QRTR_TYPE_DEL_CLIENT); in qrtr_port_remove()
704 pkt->client.node = cpu_to_le32(ipc->us.sq_node); in qrtr_port_remove()
705 pkt->client.port = cpu_to_le32(ipc->us.sq_port); in qrtr_port_remove()
707 skb_set_owner_w(skb, &ipc->sk); in qrtr_port_remove()
708 qrtr_bcast_enqueue(NULL, skb, QRTR_TYPE_DEL_CLIENT, &ipc->us, in qrtr_port_remove()
715 __sock_put(&ipc->sk); in qrtr_port_remove()
742 rc = -EACCES; in qrtr_port_assign()
749 if (rc == -EBUSY) in qrtr_port_assign()
750 return -EADDRINUSE; in qrtr_port_assign()
754 sock_hold(&ipc->sk); in qrtr_port_assign()
759 /* Reset all non-control ports */
767 sock_hold(&ipc->sk); in qrtr_reset_ports()
768 ipc->sk.sk_err = ENETRESET; in qrtr_reset_ports()
769 sk_error_report(&ipc->sk); in qrtr_reset_ports()
770 sock_put(&ipc->sk); in qrtr_reset_ports()
782 struct qrtr_sock *ipc = qrtr_sk(sock->sk); in __qrtr_bind()
783 struct sock *sk = sock->sk; in __qrtr_bind()
788 if (!zapped && addr->sq_port == ipc->us.sq_port) in __qrtr_bind()
791 port = addr->sq_port; in __qrtr_bind()
799 ipc->us.sq_port = port; in __qrtr_bind()
810 /* Auto bind to an ephemeral port. */
813 struct sock *sk = sock->sk; in qrtr_autobind()
830 struct qrtr_sock *ipc = qrtr_sk(sock->sk); in qrtr_bind()
831 struct sock *sk = sock->sk; in qrtr_bind()
834 if (len < sizeof(*addr) || addr->sq_family != AF_QIPCRTR) in qrtr_bind()
835 return -EINVAL; in qrtr_bind()
837 if (addr->sq_node != ipc->us.sq_node) in qrtr_bind()
838 return -EINVAL; in qrtr_bind()
855 ipc = qrtr_port_lookup(to->sq_port); in qrtr_local_enqueue()
856 if (!ipc || &ipc->sk == skb->sk) { /* do not send to self */ in qrtr_local_enqueue()
860 return -ENODEV; in qrtr_local_enqueue()
863 cb = (struct qrtr_cb *)skb->cb; in qrtr_local_enqueue()
864 cb->src_node = from->sq_node; in qrtr_local_enqueue()
865 cb->src_port = from->sq_port; in qrtr_local_enqueue()
867 if (sock_queue_rcv_skb(&ipc->sk, skb)) { in qrtr_local_enqueue()
870 return -ENOSPC; in qrtr_local_enqueue()
890 skb_set_owner_w(skbn, skb->sk); in qrtr_bcast_enqueue()
902 DECLARE_SOCKADDR(struct sockaddr_qrtr *, addr, msg->msg_name); in qrtr_sendmsg()
906 struct qrtr_sock *ipc = qrtr_sk(sock->sk); in qrtr_sendmsg()
907 struct sock *sk = sock->sk; in qrtr_sendmsg()
914 if (msg->msg_flags & ~(MSG_DONTWAIT)) in qrtr_sendmsg()
915 return -EINVAL; in qrtr_sendmsg()
918 return -EMSGSIZE; in qrtr_sendmsg()
923 if (msg->msg_namelen < sizeof(*addr)) { in qrtr_sendmsg()
925 return -EINVAL; in qrtr_sendmsg()
928 if (addr->sq_family != AF_QIPCRTR) { in qrtr_sendmsg()
930 return -EINVAL; in qrtr_sendmsg()
938 } else if (sk->sk_state == TCP_ESTABLISHED) { in qrtr_sendmsg()
939 addr = &ipc->peer; in qrtr_sendmsg()
942 return -ENOTCONN; in qrtr_sendmsg()
946 if (addr->sq_node == QRTR_NODE_BCAST) { in qrtr_sendmsg()
947 if (addr->sq_port != QRTR_PORT_CTRL && in qrtr_sendmsg()
950 return -ENOTCONN; in qrtr_sendmsg()
953 } else if (addr->sq_node == ipc->us.sq_node) { in qrtr_sendmsg()
956 node = qrtr_node_lookup(addr->sq_node); in qrtr_sendmsg()
959 return -ECONNRESET; in qrtr_sendmsg()
966 msg->msg_flags & MSG_DONTWAIT, &rc); in qrtr_sendmsg()
968 rc = -ENOMEM; in qrtr_sendmsg()
980 if (ipc->us.sq_port == QRTR_PORT_CTRL) { in qrtr_sendmsg()
982 rc = -EINVAL; in qrtr_sendmsg()
987 /* control messages already require the type as 'command' */ in qrtr_sendmsg()
992 rc = enqueue_fn(node, skb, type, &ipc->us, addr); in qrtr_sendmsg()
1005 struct sockaddr_qrtr remote = { AF_QIPCRTR, cb->src_node, cb->src_port }; in qrtr_send_resume_tx()
1006 struct sockaddr_qrtr local = { AF_QIPCRTR, cb->dst_node, cb->dst_port }; in qrtr_send_resume_tx()
1014 return -EINVAL; in qrtr_send_resume_tx()
1018 return -ENOMEM; in qrtr_send_resume_tx()
1020 pkt->cmd = cpu_to_le32(QRTR_TYPE_RESUME_TX); in qrtr_send_resume_tx()
1021 pkt->client.node = cpu_to_le32(cb->dst_node); in qrtr_send_resume_tx()
1022 pkt->client.port = cpu_to_le32(cb->dst_port); in qrtr_send_resume_tx()
1034 DECLARE_SOCKADDR(struct sockaddr_qrtr *, addr, msg->msg_name); in qrtr_recvmsg()
1035 struct sock *sk = sock->sk; in qrtr_recvmsg()
1044 return -EADDRNOTAVAIL; in qrtr_recvmsg()
1052 cb = (struct qrtr_cb *)skb->cb; in qrtr_recvmsg()
1054 copied = skb->len; in qrtr_recvmsg()
1057 msg->msg_flags |= MSG_TRUNC; in qrtr_recvmsg()
1066 /* There is an anonymous 2-byte hole after sq_family, in qrtr_recvmsg()
1071 addr->sq_family = AF_QIPCRTR; in qrtr_recvmsg()
1072 addr->sq_node = cb->src_node; in qrtr_recvmsg()
1073 addr->sq_port = cb->src_port; in qrtr_recvmsg()
1074 msg->msg_namelen = sizeof(*addr); in qrtr_recvmsg()
1078 if (cb->confirm_rx) in qrtr_recvmsg()
1091 struct qrtr_sock *ipc = qrtr_sk(sock->sk); in qrtr_connect()
1092 struct sock *sk = sock->sk; in qrtr_connect()
1095 if (len < sizeof(*addr) || addr->sq_family != AF_QIPCRTR) in qrtr_connect()
1096 return -EINVAL; in qrtr_connect()
1100 sk->sk_state = TCP_CLOSE; in qrtr_connect()
1101 sock->state = SS_UNCONNECTED; in qrtr_connect()
1109 ipc->peer = *addr; in qrtr_connect()
1110 sock->state = SS_CONNECTED; in qrtr_connect()
1111 sk->sk_state = TCP_ESTABLISHED; in qrtr_connect()
1121 struct qrtr_sock *ipc = qrtr_sk(sock->sk); in qrtr_getname()
1123 struct sock *sk = sock->sk; in qrtr_getname()
1127 if (sk->sk_state != TCP_ESTABLISHED) { in qrtr_getname()
1129 return -ENOTCONN; in qrtr_getname()
1132 qaddr = ipc->peer; in qrtr_getname()
1134 qaddr = ipc->us; in qrtr_getname()
1148 struct qrtr_sock *ipc = qrtr_sk(sock->sk); in qrtr_ioctl()
1149 struct sock *sk = sock->sk; in qrtr_ioctl()
1160 len = sk->sk_sndbuf - sk_wmem_alloc_get(sk); in qrtr_ioctl()
1166 skb = skb_peek(&sk->sk_receive_queue); in qrtr_ioctl()
1168 len = skb->len; in qrtr_ioctl()
1173 rc = -EFAULT; in qrtr_ioctl()
1178 *sq = ipc->us; in qrtr_ioctl()
1180 rc = -EFAULT; in qrtr_ioctl()
1193 rc = -EINVAL; in qrtr_ioctl()
1196 rc = -ENOIOCTLCMD; in qrtr_ioctl()
1207 struct sock *sk = sock->sk; in qrtr_release()
1216 sk->sk_shutdown = SHUTDOWN_MASK; in qrtr_release()
1218 sk->sk_state_change(sk); in qrtr_release()
1222 sock->sk = NULL; in qrtr_release()
1227 skb_queue_purge(&sk->sk_receive_queue); in qrtr_release()
1266 if (sock->type != SOCK_DGRAM) in qrtr_create()
1267 return -EPROTOTYPE; in qrtr_create()
1271 return -ENOMEM; in qrtr_create()
1276 sock->ops = &qrtr_proto_ops; in qrtr_create()
1279 ipc->us.sq_family = AF_QIPCRTR; in qrtr_create()
1280 ipc->us.sq_node = qrtr_local_nid; in qrtr_create()
1281 ipc->us.sq_port = 0; in qrtr_create()
1326 MODULE_DESCRIPTION("Qualcomm IPC-router driver");