Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp700432ybz; Sat, 25 Apr 2020 02:25:46 -0700 (PDT) X-Google-Smtp-Source: APiQypL5BAtxJ3j+/7mJwf1Ibl2B3Plgn8LRuNTJRiQ9lhmfpBfzolm39Q/QIcnddLnG6lLWL7kV X-Received: by 2002:a50:c004:: with SMTP id r4mr10265463edb.110.1587806745837; Sat, 25 Apr 2020 02:25:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1587806745; cv=none; d=google.com; s=arc-20160816; b=07nbRnJuFO2AhGseNMu3HzuvMVmUKYjrNuU5HyOXdLT01ZVy41+k1rPTwkiY2QpGNu 0DFjEvOMdy0KGR/wavpoUBOwIwYDykFwSSVqXezqxSYTotOqGUetk/GUtaH8nBLAwhHJ bx10AoAKvmlo2v6oHMA1Zkj5/UVrV4MaNPCzjG2tOVU93LGJhJcMxQdyoWxkeUQtGjXp V+FfkITQDSHQrl0AZQLdHBSJs074GfcVmqCWa5g/uG3rpBUEUdiknJbvQPrs3kVZrJVS Z3cqyDTU4wsrIFMtqBOzERVpg112CGoeiZ/U9Ommq6YSwqHzloy8vreK+V4o+Jz9r3fY E1Rg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=GmVvTtzXLoODUU4TVuWK38eskimbMg69bAuMIbaWkZI=; b=yvMJUP52eKv0/RRSs2aAzIuBbKQUIbTwsNX6feK1XFpDdxdUMA2i/4HkgQy6NIob6M ChdxI5ASylxliy+lEydYOuiYLX+9yt09z94etjhh8yeUwsAaFyFg479EfqSJWPuYZd/y Kyv8KY0w9OitGETDHqL3G6w2+dlDD9lKAQOlSBVZW9rwje8131GyFTJ60+WQv133y/jA MSrXiHxzwQlSZHnyQ8rrijSc4eVSsq0W/jWeVmOwEul/6ZLXQOoM/+YeUCXLvKsOV5FQ dUwkzg9BhQbKa3FUyKKtrkJpQcAcOIe7D1SYOuQO5+Vm+R4JM4lTFR9lfrBdi2SnvA6t ZRKg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@displaylink.com header.s=mimecast20151025 header.b="xs+q/GeD"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=displaylink.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id ox16si4913723ejb.427.2020.04.25.02.25.22; Sat, 25 Apr 2020 02:25:45 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@displaylink.com header.s=mimecast20151025 header.b="xs+q/GeD"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=displaylink.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726343AbgDYJUt (ORCPT + 99 others); Sat, 25 Apr 2020 05:20:49 -0400 Received: from eu-smtp-delivery-167.mimecast.com ([146.101.78.167]:59755 "EHLO eu-smtp-delivery-167.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726070AbgDYJUT (ORCPT ); Sat, 25 Apr 2020 05:20:19 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=displaylink.com; s=mimecast20151025; t=1587806415; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=GmVvTtzXLoODUU4TVuWK38eskimbMg69bAuMIbaWkZI=; b=xs+q/GeDRtU8BXVIX6MOjo2YIHCZwUheTKJIBEhXLqSb2g2zdT55UfnMayRblEqEYRM9VR igDA87G4SUD3QnUMY4QkWLGjxA0AHgbqT5oqOWIqP5c5IoRHeNnpwJEClWJb6R7RLq5f9i JmUpO124+cpC5nYqcFGbjEwZWYGCDN8= Received: from EUR01-HE1-obe.outbound.protection.outlook.com (mail-he1eur01lp2054.outbound.protection.outlook.com [104.47.0.54]) (Using TLS) by relay.mimecast.com with ESMTP id uk-mta-233-5Fyio6hUOMKXtxiv4p6Byg-3; Sat, 25 Apr 2020 10:20:14 +0100 X-MC-Unique: 5Fyio6hUOMKXtxiv4p6Byg-3 Received: from VI1PR1001MB1056.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:800:64::13) by VI1PR1001MB1056.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:800:64::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2937.22; Sat, 25 Apr 2020 09:20:11 +0000 Received: from VI1PR1001MB1056.EURPRD10.PROD.OUTLOOK.COM ([fe80::8cba:c335:a57e:9dfd]) by VI1PR1001MB1056.EURPRD10.PROD.OUTLOOK.COM ([fe80::8cba:c335:a57e:9dfd%5]) with mapi id 15.20.2937.020; Sat, 25 Apr 2020 09:20:11 +0000 From: vladimir.stankovic@displaylink.com To: gregkh@linuxfoundation.org Cc: linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, mausb-host-devel@displaylink.com Subject: [PATCH v5 2/8] usb: mausb_host: Add link layer implementation Date: Sat, 25 Apr 2020 11:19:48 +0200 Message-Id: <20200425091954.1610-3-vladimir.stankovic@displaylink.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200425091954.1610-1-vladimir.stankovic@displaylink.com> References: <20200327152614.26833-1-vladimir.stankovic@displaylink.com> <20200425091954.1610-1-vladimir.stankovic@displaylink.com> X-ClientProxiedBy: LO2P265CA0131.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:9f::23) To VI1PR1001MB1056.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:800:64::13) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from raven-hp.endava.net (94.189.199.177) by LO2P265CA0131.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:9f::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2937.13 via Frontend Transport; Sat, 25 Apr 2020 09:20:10 +0000 X-Mailer: git-send-email 2.17.1 X-Originating-IP: [94.189.199.177] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: a3be63ca-1eb5-4d02-6f08-08d7e8f9dadc X-MS-TrafficTypeDiagnostic: VI1PR1001MB1056: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:5; X-Forefront-PRVS: 0384275935 X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:VI1PR1001MB1056.EURPRD10.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFTY:;SFS:(4636009)(346002)(366004)(136003)(39840400004)(396003)(376002)(9686003)(6512007)(8936002)(66946007)(316002)(52116002)(66476007)(6666004)(5660300002)(8676002)(66556008)(81156014)(1076003)(86362001)(30864003)(6486002)(478600001)(6506007)(956004)(6916009)(2906002)(4326008)(26005)(36756003)(2616005)(186003)(16526019)(107886003);DIR:OUT;SFP:1101; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 9QnuFvMyOehPXXUjK7ZzHXJldcAy8oxDGBuNKFBXIs2dv+WvMtdiLSpw5ItNKi0GQ644U21nV9XE9eqrkthyr3b0BMg7nVtMMFkKjw7j3PWEsjdyK5VvwKucYS0xtkiVB+a8rMZ1uXQG+YFtLPonfXHJ5dSpDrelwYheGtdo39cXDaCbPlxZC3aPztGVOB14QwGo0jDcrRyHf8ZHUWiZan8WuU61gCZz90HJFMWS5/SHXeg5Oi49v3f7uV6Mz9vjpD7HTkj+CGBKwN8H3tMcJKGksdaTblcjITaYJPJpRRMXWMw+l7bw7rW865fLrwO57t/wujWxn8ntyfg9YVAqIpHqesnnVg9DOja5Z3F+wH4CbYFLB3lehKZmxnSgfdPTjmx8RB3mzXW5XWH0nwgFkhAYiucXW/DOBQr1EF0Qyph5gWleGQIvlpi83lydZkAZ X-MS-Exchange-AntiSpam-MessageData: XnXdLMQrrRKj+8x3HbDJ6Lo/iNxJXPDE9KrBSxPu+tm+185Nqg50B3cDouej0mB8LGA/DtEiSsn42zROz6Y6GdSkr8wnXXNgwqHe5m6u5JCPCy74McBqS97tH9+5ARY9oNBEdYWGA5PjeUdOkoWM+HrwPbcJ7sDEa6t6N2m2atVH6unOqx8eGDFvhhy0cZIABO8KZYCsqKqmr2+uwNuTklToE0Te9YzHzv2S2/X/yJmI88+vHywlDq+Mz6rfCuzKOrWfbKJApbJauGOW3OFpPtEHbjWe843z5mEosfNf3ntF5fSwWUhP8mIC+YLYdsrs37dDFu450SNxJGBtgZ6rMJnOqGF14QBqA8YbOYTA9WLQC9352aWqa9dpJ8v2Sebgwy7wxNq7XYETijGPbcDSGQeAtnHBcPrjDh75HtFRQxSIDadKh5ANjTsqDFZbr4Vo3oegNaNoqWFqu+7Wp1l0ukvwek5787yqSJmJFB69ubt504VLzjhCvfs3PA4hgI0pDrH7SW5fEE0q8pODCwoKc5Gl+u/xsloH+V7EkjoqdxVo+QOWvoYysBvetBH1AOBSH8kTzluhlqht1OZq+lrOg2EWZ4+pNZcEt5xIg0AcV1wXT5jZ9EBXGGl8PmKuDF6S+e4vfpTB0+MQ+AwSwALmqvg42l3cLIcVeVEoEnP5GcdOm+N/0OdaMoPdk2AMseIqyj5aZgJ2oG44QlCOWgZNqNvueIvMjuGs1b8r6wrWw5/ASXaVqNGFLi23Ghjeuk4prLq9m0lGRi2yYGAIROCiQpw1F/M/FaKA/uOFOR7Q/2M= X-OriginatorOrg: displaylink.com X-MS-Exchange-CrossTenant-Network-Message-Id: a3be63ca-1eb5-4d02-6f08-08d7e8f9dadc X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 Apr 2020 09:20:11.4933 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a4bda75a-b444-4312-9c90-44a7c4b2c91a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: ghZRqlmkQhTZ+q3jf85D2Q58wOj/DL/+gGDTlVup3oP6lQN/bovX51N5Kc1MatcxnlgDyQfQQel604VoUqsn+Z4nnFPoruf3Mij7bvouhME59LkCa0xe07m38JMme0Ps X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR1001MB1056 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: displaylink.com Content-Type: text/plain; charset=WINDOWS-1252 Content-Transfer-Encoding: quoted-printable Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Implemented link layer using kernel sockets. Link layer manages network communication and provides interface for upper layers of MA-USB stack. Signed-off-by: Vladimir Stankovic --- drivers/usb/mausb_host/Makefile | 1 + drivers/usb/mausb_host/ip_link.c | 374 +++++++++++++++++++++++++++++++ drivers/usb/mausb_host/ip_link.h | 87 +++++++ 3 files changed, 462 insertions(+) create mode 100644 drivers/usb/mausb_host/ip_link.c create mode 100644 drivers/usb/mausb_host/ip_link.h diff --git a/drivers/usb/mausb_host/Makefile b/drivers/usb/mausb_host/Makef= ile index 2e353fa0958b..19445b73b50b 100644 --- a/drivers/usb/mausb_host/Makefile +++ b/drivers/usb/mausb_host/Makefile @@ -8,5 +8,6 @@ obj-$(CONFIG_HOST_MAUSB) +=3D mausb_host.o mausb_host-y :=3D mausb_core.o mausb_host-y +=3D utils.o +mausb_host-y +=3D ip_link.o =20 ccflags-y +=3D -I$(srctree)/$(src) diff --git a/drivers/usb/mausb_host/ip_link.c b/drivers/usb/mausb_host/ip_l= ink.c new file mode 100644 index 000000000000..49b592c02210 --- /dev/null +++ b/drivers/usb/mausb_host/ip_link.c @@ -0,0 +1,374 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 - 2020 DisplayLink (UK) Ltd. + */ +#include "ip_link.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" + +static void __mausb_ip_connect(struct work_struct *work); +static int __mausb_ip_recv(struct mausb_ip_ctx *ip_ctx); +static void __mausb_ip_recv_work(struct work_struct *work); +static inline void __mausb_ip_recv_ctx_clear(struct mausb_ip_recv_ctx +=09=09=09=09=09 *recv_ctx); +static inline void __mausb_ip_recv_ctx_free(struct mausb_ip_recv_ctx +=09=09=09=09=09 *recv_ctx); + +int mausb_init_ip_ctx(struct mausb_ip_ctx **ip_ctx, +=09=09 struct net *net_ns, +=09=09 char ip_addr[INET6_ADDRSTRLEN], +=09=09 u16 port, void *context, +=09=09 void (*fn_callback)(void *ctx, enum mausb_channel channel, +=09=09=09=09=09 enum mausb_link_action act, +=09=09=09=09=09 int status, void *data), +=09=09 enum mausb_channel channel) +{ +=09struct mausb_ip_ctx *ctx; + +=09*ip_ctx =3D kzalloc(sizeof(**ip_ctx), GFP_ATOMIC); +=09if (!*ip_ctx) +=09=09return -ENOMEM; + +=09ctx =3D *ip_ctx; +=09ctx->client_socket =3D NULL; +=09__mausb_ip_recv_ctx_clear(&ctx->recv_ctx); + +=09if (in4_pton(ip_addr, -1, +=09=09 (u8 *)&ctx->dev_addr_in.sa_in.sin_addr.s_addr, -1, +=09=09 NULL) =3D=3D 1) { +=09=09ctx->dev_addr_in.sa_in.sin_family =3D AF_INET; +=09=09ctx->dev_addr_in.sa_in.sin_port =3D htons(port); +#if IS_ENABLED(CONFIG_IPV6) +=09} else if (in6_pton(ip_addr, -1, +=09=09=09 (u8 *)&ctx->dev_addr_in.sa_in6.sin6_addr.in6_u, -1, +=09=09=09 NULL) =3D=3D 1) { +=09=09ctx->dev_addr_in.sa_in6.sin6_family =3D AF_INET6; +=09=09ctx->dev_addr_in.sa_in6.sin6_port =3D htons(port); +#endif +=09} else { +=09=09mausb_pr_err("Invalid IP address received: address=3D%s", +=09=09=09 ip_addr); +=09=09kfree(ctx); +=09=09return -EINVAL; +=09} + +=09ctx->net_ns =3D net_ns; + +=09if (channel =3D=3D MAUSB_ISOCH_CHANNEL) +=09=09ctx->udp =3D true; + +=09ctx->connect_workq =3D alloc_ordered_workqueue("connect_workq", +=09=09=09=09=09=09 WQ_MEM_RECLAIM); +=09if (!ctx->connect_workq) { +=09=09kfree(ctx); +=09=09return -ENOMEM; +=09} + +=09ctx->recv_workq =3D alloc_ordered_workqueue("recv_workq", WQ_MEM_RECLAI= M); +=09if (!ctx->recv_workq) { +=09=09destroy_workqueue(ctx->connect_workq); +=09=09kfree(ctx); +=09=09return -ENOMEM; +=09} + +=09INIT_WORK(&ctx->connect_work, __mausb_ip_connect); +=09INIT_WORK(&ctx->recv_work, __mausb_ip_recv_work); + +=09ctx->channel=09 =3D channel; +=09ctx->ctx=09 =3D context; +=09ctx->fn_callback =3D fn_callback; + +=09return 0; +} + +void mausb_destroy_ip_ctx(struct mausb_ip_ctx *ip_ctx) +{ +=09if (!ip_ctx) +=09=09return; + +=09if (ip_ctx->connect_workq) { +=09=09flush_workqueue(ip_ctx->connect_workq); +=09=09destroy_workqueue(ip_ctx->connect_workq); +=09} + +=09if (ip_ctx->recv_workq) { +=09=09flush_workqueue(ip_ctx->recv_workq); +=09=09destroy_workqueue(ip_ctx->recv_workq); +=09} +=09if (ip_ctx->client_socket) +=09=09sock_release(ip_ctx->client_socket); +=09__mausb_ip_recv_ctx_free(&ip_ctx->recv_ctx); + +=09kfree(ip_ctx); +} + +static void __mausb_ip_set_options(struct socket *sock, bool udp) +{ +=09u32 optval =3D 0; +=09unsigned int optlen =3D sizeof(optval); +=09int status =3D 0; +=09struct __kernel_sock_timeval timeo =3D {.tv_sec =3D 0, .tv_usec =3D 500= 000U }; +=09struct __kernel_sock_timeval send_timeo =3D {.tv_sec =3D 1, .tv_usec = =3D 0 }; + +=09if (!udp) { +=09=09optval =3D 1; +=09=09status =3D kernel_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, +=09=09=09=09=09 (char *)&optval, optlen); +=09=09if (status < 0) +=09=09=09mausb_pr_warn("Failed to set tcp no delay option: status=3D%d", +=09=09=09=09 status); +=09} + +=09status =3D kernel_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO_NEW, +=09=09=09=09 (char *)&timeo, sizeof(timeo)); +=09if (status < 0) +=09=09mausb_pr_warn("Failed to set recv timeout option: status=3D%d", +=09=09=09 status); + +=09status =3D kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO_NEW, +=09=09=09=09 (char *)&send_timeo, sizeof(send_timeo)); +=09if (status < 0) +=09=09mausb_pr_warn("Failed to set snd timeout option: status=3D%d", +=09=09=09 status); + +=09optval =3D MAUSB_LINK_BUFF_SIZE; +=09status =3D kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUF, +=09=09=09=09 (char *)&optval, optlen); +=09if (status < 0) +=09=09mausb_pr_warn("Failed to set recv buffer size: status=3D%d", +=09=09=09 status); + +=09optval =3D MAUSB_LINK_BUFF_SIZE; +=09status =3D kernel_setsockopt(sock, SOL_SOCKET, SO_SNDBUF, +=09=09=09=09 (char *)&optval, optlen); +=09if (status < 0) +=09=09mausb_pr_warn("Failed to set send buffer size: status=3D%d", +=09=09=09 status); + +=09optval =3D MAUSB_LINK_TOS_LEVEL_EF; +=09status =3D kernel_setsockopt(sock, IPPROTO_IP, IP_TOS, +=09=09=09=09 (char *)&optval, optlen); +=09if (status < 0) +=09=09mausb_pr_warn("Failed to set QOS: status=3D%d", status); +} + +static void __mausb_ip_connect(struct work_struct *work) +{ +=09int status =3D 0; +=09struct sockaddr *sa; +=09int sa_size; +=09struct mausb_ip_ctx *ip_ctx =3D container_of(work, struct mausb_ip_ctx, +=09=09=09=09=09=09 connect_work); +=09unsigned short int family =3D ip_ctx->dev_addr_in.sa_in.sin_family; + +=09if (!ip_ctx->udp) { +=09=09status =3D sock_create_kern(ip_ctx->net_ns, family, SOCK_STREAM, +=09=09=09=09=09 IPPROTO_TCP, &ip_ctx->client_socket); +=09=09if (status < 0) { +=09=09=09mausb_pr_err("Failed to create socket: status=3D%d", +=09=09=09=09 status); +=09=09=09goto callback; +=09=09} +=09} else { +=09=09status =3D sock_create_kern(ip_ctx->net_ns, family, SOCK_DGRAM, +=09=09=09=09=09 IPPROTO_UDP, &ip_ctx->client_socket); +=09=09if (status < 0) { +=09=09=09mausb_pr_err("Failed to create socket: status=3D%d", +=09=09=09=09 status); +=09=09=09goto callback; +=09=09} +=09} + +=09__mausb_ip_set_options((struct socket *)ip_ctx->client_socket, +=09=09=09 ip_ctx->udp); + +=09if (family =3D=3D AF_INET) { +=09=09sa =3D (struct sockaddr *)&ip_ctx->dev_addr_in.sa_in; +=09=09sa_size =3D sizeof(ip_ctx->dev_addr_in.sa_in); +=09=09mausb_pr_info("Connecting to %pI4:%d, status=3D%d", +=09=09=09 &ip_ctx->dev_addr_in.sa_in.sin_addr, +=09=09=09 htons(ip_ctx->dev_addr_in.sa_in.sin_port), +=09=09=09 status); +#if IS_ENABLED(CONFIG_IPV6) +=09} else if (family =3D=3D AF_INET6) { +=09=09sa =3D (struct sockaddr *)&ip_ctx->dev_addr_in.sa_in6; +=09=09sa_size =3D sizeof(ip_ctx->dev_addr_in.sa_in6); +=09=09mausb_pr_info("Connecting to %pI6c:%d, status=3D%d", +=09=09=09 &ip_ctx->dev_addr_in.sa_in6.sin6_addr, +=09=09=09 htons(ip_ctx->dev_addr_in.sa_in6.sin6_port), +=09=09=09 status); +#endif +=09} else { +=09=09mausb_pr_err("Wrong network family provided"); +=09=09status =3D -EINVAL; +=09=09goto callback; +=09} + +=09status =3D kernel_connect(ip_ctx->client_socket, sa, sa_size, O_RDWR); +=09if (status < 0) { +=09=09mausb_pr_err("Failed to connect to host, status=3D%d", status); +=09=09goto clear_socket; +=09} + +=09queue_work(ip_ctx->recv_workq, &ip_ctx->recv_work); + +=09goto callback; + +clear_socket: +=09sock_release(ip_ctx->client_socket); +=09ip_ctx->client_socket =3D NULL; +callback: +=09ip_ctx->fn_callback(ip_ctx->ctx, ip_ctx->channel, MAUSB_LINK_CONNECT, +=09=09=09 status, NULL); +} + +void mausb_ip_connect_async(struct mausb_ip_ctx *ip_ctx) +{ +=09queue_work(ip_ctx->connect_workq, &ip_ctx->connect_work); +} + +int mausb_ip_disconnect(struct mausb_ip_ctx *ip_ctx) +{ +=09if (ip_ctx && ip_ctx->client_socket) +=09=09return kernel_sock_shutdown(ip_ctx->client_socket, SHUT_RDWR); +=09return 0; +} + +int mausb_ip_send(struct mausb_ip_ctx *ip_ctx, +=09=09 struct mausb_kvec_data_wrapper *wrapper) +{ +=09struct msghdr msghd; + +=09if (!ip_ctx) { +=09=09mausb_pr_alert("Socket ctx is NULL!"); +=09=09return -EINVAL; +=09} + +=09memset(&msghd, 0, sizeof(msghd)); +=09msghd.msg_flags =3D MSG_WAITALL; + +=09return kernel_sendmsg(ip_ctx->client_socket, &msghd, wrapper->kvec, +=09=09=09 wrapper->kvec_num, wrapper->length); +} + +static inline void __mausb_ip_recv_ctx_clear(struct mausb_ip_recv_ctx *rec= v_ctx) +{ +=09recv_ctx->buffer =3D NULL; +=09recv_ctx->left=09 =3D 0; +=09recv_ctx->received =3D 0; +} + +static inline void __mausb_ip_recv_ctx_free(struct mausb_ip_recv_ctx *recv= _ctx) +{ +=09kfree(recv_ctx->buffer); +=09__mausb_ip_recv_ctx_clear(recv_ctx); +} + +static int __mausb_ip_recv(struct mausb_ip_ctx *ip_ctx) +{ +=09struct msghdr msghd; +=09struct kvec vec; +=09int status; +=09bool peek =3D true; +=09unsigned int optval =3D 1; +=09struct socket *client_socket =3D (struct socket *)ip_ctx->client_socket= ; + +=09/* receive with timeout of 0.5s */ +=09while (true) { +=09=09memset(&msghd, 0, sizeof(msghd)); +=09=09if (peek) { +=09=09=09vec.iov_base =3D ip_ctx->recv_ctx.common_hdr; +=09=09=09vec.iov_len =3D sizeof(ip_ctx->recv_ctx.common_hdr); +=09=09=09msghd.msg_flags =3D MSG_PEEK; +=09=09} else { +=09=09=09vec.iov_base =3D +=09=09=09 ip_ctx->recv_ctx.buffer + +=09=09=09 ip_ctx->recv_ctx.received; +=09=09=09vec.iov_len =3D ip_ctx->recv_ctx.left; +=09=09=09msghd.msg_flags =3D MSG_WAITALL; +=09=09} + +=09=09if (!ip_ctx->udp) { +=09=09=09status =3D kernel_setsockopt(client_socket, IPPROTO_TCP, +=09=09=09=09=09=09 TCP_QUICKACK, +=09=09=09=09=09=09 (char *)&optval, +=09=09=09=09=09=09 sizeof(optval)); +=09=09=09if (status !=3D 0) { +=09=09=09=09mausb_pr_warn("Setting TCP_QUICKACK failed, status=3D%d", +=09=09=09=09=09 status); +=09=09=09} +=09=09} + +=09=09status =3D kernel_recvmsg(client_socket, &msghd, &vec, 1, +=09=09=09=09=09vec.iov_len, (int)msghd.msg_flags); +=09=09if (status =3D=3D -EAGAIN) { +=09=09=09return -EAGAIN; +=09=09} else if (status <=3D 0) { +=09=09=09mausb_pr_warn("kernel_recvmsg, status=3D%d", status); + +=09=09=09__mausb_ip_recv_ctx_free(&ip_ctx->recv_ctx); +=09=09=09ip_ctx->fn_callback(ip_ctx->ctx, ip_ctx->channel, +=09=09=09=09=09 MAUSB_LINK_RECV, status, NULL); +=09=09=09return status; +=09=09} + +=09=09mausb_pr_debug("kernel_recvmsg, status=3D%d", status); + +=09=09if (peek) { +=09=09=09if ((unsigned int)status < +=09=09=09=09=09sizeof(ip_ctx->recv_ctx.common_hdr)) +=09=09=09=09return -EAGAIN; +=09=09=09/* length field of mausb_common_hdr */ +=09=09=09ip_ctx->recv_ctx.left =3D +=09=09=09 *(u16 *)(&ip_ctx->recv_ctx.common_hdr[2]); +=09=09=09ip_ctx->recv_ctx.received =3D 0; +=09=09=09ip_ctx->recv_ctx.buffer=09 =3D +=09=09=09 kzalloc(ip_ctx->recv_ctx.left, GFP_KERNEL); +=09=09=09peek =3D false; +=09=09=09if (!ip_ctx->recv_ctx.buffer) { +=09=09=09=09ip_ctx->fn_callback(ip_ctx->ctx, +=09=09=09=09=09=09 ip_ctx->channel, +=09=09=09=09=09=09 MAUSB_LINK_RECV, +=09=09=09=09=09=09 -ENOMEM, NULL); +=09=09=09=09return -ENOMEM; +=09=09=09} +=09=09} else { +=09=09=09if (status < ip_ctx->recv_ctx.left) { +=09=09=09=09ip_ctx->recv_ctx.left -=3D (u16)status; +=09=09=09=09ip_ctx->recv_ctx.received +=3D (u16)status; +=09=09=09} else { +=09=09=09=09ip_ctx->fn_callback(ip_ctx->ctx, +=09=09=09=09=09=09 ip_ctx->channel, +=09=09=09=09=09=09 MAUSB_LINK_RECV, status, +=09=09=09=09=09=09 ip_ctx->recv_ctx.buffer); +=09=09=09=09__mausb_ip_recv_ctx_clear(&ip_ctx->recv_ctx); +=09=09=09=09peek =3D true; +=09=09=09} +=09=09} +=09} + +=09return status; +} + +static void __mausb_ip_recv_work(struct work_struct *work) +{ +=09struct mausb_ip_ctx *ip_ctx =3D container_of(work, struct mausb_ip_ctx, +=09=09=09=09=09=09 recv_work); +=09int status =3D __mausb_ip_recv(ip_ctx); + +=09if (status <=3D 0 && status !=3D -EAGAIN) +=09=09return; + +=09queue_work(ip_ctx->recv_workq, &ip_ctx->recv_work); +} diff --git a/drivers/usb/mausb_host/ip_link.h b/drivers/usb/mausb_host/ip_l= ink.h new file mode 100644 index 000000000000..5946151e4e4e --- /dev/null +++ b/drivers/usb/mausb_host/ip_link.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 - 2020 DisplayLink (UK) Ltd. + */ +#ifndef __MAUSB_IP_LINK_H__ +#define __MAUSB_IP_LINK_H__ + +#include +#include +#include +#include + +#define MAUSB_LINK_BUFF_SIZE=0916777216 +#define MAUSB_LINK_TOS_LEVEL_EF 0xB8 + +enum mausb_link_action { +=09MAUSB_LINK_CONNECT=09=3D 0, +=09MAUSB_LINK_DISCONNECT=09=3D 1, +=09MAUSB_LINK_RECV=09=09=3D 2, +=09MAUSB_LINK_SEND=09=09=3D 3 +}; + +enum mausb_channel { +=09MAUSB_CTRL_CHANNEL =3D 0, +=09MAUSB_ISOCH_CHANNEL =3D 1, +=09MAUSB_BULK_CHANNEL =3D 2, +=09MAUSB_INTR_CHANNEL =3D 3, +=09MAUSB_MGMT_CHANNEL =3D 4 +}; + +struct mausb_kvec_data_wrapper { +=09struct kvec *kvec; +=09u32 kvec_num; +=09u32 length; +}; + +struct mausb_ip_recv_ctx { +=09u16 left; +=09u16 received; +=09char *buffer; +=09char common_hdr[12] __aligned(4); +}; + +struct mausb_ip_ctx { +=09struct socket=09=09*client_socket; +=09union { +=09=09struct sockaddr_in sa_in; +#if IS_ENABLED(CONFIG_IPV6) +=09=09struct sockaddr_in6 sa_in6; +#endif +=09} dev_addr_in; +=09struct net=09=09*net_ns; +=09bool=09=09=09udp; + +=09/* Queues to schedule rx work */ +=09struct workqueue_struct=09*recv_workq; +=09struct workqueue_struct=09*connect_workq; +=09struct work_struct=09recv_work; +=09struct work_struct=09connect_work; + +=09struct mausb_ip_recv_ctx recv_ctx; /* recv buffer */ + +=09enum mausb_channel channel; +=09void *ctx; +=09/* callback should store task into hpal queue */ +=09void (*fn_callback)(void *ctx, enum mausb_channel channel, +=09=09=09 enum mausb_link_action act, int status, void *data); +}; + +int mausb_init_ip_ctx(struct mausb_ip_ctx **ip_ctx, +=09=09 struct net *net_ns, +=09=09 char ip_addr[INET6_ADDRSTRLEN], +=09=09 u16 port, +=09=09 void *ctx, +=09=09 void (*ctx_callback)(void *ctx, +=09=09=09=09=09 enum mausb_channel channel, +=09=09=09=09=09 enum mausb_link_action act, +=09=09=09=09=09 int status, void *data), +=09=09 enum mausb_channel channel); +int mausb_ip_disconnect(struct mausb_ip_ctx *ip_ctx); +int mausb_ip_send(struct mausb_ip_ctx *ip_ctx, +=09=09 struct mausb_kvec_data_wrapper *wrapper); + +void mausb_destroy_ip_ctx(struct mausb_ip_ctx *ip_ctx); +void mausb_ip_connect_async(struct mausb_ip_ctx *ip_ctx); + +#endif /* __MAUSB_IP_LINK_H__ */ --=20 2.17.1